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.
Files changed (119) hide show
  1. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/PKG-INFO +1 -1
  2. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/docs/api_components.rst +3 -2
  3. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python/__about__.py +1 -1
  4. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python/lib/async_register.py +77 -26
  5. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python/lib/register.py +74 -65
  6. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python.egg-info/PKG-INFO +1 -1
  7. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/unit_tests/test_reg.py +202 -0
  8. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/.github/workflows/action.yaml +0 -0
  9. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/.gitignore +0 -0
  10. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/.readthedocs.yaml +0 -0
  11. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/LICENSE +0 -0
  12. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/MANIFEST.in +0 -0
  13. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/README.md +0 -0
  14. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/docs/api.rst +0 -0
  15. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/docs/command_line.rst +0 -0
  16. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/docs/conf.py +0 -0
  17. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/docs/customisation.rst +0 -0
  18. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/docs/design_decisions.rst +0 -0
  19. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/docs/design_tools.rst +0 -0
  20. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/docs/generated_package.rst +0 -0
  21. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/docs/genindex.rst +0 -0
  22. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/docs/index.rst +0 -0
  23. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/docs/installation.rst +0 -0
  24. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/docs/requirements.txt +0 -0
  25. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/example/array_access/array_access.rdl +0 -0
  26. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/example/array_access/demo_array_access.py +0 -0
  27. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/example/enumerated_fields/demo_enumerated_fields.py +0 -0
  28. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/example/enumerated_fields/enumerated_fields.rdl +0 -0
  29. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/example/optimised_access/demo_optimised_access.py +0 -0
  30. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/example/optimised_access/demo_optimised_array_access.py +0 -0
  31. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/example/optimised_access/optimised_access.rdl +0 -0
  32. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/example/optimised_access/optimised_array_access.rdl +0 -0
  33. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/example/overridden_names/over_ridden_names.py +0 -0
  34. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/example/overridden_names/overridden_names.rdl +0 -0
  35. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/example/simulating_callbacks/chip_with_a_GPIO.rdl +0 -0
  36. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/example/simulating_callbacks/flashing_the_LED.py +0 -0
  37. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/example/tranversing_address_map/chip_with_registers.rdl +0 -0
  38. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/example/tranversing_address_map/dumping_register_state_to_json_file.py +0 -0
  39. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/example/tranversing_address_map/reg_dump.json +0 -0
  40. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/example/tranversing_address_map/reseting_registers.py +0 -0
  41. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/example/tranversing_address_map/writing_register_state_from_json_file.py +0 -0
  42. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/example/why_ral/__init__.py +0 -0
  43. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/example/why_ral/gpio.rdl +0 -0
  44. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/example/why_ral/hardware_sim.py +0 -0
  45. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/example/why_ral/with_hal.py +0 -0
  46. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/example/why_ral/with_ral.py +0 -0
  47. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/example/why_ral/without_ral.py +0 -0
  48. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/generate_and_test.py +0 -0
  49. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/generate_testcases.py +0 -0
  50. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/pyproject.toml +0 -0
  51. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/setup.cfg +0 -0
  52. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python/.coveragerc +0 -0
  53. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python/__init__.py +0 -0
  54. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python/__peakrdl__.py +0 -0
  55. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python/_node_walkers.py +0 -0
  56. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python/exporter.py +0 -0
  57. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python/lib/__init__.py +0 -0
  58. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python/lib/base.py +0 -0
  59. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python/lib/callbacks.py +0 -0
  60. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python/lib/fields.py +0 -0
  61. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python/lib/memory.py +0 -0
  62. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python/lib/utility_functions.py +0 -0
  63. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python/safe_name_utility.py +0 -0
  64. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python/systemrdl_node_utility_functions.py +0 -0
  65. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python/templates/__init__.py +0 -0
  66. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python/templates/addrmap.py.jinja +0 -0
  67. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python/templates/addrmap_field.py.jinja +0 -0
  68. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python/templates/addrmap_memory.py.jinja +0 -0
  69. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python/templates/addrmap_register.py.jinja +0 -0
  70. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python/templates/addrmap_simulation.py.jinja +0 -0
  71. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python/templates/addrmap_simulation_tb.jinja +0 -0
  72. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python/templates/addrmap_tb.py.jinja +0 -0
  73. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python/templates/baseclass_tb.py.jinja +0 -0
  74. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python/templates/header.py.jinja +0 -0
  75. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python/templates/header_tb.py.jinja +0 -0
  76. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python/templates/reg_definitions.py.jinja +0 -0
  77. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python.egg-info/SOURCES.txt +0 -0
  78. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python.egg-info/dependency_links.txt +0 -0
  79. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python.egg-info/entry_points.txt +0 -0
  80. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python.egg-info/requires.txt +0 -0
  81. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/src/peakrdl_python.egg-info/top_level.txt +0 -0
  82. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/.mypy.ini +0 -0
  83. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/alternative_template_toml/peakrdl.toml +0 -0
  84. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/alternative_templates/header.py.jinja +0 -0
  85. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/alternative_templates/header_tb.py.jinja +0 -0
  86. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/pylint.rc +0 -0
  87. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/testcases/RDLFormatCode_example.rdl +0 -0
  88. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/testcases/addr_map.rdl +0 -0
  89. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/testcases/all_register_access_types.rdl +0 -0
  90. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/testcases/basic.rdl +0 -0
  91. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/testcases/block_a.xml +0 -0
  92. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/testcases/block_b.xml +0 -0
  93. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/testcases/different_array_types.rdl +0 -0
  94. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/testcases/enum_example.rdl +0 -0
  95. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/testcases/example_issue_106.rdl +0 -0
  96. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/testcases/field_scope.rdl +0 -0
  97. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/testcases/field_with_overridden_reset.rdl +0 -0
  98. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/testcases/fields_with_HW_write.rdl +0 -0
  99. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/testcases/fields_with_reset_values.rdl +0 -0
  100. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/testcases/memories.rdl +0 -0
  101. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/testcases/memories_with_registers.rdl +0 -0
  102. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/testcases/msb0_and_lsb0.rdl +0 -0
  103. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/testcases/multi_block.rdl +0 -0
  104. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/testcases/multifile.rdl +0 -0
  105. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/testcases/name_clash.rdl +0 -0
  106. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/testcases/overridden_python_name.rdl +0 -0
  107. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/testcases/parametrised_readonly_and_readwrite.rdl +0 -0
  108. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/testcases/regfile_and_arrays.rdl +0 -0
  109. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/testcases/same_but_different_enum.rdl +0 -0
  110. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/testcases/signals_definitions_at_various_levels.rdl +0 -0
  111. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/testcases/simple.rdl +0 -0
  112. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/testcases/simple.xml +0 -0
  113. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/testcases/sizes_registers.rdl +0 -0
  114. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/testcases/sizes_registers_array.rdl +0 -0
  115. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/testcases/write_only_enum_with_undefined_reset.rdl +0 -0
  116. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/unit_tests/__init__.py +0 -0
  117. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/unit_tests/simple_components.py +0 -0
  118. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/unit_tests/test_array_indexing.py +0 -0
  119. {peakrdl-python-0.7.4 → peakrdl_python-0.7.5}/tests/unit_tests/test_optimised_reg_array.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: peakrdl-python
