From a0dcf612ead26e67064a8dcfea002f3b5a1301ae Mon Sep 17 00:00:00 2001 From: Stafford Horne Date: Thu, 4 Oct 2018 18:20:51 +0900 Subject: [PATCH 1/6] litex: sim: Get sim working in litex-buildenv Changes needed to get PLATFORM=sim to work again. The platforms/sim was basically copied from litex.boards.platforms.sim but then updated to properly handle sending the SimConfig details to the toolchain needed during building and running of the verilog backend. The changes in gateware/firmware are needed to allow the firmware to be loaded lazily at build time. This is because during build we use a single SoC for firmware and gateware build. Since the old code was looking for the firmware during SoC construction it didnt work. --- gateware/firmware.py | 46 ++++++++++++++++-------------- platforms/sim.py | 67 ++++++++++++++++++++++++++++++++++++++++++-- targets/sim/base.py | 19 ++++++------- targets/sim/net.py | 6 ++-- 4 files changed, 101 insertions(+), 37 deletions(-) diff --git a/gateware/firmware.py b/gateware/firmware.py index 7c50a3d4a..c4f2b1a0c 100644 --- a/gateware/firmware.py +++ b/gateware/firmware.py @@ -6,34 +6,38 @@ class MemoryMustHaveContents(Memory): + def load_init_data(self): + assert os.path.exists(self.filename), ( + "ROM contents not found! {}".format(self.filename)) + + data = [] + with open(self.filename, "rb") as firmware_file: + while True: + w = firmware_file.read(4) + if not w: + break + data.append(struct.unpack(">I", w)[0]) + data_size = len(data)*4 + assert data_size > 0 + assert data_size < self.size, ( + "Firmware is too big! {} bytes > {} bytes".format( + data_size, self.size)) + print("Firmware {} bytes ({} bytes left)".format( + data_size, self.size-data_size)) + + self.init = data + @staticmethod def emit_verilog(memory, ns, add_data_file): - assert memory.init, "ROM contents not found! {}".format(memory.filename) + memory.load_init_data() return Memory.emit_verilog(memory, ns, add_data_file) class FirmwareROM(wishbone.SRAM): def __init__(self, size, filename): - if os.path.exists(filename): - data = [] - with open(filename, "rb") as firmware_file: - while True: - w = firmware_file.read(4) - if not w: - break - data.append(struct.unpack(">I", w)[0]) - data_size = len(data)*4 - assert data_size > 0 - assert data_size < size, ( - "Firmware is too big! {} bytes > {} bytes".format( - data_size, size)) - print("Firmware {} bytes ({} bytes left)".format( - data_size, size-data_size)) - wishbone.SRAM.__init__(self, size, init=data) - else: - print("No firmware found! ({}) Won't compile.".format( - filename)) - wishbone.SRAM.__init__(self, size) + wishbone.SRAM.__init__(self, size) + # Switch the rom memory class to be able to lazy load contents. self.mem.__class__ = MemoryMustHaveContents self.mem.filename = filename + self.mem.size = size diff --git a/platforms/sim.py b/platforms/sim.py index 713fb6a7b..87cc5e042 100644 --- a/platforms/sim.py +++ b/platforms/sim.py @@ -1,3 +1,64 @@ -from litex.boards.platforms import sim -from litex.boards.platforms.sim import * -__all__ = ['SimPins', 'Platform'] +from litex.build.generic_platform import * +from litex.build.sim import SimPlatform + +from litex.build.sim.config import SimConfig + +class SimPins(Pins): + def __init__(self, n): + Pins.__init__(self, "s "*n) + +_io = [ + ("sys_clk", 0, SimPins(1)), + ("sys_rst", 0, SimPins(1)), + ("serial", 0, + Subsignal("source_valid", SimPins(1)), + Subsignal("source_ready", SimPins(1)), + Subsignal("source_data", SimPins(8)), + + Subsignal("sink_valid", SimPins(1)), + Subsignal("sink_ready", SimPins(1)), + Subsignal("sink_data", SimPins(8)), + ), + ("eth_clocks", 0, + Subsignal("none", SimPins(1)), + ), + ("eth", 0, + Subsignal("source_valid", SimPins(1)), + Subsignal("source_ready", SimPins(1)), + Subsignal("source_data", SimPins(8)), + + Subsignal("sink_valid", SimPins(1)), + Subsignal("sink_ready", SimPins(1)), + Subsignal("sink_data", SimPins(8)), + ), + ("vga", 0, + Subsignal("de", SimPins(1)), + Subsignal("hsync", SimPins(1)), + Subsignal("vsync", SimPins(1)), + Subsignal("r", SimPins(8)), + Subsignal("g", SimPins(8)), + Subsignal("b", SimPins(8)), + ), +] + + +class Platform(SimPlatform): + default_clk_name = "sys_clk" + default_clk_period = 1000 # on modern computers simulate at ~ 1MHz + + def __init__(self): + SimPlatform.__init__(self, "SIM", _io) + + def do_finalize(self, fragment): + pass + + def build(self, fragment, **kwargs): + scfg = SimConfig(default_clk="sys_clk") + scfg.add_module("serial2console", "serial") + if hasattr(fragment, 'localip'): + scfg.add_module('ethernet', "eth", args={ "interface": "tap1", + "ip": fragment.localip }) + kwargs['sim_config'] = scfg + # Do not run the simulator after we build it + kwargs['run'] = False + return SimPlatform.build(self, fragment, **kwargs) diff --git a/targets/sim/base.py b/targets/sim/base.py index 7723ea59f..10b87b10f 100644 --- a/targets/sim/base.py +++ b/targets/sim/base.py @@ -1,4 +1,6 @@ # Support for simulation via verilator +import os + from migen import * from migen.genlib.io import CRG @@ -17,11 +19,6 @@ class BaseSoC(SoCSDRAM): - csr_peripherals = ( - , - ) - csr_map_update(SoCSDRAM.csr_map, csr_peripherals) - mem_map = { "firmware_ram": 0x20000000, # (default shadow @0xa0000000) } @@ -32,11 +29,12 @@ def __init__(self, platform, **kwargs): kwargs['integrated_rom_size']=0x8000 if 'integrated_sram_size' not in kwargs: kwargs['integrated_sram_size']=0x8000 - if 'firmware_ram_size' not in kwargs: - kwargs['firmware_ram_size']=0x10000 - if 'firmware_filename' not in kwargs: - kwargs['firmware_filename'] = "build/sim_{}_{}/software/firmware/firmware.fbi".format( - self.__class__.__name__.lower()[:-3], kwargs.get('cpu_type', 'lm32')) + + firmware_ram_size=0x20000 + firmware_filename="{}/build/sim_{}_{}/software/firmware/firmware.fbi".format( + os.getcwd(), + self.__class__.__name__.lower()[:-3], + kwargs.get('cpu_type', 'lm32')) clk_freq = int((1/(platform.default_clk_period))*1000000000) SoCSDRAM.__init__(self, platform, clk_freq, with_uart=False, **kwargs) @@ -76,5 +74,4 @@ def __init__(self, platform, **kwargs): self.add_constant("MEMTEST_ADDR_SIZE", 1024) self.add_constant("SIMULATION", 1) - SoC = BaseSoC diff --git a/targets/sim/net.py b/targets/sim/net.py index d8ffadf51..513e13a1e 100644 --- a/targets/sim/net.py +++ b/targets/sim/net.py @@ -22,7 +22,7 @@ class NetSoC(BaseSoC): csr_map.update(BaseSoC.csr_map) interrupt_map = { - "ethmac": 2, + "ethmac": 3, } interrupt_map.update(BaseSoC.interrupt_map) @@ -48,7 +48,9 @@ def configure_iprange(self, iprange): while len(iprange) < 4: iprange.append(0) # Our IP address - self._configure_ip("LOCALIP", iprange[:-1]+[50]) + localip = iprange[:-1]+[50] + self._configure_ip("LOCALIP", localip) + self.localip = ".".join(map(str, localip)) # IP address of tftp host self._configure_ip("REMOTEIP", iprange[:-1]+[100]) From a83155cd1629f7c6b46e68a6284834677e7c7982 Mon Sep 17 00:00:00 2001 From: Stafford Horne Date: Sat, 6 Oct 2018 07:25:20 +0900 Subject: [PATCH 2/6] Add travis configs for the sim build Now that sim should build, add some travis configs so we can keep it building. --- .travis.yml | 12 ++++++++++++ scripts/download-env.sh | 8 ++++++++ scripts/enter-env.sh | 8 ++++++++ 3 files changed, 28 insertions(+) diff --git a/.travis.yml b/.travis.yml index b085002ab..b93c8b27c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,6 +18,8 @@ addons: - python-yaml - realpath - util-linux + - libevent-dev + - libjson-c-dev git: submodules: false @@ -185,3 +187,13 @@ jobs: - stage: Targets env: C=lm32 P=opsis T="hdmi2usb" + + #-------------------------------------------- + # SIM/Verilator Targets + #-------------------------------------------- + - stage: Targets + env: C=or1k P=sim T="base" + + - stage: Targets + env: C=or1k P=sim T="base net" + diff --git a/scripts/download-env.sh b/scripts/download-env.sh index 99a409616..3cdb75f46 100755 --- a/scripts/download-env.sh +++ b/scripts/download-env.sh @@ -264,6 +264,14 @@ case $PLATFORM_TOOLCHAIN in conda install -y $CONDA_FLAGS nextpnr check_exists nextpnr-ice40 ;; + Sim) + export HAVE_FPGA_TOOLCHAIN=1 + # verilator + echo + echo "Installing verilator (Verilog Simulator tool)" + conda install -y $CONDA_FLAGS verilator + check_exists verilator + ;; *) ;; esac diff --git a/scripts/enter-env.sh b/scripts/enter-env.sh index 5002732a2..cdd2d1f9b 100755 --- a/scripts/enter-env.sh +++ b/scripts/enter-env.sh @@ -251,6 +251,14 @@ case $PLATFORM_TOOLCHAIN in check_exists nextpnr-ice40 || return 1 ;; + Sim) + export HAVE_FPGA_TOOLCHAIN=1 + # verilator + + + + check_exists verilator || return 1 + ;; *) ;; esac From d348c6f011cb1f9e314e564733c38333e8b802c2 Mon Sep 17 00:00:00 2001 From: Stafford Horne Date: Wed, 10 Oct 2018 12:48:52 +0900 Subject: [PATCH 3/6] sim: Support CPU_VARIANT for finding firmware --- targets/sim/base.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/targets/sim/base.py b/targets/sim/base.py index 10b87b10f..1fb047d9e 100644 --- a/targets/sim/base.py +++ b/targets/sim/base.py @@ -31,10 +31,15 @@ def __init__(self, platform, **kwargs): kwargs['integrated_sram_size']=0x8000 firmware_ram_size=0x20000 + + full_cpu = kwargs.get('cpu_type', 'lm32') + if 'cpu_variant' in kwargs: + full_cpu = "{}.{}".format(full_cpu, kwargs['cpu_variant']) + firmware_filename="{}/build/sim_{}_{}/software/firmware/firmware.fbi".format( os.getcwd(), self.__class__.__name__.lower()[:-3], - kwargs.get('cpu_type', 'lm32')) + full_cpu) clk_freq = int((1/(platform.default_clk_period))*1000000000) SoCSDRAM.__init__(self, platform, clk_freq, with_uart=False, **kwargs) From 4ff397b27adc3d07ead99c125c54d2190c9f2606 Mon Sep 17 00:00:00 2001 From: Stafford Horne Date: Wed, 10 Oct 2018 12:49:48 +0900 Subject: [PATCH 4/6] sim: Fix IPRANGE variable name --- targets/sim/Makefile.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/targets/sim/Makefile.mk b/targets/sim/Makefile.mk index 021109686..2c89492f9 100644 --- a/targets/sim/Makefile.mk +++ b/targets/sim/Makefile.mk @@ -56,7 +56,7 @@ reset-$(PLATFORM): $(PLATFORM)-setup: sudo true sudo openvpn --mktun --dev tap0 - sudo ifconfig tap0 $(IPRANGE).100 up + sudo ifconfig tap0 $(TFTP_IPRANGE).100 up sudo mknod /dev/net/tap0 c 10 200 sudo chown $(shell whoami) /dev/net/tap0 make tftpd_start From 01effa793d1ae1799c82946a4dd5f38a6773fb1f Mon Sep 17 00:00:00 2001 From: Stafford Horne Date: Wed, 10 Oct 2018 16:57:49 +0900 Subject: [PATCH 5/6] sim: Fix networking I was thinking the TAP binds to the localIP, but it binds to the remote. Then we just need to run `make tftpd_start` and it will bind to the remote which is created by the Simulator TAP. --- platforms/sim.py | 6 +++--- targets/sim/Makefile.mk | 20 +------------------- targets/sim/net.py | 12 ++++++++---- 3 files changed, 12 insertions(+), 26 deletions(-) diff --git a/platforms/sim.py b/platforms/sim.py index 87cc5e042..6f55b9dfd 100644 --- a/platforms/sim.py +++ b/platforms/sim.py @@ -55,9 +55,9 @@ def do_finalize(self, fragment): def build(self, fragment, **kwargs): scfg = SimConfig(default_clk="sys_clk") scfg.add_module("serial2console", "serial") - if hasattr(fragment, 'localip'): - scfg.add_module('ethernet', "eth", args={ "interface": "tap1", - "ip": fragment.localip }) + if hasattr(fragment, 'remoteip'): + scfg.add_module('ethernet', "eth", args={ "interface": "tap0", + "ip": fragment.remoteip }) kwargs['sim_config'] = scfg # Do not run the simulator after we build it kwargs['run'] = False diff --git a/targets/sim/Makefile.mk b/targets/sim/Makefile.mk index 2c89492f9..96138e48b 100644 --- a/targets/sim/Makefile.mk +++ b/targets/sim/Makefile.mk @@ -46,26 +46,8 @@ bios-flash-$(PLATFORM): # Extra commands help-$(PLATFORM): - @echo " make $(PLATFORM)-setup" - @echo " make $(PLATFORM)-teardown" + @true reset-$(PLATFORM): @echo "Unsupported." @false - -$(PLATFORM)-setup: - sudo true - sudo openvpn --mktun --dev tap0 - sudo ifconfig tap0 $(TFTP_IPRANGE).100 up - sudo mknod /dev/net/tap0 c 10 200 - sudo chown $(shell whoami) /dev/net/tap0 - make tftpd_start - -$(PLATFORM)-teardown: - sudo true - make tftpd_stop - sudo rm -f /dev/net/tap0 - sudo ifconfig tap0 down - sudo openvpn --rmtun --dev tap0 - -.PHONY: $(PLATFORM)-setup $(PLATFORM)-teardown diff --git a/targets/sim/net.py b/targets/sim/net.py index 513e13a1e..391a20572 100644 --- a/targets/sim/net.py +++ b/targets/sim/net.py @@ -43,16 +43,20 @@ def __init__(self, *args, **kwargs): self.add_wb_slave(mem_decoder(self.mem_map["ethmac"]), self.ethmac.bus) self.add_memory_region("ethmac", self.mem_map["ethmac"] | self.shadow_base, 0x2000) + # Disable the flash boot address under the net target, so we boot from + # net + self.flash_boot_address = None + def configure_iprange(self, iprange): iprange = [int(x) for x in iprange.split(".")] while len(iprange) < 4: iprange.append(0) # Our IP address - localip = iprange[:-1]+[50] - self._configure_ip("LOCALIP", localip) - self.localip = ".".join(map(str, localip)) + self._configure_ip("LOCALIP", iprange[:-1]+[50]) # IP address of tftp host - self._configure_ip("REMOTEIP", iprange[:-1]+[100]) + remoteip = iprange[:-1]+[100] + self.remoteip = ".".join(map(str, remoteip)) + self._configure_ip("REMOTEIP", remoteip) def _configure_ip(self, ip_type, ip): for i, e in enumerate(ip): From 185dcbdd48be828875121747980cdd0a2c8cee5b Mon Sep 17 00:00:00 2001 From: Stafford Horne Date: Thu, 11 Oct 2018 12:46:15 +0900 Subject: [PATCH 6/6] litex: Update litex version to get fixes for sim --- third_party/litex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/third_party/litex b/third_party/litex index 6e327cda2..915c2f417 160000 --- a/third_party/litex +++ b/third_party/litex @@ -1 +1 @@ -Subproject commit 6e327cda2697d37b23f607a5a7712363dc60857a +Subproject commit 915c2f417ad87389c4ac531603e1d7763397e214