diff options
author | David Phillips <david@sighup.nz> | 2017-12-27 21:21:54 +1300 |
---|---|---|
committer | David Phillips <david@sighup.nz> | 2017-12-27 21:21:54 +1300 |
commit | f23abfdde683aee4b808f2795af1a1418125156c (patch) | |
tree | f6faf313a32395b41ca4db628ef2eb4d4d950c1f | |
download | hence-f23abfdde683aee4b808f2795af1a1418125156c.tar.xz |
Initual dump of partial work on parser and data structure
-rw-r--r-- | .gitignore | 3 | ||||
-rw-r--r-- | Makefile | 7 | ||||
-rw-r--r-- | adder.lg | 9 | ||||
-rw-r--r-- | error.h | 4 | ||||
-rw-r--r-- | logic.c | 107 | ||||
-rw-r--r-- | logic.h | 18 | ||||
-rw-r--r-- | parser.c | 188 | ||||
-rw-r--r-- | simulator.c | 8 | ||||
-rw-r--r-- | wire.c | 106 | ||||
-rw-r--r-- | wire.h | 27 |
10 files changed, 477 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7bb37c6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*.o +simulator +parser diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..651c53c --- /dev/null +++ b/Makefile @@ -0,0 +1,7 @@ +CFLAGS += "-std=c99" + +all: simulator + +simulator: simulator.o wire.o logic.o + +parser: parser.o wire.o logic.o diff --git a/adder.lg b/adder.lg new file mode 100644 index 0000000..a883081 --- /dev/null +++ b/adder.lg @@ -0,0 +1,9 @@ +module adder + +node input a +node input b +node output r0 +node output r1 + +expr r0: xor a b +expr r1: and a b @@ -0,0 +1,4 @@ +#include <stdio.h> + +#define emit_error(...) fprintf(stderr, "Error: " __VA_ARGS__) +#define emit_info(...) fprintf(stdout, "Info : " __VA_ARGS__) @@ -0,0 +1,107 @@ +#define NDEBUG +#include <assert.h> + +#include "logic.h" +#include "error.h" + +enum BINARY +logic_not(enum BINARY input) { + switch (input) { + case LOGIC_HIGH: + return LOGIC_LOW; + case LOGIC_LOW: + return LOGIC_HIGH; + default: + emit_error("Severe: Invalid logic value found\n"); + } +} + +enum BINARY +logic_and(enum BINARY a, enum BINARY b) { + if (a == LOGIC_HIGH && b == LOGIC_HIGH) + return LOGIC_HIGH; + else + return LOGIC_LOW; +} + +enum BINARY +logic_or(enum BINARY a, enum BINARY b) { + if (a == LOGIC_HIGH || b == LOGIC_HIGH) + return LOGIC_HIGH; + else + return LOGIC_LOW; +} + +enum BINARY +logic_xor(enum BINARY a, enum BINARY b) { + if ( (a == LOGIC_HIGH && b == LOGIC_LOW) + || (a == LOGIC_LOW && b == LOGIC_HIGH)) + return LOGIC_HIGH; + else + return LOGIC_LOW; +} + +enum BINARY +logic_nand(enum BINARY a, enum BINARY b) { + return logic_not(logic_and(a, b)); +} + +enum BINARY +logic_nor(enum BINARY a, enum BINARY b) { + return logic_not(logic_or(a, b)); +} + +void +logic_test_and() { + emit_info("Testing AND\n"); + assert(LOGIC_HIGH == logic_and(LOGIC_HIGH, LOGIC_HIGH)); + assert(LOGIC_LOW == logic_and(LOGIC_HIGH, LOGIC_LOW )); + assert(LOGIC_LOW == logic_and(LOGIC_LOW , LOGIC_HIGH)); + assert(LOGIC_LOW == logic_and(LOGIC_LOW , LOGIC_LOW )); +} + +void +logic_test_or() { + emit_info("Testing OR\n"); + assert(LOGIC_HIGH == logic_or(LOGIC_HIGH, LOGIC_HIGH)); + assert(LOGIC_HIGH == logic_or(LOGIC_HIGH, LOGIC_LOW )); + assert(LOGIC_HIGH == logic_or(LOGIC_LOW , LOGIC_HIGH)); + assert(LOGIC_LOW == logic_or(LOGIC_LOW , LOGIC_LOW )); +} + +void +logic_test_xor() { + emit_info("Testing XOR\n"); + assert(LOGIC_HIGH == logic_xor(LOGIC_HIGH, LOGIC_LOW )); + assert(LOGIC_HIGH == logic_xor(LOGIC_LOW , LOGIC_HIGH)); + assert(LOGIC_LOW == logic_xor(LOGIC_HIGH, LOGIC_HIGH)); + assert(LOGIC_LOW == logic_xor(LOGIC_LOW , LOGIC_LOW )); +} + +void +logic_test_nand() { + emit_info("Testing NAND\n"); + assert(LOGIC_LOW == logic_nand(LOGIC_HIGH, LOGIC_HIGH)); + assert(LOGIC_HIGH == logic_nand(LOGIC_HIGH, LOGIC_LOW )); + assert(LOGIC_HIGH == logic_nand(LOGIC_LOW , LOGIC_HIGH)); + assert(LOGIC_HIGH == logic_nand(LOGIC_LOW , LOGIC_LOW )); +} + +void +logic_test_nor() { + emit_info("Testing NOR\n"); + assert(LOGIC_HIGH == logic_nor(LOGIC_LOW , LOGIC_LOW )); + assert(LOGIC_LOW == logic_nor(LOGIC_LOW , LOGIC_HIGH)); + assert(LOGIC_LOW == logic_nor(LOGIC_HIGH, LOGIC_LOW )); + assert(LOGIC_LOW == logic_nor(LOGIC_HIGH, LOGIC_HIGH)); +} + + +void +logic_test() { + logic_test_and(); + logic_test_or(); + logic_test_nand(); + logic_test_nor(); + logic_test_xor(); +} @@ -0,0 +1,18 @@ +#ifndef LOGIC_H +#define LOGIC_H + +enum BINARY { + LOGIC_HIGH, + 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); +enum BINARY logic_nand(enum BINARY a, enum BINARY b); +enum BINARY logic_nor(enum BINARY a, enum BINARY b); + +void logic_test(); + +#endif diff --git a/parser.c b/parser.c new file mode 100644 index 0000000..b2218b1 --- /dev/null +++ b/parser.c @@ -0,0 +1,188 @@ +#include <ctype.h> +#include <stdio.h> +#include <string.h> + +#include "error.h" +#include "logic.h" +#include "wire.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 { + 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 bop_lookup bop_handlers[] = { + {.str = "and", .handler = logic_and}, + {.str = "or", .handler = logic_or}, + {.str = "nand", .handler = logic_nand}, + {.str = "nor", .handler = logic_nor}, + {.str = "xor", .handler = logic_xor} +}; + +int parse_uop(char *str, enum BINARY (*handler)(enum BINARY)) { + /**/ + (void)str; + (void)handler; + emit_error("uop unimplemented\n"); + return 0; +} + +int parse_bop(char *str, enum BINARY (*handler)(enum BINARY, enum BINARY)) { + /**/ + (void)str; + (void)handler; + emit_error("bop unimplemented\n"); + return 0; +} + +int +parse_op(char *str) { + int match = 0; + size_t i = 0; + + match = 0; + 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)) { + return 1; + } + } + } + for (i = 0; i < sizeof(uop_handlers)/sizeof(uop_handlers[0]); i++) { + if (strcmp(uop_handlers[i].str, str) == 0) { + match = 1; + if (parse_uop("FIXME", uop_handlers[i].handler)) { + return 1; + } + } + } + if (match == 0) { + emit_error("Invalid operator \"%s\"\n", str); + return 1; + } + return 0; +} + +int +parse_expr(char *str) { + printf("expression %s\n", str); + return 0; +} + +int +parse_node(char *str) { + enum NODE_TYPE type = NODE_OUTPUT; + + 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"); + return 0; +} + +int +parse_module(char *str) { + printf("FIXME module name is \"%s\" but modules are not implemented\n", str); + return 0; +} + + + + +static struct tok_lookup tok_handlers[] = { + {.str = "node", .handler = parse_node}, + {.str = "module", .handler = parse_module}, + {.str = "expr", .handler = parse_expr} +}; + + + + + +int +parse_line(char *line) { + size_t i = 0; + char *tok = line; + char *delim = " "; + int match = 0; + + if ( strlen(line) == 0 + || (strlen(line) == 1 && isspace(line[0]))) { + return 0; + } + + tok = strtok(line, delim); + + match = 0; + for (i = 0; i < sizeof(tok_handlers)/sizeof(tok_handlers[0]); i++) { + if (strcmp(tok_handlers[i].str, tok) == 0) { + match = 1; + if ((tok_handlers[i].handler)(&tok[strlen(tok)+1])) { + return 1; + } + } + } + + if (match == 0) { + emit_error("invalid token \"%s\"", tok); + return 1; + } + return 0; +} + +int main(void) { + char buf[4096]; + FILE *fd = stdin; + + while (NULL != fgets(buf, sizeof(buf), fd)) { + buf[strcspn(buf, "\r\n")] = '\0'; + if (parse_line(buf)) { + return 1; + } + } + return 0; +} + + + diff --git a/simulator.c b/simulator.c new file mode 100644 index 0000000..389adc3 --- /dev/null +++ b/simulator.c @@ -0,0 +1,8 @@ +#include "wire.h" +#include "logic.h" + +int main(int argc, char **argv) { + logic_test(); + wire_init(); + return 0; +} @@ -0,0 +1,106 @@ +#include <string.h> + +#include "wire.h" +#include "error.h" + +#define WIRE_MAX 1024 +#define NODE_MAX 1024 + +static size_t wire_count; +static size_t node_count; + +static struct wire wires[WIRE_MAX]; +static struct node nodes[NODE_MAX]; + +int +wire_count_guard(void) { + if (wire_count >= WIRE_MAX) { + emit_error("Internal: too many wires\n"); + } + return 1; +} + +/* check if the nodes in a wire are allowed to be joined together */ +int +wire_nodes_valid(struct wire *w) { + /* FIXME needs to be more explicit if more than NODE_OUTPUT and NODE_INPUT + * out are added to node types */ + if (w->b->type == w->b->type) { + emit_error("Cannot wire %sput to node of same type\n", + w->a->type == NODE_OUTPUT ? "out" : "in" ); + return 1; + } + return 0; +} + +int +wire_add(size_t aoffs, size_t boffs) { + struct wire w = {0}; + + if (wire_count_guard()) { + return 1; + } + + if (aoffs >= NODE_MAX || boffs >= NODE_MAX) { + emit_error("Internal: cannot wire between node(s) outside allowable range\n"); + return 1; + } + + /* FIXME check that nodes are initialised? */ + + w.a = &nodes[aoffs]; + w.b = &nodes[boffs]; + + if (wire_nodes_valid(&w)) { + return 1; + } + + wires[wire_count++] = w; + + return 0; +} + +int +node_update(void) { + size_t i = 0; + struct node *na; + struct node *nb; + + if (wire_count_guard()) { + return 1; + } + + for (i = 0; i < wire_count; i++) { + na = wires[i].a; + nb = wires[i].b; + if (na->type == NODE_OUTPUT && nb->type == NODE_INPUT) { + nb->value = na->value; + } + + if (na->type == NODE_INPUT && nb->type == NODE_OUTPUT) { + na->value = nb->value; + } + } + return 0; +} + + +int +tick(void) { + nodes[0].value = logic_not(nodes[0].value); + node_update(); + return 0; +} + +void +wire_init(void) { + wire_count = 0; + memset(wires, 0, sizeof(wires)); + memset(nodes, 0, sizeof(nodes)); + + /* zeroth node is the clock source */ + node_count = 1; + nodes[0].type = NODE_OUTPUT; + nodes[0].value = 0; +} + @@ -0,0 +1,27 @@ +#ifndef WIRE_H +#define WIRE_H + +#include <stddef.h> + +#include "logic.h" + +enum NODE_TYPE { + NODE_OUTPUT, + NODE_INPUT +}; + +struct node { + enum NODE_TYPE type; + enum BINARY value; +}; + +struct wire { + struct node *a; + struct node *b; +}; + +int wire_add(size_t aoffs, size_t boffs); +int tick(void); +void wire_init(void); + +#endif |