summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README48
-rw-r--r--csim/load.c100
-rw-r--r--csim/sim.c162
-rw-r--r--csim/sim.h75
-rw-r--r--sched/netlist_dumb.ml193
-rw-r--r--tests/nadder.mj4
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)
+-------------------------------------------
+
+<var count>
+[for each variable]
+ <var size> <var name>
+<input list size> [for each input <input var id>]
+<out list size> [for each input <output var id>]
+<register list size>
+[for each register]
+ <register destination variable> <register source variable>
+<ram list size>
+[for each ram]
+ <destination variable> <addr size> <word size> <read addr var>
+ <write enable var> <write addr var> <data var>
+<equation list size>
+[for each equation]
+ <destination variable> <equation type> <args...>
+
+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 <stdio.h>
// 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<n>(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