d33ee71260477f62594aa4376c36ceca2ad67f47
1 from litex
.gen
.fhdl
.structure
import *
2 from litex
.gen
.fhdl
.module
import Module
3 from litex
.gen
.fhdl
.tools
import insert_reset
, rename_clock_domain
6 __all__
= ["CEInserter", "ResetInserter", "ClockDomainsRenamer",
10 class ModuleTransformer
:
11 # overload this in derived classes
12 def transform_instance(self
, i
):
15 # overload this in derived classes
16 def transform_fragment(self
, i
, f
):
19 def wrap_class(self
, victim
):
20 class Wrapped(victim
):
21 def __init__(i
, *args
, **kwargs
):
22 victim
.__init
__(i
, *args
, **kwargs
)
23 self
.transform_instance(i
)
26 f
= victim
.get_fragment(i
)
27 self
.transform_fragment(i
, f
)
30 Wrapped
.__name
__ = victim
.__name
__
31 Wrapped
.__doc
__ = victim
.__doc
__
32 Wrapped
.__module
__ = victim
.__module
__
35 def wrap_instance(self
, victim
):
36 self
.transform_instance(victim
)
37 orig_get_fragment
= victim
.get_fragment
40 f
= orig_get_fragment()
41 self
.transform_fragment(victim
, f
)
44 victim
.get_fragment
= get_fragment
47 def __call__(self
, victim
):
48 if isinstance(victim
, Module
):
49 return self
.wrap_instance(victim
)
51 return self
.wrap_class(victim
)
54 class ControlInserter(ModuleTransformer
):
55 control_name
= None # override this
57 def __init__(self
, clock_domains
=None):
58 self
.clock_domains
= clock_domains
60 def transform_instance(self
, i
):
61 if self
.clock_domains
is None:
62 ctl
= Signal(name
=self
.control_name
)
63 assert not hasattr(i
, self
.control_name
)
64 setattr(i
, self
.control_name
, ctl
)
66 for cd
in self
.clock_domains
:
67 name
= self
.control_name
+ "_" + cd
68 ctl
= Signal(name
=name
)
69 assert not hasattr(i
, name
)
72 def transform_fragment(self
, i
, f
):
73 if self
.clock_domains
is None:
77 raise ValueError("Control signal clock domains must be specified when module has more than one domain")
78 cdn
= list(f
.sync
.keys())[0]
79 to_insert
= [(getattr(i
, self
.control_name
), cdn
)]
81 to_insert
= [(getattr(i
, self
.control_name
+ "_" + cdn
), cdn
)
82 for cdn
in self
.clock_domains
]
83 self
.transform_fragment_insert(i
, f
, to_insert
)
86 class CEInserter(ControlInserter
):
89 def transform_fragment_insert(self
, i
, f
, to_insert
):
90 for ce
, cdn
in to_insert
:
91 f
.sync
[cdn
] = [If(ce
, *f
.sync
[cdn
])]
94 class ResetInserter(ControlInserter
):
95 control_name
= "reset"
97 def transform_fragment_insert(self
, i
, f
, to_insert
):
98 for reset
, cdn
in to_insert
:
99 f
.sync
[cdn
] = insert_reset(reset
, f
.sync
[cdn
])
102 class ClockDomainsRenamer(ModuleTransformer
):
103 def __init__(self
, cd_remapping
):
104 if isinstance(cd_remapping
, str):
105 cd_remapping
= {"sys": cd_remapping
}
106 self
.cd_remapping
= cd_remapping
108 def transform_fragment(self
, i
, f
):
109 for old
, new
in self
.cd_remapping
.items():
110 rename_clock_domain(f
, old
, new
)