fhdl: arrays (TODO: use correct BV for intermediate signals)
This commit is contained in:
parent
c82a468506
commit
ed27783a53
|
@ -0,0 +1,25 @@
|
||||||
|
from migen.fhdl.structure import *
|
||||||
|
from migen.fhdl import verilog
|
||||||
|
|
||||||
|
dx = 5
|
||||||
|
dy = 5
|
||||||
|
|
||||||
|
x = Signal(BV(bits_for(dx)))
|
||||||
|
y = Signal(BV(bits_for(dy)))
|
||||||
|
out = Signal()
|
||||||
|
|
||||||
|
my_2d_array = Array(Array(Signal() for a in range(dx)) for b in range(dy))
|
||||||
|
comb = [
|
||||||
|
out.eq(my_2d_array[x][y])
|
||||||
|
]
|
||||||
|
|
||||||
|
we = Signal()
|
||||||
|
inp = Signal()
|
||||||
|
sync = [
|
||||||
|
If(we,
|
||||||
|
my_2d_array[x][y].eq(inp)
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
f = Fragment(comb)
|
||||||
|
print(verilog.convert(f))
|
|
@ -1,6 +1,8 @@
|
||||||
from migen.fhdl.structure import *
|
from migen.fhdl.structure import *
|
||||||
from migen.fhdl.structure import _Operator
|
from migen.fhdl.structure import _Operator
|
||||||
|
|
||||||
|
# multimux is deprecated - use Array instead
|
||||||
|
# TODO: remove uses of multimux
|
||||||
def multimux(sel, inputs, output):
|
def multimux(sel, inputs, output):
|
||||||
n = len(inputs)
|
n = len(inputs)
|
||||||
i = 0
|
i = 0
|
||||||
|
|
|
@ -223,7 +223,29 @@ class Case:
|
||||||
if self.default is None:
|
if self.default is None:
|
||||||
self.default = _StatementList()
|
self.default = _StatementList()
|
||||||
|
|
||||||
#
|
# arrays
|
||||||
|
|
||||||
|
class _ArrayProxy(Value):
|
||||||
|
def __init__(self, choices, key):
|
||||||
|
self.choices = choices
|
||||||
|
self.key = key
|
||||||
|
|
||||||
|
def __getattr__(self, attr):
|
||||||
|
return _ArrayProxy([getattr(choice, attr) for choice in self.choices],
|
||||||
|
self.key)
|
||||||
|
|
||||||
|
def __getitem__(self, key):
|
||||||
|
return _ArrayProxy([choice.__getitem__(key) for choice in self.choices],
|
||||||
|
self.key)
|
||||||
|
|
||||||
|
class Array(list):
|
||||||
|
def __getitem__(self, key):
|
||||||
|
if isinstance(key, Value):
|
||||||
|
return _ArrayProxy(self, key)
|
||||||
|
else:
|
||||||
|
return super().__getitem__(key)
|
||||||
|
|
||||||
|
# extras
|
||||||
|
|
||||||
class Instance:
|
class Instance:
|
||||||
def __init__(self, of, outs=[], ins=[], inouts=[], parameters=[], clkport="", rstport="", name=""):
|
def __init__(self, of, outs=[], ins=[], inouts=[], parameters=[], clkport="", rstport="", name=""):
|
||||||
|
@ -270,6 +292,8 @@ class Memory:
|
||||||
self.ports = ports
|
self.ports = ports
|
||||||
self.init = init
|
self.init = init
|
||||||
|
|
||||||
|
#
|
||||||
|
|
||||||
class Fragment:
|
class Fragment:
|
||||||
def __init__(self, comb=None, sync=None, instances=None, memories=None, sim=None):
|
def __init__(self, comb=None, sync=None, instances=None, memories=None, sim=None):
|
||||||
if comb is None: comb = []
|
if comb is None: comb = []
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
|
from copy import copy
|
||||||
|
|
||||||
from migen.fhdl.structure import *
|
from migen.fhdl.structure import *
|
||||||
from migen.fhdl.structure import _Operator, _Slice, _Assign, _StatementList
|
from migen.fhdl.structure import _Operator, _Slice, _Assign, _StatementList, _ArrayProxy
|
||||||
|
|
||||||
def list_signals(node):
|
def list_signals(node):
|
||||||
if node is None:
|
if node is None:
|
||||||
|
@ -123,3 +125,98 @@ def insert_reset(rst, sl):
|
||||||
targets = list_targets(sl)
|
targets = list_targets(sl)
|
||||||
resetcode = [t.eq(t.reset) for t in targets]
|
resetcode = [t.eq(t.reset) for t in targets]
|
||||||
return If(rst, *resetcode).Else(*sl.l)
|
return If(rst, *resetcode).Else(*sl.l)
|
||||||
|
|
||||||
|
def _lower_arrays_values(vl):
|
||||||
|
r = []
|
||||||
|
extra_comb = []
|
||||||
|
for v in vl:
|
||||||
|
v2, e = _lower_arrays_value(v)
|
||||||
|
extra_comb += e
|
||||||
|
r.append(v2)
|
||||||
|
return r, extra_comb
|
||||||
|
|
||||||
|
def _lower_arrays_value(v):
|
||||||
|
if isinstance(v, _Operator):
|
||||||
|
op2, e = _lower_arrays_values(v.operands)
|
||||||
|
return _Operator(v.op, op2), e
|
||||||
|
elif isinstance(v, _Slice):
|
||||||
|
v2, e = _lower_arrays_value(v.value)
|
||||||
|
return _Slice(v2, v.start, v.stop), e
|
||||||
|
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, Constant):
|
||||||
|
return v, []
|
||||||
|
elif isinstance(v, Signal):
|
||||||
|
return v, []
|
||||||
|
elif isinstance(v, _ArrayProxy):
|
||||||
|
choices2, e = _lower_arrays_values(v.choices)
|
||||||
|
array_muxed = Signal(BV(32)) # TODO: use the correct BV
|
||||||
|
cases = [[Constant(n), _Assign(array_muxed, choice)]
|
||||||
|
for n, choice in enumerate(choices2)]
|
||||||
|
cases[-1][0] = Default()
|
||||||
|
e.append(Case(v.key, *cases))
|
||||||
|
return array_muxed, e
|
||||||
|
|
||||||
|
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):
|
||||||
|
result = _StatementList()
|
||||||
|
rs = result.l
|
||||||
|
extra_comb = []
|
||||||
|
for statement in sl.l:
|
||||||
|
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 result, extra_comb
|
||||||
|
|
||||||
|
def lower_arrays(f):
|
||||||
|
f = copy(f)
|
||||||
|
f.comb, ec1 = _lower_arrays_sl(f.comb)
|
||||||
|
f.sync, ec2 = _lower_arrays_sl(f.sync)
|
||||||
|
f.comb.l += ec1 + ec2
|
||||||
|
return f
|
||||||
|
|
|
@ -247,6 +247,8 @@ def convert(f, ios=set(), name="top",
|
||||||
if rst_signal is None:
|
if rst_signal is None:
|
||||||
rst_signal = Signal(name_override="sys_rst")
|
rst_signal = Signal(name_override="sys_rst")
|
||||||
ios.add(rst_signal)
|
ios.add(rst_signal)
|
||||||
|
|
||||||
|
f = lower_arrays(f)
|
||||||
|
|
||||||
ns = build_namespace(list_signals(f) \
|
ns = build_namespace(list_signals(f) \
|
||||||
| list_inst_ios(f, True, True, True) \
|
| list_inst_ios(f, True, True, True) \
|
||||||
|
|
Loading…
Reference in New Issue