def prime(self, callback): """FIXME: document""" 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 prime(self, callback): if self.cbhdl is None: self.cbhdl = simulator.register_value_change_callback( self.signal._handle, callback, self._rising, self) if self.cbhdl is None: raise_error(self, "Unable set up %s Trigger" % (str(self))) Trigger.prime(self)
def _add_trigger(self, trigger, coroutine): """Adds a new trigger which will cause the coroutine to continue when fired""" try: # If we are in readonly for the currently firing trigger then new coroutines # are not added to the waiting list and primed, they are instead # added to a secondary list of events that will then be handled on the next # entry to react when we exit ReadOnly into NextTimeStep if self._readonly is True: self._entry_lock.acquire() self.delay_waiting[trigger].append(coroutine) self._entry_lock.release() else: self._entry_lock.acquire() self.waiting[trigger].append(coroutine) self._entry_lock.release() # We drop the lock before calling out to the simulator (most likely consequence of prime) trigger.prime(self.react) except TestError as e: self.waiting[trigger].remove(coroutine) # Do not re-call raise_error since the error will already be logged at point of interest raise e except Exception as e: self.waiting[trigger].remove(coroutine) raise_error(self, "Unable to prime a trigger: %s" % str(e))
def prime(self, callback): """Register notification of a value change via a callback""" if self.cbhdl is None: self.cbhdl = simulator.register_value_change_callback(self.signal._handle, callback, 3, self) if self.cbhdl is None: raise_error(self, "Unable set up %s Trigger" % (str(self))) Trigger.prime(self)
def prime(self, callback): """Register for a timed callback""" if self.cbhdl is None: self.cbhdl = simulator.register_timed_callback(self.time_ps, callback, self) if self.cbhdl is None: raise_error(self, "Unable set up %s Trigger" % (str(self))) Trigger.prime(self)
def prime(self, callback): self._callback = callback def _check(obj): if self.signal.value: self.num_cycles -= 1 if self.num_cycles <= 0: self._callback(self) return self.cbhdl = simulator.register_value_change_callback(self.signal. _handle, _check, self) if self.cbhdl is None: raise_error(self, "Unable set up %s Trigger" % (str(self))) self.cbhdl = simulator.register_value_change_callback(self.signal. _handle, _check, self) if self.cbhdl is None: raise_error(self, "Unable set up %s Trigger" % (str(self))) Trigger.prime(self)
def send(self, value): if not self.started: self.error_messages = [] self.log.info("Starting test: \"%s\"\nDescription: %s" % (self.funcname, self.__doc__)) self.start_time = time.time() self.started = True try: self.log.debug("Sending trigger %s" % (str(value))) return self._coro.send(value) except TestComplete as e: if isinstance(e, TestFailure): self.log.warning(str(e)) else: self.log.info(str(e)) buff = StringIO() for message in self.error_messages: print(message, file=buff) e.stderr.write(buff.getvalue()) raise except StopIteration: raise TestSuccess() except Exception as e: raise_error(self, "Send raised exception: %s" % (str(e)))
def prime(self, callback): """FIXME: document""" self._callback = callback def _check(obj): self.unprime() if self.signal.value: self.num_cycles -= 1 if self.num_cycles <= 0: self._callback(self) return self.cbhdl = simulator.register_value_change_callback(self.signal. _handle, _check, self._rising, self) if self.cbhdl == 0: raise_error(self, "Unable set up %s Trigger" % (str(self))) self.cbhdl = simulator.register_value_change_callback(self.signal. _handle, _check, self._rising, self) if self.cbhdl == 0: raise_error(self, "Unable set up %s Trigger" % (str(self))) Trigger.prime(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))) Trigger.prime(self)
def prime(self, callback): """Register notification of a value change via a callback""" if self.cbhdl is None: self.cbhdl = simulator.register_value_change_callback( self.signal._handle, callback, 3, self) if self.cbhdl is None: raise_error(self, "Unable set up %s Trigger" % (str(self))) Trigger.prime(self)
def prime(self, callback): """Register for a timed callback""" if self.cbhdl == 0: self.cbhdl = simulator.register_timed_callback( self.sim_steps, callback, self) if self.cbhdl == 0: raise_error(self, "Unable set up %s Trigger" % (str(self))) Trigger.prime(self)
def _check(obj): if self.signal.value: self._callback(self) else: simulator.deregister_callback(self.cbhdl) self.cbhdl = simulator.create_callback(self) if simulator.register_value_change_callback(self.cbhdl, self.signal._handle, _check, self): raise_error(self, "Unable set up %s Trigger" % (str(self)))
def prime(self, callback): if self.cbhdl is None: #import pdb #pdb.set_trace() self.cbhdl = simulator.register_rwsynch_callback(callback, self) if self.cbhdl is None: raise_error(self, "Unable set up %s Trigger" % (str(self))) Trigger.prime(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 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 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 prime(self, callback): if self.cbhdl is None: self.cbhdl = simulator.register_value_change_callback(self.signal. _handle, callback, self._rising, self) if self.cbhdl is None: raise_error(self, "Unable set up %s Trigger" % (str(self))) Trigger.prime(self)
def _check(obj): if self.signal.value: self.num_cycles -= 1 if self.num_cycles <= 0: self._callback(self) return if simulator.register_value_change_callback(self.cbhdl, self.signal._handle, _check, self): raise_error(self, "Unable set up %s Trigger" % (str(self)))
def prime(self, callback): Trigger.prime(self) self._callback = callback def _check(obj): if self.signal.value: self._callback(self) else: simulator.reenable_callback(self.cbhdl) if simulator.register_value_change_callback(self.cbhdl, self.signal._handle, _check, self): raise_error(self, "Unable set up %s Trigger" % (str(self)))
def _check(obj): self.unprime() if self.signal.value: self.num_cycles -= 1 if self.num_cycles <= 0: self._callback(self) return self.cbhdl = simulator.register_value_change_callback( self.signal._handle, _check, self._rising, self) if self.cbhdl == 0: raise_error(self, "Unable set up %s Trigger" % (str(self)))
def release(self): if not self.locked: raise_error( self, "Attempt to release an unacquired Lock %s" % (str(self))) self.locked = False # nobody waiting for this lock if not self._pending_primed: return trigger = self._pending_primed.pop(0) self.locked = True trigger()
def prime(self, callback): Trigger.prime(self) self._callback = callback def _check(obj): condition = self.signal.value == self._rising if condition: self._callback(self) else: #Riviera doesn't seem to like re-using a callback handle? simulator.reenable_callback(self.cbhdl) if simulator.register_value_change_callback(self.cbhdl, self.signal._handle, _check, self): raise_error(self, "Unable set up %s Trigger" % (str(self)))
def release(self): if not self.locked: raise_error(self, "Attempt to release an unacquired Lock %s" % (str(self))) self.locked = False # nobody waiting for this lock if not self._pending_primed: return trigger = self._pending_primed.pop(0) self.locked = True trigger()
def send(self, value): try: if isinstance(value, ExternalException): self.log.debug("Injecting ExternalException(%s)" % (repr(value))) return self._coro.throw(value.exception) self._started = True return self._coro.send(value) except TestComplete as e: if isinstance(e, TestFailure): self.log.warning(str(e)) raise except ExternalException as e: self.retval = e self._finished = True raise CoroutineComplete(callback=self._finished_cb) except ReturnValue as e: self.retval = e.retval self._finished = True raise CoroutineComplete(callback=self._finished_cb) except StopIteration as e: self._finished = True self.retval = getattr(e, 'value', None) # for python >=3.3 raise CoroutineComplete(callback=self._finished_cb) except Exception as e: self._finished = True raise raise_error(self, "Send raised exception: %s" % (str(e)))
def send(self, value): try: return self._coro.send(value) except TestComplete as e: if isinstance(e, TestFailure): self.log.warning(str(e)) else: self.log.info(str(e)) raise except ReturnValue as e: self.retval = e.retval raise CoroutineComplete(callback=self._finished_cb) except StopIteration: raise CoroutineComplete(callback=self._finished_cb) except Exception as e: raise_error(self, "Send raised exception: %s" % (str(e)))
def send(self, value): try: if isinstance(value, ExternalException): self.log.debug("Injecting ExternalException(%s)" % (repr(value))) return self._coro.throw(value.exception) self._started = True return self._coro.send(value) except TestComplete as e: if isinstance(e, TestFailure): self.log.warning(str(e)) raise except ExternalException as e: self.retval = e self._finished = True raise CoroutineComplete(callback=self._finished_cb) except ReturnValue as e: self.retval = e.retval self._finished = True raise CoroutineComplete(callback=self._finished_cb) except StopIteration: self._finished = True raise CoroutineComplete(callback=self._finished_cb) except Exception as e: self._finished = True raise raise_error(self, "Send raised exception: %s" % (str(e)))
def send(self, value): try: return self._coro.send(value) except TestComplete as e: if isinstance(e, TestFailure): self.log.warning(str(e)) raise except ReturnValue as e: self.retval = e.retval self._finished = True raise CoroutineComplete(callback=self._finished_cb) except StopIteration: self._finished = True raise CoroutineComplete(callback=self._finished_cb) except Exception as e: self._finished = True raise_error(self, "Send raised exception: %s" % (str(e)))
def test_raise_error_deprecated(dut): yield Timer(1) with assert_deprecated(): with assert_raises(TestError): raise_error(Timer(1), "A test exception")
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 hasattr(trigger, "pass_retval"): sendval = trigger.retval if _debug: coroutine.log.debug("Scheduling with ReturnValue(%s)" % (repr(sendval))) else: sendval = trigger if _debug: coroutine.log.debug("Scheduling with %s" % str(trigger)) try: result = coroutine.send(sendval) 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.finish_test(test_result) return # Normal co-routine 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 # Queue current routine to schedule when the nested routine exits if isinstance(result, cocotb.decorators.RunningCoroutine): if _debug: self.log.debug("Scheduling nested co-routine: %s" % result.__name__) self.queue(result) new_trigger = result.join() self._coroutine_yielded(coroutine, [new_trigger]) elif isinstance(result, Trigger): self._coroutine_yielded(coroutine, [result]) elif (isinstance(result, list) and not [t for t in result if not isinstance(t, Trigger)]): self._coroutine_yielded(coroutine, result) else: msg = ("Coroutine %s yielded something the scheduler can't handle" % str(coroutine)) msg += ("\nGot type: %s repr: %s str: %s" % (type(result), repr(result), str(result))) msg += "\nDid you forget to decorate with @cocotb.cocorutine?" try: raise_error(self, msg) except Exception as e: self.finish_test(e) # Handle any newly queued coroutines that need to be scheduled while self._pending_coros: self.add(self._pending_coros.pop(0)) while self._pending_callbacks: self._pending_callbacks.pop(0)()
def __call__(self, *args, **kwargs): try: return RunningCoroutine(self._func(*args, **kwargs), self) except Exception as e: raise raise_error(self, "Hook raised exception:")
def __call__(self, *args, **kwargs): try: return RunningTest(self._func(*args, **kwargs), self) except Exception as e: raise raise_error(self, "Test raised exception:")
def _wrapped_hook(*args, **kwargs): try: return RunningCoroutine(self._func(*args, **kwargs), self) except Exception as e: raise raise_error(self, str(e))
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 hasattr(trigger, "pass_retval"): self.log.debug("Coroutine returned a retval") sendval = trigger.retval else: coroutine.log.debug("Scheduling (%s)" % str(trigger)) sendval = trigger try: try: result = coroutine.send(sendval) # Normal co-routine completion except cocotb.decorators.CoroutineComplete as exc: self.log.debug("Coroutine completed execution with CoroutineComplete: %s" % str(coroutine)) # Call any pending callbacks that were waiting for this coroutine to exit exc() return # Entries may have been added to the remove list while the # coroutine was running, clear these down and deschedule # before resuming if self._terminate is False: self.prune_routines() if isinstance(result, Trigger): self._add_trigger(result, coroutine) elif isinstance(result, cocotb.decorators.RunningCoroutine): if self._terminate is False: self.log.debug("Scheduling nested co-routine: %s" % result.__name__) # Queue current routine to schedule when the nested routine exits self.queue(result) new_trigger = result.join() new_trigger.pass_retval = True self._add_trigger(new_trigger, coroutine) elif isinstance(result, list): for trigger in result: trigger.addpeers(result) self._add_trigger(trigger, coroutine) else: msg = "Coroutine %s yielded something that was not a trigger or a coroutine!" % str(coroutine) msg += "\nGot type: %s repr: %s str: %s" % (type(result), repr(result), str(result)) msg += "\nDid you forget to decorate with @cocotb.cocorutine?" raise_error(self, msg) # 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 # If we're already tearing down we ignore any further test results # that may be raised. Required because currently Python triggers don't unprime if not self._terminate: self.finish_test(test_result) return coroutine.log.debug("Finished sheduling coroutine (%s)" % str(trigger))
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 # Queue current routine to schedule when the nested routine exits yield_successful = False if isinstance(result, cocotb.decorators.RunningCoroutine): if not result.has_started(): self.queue(result) if _debug: self.log.debug("Scheduling nested coroutine: %s" % result.__name__) else: if _debug: self.log.debug("Joining to already running coroutine: %s" % result.__name__) new_trigger = result.join() self._coroutine_yielded(coroutine, [new_trigger]) yield_successful = True elif isinstance(result, Trigger): if _debug: self.log.debug("%s: is instance of Trigger" % result) self._coroutine_yielded(coroutine, [result]) yield_successful = True # If we get a list, make sure it's a list of triggers or coroutines. # For every coroutine, replace it with coroutine.join(). # This could probably be done more elegantly via list comprehension. elif isinstance(result, list): new_triggers = [] for listobj in result: if isinstance(listobj, Trigger): new_triggers.append(listobj) elif isinstance(listobj, cocotb.decorators.RunningCoroutine): if _debug: self.log.debug("Scheduling coroutine in list: %s" % listobj.__name__) if not listobj.has_started(): self.queue(listobj) new_trigger = listobj.join() new_triggers.append(new_trigger) else: # If we encounter something not a coroutine or trigger, # set the success flag to False and break out of the loop. yield_successful = False break # Make sure the lists are the same size. If they are not, it means # it contained something not a trigger/coroutine, so do nothing. if len(new_triggers) == len(result): self._coroutine_yielded(coroutine, new_triggers) yield_successful = True # If we didn't successfully yield anything, thrown an error. # Do it this way to make the logic in the list case simpler. if not yield_successful: msg = ( "Coroutine %s yielded something the scheduler can't handle" % str(coroutine)) msg += ("\nGot type: %s repr: %s str: %s" % (type(result), repr(result), str(result))) msg += "\nDid you forget to decorate with @cocotb.coroutine?" try: raise_error(self, msg) except Exception as e: self.finish_test(e) # 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)) while self._pending_callbacks: self._pending_callbacks.pop(0)()
def _wrapped_test(*args, **kwargs): try: return RunningTest(self._func(*args, **kwargs), self) except Exception as e: raise raise_error(self, str(e))
def prime(self, callback): self.cbhdl = simulator.create_callback(self) if simulator.register_readonly_callback(self.cbhdl, callback, self): raise_error(self, "Unable set up %s Trigger" % (str(self)))
def prime(self, callback): if self.cbhdl is None: self.cbhdl = simulator.register_readonly_callback(callback, self) if self.cbhdl is None: raise_error(self, "Unable set up %s Trigger" % (str(self))) Trigger.prime(self)
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 hasattr(trigger, "pass_retval"): sendval = trigger.retval if _debug: coroutine.log.debug("Scheduling with ReturnValue(%s)" % (repr(sendval))) else: sendval = trigger if _debug: coroutine.log.debug("Scheduling with %s" % str(trigger)) try: result = coroutine.send(sendval) 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 co-routine 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 # Queue current routine to schedule when the nested routine exits if isinstance(result, cocotb.decorators.RunningCoroutine): if _debug: self.log.debug("Scheduling nested co-routine: %s" % result.__name__) self.queue(result) new_trigger = result.join() self._coroutine_yielded(coroutine, [new_trigger]) elif isinstance(result, Trigger): self._coroutine_yielded(coroutine, [result]) elif (isinstance(result, list) and not [t for t in result if not isinstance(t, Trigger)]): self._coroutine_yielded(coroutine, result) else: msg = ("Coroutine %s yielded something the scheduler can't handle" % str(coroutine)) msg += ("\nGot type: %s repr: %s str: %s" % (type(result), repr(result), str(result))) msg += "\nDid you forget to decorate with @cocotb.coroutine?" try: raise_error(self, msg) except Exception as e: self.finish_test(e) # Handle any newly queued coroutines that need to be scheduled while self._pending_coros: self.add(self._pending_coros.pop(0)) while self._pending_callbacks: self._pending_callbacks.pop(0)()
def prime(self, callback): if self.cbhdl is None: self.cbhdl = simulator.register_nextstep_callback(callback, self) if self.cbhdl is None: raise_error(self, "Unable set up %s Trigger" % (str(self))) Trigger.prime(self)
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 # convert lists into `First` Waitables. if isinstance(result, list): result = cocotb.triggers.First(*result) # convert waitables into coroutines if isinstance(result, cocotb.triggers.Waitable): result = result._wait() # convert coroutinues into triggers if isinstance(result, cocotb.decorators.RunningCoroutine): if not result.has_started(): self.queue(result) if _debug: self.log.debug("Scheduling nested coroutine: %s" % result.__name__) else: if _debug: self.log.debug("Joining to already running coroutine: %s" % result.__name__) result = result.join() if isinstance(result, Trigger): if _debug: self.log.debug("%s: is instance of Trigger" % result) self._coroutine_yielded(coroutine, result) else: msg = ("Coroutine %s yielded something the scheduler can't handle" % str(coroutine)) msg += ("\nGot type: %s repr: %s str: %s" % (type(result), repr(result), str(result))) msg += "\nDid you forget to decorate with @cocotb.coroutine?" try: raise_error(self, msg) except Exception as e: self.finish_test(e) # 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)) while self._pending_callbacks: self._pending_callbacks.pop(0)()
def prime(self, callback): Trigger.prime(self) if simulator.register_rwsynch_callback(self.cbhdl, callback, self): raise_error(self, "Unable set up %s Trigger" % (str(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 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 hasattr(trigger, "pass_retval"): sendval = trigger.retval if _debug: if isinstance(sendval, ReturnValue): coroutine.log.debug("Scheduling with ReturnValue(%s)" % (repr(sendval))) elif isinstance(sendval, ExternalException): coroutine.log.debug("Scheduling with ExternalException(%s)" % (repr(sendval.exception))) else: sendval = trigger if _debug: coroutine.log.debug("Scheduling with %s" % str(trigger)) try: result = coroutine.send(sendval) 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 co-routine 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 # Queue current routine to schedule when the nested routine exits if isinstance(result, cocotb.decorators.RunningCoroutine): if not result.has_started(): self.queue(result) if _debug: self.log.debug("Scheduling nested co-routine: %s" % result.__name__) else: if _debug: self.log.debug("Joining to already running co-routine: %s" % result.__name__) new_trigger = result.join() self._coroutine_yielded(coroutine, [new_trigger]) elif isinstance(result, Trigger): if _debug: self.log.debug("%s: is instance of Trigger" % result) self._coroutine_yielded(coroutine, [result]) elif (isinstance(result, list) and not [t for t in result if not isinstance(t, Trigger)]): self._coroutine_yielded(coroutine, result) else: msg = ("Coroutine %s yielded something the scheduler can't handle" % str(coroutine)) msg += ("\nGot type: %s repr: %s str: %s" % (type(result), repr(result), str(result))) msg += "\nDid you forget to decorate with @cocotb.coroutine?" try: raise_error(self, msg) except Exception as e: self.finish_test(e) # 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)) while self._pending_callbacks: self._pending_callbacks.pop(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 # Queue current routine to schedule when the nested routine exits yield_successful = False if isinstance(result, cocotb.decorators.RunningCoroutine): if not result.has_started(): self.queue(result) if _debug: self.log.debug("Scheduling nested coroutine: %s" % result.__name__) else: if _debug: self.log.debug("Joining to already running coroutine: %s" % result.__name__) new_trigger = result.join() self._coroutine_yielded(coroutine, [new_trigger]) yield_successful = True elif isinstance(result, Trigger): if _debug: self.log.debug("%s: is instance of Trigger" % result) self._coroutine_yielded(coroutine, [result]) yield_successful = True # If we get a list, make sure it's a list of triggers or coroutines. # For every coroutine, replace it with coroutine.join(). # This could probably be done more elegantly via list comprehension. elif isinstance(result, list): new_triggers = [] for listobj in result: if isinstance(listobj, Trigger): new_triggers.append(listobj) elif isinstance(listobj, cocotb.decorators.RunningCoroutine): if _debug: self.log.debug("Scheduling coroutine in list: %s" % listobj.__name__) if not listobj.has_started(): self.queue(listobj) new_trigger = listobj.join() new_triggers.append(new_trigger) else: # If we encounter something not a coroutine or trigger, # set the success flag to False and break out of the loop. yield_successful = False break # Make sure the lists are the same size. If they are not, it means # it contained something not a trigger/coroutine, so do nothing. if len(new_triggers) == len(result): self._coroutine_yielded(coroutine, new_triggers) yield_successful = True # If we didn't successfully yield anything, thrown an error. # Do it this way to make the logic in the list case simpler. if not yield_successful: msg = ("Coroutine %s yielded something the scheduler can't handle" % str(coroutine)) msg += ("\nGot type: %s repr: %s str: %s" % (type(result), repr(result), str(result))) msg += "\nDid you forget to decorate with @cocotb.coroutine?" try: raise_error(self, msg) except Exception as e: self.finish_test(e) # 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)) while self._pending_callbacks: self._pending_callbacks.pop(0)()
def prime(self, callback): """Register for a timed callback""" self.cbhdl = simulator.create_callback(self) if simulator.register_timed_callback(self.cbhdl, self.time_ps, callback, self): raise_error(self, "Unable set up %s Trigger" % (str(self)))