fhdl: arrays (TODO: use correct BV for intermediate signals)

This commit is contained in:
Sebastien Bourdeauducq 2012-07-09 15:16:38 +02:00
parent c82a468506
commit ed27783a53
5 changed files with 152 additions and 2 deletions

25
examples/basic/arrays.py Normal file
View File

@ -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))

View File

@ -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

View File

@ -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 = []

View File

@ -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

View File

@ -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) \