From ec80024e556a7c05736668e283b44cb007f48c5c Mon Sep 17 00:00:00 2001 From: whitequark Date: Fri, 28 Jun 2019 04:14:38 +0000 Subject: [PATCH] hdl.ir, back.rtlil: allow specifying attributes on instances. Fixes #107. --- nmigen/back/rtlil.py | 9 ++++++--- nmigen/hdl/ir.py | 9 +++++++-- nmigen/hdl/xfrm.py | 1 + nmigen/test/test_hdl_ir.py | 14 ++++++++++++++ 4 files changed, 28 insertions(+), 5 deletions(-) diff --git a/nmigen/back/rtlil.py b/nmigen/back/rtlil.py index a33630a..7537820 100644 --- a/nmigen/back/rtlil.py +++ b/nmigen/back/rtlil.py @@ -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 diff --git a/nmigen/hdl/ir.py b/nmigen/hdl/ir.py index 5135544..2e9fbe1 100644 --- a/nmigen/hdl/ir.py +++ b/nmigen/hdl/ir.py @@ -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") diff --git a/nmigen/hdl/xfrm.py b/nmigen/hdl/xfrm.py index b27de27..53b3344 100644 --- a/nmigen/hdl/xfrm.py +++ b/nmigen/hdl/xfrm.py @@ -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) diff --git a/nmigen/test/test_hdl_ir.py b/nmigen/test/test_hdl_ir.py index 7f03a62..b30238f 100644 --- a/nmigen/test/test_hdl_ir.py +++ b/nmigen/test/test_hdl_ir.py @@ -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), + ])) -- 2.30.2