diff --git a/amaranth/hdl/_ir.py b/amaranth/hdl/_ir.py index 968b372..c491725 100644 --- a/amaranth/hdl/_ir.py +++ b/amaranth/hdl/_ir.py @@ -31,8 +31,11 @@ class Fragment: @staticmethod def get(obj, platform): code = None + origins = [] while True: if isinstance(obj, Fragment): + if hasattr(obj, "origins"): + obj.origins = tuple(origins) return obj elif isinstance(obj, Elaboratable): code = obj.elaborate.__code__ @@ -58,6 +61,7 @@ class Fragment: category=UserWarning, filename=code.co_filename, lineno=code.co_firstlineno) + origins.append(obj) obj = new_obj def __init__(self, *, src_loc=None): @@ -70,6 +74,7 @@ class Fragment: self.generated = OrderedDict() self.flatten = False self.src_loc = src_loc + self.origins = None def add_ports(self, *ports, dir): assert dir in ("i", "o", "io") diff --git a/tests/test_hdl_ir.py b/tests/test_hdl_ir.py index d38c197..2e9dabe 100644 --- a/tests/test_hdl_ir.py +++ b/tests/test_hdl_ir.py @@ -4,6 +4,7 @@ from collections import OrderedDict from amaranth.hdl._ast import * from amaranth.hdl._cd import * +from amaranth.hdl._dsl import * from amaranth.hdl._ir import * from amaranth.hdl._mem import * @@ -919,3 +920,29 @@ class InstanceTestCase(FHDLTestCase): f: ("top",), a_f: ("top", "a$U$0") }) + + +class ElaboratesTo(Elaboratable): + def __init__(self, lower): + self.lower = lower + + def elaborate(self, platform): + return self.lower + + +class OriginsTestCase(FHDLTestCase): + def test_origins(self): + elab1 = ElaboratesTo(elab2 := ElaboratesTo(m := Module())) + frag = Fragment.get(elab1, platform=None) + self.assertEqual(len(frag.origins), 3) + self.assertIsInstance(frag.origins, tuple) + self.assertIs(frag.origins[0], elab1) + self.assertIs(frag.origins[1], elab2) + self.assertIs(frag.origins[2], m) + + def test_origins_disable(self): + inst = Instance("test") + del inst.origins + elab = ElaboratesTo(inst) + frag = Fragment.get(elab, platform=None) + self.assertFalse(hasattr(frag, "_origins")) \ No newline at end of file