diff options
Diffstat (limited to 'src/mesh/node1d.c')
| -rw-r--r-- | src/mesh/node1d.c | 232 |
1 files changed, 58 insertions, 174 deletions
diff --git a/src/mesh/node1d.c b/src/mesh/node1d.c index 23ba2ca..5a3cb06 100644 --- a/src/mesh/node1d.c +++ b/src/mesh/node1d.c @@ -1,18 +1,13 @@ #include <gran/mesh/node1d.h> -#define left_port(n) (n)->ports[(n)->elems + 0] -#define right_port(n) (n)->ports[(n)->elems + 1] +#define north_port(n) (n)->ports[(n)->elems + 0] +#define south_port(n) (n)->ports[(n)->elems + 1] -#define left_in(n) (n)->in[(n)->elems + 0] -#define right_in(n) (n)->in[(n)->elems + 1] +#define north_in(n) (n)->in[(n)->elems + 0] +#define south_in(n) (n)->in[(n)->elems + 1] -#define left_out(n) (n)->out[(n)->elems + 0] -#define right_out(n) (n)->out[(n)->elems + 1] - -struct reg { - struct packet pkt; - bool busy; -}; +#define north_out(n) (n)->out[(n)->elems + 0] +#define south_out(n) (n)->out[(n)->elems + 1] struct node1d { struct component component; @@ -31,31 +26,11 @@ static void node1d_destroy(struct node1d *n) free(n->in); free(n->out); free(n->ports); + free(n); } -static stat reg_busy(struct reg *r, struct packet pkt) -{ - bool busy = r->busy; - if (!busy) { - r->pkt = pkt; - r->busy = true; - } - - return busy ? EBUSY : OK; -} - -static void copy_reg(struct reg *r, struct reg *s) -{ - assert(s->busy); - if (r->busy) - return; - - r->pkt = s->pkt; - r->busy = true; - s->busy = false; -} - -static stat node1d_receive(struct node1d *n, struct component *from, struct packet pkt) +static stat node1d_receive(struct node1d *n, struct component *from, + struct packet pkt) { for (int i = 0; i < n->elems + 2; ++i) { /* add timestamp to packets that originate with us */ @@ -63,7 +38,7 @@ static stat node1d_receive(struct node1d *n, struct component *from, struct pack pkt.timestamp = n->timestamp; if (from == n->ports[i]) - return reg_busy(&n->in[i], pkt); + return place_reg(&n->in[i], pkt); } /* shouldn't be possible */ @@ -85,139 +60,37 @@ static void clock_outputs(struct node1d *n) } } -static void propagate_left(struct node1d *n, struct reg *a, struct reg *b) -{ - struct reg *sel_a = NULL, *sel_b = NULL; - if (a && a->busy) { - uint16_t cluster = 0; - addr_mesh1d(a->pkt.to, &cluster, NULL, NULL); - - if (cluster > n->cluster) - sel_a = a; - } - - if (b && b->busy) { - uint16_t cluster = 0; - addr_mesh1d(b->pkt.to, &cluster, NULL, NULL); - - if (cluster > n->cluster) - sel_b = b; - } - - if (!sel_a && !sel_b) - return; - - if (sel_a && !sel_b) { - copy_reg(&left_out(n), sel_a); - return; - } - - if (!sel_a && sel_b) { - copy_reg(&left_out(n), sel_b); - return; - } +struct sel_helper { + uint16_t cluster, elem; +}; - /* both available, select older */ - if (sel_a->pkt.timestamp < sel_b->pkt.timestamp) - copy_reg(&left_out(n), sel_a); - else - copy_reg(&left_out(n), sel_b); +static bool north_sel(struct reg *r, void *data) +{ + uint16_t cluster = 0; + struct sel_helper *helper = data; + addr_mesh1d(r->pkt.to, &cluster, NULL, NULL); + return cluster > helper->cluster; } -static void propagate_right(struct node1d *n, struct reg *a, struct reg *b) +static bool south_sel(struct reg *r, void *data) { - struct reg *sel_a = NULL, *sel_b = NULL; - if (a && a->busy) { - uint16_t cluster = 0; - addr_mesh1d(a->pkt.to, &cluster, NULL, NULL); - - if (cluster < n->cluster) - sel_a = a; - } - - if (b && b->busy) { - uint16_t cluster = 0; - addr_mesh1d(b->pkt.to, &cluster, NULL, NULL); - - if (cluster < n->cluster) - sel_b = b; - } - - if (!sel_a && !sel_b) - return; - - if (sel_a && !sel_b) { - copy_reg(&right_out(n), sel_a); - return; - } - - if (!sel_a && sel_b) { - copy_reg(&right_out(n), sel_b); - return; - } - - /* both available, select older */ - if (sel_a->pkt.timestamp < sel_b->pkt.timestamp) - copy_reg(&right_out(n), sel_a); - else - copy_reg(&right_out(n), sel_b); + uint16_t cluster = 0; + struct sel_helper *helper = data; + addr_mesh1d(r->pkt.to, &cluster, NULL, NULL); + return cluster < helper->cluster; } -static void propagate(struct node1d *n, int elem, struct reg *a, struct reg *b, struct reg *c) +static bool elem_sel(struct reg *r, void *data) { - - struct reg *sel_a = NULL, *sel_b = NULL, *sel_c = NULL; - if (a && a->busy) { - uint16_t cluster = 0, element = 0; - addr_mesh1d(a->pkt.to, &cluster, &element, NULL); - - if (cluster == n->cluster && element == elem) - sel_a = a; - } - - if (b && b->busy) { - uint16_t cluster = 0, element = 0; - addr_mesh1d(b->pkt.to, &cluster, &element, NULL); - - if (cluster == n->cluster && element == elem) - sel_b = b; - } - - if (c && c->busy) { - uint16_t cluster = 0, element = 0; - addr_mesh1d(c->pkt.to, &cluster, &element, NULL); - - if (cluster == n->cluster && element == elem) - sel_c = c; - } - - struct reg *sel_0 = NULL, *sel_1 = NULL; - if (sel_a && sel_b) - sel_0 = sel_a->pkt.timestamp < sel_b->pkt.timestamp ? sel_a : sel_b; - else - sel_0 = sel_a ? sel_a : sel_b; - - if (sel_b && sel_c) - sel_1 = sel_b->pkt.timestamp < sel_c->pkt.timestamp ? sel_b : sel_c; - else - sel_1 = sel_b ? sel_b : sel_c; - - struct reg *sel = NULL; - if (sel_0 && sel_1) - sel = sel_0->pkt.timestamp < sel_1->pkt.timestamp ? sel_0 : sel_1; - else - sel = sel_0 ? sel_0 : sel_1; - - if (!sel) - return; - - copy_reg(&n->out[elem], sel); + uint16_t cluster = 0, elem = 0; + struct sel_helper *helper = data; + addr_mesh1d(r->pkt.to, &cluster, &elem, NULL); + return cluster == helper->cluster && elem == helper->elem; } static stat node1d_clock(struct node1d *n) { n->timestamp++; - clock_outputs(n); /* select oldest packet to process */ @@ -230,15 +103,28 @@ static stat node1d_clock(struct node1d *n) r = &n->in[i]; } - propagate_left(n, r, &right_in(n)); - propagate_right(n, r, &left_in(n)); - for (int i = 0; i < n->elems; ++i) - propagate(n, i, r, &right_in(n), &left_in(n)); + struct sel_helper helper = { + .cluster = n->cluster, + .elem = 0, + }; + + struct reg *north[] = {r, &south_in(n)}; + struct reg *south[] = {r, &north_in(n)}; + + propagate(&north_out(n), 2, north, north_sel, &helper); + propagate(&south_out(n), 2, south, south_sel, &helper); + + struct reg *all[] = {r, &north_in(n), &south_in(n)}; + for (int i = 0; i < n->elems; ++i) { + helper.elem = i; + propagate(&n->out[i], 3, all, elem_sel, &helper); + } return OK; } -stat mesh_node1d_connect(struct component *c, struct component *e, uint16_t elem) +stat mesh_node1d_connect(struct component *c, struct component *e, + uint16_t elem) { struct node1d *n = (struct node1d *)c; if (elem >= n->elems) @@ -251,23 +137,23 @@ stat mesh_node1d_connect(struct component *c, struct component *e, uint16_t elem return OK; } -stat mesh_node1d_connect_left(struct component *c, struct component *e) +stat mesh_node1d_connect_north(struct component *c, struct component *e) { struct node1d *n = (struct node1d *)c; - if (left_port(n)) + if (north_port(n)) return EEXISTS; - left_port(n) = e; + north_port(n) = e; return OK; } -stat mesh_node1d_connect_right(struct component *c, struct component *e) +stat mesh_node1d_connect_south(struct component *c, struct component *e) { struct node1d *n = (struct node1d *)c; - if (right_port(n)) + if (south_port(n)) return EEXISTS; - right_port(n) = e; + south_port(n) = e; return OK; } @@ -279,22 +165,20 @@ struct component *create_mesh_node1d(uint16_t cluster, uint16_t elems) n->in = (struct reg *)calloc(elems + 2, sizeof(struct reg)); if (!n->in) { - free(n); + node1d_destroy(n); return NULL; } n->out = (struct reg *)calloc(elems + 2, sizeof(struct reg)); if (!n->out) { - free(n->in); - free(n); + node1d_destroy(n); return NULL; } - n->ports = (struct component **)calloc(elems + 2, sizeof(struct component *)); + n->ports = (struct component **)calloc(elems + 2, + sizeof(struct component *)); if (!n->ports) { - free(n->out); - free(n->in); - free(n); + node1d_destroy(n); return NULL; } |
