Repository: cocotb/cocotb

Issue:
VHDL/Questa: Failed to execute callback
When trying the examples (e.g. `examples/dff/tests`) in VHDL mode with Questa as simulator by calling
`make SIM=questa TOPLEVEL_LANG=vhdl`, the test is executed, but finishes with an error:
~~~~
# Loading std.standard
# Loading std.textio(body)
# Loading ieee.std_logic_1164(body)
# Loading work.dff(rtl)#1
# Loading /tmp/cocotb/build/libs/x86_64/libfli.so
#      -.--ns INFO     cocotb.gpi                                  FliImpl.cpp:1037 in cocotb_init                     cocotb_init called
# 
#      -.--ns INFO     cocotb.gpi                                GpiCommon.cpp:91   in gpi_print_registered_impl       FLI registered
#   0.00ns INFO     cocotb.gpi                                  gpi_embed.c:248  in embed_sim_init                  Running on ModelSim for Questa-64 version 10.4c_5 2015.11
#   0.00ns INFO     cocotb.gpi                                  gpi_embed.c:249  in embed_sim_init                  Python interpreter initialised and cocotb loaded!
#   0.00ns INFO     cocotb                                      __init__.py:115  in _initialise_testbench           Running tests with Cocotb v1.0 from /tmp/cocotb
#   0.00ns INFO     cocotb                                      __init__.py:131  in _initialise_testbench           Seeding Python random module with 1500540677
#   0.00ns INFO     cocotb.regression                         regression.py:167  in initialise                      Found test dff_cocotb.run_test_001
#   0.00ns INFO     cocotb.regression                         regression.py:287  in execute                         Running test 1/1: run_test_001
#   0.00ns INFO     ..coroutine._my_test.0x7fffe83c6a20       decorators.py:191  in send                            Starting test: "run_test_001"
#                                                                                                                   Description: Automatically generated test
#                                                                                                                   
#                                                                                                                   
#   0.00ns INFO     cocotb.scoreboard.dff                     scoreboard.py:177  in add_interface                   Created with reorder_depth 0
ERROR: called callback function returned NULL
Failed to execute callback
# Simulation halt requested by foreign interface.
# End time: 10:51:18 on Jul 20,2017, Elapsed time: 0:00:01
# Errors: 0, Warnings: 0

~~~~
By rolling back the GIT history I found the error comes by commit `7942b0a65f30164783e5ab666775ae2ce9310f11`, while using `40cfcf00878cc34a150f048eeb3bd6de7e4a318c` is still ok. 

The interesting thing is, that everything works well when using `make SIM=questa TOPLEVEL_LANG=verilog` instead.

The following info may also be relevant:
* OS is Arch Linux (64 Bit)
* Python version 3.6.1, also tested with 3.5.3 and 3.3.6 (in Arch-Linux, `/usr/bin/python` points to `python3.6` instead of the pretty old `python2.7`)
* the test works well when changing `Makefile.pylib.Linux` to explicitly use `python2.7`
* tested with Questa 10.4c as well as 10.6
* tested with system gcc (7.1.1) as well as gcc delivered with Questa (4.7.4)



Discussion:
I can confirm this bug using:
* Debian Stretch
* Python 3.5.3
* QuestaSim 10.4d
* GCC delivered with Questa (4.7.4)

With Python 2.7 everything works fine.
Problem appeared after commit 7942b0a65f30164783e5ab666775ae2ce9310f11 with Python 3
This should be the fix:
``` diff
diff --git a/cocotb/scheduler.py b/cocotb/scheduler.py
index 43c39e2..1014768 100644
--- a/cocotb/scheduler.py
+++ b/cocotb/scheduler.py
@@ -542,7 +542,7 @@ class Scheduler(object):
 
         Unprime all pending triggers and kill off any coroutines
         """
-        for trigger, waiting in self._trigger2coros.items():
+        for trigger, waiting in dict(self._trigger2coros).items():
             for coro in waiting:
                 if _debug:
                     self.log.debug("Killing %s" % str(coro))
```
I will check more carefully and create PR.

Resolving patch:
diff --git a/cocotb/scheduler.py b/cocotb/scheduler.py
--- a/cocotb/scheduler.py
+++ b/cocotb/scheduler.py
@@ -542,7 +542,7 @@ def cleanup(self):
 
         Unprime all pending triggers and kill off any coroutines
         """
-        for trigger, waiting in self._trigger2coros.items():
+        for trigger, waiting in dict(self._trigger2coros).items():
             for coro in waiting:
                 if _debug:
                     self.log.debug("Killing %s" % str(coro))


Test patch: