def unschedule(self, coro): """Unschedule a coroutine. Unprime any pending triggers""" # Unprime the trigger this coroutine is waiting on try: trigger = self._coro2trigger.pop(coro) except KeyError: # coroutine probably finished pass else: if coro in self._trigger2coros.setdefault(trigger, []): self._trigger2coros[trigger].remove(coro) if not self._trigger2coros[trigger]: trigger.unprime() del self._trigger2coros[trigger] if Join(coro) in self._trigger2coros: self.react(Join(coro)) else: try: # throws an error if the background coroutine errored # and no one was monitoring it coro.retval except TestComplete as test_result: self.log.debug("TestComplete received: {}".format(test_result.__class__.__name__)) self.finish_test(test_result) except Exception as e: self.finish_test(create_error(self, "Forked coroutine {} raised exception: {}".format(coro, e)))
def unschedule(self, coro): """Unschedule a coroutine. Unprime any pending triggers""" # Unprime the trigger this coroutine is waiting on try: trigger = self._coro2trigger.pop(coro) except KeyError: # coroutine probably finished pass else: if coro in self._trigger2coros[trigger]: self._trigger2coros[trigger].remove(coro) if not self._trigger2coros[trigger]: trigger.unprime() del self._trigger2coros[trigger] if Join(coro) in self._trigger2coros: self._pending_triggers.append(Join(coro)) else: try: # throws an error if the background coroutine errored # and no one was monitoring it coro.retval except Exception as e: self._test_result = TestError( "Forked coroutine {} raised exception {}" .format(coro, e) ) self._terminate = True
async def test_join_identity(dut): """ Test that Join() returns the same object each time """ clk_gen = cocotb.fork(Clock(dut.clk, 100, "ns").start()) assert Join(clk_gen) is Join(clk_gen) await Timer(1, "ns") clk_gen.kill()
def test_coroutine_close_down(dut): clk_gen = cocotb.fork(Clock(dut.clk, 100).start()) coro_one = cocotb.fork(clock_one(dut)) coro_two = cocotb.fork(clock_two(dut)) yield Join(coro_one) yield Join(coro_two) dut._log.info("Back from joins")
def test_coroutine_close_down(dut): log = logging.getLogger("cocotb.test") clk_gen = cocotb.fork(Clock(dut.clk, 100).start()) coro_one = cocotb.fork(clock_one(dut)) coro_two = cocotb.fork(clock_two(dut)) yield Join(coro_one) yield Join(coro_two) log.info("Back from joins")
def unschedule(self, coro): """Unschedule a coroutine. Unprime any pending triggers""" for trigger in self._coro2triggers[coro]: if coro in self._trigger2coros[trigger]: self._trigger2coros[trigger].remove(coro) if not self._trigger2coros[trigger]: trigger.unprime() del self._trigger2coros[trigger] del self._coro2triggers[coro] if Join(coro) in self._trigger2coros: self._pending_triggers.append(Join(coro))
def _unschedule(self, coro): """Unschedule a coroutine. Unprime any pending triggers""" if coro in self._pending_coros: assert not coro.has_started() self._pending_coros.remove(coro) # Close coroutine so there is no RuntimeWarning that it was never awaited coro.close() return # Unprime the trigger this coroutine is waiting on trigger = coro._trigger if trigger is not None: coro._trigger = None if coro in self._trigger2coros.setdefault(trigger, []): self._trigger2coros[trigger].remove(coro) if not self._trigger2coros[trigger]: trigger.unprime() del self._trigger2coros[trigger] assert self._test is not None if coro is self._test: if _debug: self.log.debug(f"Unscheduling test {coro}") if not self._terminate: self._terminate = True self._cleanup() elif Join(coro) in self._trigger2coros: self._react(Join(coro)) else: try: # throws an error if the background coroutine errored # and no one was monitoring it coro._outcome.get() except (TestComplete, AssertionError) as e: coro.log.info("Test stopped by this forked coroutine") e = remove_traceback_frames(e, ["_unschedule", "get"]) self._abort_test(e) except Exception as e: coro.log.error("Exception raised by this forked coroutine") e = remove_traceback_frames(e, ["_unschedule", "get"]) warnings.warn( '"Unwatched" tasks that throw exceptions will not cause the test to fail. ' "See issue #2664 for more details.", FutureWarning, ) self._abort_test(e)
def test_adding_a_coroutine_without_starting(dut): """Catch (and provide useful error) for attempts to fork coroutines incorrectly""" yield Timer(100) forked = cocotb.fork(clock_gen) yield Timer(100) yield Join(forked) yield Timer(100)
def data_test(dut): tb = TbTdcGpx2Phy(dut, 100, 125) yield tb.initialize() lengths = [14, 20, 22, 38, 44] * 5 values = [randint(0, 2**l - 1) for l in lengths] monitors = [ Join(cocotb.fork(tb.data_out_monitor(ch, values, lengths))) for ch in range(4) ] drivers = [ Join(cocotb.fork(tb.frame_driver(ch, values, lengths))) for ch in range(4) ] yield Combine(*monitors, *drivers)
async def block_write(dut, addr, strb, data): t_awsend = cocotb.fork(awsend(dut, addr)) t_wsend = cocotb.fork(wsend(dut, strb, data)) Join(t_awsend) Join(t_wsend) while True: await RisingEdge(dut.clk) dut.m_BREADY <= 1 await ReadOnly() if int(dut.m_BVALID.value) and int(dut.m_BREADY.value): break await RisingEdge(dut.clk) dut.m_BREADY <= 0
async def test_afterdelay_in_readonly_valid(dut): """Test Timer delay after ReadOnly phase""" global exited exited = False clk_gen = cocotb.start_soon(Clock(dut.clk, 100, "ns").start()) coro = cocotb.start_soon(do_test_afterdelay_in_readonly(dut, 1)) await First(Join(coro), Timer(100_000, "ns")) clk_gen.kill() assert exited
async def test_cached_write_in_readonly(dut): """Test doing invalid sim operation""" global exited exited = False clk_gen = cocotb.start_soon(Clock(dut.clk, 100, "ns").start()) coro = cocotb.start_soon(do_test_cached_write_in_readonly(dut)) await First(Join(coro), Timer(10_000, "ns")) clk_gen.kill() assert exited
def test_afterdelay_in_readonly_valid(dut): """Same as test_afterdelay_in_readonly but with valid delay > 0""" global exited exited = False clk_gen = cocotb.fork(Clock(dut.clk, 100).start()) coro = cocotb.fork(do_test_afterdelay_in_readonly(dut, 1)) yield [Join(coro), Timer(100000)] clk_gen.kill() if exited is not True: raise TestFailure
def test_afterdelay_in_readonly(dut): """Test doing invalid sim operation""" global exited exited = False clk_gen = cocotb.fork(Clock(dut.clk, 100).start()) coro = cocotb.fork(do_test_afterdelay_in_readonly(dut, 0)) yield [Join(coro), Timer(1000)] clk_gen.kill() if exited is not True: raise TestFailure
def unschedule(self, coro): """Unschedule a coroutine. Unprime any pending triggers""" # Unprime the trigger this coroutine is waiting on try: trigger = self._coro2trigger.pop(coro) except KeyError: # coroutine probably finished pass else: if coro in self._trigger2coros.setdefault(trigger, []): self._trigger2coros[trigger].remove(coro) if not self._trigger2coros[trigger]: trigger.unprime() del self._trigger2coros[trigger] assert self._test is not None if coro is self._test: if _debug: self.log.debug("Unscheduling test {}".format(coro)) if not self._terminate: self._terminate = True self.cleanup() elif Join(coro) in self._trigger2coros: self.react(Join(coro)) else: try: # throws an error if the background coroutine errored # and no one was monitoring it coro._outcome.get() except (TestComplete, AssertionError) as e: coro.log.info("Test stopped by this forked coroutine") outcome = outcomes.Error(e).without_frames( ['unschedule', 'get']) self._test._force_outcome(outcome) except Exception as e: coro.log.error("Exception raised by this forked coroutine") outcome = outcomes.Error(e).without_frames( ['unschedule', 'get']) self._test._force_outcome(outcome)
def unschedule(self, coro): """Unschedule a coroutine. Unprime any pending triggers""" # Unprime the trigger this coroutine is waiting on try: trigger = self._coro2trigger.pop(coro) except KeyError: # coroutine probably finished pass else: if coro in self._trigger2coros.setdefault(trigger, []): self._trigger2coros[trigger].remove(coro) if not self._trigger2coros[trigger]: trigger.unprime() del self._trigger2coros[trigger] assert self._test is not None if coro is self._test: if _debug: self.log.debug("Unscheduling test {}".format(coro)) if not self._terminate: self._terminate = True self.cleanup() elif Join(coro) in self._trigger2coros: self.react(Join(coro)) else: try: # throws an error if the background coroutine errored # and no one was monitoring it coro.retval except TestComplete as e: self.log.debug("TestComplete received: {}".format( type(e).__name__)) self._test.abort(e) except Exception as e: self._test.abort(e)
def unschedule(self, coro): """Unschedule a coroutine. Unprime any pending triggers""" for trigger in self._coro2triggers[coro]: if coro in self._trigger2coros[trigger]: self._trigger2coros[trigger].remove(coro) if not self._trigger2coros[trigger]: trigger.unprime() del self._trigger2coros[trigger] del self._coro2triggers[coro] if Join(coro) in self._trigger2coros: self._pending_triggers.append(Join(coro)) else: try: # throws an error if the background coroutine errored # and no one was monitoring it coro.retval except Exception as e: self._test_result = TestError( "Forked coroutine {} raised exception {}".format(coro, e)) self._terminate = True
def _unschedule(self, coro): """Unschedule a coroutine. Unprime any pending triggers""" # Unprime the trigger this coroutine is waiting on trigger = coro._trigger if trigger is not None: coro._trigger = None if coro in self._trigger2coros.setdefault(trigger, []): self._trigger2coros[trigger].remove(coro) if not self._trigger2coros[trigger]: trigger.unprime() del self._trigger2coros[trigger] assert self._test is not None if coro is self._test: if _debug: self.log.debug("Unscheduling test {}".format(coro)) if not self._terminate: self._terminate = True self._cleanup() elif Join(coro) in self._trigger2coros: self._react(Join(coro)) else: try: # throws an error if the background coroutine errored # and no one was monitoring it coro._outcome.get() except (TestComplete, AssertionError) as e: coro.log.info("Test stopped by this forked coroutine") e = remove_traceback_frames(e, ['_unschedule', 'get']) self._test.abort(e) except Exception as e: coro.log.error("Exception raised by this forked coroutine") e = remove_traceback_frames(e, ['_unschedule', 'get']) self._test.abort(e)
def python_triggers(dut): """Playing with the Python Triggers""" cocotb.fork(Clock(dut.clk_i, 2).start()) yield reset(dut) # t1 = Timer(1) t2 = Timer(2) yield Combine(t1, t2) # Fires when all of the triggers have fired print_fired(dut, "Combine") yield First(t1, t2) # Fires when the first trigger fires print_fired(dut, "First") yield Join(cocotb.fork( reset(dut))) # Fires when the forked coroutine has completed print_fired(dut, "Join")
async def test_simultaneous(dut, sync, num=5): """Test simultaneous reads/writes""" axim = AXI4Master(dut, AXI_PREFIX, dut.clk) _, data_width, ram_start, _ = get_parameters(dut) await setup_dut(dut) # Avoid crossing the 4kB boundary by using just the first 4kB block base_address = randrange(ram_start, ram_start + 4096 - 2 * num * data_width, data_width) # Clear the memory cells await axim.write(base_address, [0] * num) addresses = [base_address + i * data_width for i in range(num)] write_values = [randrange(0, 2**(data_width * 8)) for i in range(num)] writers = [ axim.write(address, value, sync=sync) for address, value in zip(addresses, write_values) ] await Combine(*writers) readers = [ cocotb.fork(axim.read(address, sync=sync)) for address in addresses ] dummy_addrs = [base_address + (num + i) * data_width for i in range(num)] dummy_writers = [ cocotb.fork(axim.write(address, value, sync=sync)) for address, value in zip(dummy_addrs, write_values) ] read_values = [] for reader in readers: read_values.append((await Join(reader))[0]) await Combine(*[Join(writer) for writer in dummy_writers]) for i, (written, read) in enumerate(zip(write_values, read_values)): if written != read: raise TestFailure("#{}: wrote {:#x} but read back {:#x}".format( i, written, read.integer))
def clock_yield(generator): global test_flag yield Join(generator) test_flag = True
def transfer_frame(self, ch, bits, frame_offset=0.0, data_offset=0.0): frame = cocotb.fork(self.generate_frame_signal(ch, frame_offset)) data = cocotb.fork(self.generate_data_signal(ch, bits, data_offset)) yield Combine(Join(frame), Join(data))
def join(self): """Return a trigger that will fire when the wrapped coroutine exits.""" return Join(self)
def join(self, t): from cocotb.triggers import Join return Join(t)