Skip to content

Commit d443a6c

Browse files
authored
Merge pull request #203 from krcb197/202-shared-address-registers-do-not-get-simulated-correctly
shared address registers do not get simulated correctly
2 parents 89158ca + 09a2661 commit d443a6c

5 files changed

Lines changed: 115 additions & 25 deletions

File tree

src/peakrdl_python/__about__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,4 @@
1717
1818
Variables that describes the peakrdl-python Package
1919
"""
20-
__version__ = "1.2.1rc4"
20+
__version__ = "1.3.0"

src/peakrdl_python/exporter.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,15 +382,39 @@ def __export_simulator(self, *,
382382
asyncoutput: bool,
383383
legacy_block_access: bool) -> None:
384384

385+
# as a result of issue 202, where two registers existed at that same address,
386+
# rather than iterating through the registers within the Jinja template
387+
# we iterate through them in in advance so that cases of two registers at that same
388+
# address can be identified
389+
reg_dict:dict[int, Union[list[RegNode],RegNode]] = {}
390+
for node in filter(lambda x : isinstance(x, RegNode), top_block.descendants(unroll=True)):
391+
if not isinstance(node, RegNode):
392+
raise TypeError(f'node should be a register, got {type(node)}')
393+
reg_addr = node.absolute_address
394+
if reg_addr in reg_dict:
395+
existing_entry = reg_dict[reg_addr]
396+
# if the entry is already list simply append to it
397+
if isinstance(existing_entry, list):
398+
existing_entry.append(node)
399+
elif isinstance(existing_entry, RegNode):
400+
reg_dict[reg_addr] = [existing_entry, node]
401+
else:
402+
raise TypeError(f'exiting entry of unexpected type: {type(existing_entry)}')
403+
else:
404+
reg_dict[reg_addr] = node
405+
406+
385407
context = {
386408
'top_node': top_block,
409+
'reg_dict': reg_dict,
387410
'systemrdlRegNode': RegNode,
388411
'systemrdlMemNode': MemNode,
389412
'isinstance': isinstance,
390413
'asyncoutput': asyncoutput,
391414
'skip_lib_copy': skip_lib_copy,
392415
'version': __version__,
393416
'legacy_block_access': legacy_block_access,
417+
'list': list
394418
}
395419

396420
context.update(self.user_template_context)

src/peakrdl_python/sim_lib/simulator.py

Lines changed: 52 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,11 @@ def __init__(self, address: int):
8181
self.address = address
8282

8383
@abstractmethod
84-
def _build_registers(self) -> dict[int, Union[MemoryRegister, Register]]:
84+
def _build_registers(self) -> dict[int, Union[list[Union[MemoryRegister, Register]],
85+
Union[MemoryRegister, Register]]]:
8586
"""
86-
populate the register structure, this method is intended to written by the generated code
87-
based on then design
87+
populate the register structure, this method is intended to implemented by the generated
88+
code based on then design
8889
"""
8990

9091
@abstractmethod
@@ -145,7 +146,15 @@ def _read(self, addr: int,
145146
# see if the address is a register first this ensures that registers in memories are
146147
# accessed directly
147148
if addr in self._registers:
148-
return self._registers[addr].read()
149+
addr_entry = self._registers[addr]
150+
if isinstance(addr_entry, list):
151+
# search the list for a readable register
152+
for inner_reg in addr_entry:
153+
# pylint: disable-next=protected-access
154+
if inner_reg._readable:
155+
return inner_reg.read()
156+
else:
157+
return addr_entry.read()
149158

150159
potential_memory = self.memory_for_address(address=addr)
151160
if potential_memory is not None:
@@ -164,7 +173,14 @@ def _write(self, addr: int,
164173
# see if the address is a register first this ensures that registers in memories are
165174
# accessed directly
166175
if addr in self._registers:
167-
self._registers[addr].write(data)
176+
addr_entry = self._registers[addr]
177+
if isinstance(addr_entry, list):
178+
for inner_reg in addr_entry:
179+
# pylint: disable-next=protected-access
180+
if inner_reg._writable:
181+
inner_reg.write(data)
182+
else:
183+
addr_entry.write(data)
168184
else:
169185
potential_memory = self.memory_for_address(address=addr)
170186
if potential_memory is not None:
@@ -244,8 +260,13 @@ def register_by_full_name(self, name: str) -> Union[MemoryRegister, Register]:
244260
245261
"""
246262
for reg in self._registers.values():
247-
if reg.full_inst_name == name:
248-
return reg
263+
if isinstance(reg, list):
264+
for reg_list_entry in reg:
265+
if reg_list_entry.full_inst_name == name:
266+
return reg_list_entry
267+
else:
268+
if reg.full_inst_name == name:
269+
return reg
249270

250271
raise ValueError(f'register name not matched: {name}')
251272

