diff options
Diffstat (limited to 'csim')
-rw-r--r-- | csim/load.c | 100 | ||||
-rw-r--r-- | csim/sim.c | 162 | ||||
-rw-r--r-- | csim/sim.h | 75 |
3 files changed, 172 insertions, 165 deletions
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; } } @@ -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); } } } @@ -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); |