diff --git a/.gitignore b/.gitignore index fca93ebb7..eae7c79e8 100644 --- a/.gitignore +++ b/.gitignore @@ -53,3 +53,6 @@ examples/asm/example/example examples/C/sum/sum examples/C/fir/fir synthDC/hdl/*.sv +linux/devicetree/debug/* +!linux/devicetree/debug/dumpdts.sh +*.dtb diff --git a/linux/add_wally_to_QEMU.patch b/linux/add_wally_to_QEMU.patch deleted file mode 100644 index 3b332f202..000000000 --- a/linux/add_wally_to_QEMU.patch +++ /dev/null @@ -1,645 +0,0 @@ -From 61696744ed1197c9435b85a4ac5610090faa3179 Mon Sep 17 00:00:00 2001 -From: bbracker -Date: Wed, 26 Jan 2022 14:43:11 +0000 -Subject: [PATCH] add Wally model to QEMU - ---- - configs/devices/riscv64-softmmu/default.mak | 1 + - hw/riscv/Kconfig | 7 + - hw/riscv/meson.build | 1 + - hw/riscv/wally.c | 501 ++++++++++++++++++++ - include/hw/riscv/wally.h | 79 +++ - 5 files changed, 589 insertions(+) - create mode 100644 hw/riscv/wally.c - create mode 100644 include/hw/riscv/wally.h - -diff --git a/configs/devices/riscv64-softmmu/default.mak b/configs/devices/riscv64-softmmu/default.mak -index bc69301fa4..396ebb82a1 100644 ---- a/configs/devices/riscv64-softmmu/default.mak -+++ b/configs/devices/riscv64-softmmu/default.mak -@@ -14,3 +14,4 @@ CONFIG_SIFIVE_U=y - CONFIG_RISCV_VIRT=y - CONFIG_MICROCHIP_PFSOC=y - CONFIG_SHAKTI_C=y -+CONFIG_WALLY=y -diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig -index d2d869aaad..a7ed6ae06f 100644 ---- a/hw/riscv/Kconfig -+++ b/hw/riscv/Kconfig -@@ -81,3 +81,10 @@ config SPIKE - select MSI_NONBROKEN - select RISCV_ACLINT - select SIFIVE_PLIC -+ -+config WALLY -+ bool -+ select SERIAL -+ select RISCV_ACLINT -+ select SIFIVE_PLIC -+ select SIFIVE_TEST -diff --git a/hw/riscv/meson.build b/hw/riscv/meson.build -index ab6cae57ea..b468f2c87c 100644 ---- a/hw/riscv/meson.build -+++ b/hw/riscv/meson.build -@@ -9,5 +9,6 @@ riscv_ss.add(when: 'CONFIG_SIFIVE_E', if_true: files('sifive_e.c')) - riscv_ss.add(when: 'CONFIG_SIFIVE_U', if_true: files('sifive_u.c')) - riscv_ss.add(when: 'CONFIG_SPIKE', if_true: files('spike.c')) - riscv_ss.add(when: 'CONFIG_MICROCHIP_PFSOC', if_true: files('microchip_pfsoc.c')) -+riscv_ss.add(when: 'CONFIG_WALLY', if_true: files('wally.c')) - - hw_arch += {'riscv': riscv_ss} -diff --git a/hw/riscv/wally.c b/hw/riscv/wally.c -new file mode 100644 -index 0000000000..25792dd04c ---- /dev/null -+++ b/hw/riscv/wally.c -@@ -0,0 +1,501 @@ -+/* -+ * QEMU RISC-V Wally Board -+ * Modified from Virt Board -+ * -+ * Copyright (c) 2017 SiFive, Inc. -+ * *** What should we say for copyright? -+ * -+ * RISC-V machine with 16550a UART and VirtIO MMIO -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2 or later, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope 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 . -+ */ -+ -+#include "qemu/osdep.h" -+#include "qemu/units.h" -+#include "qemu/error-report.h" -+#include "qapi/error.h" -+#include "hw/boards.h" -+#include "hw/loader.h" -+#include "hw/sysbus.h" -+#include "hw/qdev-properties.h" -+#include "hw/char/serial.h" -+#include "target/riscv/cpu.h" -+#include "hw/riscv/riscv_hart.h" -+#include "hw/riscv/wally.h" -+#include "hw/riscv/boot.h" -+#include "hw/riscv/numa.h" -+#include "hw/intc/riscv_aclint.h" -+#include "hw/intc/sifive_plic.h" -+#include "hw/misc/sifive_test.h" -+#include "chardev/char.h" -+#include "sysemu/device_tree.h" -+#include "sysemu/sysemu.h" -+#include "hw/pci/pci.h" -+#include "hw/pci-host/gpex.h" -+#include "hw/display/ramfb.h" -+ -+static const MemMapEntry wally_memmap[] = { -+ [WALLY_MROM] = { 0x1000, 0xf000 }, -+ [WALLY_CLINT] = { 0x2000000, 0x10000 }, -+ [WALLY_PLIC] = { 0xc000000, WALLY_PLIC_SIZE(WALLY_CPUS_MAX * 2) }, -+ [WALLY_UART0] = { 0x10000000, 0x100 }, -+ [WALLY_DRAM] = { 0x80000000, 0x0 }, -+}; -+ -+static void create_fdt_socket_cpus(WallyState *s, int socket, -+ char *clust_name, uint32_t *phandle, -+ bool is_32_bit, uint32_t *intc_phandles) -+{ -+ int cpu; -+ uint32_t cpu_phandle; -+ MachineState *mc = MACHINE(s); -+ char *name, *cpu_name, *core_name, *intc_name; -+ -+ for (cpu = s->soc[socket].num_harts - 1; cpu >= 0; cpu--) { -+ cpu_phandle = (*phandle)++; -+ -+ cpu_name = g_strdup_printf("/cpus/cpu@%d", -+ s->soc[socket].hartid_base + cpu); -+ qemu_fdt_add_subnode(mc->fdt, cpu_name); -+ qemu_fdt_setprop_string(mc->fdt, cpu_name, "mmu-type", -+ (is_32_bit) ? "riscv,sv32" : "riscv,sv48"); -+ name = riscv_isa_string(&s->soc[socket].harts[cpu]); -+ qemu_fdt_setprop_string(mc->fdt, cpu_name, "riscv,isa", name); -+ g_free(name); -+ qemu_fdt_setprop_string(mc->fdt, cpu_name, "compatible", "riscv"); -+ qemu_fdt_setprop_string(mc->fdt, cpu_name, "status", "okay"); -+ qemu_fdt_setprop_cell(mc->fdt, cpu_name, "reg", -+ s->soc[socket].hartid_base + cpu); -+ qemu_fdt_setprop_string(mc->fdt, cpu_name, "device_type", "cpu"); -+ riscv_socket_fdt_write_id(mc, mc->fdt, cpu_name, socket); -+ qemu_fdt_setprop_cell(mc->fdt, cpu_name, "phandle", cpu_phandle); -+ -+ intc_phandles[cpu] = (*phandle)++; -+ -+ intc_name = g_strdup_printf("%s/interrupt-controller", cpu_name); -+ qemu_fdt_add_subnode(mc->fdt, intc_name); -+ qemu_fdt_setprop_cell(mc->fdt, intc_name, "phandle", -+ intc_phandles[cpu]); -+ qemu_fdt_setprop_string(mc->fdt, intc_name, "compatible", -+ "riscv,cpu-intc"); -+ qemu_fdt_setprop(mc->fdt, intc_name, "interrupt-controller", NULL, 0); -+ qemu_fdt_setprop_cell(mc->fdt, intc_name, "#interrupt-cells", 1); -+ -+ core_name = g_strdup_printf("%s/core%d", clust_name, cpu); -+ qemu_fdt_add_subnode(mc->fdt, core_name); -+ qemu_fdt_setprop_cell(mc->fdt, core_name, "cpu", cpu_phandle); -+ -+ g_free(core_name); -+ g_free(intc_name); -+ g_free(cpu_name); -+ } -+} -+ -+static void create_fdt_socket_memory(WallyState *s, -+ const MemMapEntry *memmap, int socket) -+{ -+ char *mem_name; -+ uint64_t addr, size; -+ MachineState *mc = MACHINE(s); -+ -+ addr = memmap[WALLY_DRAM].base + riscv_socket_mem_offset(mc, socket); -+ size = riscv_socket_mem_size(mc, socket); -+ mem_name = g_strdup_printf("/memory@%lx", (long)addr); -+ qemu_fdt_add_subnode(mc->fdt, mem_name); -+ qemu_fdt_setprop_cells(mc->fdt, mem_name, "reg", -+ addr >> 32, addr, size >> 32, size); -+ qemu_fdt_setprop_string(mc->fdt, mem_name, "device_type", "memory"); -+ riscv_socket_fdt_write_id(mc, mc->fdt, mem_name, socket); -+ g_free(mem_name); -+} -+ -+static void create_fdt_socket_clint(WallyState *s, -+ const MemMapEntry *memmap, int socket, -+ uint32_t *intc_phandles) -+{ -+ int cpu; -+ char *clint_name; -+ uint32_t *clint_cells; -+ unsigned long clint_addr; -+ MachineState *mc = MACHINE(s); -+ static const char * const clint_compat[2] = { -+ "sifive,clint0", "riscv,clint0" -+ }; -+ -+ clint_cells = g_new0(uint32_t, s->soc[socket].num_harts * 4); -+ -+ for (cpu = 0; cpu < s->soc[socket].num_harts; cpu++) { -+ clint_cells[cpu * 4 + 0] = cpu_to_be32(intc_phandles[cpu]); -+ clint_cells[cpu * 4 + 1] = cpu_to_be32(IRQ_M_SOFT); -+ clint_cells[cpu * 4 + 2] = cpu_to_be32(intc_phandles[cpu]); -+ clint_cells[cpu * 4 + 3] = cpu_to_be32(IRQ_M_TIMER); -+ } -+ -+ clint_addr = memmap[WALLY_CLINT].base + (memmap[WALLY_CLINT].size * socket); -+ clint_name = g_strdup_printf("/soc/clint@%lx", clint_addr); -+ qemu_fdt_add_subnode(mc->fdt, clint_name); -+ qemu_fdt_setprop_string_array(mc->fdt, clint_name, "compatible", -+ (char **)&clint_compat, -+ ARRAY_SIZE(clint_compat)); -+ qemu_fdt_setprop_cells(mc->fdt, clint_name, "reg", -+ 0x0, clint_addr, 0x0, memmap[WALLY_CLINT].size); -+ qemu_fdt_setprop(mc->fdt, clint_name, "interrupts-extended", -+ clint_cells, s->soc[socket].num_harts * sizeof(uint32_t) * 4); -+ riscv_socket_fdt_write_id(mc, mc->fdt, clint_name, socket); -+ g_free(clint_name); -+ -+ g_free(clint_cells); -+} -+ -+ -+static void create_fdt_socket_plic(WallyState *s, -+ const MemMapEntry *memmap, int socket, -+ uint32_t *phandle, uint32_t *intc_phandles, -+ uint32_t *plic_phandles) -+{ -+ int cpu; -+ char *plic_name; -+ uint32_t *plic_cells; -+ unsigned long plic_addr; -+ MachineState *mc = MACHINE(s); -+ static const char * const plic_compat[2] = { -+ "sifive,plic-1.0.0", "riscv,plic0" -+ }; -+ -+ plic_cells = g_new0(uint32_t, s->soc[socket].num_harts * 4); -+ -+ for (cpu = 0; cpu < s->soc[socket].num_harts; cpu++) { -+ plic_cells[cpu * 4 + 0] = cpu_to_be32(intc_phandles[cpu]); -+ plic_cells[cpu * 4 + 1] = cpu_to_be32(IRQ_M_EXT); -+ plic_cells[cpu * 4 + 2] = cpu_to_be32(intc_phandles[cpu]); -+ plic_cells[cpu * 4 + 3] = cpu_to_be32(IRQ_S_EXT); -+ } -+ -+ plic_phandles[socket] = (*phandle)++; -+ plic_addr = memmap[WALLY_PLIC].base + (memmap[WALLY_PLIC].size * socket); -+ plic_name = g_strdup_printf("/soc/plic@%lx", plic_addr); -+ qemu_fdt_add_subnode(mc->fdt, plic_name); -+ qemu_fdt_setprop_cell(mc->fdt, plic_name, -+ "#address-cells", FDT_PLIC_ADDR_CELLS); -+ qemu_fdt_setprop_cell(mc->fdt, plic_name, -+ "#interrupt-cells", FDT_PLIC_INT_CELLS); -+ qemu_fdt_setprop_string_array(mc->fdt, plic_name, "compatible", -+ (char **)&plic_compat, -+ ARRAY_SIZE(plic_compat)); -+ qemu_fdt_setprop(mc->fdt, plic_name, "interrupt-controller", NULL, 0); -+ qemu_fdt_setprop(mc->fdt, plic_name, "interrupts-extended", -+ plic_cells, s->soc[socket].num_harts * sizeof(uint32_t) * 4); -+ qemu_fdt_setprop_cells(mc->fdt, plic_name, "reg", -+ 0x0, plic_addr, 0x0, memmap[WALLY_PLIC].size); -+ qemu_fdt_setprop_cell(mc->fdt, plic_name, "riscv,ndev", WALLYIO_NDEV); -+ riscv_socket_fdt_write_id(mc, mc->fdt, plic_name, socket); -+ qemu_fdt_setprop_cell(mc->fdt, plic_name, "phandle", -+ plic_phandles[socket]); -+ g_free(plic_name); -+ -+ g_free(plic_cells); -+} -+ -+static void create_fdt_sockets(WallyState *s, const MemMapEntry *memmap, -+ bool is_32_bit, uint32_t *phandle) -+{ -+ int socket; -+ char *clust_name; -+ uint32_t *intc_phandles; -+ MachineState *mc = MACHINE(s); -+ uint32_t xplic_phandles[MAX_NODES]; -+ -+ qemu_fdt_add_subnode(mc->fdt, "/cpus"); -+ qemu_fdt_setprop_cell(mc->fdt, "/cpus", "timebase-frequency", -+ RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ); -+ qemu_fdt_setprop_cell(mc->fdt, "/cpus", "#size-cells", 0x0); -+ qemu_fdt_setprop_cell(mc->fdt, "/cpus", "#address-cells", 0x1); -+ qemu_fdt_add_subnode(mc->fdt, "/cpus/cpu-map"); -+ -+ for (socket = (riscv_socket_count(mc) - 1); socket >= 0; socket--) { -+ clust_name = g_strdup_printf("/cpus/cpu-map/cluster%d", socket); -+ qemu_fdt_add_subnode(mc->fdt, clust_name); -+ -+ intc_phandles = g_new0(uint32_t, s->soc[socket].num_harts); -+ -+ create_fdt_socket_cpus(s, socket, clust_name, phandle, -+ is_32_bit, intc_phandles); -+ -+ create_fdt_socket_memory(s, memmap, socket); -+ -+ create_fdt_socket_clint(s, memmap, socket, intc_phandles); -+ -+ create_fdt_socket_plic(s, memmap, socket, phandle, -+ intc_phandles, xplic_phandles); -+ -+ g_free(intc_phandles); -+ g_free(clust_name); -+ } -+ riscv_socket_fdt_write_distance_matrix(mc, mc->fdt); -+} -+ -+static void create_fdt_uart(WallyState *s, const MemMapEntry *memmap) -+{ -+ char *name; -+ MachineState *mc = MACHINE(s); -+ -+ name = g_strdup_printf("/soc/uart@%lx", (long)memmap[WALLY_UART0].base); -+ qemu_fdt_add_subnode(mc->fdt, name); -+ qemu_fdt_setprop_string(mc->fdt, name, "compatible", "ns16550a"); -+ qemu_fdt_setprop_cells(mc->fdt, name, "reg", -+ 0x0, memmap[WALLY_UART0].base, -+ 0x0, memmap[WALLY_UART0].size); -+ qemu_fdt_setprop_cell(mc->fdt, name, "clock-frequency", 3686400); -+ qemu_fdt_setprop_cell(mc->fdt, name, "interrupts", UART0_IRQ); -+ -+ qemu_fdt_add_subnode(mc->fdt, "/chosen"); -+ qemu_fdt_setprop_string(mc->fdt, "/chosen", "stdout-path", name); -+ g_free(name); -+} -+ -+static void create_fdt(WallyState *s, const MemMapEntry *memmap, -+ uint64_t mem_size, const char *cmdline, bool is_32_bit) -+{ -+ MachineState *mc = MACHINE(s); -+ uint32_t phandle = 1; -+ -+ if (mc->dtb) { -+ mc->fdt = load_device_tree(mc->dtb, &s->fdt_size); -+ if (!mc->fdt) { -+ error_report("load_device_tree() failed"); -+ exit(1); -+ } -+ goto update_bootargs; -+ } else { -+ mc->fdt = create_device_tree(&s->fdt_size); -+ if (!mc->fdt) { -+ error_report("create_device_tree() failed"); -+ exit(1); -+ } -+ } -+ -+ qemu_fdt_setprop_string(mc->fdt, "/", "model", "riscv-wally,qemu"); -+ qemu_fdt_setprop_string(mc->fdt, "/", "compatible", "riscv-wally"); -+ qemu_fdt_setprop_cell(mc->fdt, "/", "#size-cells", 0x2); -+ qemu_fdt_setprop_cell(mc->fdt, "/", "#address-cells", 0x2); -+ -+ qemu_fdt_add_subnode(mc->fdt, "/soc"); -+ qemu_fdt_setprop(mc->fdt, "/soc", "ranges", NULL, 0); -+ qemu_fdt_setprop_string(mc->fdt, "/soc", "compatible", "simple-bus"); -+ qemu_fdt_setprop_cell(mc->fdt, "/soc", "#size-cells", 0x2); -+ qemu_fdt_setprop_cell(mc->fdt, "/soc", "#address-cells", 0x2); -+ -+ create_fdt_sockets(s, memmap, is_32_bit, &phandle); -+ create_fdt_uart(s, memmap); -+ -+update_bootargs: -+ if (cmdline) { -+ qemu_fdt_setprop_string(mc->fdt, "/chosen", "bootargs", cmdline); -+ } -+} -+ -+static void wally_machine_init(MachineState *machine) -+{ -+ const MemMapEntry *memmap = wally_memmap; -+ WallyState *s = RISCV_WALLY_MACHINE(machine); -+ MemoryRegion *system_memory = get_system_memory(); -+ MemoryRegion *mask_rom = g_new(MemoryRegion, 1); -+ char *plic_hart_config, *soc_name; -+ target_ulong start_addr = memmap[WALLY_DRAM].base; -+ target_ulong firmware_end_addr, kernel_start_addr; -+ uint32_t fdt_load_addr; -+ uint64_t kernel_entry; -+ DeviceState *mmio_plic, *wallyio_plic, *pcie_plic; -+ int i, base_hartid, hart_count; -+ -+ /* Check socket count limit */ -+ if (WALLY_SOCKETS_MAX < riscv_socket_count(machine)) { -+ error_report("number of sockets/nodes should be less than %d", -+ WALLY_SOCKETS_MAX); -+ exit(1); -+ } -+ -+ /* Initialize sockets */ -+ mmio_plic = wallyio_plic = pcie_plic = NULL; -+ for (i = 0; i < riscv_socket_count(machine); i++) { -+ if (!riscv_socket_check_hartids(machine, i)) { -+ error_report("discontinuous hartids in socket%d", i); -+ exit(1); -+ } -+ -+ base_hartid = riscv_socket_first_hartid(machine, i); -+ if (base_hartid < 0) { -+ error_report("can't find hartid base for socket%d", i); -+ exit(1); -+ } -+ -+ hart_count = riscv_socket_hart_count(machine, i); -+ if (hart_count < 0) { -+ error_report("can't find hart count for socket%d", i); -+ exit(1); -+ } -+ -+ soc_name = g_strdup_printf("soc%d", i); -+ object_initialize_child(OBJECT(machine), soc_name, &s->soc[i], -+ TYPE_RISCV_HART_ARRAY); -+ g_free(soc_name); -+ object_property_set_str(OBJECT(&s->soc[i]), "cpu-type", -+ machine->cpu_type, &error_abort); -+ object_property_set_int(OBJECT(&s->soc[i]), "hartid-base", -+ base_hartid, &error_abort); -+ object_property_set_int(OBJECT(&s->soc[i]), "num-harts", -+ hart_count, &error_abort); -+ sysbus_realize(SYS_BUS_DEVICE(&s->soc[i]), &error_abort); -+ -+ /* Per-socket CLINT */ -+ riscv_aclint_swi_create( -+ memmap[WALLY_CLINT].base + i * memmap[WALLY_CLINT].size, -+ base_hartid, hart_count, false); -+ riscv_aclint_mtimer_create( -+ memmap[WALLY_CLINT].base + i * memmap[WALLY_CLINT].size + -+ RISCV_ACLINT_SWI_SIZE, -+ RISCV_ACLINT_DEFAULT_MTIMER_SIZE, base_hartid, hart_count, -+ RISCV_ACLINT_DEFAULT_MTIMECMP, RISCV_ACLINT_DEFAULT_MTIME, -+ RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ, true); -+ -+ /* Per-socket PLIC hart topology configuration string */ -+ plic_hart_config = riscv_plic_hart_config_string(hart_count); -+ -+ /* Per-socket PLIC */ -+ s->plic[i] = sifive_plic_create( -+ memmap[WALLY_PLIC].base + i * memmap[WALLY_PLIC].size, -+ plic_hart_config, hart_count, base_hartid, -+ WALLY_PLIC_NUM_SOURCES, -+ WALLY_PLIC_NUM_PRIORITIES, -+ WALLY_PLIC_PRIORITY_BASE, -+ WALLY_PLIC_PENDING_BASE, -+ WALLY_PLIC_ENABLE_BASE, -+ WALLY_PLIC_ENABLE_STRIDE, -+ WALLY_PLIC_CONTEXT_BASE, -+ WALLY_PLIC_CONTEXT_STRIDE, -+ memmap[WALLY_PLIC].size); -+ g_free(plic_hart_config); -+ -+ /* Try to use different PLIC instance based device type */ -+ if (i == 0) { -+ mmio_plic = s->plic[i]; -+ } -+ } -+ -+ if (riscv_is_32bit(&s->soc[0])) { -+#if HOST_LONG_BITS == 64 -+ /* limit RAM size in a 32-bit system */ -+ if (machine->ram_size > 10 * GiB) { -+ machine->ram_size = 10 * GiB; -+ error_report("Limiting RAM size to 10 GiB"); -+ } -+#endif -+ } -+ -+ /* register system main memory (actual RAM) */ -+ memory_region_add_subregion(system_memory, memmap[WALLY_DRAM].base, -+ machine->ram); -+ -+ /* create device tree */ -+ create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline, -+ riscv_is_32bit(&s->soc[0])); -+ -+ /* boot rom */ -+ memory_region_init_rom(mask_rom, NULL, "wally_board.mrom", -+ memmap[WALLY_MROM].size, &error_fatal); -+ memory_region_add_subregion(system_memory, memmap[WALLY_MROM].base, -+ mask_rom); -+ -+ if (riscv_is_32bit(&s->soc[0])) { -+ firmware_end_addr = riscv_find_and_load_firmware(machine, -+ RISCV32_BIOS_BIN, start_addr, NULL); -+ } else { -+ firmware_end_addr = riscv_find_and_load_firmware(machine, -+ RISCV64_BIOS_BIN, start_addr, NULL); -+ } -+ -+ if (machine->kernel_filename) { -+ kernel_start_addr = riscv_calc_kernel_start_addr(&s->soc[0], -+ firmware_end_addr); -+ -+ kernel_entry = riscv_load_kernel(machine->kernel_filename, -+ kernel_start_addr, NULL); -+ -+ if (machine->initrd_filename) { -+ hwaddr start; -+ hwaddr end = riscv_load_initrd(machine->initrd_filename, -+ machine->ram_size, kernel_entry, -+ &start); -+ qemu_fdt_setprop_cell(machine->fdt, "/chosen", -+ "linux,initrd-start", start); -+ qemu_fdt_setprop_cell(machine->fdt, "/chosen", "linux,initrd-end", -+ end); -+ } -+ } else { -+ /* -+ * If dynamic firmware is used, it doesn't know where is the next mode -+ * if kernel argument is not set. -+ */ -+ kernel_entry = 0; -+ } -+ -+ /* Compute the fdt load address in dram */ -+ fdt_load_addr = riscv_load_fdt(memmap[WALLY_DRAM].base, -+ machine->ram_size, machine->fdt); -+ /* load the reset vector */ -+ riscv_setup_rom_reset_vec(machine, &s->soc[0], start_addr, -+ wally_memmap[WALLY_MROM].base, -+ wally_memmap[WALLY_MROM].size, kernel_entry, -+ fdt_load_addr, machine->fdt); -+ -+ serial_mm_init(system_memory, memmap[WALLY_UART0].base, -+ 0, qdev_get_gpio_in(DEVICE(mmio_plic), UART0_IRQ), 399193, -+ serial_hd(0), DEVICE_LITTLE_ENDIAN); -+} -+ -+static void wally_machine_instance_init(Object *obj) -+{ -+} -+ -+static void wally_machine_class_init(ObjectClass *oc, void *data) -+{ -+ MachineClass *mc = MACHINE_CLASS(oc); -+ -+ mc->desc = "Wally SoC"; -+ mc->init = wally_machine_init; -+ mc->max_cpus = WALLY_CPUS_MAX; -+ mc->default_cpu_type = TYPE_RISCV_CPU_BASE; -+ mc->pci_allow_0_address = true; -+ mc->possible_cpu_arch_ids = riscv_numa_possible_cpu_arch_ids; -+ mc->cpu_index_to_instance_props = riscv_numa_cpu_index_to_props; -+ mc->get_default_cpu_node_id = riscv_numa_get_default_cpu_node_id; -+ mc->numa_mem_supported = false; -+ mc->default_ram_id = "wally_board.ram"; -+ -+ machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE); -+} -+ -+static const TypeInfo wally_machine_typeinfo = { -+ .name = MACHINE_TYPE_NAME("wally"), -+ .parent = TYPE_MACHINE, -+ .class_init = wally_machine_class_init, -+ .instance_init = wally_machine_instance_init, -+ .instance_size = sizeof(WallyState), -+}; -+ -+static void wally_machine_init_register_types(void) -+{ -+ type_register_static(&wally_machine_typeinfo); -+} -+ -+type_init(wally_machine_init_register_types) -diff --git a/include/hw/riscv/wally.h b/include/hw/riscv/wally.h -new file mode 100644 -index 0000000000..80f2cc15dc ---- /dev/null -+++ b/include/hw/riscv/wally.h -@@ -0,0 +1,79 @@ -+/* -+ * QEMU RISC-V Wally machine interface -+ * Modified from VirtIO model -+ * -+ * Copyright (c) 2017 SiFive, Inc. -+ * *** What should we say for copyright? -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms and conditions of the GNU General Public License, -+ * version 2 or later, as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope 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 . -+ */ -+ -+#ifndef HW_RISCV_WALLY_H -+#define HW_RISCV_WALLY_H -+ -+#include "hw/riscv/riscv_hart.h" -+#include "hw/sysbus.h" -+#include "qom/object.h" -+ -+#define WALLY_CPUS_MAX 8 -+#define WALLY_SOCKETS_MAX 8 -+ -+#define TYPE_RISCV_WALLY_MACHINE MACHINE_TYPE_NAME("wally") -+typedef struct WallyState WallyState; -+DECLARE_INSTANCE_CHECKER(WallyState, RISCV_WALLY_MACHINE, -+ TYPE_RISCV_WALLY_MACHINE) -+ -+struct WallyState { -+ /*< private >*/ -+ MachineState parent; -+ -+ /*< public >*/ -+ RISCVHartArrayState soc[WALLY_SOCKETS_MAX]; -+ DeviceState *plic[WALLY_SOCKETS_MAX]; -+ -+ int fdt_size; -+ bool have_aclint; -+}; -+ -+enum { -+ WALLY_MROM, -+ WALLY_CLINT, -+ WALLY_PLIC, -+ WALLY_UART0, -+ WALLY_DRAM, -+}; -+ -+enum { -+ UART0_IRQ = 10, -+ WALLYIO_NDEV = 0x35 /* Arbitrary maximum number of interrupts */ -+}; -+ -+#define WALLY_PLIC_NUM_SOURCES 127 -+#define WALLY_PLIC_NUM_PRIORITIES 7 -+#define WALLY_PLIC_PRIORITY_BASE 0x04 -+#define WALLY_PLIC_PENDING_BASE 0x1000 -+#define WALLY_PLIC_ENABLE_BASE 0x2000 -+#define WALLY_PLIC_ENABLE_STRIDE 0x80 -+#define WALLY_PLIC_CONTEXT_BASE 0x200000 -+#define WALLY_PLIC_CONTEXT_STRIDE 0x1000 -+#define WALLY_PLIC_SIZE(__num_context) \ -+ (WALLY_PLIC_CONTEXT_BASE + (__num_context) * WALLY_PLIC_CONTEXT_STRIDE) -+ -+#define FDT_PCI_ADDR_CELLS 3 -+#define FDT_PCI_INT_CELLS 1 -+#define FDT_PLIC_ADDR_CELLS 0 -+#define FDT_PLIC_INT_CELLS 1 -+#define FDT_INT_MAP_WIDTH (FDT_PCI_ADDR_CELLS + FDT_PCI_INT_CELLS + 1 + \ -+ FDT_PLIC_ADDR_CELLS + FDT_PLIC_INT_CELLS) -+ -+#endif --- -2.27.0 - diff --git a/linux/buildroot-config-src/main.config b/linux/buildroot-config-src/main.config index 438d3f368..060c8892e 100644 --- a/linux/buildroot-config-src/main.config +++ b/linux/buildroot-config-src/main.config @@ -1,8 +1,13 @@ # # Automatically generated file; DO NOT EDIT. -# Buildroot -g73f9753-dirty Configuration +# Buildroot 2021.05 Configuration # BR2_HAVE_DOT_CONFIG=y +BR2_HOST_GCC_AT_LEAST_4_9=y +BR2_HOST_GCC_AT_LEAST_5=y +BR2_HOST_GCC_AT_LEAST_6=y +BR2_HOST_GCC_AT_LEAST_7=y +BR2_HOST_GCC_AT_LEAST_8=y # # Target options @@ -101,7 +106,6 @@ BR2_ENABLE_DEBUG=y # BR2_DEBUG_1 is not set # BR2_DEBUG_2 is not set BR2_DEBUG_3=y -# BR2_ENABLE_RUNTIME_DEBUG is not set # BR2_STRIP_strip is not set # BR2_OPTIMIZE_0 is not set # BR2_OPTIMIZE_1 is not set @@ -165,11 +169,9 @@ BR2_KERNEL_HEADERS_AS_KERNEL=y # BR2_KERNEL_HEADERS_5_10 is not set # BR2_KERNEL_HEADERS_5_11 is not set # BR2_KERNEL_HEADERS_5_12 is not set -# BR2_KERNEL_HEADERS_5_13 is not set # BR2_KERNEL_HEADERS_VERSION is not set # BR2_KERNEL_HEADERS_CUSTOM_TARBALL is not set # BR2_KERNEL_HEADERS_CUSTOM_GIT is not set -# BR2_PACKAGE_HOST_LINUX_HEADERS_CUSTOM_5_13 is not set # BR2_PACKAGE_HOST_LINUX_HEADERS_CUSTOM_5_12 is not set # BR2_PACKAGE_HOST_LINUX_HEADERS_CUSTOM_5_11 is not set BR2_PACKAGE_HOST_LINUX_HEADERS_CUSTOM_5_10=y @@ -250,7 +252,6 @@ BR2_BINUTILS_EXTRA_CONFIG_OPTIONS="" # BR2_GCC_VERSION_8_X is not set # BR2_GCC_VERSION_9_X is not set BR2_GCC_VERSION_10_X=y -# BR2_GCC_VERSION_11_X is not set BR2_GCC_VERSION="10.3.0" BR2_EXTRA_GCC_CONFIG_OPTIONS="" # BR2_TOOLCHAIN_BUILDROOT_CXX is not set @@ -368,10 +369,7 @@ BR2_TARGET_GENERIC_PASSWD_METHOD="sha-256" BR2_INIT_BUSYBOX=y # BR2_INIT_SYSV is not set # BR2_INIT_OPENRC is not set - -# -# systemd needs a glibc toolchain w/ SSP, headers >= 3.10, host and target gcc >= 5 -# +# BR2_INIT_SYSTEMD is not set # BR2_INIT_NONE is not set # BR2_ROOTFS_DEVICE_CREATION_STATIC is not set BR2_ROOTFS_DEVICE_CREATION_DYNAMIC_DEVTMPFS=y @@ -656,7 +654,6 @@ BR2_PACKAGE_GDB_ARCH_SUPPORTS=y # BR2_PACKAGE_IOZONE is not set # BR2_PACKAGE_KTAP is not set # BR2_PACKAGE_LATENCYTOP is not set -# BR2_PACKAGE_LIBBPF is not set # BR2_PACKAGE_LMBENCH is not set BR2_PACKAGE_LTP_TESTSUITE_ARCH_SUPPORTS=y # BR2_PACKAGE_LTP_TESTSUITE is not set @@ -668,7 +665,6 @@ BR2_PACKAGE_LTP_TESTSUITE_ARCH_SUPPORTS=y # BR2_PACKAGE_NETSNIFF_NG is not set # BR2_PACKAGE_NMON is not set # BR2_PACKAGE_PAX_UTILS is not set -# BR2_PACKAGE_POKE is not set # BR2_PACKAGE_PV is not set # BR2_PACKAGE_RAMSMP is not set # BR2_PACKAGE_RAMSPEED is not set @@ -950,10 +946,6 @@ BR2_PACKAGE_NETSURF_ARCH_SUPPORTS=y # apitrace needs a toolchain w/ C++, wchar, dynamic library, threads, gcc >= 4.9 # -# -# mupdf needs a toolchain w/ C++, gcc >= 4.8 -# - # # vte needs a toolchain w/ wchar, threads, C++, gcc >= 4.8 # @@ -1161,10 +1153,6 @@ BR2_PACKAGE_FLASHROM_ARCH_SUPPORTS=y # BR2_PACKAGE_USB_MODESWITCH is not set # BR2_PACKAGE_USB_MODESWITCH_DATA is not set -# -# usbguard needs a toolchain w/ C++, threads, dynamic library, gcc >= 4.8 -# - # # usbmount requires udev to be enabled # @@ -1185,24 +1173,19 @@ BR2_PACKAGE_FLASHROM_ARCH_SUPPORTS=y BR2_PACKAGE_HOST_ERLANG_ARCH_SUPPORTS=y # BR2_PACKAGE_EXECLINE is not set # BR2_PACKAGE_FICL is not set -# BR2_PACKAGE_GUILE is not set # BR2_PACKAGE_HASERL is not set # BR2_PACKAGE_JANET is not set # BR2_PACKAGE_JIMTCL is not set # BR2_PACKAGE_LUA is not set BR2_PACKAGE_PROVIDES_HOST_LUAINTERPRETER="host-lua" # BR2_PACKAGE_MICROPYTHON is not set -# BR2_PACKAGE_MOARVM is not set BR2_PACKAGE_HOST_MONO_ARCH_SUPPORTS=y BR2_PACKAGE_HOST_OPENJDK_BIN_ARCH_SUPPORTS=y # BR2_PACKAGE_PERL is not set # BR2_PACKAGE_PHP is not set # BR2_PACKAGE_PYTHON is not set # BR2_PACKAGE_PYTHON3 is not set - -# -# quickjs needs a glibc or musl toolchain w/ gcc >= 4.9, host gcc >= 4.9, dynamic library -# +# BR2_PACKAGE_QUICKJS is not set # BR2_PACKAGE_RUBY is not set # BR2_PACKAGE_TCL is not set @@ -1928,7 +1911,6 @@ BR2_PACKAGE_LIBCAMERA_ARCH_SUPPORTS=y # czmq needs a toolchain w/ C++, threads # # BR2_PACKAGE_DAQ is not set -# BR2_PACKAGE_DAQ3 is not set # BR2_PACKAGE_DAVICI is not set # BR2_PACKAGE_ENET is not set @@ -2024,7 +2006,6 @@ BR2_PACKAGE_LIBCAMERA_ARCH_SUPPORTS=y # # libpjsip needs a toolchain w/ C++, threads # -# BR2_PACKAGE_LIBPSL is not set # BR2_PACKAGE_LIBRELP is not set # BR2_PACKAGE_LIBRSYNC is not set # BR2_PACKAGE_LIBSHAIRPLAY is not set @@ -2167,7 +2148,6 @@ BR2_PACKAGE_LIBCAMERA_ARCH_SUPPORTS=y # # bctoolbox needs a toolchain w/ C++, threads # -# BR2_PACKAGE_BDWGC is not set # # belr needs a toolchain w/ threads, C++ @@ -2260,8 +2240,6 @@ BR2_PACKAGE_LIBABSEIL_CPP_ARCH_SUPPORTS=y # libabseil-cpp needs a toolchain w/ gcc >= 4.9, C++, threads, dynamic library # # BR2_PACKAGE_LIBARGTABLE2 is not set -BR2_PACKAGE_LIBATOMIC_OPS_ARCH_SUPPORTS=y -# BR2_PACKAGE_LIBATOMIC_OPS is not set # BR2_PACKAGE_LIBAVL is not set # BR2_PACKAGE_LIBB64 is not set # BR2_PACKAGE_LIBBACKTRACE is not set @@ -2317,7 +2295,6 @@ BR2_PACKAGE_LIBNSPR_ARCH_SUPPORT=y # BR2_PACKAGE_LIBPTHREAD_STUBS is not set # BR2_PACKAGE_LIBPTHSEM is not set # BR2_PACKAGE_LIBPWQUALITY is not set -# BR2_PACKAGE_LIBQB is not set # # libsigc++ needs a toolchain w/ C++, gcc >= 4.8 @@ -3063,7 +3040,6 @@ BR2_PACKAGE_INITSCRIPTS=y # # sdbusplus needs systemd and a toolchain w/ C++, gcc >= 7 # -# BR2_PACKAGE_SEATD is not set # BR2_PACKAGE_SMACK is not set # @@ -3147,7 +3123,6 @@ BR2_TARGET_OPENSBI_INSTALL_JUMP_IMG=y # BR2_PACKAGE_HOST_ANDROID_TOOLS is not set # BR2_PACKAGE_HOST_ASN1C is not set # BR2_PACKAGE_HOST_BABELTRACE2 is not set -# BR2_PACKAGE_HOST_BMAP_TOOLS is not set # BR2_PACKAGE_HOST_BTRFS_PROGS is not set # BR2_PACKAGE_HOST_CHECKPOLICY is not set # BR2_PACKAGE_HOST_CHECKSEC is not set @@ -3155,12 +3130,10 @@ BR2_TARGET_OPENSBI_INSTALL_JUMP_IMG=y # BR2_PACKAGE_HOST_CRAMFS is not set # BR2_PACKAGE_HOST_CRYPTSETUP is not set # BR2_PACKAGE_HOST_DBUS_PYTHON is not set - -# -# host dfu-util needs a toolchain w/ host gcc >= 4.9 -# +# BR2_PACKAGE_HOST_DFU_UTIL is not set # BR2_PACKAGE_HOST_DOS2UNIX is not set # BR2_PACKAGE_HOST_DOSFSTOOLS is not set +# BR2_PACKAGE_HOST_DOXYGEN is not set # BR2_PACKAGE_HOST_DTC is not set BR2_PACKAGE_HOST_E2FSPROGS=y # BR2_PACKAGE_HOST_E2TOOLS is not set @@ -3197,10 +3170,7 @@ BR2_PACKAGE_HOST_KMOD=y # BR2_PACKAGE_HOST_MTD is not set # BR2_PACKAGE_HOST_MTOOLS is not set # BR2_PACKAGE_HOST_ODB is not set - -# -# host openocd needs a toolchain w/ host gcc >= 4.9 -# +# BR2_PACKAGE_HOST_OPENOCD is not set # BR2_PACKAGE_HOST_OPKG_UTILS is not set # BR2_PACKAGE_HOST_PARTED is not set BR2_PACKAGE_HOST_PATCHELF=y @@ -3225,10 +3195,7 @@ BR2_PACKAGE_HOST_QEMU_SYSTEM_MODE=y # BR2_PACKAGE_HOST_QEMU_LINUX_USER_MODE is not set # BR2_PACKAGE_HOST_QEMU_VDE2 is not set # BR2_PACKAGE_HOST_QEMU_VIRTFS is not set - -# -# USB passthrough support needs a toolchain w/ host gcc >= 4.9 -# +# BR2_PACKAGE_HOST_QEMU_USB is not set # BR2_PACKAGE_HOST_QORIQ_RCW is not set # BR2_PACKAGE_HOST_RAUC is not set BR2_PACKAGE_HOST_RUSTC_ARCH_SUPPORTS=y diff --git a/linux/buildroot-config-src/make-buildroot.sh b/linux/buildroot-config-src/make-buildroot.sh deleted file mode 100755 index 841db1ba4..000000000 --- a/linux/buildroot-config-src/make-buildroot.sh +++ /dev/null @@ -1,3 +0,0 @@ -cp main.config ../buildroot/.config -cd ../buildroot -make diff --git a/linux/buildroot-scripts/start-buildroot-session.sh b/linux/buildroot-scripts/start-buildroot-session.sh new file mode 100755 index 000000000..f93815b6c --- /dev/null +++ b/linux/buildroot-scripts/start-buildroot-session.sh @@ -0,0 +1,80 @@ +script_dir=$(readlink -f ./) +personal_config=$(readlink -f ../buildroot-config-src) +shared_config=$RISCV/buildroot-config-src + +if [ -d "$shared_config" ]; then + echo "Hold the horses, friend!" >&2 + echo "There is already a buildroot-config-src folder in \$RISCV" >&2 + if [ ! -f "$shared_config/.owner" ]; then + echo "Oy vey -- it was improperly created too!" >&2 + echo "I see no .owner file in it!" >&2 + echo "Maybe just delete it." >&2 + exit 1 + fi + owner=$(cat $shared_config/.owner) + echo "It was created by $owner." >&2 + echo "Please contact them before overwriting their source files." >&2 + exit 1 +fi +echo "Starting new buildroot session" +# Copy configs to shared location +echo "Elevate permissions to copy ../buildroot-config-src to \$RISCV" +sudo cp -r "$personal_config" "$shared_config" +sudo chown -R cad $shared_config +# Document who created these configs +whoami>.owner +sudo mv .owner $shared_config +# Copy over main.config +echo "Copying main.config to buildroot/.config." +sudo cp $shared_config/main.config $RISCV/buildroot/.config +sudo chown cad $RISCV/buildroot/.config + +echo "==============================================" +echo "I'm about to sign you in as cad." +echo "" +echo "You can go straight to the \$RISCV/buildroot" +echo "and run \`make\` if you want." +echo "" +echo "You can also run:" +echo " * \`make menuconfig\`" +echo " * \`make linux-menuconfig\`" +echo " * \`make busybox-menuconfig\`" +echo "but if you do, you have to make extra certain" +echo "that you LOAD and SAVE configs from/to " +echo "\$RISCV/buildroot-config-src." +echo "" +echo "Run \`exit\` to sign out when you are done." +echo "And then any configs that were modified in" +echo "\$RISCV/buildroot-config-src will be copied" +echo "back to ../buildroot-config-src." +echo "==============================================" +read -p "Press any key to sign in as cad" -n1 -s +echo "" +cd $RISCV +sudo su cad +cd $script_dir + +echo "" +echo "Ending buildroot session" +if [ ! -d "$shared_config" ]; then + echo "Warning: $shared_config has already been deleted." + exit 0 +fi +if [ ! -f "$shared_config/.owner" ]; then + echo "Oy vey -- no .owner file found.">&2 + echo "Not sure whether to delete $shared_config.">&2 + exit 1 +fi +owner=$(cat "$shared_config"/.owner) +if [ $owner != $(whoami) ]; then + echo "Whoah there! It seems $owner created $shared_config.">&2 + echo "Ask them before deleting their work.">&2 + exit 1 +fi +echo "Copying modified configs from \$RISCV/buildroot-config-src back to ../buildroot-config-src." +for file in $personal_config/*; do + file=$(basename $file) + cp $shared_config/$file $personal_config/$file +done +echo "Elevate permissions to remove personal configs from shared location." +sudo rm -r $shared_config diff --git a/linux/devicetree/debug/dumpdts.sh b/linux/devicetree/debug/dumpdts.sh new file mode 100755 index 000000000..70057a78f --- /dev/null +++ b/linux/devicetree/debug/dumpdts.sh @@ -0,0 +1,6 @@ +#!/bin/bash +machine=virt + +qemu-system-riscv64 -M $machine,dumpdtb=$machine.dtb -bios $RISCV/buildroot/output/images/fw_jump.elf + +dtc -I dtb -O dts $machine.dtb > $machine.dts diff --git a/linux/devicetree/virt-trimmed.dts b/linux/devicetree/virt-trimmed.dts new file mode 100644 index 000000000..b517c3de5 --- /dev/null +++ b/linux/devicetree/virt-trimmed.dts @@ -0,0 +1,75 @@ +/dts-v1/; + +/ { + #address-cells = <0x02>; + #size-cells = <0x02>; + compatible = "riscv-virtio-trimmed"; + model = "riscv-virtio-trimmed,qemu"; + + chosen { + linux,initrd-end = <0x85c43a00>; + linux,initrd-start = <0x84200000>; + bootargs = "root=/dev/vda ro"; + stdout-path = "/soc/uart@10000000"; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x00 0x80000000 0x00 0x8000000>; + }; + + cpus { + #address-cells = <0x01>; + #size-cells = <0x00>; + timebase-frequency = <0x989680>; + + cpu@0 { + phandle = <0x01>; + device_type = "cpu"; + reg = <0x00>; + status = "okay"; + compatible = "riscv"; + riscv,isa = "rv64imafdcsu"; + mmu-type = "riscv,sv48"; + + interrupt-controller { + #interrupt-cells = <0x01>; + interrupt-controller; + compatible = "riscv,cpu-intc"; + phandle = <0x02>; + }; + }; + }; + + soc { + #address-cells = <0x02>; + #size-cells = <0x02>; + compatible = "simple-bus"; + ranges; + + uart@10000000 { + interrupts = <0x0a>; + interrupt-parent = <0x03>; + clock-frequency = <0x384000>; + reg = <0x00 0x10000000 0x00 0x100>; + compatible = "ns16550a"; + }; + + plic@c000000 { + phandle = <0x03>; + riscv,ndev = <0x35>; + reg = <0x00 0xc000000 0x00 0x210000>; + interrupts-extended = <0x02 0x0b 0x02 0x09>; + interrupt-controller; + compatible = "sifive,plic-1.0.0\0riscv,plic0"; + #interrupt-cells = <0x01>; + #address-cells = <0x00>; + }; + + clint@2000000 { + interrupts-extended = <0x02 0x03 0x02 0x07>; + reg = <0x00 0x2000000 0x00 0x10000>; + compatible = "sifive,clint0\0riscv,clint0"; + }; + }; +}; diff --git a/linux/testvector-generation/genTrace.gdb b/linux/testvector-generation/genTrace.gdb new file mode 100755 index 000000000..e69e28ec5 --- /dev/null +++ b/linux/testvector-generation/genTrace.gdb @@ -0,0 +1,25 @@ +define genTrace + # Arguments + set $tcpPort=$arg0 + set $vmlinux=$arg1 + + # GDB config + set pagination off + set logging overwrite on + set logging redirect on + set confirm off + + # Connect to QEMU session + eval "target extended-remote :%d",$tcpPort + + # Symbol Files + eval "file %s",$vmlinux + + # Run until Linux login prompt + b do_idle + ignore 1 2 + c + + kill + q +end diff --git a/linux/testvector-generation/genTrace.sh b/linux/testvector-generation/genTrace.sh new file mode 100755 index 000000000..82f9e48be --- /dev/null +++ b/linux/testvector-generation/genTrace.sh @@ -0,0 +1,43 @@ +#!/bin/bash +tcpPort=1234 +imageDir=$RISCV/buildroot/output/images +outDir=$RISCV/linux-testvectors +recordFile="$outDir/all.qemu" +traceFile="$outDir/all.txt" + +read -p "Warning: running this script will overwrite the contents of: + * $recordFile + * $traceFile +Would you like to proceed? (y/n) " -n 1 -r +echo +if [[ $REPLY =~ ^[Yy]$ ]] +then + # Create Output Directory + sudo mkdir -p $outDir + sudo chown cad $outDir + sudo touch $recordFile + sudo touch $traceFile + sudo chmod a+rw $recordFile + sudo chmod a+rw $traceFile + + # Compile Devicetree from Source + dtc -I dts -O dtb ../devicetree/virt-trimmed.dts > ../devicetree/virt-trimmed.dtb + + # QEMU Simulation + (qemu-system-riscv64 \ + -M virt -dtb ../devicetree/virt-trimmed.dtb \ + -nographic -serial /dev/null \ + -bios $imageDir/fw_jump.elf -kernel $imageDir/Image -append "root=/dev/vda ro" -initrd $imageDir/rootfs.cpio \ + -singlestep -rtc clock=vm -icount shift=0,align=off,sleep=on,rr=record,rrfile=$recordFile \ + -d nochain,cpu,in_asm \ + -gdb tcp::$tcpPort -S \ + 2>&1 >/dev/null | ./parseQemuToGDB.py | ./parseGDBtoTrace.py | ./remove_dup.awk > $traceFile) \ + & riscv64-unknown-elf-gdb -quiet -x genTrace.gdb -ex "genTrace $tcpPort \"$imageDir/vmlinux\"" + + # Cleanup + sudo chown cad $recordFile + sudo chown cad $traceFile + sudo chmod o-w $recordFile + sudo chmod o-w $traceFile +fi + diff --git a/linux/testvector-generation/parseGDBtoTrace.py b/linux/testvector-generation/parseGDBtoTrace.py new file mode 100755 index 000000000..ab63330fd --- /dev/null +++ b/linux/testvector-generation/parseGDBtoTrace.py @@ -0,0 +1,220 @@ +#! /usr/bin/python3 +import sys, fileinput, re + +# Ross Thompson +# July 27, 2021 +# Rewrite of the linux trace parser. + + +InstrStartDelim = '=>' +InstrEndDelim = '-----' + +#InputFile = 'noparse.txt' +#InputFile = sys.stdin +#InputFile = 'temp.txt' +#OutputFile = 'parsedAll.txt' + +HUMAN_READABLE = False + +def toDict(lst): + 'Converts the list of register values to a dictionary' + dct= {} + for item in lst: + regTup = item.split() + dct[regTup[0]] = int(regTup[2], 10) + del dct['pc'] + return dct + +def whichClass(text, Regs): + 'Which instruction class?' + #print(text, Regs) + if text[0:2] == 'ld' or text[0:2] == 'lw' or text[0:2] == 'lh' or text[0:2] == 'lb': + return ('load', WhatAddr(text, Regs), None, WhatMemDestSource(text)) + elif text[0:2] == 'sd' or text[0:2] == 'sw' or text[0:2] == 'sh' or text[0:2] == 'sb': + return ('store', WhatAddr(text, Regs), WhatMemDestSource(text), None) + elif text[0:3] == 'amo': + return ('amo', WhatAddrAMO(text, Regs), WhatMemDestSource(text), WhatMemDestSource(text)) + elif text[0:2] == 'lr': + return ('lr', WhatAddrLR(text, Regs), None, WhatMemDestSource(text)) + elif text[0:2] == 'sc': + return ('sc', WhatAddrSC(text, Regs), WhatMemDestSource(text), None) + else: + return ('other', None, None, None) + +def whatChanged(dct0, dct1): + 'Compares two dictionaries of instrution registers and indicates which registers changed' + dct = {} + for key in dct0: + if (dct1[key] != dct0[key]): + dct[key] = dct1[key] + return dct + +def WhatMemDestSource(text): + ''''What is the destination register. Used to compute where the read data is + on a load or the write data on a store.''' + return text.split()[1].split(',')[0] + +def WhatAddr(text, Regs): + 'What is the data memory address?' + Imm = text.split(',')[1] + (Imm, Src) = Imm.split('(') + Imm = int(Imm.strip(), 10) + Src = Src.strip(')').strip() + RegVal = Regs[Src] + return Imm + RegVal + +def WhatAddrAMO(text, Regs): + 'What is the data memory address?' + Src = text.split('(')[1] + Src = Src.strip(')').strip() + return Regs[Src] + +def WhatAddrLR(text, Regs): + 'What is the data memory address?' + Src = text.split('(')[1] + Src = Src.strip(')').strip() + return Regs[Src] + +def WhatAddrSC(text, Regs): + 'What is the data memory address?' + Src = text.split('(')[1] + Src = Src.strip(')').strip() + return Regs[Src] + +def PrintInstr(instr, fp): + if instr[2] == None: + return + ChangedRegisters = instr[4] + GPR = '' + CSR = [] + for key in ChangedRegisters: + # filter out csr which are not checked. + if(key in RegNumber): + if(RegNumber[key] < 32): + # GPR + if(HUMAN_READABLE): + GPR = '{:-2d} {:016x}'.format(RegNumber[key], ChangedRegisters[key]) + else: + GPR = '{:d} {:x}'.format(RegNumber[key], ChangedRegisters[key]) + else: + if(HUMAN_READABLE): + CSR.extend([key, '{:016x}'.format(ChangedRegisters[key])]) + else: + CSR.extend([key, '{:x}'.format(ChangedRegisters[key])]) + + CSRStr = ' '.join(CSR) + + #print(instr) + + if (HUMAN_READABLE == True): + fp.write('{:016x} {:08x} {:25s}'.format(instr[0], instr[1], instr[2])) + if(len(GPR) != 0): + fp.write(' GPR {}'.format(GPR)) + if(instr[3] == 'load' or instr[3] == 'lr'): + fp.write(' MemR {:016x} {:016x} {:016x}'.format(instr[5], 0, instr[7])) + if(instr[3] == 'store'): + fp.write('\t\t\t MemW {:016x} {:016x} {:016x}'.format(instr[5], instr[6], 0)) + + if(len(CSR) != 0): + fp.write(' CSR {}'.format(CSRStr)) + else: + fp.write('{:x} {:x} {:s}'.format(instr[0], instr[1], instr[2].replace(' ', '_'))) + if(len(GPR) != 0): + fp.write(' GPR {}'.format(GPR)) + if(instr[3] == 'load' or instr[3] == 'lr'): + fp.write(' MemR {:x} {:x} {:x}'.format(instr[5], 0, instr[7])) + if(instr[3] == 'store'): + fp.write(' MemW {:x} {:x} {:x}'.format(instr[5], instr[6], 0)) + + if(len(CSR) != 0): + fp.write(' CSR {}'.format(CSRStr)) + fp.write('\n') + +# reg number +RegNumber = {'zero': 0, 'ra': 1, 'sp': 2, 'gp': 3, 'tp': 4, 't0': 5, 't1': 6, 't2': 7, 's0': 8, 's1': 9, 'a0': 10, 'a1': 11, 'a2': 12, 'a3': 13, 'a4': 14, 'a5': 15, 'a6': 16, 'a7': 17, 's2': 18, 's3': 19, 's4': 20, 's5': 21, 's6': 22, 's7': 23, 's8': 24, 's9': 25, 's10': 26, 's11': 27, 't3': 28, 't4': 29, 't5': 30, 't6': 31, 'mhartid': 32, 'mstatus': 33, 'mip': 34, 'mie': 35, 'mideleg': 36, 'medeleg': 37, 'mtvec': 38, 'stvec': 39, 'mepc': 40, 'sepc': 41, 'mcause': 42, 'scause': 43, 'mtval': 44, 'stval': 45} +# initial state +CurrentInstr = ['0', '0', None, 'other', {'zero': 0, 'ra': 0, 'sp': 0, 'gp': 0, 'tp': 0, 't0': 0, 't1': 0, 't2': 0, 's0': 0, 's1': 0, 'a0': 0, 'a1': 0, 'a2': 0, 'a3': 0, 'a4': 0, 'a5': 0, 'a6': 0, 'a7': 0, 's2': 0, 's3': 0, 's4': 0, 's5': 0, 's6': 0, 's7': 0, 's8': 0, 's9': 0, 's10': 0, 's11': 0, 't3': 0, 't4': 0, 't5': 0, 't6': 0, 'mhartid': 0, 'mstatus': 0, 'mip': 0, 'mie': 0, 'mideleg': 0, 'medeleg': 0, 'mtvec': 0, 'stvec': 0, 'mepc': 0, 'sepc': 0, 'mcause': 0, 'scause': 0, 'mtval': 0, 'stval': 0}, {}, None, None, None] + +#with open (InputFile, 'r') as InputFileFP: +#lines = InputFileFP.readlines() +lineNum = 0 +StartLine = 0 +EndLine = 0 +numInstrs = 0 +#instructions = [] +MemAdr = 0 +lines = [] +interrupts=open('interrupts.txt','w') +interrupts.close() + +for line in fileinput.input('-'): + if line.startswith('riscv_cpu_do_interrupt'): + with open('interrupts.txt','a') as interrupts: + interrupts.write(str(numInstrs)+': '+line.strip('riscv_cpu_do_interrupt')) + break + lines.insert(lineNum, line) + if InstrStartDelim in line: + lineNum = 0 + StartLine = lineNum + elif InstrEndDelim in line: + EndLine = lineNum + (InstrBits, text) = lines[StartLine].split(':') + InstrBits = int(InstrBits.strip('=> '), 16) + text = text.strip() + PC = int(lines[StartLine+1].split(':')[0][2:], 16) + Regs = toDict(lines[StartLine+2:EndLine]) + (Class, Addr, WriteReg, ReadReg) = whichClass(text, Regs) + #print("CWR", Class, WriteReg, ReadReg) + PreviousInstr = CurrentInstr + + Changed = whatChanged(PreviousInstr[4], Regs) + + if (ReadReg !=None): ReadData = ReadReg + else: ReadData = None + + if (WriteReg !=None): WriteData = WriteReg + else: WriteData = None + + CurrentInstr = [PC, InstrBits, text, Class, Regs, Changed, Addr, WriteData, ReadData] + + #print(CurrentInstr[0:4], PreviousInstr[5], CurrentInstr[6:7], PreviousInstr[8]) + + # pc, instrbits, text and class come from the last line. + MoveInstrToRegWriteLst = PreviousInstr[0:4] + # updated registers come from the current line. + MoveInstrToRegWriteLst.append(CurrentInstr[5]) # destination regs + # memory address if present comes from the last line. + MoveInstrToRegWriteLst.append(PreviousInstr[6]) # MemAdrM + # write data from the previous line + #MoveInstrToRegWriteLst.append(PreviousInstr[7]) # WriteDataM + + if (PreviousInstr[7] != None): + MoveInstrToRegWriteLst.append(Regs[PreviousInstr[7]]) # WriteDataM + else: + MoveInstrToRegWriteLst.append(None) + + # read data from the current line + #MoveInstrToRegWriteLst.append(PreviousInstr[8]) # ReadDataM + if (PreviousInstr[8] != None): + MoveInstrToRegWriteLst.append(Regs[PreviousInstr[8]]) # ReadDataM + else: + MoveInstrToRegWriteLst.append(None) + + lines.clear() + #instructions.append(MoveInstrToRegWriteLst) + PrintInstr(MoveInstrToRegWriteLst, sys.stdout) + numInstrs +=1 + if (numInstrs % 1e4 == 0): + sys.stderr.write('Trace parser reached '+str(numInstrs/1.0e6)+' million instrs.\n') + sys.stderr.flush() + lineNum += 1 + + +#for instruction in instructions[1::]: + + +#with open(OutputFile, 'w') as OutputFileFP: +# print('opened file') + + + diff --git a/linux/testvector-generation/parseQemuToGDB.py b/linux/testvector-generation/parseQemuToGDB.py new file mode 100755 index 000000000..932761db7 --- /dev/null +++ b/linux/testvector-generation/parseQemuToGDB.py @@ -0,0 +1,148 @@ +#! /usr/bin/python3 +import fileinput, sys + +sys.stderr.write("reminder: parse_qemu.py takes input from stdin\n") +parseState = "idle" +beginPageFault = 0 +inPageFault = 0 +endPageFault = 0 +CSRs = {} +pageFaultCSRs = {} +regs = {} +pageFaultRegs = {} +instrs = {} +instrCount = 0 +returnAdr = 0 + +def printPC(l): + global parseState, inPageFault, CSRs, pageFaultCSRs, regs, pageFaultCSRs, instrs, instrCount + if not inPageFault: + inst = l.split() + if len(inst) > 3: + print(f'=> {inst[1]}:\t{inst[2]} {inst[3]}') + else: + print(f'=> {inst[1]}:\t{inst[2]}') + print(f'{inst[0]} 0x{inst[1]}') + instrCount += 1 + if ((instrCount % 100000) == 0): + sys.stderr.write("QEMU parser reached "+str(instrCount)+" instrs\n") + +def printCSRs(): + global parseState, inPageFault, CSRs, pageFaultCSRs, regs, pageFaultCSRs, instrs + if not inPageFault: + for (csr,val) in CSRs.items(): + print('{}{}{:#x} {}'.format(csr, ' '*(15-len(csr)), val, val)) + print('-----') + +def parseCSRs(l): + global parseState, inPageFault, CSRs, pageFaultCSRs, regs, pageFaultCSRs, instrs + if l.strip() and (not l.startswith("Disassembler")) and (not l.startswith("Please")): + # If we've hit the register file + if l.startswith(' x0/zero'): + parseState = "regFile" + if not inPageFault: + instr = instrs[CSRs["pc"]] + printPC(instr) + parseRegs(l) + # If we've hit a CSR + else: + csr = l.split()[0] + val = int(l.split()[1],16) + # Commented out this conditional because the pageFault instrs don't corrupt CSRs + #if inPageFault: + # Not sure if these CSRs should be updated or not during page fault. + #if l.startswith("mstatus") or l.startswith("mepc") or l.startswith("mcause") or l.startswith("mtval") or l.startswith("sepc") or l.startswith("scause") or l.startswith("stval"): + # We do update some CSRs + # CSRs[csr] = val + #else: + # Others we preserve until changed later + # pageFaultCSRs[csr] = val + #elif pageFaultCSRs and (csr in pageFaultCSRs): + # if (val != pageFaultCSRs[csr]): + # del pageFaultCSRs[csr] + # CSRs[csr] = val + #else: + # CSRs[csr] = val + # + # However SEPC and STVAL do get corrupted upon exiting + if endPageFault and ((csr == 'sepc') or (csr == 'stval')): + CSRs[csr] = returnAdr + pageFaultCSRs[csr] = val + elif pageFaultCSRs and (csr in pageFaultCSRs): + if (val != pageFaultCSRs[csr]): + del pageFaultCSRs[csr] + CSRs[csr] = val + else: + CSRs[csr] = val + +def parseRegs(l): + global parseState, inPageFault, CSRs, pageFaultCSRs, regs, pageFaultCSRs, instrs, pageFaultRegs + if "pc" in l: + printCSRs() + # New non-disassembled instruction + parseState = "CSRs" + parseCSRs(l) + elif l.startswith('--------'): + # End of disassembled instruction + printCSRs() + parseState = "idle" + else: + s = l.split() + for i in range(0,len(s),2): + if '/' in s[i]: + reg = s[i].split('/')[1] + val = int(s[i+1], 16) + if inPageFault: + pageFaultRegs[reg] = val + else: + if pageFaultRegs and (reg in pageFaultRegs): + if (val != pageFaultRegs[reg]): + del pageFaultRegs[reg] + regs[reg] = val + else: + regs[reg] = val + val = regs[reg] + print('{}{}{:#x} {}'.format(reg, ' '*(15-len(reg)), val, val)) + else: + sys.stderr.write("Whoops. Expected a list of reg file regs; got:\n"+l) + +############# +# Main Code # +############# +interrupt_line="" +for l in fileinput.input(): + #sys.stderr.write(l) + if l.startswith('riscv_cpu_do_interrupt'): + sys.stderr.write(l) + interrupt_line = l.strip('\n') + continue + elif l.startswith('qemu-system-riscv64: QEMU: Terminated via GDBstub'): + break + elif l.startswith('IN:'): + # New disassembled instr + if len(interrupt_line)>0: + print(interrupt_line) + interrupt_line="" + parseState = "instr" + elif (parseState == "instr") and l.startswith('0x'): + # New instruction + if len(interrupt_line)>0: + print(interrupt_line) + interrupt_line="" + if "out of bounds" in l: + sys.stderr.write("Detected QEMU page fault error\n") + beginPageFault = not inPageFault + if beginPageFault: + returnAdr = int(l.split()[0][2:-1], 16) + sys.stderr.write('Saving SEPC of '+hex(returnAdr)+'\n') + inPageFault = 1 + else: + endPageFault = inPageFault + inPageFault = 0 + adr = int(l.split()[0][2:-1], 16) + instrs[adr] = l + parseState = "CSRs" + elif parseState == "CSRs": + parseCSRs(l) + elif parseState == "regFile": + parseRegs(l) diff --git a/linux/testvector-generation/remove_dup.awk b/linux/testvector-generation/remove_dup.awk new file mode 100755 index 000000000..7963d76a6 --- /dev/null +++ b/linux/testvector-generation/remove_dup.awk @@ -0,0 +1,20 @@ +#!/usr/bin/awk -f + +BEGIN{ + old = "first" +} + +{ + if($1 != old){ + if(old != "first"){ + print oldAll + } + } + old=$1 + oldAll=$0 +} + +END{ + print oldAll +} + diff --git a/linux/wallyVirtIO.patch b/linux/wallyVirtIO.patch deleted file mode 100644 index 76a1d240e..000000000 --- a/linux/wallyVirtIO.patch +++ /dev/null @@ -1,542 +0,0 @@ -diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c -index 4a3cd2599a..39b46e3122 100644 ---- a/hw/riscv/virt.c -+++ b/hw/riscv/virt.c -@@ -20,6 +20,7 @@ - - #include "qemu/osdep.h" - #include "qemu/units.h" -+#include "qemu/log.h" - #include "qemu/error-report.h" - #include "qapi/error.h" - #include "hw/boards.h" -@@ -44,19 +45,10 @@ - #include "hw/display/ramfb.h" - - static const MemMapEntry virt_memmap[] = { -- [VIRT_DEBUG] = { 0x0, 0x100 }, - [VIRT_MROM] = { 0x1000, 0xf000 }, -- [VIRT_TEST] = { 0x100000, 0x1000 }, -- [VIRT_RTC] = { 0x101000, 0x1000 }, - [VIRT_CLINT] = { 0x2000000, 0x10000 }, -- [VIRT_PCIE_PIO] = { 0x3000000, 0x10000 }, - [VIRT_PLIC] = { 0xc000000, VIRT_PLIC_SIZE(VIRT_CPUS_MAX * 2) }, - [VIRT_UART0] = { 0x10000000, 0x100 }, -- [VIRT_VIRTIO] = { 0x10001000, 0x1000 }, -- [VIRT_FW_CFG] = { 0x10100000, 0x18 }, -- [VIRT_FLASH] = { 0x20000000, 0x4000000 }, -- [VIRT_PCIE_ECAM] = { 0x30000000, 0x10000000 }, -- [VIRT_PCIE_MMIO] = { 0x40000000, 0x40000000 }, - [VIRT_DRAM] = { 0x80000000, 0x0 }, - }; - -@@ -67,139 +59,23 @@ static const MemMapEntry virt_memmap[] = { - /* PCIe high mmio for RV64, size is fixed but base depends on top of RAM */ - #define VIRT64_HIGH_PCIE_MMIO_SIZE (16 * GiB) - --static MemMapEntry virt_high_pcie_memmap; -- - #define VIRT_FLASH_SECTOR_SIZE (256 * KiB) - --static PFlashCFI01 *virt_flash_create1(RISCVVirtState *s, -- const char *name, -- const char *alias_prop_name) --{ -- /* -- * Create a single flash device. We use the same parameters as -- * the flash devices on the ARM virt board. -- */ -- DeviceState *dev = qdev_new(TYPE_PFLASH_CFI01); -- -- qdev_prop_set_uint64(dev, "sector-length", VIRT_FLASH_SECTOR_SIZE); -- qdev_prop_set_uint8(dev, "width", 4); -- qdev_prop_set_uint8(dev, "device-width", 2); -- qdev_prop_set_bit(dev, "big-endian", false); -- qdev_prop_set_uint16(dev, "id0", 0x89); -- qdev_prop_set_uint16(dev, "id1", 0x18); -- qdev_prop_set_uint16(dev, "id2", 0x00); -- qdev_prop_set_uint16(dev, "id3", 0x00); -- qdev_prop_set_string(dev, "name", name); -- -- object_property_add_child(OBJECT(s), name, OBJECT(dev)); -- object_property_add_alias(OBJECT(s), alias_prop_name, -- OBJECT(dev), "drive"); -- -- return PFLASH_CFI01(dev); --} -- --static void virt_flash_create(RISCVVirtState *s) --{ -- s->flash[0] = virt_flash_create1(s, "virt.flash0", "pflash0"); -- s->flash[1] = virt_flash_create1(s, "virt.flash1", "pflash1"); --} -- --static void virt_flash_map1(PFlashCFI01 *flash, -- hwaddr base, hwaddr size, -- MemoryRegion *sysmem) --{ -- DeviceState *dev = DEVICE(flash); -- -- assert(QEMU_IS_ALIGNED(size, VIRT_FLASH_SECTOR_SIZE)); -- assert(size / VIRT_FLASH_SECTOR_SIZE <= UINT32_MAX); -- qdev_prop_set_uint32(dev, "num-blocks", size / VIRT_FLASH_SECTOR_SIZE); -- sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); -- -- memory_region_add_subregion(sysmem, base, -- sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), -- 0)); --} -- --static void virt_flash_map(RISCVVirtState *s, -- MemoryRegion *sysmem) --{ -- hwaddr flashsize = virt_memmap[VIRT_FLASH].size / 2; -- hwaddr flashbase = virt_memmap[VIRT_FLASH].base; -- -- virt_flash_map1(s->flash[0], flashbase, flashsize, -- sysmem); -- virt_flash_map1(s->flash[1], flashbase + flashsize, flashsize, -- sysmem); --} -- --static void create_pcie_irq_map(void *fdt, char *nodename, -- uint32_t plic_phandle) --{ -- int pin, dev; -- uint32_t -- full_irq_map[GPEX_NUM_IRQS * GPEX_NUM_IRQS * FDT_INT_MAP_WIDTH] = {}; -- uint32_t *irq_map = full_irq_map; -- -- /* This code creates a standard swizzle of interrupts such that -- * each device's first interrupt is based on it's PCI_SLOT number. -- * (See pci_swizzle_map_irq_fn()) -- * -- * We only need one entry per interrupt in the table (not one per -- * possible slot) seeing the interrupt-map-mask will allow the table -- * to wrap to any number of devices. -- */ -- for (dev = 0; dev < GPEX_NUM_IRQS; dev++) { -- int devfn = dev * 0x8; -- -- for (pin = 0; pin < GPEX_NUM_IRQS; pin++) { -- int irq_nr = PCIE_IRQ + ((pin + PCI_SLOT(devfn)) % GPEX_NUM_IRQS); -- int i = 0; -- -- irq_map[i] = cpu_to_be32(devfn << 8); -- -- i += FDT_PCI_ADDR_CELLS; -- irq_map[i] = cpu_to_be32(pin + 1); -- -- i += FDT_PCI_INT_CELLS; -- irq_map[i++] = cpu_to_be32(plic_phandle); -- -- i += FDT_PLIC_ADDR_CELLS; -- irq_map[i] = cpu_to_be32(irq_nr); -- -- irq_map += FDT_INT_MAP_WIDTH; -- } -- } -- -- qemu_fdt_setprop(fdt, nodename, "interrupt-map", -- full_irq_map, sizeof(full_irq_map)); -- -- qemu_fdt_setprop_cells(fdt, nodename, "interrupt-map-mask", -- 0x1800, 0, 0, 0x7); --} -- - static void create_fdt(RISCVVirtState *s, const MemMapEntry *memmap, - uint64_t mem_size, const char *cmdline, bool is_32_bit) - { - void *fdt; -- int i, cpu, socket; -+ //int i, cpu, socket; -+ int cpu, socket; - MachineState *mc = MACHINE(s); - uint64_t addr, size; - uint32_t *clint_cells, *plic_cells; - unsigned long clint_addr, plic_addr; - uint32_t plic_phandle[MAX_NODES]; -- uint32_t cpu_phandle, intc_phandle, test_phandle; -+ uint32_t cpu_phandle, intc_phandle; - uint32_t phandle = 1, plic_mmio_phandle = 1; -- uint32_t plic_pcie_phandle = 1, plic_virtio_phandle = 1; - char *mem_name, *cpu_name, *core_name, *intc_name; - char *name, *clint_name, *plic_name, *clust_name; -- hwaddr flashsize = virt_memmap[VIRT_FLASH].size / 2; -- hwaddr flashbase = virt_memmap[VIRT_FLASH].base; -- static const char * const clint_compat[2] = { -- "sifive,clint0", "riscv,clint0" -- }; -- static const char * const plic_compat[2] = { -- "sifive,plic-1.0.0", "riscv,plic0" -- }; - - if (mc->dtb) { - fdt = mc->fdt = load_device_tree(mc->dtb, &s->fdt_size); -@@ -305,8 +181,7 @@ static void create_fdt(RISCVVirtState *s, const MemMapEntry *memmap, - (memmap[VIRT_CLINT].size * socket); - clint_name = g_strdup_printf("/soc/clint@%lx", clint_addr); - qemu_fdt_add_subnode(fdt, clint_name); -- qemu_fdt_setprop_string_array(fdt, clint_name, "compatible", -- (char **)&clint_compat, ARRAY_SIZE(clint_compat)); -+ qemu_fdt_setprop_string(fdt, clint_name, "compatible", "riscv,clint0"); - qemu_fdt_setprop_cells(fdt, clint_name, "reg", - 0x0, clint_addr, 0x0, memmap[VIRT_CLINT].size); - qemu_fdt_setprop(fdt, clint_name, "interrupts-extended", -@@ -322,8 +197,7 @@ static void create_fdt(RISCVVirtState *s, const MemMapEntry *memmap, - "#address-cells", FDT_PLIC_ADDR_CELLS); - qemu_fdt_setprop_cell(fdt, plic_name, - "#interrupt-cells", FDT_PLIC_INT_CELLS); -- qemu_fdt_setprop_string_array(fdt, plic_name, "compatible", -- (char **)&plic_compat, ARRAY_SIZE(plic_compat)); -+ qemu_fdt_setprop_string(fdt, plic_name, "compatible", "riscv,plic0"); - qemu_fdt_setprop(fdt, plic_name, "interrupt-controller", NULL, 0); - qemu_fdt_setprop(fdt, plic_name, "interrupts-extended", - plic_cells, s->soc[socket].num_harts * sizeof(uint32_t) * 4); -@@ -342,95 +216,11 @@ static void create_fdt(RISCVVirtState *s, const MemMapEntry *memmap, - for (socket = 0; socket < riscv_socket_count(mc); socket++) { - if (socket == 0) { - plic_mmio_phandle = plic_phandle[socket]; -- plic_virtio_phandle = plic_phandle[socket]; -- plic_pcie_phandle = plic_phandle[socket]; -- } -- if (socket == 1) { -- plic_virtio_phandle = plic_phandle[socket]; -- plic_pcie_phandle = plic_phandle[socket]; -- } -- if (socket == 2) { -- plic_pcie_phandle = plic_phandle[socket]; - } - } - - riscv_socket_fdt_write_distance_matrix(mc, fdt); - -- for (i = 0; i < VIRTIO_COUNT; i++) { -- name = g_strdup_printf("/soc/virtio_mmio@%lx", -- (long)(memmap[VIRT_VIRTIO].base + i * memmap[VIRT_VIRTIO].size)); -- qemu_fdt_add_subnode(fdt, name); -- qemu_fdt_setprop_string(fdt, name, "compatible", "virtio,mmio"); -- qemu_fdt_setprop_cells(fdt, name, "reg", -- 0x0, memmap[VIRT_VIRTIO].base + i * memmap[VIRT_VIRTIO].size, -- 0x0, memmap[VIRT_VIRTIO].size); -- qemu_fdt_setprop_cell(fdt, name, "interrupt-parent", -- plic_virtio_phandle); -- qemu_fdt_setprop_cell(fdt, name, "interrupts", VIRTIO_IRQ + i); -- g_free(name); -- } -- -- name = g_strdup_printf("/soc/pci@%lx", -- (long) memmap[VIRT_PCIE_ECAM].base); -- qemu_fdt_add_subnode(fdt, name); -- qemu_fdt_setprop_cell(fdt, name, "#address-cells", FDT_PCI_ADDR_CELLS); -- qemu_fdt_setprop_cell(fdt, name, "#interrupt-cells", FDT_PCI_INT_CELLS); -- qemu_fdt_setprop_cell(fdt, name, "#size-cells", 0x2); -- qemu_fdt_setprop_string(fdt, name, "compatible", "pci-host-ecam-generic"); -- qemu_fdt_setprop_string(fdt, name, "device_type", "pci"); -- qemu_fdt_setprop_cell(fdt, name, "linux,pci-domain", 0); -- qemu_fdt_setprop_cells(fdt, name, "bus-range", 0, -- memmap[VIRT_PCIE_ECAM].size / PCIE_MMCFG_SIZE_MIN - 1); -- qemu_fdt_setprop(fdt, name, "dma-coherent", NULL, 0); -- qemu_fdt_setprop_cells(fdt, name, "reg", 0, -- memmap[VIRT_PCIE_ECAM].base, 0, memmap[VIRT_PCIE_ECAM].size); -- qemu_fdt_setprop_sized_cells(fdt, name, "ranges", -- 1, FDT_PCI_RANGE_IOPORT, 2, 0, -- 2, memmap[VIRT_PCIE_PIO].base, 2, memmap[VIRT_PCIE_PIO].size, -- 1, FDT_PCI_RANGE_MMIO, -- 2, memmap[VIRT_PCIE_MMIO].base, -- 2, memmap[VIRT_PCIE_MMIO].base, 2, memmap[VIRT_PCIE_MMIO].size, -- 1, FDT_PCI_RANGE_MMIO_64BIT, -- 2, virt_high_pcie_memmap.base, -- 2, virt_high_pcie_memmap.base, 2, virt_high_pcie_memmap.size); -- -- create_pcie_irq_map(fdt, name, plic_pcie_phandle); -- g_free(name); -- -- test_phandle = phandle++; -- name = g_strdup_printf("/soc/test@%lx", -- (long)memmap[VIRT_TEST].base); -- qemu_fdt_add_subnode(fdt, name); -- { -- static const char * const compat[3] = { -- "sifive,test1", "sifive,test0", "syscon" -- }; -- qemu_fdt_setprop_string_array(fdt, name, "compatible", (char **)&compat, -- ARRAY_SIZE(compat)); -- } -- qemu_fdt_setprop_cells(fdt, name, "reg", -- 0x0, memmap[VIRT_TEST].base, -- 0x0, memmap[VIRT_TEST].size); -- qemu_fdt_setprop_cell(fdt, name, "phandle", test_phandle); -- test_phandle = qemu_fdt_get_phandle(fdt, name); -- g_free(name); -- -- name = g_strdup_printf("/soc/reboot"); -- qemu_fdt_add_subnode(fdt, name); -- qemu_fdt_setprop_string(fdt, name, "compatible", "syscon-reboot"); -- qemu_fdt_setprop_cell(fdt, name, "regmap", test_phandle); -- qemu_fdt_setprop_cell(fdt, name, "offset", 0x0); -- qemu_fdt_setprop_cell(fdt, name, "value", FINISHER_RESET); -- g_free(name); -- -- name = g_strdup_printf("/soc/poweroff"); -- qemu_fdt_add_subnode(fdt, name); -- qemu_fdt_setprop_string(fdt, name, "compatible", "syscon-poweroff"); -- qemu_fdt_setprop_cell(fdt, name, "regmap", test_phandle); -- qemu_fdt_setprop_cell(fdt, name, "offset", 0x0); -- qemu_fdt_setprop_cell(fdt, name, "value", FINISHER_PASS); -- g_free(name); -- - name = g_strdup_printf("/soc/uart@%lx", (long)memmap[VIRT_UART0].base); - qemu_fdt_add_subnode(fdt, name); - qemu_fdt_setprop_string(fdt, name, "compatible", "ns16550a"); -@@ -445,102 +235,12 @@ static void create_fdt(RISCVVirtState *s, const MemMapEntry *memmap, - qemu_fdt_setprop_string(fdt, "/chosen", "stdout-path", name); - g_free(name); - -- name = g_strdup_printf("/soc/rtc@%lx", (long)memmap[VIRT_RTC].base); -- qemu_fdt_add_subnode(fdt, name); -- qemu_fdt_setprop_string(fdt, name, "compatible", "google,goldfish-rtc"); -- qemu_fdt_setprop_cells(fdt, name, "reg", -- 0x0, memmap[VIRT_RTC].base, -- 0x0, memmap[VIRT_RTC].size); -- qemu_fdt_setprop_cell(fdt, name, "interrupt-parent", plic_mmio_phandle); -- qemu_fdt_setprop_cell(fdt, name, "interrupts", RTC_IRQ); -- g_free(name); -- -- name = g_strdup_printf("/soc/flash@%" PRIx64, flashbase); -- qemu_fdt_add_subnode(mc->fdt, name); -- qemu_fdt_setprop_string(mc->fdt, name, "compatible", "cfi-flash"); -- qemu_fdt_setprop_sized_cells(mc->fdt, name, "reg", -- 2, flashbase, 2, flashsize, -- 2, flashbase + flashsize, 2, flashsize); -- qemu_fdt_setprop_cell(mc->fdt, name, "bank-width", 4); -- g_free(name); -- - update_bootargs: - if (cmdline) { - qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", cmdline); - } - } - --static inline DeviceState *gpex_pcie_init(MemoryRegion *sys_mem, -- hwaddr ecam_base, hwaddr ecam_size, -- hwaddr mmio_base, hwaddr mmio_size, -- hwaddr high_mmio_base, -- hwaddr high_mmio_size, -- hwaddr pio_base, -- DeviceState *plic) --{ -- DeviceState *dev; -- MemoryRegion *ecam_alias, *ecam_reg; -- MemoryRegion *mmio_alias, *high_mmio_alias, *mmio_reg; -- qemu_irq irq; -- int i; -- -- dev = qdev_new(TYPE_GPEX_HOST); -- -- sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); -- -- ecam_alias = g_new0(MemoryRegion, 1); -- ecam_reg = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0); -- memory_region_init_alias(ecam_alias, OBJECT(dev), "pcie-ecam", -- ecam_reg, 0, ecam_size); -- memory_region_add_subregion(get_system_memory(), ecam_base, ecam_alias); -- -- mmio_alias = g_new0(MemoryRegion, 1); -- mmio_reg = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 1); -- memory_region_init_alias(mmio_alias, OBJECT(dev), "pcie-mmio", -- mmio_reg, mmio_base, mmio_size); -- memory_region_add_subregion(get_system_memory(), mmio_base, mmio_alias); -- -- /* Map high MMIO space */ -- high_mmio_alias = g_new0(MemoryRegion, 1); -- memory_region_init_alias(high_mmio_alias, OBJECT(dev), "pcie-mmio-high", -- mmio_reg, high_mmio_base, high_mmio_size); -- memory_region_add_subregion(get_system_memory(), high_mmio_base, -- high_mmio_alias); -- -- sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, pio_base); -- -- for (i = 0; i < GPEX_NUM_IRQS; i++) { -- irq = qdev_get_gpio_in(plic, PCIE_IRQ + i); -- -- sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, irq); -- gpex_set_irq_num(GPEX_HOST(dev), i, PCIE_IRQ + i); -- } -- -- return dev; --} -- --static FWCfgState *create_fw_cfg(const MachineState *mc) --{ -- hwaddr base = virt_memmap[VIRT_FW_CFG].base; -- hwaddr size = virt_memmap[VIRT_FW_CFG].size; -- FWCfgState *fw_cfg; -- char *nodename; -- -- fw_cfg = fw_cfg_init_mem_wide(base + 8, base, 8, base + 16, -- &address_space_memory); -- fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, (uint16_t)mc->smp.cpus); -- -- nodename = g_strdup_printf("/fw-cfg@%" PRIx64, base); -- qemu_fdt_add_subnode(mc->fdt, nodename); -- qemu_fdt_setprop_string(mc->fdt, nodename, -- "compatible", "qemu,fw-cfg-mmio"); -- qemu_fdt_setprop_sized_cells(mc->fdt, nodename, "reg", -- 2, base, 2, size); -- qemu_fdt_setprop(mc->fdt, nodename, "dma-coherent", NULL, 0); -- g_free(nodename); -- return fw_cfg; --} -- - static void virt_machine_init(MachineState *machine) - { - const MemMapEntry *memmap = virt_memmap; -@@ -554,7 +254,7 @@ static void virt_machine_init(MachineState *machine) - target_ulong firmware_end_addr, kernel_start_addr; - uint32_t fdt_load_addr; - uint64_t kernel_entry; -- DeviceState *mmio_plic, *virtio_plic, *pcie_plic; -+ DeviceState *mmio_plic; - int i, j, base_hartid, hart_count; - - /* Check socket count limit */ -@@ -565,7 +265,7 @@ static void virt_machine_init(MachineState *machine) - } - - /* Initialize sockets */ -- mmio_plic = virtio_plic = pcie_plic = NULL; -+ mmio_plic = NULL; - for (i = 0; i < riscv_socket_count(machine); i++) { - if (!riscv_socket_check_hartids(machine, i)) { - error_report("discontinuous hartids in socket%d", i); -@@ -634,15 +334,6 @@ static void virt_machine_init(MachineState *machine) - /* Try to use different PLIC instance based device type */ - if (i == 0) { - mmio_plic = s->plic[i]; -- virtio_plic = s->plic[i]; -- pcie_plic = s->plic[i]; -- } -- if (i == 1) { -- virtio_plic = s->plic[i]; -- pcie_plic = s->plic[i]; -- } -- if (i == 2) { -- pcie_plic = s->plic[i]; - } - } - -@@ -654,13 +345,6 @@ static void virt_machine_init(MachineState *machine) - error_report("Limiting RAM size to 10 GiB"); - } - #endif -- virt_high_pcie_memmap.base = VIRT32_HIGH_PCIE_MMIO_BASE; -- virt_high_pcie_memmap.size = VIRT32_HIGH_PCIE_MMIO_SIZE; -- } else { -- virt_high_pcie_memmap.size = VIRT64_HIGH_PCIE_MMIO_SIZE; -- virt_high_pcie_memmap.base = memmap[VIRT_DRAM].base + machine->ram_size; -- virt_high_pcie_memmap.base = -- ROUND_UP(virt_high_pcie_memmap.base, virt_high_pcie_memmap.size); - } - - /* register system main memory (actual RAM) */ -@@ -681,10 +365,12 @@ static void virt_machine_init(MachineState *machine) - - if (riscv_is_32bit(&s->soc[0])) { - firmware_end_addr = riscv_find_and_load_firmware(machine, -- RISCV32_BIOS_BIN, start_addr, NULL); -+ "opensbi-riscv32-generic-fw_dynamic.bin", -+ start_addr, NULL); - } else { - firmware_end_addr = riscv_find_and_load_firmware(machine, -- RISCV64_BIOS_BIN, start_addr, NULL); -+ "opensbi-riscv64-generic-fw_dynamic.bin", -+ start_addr, NULL); - } - - if (machine->kernel_filename) { -@@ -712,21 +398,6 @@ static void virt_machine_init(MachineState *machine) - kernel_entry = 0; - } - -- if (drive_get(IF_PFLASH, 0, 0)) { -- /* -- * Pflash was supplied, let's overwrite the address we jump to after -- * reset to the base of the flash. -- */ -- start_addr = virt_memmap[VIRT_FLASH].base; -- } -- -- /* -- * Init fw_cfg. Must be done before riscv_load_fdt, otherwise the device -- * tree cannot be altered and we get FDT_ERR_NOSPACE. -- */ -- s->fw_cfg = create_fw_cfg(machine); -- rom_set_fw(s->fw_cfg); -- - /* Compute the fdt load address in dram */ - fdt_load_addr = riscv_load_fdt(memmap[VIRT_DRAM].base, - machine->ram_size, machine->fdt); -@@ -736,41 +407,10 @@ static void virt_machine_init(MachineState *machine) - virt_memmap[VIRT_MROM].size, kernel_entry, - fdt_load_addr, machine->fdt); - -- /* SiFive Test MMIO device */ -- sifive_test_create(memmap[VIRT_TEST].base); -- -- /* VirtIO MMIO devices */ -- for (i = 0; i < VIRTIO_COUNT; i++) { -- sysbus_create_simple("virtio-mmio", -- memmap[VIRT_VIRTIO].base + i * memmap[VIRT_VIRTIO].size, -- qdev_get_gpio_in(DEVICE(virtio_plic), VIRTIO_IRQ + i)); -- } -- -- gpex_pcie_init(system_memory, -- memmap[VIRT_PCIE_ECAM].base, -- memmap[VIRT_PCIE_ECAM].size, -- memmap[VIRT_PCIE_MMIO].base, -- memmap[VIRT_PCIE_MMIO].size, -- virt_high_pcie_memmap.base, -- virt_high_pcie_memmap.size, -- memmap[VIRT_PCIE_PIO].base, -- DEVICE(pcie_plic)); -- -- serial_mm_init(system_memory, memmap[VIRT_UART0].base, -+ serial_mm_init(system_memory, memmap[VIRT_UART0].base, - 0, qdev_get_gpio_in(DEVICE(mmio_plic), UART0_IRQ), 399193, - serial_hd(0), DEVICE_LITTLE_ENDIAN); - -- sysbus_create_simple("goldfish_rtc", memmap[VIRT_RTC].base, -- qdev_get_gpio_in(DEVICE(mmio_plic), RTC_IRQ)); -- -- virt_flash_create(s); -- -- for (i = 0; i < ARRAY_SIZE(s->flash); i++) { -- /* Map legacy -drive if=pflash to machine properties */ -- pflash_cfi01_legacy_drive(s->flash[i], -- drive_get(IF_PFLASH, 0, i)); -- } -- virt_flash_map(s, system_memory); - } - - static void virt_machine_instance_init(Object *obj) -diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c -index 991a6bb760..401028b8d9 100644 ---- a/target/riscv/cpu.c -+++ b/target/riscv/cpu.c -@@ -269,6 +269,15 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, int flags) - qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mip ", env->mip); - qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mie ", env->mie); - qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mideleg ", env->mideleg); -+ qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mcounteren ", env->mcounteren); -+ qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "misa ", env->misa); -+ qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mscratch ", env->mscratch); -+ qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "satp ", env->satp); -+ qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "scounteren ", env->scounteren); -+ qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "sscratch ", env->sscratch); -+ qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "stvec ", env->stvec); -+ qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mhartid ", env->mhartid); -+ - if (riscv_has_ext(env, RVH)) { - qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "hideleg ", env->hideleg); - } diff --git a/pipelined/config/rv32e/wally-config.vh b/pipelined/config/rv32e/wally-config.vh index 9102cf637..2e5bc34bb 100644 --- a/pipelined/config/rv32e/wally-config.vh +++ b/pipelined/config/rv32e/wally-config.vh @@ -49,8 +49,8 @@ `define UARCH_SUPERSCALR 0 `define UARCH_SINGLECYCLE 0 // *** replace with MEM_BUS -`define DMEM `MEM_BUS -`define IMEM `MEM_BUS +`define DMEM `MEM_CACHE +`define IMEM `MEM_CACHE `define VIRTMEM_SUPPORTED 0 `define VECTORED_INTERRUPTS_SUPPORTED 0 diff --git a/pipelined/testbench/tests.vh b/pipelined/testbench/tests.vh index 4a78455ea..9cce5847f 100644 --- a/pipelined/testbench/tests.vh +++ b/pipelined/testbench/tests.vh @@ -1498,12 +1498,12 @@ string imperas32f[] = '{ string wally32e[] = '{ `WALLYTEST, + "rv32i_m/I/E-beq-01", "03b010", "rv32i_m/I/E-add-01", "005010", "rv32i_m/I/E-addi-01", "004010", "rv32i_m/I/E-and-01", "005010", "rv32i_m/I/E-andi-01", "004010", "rv32i_m/I/E-auipc-01", "002010", - "rv32i_m/I/E-beq-01", "03b010", "rv32i_m/I/E-bge-01", "034010", "rv32i_m/I/E-bgeu-01", "047010", "rv32i_m/I/E-blt-01", "038010", diff --git a/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/I/Makefrag b/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/I/Makefrag index eda625075..792ea2e24 100644 --- a/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/I/Makefrag +++ b/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/I/Makefrag @@ -28,6 +28,43 @@ # Description: Makefrag for RV32I architectural tests rv32i_sc_tests = \ + E-add-01 \ + E-addi-01 \ + E-and-01 \ + E-andi-01 \ + E-auipc-01 \ + E-beq-01 \ + E-bge-01 \ + E-bgeu-01 \ + E-blt-01 \ + E-bltu-01 \ + E-bne-01 \ + E-jal-01 \ + E-jalr-01 \ + E-lb-align-01 \ + E-lbu-align-01 \ + E-lh-align-01 \ + E-lhu-align-01 \ + E-lui-01 \ + E-lw-align-01 \ + E-or-01 \ + E-ori-01 \ + E-sb-align-01 \ + E-sh-align-01 \ + E-sll-01 \ + E-slli-01 \ + E-slt-01 \ + E-slti-01 \ + E-sltiu-01 \ + E-sltu-01 \ + E-sra-01 \ + E-srai-01 \ + E-srl-01 \ + E-srli-01 \ + E-sub-01 \ + E-sw-align-01 \ + E-xor-01 \ + E-xori-01 \ WALLY-ADD \ WALLY-SLT \ WALLY-SLTU \