+++ /dev/null
-import collections
-
-from migen.fhdl.structure import *
-from migen.fhdl.specials import Special
-from migen.fhdl.tools import flat_iteration
-
-def flat_list(e):
- if isinstance(e, collections.Iterable):
- return flat_iteration(e)
- else:
- return [e]
-
-class _FModuleProxy:
- def __init__(self, fm):
- object.__setattr__(self, "_fm", fm)
-
-class _FModuleComb(_FModuleProxy):
- def __iadd__(self, other):
- self._fm._fragment.comb += flat_list(other)
- return self
-
-def _cd_append(d, key, statements):
- try:
- l = d[key]
- except KeyError:
- l = []
- d[key] = l
- l += flat_list(statements)
-
-class _FModuleSyncCD:
- def __init__(self, fm, cd):
- self._fm = fm
- self._cd = cd
-
- def __iadd__(self, other):
- _cd_append(self._fm._fragment.sync, self._cd, other)
- return self
-
-class _FModuleSync(_FModuleProxy):
- def __iadd__(self, other):
- _cd_append(self._fm._fragment.sync, "sys", other)
- return self
-
- def __getattr__(self, name):
- return _FModuleSyncCD(self._fm, name)
-
- def __setattr__(self, name, value):
- if not isinstance(value, _FModuleSyncCD):
- raise AttributeError("Attempted to assign sync property - use += instead")
-
-class _FModuleSpecials(_FModuleProxy):
- def __iadd__(self, other):
- self._fm._fragment.specials |= set(flat_list(other))
- return self
-
-class _FModuleSubmodules(_FModuleProxy):
- def __iadd__(self, other):
- self._fm._submodules += flat_list(other)
- return self
-
-class FModule:
- auto_attr = True
-
- def get_fragment(self):
- assert(not hasattr(self, "_fragment"))
- self._fragment = Fragment()
- self._submodules = []
- self.build_fragment()
- if hasattr(self, "do_simulation"):
- self._fragment.sim.append(self.do_simulation)
- for submodule in self._submodules:
- self._fragment += submodule.get_fragment()
- if self.auto_attr:
- for x in self.__dict__.values():
- if isinstance(x, Special):
- self._fragment.specials.add(x)
- elif hasattr(x, "get_fragment"):
- self._fragment += x.get_fragment()
- return self._fragment
-
- def __getattr__(self, name):
- if name == "comb":
- return _FModuleComb(self)
- elif name == "sync":
- return _FModuleSync(self)
- elif name == "specials":
- return _FModuleSpecials(self)
- elif name == "submodules":
- return _FModuleSubmodules(self)
- else:
- raise AttributeError("'"+self.__class__.__name__+"' object has no attribute '"+name+"'")
-
- def __setattr__(self, name, value):
- if name in ["comb", "sync", "specials", "submodules"]:
- if not isinstance(value, _FModuleProxy):
- raise AttributeError("Attempted to assign special FModule property - use += instead")
- else:
- object.__setattr__(self, name, value)
-
- def build_fragment(self):
- pass # do nothing (e.g. module has only submodules)
--- /dev/null
+import collections
+
+from migen.fhdl.structure import *
+from migen.fhdl.specials import Special
+from migen.fhdl.tools import flat_iteration
+
+class FinalizeError(Exception):
+ pass
+
+def _flat_list(e):
+ if isinstance(e, collections.Iterable):
+ return flat_iteration(e)
+ else:
+ return [e]
+
+class _ModuleProxy:
+ def __init__(self, fm):
+ object.__setattr__(self, "_fm", fm)
+
+class _ModuleComb(_ModuleProxy):
+ def __iadd__(self, other):
+ self._fm._fragment.comb += _flat_list(other)
+ return self
+
+def _cd_append(d, key, statements):
+ try:
+ l = d[key]
+ except KeyError:
+ l = []
+ d[key] = l
+ l += _flat_list(statements)
+
+class _ModuleSyncCD:
+ def __init__(self, fm, cd):
+ self._fm = fm
+ self._cd = cd
+
+ def __iadd__(self, other):
+ _cd_append(self._fm._fragment.sync, self._cd, other)
+ return self
+
+class _ModuleSync(_ModuleProxy):
+ def __iadd__(self, other):
+ _cd_append(self._fm._fragment.sync, "sys", other)
+ return self
+
+ def __getattr__(self, name):
+ return _ModuleSyncCD(self._fm, name)
+
+ def __setattr__(self, name, value):
+ if not isinstance(value, _ModuleSyncCD):
+ raise AttributeError("Attempted to assign sync property - use += instead")
+
+# _ModuleForwardAttr enables user classes to do e.g.:
+# self.subm.foobar = SomeModule()
+# and then access the submodule with self.foobar.
+class _ModuleForwardAttr:
+ def __setattr__(self, name, value):
+ self.__iadd__(value)
+ setattr(self._fm, name, value)
+
+class _ModuleSpecials(_ModuleProxy, _ModuleForwardAttr):
+ def __iadd__(self, other):
+ self._fm._fragment.specials |= set(_flat_list(other))
+ return self
+
+class _ModuleSubmodules(_ModuleProxy, _ModuleForwardAttr):
+ def __iadd__(self, other):
+ self._fm._submodules += _flat_list(other)
+ return self
+
+class Module:
+ def get_fragment(self):
+ assert(not self._get_fragment_called)
+ self._get_fragment_called = True
+ self.finalize()
+ return self._fragment
+
+ def __getattr__(self, name):
+ if name == "comb":
+ return _ModuleComb(self)
+ elif name == "sync":
+ return _ModuleSync(self)
+ elif name == "specials":
+ return _ModuleSpecials(self)
+ elif name == "submodules":
+ return _ModuleSubmodules(self)
+
+ # hack to have initialized regular attributes without using __init__
+ # (which would require derived classes to call it)
+ elif name == "finalized":
+ self.finalized = False
+ return self.finalized
+ elif name == "_fragment":
+ try:
+ sim = [self.do_simulation]
+ except AttributeError:
+ sim = []
+ self._fragment = Fragment(sim=sim)
+ return self._fragment
+ elif name == "_submodules":
+ self._submodules = []
+ return self._submodules
+ elif name == "_get_fragment_called":
+ self._get_fragment_called = False
+ return self._get_fragment_called
+
+ else:
+ raise AttributeError("'"+self.__class__.__name__+"' object has no attribute '"+name+"'")
+
+ def __setattr__(self, name, value):
+ if name in ["comb", "sync", "specials", "submodules"]:
+ if not isinstance(value, _ModuleProxy):
+ raise AttributeError("Attempted to assign special Module property - use += instead")
+ else:
+ object.__setattr__(self, name, value)
+
+ def finalize(self):
+ if not self.finalized:
+ self.finalized = True
+ for submodule in self._submodules:
+ self._fragment += submodule.get_fragment()
+ self._submodules = []
+ self.do_finalize()
+ for submodule in self._submodules:
+ self._fragment += submodule.get_fragment()
+
+ def do_finalize(self):
+ pass