From cc78e19aa9e6b7c8ec0e1e5ac26685e57406c69d Mon Sep 17 00:00:00 2001 From: Alex AUVOLAT Date: Mon, 11 Nov 2013 17:30:46 +0100 Subject: Added ROM support, coded a 24/60/60 watch with output for 7-bit LCD display --- csim/Makefile | 2 +- csim/load.c | 47 +++++++++++++++++++++++-- csim/main.c | 14 ++++++-- csim/sim.c | 38 ++++---------------- csim/sim.h | 17 +++++++-- csim/util.c | 48 +++++++++++++++++++++++++ tests/clock2.mj | 103 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ tests/decode7.rom | 17 +++++++++ tests/romtest.mj | 9 +++++ 9 files changed, 253 insertions(+), 42 deletions(-) create mode 100644 csim/util.c create mode 100644 tests/clock2.mj create mode 100644 tests/decode7.rom create mode 100644 tests/romtest.mj diff --git a/csim/Makefile b/csim/Makefile index cc88ac3..6827579 100644 --- a/csim/Makefile +++ b/csim/Makefile @@ -1,4 +1,4 @@ -csim: main.o load.o sim.o +csim: main.o load.o sim.o util.o gcc -o csim $^ %.o: %.c diff --git a/csim/load.c b/csim/load.c index eb441cc..e6fcf29 100644 --- a/csim/load.c +++ b/csim/load.c @@ -11,9 +11,34 @@ #include "sim.h" +t_rom *roms = NULL; + +void add_rom(const char *prefix, FILE *file) { + int i; + + t_rom *rom = malloc(sizeof(t_rom)); + rom->prefix = prefix; + + // Load ROM file + fscanf(file, "%d %d\n", &(rom->addr_size), &(rom->word_size)); + rom->data = malloc(pow2(rom->addr_size) * sizeof(t_value)); + + for (i = 0; i < pow2(rom->addr_size); i++) { + fscanf(file, " "); + if (fscanf(file, "/%lu", &(rom->data[i]))) { + // ok, value is read + } else { + rom->data[i] = read_bool(file, NULL); + } + } + + rom->next = roms; + roms = rom; +} t_program *load_dumb_netlist (FILE *stream) { - int i, j; + int i, j, as, ws; + t_rom *r; // let us suppose that the input to be read is well-formed. t_program *p = malloc(sizeof(t_program)); @@ -94,9 +119,25 @@ t_program *load_dumb_netlist (FILE *stream) { break; case C_ROM: fscanf(stream, "%d %d %d ", - &(p->eqs[i].Rom.addr_size), - &(p->eqs[i].Rom.word_size), + &as, &ws, &(p->eqs[i].Rom.read_addr)); + p->eqs[i].Rom.rom = NULL; + // find corresponding ROM + for (r = roms; r != NULL; r = r->next) { + if (is_prefix(r->prefix, p->vars[p->eqs[i].dest_var].name)) { + if (r->addr_size == as && r->word_size == ws) { + p->eqs[i].Rom.rom = r; + break; + } else { + fprintf(stderr, + "Error: ROM prefixed by '%s' does not have size corresponding to variable that uses it.\n", + r->prefix); + } + } + } + if (p->eqs[i].Rom.rom == NULL) + fprintf(stderr, "Warning: ROM variable '%s' has no ROM data.\n", + p->vars[p->eqs[i].dest_var].name); break; case C_CONCAT: fscanf(stream, "%d %d ", diff --git a/csim/main.c b/csim/main.c index a43d7c9..6e5bc29 100644 --- a/csim/main.c +++ b/csim/main.c @@ -12,10 +12,12 @@ #include "sim.h" + void usage() { printf ("\nUsage:\n\tcsim [options] \n\n"); printf("Available options:\n"); - printf("\n -rom \n\tLoad a filename as a ROM file for the machine\n"); + printf("\n -rom \n\tLoad a filename as a ROM file for the machine\n"); + printf("\tA given ROM file is used for all ROM chips with variable name having given prefix\n"); printf("\n -n \n\tOnly run #steps steps of simulation (0 = infinity)\n"); printf("\n -in \n\tRead inputs from given file (eg. named pipe). Defaults to STDIN.\n"); printf("\n -out \n\tWrite outputs to given file (eg. named pipe). Defaults to STDOut.\n"); @@ -24,7 +26,6 @@ void usage() { // Arguments to be parsed int steps = 12; -char *romfile = NULL; char *filename = NULL; char *infile = NULL; char *outfile = NULL; @@ -34,7 +35,14 @@ int main(int argc, char **argv) { for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "-rom")) { if (++i == argc) usage(); - romfile = argv[i]; + if (++i == argc) usage(); + FILE *rom = fopen(argv[i], "r"); + if (!rom) { + fprintf(stderr, "Could not open ROM file: '%s'\n", argv[i]); + return 1; + } + add_rom(argv[i-1], rom); + fclose(rom); } else if (!strcmp(argv[i], "-n")) { if (++i == argc) usage(); steps = atoi(argv[i]); diff --git a/csim/sim.c b/csim/sim.c index 9c766e9..56c061b 100644 --- a/csim/sim.c +++ b/csim/sim.c @@ -13,16 +13,6 @@ #define DEBUG 0 -// Util - -int pow2(int exp) { - if (exp == 0) return 1; - if (exp == 1) return 2; - int k = pow2(exp / 2); - return (exp % 2 == 0 ? k * k : 2 * k * k); -} - -// The code t_machine *init_machine (t_program *p) { int i, j; @@ -62,27 +52,6 @@ t_machine *init_machine (t_program *p) { 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*, @@ -161,7 +130,12 @@ void machine_step(t_machine *m) { } break; case C_ROM: - // TODO + if (p->eqs[i].Rom.rom != NULL) { + a = m->var_values[p->eqs[i].Rom.read_addr]; + v = p->eqs[i].Rom.rom->data[a]; + } else { + v = 0; + } break; case C_CONCAT: a = m->var_values[p->eqs[i].Concat.a]; diff --git a/csim/sim.h b/csim/sim.h index 8b4a726..27b492d 100644 --- a/csim/sim.h +++ b/csim/sim.h @@ -1,8 +1,6 @@ #ifndef DEF_SIM_H #define DEF_SIM_H -// TODO implement ROM - #include // Gate types @@ -25,6 +23,14 @@ // 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; + +typedef struct _s_rom { + int addr_size, word_size; + t_value *data; + const char *prefix; + struct _s_rom *next; +} t_rom; + // Identifier for the variables of the circuit. typedef int t_id; @@ -62,7 +68,7 @@ typedef struct { t_id a, b, c; } Mux; struct { - int addr_size, word_size; + t_rom *rom; t_id read_addr; } Rom; struct { @@ -109,11 +115,16 @@ typedef struct { // The functions for doing stuff with these data structures t_program *load_dumb_netlist(FILE *stream); +void add_rom(const char *prefix, FILE *file); t_machine *init_machine(t_program *p); void read_inputs(t_machine *m, FILE *stream); void machine_step(t_machine *m); void write_outputs(t_machine *m, FILE *stream); +// util +int pow2(int exp); +t_value read_bool(FILE *stream, t_value *mask); +int is_prefix(char *prefix, char *str); #endif diff --git a/csim/util.c b/csim/util.c new file mode 100644 index 0000000..a09e959 --- /dev/null +++ b/csim/util.c @@ -0,0 +1,48 @@ +/* + Système Digital + 2013-2014 + Alex AUVOLAT + + util.c Various utility functions used elsewhere +*/ + + +#include "sim.h" + +int pow2(int exp) { + if (exp == 0) return 1; + if (exp == 1) return 2; + int k = pow2(exp / 2); + return (exp % 2 == 0 ? k * k : 2 * k * k); +} + +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; +} + +int is_prefix(char *prefix, char *str) { + while (*prefix) { + if (*prefix != *str) return 0; + prefix++; + str++; + } + return 1; +} diff --git a/tests/clock2.mj b/tests/clock2.mj new file mode 100644 index 0000000..50a0308 --- /dev/null +++ b/tests/clock2.mj @@ -0,0 +1,103 @@ +repeat(a) = (x:[n]) where + if n = 0 then + x = [] + else + x = a . repeat(a) + end if +end where + +fulladder(a,b,c) = (s, r) where + s = (a ^ b) ^ c; + r = (a & b) + ((a ^ b) & c); +end where + +adder(a:[n], b:[n], c_in) = (o:[n], c_out) where + if n = 1 then + (o, c_out) = fulladder(a[0], b[0], c_in) + else + (s_n, c_n1) = fulladder(a[0], b[0], c_in); + (s_n1, c_out) = adder(a[1..], b[1..], c_n1); + o = s_n . s_n1 + end if +end where + +equal(a:[n]) = (eq) where + if n = 0 then + eq = 1 + else + if m - (2 * (m / 2)) = 1 then + eq = a[0] & equal(a[1..]); + else + eq = (not a[0]) & equal(a[1..]); + end if + end if +end where + +reg_n(a:[n]) = (r:[n]) where + if n = 1 then + r = reg a[0] + else + r = (reg a[0]) . (reg_n(a[1..])) + end if +end where + +and_each(a, b:[n]) = (o:[n]) where + if n = 1 then + o = b[0] and a + else + o = (b[0] and a) . and_each(a, b[1..]) + end if +end where + +count_mod(in:[n], op) = (out:[n], reset) where + (incr, carry) = adder(in, repeat(0), op); + reset = equal(incr); + neq = not reset; + out = and_each(neq, incr); +end where + +count_mod_keep(op) = (out:[n], reset) where + (incr, carry) = adder(in, op . repeat(0), 0); + reset = equal(incr); + neq = not reset; + out = and_each(neq, incr); + in = reg_n(out) +end where + +dec7(i:[4]) = (o:[7]) where + decode7 = rom<4,7>(i); + o = decode7 +end where + +main() = (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_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; + d7_sec_u = dec7(sec_u); + sec_d = count_secc . 0; + d7_sec_d = dec7(sec_d); + + (count_mina, aug_mina) = count_mod_keep<2,2>(aug_min); + (count_minb, aug_minb) = count_mod_keep<3,5>(aug_mina); + (count_minc, aug_hour) = count_mod_keep<3,6>(aug_minb); + min_u = count_mina[0] . count_minb; + d7_min_u = dec7(min_u); + min_d = count_minc . 0; + d7_min_d = dec7(min_d); + + (v_hour_u, aug_houru) = count_mod<4, 10>(keep_hour_u, 1); + (v_hour_d, aug_hourd) = adder<2>(keep_hour_d, 0.0, aug_houru); + next_day = (equal<4,4>(v_hour_u)) and (equal<2,2>(v_hour_d)); + hour_u = and_each<4>(not next_day, v_hour_u); + hour_d_part = and_each<2>(not next_day, v_hour_d); + keep_hour_u = reg_n<4>(hour_u); + keep_hour_d = reg_n<2>(hour_d_part); + hour_d = hour_d_part . 0 . 0; + d7_hour_u = dec7(hour_u); + d7_hour_d = dec7(hour_d); +end where + diff --git a/tests/decode7.rom b/tests/decode7.rom new file mode 100644 index 0000000..0eaa3b1 --- /dev/null +++ b/tests/decode7.rom @@ -0,0 +1,17 @@ +4 7 +1110111 +0010010 +1011101 +1011011 +0111010 +1101011 +1101111 +1010010 +1111111 +1111011 +1011111 +0101111 +0001101 +0011111 +1101101 +1101100 diff --git a/tests/romtest.mj b/tests/romtest.mj new file mode 100644 index 0000000..6d2daf2 --- /dev/null +++ b/tests/romtest.mj @@ -0,0 +1,9 @@ +dec7(i:[4]) = (o:[7]) where + decode7 = rom<4,7>(i); + o = decode7 +end where + +main(i1:[4],i2:[4]) = (o1:[7],o2:[7]) where + o1 = dec7(i1); + o2 = dec7(i2) +end where -- cgit v1.2.3