sim: basic functionality working
This commit is contained in:
parent
c4c22c9ca0
commit
aac9752558
|
@ -0,0 +1,19 @@
|
|||
from migen.fhdl.structure import *
|
||||
from migen.sim.generic import Simulator
|
||||
from migen.sim.icarus import Runner
|
||||
|
||||
class Counter:
|
||||
def __init__(self):
|
||||
self.count = Signal(BV(4))
|
||||
|
||||
def do_simulation(self, s, cycle):
|
||||
print("Cycle: " + str(cycle) + " Count: " + str(s.rd(self.count)))
|
||||
|
||||
def get_fragment(self):
|
||||
sync = [self.count.eq(self.count + 1)]
|
||||
sim = [self.do_simulation]
|
||||
return Fragment(sync=sync, sim=sim)
|
||||
|
||||
dut = Counter()
|
||||
sim = Simulator(dut.get_fragment(), Runner())
|
||||
sim.run(10)
|
|
@ -0,0 +1,104 @@
|
|||
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))
|
|
@ -0,0 +1,21 @@
|
|||
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])
|
Loading…
Reference in New Issue