Skip to content

Commit 5e59189

Browse files
whitequarkwanda-phi
andcommitted
hdl: track domain renames in IR.
Co-authored-by: Wanda <wanda@phinode.net>
1 parent f637530 commit 5e59189

File tree

3 files changed

+64
-0
lines changed

3 files changed

+64
-0
lines changed

amaranth/hdl/_ir.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ def __init__(self, *, src_loc=None):
7171
self.src_loc = src_loc
7272
self.origins = None
7373
self.domains_propagated_up = {}
74+
self.domain_renames = {}
7475

7576
def add_domains(self, *domains):
7677
for domain in flatten(domains):
@@ -655,6 +656,19 @@ def _assign_names(self, fragment: Fragment, hierarchy: "tuple[str]"):
655656
subfragment_name = _add_name(frag_info.assigned_names, subfragment_name)
656657
self._assign_names(subfragment, hierarchy=(*hierarchy, subfragment_name))
657658

659+
def lookup_domain(self, domain, context):
660+
if domain == "comb":
661+
raise KeyError("comb")
662+
if context is not None:
663+
try:
664+
fragment = self.elaboratables[context]
665+
except KeyError:
666+
raise ValueError(f"Elaboratable {context!r} is not a part of the design")
667+
else:
668+
fragment = self.fragment
669+
domain = fragment.domain_renames.get(domain, domain)
670+
return fragment.domains[domain]
671+
658672

659673
############################################################################################### >:3
660674

amaranth/hdl/_xfrm.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,9 @@ def map_statements(self, fragment, new_fragment):
252252
for domain, statements in fragment.statements.items():
253253
new_fragment.add_statements(domain, statements)
254254

255+
def map_domain_renames(self, fragment, new_fragment):
256+
new_fragment.domain_renames = dict(fragment.domain_renames)
257+
255258
def map_memory_ports(self, fragment, new_fragment):
256259
if hasattr(self, "on_value"):
257260
for port in new_fragment._read_ports:
@@ -318,6 +321,7 @@ def on_fragment(self, fragment):
318321
self.map_subfragments(fragment, new_fragment)
319322
self.map_domains(fragment, new_fragment)
320323
self.map_statements(fragment, new_fragment)
324+
self.map_domain_renames(fragment, new_fragment)
321325
return new_fragment
322326

323327
def __call__(self, value, *, src_loc_at=0):
@@ -513,6 +517,15 @@ def map_statements(self, fragment, new_fragment):
513517
map(self.on_statement, statements)
514518
)
515519

520+
def map_domain_renames(self, fragment, new_fragment):
521+
new_fragment.domain_renames = {
522+
src: self.domain_map.get(dst, dst)
523+
for src, dst in fragment.domain_renames.items()
524+
}
525+
for src, dst in self.domain_map.items():
526+
if src not in new_fragment.domain_renames:
527+
new_fragment.domain_renames[src] = dst
528+
516529
def map_memory_ports(self, fragment, new_fragment):
517530
super().map_memory_ports(fragment, new_fragment)
518531
for port in new_fragment._read_ports:

tests/test_hdl_ir.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from amaranth.hdl._ir import *
99
from amaranth.hdl._mem import *
1010
from amaranth.hdl._nir import SignalField, CombinationalCycle
11+
from amaranth.hdl._xfrm import *
1112

1213
from amaranth.lib import enum, data
1314

@@ -3561,3 +3562,39 @@ def test_cycle(self):
35613562
r".*test_hdl_ir.py:\d+: signal a bit 0\n"
35623563
r"$"):
35633564
build_netlist(Fragment.get(m, None), [])
3565+
3566+
3567+
class DomainLookupTestCase(FHDLTestCase):
3568+
def test_domain_lookup(self):
3569+
m1 = Module()
3570+
m1_a = m1.domains.a = ClockDomain("a")
3571+
m1_b = m1.domains.b = ClockDomain("b")
3572+
m1_c = m1.domains.c = ClockDomain("c")
3573+
m2 = Module()
3574+
m3 = Module()
3575+
m3.d.sync += Print("m3")
3576+
m4 = Module()
3577+
m4.d.sync += Print("m4")
3578+
m4_d = m4.domains.d = ClockDomain("d")
3579+
m5 = Module()
3580+
m5.d.sync += Print("m5")
3581+
m5_d = m5.domains.d = ClockDomain("d")
3582+
3583+
m1.submodules.m2 = xm2 = DomainRenamer({"a": "b"})(m2)
3584+
m2.submodules.m3 = xm3 = DomainRenamer("a")(m3)
3585+
m2.submodules.m4 = xm4 = DomainRenamer("b")(m4)
3586+
m2.submodules.m5 = xm5 = DomainRenamer("c")(m5)
3587+
3588+
design = Fragment.get(m1, None).prepare()
3589+
3590+
self.assertIs(design.lookup_domain("a", m1), m1_a)
3591+
self.assertIs(design.lookup_domain("b", m1), m1_b)
3592+
self.assertIs(design.lookup_domain("c", m1), m1_c)
3593+
self.assertIs(design.lookup_domain("a", xm2), m1_b)
3594+
self.assertIs(design.lookup_domain("b", xm2), m1_b)
3595+
self.assertIs(design.lookup_domain("c", xm2), m1_c)
3596+
self.assertIs(design.lookup_domain("sync", xm3), m1_b)
3597+
self.assertIs(design.lookup_domain("sync", xm4), m1_b)
3598+
self.assertIs(design.lookup_domain("sync", xm5), m1_c)
3599+
self.assertIs(design.lookup_domain("d", xm4), m4_d)
3600+
self.assertIs(design.lookup_domain("d", xm5), m5_d)

0 commit comments

Comments
 (0)