Beispiel #1
0
    def _coroutine_yielded(self, coro, trigger):
        """Prime the trigger and update our internal mappings."""
        self._coro2trigger[coro] = trigger

        trigger_coros = self._trigger2coros.setdefault(trigger, [])
        if coro is self._write_coro_inst:
            # Our internal write coroutine always runs before any user coroutines.
            # This preserves the behavior prior to the refactoring of writes to
            # this coroutine.
            trigger_coros.insert(0, coro)
        else:
            # Everything else joins the back of the queue
            trigger_coros.append(coro)

        if not trigger.primed:

            if trigger_coros != [coro]:
                # should never happen
                raise InternalError(
                    "More than one coroutine waiting on an unprimed trigger")

            try:
                trigger.prime(self.react)
            except Exception as e:
                # discard the trigger we associated, it will never fire
                self._trigger2coros.pop(trigger)

                # replace it with a new trigger that throws back the exception
                error_trigger = NullTrigger(outcome=outcomes.Error(e))
                self._coro2trigger[coro] = error_trigger
                self._trigger2coros[error_trigger] = [coro]

                # wake up the coroutines
                error_trigger.prime(self.react)
Beispiel #2
0
    def _write_default(self):
        '''
        Writes out the specified default transaction. If no default
        transaction was specified with the constructor, simply
        set the unknown signals to zero.
        '''

        # Generate a transaction with all the data signals. Set the
        # default values.
        default_dict = {}
        if self.__default_trans is not None:
            default_dict = vars(self.__default_trans)
        trans = self._interface.transaction(**default_dict)

        # If there are any data signals not assigned, assume their default
        # value should be zerp.
        for name, value in vars(trans).items():
            if value is None: setattr(trans, name, 0)

        # Write the transaction to the interface.
        self._interface.write(trans)

        # Yielding on a null trigger is necessary since
        # every coroutine-decorate method needs to yield
        # on a trigger.
        yield NullTrigger()
Beispiel #3
0
 def _read(self):
     '''
     Samples from the interface and writes it out 
     on to the outport.
     '''
     self.outport.write(self._interface.read(), execute_behavior=True)
     yield NullTrigger()
Beispiel #4
0
 def _write_default(self):
     '''
     Writes out the default state of the handshake interface. Do not
     write over the data signals since we're reading from them.
     '''
     self._interface.rdy.value = 0
     yield NullTrigger()
Beispiel #5
0
 def _write(self, data):
     '''
     Writes out the queued data transasction
     to the interface.
     '''
     self._interface.write(data)
     yield NullTrigger()
Beispiel #6
0
    def _resume_coro_upon(self, coro, trigger):
        """Schedule `coro` to be resumed when `trigger` fires."""
        coro._trigger = trigger

        trigger_coros = self._trigger2coros.setdefault(trigger, [])
        if coro is self._write_coro_inst:
            # Our internal write coroutine always runs before any user coroutines.
            # This preserves the behavior prior to the refactoring of writes to
            # this coroutine.
            trigger_coros.insert(0, coro)
        else:
            # Everything else joins the back of the queue
            trigger_coros.append(coro)

        if not trigger.primed:

            if trigger_coros != [coro]:
                # should never happen
                raise InternalError(
                    "More than one coroutine waiting on an unprimed trigger")

            try:
                trigger.prime(self.react)
            except Exception as e:
                # discard the trigger we associated, it will never fire
                self._trigger2coros.pop(trigger)

                # replace it with a new trigger that throws back the exception
                self._resume_coro_upon(
                    coro,
                    NullTrigger(name="Trigger.prime() Error",
                                outcome=outcomes.Error(e)))
Beispiel #7
0
 def flush(self):
     '''
     Do not used this method with read port.
     '''
     raise NotImplementedError(
         "flush should not be used with the read driver.")
     yield NullTrigger()
Beispiel #8
0
 def wait(self):
     '''
     Yield on this method as a way to wait until
     all resets finish their operation.
     '''
     if not self.__event.fired:
         yield self.__event.wait()
     yield NullTrigger()
