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/nmigen
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 37b81309d3aa
Choose a base ref
...
head repository: m-labs/nmigen
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: b9f856bde342
Choose a head ref
  • 2 commits
  • 3 files changed
  • 1 contributor

Commits on Dec 22, 2018

  1. hdl.xfrm: Abstract*Transformer→*Visitor

    whitequark committed Dec 22, 2018
    Copy the full SHA
    98a9744 View commit details
  2. hdl.xfrm: implement LHSGroupAnalyzer.

    whitequark committed Dec 22, 2018
    Copy the full SHA
    b9f856b View commit details
Showing with 104 additions and 14 deletions.
  1. +4 −4 nmigen/back/pysim.py
  2. +57 −10 nmigen/hdl/xfrm.py
  3. +43 −0 nmigen/test/test_hdl_xfrm.py
8 changes: 4 additions & 4 deletions nmigen/back/pysim.py
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@

from ..tools import flatten
from ..hdl.ast import *
from ..hdl.xfrm import AbstractValueTransformer, AbstractStatementTransformer
from ..hdl.xfrm import ValueVisitor, StatementVisitor


__all__ = ["Simulator", "Delay", "Tick", "Passive", "DeadlineError"]
@@ -71,7 +71,7 @@ def iter_next_dirty(self):
normalize = Const.normalize


class _RHSValueCompiler(AbstractValueTransformer):
class _RHSValueCompiler(ValueVisitor):
def __init__(self, signal_slots, sensitivity=None, mode="rhs"):
self.signal_slots = signal_slots
self.sensitivity = sensitivity
@@ -201,7 +201,7 @@ def eval(state):
return eval


class _LHSValueCompiler(AbstractValueTransformer):
class _LHSValueCompiler(ValueVisitor):
def __init__(self, signal_slots, rhs_compiler):
self.signal_slots = signal_slots
self.rhs_compiler = rhs_compiler
@@ -275,7 +275,7 @@ def eval(state, rhs):
return eval


class _StatementCompiler(AbstractStatementTransformer):
class _StatementCompiler(StatementVisitor):
def __init__(self, signal_slots):
self.sensitivity = SignalSet()
self.rrhs_compiler = _RHSValueCompiler(signal_slots, self.sensitivity, mode="rhs")
67 changes: 57 additions & 10 deletions nmigen/hdl/xfrm.py
Original file line number Diff line number Diff line change
@@ -9,13 +9,15 @@
from .ir import *


__all__ = ["AbstractValueTransformer", "ValueTransformer",
"AbstractStatementTransformer", "StatementTransformer",
__all__ = ["ValueVisitor", "ValueTransformer",
"StatementVisitor", "StatementTransformer",
"FragmentTransformer",
"DomainRenamer", "DomainLowerer", "ResetInserter", "CEInserter"]
"DomainRenamer", "DomainLowerer",
"LHSGroupAnalyzer",
"ResetInserter", "CEInserter"]


class AbstractValueTransformer(metaclass=ABCMeta):
class ValueVisitor(metaclass=ABCMeta):
@abstractmethod
def on_Const(self, value):
pass # :nocov:
@@ -91,7 +93,7 @@ def __call__(self, value):
return self.on_value(value)


class ValueTransformer(AbstractValueTransformer):
class ValueTransformer(ValueVisitor):
def on_Const(self, value):
return value

@@ -124,7 +126,7 @@ def on_ArrayProxy(self, value):
self.on_value(value.index))


class AbstractStatementTransformer(metaclass=ABCMeta):
class StatementVisitor(metaclass=ABCMeta):
@abstractmethod
def on_Assign(self, stmt):
pass # :nocov:
@@ -134,7 +136,7 @@ def on_Switch(self, stmt):
pass # :nocov:

@abstractmethod
def on_statements(self, stmt):
def on_statements(self, stmts):
pass # :nocov:

def on_unknown_statement(self, stmt):
@@ -155,7 +157,7 @@ def __call__(self, value):
return self.on_statement(value)


class StatementTransformer(AbstractStatementTransformer):
class StatementTransformer(StatementVisitor):
def on_value(self, value):
return value

@@ -166,8 +168,8 @@ def on_Switch(self, stmt):
cases = OrderedDict((k, self.on_statement(v)) for k, v in stmt.cases.items())
return Switch(self.on_value(stmt.test), cases)

def on_statements(self, stmt):
return _StatementList(flatten(self.on_statement(stmt) for stmt in stmt))
def on_statements(self, stmts):
return _StatementList(flatten(self.on_statement(stmt) for stmt in stmts))


class FragmentTransformer:
@@ -278,6 +280,51 @@ def on_ResetSignal(self, value):
return cd.rst


class LHSGroupAnalyzer(StatementVisitor):
def __init__(self):
self.signals = SignalDict()
self.unions = OrderedDict()

def find(self, signal):
if signal not in self.signals:
self.signals[signal] = len(self.signals)
group = self.signals[signal]
while group in self.unions:
group = self.unions[group]
self.signals[signal] = group
return group

def unify(self, root, *leaves):
root_group = self.find(root)
for leaf in leaves:
leaf_group = self.find(leaf)
self.unions[leaf_group] = root_group

def groups(self):
groups = OrderedDict()
for signal in self.signals:
group = self.find(signal)
if group not in groups:
groups[group] = SignalSet()
groups[group].add(signal)
return groups.values()

def on_Assign(self, stmt):
self.unify(*stmt._lhs_signals())

def on_Switch(self, stmt):
for case_stmts in stmt.cases.values():
self.on_statements(case_stmts)

def on_statements(self, stmts):
for stmt in stmts:
self.on_statement(stmt)

def __call__(self, stmts):
self.on_statements(stmts)
return list(self.groups())


class _ControlInserter(FragmentTransformer):
def __init__(self, controls):
if isinstance(controls, Value):
43 changes: 43 additions & 0 deletions nmigen/test/test_hdl_xfrm.py
Original file line number Diff line number Diff line change
@@ -158,6 +158,49 @@ def test_lower_wrong_reset_less_domain(self):
DomainLowerer({"sync": sync})(f)


class LHSGroupAnalyzerTestCase(FHDLTestCase):
def test_no_group_unrelated(self):
a = Signal()
b = Signal()
stmts = [
a.eq(0),
b.eq(0),
]

self.assertEqual(LHSGroupAnalyzer()(stmts), [
SignalSet((a,)),
SignalSet((b,)),
])

def test_group_related(self):
a = Signal()
b = Signal()
stmts = [
a.eq(0),
Cat(a, b).eq(0),
]

self.assertEqual(LHSGroupAnalyzer()(stmts), [
SignalSet((a, b)),
])

def test_switch(self):
a = Signal()
b = Signal()
stmts = [
a.eq(0),
Switch(a, {
1: b.eq(0),
})
]

self.assertEqual(LHSGroupAnalyzer()(stmts), [
SignalSet((a,)),
SignalSet((b,)),
])



class ResetInserterTestCase(FHDLTestCase):
def setUp(self):
self.s1 = Signal()