Fix alias bugs introduced when adding external registers

Furthermore, some compilation bugs were added when optimizing away swacc
and swmod wires when not required.
This commit is contained in:
Dennis Potter 2021-11-06 22:45:34 -07:00
parent c589a17ea5
commit 0887372dbd
Signed by: Dennis
GPG Key ID: 186A8AD440942BAF
4 changed files with 88 additions and 29 deletions

View File

@ -68,6 +68,7 @@ class Field(Component):
elif self.storage_type is not StorageType.FLOPS:
self.__add_wire_const()
self.__add_hw_rd_access()
self.__add_swmod_swacc()
self.add_sw_access(obj)
else:
self.__add_always_ff()
@ -84,17 +85,37 @@ class Field(Component):
self.add_sw_access(obj)
def add_sw_access(self, obj, alias = False):
# Perform some basic checks
if onwrite := obj.get_property('onwrite') \
and not self.properties['sw_wr']:
self.logger.fatal("An onwrite property '%s' is defined but "\
"software does not have write-access. This is not "\
"legal.", onwrite)
sys.exit(1)
elif onread := obj.get_property('onread') \
and self.storage_type is not StorageType.FLOPS:
self.logger.warning("Field has an onread property but does not "
"implement a flop. Since the flop itself is "
"implemented outside of the register block it is "
"advised to remove the property and notify the external "
"hardware by using the 'swacc' property.")
access_rtl = {}
if alias:
_, _, path, path_underscored =\
_, _, path, alias_path_underscored = \
Field.create_underscored_path_static(obj)
else:
owning_addrmap, full_path, path, path_underscored =\
self.owning_addrmap, self.full_path, self.path, self.path_underscored
path = self.path
path_wo_field = '__'.join(path.split('.', -1)[0:-1])
# path_wo_field_vec & path_undrescored_vec only used for external registers
self.path_wo_field_vec.append(path_wo_field)
self.path_underscored_vec.append(alias_path_underscored if alias else self.path_underscored)
# Define software access (if applicable)
access_rtl['sw_write'] = ([], False)
@ -151,7 +172,7 @@ class Field(Component):
access_rtl['sw_write'][0].append(
self._process_yaml(
Field.templ_dict[str(onwrite)],
{'path': path_underscored,
{'path': self.path_underscored,
'genvars': self.genvars_str,
'i': i,
'width': msb_bus - lsb_bus + 1,
@ -186,19 +207,18 @@ class Field(Component):
access_rtl['sw_write'][0].append("end")
onread = obj.get_property('onread')
access_rtl['sw_read'] = ([], False)
if obj.get_property('sw') in (AccessType.rw, AccessType.r):
# Append to list of registers that can read
self.readable_by.add(path_wo_field)
self.properties['sw_wr'] = True
self.properties['sw_rd'] = True
# Set onread properties
if onread == OnReadType.ruser:
if onread is OnReadType.ruser:
self.logger.error("The OnReadType.ruser is not yet supported!")
elif onread:
elif onread and self.storage_type is StorageType.FLOPS:
self.properties['sw_rd_wire'] = True
access_rtl['sw_read'][0].append(
@ -215,7 +235,7 @@ class Field(Component):
access_rtl['sw_read'][0].append(
self._process_yaml(
Field.templ_dict[str(onread)],
{'path': path_underscored,
{'path': self.path_underscored,
'genvars': self.genvars_str,
'i': i,
'width': msb_bus - lsb_bus + 1,
@ -252,9 +272,6 @@ class Field(Component):
self.access_rtl['sw_read'] = [access_rtl['sw_read']]
self.access_rtl['sw_write'] = [access_rtl['sw_write']]
self.path_underscored_vec.append(path_underscored)
self.path_wo_field_vec.append(path_wo_field)
def __add_counter(self):
if self.obj.get_property('counter'):
self.logger.debug("Detected counter property")
@ -683,6 +700,9 @@ class Field(Component):
if self.obj.get_property('swmod'):
self.logger.debug("Field has swmod property")
self.properties['swmod'] = True
self.properties['sw_wr_wire'] = True
swmod_assigns = []
# Check if read side-effects are defined.
@ -1379,7 +1399,9 @@ class Field(Component):
sw_prop = self.obj.get_property('sw')
# Check the storage type, according to Table 12 of the SystemRDL 2.0 LRM
if hw_prop is AccessType.r and sw_prop is AccessType.r:
if self.obj.get_property('intr'):
self.storage_type = StorageType.FLOPS
elif hw_prop is AccessType.r and sw_prop is AccessType.r:
# hw=r/sw=r --> Constant
self.storage_type = StorageType.CONST
elif hw_prop is AccessType.na and sw_prop is AccessType.r:

View File

@ -152,7 +152,7 @@ class Register(Component):
accesswidth = self.obj.get_property('accesswidth') - 1
self.rtl_footer.append("")
for na_map in self.name_addr_mappings:
for alias_idx, na_map in enumerate(self.name_addr_mappings):
current_bit = 0
# Start tracking errors
@ -352,6 +352,7 @@ class Register(Component):
'genvars': self.genvars_str if not no_reads else '',
'rdy_condition': sw_rdy_condition,
'err_condition': sw_err_condition,
'alias_indicator': '(alias)' if alias_idx > 0 else '',
'list_of_fields': ', '.join(reversed(list_of_fields))}
)
)
@ -471,18 +472,28 @@ class Register(Component):
)
# Add combined signal to be used for general access of the register
if self.properties['swacc'] or self.properties['swmod']:
self.rtl_header.append(
self._process_yaml(
Register.templ_dict['w_wire_assign_any_alias'],
{'path': self.name_addr_mappings[0][0],
'genvars': self.genvars_str,
'sw_wrs_w_genvars': ' || '.join(
[''.join([x[0], '_sw_wr', self.genvars_str])
for x in self.name_addr_mappings])
}
)
)
if self.properties['swacc']:
self.rtl_header.append(
self._process_yaml(
Register.templ_dict['rw_wire_assign_any_alias'],
Register.templ_dict['r_wire_assign_any_alias'],
{'path': self.name_addr_mappings[0][0],
'genvars': self.genvars_str,
'sw_rds_w_genvars': ' || '.join(
[''.join([x[0], '_sw_rd', self.genvars_str])
for x in self.name_addr_mappings]),
'sw_wrs_w_genvars': ' || '.join(
[''.join([x[0], '_sw_wr', self.genvars_str])
for x in self.name_addr_mappings])
}
)
)

View File

@ -136,42 +136,63 @@ OnWriteType.woset:
<<INDENT>>
{path}_q{genvars}[{msb_field}:{lsb_field}] <= {path}_q{genvars}[{msb_field}:{lsb_field}] | widget_if.w_data[{msb_bus}:{lsb_bus}];
<<UNINDENT>>
signals:
- name: '{path}_q'
signal_type: '{field_type}'
OnWriteType.woclr:
rtl: |-
if (widget_if.byte_en[{i}]) // woclr property
<<INDENT>>
{path}_q{genvars}[{msb_field}:{lsb_field}] <= {path}_q{genvars}[{msb_field}:{lsb_field}] & ~widget_if.w_data[{msb_bus}:{lsb_bus}];
<<UNINDENT>>
signals:
- name: '{path}_q'
signal_type: '{field_type}'
OnWriteType.wot:
rtl: |-
if (widget_if.byte_en[{i}]) // wot property
<<INDENT>>
{path}_q{genvars}[{msb_field}:{lsb_field}] <= {path}_q{genvars}[{msb_field}:{lsb_field}] ^ widget_if.w_data[{msb_bus}:{lsb_bus}];
<<UNINDENT>>
signals:
- name: '{path}_q'
signal_type: '{field_type}'
OnWriteType.wzs:
rtl: |-
if (widget_if.byte_en[{i}]) // wzs property
<<INDENT>>
{path}_q{genvars}[{msb_field}:{lsb_field}] <= {path}_q{genvars}[{msb_field}:{lsb_field}] & widget_if.w_data[{msb_bus}:{lsb_bus}];
<<UNINDENT>>
signals:
- name: '{path}_q'
signal_type: '{field_type}'
OnWriteType.wzt:
rtl: |-
if (widget_if.byte_en[{i}]) // wzt property
<<INDENT>>
{path}_q{genvars}[{msb_field}:{lsb_field}] <= {path}_q{genvars}[{msb_field}:{lsb_field}] ~^ widget_if.w_data[{msb_bus}:{lsb_bus}];
<<UNINDENT>>
signals:
- name: '{path}_q'
signal_type: '{field_type}'
OnWriteType.wclr:
rtl: |-
if (widget_if.byte_en[{i}]) // wclr property
<<INDENT>>
{path}_q{genvars}[{msb_field}:{lsb_field}] <= {width}'b0;
<<UNINDENT>>
signals:
- name: '{path}_q'
signal_type: '{field_type}'
OnWriteType.wset:
rtl: |-
if (widget_if.byte_en[{i}]) // wclr property
<<INDENT>>
{path}_q{genvars}[{msb_field}:{lsb_field}] <= {{{width}{{1'b1}}}};
<<UNINDENT>>
signals:
- name: '{path}_q'
signal_type: '{field_type}'
sw_read_access_field:
rtl: |-
if ({path_wo_field}_sw_rd{genvars})
@ -260,13 +281,13 @@ swmod_always_comb:
end
output_ports:
- name: '{path}_swmod'
signal_type: 'logic'
signal_type: 'reg'
swmod_assign:
rtl: |-
{path}_swmod{genvars} |= {path_wo_field}__any_alias_sw_{rd_wr}{genvars} && |widget_if.byte_en[{msbyte}:{lsbyte}];
output_ports:
- name: '{path}_swmod'
signal_type: 'logic'
signal_type: 'reg'
counter_comment:
rtl: |-
/***********************

View File

@ -39,17 +39,22 @@ write_wire_assign_0:
signals:
- name: '{path}_sw_wr'
signal_type: 'logic'
rw_wire_assign_any_alias:
w_wire_assign_any_alias:
rtl: |-
// Combined register activation. These will become active
assign {path}__any_alias_sw_rd{genvars} = {sw_rds_w_genvars};
// Combined register activation. These will become active on
// access via any of the alias registers.
assign {path}__any_alias_sw_wr{genvars} = {sw_wrs_w_genvars};
signals:
- name: '{path}__any_alias_sw_rd'
signal_type: 'logic'
- name: '{path}__any_alias_sw_wr'
signal_type: 'logic'
r_wire_assign_any_alias:
rtl: |-
assign {path}__any_alias_sw_rd{genvars} = {sw_rds_w_genvars};
signals:
- name: '{path}__any_alias_sw_rd'
signal_type: 'logic'
reg_comment: |-
/*******************************************************************
@ -96,9 +101,9 @@ sw_err_condition:
sw_data_assignment:
rtl: |-
/**************************************
* Assign all fields to signal to Mux *
**************************************/
/**********************************************
* Assign all fields to signal to Mux {alias_indicator:7} *
**********************************************/
// Assign all fields. Fields that are not readable are tied to 0.
assign {sw_data_assignment_var_name}{genvars} = {{{list_of_fields}}};