Repository: cocotb/cocotb

Issue:
Better support `LogicArray` interaction with the simulator
We can convert `BinaryValue` to `LogicArray`, but there is no way to go the other way, or to assign `LogicArray` to handles. These are necessary to effectively use `LogicArray` and `Logic` in simulations.

```python
value = LogicArray(dut.handle.value)  # this construction will not be necessary in 2.0, .value will return a LogicArray
dut.handle.value = value & LogicArray("1010")
```




Discussion:

Resolving patch:
diff --git a/cocotb/handle.py b/cocotb/handle.py
--- a/cocotb/handle.py
+++ b/cocotb/handle.py
@@ -39,6 +39,7 @@
 from cocotb import simulator
 from cocotb.binary import BinaryValue, BinaryRepresentation
 from cocotb.log import SimLog
+from cocotb.types import LogicArray
 
 # Only issue a warning for each deprecated attribute access
 _deprecation_warned = set()
@@ -791,6 +792,9 @@ def _set_value(self, value, call_sim):
                 num = (num << value["bits"]) + val
             value = BinaryValue(value=num, n_bits=len(self), bigEndian=False)
 
+        elif isinstance(value, LogicArray):
+            value = value.to_BinaryValue()
+
         elif not isinstance(value, BinaryValue):
             raise TypeError(
                 "Unsupported type for value assignment: {} ({!r})"
diff --git a/cocotb/types/logic_array.py b/cocotb/types/logic_array.py
--- a/cocotb/types/logic_array.py
+++ b/cocotb/types/logic_array.py
@@ -3,7 +3,7 @@
 # SPDX-License-Identifier: BSD-3-Clause
 import typing
 
-from cocotb.binary import BinaryValue
+from cocotb.binary import BinaryValue, BinaryRepresentation
 from cocotb.types.array import Array
 from cocotb.types.logic import Logic, LogicConstructibleT
 from cocotb.types.range import Range
@@ -246,6 +246,18 @@ def __rxor__(self: Self, other: Self) -> Self:
     def __invert__(self: Self) -> Self:
         return type(self)(~v for v in self)
 
+    def to_BinaryValue(
+        self,
+        bigEndian: bool = True,
+        binaryRepresentation: BinaryRepresentation = BinaryRepresentation.UNSIGNED,
+    ) -> BinaryValue:
+        return BinaryValue(
+            value=self.binstr,
+            n_bits=len(self),
+            bigEndian=bigEndian,
+            binaryRepresentation=binaryRepresentation
+        )
+
 
 def _int_to_bitstr(value: int, n_bits: int) -> str:
     if value < 0:


Test patch:
diff --git a/tests/pytest/test_logic_array.py b/tests/pytest/test_logic_array.py
--- a/tests/pytest/test_logic_array.py
+++ b/tests/pytest/test_logic_array.py
@@ -3,7 +3,7 @@
 # SPDX-License-Identifier: BSD-3-Clause
 import pytest
 
-from cocotb.binary import BinaryValue
+from cocotb.binary import BinaryValue, BinaryRepresentation
 from cocotb.types import Logic, LogicArray, Range, concat
 
 
@@ -108,3 +108,8 @@ def test_logic_array_invert():
 def test_binaryvalue_conversion():
     b = BinaryValue(3, n_bits=5)
     assert LogicArray(b) == LogicArray("11000")
+    la = LogicArray("1010")
+    bv = la.to_BinaryValue()
+    assert bv.binstr == "1010"
+    assert bv.binaryRepresentation == BinaryRepresentation.UNSIGNED
+    assert len(bv) == 4
diff --git a/tests/test_cases/test_cocotb/test_handle.py b/tests/test_cases/test_cocotb/test_handle.py
--- a/tests/test_cases/test_cocotb/test_handle.py
+++ b/tests/test_cases/test_cocotb/test_handle.py
@@ -8,6 +8,7 @@
 import random
 import cocotb
 from cocotb.triggers import Timer
+from cocotb.types import LogicArray
 
 from common import assert_raises
 from cocotb.handle import _Limits
@@ -361,3 +362,10 @@ async def test_access_underscore_name(dut):
     dut._id("_underscore_name", extended=False).value = 0
     await Timer(1, 'ns')
     assert dut._id("_underscore_name", extended=False).value == 0
+
+
+@cocotb.test()
+async def assign_LogicArray(dut):
+    value = LogicArray(dut.stream_in_data.value)
+    value &= LogicArray("0x1X011z")
+    dut.stream_in_data.value = value