From eed8fa374d876d89e23a2db760ae92ad002e8bfa Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Wed, 11 Jul 2012 12:06:32 +0200 Subject: [PATCH] fhdl/arrays: use correct BV for intermediate signals --- examples/basic/arrays.py | 4 ++-- migen/fhdl/tools.py | 52 ++++++++++++++++++++++++++++++++++------ 2 files changed, 47 insertions(+), 9 deletions(-) diff --git a/examples/basic/arrays.py b/examples/basic/arrays.py index 4081f8513..0dc332431 100644 --- a/examples/basic/arrays.py +++ b/examples/basic/arrays.py @@ -4,8 +4,8 @@ from migen.fhdl import verilog dx = 5 dy = 5 -x = Signal(BV(bits_for(dx))) -y = Signal(BV(bits_for(dy))) +x = Signal(BV(bits_for(dx-1))) +y = Signal(BV(bits_for(dy-1))) out = Signal() my_2d_array = Array(Array(Signal() for a in range(dx)) for b in range(dy)) diff --git a/migen/fhdl/tools.py b/migen/fhdl/tools.py index f79002966..a2f3f78a4 100644 --- a/migen/fhdl/tools.py +++ b/migen/fhdl/tools.py @@ -126,6 +126,44 @@ def insert_reset(rst, sl): resetcode = [t.eq(t.reset) for t in targets] return If(rst, *resetcode).Else(*sl.l) +def value_bv(v): + if isinstance(v, Constant): + return v.bv + elif isinstance(v, Signal): + return v.bv + elif isinstance(v, _Operator): + obv = map(value_bv, v.operands) + if v.op == "+" or v.op == "-": + return BV(max(obv[0].width, obv[1].width) + 1, + obv[0].signed and obv[1].signed) + elif v.op == "*": + signed = obv[0].signed and obv[1].signed + if signed: + return BV(obv[0].width + obv[1].width - 1, signed) + else: + return BV(obv[0].width + obv[1].width, signed) + elif v.op == "<<" or v.op == ">>": + return obv[0].bv + elif v.op == "&" or v.op == "^" or v.op == "|": + return BV(max(obv[0].width, obv[1].width), + obv[0].signed and obv[1].signed) + elif v.op == "<" or v.op == "<=" or v.op == "==" or v.op == "!=" \ + or v.op == ">" or v.op == ">=": + return BV(1) + else: + raise TypeError + elif isinstance(v, _Slice): + return BV(v.stop - v.start, value_bv(v.value).signed) + elif isinstance(v, Cat): + return BV(sum(value_bv(sv).width for sv in v.l)) + elif isinstance(v, Replicate): + return BV(value_bv(v.v).width*v.n) + elif isinstance(v, _ArrayProxy): + bvc = map(value_bv, v.choices) + return BV(max(bv.width for bv in bvc), any(bv.signed for bv in bvc)) + else: + raise TypeError + def _lower_arrays_values(vl): r = [] extra_comb = [] @@ -134,9 +172,13 @@ def _lower_arrays_values(vl): extra_comb += e r.append(v2) return r, extra_comb - + def _lower_arrays_value(v): - if isinstance(v, _Operator): + if isinstance(v, Constant): + return v, [] + elif isinstance(v, Signal): + return v, [] + elif isinstance(v, _Operator): op2, e = _lower_arrays_values(v.operands) return _Operator(v.op, op2), e elif isinstance(v, _Slice): @@ -148,13 +190,9 @@ def _lower_arrays_value(v): 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 + array_muxed = Signal(value_bv(v)) cases = [[Constant(n), _Assign(array_muxed, choice)] for n, choice in enumerate(choices2)] cases[-1][0] = Default()