@@ -260,9 +281,15 @@ def field_by_full_name(self, name: str) -> Field:
260281
261282
"""
262283
for reg in self._registers.values():
263-
for field in reg.fields:
264-
if field.full_inst_name == name:
265-
return field
284+
if isinstance(reg, list):
285+
for reg_list_entry in reg:
286+
for field in reg_list_entry.fields:
287+
if field.full_inst_name == name:
288+
return field
289+
else:
290+
for field in reg.fields:
291+
if field.full_inst_name == name:
292+
return field
266293

267294
raise ValueError(f'field name not matched: {name}')
268295

@@ -282,12 +309,21 @@ def node_by_full_name(self, name: str) -> Union[Memory, MemoryRegister, Register
282309
return mem.memory
283310

284311
for reg in self._registers.values():
285-
if reg.full_inst_name == name:
286-
return reg
287-
288-
for field in reg.fields:
289-
if field.full_inst_name == name:
290-
return field
312+
if isinstance(reg, list):
313+
for reg_list_entry in reg:
314+
if reg_list_entry.full_inst_name == name:
315+
return reg_list_entry
316+
317+
for field in reg_list_entry.fields:
318+
if field.full_inst_name == name:
319+
return field
320+
else:
321+
if reg.full_inst_name == name:
322+
return reg
323+
324+
for field in reg.fields:
325+
if field.full_inst_name == name:
326+
return field
291327

292328
raise ValueError(f'node name not matched: {name}')
293329

src/peakrdl_python/templates/sim_addrmap.py.jinja

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,18 +30,24 @@ from {% if skip_lib_copy %}peakrdl_python.{% else %}..{% endif %}sim_lib.simulat
3030
from {% if skip_lib_copy %}peakrdl_python.{% else %}..{% endif %}sim_lib.simulator import Simulator{% if legacy_block_access %}Legacy{% endif %}
3131
{%- endif %}
3232

33-
class {{top_node.inst_name}}_simulator_cls(Simulator{% if legacy_block_access %}Legacy{% endif %}):
34-
35-
def _build_registers(self) -> dict[int, Union[MemoryRegister, Register]]:
36-
return {
37-
{%- for node in top_node.descendants(unroll=True) -%}
38-
{% if isinstance(node, systemrdlRegNode) %}
39-
{{node.absolute_address}} : {% if isinstance(node.parent, systemrdlMemNode) %}MemoryRegister(memory=self.memory_for_address_with_exception({{node.absolute_address}}).memory,memory_address_offset={{node.address_offset}},{% else %}Register({% endif %}width={{node.size*8}}, full_inst_name='{{'.'.join(node.get_path_segments())}}', readable={{node.has_sw_readable}}, writable={{node.has_sw_writable}},
33+
{%- macro single_reg_entry(node) %}
34+
{% if isinstance(node.parent, systemrdlMemNode) %}MemoryRegister(memory=self.memory_for_address_with_exception({{node.absolute_address}}).memory,memory_address_offset={{node.address_offset}},{% else %}Register({% endif %}width={{node.size*8}}, full_inst_name='{{'.'.join(node.get_path_segments())}}', readable={{node.has_sw_readable}}, writable={{node.has_sw_writable}},
4035
fields=[
4136
{%- for field in node.fields() -%}
4237
FieldDefinition(high={{field.high}}, low={{field.low}}, msb={{field.msb}}, lsb={{field.lsb}}, inst_name='{{field.inst_name}}'),
4338
{%- endfor %}
44-
]),
39+
])
40+
{%- endmacro %}
41+
42+
class {{top_node.inst_name}}_simulator_cls(Simulator{% if legacy_block_access %}Legacy{% endif %}):
43+
44+
def _build_registers(self) -> dict[int, Union[list[Union[MemoryRegister, Register]], Union[MemoryRegister, Register]]]:
45+
return {
46+
{%- for addr, addr_entry in reg_dict.items() -%}
47+
{% if isinstance(addr_entry, list) %}
48+
{{addr}} : [{% for node in addr_entry %}{{single_reg_entry(node)}},{% endfor %}],
49+
{% else %}
50+
{{addr}} : {{single_reg_entry(addr_entry)}},
4551
{%- endif %}
4652
{%- endfor %}
4753
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
addrmap shared_register_issue_202 {
2+
3+
reg {
4+
field { fieldwidth=1; sw=rw; } enable;
5+
} control ;
6+
7+
reg {
8+
field { fieldwidth=16; sw=w; hw=r; } data;
9+
} tx @ 4;
10+
11+
reg {
12+
field { fieldwidth=16; sw=r; hw=w; } data;
13+
} rx @ 4;
14+
15+
reg {
16+
field { fieldwidth=8; sw=r; hw=w; } count;
17+
} rx_fifo_fill;
18+
19+
reg {
20+
field { fieldwidth=8; sw=r; hw=w; } count;
21+
} tx_fifo_fill;
22+
23+
};
24+

0 commit comments

Comments
 (0)