Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: m-labs/migen
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: aac953dd9035
Choose a base ref
...
head repository: m-labs/migen
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: db76defa2a2b
Choose a head ref
  • 3 commits
  • 3 files changed
  • 2 contributors

Commits on Apr 4, 2015

  1. fhdl/decorators: make the transform logic more idiomatic

    * the transformers work on classes and instances.
      you can now do just do:
    
        @ResetInserter()
        @ClockDomainRenamer({"sys": "new"})
        class Foo(Module):
            pass
    
      or:
    
        a = ResetInserter()(FooModule())
    
    * the old usage semantics still work
    * the old DecorateModule is deprecated,
      ModuleDecorator has been refactored into ModuleTransformer
      (because it not only decorates things)
    jordens authored and sbourdeauducq committed Apr 4, 2015
    Copy the full SHA
    4091af6 View commit details
  2. Copy the full SHA
    e702fb7 View commit details
  3. Copy the full SHA
    db76def View commit details
Showing with 91 additions and 81 deletions.
  1. +88 −67 migen/fhdl/decorators.py
  2. +3 −3 migen/fhdl/simplify.py
  3. +0 −11 migen/fhdl/visit.py
155 changes: 88 additions & 67 deletions migen/fhdl/decorators.py
Original file line number Diff line number Diff line change
@@ -1,94 +1,115 @@
import warnings

from migen.fhdl.structure import *
from migen.fhdl.module import Module
from migen.fhdl.tools import insert_reset, rename_clock_domain

class ModuleDecorator:
def __init__(self, decorated):
object.__setattr__(self, "_md_decorated", decorated)

def __getattr__(self, name):
return getattr(self._md_decorated, name)

def __setattr__(self, name, value):
return setattr(self._md_decorated, name, value)
class ModuleTransformer:
# overload this in derived classes
def transform_instance(self, i):
pass

# overload this in derived classes
def transform_fragment(self, f):
def transform_fragment(self, i, f):
pass

def get_fragment(self):
f = self._md_decorated.get_fragment()
self.transform_fragment(f)
return f

def __dir__(self):
return dir(self._md_decorated)

class DecorateModule:
def __init__(self, decorator, *dec_args, **dec_kwargs):
self.decorator = decorator
self.dec_args = dec_args
self.dec_kwargs = dec_kwargs

def __call__(self, decorated):
def dfinit(dfself, *args, **kwargs):
self.decorator.__init__(dfself, decorated(*args, **kwargs),
*self.dec_args, **self.dec_kwargs)
typename = self.decorator.__name__ + "(" + decorated.__name__ + ")"
return type(typename, (self.decorator,), dict(__init__=dfinit))

class InsertControl(ModuleDecorator):
def __init__(self, control_name, decorated, clock_domains=None):
ModuleDecorator.__init__(self, decorated)

object.__setattr__(self, "_ic_control_name", control_name)
object.__setattr__(self, "_ic_clock_domains", clock_domains)

if clock_domains is None:
ctl = Signal(name=control_name)
assert(not hasattr(decorated, control_name))
object.__setattr__(self, control_name, ctl)
def wrap_class(self, victim):
class Wrapped(victim):
def __init__(i, *args, **kwargs):
victim.__init__(i, *args, **kwargs)
self.transform_instance(i)

def get_fragment(i):
f = victim.get_fragment(i)
self.transform_fragment(i, f)
return f

Wrapped.__name__ = victim.__name__
# "{}_{}".format(self.__class__.__name__, victim.__name__)
return Wrapped

def wrap_instance(self, victim):
self.transform_instance(victim)
orig_get_fragment = victim.get_fragment

def get_fragment():
f = orig_get_fragment()
self.transform_fragment(victim, f)
return f

victim.get_fragment = get_fragment
return victim

def __call__(self, victim):
if isinstance(victim, Module):
return self.wrap_instance(victim)
else:
return self.wrap_class(victim)

@classmethod
def adhoc(cls, i, *args, **kwargs):
warnings.warn("deprecated, use the plain transformer", DeprecationWarning)
return cls(*args, **kwargs)(i)

def DecorateModule(transformer, *args, **kwargs):
warnings.warn("deprecated, use the plain transformer", DeprecationWarning)
return transformer.__self__(*args, **kwargs)

