From 0fa2d31cec6d8d64fc5dd22bb6e6c8cab538562f Mon Sep 17 00:00:00 2001 From: Michel Pollet Date: Tue, 22 Feb 2011 12:50:51 +0000 Subject: [PATCH] core: Add a muxer for IO writes It turns out that some core (tiny85 at the very least) are competing for IO writes on some register. This patch introduces a muxer callback that can call multiple clients without impacting performance for the rest of the cores. The system could be extended for IO read if it proves necessary. Signed-off-by: Michel Pollet --- simavr/sim/sim_avr.h | 18 ++++++++++++++ simavr/sim/sim_io.c | 57 ++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 71 insertions(+), 4 deletions(-) diff --git a/simavr/sim/sim_avr.h b/simavr/sim/sim_avr.h index ae1a3ab..cdaf598 100644 --- a/simavr/sim/sim_avr.h +++ b/simavr/sim/sim_avr.h @@ -159,6 +159,24 @@ typedef struct avr_t { } w; } io[MAX_IOs]; + /* + * This block allows sharing of the IO write/read on addresses between + * multiple callbacks. In 99% of case it's not needed, however on the tiny* + * (tiny85 at last) some registers have bits that are used by different + * IO modules. + * If this case is detected, a special "dispatch" callback is installed that + * will handle this particular case, without impacting the performance of the + * other, normal cases... + */ + int io_shared_io_count; + struct { + int used; + struct { + void * param; + void * c; + } io[4]; + } io_shared_io[4]; + // flash memory (initialized to 0xff, and code loaded into it) uint8_t * flash; // this is the general purpose registers, IO registers, and SRAM diff --git a/simavr/sim/sim_io.c b/simavr/sim/sim_io.c index 3ef9d35..e85d0b2 100644 --- a/simavr/sim/sim_io.c +++ b/simavr/sim/sim_io.c @@ -48,20 +48,69 @@ void avr_register_io_read(avr_t *avr, avr_io_addr_t addr, avr_io_read_t readp, v { avr_io_addr_t a = AVR_DATA_TO_IO(addr); if (avr->io[a].r.param || avr->io[a].r.c) { - fputs("Error: avr_register_io_read(): Already registered, refusing to override.\n", stderr); - exit(1); + if (avr->io[a].r.param != param || avr->io[a].r.c != readp) { + fprintf(stderr, + "Error: avr_register_io_read(): Already registered, refusing to override.\n"); + fprintf(stderr, + "Error: avr_register_io_read(%04x : %p/%p): %p/%p\n", a, + avr->io[a].r.c, avr->io[a].r.param, readp, param); + abort(); + } } avr->io[a].r.param = param; avr->io[a].r.c = readp; } +static void +_avr_io_mux_write(avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param) +{ + int io = (int)param; + for (int i = 0; i < avr->io_shared_io[io].used; i++) { + avr_io_write_t c = avr->io_shared_io[io].io[i].c; + if (c) + c(avr, addr, v, avr->io_shared_io[io].io[i].param); + } +} + void avr_register_io_write(avr_t *avr, avr_io_addr_t addr, avr_io_write_t writep, void * param) { avr_io_addr_t a = AVR_DATA_TO_IO(addr); + + /* + * Verifying that some other piece of code is not installed to watch write + * on this address. If there is, this code installs a "dispatcher" callback + * instead to handle multiple clients, otherwise, it continues as usual + */ if (avr->io[a].w.param || avr->io[a].w.c) { - fputs("Error: avr_register_io_write(): Already registered, refusing to override.\n", stderr); - exit(1); + if (avr->io[a].w.param != param || avr->io[a].w.c != writep) { + // if the muxer not already installed, allocate a new slot + if (avr->io[a].w.c != _avr_io_mux_write) { + int no = avr->io_shared_io_count++; + if (avr->io_shared_io_count > 4) { + fprintf(stderr, + "Error: avr_register_io_write(): Too many shared IO registers.\n"); + abort(); + } + fprintf(stderr, + "Note: avr_register_io_write(%04x): Installing muxer on register.\n", addr); + avr->io_shared_io[no].used = 1; + avr->io_shared_io[no].io[0].param = avr->io[a].w.param; + avr->io_shared_io[no].io[0].c = avr->io[a].w.c; + avr->io[a].w.param = (void*)no; + avr->io[a].w.c = _avr_io_mux_write; + } + int no = (int)avr->io[a].w.param; + int d = avr->io_shared_io[no].used++; + if (avr->io_shared_io[no].used > 4) { + fprintf(stderr, + "Error: avr_register_io_write(): Too many callbacks on %04x.\n", addr); + abort(); + } + avr->io_shared_io[no].io[d].param = param; + avr->io_shared_io[no].io[d].c = writep; + } } + avr->io[a].w.param = param; avr->io[a].w.c = writep; } -- 2.39.5