aboutsummaryrefslogtreecommitdiff
path: root/src/components/grid
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2024-09-22 22:45:18 +0300
committerKimplul <kimi.h.kuparinen@gmail.com>2024-09-22 22:45:18 +0300
commitb1d67364b4b4832b8efed112f7b0ead1a0b3cd3b (patch)
tree7926bfb428703515438c08b98c61cbffd34b3cbb /src/components/grid
parent32f9719e29762001f73460acd31f2a6da8fd6298 (diff)
downloadgran-b1d67364b4b4832b8efed112f7b0ead1a0b3cd3b.tar.gz
gran-b1d67364b4b4832b8efed112f7b0ead1a0b3cd3b.zip
start experimenting with processor grids
Diffstat (limited to 'src/components/grid')
-rw-r--r--src/components/grid/node.c106
-rw-r--r--src/components/grid/router.c114
-rw-r--r--src/components/grid/source.mk1
3 files changed, 221 insertions, 0 deletions
diff --git a/src/components/grid/node.c b/src/components/grid/node.c
new file mode 100644
index 0000000..0aed768
--- /dev/null
+++ b/src/components/grid/node.c
@@ -0,0 +1,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;
+}
diff --git a/src/components/grid/router.c b/src/components/grid/router.c
new file mode 100644
index 0000000..bdb05c8
--- /dev/null
+++ b/src/components/grid/router.c
@@ -0,0 +1,114 @@
+#include <gran/grid/router.h>
+#include <gran/vec.h>
+
+struct router_region {
+ uint32_t addr;
+ uint32_t size;
+ struct component *component;
+};
+
+struct node_router {
+ struct component component;
+ struct component *ascend;
+ struct vec regions;
+ uint8_t u, v, x, y;
+};
+
+static struct router_region *find_region(struct node_router *router, uint32_t addr)
+{
+ for (size_t i = 0; i < vec_len(&router->regions); ++i) {
+ struct router_region *region = vec_at(&router->regions, i);
+
+ if (addr >= region->addr && addr < region->addr + region->size)
+ return region;
+ }
+
+ return NULL;
+}
+
+static stat router_write(struct node_router *router, struct packet *pkt)
+{
+ 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 (router->u != u || router->v != v || router->x != x || router->y != y)
+ return write(router->ascend, pkt);
+
+ struct router_region *region = find_region(router, addr);
+ if (!region)
+ return write(router->ascend, pkt);
+
+ return write(region->component, pkt);
+}
+
+static stat router_read(struct node_router *router, struct packet *pkt)
+{
+ 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 (router->u != u || router->v != v || router->x != x || router->y != y)
+ return read(router->ascend, pkt);
+
+ struct router_region *region = find_region(router, addr);
+ if (!region)
+ return read(router->ascend, pkt);
+
+ return read(region->component, pkt);
+}
+
+struct component *create_node_router(uint8_t u, uint8_t v, uint8_t x, uint8_t y)
+{
+ struct node_router *router = calloc(1, sizeof(struct node_router));
+ if (!router)
+ return NULL;
+
+ router->u = u;
+ router->v = v;
+ router->x = x;
+ router->y = y;
+
+ router->component.write = (write_callback)router_write;
+ router->component.read = (read_callback)router_read;
+ router->regions = vec_create(sizeof(struct router_region));
+
+ return (struct component *)router;
+}
+
+stat node_router_add(struct component *router, struct component *component, uint32_t addr, uint32_t size)
+{
+ struct node_router *nr = (struct node_router *)router;
+ struct router_region *found = find_region(nr, addr);
+ if (!found) found = find_region(nr, addr + size);
+
+ if (found) {
+ error("%s overlaps with %s at %x",
+ found->component->name,
+ component->name,
+ found->addr
+ );
+
+ return EEXISTS;
+ }
+
+ struct router_region r = (struct router_region){
+ .addr = addr,
+ .size = size,
+ .component = component
+ };
+ vect_append(struct node_region, nr->regions, &r);
+
+ return OK;
+}
+
+stat node_router_ascend(struct component *router, struct component *node)
+{
+ struct node_router *nr = (struct node_router *)router;
+ nr->ascend = node;
+ return OK;
+}
diff --git a/src/components/grid/source.mk b/src/components/grid/source.mk
new file mode 100644
index 0000000..4fb44ec
--- /dev/null
+++ b/src/components/grid/source.mk
@@ -0,0 +1 @@
+SOURCES += src/components/grid/node.c src/components/grid/router.c