class ControlInserter(ModuleTransformer):
control_name = None # override this

def __init__(self, clock_domains=None):
self.clock_domains = clock_domains

def transform_instance(self, i):
if self.clock_domains is None:
ctl = Signal(name=self.control_name)
assert not hasattr(i, self.control_name)
setattr(i, self.control_name, ctl)
else:
for cd in clock_domains:
name = control_name + "_" + cd
for cd in self.clock_domains:
name = self.control_name + "_" + cd
ctl = Signal(name=name)
assert(not hasattr(decorated, name))
object.__setattr__(self, name, ctl)
assert not hasattr(i, name)
setattr(i, name, ctl)

def transform_fragment(self, f):
control_name = self._ic_control_name
clock_domains = self._ic_clock_domains
if clock_domains is None:
def transform_fragment(self, i, f):
if self.clock_domains is None:
if len(f.sync) != 1:
raise ValueError("Control signal clock domains must be specified when module has more than one domain")
cdn = list(f.sync.keys())[0]
to_insert = [(getattr(self, control_name), cdn)]
to_insert = [(getattr(i, self.control_name), cdn)]
else:
to_insert = [(getattr(self, control_name+"_"+cdn), cdn) for cdn in clock_domains]
self.transform_fragment_insert(f, to_insert)
to_insert = [(getattr(i, self.control_name + "_" + cdn), cdn)
for cdn in clock_domains]
self.transform_fragment_insert(i, f, to_insert)

class InsertCE(InsertControl):
def __init__(self, *args, **kwargs):
InsertControl.__init__(self, "ce", *args, **kwargs)
class CEInserter(ControlInserter):
control_name = "ce"

def transform_fragment_insert(self, f, to_insert):
def transform_fragment_insert(self, i, f, to_insert):
for ce, cdn in to_insert:
f.sync[cdn] = [If(ce, *f.sync[cdn])]

class InsertReset(InsertControl):
def __init__(self, *args, **kwargs):
InsertControl.__init__(self, "reset", *args, **kwargs)
InsertCE = CEInserter.adhoc

class ResetInserter(ControlInserter):
control_name = "reset"

def transform_fragment_insert(self, f, to_insert):
def transform_fragment_insert(self, i, f, to_insert):
for reset, cdn in to_insert:
f.sync[cdn] = insert_reset(reset, f.sync[cdn])

class RenameClockDomains(ModuleDecorator):
def __init__(self, decorated, cd_remapping):
ModuleDecorator.__init__(self, decorated)
InsertReset = ResetInserter.adhoc

class ClockDomainsRenamer(ModuleTransformer):
def __init__(self, cd_remapping):
if isinstance(cd_remapping, str):
cd_remapping = {"sys": cd_remapping}
object.__setattr__(self, "_rc_cd_remapping", cd_remapping)
self.cd_remapping = cd_remapping

def transform_fragment(self, f):
for old, new in self._rc_cd_remapping.items():
def transform_fragment(self, i, f):
for old, new in self.cd_remapping.items():
rename_clock_domain(f, old, new)

RenameClockDomains = ClockDomainsRenamer.adhoc
6 changes: 3 additions & 3 deletions migen/fhdl/simplify.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from migen.fhdl.std import *
from migen.fhdl.specials import _MemoryPort
from migen.fhdl.decorators import ModuleDecorator
from migen.fhdl.decorators import ModuleTransformer
from migen.util.misc import gcd_multiple

class FullMemoryWE(ModuleDecorator):
def transform_fragment(self, f):
class FullMemoryWE(ModuleTransformer):
def transform_fragment(self, i, f):
newspecials = set()

for orig in f.specials:
11 changes: 0 additions & 11 deletions migen/fhdl/visit.py
Original file line number Diff line number Diff line change
@@ -197,14 +197,3 @@ def visit_ArrayProxy(self, node):

def visit_unknown(self, node):
return node

class TransformModule:
def __init__(self, transform, module):
self.transform = transform
self.module = module
self.get_fragment_called = False

def get_fragment(self):
assert(not self.get_fragment_called)
self.get_fragment_called = True
return self.transform(self.module.get_fragment())