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
|
/* very simple grid node with 32bit private region, does not currently signal
* being busy or anything. I think I might have to refine the message passing
* interface I have, but this is good enough.
*
* Each node should have a router beneath it, just to simplify my life. A router
* is basically a bus with a fallback ascension path.
*/
#include <gran/grid/node.h>
struct grid_node {
struct component component;
uint8_t u, v, x, y;
struct component *left, *right, *up, *down, *ascend, *lower;
};
typedef read_callback callback;
static stat grid_route(struct grid_node *grid, struct packet *pkt, callback op)
{
uint64_t addr = packet_addr(pkt);
uint8_t u = (addr >> 56) & 0xff;
uint8_t v = (addr >> 48) & 0xff;
uint8_t x = (addr >> 40) & 0xff;
uint8_t y = (addr >> 32) & 0xff;
if (grid->u == u && grid->v == v && grid->x == x && grid->y == y)
return op(grid->lower, pkt);
if (grid->u != u || grid->v != v) {
if (!grid->ascend)
return EBUS;
return op(grid->ascend, pkt);
}
if (y < grid->y) {
if (!grid->down)
return EBUS;
return op(grid->down, pkt);
}
if (y > grid->y) {
if (!grid->up)
return EBUS;
return op(grid->up, pkt);
}
if (x < grid->x) {
if (!grid->left)
return EBUS;
return op(grid->left, pkt);
}
if (x > grid->x) {
if (!grid->right)
return EBUS;
return op(grid->right, pkt);
}
return EBUS;
}
static stat grid_write(struct grid_node *node, struct packet *pkt)
{
return grid_route(node, pkt, write);
}
static stat grid_read(struct grid_node *node, struct packet *pkt)
{
return grid_route(node, pkt, read);
}
struct component *create_grid_node(uint8_t u, uint8_t v, uint8_t x, uint8_t y)
{
struct grid_node *node = calloc(1, sizeof(struct grid_node));
if (!node)
return NULL;
node->u = u;
node->v = v;
node->x = x;
node->y = y;
node->component.write = (write_callback)grid_write;
node->component.read = (read_callback)grid_read;
return (struct component *)node;
}
stat grid_node_connect(struct component *node,
struct component *left, struct component *right,
struct component *up, struct component *down,
struct component *lower, struct component *ascend)
{
struct grid_node *n = (struct grid_node *)node;
n->left = left;
n->right = right;
n->up = up;
n->down = down;
n->lower = lower;
n->ascend = ascend;
return OK;
}
|