hdl._ir: raise an error when an elaboratable is duplicated in hierarchy.
Fixes #1194.
This commit is contained in:
parent
2cf9bbf306
commit
466536efcf
|
@ -9,8 +9,8 @@ from . import _ast, _cd, _ir, _nir
|
||||||
|
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"UnusedElaboratable", "Elaboratable", "DriverConflict", "Fragment", "Instance",
|
"UnusedElaboratable", "Elaboratable", "DuplicateElaboratable", "DriverConflict", "Fragment",
|
||||||
"IOBufferInstance", "PortDirection", "Design", "build_netlist",
|
"Instance", "IOBufferInstance", "PortDirection", "Design", "build_netlist",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -30,6 +30,10 @@ class DriverConflict(UserWarning):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class DuplicateElaboratable(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class Fragment:
|
class Fragment:
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get(obj, platform):
|
def get(obj, platform):
|
||||||
|
@ -430,6 +434,7 @@ class Design:
|
||||||
self.hierarchy = hierarchy
|
self.hierarchy = hierarchy
|
||||||
self.fragments: dict[Fragment, DesignFragmentInfo] = {}
|
self.fragments: dict[Fragment, DesignFragmentInfo] = {}
|
||||||
self.signal_lca = _ast.SignalDict()
|
self.signal_lca = _ast.SignalDict()
|
||||||
|
self.elaboratables: dict[Elaboratable, Fragment] = {}
|
||||||
self._compute_fragment_depth_parent(fragment, None, 0)
|
self._compute_fragment_depth_parent(fragment, None, 0)
|
||||||
self._collect_used_signals(fragment)
|
self._collect_used_signals(fragment)
|
||||||
self._add_io_ports()
|
self._add_io_ports()
|
||||||
|
@ -598,6 +603,15 @@ class Design:
|
||||||
frag_info = self.fragments[fragment]
|
frag_info = self.fragments[fragment]
|
||||||
frag_info.name = hierarchy
|
frag_info.name = hierarchy
|
||||||
|
|
||||||
|
if fragment.origins is not None:
|
||||||
|
for origin in fragment.origins:
|
||||||
|
if origin in self.elaboratables:
|
||||||
|
other_hierarchy = self.fragments[self.elaboratables[origin]].name
|
||||||
|
raise DuplicateElaboratable(f"Elaboratable {origin!r} is included twice "
|
||||||
|
f"in the hierarchy, as {'.'.join(other_hierarchy)} "
|
||||||
|
f"and {'.'.join(hierarchy)}")
|
||||||
|
self.elaboratables[origin] = fragment
|
||||||
|
|
||||||
if fragment is self.fragment:
|
if fragment is self.fragment:
|
||||||
# Reserve names for top-level ports. If equal to the signal name, let the signal share it.
|
# Reserve names for top-level ports. If equal to the signal name, let the signal share it.
|
||||||
for name, conn, _dir in self.ports:
|
for name, conn, _dir in self.ports:
|
||||||
|
|
|
@ -318,6 +318,7 @@ class FragmentTransformer:
|
||||||
else:
|
else:
|
||||||
new_fragment = Fragment(src_loc=fragment.src_loc)
|
new_fragment = Fragment(src_loc=fragment.src_loc)
|
||||||
new_fragment.attrs = OrderedDict(fragment.attrs)
|
new_fragment.attrs = OrderedDict(fragment.attrs)
|
||||||
|
new_fragment.origins = fragment.origins
|
||||||
self.map_subfragments(fragment, new_fragment)
|
self.map_subfragments(fragment, new_fragment)
|
||||||
self.map_domains(fragment, new_fragment)
|
self.map_domains(fragment, new_fragment)
|
||||||
self.map_statements(fragment, new_fragment)
|
self.map_statements(fragment, new_fragment)
|
||||||
|
|
|
@ -77,6 +77,18 @@ class FragmentDriversTestCase(FHDLTestCase):
|
||||||
self.assertEqual(list(f.iter_sync()), [])
|
self.assertEqual(list(f.iter_sync()), [])
|
||||||
|
|
||||||
|
|
||||||
|
class DuplicateElaboratableTestCase(FHDLTestCase):
|
||||||
|
def test_duplicate(self):
|
||||||
|
sub = Module()
|
||||||
|
m = Module()
|
||||||
|
m.submodules.a = sub
|
||||||
|
m.submodules.b = sub
|
||||||
|
with self.assertRaisesRegex(DuplicateElaboratable,
|
||||||
|
r"^Elaboratable .* is included twice in the hierarchy, as "
|
||||||
|
r"top\.a and top\.b$"):
|
||||||
|
Fragment.get(m, None).prepare()
|
||||||
|
|
||||||
|
|
||||||
class FragmentPortsTestCase(FHDLTestCase):
|
class FragmentPortsTestCase(FHDLTestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.s1 = Signal()
|
self.s1 = Signal()
|
||||||
|
|
Loading…
Reference in a new issue