hdl.ir, back.rtlil: allow specifying attributes on instances.
authorwhitequark <cz@m-labs.hk>
Fri, 28 Jun 2019 04:14:38 +0000 (04:14 +0000)
committerwhitequark <cz@m-labs.hk>
Fri, 28 Jun 2019 04:14:38 +0000 (04:14 +0000)
Fixes #107.

nmigen/back/rtlil.py
nmigen/hdl/ir.py
nmigen/hdl/xfrm.py
nmigen/test/test_hdl_ir.py

index a33630abac558c2d6dc94fe4363a045db6f756d1..7537820553fd48dd75ebeef53ec04bb09cb49558 100644 (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
index 513554481192538cb07a6ad1629ace7fb7f5b07a..2e9fbe1d5a78fc185ffaa239e125401ca7a5362f 100644 (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")
index b27de27fbf6748db516ccbd839854de1adcfefbc..53b3344a4a5acd1f586f0c419f3d469ef4d5f195 100644 (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)
index 7f03a62b112fea66132fbd0f6ccdb4c6b7925463..b30238f70095e559362ac980ca362b0ee1c79229 100644 (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),
+        ]))