Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: litex: sim: Get sim working in litex-buildenv #82

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ addons:
- python-yaml
- realpath
- util-linux
- libevent-dev
- libjson-c-dev

git:
submodules: false
Expand Down Expand Up @@ -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"

46 changes: 25 additions & 21 deletions gateware/firmware.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
67 changes: 64 additions & 3 deletions platforms/sim.py
Original file line number Diff line number Diff line change
@@ -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, '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
return SimPlatform.build(self, fragment, **kwargs)
8 changes: 8 additions & 0 deletions scripts/download-env.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 8 additions & 0 deletions scripts/enter-env.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
20 changes: 1 addition & 19 deletions targets/sim/Makefile.mk
Original file line number Diff line number Diff line change
Expand Up @@ -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 $(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
24 changes: 13 additions & 11 deletions targets/sim/base.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# Support for simulation via verilator
import os

from migen import *
from migen.genlib.io import CRG

Expand All @@ -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)
}
Expand All @@ -32,11 +29,17 @@ 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

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(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There should be a better way to get the firmware name here. But I can't figure out how to pass it in make.py yet.

os.getcwd(),
self.__class__.__name__.lower()[:-3],
full_cpu)

clk_freq = int((1/(platform.default_clk_period))*1000000000)
SoCSDRAM.__init__(self, platform, clk_freq, with_uart=False, **kwargs)
Expand Down Expand Up @@ -76,5 +79,4 @@ def __init__(self, platform, **kwargs):
self.add_constant("MEMTEST_ADDR_SIZE", 1024)
self.add_constant("SIMULATION", 1)


SoC = BaseSoC
10 changes: 8 additions & 2 deletions targets/sim/net.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand All @@ -43,14 +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
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):
Expand Down