summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--adder.lg6
-rw-r--r--gate.c104
-rw-r--r--gate.h11
-rw-r--r--logic.h1
-rw-r--r--parser.c85
6 files changed, 135 insertions, 74 deletions
diff --git a/Makefile b/Makefile
index b40650e..0f21fee 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-CFLAGS += "-std=c99"
+CFLAGS += -std=c99 -D_XOPEN_SOURCE=500
all: simulator
diff --git a/adder.lg b/adder.lg
index a883081..f751a3b 100644
--- a/adder.lg
+++ b/adder.lg
@@ -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
diff --git a/gate.c b/gate.c
index 0d4337a..fb5ff41 100644
--- a/gate.c
+++ b/gate.c
@@ -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);
+ }
+}
diff --git a/gate.h b/gate.h
index fcc84bb..1838913 100644
--- a/gate.h
+++ b/gate.h
@@ -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
diff --git a/logic.h b/logic.h
index 95d2663..d791eef 100644
--- a/logic.h
+++ b/logic.h
@@ -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);
diff --git a/parser.c b/parser.c
index f3fe38d..19610b9 100644
--- a/parser.c
+++ b/parser.c
@@ -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;
}