Skip to content

hdl._ir: chain Fragment.origins with preexisting #1593

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 12, 2025

Conversation

rroohhh
Copy link
Contributor

@rroohhh rroohhh commented May 11, 2025

This PR changes Fragment.origins from being overwritten if during Fragment.get a Fragment is encountered that already has a Fragment.origins field to
appending to the preexisting origins tuple. This case is interesting for anything using a FragmentTransformer. With this change,

from amaranth import *

for transformer in (DomainRenamer("sync"), ResetInserter(Signal()), EnableInserter(Signal())):
    origins = Fragment.get(transformer(inst := Module()), None).origins
    assert inst in origins

no longer asserts, like it does currently.

Some before after examples:

Before:

>>> Fragment.get(DomainRenamer("sync")(Module()), None).origins
(<amaranth.hdl._xfrm.TransformedElaboratable object at 0x7fa86fee1d10>,)
>>> Fragment.get(ResetInserter(Signal())(DomainRenamer("sync")(Module())), None).origins
(<amaranth.hdl._xfrm.TransformedElaboratable object at 0x7fa86fee3310>,)

After:

>>> Fragment.get(DomainRenamer("sync")(Module()), None).origins
(<amaranth.hdl._xfrm.TransformedElaboratable object at 0x7f701f7266d0>, <amaranth.hdl._dsl.Module object at 0x7f70200a6690>)
>>> Fragment.get(ResetInserter(Signal())(DomainRenamer("sync")(Module())), None).origins
(<amaranth.hdl._xfrm.TransformedElaboratable object at 0x7f701f425a50>, <amaranth.hdl._dsl.Module object at 0x7f701f8f9250>)

Furthermore, with this change, the duplicate fragment check performed by Fragment.prepare() now also works if the duplicate is behind something that uses a fragment transformer, for example

from amaranth import *

m = Module()
m.submodules.a1 = a1 = DomainRenamer("sync")(inst := Module())
m.submodules.a2 = a2 = inst

Fragment.get(m, None).prepare()

previously did not raise any exception, but now (correctly) raises:

amaranth.hdl._ir.DuplicateElaboratable: Elaboratable <amaranth.hdl._dsl.Module object at 0x7fabfb3872d0> is included twice in the hierarchy, as top.a1 and top.a2

By chaining, `Fragment.origins` gets tracked through `FragmentTransformer`s
Copy link
Member

@whitequark whitequark left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks!

@whitequark whitequark added this pull request to the merge queue May 12, 2025
Merged via the queue into amaranth-lang:main with commit d805f96 May 12, 2025
18 of 19 checks passed
@rroohhh rroohhh deleted the origins branch May 12, 2025 22:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

2 participants