Repository: cocotb/cocotb

Issue:
[Riviera-Pro] Simulator crash in test_vhdl_access.port_not_hierarchy
Riviera-PRO 2019.10 on linux64 crashes in the test_vhdl_access.port_not_hierarchy test. Could be related to #1854.

```
$ make -C ~/src/cocotb/tests/test_cases/test_vhdl_access SIM=riviera COCOTB_REDUCED_LOG_FMT=1 clean results.xml

# COUT:      0.00ns INFO     Running test 1/3: check_enum_object
# COUT:      0.00ns INFO     Starting test: "check_enum_object"
# COUT:                      Description: 
# COUT:                          Enumerations currently behave as normal signals
# COUT:                      
# COUT:                          TODO: Implement an EnumObject class and detect valid string mappings
# COUT:                          
# COUT:      0.10ns INFO     Test Passed: check_enum_object
# COUT:      0.10ns INFO     Running test 2/3: check_objects
# COUT:      0.10ns INFO     Starting test: "check_objects"
# COUT:                      Description: 
# COUT:                          Check the types of objects that are returned
# COUT:                          
# COUT:      0.20ns INFO     inst_axi4s_buffer(GPI_MODULE) is HierarchyObject
# COUT:      0.20ns INFO     gen_branch_distance__0(GPI_MODULE) is HierarchyObject
# COUT:      0.20ns INFO     inst_branch_distance(GPI_MODULE) is HierarchyObject
# COUT:      0.20ns INFO     inbranch_tdata_low(GPI_REGISTER) is ModifiableObject
# COUT:      0.20ns INFO     inbranch_tdata_low(0)(GPI_REGISTER) is ModifiableObject
# COUT:      0.20ns INFO     aclk(GPI_REGISTER) is ModifiableObject
# COUT:      0.20ns INFO     s_axis_input_tdata(GPI_REGISTER) is ModifiableObject
# COUT:      0.20ns INFO     current_active(GPI_INTEGER) is IntegerObject
# COUT:      0.20ns INFO     DATA_WIDTH(GPI_INTEGER) is ConstantObject
# COUT:      0.20ns INFO     inst_ram_ctrl(GPI_MODULE) is HierarchyObject
# COUT:      0.20ns INFO     Test Passed: check_objects
# COUT:      0.20ns INFO     Running test 3/3: port_not_hierarchy
# COUT:      0.20ns INFO     Starting test: "port_not_hierarchy"
# COUT:                      Description: 
# COUT:                          Test for issue raised by Luke - iteration causes a toplevel port type to
# COUT:                          change from ModifiableObject to HierarchyObject
# COUT:                          
# COUT:      0.30ns INFO     dut.aclk is ModifiableObject
# COUT: Stack pointer: 0x7fa9318c5630
# COUT: Local variable address: 0x7fa9318c5a4f
# KERNEL: Fatal Error: System exception occurred: SIGSEGV. Cannot continue.
# KERNEL: stopped at time: 302 ps
# KERNEL: Simulation has stopped after unknown error.
# VSIM: Error: Fatal error occurred during simulation.
```


Discussion:

Resolving patch:
diff --git a/cocotb/__init__.py b/cocotb/__init__.py
--- a/cocotb/__init__.py
+++ b/cocotb/__init__.py
@@ -183,8 +183,8 @@ def _initialise_testbench(argv_):
     from cocotb import simulator
 
     global SIM_NAME, SIM_VERSION
-    SIM_NAME = simulator.get_simulator_product()
-    SIM_VERSION = simulator.get_simulator_version()
+    SIM_NAME = simulator.get_simulator_product().strip()
+    SIM_VERSION = simulator.get_simulator_version().strip()
 
     cocotb.log.info("Running on {} version {}".format(SIM_NAME, SIM_VERSION))
 


Test patch:
diff --git a/tests/test_cases/test_iteration_vhdl/test_iteration.py b/tests/test_cases/test_iteration_vhdl/test_iteration.py
--- a/tests/test_cases/test_iteration_vhdl/test_iteration.py
+++ b/tests/test_cases/test_iteration_vhdl/test_iteration.py
@@ -26,27 +26,52 @@
 import logging
 
 import cocotb
-from cocotb.triggers import Timer
+from cocotb.triggers import Timer, Combine
 from cocotb.result import TestFailure
 
 
-# This test crashes Riviera-PRO 2019.10 (at least); skip to avoid hanging the
-# tests. See issue #1854 for details.
-@cocotb.test(skip=cocotb.SIM_NAME.lower().startswith("riviera") and cocotb.SIM_VERSION.startswith("2019.10"))
-def recursive_discovery(dut):
-    """
-    Recursively discover every single object in the design
-    """
+def total_object_count():
+    """Return the total object count based on simulator."""
+    SIM_NAME = cocotb.SIM_NAME.lower()
+    SIM_VERSION = cocotb.SIM_VERSION.lower()
 
