summaryrefslogtreecommitdiff
path: root/csim
diff options
context:
space:
mode:
Diffstat (limited to 'csim')
-rw-r--r--csim/load.c100
-rw-r--r--csim/sim.c162
-rw-r--r--csim/sim.h75
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;
}
}
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);