Skip to content

Commit

Permalink
Uniquify fields with name collisions on import
Browse files Browse the repository at this point in the history
  • Loading branch information
amykyta3 committed Aug 31, 2023
1 parent 154a562 commit 384bc41
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 7 deletions.
3 changes: 3 additions & 0 deletions docs/importer.rst
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,9 @@ may be performed:
* IP-XACT allows registers to be any arbitrary bit width, but SystemRDL requires
the ``regwidth`` property to be at least 8, and a power of 2.
The imported ``regwidth`` may be padded up as necessary.
* IP-XACT allows a register to contain multiple fields with the same name. If
this is detected, the importer will uniquify the instance names based on the
fields' bit ranges.



Expand Down
2 changes: 1 addition & 1 deletion src/peakrdl_ipxact/__about__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "3.4.2"
__version__ = "3.4.3"
40 changes: 34 additions & 6 deletions src/peakrdl_ipxact/importer.py
Original file line number Diff line number Diff line change
Expand Up @@ -502,20 +502,41 @@ def parse_register(self, register: ElementTree.Element) -> Optional[comp.Reg]:
reg_reset_value = d.get('reset.value', None)
reg_reset_mask = d.get('reset.mask', None)

# collect children
# Collect field elements and scan for name collisions
field_tuples = []
field_names = set()
field_name_collisions = set()
for child_el in d['child_els']:
local_name = get_local_name(child_el)
if local_name == "field":
field = self.parse_field(child_el, reg_access, reg_reset_value, reg_reset_mask)
if field is not None:
self.add_child(C, field)
# This XML element is a field
field_name = self.get_sanitized_element_name(child_el)
field_tuples.append((field_name, child_el))
if field_name in field_names:
field_name_collisions.add(field_name)
else:
field_names.add(field_name)
else:
self.msg.error(
"Invalid child element <%s> found in <%s:register>"
% (child_el.tag, self.ns),
self.src_ref
)

# Process fields
for field_name, field_el in field_tuples:
# Uniquify field name if necessary
uniquify_field_name = field_name in field_name_collisions

field = self.parse_field(
field_name, field_el,
reg_access, reg_reset_value, reg_reset_mask,
uniquify_field_name
)
if field is not None:
self.add_child(C, field)


if 'vendorExtensions' in d:
C = self.register_vendorExtensions(d['vendorExtensions'], C)

Expand All @@ -531,7 +552,12 @@ def parse_register(self, register: ElementTree.Element) -> Optional[comp.Reg]:
return C


def parse_field(self, field: ElementTree.Element, reg_access: rdltypes.AccessType, reg_reset_value: Optional[int], reg_reset_mask: Optional[int]) -> Optional[comp.Field]:
def parse_field(
self,
name: str, field: ElementTree.Element,
reg_access: rdltypes.AccessType, reg_reset_value: Optional[int], reg_reset_mask: Optional[int],
uniquify_field_name: bool,
) -> Optional[comp.Field]:
"""
Parses an field and returns an instantiated field component
"""
Expand Down Expand Up @@ -565,7 +591,6 @@ def parse_field(self, field: ElementTree.Element, reg_access: rdltypes.AccessTyp
# vendorExtensions

d = self.flatten_element_values(field)
name = self.get_sanitized_element_name(field)

# Check for required values
required = {'bitOffset', 'bitWidth'}
Expand All @@ -579,6 +604,9 @@ def parse_field(self, field: ElementTree.Element, reg_access: rdltypes.AccessTyp
if d.get('reserved', False):
return None

if uniquify_field_name:
name += "_%d_%d" % (d['bitOffset'] + d['bitWidth'] - 1, d['bitOffset'])

# Create component instance
C = self.instantiate_field(
self.create_field_definition(),
Expand Down

0 comments on commit 384bc41

Please sign in to comment.