diff --git a/CHANGES b/CHANGES index 2e72fb988..7ecfcb89b 100644 --- a/CHANGES +++ b/CHANGES @@ -1,51 +1,97 @@ -[> Changes since 2022.04 +[> Changes since 2022.08 ------------------------ + [> Issues resolved + ------------------ + + [> Added Features + ----------------- + + [> API changes/Deprecation + -------------------------- + + +[> 2022.08, released on September 12th 2022 +------------------------------------------- + [> Issues resolved ------------------ - cpu/vexriscv: Fix compilation with new binutils. - soc/LiteXSocArgumentParser: Fix --cpu-type parsing. - litex_sim: Fix --with-ethernet. + - liblitesdcard: Fix SDCard initialization corner cases. + - liblitedram: Enable sdram_init/mr_write for SDRAM. + - export/get_memory_x: Replace SPIFlash with ROM. + - soc/cores/video: Fix operation with some monitors (set data to 0 during blanking). + - tools/remote/comm_usb: Fix multi-word reads/writes. + - build/lattice/oxide: Fix ES posfix on device name. + - interconnect/axi: Fix AXIArbiter corner case. + - litex_server/client: Fix remapping over CommPCIe. + - LitePCIe: Fix LiteUART support with multi-boards. - [> Added Features + [> Added Features ----------------- - - litex_setup: Add -tag support for install/update. - - tools: Add initial LiteX standalone SoC generator. - - cores/ram: Add Xilinx's FIFO_SYNC_MACRO equivalent. - - LitePCIe: Always use 24-bit depth fields on LitePCIeBuffering to simplify software. - - gen/fhdl: Integrate Migen namer to give us more flexibility. - - fhdl/memory: Prefix memory files with build name to simplify reuse/integration. - - cpu/rocket: Add more variants. - - cores/video: Enable driving both + and - diff outs to compensate hardware issues. - - build: Add intial OSFPGA Foedag/Raptor build backend. - - cpu/cva5: Add initial CVA5 CPU support (ex Taiga). - - LiteSATA: Add IRQ and Identify support. - - clock/intel: Improve to find the best PLL config. - - cpu/cva6: Add initial CVA6 CPU support (ex Ariane). - - bios: Improve config flags. - - tools: Add I2s/MMCM support to litex_json2dts_zephyr. - - clock/gowin: Add GW2A support. - - bios: Disable LTO (does not work in all cases, needs to be investigated). - - CI: Test more RISC-V CPUs and OpenRisc CPUs in CI. - - bios: Add CONFIG_NO_BOOT to allow disabling boot sequence. - - export: Allow disabling CSR_BASE define in csr.h. - - build/openocd: Update for compatibility with upstream OpenOCD. - - cpu/openc906: Add initial OpenC906 support (open version of the Allwinner's D1 chip). - - soc: Add automatic bridging between AXI <-> AXI-Lite <-> Wishbone. - - soc: Add AXI-Full bus support. - - interconnect: Add AXI DownConverted and Interconnect/Crossbar. - - interconnect: Create axi directory and split code. - - soc: Modify SoC finalization order for more flexibility. - - soc: Add --bus-interconnect parameter to select interconect: shared/crossbar. - - valentyusb: Package and install it with LiteX. - - bios/mem_list: Align Mem Regions. + - litex_setup: Add -tag support for install/update. + - tools: Add initial LiteX standalone SoC generator. + - cores/ram: Add Xilinx's FIFO_SYNC_MACRO equivalent. + - LitePCIe: Always use 24-bit depth fields on LitePCIeBuffering to simplify software. + - gen/fhdl: Integrate Migen namer to give us more flexibility. + - fhdl/memory: Prefix memory files with build name to simplify reuse/integration. + - cpu/rocket: Add more variants. + - cores/video: Enable driving both + and - diff outs to compensate hardware issues. + - build: Add intial OSFPGA Foedag/Raptor build backend. + - cpu/cva5: Add initial CVA5 CPU support (ex Taiga). + - LiteSATA: Add IRQ and Identify support. + - clock/intel: Improve to find the best PLL config. + - cpu/cva6: Add initial CVA6 CPU support (ex Ariane). + - bios: Improve config flags. + - tools: Add I2s/MMCM support to litex_json2dts_zephyr. + - clock/gowin: Add GW2A support. + - bios: Disable LTO (does not work in all cases, needs to be investigated). + - CI: Test more RISC-V CPUs and OpenRisc CPUs in CI. + - bios: Add CONFIG_NO_BOOT to allow disabling boot sequence. + - export: Allow disabling CSR_BASE define in csr.h. + - build/openocd: Update for compatibility with upstream OpenOCD. + - cpu/openc906: Add initial OpenC906 support (open version of the Allwinner's D1 chip). + - soc: Add automatic bridging between AXI <-> AXI-Lite <-> Wishbone. + - soc: Add AXI-Full bus support. + - interconnect: Add AXI DownConverted and Interconnect/Crossbar. + - interconnect: Create axi directory and split code. + - soc: Modify SoC finalization order for more flexibility. + - soc: Add --bus-interconnect parameter to select interconect: shared/crossbar. + - valentyusb: Package and install it with LiteX. + - bios/mem_list: Align Mem Regions. + - build: Introduce GenericToolchain to cleanup/simplify build backends. + - soc/etherbone: Expose broadcast capability. + - build/lattice: Add MCLK frequency support. + - cpu/cva6: Add IRQ support. + - cores/clock: Add manual placement support to ECP5PLL. + - cores/leds: Add polarity support. + - cpu/neorv32: Switch to new NeoRV32 LiteX Core Complex and add variants support. + - cores/gpio: Add optional reset value. + - litex_client: Add --host support for remote operation. + - sim/verilator: Add jobs number support (to limit RAM usage with large SoCs/CPUs). + - soc/SocBusHandler Add get_address_width method to simplify peripheral integration. + - bios: Expose BIOS console parameters (to enable/disable history/autocomplete). + - bios: Expose BIOS LTO configuration. + - litex_json2renode: Update. + - build: Introduce YosysNextPNRToolchain to cleanup/simplify Yosys support. + - bios: Add buttons support/command. + - litex_client: Add XADC/Identifier/Leds/Buttons support to GUI. + - cpu/NaxRiscv: Update. + - build/generic_platofrm: Add add_connector methode to allow extending connectors. + - litex_server/client: Add initial information exchange between server/client. + - LitePCIe: Improve 64-bit support. + - interconnect/axi: Add missing optional signals. + - interconnect/wishbone: Improve DownConverter efficiency. - [> API changes/Deprecation + [> API changes/Deprecation -------------------------- - LiteX-Boards : Remove short import support on platforms/targets. - tools: Rename litex_gen to litex_periph_gen. - LiteX-Boards: Only generate SoC/Software headers when --build is set - Symbiflow: Rename to F4PGA. + - mkmsscimg: Rename to crcfbigen. [> 2022.04, released on May 3th 2022 ------------------------------------ diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 91f806718..20f510e48 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -10,40 +10,46 @@ and we'll fix it! Contributors: Copyright (c) 2021 Acathla-fr -Copyright (c) 2011-2012 Alain Péteut +Copyright (c) 2011-2015 Alain Péteut Copyright (c) 2019 Ambroz Bizjak Copyright (c) 2021 Andreas Galauner Copyright (c) 2021-2022 Andrew Dennison Copyright (c) 2021 Andwer E Wilson Copyright (c) 2021 Andy Kitchen +Copyright (c) 2018-2022 Antmicro Copyright (c) 2019 Antony Pavlov Copyright (c) 2019 Antti Lukats -Copyright (c) 2018-2021 Antmicro Copyright (c) 2019-2020 Arnaud Durand +Copyright (c) 2019 atommann Copyright (c) 2022 Bastian Löher +Copyright (c) 2022 Ben Stobbs Copyright (c) 2021 Benjamin Henrion Copyright (c) 2019-2020 Benjamin Herrenschmidt -Copyright (c) 2022 Ben Stobbs Copyright (c) 2021 Blake Smith Copyright (c) 2012-2013 Brandon Hamilton +Copyright (c) 2022 Brian Swetland Copyright (c) 2017-2021 bunnie Copyright (c) 2019 Caleb Jamison Copyright (c) 2021 Camilo Andres Vera Ruiz Copyright (c) 2021-2022 Charles-Henri Mousset +Copyright (c) 2019 chmousset Copyright (c) 2018 Chris Ballance Copyright (c) 2021 Chris Osterwood Copyright (c) 2020-2022 Christian Klarhorst -Copyright (c) 2021 Dan Callaghan +Copyright (c) 2022 curliph Copyright (c) 2019 Daniel Kucera Copyright (c) 2020 Dave Marples Copyright (c) 2013 David Carne -Copyright (c) 2020 davidcorrigan714 Copyright (c) 2020-2021 David Jablonski Copyright (c) 2020-2021 David Lattimore +Copyright (c) 2022 David Lobato Copyright (c) 2020-2022 David Sawatzke +Copyright (c) 2018-2020 David Shah +Copyright (c) 2020 davidcorrigan714 Copyright (c) 2018 Deano Calver Copyright (c) 2021-2022 developandplay <34752929+developandplay@users.noreply.github.com> Copyright (c) 2018-2022 Dolu1990 +Copyright (c) 2022 Eric Matthews Copyright (c) 2021 Evan Lojewski Copyright (c) 2018 Ewen McNeill Copyright (c) 2014 Fabien Marteau @@ -53,10 +59,10 @@ Copyright (c) 2017-2018 Felix Held Copyright (c) 2020 Filipe Laíns Copyright (c) 2012-2022 Florent Kermarrec Copyright (c) 2019 Francis Lam -Copyright (c) 2022-2021 Franck Jullien +Copyright (c) 2020-2022 Franck Jullien Copyright (c) 2019-2022 Gabriel L. Somlo Copyright (c) 2021 Gary Wong -Copyright (c) 2018-2021 Gatecat +Copyright (c) 2018-2022 gatecat Copyright (c) 2020-2021 Geert Uytterhoeven Copyright (c) 2021 George Hilliard Copyright (c) 2019 Giammarco Zacheo @@ -64,7 +70,7 @@ Copyright (c) 2021-2022 Google Copyright (c) 2017 Greg Darke Copyright (c) 2020-2022 Greg Davill Copyright (c) 2021 Guillaume REMBERT -Copyright (c) 2015-2014 Guy Hutchison +Copyright (c) 2014-2015 Guy Hutchison Copyright (c) 2020-2022 Gwenhael Goavec-Merou Copyright (c) 2021 Hans Baier Copyright (c) 2022 Icenowy Zheng @@ -74,11 +80,12 @@ Copyright (c) 2021 Jakub Piecuch Copyright (c) 2021 Jan Luebbe Copyright (c) 2014 Jannis Harder Copyright (c) 2018 Jean-François Nguyen -Copyright (c) 2020 Jędrzej Boczar Copyright (c) 2022 Jevin Sweval Copyright (c) 2015 Joe Britton Copyright (c) 2017 Joel Addison Copyright (c) 2020-2022 Joel Stanley +Copyright (c) 2022 Johannes Rudolph +Copyright (c) 2020 Jędrzej Boczar Copyright (c) 2019 Kees Jongenburger Copyright (c) 2013 Kenneth Ryerson Copyright (c) 2020 kessam <61152217+kessam@users.noreply.github.com> @@ -87,22 +94,26 @@ Copyright (c) 2021 Konstantin Copyright (c) 2019 Kurt Kiefer Copyright (c) 2019 Larry Doolittle Copyright (c) 2012-2013 Lars-Peter Clausen -Copyright (c) 2020-2021 Leon Schuermann +Copyright (c) 2020-2022 Leon Schuermann +Copyright (c) 2022 Marcus Comstedt Copyright (c) 2021 Marek Czerski Copyright (c) 2021 Marek Materzok Copyright (c) 2019 Martin Cornil +Copyright (c) 2022 Massimiliano Giacometti Copyright (c) 2021 Matt Johnston Copyright (c) 2017 Matt Kelly Copyright (c) 2019-2022 Michael Betz Copyright (c) 2012 Michael Walle +Copyright (c) 2022 Mikolaj Sowinski Copyright (c) 2021-2022 Mikołaj Sowiński Copyright (c) 2019-2021 Miodrag Milanovic Copyright (c) 2019 msloniewski Copyright (c) 2021 Nathaniel R. Lewis +Copyright (c) 2021 Navaneeth Copyright (c) 2021 Navaneeth Bhardwaj Copyright (c) 2021 Nick Østergaard Copyright (c) 2013 Nina Engelhardt -Copyright (c) 2015 Numato +Copyright (c) 2015 numato Copyright (c) 2021 Nick Østergaard Copyright (c) 2020 Owen Kirby Copyright (c) 2015 Olof Kindgren @@ -111,27 +122,28 @@ Copyright (c) 2021 Paul Mackerras Copyright (c) 2020 Paul Sajna Copyright (c) 2018 Paul Schulz Copyright (c) 2020 Pepijn de Vos -Copyright (c) 2018 Phlipped +Copyright (c) 2018 phlipped Copyright (c) 2020 Piense Copyright (c) 2017 Pierre-Olivier Vauboin Copyright (c) 2020 Piotr Esden-Tempski -Copyright (c) 2015 Psmears +Copyright (c) 2015 psmears Copyright (c) 2020 Rangel Ivanov +Copyright (c) 2021-2022 RapidSilicon Copyright (c) 2020-2021 Raptor Engineering Development Team Copyright (c) 2021 Ray Molenkamp +Copyright (c) 2020 rob-ng15 <58272847+rob-ng15@users.noreply.github.com> Copyright (c) 2013-2016 Robert Jordens Copyright (c) 2013 Robert Jördens Copyright (c) 2021 Robert Wilbrandt -Copyright (c) 2020 rob-ng15 <58272847+rob-ng15@users.noreply.github.com> Copyright (c) 2015 Rohit Kumar Singh Copyright (c) 2021 Romain Dolbeau +Copyright (c) 2022 Rouven Broszeit Copyright (c) 2020 rprinz08 Copyright (c) 2015 Ryan Verner -Copyright (c) 2020 Sadullah Canakci -Copyright (c) 2019-2021 sadullah +Copyright (c) 2019-2020 Sadullah Canakci Copyright (c) 2020 Samuel Lindemer Copyright (c) 2018-2020 Sean Cross -Copyright (c) 2013-2016 Sebastien Bourdeauducq +Copyright (c) 2011-2016 Sebastien Bourdeauducq Copyright (c) 2021 Sergiu Mosanu Copyright (c) 2017-2018 Sergiusz Bazanski Copyright (c) 2020 Shawn Anastasio @@ -139,10 +151,13 @@ Copyright (c) 2020-2021 Shawn Hoffman Copyright (c) 2020 shuffle2 Copyright (c) 2021 Simon Thornington Copyright (c) 2018-2022 Stafford Horne +Copyright (c) 2020 Stephane Gourichon +Copyright (c) 2022 stnolting Copyright (c) 2020 Stéphane Gourichon Copyright (c) 2022 Sylvain Lefebvre Copyright (c) 2021-2022 Sylvain Munaut -Copyright (c) 2017-2018 Tim 'mithro' Ansell +Copyright (c) 2022 Thomas Watson +Copyright (c) 2017-2021 Tim 'mithro' Ansell Copyright (c) 2019 Tom Keddie Copyright (c) 2021-2022 tongchen126 Copyright (c) 2020 Vadim Kaushan @@ -154,11 +169,13 @@ Copyright (c) 2022 Victor Suarez Rovere Copyright (c) 2019 vytautasb Copyright (c) 2013 Werner Almesberger Copyright (c) 2015-2021 whitequark -Copyright (c) 2015-2021 William D. Jones +Copyright (c) 2015-2022 William D. Jones Copyright (c) 2022 Wolfgang Nagele -Copyright (c) 2013-2014 Yann Sionneau -Copyright (c) 2015 Yves Delley +Copyright (c) 2021 wuhanstudio +Copyright (c) 2022 xhe Copyright (c) 2020 Xiretza +Copyright (c) 2013-2015 Yann Sionneau +Copyright (c) 2015 Yves Delley Copyright (c) 2020 Yehowshua Immanuel Copyright (c) 2021 Yoshimasa Niwa Copyright (c) 2015 Yves Delley diff --git a/litex/build/generic_platform.py b/litex/build/generic_platform.py index 3054103c0..c327b9f6a 100644 --- a/litex/build/generic_platform.py +++ b/litex/build/generic_platform.py @@ -132,6 +132,12 @@ def _resource_type(resource): class ConnectorManager: def __init__(self, connectors): self.connector_table = dict() + self.add_connector(connectors) + + def add_connector(self, connectors): + if isinstance(connectors, tuple): + connectors = [connectors] + for connector in connectors: cit = iter(connector) conn_name = next(cit) @@ -162,7 +168,10 @@ class ConnectorManager: if pn.isdigit(): pn = int(pn) - r.append(self.connector_table[conn][pn]) + conn_pn = self.connector_table[conn][pn] + if ":" in conn_pn: + conn_pn = self.resolve_identifiers([conn_pn])[0] + r.append(conn_pn) else: r.append(identifier) @@ -193,6 +202,9 @@ class ConstraintManager: def add_extension(self, io): self.available.extend(io) + def add_connector(self, connectors): + self.connector_manager.add_connector(connectors) + def request(self, name, number=None, loose=False): resource = _lookup(self.available, name, number, loose) if resource is None: @@ -356,6 +368,9 @@ class GenericPlatform: def add_extension(self, *args, **kwargs): return self.constraint_manager.add_extension(*args, **kwargs) + def add_connector(self, *args, **kwargs): + self.constraint_manager.add_connector(*args, **kwargs) + def finalize(self, fragment, *args, **kwargs): if self.finalized: raise ConstraintError("Already finalized") diff --git a/litex/build/xilinx/f4pga.py b/litex/build/xilinx/f4pga.py index 743f86aa2..cba6bccd4 100644 --- a/litex/build/xilinx/f4pga.py +++ b/litex/build/xilinx/f4pga.py @@ -16,10 +16,11 @@ from litex.build.xilinx.vivado import _xdc_separator, _build_xdc from litex.build import tools try: - from f4pga import Flow, make_flow_config - from f4pga.common import set_verbosity_level - from f4pga.cache import F4Cache - from f4pga.flow_config import ProjectFlowConfig + from f4pga.flows.flow import Flow + from f4pga.flows.commands import make_flow_config + from f4pga.flows.common import set_verbosity_level + from f4pga.flows.cache import F4Cache + from f4pga.flows.flow_config import ProjectFlowConfig except ModuleNotFoundError as e: raise ModuleNotFoundError("Try getting/updating F4PGA tool (https://github.com/chipsalliance/f4pga/)") from e diff --git a/litex/soc/cores/cpu/naxriscv/core.py b/litex/soc/cores/cpu/naxriscv/core.py old mode 100644 new mode 100755 index dd0bc34fe..d857c63bb --- a/litex/soc/cores/cpu/naxriscv/core.py +++ b/litex/soc/cores/cpu/naxriscv/core.py @@ -196,6 +196,7 @@ class NaxRiscv(CPU): md5_hash.update(str(NaxRiscv.xlen).encode('utf-8')) md5_hash.update(str(NaxRiscv.jtag_tap).encode('utf-8')) md5_hash.update(str(NaxRiscv.jtag_instruction).encode('utf-8')) + md5_hash.update(str(NaxRiscv.memory_regions).encode('utf-8')) for args in NaxRiscv.scala_args: md5_hash.update(args.encode('utf-8')) for file in NaxRiscv.scala_paths: @@ -227,7 +228,7 @@ class NaxRiscv(CPU): ndir = os.path.join(vdir, "ext", "NaxRiscv") sdir = os.path.join(vdir, "ext", "SpinalHDL") - NaxRiscv.git_setup("NaxRiscv", ndir, "https://github.com/SpinalHDL/NaxRiscv.git" , "main", "b13c0aad") + NaxRiscv.git_setup("NaxRiscv", ndir, "https://github.com/SpinalHDL/NaxRiscv.git" , "main", "cb2a598a") NaxRiscv.git_setup("SpinalHDL", sdir, "https://github.com/SpinalHDL/SpinalHDL.git", "dev" , "a130f7b7") gen_args = [] @@ -235,6 +236,8 @@ class NaxRiscv(CPU): gen_args.append(f"--netlist-directory={vdir}") gen_args.append(f"--reset-vector={reset_address}") gen_args.append(f"--xlen={NaxRiscv.xlen}") + for region in NaxRiscv.memory_regions: + gen_args.append(f"--memory-region={region[0]},{region[1]},{region[2]},{region[3]}") for args in NaxRiscv.scala_args: gen_args.append(f"--scala-args={args}") if(NaxRiscv.jtag_tap) : @@ -395,6 +398,7 @@ class NaxRiscv(CPU): o_peripheral_clint_rresp = clintbus.r.resp, ) soc.bus.add_slave("clint", clintbus, region=soc_region_cls(origin=soc.mem_map.get("clint"), size=0x1_0000, cached=False)) + self.soc = soc # FIXME: Save SoC instance to retrieve the final mem layout on finalization. def add_memory_buses(self, address_width, data_width): nax_data_width = 64 @@ -463,8 +467,29 @@ class NaxRiscv(CPU): def do_finalize(self): assert hasattr(self, "reset_address") - self.find_scala_files() + + # Generate memory map from CPU perspective + # naxriscv modes: + # r,w,x,c : readable, writeable, executable, caching allowed + # io : IO region (Implies P bus, preserve memory order, no dcache) + # naxriscv bus: + # p : peripheral + # m : memory + NaxRiscv.memory_regions = [] + for name, region in self.soc.bus.io_regions.items(): + NaxRiscv.memory_regions.append( (region.origin, region.size, "io", "p") ) # IO is only allowed on the p bus + for name, region in self.soc.bus.regions.items(): + if region.linker: # remove virtual regions + continue + if len(self.memory_buses) and name == 'main_ram': # m bus + bus = "m" + else: + bus = "p" + mode = region.mode + mode += "c" if region.cached else "" + NaxRiscv.memory_regions.append( (region.origin, region.size, mode, bus) ) + self.generate_netlist_name(self.reset_address) # Do verilog instance. diff --git a/litex/soc/cores/cpu/vexriscv_smp/core.py b/litex/soc/cores/cpu/vexriscv_smp/core.py index 1f9a8cbae..e6061c254 100755 --- a/litex/soc/cores/cpu/vexriscv_smp/core.py +++ b/litex/soc/cores/cpu/vexriscv_smp/core.py @@ -260,7 +260,7 @@ class VexRiscvSMP(CPU): gen_args.append(f"--aes-instruction={VexRiscvSMP.aes_instruction}") gen_args.append(f"--out-of-order-decoder={VexRiscvSMP.out_of_order_decoder}") gen_args.append(f"--wishbone-memory={VexRiscvSMP.wishbone_memory}") - gen_args.append(f"--wishbone-force-32b={VexRiscvSMP.wishbone_force_32b}") + if(VexRiscvSMP.wishbone_force_32b): gen_args.append(f"--wishbone-force-32b={VexRiscvSMP.wishbone_force_32b}") gen_args.append(f"--fpu={VexRiscvSMP.with_fpu}") gen_args.append(f"--cpu-per-fpu={VexRiscvSMP.cpu_per_fpu}") gen_args.append(f"--rvc={VexRiscvSMP.with_rvc}") diff --git a/litex/soc/cores/dna.py b/litex/soc/cores/dna.py index 53448ad9f..5d515bba6 100644 --- a/litex/soc/cores/dna.py +++ b/litex/soc/cores/dna.py @@ -2,6 +2,7 @@ # This file is part of LiteX. # # Copyright (c) 2014-2015 Robert Jordens +# Copyright (c) 2022 Florent Kermarrec # SPDX-License-Identifier: BSD-2-Clause from migen import * @@ -12,34 +13,36 @@ from litex.soc.interconnect.csr import * # Xilinx DNA (Device Identifier) ------------------------------------------------------------------- class DNA(Module, AutoCSR): + nbits = 57 def __init__(self): - n = 57 - self._id = CSRStatus(n) + self._id = CSRStatus(self.nbits) # # # - self.do = do = Signal() - self.count = count = Signal(max=2*n + 1) - self.clk = clk = Signal() + # Create slow DNA Clk (sys_clk/16). + self.clock_domains.cd_dna = ClockDomain() + dna_clk_count = Signal(4) + self.sync += dna_clk_count.eq(dna_clk_count + 1) + self.sync += self.cd_dna.clk.eq(dna_clk_count[3]) - self.comb += clk.eq(count[0]) + + # Shift-Out DNA Identifier. + count = Signal(8) + dout = Signal() self.specials += Instance("DNA_PORT", - i_DIN = self._id.status[-1], - o_DOUT = do, - i_CLK = clk, - i_READ = count < 2, - i_SHIFT = 1 + i_CLK = ClockSignal("dna"), + i_READ = (count == 0), + i_SHIFT = 1, + i_DIN = 0, + o_DOUT = dout, ) - - self.sync += [ - If(count < 2*n, + self.sync.dna += [ + If(count < (self.nbits + 1), count.eq(count + 1), - If(clk, - self._id.status.eq(Cat(do, self._id.status)) - ) + self._id.status.eq(Cat(dout, self._id.status)) ) ] def add_timing_constraints(self, platform, sys_clk_freq, sys_clk): - platform.add_period_constraint(self.clk, 2*1e9/sys_clk_freq) - platform.add_false_path_constraints(self.clk, sys_clk) + platform.add_period_constraint(self.cd_dna.clk, 16*1e9/sys_clk_freq) + platform.add_false_path_constraints(self.cd_dna.clk, sys_clk) diff --git a/litex/soc/cores/video.py b/litex/soc/cores/video.py index 03ccaf6b7..522c7c84e 100644 --- a/litex/soc/cores/video.py +++ b/litex/soc/cores/video.py @@ -809,6 +809,52 @@ class VideoHDMIPHY(Module): ) setattr(self.submodules, f"{color}_serializer", serializer) +# HDMI (Gowin). + +class VideoGowinHDMIPHY(Module): + def __init__(self, pads, clock_domain="sys", pn_swap=[]): + self.sink = sink = stream.Endpoint(video_data_layout) + + # # # + + # Always ack Sink, no backpressure. + self.comb += sink.ready.eq(1) + + # Clocking + Differential Signaling. + pix_clk = ClockSignal(clock_domain) + self.specials += Instance("ELVDS_OBUF", + i_I = pix_clk if "clk" not in pn_swap else ~pix_clk, + o_O = pads.clk_p, + o_OB = pads.clk_n, + ) + + for color in ["r", "g", "b"]: + # TMDS Encoding. + encoder = ClockDomainsRenamer(clock_domain)(TMDSEncoder()) + setattr(self.submodules, f"{color}_encoder", encoder) + self.comb += encoder.d.eq(getattr(sink, color)) + self.comb += encoder.c.eq(Cat(sink.hsync, sink.vsync) if color == "r" else 0) + self.comb += encoder.de.eq(sink.de) + + # 10:1 Serialization + Differential Signaling. + data_i = encoder.out if color not in pn_swap else ~encoder.out + pad_o = Signal() + self.specials += Instance("OSER10", + i_PCLK = pix_clk, + i_FCLK = ClockSignal(clock_domain + "5x"), + i_RESET = ResetSignal(clock_domain), + **{f"i_D{i}" : data_i[i] for i in range(10)}, + o_Q = pad_o, + ) + + c2d = {"r": 0, "g": 1, "b": 2} + self.specials += Instance("ELVDS_OBUF", + i_I = pad_o, + o_O = getattr(pads, f"data{c2d[color]}_p"), + o_OB = getattr(pads, f"data{c2d[color]}_n"), + ) + + # HDMI (Xilinx Spartan6). class VideoS6HDMIPHY(Module): diff --git a/litex/soc/integration/builder.py b/litex/soc/integration/builder.py index e5543e0ba..dfd195677 100644 --- a/litex/soc/integration/builder.py +++ b/litex/soc/integration/builder.py @@ -69,11 +69,10 @@ class Builder: include_dir = None, generated_dir = None, - # Compile Options. + # Compilation. compile_software = True, compile_gateware = True, build_backend = "litex", - lto = False, # Exports. csr_json = None, @@ -81,8 +80,9 @@ class Builder: csr_svd = None, memory_x = None, - # BIOS Options. - bios_options = [], + # BIOS. + bios_lto = False, + bios_console = "full", # Documentation. generate_doc = False): @@ -96,11 +96,10 @@ class Builder: self.include_dir = os.path.abspath(include_dir or os.path.join(self.software_dir, "include")) self.generated_dir = os.path.abspath(generated_dir or os.path.join(self.include_dir, "generated")) - # Compile Options. + # Compilation. self.compile_software = compile_software self.compile_gateware = compile_gateware self.build_backend = build_backend - self.lto = lto # Exports. self.csr_csv = csr_csv @@ -108,16 +107,16 @@ class Builder: self.csr_svd = csr_svd self.memory_x = memory_x - # BIOS Options. - self.bios_options = bios_options + # BIOS. + self.bios_lto = bios_lto + self.bios_console = bios_console - # Documentation + # Documentation. self.generate_doc = generate_doc - # List software packages and libraries. + # Software packages and libraries. self.software_packages = [] self.software_libraries = [] - for name in soc_software_packages: self.add_software_package(name) self.add_software_library(name) @@ -134,6 +133,7 @@ class Builder: # Helper. variables_contents = [] def define(k, v): + k = k.replace("-", "_") try: variables_contents.append("{}={}".format(k, _makefile_escape(v))) except AttributeError as e: @@ -161,11 +161,10 @@ class Builder: for name, src_dir in self.software_packages: define(name.upper() + "_DIRECTORY", src_dir) - # Define Compile/BIOS Options. - define("LTO", f"{self.lto:d}") - for bios_option in self.bios_options: - assert bios_option in ["TERM_NO_HIST", "TERM_MINI", "TERM_NO_COMPLETE"] - define(bios_option, "1") + # Define BIOS variables. + define("LTO", f"{self.bios_lto:d}") + assert self.bios_console in ["full", "no-history", "no-autocomplete", "lite", "disable"] + define(f"BIOS_CONSOLE_{self.bios_console.upper()}", "1") return "\n".join(variables_contents) @@ -257,10 +256,15 @@ class Builder: meson_minor_min = 59 if meson_present: meson_version = subprocess.check_output(["meson", "-v"]).decode("utf-8").split(".") - if (not meson_present) or (int(meson_version[0]) < meson_major_min) or (int(meson_version[1]) < meson_minor_min): + if (not meson_present): msg = "Unable to find valid Meson build system, please install it with:\n" msg += "- pip3 install meson.\n" raise OSError(msg) + if (int(meson_version[0]) < meson_major_min) or (int(meson_version[1]) < meson_minor_min): + msg = f"Meson version to old. Found: {meson_version[0]}.{meson_version[1]}. Required: {meson_major_min}.{meson_minor_min}.\n" + msg += "Try updating with:\n" + msg += "- pip3 install -U meson.\n" + raise OSError(msg) def _prepare_rom_software(self): # Create directories for all software packages. @@ -283,7 +287,10 @@ class Builder: def _initialize_rom_software(self): # Get BIOS data from compiled BIOS binary. bios_file = os.path.join(self.software_dir, "bios", "bios.bin") - bios_data = soc_core.get_mem_data(bios_file, self.soc.cpu.endianness) + bios_data = soc_core.get_mem_data(bios_file, + data_width = self.soc.bus.data_width, + endianness = self.soc.cpu.endianness, + ) # Initialize SoC with with BIOS data. self.soc.initialize_rom(bios_data) @@ -392,12 +399,14 @@ def builder_args(parser): builder_group.add_argument("--no-compile", action="store_true", help="Disable Software and Gateware compilation.") builder_group.add_argument("--no-compile-software", action="store_true", help="Disable Software compilation only.") builder_group.add_argument("--no-compile-gateware", action="store_true", help="Disable Gateware compilation only.") - builder_group.add_argument("--lto", action="store_true", help="Enable LTO (Link Time Optimization) for Software compilation.") builder_group.add_argument("--csr-csv", default=None, help="Write SoC mapping to the specified CSV file.") builder_group.add_argument("--csr-json", default=None, help="Write SoC mapping to the specified JSON file.") builder_group.add_argument("--csr-svd", default=None, help="Write SoC mapping to the specified SVD file.") builder_group.add_argument("--memory-x", default=None, help="Write SoC Memory Regions to the specified Memory-X file.") builder_group.add_argument("--doc", action="store_true", help="Generate SoC Documentation.") + bios_group = parser.add_argument_group(title="BIOS options") # FIXME: Move? + bios_group.add_argument("--bios-lto", action="store_true", help="Enable BIOS LTO (Link Time Optimization) compilation.") + bios_group.add_argument("--bios-console", default="full" , help="Select BIOS console config.", choices=["full", "no-history", "no-autocomplete", "lite", "disable"]) def builder_argdict(args): return { @@ -409,10 +418,11 @@ def builder_argdict(args): "build_backend" : args.build_backend, "compile_software" : (not args.no_compile) and (not args.no_compile_software), "compile_gateware" : (not args.no_compile) and (not args.no_compile_gateware), - "lto" : args.lto, "csr_csv" : args.csr_csv, "csr_json" : args.csr_json, "csr_svd" : args.csr_svd, "memory_x" : args.memory_x, "generate_doc" : args.doc, + "bios_lto" : args.bios_lto, + "bios_console" : args.bios_console, } diff --git a/litex/soc/integration/common.py b/litex/soc/integration/common.py index 478d57c49..1cdb9b0fa 100644 --- a/litex/soc/integration/common.py +++ b/litex/soc/integration/common.py @@ -39,7 +39,8 @@ def get_mem_regions(filename_or_regions, offset): regions = {filename: f"{offset:08x}"} return regions -def get_mem_data(filename_or_regions, endianness="big", mem_size=None, offset=0): +def get_mem_data(filename_or_regions, data_width=32, endianness="big", mem_size=None, offset=0): + assert data_width in [32, 64] # Create memory regions. regions = get_mem_regions(filename_or_regions, offset) @@ -56,23 +57,28 @@ def get_mem_data(filename_or_regions, endianness="big", mem_size=None, offset=0) data_size, mem_size)) # Fill data. - data = [0]*math.ceil(data_size/4) + bytes_per_data = data_width//8 + data = [0]*math.ceil(data_size/bytes_per_data) for filename, base in regions.items(): base = int(base, 16) with open(filename, "rb") as f: i = 0 while True: - w = f.read(4) + w = f.read(bytes_per_data) if not w: break - if len(w) != 4: - for _ in range(len(w), 4): + if len(w) != bytes_per_data: + for _ in range(len(w), bytes_per_data): w += b'\x00' unpack_order = { "little": "I" }[endianness] - data[(base - offset)//4 + i] = struct.unpack(unpack_order, w)[0] + if data_width == 32: + data[(base - offset)//bytes_per_data + i] = struct.unpack(unpack_order, w)[0] + if data_width == 64: + data[(base - offset)//bytes_per_data + i] = (struct.unpack(unpack_order, w[0:4])[0] << 0) + data[(base - offset)//bytes_per_data + i] |= (struct.unpack(unpack_order, w[4:8])[0] << 32) i += 1 return data diff --git a/litex/soc/integration/soc.py b/litex/soc/integration/soc.py old mode 100644 new mode 100755 index a9c7f5eee..377a7458d --- a/litex/soc/integration/soc.py +++ b/litex/soc/integration/soc.py @@ -332,7 +332,10 @@ class SoCBusHandler(Module): axi.AXILiteInterface : axi.AXILiteConverter, axi.AXIInterface : axi.AXIConverter, }[interface_cls] - adapted_interface = interface_cls(data_width=self.data_width) + adapted_interface = interface_cls( + data_width = self.data_width, + address_width = self.address_width + ) if direction == "m2s": master, slave = interface, adapted_interface elif direction == "s2m": @@ -353,7 +356,10 @@ class SoCBusHandler(Module): return interface # Different Bus-Standard: Return adapted interface. else: - adapted_interface = main_bus_cls(data_width=self.data_width) + adapted_interface = main_bus_cls( + data_width = self.data_width, + address_width = self.address_width + ) if direction == "m2s": master, slave = interface, adapted_interface elif direction == "s2m": @@ -886,7 +892,7 @@ class SoC(Module): colorer("added", color="green"))) setattr(self.submodules, name, SoCController(**kwargs)) - def add_ram(self, name, origin, size, contents=[], mode="rw"): + def add_ram(self, name, origin, size, contents=[], mode="rwx"): ram_cls = { "wishbone": wishbone.SRAM, "axi-lite": axi.AXILiteSRAM, @@ -897,8 +903,12 @@ class SoC(Module): "axi-lite": axi.AXILiteInterface, "axi" : axi.AXILiteInterface, # FIXME: Use AXI-Lite for now, create AXISRAM. }[self.bus.standard] - ram_bus = interface_cls(data_width=self.bus.data_width, bursting=self.bus.bursting) - ram = ram_cls(size, bus=ram_bus, init=contents, read_only=(mode == "r"), name=name) + ram_bus = interface_cls( + data_width = self.bus.data_width, + address_width = self.bus.address_width, + bursting = self.bus.bursting + ) + ram = ram_cls(size, bus=ram_bus, init=contents, read_only=("w" not in mode), name=name) self.bus.add_slave(name, ram.bus, SoCRegion(origin=origin, size=size, mode=mode)) self.check_if_exists(name) self.logger.info("RAM {} {} {}.".format( @@ -909,7 +919,7 @@ class SoC(Module): if contents != []: self.add_config(f"{name}_INIT", 1) - def add_rom(self, name, origin, size, contents=[], mode="r"): + def add_rom(self, name, origin, size, contents=[], mode="rx"): self.add_ram(name, origin, size, contents, mode=mode) def init_rom(self, name, contents=[], auto_size=True): @@ -917,7 +927,7 @@ class SoC(Module): colorer(name), colorer(f"0x{4*len(contents):x}"))) getattr(self, name).mem.init = contents - if auto_size and self.bus.regions[name].mode == "r": + if auto_size and "w" not in self.bus.regions[name].mode: self.logger.info("Auto-Resizing ROM {} from {} to {}.".format( colorer(name), colorer(f"0x{self.bus.regions[name].size:x}"), @@ -1475,7 +1485,11 @@ class LiteXSoC(SoC): sdram_size = min(sdram_size, size) # Add SDRAM region. - self.bus.add_region("main_ram", SoCRegion(origin=self.mem_map.get("main_ram", origin), size=sdram_size)) + main_ram_region = SoCRegion( + origin = self.mem_map.get("main_ram", origin), + size = sdram_size, + mode = "rwx") + self.bus.add_region("main_ram", main_ram_region) # Add CPU's direct memory buses (if not already declared) ---------------------------------- if hasattr(self.cpu, "add_memory_buses"): @@ -1906,7 +1920,7 @@ class LiteXSoC(SoC): if "write" in mode: self.comb += self.sata_irq.mem2sector_dma.trigger.eq(self.sata_mem2sector.irq) if self.irq.enabled: - self.irq.add("sata", use_loc_if_exists=True) + self.irq.add("sata_irq", use_loc_if_exists=True) # Timing constraints. self.platform.add_period_constraint(self.sata_phy.crg.cd_sata_tx.clk, 1e9/sata_clk_freq) @@ -1920,7 +1934,8 @@ class LiteXSoC(SoC): def add_pcie(self, name="pcie", phy=None, ndmas=0, max_pending_requests=8, address_width=32, with_dma_buffering = True, dma_buffering_depth=1024, with_dma_loopback = True, - with_msi = True): + with_msi = True, + with_synchronizer = False): # Imports from litepcie.core import LitePCIeEndpoint, LitePCIeMSI from litepcie.frontend.dma import LitePCIeDMA @@ -1957,9 +1972,10 @@ class LiteXSoC(SoC): assert with_msi self.check_if_exists(f"{name}_dma{i}") dma = LitePCIeDMA(phy, endpoint, - with_buffering = with_dma_buffering, buffering_depth=dma_buffering_depth, - with_loopback = with_dma_loopback, - address_width = address_width + with_buffering = with_dma_buffering, buffering_depth=dma_buffering_depth, + with_loopback = with_dma_loopback, + with_synchronizer = with_synchronizer, + address_width = address_width ) setattr(self.submodules, f"{name}_dma{i}", dma) self.msis[f"{name.upper()}_DMA{i}_WRITER"] = dma.writer.irq diff --git a/litex/soc/integration/soc_core.py b/litex/soc/integration/soc_core.py index d7208903f..1cd74ab84 100644 --- a/litex/soc/integration/soc_core.py +++ b/litex/soc/integration/soc_core.py @@ -78,7 +78,7 @@ class SoCCore(LiteXSoC): # ROM parameters integrated_rom_size = 0, - integrated_rom_mode = "r", + integrated_rom_mode = "rx", integrated_rom_init = [], # SRAM parameters @@ -156,7 +156,10 @@ class SoCCore(LiteXSoC): # ROM. # Initialize ROM from binary file when provided. if isinstance(integrated_rom_init, str): - integrated_rom_init = get_mem_data(integrated_rom_init, "little") # FIXME: Endianness. + integrated_rom_init = get_mem_data(integrated_rom_init, + endianness = "little", # FIXME: Depends on CPU. + data_width = bus_data_width + ) integrated_rom_size = 4*len(integrated_rom_init) # Disable ROM when no CPU/hard-CPU. diff --git a/litex/soc/interconnect/axi/axi_full.py b/litex/soc/interconnect/axi/axi_full.py index ae9038642..eed496363 100644 --- a/litex/soc/interconnect/axi/axi_full.py +++ b/litex/soc/interconnect/axi/axi_full.py @@ -18,53 +18,73 @@ from litex.soc.interconnect.axi.axi_common import * # AXI Definition ----------------------------------------------------------------------------------- -def ax_description(address_width, id_width): - return [ - ("addr", address_width), - ("burst", 2), # Burst type - ("len", 8), # Number of data (-1) transfers (up to 256) - ("size", 4), # Number of bytes (-1) of each data transfer (up to 1024 bits) - ("lock", 2), # * - ("prot", 3), # * - ("cache", 4), # * - ("qos", 4), # * - ("id", id_width) - ] +def ax_description(address_width, id_width=0, user_width=0): # * present for interconnect with others cores but not used by LiteX. + ax = [ + ("addr", address_width), # Address Width. + ("burst", 2), # Burst type. + ("len", 8), # Number of data (-1) transfers (up to 256). + ("size", 4), # Number of bytes (-1) of each data transfer (up to 1024 bits). + ("lock", 2), # * + ("prot", 3), # * + ("cache", 4), # * + ("qos", 4), # * + ("region", 4), # * + ] + if id_width: + ax += [("id", id_width)] # ID Width. + if user_width: + ax += [("user", user_width)] # * + return ax -def w_description(data_width, id_width): - return [ +def w_description(data_width, id_width=0, user_width=0): + w = [ ("data", data_width), ("strb", data_width//8), - ("id", id_width) ] + if id_width: + w += [("id", id_width)] + if user_width: + w += [("user", user_width)] + return w -def b_description(id_width): - return [ - ("resp", 2), - ("id", id_width) - ] +def b_description(id_width=0, user_width=0): + b = [("resp", 2)] + if id_width: + b += [("id", id_width)] + if user_width: + b += [("user", user_width)] + return b -def r_description(data_width, id_width): - return [ +def r_description(data_width, id_width=0, user_width=0): + r = [ ("resp", 2), ("data", data_width), - ("id", id_width) ] + if id_width: + r += [("id", id_width)] + if user_width: + r += [("user", user_width)] + return r class AXIInterface: - def __init__(self, data_width=32, address_width=32, id_width=1, clock_domain="sys", name=None, bursting=False): + def __init__(self, data_width=32, address_width=32, id_width=1, clock_domain="sys", name=None, bursting=False, + aw_user_width = 0, + w_user_width = 0, + b_user_width = 0, + ar_user_width = 0, + r_user_width = 0): self.data_width = data_width self.address_width = address_width self.id_width = id_width self.clock_domain = clock_domain self.bursting = bursting # FIXME: Use or add check. - self.aw = stream.Endpoint(ax_description(address_width, id_width), name=name) - self.w = stream.Endpoint(w_description(data_width, id_width), name=name) - self.b = stream.Endpoint(b_description(id_width), name=name) - self.ar = stream.Endpoint(ax_description(address_width, id_width), name=name) - self.r = stream.Endpoint(r_description(data_width, id_width), name=name) + self.aw = stream.Endpoint(ax_description(address_width, id_width, aw_user_width), name=name) + self.w = stream.Endpoint(w_description(data_width, id_width, w_user_width), name=name) + self.b = stream.Endpoint(b_description(id_width, b_user_width), name=name) + self.ar = stream.Endpoint(ax_description(address_width, id_width, ar_user_width), name=name) + self.r = stream.Endpoint(r_description(data_width, id_width, r_user_width), name=name) def connect_to_pads(self, pads, mode="master"): return connect_to_pads(self, pads, mode, axi_full=True) diff --git a/litex/soc/interconnect/axi/axi_lite.py b/litex/soc/interconnect/axi/axi_lite.py index 1090683f8..17609f02f 100644 --- a/litex/soc/interconnect/axi/axi_lite.py +++ b/litex/soc/interconnect/axi/axi_lite.py @@ -19,7 +19,11 @@ from litex.soc.interconnect.axi.axi_common import * # AXI-Lite Definition ------------------------------------------------------------------------------ def ax_lite_description(address_width): - return [("addr", address_width)] + return [ + ("addr", address_width), + ("prot", 3), # * + ] + # * present for interconnect with others cores but not used by LiteX. def w_lite_description(data_width): return [ diff --git a/litex/soc/interconnect/axi/axi_stream.py b/litex/soc/interconnect/axi/axi_stream.py index ff5db4e67..5a7ad1f1d 100644 --- a/litex/soc/interconnect/axi/axi_stream.py +++ b/litex/soc/interconnect/axi/axi_stream.py @@ -17,27 +17,48 @@ from litex.soc.interconnect.axi.axi_common import * # AXI-Stream Definition ---------------------------------------------------------------------------- class AXIStreamInterface(stream.Endpoint): - def __init__(self, data_width=32, keep_width=0, user_width=0): + def __init__(self, data_width=32, keep_width=0, id_width=0, dest_width=0, user_width=0): self.data_width = data_width self.keep_width = keep_width + self.id_width = id_width + self.dest_width = dest_width self.user_width = user_width + + # Define Payload Layout. payload_layout = [("data", data_width)] if self.keep_width: payload_layout += [("keep", keep_width)] + + # Define Param Layout. param_layout = [] + if self.id_width: + param_layout += [("id", id_width)] + if self.dest_width: + param_layout += [("dest", dest_width)] if self.user_width: param_layout += [("user", user_width)] + + # Create Endpoint. stream.Endpoint.__init__(self, stream.EndpointDescription(payload_layout, param_layout)) def get_ios(self, bus_name="axi"): + # Control Signals. subsignals = [ Subsignal("tvalid", Pins(1)), Subsignal("tlast", Pins(1)), Subsignal("tready", Pins(1)), - Subsignal("tdata", Pins(self.data_width)), ] + + # Payload Signals. + subsignals += [Subsignal("tdata", Pins(self.data_width))] if self.keep_width: subsignals += [Subsignal("tkeep", Pins(self.keep_width))] + + # Param Signals. + if self.id_width: + subsignals += [Subsignal("tid", Pins(self.id_width))] + if self.dest_width: + subsignals += [Subsignal("tdest", Pins(self.dest_width))] if self.user_width: subsignals += [Subsignal("tuser", Pins(self.user_width))] ios = [(bus_name , 0) + tuple(subsignals)] @@ -47,21 +68,35 @@ class AXIStreamInterface(stream.Endpoint): assert mode in ["slave", "master"] r = [] if mode == "master": + # Control Signals. r.append(pads.tvalid.eq(self.valid)) r.append(self.ready.eq(pads.tready)) r.append(pads.tlast.eq(self.last)) + # Payload Signals. r.append(pads.tdata.eq(self.data)) if self.keep_width: r.append(pads.tkeep.eq(self.keep)) + # Param Signals. + if self.id_width: + r.append(pads.tid.eq(self.id)) + if self.dest_width: + r.append(pads.tdest.eq(self.dest)) if self.user_width: r.append(pads.tuser.eq(self.user)) if mode == "slave": + # Control Signals. r.append(self.valid.eq(pads.tvalid)) r.append(pads.tready.eq(self.ready)) r.append(self.last.eq(pads.tlast)) + # Payload Signals. r.append(self.data.eq(pads.tdata)) if self.keep_width: r.append(self.keep.eq(pads.tkeep)) + # Param Signals. + if self.id_width: + r.append(self.id.eq(pads.tid)) + if self.dest_width: + r.append(self.dest.eq(pads.tdest)) if self.user_width: r.append(self.user.eq(pads.tuser)) return r diff --git a/litex/soc/interconnect/stream.py b/litex/soc/interconnect/stream.py index 1543cdfaa..dde5e23be 100644 --- a/litex/soc/interconnect/stream.py +++ b/litex/soc/interconnect/stream.py @@ -766,7 +766,32 @@ class PipeReady(Module): # Buffer ------------------------------------------------------------------------------------------- -class Buffer(PipeValid): pass # FIXME: Replace Buffer with PipeValid in codebase? +class Buffer(Module): + """Pipe valid/payload and/or ready to cut timing path""" + def __init__(self, layout, pipe_valid=True, pipe_ready=False): + self.sink = sink = Endpoint(layout) + self.source = source = Endpoint(layout) + + # # # + + pipeline = [] + + # Pipe Valid (Optional). + if pipe_valid: + self.submodules.pipe_valid = PipeValid(layout) + pipeline.append(self.pipe_valid) + + # Pipe Ready (Optional). + if pipe_ready: + self.submodules.pipe_ready = PipeReady(layout) + pipeline.append(self.pipe_ready) + + # Buffer Pipeline. + self.submodules.pipeline = Pipeline( + sink, + *pipeline, + source + ) # Cast --------------------------------------------------------------------------------------------- diff --git a/litex/soc/interconnect/wishbone.py b/litex/soc/interconnect/wishbone.py index 9e3cf8f7f..d97a3bd66 100644 --- a/litex/soc/interconnect/wishbone.py +++ b/litex/soc/interconnect/wishbone.py @@ -46,9 +46,12 @@ CTI_BURST_END = 0b111 class Interface(Record): - def __init__(self, data_width=32, adr_width=30, bursting=False): + def __init__(self, data_width=32, adr_width=30, bursting=False, **kwargs): self.data_width = data_width - self.adr_width = adr_width + if kwargs.get("address_width", False): + # FIXME: Improve or switch Wishbone to byte addressing instead of word addressing. + adr_width = kwargs["address_width"] - int(log2(data_width//8)) + self.adr_width = adr_width self.bursting = bursting Record.__init__(self, set_layout_parameters(_layout, adr_width = adr_width, @@ -257,42 +260,40 @@ class DownConverter(Module): # # # - skip = Signal() - counter = Signal(max=ratio) + skip = Signal() + done = Signal() + count = Signal(max=ratio) - # Control Path - fsm = FSM(reset_state="IDLE") - fsm = ResetInserter()(fsm) - self.submodules.fsm = fsm - self.comb += fsm.reset.eq(~master.cyc) - fsm.act("IDLE", - NextValue(counter, 0), - If(master.stb & master.cyc, - NextState("CONVERT"), - ) - ) - fsm.act("CONVERT", - slave.adr.eq(Cat(counter, master.adr)), - Case(counter, {i: slave.sel.eq(master.sel[i*dw_to//8:]) for i in range(ratio)}), + # Control Path. + self.comb += [ + done.eq(count == (ratio - 1)), If(master.stb & master.cyc, skip.eq(slave.sel == 0), - slave.we.eq(master.we), slave.cyc.eq(~skip), slave.stb.eq(~skip), + slave.we.eq(master.we), If(slave.ack | skip, - NextValue(counter, counter + 1), - If(counter == (ratio - 1), - master.ack.eq(1), - NextState("IDLE") - ) + master.ack.eq(done) ) ) - ) + ] + self.sync += [ + If((slave.stb & slave.cyc & slave.ack) | skip, + count.eq(count + 1) + ), + If(master.ack | ~master.cyc, + count.eq(0) + ) + ] - # Write Datapath - self.comb += Case(counter, {i: slave.dat_w.eq(master.dat_w[i*dw_to:]) for i in range(ratio)}) + # Address. + self.comb += slave.adr.eq(Cat(count, master.adr)) - # Read Datapath + # Write Datapath. + self.comb += Case(count, {i: slave.dat_w.eq(master.dat_w[i*dw_to:]) for i in range(ratio)}) + self.comb += Case(count, {i: slave.sel.eq(master.sel[i*dw_to//8:]) for i in range(ratio)}), + + # Read Datapath. dat_r = Signal(dw_from, reset_less=True) self.comb += master.dat_r.eq(Cat(dat_r[dw_to:], slave.dat_r)) self.sync += If(slave.ack | skip, dat_r.eq(master.dat_r)) diff --git a/litex/soc/software/bios/Makefile b/litex/soc/software/bios/Makefile index 3dd797933..e85fc40ba 100755 --- a/litex/soc/software/bios/Makefile +++ b/litex/soc/software/bios/Makefile @@ -21,18 +21,22 @@ OBJECTS = boot-helper.o \ sim_debug.o \ main.o -ifneq "$(or $(TERM_NO_COMPLETE),$(TERM_MINI))" "" -CFLAGS += -DTERM_NO_COMPLETE +ifneq "$(or $(BIOS_CONSOLE_NO_AUTOCOMPLETE),$(BIOS_CONSOLE_LITE))" "" +CFLAGS += -DBIOS_CONSOLE_NO_AUTOCOMPLETE else OBJECTS += complete.o endif -ifdef TERM_NO_HIST -CFLAGS += -DTERM_NO_HIST +ifdef BIOS_CONSOLE_NO_HISTORY +CFLAGS += -DBIOS_CONSOLE_NO_HISTORY endif -ifdef TERM_MINI -CFLAGS += -DTERM_MINI +ifdef BIOS_CONSOLE_DISABLE +CFLAGS += -DBIOS_CONSOLE_DISABLE +endif + +ifdef BIOS_CONSOLE_LITE +CFLAGS += -DBIOS_CONSOLE_LITE OBJECTS += readline_simple.o else OBJECTS += readline.o diff --git a/litex/soc/software/bios/command.h b/litex/soc/software/bios/command.h index 5124d24c8..d9402bcca 100644 --- a/litex/soc/software/bios/command.h +++ b/litex/soc/software/bios/command.h @@ -32,17 +32,20 @@ struct command_struct { extern struct command_struct *const __bios_cmd_start[]; extern struct command_struct *const __bios_cmd_end[]; -#define define_command(cmd_name, handler, help_txt, group_id) \ - struct command_struct s_##cmd_name = { \ - .func = (cmd_handler)handler, \ - .name = #cmd_name, \ - .help = help_txt, \ - .group = group_id, \ - }; \ - const struct command_struct *__bios_cmd_##cmd_name __attribute__((__used__)) \ - __attribute__((__section__(".bios_cmd"))) = &s_##cmd_name +#ifdef BIOS_CONSOLE_BIOS_CONSOLE_DISABLE + #define define_command(cmd_name, handler, help_txt, group_id) +#else + #define define_command(cmd_name, handler, help_txt, group_id) \ + struct command_struct s_##cmd_name = { \ + .func = (cmd_handler)handler, \ + .name = #cmd_name, \ + .help = help_txt, \ + .group = group_id, \ + }; \ + const struct command_struct *__bios_cmd_##cmd_name __attribute__((__used__)) \ + __attribute__((__section__(".bios_cmd"))) = &s_##cmd_name + struct command_struct *command_dispatcher(char *command, int nb_params, char **params); -struct command_struct *command_dispatcher(char *command, int nb_params, char **params); - -#endif + #endif +#endif \ No newline at end of file diff --git a/litex/soc/software/bios/main.c b/litex/soc/software/bios/main.c index d92694b9b..bdb9a926d 100644 --- a/litex/soc/software/bios/main.c +++ b/litex/soc/software/bios/main.c @@ -80,11 +80,13 @@ static void boot_sequence(void) __attribute__((__used__)) int main(int i, char **c) { +#ifndef BIOS_CONSOLE_DISABLE char buffer[CMD_LINE_BUFFER_SIZE]; char *params[MAX_PARAM]; char *command; struct command_struct *cmd; int nb_params; +#endif int sdr_ok; #ifdef CONFIG_CPU_HAS_INTERRUPT @@ -207,8 +209,11 @@ __attribute__((__used__)) int main(int i, char **c) #endif /* Console */ +#ifdef BIOS_CONSOLE_DISABLE + printf("--======= \e[1mDone (No Console) \e[0m ==========--\n"); +#else printf("--============= \e[1mConsole\e[0m ================--\n"); -#if !defined(TERM_MINI) && !defined(TERM_NO_HIST) +#if !defined(BIOS_CONSOLE_LITE) && !defined(BIOS_CONSOLE_NO_HISTORY) hist_init(); #endif printf("\n%s", PROMPT); @@ -223,5 +228,6 @@ __attribute__((__used__)) int main(int i, char **c) } printf("\n%s", PROMPT); } +#endif return 0; } diff --git a/litex/soc/software/bios/readline.c b/litex/soc/software/bios/readline.c index d386a84a5..f477eeb95 100644 --- a/litex/soc/software/bios/readline.c +++ b/litex/soc/software/bios/readline.c @@ -16,7 +16,7 @@ #include "readline.h" #include "complete.h" -#ifndef TERM_NO_HIST +#ifndef BIOS_CONSOLE_NO_HISTORY static int hist_max = 0; static int hist_add_idx = 0; static int hist_cur = 0; @@ -76,7 +76,7 @@ static int read_key(void) return c; } -#ifndef TERM_NO_HIST +#ifndef BIOS_CONSOLE_NO_HISTORY static void cread_add_to_hist(char *line) { strcpy(&hist_lines[hist_add_idx][0], line); @@ -189,7 +189,7 @@ int readline(char *buf, int len) int insert = 1; unsigned char ichar; -#ifndef TERM_NO_COMPLETE +#ifndef BIOS_CONSOLE_NO_AUTOCOMPLETE char tmp; int reprint, i; char *completestr; @@ -204,7 +204,7 @@ int readline(char *buf, int len) switch (ichar) { case '\t': -#ifndef TERM_NO_COMPLETE +#ifndef BIOS_CONSOLE_NO_AUTOCOMPLETE buf[eol_num] = 0; tmp = buf[num]; @@ -306,7 +306,7 @@ int readline(char *buf, int len) case KEY_UP: case KEY_DOWN: { -#ifndef TERM_NO_HIST +#ifndef BIOS_CONSOLE_NO_HISTORY char * hline; if (ichar == KEY_UP) hline = hist_prev(); @@ -343,7 +343,7 @@ int readline(char *buf, int len) len = eol_num; buf[eol_num] = '\0'; -#ifndef TERM_NO_HIST +#ifndef BIOS_CONSOLE_NO_HISTORY if (buf[0] && buf[0] != CREAD_HIST_CHAR) cread_add_to_hist(buf); hist_cur = hist_add_idx; diff --git a/litex/soc/software/liblitedram/sdram.c b/litex/soc/software/liblitedram/sdram.c index 53acec829..48bb2bf48 100644 --- a/litex/soc/software/liblitedram/sdram.c +++ b/litex/soc/software/liblitedram/sdram.c @@ -326,7 +326,7 @@ static unsigned int sdram_write_read_check_test_pattern(int module, unsigned int command_pwr(DFII_COMMAND_CAS|DFII_COMMAND_WE|DFII_COMMAND_CS|DFII_COMMAND_WRDATA); cdelay(15); -#ifdef SDRAM_PHY_ECP5DDRPHY +#if defined(SDRAM_PHY_ECP5DDRPHY) || defined(SDRAM_PHY_GW2DDRPHY) ddrphy_burstdet_clr_write(1); #endif @@ -362,7 +362,7 @@ static unsigned int sdram_write_read_check_test_pattern(int module, unsigned int } } -#ifdef SDRAM_PHY_ECP5DDRPHY +#if defined(SDRAM_PHY_ECP5DDRPHY) || defined(SDRAM_PHY_GW2DDRPHY) if (((ddrphy_burstdet_seen_read() >> module) & 0x1) != 1) errors += 1; #endif @@ -894,7 +894,7 @@ static void sdram_read_leveling_rst_delay(int module) { /* Un-select module */ ddrphy_dly_sel_write(0); -#ifdef SDRAM_PHY_ECP5DDRPHY +#if defined(SDRAM_PHY_ECP5DDRPHY) || defined(SDRAM_PHY_GW2DDRPHY) /* Sync all DQSBUFM's, By toggling all dly_sel (DQSBUFM.PAUSE) lines. */ ddrphy_dly_sel_write(0xff); ddrphy_dly_sel_write(0); @@ -911,7 +911,7 @@ static void sdram_read_leveling_inc_delay(int module) { /* Un-select module */ ddrphy_dly_sel_write(0); -#ifdef SDRAM_PHY_ECP5DDRPHY +#if defined(SDRAM_PHY_ECP5DDRPHY) || defined(SDRAM_PHY_GW2DDRPHY) /* Sync all DQSBUFM's, By toggling all dly_sel (DQSBUFM.PAUSE) lines. */ ddrphy_dly_sel_write(0xff); ddrphy_dly_sel_write(0); diff --git a/litex/tools/litex_client.py b/litex/tools/litex_client.py index 3abb57628..e59b77154 100644 --- a/litex/tools/litex_client.py +++ b/litex/tools/litex_client.py @@ -36,11 +36,19 @@ class RemoteClient(EtherboneIPC, CSRBuilder): self.debug = debug self.base_address = base_address if base_address is not None else 0 + def _receive_server_info(self): + info = str(self.socket.recv(128)) + + # With LitePCIe, CSRs are translated to 0 to limit BAR0 size, so also translate base address. + if "CommPCIe" in info: + self.base_address = -self.mems.csr.base + def open(self): if hasattr(self, "socket"): return self.socket = socket.create_connection((self.host, self.port), 5.0) self.socket.settimeout(5.0) + self._receive_server_info() def close(self): if not hasattr(self, "socket"): @@ -99,10 +107,6 @@ def dump_identifier(host, csr_csv, port): bus = RemoteClient(host=host, csr_csv=csr_csv, port=port) bus.open() - # On PCIe designs, CSR is remapped to 0 to limit BAR0 size. - if hasattr(bus.bases, "pcie_phy"): - bus.base_address = -bus.mems.csr.base - fpga_identifier = "" for i in range(256): @@ -119,10 +123,6 @@ def dump_registers(host, csr_csv, port, filter=None): bus = RemoteClient(host=host, csr_csv=csr_csv, port=port) bus.open() - # On PCIe designs, CSR is remapped to 0 to limit BAR0 size. - if hasattr(bus.bases, "pcie_phy"): - bus.base_address = -bus.mems.csr.base - for name, register in bus.regs.__dict__.items(): if (filter is None) or filter in name: print("0x{:08x} : 0x{:08x} {}".format(register.addr, register.read(), name)) diff --git a/litex/tools/litex_contributors.py b/litex/tools/litex_contributors.py index fc6afb4af..666e02fd7 100755 --- a/litex/tools/litex_contributors.py +++ b/litex/tools/litex_contributors.py @@ -27,12 +27,14 @@ class Author: def add_year(self, year): self.years.append(year) self.years = make_unique(self.years) + self.years.sort() # Use Git Log + Processing to create the list of Contibutors --------------------------------------- companies = { - "Antmicro" : "Antmicro.com", - "Google" : "Google.com", + "Antmicro" : "Antmicro.com", + "Google" : "Google.com", + "RapidSilicon" : "RapidSilicon.com", } def list_contributors(path): @@ -41,7 +43,7 @@ def list_contributors(path): os.system(f"git log --follow --pretty=format:\"%an,%ae,%aI\" {path} | sort | uniq > contribs.csv") # Read .csv and process it. - authors = {} + contributors = {} with open("contribs.csv", newline='') as csvfile: reader = csv.reader(csvfile, delimiter=",") for line in reader: @@ -53,13 +55,14 @@ def list_contributors(path): if companies_email.lower() in email: name = companies_name email = companies_email - if name in authors.keys(): - authors[name].add_year(int(year)) + if name in contributors.keys(): + contributors[name].add_year(int(year)) else: - authors[name] = Author(email, int(year)) + contributors[name] = Author(email, int(year)) # Export Contributors. - for name, info in authors.items(): + for name in sorted(contributors.keys(), key=lambda x:x.upper()): + info = contributors[name] r = "Copyright (c) " if len(info.years) > 1: years = f"{info.years[0]}-{info.years[-1]}" diff --git a/litex/tools/litex_server.py b/litex/tools/litex_server.py index af2442a19..8a8f6339a 100755 --- a/litex/tools/litex_server.py +++ b/litex/tools/litex_server.py @@ -96,35 +96,48 @@ class RemoteServer(EtherboneIPC): self.socket.close() del self.socket + def _send_server_info(self, client_socket): + # FIXME: Formalize info/improve. + info = [] + info.append(f"{self.comm.__class__.__name__}") + info.append(f"{self.bind_ip}") + info.append(f"{self.bind_port}") + info = ":".join(info) + client_socket.sendall(bytes(info, "UTF-8")) + def _serve_thread(self): while True: client_socket, addr = self.socket.accept() + self._send_server_info(client_socket) print("Connected with " + addr[0] + ":" + str(addr[1])) try: + # Serve Etherbone reads/writes. while True: + # Receive packet. try: packet = self.receive_packet(client_socket) if packet == 0: break except: break + + # Decode Packet. packet = EtherbonePacket(packet) packet.decode() + # Get Packet's Record. record = packet.records.pop() - # Wait for lock + # Hardware lock/reservation. while self.lock: time.sleep(0.01) - - # Set lock self.lock = True - # Handle writes: + # Handle Etherbone writes. if record.writes != None: self.comm.write(record.writes.base_addr, record.writes.get_datas()) - # Handle reads + # Handle Etherbone reads. if record.reads != None: max_length = { "CommUART": 256, @@ -148,7 +161,7 @@ class RemoteServer(EtherboneIPC): packet.encode() self.send_packet(client_socket, packet) - # release lock + # Release hardware lock. self.lock = False finally: diff --git a/litex/tools/litex_sim.py b/litex/tools/litex_sim.py index 100d7069f..a83c40111 100755 --- a/litex/tools/litex_sim.py +++ b/litex/tools/litex_sim.py @@ -403,7 +403,8 @@ def main(): # Configuration -------------------------------------------------------------------------------- - cpu = CPUS.get(soc_kwargs.get("cpu_type", "vexriscv")) + cpu = CPUS.get(soc_kwargs.get("cpu_type", "vexriscv")) + bus_data_width = int(soc_kwargs["bus_data_width"]) # UART. if soc_kwargs["uart_name"] == "serial": @@ -412,7 +413,10 @@ def main(): # ROM. if args.rom_init: - soc_kwargs["integrated_rom_init"] = get_mem_data(args.rom_init, endianness=cpu.endianness) + soc_kwargs["integrated_rom_init"] = get_mem_data(args.rom_init, + data_width = bus_data_width, + endianness = cpu.endianness + ) # RAM / SDRAM. ram_boot_offset = 0x40000000 # FIXME @@ -420,8 +424,12 @@ def main(): soc_kwargs["integrated_main_ram_size"] = args.integrated_main_ram_size if args.integrated_main_ram_size: if args.ram_init is not None: - soc_kwargs["integrated_main_ram_init"] = get_mem_data(args.ram_init, endianness=cpu.endianness, offset=ram_boot_offset) - ram_boot_address = get_boot_address(args.ram_init) + soc_kwargs["integrated_main_ram_init"] = get_mem_data(args.ram_init, + data_width = bus_data_width, + endianness = cpu.endianness, + offset = ram_boot_offset + ) + ram_boot_address = get_boot_address(args.ram_init) elif args.with_sdram: assert args.ram_init is None soc_kwargs["sdram_module"] = args.sdram_module @@ -430,7 +438,11 @@ def main(): if args.sdram_from_spd_dump: soc_kwargs["sdram_spd_data"] = parse_spd_hexdump(args.sdram_from_spd_dump) if args.sdram_init is not None: - soc_kwargs["sdram_init"] = get_mem_data(args.sdram_init, endianness=cpu.endianness, offset=ram_boot_offset) + soc_kwargs["sdram_init"] = get_mem_data(args.sdram_init, + data_width = bus_data_width, + endianness = cpu.endianness, + offset = ram_boot_offset + ) ram_boot_address = get_boot_address(args.sdram_init) # Ethernet. diff --git a/litex/tools/litex_term.py b/litex/tools/litex_term.py index bf72d390e..a0e76ad9e 100755 --- a/litex/tools/litex_term.py +++ b/litex/tools/litex_term.py @@ -97,10 +97,6 @@ class CrossoverUART: if not present: raise ValueError(f"CrossoverUART {name} not present in design.") - # FIXME: On PCIe designs, CSR is remapped to 0 to limit BAR0 size. - if base_address is None and hasattr(self.bus.bases, "pcie_phy"): - self.bus.base_address = -self.bus.mems.csr.base - def open(self): self.bus.open() self.file, self.name = pty.openpty() diff --git a/test/test_axi_stream.py b/test/test_axi_stream.py new file mode 100644 index 000000000..ac6fff393 --- /dev/null +++ b/test/test_axi_stream.py @@ -0,0 +1,23 @@ +# +# This file is part of LiteX. +# +# Copyright (c) 2020-2022 Florent Kermarrec +# SPDX-License-Identifier: BSD-2-Clause + +import unittest + +from migen import * + +from litex.soc.interconnect.axi import AXIStreamInterface + +class TestAXIStream(unittest.TestCase): + def test_axi_stream_syntax(self): + axis = AXIStreamInterface(data_width=32) + axis = AXIStreamInterface(data_width=32, keep_width=4) + axis = AXIStreamInterface(data_width=32, keep_width=4, id_width=4) + axis = AXIStreamInterface(data_width=32, keep_width=4, id_width=4, dest_width=4) + axis = AXIStreamInterface(data_width=32, keep_width=4, id_width=4, dest_width=4, user_width=4) + + def test_axi_stream_get_ios(self): + axis = AXIStreamInterface(data_width=32, keep_width=4, id_width=4, dest_width=4, user_width=4) + pads = axis.get_ios() diff --git a/test/test_stream.py b/test/test_stream.py index 7da893850..d2865b7d5 100644 --- a/test/test_stream.py +++ b/test/test_stream.py @@ -50,3 +50,15 @@ class TestStream(unittest.TestCase): def test_pipe_ready(self): dut = PipeReady([("data", 8)]) self.pipe_test(dut) + + def test_buffer_valid(self): + dut = Buffer([("data", 8)], pipe_valid=True, pipe_ready=False) + self.pipe_test(dut) + + def test_buffer_ready(self): + dut = Buffer([("data", 8)], pipe_valid=False, pipe_ready=True) + self.pipe_test(dut) + + def test_buffer_valid_ready(self): + dut = Buffer([("data", 8)], pipe_valid=True, pipe_ready=True) + self.pipe_test(dut)