From 05749abf8efdcaae6afd9f3dd087df475e5e93ad Mon Sep 17 00:00:00 2001 From: Alex AUVOLAT Date: Fri, 8 Nov 2013 15:51:54 +0100 Subject: [WIP] Change dumb netlist format in scheduler and simulator. --- README | 48 ++++++++++++- csim/load.c | 100 +++++++++++--------------- csim/sim.c | 162 ++++++++++++++++++++++++------------------ csim/sim.h | 75 +++++++++----------- sched/netlist_dumb.ml | 193 ++++++++++++++++++++++++++++++++++++++++++++++---- tests/nadder.mj | 4 +- 6 files changed, 398 insertions(+), 184 deletions(-) diff --git a/README b/README index 9235b1a..81eadea 100644 --- a/README +++ b/README @@ -82,8 +82,8 @@ The right shift is also inverted. - left shift logical -> rigth shift logical -The dumbed-down netlist format ------------------------------- +The dumbed-down netlist format (OLD FORMAT) +------------------------------------------- The C simulator does NOT read a properly formatted netlist, but only a file representing it written in a simple format, that can be parsed with only calls @@ -142,6 +142,48 @@ be assigned to a constant-type variable that can be counted among the inputs (or whatever - anyway, no need to recalculate them at every iteration). +The dumbed-down netlist format (NEW FORMAT) +------------------------------------------- + + +[for each variable] + + [for each input ] + [for each input ] + +[for each register] + + +[for each ram] + + + +[for each equation] + + +Equation types : +ID DESCR ARGS +-- ----- ---- +0 Copy var_id +1 Not var_id +2 Binop op_id var_a_id var_b_id +3 Mux var_a_id var_b_id +4 ROM addr_size word_size write_addr_var_id +5 Concat var_a var_b +6 Slice begin end var_id +7 Select number var_id + +Operators : +0 OR +1 XOR +2 AND +3 NAND + +Constant variables are standardized so that their name (eg. $00101) +gives the value of the constant, therefore there is no need to write a constant +list in the program file. + + The Input/Output format ----------------------- @@ -173,7 +215,7 @@ the name of the variable that is read from the ROM. For example, if we have : which is a possible output for the MiniJazz compiler, and if the simulator is provided with the command-line argument : -rom decode7 path/to/decode7.rom -then the compiler will detect the prefix `decode7` in the variable name +then the simulator will detect the prefix `decode7` in the variable name decode7_128, and use the ROM from the file specified on the command line. Suggested format for the ROM files : diff --git a/csim/load.c b/csim/load.c index 7971a71..f652d78 100644 --- a/csim/load.c +++ b/csim/load.c @@ -11,36 +11,6 @@ #include "sim.h" -t_value read_bool(FILE *stream, t_value *mask) { - t_value r = 0; - t_value pow = 1; - - char c; - if (mask != NULL) *mask = 0; - - for(;;) { - fscanf(stream, "%c", &c); - if (c == '1') { - r |= pow; - } else if (c != '0') { - break; - } - if (mask != NULL) (*mask) |= pow; - - pow *= 2; - } - - return r; -} - -void read_arg(FILE *stream, t_arg *dest) { - dest->mask = 0; - if (fscanf(stream, "$%d ", &(dest->SrcVar))) { - // ok, value is read - } else { - dest->Val = read_bool(stream, &dest->mask); - } -} t_program *load_dumb_netlist (FILE *stream) { int i, j; @@ -79,6 +49,24 @@ t_program *load_dumb_netlist (FILE *stream) { fscanf(stream, "%d ", &(p->outputs[i])); } + // read register list + fscanf(stream, "%d", &(p->n_regs)); + p->regs = malloc(p->n_regs * sizeof(t_reg)); + for (i = 0; i < p->n_regs; i++) { + fscanf(stream, "%d %d\n", &(p->regs[i].dest), &(p->regs[i].source)); + } + // read RAM list + fscanf(stream, "%d", &(p->n_rams)); + p->rams = malloc(p->n_rams * sizeof(t_ram)); + for (i = 0; i < p->n_rams; i++) { + fscanf(stream, "%d %d %d %d %d %d %d\n", + &(p->rams[i].dest), + &(p->rams[i].addr_size), + &(p->rams[i].word_size), + &(p->rams[i].read_addr), &(p->rams[i].write_enable), + &(p->rams[i].write_addr), &(p->rams[i].data)); + } + // read equation list fscanf(stream, "%d ", &(p->n_eqs)); p->eqs = malloc(p->n_eqs * sizeof(t_equation)); @@ -86,47 +74,45 @@ t_program *load_dumb_netlist (FILE *stream) { fscanf(stream, "%d ", &(p->eqs[i].dest_var)); fscanf(stream, "%d ", &(p->eqs[i].type)); switch (p->eqs[i].type) { - case C_ARG: - read_arg(stream, &(p->eqs[i].Arg.a)); - break; - case C_REG: - fscanf(stream, "%d ", &(p->eqs[i].Reg.var)); + case C_COPY: + fscanf(stream, "%d ", &(p->eqs[i].Copy.a)); break; case C_NOT: - read_arg(stream, &(p->eqs[i].Not.a)); + fscanf(stream, "%d ", &(p->eqs[i].Not.a)); break; case C_BINOP: - fscanf(stream, "%d ", &(p->eqs[i].Binop.op)); - read_arg(stream, &(p->eqs[i].Binop.a)); - read_arg(stream, &(p->eqs[i].Binop.b)); + fscanf(stream, "%d %d %d ", + &(p->eqs[i].Binop.op), + &(p->eqs[i].Binop.a), + &(p->eqs[i].Binop.b)); break; case C_MUX: - read_arg(stream, &(p->eqs[i].Mux.a)); - read_arg(stream, &(p->eqs[i].Mux.b)); - read_arg(stream, &(p->eqs[i].Mux.c)); + fscanf(stream, "%d %d %d ", + &(p->eqs[i].Mux.a), + &(p->eqs[i].Mux.b), + &(p->eqs[i].Mux.c)); break; case C_ROM: - fscanf(stream, "%d %d ", &(p->eqs[i].Rom.addr_size), &(p->eqs[i].Rom.word_size)); - read_arg(stream, &(p->eqs[i].Rom.read_addr)); - break; - case C_RAM: - fscanf(stream, "%d %d ", &(p->eqs[i].Ram.addr_size), &(p->eqs[i].Ram.word_size)); - read_arg(stream, &(p->eqs[i].Ram.read_addr)); - read_arg(stream, &(p->eqs[i].Ram.write_enable)); - read_arg(stream, &(p->eqs[i].Ram.write_addr)); - read_arg(stream, &(p->eqs[i].Ram.data)); + fscanf(stream, "%d %d %d ", + &(p->eqs[i].Rom.addr_size), + &(p->eqs[i].Rom.word_size), + &(p->eqs[i].Rom.read_addr)); break; case C_CONCAT: - read_arg(stream, &(p->eqs[i].Mux.a)); - read_arg(stream, &(p->eqs[i].Mux.b)); + fscanf(stream, "%d %d ", + &(p->eqs[i].Concat.a), + &(p->eqs[i].Concat.b)); + p->eqs[i].Concat.shift = p->vars[p->eqs[i].Concat.a].size; break; case C_SLICE: - fscanf(stream, "%d %d ", &(p->eqs[i].Slice.begin), &(p->eqs[i].Slice.end)); - read_arg(stream, &(p->eqs[i].Slice.source)); + fscanf(stream, "%d %d %d ", + &(p->eqs[i].Slice.begin), + &(p->eqs[i].Slice.end), + &(p->eqs[i].Slice.source)); break; case C_SELECT: - fscanf(stream, "%d ", &(p->eqs[i].Select.i)); - read_arg(stream, &(p->eqs[i].Select.source)); + fscanf(stream, "%d %d ", &(p->eqs[i].Select.i), + &(p->eqs[i].Select.source)); break; } } diff --git a/csim/sim.c b/csim/sim.c index db3b711..94bf70e 100644 --- a/csim/sim.c +++ b/csim/sim.c @@ -11,7 +11,7 @@ #include "sim.h" -#define DEBUG 0 +#define DEBUG 1 // Util @@ -30,28 +30,59 @@ t_machine *init_machine (t_program *p) { t_machine *m = malloc(sizeof(t_machine)); m->prog = p; + // Allocate variables m->var_values = malloc(p->n_vars * sizeof(t_value)); for (i = 0; i < p->n_vars; i++) { m->var_values[i] = 0; + if (p->vars[i].name[0] == '$') { + // setup constant value + t_value a = 1; + char *o = p->vars[i].name + 1; + while (*o) { + m->var_values[i] |= a; + a >>= 1; + o++; + } + } } - m->mem_data = malloc(p->n_eqs * sizeof(t_value)); - for (i =0; i < p->n_eqs; i++) { - if (p->eqs[i].type == C_REG) { - m->mem_data[i].RegVal = 0; - } else if (p->eqs[i].type == C_RAM) { - m->mem_data[i].RamData = malloc(pow2(p->eqs[i].Ram.addr_size) * sizeof(t_value)); - for (j = 0; j < pow2(p->eqs[i].Ram.addr_size); j++) { - m->mem_data[i].RamData[j] = 0; - } - } else { - // Leave uninitialized. Not as if anybody cares. + // Allocate space for registers and rams + m->reg_data = malloc(p->n_regs * sizeof(t_value)); + for (i = 0; i < p->n_regs; i++) { + m->reg_data[i] = 0; + } + m->ram_data = malloc(p->n_rams * sizeof(t_value*)); + for (i = 0; i < p->n_rams; i++) { + m->ram_data[i] = malloc(pow2(p->rams[i].addr_size) * sizeof(t_value)); + for (j = 0; j < pow2(p->rams[i].addr_size); j++) { + m->ram_data[i][j] = 0; } } - + return m; } +t_value read_bool(FILE *stream, t_value *mask) { + t_value r = 0; + t_value pow = 1; + + char c; + if (mask != NULL) *mask = 0; + + for(;;) { + fscanf(stream, "%c", &c); + if (c == '1') { + r |= pow; + } else if (c != '0') { + break; + } + if (mask != NULL) (*mask) |= pow; + + pow *= 2; + } + + return r; +} void read_inputs(t_machine *m, FILE *stream) { /* FORMAT : For each input in the list, *in the order specified*, @@ -77,59 +108,52 @@ void read_inputs(t_machine *m, FILE *stream) { } -t_value get_var(t_machine *m, t_arg a) { - if (a.mask == 0) return m->var_values[a.SrcVar]; - return a.Val; -} - -t_value get_mask(t_machine *m, t_arg a) { - if (a.mask == 0) return m->prog->vars[a.SrcVar].mask; - return a.mask; -} - void machine_step(t_machine *m) { int i, j; t_value a, b, c, d, e, ma, mb, v; t_program *p = m->prog; // READ REGISTERS && MEMORY - for (i = 0; i < p->n_eqs; i++) { - if (p->eqs[i].type == C_REG) { - m->var_values[p->eqs[i].dest_var] = m->mem_data[i].RegVal; - } else if (p->eqs[i].type == C_RAM) { - e = get_var(m, p->eqs[i].Ram.write_enable); - if (e == 0) { - a = get_var(m, p->eqs[i].Ram.read_addr); - m->var_values[p->eqs[i].dest_var] = m->mem_data[i].RamData[a]; - if (DEBUG) fprintf(stderr, "Read ram %lx = %lx\n", a, m->mem_data[i].RamData[a]); - } + for (i = 0; i < p->n_regs; i++) { + m->var_values[p->regs[i].dest] = m->reg_data[i]; + if (DEBUG) fprintf(stderr, "%s <- reg %s : %lx\n", + p->vars[p->regs[i].dest].name, + p->vars[p->regs[i].dest].name, + m->reg_data[i]); + } + for (i = 0; i < p->n_rams; i++) { + e = m->var_values[p->rams[i].write_enable]; + if (e == 0) { + a = m->var_values[p->rams[i].read_addr]; + b = m->ram_data[i][a]; + m->var_values[p->rams[i].dest] = b; + if (DEBUG) fprintf(stderr, "Read ram %lx = %lx\n", a, b); } } // DO THE LOGIC for (i = 0; i < p->n_eqs; i++) { - if (p->eqs[i].type == C_REG || p->eqs[i].type == C_RAM) continue; v = 0; switch (p->eqs[i].type) { - case C_ARG: - v = get_var(m, p->eqs[i].Arg.a); + case C_COPY: + v = m->var_values[p->eqs[i].Copy.a]; break; case C_NOT: - v = ~get_var(m, p->eqs[i].Not.a); + v = ~m->var_values[p->eqs[i].Not.a]; break; case C_BINOP: - a = get_var(m, p->eqs[i].Binop.a); - b = get_var(m, p->eqs[i].Binop.b); + a = m->var_values[p->eqs[i].Binop.a]; + b = m->var_values[p->eqs[i].Binop.b]; if (p->eqs[i].Binop.op == OP_OR) v = a | b; if (p->eqs[i].Binop.op == OP_AND) v = a & b; if (p->eqs[i].Binop.op == OP_XOR) v = a ^ b; if (p->eqs[i].Binop.op == OP_NAND) v = ~(a & b); break; case C_MUX: - a = get_var(m, p->eqs[i].Mux.a); - b = get_var(m, p->eqs[i].Mux.b); - c = get_var(m, p->eqs[i].Mux.c); - ma = get_mask(m, p->eqs[i].Mux.a); + a = m->var_values[p->eqs[i].Mux.a]; + b = m->var_values[p->eqs[i].Mux.b]; + c = m->var_values[p->eqs[i].Mux.c]; + ma = m->prog->vars[p->eqs[i].Mux.a].mask; if (ma == 1) { v = (a ? c : b); } else { @@ -140,19 +164,17 @@ void machine_step(t_machine *m) { // TODO break; case C_CONCAT: - a = get_var(m, p->eqs[i].Concat.a); - b = get_var(m, p->eqs[i].Concat.b); - ma = get_mask(m, p->eqs[i].Concat.a); - mb = get_mask(m, p->eqs[i].Concat.b); - while (ma & mb) { - mb <<= 1; - b <<= 1; - } - v = (a & ma) | (b & mb); - if (DEBUG) fprintf (stderr, "concat %lx (%lx), %lx (%lx) = %lx .. ", a, ma, b, mb, v); + a = m->var_values[p->eqs[i].Concat.a]; + b = m->var_values[p->eqs[i].Concat.b]; + ma = p->vars[p->eqs[i].Concat.a].mask; + mb = p->vars[p->eqs[i].Concat.b].mask; + b <<= p->eqs[i].Concat.shift; + v = a | b; + if (DEBUG) fprintf (stderr, "concat %lx (&%lx) %lx (&%lx) <%d = %lx .. ", + a, ma, b, mb, p->eqs[i].Concat.shift, v); break; case C_SLICE: - a = get_var(m, p->eqs[i].Slice.source); + a = m->var_values[p->eqs[i].Slice.source]; ma = 1; mb = 0; for (j = 0; j <= p->eqs[i].Slice.end; j++) { @@ -166,28 +188,34 @@ void machine_step(t_machine *m) { mb, a, v); break; case C_SELECT: - a = get_var(m, p->eqs[i].Select.source); + a = m->var_values[p->eqs[i].Select.source]; v = (a >> p->eqs[i].Select.i) & 1; if (DEBUG) fprintf(stderr, "select %d %lx->%lx .. ", p->eqs[i].Select.i, a, v); break; } m->var_values[p->eqs[i].dest_var] = v & (p->vars[p->eqs[i].dest_var].mask); - if (DEBUG) fprintf(stderr, "%s &%lx : %lx\n", p->vars[p->eqs[i].dest_var].name, p->vars[p->eqs[i].dest_var].mask, m->var_values[p->eqs[i].dest_var]); + if (DEBUG) fprintf(stderr, "%s &%lx : %lx\n", + p->vars[p->eqs[i].dest_var].name, + p->vars[p->eqs[i].dest_var].mask, + m->var_values[p->eqs[i].dest_var]); } // SAVE REGISTERS && MEMORY - for (i = 0; i < p->n_eqs; i++) { - if (p->eqs[i].type == C_REG) { - m->mem_data[i].RegVal = m->var_values[p->eqs[i].Reg.var]; - } else if (p->eqs[i].type == C_RAM) { - e = get_var(m, p->eqs[i].Ram.write_enable); - if (e != 0) { - a = get_var(m, p->eqs[i].Ram.write_addr); - d = get_var(m, p->eqs[i].Ram.data); - if (DEBUG) fprintf(stderr, "Write ram %lx = %lx\n", a, d); - m->mem_data[i].RamData[a] = d; - } + for (i = 0; i < p->n_regs; i++) { + m->reg_data[i] = m->var_values[p->regs[i].source]; + if (DEBUG) printf("reg %s <- %s : %lx\n", + p->vars[p->regs[i].dest].name, + p->vars[p->regs[i].source].name, + m->reg_data[i]); + } + for (i = 0; i < p->n_rams; i++) { + e = m->var_values[p->rams[i].write_enable]; + if (e != 0) { + a = m->var_values[p->rams[i].write_addr]; + d = m->var_values[p->rams[i].data]; + m->ram_data[i][a] = d; + if (DEBUG) fprintf(stderr, "Write ram %lx = %lx\n", a, d); } } } diff --git a/csim/sim.h b/csim/sim.h index 8e35c45..8b4a726 100644 --- a/csim/sim.h +++ b/csim/sim.h @@ -6,16 +6,14 @@ #include // Gate types -#define C_ARG 0 -#define C_REG 1 -#define C_NOT 2 -#define C_BINOP 3 -#define C_MUX 4 -#define C_ROM 5 -#define C_RAM 6 -#define C_CONCAT 7 -#define C_SLICE 8 -#define C_SELECT 9 +#define C_COPY 0 +#define C_NOT 1 +#define C_BINOP 2 +#define C_MUX 3 +#define C_ROM 4 +#define C_CONCAT 5 +#define C_SLICE 6 +#define C_SELECT 7 // Binary operators #define OP_OR 0 @@ -25,7 +23,6 @@ // Data structures - // Use 64-bit ints as bit arrays. Bit index 0 is bitmask 1, bit index 1 is bitmask 2, etc. typedef unsigned long long int t_value; // Identifier for the variables of the circuit. @@ -38,51 +35,47 @@ typedef struct { // a variable in the simulator } t_variable; typedef struct { - t_value mask; // if direct value, mask = all possible bits. Else mask = 0 - union { - t_value Val; - t_id SrcVar; // if source_var == -1 then it's a direct value, else it's that variable - }; -} t_arg; + t_id dest, source; +} t_reg; + +typedef struct { + t_id dest; + int addr_size, word_size; + t_id read_addr, write_enable, write_addr, data; +} t_ram; typedef struct { int type; t_id dest_var; union { struct { - t_arg a; - } Arg; - struct { - t_id var; - } Reg; + t_id a; + } Copy; struct { - t_arg a; + t_id a; } Not; struct { int op; - t_arg a, b; + t_id a, b; } Binop; struct { - t_arg a, b, c; + t_id a, b, c; } Mux; struct { int addr_size, word_size; - t_arg read_addr; + t_id read_addr; } Rom; struct { - int addr_size, word_size; - t_arg read_addr, write_enable, write_addr, data; - } Ram; - struct { - t_arg a, b; + t_id a, b; + int shift; } Concat; struct { int begin, end; - t_arg source; + t_id source; } Slice; struct { int i; - t_arg source; + t_id source; } Select; }; } t_equation; @@ -90,31 +83,31 @@ typedef struct { typedef struct { int n_vars, n_inputs, n_outputs; + t_variable *vars; t_id *inputs, *outputs; + int n_regs, n_rams; + t_reg *regs; + t_ram *rams; + int n_eqs; t_equation *eqs; } t_program; // machine = execution instance -typedef union { - t_value RegVal; - t_value *RamData; -} t_mem_reg_data; - typedef struct { t_program *prog; t_value *var_values; // indexed by variable ID - t_mem_reg_data *mem_data; // indexed by equation number + + t_value *reg_data; // indexed by number in register list + t_value **ram_data; // indexed by number in ram list } t_machine; // The functions for doing stuff with these data structures -t_value read_bool(FILE *stream, t_value* mask); - t_program *load_dumb_netlist(FILE *stream); t_machine *init_machine(t_program *p); diff --git a/sched/netlist_dumb.ml b/sched/netlist_dumb.ml index 7736d94..1e2a57f 100644 --- a/sched/netlist_dumb.ml +++ b/sched/netlist_dumb.ml @@ -14,7 +14,6 @@ type var_id = int type const_val = bool array (* keep type binop from netlist_ast *) -type const_var = { dest : var_id; value : const_val } type reg_var = { dest : var_id; source : var_id } type ram_var = { dest : var_id; addr_size : int; word_size : int; @@ -50,19 +49,191 @@ let mkbinstr a = done; r +let const_info = function + | VBit(a) -> "$" ^ (mkbinstr [|a|]), 1, [|a|] + | VBitArray(a) -> "$" ^ (mkbinstr a), Array.length a, a + let make_program_dumb p = - let vars = ref [] in - let var_map = Hashtbl.create (Env.cardinal p.p_vars) in - () (* TODO *) (* - 1. Identify constants and create new variables for them, put them on the variable list - 2. Create map from variable identifier to variable ID, add them to variable list + 1. Identify constants and create new variables for them, + put them on the variable list + 2. Create map from variable identifier to variable ID, + add them to variable list 3. Extract regs and rams into separate list - 4. Reformat equation list (replace constants by the coresponding constant variables) + 4. Reformat equation list (replace constants by the + coresponding constant variables) 5. Done. *) + let next_id = ref 0 in + let vars = ref [] in + let var_map = Hashtbl.create (Env.cardinal p.p_vars) in + + (* Extract constants *) + List.iter + (fun (_, eq) -> + let add = function + | Aconst(k) -> + let id, sz, v = const_info k in + if not (Hashtbl.mem var_map id) then begin + vars := { name= id; size= sz }::(!vars); + Hashtbl.add var_map id (!next_id); + next_id := !next_id + 1 + end + | _ -> () + in match eq with + | Earg(a) -> add a + | Enot(a) -> add a + | Ebinop(_, a, b) -> add a; add b + | Emux(a, b, c) -> add a; add b; add c + | Erom(_, _, a) -> add a + | Eram(_, _, a, b, c, d) -> add a; add b; add c; add d + | Econcat(a, b) -> add a; add b + | Eslice(_, _, a) -> add a + | Eselect(_, a) ->add a + | _ -> ()) + p.p_eqs; + + (* Make ids for variables *) + Env.iter + (fun k v -> + let sz = match v with + | TBit -> 1 + | TBitArray(n) -> n + in + vars := { name = k; size = sz }::(!vars); + Hashtbl.add var_map k (!next_id); + next_id := !next_id + 1) + p.p_vars; + + let var_id = Hashtbl.find var_map in + let arg_id = function + | Avar(x) -> var_id x + | Aconst(x) -> + let n, _, _ = const_info x in var_id n + in + + (* Extract registers *) + let regs, eq2 = List.fold_left + (fun (regs, eqs) (n, eq) -> + match eq with + | Ereg(x) -> + { + dest = var_id n; + source = var_id x; + }::regs, eqs + | _ -> regs, (n, eq)::eqs) + ([],[]) + p.p_eqs in + (* Extract rams *) + let rams, eq3 = List.fold_left + (fun (rams, eqs) (n, eq) -> + match eq with + | Eram(asz, wsz, ra, we, wa, d) -> + { + dest = var_id n; + addr_size = asz; + word_size = wsz; + read_addr = arg_id ra; + write_enable = arg_id we; + write_addr = arg_id wa; + data = arg_id d; + }::rams, eqs + | _ -> rams, (n, eq)::eqs) + ([],[]) + eq2 in + + (* Replace arguments by variable id's *) + let eqs = List.map + (fun (n, eq) -> + (var_id n, match eq with + | Earg(a) -> Dcopy(arg_id a) + | Enot(a) -> Dnot(arg_id a) + | Ebinop(o, a, b) -> Dbinop(o, arg_id a, arg_id b) + | Emux(a, b, c) -> Dmux(arg_id a, arg_id b, arg_id c) + | Erom(u, v, a) -> Drom(u, v, arg_id a) + | Econcat(a, b) -> Dconcat(arg_id a, arg_id b) + | Eslice(u, v, a) -> Dslice(u, v, arg_id a) + | Eselect(i, a) -> Dselect(i, arg_id a) + | _ -> failwith "This should not happen.")) + eq3 in + + { + d_vars = List.rev (!vars); + d_inputs = List.map var_id p.p_inputs; + d_outputs = List.map var_id p.p_outputs; + d_regs = regs; + d_rams = rams; + d_eqs = eqs; + } +(* Printer code *) + +(* Identifiers *) +let c_copy = 0 +let c_not = 1 +let c_binop = 2 +let c_mux = 3 +let c_rom = 4 +let c_concat = 5 +let c_slice = 6 +let c_select = 7 + +let binop_id = function + | Or -> 0 + | Xor -> 1 + | And -> 2 + | Nand -> 3 + +let print_dumb_program oc p = + let ff = formatter_of_out_channel oc in + (* print variable list *) + fprintf ff "%d\n" (List.length p.d_vars); + List.iter + (fun v -> + fprintf ff "%d %s\n" v.size v.name) + p.d_vars; + (* print input list *) + fprintf ff "%d" (List.length p.d_inputs); + List.iter (fun k -> fprintf ff " %d" k) p.d_inputs; + fprintf ff "\n"; + (* print output list *) + fprintf ff "%d" (List.length p.d_outputs); + List.iter (fun k -> fprintf ff " %d" k) p.d_outputs; + fprintf ff "\n"; + (* print register list *) + fprintf ff "%d\n" (List.length p.d_regs); + List.iter (fun (r: reg_var) -> + fprintf ff "%d %d\n" r.dest r.source) p.d_regs; + (* print ram list *) + fprintf ff "%d\n" (List.length p.d_rams); + List.iter (fun r -> fprintf ff "%d %d %d %d %d %d %d\n" + r.dest r.addr_size r.word_size r.read_addr r.write_enable + r.write_addr r.data) p.d_rams; + (* print equation list *) + fprintf ff "%d\n" (List.length p.d_eqs); + List.iter (fun (n, e) -> + fprintf ff "%d " n; match e with + | Dcopy(x) -> fprintf ff "%d %d\n" c_copy x + | Dnot(x) -> fprintf ff "%d %d\n" c_not x + | Dbinop(o, a, b) -> fprintf ff "%d %d %d %d\n" c_binop (binop_id o) a b + | Dmux(a, b, c) -> fprintf ff "%d %d %d %d\n" c_mux a b c + | Drom(u, v, a) -> fprintf ff "%d %d %d %d\n" c_rom u v a + | Dconcat(a, b) -> fprintf ff "%d %d %d\n" c_concat a b + | Dslice(u, v, a) -> fprintf ff "%d %d %d %d\n" c_slice u v a + | Dselect(i, a) -> fprintf ff "%d %d %d\n" c_select i a) + p.d_eqs; + (*flush*) + fprintf ff "@." + +let print_program oc p = + print_dumb_program oc (make_program_dumb p) + + +(* OLD PRINTER CODE *) + + +(* (* constants *) let c_arg = 0 @@ -76,12 +247,6 @@ let c_concat = 7 let c_slice = 8 let c_select = 9 -let binop_i = function - | Or -> 0 - | Xor -> 1 - | And -> 2 - | Nand -> 3 - let print_program oc p = let ff = formatter_of_out_channel oc in (* associate numbers to variables *) @@ -151,6 +316,6 @@ let print_program oc p = (* flush *) fprintf ff "@." - +*) diff --git a/tests/nadder.mj b/tests/nadder.mj index b75a83c..0e24ca4 100644 --- a/tests/nadder.mj +++ b/tests/nadder.mj @@ -14,6 +14,6 @@ adder(a:[n], b:[n], c_in) = (o:[n], c_out) where end if end where -main(a:[4], b:[4]) = (o:[4], c) where - (o, c) = adder<4>(a,b,0) +main(a:[2], b:[2]) = (o:[2], c) where + (o, c) = adder<2>(a,b,0) end where -- cgit v1.2.3