3
- Version: 0.7.4
3
+ Version: 0.7.5
4
4
  Summary: Generate Python Register Access Layer (RAL) from SystemRDL
5
5
  Author: Keith Brady
6
6
  License: GNU GENERAL PUBLIC LICENSE
@@ -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:
@@ -17,4 +17,4 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
17
17
 
18
18
  Variables that describes the peakrdl-python Package
19
19
  """
20
- __version__ = "0.7.4"
20
+ __version__ = "0.7.5"
@@ -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
- yield self
137
- self.__in_context_manager = False
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] = ['__in_context_manager', '__register_state']
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.__in_context_manager: bool = False
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
- self.__in_context_manager = True
332
- yield self
333
- self.__in_context_manager = False
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.__in_context_manager:
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
- if self.__in_context_manager:
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.single_read_modify_write(skip_write=True) as reg:
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: cache entry
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
- yield self
651
- self.__in_context_manager = False
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
- skip_initial_read=False) as reg_array:
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
- skip_initial_read=False) as reg_array:
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
- """maximum unsigned integer value that can be stored in the register
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: cache entry
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
- skip_initial_read: bool = False) -> \
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
- yield self
532
- self.__in_context_manager = False
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
- yield self
599
- self.__in_context_manager = False
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
- """Read value from the register
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] = ['__in_context_manager', '__register_state']
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.__in_context_manager: bool = False
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.__in_context_manager = True
788
- yield self
789
- self.__in_context_manager = False
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.__in_context_manager:
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
- if self.__in_context_manager:
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.single_read_modify_write(skip_write=True) as reg:
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
- skip_initial_read=False) as reg_array:
1048
+ skip_initial_read=False) as reg_array:
1040
1049
  yield reg_array
1041
1050
 
1042
1051
  @property
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: peakrdl-python
3
- Version: 0.7.4
3
+ Version: 0.7.5
4
4
  Summary: Generate Python Register Access Layer (RAL) from SystemRDL
5
5
  Author: Keith Brady
6
6
  License: GNU GENERAL PUBLIC LICENSE