diff options
| author | Kimplul <kimi.h.kuparinen@gmail.com> | 2025-08-09 16:06:43 +0300 |
|---|---|---|
| committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2025-08-09 16:06:43 +0300 |
| commit | 3083284c797fc8fc267144b05c8a58395e4583e3 (patch) | |
| tree | d0413af85d65cf895aa85fdaaf3a9f090f41dac1 /tests/simple_mesh2d | |
| parent | aba90a3a6f6c1caee28aaf3dadebb4daba5b5761 (diff) | |
| download | gran-3083284c797fc8fc267144b05c8a58395e4583e3.tar.gz gran-3083284c797fc8fc267144b05c8a58395e4583e3.zip | |
add 1d mesh node and refactor 2d mesh node
+ Seems to decrease performance a little bit, presumably due to
extra register copy, but simplifies code a lot and opens up more
genericism so I'll consider it an upgrade for now. Copying packets
around is rather slow though, might in the future move to some
kind of pointer based packet handling
Diffstat (limited to 'tests/simple_mesh2d')
| -rw-r--r-- | tests/simple_mesh2d/sim.c | 126 | ||||
| -rw-r--r-- | tests/simple_mesh2d/source.mk | 18 | ||||
| -rw-r--r-- | tests/simple_mesh2d/test.c | 55 |
3 files changed, 199 insertions, 0 deletions
diff --git a/tests/simple_mesh2d/sim.c b/tests/simple_mesh2d/sim.c new file mode 100644 index 0000000..1a9ba32 --- /dev/null +++ b/tests/simple_mesh2d/sim.c @@ -0,0 +1,126 @@ +#include <assert.h> + +#include <gran/root.h> +#include <gran/mem/simple_mem.h> +#include <gran/bus/simple_bus.h> +#include <gran/uart/simple_uart.h> +#include <gran/mesh/node2d.h> +#include <gran/cpu/riscv/simple_riscv64.h> + +#include "../build/tests/simple_mesh2d/test.inc" + +static size_t idx_1d(int x, int y, uint8_t xw, uint8_t yw) +{ + (void)xw; /* maybe unused */ + assert(0 <= x && x < xw); + assert(0 <= y && y < yw); + return (x * yw) + y; +} + +static struct component *mesh_at(struct component **mesh, + int x, int y, + uint8_t xw, uint8_t yw) +{ + if (x < 0) + return NULL; + + if (y < 0) + return NULL; + + if (x >= xw) + return NULL; + + if (y >= yw) + return NULL; + + return mesh[idx_1d(x, y, xw, yw)]; +} + +static void connect_mesh(struct component **mesh, struct component *c, + uint16_t x, uint16_t y, + uint16_t xw, uint16_t yw) +{ + mesh_node2d_connect_north(mesh_at(mesh, x, y, xw, yw), mesh_at(mesh, x , y+1, xw, yw)); + mesh_node2d_connect_south(mesh_at(mesh, x, y, xw, yw), mesh_at(mesh, x , y-1, xw, yw)); + mesh_node2d_connect_east(mesh_at(mesh, x, y, xw, yw), mesh_at(mesh, x+1, y , xw, yw)); + mesh_node2d_connect_west(mesh_at(mesh, x, y, xw, yw), mesh_at(mesh, x-1, y , xw, yw)); + mesh_node2d_connect(mesh_at(mesh, x, y, xw, yw), c, 0); +} + +static stat build_mesh(struct clock_domain *clk, uint16_t x, uint16_t y) +{ + struct component **mesh = calloc(x * y, sizeof(struct component *)); + assert(mesh); + + struct component **pes = calloc(x * y, sizeof(struct component *)); + assert(pes); + + for (size_t i = 0; i < x; ++i) + for (size_t j = 0; j < y; ++j) { + struct component *node = create_mesh_node2d(i, j, 1); + clock_domain_add(clk, node); + mesh[idx_1d(i, j, x, y)] = node; + + if (i == 0 && j == 0) + continue; + + if (i == 0 && j == 1) + continue; + + struct component *imem = create_simple_mem(4096); + init_simple_mem(imem, 0, + build_tests_simple_mesh2d_test_bin_len, + build_tests_simple_mesh2d_test_bin); + + uint64_t rcv = mesh2d_addr(i, j, 0, 0); + struct component *rv64 = create_simple_riscv64(rcv, 0, imem, node); + simple_riscv64_set_reg(rv64, 10, i); /* a0 */ + simple_riscv64_set_reg(rv64, 11, j); /* a1 */ + simple_riscv64_set_reg(rv64, 12, x); /* a3 */ + simple_riscv64_set_reg(rv64, 13, y); /* a4 */ + + clock_domain_add(clk, rv64); + clock_domain_add(clk, imem); + + pes[idx_1d(i, j, x, y)] = rv64; + } + + struct component *uart = create_simple_uart(); + clock_domain_add(clk, uart); + connect_mesh(mesh, uart, 0, 0, x, y); + + struct component *dmem = create_simple_mem(4096); + clock_domain_add(clk, dmem); + connect_mesh(mesh, dmem, 0, 1, x, y); + + for (int i = 0; i < x; ++i) + for (int j = 0; j < y; ++j) { + if (i == 0 && j == 0) + continue; + + if (i == 0 && j == 1) + continue; + + connect_mesh(mesh, pes[idx_1d(i, j, x, y)], i, j, x, y); + } + + free(mesh); + free(pes); + return OK; +} + +int main() +{ + struct clock_domain *clk = create_clock_domain(NS(1)); + + stat r = build_mesh(clk, 8, 8); + assert(r == OK); + + struct gran_root *root = create_root(); + root_add_clock(root, clk); + + r = root_run(root); + assert(r == OK); + + destroy_root(root); +} diff --git a/tests/simple_mesh2d/source.mk b/tests/simple_mesh2d/source.mk new file mode 100644 index 0000000..525efa3 --- /dev/null +++ b/tests/simple_mesh2d/source.mk @@ -0,0 +1,18 @@ +MESH2D_TEST_OBJ != ./scripts/gen-deps --sources "tests/simple_mesh2d/sim.c" +TEST_PROGS += build/tests/simple_mesh2d/sim + +build/tests/simple_mesh2d/test.inc: tests/simple_mesh2d/test.c + riscv64-unknown-elf-gcc -O2 -Wall -Wextra -ffreestanding -nostdlib \ + -march=rv64i -mabi=lp64 \ + -o build/tests/simple_mesh2d/test \ + tests/simple_mesh2d/test.c + riscv64-unknown-elf-objcopy -Obinary \ + build/tests/simple_mesh2d/test \ + build/tests/simple_mesh2d/test.bin + xxd -i build/tests/simple_mesh2d/test.bin \ + > build/tests/simple_mesh2d/test.inc + +build/tests/simple_mesh2d/sim.o: build/tests/simple_mesh2d/test.inc + +build/tests/simple_mesh2d/sim: $(MESH2D_TEST_OBJ) $(OBJS) + $(COMPILE) $(MESH2D_TEST_OBJ) $(OBJS) -o $@ diff --git a/tests/simple_mesh2d/test.c b/tests/simple_mesh2d/test.c new file mode 100644 index 0000000..d607a59 --- /dev/null +++ b/tests/simple_mesh2d/test.c @@ -0,0 +1,55 @@ +__attribute__((always_inline)) +static inline void print_int8(volatile char *uart, unsigned x) +{ + *uart = ((x >> 4) & 0xf) + '0'; + *uart = ((x >> 0) & 0xf) + '0'; +} + +__attribute__((always_inline)) +static inline void print_addr(volatile char *uart, unsigned x, unsigned y) +{ + *uart = '('; + print_int8(uart, x); + *uart = ','; + *uart = ' '; + print_int8(uart, y); + *uart = ')'; + *uart = '\n'; +} + +__attribute__((always_inline)) +static inline unsigned wrap(unsigned x, unsigned X) +{ + return x + 1 >= X ? 0 : x + 1; +} + +__attribute__((always_inline)) +static inline unsigned next_idx(unsigned x, unsigned y, unsigned X, unsigned Y) +{ + unsigned yi = wrap(y, Y); + unsigned xi = yi < y ? wrap(x, X) : x; + + return (xi << 16) | yi; +} + +void _start(unsigned x, unsigned y, unsigned X, unsigned Y) +{ + volatile char *uart = (char *)4096; + volatile unsigned *control = (unsigned *)(1ULL << 56); + + if (x == 0 && y == 2) { + goto do_work; + } else { + while (*control != ((x << 16) | y)) {} + } + +do_work: + print_addr(uart, x, y); + *control = next_idx(x, y, X, Y); + + if (x == X - 1 && y == Y - 1) + asm("ebreak"); + + /* otherwise just loop */ + while (1) {} +} |
