From fecb86f6093c1e8aed6ab05c29c5af9d0cb93157 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Tue, 24 Sep 2024 16:51:51 +0300 Subject: 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 --- include/gran/bus/simple_bus.h | 2 +- include/gran/component.h | 62 ++------- include/gran/cpu/riscv/simple_riscv64.h | 2 +- include/gran/grid/node.h | 19 +++ include/gran/packet.h | 223 ++++++++++++++++++++++++++++---- include/gran/snoop.h | 23 ---- 6 files changed, 227 insertions(+), 104 deletions(-) delete mode 100644 include/gran/snoop.h (limited to 'include') diff --git a/include/gran/bus/simple_bus.h b/include/gran/bus/simple_bus.h index 62dd7d2..eb1e821 100644 --- a/include/gran/bus/simple_bus.h +++ b/include/gran/bus/simple_bus.h @@ -4,7 +4,7 @@ #ifndef GRAN_SIMPLE_BUS_H #define GRAN_SIMPLE_BUS_H -#include +#include struct component *create_simple_bus(); stat simple_bus_add(struct component *bus, struct component *component, diff --git a/include/gran/component.h b/include/gran/component.h index 4ef94ad..289d0a6 100644 --- a/include/gran/component.h +++ b/include/gran/component.h @@ -12,36 +12,20 @@ #include #include -#include struct component; -typedef stat (*read_callback)(struct component *, struct packet *pkt); -typedef stat (*write_callback)(struct component *, struct packet *pkt); -typedef stat (*swap_callback)(struct component *, struct packet *pkt); - -typedef stat (*snoop_callback)(struct component *, struct snoop *snoop); -typedef stat (*ctrl_callback)(struct component *, struct packet *pkt); - -typedef stat (*irq_callback)(struct component *, int); +typedef stat (*receive_callback)(struct component *to, struct component *from, struct packet pkt); typedef stat (*clock_callback)(struct component *); typedef stat (*stat_callback)(struct component *, FILE *); typedef stat (*dts_callback)(struct component *, FILE *); - typedef void (*destroy_callback)(struct component *); struct component { /* optional */ char *name; - read_callback read; - write_callback write; - swap_callback swap; - - snoop_callback snoop; - ctrl_callback ctrl; - - irq_callback irq; + receive_callback receive; clock_callback clock; dts_callback dts; @@ -50,48 +34,20 @@ struct component { destroy_callback destroy; }; -static inline stat write(struct component *component, struct packet *pkt) +static inline stat send(struct component *from, struct component *to, struct packet pkt) { - assert(packet_type(pkt) == PACKET_WRITE); - if (!component->write) { + if (!to->receive) { /* printf formatted asserts would maybe be preferable? */ error( - "tried writing %p:%" PRIuPTR " but it doesn't support writing", - component->name, packet_addr(pkt)); - return ENOSUCH; - } - - packet_set_state(pkt, PACKET_SENT); - return component->write(component, pkt); -} - -static inline stat read(struct component *component, struct packet *pkt) -{ - assert(packet_type(pkt) == PACKET_READ); - if (!component->read) { - error( - "tried reading %p:%" PRIuPTR " but it doesn't support reading", - component->name, packet_addr(pkt)); - return ENOSUCH; - } - - packet_set_state(pkt, PACKET_SENT); - return component->read(component, pkt); -} - -static inline stat swap(struct component *component, struct packet *pkt) -{ - assert(packet_type(pkt) == PACKET_SWAP); - if (!component->swap) { - error( - "tried swapping %p:%" PRIuPTR " but it doesn't support swapping", - component->name, packet_addr(pkt)); + "%s:%lx tried sending to %s:%lx", + from->name, pkt.from, + to->name, pkt.to); return ENOSUCH; } - packet_set_state(pkt, PACKET_SENT); - return component->swap(component, pkt); + return to->receive(to, from, pkt); } +#define SEND(x, y, z) send((struct component *)(x), (struct component *)(y), z) static inline void destroy(struct component *component) { diff --git a/include/gran/cpu/riscv/simple_riscv64.h b/include/gran/cpu/riscv/simple_riscv64.h index 8f66013..fe6e686 100644 --- a/include/gran/cpu/riscv/simple_riscv64.h +++ b/include/gran/cpu/riscv/simple_riscv64.h @@ -6,7 +6,7 @@ #include -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); diff --git a/include/gran/grid/node.h b/include/gran/grid/node.h index 637ac91..16116d2 100644 --- a/include/gran/grid/node.h +++ b/include/gran/grid/node.h @@ -11,4 +11,23 @@ stat grid_node_connect(struct component *node, struct component *up, struct component *down, struct component *lower, struct component *ascend); +static inline uint64_t grid_addr(uint8_t u, uint8_t v, uint8_t x, uint8_t y, uint32_t off) +{ + return off + | ((uint64_t)x << 32) + | ((uint64_t)y << 40) + | ((uint64_t)u << 48) + | ((uint64_t)v << 56) + ; +} + +static inline void addr_grid(uint64_t addr, uint32_t *off, uint8_t *x, uint8_t *y, uint8_t *u, uint8_t *v) +{ + if (off) *off = addr & 0xffffffff; + if (x) *x = (addr >> 32) & 0xff; + if (y) *y = (addr >> 40) & 0xff; + if (u) *u = (addr >> 48) & 0xff; + if (v) *v = (addr >> 56) & 0xff; +} + #endif /* GRAN_GRID_NODE_H */ diff --git a/include/gran/packet.h b/include/gran/packet.h index ab07b56..5f8bd9c 100644 --- a/include/gran/packet.h +++ b/include/gran/packet.h @@ -4,44 +4,215 @@ #ifndef GRAN_PACKET_H #define GRAN_PACKET_H +#include #include #include +#include +#include -enum packet_state { - PACKET_INIT, - PACKET_FAILED, - PACKET_SENT, - PACKET_WAITING, - PACKET_DONE, +enum packet_flags { + PACKET_READ = (1 << 0), + PACKET_WRITE = (1 << 1), + PACKET_ATOMIC = (1 << 2), + PACKET_ERROR = (1 << 3), + PACKET_DONE = (1 << 4) }; -enum packet_type { - PACKET_READ, - PACKET_WRITE, - PACKET_SWAP, - PACKET_SNOOP, - PACKET_CTRL, +struct packet { + uint64_t from; + uint64_t to; + uint64_t mask; + uint8_t data[64]; + enum packet_flags flags; }; -struct packet; +static inline struct packet response(struct packet pkt) +{ + uint64_t from = pkt.from; + uint64_t to = pkt.to; + pkt.from = to; + pkt.to = from; + return pkt; +} -struct packet *create_packet(enum packet_type type, uintptr_t addr, - size_t size); +static inline void set_flags(struct packet *pkt, enum packet_flags flags) +{ + pkt->flags |= flags; +} -struct packet *create_packet_with(enum packet_type type, uintptr_t addr, - size_t size, void *data); +static inline void clear_flags(struct packet *pkt, enum packet_flags flags) +{ + pkt->flags &= ~flags; +} -struct packet *reuse_packet(struct packet *pkt, enum packet_type type, - uintptr_t addr, size_t size, void *data); +static inline bool is_set(struct packet *pkt, enum packet_flags flags) +{ + return pkt->flags & flags; +} -enum packet_type packet_type(struct packet *pkt); -enum packet_state packet_state(struct packet *pkt); -void packet_set_state(struct packet *pkt, enum packet_state state); +static inline uint64_t packet_align(uint64_t addr) +{ + return addr & ~(64 - 1); +} -size_t packet_size(struct packet *pkt); -uint64_t packet_addr(struct packet *pkt); -void *packet_data(struct packet *pkt); +static inline uint64_t packet_mask(uint64_t addr, uint64_t size) +{ + assert(size <= 64); + uint64_t mask = size == 64 ? ((uint64_t)-1) : (((uint64_t)1 << size) - 1); + uint64_t aligned = packet_align(addr); + uint64_t diff = addr - aligned; -void destroy_packet(struct packet *pkt); + assert((diff == 0) || ((mask >> (64 - diff)) == 0)); + mask <<= diff; + return mask; +} + +static inline uint64_t packet_convsize(struct packet *pkt) +{ + int start = __builtin_ffsll(pkt->mask); + if (start == 0) + return 0; + + switch ((pkt->mask >> (start - 1)) & 0xff) { + case 0x01: return 1; + case 0x03: return 2; + case 0x0f: return 4; + case 0xff: return 8; + default: abort(); + } + + return 0; +} + +static inline uint64_t packet_convto(struct packet *pkt) +{ + int start = __builtin_ffsll(pkt->mask); + if (start == 0) + return pkt->to; + + return pkt->to + (start - 1); +} + +static inline uint64_t packet_convfrom(struct packet *pkt) +{ + int start = __builtin_ffsll(pkt->mask); + if (start == 0) + return pkt->from; + + return pkt->from + (start - 1); +} + +static inline int64_t packet_convi8(struct packet *pkt) +{ + int start = __builtin_ffsll(pkt->mask); + assert(start != 0); + + return pkt->data[start - 1]; +} + +static inline uint8_t packet_convu8(struct packet *pkt) +{ + int start = __builtin_ffsll(pkt->mask); + assert(start != 0); + + return pkt->data[start - 1]; +} + +static inline int16_t packet_convi16(struct packet *pkt) +{ + int start = __builtin_ffsll(pkt->mask); + assert(start != 0); + + int16_t res = 0; + memcpy(&res, pkt->data + (start - 1), 2); + return res; +} + +static inline uint16_t packet_convu16(struct packet *pkt) +{ + int start = __builtin_ffsll(pkt->mask); + assert(start != 0); + + uint16_t res = 0; + memcpy(&res, pkt->data + (start - 1), 2); + return res; +} + +static inline int32_t packet_convi32(struct packet *pkt) +{ + int start = __builtin_ffsll(pkt->mask); + assert(start != 0); + + int32_t res = 0; + memcpy(&res, pkt->data + (start - 1), 4); + return res; +} + +static inline uint32_t packet_convu32(struct packet *pkt) +{ + int start = __builtin_ffsll(pkt->mask); + assert(start != 0); + + uint32_t res = 0; + memcpy(&res, pkt->data + (start - 1), 4); + return res; +} + +static inline int64_t packet_convi64(struct packet *pkt) +{ + int start = __builtin_ffsll(pkt->mask); + assert(start != 0); + + int64_t res = 0; + memcpy(&res, pkt->data + (start - 1), 8); + return res; +} + +static inline uint64_t packet_convu64(struct packet *pkt) +{ + int start = __builtin_ffsll(pkt->mask); + assert(start != 0); + + uint64_t res = 0; + memcpy(&res, pkt->data + (start - 1), 8); + return res; +} + +static inline struct packet create_packet(uint64_t from, uint64_t to, uint64_t size, void *data, enum packet_flags flags) +{ + assert(size <= 64); + assert(packet_align(from) == from); + + uint64_t aligned = packet_align(to); + uint64_t mask = packet_mask(to, size); + struct packet pkt = (struct packet){ + .from = from, + .to = aligned, + .mask = mask, + .data = {}, + .flags = flags + }; + + if (is_set(&pkt, PACKET_WRITE)) + memcpy(pkt.data + (to - aligned), data, size); + + return pkt; +} + +static inline void checked_copyto(struct packet *pkt, uint8_t *data) +{ + for (size_t i = 0; i < 64; ++i) { + if (pkt->mask & ((uint64_t)1 << i)) + pkt->data[i] = data[i]; + } +} + +static inline void checked_copyfrom(struct packet *pkt, uint8_t *data) +{ + for (size_t i = 0; i < 64; ++i) { + if (pkt->mask & ((uint64_t)1 << i)) + data[i] = pkt->data[i]; + } +} #endif /* GRAN_PACKET_H */ diff --git a/include/gran/snoop.h b/include/gran/snoop.h deleted file mode 100644 index 5254984..0000000 --- a/include/gran/snoop.h +++ /dev/null @@ -1,23 +0,0 @@ -/* SPDX-License-Identifier: copyleft-next-0.3.1 */ -/* Copyright 2023 Kim Kuparinen < kimi.h.kuparinen@gmail.com > */ - -#ifndef GRAN_SNOOP_H -#define GRAN_SNOOP_H - -#include - -enum snoop_state { - SNOOP_UNANSWERED, - SNOOP_ANSWERED, -}; - -struct snoop; - -struct snoop *create_snoop(uintptr_t addr, size_t size); -void destroy_snoop(struct snoop *snoop); - -enum snoop_state snoop_state(struct snoop *snoop); -uintptr_t snoop_addr(struct snoop *snoop); -size_t snoop_size(struct snoop *snoop); - -#endif /* GRAN_SNOOP_H */ -- cgit v1.3