diff options
| author | Kimplul <kimi.h.kuparinen@gmail.com> | 2025-02-24 21:31:46 +0200 |
|---|---|---|
| committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2025-02-24 21:31:46 +0200 |
| commit | e991095180f774e3582329447c291a11499989ba (patch) | |
| tree | 0708d2308a229b932a84d8ae803b31d296f9fc0f /src | |
| parent | 238116c1cf08b93335abd493df110a669786553e (diff) | |
| download | gran-e991095180f774e3582329447c291a11499989ba.tar.gz gran-e991095180f774e3582329447c291a11499989ba.zip | |
overhaul meshes
+ Previous name was grid
Diffstat (limited to 'src')
| -rw-r--r-- | src/grid/node.c | 178 | ||||
| -rw-r--r-- | src/grid/node3d.c | 205 | ||||
| -rw-r--r-- | src/grid/source.mk | 1 | ||||
| -rw-r--r-- | src/mesh/node.c | 164 | ||||
| -rw-r--r-- | src/mesh/node3d.c | 189 | ||||
| -rw-r--r-- | src/mesh/source.mk | 1 |
6 files changed, 354 insertions, 384 deletions
diff --git a/src/grid/node.c b/src/grid/node.c deleted file mode 100644 index 512cae3..0000000 --- a/src/grid/node.c +++ /dev/null @@ -1,178 +0,0 @@ -/* 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 <stdbool.h> - -#include <gran/grid/node.h> - -struct port { - struct component *send; - struct packet pkt; - bool busy; -}; - -struct grid_node { - struct component component; - uint16_t x, y; - - struct port left, right, up, down, lower; - - unsigned priority; -}; - -static stat port_clock(struct grid_node *grid, struct port *to, struct port *from) -{ - assert(from->busy); - stat r = SEND(grid, to->send, from->pkt); - if (r == EBUSY) { - grid->priority++; - return OK; - } - - from->busy = false; - return OK; -} - -static struct port *select_input(struct grid_node *grid) -{ - struct port *ports[5] = { - &grid->left, - &grid->right, - &grid->up, - &grid->down, - &grid->lower, - }; - for (size_t i = 0; i < 5; ++i) { - size_t idx = (i + grid->priority) % 5; - struct port *port = ports[idx]; - if (!port) - continue; - - if (!port->busy) - continue; - - return port; - } - - return NULL; -} - -static stat clock_once(struct grid_node *grid) -{ - struct port *input = select_input(grid); - if (!input) - return OK; - - uint16_t x; - uint16_t y; - uint64_t addr = input->pkt.to; - addr_grid(addr, NULL, &x, &y); - - if (grid->x == x && grid->y == y) { - if (!grid->lower.send) - goto nosuch; - - return port_clock(grid, &grid->lower, input); - } - - if (y < grid->y) { - if (!grid->down.send) - goto nosuch; - - return port_clock(grid, &grid->down, input); - } - - if (y > grid->y) { - if (!grid->up.send) - goto nosuch; - - return port_clock(grid, &grid->up, input); - } - - if (x < grid->x) { - if (!grid->left.send) - goto nosuch; - - return port_clock(grid, &grid->left, input); - } - - if (x > grid->x) { - if (!grid->right.send) - goto nosuch; - - return port_clock(grid, &grid->right, input); - } - -nosuch: - abort(); - return OK; -} - -static stat grid_clock(struct grid_node *grid) -{ - clock_once(grid); - return OK; -} - - -static stat port_receive(struct port *port, struct packet pkt) -{ - if (port->busy) - return EBUSY; - - port->pkt = pkt; - port->busy = true; - return OK; -} - -static stat grid_receive(struct grid_node *grid, struct component *from, struct packet pkt) -{ - if (from == grid->lower.send) - return port_receive(&grid->lower, pkt); - - if (from == grid->left.send) - return port_receive(&grid->left, pkt); - - if (from == grid->right.send) - return port_receive(&grid->right, pkt); - - if (from == grid->down.send) - return port_receive(&grid->down, pkt); - - if (from == grid->up.send) - return port_receive(&grid->up, pkt); - - abort(); - return OK; -} - -struct component *create_grid_node(uint16_t x, uint16_t y) -{ - struct grid_node *node = calloc(1, sizeof(struct grid_node)); - if (!node) - return NULL; - - node->component.receive = (receive_callback)grid_receive; - node->component.clock = (clock_callback)grid_clock; - node->x = x; - node->y = y; - 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 grid_node *n = (struct grid_node *)node; - n->left.send = left; - n->right.send = right; - n->up.send = up; - n->down.send = down; - n->lower.send = lower; - return OK; -} diff --git a/src/grid/node3d.c b/src/grid/node3d.c deleted file mode 100644 index f404ea0..0000000 --- a/src/grid/node3d.c +++ /dev/null @@ -1,205 +0,0 @@ -#include <gran/grid/node3d.h> - -struct reg { - struct packet pkt; - bool busy; -}; - -struct node3d { - struct component component; - uint8_t x, y, z; - - uint64_t timestamp; - - struct component *n, *s, *w, *e, *u, *d, *l; - - struct reg n_in, s_in, w_in, e_in, u_in, d_in, l_in; -}; - -static stat reg_receive(struct reg *r, struct packet pkt) -{ - if (r->busy) - return EBUSY; - - r->pkt = pkt; - r->busy = true; - return OK; -} - -/* LX = node.x > pkt.x, etc */ -enum match { - LX = (1 << 0), - LY = (1 << 1), - LZ = (1 << 2), - GX = (1 << 3), - GY = (1 << 4), - GZ = (1 << 5), - NX = (1 << 6), - NY = (1 << 7), - NZ = (1 << 8), -}; - -static void maybe_route_reg(struct node3d *node3d, struct reg *reg, enum match m, uint64_t *oldest, struct packet **pkt, bool **busy) -{ - if (!reg->busy) - return; - - uint8_t x, y, z; - addr_grid3d(reg->pkt.to, &x, &y, &z, NULL); - - if ((m & LX) && x < node3d->x) - return; - - if ((m & LY) && y < node3d->y) - return; - - if ((m & LZ) && z < node3d->z) - return; - - if ((m & GX) && x > node3d->x) - return; - - if ((m & GY) && y > node3d->y) - return; - - if ((m & GZ) && z > node3d->z) - return; - - if ((m & NX) && x == node3d->x) - return; - - if ((m & NY) && y == node3d->y) - return; - - if ((m & NZ) && z == node3d->z) - return; - - if (reg->pkt.timestamp < *oldest) { - *oldest = reg->pkt.timestamp; - *busy = ®->busy; - *pkt = ®->pkt; - } -} - -static stat route(struct node3d *node3d, struct component *next, enum match m) -{ - uint64_t oldest = -1; struct packet *pkt = NULL; bool *busy = NULL; - maybe_route_reg(node3d, &node3d->l_in, m, &oldest, &pkt, &busy); - maybe_route_reg(node3d, &node3d->n_in, m, &oldest, &pkt, &busy); - maybe_route_reg(node3d, &node3d->s_in, m, &oldest, &pkt, &busy); - maybe_route_reg(node3d, &node3d->e_in, m, &oldest, &pkt, &busy); - maybe_route_reg(node3d, &node3d->w_in, m, &oldest, &pkt, &busy); - maybe_route_reg(node3d, &node3d->u_in, m, &oldest, &pkt, &busy); - maybe_route_reg(node3d, &node3d->d_in, m, &oldest, &pkt, &busy); - - /* no suitable match */ - if (pkt == NULL) - return OK; - - assert(busy); - - if (!next) { - abort(); /* for now, eventually should probably return to sender */ - return OK; - } - - stat ret = SEND(node3d, next, *pkt); - if (ret == EBUSY) - return OK; - - *busy = false; - return OK; -} - -static stat node3d_clock(struct node3d *node3d) -{ - node3d->timestamp++; - - stat ret = OK; - if ((ret = route(node3d, node3d->e, LX | NX))) - return ret; - - if ((ret = route(node3d, node3d->w, GX | NX))) - return ret; - - if ((ret = route(node3d, node3d->n, LX | GX | LY | NY))) - return ret; - - if ((ret = route(node3d, node3d->s, LX | GX | GY | NY))) - return ret; - - if ((ret = route(node3d, node3d->u, LX | GX | LY | GY | LZ | NZ))) - return ret; - - if ((ret = route(node3d, node3d->d, LX | GX | LY | GY | GZ | NZ))) - return ret; - - if ((ret = route(node3d, node3d->l, LX | LY | LZ | GX | GY | GZ))) - return ret; - - return OK; -} - -static stat node3d_receive(struct node3d *node3d, struct component *from, struct packet pkt) -{ - if (from == node3d->l) { - /* add time when packet entered network */ - pkt.timestamp = node3d->timestamp; - return reg_receive(&node3d->l_in, pkt); - } - - if (from == node3d->n) - return reg_receive(&node3d->n_in, pkt); - - if (from == node3d->s) - return reg_receive(&node3d->s_in, pkt); - - if (from == node3d->w) - return reg_receive(&node3d->w_in, pkt); - - if (from == node3d->e) - return reg_receive(&node3d->e_in, pkt); - - if (from == node3d->u) - return reg_receive(&node3d->u_in, pkt); - - if (from == node3d->d) - return reg_receive(&node3d->d_in, pkt); - - abort(); - return OK; -} - -struct component *create_grid_node3d(uint8_t x, uint8_t y, uint8_t z) -{ - struct node3d *node = calloc(1, sizeof(struct node3d)); - if (!node) - return NULL; - - node->component.receive = (receive_callback)node3d_receive; - node->component.clock = (clock_callback)node3d_clock; - node->x = x; - node->y = y; - node->z = z; - return (struct component *)node; -} - -stat grid_node3d_connect(struct component *node, - struct component *n, - struct component *s, - struct component *w, - struct component *e, - struct component *u, - struct component *d, - struct component *l) -{ - struct node3d *node3d = (struct node3d *)node; - node3d->n = n; - node3d->s = s; - node3d->w = w; - node3d->e = e; - node3d->u = u; - node3d->d = d; - node3d->l = l; - return OK; -} diff --git a/src/grid/source.mk b/src/grid/source.mk deleted file mode 100644 index 79fe708..0000000 --- a/src/grid/source.mk +++ /dev/null @@ -1 +0,0 @@ -SOURCES += src/grid/node.c src/grid/node3d.c diff --git a/src/mesh/node.c b/src/mesh/node.c new file mode 100644 index 0000000..2ac921a --- /dev/null +++ b/src/mesh/node.c @@ -0,0 +1,164 @@ +#include <gran/mesh/node.h> + +struct reg { + struct packet pkt; + bool busy; +}; + +struct node { + struct component component; + uint16_t x, y; + + uint64_t timestamp; + + struct component *n, *s, *e, *w, *l; + + struct reg n_in, s_in, e_in, w_in, l_in; +}; + +enum order { + N, S, E, W, L +}; + +static inline void maybe_pick(struct reg *output[5], enum order d, struct reg *r) +{ + if (output[d] && output[d]->pkt.timestamp < r->pkt.timestamp) + return; + + output[d] = r; +} + +static stat node_clock(struct node *node) +{ + node->timestamp++; + + struct reg *output[5] = {NULL, NULL, NULL, NULL, NULL}; + struct reg *input[5] = { + &node->n_in, + &node->s_in, + &node->e_in, + &node->w_in, + &node->l_in + }; + + uint8_t X = node->x, Y = node->y; + for (size_t i = 0; i < 5; ++i) { + struct reg *r = input[i]; + if (!r->busy) + continue; + + uint16_t x, y; + addr_mesh(r->pkt.to, &x, &y, NULL); + if (x < X) { + maybe_pick(output, W, r); + continue; + } + + if (x > X) { + maybe_pick(output, E, r); + continue; + } + + if (y < Y) { + maybe_pick(output, S, r); + continue; + } + + if (y > Y) { + maybe_pick(output, N, r); + continue; + } + + maybe_pick(output, L, r); + } + + struct component *target[7] = { + node->n, + node->s, + node->e, + node->w, + node->l + }; + + for (size_t i = 0; i < 5; ++i) { + if (!output[i]) + continue; + + if (!target[i]) { + /* for now, should send packet back with an error or something */ + abort(); + } + + stat ret = SEND(node, target[i], output[i]->pkt); + if (ret == EBUSY) + continue; + + assert(ret == OK); + output[i]->busy = false; + } + + return OK; +} + +static stat reg_receive(struct reg *r, struct packet pkt) +{ + if (r->busy) + return EBUSY; + + r->pkt = pkt; + r->busy = true; + return OK; +} + +static stat node_receive(struct node *node, struct component *from, struct packet pkt) +{ + if (from == node->l) { + /* add time when packet entered network */ + pkt.timestamp = node->timestamp; + return reg_receive(&node->l_in, pkt); + } + + if (from == node->n) + return reg_receive(&node->n_in, pkt); + + if (from == node->s) + return reg_receive(&node->s_in, pkt); + + if (from == node->e) + return reg_receive(&node->e_in, pkt); + + if (from == node->w) + return reg_receive(&node->w_in, pkt); + + abort(); + return OK; +} + +struct component *create_mesh_node(uint16_t x, uint16_t y) +{ + struct node *node = calloc(1, sizeof(struct node)); + if (!node) + return NULL; + + node->component.receive = (receive_callback)node_receive; + node->component.clock = (clock_callback)node_clock; + node->x = x; + node->y = y; + return (struct component *)node; +} + +stat mesh_node_connect(struct component *node, + struct component *n, + struct component *s, + struct component *e, + struct component *w, + struct component *l) +{ + struct node *nod = (struct node *)node; + nod->n = n; + nod->s = s; + nod->e = e; + nod->w = w; + nod->l = l; + return OK; +} diff --git a/src/mesh/node3d.c b/src/mesh/node3d.c new file mode 100644 index 0000000..d00f762 --- /dev/null +++ b/src/mesh/node3d.c @@ -0,0 +1,189 @@ +#include <gran/mesh/node3d.h> + +struct reg { + struct packet pkt; + bool busy; +}; + +struct node3d { + struct component component; + uint8_t x, y, z; + + uint64_t timestamp; + + struct component *n, *s, *e, *w, *u, *d, *l; + + struct reg n_in, s_in, e_in, w_in, u_in, d_in, l_in; +}; + +enum order { + N, S, E, W, U, D, L +}; + +static inline void maybe_pick(struct reg *output[7], enum order d, struct reg *r) +{ + if (output[d] && output[d]->pkt.timestamp < r->pkt.timestamp) + return; + + output[d] = r; +} + +static stat node3d_clock(struct node3d *node3d) +{ + node3d->timestamp++; + + struct reg *output[7] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL}; + struct reg *input[7] = { + &node3d->n_in, + &node3d->s_in, + &node3d->e_in, + &node3d->w_in, + &node3d->u_in, + &node3d->d_in, + &node3d->l_in + }; + + uint8_t X = node3d->x, Y = node3d->y, Z = node3d->z; + for (size_t i = 0; i < 7; ++i) { + struct reg *r = input[i]; + if (!r->busy) + continue; + + uint8_t x, y, z; + addr_mesh3d(r->pkt.to, &x, &y, &z, NULL); + if (x < X) { + maybe_pick(output, W, r); + continue; + } + + if (x > X) { + maybe_pick(output, E, r); + continue; + } + + if (y < Y) { + maybe_pick(output, S, r); + continue; + } + + if (y > Y) { + maybe_pick(output, N, r); + continue; + } + + if (z < Z) { + maybe_pick(output, D, r); + continue; + } + + if (z > Z) { + maybe_pick(output, U, r); + continue; + } + + maybe_pick(output, L, r); + } + + struct component *target[7] = { + node3d->n, + node3d->s, + node3d->e, + node3d->w, + node3d->u, + node3d->d, + node3d->l + }; + + for (size_t i = 0; i < 7; ++i) { + if (!output[i]) + continue; + + if (!target[i]) { + /* for now, should send packet back with an error or something */ + abort(); + } + + stat ret = SEND(node3d, target[i], output[i]->pkt); + if (ret == EBUSY) + continue; + + assert(ret == OK); + output[i]->busy = false; + } + + return OK; +} + +static stat reg_receive(struct reg *r, struct packet pkt) +{ + if (r->busy) + return EBUSY; + + r->pkt = pkt; + r->busy = true; + return OK; +} + +static stat node3d_receive(struct node3d *node3d, struct component *from, struct packet pkt) +{ + if (from == node3d->l) { + /* add time when packet entered network */ + pkt.timestamp = node3d->timestamp; + return reg_receive(&node3d->l_in, pkt); + } + + if (from == node3d->n) + return reg_receive(&node3d->n_in, pkt); + + if (from == node3d->s) + return reg_receive(&node3d->s_in, pkt); + + if (from == node3d->e) + return reg_receive(&node3d->e_in, pkt); + + if (from == node3d->w) + return reg_receive(&node3d->w_in, pkt); + + if (from == node3d->u) + return reg_receive(&node3d->u_in, pkt); + + if (from == node3d->d) + return reg_receive(&node3d->d_in, pkt); + + abort(); + return OK; +} + +struct component *create_mesh_node3d(uint8_t x, uint8_t y, uint8_t z) +{ + struct node3d *node = calloc(1, sizeof(struct node3d)); + if (!node) + return NULL; + + node->component.receive = (receive_callback)node3d_receive; + node->component.clock = (clock_callback)node3d_clock; + node->x = x; + node->y = y; + node->z = z; + return (struct component *)node; +} + +stat mesh_node3d_connect(struct component *node, + struct component *n, + struct component *s, + struct component *e, + struct component *w, + struct component *u, + struct component *d, + struct component *l) +{ + struct node3d *node3d = (struct node3d *)node; + node3d->n = n; + node3d->s = s; + node3d->e = e; + node3d->w = w; + node3d->u = u; + node3d->d = d; + node3d->l = l; + return OK; +} diff --git a/src/mesh/source.mk b/src/mesh/source.mk new file mode 100644 index 0000000..55a7d03 --- /dev/null +++ b/src/mesh/source.mk @@ -0,0 +1 @@ +SOURCES += src/mesh/node.c src/mesh/node3d.c |
