Repository: cocotb/cocotb

Issue:
Munging of setting binary and ASCII strings in GPI/VPI
As discovered in #834 the `access_var_string` test fails in Questa when using the VPI. A solution is to change the format in the following snippet from `vpiBinStrVal` to `vpiStringVal`.

https://github.com/cocotb/cocotb/blob/92a032a4349b2fe9e2f9bff5d1060ef44cd4cd72/cocotb/share/lib/vpi/VpiCbHdl.cpp#L346-L357

Conceptually this is changing the format from a binary string to an ASCII string. This makes the test pass on Questa because we are writing actual strings on the failing test. However, this fix causes other tests to fail on Icarus.

Fundamentally, setting ASCII strings and binary string are different operation on different types, which is why there are distinct VPI format types. But the GPI only has one function overload for setting signal values to strings. For the VPI it makes the assumption that `vpiBinStrVal` is correct, and this works for Icarus by "happenstance". Really the whole thing is just wrong, there should be two functions: one for handling binary strings, and the other for ASCII strings. This requires modifying the GPI and all the interfaces.


Discussion:

Resolving patch:
diff --git a/cocotb/handle.py b/cocotb/handle.py
--- a/cocotb/handle.py
+++ b/cocotb/handle.py
@@ -625,7 +625,7 @@ def setimmediatevalue(self, value):
             self._log.critical("Unsupported type for value assignment: %s (%s)", type(value), repr(value))
             raise TypeError("Unable to set simulator value with type %s" % (type(value)))
 
-        simulator.set_signal_val_str(self._handle, value.binstr)
+        simulator.set_signal_val_binstr(self._handle, value.binstr)
 
     @NonConstantObject.value.getter
     def value(self):


Test patch:
diff --git a/tests/test_cases/issue_957/issue_957.py b/tests/test_cases/issue_957/issue_957.py
--- a/tests/test_cases/issue_957/issue_957.py
+++ b/tests/test_cases/issue_957/issue_957.py
@@ -5,7 +5,7 @@
 def wait_edge(dut):
     # this trigger never fires
     yield First(
-        RisingEdge(dut.and_output)
+        RisingEdge(dut.stream_out_ready)
     )
 
 @cocotb.test()
diff --git a/tests/test_cases/test_closedown/test_closedown.py b/tests/test_cases/test_closedown/test_closedown.py
--- a/tests/test_cases/test_closedown/test_closedown.py
+++ b/tests/test_cases/test_closedown/test_closedown.py
@@ -34,7 +34,7 @@
 """
 
 import cocotb
-from cocotb.triggers import Timer, Join, RisingEdge
+from cocotb.triggers import Timer, RisingEdge
 from cocotb.clock import Clock
 
 
@@ -56,11 +56,13 @@ def clock_mon(dut):
     yield RisingEdge(dut.clk)
 
 
-@cocotb.test(expect_fail=True)
+@cocotb.test(expect_fail=True,
+             expect_error=cocotb.SIM_NAME.lower().startswith(("modelsim",  # $fail_test() fails hard on Questa
+                                                              )))
 def test_failure_from_system_task(dut):
     """Allow the dut to call $fail_test() from verilog"""
     clock = Clock(dut.clk, 100)
     clock.start()
-    coro = cocotb.fork(clock_mon(dut))
-    extern = cocotb.fork(run_external(dut))
+    cocotb.fork(clock_mon(dut))
+    cocotb.fork(run_external(dut))
     yield Timer(10000000)
diff --git a/tests/test_cases/test_discovery/test_discovery.py b/tests/test_cases/test_discovery/test_discovery.py
--- a/tests/test_cases/test_discovery/test_discovery.py
+++ b/tests/test_cases/test_discovery/test_discovery.py
@@ -273,8 +273,8 @@ def access_string_vhdl(dut):
 
 # TODO: add tests for Verilog "string_input_port" and "STRING_LOCALPARAM" (see issue #802)
 
-@cocotb.test(skip=cocotb.LANGUAGE in ["vhdl"],
-             expect_error=cocotb.SIM_NAME.lower().startswith("icarus"))
+@cocotb.test(skip=cocotb.LANGUAGE in ["vhdl"] or cocotb.SIM_NAME.lower().startswith("icarus"),
+             expect_fail=cocotb.SIM_NAME.lower().startswith("modelsim"))
 def access_const_string_verilog(dut):
     """Access to a const Verilog string."""
     tlog = logging.getLogger("cocotb.test")
@@ -370,7 +370,7 @@ def access_boolean(dut):
     if (int(curr_val) == int(output_bool)):
         raise TestFailure("Value did not propogate")
 
-@cocotb.test()
+@cocotb.test(skip=cocotb.LANGUAGE in ["vhdl"])
 def access_internal_register_array(dut):
     """Test access to an internal register array"""