From 2318ff37d2023fa32844873fdc6525f7abd55e44 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Tue, 19 Dec 2023 10:08:40 +0100 Subject: [PATCH 01/78] setup.py: Improve indentation. --- setup.py | 54 +++++++++++++++++++++++++++--------------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/setup.py b/setup.py index 08af7085f..0a0f7a601 100755 --- a/setup.py +++ b/setup.py @@ -9,25 +9,25 @@ with open("README.md", "r") as fp: setup( - name="litex", - version="2023.08", - description="Python SoC/Core builder for building FPGA based systems.", - long_description=long_description, - long_description_content_type="text/markdown", - author="Florent Kermarrec", - author_email="florent@enjoy-digital.fr", - url="http://enjoy-digital.fr", - download_url="https://github.com/enjoy-digital/litex", - test_suite="test", - license="BSD", - python_requires="~=3.6", - install_requires=[ + name = "litex", + version = "2023.08", + description = "Python SoC/Core builder for building FPGA based systems.", + long_description = long_description, + long_description_content_type = "text/markdown", + author = "Florent Kermarrec", + author_email = "florent@enjoy-digital.fr", + url = "http://enjoy-digital.fr", + download_url = "https://github.com/enjoy-digital/litex", + test_suite = "test", + license = "BSD", + python_requires = "~=3.6", + install_requires = [ "migen", "packaging", "pyserial", "requests", ], - extras_require={ + extras_require = { "develop": [ "meson" "pexpect" @@ -35,23 +35,23 @@ setup( "requests" ] }, - packages=find_packages(exclude=("test*", "sim*", "doc*")), - include_package_data=True, - package_data={ + packages = find_packages(exclude=("test*", "sim*", "doc*")), + include_package_data = True, + package_data = { 'litex.soc.doc': ['static/*'] }, - platforms=["Any"], - keywords="HDL ASIC FPGA hardware design", - classifiers=[ - "Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)", - "Environment :: Console", - "Development Status :: 3 - Alpha", - "Intended Audience :: Developers", - "License :: OSI Approved :: BSD License", - "Operating System :: OS Independent", + platforms = ["Any"], + keywords = "HDL ASIC FPGA hardware design", + classifiers = [ + "Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)", + "Environment :: Console", + "Development Status :: 3 - Alpha", + "Intended Audience :: Developers", + "License :: OSI Approved :: BSD License", + "Operating System :: OS Independent", "Programming Language :: Python", ], - entry_points={ + entry_points = { "console_scripts": [ # Terminal/Server/Client. "litex_term = litex.tools.litex_term:main", From 0c3cda3ee823ef0877d2ccf3f48a6eb8e200376d Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Tue, 19 Dec 2023 10:09:44 +0100 Subject: [PATCH 02/78] CHANGES.md: Update. --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index b537e2812..61d175b20 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -36,6 +36,7 @@ - interconnect : Added 64-bit support to Wishbone/AXI-Lite/AXI. - jtag : Fixed firmware upload over JTAG-UART. - jtag : Improved speed (~X16) on JTABone/JTAGUART on all supported devices (Xilinx, Altera, Efinix, etc...) + - litesata/phy : Added GTHE4 support on Ultrascale+. [> Changed ---------- From 33c07a094e7bf257dc34f230c4e9667ea0da0275 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Tue, 19 Dec 2023 10:16:15 +0100 Subject: [PATCH 03/78] setup.py: Specify UTF-8 encoding for long_description/README.md. --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 0a0f7a601..696177dc5 100755 --- a/setup.py +++ b/setup.py @@ -4,7 +4,7 @@ from setuptools import setup from setuptools import find_packages -with open("README.md", "r") as fp: +with open("README.md", "r", encoding="utf-8") as fp: long_description = fp.read() From 048c42820c8b934d5dc60660eab075de009d8d4d Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Tue, 19 Dec 2023 10:32:12 +0100 Subject: [PATCH 04/78] setup.py: Switch minimum Python version to 3.7 (To allow more than 255 arguments in functions). --- CHANGES.md | 3 ++- setup.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 61d175b20..82b322eae 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -40,7 +40,8 @@ [> Changed ---------- - - build/osfpga: Removed initial support (would need feedbacks/updates). + - build/osfpga : Removed initial support (would need feedbacks/updates). + - python3 : Updated minimum python3 version to 3.7 (To allow more than 255 arguments in functions). [> 2023.08, released on September 14th 2023 ------------------------------------------- diff --git a/setup.py b/setup.py index 696177dc5..c1d57adea 100755 --- a/setup.py +++ b/setup.py @@ -20,7 +20,7 @@ setup( download_url = "https://github.com/enjoy-digital/litex", test_suite = "test", license = "BSD", - python_requires = "~=3.6", + python_requires = "~=3.7", install_requires = [ "migen", "packaging", From cd503bc9af28e92116b17f0ace49756ae5d4e984 Mon Sep 17 00:00:00 2001 From: Gwenhael Goavec-Merou Date: Tue, 19 Dec 2023 21:25:59 +0100 Subject: [PATCH 05/78] build/efinix/ifacewriter: Titanium PLL's feedback clock --- litex/build/efinix/ifacewriter.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/litex/build/efinix/ifacewriter.py b/litex/build/efinix/ifacewriter.py index be480cb26..325e49d55 100644 --- a/litex/build/efinix/ifacewriter.py +++ b/litex/build/efinix/ifacewriter.py @@ -281,7 +281,6 @@ design.create("{2}", "{3}", "./../gateware", overwrite=True) if block["version"] == "V3": cmd += 'design.gen_pll_ref_clock("{}", pll_res="{}", refclk_src="EXTERNAL", refclk_name="{}", ext_refclk_no="{}", ext_refclk_type="LVDS_RX")\n\n' \ .format(name, block["resource"], block["input_clock_pad"], block["clock_no"]) - cmd += 'design.set_property("{}","FEEDBACK_MODE","CORE","PLL")\n\n'.format(name) else: cmd += 'design.set_property("{}","EXT_CLK","EXT_CLK{}","PLL")\n'.format(name, block["clock_no"]) @@ -329,7 +328,14 @@ design.create("{2}", "{3}", "./../gateware", overwrite=True) else: cmd += 'design.set_property("{}","CLKOUT{}_PHASE_SETTING","{}","PLL")\n'.format(name, i, clock[2] // 45) - if block["feedback"] == -1: + # Titanium has always a feedback (local: CLK0, CORE: any output) + if block["version"] == "V3": + feedback_clk = block["feedback"] + cmd += 'design.set_property("{}", "FEEDBACK_MODE", "{}", "PLL")\n'.format(name, "LOCAL" if feedback_clk < 1 else "CORE") + cmd += 'design.set_property("{}", "FEEDBACK_CLK", "CLK{}", "PLL")\n'.format(name, 0 if feedback_clk < 1 else feedback_clk) + + # auto_calc_pll_clock is always working with Titanium and only working when feedback is unused for Trion + if block["feedback"] == -1 or block["version"] == "V3": cmd += "target_freq = {\n" for i, clock in enumerate(block["clk_out"]): cmd += ' "CLKOUT{}_FREQ": "{}",\n'.format(i, clock[1] / 1e6) @@ -358,7 +364,7 @@ design.create("{2}", "{3}", "./../gateware", overwrite=True) cmd += 'print("#### {} ####")\n'.format(name) cmd += 'clksrc_info = design.trace_ref_clock("{}", block_type="PLL")\n'.format(name) cmd += 'pprint.pprint(clksrc_info)\n' - cmd += 'clock_source_prop = ["REFCLK_SOURCE", "CORE_CLK_PIN", "EXT_CLK", "REFCLK_FREQ", "RESOURCE"]\n' + cmd += 'clock_source_prop = ["REFCLK_SOURCE", "CORE_CLK_PIN", "EXT_CLK", "REFCLK_FREQ", "RESOURCE", "FEEDBACK_MODE", "FEEDBACK_CLK"]\n' for i, clock in enumerate(block["clk_out"]): cmd += 'clock_source_prop += ["CLKOUT{}_FREQ", "CLKOUT{}_PHASE", "CLKOUT{}_EN"]\n'.format(i, i, i) cmd += 'prop_map = design.get_property("{}", clock_source_prop, block_type="PLL")\n'.format(name) From fadea1d31bc7dc3cf5cf6030f44ee6ec61491976 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Wed, 20 Dec 2023 08:08:42 +0100 Subject: [PATCH 06/78] CHANGES.md: Update. --- CHANGES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 82b322eae..2b0affab0 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -30,7 +30,7 @@ - litepcie : Simplify/Cleanup Ultrascale(+) integration and allow .xci generation from .tcl. - litepcie : Initial 64-bit DMA suppport. - bios : Added bios_format / --bios-format to allow enabling float/double printf. - - soc/cores/clock : Added proper clock feedback support on Efinix TRIONPLL. + - soc/cores/clock : Added proper clock feedback support on Efinix TRIONPLL/TITANIUMPLL. - liteiclink/phy : Added Efinix support/examples on Trion/Titanium. - liteiclink/serwb : Reused Etherbone from LiteEth to avoid code duplication. - interconnect : Added 64-bit support to Wishbone/AXI-Lite/AXI. From 4721029e58311cb9eaee72a2f5861f34f157c03a Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Wed, 20 Dec 2023 15:25:14 +0100 Subject: [PATCH 07/78] CHANGES.md: Update. --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index 2b0affab0..6d76c8bca 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -37,6 +37,7 @@ - jtag : Fixed firmware upload over JTAG-UART. - jtag : Improved speed (~X16) on JTABone/JTAGUART on all supported devices (Xilinx, Altera, Efinix, etc...) - litesata/phy : Added GTHE4 support on Ultrascale+. + - litex_boards : Added Machdyne's Mozart with the Sechzig ML1 module support. [> Changed ---------- From 23fbd1b334b715b92464687696c0a9cd7e730427 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Wed, 20 Dec 2023 16:10:03 +0100 Subject: [PATCH 08/78] CHANGES.md: Update. --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index 6d76c8bca..b20791b09 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -38,6 +38,7 @@ - jtag : Improved speed (~X16) on JTABone/JTAGUART on all supported devices (Xilinx, Altera, Efinix, etc...) - litesata/phy : Added GTHE4 support on Ultrascale+. - litex_boards : Added Machdyne's Mozart with the Sechzig ML1 module support. + - liteiclink : Added clk_ratio of 1:2, 1:4 on Efinix/SerWB to allow make clocking more flexible. [> Changed ---------- From 040b5540220889affb3b0d8482a4754322db3b51 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Wed, 20 Dec 2023 16:11:12 +0100 Subject: [PATCH 09/78] CHANGES.md: Update. --- CHANGES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index b20791b09..764da9aec 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -38,7 +38,7 @@ - jtag : Improved speed (~X16) on JTABone/JTAGUART on all supported devices (Xilinx, Altera, Efinix, etc...) - litesata/phy : Added GTHE4 support on Ultrascale+. - litex_boards : Added Machdyne's Mozart with the Sechzig ML1 module support. - - liteiclink : Added clk_ratio of 1:2, 1:4 on Efinix/SerWB to allow make clocking more flexible. + - liteiclink : Added clk_ratio of 1:2, 1:4 on Efinix/SerWB to make clocking more flexible. [> Changed ---------- From 7d5de90a247be3a32cba56178b81f5246d5e4410 Mon Sep 17 00:00:00 2001 From: Gwenhael Goavec-Merou Date: Wed, 20 Dec 2023 20:28:51 +0100 Subject: [PATCH 10/78] soc/cores/clock/efinix: remove 2 output clocks limit, reset o_div_max when a nex vco_max_freq is found --- litex/soc/cores/clock/efinix.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/litex/soc/cores/clock/efinix.py b/litex/soc/cores/clock/efinix.py index ba803c741..d71197107 100644 --- a/litex/soc/cores/clock/efinix.py +++ b/litex/soc/cores/clock/efinix.py @@ -240,23 +240,24 @@ class EFINIXPLL(LiteXModule): # no solution found for this clk: params are uncompatibles if found == False: break - if len(cx_list) == 2: - params_list.append([n, m, o, c, cx_list[0], cx_list[1]]) + if len(cx_list) == n_out: + params_list.append([n, m, o, c, cx_list]) vco_max_freq = 0 o_div_max = 0 params_list2 = [] for p in params_list: - (n, m, o, c, c0, c1) = p + (n, m, o, c, cx_list) = p fpfd_tmp = clk_in_freq / n fvco_tmp = fpfd_tmp * m * o * c - if o > o_div_max: - o_div_max = o # Interface designer always select high VCO freq if fvco_tmp > vco_max_freq: vco_max_freq = fvco_tmp params_list2.clear() + o_div_max = 0 fpll_tmp = fvco_tmp / o if fvco_tmp == vco_max_freq: + if o > o_div_max: + o_div_max = o params_list2.append({ "fvco" : fvco_tmp, "fpll" : fpll_tmp, @@ -265,8 +266,7 @@ class EFINIXPLL(LiteXModule): "N" : n, "O" : o, "Cfbk" : c, - "c0" : c0, - "c1" : c1, + **{f"c{n}" : cx_list[n] for n in range(n_out)}, }) # Again: Interface Designer prefers high O divider. From 54c58ef8b9caa6b8c1a6ad9710793b9bec804994 Mon Sep 17 00:00:00 2001 From: Gwenhael Goavec-Merou Date: Wed, 20 Dec 2023 20:29:10 +0100 Subject: [PATCH 11/78] build/efinix/ifacewriter: reorder FEEDBACK for Trion devices. --- litex/build/efinix/ifacewriter.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/litex/build/efinix/ifacewriter.py b/litex/build/efinix/ifacewriter.py index 325e49d55..dbeedc088 100644 --- a/litex/build/efinix/ifacewriter.py +++ b/litex/build/efinix/ifacewriter.py @@ -284,11 +284,6 @@ design.create("{2}", "{3}", "./../gateware", overwrite=True) else: cmd += 'design.set_property("{}","EXT_CLK","EXT_CLK{}","PLL")\n'.format(name, block["clock_no"]) - if block["feedback"] != -1: - cmd += 'design.set_property("{}","FEEDBACK_MODE","{}","PLL")\n'.format(name, "CORE" if block["feedback"] == 0 else "LOCAL") - cmd += 'design.set_property("{}","FEEDBACK_CLK","CLK{}","PLL")\n'.format(name, block["feedback"]) - else: - cmd += 'design.set_property("{}","FEEDBACK_MODE","INTERNAL","PLL")\n'.format(name) cmd += 'design.assign_resource("{}","{}","PLL")\n'.format(name, block["resource"]) @@ -344,6 +339,9 @@ design.create("{2}", "{3}", "./../gateware", overwrite=True) cmd += ' "CLKOUT{}_DYNPHASE_EN": "1",\n'.format(i) cmd += "}\n" + if block["version"] == "V1_V2": + cmd += 'design.set_property("{}","FEEDBACK_MODE","INTERNAL","PLL")\n'.format(name) + cmd += 'calc_result = design.auto_calc_pll_clock("{}", target_freq)\n'.format(name) cmd += 'for c in calc_result:\n' cmd += ' print(c)\n' @@ -355,6 +353,8 @@ design.create("{2}", "{3}", "./../gateware", overwrite=True) cmd += 'design.set_property("{}","CLKOUT{}_PHASE","{}","PLL")\n'.format(name, i, clock[2]) #cmd += 'design.set_property("{}","CLKOUT{}_FREQ","{}","PLL")\n'.format(name, i, clock[2]) cmd += 'design.set_property("{}","CLKOUT{}_DIV","{}","PLL")\n'.format(name, i, block[f"CLKOUT{i}_DIV"]) + cmd += 'design.set_property("{}","FEEDBACK_MODE","{}","PLL")\n'.format(name, "LOCAL" if block["feedback"] == 0 else "CORE") + cmd += 'design.set_property("{}","FEEDBACK_CLK","CLK{}","PLL")\n'.format(name, block["feedback"]) if "extra" in block: cmd += block["extra"] From 7062e3379fdd80ac0523390ca46c87906b8c68ff Mon Sep 17 00:00:00 2001 From: Gwenhael Goavec-Merou Date: Wed, 20 Dec 2023 20:33:15 +0100 Subject: [PATCH 12/78] build/efinix/ifacewriter: bypass clks out frequency check for Trion when a feedback clock is used --- litex/build/efinix/ifacewriter.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/litex/build/efinix/ifacewriter.py b/litex/build/efinix/ifacewriter.py index dbeedc088..5ec2a3b88 100644 --- a/litex/build/efinix/ifacewriter.py +++ b/litex/build/efinix/ifacewriter.py @@ -370,11 +370,13 @@ design.create("{2}", "{3}", "./../gateware", overwrite=True) cmd += 'prop_map = design.get_property("{}", clock_source_prop, block_type="PLL")\n'.format(name) cmd += 'pprint.pprint(prop_map)\n' - for i, clock in enumerate(block["clk_out"]): - cmd += '\nfreq = float(prop_map["CLKOUT{}_FREQ"])\n'.format(i) - cmd += 'if freq != {}:\n'.format(clock[1]/1e6) - cmd += ' print("ERROR: CLKOUT{} configured for {}MHz is {{}}MHz".format(freq))\n'.format(i, clock[1]/1e6) - cmd += ' exit("PLL ERROR")\n' + # Efinix python API is buggy for Trion devices when a feedback is defined... + if block["version"] == "V3" or (block["version"] == "V1_V2" and block["feedback"] == -1): + for i, clock in enumerate(block["clk_out"]): + cmd += '\nfreq = float(prop_map["CLKOUT{}_FREQ"])\n'.format(i) + cmd += 'if freq != {}:\n'.format(clock[1]/1e6) + cmd += ' print("ERROR: CLKOUT{} configured for {}MHz is {{}}MHz".format(freq))\n'.format(i, clock[1]/1e6) + cmd += ' exit("PLL ERROR")\n' cmd += "\n#---------- END PLL {} ---------\n\n".format(name) return cmd From 67cfcadf7933ec6a6e75735e340c153fe4ca8480 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Mon, 25 Dec 2023 15:36:10 +0100 Subject: [PATCH 13/78] setup.py/CHANGES.md: Prepare 2023.12 release. --- CHANGES.md | 4 ++-- setup.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 764da9aec..2d1d09728 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,5 @@ -[> Changes since 2023.08 ------------------------- +[> 2023.12, released on December 25th 2023 +------------------------------------------ [> Fixed -------- - liteeth/arp : Fixed response on table update. diff --git a/setup.py b/setup.py index c1d57adea..ab33e6b9a 100755 --- a/setup.py +++ b/setup.py @@ -10,7 +10,7 @@ with open("README.md", "r", encoding="utf-8") as fp: setup( name = "litex", - version = "2023.08", + version = "2023.12", description = "Python SoC/Core builder for building FPGA based systems.", long_description = long_description, long_description_content_type = "text/markdown", From 68cfb6eea04a8296f6ac38d6b2c94ca77dd15d42 Mon Sep 17 00:00:00 2001 From: Tim Paine <3105306+timkpaine@users.noreply.github.com> Date: Thu, 28 Dec 2023 15:49:31 -0500 Subject: [PATCH 14/78] Fix classifiers to satisfy format checks --- setup.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/setup.py b/setup.py index ab33e6b9a..a52575a62 100755 --- a/setup.py +++ b/setup.py @@ -43,12 +43,12 @@ setup( platforms = ["Any"], keywords = "HDL ASIC FPGA hardware design", classifiers = [ - "Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)", - "Environment :: Console", - "Development Status :: 3 - Alpha", - "Intended Audience :: Developers", - "License :: OSI Approved :: BSD License", - "Operating System :: OS Independent", + "Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)", + "Environment :: Console", + "Development Status :: 3 - Alpha", + "Intended Audience :: Developers", + "License :: OSI Approved :: BSD License", + "Operating System :: OS Independent", "Programming Language :: Python", ], entry_points = { From acf07a21c96cd2fc10dd53151af4a645e42c44bb Mon Sep 17 00:00:00 2001 From: gsomlo Date: Mon, 1 Jan 2024 13:32:40 -0500 Subject: [PATCH 15/78] soc: fix typo in cpu mem_bus axi-via-wb downconvert (#1865) Fixes: 002aad7a4 Signed-off-by: Gabriel Somlo --- litex/soc/integration/soc.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/litex/soc/integration/soc.py b/litex/soc/integration/soc.py index 17fe98f79..dbce3a988 100644 --- a/litex/soc/integration/soc.py +++ b/litex/soc/integration/soc.py @@ -1651,9 +1651,9 @@ class LiteXSoC(SoC): else: mem_wb = wishbone.Interface( data_width = self.cpu.mem_axi.data_width, - adr_width = 32-log2_int(mem_bus.data_width//8, + adr_width = 32-log2_int(mem_bus.data_width//8), addressing = "word", - )) + ) mem_a2w = axi.AXI2Wishbone( axi = mem_bus, wishbone = mem_wb, From 3909b1d6117231d420ddeeab12567c96ba5cec79 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Tue, 2 Jan 2024 13:43:48 +0100 Subject: [PATCH 16/78] build/openfpgaloader: Add kwargs support to flash method and some comments. --- litex/build/openfpgaloader.py | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/litex/build/openfpgaloader.py b/litex/build/openfpgaloader.py index c6f38ae38..8721dcfb9 100644 --- a/litex/build/openfpgaloader.py +++ b/litex/build/openfpgaloader.py @@ -13,31 +13,62 @@ class OpenFPGALoader(GenericProgrammer): needs_bitreverse = False def __init__(self, board="", cable="", freq=0, fpga_part="", index_chain=None): + # openFPGALoader base command. self.cmd = ["openFPGALoader"] + + # Specify FPGA board. if board: self.cmd += ["--board", board] + + # Specify FPGA part/device. if fpga_part: self.cmd += ["--fpga-part", fpga_part] + + # Specify programmation cable. if cable: self.cmd += ["--cable", cable] + + # Specify programmation frequency. if freq: self.cmd += ["--freq", str(int(float(freq)))] + + # Specify index in the JTAG chain. if index_chain is not None: self.cmd += ["--index-chain", str(int(index_chain))] def load_bitstream(self, bitstream_file): + # Load base command. cmd = self.cmd + ["--bitstream", bitstream_file] + + # Execute command. self.call(cmd) - def flash(self, address, data_file, external=False, unprotect_flash=False, verify=False): + def flash(self, address, data_file, external=False, unprotect_flash=False, verify=False, **kwargs): + # Flash base command. cmd = self.cmd + ["--write-flash", "--bitstream", data_file] + + # Flash Internal/External selection. if external: cmd += ["--external-flash"] + + # Flash Offset. if address: cmd += ["--offset"] cmd += [str(address)] + + # Flash Unprotect. if unprotect_flash: cmd += ["--unprotect-flash"] + + # Flash Verify. if verify: cmd += ["--verify"] + + # Handle kwargs for specific, less common cases. + for key, value in kwargs.items(): + cmd.append(f"--{key}") + if value is not None: + cmd.append(str(value)) + + # Execute Command. self.call(cmd) From 456dda050cbf0eb8417670a2912c0487d27beb75 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Wed, 3 Jan 2024 19:07:55 +0100 Subject: [PATCH 17/78] cpu/gowin_emcu: Cleanup/Simplify. --- litex/soc/cores/cpu/gowin_emcu/core.py | 144 +++++++++++++------------ 1 file changed, 76 insertions(+), 68 deletions(-) diff --git a/litex/soc/cores/cpu/gowin_emcu/core.py b/litex/soc/cores/cpu/gowin_emcu/core.py index c8551b21c..dddf86e23 100644 --- a/litex/soc/cores/cpu/gowin_emcu/core.py +++ b/litex/soc/cores/cpu/gowin_emcu/core.py @@ -2,6 +2,7 @@ # This file is part of LiteX. # # Copyright (c) 2021 Ilia Sergachev +# Copyright (c) 2024 Florent Kermarrec # SPDX-License-Identifier: BSD-2-Clause from migen import * @@ -11,42 +12,6 @@ from litex.gen import * from litex.soc.interconnect import wishbone, ahb from litex.soc.cores.cpu import CPU -# AHB Flash ---------------------------------------------------------------------------------------- - -class AHBFlash(LiteXModule): - def __init__(self, bus): - addr = Signal(13) - read = Signal() - self.comb += bus.resp.eq(0) - - self.fsm = fsm = FSM() - fsm.act("IDLE", - bus.readyout.eq(1), - If(bus.sel & bus.trans[1], - NextValue(addr, bus.addr[2:]), - NextState("READ"), - ) - ) - fsm.act("READ", - read.eq(1), - NextState("WAIT"), - ) - fsm.act("WAIT", - NextState("IDLE") - ) - self.specials += Instance("FLASH256K", - o_DOUT = bus.rdata, - i_DIN = Signal(32), - i_XADR = addr[6:], - i_YADR = addr[:6], - i_XE = ~ResetSignal("sys"), - i_YE = ~ResetSignal("sys"), - i_SE = read, - i_PROG = 0, - i_ERASE = 0, - i_NVSTR = 0 - ) - # Gowin EMCU --------------------------------------------------------------------------------------- class GowinEMCU(CPU): @@ -64,7 +29,7 @@ class GowinEMCU(CPU): io_regions = { # Origin, Length. 0x4000_0000: 0x2000_0000, - 0xA000_0000: 0x6000_0000 + 0xa000_0000: 0x6000_0000 } @property @@ -78,45 +43,50 @@ class GowinEMCU(CPU): def __init__(self, platform, variant, *args, **kwargs): super().__init__(*args, **kwargs) - - self.reset = Signal() - self.bus_reset = Signal() - bus_reset_n = Signal() - self.comb += self.bus_reset.eq(~bus_reset_n) + self.reset = Signal() self.interrupt = Signal(5) self.reset_address = self.mem_map["rom"] + 0 + self.periph_buses = [] - self.gpio_in = Signal(16) - self.gpio_out = Signal(16) - self.gpio_out_en = Signal(16) + # CPU Instance. + # ------------- + bus_reset_n = Signal() self.cpu_params = dict() self.cpu_params.update( - i_MTXREMAP = Signal(4, reset=0b1111), - o_MTXHRESETN = bus_reset_n, - - i_FLASHERR = Signal(), - i_FLASHINT = Signal(), - + # Clk/Rst. i_FCLK = ClockSignal("sys"), i_PORESETN = ~self.reset, i_SYSRESETN = ~self.reset, - i_RTCSRCCLK = Signal(), # TODO - RTC clk in + i_MTXREMAP = Signal(4, reset=0b1111), + o_MTXHRESETN = bus_reset_n, - i_IOEXPINPUTI = self.gpio_in, - o_IOEXPOUTPUTO = self.gpio_out, - o_IOEXPOUTPUTENO = self.gpio_out_en, + # RTC. + i_RTCSRCCLK = Signal(), # TODO: RTC Clk In. + # GPIOs. + i_IOEXPINPUTI = Signal(), # TODO: GPIO Input (16-bit). + o_IOEXPOUTPUTO = Signal(), # TODO: GPIO Output (16-bit). + o_IOEXPOUTPUTENO = Signal(), # TODO: GPIO Output Enable (16-bit). + + # Interrupts. i_GPINT = self.interrupt, o_INTMONITOR = Signal(), + + # Flash. + i_FLASHERR = Signal(), + i_FLASHINT = Signal(), ) - # 32b CPU SRAM split between 8 SRAMs x 4 bit each + # SRAM (32-bit RAM split between 8 SRAMs x 4 bit each). + # ----------------------------------------------------- + # Parameters. sram_dw = 32 single_sram_dw = 4 - n_srams = sram_dw // single_sram_dw + nsrams = sram_dw // single_sram_dw + # CPU SRAM Interface. sram0_addr = Signal(13) sram0_rdata = Signal(sram_dw) sram0_wdata = Signal(sram_dw) @@ -130,7 +100,8 @@ class GowinEMCU(CPU): o_SRAM0CS = sram0_cs, ) - for i in range(n_srams): + # SRAMS Instances. + for i in range(nsrams): self.specials += Instance("SDPB", p_READ_MODE = 0, p_BIT_WIDTH_0 = single_sram_dw, @@ -144,16 +115,51 @@ class GowinEMCU(CPU): i_ADB = Cat(Signal(2), sram0_addr[:-1]), i_CEA = sram0_wren[i // 2], i_CEB = ~sram0_wren[i // 2], - i_CLKA = ClockSignal(), - i_CLKB = ClockSignal(), + i_CLKA = ClockSignal("sys"), + i_CLKB = ClockSignal("sys"), i_RESETA = 0, - i_RESETB = self.bus_reset, + i_RESETB = ~bus_reset_n, i_OCE = 1, i_BLKSELA = Cat(sram0_cs, sram0_cs, sram0_cs), i_BLKSELB = Cat(sram0_cs, sram0_cs, sram0_cs), ) - # Boot Flash memory connected via AHB + # Flash (Boot Flash memory connected via AHB). + # -------------------------------------------- + + class AHBFlash(LiteXModule): + def __init__(self, bus): + addr = Signal(13) + read = Signal() + self.comb += bus.resp.eq(0) + + self.fsm = fsm = FSM() + fsm.act("IDLE", + bus.readyout.eq(1), + If(bus.sel & bus.trans[1], + NextValue(addr, bus.addr[2:]), + NextState("READ"), + ) + ) + fsm.act("READ", + read.eq(1), + NextState("WAIT"), + ) + fsm.act("WAIT", + NextState("IDLE") + ) + self.specials += Instance("FLASH256K", + o_DOUT = bus.rdata, + i_DIN = Signal(32), + i_XADR = addr[6:], + i_YADR = addr[:6], + i_XE = ~ResetSignal("sys"), + i_YE = ~ResetSignal("sys"), + i_SE = read, + i_PROG = 0, + i_ERASE = 0, + i_NVSTR = 0 + ) ahb_flash = ahb.Interface() for s, _ in ahb_flash.master_signals: @@ -163,26 +169,28 @@ class GowinEMCU(CPU): for s, _ in ahb_flash.slave_signals: self.cpu_params[f"i_TARGFLASH0H{s.upper()}"] = getattr(ahb_flash, s) flash = ResetInserter()(AHBFlash(ahb_flash)) - self.comb += flash.reset.eq(self.bus_reset) + self.comb += flash.reset.eq(~bus_reset_n) self.submodules += flash - # Extension AHB -> Wishbone CSR via bridge + + # Peripheral Bus (AHB -> Wishbone). + # --------------------------------- self.pbus = wishbone.Interface(data_width=32, adr_width=30, addressing="word") - self.periph_buses = [self.pbus] ahb_targexp0 = ahb.Interface() for s, _ in ahb_targexp0.master_signals: self.cpu_params[f"o_TARGEXP0H{s.upper()}"] = getattr(ahb_targexp0, s) for s, _ in ahb_targexp0.slave_signals: self.cpu_params[f"i_TARGEXP0H{s.upper()}"] = getattr(ahb_targexp0, s) self.submodules += ahb.AHB2Wishbone(ahb_targexp0, self.pbus) + self.periph_buses.append(self.pbus) def connect_uart(self, pads, n=0): assert n in (0, 1), "this CPU has 2 built-in UARTs, 0 and 1" self.cpu_params.update({ - f"i_UART{n}RXDI": pads.rx, - f"o_UART{n}TXDO": pads.tx, - f"o_UART{n}BAUDTICK": Signal() + f"i_UART{n}RXDI" : pads.rx, + f"o_UART{n}TXDO" : pads.tx, + f"o_UART{n}BAUDTICK" : Signal() }) def connect_jtag(self, pads): From 3f9de470f6d647ef6c6f821293ce4152cdaca6b7 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Wed, 3 Jan 2024 19:15:46 +0100 Subject: [PATCH 18/78] cpu/gowin_emcu: Add gcc_flags method and set UART_POLLING in it. --- litex/soc/cores/cpu/gowin_emcu/core.py | 9 ++++++++- litex/soc/cores/cpu/gowin_emcu/system.h | 1 - 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/litex/soc/cores/cpu/gowin_emcu/core.py b/litex/soc/cores/cpu/gowin_emcu/core.py index dddf86e23..5046f01a2 100644 --- a/litex/soc/cores/cpu/gowin_emcu/core.py +++ b/litex/soc/cores/cpu/gowin_emcu/core.py @@ -23,7 +23,6 @@ class GowinEMCU(CPU): data_width = 32 endianness = "little" gcc_triple = "arm-none-eabi" - gcc_flags = "-mcpu=cortex-m3 -mthumb" linker_output_format = "elf32-littlearm" nop = "nop" io_regions = { @@ -32,6 +31,7 @@ class GowinEMCU(CPU): 0xa000_0000: 0x6000_0000 } + # Memory Mapping. @property def mem_map(self): return { @@ -41,6 +41,13 @@ class GowinEMCU(CPU): "csr" : 0xa000_0000, } + # GCC Flags. + @property + def gcc_flags(self): + flags = f" -mcpu=cortex-m3 -mthumb" + flags += f" -DUART_POLLING" + return flags + def __init__(self, platform, variant, *args, **kwargs): super().__init__(*args, **kwargs) self.reset = Signal() diff --git a/litex/soc/cores/cpu/gowin_emcu/system.h b/litex/soc/cores/cpu/gowin_emcu/system.h index 2fc3a77d1..1e0b33aab 100644 --- a/litex/soc/cores/cpu/gowin_emcu/system.h +++ b/litex/soc/cores/cpu/gowin_emcu/system.h @@ -16,7 +16,6 @@ void busy_wait_us(unsigned int us); // FIXME #define CSR_UART_BASE -#define UART_POLLING struct EMCU_UART { From 85ef3bd8a79a2d5186e923361a3a237d0d507288 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Wed, 3 Jan 2024 19:41:03 +0100 Subject: [PATCH 19/78] cpu/gowin_emcu: Add missing reset signals. --- litex/soc/cores/cpu/gowin_emcu/core.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/litex/soc/cores/cpu/gowin_emcu/core.py b/litex/soc/cores/cpu/gowin_emcu/core.py index 5046f01a2..4a9dcdb6f 100644 --- a/litex/soc/cores/cpu/gowin_emcu/core.py +++ b/litex/soc/cores/cpu/gowin_emcu/core.py @@ -63,8 +63,8 @@ class GowinEMCU(CPU): self.cpu_params.update( # Clk/Rst. i_FCLK = ClockSignal("sys"), - i_PORESETN = ~self.reset, - i_SYSRESETN = ~self.reset, + i_PORESETN = ~ResetSignal("sys") & ~self.reset, + i_SYSRESETN = ~ResetSignal("sys") & ~self.reset, i_MTXREMAP = Signal(4, reset=0b1111), o_MTXHRESETN = bus_reset_n, @@ -124,7 +124,7 @@ class GowinEMCU(CPU): i_CEB = ~sram0_wren[i // 2], i_CLKA = ClockSignal("sys"), i_CLKB = ClockSignal("sys"), - i_RESETA = 0, + i_RESETA = ~bus_reset_n, i_RESETB = ~bus_reset_n, i_OCE = 1, i_BLKSELA = Cat(sram0_cs, sram0_cs, sram0_cs), From 6d3c955d59e564a8fcac281da8a5cc5bd5f419b3 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Thu, 4 Jan 2024 08:57:25 +0100 Subject: [PATCH 20/78] cpu/gowin_emcu: Increase similarities with cortex_m3 (since gowin_emcu is a Cortex M3). --- litex/soc/cores/cpu/cortex_m3/core.py | 2 -- litex/soc/cores/cpu/gowin_emcu/core.py | 34 ++++++++++++------------- litex/soc/cores/cpu/gowin_emcu/system.h | 4 +-- 3 files changed, 19 insertions(+), 21 deletions(-) diff --git a/litex/soc/cores/cpu/cortex_m3/core.py b/litex/soc/cores/cpu/cortex_m3/core.py index b2a852afc..c1f88908a 100644 --- a/litex/soc/cores/cpu/cortex_m3/core.py +++ b/litex/soc/cores/cpu/cortex_m3/core.py @@ -5,8 +5,6 @@ # Copyright (c) 2022 Florent Kermarrec # SPDX-License-Identifier: BSD-2-Clause -import os - from migen import * from litex.gen import * diff --git a/litex/soc/cores/cpu/gowin_emcu/core.py b/litex/soc/cores/cpu/gowin_emcu/core.py index 4a9dcdb6f..0494befc7 100644 --- a/litex/soc/cores/cpu/gowin_emcu/core.py +++ b/litex/soc/cores/cpu/gowin_emcu/core.py @@ -9,8 +9,8 @@ from migen import * from litex.gen import * -from litex.soc.interconnect import wishbone, ahb from litex.soc.cores.cpu import CPU +from litex.soc.interconnect import wishbone, ahb # Gowin EMCU --------------------------------------------------------------------------------------- @@ -22,38 +22,41 @@ class GowinEMCU(CPU): human_name = "Gowin EMCU" data_width = 32 endianness = "little" + reset_address = 0x0000_0000 gcc_triple = "arm-none-eabi" linker_output_format = "elf32-littlearm" nop = "nop" io_regions = { # Origin, Length. - 0x4000_0000: 0x2000_0000, - 0xa000_0000: 0x6000_0000 + 0x4000_0000 : 0x2000_0000, + 0xa000_0000 : 0x6000_0000, } # Memory Mapping. @property def mem_map(self): return { - "rom" : 0x0000_0000, - "sram" : 0x2000_0000, - "peripherals" : 0x4000_0000, - "csr" : 0xa000_0000, + "rom" : 0x0000_0000, + "sram" : 0x2000_0000, + "main_ram" : 0x1000_0000, + "csr" : 0xa000_0000, } # GCC Flags. @property def gcc_flags(self): - flags = f" -mcpu=cortex-m3 -mthumb" + flags = f" -march=armv7-m -mthumb" + flags += f" -D__CortexM3__" flags += f" -DUART_POLLING" return flags - def __init__(self, platform, variant, *args, **kwargs): - super().__init__(*args, **kwargs) + def __init__(self, platform, variant="standard"): + self.platform = platform self.reset = Signal() self.interrupt = Signal(5) - self.reset_address = self.mem_map["rom"] + 0 - self.periph_buses = [] + self.pbus = wishbone.Interface(data_width=32, adr_width=30, addressing="word") + self.periph_buses = [self.pbus] + self.memory_buses = [] # CPU Instance. # ------------- @@ -63,8 +66,8 @@ class GowinEMCU(CPU): self.cpu_params.update( # Clk/Rst. i_FCLK = ClockSignal("sys"), - i_PORESETN = ~ResetSignal("sys") & ~self.reset, - i_SYSRESETN = ~ResetSignal("sys") & ~self.reset, + i_PORESETN = ~ (ResetSignal("sys") | self.reset), + i_SYSRESETN = ~ (ResetSignal("sys") | self.reset), i_MTXREMAP = Signal(4, reset=0b1111), o_MTXHRESETN = bus_reset_n, @@ -182,15 +185,12 @@ class GowinEMCU(CPU): # Peripheral Bus (AHB -> Wishbone). # --------------------------------- - - self.pbus = wishbone.Interface(data_width=32, adr_width=30, addressing="word") ahb_targexp0 = ahb.Interface() for s, _ in ahb_targexp0.master_signals: self.cpu_params[f"o_TARGEXP0H{s.upper()}"] = getattr(ahb_targexp0, s) for s, _ in ahb_targexp0.slave_signals: self.cpu_params[f"i_TARGEXP0H{s.upper()}"] = getattr(ahb_targexp0, s) self.submodules += ahb.AHB2Wishbone(ahb_targexp0, self.pbus) - self.periph_buses.append(self.pbus) def connect_uart(self, pads, n=0): assert n in (0, 1), "this CPU has 2 built-in UARTs, 0 and 1" diff --git a/litex/soc/cores/cpu/gowin_emcu/system.h b/litex/soc/cores/cpu/gowin_emcu/system.h index 1e0b33aab..c7a14e816 100644 --- a/litex/soc/cores/cpu/gowin_emcu/system.h +++ b/litex/soc/cores/cpu/gowin_emcu/system.h @@ -5,8 +5,8 @@ extern "C" { #endif -__attribute__((unused)) static void flush_cpu_icache(void){}; -__attribute__((unused)) static void flush_cpu_dcache(void){}; +__attribute__((unused)) static void flush_cpu_icache(void){}; /* No instruction cache */ +__attribute__((unused)) static void flush_cpu_dcache(void){}; /* No instruction cache */ void flush_l2_cache(void); void busy_wait(unsigned int ms); From 01520cd63895eb91a3234d374a50c2c57809dfef Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Thu, 4 Jan 2024 09:51:17 +0100 Subject: [PATCH 21/78] cpu/gowin_emcu: Simplify SRAM. --- litex/soc/cores/cpu/gowin_emcu/core.py | 36 ++++++++++---------------- 1 file changed, 13 insertions(+), 23 deletions(-) diff --git a/litex/soc/cores/cpu/gowin_emcu/core.py b/litex/soc/cores/cpu/gowin_emcu/core.py index 0494befc7..c2beb920a 100644 --- a/litex/soc/cores/cpu/gowin_emcu/core.py +++ b/litex/soc/cores/cpu/gowin_emcu/core.py @@ -62,8 +62,7 @@ class GowinEMCU(CPU): # ------------- bus_reset_n = Signal() - self.cpu_params = dict() - self.cpu_params.update( + self.cpu_params = dict( # Clk/Rst. i_FCLK = ClockSignal("sys"), i_PORESETN = ~ (ResetSignal("sys") | self.reset), @@ -88,18 +87,13 @@ class GowinEMCU(CPU): i_FLASHINT = Signal(), ) - # SRAM (32-bit RAM split between 8 SRAMs x 4 bit each). + # SRAM (32-bit RAM split between 8 SRAMs x 4-bit each). # ----------------------------------------------------- - # Parameters. - sram_dw = 32 - single_sram_dw = 4 - nsrams = sram_dw // single_sram_dw - # CPU SRAM Interface. sram0_addr = Signal(13) - sram0_rdata = Signal(sram_dw) - sram0_wdata = Signal(sram_dw) + sram0_rdata = Signal(32) + sram0_wdata = Signal(32) sram0_cs = Signal() sram0_wren = Signal(4) self.cpu_params.update( @@ -111,27 +105,23 @@ class GowinEMCU(CPU): ) # SRAMS Instances. - for i in range(nsrams): + for i in range(8): self.specials += Instance("SDPB", p_READ_MODE = 0, - p_BIT_WIDTH_0 = single_sram_dw, - p_BIT_WIDTH_1 = single_sram_dw, + p_BIT_WIDTH_0 = 4, + p_BIT_WIDTH_1 = 4, p_RESET_MODE = "SYNC", - p_BLK_SEL_0 = 0b111, - p_BLK_SEL_1 = 0b111, - o_DO = Cat(sram0_rdata[i * single_sram_dw: (i + 1) * single_sram_dw], Signal(sram_dw - single_sram_dw)), - i_DI = Cat(sram0_wdata[i * single_sram_dw: (i + 1) * single_sram_dw], Signal(sram_dw - single_sram_dw)), - i_ADA = Cat(Signal(2), sram0_addr[:-1]), - i_ADB = Cat(Signal(2), sram0_addr[:-1]), - i_CEA = sram0_wren[i // 2], - i_CEB = ~sram0_wren[i // 2], + o_DO = sram0_rdata[4*i:4*(i + 1)], + i_DI = sram0_wdata[4*i:4*(i + 1)], + i_ADA = Cat(Signal(2), sram0_addr), + i_ADB = Cat(Signal(2), sram0_addr), + i_CEA = sram0_cs & sram0_wren[i//2], + i_CEB = sram0_cs & ~sram0_wren[i//2], i_CLKA = ClockSignal("sys"), i_CLKB = ClockSignal("sys"), i_RESETA = ~bus_reset_n, i_RESETB = ~bus_reset_n, i_OCE = 1, - i_BLKSELA = Cat(sram0_cs, sram0_cs, sram0_cs), - i_BLKSELB = Cat(sram0_cs, sram0_cs, sram0_cs), ) # Flash (Boot Flash memory connected via AHB). From b0cde1acdd94c49b5aa4a96ae6bc24419dbdfca3 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Thu, 4 Jan 2024 10:12:36 +0100 Subject: [PATCH 22/78] cpu/gowin_emcu: Switch SRAM to 4 SRAMS of 8-bit each. --- litex/soc/cores/cpu/gowin_emcu/core.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/litex/soc/cores/cpu/gowin_emcu/core.py b/litex/soc/cores/cpu/gowin_emcu/core.py index c2beb920a..8cbdcfd23 100644 --- a/litex/soc/cores/cpu/gowin_emcu/core.py +++ b/litex/soc/cores/cpu/gowin_emcu/core.py @@ -87,7 +87,7 @@ class GowinEMCU(CPU): i_FLASHINT = Signal(), ) - # SRAM (32-bit RAM split between 8 SRAMs x 4-bit each). + # SRAM (32-bit RAM split between 4 SRAMs x 8-bit each). # ----------------------------------------------------- # CPU SRAM Interface. @@ -105,18 +105,18 @@ class GowinEMCU(CPU): ) # SRAMS Instances. - for i in range(8): + for i in range(4): self.specials += Instance("SDPB", p_READ_MODE = 0, - p_BIT_WIDTH_0 = 4, - p_BIT_WIDTH_1 = 4, + p_BIT_WIDTH_0 = 8, + p_BIT_WIDTH_1 = 8, p_RESET_MODE = "SYNC", - o_DO = sram0_rdata[4*i:4*(i + 1)], - i_DI = sram0_wdata[4*i:4*(i + 1)], - i_ADA = Cat(Signal(2), sram0_addr), - i_ADB = Cat(Signal(2), sram0_addr), - i_CEA = sram0_cs & sram0_wren[i//2], - i_CEB = sram0_cs & ~sram0_wren[i//2], + o_DO = sram0_rdata[8*i:8*(i + 1)], + i_DI = sram0_wdata[8*i:8*(i + 1)], + i_ADA = Cat(Signal(3), sram0_addr), + i_ADB = Cat(Signal(3), sram0_addr), + i_CEA = sram0_cs & sram0_wren[i], + i_CEB = sram0_cs, i_CLKA = ClockSignal("sys"), i_CLKB = ClockSignal("sys"), i_RESETA = ~bus_reset_n, From de6fbf1271961988959759d9f26befc0fd7a8df8 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Thu, 4 Jan 2024 10:32:51 +0100 Subject: [PATCH 23/78] cpu/gowin_emcu: Directly connect AHB interfaces, using for loops make things unclear/difficult to follow. --- litex/soc/cores/cpu/gowin_emcu/core.py | 34 ++++++++++++++++++-------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/litex/soc/cores/cpu/gowin_emcu/core.py b/litex/soc/cores/cpu/gowin_emcu/core.py index 8cbdcfd23..3e8159280 100644 --- a/litex/soc/cores/cpu/gowin_emcu/core.py +++ b/litex/soc/cores/cpu/gowin_emcu/core.py @@ -162,12 +162,16 @@ class GowinEMCU(CPU): ) ahb_flash = ahb.Interface() - for s, _ in ahb_flash.master_signals: - if s in ["wdata", "write", "mastlock", "prot"]: - continue - self.cpu_params[f"o_TARGFLASH0H{s.upper()}"] = getattr(ahb_flash, s) - for s, _ in ahb_flash.slave_signals: - self.cpu_params[f"i_TARGFLASH0H{s.upper()}"] = getattr(ahb_flash, s) + self.cpu_params.update( + o_TARGFLASH0HADDR = ahb_flash.addr, + o_TARGFLASH0HBURST = ahb_flash.burst, + o_TARGFLASH0HSIZE = ahb_flash.size, + o_TARGFLASH0HTRANS = ahb_flash.trans, + o_TARGFLASH0HSEL = ahb_flash.sel, + i_TARGFLASH0HRDATA = ahb_flash.rdata, + i_TARGFLASH0HREADYOUT = ahb_flash.readyout, + i_TARGFLASH0HRESP = ahb_flash.resp, + ) flash = ResetInserter()(AHBFlash(ahb_flash)) self.comb += flash.reset.eq(~bus_reset_n) self.submodules += flash @@ -176,10 +180,20 @@ class GowinEMCU(CPU): # Peripheral Bus (AHB -> Wishbone). # --------------------------------- ahb_targexp0 = ahb.Interface() - for s, _ in ahb_targexp0.master_signals: - self.cpu_params[f"o_TARGEXP0H{s.upper()}"] = getattr(ahb_targexp0, s) - for s, _ in ahb_targexp0.slave_signals: - self.cpu_params[f"i_TARGEXP0H{s.upper()}"] = getattr(ahb_targexp0, s) + self.cpu_params.update( + o_TARGEXP0HADDR = ahb_targexp0.addr, + o_TARGEXP0HBURST = ahb_targexp0.burst, + o_TARGEXP0HMASTLOCK = ahb_targexp0.mastlock, + o_TARGEXP0HPROT = ahb_targexp0.prot, + o_TARGEXP0HSIZE = ahb_targexp0.size, + o_TARGEXP0HTRANS = ahb_targexp0.trans, + o_TARGEXP0HWDATA = ahb_targexp0.wdata, + o_TARGEXP0HWRITE = ahb_targexp0.write, + o_TARGEXP0HSEL = ahb_targexp0.sel, + i_TARGEXP0HRDATA = ahb_targexp0.rdata, + i_TARGEXP0HREADYOUT = ahb_targexp0.readyout, + i_TARGEXP0HRESP = ahb_targexp0.resp, + ) self.submodules += ahb.AHB2Wishbone(ahb_targexp0, self.pbus) def connect_uart(self, pads, n=0): From 386854cbd3f1b8e7952141cc1290d46eb6f8d9e1 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Thu, 4 Jan 2024 10:38:45 +0100 Subject: [PATCH 24/78] cpu/gowin_emcu: Use crt0.c from cortex_m3. --- litex/soc/cores/cpu/gowin_emcu/crt0.c | 67 +++++++++++++++++++++++---- 1 file changed, 59 insertions(+), 8 deletions(-) diff --git a/litex/soc/cores/cpu/gowin_emcu/crt0.c b/litex/soc/cores/cpu/gowin_emcu/crt0.c index bea687093..cafc474c8 100644 --- a/litex/soc/cores/cpu/gowin_emcu/crt0.c +++ b/litex/soc/cores/cpu/gowin_emcu/crt0.c @@ -8,6 +8,10 @@ void _start(void); void default_handler(void); void _start(void) { + __asm__( + "mov r0, %0\n" + "mov sp, r0\n" : : "r" (&_fstack) + ); uint32_t *y = &_fdata_rom; for (uint32_t *x = &_fdata; x < &_edata; x ++) *x = *y ++; @@ -22,26 +26,73 @@ void _start(void) { while(1); } + void default_handler(void) { while(1); } - const void* isr_vector[] __attribute__((__used__)) __attribute__((section(".isr_vector"))) = { &_fstack, - _start, + _start, // reset + default_handler, // nmi + default_handler, // hard fault + default_handler, // mem manage + default_handler, // bus fault + default_handler, // usage fault + (void *) 0x55, // reserved + 0, // reserved + 0, // reserved + 0, // reserved + default_handler, // svc + default_handler, // debug mon + 0, // reserved + default_handler, // pend sv + default_handler, // systick + // external + default_handler, + default_handler, + default_handler, + default_handler, + default_handler, + default_handler, + default_handler, + default_handler, + default_handler, + default_handler, + default_handler, + default_handler, + default_handler, + default_handler, + default_handler, + default_handler, + default_handler, + default_handler, + default_handler, + default_handler, + default_handler, + default_handler, + default_handler, + default_handler, default_handler, default_handler, default_handler, default_handler, default_handler, - 0, - 0, - 0, - 0, default_handler, default_handler, - 0, default_handler, - default_handler }; + +__asm__ ( +"__gnu_thumb1_case_uhi:\n" +"push {r0, r1}\n" +"mov r1, lr\n" +"lsrs r1, r1, #1\n" +"lsls r0, r0, #1\n" +"lsls r1, r1, #1\n" +"ldrh r1, [r1, r0]\n" +"lsls r1, r1, #1\n" +"add lr, lr, r1\n" +"pop {r0, r1}\n" +"bx lr\n" +); From 6a6837062a0eebc99a81caee4ecc5a238489481c Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Thu, 4 Jan 2024 10:40:47 +0100 Subject: [PATCH 25/78] cpu/gowin_emcu: Remove interrupt signal since not yet functional/used. --- litex/soc/cores/cpu/gowin_emcu/core.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/litex/soc/cores/cpu/gowin_emcu/core.py b/litex/soc/cores/cpu/gowin_emcu/core.py index 3e8159280..22e5e8b30 100644 --- a/litex/soc/cores/cpu/gowin_emcu/core.py +++ b/litex/soc/cores/cpu/gowin_emcu/core.py @@ -53,7 +53,6 @@ class GowinEMCU(CPU): def __init__(self, platform, variant="standard"): self.platform = platform self.reset = Signal() - self.interrupt = Signal(5) self.pbus = wishbone.Interface(data_width=32, adr_width=30, addressing="word") self.periph_buses = [self.pbus] self.memory_buses = [] @@ -79,7 +78,7 @@ class GowinEMCU(CPU): o_IOEXPOUTPUTENO = Signal(), # TODO: GPIO Output Enable (16-bit). # Interrupts. - i_GPINT = self.interrupt, + i_GPINT = Open(), o_INTMONITOR = Signal(), # Flash. From 5bbcda4d5ca53f7a36e4499cb4d3e970f7d2d328 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Thu, 4 Jan 2024 13:09:31 +0100 Subject: [PATCH 26/78] interconnect/ahb/AHB2Wishbone: Fix size check that is too restrictive, can be <= log2_int(ahb.data_width//8). --- litex/soc/interconnect/ahb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/litex/soc/interconnect/ahb.py b/litex/soc/interconnect/ahb.py index a39d3d2e2..e7c73f238 100644 --- a/litex/soc/interconnect/ahb.py +++ b/litex/soc/interconnect/ahb.py @@ -70,7 +70,7 @@ class AHB2Wishbone(LiteXModule): fsm.act("IDLE", ahb.readyout.eq(1), If(ahb.sel & - (ahb.size == wishbone_adr_shift) & + (ahb.size <= log2_int(ahb.data_width//8)) & (ahb.trans == TransferType.NONSEQUENTIAL), NextValue(wishbone.adr, ahb.addr[wishbone_adr_shift:]), NextValue(wishbone.dat_w, ahb.wdata), From 55e2a1cec6948470b02cc2c42c0bbd59b500d2f6 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Thu, 4 Jan 2024 13:13:21 +0100 Subject: [PATCH 27/78] cpu/gowin_emcu: Switch pbus to byte addresssing. --- litex/soc/cores/cpu/gowin_emcu/core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/litex/soc/cores/cpu/gowin_emcu/core.py b/litex/soc/cores/cpu/gowin_emcu/core.py index 22e5e8b30..3c0352054 100644 --- a/litex/soc/cores/cpu/gowin_emcu/core.py +++ b/litex/soc/cores/cpu/gowin_emcu/core.py @@ -53,7 +53,7 @@ class GowinEMCU(CPU): def __init__(self, platform, variant="standard"): self.platform = platform self.reset = Signal() - self.pbus = wishbone.Interface(data_width=32, adr_width=30, addressing="word") + self.pbus = wishbone.Interface(data_width=32, address_width=32, addressing="byte") self.periph_buses = [self.pbus] self.memory_buses = [] From 02f0a96c847d1327233a84c243eff3e1357d49d2 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Thu, 4 Jan 2024 15:21:32 +0100 Subject: [PATCH 28/78] interconnect/ahb: Add AHB prefix to TransferType/Interface (similar to AXI). --- litex/soc/cores/cpu/gowin_emcu/core.py | 7 ++++--- litex/soc/interconnect/ahb.py | 6 +++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/litex/soc/cores/cpu/gowin_emcu/core.py b/litex/soc/cores/cpu/gowin_emcu/core.py index 3c0352054..6d8f8da90 100644 --- a/litex/soc/cores/cpu/gowin_emcu/core.py +++ b/litex/soc/cores/cpu/gowin_emcu/core.py @@ -10,7 +10,8 @@ from migen import * from litex.gen import * from litex.soc.cores.cpu import CPU -from litex.soc.interconnect import wishbone, ahb +from litex.soc.interconnect import wishbone +from litex.soc.interconnect import ahb # Gowin EMCU --------------------------------------------------------------------------------------- @@ -160,7 +161,7 @@ class GowinEMCU(CPU): i_NVSTR = 0 ) - ahb_flash = ahb.Interface() + ahb_flash = ahb.AHBInterface() self.cpu_params.update( o_TARGFLASH0HADDR = ahb_flash.addr, o_TARGFLASH0HBURST = ahb_flash.burst, @@ -178,7 +179,7 @@ class GowinEMCU(CPU): # Peripheral Bus (AHB -> Wishbone). # --------------------------------- - ahb_targexp0 = ahb.Interface() + ahb_targexp0 = ahb.AHBInterface() self.cpu_params.update( o_TARGEXP0HADDR = ahb_targexp0.addr, o_TARGEXP0HBURST = ahb_targexp0.burst, diff --git a/litex/soc/interconnect/ahb.py b/litex/soc/interconnect/ahb.py index e7c73f238..6d0943d0a 100644 --- a/litex/soc/interconnect/ahb.py +++ b/litex/soc/interconnect/ahb.py @@ -15,7 +15,7 @@ from litex.gen import * # Helpers ------------------------------------------------------------------------------------------ -class TransferType(IntEnum): +class AHBTransferType(IntEnum): """Defines types of AHB transfers.""" IDLE = 0 BUSY = 1 @@ -24,7 +24,7 @@ class TransferType(IntEnum): # AHB Interface ------------------------------------------------------------------------------------ -class Interface(Record): +class AHBInterface(Record): """Sets up the AHB interface signals for master and slave.""" adr_width = 32 data_width = 32 @@ -71,7 +71,7 @@ class AHB2Wishbone(LiteXModule): ahb.readyout.eq(1), If(ahb.sel & (ahb.size <= log2_int(ahb.data_width//8)) & - (ahb.trans == TransferType.NONSEQUENTIAL), + (ahb.trans == AHBTransferType.NONSEQUENTIAL), NextValue(wishbone.adr, ahb.addr[wishbone_adr_shift:]), NextValue(wishbone.dat_w, ahb.wdata), NextValue(wishbone.we, ahb.write), From 70092991323680fe8218e29515aa34f0abf96349 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Thu, 4 Jan 2024 15:30:26 +0100 Subject: [PATCH 29/78] interconnect/ahb: Simplify AHBInterface and add data_width/address_width parameters. --- litex/soc/interconnect/ahb.py | 49 +++++++++++++++++------------------ 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/litex/soc/interconnect/ahb.py b/litex/soc/interconnect/ahb.py index 6d0943d0a..044636ace 100644 --- a/litex/soc/interconnect/ahb.py +++ b/litex/soc/interconnect/ahb.py @@ -22,31 +22,30 @@ class AHBTransferType(IntEnum): NONSEQUENTIAL = 2 SEQUENTIAL = 3 -# AHB Interface ------------------------------------------------------------------------------------ +# AHB Definition ----------------------------------------------------------------------------------- + +def ahb_description(data_width, address_width): + return [ + ("addr", address_width, DIR_M_TO_S), + ("burst", 3, DIR_M_TO_S), + ("mastlock", 1, DIR_M_TO_S), + ("prot", 4, DIR_M_TO_S), + ("size", 3, DIR_M_TO_S), + ("trans", 2, DIR_M_TO_S), + ("wdata", data_width, DIR_M_TO_S), + ("write", 1, DIR_M_TO_S), + ("sel", 1, DIR_M_TO_S), + ("rdata", data_width, DIR_S_TO_M), + ("readyout", 1, DIR_S_TO_M), + ("resp", 1, DIR_S_TO_M), +] class AHBInterface(Record): - """Sets up the AHB interface signals for master and slave.""" - adr_width = 32 - data_width = 32 - addressing = "byte" - master_signals = [ - ("addr", adr_width), - ("burst", 3), - ("mastlock", 1), - ("prot", 4), - ("size", 3), - ("trans", 2), - ("wdata", data_width), - ("write", 1), - ("sel", 1), - ] - slave_signals = [ - ("rdata", data_width), - ("readyout", 1), - ("resp", 1), - ] - def __init__(self): - Record.__init__(self, set_layout_parameters(self.master_signals + self.slave_signals)) + def __init__(self, data_width=32, address_width=32): + Record.__init__(self, ahb_description(data_width, address_width)) + self.data_width = data_width + self.address_width = address_width + self.addressing = "byte" # AHB to Wishbone --------------------------------------------------------------------------------- @@ -62,8 +61,8 @@ class AHB2Wishbone(LiteXModule): "word" : log2_int(ahb.data_width//8), "byte" : 0 }[wishbone.addressing] - assert ahb.data_width == wishbone.data_width - assert ahb.adr_width == wishbone.adr_width + wishbone_adr_shift + assert ahb.data_width == wishbone.data_width + assert ahb.address_width == wishbone.adr_width + wishbone_adr_shift # FSM. self.fsm = fsm = FSM() From 739a8db8c37205e3b3eec532af1f7db87e4a98ef Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Thu, 4 Jan 2024 15:30:47 +0100 Subject: [PATCH 30/78] cpu/gowin_emcu: Specify AHB data_width/address_width. --- litex/soc/cores/cpu/gowin_emcu/core.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/litex/soc/cores/cpu/gowin_emcu/core.py b/litex/soc/cores/cpu/gowin_emcu/core.py index 6d8f8da90..6bd90550e 100644 --- a/litex/soc/cores/cpu/gowin_emcu/core.py +++ b/litex/soc/cores/cpu/gowin_emcu/core.py @@ -161,7 +161,7 @@ class GowinEMCU(CPU): i_NVSTR = 0 ) - ahb_flash = ahb.AHBInterface() + ahb_flash = ahb.AHBInterface(data_width=32, address_width=32) self.cpu_params.update( o_TARGFLASH0HADDR = ahb_flash.addr, o_TARGFLASH0HBURST = ahb_flash.burst, @@ -179,7 +179,7 @@ class GowinEMCU(CPU): # Peripheral Bus (AHB -> Wishbone). # --------------------------------- - ahb_targexp0 = ahb.AHBInterface() + ahb_targexp0 = ahb.AHBInterface(data_width=32, address_width=32) self.cpu_params.update( o_TARGEXP0HADDR = ahb_targexp0.addr, o_TARGEXP0HBURST = ahb_targexp0.burst, From cf165d3c2c6305c32880dd0598685dbac470b466 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Thu, 4 Jan 2024 15:33:01 +0100 Subject: [PATCH 31/78] README/Bios: Bump year. --- README.md | 2 +- litex/soc/software/bios/main.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 721021380..becbbe4de 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@

``` - Copyright 2012-2023 / Enjoy-Digital & LiteX developers + Copyright 2012-2024 / Enjoy-Digital & LiteX developers ``` [![](https://github.com/enjoy-digital/litex/workflows/ci/badge.svg)](https://github.com/enjoy-digital/litex/actions) ![License](https://img.shields.io/badge/License-BSD%202--Clause-orange.svg) diff --git a/litex/soc/software/bios/main.c b/litex/soc/software/bios/main.c index 69fbd22af..a39caafd3 100644 --- a/litex/soc/software/bios/main.c +++ b/litex/soc/software/bios/main.c @@ -110,7 +110,7 @@ __attribute__((__used__)) int main(int i, char **c) printf("\e[1m /____/_/\\__/\\__/_/|_|\e[0m\n"); printf("\e[1m Build your hardware, easily!\e[0m\n"); printf("\n"); - printf(" (c) Copyright 2012-2023 Enjoy-Digital\n"); + printf(" (c) Copyright 2012-2024 Enjoy-Digital\n"); printf(" (c) Copyright 2007-2015 M-Labs\n"); printf("\n"); #ifndef CONFIG_BIOS_NO_BUILD_TIME From c61d2de13b1665d28e86f5a2c20d4a613bf9da78 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Thu, 4 Jan 2024 15:37:58 +0100 Subject: [PATCH 32/78] CHANGES.md: Update. --- CHANGES.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 2d1d09728..d431772ec 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,19 @@ +[> Changes since 2023.12 +------------------------ + [> Fixed + -------- + - integration/soc : Fixed typo in cpu mem_bus axi-via-wb downconvert + - interconnect/ahb/AHB2Wishbone : Fix size check that was too restrictive. + + [> Added + -------- + - build/openfpgaloader : Added kwargs support to flash for specific/less common cases. + - cpu/gowin_emcu : Improved/Cleaned-up. + - interconnect/ahb : Added data_width/address_width parameters. + + [> Changed + ---------- + [> 2023.12, released on December 25th 2023 ------------------------------------------ [> Fixed From 718c26d8fc30045b61c1760376dd27a52a57400d Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Thu, 4 Jan 2024 19:33:43 +0100 Subject: [PATCH 33/78] cpu/gowin_emcu: Add interfaces directly to instances and simplify/cleanup to remove some warnings. --- litex/soc/cores/cpu/gowin_emcu/core.py | 125 ++++++++++++++++++------- 1 file changed, 90 insertions(+), 35 deletions(-) diff --git a/litex/soc/cores/cpu/gowin_emcu/core.py b/litex/soc/cores/cpu/gowin_emcu/core.py index 6bd90550e..dcc38edc0 100644 --- a/litex/soc/cores/cpu/gowin_emcu/core.py +++ b/litex/soc/cores/cpu/gowin_emcu/core.py @@ -13,7 +13,7 @@ from litex.soc.cores.cpu import CPU from litex.soc.interconnect import wishbone from litex.soc.interconnect import ahb -# Gowin EMCU --------------------------------------------------------------------------------------- +# Gowin EMCU (Enhanced MCU / Cortex M3) ------------------------------------------------------------ class GowinEMCU(CPU): variants = ["standard"] @@ -61,7 +61,10 @@ class GowinEMCU(CPU): # CPU Instance. # ------------- - bus_reset_n = Signal() + bus_reset_n = Signal() + ahb_flash = ahb.AHBInterface(data_width=32, address_width=32) + ahb_targexp0 = ahb.AHBInterface(data_width=32, address_width=32) + self.cpu_params = dict( # Clk/Rst. i_FCLK = ClockSignal("sys"), @@ -71,20 +74,95 @@ class GowinEMCU(CPU): o_MTXHRESETN = bus_reset_n, # RTC. - i_RTCSRCCLK = Signal(), # TODO: RTC Clk In. + i_RTCSRCCLK = 0b0, # RTC Clk In. # GPIOs. - i_IOEXPINPUTI = Signal(), # TODO: GPIO Input (16-bit). - o_IOEXPOUTPUTO = Signal(), # TODO: GPIO Output (16-bit). - o_IOEXPOUTPUTENO = Signal(), # TODO: GPIO Output Enable (16-bit). + i_IOEXPINPUTI = 0x0000, # GPIO Input (16-bit). + o_IOEXPOUTPUTO = Open(16), # GPIO Output (16-bit). + o_IOEXPOUTPUTENO = Open(16), # GPIO Output Enable (16-bit). + + # UART0. + i_UART0RXDI = 0b0, + o_UART0TXDO = Open(), + o_UART0BAUDTICK = Open(), + + # UART1. + i_UART1RXDI = 0b0, + o_UART1TXDO = Open(), + o_UART1BAUDTICK = Open(), # Interrupts. - i_GPINT = Open(), - o_INTMONITOR = Signal(), + i_GPINT = 0, + o_INTMONITOR = Open(), # Flash. i_FLASHERR = Signal(), i_FLASHINT = Signal(), + + # Debug/JTAG. + o_DAPTDO = Open(), + o_DAPJTAGNSW = Open(), + o_DAPNTDOEN = Open(), + i_DAPSWDITMS = 0, + i_DAPTDI = 0, + i_DAPNTRST = 0, + i_DAPSWCLKTCK = 0, + + # TARGFLASH0 / AHBLite Master. + o_TARGFLASH0HSEL = ahb_flash.sel, + o_TARGFLASH0HADDR = ahb_flash.addr, + o_TARGFLASH0HTRANS = ahb_flash.trans, + o_TARGFLASH0HSIZE = ahb_flash.size, + o_TARGFLASH0HBURST = ahb_flash.burst, + o_TARGFLASH0HREADYMUX = Open(), + i_TARGFLASH0HRDATA = ahb_flash.rdata, + i_TARGFLASH0HRUSER = 0b000, + i_TARGFLASH0HRESP = ahb_flash.resp, + i_TARGFLASH0EXRESP = 0b0, + i_TARGFLASH0HREADYOUT = ahb_flash.readyout, + + # TARGEXP0 / AHBLite Master. + o_TARGEXP0HSEL = ahb_targexp0.sel, + o_TARGEXP0HADDR = ahb_targexp0.addr, + o_TARGEXP0HTRANS = ahb_targexp0.trans, + o_TARGEXP0HWRITE = ahb_targexp0.write, + o_TARGEXP0HSIZE = ahb_targexp0.size, + o_TARGEXP0HBURST = ahb_targexp0.burst, + o_TARGEXP0HPROT = ahb_targexp0.prot, + o_TARGEXP0MEMATTR = Open(2), + o_TARGEXP0EXREQ = Open(), + o_TARGEXP0HMASTER = Open(4), + o_TARGEXP0HWDATA = ahb_targexp0.wdata, + o_TARGEXP0HMASTLOCK = ahb_targexp0.mastlock, + o_TARGEXP0HREADYMUX = Open(), + o_TARGEXP0HAUSER = Open(), + o_TARGEXP0HWUSER = Open(4), + i_TARGEXP0HRDATA = ahb_targexp0.rdata, + i_TARGEXP0HREADYOUT = ahb_targexp0.readyout, + i_TARGEXP0HRESP = ahb_targexp0.resp, + i_TARGEXP0EXRESP = 0b0, + i_TARGEXP0HRUSER = 0b000, + + # INITEXP0 / AHBLite Slave. + o_INITEXP0HRDATA = Open(32), + o_INITEXP0HREADY = Open(), + o_INITEXP0HRESP = Open(), + o_INITEXP0EXRESP = Open(), + o_INITEXP0HRUSER = Open(3), + i_INITEXP0HSEL = 0b0, + i_INITEXP0HADDR = 0x00000000, + i_INITEXP0HTRANS = 0b00, + i_INITEXP0HWRITE = 0b0, + i_INITEXP0HSIZE = 0b000, + i_INITEXP0HBURST = 0b000, + i_INITEXP0HPROT = 0b0000, + i_INITEXP0MEMATTR = 0b00, + i_INITEXP0EXREQ = 0b0, + i_INITEXP0HMASTER = 0b0000, + i_INITEXP0HWDATA = 0x00000000, + i_INITEXP0HMASTLOCK = 0b0, + i_INITEXP0HAUSER = 0b0, + i_INITEXP0HWUSER = 0b0000, ) # SRAM (32-bit RAM split between 4 SRAMs x 8-bit each). @@ -111,6 +189,10 @@ class GowinEMCU(CPU): p_BIT_WIDTH_0 = 8, p_BIT_WIDTH_1 = 8, p_RESET_MODE = "SYNC", + p_BLK_SEL_0 = Constant(0, 3), + p_BLK_SEL_1 = Constant(0, 3), + i_BLKSELA = 0b000, + i_BLKSELB = 0b000, o_DO = sram0_rdata[8*i:8*(i + 1)], i_DI = sram0_wdata[8*i:8*(i + 1)], i_ADA = Cat(Signal(3), sram0_addr), @@ -161,39 +243,12 @@ class GowinEMCU(CPU): i_NVSTR = 0 ) - ahb_flash = ahb.AHBInterface(data_width=32, address_width=32) - self.cpu_params.update( - o_TARGFLASH0HADDR = ahb_flash.addr, - o_TARGFLASH0HBURST = ahb_flash.burst, - o_TARGFLASH0HSIZE = ahb_flash.size, - o_TARGFLASH0HTRANS = ahb_flash.trans, - o_TARGFLASH0HSEL = ahb_flash.sel, - i_TARGFLASH0HRDATA = ahb_flash.rdata, - i_TARGFLASH0HREADYOUT = ahb_flash.readyout, - i_TARGFLASH0HRESP = ahb_flash.resp, - ) flash = ResetInserter()(AHBFlash(ahb_flash)) self.comb += flash.reset.eq(~bus_reset_n) self.submodules += flash - # Peripheral Bus (AHB -> Wishbone). # --------------------------------- - ahb_targexp0 = ahb.AHBInterface(data_width=32, address_width=32) - self.cpu_params.update( - o_TARGEXP0HADDR = ahb_targexp0.addr, - o_TARGEXP0HBURST = ahb_targexp0.burst, - o_TARGEXP0HMASTLOCK = ahb_targexp0.mastlock, - o_TARGEXP0HPROT = ahb_targexp0.prot, - o_TARGEXP0HSIZE = ahb_targexp0.size, - o_TARGEXP0HTRANS = ahb_targexp0.trans, - o_TARGEXP0HWDATA = ahb_targexp0.wdata, - o_TARGEXP0HWRITE = ahb_targexp0.write, - o_TARGEXP0HSEL = ahb_targexp0.sel, - i_TARGEXP0HRDATA = ahb_targexp0.rdata, - i_TARGEXP0HREADYOUT = ahb_targexp0.readyout, - i_TARGEXP0HRESP = ahb_targexp0.resp, - ) self.submodules += ahb.AHB2Wishbone(ahb_targexp0, self.pbus) def connect_uart(self, pads, n=0): From 91fbc79ac2e0af4e9edf3a3fe423f98fb7bdeffb Mon Sep 17 00:00:00 2001 From: Gwenhael Goavec-Merou Date: Mon, 8 Jan 2024 07:28:56 +0100 Subject: [PATCH 34/78] build/gowin/common: adding missing TX/Q1 ODDR signals --- litex/build/gowin/common.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/litex/build/gowin/common.py b/litex/build/gowin/common.py index fd554e946..1869385af 100644 --- a/litex/build/gowin/common.py +++ b/litex/build/gowin/common.py @@ -7,6 +7,8 @@ from migen.fhdl.module import Module from migen.genlib.resetsync import AsyncResetSynchronizer +from litex.gen import * + from litex.build.io import * # Gowin AsyncResetSynchronizer --------------------------------------------------------------------- @@ -58,7 +60,9 @@ class GowinDDROutputImpl(Module): i_CLK = clk, i_D0 = i1, i_D1 = i2, + i_TX = 0, o_Q0 = o, + o_Q1 = Open(), ) class GowinDDROutput: From 31d3325219a387c4e426061799f28019b7069951 Mon Sep 17 00:00:00 2001 From: Gwenhael Goavec-Merou Date: Wed, 10 Jan 2024 06:51:18 +0100 Subject: [PATCH 35/78] build/gowin/platform: adding mock add_false_path_constraint method Signed-off-by: Gwenhael Goavec-Merou --- litex/build/gowin/platform.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/litex/build/gowin/platform.py b/litex/build/gowin/platform.py index 2e8a75f44..f21d11ee7 100644 --- a/litex/build/gowin/platform.py +++ b/litex/build/gowin/platform.py @@ -43,3 +43,6 @@ class GowinPlatform(GenericPlatform): def build(self, *args, **kwargs): return self.toolchain.build(self, *args, **kwargs) + + def add_false_path_constraint(self, from_, to): + pass From a2c2d7084176b8b16ed1076dbeab1ffa13f1941c Mon Sep 17 00:00:00 2001 From: Gwenhael Goavec-Merou Date: Wed, 10 Jan 2024 06:52:06 +0100 Subject: [PATCH 36/78] build/gowin/gowin: adding list of additional cst commands (to place resources) Signed-off-by: Gwenhael Goavec-Merou --- litex/build/gowin/gowin.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/litex/build/gowin/gowin.py b/litex/build/gowin/gowin.py index 8ee97cecf..7129db38e 100644 --- a/litex/build/gowin/gowin.py +++ b/litex/build/gowin/gowin.py @@ -26,6 +26,7 @@ class GowinToolchain(GenericToolchain): def __init__(self): super().__init__() self.options = {} + self.additional_cst_commands = [] def finalize(self): if self.platform.verilog_include_paths: @@ -108,6 +109,8 @@ class GowinToolchain(GenericToolchain): if self.named_pc: cst.extend(self.named_pc) + cst.extend(self.additional_cst_commands) + tools.write_to_file(f"{self._build_name}.cst", "\n".join(cst)) return (f"{self._build_name}.cst", "CST") From 80dfb5ca34daa7bc13c1e3b20eae58419f8cbd52 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Wed, 10 Jan 2024 12:10:15 +0100 Subject: [PATCH 37/78] interconnect/ahb/AHB2Wishbone: Simplify and add proper Address/Data-Phases. --- litex/soc/interconnect/ahb.py | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/litex/soc/interconnect/ahb.py b/litex/soc/interconnect/ahb.py index 044636ace..8fe6aff4f 100644 --- a/litex/soc/interconnect/ahb.py +++ b/litex/soc/interconnect/ahb.py @@ -66,27 +66,24 @@ class AHB2Wishbone(LiteXModule): # FSM. self.fsm = fsm = FSM() - fsm.act("IDLE", + fsm.act("ADDRESS-PHASE", ahb.readyout.eq(1), If(ahb.sel & (ahb.size <= log2_int(ahb.data_width//8)) & (ahb.trans == AHBTransferType.NONSEQUENTIAL), - NextValue(wishbone.adr, ahb.addr[wishbone_adr_shift:]), - NextValue(wishbone.dat_w, ahb.wdata), - NextValue(wishbone.we, ahb.write), - NextValue(wishbone.sel, 2**len(wishbone.sel) - 1), - NextState("ACT"), + NextValue(wishbone.adr, ahb.addr[wishbone_adr_shift:]), + NextValue(wishbone.we, ahb.write), + NextState("DATA-PHASE"), ) ) - fsm.act("ACT", + fsm.act("DATA-PHASE", wishbone.stb.eq(1), wishbone.cyc.eq(1), + wishbone.dat_w.eq(ahb.wdata), + wishbone.sel.eq(2**len(wishbone.sel) - 1), + ahb.resp.eq(wishbone.err), If(wishbone.ack, - If(~wishbone.we, - NextValue(ahb.rdata, wishbone.dat_r) - ), - NextState("IDLE") + NextValue(ahb.rdata, wishbone.dat_r), + NextState("ADDRESS-PHASE") ) ) - - self.comb += ahb.resp.eq(wishbone.err) From e689aab18a9eb8b11a99463e04df146890c72c28 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Thu, 11 Jan 2024 10:17:22 +0100 Subject: [PATCH 38/78] interconnect/ahb/AHB2Wishbone: Add proper Wishbone sel decoder/support. --- litex/soc/interconnect/ahb.py | 39 +++++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/litex/soc/interconnect/ahb.py b/litex/soc/interconnect/ahb.py index 8fe6aff4f..cee3540cd 100644 --- a/litex/soc/interconnect/ahb.py +++ b/litex/soc/interconnect/ahb.py @@ -64,6 +64,37 @@ class AHB2Wishbone(LiteXModule): assert ahb.data_width == wishbone.data_width assert ahb.address_width == wishbone.adr_width + wishbone_adr_shift + def wishbone_sel_decoder(ahb_size, ahb_addr): + wishbone_sel = Signal(8) + self.comb += Case(ahb_size, { + # 8-bit access. + 0b00 : Case(ahb_addr[0:3], { + 0b000 : wishbone_sel.eq(0b0000_0001), + 0b001 : wishbone_sel.eq(0b0000_0010), + 0b010 : wishbone_sel.eq(0b0000_0100), + 0b011 : wishbone_sel.eq(0b0000_1000), + 0b100 : wishbone_sel.eq(0b0001_0000), + 0b101 : wishbone_sel.eq(0b0010_0000), + 0b110 : wishbone_sel.eq(0b0100_0000), + 0b111 : wishbone_sel.eq(0b1000_0000), + }), + # 16-bit access. + 0b01 : Case(ahb_addr[1:3], { + 0b00 : wishbone_sel.eq(0b0000_0011), + 0b01 : wishbone_sel.eq(0b0000_1100), + 0b10 : wishbone_sel.eq(0b0011_0000), + 0b11 : wishbone_sel.eq(0b1100_0000), + }), + # 32-bit access. + 0b10 : Case(ahb_addr[2:3], { + 0b0 : wishbone_sel.eq(0b0000_1111), + 0b1 : wishbone_sel.eq(0b1111_0000), + }), + # 64-bit access. + 0b11 : wishbone_sel.eq(0b1111_1111), + }) + return wishbone_sel + # FSM. self.fsm = fsm = FSM() fsm.act("ADDRESS-PHASE", @@ -71,16 +102,16 @@ class AHB2Wishbone(LiteXModule): If(ahb.sel & (ahb.size <= log2_int(ahb.data_width//8)) & (ahb.trans == AHBTransferType.NONSEQUENTIAL), - NextValue(wishbone.adr, ahb.addr[wishbone_adr_shift:]), - NextValue(wishbone.we, ahb.write), - NextState("DATA-PHASE"), + NextValue(wishbone.adr, ahb.addr[wishbone_adr_shift:]), + NextValue(wishbone.we, ahb.write), + NextValue(wishbone.sel, wishbone_sel_decoder(ahb.size, ahb.addr)), + NextState("DATA-PHASE"), ) ) fsm.act("DATA-PHASE", wishbone.stb.eq(1), wishbone.cyc.eq(1), wishbone.dat_w.eq(ahb.wdata), - wishbone.sel.eq(2**len(wishbone.sel) - 1), ahb.resp.eq(wishbone.err), If(wishbone.ack, NextValue(ahb.rdata, wishbone.dat_r), From 8aa5958fb7138add921c9f959d6bf4ea8f50d0d7 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Thu, 11 Jan 2024 13:11:56 +0100 Subject: [PATCH 39/78] cores/cpu: Add intitial gowin_ae350 support. --- CHANGES.md | 2 + litex/soc/cores/cpu/gowin_ae350/__init__.py | 1 + litex/soc/cores/cpu/gowin_ae350/boot-helper.S | 4 + litex/soc/cores/cpu/gowin_ae350/core.py | 308 ++++++++++++++++++ litex/soc/cores/cpu/gowin_ae350/crt0.S | 75 +++++ litex/soc/cores/cpu/gowin_ae350/irq.h | 4 + litex/soc/cores/cpu/gowin_ae350/system.h | 19 ++ litex/soc/software/bios/main.c | 4 + 8 files changed, 417 insertions(+) create mode 100644 litex/soc/cores/cpu/gowin_ae350/__init__.py create mode 100644 litex/soc/cores/cpu/gowin_ae350/boot-helper.S create mode 100644 litex/soc/cores/cpu/gowin_ae350/core.py create mode 100644 litex/soc/cores/cpu/gowin_ae350/crt0.S create mode 100644 litex/soc/cores/cpu/gowin_ae350/irq.h create mode 100644 litex/soc/cores/cpu/gowin_ae350/system.h diff --git a/CHANGES.md b/CHANGES.md index d431772ec..9efb5d1ee 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -10,6 +10,8 @@ - build/openfpgaloader : Added kwargs support to flash for specific/less common cases. - cpu/gowin_emcu : Improved/Cleaned-up. - interconnect/ahb : Added data_width/address_width parameters. + - interconnect/ahb : Added proper byte/sel support to AHB2Wishbone. + - cpu/gowin_ae350 : Added initial support. [> Changed ---------- diff --git a/litex/soc/cores/cpu/gowin_ae350/__init__.py b/litex/soc/cores/cpu/gowin_ae350/__init__.py new file mode 100644 index 000000000..55596975c --- /dev/null +++ b/litex/soc/cores/cpu/gowin_ae350/__init__.py @@ -0,0 +1 @@ +from litex.soc.cores.cpu.gowin_ae350.core import GowinAE350 diff --git a/litex/soc/cores/cpu/gowin_ae350/boot-helper.S b/litex/soc/cores/cpu/gowin_ae350/boot-helper.S new file mode 100644 index 000000000..e8bd5c760 --- /dev/null +++ b/litex/soc/cores/cpu/gowin_ae350/boot-helper.S @@ -0,0 +1,4 @@ + .section .text, "ax", @progbits + .global boot_helper +boot_helper: + jr x13 diff --git a/litex/soc/cores/cpu/gowin_ae350/core.py b/litex/soc/cores/cpu/gowin_ae350/core.py new file mode 100644 index 000000000..6d7a8271e --- /dev/null +++ b/litex/soc/cores/cpu/gowin_ae350/core.py @@ -0,0 +1,308 @@ +# +# This file is part of LiteX. +# +# Copyright (c) 2024 Gwenhael Goavec-Merou +# Copyright (c) 2024 Florent Kermarrec +# SPDX-License-Identifier: BSD-2-Clause + +import os + +from migen import * + +from litex.gen import * + +from litex.soc.interconnect import wishbone, ahb +from litex.soc.interconnect.csr import * +from litex.soc.cores.cpu import CPU, CPU_GCC_TRIPLE_RISCV32 + +# Gowin AE350 Constants ---------------------------------------------------------------------------- + +APB_CE_APB = (1 << 0) +APB_CE_UART1 = (1 << 1) +APB_CE_UART2 = (1 << 2) +APB_CE_SPI = (1 << 3) +APB_CE_GPIO = (1 << 4) +APB_CE_PIT = (1 << 5) +APB_CE_I2C = (1 << 6) +APB_CE_WDT = (1 << 7) + +# Gowin AE350 -------------------------------------------------------------------------------------- + +class GowinAE350(CPU): + variants = ["standard"] + category = "hardcore" + family = "riscv" + name = "gowin_ae350" + human_name = "Gowin AE350" + data_width = 32 + endianness = "little" + reset_address = 0x8000_0000 + gcc_triple = CPU_GCC_TRIPLE_RISCV32 + linker_output_format = "elf32-littleriscv" + nop = "nop" + io_regions = { + # Origin, Length. + 0xe800_0000: 0x6000_0000 + } + + @property + def mem_map(self): + return { + "rom" : 0x80000000, + "sram" : 0x00000000, + "peripherals" : 0xf0000000, + "csr" : 0xe8000000, + } + + # GCC Flags. + @property + def gcc_flags(self): + flags = f" -mabi=ilp32 -march=rv32imafdc" + flags += f" -D__AE350__" + return flags + + def __init__(self, platform, variant, *args, **kwargs): + self.platform = platform + self.reset = Signal() + self.ibus = ibus = wishbone.Interface(data_width=32, address_width=32, addressing="byte") + self.dbus = dbus = wishbone.Interface(data_width=64, address_width=32, addressing="word") + self.pbus = pbus = wishbone.Interface(data_width=32, address_width=32, addressing="byte") + self.periph_buses = [ibus, dbus, pbus] # Peripheral buses (Connected to main SoC's bus). + self.memory_buses = [] # Memory buses (Connected directly to LiteDRAM). + + + # AHBLite Buses. + # -------------- + self.ahb_rom = ahb_rom = ahb.AHBInterface(data_width=32, address_width=32) + self.ahb_ram = ahb_ram = ahb.AHBInterface(data_width=64, address_width=32) + self.ahb_exts = ahb_exts = ahb.AHBInterface(data_width=32, address_width=32) + self.comb += [ + # Set AHBLite ROM static signals. + ahb_rom.sel.eq(1), + ahb_rom.size.eq(0b010), + ahb_rom.burst.eq(0), + # Set AHBLite RAM static signals. + ahb_ram.sel.eq(1), + ] + + # CPU Instance. + # ------------- + self.cpu_params = dict( + # Clk/Rst. + i_CORE_CLK = ClockSignal("cpu"), + i_DDR_CLK = ClockSignal("sys"), + i_AHB_CLK = ClockSignal("sys"), + i_APB_CLK = ClockSignal("sys"), + i_POR_N = 1, + i_HW_RSTN = ~(ResetSignal("sys") | self.reset), + o_PRESETN = Open(), + o_HRESETN = Open(), + o_DDR_RSTN = Open(), + + # Features/Peripherals Enable. + i_CORE_CE = 1, + i_AXI_CE = 1, + i_DDR_CE = 1, + i_AHB_CE = 1, + i_APB_CE = Constant(APB_CE_APB, 8), + i_APB2AHB_CE = 1, + + # WFI. + o_CORE0_WFI_MODE = Open(), + i_WAKEUP_IN = 0, + + # RTC. + i_RTC_CLK = ClockSignal("sys"), + o_RTC_WAKEUP = Open(), + + # Interrupts. + i_GP_INT = Constant(0, 16), + + # DMA. + i_DMA_REQ = Constant(0, 8), + o_DMA_ACK = Open(8), + + # AHBLite ROM interface. + i_ROM_HRDATA = ahb_rom.rdata, + i_ROM_HREADY = ahb_rom.readyout, + i_ROM_HRESP = ahb_rom.resp, + o_ROM_HADDR = ahb_rom.addr, + o_ROM_HTRANS = ahb_rom.trans, + o_ROM_HWRITE = ahb_rom.write, + + # APBLite Fabric interface (Slave). + o_APB_PADDR = Open(32), + o_APB_PENABLE = Open(), + i_APB_PRDATA = Constant(0, 32), + i_APB_PREADY = 0, + o_APB_PSEL = Open(), + o_APB_PWDATA = Open(32), + o_APB_PWRITE = Open(), + i_APB_PSLVERR = 0, + o_APB_PPROT = Open(3), + o_APB_PSTRB = Open(4), + + # AHBLite Peripheral interface (Master). + i_EXTS_HRDATA = ahb_exts.rdata, + i_EXTS_HREADYIN = ahb_exts.readyout, + i_EXTS_HRESP = ahb_exts.resp, + o_EXTS_HADDR = ahb_exts.addr, + o_EXTS_HBURST = ahb_exts.burst, + o_EXTS_HPROT = ahb_exts.prot, + o_EXTS_HSEL = ahb_exts.sel, + o_EXTS_HSIZE = ahb_exts.size, + o_EXTS_HTRANS = ahb_exts.trans, + o_EXTS_HWDATA = ahb_exts.wdata, + o_EXTS_HWRITE = ahb_exts.write, + + # AHBLite Peripheral interface (Slave). + i_EXTM_HADDR = Constant(0, 32), + i_EXTM_HBURST = Constant(0, 3), + i_EXTM_HPROT = Constant(0, 4), + o_EXTM_HRDATA = Open(64), + i_EXTM_HREADY = 0, + o_EXTM_HREADYOUT = Open(), + o_EXTM_HRESP = Open(), + i_EXTM_HSEL = 0, + i_EXTM_HSIZE = Constant(0, 3), + i_EXTM_HTRANS = Constant(0, 2), + i_EXTM_HWDATA = Constant(0, 64), + i_EXTM_HWRITE = 0, + + # AHBLite RAM interface (Slave). + i_DDR_HRDATA = ahb_ram.rdata, + i_DDR_HREADY = ahb_ram.readyout, + i_DDR_HRESP = ahb_ram.resp, + o_DDR_HADDR = ahb_ram.addr, + o_DDR_HBURST = ahb_ram.burst, + o_DDR_HPROT = ahb_ram.prot, + o_DDR_HSIZE = ahb_ram.size, + o_DDR_HTRANS = ahb_ram.trans, + o_DDR_HWDATA = ahb_ram.wdata, + o_DDR_HWRITE = ahb_ram.write, + + # GPIOs. + i_GPIO_IN = Constant(0, 32), + o_GPIO_OUT = Open(32), + o_GPIO_OE = Open(32), + + # SCAN. + i_SCAN_EN = 0, + i_SCAN_TEST = 0, + i_SCAN_IN = Constant(0xfffff, 20), + o_SCAN_OUT = Open(20), + + # Integrated JTAG. + i_INTEG_TCK = 1, + i_INTEG_TDI = 1, + i_INTEG_TMS = 1, + i_INTEG_TRST = 1, + o_INTEG_TDO = Open(), + + # SRAM (FIXME : Cleanup). + i_PGEN_CHAIN_I = 1, + o_PRDYN_CHAIN_O = Open(), + i_EMA = Constant(0b011, 3), + i_EMAW = Constant(0b01, 2), + i_EMAS = 0, + i_RET1N = 1, + i_RET2N = 1, + + # SPI. + i_SPI2_HOLDN_IN = 0, + i_SPI2_WPN_IN = 0, + i_SPI2_CLK_IN = 0, + i_SPI2_CSN_IN = 0, + i_SPI2_MISO_IN = 0, + i_SPI2_MOSI_IN = 0, + o_SPI2_HOLDN_OUT = Open(), + o_SPI2_HOLDN_OE = Open(), + o_SPI2_WPN_OUT = Open(), + o_SPI2_WPN_OE = Open(), + o_SPI2_CLK_OUT = Open(), + o_SPI2_CLK_OE = Open(), + o_SPI2_CSN_OUT = Open(), + o_SPI2_CSN_OE = Open(), + o_SPI2_MISO_OUT = Open(), + o_SPI2_MISO_OE = Open(), + o_SPI2_MOSI_OUT = Open(), + o_SPI2_MOSI_OE = Open(), + + # I2C. + i_I2C_SCL_IN = 0, + i_I2C_SDA_IN = 0, + o_I2C_SCL = Open(), + o_I2C_SDA = Open(), + + # PIT/PWM. + o_CH0_PWM = Open(), + o_CH0_PWMOE = Open(), + o_CH1_PWM = Open(), + o_CH1_PWMOE = Open(), + o_CH2_PWM = Open(), + o_CH2_PWMOE = Open(), + o_CH3_PWM = Open(), + o_CH3_PWMOE = Open(), + + # UART1. + o_UART1_TXD = Open(), + o_UART1_RTSN = Open(), + i_UART1_RXD = 0, + i_UART1_CTSN = 0, + i_UART1_DSRN = 0, + i_UART1_DCDN = 0, + i_UART1_RIN = 0, + o_UART1_DTRN = Open(), + o_UART1_OUT1N = Open(), + o_UART1_OUT2N = Open(), + + # UART2. + o_UART2_TXD = Open(), + o_UART2_RTSN = Open(), + i_UART2_RXD = 0, + i_UART2_CTSN = 1, + i_UART2_DCDN = 1, + i_UART2_DSRN = 1, + i_UART2_RIN = 1, + o_UART2_DTRN = Open(), + o_UART2_OUT1N = Open(), + o_UART2_OUT2N = Open(), + + # JTAG. + i_DBG_TCK = 1, + i_TMS_IN = 1, + i_TRST_IN = 1, + i_TDI_IN = 0, + o_TDO_OUT = Open(), + o_TDO_OE = Open(), + + # Test. + i_TEST_CLK = 0, + i_TEST_MODE = 0, + i_TEST_RSTN = 1, + ) + + # AHBLite ROM Interface. + # ---------------------- + self.submodules += ahb.AHB2Wishbone(ahb_rom, self.ibus) + + # AHBLite RAM Interface. + # ---------------------- + self.submodules += ahb.AHB2Wishbone(ahb_ram, self.dbus) + + # AHBLite Peripheral Interface. + # ----------------------------- + self.submodules += ahb.AHB2Wishbone(ahb_exts, self.pbus) + + def connect_jtag(self, pads): + self.cpu_params.update( + i_DBG_TCK = pads.tck, + i_TMS_IN = pads.tms, + i_TRST_IN = pads.trst, + i_TDI_IN = pads.tdi, + o_TDO_OUT = pads.tdo, + o_TDO_OE = Open(), + ) + + def do_finalize(self): + self.specials += Instance("AE350_SOC", **self.cpu_params) diff --git a/litex/soc/cores/cpu/gowin_ae350/crt0.S b/litex/soc/cores/cpu/gowin_ae350/crt0.S new file mode 100644 index 000000000..13bfc48e9 --- /dev/null +++ b/litex/soc/cores/cpu/gowin_ae350/crt0.S @@ -0,0 +1,75 @@ +#define MIE_MEIE 0x800 + + .global _start +_start: + j reset_vector + +reset_vector: + la sp, _fstack + la t0, trap_vector + csrw mtvec, t0 + + // initialize .data + la t0, _fdata + la t1, _edata + la t2, _fdata_rom +1: beq t0, t1, 2f + lw t3, 0(t2) + sw t3, 0(t0) + addi t0, t0, 4 + addi t2, t2, 4 + j 1b +2: + + // initialize .bss + la t0, _fbss + la t1, _ebss +1: beq t0, t1, 3f + sw zero, 0(t0) + addi t0, t0, 4 + j 1b +3: + // enable external interrupts + li t0, MIE_MEIE + csrs mie, t0 + + call main +1: j 1b + +trap_vector: + addi sp, sp, -16*4 + sw ra, 0*4(sp) + sw t0, 1*4(sp) + sw t1, 2*4(sp) + sw t2, 3*4(sp) + sw a0, 4*4(sp) + sw a1, 5*4(sp) + sw a2, 6*4(sp) + sw a3, 7*4(sp) + sw a4, 8*4(sp) + sw a5, 9*4(sp) + sw a6, 10*4(sp) + sw a7, 11*4(sp) + sw t3, 12*4(sp) + sw t4, 13*4(sp) + sw t5, 14*4(sp) + sw t6, 15*4(sp) + call isr + lw ra, 0*4(sp) + lw t0, 1*4(sp) + lw t1, 2*4(sp) + lw t2, 3*4(sp) + lw a0, 4*4(sp) + lw a1, 5*4(sp) + lw a2, 6*4(sp) + lw a3, 7*4(sp) + lw a4, 8*4(sp) + lw a5, 9*4(sp) + lw a6, 10*4(sp) + lw a7, 11*4(sp) + lw t3, 12*4(sp) + lw t4, 13*4(sp) + lw t5, 14*4(sp) + lw t6, 15*4(sp) + addi sp, sp, 16*4 + mret diff --git a/litex/soc/cores/cpu/gowin_ae350/irq.h b/litex/soc/cores/cpu/gowin_ae350/irq.h new file mode 100644 index 000000000..7374cf506 --- /dev/null +++ b/litex/soc/cores/cpu/gowin_ae350/irq.h @@ -0,0 +1,4 @@ +#ifndef __IRQ_H +#define __IRQ_H + +#endif /* __IRQ_H */ diff --git a/litex/soc/cores/cpu/gowin_ae350/system.h b/litex/soc/cores/cpu/gowin_ae350/system.h new file mode 100644 index 000000000..c27fc4da8 --- /dev/null +++ b/litex/soc/cores/cpu/gowin_ae350/system.h @@ -0,0 +1,19 @@ +#ifndef __SYSTEM_H +#define __SYSTEM_H + +#ifdef __cplusplus +extern "C" { +#endif + +__attribute__((unused)) static void flush_cpu_icache(void){}; /* FIXME */ +__attribute__((unused)) static void flush_cpu_dcache(void){}; /* FIXME */ +void flush_l2_cache(void); + +void busy_wait(unsigned int ms); +void busy_wait_us(unsigned int us); + +#ifdef __cplusplus +} +#endif + +#endif /* __SYSTEM_H */ diff --git a/litex/soc/software/bios/main.c b/litex/soc/software/bios/main.c index a39caafd3..67ca3d590 100644 --- a/litex/soc/software/bios/main.c +++ b/litex/soc/software/bios/main.c @@ -125,7 +125,11 @@ __attribute__((__used__)) int main(int i, char **c) printf("--=============== \e[1mSoC\e[0m ==================--\n"); printf("\e[1mCPU\e[0m:\t\t%s @ %dMHz\n", CONFIG_CPU_HUMAN_NAME, +#ifdef CONFIG_CPU_CLK_FREQ + CONFIG_CPU_CLK_FREQ/1000000); +#else CONFIG_CLOCK_FREQUENCY/1000000); +#endif printf("\e[1mBUS\e[0m:\t\t%s %d-bit @ %dGiB\n", CONFIG_BUS_STANDARD, CONFIG_BUS_DATA_WIDTH, From 6b79644108a49411c20a982441a2f908fda32852 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Thu, 11 Jan 2024 13:53:15 +0100 Subject: [PATCH 40/78] cores/cpu/gowin_emcu: Switch to LiteX's UART. A UART does not cost that much ressources and this avoid specific code/allow simplifying support. --- litex/soc/cores/cpu/gowin_emcu/core.py | 8 ---- litex/soc/cores/cpu/gowin_emcu/crt0.c | 3 -- litex/soc/cores/cpu/gowin_emcu/system.h | 52 ------------------------- 3 files changed, 63 deletions(-) diff --git a/litex/soc/cores/cpu/gowin_emcu/core.py b/litex/soc/cores/cpu/gowin_emcu/core.py index dcc38edc0..d9ba87858 100644 --- a/litex/soc/cores/cpu/gowin_emcu/core.py +++ b/litex/soc/cores/cpu/gowin_emcu/core.py @@ -251,14 +251,6 @@ class GowinEMCU(CPU): # --------------------------------- self.submodules += ahb.AHB2Wishbone(ahb_targexp0, self.pbus) - def connect_uart(self, pads, n=0): - assert n in (0, 1), "this CPU has 2 built-in UARTs, 0 and 1" - self.cpu_params.update({ - f"i_UART{n}RXDI" : pads.rx, - f"o_UART{n}TXDO" : pads.tx, - f"o_UART{n}BAUDTICK" : Signal() - }) - def connect_jtag(self, pads): self.cpu_params.update( i_DAPSWDITMS = pads.tms, diff --git a/litex/soc/cores/cpu/gowin_emcu/crt0.c b/litex/soc/cores/cpu/gowin_emcu/crt0.c index cafc474c8..54415dad1 100644 --- a/litex/soc/cores/cpu/gowin_emcu/crt0.c +++ b/litex/soc/cores/cpu/gowin_emcu/crt0.c @@ -19,9 +19,6 @@ void _start(void) { for (uint32_t *x = &_fbss; x < &_ebss; x ++) *x = 0; - UART0->ctrl = 0b11; // set rx and tx enable bits - UART0->baud_div = CONFIG_CLOCK_FREQUENCY / 115200; // FIXME - __asm__("bl main"); while(1); } diff --git a/litex/soc/cores/cpu/gowin_emcu/system.h b/litex/soc/cores/cpu/gowin_emcu/system.h index c7a14e816..262446a62 100644 --- a/litex/soc/cores/cpu/gowin_emcu/system.h +++ b/litex/soc/cores/cpu/gowin_emcu/system.h @@ -12,58 +12,6 @@ void flush_l2_cache(void); void busy_wait(unsigned int ms); void busy_wait_us(unsigned int us); -#include - -// FIXME -#define CSR_UART_BASE - -struct EMCU_UART -{ - volatile uint32_t data; - volatile uint32_t state; - volatile uint32_t ctrl; - volatile uint32_t int_ctrl; - volatile uint32_t baud_div; -}; - -#define PERIPHERALS_BASE 0x40000000 -#define UART0 ((struct EMCU_UART *) (PERIPHERALS_BASE + 0x4000)) - -static inline char uart_txfull_read(void); -static inline char uart_rxempty_read(void); -static inline void uart_ev_enable_write(char c); -static inline void uart_rxtx_write(char c); -static inline char uart_rxtx_read(void); -static inline void uart_ev_pending_write(char); -static inline char uart_ev_pending_read(void); - -static inline char uart_txfull_read(void) { - return UART0->state & 0b01; -} - -static inline char uart_rxempty_read(void) { - return !(UART0->state & 0b10); -} - -static inline void uart_ev_enable_write(char c) { - // FIXME -} - -static inline void uart_rxtx_write(char c) { - UART0->data = (uint32_t) c; -} - -static inline char uart_rxtx_read(void) -{ - return (char)(UART0->data); -} - -static inline void uart_ev_pending_write(char x) {} -static inline char uart_ev_pending_read(void) { - return 0; -} - - #ifdef __cplusplus } #endif From b19d992f231699f1ac7d07b73a15deb400d23b59 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Mon, 15 Jan 2024 11:40:25 +0100 Subject: [PATCH 41/78] inteconnect/ahb: Add specific case for 32-bit data width, fix CSR accesses with gowin_ae350. --- litex/soc/interconnect/ahb.py | 81 ++++++++++++++++++++++------------- 1 file changed, 52 insertions(+), 29 deletions(-) diff --git a/litex/soc/interconnect/ahb.py b/litex/soc/interconnect/ahb.py index cee3540cd..178eeb346 100644 --- a/litex/soc/interconnect/ahb.py +++ b/litex/soc/interconnect/ahb.py @@ -61,39 +61,62 @@ class AHB2Wishbone(LiteXModule): "word" : log2_int(ahb.data_width//8), "byte" : 0 }[wishbone.addressing] + assert ahb.data_width in [32, 64] assert ahb.data_width == wishbone.data_width assert ahb.address_width == wishbone.adr_width + wishbone_adr_shift def wishbone_sel_decoder(ahb_size, ahb_addr): - wishbone_sel = Signal(8) - self.comb += Case(ahb_size, { - # 8-bit access. - 0b00 : Case(ahb_addr[0:3], { - 0b000 : wishbone_sel.eq(0b0000_0001), - 0b001 : wishbone_sel.eq(0b0000_0010), - 0b010 : wishbone_sel.eq(0b0000_0100), - 0b011 : wishbone_sel.eq(0b0000_1000), - 0b100 : wishbone_sel.eq(0b0001_0000), - 0b101 : wishbone_sel.eq(0b0010_0000), - 0b110 : wishbone_sel.eq(0b0100_0000), - 0b111 : wishbone_sel.eq(0b1000_0000), - }), - # 16-bit access. - 0b01 : Case(ahb_addr[1:3], { - 0b00 : wishbone_sel.eq(0b0000_0011), - 0b01 : wishbone_sel.eq(0b0000_1100), - 0b10 : wishbone_sel.eq(0b0011_0000), - 0b11 : wishbone_sel.eq(0b1100_0000), - }), - # 32-bit access. - 0b10 : Case(ahb_addr[2:3], { - 0b0 : wishbone_sel.eq(0b0000_1111), - 0b1 : wishbone_sel.eq(0b1111_0000), - }), - # 64-bit access. - 0b11 : wishbone_sel.eq(0b1111_1111), - }) - return wishbone_sel + if ahb.data_width == 64: + wishbone_sel = Signal(8) + self.comb += Case(ahb_size, { + # 8-bit access. + 0b00 : Case(ahb_addr[0:3], { + 0b000 : wishbone_sel.eq(0b0000_0001), + 0b001 : wishbone_sel.eq(0b0000_0010), + 0b010 : wishbone_sel.eq(0b0000_0100), + 0b011 : wishbone_sel.eq(0b0000_1000), + 0b100 : wishbone_sel.eq(0b0001_0000), + 0b101 : wishbone_sel.eq(0b0010_0000), + 0b110 : wishbone_sel.eq(0b0100_0000), + 0b111 : wishbone_sel.eq(0b1000_0000), + }), + # 16-bit access. + 0b01 : Case(ahb_addr[1:3], { + 0b00 : wishbone_sel.eq(0b0000_0011), + 0b01 : wishbone_sel.eq(0b0000_1100), + 0b10 : wishbone_sel.eq(0b0011_0000), + 0b11 : wishbone_sel.eq(0b1100_0000), + }), + # 32-bit access. + 0b10 : Case(ahb_addr[2:3], { + 0b0 : wishbone_sel.eq(0b0000_1111), + 0b1 : wishbone_sel.eq(0b1111_0000), + }), + # 64-bit access. + 0b11 : wishbone_sel.eq(0b1111_1111), + }) + return wishbone_sel + if ahb.data_width == 32: + wishbone_sel = Signal(4) + self.comb += Case(ahb_size, { + # 8-bit access. + 0b00 : Case(ahb_addr[0:2], { + 0b00 : wishbone_sel.eq(0b0001), + 0b01 : wishbone_sel.eq(0b0010), + 0b10 : wishbone_sel.eq(0b0100), + 0b11 : wishbone_sel.eq(0b1000), + }), + # 16-bit access. + 0b01 : Case(ahb_addr[1:2], { + 0b0 : wishbone_sel.eq(0b0011), + 0b1 : wishbone_sel.eq(0b1100), + }), + # 32-bit access. + 0b10 : wishbone_sel.eq(0b1111), + # 64-bit access (Should not happen but do a full 32-bit access). + 0b11 : wishbone_sel.eq(0b1111), + }) + return wishbone_sel # FSM. self.fsm = fsm = FSM() From 4222a585c920c516edec6873145356966bc6e0df Mon Sep 17 00:00:00 2001 From: Gwenhael Goavec-Merou Date: Thu, 18 Jan 2024 15:04:09 +0100 Subject: [PATCH 42/78] soc/cores/cpu/naxriscv/core: fix arch definition --- litex/soc/cores/cpu/naxriscv/core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/litex/soc/cores/cpu/naxriscv/core.py b/litex/soc/cores/cpu/naxriscv/core.py index 294974b2e..da2376258 100755 --- a/litex/soc/cores/cpu/naxriscv/core.py +++ b/litex/soc/cores/cpu/naxriscv/core.py @@ -69,7 +69,7 @@ class NaxRiscv(CPU): # Arch. @staticmethod def get_arch(): - arch = f"rv{NaxRiscv.xlen}ima" + arch = f"rv{NaxRiscv.xlen}i2p0_ma" if NaxRiscv.with_fpu: arch += "fd" if NaxRiscv.with_rvc: From f00d49211b7e54c5e90dd487bc1fea86f762494a Mon Sep 17 00:00:00 2001 From: Gwenhael Goavec-Merou Date: Thu, 18 Jan 2024 15:21:37 +0100 Subject: [PATCH 43/78] soc/cores/cpu/naxriscv/core: force go back previous directory after git clone --- litex/soc/cores/cpu/naxriscv/core.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/litex/soc/cores/cpu/naxriscv/core.py b/litex/soc/cores/cpu/naxriscv/core.py index da2376258..ca644ac80 100755 --- a/litex/soc/cores/cpu/naxriscv/core.py +++ b/litex/soc/cores/cpu/naxriscv/core.py @@ -302,10 +302,12 @@ class NaxRiscv(CPU): ), shell=True) # Use specific SHA1 (Optional). print(f"Updating {name} Git repository...") + cwd = os.getcwd() 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 submodule init && git pull --recurse-submodules {checkout_cmd}", shell=True) + os.chdir(cwd) # Netlist Generation. @staticmethod From 854541d5c7b2c726ee331711a442af6d91d646ff Mon Sep 17 00:00:00 2001 From: Gwenhael Goavec-Merou Date: Fri, 19 Jan 2024 07:37:55 +0100 Subject: [PATCH 44/78] soc/cores/cpu/naxriscv/core: adding argument to enable rvc extension --- litex/soc/cores/cpu/naxriscv/core.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/litex/soc/cores/cpu/naxriscv/core.py b/litex/soc/cores/cpu/naxriscv/core.py index ca644ac80..a052dc6b2 100755 --- a/litex/soc/cores/cpu/naxriscv/core.py +++ b/litex/soc/cores/cpu/naxriscv/core.py @@ -115,6 +115,7 @@ class NaxRiscv(CPU): 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("--no-netlist-cache", action="store_true", help="Always (re-)build the netlist.") cpu_group.add_argument("--with-fpu", action="store_true", help="Enable the F32/F64 FPU.") + cpu_group.add_argument("--with-rvc", action="store_true", help="Enable the Compress ISA extension.") cpu_group.add_argument("--l2-bytes", default=128*1024, help="NaxRiscv L2 bytes, default 128 KB.") cpu_group.add_argument("--l2-ways", default=8, help="NaxRiscv L2 ways, default 8.") @@ -127,6 +128,7 @@ class NaxRiscv(CPU): NaxRiscv.update_repo = args.update_repo NaxRiscv.no_netlist_cache = args.no_netlist_cache NaxRiscv.with_fpu = args.with_fpu + NaxRiscv.with_rvc = args.with_rvc if args.scala_file: NaxRiscv.scala_files = args.scala_file if args.scala_args: @@ -344,6 +346,8 @@ class NaxRiscv(CPU): gen_args.append(f"--scala-file={file}") if(NaxRiscv.with_fpu): gen_args.append(f"--scala-args=rvf=true,rvd=true") + if(NaxRiscv.with_rvc): + gen_args.append(f"--scala-args=rvc=true") cmd = f"""cd {ndir} && sbt "runMain naxriscv.platform.litex.NaxGen {" ".join(gen_args)}\"""" print("NaxRiscv generation command :") From bb62f7aa63a6e1eb4ffd5658ff0b4849442a182e Mon Sep 17 00:00:00 2001 From: Gwenhael Goavec-Merou Date: Mon, 22 Jan 2024 18:27:17 +0100 Subject: [PATCH 45/78] soc/cores/cpu/vexriscv_smp/core: allowing configure CSR/CLINT/PLIC base address by overriding default value or using args --- litex/soc/cores/cpu/vexriscv_smp/core.py | 61 ++++++++++++++---------- 1 file changed, 35 insertions(+), 26 deletions(-) diff --git a/litex/soc/cores/cpu/vexriscv_smp/core.py b/litex/soc/cores/cpu/vexriscv_smp/core.py index 4031dc70a..62bf0bf6c 100755 --- a/litex/soc/cores/cpu/vexriscv_smp/core.py +++ b/litex/soc/cores/cpu/vexriscv_smp/core.py @@ -57,32 +57,38 @@ class VexRiscvSMP(CPU): with_rvc = False dtlb_size = 4 itlb_size = 4 + csr_base = 0xf000_0000 + clint_base = 0xf001_0000 + plic_base = 0xf0c0_0000 # Command line configuration arguments. @staticmethod def args_fill(parser): cpu_group = parser.add_argument_group(title="CPU options") - cpu_group.add_argument("--cpu-count", default=1, help="Number of CPU(s) in the cluster.", type=int) - cpu_group.add_argument("--with-coherent-dma", action="store_true", help="Enable Coherent DMA Slave interface.") - cpu_group.add_argument("--without-coherent-dma", action="store_true", help="Disable Coherent DMA Slave interface.") - cpu_group.add_argument("--dcache-width", default=None, help="L1 data cache bus width.") - cpu_group.add_argument("--icache-width", default=None, help="L1 instruction cache bus width.") - cpu_group.add_argument("--dcache-size", default=None, help="L1 data cache size in byte per CPU.") - cpu_group.add_argument("--dcache-ways", default=None, help="L1 data cache ways per CPU.") - cpu_group.add_argument("--icache-size", default=None, help="L1 instruction cache size in byte per CPU.") - cpu_group.add_argument("--icache-ways", default=None, help="L1 instruction cache ways per CPU") - cpu_group.add_argument("--aes-instruction", default=None, help="Enable AES instruction acceleration.") - cpu_group.add_argument("--without-out-of-order-decoder", action="store_true", help="Reduce area at cost of peripheral access speed") - cpu_group.add_argument("--with-wishbone-memory", action="store_true", help="Disable native LiteDRAM interface") - cpu_group.add_argument("--with-privileged-debug", action="store_true", help="Enable official RISC-V debug spec") - cpu_group.add_argument("--hardware-breakpoints", default=1, help="Number of hardware breapoints", type=int) - cpu_group.add_argument("--wishbone-force-32b", action="store_true", help="Force the wishbone bus to be 32 bits") - cpu_group.add_argument("--with-fpu", action="store_true", help="Enable the F32/F64 FPU") - cpu_group.add_argument("--cpu-per-fpu", default="4", help="Maximal ratio between CPU count and FPU count. Will instanciate as many FPU as necessary.") - cpu_group.add_argument("--with-rvc", action="store_true", help="Enable RISC-V compressed instruction support") - cpu_group.add_argument("--dtlb-size", default=4, help="Data TLB size.") - cpu_group.add_argument("--itlb-size", default=4, help="Instruction TLB size.") - cpu_group.add_argument("--expose-time", action="store_true", help="Add CLINT time output.") + cpu_group.add_argument("--cpu-count", default=1, help="Number of CPU(s) in the cluster.", type=int) + cpu_group.add_argument("--with-coherent-dma", action="store_true", help="Enable Coherent DMA Slave interface.") + cpu_group.add_argument("--without-coherent-dma", action="store_true", help="Disable Coherent DMA Slave interface.") + cpu_group.add_argument("--dcache-width", default=None, help="L1 data cache bus width.") + cpu_group.add_argument("--icache-width", default=None, help="L1 instruction cache bus width.") + cpu_group.add_argument("--dcache-size", default=None, help="L1 data cache size in byte per CPU.") + cpu_group.add_argument("--dcache-ways", default=None, help="L1 data cache ways per CPU.") + cpu_group.add_argument("--icache-size", default=None, help="L1 instruction cache size in byte per CPU.") + cpu_group.add_argument("--icache-ways", default=None, help="L1 instruction cache ways per CPU") + cpu_group.add_argument("--aes-instruction", default=None, help="Enable AES instruction acceleration.") + cpu_group.add_argument("--without-out-of-order-decoder", action="store_true", help="Reduce area at cost of peripheral access speed") + cpu_group.add_argument("--with-wishbone-memory", action="store_true", help="Disable native LiteDRAM interface") + cpu_group.add_argument("--with-privileged-debug", action="store_true", help="Enable official RISC-V debug spec") + cpu_group.add_argument("--hardware-breakpoints", default=1, help="Number of hardware breapoints", type=int) + cpu_group.add_argument("--wishbone-force-32b", action="store_true", help="Force the wishbone bus to be 32 bits") + cpu_group.add_argument("--with-fpu", action="store_true", help="Enable the F32/F64 FPU") + cpu_group.add_argument("--cpu-per-fpu", default="4", help="Maximal ratio between CPU count and FPU count. Will instanciate as many FPU as necessary.") + cpu_group.add_argument("--with-rvc", action="store_true", help="Enable RISC-V compressed instruction support") + cpu_group.add_argument("--dtlb-size", default=4, help="Data TLB size.") + cpu_group.add_argument("--itlb-size", default=4, help="Instruction TLB size.") + cpu_group.add_argument("--expose-time", action="store_true", help="Add CLINT time output.") + cpu_group.add_argument("--csr-base", default="0xf0000000", help="CSR base address.") + cpu_group.add_argument("--clint-base", default="0xf0010000", help="CLINT base address.") + cpu_group.add_argument("--plic-base", default="0xf0c00000", help="PLIC base address.") @staticmethod def args_read(args): @@ -118,8 +124,11 @@ class VexRiscvSMP(CPU): VexRiscvSMP.cpu_per_fpu = args.cpu_per_fpu if(args.with_rvc): VexRiscvSMP.with_rvc = True - if(args.dtlb_size): VexRiscvSMP.dtlb_size = int(args.dtlb_size) - if(args.itlb_size): VexRiscvSMP.itlb_size = int(args.itlb_size) + if(args.dtlb_size): VexRiscvSMP.dtlb_size = int(args.dtlb_size) + if(args.itlb_size): VexRiscvSMP.itlb_size = int(args.itlb_size) + if(args.csr_base): VexRiscvSMP.csr_base = int(args.csr_base, 16) + if(args.clint_base): VexRiscvSMP.clint_base = int(args.clint_base, 16) + if(args.plic_base): VexRiscvSMP.plic_base = int(args.plic_base, 16) # ABI. @staticmethod @@ -146,9 +155,9 @@ class VexRiscvSMP(CPU): "rom": 0x0000_0000, "sram": 0x1000_0000, "main_ram": 0x4000_0000, - "csr": 0xf000_0000, - "clint": 0xf001_0000, - "plic": 0xf0c0_0000, + "csr": VexRiscvSMP.csr_base, + "clint": VexRiscvSMP.clint_base, + "plic": VexRiscvSMP.plic_base, } # GCC Flags. From c31ec799811419e8b4bf8a1a171904d8d39cbf0e Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Tue, 23 Jan 2024 16:02:11 +0100 Subject: [PATCH 46/78] CHANGES.md: Update. --- CHANGES.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 9efb5d1ee..e51a6ce7a 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -12,6 +12,9 @@ - interconnect/ahb : Added data_width/address_width parameters. - interconnect/ahb : Added proper byte/sel support to AHB2Wishbone. - cpu/gowin_ae350 : Added initial support. + - cpu/naxriscv : Updated arch definition and added rvc configuration parameters. + - cpu/vexriscv_smp : Added csr/clint/plic base address configuration parameters. + - liteeth/phy : Added 7-Series/Ultrascale(+) 2500BaseX PHYs. [> Changed ---------- From bcde71b051b7c13289e85f01c69dd54a6dc77df5 Mon Sep 17 00:00:00 2001 From: Gwenhael Goavec-Merou Date: Wed, 24 Jan 2024 14:59:45 +0100 Subject: [PATCH 47/78] soc/integration/soc: add_etherbone: allowing to specify local/remote IP --- litex/soc/integration/soc.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/litex/soc/integration/soc.py b/litex/soc/integration/soc.py index dbce3a988..f637f6c6f 100644 --- a/litex/soc/integration/soc.py +++ b/litex/soc/integration/soc.py @@ -1726,7 +1726,9 @@ class LiteXSoC(SoC): nrxslots = 2, rxslots_read_only = True, ntxslots = 2, txslots_write_only = False, with_timestamp = False, - with_timing_constraints = True): + with_timing_constraints = True, + local_ip = None, + remote_ip = None): # Imports from liteeth.mac import LiteEthMAC from liteeth.phy.model import LiteEthPHYModel @@ -1764,8 +1766,23 @@ class LiteXSoC(SoC): # Dynamic IP (if enabled). if dynamic_ip: + assert local_ip is None self.add_constant("ETH_DYNAMIC_IP") + if local_ip: + local_ip = local_ip.split(".") + self.add_constant("LOCALIP1", int(local_ip[0])) + self.add_constant("LOCALIP2", int(local_ip[1])) + self.add_constant("LOCALIP3", int(local_ip[2])) + self.add_constant("LOCALIP4", int(local_ip[3])) + + if remote_ip: + remote_ip = remote_ip.split(".") + self.add_constant("REMOTEIP1", int(remote_ip[0])) + self.add_constant("REMOTEIP2", int(remote_ip[1])) + self.add_constant("REMOTEIP3", int(remote_ip[2])) + self.add_constant("REMOTEIP4", int(remote_ip[3])) + # Software Debug if software_debug: self.add_constant("ETH_UDP_TX_DEBUG") From f543b18d026a83b6ede61d3fa36b91821810643f Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Wed, 24 Jan 2024 15:28:18 +0100 Subject: [PATCH 48/78] soc/add_ethernet: Refactor local/remote_ip configuration and add basic checks for IP address length + validity. --- litex/soc/integration/soc.py | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/litex/soc/integration/soc.py b/litex/soc/integration/soc.py index f637f6c6f..cc09c8e8c 100644 --- a/litex/soc/integration/soc.py +++ b/litex/soc/integration/soc.py @@ -1769,19 +1769,17 @@ class LiteXSoC(SoC): assert local_ip is None self.add_constant("ETH_DYNAMIC_IP") + # Local/Remote IP Configuration (optional). + def add_ip_constants(name, ip): + _ip = ip.split(".") + assert len(_ip) == 4 + for n in range(4): + assert int(_ip[n]) < 256 + self.add_constant(f"{name}{n+1}", _ip[n]) if local_ip: - local_ip = local_ip.split(".") - self.add_constant("LOCALIP1", int(local_ip[0])) - self.add_constant("LOCALIP2", int(local_ip[1])) - self.add_constant("LOCALIP3", int(local_ip[2])) - self.add_constant("LOCALIP4", int(local_ip[3])) - + add_ip_constants("LOCALIP", local_ip) if remote_ip: - remote_ip = remote_ip.split(".") - self.add_constant("REMOTEIP1", int(remote_ip[0])) - self.add_constant("REMOTEIP2", int(remote_ip[1])) - self.add_constant("REMOTEIP3", int(remote_ip[2])) - self.add_constant("REMOTEIP4", int(remote_ip[3])) + add_ip_constants("REMOTEIP", remote_ip) # Software Debug if software_debug: From d32095540abe105fea73fc7e2d4127dc69bb2815 Mon Sep 17 00:00:00 2001 From: Gwenhael Goavec-Merou Date: Wed, 24 Jan 2024 16:06:44 +0100 Subject: [PATCH 49/78] soc/integration/soc: add_ethernet/add_ip_constants: cast str to int (avoid double quote in soc.h --- litex/soc/integration/soc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/litex/soc/integration/soc.py b/litex/soc/integration/soc.py index cc09c8e8c..442ba3176 100644 --- a/litex/soc/integration/soc.py +++ b/litex/soc/integration/soc.py @@ -1775,7 +1775,7 @@ class LiteXSoC(SoC): assert len(_ip) == 4 for n in range(4): assert int(_ip[n]) < 256 - self.add_constant(f"{name}{n+1}", _ip[n]) + self.add_constant(f"{name}{n+1}", int(_ip[n])) if local_ip: add_ip_constants("LOCALIP", local_ip) if remote_ip: From 245bed719559bb93960e910ec0f98ff63288bbad Mon Sep 17 00:00:00 2001 From: Gwenhael Goavec-Merou Date: Thu, 25 Jan 2024 17:39:12 +0100 Subject: [PATCH 50/78] soc/cores/clock/efinix: fix input clock code for trion when the input clock comes from another PLL --- litex/soc/cores/clock/efinix.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/litex/soc/cores/clock/efinix.py b/litex/soc/cores/clock/efinix.py index d71197107..63cca6839 100644 --- a/litex/soc/cores/clock/efinix.py +++ b/litex/soc/cores/clock/efinix.py @@ -88,7 +88,7 @@ class EFINIXPLL(LiteXModule): self.logger.info("Clock source: {}, using EXT_CLK{}".format(block["input_clock"], clock_no)) self.platform.get_pll_resource(pll_res) else: - block["input_clock"] = "INTERNAL" + block["input_clock"] = "INTERNAL" if self.type == "TITANIUMPLL" else "CORE" block["resource"] = self.platform.get_free_pll_resource() block["input_signal"] = name self.logger.info("Clock source: {}".format(block["input_clock"])) From 488247e4f7bbbe17b01cc1f9bc4e5772586b85e8 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Tue, 30 Jan 2024 09:44:52 +0100 Subject: [PATCH 51/78] build/efinix/programmer: Define EFXDBG_HOME now required by latest Efinity versions. --- litex/build/efinix/programmer.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/litex/build/efinix/programmer.py b/litex/build/efinix/programmer.py index 1b91863b4..1c42a0c9f 100644 --- a/litex/build/efinix/programmer.py +++ b/litex/build/efinix/programmer.py @@ -28,7 +28,8 @@ class EfinixProgrammer(GenericProgrammer): os.environ["EFINITY_HOME"] = self.efinity_path def load_bitstream(self, bitstream_file, cable_suffix=""): - os.environ['EFXPGM_HOME'] = self.efinity_path + '/pgm' + os.environ['EFXPGM_HOME'] = self.efinity_path + "/pgm" + os.environ["EFXDBG_HOME"] = self.efinity_path + "/debugger" if (subprocess.call([self.efinity_path + '/bin/python3', self.efinity_path + '/pgm/bin/efx_pgm/ftdi_program.py', bitstream_file, "-m", "jtag"], env=os.environ.copy()) != 0): From a3904ac26d595c0e86357697697c873b4f3ad1ba Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Tue, 30 Jan 2024 09:51:05 +0100 Subject: [PATCH 52/78] CHANGES.md: Update. --- CHANGES.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index e51a6ce7a..769675550 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -3,7 +3,9 @@ [> Fixed -------- - integration/soc : Fixed typo in cpu mem_bus axi-via-wb downconvert - - interconnect/ahb/AHB2Wishbone : Fix size check that was too restrictive. + - interconnect/ahb/AHB2Wishbone : Fixed size check that was too restrictive. + - liteeth/phy/gw5rgmii : Fixed Clk assignments. + - build/efinix/programmer : Updated for compatibility with latest Efinity versions. [> Added -------- From f73fbee309b6c8c98e6cc0cd236f8ca87311c6fa Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Tue, 30 Jan 2024 10:56:55 +0100 Subject: [PATCH 53/78] cores/spi/spi_master: Improve documentation, especially on Raw/Aligned mode and CS control. --- litex/soc/cores/spi/spi_master.py | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/litex/soc/cores/spi/spi_master.py b/litex/soc/cores/spi/spi_master.py index 377cb4782..a7d42f9b7 100644 --- a/litex/soc/cores/spi/spi_master.py +++ b/litex/soc/cores/spi/spi_master.py @@ -1,7 +1,7 @@ # # This file is part of LiteX. # -# Copyright (c) 2019-2020 Florent Kermarrec +# Copyright (c) 2019-2024 Florent Kermarrec # SPDX-License-Identifier: BSD-2-Clause import math @@ -18,8 +18,26 @@ from litex.soc.interconnect.csr import * class SPIMaster(LiteXModule): """4-wire SPI Master - Provides a simple and minimal hardware SPI Master with CPOL=0, CPHA=0 and build time - configurable data_width and frequency. + Implements a 4-wire SPI Master with CPOL=0 and CPHA=0, tailored for FPGA designs. It allows + configurable data_width and SPI clock frequency at build time. Supports Raw and Aligned modes + for data transfer and software-controlled Chip Select (CS) for extended SPI operations. + + Parameters: + pads (Record) : Interface pads for SPI signals. If None, a default layout is used. + data_width (int) : Maximum Data width of SPI transactions. + sys_clk_freq (int) : System clock frequency in Hz. + spi_clk_freq (int) : Desired SPI clock frequency in Hz. + with_csr (bool, optional) : Enables CSR interface if True. + mode (str, optional) : 'raw' for as-is data transfer or 'aligned' for transaction length-based alignment. + + Modes: + Raw : MOSI data is aligned to the core's data-width. Optimal for data-width matching SPI transactions. + Aligned : MOSI data is aligned based on the transaction's length. Suitable for variable-length SPI transactions. + + CS Control: + Software-controlled CS is available for scenarios requiring precise control over CS assertion, like + SPI Flash page programming or when hardware CS lines are insufficient. It allows manual CS management, + enabling complex transaction sequences and extended device communication. """ pads_layout = [("clk", 1), ("cs_n", 1), ("mosi", 1), ("miso", 1)] def __init__(self, pads, data_width, sys_clk_freq, spi_clk_freq, with_csr=True, mode="raw"): From 4dae3a9f4da14aa602ffda87ac4c3d2682577ba1 Mon Sep 17 00:00:00 2001 From: Andrew Dennison Date: Mon, 29 Jan 2024 16:19:44 +1100 Subject: [PATCH 54/78] build/openfpgaloader: report command line on error Helps explain failures --- litex/build/openfpgaloader.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/litex/build/openfpgaloader.py b/litex/build/openfpgaloader.py index 8721dcfb9..21e704bf4 100644 --- a/litex/build/openfpgaloader.py +++ b/litex/build/openfpgaloader.py @@ -71,4 +71,8 @@ class OpenFPGALoader(GenericProgrammer): cmd.append(str(value)) # Execute Command. - self.call(cmd) + try: + self.call(cmd) + except OSError as e: + print(' '.join(cmd)) + raise From 08189663ba5e568d1667c8743af98adda4839e8e Mon Sep 17 00:00:00 2001 From: Andrew Dennison Date: Tue, 30 Jan 2024 17:15:45 +1100 Subject: [PATCH 55/78] soc/add_spi_flash: fix bios 1x mode support require both phy and flash support to enable QUAD/QPI capability. Many flash devices support 4x read but may be on a 1x phy --- 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 442ba3176..385e83da1 100644 --- a/litex/soc/integration/soc.py +++ b/litex/soc/integration/soc.py @@ -1909,10 +1909,11 @@ class LiteXSoC(SoC): self.add_constant(f"{name}_MODULE_NAME", module.name.upper()) self.add_constant(f"{name}_MODULE_TOTAL_SIZE", module.total_size) self.add_constant(f"{name}_MODULE_PAGE_SIZE", module.page_size) - if SpiNorFlashOpCodes.READ_1_1_4 in module.supported_opcodes: - self.add_constant(f"{name}_MODULE_QUAD_CAPABLE") - if SpiNorFlashOpCodes.READ_4_4_4 in module.supported_opcodes: - self.add_constant(f"{name}_MODULE_QPI_CAPABLE") + if mode in [ "4x" ]: + if SpiNorFlashOpCodes.READ_1_1_4 in module.supported_opcodes: + self.add_constant(f"{name}_MODULE_QUAD_CAPABLE") + if SpiNorFlashOpCodes.READ_4_4_4 in module.supported_opcodes: + self.add_constant(f"{name}_MODULE_QPI_CAPABLE") if software_debug: self.add_constant(f"{name}_DEBUG") From 1dddfa6841f9e40914f735d8d589d171096a24c0 Mon Sep 17 00:00:00 2001 From: Andrew Dennison Date: Thu, 1 Feb 2024 09:57:51 +1100 Subject: [PATCH 56/78] soc/add_spi_flash: fix default divisor and PHY_CLOCK calculation Ensure default_divisor is set to desired default - 1 as required by LiteSPIClkGen Calculate actual PHY_CLK based on default_divisor --- litex/soc/integration/soc.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/litex/soc/integration/soc.py b/litex/soc/integration/soc.py index 385e83da1..1031c43be 100644 --- a/litex/soc/integration/soc.py +++ b/litex/soc/integration/soc.py @@ -1884,17 +1884,21 @@ class LiteXSoC(SoC): from litespi import LiteSPI from litespi.phy.generic import LiteSPIPHY from litespi.opcodes import SpiNorFlashOpCodes + import math # Checks/Parameters. assert mode in ["1x", "4x"] if clk_freq is None: clk_freq = self.sys_clk_freq + # From LiteSPIClkGen: clk_freq will be ``sys_clk_freq/(2*(1+div))``. + default_divisor = math.ceil(self.sys_clk_freq/(clk_freq*2))-1 + clk_freq = int(self.sys_clk_freq/(2*(1+default_divisor))) # PHY. spiflash_phy = phy if spiflash_phy is None: self.check_if_exists(f"{name}_phy") spiflash_pads = self.platform.request(name if mode == "1x" else name + mode) - spiflash_phy = LiteSPIPHY(spiflash_pads, module, device=self.platform.device, default_divisor=int(self.sys_clk_freq/clk_freq), rate=rate) + spiflash_phy = LiteSPIPHY(spiflash_pads, module, device=self.platform.device, default_divisor=default_divisor, rate=rate) self.add_module(name=f"{name}_phy", module=spiflash_phy) # Core. From 51c3cb3552a8770c817ead7c1e87d477f384effb Mon Sep 17 00:00:00 2001 From: Andrew Dennison Date: Thu, 1 Feb 2024 10:01:15 +1100 Subject: [PATCH 57/78] soc/add_spi_flash: default clk_freq to 20MHz This is safer than defaulting to sys_clock / 2 if sys_clock > 100MHz clk_freq tuning will result in a faster clock if supported by hardware. --- litex/soc/integration/soc.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/litex/soc/integration/soc.py b/litex/soc/integration/soc.py index 1031c43be..16fba83ab 100644 --- a/litex/soc/integration/soc.py +++ b/litex/soc/integration/soc.py @@ -1879,7 +1879,7 @@ class LiteXSoC(SoC): self.add_constant("ETH_PHY_NO_RESET") # Disable reset from BIOS to avoid disabling Hardware Interface. # Add SPI Flash -------------------------------------------------------------------------------- - def add_spi_flash(self, name="spiflash", mode="4x", clk_freq=None, module=None, phy=None, rate="1:1", software_debug=False, **kwargs): + def add_spi_flash(self, name="spiflash", mode="4x", clk_freq=20e6, module=None, phy=None, rate="1:1", software_debug=False, **kwargs): # Imports. from litespi import LiteSPI from litespi.phy.generic import LiteSPIPHY @@ -1888,7 +1888,6 @@ class LiteXSoC(SoC): # Checks/Parameters. assert mode in ["1x", "4x"] - if clk_freq is None: clk_freq = self.sys_clk_freq # From LiteSPIClkGen: clk_freq will be ``sys_clk_freq/(2*(1+div))``. default_divisor = math.ceil(self.sys_clk_freq/(clk_freq*2))-1 clk_freq = int(self.sys_clk_freq/(2*(1+default_divisor))) From e0416639f762b4035e22b98ed61cb7fe713c2b7c Mon Sep 17 00:00:00 2001 From: Andrew Dennison Date: Thu, 1 Feb 2024 10:09:06 +1100 Subject: [PATCH 58/78] software/liblitespi/spiflash: fix reported flash clk --- litex/soc/software/liblitespi/spiflash.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/litex/soc/software/liblitespi/spiflash.c b/litex/soc/software/liblitespi/spiflash.c index 410c43948..e31f21410 100644 --- a/litex/soc/software/liblitespi/spiflash.c +++ b/litex/soc/software/liblitespi/spiflash.c @@ -46,13 +46,13 @@ int spiflash_freq_init(void) #endif } lowest_div++; - printf("SPI Flash clk configured to %d MHz\n", (SPIFLASH_PHY_FREQUENCY/(2*(1 + lowest_div)))/1000000); + printf("SPI Flash clk configured to %d MHz\n", CONFIG_CLOCK_FREQUENCY/(2*(1+lowest_div)*1000000)); spiflash_phy_clk_divisor_write(lowest_div); #else - printf("SPI Flash clk configured to %ld MHz\n", (unsigned long)(SPIFLASH_PHY_FREQUENCY/1e6)); + printf("SPI Flash clk configured to %ld MHz\n", SPIFLASH_PHY_FREQUENCY/1000000); #endif From 3a890a077b138d674f11841564db2042f6871827 Mon Sep 17 00:00:00 2001 From: Andrew Dennison Date: Thu, 1 Feb 2024 10:14:20 +1100 Subject: [PATCH 59/78] software/liblitespi/spiflash: fix clk_freq tuning with L2 cache Correct CRC was always calculated, regardless of divisor, as the test flash block was in the L2 cache. This resulted in the minimum divisor being used and incorrect flash reads with 200MHz sys_clock. --- litex/soc/software/liblitespi/spiflash.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/litex/soc/software/liblitespi/spiflash.c b/litex/soc/software/liblitespi/spiflash.c index e31f21410..987b7493e 100644 --- a/litex/soc/software/liblitespi/spiflash.c +++ b/litex/soc/software/liblitespi/spiflash.c @@ -25,6 +25,8 @@ int spiflash_freq_init(void) unsigned int lowest_div, crc, crc_test; lowest_div = spiflash_phy_clk_divisor_read(); + flush_cpu_dcache(); + flush_l2_cache(); crc = crc32((unsigned char *)SPIFLASH_BASE, SPI_FLASH_BLOCK_SIZE); crc_test = crc; @@ -40,6 +42,8 @@ int spiflash_freq_init(void) while((crc == crc_test) && (lowest_div-- > 0)) { spiflash_phy_clk_divisor_write((uint32_t)lowest_div); + flush_cpu_dcache(); + flush_l2_cache(); crc_test = crc32((unsigned char *)SPIFLASH_BASE, SPI_FLASH_BLOCK_SIZE); #ifdef SPIFLASH_DEBUG printf("[DIV: %d] %08x\n\r", lowest_div, crc_test); From de594e44c983abcb32ea56c35608dc77e293e82f Mon Sep 17 00:00:00 2001 From: Andrew Dennison Date: Thu, 1 Feb 2024 10:18:52 +1100 Subject: [PATCH 60/78] software/bios/cmds: fix crc command with L2 cache Same CRC was always reported if the memory region was in the cache... Noticed when manually testing spiflash divisor. --- litex/soc/software/bios/cmds/cmd_bios.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/litex/soc/software/bios/cmds/cmd_bios.c b/litex/soc/software/bios/cmds/cmd_bios.c index 2006dd540..5acf67140 100644 --- a/litex/soc/software/bios/cmds/cmd_bios.c +++ b/litex/soc/software/bios/cmds/cmd_bios.c @@ -115,6 +115,8 @@ static void crc_handler(int nb_params, char **params) return; } + flush_cpu_dcache(); + flush_l2_cache(); printf("CRC32: %08x", crc32((unsigned char *)addr, length)); } From afe7b939952d15672612716059b09f99edb0466e Mon Sep 17 00:00:00 2001 From: Andrew Dennison Date: Thu, 1 Feb 2024 10:22:46 +1100 Subject: [PATCH 61/78] software/liblitespi/spiflash: fix warnings --- litex/soc/software/liblitespi/spiflash.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/litex/soc/software/liblitespi/spiflash.c b/litex/soc/software/liblitespi/spiflash.c index 987b7493e..53bb936ef 100644 --- a/litex/soc/software/liblitespi/spiflash.c +++ b/litex/soc/software/liblitespi/spiflash.c @@ -1,6 +1,7 @@ // This file is Copyright (c) 2020 Antmicro // License: BSD +#include #include #include #include @@ -67,7 +68,7 @@ void spiflash_dummy_bits_setup(unsigned int dummy_bits) { spiflash_core_mmap_dummy_bits_write((uint32_t)dummy_bits); #ifdef SPIFLASH_DEBUG - printf("Dummy bits set to: %d\n\r", spiflash_core_mmap_dummy_bits_read()); + printf("Dummy bits set to: %" PRIx32 "\n\r", spiflash_core_mmap_dummy_bits_read()); #endif } @@ -111,7 +112,7 @@ static uint32_t transfer_byte(uint8_t b) return spiflash_core_master_rxtx_read(); } -static void transfer_cmd(uint8_t *bs, uint8_t *resp, int len) +static void transfer_cmd(volatile uint8_t *bs, volatile uint8_t *resp, int len) { spiflash_core_master_phyconfig_len_write(8); spiflash_core_master_phyconfig_width_write(1); @@ -174,7 +175,7 @@ static void page_program(uint32_t addr, uint8_t *data, int len) w_buf[1] = addr>>16; w_buf[2] = addr>>8; w_buf[3] = addr>>0; - memcpy(w_buf+4, data, len); + memcpy((void *)w_buf+4, (void *)data, len); transfer_cmd(w_buf, r_buf, len+4); } From fc85fdd178fa6711cb9055128fdc71df9ba86dd7 Mon Sep 17 00:00:00 2001 From: Andrew Dennison Date: Thu, 1 Feb 2024 15:51:30 +1100 Subject: [PATCH 62/78] build/openfpgaloader: support args with '-' many openfpgaloader args have a name with '-' as per normal convention. This kwarg now works: file_type="raw" --- litex/build/openfpgaloader.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/litex/build/openfpgaloader.py b/litex/build/openfpgaloader.py index 21e704bf4..8b41d3093 100644 --- a/litex/build/openfpgaloader.py +++ b/litex/build/openfpgaloader.py @@ -66,7 +66,7 @@ class OpenFPGALoader(GenericProgrammer): # Handle kwargs for specific, less common cases. for key, value in kwargs.items(): - cmd.append(f"--{key}") + cmd.append(f"--{key.replace('_', '-')}") if value is not None: cmd.append(str(value)) From e44631294a368a839df75c738409b29b1a4fda74 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Thu, 1 Feb 2024 08:34:17 +0100 Subject: [PATCH 63/78] CHANGES.md: Update. --- CHANGES.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 769675550..34b60119c 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -6,6 +6,7 @@ - interconnect/ahb/AHB2Wishbone : Fixed size check that was too restrictive. - liteeth/phy/gw5rgmii : Fixed Clk assignments. - build/efinix/programmer : Updated for compatibility with latest Efinity versions. + - litespi/software: : Fixed SPI Flash Clk Divider computation when with L2 Cache. [> Added -------- @@ -17,6 +18,8 @@ - cpu/naxriscv : Updated arch definition and added rvc configuration parameters. - cpu/vexriscv_smp : Added csr/clint/plic base address configuration parameters. - liteeth/phy : Added 7-Series/Ultrascale(+) 2500BaseX PHYs. + - litespi/sdrphy: : Allowed flash parameter to be None. + - litespi/integration : Improved integration and simplifications. [> Changed ---------- From e498a5669858936dd34c3681b4fa0617c2b6fa8a Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Thu, 1 Feb 2024 08:42:11 +0100 Subject: [PATCH 64/78] soc/add_spi_flash: Minor integration cleanup and remove PHY_FREQUENCY constants that is no longer used. --- litex/soc/integration/soc.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/litex/soc/integration/soc.py b/litex/soc/integration/soc.py index 16fba83ab..53c75a4fa 100644 --- a/litex/soc/integration/soc.py +++ b/litex/soc/integration/soc.py @@ -8,6 +8,7 @@ import os import sys +import math import time import logging import argparse @@ -1884,13 +1885,11 @@ class LiteXSoC(SoC): from litespi import LiteSPI from litespi.phy.generic import LiteSPIPHY from litespi.opcodes import SpiNorFlashOpCodes - import math # Checks/Parameters. assert mode in ["1x", "4x"] - # From LiteSPIClkGen: clk_freq will be ``sys_clk_freq/(2*(1+div))``. - default_divisor = math.ceil(self.sys_clk_freq/(clk_freq*2))-1 - clk_freq = int(self.sys_clk_freq/(2*(1+default_divisor))) + default_divisor = math.ceil(self.sys_clk_freq/(2*clk_freq)) - 1 + clk_freq = int(self.sys_clk_freq/(2*(default_divisor + 1))) # PHY. spiflash_phy = phy @@ -1908,7 +1907,6 @@ class LiteXSoC(SoC): self.bus.add_slave(name=name, slave=spiflash_core.bus, region=spiflash_region) # Constants. - self.add_constant(f"{name}_PHY_FREQUENCY", clk_freq) self.add_constant(f"{name}_MODULE_NAME", module.name.upper()) self.add_constant(f"{name}_MODULE_TOTAL_SIZE", module.total_size) self.add_constant(f"{name}_MODULE_PAGE_SIZE", module.page_size) From a59b67e4ee0bca90fc95b99b8d5dce55e29ebd01 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Thu, 1 Feb 2024 08:44:52 +0100 Subject: [PATCH 65/78] soc: Avoid .upper() on add_config/constant since already done in methods. --- litex/soc/integration/soc.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/litex/soc/integration/soc.py b/litex/soc/integration/soc.py index 53c75a4fa..ad63ce048 100644 --- a/litex/soc/integration/soc.py +++ b/litex/soc/integration/soc.py @@ -1247,7 +1247,7 @@ class SoC(LiteXModule, SoCCoreCompat): if hasattr(self, "ctrl") and self.bus.timeout is not None: if hasattr(self.ctrl, "bus_error") and hasattr(self.bus._interconnect, "timeout"): self.comb += self.ctrl.bus_error.eq(self.bus._interconnect.timeout.error) - self.add_config("BUS_STANDARD", self.bus.standard.upper()) + self.add_config("BUS_STANDARD", self.bus.standard) self.add_config("BUS_DATA_WIDTH", self.bus.data_width) self.add_config("BUS_ADDRESS_WIDTH", self.bus.address_width) self.add_config("BUS_BURSTING", int(self.bus.bursting)) @@ -1907,7 +1907,7 @@ class LiteXSoC(SoC): self.bus.add_slave(name=name, slave=spiflash_core.bus, region=spiflash_region) # Constants. - self.add_constant(f"{name}_MODULE_NAME", module.name.upper()) + self.add_constant(f"{name}_MODULE_NAME", module.name) self.add_constant(f"{name}_MODULE_TOTAL_SIZE", module.total_size) self.add_constant(f"{name}_MODULE_PAGE_SIZE", module.page_size) if mode in [ "4x" ]: From d9f006e123ed6991578466cf3740305cd4b6eb6b Mon Sep 17 00:00:00 2001 From: Andrew Dennison Date: Mon, 5 Feb 2024 10:38:24 +1100 Subject: [PATCH 66/78] litex/build/efinix: add spi_width Doesn't seem needed for Trion but probably essential for Titanium? --- litex/build/efinix/efinity.py | 2 +- litex/build/efinix/platform.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/litex/build/efinix/efinity.py b/litex/build/efinix/efinity.py index 04f6df610..5fdd4ea1f 100644 --- a/litex/build/efinix/efinity.py +++ b/litex/build/efinix/efinity.py @@ -361,7 +361,7 @@ class EfinityToolchain(GenericToolchain): "--io_weak_pullup", "on", "--enable_roms", "on", "--mode", self.platform.spi_mode, - "--width", "1", + "--width", self.platform.spi_width, "--enable_crc_check", "on" ], common.colors) if r != 0: diff --git a/litex/build/efinix/platform.py b/litex/build/efinix/platform.py index 1dc76fb90..52d1fc4cc 100644 --- a/litex/build/efinix/platform.py +++ b/litex/build/efinix/platform.py @@ -23,13 +23,14 @@ class EfinixPlatform(GenericPlatform): _supported_toolchains = ["efinity"] - def __init__(self, *args, iobank_info=None, toolchain="efinity", spi_mode="active", **kwargs): + def __init__(self, *args, iobank_info=None, toolchain="efinity", spi_mode="active", spi_width="1", **kwargs): GenericPlatform.__init__(self, *args, **kwargs) self.timing_model = self.device[-2:] self.device = self.device[:-2] self.iobank_info = iobank_info self.spi_mode = spi_mode + self.spi_width = spi_width if self.device[:2] == "Ti": self.family = "Titanium" else: From f81c940e7bb123d0fbc4c7eeacc01e8418a938c2 Mon Sep 17 00:00:00 2001 From: Andrew Dennison Date: Mon, 5 Feb 2024 10:40:04 +1100 Subject: [PATCH 67/78] litex/build/efinix: add binary output This is the file required for passive SPI loading. --- litex/build/efinix/efinity.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/litex/build/efinix/efinity.py b/litex/build/efinix/efinity.py index 5fdd4ea1f..2e0b79963 100644 --- a/litex/build/efinix/efinity.py +++ b/litex/build/efinix/efinity.py @@ -366,3 +366,14 @@ class EfinityToolchain(GenericToolchain): ], common.colors) if r != 0: raise OSError("Error occurred during efx_pgm execution.") + + # BINARY + os.environ['EFXPGM_HOME'] = self.efinity_path + "/pgm" + r = tools.subprocess_call_filtered([self.efinity_path + "/bin/python3", + self.efinity_path + "/pgm/bin/efx_pgm/export_bitstream.py", + "hex_to_bin", + f"{self._build_name}.hex", + f"{self._build_name}.bin" + ], common.colors) + if r != 0: + raise OSError("Error occurred during export_bitstream execution.") From 3127e504d3ae509317b801918813dbccb621197e Mon Sep 17 00:00:00 2001 From: Sylvain Munaut Date: Mon, 5 Feb 2024 11:45:34 +0100 Subject: [PATCH 68/78] soc/integration: Allow 0x400 CSR paging It's a convenient way to get more CSR locations without changing the whole address space layout (i.e. more space for CSR). It still leaves 256 full 32b registers in each location which I've never encountered a device even coming close to this, so it should be fairly safe to do. This doesn't change the default, just allow the user to select it. Signed-off-by: Sylvain Munaut --- litex/soc/integration/soc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/litex/soc/integration/soc.py b/litex/soc/integration/soc.py index ad63ce048..0f0b4edce 100644 --- a/litex/soc/integration/soc.py +++ b/litex/soc/integration/soc.py @@ -652,7 +652,7 @@ class SoCCSRHandler(SoCLocHandler): supported_data_width = [8, 32] supported_address_width = [14+i for i in range(4)] supported_alignment = [32] - supported_paging = [0x800*2**i for i in range(4)] + supported_paging = [0x400*2**i for i in range(5)] supported_ordering = ["big", "little"] # Creation ------------------------------------------------------------------------------------- From 57bc0369c728c3666f51c3da9281c122132ee594 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Mon, 5 Feb 2024 12:57:06 +0100 Subject: [PATCH 69/78] integration/soc/SocCSRHandler: Make supported_address_width/paging values explicit. --- litex/soc/integration/soc.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/litex/soc/integration/soc.py b/litex/soc/integration/soc.py index 0f0b4edce..22c1d50c5 100644 --- a/litex/soc/integration/soc.py +++ b/litex/soc/integration/soc.py @@ -650,9 +650,9 @@ class SoCLocHandler(LiteXModule): class SoCCSRHandler(SoCLocHandler): supported_data_width = [8, 32] - supported_address_width = [14+i for i in range(4)] + supported_address_width = [14, 15, 16, 17, 18] supported_alignment = [32] - supported_paging = [0x400*2**i for i in range(5)] + supported_paging = [0x400, 0x800, 0x1000, 0x2000, 0x4000] supported_ordering = ["big", "little"] # Creation ------------------------------------------------------------------------------------- From 13c57e8304d8c685268be67400a66a5f7c08c4a2 Mon Sep 17 00:00:00 2001 From: Gwenhael Goavec-Merou Date: Wed, 7 Feb 2024 07:20:31 +0100 Subject: [PATCH 70/78] soc/integration/soc: add_etherbone/ClockDomainRenamer: keep sys connected to sys instead of eth rx --- litex/soc/integration/soc.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/litex/soc/integration/soc.py b/litex/soc/integration/soc.py index 22c1d50c5..6f85dfb47 100644 --- a/litex/soc/integration/soc.py +++ b/litex/soc/integration/soc.py @@ -1834,8 +1834,7 @@ class LiteXSoC(SoC): # Use PHY's eth_tx/eth_rx clock domains. ethcore = ClockDomainsRenamer({ "eth_tx": phy_cd + "_tx", - "eth_rx": phy_cd + "_rx", - "sys": phy_cd + "_rx"})(ethcore) + "eth_rx": phy_cd + "_rx"})(ethcore) self.add_module(name=f"ethcore_{name}", module=ethcore) etherbone_cd = "sys" From e866892798237eddd8ef52d5298b3d4a6d9544d7 Mon Sep 17 00:00:00 2001 From: Gwenhael Goavec-Merou Date: Wed, 7 Feb 2024 11:16:12 +0100 Subject: [PATCH 71/78] soc/software/bios/boot: allow to override macaddr by using constant MACADDRx --- litex/soc/software/bios/boot.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/litex/soc/software/bios/boot.c b/litex/soc/software/bios/boot.c index 34079b69d..7c62409e4 100755 --- a/litex/soc/software/bios/boot.c +++ b/litex/soc/software/bios/boot.c @@ -304,7 +304,11 @@ int serialboot(void) #define TFTP_SERVER_PORT 69 #endif +#ifdef MACADDR1 +static unsigned char macadr[6] = {MACADDR1, MACADDR2, MACADDR3, MACADDR4, MACADDR5, MACADDR6}; +#else static unsigned char macadr[6] = {0x10, 0xe2, 0xd5, 0x00, 0x00, 0x00}; +#endif #ifdef LOCALIP1 static unsigned int local_ip[4] = {LOCALIP1, LOCALIP2, LOCALIP3, LOCALIP4}; From 177df0b57e4307ff7875ea70dcf44048890d0e87 Mon Sep 17 00:00:00 2001 From: Gwenhael Goavec-Merou Date: Wed, 7 Feb 2024 11:18:21 +0100 Subject: [PATCH 72/78] soc/integration/soc: move add_ip_constant to helpers with a renaming to add_ip_address_constants, adding function to add MACADDRx constant --- litex/soc/integration/soc.py | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/litex/soc/integration/soc.py b/litex/soc/integration/soc.py index 6f85dfb47..85cba9003 100644 --- a/litex/soc/integration/soc.py +++ b/litex/soc/integration/soc.py @@ -41,6 +41,18 @@ def build_time(with_time=True): fmt = "%Y-%m-%d %H:%M:%S" if with_time else "%Y-%m-%d" return datetime.datetime.fromtimestamp(time.time()).strftime(fmt) +def add_ip_address_constants(soc, name, ip_address): + _ip_address = ip_address.split(".") + assert len(_ip_address) == 4 + for n in range(4): + assert int(_ip_address[n]) < 256 + soc.add_constant(f"{name}{n+1}", int(_ip_address[n])) + +def add_mac_address_constants(soc, name, mac_address): + assert mac_address < 2**48 + for n in range(6): + soc.add_constant(f"{name}{n+1}", (mac_address >> ((5 - n) * 8)) & 0xff) + # SoCError ----------------------------------------------------------------------------------------- class SoCError(Exception): @@ -1771,16 +1783,10 @@ class LiteXSoC(SoC): self.add_constant("ETH_DYNAMIC_IP") # Local/Remote IP Configuration (optional). - def add_ip_constants(name, ip): - _ip = ip.split(".") - assert len(_ip) == 4 - for n in range(4): - assert int(_ip[n]) < 256 - self.add_constant(f"{name}{n+1}", int(_ip[n])) if local_ip: - add_ip_constants("LOCALIP", local_ip) + add_ip_address_constants(self, "LOCALIP", local_ip) if remote_ip: - add_ip_constants("REMOTEIP", remote_ip) + add_ip_address_constants(self, "REMOTEIP", remote_ip) # Software Debug if software_debug: From 7f211048ac39f6ac0b8f52590a619576e2695cb5 Mon Sep 17 00:00:00 2001 From: Gwenhael Goavec-Merou Date: Wed, 7 Feb 2024 11:21:49 +0100 Subject: [PATCH 73/78] soc/integration/soc/add_etherbone: adding ethernet mac address, local/remote ip as parameters, sanity check when hybrid mode and adding ip/mac constants --- litex/soc/integration/soc.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/litex/soc/integration/soc.py b/litex/soc/integration/soc.py index 85cba9003..5c465d5ad 100644 --- a/litex/soc/integration/soc.py +++ b/litex/soc/integration/soc.py @@ -1809,6 +1809,9 @@ class LiteXSoC(SoC): def add_etherbone(self, name="etherbone", phy=None, phy_cd="eth", data_width=8, mac_address = 0x10e2d5000000, ip_address = "192.168.1.50", + ethernet_mac_address = 0x10e2d5000001, + ethernet_local_ip = "192.168.1.51", + ethernet_remote_ip = "192.168.1.100", arp_entries = 1, udp_port = 1234, buffer_depth = 16, @@ -1871,6 +1874,9 @@ class LiteXSoC(SoC): # Ethernet MAC (CPU). if with_ethmac: + assert mac_address != ethernet_mac_address + assert ip_address != ethernet_local_ip + self.check_if_exists("ethmac") ethcore.autocsr_exclude = {"mac"} # Software Interface. @@ -1884,6 +1890,10 @@ class LiteXSoC(SoC): self.add_constant("ETH_PHY_NO_RESET") # Disable reset from BIOS to avoid disabling Hardware Interface. + add_ip_address_constants(self, "LOCALIP", ethernet_local_ip) + add_ip_address_constants(self, "REMOTEIP", ethernet_remote_ip) + add_mac_address_constants(self, "MACADDR", ethernet_mac_address) + # Add SPI Flash -------------------------------------------------------------------------------- def add_spi_flash(self, name="spiflash", mode="4x", clk_freq=20e6, module=None, phy=None, rate="1:1", software_debug=False, **kwargs): # Imports. From afcf78f6433a7f274e9791833d210e44ce6c0162 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Wed, 7 Feb 2024 19:21:38 +0100 Subject: [PATCH 74/78] soc/add_etherbone: Rename ethmac parameters with ethmac suffix since related to ethmac. --- litex/soc/integration/soc.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/litex/soc/integration/soc.py b/litex/soc/integration/soc.py index 5c465d5ad..121d3b691 100644 --- a/litex/soc/integration/soc.py +++ b/litex/soc/integration/soc.py @@ -1809,15 +1809,16 @@ class LiteXSoC(SoC): def add_etherbone(self, name="etherbone", phy=None, phy_cd="eth", data_width=8, mac_address = 0x10e2d5000000, ip_address = "192.168.1.50", - ethernet_mac_address = 0x10e2d5000001, - ethernet_local_ip = "192.168.1.51", - ethernet_remote_ip = "192.168.1.100", arp_entries = 1, udp_port = 1234, buffer_depth = 16, with_ip_broadcast = True, with_timing_constraints = True, - with_ethmac = False): + with_ethmac = False, + ethmac_address = 0x10e2d5000001, + ethmac_local_ip = "192.168.1.51", + ethmac_remote_ip = "192.168.1.100"): + # Imports from liteeth.core import LiteEthUDPIPCore from liteeth.frontend.etherbone import LiteEthEtherbone @@ -1874,8 +1875,8 @@ class LiteXSoC(SoC): # Ethernet MAC (CPU). if with_ethmac: - assert mac_address != ethernet_mac_address - assert ip_address != ethernet_local_ip + assert mac_address != ethmac_address + assert ip_address != ethmac_local_ip self.check_if_exists("ethmac") ethcore.autocsr_exclude = {"mac"} @@ -1890,9 +1891,9 @@ class LiteXSoC(SoC): self.add_constant("ETH_PHY_NO_RESET") # Disable reset from BIOS to avoid disabling Hardware Interface. - add_ip_address_constants(self, "LOCALIP", ethernet_local_ip) - add_ip_address_constants(self, "REMOTEIP", ethernet_remote_ip) - add_mac_address_constants(self, "MACADDR", ethernet_mac_address) + add_ip_address_constants(self, "LOCALIP", ethmac_local_ip) + add_ip_address_constants(self, "REMOTEIP", ethmac_remote_ip) + add_mac_address_constants(self, "MACADDR", ethmac_address) # Add SPI Flash -------------------------------------------------------------------------------- def add_spi_flash(self, name="spiflash", mode="4x", clk_freq=20e6, module=None, phy=None, rate="1:1", software_debug=False, **kwargs): From 1b32d8a34160a40a6d93e5a6b0e3c9a9eb168878 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Fri, 9 Feb 2024 15:10:47 +0100 Subject: [PATCH 75/78] soc/add_etherbone: Revert sys_clk domain renaming when ethmac is disabled. --- litex/soc/integration/soc.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/litex/soc/integration/soc.py b/litex/soc/integration/soc.py index 121d3b691..2aab9e24f 100644 --- a/litex/soc/integration/soc.py +++ b/litex/soc/integration/soc.py @@ -1844,7 +1844,9 @@ class LiteXSoC(SoC): # Use PHY's eth_tx/eth_rx clock domains. ethcore = ClockDomainsRenamer({ "eth_tx": phy_cd + "_tx", - "eth_rx": phy_cd + "_rx"})(ethcore) + "eth_rx": phy_cd + "_rx", + "sys" : {True: "sys", False: phy_cd + "_rx"}[with_ethmac], + })(ethcore) self.add_module(name=f"ethcore_{name}", module=ethcore) etherbone_cd = "sys" From 38ff48a54394e40bf5e37e66ae50379b95ca0494 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Mon, 12 Feb 2024 17:16:54 +0100 Subject: [PATCH 76/78] soc/integration/export: Add load_csr_json function to load/import .json exports. Useful to merge SoC/Sub-SoCs Constants/CSRs/Memory Regions. --- litex/soc/integration/export.py | 56 ++++++++++++++++++++++++++++++--- litex/soc/integration/soc.py | 1 + 2 files changed, 53 insertions(+), 4 deletions(-) diff --git a/litex/soc/integration/export.py b/litex/soc/integration/export.py index 3a00b88f7..487a36041 100644 --- a/litex/soc/integration/export.py +++ b/litex/soc/integration/export.py @@ -2,7 +2,7 @@ # This file is part of LiteX. # # This file is Copyright (c) 2013-2014 Sebastien Bourdeauducq -# This file is Copyright (c) 2014-2019 Florent Kermarrec +# This file is Copyright (c) 2014-2024 Florent Kermarrec # This file is Copyright (c) 2018 Dolu1990 # This file is Copyright (c) 2019 Gabriel L. Somlo # This file is Copyright (c) 2018 Jean-François Nguyen @@ -29,6 +29,7 @@ from sysconfig import get_platform from migen import * from litex.soc.interconnect.csr import CSRStatus +from litex.soc.integration.soc import SoCRegion from litex.build.tools import generated_banner @@ -149,7 +150,7 @@ def get_mem_header(regions): for name, region in regions.items(): r += f"#ifndef {name.upper()}_BASE\n" r += f"#define {name.upper()}_BASE 0x{region.origin:08x}L\n" - r += f"#define {name.upper()}_SIZE 0x{region.length:08x}\n" + r += f"#define {name.upper()}_SIZE 0x{region.size:08x}\n" r += "#endif\n\n" r += "#ifndef MEM_REGIONS\n" @@ -370,7 +371,7 @@ def get_i2c_header(i2c_init_values): r += "\n#endif\n" return r -# JSON Export -------------------------------------------------------------------------------------- +# JSON Export / Import ---------------------------------------------------------------------------- def get_csr_json(csr_regions={}, constants={}, mem_regions={}): alignment = constants.get("CONFIG_CSR_ALIGNMENT", 32) @@ -382,6 +383,7 @@ def get_csr_json(csr_regions={}, constants={}, mem_regions={}): "memories": {}, } + # Get CSR Regions. for name, region in csr_regions.items(): d["csr_bases"][name] = region.origin region_origin = region.origin @@ -398,18 +400,64 @@ def get_csr_json(csr_regions={}, constants={}, mem_regions={}): } region_origin += alignment//8*_size + # Get Constants. for name, value in constants.items(): d["constants"][name.lower()] = value.lower() if isinstance(value, str) else value + # Get Mem Regions. for name, region in mem_regions.items(): d["memories"][name.lower()] = { "base": region.origin, - "size": region.length, + "size": region.size, "type": region.type, } + # Return JSON Dump. return json.dumps(d, indent=4) +class MockCSR: + def __init__(self, name, size, type): + self.name = name + self.size = size + self.type = type + +class MockCSRRegion: + def __init__(self, origin, obj): + self.origin = origin + self.obj = obj + self.busword = 32 + +def load_csr_json(filename, origin=0, name=""): + if len(name): + name += "_" + # Read File. + with open(filename, 'r') as json_file: + config_data = json.load(json_file) + + # Load CSR Regions. + csr_regions = {} + for region_name, addr in config_data.get("csr_bases", {}).items(): + csrs = [] + for csr_name, info in config_data.get("csr_registers", {}).items(): + region_prefix, _, csr_suffix = csr_name.rpartition("_") + if region_prefix.startswith(region_name): + if region_prefix == region_name: + final_name = csr_suffix + else: + final_name = f"{region_prefix[len(region_name) + 1:]}_{csr_suffix}" + csrs.append(MockCSR(final_name, info["size"], info["type"])) + csr_regions[name + region_name] = MockCSRRegion(origin + addr, csrs) + + # Load Constants. + constants = {(name + const_name).upper(): value for const_name, value in config_data.get("constants", {}).items()} + + # Load Memory Regions. + mem_regions = {} + for mem_name, info in config_data.get("memories", {}).items(): + mem_regions[name + mem_name.lower()] = SoCRegion(origin + info["base"], info["size"], info["type"]) + + # Return CSR Regions, Constants, Mem Regions. + return csr_regions, constants, mem_regions # CSV Export -------------------------------------------------------------------------------------- diff --git a/litex/soc/integration/soc.py b/litex/soc/integration/soc.py index 2aab9e24f..c5c43aa7f 100644 --- a/litex/soc/integration/soc.py +++ b/litex/soc/integration/soc.py @@ -81,6 +81,7 @@ class SoCRegion: self.mode = mode self.cached = cached self.linker = linker + self.type = "" def decoder(self, bus): origin = self.origin From 244bc438862df854ca7ee373d8251c74605b2197 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Mon, 12 Feb 2024 17:19:04 +0100 Subject: [PATCH 77/78] soc/integration/builder: Add add_json method to allow adding exported .json from Sub-SoCs. Ex: builder.add_json("icebreaker_soc.json", 0x30000000, "icebreaker_soc") to import/merge a SoC's json file from a Sub-SoC in Main-SoC. --- litex/soc/integration/builder.py | 36 ++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/litex/soc/integration/builder.py b/litex/soc/integration/builder.py index 5e0595ac7..955c29293 100644 --- a/litex/soc/integration/builder.py +++ b/litex/soc/integration/builder.py @@ -2,7 +2,7 @@ # This file is part of LiteX. # # This file is Copyright (c) 2015 Sebastien Bourdeauducq -# This file is Copyright (c) 2015-2021 Florent Kermarrec +# This file is Copyright (c) 2015-2024 Florent Kermarrec # This file is Copyright (c) 2018-2019 Antmicro # This file is Copyright (c) 2018 Sergiusz Bazanski # This file is Copyright (c) 2016-2017 Tim 'mithro' Ansell @@ -127,6 +127,9 @@ class Builder: self.add_software_package(name) self.add_software_library(name) + # JSONs. + self.jsons = [] + def add_software_package(self, name, src_dir=None): if src_dir is None: src_dir = os.path.join(soc_directory, "software", name) @@ -135,6 +138,30 @@ class Builder: def add_software_library(self, name): self.software_libraries.append(name) + def add_json(self, filename, name="", origin=0): + self.jsons.append((filename, name, origin)) + + def _get_json_mem_regions(self): + mem_regions = {} + for filename, name, origin in self.jsons: + _, _, _mem_regions = export.load_csr_json(filename, name, origin) + mem_regions.update(_mem_regions) + return mem_regions + + def _get_json_constants(self): + constants = {} + for filename, name, origin in self.jsons: + _, _constants, _ = export.load_csr_json(filename, name, origin) + constants.update(_constants) + return constants + + def _get_json_csr_regions(self): + csr_regions = {} + for filename, name, origin in self.jsons: + _csr_regions, _, _ = export.load_csr_json(filename, name, origin) + csr_regions.update(_csr_regions) + return csr_regions + def _get_variables_contents(self): # Helper. variables_contents = [] @@ -147,7 +174,7 @@ class Builder: raise e # Define packages and libraries. - define("PACKAGES", " ".join(name for name, src_dir in self.software_packages)) + define("PACKAGES", " ".join(name for name, src_dir in self.software_packages)) define("PACKAGE_DIRS", " ".join(src_dir for name, src_dir in self.software_packages)) define("LIBS", " ".join(self.software_libraries)) @@ -180,6 +207,11 @@ class Builder: _create_dir(self.include_dir) _create_dir(self.generated_dir) + # Integrate JSON files. + self.soc.mem_regions.update(self._get_json_mem_regions()) + self.soc.constants.update( self._get_json_constants()) + self.soc.csr_regions.update(self._get_json_csr_regions()) + # Generate BIOS files when the SoC uses it. if with_bios: # Generate Variables to variables.mak. From f36e7d379a4fb847917effb54068741be0148715 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Mon, 12 Feb 2024 17:21:42 +0100 Subject: [PATCH 78/78] CHANGES.md: Update. --- CHANGES.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 34b60119c..f672c3d10 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -7,6 +7,7 @@ - liteeth/phy/gw5rgmii : Fixed Clk assignments. - build/efinix/programmer : Updated for compatibility with latest Efinity versions. - litespi/software: : Fixed SPI Flash Clk Divider computation when with L2 Cache. + - litepcie/us(p)pciephy : Fixed x8 / 256-bit wide case. [> Added -------- @@ -20,6 +21,7 @@ - liteeth/phy : Added 7-Series/Ultrascale(+) 2500BaseX PHYs. - litespi/sdrphy: : Allowed flash parameter to be None. - litespi/integration : Improved integration and simplifications. + - export/builder : Add import/merge of Sub-SoCs .json files. [> Changed ----------