diff --git a/migen/fhdl/autofragment.py b/migen/fhdl/autofragment.py index 50e7bc379..bbc72446b 100644 --- a/migen/fhdl/autofragment.py +++ b/migen/fhdl/autofragment.py @@ -18,3 +18,86 @@ def from_attributes(obj): if hasattr(x, "get_fragment"): f += x.get_fragment() return f + +class _FModuleProxy: + def __init__(self, fm): + object.__setattr__(self, "_fm", fm) + +class _FModuleComb(_FModuleProxy): + def __iadd__(self, other): + if isinstance(other, (list, tuple)): + self._fm._fragment.comb += other + else: + self._fm._fragment.comb.append(other) + return self + +def _cd_append(d, key, statements): + try: + l = d[key] + except KeyError: + l = [] + d[key] = l + if isinstance(statements, (list, tuple)): + l += other + else: + l.append(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): + if isinstance(other, (set, list, tuple)): + self._fm._fragment.specials |= set(other) + else: + self._fm._fragment.specials.add(other) + return self + +class FModule: + def do_simulation(self, s): + pass + + def get_fragment(self): + assert(not hasattr(self, "_fragment")) + self._fragment = Fragment(sim=[self.do_simulation]) + self.build_fragment() + self._fragment += from_attributes(self) + 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) + else: + raise AttributeError + + def __setattr__(self, name, value): + if name in ["comb", "sync", "specials"]: + 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): + raise NotImplementedError("FModule.build_fragment needs to be overloaded")