-    if (cocotb.SIM_NAME.lower().startswith(("ncsim", "xmsim", "modelsim")) or
-       (cocotb.SIM_NAME.lower().startswith("riviera") and not cocotb.SIM_VERSION.startswith("2016.02"))):
-        # Finds regions, signal, generics, constants, varibles and ports.
-        pass_total = 34569
-    else:
-        pass_total = 32393
+    if SIM_NAME.startswith(
+        (
+            "ncsim",
+            "xmsim",
+            "modelsim",
+        )
+    ):
+        return 34569
+
+    # Riviera-PRO
+    if SIM_NAME.startswith("riviera"):
+        if SIM_VERSION.startswith("2019.10"):
+            return 27359
+        if SIM_VERSION.startswith("2016.02"):
+            return 32393
+        return 34569
+
+    # Active-HDL
+    if SIM_NAME.startswith("aldec"):
+        if SIM_VERSION.startswith("11.1"):
+            # Active-HDL 11.1 only finds 'inbranch_tdata_low' inside the gen_acs for generate block
+            return 27359
+        if SIM_VERSION.startswith("10.01"):
+            # Active-HDL 10.1 doesn't find any signals declared inside the gen_acs for generate block
+            return 26911
+
+    return 0
+
+
+@cocotb.test(skip=(total_object_count() == 0))
+async def recursive_discovery(dut):
+    """Recursively discover every single object in the design."""
+
+    pass_total = total_object_count()
 
     tlog = logging.getLogger("cocotb.test")
-    yield Timer(100)
+    await Timer(100)
 
     def dump_all_the_things(parent):
         count = 0
@@ -62,51 +87,37 @@ def dump_all_the_things(parent):
 
 
 @cocotb.test()
-def discovery_all(dut):
-    dut._log.info("Trying to discover")
-    yield Timer(0)
+async def discovery_all(dut):
+    """Discover everything on top-level."""
+    dut._log.info("Iterating over top-level to discover objects")
     for thing in dut:
         thing._log.info("Found something: %s", thing._fullname)
-        # for subthing in thing:
-        #     thing._log.info("Found something: %s" % thing._fullname)
 
     dut._log.info("length of dut.inst_acs is %d", len(dut.gen_acs))
     item = dut.gen_acs[3]
     item._log.info("this is item")
 
 
-@cocotb.coroutine
-def iteration_loop(dut):
-    for thing in dut:
-        thing._log.info("Found something: %s", thing._fullname)
-        yield Timer(1)
-
-
 @cocotb.test()
-def dual_iteration(dut):
-    loop_one = cocotb.fork(iteration_loop(dut))
-    loop_two = cocotb.fork(iteration_loop(dut))
+async def dual_iteration(dut):
+    """Test iteration over top-level in two forked coroutines."""
+    async def iteration_loop():
+        for thing in dut:
+            thing._log.info("Found something: %s", thing._fullname)
+            await Timer(1)
 
-    yield [loop_one.join(), loop_two.join()]
+    loop_one = cocotb.fork(iteration_loop())
+    loop_two = cocotb.fork(iteration_loop())
 
+    await Combine(loop_one, loop_two)
 
-@cocotb.test()
-def get_clock(dut):
-    dut._log.info("dut.aclk is %s", type(dut.aclk).__name__)
-    dut.aclk <= 0
-    yield Timer(1)
-    dut.aclk <= 1
-    yield Timer(1)
-    if int(dut.aclk) != 1:
-        raise TestFailure("dut.aclk is not what we expected (got %d)" % int(dut.aclk))
-
-
-@cocotb.test(expect_fail=cocotb.SIM_NAME.lower().startswith("riviera") and cocotb.SIM_VERSION.startswith("2019.10"))
-def test_n_dimension_array(dut):
+
+@cocotb.test(expect_fail=(cocotb.SIM_NAME.lower().startswith("riviera") and cocotb.SIM_VERSION.startswith("2019.10")) or cocotb.SIM_NAME.lower().startswith("aldec"))
+async def test_n_dimension_array(dut):
+    """Test iteration over multi-dimensional array."""
     tlog = logging.getLogger("cocotb.test")
     inner_count = 0
     outer_count = 0
-    yield Timer(0)
     config = dut.inst_ram_ctrl.config
     # This signal is a 2 x 7 vhpiEnumVecVal
     for thing in config:
diff --git a/tests/test_cases/test_vhdl_access/test_vhdl_access.py b/tests/test_cases/test_vhdl_access/test_vhdl_access.py
--- a/tests/test_cases/test_vhdl_access/test_vhdl_access.py
+++ b/tests/test_cases/test_vhdl_access/test_vhdl_access.py
@@ -95,9 +95,7 @@ def check_instance(obj, objtype):
         raise TestFailure("%d Failures during the test" % fails)
 
 
-# This test crashes Riviera-PRO 2019.10 (at least); skip to avoid hanging the
-# tests. See issue #1857 for details.
-@cocotb.test(skip=cocotb.SIM_NAME.lower().startswith("riviera") and cocotb.SIM_VERSION.startswith("2019.10"))
+@cocotb.test()
 def port_not_hierarchy(dut):
     """
     Test for issue raised by Luke - iteration causes a toplevel port type to