diff --git a/myhdl/_ShadowSignal.py b/myhdl/_ShadowSignal.py index 299e36f2..099f68c9 100644 --- a/myhdl/_ShadowSignal.py +++ b/myhdl/_ShadowSignal.py @@ -23,13 +23,19 @@ """ from myhdl._Signal import _Signal +from myhdl._Waiter import _SignalWaiter, _SignalTupleWaiter +from myhdl._intbv import intbv # shadow signals class _ShadowSignal(_Signal): - __slots__ = ('gen', ) + __slots__ = ('gen', 'waiter') + + def __init__(self, val): + _Signal.__init__(self, val) + self.driven = True @@ -40,9 +46,9 @@ class _SliceSignal(_ShadowSignal): def __init__(self, sig, left, right=None): ### XXX error checks if right is None: - _Signal.__init__(self, sig[left]) + _ShadowSignal.__init__(self, sig[left]) else: - _Signal.__init__(self, sig[left:right]) + _ShadowSignal.__init__(self, sig[left:right]) self.sig = sig self.left = left self.right = right @@ -50,7 +56,7 @@ class _SliceSignal(_ShadowSignal): self.gen = self.genfuncIndex() else: self.gen = self.genfuncSlice() - self._driven = True + self.waiter = _SignalWaiter(self.gen) def genfuncIndex(self): sig, index = self.sig, self.left @@ -77,3 +83,42 @@ class _SliceSignal(_ShadowSignal): return "%s <= %s(%s);" % (self._name, self.sig._name, self.left) else: return "%s <= %s(%s-1 downto %s);" % (self._name, self.sig._name, self.left, self.right) + + + +class ConcatSignal(_ShadowSignal): + + __slots__ = ('_args',) + + def __init__(self, *args): + assert len(args) >= 2 + self._args = args + ### XXX error checks + nrbits = 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 + _ShadowSignal.__init__(self, ini) + self.gen = self.genfunc() + self.waiter = _SignalTupleWaiter(self.gen) + + def genfunc(self): + set_next = _Signal._set_next + args = self._args + nrbits = self._nrbits + newval = intbv(0)[nrbits:] + while 1: + hi = nrbits + for a in args: + lo = hi - len(a) + newval[hi:lo] = a + hi = lo + set_next(self, newval) + yield args + + diff --git a/myhdl/_Simulation.py b/myhdl/_Simulation.py index 6046798d..34b39fd4 100644 --- a/myhdl/_Simulation.py +++ b/myhdl/_Simulation.py @@ -224,10 +224,9 @@ def _makeWaiters(arglist): raise SimulationError(_error.DuplicatedArg) ids.add(id(arg)) # add waiters for shadow signals - # waiter wrapping done here to avoid circular imports for sig in _signals: if not isinstance(sig, _ShadowSignal): continue - waiters.append(_SignalWaiter(sig.gen)) + waiters.append(sig.waiter) return waiters, cosim diff --git a/myhdl/__init__.py b/myhdl/__init__.py index d26e661a..39dfa355 100644 --- a/myhdl/__init__.py +++ b/myhdl/__init__.py @@ -24,6 +24,7 @@ Simulation -- simulation class StopStimulation -- exception that stops a simulation now -- function that returns the current time Signal -- class to model hardware signals +ConcatSignal -- class that models a concatenation shadow signal delay -- callable to model delay in a yield statement posedge -- callable to model a rising edge on a signal in a yield statement negedge -- callable to model a falling edge on a signal in a yield statement @@ -36,7 +37,6 @@ bin -- returns a binary string representation. concat -- function to concat ints, bitstrings, bools, intbvs, Signals -- returns an intbv instances -- function that returns all instances defined in a function -processes -- function that returns all processes defined in a function always_comb -- function that returns an input-sensitive generator enum -- function that returns an enumeration type traceSignals -- function that enables signal tracing in a VCD file @@ -110,6 +110,7 @@ from _concat import concat from _intbv import intbv from _join import join from _Signal import posedge, negedge, Signal +from _ShadowSignal import ConcatSignal from _simulator import now from _delay import delay from _Cosimulation import Cosimulation @@ -135,6 +136,7 @@ __all__ = ["bin", "posedge", "negedge", "Signal", + "ConcatSignal", "now", "delay", "downrange", diff --git a/myhdl/test/core2/test_ShadowSignal.py b/myhdl/test/core2/test_ShadowSignal.py index cdfd3964..9c09adc1 100644 --- a/myhdl/test/core2/test_ShadowSignal.py +++ b/myhdl/test/core2/test_ShadowSignal.py @@ -1,6 +1,6 @@ from myhdl import * -def bench_ShadowSignal(): +def bench_SliceSignal(): s = Signal(intbv(0)[8:]) a, b, c = s(7), s(5), s(0) @@ -22,6 +22,41 @@ def bench_ShadowSignal(): return check -def test_ShadowSignal(): - Simulation(bench_ShadowSignal()).run() +def test_SliceSignal(): + Simulation(bench_SliceSignal()).run() + + +def bench_ConcatSignal(): + + a = Signal(intbv(0)[8:]) + b = Signal(bool(0)) + c = Signal(intbv(0)[3:]) + d = Signal(intbv(0)[4:]) + + s = ConcatSignal(a, b, c, d) + + @instance + def check(): + for i in range(2**len(a)): + for j in (0, 1): + for k in range(len(c)): + for m in range(len(d)): + a.next = i + b.next = j + c.next = k + d.next = m + yield delay(10) + assert s[16:8] == a + assert s[7] == b + assert s[7:4] == c + assert s[4:] == d + + return check + + +def test_ConcatSignal(): + Simulation(bench_ConcatSignal()).run() + + +