diff options
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | README | 89 | ||||
-rw-r--r-- | cpu/Makefile | 2 | ||||
-rw-r--r-- | monitor/Makefile | 3 | ||||
-rw-r--r-- | monitor/disp.c | 35 | ||||
-rwxr-xr-x | monitor/mon | bin | 17656 -> 0 bytes | |||
-rw-r--r-- | monitor/mon.c | 51 | ||||
-rw-r--r-- | monitor/mon.h | 7 | ||||
-rw-r--r-- | sched/Makefile | 7 | ||||
-rw-r--r-- | sched/simplify.ml | 5 | ||||
-rw-r--r-- | tests/Makefile | 16 | ||||
-rw-r--r-- | tests/clock2.mj | 4 | ||||
-rw-r--r-- | tests/clockHMS.mj | 4 |
13 files changed, 186 insertions, 39 deletions
@@ -3,6 +3,8 @@ *.byte *.native csim/csim +sched/sched +monitor/mon *.o *.ps */*.net @@ -2,6 +2,8 @@ Système Digital 2013-2014 Cours J.Vuillemin, TD T.Bourke Alex AUVOLAT (Info 2013) +Émile ENGUEHARD (Info 2013) +Jonathan LAURENT (Info 2013) Introduction @@ -14,11 +16,11 @@ sched/ A scheduler for netlists. Input : a netlist. Output : a netlist with topologically sorted operators - plus a dumbed-down version for input to the C circuit simulator + plus a dumbed-down version for input to the C circuit simulator This program is also capable of a few optimisation (usually reduces netlist - size by 1/4 or 1/3). + size by 1/3 or better). $ cd sched/ - $ ocamlbuild main.byte + $ make csim/ A circuit simulator written in C. @@ -27,12 +29,36 @@ csim/ dumbed-down netlist, that is output by the scheduler. $ cd csim/ $ make + Command-line arguments are detailed if the simulator is run with no arguments. -minijazz/ - The MiniJazz compiler (given by the teachers). +cpu/ + A CPU circuit designed in `plan_micro.pdf`. + The netlist for the CPU is generated by Caml code (and not MiniJazz code), + therefore this directory also contains Caml files for generating netlists + with Caml code (see `netlist_gen.mli` and `example_cpu.ml` for usage example). + +monitor/ + A C program used to monitor the simulator. The monitor has many functionnalities : + - Shows input and output at every step on a nice screen + - Ticking (every second or at every step) + - Running the simulator manually, at fixed frequency, or at maximum speed + - Serial input/output with simulated CPU + - 7-bar digit display based on simulator output + $ cd monitor/ + $ make + Command-line arguments are in the format : + <simulator path> [<arguments for simulator> ...] tests/ - Various test files. + Various test circuits (written in MiniJazz). + For file a.mj, type : + $ make a.sim + to compile and run the simulator on that file, and type : + $ make a.mon + to compile and run it with the monitor (better !) + +minijazz/ + The MiniJazz compiler (given by the teachers). *.pdf Documentation about the project. @@ -47,12 +73,34 @@ REFERENCES Chapters 2 to 4 +HOW TO RUN THE CPU +================== -INTERNALS -========= +Compile the scheduler : -Convention for binary values ----------------------------- + $ cd sched/; make; cd .. + +Compile the monitor : + + $ cd monitor/; make; cd .. + +Run the CPU with the monitor : + + $ cd cpu/; make + +You are now in the main screen of the monitor. The following commands are usefull : + + (empty command) Execute one step of simulator + q Exit simulator + a Run simulator at max speed + f <freq> Run simulator at given frequency (in Hz) + t <input#> Send ticks every second on selected input + +Other commands are documented in `monitor/mon.c` + + +CONVENTION FOR BINARY VALUES +============================ /!\ This convention is contrary to the one used in the example file nadder.mj (Therefore I have modified that file...) @@ -77,6 +125,9 @@ The right shift is also inverted. - left shift logical -> rigth shift logical +SIMULATOR INTERNALS +=================== + The dumbed-down netlist format (OLD FORMAT) ------------------------------------------- @@ -204,6 +255,11 @@ the format : <variable name>\t<binary representation>\t<decimal representation> The output contains an empty line at the end of every cycle. +When the simulator is launched, it sends an output describing the I/O mechanism +of the simulated circuit : +<number of inputs> <number of outputs>\n +[for each input : <input size> <input name>\n] + How ROMs are handled -------------------- @@ -241,19 +297,12 @@ not defined in the ROM file) will be considered zeroes. -TODO ----- - -- More advanced commands for the simulator (cf Jonathan's simulator) - NEXT STEPS ---------- -- Define convention for processor input/output -- Code UI -- How can we generate netlists with ocaml code ? -- Code processor - +- Finish ALU +- Code assembler +- Code basic OS for the CPU diff --git a/cpu/Makefile b/cpu/Makefile index a39375b..898b007 100644 --- a/cpu/Makefile +++ b/cpu/Makefile @@ -3,7 +3,7 @@ GENERATOR=netlist_ast.ml netlist_gen.ml netlist_gen.mli AUXILLARY=alu.ml -SCHED=../sched/main.native +SCHED=../sched/sched SIM=../csim/csim MON=../monitor/mon diff --git a/monitor/Makefile b/monitor/Makefile index 15dadc4..92b7a60 100644 --- a/monitor/Makefile +++ b/monitor/Makefile @@ -3,3 +3,6 @@ HF=mon.h mon: $(CF) $(HF) gcc -o $@ $(CF) -lcurses -O2 + +clean: + rm mon diff --git a/monitor/disp.c b/monitor/disp.c index 7eaedc0..96d994d 100644 --- a/monitor/disp.c +++ b/monitor/disp.c @@ -74,9 +74,12 @@ void disp_display(t_mon *mon) { werase(wpstatus); - wprintw(wpstatus, "Step:\t\t%d\t%s\t%s\n", + wprintw(wpstatus, "Step:\t\t%d\t%s", mon->step, - (mon->status == MS_AUTO ? "A" : "M"), + (mon->status == MS_AUTO ? "A" : (mon->status == MS_RUN ? "M" : ""))); + if (mon->status == MS_FREQ) wprintw(wpstatus, "%dHz", mon->freq); + if (mon->status == MS_AUTO) wprintw(wpstatus, " %dHz", mon->max_freq); + wprintw(wpstatus, "\t%s\n", (mon->ticker_mode == TM_SECOND ? "TS" : (mon->ticker_mode == TM_FAST ? "TF" : "TZ"))); wprintw(wpstatus, "\nInputs:\n"); @@ -98,9 +101,30 @@ void disp_display(t_mon *mon) { } if (mon->n_outputs == 0) wprintw(wpstatus, "\t(none)\n"); - wprintw(wpstatus, "\nSerial buffer:\n%s\n", mon->ser_buf); + if (mon->ser_in_in != -1) { + wprintw(wpstatus, "\nSerial buffer:\n%s\n", mon->ser_buf); + } + + wprintw(wpstatus, "\n\n"); + for (i = 0; i < 8; i++) + wprintw(wpstatus, " %s ", (mon->d7[i] != -1 && mon->outputs[mon->d7[i]].v_bin[0] == '1' ? "---" : " ")); + wprintw(wpstatus, "\n"); + for (i = 0; i < 8; i++) + wprintw(wpstatus, " %c %c", + (mon->d7[i] != -1 && mon->outputs[mon->d7[i]].v_bin[1] == '1' ? '|' : ' '), + (mon->d7[i] != -1 && mon->outputs[mon->d7[i]].v_bin[2] == '1' ? '|' : ' ')); + wprintw(wpstatus, "\n"); + for (i = 0; i < 8; i++) + wprintw(wpstatus, " %s ", (mon->d7[i] != -1 && mon->outputs[mon->d7[i]].v_bin[3] == '1' ? "---" : " ")); + wprintw(wpstatus, "\n"); + for (i = 0; i < 8; i++) + wprintw(wpstatus, " %c %c", + (mon->d7[i] != -1 && mon->outputs[mon->d7[i]].v_bin[4] == '1' ? '|' : ' '), + (mon->d7[i] != -1 && mon->outputs[mon->d7[i]].v_bin[5] == '1' ? '|' : ' ')); + wprintw(wpstatus, "\n"); + for (i = 0; i < 8; i++) + wprintw(wpstatus, " %s ", (mon->d7[i] != -1 && mon->outputs[mon->d7[i]].v_bin[6] == '1' ? "---" : " ")); - wmove(wcmdline, 0, cmd_pos + 2); wrefresh(wpstatus); if (mon->ser_out_buf != 0) { @@ -108,6 +132,9 @@ void disp_display(t_mon *mon) { wrefresh(wpoutput); mon->ser_out_buf = 0; } + + wmove(wcmdline, 0, cmd_pos + 2); + wrefresh(wcmdline); } diff --git a/monitor/mon b/monitor/mon Binary files differdeleted file mode 100755 index 0c60bde..0000000 --- a/monitor/mon +++ /dev/null diff --git a/monitor/mon.c b/monitor/mon.c index 41182a8..4a51f6e 100644 --- a/monitor/mon.c +++ b/monitor/mon.c @@ -10,6 +10,7 @@ q Quit a Set automatic mode (send input all the time) m Set manual mode (send input when user sends empty command) + f <freq> Set frequency mode (every second, do 'freq' steps) i <id> <v> Set input #id to value v (v is a string, transmitted as-is to simulator) tf Tick fast (send 1 every cycle) ts Tick for every second @@ -22,6 +23,7 @@ i3 : output for serial output s Set no serial input :<text> Send text to serial + d7 x x ... Set outputs to be interpreted as 7-bar digit displayer (up to 8 outputs, use - for no output) */ int mon_read_prologue(t_mon *mon) { @@ -49,6 +51,8 @@ int mon_read_prologue(t_mon *mon) { } mon->step = 0; + mon->freq = 1; + mon->max_freq = 1000; mon->status = MS_RUN; mon->clk = time(NULL); @@ -61,15 +65,39 @@ int mon_read_prologue(t_mon *mon) { mon->ser_buf[0] = 0; mon->ser_out_buf = 0; + for (i = 0; i < 8; i++) mon->d7[i] = -1; + return 0; } void mon_loop(t_mon *mon) { disp_display(mon); + time_t prev_time = time(NULL); + int steps = 0; + while (mon->status != MS_FINISH) { handle_kbd(mon); if (mon->status == MS_AUTO) { mon_step(mon); + steps++; + if (time(NULL) != prev_time) { + mon->max_freq = steps; + steps = 0; + prev_time = time(NULL); + } + } else if (mon->status == MS_FREQ) { + if (steps < mon->freq) { + mon_step(mon); + steps++; + usleep(1000000 / mon->freq - 1000000 / mon->max_freq); + } else { + if (prev_time != time(NULL)) { + steps = 0; + prev_time = time(NULL); + } else { + usleep(10000); + } + } } else { usleep(10000); } @@ -85,6 +113,12 @@ void mon_handle_command(t_mon *mon, const char *c) { mon->status = MS_AUTO; } else if (!strcmp(c, "m")) { mon->status = MS_RUN; + } else if (c[0] == 'f') { + const char *p = c + 1; + mon->freq = 0; + while (isspace(*p)) p++; + while (isdigit(*p)) mon->freq = 10 * mon->freq + (*(p++) - '0'); + mon->status = MS_FREQ; } else if (c[0] == 'i') { const char *p = c + 1; int a = 0; @@ -132,9 +166,26 @@ void mon_handle_command(t_mon *mon, const char *c) { mon->ser_out = w; } } + } else if (c[0] == ':') { strcat(mon->ser_buf, c + 1); strcat(mon->ser_buf, "\n"); + } else if (c[0] == 'd' && c[1] == '7') { + const char *p = c + 2; + int i = 0; + for (i = 0; i < 8; i++) { + while (isspace(*p)) p++; + if (*p == 0) { + mon->d7[i] = -1; + } else if (*p == '-') { + mon->d7[i] = -1; + p++; + } else { + mon->d7[i] = 0; + while (isdigit(*p)) mon->d7[i] = 10 * mon->d7[i] + (*(p++) - '0'); + if (mon->d7[i] >= mon->n_outputs) mon->d7[i] = -1; + } + } } disp_display(mon); } diff --git a/monitor/mon.h b/monitor/mon.h index 39ac37e..7abcf8c 100644 --- a/monitor/mon.h +++ b/monitor/mon.h @@ -22,7 +22,8 @@ typedef struct { typedef enum { MS_FINISH, MS_RUN, - MS_AUTO + MS_AUTO, + MS_FREQ } t_status; typedef enum { @@ -39,6 +40,8 @@ typedef struct { t_output *outputs; int step; + int freq; + int max_freq; t_status status; @@ -49,6 +52,8 @@ typedef struct { int ser_in_in, ser_in_busy_out, ser_out; char ser_buf[256]; char ser_out_buf; + + int d7[8]; } t_mon; void disp_init(); diff --git a/sched/Makefile b/sched/Makefile index 460b639..4d36b96 100644 --- a/sched/Makefile +++ b/sched/Makefile @@ -1,10 +1,11 @@ IN=graph.ml main.ml netlist_ast.ml netlist_dumb.ml netlist_lexer.mll netlist.ml netlist_parser.mly netlist_printer.ml scheduler.ml simplify.ml -all: main.native +all: sched -main.native: $(IN) +sched: $(IN) ocamlbuild -libs unix main.native + mv main.native sched clean: + rm sched rm -rf _build - rm main.native diff --git a/sched/simplify.ml b/sched/simplify.ml index 86c4790..ef2f0dc 100644 --- a/sched/simplify.ml +++ b/sched/simplify.ml @@ -328,9 +328,8 @@ let topo_sort p = let rec simplify_with steps p = let pp, use = List.fold_left (fun (x, u) (f, n) -> - print_string n; let xx, uu = f x in - print_string (if uu then " *\n" else "\n"); + print_endline (if uu then n ^ " *" else n); (xx, u || uu)) (p, false) steps in if use then simplify_with steps pp else pp @@ -338,6 +337,8 @@ let rec simplify_with steps p = let simplify p = let p = simplify_with [ topo_sort, "topo_sort"; + ] p in + let p = simplify_with [ cascade_slices, "cascade_slices"; pass_concat, "pass_concat"; select_to_id, "select_to_id"; diff --git a/tests/Makefile b/tests/Makefile index cf2f62f..02f1c9b 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,17 +1,25 @@ .SECONDARY: MINIJAZZ=../minijazz/mjc.byte -SCHED=../sched/main.native +SCHED=../sched/sched SIM=../csim/csim +MON=../monitor/mon -%.sim: %.dumb +%.mon: _build/%.dumb + $(MON) $(SIM) -rom decode7 decode7.rom $< + +%.sim: _build/%.dumb $(SIM) -n 12 $< -%.dumb %.snet %_opt.dumb %_opt.snet: %.net +_build/%.dumb _build/%.snet _build/%_opt.dumb _build/%_opt.snet: _build/%.net $(SCHED) $< -%.net: %.mj +_build/%.net: %.mj _build $(MINIJAZZ) $< + mv `basename -s .mj $<`.net _build + +_build: + mkdir _build clean: rm *.net diff --git a/tests/clock2.mj b/tests/clock2.mj index 6f28603..73b5e6a 100644 --- a/tests/clock2.mj +++ b/tests/clock2.mj @@ -69,11 +69,11 @@ dec7(i:[4]) = (o:[7]) where o = decode7 end where -main() = (sec_u:[4],d7_sec_u:[7],sec_d:[4],d7_sec_d:[7], +main(tick) = (sec_u:[4],d7_sec_u:[7],sec_d:[4],d7_sec_d:[7], min_u:[4],d7_min_u:[7],min_d:[4],d7_min_d:[7], hour_u:[4],d7_hour_u:[7],hour_d:[4],d7_hour_d:[7], next_day) where - (count_seca, aug_seca) = count_mod_keep<2,2>(1); + (count_seca, aug_seca) = count_mod_keep<2,2>(tick); (count_secb, aug_secb) = count_mod_keep<3,5>(aug_seca); (count_secc, aug_min) = count_mod_keep<3,6>(aug_secb); sec_u = count_seca[0] . count_secb; diff --git a/tests/clockHMS.mj b/tests/clockHMS.mj index 4575c58..ea10d4f 100644 --- a/tests/clockHMS.mj +++ b/tests/clockHMS.mj @@ -62,8 +62,8 @@ count_mod<n, m>(in:[n], op) = (out:[n], reset) where out = and_each<n>(neq, incr); end where -main() = (count_sec:[6],count_min:[6],count_hour:[5],next_day) where - (count_sec, aug_min) = count_mod<6, 60>(save_sec, 1); +main(tick) = (count_sec:[6],count_min:[6],count_hour:[5],next_day) where + (count_sec, aug_min) = count_mod<6, 60>(save_sec, tick); save_sec = reg_n<6>(count_sec); (count_min, aug_hour) = count_mod<6, 60>(save_min, aug_min); |