diff options
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | adder.lg | 6 | ||||
-rw-r--r-- | gate.c | 104 | ||||
-rw-r--r-- | gate.h | 11 | ||||
-rw-r--r-- | logic.h | 1 | ||||
-rw-r--r-- | parser.c | 85 |
6 files changed, 135 insertions, 74 deletions
@@ -1,4 +1,4 @@ -CFLAGS += "-std=c99" +CFLAGS += -std=c99 -D_XOPEN_SOURCE=500 all: simulator @@ -1,9 +1,7 @@ module adder -node input a -node input b -node output r0 -node output r1 +input a +input b expr r0: xor a b expr r1: and a b @@ -1,37 +1,110 @@ #include <string.h> +#include <stdlib.h> #include "gate.h" #include "error.h" -#define GATE_MAX 1024 +#define GATE_MAX 1024 +#define INPUT_MAX 1024 +#define OUTPUT_MAX 1024 static size_t gate_count; +static size_t input_count; +static size_t output_count; static struct gate gates[GATE_MAX]; +static struct gate inputs[INPUT_MAX]; +static struct gate outputs[OUTPUT_MAX]; + int -gate_count_guard(void) { - if (gate_count >= GATE_MAX) { - emit_error("Internal: too many gates\n"); +count_guard(int c, int max, char *desc) { + if (c >= max) { + emit_error("Internal: too many %s\n", desc); + return 1; } - return 1; + return 0; } int -gate_add(struct gate *in1, struct gate *in2) { +gate_add_generic(struct gate *array, size_t array_index, char *name, enum BINARY (*operation)(enum BINARY, enum BINARY), struct gate *in1, struct gate *in2) { struct gate g = {0}; - if (gate_count_guard()) { - return 1; + if (name == NULL) { + g.name = NULL; + } else { + g.name = strdup(name); + if (g.name == NULL) { + emit_error("strdup failed"); + return 1; + } } - + g.operation = operation; g.in1 = in1; g.in2 = in2; - gates[gate_count++] = g; + array[array_index] = g; + + return 0; +} + +struct gate* +gate_get_input_by_name(char *name) { + struct gate *res = NULL; + size_t i = 0; + + for (i = 0; i < input_count; i++) { + if (inputs[i].name == NULL) { + emit_error("input at index %zd has NULL name, ignoring", i); + continue; + } + if (strcmp(inputs[i].name, name) == 0) { + res = &inputs[i]; + break; + } + } + + return res; +} + +int +gate_input_add(char *name) { + int res = 0; + if (count_guard(input_count, INPUT_MAX, "inputs")) { + return 1; + } + + if (gate_get_input_by_name(name) != NULL) { + emit_error("Already an input called \"%s\"!\n", name); + return 1; + } + + res = gate_add_generic(inputs, input_count, name, logic_and, NULL, NULL); + input_count++; + return res; +} + +int +gate_add(char *name, enum BINARY (*operation)(enum BINARY, enum BINARY), struct gate *in1, struct gate *in2) { + if (count_guard(gate_count, GATE_MAX, "gates")) { + return 1; + } + + gate_add_generic(gates, gate_count, name, operation, in1, in2); + gate_count++; return 0; } +void +gate_free_all() { + size_t i = 0; + for (i = 0; i < gate_count; i++) { + if (gates[i].name != NULL) { + free(gates[i].name); + } + } +} + int tick(void) { /* FIXME */ @@ -41,6 +114,17 @@ tick(void) { void gate_init(void) { gate_count = 0; + input_count = 0; memset(gates, 0, sizeof(gates)); + memset(inputs, 0, sizeof(inputs)); } +void +gate_dump(void) { + size_t i = 0; + + emit_info("Gates:\n"); + for (i = 0; i < gate_count; i++) { + emit_info("gate '%s'\n", gates[i].name); + } +} @@ -5,7 +5,13 @@ #include "logic.h" +enum NODE_TYPE { + NODE_INPUT, + NODE_OUTPUT +}; + struct gate { + char *name; enum BINARY (*operation)(enum BINARY, enum BINARY); enum BINARY output; struct gate *in1; @@ -13,8 +19,11 @@ struct gate { }; void gate_update_output(struct gate *); -int gate_add(struct gate *in1, struct gate *in2); +int gate_input_add(char *name); +struct gate* gate_get_input_by_name(char *name); +int gate_add(char *name, enum BINARY (*operation)(enum BINARY, enum BINARY), struct gate *in1, struct gate *in2); int tick(void); void gate_init(void); +void gate_dump(void); #endif @@ -6,7 +6,6 @@ enum BINARY { LOGIC_LOW }; -enum BINARY logic_not(enum BINARY input); enum BINARY logic_and(enum BINARY a, enum BINARY b); enum BINARY logic_or(enum BINARY a, enum BINARY b); enum BINARY logic_xor(enum BINARY a, enum BINARY b); @@ -7,45 +7,21 @@ #include "logic.h" #include "gate.h" -enum STATEMENT_TYPE { - DECL_EXPR, - DECL_INPUT, - DECL_OUTPUT, - MODULE_NAME -}; - -enum UNARY_OPERATOR { - UOP_NOT -}; - -enum BINARY_OPERATOR { - BOP_AND, - BOR_OR, - BOP_NAND, - BOP_NOR, - BOP_XOR -}; - struct tok_lookup { char *str; int (*handler)(char*); }; -struct bop_lookup { +struct op_lookup { char *str; enum BINARY (*handler)(enum BINARY, enum BINARY); }; -struct uop_lookup { - char *str; - enum BINARY (*handler)(enum BINARY); -}; - -static struct uop_lookup uop_handlers[] = { - {.str = "not", .handler = logic_not}, +static struct op_lookup uop_handlers[] = { + {.str = "not", .handler = logic_nand}, }; -static struct bop_lookup bop_handlers[] = { +static struct op_lookup bop_handlers[] = { {.str = "and", .handler = logic_and}, {.str = "or", .handler = logic_or}, {.str = "nand", .handler = logic_nand}, @@ -67,24 +43,32 @@ expect(const char *expect, char *actual) { } -int parse_uop(char *str, enum BINARY (*handler)(enum BINARY)) { - /**/ +int parse_uop(char *str, enum BINARY (*handler)(enum BINARY, enum BINARY)) { (void)str; (void)handler; emit_error("uop unimplemented\n"); - return 0; + /* FIXME add gate with specified handler, tie both inputs together */ + return 1; } -int parse_bop(char *str, enum BINARY (*handler)(enum BINARY, enum BINARY)) { - /**/ - (void)str; - (void)handler; - emit_error("bop unimplemented\n"); +int parse_bop(char *str, char *name, enum BINARY (*handler)(enum BINARY, enum BINARY)) { + char *gate_name1 = str; + char *gate_name2 = NULL; + + strtok(gate_name1, " "); + gate_name2 = gate_name1 + strlen(gate_name1) + 1; + strtok(gate_name2, " "); + + /* FIXME allow input from other gates, not just inputs */ + struct gate *in1 = gate_get_input_by_name(gate_name1); + struct gate *in2 = gate_get_input_by_name(gate_name2); + + gate_add(name, handler, in1, in2); return 0; } int -parse_op(char *str) { +parse_op(char *str, char *name) { int match = 0; size_t i = 0; @@ -93,7 +77,7 @@ parse_op(char *str) { for (i = 0; i < sizeof(bop_handlers)/sizeof(bop_handlers[0]); i++) { if (strcmp(bop_handlers[i].str, str) == 0) { match = 1; - if (parse_bop("FIXME", bop_handlers[i].handler)) { + if (parse_bop(str+strlen(str)+1, name, bop_handlers[i].handler)) { return 1; } } @@ -120,8 +104,6 @@ parse_expr(char *str) { char *ident = NULL; char *op = NULL; - printf("expression %s\n", str); - /* FIXME magic constant string */ ident_len = strspn(str, "abcdefghijklmnopqrstuvwxyz0123456789"); @@ -133,26 +115,13 @@ parse_expr(char *str) { ident = str; op = str + ident_len + strlen(expr_sep); - /* FIXME do something with the identifier */ - - return parse_op(op); + return parse_op(op, ident); } int -parse_node(char *str) { - enum NODE_TYPE type = NODE_OUTPUT; - +parse_input(char *str) { strtok(str, " "); - if (strcmp(str, "output") == 0) { - type = NODE_OUTPUT; - } else if (strcmp(str, "input") == 0) { - type = NODE_INPUT; - } else { - emit_error("'%s' is not a valid node type\n", str); - return 1; - } - - printf("FIXME need to add node of type %s\n", type == NODE_OUTPUT ? "oot" : "innnn"); + gate_input_add(str); return 0; } @@ -166,7 +135,7 @@ parse_module(char *str) { static struct tok_lookup tok_handlers[] = { - {.str = "node", .handler = parse_node}, + {.str = "input", .handler = parse_input}, {.str = "module", .handler = parse_module}, {.str = "expr", .handler = parse_expr} }; @@ -216,6 +185,8 @@ int main(void) { return 1; } } + gate_dump(); + return 0; } |