Beispiel #9
0
 def flush(self):
     '''
     Blocks until the driver's queue is
     empty.
     '''
     if self._ready() == True:
         self.__flushevt.clear()
         yield self.__flushevt.wait()
     yield NullTrigger()
Beispiel #10
0
 def _wait_reset(self, active_mode=1):
     '''
     Wait until reset is in an inactive state.
     '''
     rst = self.rst
     if str(rst.value) == 'z' or str(rst.value) == 'x' or int(
             rst.value) == active_mode:
         yield Edge(rst)
     yield NullTrigger()
Beispiel #11
0
    def add_test(self, test_coro):
        """Called by the regression manager to queue the next test"""
        if self._test is not None:
            raise InternalError("Test was added while another was in progress")

        self._test = test_coro
        self._resume_coro_upon(
            test_coro,
            NullTrigger(name="Start {!s}".format(test_coro),
                        outcome=outcomes.Value(None)))
Beispiel #12
0
    def _write(self):
        '''
        Writes out the queued data transasction
        to the interface.
        '''

        # Check the allow to determine if the driver is
        # allowed to set its ready.
        while next(self.allow) == False:
            self._interface.rdy.value = 0
            yield RegisterInterface._synchronize(self._interface)

        # Once it's finally allowed to read, set
        # the ready and continue.
        self._interface.rdy.value = 1
        yield NullTrigger()
Beispiel #13
0
    def _drive(self):
        '''
        Implements the behavior of the clock driver.
        '''

        for name, handle in vars(self._interface).items():
            params = getattr(self.__param_namespace, name, None)
            period = getattr(params, "period", None)
            phase = getattr(params, "phase", None)
            param_dict = {}
            if period is not None: param_dict["period"] = period
            if phase is not None: param_dict["phase"] = phase
            self.__log.info(
                "Starting clock {} with period {} and phase {}...".format(
                    name, period, phase))
            fork(start_clock(clock=handle, **param_dict))

        yield NullTrigger()
Beispiel #14
0
    def _write(self, data):
        '''
        Writes out the queued data transasction
        to the interface.
        '''

        # Write out the data.
        self._interface.write(data)

        # Check the allow to determine if the driver is
        # allowed to set its valid.
        while next(self.allow) == False:
            self._interface.vld.value = 0
            yield RegisterInterface._synchronize(self._interface)

        # Once it's finally allowed to write data, set
        # the valid and continue.
        self._interface.vld.value = 1
        yield NullTrigger()
Beispiel #15
0
    def schedule(self, coroutine, trigger=None):
        """Schedule a coroutine by calling the send method.

        Args:
            coroutine (cocotb.decorators.coroutine): The coroutine to schedule.
            trigger (cocotb.triggers.Trigger): The trigger that caused this
                coroutine to be scheduled.
        """
        with self._task_context(coroutine):
            if trigger is None:
                send_outcome = outcomes.Value(None)
            else:
                send_outcome = trigger._outcome
            if _debug:
                self.log.debug("Scheduling with {}".format(send_outcome))

            coro_completed = False
            try:
                coroutine._trigger = None
                result = coroutine._advance(send_outcome)
                if _debug:
                    self.log.debug("Coroutine %s yielded %s (mode %d)" %
                                   (coroutine._coro.__qualname__, str(result),
                                    self._mode))

            except cocotb.decorators.CoroutineComplete:
                if _debug:
                    self.log.debug("Coroutine {} completed with {}".format(
                        coroutine, coroutine._outcome))
                coro_completed = True

            # this can't go in the else above, as that causes unwanted exception
            # chaining
            if coro_completed:
                self.unschedule(coroutine)

            # Don't handle the result if we're shutting down
            if self._terminate:
                return

            if not coro_completed:
                try:
                    result = self._trigger_from_any(result)
                except TypeError as exc:
                    # restart this coroutine with an exception object telling it that
                    # it wasn't allowed to yield that
                    result = NullTrigger(outcome=outcomes.Error(exc))

                self._resume_coro_upon(coroutine, result)

            # We do not return from here until pending threads have completed, but only
            # from the main thread, this seems like it could be problematic in cases
            # where a sim might change what this thread is.

            if self._main_thread is threading.current_thread():

                for ext in self._pending_threads:
                    ext.thread_start()
                    if _debug:
                        self.log.debug(
                            "Blocking from %s on %s" %
                            (threading.current_thread(), ext.thread))
                    state = ext.thread_wait()
                    if _debug:
                        self.log.debug(
                            "Back from wait on self %s with newstate %d" %
                            (threading.current_thread(), state))
                    if state == external_state.EXITED:
                        self._pending_threads.remove(ext)
                        self._pending_events.append(ext.event)

            # Handle any newly queued coroutines that need to be scheduled
            while self._pending_coros:
                self.add(self._pending_coros.pop(0))
