Merge pull request #1776 from Dolu1990/nax-smp
core/naxriscv provide a deployable NaxRiscv SMP
This commit is contained in:
commit
4639c7b39c
|
@ -1,4 +1,15 @@
|
||||||
.section .text, "ax", @progbits
|
.section .text, "ax", @progbits
|
||||||
.global boot_helper
|
.global boot_helper
|
||||||
|
.global smp_lottery_target
|
||||||
|
.global smp_lottery_lock
|
||||||
|
.global smp_lottery_args
|
||||||
|
|
||||||
boot_helper:
|
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
|
jr x13
|
||||||
|
|
|
@ -50,8 +50,11 @@ class NaxRiscv(CPU):
|
||||||
netlist_name = None
|
netlist_name = None
|
||||||
scala_paths = []
|
scala_paths = []
|
||||||
xlen = 32
|
xlen = 32
|
||||||
|
cpu_count = 1
|
||||||
jtag_tap = False
|
jtag_tap = False
|
||||||
jtag_instruction = False
|
jtag_instruction = False
|
||||||
|
with_dma = False
|
||||||
|
litedram_width = 32
|
||||||
|
|
||||||
# ABI.
|
# ABI.
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -73,7 +76,7 @@ class NaxRiscv(CPU):
|
||||||
|
|
||||||
# Memory Mapping.
|
# Memory Mapping.
|
||||||
@property
|
@property
|
||||||
def mem_map(self):
|
def mem_map(self): # TODO
|
||||||
return {
|
return {
|
||||||
"rom": 0x0000_0000,
|
"rom": 0x0000_0000,
|
||||||
"sram": 0x1000_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-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("--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("--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-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("--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)")
|
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)
|
print(args)
|
||||||
NaxRiscv.jtag_tap = args.with_jtag_tap
|
NaxRiscv.jtag_tap = args.with_jtag_tap
|
||||||
NaxRiscv.jtag_instruction = args.with_jtag_instruction
|
NaxRiscv.jtag_instruction = args.with_jtag_instruction
|
||||||
|
NaxRiscv.with_dma = args.with_coherent_dma
|
||||||
NaxRiscv.update_repo = args.update_repo
|
NaxRiscv.update_repo = args.update_repo
|
||||||
NaxRiscv.no_netlist_cache = args.no_netlist_cache
|
NaxRiscv.no_netlist_cache = args.no_netlist_cache
|
||||||
NaxRiscv.with_fpu = args.with_fpu
|
NaxRiscv.with_fpu = args.with_fpu
|
||||||
|
@ -128,6 +134,8 @@ class NaxRiscv(CPU):
|
||||||
NaxRiscv.data_width = xlen
|
NaxRiscv.data_width = xlen
|
||||||
NaxRiscv.gcc_triple = CPU_GCC_TRIPLE_RISCV64
|
NaxRiscv.gcc_triple = CPU_GCC_TRIPLE_RISCV64
|
||||||
NaxRiscv.linker_output_format = f"elf{xlen}-littleriscv"
|
NaxRiscv.linker_output_format = f"elf{xlen}-littleriscv"
|
||||||
|
if args.cpu_count:
|
||||||
|
NaxRiscv.cpu_count = args.cpu_count
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, platform, variant):
|
def __init__(self, platform, variant):
|
||||||
|
@ -136,55 +144,97 @@ class NaxRiscv(CPU):
|
||||||
self.human_name = self.human_name
|
self.human_name = self.human_name
|
||||||
self.reset = Signal()
|
self.reset = Signal()
|
||||||
self.interrupt = Signal(32)
|
self.interrupt = Signal(32)
|
||||||
self.ibus = ibus = axi.AXILiteInterface(address_width=32, data_width=32)
|
self.pbus = pbus = axi.AXILiteInterface(address_width=32, data_width=32)
|
||||||
self.dbus = dbus = 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.memory_buses = [] # Memory buses (Connected directly to LiteDRAM).
|
||||||
|
|
||||||
# # #
|
# # #
|
||||||
|
|
||||||
|
self.tracer_valid = Signal()
|
||||||
|
self.tracer_payload = Signal(8)
|
||||||
|
|
||||||
# CPU Instance.
|
# CPU Instance.
|
||||||
self.cpu_params = dict(
|
self.cpu_params = dict(
|
||||||
# Clk/Rst.
|
# Clk/Rst.
|
||||||
i_clk = ClockSignal("sys"),
|
i_clk = ClockSignal("sys"),
|
||||||
i_reset = ResetSignal("sys") | self.reset,
|
i_reset = ResetSignal("sys") | self.reset,
|
||||||
|
|
||||||
# Interrupt.
|
o_patcher_tracer_valid=self.tracer_valid,
|
||||||
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_payload=self.tracer_payload,
|
||||||
|
|
||||||
# Peripheral Instruction Bus (AXI Lite Slave).
|
# Interrupt.
|
||||||
o_peripheral_ibus_arvalid = ibus.ar.valid,
|
i_peripheral_externalInterrupts_port = self.interrupt,
|
||||||
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,
|
|
||||||
|
|
||||||
# Peripheral Memory Bus (AXI Lite Slave).
|
# Peripheral Memory Bus (AXI Lite Slave).
|
||||||
o_peripheral_dbus_awvalid = dbus.aw.valid,
|
o_pBus_awvalid = pbus.aw.valid,
|
||||||
i_peripheral_dbus_awready = dbus.aw.ready,
|
i_pBus_awready = pbus.aw.ready,
|
||||||
o_peripheral_dbus_awaddr = dbus.aw.addr,
|
o_pBus_awaddr = pbus.aw.addr,
|
||||||
o_peripheral_dbus_awprot = Open(),
|
o_pBus_awprot = Open(),
|
||||||
o_peripheral_dbus_wvalid = dbus.w.valid,
|
o_pBus_wvalid = pbus.w.valid,
|
||||||
i_peripheral_dbus_wready = dbus.w.ready,
|
i_pBus_wready = pbus.w.ready,
|
||||||
o_peripheral_dbus_wdata = dbus.w.data,
|
o_pBus_wdata = pbus.w.data,
|
||||||
o_peripheral_dbus_wstrb = dbus.w.strb,
|
o_pBus_wstrb = pbus.w.strb,
|
||||||
i_peripheral_dbus_bvalid = dbus.b.valid,
|
i_pBus_bvalid = pbus.b.valid,
|
||||||
o_peripheral_dbus_bready = dbus.b.ready,
|
o_pBus_bready = pbus.b.ready,
|
||||||
i_peripheral_dbus_bresp = dbus.b.resp,
|
i_pBus_bresp = pbus.b.resp,
|
||||||
o_peripheral_dbus_arvalid = dbus.ar.valid,
|
o_pBus_arvalid = pbus.ar.valid,
|
||||||
i_peripheral_dbus_arready = dbus.ar.ready,
|
i_pBus_arready = pbus.ar.ready,
|
||||||
o_peripheral_dbus_araddr = dbus.ar.addr,
|
o_pBus_araddr = pbus.ar.addr,
|
||||||
o_peripheral_dbus_arprot = Open(),
|
o_pBus_arprot = Open(),
|
||||||
i_peripheral_dbus_rvalid = dbus.r.valid,
|
i_pBus_rvalid = pbus.r.valid,
|
||||||
o_peripheral_dbus_rready = dbus.r.ready,
|
o_pBus_rready = pbus.r.ready,
|
||||||
i_peripheral_dbus_rdata = dbus.r.data,
|
i_pBus_rdata = pbus.r.data,
|
||||||
i_peripheral_dbus_rresp = dbus.r.resp,
|
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):
|
def set_reset_address(self, reset_address):
|
||||||
self.reset_address = reset_address
|
self.reset_address = reset_address
|
||||||
|
|
||||||
|
@ -206,9 +256,12 @@ class NaxRiscv(CPU):
|
||||||
def generate_netlist_name(reset_address):
|
def generate_netlist_name(reset_address):
|
||||||
md5_hash = hashlib.md5()
|
md5_hash = hashlib.md5()
|
||||||
md5_hash.update(str(reset_address).encode('utf-8'))
|
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.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_tap).encode('utf-8'))
|
||||||
md5_hash.update(str(NaxRiscv.jtag_instruction).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'))
|
md5_hash.update(str(NaxRiscv.memory_regions).encode('utf-8'))
|
||||||
for args in NaxRiscv.scala_args:
|
for args in NaxRiscv.scala_args:
|
||||||
md5_hash.update(args.encode('utf-8'))
|
md5_hash.update(args.encode('utf-8'))
|
||||||
|
@ -235,7 +288,7 @@ class NaxRiscv(CPU):
|
||||||
os.chdir(os.path.join(dir))
|
os.chdir(os.path.join(dir))
|
||||||
wipe_cmd = "&& git clean --force -d -x && git reset --hard" if "wipe" in NaxRiscv.update_repo else ""
|
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 ""
|
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.
|
# Netlist Generation.
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -245,14 +298,16 @@ class NaxRiscv(CPU):
|
||||||
sdir = os.path.join(vdir, "ext", "SpinalHDL")
|
sdir = os.path.join(vdir, "ext", "SpinalHDL")
|
||||||
|
|
||||||
if NaxRiscv.update_repo != "no":
|
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("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", "dev", "912f4b37" 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 = []
|
||||||
gen_args.append(f"--netlist-name={NaxRiscv.netlist_name}")
|
gen_args.append(f"--netlist-name={NaxRiscv.netlist_name}")
|
||||||
gen_args.append(f"--netlist-directory={vdir}")
|
gen_args.append(f"--netlist-directory={vdir}")
|
||||||
gen_args.append(f"--reset-vector={reset_address}")
|
gen_args.append(f"--reset-vector={reset_address}")
|
||||||
gen_args.append(f"--xlen={NaxRiscv.xlen}")
|
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:
|
for region in NaxRiscv.memory_regions:
|
||||||
gen_args.append(f"--memory-region={region[0]},{region[1]},{region[2]},{region[3]}")
|
gen_args.append(f"--memory-region={region[0]},{region[1]},{region[2]},{region[3]}")
|
||||||
for args in NaxRiscv.scala_args:
|
for args in NaxRiscv.scala_args:
|
||||||
|
@ -263,12 +318,14 @@ class NaxRiscv(CPU):
|
||||||
gen_args.append(f"--with-jtag-instruction")
|
gen_args.append(f"--with-jtag-instruction")
|
||||||
if(NaxRiscv.jtag_tap or NaxRiscv.jtag_instruction):
|
if(NaxRiscv.jtag_tap or NaxRiscv.jtag_instruction):
|
||||||
gen_args.append(f"--with-debug")
|
gen_args.append(f"--with-debug")
|
||||||
|
if(NaxRiscv.with_dma) :
|
||||||
|
gen_args.append(f"--with-dma")
|
||||||
for file in NaxRiscv.scala_paths:
|
for file in NaxRiscv.scala_paths:
|
||||||
gen_args.append(f"--scala-file={file}")
|
gen_args.append(f"--scala-file={file}")
|
||||||
if(NaxRiscv.with_fpu):
|
if(NaxRiscv.with_fpu):
|
||||||
gen_args.append(f"--scala-args=rvf=true,rvd=true")
|
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("NaxRiscv generation command :")
|
||||||
print(cmd)
|
print(cmd)
|
||||||
subprocess.check_call(cmd, shell=True)
|
subprocess.check_call(cmd, shell=True)
|
||||||
|
@ -277,6 +334,7 @@ class NaxRiscv(CPU):
|
||||||
def add_sources(self, platform):
|
def add_sources(self, platform):
|
||||||
vdir = get_data_mod("cpu", "naxriscv").data_location
|
vdir = get_data_mod("cpu", "naxriscv").data_location
|
||||||
print(f"NaxRiscv netlist : {self.netlist_name}")
|
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")):
|
if NaxRiscv.no_netlist_cache or not os.path.exists(os.path.join(vdir, self.netlist_name + ".v")):
|
||||||
self.generate_netlist(self.reset_address)
|
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))
|
soc.bus.add_region("opensbi", SoCRegion(origin=self.mem_map["main_ram"] + 0x00f0_0000, size=0x8_0000, cached=True, linker=True))
|
||||||
|
|
||||||
# Define ISA.
|
# Define ISA.
|
||||||
|
soc.add_config("CPU_COUNT", NaxRiscv.cpu_count)
|
||||||
soc.add_config("CPU_ISA", NaxRiscv.get_arch())
|
soc.add_config("CPU_ISA", NaxRiscv.get_arch())
|
||||||
soc.add_config("CPU_MMU", {32 : "sv32", 64 : "sv39"}[NaxRiscv.xlen])
|
soc.add_config("CPU_MMU", {32 : "sv32", 64 : "sv39"}[NaxRiscv.xlen])
|
||||||
|
|
||||||
# Add PLIC Bus (AXILite Slave).
|
soc.bus.add_region("plic", SoCRegion(origin=soc.mem_map.get("plic"), size=0x40_0000, cached=False, linker=True))
|
||||||
self.plicbus = plicbus = axi.AXILiteInterface(address_width=32, data_width=32)
|
soc.bus.add_region("clint", SoCRegion(origin=soc.mem_map.get("clint"), size= 0x1_0000, cached=False, linker=True))
|
||||||
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))
|
|
||||||
|
|
||||||
if NaxRiscv.jtag_tap:
|
if NaxRiscv.jtag_tap:
|
||||||
self.jtag_tms = Signal()
|
self.jtag_tms = Signal()
|
||||||
|
@ -390,95 +427,54 @@ class NaxRiscv(CPU):
|
||||||
self.comb += debug_ndmreset_rise.eq(debug_ndmreset & ~debug_ndmreset_last)
|
self.comb += debug_ndmreset_rise.eq(debug_ndmreset & ~debug_ndmreset_last)
|
||||||
self.comb += If(debug_ndmreset_rise, soc.crg.rst.eq(1))
|
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.
|
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):
|
def add_memory_buses(self, address_width, data_width):
|
||||||
|
NaxRiscv.litedram_width = data_width
|
||||||
nax_data_width = 64
|
nax_data_width = 64
|
||||||
nax_burst_size = 64
|
nax_burst_size = 64
|
||||||
assert data_width >= nax_data_width # FIXME: Only supporting up-conversion for now.
|
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.
|
assert data_width <= nax_burst_size*8 # FIXME: AXIUpConverter doing assumptions on minimal burst_size.
|
||||||
|
|
||||||
ibus = axi.AXIInterface(
|
mbus = axi.AXIInterface(
|
||||||
data_width = nax_data_width,
|
data_width = NaxRiscv.litedram_width,
|
||||||
address_width = 32,
|
address_width = 32,
|
||||||
id_width = 1,
|
id_width = 8, #TODO
|
||||||
)
|
)
|
||||||
dbus = axi.AXIInterface(
|
self.memory_buses.append(mbus)
|
||||||
data_width = nax_data_width,
|
|
||||||
address_width = 32,
|
|
||||||
id_width = 4,
|
|
||||||
)
|
|
||||||
self.memory_buses.append(ibus)
|
|
||||||
self.memory_buses.append(dbus)
|
|
||||||
|
|
||||||
self.cpu_params.update(
|
self.cpu_params.update(
|
||||||
# Instruction Memory Bus (Master).
|
# Memory Bus (Master).
|
||||||
o_ram_ibus_arvalid = ibus.ar.valid,
|
o_mBus_awvalid = mbus.aw.valid,
|
||||||
i_ram_ibus_arready = ibus.ar.ready,
|
i_mBus_awready = mbus.aw.ready,
|
||||||
o_ram_ibus_araddr = ibus.ar.addr,
|
o_mBus_awaddr = mbus.aw.addr,
|
||||||
o_ram_ibus_arlen = ibus.ar.len,
|
o_mBus_awid = mbus.aw.id,
|
||||||
o_ram_ibus_arsize = ibus.ar.size,
|
o_mBus_awlen = mbus.aw.len,
|
||||||
o_ram_ibus_arburst = ibus.ar.burst,
|
o_mBus_awsize = mbus.aw.size,
|
||||||
i_ram_ibus_rvalid = ibus.r.valid,
|
o_mBus_awburst = mbus.aw.burst,
|
||||||
o_ram_ibus_rready = ibus.r.ready,
|
o_mBus_awallStrb = Open(),
|
||||||
i_ram_ibus_rdata = ibus.r.data,
|
o_mBus_wvalid = mbus.w.valid,
|
||||||
i_ram_ibus_rresp = ibus.r.resp,
|
i_mBus_wready = mbus.w.ready,
|
||||||
i_ram_ibus_rlast = ibus.r.last,
|
o_mBus_wdata = mbus.w.data,
|
||||||
|
o_mBus_wstrb = mbus.w.strb,
|
||||||
# Data Memory Bus (Master).
|
o_mBus_wlast = mbus.w.last,
|
||||||
o_ram_dbus_awvalid = dbus.aw.valid,
|
i_mBus_bvalid = mbus.b.valid,
|
||||||
i_ram_dbus_awready = dbus.aw.ready,
|
o_mBus_bready = mbus.b.ready,
|
||||||
o_ram_dbus_awaddr = dbus.aw.addr,
|
i_mBus_bid = mbus.b.id,
|
||||||
o_ram_dbus_awid = dbus.aw.id,
|
i_mBus_bresp = mbus.b.resp,
|
||||||
o_ram_dbus_awlen = dbus.aw.len,
|
o_mBus_arvalid = mbus.ar.valid,
|
||||||
o_ram_dbus_awsize = dbus.aw.size,
|
i_mBus_arready = mbus.ar.ready,
|
||||||
o_ram_dbus_awburst = dbus.aw.burst,
|
o_mBus_araddr = mbus.ar.addr,
|
||||||
o_ram_dbus_wvalid = dbus.w.valid,
|
o_mBus_arid = mbus.ar.id,
|
||||||
i_ram_dbus_wready = dbus.w.ready,
|
o_mBus_arlen = mbus.ar.len,
|
||||||
o_ram_dbus_wdata = dbus.w.data,
|
o_mBus_arsize = mbus.ar.size,
|
||||||
o_ram_dbus_wstrb = dbus.w.strb,
|
o_mBus_arburst = mbus.ar.burst,
|
||||||
o_ram_dbus_wlast = dbus.w.last,
|
i_mBus_rvalid = mbus.r.valid,
|
||||||
i_ram_dbus_bvalid = dbus.b.valid,
|
o_mBus_rready = mbus.r.ready,
|
||||||
o_ram_dbus_bready = dbus.b.ready,
|
i_mBus_rdata = mbus.r.data,
|
||||||
i_ram_dbus_bid = dbus.b.id,
|
i_mBus_rid = mbus.r.id,
|
||||||
i_ram_dbus_bresp = dbus.b.resp,
|
i_mBus_rresp = mbus.r.resp,
|
||||||
o_ram_dbus_arvalid = dbus.ar.valid,
|
i_mBus_rlast = mbus.r.last,
|
||||||
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,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def do_finalize(self):
|
def do_finalize(self):
|
||||||
|
|
|
@ -2,6 +2,11 @@
|
||||||
.global isr
|
.global isr
|
||||||
.global _start
|
.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_INITIAL (1 << 13)
|
||||||
#define MSTATUS_FS_CLEAN (2 << 13)
|
#define MSTATUS_FS_CLEAN (2 << 13)
|
||||||
#define MSTATUS_FS_DIRTY (3 << 13)
|
#define MSTATUS_FS_DIRTY (3 << 13)
|
||||||
|
@ -67,6 +72,24 @@ enable_fpu:
|
||||||
li x1, MSTATUS_FS_INITIAL
|
li x1, MSTATUS_FS_INITIAL
|
||||||
csrs mstatus, x1
|
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:
|
data_init:
|
||||||
la a0, _fdata
|
la a0, _fdata
|
||||||
la a1, _edata
|
la a1, _edata
|
||||||
|
@ -96,3 +119,10 @@ bss_done:
|
||||||
call main
|
call main
|
||||||
infinit_loop:
|
infinit_loop:
|
||||||
j 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
|
||||||
|
|
||||||
|
|
|
@ -122,7 +122,7 @@ git_repos = {
|
||||||
"pythondata-cpu-cva6": GitRepo(url="https://github.com/litex-hub/", clone="recursive"),
|
"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-ibex": GitRepo(url="https://github.com/litex-hub/", clone="recursive", sha1=0xd3d53df),
|
||||||
"pythondata-cpu-minerva": GitRepo(url="https://github.com/litex-hub/"),
|
"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-picorv32": GitRepo(url="https://github.com/litex-hub/"),
|
||||||
"pythondata-cpu-rocket": 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/"),
|
"pythondata-cpu-serv": GitRepo(url="https://github.com/litex-hub/"),
|
||||||
|
|
Loading…
Reference in New Issue