From 35dd87499c99c76a594044981bfd1a5fd06f4a98 Mon Sep 17 00:00:00 2001 From: Jiaxun Yang Date: Tue, 5 Mar 2024 21:34:56 +0000 Subject: [PATCH 01/28] build/openocd: Disable polling after init OpenOCD's event polling mechanism may interfere with jtagstream, as we don't expect any command sent by openocd itself. Signed-off-by: Jiaxun Yang --- litex/build/openocd.py | 1 + 1 file changed, 1 insertion(+) diff --git a/litex/build/openocd.py b/litex/build/openocd.py index 2a8f47684..8518a586c 100644 --- a/litex/build/openocd.py +++ b/litex/build/openocd.py @@ -185,6 +185,7 @@ proc jtagstream_serve {tap port} { write_to_file("stream.cfg", cfg) script = "; ".join([ "init", + "poll off", "irscan $_CHIPNAME.tap {:d}".format(ir), "jtagstream_serve $_CHIPNAME.tap {:d}".format(port), "exit", From 18720e29cc4c03207816b79112132f971f43eb19 Mon Sep 17 00:00:00 2001 From: Jiaxun Yang Date: Tue, 5 Mar 2024 21:42:59 +0000 Subject: [PATCH 02/28] build/openocd: Fix tap name for zynq_7000 zynq_7000 have a special tap name fpr PL defined in openocd config file. Just hardcode it here. Signed-off-by: Jiaxun Yang --- litex/build/openocd.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/litex/build/openocd.py b/litex/build/openocd.py index 8518a586c..166fb2e26 100644 --- a/litex/build/openocd.py +++ b/litex/build/openocd.py @@ -40,6 +40,12 @@ class OpenOCD(GenericProgrammer): ]) self.call(["openocd", "-f", config, "-c", script]) + def get_tap_name(self, config): + cfg_str = open(config).read() + if "zynq_7000" in cfg_str: + return "zynq_pl.bs" + return "$_CHIPNAME.tap" + def get_ir(self, chain, config): cfg_str = open(config).read() # Lattice ECP5. @@ -98,6 +104,7 @@ class OpenOCD(GenericProgrammer): - TX valid : bit 9 """ config = self.find_config() + tap_name = self.get_tap_name(config) ir = self.get_ir(chain, config) endstate = self.get_endstate(config) cfg = """ @@ -186,8 +193,8 @@ proc jtagstream_serve {tap port} { script = "; ".join([ "init", "poll off", - "irscan $_CHIPNAME.tap {:d}".format(ir), - "jtagstream_serve $_CHIPNAME.tap {:d}".format(port), + "irscan {} {:d}".format(tap_name, ir), + "jtagstream_serve {} {:d}".format(tap_name, port), "exit", ]) self.call(["openocd", "-f", config, "-f", "stream.cfg", "-c", script]) From a7d441488c784859813579321581c80dc7fc10ba Mon Sep 17 00:00:00 2001 From: Jiaxun Yang Date: Thu, 7 Mar 2024 19:54:04 +0000 Subject: [PATCH 03/28] build/openocd: Allow config file to be searched from local dirs To sort out path for boards using OpenOCD config file shipped with OpenOCD itself. Signed-off-by: Jiaxun Yang --- litex/build/generic_programmer.py | 9 ++++++--- litex/build/openocd.py | 2 ++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/litex/build/generic_programmer.py b/litex/build/generic_programmer.py index de968f60d..4c7f602d8 100644 --- a/litex/build/generic_programmer.py +++ b/litex/build/generic_programmer.py @@ -24,6 +24,7 @@ class GenericProgrammer: self.flash_proxy_repos = [ "https://github.com/quartiq/bscan_spi_bitstreams/raw/master/", ] + self.config_dirs = ["prog"] self.config_repos = [ "https://raw.githubusercontent.com/litex-hub/litex-boards/master/litex_boards/prog/", ] @@ -65,9 +66,11 @@ class GenericProgrammer: if os.path.exists(fullname): return self.config # Search in local config directory - fullname = tools.cygpath(os.path.join(self.prog_local, self.config)) - if os.path.exists(fullname): - return fullname + for d in self.config_dirs: + fulldir = os.path.abspath(os.path.expanduser(d)) + fullname = tools.cygpath(os.path.join(fulldir, self.config)) + if os.path.exists(fullname): + return fullname # Search in repositories and download it import requests os.makedirs(self.prog_local, exist_ok=True) diff --git a/litex/build/openocd.py b/litex/build/openocd.py index 166fb2e26..b95d9f1a2 100644 --- a/litex/build/openocd.py +++ b/litex/build/openocd.py @@ -17,6 +17,8 @@ class OpenOCD(GenericProgrammer): def __init__(self, config, flash_proxy_basename=None): GenericProgrammer.__init__(self, flash_proxy_basename) self.config = config + self.config_dirs.append("/usr/share/openocd/scripts") + self.config_dirs.append("/usr/local/share/openocd/scripts") def load_bitstream(self, bitstream): config = self.find_config() From 8f04542c15d062e566df71047815aa089022e8bf Mon Sep 17 00:00:00 2001 From: Gwenhael Goavec-Merou Date: Wed, 20 Mar 2024 16:44:58 +0100 Subject: [PATCH 04/28] Revert "build/openocd: Allow config file to be searched from local dirs" This reverts commit a7d441488c784859813579321581c80dc7fc10ba. --- litex/build/generic_programmer.py | 9 +++------ litex/build/openocd.py | 2 -- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/litex/build/generic_programmer.py b/litex/build/generic_programmer.py index 4c7f602d8..de968f60d 100644 --- a/litex/build/generic_programmer.py +++ b/litex/build/generic_programmer.py @@ -24,7 +24,6 @@ class GenericProgrammer: self.flash_proxy_repos = [ "https://github.com/quartiq/bscan_spi_bitstreams/raw/master/", ] - self.config_dirs = ["prog"] self.config_repos = [ "https://raw.githubusercontent.com/litex-hub/litex-boards/master/litex_boards/prog/", ] @@ -66,11 +65,9 @@ class GenericProgrammer: if os.path.exists(fullname): return self.config # Search in local config directory - for d in self.config_dirs: - fulldir = os.path.abspath(os.path.expanduser(d)) - fullname = tools.cygpath(os.path.join(fulldir, self.config)) - if os.path.exists(fullname): - return fullname + fullname = tools.cygpath(os.path.join(self.prog_local, self.config)) + if os.path.exists(fullname): + return fullname # Search in repositories and download it import requests os.makedirs(self.prog_local, exist_ok=True) diff --git a/litex/build/openocd.py b/litex/build/openocd.py index b95d9f1a2..166fb2e26 100644 --- a/litex/build/openocd.py +++ b/litex/build/openocd.py @@ -17,8 +17,6 @@ class OpenOCD(GenericProgrammer): def __init__(self, config, flash_proxy_basename=None): GenericProgrammer.__init__(self, flash_proxy_basename) self.config = config - self.config_dirs.append("/usr/share/openocd/scripts") - self.config_dirs.append("/usr/local/share/openocd/scripts") def load_bitstream(self, bitstream): config = self.find_config() From c640efcec320adf52d452887dd156ba8ed765049 Mon Sep 17 00:00:00 2001 From: jdavidberger Date: Wed, 20 Mar 2024 10:16:45 -0600 Subject: [PATCH 05/28] Avoid extra timing delays for NXLRAM path --- litex/soc/cores/ram/lattice_nx.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/litex/soc/cores/ram/lattice_nx.py b/litex/soc/cores/ram/lattice_nx.py index b2fa75fee..20eada5da 100644 --- a/litex/soc/cores/ram/lattice_nx.py +++ b/litex/soc/cores/ram/lattice_nx.py @@ -79,10 +79,10 @@ class NXLRAM(LiteXModule): wren = Signal() self.comb += [ datain.eq(self.bus.dat_w[32*w:32*(w+1)]), + self.bus.dat_r[32*w:32*(w+1)].eq(dataout), If(self.bus.adr[14:14+self.depth_cascading.bit_length()] == d, cs.eq(1), - wren.eq(self.bus.we & self.bus.stb & self.bus.cyc), - self.bus.dat_r[32*w:32*(w+1)].eq(dataout) + wren.eq(self.bus.we & self.bus.stb & self.bus.cyc) ), ] lram_block = Instance("SP512K", From 68108e396dafc74c6cc3a96e0071edc7fe05f0e5 Mon Sep 17 00:00:00 2001 From: Gwenhael Goavec-Merou Date: Thu, 21 Mar 2024 20:53:19 +0100 Subject: [PATCH 06/28] tools/litex_json2dts_linux: added isa-base,isa-extensions required by kernel > 6.6.0 in replacement to isa --- litex/tools/litex_json2dts_linux.py | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/litex/tools/litex_json2dts_linux.py b/litex/tools/litex_json2dts_linux.py index 5ccf5d47d..5fca60b81 100755 --- a/litex/tools/litex_json2dts_linux.py +++ b/litex/tools/litex_json2dts_linux.py @@ -32,7 +32,9 @@ def generate_dts(d, initrd_start=None, initrd_size=None, initrd=None, root_devic ncpus = int(d["constants"].get("config_cpu_count", 1)) cpu_name = d["constants"].get("config_cpu_name") cpu_arch = cpu_architectures[cpu_name] - cpu_isa = d["constants"].get("config_cpu_isa", None) + cpu_isa = d["constants"].get("config_cpu_isa", None) # kernel < 6.6.0 + cpu_isa_base = cpu_isa[:5] # kernel >= 6.6.0 + cpu_isa_extensions = "\"i\", \"m\", \"a\"" # kernel >= 6.6.0 cpu_mmu = d["constants"].get("config_cpu_mmu", None) # Header --------------------------------------------------------------------------------------- @@ -152,7 +154,6 @@ def generate_dts(d, initrd_start=None, initrd_size=None, initrd=None, root_devic # Rocket specific attributes if ("rocket" in cpu_name): - cpu_isa = cpu_isa.replace("2p0_", "") extra_attr = """ hardware-exec-breakpoint-count = <1>; next-level-cache = <&memory>; @@ -190,6 +191,8 @@ def generate_dts(d, initrd_start=None, initrd_size=None, initrd=None, root_devic device_type = "cpu"; compatible = "riscv"; riscv,isa = "{cpu_isa}"; + riscv,isa-base = "{cpu_isa_base}"; + riscv,isa-extensions = {cpu_isa_extensions}; mmu-type = "riscv,{cpu_mmu}"; reg = <{cpu}>; clock-frequency = <{sys_clk_freq}>; @@ -205,12 +208,14 @@ def generate_dts(d, initrd_start=None, initrd_size=None, initrd=None, root_devic }}; }}; """.format(cpu=cpu, irq=cpu, - sys_clk_freq = d["constants"]["config_clock_frequency"], - cpu_isa = cpu_isa, - cpu_mmu = cpu_mmu, - cache_desc = cache_desc, - tlb_desc = tlb_desc, - extra_attr = extra_attr) + sys_clk_freq = d["constants"]["config_clock_frequency"], + cpu_isa = cpu_isa, # for kernel < 6.6.0 + cpu_isa_base = cpu_isa_base, # for kernel >= 6.6.0 + cpu_isa_extensions = cpu_isa_extensions, # for kernel >= 6.6.0 + cpu_mmu = cpu_mmu, + cache_desc = cache_desc, + tlb_desc = tlb_desc, + extra_attr = extra_attr) dts += """ {cpu_map} }}; From 9156d7902e223364bb05c84587702f63c74fb03a Mon Sep 17 00:00:00 2001 From: Gwenhael Goavec-Merou Date: Thu, 21 Mar 2024 20:54:08 +0100 Subject: [PATCH 07/28] tools/litex_json2dts_linux: increment interrupts value by one for rocket --- litex/tools/litex_json2dts_linux.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/litex/tools/litex_json2dts_linux.py b/litex/tools/litex_json2dts_linux.py index 5fca60b81..4620b5ac2 100755 --- a/litex/tools/litex_json2dts_linux.py +++ b/litex/tools/litex_json2dts_linux.py @@ -386,6 +386,7 @@ def generate_dts(d, initrd_start=None, initrd_size=None, initrd=None, root_devic if "uart" in d["csr_bases"]: aliases["serial0"] = "liteuart0" + it_incr = {True: 1, False: 0}["rocket" in cpu_name] dts += """ liteuart0: serial@{uart_csr_base:x} {{ compatible = "litex,liteuart"; @@ -395,11 +396,12 @@ def generate_dts(d, initrd_start=None, initrd_size=None, initrd=None, root_devic }}; """.format( uart_csr_base = d["csr_bases"]["uart"], - uart_interrupt = "" if polling else "interrupts = <{}>;".format(d["constants"]["uart_interrupt"])) + uart_interrupt = "" if polling else "interrupts = <{}>;".format(int(d["constants"]["uart_interrupt"]) + it_incr)) # Ethernet ------------------------------------------------------------------------------------- if "ethphy" in d["csr_bases"] and "ethmac" in d["csr_bases"]: + it_incr = {True: 1, False: 0}["rocket" in cpu_name] dts += """ mac0: mac@{ethmac_csr_base:x} {{ compatible = "litex,liteeth"; @@ -421,7 +423,7 @@ def generate_dts(d, initrd_start=None, initrd_size=None, initrd=None, root_devic ethmac_rx_slots = d["constants"]["ethmac_rx_slots"], ethmac_tx_slots = d["constants"]["ethmac_tx_slots"], ethmac_slot_size = d["constants"]["ethmac_slot_size"], - ethmac_interrupt = "" if polling else "interrupts = <{}>;".format(d["constants"]["ethmac_interrupt"])) + ethmac_interrupt = "" if polling else "interrupts = <{}>;".format(int(d["constants"]["ethmac_interrupt"]) + it_incr)) # USB OHCI ------------------------------------------------------------------------------------- From 40ff2da45c18413afabd2bccd7820ee5cf8b8d9d Mon Sep 17 00:00:00 2001 From: Fernando Oleo Blanco Date: Sat, 23 Mar 2024 10:18:07 +0100 Subject: [PATCH 08/28] Update NeoRV32 CPU to v1.9.7 --- litex/soc/cores/cpu/neorv32/core.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/litex/soc/cores/cpu/neorv32/core.py b/litex/soc/cores/cpu/neorv32/core.py index a3f953048..174f39c51 100644 --- a/litex/soc/cores/cpu/neorv32/core.py +++ b/litex/soc/cores/cpu/neorv32/core.py @@ -171,11 +171,14 @@ class NEORV32(CPU): "neorv32_application_image.vhd", "neorv32_bootloader_image.vhd", "neorv32_boot_rom.vhd", + "neorv32_cache.vhd", "neorv32_cfs.vhd", + "neorv32_clockgate.vhd", "neorv32_cpu_alu.vhd", "neorv32_cpu_control.vhd", "neorv32_cpu_cp_bitmanip.vhd", "neorv32_cpu_cp_cfu.vhd", + "neorv32_cpu_cp_cond.vhd", "neorv32_cpu_cp_fpu.vhd", "neorv32_cpu_cp_muldiv.vhd", "neorv32_cpu_cp_shifter.vhd", @@ -185,7 +188,6 @@ class NEORV32(CPU): "neorv32_cpu_regfile.vhd", "neorv32_cpu.vhd", "neorv32_crc.vhd", - "neorv32_dcache.vhd", "neorv32_debug_dm.vhd", "neorv32_debug_dtm.vhd", "neorv32_dma.vhd", @@ -193,7 +195,6 @@ class NEORV32(CPU): "neorv32_fifo.vhd", "neorv32_gpio.vhd", "neorv32_gptmr.vhd", - "neorv32_icache.vhd", "neorv32_imem.entity.vhd", "neorv32_intercon.vhd", "neorv32_mtime.vhd", @@ -210,7 +211,7 @@ class NEORV32(CPU): "neorv32_twi.vhd", "neorv32_uart.vhd", "neorv32_wdt.vhd", - "neorv32_wishbone.vhd", + "neorv32_xbus.vhd", "neorv32_xip.vhd", "neorv32_xirq.vhd", ], @@ -226,8 +227,8 @@ class NEORV32(CPU): } # Download VHDL sources (if not already present). - # Version 1.8.9 - sha1 = "fdb00a5d24e256ac9a9cb29410f2653c95068c91" + # Version 1.9.7 + sha1 = "ed17ae4df64e6a5221562e4adf4de378eaf0c2e8" for directory, vhds in sources.items(): for vhd in vhds: self.vhd2v_converter.add_source(os.path.join(cdir, vhd)) From 4389742a4f8ba1c9a62a58afa3ecf9cdf8d7a017 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Mon, 25 Mar 2024 19:10:07 +0100 Subject: [PATCH 09/28] CHANGES.md: Update. --- CHANGES.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 413a92d40..dda61b273 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -9,6 +9,7 @@ - litespi/software: : Fixed SPI Flash Clk Divider computation when with L2 Cache. - litepcie/us(p)pciephy : Fixed x8 / 256-bit wide case. - litex_sim/serial2console : Fixed RX backpressure handling. + - litedram/frontend/avalon : Fixed and cleaned-up. [> Added -------- @@ -27,6 +28,9 @@ - litex_sim : Added jtagremote support. - soc/add_master : Added region support to allow/limit access to a specific region. - litex_json2dts_linux : Added ip= bootarg when local/remote ips are defined. + - cores/jtag : Added JTAGBone support for Zynq. + - cores/ram/lattice_nx : Improved timings. + - liteeth_gen : Added QPLL/BUFH/BUFG parameters for A7 1000BaseX PHY. [> Changed ---------- From 6735728340b0854fec9ace3b20b34bb75a4e7f29 Mon Sep 17 00:00:00 2001 From: David A Roberts Date: Tue, 26 Mar 2024 20:22:58 +1000 Subject: [PATCH 10/28] sim/video: Change pixel format to RGBA --- litex/build/sim/core/modules/video/sim_fb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/litex/build/sim/core/modules/video/sim_fb.c b/litex/build/sim/core/modules/video/sim_fb.c index 79c5c10f5..3535985a7 100644 --- a/litex/build/sim/core/modules/video/sim_fb.c +++ b/litex/build/sim/core/modules/video/sim_fb.c @@ -17,7 +17,7 @@ bool fb_init(unsigned width, unsigned height, bool vsync, fb_handle_t *handle) if (!handle->renderer) return false; - handle->texture = SDL_CreateTexture(handle->renderer, SDL_PIXELFORMAT_BGRA32, SDL_TEXTUREACCESS_TARGET, width, height); + handle->texture = SDL_CreateTexture(handle->renderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_TARGET, width, height); if (!handle->texture) return false; From 1895dd36e2b96ac7969481b492b9e7e18bbbed44 Mon Sep 17 00:00:00 2001 From: David A Roberts Date: Tue, 26 Mar 2024 20:23:51 +1000 Subject: [PATCH 11/28] tools/litex_sim: Add --with-video-colorbars option --- litex/tools/litex_sim.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/litex/tools/litex_sim.py b/litex/tools/litex_sim.py index 1e412b87c..5444ad449 100755 --- a/litex/tools/litex_sim.py +++ b/litex/tools/litex_sim.py @@ -178,6 +178,7 @@ class SimSoC(SoCCore): with_gpio = False, with_video_framebuffer = False, with_video_terminal = False, + with_video_colorbars = False, sim_debug = False, trace_reset_on = False, with_jtag = False, @@ -313,6 +314,11 @@ class SimSoC(SoCCore): self.submodules.videophy = VideoGenericPHY(platform.request("vga")) self.add_video_terminal(phy=self.videophy, timings="640x480@60Hz") + # Video test pattern ----------------------------------------------------------------------- + if with_video_colorbars: + self.submodules.videophy = VideoGenericPHY(platform.request("vga")) + self.add_video_colorbars(phy=self.videophy, timings="640x480@60Hz") + # Simulation debugging ---------------------------------------------------------------------- if sim_debug: platform.add_debug(self, reset=1 if trace_reset_on else 0) @@ -428,6 +434,7 @@ def sim_args(parser): # Video. parser.add_argument("--with-video-framebuffer", action="store_true", help="Enable Video Framebuffer.") parser.add_argument("--with-video-terminal", action="store_true", help="Enable Video Terminal.") + parser.add_argument("--with-video-colorbars", action="store_true", help="Enable Video test pattern.") # Debug/Waveform. parser.add_argument("--sim-debug", action="store_true", help="Add simulation debugging modules.") @@ -510,7 +517,7 @@ def main(): sim_config.add_module("jtagremote", "jtag", args={'port': 44853}) # Video. - if args.with_video_framebuffer or args.with_video_terminal: + if args.with_video_framebuffer or args.with_video_terminal or args.with_video_colorbars: sim_config.add_module("video", "vga") # SoC ------------------------------------------------------------------------------------------ @@ -528,6 +535,7 @@ def main(): with_gpio = args.with_gpio, with_video_framebuffer = args.with_video_framebuffer, with_video_terminal = args.with_video_terminal, + with_video_colorbars = args.with_video_colorbars, sim_debug = args.sim_debug, trace_reset_on = int(float(args.trace_start)) > 0 or int(float(args.trace_end)) > 0, spi_flash_init = None if args.spi_flash_init is None else get_mem_data(args.spi_flash_init, endianness="big"), @@ -551,7 +559,7 @@ def main(): builder.build( sim_config = sim_config, interactive = not args.non_interactive, - video = args.with_video_framebuffer or args.with_video_terminal, + video = args.with_video_framebuffer or args.with_video_terminal or args.with_video_colorbars, pre_run_callback = pre_run_callback, **parser.toolchain_argdict, ) From e74b7f7ebe291585d5f91a82eddcbd1632f1a6db Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Wed, 27 Mar 2024 16:49:09 +0100 Subject: [PATCH 12/28] integration/export: Fix MockCSRRegion C header export. Use full address for export since when used, CSR_BASE is related to the top level SoC and not to the imported external mapping. --- litex/soc/integration/export.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/litex/soc/integration/export.py b/litex/soc/integration/export.py index f04b03fef..5a0475cec 100644 --- a/litex/soc/integration/export.py +++ b/litex/soc/integration/export.py @@ -279,7 +279,7 @@ def get_csr_header(regions, constants, csr_base=None, with_csr_base_define=True, alignment = alignment, read_only = getattr(csr, "read_only", False), csr_base = csr_base, - with_csr_base_define = with_csr_base_define, + with_csr_base_define = with_csr_base_define and (not isinstance(region, MockCSRRegion)), with_access_functions = with_access_functions, ) origin += alignment//8*nr From 60920f3c7dc13f49332ad4dab68ccaf12aa60a43 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Wed, 27 Mar 2024 17:09:33 +0100 Subject: [PATCH 13/28] integration/export: Also fix MockCSRRegion base definition. --- litex/soc/integration/export.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/litex/soc/integration/export.py b/litex/soc/integration/export.py index 5a0475cec..21ac7e7fc 100644 --- a/litex/soc/integration/export.py +++ b/litex/soc/integration/export.py @@ -265,9 +265,10 @@ def get_csr_header(regions, constants, csr_base=None, with_csr_base_define=True, r += f"#define CSR_BASE {hex(csr_base)}L\n" r += "#endif\n" for name, region in regions.items(): - origin = region.origin - _csr_base + origin = region.origin - _csr_base + base_define = not isinstance(region, MockCSRRegion) r += "\n/* "+name+" */\n" - r += f"#define CSR_{name.upper()}_BASE {_get_csr_addr(csr_base, origin, with_csr_base_define)}\n" + r += f"#define CSR_{name.upper()}_BASE {_get_csr_addr(csr_base, origin, base_define)}\n" if not isinstance(region.obj, Memory): for csr in region.obj: nr = (csr.size + region.busword - 1)//region.busword @@ -279,7 +280,7 @@ def get_csr_header(regions, constants, csr_base=None, with_csr_base_define=True, alignment = alignment, read_only = getattr(csr, "read_only", False), csr_base = csr_base, - with_csr_base_define = with_csr_base_define and (not isinstance(region, MockCSRRegion)), + with_csr_base_define = base_define, with_access_functions = with_access_functions, ) origin += alignment//8*nr From 87137c30277f36ed275d28894aba383759e6e519 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Thu, 28 Mar 2024 14:24:12 +0100 Subject: [PATCH 14/28] CHANGES.md: Update. --- CHANGES.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index dda61b273..8f6b06604 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -10,6 +10,7 @@ - litepcie/us(p)pciephy : Fixed x8 / 256-bit wide case. - litex_sim/serial2console : Fixed RX backpressure handling. - litedram/frontend/avalon : Fixed and cleaned-up. + - litex_sim/video : Fixed pixel format to RGBA. [> Added -------- @@ -31,6 +32,8 @@ - cores/jtag : Added JTAGBone support for Zynq. - cores/ram/lattice_nx : Improved timings. - liteeth_gen : Added QPLL/BUFH/BUFG parameters for A7 1000BaseX PHY. + - litex_sim : Added Video Color Bar support. + - cpu/neorv32 : Updated to v1.9.7. [> Changed ---------- From 5d2676482f75eb32f6acb7dacce69908d3c197b7 Mon Sep 17 00:00:00 2001 From: David A Roberts Date: Fri, 29 Mar 2024 11:24:16 +1000 Subject: [PATCH 15/28] sim/video: Add option to render only on frame vsync --- litex/build/sim/core/modules/video/video.c | 47 +++++++++++++++++++--- litex/tools/litex_sim.py | 3 +- 2 files changed, 44 insertions(+), 6 deletions(-) diff --git a/litex/build/sim/core/modules/video/video.c b/litex/build/sim/core/modules/video/video.c index 7549b5545..264845569 100644 --- a/litex/build/sim/core/modules/video/video.c +++ b/litex/build/sim/core/modules/video/video.c @@ -5,6 +5,7 @@ #include #include #include +#include #include "error.h" #include #include @@ -29,6 +30,7 @@ struct session_s { unsigned frame, stride; uint8_t *buf, *pbuf; fb_handle_t fb; + char render_on_vsync; }; static int litex_sim_module_pads_get(struct pad_s *pads, char *name, void **signal) @@ -56,6 +58,30 @@ out: return ret; } +static int videosim_parse_args(struct session_s *s, const char *args) +{ + int ret = RC_OK; + json_object *args_json = NULL; + json_object *render_on_vsync_json = NULL; + + args_json = json_tokener_parse(args); + if (!args_json) { + ret = RC_JSERROR; + fprintf(stderr, "[video] Could not parse args: %s\n", args); + goto out; + } + + if(json_object_object_get_ex(args_json, "render_on_vsync", &render_on_vsync_json)) { + s->render_on_vsync = json_object_get_boolean(render_on_vsync_json); + } else { + s->render_on_vsync = false; + } + +out: + if(args_json) json_object_put(args_json); + return ret; +} + static int videosim_start(void *b) { printf("[video] loaded (%p)\n", (struct event_base *)b); @@ -79,6 +105,7 @@ static int videosim_new(void **sess, char *args) } memset(s, 0, sizeof(struct session_s)); + if (args) videosim_parse_args(s, args); out: *sess = (void*) s; return ret; @@ -143,6 +170,14 @@ static int videosim_tick(void *sess, uint64_t time_ps) { fb_init(s->hres, s->vres, false, &s->fb); s->stride = s->hres*sizeof(uint32_t); } + if (s->render_on_vsync) { + if(fb_should_quit()) + { + fb_deinit(&s->fb); + exit(1); //FIXME: end gracefully + } + fb_update(&s->fb, s->buf, s->stride); + } s->y = 0; s->pbuf = s->buf; ++s->frame; @@ -164,12 +199,14 @@ static int videosim_tick(void *sess, uint64_t time_ps) { { if(s->buf) //update each horizontal line { - if(fb_should_quit()) - { - fb_deinit(&s->fb); - exit(1); //FIXME: end gracefully + if (!s->render_on_vsync) { + if(fb_should_quit()) + { + fb_deinit(&s->fb); + exit(1); //FIXME: end gracefully + } + fb_update(&s->fb, s->buf, s->stride); } - fb_update(&s->fb, s->buf, s->stride); s->pbuf = s->buf + s->y*s->stride; } diff --git a/litex/tools/litex_sim.py b/litex/tools/litex_sim.py index 5444ad449..5a1cb0da8 100755 --- a/litex/tools/litex_sim.py +++ b/litex/tools/litex_sim.py @@ -435,6 +435,7 @@ def sim_args(parser): parser.add_argument("--with-video-framebuffer", action="store_true", help="Enable Video Framebuffer.") parser.add_argument("--with-video-terminal", action="store_true", help="Enable Video Terminal.") parser.add_argument("--with-video-colorbars", action="store_true", help="Enable Video test pattern.") + parser.add_argument("--video-vsync", action="store_true", help="Only render on frame vsync.") # Debug/Waveform. parser.add_argument("--sim-debug", action="store_true", help="Add simulation debugging modules.") @@ -518,7 +519,7 @@ def main(): # Video. if args.with_video_framebuffer or args.with_video_terminal or args.with_video_colorbars: - sim_config.add_module("video", "vga") + sim_config.add_module("video", "vga", args={"render_on_vsync": args.video_vsync}) # SoC ------------------------------------------------------------------------------------------ soc = SimSoC( From a763e82d861db9ae237eb8a7ae1da8f295f29ca9 Mon Sep 17 00:00:00 2001 From: Andrew Dennison Date: Thu, 3 Aug 2023 16:24:06 +1000 Subject: [PATCH 16/28] soc/builder: add initialize_memory() Allows the target soc to override memory initialization: rom and/or ram. --- litex/soc/integration/builder.py | 5 +++- litex/soc/integration/soc_core.py | 42 +++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/litex/soc/integration/builder.py b/litex/soc/integration/builder.py index dfe0fc7b7..d11e94bbb 100644 --- a/litex/soc/integration/builder.py +++ b/litex/soc/integration/builder.py @@ -388,8 +388,11 @@ class Builder: self._prepare_rom_software() self._generate_rom_software(compile_bios=use_bios) + # Allow soc to override the memory initialisation. + self.soc.initialize_memory(self.software_dir, **kwargs) + # Initialize ROM. - if use_bios and self.soc.integrated_rom_size: + if use_bios and self.soc.integrated_rom_size and not getattr(self.soc, "rom").mem.init: self._initialize_rom_software() # Translate compile_gateware to run. diff --git a/litex/soc/integration/soc_core.py b/litex/soc/integration/soc_core.py index 28611d197..39477d3c1 100644 --- a/litex/soc/integration/soc_core.py +++ b/litex/soc/integration/soc_core.py @@ -282,6 +282,48 @@ class SoCCore(LiteXSoC): def add_csr_region(self, name, origin, busword, obj): self.csr_regions[name] = SoCCSRRegion(origin, busword, obj) + def initialize_memory(self, software_dir, **kwargs): + """initialize_memory + The target SoC can implement this function to override the memory initialisation + during the build to load a program or data to main_ram and/or rom. + + Parameters + ---------- + software_dir : str + Builder software_dir where the soc libs and bios are built. + + kwargs + Builder kwargs for any additional context if required +. + Example: + + class MySoC(SoCCore): + def __init__(self, + ... + self.add_config("MAIN_RAM_INIT") # firmware is in ram + + def initialize_memory(self, software_dir, **kwargs): + if self.cpu_type is None: + return + + filename = os.path.join(software_dir, "firmware", "firmware.bin") + data = get_mem_data(filename, endianness=self.cpu.endianness) + self.init_rom(name="main_ram", contents=data, auto_size=False) + + def main(): + ... + + builder = Builder(soc, **parser.builder_argdict) + + # add custom firmware: compiled by connecting here and stored in initialize_memory() + src="firmware" + src_dir = os.path.join(os.path.abspath(os.path.dirname(__file__)), src) + builder.add_software_package(src, src_dir) + + builder.build(**parser.toolchain_argdict) + """ + pass + # SoCCore arguments -------------------------------------------------------------------------------- def soc_core_args(parser): From 0cb101da25a03e9644167928b7427b4081854ee0 Mon Sep 17 00:00:00 2001 From: Andrew Dennison Date: Mon, 26 Feb 2024 03:32:50 +0000 Subject: [PATCH 17/28] build/efinix/platform: fix get_pin_name() get_pin_name did not include the resource index, so additional core instances were generated with identical pin names. See below for examples. Also only adds slice index for slices with more than one io for cleaner naming. ("i2c", 0, Subsignal("scl", Pins(...)), Subsignal("sda", Pins(...)), ), ("i2c", 1, Subsignal("scl", Pins(...)), Subsignal("sda", Pins(...)), ), Before: output wire i2c0_oe, input wire i2c0_scl, input wire i2c0_sda, input wire i2c1_scl, input wire i2c1_sda, input wire i2c_scl0_IN, input wire i2c_scl0_IN_1, input wire i2c_scl0_IN_2, output wire i2c_scl0_OE, output wire i2c_scl0_OE_1, output wire i2c_scl0_OE_2, input wire i2c_sda0_IN, input wire i2c_sda0_IN_1, input wire i2c_sda0_IN_2, output wire i2c_sda0_OE, output wire i2c_sda0_OE_1, output wire i2c_sda0_OE_2, After: output wire i2c0_oe, input wire i2c0_scl, input wire i2c0_scl_IN, output wire i2c0_scl_OE, output wire i2c0_scl_OUT, input wire i2c0_sda, input wire i2c0_sda_IN, output wire i2c0_sda_OE, output wire i2c0_sda_OUT, input wire i2c1_scl, input wire i2c1_scl_IN, output wire i2c1_scl_OE, output wire i2c1_scl_OUT, input wire i2c1_sda, input wire i2c1_sda_IN, output wire i2c1_sda_OE, output wire i2c1_sda_OUT, --- litex/build/efinix/platform.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/litex/build/efinix/platform.py b/litex/build/efinix/platform.py index 52d1fc4cc..1ec15d767 100644 --- a/litex/build/efinix/platform.py +++ b/litex/build/efinix/platform.py @@ -125,26 +125,24 @@ class EfinixPlatform(GenericPlatform): sig = sig.value return sig - def get_pin_name(self, sig, without_index=False): + def get_pin_name(self, sig): if sig is None: return None assert len(sig) == 1 idx = 0 slc = False while isinstance(sig, _Slice) and hasattr(sig, "value"): - slc = True idx = sig.start sig = sig.value + slc = hasattr(sig, "nbits") and sig.nbits > 1 sc = self.constraint_manager.get_sig_constraints() for s, pins, others, resource in sc: if s == sig: + name = resource[0] + (f"{resource[1]}" if resource[1] is not None else "") if resource[2]: - name = resource[0] + "_" + resource[2] - if without_index is False: - name = name + (f"{idx}" if slc else "") - return name - else: - return resource[0] + (f"{idx}" if slc else "") + name = name + "_" + resource[2] + name = name + (f"{idx}" if slc else "") + return name return None def get_pad_name(self, sig): From f181eabebb6a01b2a171cdcb3abfd18d3232de59 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Tue, 2 Apr 2024 09:12:03 +0200 Subject: [PATCH 18/28] soc/init_rom: Add SoCError when ROM Size < Contents Size and cosmetic cleanups. --- litex/soc/integration/soc.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/litex/soc/integration/soc.py b/litex/soc/integration/soc.py index 8439b97c9..93ae9c297 100644 --- a/litex/soc/integration/soc.py +++ b/litex/soc/integration/soc.py @@ -1050,7 +1050,7 @@ class SoC(LiteXModule, SoCCoreCompat): address_width = self.bus.address_width, bursting = self.bus.bursting ) - ram = ram_cls(size, bus=ram_bus, init=contents, read_only=("w" not in mode), name=name) + ram = ram_cls(size, bus=ram_bus, init=contents, read_only=("w" not in mode), name=name) self.bus.add_slave(name=name, slave=ram.bus, region=SoCRegion(origin=origin, size=size, mode=mode)) self.check_if_exists(name) self.logger.info("RAM {} {} {}.".format( @@ -1068,8 +1068,15 @@ class SoC(LiteXModule, SoCCoreCompat): self.logger.info("Initializing ROM {} with contents (Size: {}).".format( colorer(name), colorer(f"0x{4*len(contents):x}"))) + if self.bus.regions[name].size < 4*len(contents): + self.logger.error("Contents Size ({}) {} ROM Size ({}).".format( + colorer(f"0x{4*len(contents):x}"), + colorer("exceeds", color="red"), + colorer(f"0x{self.bus.regions[name].size:x}"), + )) + raise SoCError() getattr(self, name).mem.init = contents - if auto_size and "w" not in self.bus.regions[name].mode: + if auto_size and ("w" not in self.bus.regions[name].mode): self.logger.info("Auto-Resizing ROM {} from {} to {}.".format( colorer(name), colorer(f"0x{self.bus.regions[name].size:x}"), From 9f49b13f8c8ac48b4cf23746be27bc63a21495d7 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Tue, 2 Apr 2024 09:15:33 +0200 Subject: [PATCH 19/28] soc_core: Minor cosmetic changes. --- litex/soc/integration/soc_core.py | 87 ++++++++++++++++--------------- 1 file changed, 44 insertions(+), 43 deletions(-) diff --git a/litex/soc/integration/soc_core.py b/litex/soc/integration/soc_core.py index 39477d3c1..38dc1f926 100644 --- a/litex/soc/integration/soc_core.py +++ b/litex/soc/integration/soc_core.py @@ -42,7 +42,7 @@ __all__ = [ # SoCCore ------------------------------------------------------------------------------------------ class SoCCore(LiteXSoC): - # Default register/interrupt/memory mappings (can be redefined by user) + # Default register/interrupt/memory mappings (can be redefined by user). csr_map = {} interrupt_map = {} mem_map = { @@ -52,7 +52,7 @@ class SoCCore(LiteXSoC): } def __init__(self, platform, clk_freq, - # Bus parameters + # Bus parameters. bus_standard = "wishbone", bus_data_width = 32, bus_address_width = 32, @@ -60,62 +60,62 @@ class SoCCore(LiteXSoC): bus_bursting = False, bus_interconnect = "shared", - # CPU parameters + # CPU parameters. cpu_type = "vexriscv", cpu_reset_address = None, cpu_variant = None, cpu_cfu = None, - # CFU parameters + # CFU parameters. cfu_filename = None, - # ROM parameters + # ROM parameters. integrated_rom_size = 0, integrated_rom_mode = "rx", integrated_rom_init = [], - # SRAM parameters + # SRAM parameters. integrated_sram_size = 0x2000, integrated_sram_init = [], - # MAIN_RAM parameters + # MAIN_RAM parameters. integrated_main_ram_size = 0, integrated_main_ram_init = [], - # CSR parameters + # CSR parameters. csr_data_width = 32, csr_address_width = 14, csr_paging = 0x800, csr_ordering = "big", - # Interrupt parameters + # Interrupt parameters. irq_n_irqs = 32, - # Identifier parameters + # Identifier parameters. ident = "", ident_version = False, - # UART parameters + # UART parameters. with_uart = True, uart_name = "serial", uart_baudrate = 115200, uart_fifo_depth = 16, - # Timer parameters + # Timer parameters. with_timer = True, timer_uptime = False, - # Controller parameters + # Controller parameters. with_ctrl = True, - # JTAGBone + # JTAGBone. with_jtagbone = False, jtagbone_chain = 1, - # UARTBone + # UARTBone. with_uartbone = False, - # Others + # Others. **kwargs): # New LiteXSoC class ----------------------------------------------------------------------- @@ -138,7 +138,7 @@ class SoCCore(LiteXSoC): irq_reserved_irqs = {}, ) - # Attributes + # Attributes. self.mem_regions = self.bus.regions self.clk_freq = self.sys_clk_freq self.mem_map = self.mem_map @@ -198,28 +198,29 @@ class SoCCore(LiteXSoC): # JTAGBone and jtag_uart can't be used at the same time. assert not (with_jtagbone and uart_name == "jtag_uart") + # UARTBone and serial can't be used at the same time. assert not (with_uartbone and uart_name == "serial") # Modules instances ------------------------------------------------------------------------ - # Add SoCController + # Add SoCController. if with_ctrl: self.add_controller("ctrl") - # Add CPU + # Add CPU. self.add_cpu( name = str(cpu_type), variant = "standard" if cpu_variant is None else cpu_variant, reset_address = None if integrated_rom_size else cpu_reset_address, cfu = cpu_cfu) - # Add User's interrupts + # Add User's interrupts. if self.irq.enabled: for name, loc in self.interrupt_map.items(): self.irq.add(name, loc) - # Add integrated ROM + # Add integrated ROM. if integrated_rom_size: self.add_rom("rom", origin = self.cpu.reset_address, @@ -228,14 +229,14 @@ class SoCCore(LiteXSoC): mode = integrated_rom_mode ) - # Add integrated SRAM + # Add integrated SRAM. if integrated_sram_size: self.add_ram("sram", origin = self.mem_map["sram"], size = integrated_sram_size, ) - # Add integrated MAIN_RAM (only useful when no external SRAM/SDRAM is available) + # Add integrated MAIN_RAM (only useful when no external SRAM/SDRAM is available). if integrated_main_ram_size: self.add_ram("main_ram", origin = self.mem_map["main_ram"], @@ -243,23 +244,23 @@ class SoCCore(LiteXSoC): contents = integrated_main_ram_init, ) - # Add Identifier + # Add Identifier. if ident != "": self.add_identifier("identifier", identifier=ident, with_build_time=ident_version) - # Add UARTBone + # Add UARTBone. if with_uartbone: self.add_uartbone(baudrate=uart_baudrate) - # Add UART + # Add UART. if with_uart: self.add_uart(name="uart", uart_name=uart_name, baudrate=uart_baudrate, fifo_depth=uart_fifo_depth) - # Add JTAGBone + # Add JTAGBone. if with_jtagbone: self.add_jtagbone(chain=jtagbone_chain) - # Add Timer + # Add Timer. if with_timer: self.add_timer(name="timer0") if timer_uptime: @@ -328,7 +329,7 @@ class SoCCore(LiteXSoC): def soc_core_args(parser): soc_group = parser.add_argument_group(title="SoC options") - # Bus parameters + # Bus parameters. soc_group.add_argument("--bus-standard", default="wishbone", help="Select bus standard: {}.".format(", ".join(SoCBusHandler.supported_standard))) soc_group.add_argument("--bus-data-width", default=32, type=auto_int, help="Bus data-width.") soc_group.add_argument("--bus-address-width", default=32, type=auto_int, help="Bus address-width.") @@ -336,53 +337,53 @@ def soc_core_args(parser): soc_group.add_argument("--bus-bursting", action="store_true", help="Enable burst cycles on the bus if supported.") soc_group.add_argument("--bus-interconnect", default="shared", help="Select bus interconnect: shared (default) or crossbar.") - # CPU parameters + # CPU parameters. soc_group.add_argument("--cpu-type", default="vexriscv", help="Select CPU: {}.".format(", ".join(iter(cpu.CPUS.keys())))) soc_group.add_argument("--cpu-variant", default=None, help="CPU variant.") soc_group.add_argument("--cpu-reset-address", default=None, type=auto_int, help="CPU reset address (Boot from Integrated ROM by default).") soc_group.add_argument("--cpu-cfu", default=None, help="Optional CPU CFU file/instance to add to the CPU.") - # Controller parameters + # Controller parameters. soc_group.add_argument("--no-ctrl", action="store_true", help="Disable Controller.") - # ROM parameters + # ROM parameters. soc_group.add_argument("--integrated-rom-size", default=0x20000, type=auto_int, help="Size/Enable the integrated (BIOS) ROM (Automatically resized to BIOS size when smaller).") soc_group.add_argument("--integrated-rom-init", default=None, type=str, help="Integrated ROM binary initialization file (override the BIOS when specified).") - # SRAM parameters + # SRAM parameters. soc_group.add_argument("--integrated-sram-size", default=0x2000, type=auto_int, help="Size/Enable the integrated SRAM.") - # MAIN_RAM parameters + # MAIN_RAM parameters. soc_group.add_argument("--integrated-main-ram-size", default=None, type=auto_int, help="size/enable the integrated main RAM.") - # CSR parameters + # CSR parameters. soc_group.add_argument("--csr-data-width", default=32 , type=auto_int, help="CSR bus data-width (8 or 32).") soc_group.add_argument("--csr-address-width", default=14, type=auto_int, help="CSR bus address-width.") soc_group.add_argument("--csr-paging", default=0x800, type=auto_int, help="CSR bus paging.") soc_group.add_argument("--csr-ordering", default="big", help="CSR registers ordering (big or little).") - # Identifier parameters + # Identifier parameters. soc_group.add_argument("--ident", default=None, type=str, help="SoC identifier.") soc_group.add_argument("--no-ident-version", action="store_true", help="Disable date/time in SoC identifier.") - # UART parameters + # UART parameters. soc_group.add_argument("--no-uart", action="store_true", help="Disable UART.") soc_group.add_argument("--uart-name", default="serial", type=str, help="UART type/name.") soc_group.add_argument("--uart-baudrate", default=115200, type=auto_int, help="UART baudrate.") soc_group.add_argument("--uart-fifo-depth", default=16, type=auto_int, help="UART FIFO depth.") - # UARTBone parameters + # UARTBone parameters. soc_group.add_argument("--with-uartbone", action="store_true", help="Enable UARTbone.") - # JTAGBone parameters + # JTAGBone parameters. soc_group.add_argument("--with-jtagbone", action="store_true", help="Enable Jtagbone support.") soc_group.add_argument("--jtagbone-chain", default=1, type=int, help="Jtagbone chain index.") - # Timer parameters + # Timer parameters. soc_group.add_argument("--no-timer", action="store_true", help="Disable Timer.") soc_group.add_argument("--timer-uptime", action="store_true", help="Add an uptime capability to Timer.") - # L2 Cache + # L2 Cache. soc_group.add_argument("--l2-size", default=8192, type=auto_int, help="L2 cache size.") def soc_core_argdict(args): @@ -408,7 +409,7 @@ def soc_core_argdict(args): r[a] = arg return r -# SoCMini --------------------------------------------------------------------------------------- +# SoCMini ------------------------------------------------------------------------------------------ class SoCMini(SoCCore): def __init__(self, *args, **kwargs): @@ -423,7 +424,7 @@ class SoCMini(SoCCore): SoCCore.__init__(self, *args, **kwargs) -# SoCMini arguments ----------------------------------------------------------------------------- +# SoCMini arguments -------------------------------------------------------------------------------- soc_mini_args = soc_core_args soc_mini_argdict = soc_core_argdict From 175aab73a835d777d1be99bc8679a124a1e55e35 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Tue, 2 Apr 2024 10:09:38 +0200 Subject: [PATCH 20/28] soc/SoC: Add init_ram method from init_rom, allowing initilization of any RAM of the SoC and switch init_rom to it. --- litex/soc/integration/soc.py | 53 ++++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 17 deletions(-) diff --git a/litex/soc/integration/soc.py b/litex/soc/integration/soc.py index 93ae9c297..7f9aae766 100644 --- a/litex/soc/integration/soc.py +++ b/litex/soc/integration/soc.py @@ -1061,27 +1061,46 @@ class SoC(LiteXModule, SoCCoreCompat): if contents != []: self.add_config(f"{name}_INIT", 1) + def init_ram(self, name, contents=[], auto_size=False): + # RAM Parameters. + ram = getattr(self, name) + ram_region = self.bus.regions[name] + ram_type = { + True : "ROM", + False : "RAM", + }["w" not in ram_region.mode] + + # Size Check. + if ram_region.size < 4*len(contents): + self.logger.error("Contents Size ({}) {} {} Size ({}).".format( + colorer(f"0x{4*len(contents):x}"), + colorer("exceeds", color="red"), + ram_type, + colorer(f"0x{ram_region.size:x}"), + )) + raise SoCError() + + # RAM Initialization. + self.logger.info("Initializing {} {} with contents (Size: {}).".format( + ram_type, + colorer(name), + colorer(f"0x{4*len(contents):x}"))) + ram.mem.init = contents + + # RAM Auto-Resize (Optional). + if auto_size and ("w" not in ram_region.mode): + self.logger.info("Auto-Resizing {} {} from {} to {}.".format( + ram_type, + colorer(name), + colorer(f"0x{ram_region.size:x}"), + colorer(f"0x{4*len(contents):x}"))) + ram.mem.depth = len(contents) + def add_rom(self, name, origin, size, contents=[], mode="rx"): self.add_ram(name, origin, size, contents, mode=mode) def init_rom(self, name, contents=[], auto_size=True): - self.logger.info("Initializing ROM {} with contents (Size: {}).".format( - colorer(name), - colorer(f"0x{4*len(contents):x}"))) - if self.bus.regions[name].size < 4*len(contents): - self.logger.error("Contents Size ({}) {} ROM Size ({}).".format( - colorer(f"0x{4*len(contents):x}"), - colorer("exceeds", color="red"), - colorer(f"0x{self.bus.regions[name].size:x}"), - )) - raise SoCError() - getattr(self, name).mem.init = contents - if auto_size and ("w" not in self.bus.regions[name].mode): - self.logger.info("Auto-Resizing ROM {} from {} to {}.".format( - colorer(name), - colorer(f"0x{self.bus.regions[name].size:x}"), - colorer(f"0x{4*len(contents):x}"))) - getattr(self, name).mem.depth = len(contents) + self.init_ram(name, contents, auto_size) def add_csr_bridge(self, name="csr", origin=None, register=False): csr_bridge_cls = { From ca04858b391eab791a1dfd818a2cb8d1d1dd9864 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Tue, 2 Apr 2024 10:16:43 +0200 Subject: [PATCH 21/28] integration/builder: Switch to SoC.init_rom directly and remove initialize_rom that is no longer used. --- litex/soc/integration/builder.py | 2 +- litex/soc/integration/soc_core.py | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/litex/soc/integration/builder.py b/litex/soc/integration/builder.py index d11e94bbb..fbfe7673a 100644 --- a/litex/soc/integration/builder.py +++ b/litex/soc/integration/builder.py @@ -331,7 +331,7 @@ class Builder: ) # Initialize SoC with with BIOS data. - self.soc.initialize_rom(bios_data) + self.soc.init_rom(name="rom", contents=bios_data) def build(self, **kwargs): # Pass Output Directory to Platform. diff --git a/litex/soc/integration/soc_core.py b/litex/soc/integration/soc_core.py index 38dc1f926..7e89c9c0d 100644 --- a/litex/soc/integration/soc_core.py +++ b/litex/soc/integration/soc_core.py @@ -271,9 +271,6 @@ class SoCCore(LiteXSoC): def add_csr(self, csr_name, csr_id=None, use_loc_if_exists=False): self.csr.add(csr_name, csr_id, use_loc_if_exists=use_loc_if_exists) - def initialize_rom(self, data): - self.init_rom(name="rom", contents=data) - def add_memory_region(self, name, origin, length, type="cached"): self.bus.add_region(name, SoCRegion(origin=origin, size=length, cached="cached" in type, From 06083c7863b0063c06df2b11b34b75c2a739a402 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Tue, 2 Apr 2024 10:21:35 +0200 Subject: [PATCH 22/28] soc/init_ram: Define and use contents_size. --- litex/soc/integration/soc.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/litex/soc/integration/soc.py b/litex/soc/integration/soc.py index 7f9aae766..b2a7cde44 100644 --- a/litex/soc/integration/soc.py +++ b/litex/soc/integration/soc.py @@ -1069,11 +1069,12 @@ class SoC(LiteXModule, SoCCoreCompat): True : "ROM", False : "RAM", }["w" not in ram_region.mode] + contents_size = 4*len(contents) # FIXME. # Size Check. - if ram_region.size < 4*len(contents): + if ram_region.size < contents_size: self.logger.error("Contents Size ({}) {} {} Size ({}).".format( - colorer(f"0x{4*len(contents):x}"), + colorer(f"0x{contents_size:x}"), colorer("exceeds", color="red"), ram_type, colorer(f"0x{ram_region.size:x}"), @@ -1084,7 +1085,7 @@ class SoC(LiteXModule, SoCCoreCompat): self.logger.info("Initializing {} {} with contents (Size: {}).".format( ram_type, colorer(name), - colorer(f"0x{4*len(contents):x}"))) + colorer(f"0x{contents_size:x}"))) ram.mem.init = contents # RAM Auto-Resize (Optional). @@ -1093,7 +1094,7 @@ class SoC(LiteXModule, SoCCoreCompat): ram_type, colorer(name), colorer(f"0x{ram_region.size:x}"), - colorer(f"0x{4*len(contents):x}"))) + colorer(f"0x{contents_size:x}"))) ram.mem.depth = len(contents) def add_rom(self, name, origin, size, contents=[], mode="rx"): From 31508ddfa43d1fe277050c1dc6a57a1d0ee545cd Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Tue, 2 Apr 2024 10:25:59 +0200 Subject: [PATCH 23/28] soc: Add separators for SoC Main Components. --- litex/soc/integration/soc.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/litex/soc/integration/soc.py b/litex/soc/integration/soc.py index b2a7cde44..dc3a4e49b 100644 --- a/litex/soc/integration/soc.py +++ b/litex/soc/integration/soc.py @@ -1027,6 +1027,8 @@ class SoC(LiteXModule, SoCCoreCompat): raise SoCError() # SoC Main Components -------------------------------------------------------------------------- + + # Add Controller ------------------------------------------------------------------------------- def add_controller(self, name="ctrl", **kwargs): self.check_if_exists(name) self.logger.info("Controller {} {}.".format( @@ -1034,6 +1036,7 @@ class SoC(LiteXModule, SoCCoreCompat): colorer("added", color="green"))) self.add_module(name=name, module=SoCController(**kwargs)) + # Add/Init RAM --------------------------------------------------------------------------------- def add_ram(self, name, origin, size, contents=[], mode="rwx"): ram_cls = { "wishbone": wishbone.SRAM, @@ -1097,12 +1100,14 @@ class SoC(LiteXModule, SoCCoreCompat): colorer(f"0x{contents_size:x}"))) ram.mem.depth = len(contents) + # Add/Init ROM --------------------------------------------------------------------------------- def add_rom(self, name, origin, size, contents=[], mode="rx"): self.add_ram(name, origin, size, contents, mode=mode) def init_rom(self, name, contents=[], auto_size=True): self.init_ram(name, contents, auto_size) + # Add CSR Bridge ------------------------------------------------------------------------------- def add_csr_bridge(self, name="csr", origin=None, register=False): csr_bridge_cls = { "wishbone": wishbone.Wishbone2CSR, @@ -1141,6 +1146,7 @@ class SoC(LiteXModule, SoCCoreCompat): self.add_config("CSR_DATA_WIDTH", self.csr.data_width) self.add_config("CSR_ALIGNMENT", self.csr.alignment) + # Add CPU -------------------------------------------------------------------------------------- def add_cpu(self, name="vexriscv", variant="standard", reset_address=None, cfu=None): from litex.soc.cores import cpu @@ -1284,6 +1290,7 @@ class SoC(LiteXModule, SoCCoreCompat): if hasattr(self.cpu, "nop"): self.add_config("CPU_NOP", self.cpu.nop) + # Add Timer ------------------------------------------------------------------------------------ def add_timer(self, name="timer0"): from litex.soc.cores.timer import Timer self.check_if_exists(name) From 38a8a171dd04d6c6a635709c651b098a94783902 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Tue, 2 Apr 2024 10:43:01 +0200 Subject: [PATCH 24/28] integration/builder: Replace soc_core's initialize_memory with optional "init_mems" method. Make sure to also attach Builder to SoC to allow easily get/use builder properties in init_mems method. --- litex/soc/integration/builder.py | 16 ++++++++---- litex/soc/integration/soc_core.py | 42 ------------------------------- 2 files changed, 11 insertions(+), 47 deletions(-) diff --git a/litex/soc/integration/builder.py b/litex/soc/integration/builder.py index fbfe7673a..0e01155ee 100644 --- a/litex/soc/integration/builder.py +++ b/litex/soc/integration/builder.py @@ -92,7 +92,9 @@ class Builder: # Documentation. generate_doc = False): - self.soc = soc + # SoC/Builder Attach. + self.soc = soc # Attach SoC to Builder. + self.soc.builder = self # Attach Builder to SoC. # Directories. self.output_dir = os.path.abspath(output_dir or os.path.join("build", soc.platform.name)) @@ -388,12 +390,16 @@ class Builder: self._prepare_rom_software() self._generate_rom_software(compile_bios=use_bios) - # Allow soc to override the memory initialisation. - self.soc.initialize_memory(self.software_dir, **kwargs) + # Initialize Memories. + # Allow User Design to optionally initialize Memories through SoC.init_ram/init_rom. + if hasattr(self.soc, "init_mems"): + self.soc.init_mems(**kwargs) # Initialize ROM. - if use_bios and self.soc.integrated_rom_size and not getattr(self.soc, "rom").mem.init: - self._initialize_rom_software() + if use_bios and self.soc.integrated_rom_size: + # Only initialize if not already initialized. + if not getattr(self.soc, "rom").mem.init: + self._initialize_rom_software() # Translate compile_gateware to run. if "run" not in kwargs: diff --git a/litex/soc/integration/soc_core.py b/litex/soc/integration/soc_core.py index 7e89c9c0d..34a430bfc 100644 --- a/litex/soc/integration/soc_core.py +++ b/litex/soc/integration/soc_core.py @@ -280,48 +280,6 @@ class SoCCore(LiteXSoC): def add_csr_region(self, name, origin, busword, obj): self.csr_regions[name] = SoCCSRRegion(origin, busword, obj) - def initialize_memory(self, software_dir, **kwargs): - """initialize_memory - The target SoC can implement this function to override the memory initialisation - during the build to load a program or data to main_ram and/or rom. - - Parameters - ---------- - software_dir : str - Builder software_dir where the soc libs and bios are built. - - kwargs - Builder kwargs for any additional context if required -. - Example: - - class MySoC(SoCCore): - def __init__(self, - ... - self.add_config("MAIN_RAM_INIT") # firmware is in ram - - def initialize_memory(self, software_dir, **kwargs): - if self.cpu_type is None: - return - - filename = os.path.join(software_dir, "firmware", "firmware.bin") - data = get_mem_data(filename, endianness=self.cpu.endianness) - self.init_rom(name="main_ram", contents=data, auto_size=False) - - def main(): - ... - - builder = Builder(soc, **parser.builder_argdict) - - # add custom firmware: compiled by connecting here and stored in initialize_memory() - src="firmware" - src_dir = os.path.join(os.path.abspath(os.path.dirname(__file__)), src) - builder.add_software_package(src, src_dir) - - builder.build(**parser.toolchain_argdict) - """ - pass - # SoCCore arguments -------------------------------------------------------------------------------- def soc_core_args(parser): From dc78c3f47b2edb0fd2e26410ebb213f0b76ef426 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Thu, 4 Apr 2024 13:02:17 +0200 Subject: [PATCH 25/28] soc/interconnect/stream/ClockDomainCrossing: Add a Buffer when same Clk Domains when buffered=True. --- litex/soc/interconnect/stream.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/litex/soc/interconnect/stream.py b/litex/soc/interconnect/stream.py index c7d521221..2a95d9baa 100644 --- a/litex/soc/interconnect/stream.py +++ b/litex/soc/interconnect/stream.py @@ -254,8 +254,16 @@ class ClockDomainCrossing(LiteXModule, DUID): # Same Clk Domains. if cd_from == cd_to: - # No adaptation. - self.comb += self.sink.connect(self.source) + if buffered: + # Add Buffer. + self.buffer = ClockDomainsRenamer(cd_from)(Buffer(layout)) + self.comb += [ + self.sink.connect(self.buffer.sink), + self.buffer.source.connect(self.source), + ] + else: + # No adaptation. + self.comb += self.sink.connect(self.source) # Different Clk Domains. else: if with_common_rst: From 06009c57a383f4847b8b31d257ee9dad03e45c42 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Fri, 5 Apr 2024 16:03:33 +0200 Subject: [PATCH 26/28] build/xilinx/common: Fix missing clk parameter on XilinxSDRTristateImpl. --- CHANGES.md | 1 + litex/build/xilinx/common.py | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 8f6b06604..ba03c7d2a 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -11,6 +11,7 @@ - litex_sim/serial2console : Fixed RX backpressure handling. - litedram/frontend/avalon : Fixed and cleaned-up. - litex_sim/video : Fixed pixel format to RGBA. + - build/xilinx/common : Fixed missing clk parameter on XilinxSDRTristateImpl. [> Added -------- diff --git a/litex/build/xilinx/common.py b/litex/build/xilinx/common.py index 6d7e1e435..d0d6bf0f6 100644 --- a/litex/build/xilinx/common.py +++ b/litex/build/xilinx/common.py @@ -141,9 +141,9 @@ class XilinxSDRTristateImpl(Module): _o = Signal() _oe_n = Signal() _i = Signal() - self.specials += SDROutput(o, _o) - self.specials += SDROutput(~oe, _oe_n) - self.specials += SDRInput(_i, i) + self.specials += SDROutput(o, _o, clk) + self.specials += SDROutput(~oe, _oe_n, clk) + self.specials += SDRInput(_i, i, clk) self.specials += Instance("IOBUF", io_IO = io, o_O = _i, From 3864615f6fbe299e12f0541702596543829ce807 Mon Sep 17 00:00:00 2001 From: Gwenhael Goavec-Merou Date: Sat, 6 Apr 2024 08:13:56 +0200 Subject: [PATCH 27/28] tools/litex_json2dts_linux.py: improved cpu_isa_extension attribute (fdc) and fixed kernel panic during rocket booting with linux --- litex/tools/litex_json2dts_linux.py | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/litex/tools/litex_json2dts_linux.py b/litex/tools/litex_json2dts_linux.py index 4620b5ac2..8d1c215fb 100755 --- a/litex/tools/litex_json2dts_linux.py +++ b/litex/tools/litex_json2dts_linux.py @@ -33,8 +33,25 @@ def generate_dts(d, initrd_start=None, initrd_size=None, initrd=None, root_devic cpu_name = d["constants"].get("config_cpu_name") cpu_arch = cpu_architectures[cpu_name] cpu_isa = d["constants"].get("config_cpu_isa", None) # kernel < 6.6.0 - cpu_isa_base = cpu_isa[:5] # kernel >= 6.6.0 - cpu_isa_extensions = "\"i\", \"m\", \"a\"" # kernel >= 6.6.0 + + # kernel >= 6.6.0 + cpu_isa_base = cpu_isa[:5] + cpu_isa_extensions = "\"i\"" # default + # Append with optionals + if "m" in cpu_isa[5:]: + cpu_isa_extensions += ", \"m\"" + if "a" in cpu_isa[5:]: + cpu_isa_extensions += ", \"a\"" + if "f" in cpu_isa[5:]: + cpu_isa_extensions += ", \"f\"" + if "d" in cpu_isa[5:]: + cpu_isa_extensions += ", \"d\"" + if "d" in cpu_isa[5:]: + cpu_isa_extensions += ", \"c\"" + # rocket specific extensions + if "rocket" in cpu_name: + cpu_isa_extensions += ", \"zicsr\", \"zifencei\", \"zihpm\"" + cpu_mmu = d["constants"].get("config_cpu_mmu", None) # Header --------------------------------------------------------------------------------------- From b8ca87ece5ba08ec8b4755323c8bad0f7a253cc2 Mon Sep 17 00:00:00 2001 From: Gwenhael Goavec-Merou Date: Thu, 11 Apr 2024 15:13:52 +0200 Subject: [PATCH 28/28] build/openocd: disabled 'poll off' because not supported by ECP5 --- litex/build/openocd.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/litex/build/openocd.py b/litex/build/openocd.py index 166fb2e26..c9160c51c 100644 --- a/litex/build/openocd.py +++ b/litex/build/openocd.py @@ -192,7 +192,7 @@ proc jtagstream_serve {tap port} { write_to_file("stream.cfg", cfg) script = "; ".join([ "init", - "poll off", + #"poll off", # FIXME: not supported for ECP5 "irscan {} {:d}".format(tap_name, ir), "jtagstream_serve {} {:d}".format(tap_name, port), "exit",