diff --git a/.travis.yml b/.travis.yml index f461f48c9..8f491ae73 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,5 @@ jobs: include: - - os: linux - dist: xenial - language: python - python: "3.5" - os: linux dist: xenial language: python diff --git a/CHANGES b/CHANGES index 221c91be1..f4b28cd8a 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,22 @@ +[> 2020.XX, planned for July 2020 +--------------------------------- + + [> Issues resolved + ------------------ + - Fix flush_cpu_icache on VexRiscv. + + [> Added Features + ------------------ + - BIOS history, autocomplete. + - Pluggable CPUs. + - Add nMigen dependency. + - Properly integrate Minerva CPU. + + [> API changes/Deprecation + -------------------------- + - NA + + [> 2020.04, released April 28th, 2020 ------------------------------------- diff --git a/MANIFEST.in b/MANIFEST.in index d64974bd3..683cad06c 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1 +1,11 @@ graft litex/build/sim +graft litex/soc/software +graft litex/soc/cores/cpu/blackparrot +graft litex/soc/cores/cpu/lm32 +graft litex/soc/cores/cpu/microwatt +graft litex/soc/cores/cpu/minerva +graft litex/soc/cores/cpu/mor1kx +graft litex/soc/cores/cpu/picorv32 +graft litex/soc/cores/cpu/rocket +graft litex/soc/cores/cpu/serv +graft litex/soc/cores/cpu/vexriscv diff --git a/litex/__init__.py b/litex/__init__.py index 0499e31a8..5f37b49da 100644 --- a/litex/__init__.py +++ b/litex/__init__.py @@ -1,13 +1,5 @@ import sys -# retro-compat 2019-09-30 -from litex.soc.interconnect import packet -sys.modules["litex.soc.interconnect.stream_packet"] = packet - -# retro-compat 2019-09-29 -from litex.soc.integration import export -sys.modules["litex.soc.integration.cpu_interface"] = export - from litex.tools.litex_client import RemoteClient def get_data_mod(data_type, data_name): diff --git a/litex/boards/platforms/arty.py b/litex/boards/platforms/arty.py index 1e2d8743e..1f8101d47 100644 --- a/litex/boards/platforms/arty.py +++ b/litex/boards/platforms/arty.py @@ -3,7 +3,8 @@ # License: BSD from litex.build.generic_platform import * -from litex.build.xilinx import XilinxPlatform, VivadoProgrammer +from litex.build.xilinx import XilinxPlatform +from litex.build.openocd import OpenOCD # IOs ---------------------------------------------------------------------------------------------- @@ -257,4 +258,9 @@ class Platform(XilinxPlatform): self.add_platform_command("set_property INTERNAL_VREF 0.675 [get_iobanks 34]") def create_programmer(self): - return VivadoProgrammer(flash_part="n25q128-3.3v-spi-x1_x2_x4") + bscan_spi = "bscan_spi_xc7a100t.bit" if "xc7a100t" in self.device else "bscan_spi_xc7a35t.bit" + return OpenOCD("openocd_xc7_ft2232.cfg", bscan_spi) + + def do_finalize(self, fragment): + XilinxPlatform.do_finalize(self, fragment) + self.add_period_constraint(self.lookup_request("clk100", loose=True), 1e9/100e6) diff --git a/litex/boards/platforms/avalanche.py b/litex/boards/platforms/avalanche.py index 5de18cde7..ac5f568b3 100644 --- a/litex/boards/platforms/avalanche.py +++ b/litex/boards/platforms/avalanche.py @@ -92,3 +92,8 @@ class Platform(MicrosemiPlatform): def __init__(self): MicrosemiPlatform.__init__(self, "MPF300TS_ES-FCG484-1", _io) + + def do_finalize(self, fragment): + MicrosemiPlatform.do_finalize(self, fragment) + self.add_period_constraint(self.lookup_request("clk50", 0, loose=True), 1e9/50e6) + self.add_period_constraint(self.lookup_request("clk50", 1, loose=True), 1e9/50e6) diff --git a/litex/boards/platforms/de0nano.py b/litex/boards/platforms/de0nano.py index 042a543e5..819a47eb3 100644 --- a/litex/boards/platforms/de0nano.py +++ b/litex/boards/platforms/de0nano.py @@ -114,3 +114,7 @@ class Platform(AlteraPlatform): def create_programmer(self): return USBBlaster() + + def do_finalize(self, fragment): + AlteraPlatform.do_finalize(self, fragment) + self.add_period_constraint(self.lookup_request("clk50", loose=True), 1e9/50e6) diff --git a/litex/boards/platforms/genesys2.py b/litex/boards/platforms/genesys2.py index 523aa92b9..7da31c872 100644 --- a/litex/boards/platforms/genesys2.py +++ b/litex/boards/platforms/genesys2.py @@ -3,6 +3,7 @@ from litex.build.generic_platform import * from litex.build.xilinx import XilinxPlatform, VivadoProgrammer +from litex.build.openocd import OpenOCD # IOs ---------------------------------------------------------------------------------------------- @@ -116,11 +117,9 @@ class Platform(XilinxPlatform): XilinxPlatform.__init__(self, "xc7k325t-ffg900-2", _io, _connectors, toolchain="vivado") def create_programmer(self): - return VivadoProgrammer() + return OpenOCD("openocd_xc7_ft2232.cfg", "bscan_spi_xc7a325t.bit") def do_finalize(self, fragment): XilinxPlatform.do_finalize(self, fragment) - try: - self.add_period_constraint(self.lookup_request("eth_clocks").rx, 1e9/125e6) - except ConstraintError: - pass + self.add_period_constraint(self.lookup_request("clk200", loose=True), 1e9/200e6) + self.add_period_constraint(self.lookup_request("eth_clocks:rx", loose=True), 1e9/125e6) diff --git a/litex/boards/platforms/icebreaker.py b/litex/boards/platforms/icebreaker.py index a46651ef3..1525ba6be 100644 --- a/litex/boards/platforms/icebreaker.py +++ b/litex/boards/platforms/icebreaker.py @@ -86,3 +86,7 @@ class Platform(LatticePlatform): def create_programmer(self): return IceStormProgrammer() + + def do_finalize(self, fragment): + LatticePlatform.do_finalize(self, fragment) + self.add_period_constraint(self.lookup_request("clk12", loose=True), 1e9/12e6) diff --git a/litex/boards/platforms/kc705.py b/litex/boards/platforms/kc705.py index d1f02a505..dcb0001e1 100644 --- a/litex/boards/platforms/kc705.py +++ b/litex/boards/platforms/kc705.py @@ -3,7 +3,8 @@ # This file is Copyright (c) 2015 Yann Sionneau from litex.build.generic_platform import * -from litex.build.xilinx import XilinxPlatform, VivadoProgrammer +from litex.build.xilinx import XilinxPlatform +from litex.build.openocd import OpenOCD # IOs ---------------------------------------------------------------------------------------------- @@ -548,20 +549,11 @@ set_property CONFIG_VOLTAGE 2.5 [current_design] self.toolchain.additional_commands = ["write_cfgmem -force -format bin -interface spix4 -size 16 -loadbit \"up 0x0 {build_name}.bit\" -file {build_name}.bin"] def create_programmer(self): - return VivadoProgrammer() + return OpenOCD("openocd_xc7_ft2232.cfg", "bscan_spi_xc7a325t.bit") def do_finalize(self, fragment): XilinxPlatform.do_finalize(self, fragment) - try: - self.add_period_constraint(self.lookup_request("clk200").p, 1e9/200e6) - except ConstraintError: - pass - try: - self.add_period_constraint(self.lookup_request("eth_clocks").rx, 1e9/125e6) - except ConstraintError: - pass - try: - self.add_period_constraint(self.lookup_request("eth_clocks").tx, 1e9/125e6) - except ConstraintError: - pass + self.add_period_constraint(self.lookup_request("clk200", loose=True), 1e9/200e6) + self.add_period_constraint(self.lookup_request("eth_clocks:rx", loose=True), 1e9/125e6) + self.add_period_constraint(self.lookup_request("eth_clocks:tx", loose=True), 1e9/125e6) self.add_platform_command("set_property DCI_CASCADE {{32 34}} [get_iobanks 33]") diff --git a/litex/boards/platforms/kcu105.py b/litex/boards/platforms/kcu105.py index 038df0fbc..1230011de 100644 --- a/litex/boards/platforms/kcu105.py +++ b/litex/boards/platforms/kcu105.py @@ -498,6 +498,8 @@ class Platform(XilinxPlatform): def do_finalize(self, fragment): XilinxPlatform.do_finalize(self, fragment) + self.add_period_constraint(self.lookup_request("clk125", loose=True), 1e9/125e6) + self.add_period_constraint(self.lookup_request("clk300", loose=True), 1e9/300e6) self.add_platform_command("set_property INTERNAL_VREF 0.84 [get_iobanks 44]") self.add_platform_command("set_property INTERNAL_VREF 0.84 [get_iobanks 45]") self.add_platform_command("set_property INTERNAL_VREF 0.84 [get_iobanks 46]") diff --git a/litex/boards/platforms/machxo3.py b/litex/boards/platforms/machxo3.py index ebf72d6a1..d47242f41 100644 --- a/litex/boards/platforms/machxo3.py +++ b/litex/boards/platforms/machxo3.py @@ -92,3 +92,7 @@ class Platform(LatticePlatform): """ return LatticeProgrammer(_xcf_template) + + def do_finalize(self, fragment): + LatticePlatform.do_finalize(self, fragment) + self.add_period_constraint(self.lookup_request("clk12", loose=True), 1e9/12e6) diff --git a/litex/boards/platforms/minispartan6.py b/litex/boards/platforms/minispartan6.py index 046ee16b3..0ad7e0799 100644 --- a/litex/boards/platforms/minispartan6.py +++ b/litex/boards/platforms/minispartan6.py @@ -3,7 +3,7 @@ from litex.build.generic_platform import * from litex.build.xilinx import XilinxPlatform -from litex.build.xilinx.programmer import FpgaProg +from litex.build.xilinx.programmer import XC3SProg # IOs ---------------------------------------------------------------------------------------------- @@ -136,4 +136,9 @@ class Platform(XilinxPlatform): XilinxPlatform.__init__(self, device+"-3-ftg256", _io, _connectors) def create_programmer(self): - return FpgaProg() + return XC3SProg(cable="ftdi") + + def do_finalize(self, fragment): + XilinxPlatform.do_finalize(self, fragment) + self.add_period_constraint(self.lookup_request("clk32", loose=True), 1e9/32e6) + self.add_period_constraint(self.lookup_request("clk50", loose=True), 1e9/50e6) diff --git a/litex/boards/platforms/netv2.py b/litex/boards/platforms/netv2.py index f3e8abc8e..b598172c7 100644 --- a/litex/boards/platforms/netv2.py +++ b/litex/boards/platforms/netv2.py @@ -2,7 +2,8 @@ # License: BSD from litex.build.generic_platform import * -from litex.build.xilinx import XilinxPlatform, VivadoProgrammer +from litex.build.xilinx import XilinxPlatform +from litex.build.openocd import OpenOCD # IOs ---------------------------------------------------------------------------------------------- @@ -191,3 +192,12 @@ class Platform(XilinxPlatform): def __init__(self, device="xc7a35t"): assert device in ["xc7a35t", "xc7a100t"] XilinxPlatform.__init__(self, device + "-fgg484-2", _io, toolchain="vivado") + + def create_programmer(self): + bscan_spi = "bscan_spi_xc7a100t.bit" if "xc7a100t" in self.device else "bscan_spi_xc7a35t.bit" + return OpenOCD("openocd_netv2_rpi.cfg", bscan_spi) + + def do_finalize(self, fragment): + XilinxPlatform.do_finalize(self, fragment) + self.add_period_constraint(self.lookup_request("clk50", loose=True), 1e9/50e6) + self.add_period_constraint(self.lookup_request("eth_clocks:ref_clk", loose=True), 1e9/50e6) diff --git a/litex/boards/platforms/nexys4ddr.py b/litex/boards/platforms/nexys4ddr.py index b52ca6491..060caeb03 100644 --- a/litex/boards/platforms/nexys4ddr.py +++ b/litex/boards/platforms/nexys4ddr.py @@ -3,6 +3,7 @@ from litex.build.generic_platform import * from litex.build.xilinx import XilinxPlatform, VivadoProgrammer +from litex.build.openocd import OpenOCD # IOs ---------------------------------------------------------------------------------------------- @@ -131,4 +132,9 @@ class Platform(XilinxPlatform): self.add_platform_command("set_property INTERNAL_VREF 0.750 [get_iobanks 34]") def create_programmer(self): - return VivadoProgrammer() + return OpenOCD("openocd_xc7_ft2232.cfg", "bscan_spi_xc7a100t.bit") + + def do_finalize(self, fragment): + XilinxPlatform.do_finalize(self, fragment) + self.add_period_constraint(self.lookup_request("clk100", loose=True), 1e9/100e6) + self.add_period_constraint(self.lookup_request("eth_clocks:ref_clk", loose=True), 1e9/50e6) diff --git a/litex/boards/platforms/nexys_video.py b/litex/boards/platforms/nexys_video.py index dad949b8f..6dbb9456f 100644 --- a/litex/boards/platforms/nexys_video.py +++ b/litex/boards/platforms/nexys_video.py @@ -3,6 +3,7 @@ from litex.build.generic_platform import * from litex.build.xilinx import XilinxPlatform, VivadoProgrammer +from litex.build.openocd import OpenOCD # IOs ---------------------------------------------------------------------------------------------- @@ -230,9 +231,8 @@ class Platform(XilinxPlatform): "-loadbit \"up 0x0 {build_name}.bit\" -file {build_name}.bin"] self.add_platform_command("set_property INTERNAL_VREF 0.750 [get_iobanks 35]") - def create_programmer(self): - return VivadoProgrammer(flash_part="n25q128-3.3v-spi-x1_x2_x4") + return OpenOCD("openocd_xc7_ft2232.cfg", "bscan_spi_xc7a200t.bit") def do_finalize(self, fragment): XilinxPlatform.do_finalize(self, fragment) @@ -240,3 +240,8 @@ class Platform(XilinxPlatform): self.add_period_constraint(self.lookup_request("eth_clocks").rx, 1e9/125e6) except ConstraintError: pass + + def do_finalize(self, fragment): + XilinxPlatform.do_finalize(self, fragment) + self.add_period_constraint(self.lookup_request("clk100", loose=True), 1e9/100e6) + self.add_period_constraint(self.lookup_request("eth_clocks:rx", loose=True), 1e9/125e6) diff --git a/litex/boards/platforms/tinyfpga_bx.py b/litex/boards/platforms/tinyfpga_bx.py index 4cfe96382..a1bfd5e52 100644 --- a/litex/boards/platforms/tinyfpga_bx.py +++ b/litex/boards/platforms/tinyfpga_bx.py @@ -67,3 +67,7 @@ class Platform(LatticePlatform): def create_programmer(self): return TinyProgProgrammer() + + def do_finalize(self, fragment): + LatticePlatform.do_finalize(self, fragment) + self.add_period_constraint(self.lookup_request("clk16", loose=True), 1e9/16e6) diff --git a/litex/boards/platforms/ulx3s.py b/litex/boards/platforms/ulx3s.py index 20640fc38..f2859cba0 100644 --- a/litex/boards/platforms/ulx3s.py +++ b/litex/boards/platforms/ulx3s.py @@ -3,6 +3,7 @@ from litex.build.generic_platform import * from litex.build.lattice import LatticePlatform +from litex.build.lattice.programmer import UJProg # IOs ---------------------------------------------------------------------------------------------- @@ -84,6 +85,13 @@ _io = [ Subsignal("n", Pins("C10")), IOStandard("LVCMOS33") ), + + ("usb", 0, + Subsignal("d_p", Pins("D15")), + Subsignal("d_n", Pins("E15")), + Subsignal("pullup", Pins("B12 C12")), + IOStandard("LVCMOS33") + ), ] # Platform ----------------------------------------------------------------------------------------- @@ -94,3 +102,10 @@ class Platform(LatticePlatform): def __init__(self, device="LFE5U-45F", **kwargs): LatticePlatform.__init__(self, device + "-6BG381C", _io, **kwargs) + + def create_programmer(self): + return UJProg() + + def do_finalize(self, fragment): + LatticePlatform.do_finalize(self, fragment) + self.add_period_constraint(self.lookup_request("clk25", loose=True), 1e9/25e6) diff --git a/litex/boards/platforms/versa_ecp5.py b/litex/boards/platforms/versa_ecp5.py index e3b40b418..4ea3df466 100644 --- a/litex/boards/platforms/versa_ecp5.py +++ b/litex/boards/platforms/versa_ecp5.py @@ -4,7 +4,7 @@ from litex.build.generic_platform import * from litex.build.lattice import LatticePlatform -from litex.build.lattice.programmer import LatticeProgrammer +from litex.build.lattice.programmer import OpenOCDJTAGProgrammer # IOs ---------------------------------------------------------------------------------------------- @@ -224,12 +224,10 @@ class Platform(LatticePlatform): def __init__(self, **kwargs): LatticePlatform.__init__(self, "LFE5UM5G-45F-8BG381C", _io, _connectors, **kwargs) + def create_programmer(self): + return OpenOCDJTAGProgrammer("openocd_versa_ecp5.cfg") + def do_finalize(self, fragment): - try: - self.add_period_constraint(self.lookup_request("eth_clocks", 0).rx, 1e9/125e6) - except ConstraintError: - pass - try: - self.add_period_constraint(self.lookup_request("eth_clocks", 1).rx, 1e9/125e6) - except ConstraintError: - pass + self.add_period_constraint(self.lookup_request("clk100", loose=True), 1e9/100e6) + self.add_period_constraint(self.lookup_request("eth_clocks:rx", 0, loose=True), 1e9/125e6) + self.add_period_constraint(self.lookup_request("eth_clocks:rx", 1, loose=True), 1e9/125e6) diff --git a/litex/boards/targets/arty.py b/litex/boards/targets/arty.py index 8f3368389..29e33bc3e 100755 --- a/litex/boards/targets/arty.py +++ b/litex/boards/targets/arty.py @@ -3,6 +3,7 @@ # This file is Copyright (c) 2015-2019 Florent Kermarrec # License: BSD +import os import argparse from migen import * @@ -96,20 +97,25 @@ class BaseSoC(SoCCore): # Build -------------------------------------------------------------------------------------------- def main(): - parser = argparse.ArgumentParser(description="LiteX SoC on Arty") + parser = argparse.ArgumentParser(description="LiteX SoC on Arty A7") + parser.add_argument("--build", action="store_true", help="Build bitstream") + parser.add_argument("--load", action="store_true", help="Load bitstream") builder_args(parser) soc_sdram_args(parser) vivado_build_args(parser) - parser.add_argument("--with-ethernet", action="store_true", help="enable Ethernet support") - parser.add_argument("--with-etherbone", action="store_true", help="enable Etherbone support") + parser.add_argument("--with-ethernet", action="store_true", help="Enable Ethernet support") + parser.add_argument("--with-etherbone", action="store_true", help="Enable Etherbone support") args = parser.parse_args() assert not (args.with_ethernet and args.with_etherbone) soc = BaseSoC(with_ethernet=args.with_ethernet, with_etherbone=args.with_etherbone, **soc_sdram_argdict(args)) builder = Builder(soc, **builder_argdict(args)) - builder.build(**vivado_build_argdict(args)) + builder.build(**vivado_build_argdict(args), run=args.build) + if args.load: + prog = soc.platform.create_programmer() + prog.load_bitstream(os.path.join(builder.gateware_dir, "top.bit")) if __name__ == "__main__": main() diff --git a/litex/boards/targets/de0nano.py b/litex/boards/targets/de0nano.py index 5830f35e8..960dc48ec 100755 --- a/litex/boards/targets/de0nano.py +++ b/litex/boards/targets/de0nano.py @@ -3,6 +3,7 @@ # This file is Copyright (c) 2015-2020 Florent Kermarrec # License: BSD +import os import argparse from migen import * @@ -31,7 +32,6 @@ class _CRG(Module): # Clk / Rst clk50 = platform.request("clk50") - platform.add_period_constraint(clk50, 1e9/50e6) # PLL self.submodules.pll = pll = CycloneIVPLL(speedgrade="-6") @@ -71,14 +71,19 @@ class BaseSoC(SoCCore): def main(): parser = argparse.ArgumentParser(description="LiteX SoC on DE0 Nano") + parser.add_argument("--build", action="store_true", help="Build bitstream") + parser.add_argument("--load", action="store_true", help="Load bitstream") builder_args(parser) soc_sdram_args(parser) args = parser.parse_args() soc = BaseSoC(**soc_sdram_argdict(args)) builder = Builder(soc, **builder_argdict(args)) - builder.build() + builder.build(run=args.build) + if args.load: + prog = soc.platform.create_programmer() + prog.load_bitstream(os.path.join(builder.gateware_dir, "top.sof")) if __name__ == "__main__": main() diff --git a/litex/boards/targets/genesys2.py b/litex/boards/targets/genesys2.py index d97b68a36..d0b33def0 100755 --- a/litex/boards/targets/genesys2.py +++ b/litex/boards/targets/genesys2.py @@ -3,6 +3,7 @@ # This file is Copyright (c) 2019 Florent Kermarrec # License: BSD +import os import argparse from migen import * @@ -55,7 +56,8 @@ class BaseSoC(SoCCore): self.submodules.ddrphy = s7ddrphy.K7DDRPHY(platform.request("ddram"), memtype = "DDR3", nphases = 4, - sys_clk_freq = sys_clk_freq) + sys_clk_freq = sys_clk_freq, + cmd_latency = 1) self.add_csr("ddrphy") self.add_sdram("sdram", phy = self.ddrphy, @@ -87,6 +89,8 @@ class BaseSoC(SoCCore): def main(): parser = argparse.ArgumentParser(description="LiteX SoC on Genesys2") + parser.add_argument("--build", action="store_true", help="Build bitstream") + parser.add_argument("--load", action="store_true", help="Load bitstream") builder_args(parser) soc_sdram_args(parser) parser.add_argument("--with-ethernet", action="store_true", help="enable Ethernet support") @@ -97,8 +101,11 @@ def main(): soc = BaseSoC(with_ethernet=args.with_ethernet, with_etherbone=args.with_etherbone, **soc_sdram_argdict(args)) builder = Builder(soc, **builder_argdict(args)) - builder.build() + builder.build(run=args.build) + if args.load: + prog = soc.platform.create_programmer() + prog.load_bitstream(os.path.join(builder.gateware_dir, "top.bit")) if __name__ == "__main__": main() diff --git a/litex/boards/targets/icebreaker.py b/litex/boards/targets/icebreaker.py index 938281798..ae1363b92 100755 --- a/litex/boards/targets/icebreaker.py +++ b/litex/boards/targets/icebreaker.py @@ -14,6 +14,7 @@ # with more features, examples to run C/Rust code on the RISC-V CPU and documentation can be found # at: https://github.com/icebreaker-fpga/icebreaker-litex-examples +import os import argparse from migen import * @@ -115,18 +116,24 @@ def flash(bios_flash_offset): def main(): parser = argparse.ArgumentParser(description="LiteX SoC on iCEBreaker") - parser.add_argument("--bios-flash-offset", default=0x40000, help="BIOS offset in SPI Flash") - parser.add_argument("--flash", action="store_true", help="Load Bitstream") + parser.add_argument("--build", action="store_true", help="Build bitstream") + parser.add_argument("--load", action="store_true", help="Load bitstream") + parser.add_argument("--bios-flash-offset", default=0x40000, help="BIOS offset in SPI Flash") + parser.add_argument("--flash", action="store_true", help="Flash Bitstream") builder_args(parser) soc_core_args(parser) args = parser.parse_args() + soc = BaseSoC(args.bios_flash_offset, **soc_core_argdict(args)) + builder = Builder(soc, **builder_argdict(args)) + builder.build(run=args.build) + + if args.load: + prog = soc.platform.create_programmer() + prog.load_bitstream(os.path.join(builder.gateware_dir, "top.bin")) + if args.flash: flash(args.bios_flash_offset) - soc = BaseSoC(args.bios_flash_offset, **soc_core_argdict(args)) - builder = Builder(soc, **builder_argdict(args)) - builder.build() - if __name__ == "__main__": main() diff --git a/litex/boards/targets/kc705.py b/litex/boards/targets/kc705.py index 87290e477..9bca15823 100755 --- a/litex/boards/targets/kc705.py +++ b/litex/boards/targets/kc705.py @@ -5,6 +5,7 @@ # This file is Copyright (c) 2014-2015 Yann Sionneau # License: BSD +import os import argparse from migen import * @@ -83,16 +84,20 @@ class BaseSoC(SoCCore): def main(): parser = argparse.ArgumentParser(description="LiteX SoC on KC705") + parser.add_argument("--build", action="store_true", help="Build bitstream") + parser.add_argument("--load", action="store_true", help="Load bitstream") builder_args(parser) soc_sdram_args(parser) - parser.add_argument("--with-ethernet", action="store_true", - help="enable Ethernet support") + parser.add_argument("--with-ethernet", action="store_true", help="Enable Ethernet support") args = parser.parse_args() soc = BaseSoC(with_ethernet=args.with_ethernet, **soc_sdram_argdict(args)) builder = Builder(soc, **builder_argdict(args)) - builder.build() + builder.build(run=args.build) + if args.load: + prog = soc.platform.create_programmer() + prog.load_bitstream(os.path.join(builder.gateware_dir, "top.bit")) if __name__ == "__main__": main() diff --git a/litex/boards/targets/kcu105.py b/litex/boards/targets/kcu105.py index b632b16cc..138f3ffa7 100755 --- a/litex/boards/targets/kcu105.py +++ b/litex/boards/targets/kcu105.py @@ -3,6 +3,7 @@ # This file is Copyright (c) 2018-2019 Florent Kermarrec # License: BSD +import os import argparse from migen import * @@ -67,7 +68,6 @@ class BaseSoC(SoCCore): iodelay_clk_freq = 200e6, cmd_latency = 1) self.add_csr("ddrphy") - self.add_constant("USDDRPHY_DEBUG") self.add_sdram("sdram", phy = self.ddrphy, module = EDY4016A(sys_clk_freq, "1:4"), @@ -92,16 +92,20 @@ class BaseSoC(SoCCore): def main(): parser = argparse.ArgumentParser(description="LiteX SoC on KCU105") + parser.add_argument("--build", action="store_true", help="Build bitstream") + parser.add_argument("--load", action="store_true", help="Load bitstream") builder_args(parser) soc_sdram_args(parser) - parser.add_argument("--with-ethernet", action="store_true", - help="enable Ethernet support") + parser.add_argument("--with-ethernet", action="store_true", help="Enable Ethernet support") args = parser.parse_args() soc = BaseSoC(with_ethernet=args.with_ethernet, **soc_sdram_argdict(args)) builder = Builder(soc, **builder_argdict(args)) - builder.build() + builder.build(run=args.build) + if args.load: + prog = soc.platform.create_programmer() + prog.load_bitstream(os.path.join(builder.gateware_dir, "top.bit")) if __name__ == "__main__": main() diff --git a/litex/boards/targets/minispartan6.py b/litex/boards/targets/minispartan6.py index 638d28d18..641e11192 100755 --- a/litex/boards/targets/minispartan6.py +++ b/litex/boards/targets/minispartan6.py @@ -5,6 +5,7 @@ # This file is Copyright (c) 2014 Yann Sionneau # License: BSD +import os import argparse from fractions import Fraction @@ -69,14 +70,19 @@ class BaseSoC(SoCCore): def main(): parser = argparse.ArgumentParser(description="LiteX SoC on MiniSpartan6") + parser.add_argument("--build", action="store_true", help="Build bitstream") + parser.add_argument("--load", action="store_true", help="Load bitstream") builder_args(parser) soc_sdram_args(parser) args = parser.parse_args() soc = BaseSoC(**soc_sdram_argdict(args)) builder = Builder(soc, **builder_argdict(args)) - builder.build() + builder.build(run=args.build) + if args.load: + prog = soc.platform.create_programmer() + prog.load_bitstream(os.path.join(builder.gateware_dir, "top.bit")) if __name__ == "__main__": main() diff --git a/litex/boards/targets/netv2.py b/litex/boards/targets/netv2.py index cb4270489..7535bc3c6 100755 --- a/litex/boards/targets/netv2.py +++ b/litex/boards/targets/netv2.py @@ -3,6 +3,7 @@ # This file is Copyright (c) 2018-2019 Florent Kermarrec # License: BSD +import os import argparse from migen import * @@ -95,18 +96,21 @@ class BaseSoC(SoCCore): def main(): parser = argparse.ArgumentParser(description="LiteX SoC on NeTV2") + parser.add_argument("--build", action="store_true", help="Build bitstream") + parser.add_argument("--load", action="store_true", help="Load bitstream") builder_args(parser) soc_sdram_args(parser) - parser.add_argument("--with-ethernet", action="store_true", - help="enable Ethernet support") - parser.add_argument("--with-spi-xip", action="store_true", - help="enable SPI XIP support") + parser.add_argument("--with-ethernet", action="store_true", help="Enable Ethernet support") + parser.add_argument("--with-spi-xip", action="store_true", help="Enable SPI XIP support") args = parser.parse_args() soc = BaseSoC(with_ethernet=args.with_ethernet, with_spi_xip=args.with_spi_xip, **soc_sdram_argdict(args)) builder = Builder(soc, **builder_argdict(args)) - builder.build() + builder.build(run=args.build) + if args.load: + prog = soc.platform.create_programmer() + prog.load_bitstream(os.path.join(builder.gateware_dir, "top.bit")) if __name__ == "__main__": main() diff --git a/litex/boards/targets/nexys4ddr.py b/litex/boards/targets/nexys4ddr.py index a4b617df8..e608963fb 100755 --- a/litex/boards/targets/nexys4ddr.py +++ b/litex/boards/targets/nexys4ddr.py @@ -3,6 +3,7 @@ # This file is Copyright (c) 2018-2019 Florent Kermarrec # License: BSD +import os import argparse from migen import * @@ -117,16 +118,14 @@ class BaseSoC(SoCCore): def main(): parser = argparse.ArgumentParser(description="LiteX SoC on Nexys4DDR") + parser.add_argument("--build", action="store_true", help="Build bitstream") + parser.add_argument("--load", action="store_true", help="Load bitstream") builder_args(parser) soc_sdram_args(parser) - parser.add_argument("--sys-clk-freq", default=75e6, - help="system clock frequency (default=75MHz)") - parser.add_argument("--with-ethernet", action="store_true", - help="enable Ethernet support") - parser.add_argument("--with-spi-sdcard", action="store_true", - help="enable SPI-mode SDCard support") - parser.add_argument("--with-sdcard", action="store_true", - help="enable SDCard support") + parser.add_argument("--sys-clk-freq", default=75e6, help="System clock frequency (default=75MHz)") + parser.add_argument("--with-ethernet", action="store_true", help="Enable Ethernet support") + parser.add_argument("--with-spi-sdcard", action="store_true", help="enable SPI-mode SDCard support") + parser.add_argument("--with-sdcard", action="store_true", help="enable SDCard support") args = parser.parse_args() soc = BaseSoC(sys_clk_freq=int(float(args.sys_clk_freq)), @@ -139,8 +138,11 @@ def main(): raise ValueError("'--with-spi-sdcard' and '--with-sdcard' are mutually exclusive!") soc.add_sdcard() builder = Builder(soc, **builder_argdict(args)) - builder.build() + builder.build(run=args.build) + if args.load: + prog = soc.platform.create_programmer() + prog.load_bitstream(os.path.join(builder.gateware_dir, "top.bit")) if __name__ == "__main__": main() diff --git a/litex/boards/targets/nexys_video.py b/litex/boards/targets/nexys_video.py index 677a20f05..f53a0bfa0 100755 --- a/litex/boards/targets/nexys_video.py +++ b/litex/boards/targets/nexys_video.py @@ -3,6 +3,7 @@ # This file is Copyright (c) 2015-2019 Florent Kermarrec # License: BSD +import os import argparse from migen import * @@ -83,16 +84,20 @@ class BaseSoC(SoCCore): def main(): parser = argparse.ArgumentParser(description="LiteX SoC on Nexys Video") + parser.add_argument("--build", action="store_true", help="Build bitstream") + parser.add_argument("--load", action="store_true", help="Load bitstream") builder_args(parser) soc_sdram_args(parser) - parser.add_argument("--with-ethernet", action="store_true", - help="enable Ethernet support") + parser.add_argument("--with-ethernet", action="store_true", help="Enable Ethernet support") args = parser.parse_args() soc = BaseSoC(with_ethernet=args.with_ethernet, **soc_sdram_argdict(args)) builder = Builder(soc, **builder_argdict(args)) - builder.build() + builder.build(run=args.build) + if args.load: + prog = soc.platform.create_programmer() + prog.load_bitstream(os.path.join(builder.gateware_dir, "top.bit")) if __name__ == "__main__": main() diff --git a/litex/boards/targets/simple.py b/litex/boards/targets/simple.py index b208544fb..70872bb0c 100755 --- a/litex/boards/targets/simple.py +++ b/litex/boards/targets/simple.py @@ -4,6 +4,7 @@ # This file is Copyright (c) 2013-2014 Sebastien Bourdeauducq # License: BSD +import os import argparse import importlib @@ -41,14 +42,12 @@ class BaseSoC(SoCCore): def main(): parser = argparse.ArgumentParser(description="Generic LiteX SoC") + parser.add_argument("--build", action="store_true", help="Build bitstream") builder_args(parser) soc_core_args(parser) - parser.add_argument("--with-ethernet", action="store_true", - help="enable Ethernet support") - parser.add_argument("platform", - help="module name of the platform to build for") - parser.add_argument("--gateware-toolchain", default=None, - help="FPGA gateware toolchain used for build") + parser.add_argument("--with-ethernet", action="store_true", help="Enable Ethernet support") + parser.add_argument("platform", help="Module name of the platform to build for") + parser.add_argument("--gateware-toolchain", default=None, help="FPGA gateware toolchain used for build") args = parser.parse_args() platform_module = importlib.import_module(args.platform) @@ -58,7 +57,7 @@ def main(): platform = platform_module.Platform() soc = BaseSoC(platform, with_ethernet=args.with_ethernet, **soc_core_argdict(args)) builder = Builder(soc, **builder_argdict(args)) - builder.build() + builder.build(run=args.build) if __name__ == "__main__": diff --git a/litex/boards/targets/ulx3s.py b/litex/boards/targets/ulx3s.py index a7668e3a9..9802266ca 100755 --- a/litex/boards/targets/ulx3s.py +++ b/litex/boards/targets/ulx3s.py @@ -4,6 +4,7 @@ # This file is Copyright (c) 2018 David Shah # License: BSD +import os import argparse import sys @@ -27,7 +28,7 @@ from litedram.phy import GENSDRPHY # CRG ---------------------------------------------------------------------------------------------- class _CRG(Module): - def __init__(self, platform, sys_clk_freq): + def __init__(self, platform, sys_clk_freq, with_usb_pll=False): self.clock_domains.cd_sys = ClockDomain() self.clock_domains.cd_sys_ps = ClockDomain(reset_less=True) @@ -36,7 +37,6 @@ class _CRG(Module): # Clk / Rst clk25 = platform.request("clk25") rst = platform.request("rst") - platform.add_period_constraint(clk25, 1e9/25e6) # PLL self.submodules.pll = pll = ECP5PLL() @@ -46,6 +46,15 @@ class _CRG(Module): pll.create_clkout(self.cd_sys_ps, sys_clk_freq, phase=90) self.specials += AsyncResetSynchronizer(self.cd_sys, ~pll.locked | rst) + # USB PLL + if with_usb_pll: + self.submodules.usb_pll = usb_pll = ECP5PLL() + usb_pll.register_clkin(clk25, 25e6) + self.clock_domains.cd_usb_12 = ClockDomain() + self.clock_domains.cd_usb_48 = ClockDomain() + usb_pll.create_clkout(self.cd_usb_12, 12e6, margin=0) + usb_pll.create_clkout(self.cd_usb_48, 48e6, margin=0) + # SDRAM clock self.specials += DDROutput(1, 0, platform.request("sdram_clock"), ClockSignal("sys_ps")) @@ -64,7 +73,8 @@ class BaseSoC(SoCCore): SoCCore.__init__(self, platform, clk_freq=sys_clk_freq, **kwargs) # CRG -------------------------------------------------------------------------------------- - self.submodules.crg = _CRG(platform, sys_clk_freq) + with_usb_pll = kwargs.get("uart_name", None) == "usb_acm" + self.submodules.crg = _CRG(platform, sys_clk_freq, with_usb_pll) # SDR SDRAM -------------------------------------------------------------------------------- if not self.integrated_main_ram_size: @@ -83,14 +93,12 @@ class BaseSoC(SoCCore): def main(): parser = argparse.ArgumentParser(description="LiteX SoC on ULX3S") - parser.add_argument("--gateware-toolchain", dest="toolchain", default="trellis", - help="gateware toolchain to use, trellis (default) or diamond") - parser.add_argument("--device", dest="device", default="LFE5U-45F", - help="FPGA device, ULX3S can be populated with LFE5U-12F, LFE5U-25F, LFE5U-45F (default) or LFE5U-85F") - parser.add_argument("--sys-clk-freq", default=50e6, - help="system clock frequency (default=50MHz)") - parser.add_argument("--sdram-module", default="MT48LC16M16", - help="SDRAM module: MT48LC16M16, AS4C32M16 or AS4C16M16 (default=MT48LC16M16)") + parser.add_argument("--build", action="store_true", help="Build bitstream") + parser.add_argument("--load", action="store_true", help="Load bitstream") + parser.add_argument("--gateware-toolchain", dest="toolchain", default="trellis", help="Gateware toolchain to use, trellis (default) or diamond") + parser.add_argument("--device", dest="device", default="LFE5U-45F", help="FPGA device, ULX3S can be populated with LFE5U-45F (default) or LFE5U-85F") + parser.add_argument("--sys-clk-freq", default=50e6, help="System clock frequency (default=50MHz)") + parser.add_argument("--sdram-module", default="MT48LC16M16", help="SDRAM module: MT48LC16M16, AS4C32M16 or AS4C16M16 (default=MT48LC16M16)") builder_args(parser) soc_sdram_args(parser) trellis_args(parser) @@ -102,7 +110,11 @@ def main(): **soc_sdram_argdict(args)) builder = Builder(soc, **builder_argdict(args)) builder_kargs = trellis_argdict(args) if args.toolchain == "trellis" else {} - builder.build(**builder_kargs) + builder.build(**builder_kargs, run=args.build) + + if args.load: + prog = soc.platform.create_programmer() + prog.load_bitstream(os.path.join(builder.gateware_dir, "top.svf")) if __name__ == "__main__": main() diff --git a/litex/boards/targets/versa_ecp5.py b/litex/boards/targets/versa_ecp5.py index 49d8a6517..e390575f5 100755 --- a/litex/boards/targets/versa_ecp5.py +++ b/litex/boards/targets/versa_ecp5.py @@ -4,6 +4,7 @@ # This file is Copyright (c) 2018-2019 David Shah # License: BSD +import os import argparse from migen import * @@ -40,7 +41,6 @@ class _CRG(Module): # Clk / Rst clk100 = platform.request("clk100") rst_n = platform.request("rst_n") - platform.add_period_constraint(clk100, 1e9/100e6) # Power on reset por_count = Signal(16, reset=2**16-1) @@ -110,21 +110,24 @@ class BaseSoC(SoCCore): def main(): parser = argparse.ArgumentParser(description="LiteX SoC on Versa ECP5") - parser.add_argument("--gateware-toolchain", dest="toolchain", default="trellis", - help="gateware toolchain to use, trellis (default) or diamond") + parser.add_argument("--build", action="store_true", help="Build bitstream") + parser.add_argument("--load", action="store_true", help="Load bitstream") + parser.add_argument("--gateware-toolchain", dest="toolchain", default="trellis", help="Gateware toolchain to use, trellis (default) or diamond") builder_args(parser) soc_sdram_args(parser) trellis_args(parser) - parser.add_argument("--sys-clk-freq", default=75e6, - help="system clock frequency (default=75MHz)") - parser.add_argument("--with-ethernet", action="store_true", - help="enable Ethernet support") + parser.add_argument("--sys-clk-freq", default=75e6, help="System clock frequency (default=75MHz)") + parser.add_argument("--with-ethernet", action="store_true", help="Enable Ethernet support") args = parser.parse_args() soc = BaseSoC(sys_clk_freq=int(float(args.sys_clk_freq)), with_ethernet=args.with_ethernet, toolchain=args.toolchain, **soc_sdram_argdict(args)) builder = Builder(soc, **builder_argdict(args)) builder_kargs = trellis_argdict(args) if args.toolchain == "trellis" else {} - builder.build(**builder_kargs) + builder.build(**builder_kargs, run=args.build) + + if args.load: + prog = soc.platform.create_programmer() + prog.load_bitstream(os.path.join(builder.gateware_dir, "top.svf")) if __name__ == "__main__": main() diff --git a/litex/build/altera/platform.py b/litex/build/altera/platform.py index a95dcf4b9..2f03fc720 100644 --- a/litex/build/altera/platform.py +++ b/litex/build/altera/platform.py @@ -33,6 +33,7 @@ class AlteraPlatform(GenericPlatform): return self.toolchain.build(self, *args, **kwargs) def add_period_constraint(self, clk, period): + if clk is None: return if hasattr(clk, "p"): clk = clk.p self.toolchain.add_period_constraint(self, clk, period) diff --git a/litex/build/generic_platform.py b/litex/build/generic_platform.py index d540cc38a..7c489efea 100644 --- a/litex/build/generic_platform.py +++ b/litex/build/generic_platform.py @@ -205,13 +205,21 @@ class ConstraintManager: self.matched.append((resource, obj)) return obj - def lookup_request(self, name, number=None): + def lookup_request(self, name, number=None, loose=False): + subname = None + if ":" in name: name, subname = name.split(":") for resource, obj in self.matched: if resource[0] == name and (number is None or resource[1] == number): - return obj + if subname is not None: + return getattr(obj, subname) + else: + return obj - raise ConstraintError("Resource not found: {}:{}".format(name, number)) + if loose: + return None + else: + raise ConstraintError("Resource not found: {}:{}".format(name, number)) def add_platform_command(self, command, **signals): self.platform_commands.append((command, signals)) diff --git a/litex/build/generic_programmer.py b/litex/build/generic_programmer.py index 394440300..cb0597d1d 100644 --- a/litex/build/generic_programmer.py +++ b/litex/build/generic_programmer.py @@ -20,7 +20,10 @@ class GenericProgrammer: self.flash_proxy_repos = [ "https://github.com/quartiq/bscan_spi_bitstreams/raw/master/", ] - self.flash_proxy_local = "flash_proxies" + self.config_repos = [ + "https://raw.githubusercontent.com/litex-hub/litex-boards/master/litex_boards/prog/", + ] + self.prog_local = "prog" def set_flash_proxy_dir(self, flash_proxy_dir): if flash_proxy_dir is not None: @@ -34,23 +37,48 @@ class GenericProgrammer: if os.path.exists(fullname): return fullname # Search in local flash_proxy directory - fullname = tools.cygpath(os.path.join(self.flash_proxy_local, self.flash_proxy_basename)) + fullname = tools.cygpath(os.path.join(self.prog_local, self.flash_proxy_basename)) if os.path.exists(fullname): return fullname # Search in repositories and download it import requests - os.makedirs(self.flash_proxy_local, exist_ok=True) + os.makedirs(self.prog_local, exist_ok=True) for d in self.flash_proxy_repos: - fullname = tools.cygpath(os.path.join(self.flash_proxy_local, self.flash_proxy_basename)) + fullname = tools.cygpath(os.path.join(self.prog_local, self.flash_proxy_basename)) try: r = requests.get(d + self.flash_proxy_basename) - with open(fullname, "wb") as f: - f.write(r.content) - return fullname + if r.status_code != 404: + with open(fullname, "wb") as f: + f.write(r.content) + return fullname except: pass raise OSError("Failed to find flash proxy bitstream") + def find_config(self): + # Search in local directory + fullname = tools.cygpath(self.config) + if os.path.exists(fullname): + return self.config + # Search in local config directory + fullname = tools.cygpath(os.path.join(self.prog_local, self.config)) + if os.path.exists(fullname): + return fullname + # Search in repositories and download it + import requests + os.makedirs(self.prog_local, exist_ok=True) + for d in self.config_repos: + fullname = tools.cygpath(os.path.join(self.prog_local, self.config)) + try: + r = requests.get(d + self.config) + if r.status_code != 404: + with open(fullname, "wb") as f: + f.write(r.content) + return fullname + except: + pass + raise OSError("Failed to find config file") + # Must be overloaded by specific programmer def load_bitstream(self, bitstream_file): raise NotImplementedError diff --git a/litex/build/lattice/icestorm.py b/litex/build/lattice/icestorm.py index 2822a9b53..059363c04 100644 --- a/litex/build/lattice/icestorm.py +++ b/litex/build/lattice/icestorm.py @@ -93,32 +93,35 @@ def parse_device(device): _build_template = [ "yosys -l {build_name}.rpt {build_name}.ys", "nextpnr-ice40 --json {build_name}.json --pcf {build_name}.pcf --asc {build_name}.txt \ - --pre-pack {build_name}_pre_pack.py --{architecture} --package {package} {timefailarg}", + --pre-pack {build_name}_pre_pack.py --{architecture} --package {package} {timefailarg} {ignoreloops} --seed {seed}", "icepack -s {build_name}.txt {build_name}.bin" ] -def _build_script(build_template, build_name, architecture, package, timingstrict): +def _build_script(build_template, build_name, architecture, package, timingstrict, ignoreloops, seed): if sys.platform in ("win32", "cygwin"): script_ext = ".bat" - build_script_contents = "@echo off\nrem Autogenerated by LiteX / git: " + tools.get_litex_git_revision() + "\n\n" + script_contents = "@echo off\nrem Autogenerated by LiteX / git: " + tools.get_litex_git_revision() + "\n\n" fail_stmt = " || exit /b" else: script_ext = ".sh" - build_script_contents = "# Autogenerated by LiteX / git: " + tools.get_litex_git_revision() + "\nset -e\n" + script_contents = "# Autogenerated by LiteX / git: " + tools.get_litex_git_revision() + "\nset -e\n" fail_stmt = "" for s in build_template: s_fail = s + "{fail_stmt}\n" # Required so Windows scripts fail early. - build_script_contents += s_fail.format( + script_contents += s_fail.format( build_name = build_name, architecture = architecture, package = package, timefailarg = "--timing-allow-fail" if not timingstrict else "", - fail_stmt = fail_stmt) + ignoreloops = "--ignore-loops" if ignoreloops else "", + fail_stmt = fail_stmt, + seed = seed) - build_script_file = "build_" + build_name + script_ext - tools.write_to_file(build_script_file, build_script_contents,force_unix=False) - return build_script_file + script_file = "build_" + build_name + script_ext + tools.write_to_file(script_file, script_contents, force_unix=False) + + return script_file def _run_script(script): if sys.platform in ("win32", "cygwin"): @@ -158,6 +161,8 @@ class LatticeIceStormToolchain: synth_opts = "", run = True, timingstrict = False, + ignoreloops = False, + seed = 1, **kwargs): # Create build directory @@ -190,7 +195,7 @@ class LatticeIceStormToolchain: (family, architecture, package) = parse_device(platform.device) # Generate build script - script = _build_script(self.build_template, build_name, architecture, package, timingstrict) + script = _build_script(self.build_template, build_name, architecture, package, timingstrict, ignoreloops, seed) # Run if run: @@ -207,3 +212,18 @@ class LatticeIceStormToolchain: raise ValueError("Clock already constrained to {:.2f}ns, new constraint to {:.2f}ns" .format(self.clocks[clk], period)) self.clocks[clk] = period + +def icestorm_args(parser): + parser.add_argument("--nextpnr-timingstrict", action="store_true", + help="fail if timing not met, i.e., do NOT pass '--timing-allow-fail' to nextpnr") + parser.add_argument("--nextpnr-ignoreloops", action="store_true", + help="ignore combinational loops in timing analysis, i.e. pass '--ignore-loops' to nextpnr") + parser.add_argument("--nextpnr-seed", default=1, type=int, + help="seed to pass to nextpnr") + +def icestorm_argdict(args): + return { + "timingstrict": args.nextpnr_timingstrict, + "ignoreloops": args.nextpnr_ignoreloops, + "seed": args.nextpnr_seed, + } \ No newline at end of file diff --git a/litex/build/lattice/platform.py b/litex/build/lattice/platform.py index 71ff2a653..7380b45e0 100644 --- a/litex/build/lattice/platform.py +++ b/litex/build/lattice/platform.py @@ -34,6 +34,7 @@ class LatticePlatform(GenericPlatform): return self.toolchain.build(self, *args, **kwargs) def add_period_constraint(self, clk, period): + if clk is None: return if hasattr(clk, "p"): clk = clk.p self.toolchain.add_period_constraint(self, clk, period) diff --git a/litex/build/lattice/programmer.py b/litex/build/lattice/programmer.py index c97bb07b0..96204e189 100644 --- a/litex/build/lattice/programmer.py +++ b/litex/build/lattice/programmer.py @@ -25,39 +25,31 @@ class LatticeProgrammer(GenericProgrammer): # OpenOCDJTAGProgrammer -------------------------------------------------------------------------------- class OpenOCDJTAGProgrammer(GenericProgrammer): - def __init__(self, openocd_config, flash_proxy_basename=None): - GenericProgrammer.__init__(self, flash_proxy_basename=flash_proxy_basename) - self.openocd_config = openocd_config + def __init__(self, config, flash_proxy_basename=None): + GenericProgrammer.__init__(self, flash_proxy_basename) + self.config = config def load_bitstream(self, bitstream_file): + config = self.find_config() svf_file = bitstream_file.replace(".bit", ".svf") + subprocess.call(["openocd", "-f", config, "-c", "transport select jtag; init; svf quiet progress \"{}\"; exit".format(svf_file)]) - subprocess.call(["openocd", "-f", self.openocd_config , "-c", "transport select jtag; init; svf \"{}\"; exit".format(svf_file)]) - - def flash(self, address, data, erase=False, verify=True): - if self.flash_proxy_basename is None: - flash_proxy = None - else: - flash_proxy = self.find_flash_proxy() - - if erase: - erase = "erase" - else: - erase = "" - + def flash(self, address, data, verify=True): + config = self.find_config() + flash_proxy = self.find_flash_proxy() script = "; ".join([ "transport select jtag", "target create ecp5.spi0.proxy testee -chain-position ecp5.tap", "flash bank spi0 jtagspi 0 0 0 0 ecp5.spi0.proxy 0x32", "init", - "svf \"{}\"" if flash_proxy is not None else "".format(flash_proxy), + "svf quiet progress \"{}\"".format(flash_proxy), "reset halt", "flash probe spi0", - "flash write_image {0} \"{1}\" 0x{2:x}".format(erase, data, address), + "flash write_image erase \"{0}\" 0x{1:x}".format(data, address), "flash verify_bank spi0 \"{0}\" 0x{1:x}" if verify else "".format(data, address), "exit" ]) - subprocess.call(["openocd", "-f", self.openocd_config, "-c", script]) + subprocess.call(["openocd", "-f", config, "-c", script]) # IceStormProgrammer ------------------------------------------------------------------------------- @@ -138,3 +130,11 @@ class MyStormProgrammer(GenericProgrammer): with serial.Serial(self.serial_port) as port: with open(bitstream_file, "rb") as f: port.write(f.read()) + +# UJProg ------------------------------------------------------------------------------------------- + +class UJProg(GenericProgrammer): + needs_bitreverse = False + + def load_bitstream(self, bitstream_file): + subprocess.call(["ujprog", bitstream_file]) diff --git a/litex/build/lattice/trellis.py b/litex/build/lattice/trellis.py index fa19b9192..38e4cdaeb 100644 --- a/litex/build/lattice/trellis.py +++ b/litex/build/lattice/trellis.py @@ -117,11 +117,11 @@ nextpnr_ecp5_architectures = { _build_template = [ "yosys -l {build_name}.rpt {build_name}.ys", "nextpnr-ecp5 --json {build_name}.json --lpf {build_name}.lpf --textcfg {build_name}.config \ - --{architecture} --package {package} --speed {speed_grade} {timefailarg} {ignoreloops}", + --{architecture} --package {package} --speed {speed_grade} {timefailarg} {ignoreloops} --seed {seed}", "ecppack {build_name}.config --svf {build_name}.svf --bit {build_name}.bit" ] -def _build_script(source, build_template, build_name, architecture, package, speed_grade, timingstrict, ignoreloops): +def _build_script(source, build_template, build_name, architecture, package, speed_grade, timingstrict, ignoreloops, seed): if sys.platform in ("win32", "cygwin"): script_ext = ".bat" script_contents = "@echo off\nrem Autogenerated by LiteX / git: " + tools.get_litex_git_revision() + "\n\n" @@ -134,13 +134,14 @@ def _build_script(source, build_template, build_name, architecture, package, spe for s in build_template: s_fail = s + "{fail_stmt}\n" # Required so Windows scripts fail early. script_contents += s_fail.format( - build_name = build_name, - architecture = architecture, - package = package, - speed_grade = speed_grade, - timefailarg = "--timing-allow-fail" if not timingstrict else "", - ignoreloops = "--ignore-loops" if ignoreloops else "", - fail_stmt = fail_stmt) + build_name = build_name, + architecture = architecture, + package = package, + speed_grade = speed_grade, + timefailarg = "--timing-allow-fail" if not timingstrict else "", + ignoreloops = "--ignore-loops" if ignoreloops else "", + fail_stmt = fail_stmt, + seed = seed) script_file = "build_" + build_name + script_ext tools.write_to_file(script_file, script_contents, force_unix=False) @@ -186,6 +187,7 @@ class LatticeTrellisToolchain: nowidelut = False, timingstrict = False, ignoreloops = False, + seed = 1, **kwargs): # Create build directory @@ -217,7 +219,7 @@ class LatticeTrellisToolchain: # Generate build script script = _build_script(False, self.build_template, build_name, architecture, package, - speed_grade, timingstrict, ignoreloops) + speed_grade, timingstrict, ignoreloops, seed) # Run if run: @@ -244,10 +246,13 @@ def trellis_args(parser): help="fail if timing not met, i.e., do NOT pass '--timing-allow-fail' to nextpnr") parser.add_argument("--nextpnr-ignoreloops", action="store_true", help="ignore combinational loops in timing analysis, i.e. pass '--ignore-loops' to nextpnr") + parser.add_argument("--nextpnr-seed", default=1, type=int, + help="seed to pass to nextpnr") def trellis_argdict(args): return { "nowidelut": args.yosys_nowidelut, "timingstrict": args.nextpnr_timingstrict, "ignoreloops": args.nextpnr_ignoreloops, + "seed": args.nextpnr_seed, } diff --git a/litex/build/microsemi/platform.py b/litex/build/microsemi/platform.py index 65d2c996d..c8f13bd89 100644 --- a/litex/build/microsemi/platform.py +++ b/litex/build/microsemi/platform.py @@ -28,6 +28,7 @@ class MicrosemiPlatform(GenericPlatform): return self.toolchain.build(self, *args, **kwargs) def add_period_constraint(self, clk, period): + if clk is None: return clk.attr.add("keep") if hasattr(clk, "p"): clk = clk.p diff --git a/litex/build/openocd.py b/litex/build/openocd.py index c149ca2cc..d3680d609 100644 --- a/litex/build/openocd.py +++ b/litex/build/openocd.py @@ -17,14 +17,16 @@ class OpenOCD(GenericProgrammer): self.config = config def load_bitstream(self, bitstream): + config = self.find_config() script = "; ".join([ "init", "pld load 0 {{{}}}".format(bitstream), "exit", ]) - subprocess.call(["openocd", "-f", self.config, "-c", script]) + subprocess.call(["openocd", "-f", config, "-c", script]) def flash(self, address, data, set_qe=False): + config = self.find_config() flash_proxy = self.find_flash_proxy() script = "; ".join([ "init", @@ -34,7 +36,7 @@ class OpenOCD(GenericProgrammer): "fpga_program", "exit" ]) - subprocess.call(["openocd", "-f", self.config, "-c", script]) + subprocess.call(["openocd", "-f", config, "-c", script]) def stream(self, port=20000): diff --git a/litex/build/xilinx/platform.py b/litex/build/xilinx/platform.py index cf7bbeb50..c2b769ffa 100644 --- a/litex/build/xilinx/platform.py +++ b/litex/build/xilinx/platform.py @@ -15,7 +15,7 @@ class XilinxPlatform(GenericPlatform): def __init__(self, *args, toolchain="ise", **kwargs): GenericPlatform.__init__(self, *args, **kwargs) self.edifs = set() - self.ips = set() + self.ips = {} if toolchain == "ise": self.toolchain = ise.XilinxISEToolchain() elif toolchain == "vivado": @@ -26,8 +26,8 @@ class XilinxPlatform(GenericPlatform): def add_edif(self, filename): self.edifs.add((os.path.abspath(filename))) - def add_ip(self, filename): - self.ips.add((os.path.abspath(filename))) + def add_ip(self, filename, disable_constraints=False): + self.ips.update({os.path.abspath(filename): disable_constraints}) def get_verilog(self, *args, special_overrides=dict(), **kwargs): so = dict(common.xilinx_special_overrides) @@ -48,6 +48,7 @@ class XilinxPlatform(GenericPlatform): return self.toolchain.build(self, *args, **kwargs) def add_period_constraint(self, clk, period): + if clk is None: return if hasattr(clk, "p"): clk = clk.p self.toolchain.add_period_constraint(self, clk, period) diff --git a/litex/build/xilinx/vivado.py b/litex/build/xilinx/vivado.py index 2a8b91d29..ac43dfc74 100644 --- a/litex/build/xilinx/vivado.py +++ b/litex/build/xilinx/vivado.py @@ -155,7 +155,7 @@ class XilinxVivadoToolchain: # Add IPs tcl.append("\n# Add IPs\n") - for filename in platform.ips: + for filename, disable_constraints in platform.ips.items(): filename_tcl = "{" + filename + "}" ip = os.path.splitext(os.path.basename(filename))[0] tcl.append("read_ip " + filename_tcl) @@ -163,10 +163,13 @@ class XilinxVivadoToolchain: tcl.append("generate_target all [get_ips {}]".format(ip)) tcl.append("synth_ip [get_ips {}] -force".format(ip)) tcl.append("get_files -all -of_objects [get_files {}]".format(filename_tcl)) + if disable_constraints: + tcl.append("set_property is_enabled false [get_files -of_objects [get_files {}] -filter {{FILE_TYPE == XDC}}]".format(filename_tcl)) # Add constraints tcl.append("\n# Add constraints\n") tcl.append("read_xdc {}.xdc".format(build_name)) + tcl.append("set_property PROCESSING_ORDER EARLY [get_files {}.xdc]".format(build_name)) # Add pre-synthesis commands tcl.append("\n# Add pre-synthesis commands\n") @@ -276,7 +279,7 @@ class XilinxVivadoToolchain: "-to [get_pins -filter {{REF_PIN_NAME == PRE}} " "-of_objects [get_cells -hierarchical -filter {{ars_ff1 == TRUE || ars_ff2 == TRUE}}]]" ) - # clock_period-2ns to resolve metastability on the wire between the AsyncResetSynchronizer FFs + # clock_period-2ns to resolve metastability on the wire between the AsyncResetSynchronizer FFs platform.add_platform_command( "set_max_delay 2 -quiet " "-from [get_pins -filter {{REF_PIN_NAME == C}} " diff --git a/litex/gen/fhdl/verilog.py b/litex/gen/fhdl/verilog.py index f515dbfb2..98a732707 100644 --- a/litex/gen/fhdl/verilog.py +++ b/litex/gen/fhdl/verilog.py @@ -236,17 +236,17 @@ def _printheader(f, ios, name, ns, attr_translate, sig.type = "wire" if sig in inouts: sig.direction = "inout" - r += "\tinout " + _printsig(ns, sig) + r += "\tinout wire " + _printsig(ns, sig) elif sig in targets: sig.direction = "output" if sig in wires: - r += "\toutput " + _printsig(ns, sig) + r += "\toutput wire " + _printsig(ns, sig) else: sig.type = "reg" r += "\toutput reg " + _printsig(ns, sig) else: sig.direction = "input" - r += "\tinput " + _printsig(ns, sig) + r += "\tinput wire " + _printsig(ns, sig) r += "\n);\n\n" for sig in sorted(sigs - ios, key=lambda x: x.duid): attr = _printattr(sig.attr, attr_translate) diff --git a/litex/soc/cores/clock.py b/litex/soc/cores/clock.py index 97f83c7ba..321768e6c 100644 --- a/litex/soc/cores/clock.py +++ b/litex/soc/cores/clock.py @@ -676,6 +676,7 @@ class ECP5PLL(Module): clkfb = Signal() self.params.update( attr=[ + ("FREQUENCY_PIN_CLKI", str(self.clkin_freq/1e6)), ("ICP_CURRENT", "6"), ("LPF_RESISTOR", "16"), ("MFG_ENABLE_FILTEROPAMP", "1"), diff --git a/litex/soc/cores/cpu/__init__.py b/litex/soc/cores/cpu/__init__.py index 21f7ce5d5..4c273e50b 100644 --- a/litex/soc/cores/cpu/__init__.py +++ b/litex/soc/cores/cpu/__init__.py @@ -29,46 +29,73 @@ class CPUNone(CPU): periph_buses = [] memory_buses = [] +CPU_GCC_TRIPLE_RISCV32 = ( + "riscv64-unknown-elf", + "riscv32-unknown-elf", + "riscv-none-embed", + "riscv64-linux", + "riscv-sifive-elf", + "riscv64-none-elf", +) + +CPU_GCC_TRIPLE_RISCV64 = ( + "riscv64-unknown-elf", + "riscv64-linux", + "riscv-sifive-elf", + "riscv64-none-elf", +) + # CPUS --------------------------------------------------------------------------------------------- from litex.soc.cores.cpu.lm32 import LM32 from litex.soc.cores.cpu.mor1kx import MOR1KX -from litex.soc.cores.cpu.picorv32 import PicoRV32 -from litex.soc.cores.cpu.vexriscv import VexRiscv -from litex.soc.cores.cpu.minerva import Minerva -from litex.soc.cores.cpu.rocket import RocketRV64 from litex.soc.cores.cpu.microwatt import Microwatt -from litex.soc.cores.cpu.blackparrot import BlackParrotRV64 from litex.soc.cores.cpu.serv import SERV +from litex.soc.cores.cpu.picorv32 import PicoRV32 +from litex.soc.cores.cpu.minerva import Minerva +from litex.soc.cores.cpu.vexriscv import VexRiscv +from litex.soc.cores.cpu.rocket import RocketRV64 +from litex.soc.cores.cpu.blackparrot import BlackParrotRV64 CPUS = { + # None "None" : CPUNone, + + # LM32 "lm32" : LM32, + + # OpenRisc "mor1kx" : MOR1KX, - "picorv32" : PicoRV32, - "vexriscv" : VexRiscv, - "minerva" : Minerva, - "rocket" : RocketRV64, + + # Open Power "microwatt" : Microwatt, + + # RISC-V 32-bit + "serv" : SERV, + "picorv32" : PicoRV32, + "minerva" : Minerva, + "vexriscv" : VexRiscv, + + # RISC-V 64-bit + "rocket" : RocketRV64, "blackparrot" : BlackParrotRV64, - "serv" : SERV } # CPU Variants/Extensions Definition --------------------------------------------------------------- CPU_VARIANTS = { # "official name": ["alias 1", "alias 2"], - "minimal" : ["min",], - "lite" : ["light", "zephyr", "nuttx"], - "standard": [None, "std"], - "full": [], - "linux" : [], - "linuxd" : [], - "linuxq" : [], + "minimal" : ["min",], + "lite" : ["light", "zephyr", "nuttx"], + "standard": [None, "std"], + "imac": [], + "full": [], + "linux" : [], + "linuxd" : [], + "linuxq" : [], } CPU_VARIANTS_EXTENSIONS = ["debug", "no-dsp"] - class InvalidCPUVariantError(ValueError): def __init__(self, variant): msg = """\ diff --git a/litex/soc/cores/cpu/blackparrot/GETTING_STARTED.md b/litex/soc/cores/cpu/blackparrot/GETTING_STARTED.md new file mode 100644 index 000000000..55ec62e2d --- /dev/null +++ b/litex/soc/cores/cpu/blackparrot/GETTING_STARTED.md @@ -0,0 +1,24 @@ +# Getting started (TODO:update) + +## Running BP in LiteX + +cd $LITEX/litex/tools # the folder where litex simulator resides + +./litex_sim.py --cpu-type blackparrot --cpu-variant standard --integrated-rom-size 40960 --output-dir build/BP --threads 4 --opt-level=O0 --trace --trace-start 0 + +#The above command will generate a dut.vcd file under build/BP/gateware folder. gtkwave works fine with the generated dut.vcd. + +## Additional Information + +The BlackParrot resides in $BP/pre-alpha-release/ + +core.py in $BP folder is the wrapper that integrates BP into LiteX. + +flist.verilator in $BP is all the files that litex_sim fetches for simulation. + +The top module is $BP_FPGA_DIR/ExampleBlackParrotSystem.v + +The transducer for wishbone communication is $BP_FPGA_DIR/bp2wb_convertor.v + +if args.sdram_init is not None: #instead of ram_init for sdram init boot + soc.add_constant("ROM_BOOT_ADDRESS", 0x80000000) diff --git a/litex/soc/cores/cpu/blackparrot/README.md b/litex/soc/cores/cpu/blackparrot/README.md index d320d4b45..4fe921f79 100644 --- a/litex/soc/cores/cpu/blackparrot/README.md +++ b/litex/soc/cores/cpu/blackparrot/README.md @@ -1,12 +1,60 @@ -TODO: Edit -git submodule update --init --recursive (for blackparrot pre-alpha repo) -cd pre_alpha_release -follow getting_started to install blackparrot -cd .. +# BlackParrot in LiteX + + +## Getting Started + +TODO: modify getting started [Getting Started (Full)](GETTING_STARTED.md) + +### Prerequisites + +``` +BP sources (https://github.com/litex-hub/pythondata-cpu-blackparrot) +RISC-V toolchain built for IA architecture (prebuilt binaries provided by LiteX works fine) +Verilator (tested with Verilator 4.031) +``` + +### Installing + +``` +https://github.com/litex-hub/pythondata-cpu-blackparrot is required to run BP in LiteX. source ./setEnvironment.sh #should be sourced each time you open a terminal or just add this line to bashrc -Add $BP_TOP/external/bin to $PATH for verilator and riscv-gnu tools -./update_BP.sh #to modify some of the files in Blackparrot repo (one-time process) -Currently, we could simulate the LITEX-BIOS on BP processor. +``` + +## Running BIOS + +### Simulation +``` +cd $LITEX/litex/tools +./litex_sim.py --cpu-type blackparrot --cpu-variant standard --output-dir build/BP_Trial +``` +[![asciicast](https://asciinema.org/a/326077.svg)](https://asciinema.org/a/326077) + +### FPGA +``` +Coming soon! +``` + +## Running Linux + + +### Simulation +``` +Modify litex_sim.py by replacing soc.add_constant("ROM_BOOT_ADDRESS", 0x40000000) with soc.add_constant("ROM_BOOT_ADDRESS", 0x80000000) + +./litex_sim.py --cpu-type blackparrot --cpu-variant standard --integrated-rom-size 40960 --output-dir build/BP_newversion_linux_ram/ --threads 4 --ram-init build/tests/boot.bin.uart.simu.trial + +TODO: add prebuilt bbl files into python-data repository + +``` + +### FPGA + +``` +Coming soon! +``` + + + + -[![asciicast](https://asciinema.org/a/286568.svg)](https://asciinema.org/a/286568) diff --git a/litex/soc/software/bios/boot-helper-blackparrot.S b/litex/soc/cores/cpu/blackparrot/boot-helper.S similarity index 100% rename from litex/soc/software/bios/boot-helper-blackparrot.S rename to litex/soc/cores/cpu/blackparrot/boot-helper.S diff --git a/litex/soc/cores/cpu/blackparrot/bp_fpga/ExampleBlackParrotSystem.v b/litex/soc/cores/cpu/blackparrot/bp_fpga/ExampleBlackParrotSystem.v deleted file mode 100644 index cdd1a95e0..000000000 --- a/litex/soc/cores/cpu/blackparrot/bp_fpga/ExampleBlackParrotSystem.v +++ /dev/null @@ -1,434 +0,0 @@ -/** - * - * ExampleBlackParrotSystem For Simulating With Litex - * - */ - -`include "bsg_noc_links.vh" - -module ExampleBlackParrotSystem - import bp_common_pkg::*; - import bp_common_aviary_pkg::*; - import bp_be_pkg::*; - import bp_common_rv64_pkg::*; - import bp_cce_pkg::*; - import bp_cfg_link_pkg::*; - #(parameter bp_cfg_e cfg_p = e_bp_single_core_cfg // Replaced by the flow with a specific bp_cfg - `declare_bp_proc_params(cfg_p) - `declare_bp_me_if_widths(paddr_width_p, cce_block_width_p, num_lce_p, lce_assoc_p) - - // Tracing parameters - , parameter calc_trace_p = 1 - , parameter cce_trace_p = 0 - , parameter cmt_trace_p = 0 - , parameter dram_trace_p = 0 - , parameter skip_init_p = 0 - - , parameter mem_load_p = 1 - , parameter mem_file_p = "prog.mem" - , parameter mem_cap_in_bytes_p = 2**20 - , parameter [paddr_width_p-1:0] mem_offset_p = paddr_width_p'(32'h8000_0000) - - ) - (input clk_i - , input reset_i - //Wishbone interface - , input [63:0] wbm_dat_i - , output [63:0] wbm_dat_o - , input wbm_ack_i - // , input wbm_err_i - // , input wbm_rty_i - , output [36:0] wbm_adr_o //TODO parametrize this - , output wbm_stb_o - , output wbm_cyc_o - , output wbm_sel_o //TODO: how many bits ? check 3.5 table 3-1 - , output wbm_we_o - , output [2:0] wbm_cti_o //TODO: hardwire in Litex - , output [1:0] wbm_bte_o //TODO: hardwire in Litex - , output all_finished_debug_o //SC_add - , output core_passed_debug - , output core_failed_debug - , input [3:0] interrupts - ); - -`declare_bsg_ready_and_link_sif_s(mem_noc_flit_width_p, bsg_ready_and_link_sif_s); -`declare_bp_me_if(paddr_width_p, cce_block_width_p, num_lce_p, lce_assoc_p) - -bsg_ready_and_link_sif_s cmd_link_li, cmd_link_lo; -bsg_ready_and_link_sif_s resp_link_li, resp_link_lo; - -bsg_ready_and_link_sif_s mem_cmd_link_li, mem_cmd_link_lo, mem_resp_link_li, mem_resp_link_lo; -bsg_ready_and_link_sif_s cfg_cmd_link_li, cfg_cmd_link_lo, cfg_resp_link_li, cfg_resp_link_lo; - -assign mem_cmd_link_li = cmd_link_li; -assign cfg_cmd_link_li = '{ready_and_rev: cmd_link_li.ready_and_rev, default: '0}; -assign cmd_link_lo = '{data: cfg_cmd_link_lo.data - ,v : cfg_cmd_link_lo.v - ,ready_and_rev: mem_cmd_link_lo.ready_and_rev - }; - -assign mem_resp_link_li = '{ready_and_rev: resp_link_li.ready_and_rev, default: '0}; -assign cfg_resp_link_li = resp_link_li; -assign resp_link_lo = '{data: mem_resp_link_lo.data - ,v : mem_resp_link_lo.v - ,ready_and_rev: cfg_resp_link_lo.ready_and_rev - }; - -bp_cce_mem_msg_s mem_resp_li; -logic mem_resp_v_li, mem_resp_ready_lo; -bp_cce_mem_msg_s mem_cmd_lo; -logic mem_cmd_v_lo, mem_cmd_yumi_li; - -bp_cce_mem_msg_s dram_resp_lo; -logic dram_resp_v_lo, dram_resp_ready_li; -bp_cce_mem_msg_s dram_cmd_li; -logic dram_cmd_v_li, dram_cmd_yumi_lo; - -bp_cce_mem_msg_s host_resp_lo; -logic host_resp_v_lo, host_resp_ready_li; -bp_cce_mem_msg_s host_cmd_li; -logic host_cmd_v_li, host_cmd_yumi_lo; - -bp_cce_mem_msg_s cfg_cmd_lo; -logic cfg_cmd_v_lo, cfg_cmd_ready_li; -bp_cce_mem_msg_s cfg_resp_li; -logic cfg_resp_v_li, cfg_resp_ready_lo; - -logic [mem_noc_cord_width_p-1:0] dram_cord_lo, mmio_cord_lo, host_cord_lo; -logic [num_core_p-1:0][mem_noc_cord_width_p-1:0] tile_cord_lo; -logic [num_mem_p-1:0][mem_noc_cord_width_p-1:0] mem_cord_lo; - -assign mmio_cord_lo[0+:mem_noc_x_cord_width_p] = mmio_x_pos_p; -assign mmio_cord_lo[mem_noc_x_cord_width_p+:mem_noc_y_cord_width_p] = '0; -assign dram_cord_lo[0+:mem_noc_x_cord_width_p] = mem_noc_x_dim_p+2; -assign dram_cord_lo[mem_noc_x_cord_width_p+:mem_noc_y_cord_width_p] = '0; -assign host_cord_lo[0+:mem_noc_x_cord_width_p] = mem_noc_x_dim_p+2; -assign host_cord_lo[mem_noc_x_cord_width_p+:mem_noc_y_cord_width_p] = '0; - -for (genvar j = 0; j < mem_noc_y_dim_p; j++) - begin : y - for (genvar i = 0; i < mem_noc_x_dim_p; i++) - begin : x - localparam idx = j*mem_noc_x_dim_p + i; - assign tile_cord_lo[idx][0+:mem_noc_x_cord_width_p] = i+1; - assign tile_cord_lo[idx][mem_noc_x_cord_width_p+:mem_noc_y_cord_width_p] = j+1; - end - end -for (genvar i = 0; i < num_mem_p; i++) - begin : x - assign mem_cord_lo[i][0+:mem_noc_x_cord_width_p] = i; - assign mem_cord_lo[i][mem_noc_x_cord_width_p+:mem_noc_y_cord_width_p] = '0; - end - -// Chip -bp_chip - #(.cfg_p(cfg_p)) - chip - (.core_clk_i(clk_i) - ,.core_reset_i(reset_i) - - ,.coh_clk_i(clk_i) - ,.coh_reset_i(reset_i) - - ,.mem_clk_i(clk_i) - ,.mem_reset_i(reset_i) - - ,.mem_cord_i(mem_cord_lo) - ,.tile_cord_i(tile_cord_lo) - ,.dram_cord_i(dram_cord_lo) - ,.mmio_cord_i(mmio_cord_lo) - ,.host_cord_i(host_cord_lo) - - ,.prev_cmd_link_i('0) - ,.prev_cmd_link_o() - - ,.prev_resp_link_i('0) - ,.prev_resp_link_o() - - ,.next_cmd_link_i(cmd_link_lo) - ,.next_cmd_link_o(cmd_link_li) - - ,.next_resp_link_i(resp_link_lo) - ,.next_resp_link_o(resp_link_li) - ); - - bind bp_be_top - bp_nonsynth_commit_tracer - #(.cfg_p(cfg_p)) - commit_tracer - (.clk_i(clk_i & (ExampleBlackParrotSystem.cmt_trace_p == 1)) - ,.reset_i(reset_i) - - ,.mhartid_i('0) - - ,.commit_v_i(be_calculator.instret_mem3_o) - ,.commit_pc_i(be_calculator.pc_mem3_o) - ,.commit_instr_i(be_calculator.instr_mem3_o) - - ,.rd_w_v_i(be_calculator.int_regfile.rd_w_v_i) - ,.rd_addr_i(be_calculator.int_regfile.rd_addr_i) - ,.rd_data_i(be_calculator.int_regfile.rd_data_i) - ); - - - bind bp_be_top - bp_be_nonsynth_tracer - #(.cfg_p(cfg_p)) - tracer - // Workaround for verilator binding by accident - // TODO: Figure out why tracing is always enabled - (.clk_i(clk_i & (ExampleBlackParrotSystem.calc_trace_p == 1)) - ,.reset_i(reset_i) - - ,.mhartid_i(be_calculator.proc_cfg.core_id) - - ,.issue_pkt_i(be_calculator.issue_pkt) - ,.issue_pkt_v_i(be_calculator.issue_pkt_v_i) - - ,.fe_nop_v_i(be_calculator.fe_nop_v) - ,.be_nop_v_i(be_calculator.be_nop_v) - ,.me_nop_v_i(be_calculator.me_nop_v) - ,.dispatch_pkt_i(be_calculator.dispatch_pkt) - - ,.ex1_br_tgt_i(be_calculator.calc_status.int1_br_tgt) - ,.ex1_btaken_i(be_calculator.calc_status.int1_btaken) - ,.iwb_result_i(be_calculator.comp_stage_n[3]) - ,.fwb_result_i(be_calculator.comp_stage_n[4]) - - ,.cmt_trace_exc_i(be_calculator.exc_stage_n[1+:5]) - - ,.trap_v_i(be_mem.csr.trap_v_o) - ,.mtvec_i(be_mem.csr.mtvec_n) - ,.mtval_i(be_mem.csr.mtval_n[0+:vaddr_width_p]) - ,.ret_v_i(be_mem.csr.ret_v_o) - ,.mepc_i(be_mem.csr.mepc_n[0+:vaddr_width_p]) - ,.mcause_i(be_mem.csr.mcause_n) - - ,.priv_mode_i(be_mem.csr.priv_mode_n) - ,.mpp_i(be_mem.csr.mstatus_n.mpp) - ); - -/*bind bp_be_top - bp_be_nonsynth_perf - #(.cfg_p(cfg_p)) - perf - (.clk_i(clk_i) - ,.reset_i(reset_i) - - ,.mhartid_i(be_calculator.proc_cfg.core_id) - - ,.fe_nop_i(be_calculator.exc_stage_r[2].fe_nop_v) - ,.be_nop_i(be_calculator.exc_stage_r[2].be_nop_v) - ,.me_nop_i(be_calculator.exc_stage_r[2].me_nop_v) - ,.poison_i(be_calculator.exc_stage_r[2].poison_v) - ,.roll_i(be_calculator.exc_stage_r[2].roll_v) - ,.instr_cmt_i(be_calculator.calc_status.mem3_cmt_v) - - ,.program_finish_i(testbench.program_finish) - ); -*/ -/*if (dram_trace_p) - bp_mem_nonsynth_tracer - #(.cfg_p(cfg_p)) - bp_mem_tracer - (.clk_i(clk_i & (testbench.dram_trace_p == 1)) - ,.reset_i(reset_i) - - ,.mem_cmd_i(dram_cmd_li) - ,.mem_cmd_v_i(dram_cmd_v_li) - ,.mem_cmd_yumi_i(dram_cmd_yumi_lo) - - ,.mem_resp_i(dram_resp_lo) - ,.mem_resp_v_i(dram_resp_v_lo) - ,.mem_resp_ready_i(dram_resp_ready_li) - ); - -if (cce_trace_p) - bind bp_cce_top - bp_cce_nonsynth_tracer - #(.cfg_p(cfg_p)) - bp_cce_tracer - (.clk_i(clk_i & (testbench.cce_trace_p == 1)) - ,.reset_i(reset_i) - - ,.cce_id_i(cce_id_i) - - // To CCE - ,.lce_req_i(lce_req_to_cce) - ,.lce_req_v_i(lce_req_v_to_cce) - ,.lce_req_yumi_i(lce_req_yumi_from_cce) - ,.lce_resp_i(lce_resp_to_cce) - ,.lce_resp_v_i(lce_resp_v_to_cce) - ,.lce_resp_yumi_i(lce_resp_yumi_from_cce) - - // From CCE - ,.lce_cmd_i(lce_cmd_o) - ,.lce_cmd_v_i(lce_cmd_v_o) - ,.lce_cmd_ready_i(lce_cmd_ready_i) - - // To CCE - ,.mem_resp_i(mem_resp_to_cce) - ,.mem_resp_v_i(mem_resp_v_to_cce) - ,.mem_resp_yumi_i(mem_resp_yumi_from_cce) - - // From CCE - ,.mem_cmd_i(mem_cmd_from_cce) - ,.mem_cmd_v_i(mem_cmd_v_from_cce) - ,.mem_cmd_ready_i(mem_cmd_ready_to_cce) - ); -*/ -// DRAM + link -bp_me_cce_to_wormhole_link_client - #(.cfg_p(cfg_p)) - client_link - (.clk_i(clk_i) - ,.reset_i(reset_i) - - ,.mem_cmd_o(mem_cmd_lo) - ,.mem_cmd_v_o(mem_cmd_v_lo) - ,.mem_cmd_yumi_i(mem_cmd_yumi_li) - - ,.mem_resp_i(mem_resp_li) - ,.mem_resp_v_i(mem_resp_v_li) - ,.mem_resp_ready_o(mem_resp_ready_lo) - - ,.my_cord_i(dram_cord_lo) - ,.my_cid_i(mem_noc_cid_width_p'(0)) - - ,.cmd_link_i(mem_cmd_link_li) - ,.cmd_link_o(mem_cmd_link_lo) - - ,.resp_link_i(mem_resp_link_li) - ,.resp_link_o(mem_resp_link_lo) - ); - -bp2wb_convertor - #(.cfg_p(cfg_p)) -bp2wb - (.clk_i(clk_i) - ,.reset_i(reset_i) - ,.mem_cmd_i(dram_cmd_li) - ,.mem_cmd_v_i(dram_cmd_v_li) - ,.mem_cmd_yumi_o(dram_cmd_yumi_lo) - ,.mem_resp_o(dram_resp_lo) - ,.mem_resp_v_o(dram_resp_v_lo) - ,.mem_resp_ready_i(dram_resp_ready_li) - ,.dat_i(wbm_dat_i) - ,.dat_o(wbm_dat_o) - ,.ack_i(wbm_ack_i) - ,.adr_o(wbm_adr_o) - ,.stb_o(wbm_stb_o) - ,.cyc_o(wbm_cyc_o) - ,.sel_o(wbm_sel_o ) - ,.we_o(wbm_we_o) - ,.cti_o(wbm_cti_o) - ,.bte_o(wbm_bte_o ) - ); - -logic [num_core_p-1:0] program_finish; - -bp_nonsynth_host - #(.cfg_p(cfg_p)) - host_mmio - (.clk_i(clk_i) - ,.reset_i(reset_i) - - ,.mem_cmd_i(host_cmd_li) - ,.mem_cmd_v_i(host_cmd_v_li) - ,.mem_cmd_yumi_o(host_cmd_yumi_lo) - - ,.mem_resp_o(host_resp_lo) - ,.mem_resp_v_o(host_resp_v_lo) - ,.mem_resp_ready_i(host_resp_ready_li) - - ,.program_finish_o(program_finish) - ,.all_finished_debug_o(all_finished_debug_o) - ,.core_passed_debug(core_passed_debug) - ,.core_failed_debug(core_failed_debug) - ); - -/*bp_nonsynth_if_verif - #(.cfg_p(cfg_p)) - if_verif - (); -*/ -// MMIO arbitration -// Should this be on its own I/O router? -logic req_outstanding_r; -bsg_dff_reset_en - #(.width_p(1)) - req_outstanding_reg - (.clk_i(clk_i) - ,.reset_i(reset_i) - ,.en_i(mem_cmd_yumi_li | mem_resp_v_li) - - ,.data_i(mem_cmd_yumi_li) - ,.data_o(req_outstanding_r) - ); - -wire host_cmd_not_dram = mem_cmd_v_lo & (mem_cmd_lo.addr < 39'h00_4000_0000 );//dram_base_addr_gp - -assign host_cmd_li = mem_cmd_lo; -assign host_cmd_v_li = mem_cmd_v_lo & host_cmd_not_dram & ~req_outstanding_r; -assign dram_cmd_li = mem_cmd_lo; -assign dram_cmd_v_li = mem_cmd_v_lo & ~host_cmd_not_dram & ~req_outstanding_r; -assign mem_cmd_yumi_li = host_cmd_not_dram - ? host_cmd_yumi_lo - : dram_cmd_yumi_lo; - -assign mem_resp_li = host_resp_v_lo ? host_resp_lo : dram_resp_lo; -assign mem_resp_v_li = host_resp_v_lo | dram_resp_v_lo; -assign host_resp_ready_li = mem_resp_ready_lo; -assign dram_resp_ready_li = mem_resp_ready_lo; - -// CFG loader + rom + link -bp_me_cce_to_wormhole_link_master - #(.cfg_p(cfg_p)) - master_link - (.clk_i(clk_i) - ,.reset_i(reset_i) - - ,.mem_cmd_i(cfg_cmd_lo) - ,.mem_cmd_v_i(cfg_cmd_ready_li & cfg_cmd_v_lo) - ,.mem_cmd_ready_o(cfg_cmd_ready_li) - - ,.mem_resp_o(cfg_resp_li) - ,.mem_resp_v_o(cfg_resp_v_li) - ,.mem_resp_yumi_i(cfg_resp_ready_lo & cfg_resp_v_li) - - ,.my_cord_i(dram_cord_lo) - ,.my_cid_i(mem_noc_cid_width_p'(0)) - ,.dram_cord_i(dram_cord_lo) - ,.mmio_cord_i(mmio_cord_lo) - ,.host_cord_i(host_cord_lo) - - ,.cmd_link_i(cfg_cmd_link_li) - ,.cmd_link_o(cfg_cmd_link_lo) - - ,.resp_link_i(cfg_resp_link_li) - ,.resp_link_o(cfg_resp_link_lo) - ); - -localparam cce_instr_ram_addr_width_lp = `BSG_SAFE_CLOG2(num_cce_instr_ram_els_p); -bp_cce_mmio_cfg_loader - #(.cfg_p(cfg_p) - ,.inst_width_p(`bp_cce_inst_width) - ,.inst_ram_addr_width_p(cce_instr_ram_addr_width_lp) - ,.inst_ram_els_p(num_cce_instr_ram_els_p) - ,.skip_ram_init_p(skip_init_p) - ) - cfg_loader - (.clk_i(clk_i) - ,.reset_i(reset_i) - - ,.mem_cmd_o(cfg_cmd_lo) - ,.mem_cmd_v_o(cfg_cmd_v_lo) - ,.mem_cmd_yumi_i(cfg_cmd_ready_li & cfg_cmd_v_lo) - - ,.mem_resp_i(cfg_resp_li) - ,.mem_resp_v_i(cfg_resp_v_li) - ,.mem_resp_ready_o(cfg_resp_ready_lo) - ); - -endmodule - diff --git a/litex/soc/cores/cpu/blackparrot/bp_fpga/bp2wb_convertor.v b/litex/soc/cores/cpu/blackparrot/bp_fpga/bp2wb_convertor.v deleted file mode 100644 index 3780fb8ce..000000000 --- a/litex/soc/cores/cpu/blackparrot/bp_fpga/bp2wb_convertor.v +++ /dev/null @@ -1,214 +0,0 @@ -/** - * bp2wb_convertor.v - * DESCRIPTION: THIS MODULE ADAPTS BP MEMORY BUS TO 64-BIT WISHBONE - */ - -module bp2wb_convertor - import bp_common_pkg::*; - import bp_common_aviary_pkg::*; - import bp_cce_pkg::*; - import bp_me_pkg::*; - #(parameter bp_cfg_e cfg_p = e_bp_single_core_cfg - `declare_bp_proc_params(cfg_p) - `declare_bp_me_if_widths(paddr_width_p, cce_block_width_p, num_lce_p, lce_assoc_p) - -// , parameter [paddr_width_p-1:0] dram_offset_p = '0 - , localparam num_block_words_lp = cce_block_width_p / 64 - , localparam num_block_bytes_lp = cce_block_width_p / 8 - , localparam num_word_bytes_lp = dword_width_p / 8 - , localparam block_offset_bits_lp = `BSG_SAFE_CLOG2(num_block_bytes_lp) - , localparam word_offset_bits_lp = `BSG_SAFE_CLOG2(num_block_words_lp) - , localparam byte_offset_bits_lp = `BSG_SAFE_CLOG2(num_word_bytes_lp) - , localparam wbone_data_width = 64 - , localparam wbone_addr_ubound = paddr_width_p - , localparam mem_granularity = 64 //TODO: adapt selection bit parametrized - , localparam wbone_addr_lbound = 3 //`BSG_SAFE_CLOG2(wbone_data_width / mem_granularity) //dword granularity - , localparam total_datafetch_cycle_lp = cce_block_width_p / wbone_data_width - , localparam total_datafetch_cycle_width = `BSG_SAFE_CLOG2(total_datafetch_cycle_lp) - , localparam cached_addr_base = 32'h4000_4000// 32'h5000_0000 - ) - (input clk_i - ,(* mark_debug = "true" *) input reset_i - - // BP side - ,(* mark_debug = "true" *) input [cce_mem_msg_width_lp-1:0] mem_cmd_i - ,(* mark_debug = "true" *) input mem_cmd_v_i - ,(* mark_debug = "true" *) output mem_cmd_yumi_o - - , (* mark_debug = "true" *) output [cce_mem_msg_width_lp-1:0] mem_resp_o - , (* mark_debug = "true" *) output mem_resp_v_o - , (* mark_debug = "true" *) input mem_resp_ready_i - - // Wishbone side - , (* mark_debug = "true" *) input [63:0] dat_i - , (* mark_debug = "true" *) output logic [63:0] dat_o - , (* mark_debug = "true" *) input ack_i - // , input err_i - // , input rty_i - , (* mark_debug = "true" *) output logic [wbone_addr_ubound-wbone_addr_lbound-1:0] adr_o//TODO: Double check!!! - , (* mark_debug = "true" *) output logic stb_o - , output cyc_o - , output sel_o //TODO: double check!!! - , (* mark_debug = "true" *) output we_o - , output [2:0] cti_o //TODO: hardwire in Litex - , output [1:0] bte_o //TODO: hardwire in Litex - - ); - - `declare_bp_me_if(paddr_width_p, cce_block_width_p, num_lce_p, lce_assoc_p); - - //locals - (* mark_debug = "true" *) logic [total_datafetch_cycle_width:0] ack_ctr = 0; - (* mark_debug = "true" *) bp_cce_mem_msg_s mem_cmd_cast_i, mem_resp_cast_o, mem_cmd_r; - (* mark_debug = "true" *) logic ready_li, v_li, stb_justgotack; - (* mark_debug = "true" *) logic [cce_block_width_p-1:0] data_lo; - (* mark_debug = "true" *) logic [cce_block_width_p-1:0] data_li; - (* mark_debug = "true" *) wire [paddr_width_p-1:0] mem_cmd_addr_l; - (* mark_debug = "true" *) logic [paddr_width_p-1:0] addr_lo; - (* mark_debug = "true" *) logic set_stb; - (* mark_debug = "true" *) wire [63:0] data_little_end; - - - //reset - //TODO: reset ack_ctr here - //Handshaking between Wishbone and BlackParrot through convertor - //3.1.3:At every rising edge of [CLK_I] the terminating signal(ACK) is sampled. If it - //is asserted, then [STB_O] is negated. - - assign ready_li = ( ack_ctr == 0 ); - assign mem_cmd_yumi_o = mem_cmd_v_i && ready_li;//!stb_o then ready to take! - // assign v_li = (ack_ctr == total_datafetch_cycle_lp-1); - assign mem_resp_v_o = mem_resp_ready_i & v_li; - assign stb_o = (set_stb) && !stb_justgotack; //addresi mem_cmd_rdan aldigimiz icin 1 cycle geriden geliyo - assign cyc_o = stb_o; - assign sel_o = 0; - assign cti_o = 0; - assign bte_o = 0; - - initial begin - ack_ctr = 0; - //stb_reset_lo =0; - end - -/* always_ff @(posedge clk_i) - if ( mem_cmd_yumi_o )// || (ack_ctr > 0)) - begin - data_li <= 0; - set_stb <= 1; - end -*/ - - -//Flip stb after each ack--->RULE 3.20: - -// Every time we get an ACK from WB, increment counter until the counter reaches to total_datafetch_cycle_lp -assign data_little_end = dat_i; - always_ff @(posedge clk_i) - begin - - if(reset_i) - begin - ack_ctr <= 0; - set_stb <= 0; - v_li <=0; - end - - else if (mem_cmd_yumi_o) - begin - data_li <= 0; - set_stb <= 1; - v_li <= 0; - stb_justgotack <= 0; - end - - else - begin - if (ack_i)//stb should be negated after ack - begin - stb_justgotack <= 1; - data_li[(ack_ctr*wbone_data_width) +: wbone_data_width] <= data_little_end; - if ((ack_ctr == total_datafetch_cycle_lp-1) || (mem_cmd_addr_l < cached_addr_base && mem_cmd_r.msg_type == e_cce_mem_uc_wr )) //if uncached store, just one cycle is fine - begin - ack_ctr <= 0; - v_li <=1; - set_stb <= 0; - end - else - ack_ctr <= ack_ctr + 1; - end - else - begin - stb_justgotack <= 0; - v_li <=0; - end - end - end - - //Packet Pass from BP to BP2WB - assign mem_cmd_cast_i = mem_cmd_i; - - bsg_dff_reset_en - #(.width_p(cce_mem_msg_width_lp)) - mshr_reg - (.clk_i(clk_i) - ,.reset_i(reset_i) - ,.en_i(mem_cmd_yumi_o)//when - ,.data_i(mem_cmd_i) - ,.data_o(mem_cmd_r) - ); - - - //Addr && Data && Command Pass from BP2WB to WB - logic [wbone_addr_lbound-1:0] throw_away; - assign mem_cmd_addr_l = mem_cmd_r.addr; - assign data_lo = mem_cmd_r.data; - logic [39:0] mem_cmd_addr_l_zero64; - logic [7:0] partial; - always_comb begin - if( mem_cmd_addr_l < cached_addr_base ) - begin - adr_o = mem_cmd_addr_l[wbone_addr_ubound-1:wbone_addr_lbound];//no need to change address for uncached stores/loads - dat_o = data_lo[(0*wbone_data_width) +: wbone_data_width];//unchached data is stored in LS 64bits - end - - else - begin - mem_cmd_addr_l_zero64 = mem_cmd_addr_l >> 6 << 6; - // addr_lo = - {adr_o,throw_away} = mem_cmd_addr_l_zero64 + (ack_ctr*8);//TODO:careful - // adr_o = addr_lo[wbone_addr_ubound-1:wbone_addr_lbound]; - dat_o = data_lo[(ack_ctr*wbone_data_width) +: wbone_data_width]; - end - end - - assign we_o = (mem_cmd_r.msg_type inside {e_cce_mem_uc_wr, e_cce_mem_wb}); - -//DEBUG - -wire [3:0] typean; -assign typean = mem_cmd_r.msg_type; -wire [2:0] debug1; -assign debug1 = (mem_cmd_r.addr[5:0]>>3); - -//Data Pass from BP2WB to BP - -wire [cce_block_width_p-1:0] rd_word_offset = mem_cmd_r.addr[3+:3]; -//wire [cce_block_width_p-1:0] rd_byte_offset = mem_cmd_r.addr[0+:3]; -wire [cce_block_width_p-1:0] rd_bit_shift = rd_word_offset*64; // We rely on receiver to adjust bits - -wire [cce_block_width_p-1:0] data_li_resp = (mem_cmd_r.msg_type == e_cce_mem_uc_rd) - ? data_li >> rd_bit_shift - : data_li; - -assign mem_resp_cast_o = '{data : data_li_resp - ,payload : mem_cmd_r.payload - ,size : mem_cmd_r.size - ,addr : mem_cmd_r.addr - ,msg_type: mem_cmd_r.msg_type - }; - -assign mem_resp_o = mem_resp_cast_o; - - -endmodule - diff --git a/litex/soc/cores/cpu/blackparrot/bp_fpga/bsg_mem_1rw_sync_mask_write_bit.v b/litex/soc/cores/cpu/blackparrot/bp_fpga/bsg_mem_1rw_sync_mask_write_bit.v deleted file mode 100644 index a6fdae9a6..000000000 --- a/litex/soc/cores/cpu/blackparrot/bp_fpga/bsg_mem_1rw_sync_mask_write_bit.v +++ /dev/null @@ -1,55 +0,0 @@ -/* -* bsg_mem_1rw_sync_mask_write_bit.v -* -* distributed synchronous 1-port ram for xilinx ultrascale or ultrascale plus FPGA -* Write mode: No-change | Read mode: No-change -* Note: -* There are 2 basic BRAM library primitives, RAMB18E2 and RAMB36E2 in Vivado. -* But none of them support bit-wise mask. They have Byte-wide write enable ports though. -* So we use the RAM_STYLE attribute to instruct the tool to infer distributed LUT RAM instead. -* -* To save resources, the code is written to be inferred as Signle-port distributed ram RAM64X1S. -* https://www.xilinx.com/support/documentation/user_guides/ug574-ultrascale-clb.pdf -* -*/ - - -module bsg_mem_1rw_sync_mask_write_bit #( - parameter width_p = "inv" - , parameter els_p = "inv" - , parameter latch_last_read_p=0 - , parameter enable_clock_gating_p=0 - , localparam addr_width_lp = `BSG_SAFE_CLOG2(els_p) -) ( - input clk_i - , input reset_i - , input [ width_p-1:0] data_i - , input [addr_width_lp-1:0] addr_i - , input v_i - , input [ width_p-1:0] w_mask_i - , input w_i - , output [ width_p-1:0] data_o -); - - wire unused = reset_i; - - (* ram_style = "distributed" *) logic [width_p-1:0] mem [els_p-1:0]; - - logic [width_p-1:0] data_r; - always_ff @(posedge clk_i) begin - if (v_i & ~w_i) - data_r <= mem[addr_i]; - end - - assign data_o = data_r; - - for (genvar i=0; i> 1'b1; - - always_comb - begin - mem_cmd_v_o = cfg_v_lo; - - // uncached store - mem_cmd_cast_o.msg_type = e_cce_mem_uc_wr; - mem_cmd_cast_o.addr = bp_cfg_base_addr_gp; - mem_cmd_cast_o.payload = '0; - mem_cmd_cast_o.size = e_mem_size_8; - mem_cmd_cast_o.data = cce_block_width_p'({cfg_core_lo, cfg_addr_lo, cfg_data_lo}); - end - - always_comb - begin - ucode_cnt_clr = 1'b0; - ucode_cnt_inc = 1'b0; - - cfg_v_lo = '0; - cfg_core_lo = 8'hff; - cfg_addr_lo = '0; - cfg_data_lo = '0; - - case (state_r) - RESET: begin - state_n = skip_ram_init_p ? BP_FREEZE_CLR : BP_RESET_SET; - - ucode_cnt_clr = 1'b1; - end - BP_RESET_SET: begin - state_n = BP_FREEZE_SET; - - cfg_v_lo = 1'b1; - cfg_addr_lo = bp_cfg_reg_reset_gp; - cfg_data_lo = cfg_data_width_p'(1); - end - BP_FREEZE_SET: begin - state_n = BP_RESET_CLR; - - cfg_v_lo = 1'b1; - cfg_addr_lo = bp_cfg_reg_freeze_gp; - cfg_data_lo = cfg_data_width_p'(1); - end - BP_RESET_CLR: begin - state_n = SEND_RAM_LO; - - cfg_v_lo = 1'b1; - cfg_addr_lo = bp_cfg_reg_reset_gp; - cfg_data_lo = cfg_data_width_p'(0); - end - SEND_RAM_LO: begin - state_n = SEND_RAM_HI; - - cfg_v_lo = 1'b1; - cfg_addr_lo = cfg_addr_width_p'(bp_cfg_mem_base_cce_ucode_gp) + (ucode_cnt_r << 1); - cfg_data_lo = cce_inst_boot_rom_data[0+:cfg_data_width_p]; - // TODO: This is nonsynth, won't work on FPGA - cfg_data_lo = (|cfg_data_lo === 'X) ? '0 : cfg_data_lo; - end - SEND_RAM_HI: begin - state_n = ucode_prog_done ? SEND_CCE_NORMAL : SEND_RAM_LO; - - ucode_cnt_inc = 1'b1; - - cfg_v_lo = 1'b1; - cfg_addr_lo = cfg_addr_width_p'(bp_cfg_mem_base_cce_ucode_gp) + (ucode_cnt_r << 1) + 1'b1; - cfg_data_lo = cfg_data_width_p'(cce_inst_boot_rom_data[inst_width_p-1:cfg_data_width_p]); - // TODO: This is nonsynth, won't work on FPGA - cfg_data_lo = (|cfg_data_lo === 'X) ? '0 : cfg_data_lo; - end - SEND_CCE_NORMAL: begin - state_n = SEND_ICACHE_NORMAL; - - cfg_v_lo = 1'b1; - cfg_addr_lo = bp_cfg_reg_cce_mode_gp; - cfg_data_lo = cfg_data_width_p'(e_cce_mode_normal); - end - SEND_ICACHE_NORMAL: begin - state_n = SEND_DCACHE_NORMAL; - - cfg_v_lo = 1'b1; - cfg_addr_lo = cfg_addr_width_p'(bp_cfg_reg_icache_mode_gp); - cfg_data_lo = cfg_data_width_p'(e_dcache_lce_mode_normal); // TODO: tapeout hack, change to icache - end - SEND_DCACHE_NORMAL: begin - state_n = SEND_PC_LO; - - cfg_v_lo = 1'b1; - cfg_addr_lo = cfg_addr_width_p'(bp_cfg_reg_dcache_mode_gp); - cfg_data_lo = cfg_data_width_p'(e_dcache_lce_mode_normal); - end - SEND_PC_LO: begin - state_n = SEND_PC_HI; - - cfg_v_lo = 1'b1; - cfg_addr_lo = cfg_addr_width_p'(bp_cfg_reg_start_pc_lo_gp); - cfg_data_lo = bp_pc_entry_point_gp[0+:cfg_data_width_p]; - end - SEND_PC_HI: begin - state_n = BP_FREEZE_CLR; - - cfg_v_lo = 1'b1; - cfg_addr_lo = cfg_addr_width_p'(bp_cfg_reg_start_pc_hi_gp); - cfg_data_lo = cfg_data_width_p'(bp_pc_entry_point_gp[vaddr_width_p-1:cfg_data_width_p]); - end - BP_FREEZE_CLR: begin - state_n = DONE; - - cfg_v_lo = 1'b1; - cfg_addr_lo = cfg_addr_width_p'(bp_cfg_reg_freeze_gp); - cfg_data_lo = cfg_data_width_p'(0);; - end - DONE: begin - state_n = DONE; - end - default: begin - state_n = RESET; - end - endcase - end - -endmodule diff --git a/litex/soc/cores/cpu/blackparrot/bp_hardware/bp_common_pkg.vh b/litex/soc/cores/cpu/blackparrot/bp_hardware/bp_common_pkg.vh deleted file mode 100644 index 9500673b8..000000000 --- a/litex/soc/cores/cpu/blackparrot/bp_hardware/bp_common_pkg.vh +++ /dev/null @@ -1,55 +0,0 @@ -/* - * bp_common_pkg.vh - * - * Contains the interface structures used for communicating between FE, BE, ME in BlackParrot. - * Additionally contains global parameters used to configure the system. In the future, when - * multiple configurations are supported, these global parameters will belong to groups - * e.g. SV39, VM-disabled, ... - * - */ - -package bp_common_pkg; - - `include "bsg_defines.v" - `include "bp_common_defines.vh" - `include "bp_common_fe_be_if.vh" - `include "bp_common_me_if.vh" - - /* - * RV64 specifies a 64b effective address and 32b instruction. - * BlackParrot supports SV39 virtual memory, which specifies 39b virtual / 56b physical address. - * Effective addresses must have bits 39-63 match bit 38 - * or a page fault exception will occur during translation. - * Currently, we only support a very limited number of parameter configurations. - * Thought: We could have a `define surrounding core instantiations of each parameter and then - * when they import this package, `declare the if structs. No more casting! - */ - - localparam bp_eaddr_width_gp = 64; - localparam bp_instr_width_gp = 32; - - parameter bp_sv39_page_table_depth_gp = 3; - parameter bp_sv39_pte_width_gp = 64; - parameter bp_sv39_vaddr_width_gp = 39; - parameter bp_sv39_paddr_width_gp = 56; - parameter bp_sv39_ppn_width_gp = 44; - parameter bp_page_size_in_bytes_gp = 4096; - parameter bp_page_offset_width_gp = `BSG_SAFE_CLOG2(bp_page_size_in_bytes_gp); - - parameter bp_data_resp_num_flit_gp = 4; - parameter bp_data_cmd_num_flit_gp = 4; - - localparam dram_base_addr_gp = 32'h5000_0000; - - localparam cfg_link_dev_base_addr_gp = 32'h01??_????; - localparam clint_dev_base_addr_gp = 32'h02??_????; - localparam host_dev_base_addr_gp = 32'h03??_????; - localparam plic_dev_base_addr_gp = 32'h0c??_????; - - localparam mipi_reg_base_addr_gp = 32'h0200_0???; - localparam mtimecmp_reg_base_addr_gp = 32'h0200_4???; - localparam mtime_reg_addr_gp = 32'h0200_bff8; - localparam plic_reg_base_addr_gp = 32'h0c00_0???; - -endpackage : bp_common_pkg - diff --git a/litex/soc/cores/cpu/blackparrot/bp_hardware/bp_nonsynth_host.v b/litex/soc/cores/cpu/blackparrot/bp_hardware/bp_nonsynth_host.v deleted file mode 100644 index e64ce690a..000000000 --- a/litex/soc/cores/cpu/blackparrot/bp_hardware/bp_nonsynth_host.v +++ /dev/null @@ -1,190 +0,0 @@ - -module bp_nonsynth_host - import bp_common_pkg::*; - import bp_common_aviary_pkg::*; - import bp_be_pkg::*; - import bp_common_rv64_pkg::*; - import bp_cce_pkg::*; - import bsg_noc_pkg::*; - import bp_cfg_link_pkg::*; - #(parameter bp_cfg_e cfg_p = e_bp_inv_cfg - `declare_bp_proc_params(cfg_p) - `declare_bp_me_if_widths(paddr_width_p, cce_block_width_p, num_lce_p, lce_assoc_p) - ) - (input clk_i - , input reset_i - - , input [cce_mem_msg_width_lp-1:0] mem_cmd_i - , input mem_cmd_v_i - , output logic mem_cmd_yumi_o - - , output logic [cce_mem_msg_width_lp-1:0] mem_resp_o - , output logic mem_resp_v_o - , input mem_resp_ready_i - - , output [num_core_p-1:0] program_finish_o - ,(* mark_debug = "true" *) output logic all_finished_debug_o //SC_add - , (* mark_debug = "true" *) output logic core_passed_debug - , (* mark_debug = "true" *) output logic core_failed_debug - ); - -`declare_bp_me_if(paddr_width_p, cce_block_width_p, num_lce_p, lce_assoc_p); - -// HOST I/O mappings -//localparam host_dev_base_addr_gp = 32'h03??_????; - -// Host I/O mappings (arbitrarily decided for now) -// Overall host controls 32'h0300_0000-32'h03FF_FFFF - -localparam hprint_base_addr_gp = paddr_width_p'(32'h0300_0???); -localparam cprint_base_addr_gp = paddr_width_p'(64'h0300_1???); -localparam finish_base_addr_gp = paddr_width_p'(64'h0300_2???); - -bp_cce_mem_msg_s mem_cmd_cast_i; - -assign mem_cmd_cast_i = mem_cmd_i; - -localparam lg_num_core_lp = `BSG_SAFE_CLOG2(num_core_p); - -logic hprint_data_cmd_v; -logic cprint_data_cmd_v; -logic finish_data_cmd_v; - -always_comb - begin - hprint_data_cmd_v = 1'b0; - cprint_data_cmd_v = 1'b0; - finish_data_cmd_v = 1'b0; - - unique - casez (mem_cmd_cast_i.addr) - hprint_base_addr_gp: hprint_data_cmd_v = mem_cmd_v_i; - cprint_base_addr_gp: cprint_data_cmd_v = mem_cmd_v_i; - finish_base_addr_gp: finish_data_cmd_v = mem_cmd_v_i; - default: begin end - endcase - end - -logic [num_core_p-1:0] hprint_w_v_li; -logic [num_core_p-1:0] cprint_w_v_li; -logic [num_core_p-1:0] finish_w_v_li; - -// Memory-mapped I/O is 64 bit aligned -localparam byte_offset_width_lp = 3; -wire [lg_num_core_lp-1:0] mem_cmd_core_enc = - mem_cmd_cast_i.addr[byte_offset_width_lp+:lg_num_core_lp]; - -bsg_decode_with_v - #(.num_out_p(num_core_p)) - hprint_data_cmd_decoder - (.v_i(hprint_data_cmd_v) - ,.i(mem_cmd_core_enc) - - ,.o(hprint_w_v_li) - ); - -bsg_decode_with_v - #(.num_out_p(num_core_p)) - cprint_data_cmd_decoder - (.v_i(cprint_data_cmd_v) - ,.i(mem_cmd_core_enc) - - ,.o(cprint_w_v_li) - ); - -bsg_decode_with_v - #(.num_out_p(num_core_p)) - finish_data_cmd_decoder - (.v_i(finish_data_cmd_v) - ,.i(mem_cmd_core_enc) - - ,.o(finish_w_v_li) - ); - -logic [num_core_p-1:0] finish_r; -bsg_dff_reset - #(.width_p(num_core_p)) - finish_accumulator - (.clk_i(clk_i) - ,.reset_i(reset_i) - - ,.data_i(finish_r | finish_w_v_li) - ,.data_o(finish_r) - ); - -logic all_finished_r; -bsg_dff_reset - #(.width_p(1)) - all_finished_reg - (.clk_i(clk_i) - ,.reset_i(reset_i) - - ,.data_i(&finish_r) - ,.data_o(all_finished_r) - ); - -assign program_finish_o = finish_r; - -always_ff @(negedge clk_i) - begin - for (integer i = 0; i < num_core_p; i++) - begin - if (hprint_w_v_li[i] & mem_cmd_yumi_o) - $display("[CORE%0x PRT] %x", i, mem_cmd_cast_i.data[0+:8]); - if (cprint_w_v_li[i] & mem_cmd_yumi_o) - $display("[CORE%0x PRT] %c", i, mem_cmd_cast_i.data[0+:8]); - if (finish_w_v_li[i] & mem_cmd_yumi_o & ~mem_cmd_cast_i.data[0]) - begin - $display("[CORE%0x FSH] PASS", i); - core_passed_debug <= 1; - end - if (finish_w_v_li[i] & mem_cmd_yumi_o & mem_cmd_cast_i.data[0]) - begin - $display("[CORE%0x FSH] FAIL", i); - core_failed_debug <=1; - end - end - - if (all_finished_r) - begin - $display("All cores finished! Terminating..."); - $finish(); - all_finished_debug_o <= 1; - end - if (reset_i) - begin - all_finished_debug_o <= 0; - core_passed_debug <= 0; - core_failed_debug <= 0; - end - end -bp_cce_mem_msg_s mem_resp_lo; -logic mem_resp_v_lo, mem_resp_ready_lo; -assign mem_cmd_yumi_o = mem_cmd_v_i & mem_resp_ready_lo; -bsg_one_fifo - #(.width_p(cce_mem_msg_width_lp)) - mem_resp_buffer - (.clk_i(clk_i) - ,.reset_i(reset_i) - - ,.data_i(mem_resp_lo) - ,.v_i(mem_cmd_yumi_o) - ,.ready_o(mem_resp_ready_lo) - - ,.data_o(mem_resp_o) - ,.v_o(mem_resp_v_lo) - ,.yumi_i(mem_resp_ready_i & mem_resp_v_lo) - ); -assign mem_resp_v_o = mem_resp_v_lo & mem_resp_ready_i; - -assign mem_resp_lo = - '{msg_type : mem_cmd_cast_i.msg_type - ,addr : mem_cmd_cast_i.addr - ,payload : mem_cmd_cast_i.payload - ,size : mem_cmd_cast_i.size - ,data : '0 - }; - - -endmodule : bp_nonsynth_host - diff --git a/litex/soc/cores/cpu/blackparrot/bp_software/cce_ucode.mem b/litex/soc/cores/cpu/blackparrot/bp_software/cce_ucode.mem deleted file mode 100644 index 5815a7323..000000000 --- a/litex/soc/cores/cpu/blackparrot/bp_software/cce_ucode.mem +++ /dev/null @@ -1,96 +0,0 @@ -010001000001111100000000000000000000000001000000 -001000000001111100000000000010110000000000000000 -000001000000000011111000000000000000100000000000 -010001000011111100000000000000000000000000000010 -001000000011111100000000000000010000000000000000 -000001000010000111111000000000000000100000000000 -010001000101111100000000000000000000000000001000 -001000000101111100000000000001000000000000000000 -000001000100001011111000000000000000100000000000 -101001000000010010100110100000000000000000000000 -001111000000000000000000000001110000000000000000 -010001000001111100000000000000000000000000000000 -010001000011111100000000000000000000000000000010 -001101000010000000000000000110000000000000000000 -010001000101111100000000000000000000000000000000 -010001000111111100000000000000000000000001000000 -010001001001111100000000000000000000000000000000 -001101000110001000000000000101100000000000000000 -111001000001000001001100100100000000000000000000 -000000000100001011111000000000000000100000000000 -000000001000010011111000000000100000000000000000 -001111000000000000000000000100010000000000000000 -000000000000000011111000000000000000100000000000 -001111000000000000000000000011010000000000000000 -010001000001111100000000000000000000000000000000 -010001000011111100000000000000000000000000000010 -010001000111111100000000000000000000000000000000 -001101000010000000000000001000010000000000000000 -111001000000000010101100100100000000000000000000 -111010011001000000000000000000000000000000000000 -001001000110010000000000010111110000000000000000 -000000000000000011111000000000000000100000000000 -001111000000000000000000000110110000000000000000 -111000010000000000000000000000000000000000000000 -110001000000000000000000000000000000000000000000 -111011000000000000000000000000000000000000000000 -001010000011111100000000010110010000000000000001 -100000100000000000000000000000000000000000000000 -001010001001111100000000001000010000000000000001 -111010000000000000000000000000000000000000000000 -100001100010000000100000000000000000000000000000 -110000000000000000000000000000000000000000000000 -001010000001111100000000001100010000000000000001 -001010000101111100000000001011110000000000000001 -001010001101111100000000001011110000000000000001 -010100000001111100000000000000000000000000000010 -001111000000000000000000001100100000000000000000 -010100000001111100000000000000000000000000000001 -001111000000000000000000001100100000000000000000 -010100000001111100000000000000000000000000000110 -001010011011111100000000010000110000000000000000 -010001000001111100000000000000000000000000000000 -010001000011111100000000000000000000000000000010 -010001000101111100000000000000000000000000000000 -010001000111111100000000000000000000000000000001 -001101000010000000000000001111110000000000000000 -001011000001111100000000001111010000000000000000 -001011010000000000000000001111010000000000000000 -000000000100001011111000000000000000100000000000 -111001000110000010001010100100000000000000000000 -101010100000001010100100000000000000000000000000 -000000000000000011111000000000000000100000000000 -001111000000000000000000001101110000000000000000 -001000000101111100000000010000110000000000000000 -111010011001000000000000000000000000000000000000 -000001000100001011111000000000000000100000000000 -001111000000000000000000001111110000000000000000 -001010011001111100000000010001110000000000000000 -101010100010001000100000000000000000000000000000 -111001000101100010001000100100000000000000000000 -001111000000000000000000001000010000000000000000 -101001100010001001100010000000000000000000000000 -001010010111111100000000010011110000000000000000 -111001000011100010011011100100000000000000000000 -111011011000000000000000000000000000000000000000 -001010011101111100000000010011010000000000000001 -111001010100101010101100100000000000000000000000 -111010011000000000000000000000000000000000000000 -011000010110000000000000000000000000000000000000 -001010010101111100000000010101110000000000000000 -111001000010100110001001100100000000000000000000 -111001000011100110001001100100000000000000000000 -111011011000000000000000000000000000000000000000 -001010011101111100000000010101010000000000000001 -111001010100101010101100100100000000000000000000 -111010011000000000000000000000000000000000000000 -001111000000000000000000001000010000000000000000 -111001010000101010101100100100000000000000000000 -001111000000000000000000001000010000000000000000 -111010000000000000000000000000000000000000000000 -001010000001111100000000010111010000000000000001 -111001010000101010101100100100000000000000000000 -001111000000000000000000001000010000000000000000 -111001010000101010101100100100000000000000000000 -001111000000000000000000001000010000000000000000 -110111000000000000000000000000000000000000000000 diff --git a/litex/soc/cores/cpu/blackparrot/bp_software/udivmoddi4.c b/litex/soc/cores/cpu/blackparrot/bp_software/udivmoddi4.c deleted file mode 100644 index a57c6e0e6..000000000 --- a/litex/soc/cores/cpu/blackparrot/bp_software/udivmoddi4.c +++ /dev/null @@ -1,358 +0,0 @@ -/* ===-- udivmoddi4.c - Implement __udivmoddi4 -----------------------------=== - * - * The LLVM Compiler Infrastructure - * - * This file is dual licensed under the MIT and the University of Illinois Open - * Source Licenses. See LICENSE.TXT for details. - * - * ===----------------------------------------------------------------------=== - * - * This file implements __udivmoddi4 for the compiler_rt library. - * - * ===----------------------------------------------------------------------=== - */ - -#ifndef __blackparrot__ -#include "int_lib.h" - -/* Effects: if rem != 0, *rem = a % b - * Returns: a / b - */ - -/* Translated from Figure 3-40 of The PowerPC Compiler Writer's Guide */ - -COMPILER_RT_ABI du_int -__udivmoddi4(du_int a, du_int b, du_int* rem) -{ - const unsigned n_uword_bits = sizeof(su_int) * CHAR_BIT; - const unsigned n_udword_bits = sizeof(du_int) * CHAR_BIT; - udwords n; - n.all = a; - udwords d; - d.all = b; - udwords q; - udwords r; - unsigned sr; - /* special cases, X is unknown, K != 0 */ - if (n.s.high == 0) - { - if (d.s.high == 0) - { - /* 0 X - * --- - * 0 X - */ - if (rem) - *rem = n.s.low % d.s.low; - return n.s.low / d.s.low; - } - /* 0 X - * --- - * K X - */ - if (rem) - *rem = n.s.low; - return 0; - } - /* n.s.high != 0 */ - if (d.s.low == 0) - { - if (d.s.high == 0) - { - /* K X - * --- - * 0 0 - */ - if (rem) - *rem = n.s.high % d.s.low; - return n.s.high / d.s.low; - } - /* d.s.high != 0 */ - if (n.s.low == 0) - { - /* K 0 - * --- - * K 0 - */ - if (rem) - { - r.s.high = n.s.high % d.s.high; - r.s.low = 0; - *rem = r.all; - } - return n.s.high / d.s.high; - } - /* K K - * --- - * K 0 - */ - if ((d.s.high & (d.s.high - 1)) == 0) /* if d is a power of 2 */ - { - if (rem) - { - r.s.low = n.s.low; - r.s.high = n.s.high & (d.s.high - 1); - *rem = r.all; - } - return n.s.high >> __builtin_ctz(d.s.high); - } - /* K K - * --- - * K 0 - */ - sr = __builtin_clz(d.s.high) - __builtin_clz(n.s.high); - /* 0 <= sr <= n_uword_bits - 2 or sr large */ - if (sr > n_uword_bits - 2) - { - if (rem) - *rem = n.all; - return 0; - } - ++sr; - /* 1 <= sr <= n_uword_bits - 1 */ - /* q.all = n.all << (n_udword_bits - sr); */ - q.s.low = 0; - q.s.high = n.s.low << (n_uword_bits - sr); - /* r.all = n.all >> sr; */ - r.s.high = n.s.high >> sr; - r.s.low = (n.s.high << (n_uword_bits - sr)) | (n.s.low >> sr); - } - else /* d.s.low != 0 */ - { - if (d.s.high == 0) - { - /* K X - * --- - * 0 K - */ - if ((d.s.low & (d.s.low - 1)) == 0) /* if d is a power of 2 */ - { - if (rem) - *rem = n.s.low & (d.s.low - 1); - if (d.s.low == 1) - return n.all; - sr = __builtin_ctz(d.s.low); - q.s.high = n.s.high >> sr; - q.s.low = (n.s.high << (n_uword_bits - sr)) | (n.s.low >> sr); - return q.all; - } - /* K X - * --- - * 0 K - */ - sr = 1 + n_uword_bits + __builtin_clz(d.s.low) - __builtin_clz(n.s.high); - /* 2 <= sr <= n_udword_bits - 1 - * q.all = n.all << (n_udword_bits - sr); - * r.all = n.all >> sr; - */ - if (sr == n_uword_bits) - { - q.s.low = 0; - q.s.high = n.s.low; - r.s.high = 0; - r.s.low = n.s.high; - } - else if (sr < n_uword_bits) // 2 <= sr <= n_uword_bits - 1 - { - q.s.low = 0; - q.s.high = n.s.low << (n_uword_bits - sr); - r.s.high = n.s.high >> sr; - r.s.low = (n.s.high << (n_uword_bits - sr)) | (n.s.low >> sr); - } - else // n_uword_bits + 1 <= sr <= n_udword_bits - 1 - { - q.s.low = n.s.low << (n_udword_bits - sr); - q.s.high = (n.s.high << (n_udword_bits - sr)) | - (n.s.low >> (sr - n_uword_bits)); - r.s.high = 0; - r.s.low = n.s.high >> (sr - n_uword_bits); - } - } - else - { - /* K X - * --- - * K K - */ - sr = __builtin_clz(d.s.high) - __builtin_clz(n.s.high); - /* 0 <= sr <= n_uword_bits - 1 or sr large */ - if (sr > n_uword_bits - 1) - { - if (rem) - *rem = n.all; - return 0; - } - ++sr; - /* 1 <= sr <= n_uword_bits */ - /* q.all = n.all << (n_udword_bits - sr); */ - q.s.low = 0; - if (sr == n_uword_bits) - { - q.s.high = n.s.low; - r.s.high = 0; - r.s.low = n.s.high; - } - else - { - q.s.high = n.s.low << (n_uword_bits - sr); - r.s.high = n.s.high >> sr; - r.s.low = (n.s.high << (n_uword_bits - sr)) | (n.s.low >> sr); - } - } - } - /* Not a special case - * q and r are initialized with: - * q.all = n.all << (n_udword_bits - sr); - * r.all = n.all >> sr; - * 1 <= sr <= n_udword_bits - 1 - */ - su_int carry = 0; - for (; sr > 0; --sr) - { - /* r:q = ((r:q) << 1) | carry */ - r.s.high = (r.s.high << 1) | (r.s.low >> (n_uword_bits - 1)); - r.s.low = (r.s.low << 1) | (q.s.high >> (n_uword_bits - 1)); - q.s.high = (q.s.high << 1) | (q.s.low >> (n_uword_bits - 1)); - q.s.low = (q.s.low << 1) | carry; - /* carry = 0; - * if (r.all >= d.all) - * { - * r.all -= d.all; - * carry = 1; - * } - */ - const di_int s = (di_int)(d.all - r.all - 1) >> (n_udword_bits - 1); - carry = s & 1; - r.all -= d.all & s; - } - q.all = (q.all << 1) | carry; - if (rem) - *rem = r.all; - return q.all; -} -#else - -/* More subroutines needed by GCC output code on some machines. */ -/* Compile this one with gcc. */ -/* Copyright (C) 1989-2014 Free Software Foundation, Inc. - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 3, or (at your option) any later -version. - -GCC is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. - -Under Section 7 of GPL version 3, you are granted additional -permissions described in the GCC Runtime Library Exception, version -3.1, as published by the Free Software Foundation. - -You should have received a copy of the GNU General Public License and -a copy of the GCC Runtime Library Exception along with this program; -see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -. */ - -/* This is extracted from gcc's libgcc/libgcc2.c with these typedefs added: */ -typedef short Wtype; -typedef int DWtype; -typedef unsigned int UWtype; -typedef unsigned long long UDWtype; -#if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__ -struct DWstruct {Wtype high, low;}; -#else -struct DWstruct {Wtype low, high;}; -#endif -typedef union { - struct DWstruct s; - DWtype ll; -} DWunion; - -UDWtype -__udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp) -{ - UDWtype q = 0, r = n, y = d; - UWtype lz1, lz2, i, k; - - /* Implements align divisor shift dividend method. This algorithm - aligns the divisor under the dividend and then perform number of - test-subtract iterations which shift the dividend left. Number of - iterations is k + 1 where k is the number of bit positions the - divisor must be shifted left to align it under the dividend. - quotient bits can be saved in the rightmost positions of the dividend - as it shifts left on each test-subtract iteration. */ - - if (y <= r) - { - lz1 = __builtin_clzll (d); - lz2 = __builtin_clzll (n); - - k = lz1 - lz2; - y = (y << k); - - /* Dividend can exceed 2 ^ (width − 1) − 1 but still be less than the - aligned divisor. Normal iteration can drops the high order bit - of the dividend. Therefore, first test-subtract iteration is a - special case, saving its quotient bit in a separate location and - not shifting the dividend. */ - if (r >= y) - { - r = r - y; - q = (1ULL << k); - } - - if (k > 0) - { - y = y >> 1; - - /* k additional iterations where k regular test subtract shift - dividend iterations are done. */ - i = k; - do - { - if (r >= y) - r = ((r - y) << 1) + 1; - else - r = (r << 1); - i = i - 1; - } while (i != 0); - - /* First quotient bit is combined with the quotient bits resulting - from the k regular iterations. */ - q = q + r; - r = r >> k; - q = q - (r << k); - } - } - - if (rp) - *rp = r; - return q; -} - -DWtype -__moddi3 (DWtype u, DWtype v) -{ - Wtype c = 0; - DWunion uu = {.ll = u}; - DWunion vv = {.ll = v}; - DWtype w; - - if (uu.s.high < 0) - c = ~c, - uu.ll = -uu.ll; - if (vv.s.high < 0) - vv.ll = -vv.ll; - - (void) __udivmoddi4 (uu.ll, vv.ll, (UDWtype*)&w); - if (c) - w = -w; - - return w; -} - -#endif diff --git a/litex/soc/cores/cpu/blackparrot/core.py b/litex/soc/cores/cpu/blackparrot/core.py index e9ad41643..9f3d4fb7c 100644 --- a/litex/soc/cores/cpu/blackparrot/core.py +++ b/litex/soc/cores/cpu/blackparrot/core.py @@ -35,32 +35,33 @@ from migen import * from litex import get_data_mod from litex.soc.interconnect import axi from litex.soc.interconnect import wishbone -from litex.soc.cores.cpu import CPU +from litex.soc.cores.cpu import CPU, CPU_GCC_TRIPLE_RISCV64 CPU_VARIANTS = { "standard": "freechips.rocketchip.system.LitexConfig", } GCC_FLAGS = { - "standard": "-march=rv64ia -mabi=lp64 -O0 ", + "standard": "-march=rv64ia -mabi=lp64 -O0 ", } class BlackParrotRV64(CPU): name = "blackparrot" + human_name = "BlackParrotRV64[ia]" data_width = 64 endianness = "little" - gcc_triple = ("riscv64-unknown-elf", "riscv64-linux", "riscv-sifive-elf", - "riscv64-none-elf") + gcc_triple = CPU_GCC_TRIPLE_RISCV64 linker_output_format = "elf64-littleriscv" - io_regions = {0x30000000: 0x20000000} # origin, length + nop = "nop" + io_regions = {0x50000000: 0x10000000} # origin, length @property def mem_map(self): return { - "ethmac" : 0x30000000, - "csr" : 0x40000000, - "rom" : 0x50000000, - "sram" : 0x51000000, + "csr" : 0x50000000, +# "ethmac" : 0x55000000, + "rom" : 0x70000000, + "sram" : 0x71000000, "main_ram" : 0x80000000, } @@ -77,48 +78,53 @@ class BlackParrotRV64(CPU): self.platform = platform self.variant = variant self.reset = Signal() - self.interrupt = Signal(4) +# self.interrupt = Signal(4) self.idbus = idbus = wishbone.Interface(data_width=64, adr_width=37) self.periph_buses = [idbus] self.memory_buses = [] - - # # # +# self.buses = [wbn] self.cpu_params = dict( # clock, reset - i_clk_i = ClockSignal(), - i_reset_i = ResetSignal() | self.reset, + i_clk_i = ClockSignal(), + i_reset_i = ResetSignal() | self.reset, # irq - i_interrupts = self.interrupt, + #i_interrupts = self.interrupt, - # wishbone - i_wbm_dat_i = idbus.dat_r, - o_wbm_dat_o = idbus.dat_w, - i_wbm_ack_i = idbus.ack, - i_wbm_err_i = 0, - i_wbm_rty_i = 0, - o_wbm_adr_o = idbus.adr, - o_wbm_stb_o = idbus.stb, - o_wbm_cyc_o = idbus.cyc, - o_wbm_sel_o = idbus.sel, - o_wbm_we_o = idbus.we, - o_wbm_cti_o = idbus.cti, - o_wbm_bte_o = idbus.bte, - ) + #wishbone + i_wbm_dat_i = idbus.dat_r, + o_wbm_dat_o = idbus.dat_w, + i_wbm_ack_i = idbus.ack, + i_wbm_err_i = idbus.err, + #i_wbm_rty_i = 0, + o_wbm_adr_o = idbus.adr, + o_wbm_stb_o = idbus.stb, + o_wbm_cyc_o = idbus.cyc, + o_wbm_sel_o = idbus.sel, + o_wbm_we_o = idbus.we, + o_wbm_cti_o = idbus.cti, + o_wbm_bte_o = idbus.bte, + ) - # add verilog sources + # add verilog sources self.add_sources(platform, variant) def set_reset_address(self, reset_address): assert not hasattr(self, "reset_address") self.reset_address = reset_address - assert reset_address == 0x00000000, "cpu_reset_addr hardcoded to 0x00000000!" + #FIXME: set reset addr to 0x70000000 + #assert reset_address == 0x00000000, "cpu_reset_addr hardcoded to 0x00000000!" @staticmethod def add_sources(platform, variant="standard"): - filename = get_data_mod("cpu", "blackparrot").data_file( - "flist_litex.verilator") + vdir = get_data_mod("cpu", "blackparrot").data_location + bp_litex_dir = os.path.join(vdir,"bp_litex") + simulation = 1 + if (simulation == 1): + filename= os.path.join(bp_litex_dir,"flist.verilator") + else: + filename= os.path.join(bp_litex_dir,"flist.fpga") with open(filename) as openfileobject: for line in openfileobject: temp = line @@ -131,7 +137,6 @@ class BlackParrotRV64(CPU): a = os.popen('echo '+ str(dir_)) dir_start = a.read() vdir = dir_start[:-1] + line[s2:-1] - print("INCDIR" + vdir) platform.add_verilog_include_path(vdir) #this line might be changed elif (temp[0]=='$') : s2 = line.find('/') @@ -139,7 +144,6 @@ class BlackParrotRV64(CPU): a = os.popen('echo '+ str(dir_)) dir_start = a.read() vdir = dir_start[:-1]+ line[s2:-1] - print(vdir) platform.add_source(vdir) #this line might be changed elif (temp[0] == '/'): assert("No support for absolute path for now") diff --git a/litex/soc/software/libbase/crt0-blackparrot.S b/litex/soc/cores/cpu/blackparrot/crt0.S similarity index 94% rename from litex/soc/software/libbase/crt0-blackparrot.S rename to litex/soc/cores/cpu/blackparrot/crt0.S index 9badaa48a..2b82399d4 100644 --- a/litex/soc/software/libbase/crt0-blackparrot.S +++ b/litex/soc/cores/cpu/blackparrot/crt0.S @@ -68,7 +68,7 @@ bss_loop: bss_done: // call plic_init // initialize external interrupt controller -# li a0, 0x800 // external interrupt sources only (using LiteX timer); + li a0, 0x800 // external interrupt sources only (using LiteX timer); // NOTE: must still enable mstatus.MIE! csrw mie,a0 diff --git a/litex/soc/cores/cpu/blackparrot/csr-defs.h b/litex/soc/cores/cpu/blackparrot/csr-defs.h new file mode 100644 index 000000000..170bd4540 --- /dev/null +++ b/litex/soc/cores/cpu/blackparrot/csr-defs.h @@ -0,0 +1,8 @@ +#ifndef CSR_DEFS__H +#define CSR_DEFS__H + +#define CSR_MSTATUS_MIE 0x8 + +#define CSR_DCACHE_INFO 0xCC0 + +#endif /* CSR_DEFS__H */ diff --git a/litex/soc/cores/cpu/blackparrot/flist_litex.verilator b/litex/soc/cores/cpu/blackparrot/flist_litex.verilator deleted file mode 100644 index 65e8e1c4e..000000000 --- a/litex/soc/cores/cpu/blackparrot/flist_litex.verilator +++ /dev/null @@ -1,228 +0,0 @@ -//// Includes -// bsg_ip_cores includes -+incdir+$BASEJUMP_STL_DIR/bsg_dataflow -+incdir+$BASEJUMP_STL_DIR/bsg_mem -+incdir+$BASEJUMP_STL_DIR/bsg_misc -+incdir+$BASEJUMP_STL_DIR/bsg_test -+incdir+$BASEJUMP_STL_DIR/bsg_noc -// common includes -+incdir+$BP_COMMON_DIR/src/include -// fe includes -+incdir+$BP_FE_DIR/src/include -// be includes -+incdir+$BP_BE_DIR/src/include -+incdir+$BP_BE_DIR/src/include/bp_be_dcache -// me includes -+incdir+$BP_ME_DIR/src/include/v -// top includes -+incdir+$BP_TOP_DIR/src/include -//// Packages -// bsg_ip_cores packages -$BASEJUMP_STL_DIR/bsg_noc/bsg_noc_pkg.v -$BASEJUMP_STL_DIR/bsg_noc/bsg_wormhole_router_pkg.v -// Interface packages -$BP_COMMON_DIR/src/include/bp_common_rv64_pkg.vh -$BP_COMMON_DIR/src/include/bp_common_pkg.vh -$BP_COMMON_DIR/src/include/bp_common_aviary_pkg.vh -// FE packages -$BP_FE_DIR/src/include/bp_fe_icache_pkg.vh -$BP_FE_DIR/src/include/bp_fe_pkg.vh -// BE packages -$BP_BE_DIR/src/include/bp_be_pkg.vh -$BP_BE_DIR/src/include/bp_be_dcache/bp_be_dcache_pkg.vh -// ME packages -$BP_ME_DIR/src/include/v/bp_cce_pkg.v -$BP_ME_DIR/src/include/v/bp_me_pkg.vh -// Top packages -$BP_TOP_DIR/src/include/bp_cfg_link_pkg.vh -//// bsg_ip_cores files -$BASEJUMP_STL_DIR/bsg_async/bsg_async_fifo.v -$BASEJUMP_STL_DIR/bsg_async/bsg_launch_sync_sync.v -$BASEJUMP_STL_DIR/bsg_async/bsg_async_ptr_gray.v -$BASEJUMP_STL_DIR/bsg_dataflow/bsg_channel_tunnel.v -$BASEJUMP_STL_DIR/bsg_dataflow/bsg_channel_tunnel_in.v -$BASEJUMP_STL_DIR/bsg_dataflow/bsg_channel_tunnel_out.v -$BASEJUMP_STL_DIR/bsg_dataflow/bsg_1_to_n_tagged_fifo.v -$BASEJUMP_STL_DIR/bsg_dataflow/bsg_1_to_n_tagged.v -$BASEJUMP_STL_DIR/bsg_dataflow/bsg_fifo_1r1w_large.v -$BASEJUMP_STL_DIR/bsg_dataflow/bsg_fifo_1rw_large.v -$BASEJUMP_STL_DIR/bsg_dataflow/bsg_serial_in_parallel_out.v -$BASEJUMP_STL_DIR/bsg_dataflow/bsg_one_fifo.v -$BASEJUMP_STL_DIR/bsg_dataflow/bsg_round_robin_2_to_2.v -$BASEJUMP_STL_DIR/bsg_dataflow/bsg_fifo_1r1w_pseudo_large.v -$BASEJUMP_STL_DIR/bsg_dataflow/bsg_fifo_1r1w_small.v -$BASEJUMP_STL_DIR/bsg_dataflow/bsg_fifo_tracker.v -$BASEJUMP_STL_DIR/bsg_dataflow/bsg_flow_counter.v -$BASEJUMP_STL_DIR/bsg_dataflow/bsg_parallel_in_serial_out_dynamic.v -$BASEJUMP_STL_DIR/bsg_dataflow/bsg_round_robin_n_to_1.v -$BASEJUMP_STL_DIR/bsg_dataflow/bsg_serial_in_parallel_out_dynamic.v -$BASEJUMP_STL_DIR/bsg_dataflow/bsg_shift_reg.v -$BASEJUMP_STL_DIR/bsg_dataflow/bsg_two_fifo.v -$BASEJUMP_STL_DIR/bsg_mem/bsg_cam_1r1w.v -$BASEJUMP_STL_DIR/bsg_mem/bsg_mem_1r1w.v -$BASEJUMP_STL_DIR/bsg_mem/bsg_mem_1r1w_sync.v -$BASEJUMP_STL_DIR/bsg_mem/bsg_mem_1r1w_sync_synth.v -$BASEJUMP_STL_DIR/bsg_mem/bsg_mem_1r1w_synth.v -$BASEJUMP_STL_DIR/bsg_mem/bsg_mem_1rw_sync.v -// $BASEJUMP_STL_DIR/bsg_mem/bsg_mem_1rw_sync_mask_write_bit.v -$BASEJUMP_STL_DIR/bsg_mem/bsg_mem_1rw_sync_mask_write_bit_synth.v -$BASEJUMP_STL_DIR/bsg_mem/bsg_mem_1rw_sync_mask_write_byte.v -$BASEJUMP_STL_DIR/bsg_mem/bsg_mem_1rw_sync_mask_write_byte_synth.v -$BASEJUMP_STL_DIR/bsg_mem/bsg_mem_1rw_sync_synth.v -$BASEJUMP_STL_DIR/bsg_mem/bsg_mem_2r1w_sync.v -$BASEJUMP_STL_DIR/bsg_mem/bsg_mem_2r1w_sync_synth.v -$BASEJUMP_STL_DIR/bsg_misc/bsg_adder_ripple_carry.v -$BASEJUMP_STL_DIR/bsg_misc/bsg_arb_fixed.v -$BASEJUMP_STL_DIR/bsg_misc/bsg_array_concentrate_static.v -$BASEJUMP_STL_DIR/bsg_misc/bsg_circular_ptr.v -$BASEJUMP_STL_DIR/bsg_misc/bsg_concentrate_static.v -$BASEJUMP_STL_DIR/bsg_misc/bsg_counter_clear_up.v -$BASEJUMP_STL_DIR/bsg_misc/bsg_counter_set_down.v -$BASEJUMP_STL_DIR/bsg_misc/bsg_counter_up_down.v -$BASEJUMP_STL_DIR/bsg_misc/bsg_counter_up_down_variable.v -$BASEJUMP_STL_DIR/bsg_misc/bsg_crossbar_o_by_i.v -$BASEJUMP_STL_DIR/bsg_misc/bsg_cycle_counter.v -$BASEJUMP_STL_DIR/bsg_misc/bsg_decode.v -$BASEJUMP_STL_DIR/bsg_misc/bsg_decode_with_v.v -$BASEJUMP_STL_DIR/bsg_misc/bsg_dff.v -$BASEJUMP_STL_DIR/bsg_misc/bsg_dff_en_bypass.v -$BASEJUMP_STL_DIR/bsg_misc/bsg_dff_chain.v -$BASEJUMP_STL_DIR/bsg_misc/bsg_dff_en.v -$BASEJUMP_STL_DIR/bsg_misc/bsg_dff_reset.v -$BASEJUMP_STL_DIR/bsg_misc/bsg_dff_reset_en.v -$BASEJUMP_STL_DIR/bsg_misc/bsg_encode_one_hot.v -$BASEJUMP_STL_DIR/bsg_misc/bsg_lfsr.v -$BASEJUMP_STL_DIR/bsg_misc/bsg_lru_pseudo_tree_decode.v -$BASEJUMP_STL_DIR/bsg_misc/bsg_lru_pseudo_tree_encode.v -$BASEJUMP_STL_DIR/bsg_misc/bsg_mux.v -$BASEJUMP_STL_DIR/bsg_misc/bsg_mux_butterfly.v -$BASEJUMP_STL_DIR/bsg_misc/bsg_mux_one_hot.v -$BASEJUMP_STL_DIR/bsg_misc/bsg_mux_segmented.v -$BASEJUMP_STL_DIR/bsg_misc/bsg_priority_encode.v -$BASEJUMP_STL_DIR/bsg_misc/bsg_priority_encode_one_hot_out.v -$BASEJUMP_STL_DIR/bsg_misc/bsg_round_robin_arb.v -$BASEJUMP_STL_DIR/bsg_misc/bsg_scan.v -$BASEJUMP_STL_DIR/bsg_misc/bsg_swap.v -$BASEJUMP_STL_DIR/bsg_misc/bsg_thermometer_count.v -$BASEJUMP_STL_DIR/bsg_misc/bsg_transpose.v -$BASEJUMP_STL_DIR/bsg_misc/bsg_unconcentrate_static.v -$BASEJUMP_STL_DIR/bsg_noc/bsg_mesh_router.v -$BASEJUMP_STL_DIR/bsg_noc/bsg_mesh_router_buffered.v -$BASEJUMP_STL_DIR/bsg_noc/bsg_noc_repeater_node.v -$BASEJUMP_STL_DIR/bsg_noc/bsg_wormhole_concentrator.v -$BASEJUMP_STL_DIR/bsg_noc/bsg_wormhole_concentrator_in.v -$BASEJUMP_STL_DIR/bsg_noc/bsg_wormhole_concentrator_out.v -$BASEJUMP_STL_DIR/bsg_noc/bsg_wormhole_router.v -$BASEJUMP_STL_DIR/bsg_noc/bsg_wormhole_router_adapter.v -$BASEJUMP_STL_DIR/bsg_noc/bsg_wormhole_router_adapter_in.v -$BASEJUMP_STL_DIR/bsg_noc/bsg_wormhole_router_adapter_out.v -$BASEJUMP_STL_DIR/bsg_noc/bsg_wormhole_router_decoder_dor.v -$BASEJUMP_STL_DIR/bsg_noc/bsg_wormhole_router_input_control.v -$BASEJUMP_STL_DIR/bsg_noc/bsg_wormhole_router_output_control.v -// Common files -$BP_COMMON_DIR/src/v/bsg_fifo_1r1w_fence.v -$BP_COMMON_DIR/src/v/bsg_fifo_1r1w_rolly.v -$BP_COMMON_DIR/src/v/bp_tlb.v -$BP_COMMON_DIR/src/v/bp_tlb_replacement.v -// BE files -$BP_BE_DIR/src/v/bp_be_top.v -// Calculator -$BP_BE_DIR/src/v/bp_be_calculator/bp_be_bypass.v -$BP_BE_DIR/src/v/bp_be_calculator/bp_be_calculator_top.v -$BP_BE_DIR/src/v/bp_be_calculator/bp_be_instr_decoder.v -$BP_BE_DIR/src/v/bp_be_calculator/bp_be_int_alu.v -$BP_BE_DIR/src/v/bp_be_calculator/bp_be_pipe_fp.v -$BP_BE_DIR/src/v/bp_be_calculator/bp_be_pipe_int.v -$BP_BE_DIR/src/v/bp_be_calculator/bp_be_pipe_mem.v -$BP_BE_DIR/src/v/bp_be_calculator/bp_be_pipe_mul.v -$BP_BE_DIR/src/v/bp_be_calculator/bp_be_regfile.v -// Checker -$BP_BE_DIR/src/v/bp_be_checker/bp_be_checker_top.v -$BP_BE_DIR/src/v/bp_be_checker/bp_be_detector.v -$BP_BE_DIR/src/v/bp_be_checker/bp_be_director.v -$BP_BE_DIR/src/v/bp_be_checker/bp_be_scheduler.v -// MMU -$BP_BE_DIR/src/v/bp_be_mem/bp_be_ptw.v -$BP_BE_DIR/src/v/bp_be_mem/bp_be_csr.v -$BP_BE_DIR/src/v/bp_be_mem/bp_be_dcache/bp_be_dcache.v -$BP_BE_DIR/src/v/bp_be_mem/bp_be_dcache/bp_be_dcache_lce_cmd.v -$BP_BE_DIR/src/v/bp_be_mem/bp_be_dcache/bp_be_dcache_lce.v -$BP_BE_DIR/src/v/bp_be_mem/bp_be_dcache/bp_be_dcache_lce_req.v -$BP_BE_DIR/src/v/bp_be_mem/bp_be_dcache/bp_be_dcache_wbuf.v -$BP_BE_DIR/src/v/bp_be_mem/bp_be_dcache/bp_be_dcache_wbuf_queue.v -$BP_BE_DIR/src/v/bp_be_mem/bp_be_mem_top.v -//// FE files -$BP_FE_DIR/src/v/bp_fe_bht.v -$BP_FE_DIR/src/v/bp_fe_btb.v -$BP_FE_DIR/src/v/bp_fe_lce_cmd.v -$BP_FE_DIR/src/v/bp_fe_icache.v -$BP_FE_DIR/src/v/bp_fe_instr_scan.v -$BP_FE_DIR/src/v/bp_fe_lce.v -$BP_FE_DIR/src/v/bp_fe_lce_req.v -$BP_FE_DIR/src/v/bp_fe_mem.v -$BP_FE_DIR/src/v/bp_fe_pc_gen.v -$BP_FE_DIR/src/v/bp_fe_top.v -//// ME files -// CCE -$BP_ME_DIR/src/v/cce/bp_cce.v -$BP_ME_DIR/src/v/cce/bp_cce_alu.v -$BP_ME_DIR/src/v/cce/bp_cce_dir.v -$BP_ME_DIR/src/v/cce/bp_cce_dir_tag_checker.v -$BP_ME_DIR/src/v/cce/bp_cce_dir_lru_extract.v -$BP_ME_DIR/src/v/cce/bp_cce_gad.v -$BP_ME_DIR/src/v/cce/bp_cce_inst_decode.v -$BP_ME_DIR/src/v/cce/bp_cce_msg.v -$BP_ME_DIR/src/v/cce/bp_cce_msg_cached.v -$BP_ME_DIR/src/v/cce/bp_cce_msg_uncached.v -$BP_ME_DIR/src/v/cce/bp_cce_pc.v -$BP_ME_DIR/src/v/cce/bp_cce_pending.v -$BP_ME_DIR/src/v/cce/bp_cce_reg.v -$BP_ME_DIR/src/v/cce/bp_cce_top.v -// Network -$BP_ME_DIR/src/v/wormhole/bp_me_cce_id_to_cord.v -$BP_ME_DIR/src/v/wormhole/bp_me_cce_to_wormhole_link_client.v -$BP_ME_DIR/src/v/wormhole/bp_me_cce_to_wormhole_link_master.v -$BP_ME_DIR/src/v/wormhole/bp_me_lce_id_to_cord.v -$BP_ME_DIR/src/v/wormhole/bp_me_wormhole_packet_encode_lce_cmd.v -$BP_ME_DIR/src/v/wormhole/bp_me_wormhole_packet_encode_lce_req.v -$BP_ME_DIR/src/v/wormhole/bp_me_wormhole_packet_encode_lce_resp.v -$BP_ME_DIR/src/v/wormhole/bp_me_wormhole_packet_encode_mem_cmd.v -$BP_ME_DIR/src/v/wormhole/bp_me_wormhole_packet_encode_mem_resp.v -//// TOP -$BP_TOP_DIR/src/v/bp_chip.v -$BP_TOP_DIR/src/v/bp_core.v -$BP_TOP_DIR/src/v/bp_core_complex.v -$BP_TOP_DIR/src/v/bp_mem_complex.v -$BP_TOP_DIR/src/v/bp_mmio_enclave.v -$BP_TOP_DIR/src/v/bp_mmio_node.v -$BP_TOP_DIR/src/v/bp_tile.v -$BP_TOP_DIR/src/v/bp_tile_node.v -//// Common -$BP_COMMON_DIR/src/v/bp_addr_map.v - -// bsg_ip_cores files -$BASEJUMP_STL_DIR/bsg_fsb/bsg_fsb_node_trace_replay.v -// be files -$BP_BE_DIR/test/common/bp_be_nonsynth_tracer.v -// $BP_BE_DIR/test/common/bp_be_nonsynth_perf.v -// me files -// $BP_ME_DIR/test/common/bp_mem.v -// $BP_ME_DIR/test/common/bp_mem_delay_model.v -// $BP_ME_DIR/test/common/bp_mem_transducer.v -// $BP_ME_DIR/test/common/bp_mem_storage_sync.v -// $BP_ME_DIR/test/common/dramsim2_wrapper.cpp -$BP_ME_DIR/test/common/bp_cce_mmio_cfg_loader.v -// $BP_ME_DIR/test/common/bp_mem_nonsynth_tracer.v -// $BP_ME_DIR/test/common/bp_cce_nonsynth_tracer.v -// $BP_ME_DIR/test/common/bp_mem_utils.cpp -// top files -$BP_TOP_DIR/test/common/bp_nonsynth_host.v -// $BP_TOP_DIR/test/common/bp_nonsynth_if_verif.v -$BP_TOP_DIR/test/common/bp_nonsynth_commit_tracer.v -// /home/scanakci/Research_sado/litex/litex/litex/soc/cores/cpu/blackparrot/pre-alpha-release/bp_top/syn/results/verilator/bp_top_trace_demo.e_bp_single_core_cfg.build/wrapper.v -// /home/scanakci/Research_sado/litex/litex/litex/soc/cores/cpu/blackparrot/pre-alpha-release/bp_top/syn/results/verilator/bp_top_trace_demo.e_bp_single_core_cfg.build/test_bp.cpp -$BP_FPGA_DIR/bp2wb_convertor.v -$BP_FPGA_DIR/ExampleBlackParrotSystem.v -$BP_FPGA_DIR/bsg_mem_1rw_sync_mask_write_bit.v -// Recent -$BASEJUMP_STL_DIR/bsg_noc/bsg_mesh_stitch.v diff --git a/litex/soc/cores/cpu/blackparrot/irq.h b/litex/soc/cores/cpu/blackparrot/irq.h new file mode 100644 index 000000000..af5b7991c --- /dev/null +++ b/litex/soc/cores/cpu/blackparrot/irq.h @@ -0,0 +1,51 @@ +#ifndef __IRQ_H +#define __IRQ_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +// The RocketChip uses a Platform-Level Interrupt Controller (PLIC) which +// is programmed and queried via a set of MMIO registers. +// TODO: How about Blackparrot? Should be probably included in linux version + +#define PLIC_BASE 0x0c000000L // Base address and per-pin priority array +#define PLIC_PENDING 0x0c001000L // Bit field matching currently pending pins +#define PLIC_ENABLED 0x0c002000L // Bit field corresponding to the current mask +#define PLIC_THRSHLD 0x0c200000L // Per-pin priority must be >= this to trigger +#define PLIC_CLAIM 0x0c200004L // Claim & completion register address + +static inline unsigned int irq_getie(void) +{ + return (csrr(mstatus) & CSR_MSTATUS_MIE) != 0; /* FIXME */ +} + +static inline void irq_setie(unsigned int ie) +{ + if(ie) csrs(mstatus,CSR_MSTATUS_MIE); else csrc(mstatus,CSR_MSTATUS_MIE); /* FIXME */ +} + +static inline unsigned int irq_getmask(void) +{ + return 0; /* FIXME */ +} + +static inline void irq_setmask(unsigned int mask) +{ + /* FIXME */ +} + +static inline unsigned int irq_pending(void) +{ + return csr_readl(PLIC_PENDING) >> 1; /* FIXME */ +} + +#ifdef __cplusplus +} +#endif + +#endif /* __IRQ_H */ diff --git a/litex/soc/cores/cpu/blackparrot/setEnvironment.sh b/litex/soc/cores/cpu/blackparrot/setEnvironment.sh index d818ec52b..0f6fa1268 100755 --- a/litex/soc/cores/cpu/blackparrot/setEnvironment.sh +++ b/litex/soc/cores/cpu/blackparrot/setEnvironment.sh @@ -1,97 +1,24 @@ #!/bin/bash ## Set common environment variables export LITEX=$(git rev-parse --show-toplevel) -export BP=$PWD -cp bp_software/cce_ucode.mem /tmp/. -cd pre-alpha-release -TOP=$(git rev-parse --show-toplevel) -export BP_COMMON_DIR=$TOP/bp_common -export BP_FE_DIR=$TOP/bp_fe -export BP_BE_DIR=$TOP/bp_be -export BP_ME_DIR=$TOP/bp_me -export BP_TOP_DIR=$TOP/bp_top -export BP_EXTERNAL_DIR=$TOP/external +export BP=$LITEX/../pythondata-cpu-blackparrot/pythondata_cpu_blackparrot/system_verilog +export BP_LITEX_DIR=$BP/bp_litex +export LITEX_SOFTWARE_COMPILER_RT=$LITEX/../pythondata-software-compiler_rt + +#TODO: check if BP exists and warn user +export BP_COMMON_DIR=$BP/bp_common +export BP_FE_DIR=$BP/bp_fe +export BP_BE_DIR=$BP/bp_be +export BP_ME_DIR=$BP/bp_me +export BP_TOP_DIR=$BP/bp_top +export BP_EXTERNAL_DIR=$BP/external export BASEJUMP_STL_DIR=$BP_EXTERNAL_DIR/basejump_stl -export BP_FPGA_DIR=$TOP/bp_fpga -## Setup CAD tools +export LITEX_FPGA_DIR=$BP_LITEX_DIR/fpga +export LITEX_SIMU_DIR=$BP_LITEX_DIR/simulation +export BP_LITEX_SOFTWARE=$BP_LITEX_DIR/software -# If the machine you are working on is bsg_cadenv compliant, then you do not -# need to setup the cad tools, simply put bsg_cadenv in the same root dir. -#BSG_CADENV_DIR=$(TOP)/external/bsg_cadenv -#-include $(BSG_CADENV_DIR)/cadenv.mk +##SOFTWARE CHANGES## -## Sepcify license path if needed -#LM_LICENSE_FILE ?= +#for a reason, provided udivmoddi4.c is not functionally correct when used with either BP or Rocket under IA extension. Another version of udivmoddi4.c is a workaround to run BIOS on these architectures. +cp $BP_LITEX_SOFTWARE/udivmoddi4.c $LITEX_SOFTWARE_COMPILER_RT/pythondata_software_compiler_rt/data/lib/builtins/. -## Override tool paths if needed -#GCC ?= gcc -#VCS_HOME ?= -#VCS ?= vcs -#URG ?= urg -#VERILATOR ?= verilator -#DC_SHELL ?= dc_shell -#DVE ?= dve -#PYTHON ?= python - -## Needed for verilator g++ compilations -export SYSTEMC_INCLUDE=$BP_EXTERNAL_DIR/include -export SYSTEMC_LIBDIR=$BP_EXTERNAL_DIR/lib-linux64 - -## Add external tools and libraries to environment -export LD_LIBRARY_PATH=$SYSTEMC_LIBDIR:$LD_LIBRARY_PATH -#export PATH=$(BP_EXTERNAL_DIR)/bin:$(PATH) -#export SYN_PATH=$(BP_TOP_DIR)/syn -#export TB_PATH=$(BP_TOP_DIR)/test/tb -#export MEM_PATH=$(BP_COMMON_DIR)/test/mem - -#export LOG_PATH=$(BP_TOP_DIR)/syn/logs -#export RESULTS_PATH=$(BP_TOP_DIR)/syn/results -#export REPORT_PATH=$(BP_TOP_DIR)/syn/reports - -TB="bp_top_trace_demo" -CFG="e_bp_single_core_cfg" -START_PC=0x80000000 -TOLERANCE=2 - -# Select CCE ROM based on CFG and Coherence Protocol -# TODO: is there a more scalable way to do this? -if [ $CFG = "e_bp_half_core_cfg" ] -then - NUM_LCE_P=1 - N_WG=64 -elif [ $CFG = "e_bp_single_core_cfg" ] -then - NUM_LCE_P=2 - N_WG=64 - #echo "Single Core config" -#elif ($CFG -eq e_bp_dual_core_cfg) -# NUM_LCE_P=4 -# N_WG=32 -#elif ($CFG -eq e_bp_quad_core_cfg) -# NUM_LCE_P=8 -# N_WG=16 -#elif ($CFG -eq e_bp_oct_core_cfg) -# NUM_LCE_P=16 -# N_WG=8 -#elif ($(CFG), e_bp_sexta_core_cfg) -# NUM_LCE_P=32 -# N_WG=4 -#elif ($(CFG), e_bp_quad_core_2d_cfg) -# NUM_LCE_P=8 -# N_WG=16 -#elif ($(CFG), e_bp_oct_core_2d_cfg) -# NUM_LCE_P=16 -# N_WG=8 -fi - -COH_PROTO="mesi" -CCE_MEM_PATH=$BP_ME_DIR/src/asm/roms/$COH_PROTO -CCE_MEM=bp_cce_inst_rom_$COH_PROTO_lce$NUM_LCE_P_wg$N_WG_assoc8.mem -#DRAMSIM_CH_CFG=DDR2_micron_16M_8b_x8_sg3E.ini -#DRAMSIM_SYS_CFG=system.ini -#$include $BP_COMMON_DIR/syn/Makefile.verilator -#iinclude $(BP_COMMON_DIR)/syn/Makefile.common -#include $(BP_COMMON_DIR)/syn/Makefile.dc -#include $(BP_COMMON_DIR)/syn/Makefile.regress -#include $(BP_COMMON_DIR)/syn/Makefile.vcs -cd ../ diff --git a/litex/soc/cores/cpu/blackparrot/system.h b/litex/soc/cores/cpu/blackparrot/system.h new file mode 100644 index 000000000..079c7cfd7 --- /dev/null +++ b/litex/soc/cores/cpu/blackparrot/system.h @@ -0,0 +1,41 @@ +#ifndef __SYSTEM_H +#define __SYSTEM_H + +#ifdef __cplusplus +extern "C" { +#endif + +__attribute__((unused)) static void flush_cpu_icache(void){}; /* FIXME: do something useful here! */ +__attribute__((unused)) static void flush_cpu_dcache(void){}; /* FIXME: do something useful here! */ +void flush_l2_cache(void); +void busy_wait(unsigned int ms); + +#include + +#define csrr(reg) ({ unsigned long __tmp; \ + asm volatile ("csrr %0, " #reg : "=r"(__tmp)); \ + __tmp; }) + +#define csrw(reg, val) ({ \ + if (__builtin_constant_p(val) && (unsigned long)(val) < 32) \ + asm volatile ("csrw " #reg ", %0" :: "i"(val)); \ + else \ + asm volatile ("csrw " #reg ", %0" :: "r"(val)); }) + +#define csrs(reg, bit) ({ \ + if (__builtin_constant_p(bit) && (unsigned long)(bit) < 32) \ + asm volatile ("csrrs x0, " #reg ", %0" :: "i"(bit)); \ + else \ + asm volatile ("csrrs x0, " #reg ", %0" :: "r"(bit)); }) + +#define csrc(reg, bit) ({ \ + if (__builtin_constant_p(bit) && (unsigned long)(bit) < 32) \ + asm volatile ("csrrc x0, " #reg ", %0" :: "i"(bit)); \ + else \ + asm volatile ("csrrc x0, " #reg ", %0" :: "r"(bit)); }) + +#ifdef __cplusplus +} +#endif + +#endif /* __SYSTEM_H */ diff --git a/litex/soc/cores/cpu/blackparrot/update_BP.sh b/litex/soc/cores/cpu/blackparrot/update_BP.sh deleted file mode 100755 index c6ddde977..000000000 --- a/litex/soc/cores/cpu/blackparrot/update_BP.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash - - -##SOFTWARE CHANGES## - -#for a reason, provided udivmoddi4.c is not functionally correct when used with either BP or Rocket under IA extension. Another version of udivmoddi4.c is a workaround to run BIOS on these architectures. -cp bp_software/udivmoddi4.c $LITEX/litex/soc/software/compiler_rt/lib/builtins/. -cp bp_software/cce_ucode.mem /tmp/. - -##HARDWARE CHANGES## -#Need to change some files because of memory map differences and proper syntesis -cp bp_hardware/bp_common_pkg.vh $BP_COMMON_DIR/src/include/. -cp bp_hardware/bp_cce_mmio_cfg_loader.v $BP_ME_DIR/test/common/. -cp bp_hardware/bp_nonsynth_host.v $BP_TOP_DIR/test/common/. - -# Neccessary files for FPGA Implementations -cp -r bp_fpga $BP_TOP/DIR diff --git a/litex/soc/software/bios/boot-helper-lm32.S b/litex/soc/cores/cpu/lm32/boot-helper.S similarity index 100% rename from litex/soc/software/bios/boot-helper-lm32.S rename to litex/soc/cores/cpu/lm32/boot-helper.S diff --git a/litex/soc/cores/cpu/lm32/core.py b/litex/soc/cores/cpu/lm32/core.py index 42d5a9754..2b6273f3d 100644 --- a/litex/soc/cores/cpu/lm32/core.py +++ b/litex/soc/cores/cpu/lm32/core.py @@ -18,10 +18,12 @@ CPU_VARIANTS = ["minimal", "lite", "standard"] class LM32(CPU): name = "lm32" + human_name = "LM32" data_width = 32 endianness = "big" gcc_triple = "lm32-elf" linker_output_format = "elf32-lm32" + nop = "nop" io_regions = {0x80000000: 0x80000000} # origin, length @property diff --git a/litex/soc/software/libbase/crt0-lm32.S b/litex/soc/cores/cpu/lm32/crt0.S old mode 100755 new mode 100644 similarity index 100% rename from litex/soc/software/libbase/crt0-lm32.S rename to litex/soc/cores/cpu/lm32/crt0.S diff --git a/litex/soc/cores/cpu/lm32/irq.h b/litex/soc/cores/cpu/lm32/irq.h new file mode 100644 index 000000000..dd9477fa4 --- /dev/null +++ b/litex/soc/cores/cpu/lm32/irq.h @@ -0,0 +1,47 @@ +#ifndef __IRQ_H +#define __IRQ_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +static inline unsigned int irq_getie(void) +{ + unsigned int ie; + __asm__ __volatile__("rcsr %0, IE" : "=r" (ie)); + return ie; +} + +static inline void irq_setie(unsigned int ie) +{ + __asm__ __volatile__("wcsr IE, %0" : : "r" (ie)); +} + +static inline unsigned int irq_getmask(void) +{ + unsigned int mask; + __asm__ __volatile__("rcsr %0, IM" : "=r" (mask)); + return mask; +} + +static inline void irq_setmask(unsigned int mask) +{ + __asm__ __volatile__("wcsr IM, %0" : : "r" (mask)); +} + +static inline unsigned int irq_pending(void) +{ + unsigned int pending; + __asm__ __volatile__("rcsr %0, IP" : "=r" (pending)); + return pending; +} + +#ifdef __cplusplus +} +#endif + +#endif /* __IRQ_H */ diff --git a/litex/soc/cores/cpu/lm32/system.h b/litex/soc/cores/cpu/lm32/system.h new file mode 100644 index 000000000..1272cf1ae --- /dev/null +++ b/litex/soc/cores/cpu/lm32/system.h @@ -0,0 +1,35 @@ +#ifndef __SYSTEM_H +#define __SYSTEM_H + +#ifdef __cplusplus +extern "C" { +#endif + +__attribute__((unused)) static void flush_cpu_icache(void) +{ + asm volatile( + "wcsr ICC, r0\n" + "nop\n" + "nop\n" + "nop\n" + "nop\n" + ); +} + +__attribute__((unused)) static void flush_cpu_dcache(void) +{ + asm volatile( + "wcsr DCC, r0\n" + "nop\n" + ); +} + +void flush_l2_cache(void); + +void busy_wait(unsigned int ms); + +#ifdef __cplusplus +} +#endif + +#endif /* __SYSTEM_H */ diff --git a/litex/soc/software/bios/boot-helper-microwatt.S b/litex/soc/cores/cpu/microwatt/boot-helper.S similarity index 100% rename from litex/soc/software/bios/boot-helper-microwatt.S rename to litex/soc/cores/cpu/microwatt/boot-helper.S diff --git a/litex/soc/cores/cpu/microwatt/core.py b/litex/soc/cores/cpu/microwatt/core.py index ba3867d79..81802f345 100644 --- a/litex/soc/cores/cpu/microwatt/core.py +++ b/litex/soc/cores/cpu/microwatt/core.py @@ -16,10 +16,12 @@ CPU_VARIANTS = ["standard"] class Microwatt(CPU): name = "microwatt" + human_name = "Microwatt" data_width = 64 endianness = "little" - gcc_triple = ("powerpc64le-linux") + gcc_triple = ("powerpc64le-linux", "powerpc64le-linux-gnu") linker_output_format = "elf64-powerpcle" + nop = "nop" io_regions = {0xc0000000: 0x10000000} # origin, length @property @@ -45,8 +47,8 @@ class Microwatt(CPU): self.platform = platform self.variant = variant self.reset = Signal() - self.wb_insn = wb_insn = wishbone.Interface(data_width=64, adr_width=28) - self.wb_data = wb_data = wishbone.Interface(data_width=64, adr_width=28) + self.wb_insn = wb_insn = wishbone.Interface(data_width=64, adr_width=29) + self.wb_data = wb_data = wishbone.Interface(data_width=64, adr_width=29) self.periph_buses = [wb_insn, wb_data] self.memory_buses = [] @@ -62,7 +64,7 @@ class Microwatt(CPU): i_wishbone_insn_ack = wb_insn.ack, i_wishbone_insn_stall = wb_insn.cyc & ~wb_insn.ack, # No burst support - o_wishbone_insn_adr = Cat(Signal(4), wb_insn.adr), + o_wishbone_insn_adr = Cat(Signal(3), wb_insn.adr), o_wishbone_insn_dat_w = wb_insn.dat_w, o_wishbone_insn_cyc = wb_insn.cyc, o_wishbone_insn_stb = wb_insn.stb, @@ -74,7 +76,7 @@ class Microwatt(CPU): i_wishbone_data_ack = wb_data.ack, i_wishbone_data_stall = wb_data.cyc & ~wb_data.ack, # No burst support - o_wishbone_data_adr = Cat(Signal(4), wb_data.adr), + o_wishbone_data_adr = Cat(Signal(3), wb_data.adr), o_wishbone_data_dat_w = wb_data.dat_w, o_wishbone_data_cyc = wb_data.cyc, o_wishbone_data_stb = wb_data.stb, @@ -100,9 +102,7 @@ class Microwatt(CPU): @staticmethod def add_sources(platform): - sdir = os.path.join( - get_data_mod("cpu", "microwatt").data_location, - "sources") + sdir = get_data_mod("cpu", "microwatt").data_location platform.add_sources(sdir, # Common / Types / Helpers "decode_types.vhdl", @@ -155,7 +155,7 @@ class Microwatt(CPU): "core_debug.vhdl", "core.vhdl", ) - platform.add_source(os.path.join(sdir, "..", "microwatt_wrapper.vhdl")) + platform.add_source(os.path.join(os.path.dirname(__file__), "microwatt_wrapper.vhdl")) def do_finalize(self): self.specials += Instance("microwatt_wrapper", **self.cpu_params) diff --git a/litex/soc/software/libbase/crt0-microwatt.S b/litex/soc/cores/cpu/microwatt/crt0.S similarity index 87% rename from litex/soc/software/libbase/crt0-microwatt.S rename to litex/soc/cores/cpu/microwatt/crt0.S index 0dd6f343b..e03ac0bb4 100644 --- a/litex/soc/software/libbase/crt0-microwatt.S +++ b/litex/soc/cores/cpu/microwatt/crt0.S @@ -14,8 +14,6 @@ * limitations under the License. */ -#define STACK_TOP 0xffff4000 - #define FIXUP_ENDIAN \ tdi 0,0,0x48; /* Reverse endian of b . + 8 */ \ b 191f; /* Skip trampoline if endian is good */ \ @@ -38,24 +36,17 @@ oris r,r, (e)@h; \ ori r,r, (e)@l; - .section ".head","ax" - . = 0 .global _start _start: FIXUP_ENDIAN /* setup stack */ - LOAD_IMM64(%r1, STACK_TOP - 0x100) + LOAD_IMM64(%r1, _fstack - 0x100) LOAD_IMM64(%r12, main) mtctr %r12, bctrl - ba 0 - - /* XXX: litedram init should not take exceptions, maybe we could get - * rid of these to save space, along with a core tweak to suppress - * exceptions in case they happen (just terminate ?) - */ + b . #define EXCEPTION(nr) \ .= nr; \ diff --git a/litex/soc/cores/cpu/microwatt/irq.h b/litex/soc/cores/cpu/microwatt/irq.h new file mode 100644 index 000000000..7374cf506 --- /dev/null +++ b/litex/soc/cores/cpu/microwatt/irq.h @@ -0,0 +1,4 @@ +#ifndef __IRQ_H +#define __IRQ_H + +#endif /* __IRQ_H */ diff --git a/litex/soc/cores/cpu/microwatt/system.h b/litex/soc/cores/cpu/microwatt/system.h new file mode 100644 index 000000000..941dc5644 --- /dev/null +++ b/litex/soc/cores/cpu/microwatt/system.h @@ -0,0 +1,18 @@ +#ifndef __SYSTEM_H +#define __SYSTEM_H + +#ifdef __cplusplus +extern "C" { +#endif + +__attribute__((unused)) static void flush_cpu_icache(void){}; /* FIXME: do something useful here! */ +__attribute__((unused)) static void flush_cpu_dcache(void){}; /* FIXME: do something useful here! */ +void flush_l2_cache(void); + +void busy_wait(unsigned int ms); + +#ifdef __cplusplus +} +#endif + +#endif /* __SYSTEM_H */ diff --git a/litex/soc/software/bios/boot-helper-minerva.S b/litex/soc/cores/cpu/minerva/boot-helper.S similarity index 100% rename from litex/soc/software/bios/boot-helper-minerva.S rename to litex/soc/cores/cpu/minerva/boot-helper.S diff --git a/litex/soc/cores/cpu/minerva/core.py b/litex/soc/cores/cpu/minerva/core.py index 4ec118b0f..64cf86662 100644 --- a/litex/soc/cores/cpu/minerva/core.py +++ b/litex/soc/cores/cpu/minerva/core.py @@ -7,19 +7,21 @@ import subprocess from migen import * +from litex import get_data_mod from litex.soc.interconnect import wishbone -from litex.soc.cores.cpu import CPU +from litex.soc.cores.cpu import CPU, CPU_GCC_TRIPLE_RISCV32 CPU_VARIANTS = ["standard"] class Minerva(CPU): name = "minerva" + human_name = "Minerva" data_width = 32 endianness = "little" - gcc_triple = ("riscv64-unknown-elf", "riscv32-unknown-elf", "riscv-none-embed", - "riscv64-linux", "riscv-sifive-elf", "riscv64-none-elf") + gcc_triple = CPU_GCC_TRIPLE_RISCV32 linker_output_format = "elf32-littleriscv" + nop = "nop" io_regions = {0x80000000: 0x80000000} # origin, length @property @@ -98,8 +100,8 @@ class Minerva(CPU): cli_params.append("--with-dcache") if with_muldiv: cli_params.append("--with-muldiv") - _dir = os.path.abspath(os.path.dirname(__file__)) - if subprocess.call(["python3", os.path.join(_dir, "verilog", "cli.py"), *cli_params, "generate"], + sdir = get_data_mod("cpu", "minerva").data_location + if subprocess.call(["python3", os.path.join(sdir, "cli.py"), *cli_params, "generate"], stdout=open(verilog_filename, "w")): raise OSError("Unable to elaborate Minerva CPU, please check your nMigen/Yosys install") diff --git a/litex/soc/software/libbase/crt0-minerva.S b/litex/soc/cores/cpu/minerva/crt0.S similarity index 100% rename from litex/soc/software/libbase/crt0-minerva.S rename to litex/soc/cores/cpu/minerva/crt0.S diff --git a/litex/soc/software/include/base/csr-defs.h b/litex/soc/cores/cpu/minerva/csr-defs.h similarity index 59% rename from litex/soc/software/include/base/csr-defs.h rename to litex/soc/cores/cpu/minerva/csr-defs.h index 75c8e043d..5f5ea8476 100644 --- a/litex/soc/software/include/base/csr-defs.h +++ b/litex/soc/cores/cpu/minerva/csr-defs.h @@ -3,15 +3,8 @@ #define CSR_MSTATUS_MIE 0x8 -#if defined (__vexriscv__) -#define CSR_IRQ_MASK 0xBC0 -#define CSR_IRQ_PENDING 0xFC0 -#endif - -#if defined (__minerva__) #define CSR_IRQ_MASK 0x330 #define CSR_IRQ_PENDING 0x360 -#endif #define CSR_DCACHE_INFO 0xCC0 diff --git a/litex/soc/cores/cpu/minerva/irq.h b/litex/soc/cores/cpu/minerva/irq.h new file mode 100644 index 000000000..69bac122d --- /dev/null +++ b/litex/soc/cores/cpu/minerva/irq.h @@ -0,0 +1,45 @@ +#ifndef __IRQ_H +#define __IRQ_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +static inline unsigned int irq_getie(void) +{ + return (csrr(mstatus) & CSR_MSTATUS_MIE) != 0; +} + +static inline void irq_setie(unsigned int ie) +{ + if(ie) csrs(mstatus,CSR_MSTATUS_MIE); else csrc(mstatus,CSR_MSTATUS_MIE); +} + +static inline unsigned int irq_getmask(void) +{ + unsigned int mask; + asm volatile ("csrr %0, %1" : "=r"(mask) : "i"(CSR_IRQ_MASK)); + return mask; +} + +static inline void irq_setmask(unsigned int mask) +{ + asm volatile ("csrw %0, %1" :: "i"(CSR_IRQ_MASK), "r"(mask)); +} + +static inline unsigned int irq_pending(void) +{ + unsigned int pending; + asm volatile ("csrr %0, %1" : "=r"(pending) : "i"(CSR_IRQ_PENDING)); + return pending; +} + +#ifdef __cplusplus +} +#endif + +#endif /* __IRQ_H */ diff --git a/litex/soc/cores/cpu/minerva/system.h b/litex/soc/cores/cpu/minerva/system.h new file mode 100644 index 000000000..408ab3659 --- /dev/null +++ b/litex/soc/cores/cpu/minerva/system.h @@ -0,0 +1,41 @@ +#ifndef __SYSTEM_H +#define __SYSTEM_H + +#ifdef __cplusplus +extern "C" { +#endif + +__attribute__((unused)) static void flush_cpu_icache(void){}; /* FIXME: do something useful here! */ +__attribute__((unused)) static void flush_cpu_dcache(void){}; /* FIXME: do something useful here! */ +void flush_l2_cache(void); +void busy_wait(unsigned int ms); + +#include + +#define csrr(reg) ({ unsigned long __tmp; \ + asm volatile ("csrr %0, " #reg : "=r"(__tmp)); \ + __tmp; }) + +#define csrw(reg, val) ({ \ + if (__builtin_constant_p(val) && (unsigned long)(val) < 32) \ + asm volatile ("csrw " #reg ", %0" :: "i"(val)); \ + else \ + asm volatile ("csrw " #reg ", %0" :: "r"(val)); }) + +#define csrs(reg, bit) ({ \ + if (__builtin_constant_p(bit) && (unsigned long)(bit) < 32) \ + asm volatile ("csrrs x0, " #reg ", %0" :: "i"(bit)); \ + else \ + asm volatile ("csrrs x0, " #reg ", %0" :: "r"(bit)); }) + +#define csrc(reg, bit) ({ \ + if (__builtin_constant_p(bit) && (unsigned long)(bit) < 32) \ + asm volatile ("csrrc x0, " #reg ", %0" :: "i"(bit)); \ + else \ + asm volatile ("csrrc x0, " #reg ", %0" :: "r"(bit)); }) + +#ifdef __cplusplus +} +#endif + +#endif /* __SYSTEM_H */ diff --git a/litex/soc/software/bios/boot-helper-mor1kx.S b/litex/soc/cores/cpu/mor1kx/boot-helper.S similarity index 100% rename from litex/soc/software/bios/boot-helper-mor1kx.S rename to litex/soc/cores/cpu/mor1kx/boot-helper.S diff --git a/litex/soc/cores/cpu/mor1kx/core.py b/litex/soc/cores/cpu/mor1kx/core.py index 5dea660fb..5f05ef340 100644 --- a/litex/soc/cores/cpu/mor1kx/core.py +++ b/litex/soc/cores/cpu/mor1kx/core.py @@ -17,11 +17,13 @@ CPU_VARIANTS = ["standard", "linux"] class MOR1KX(CPU): name = "mor1kx" + human_name = "MOR1KX" data_width = 32 endianness = "big" gcc_triple = "or1k-elf" clang_triple = "or1k-linux" linker_output_format = "elf32-or1k" + nop = "l.nop" io_regions = {0x80000000: 0x80000000} # origin, length @property diff --git a/litex/soc/software/libbase/crt0-mor1kx.S b/litex/soc/cores/cpu/mor1kx/crt0.S similarity index 100% rename from litex/soc/software/libbase/crt0-mor1kx.S rename to litex/soc/cores/cpu/mor1kx/crt0.S diff --git a/litex/soc/cores/cpu/mor1kx/irq.h b/litex/soc/cores/cpu/mor1kx/irq.h new file mode 100644 index 000000000..acc64c0a7 --- /dev/null +++ b/litex/soc/cores/cpu/mor1kx/irq.h @@ -0,0 +1,44 @@ +#ifndef __IRQ_H +#define __IRQ_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +static inline unsigned int irq_getie(void) +{ + return !!(mfspr(SPR_SR) & SPR_SR_IEE); +} + +static inline void irq_setie(unsigned int ie) +{ + if (ie & 0x1) + mtspr(SPR_SR, mfspr(SPR_SR) | SPR_SR_IEE); + else + mtspr(SPR_SR, mfspr(SPR_SR) & ~SPR_SR_IEE); +} + +static inline unsigned int irq_getmask(void) +{ + return mfspr(SPR_PICMR); +} + +static inline void irq_setmask(unsigned int mask) +{ + mtspr(SPR_PICMR, mask); +} + +static inline unsigned int irq_pending(void) +{ + return mfspr(SPR_PICSR); +} + +#ifdef __cplusplus +} +#endif + +#endif /* __IRQ_H */ diff --git a/litex/soc/software/include/base/spr-defs.h b/litex/soc/cores/cpu/mor1kx/spr-defs.h similarity index 99% rename from litex/soc/software/include/base/spr-defs.h rename to litex/soc/cores/cpu/mor1kx/spr-defs.h index e073a5068..4dbc3b1c7 100644 --- a/litex/soc/software/include/base/spr-defs.h +++ b/litex/soc/cores/cpu/mor1kx/spr-defs.h @@ -1,8 +1,8 @@ /* spr-defs.h - Special purpose registers definitions file - + Copyright (C) 2000 Damjan Lampret Copyright (C) 2008, 2010 Embecosm Limited - + Contributor Damjan Lampret Contributor Jeremy Bennett @@ -184,10 +184,10 @@ #define SPR_CPUCFGR_OV64S 0x00000200 /* ORVDX64 supported */ #define SPR_CPUCFGR_ND 0x00000400 /* No delay-slot */ #define SPR_CPUCFGR_AVRP 0x00000800 /* Architecture version register present */ -#define SPR_CPUCFGR_EVBARP 0x00001000 /* Exception vector base address register +#define SPR_CPUCFGR_EVBARP 0x00001000 /* Exception vector base address register present */ #define SPR_CPUCFGR_ISRP 0x00002000 /* Implementation-specific registers present */ -#define SPR_CPUCFGR_AECSRP 0x00004000 /* Arithmetic exception control/status +#define SPR_CPUCFGR_AECSRP 0x00004000 /* Arithmetic exception control/status registers present */ #define SPR_CPUCFGR_RES 0xffff8000 /* Reserved */ @@ -628,7 +628,7 @@ #define SPR_PCMR_DDS 0x00004000 /* Data dependency stall event */ #define SPR_PCMR_WPE 0x03ff8000 /* Watchpoint events */ -/* +/* * Bit definitions for the Power management register * */ diff --git a/litex/soc/cores/cpu/mor1kx/system.h b/litex/soc/cores/cpu/mor1kx/system.h new file mode 100644 index 000000000..77366810a --- /dev/null +++ b/litex/soc/cores/cpu/mor1kx/system.h @@ -0,0 +1,70 @@ +#ifndef __SYSTEM_H +#define __SYSTEM_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +static inline unsigned long mfspr(unsigned long add) +{ + unsigned long ret; + + __asm__ __volatile__ ("l.mfspr %0,%1,0" : "=r" (ret) : "r" (add)); + + return ret; +} + +static inline void mtspr(unsigned long add, unsigned long val) +{ + __asm__ __volatile__ ("l.mtspr %0,%1,0" : : "r" (add), "r" (val)); +} + +__attribute__((unused)) static void flush_cpu_icache(void) +{ + unsigned long iccfgr; + unsigned long cache_set_size; + unsigned long cache_ways; + unsigned long cache_block_size; + unsigned long cache_size; + int i; + + iccfgr = mfspr(SPR_ICCFGR); + cache_ways = 1 << (iccfgr & SPR_ICCFGR_NCW); + cache_set_size = 1 << ((iccfgr & SPR_ICCFGR_NCS) >> 3); + cache_block_size = (iccfgr & SPR_ICCFGR_CBS) ? 32 : 16; + cache_size = cache_set_size * cache_ways * cache_block_size; + + for (i = 0; i < cache_size; i += cache_block_size) + mtspr(SPR_ICBIR, i); +} + +__attribute__((unused)) static void flush_cpu_dcache(void) +{ + unsigned long dccfgr; + unsigned long cache_set_size; + unsigned long cache_ways; + unsigned long cache_block_size; + unsigned long cache_size; + int i; + + dccfgr = mfspr(SPR_DCCFGR); + cache_ways = 1 << (dccfgr & SPR_ICCFGR_NCW); + cache_set_size = 1 << ((dccfgr & SPR_DCCFGR_NCS) >> 3); + cache_block_size = (dccfgr & SPR_DCCFGR_CBS) ? 32 : 16; + cache_size = cache_set_size * cache_ways * cache_block_size; + + for (i = 0; i < cache_size; i += cache_block_size) + mtspr(SPR_DCBIR, i); +} + +void flush_l2_cache(void); + +void busy_wait(unsigned int ms); + +#ifdef __cplusplus +} +#endif + +#endif /* __SYSTEM_H */ diff --git a/litex/soc/software/bios/boot-helper-picorv32.S b/litex/soc/cores/cpu/picorv32/boot-helper.S similarity index 100% rename from litex/soc/software/bios/boot-helper-picorv32.S rename to litex/soc/cores/cpu/picorv32/boot-helper.S diff --git a/litex/soc/cores/cpu/picorv32/core.py b/litex/soc/cores/cpu/picorv32/core.py index ebb96b810..3f568db4b 100644 --- a/litex/soc/cores/cpu/picorv32/core.py +++ b/litex/soc/cores/cpu/picorv32/core.py @@ -13,7 +13,7 @@ from migen import * from litex import get_data_mod from litex.soc.interconnect import wishbone -from litex.soc.cores.cpu import CPU +from litex.soc.cores.cpu import CPU, CPU_GCC_TRIPLE_RISCV64 CPU_VARIANTS = ["minimal", "standard"] @@ -33,11 +33,12 @@ GCC_FLAGS = { class PicoRV32(CPU): name = "picorv32" + human_name = "PicoRV32" data_width = 32 endianness = "little" - gcc_triple = ("riscv64-unknown-elf", "riscv32-unknown-elf", "riscv-none-embed", - "riscv64-linux", "riscv-sifive-elf", "riscv64-none-elf") + gcc_triple = CPU_GCC_TRIPLE_RISCV64 linker_output_format = "elf32-littleriscv" + nop = "nop" io_regions = {0x80000000: 0x80000000} # origin, length @property diff --git a/litex/soc/software/libbase/crt0-picorv32.S b/litex/soc/cores/cpu/picorv32/crt0.S similarity index 99% rename from litex/soc/software/libbase/crt0-picorv32.S rename to litex/soc/cores/cpu/picorv32/crt0.S index 3f7a4f5c0..49883ed09 100644 --- a/litex/soc/software/libbase/crt0-picorv32.S +++ b/litex/soc/cores/cpu/picorv32/crt0.S @@ -5,7 +5,7 @@ * purpose with or without fee is hereby granted. */ -#include "picorv32-extraops.S" +#include "extraops.S" /* * Interrupt vector. diff --git a/litex/soc/software/include/base/picorv32-extraops.S b/litex/soc/cores/cpu/picorv32/extraops.S similarity index 100% rename from litex/soc/software/include/base/picorv32-extraops.S rename to litex/soc/cores/cpu/picorv32/extraops.S diff --git a/litex/soc/cores/cpu/picorv32/irq.h b/litex/soc/cores/cpu/picorv32/irq.h new file mode 100644 index 000000000..0badb1320 --- /dev/null +++ b/litex/soc/cores/cpu/picorv32/irq.h @@ -0,0 +1,67 @@ +#ifndef __IRQ_H +#define __IRQ_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +// PicoRV32 has a very limited interrupt support, implemented via custom +// instructions. It also doesn't have a global interrupt enable/disable, so +// we have to emulate it via saving and restoring a mask and using 0/~1 as a +// hardware mask. +// Due to all this somewhat low-level mess, all of the glue is implemented in +// the RiscV crt0, and this header is kept as a thin wrapper. Since interrupts +// managed by this layer, do not call interrupt instructions directly, as the +// state will go out of sync with the hardware. + +// Read only. +extern unsigned int _irq_pending; +// Read only. +extern unsigned int _irq_mask; +// Read only. +extern unsigned int _irq_enabled; +extern void _irq_enable(void); +extern void _irq_disable(void); +extern void _irq_setmask(unsigned int); + +static inline unsigned int irq_getie(void) +{ + return _irq_enabled != 0; +} + +static inline void irq_setie(unsigned int ie) +{ + if (ie & 0x1) + _irq_enable(); + else + _irq_disable(); +} + +static inline unsigned int irq_getmask(void) +{ + // PicoRV32 interrupt mask bits are high-disabled. This is the inverse of how + // LiteX sees things. + return ~_irq_mask; +} + +static inline void irq_setmask(unsigned int mask) +{ + // PicoRV32 interrupt mask bits are high-disabled. This is the inverse of how + // LiteX sees things. + _irq_setmask(~mask); +} + +static inline unsigned int irq_pending(void) +{ + return _irq_pending; +} + +#ifdef __cplusplus +} +#endif + +#endif /* __IRQ_H */ diff --git a/litex/soc/cores/cpu/picorv32/system.h b/litex/soc/cores/cpu/picorv32/system.h new file mode 100644 index 000000000..afa56d677 --- /dev/null +++ b/litex/soc/cores/cpu/picorv32/system.h @@ -0,0 +1,18 @@ +#ifndef __SYSTEM_H +#define __SYSTEM_H + +#ifdef __cplusplus +extern "C" { +#endif + +__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); + +#ifdef __cplusplus +} +#endif + +#endif /* __SYSTEM_H */ diff --git a/litex/soc/software/bios/boot-helper-rocket.S b/litex/soc/cores/cpu/rocket/boot-helper.S similarity index 100% rename from litex/soc/software/bios/boot-helper-rocket.S rename to litex/soc/cores/cpu/rocket/boot-helper.S diff --git a/litex/soc/cores/cpu/rocket/core.py b/litex/soc/cores/cpu/rocket/core.py index 80d300fea..f08019fff 100644 --- a/litex/soc/cores/cpu/rocket/core.py +++ b/litex/soc/cores/cpu/rocket/core.py @@ -36,7 +36,7 @@ from migen import * from litex import get_data_mod from litex.soc.interconnect import axi from litex.soc.interconnect import wishbone -from litex.soc.cores.cpu import CPU +from litex.soc.cores.cpu import CPU, CPU_GCC_TRIPLE_RISCV64 CPU_VARIANTS = { @@ -66,11 +66,12 @@ AXI_DATA_WIDTHS = { class RocketRV64(CPU): name = "rocket" + human_name = "RocketRV64[imac]" data_width = 64 endianness = "little" - gcc_triple = ("riscv64-unknown-elf", "riscv64-linux", "riscv-sifive-elf", - "riscv64-none-elf") + gcc_triple = CPU_GCC_TRIPLE_RISCV64 linker_output_format = "elf64-littleriscv" + nop = "nop" io_regions = {0x10000000: 0x70000000} # origin, length @property diff --git a/litex/soc/software/libbase/crt0-rocket.S b/litex/soc/cores/cpu/rocket/crt0.S similarity index 100% rename from litex/soc/software/libbase/crt0-rocket.S rename to litex/soc/cores/cpu/rocket/crt0.S diff --git a/litex/soc/cores/cpu/rocket/csr-defs.h b/litex/soc/cores/cpu/rocket/csr-defs.h new file mode 100644 index 000000000..170bd4540 --- /dev/null +++ b/litex/soc/cores/cpu/rocket/csr-defs.h @@ -0,0 +1,8 @@ +#ifndef CSR_DEFS__H +#define CSR_DEFS__H + +#define CSR_MSTATUS_MIE 0x8 + +#define CSR_DCACHE_INFO 0xCC0 + +#endif /* CSR_DEFS__H */ diff --git a/litex/soc/cores/cpu/rocket/irq.h b/litex/soc/cores/cpu/rocket/irq.h new file mode 100644 index 000000000..9548b01fd --- /dev/null +++ b/litex/soc/cores/cpu/rocket/irq.h @@ -0,0 +1,50 @@ +#ifndef __IRQ_H +#define __IRQ_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +// The RocketChip uses a Platform-Level Interrupt Controller (PLIC) which +// is programmed and queried via a set of MMIO registers. + +#define PLIC_BASE 0x0c000000L // Base address and per-pin priority array +#define PLIC_PENDING 0x0c001000L // Bit field matching currently pending pins +#define PLIC_ENABLED 0x0c002000L // Bit field corresponding to the current mask +#define PLIC_THRSHLD 0x0c200000L // Per-pin priority must be >= this to trigger +#define PLIC_CLAIM 0x0c200004L // Claim & completion register address + +static inline unsigned int irq_getie(void) +{ + return (csrr(mstatus) & CSR_MSTATUS_MIE) != 0; +} + +static inline void irq_setie(unsigned int ie) +{ + if(ie) csrs(mstatus,CSR_MSTATUS_MIE); else csrc(mstatus,CSR_MSTATUS_MIE); +} + +static inline unsigned int irq_getmask(void) +{ + return *((unsigned int *)PLIC_ENABLED) >> 1; +} + +static inline void irq_setmask(unsigned int mask) +{ + *((unsigned int *)PLIC_ENABLED) = mask << 1; +} + +static inline unsigned int irq_pending(void) +{ + return *((unsigned int *)PLIC_PENDING) >> 1; +} + +#ifdef __cplusplus +} +#endif + +#endif /* __IRQ_H */ diff --git a/litex/soc/software/include/base/system.h b/litex/soc/cores/cpu/rocket/system.h similarity index 65% rename from litex/soc/software/include/base/system.h rename to litex/soc/cores/cpu/rocket/system.h index ef3bf45b0..d3e98e1db 100644 --- a/litex/soc/software/include/base/system.h +++ b/litex/soc/cores/cpu/rocket/system.h @@ -5,31 +5,14 @@ extern "C" { #endif -void flush_cpu_icache(void); -void flush_cpu_dcache(void); +__attribute__((unused)) static void flush_cpu_icache(void){} /* FIXME: do something useful here! */ +__attribute__((unused)) static void flush_cpu_dcache(void){}; /* FIXME: do something useful here! */ void flush_l2_cache(void); void busy_wait(unsigned int ms); -#ifdef __or1k__ -#include -static inline unsigned long mfspr(unsigned long add) -{ - unsigned long ret; - - __asm__ __volatile__ ("l.mfspr %0,%1,0" : "=r" (ret) : "r" (add)); - - return ret; -} - -static inline void mtspr(unsigned long add, unsigned long val) -{ - __asm__ __volatile__ ("l.mtspr %0,%1,0" : : "r" (add), "r" (val)); -} -#endif - -#if defined(__vexriscv__) || defined(__minerva__) || defined(__rocket__) || defined(__blackparrot__) #include + #define csrr(reg) ({ unsigned long __tmp; \ asm volatile ("csrr %0, " #reg : "=r"(__tmp)); \ __tmp; }) @@ -51,7 +34,6 @@ static inline void mtspr(unsigned long add, unsigned long val) asm volatile ("csrrc x0, " #reg ", %0" :: "i"(bit)); \ else \ asm volatile ("csrrc x0, " #reg ", %0" :: "r"(bit)); }) -#endif #ifdef __cplusplus } diff --git a/litex/soc/software/bios/boot-helper-serv.S b/litex/soc/cores/cpu/serv/boot-helper.S similarity index 100% rename from litex/soc/software/bios/boot-helper-serv.S rename to litex/soc/cores/cpu/serv/boot-helper.S diff --git a/litex/soc/cores/cpu/serv/core.py b/litex/soc/cores/cpu/serv/core.py index d99661d66..739b83b6b 100644 --- a/litex/soc/cores/cpu/serv/core.py +++ b/litex/soc/cores/cpu/serv/core.py @@ -8,7 +8,7 @@ from migen import * from litex import get_data_mod from litex.soc.interconnect import wishbone -from litex.soc.cores.cpu import CPU +from litex.soc.cores.cpu import CPU, CPU_GCC_TRIPLE_RISCV32 CPU_VARIANTS = ["standard"] @@ -16,11 +16,12 @@ CPU_VARIANTS = ["standard"] class SERV(CPU): name = "serv" + human_name = "SERV" data_width = 32 endianness = "little" - gcc_triple = ("riscv64-unknown-elf", "riscv32-unknown-elf", "riscv-none-embed", - "riscv64-linux", "riscv-sifive-elf", "riscv64-none-elf") + gcc_triple = CPU_GCC_TRIPLE_RISCV32 linker_output_format = "elf32-littleriscv" + nop = "nop" io_regions = {0x80000000: 0x80000000} # origin, length @property diff --git a/litex/soc/software/libbase/crt0-serv.S b/litex/soc/cores/cpu/serv/crt0.S similarity index 100% rename from litex/soc/software/libbase/crt0-serv.S rename to litex/soc/cores/cpu/serv/crt0.S diff --git a/litex/soc/cores/cpu/serv/irq.h b/litex/soc/cores/cpu/serv/irq.h new file mode 100644 index 000000000..7374cf506 --- /dev/null +++ b/litex/soc/cores/cpu/serv/irq.h @@ -0,0 +1,4 @@ +#ifndef __IRQ_H +#define __IRQ_H + +#endif /* __IRQ_H */ diff --git a/litex/soc/cores/cpu/serv/system.h b/litex/soc/cores/cpu/serv/system.h new file mode 100644 index 000000000..afa56d677 --- /dev/null +++ b/litex/soc/cores/cpu/serv/system.h @@ -0,0 +1,18 @@ +#ifndef __SYSTEM_H +#define __SYSTEM_H + +#ifdef __cplusplus +extern "C" { +#endif + +__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); + +#ifdef __cplusplus +} +#endif + +#endif /* __SYSTEM_H */ diff --git a/litex/soc/software/bios/boot-helper-vexriscv.S b/litex/soc/cores/cpu/vexriscv/boot-helper.S similarity index 100% rename from litex/soc/software/bios/boot-helper-vexriscv.S rename to litex/soc/cores/cpu/vexriscv/boot-helper.S diff --git a/litex/soc/cores/cpu/vexriscv/core.py b/litex/soc/cores/cpu/vexriscv/core.py index 8e27e5d3f..9b981506f 100644 --- a/litex/soc/cores/cpu/vexriscv/core.py +++ b/litex/soc/cores/cpu/vexriscv/core.py @@ -15,7 +15,7 @@ from migen import * from litex import get_data_mod from litex.soc.interconnect import wishbone from litex.soc.interconnect.csr import * -from litex.soc.cores.cpu import CPU +from litex.soc.cores.cpu import CPU, CPU_GCC_TRIPLE_RISCV32 CPU_VARIANTS = { @@ -25,6 +25,8 @@ CPU_VARIANTS = { "lite+debug": "VexRiscv_LiteDebug", "standard": "VexRiscv", "standard+debug": "VexRiscv_Debug", + "imac": "VexRiscv_IMAC", + "imac+debug": "VexRiscv_IMACDebug", "full": "VexRiscv_Full", "full+debug": "VexRiscv_FullDebug", "linux": "VexRiscv_Linux", @@ -47,6 +49,8 @@ GCC_FLAGS = { "lite+debug": "-march=rv32i -mabi=ilp32", "standard": "-march=rv32im -mabi=ilp32", "standard+debug": "-march=rv32im -mabi=ilp32", + "imac": "-march=rv32imac -mabi=ilp32", + "imac+debug": "-march=rv32imac -mabi=ilp32", "full": "-march=rv32im -mabi=ilp32", "full+debug": "-march=rv32im -mabi=ilp32", "linux": "-march=rv32ima -mabi=ilp32", @@ -76,11 +80,12 @@ class VexRiscvTimer(Module, AutoCSR): class VexRiscv(CPU, AutoCSR): name = "vexriscv" + human_name = "VexRiscv" data_width = 32 endianness = "little" - gcc_triple = ("riscv64-unknown-elf", "riscv32-unknown-elf", "riscv-none-embed", - "riscv64-linux", "riscv-sifive-elf", "riscv64-none-elf") + gcc_triple = CPU_GCC_TRIPLE_RISCV32 linker_output_format = "elf32-littleriscv" + nop = "nop" io_regions = {0x80000000: 0x80000000} # origin, length @property diff --git a/litex/soc/software/libbase/crt0-vexriscv.S b/litex/soc/cores/cpu/vexriscv/crt0.S similarity index 100% rename from litex/soc/software/libbase/crt0-vexriscv.S rename to litex/soc/cores/cpu/vexriscv/crt0.S diff --git a/litex/soc/cores/cpu/vexriscv/csr-defs.h b/litex/soc/cores/cpu/vexriscv/csr-defs.h new file mode 100644 index 000000000..d98e8dfb7 --- /dev/null +++ b/litex/soc/cores/cpu/vexriscv/csr-defs.h @@ -0,0 +1,11 @@ +#ifndef CSR_DEFS__H +#define CSR_DEFS__H + +#define CSR_MSTATUS_MIE 0x8 + +#define CSR_IRQ_MASK 0xBC0 +#define CSR_IRQ_PENDING 0xFC0 + +#define CSR_DCACHE_INFO 0xCC0 + +#endif /* CSR_DEFS__H */ diff --git a/litex/soc/cores/cpu/vexriscv/irq.h b/litex/soc/cores/cpu/vexriscv/irq.h new file mode 100644 index 000000000..69bac122d --- /dev/null +++ b/litex/soc/cores/cpu/vexriscv/irq.h @@ -0,0 +1,45 @@ +#ifndef __IRQ_H +#define __IRQ_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +static inline unsigned int irq_getie(void) +{ + return (csrr(mstatus) & CSR_MSTATUS_MIE) != 0; +} + +static inline void irq_setie(unsigned int ie) +{ + if(ie) csrs(mstatus,CSR_MSTATUS_MIE); else csrc(mstatus,CSR_MSTATUS_MIE); +} + +static inline unsigned int irq_getmask(void) +{ + unsigned int mask; + asm volatile ("csrr %0, %1" : "=r"(mask) : "i"(CSR_IRQ_MASK)); + return mask; +} + +static inline void irq_setmask(unsigned int mask) +{ + asm volatile ("csrw %0, %1" :: "i"(CSR_IRQ_MASK), "r"(mask)); +} + +static inline unsigned int irq_pending(void) +{ + unsigned int pending; + asm volatile ("csrr %0, %1" : "=r"(pending) : "i"(CSR_IRQ_PENDING)); + return pending; +} + +#ifdef __cplusplus +} +#endif + +#endif /* __IRQ_H */ diff --git a/litex/soc/cores/cpu/vexriscv/system.h b/litex/soc/cores/cpu/vexriscv/system.h new file mode 100644 index 000000000..a8fbe42bb --- /dev/null +++ b/litex/soc/cores/cpu/vexriscv/system.h @@ -0,0 +1,65 @@ +#ifndef __SYSTEM_H +#define __SYSTEM_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +__attribute__((unused)) static void flush_cpu_icache(void) +{ + asm volatile( + ".word(0x100F)\n" + "nop\n" + "nop\n" + "nop\n" + "nop\n" + "nop\n" + ); +} + +__attribute__((unused)) static void flush_cpu_dcache(void) +{ + unsigned long cache_info; + asm volatile ("csrr %0, %1" : "=r"(cache_info) : "i"(CSR_DCACHE_INFO)); + unsigned long cache_way_size = cache_info & 0xFFFFF; + unsigned long cache_line_size = (cache_info >> 20) & 0xFFF; + for(register unsigned long idx = 0;idx < cache_way_size;idx += cache_line_size){ + asm volatile("mv x10, %0 \n .word(0b01110000000001010101000000001111)"::"r"(idx)); + } +} + +void flush_l2_cache(void); + +void busy_wait(unsigned int ms); + +#include + +#define csrr(reg) ({ unsigned long __tmp; \ + asm volatile ("csrr %0, " #reg : "=r"(__tmp)); \ + __tmp; }) + +#define csrw(reg, val) ({ \ + if (__builtin_constant_p(val) && (unsigned long)(val) < 32) \ + asm volatile ("csrw " #reg ", %0" :: "i"(val)); \ + else \ + asm volatile ("csrw " #reg ", %0" :: "r"(val)); }) + +#define csrs(reg, bit) ({ \ + if (__builtin_constant_p(bit) && (unsigned long)(bit) < 32) \ + asm volatile ("csrrs x0, " #reg ", %0" :: "i"(bit)); \ + else \ + asm volatile ("csrrs x0, " #reg ", %0" :: "r"(bit)); }) + +#define csrc(reg, bit) ({ \ + if (__builtin_constant_p(bit) && (unsigned long)(bit) < 32) \ + asm volatile ("csrrc x0, " #reg ", %0" :: "i"(bit)); \ + else \ + asm volatile ("csrrc x0, " #reg ", %0" :: "r"(bit)); }) + +#ifdef __cplusplus +} +#endif + +#endif /* __SYSTEM_H */ diff --git a/litex/soc/cores/led.py b/litex/soc/cores/led.py new file mode 100644 index 000000000..54c1d2a08 --- /dev/null +++ b/litex/soc/cores/led.py @@ -0,0 +1,34 @@ +# This file is Copyright (c) 2020 Florent Kermarrec +# License: BSD + +from migen import * +from migen.genlib.misc import WaitTimer + +from litex.soc.interconnect.csr import * + +# Led Chaser --------------------------------------------------------------------------------------- + +_CHASER_MODE = 0 +_CONTROL_MODE = 1 + +class LedChaser(Module, AutoCSR): + def __init__(self, pads, sys_clk_freq, period=1e0): + self._out = CSRStorage(len(pads), description="Led Output(s) Control.") + + # # # + + n = len(pads) + chaser = Signal(n) + mode = Signal(reset=_CHASER_MODE) + timer = WaitTimer(int(period*sys_clk_freq/(2*n))) + self.submodules += timer + self.comb += timer.wait.eq(~timer.done) + self.sync += If(timer.done, chaser.eq(Cat(~chaser[-1], chaser))) + self.sync += If(self._out.re, mode.eq(_CONTROL_MODE)) + self.comb += [ + If(mode == _CONTROL_MODE, + pads.eq(self._out.storage) + ).Else( + pads.eq(chaser) + ) + ] diff --git a/litex/soc/cores/uart.py b/litex/soc/cores/uart.py index e6315016d..07fdac305 100644 --- a/litex/soc/cores/uart.py +++ b/litex/soc/cores/uart.py @@ -239,11 +239,13 @@ class UART(Module, AutoCSR, UARTInterface): self.ev.rx.trigger.eq(~rx_fifo.source.valid) ] -class UARTWishboneBridge(WishboneStreamingBridge): +class UARTBone(WishboneStreamingBridge): def __init__(self, pads, clk_freq, baudrate=115200): self.submodules.phy = RS232PHY(pads, clk_freq, baudrate) WishboneStreamingBridge.__init__(self, self.phy, clk_freq) +class UARTWishboneBridge(UARTBone): pass + # UART Multiplexer --------------------------------------------------------------------------------- class UARTMultiplexer(Module): diff --git a/litex/soc/integration/builder.py b/litex/soc/integration/builder.py index 745eb75e9..4fd1b2330 100644 --- a/litex/soc/integration/builder.py +++ b/litex/soc/integration/builder.py @@ -49,7 +49,8 @@ class Builder: csr_json = None, csr_csv = None, csr_svd = None, - memory_x = None): + memory_x = None, + bios_options = None): self.soc = soc # From Python doc: makedirs() will become confused if the path @@ -66,6 +67,7 @@ class Builder: self.csr_json = csr_json self.csr_svd = csr_svd self.memory_x = memory_x + self.bios_options = bios_options self.software_packages = [] for name in soc_software_packages: @@ -110,6 +112,10 @@ class Builder: for name, src_dir in self.software_packages: define(name.upper() + "_DIRECTORY", src_dir) + if self.bios_options is not None: + for option in self.bios_options: + define(option, "1") + write_to_file( os.path.join(self.generated_dir, "variables.mak"), "".join(variables_contents)) diff --git a/litex/soc/integration/export.py b/litex/soc/integration/export.py index 2761443a5..9117d82e3 100644 --- a/litex/soc/integration/export.py +++ b/litex/soc/integration/export.py @@ -15,6 +15,7 @@ import os import json +import inspect from shutil import which from sysconfig import get_platform @@ -85,7 +86,8 @@ def get_cpu_mak(cpu, compile_software): ("CPU", cpu.name), ("CPUFLAGS", flags), ("CPUENDIANNESS", cpu.endianness), - ("CLANG", str(int(clang))) + ("CLANG", str(int(clang))), + ("CPU_DIRECTORY", os.path.dirname(inspect.getfile(cpu.__class__))), ] diff --git a/litex/soc/integration/soc.py b/litex/soc/integration/soc.py index 11e8dd2b2..c6cc1e0f8 100644 --- a/litex/soc/integration/soc.py +++ b/litex/soc/integration/soc.py @@ -282,7 +282,8 @@ class SoCBusHandler(Module): return is_io # Add Master/Slave ----------------------------------------------------------------------------- - def add_adapter(self, name, interface): + def add_adapter(self, name, interface, direction="m2s"): + assert direction in ["m2s", "s2m"] if interface.data_width != self.data_width: self.logger.info("{} Bus {} from {}-bit to {}-bit.".format( colorer(name), @@ -290,7 +291,11 @@ class SoCBusHandler(Module): colorer(interface.data_width), colorer(self.data_width))) new_interface = wishbone.Interface(data_width=self.data_width) - self.submodules += wishbone.Converter(interface, new_interface) + if direction == "m2s": + converter = wishbone.Converter(master=interface, slave=new_interface) + if direction == "s2m": + converter = wishbone.Converter(master=new_interface, slave=interface) + self.submodules += converter return new_interface else: return interface @@ -304,7 +309,7 @@ class SoCBusHandler(Module): colorer("already declared", color="red"))) self.logger.error(self) raise - master = self.add_adapter(name, master) + master = self.add_adapter(name, master, "m2s") self.masters[name] = master self.logger.info("{} {} as Bus Master.".format( colorer(name, color="underline"), @@ -336,7 +341,7 @@ class SoCBusHandler(Module): colorer("already declared", color="red"))) self.logger.error(self) raise - slave = self.add_adapter(name, slave) + slave = self.add_adapter(name, slave, "s2m") self.slaves[name] = slave self.logger.info("{} {} as Bus Slave.".format( colorer(name, color="underline"), @@ -762,7 +767,7 @@ class SoC(Module): self.add_config("CSR_DATA_WIDTH", self.csr.data_width) self.add_config("CSR_ALIGNMENT", self.csr.alignment) - def add_cpu(self, name="vexriscv", variant="standard", reset_address=None): + def add_cpu(self, name="vexriscv", variant="standard", cls=None, reset_address=None): if name not in cpu.CPUS.keys(): self.logger.error("{} CPU {}, supporteds: {}".format( colorer(name), @@ -770,7 +775,8 @@ class SoC(Module): colorer(", ".join(cpu.CPUS.keys())))) raise # Add CPU - self.submodules.cpu = cpu.CPUS[name](self.platform, variant) + cpu_cls = cls if cls is not None else cpu.CPUS[name] + self.submodules.cpu = cpu_cls(self.platform, variant) # Update SoC with CPU constraints for n, (origin, size) in enumerate(self.cpu.io_regions.items()): self.bus.add_region("io{}".format(n), SoCIORegion(origin=origin, size=size, cached=False)) @@ -794,6 +800,9 @@ class SoC(Module): # Add constants self.add_config("CPU_TYPE", str(name)) self.add_config("CPU_VARIANT", str(variant.split('+')[0])) + self.add_constant("CONFIG_CPU_HUMAN_NAME", getattr(self.cpu, "human_name", "Unknown")) + if hasattr(self.cpu, "nop"): + self.add_constant("CONFIG_CPU_NOP", self.cpu.nop) def add_timer(self, name="timer0"): self.check_if_exists(name) @@ -922,13 +931,9 @@ class LiteXSoC(SoC): if name == "stub": self.comb += self.uart.sink.ready.eq(1) - # Bridge - elif name in ["bridge"]: - self.submodules.uart = uart.UARTWishboneBridge( - pads = self.platform.request("serial"), - clk_freq = self.sys_clk_freq, - baudrate = baudrate) - self.bus.add_master(name="uart_bridge", master=self.uart.wishbone) + # UARTBone / Bridge + elif name in ["uartbone", "bridge"]: + self.add_uartbone(baudrate=baudrate) # Crossover elif name in ["crossover"]: @@ -957,8 +962,8 @@ class LiteXSoC(SoC): tx_fifo_depth = fifo_depth, rx_fifo_depth = fifo_depth)) - # USB CDC (with ValentyUSB core) - elif name in ["usb_cdc"]: + # USB ACM (with ValentyUSB core) + elif name in ["usb_acm"]: import valentyusb.usbcore.io as usbio import valentyusb.usbcore.cpu.cdc_eptri as cdc_eptri usb_pads = self.platform.request("usb") @@ -982,6 +987,15 @@ class LiteXSoC(SoC): else: self.add_constant("UART_POLLING") + # Add UARTbone --------------------------------------------------------------------------------- + def add_uartbone(self, name="serial", baudrate=115200): + from litex.soc.cores import uart + self.submodules.uartbone = uart.UARTBone( + pads = self.platform.request(name), + clk_freq = self.sys_clk_freq, + baudrate = baudrate) + self.bus.add_master(name="uartbone", master=self.uartbone.wishbone) + # Add SDRAM ------------------------------------------------------------------------------------ def add_sdram(self, name, phy, module, origin, size=None, l2_cache_size = 8192, @@ -1129,7 +1143,7 @@ class LiteXSoC(SoC): eth_tx_clk) # Add Etherbone -------------------------------------------------------------------------------- - def add_etherbone(self, name="etherbone", phy=None, + def add_etherbone(self, name="etherbone", phy=None, clock_domain=None, mac_address = 0x10e2d5000000, ip_address = "192.168.1.50", udp_port = 1234): @@ -1142,9 +1156,21 @@ class LiteXSoC(SoC): mac_address = mac_address, ip_address = ip_address, clk_freq = self.clk_freq) + if clock_domain is not None: # FIXME: Could probably be avoided. + ethcore = ClockDomainsRenamer("eth_tx")(ethcore) self.submodules += ethcore + + # Clock domain renaming + if clock_domain is not None: # FIXME: Could probably be avoided. + self.clock_domains.cd_etherbone = ClockDomain("etherbone") + self.comb += self.cd_etherbone.clk.eq(ClockSignal(clock_domain)) + self.comb += self.cd_etherbone.rst.eq(ResetSignal(clock_domain)) + clock_domain = "etherbone" + else: + clock_domain = "sys" + # Etherbone - etherbone = LiteEthEtherbone(ethcore.udp, udp_port) + etherbone = LiteEthEtherbone(ethcore.udp, udp_port, cd=clock_domain) setattr(self.submodules, name, etherbone) self.add_wb_master(etherbone.wishbone.bus) # Timing constraints diff --git a/litex/soc/integration/soc_core.py b/litex/soc/integration/soc_core.py index 3eb0016c7..f61555a31 100644 --- a/litex/soc/integration/soc_core.py +++ b/litex/soc/integration/soc_core.py @@ -65,6 +65,7 @@ class SoCCore(LiteXSoC): cpu_type = "vexriscv", cpu_reset_address = None, cpu_variant = None, + cpu_cls = None, # ROM parameters integrated_rom_size = 0, integrated_rom_init = [], @@ -131,6 +132,7 @@ class SoCCore(LiteXSoC): self.cpu_type = cpu_type self.cpu_variant = cpu_variant + self.cpu_cls = cpu_cls self.integrated_rom_size = integrated_rom_size self.integrated_rom_initialized = integrated_rom_init != [] @@ -154,6 +156,7 @@ class SoCCore(LiteXSoC): self.add_cpu( name = str(cpu_type), variant = "standard" if cpu_variant is None else cpu_variant, + cls = cpu_cls, reset_address = None if integrated_rom_size else cpu_reset_address) # Add User's interrupts diff --git a/litex/soc/integration/soc_zynq.py b/litex/soc/integration/soc_zynq.py index 3bcc86b90..b65c2f770 100644 --- a/litex/soc/integration/soc_zynq.py +++ b/litex/soc/integration/soc_zynq.py @@ -7,7 +7,7 @@ from migen import * from litex.build.generic_platform import tools from litex.soc.integration.soc_core import * -from litex.soc.integration.cpu_interface import get_csr_header +from litex.soc.integration.export import get_csr_header from litex.soc.interconnect import wishbone from litex.soc.interconnect import axi diff --git a/litex/soc/interconnect/wishbonebridge.py b/litex/soc/interconnect/wishbonebridge.py index 3f5fc89f5..00ec4a0ce 100644 --- a/litex/soc/interconnect/wishbonebridge.py +++ b/litex/soc/interconnect/wishbonebridge.py @@ -67,7 +67,7 @@ class WishboneStreamingBridge(Module): ] fsm = ResetInserter()(FSM(reset_state="IDLE")) - timer = WaitTimer(clk_freq//10) + timer = WaitTimer(int(clk_freq//10)) self.submodules += fsm, timer self.comb += [ fsm.reset.eq(timer.done), diff --git a/litex/soc/software/bios/Makefile b/litex/soc/software/bios/Makefile index 12510a712..9fba33a62 100755 --- a/litex/soc/software/bios/Makefile +++ b/litex/soc/software/bios/Makefile @@ -2,7 +2,7 @@ include ../include/generated/variables.mak include $(SOC_DIRECTORY)/software/common.mak ifeq ($(CPU),blackparrot) -BP_LIBS = -L$(BP_EXTERNAL_DIR)/lib/gcc/riscv64-unknown-elf/8.3.0 +BP_LIBS = -L$(BP_LITEX_SOFTWARE) BP_FLAGS = -lgcc endif # Permit TFTP_SERVER_PORT override from shell environment / command line @@ -10,7 +10,37 @@ ifdef TFTP_SERVER_PORT CFLAGS += -DTFTP_SERVER_PORT=$(TFTP_SERVER_PORT) endif -OBJECTS=isr.o sdram.o sdcard.o main.o boot-helper-$(CPU).o boot.o +OBJECTS = isr.o \ + sdram.o \ + sdcard.o \ + main.o \ + boot-helper.o \ + boot.o \ + helpers.o \ + cmd_bios.o \ + cmd_boot.o \ + cmd_dram.o \ + cmd_mdio.o \ + cmd_mem_access.o \ + cmd_sdcard.o \ + cmd_spi_flash.o \ + +ifneq "$(or $(TERM_NO_COMPLETE),$(TERM_MINI))" "" +CFLAGS += -DTERM_NO_COMPLETE +else +OBJECTS += complete.o +endif + +ifdef TERM_NO_HIST +CFLAGS += -DTERM_NO_HIST +endif + +ifdef TERM_MINI +CFLAGS += -DTERM_MINI +OBJECTS += readline_simple.o +else +OBJECTS += readline.o +endif all: bios.bin $(PYTHON) -m litex.soc.software.memusage bios.elf $(CURDIR)/../include/generated/regions.ld $(TRIPLE) @@ -29,9 +59,9 @@ endif bios.elf: $(BIOS_DIRECTORY)/linker.ld $(OBJECTS) -%.elf: ../libbase/crt0-$(CPU)-ctr.o ../libnet/libnet.a ../libbase/libbase-nofloat.a ../libcompiler_rt/libcompiler_rt.a +%.elf: ../libbase/crt0-ctr.o ../libnet/libnet.a ../libbase/libbase-nofloat.a ../libcompiler_rt/libcompiler_rt.a $(LD) $(LDFLAGS) -T $(BIOS_DIRECTORY)/linker.ld -N -o $@ \ - ../libbase/crt0-$(CPU)-ctr.o \ + ../libbase/crt0-ctr.o \ $(OBJECTS) \ -L../libnet \ -L../libbase \ @@ -39,7 +69,7 @@ bios.elf: $(BIOS_DIRECTORY)/linker.ld $(OBJECTS) $(BP_LIBS) \ -lnet -lbase-nofloat -lcompiler_rt \ $(BP_FLAGS) - + ifneq ($(OS),Windows_NT) chmod -x $@ endif @@ -50,9 +80,15 @@ endif %.o: $(BIOS_DIRECTORY)/%.c $(compile) +%.o: $(BIOS_DIRECTORY)/commands/%.c + $(compile) + %.o: $(BIOS_DIRECTORY)/%.S $(assemble) +boot-helper.o: $(CPU_DIRECTORY)/boot-helper.S + $(assemble) + clean: $(RM) $(OBJECTS) bios.elf bios.bin .*~ *~ diff --git a/litex/soc/software/bios/boot.c b/litex/soc/software/bios/boot.c index 08b3be4a8..8f53fcca3 100644 --- a/litex/soc/software/bios/boot.c +++ b/litex/soc/software/bios/boot.c @@ -43,10 +43,7 @@ static void __attribute__((noreturn)) boot(unsigned long r1, unsigned long r2, u irq_setmask(0); irq_setie(0); #endif -/* FIXME: understand why flushing icache on Vexriscv make boot fail */ -#ifndef __vexriscv__ flush_cpu_icache(); -#endif flush_cpu_dcache(); #ifdef CONFIG_L2_SIZE flush_l2_cache(); diff --git a/litex/soc/software/bios/command.h b/litex/soc/software/bios/command.h new file mode 100644 index 000000000..693d79825 --- /dev/null +++ b/litex/soc/software/bios/command.h @@ -0,0 +1,49 @@ +// This file is Copyright (c) 2020 Franck Jullien + +// SPDX-License-Identifier: BSD-Source-Code + +#ifndef __COMMAND_H__ +#define __COMMAND_H__ + +#define MAX_PARAM 8 + +#define HIST_DEPTH 10 /* Used in string list, complete.c */ + +#define MISC_CMDS 0 +#define SYSTEM_CMDS 1 +#define CACHE_CMDS 2 +#define BOOT_CMDS 3 +#define DRAM_CMDS 4 +#define MDIO_CMDS 5 +#define MEM_CMDS 6 +#define SD_CMDS 7 +#define SPIFLASH_CMDS 8 +#define DDR_CMDS 9 +#define NB_OF_GROUPS 10 + +typedef void (*cmd_handler)(int nb_params, char **params); + +struct command_struct { + void (*func)(int nb_params, char **params); + const char *name; + const char *help; + int group; +}; + +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 + + +struct command_struct *command_dispatcher(char *command, int nb_params, char **params); + +#endif diff --git a/litex/soc/software/bios/commands/cmd_bios.c b/litex/soc/software/bios/commands/cmd_bios.c new file mode 100644 index 000000000..a5e704248 --- /dev/null +++ b/litex/soc/software/bios/commands/cmd_bios.c @@ -0,0 +1,125 @@ +// SPDX-License-Identifier: BSD-Source-Code + +#include +#include + +#include +#include +#include +#include + +#include "../command.h" +#include "../helpers.h" + +/** + * Command "help" + * + * Print a list of available commands with their help text + * + */ +static void help_handler(int nb_params, char **params) +{ + struct command_struct * const *cmd; + int i, not_empty; + + puts("\nLiteX BIOS, available commands:\n"); + + for (i = 0; i < NB_OF_GROUPS; i++) { + not_empty = 0; + for (cmd = __bios_cmd_start; cmd != __bios_cmd_end; cmd++) { + if ((*cmd)->group == i) { + printf("%-16s - %s\n", (*cmd)->name, (*cmd)->help ? (*cmd)->help : "-"); + not_empty = 1; + } + } + if (not_empty) + printf("\n"); + } +} + +define_command(help, help_handler, "Print this help", MISC_CMDS); + +/** + * Command "ident" + * + * Print SoC identyifier if available + * + */ +static void ident_helper(int nb_params, char **params) +{ + char buffer[IDENT_SIZE]; + + get_ident(buffer); + printf("Ident: %s", *buffer ? buffer : "-"); +} + +define_command(ident, ident_helper, "Display identifier", SYSTEM_CMDS); + +/** + * Command "reboot" + * + * Reboot the system + * + */ +#ifdef CSR_CTRL_BASE +static void reboot(int nb_params, char **params) +{ + ctrl_reset_write(1); +} + +define_command(reboot, reboot, "Reset processor", SYSTEM_CMDS); +#endif + +/** + * Command "crc" + * + * Compute CRC32 over an address range + * + */ +static void crc(int nb_params, char **params) +{ + char *c; + unsigned int addr; + unsigned int length; + + if (nb_params < 2) { + printf("crc
"); + return; + } + + addr = strtoul(params[0], &c, 0); + if (*c != 0) { + printf("Incorrect address"); + return; + } + + length = strtoul(params[1], &c, 0); + if (*c != 0) { + printf("Incorrect length"); + return; + } + + printf("CRC32: %08x", crc32((unsigned char *)addr, length)); +} + +define_command(crc, crc, "Compute CRC32 of a part of the address space", MISC_CMDS); + +/** + * Command "flush_cpu_dcache" + * + * Flush CPU data cache + * + */ + +define_command(flush_cpu_dcache, flush_cpu_dcache, "Flush CPU data cache", CACHE_CMDS); + +/** + * Command "flush_l2_cache" + * + * Flush L2 cache + * + */ +#ifdef CONFIG_L2_SIZE +define_command(flush_l2_cache, flush_l2_cache, "Flush L2 cache", CACHE_CMDS); +#endif + diff --git a/litex/soc/software/bios/commands/cmd_boot.c b/litex/soc/software/bios/commands/cmd_boot.c new file mode 100644 index 000000000..c9cb8a11d --- /dev/null +++ b/litex/soc/software/bios/commands/cmd_boot.c @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: BSD-Source-Code + +#include +#include + +#include + +#include "../command.h" +#include "../helpers.h" +#include "../boot.h" + +/** + * Command "flashboot" + * + * Boot software from flash + * + */ +#ifdef FLASH_BOOT_ADDRESS +define_command(flashboot, flashboot, "Boot from flash", BOOT_CMDS); +#endif + +/** + * Command "romboot" + * + * Boot software from embedded rom + * + */ +#ifdef ROM_BOOT_ADDRESS +define_command(romboot, romboot, "Boot from embedded rom", BOOT_CMDS); +#endif + +/** + * Command "serialboot" + * + * Boot software from serial interface + * + */ +define_command(serialboot, serialboot, "Boot via SFL", BOOT_CMDS); + +/** + * Command "netboot" + * + * Boot software from TFTP server + * + */ +#ifdef CSR_ETHMAC_BASE +define_command(netboot, netboot, "Boot via TFTP", BOOT_CMDS); +#endif + +/** + * Command "spisdcardboot" + * + * Boot software from SDcard + * + */ +#ifdef CSR_SPISDCARD_BASE +define_command(spisdcardboot, spisdcardboot, "Boot from SDCard via SPI hardware bitbang", BOOT_CMDS); +#endif + diff --git a/litex/soc/software/bios/commands/cmd_dram.c b/litex/soc/software/bios/commands/cmd_dram.c new file mode 100644 index 000000000..0d6fa1d46 --- /dev/null +++ b/litex/soc/software/bios/commands/cmd_dram.c @@ -0,0 +1,222 @@ +// SPDX-License-Identifier: BSD-Source-Code + +#include +#include + +#include + +#include "../command.h" +#include "../helpers.h" +#include "../sdram.h" + +/** + * Command "sdrrow" + * + * Precharge/Activate row + * + */ +#ifdef CSR_SDRAM_BASE +static void sdrrow_handler(int nb_params, char **params) +{ + char *c; + unsigned int row; + + if (nb_params < 1) { + sdrrow(0); + printf("Precharged"); + } + + row = strtoul(params[0], &c, 0); + if (*c != 0) { + printf("Incorrect row"); + return; + } + + sdrrow(row); + printf("Activated row %d", row); +} +define_command(sdrrow, sdrrow_handler, "Precharge/Activate row", DRAM_CMDS); +#endif + +/** + * Command "sdrsw" + * + * Gives SDRAM control to SW + * + */ +#ifdef CSR_SDRAM_BASE +define_command(sdrsw, sdrsw, "Gives SDRAM control to SW", DRAM_CMDS); +#endif + +/** + * Command "sdrhw" + * + * Gives SDRAM control to HW + * + */ +#ifdef CSR_SDRAM_BASE +define_command(sdrhw, sdrhw, "Gives SDRAM control to HW", DRAM_CMDS); +#endif + +/** + * Command "sdrrdbuf" + * + * Dump SDRAM read buffer + * + */ +#ifdef CSR_SDRAM_BASE +static void sdrrdbuf_handler(int nb_params, char **params) +{ + sdrrdbuf(-1); +} + +define_command(sdrrdbuf, sdrrdbuf_handler, "Dump SDRAM read buffer", DRAM_CMDS); +#endif + +/** + * Command "sdrrd" + * + * Read SDRAM data + * + */ +#ifdef CSR_SDRAM_BASE +static void sdrrd_handler(int nb_params, char **params) +{ + unsigned int addr; + int dq; + char *c; + + if (nb_params < 1) { + printf("sdrrd
"); + return; + } + + addr = strtoul(params[0], &c, 0); + if (*c != 0) { + printf("Incorrect address"); + return; + } + + if (nb_params < 2) + dq = -1; + else { + dq = strtoul(params[1], &c, 0); + if (*c != 0) { + printf("Incorrect DQ"); + return; + } + } + + sdrrd(addr, dq); +} + +define_command(sdrrd, sdrrd_handler, "Read SDRAM data", DRAM_CMDS); +#endif + +/** + * Command "sdrrderr" + * + * Print SDRAM read errors + * + */ +#ifdef CSR_SDRAM_BASE +static void sdrrderr_handler(int nb_params, char **params) +{ + int count; + char *c; + + if (nb_params < 1) { + printf("sdrrderr "); + return; + } + + count = strtoul(params[0], &c, 0); + if (*c != 0) { + printf("Incorrect count"); + return; + } + + sdrrderr(count); +} + +define_command(sdrrderr, sdrrderr_handler, "Print SDRAM read errors", DRAM_CMDS); +#endif + +/** + * Command "sdrwr" + * + * Write SDRAM test data + * + */ +#ifdef CSR_SDRAM_BASE +static void sdrwr_handler(int nb_params, char **params) +{ + unsigned int addr; + char *c; + + if (nb_params < 1) { + printf("sdrwr
"); + return; + } + + addr = strtoul(params[0], &c, 0); + if (*c != 0) { + printf("Incorrect address"); + return; + } + + sdrwr(addr); +} + +define_command(sdrwr, sdrwr_handler, "Write SDRAM test data", DRAM_CMDS); +#endif + +/** + * Command "sdrinit" + * + * Start SDRAM initialisation + * + */ +#if defined(CSR_SDRAM_BASE) && defined(CSR_DDRPHY_BASE) +define_command(sdrinit, sdrinit, "Start SDRAM initialisation", DRAM_CMDS); +#endif + +/** + * Command "sdrwlon" + * + * Write leveling ON + * + */ +#if defined(CSR_DDRPHY_BASE) && defined(SDRAM_PHY_WRITE_LEVELING_CAPABLE) && defined(CSR_SDRAM_BASE) +define_command(sdrwlon, sdrwlon, "Enable write leveling", DRAM_CMDS); +#endif + +/** + * Command "sdrwloff" + * + * Write leveling OFF + * + */ +#if defined(CSR_DDRPHY_BASE) && defined(SDRAM_PHY_WRITE_LEVELING_CAPABLE) && defined(CSR_SDRAM_BASE) +define_command(sdrwloff, sdrwloff, "Disable write leveling", DRAM_CMDS); +#endif + +/** + * Command "sdrlevel" + * + * Perform read/write leveling + * + */ +#if defined(CSR_DDRPHY_BASE) && defined(CSR_SDRAM_BASE) +define_command(sdrlevel, sdrlevel, "Perform read/write leveling", DRAM_CMDS); +#endif + +/** + * Command "memtest" + * + * Run a memory test + * + */ +#ifdef CSR_SDRAM_BASE +define_command(memtest, memtest, "Run a memory test", DRAM_CMDS); +#endif diff --git a/litex/soc/software/bios/commands/cmd_mdio.c b/litex/soc/software/bios/commands/cmd_mdio.c new file mode 100644 index 000000000..35b020737 --- /dev/null +++ b/litex/soc/software/bios/commands/cmd_mdio.c @@ -0,0 +1,134 @@ +// SPDX-License-Identifier: BSD-Source-Code + +#include +#include + +#include + +#include + +#include "../command.h" +#include "../helpers.h" + +/** + * Command "mdiow" + * + * Write MDIO register + * + */ +#ifdef CSR_ETHPHY_MDIO_W_ADDR +static void mdiow(int nb_params, char **params) +{ + char *c; + unsigned int phyadr2; + unsigned int reg2; + unsigned int val2; + + if (nb_params < 3) { + printf("mdiow "); + return; + } + + phyadr2 = strtoul(params[0], &c, 0); + if (*c != 0) { + printf("Incorrect phyadr"); + return; + } + + reg2 = strtoul(params[1], &c, 0); + if (*c != 0) { + printf("Incorrect reg"); + return; + } + + val2 = strtoul(params[2], &c, 0); + if (*c != 0) { + printf("Incorrect val"); + return; + } + + mdio_write(phyadr2, reg2, val2); +} + +define_command(mdiow, mdiow, "Write MDIO register", MDIO_CMDS); +#endif + +/** + * Command "mdior" + * + * Read MDIO register + * + */ +#ifdef CSR_ETHPHY_MDIO_W_ADDR +static void mdior(int nb_params, char **params) +{ + char *c; + unsigned int phyadr2; + unsigned int reg2; + unsigned int val; + + if (nb_params < 2) { + printf("mdior "); + return; + } + + phyadr2 = strtoul(params[0], &c, 0); + if (*c != 0) { + printf("Incorrect phyadr"); + return; + } + + reg2 = strtoul(params[1], &c, 0); + if (*c != 0) { + printf("Incorrect reg"); + return; + } + + val = mdio_read(phyadr2, reg2); + printf("Reg %d: 0x%04x", reg2, val); +} + +define_command(mdior, mdior, "Read MDIO register", MDIO_CMDS); +#endif + +/** + * Command "mdiod" + * + * Dump MDIO registers + * + */ +#ifdef CSR_ETHPHY_MDIO_W_ADDR +static void mdiod(int nb_params, char **params) +{ + char *c; + unsigned int phyadr; + unsigned int count; + unsigned int val; + int i; + + if (nb_params < 2) { + printf("mdiod "); + return; + } + + phyadr = strtoul(params[0], &c, 0); + if (*c != 0) { + printf("Incorrect phyadr"); + return; + } + + count = strtoul(params[1], &c, 0); + if (*c != 0) { + printf("Incorrect count"); + return; + } + + printf("MDIO dump @0x%x:\n", phyadr); + for (i = 0; i < count; i++) { + val = mdio_read(phyadr, i); + printf("reg %d: 0x%04x", i, val); + } +} + +define_command(mdiod, mdiod, "Dump MDIO registers", MDIO_CMDS); +#endif diff --git a/litex/soc/software/bios/commands/cmd_mem_access.c b/litex/soc/software/bios/commands/cmd_mem_access.c new file mode 100644 index 000000000..8c63d4c44 --- /dev/null +++ b/litex/soc/software/bios/commands/cmd_mem_access.c @@ -0,0 +1,137 @@ +// SPDX-License-Identifier: BSD-Source-Code + +#include +#include + +#include "../command.h" +#include "../helpers.h" + +/** + * Command "mr" + * + * Memory read + * + */ +static void mr(int nb_params, char **params) +{ + char *c; + unsigned int *addr; + unsigned int length; + + if (nb_params < 1) { + printf("mr
[length]"); + return; + } + addr = (unsigned int *)strtoul(params[0], &c, 0); + if (*c != 0) { + printf("Incorrect address"); + return; + } + if (nb_params == 1) { + length = 4; + } else { + length = strtoul(params[1], &c, 0); + if(*c != 0) { + printf("\nIncorrect length"); + return; + } + } + + dump_bytes(addr, length, (unsigned long)addr); +} + +define_command(mr, mr, "Read address space", MEM_CMDS); + +/** + * Command "mw" + * + * Memory write + * + */ +static void mw(int nb_params, char **params) +{ + char *c; + unsigned int *addr; + unsigned int value; + unsigned int count; + unsigned int i; + + if (nb_params < 2) { + printf("mw
[count]"); + return; + } + + addr = (unsigned int *)strtoul(params[0], &c, 0); + if (*c != 0) { + printf("Incorrect address"); + return; + } + + value = strtoul(params[1], &c, 0); + if(*c != 0) { + printf("Incorrect value"); + return; + } + + if (nb_params == 2) { + count = 1; + } else { + count = strtoul(params[2], &c, 0); + if(*c != 0) { + printf("Incorrect count"); + return; + } + } + + for (i = 0; i < count; i++) + *addr++ = value; +} + +define_command(mw, mw, "Write address space", MEM_CMDS); + +/** + * Command "mc" + * + * Memory copy + * + */ +static void mc(int nb_params, char **params) +{ + char *c; + unsigned int *dstaddr; + unsigned int *srcaddr; + unsigned int count; + unsigned int i; + + if (nb_params < 2) { + printf("mc [count]"); + return; + } + + dstaddr = (unsigned int *)strtoul(params[0], &c, 0); + if (*c != 0) { + printf("Incorrect destination address"); + return; + } + + srcaddr = (unsigned int *)strtoul(params[1], &c, 0); + if (*c != 0) { + printf("Incorrect source address"); + return; + } + + if (nb_params == 2) { + count = 1; + } else { + count = strtoul(params[2], &c, 0); + if (*c != 0) { + printf("Incorrect count"); + return; + } + } + + for (i = 0; i < count; i++) + *dstaddr++ = *srcaddr++; +} + +define_command(mc, mc, "Copy address space", MEM_CMDS); diff --git a/litex/soc/software/bios/commands/cmd_sdcard.c b/litex/soc/software/bios/commands/cmd_sdcard.c new file mode 100644 index 000000000..96f9fe64c --- /dev/null +++ b/litex/soc/software/bios/commands/cmd_sdcard.c @@ -0,0 +1,85 @@ +// SPDX-License-Identifier: BSD-Source-Code + +#include +#include + +#include + +#include "../command.h" +#include "../helpers.h" +#include "../sdcard.h" + +/** + * Command "sdclk" + * + * Configure SDcard clock frequency + * + */ +#ifdef CSR_SDCORE_BASE +static void sdclk(int nb_params, char **params) +{ + unsigned int frequ; + char *c; + + if (nb_params < 1) { + printf("sdclk "); + return; + } + + frequ = strtoul(params[0], &c, 0); + if (*c != 0) { + printf("Incorrect frequency"); + return; + } + + sdclk_set_clk(frequ); +} + +struct command_struct cmd_sdclk = +{ + .func = sdclk, + .name = "sdclk", + .help = "SDCard set clk frequency (Mhz)", +}; + +define_command(sdclk, sdclk, "SDCard set clk frequency (Mhz)", SD_CMDS); +#endif + +/** + * Command "sdinit" + * + * Initialize SDcard + * + */ +#ifdef CSR_SDCORE_BASE +define_command(sdinit, sdinit, "SDCard initialization", SD_CMDS); +#endif + +/** + * Command "sdtest" + * + * Perform SDcard access tests + * + */ +#ifdef CSR_SDCORE_BASE +static void sdtest(int nb_params, char **params) +{ + unsigned int loops; + char *c; + + if (nb_params < 1) { + printf("sdtest "); + return; + } + + loops = strtoul(params[0], &c, 0); + if (*c != 0) { + printf("Incorrect number of loops"); + return; + } + + sdcard_test(loops); +} + +define_command(sdtest, sdtest, "SDCard test", SD_CMDS); +#endif diff --git a/litex/soc/software/bios/commands/cmd_spi_flash.c b/litex/soc/software/bios/commands/cmd_spi_flash.c new file mode 100644 index 000000000..e607a89df --- /dev/null +++ b/litex/soc/software/bios/commands/cmd_spi_flash.c @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: BSD-Source-Code + +#include +#include + +#include + +#include "../command.h" +#include "../helpers.h" + +/** + * Command "fw" + * + * Write data from a memory buffer to SPI flash + * + */ +#if (defined CSR_SPIFLASH_BASE && defined SPIFLASH_PAGE_SIZE) +static void fw(int nb_params, char **params) +{ + char *c; + unsigned int addr; + unsigned int value; + unsigned int count; + unsigned int i; + + if (nb_params < 2) { + printf("fw [count]"); + return; + } + + addr = strtoul(params[0], &c, 0); + if (*c != 0) { + printf("Incorrect offset"); + return; + } + + value = strtoul(params[1], &c, 0); + if (*c != 0) { + printf("Incorrect value"); + return; + } + + if (nb_params == 2) { + count = 1; + } else { + count = strtoul(count, &c, 0); + if (*c != 0) { + printf("Incorrect count"); + return; + } + } + + for (i = 0; i < count; i++) + write_to_flash(addr + i * 4, (unsigned char *)&value, 4); +} + +define_command(fw, fw, "Write to flash", SPIFLASH_CMDS); +#endif + +/** + * Command "fe" + * + * Flash erase + * + */ +#if (defined CSR_SPIFLASH_BASE && defined SPIFLASH_PAGE_SIZE) +static void fe(int nb_params, char **params) +{ + erase_flash(); + printf("Flash erased\n"); +} + +define_command(fe, fe, "Erase whole flash", SPIFLASH_CMDS); +#endif + diff --git a/litex/soc/software/bios/complete.c b/litex/soc/software/bios/complete.c new file mode 100644 index 000000000..e4283297f --- /dev/null +++ b/litex/soc/software/bios/complete.c @@ -0,0 +1,174 @@ +// This file is Copyright (c) 2020 Franck Jullien +// +// Largely inspired/copied from U-boot and Barebox projects wich are: +// Sascha Hauer, Pengutronix, + +// License: BSD + +#include +#include +#include + +#include "readline.h" +#include "helpers.h" +#include "command.h" +#include "complete.h" + +static int tab_pressed = 0; + +char sl[HIST_DEPTH][CMD_LINE_BUFFER_SIZE]; +int sl_idx = 0; + +char out[CMD_LINE_BUFFER_SIZE]; + +static void string_list_init(void) +{ + int i; + for (i = 0; i < HIST_DEPTH; i++) + sl[i][0] = 0; +} + +static int string_list_add(const char *string) +{ + int i; + for (i = 0; i < HIST_DEPTH; i++) { + if (sl[i][0] == 0) { + strncpy(&sl[i][0], string, CMD_LINE_BUFFER_SIZE); + return 0; + } + } + return -1; +} + +static int string_list_empty(void) +{ + int i; + for (i = 0; i < HIST_DEPTH; i++) + if (sl[i][0] != 0) + return 0; + return 1; +} + +static int string_list_count(void) +{ + int i, count = 0; + for (i = 0; i < HIST_DEPTH; i++) + if (sl[i][0] != 0) + count++; + return count; +} + +static char *list_first_entry(void) +{ + int i; + for (i = 0; i < HIST_DEPTH; i++) + if (sl[i][0] != 0) + return &sl[i][0]; + return NULL; +} + +static void string_list_print_by_column(void) +{ + int len = 0, num, i, j; + + for (i = 0; i < HIST_DEPTH; i++) { + if (sl[i][0] != 0) { + int l = strlen(&sl[i][0]) + 4; + if (l > len) + len = l; + } + } + + if (!len) + return; + + num = 80 / (len + 1); + + for (j = 0; j < HIST_DEPTH; j++) { + if (sl[j][0] != 0) { + if (!(++i % num)) + printf("%s\n", &sl[j][0]); + else + printf("%-*s", len, &sl[j][0]); + } + } + if (i % num) + printf("\n"); +} + +static void command_complete(char *instr) +{ + struct command_struct * const *cmd; + + for (cmd = __bios_cmd_start; cmd != __bios_cmd_end; cmd++) + if (!strncmp(instr, (*cmd)->name, strlen(instr))) + string_list_add((*cmd)->name); +} + +int complete(char *instr, char **outstr) +{ + int pos; + char ch; + int changed; + int outpos = 0; + int reprint = 0; + char *first_entry; + char *entry; + int i; + + string_list_init(); + command_complete(instr); + + pos = strlen(instr); + + *outstr = ""; + if (string_list_empty()) + reprint = 0; + else + { + out[0] = 0; + + first_entry = list_first_entry(); + + while (1) { + entry = first_entry; + ch = entry[pos]; + if (!ch) + break; + + changed = 0; + for (i = 0; i < HIST_DEPTH; i++) { + if (sl[i][0] != 0) { + if (!sl[i][pos]) + break; + if (ch != sl[i][pos]) { + changed = 1; + break; + } + } + } + + if (changed) + break; + out[outpos++] = ch; + pos++; + } + + if ((string_list_count() != 1) && !outpos && tab_pressed) { + printf("\n"); + string_list_print_by_column(); + reprint = 1; + tab_pressed = 0; + } + + out[outpos++] = 0; + *outstr = out; + + if (*out == 0) + tab_pressed = 1; + else + tab_pressed = 0; + } + + return reprint; +} diff --git a/litex/soc/software/bios/complete.h b/litex/soc/software/bios/complete.h new file mode 100644 index 000000000..b615df76a --- /dev/null +++ b/litex/soc/software/bios/complete.h @@ -0,0 +1,6 @@ +#ifndef __COMPLETE_H__ +#define __COMPLETE_H__ + +int complete(char *instr, char **outstr); + +#endif diff --git a/litex/soc/software/bios/helpers.c b/litex/soc/software/bios/helpers.c new file mode 100644 index 000000000..535dd61b2 --- /dev/null +++ b/litex/soc/software/bios/helpers.c @@ -0,0 +1,128 @@ +// This file is Copyright (c) 2017 Florent Kermarrec + +// SPDX-License-Identifier: BSD-Source-Code + +#include +#include +#include +#include + +#include "readline.h" +#include "helpers.h" +#include "command.h" + +extern unsigned int _ftext, _edata; + +#define NUMBER_OF_BYTES_ON_A_LINE 16 +void dump_bytes(unsigned int *ptr, int count, unsigned long addr) +{ + char *data = (char *)ptr; + int line_bytes = 0, i = 0; + + putsnonl("Memory dump:"); + while (count > 0) { + line_bytes = + (count > NUMBER_OF_BYTES_ON_A_LINE)? + NUMBER_OF_BYTES_ON_A_LINE : count; + + printf("\n0x%08x ", addr); + for (i = 0; i < line_bytes; i++) + printf("%02x ", *(unsigned char *)(data+i)); + + for (; i < NUMBER_OF_BYTES_ON_A_LINE; i++) + printf(" "); + + printf(" "); + + for (i = 0; i 0x7e)) + printf("."); + else + printf("%c", *(data+i)); + } + + for (; i < NUMBER_OF_BYTES_ON_A_LINE; i++) + printf(" "); + + data += (char)line_bytes; + count -= line_bytes; + addr += line_bytes; + } + printf("\n"); +} + +void crcbios(void) +{ + unsigned long offset_bios; + unsigned long length; + unsigned int expected_crc; + unsigned int actual_crc; + + /* + * _edata is located right after the end of the flat + * binary image. The CRC tool writes the 32-bit CRC here. + * We also use the address of _edata to know the length + * of our code. + */ + offset_bios = (unsigned long)&_ftext; + expected_crc = _edata; + length = (unsigned long)&_edata - offset_bios; + actual_crc = crc32((unsigned char *)offset_bios, length); + if (expected_crc == actual_crc) + printf(" BIOS CRC passed (%08x)\n", actual_crc); + else { + printf(" BIOS CRC failed (expected %08x, got %08x)\n", expected_crc, actual_crc); + printf(" The system will continue, but expect problems.\n"); + } +} + +int get_param(char *buf, char **cmd, char **params) +{ + int nb_param = 0; + int i; + + for (i = 0; i < MAX_PARAM; i++) + params[i] = NULL; + + *cmd = buf; + + while ((*buf != ' ') && (*buf !=0)) + buf++; + + if (*buf == 0) + return nb_param; + + *buf++ = 0; + + while (1) { + while ((*buf == ' ') && (*buf !=0)) + buf++; + + + if (*buf == 0) + return nb_param; + + params[nb_param++] = buf; + + while ((*buf != ' ') && (*buf !=0)) + buf++; + + if (*buf == 0) + return nb_param; + *buf++ = 0; + } +} + +struct command_struct *command_dispatcher(char *command, int nb_params, char **params) +{ + struct command_struct * const *cmd; + + for (cmd = __bios_cmd_start; cmd != __bios_cmd_end; cmd++) { + if (!strcmp(command, (*cmd)->name)) { + (*cmd)->func(nb_params, params); + return (*cmd); + } + } + + return NULL; +} diff --git a/litex/soc/software/bios/helpers.h b/litex/soc/software/bios/helpers.h new file mode 100644 index 000000000..6f1f2deeb --- /dev/null +++ b/litex/soc/software/bios/helpers.h @@ -0,0 +1,9 @@ +#ifndef __HELPERS_H__ +#define __HELPERS_H__ + +void dump_bytes(unsigned int *ptr, int count, unsigned long addr); +void crcbios(void); +int get_param(char *buf, char **cmd, char **params); +struct command_struct *command_dispatcher(char *command, int nb_params, char **params); + +#endif diff --git a/litex/soc/software/bios/lfsr.h b/litex/soc/software/bios/lfsr.h new file mode 100644 index 000000000..50dfccfc7 --- /dev/null +++ b/litex/soc/software/bios/lfsr.h @@ -0,0 +1,109 @@ +#include + +/* + * Copyright (C) 2020, Anton Blanchard , IBM + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Galois LFSR + * + * Polynomials verified with https://bitbucket.org/gallen/mlpolygen/ + */ +static inline unsigned long lfsr(unsigned long bits, unsigned long prev) +{ + static const unsigned long lfsr_taps[] = { + 0x0, + 0x0, + 0x3, + 0x6, + 0xc, + 0x14, + 0x30, + 0x60, + 0xb8, + 0x110, + 0x240, + 0x500, + 0x829, + 0x100d, + 0x2015, + 0x6000, + 0xd008, + 0x12000, + 0x20400, + 0x40023, + 0x90000, + 0x140000, + 0x300000, + 0x420000, + 0xe10000, + 0x1200000, + 0x2000023, + 0x4000013, + 0x9000000, + 0x14000000, + 0x20000029, + 0x48000000, + 0x80200003, +#if __WORDSIZE == 64 + 0x100080000, + 0x204000003, + 0x500000000, + 0x801000000, + 0x100000001f, + 0x2000000031, + 0x4400000000, + 0xa000140000, + 0x12000000000, + 0x300000c0000, + 0x63000000000, + 0xc0000030000, + 0x1b0000000000, + 0x300003000000, + 0x420000000000, + 0xc00000180000, + 0x1008000000000, + 0x3000000c00000, + 0x6000c00000000, + 0x9000000000000, + 0x18003000000000, + 0x30000000030000, + 0x40000040000000, + 0xc0000600000000, + 0x102000000000000, + 0x200004000000000, + 0x600003000000000, + 0xc00000000000000, + 0x1800300000000000, + 0x3000000000000030, + 0x6000000000000000, + 0x800000000000000d +#endif + }; + unsigned long lsb = prev & 1; + + prev >>= 1; + prev ^= (-lsb) & lfsr_taps[bits]; + + return prev; +} diff --git a/litex/soc/software/bios/linker.ld b/litex/soc/software/bios/linker.ld index 7760e551d..e0211a6b4 100644 --- a/litex/soc/software/bios/linker.ld +++ b/litex/soc/software/bios/linker.ld @@ -26,6 +26,13 @@ SECTIONS _erodata = .; } > rom + .commands : + { + PROVIDE_HIDDEN (__bios_cmd_start = .); + KEEP(*(.bios_cmd)) + PROVIDE_HIDDEN (__bios_cmd_end = .); + } > rom + .data : { . = ALIGN(8); diff --git a/litex/soc/software/bios/main.c b/litex/soc/software/bios/main.c index b6501edbb..7864260aa 100644 --- a/litex/soc/software/bios/main.c +++ b/litex/soc/software/bios/main.c @@ -10,6 +10,7 @@ // This file is Copyright (c) 2018 Jean-François Nguyen // This file is Copyright (c) 2018 Sergiusz Bazanski // This file is Copyright (c) 2016 Tim 'mithro' Ansell +// This file is Copyright (c) 2020 Franck Jullien // License: BSD @@ -24,6 +25,7 @@ #include #include +#include #include #include @@ -42,553 +44,9 @@ #include "sdram.h" #include "sdcard.h" #include "boot.h" - -/* General address space functions */ - -#define NUMBER_OF_BYTES_ON_A_LINE 16 -static void dump_bytes(unsigned int *ptr, int count, unsigned long addr) -{ - char *data = (char *)ptr; - int line_bytes = 0, i = 0; - - putsnonl("Memory dump:"); - while(count > 0){ - line_bytes = - (count > NUMBER_OF_BYTES_ON_A_LINE)? - NUMBER_OF_BYTES_ON_A_LINE : count; - - printf("\n0x%08x ", addr); - for(i=0;i 0x7e)) - printf("."); - else - printf("%c", *(data+i)); - } - - for(;i [length]\n"); - return; - } - addr = (unsigned *)strtoul(startaddr, &c, 0); - if(*c != 0) { - printf("incorrect address\n"); - return; - } - if(*len == 0) { - length = 4; - } else { - length = strtoul(len, &c, 0); - if(*c != 0) { - printf("incorrect length\n"); - return; - } - } - - dump_bytes(addr, length, (unsigned long)addr); -} - -static void mw(char *addr, char *value, char *count) -{ - char *c; - unsigned int *addr2; - unsigned int value2; - unsigned int count2; - unsigned int i; - - if((*addr == 0) || (*value == 0)) { - printf("mw
[count]\n"); - return; - } - addr2 = (unsigned int *)strtoul(addr, &c, 0); - if(*c != 0) { - printf("incorrect address\n"); - return; - } - value2 = strtoul(value, &c, 0); - if(*c != 0) { - printf("incorrect value\n"); - return; - } - if(*count == 0) { - count2 = 1; - } else { - count2 = strtoul(count, &c, 0); - if(*c != 0) { - printf("incorrect count\n"); - return; - } - } - for (i=0;i [count]\n"); - return; - } - dstaddr2 = (unsigned int *)strtoul(dstaddr, &c, 0); - if(*c != 0) { - printf("incorrect destination address\n"); - return; - } - srcaddr2 = (unsigned int *)strtoul(srcaddr, &c, 0); - if(*c != 0) { - printf("incorrect source address\n"); - return; - } - if(*count == 0) { - count2 = 1; - } else { - count2 = strtoul(count, &c, 0); - if(*c != 0) { - printf("incorrect count\n"); - return; - } - } - for (i=0;i [count]\n"); - return; - } - addr2 = strtoul(addr, &c, 0); - if(*c != 0) { - printf("incorrect offset\n"); - return; - } - value2 = strtoul(value, &c, 0); - if(*c != 0) { - printf("incorrect value\n"); - return; - } - if(*count == 0) { - count2 = 1; - } else { - count2 = strtoul(count, &c, 0); - if(*c != 0) { - printf("incorrect count\n"); - return; - } - } - for (i=0;i \n"); - return; - } - phyadr2 = strtoul(phyadr, &c, 0); - if(*c != 0) { - printf("incorrect phyadr\n"); - return; - } - reg2 = strtoul(reg, &c, 0); - if(*c != 0) { - printf("incorrect reg\n"); - return; - } - val2 = strtoul(val, &c, 0); - if(*c != 0) { - printf("incorrect val\n"); - return; - } - mdio_write(phyadr2, reg2, val2); -} - -static void mdior(char *phyadr, char *reg) -{ - char *c; - unsigned int phyadr2; - unsigned int reg2; - unsigned int val; - - if((*phyadr == 0) || (*reg == 0)) { - printf("mdior \n"); - return; - } - phyadr2 = strtoul(phyadr, &c, 0); - if(*c != 0) { - printf("incorrect phyadr\n"); - return; - } - reg2 = strtoul(reg, &c, 0); - if(*c != 0) { - printf("incorrect reg\n"); - return; - } - val = mdio_read(phyadr2, reg2); - printf("reg %d: 0x%04x\n", reg2, val); -} - -static void mdiod(char *phyadr, char *count) -{ - char *c; - unsigned int phyadr2; - unsigned int count2; - unsigned int val; - int i; - - if((*phyadr == 0) || (*count == 0)) { - printf("mdiod \n"); - return; - } - phyadr2 = strtoul(phyadr, &c, 0); - if(*c != 0) { - printf("incorrect phyadr\n"); - return; - } - count2 = strtoul(count, &c, 0); - if(*c != 0) { - printf("incorrect count\n"); - return; - } - printf("MDIO dump @0x%x:\n", phyadr2); - for (i=0; i \n"); - return; - } - addr = (char *)strtoul(startaddr, &c, 0); - if(*c != 0) { - printf("incorrect address\n"); - return; - } - length = strtoul(len, &c, 0); - if(*c != 0) { - printf("incorrect length\n"); - return; - } - - printf("CRC32: %08x\n", crc32((unsigned char *)addr, length)); -} - -static void ident(void) -{ - char buffer[IDENT_SIZE]; - - get_ident(buffer); - printf("Ident: %s\n", buffer); -} - -/* Init + command line */ - -static void help(void) -{ - puts("LiteX BIOS, available commands:"); - puts("mr - read address space"); - puts("mw - write address space"); - puts("mc - copy address space"); -#if (defined CSR_SPIFLASH_BASE && defined SPIFLASH_PAGE_SIZE) - puts("fe - erase whole flash"); - puts("fw - write to flash"); - -#endif -#ifdef CSR_ETHPHY_MDIO_W_ADDR - puts("mdiow - write MDIO register"); - puts("mdior - read MDIO register"); - puts("mdiod - dump MDIO registers"); -#endif - puts(""); - puts("crc - compute CRC32 of a part of the address space"); - puts("ident - display identifier"); - puts(""); - puts("flush_cpu_dcache - flush CPU data cache"); -#ifdef CONFIG_L2_SIZE - puts("flush_l2_cache - flush L2 cache"); -#endif - puts(""); -#ifdef CSR_CTRL_BASE - puts("reboot - reset processor"); -#endif -#ifdef CSR_ETHMAC_BASE - puts("netboot - boot via TFTP"); -#endif - puts("serialboot - boot via SFL"); -#ifdef FLASH_BOOT_ADDRESS - puts("flashboot - boot from flash"); -#endif -#ifdef ROM_BOOT_ADDRESS - puts("romboot - boot from embedded rom"); -#endif - puts(""); -#ifdef CSR_SDRAM_BASE - puts("memtest - run a memory test"); -#endif - puts(""); -#ifdef CSR_SDCORE_BASE - puts("sdclk - SDCard set clk frequency (Mhz)"); - puts("sdinit - SDCard initialization"); - puts("sdtest - SDCard test"); -#endif -#ifdef USDDRPHY_DEBUG - puts(""); - puts("sdram_cdly value - Set SDRAM clk/cmd delay"); - puts("sdram_cal - run SDRAM calibration"); - puts("sdram_mpr - read SDRAM MPR"); - puts("sdram_mrwr reg value - write SDRAM mode registers"); - puts("sdram_cdly_scan enabled - enable/disable cdly scan"); -#endif -#ifdef CSR_SPISDCARD_BASE - puts("spisdcardboot - boot from SDCard via SPI hardware bitbang"); -#endif -} - -static char *get_token(char **str) -{ - char *c, *d; - - c = (char *)strchr(*str, ' '); - if(c == NULL) { - d = *str; - *str = *str+strlen(*str); - return d; - } - *c = 0; - d = *str; - *str = c+1; - return d; -} - -#ifdef CSR_CTRL_BASE -static void reboot(void) -{ - ctrl_reset_write(1); -} -#endif - -static void do_command(char *c) -{ - char *token; - - token = get_token(&c); - - if(strcmp(token, "mr") == 0) mr(get_token(&c), get_token(&c)); - else if(strcmp(token, "mw") == 0) mw(get_token(&c), get_token(&c), get_token(&c)); - else if(strcmp(token, "mc") == 0) mc(get_token(&c), get_token(&c), get_token(&c)); -#if (defined CSR_SPIFLASH_BASE && defined SPIFLASH_PAGE_SIZE) - else if(strcmp(token, "fw") == 0) fw(get_token(&c), get_token(&c), get_token(&c)); - else if(strcmp(token, "fe") == 0) fe(); -#endif -#ifdef CSR_ETHPHY_MDIO_W_ADDR - else if(strcmp(token, "mdiow") == 0) mdiow(get_token(&c), get_token(&c), get_token(&c)); - else if(strcmp(token, "mdior") == 0) mdior(get_token(&c), get_token(&c)); - else if(strcmp(token, "mdiod") == 0) mdiod(get_token(&c), get_token(&c)); -#endif - else if(strcmp(token, "crc") == 0) crc(get_token(&c), get_token(&c)); - else if(strcmp(token, "ident") == 0) ident(); - - else if(strcmp(token, "flush_cpu_dcache") == 0) flush_cpu_dcache(); -#ifdef CONFIG_L2_SIZE - else if(strcmp(token, "flush_l2_cache") == 0) flush_l2_cache(); -#endif - -#ifdef CSR_CTRL_BASE - else if(strcmp(token, "reboot") == 0) reboot(); -#endif -#ifdef FLASH_BOOT_ADDRESS - else if(strcmp(token, "flashboot") == 0) flashboot(); -#endif -#ifdef ROM_BOOT_ADDRESS - else if(strcmp(token, "romboot") == 0) romboot(); -#endif - else if(strcmp(token, "serialboot") == 0) serialboot(); -#ifdef CSR_ETHMAC_BASE - else if(strcmp(token, "netboot") == 0) netboot(); -#endif - - else if(strcmp(token, "help") == 0) help(); - -#ifdef CSR_SDRAM_BASE - else if(strcmp(token, "sdrrow") == 0) sdrrow(get_token(&c)); - else if(strcmp(token, "sdrsw") == 0) sdrsw(); - else if(strcmp(token, "sdrhw") == 0) sdrhw(); - else if(strcmp(token, "sdrrdbuf") == 0) sdrrdbuf(-1); - else if(strcmp(token, "sdrrd") == 0) sdrrd(get_token(&c), get_token(&c)); - else if(strcmp(token, "sdrrderr") == 0) sdrrderr(get_token(&c)); - else if(strcmp(token, "sdrwr") == 0) sdrwr(get_token(&c)); -#ifdef CSR_DDRPHY_BASE - else if(strcmp(token, "sdrinit") == 0) sdrinit(); -#ifdef SDRAM_PHY_WRITE_LEVELING_CAPABLE - else if(strcmp(token, "sdrwlon") == 0) sdrwlon(); - else if(strcmp(token, "sdrwloff") == 0) sdrwloff(); -#endif - else if(strcmp(token, "sdrlevel") == 0) sdrlevel(); -#endif - else if(strcmp(token, "memtest") == 0) memtest(); -#endif - -#ifdef CSR_SDCORE_BASE - else if(strcmp(token, "sdclk") == 0) sdclk_set_clk(atoi(get_token(&c))); - else if(strcmp(token, "sdinit") == 0) sdcard_init(); - else if(strcmp(token, "sdtest") == 0) sdcard_test(atoi(get_token(&c))); -#endif -#ifdef USDDRPHY_DEBUG - else if(strcmp(token, "sdram_cdly") == 0) - ddrphy_cdly(atoi(get_token(&c))); - else if(strcmp(token, "sdram_cal") == 0) - sdrcal(); - else if(strcmp(token, "sdram_mpr") == 0) - sdrmpr(); - else if(strcmp(token, "sdram_mrwr") == 0) { - unsigned int reg; - unsigned int value; - reg = atoi(get_token(&c)); - value = atoi(get_token(&c)); - sdrsw(); - printf("Writing 0x%04x to SDRAM mode register %d\n", value, reg); - sdrmrwr(reg, value); - sdrhw(); - } - else if(strcmp(token, "sdram_cdly_scan") == 0) { - unsigned int enabled; - enabled = atoi(get_token(&c)); - sdr_cdly_scan(enabled); - } -#endif -#ifdef CSR_SPISDCARD_BASE - else if(strcmp(token, "spisdcardboot") == 0) spisdcardboot(); -#endif - - else if(strcmp(token, "") != 0) - printf("Command not found\n"); -} - -extern unsigned int _ftext, _edata; - -static void crcbios(void) -{ - unsigned long offset_bios; - unsigned long length; - unsigned int expected_crc; - unsigned int actual_crc; - - /* - * _edata is located right after the end of the flat - * binary image. The CRC tool writes the 32-bit CRC here. - * We also use the address of _edata to know the length - * of our code. - */ - offset_bios = (unsigned long)&_ftext; - expected_crc = _edata; - length = (unsigned long)&_edata - offset_bios; - actual_crc = crc32((unsigned char *)offset_bios, length); - if(expected_crc == actual_crc) - printf(" BIOS CRC passed (%08x)\n", actual_crc); - else { - printf(" BIOS CRC failed (expected %08x, got %08x)\n", expected_crc, actual_crc); - printf(" The system will continue, but expect problems.\n"); - } -} - -static void readstr(char *s, int size) -{ - static char skip = 0; - char c[2]; - int ptr; - - c[1] = 0; - ptr = 0; - while(1) { - c[0] = readchar(); - if (c[0] == skip) - continue; - skip = 0; - switch(c[0]) { - case 0x7f: - case 0x08: - if(ptr > 0) { - ptr--; - putsnonl("\x08 \x08"); - } - break; - case 0x07: - break; - case '\r': - skip = '\n'; - s[ptr] = 0x00; - putsnonl("\n"); - return; - case '\n': - skip = '\r'; - s[ptr] = 0x00; - putsnonl("\n"); - return; - default: - putsnonl(c); - s[ptr] = c[0]; - ptr++; - break; - } - } -} +#include "readline.h" +#include "helpers.h" +#include "command.h" static void boot_sequence(void) { @@ -614,8 +72,13 @@ static void boot_sequence(void) int main(int i, char **c) { - char buffer[64]; + char buffer[CMD_LINE_BUFFER_SIZE]; + char *params[MAX_PARAM]; + char *command; + struct command_struct *cmd; + int nb_params; int sdr_ok; + #ifdef CONFIG_CPU_HAS_INTERRUPT irq_setmask(0); irq_setie(1); @@ -639,27 +102,9 @@ int main(int i, char **c) printf(" LiteX git sha1: "LITEX_GIT_SHA1"\n"); printf("\n"); printf("--=============== \e[1mSoC\e[0m ==================--\n"); - printf("\e[1mCPU\e[0m: "); -#ifdef __lm32__ - printf("LM32"); -#elif __or1k__ - printf("MOR1KX"); -#elif __picorv32__ - printf("PicoRV32"); -#elif __vexriscv__ - printf("VexRiscv"); -#elif __minerva__ - printf("Minerva"); -#elif __rocket__ - printf("RocketRV64[imac]"); -#elif __blackparrot__ - printf("BlackParrotRV64[ia]"); -#elif __serv__ - printf("SERV"); -#else - printf("Unknown"); -#endif - printf(" @ %dMHz\n", CONFIG_CLOCK_FREQUENCY/1000000); + printf("\e[1mCPU\e[0m: %s @ %dMHz\n", + CONFIG_CPU_HUMAN_NAME, + CONFIG_CLOCK_FREQUENCY/1000000); printf("\e[1mROM\e[0m: %dKB\n", ROM_SIZE/1024); printf("\e[1mSRAM\e[0m: %dKB\n", SRAM_SIZE/1024); #ifdef CONFIG_L2_SIZE @@ -696,10 +141,20 @@ int main(int i, char **c) } printf("--============= \e[1mConsole\e[0m ================--\n"); - while(1) { - putsnonl("\e[92;1mlitex\e[0m> "); - readstr(buffer, 64); - do_command(buffer); +#if !defined(TERM_MINI) && !defined(TERM_NO_HIST) + hist_init(); +#endif + printf("\n%s", PROMPT); + while(1) { + readline(buffer, CMD_LINE_BUFFER_SIZE); + if (buffer[0] != 0) { + printf("\n"); + nb_params = get_param(buffer, &command, params); + cmd = command_dispatcher(command, nb_params, params); + if (!cmd) + printf("Command not found"); + } + printf("\n%s", PROMPT); } return 0; } diff --git a/litex/soc/software/bios/readline.c b/litex/soc/software/bios/readline.c new file mode 100644 index 000000000..48d8f1a6c --- /dev/null +++ b/litex/soc/software/bios/readline.c @@ -0,0 +1,359 @@ +// This file is Copyright (c) 2020 Franck Jullien +// +// Largely inspired/copied from U-boot and Barebox projects wich are: +// Wolfgang Denk, DENX Software Engineering, +// Sascha Hauer, Pengutronix, +// cmdline-editing related codes from vivi +// Author: Janghoon Lyu + +// SPDX-License-Identifier: BSD-Source-Code + +#include +#include +#include +#include + +#include +#include + +#include "readline.h" +#include "complete.h" + +#ifndef TERM_NO_HIST +static int hist_max = 0; +static int hist_add_idx = 0; +static int hist_cur = 0; +static int hist_num = 0; +static char hist_lines[HIST_MAX][CMD_LINE_BUFFER_SIZE]; +#endif + +#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0])) + +static const struct esc_cmds esccmds[] = { + {"OA", KEY_UP}, // cursor key Up + {"OB", KEY_DOWN}, // cursor key Down + {"OC", KEY_RIGHT}, // Cursor Key Right + {"OD", KEY_LEFT}, // cursor key Left + {"OH", KEY_HOME}, // Cursor Key Home + {"OF", KEY_END}, // Cursor Key End + {"[A", KEY_UP}, // cursor key Up + {"[B", KEY_DOWN}, // cursor key Down + {"[C", KEY_RIGHT}, // Cursor Key Right + {"[D", KEY_LEFT}, // cursor key Left + {"[H", KEY_HOME}, // Cursor Key Home + {"[F", KEY_END}, // Cursor Key End + {"[1~", KEY_HOME}, // Cursor Key Home + {"[2~", KEY_INSERT}, // Cursor Key Insert + {"[3~", KEY_DEL}, // Cursor Key Delete + {"[4~", KEY_END}, // Cursor Key End + {"[5~", KEY_PAGEUP}, // Cursor Key Page Up + {"[6~", KEY_PAGEDOWN},// Cursor Key Page Down +}; + +static int read_key(void) +{ + char c; + char esc[5]; + c = readchar(); + + if (c == 27) { + int i = 0; + esc[i++] = readchar(); + esc[i++] = readchar(); + if (isdigit(esc[1])) { + while(1) { + esc[i] = readchar(); + if (esc[i++] == '~') + break; + if (i == ARRAY_SIZE(esc)) + return -1; + } + } + esc[i] = 0; + for (i = 0; i < ARRAY_SIZE(esccmds); i++){ + if (!strcmp(esc, esccmds[i].seq)) + return esccmds[i].val; + } + return -1; + } + return c; +} + +#ifndef TERM_NO_HIST +static void cread_add_to_hist(char *line) +{ + strcpy(&hist_lines[hist_add_idx][0], line); + + if (++hist_add_idx >= HIST_MAX) + hist_add_idx = 0; + + if (hist_add_idx > hist_max) + hist_max = hist_add_idx; + + hist_num++; +} + +static char* hist_prev(void) +{ + char *ret; + int old_cur; + + if (hist_cur < 0) + return NULL; + + old_cur = hist_cur; + if (--hist_cur < 0) + hist_cur = hist_max; + + if (hist_cur == hist_add_idx) { + hist_cur = old_cur; + ret = NULL; + } else { + ret = &hist_lines[hist_cur][0]; + } + + return ret; +} + +static char* hist_next(void) +{ + char *ret; + + if (hist_cur < 0) + return NULL; + + if (hist_cur == hist_add_idx) + return NULL; + + if (++hist_cur > hist_max) + hist_cur = 0; + + if (hist_cur == hist_add_idx) + ret = ""; + else + ret = &hist_lines[hist_cur][0]; + + return ret; +} + +void hist_init(void) +{ + int i; + + hist_max = 0; + hist_add_idx = 0; + hist_cur = -1; + hist_num = 0; + + for (i = 0; i < HIST_MAX; i++) + hist_lines[i][0] = '\0'; +} +#endif + +static void cread_add_char(char ichar, int insert, unsigned long *num, + unsigned long *eol_num, char *buf, unsigned long len) +{ + unsigned long wlen; + + if (insert || *num == *eol_num) { + if (*eol_num > len - 1) { + getcmd_cbeep(); + return; + } + (*eol_num)++; + } + + if (insert) { + wlen = *eol_num - *num; + if (wlen > 1) { + memmove(&buf[*num+1], &buf[*num], wlen-1); + } + + buf[*num] = ichar; + putnstr(buf + *num, wlen); + (*num)++; + while (--wlen) { + getcmd_putch(CTL_BACKSPACE); + } + } else { + /* echo the character */ + wlen = 1; + buf[*num] = ichar; + putnstr(buf + *num, wlen); + (*num)++; + } +} + +int readline(char *buf, int len) +{ + unsigned long num = 0; + unsigned long eol_num = 0; + unsigned long wlen; + int insert = 1; + char ichar; + +#ifndef TERM_NO_COMPLETE + char tmp; + int reprint, i; + char *completestr; +#endif + + while (1) { + + ichar = read_key(); + + if ((ichar == '\n') || (ichar == '\r')) + break; + + switch (ichar) { + case '\t': +#ifndef TERM_NO_COMPLETE + buf[eol_num] = 0; + tmp = buf[num]; + + buf[num] = 0; + reprint = complete(buf, &completestr); + buf[num] = tmp; + + if (reprint) { + printf("%s%s", PROMPT, buf); + + if (tmp) + for (i = 0; i < eol_num - num; i++) + getcmd_putch(CTL_BACKSPACE); + } + + i = 0; + while (completestr[i]) + cread_add_char(completestr[i++], insert, &num, + &eol_num, buf, len); +#endif + break; + + case KEY_HOME: + BEGINNING_OF_LINE(); + break; + case CTL_CH('c'): /* ^C - break */ + *buf = 0; /* discard input */ + return -1; + break; + case KEY_RIGHT: + if (num < eol_num) { + getcmd_putch(buf[num]); + num++; + } + break; + case KEY_LEFT: + if (num) { + getcmd_putch(CTL_BACKSPACE); + num--; + } + break; + case CTL_CH('d'): + if (num < eol_num) { + wlen = eol_num - num - 1; + if (wlen) { + memmove(&buf[num], &buf[num+1], wlen); + putnstr(buf + num, (int)wlen); + } + + getcmd_putch(' '); + do { + getcmd_putch(CTL_BACKSPACE); + } while (wlen--); + eol_num--; + } + break; + case KEY_ERASE_TO_EOL: + ERASE_TO_EOL(); + break; + case KEY_REFRESH_TO_EOL: + case KEY_END: + REFRESH_TO_EOL(); + break; + case KEY_INSERT: + insert = !insert; + break; + case KEY_ERASE_LINE: + BEGINNING_OF_LINE(); + ERASE_TO_EOL(); + break; + case DEL: + case KEY_DEL7: + case 8: + if (num) { + wlen = eol_num - num; + num--; + memmove(buf + num, buf + num + 1, wlen); + getcmd_putch(CTL_BACKSPACE); + putnstr(buf + num, (int)wlen); + getcmd_putch(' '); + do { + getcmd_putch(CTL_BACKSPACE); + } while (wlen--); + eol_num--; + } + break; + case KEY_DEL: + if (num < eol_num) { + wlen = eol_num - num; + memmove(buf + num, buf + num + 1, wlen); + putnstr(buf + num, (int)(wlen - 1)); + getcmd_putch(' '); + do { + getcmd_putch(CTL_BACKSPACE); + } while (--wlen); + eol_num--; + } + break; + case KEY_UP: + case KEY_DOWN: + { +#ifndef TERM_NO_HIST + char * hline; + if (ichar == KEY_UP) + hline = hist_prev(); + else + hline = hist_next(); + + if (!hline) { + getcmd_cbeep(); + break; + } + + /* nuke the current line */ + /* first, go home */ + BEGINNING_OF_LINE(); + + /* erase to end of line */ + ERASE_TO_EOL(); + + /* copy new line into place and display */ + strcpy(buf, hline); + eol_num = strlen(buf); + REFRESH_TO_EOL(); +#endif + break; + } + + default: + if (isascii(ichar) && isprint(ichar)) + cread_add_char (ichar, insert, &num, &eol_num, buf, len); + break; + } + } + + len = eol_num; + buf[eol_num] = '\0'; + +#ifndef TERM_NO_HIST + if (buf[0] && buf[0] != CREAD_HIST_CHAR) + cread_add_to_hist(buf); + hist_cur = hist_add_idx; +#endif + + num = 0; + eol_num = 0; + + return len; +} diff --git a/litex/soc/software/bios/readline.h b/litex/soc/software/bios/readline.h new file mode 100644 index 000000000..f1284c5d1 --- /dev/null +++ b/litex/soc/software/bios/readline.h @@ -0,0 +1,83 @@ +#ifndef __READLINE_H__ +#define __READLINE_H__ + +#include +#include + +#define CMD_LINE_BUFFER_SIZE 64 + +#define PROMPT "\e[92;1mlitex\e[0m> " + +#define ESC 27 + +struct esc_cmds { + const char *seq; + char val; +}; + +#define CTL_CH(c) ((c) - 'a' + 1) + +/* Misc. non-Ascii keys */ +#define KEY_UP CTL_CH('p') /* cursor key Up */ +#define KEY_DOWN CTL_CH('n') /* cursor key Down */ +#define KEY_RIGHT CTL_CH('f') /* Cursor Key Right */ +#define KEY_LEFT CTL_CH('b') /* cursor key Left */ +#define KEY_HOME CTL_CH('a') /* Cursor Key Home */ +#define KEY_ERASE_TO_EOL CTL_CH('k') +#define KEY_REFRESH_TO_EOL CTL_CH('e') +#define KEY_ERASE_LINE CTL_CH('x') +#define KEY_INSERT CTL_CH('o') +#define KEY_CLEAR_SCREEN CTL_CH('l') +#define KEY_DEL7 127 +#define KEY_END 133 /* Cursor Key End */ +#define KEY_PAGEUP 135 /* Cursor Key Page Up */ +#define KEY_PAGEDOWN 136 /* Cursor Key Page Down */ +#define KEY_DEL 137 /* Cursor Key Del */ + +#define MAX_CMDBUF_SIZE 256 + +#define CTL_BACKSPACE ('\b') +#define DEL 255 +#define DEL7 127 +#define CREAD_HIST_CHAR ('!') + +#define HIST_MAX 10 + +#define putnstr(str,n) do { \ + printf ("%.*s", n, str); \ + } while (0) + +#define getcmd_putch(ch) putchar(ch) +#define getcmd_cbeep() getcmd_putch('\a') +#define ANSI_CLEAR_SCREEN "\e[2J\e[;H" + +#define BEGINNING_OF_LINE() { \ + while (num) { \ + getcmd_putch(CTL_BACKSPACE); \ + num--; \ + } \ +} + +#define ERASE_TO_EOL() { \ + if (num < eol_num) { \ + int t; \ + for (t = num; t < eol_num; t++) \ + getcmd_putch(' '); \ + while (t-- > num) \ + getcmd_putch(CTL_BACKSPACE); \ + eol_num = num; \ + } \ +} + +#define REFRESH_TO_EOL() { \ + if (num < eol_num) { \ + wlen = eol_num - num; \ + putnstr(buf + num, (int)wlen); \ + num = eol_num; \ + } \ +} + +int readline(char *buf, int len); +void hist_init(void); + +#endif /* READLINE_H_ */ diff --git a/litex/soc/software/bios/readline_simple.c b/litex/soc/software/bios/readline_simple.c new file mode 100644 index 000000000..bcf062138 --- /dev/null +++ b/litex/soc/software/bios/readline_simple.c @@ -0,0 +1,59 @@ +// This file is Copyright (c) 2013-2014 Sebastien Bourdeauducq +// This file is Copyright (c) 2014-2019 Florent Kermarrec + +// SPDX-License-Identifier: BSD-Source-Code + +#include +#include +#include +#include + +#include +#include + +#include "readline.h" + +int readline(char *s, int size) +{ + static char skip = 0; + char c[2]; + int ptr; + + c[1] = 0; + ptr = 0; + while(1) { + c[0] = readchar(); + if (c[0] == skip) + continue; + skip = 0; + switch(c[0]) { + case 0x7f: + case 0x08: + if(ptr > 0) { + ptr--; + putsnonl("\x08 \x08"); + } + break; + case 0x07: + break; + case '\r': + skip = '\n'; + s[ptr] = 0x00; + putsnonl("\n"); + return 0; + case '\n': + skip = '\r'; + s[ptr] = 0x00; + putsnonl("\n"); + return 0; + default: + putsnonl(c); + s[ptr] = c[0]; + ptr++; + break; + } + } + + return 0; +} + diff --git a/litex/soc/software/bios/sdram.c b/litex/soc/software/bios/sdram.c index 94df63168..81f48f488 100644 --- a/litex/soc/software/bios/sdram.c +++ b/litex/soc/software/bios/sdram.c @@ -21,6 +21,7 @@ #include #include "sdram.h" +#include "lfsr.h" // FIXME(hack): If we don't have main ram, just target the sram instead. #ifndef MAIN_RAM_BASE @@ -30,29 +31,7 @@ __attribute__((unused)) static void cdelay(int i) { while(i > 0) { -#if defined (__lm32__) - __asm__ volatile("nop"); -#elif defined (__or1k__) - __asm__ volatile("l.nop"); -#elif defined (__picorv32__) - __asm__ volatile("nop"); -#elif defined (__vexriscv__) - __asm__ volatile("nop"); -#elif defined (__minerva__) - __asm__ volatile("nop"); -#elif defined (__rocket__) - __asm__ volatile("nop"); -#elif defined (__powerpc__) - __asm__ volatile("nop"); -#elif defined (__microwatt__) - __asm__ volatile("nop"); -#elif defined (__blackparrot__) - __asm__ volatile("nop"); -#elif defined (__serv__) - __asm__ volatile("nop"); -#else -#error Unsupported architecture -#endif + __asm__ volatile(CONFIG_CPU_NOP); i--; } } @@ -77,28 +56,18 @@ void sdrhw(void) printf("SDRAM now under hardware control\n"); } -void sdrrow(char *_row) +void sdrrow(unsigned int row) { - char *c; - unsigned int row; - - if(*_row == 0) { + if(row == 0) { sdram_dfii_pi0_address_write(0x0000); sdram_dfii_pi0_baddress_write(0); command_p0(DFII_COMMAND_RAS|DFII_COMMAND_WE|DFII_COMMAND_CS); cdelay(15); - printf("Precharged\n"); } else { - row = strtoul(_row, &c, 0); - if(*c != 0) { - printf("incorrect row\n"); - return; - } sdram_dfii_pi0_address_write(row); sdram_dfii_pi0_baddress_write(0); command_p0(DFII_COMMAND_RAS|DFII_COMMAND_CS); cdelay(15); - printf("Activated row %d\n", row); } } @@ -125,58 +94,23 @@ void sdrrdbuf(int dq) printf("\n"); } -void sdrrd(char *startaddr, char *dq) +void sdrrd(unsigned int addr, int dq) { - char *c; - unsigned int addr; - int _dq; - - if(*startaddr == 0) { - printf("sdrrd
\n"); - return; - } - addr = strtoul(startaddr, &c, 0); - if(*c != 0) { - printf("incorrect address\n"); - return; - } - if(*dq == 0) - _dq = -1; - else { - _dq = strtoul(dq, &c, 0); - if(*c != 0) { - printf("incorrect DQ\n"); - return; - } - } - sdram_dfii_pird_address_write(addr); sdram_dfii_pird_baddress_write(0); command_prd(DFII_COMMAND_CAS|DFII_COMMAND_CS|DFII_COMMAND_RDDATA); cdelay(15); - sdrrdbuf(_dq); + sdrrdbuf(dq); } -void sdrrderr(char *count) +void sdrrderr(int count) { int addr; - char *c; - int _count; int i, j, p; unsigned char prev_data[SDRAM_PHY_PHASES][DFII_PIX_DATA_BYTES]; unsigned char errs[SDRAM_PHY_PHASES][DFII_PIX_DATA_BYTES]; unsigned char new_data[DFII_PIX_DATA_BYTES]; - if(*count == 0) { - printf("sdrrderr \n"); - return; - } - _count = strtoul(count, &c, 0); - if(*c != 0) { - printf("incorrect count\n"); - return; - } - for(p=0;p\n"); - return; - } - addr = strtoul(startaddr, &c, 0); - if(*c != 0) { - printf("incorrect address\n"); - return; - } - for(p=0;p -#include -#include - -#ifdef CONFIG_CPU_HAS_INTERRUPT - -#ifdef __picorv32__ -// PicoRV32 has a very limited interrupt support, implemented via custom -// instructions. It also doesn't have a global interrupt enable/disable, so -// we have to emulate it via saving and restoring a mask and using 0/~1 as a -// hardware mask. -// Due to all this somewhat low-level mess, all of the glue is implemented in -// the RiscV crt0, and this header is kept as a thin wrapper. Since interrupts -// managed by this layer, do not call interrupt instructions directly, as the -// state will go out of sync with the hardware. - -// Read only. -extern unsigned int _irq_pending; -// Read only. -extern unsigned int _irq_mask; -// Read only. -extern unsigned int _irq_enabled; -extern void _irq_enable(void); -extern void _irq_disable(void); -extern void _irq_setmask(unsigned int); -#endif - -#ifdef __rocket__ -// The RocketChip uses a Platform-Level Interrupt Controller (PLIC) which -// is programmed and queried via a set of MMIO registers. - -#define PLIC_BASE 0x0c000000L // Base address and per-pin priority array -#define PLIC_PENDING 0x0c001000L // Bit field matching currently pending pins -#define PLIC_ENABLED 0x0c002000L // Bit field corresponding to the current mask -#define PLIC_THRSHLD 0x0c200000L // Per-pin priority must be >= this to trigger -#define PLIC_CLAIM 0x0c200004L // Claim & completion register address -#endif /* __rocket__ */ - - -#ifdef __blackparrot__ -// The RocketChip uses a Platform-Level Interrupt Controller (PLIC) which -// is programmed and queried via a set of MMIO registers. -// TODO: How about Blackparrot? Should be probably included in linux version - -#define PLIC_BASE 0x0c000000L // Base address and per-pin priority array -#define PLIC_PENDING 0x0c001000L // Bit field matching currently pending pins -#define PLIC_ENABLED 0x0c002000L // Bit field corresponding to the current mask -#define PLIC_THRSHLD 0x0c200000L // Per-pin priority must be >= this to trigger -#define PLIC_CLAIM 0x0c200004L // Claim & completion register address -#endif /* __blackparrot__ */ - - - -static inline unsigned int irq_getie(void) -{ -#if defined (__lm32__) - unsigned int ie; - __asm__ __volatile__("rcsr %0, IE" : "=r" (ie)); - return ie; -#elif defined (__or1k__) - return !!(mfspr(SPR_SR) & SPR_SR_IEE); -#elif defined (__picorv32__) - return _irq_enabled != 0; -#elif defined (__vexriscv__) - return (csrr(mstatus) & CSR_MSTATUS_MIE) != 0; -#elif defined (__minerva__) - return (csrr(mstatus) & CSR_MSTATUS_MIE) != 0; -#elif defined (__rocket__) - return (csrr(mstatus) & CSR_MSTATUS_MIE) != 0; -#elif defined (__blackparrot__) - return (csrr(mstatus) & CSR_MSTATUS_MIE) != 0; /* FIXME */ -#else -#error Unsupported architecture -#endif -} - -static inline void irq_setie(unsigned int ie) -{ -#if defined (__lm32__) - __asm__ __volatile__("wcsr IE, %0" : : "r" (ie)); -#elif defined (__or1k__) - if (ie & 0x1) - mtspr(SPR_SR, mfspr(SPR_SR) | SPR_SR_IEE); - else - mtspr(SPR_SR, mfspr(SPR_SR) & ~SPR_SR_IEE); -#elif defined (__picorv32__) - if (ie & 0x1) - _irq_enable(); - else - _irq_disable(); -#elif defined (__vexriscv__) - if(ie) csrs(mstatus,CSR_MSTATUS_MIE); else csrc(mstatus,CSR_MSTATUS_MIE); -#elif defined (__minerva__) - if(ie) csrs(mstatus,CSR_MSTATUS_MIE); else csrc(mstatus,CSR_MSTATUS_MIE); -#elif defined (__rocket__) - if(ie) csrs(mstatus,CSR_MSTATUS_MIE); else csrc(mstatus,CSR_MSTATUS_MIE); -#elif defined (__blackparrot__) - if(ie) csrs(mstatus,CSR_MSTATUS_MIE); else csrc(mstatus,CSR_MSTATUS_MIE); /* FIXME */ -#else -#error Unsupported architecture -#endif -} - -static inline unsigned int irq_getmask(void) -{ -#if defined (__lm32__) - unsigned int mask; - __asm__ __volatile__("rcsr %0, IM" : "=r" (mask)); - return mask; -#elif defined (__or1k__) - return mfspr(SPR_PICMR); -#elif defined (__picorv32__) - // PicoRV32 interrupt mask bits are high-disabled. This is the inverse of how - // LiteX sees things. - return ~_irq_mask; -#elif defined (__vexriscv__) - unsigned int mask; - asm volatile ("csrr %0, %1" : "=r"(mask) : "i"(CSR_IRQ_MASK)); - return mask; -#elif defined (__minerva__) - unsigned int mask; - asm volatile ("csrr %0, %1" : "=r"(mask) : "i"(CSR_IRQ_MASK)); - return mask; -#elif defined (__rocket__) - return *((unsigned int *)PLIC_ENABLED) >> 1; -#elif defined (__blackparrot__) - return 0; /* FIXME */ -#else -#error Unsupported architecture -#endif -} - -static inline void irq_setmask(unsigned int mask) -{ -#if defined (__lm32__) - __asm__ __volatile__("wcsr IM, %0" : : "r" (mask)); -#elif defined (__or1k__) - mtspr(SPR_PICMR, mask); -#elif defined (__picorv32__) - // PicoRV32 interrupt mask bits are high-disabled. This is the inverse of how - // LiteX sees things. - _irq_setmask(~mask); -#elif defined (__vexriscv__) - asm volatile ("csrw %0, %1" :: "i"(CSR_IRQ_MASK), "r"(mask)); -#elif defined (__minerva__) - asm volatile ("csrw %0, %1" :: "i"(CSR_IRQ_MASK), "r"(mask)); -#elif defined (__rocket__) - *((unsigned int *)PLIC_ENABLED) = mask << 1; -#elif defined (__blackparrot__) - /* FIXME */ -#else -#error Unsupported architecture -#endif -} - -static inline unsigned int irq_pending(void) -{ -#if defined (__lm32__) - unsigned int pending; - __asm__ __volatile__("rcsr %0, IP" : "=r" (pending)); - return pending; -#elif defined (__or1k__) - return mfspr(SPR_PICSR); -#elif defined (__picorv32__) - return _irq_pending; -#elif defined (__vexriscv__) - unsigned int pending; - asm volatile ("csrr %0, %1" : "=r"(pending) : "i"(CSR_IRQ_PENDING)); - return pending; -#elif defined (__minerva__) - unsigned int pending; - asm volatile ("csrr %0, %1" : "=r"(pending) : "i"(CSR_IRQ_PENDING)); - return pending; -#elif defined (__rocket__) - return *((unsigned int *)PLIC_PENDING) >> 1; -#elif defined (__blackparrot__) - return csr_readl(PLIC_PENDING) >> 1; /* FIXME */ -#else -#error Unsupported architecture -#endif -} - -#ifdef __cplusplus -} -#endif - -#endif - -#endif /* __IRQ_H */ diff --git a/litex/soc/software/include/base/stdlib.h b/litex/soc/software/include/base/stdlib.h index 448b2f670..a8af6cdf2 100644 --- a/litex/soc/software/include/base/stdlib.h +++ b/litex/soc/software/include/base/stdlib.h @@ -46,7 +46,7 @@ static inline long int labs(long int x) return x > 0 ? x : -x; } -unsigned long strtoul(const char *nptr, char **endptr, int base); +unsigned long strtoul(const char *nptr, char **endptr, unsigned int base); long strtol(const char *nptr, char **endptr, int base); double strtod(const char *str, char **endptr); diff --git a/litex/soc/software/libbase/Makefile b/litex/soc/software/libbase/Makefile index e3a80a039..13680ad0e 100755 --- a/litex/soc/software/libbase/Makefile +++ b/litex/soc/software/libbase/Makefile @@ -4,7 +4,7 @@ include $(SOC_DIRECTORY)/software/common.mak OBJECTS=exception.o libc.o errno.o crc16.o crc32.o console.o \ system.o id.o uart.o time.o qsort.o strtod.o spiflash.o spisdcard.o strcasecmp.o mdio.o -all: crt0-$(CPU)-ctr.o crt0-$(CPU)-xip.o libbase.a libbase-nofloat.a +all: crt0-ctr.o crt0-xip.o libbase.a libbase-nofloat.a libbase.a: $(OBJECTS) vsnprintf.o $(AR) crs libbase.a $(OBJECTS) vsnprintf.o @@ -24,10 +24,10 @@ vsnprintf-nofloat.o: $(LIBBASE_DIRECTORY)/vsnprintf.c %.o: $(LIBBASE_DIRECTORY)/%.S $(assemble) -crt0-$(CPU)-ctr.o: $(LIBBASE_DIRECTORY)/crt0-$(CPU).S +crt0-ctr.o: $(CPU_DIRECTORY)/crt0.S $(assemble) -crt0-$(CPU)-xip.o: $(LIBBASE_DIRECTORY)/crt0-$(CPU).S +crt0-xip.o: $(CPU_DIRECTORY)/crt0.S $(CC) -c -DEXECUTE_IN_PLACE $(CFLAGS) -o $@ $< .PHONY: all clean diff --git a/litex/soc/software/libbase/libc.c b/litex/soc/software/libbase/libc.c index be48cf651..7a2728bb7 100644 --- a/litex/soc/software/libbase/libc.c +++ b/litex/soc/software/libbase/libc.c @@ -374,7 +374,7 @@ void *memchr(const void *s, int c, size_t n) * @endptr: A pointer to the end of the parsed string will be placed here * @base: The number base to use */ -unsigned long strtoul(const char *nptr, char **endptr, int base) +unsigned long strtoul(const char *nptr, char **endptr, unsigned int base) { unsigned long result = 0,value; @@ -535,7 +535,7 @@ char *number(char *buf, char *end, unsigned long num, int base, int size, int pr */ int vscnprintf(char *buf, size_t size, const char *fmt, va_list args) { - int i; + size_t i; i=vsnprintf(buf,size,fmt,args); return (i >= size) ? (size - 1) : i; @@ -579,7 +579,7 @@ int snprintf(char * buf, size_t size, const char *fmt, ...) int scnprintf(char * buf, size_t size, const char *fmt, ...) { va_list args; - int i; + size_t i; va_start(args, fmt); i = vsnprintf(buf, size, fmt, args); diff --git a/litex/soc/software/libbase/qsort.c b/litex/soc/software/libbase/qsort.c index 4df3987a0..7fab2f4dc 100644 --- a/litex/soc/software/libbase/qsort.c +++ b/litex/soc/software/libbase/qsort.c @@ -196,15 +196,15 @@ loop: pn = (char *) base + nmemb * size; r = min(pa - (char *)base, pb - pa); vecswap(base, pb - r, r); - r = min(pd - pc, pn - pd - size); + r = min(pd - pc, pn - pd - (int)size); vecswap(pb, pn - r, r); - if ((r = pb - pa) > size) + if ((r = pb - pa) > (int)size) { qsort(base, r / size, size, compar); } - if ((r = pd - pc) > size) + if ((r = pd - pc) > (int)size) { /* Iterate rather than recurse to save stack space */ base = pn - r; diff --git a/litex/soc/software/libbase/spisdcard.c b/litex/soc/software/libbase/spisdcard.c index ab6cbe039..ae3ec7305 100644 --- a/litex/soc/software/libbase/spisdcard.c +++ b/litex/soc/software/libbase/spisdcard.c @@ -567,10 +567,9 @@ uint8_t spi_sdcard_readFile(char *filename, char *ext, unsigned long address) // Read each cluster sector by sector, i being number of clusters bytesRemaining=fileLength; - printf("Clusters: "); // Calculate number of clusters (always >1) for(i=0; i<1+((fileLength/sdCardFatBootSector.sectors_per_cluster)/sdCardFatBootSector.sector_size); i++) { - printf("%d ",fileClusterStart); + printf("\rCluster: %d",fileClusterStart); // Locate start of cluster on SD CARD and read appropraite number of sectors clusterSectorStart=rootDirSectorStart+(fileClusterStart-1)*sdCardFatBootSector.sectors_per_cluster; @@ -580,14 +579,14 @@ uint8_t spi_sdcard_readFile(char *filename, char *ext, unsigned long address) // Otherwise, read to sdCardSector buffer and transfer appropriate number of bytes if(bytesRemaining>sdCardFatBootSector.sector_size) { if( readSector(clusterSectorStart+sector,(uint8_t *)address) == FAILURE ) { - printf("Read Error\n"); + printf("\nRead Error\n"); return FAILURE; } bytesRemaining=bytesRemaining-sdCardFatBootSector.sector_size; address=address+sdCardFatBootSector.sector_size; } else { if( readSector(clusterSectorStart+sector,sdCardSector) == FAILURE ) { - printf("Read Error\n"); + printf("\nRead Error\n"); return FAILURE; } memcpy((uint8_t *)address, sdCardSector, bytesRemaining); diff --git a/litex/soc/software/libbase/strtod.c b/litex/soc/software/libbase/strtod.c index e79a1eeb6..38b4b3913 100644 --- a/litex/soc/software/libbase/strtod.c +++ b/litex/soc/software/libbase/strtod.c @@ -107,7 +107,7 @@ double strtod(const char *str, char **endptr) switch (*p) { case '-': - negative = 1; /* Fall through to increment position */ + negative = 1; /* FALLTHRU */ /* to increment position */ case '+': p++; } @@ -166,7 +166,7 @@ double strtod(const char *str, char **endptr) switch(*++p) { case '-': - negative = 1; /* Fall through to increment pos */ + negative = 1; /* FALLTHRU */ /* to increment pos */ case '+': p++; } diff --git a/litex/soc/software/libbase/system.c b/litex/soc/software/libbase/system.c index 49d23ac6d..ed4110dde 100644 --- a/litex/soc/software/libbase/system.c +++ b/litex/soc/software/libbase/system.c @@ -1,128 +1,10 @@ #include #include -#ifdef __or1k__ -#include -#endif - -#if defined (__vexriscv__) -#include -#endif #include #include #include -void flush_cpu_icache(void) -{ -#if defined (__lm32__) - asm volatile( - "wcsr ICC, r0\n" - "nop\n" - "nop\n" - "nop\n" - "nop\n" - ); -#elif defined (__or1k__) - unsigned long iccfgr; - unsigned long cache_set_size; - unsigned long cache_ways; - unsigned long cache_block_size; - unsigned long cache_size; - int i; - - iccfgr = mfspr(SPR_ICCFGR); - cache_ways = 1 << (iccfgr & SPR_ICCFGR_NCW); - cache_set_size = 1 << ((iccfgr & SPR_ICCFGR_NCS) >> 3); - cache_block_size = (iccfgr & SPR_ICCFGR_CBS) ? 32 : 16; - cache_size = cache_set_size * cache_ways * cache_block_size; - - for (i = 0; i < cache_size; i += cache_block_size) - mtspr(SPR_ICBIR, i); -#elif defined (__picorv32__) - /* no instruction cache */ - asm volatile("nop"); -#elif defined (__vexriscv__) - asm volatile( - ".word(0x400F)\n" - "nop\n" - "nop\n" - "nop\n" - "nop\n" - "nop\n" - ); -#elif defined (__minerva__) - /* no instruction cache */ - asm volatile("nop"); -#elif defined (__rocket__) - /* FIXME: do something useful here! */ - asm volatile("nop"); -#elif defined (__microwatt__) - /* FIXME: do something useful here! */ - asm volatile("nop"); -#elif defined (__blackparrot__) - /* TODO: BP do something useful here! */ - asm volatile("nop"); -#elif defined (__serv__) - /* no instruction cache */ -#else -#error Unsupported architecture -#endif -} - -void flush_cpu_dcache(void) -{ -#if defined (__lm32__) - asm volatile( - "wcsr DCC, r0\n" - "nop\n" - ); -#elif defined (__or1k__) - unsigned long dccfgr; - unsigned long cache_set_size; - unsigned long cache_ways; - unsigned long cache_block_size; - unsigned long cache_size; - int i; - - dccfgr = mfspr(SPR_DCCFGR); - cache_ways = 1 << (dccfgr & SPR_ICCFGR_NCW); - cache_set_size = 1 << ((dccfgr & SPR_DCCFGR_NCS) >> 3); - cache_block_size = (dccfgr & SPR_DCCFGR_CBS) ? 32 : 16; - cache_size = cache_set_size * cache_ways * cache_block_size; - - for (i = 0; i < cache_size; i += cache_block_size) - mtspr(SPR_DCBIR, i); -#elif defined (__picorv32__) - /* no data cache */ - asm volatile("nop"); -#elif defined (__vexriscv__) - unsigned long cache_info; - asm volatile ("csrr %0, %1" : "=r"(cache_info) : "i"(CSR_DCACHE_INFO)); - unsigned long cache_way_size = cache_info & 0xFFFFF; - unsigned long cache_line_size = (cache_info >> 20) & 0xFFF; - for(register unsigned long idx = 0;idx < cache_way_size;idx += cache_line_size){ - asm volatile("mv x10, %0 \n .word(0b01110000000001010101000000001111)"::"r"(idx)); - } -#elif defined (__minerva__) - /* no data cache */ - asm volatile("nop"); -#elif defined (__rocket__) - /* FIXME: do something useful here! */ - asm volatile("nop"); -#elif defined (__microwatt__) - /* FIXME: do something useful here! */ - asm volatile("nop"); -/*SC_add: What BB does here?*/ -#elif defined (__blackparrot__) - /* FIXME: do something useful here! */ - asm volatile("nop"); -#elif defined (__serv__) - /* no data cache */ -#else -#error Unsupported architecture -#endif -} - #ifdef CONFIG_L2_SIZE void flush_l2_cache(void) { diff --git a/litex/soc/software/libbase/vsnprintf.c b/litex/soc/software/libbase/vsnprintf.c index e056d328b..1785676f3 100644 --- a/litex/soc/software/libbase/vsnprintf.c +++ b/litex/soc/software/libbase/vsnprintf.c @@ -262,6 +262,7 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) case 'X': flags |= PRINTF_LARGE; + /* FALLTHRU */ case 'x': base = 16; break; diff --git a/litex_setup.py b/litex_setup.py index f2502abc0..287cc076a 100755 --- a/litex_setup.py +++ b/litex_setup.py @@ -17,6 +17,7 @@ current_path = os.path.abspath(os.curdir) repos = [ # HDL ("migen", ("https://github.com/m-labs/", True, True)), + ("nmigen", ("https://github.com/nmigen/", True, True)), # LiteX SoC builder ("pythondata-software-compiler_rt", ("https://github.com/litex-hub/", False, True)), @@ -45,6 +46,8 @@ repos = [ ("pythondata-cpu-serv", ("https://github.com/litex-hub/", False, True)), ("pythondata-cpu-vexriscv", ("https://github.com/litex-hub/", False, True)), ("pythondata-cpu-rocket", ("https://github.com/litex-hub/", False, True)), + ("pythondata-cpu-minerva", ("https://github.com/litex-hub/", False, True)), + ("pythondata-cpu-microwatt", ("https://github.com/litex-hub/", False, True)), ] repos = OrderedDict(repos) diff --git a/test/test_targets.py b/test/test_targets.py index f8100fe49..2e71719f3 100644 --- a/test/test_targets.py +++ b/test/test_targets.py @@ -134,7 +134,6 @@ class TestTargets(unittest.TestCase): litex/boards/targets/simple.py litex.boards.platforms.{p} \ --cpu-type=vexriscv \ --no-compile-software \ - --no-compile-gateware \ --uart-name=stub \ """.format(p=p) subprocess.check_call(cmd, shell=True) @@ -155,7 +154,6 @@ litex/boards/targets/simple.py litex.boards.platforms.arty \ --cpu-type={c} \ --cpu-variant={v} \ --no-compile-software \ - --no-compile-gateware \ --uart-name=stub \ """.format(c=cpu, v=variant) subprocess.check_output(cmd, shell=True)