gen/fhdl/verilog: add regular comb parameter to allow implementation of simulation code (for icarus)

We will remove that when we will be using new migen simulator
This commit is contained in:
Florent Kermarrec 2015-12-02 12:37:53 +01:00
parent 646d3b19b4
commit b7a1888a36
3 changed files with 52 additions and 21 deletions

View File

@ -9,7 +9,7 @@ from litex.gen.fhdl.bitcontainer import bits_for
from litex.gen.fhdl.namer import build_namespace from litex.gen.fhdl.namer import build_namespace
from litex.gen.fhdl.conv_output import ConvOutput from litex.gen.fhdl.conv_output import ConvOutput
# TODO: clean up simulation hack # TODO: remove printcomb_simulation when we will be using new migen simulator
_reserved_keywords = { _reserved_keywords = {
"always", "and", "assign", "automatic", "begin", "buf", "bufif0", "bufif1", "always", "and", "assign", "automatic", "begin", "buf", "bufif0", "bufif1",
@ -207,10 +207,10 @@ def _printheader(f, ios, name, ns,
return r return r
def _printcomb(f, ns, def _printcomb_simulation(f, ns,
display_run, display_run,
dummy_signal, dummy_signal,
blocking_assign): blocking_assign):
r = "" r = ""
if f.comb: if f.comb:
if dummy_signal: if dummy_signal:
@ -251,20 +251,44 @@ def _printcomb(f, ns,
if display_run: if display_run:
r += "\t$display(\"Running comb block #" + str(n) + "\");\n" r += "\t$display(\"Running comb block #" + str(n) + "\");\n"
if blocking_assign: if blocking_assign:
r += "\t" + ns.get_name(t) + " = " + _printexpr(ns, t.reset)[0] + ";\n" r += "\t" + ns.get_name(t) + " = " + _printexpr(ns, t.reset)[0] + ";\n"
r += _printnode(ns, _AT_BLOCKING, 1, stmts, t) r += _printnode(ns, _AT_BLOCKING, 1, stmts, t)
else: else:
r += "\t" + ns.get_name(t) + " <= " + _printexpr(ns, t.reset)[0] + ";\n" r += "\t" + ns.get_name(t) + " <= " + _printexpr(ns, t.reset)[0] + ";\n"
r += _printnode(ns, _AT_NONBLOCKING, 1, stmts, t) r += _printnode(ns, _AT_NONBLOCKING, 1, stmts, t)
if dummy_signal: if dummy_signal:
r += syn_off r += syn_off
r += "\t" + ns.get_name(dummy_d) + " = " + ns.get_name(dummy_s) + ";\n" r += "\t" + ns.get_name(dummy_d) + " = " + ns.get_name(dummy_s) + ";\n"
r += syn_on r += syn_on
r += "end\n" r += "end\n"
r += "\n" r += "\n"
return r return r
def _printcomb_regular(f, ns, blocking_assign):
r = ""
if f.comb:
groups = group_by_targets(f.comb)
for n, g in enumerate(groups):
if len(g[1]) == 1 and isinstance(g[1][0], _Assign):
r += "assign " + _printnode(ns, _AT_BLOCKING, 0, g[1][0])
else:
r += "always @(*) begin\n"
if blocking_assign:
for t in g[0]:
r += "\t" + ns.get_name(t) + " = " + _printexpr(ns, t.reset)[0] + ";\n"
r += _printnode(ns, _AT_BLOCKING, 1, g[1])
else:
for t in g[0]:
r += "\t" + ns.get_name(t) + " <= " + _printexpr(ns, t.reset)[0] + ";\n"
r += _printnode(ns, _AT_NONBLOCKING, 1, g[1])
r += "end\n"
r += "\n"
return r
def _printsync(f, ns): def _printsync(f, ns):
r = "" r = ""
for k, v in sorted(f.sync.items(), key=itemgetter(0)): for k, v in sorted(f.sync.items(), key=itemgetter(0)):
@ -331,7 +355,8 @@ def convert(f, ios=None, name="top",
display_run=False, display_run=False,
reg_initialization=True, reg_initialization=True,
dummy_signal=True, dummy_signal=True,
blocking_assign=False): blocking_assign=False,
regular_comb=True):
r = ConvOutput() r = ConvOutput()
if not isinstance(f, _Fragment): if not isinstance(f, _Fragment):
f = f.get_fragment() f = f.get_fragment()
@ -361,10 +386,16 @@ def convert(f, ios=None, name="top",
ns.clock_domains = f.clock_domains ns.clock_domains = f.clock_domains
r.ns = ns r.ns = ns
src = "/* Machine-generated using LiteX gen*/\n" src = "/* Machine-generated using LiteX gen "
src += "(regular)" if regular_comb else "(simulation)"
src += " */\n"
src += _printheader(f, ios, name, ns, src += _printheader(f, ios, name, ns,
reg_initialization=reg_initialization) reg_initialization=reg_initialization)
src += _printcomb(f, ns, if regular_comb:
src += _printcomb_regular(f, ns,
blocking_assign=blocking_assign)
else:
src += _printcomb_simulation(f, ns,
display_run=display_run, display_run=display_run,
dummy_signal=dummy_signal, dummy_signal=dummy_signal,
blocking_assign=blocking_assign) blocking_assign=blocking_assign)

View File

@ -102,6 +102,7 @@ class Simulator:
c_fragment = verilog.convert(fragment, c_fragment = verilog.convert(fragment,
ios=self.top_level.ios, ios=self.top_level.ios,
name=self.top_level.dut_type, name=self.top_level.dut_type,
regular_comb=False,
**vopts) **vopts)
self.namespace = c_fragment.ns self.namespace = c_fragment.ns

View File

@ -130,7 +130,7 @@ class Builder:
boot_data.append(struct.unpack(">I", w)[0]) boot_data.append(struct.unpack(">I", w)[0])
self.soc.initialize_rom(boot_data) self.soc.initialize_rom(boot_data)
def build(self): def build(self, toolchain_path=None, **kwargs):
self.soc.finalize() self.soc.finalize()
os.makedirs(self.output_dir, exist_ok=True) os.makedirs(self.output_dir, exist_ok=True)
@ -145,12 +145,11 @@ class Builder:
self._generate_software() self._generate_software()
self._initialize_rom() self._initialize_rom()
if self.gateware_toolchain_path is None: if self.gateware_toolchain_path is not None:
kwargs = dict() toolchain_path = self.gateware_toolchain_path
else:
kwargs = {"toolchain_path": self.gateware_toolchain_path}
self.soc.build(build_dir=os.path.join(self.output_dir, "gateware"), self.soc.build(build_dir=os.path.join(self.output_dir, "gateware"),
run=self.compile_gateware, **kwargs) run=self.compile_gateware, toolchain_path=toolchain_path,
**kwargs)
def builder_args(parser): def builder_args(parser):