litex/mibuild/sim/verilator.py
Florent Kermarrec 991572f4fe mibuild/sim: create server.py and server_tb (Proof of concept OK with flterm)
Using a server allow us to create a virtual UART (and ethernet TAP in the future).

1) start the server
2) start flterm on the virtual serial port created by the server
3) run the simulation

This will enable us to do serialboot and netboot in simulation.
This will also enable prototyping  ethernet for ARTIQ in simulation.
2015-03-03 17:38:22 +01:00

113 lines
3.3 KiB
Python

# This file is Copyright (c) 2015 Florent Kermarrec <florent@enjoy-digital.fr>
# License: BSD
import os, subprocess
from migen.fhdl.std import *
from migen.fhdl.structure import _Fragment
from mibuild.generic_platform import *
def _build_tb(platform, template):
def io_name(ressource, subsignal=None):
res = platform.lookup_request(ressource)
if subsignal is not None:
res = getattr(res, subsignal)
return platform.vns.get_name(res)
ios = """
#define SYS_CLK dut->{sys_clk}
#define SERIAL_SOURCE_STB dut->{serial_source_stb}
#define SERIAL_SOURCE_ACK dut->{serial_source_ack}
#define SERIAL_SOURCE_DATA dut->{serial_source_data}
#define SERIAL_SINK_STB dut->{serial_sink_stb}
#define SERIAL_SINK_ACK dut->{serial_sink_ack}
#define SERIAL_SINK_DATA dut->{serial_sink_data}
""".format(
sys_clk=io_name("sys_clk"),
serial_source_stb=io_name("serial", "source_stb"),
serial_source_ack=io_name("serial", "source_ack"),
serial_source_data=io_name("serial", "source_data"),
serial_sink_stb=io_name("serial", "sink_stb"),
serial_sink_ack=io_name("serial", "sink_ack"),
serial_sink_data=io_name("serial", "sink_data"),
)
content = ""
f = open(template, "r")
done = False
for l in f:
content += l
if "/* ios */" in l and not done:
content += ios
done = True
f.close()
tools.write_to_file("dut_tb.cpp", content)
def _build_sim(platform, build_name, include_paths, sim_path, dut, verbose):
include = ""
for path in include_paths:
include += "-I"+path+" "
build_script_contents = """# Autogenerated by mibuild
rm -rf obj_dir/
verilator {disable_warnings} -O3 --cc dut.v --exe dut_tb.cpp -LDFLAGS "-lpthread" -trace {include}
make -j -C obj_dir/ -f Vdut.mk Vdut
""".format(
disable_warnings="-Wno-fatal",
include=include)
build_script_file = "build_" + build_name + ".sh"
tools.write_to_file(build_script_file, build_script_contents, force_unix=True)
_build_tb(platform, os.path.join("../", sim_path, dut + ".cpp")) # XXX
if verbose:
r = subprocess.call(["bash", build_script_file])
else:
r = subprocess.call(["bash", build_script_file], stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
if r != 0:
raise OSError("Subprocess failed")
def _run_sim(build_name):
run_script_contents = """obj_dir/Vdut
"""
run_script_file = "run_" + build_name + ".sh"
tools.write_to_file(run_script_file, run_script_contents, force_unix=True)
r = subprocess.call(["bash", run_script_file])
if r != 0:
raise OSError("Subprocess failed")
class VerilatorPlatform(GenericPlatform):
# XXX fir sim_path
def build(self, soc, build_dir="build", build_name="top",
sim_path="../migen/mibuild/sim/", dut="console_tb",
run=True, verbose=False):
tools.mkdir_noerror(build_dir)
os.chdir(build_dir)
self.soc = soc
fragment = soc.get_fragment()
self.finalize(fragment)
v_src, vns = self.get_verilog(fragment)
named_sc, named_pc = self.resolve_signals(vns)
self.vns = vns
v_file = "dut.v"
tools.write_to_file(v_file, v_src)
include_paths = []
for source in self.sources:
path = os.path.dirname(source[0]).replace("\\", "\/")
if path not in include_paths:
include_paths.append(path)
include_paths += self.verilog_include_paths
_build_sim(self, build_name, include_paths, sim_path, dut, verbose)
if run:
_run_sim(build_name)
os.chdir("..")