hdl.ir, back.rtlil: allow specifying attributes on instances.

Fixes #107.
This commit is contained in:
whitequark 2019-06-28 04:14:38 +00:00
parent 2b92f12016
commit 48d4ee4031
4 changed files with 28 additions and 5 deletions

View file

@ -106,9 +106,11 @@ class _ModuleBuilder(_Namer, _Bufferer):
self._append(" memory width {} size {} {}\n", width, size, name)
return name
def cell(self, kind, name=None, params={}, ports={}, src=""):
def cell(self, kind, name=None, params={}, ports={}, attrs={}, src=""):
self._src(src)
name = self._make_name(name, local=False)
for attr_name, attr_value in attrs.items():
self.attribute(attr_name, attr_value)
self._append(" cell {} {}\n", kind, name)
for param, value in params.items():
if isinstance(value, str):
@ -678,7 +680,7 @@ def convert_fragment(builder, fragment, hierarchy):
return "\\{}".format(fragment.type), port_map
module_name = hierarchy[-1] or "anonymous"
module_attrs = {}
module_attrs = OrderedDict()
if len(hierarchy) == 1:
module_attrs["top"] = 1
module_attrs["nmigen.hierarchy"] = ".".join(name or "anonymous" for name in hierarchy)
@ -761,7 +763,8 @@ def convert_fragment(builder, fragment, hierarchy):
compiler_state.resolve_curr(signal, prefix=sub_name)
sub_ports[port] = rhs_compiler(value)
module.cell(sub_type, name=sub_name, ports=sub_ports, params=sub_params)
module.cell(sub_type, name=sub_name, ports=sub_ports, params=sub_params,
attrs=subfragment.attrs)
# If we emit all of our combinatorial logic into a single RTLIL process, Verilog
# simulators will break horribly, because Yosys write_verilog transforms RTLIL processes

View file

@ -71,6 +71,7 @@ class Fragment:
self.statements = []
self.domains = OrderedDict()
self.subfragments = []
self.attrs = OrderedDict()
self.generated = OrderedDict()
self.flatten = False
@ -528,7 +529,9 @@ class Instance(Fragment):
self.named_ports = OrderedDict()
for (kind, name, value) in args:
if kind == "p":
if kind == "a":
self.attrs[name] = value
elif kind == "p":
self.parameters[name] = value
elif kind in ("i", "o", "io"):
self.named_ports[name] = (value, kind)
@ -538,7 +541,9 @@ class Instance(Fragment):
.format((kind, name, value)))
for kw, arg in kwargs.items():
if kw.startswith("p_"):
if kw.startswith("a_"):
self.attrs[kw[2:]] = arg
elif kw.startswith("p_"):
self.parameters[kw[2:]] = arg
elif kw.startswith("i_"):
self.named_ports[kw[2:]] = (arg, "i")

View file

@ -274,6 +274,7 @@ class FragmentTransformer:
else:
new_fragment = Fragment()
new_fragment.flatten = fragment.flatten
new_fragment.attrs = OrderedDict(fragment.attrs)
self.map_ports(fragment, new_fragment)
self.map_subfragments(fragment, new_fragment)
self.map_domains(fragment, new_fragment)

View file

@ -555,15 +555,21 @@ class InstanceTestCase(FHDLTestCase):
s5 = Signal()
s6 = Signal()
inst = Instance("foo",
("a", "ATTR1", 1),
("p", "PARAM1", 0x1234),
("i", "s1", s1),
("o", "s2", s2),
("io", "s3", s3),
a_ATTR2=2,
p_PARAM2=0x5678,
i_s4=s4,
o_s5=s5,
io_s6=s6,
)
self.assertEqual(inst.attrs, OrderedDict([
("ATTR1", 1),
("ATTR2", 2),
]))
self.assertEqual(inst.parameters, OrderedDict([
("PARAM1", 0x1234),
("PARAM2", 0x5678),
@ -648,3 +654,11 @@ class InstanceTestCase(FHDLTestCase):
self.assertEqual(fp.ports, SignalDict([
(s, "o"),
]))
def test_prepare_attrs(self):
self.setUp_cpu()
self.inst.attrs["ATTR"] = 1
f = self.inst.prepare()
self.assertEqual(f.attrs, OrderedDict([
("ATTR", 1),
]))