--- /dev/null
+from migen.fhdl.structure import *
+from migen.fhdl import verilog
+from migen.sim.ipc import *
+
+class TopLevel:
+ def __init__(self, top_name="top", dut_type="dut", dut_name="dut", clk_name="sys_clk",
+ clk_period=10, rst_name="sys_rst"):
+ self.top_name = top_name
+ self.dut_type = dut_type
+ self.dut_name = dut_name
+ self.clk_name = clk_name
+ self.clk_period = clk_period
+ self.rst_name = rst_name
+
+ def get(self, sockaddr):
+ template = """module {top_name}();
+
+reg {clk_name};
+reg {rst_name};
+
+initial begin
+ {rst_name} <= 1'b1;
+ @(posedge {clk_name});
+ {rst_name} <= 1'b0;
+end
+
+always begin
+ {clk_name} <= 1'b0;
+ #{hclk_period};
+ {clk_name} <= 1'b1;
+ #{hclk_period};
+end
+
+{dut_type} {dut_name}(
+ .{rst_name}({rst_name}),
+ .{clk_name}({clk_name})
+);
+
+initial $migensim_connect("{sockaddr}");
+always @(posedge {clk_name}) $migensim_tick;
+
+endmodule
+"""
+ return template.format(top_name=self.top_name,
+ dut_type=self.dut_type,
+ dut_name=self.dut_name,
+ clk_name=self.clk_name,
+ hclk_period=str(self.clk_period/2),
+ rst_name=self.rst_name,
+ sockaddr=sockaddr)
+
+class Simulator:
+ def __init__(self, fragment, sim_runner, top_level=None, sockaddr="simsocket"):
+ self.fragment = fragment
+ if top_level is None:
+ self.top_level = TopLevel()
+ else:
+ self.top_level = top_level
+ self.ipc = Initiator(sockaddr)
+
+ c_top = self.top_level.get(sockaddr)
+
+ clk_signal = Signal(name_override=self.top_level.clk_name)
+ rst_signal = Signal(name_override=self.top_level.rst_name)
+ c_fragment, self.namespace = verilog.convert(fragment,
+ {clk_signal, rst_signal},
+ name=self.top_level.dut_type,
+ clk_signal=clk_signal,
+ rst_signal=rst_signal,
+ return_ns=True)
+
+ sim_runner.start(c_top, c_fragment)
+ self.ipc.accept()
+ self.cycle_counter = 0
+ self.interrupt = False
+ self.fragment.call_sim(self, 0)
+ self.ipc.send(MessageGo())
+
+ def run(self, ncycles=-1):
+ counter = 0
+ while not self.interrupt and (ncycles < 0 or counter < ncycles):
+ reply = self.ipc.recv()
+ assert(isinstance(reply, MessageTick))
+ self.cycle_counter += 1
+ counter += 1
+ self.fragment.call_sim(self, self.cycle_counter)
+ self.ipc.send(MessageGo())
+
+ def rd(self, signal):
+ name = self.top_level.top_name + "." \
+ + self.top_level.dut_name + "." \
+ + self.namespace.get_name(signal)
+ self.ipc.send(MessageRead(name))
+ reply = self.ipc.recv()
+ assert(isinstance(reply, MessageReadReply))
+ # TODO: negative numbers + cleanup LSBs
+ return reply.value
+
+ def wr(self, signal, value):
+ name = self.top_level.top_name + "." \
+ + self.top_level.dut_name + "." \
+ + self.namespace.get_name(signal)
+ # TODO: negative numbers
+ self.ipc.send(MessageWrite(name, value))
--- /dev/null
+import subprocess
+
+def _str2file(filename, contents):
+ f = open(filename, "w")
+ f.write(contents)
+ f.close()
+
+class Runner:
+ def __init__(self, top_file="migensim_top.v", dut_file="migensim_dut.v", extra_files=None, vvp_file=None):
+ if extra_files is None: extra_files = []
+ if vvp_file is None: vvp_file = dut_file + "vp"
+ self.top_file = top_file
+ self.dut_file = dut_file
+ self.extra_files = extra_files
+ self.vvp_file = vvp_file
+
+ def start(self, c_top, c_dut):
+ _str2file(self.top_file, c_top)
+ _str2file(self.dut_file, c_dut)
+ subprocess.check_call(["iverilog", "-o", self.vvp_file, self.top_file, self.dut_file] + self.extra_files)
+ subprocess.Popen(["vvp", "-mmigensim", self.vvp_file])