* Adding CVA6 machine to RISC-V @ 2025-05-21 15:54 Ben Dooks 2025-05-21 15:54 ` [PATCH 1/2] hw/riscv: add CVA6 machine Ben Dooks 2025-05-21 15:54 ` [PATCH 2/2] target/riscv: add cva6 cpu type Ben Dooks 0 siblings, 2 replies; 6+ messages in thread From: Ben Dooks @ 2025-05-21 15:54 UTC (permalink / raw) To: nazar.kazakov, joseph.baker, fran.redondo, lawrence.hunter, liwei1518, dbarboza, zhiwei_liu, qemu-riscv Cc: ben.dooks, qemu-devel This is an addition of the CVA6 (as implemented by the corev_apu) that we've been working on. Min arguments -M cva6 -m 1G -sd <sdcard> -bios <bootrom_64.elf> ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 1/2] hw/riscv: add CVA6 machine 2025-05-21 15:54 Adding CVA6 machine to RISC-V Ben Dooks @ 2025-05-21 15:54 ` Ben Dooks 2025-05-26 10:10 ` Daniel Henrique Barboza 2025-05-21 15:54 ` [PATCH 2/2] target/riscv: add cva6 cpu type Ben Dooks 1 sibling, 1 reply; 6+ messages in thread From: Ben Dooks @ 2025-05-21 15:54 UTC (permalink / raw) To: nazar.kazakov, joseph.baker, fran.redondo, lawrence.hunter, liwei1518, dbarboza, zhiwei_liu, qemu-riscv Cc: ben.dooks, qemu-devel Add a (currently Genesy2 based) CVA6 machine. Has SPI and UART, the GPIO and Ethernet are currently black-holed as there is no hardware model for them (lowRISC ethernet and Xilinx GPIO) Signed-off-by: Ben Dooks <ben.dooks@codethink.co.uk> --- - squashed in fixes for sd-card and new qemu init - move to spdx for cva6 machine - code cleanups missed in first review --- hw/riscv/Kconfig | 10 ++ hw/riscv/cva6.c | 231 ++++++++++++++++++++++++++++++++++++++++ hw/riscv/meson.build | 1 + include/hw/riscv/cva6.h | 83 +++++++++++++++ 4 files changed, 325 insertions(+) create mode 100644 hw/riscv/cva6.c create mode 100644 include/hw/riscv/cva6.h diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig index e6a0ac1fa1..b96f6fa014 100644 --- a/hw/riscv/Kconfig +++ b/hw/riscv/Kconfig @@ -9,6 +9,16 @@ config IBEX # RISC-V machines in alphabetical order +config CVA6 + bool + default y + depends on RISCV32 || RISCV64 + select DEVICE_TREE + select SIFIVE_PLIC + select XILINX_SPI + select RISCV_ACLINT + select UNIMP + config MICROCHIP_PFSOC bool default y diff --git a/hw/riscv/cva6.c b/hw/riscv/cva6.c new file mode 100644 index 0000000000..822714d794 --- /dev/null +++ b/hw/riscv/cva6.c @@ -0,0 +1,231 @@ +/* + * QEMU RISC-V Board for OpenHW CVA6 SoC + * + * Copyright (c) 2025 Codethink Ltd + * Ben Dooks <ben.dooks@codethink.co.uk> + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "qemu/error-report.h" +#include "qemu/units.h" +#include "qapi/error.h" +#include "qapi/visitor.h" +#include "hw/boards.h" +#include "hw/irq.h" +#include "hw/loader.h" +#include "hw/sysbus.h" +#include "hw/misc/unimp.h" + +#include "hw/sd/sd.h" +#include "hw/ssi/ssi.h" + +#include "hw/riscv/cva6.h" +#include "hw/riscv/boot.h" +#include "hw/intc/riscv_aclint.h" + +#include "system/system.h" + +#include <libfdt.h> + +#define CVA6_ROM_BASE 0x10000 + +static const MemMapEntry cva6_memmap[] = { + [CVA6_DEBUG] = { 0x0000000, 0x1000 }, + [CVA6_ROM] = { CVA6_ROM_BASE, 0x10000 }, + [CVA6_CLINT] = { 0x2000000, 0xC0000 }, + [CVA6_PLIC] = { 0xC000000, 0x4000000 }, + [CVA6_UART] = { 0x10000000, 0x1000 }, + [CVA6_TIMER] = { 0x18000000, 0x10000 }, + [CVA6_SPI] = { 0x20000000, 0x800000 }, + [CVA6_ETHERNET] = { 0x30000000, 0x10000 }, + [CVA6_GPIO] = { 0x40000000, 0x1000 }, + [CVA6_DRAM] = { 0x80000000, 0x40000000 }, +}; + +static void cva6_machine_init(MachineState *machine) +{ + MachineClass *mc = MACHINE_GET_CLASS(machine); + MemoryRegion *sys_mem = get_system_memory(); + hwaddr dram_addr = cva6_memmap[CVA6_DRAM].base; + CVA6State *s = CVA6_MACHINE(machine); + RISCVBootInfo boot_info; + + object_initialize_child(OBJECT(machine), "soc", &s->soc, TYPE_RISCV_CVA6); + qdev_realize(DEVICE(&s->soc), NULL, &error_fatal); + + if (machine->ram_size > mc->default_ram_size) { + error_report("RAM size is too big for DRAM area"); + exit(EXIT_FAILURE); + } + + memory_region_add_subregion(sys_mem, dram_addr, machine->ram); + riscv_boot_info_init(&boot_info, &s->soc.cpus); + + if (machine->firmware) { + hwaddr firmware_load_addr = cva6_memmap[CVA6_ROM].base; + riscv_load_firmware(machine->firmware, &firmware_load_addr, NULL); + } + + if (machine->kernel_filename) { + /* note - we've not tested just loading the kernel w/o uboot */ + riscv_load_kernel(machine, &boot_info, dram_addr, false, NULL); + } + +} + +static void cva6_machine_class_init(ObjectClass *oc, const void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + + mc->desc = "RISC-V board for CVA6"; + mc->init = cva6_machine_init; + mc->max_cpus = 1; + mc->default_ram_id = "cva6.ram"; + /* start with "max" cpu type until we sort out CVA6 type */ + mc->default_cpu_type = TYPE_RISCV_CPU_MAX; + mc->default_ram_size = cva6_memmap[CVA6_DRAM].size; +}; + +static void cva6_soc_init(Object *obj) +{ + CVA6SoCState *s = RISCV_CVA6(obj); + + object_initialize_child(obj, "cpus", &s->cpus, TYPE_RISCV_HART_ARRAY); +} + +static void cva6_add_spi(CVA6SoCState *s, const MemMapEntry *map) +{ + DriveInfo *dinfo; + BlockBackend *blk; + DeviceState *card_dev; + qemu_irq sd_cs; + DeviceState *sddev; + SysBusDevice *busdev; + DeviceState *spi_dev; + SSIBus *spi; + + spi_dev = qdev_new("xlnx.xps-spi"); + qdev_prop_set_uint8(spi_dev, "num-ss-bits", 1); + qdev_prop_set_string(spi_dev, "endianness", "little"); + + busdev = SYS_BUS_DEVICE(spi_dev); + sysbus_realize_and_unref(busdev, &error_fatal); + sysbus_mmio_map(busdev, 0, map->base); + sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(DEVICE(s->plic), CVA6_SPI_IRQ)); + + spi = (SSIBus *)qdev_get_child_bus(spi_dev, "spi"); + + sddev = ssi_create_peripheral(spi, "ssi-sd"); + sd_cs = qdev_get_gpio_in_named(sddev, SSI_GPIO_CS, 0); + sysbus_connect_irq(busdev, 1, sd_cs); + + dinfo = drive_get(IF_SD, 0, 0); + blk = dinfo ? blk_by_legacy_dinfo(dinfo) : NULL; + card_dev = qdev_new(TYPE_SD_CARD_SPI); + qdev_prop_set_drive_err(card_dev, "drive", blk, &error_fatal); + + qdev_realize_and_unref(card_dev, qdev_get_child_bus(sddev, "sd-bus"), &error_fatal); +} + +static void not_implemented(const char *name, const MemMapEntry *map) +{ + create_unimplemented_device(name, map->base, map->size); +} + +static void cva6_soc_realize(DeviceState *dev_soc, Error **errp) +{ + MemoryRegion *system_memory = get_system_memory(); + MachineState *ms = MACHINE(qdev_get_machine()); + CVA6SoCState *s = RISCV_CVA6(dev_soc); + const MemMapEntry *memmap = cva6_memmap; + MemoryRegion *rom = g_new(MemoryRegion, 1); + char *plic_hart_config; + + object_property_set_str(OBJECT(&s->cpus), "cpu-type", ms->cpu_type, + &error_abort); + object_property_set_int(OBJECT(&s->cpus), "num-harts", ms->smp.cpus, + &error_abort); + object_property_set_int(OBJECT(&s->cpus), "resetvec", CVA6_ROM_BASE, + &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&s->cpus), &error_fatal); + + /* boot rom */ + memory_region_init_rom(rom, OBJECT(dev_soc), "riscv.cva6.bootrom", + memmap[CVA6_ROM].size, &error_fatal); + memory_region_add_subregion(system_memory, memmap[CVA6_ROM].base, + rom); + + /* create PLIC hart topology configuration string */ + plic_hart_config = riscv_plic_hart_config_string(ms->smp.cpus); + + /* MMIO */ + s->plic = sifive_plic_create(memmap[CVA6_PLIC].base, + plic_hart_config, ms->smp.cpus, 0, + CVA6_PLIC_NUM_SOURCES, + CVA6_PLIC_NUM_PRIORITIES, + CVA6_PLIC_PRIORITY_BASE, + CVA6_PLIC_PENDING_BASE, + CVA6_PLIC_ENABLE_BASE, + CVA6_PLIC_ENABLE_STRIDE, + CVA6_PLIC_CONTEXT_BASE, + CVA6_PLIC_CONTEXT_STRIDE, + memmap[CVA6_PLIC].size); + g_free(plic_hart_config); + + riscv_aclint_swi_create(memmap[CVA6_CLINT].base, 0, + ms->smp.cpus, false); + +#define CLINT_TIMEBASE_FREQ 25000000 + riscv_aclint_mtimer_create( + memmap[CVA6_CLINT].base + RISCV_ACLINT_SWI_SIZE, + RISCV_ACLINT_DEFAULT_MTIMER_SIZE, 0, ms->smp.cpus, + RISCV_ACLINT_DEFAULT_MTIMECMP, RISCV_ACLINT_DEFAULT_MTIME, + CLINT_TIMEBASE_FREQ, true); + + /* something in cva6-sdk uboot seems to prod the debug + * unit by accident, so make it not implemented */ + not_implemented("debug", &memmap[CVA6_DEBUG]); + + /* 16550 uart, one 32bit register per 32bit word */ + + serial_mm_init(system_memory, memmap[CVA6_UART].base, 2, + qdev_get_gpio_in(DEVICE(s->plic), CVA6_UART_IRQ), + 50*1000*10000, + serial_hd(0), DEVICE_LITTLE_ENDIAN); + + /* just unimplement the timers, network and gpio here for now. + * no-one seems to be using the apb timer block anyway*/ + not_implemented("net", &memmap[CVA6_ETHERNET]); + not_implemented("gpio", &memmap[CVA6_GPIO]); + not_implemented("timer", &memmap[CVA6_TIMER]); + + /* connect xilinx spi block here */ + cva6_add_spi(s, &memmap[CVA6_SPI]); +} + +static void cva6_soc_class_init(ObjectClass *oc, const void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->realize = cva6_soc_realize; + dc->user_creatable = false; +}; + +static const TypeInfo cva6_types[] = { + { + .name = TYPE_RISCV_CVA6, + .parent = TYPE_DEVICE, + .instance_size = sizeof(CVA6SoCState), + .instance_init = cva6_soc_init, + .class_init = cva6_soc_class_init, + }, { + .name = TYPE_CVA6_MACHINE, + .parent = TYPE_MACHINE, + .instance_size = sizeof(CVA6State), + .class_init = cva6_machine_class_init, + } +}; + +DEFINE_TYPES(cva6_types) diff --git a/hw/riscv/meson.build b/hw/riscv/meson.build index c22f3a7216..a32fffab63 100644 --- a/hw/riscv/meson.build +++ b/hw/riscv/meson.build @@ -2,6 +2,7 @@ riscv_ss = ss.source_set() riscv_ss.add(files('boot.c')) riscv_ss.add(when: 'CONFIG_RISCV_NUMA', if_true: files('numa.c')) riscv_ss.add(files('riscv_hart.c')) +riscv_ss.add(when: 'CONFIG_CVA6', if_true: files('cva6.c')) riscv_ss.add(when: 'CONFIG_OPENTITAN', if_true: files('opentitan.c')) riscv_ss.add(when: 'CONFIG_RISCV_VIRT', if_true: files('virt.c')) riscv_ss.add(when: 'CONFIG_SHAKTI_C', if_true: files('shakti_c.c')) diff --git a/include/hw/riscv/cva6.h b/include/hw/riscv/cva6.h new file mode 100644 index 0000000000..2d82d7eaf0 --- /dev/null +++ b/include/hw/riscv/cva6.h @@ -0,0 +1,83 @@ +/* + * QEMU RISC-V Board for OpenHW CVA6 SoC + * + * Copyright (c) 2025 Codethink Ltd + * Ben Dooks <ben.dooks@codethink.co.uk> + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef HW_CVA6_H +#define HW_CVA6_H + +#include "hw/riscv/riscv_hart.h" +#include "hw/intc/sifive_plic.h" +#include "hw/char/serial-mm.h" + +#include "hw/boards.h" +#include "hw/sysbus.h" +#include "qom/object.h" + +#define TYPE_RISCV_CVA6 "riscv.cva6.soc" +OBJECT_DECLARE_SIMPLE_TYPE(CVA6SoCState, RISCV_CVA6) + +typedef struct CVA6SoCState { + /*< private >*/ + DeviceState parent_obj; + + /*< public >*/ + RISCVHartArrayState cpus; + DeviceState *plic; + MemoryRegion rom; + + uint32_t resetvec; +} CVA6SoCState; + +#define TYPE_CVA6_MACHINE MACHINE_TYPE_NAME("cva6") +OBJECT_DECLARE_SIMPLE_TYPE(CVA6State, CVA6_MACHINE) + +typedef struct CVA6State { + /*< private >*/ + MachineState parent_obj; + + /*< public >*/ + CVA6SoCState soc; +} +CVA6State; + +enum { + CVA6_DEBUG, + CVA6_ROM, + CVA6_CLINT, + CVA6_PLIC, + CVA6_UART, + CVA6_TIMER, + CVA6_SPI, + CVA6_ETHERNET, + CVA6_GPIO, + CVA6_DRAM, +}; + +enum { + CVA6_UART_IRQ = 1, + CVA6_SPI_IRQ = 2, + CVA6_ETH_IRQ = 3, + CVA6_TIMER0_OVF_IRQ = 4, + CVA6_TIMER0_CMP_IRQ = 5, + CVA6_TIMER1_OVF_IRQ = 6, + CVA6_TIMER1_CMP_IRQ = 7, +}; + +/* plic register interface in corev_apu/rv_plic/rtl/plic_regmap.sv */ + +#define CVA6_PLIC_NUM_SOURCES 32 +#define CVA6_PLIC_NUM_PRIORITIES 7 +#define CVA6_PLIC_PRIORITY_BASE 0x0000 +#define CVA6_PLIC_PENDING_BASE 0x1000 +#define CVA6_PLIC_ENABLE_BASE 0x2000 +#define CVA6_PLIC_ENABLE_STRIDE 0x80 +#define CVA6_PLIC_CONTEXT_BASE 0x200000 +#define CVA6_PLIC_CONTEXT_STRIDE 0x1000 + +#endif + -- 2.37.2.352.g3c44437643 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH 1/2] hw/riscv: add CVA6 machine 2025-05-21 15:54 ` [PATCH 1/2] hw/riscv: add CVA6 machine Ben Dooks @ 2025-05-26 10:10 ` Daniel Henrique Barboza 2025-05-27 11:30 ` Ben Dooks 0 siblings, 1 reply; 6+ messages in thread From: Daniel Henrique Barboza @ 2025-05-26 10:10 UTC (permalink / raw) To: Ben Dooks, nazar.kazakov, joseph.baker, fran.redondo, lawrence.hunter, liwei1518, zhiwei_liu, qemu-riscv Cc: qemu-devel On 5/21/25 12:54 PM, Ben Dooks wrote: > Add a (currently Genesy2 based) CVA6 machine. > > Has SPI and UART, the GPIO and Ethernet are currently black-holed > as there is no hardware model for them (lowRISC ethernet and Xilinx > GPIO) > > Signed-off-by: Ben Dooks <ben.dooks@codethink.co.uk> > --- Please remove the blank line at the EOF in include/hw/riscv/cva6.h: $ git am \[PATCH\ 1_2\]\ hw_riscv\:\ add\ CVA6\ machine\ -\ Ben\ Dooks\ \<ben.dooks@codethink.co.uk\>\ -\ 2025-05-21\ 1254.eml Applying: hw/riscv: add CVA6 machine .git/rebase-apply/patch:372: new blank line at EOF. + warning: 1 line adds whitespace errors. > - squashed in fixes for sd-card and new qemu init > - move to spdx for cva6 machine > - code cleanups missed in first review > --- > hw/riscv/Kconfig | 10 ++ > hw/riscv/cva6.c | 231 ++++++++++++++++++++++++++++++++++++++++ > hw/riscv/meson.build | 1 + > include/hw/riscv/cva6.h | 83 +++++++++++++++ > 4 files changed, 325 insertions(+) > create mode 100644 hw/riscv/cva6.c > create mode 100644 include/hw/riscv/cva6.h > > diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig > index e6a0ac1fa1..b96f6fa014 100644 > --- a/hw/riscv/Kconfig > +++ b/hw/riscv/Kconfig > @@ -9,6 +9,16 @@ config IBEX > > # RISC-V machines in alphabetical order > > +config CVA6 > + bool > + default y > + depends on RISCV32 || RISCV64 > + select DEVICE_TREE > + select SIFIVE_PLIC > + select XILINX_SPI > + select RISCV_ACLINT > + select UNIMP > + > config MICROCHIP_PFSOC > bool > default y > diff --git a/hw/riscv/cva6.c b/hw/riscv/cva6.c > new file mode 100644 > index 0000000000..822714d794 > --- /dev/null > +++ b/hw/riscv/cva6.c > @@ -0,0 +1,231 @@ > +/* > + * QEMU RISC-V Board for OpenHW CVA6 SoC > + * > + * Copyright (c) 2025 Codethink Ltd > + * Ben Dooks <ben.dooks@codethink.co.uk> > + * > + * SPDX-License-Identifier: GPL-2.0-or-later > + */ > + > +#include "qemu/osdep.h" > +#include "qemu/error-report.h" > +#include "qemu/units.h" > +#include "qapi/error.h" > +#include "qapi/visitor.h" > +#include "hw/boards.h" > +#include "hw/irq.h" > +#include "hw/loader.h" > +#include "hw/sysbus.h" > +#include "hw/misc/unimp.h" > + > +#include "hw/sd/sd.h" > +#include "hw/ssi/ssi.h" > + > +#include "hw/riscv/cva6.h" > +#include "hw/riscv/boot.h" > +#include "hw/intc/riscv_aclint.h" > + > +#include "system/system.h" > + > +#include <libfdt.h> > + > +#define CVA6_ROM_BASE 0x10000 > + > +static const MemMapEntry cva6_memmap[] = { > + [CVA6_DEBUG] = { 0x0000000, 0x1000 }, > + [CVA6_ROM] = { CVA6_ROM_BASE, 0x10000 }, > + [CVA6_CLINT] = { 0x2000000, 0xC0000 }, > + [CVA6_PLIC] = { 0xC000000, 0x4000000 }, > + [CVA6_UART] = { 0x10000000, 0x1000 }, > + [CVA6_TIMER] = { 0x18000000, 0x10000 }, > + [CVA6_SPI] = { 0x20000000, 0x800000 }, > + [CVA6_ETHERNET] = { 0x30000000, 0x10000 }, > + [CVA6_GPIO] = { 0x40000000, 0x1000 }, > + [CVA6_DRAM] = { 0x80000000, 0x40000000 }, > +}; > + > +static void cva6_machine_init(MachineState *machine) > +{ > + MachineClass *mc = MACHINE_GET_CLASS(machine); > + MemoryRegion *sys_mem = get_system_memory(); > + hwaddr dram_addr = cva6_memmap[CVA6_DRAM].base; > + CVA6State *s = CVA6_MACHINE(machine); > + RISCVBootInfo boot_info; > + > + object_initialize_child(OBJECT(machine), "soc", &s->soc, TYPE_RISCV_CVA6); > + qdev_realize(DEVICE(&s->soc), NULL, &error_fatal); > + > + if (machine->ram_size > mc->default_ram_size) { > + error_report("RAM size is too big for DRAM area"); > + exit(EXIT_FAILURE); > + } > + > + memory_region_add_subregion(sys_mem, dram_addr, machine->ram); > + riscv_boot_info_init(&boot_info, &s->soc.cpus); > + > + if (machine->firmware) { > + hwaddr firmware_load_addr = cva6_memmap[CVA6_ROM].base; > + riscv_load_firmware(machine->firmware, &firmware_load_addr, NULL); > + } > + > + if (machine->kernel_filename) { > + /* note - we've not tested just loading the kernel w/o uboot */ > + riscv_load_kernel(machine, &boot_info, dram_addr, false, NULL); > + } > + > +} > + > +static void cva6_machine_class_init(ObjectClass *oc, const void *data) > +{ > + MachineClass *mc = MACHINE_CLASS(oc); > + > + mc->desc = "RISC-V board for CVA6"; > + mc->init = cva6_machine_init; > + mc->max_cpus = 1; > + mc->default_ram_id = "cva6.ram"; > + /* start with "max" cpu type until we sort out CVA6 type */ > + mc->default_cpu_type = TYPE_RISCV_CPU_MAX; > + mc->default_ram_size = cva6_memmap[CVA6_DRAM].size; > +}; > + > +static void cva6_soc_init(Object *obj) > +{ > + CVA6SoCState *s = RISCV_CVA6(obj); > + > + object_initialize_child(obj, "cpus", &s->cpus, TYPE_RISCV_HART_ARRAY); > +} > + > +static void cva6_add_spi(CVA6SoCState *s, const MemMapEntry *map) > +{ > + DriveInfo *dinfo; > + BlockBackend *blk; > + DeviceState *card_dev; > + qemu_irq sd_cs; > + DeviceState *sddev; > + SysBusDevice *busdev; > + DeviceState *spi_dev; > + SSIBus *spi; > + > + spi_dev = qdev_new("xlnx.xps-spi"); > + qdev_prop_set_uint8(spi_dev, "num-ss-bits", 1); > + qdev_prop_set_string(spi_dev, "endianness", "little"); > + > + busdev = SYS_BUS_DEVICE(spi_dev); > + sysbus_realize_and_unref(busdev, &error_fatal); > + sysbus_mmio_map(busdev, 0, map->base); > + sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(DEVICE(s->plic), CVA6_SPI_IRQ)); > + > + spi = (SSIBus *)qdev_get_child_bus(spi_dev, "spi"); > + > + sddev = ssi_create_peripheral(spi, "ssi-sd"); > + sd_cs = qdev_get_gpio_in_named(sddev, SSI_GPIO_CS, 0); > + sysbus_connect_irq(busdev, 1, sd_cs); > + > + dinfo = drive_get(IF_SD, 0, 0); > + blk = dinfo ? blk_by_legacy_dinfo(dinfo) : NULL; > + card_dev = qdev_new(TYPE_SD_CARD_SPI); > + qdev_prop_set_drive_err(card_dev, "drive", blk, &error_fatal); > + > + qdev_realize_and_unref(card_dev, qdev_get_child_bus(sddev, "sd-bus"), &error_fatal); > +} > + > +static void not_implemented(const char *name, const MemMapEntry *map) > +{ > + create_unimplemented_device(name, map->base, map->size); > +} > + > +static void cva6_soc_realize(DeviceState *dev_soc, Error **errp) > +{ > + MemoryRegion *system_memory = get_system_memory(); > + MachineState *ms = MACHINE(qdev_get_machine()); > + CVA6SoCState *s = RISCV_CVA6(dev_soc); > + const MemMapEntry *memmap = cva6_memmap; > + MemoryRegion *rom = g_new(MemoryRegion, 1); > + char *plic_hart_config; You can use g_autofree char *plic_hart_config = NULL; And avoid the g_free() call afterwards. > + > + object_property_set_str(OBJECT(&s->cpus), "cpu-type", ms->cpu_type, > + &error_abort); > + object_property_set_int(OBJECT(&s->cpus), "num-harts", ms->smp.cpus, > + &error_abort); > + object_property_set_int(OBJECT(&s->cpus), "resetvec", CVA6_ROM_BASE, > + &error_abort); > + sysbus_realize(SYS_BUS_DEVICE(&s->cpus), &error_fatal); > + > + /* boot rom */ > + memory_region_init_rom(rom, OBJECT(dev_soc), "riscv.cva6.bootrom", > + memmap[CVA6_ROM].size, &error_fatal); > + memory_region_add_subregion(system_memory, memmap[CVA6_ROM].base, > + rom); > + > + /* create PLIC hart topology configuration string */ > + plic_hart_config = riscv_plic_hart_config_string(ms->smp.cpus); > + > + /* MMIO */ > + s->plic = sifive_plic_create(memmap[CVA6_PLIC].base, > + plic_hart_config, ms->smp.cpus, 0, > + CVA6_PLIC_NUM_SOURCES, > + CVA6_PLIC_NUM_PRIORITIES, > + CVA6_PLIC_PRIORITY_BASE, > + CVA6_PLIC_PENDING_BASE, > + CVA6_PLIC_ENABLE_BASE, > + CVA6_PLIC_ENABLE_STRIDE, > + CVA6_PLIC_CONTEXT_BASE, > + CVA6_PLIC_CONTEXT_STRIDE, > + memmap[CVA6_PLIC].size); > + g_free(plic_hart_config); > + > + riscv_aclint_swi_create(memmap[CVA6_CLINT].base, 0, > + ms->smp.cpus, false); > + > +#define CLINT_TIMEBASE_FREQ 25000000 Although we have some instances of macros being defined inside functions, when a macro is doing something that is only relevant inside the function scope, this is not a pattern we want to promote. Please move this define outside cva6_soc_realize(), preferably at the start of the file. > + riscv_aclint_mtimer_create( > + memmap[CVA6_CLINT].base + RISCV_ACLINT_SWI_SIZE, > + RISCV_ACLINT_DEFAULT_MTIMER_SIZE, 0, ms->smp.cpus, > + RISCV_ACLINT_DEFAULT_MTIMECMP, RISCV_ACLINT_DEFAULT_MTIME, > + CLINT_TIMEBASE_FREQ, true); > + > + /* something in cva6-sdk uboot seems to prod the debug > + * unit by accident, so make it not implemented */ > + not_implemented("debug", &memmap[CVA6_DEBUG]); > + > + /* 16550 uart, one 32bit register per 32bit word */ > + > + serial_mm_init(system_memory, memmap[CVA6_UART].base, 2, > + qdev_get_gpio_in(DEVICE(s->plic), CVA6_UART_IRQ), > + 50*1000*10000, > + serial_hd(0), DEVICE_LITTLE_ENDIAN); > + > + /* just unimplement the timers, network and gpio here for now. > + * no-one seems to be using the apb timer block anyway*/ > + not_implemented("net", &memmap[CVA6_ETHERNET]); > + not_implemented("gpio", &memmap[CVA6_GPIO]); > + not_implemented("timer", &memmap[CVA6_TIMER]); > + > + /* connect xilinx spi block here */ > + cva6_add_spi(s, &memmap[CVA6_SPI]); > +} > + > +static void cva6_soc_class_init(ObjectClass *oc, const void *data) > +{ > + DeviceClass *dc = DEVICE_CLASS(oc); > + > + dc->realize = cva6_soc_realize; > + dc->user_creatable = false; > +}; > + > +static const TypeInfo cva6_types[] = { > + { > + .name = TYPE_RISCV_CVA6, > + .parent = TYPE_DEVICE, > + .instance_size = sizeof(CVA6SoCState), > + .instance_init = cva6_soc_init, > + .class_init = cva6_soc_class_init, > + }, { > + .name = TYPE_CVA6_MACHINE, > + .parent = TYPE_MACHINE, > + .instance_size = sizeof(CVA6State), > + .class_init = cva6_machine_class_init, > + } > +}; > + > +DEFINE_TYPES(cva6_types) > diff --git a/hw/riscv/meson.build b/hw/riscv/meson.build > index c22f3a7216..a32fffab63 100644 > --- a/hw/riscv/meson.build > +++ b/hw/riscv/meson.build > @@ -2,6 +2,7 @@ riscv_ss = ss.source_set() > riscv_ss.add(files('boot.c')) > riscv_ss.add(when: 'CONFIG_RISCV_NUMA', if_true: files('numa.c')) > riscv_ss.add(files('riscv_hart.c')) > +riscv_ss.add(when: 'CONFIG_CVA6', if_true: files('cva6.c')) > riscv_ss.add(when: 'CONFIG_OPENTITAN', if_true: files('opentitan.c')) > riscv_ss.add(when: 'CONFIG_RISCV_VIRT', if_true: files('virt.c')) > riscv_ss.add(when: 'CONFIG_SHAKTI_C', if_true: files('shakti_c.c')) > diff --git a/include/hw/riscv/cva6.h b/include/hw/riscv/cva6.h > new file mode 100644 > index 0000000000..2d82d7eaf0 > --- /dev/null > +++ b/include/hw/riscv/cva6.h > @@ -0,0 +1,83 @@ > +/* > + * QEMU RISC-V Board for OpenHW CVA6 SoC > + * > + * Copyright (c) 2025 Codethink Ltd > + * Ben Dooks <ben.dooks@codethink.co.uk> > + * > + * SPDX-License-Identifier: GPL-2.0-or-later > + */ > + > +#ifndef HW_CVA6_H > +#define HW_CVA6_H > + > +#include "hw/riscv/riscv_hart.h" > +#include "hw/intc/sifive_plic.h" > +#include "hw/char/serial-mm.h" > + > +#include "hw/boards.h" > +#include "hw/sysbus.h" > +#include "qom/object.h" > + > +#define TYPE_RISCV_CVA6 "riscv.cva6.soc" > +OBJECT_DECLARE_SIMPLE_TYPE(CVA6SoCState, RISCV_CVA6) > + > +typedef struct CVA6SoCState { > + /*< private >*/ > + DeviceState parent_obj; > + > + /*< public >*/ > + RISCVHartArrayState cpus; > + DeviceState *plic; > + MemoryRegion rom; > + > + uint32_t resetvec; > +} CVA6SoCState; > + > +#define TYPE_CVA6_MACHINE MACHINE_TYPE_NAME("cva6") > +OBJECT_DECLARE_SIMPLE_TYPE(CVA6State, CVA6_MACHINE) > + > +typedef struct CVA6State { > + /*< private >*/ > + MachineState parent_obj; > + > + /*< public >*/ > + CVA6SoCState soc; > +} > +CVA6State; > + > +enum { > + CVA6_DEBUG, > + CVA6_ROM, > + CVA6_CLINT, > + CVA6_PLIC, > + CVA6_UART, > + CVA6_TIMER, > + CVA6_SPI, > + CVA6_ETHERNET, > + CVA6_GPIO, > + CVA6_DRAM, > +}; > + > +enum { > + CVA6_UART_IRQ = 1, > + CVA6_SPI_IRQ = 2, > + CVA6_ETH_IRQ = 3, > + CVA6_TIMER0_OVF_IRQ = 4, > + CVA6_TIMER0_CMP_IRQ = 5, > + CVA6_TIMER1_OVF_IRQ = 6, > + CVA6_TIMER1_CMP_IRQ = 7, > +}; > + > +/* plic register interface in corev_apu/rv_plic/rtl/plic_regmap.sv */ Where is this file? It's not on QEMU or Linux. I'm assuming that you're referring to plic_regmap.sv from this repo: https://github.com/openhwgroup/cva6/tree/master/corev_apu If that's the case we need to point to this repo in the comment. The commit msg also works. Thanks, Daniel > + > +#define CVA6_PLIC_NUM_SOURCES 32 > +#define CVA6_PLIC_NUM_PRIORITIES 7 > +#define CVA6_PLIC_PRIORITY_BASE 0x0000 > +#define CVA6_PLIC_PENDING_BASE 0x1000 > +#define CVA6_PLIC_ENABLE_BASE 0x2000 > +#define CVA6_PLIC_ENABLE_STRIDE 0x80 > +#define CVA6_PLIC_CONTEXT_BASE 0x200000 > +#define CVA6_PLIC_CONTEXT_STRIDE 0x1000 > + > +#endif > + ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 1/2] hw/riscv: add CVA6 machine 2025-05-26 10:10 ` Daniel Henrique Barboza @ 2025-05-27 11:30 ` Ben Dooks 0 siblings, 0 replies; 6+ messages in thread From: Ben Dooks @ 2025-05-27 11:30 UTC (permalink / raw) To: Daniel Henrique Barboza, nazar.kazakov, joseph.baker, fran.redondo, lawrence.hunter, liwei1518, zhiwei_liu, qemu-riscv Cc: qemu-devel On 26/05/2025 11:10, Daniel Henrique Barboza wrote: > > > On 5/21/25 12:54 PM, Ben Dooks wrote: >> Add a (currently Genesy2 based) CVA6 machine. >> >> Has SPI and UART, the GPIO and Ethernet are currently black-holed >> as there is no hardware model for them (lowRISC ethernet and Xilinx >> GPIO) >> >> Signed-off-by: Ben Dooks <ben.dooks@codethink.co.uk> >> --- > > Please remove the blank line at the EOF in include/hw/riscv/cva6.h: > > $ git am \[PATCH\ 1_2\]\ hw_riscv\:\ add\ CVA6\ machine\ -\ Ben\ Dooks\ > \<ben.dooks@codethink.co.uk\>\ -\ 2025-05-21\ 1254.eml > Applying: hw/riscv: add CVA6 machine > .git/rebase-apply/patch:372: new blank line at EOF. > + > warning: 1 line adds whitespace errors. > > >> - squashed in fixes for sd-card and new qemu init >> - move to spdx for cva6 machine >> - code cleanups missed in first review >> --- >> hw/riscv/Kconfig | 10 ++ >> hw/riscv/cva6.c | 231 ++++++++++++++++++++++++++++++++++++++++ >> hw/riscv/meson.build | 1 + >> include/hw/riscv/cva6.h | 83 +++++++++++++++ >> 4 files changed, 325 insertions(+) >> create mode 100644 hw/riscv/cva6.c >> create mode 100644 include/hw/riscv/cva6.h >> >> diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig >> index e6a0ac1fa1..b96f6fa014 100644 >> --- a/hw/riscv/Kconfig >> +++ b/hw/riscv/Kconfig >> @@ -9,6 +9,16 @@ config IBEX >> # RISC-V machines in alphabetical order >> +config CVA6 >> + bool >> + default y >> + depends on RISCV32 || RISCV64 >> + select DEVICE_TREE >> + select SIFIVE_PLIC >> + select XILINX_SPI >> + select RISCV_ACLINT >> + select UNIMP >> + >> config MICROCHIP_PFSOC >> bool >> default y >> diff --git a/hw/riscv/cva6.c b/hw/riscv/cva6.c >> new file mode 100644 >> index 0000000000..822714d794 >> --- /dev/null >> +++ b/hw/riscv/cva6.c >> @@ -0,0 +1,231 @@ >> +/* >> + * QEMU RISC-V Board for OpenHW CVA6 SoC >> + * >> + * Copyright (c) 2025 Codethink Ltd >> + * Ben Dooks <ben.dooks@codethink.co.uk> >> + * >> + * SPDX-License-Identifier: GPL-2.0-or-later >> + */ >> + >> +#include "qemu/osdep.h" >> +#include "qemu/error-report.h" >> +#include "qemu/units.h" >> +#include "qapi/error.h" >> +#include "qapi/visitor.h" >> +#include "hw/boards.h" >> +#include "hw/irq.h" >> +#include "hw/loader.h" >> +#include "hw/sysbus.h" >> +#include "hw/misc/unimp.h" >> + >> +#include "hw/sd/sd.h" >> +#include "hw/ssi/ssi.h" >> + >> +#include "hw/riscv/cva6.h" >> +#include "hw/riscv/boot.h" >> +#include "hw/intc/riscv_aclint.h" >> + >> +#include "system/system.h" >> + >> +#include <libfdt.h> >> + >> +#define CVA6_ROM_BASE 0x10000 >> + >> +static const MemMapEntry cva6_memmap[] = { >> + [CVA6_DEBUG] = { 0x0000000, 0x1000 }, >> + [CVA6_ROM] = { CVA6_ROM_BASE, 0x10000 }, >> + [CVA6_CLINT] = { 0x2000000, 0xC0000 }, >> + [CVA6_PLIC] = { 0xC000000, 0x4000000 }, >> + [CVA6_UART] = { 0x10000000, 0x1000 }, >> + [CVA6_TIMER] = { 0x18000000, 0x10000 }, >> + [CVA6_SPI] = { 0x20000000, 0x800000 }, >> + [CVA6_ETHERNET] = { 0x30000000, 0x10000 }, >> + [CVA6_GPIO] = { 0x40000000, 0x1000 }, >> + [CVA6_DRAM] = { 0x80000000, 0x40000000 }, >> +}; >> + >> +static void cva6_machine_init(MachineState *machine) >> +{ >> + MachineClass *mc = MACHINE_GET_CLASS(machine); >> + MemoryRegion *sys_mem = get_system_memory(); >> + hwaddr dram_addr = cva6_memmap[CVA6_DRAM].base; >> + CVA6State *s = CVA6_MACHINE(machine); >> + RISCVBootInfo boot_info; >> + >> + object_initialize_child(OBJECT(machine), "soc", &s->soc, >> TYPE_RISCV_CVA6); >> + qdev_realize(DEVICE(&s->soc), NULL, &error_fatal); >> + >> + if (machine->ram_size > mc->default_ram_size) { >> + error_report("RAM size is too big for DRAM area"); >> + exit(EXIT_FAILURE); >> + } >> + >> + memory_region_add_subregion(sys_mem, dram_addr, machine->ram); >> + riscv_boot_info_init(&boot_info, &s->soc.cpus); >> + >> + if (machine->firmware) { >> + hwaddr firmware_load_addr = cva6_memmap[CVA6_ROM].base; >> + riscv_load_firmware(machine->firmware, &firmware_load_addr, >> NULL); >> + } >> + >> + if (machine->kernel_filename) { >> + /* note - we've not tested just loading the kernel w/o uboot */ >> + riscv_load_kernel(machine, &boot_info, dram_addr, false, NULL); >> + } >> + >> +} >> + >> +static void cva6_machine_class_init(ObjectClass *oc, const void *data) >> +{ >> + MachineClass *mc = MACHINE_CLASS(oc); >> + >> + mc->desc = "RISC-V board for CVA6"; >> + mc->init = cva6_machine_init; >> + mc->max_cpus = 1; >> + mc->default_ram_id = "cva6.ram"; >> + /* start with "max" cpu type until we sort out CVA6 type */ >> + mc->default_cpu_type = TYPE_RISCV_CPU_MAX; >> + mc->default_ram_size = cva6_memmap[CVA6_DRAM].size; >> +}; >> + >> +static void cva6_soc_init(Object *obj) >> +{ >> + CVA6SoCState *s = RISCV_CVA6(obj); >> + >> + object_initialize_child(obj, "cpus", &s->cpus, >> TYPE_RISCV_HART_ARRAY); >> +} >> + >> +static void cva6_add_spi(CVA6SoCState *s, const MemMapEntry *map) >> +{ >> + DriveInfo *dinfo; >> + BlockBackend *blk; >> + DeviceState *card_dev; >> + qemu_irq sd_cs; >> + DeviceState *sddev; >> + SysBusDevice *busdev; >> + DeviceState *spi_dev; >> + SSIBus *spi; >> + >> + spi_dev = qdev_new("xlnx.xps-spi"); >> + qdev_prop_set_uint8(spi_dev, "num-ss-bits", 1); >> + qdev_prop_set_string(spi_dev, "endianness", "little"); >> + >> + busdev = SYS_BUS_DEVICE(spi_dev); >> + sysbus_realize_and_unref(busdev, &error_fatal); >> + sysbus_mmio_map(busdev, 0, map->base); >> + sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(DEVICE(s->plic), >> CVA6_SPI_IRQ)); >> + >> + spi = (SSIBus *)qdev_get_child_bus(spi_dev, "spi"); >> + >> + sddev = ssi_create_peripheral(spi, "ssi-sd"); >> + sd_cs = qdev_get_gpio_in_named(sddev, SSI_GPIO_CS, 0); >> + sysbus_connect_irq(busdev, 1, sd_cs); >> + >> + dinfo = drive_get(IF_SD, 0, 0); >> + blk = dinfo ? blk_by_legacy_dinfo(dinfo) : NULL; >> + card_dev = qdev_new(TYPE_SD_CARD_SPI); >> + qdev_prop_set_drive_err(card_dev, "drive", blk, &error_fatal); >> + >> + qdev_realize_and_unref(card_dev, qdev_get_child_bus(sddev, "sd- >> bus"), &error_fatal); >> +} >> + >> +static void not_implemented(const char *name, const MemMapEntry *map) >> +{ >> + create_unimplemented_device(name, map->base, map->size); >> +} >> + >> +static void cva6_soc_realize(DeviceState *dev_soc, Error **errp) >> +{ >> + MemoryRegion *system_memory = get_system_memory(); >> + MachineState *ms = MACHINE(qdev_get_machine()); >> + CVA6SoCState *s = RISCV_CVA6(dev_soc); >> + const MemMapEntry *memmap = cva6_memmap; >> + MemoryRegion *rom = g_new(MemoryRegion, 1); >> + char *plic_hart_config; > > You can use > > g_autofree char *plic_hart_config = NULL; > > > And avoid the g_free() call afterwards. > >> + >> + object_property_set_str(OBJECT(&s->cpus), "cpu-type", ms->cpu_type, >> + &error_abort); >> + object_property_set_int(OBJECT(&s->cpus), "num-harts", ms->smp.cpus, >> + &error_abort); >> + object_property_set_int(OBJECT(&s->cpus), "resetvec", CVA6_ROM_BASE, >> + &error_abort); >> + sysbus_realize(SYS_BUS_DEVICE(&s->cpus), &error_fatal); >> + >> + /* boot rom */ >> + memory_region_init_rom(rom, OBJECT(dev_soc), "riscv.cva6.bootrom", >> + memmap[CVA6_ROM].size, &error_fatal); >> + memory_region_add_subregion(system_memory, memmap[CVA6_ROM].base, >> + rom); >> + >> + /* create PLIC hart topology configuration string */ >> + plic_hart_config = riscv_plic_hart_config_string(ms->smp.cpus); >> + >> + /* MMIO */ >> + s->plic = sifive_plic_create(memmap[CVA6_PLIC].base, >> + plic_hart_config, ms->smp.cpus, 0, >> + CVA6_PLIC_NUM_SOURCES, >> + CVA6_PLIC_NUM_PRIORITIES, >> + CVA6_PLIC_PRIORITY_BASE, >> + CVA6_PLIC_PENDING_BASE, >> + CVA6_PLIC_ENABLE_BASE, >> + CVA6_PLIC_ENABLE_STRIDE, >> + CVA6_PLIC_CONTEXT_BASE, >> + CVA6_PLIC_CONTEXT_STRIDE, >> + memmap[CVA6_PLIC].size); >> + g_free(plic_hart_config); >> + >> + riscv_aclint_swi_create(memmap[CVA6_CLINT].base, 0, >> + ms->smp.cpus, false); >> + >> +#define CLINT_TIMEBASE_FREQ 25000000 > > Although we have some instances of macros being defined inside functions, > when a macro is doing something that is only relevant inside the function > scope, this is not a pattern we want to promote. > > Please move this define outside cva6_soc_realize(), preferably at the start > of the file. > > >> + riscv_aclint_mtimer_create( >> + memmap[CVA6_CLINT].base + RISCV_ACLINT_SWI_SIZE, >> + RISCV_ACLINT_DEFAULT_MTIMER_SIZE, 0, ms->smp.cpus, >> + RISCV_ACLINT_DEFAULT_MTIMECMP, RISCV_ACLINT_DEFAULT_MTIME, >> + CLINT_TIMEBASE_FREQ, true); >> + >> + /* something in cva6-sdk uboot seems to prod the debug >> + * unit by accident, so make it not implemented */ >> + not_implemented("debug", &memmap[CVA6_DEBUG]); >> + >> + /* 16550 uart, one 32bit register per 32bit word */ >> + >> + serial_mm_init(system_memory, memmap[CVA6_UART].base, 2, >> + qdev_get_gpio_in(DEVICE(s->plic), CVA6_UART_IRQ), >> + 50*1000*10000, >> + serial_hd(0), DEVICE_LITTLE_ENDIAN); >> + >> + /* just unimplement the timers, network and gpio here for now. >> + * no-one seems to be using the apb timer block anyway*/ >> + not_implemented("net", &memmap[CVA6_ETHERNET]); >> + not_implemented("gpio", &memmap[CVA6_GPIO]); >> + not_implemented("timer", &memmap[CVA6_TIMER]); >> + >> + /* connect xilinx spi block here */ >> + cva6_add_spi(s, &memmap[CVA6_SPI]); >> +} >> + >> +static void cva6_soc_class_init(ObjectClass *oc, const void *data) >> +{ >> + DeviceClass *dc = DEVICE_CLASS(oc); >> + >> + dc->realize = cva6_soc_realize; >> + dc->user_creatable = false; >> +}; >> + >> +static const TypeInfo cva6_types[] = { >> + { >> + .name = TYPE_RISCV_CVA6, >> + .parent = TYPE_DEVICE, >> + .instance_size = sizeof(CVA6SoCState), >> + .instance_init = cva6_soc_init, >> + .class_init = cva6_soc_class_init, >> + }, { >> + .name = TYPE_CVA6_MACHINE, >> + .parent = TYPE_MACHINE, >> + .instance_size = sizeof(CVA6State), >> + .class_init = cva6_machine_class_init, >> + } >> +}; >> + >> +DEFINE_TYPES(cva6_types) >> diff --git a/hw/riscv/meson.build b/hw/riscv/meson.build >> index c22f3a7216..a32fffab63 100644 >> --- a/hw/riscv/meson.build >> +++ b/hw/riscv/meson.build >> @@ -2,6 +2,7 @@ riscv_ss = ss.source_set() >> riscv_ss.add(files('boot.c')) >> riscv_ss.add(when: 'CONFIG_RISCV_NUMA', if_true: files('numa.c')) >> riscv_ss.add(files('riscv_hart.c')) >> +riscv_ss.add(when: 'CONFIG_CVA6', if_true: files('cva6.c')) >> riscv_ss.add(when: 'CONFIG_OPENTITAN', if_true: files('opentitan.c')) >> riscv_ss.add(when: 'CONFIG_RISCV_VIRT', if_true: files('virt.c')) >> riscv_ss.add(when: 'CONFIG_SHAKTI_C', if_true: files('shakti_c.c')) >> diff --git a/include/hw/riscv/cva6.h b/include/hw/riscv/cva6.h >> new file mode 100644 >> index 0000000000..2d82d7eaf0 >> --- /dev/null >> +++ b/include/hw/riscv/cva6.h >> @@ -0,0 +1,83 @@ >> +/* >> + * QEMU RISC-V Board for OpenHW CVA6 SoC >> + * >> + * Copyright (c) 2025 Codethink Ltd >> + * Ben Dooks <ben.dooks@codethink.co.uk> >> + * >> + * SPDX-License-Identifier: GPL-2.0-or-later >> + */ >> + >> +#ifndef HW_CVA6_H >> +#define HW_CVA6_H >> + >> +#include "hw/riscv/riscv_hart.h" >> +#include "hw/intc/sifive_plic.h" >> +#include "hw/char/serial-mm.h" >> + >> +#include "hw/boards.h" >> +#include "hw/sysbus.h" >> +#include "qom/object.h" >> + >> +#define TYPE_RISCV_CVA6 "riscv.cva6.soc" >> +OBJECT_DECLARE_SIMPLE_TYPE(CVA6SoCState, RISCV_CVA6) >> + >> +typedef struct CVA6SoCState { >> + /*< private >*/ >> + DeviceState parent_obj; >> + >> + /*< public >*/ >> + RISCVHartArrayState cpus; >> + DeviceState *plic; >> + MemoryRegion rom; >> + >> + uint32_t resetvec; >> +} CVA6SoCState; >> + >> +#define TYPE_CVA6_MACHINE MACHINE_TYPE_NAME("cva6") >> +OBJECT_DECLARE_SIMPLE_TYPE(CVA6State, CVA6_MACHINE) >> + >> +typedef struct CVA6State { >> + /*< private >*/ >> + MachineState parent_obj; >> + >> + /*< public >*/ >> + CVA6SoCState soc; >> +} >> +CVA6State; >> + >> +enum { >> + CVA6_DEBUG, >> + CVA6_ROM, >> + CVA6_CLINT, >> + CVA6_PLIC, >> + CVA6_UART, >> + CVA6_TIMER, >> + CVA6_SPI, >> + CVA6_ETHERNET, >> + CVA6_GPIO, >> + CVA6_DRAM, >> +}; >> + >> +enum { >> + CVA6_UART_IRQ = 1, >> + CVA6_SPI_IRQ = 2, >> + CVA6_ETH_IRQ = 3, >> + CVA6_TIMER0_OVF_IRQ = 4, >> + CVA6_TIMER0_CMP_IRQ = 5, >> + CVA6_TIMER1_OVF_IRQ = 6, >> + CVA6_TIMER1_CMP_IRQ = 7, >> +}; >> + >> +/* plic register interface in corev_apu/rv_plic/rtl/plic_regmap.sv */ > > > Where is this file? It's not on QEMU or Linux. > > I'm assuming that you're referring to plic_regmap.sv from this repo: > > https://github.com/openhwgroup/cva6/tree/master/corev_apu > > If that's the case we need to point to this repo in the comment. The commit > msg also works. > Great, thanks for the review. I've sent a new series out. -- Ben Dooks http://www.codethink.co.uk/ Senior Engineer Codethink - Providing Genius https://www.codethink.co.uk/privacy.html ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 2/2] target/riscv: add cva6 cpu type 2025-05-21 15:54 Adding CVA6 machine to RISC-V Ben Dooks 2025-05-21 15:54 ` [PATCH 1/2] hw/riscv: add CVA6 machine Ben Dooks @ 2025-05-21 15:54 ` Ben Dooks 2025-05-26 10:12 ` Daniel Henrique Barboza 1 sibling, 1 reply; 6+ messages in thread From: Ben Dooks @ 2025-05-21 15:54 UTC (permalink / raw) To: nazar.kazakov, joseph.baker, fran.redondo, lawrence.hunter, liwei1518, dbarboza, zhiwei_liu, qemu-riscv Cc: ben.dooks, qemu-devel Add CVA6 CPU type, for the OpenHW CVA6 cores Signed-off-by: Ben Dooks <ben.dooks@codethink.co.uk> --- target/riscv/cpu-qom.h | 1 + target/riscv/cpu.c | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/target/riscv/cpu-qom.h b/target/riscv/cpu-qom.h index 4cfdb74891..b5460771d7 100644 --- a/target/riscv/cpu-qom.h +++ b/target/riscv/cpu-qom.h @@ -34,6 +34,7 @@ #define TYPE_RISCV_CPU_BASE32 RISCV_CPU_TYPE_NAME("rv32") #define TYPE_RISCV_CPU_BASE64 RISCV_CPU_TYPE_NAME("rv64") #define TYPE_RISCV_CPU_BASE128 RISCV_CPU_TYPE_NAME("x-rv128") +#define TYPE_RISCV_CPU_CVA6 RISCV_CPU_TYPE_NAME("cva6") #define TYPE_RISCV_CPU_RV32I RISCV_CPU_TYPE_NAME("rv32i") #define TYPE_RISCV_CPU_RV32E RISCV_CPU_TYPE_NAME("rv32e") #define TYPE_RISCV_CPU_RV64I RISCV_CPU_TYPE_NAME("rv64i") diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index d92874baa0..0ad6a7b616 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -496,6 +496,24 @@ static void rv64_base_cpu_init(Object *obj) #endif } +static void rv64_cva6_cpu_init(Object *obj) +{ + RISCVCPU *cpu = RISCV_CPU(obj); + CPURISCVState *env = &cpu->env; + + riscv_cpu_set_misa_ext(env, RVI | RVM | RVA | RVF | RVD | RVC | RVB | RVS | RVU); + env->priv_ver = PRIV_VERSION_1_12_0; +#ifndef CONFIG_USER_ONLY + set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV39); +#endif + + /* inherited from parent obj via riscv_cpu_init() */ + cpu->cfg.ext_zifencei = true; + cpu->cfg.ext_zicsr = true; + cpu->cfg.mmu = true; + cpu->cfg.pmp = true; +} + static void rv64_sifive_u_cpu_init(Object *obj) { RISCVCPU *cpu = RISCV_CPU(obj); @@ -3247,6 +3265,7 @@ static const TypeInfo riscv_cpu_type_infos[] = { #if defined(TARGET_RISCV64) DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_BASE64, MXL_RV64, rv64_base_cpu_init), + DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_CVA6, MXL_RV64, rv64_cva6_cpu_init), DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_E51, MXL_RV64, rv64_sifive_e_cpu_init), DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_U54, MXL_RV64, rv64_sifive_u_cpu_init), DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SHAKTI_C, MXL_RV64, rv64_sifive_u_cpu_init), -- 2.37.2.352.g3c44437643 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH 2/2] target/riscv: add cva6 cpu type 2025-05-21 15:54 ` [PATCH 2/2] target/riscv: add cva6 cpu type Ben Dooks @ 2025-05-26 10:12 ` Daniel Henrique Barboza 0 siblings, 0 replies; 6+ messages in thread From: Daniel Henrique Barboza @ 2025-05-26 10:12 UTC (permalink / raw) To: Ben Dooks, nazar.kazakov, joseph.baker, fran.redondo, lawrence.hunter, liwei1518, zhiwei_liu, qemu-riscv Cc: qemu-devel On 5/21/25 12:54 PM, Ben Dooks wrote: > Add CVA6 CPU type, for the OpenHW CVA6 cores > > Signed-off-by: Ben Dooks <ben.dooks@codethink.co.uk> > --- The patch LGTM but I'm afraid you'll have to rebase it with the current master: we changed how CPUs are declared after the RISCVCPUDef changes landed. Thanks, Daniel > target/riscv/cpu-qom.h | 1 + > target/riscv/cpu.c | 19 +++++++++++++++++++ > 2 files changed, 20 insertions(+) > > diff --git a/target/riscv/cpu-qom.h b/target/riscv/cpu-qom.h > index 4cfdb74891..b5460771d7 100644 > --- a/target/riscv/cpu-qom.h > +++ b/target/riscv/cpu-qom.h > @@ -34,6 +34,7 @@ > #define TYPE_RISCV_CPU_BASE32 RISCV_CPU_TYPE_NAME("rv32") > #define TYPE_RISCV_CPU_BASE64 RISCV_CPU_TYPE_NAME("rv64") > #define TYPE_RISCV_CPU_BASE128 RISCV_CPU_TYPE_NAME("x-rv128") > +#define TYPE_RISCV_CPU_CVA6 RISCV_CPU_TYPE_NAME("cva6") > #define TYPE_RISCV_CPU_RV32I RISCV_CPU_TYPE_NAME("rv32i") > #define TYPE_RISCV_CPU_RV32E RISCV_CPU_TYPE_NAME("rv32e") > #define TYPE_RISCV_CPU_RV64I RISCV_CPU_TYPE_NAME("rv64i") > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c > index d92874baa0..0ad6a7b616 100644 > --- a/target/riscv/cpu.c > +++ b/target/riscv/cpu.c > @@ -496,6 +496,24 @@ static void rv64_base_cpu_init(Object *obj) > #endif > } > > +static void rv64_cva6_cpu_init(Object *obj) > +{ > + RISCVCPU *cpu = RISCV_CPU(obj); > + CPURISCVState *env = &cpu->env; > + > + riscv_cpu_set_misa_ext(env, RVI | RVM | RVA | RVF | RVD | RVC | RVB | RVS | RVU); > + env->priv_ver = PRIV_VERSION_1_12_0; > +#ifndef CONFIG_USER_ONLY > + set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV39); > +#endif > + > + /* inherited from parent obj via riscv_cpu_init() */ > + cpu->cfg.ext_zifencei = true; > + cpu->cfg.ext_zicsr = true; > + cpu->cfg.mmu = true; > + cpu->cfg.pmp = true; > +} > + > static void rv64_sifive_u_cpu_init(Object *obj) > { > RISCVCPU *cpu = RISCV_CPU(obj); > @@ -3247,6 +3265,7 @@ static const TypeInfo riscv_cpu_type_infos[] = { > > #if defined(TARGET_RISCV64) > DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_BASE64, MXL_RV64, rv64_base_cpu_init), > + DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_CVA6, MXL_RV64, rv64_cva6_cpu_init), > DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_E51, MXL_RV64, rv64_sifive_e_cpu_init), > DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_U54, MXL_RV64, rv64_sifive_u_cpu_init), > DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SHAKTI_C, MXL_RV64, rv64_sifive_u_cpu_init), ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2025-05-27 12:04 UTC | newest] Thread overview: 6+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-05-21 15:54 Adding CVA6 machine to RISC-V Ben Dooks 2025-05-21 15:54 ` [PATCH 1/2] hw/riscv: add CVA6 machine Ben Dooks 2025-05-26 10:10 ` Daniel Henrique Barboza 2025-05-27 11:30 ` Ben Dooks 2025-05-21 15:54 ` [PATCH 2/2] target/riscv: add cva6 cpu type Ben Dooks 2025-05-26 10:12 ` Daniel Henrique Barboza
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).