Exemple #1
0
class Join(with_metaclass(ParametrizedSingleton, PythonTrigger)):
    """Join a coroutine, firing when it exits."""
    @classmethod
    def __singleton_key__(cls, coroutine):
        return coroutine

    def __init__(self, coroutine):
        super(Join, self).__init__()
        self._coroutine = coroutine
        self.pass_retval = True

    @property
    def _outcome(self):
        return self._coroutine._outcome

    @property
    def retval(self):
        return self._coroutine.retval

    def prime(self, callback):
        if self._coroutine._finished:
            callback(self)
        else:
            super(Join, self).prime(callback)

    def __str__(self):
        return self.__class__.__name__ + "(%s)" % self._coroutine.__name__
Exemple #2
0
class _EdgeBase(with_metaclass(_ParameterizedSingletonAndABC, GPITrigger)):
    """Internal base class that fires on a given edge of a signal."""
    __slots__ = ('signal',)

    @classmethod
    @property
    def _edge_type(self):
        """The edge type, as understood by the C code. Must be set in subclasses."""
        raise NotImplementedError

    @classmethod
    def __singleton_key__(cls, signal):
        return signal

    def __init__(self, signal):
        super(_EdgeBase, self).__init__()
        self.signal = signal

    def prime(self, callback):
        """Register notification of a value change via a callback"""
        if self.cbhdl == 0:
            self.cbhdl = simulator.register_value_change_callback(
                self.signal._handle, callback, type(self)._edge_type, self
            )
            if self.cbhdl == 0:
                raise_error(self, "Unable set up %s Trigger" % (str(self)))
        super(_EdgeBase, self).prime(callback)

    def __str__(self):
        return self.__class__.__name__ + "(%s)" % self.signal._name
Exemple #3
0
class _EdgeBase(with_metaclass(ParametrizedSingleton, GPITrigger)):
    """Execution will resume when an edge occurs on the provided signal."""
    @classmethod
    @property
    def _edge_type(self):
        """The edge type, as understood by the C code. Must be set in subclasses."""
        raise NotImplementedError

    @classmethod
    def __singleton_key__(cls, signal):
        return signal

    def __init__(self, signal):
        super(_EdgeBase, self).__init__()
        self.signal = signal

    def prime(self, callback):
        """Register notification of a value change via a callback"""
        if self.cbhdl == 0:
            self.cbhdl = simulator.register_value_change_callback(
                self.signal._handle, callback,
                type(self)._edge_type, self)
            if self.cbhdl == 0:
                raise_error(self, "Unable set up %s Trigger" % (str(self)))
        super(_EdgeBase, self).prime()

    def __str__(self):
        return self.__class__.__name__ + "(%s)" % self.signal._name
Exemple #4
0
class Join(with_metaclass(_ParameterizedSingletonAndABC, PythonTrigger)):
    """Join a coroutine, firing when it exits."""
    __slots__ = ('_coroutine',)

    @classmethod
    def __singleton_key__(cls, coroutine):
        return coroutine

    def __init__(self, coroutine):
        super(Join, self).__init__()
        self._coroutine = coroutine

    @property
    def _outcome(self):
        return self._coroutine._outcome

    @property
    def retval(self):
        """The return value of the joined coroutine.

        If the coroutine threw an exception, this attribute will re-raise it.
        """
        return self._coroutine.retval

    def prime(self, callback):
        if self._coroutine._finished:
            callback(self)
        else:
            super(Join, self).prime(callback)

    def __str__(self):
        return self.__class__.__name__ + "(%s)" % self._coroutine.__name__
Exemple #5
0
class ReadOnly(with_metaclass(_ParameterizedSingletonAndABC, GPITrigger)):
    """Fires when the current simulation timestep moves to the readonly phase.

    The :any:`ReadOnly` phase is entered when the current timestep no longer has any further delta steps.
    This will be a point where all the signal values are stable as there are no more RTL events scheduled for the timestep.
    The simulator will not allow scheduling of more events in this timestep.
    Useful for monitors which need to wait for all processes to execute (both RTL and cocotb) to ensure sampled signal values are final.
    """
    __slots__ = ()

    @classmethod
    def __singleton_key__(cls):
        return None

    def __init__(self):
        GPITrigger.__init__(self)

    def prime(self, callback):
        if self.cbhdl == 0:
            self.cbhdl = simulator.register_readonly_callback(callback, self)
            if self.cbhdl == 0:
                raise_error(self, "Unable set up %s Trigger" % (str(self)))
        GPITrigger.prime(self, callback)

    def __str__(self):
        return self.__class__.__name__ + "(readonly)"
Exemple #6
0
class hook(with_metaclass(_decorator_helper, coroutine)):
    """Decorator to mark a function as a hook for cocotb.

    Used as ``@cocotb.hook()``.

    All hooks are run at the beginning of a cocotb test suite, prior to any
    test code being run."""
    def __init__(self, f):
        super(hook, self).__init__(f)
        self.im_hook = True
        self.name = self._func.__name__

    def __call__(self, *args, **kwargs):
        try:
            return RunningCoroutine(self._func(*args, **kwargs), self)
        except Exception as e:
            raise raise_error(self, "Hook raised exception:")
