fhdl/module: replace autofragment
authorSebastien Bourdeauducq <sebastien@milkymist.org>
Sun, 10 Mar 2013 18:27:55 +0000 (19:27 +0100)
committerSebastien Bourdeauducq <sebastien@milkymist.org>
Sun, 10 Mar 2013 18:27:55 +0000 (19:27 +0100)
migen/fhdl/autofragment.py [deleted file]
migen/fhdl/module.py [new file with mode: 0644]
migen/fhdl/structure.py

diff --git a/migen/fhdl/autofragment.py b/migen/fhdl/autofragment.py
deleted file mode 100644 (file)
index f10be64..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-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)
diff --git a/migen/fhdl/module.py b/migen/fhdl/module.py
new file mode 100644 (file)
index 0000000..4bc42f1
--- /dev/null
@@ -0,0 +1,129 @@
+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
index 3b5ca53e978b17f7f359580a83a32b5a886a5816..8052fdffbbc700e473247c8dab0f8ecd2643ec15 100644 (file)
@@ -276,6 +276,3 @@ class ClockDomain:
                        n_rst = n2
                self.clk = Signal(name_override=n_clk)
                self.rst = Signal(name_override=n_rst)
-
-class FinalizeError(Exception):
-       pass