2013-03-09 17:23:24 -05:00
|
|
|
import collections
|
|
|
|
|
2011-12-16 10:02:55 -05:00
|
|
|
from migen.fhdl.structure import *
|
2013-03-03 11:53:06 -05:00
|
|
|
from migen.fhdl.specials import Special
|
2013-03-09 17:23:24 -05:00
|
|
|
from migen.fhdl.tools import flat_iteration
|
|
|
|
|
|
|
|
def flat_list(e):
|
|
|
|
if isinstance(e, collections.Iterable):
|
|
|
|
return flat_iteration(e)
|
|
|
|
else:
|
|
|
|
return [e]
|
2011-12-16 10:02:55 -05:00
|
|
|
|
2013-03-02 17:30:54 -05:00
|
|
|
class _FModuleProxy:
|
|
|
|
def __init__(self, fm):
|
|
|
|
object.__setattr__(self, "_fm", fm)
|
|
|
|
|
|
|
|
class _FModuleComb(_FModuleProxy):
|
|
|
|
def __iadd__(self, other):
|
2013-03-09 17:23:24 -05:00
|
|
|
self._fm._fragment.comb += flat_list(other)
|
2013-03-02 17:30:54 -05:00
|
|
|
return self
|
|
|
|
|
|
|
|
def _cd_append(d, key, statements):
|
|
|
|
try:
|
|
|
|
l = d[key]
|
|
|
|
except KeyError:
|
|
|
|
l = []
|
|
|
|
d[key] = l
|
2013-03-09 17:23:24 -05:00
|
|
|
l += flat_list(statements)
|
2013-03-02 17:30:54 -05:00
|
|
|
|
|
|
|
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):
|
2013-03-09 17:23:24 -05:00
|
|
|
self._fm._fragment.specials |= set(flat_list(other))
|
2013-03-02 17:30:54 -05:00
|
|
|
return self
|
|
|
|
|
2013-03-03 11:53:06 -05:00
|
|
|
class _FModuleSubmodules(_FModuleProxy):
|
|
|
|
def __iadd__(self, other):
|
2013-03-09 17:23:24 -05:00
|
|
|
self._fm._submodules += flat_list(other)
|
2013-03-03 11:53:06 -05:00
|
|
|
return self
|
|
|
|
|
2013-03-02 17:30:54 -05:00
|
|
|
class FModule:
|
2013-03-03 11:53:06 -05:00
|
|
|
auto_attr = True
|
2013-03-02 17:30:54 -05:00
|
|
|
|
|
|
|
def get_fragment(self):
|
|
|
|
assert(not hasattr(self, "_fragment"))
|
2013-03-03 11:53:06 -05:00
|
|
|
self._fragment = Fragment()
|
|
|
|
self._submodules = []
|
2013-03-02 17:30:54 -05:00
|
|
|
self.build_fragment()
|
2013-03-03 11:53:06 -05:00
|
|
|
if hasattr(self, "do_simulation"):
|
|
|
|
self._fragment.sim.append(self.do_simulation)
|
|
|
|
for submodule in self._submodules:
|
2013-03-09 15:15:38 -05:00
|
|
|
self._fragment += submodule.get_fragment()
|
2013-03-03 11:53:06 -05:00
|
|
|
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()
|
2013-03-02 17:30:54 -05:00
|
|
|
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)
|
2013-03-03 11:53:06 -05:00
|
|
|
elif name == "submodules":
|
|
|
|
return _FModuleSubmodules(self)
|
2013-03-02 17:30:54 -05:00
|
|
|
else:
|
2013-03-03 11:53:06 -05:00
|
|
|
raise AttributeError("'"+self.__class__.__name__+"' object has no attribute '"+name+"'")
|
2013-03-02 17:30:54 -05:00
|
|
|
|
|
|
|
def __setattr__(self, name, value):
|
2013-03-03 11:53:06 -05:00
|
|
|
if name in ["comb", "sync", "specials", "submodules"]:
|
2013-03-02 17:30:54 -05:00
|
|
|
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):
|
2013-03-09 13:10:47 -05:00
|
|
|
pass # do nothing (e.g. module has only submodules)
|