From 0464b7765aa4d1fc2178e443a3b37d19cfe541a0 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Sun, 2 Mar 2025 21:45:51 +0200 Subject: add ideal allocation tracker + Kind of like CHERI, but uses out-of-line pointer information. The idea is that a core that is compatible with ALLOC_IF queries the allocation tracker if an address is legal and gets a response. This ideal tracker effectively has infinite memory and doesn't talk to any other components, but a real implementation might want to limit the allocations per process or chat with some reserved memory region somewhere else in the system to maintain a binary tree or something. --- tests/simple_ideal_alloc/sim.c | 26 ++++++++ tests/simple_ideal_alloc/source.mk | 7 +++ tests/simple_ideal_alloc/testbench.c | 119 +++++++++++++++++++++++++++++++++++ tests/simple_ideal_alloc/testbench.h | 9 +++ 4 files changed, 161 insertions(+) create mode 100644 tests/simple_ideal_alloc/sim.c create mode 100644 tests/simple_ideal_alloc/source.mk create mode 100644 tests/simple_ideal_alloc/testbench.c create mode 100644 tests/simple_ideal_alloc/testbench.h (limited to 'tests/simple_ideal_alloc') diff --git a/tests/simple_ideal_alloc/sim.c b/tests/simple_ideal_alloc/sim.c new file mode 100644 index 0000000..6aeb5b6 --- /dev/null +++ b/tests/simple_ideal_alloc/sim.c @@ -0,0 +1,26 @@ +#include + +#include +#include + +#include "testbench.h" + +int main() +{ + struct component *traffic_gen = create_testbench(); + struct component *ideal_alloc = create_ideal_alloc(1); + + ideal_alloc_connect(ideal_alloc, traffic_gen); + testbench_connect(traffic_gen, ideal_alloc); + + struct clock_domain *clk = create_clock_domain(NS(1)); + clock_domain_add(clk, traffic_gen); + clock_domain_add(clk, ideal_alloc); + + struct gran_root *root = create_root(); + root_add_clock(root, clk); + + assert(root_run(root) == OK); + + destroy_root(root); +} diff --git a/tests/simple_ideal_alloc/source.mk b/tests/simple_ideal_alloc/source.mk new file mode 100644 index 0000000..f797cdd --- /dev/null +++ b/tests/simple_ideal_alloc/source.mk @@ -0,0 +1,7 @@ +ALLOC_TB_OBJ != ./scripts/gen-deps --sources "tests/simple_ideal_alloc/testbench.c" +IDEAL_ALLOC_TEST_OBJ != ./scripts/gen-deps --sources "tests/simple_ideal_alloc/sim.c" + +TEST_PROGS += build/tests/simple_ideal_alloc/sim + +build/tests/simple_ideal_alloc/sim: $(ALLOC_TB_OBJ) $(IDEAL_ALLOC_TEST_OBJ) $(OBJS) + $(COMPILE) $(ALLOC_TB_OBJ) $(IDEAL_ALLOC_TEST_OBJ) $(TEST_OBJS) $(OBJS) -o $@ diff --git a/tests/simple_ideal_alloc/testbench.c b/tests/simple_ideal_alloc/testbench.c new file mode 100644 index 0000000..703c2a8 --- /dev/null +++ b/tests/simple_ideal_alloc/testbench.c @@ -0,0 +1,119 @@ +#include +#include "testbench.h" + +struct reg { + struct packet pkt; + bool busy; +}; + +struct tb { + struct component component; + struct component *dut; + struct reg in; + + enum { + ADD_REGION, + QUERY_EXISTING, + REMOVE_REGION, + QUERY_NONEXISTING, + FINAL + } state; +}; + +static stat tb_receive(struct tb *tb, struct component *from, struct packet pkt) +{ + assert(tb->dut == from); + tb->in.pkt = pkt; + tb->in.busy = true; + return OK; +} + +static stat tb_clock(struct tb *tb) +{ + assert(tb->dut); + + switch (tb->state) { + case ADD_REGION: { + struct alloc_if_new n = {.space = 0, .start = 0, .end = 10}; + struct packet pkt = create_packet(0, ALLOC_IF_NEW, sizeof(n), &n, PACKET_WRITE); + assert(SEND(tb, tb->dut, pkt) == OK); + tb->state = QUERY_EXISTING; + break; + } + + case QUERY_EXISTING: { + if (!tb->in.busy) + break; + + struct alloc_if_r *r = (struct alloc_if_r *)&tb->in.pkt.data; + assert(r->r == ALLOC_IF_OK); + + struct alloc_if_q q = {.space = 0, .addr = 5}; + struct packet pkt = create_packet(0, ALLOC_IF_Q, sizeof(q), &q, PACKET_WRITE); + assert(SEND(tb, tb->dut, pkt) == OK); + tb->state = REMOVE_REGION; + tb->in.busy = false; + break; + } + + case REMOVE_REGION: { + if (!tb->in.busy) + break; + + struct alloc_if_r *r = (struct alloc_if_r *)&tb->in.pkt.data; + assert(r->r == ALLOC_IF_OK); + assert(r->start == 0); + assert(r->end == 10); + + struct alloc_if_rm rm = {.space = 0, .start = 0, .end = 10}; + struct packet pkt = create_packet(0, ALLOC_IF_RM, sizeof(rm), &rm, PACKET_WRITE); + assert(SEND(tb, tb->dut, pkt) == OK); + tb->state = QUERY_NONEXISTING; + tb->in.busy = false; + break; + } + + case QUERY_NONEXISTING: { + if (!tb->in.busy) + break; + + struct alloc_if_r *r = (struct alloc_if_r *)&tb->in.pkt.data; + assert(r->r == ALLOC_IF_OK); + + struct alloc_if_q q = {.space = 0, .addr = 5}; + struct packet pkt = create_packet(0, ALLOC_IF_Q, sizeof(q), &q, PACKET_WRITE); + assert(SEND(tb, tb->dut, pkt) == OK); + tb->state = FINAL; + tb->in.busy = false; + break; + } + + case FINAL: { + if (!tb->in.busy) + break; + + struct alloc_if_r *r = (struct alloc_if_r *)&tb->in.pkt.data; + assert(r->r != ALLOC_IF_OK); + return DONE; + } + + default: abort(); + } + + return OK; +} + +struct component *create_testbench() +{ + struct tb *tb = calloc(1, sizeof(struct tb)); + tb->component.clock = (clock_callback)tb_clock; + tb->component.receive = (receive_callback)tb_receive; + return (struct component *)tb; +} + +stat testbench_connect(struct component *tb, struct component *dut) +{ + struct tb *t = (struct tb *)tb; + t->dut = dut; + return OK; +} diff --git a/tests/simple_ideal_alloc/testbench.h b/tests/simple_ideal_alloc/testbench.h new file mode 100644 index 0000000..6f72060 --- /dev/null +++ b/tests/simple_ideal_alloc/testbench.h @@ -0,0 +1,9 @@ +#ifndef GRAN_IDEAL_ALLOC_TESTBENCH_H +#define GRAN_IDEAL_ALLOC_TESTBENCH_H + +#include + +struct component *create_testbench(); +stat testbench_connect(struct component *tb, struct component *dut); + +#endif /* GRAN_IDEAL_ALLOC_TESTBENCH_H */ -- cgit v1.3