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: b9f856bde342
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: ae0cb48fbb4f
Choose a head ref
  • 1 commit
  • 2 files changed
  • 1 contributor

Commits on Dec 22, 2018

  1. hdl.xfrm: implement LHSGroupAnalyzer.

    whitequark committed Dec 22, 2018
    Copy the full SHA
    ae0cb48 View commit details
Showing with 97 additions and 4 deletions.
  1. +51 −4 nmigen/hdl/xfrm.py
  2. +46 −0 nmigen/test/test_hdl_xfrm.py
55 changes: 51 additions & 4 deletions nmigen/hdl/xfrm.py
Original file line number Diff line number Diff line change
@@ -12,7 +12,9 @@
__all__ = ["ValueVisitor", "ValueTransformer",
"StatementVisitor", "StatementTransformer",
"FragmentTransformer",
"DomainRenamer", "DomainLowerer", "ResetInserter", "CEInserter"]
"DomainRenamer", "DomainLowerer",
"LHSGroupAnalyzer",
"ResetInserter", "CEInserter"]


class ValueVisitor(metaclass=ABCMeta):
@@ -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):
@@ -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

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 self.groups()


class _ControlInserter(FragmentTransformer):
def __init__(self, controls):
if isinstance(controls, Value):
46 changes: 46 additions & 0 deletions nmigen/test/test_hdl_xfrm.py
Original file line number Diff line number Diff line change
@@ -158,6 +158,52 @@ 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),
]

groups = LHSGroupAnalyzer()(stmts)
self.assertEqual(list(groups.values()), [
SignalSet((a,)),
SignalSet((b,)),
])

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

groups = LHSGroupAnalyzer()(stmts)
self.assertEqual(list(groups.values()), [
SignalSet((a, b)),
])

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

groups = LHSGroupAnalyzer()(stmts)
self.assertEqual(list(groups.values()), [
SignalSet((a,)),
SignalSet((b,)),
])



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