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 _Operator
|
||||
|
||||
# multimux is deprecated - use Array instead
|
||||
# TODO: remove uses of multimux
|
||||
def multimux(sel, inputs, output):
|
||||
n = len(inputs)
|
||||
i = 0
|
||||
|
|
|
@ -223,7 +223,29 @@ class Case:
|
|||
if self.default is None:
|
||||
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:
|
||||
def __init__(self, of, outs=[], ins=[], inouts=[], parameters=[], clkport="", rstport="", name=""):
|
||||
|
@ -270,6 +292,8 @@ class Memory:
|
|||
self.ports = ports
|
||||
self.init = init
|
||||
|
||||
#
|
||||
|
||||
class Fragment:
|
||||
def __init__(self, comb=None, sync=None, instances=None, memories=None, sim=None):
|
||||
if comb is None: comb = []
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
from copy import copy
|
||||
|
||||
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):
|
||||
if node is None:
|
||||
|
@ -123,3 +125,98 @@ def insert_reset(rst, sl):
|
|||
targets = list_targets(sl)
|
||||
resetcode = [t.eq(t.reset) for t in targets]
|
||||
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:
|
||||
rst_signal = Signal(name_override="sys_rst")
|
||||
ios.add(rst_signal)
|
||||
|
||||
f = lower_arrays(f)
|
||||
|
||||
ns = build_namespace(list_signals(f) \
|
||||
| list_inst_ios(f, True, True, True) \
|
||||
|
|
Loading…
Reference in New Issue