# This file is Copyright (c) 2015 Florent Kermarrec # 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} """.format(sys_clk=io_name("sys_clk")) try: ios += """ #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( 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"), ) except: pass try: ios += """ #define ETH_SOURCE_STB dut->{eth_source_stb} #define ETH_SOURCE_ACK dut->{eth_source_ack} #define ETH_SOURCE_DATA dut->{eth_source_data} #define ETH_SINK_STB dut->{eth_sink_stb} #define ETH_SINK_ACK dut->{eth_sink_ack} #define ETH_SINK_DATA dut->{eth_sink_data} """.format( eth_source_stb=io_name("eth", "source_stb"), eth_source_ack=io_name("eth", "source_ack"), eth_source_data=io_name("eth", "source_data"), eth_sink_stb=io_name("eth", "sink_stb"), eth_sink_ack=io_name("eth", "sink_ack"), eth_sink_data=io_name("eth", "sink_data"), ) except: pass 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="dut_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("..")