summaryrefslogtreecommitdiff
path: root/gate.c
diff options
context:
space:
mode:
authorDavid Phillips <david@sighup.nz>2017-12-28 16:06:01 +1300
committerDavid Phillips <david@sighup.nz>2017-12-28 16:06:01 +1300
commit9026a7e5c0f16bde1c0826dc95158c6e03795905 (patch)
treeb126e3c2d2233ade9325075f4f325c5e3822cfa5 /gate.c
parentf5411bc35f6df1c27aae8d3405e18452cbbc957f (diff)
downloadhence-9026a7e5c0f16bde1c0826dc95158c6e03795905.tar.xz
Rough-out logic gate wiring
Diffstat (limited to 'gate.c')
-rw-r--r--gate.c104
1 files changed, 94 insertions, 10 deletions
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);
+ }
+}