From: Sebastien Bourdeauducq Date: Sun, 10 Mar 2013 18:27:55 +0000 (+0100) Subject: fhdl/module: replace autofragment X-Git-Tag: 24jan2021_ls180~2099^2~665 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=17e0dfe120eb28d5e4fd6c34395be051f788f275;p=litex.git fhdl/module: replace autofragment --- diff --git a/migen/fhdl/autofragment.py b/migen/fhdl/autofragment.py deleted file mode 100644 index f10be642..00000000 --- a/migen/fhdl/autofragment.py +++ /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 index 00000000..4bc42f1f --- /dev/null +++ b/migen/fhdl/module.py @@ -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 diff --git a/migen/fhdl/structure.py b/migen/fhdl/structure.py index 3b5ca53e..8052fdff 100644 --- a/migen/fhdl/structure.py +++ b/migen/fhdl/structure.py @@ -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