summaryrefslogtreecommitdiff
path: root/wire.c
blob: e181d83725310fc12c8ef74eaf7de3585c1588c7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
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;
}