fhdl: introduce module decorators
authorSebastien Bourdeauducq <sebastien@milkymist.org>
Thu, 25 Jul 2013 15:56:31 +0000 (17:56 +0200)
committerSebastien Bourdeauducq <sebastien@milkymist.org>
Thu, 25 Jul 2013 15:56:31 +0000 (17:56 +0200)
migen/fhdl/decorators.py [new file with mode: 0644]
migen/fhdl/std.py

diff --git a/migen/fhdl/decorators.py b/migen/fhdl/decorators.py
new file mode 100644 (file)
index 0000000..0a9d1cf
--- /dev/null
@@ -0,0 +1,80 @@
+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])
index ccdc82c058958edb67246f4bee9b7a06cc0e5ca4..8a6f6845cde5ea186920b2664b9c6977844971e7 100644 (file)
@@ -2,3 +2,4 @@ from migen.fhdl.structure import *
 from migen.fhdl.module import Module
 from migen.fhdl.specials import TSTriple, Instance, Memory
 from migen.fhdl.size import log2_int, bits_for, flen
+from migen.fhdl.decorators import DecorateModule, InsertCE, InsertReset