diff --git a/myhdl/_ShadowSignal.py b/myhdl/_ShadowSignal.py index b8677d9b..7df529e1 100644 --- a/myhdl/_ShadowSignal.py +++ b/myhdl/_ShadowSignal.py @@ -119,21 +119,39 @@ class _SliceSignal(_ShadowSignal): class ConcatSignal(_ShadowSignal): - __slots__ = ('_args',) + __slots__ = ('_args', '_sigargs', '_initval') def __init__(self, *args): assert len(args) >= 2 self._args = args - ### XXX error checks + self._sigargs = sigargs = [] + nrbits = 0 + val = 0 for a in args: - nrbits += len(a) - ini = intbv(0)[nrbits:] - hi = nrbits - for a in args: - lo = hi - len(a) - ini[hi:lo] = a - hi = lo + if isinstance(a, intbv): + w = a._nrbits + v = a._val + elif isinstance(a, _Signal): + sigargs.append(a) + w = a._nrbits + if isinstance(a._val, intbv): + v = a._val._val + else: + v = a._val + elif isinstance(a, bool): + w = 1 + v = a + elif isinstance(a, str): + w = len(a) + v = long(a, 2) + else: + raise TypeError("ConcatSignal: inappropriate argument type: %s" \ + % type(arg)) + nrbits += w + val = val << w | v & (long(1) << w)-1 + self._initval = val + ini = intbv(val)[nrbits:] _ShadowSignal.__init__(self, ini) gen = self.genfunc() self._waiter = _SignalTupleWaiter(gen) @@ -141,25 +159,31 @@ class ConcatSignal(_ShadowSignal): def genfunc(self): set_next = _Signal.next.fset args = self._args + sigargs = self._sigargs nrbits = self._nrbits - newval = intbv(0)[nrbits:] + newval = intbv(self._initval)[nrbits:] while 1: hi = nrbits for a in args: - lo = hi - len(a) - newval[hi:lo] = a + if isinstance(a, bool): + w = 1 + else: + w = len(a) + lo = hi - w + if a in sigargs: + newval[hi:lo] = a hi = lo set_next(self, newval) - yield args + yield sigargs def _markRead(self): self._read = True - for s in self._args: + for s in self._sigargs: s._markRead() def _markUsed(self): self._used = True - for s in self._args: + for s in self._sigargs: s._markUsed() def toVHDL(self): diff --git a/myhdl/test/core/test_ShadowSignal.py b/myhdl/test/core/test_ShadowSignal.py index 62f65a05..3430a3d7 100644 --- a/myhdl/test/core/test_ShadowSignal.py +++ b/myhdl/test/core/test_ShadowSignal.py @@ -47,17 +47,53 @@ def bench_ConcatSignal(): c.next = k d.next = m yield delay(10) - assert s[16:8] == a + assert s[13:8] == a assert s[7] == b assert s[7:4] == c assert s[4:] == d return check - def test_ConcatSignal(): Simulation(bench_ConcatSignal()).run() +def bench_ConcatSignalWithConsts(): + + a = Signal(intbv(0)[5:]) + b = Signal(bool(0)) + c = Signal(intbv(0)[3:]) + d = Signal(intbv(0)[4:]) + c1 = "10" + c2 = '0' + c3 = intbv(5)[3:] + c4 = bool(1) + + s = ConcatSignal(c1, a, c2, b, c3, c, c4, d) + + @instance + def check(): + for i in range(2**len(a)): + for j in (0, 1): + for k in range(2**len(c)): + for m in range(2**len(d)): + a.next = i + b.next = j + c.next = k + d.next = m + yield delay(10) + assert s[20:18] == long(c1, 2) + assert s[18:13] == a + assert s[12] == long(c2, 2) + assert s[11] == b + assert s[11:8] == c3 + assert s[8:5] == c + assert s[4] == c4 + assert s[4:] == d + + return check + +def test_ConcatSignalWithConsts(): + Simulation(bench_ConcatSignalWithConsts()).run() def bench_TristateSignal():