Source code for hwtLib.mem.sim.segmentedArrayProxy
from typing import List
from hwt.code import Concat
from hwtLib.tools.debug_bus_monitor_ctl import select_bit_range
from hwtSimApi.basic_hdl_simulator.proxy import BasicRtlSimProxy
from pyMathBitPrecise.bit_utils import int_to_int_list
[docs]class SegmentedArrayProxy():
"""
A simulation proxy whic can read a and write to memories which are physicaly stored in multiple arrays.
e.g.
.. code-block:: c
// example definition of two segments
int array0[10];
int array1[10];
// a get of actual item
Concat(array1[i] array0[i])
// a set of actual item
array1[i] = select_bit_range(v, 32, 64)
array0[i] = select_bit_range(v, 0, 32)
This object allows to use such a list of memories as a list
thus removing of manual bit selections and concatenations
when accessing the items stored in memory.
"""
[docs] def __init__(self, mems: List[BasicRtlSimProxy], items_per_index=None, words_per_item=None):
assert mems, mems
self.mems = mems
assert items_per_index is None or words_per_item is None, (items_per_index, words_per_item)
self.items_per_index = items_per_index
self.words_per_item = words_per_item
self.ITEM_WIDTH = mems[0]._dtype.element_t.bit_length() * len(mems)
[docs] def clean(self):
for mem in self.mems:
# may not neccessary have to be two different instances
# as the value is copied into simulator, (copy just to make sure)
t = mem._dtype
mem.val = t.from_py([0 for _ in range(t.size)])
mem.def_val = t.from_py([0 for _ in range(t.size)])
[docs] def __getitem__(self, i: int):
if self.items_per_index and self.items_per_index != 1:
raise NotImplementedError()
elif self.words_per_item and self.words_per_item != 1:
return Concat(*(
self._getitem(i * self.words_per_item + i2)
for i2 in range(self.words_per_item - 1, -1, -1)
))
else:
return self._getitem(i)
[docs] def _getitem(self, i: int):
res = [data_mem.val[i] for data_mem in reversed(self.mems)]
return Concat(*res)
[docs] def _setitem(self, i, val):
for B_i, data_mem in enumerate(self.mems):
t = data_mem._dtype
_data = select_bit_range(val, B_i * 8, 8)
if data_mem.def_val is None:
# a default state before sim execution if there is no default value
data_mem.def_val = t.from_py([0 for _ in range(t.size)])
data_mem.val[i] = data_mem.def_val[i] = t.element_t.from_py(_data)
return val
[docs] def __setitem__(self, i: int, val: int):
if self.items_per_index and self.items_per_index != 1:
raise NotImplementedError()
elif self.words_per_item and self.words_per_item != 1:
_i = i * self.words_per_item
_data = int_to_int_list(val, self.ITEM_WIDTH, self.words_per_item)
for i2, _d in enumerate(_data):
self._setitem(_i + i2, _d)
return val
else:
return self._setitem(i, val)
[docs] def __len__(self):
return len(self.mems[0]) // self.words_per_item
[docs] def __iter__(self):
for i in range(len(self)):
yield self[i]