diff --git a/srdl2sv/components/field.py b/srdl2sv/components/field.py index 05b7911..81aeb67 100644 --- a/srdl2sv/components/field.py +++ b/srdl2sv/components/field.py @@ -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: diff --git a/srdl2sv/components/register.py b/srdl2sv/components/register.py index 17cdb23..d280545 100644 --- a/srdl2sv/components/register.py +++ b/srdl2sv/components/register.py @@ -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]) } ) ) diff --git a/srdl2sv/components/templates/fields.yaml b/srdl2sv/components/templates/fields.yaml index 90305a0..a3ab2aa 100644 --- a/srdl2sv/components/templates/fields.yaml +++ b/srdl2sv/components/templates/fields.yaml @@ -136,42 +136,63 @@ OnWriteType.woset: <> {path}_q{genvars}[{msb_field}:{lsb_field}] <= {path}_q{genvars}[{msb_field}:{lsb_field}] | widget_if.w_data[{msb_bus}:{lsb_bus}]; <> + signals: + - name: '{path}_q' + signal_type: '{field_type}' OnWriteType.woclr: rtl: |- if (widget_if.byte_en[{i}]) // woclr property <> {path}_q{genvars}[{msb_field}:{lsb_field}] <= {path}_q{genvars}[{msb_field}:{lsb_field}] & ~widget_if.w_data[{msb_bus}:{lsb_bus}]; <> + signals: + - name: '{path}_q' + signal_type: '{field_type}' OnWriteType.wot: rtl: |- if (widget_if.byte_en[{i}]) // wot property <> {path}_q{genvars}[{msb_field}:{lsb_field}] <= {path}_q{genvars}[{msb_field}:{lsb_field}] ^ widget_if.w_data[{msb_bus}:{lsb_bus}]; <> + signals: + - name: '{path}_q' + signal_type: '{field_type}' OnWriteType.wzs: rtl: |- if (widget_if.byte_en[{i}]) // wzs property <> {path}_q{genvars}[{msb_field}:{lsb_field}] <= {path}_q{genvars}[{msb_field}:{lsb_field}] & widget_if.w_data[{msb_bus}:{lsb_bus}]; <> + signals: + - name: '{path}_q' + signal_type: '{field_type}' OnWriteType.wzt: rtl: |- if (widget_if.byte_en[{i}]) // wzt property <> {path}_q{genvars}[{msb_field}:{lsb_field}] <= {path}_q{genvars}[{msb_field}:{lsb_field}] ~^ widget_if.w_data[{msb_bus}:{lsb_bus}]; <> + signals: + - name: '{path}_q' + signal_type: '{field_type}' OnWriteType.wclr: rtl: |- if (widget_if.byte_en[{i}]) // wclr property <> {path}_q{genvars}[{msb_field}:{lsb_field}] <= {width}'b0; <> + signals: + - name: '{path}_q' + signal_type: '{field_type}' OnWriteType.wset: rtl: |- if (widget_if.byte_en[{i}]) // wclr property <> {path}_q{genvars}[{msb_field}:{lsb_field}] <= {{{width}{{1'b1}}}}; <> + 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: |- /*********************** diff --git a/srdl2sv/components/templates/register.yaml b/srdl2sv/components/templates/register.yaml index b744778..25af430 100644 --- a/srdl2sv/components/templates/register.yaml +++ b/srdl2sv/components/templates/register.yaml @@ -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}}};