From 9026a7e5c0f16bde1c0826dc95158c6e03795905 Mon Sep 17 00:00:00 2001
From: David Phillips <david@sighup.nz>
Date: Thu, 28 Dec 2017 16:06:01 +1300
Subject: Rough-out logic gate wiring

---
 Makefile |   2 +-
 adder.lg |   6 ++--
 gate.c   | 104 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
 gate.h   |  11 ++++++-
 logic.h  |   1 -
 parser.c |  85 +++++++++++++++++----------------------------------
 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;
 }
 
-- 
cgit v1.1