Beispiel #16
0
    def schedule(self, coroutine, trigger=None):
        """Schedule a coroutine by calling the send method.

        Args:
            coroutine (cocotb.decorators.coroutine): The coroutine to schedule.
            trigger (cocotb.triggers.Trigger): The trigger that caused this
                coroutine to be scheduled.
        """
        if trigger is None:
            send_outcome = outcomes.Value(None)
        else:
            send_outcome = trigger._outcome
        if _debug:
            self.log.debug("Scheduling with {}".format(send_outcome))

        try:
            result = coroutine._advance(send_outcome)
            if _debug:
                self.log.debug("Coroutine %s yielded %s (mode %d)" %
                               (coroutine.__name__, str(result), self._mode))

        # TestComplete indication is game over, tidy up
        except TestComplete as test_result:
            # Tag that close down is needed, save the test_result
            # for later use in cleanup handler
            self.log.debug("TestComplete received: %s" % test_result.__class__.__name__)
            self.finish_test(test_result)
            return

        # Normal coroutine completion
        except cocotb.decorators.CoroutineComplete as exc:
            if _debug:
                self.log.debug("Coroutine completed: %s" % str(coroutine))
            self.unschedule(coroutine)
            return

        # Don't handle the result if we're shutting down
        if self._terminate:
            return

        try:
            result = self._trigger_from_any(result)
        except TypeError as exc:
            # restart this coroutine with an exception object telling it that
            # it wasn't allowed to yield that
            result = NullTrigger(outcome=outcomes.Error(exc))

        self._coroutine_yielded(coroutine, result)

        # We do not return from here until pending threads have completed, but only
        # from the main thread, this seems like it could be problematic in cases
        # where a sim might change what this thread is.
        def unblock_event(ext):
            @cocotb.coroutine
            def wrapper():
                ext.event.set()
                yield PythonTrigger()

        if self._main_thread is threading.current_thread():

            for ext in self._pending_threads:
                ext.thread_start()
                if _debug:
                    self.log.debug("Blocking from %s on %s" % (threading.current_thread(), ext.thread))
                state = ext.thread_wait()
                if _debug:
                    self.log.debug("Back from wait on self %s with newstate %d" % (threading.current_thread(), state))
                if state == external_state.EXITED:
                    self._pending_threads.remove(ext)
                    self._pending_events.append(ext.event)

        # Handle any newly queued coroutines that need to be scheduled
        while self._pending_coros:
            self.add(self._pending_coros.pop(0))
Beispiel #17
0
 def _wait_reset(self):
     '''
     Do not wait on reset; immediately start writing out any new value.
     '''
     yield NullTrigger()
Beispiel #18
0
 def join(self):
     """Return a trigger that will fire when the wrapped coroutine exits"""
     if self._finished:
         return NullTrigger()
     else:
         return self._join
Beispiel #19
0
def example():
    yield NullTrigger()
Beispiel #20
0
def generator_test(dut, arg):
    generator_testfactory_args.add(arg)
    yield NullTrigger()
Beispiel #21
0
def unblock_external(bridge):
    yield NullTrigger()
    bridge.set_out()
Beispiel #22
0
 def null_coroutine():
     yield NullTrigger()
Beispiel #23
0
 def _synchronize(self):
     '''
     Remove synchronization, since the intent is to always write out any new
     data.
     '''
     yield NullTrigger()