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__ = [
|
||||
"UnusedElaboratable", "Elaboratable", "DriverConflict", "Fragment", "Instance",
|
||||
"IOBufferInstance", "PortDirection", "Design", "build_netlist",
|
||||
"UnusedElaboratable", "Elaboratable", "DuplicateElaboratable", "DriverConflict", "Fragment",
|
||||
"Instance", "IOBufferInstance", "PortDirection", "Design", "build_netlist",
|
||||
]
|
||||
|
||||
|
||||
|
@ -30,6 +30,10 @@ class DriverConflict(UserWarning):
|
|||
pass
|
||||
|
||||
|
||||
class DuplicateElaboratable(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class Fragment:
|
||||
@staticmethod
|
||||
def get(obj, platform):
|
||||
|
@ -430,6 +434,7 @@ class Design:
|
|||
self.hierarchy = hierarchy
|
||||
self.fragments: dict[Fragment, DesignFragmentInfo] = {}
|
||||
self.signal_lca = _ast.SignalDict()
|
||||
self.elaboratables: dict[Elaboratable, Fragment] = {}
|
||||
self._compute_fragment_depth_parent(fragment, None, 0)
|
||||
self._collect_used_signals(fragment)
|
||||
self._add_io_ports()
|
||||
|
@ -598,6 +603,15 @@ class Design:
|
|||
frag_info = self.fragments[fragment]
|
||||
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:
|
||||
# Reserve names for top-level ports. If equal to the signal name, let the signal share it.
|
||||
for name, conn, _dir in self.ports:
|
||||
|
|
|
@ -318,6 +318,7 @@ class FragmentTransformer:
|
|||
else:
|
||||
new_fragment = Fragment(src_loc=fragment.src_loc)
|
||||
new_fragment.attrs = OrderedDict(fragment.attrs)
|
||||
new_fragment.origins = fragment.origins
|
||||
self.map_subfragments(fragment, new_fragment)
|
||||
self.map_domains(fragment, new_fragment)
|
||||
self.map_statements(fragment, new_fragment)
|
||||
|
|
|
@ -77,6 +77,18 @@ class FragmentDriversTestCase(FHDLTestCase):
|
|||
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):
|
||||
def setUp(self):
|
||||
self.s1 = Signal()
|
||||
|
|
Loading…
Reference in a new issue