--- /dev/null
+from migen.fhdl.structure import *
+from migen.fhdl.tools import insert_reset
+
+class ModuleDecorator:
+ def __init__(self, decorated):
+ object.__setattr__(self, "_md_decorated", decorated)
+
+ def __getattr__(self, name):
+ return getattr(self._md_decorated, name)
+
+ def __setattr__(self, name, value):
+ return setattr(self._md_decorated, name, value)
+
+ # overload this in derived classes
+ def transform_fragment(self, f):
+ pass
+
+ def get_fragment(self):
+ f = self._md_decorated.get_fragment()
+ self.transform_fragment(f)
+ return f
+
+class DecorateModule:
+ def __init__(self, decorator, *dec_args, **dec_kwargs):
+ self.decorator = decorator
+ self.dec_args = dec_args
+ self.dec_kwargs = dec_kwargs
+
+ def __call__(self, decorated):
+ def dfinit(dfself, *args, **kwargs):
+ self.decorator.__init__(dfself, decorated(*args, **kwargs),
+ *self.dec_args, **self.dec_kwargs)
+ typename = self.decorator.__name__ + "(" + decorated.__name__ + ")"
+ return type(typename, (self.decorator,), dict(__init__=dfinit))
+
+class InsertControl(ModuleDecorator):
+ def __init__(self, control_name, decorated, clock_domains=None):
+ ModuleDecorator.__init__(self, decorated)
+
+ object.__setattr__(self, "_ic_control_name", control_name)
+ object.__setattr__(self, "_ic_clock_domains", clock_domains)
+
+ if clock_domains is None:
+ ctl = Signal(name=control_name)
+ assert(not hasattr(decorated, control_name))
+ object.__setattr__(self, control_name, ctl)
+ else:
+ for cd in clock_domains:
+ name = control_name + "_" + cd
+ ctl = Signal(name=name)
+ assert(not hasattr(decorated, name))
+ object.__setattr__(self, name, ctl)
+
+ def transform_fragment(self, f):
+ control_name = self._ic_control_name
+ clock_domains = self._ic_clock_domains
+ if clock_domains is None:
+ if len(f.sync) != 1:
+ raise ValueError("Control signal clock domains must be specified when module has more than one domain")
+ cdn = list(f.sync.keys())[0]
+ to_insert = [(getattr(self, control_name), cdn)]
+ else:
+ to_insert = [(getattr(self, control_name+"_"+cdn), cdn) for cdn in clock_domains]
+ self.transform_fragment_insert(f, to_insert)
+
+class InsertCE(InsertControl):
+ def __init__(self, *args, **kwargs):
+ InsertControl.__init__(self, "ce", *args, **kwargs)
+
+ def transform_fragment_insert(self, f, to_insert):
+ for ce, cdn in to_insert:
+ f.sync[cdn] = [If(ce, *f.sync[cdn])]
+
+class InsertReset(InsertControl):
+ def __init__(self, *args, **kwargs):
+ InsertControl.__init__(self, "reset", *args, **kwargs)
+
+ def transform_fragment_insert(self, f, to_insert):
+ for reset, cdn in to_insert:
+ f.sync[cdn] = insert_reset(reset, f.sync[cdn])