Exemple #7
0
class test(with_metaclass(_decorator_helper, coroutine)):
    """Decorator to mark a function as a test.

    All tests are coroutines.  The test decorator provides
    some common reporting etc., a test timeout and allows
    us to mark tests as expected failures.

    Used as ``@cocotb.test(...)``.

    Args:
        timeout (int, optional):
            value representing simulation timeout (not implemented).
        expect_fail (bool, optional):
            Don't mark the result as a failure if the test fails.
        expect_error (bool, optional):
            Don't mark the result as an error if an error is raised.
            This is for cocotb internal regression use 
            when a simulator error is expected.
        skip (bool, optional):
            Don't execute this test as part of the regression.
        stage (int, optional)
            Order tests logically into stages, where multiple tests can share a stage.
    """
    def __init__(self,
                 f,
                 timeout=None,
                 expect_fail=False,
                 expect_error=False,
                 skip=False,
                 stage=None):
        super(test, self).__init__(f)

        self.timeout = timeout
        self.expect_fail = expect_fail
        self.expect_error = expect_error
        self.skip = skip
        self.stage = stage
        self.im_test = True  # For auto-regressions
        self.name = self._func.__name__

    def __call__(self, *args, **kwargs):
        try:
            return RunningTest(self._func(*args, **kwargs), self)
        except Exception as e:
            raise raise_error(self, "Test raised exception:")
Exemple #8
0
class NextTimeStep(with_metaclass(ParametrizedSingleton, GPITrigger)):
    """Execution will resume when the next time step is started."""
    @classmethod
    def __singleton_key__(cls):
        return None

    def __init__(self):
        GPITrigger.__init__(self)

    def prime(self, callback):
        if self.cbhdl == 0:
            self.cbhdl = simulator.register_nextstep_callback(callback, self)
            if self.cbhdl == 0:
                raise_error(self, "Unable set up %s Trigger" % (str(self)))
        Trigger.prime(self)

    def __str__(self):
        return self.__class__.__name__ + "(nexttimestep)"
Exemple #9
0
class ReadOnly(with_metaclass(ParametrizedSingleton, GPITrigger)):
    """Execution will resume when the readonly portion of the sim cycles is
    reached.
    """
    @classmethod
    def __singleton_key__(cls):
        return None

    def __init__(self):
        GPITrigger.__init__(self)

    def prime(self, callback):
        if self.cbhdl == 0:
            self.cbhdl = simulator.register_readonly_callback(callback, self)
            if self.cbhdl == 0:
                raise_error(self, "Unable set up %s Trigger" % (str(self)))
        Trigger.prime(self)

    def __str__(self):
        return self.__class__.__name__ + "(readonly)"
Exemple #10
0
class ReadWrite(with_metaclass(_ParameterizedSingletonAndABC, GPITrigger)):
    """Fires when the readwrite portion of the sim cycles is reached."""
    __slots__ = ()

    @classmethod
    def __singleton_key__(cls):
        return None

    def __init__(self):
        GPITrigger.__init__(self)

    def prime(self, callback):
        if self.cbhdl == 0:
            # import pdb
            # pdb.set_trace()
            self.cbhdl = simulator.register_rwsynch_callback(callback, self)
            if self.cbhdl == 0:
                raise_error(self, "Unable set up %s Trigger" % (str(self)))
        GPITrigger.prime(self, callback)

    def __str__(self):
        return self.__class__.__name__ + "(readwritesync)"
class ReadWrite(with_metaclass(ParametrizedSingleton, GPITrigger)):
    """Execution will resume when the readwrite portion of the sim cycles is
    reached.
    """
    @classmethod
    def __singleton_key__(cls):
        return None

    def __init__(self):
        GPITrigger.__init__(self)

    def prime(self, callback):
        """FIXME: document"""
        if self.cbhdl == 0:
            # import pdb
            # pdb.set_trace()
            self.cbhdl = simulator.register_rwsynch_callback(callback, self)
            if self.cbhdl == 0:
                raise_error(self, "Unable set up %s Trigger" % (str(self)))
        Trigger.prime(self)

    def __str__(self):
        return self.__class__.__name__ + "(readwritesync)"
