aboutsummaryrefslogtreecommitdiff
path: root/src/mesh/node1d.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesh/node1d.c')
-rw-r--r--src/mesh/node1d.c232
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;
}