diff --git a/src/peakrdl_python/lib_test/_common_base_test_class.py b/src/peakrdl_python/lib_test/_common_base_test_class.py index 23ba92b0..c0c5c907 100644 --- a/src/peakrdl_python/lib_test/_common_base_test_class.py +++ b/src/peakrdl_python/lib_test/_common_base_test_class.py @@ -26,6 +26,16 @@ from ..lib import FieldEnumReadWrite, FieldEnumReadOnly, FieldEnumWriteOnly from ..lib import FieldAsyncReadOnly, FieldAsyncWriteOnly, FieldAsyncReadWrite from ..lib import FieldEnumAsyncReadOnly, FieldEnumAsyncWriteOnly, FieldEnumAsyncReadWrite +from ..lib import RegReadOnly, RegReadWrite, RegWriteOnly +from ..lib import RegAsyncReadOnly, RegAsyncReadWrite, RegAsyncWriteOnly +from ..lib import AddressMap, AsyncAddressMap +from ..lib import RegFile, AsyncRegFile +from ..lib import MemoryReadOnly, MemoryReadOnlyLegacy +from ..lib import MemoryWriteOnly, MemoryWriteOnlyLegacy +from ..lib import MemoryReadWrite, MemoryReadWriteLegacy +from ..lib import MemoryAsyncReadOnly, MemoryAsyncReadOnlyLegacy +from ..lib import MemoryAsyncWriteOnly, MemoryAsyncWriteOnlyLegacy +from ..lib import MemoryAsyncReadWrite, MemoryAsyncReadWriteLegacy from ..lib.base_register import BaseReg from ..lib import Base from .utilities import get_field_bitmask_int, get_field_inv_bitmask @@ -136,3 +146,124 @@ def _test_node_inst_name(self, self.assertEqual(dut.inst_name, inst_name) full_inst_name = parent_full_inst_name + '.' + inst_name self.assertEqual(dut.full_inst_name, full_inst_name) + + def _test_field_iterators(self, *, + rut: Union[RegReadOnly, + RegReadWrite, + RegWriteOnly, + RegAsyncReadOnly, + RegAsyncReadWrite, + RegAsyncWriteOnly], + has_sw_readable: bool, + has_sw_writable: bool, + readable_fields: set[str], + writeable_fields: set[str]) -> None: + if has_sw_readable: + if not isinstance(rut, (RegReadOnly, + RegReadWrite, + RegAsyncReadOnly, + RegAsyncReadWrite, + )): + raise TypeError(f'Register was expected to readable, got {type(rut)}') + + child_readable_field_names = { field.inst_name for field in rut.readable_fields} + + self.assertEqual(readable_fields, child_readable_field_names) + else: + self.assertFalse(hasattr(rut, 'readable_fields')) + # check the readable_fields is empty + self.assertFalse(readable_fields) + + if has_sw_writable: + if not isinstance(rut, (RegWriteOnly, + RegReadWrite, + RegAsyncWriteOnly, + RegAsyncReadWrite, + )): + raise TypeError(f'Register was expected to writable, got {type(rut)}') + + child_writeable_fields_names = {field.inst_name for field in rut.writable_fields} + + self.assertEqual(writeable_fields, child_writeable_fields_names) + else: + self.assertFalse(hasattr(rut, 'writeable_fields')) + # check the writeable_fields is empty + self.assertFalse(writeable_fields) + + child_field_names = {field.inst_name for field in rut.fields} + self.assertEqual(readable_fields | writeable_fields, child_field_names) + + def _test_register_iterators(self, + dut: Union[AddressMap, AsyncAddressMap, RegFile, AsyncRegFile, + MemoryReadOnly, MemoryReadOnlyLegacy, + MemoryWriteOnly, MemoryWriteOnlyLegacy, + MemoryReadWrite, MemoryReadWriteLegacy, + MemoryAsyncReadOnly, MemoryAsyncReadOnlyLegacy, + MemoryAsyncWriteOnly, MemoryAsyncWriteOnlyLegacy, + MemoryAsyncReadWrite, MemoryAsyncReadWriteLegacy], + readable_registers: set[str], + writeable_registers: set[str]) -> None: + + if isinstance(dut, (AddressMap, AsyncAddressMap, RegFile, AsyncRegFile, + MemoryReadOnly, MemoryReadOnlyLegacy, + MemoryReadWrite, MemoryReadWriteLegacy, + MemoryAsyncReadOnly, MemoryAsyncReadOnlyLegacy, + MemoryAsyncReadWrite, MemoryAsyncReadWriteLegacy)): + child_readable_reg_names = { reg.inst_name for reg in + dut.get_readable_registers(unroll=True)} + self.assertEqual(readable_registers, child_readable_reg_names) + else: + self.assertFalse(hasattr(dut, 'get_readable_registers')) + + if isinstance(dut, (AddressMap, AsyncAddressMap, RegFile, AsyncRegFile, + MemoryWriteOnly, MemoryWriteOnlyLegacy, + MemoryReadWrite, MemoryReadWriteLegacy, + MemoryAsyncWriteOnly, MemoryAsyncWriteOnlyLegacy, + MemoryAsyncReadWrite, MemoryAsyncReadWriteLegacy)): + child_writable_reg_names = {reg.inst_name for reg in + dut.get_writable_registers(unroll=True)} + self.assertEqual(writeable_registers, child_writable_reg_names) + else: + self.assertFalse(hasattr(dut, 'get_writable_registers')) + + child_reg_names = {field.inst_name for field in dut.get_registers(unroll=True)} + self.assertEqual(readable_registers | writeable_registers, child_reg_names) + + + def _test_memory_iterators(self, + dut: Union[AddressMap, AsyncAddressMap], + memories: set[str]) -> None: + child_mem_names = {reg.inst_name for reg in dut.get_memories(unroll=True)} + self.assertEqual(memories, child_mem_names) + + def __test_section_iterators(self, + dut: Union[AddressMap, AsyncAddressMap, RegFile, AsyncRegFile], + sections: set[str]) -> None: + child_section_names = {reg.inst_name for reg in dut.get_sections(unroll=True)} + self.assertEqual(sections, child_section_names) + + def _test_addrmap_iterators(self, *, + dut: Union[AddressMap, AsyncAddressMap], + memories: set[str], + sections: set[str], + readable_registers: set[str], + writeable_registers: set[str]) -> None: + self._test_register_iterators(dut=dut, + readable_registers=readable_registers, + writeable_registers=writeable_registers) + self._test_memory_iterators(dut=dut, + memories=memories) + self.__test_section_iterators(dut=dut, + sections=sections) + + def _test_regfile_iterators(self, + dut: Union[RegFile, AsyncRegFile], + sections: set[str], + readable_registers: set[str], + writeable_registers: set[str]) -> None: + self._test_register_iterators(dut=dut, + readable_registers=readable_registers, + writeable_registers=writeable_registers) + self.__test_section_iterators(dut=dut, + sections=sections) + self.assertFalse(hasattr(dut, 'get_memories')) diff --git a/src/peakrdl_python/lib_test/async_reg_base_test_class.py b/src/peakrdl_python/lib_test/async_reg_base_test_class.py index 5f49fe2c..5556fab1 100644 --- a/src/peakrdl_python/lib_test/async_reg_base_test_class.py +++ b/src/peakrdl_python/lib_test/async_reg_base_test_class.py @@ -318,13 +318,21 @@ async def _single_enum_field_read_and_write_test( enum_definition=enum_definition) async def _single_register_read_and_write_test( - self, + self, *, rut: Union[RegAsyncReadOnly, RegAsyncReadWrite, RegAsyncWriteOnly], has_sw_readable: bool, - has_sw_writable: bool) -> None: + has_sw_writable: bool, + readable_fields: set[str], + writeable_fields: set[str]) -> None: # the register properties are tested separately so are available to be used here + self._test_field_iterators(rut=rut, + has_sw_readable=has_sw_readable, + has_sw_writable=has_sw_writable, + readable_fields=readable_fields, + writeable_fields=writeable_fields) + await self.__single_register_simulator_read_and_write_test( rut=rut, has_sw_readable=has_sw_readable, diff --git a/src/peakrdl_python/lib_test/base_reg_test_class.py b/src/peakrdl_python/lib_test/base_reg_test_class.py index 29a93f98..7aa7ca84 100644 --- a/src/peakrdl_python/lib_test/base_reg_test_class.py +++ b/src/peakrdl_python/lib_test/base_reg_test_class.py @@ -309,13 +309,21 @@ def _single_enum_field_read_and_write_test( self.__single_enum_field_write_test(fut=fut, enum_definition=enum_definition) - def _single_register_read_and_write_test(self, + def _single_register_read_and_write_test(self, *, rut: Union[RegReadOnly, RegReadWrite, RegWriteOnly], has_sw_readable: bool, - has_sw_writable: bool) -> None: + has_sw_writable: bool, + readable_fields: set[str], + writeable_fields: set[str]) -> None: # the register properties are tested separately so are available to be used here + self._test_field_iterators(rut=rut, + has_sw_readable=has_sw_readable, + has_sw_writable=has_sw_writable, + readable_fields=readable_fields, + writeable_fields=writeable_fields) + self.__single_register_simulator_read_and_write_test(rut=rut, has_sw_readable=has_sw_readable, has_sw_writable=has_sw_writable) diff --git a/src/peakrdl_python/templates/addrmap_register.py.jinja b/src/peakrdl_python/templates/addrmap_register.py.jinja index fe430b93..06747872 100644 --- a/src/peakrdl_python/templates/addrmap_register.py.jinja +++ b/src/peakrdl_python/templates/addrmap_register.py.jinja @@ -93,7 +93,7 @@ class {{node.python_class_name}}({{node.base_class(asyncoutput)}}): Memory{% if asyncoutput %}Async{% endif -%}ReadWrite{% if legacy_block_access %}Legacy{% endif %} {%- elif node.read_only -%} Readable{% if asyncoutput %}Async{% endif -%}Memory{% if legacy_block_access %}Legacy{% endif %} - {%- elif node.read_only -%} + {%- elif node.write_only -%} Writable{% if asyncoutput %}Async{% endif -%}Memory{% if legacy_block_access %}Legacy{% endif %} {%- endif -%} ]): diff --git a/src/peakrdl_python/templates/addrmap_tb.py.jinja b/src/peakrdl_python/templates/addrmap_tb.py.jinja index c2ace76f..279447e5 100644 --- a/src/peakrdl_python/templates/addrmap_tb.py.jinja +++ b/src/peakrdl_python/templates/addrmap_tb.py.jinja @@ -201,7 +201,9 @@ class {{fq_block_name}}_single_access({{top_node.inst_name}}_TestCase): # type: {% for node in owned_elements.registers -%} with self.subTest(msg='register: {{'.'.join(node.get_path_segments())}}'): self._single_register_property_test(rut=self.dut.{{'.'.join(get_python_path_segments(node))}}, address={{node.absolute_address}}, width={{node.size * 8}}, accesswidth={% if 'accesswidth' in node.list_properties() -%}{{node.get_property('accesswidth')}}{% else %}None{%- endif %}) - {% if asyncoutput %}await {%endif %}self._single_register_read_and_write_test(rut=self.dut.{{'.'.join(get_python_path_segments(node))}}, has_sw_readable={{node.has_sw_readable}}, has_sw_writable={{node.has_sw_writable}}) + {% if asyncoutput %}await {%endif %}self._single_register_read_and_write_test(rut=self.dut.{{'.'.join(get_python_path_segments(node))}}, has_sw_readable={{node.has_sw_readable}}, has_sw_writable={{node.has_sw_writable}}, + readable_fields=set([ {%- for child_node in node.children(unroll=True) -%}{%- if not hide_node_func(child_node) -%}{% if isinstance(child_node, systemrdlFieldNode) %}{% if child_node.is_sw_readable %}'{{child_node.inst_name}}',{% endif %}{% endif %}{% endif %}{% endfor %} ]), + writeable_fields=set([ {%- for child_node in node.children(unroll=True) -%}{%- if not hide_node_func(child_node) -%}{% if isinstance(child_node, systemrdlFieldNode) %}{% if child_node.is_sw_writable %}'{{child_node.inst_name}}',{% endif %}{% endif %}{% endif %}{% endfor %} ]) ) {% endfor %} {% if asyncoutput %}async {% endif %}def test_field(self) -> None: @@ -341,308 +343,45 @@ class {{fq_block_name}}_single_access({{top_node.inst_name}}_TestCase): # type: {% if block == top_node %} def test_top_traversal_iterators(self) -> None: - {% if asyncoutput %} - expected_writable_regs: list[WritableAsyncRegister] - expected_readable_regs: list[ReadableAsyncRegister] - expected_memories:list[Union[MemoryAsyncReadOnly{% if legacy_block_access %}Legacy{% endif %}, MemoryAsyncWriteOnly{% if legacy_block_access %}Legacy{% endif %}, MemoryAsyncReadWrite{% if legacy_block_access %}Legacy{% endif %}]] - {% else %} - expected_writable_regs: list[WritableRegister] - expected_readable_regs: list[ReadableRegister] - expected_memories:list[Union[MemoryReadOnly{% if legacy_block_access %}Legacy{% endif %}, MemoryWriteOnly{% if legacy_block_access %}Legacy{% endif %}, MemoryReadWrite{% if legacy_block_access %}Legacy{% endif %}]] - {% endif %} - expected_sections : list[Union[{% if asyncoutput %}Async{% endif %}AddressMap, {% if asyncoutput %}Async{% endif %}RegFile]] - - # check the readable registers - expected_readable_regs = [ {%- for child_node in top_node.children(unroll=True) %} - {%- if not hide_node_func(child_node) %} - {%- if isinstance(child_node, systemrdlRegNode) %}{% if child_node.has_sw_readable %}self.dut.{{'.'.join(get_python_path_segments(child_node))}}, # type: ignore[union-attr,list-item] {% endif %}{% endif %} - {% endif %} - {% endfor %} ] - readable_regs = [] - for readable_reg in self.dut.get_readable_registers(unroll=True): # type: ignore[union-attr] - self.assertIsInstance(readable_reg, (Reg{% if asyncoutput %}Async{% endif %}ReadWrite, Reg{% if asyncoutput %}Async{% endif %}ReadOnly)) - readable_regs.append(readable_reg) - self.assertCountEqual(expected_readable_regs, readable_regs) - {# check the rolled case second #} - expected_readable_regs = [ {%- for child_node in top_node.children(unroll=False) %} - {%- if not hide_node_func(child_node) %} - {%- if isinstance(child_node, systemrdlRegNode) %}{% if child_node.has_sw_readable %}self.dut.{{'.'.join(get_python_path_segments(child_node))}}, # type: ignore[union-attr,list-item] {% endif %}{% endif %} - {% endif %} - {% endfor %} ] - readable_regs = [] - for readable_reg in self.dut.get_readable_registers(unroll=False): # type: ignore[union-attr] - readable_regs.append(readable_reg) - self.assertCountEqual(expected_readable_regs, readable_regs) - - # check the writable registers - expected_writable_regs = [ {%- for child_node in top_node.children(unroll=True) %} - {%- if not hide_node_func(child_node) %} - {%- if isinstance(child_node, systemrdlRegNode) %}{% if child_node.has_sw_writable %}self.dut.{{'.'.join(get_python_path_segments(child_node))}}, # type: ignore[union-attr,list-item] {% endif %}{% endif %} - {% endif %} - {% endfor %} ] - writable_regs = [] - for writable_reg in self.dut.get_writable_registers(unroll=True): # type: ignore[union-attr] - self.assertIsInstance(writable_reg, (Reg{% if asyncoutput %}Async{% endif %}ReadWrite, Reg{% if asyncoutput %}Async{% endif %}WriteOnly)) - writable_regs.append(writable_reg) - self.assertCountEqual(expected_writable_regs, writable_regs) - {# check the rolled case second #} - expected_writable_regs = [ {%- for child_node in top_node.children(unroll=False) %} - {%- if not hide_node_func(child_node) %} - {%- if isinstance(child_node, systemrdlRegNode) %}{% if child_node.has_sw_writable %}self.dut.{{'.'.join(get_python_path_segments(child_node))}}, # type: ignore[union-attr,list-item] {% endif %}{% endif %} - {% endif %} - {% endfor %} ] - writable_regs = [] - for writable_reg in self.dut.get_writable_registers(unroll=False): # type: ignore[union-attr] - writable_regs.append(writable_reg) - self.assertCountEqual(expected_writable_regs, writable_regs) - - # check the sections - expected_sections = [ {%- for child_node in top_node.children(unroll=True) %} - {%- if not hide_node_func(child_node) %} - {%- if isinstance(child_node, (systemrdlAddrmapNode, systemrdlRegfileNode)) %}self.dut.{{'.'.join(get_python_path_segments(child_node))}}, # type: ignore[union-attr,list-item] {% endif %} - {% endif %} - {% endfor %} ] - sections = [] - for section in self.dut.get_sections(unroll=True): # type: ignore[union-attr] - self.assertIsInstance(section, ({% if asyncoutput %}Async{% endif %}AddressMap, {% if asyncoutput %}Async{% endif %}RegFile)) - sections.append(section) - self.assertCountEqual(expected_sections, sections) - {# check the rolled case second #} - expected_sections = [ {%- for child_node in top_node.children(unroll=False) %} - {%- if not hide_node_func(child_node) %} - {%- if isinstance(child_node, (systemrdlAddrmapNode, systemrdlRegfileNode)) %}self.dut.{{'.'.join(get_python_path_segments(child_node))}}, # type: ignore[union-attr,list-item] {% endif %} - {% endif %} - {% endfor %} ] - sections = [] - for section in self.dut.get_sections(unroll=False): # type: ignore[union-attr] - sections.append(section) - self.assertCountEqual(expected_sections, sections) - - # check the memories - expected_memories = [ {%- for child_node in top_node.children(unroll=True) %} - {%- if not hide_node_func(child_node) %} - {%- if isinstance(child_node, systemrdlMemNode) %}self.dut.{{'.'.join(get_python_path_segments(child_node))}}, # type: ignore[union-attr,list-item] {% endif %} - {% endif %} - {% endfor %} ] - memories = [] - for memory in self.dut.get_memories(unroll=True): # type: ignore[union-attr] - self.assertIsInstance(memory, (Memory{% if asyncoutput %}Async{% endif %}ReadOnly{% if legacy_block_access %}Legacy{% endif %}, Memory{% if asyncoutput %}Async{% endif %}WriteOnly{% if legacy_block_access %}Legacy{% endif %}, Memory{% if asyncoutput %}Async{% endif %}ReadWrite{% if legacy_block_access %}Legacy{% endif %})) - memories.append(memory) - self.assertCountEqual(expected_memories, memories) - {# check the rolled case second #} - expected_memories = [ {%- for child_node in top_node.children(unroll=False) %} - {%- if not hide_node_func(child_node) %} - {%- if isinstance(child_node, systemrdlMemNode) %}self.dut.{{'.'.join(get_python_path_segments(child_node))}}, # type: ignore[union-attr,list-item] {% endif %} - {% endif %} - {% endfor %} ] - memories = [] - for memory in self.dut.get_memories(unroll=False): # type: ignore[union-attr] - self.assertIsInstance(memory, (Memory{% if asyncoutput %}Async{% endif %}ReadOnly{% if legacy_block_access %}Legacy{% endif %}, Memory{% if asyncoutput %}Async{% endif %}WriteOnly{% if legacy_block_access %}Legacy{% endif %}, Memory{% if asyncoutput %}Async{% endif %}ReadWrite{% if legacy_block_access %}Legacy{% endif %}, Memory{% if asyncoutput %}Async{% endif %}ReadOnly{% if legacy_block_access %}Legacy{% endif %}Array, Memory{% if asyncoutput %}Async{% endif %}WriteOnly{% if legacy_block_access %}Legacy{% endif %}Array, Memory{% if asyncoutput %}Async{% endif %}ReadWrite{% if legacy_block_access %}Legacy{% endif %}Array)) - memories.append(memory) - self.assertCountEqual(expected_memories, memories) + self._test_addrmap_iterators(dut=self.dut, + writeable_registers=set([ {%- for child_node in top_node.children(unroll=True) %}{%- if not hide_node_func(child_node) %}{%- if isinstance(child_node, systemrdlRegNode) %}{% if child_node.has_sw_writable %}'{{child_node.get_path_segments()[-1]}}',{% endif %}{% endif %}{% endif %}{% endfor %} ]), + readable_registers=set([ {%- for child_node in top_node.children(unroll=True) %}{%- if not hide_node_func(child_node) %}{%- if isinstance(child_node, systemrdlRegNode) %}{% if child_node.has_sw_readable %}'{{child_node.get_path_segments()[-1]}}',{% endif %}{% endif %}{% endif %}{% endfor %} ]), + sections=set([ {%- for child_node in top_node.children(unroll=True) %}{%- if not hide_node_func(child_node) %}{%- if isinstance(child_node, (systemrdlRegfileNode,systemrdlAddrmapNode)) %}'{{child_node.get_path_segments()[-1]}}',{% endif %}{% endif %}{% endfor %} ]), + memories=set([ {%- for child_node in top_node.children(unroll=True) %}{%- if not hide_node_func(child_node) %}{%- if isinstance(child_node, systemrdlMemNode) %}'{{child_node.get_path_segments()[-1]}}',{% endif %}{% endif %}{% endfor %} ])) {% endif %}{# if block == top_block #} - {% macro check_readable_register_iterators(node) %} - {# check the unrolled case first #} - expected_readable_regs = [ {%- for child_node in node.children(unroll=True) %} - {%- if not hide_node_func(child_node) %} - {%- if isinstance(child_node, systemrdlRegNode) %}{% if child_node.has_sw_readable %}self.dut.{{'.'.join(get_python_path_segments(child_node))}}, # type: ignore[union-attr,list-item] {% endif %}{% endif %} - {% endif %} - {% endfor %} ] - readable_regs = [] - for readable_reg in self.dut.{{'.'.join(get_python_path_segments(node))}}.get_readable_registers(unroll=True): # type: ignore[union-attr] - self.assertIsInstance(readable_reg, (Reg{% if asyncoutput %}Async{% endif %}ReadWrite, Reg{% if asyncoutput %}Async{% endif %}ReadOnly)) - readable_regs.append(readable_reg) - self.assertCountEqual(expected_readable_regs, readable_regs) - {# check the rolled case second #} - expected_readable_regs = [ {%- for child_node in node.children(unroll=False) %} - {%- if not hide_node_func(child_node) %} - {%- if isinstance(child_node, systemrdlRegNode) %}{% if child_node.has_sw_readable %}self.dut.{{'.'.join(get_python_path_segments(child_node))}}, # type: ignore[union-attr,list-item] {% endif %}{% endif %} - {% endif %} - {% endfor %} ] - readable_regs = [] - for readable_reg in self.dut.{{'.'.join(get_python_path_segments(node))}}.get_readable_registers(unroll=False): # type: ignore[union-attr] - self.assertIsInstance(readable_reg, (Reg{% if asyncoutput %}Async{% endif %}ReadWrite, Reg{% if asyncoutput %}Async{% endif %}ReadOnly, Reg{% if asyncoutput %}Async{% endif %}ReadWriteArray, Reg{% if asyncoutput %}Async{% endif %}ReadOnlyArray)) - readable_regs.append(readable_reg) - self.assertCountEqual(expected_readable_regs, readable_regs) - {% endmacro %} - - {% macro check_writable_register_iterators(node) %} - {# check the unrolled case first #} - expected_writable_regs = [ {%- for child_node in node.children(unroll=True) %} - {%- if not hide_node_func(child_node) %} - {%- if isinstance(child_node, systemrdlRegNode) %}{% if child_node.has_sw_writable %}self.dut.{{'.'.join(get_python_path_segments(child_node))}}, # type: ignore[union-attr,list-item] {% endif %}{% endif %} - {% endif %} - {% endfor %} ] - writable_regs = [] - for writable_reg in self.dut.{{'.'.join(get_python_path_segments(node))}}.get_writable_registers(unroll=True): # type: ignore[union-attr] - self.assertIsInstance(writable_reg, (Reg{% if asyncoutput %}Async{% endif %}ReadWrite, Reg{% if asyncoutput %}Async{% endif %}WriteOnly)) - writable_regs.append(writable_reg) - self.assertCountEqual(expected_writable_regs, writable_regs) - {# check the rolled case second #} - expected_writable_regs = [ {%- for child_node in node.children(unroll=False) %} - {%- if not hide_node_func(child_node) %} - {%- if isinstance(child_node, systemrdlRegNode) %}{% if child_node.has_sw_writable %}self.dut.{{'.'.join(get_python_path_segments(child_node))}}, # type: ignore[union-attr,list-item] {% endif %}{% endif %} - {% endif %} - {% endfor %} ] - writable_regs = [] - for writable_reg in self.dut.{{'.'.join(get_python_path_segments(node))}}.get_writable_registers(unroll=False): # type: ignore[union-attr] - self.assertIsInstance(writable_reg, (Reg{% if asyncoutput %}Async{% endif %}ReadWrite, Reg{% if asyncoutput %}Async{% endif %}WriteOnly, Reg{% if asyncoutput %}Async{% endif %}ReadWriteArray, Reg{% if asyncoutput %}Async{% endif %}WriteOnlyArray)) - writable_regs.append(writable_reg) - self.assertCountEqual(expected_writable_regs, writable_regs) - {% endmacro %} - - {% macro check_section_iterators(node) %} - {# check the unrolled case first #} - expected_sections = [ {%- for child_node in node.children(unroll=True) %} - {%- if not hide_node_func(child_node) %} - {%- if isinstance(child_node, (systemrdlAddrmapNode, systemrdlRegfileNode)) %}self.dut.{{'.'.join(get_python_path_segments(child_node))}}, # type: ignore[union-attr,list-item] {% endif %} - {% endif %} - {% endfor %} ] - sections = [] - for section in self.dut.{{'.'.join(get_python_path_segments(node))}}.get_sections(unroll=True): # type: ignore[union-attr] - self.assertIsInstance(section, ({% if asyncoutput %}Async{% endif %}AddressMap, {% if asyncoutput %}Async{% endif %}RegFile)) - sections.append(section) - self.assertCountEqual(expected_sections, sections) - {# check the rolled case second #} - expected_sections = [ {%- for child_node in node.children(unroll=False) %} - {%- if not hide_node_func(child_node) %} - {%- if isinstance(child_node, (systemrdlAddrmapNode, systemrdlRegfileNode)) %}self.dut.{{'.'.join(get_python_path_segments(child_node))}}, # type: ignore[union-attr,list-item] {% endif %} - {% endif %} - {% endfor %} ] - sections = [] - for section in self.dut.{{'.'.join(get_python_path_segments(node))}}.get_sections(unroll=False): # type: ignore[union-attr] - self.assertIsInstance(section, ({% if asyncoutput %}Async{% endif %}AddressMap, {% if asyncoutput %}Async{% endif %}RegFile, {% if asyncoutput %}Async{% endif %}AddressMapArray, {% if asyncoutput %}Async{% endif %}RegFileArray)) - sections.append(section) - self.assertCountEqual(expected_sections, sections) - {% endmacro %} - - {% macro check_memory_iterators(node) %} - {# check the unrolled case first #} - expected_memories = [ {%- for child_node in node.children(unroll=True) %} - {%- if not hide_node_func(child_node) %} - {%- if isinstance(child_node, systemrdlMemNode) %}self.dut.{{'.'.join(get_python_path_segments(child_node))}}, # type: ignore[union-attr,list-item] {% endif %} - {% endif %} - {% endfor %} ] - memories = [] - for memory in self.dut.{{'.'.join(get_python_path_segments(node))}}.get_memories(unroll=True): # type: ignore[union-attr] - self.assertIsInstance(memory, (Memory{% if asyncoutput %}Async{% endif %}ReadOnly{% if legacy_block_access %}Legacy{% endif %}, Memory{% if asyncoutput %}Async{% endif %}WriteOnly{% if legacy_block_access %}Legacy{% endif %}, Memory{% if asyncoutput %}Async{% endif %}ReadWrite{% if legacy_block_access %}Legacy{% endif %})) - memories.append(memory) - self.assertCountEqual(expected_memories, memories) - {# check the rolled case second #} - expected_memories = [ {%- for child_node in node.children(unroll=False) %} - {%- if not hide_node_func(child_node) %} - {%- if isinstance(child_node, systemrdlMemNode) %}self.dut.{{'.'.join(get_python_path_segments(child_node))}}, # type: ignore[union-attr,list-item] {% endif %} - {% endif %} - {% endfor %} ] - memories = [] - for memory in self.dut.{{'.'.join(get_python_path_segments(node))}}.get_memories(unroll=False): # type: ignore[union-attr] - self.assertIsInstance(memory, (Memory{% if asyncoutput %}Async{% endif %}ReadOnly{% if legacy_block_access %}Legacy{% endif %}, Memory{% if asyncoutput %}Async{% endif %}WriteOnly{% if legacy_block_access %}Legacy{% endif %}, Memory{% if asyncoutput %}Async{% endif %}ReadWrite{% if legacy_block_access %}Legacy{% endif %}, Memory{% if asyncoutput %}Async{% endif %}ReadOnly{% if legacy_block_access %}Legacy{% endif %}Array, Memory{% if asyncoutput %}Async{% endif %}WriteOnly{% if legacy_block_access %}Legacy{% endif %}Array, Memory{% if asyncoutput %}Async{% endif %}ReadWrite{% if legacy_block_access %}Legacy{% endif %}Array)) - memories.append(memory) - self.assertCountEqual(expected_memories, memories) - {% endmacro %} - def test_traversal_iterators(self) -> None: """ Walk the address map and check that the iterators for each node as as expected """ - {% if asyncoutput %} - expected_writable_fields: list[Union[FieldAsyncWriteOnly, FieldAsyncReadWrite]] - expected_readable_fields: list[Union[FieldAsyncReadOnly, FieldAsyncReadWrite]] - expected_fields: list[Union[FieldAsyncWriteOnly, FieldAsyncReadOnly, FieldAsyncReadWrite]] - expected_writable_regs: list[WritableAsyncRegister] - expected_readable_regs: list[ReadableAsyncRegister] - expected_memories:list[Union[MemoryAsyncReadOnly{% if legacy_block_access %}Legacy{% endif %}, MemoryAsyncWriteOnly{% if legacy_block_access %}Legacy{% endif %}, MemoryAsyncReadWrite{% if legacy_block_access %}Legacy{% endif %}]] - {% else %} - expected_writable_fields: list[Union[FieldWriteOnly, FieldReadWrite]] - expected_readable_fields: list[Union[FieldReadOnly, FieldReadWrite]] - expected_fields: list[Union[FieldWriteOnly, FieldReadOnly, FieldReadWrite]] - expected_writable_regs: list[WritableRegister] - expected_readable_regs: list[ReadableRegister] - expected_memories:list[Union[MemoryReadOnly{% if legacy_block_access %}Legacy{% endif %}, MemoryWriteOnly{% if legacy_block_access %}Legacy{% endif %}, MemoryReadWrite{% if legacy_block_access %}Legacy{% endif %}]] - {% endif %} - expected_sections : list[Union[{% if asyncoutput %}Async{% endif %}AddressMap, {% if asyncoutput %}Async{% endif %}RegFile]] - # test all the registers - {% for node in owned_elements.registers -%} - with self.subTest(msg='register: {{'.'.join(node.get_path_segments())}}'): - {# a register can only have fields beneath it #} - expected_fields = [ {%- for child_node in node.children(unroll=True) -%} - {% if isinstance(child_node, systemrdlFieldNode) %} - {%- if not hide_node_func(child_node) -%} - self.dut.{{'.'.join(get_python_path_segments(child_node))}}, # type: ignore[union-attr,list-item] - {% endif %} - {% endif %} - {% endfor %} - ] - fields = [] - for field in self.dut.{{'.'.join(get_python_path_segments(node))}}.fields: # type: ignore[union-attr] - fields.append(field) - self.assertCountEqual(expected_fields, fields) - {% if node.has_sw_writable %} - expected_writable_fields = [ {%- for child_node in node.children(unroll=True) -%} - {%- if not hide_node_func(child_node) -%} - {% if isinstance(child_node, systemrdlFieldNode) %}{% if child_node.is_sw_writable %}self.dut.{{'.'.join(get_python_path_segments(child_node))}}, # type: ignore[union-attr,list-item] {% endif %}{% endif %} - {% endif %} - {% endfor %} - ] - writable_fields = [] - for writable_field in self.dut.{{'.'.join(get_python_path_segments(node))}}.writable_fields: # type: ignore[union-attr] - writable_fields.append(writable_field) - self.assertCountEqual(expected_writable_fields, writable_fields) - {% else %} - # register should not have writable_fields attribute - self.assertFalse(hasattr(self.dut.{{'.'.join(get_python_path_segments(node))}}, 'writable_fields')) # type: ignore[union-attr] - {% endif %} - {% if node.has_sw_readable %} - expected_readable_fields = [ {%- for child_node in node.children(unroll=True) -%} - {%- if not hide_node_func(child_node) -%} - {% if isinstance(child_node, systemrdlFieldNode) %}{% if child_node.is_sw_readable %}self.dut.{{'.'.join(get_python_path_segments(child_node))}}, # type: ignore[union-attr,list-item] {% endif %}{% endif %} - {% endif %} - {% endfor %} - ] - readable_fields = [] - for readable_field in self.dut.{{'.'.join(get_python_path_segments(node))}}.readable_fields: # type: ignore[union-attr] - readable_fields.append(readable_field) - self.assertCountEqual(expected_readable_fields, readable_fields) - {% else %} - # register should not have readable_fields attribute - self.assertFalse(hasattr(self.dut.{{'.'.join(get_python_path_segments(node))}}, 'readable_fields')) # type: ignore[union-attr] - {% endif %} - {% endfor %} + # test all the memories {% for node in owned_elements.memories -%} - with self.subTest(msg='memory: {{'.'.join(node.get_path_segments())}}'): - {% if node.is_sw_writable %} - {{ check_writable_register_iterators(node) | indent }} - {% else %} - self.assertFalse(hasattr(self.dut.{{'.'.join(get_python_path_segments(node))}}, 'get_writeable_registers')) # type: ignore[union-attr] - {% endif %} - {% if node.is_sw_readable %} - {{ check_readable_register_iterators(node) | indent}} - {% else %} - self.assertFalse(hasattr(self.dut.{{'.'.join(get_python_path_segments(node))}}, 'get_readable_registers')) # type: ignore[union-attr] - {% endif %} + self._test_register_iterators(dut=self.dut.{{'.'.join(get_python_path_segments(node))}}, + writeable_registers=set([ {%- for child_node in node.children(unroll=True) %}{%- if not hide_node_func(child_node) %}{%- if isinstance(child_node, systemrdlRegNode) %}{% if child_node.has_sw_writable %}'{{child_node.get_path_segments()[-1]}}',{% endif %}{% endif %}{% endif %}{% endfor %} ]), + readable_registers=set([ {%- for child_node in node.children(unroll=True) %}{%- if not hide_node_func(child_node) %}{%- if isinstance(child_node, systemrdlRegNode) %}{% if child_node.has_sw_readable %}'{{child_node.get_path_segments()[-1]}}',{% endif %}{% endif %}{% endif %}{% endfor %} ])) {% endfor %} # test all the address maps {% for node in owned_elements.addr_maps -%} with self.subTest(msg='addrmap: {{'.'.join(node.get_path_segments())}}'): - {{ check_readable_register_iterators(node) | indent }} - {{ check_writable_register_iterators(node) | indent}} - {{ check_section_iterators(node) | indent }} - {{ check_memory_iterators(node) | indent}} + self._test_addrmap_iterators(dut=self.dut.{{'.'.join(get_python_path_segments(node))}}, + writeable_registers=set([ {%- for child_node in node.children(unroll=True) %}{%- if not hide_node_func(child_node) %}{%- if isinstance(child_node, systemrdlRegNode) %}{% if child_node.has_sw_writable %}'{{child_node.get_path_segments()[-1]}}',{% endif %}{% endif %}{% endif %}{% endfor %} ]), + readable_registers=set([ {%- for child_node in node.children(unroll=True) %}{%- if not hide_node_func(child_node) %}{%- if isinstance(child_node, systemrdlRegNode) %}{% if child_node.has_sw_readable %}'{{child_node.get_path_segments()[-1]}}',{% endif %}{% endif %}{% endif %}{% endfor %} ]), + sections=set([ {%- for child_node in node.children(unroll=True) %}{%- if not hide_node_func(child_node) %}{%- if isinstance(child_node, (systemrdlRegfileNode,systemrdlAddrmapNode)) %}'{{child_node.get_path_segments()[-1]}}',{% endif %}{% endif %}{% endfor %} ]), + memories=set([ {%- for child_node in node.children(unroll=True) %}{%- if not hide_node_func(child_node) %}{%- if isinstance(child_node, systemrdlMemNode) %}'{{child_node.get_path_segments()[-1]}}',{% endif %}{% endif %}{% endfor %} ])) {% endfor %} # test all the register files {% for node in owned_elements.reg_files -%} with self.subTest(msg='regfile: {{'.'.join(node.get_path_segments())}}'): - {{ check_readable_register_iterators(node) | indent }} - {{ check_writable_register_iterators(node) | indent}} - {{ check_section_iterators(node) | indent }} - self.assertFalse(hasattr(self.dut.{{'.'.join(get_python_path_segments(node))}}, 'get_memories')) # type: ignore[union-attr] + self._test_regfile_iterators(dut=self.dut.{{'.'.join(get_python_path_segments(node))}}, + writeable_registers=set([ {%- for child_node in node.children(unroll=True) %}{%- if not hide_node_func(child_node) %}{%- if isinstance(child_node, systemrdlRegNode) %}{% if child_node.has_sw_writable %}'{{child_node.get_path_segments()[-1]}}',{% endif %}{% endif %}{% endif %}{% endfor %} ]), + readable_registers=set([ {%- for child_node in node.children(unroll=True) %}{%- if not hide_node_func(child_node) %}{%- if isinstance(child_node, systemrdlRegNode) %}{% if child_node.has_sw_readable %}'{{child_node.get_path_segments()[-1]}}',{% endif %}{% endif %}{% endif %}{% endfor %} ]), + sections=set([ {%- for child_node in node.children(unroll=True) %}{%- if not hide_node_func(child_node) %}{%- if isinstance(child_node, (systemrdlRegfileNode,systemrdlAddrmapNode)) %}'{{child_node.get_path_segments()[-1]}}',{% endif %}{% endif %}{% endfor %} ])) {% endfor %} def test_name_map(self) -> None: diff --git a/tests/testcases/memories_with_registers.rdl b/tests/testcases/memories_with_registers.rdl index b51bc118..91ad59f9 100644 --- a/tests/testcases/memories_with_registers.rdl +++ b/tests/testcases/memories_with_registers.rdl @@ -6,11 +6,39 @@ addrmap memories_with_registers { sw=rw; reg mem_entry_definition { - field {} lower_entry[15:0]; + field { sw=rw;} lower_entry[15:0]; }; mem_entry_definition mem_entry_set1; mem_entry_definition mem_entry_set2[4]; } mem_with_internal_registers; + + external mem { + mementries = 16; + memwidth = 32; + sw=r; + + reg mem_entry_definition { + field {sw=r;} lower_entry[15:0]; + }; + + mem_entry_definition mem_entry_set1; + mem_entry_definition mem_entry_set2[4]; + + } mem_with_internal_registers_read_only; + + external mem { + mementries = 16; + memwidth = 32; + sw=w; + + reg mem_entry_definition { + field {sw=w;} lower_entry[15:0]; + }; + + mem_entry_definition mem_entry_set1; + mem_entry_definition mem_entry_set2[4]; + + } mem_with_internal_registers_write_only; }; \ No newline at end of file