1 # This file is Copyright (c) 2015 Florent Kermarrec <florent@enjoy-digital.fr>
7 from litex
.gen
.fhdl
.structure
import _Fragment
8 from litex
.build
import tools
9 from litex
.build
.generic_platform
import *
12 sim_directory
= os
.path
.abspath(os
.path
.dirname(__file__
))
15 def _build_tb(platform
, vns
, serial
, template
):
16 def io_name(resource
, subsignal
=None):
17 res
= platform
.lookup_request(resource
)
18 if subsignal
is not None:
19 res
= getattr(res
, subsignal
)
20 return vns
.get_name(res
)
23 #define SYS_CLK dut->{sys_clk}
24 """.format(sys_clk
=io_name("sys_clk"))
27 ios
+= "#define WITH_SERIAL_PTY"
28 elif serial
== "console":
34 #define SERIAL_SOURCE_VALID dut->{serial_source_valid}
35 #define SERIAL_SOURCE_READY dut->{serial_source_ready}
36 #define SERIAL_SOURCE_DATA dut->{serial_source_data}
38 #define SERIAL_SINK_VALID dut->{serial_sink_valid}
39 #define SERIAL_SINK_READY dut->{serial_sink_ready}
40 #define SERIAL_SINK_DATA dut->{serial_sink_data}
42 serial_source_valid
=io_name("serial", "source_valid"),
43 serial_source_ready
=io_name("serial", "source_ready"),
44 serial_source_data
=io_name("serial", "source_data"),
46 serial_sink_valid
=io_name("serial", "sink_valid"),
47 serial_sink_ready
=io_name("serial", "sink_ready"),
48 serial_sink_data
=io_name("serial", "sink_data"),
55 #define ETH_SOURCE_VALID dut->{eth_source_valid}
56 #define ETH_SOURCE_READY dut->{eth_source_ready}
57 #define ETH_SOURCE_DATA dut->{eth_source_data}
59 #define ETH_SINK_VALID dut->{eth_sink_valid}
60 #define ETH_SINK_READY dut->{eth_sink_ready}
61 #define ETH_SINK_DATA dut->{eth_sink_data}
63 eth_source_valid
=io_name("eth", "source_valid"),
64 eth_source_ready
=io_name("eth", "source_ready"),
65 eth_source_data
=io_name("eth", "source_data"),
67 eth_sink_valid
=io_name("eth", "sink_valid"),
68 eth_sink_ready
=io_name("eth", "sink_ready"),
69 eth_sink_data
=io_name("eth", "sink_data"),
75 f
= open(template
, "r")
79 if "/* ios */" in l
and not done
:
84 tools
.write_to_file("dut_tb.cpp", content
)
87 def _build_sim(platform
, vns
, build_name
, include_paths
, serial
, verbose
):
89 for path
in include_paths
:
90 include
+= "-I"+path
+" "
92 build_script_contents
= """# Autogenerated by LiteX
94 verilator {disable_warnings} -O3 --cc dut.v --exe dut_tb.cpp -LDFLAGS "-lpthread" -trace {include}
95 make -j -C obj_dir/ -f Vdut.mk Vdut
98 disable_warnings
="-Wno-fatal",
100 build_script_file
= "build_" + build_name
+ ".sh"
101 tools
.write_to_file(build_script_file
, build_script_contents
, force_unix
=True)
103 _build_tb(platform
, vns
, serial
, os
.path
.join(sim_directory
, "dut_tb.cpp"))
104 p
= subprocess
.Popen(["bash", build_script_file
], stdout
=subprocess
.PIPE
, stderr
=subprocess
.STDOUT
)
105 output
, _
= p
.communicate()
106 output
= output
.decode('utf-8')
107 if p
.returncode
!= 0:
109 for l
in output
.splitlines():
110 if verbose
or "error" in l
.lower():
111 error_messages
.append(l
)
112 raise OSError("Subprocess failed with {}\n{}".format(p
.returncode
, "\n".join(error_messages
)))
117 def _run_sim(build_name
):
118 run_script_contents
= """obj_dir/Vdut
120 run_script_file
= "run_" + build_name
+ ".sh"
121 tools
.write_to_file(run_script_file
, run_script_contents
, force_unix
=True)
122 r
= subprocess
.call(["bash", run_script_file
])
124 raise OSError("Subprocess failed")
127 class SimVerilatorToolchain
:
128 def build(self
, platform
, fragment
, build_dir
="build", build_name
="top",
129 toolchain_path
=None, serial
="console", run
=True, verbose
=False):
130 tools
.mkdir_noerror(build_dir
)
133 if not isinstance(fragment
, _Fragment
):
134 fragment
= fragment
.get_fragment()
135 platform
.finalize(fragment
)
137 v_output
= platform
.get_verilog(fragment
)
138 named_sc
, named_pc
= platform
.resolve_signals(v_output
.ns
)
139 v_output
.write("dut.v")
142 for source
in platform
.sources
:
143 path
= os
.path
.dirname(source
[0]).replace("\\", "\/")
144 if path
not in include_paths
:
145 include_paths
.append(path
)
146 include_paths
+= platform
.verilog_include_paths
147 _build_sim(platform
, v_output
.ns
, build_name
, include_paths
, serial
, verbose
)