From cebd07b64f1f537c5ecf00ec21ff4b7c4032f0a3 Mon Sep 17 00:00:00 2001 From: Alex AUVOLAT Date: Mon, 4 Nov 2013 22:05:57 +0100 Subject: Added stub C simulator (defined dumb-down syntax for netlists). --- csim/Makefile | 5 +++ csim/load.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++++ csim/main.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++ csim/sim.c | 23 ++++++++++++ csim/sim.h | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 345 insertions(+) create mode 100644 csim/Makefile create mode 100644 csim/load.c create mode 100644 csim/main.c create mode 100644 csim/sim.c create mode 100644 csim/sim.h (limited to 'csim') diff --git a/csim/Makefile b/csim/Makefile new file mode 100644 index 0000000..32d100d --- /dev/null +++ b/csim/Makefile @@ -0,0 +1,5 @@ +main: main.o load.o sim.o + gcc -o csim $^ + +%.o: %.c + gcc -c $< -o $@ -g diff --git a/csim/load.c b/csim/load.c new file mode 100644 index 0000000..397af5a --- /dev/null +++ b/csim/load.c @@ -0,0 +1,104 @@ +/* + Système Digital + 2013-2014 + Alex AUVOLAT + + load.c Code for loading dumbed-down netlist files + (no parsing of .net files !!) +*/ + +#include + +#include "sim.h" + +void read_arg(FILE *stream, t_arg *dest) { + if (fscanf(stream, "$%Ld ", &(dest->val)) > 0) { + dest->source_var = -1; + } else { + fscanf(stream, "%d ", &(dest->source_var)); + } +} + +t_program *load_dumb_netlist (FILE *stream) { + int i; + + // let us suppose that the input to be read is well-formed. + t_program *p = malloc(sizeof(t_program)); + + // Read variable list, with sizes and identifiers + fscanf(stream, "%d ", &(p->n_vars)); + p->vars = malloc(p->n_vars * sizeof(t_variable)); + + for (i = 0; i < p->n_vars; i++) { + fscanf(stream, "%d ", &(p->vars[i].size)); + p->vars[i].mask = (0xFFFFFFFFFFFFFFFF >> (64 - p->vars[i].size)); + + p->vars[i].name = malloc(42); // let's bet that the name of a variable will never be longer than 42 chars + fscanf(stream, "%s\n", p->vars[i].name); + } + + // read input list + fscanf(stream, "%d ", &(p->n_inputs)); + p->inputs = malloc(p->n_inputs * sizeof(t_id)); + for (i = 0; i < p->n_inputs; i++) { + fscanf(stream, "%d ", &(p->inputs[i])); + } + // read output list + fscanf(stream, "%d ", &(p->n_outputs)); + p->outputs = malloc(p->n_outputs * sizeof(t_id)); + for (i = 0; i < p->n_outputs; i++) { + fscanf(stream, "%d ", &(p->outputs[i])); + } + + // read equation list + fscanf(stream, "%d ", &(p->n_eqs)); + p->eqs = malloc(p->n_eqs * sizeof(t_equation)); + for (i = 0; i < p->n_eqs; i++) { + 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)); + break; + case C_NOT: + read_arg(stream, &(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)); + 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)); + 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_enable)); + read_arg(stream, &(p->eqs[i].Ram.data)); + break; + case C_CONCAT: + read_arg(stream, &(p->eqs[i].Mux.a)); + read_arg(stream, &(p->eqs[i].Mux.b)); + 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)); + break; + case C_SELECT: + fscanf(stream, "%d ", &(p->eqs[i].Select.i)); + read_arg(stream, &(p->eqs[i].Select.source)); + break; + } + } +} diff --git a/csim/main.c b/csim/main.c new file mode 100644 index 0000000..ce3f5b6 --- /dev/null +++ b/csim/main.c @@ -0,0 +1,97 @@ +/* + Système Digital + 2013-2014 + Alex AUVOLAT + + main.c Main file for the C simulator +*/ + +#include +#include +#include + +#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 -n \n\tOnly run #steps steps of simulation (-1 = 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"); + exit(1); +} + +// Arguments to be parsed +int steps = 42; +char *romfile = NULL; +char *filename = NULL; +char *infile = NULL; +char *outfile = NULL; + +int main(int argc, char **argv) { + int i; + for (i = 1; i < argc; i++) { + if (!strcmp(argv[i], "-rom")) { + if (++i == argc) usage(); + romfile = argv[i]; + } else if (!strcmp(argv[i], "-n")) { + if (++i == argc) usage(); + steps = atoi(argv[i]); + } else if (!strcmp(argv[i], "-in")) { + if (++i == argc) usage(); + infile = argv[i]; + } else if (!strcmp(argv[i], "-out")) { + if (++i == argc) usage(); + outfile = argv[i]; + } else { + filename = argv[i]; + } + } + + if (filename == NULL) usage(); + + // Load program + FILE *p_in; + p_in = fopen(filename, "r"); + if (!p_in) { + fprintf(stderr, "Error: could not open file %s for input.\n", filename); + return 1; + } + t_program* program = load_dumb_netlist(p_in); + fclose(p_in); + + // Setup input and outputs + FILE *input = stdin, *output = stdout; + if (infile != NULL) { + input = fopen(infile, "r"); + if (!infile) { + fprintf(stderr, "Error: could not open file %s for input.\n", infile); + return 1; + } + } + if (outfile != NULL) { + output = fopen(outfile, "w"); + if (!output) { + fprintf(stderr, "Error: could not open file %s for output.\n", outfile); + return 1; + } + } + + // Run + t_machine *machine = init_machine(program); + while (i < steps || steps == -1) { + read_inputs(machine, input); + machine_step(machine); + write_outputs(machine, output); + } + + // Cleanup + if (input != stdin) fclose(input); + if (output != stdout) fclose(output); + + // No need to free memory, the OS deletes everything anyways when the process ends. + + return 0; +} + diff --git a/csim/sim.c b/csim/sim.c new file mode 100644 index 0000000..27827d5 --- /dev/null +++ b/csim/sim.c @@ -0,0 +1,23 @@ +/* + Système Digital + 2013-2014 + Alex AUVOLAT + + sim.c The code that actually runs the machine +*/ + +#include "sim.h" + +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) { +} + + diff --git a/csim/sim.h b/csim/sim.h new file mode 100644 index 0000000..75f3502 --- /dev/null +++ b/csim/sim.h @@ -0,0 +1,116 @@ +#ifndef DEF_SIM_H +#define DEF_SIM_H + +// TODO implement ROM + +#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 + +// Binary operators +#define OP_OR 0 +#define OP_XOR 1 +#define OP_AND 2 +#define OP_NAND 3 + +// Data structures +typedef unsigned long long int t_value; +typedef int t_id; + +typedef struct { // a variable in the simulator + t_value mask; + int size; + char *name; +} t_variable; + +typedef struct { + t_value val; + t_id source_var; // if source_var == -1 then it's a direct value, else it's that variable +} t_arg; + +typedef struct { + int type; + t_id dest_var; + union { + struct { + t_arg a; + } Arg; + struct { + t_id var; + } Reg; + struct { + t_arg a; + } Not; + struct { + int op; + t_arg a, b; + } Binop; + struct { + t_arg a, b, c; + } Mux; + struct { + int addr_size, word_size; + t_arg read_addr; + } Rom; + struct { + int addr_size, word_size; + t_arg read_addr, write_enable, write_addr, data; + } Ram; + struct { + t_arg a, b; + } Concat; + struct { + int begin, end; + t_arg source; + } Slice; + struct { + int i; + t_arg source; + } Select; + }; +} t_equation; + + +typedef struct { + int n_vars, n_inputs, n_outputs; + t_variable *vars; + t_id *inputs, *outputs; + + int n_eqs; + t_equation *eqs; +} t_program; + +// machine = execution instance + +typedef union { + t_value r_val; + t_value *mem_val; +} t_mem_reg_data; + +typedef struct { + t_program *prog; + t_value *var_values; + t_mem_reg_data *mem_data; +} t_machine; + + +// The functions for doing stuff with these data structures + +t_program *load_dumb_netlist(FILE *stream); +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); + + +#endif -- cgit v1.2.3