peakrdl-python 0.7.4__tar.gz → 0.7.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/PKG-INFO +1 -1
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/docs/api_components.rst +3 -2
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python/__about__.py +1 -1
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python/lib/async_register.py +77 -26
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python/lib/register.py +74 -65
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python.egg-info/PKG-INFO +1 -1
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/unit_tests/test_reg.py +202 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/.github/workflows/action.yaml +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/.gitignore +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/.readthedocs.yaml +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/LICENSE +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/MANIFEST.in +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/README.md +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/docs/api.rst +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/docs/command_line.rst +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/docs/conf.py +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/docs/customisation.rst +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/docs/design_decisions.rst +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/docs/design_tools.rst +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/docs/generated_package.rst +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/docs/genindex.rst +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/docs/index.rst +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/docs/installation.rst +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/docs/requirements.txt +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/example/array_access/array_access.rdl +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/example/array_access/demo_array_access.py +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/example/enumerated_fields/demo_enumerated_fields.py +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/example/enumerated_fields/enumerated_fields.rdl +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/example/optimised_access/demo_optimised_access.py +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/example/optimised_access/demo_optimised_array_access.py +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/example/optimised_access/optimised_access.rdl +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/example/optimised_access/optimised_array_access.rdl +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/example/overridden_names/over_ridden_names.py +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/example/overridden_names/overridden_names.rdl +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/example/simulating_callbacks/chip_with_a_GPIO.rdl +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/example/simulating_callbacks/flashing_the_LED.py +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/example/tranversing_address_map/chip_with_registers.rdl +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/example/tranversing_address_map/dumping_register_state_to_json_file.py +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/example/tranversing_address_map/reg_dump.json +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/example/tranversing_address_map/reseting_registers.py +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/example/tranversing_address_map/writing_register_state_from_json_file.py +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/example/why_ral/__init__.py +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/example/why_ral/gpio.rdl +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/example/why_ral/hardware_sim.py +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/example/why_ral/with_hal.py +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/example/why_ral/with_ral.py +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/example/why_ral/without_ral.py +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/generate_and_test.py +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/generate_testcases.py +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/pyproject.toml +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/setup.cfg +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python/.coveragerc +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python/__init__.py +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python/__peakrdl__.py +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python/_node_walkers.py +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python/exporter.py +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python/lib/__init__.py +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python/lib/base.py +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python/lib/callbacks.py +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python/lib/fields.py +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python/lib/memory.py +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python/lib/utility_functions.py +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python/safe_name_utility.py +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python/systemrdl_node_utility_functions.py +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python/templates/__init__.py +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python/templates/addrmap.py.jinja +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python/templates/addrmap_field.py.jinja +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python/templates/addrmap_memory.py.jinja +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python/templates/addrmap_register.py.jinja +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python/templates/addrmap_simulation.py.jinja +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python/templates/addrmap_simulation_tb.jinja +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python/templates/addrmap_tb.py.jinja +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python/templates/baseclass_tb.py.jinja +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python/templates/header.py.jinja +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python/templates/header_tb.py.jinja +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python/templates/reg_definitions.py.jinja +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python.egg-info/SOURCES.txt +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python.egg-info/dependency_links.txt +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python.egg-info/entry_points.txt +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python.egg-info/requires.txt +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python.egg-info/top_level.txt +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/.mypy.ini +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/alternative_template_toml/peakrdl.toml +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/alternative_templates/header.py.jinja +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/alternative_templates/header_tb.py.jinja +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/pylint.rc +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/testcases/RDLFormatCode_example.rdl +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/testcases/addr_map.rdl +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/testcases/all_register_access_types.rdl +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/testcases/basic.rdl +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/testcases/block_a.xml +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/testcases/block_b.xml +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/testcases/different_array_types.rdl +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/testcases/enum_example.rdl +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/testcases/example_issue_106.rdl +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/testcases/field_scope.rdl +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/testcases/field_with_overridden_reset.rdl +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/testcases/fields_with_HW_write.rdl +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/testcases/fields_with_reset_values.rdl +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/testcases/memories.rdl +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/testcases/memories_with_registers.rdl +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/testcases/msb0_and_lsb0.rdl +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/testcases/multi_block.rdl +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/testcases/multifile.rdl +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/testcases/name_clash.rdl +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/testcases/overridden_python_name.rdl +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/testcases/parametrised_readonly_and_readwrite.rdl +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/testcases/regfile_and_arrays.rdl +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/testcases/same_but_different_enum.rdl +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/testcases/signals_definitions_at_various_levels.rdl +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/testcases/simple.rdl +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/testcases/simple.xml +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/testcases/sizes_registers.rdl +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/testcases/sizes_registers_array.rdl +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/testcases/write_only_enum_with_undefined_reset.rdl +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/unit_tests/__init__.py +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/unit_tests/simple_components.py +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/unit_tests/test_array_indexing.py +0 -0
- {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/unit_tests/test_optimised_reg_array.py +0 -0
|
@@ -65,7 +65,7 @@ Memories
|
|
|
65
65
|
:inherited-members:
|
|
66
66
|
|
|
67
67
|
Registers
|
|
68
|
-
|
|
68
|
+
=========
|
|
69
69
|
|
|
70
70
|
.. autoclass:: peakrdl_python.lib.register.RegReadOnly
|
|
71
71
|
:members:
|
|
@@ -93,6 +93,7 @@ Registers
|
|
|
93
93
|
|
|
94
94
|
Register Fields
|
|
95
95
|
^^^^^^^^^^^^^^^
|
|
96
|
+
A register will always have fields within it
|
|
96
97
|
|
|
97
98
|
.. autoclass:: peakrdl_python.lib.fields.FieldReadOnly
|
|
98
99
|
:members:
|
|
@@ -116,4 +117,4 @@ Register Fields
|
|
|
116
117
|
|
|
117
118
|
.. autoclass:: peakrdl_python.lib.fields.FieldEnumReadWrite
|
|
118
119
|
:members:
|
|
119
|
-
:inherited-members:
|
|
120
|
+
:inherited-members:
|
|
@@ -26,6 +26,7 @@ from abc import ABC, abstractmethod
|
|
|
26
26
|
from contextlib import asynccontextmanager
|
|
27
27
|
from array import array as Array
|
|
28
28
|
import sys
|
|
29
|
+
from warnings import warn
|
|
29
30
|
|
|
30
31
|
from .utility_functions import get_array_typecode
|
|
31
32
|
from .base import AsyncAddressMap, AsyncRegFile
|
|
@@ -127,14 +128,16 @@ class RegAsyncReadOnly(AsyncReg, ABC):
|
|
|
127
128
|
"""
|
|
128
129
|
Context manager to allow multiple field accesses to be performed with a single
|
|
129
130
|
read of the register
|
|
130
|
-
|
|
131
|
-
Returns:
|
|
132
|
-
|
|
133
131
|
"""
|
|
134
132
|
self.__register_state = await self.read()
|
|
133
|
+
# pylint: disable=duplicate-code
|
|
135
134
|
self.__in_context_manager = True
|
|
136
|
-
|
|
137
|
-
|
|
135
|
+
# this try/finally is needed to make sure that in the event of an exception
|
|
136
|
+
# the state flags are not left incorrectly set
|
|
137
|
+
try:
|
|
138
|
+
yield self
|
|
139
|
+
finally:
|
|
140
|
+
self.__in_context_manager = False
|
|
138
141
|
|
|
139
142
|
async def read(self) -> int:
|
|
140
143
|
"""Asynchronously read value from the register
|
|
@@ -292,7 +295,8 @@ class RegAsyncReadWrite(RegAsyncReadOnly, RegAsyncWriteOnly, ABC):
|
|
|
292
295
|
class for an async read and write only register
|
|
293
296
|
|
|
294
297
|
"""
|
|
295
|
-
__slots__: List[str] = ['
|
|
298
|
+
__slots__: List[str] = ['__in_read_write_context_manager', '__in_read_context_manager',
|
|
299
|
+
'__register_state']
|
|
296
300
|
|
|
297
301
|
# pylint: disable=too-many-arguments, duplicate-code
|
|
298
302
|
def __init__(self, *,
|
|
@@ -308,7 +312,8 @@ class RegAsyncReadWrite(RegAsyncReadOnly, RegAsyncWriteOnly, ABC):
|
|
|
308
312
|
inst_name=inst_name,
|
|
309
313
|
parent=parent, width=width, accesswidth=accesswidth)
|
|
310
314
|
|
|
311
|
-
self.
|
|
315
|
+
self.__in_read_write_context_manager: bool = False
|
|
316
|
+
self.__in_read_context_manager: bool = False
|
|
312
317
|
self.__register_state: Optional[int] = None
|
|
313
318
|
|
|
314
319
|
# pylint: enable=too-many-arguments, duplicate-code
|
|
@@ -324,19 +329,53 @@ class RegAsyncReadWrite(RegAsyncReadOnly, RegAsyncWriteOnly, ABC):
|
|
|
324
329
|
verify (bool): very the write with a read afterwards
|
|
325
330
|
skip_write (bool): skip the write back at the end
|
|
326
331
|
|
|
327
|
-
Returns:
|
|
328
|
-
|
|
329
332
|
"""
|
|
333
|
+
# pylint: disable=duplicate-code
|
|
334
|
+
if self.__in_read_context_manager:
|
|
335
|
+
raise RuntimeError('using the `single_read_modify_write` context manager within the '
|
|
336
|
+
'single_read` is not permitted')
|
|
337
|
+
|
|
338
|
+
if skip_write is True:
|
|
339
|
+
warn('The `skip_write` argument will be removed in the future, use `single_read`'
|
|
340
|
+
' instead',
|
|
341
|
+
DeprecationWarning, stacklevel=2)
|
|
342
|
+
# pylint: enable=duplicate-code
|
|
343
|
+
|
|
330
344
|
self.__register_state = await self.read()
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
self.
|
|
345
|
+
|
|
346
|
+
# pylint: disable=duplicate-code
|
|
347
|
+
self.__in_read_write_context_manager = True
|
|
348
|
+
# this try/finally is needed to make sure that in the event of an exception
|
|
349
|
+
# the state flags are not left incorrectly set
|
|
350
|
+
try:
|
|
351
|
+
yield self
|
|
352
|
+
finally:
|
|
353
|
+
self.__in_read_write_context_manager = False
|
|
354
|
+
# pylint: enable=duplicate-code
|
|
334
355
|
if not skip_write:
|
|
335
356
|
await self.write(self.__register_state, verify)
|
|
336
357
|
|
|
337
358
|
# clear the register states at the end of the context manager
|
|
338
359
|
self.__register_state = None
|
|
339
360
|
|
|
361
|
+
@asynccontextmanager
|
|
362
|
+
async def single_read(self) -> \
|
|
363
|
+
AsyncGenerator[Self, None]:
|
|
364
|
+
"""
|
|
365
|
+
Context manager to allow multiple field reads with a single register read
|
|
366
|
+
"""
|
|
367
|
+
# pylint: disable=duplicate-code
|
|
368
|
+
if self.__in_read_write_context_manager:
|
|
369
|
+
raise RuntimeError('using the `single_read` context manager within the '
|
|
370
|
+
'single_read_modify_write` is not permitted')
|
|
371
|
+
self.__in_read_context_manager = True
|
|
372
|
+
# pylint: enable=duplicate-code
|
|
373
|
+
try:
|
|
374
|
+
async with super().single_read() as reg:
|
|
375
|
+
yield reg
|
|
376
|
+
finally:
|
|
377
|
+
self.__in_read_context_manager = False
|
|
378
|
+
|
|
340
379
|
async def write(self, data: int, verify: bool = False) -> None:
|
|
341
380
|
"""
|
|
342
381
|
Writes a value to the register
|
|
@@ -352,7 +391,10 @@ class RegAsyncReadWrite(RegAsyncReadOnly, RegAsyncWriteOnly, ABC):
|
|
|
352
391
|
RegisterWriteVerifyError: the read back data after the write does not match the
|
|
353
392
|
expected value
|
|
354
393
|
"""
|
|
355
|
-
if self.
|
|
394
|
+
if self.__in_read_context_manager:
|
|
395
|
+
raise RuntimeError('writes within the single read context manager are not permitted')
|
|
396
|
+
|
|
397
|
+
if self.__in_read_write_context_manager:
|
|
356
398
|
# pylint: disable=duplicate-code
|
|
357
399
|
if self.__register_state is None:
|
|
358
400
|
raise RuntimeError('The internal register state should never be None in the '
|
|
@@ -367,18 +409,19 @@ class RegAsyncReadWrite(RegAsyncReadOnly, RegAsyncWriteOnly, ABC):
|
|
|
367
409
|
f'after writing {data:X}')
|
|
368
410
|
|
|
369
411
|
async def read(self) -> int:
|
|
370
|
-
"""Asynchronously read value from the register
|
|
371
|
-
|
|
372
|
-
Returns:
|
|
373
|
-
The value from register
|
|
374
412
|
"""
|
|
375
|
-
|
|
413
|
+
Asynchronously read value from the register
|
|
414
|
+
"""
|
|
415
|
+
if self.__in_read_write_context_manager:
|
|
376
416
|
# pylint: disable=duplicate-code
|
|
377
417
|
if self.__register_state is None:
|
|
378
418
|
raise RuntimeError('The internal register state should never be None in the '
|
|
379
419
|
'context manager')
|
|
380
420
|
return self.__register_state
|
|
381
421
|
|
|
422
|
+
# the single read context manager is handled in the base class so does need any
|
|
423
|
+
# handling here
|
|
424
|
+
|
|
382
425
|
return await super().read()
|
|
383
426
|
|
|
384
427
|
async def read_fields(self) -> Dict['str', Union[bool, Enum, int]]:
|
|
@@ -386,7 +429,7 @@ class RegAsyncReadWrite(RegAsyncReadOnly, RegAsyncWriteOnly, ABC):
|
|
|
386
429
|
asynchronously read the register and return a dictionary of the field values
|
|
387
430
|
"""
|
|
388
431
|
return_dict: Dict['str', Union[bool, Enum, int]] = {}
|
|
389
|
-
async with self.
|
|
432
|
+
async with self.single_read() as reg:
|
|
390
433
|
for field in reg.readable_fields:
|
|
391
434
|
return_dict[field.inst_name] = await field.read()
|
|
392
435
|
|
|
@@ -554,7 +597,8 @@ class AsyncRegArray(BaseRegArray, ABC):
|
|
|
554
597
|
width: Width of the register in bits
|
|
555
598
|
accesswidth: Minimum access width of the register in bits
|
|
556
599
|
|
|
557
|
-
Returns:
|
|
600
|
+
Returns:
|
|
601
|
+
cache entry
|
|
558
602
|
|
|
559
603
|
"""
|
|
560
604
|
if not isinstance(width, int):
|
|
@@ -637,8 +681,6 @@ class AsyncRegArray(BaseRegArray, ABC):
|
|
|
637
681
|
verify (bool): very the write with a read afterwards
|
|
638
682
|
skip_write (bool): skip the write back at the end
|
|
639
683
|
|
|
640
|
-
Returns:
|
|
641
|
-
|
|
642
684
|
"""
|
|
643
685
|
self.__register_address_array = \
|
|
644
686
|
[self.address + (i * (self.width >> 3)) for i in range(self.__number_cache_entries)]
|
|
@@ -647,8 +689,12 @@ class AsyncRegArray(BaseRegArray, ABC):
|
|
|
647
689
|
else:
|
|
648
690
|
self.__register_array_cache = await self.__block_read()
|
|
649
691
|
self.__in_context_manager = True
|
|
650
|
-
|
|
651
|
-
|
|
692
|
+
# this try/finally is needed to make sure that in the event of an exception
|
|
693
|
+
# the state flags are not left incorrectly set
|
|
694
|
+
try:
|
|
695
|
+
yield self
|
|
696
|
+
finally:
|
|
697
|
+
self.__in_context_manager = False
|
|
652
698
|
if not skip_write:
|
|
653
699
|
await self.__block_write(self.__register_array_cache, verify)
|
|
654
700
|
|
|
@@ -711,7 +757,7 @@ class RegAsyncReadOnlyArray(AsyncRegArray, ABC):
|
|
|
711
757
|
|
|
712
758
|
"""
|
|
713
759
|
async with self._cached_access(verify=False, skip_write=True,
|
|
714
|
-
|
|
760
|
+
skip_initial_read=False) as reg_array:
|
|
715
761
|
yield reg_array
|
|
716
762
|
|
|
717
763
|
@property
|
|
@@ -818,8 +864,13 @@ class RegAsyncReadWriteArray(AsyncRegArray, ABC):
|
|
|
818
864
|
Returns:
|
|
819
865
|
|
|
820
866
|
"""
|
|
867
|
+
if skip_write is True:
|
|
868
|
+
warn('The `skip_write` argument will be removed in the future, use `single_read`'
|
|
869
|
+
' instead',
|
|
870
|
+
DeprecationWarning, stacklevel=2)
|
|
871
|
+
|
|
821
872
|
async with self._cached_access(verify=verify, skip_write=skip_write,
|
|
822
|
-
|
|
873
|
+
skip_initial_read=False) as reg_array:
|
|
823
874
|
yield reg_array
|
|
824
875
|
|
|
825
876
|
@property
|
|
@@ -26,6 +26,7 @@ from abc import ABC, abstractmethod
|
|
|
26
26
|
from contextlib import contextmanager
|
|
27
27
|
from array import array as Array
|
|
28
28
|
import sys
|
|
29
|
+
from warnings import warn
|
|
29
30
|
|
|
30
31
|
from .base import Node, AddressMap, RegFile, NodeArray
|
|
31
32
|
from .utility_functions import get_array_typecode
|
|
@@ -93,7 +94,8 @@ class BaseReg(Node, ABC):
|
|
|
93
94
|
|
|
94
95
|
@property
|
|
95
96
|
def max_value(self) -> int:
|
|
96
|
-
"""
|
|
97
|
+
"""
|
|
98
|
+
maximum unsigned integer value that can be stored in the register
|
|
97
99
|
|
|
98
100
|
For example:
|
|
99
101
|
|
|
@@ -121,9 +123,6 @@ class BaseReg(Node, ABC):
|
|
|
121
123
|
def width(self) -> int:
|
|
122
124
|
"""
|
|
123
125
|
The width of the register in bits, this uses the `regwidth` systemRDL property
|
|
124
|
-
|
|
125
|
-
Returns: register width
|
|
126
|
-
|
|
127
126
|
"""
|
|
128
127
|
return self.__width
|
|
129
128
|
|
|
@@ -131,8 +130,6 @@ class BaseReg(Node, ABC):
|
|
|
131
130
|
def accesswidth(self) -> int:
|
|
132
131
|
"""
|
|
133
132
|
The access width of the register in bits, this uses the `accesswidth` systemRDL property
|
|
134
|
-
|
|
135
|
-
Returns: register access width
|
|
136
133
|
"""
|
|
137
134
|
return self.__accesswidth
|
|
138
135
|
|
|
@@ -143,7 +140,6 @@ class BaseReg(Node, ABC):
|
|
|
143
140
|
"""
|
|
144
141
|
return self.__width >> 3
|
|
145
142
|
|
|
146
|
-
|
|
147
143
|
@property
|
|
148
144
|
@abstractmethod
|
|
149
145
|
def _is_readable(self) -> bool:
|
|
@@ -154,6 +150,7 @@ class BaseReg(Node, ABC):
|
|
|
154
150
|
def _is_writeable(self) -> bool:
|
|
155
151
|
...
|
|
156
152
|
|
|
153
|
+
|
|
157
154
|
class Reg(BaseReg, ABC):
|
|
158
155
|
"""
|
|
159
156
|
base class of non-async register wrappers
|
|
@@ -242,9 +239,6 @@ class BaseRegArray(NodeArray[BaseRegArrayElementType], ABC):
|
|
|
242
239
|
def width(self) -> int:
|
|
243
240
|
"""
|
|
244
241
|
The width of the register in bits, this uses the `regwidth` systemRDL property
|
|
245
|
-
|
|
246
|
-
Returns: register width
|
|
247
|
-
|
|
248
242
|
"""
|
|
249
243
|
return self.__width
|
|
250
244
|
|
|
@@ -252,8 +246,6 @@ class BaseRegArray(NodeArray[BaseRegArrayElementType], ABC):
|
|
|
252
246
|
def accesswidth(self) -> int:
|
|
253
247
|
"""
|
|
254
248
|
The access width of the register in bits, this uses the `accesswidth` systemRDL property
|
|
255
|
-
|
|
256
|
-
Returns: register access width
|
|
257
249
|
"""
|
|
258
250
|
return self.__accesswidth
|
|
259
251
|
|
|
@@ -267,7 +259,6 @@ class BaseRegArray(NodeArray[BaseRegArrayElementType], ABC):
|
|
|
267
259
|
accesswidth=self.accesswidth,
|
|
268
260
|
parent=self)
|
|
269
261
|
|
|
270
|
-
|
|
271
262
|
def _sub_instance(self, elements: Dict[Tuple[int, ...], BaseRegArrayElementType]) ->\
|
|
272
263
|
NodeArray[BaseRegArrayElementType]:
|
|
273
264
|
if not isinstance(self.parent, (AddressMap, AsyncAddressMap, RegFile,
|
|
@@ -431,7 +422,8 @@ class RegArray(BaseRegArray, ABC):
|
|
|
431
422
|
width: Width of the register in bits
|
|
432
423
|
accesswidth: Minimum access width of the register in bits
|
|
433
424
|
|
|
434
|
-
Returns:
|
|
425
|
+
Returns:
|
|
426
|
+
cache entry
|
|
435
427
|
|
|
436
428
|
"""
|
|
437
429
|
if not isinstance(width, int):
|
|
@@ -472,8 +464,6 @@ class RegArray(BaseRegArray, ABC):
|
|
|
472
464
|
width=width,
|
|
473
465
|
accesswidth=accesswidth)]
|
|
474
466
|
|
|
475
|
-
|
|
476
|
-
|
|
477
467
|
def __cache_write(self, addr: int, width: int, accesswidth: int, data: int) -> None:
|
|
478
468
|
"""
|
|
479
469
|
Used to replace the normal callbacks with those that access the cache
|
|
@@ -495,20 +485,18 @@ class RegArray(BaseRegArray, ABC):
|
|
|
495
485
|
width=width,
|
|
496
486
|
accesswidth=accesswidth)] = data
|
|
497
487
|
|
|
498
|
-
|
|
499
488
|
@property
|
|
500
489
|
def __cache_callbacks(self) -> NormalCallbackSet:
|
|
501
490
|
return NormalCallbackSet(read_callback=self.__cache_read,
|
|
502
491
|
write_callback=self.__cache_write)
|
|
503
492
|
|
|
504
|
-
|
|
505
493
|
@property
|
|
506
494
|
def __number_cache_entries(self) -> int:
|
|
507
495
|
return self.size // (self.width >> 3)
|
|
508
496
|
|
|
509
497
|
@contextmanager
|
|
510
498
|
def _cached_access(self, verify: bool = False, skip_write: bool = False,
|
|
511
|
-
|
|
499
|
+
skip_initial_read: bool = False) -> \
|
|
512
500
|
Generator[Self, None, None]:
|
|
513
501
|
"""
|
|
514
502
|
Context manager to allow multiple field reads/write to be done with a single set of
|
|
@@ -517,9 +505,6 @@ class RegArray(BaseRegArray, ABC):
|
|
|
517
505
|
Args:
|
|
518
506
|
verify (bool): very the write with a read afterwards
|
|
519
507
|
skip_write (bool): skip the write back at the end
|
|
520
|
-
|
|
521
|
-
Returns:
|
|
522
|
-
|
|
523
508
|
"""
|
|
524
509
|
self.__register_address_array = \
|
|
525
510
|
[self.address + (i * (self.width >> 3)) for i in range(self.__number_cache_entries)]
|
|
@@ -528,8 +513,12 @@ class RegArray(BaseRegArray, ABC):
|
|
|
528
513
|
else:
|
|
529
514
|
self.__register_array_cache = self.__block_read()
|
|
530
515
|
self.__in_context_manager = True
|
|
531
|
-
|
|
532
|
-
|
|
516
|
+
# this try/finally is needed to make sure that in the event of an exception
|
|
517
|
+
# the state flags are not left incorrectly set
|
|
518
|
+
try:
|
|
519
|
+
yield self
|
|
520
|
+
finally:
|
|
521
|
+
self.__in_context_manager = False
|
|
533
522
|
if not skip_write:
|
|
534
523
|
self.__block_write(self.__register_array_cache, verify)
|
|
535
524
|
|
|
@@ -549,6 +538,7 @@ class RegArray(BaseRegArray, ABC):
|
|
|
549
538
|
# pylint: disable-next=protected-access
|
|
550
539
|
return cast(NormalCallbackSet, self.parent._callbacks)
|
|
551
540
|
|
|
541
|
+
|
|
552
542
|
class RegReadOnly(Reg, ABC):
|
|
553
543
|
"""
|
|
554
544
|
class for a read only register
|
|
@@ -589,21 +579,19 @@ class RegReadOnly(Reg, ABC):
|
|
|
589
579
|
"""
|
|
590
580
|
Context manager to allow multiple field accesses to be performed with a single
|
|
591
581
|
read of the register
|
|
592
|
-
|
|
593
|
-
Returns:
|
|
594
|
-
|
|
595
582
|
"""
|
|
596
583
|
self.__register_state = self.read()
|
|
597
584
|
self.__in_context_manager = True
|
|
598
|
-
|
|
599
|
-
|
|
585
|
+
# this try/finally is needed to make sure that in the event of an exception
|
|
586
|
+
# the state flags are not left incorrectly set
|
|
587
|
+
try:
|
|
588
|
+
yield self
|
|
589
|
+
finally:
|
|
590
|
+
self.__in_context_manager = False
|
|
600
591
|
|
|
601
592
|
def read(self) -> int:
|
|
602
|
-
"""
|
|
603
|
-
|
|
604
|
-
Returns:
|
|
605
|
-
The value from register
|
|
606
|
-
|
|
593
|
+
"""
|
|
594
|
+
Read value from the register
|
|
607
595
|
"""
|
|
608
596
|
if self.__in_context_manager:
|
|
609
597
|
return self.__register_state
|
|
@@ -748,7 +736,8 @@ class RegReadWrite(RegReadOnly, RegWriteOnly, ABC):
|
|
|
748
736
|
class for a read and write only register
|
|
749
737
|
|
|
750
738
|
"""
|
|
751
|
-
__slots__: List[str] = ['
|
|
739
|
+
__slots__: List[str] = ['__in_read_write_context_manager', '__in_read_context_manager',
|
|
740
|
+
'__register_state']
|
|
752
741
|
|
|
753
742
|
# pylint: disable=too-many-arguments, duplicate-code
|
|
754
743
|
def __init__(self, *,
|
|
@@ -764,7 +753,8 @@ class RegReadWrite(RegReadOnly, RegWriteOnly, ABC):
|
|
|
764
753
|
inst_name=inst_name,
|
|
765
754
|
parent=parent, width=width, accesswidth=accesswidth)
|
|
766
755
|
|
|
767
|
-
self.
|
|
756
|
+
self.__in_read_write_context_manager: bool = False
|
|
757
|
+
self.__in_read_context_manager: bool = False
|
|
768
758
|
self.__register_state: Optional[int] = None
|
|
769
759
|
|
|
770
760
|
# pylint: enable=too-many-arguments, duplicate-code
|
|
@@ -780,19 +770,47 @@ class RegReadWrite(RegReadOnly, RegWriteOnly, ABC):
|
|
|
780
770
|
verify (bool): very the write with a read afterwards
|
|
781
771
|
skip_write (bool): skip the write back at the end
|
|
782
772
|
|
|
783
|
-
Returns:
|
|
784
|
-
|
|
785
773
|
"""
|
|
774
|
+
if self.__in_read_context_manager:
|
|
775
|
+
raise RuntimeError('using the `single_read_modify_write` context manager within the '
|
|
776
|
+
'single_read` is not permitted')
|
|
777
|
+
|
|
778
|
+
if skip_write is True:
|
|
779
|
+
warn('The `skip_write` argument will be removed in the future, use `single_read`'
|
|
780
|
+
' instead',
|
|
781
|
+
DeprecationWarning, stacklevel=2)
|
|
782
|
+
|
|
786
783
|
self.__register_state = self.read()
|
|
787
|
-
self.
|
|
788
|
-
|
|
789
|
-
|
|
784
|
+
self.__in_read_write_context_manager = True
|
|
785
|
+
try:
|
|
786
|
+
yield self
|
|
787
|
+
finally:
|
|
788
|
+
# need to make sure the state flag is cleared even if an exception occurs within
|
|
789
|
+
# the context
|
|
790
|
+
self.__in_read_write_context_manager = False
|
|
791
|
+
|
|
790
792
|
if not skip_write:
|
|
791
793
|
self.write(self.__register_state, verify)
|
|
792
794
|
|
|
793
795
|
# clear the register states at the end of the context manager
|
|
794
796
|
self.__register_state = None
|
|
795
797
|
|
|
798
|
+
@contextmanager
|
|
799
|
+
def single_read(self) -> \
|
|
800
|
+
Generator[Self, None, None]:
|
|
801
|
+
"""
|
|
802
|
+
Context manager to allow multiple field reads with a single register read
|
|
803
|
+
"""
|
|
804
|
+
if self.__in_read_write_context_manager:
|
|
805
|
+
raise RuntimeError('using the `single_read` context manager within the '
|
|
806
|
+
'single_read_modify_write` is not permitted')
|
|
807
|
+
self.__in_read_context_manager = True
|
|
808
|
+
try:
|
|
809
|
+
with super().single_read() as reg:
|
|
810
|
+
yield reg
|
|
811
|
+
finally:
|
|
812
|
+
self.__in_read_context_manager = False
|
|
813
|
+
|
|
796
814
|
def write(self, data: int, verify: bool = False) -> None: # pylint: disable=arguments-differ
|
|
797
815
|
"""
|
|
798
816
|
Writes a value to the register
|
|
@@ -808,7 +826,10 @@ class RegReadWrite(RegReadOnly, RegWriteOnly, ABC):
|
|
|
808
826
|
RegisterWriteVerifyError: the read back data after the write does not match the
|
|
809
827
|
expected value
|
|
810
828
|
"""
|
|
811
|
-
if self.
|
|
829
|
+
if self.__in_read_context_manager:
|
|
830
|
+
raise RuntimeError('writes within the single read context manager are not permitted')
|
|
831
|
+
|
|
832
|
+
if self.__in_read_write_context_manager:
|
|
812
833
|
if self.__register_state is None:
|
|
813
834
|
raise RuntimeError('The internal register state should never be None in the '
|
|
814
835
|
'context manager')
|
|
@@ -822,17 +843,18 @@ class RegReadWrite(RegReadOnly, RegWriteOnly, ABC):
|
|
|
822
843
|
f'after writing {data:X}')
|
|
823
844
|
|
|
824
845
|
def read(self) -> int:
|
|
825
|
-
"""Read value from the register
|
|
826
|
-
|
|
827
|
-
Returns:
|
|
828
|
-
The value from register
|
|
829
846
|
"""
|
|
830
|
-
|
|
847
|
+
Read value from the register
|
|
848
|
+
"""
|
|
849
|
+
if self.__in_read_write_context_manager:
|
|
831
850
|
if self.__register_state is None:
|
|
832
851
|
raise RuntimeError('The internal register state should never be None in the '
|
|
833
852
|
'context manager')
|
|
834
853
|
return self.__register_state
|
|
835
854
|
|
|
855
|
+
# the single read context manager is handled in the base class so does need any
|
|
856
|
+
# handling here
|
|
857
|
+
|
|
836
858
|
return super().read()
|
|
837
859
|
|
|
838
860
|
def write_fields(self, **kwargs) -> None: # type: ignore[no-untyped-def]
|
|
@@ -856,7 +878,7 @@ class RegReadWrite(RegReadOnly, RegWriteOnly, ABC):
|
|
|
856
878
|
read the register and return a dictionary of the field values
|
|
857
879
|
"""
|
|
858
880
|
return_dict: Dict['str', Union[bool, Enum, int]] = {}
|
|
859
|
-
with self.
|
|
881
|
+
with self.single_read() as reg:
|
|
860
882
|
for field in reg.readable_fields:
|
|
861
883
|
return_dict[field.inst_name] = field.read()
|
|
862
884
|
|
|
@@ -872,9 +894,11 @@ class RegReadWrite(RegReadOnly, RegWriteOnly, ABC):
|
|
|
872
894
|
# pylint: disable=duplicate-code
|
|
873
895
|
return True
|
|
874
896
|
|
|
897
|
+
|
|
875
898
|
ReadableRegister = Union[RegReadOnly, RegReadWrite]
|
|
876
899
|
WritableRegister = Union[RegWriteOnly, RegReadWrite]
|
|
877
900
|
|
|
901
|
+
|
|
878
902
|
class RegReadOnlyArray(RegArray, ABC):
|
|
879
903
|
"""
|
|
880
904
|
base class for a array of read only registers
|
|
@@ -911,12 +935,6 @@ class RegReadOnlyArray(RegArray, ABC):
|
|
|
911
935
|
"""
|
|
912
936
|
Context manager to allow multiple field reads/write to be done with a single set of
|
|
913
937
|
field operations
|
|
914
|
-
|
|
915
|
-
Args:
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
Returns:
|
|
919
|
-
|
|
920
938
|
"""
|
|
921
939
|
with self._cached_access(verify=False, skip_write=True,
|
|
922
940
|
skip_initial_read=False) as reg_array:
|
|
@@ -932,6 +950,7 @@ class RegReadOnlyArray(RegArray, ABC):
|
|
|
932
950
|
# pylint: disable=duplicate-code
|
|
933
951
|
return False
|
|
934
952
|
|
|
953
|
+
|
|
935
954
|
class RegWriteOnlyArray(RegArray, ABC):
|
|
936
955
|
"""
|
|
937
956
|
base class for a array of write only registers
|
|
@@ -968,12 +987,6 @@ class RegWriteOnlyArray(RegArray, ABC):
|
|
|
968
987
|
"""
|
|
969
988
|
Context manager to allow multiple field reads/write to be done with a single set of
|
|
970
989
|
field operations
|
|
971
|
-
|
|
972
|
-
Args:
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
Returns:
|
|
976
|
-
|
|
977
990
|
"""
|
|
978
991
|
with self._cached_access(verify=False, skip_write=False,
|
|
979
992
|
skip_initial_read=True) as reg_array:
|
|
@@ -1018,7 +1031,6 @@ class RegReadWriteArray(RegArray, ABC):
|
|
|
1018
1031
|
parent=parent, address=address, width=width, accesswidth=accesswidth,
|
|
1019
1032
|
stride=stride, dimensions=dimensions, elements=elements)
|
|
1020
1033
|
|
|
1021
|
-
|
|
1022
1034
|
# pylint: enable=too-many-arguments,duplicate-code
|
|
1023
1035
|
|
|
1024
1036
|
@contextmanager
|
|
@@ -1031,12 +1043,9 @@ class RegReadWriteArray(RegArray, ABC):
|
|
|
1031
1043
|
Args:
|
|
1032
1044
|
verify (bool): very the write with a read afterwards
|
|
1033
1045
|
skip_write (bool): skip the write back at the end
|
|
1034
|
-
|
|
1035
|
-
Returns:
|
|
1036
|
-
|
|
1037
1046
|
"""
|
|
1038
1047
|
with self._cached_access(verify=verify, skip_write=skip_write,
|
|
1039
|
-
|
|
1048
|
+
skip_initial_read=False) as reg_array:
|
|
1040
1049
|
yield reg_array
|
|
1041
1050
|
|
|
1042
1051
|
@property
|