Exemple #12
0
class Trigger(with_metaclass(abc.ABCMeta)):
    """Base class to derive from."""
    __slots__ = ('primed', '__weakref__')

    def __init__(self):
        self.primed = False

    @lazy_property
    def log(self):
        return SimLog("cocotb.%s" % (self.__class__.__name__), id(self))

    @abc.abstractmethod
    def prime(self, callback):
        """Set a callback to be invoked when the trigger fires.

        The callback will be invoked with a single argumement, `self`.

        Subclasses must override this, but should end by calling the base class
        method.

        Do not call this directly within coroutines, it is intended to be used
        only by the scheduler.
        """
        self.primed = True

    def unprime(self):
        """Remove the callback, and perform cleanup if necessary.

        After being unprimed, a Trigger may be reprimed again in future.
        Calling `unprime` multiple times is allowed, subsequent calls should be
        a no-op.

        Subclasses may override this, but should end by calling the base class
        method.

        Do not call this directly within coroutines, it is intended to be used
        only by the scheduler.
        """
        self.primed = False

    def __del__(self):
        # Ensure if a trigger drops out of scope we remove any pending callbacks
        self.unprime()

    def __str__(self):
        return self.__class__.__name__

    @property
    def _outcome(self):
        """The result that `yield this_trigger` produces in a coroutine.

        The default is to produce the trigger itself, which is done for
        ease of use with :class:`~cocotb.triggers.First`.
        """
        return outcomes.Value(self)

    # Once 2.7 is dropped, this can be run unconditionally
    if sys.version_info >= (3, 3):
        exec_(textwrap.dedent("""
        def __await__(self):
            # hand the trigger back to the scheduler trampoline
            return (yield self)
        """))
Exemple #13
0
class Trigger(with_metaclass(abc.ABCMeta)):
    """Base class to derive from."""

    # __dict__ is needed here for the `.log` lazy_property below to work.
    # The implementation of `_PyObject_GenericGetAttrWithDict` suggests that
    # despite its inclusion, __slots__ will overall give speed and memory
    # improvements:
    #  - the `__dict__` is not actually constructed until it's needed, and that
    #    only happens if the `.log` attribute is used, where performance
    #    concerns no longer matter.
    #  - Attribute setting and getting will still go through the slot machinery
    #    first, as "data descriptors" take priority over dict access
    __slots__ = ('primed', '__weakref__', '__dict__')

    def __init__(self):
        self.primed = False

    @lazy_property
    def log(self):
        return SimLog("cocotb.%s" % (self.__class__.__name__), id(self))

    @abc.abstractmethod
    def prime(self, callback):
        """Set a callback to be invoked when the trigger fires.

        The callback will be invoked with a single argumement, `self`.

        Subclasses must override this, but should end by calling the base class
        method.

        Do not call this directly within coroutines, it is intended to be used
        only by the scheduler.
        """
        self.primed = True

    def unprime(self):
        """Remove the callback, and perform cleanup if necessary.

        After being unprimed, a Trigger may be reprimed again in future.
        Calling `unprime` multiple times is allowed, subsequent calls should be
        a no-op.

        Subclasses may override this, but should end by calling the base class
        method.

        Do not call this directly within coroutines, it is intended to be used
        only by the scheduler.
        """
        self.primed = False

    def __del__(self):
        # Ensure if a trigger drops out of scope we remove any pending callbacks
        self.unprime()

    def __str__(self):
        return self.__class__.__name__

    @property
    def _outcome(self):
        """The result that `yield this_trigger` produces in a coroutine.

        The default is to produce the trigger itself, which is done for
        ease of use with :class:`~cocotb.triggers.First`.
        """
        return outcomes.Value(self)

    # Once 2.7 is dropped, this can be run unconditionally
    if sys.version_info >= (3, 3):
        exec_(textwrap.dedent("""
        def __await__(self):
            # hand the trigger back to the scheduler trampoline
            return (yield self)
        """))
Exemple #14
0
class Join(with_metaclass(_ParameterizedSingletonAndABC, PythonTrigger)):
    r"""Fires when a :func:`fork`\ ed coroutine completes

    The result of blocking on the trigger can be used to get the coroutine
    result::

        @cocotb.coroutine()
        def coro_inner():
            yield Timer(1)
            raise ReturnValue("Hello world")

        task = cocotb.fork(coro_inner())
        result = yield Join(task)
        assert result == "Hello world"

    Or using the syntax in Python 3.5 onwards:

    .. code-block:: python3

        @cocotb.coroutine()
        async def coro_inner():
            await Timer(1)
            return "Hello world"

        task = cocotb.fork(coro_inner())
        result = await Join(task)
        assert result == "Hello world"

    If the coroutine threw an exception, the :keyword:`await` or :keyword:`yield`
    will re-raise it.

    """
    __slots__ = ('_coroutine',)

    @classmethod
    def __singleton_key__(cls, coroutine):
        return coroutine

    def __init__(self, coroutine):
        super(Join, self).__init__()
        self._coroutine = coroutine

    @property
    def _outcome(self):
        return self._coroutine._outcome

    @property
    def retval(self):
        """The return value of the joined coroutine.

        .. note::
            Typically there is no need to use this attribute - the
            following code samples are equivalent::

                forked = cocotb.fork(mycoro())
                j = Join(forked)
                yield j
                result = j.retval

            ::

                forked = cocotb.fork(mycoro())
                result = yield Join(forked)
        """
        return self._coroutine.retval

    def prime(self, callback):
        if self._coroutine._finished:
            callback(self)
        else:
            super(Join, self).prime(callback)

    def __str__(self):
        return self.__class__.__name__ + "(%s)" % self._coroutine.__name__