diff options
| author | Kimplul <kimi.h.kuparinen@gmail.com> | 2024-09-24 16:51:51 +0300 |
|---|---|---|
| committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2024-09-24 18:47:13 +0300 |
| commit | fecb86f6093c1e8aed6ab05c29c5af9d0cb93157 (patch) | |
| tree | 10171c839d77167fc98fbae0b315d2c87aa13fa5 /src/components | |
| parent | b1d67364b4b4832b8efed112f7b0ead1a0b3cd3b (diff) | |
| download | gran-fecb86f6093c1e8aed6ab05c29c5af9d0cb93157.tar.gz gran-fecb86f6093c1e8aed6ab05c29c5af9d0cb93157.zip | |
initial work towards message passing interface
+ As they are currently implemented, grid *may* get stuck if two nodes
try to send to eachother at the same time, I should probably add in
some kind of input buffer as well
Diffstat (limited to 'src/components')
| -rw-r--r-- | src/components/bus/simple_bus.c | 182 | ||||
| -rw-r--r-- | src/components/cpu/riscv/simple_riscv64.c | 207 | ||||
| -rw-r--r-- | src/components/grid/node.c | 91 | ||||
| -rw-r--r-- | src/components/grid/router.c | 72 | ||||
| -rw-r--r-- | src/components/mem/simple_mem.c | 53 | ||||
| -rw-r--r-- | src/components/uart/simple_uart.c | 42 |
6 files changed, 351 insertions, 296 deletions
diff --git a/src/components/bus/simple_bus.c b/src/components/bus/simple_bus.c index 218e930..1932419 100644 --- a/src/components/bus/simple_bus.c +++ b/src/components/bus/simple_bus.c @@ -1,154 +1,76 @@ /* SPDX-License-Identifier: copyleft-next-0.3.1 */ /* Copyright 2023 Kim Kuparinen < kimi.h.kuparinen@gmail.com > */ - -#include <threads.h> -#include <inttypes.h> -#include <stdlib.h> - -#include <gran/common.h> -#include <gran/component.h> +#include <stdbool.h> #include <gran/bus/simple_bus.h> +#include <gran/vec.h> -struct mem_region { - uintptr_t addr; - size_t size; +struct bus_region { + uint64_t addr; + uint64_t size; struct component *component; - struct mem_region *next; }; struct simple_bus { struct component component; - mtx_t lock; + struct vec regions; - struct mem_region *mem_regions; + struct component *send; + struct packet pkt; + bool busy; }; -static struct mem_region *find_mem_region(struct simple_bus *bus, - uintptr_t addr) +static struct bus_region *find_bus_region(struct simple_bus *bus, uint64_t addr) { - if (!bus->mem_regions) - return NULL; - - struct mem_region *cur = bus->mem_regions; - while (cur) { - /* address is within memory region */ - if (addr >= cur->addr && addr < cur->addr + cur->size) - return cur; - - cur = cur->next; + foreach_vec(i, bus->regions) { + struct bus_region *r = vec_at(&bus->regions, i); + if (addr >= r->addr && addr < (r->addr + r->size)) + return r; } return NULL; } -static stat add_mem_region(struct simple_bus *bus, struct mem_region *new) +static stat simple_bus_clock(struct simple_bus *bus) { - if (!bus->mem_regions) { - bus->mem_regions = new; - return OK; - } + if (bus->busy) { + stat r = SEND(bus, bus->send, bus->pkt); + if (r == EBUSY) + return OK; - struct mem_region *found = NULL; - if ((found = find_mem_region(bus, new->addr))) { - error("%s overlaps with %s at %" PRIuPTR, - new->component->name, - found->component->name, - new->addr - ); - return EEXISTS; + bus->busy = false; + return r; } - new->next = bus->mem_regions; - bus->mem_regions = new; return OK; } -static stat simple_bus_write(struct simple_bus *bus, struct packet *pkt) -{ - /* only one device can drive the bus at one time */ - if (mtx_trylock(&bus->lock) != thrd_success) - return EBUSY; - - struct mem_region *mem_region = find_mem_region(bus, packet_addr(pkt)); - if (!mem_region) { - warn("nothing to write on bus %s at %" PRIuPTR, - bus->component.name, packet_addr(pkt)); - return EBUS; - } - - stat ret = write(mem_region->component, pkt); - - mtx_unlock(&bus->lock); - return ret; -} - -static stat simple_bus_read(struct simple_bus *bus, struct packet *pkt) +static stat simple_bus_receive(struct simple_bus *bus, struct component *from, struct packet pkt) { - /* only one device can drive the bus at one time */ - if (mtx_trylock(&bus->lock) != thrd_success) + if (bus->busy) return EBUSY; - struct mem_region *mem_region = find_mem_region(bus, packet_addr(pkt)); - if (!mem_region) { - warn("nothing to read on bus %s at %" PRIuPTR, - bus->component.name, packet_addr(pkt)); - return EBUS; - } + bus->busy = true; - stat ret = read(mem_region->component, pkt); + struct bus_region *region = find_bus_region(bus, pkt.to); + if (!region) { + warn("illegal address on bus %s at %" PRIuPTR, + bus->component.name, pkt.to); - mtx_unlock(&bus->lock); - return ret; -} - -static stat simple_bus_swap(struct simple_bus *bus, struct packet *pkt) -{ - if (mtx_trylock(&bus->lock) != thrd_success) - return EBUSY; - - struct mem_region *mem_region = find_mem_region(bus, packet_addr(pkt)); - if (!mem_region) { - warn("nothing to swap on bus %s at %" PRIuPTR, - bus->component.name, packet_addr(pkt)); - return EBUS; - } - - stat ret = swap(mem_region->component, pkt); - - mtx_unlock(&bus->lock); - return ret; -} - -static stat simple_bus_snoop(struct simple_bus *bus, struct snoop *snoop) -{ - struct mem_region *cur = bus->mem_regions; - while (cur) { - if (cur->component->snoop) { - stat ret = cur->component->snoop(cur->component, snoop); - if (ret) - return ret; - - if (snoop_state(snoop) == SNOOP_ANSWERED) - return OK; - } - - cur = cur->next; + bus->send = from; + bus->pkt = response(pkt); + set_flags(&bus->pkt, PACKET_ERROR); + return OK; } + bus->send = region->component; + bus->pkt = pkt; return OK; } static void simple_bus_destroy(struct simple_bus *bus) { - struct mem_region *cur = bus->mem_regions, *next = NULL; - if (cur) - do { - next = cur->next; - destroy(cur->component); - free(cur); - } while ((cur = next)); - + vec_destroy(&bus->regions); free(bus); } @@ -158,34 +80,38 @@ struct component *create_simple_bus() if (!bus) return NULL; - bus->component.write = (write_callback)simple_bus_write; - bus->component.read = (read_callback)simple_bus_read; - bus->component.swap = (swap_callback)simple_bus_swap; - bus->component.snoop = (snoop_callback)simple_bus_snoop; - // actually, still not sure about what API I want to use for controls - // bus->component.ctrl = (ctrl_callback)simple_bus_ctrl; + bus->component.receive = (receive_callback)simple_bus_receive; + bus->component.clock = (clock_callback)simple_bus_clock; bus->component.destroy = (destroy_callback)simple_bus_destroy; + bus->regions = vec_create(sizeof(struct bus_region)); - mtx_init(&bus->lock, mtx_plain); return (struct component *)bus; } stat simple_bus_add(struct component *bus, struct component *component, uint64_t addr, uint64_t size) { - struct mem_region *new = calloc(1, sizeof(struct mem_region)); - if (!new) - return ENOMEM; + struct simple_bus *b = (struct simple_bus *)bus; + struct bus_region *found = find_bus_region(b, addr); + if (!found) found = find_bus_region(b, addr + size); - new->addr = addr; - new->size = size; - new->component = component; + if (found) { + error("%s overlaps with %s at %" PRIuPTR, + found->component->name, + component->name, + found->addr + ); - if (add_mem_region((struct simple_bus *)bus, new)) { - free(new); return EEXISTS; } + struct bus_region new = (struct bus_region){ + .component = component, + .addr = addr, + .size = size + }; + + vect_append(struct bus_region, b->regions, &new); return OK; } diff --git a/src/components/cpu/riscv/simple_riscv64.c b/src/components/cpu/riscv/simple_riscv64.c index be96e60..987838e 100644 --- a/src/components/cpu/riscv/simple_riscv64.c +++ b/src/components/cpu/riscv/simple_riscv64.c @@ -9,8 +9,13 @@ #include <gran/cpu/riscv/simple_riscv64.h> -struct simple_rv64_ldst { - struct packet *pkt; +enum ldst_state { + LDST_IDLE, LDST_BLOCKED, LDST_SENT, LDST_DONE +}; + +struct ldst { + struct packet pkt; + enum ldst_state state; uint32_t reg; bool u; }; @@ -21,8 +26,10 @@ struct simple_riscv64 { struct component *imem; struct component *dmem; - struct simple_rv64_ldst dls; - struct simple_rv64_ldst ils; + struct ldst dls; + struct ldst ils; + + uint64_t rcv; /* have to be careful with x0 */ uint64_t regs[32]; @@ -396,25 +403,31 @@ static stat load(struct simple_riscv64 *cpu, union rv_insn insn) /* LH/LHU */ case 0b101: u = true; /* fallthrough */ case 0b001: size = 2; break; - /* LW */ + /* LW/LWU */ + case 0b110: u = true; /* fallthrough */ case 0b010: size = 4; break; + /* LD */ case 0b011: size = 8; break; default: error("unknown LOAD width %x", insn.btype.funct3); return ENOSUCH; } - struct packet *pkt = create_packet(PACKET_READ, addr, size); - if (!pkt) - return EMEM; + struct packet pkt = create_packet(cpu->rcv, + addr, + size, + NULL, + PACKET_READ); - cpu->dls = (struct simple_rv64_ldst){pkt, insn.itype.rd, u}; - stat ret = read(cpu->dmem, pkt); - if (ret) - return ret; + cpu->dls = (struct ldst){pkt, LDST_SENT, insn.itype.rd, u}; + stat ret = SEND(cpu, cpu->dmem, pkt); + if (ret == EBUSY) { + cpu->dls.state = LDST_BLOCKED; + ret = OK; + } cpu->pc += 4; - return OK; + return ret; } #define STYPE_IMM(insn) \ @@ -428,66 +441,58 @@ static stat store(struct simple_riscv64 *cpu, union rv_insn insn) int64_t addr = base + imm; uint64_t src = get_reg(cpu, insn.stype.rs2); + uint64_t size = 0; switch (insn.stype.funct3) { /* SB */ - case 0b000: { - cpu->dls.pkt = create_packet(PACKET_WRITE, addr, 1); - *(uint8_t *)packet_data(cpu->dls.pkt) = src; - break; - } + case 0b000: size = 1; break; /* SH */ - case 0b001: { - cpu->dls.pkt = create_packet(PACKET_WRITE, addr, 2); - *(uint16_t *)packet_data(cpu->dls.pkt) = src; - break; - } + case 0b001: size = 2; break; /* SW */ - case 0b010: { - cpu->dls.pkt = create_packet(PACKET_WRITE, addr, 4); - *(uint32_t *)packet_data(cpu->dls.pkt) = src; - break; - } + case 0b010: size = 4; break; /* SD */ - case 0b011: { - cpu->dls.pkt = create_packet(PACKET_WRITE, addr, 8); - *(uint64_t *)packet_data(cpu->dls.pkt) = src; - break; - } + case 0b011: size = 8; break; default: error("unknown width of STORE %x", insn.stype.funct3); return ENOSUCH; } + struct packet pkt = create_packet(cpu->rcv, addr, size, &src, PACKET_WRITE); + cpu->dls = (struct ldst){pkt, LDST_SENT, 0, false}; + stat ret = SEND(cpu, cpu->dmem, pkt); + if (ret == EBUSY) { + cpu->dls.state = LDST_BLOCKED; + ret = OK; + } + cpu->pc += 4; - return write(cpu->dmem, cpu->dls.pkt); + return ret; } static void finalize_ld(struct simple_riscv64 *cpu) { - struct simple_rv64_ldst ld = cpu->dls; + struct ldst ld = cpu->dls; uint64_t val = 0; - void *data = packet_data(ld.pkt); - switch (packet_size(ld.pkt)) { + switch (packet_convsize(&ld.pkt)) { case 1: - if (ld.u) val = *(uint8_t *)data; - else val = *(int8_t *)data; + if (ld.u) val = packet_convu8(&ld.pkt); + else val = packet_convi8(&ld.pkt); break; - case 2: if (ld.u) val = *(uint16_t *)data; - else val = *(int16_t *)data; + case 2: if (ld.u) val = packet_convu16(&ld.pkt); + else val = packet_convi16(&ld.pkt); break; - case 4: if (ld.u) val = *(uint32_t *)data; - else val = *(int32_t *)data; + case 4: if (ld.u) val = packet_convi32(&ld.pkt); + else val = packet_convu32(&ld.pkt); break; - case 8: val = *(uint64_t *)data; + case 8: val = packet_convu64(&ld.pkt); break; default: - error("unknown load size %zu", packet_size(ld.pkt)); + error("unknown load size %zu", packet_convsize(&ld.pkt)); } set_reg(cpu, ld.reg, val); @@ -501,58 +506,97 @@ static void finalize_st(struct simple_riscv64 *cpu) static void finalize_dls(struct simple_riscv64 *cpu) { - struct packet *pkt = cpu->dls.pkt; + cpu->dls.state = LDST_IDLE; + struct packet pkt = cpu->dls.pkt; - if (packet_type(pkt) == PACKET_READ) + if (is_set(&pkt, PACKET_READ)) finalize_ld(cpu); - else if (packet_type(pkt) == PACKET_WRITE) + else if (is_set(&pkt, PACKET_WRITE)) finalize_st(cpu); else error("unsupported packet type for simple_riscv64"); - - destroy_packet(pkt); - cpu->dls.pkt = NULL; } static uint32_t finalize_ils(struct simple_riscv64 *cpu) { - uint32_t insn = *(uint32_t *)packet_data(cpu->ils.pkt); - destroy_packet(cpu->ils.pkt); - cpu->ils.pkt = NULL; - return insn; + cpu->ils.state = LDST_IDLE; + return packet_convu32(&cpu->ils.pkt); +} + +static stat simple_riscv64_receive(struct simple_riscv64 *cpu, struct component *from, struct packet pkt) +{ + (void)from; + + if (pkt.to == cpu->rcv) { + cpu->dls.pkt = pkt; + cpu->dls.state = LDST_DONE; + return OK; + } + else if (pkt.to == cpu->rcv + 64) { + cpu->ils.pkt = pkt; + cpu->ils.state = LDST_DONE; + return OK; + } + else { + error("illegal receive on %s", cpu->component.name); + return EBUS; + } } static stat simple_riscv64_clock(struct simple_riscv64 *cpu) { /* there's an active data transfer we should handle */ - if (cpu->dls.pkt) { - assert(packet_state(cpu->dls.pkt) != PACKET_FAILED); + if (cpu->dls.state != LDST_IDLE) { + assert(!is_set(&cpu->dls.pkt, PACKET_ERROR)); + + if (cpu->dls.state == LDST_BLOCKED) { + stat r = SEND(cpu, cpu->dmem, cpu->dls.pkt); + if (r == EBUSY) + return OK; - if (packet_state(cpu->dls.pkt) == PACKET_DONE) + cpu->dls.state = LDST_SENT; + return OK; + } + + if (cpu->dls.state == LDST_SENT) + return OK; + + if (cpu->dls.state == LDST_DONE) { finalize_dls(cpu); - else /* wait for data */ + cpu->dls.state = LDST_IDLE; + } + else return OK; } - if (!cpu->ils.pkt) { - cpu->ils.pkt = - create_packet(PACKET_READ, cpu->pc, sizeof(uint32_t)); - if (!cpu->ils.pkt) - return EMEM; + if (cpu->ils.state == LDST_BLOCKED) { + stat ret = SEND(cpu, cpu->imem, cpu->ils.pkt); + if (ret == EBUSY) + return OK; - stat ret = read(cpu->imem, cpu->ils.pkt); - if (ret) - return ret; + return OK; } uint32_t insn = 0; - if (cpu->ils.pkt) { - assert(packet_state(cpu->ils.pkt) != PACKET_FAILED); + if (cpu->ils.state == LDST_DONE) { + assert(!is_set(&cpu->dls.pkt, PACKET_ERROR)); - if (packet_state(cpu->ils.pkt) == PACKET_DONE) - insn = finalize_ils(cpu); - else /* wait for instruction */ - return OK; + insn = finalize_ils(cpu); + cpu->ils.state = LDST_IDLE; + } + + if (cpu->ils.state == LDST_IDLE) { + cpu->ils.pkt = create_packet(cpu->rcv + 64, + cpu->pc, + sizeof(uint32_t), + NULL, + PACKET_READ); + cpu->ils.state = LDST_SENT; + stat ret = SEND(cpu, cpu->imem, cpu->ils.pkt); + if (ret == EBUSY) { + cpu->ils.state = LDST_BLOCKED; + return ret; + } } // for now assume little endian emulated and host cpu @@ -586,23 +630,12 @@ static stat simple_riscv64_clock(struct simple_riscv64 *cpu) static void simple_riscv64_destroy(struct simple_riscv64 *cpu) { - /* oh yeah, will have to think about the name stuff, - * i.e. how and where to free it, and where to assign it */ destroy(cpu->imem); - - if (cpu->imem != cpu->dmem) - destroy(cpu->dmem); - - if (cpu->ils.pkt) - destroy_packet(cpu->ils.pkt); - - if (cpu->dls.pkt) - destroy_packet(cpu->dls.pkt); - + destroy(cpu->dmem); free(cpu); } -struct component *create_simple_riscv64(uint32_t start_pc, +struct component *create_simple_riscv64(uint64_t rcv, uint32_t start_pc, struct component *imem, struct component *dmem) { @@ -610,10 +643,12 @@ struct component *create_simple_riscv64(uint32_t start_pc, if (!new) return NULL; + new->component.receive = (receive_callback)simple_riscv64_receive; new->component.clock = (clock_callback)simple_riscv64_clock; new->component.destroy = (destroy_callback)simple_riscv64_destroy; new->pc = start_pc; + new->rcv = rcv; new->imem = imem; new->dmem = dmem; return (struct component *)new; diff --git a/src/components/grid/node.c b/src/components/grid/node.c index 0aed768..57ef7ed 100644 --- a/src/components/grid/node.c +++ b/src/components/grid/node.c @@ -5,73 +5,101 @@ * 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 grid_node { struct component component; uint8_t u, v, x, y; struct component *left, *right, *up, *down, *ascend, *lower; + + struct component *send; + struct packet pkt; + bool busy; }; -typedef read_callback callback; +static stat grid_clock(struct grid_node *grid) +{ + if (!grid->busy) + return OK; + + stat r = SEND(grid, grid->send, grid->pkt); + if (r == EBUSY) + return OK; + + grid->busy = false; + return r; +} -static stat grid_route(struct grid_node *grid, struct packet *pkt, callback op) +static stat grid_receive(struct grid_node *grid, struct component *from, struct packet pkt) { - uint64_t addr = packet_addr(pkt); - uint8_t u = (addr >> 56) & 0xff; - uint8_t v = (addr >> 48) & 0xff; - uint8_t x = (addr >> 40) & 0xff; - uint8_t y = (addr >> 32) & 0xff; + if (grid->busy) + return EBUSY; - if (grid->u == u && grid->v == v && grid->x == x && grid->y == y) - return op(grid->lower, pkt); + uint8_t u; + uint8_t v; + uint8_t x; + uint8_t y; + uint64_t addr = pkt.to; + addr_grid(addr, NULL, &x, &y, &u, &v); + + grid->busy = true; + grid->pkt = pkt; + + if (grid->u == u && grid->v == v && grid->x == x && grid->y == y) { + if (!grid->lower) + goto nosuch; + + grid->send = grid->lower; + return OK; + } if (grid->u != u || grid->v != v) { if (!grid->ascend) - return EBUS; + goto nosuch; - return op(grid->ascend, pkt); + grid->send = grid->ascend; + return OK; } if (y < grid->y) { if (!grid->down) - return EBUS; + goto nosuch; - return op(grid->down, pkt); + grid->send = grid->down; + return OK; } if (y > grid->y) { if (!grid->up) - return EBUS; + goto nosuch; - return op(grid->up, pkt); + grid->send = grid->up; + return OK; } if (x < grid->x) { if (!grid->left) - return EBUS; + goto nosuch; - return op(grid->left, pkt); + grid->send = grid->left; + return OK; } if (x > grid->x) { if (!grid->right) return EBUS; - return op(grid->right, pkt); + grid->send = grid->right; + return OK; } - return EBUS; -} - -static stat grid_write(struct grid_node *node, struct packet *pkt) -{ - return grid_route(node, pkt, write); -} - -static stat grid_read(struct grid_node *node, struct packet *pkt) -{ - return grid_route(node, pkt, read); +nosuch: + grid->send = from; + grid->pkt = response(pkt); + set_flags(&grid->pkt, PACKET_ERROR); + return OK; } struct component *create_grid_node(uint8_t u, uint8_t v, uint8_t x, uint8_t y) @@ -80,13 +108,12 @@ struct component *create_grid_node(uint8_t u, uint8_t v, uint8_t x, uint8_t y) if (!node) return NULL; + node->component.receive = (receive_callback)grid_receive; + node->component.clock = (clock_callback)grid_clock; node->u = u; node->v = v; node->x = x; node->y = y; - node->component.write = (write_callback)grid_write; - node->component.read = (read_callback)grid_read; - return (struct component *)node; } diff --git a/src/components/grid/router.c b/src/components/grid/router.c index bdb05c8..63c4011 100644 --- a/src/components/grid/router.c +++ b/src/components/grid/router.c @@ -1,3 +1,6 @@ +#include <stdbool.h> + +#include <gran/grid/node.h> #include <gran/grid/router.h> #include <gran/vec.h> @@ -12,6 +15,10 @@ struct node_router { struct component *ascend; struct vec regions; uint8_t u, v, x, y; + + struct component *send; + struct packet pkt; + bool busy; }; static struct router_region *find_region(struct node_router *router, uint32_t addr) @@ -26,40 +33,55 @@ static struct router_region *find_region(struct node_router *router, uint32_t ad return NULL; } -static stat router_write(struct node_router *router, struct packet *pkt) +static stat router_clock(struct node_router *router) { - uint64_t addr = packet_addr(pkt); - uint8_t u = (addr >> 56) & 0xff; - uint8_t v = (addr >> 48) & 0xff; - uint8_t x = (addr >> 40) & 0xff; - uint8_t y = (addr >> 32) & 0xff; + if (!router->busy) + return OK; - if (router->u != u || router->v != v || router->x != x || router->y != y) - return write(router->ascend, pkt); + stat r = SEND(router, router->send, router->pkt); + if (r == EBUSY) + return OK; - struct router_region *region = find_region(router, addr); - if (!region) - return write(router->ascend, pkt); - - return write(region->component, pkt); + router->busy = false; + return OK; } -static stat router_read(struct node_router *router, struct packet *pkt) +static stat router_receive(struct node_router *router, struct component *from, struct packet pkt) { - uint64_t addr = packet_addr(pkt); - uint8_t u = (addr >> 56) & 0xff; - uint8_t v = (addr >> 48) & 0xff; - uint8_t x = (addr >> 40) & 0xff; - uint8_t y = (addr >> 32) & 0xff; + if (router->busy) + return EBUSY; + + router->busy = true; - if (router->u != u || router->v != v || router->x != x || router->y != y) - return read(router->ascend, pkt); + uint64_t addr = pkt.to; + uint8_t u; + uint8_t v; + uint8_t x; + uint8_t y; + addr_grid(addr, NULL, &x, &y, &u, &v); + + router->pkt = pkt; + + if (router->u != u || router->v != v || router->x != x || router->y != y) { + if (!router->ascend) + goto nosuch; + + router->send = router->ascend; + return OK; + } struct router_region *region = find_region(router, addr); if (!region) - return read(router->ascend, pkt); + goto nosuch; - return read(region->component, pkt); + router->send = region->component; + return OK; + +nosuch: + router->send = from; + router->pkt = response(pkt); + set_flags(&router->pkt, PACKET_ERROR); + return OK; } struct component *create_node_router(uint8_t u, uint8_t v, uint8_t x, uint8_t y) @@ -73,8 +95,8 @@ struct component *create_node_router(uint8_t u, uint8_t v, uint8_t x, uint8_t y) router->x = x; router->y = y; - router->component.write = (write_callback)router_write; - router->component.read = (read_callback)router_read; + router->component.receive = (receive_callback)router_receive; + router->component.clock = (clock_callback)router_clock; router->regions = vec_create(sizeof(struct router_region)); return (struct component *)router; diff --git a/src/components/mem/simple_mem.c b/src/components/mem/simple_mem.c index bb9dd40..e435ea5 100644 --- a/src/components/mem/simple_mem.c +++ b/src/components/mem/simple_mem.c @@ -3,38 +3,57 @@ #include <string.h> #include <stdlib.h> +#include <stdbool.h> #include <gran/mem/simple_mem.h> struct simple_mem { struct component component; + struct component *send; + struct packet pkt; + bool busy; + size_t size; - char buf[]; + uint8_t buf[]; }; -static stat simple_mem_write(struct simple_mem *mem, struct packet *pkt) +static stat simple_mem_clock(struct simple_mem *mem) { - uintptr_t offset = packet_addr(pkt) % mem->size; - if (offset + packet_size(pkt) > mem->size) { - error("write outside memory"); - return ESIZE; - } + if (mem->busy) + return OK; + + stat r = SEND(mem, mem->send, mem->pkt); + if (r == EBUSY) + return OK; - memcpy(mem->buf + offset, packet_data(pkt), packet_size(pkt)); - packet_set_state(pkt, PACKET_DONE); + mem->busy = false; return OK; } -static stat simple_mem_read(struct simple_mem *mem, struct packet *pkt) +static stat simple_mem_receive(struct simple_mem *mem, struct component *from, struct packet pkt) { - uintptr_t offset = packet_addr(pkt) % mem->size; - if (offset + packet_size(pkt) > mem->size) { + if (mem->busy) + return EBUSY; + + mem->send = from; + + uint64_t offset = pkt.to % mem->size; + if (offset >= mem->size) { error("read outside memory"); - return ESIZE; + mem->pkt = response(pkt); + set_flags(&mem->pkt, PACKET_ERROR); + return OK; } - memcpy(packet_data(pkt), mem->buf + offset, packet_size(pkt)); - packet_set_state(pkt, PACKET_DONE); + if (is_set(&pkt, PACKET_READ)) + checked_copyto(&pkt, mem->buf + offset); + else if (is_set(&pkt, PACKET_WRITE)) + checked_copyfrom(&pkt, mem->buf + offset); + else + abort(); + + mem->pkt = response(pkt); + set_flags(&mem->pkt, PACKET_DONE); return OK; } @@ -45,8 +64,8 @@ struct component *create_simple_mem(size_t size) return NULL; new->size = size; - new->component.write = (write_callback)simple_mem_write; - new->component.read = (read_callback)simple_mem_read; + new->component.receive = (receive_callback)simple_mem_receive; + new->component.clock = (clock_callback)simple_mem_clock; return (struct component *)new; } diff --git a/src/components/uart/simple_uart.c b/src/components/uart/simple_uart.c index 5c97ccd..1528a70 100644 --- a/src/components/uart/simple_uart.c +++ b/src/components/uart/simple_uart.c @@ -3,17 +3,42 @@ struct simple_uart { struct component component; + + struct component *send; + struct packet pkt; + bool busy; }; -static stat simple_uart_write(struct simple_uart *uart, struct packet *pkt) +static stat simple_uart_clock(struct simple_uart *uart) { - (void)uart; - size_t size = packet_size(pkt); - if (size != 1) - return EBUS; + if (!uart->busy) + return OK; + + stat r = SEND(uart, uart->send, uart->pkt); + if (r == EBUSY) + return OK; + + uart->busy = false; + return OK; +} + +static stat simple_uart_receive(struct simple_uart *uart, struct component *from, struct packet pkt) +{ + if (uart->busy) + return EBUSY; + + uart->busy = true; + uart->send = from; + uart->pkt = response(pkt); + + size_t size = packet_convsize(&pkt); + if (size != 1) { + set_flags(&uart->pkt, PACKET_ERROR); + return OK; + } - putchar(*(uint8_t *)packet_data(pkt)); - packet_set_state(pkt, PACKET_DONE); + putchar(packet_convu8(&pkt)); + set_flags(&uart->pkt, PACKET_DONE); return OK; } @@ -23,6 +48,7 @@ struct component *create_simple_uart() if (!uart) return NULL; - uart->component.write = (write_callback)simple_uart_write; + uart->component.receive = (receive_callback)simple_uart_receive; + uart->component.clock = (clock_callback)simple_uart_clock; return (struct component *)uart; } |
