diff options
author | Jiri Gaisler <jiri@gaisler.se> | 2020-11-30 22:52:27 +0100 |
---|---|---|
committer | Jiri Gaisler <jiri@gaisler.se> | 2020-12-01 16:44:49 +0100 |
commit | 11154be7bec2967b869fe385ab1df93a27efd82c (patch) | |
tree | 955b1c03b0ea4bd3bf6d36af9ec0431c27391401 | |
parent | 416cfac77679c69ea79ecc207f72a4693186a6ca (diff) |
Make grlib IP cores more modular and move them to grlib.c
-rw-r--r-- | elf.c | 6 | ||||
-rw-r--r-- | erc32.c | 2 | ||||
-rw-r--r-- | func.c | 39 | ||||
-rw-r--r-- | greth.c | 3 | ||||
-rw-r--r-- | grlib.c | 1195 | ||||
-rw-r--r-- | grlib.h | 39 | ||||
-rw-r--r-- | leon2.c | 2 | ||||
-rw-r--r-- | leon3.c | 1068 | ||||
-rw-r--r-- | sis.h | 5 |
9 files changed, 1300 insertions, 1059 deletions
@@ -240,13 +240,13 @@ elf_load (char *fname, int load) res = read_elf_header (fp); - if (res < 0) + if (res == -1) printf ("File read error\n"); - if (load && (res >= 0)) + else if (load) { res = read_elf_body (); - if (res < 0) + if (res == -1) printf ("File read error\n"); else printf (" Loaded %s, entry 0x%08x\n", fname, res); @@ -17,7 +17,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ #define ROM_START 0 +#define ROM_SIZE 0x01000000 #define RAM_START 0x02000000 +#define RAM_SIZE 0x01000000 #include "config.h" #include <errno.h> @@ -36,8 +36,6 @@ #include <inttypes.h> #include <sys/time.h> -//#define ROM_ENABLED - /* set if UART device cannot handle attributes, terminal oriented IO by default */ int dumbio = 0; @@ -67,8 +65,8 @@ int sync_rt = 0; char bridge[32] = ""; /* RAM and ROM for all systems */ -char romb[ROM_SIZE]; -char ramb[RAM_SIZE]; +char romb[MAX_ROM_SIZE]; +char ramb[MAX_RAM_SIZE]; const struct memsys *ms = &erc32sys; int cputype = 0; /* 0 = erc32, 2 = leon2,3 = leon3, 5 = riscv */ int sis_gdb_break; @@ -301,7 +299,7 @@ exec_cmd (const char *cmd) sregs[i].pc = len & ~1; sregs[i].npc = sregs->pc + 4; } - if ((sregs->pc != 0) && (ebase.simtime == 0)) + if (ebase.simtime == 0) ms->boot_init (); printf ("resuming at 0x%08x\n", sregs->pc); if ((cmd2 = strtok (NULL, " \t\n\r")) != NULL) @@ -468,7 +466,7 @@ exec_cmd (const char *cmd) sregs[i].npc = sregs[i].pc + 4; } } - if ((sregs->pc != 0) && (ebase.simtime == 0)) + if (ebase.simtime == 0) ms->boot_init (); if ((cmd1 = strtok (NULL, " \t\n\r")) == NULL) { @@ -1184,13 +1182,7 @@ run_sim_un (sregs, icount, dis) irq = arch->check_interrupts (sregs); if (!irq) { -#ifdef ROM_ENABLED mexc = ms->memory_iread (sregs->pc, &sregs->inst, &sregs->hold); -#else - inst = (uint32 *) & ramb[sregs->pc & RAM_MASK]; - sregs->inst = *inst; - sregs->hold = 0; -#endif if (mexc) { sregs->trap = I_ACC_EXC; @@ -1310,12 +1302,7 @@ run_sim_core (sregs, ntime, deb, dis) else irq = 0; sregs->icnt = 1; -#ifdef ROM_ENABLED mexc = ms->memory_iread (sregs->pc, &sregs->inst, &sregs->hold); -#else - sregs->inst = *((uint32 *) & ramb[sregs->pc & RAM_MASK]); - sregs->hold = 0; -#endif #ifdef ENABLE_L1CACHE if (sregs->l1itags[(sregs->pc >> L1ILINEBITS) & L1IMASK] != (sregs->pc >> L1ILINEBITS)) @@ -1585,39 +1572,39 @@ mygetline (char **lineptr, size_t * n, FILE * stream) #define COV_BT 8 #define COV_BNT 16 -unsigned char covram[RAM_SIZE / 4]; +unsigned char covram[MAX_RAM_SIZE / 4]; void cov_start (int address) { - covram[(address >> 2) & RAM_MASK] |= (COV_START | COV_EXEC); + covram[(address >> 2) & MAX_RAM_MASK] |= (COV_START | COV_EXEC); } void cov_exec (int address) { - covram[(address >> 2) & RAM_MASK] |= COV_EXEC; + covram[(address >> 2) & MAX_RAM_MASK] |= COV_EXEC; } void cov_bt (int address1, int address2) { - covram[(address1 >> 2) & RAM_MASK] |= (COV_BT | COV_EXEC); - covram[(address2 >> 2) & RAM_MASK] |= (COV_START | COV_EXEC); + covram[(address1 >> 2) & MAX_RAM_MASK] |= (COV_BT | COV_EXEC); + covram[(address2 >> 2) & MAX_RAM_MASK] |= (COV_START | COV_EXEC); } void cov_bnt (int address) { - covram[(address >> 2) & RAM_MASK] |= (COV_BNT | COV_EXEC); + covram[(address >> 2) & MAX_RAM_MASK] |= (COV_BNT | COV_EXEC); } void cov_jmp (int address1, int address2) { - covram[(address1 >> 2) & RAM_MASK] |= (COV_JMP | COV_EXEC); - covram[(address2 >> 2) & RAM_MASK] |= (COV_START | COV_EXEC); + covram[(address1 >> 2) & MAX_RAM_MASK] |= (COV_JMP | COV_EXEC); + covram[(address2 >> 2) & MAX_RAM_MASK] |= (COV_START | COV_EXEC); } void @@ -1631,7 +1618,7 @@ cov_save (char *name) strcat (filename, ".cov"); fp = fopen (filename, "w"); state = 0; - for (i = 0; i < RAM_SIZE / 4; i += 32) + for (i = 0; i < MAX_RAM_SIZE / 4; i += 32) { k = 0; for (j = 0; j < 32; j++) @@ -255,9 +255,6 @@ greth_read (uint32 address) default: res = 0; } - if (sis_verbose > 1) - printf ("%8lu cpu %d APB read a: %08x, d: %08x\n", - ebase.simtime, cpu, address, res); return res; } @@ -18,7 +18,17 @@ * */ - +#include "config.h" +#include <stdio.h> +#include <inttypes.h> +#ifdef HAVE_TERMIOS_H +#include <termios.h> +#endif +#include <sys/file.h> +#include <unistd.h> +#include <errno.h> +#include <sys/types.h> +#include <string.h> #include "sis.h" #include "grlib.h" @@ -90,21 +100,1190 @@ grlib_ahbpnp_read (uint32 addr) } +static struct grlib_buscore ahbmcores[16]; +static struct grlib_buscore ahbscores[16]; +static struct grlib_buscore apbcores[16]; +static int ahbmi; +static int ahbsi; +static int apbi; + void grlib_init () { - /* Add PP records for Leon3, APB bridge and interrupt controller - as this is not done elsewhere */ + int i; + + for (i = 0; i < ahbmi; i++) + if (ahbmcores[i].core->init) + ahbmcores[i].core->init (); + for (i = 0; i < ahbsi; i++) + if (ahbscores[i].core->init) + ahbscores[i].core->init (); +} + +void +grlib_reset () +{ + int i; + + for (i = 0; i < ahbmi; i++) + if (ahbmcores[i].core->reset) + ahbmcores[i].core->reset (); + for (i = 0; i < ahbsi; i++) + if (ahbscores[i].core->reset) + ahbscores[i].core->reset (); +} + + +void +grlib_ahbm_add (const struct grlib_ipcore *core, int irq) +{ + ahbmcores[ahbmi].core = core; + if (core->add) + core->add (irq, 0, 0); + ahbmi++; +} + +void +grlib_ahbs_add (const struct grlib_ipcore *core, int irq, + uint32 addr, uint32 mask) +{ + ahbscores[ahbsi].core = core; + if (core->add) + { + ahbscores[ahbsi].start = addr; + ahbscores[ahbsi].end = addr + ~(mask << 20) + 1; + ahbscores[ahbsi].mask = ~(mask << 20); + core->add (irq, addr, mask); + } + ahbsi++; +} + +int +grlib_read (uint32 addr, uint32 * data) +{ + int i; + int res = 0; + + for (i = 0; i < ahbsi; i++) + if ((addr >= ahbscores[i].start) && (addr < ahbscores[i].end)) + { + if (ahbscores[i].core->read) + res = ahbscores[i].core->read (addr & ahbscores[i].mask, data); + if (sis_verbose > 2) + printf ("AHB read a: %08x, d: %08x\n", addr, *data); + break; + } + + if (!res && ((addr >= AHBPP_START) && (addr <= AHBPP_END))) + { + *data = grlib_ahbpnp_read (addr); + if (sis_verbose > 1) + printf ("AHB PP read a: %08x, d: %08x\n", addr, *data); + return 0; + } + + return !res; +} + +int +grlib_write (uint32 addr, uint32 * data, uint32 sz) +{ + int i; + int res = 0; + + for (i = 0; i < ahbsi; i++) + if ((addr >= ahbscores[i].start) && (addr < ahbscores[i].end)) + { + if (ahbscores[i].core->write) + res = ahbscores[i].core->write (addr & ahbscores[i].mask, data, sz); + if (sis_verbose > 2) + printf ("AHB write a: %08x, d: %08x\n", addr, *data); + break; + } + return !res; +} + +void +grlib_apb_add (const struct grlib_ipcore *core, int irq, + uint32 addr, uint32 mask) +{ + apbcores[apbi].core = core; + if (core->add) + { + apbcores[apbi].start = addr & (mask << 8); + apbcores[apbi].end = + (apbcores[apbi].start + ~(mask << 8) + 1) & 0x0fffff; + apbcores[apbi].mask = ~(mask << 8) & 0x0fffff; + core->add (irq, addr, mask); + } + apbi++; +} + +/* ------------------- GRETH -----------------------*/ + + +static int +grlib_greth_read (uint32 addr, uint32 * data) +{ + *data = greth_read (addr); +} + +static int +grlib_greth_write (uint32 addr, uint32 * data, uint32 size) +{ + greth_write (addr, *data); +} + +static void +greth_add (int irq, uint32 addr, uint32 mask) +{ + grlib_ahbmpp_add (GRLIB_PP_ID (VENDOR_GAISLER, GAISLER_GRETH, 0, 0)); + grlib_apbpp_add (GRLIB_PP_ID (VENDOR_GAISLER, GAISLER_GRETH, 0, 6), + GRLIB_PP_APBADDR (addr, mask)); +} + +const struct grlib_ipcore greth = { + NULL, NULL, grlib_greth_read, grlib_greth_write, greth_add +}; + + +/* ------------------- LEON3 -----------------------*/ +static void +leon3_add () +{ grlib_ahbmpp_add (GRLIB_PP_ID (VENDOR_GAISLER, GAISLER_LEON3, 0, 0)); +} + +const struct grlib_ipcore leon3s = { + NULL, NULL, NULL, NULL, leon3_add +}; + +/* ------------------- APBMST ----------------------*/ + +static void +apbmst_init () +{ + int i; + + for (i = 0; i < apbi; i++) + if (apbcores[i].core->init) + apbcores[i].core->init (); +} + +static void +apbmst_reset () +{ + int i; + + for (i = 0; i < apbi; i++) + if (apbcores[i].core->reset) + apbcores[i].core->reset (); +} + +static int +apbmst_read (uint32 addr, uint32 * data) +{ + int i; + int res = 0; + + for (i = 0; i < apbi; i++) + { + if ((addr >= apbcores[i].start) && (addr < apbcores[i].end)) + { + res = 1; + if (apbcores[i].core->read) + apbcores[i].core->read (addr & apbcores[i].mask, data); + break; + } + } + if (!res && (addr >= 0xFF000)) + { + *data = grlib_apbpnp_read (addr); + if (sis_verbose > 1) + printf ("APB PP read a: %08x, d: %08x\n", addr, *data); + } + return 1; +} + +static int +apbmst_write (uint32 addr, uint32 * data, uint32 size) +{ + int i; + + for (i = 0; i < apbi; i++) + if ((addr >= apbcores[i].start) && (addr < apbcores[i].end)) + { + if (apbcores[i].core->write) + apbcores[i].core->write (addr & apbcores[i].mask, data, size); + break; + } + return 1; +} + +static void +apbmst_add (int irq, uint32 addr, uint32 mask) +{ grlib_ahbspp_add (GRLIB_PP_ID (VENDOR_GAISLER, GAISLER_APBMST, 0, 0), - GRLIB_PP_AHBADDR (0x80000000, 0xFFF, 0, 0, 2), 0, 0, 0); + GRLIB_PP_AHBADDR (addr, mask, 0, 0, 2), 0, 0, 0); +} + +const struct grlib_ipcore apbmst = { + apbmst_init, apbmst_reset, apbmst_read, apbmst_write, apbmst_add +}; + +/* ------------------- IRQMP -----------------------*/ + +#define IRQMP_IPR 0x04 +#define IRQMP_IFR 0x08 +#define IRQMP_ICR 0x0C +#define IRQMP_ISR 0x10 +#define IRQMP_IBR 0x14 +#define IRQMP_IMR 0x40 +#define IRQMP_IMR1 0x44 +#define IRQMP_IMR2 0x48 +#define IRQMP_IMR3 0x4C +#define IRQMP_IFR0 0x80 +#define IRQMP_IFR1 0x84 +#define IRQMP_IFR2 0x88 +#define IRQMP_IFR3 0x8C + +static void irqmp_intack (int level, int cpu); +static void chk_irq (void); + +/* IRQMP registers. */ + +static uint32 irqmp_ipr; +static uint32 irqmp_ibr; +static uint32 irqmp_imr[NCPU]; +static uint32 irqmp_ifr[NCPU]; + +static void +irqmp_init (void) +{ + int i; + + for (i = 0; i < NCPU; i++) + { + sregs[i].intack = irqmp_intack; + } +} + +static void +irqmp_reset (void) +{ + int i; + + irqmp_ipr = 0; + for (i = 0; i < NCPU; i++) + { + irqmp_imr[i] = 0; + irqmp_ifr[i] = 0; + } +} + +static void +irqmp_intack (int level, int cpu) +{ + int irq_test; + + if ((sis_verbose > 2) && (level != 10)) + printf ("%8" PRIu64 " cpu %d interrupt %d acknowledged\n", + ebase.simtime, cpu, level); + if (irqmp_ifr[cpu] & (1 << level)) + irqmp_ifr[cpu] &= ~(1 << level); + else + irqmp_ipr &= ~(1 << level); + chk_irq (); +} + +static void +chk_irq () +{ + int32 i, cpu; + uint32 itmp; + int old_irl; + + for (cpu = 0; cpu < ncpu; cpu++) + { + old_irl = ext_irl[cpu]; + itmp = ((irqmp_ipr | irqmp_ifr[cpu]) & irqmp_imr[cpu]) & 0x0fffe; + ext_irl[cpu] = 0; + if (itmp != 0) + { + for (i = 15; i > 0; i--) + { + if (((itmp >> i) & 1) != 0) + { + if ((sis_verbose > 2) && (i != old_irl)) + printf ("%8" PRIu64 " cpu %d irl: %d\n", + ebase.simtime, cpu, i); + ext_irl[cpu] = i; + break; + } + } + } + } +} + +void +grlib_set_irq (int32 level) +{ + int i; + + if ((irqmp_ibr >> level) & 1) + for (i = 0; i < ncpu; i++) + irqmp_ifr[i] |= (1 << level); + else + irqmp_ipr |= (1 << level); + chk_irq (); +} + +static int +irqmp_read (uint32 addr, uint32 * data) +{ + int i; + + switch (addr & 0xff) + { + case IRQMP_IPR: /* 0x04 */ + *data = irqmp_ipr; + break; + + case IRQMP_IFR: /* 0x08 */ + *data = irqmp_ifr[0]; + break; + + case IRQMP_ISR: /* 0x10 */ + *data = ((ncpu - 1) << 28); + for (i = 0; i < ncpu; i++) + *data |= (sregs[i].pwd_mode << i); + break; + + case IRQMP_IBR: /* 0x14 */ + *data = irqmp_ibr; + break; + + case IRQMP_IMR: /* 0x40 */ + *data = irqmp_imr[0]; + break; + + case IRQMP_IMR1: /* 0x44 */ + *data = irqmp_imr[1]; + break; + case IRQMP_IMR2: /* 0x48 */ + *data = irqmp_imr[2]; + break; + + case IRQMP_IMR3: /* 0x4C */ + *data = irqmp_imr[3]; + break; + + case IRQMP_IFR0: /* 0x80 */ + *data = irqmp_ifr[0]; + break; + + case IRQMP_IFR1: /* 0x84 */ + *data = irqmp_ifr[1]; + break; + + case IRQMP_IFR2: /* 0x88 */ + *data = irqmp_ifr[2]; + break; + + case IRQMP_IFR3: /* 0x8C */ + *data = irqmp_ifr[3]; + break; + + default: + *data = 0; + } +} + +static int +irqmp_write (uint32 addr, uint32 * data, uint32 size) +{ + int i; + + switch (addr & 0xff) + { + + case IRQMP_IFR: /* 0x08 */ + irqmp_ifr[0] = *data & 0xfffe; + chk_irq (); + break; + + case IRQMP_ICR: /* 0x0C */ + irqmp_ipr &= ~*data & 0x0fffe; + chk_irq (); + break; + + case IRQMP_ISR: /* 0x10 */ + for (i = 0; i < ncpu; i++) + { + if ((*data >> i) & 1) + { + if (sregs[i].pwd_mode) + { + sregs[i].simtime = ebase.simtime; + if (sis_verbose > 1) + printf ("%8" PRIu64 " cpu %d starting\n", ebase.simtime, + i); + sregs[i].pwdtime += ebase.simtime - sregs[i].pwdstart; + } + sregs[i].pwd_mode = 0; + } + } + break; + + case IRQMP_IBR: /* 0x14 */ + irqmp_ibr = *data & 0xfffe; + break; + + case IRQMP_IMR: /* 0x40 */ + irqmp_imr[0] = *data & 0x7ffe; + chk_irq (); + break; + + case IRQMP_IMR1: /* 0x44 */ + irqmp_imr[1] = *data & 0x7ffe; + chk_irq (); + break; + + case IRQMP_IMR2: /* 0x48 */ + irqmp_imr[2] = *data & 0x7ffe; + chk_irq (); + break; + + case IRQMP_IMR3: /* 0x4C */ + irqmp_imr[3] = *data & 0x7ffe; + chk_irq (); + break; + + case IRQMP_IFR0: /* 0x80 */ + irqmp_ifr[0] = *data & 0xfffe; + chk_irq (); + break; + + case IRQMP_IFR1: /* 0x84 */ + irqmp_ifr[1] = *data & 0xfffe; + chk_irq (); + break; + + case IRQMP_IFR2: /* 0x88 */ + irqmp_ifr[2] = *data & 0xfffe; + chk_irq (); + break; + + case IRQMP_IFR3: /* 0x8C */ + irqmp_ifr[3] = *data & 0xfffe; + chk_irq (); + break; + } +} + +static void +irqmp_add (int irq, uint32 addr, uint32 mask) +{ grlib_apbpp_add (GRLIB_PP_ID (VENDOR_GAISLER, GAISLER_IRQMP, 2, 0), - GRLIB_PP_APBADDR (0x80000200, 0xFFF)); + GRLIB_PP_APBADDR (addr, mask)); +} - grlib_ahbmpp_add (GRLIB_PP_ID (VENDOR_GAISLER, GAISLER_GRETH, 0, 0)); - grlib_apbpp_add (GRLIB_PP_ID (VENDOR_GAISLER, GAISLER_GRETH, 0, 6), - GRLIB_PP_APBADDR (0x80000B00, 0xFFF)); +const struct grlib_ipcore irqmp = { + irqmp_init, irqmp_reset, irqmp_read, irqmp_write, irqmp_add +}; + +/* ------------------- GPTIMER -----------------------*/ + +#define GPTIMER_SCALER 0x00 +#define GPTIMER_SCLOAD 0x04 +#define GPTIMER_CONFIG 0x08 +#define GPTIMER_TIMER1 0x10 +#define GPTIMER_RELOAD1 0x14 +#define GPTIMER_CTRL1 0x18 +#define GPTIMER_TIMER2 0x20 +#define GPTIMER_RELOAD2 0x24 +#define GPTIMER_CTRL2 0x28 + +#define NGPTIMERS 2 + +static uint32 gpt_irq; +static uint32 gpt_scaler; +static uint64 gpt_scaler_start; +static uint32 gpt_counter[NGPTIMERS]; +static uint32 gpt_reload[NGPTIMERS]; +static uint64 gpt_counter_start[NGPTIMERS]; +static uint32 gpt_ctrl[NGPTIMERS]; + +static void gpt_intr (int32 arg); + +static void +gpt_add_intr (int i) +{ + if (gpt_ctrl[i] & 1) + { + event (gpt_intr, i, + (uint64) (gpt_scaler + 1) * (uint64) ((uint64) gpt_counter[i] + + (uint64) 1)); + gpt_counter_start[i] = now (); + } +} +static void +gpt_intr (int32 i) +{ + gpt_counter[i] = -1; + if (gpt_ctrl[i] & 1) + { + if (gpt_ctrl[i] & 2) + { + gpt_counter[i] = gpt_reload[i]; + } + if (gpt_ctrl[i] & 8) + { + grlib_set_irq (gpt_irq + i); + } + gpt_add_intr (i); + } +} + +static void +gpt_init (void) +{ +} + +static void +gpt_add (int irq, uint32 addr, uint32 mask) +{ + grlib_apbpp_add (GRLIB_PP_ID (VENDOR_GAISLER, GAISLER_GPTIMER, 0, irq), + GRLIB_PP_APBADDR (addr, mask)); + gpt_irq = irq; +} + +static void +gpt_reset (void) +{ + gpt_counter[0] = 0xffffffff; + gpt_reload[0] = 0xffffffff; + gpt_scaler = 0xffff; + gpt_ctrl[0] = 0; + gpt_ctrl[1] = 0; + remove_event (gpt_intr, -1); + gpt_scaler_start = now (); + if (sis_verbose) + printf ("GPT started (period %d)\n\r", gpt_scaler + 1); +} + +static void +gpt_add_intr_all () +{ + int i; + + for (i = 0; i < NGPTIMERS; i++) + { + gpt_add_intr (i); + } +} + +static void +gpt_scaler_set (uint32 val) +{ + /* Mask for 16-bit scaler. */ + if (gpt_scaler != (val & 0x0ffff)) + { + gpt_scaler = val & 0x0ffff; + remove_event (gpt_intr, -1); + gpt_scaler_start = now (); + gpt_add_intr_all (); + } +} + +static void +gpt_ctrl_write (uint32 val, int i) +{ + if (val & 4) + { + /* Reload. */ + gpt_counter[i] = gpt_reload[i]; + } + if (val & 1) + { + gpt_ctrl[i] = val & 0xb; + remove_event (gpt_intr, i); + gpt_add_intr (i); + } + gpt_ctrl[i] = val & 0xb; +} + +static uint32 +gpt_counter_read (int i) +{ + if (gpt_ctrl[i] & 1) + return gpt_counter[i] - + ((now () - gpt_counter_start[i]) / (gpt_scaler + 1)); + else + return gpt_counter[i]; +} + +static uint32 +gpt_scaler_read () +{ + return gpt_scaler - ((now () - gpt_scaler_start) % (gpt_scaler + 1)); +} + +static int +gpt_read (uint32 addr, uint32 * data) +{ + int i; + + switch (addr & 0xff) + { + case GPTIMER_SCALER: /* 0x00 */ + *data = gpt_scaler_read (); + break; + + case GPTIMER_SCLOAD: /* 0x04 */ + *data = gpt_scaler; + break; + + case GPTIMER_CONFIG: /* 0x08 */ + *data = 0x100 | (gpt_irq << 3) | NGPTIMERS; + break; + + case GPTIMER_TIMER1: /* 0x10 */ + *data = gpt_counter_read (0); + break; + + case GPTIMER_RELOAD1: /* 0x14 */ + *data = gpt_reload[0]; + break; + + case GPTIMER_CTRL1: /* 0x18 */ + *data = gpt_ctrl[0]; + break; + + case GPTIMER_TIMER2: /* 0x20 */ + *data = gpt_counter_read (1); + break; + + case GPTIMER_RELOAD2: /* 0x24 */ + *data = gpt_reload[1]; + break; + + case GPTIMER_CTRL2: /* 0x28 */ + *data = gpt_ctrl[1]; + break; + + default: + *data = 0; + } +} + +static int +gpt_write (uint32 addr, uint32 * data, uint32 sz) +{ + int i; + + switch (addr & 0xff) + { + case GPTIMER_SCLOAD: /* 0x04 */ + gpt_scaler_set (*data); + break; + + case GPTIMER_TIMER1: /* 0x10 */ + gpt_counter[0] = *data; + remove_event (gpt_intr, 0); + gpt_add_intr (0); + break; + + case GPTIMER_RELOAD1: /* 0x14 */ + gpt_reload[0] = *data; + break; + + case GPTIMER_CTRL1: /* 0x18 */ + gpt_ctrl_write (*data, 0); + break; + + case GPTIMER_TIMER2: /* 0x20 */ + gpt_counter[1] = *data; + remove_event (gpt_intr, 1); + gpt_add_intr (1); + break; + + case GPTIMER_RELOAD2: /* 0x24 */ + gpt_reload[1] = *data; + break; + + case GPTIMER_CTRL2: /* 0x28 */ + gpt_ctrl_write (*data, 1); + break; + + } +} + +const struct grlib_ipcore gptimer = { + gpt_init, gpt_reset, gpt_read, gpt_write, gpt_add +}; + + +/* APBUART. */ + +#define APBUART_RXTX 0x00 +#define APBUART_STATUS 0x04 +#define APBUART_CTRL 0x08 + +/* Size of UART buffers (bytes). */ +#define UARTBUF 1024 + +/* Number of simulator ticks between flushing the UARTS. */ +/* For good performance, keep above 1000. */ +#define UART_FLUSH_TIME 5000 + +/* New uart defines. */ +#define UART_TX_TIME 1000 +#define UART_RX_TIME 1000 +#define UARTA_DR 0x1 +#define UARTA_SRE 0x2 +#define UARTA_HRE 0x4 +#define UARTA_OR 0x10 + +/* UART support variables. */ + +/* File descriptor for input file. */ +static int32 fd1, fd2; + +/* UART status register */ +static int32 Ucontrol; + +static unsigned char aq[UARTBUF], bq[UARTBUF]; +static int32 anum, aind = 0; +static int32 bnum, bind = 0; +static char wbufa[UARTBUF], wbufb[UARTBUF]; +static unsigned wnuma; +static unsigned wnumb; +static FILE *f1in, *f1out; +#ifdef HAVE_TERMIOS_H +static struct termios ioc1, ioc2, iocold1, iocold2; +#endif +#ifndef O_NONBLOCK +#define O_NONBLOCK 0 +#endif + +static int f1open = 0; + +static char uarta_sreg, uarta_hreg; +static uint32 uart_stat_reg; +static uint32 uarta_data; + +static int ifd1 = -1, ofd1 = -1; + +void +apbuart_init_stdio (void) +{ + if (dumbio) + return; +#ifdef HAVE_TERMIOS_H + if (ifd1 == 0 && f1open) + { + tcsetattr (0, TCSANOW, &ioc1); + tcflush (ifd1, TCIFLUSH); + } +#endif +} + +void +apbuart_restore_stdio (void) +{ + if (dumbio) + return; +#ifdef HAVE_TERMIOS_H + if (ifd1 == 0 && f1open && tty_setup) + tcsetattr (0, TCSANOW, &iocold1); +#endif +} + +#define DO_STDIO_READ( _fd_, _buf_, _len_ ) \ + ( dumbio || nouartrx ? (0) : read( _fd_, _buf_, _len_ ) ) + +static void +apbuart_init (void) +{ + f1in = stdin; + f1out = stdout; + if (uart_dev1[0] != 0) + { + if ((fd1 = open (uart_dev1, O_RDWR | O_NONBLOCK)) < 0) + { + printf ("Warning, couldn't open output device %s\n", uart_dev1); + } + else + { + if (sis_verbose) + printf ("serial port A on %s\n", uart_dev1); + f1in = f1out = fdopen (fd1, "r+"); + setbuf (f1out, NULL); + f1open = 1; + } + } + if (f1in) + ifd1 = fileno (f1in); + if (ifd1 == 0) + { + if (sis_verbose) + printf ("serial port A on stdin/stdout\n"); + if (!dumbio) + { +#ifdef HAVE_TERMIOS_H + tcgetattr (ifd1, &ioc1); + if (tty_setup) + { + iocold1 = ioc1; + ioc1.c_lflag &= ~(ICANON | ECHO); + ioc1.c_cc[VMIN] = 0; + ioc1.c_cc[VTIME] = 0; + } +#endif + } + f1open = 1; + } + + if (f1out) + { + ofd1 = fileno (f1out); + if (!dumbio && tty_setup && ofd1 == 1) + setbuf (f1out, NULL); + } + + wnuma = 0; +} + +static int +apbuart_read (uint32 addr, uint32 * data) +{ + unsigned tmp = 0; + + switch (addr & 0xff) + { + + case 0x00: /* UART 1 RX/TX */ +#ifndef _WIN32 +#ifdef FAST_UART + + if (aind < anum) + { + if ((aind + 1) < anum) + grlib_set_irq (3); + *data = (uint32) aq[aind++]; + return 0; + } + else + { + if (f1open) + anum = DO_STDIO_READ (ifd1, aq, UARTBUF); + else + anum = 0; + if (anum > 0) + { + aind = 0; + if ((aind + 1) < anum) + grlib_set_irq (3); + *data = (uint32) aq[aind++]; + return 0; + } + else + { + *data = (uint32) aq[aind]; + return 0; + } + } +#else + tmp = uarta_data; + uarta_data &= ~UART_DR; + uart_stat_reg &= ~UARTA_DR; + *data = tmp; + return 0; +#endif +#else + *data = 0; + return 0; +#endif + break; + + case 0x04: /* UART status register */ +#ifndef _WIN32 +#ifdef FAST_UART + + Ucontrol = 0; + if (aind < anum) + { + Ucontrol |= 0x00000001; + } + else + { + if (f1open) + anum = DO_STDIO_READ (ifd1, aq, UARTBUF); + else + anum = 0; + if (anum > 0) + { + Ucontrol |= 0x00000001; + aind = 0; + grlib_set_irq (3); + } + } + Ucontrol |= 0x00000006; + *data = Ucontrol; + return 0; +#else + *data = uart_stat_reg; + return 0; +#endif +#else + *data = 0x00060006; + return 0; +#endif + break; + case 0x08: /* UART control register */ + *data = 3; + return 0; + break; + default: + if (sis_verbose) + printf ("Read from unimplemented UART register (%x)\n", addr); + } + + *data = 0; + return 0; +} + +static int +apbuart_write (uint32 addr, uint32 * data, uint32 sz) +{ + unsigned char c; + + c = (unsigned char) *data; + switch (addr & 0xff) + { + + case 0x00: /* UART A */ +#ifdef FAST_UART + if (f1open) + { + if (wnuma < UARTBUF) + wbufa[wnuma++] = c; + else + { + while (wnuma) + { + wnuma -= fwrite (wbufa, 1, wnuma, f1out); + } + wbufa[wnuma++] = c; + } + } + grlib_set_irq (3); +#else + if (uart_stat_reg & UARTA_SRE) + { + uarta_sreg = c; + uart_stat_reg &= ~UARTA_SRE; + event (uarta_tx, 0, UART_TX_TIME); + } + else + { + uarta_hreg = c; + uart_stat_reg &= ~UARTA_HRE; + } +#endif + break; + + case 0x04: /* UART status register */ +#ifndef FAST_UART + uart_stat_reg &= 1; +#endif + break; + case 0x08: /* UART control register */ + break; + default: + if (sis_verbose) + printf ("Write to unimplemented UART register (%x)\n", addr); + } +} + +void +apbuart_flush (void) +{ + while (wnuma && f1open) + { + wnuma -= fwrite (wbufa, 1, wnuma, f1out); + } +} + +static void +uarta_tx (void) +{ + while (f1open) + { + while (fwrite (&uarta_sreg, 1, 1, f1out) != 1) + continue; + } + if (uart_stat_reg & UARTA_HRE) + { + uart_stat_reg |= UARTA_SRE; + } + else + { + uarta_sreg = uarta_hreg; + uart_stat_reg |= UARTA_HRE; + event (uarta_tx, 0, UART_TX_TIME); + } + grlib_set_irq (3); +} + +static void +uart_rx (int32 arg) +{ + char rxd; + int32 rsize = 0; + + + if (f1open) + rsize = DO_STDIO_READ (ifd1, &rxd, 1); + else + rsize = 0; + if (rsize > 0) + { + uarta_data = rxd; + if (uart_stat_reg & UARTA_DR) + { + uart_stat_reg |= UARTA_OR; + } + uart_stat_reg |= UARTA_DR; + grlib_set_irq (3); + } + event (uart_rx, 0, UART_RX_TIME); +} + +static void +uart_intr (int32 arg) +{ + uint32 tmp; + /* Check for UART interrupts every 1000 clk. */ + apbuart_read (APBUART_STATUS, &tmp); + apbuart_flush (); + event (uart_intr, 0, UART_FLUSH_TIME); +} + + +static void +uart_irq_start (void) +{ +#ifdef FAST_UART + event (uart_intr, 0, UART_FLUSH_TIME); +#else +#ifndef _WIN32 + event (uart_rx, 0, UART_RX_TIME); +#endif +#endif +} + +static void +apbuart_reset (void) +{ + wnuma = wnumb = 0; + anum = aind = bnum = bind = 0; + uart_stat_reg = UARTA_SRE | UARTA_HRE; + + uart_irq_start (); +} + +void +apbuart_close_port (void) +{ + if (f1open && f1in != stdin) + fclose (f1in); +} + +static void +apbuart_add (int irq, uint32 addr, uint32 mask) +{ + grlib_apbpp_add (GRLIB_PP_ID (VENDOR_GAISLER, GAISLER_APBUART, 1, irq), + GRLIB_PP_APBADDR (addr, mask)); +} + +const struct grlib_ipcore apbuart = { + apbuart_init, apbuart_reset, apbuart_read, apbuart_write, apbuart_add +}; + +/* ------------------- SRCTRL -----------------------*/ + +/* Store data in host byte order. MEM points to the beginning of the + emulated memory; WADDR contains the index the emulated memory, + DATA points to words in host byte order to be stored. SZ contains log(2) + of the number of bytes to retrieve, and can be 0 (1 byte), 1 (one half-word), + 2 (one word), or 3 (two words); WS should return the number of wait-states. */ + +void +grlib_store_bytes (char *mem, uint32 waddr, uint32 * data, int32 sz) +{ + if (sz == 2) + memcpy (&mem[waddr], data, 4); + else + switch (sz) + { + case 0: + waddr ^= arch->bswap; + mem[waddr] = *data & 0x0ff; + break; + case 1: + waddr ^= arch->bswap & 2; + *((uint16 *) & mem[waddr]) = (*data & 0x0ffff); + break; + case 3: + memcpy (&mem[waddr], data, 8); + break; + } +} + +static int +srctrl_write (uint32 addr, uint32 * data, uint32 sz) +{ + grlib_store_bytes (ramb, addr, data, sz); + return 1; +} + +static int +srctrl_read (uint32 addr, uint32 * data) +{ + memcpy (data, &ramb[addr & ~0x3], 4); + return 4; +} + +static void +srctrl_add (int irq, uint32 addr, uint32 mask) +{ + grlib_ahbspp_add (GRLIB_PP_ID (VENDOR_GAISLER, GAISLER_SRCTRL, 0, 0), + GRLIB_PP_AHBADDR (addr, mask, 1, 1, 2), 0, 0, 0); + if (sis_verbose) + printf ("RAM start: 0x%x, RAM size: %d K\n", + addr, ((~mask << 20) + 1) / 1024); +} + +const struct grlib_ipcore srctrl = { + NULL, NULL, srctrl_read, srctrl_write, srctrl_add +}; + +void +grlib_boot_init (void) +{ + uint32 tmp; + /* Generate 1 MHz RTC tick. */ +// apb_write (GPTIMER_SCALER, ebase.freq - 1); + tmp = ebase.freq - 1; + gpt_write (GPTIMER_SCLOAD, &tmp, 2); + tmp = -1; + gpt_write (GPTIMER_TIMER1, &tmp, 2); + gpt_write (GPTIMER_RELOAD1, &tmp, 2); + tmp = 7; + gpt_write (GPTIMER_CTRL1, &tmp, 2); } @@ -52,6 +52,9 @@ #define APBPP_START 0x800FF000 #define APBPP_END 0x800FFFFF +#define ROM_MASKPP ((~ROM_MASK >> 20) & 0xFFF) +#define RAM_MASKPP ((~RAM_MASK >> 20) & 0xFFF) + extern int grlib_apbpp_add (uint32 id, uint32 addr); extern int grlib_ahbmpp_add (uint32 id); extern int grlib_ahbspp_add (uint32 id, uint32 addr1, uint32 addr2, @@ -60,3 +63,39 @@ extern uint32 grlib_ahbpnp_read (uint32 addr); extern uint32 grlib_apbpnp_read (uint32 addr); extern void grlib_init (); extern uint32 rvtimer_read (int address, int cpu); + +struct grlib_ipcore +{ + void (*init) (void); + void (*reset) (void); + int (*read) (uint32 addr, uint32 * data); + int (*write) (uint32 addr, uint32 * data, uint32 size); + void (*add) (int irq, uint32 addr, uint32 mask); +}; + +struct grlib_buscore +{ + const struct grlib_ipcore *core; + uint32 start; + uint32 end; + uint32 mask; +}; + +extern void grlib_ahbs_add (const struct grlib_ipcore *core, int irq, + uint32 addr, uint32 mask); +extern void grlib_ahbm_add (const struct grlib_ipcore *core, int irq); +extern void grlib_apb_add (const struct grlib_ipcore *core, int irq, + uint32 addr, uint32 mask); +extern int grlib_read (uint32 addr, uint32 * data); +extern int grlib_write (uint32 addr, uint32 * data, uint32 sz); +extern void grlib_set_irq (int32 level); +extern void grlib_store_bytes (char *mem, uint32 waddr, uint32 * data, + int32 sz); +extern void grlib_boot_init (void); +extern void grlib_reset (void); +extern void apbuart_init_stdio (void); +extern void apbuart_restore_stdio (void); +extern void apbuart_close_port (void); +extern void apbuart_flush (void); +extern const struct grlib_ipcore gptimer, irqmp, apbuart, apbmst, + greth, leon3s, srctrl; @@ -20,7 +20,9 @@ */ #define ROM_START 0x00000000 +#define ROM_SIZE 0x01000000 #define RAM_START 0x40000000 +#define RAM_SIZE 0x02000000 #include "config.h" #include <errno.h> @@ -20,14 +20,10 @@ * Leon3 emulation, loosely based on erc32.c. */ -#ifdef WORDS_BIGENDIAN -#define EBT 0 -#else -#define EBT 3 -#endif - #define ROM_START 0x00000000 +#define ROM_SIZE 0x01000000 #define RAM_START 0x40000000 +#define RAM_SIZE 0x04000000 #include "config.h" #include <errno.h> @@ -45,141 +41,33 @@ /* APB registers */ #define APBSTART 0x80000000 -#define APBEND 0x80100000 /* Memory exception waitstates. */ #define MEM_EX_WS 1 -#define MOK 0 - -/* LEON3 APB register addresses. */ - -#define IRQMP_IPR 0x204 -#define IRQMP_IFR 0x208 -#define IRQMP_ICR 0x20C -#define IRQMP_ISR 0x210 -#define IRQMP_IBR 0x214 -#define IRQMP_IMR 0x240 -#define IRQMP_IMR1 0x244 -#define IRQMP_IMR2 0x248 -#define IRQMP_IMR3 0x24C -#define IRQMP_IFR0 0x280 -#define IRQMP_IFR1 0x284 -#define IRQMP_IFR2 0x288 -#define IRQMP_IFR3 0x28C -#define GPTIMER_SCALER 0x300 -#define GPTIMER_SCLOAD 0x304 -#define GPTIMER_CONFIG 0x308 -#define GPTIMER_TIMER1 0x310 -#define GPTIMER_RELOAD1 0x314 -#define GPTIMER_CTRL1 0x318 -#define GPTIMER_TIMER2 0x320 -#define GPTIMER_RELOAD2 0x324 -#define GPTIMER_CTRL2 0x328 - -#define APBUART_RXTX 0x100 -#define APBUART_STATUS 0x104 -#define APBUART_CTRL 0x108 - -/* Size of UART buffers (bytes). */ -#define UARTBUF 1024 - -/* Number of simulator ticks between flushing the UARTS. */ -/* For good performance, keep above 1000. */ -#define UART_FLUSH_TIME 3000 - -/* New uart defines. */ -#define UART_TX_TIME 1000 -#define UART_RX_TIME 1000 -#define UARTA_DR 0x1 -#define UARTA_SRE 0x2 -#define UARTA_HRE 0x4 -#define UARTA_OR 0x10 - -/* IRQMP registers. */ - -static uint32 irqmp_ipr; -static uint32 irqmp_ibr; -static uint32 irqmp_imr[NCPU]; -static uint32 irqmp_ifr[NCPU]; - -/* GPTIMER registers. */ - -#define NGPTIMERS 2 -#define GPTIMER_IRQ 8 - -static uint32 gpt_scaler; -static uint64 gpt_scaler_start; -static uint32 gpt_counter[NGPTIMERS]; -static uint32 gpt_reload[NGPTIMERS]; -static uint64 gpt_counter_start[NGPTIMERS]; -static uint32 gpt_ctrl[NGPTIMERS]; - -/* UART support variables. */ - -/* File descriptor for input file. */ -static int32 fd1, fd2; - -/* UART status register */ -static int32 Ucontrol; - -static unsigned char aq[UARTBUF], bq[UARTBUF]; -static int32 anum, aind = 0; -static int32 bnum, bind = 0; -static char wbufa[UARTBUF], wbufb[UARTBUF]; -static unsigned wnuma; -static unsigned wnumb; -static FILE *f1in, *f1out; -#ifdef HAVE_TERMIOS_H -static struct termios ioc1, ioc2, iocold1, iocold2; -#endif -#ifndef O_NONBLOCK -#define O_NONBLOCK 0 -#endif - -static int f1open = 0; - -static char uarta_sreg, uarta_hreg; -static uint32 uart_stat_reg; -static uint32 uarta_data; - /* Forward declarations. */ -static void mem_init (void); -static void close_port (void); -static void leon3_reset (void); -static void irqmp_intack (int level, int cpu); -static void chk_irq (void); -static int32 apb_read (uint32 addr, uint32 * data); -static int apb_write (uint32 addr, uint32 data); -static void port_init (void); -static uint32 grlib_read_uart (uint32 addr); -static void grlib_write_uart (uint32 addr, uint32 data); -static void flush_uart (void); -static void uarta_tx (void); -static void uart_rx (int32 arg); -static void uart_intr (int32 arg); -static void uart_irq_start (void); -static void gpt_intr (int32 arg); -static void gpt_init (void); -static void gpt_reset (void); -static void gpt_scaler_set (uint32 val); -static void timer_ctrl (uint32 val, int i); static char *get_mem_ptr (uint32 addr, uint32 size); -static void store_bytes (char *mem, uint32 waddr, - uint32 * data, int sz, int32 * ws); -static void gpt_add_intr (int i); -static void set_irq (int32 level); /* One-time init. */ static void init_sim (void) { + int i; + + for (i = 0; i < NCPU; i++) + grlib_ahbm_add (&leon3s, 0); + + grlib_ahbs_add (&apbmst, 0, APBSTART, 0xFFF); + grlib_ahbs_add (&srctrl, 0, RAM_START, RAM_MASKPP); + + grlib_apb_add (&apbuart, 3, APBSTART + 0x100, 0xFFF); + grlib_apb_add (&irqmp, 0, APBSTART + 0x200, 0xFFF); + grlib_apb_add (&gptimer, 8, APBSTART + 0x300, 0xFFF); + grlib_apb_add (&greth, 6, APBSTART + 0xB00, 0xFFF); + grlib_init (); - mem_init (); - port_init (); - gpt_init (); ebase.ramstart = RAM_START; } @@ -188,9 +76,7 @@ init_sim (void) static void reset (void) { - leon3_reset (); - uart_irq_start (); - gpt_reset (); + grlib_reset (); } /* IU error mode manager. */ @@ -201,943 +87,97 @@ error_mode (uint32 pc) } -/* Memory init. */ - -static void -mem_init (void) -{ - -/* Add AMBA P&P record for SRCTRL memory controller */ - - grlib_ahbspp_add (GRLIB_PP_ID (VENDOR_GAISLER, GAISLER_SRCTRL, 0, 0), - GRLIB_PP_AHBADDR (0x00000000, 0xE00, 1, 1, 2), - GRLIB_PP_AHBADDR (0x40000000, 0xC00, 1, 1, 2), - GRLIB_PP_AHBADDR (0x20000000, 0xE00, 0, 0, 2), 0); - if (sis_verbose) - printf ("RAM start: 0x%x, RAM size: %d K, ROM size: %d K\n", - RAM_START, (RAM_MASK + 1) / 1024, (ROM_MASK + 1) / 1024); -} - /* Flush ports when simulator stops. */ static void sim_halt (void) { #ifdef FAST_UART - flush_uart (); + apbuart_flush (); #endif } static void -close_port (void) -{ - if (f1open && f1in != stdin) - fclose (f1in); -} - -static void exit_sim (void) { - close_port (); -} - -static void -leon3_reset (void) -{ - int i; - - irqmp_ipr = 0; - for (i = 0; i < NCPU; i++) - { - irqmp_imr[i] = 0; - irqmp_ifr[i] = 0; - sregs[i].intack = irqmp_intack; - } - wnuma = wnumb = 0; - anum = aind = bnum = bind = 0; - - uart_stat_reg = UARTA_SRE | UARTA_HRE; - - gpt_counter[0] = 0xffffffff; - gpt_reload[0] = 0xffffffff; - gpt_scaler = 0xffff; - gpt_ctrl[0] = 0; - gpt_ctrl[1] = 0; - -} - -static void -irqmp_intack (int level, int cpu) -{ - int irq_test; - - if ((sis_verbose > 2) && (level != 10)) - printf ("%8" PRIu64 " cpu %d interrupt %d acknowledged\n", - ebase.simtime, cpu, level); - if (irqmp_ifr[cpu] & (1 << level)) - irqmp_ifr[cpu] &= ~(1 << level); - else - irqmp_ipr &= ~(1 << level); - chk_irq (); -} - -static void -chk_irq () -{ - int32 i, cpu; - uint32 itmp; - int old_irl; - - for (cpu = 0; cpu < ncpu; cpu++) - { - old_irl = ext_irl[cpu]; - itmp = ((irqmp_ipr | irqmp_ifr[cpu]) & irqmp_imr[cpu]) & 0x0fffe; - ext_irl[cpu] = 0; - if (itmp != 0) - { - for (i = 15; i > 0; i--) - { - if (((itmp >> i) & 1) != 0) - { - if ((sis_verbose > 2) && (i != old_irl)) - printf ("%8" PRIu64 " cpu %d irl: %d\n", - ebase.simtime, cpu, i); - ext_irl[cpu] = i; - break; - } - } - } - } -} - -static void -set_irq (int32 level) -{ - int i; - - if ((irqmp_ibr >> level) & 1) - for (i = 0; i < ncpu; i++) - irqmp_ifr[i] |= (1 << level); - else - irqmp_ipr |= (1 << level); - chk_irq (); -} - -static uint32 -gpt_counter_read (int i) -{ - if (gpt_ctrl[i] & 1) - return gpt_counter[i] - - ((now () - gpt_counter_start[i]) / (gpt_scaler + 1)); - else - return gpt_counter[i]; -} - -static uint32 -gpt_scaler_read () -{ - return gpt_scaler - ((now () - gpt_scaler_start) % (gpt_scaler + 1)); -} - -static int32 -apb_read (uint32 addr, uint32 * data) -{ - int i; - - switch (addr & 0xfff) - { - - case APBUART_RXTX: /* 0x100 */ - case APBUART_STATUS: /* 0x104 */ - *data = grlib_read_uart (addr); - break; - case APBUART_CTRL: /* 0x108 */ - *data = 3; - break; - - case IRQMP_IPR: /* 0x204 */ - *data = irqmp_ipr; - break; - - case IRQMP_IFR: /* 0x208 */ - *data = irqmp_ifr[0]; - break; - - case IRQMP_ISR: /* 0x210 */ - *data = ((ncpu - 1) << 28); - for (i = 0; i < ncpu; i++) - *data |= (sregs[i].pwd_mode << i); - break; - - case IRQMP_IBR: /* 0x214 */ - *data = irqmp_ibr; - break; - - case IRQMP_IMR: /* 0x240 */ - *data = irqmp_imr[0]; - break; - - case IRQMP_IMR1: /* 0x244 */ - *data = irqmp_imr[1]; - break; - - case IRQMP_IMR2: /* 0x248 */ - *data = irqmp_imr[2]; - break; - - case IRQMP_IMR3: /* 0x24C */ - *data = irqmp_imr[3]; - break; - - case IRQMP_IFR0: /* 0x280 */ - *data = irqmp_ifr[0]; - break; - - case IRQMP_IFR1: /* 0x284 */ - *data = irqmp_ifr[1]; - break; - - case IRQMP_IFR2: /* 0x288 */ - *data = irqmp_ifr[2]; - break; - - case IRQMP_IFR3: /* 0x28C */ - *data = irqmp_ifr[3]; - break; - - case GPTIMER_SCALER: /* 0x300 */ - *data = gpt_scaler_read (); - break; - - case GPTIMER_SCLOAD: /* 0x304 */ - *data = gpt_scaler; - break; - - case GPTIMER_CONFIG: /* 0x308 */ - *data = 0x100 | (GPTIMER_IRQ << 3) | NGPTIMERS; - break; - - case GPTIMER_TIMER1: /* 0x310 */ - *data = gpt_counter_read (0); - break; - - case GPTIMER_RELOAD1: /* 0x314 */ - *data = gpt_reload[0]; - break; - - case GPTIMER_CTRL1: /* 0x318 */ - *data = gpt_ctrl[0]; - break; - - case GPTIMER_TIMER2: /* 0x320 */ - *data = gpt_counter_read (1); - break; - - case GPTIMER_RELOAD2: /* 0x324 */ - *data = gpt_reload[1]; - break; - - case GPTIMER_CTRL2: /* 0x328 */ - *data = gpt_ctrl[1]; - break; - - default: - *data = 0; - if ((addr & 0xF00) == 0xB00) - *data = greth_read (addr); - else if (sis_verbose > 1) - printf ("%8" PRIu64 - " cpu %d APB read a: %08x, d: %08x unimplemented!\n", - ebase.simtime, cpu, addr, *data); - break; - } - - if (sis_verbose > 1) - if ((addr & 0xF00) != 0x100) - printf ("%8" PRIu64 " cpu %d APB read a: %08x, d: %08x\n", - ebase.simtime, cpu, addr, *data); - - return MOK; -} - -static int -apb_write (uint32 addr, uint32 data) -{ - int i; - - if (sis_verbose > 1) - if ((addr & 0xF00) != 0x100) - printf ("%8" PRIu64 " cpu %d APB write a: %08x, d: %08x\n", - ebase.simtime, cpu, addr, data); - switch (addr & 0xfff) - { - - case APBUART_RXTX: /* 0x100 */ - case APBUART_STATUS: /* 0x104 */ - grlib_write_uart (addr, data); - break; - case APBUART_CTRL: /* 0x108 */ - break; - - case IRQMP_IFR: /* 0x208 */ - irqmp_ifr[0] = data & 0xfffe; - chk_irq (); - break; - - case IRQMP_ICR: /* 0x20C */ - irqmp_ipr &= ~data & 0x0fffe; - chk_irq (); - break; - - case IRQMP_ISR: /* 0x210 */ - for (i = 0; i < ncpu; i++) - { - if ((data >> i) & 1) - { - if (sregs[i].pwd_mode) - { - sregs[i].simtime = ebase.simtime; - if (sis_verbose > 1) - printf ("%8" PRIu64 " cpu %d starting\n", ebase.simtime, - i); - sregs[i].pwdtime += ebase.simtime - sregs[i].pwdstart; - } - sregs[i].pwd_mode = 0; - } - } - break; - - case IRQMP_IBR: /* 0x214 */ - irqmp_ibr = data & 0xfffe; - break; - - case IRQMP_IMR: /* 0x240 */ - irqmp_imr[0] = data & 0x7ffe; - chk_irq (); - break; - - case IRQMP_IMR1: /* 0x244 */ - irqmp_imr[1] = data & 0x7ffe; - chk_irq (); - break; - - case IRQMP_IMR2: /* 0x248 */ - irqmp_imr[2] = data & 0x7ffe; - chk_irq (); - break; - - case IRQMP_IMR3: /* 0x24C */ - irqmp_imr[3] = data & 0x7ffe; - chk_irq (); - break; - - case IRQMP_IFR0: /* 0x280 */ - irqmp_ifr[0] = data & 0xfffe; - chk_irq (); - break; - - case IRQMP_IFR1: /* 0x284 */ - irqmp_ifr[1] = data & 0xfffe; - chk_irq (); - break; - - case IRQMP_IFR2: /* 0x288 */ - irqmp_ifr[2] = data & 0xfffe; - chk_irq (); - break; - - case IRQMP_IFR3: /* 0x28C */ - irqmp_ifr[3] = data & 0xfffe; - chk_irq (); - break; - - case GPTIMER_SCLOAD: /* 0x304 */ - gpt_scaler_set (data); - break; - - case GPTIMER_TIMER1: /* 0x310 */ - gpt_counter[0] = data; - remove_event (gpt_intr, 0); - gpt_add_intr (0); - break; - - case GPTIMER_RELOAD1: /* 0x314 */ - gpt_reload[0] = data; - break; - - case GPTIMER_CTRL1: /* 0x318 */ - timer_ctrl (data, 0); - break; - - case GPTIMER_TIMER2: /* 0x320 */ - gpt_counter[1] = data; - remove_event (gpt_intr, 1); - gpt_add_intr (1); - break; - - case GPTIMER_RELOAD2: /* 0x324 */ - gpt_reload[1] = data; - break; - - case GPTIMER_CTRL2: /* 0x328 */ - timer_ctrl (data, 1); - break; - - default: - if ((addr & 0xF00) == 0xB00) - greth_write (addr, data); - else if (sis_verbose) - printf ("%8" PRIu64 - " cpu %d APB write a: %08x, d: %08x unimplemented!\n", - ebase.simtime, cpu, addr, data); - break; - } - return MOK; -} - - -/* APBUART. */ - -static int ifd1 = -1, ofd1 = -1; - -static void -init_stdio (void) -{ - if (dumbio) - return; -#ifdef HAVE_TERMIOS_H - if (ifd1 == 0 && f1open) - { - tcsetattr (0, TCSANOW, &ioc1); - tcflush (ifd1, TCIFLUSH); - } -#endif -} - -static void -restore_stdio (void) -{ - if (dumbio) - return; -#ifdef HAVE_TERMIOS_H - if (ifd1 == 0 && f1open && tty_setup) - tcsetattr (0, TCSANOW, &iocold1); -#endif -} - -#define DO_STDIO_READ( _fd_, _buf_, _len_ ) \ - ( dumbio || nouartrx ? (0) : read( _fd_, _buf_, _len_ ) ) - -static void -port_init (void) -{ - f1in = stdin; - f1out = stdout; - if (uart_dev1[0] != 0) - { - if ((fd1 = open (uart_dev1, O_RDWR | O_NONBLOCK)) < 0) - { - printf ("Warning, couldn't open output device %s\n", uart_dev1); - } - else - { - if (sis_verbose) - printf ("serial port A on %s\n", uart_dev1); - f1in = f1out = fdopen (fd1, "r+"); - setbuf (f1out, NULL); - f1open = 1; - } - } - if (f1in) - ifd1 = fileno (f1in); - if (ifd1 == 0) - { - if (sis_verbose) - printf ("serial port A on stdin/stdout\n"); - if (!dumbio) - { -#ifdef HAVE_TERMIOS_H - tcgetattr (ifd1, &ioc1); - if (tty_setup) - { - iocold1 = ioc1; - ioc1.c_lflag &= ~(ICANON | ECHO); - ioc1.c_cc[VMIN] = 0; - ioc1.c_cc[VTIME] = 0; - } -#endif - } - f1open = 1; - } - - if (f1out) - { - ofd1 = fileno (f1out); - if (!dumbio && tty_setup && ofd1 == 1) - setbuf (f1out, NULL); - } - - wnuma = 0; - - grlib_apbpp_add (GRLIB_PP_ID (VENDOR_GAISLER, GAISLER_APBUART, 1, 3), - GRLIB_PP_APBADDR (0x80000100, 0xFFF)); -} - -static uint32 -grlib_read_uart (uint32 addr) -{ - unsigned tmp = 0; - - switch (addr & 0xff) - { - - case 0x00: /* UART 1 RX/TX */ -#ifndef _WIN32 -#ifdef FAST_UART - - if (aind < anum) - { - if ((aind + 1) < anum) - set_irq (3); - return (uint32) aq[aind++]; - } - else - { - if (f1open) - anum = DO_STDIO_READ (ifd1, aq, UARTBUF); - else - anum = 0; - if (anum > 0) - { - aind = 0; - if ((aind + 1) < anum) - set_irq (3); - return (uint32) aq[aind++]; - } - else - return (uint32) aq[aind]; - } -#else - tmp = uarta_data; - uarta_data &= ~UART_DR; - uart_stat_reg &= ~UARTA_DR; - return tmp; -#endif -#else - return 0; -#endif - break; - - case 0x04: /* UART status register */ -#ifndef _WIN32 -#ifdef FAST_UART - - Ucontrol = 0; - if (aind < anum) - { - Ucontrol |= 0x00000001; - } - else - { - if (f1open) - anum = DO_STDIO_READ (ifd1, aq, UARTBUF); - else - anum = 0; - if (anum > 0) - { - Ucontrol |= 0x00000001; - aind = 0; - set_irq (3); - } - } - Ucontrol |= 0x00000006; - return Ucontrol; -#else - return uart_stat_reg; -#endif -#else - return 0x00060006; -#endif - break; - default: - if (sis_verbose) - printf ("Read from unimplemented UART register (%x)\n", addr); - } - - return 0; -} - -static void -grlib_write_uart (uint32 addr, uint32 data) -{ - unsigned char c; - - c = (unsigned char) data; - switch (addr & 0xff) - { - - case 0x00: /* UART A */ -#ifdef FAST_UART - if (f1open) - { - if (wnuma < UARTBUF) - wbufa[wnuma++] = c; - else - { - while (wnuma) - { - wnuma -= fwrite (wbufa, 1, wnuma, f1out); - } - wbufa[wnuma++] = c; - } - } - set_irq (3); -#else - if (uart_stat_reg & UARTA_SRE) - { - uarta_sreg = c; - uart_stat_reg &= ~UARTA_SRE; - event (uarta_tx, 0, UART_TX_TIME); - } - else - { - uarta_hreg = c; - uart_stat_reg &= ~UARTA_HRE; - } -#endif - break; - - case 0x04: /* UART status register */ -#ifndef FAST_UART - uart_stat_reg &= 1; -#endif - break; - default: - if (sis_verbose) - printf ("Write to unimplemented UART register (%x)\n", addr); - } -} - -static void -flush_uart (void) -{ - while (wnuma && f1open) - { - wnuma -= fwrite (wbufa, 1, wnuma, f1out); - } -} - -static void -uarta_tx (void) -{ - while (f1open) - { - while (fwrite (&uarta_sreg, 1, 1, f1out) != 1) - continue; - } - if (uart_stat_reg & UARTA_HRE) - { - uart_stat_reg |= UARTA_SRE; - } - else - { - uarta_sreg = uarta_hreg; - uart_stat_reg |= UARTA_HRE; - event (uarta_tx, 0, UART_TX_TIME); - } - set_irq (3); -} - -static void -uart_rx (int32 arg) -{ - char rxd; - int32 rsize = 0; - - - if (f1open) - rsize = DO_STDIO_READ (ifd1, &rxd, 1); - else - rsize = 0; - if (rsize > 0) - { - uarta_data = rxd; - if (uart_stat_reg & UARTA_DR) - { - uart_stat_reg |= UARTA_OR; - } - uart_stat_reg |= UARTA_DR; - set_irq (3); - } - event (uart_rx, 0, UART_RX_TIME); -} - -static void -uart_intr (int32 arg) -{ - /* Check for UART interrupts every 1000 clk. */ - grlib_read_uart (APBUART_STATUS); - flush_uart (); - event (uart_intr, 0, UART_FLUSH_TIME); -} - - -static void -uart_irq_start (void) -{ -#ifdef FAST_UART - event (uart_intr, 0, UART_FLUSH_TIME); -#else -#ifndef _WIN32 - event (uart_rx, 0, UART_RX_TIME); -#endif -#endif -} - -/* GPTIMER. */ - -static void -gpt_add_intr (int i) -{ - if (gpt_ctrl[i] & 1) - { - event (gpt_intr, i, - (uint64) (gpt_scaler + 1) * (uint64) ((uint64) gpt_counter[i] + - (uint64) 1)); - gpt_counter_start[i] = now (); - } -} - -static void -gpt_intr (int32 i) -{ - gpt_counter[i] = -1; - if (gpt_ctrl[i] & 1) - { - if (gpt_ctrl[i] & 2) - { - gpt_counter[i] = gpt_reload[i]; - } - if (gpt_ctrl[i] & 8) - { - set_irq (GPTIMER_IRQ + i); - } - gpt_add_intr (i); - } -} - -static void -gpt_init (void) -{ - if (sis_verbose) - printf ("GPT started (period %d)\n\r", gpt_scaler + 1); - - grlib_apbpp_add (GRLIB_PP_ID (VENDOR_GAISLER, GAISLER_GPTIMER, 0, 8), - GRLIB_PP_APBADDR (0x80000300, 0xFFF)); -} - -static void -gpt_reset (void) -{ -// event (gpt_intr, 0, gpt_scaler + 1); - remove_event (gpt_intr, -1); - gpt_scaler_start = now (); -} - -static void -gpt_add_intr_all () -{ - int i; - - for (i = 0; i < NGPTIMERS; i++) - { - gpt_add_intr (i); - } -} - -static void -gpt_scaler_set (uint32 val) -{ - /* Mask for 16-bit scaler. */ - if (gpt_scaler != (val & 0x0ffff)) - { - gpt_scaler = val & 0x0ffff; - remove_event (gpt_intr, -1); - gpt_scaler_start = now (); - gpt_add_intr_all (); - } -} - -static void -timer_ctrl (uint32 val, int i) -{ - if (val & 4) - { - /* Reload. */ - gpt_counter[i] = gpt_reload[i]; - } - if (val & 1) - { - gpt_ctrl[i] = val & 0xb; - remove_event (gpt_intr, i); - gpt_add_intr (i); - } - gpt_ctrl[i] = val & 0xb; -} - -/* Store data in host byte order. MEM points to the beginning of the - emulated memory; WADDR contains the index the emulated memory, - DATA points to words in host byte order to be stored. SZ contains log(2) - of the number of bytes to retrieve, and can be 0 (1 byte), 1 (one half-word), - 2 (one word), or 3 (two words); WS should return the number of wait-states. */ - -static void -store_bytes (char *mem, uint32 waddr, uint32 * data, int32 sz, int32 * ws) -{ - if (sz == 2) - memcpy (&mem[waddr], data, 4); - else - switch (sz) - { - case 0: - waddr ^= arch->bswap; - mem[waddr] = *data & 0x0ff; - break; - case 1: - waddr ^= arch->bswap & 2; - *((uint16 *) & mem[waddr]) = (*data & 0x0ffff); - break; - case 3: - memcpy (&mem[waddr], data, 8); - break; - } - *ws = 0; + apbuart_close_port (); } - /* Memory emulation. */ static int -memory_iread (uint32 addr, uint32 * data, int32 * ws) -{ - if ((addr >= RAM_START) && (addr < RAM_END)) - { - memcpy (data, &ramb[addr & RAM_MASK], 4); - *ws = 0; - return 0; - } - else if (addr < ROM_END) - { - memcpy (data, &romb[addr], 4); - *ws = 0; - return 0; - } - - if (sis_verbose) - printf ("Memory exception at %x (illegal address)\n", addr); - *ws = MEM_EX_WS; - return 1; -} - -static int memory_read (uint32 addr, uint32 * data, int32 * ws) { int32 mexc; + *ws = 0; if ((addr >= RAM_START) && (addr < RAM_END)) { memcpy (data, &ramb[addr & RAM_MASK], 4); - *ws = 0; return 0; } - else if ((addr >= APBPP_START) && (addr <= APBPP_END)) + else if ((addr >= ROM_START) && (addr < ROM_END)) { - *data = grlib_apbpnp_read (addr); - if (sis_verbose > 1) - printf ("APB PP read a: %08x, d: %08x\n", addr, *data); - *ws = 4; + memcpy (data, &romb[addr & ROM_MASK], 4); + *ws = 2; return 0; } - else if ((addr >= APBSTART) && (addr < APBEND)) - { - mexc = apb_read (addr, data); - if (mexc) - *ws = MEM_EX_WS; - else - *ws = 0; - return mexc; - } - else if ((addr >= AHBPP_START) && (addr <= AHBPP_END)) + else { - *data = grlib_ahbpnp_read (addr); - if (sis_verbose > 1) - printf ("AHB PP read a: %08x, d: %08x\n", addr, *data); + mexc = grlib_read (addr, data); *ws = 4; - return 0; } - else if (addr < ROM_END) + + if (sis_verbose && mexc) { - memcpy (data, &romb[addr], 4); - *ws = 0; - return 0; + printf ("Memory exception at %x (illegal address)\n", addr); + *ws = MEM_EX_WS; } - - if (sis_verbose) - printf ("Memory exception at %x (illegal address)\n", addr); - *ws = MEM_EX_WS; - return 1; + return mexc; } static int memory_write (uint32 addr, uint32 * data, int32 sz, int32 * ws) { - uint32 byte_addr; - uint32 byte_mask; uint32 waddr; - uint32 *ram; int32 mexc; - int i; - int wphit[2]; + *ws = 0; if ((addr >= RAM_START) && (addr < RAM_END)) { waddr = addr & RAM_MASK; - store_bytes (ramb, waddr, data, sz, ws); + grlib_store_bytes (ramb, waddr, data, sz); return 0; } - else if ((addr >= APBSTART) && (addr < APBEND)) + else if ((addr >= ROM_START) && (addr < ROM_END)) { - if (sz != 2) - { - *ws = MEM_EX_WS; - return 1; - } - apb_write (addr, *data); - *ws = 0; + grlib_store_bytes (romb, addr, data, sz); return 0; - } - else if (addr < ROM_END) + else { - *ws = 0; - store_bytes (romb, addr, data, sz, ws); - return 0; + mexc = grlib_write (addr, data, sz); + *ws = 4; } - *ws = MEM_EX_WS; - return 1; + if (sis_verbose && mexc) + { + printf ("Memory exception at %x (illegal address)\n", addr); + *ws = MEM_EX_WS; + } + return mexc; } static char * get_mem_ptr (uint32 addr, uint32 size) { - if ((addr + size) < ROM_END) + if ((addr >= RAM_START) && ((addr + size) < RAM_END)) { - return &romb[addr]; + return &ramb[addr & RAM_MASK]; } - else if ((addr >= RAM_START) && ((addr + size) < RAM_END)) + else if ((addr >= ROM_START) && ((addr + size) < ROM_END)) { - return &ramb[addr & RAM_MASK]; + return &romb[addr & ROM_MASK]; } return NULL; @@ -1184,13 +224,7 @@ boot_init (void) int i; - /* Generate 1 MHz RTC tick. */ -// apb_write (GPTIMER_SCALER, ebase.freq - 1); - apb_write (GPTIMER_SCLOAD, ebase.freq - 1); - apb_write (GPTIMER_TIMER1, -1); - apb_write (GPTIMER_RELOAD1, -1); - apb_write (GPTIMER_CTRL1, 0x7); - + grlib_boot_init (); for (i = 0; i < NCPU; i++) { sregs[i].wim = 2; @@ -1208,14 +242,14 @@ const struct memsys leon3 = { error_mode, sim_halt, exit_sim, - init_stdio, - restore_stdio, - memory_iread, + apbuart_init_stdio, + apbuart_restore_stdio, + memory_read, memory_read, memory_write, sis_memory_write, sis_memory_read, boot_init, get_mem_ptr, - set_irq + grlib_set_irq }; @@ -42,12 +42,13 @@ #define NCPU 4 /* size of simulated memory */ -#define ROM_SIZE 0x01000000 #define ROM_MASK (ROM_SIZE - 1) #define ROM_END (ROM_START + ROM_SIZE) -#define RAM_SIZE 0x01000000 #define RAM_MASK (RAM_SIZE - 1) #define RAM_END (RAM_START + RAM_SIZE) +#define MAX_ROM_SIZE 0x01000000 +#define MAX_RAM_SIZE 0x04000000 +#define MAX_RAM_MASK (MAX_RAM_SIZE - 1) /* cache config */ |