/* * This file is part of SIS. * * SIS, SPARC instruction simulator V2.5 Copyright (C) 1995 Jiri Gaisler, * European Space Agency * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free * Software Foundation; either version 3 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program; if not, see . * * Leon3 emulation, loosely based on erc32.c. */ #define ROM_START 0x20000000 #define ROM_SIZE 0x01000000 #define RAM_START 0x80000000 #define RAM_SIZE 0x04000000 #include #include #include #include #include #ifdef HAVE_TERMIOS_H #include #endif #include #include #include "riscv.h" #include "grlib.h" #include "rv32dtb.h" #define PLIC_START 0x0C000000 #define PLIC_MASK 0xFFC #define NS16550_START 0x10000000 #define TESTSTART 0x00100000 #define CLINT_START 0x02000000 /* APB registers */ #define APBSTART 0xC0000000 /* Memory exception waitstates. */ #define MEM_EX_WS 1 /* Forward declarations. */ static char *get_mem_ptr (uint32 addr, uint32 size); /* One-time init. */ static void init_sim (void) { int i; for (i = 0; i < ncpu; i++) grlib_ahbm_add (&leon3s, 0); grlib_ahbs_add (&s5test, 0, TESTSTART, 0xFFF); grlib_ahbs_add (&clint, 0, CLINT_START, 0xFFF); grlib_ahbs_add (&plic, 0, PLIC_START, PLIC_MASK); grlib_ahbs_add (&ns16550, 10, NS16550_START, 0xFFF); grlib_ahbs_add (&srctrl, 0, ROM_START, ROM_MASKPP); grlib_ahbs_add (&sdctrl, 0, RAM_START, RAM_MASKPP); grlib_init (); memcpy (&romb[(ROM_END - 0x10000) & ROM_MASK], rv32_dtb, sizeof (rv32_dtb)); ebase.ramstart = RAM_START; } /* Power-on reset init. */ static void reset (void) { grlib_reset (); } /* IU error mode manager. */ static void error_mode (uint32 pc) { } /* Flush ports when simulator stops. */ static void sim_halt (void) { #ifdef FAST_UART apbuart_flush (); #endif } static void exit_sim (void) { apbuart_close_port (); } /* Memory emulation. */ static int memory_read (uint32 addr, uint32 * data, int32 * ws) { uint64 tmp; int32 mexc; int reg, cpuid; *ws = 0; /* bypass system bus decoding to speed-up RAM/ROM access */ if ((addr >= RAM_START) && (addr < RAM_END)) { memcpy (data, &ramb[addr & RAM_MASK], 4); return 0; } if ((addr >= ROM_START) && (addr < ROM_END)) { memcpy (data, &romb[addr & ROM_MASK], 4); return 0; } /* regular system bus access */ mexc = grlib_read (addr, data); *ws = 4; if (sis_verbose > 1) printf ("BUS read a: %08x, d: %08x\n", addr, *data); if (sis_verbose && mexc) { printf ("Memory exception at %x (illegal address)\n", addr); *ws = MEM_EX_WS; } return mexc; } static int memory_write (uint32 addr, uint32 * data, int32 sz, int32 * ws) { uint32 waddr; int32 mexc; uint64 tmp; int reg, cpuid; mexc = 0; *ws = 0; if ((addr >= RAM_START) && (addr < RAM_END)) { waddr = addr & RAM_MASK; grlib_store_bytes (ramb, waddr, data, sz); return 0; } else if ((addr >= ROM_START) && (addr < ROM_END)) { grlib_store_bytes (romb, addr, data, sz); return 0; } else { mexc = grlib_write (addr, data, sz); *ws = 4; } if (sis_verbose > 2) printf ("AHB write a: %08x, d: %08x\n", addr, *data); 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 >= RAM_START) && ((addr + size) < RAM_END)) { return &ramb[addr & RAM_MASK]; } else if ((addr >= ROM_START) && ((addr + size) < ROM_END)) { return &romb[addr & ROM_MASK]; } return NULL; } static int sis_memory_write (uint32 addr, const char *data, uint32 length) { char *mem; int32 ws; if ((mem = get_mem_ptr (addr, length)) != NULL) { memcpy (mem, data, length); return length; } else if (length == 4) memory_write (addr, (uint32 *) data, 2, &ws); return 0; } static int sis_memory_read (uint32 addr, char *data, uint32 length) { char *mem; int ws; if (length == 4) { memory_read (addr, (uint32 *) data, &ws); return 4; } if ((mem = get_mem_ptr (addr, length)) == NULL) return 0; memcpy (data, mem, length); return length; } static void boot_init (void) { int i; grlib_boot_init (); for (i = 0; i < ncpu; i++) { sregs[i].wim = 2; sregs[i].psr = 0xF30010e0; sregs[i].r[30] = RAM_END - (i * 0x20000); sregs[i].r[14] = sregs[i].r[30] - 96 * 4; sregs[i].cache_ctrl = 0x81000f; sregs[i].r[2] = sregs[i].r[30]; /* sp on RISCV-V */ sregs[i].r[11] = ROM_END - 0x10000; /* dtb on RISCV-V */ sregs[i].pwd_mode = 0; } } const struct memsys rv32 = { init_sim, reset, error_mode, sim_halt, exit_sim, apbuart_init_stdio, apbuart_restore_stdio, memory_read, memory_read, memory_write, sis_memory_write, sis_memory_read, boot_init, get_mem_ptr, grlib_set_irq };