hdl.ir, back.rtlil: allow specifying attributes on instances.
Fixes #107.
This commit is contained in:
parent
2b92f12016
commit
48d4ee4031
|
@ -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
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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),
|
||||
]))
|
||||
|
|
Loading…
Reference in a new issue