diff --git a/litex/soc/cores/cpu/naxriscv/boot-helper.S b/litex/soc/cores/cpu/naxriscv/boot-helper.S index 6dd74aaeb..3a530dd1f 100644 --- a/litex/soc/cores/cpu/naxriscv/boot-helper.S +++ b/litex/soc/cores/cpu/naxriscv/boot-helper.S @@ -1,4 +1,15 @@ .section .text, "ax", @progbits -.global boot_helper +.global boot_helper +.global smp_lottery_target +.global smp_lottery_lock +.global smp_lottery_args + boot_helper: + sw x10, smp_lottery_args , x14 + sw x11, smp_lottery_args+4, x14 + sw x12, smp_lottery_args+8, x14 + sw x13, smp_lottery_target, x14 + fence w, w + li x15, 1 + sw x15, smp_lottery_lock, x14 jr x13 diff --git a/litex/soc/cores/cpu/naxriscv/core.py b/litex/soc/cores/cpu/naxriscv/core.py index 86d4c833f..3dd5aa03a 100755 --- a/litex/soc/cores/cpu/naxriscv/core.py +++ b/litex/soc/cores/cpu/naxriscv/core.py @@ -50,8 +50,11 @@ class NaxRiscv(CPU): netlist_name = None scala_paths = [] xlen = 32 + cpu_count = 1 jtag_tap = False jtag_instruction = False + with_dma = False + litedram_width = 32 # ABI. @staticmethod @@ -73,7 +76,7 @@ class NaxRiscv(CPU): # Memory Mapping. @property - def mem_map(self): + def mem_map(self): # TODO return { "rom": 0x0000_0000, "sram": 0x1000_0000, @@ -103,6 +106,8 @@ class NaxRiscv(CPU): cpu_group.add_argument("--scala-file", action="append", help="Specify the scala files used to configure NaxRiscv.") cpu_group.add_argument("--scala-args", action="append", help="Add arguements for the scala run time. Ex : --scala-args 'rvc=true,mmu=false'") cpu_group.add_argument("--xlen", default=32, help="Specify the RISC-V data width.") + cpu_group.add_argument("--cpu-count", default=1, help="How many NaxRiscv CPU") + cpu_group.add_argument("--with-coherent-dma", action="store_true", help="Enable coherent DMA accesses") cpu_group.add_argument("--with-jtag-tap", action="store_true", help="Add a embedded JTAG tap for debugging") cpu_group.add_argument("--with-jtag-instruction", action="store_true", help="Add a JTAG instruction port which implement tunneling for debugging (TAP not included)") cpu_group.add_argument("--update-repo", default="recommended", choices=["latest","wipe+latest","recommended","wipe+recommended","no"], help="Specify how the NaxRiscv & SpinalHDL repo should be updated (latest: update to HEAD, recommended: Update to known compatible version, no: Don't update, wipe+*: Do clean&reset before checkout)") @@ -114,6 +119,7 @@ class NaxRiscv(CPU): print(args) NaxRiscv.jtag_tap = args.with_jtag_tap NaxRiscv.jtag_instruction = args.with_jtag_instruction + NaxRiscv.with_dma = args.with_coherent_dma NaxRiscv.update_repo = args.update_repo NaxRiscv.no_netlist_cache = args.no_netlist_cache NaxRiscv.with_fpu = args.with_fpu @@ -128,6 +134,8 @@ class NaxRiscv(CPU): NaxRiscv.data_width = xlen NaxRiscv.gcc_triple = CPU_GCC_TRIPLE_RISCV64 NaxRiscv.linker_output_format = f"elf{xlen}-littleriscv" + if args.cpu_count: + NaxRiscv.cpu_count = args.cpu_count def __init__(self, platform, variant): @@ -136,55 +144,97 @@ class NaxRiscv(CPU): self.human_name = self.human_name self.reset = Signal() self.interrupt = Signal(32) - self.ibus = ibus = axi.AXILiteInterface(address_width=32, data_width=32) - self.dbus = dbus = axi.AXILiteInterface(address_width=32, data_width=32) + self.pbus = pbus = axi.AXILiteInterface(address_width=32, data_width=32) - self.periph_buses = [ibus, dbus] # Peripheral buses (Connected to main SoC's bus). + self.periph_buses = [pbus] # Peripheral buses (Connected to main SoC's bus). self.memory_buses = [] # Memory buses (Connected directly to LiteDRAM). # # # + self.tracer_valid = Signal() + self.tracer_payload = Signal(8) + # CPU Instance. self.cpu_params = dict( # Clk/Rst. i_clk = ClockSignal("sys"), i_reset = ResetSignal("sys") | self.reset, - # Interrupt. - i_peripheral_interrupt = self.interrupt, # FIXME: Check what is expected. => interrupt(0) is dummy and should not be used (PLIC stuff), need to reserve interrupt(0) + o_patcher_tracer_valid=self.tracer_valid, + o_patcher_tracer_payload=self.tracer_payload, - # Peripheral Instruction Bus (AXI Lite Slave). - o_peripheral_ibus_arvalid = ibus.ar.valid, - i_peripheral_ibus_arready = ibus.ar.ready, - o_peripheral_ibus_araddr = ibus.ar.addr, - o_peripheral_ibus_arprot = Open(), - i_peripheral_ibus_rvalid = ibus.r.valid, - o_peripheral_ibus_rready = ibus.r.ready, - i_peripheral_ibus_rdata = ibus.r.data, - i_peripheral_ibus_rresp = ibus.r.resp, + # Interrupt. + i_peripheral_externalInterrupts_port = self.interrupt, # Peripheral Memory Bus (AXI Lite Slave). - o_peripheral_dbus_awvalid = dbus.aw.valid, - i_peripheral_dbus_awready = dbus.aw.ready, - o_peripheral_dbus_awaddr = dbus.aw.addr, - o_peripheral_dbus_awprot = Open(), - o_peripheral_dbus_wvalid = dbus.w.valid, - i_peripheral_dbus_wready = dbus.w.ready, - o_peripheral_dbus_wdata = dbus.w.data, - o_peripheral_dbus_wstrb = dbus.w.strb, - i_peripheral_dbus_bvalid = dbus.b.valid, - o_peripheral_dbus_bready = dbus.b.ready, - i_peripheral_dbus_bresp = dbus.b.resp, - o_peripheral_dbus_arvalid = dbus.ar.valid, - i_peripheral_dbus_arready = dbus.ar.ready, - o_peripheral_dbus_araddr = dbus.ar.addr, - o_peripheral_dbus_arprot = Open(), - i_peripheral_dbus_rvalid = dbus.r.valid, - o_peripheral_dbus_rready = dbus.r.ready, - i_peripheral_dbus_rdata = dbus.r.data, - i_peripheral_dbus_rresp = dbus.r.resp, + o_pBus_awvalid = pbus.aw.valid, + i_pBus_awready = pbus.aw.ready, + o_pBus_awaddr = pbus.aw.addr, + o_pBus_awprot = Open(), + o_pBus_wvalid = pbus.w.valid, + i_pBus_wready = pbus.w.ready, + o_pBus_wdata = pbus.w.data, + o_pBus_wstrb = pbus.w.strb, + i_pBus_bvalid = pbus.b.valid, + o_pBus_bready = pbus.b.ready, + i_pBus_bresp = pbus.b.resp, + o_pBus_arvalid = pbus.ar.valid, + i_pBus_arready = pbus.ar.ready, + o_pBus_araddr = pbus.ar.addr, + o_pBus_arprot = Open(), + i_pBus_rvalid = pbus.r.valid, + o_pBus_rready = pbus.r.ready, + i_pBus_rdata = pbus.r.data, + i_pBus_rresp = pbus.r.resp ) + if NaxRiscv.with_dma: + self.dma_bus = dma_bus = axi.AXIInterface(data_width=64, address_width=32, id_width=4) + + self.cpu_params.update( + o_dma_bus_awready=dma_bus.aw.ready, + i_dma_bus_awvalid=dma_bus.aw.valid, + i_dma_bus_awid=dma_bus.aw.id, + i_dma_bus_awaddr=dma_bus.aw.addr, + i_dma_bus_awlen=dma_bus.aw.len, + i_dma_bus_awsize=dma_bus.aw.size, + i_dma_bus_awburst=dma_bus.aw.burst, + i_dma_bus_awlock=dma_bus.aw.lock, + i_dma_bus_awcache=dma_bus.aw.cache, + i_dma_bus_awprot=dma_bus.aw.prot, + i_dma_bus_awqos=dma_bus.aw.qos, + + o_dma_bus_wready=dma_bus.w.ready, + i_dma_bus_wvalid=dma_bus.w.valid, + i_dma_bus_wdata=dma_bus.w.data, + i_dma_bus_wstrb=dma_bus.w.strb, + i_dma_bus_wlast=dma_bus.w.last, + + i_dma_bus_bready=dma_bus.b.ready, + o_dma_bus_bvalid=dma_bus.b.valid, + o_dma_bus_bid=dma_bus.b.id, + o_dma_bus_bresp=dma_bus.b.resp, + + o_dma_bus_arready=dma_bus.ar.ready, + i_dma_bus_arvalid=dma_bus.ar.valid, + i_dma_bus_arid=dma_bus.ar.id, + i_dma_bus_araddr=dma_bus.ar.addr, + i_dma_bus_arlen=dma_bus.ar.len, + i_dma_bus_arsize=dma_bus.ar.size, + i_dma_bus_arburst=dma_bus.ar.burst, + i_dma_bus_arlock=dma_bus.ar.lock, + i_dma_bus_arcache=dma_bus.ar.cache, + i_dma_bus_arprot=dma_bus.ar.prot, + i_dma_bus_arqos=dma_bus.ar.qos, + + i_dma_bus_rready=dma_bus.r.ready, + o_dma_bus_rvalid=dma_bus.r.valid, + o_dma_bus_rid=dma_bus.r.id, + o_dma_bus_rdata=dma_bus.r.data, + o_dma_bus_rresp=dma_bus.r.resp, + o_dma_bus_rlast=dma_bus.r.last + ) + def set_reset_address(self, reset_address): self.reset_address = reset_address @@ -206,9 +256,12 @@ class NaxRiscv(CPU): def generate_netlist_name(reset_address): md5_hash = hashlib.md5() md5_hash.update(str(reset_address).encode('utf-8')) + md5_hash.update(str(NaxRiscv.litedram_width).encode('utf-8')) md5_hash.update(str(NaxRiscv.xlen).encode('utf-8')) + md5_hash.update(str(NaxRiscv.cpu_count).encode('utf-8')) md5_hash.update(str(NaxRiscv.jtag_tap).encode('utf-8')) md5_hash.update(str(NaxRiscv.jtag_instruction).encode('utf-8')) + md5_hash.update(str(NaxRiscv.with_dma).encode('utf-8')) md5_hash.update(str(NaxRiscv.memory_regions).encode('utf-8')) for args in NaxRiscv.scala_args: md5_hash.update(args.encode('utf-8')) @@ -235,7 +288,7 @@ class NaxRiscv(CPU): os.chdir(os.path.join(dir)) wipe_cmd = "&& git clean --force -d -x && git reset --hard" if "wipe" in NaxRiscv.update_repo else "" checkout_cmd = f"&& git checkout {hash}" if hash is not None else "" - subprocess.check_call(f"cd {dir} {wipe_cmd} && git checkout {branch} && git pull {checkout_cmd}", shell=True) + subprocess.check_call(f"cd {dir} {wipe_cmd} && git checkout {branch} && git submodule init && git pull --recurse-submodules {checkout_cmd}", shell=True) # Netlist Generation. @staticmethod @@ -245,14 +298,16 @@ class NaxRiscv(CPU): sdir = os.path.join(vdir, "ext", "SpinalHDL") if NaxRiscv.update_repo != "no": - NaxRiscv.git_setup("NaxRiscv", ndir, "https://github.com/SpinalHDL/NaxRiscv.git" , "main", "d7213a3f" if (NaxRiscv.update_repo == "recommended") else None) - NaxRiscv.git_setup("SpinalHDL", sdir, "https://github.com/SpinalHDL/SpinalHDL.git", "dev", "912f4b37" if (NaxRiscv.update_repo == "recommended") else None) + NaxRiscv.git_setup("NaxRiscv", ndir, "https://github.com/SpinalHDL/NaxRiscv.git", "coherency", "ee4c6fb7" if NaxRiscv.update_repo=="recommended" else None) + NaxRiscv.git_setup("SpinalHDL", sdir, "https://github.com/SpinalHDL/SpinalHDL.git", "bus-fabric" , "ee95492a" if NaxRiscv.update_repo=="recommended" else None) gen_args = [] gen_args.append(f"--netlist-name={NaxRiscv.netlist_name}") gen_args.append(f"--netlist-directory={vdir}") gen_args.append(f"--reset-vector={reset_address}") gen_args.append(f"--xlen={NaxRiscv.xlen}") + gen_args.append(f"--cpu-count={NaxRiscv.cpu_count}") + gen_args.append(f"--litedram-width={NaxRiscv.litedram_width}") for region in NaxRiscv.memory_regions: gen_args.append(f"--memory-region={region[0]},{region[1]},{region[2]},{region[3]}") for args in NaxRiscv.scala_args: @@ -263,12 +318,14 @@ class NaxRiscv(CPU): gen_args.append(f"--with-jtag-instruction") if(NaxRiscv.jtag_tap or NaxRiscv.jtag_instruction): gen_args.append(f"--with-debug") + if(NaxRiscv.with_dma) : + gen_args.append(f"--with-dma") for file in NaxRiscv.scala_paths: gen_args.append(f"--scala-file={file}") if(NaxRiscv.with_fpu): gen_args.append(f"--scala-args=rvf=true,rvd=true") - cmd = f"""cd {ndir} && sbt "runMain naxriscv.platform.LitexGen {" ".join(gen_args)}\"""" + cmd = f"""cd {ndir} && sbt "runMain naxriscv.platform.litex.NaxGen {" ".join(gen_args)}\"""" print("NaxRiscv generation command :") print(cmd) subprocess.check_call(cmd, shell=True) @@ -277,6 +334,7 @@ class NaxRiscv(CPU): def add_sources(self, platform): vdir = get_data_mod("cpu", "naxriscv").data_location print(f"NaxRiscv netlist : {self.netlist_name}") + if NaxRiscv.no_netlist_cache or not os.path.exists(os.path.join(vdir, self.netlist_name + ".v")): self.generate_netlist(self.reset_address) @@ -305,33 +363,12 @@ class NaxRiscv(CPU): soc.bus.add_region("opensbi", SoCRegion(origin=self.mem_map["main_ram"] + 0x00f0_0000, size=0x8_0000, cached=True, linker=True)) # Define ISA. + soc.add_config("CPU_COUNT", NaxRiscv.cpu_count) soc.add_config("CPU_ISA", NaxRiscv.get_arch()) soc.add_config("CPU_MMU", {32 : "sv32", 64 : "sv39"}[NaxRiscv.xlen]) - # Add PLIC Bus (AXILite Slave). - self.plicbus = plicbus = axi.AXILiteInterface(address_width=32, data_width=32) - self.cpu_params.update( - i_peripheral_plic_awvalid = plicbus.aw.valid, - o_peripheral_plic_awready = plicbus.aw.ready, - i_peripheral_plic_awaddr = plicbus.aw.addr, - i_peripheral_plic_awprot = Constant(2), - i_peripheral_plic_wvalid = plicbus.w.valid, - o_peripheral_plic_wready = plicbus.w.ready, - i_peripheral_plic_wdata = plicbus.w.data, - i_peripheral_plic_wstrb = plicbus.w.strb, - o_peripheral_plic_bvalid = plicbus.b.valid, - i_peripheral_plic_bready = plicbus.b.ready, - o_peripheral_plic_bresp = plicbus.b.resp, - i_peripheral_plic_arvalid = plicbus.ar.valid, - o_peripheral_plic_arready = plicbus.ar.ready, - i_peripheral_plic_araddr = plicbus.ar.addr, - i_peripheral_plic_arprot = Constant(2), - o_peripheral_plic_rvalid = plicbus.r.valid, - i_peripheral_plic_rready = plicbus.r.ready, - o_peripheral_plic_rdata = plicbus.r.data, - o_peripheral_plic_rresp = plicbus.r.resp, - ) - soc.bus.add_slave("plic", self.plicbus, region=SoCRegion(origin=soc.mem_map.get("plic"), size=0x40_0000, cached=False)) + soc.bus.add_region("plic", SoCRegion(origin=soc.mem_map.get("plic"), size=0x40_0000, cached=False, linker=True)) + soc.bus.add_region("clint", SoCRegion(origin=soc.mem_map.get("clint"), size= 0x1_0000, cached=False, linker=True)) if NaxRiscv.jtag_tap: self.jtag_tms = Signal() @@ -390,95 +427,54 @@ class NaxRiscv(CPU): self.comb += debug_ndmreset_rise.eq(debug_ndmreset & ~debug_ndmreset_last) self.comb += If(debug_ndmreset_rise, soc.crg.rst.eq(1)) - # Add CLINT Bus (AXILite Slave). - self.clintbus = clintbus = axi.AXILiteInterface(address_width=32, data_width=32) - self.cpu_params.update( - i_peripheral_clint_awvalid = clintbus.aw.valid, - o_peripheral_clint_awready = clintbus.aw.ready, - i_peripheral_clint_awaddr = clintbus.aw.addr, - i_peripheral_clint_awprot = Constant(2), - i_peripheral_clint_wvalid = clintbus.w.valid, - o_peripheral_clint_wready = clintbus.w.ready, - i_peripheral_clint_wdata = clintbus.w.data, - i_peripheral_clint_wstrb = clintbus.w.strb, - o_peripheral_clint_bvalid = clintbus.b.valid, - i_peripheral_clint_bready = clintbus.b.ready, - o_peripheral_clint_bresp = clintbus.b.resp, - i_peripheral_clint_arvalid = clintbus.ar.valid, - o_peripheral_clint_arready = clintbus.ar.ready, - i_peripheral_clint_araddr = clintbus.ar.addr, - i_peripheral_clint_arprot = Constant(2), - o_peripheral_clint_rvalid = clintbus.r.valid, - i_peripheral_clint_rready = clintbus.r.ready, - o_peripheral_clint_rdata = clintbus.r.data, - o_peripheral_clint_rresp = clintbus.r.resp, - ) - soc.bus.add_slave("clint", clintbus, region=SoCRegion(origin=soc.mem_map.get("clint"), size=0x1_0000, cached=False)) self.soc_bus = soc.bus # FIXME: Save SoC Bus instance to retrieve the final mem layout on finalization. def add_memory_buses(self, address_width, data_width): + NaxRiscv.litedram_width = data_width nax_data_width = 64 nax_burst_size = 64 assert data_width >= nax_data_width # FIXME: Only supporting up-conversion for now. assert data_width <= nax_burst_size*8 # FIXME: AXIUpConverter doing assumptions on minimal burst_size. - ibus = axi.AXIInterface( - data_width = nax_data_width, + mbus = axi.AXIInterface( + data_width = NaxRiscv.litedram_width, address_width = 32, - id_width = 1, + id_width = 8, #TODO ) - dbus = axi.AXIInterface( - data_width = nax_data_width, - address_width = 32, - id_width = 4, - ) - self.memory_buses.append(ibus) - self.memory_buses.append(dbus) + self.memory_buses.append(mbus) self.cpu_params.update( - # Instruction Memory Bus (Master). - o_ram_ibus_arvalid = ibus.ar.valid, - i_ram_ibus_arready = ibus.ar.ready, - o_ram_ibus_araddr = ibus.ar.addr, - o_ram_ibus_arlen = ibus.ar.len, - o_ram_ibus_arsize = ibus.ar.size, - o_ram_ibus_arburst = ibus.ar.burst, - i_ram_ibus_rvalid = ibus.r.valid, - o_ram_ibus_rready = ibus.r.ready, - i_ram_ibus_rdata = ibus.r.data, - i_ram_ibus_rresp = ibus.r.resp, - i_ram_ibus_rlast = ibus.r.last, - - # Data Memory Bus (Master). - o_ram_dbus_awvalid = dbus.aw.valid, - i_ram_dbus_awready = dbus.aw.ready, - o_ram_dbus_awaddr = dbus.aw.addr, - o_ram_dbus_awid = dbus.aw.id, - o_ram_dbus_awlen = dbus.aw.len, - o_ram_dbus_awsize = dbus.aw.size, - o_ram_dbus_awburst = dbus.aw.burst, - o_ram_dbus_wvalid = dbus.w.valid, - i_ram_dbus_wready = dbus.w.ready, - o_ram_dbus_wdata = dbus.w.data, - o_ram_dbus_wstrb = dbus.w.strb, - o_ram_dbus_wlast = dbus.w.last, - i_ram_dbus_bvalid = dbus.b.valid, - o_ram_dbus_bready = dbus.b.ready, - i_ram_dbus_bid = dbus.b.id, - i_ram_dbus_bresp = dbus.b.resp, - o_ram_dbus_arvalid = dbus.ar.valid, - i_ram_dbus_arready = dbus.ar.ready, - o_ram_dbus_araddr = dbus.ar.addr, - o_ram_dbus_arid = dbus.ar.id, - o_ram_dbus_arlen = dbus.ar.len, - o_ram_dbus_arsize = dbus.ar.size, - o_ram_dbus_arburst = dbus.ar.burst, - i_ram_dbus_rvalid = dbus.r.valid, - o_ram_dbus_rready = dbus.r.ready, - i_ram_dbus_rdata = dbus.r.data, - i_ram_dbus_rid = dbus.r.id, - i_ram_dbus_rresp = dbus.r.resp, - i_ram_dbus_rlast = dbus.r.last, + # Memory Bus (Master). + o_mBus_awvalid = mbus.aw.valid, + i_mBus_awready = mbus.aw.ready, + o_mBus_awaddr = mbus.aw.addr, + o_mBus_awid = mbus.aw.id, + o_mBus_awlen = mbus.aw.len, + o_mBus_awsize = mbus.aw.size, + o_mBus_awburst = mbus.aw.burst, + o_mBus_awallStrb = Open(), + o_mBus_wvalid = mbus.w.valid, + i_mBus_wready = mbus.w.ready, + o_mBus_wdata = mbus.w.data, + o_mBus_wstrb = mbus.w.strb, + o_mBus_wlast = mbus.w.last, + i_mBus_bvalid = mbus.b.valid, + o_mBus_bready = mbus.b.ready, + i_mBus_bid = mbus.b.id, + i_mBus_bresp = mbus.b.resp, + o_mBus_arvalid = mbus.ar.valid, + i_mBus_arready = mbus.ar.ready, + o_mBus_araddr = mbus.ar.addr, + o_mBus_arid = mbus.ar.id, + o_mBus_arlen = mbus.ar.len, + o_mBus_arsize = mbus.ar.size, + o_mBus_arburst = mbus.ar.burst, + i_mBus_rvalid = mbus.r.valid, + o_mBus_rready = mbus.r.ready, + i_mBus_rdata = mbus.r.data, + i_mBus_rid = mbus.r.id, + i_mBus_rresp = mbus.r.resp, + i_mBus_rlast = mbus.r.last, ) def do_finalize(self): diff --git a/litex/soc/cores/cpu/naxriscv/crt0.S b/litex/soc/cores/cpu/naxriscv/crt0.S index 8078020fd..b27df7f47 100644 --- a/litex/soc/cores/cpu/naxriscv/crt0.S +++ b/litex/soc/cores/cpu/naxriscv/crt0.S @@ -2,6 +2,11 @@ .global isr .global _start +.global smp_lottery_target +.global smp_lottery_lock +.global smp_lottery_args +.global smp_slave + #define MSTATUS_FS_INITIAL (1 << 13) #define MSTATUS_FS_CLEAN (2 << 13) #define MSTATUS_FS_DIRTY (3 << 13) @@ -67,6 +72,24 @@ enable_fpu: li x1, MSTATUS_FS_INITIAL csrs mstatus, x1 + sw x0, smp_lottery_lock, a1 +smp_tyranny: + csrr a0, mhartid + beqz a0, data_init + +smp_slave: + lw a0, smp_lottery_lock + beqz a0, smp_slave + fence r, r + + .word(0x100F) //i$ flush + lw x10, smp_lottery_args + lw x11, smp_lottery_args+4 + lw x12, smp_lottery_args+8 + lw x13, smp_lottery_target + jr x13 + + data_init: la a0, _fdata la a1, _edata @@ -96,3 +119,10 @@ bss_done: call main infinit_loop: j infinit_loop + +//Initialized to avoid having them set to zero by BSS clear +.bss + smp_lottery_target: .word 0 + smp_lottery_args: .word 0; .word 0; .word 0 + smp_lottery_lock: .word 0 + diff --git a/litex_setup.py b/litex_setup.py index 577675dfd..4bf5f9d85 100755 --- a/litex_setup.py +++ b/litex_setup.py @@ -122,7 +122,7 @@ git_repos = { "pythondata-cpu-cva6": GitRepo(url="https://github.com/litex-hub/", clone="recursive"), "pythondata-cpu-ibex": GitRepo(url="https://github.com/litex-hub/", clone="recursive", sha1=0xd3d53df), "pythondata-cpu-minerva": GitRepo(url="https://github.com/litex-hub/"), - "pythondata-cpu-naxriscv": GitRepo(url="https://github.com/litex-hub/"), + "pythondata-cpu-naxriscv": GitRepo(url="https://github.com/litex-hub/", branch="smp"), "pythondata-cpu-picorv32": GitRepo(url="https://github.com/litex-hub/"), "pythondata-cpu-rocket": GitRepo(url="https://github.com/litex-hub/"), "pythondata-cpu-serv": GitRepo(url="https://github.com/litex-hub/"),