question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

simulator exits early if first nested coroutine exits without yielding trigger

See original GitHub issue

Sample code snippet:

@cocotb.test()
def test_premature_exit(dut):
    @cocotb.coroutine
    def set_valid(signal, wait=False):
        if wait:
            yield Timer(10, "ns")
        signal <= 1
    @cocotb.coroutine
    def enable_tb(dut):
        yield set_valid(dut.stream_in_valid)
        yield Timer(10, "ns")

    yield enable_tb(dut)

leads to (run as part of test_cocotb.py at the very end)

# COUT:  2533.28ns ERROR    cocotb.scheduler                            __init__.py:177  in _sim_event                      Failing test at simulator request before test run completion: Simulator shutdown prematurely
# COUT:  2533.28ns DEBUG    cocotb.scheduler                           scheduler.py:698  in finish_scheduler                Issue sim closedown result to regresssion object
# COUT:  2533.28ns ERROR    cocotb.regression                         regression.py:290  in handle_result                   Test error has lead to simulator shuttting us down

With my understanding of the scheduler, this is due to the fact that we never entered react at some point before we return from the set_valid coroutine. During unschedule the _join trigger is only appended. The problem in this case is that that trigger won’t ever be executed.

Even as little as yielding a NullTrigger inside of set_valid would not cause this issue Here the full trace with COCOTB_SCHEDULER_DEBUG=1 COCOTB_LOG_LEVEL=DEBUG SIM=aldec

# COUT:  2533.28ns INFO     cocotb.regression                         regression.py:318  in execute                         Running test 22/27: test_premature_exit
# COUT:  2533.28ns DEBUG    ..est_premature_exit.0x7fffbb0ac750        scheduler.py:594  in schedule                        Scheduling with None
# COUT:  2533.28ns INFO     ..est_premature_exit.0x7fffbb0ac750       decorators.py:211  in send                            Starting test: "test_premature_exit"
# COUT:                                                                                                                     Description: None
# COUT:  2533.28ns DEBUG    ..est_premature_exit.0x7fffbb0ac750       decorators.py:219  in send                            Sending trigger None
# COUT:  2533.28ns DEBUG    cocotb.scheduler                           scheduler.py:600  in schedule                        Coroutine test_premature_exit yielded enable_tb (mode 1)
# COUT:  2533.28ns DEBUG    cocotb.scheduler                           scheduler.py:628  in schedule                        Scheduling nested co-routine: enable_tb
# COUT:  2533.28ns DEBUG    cocotb.scheduler                           scheduler.py:562  in add                             Adding new coroutine enable_tb
# COUT:  2533.28ns DEBUG    ..oroutine.enable_tb.0x7fffb9771950        scheduler.py:594  in schedule                        Scheduling with None
# COUT:  2533.28ns DEBUG    cocotb.gpi                                GpiCommon.cpp:256  in __gpi_get_handle_by_name        Searching for stream_in_valid
# COUT:  2533.28ns DEBUG    cocotb.gpi                                GpiCommon.cpp:269  in __gpi_get_handle_by_name        Checking if stream_in_valid native though impl VPI
# COUT:  2533.28ns DEBUG    cocotb.gpi                                 VpiCbHdl.cpp:279  in initialise                      VPI: stream_in_valid initialised with 1 elements
# COUT:  2533.28ns DEBUG    cocotb.gpi                                  VpiImpl.cpp:208  in create_gpi_obj_from_handle      VPI: Created object with type was vpiNet(36)
# COUT:  2533.28ns DEBUG    cocotb.gpi                                GpiCommon.cpp:279  in __gpi_get_handle_by_name        Found stream_in_valid via VPI
# COUT:  2533.28ns DEBUG    cocotb.gpi                                GpiCommon.cpp:50   in check_and_store                 Checking sample_module.stream_in_valid exists
# COUT:  2533.28ns DEBUG    cocotb.stream_in_valid                        handle.py:92   in __init__                        Created
# COUT:  2533.28ns DEBUG    cocotb.scheduler                           scheduler.py:600  in schedule                        Coroutine enable_tb yielded set_valid (mode 1)
# COUT:  2533.28ns DEBUG    cocotb.scheduler                           scheduler.py:628  in schedule                        Scheduling nested co-routine: set_valid
# COUT:  2533.28ns DEBUG    cocotb.scheduler                           scheduler.py:562  in add                             Adding new coroutine set_valid
# COUT:  2533.28ns DEBUG    ..oroutine.set_valid.0x7fffb9792050        scheduler.py:594  in schedule                        Scheduling with None
# COUT:  2533.28ns DEBUG    cocotb.scheduler                           scheduler.py:613  in schedule                        Coroutine completed: set_valid
# COUT:  2533.28ns DEBUG    cocotb.gpi                                 GpiCbHdl.cpp:128  in run_callback                    Generic run_callback done
# COUT:  2533.28ns DEBUG    cocotb.gpi                                 GpiCbHdl.cpp:126  in run_callback                    Generic run_callback
# COUT:  2533.28ns DEBUG    cocotb.scheduler                           scheduler.py:314  in react                           Trigger fired: _ReadWrite(readwritesync)
# COUT:  2533.28ns DEBUG    cocotb.scheduler                           scheduler.py:334  in react                           Writing cached signal updates
# COUT:  2533.28ns DEBUG    cocotb.gpi                                   gpi_priv.h:129  in get_num_elems                   stream_in_valid has 1 elements
# COUT:  2533.28ns DEBUG    cocotb.gpi                                 GpiCbHdl.cpp:128  in run_callback                    Generic run_callback done
# KERNEL: Simulation has finished. There are no more test vectors to simulate.
endsim
# COUT:  2533.28ns ERROR    cocotb.scheduler                            __init__.py:177  in _sim_event                      Failing test at simulator request before test run completion: Simulator shutdown prematurely
# COUT:  2533.28ns DEBUG    cocotb.scheduler                           scheduler.py:698  in finish_scheduler                Issue sim closedown result to regresssion object
# COUT:  2533.28ns ERROR    cocotb.regression                         regression.py:289  in handle_result                   Test error has lead to simulator shutting us down
# COUT:  2533.28ns ERROR    cocotb.regression                         regression.py:207  in tear_down                       Failed 1 out of 22 tests (3 skipped)

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:5 (5 by maintainers)

github_iconTop GitHub Comments

1reaction
ktbarrettcommented, Oct 1, 2019

This can be closed. Just tested and the code snippet works.

0reactions
eric-wiesercommented, Oct 1, 2019

Note that #637 still has issues with external (which I’ve made a start on fixing), but this specific case is indeed fixed.

Read more comments on GitHub >

github_iconTop Results From Across the Web

simulator exits early if first nested coroutine exits ... - GitHub
The problem in this case is that that trigger won't ever be executed. Even as little as yielding a NullTrigger inside of set_valid...
Read more >
Call nested coroutines without yielding? - Unity Forum
When the MonoBehaviour gets destroyed, all coroutines stop working because the MonoBehaviour class can't advance them to the "next iteration".
Read more >
Source code for cocotb.scheduler
"""Coroutine scheduler. FIXME: We have a problem here. If a coroutine schedules a read-only but we also have pending writes we have to...
Read more >
cocotb Documentation - Read the Docs
if first == second: raise TestFailure("Signal did not change"). Coroutines may also yield a list of triggers and coroutines to indicate that ...
Read more >
Classic Coroutines | Fluent Python, the lizard book
yield is used in an expression; when the coroutine is designed just to receive data from the client it yields None—this is implicit...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found