Skip to content

Commit

Permalink
Use Array for ArrayObject types
Browse files Browse the repository at this point in the history
This changes the return type of ArrayObjects to be Arrays. This allows
the simulator objects indexing to be used rather than just 0 to
length-1 as was done for list.

Lists, and now any sequence, is still accepted when setting the value in
addition to Array.
  • Loading branch information
ktbarrett committed Feb 23, 2024
1 parent 7474a79 commit 1f54f33
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 36 deletions.
41 changes: 21 additions & 20 deletions src/cocotb/handle.py
Expand Up @@ -25,6 +25,7 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

import collections.abc
import enum
import logging
import re
Expand All @@ -37,7 +38,6 @@
Dict,
Generic,
Iterable,
List,
Optional,
Sequence,
Tuple,
Expand All @@ -51,8 +51,7 @@
from cocotb import simulator
from cocotb._deprecation import deprecated
from cocotb._py_compat import cached_property
from cocotb.types import Logic, LogicArray
from cocotb.types.range import Range
from cocotb.types import Array, Logic, LogicArray, Range


class _Limits(enum.IntEnum):
Expand Down Expand Up @@ -809,7 +808,9 @@ def __iter__(self) -> Iterable[ChildObjectT]:


class ArrayObject(
IndexableValueObjectBase[List[ElemValueT], List[ElemValueT], ChildObjectT],
IndexableValueObjectBase[
Array[ElemValueT], Union[Array[ElemValueT], Sequence[ElemValueT]], ChildObjectT
],
Generic[ElemValueT, ChildObjectT],
):
"""A simulation object that is an array of value-having simulation objects.
Expand All @@ -821,26 +822,26 @@ def __init__(self, handle: simulator.gpi_sim_hdl, path: Optional[str]) -> None:
super().__init__(handle, path)

@property
def value(self) -> List[ElemValueT]:
def value(self) -> Array[ElemValueT]:
"""The current value of the simulation object.
:getter:
Returns the current values of each element of the array object as a :class:`list` of element values.
Returns the current values of each element of the array object as a :class:`~cocotb.types.Array` of element values.
The elements of the array appear in the list in left-to-right order.
:setter:
Assigns a :class:`list` of values to each element of the array at the end of the current delta cycle.
Assigns a :class:`~cocotb.types.Array`, :class:`list`, or :class:`tuple` of values to each element of the array at the end of the current delta cycle.
The element values are assigned in left-to-right order.
Given an HDL array ``arr``, when getting the value:
+--------------+---------------------+--------------------------------------------------------------+
| Verilog | VHDL | ``arr.value`` is equivalent to |
+==============+=====================+==============================================================+
| ``arr[4:7]`` | ``arr(4 to 7)`` | ``[arr[4].value, arr[5].value, arr[6].value, arr[7].value]`` |
+--------------+---------------------+--------------------------------------------------------------+
| ``arr[7:4]`` | ``arr(7 downto 4)`` | ``[arr[7].value, arr[6].value, arr[5].value, arr[4].value]`` |
+--------------+---------------------+--------------------------------------------------------------+
+--------------+---------------------+--------------------------------------------------------------------------------------------------+
| Verilog | VHDL | ``arr.value`` is equivalent to |
+==============+=====================+==================================================================================================+
| ``arr[4:7]`` | ``arr(4 to 7)`` | ``Array([arr[4].value, arr[5].value, arr[6].value, arr[7].value], range=Range(4, 'to', 7))`` |
+--------------+---------------------+--------------------------------------------------------------------------------------------------+
| ``arr[7:4]`` | ``arr(7 downto 4)`` | ``Array([arr[7].value, arr[6].value, arr[5].value, arr[4].value], range=Range(7, 'downto', 4))`` |
+--------------+---------------------+--------------------------------------------------------------------------------------------------+
When setting the signal as in ``arr.value = ...``, the same index equivalence as noted in the table holds.
Expand All @@ -857,21 +858,21 @@ def value(self) -> List[ElemValueT]:
ValueError:
If assigning a :class:`list` of different length than the simulation object.
"""
return [self[i].value for i in self.range]
return Array((self[i].value for i in self.range), range=self.range)

@value.setter
def value(self, value: List[ElemValueT]) -> None:
def value(self, value: Array[ElemValueT]) -> None:
self.set(value)

def _set_value(
self,
value: List[ElemValueT],
value: Union[Array[ElemValueT], Sequence[ElemValueT]],
action: _GPISetAction,
schedule_write: Callable[
[ValueObjectBase[Any, Any], Callable[..., None], Sequence[Any]], None
],
) -> None:
if not isinstance(value, list):
if not isinstance(value, (collections.abc.Sequence, Array)):
raise TypeError(
f"Assigning non-list value to object {self._name} of type {type(self)}"
)
Expand All @@ -880,8 +881,8 @@ def _set_value(
"Assigning list of length %d to object %s of length %d"
% (len(value), self._name, len(self))
)
for val_idx, self_idx in enumerate(self.range):
self[self_idx]._set_value(value[val_idx], action, schedule_write)
for elem, self_idx in zip(value, self.range):
self[self_idx]._set_value(elem, action, schedule_write)


class LogicObject(
Expand Down
20 changes: 4 additions & 16 deletions tests/test_cases/test_array_simple/test_array_simple.py
Expand Up @@ -2,10 +2,10 @@
# Licensed under the Revised BSD License, see LICENSE for details.
# SPDX-License-Identifier: BSD-3-Clause
"""Test getting and setting values of arrays"""
import contextlib
import logging

import cocotb
import pytest
from cocotb._sim_versions import RivieraVersion
from cocotb.clock import Clock
from cocotb.triggers import Timer
Expand Down Expand Up @@ -169,24 +169,12 @@ async def test_struct(dut):
_check_value(tlog, dut.inout_if.a_in, 0)


@contextlib.contextmanager
def assert_raises(exc_type):
try:
yield
except exc_type as exc:
tlog.info(f" {exc_type.__name__} raised as expected: {exc}")
else:
raise AssertionError(f"{exc_type.__name__} was not raised")


@cocotb.test()
async def test_exceptions(dut):
"""Test that correct Exceptions are raised."""
with assert_raises(TypeError):
dut.array_7_downto_4.value = (0xF0, 0xE0, 0xD0, 0xC0)
with assert_raises(TypeError):
with pytest.raises(TypeError):
dut.array_4_to_7.value = Exception("Exception Object")
with assert_raises(ValueError):
with pytest.raises(ValueError):
dut.array_3_downto_0.value = [0x70, 0x60, 0x50]
with assert_raises(ValueError):
with pytest.raises(ValueError):
dut.array_0_to_3.value = [0x40, 0x30, 0x20, 0x10, 0x00]

0 comments on commit 1f54f33

Please sign in to comment.