mirror of
https://github.com/enjoy-digital/litex.git
synced 2025-01-04 09:52:26 -05:00
fhdl/tools: use NodeTransformer to lower arrays
This commit is contained in:
parent
5440fa715c
commit
a2bcbfdf8f
1 changed files with 27 additions and 97 deletions
|
@ -1,8 +1,6 @@
|
||||||
from copy import copy
|
|
||||||
|
|
||||||
from migen.fhdl.structure import *
|
from migen.fhdl.structure import *
|
||||||
from migen.fhdl.structure import _Operator, _Slice, _Assign, _ArrayProxy
|
from migen.fhdl.structure import _Operator, _Slice, _Assign, _ArrayProxy
|
||||||
from migen.fhdl.visit import NodeVisitor
|
from migen.fhdl.visit import NodeVisitor, NodeTransformer
|
||||||
|
|
||||||
class _SignalLister(NodeVisitor):
|
class _SignalLister(NodeVisitor):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
@ -144,100 +142,32 @@ def value_bv(v):
|
||||||
else:
|
else:
|
||||||
raise TypeError
|
raise TypeError
|
||||||
|
|
||||||
def _lower_arrays_values(vl):
|
class _ArrayLowerer(NodeTransformer):
|
||||||
r = []
|
def __init__(self):
|
||||||
extra_comb = []
|
self.comb = []
|
||||||
for v in vl:
|
|
||||||
v2, e = _lower_arrays_value(v)
|
def visit_Assign(self, node):
|
||||||
extra_comb += e
|
if isinstance(node.l, _ArrayProxy):
|
||||||
r.append(v2)
|
k = self.visit(node.l.key)
|
||||||
return r, extra_comb
|
cases = []
|
||||||
|
for n, choice in enumerate(node.l.choices):
|
||||||
def _lower_arrays_value(v):
|
assign = self.visit_Assign(_Assign(choice, node.r))
|
||||||
if isinstance(v, Constant):
|
cases.append([Constant(n), assign])
|
||||||
return v, []
|
cases[-1][0] = Default()
|
||||||
elif isinstance(v, Signal):
|
return Case(k, *cases)
|
||||||
return v, []
|
else:
|
||||||
elif isinstance(v, _Operator):
|
return super().visit_Assign(node)
|
||||||
op2, e = _lower_arrays_values(v.operands)
|
|
||||||
return _Operator(v.op, op2), e
|
def visit_ArrayProxy(self, node):
|
||||||
elif isinstance(v, _Slice):
|
array_muxed = Signal(value_bv(node))
|
||||||
v2, e = _lower_arrays_value(v.value)
|
cases = [[Constant(n), _Assign(array_muxed, self.visit(choice))]
|
||||||
return _Slice(v2, v.start, v.stop), e
|
for n, choice in enumerate(node.choices)]
|
||||||
elif isinstance(v, Cat):
|
|
||||||
l2, e = _lower_arrays_values(v.l)
|
|
||||||
return Cat(*l2), e
|
|
||||||
elif isinstance(v, Replicate):
|
|
||||||
v2, e = _lower_arrays_value(v.v)
|
|
||||||
return Replicate(v2, v.n), e
|
|
||||||
elif isinstance(v, _ArrayProxy):
|
|
||||||
choices2, e = _lower_arrays_values(v.choices)
|
|
||||||
array_muxed = Signal(value_bv(v))
|
|
||||||
cases = [[Constant(n), _Assign(array_muxed, choice)]
|
|
||||||
for n, choice in enumerate(choices2)]
|
|
||||||
cases[-1][0] = Default()
|
cases[-1][0] = Default()
|
||||||
e.append(Case(v.key, *cases))
|
self.comb.append(Case(self.visit(node.key), *cases))
|
||||||
return array_muxed, e
|
return array_muxed
|
||||||
|
|
||||||
def _lower_arrays_assign(l, r):
|
|
||||||
extra_comb = []
|
|
||||||
if isinstance(l, _ArrayProxy):
|
|
||||||
k, e = _lower_arrays_value(l.key)
|
|
||||||
extra_comb += e
|
|
||||||
cases = []
|
|
||||||
for n, choice in enumerate(l.choices):
|
|
||||||
assign, e = _lower_arrays_assign(choice, r)
|
|
||||||
extra_comb += e
|
|
||||||
cases.append([Constant(n), assign])
|
|
||||||
cases[-1][0] = Default()
|
|
||||||
return Case(k, *cases), extra_comb
|
|
||||||
else:
|
|
||||||
return _Assign(l, r), extra_comb
|
|
||||||
|
|
||||||
def _lower_arrays_sl(sl):
|
|
||||||
rs = []
|
|
||||||
extra_comb = []
|
|
||||||
for statement in sl:
|
|
||||||
if isinstance(statement, _Assign):
|
|
||||||
r, e = _lower_arrays_value(statement.r)
|
|
||||||
extra_comb += e
|
|
||||||
r, e = _lower_arrays_assign(statement.l, r)
|
|
||||||
extra_comb += e
|
|
||||||
rs.append(r)
|
|
||||||
elif isinstance(statement, If):
|
|
||||||
cond, e = _lower_arrays_value(statement.cond)
|
|
||||||
extra_comb += e
|
|
||||||
t, e = _lower_arrays_sl(statement.t)
|
|
||||||
extra_comb += e
|
|
||||||
f, e = _lower_arrays_sl(statement.f)
|
|
||||||
extra_comb += e
|
|
||||||
i = If(cond)
|
|
||||||
i.t = t
|
|
||||||
i.f = f
|
|
||||||
rs.append(i)
|
|
||||||
elif isinstance(statement, Case):
|
|
||||||
test, e = _lower_arrays_value(statement.test)
|
|
||||||
extra_comb += e
|
|
||||||
c = Case(test)
|
|
||||||
for cond, csl in statement.cases:
|
|
||||||
stmts, e = _lower_arrays_sl(csl)
|
|
||||||
extra_comb += e
|
|
||||||
c.cases.append((cond, stmts))
|
|
||||||
if statement.default is not None:
|
|
||||||
c.default, e = _lower_arrays_sl(statement.default)
|
|
||||||
extra_comb += e
|
|
||||||
rs.append(c)
|
|
||||||
elif statement is not None:
|
|
||||||
raise TypeError
|
|
||||||
return rs, extra_comb
|
|
||||||
|
|
||||||
def lower_arrays(f):
|
def lower_arrays(f):
|
||||||
f = copy(f)
|
al = _ArrayLowerer()
|
||||||
f.comb, ec1 = _lower_arrays_sl(f.comb)
|
f2 = al.visit(f)
|
||||||
f.comb += ec1
|
f2.comb += al.comb
|
||||||
newsync = dict()
|
return f2
|
||||||
for k, v in f.sync.items():
|
|
||||||
newsync[k], ec2 = _lower_arrays_sl(v)
|
|
||||||
f.comb += ec2
|
|
||||||
f.sync = newsync
|
|
||||||
return f
|
|
||||||
|
|
Loading…
Reference in a new issue