mirror of
https://github.com/Silicon1602/srdl2sv.git
synced 2024-11-14 11:03:36 +00:00
Ensure that sw_rd/sw_wr wires are only generated if they are required
This commit is contained in:
parent
8756945a6d
commit
dc37c87944
@ -40,8 +40,16 @@ class Component():
|
|||||||
self.config = config.copy()
|
self.config = config.copy()
|
||||||
|
|
||||||
# By default, registers and fields are not interrupt registers
|
# By default, registers and fields are not interrupt registers
|
||||||
self.intr = False
|
self.properties = {
|
||||||
self.halt = False
|
'intr': False,
|
||||||
|
'halt': False,
|
||||||
|
'swmod': False,
|
||||||
|
'swacc': False,
|
||||||
|
'sw_rd': False,
|
||||||
|
'sw_wr': False,
|
||||||
|
'sw_rd_wire': False,
|
||||||
|
'sw_wr_wire': False,
|
||||||
|
}
|
||||||
|
|
||||||
# Create logger object
|
# Create logger object
|
||||||
self.create_logger("{}".format(self.full_path), config)
|
self.create_logger("{}".format(self.full_path), config)
|
||||||
|
@ -76,6 +76,10 @@ class Field(Component):
|
|||||||
# Append to list of registers that can write
|
# Append to list of registers that can write
|
||||||
self.writable_by.add(path_wo_field)
|
self.writable_by.add(path_wo_field)
|
||||||
|
|
||||||
|
# This will need a wire to indicate that a write is taking place
|
||||||
|
self.properties['sw_wr_wire'] = True
|
||||||
|
self.properties['sw_wr'] = True
|
||||||
|
|
||||||
swwe = obj.get_property('swwe')
|
swwe = obj.get_property('swwe')
|
||||||
swwel = obj.get_property('swwel')
|
swwel = obj.get_property('swwel')
|
||||||
|
|
||||||
@ -114,7 +118,7 @@ class Field(Component):
|
|||||||
|
|
||||||
if onwrite:
|
if onwrite:
|
||||||
if onwrite == OnWriteType.wuser:
|
if onwrite == OnWriteType.wuser:
|
||||||
self.logger.warning("The OnReadType.wuser is not yet supported!")
|
self.logger.warning("The OnWriteType.wuser is not yet supported!")
|
||||||
elif onwrite in (OnWriteType.wclr, OnWriteType.wset):
|
elif onwrite in (OnWriteType.wclr, OnWriteType.wset):
|
||||||
access_rtl['sw_write'][0].append(
|
access_rtl['sw_write'][0].append(
|
||||||
self.process_yaml(
|
self.process_yaml(
|
||||||
@ -177,10 +181,14 @@ class Field(Component):
|
|||||||
# Append to list of registers that can read
|
# Append to list of registers that can read
|
||||||
self.readable_by.add(path_wo_field)
|
self.readable_by.add(path_wo_field)
|
||||||
|
|
||||||
|
self.properties['sw_wr'] = True
|
||||||
|
|
||||||
# Set onread properties
|
# Set onread properties
|
||||||
if onread == OnReadType.ruser:
|
if onread == OnReadType.ruser:
|
||||||
self.logger.error("The OnReadType.ruser is not yet supported!")
|
self.logger.error("The OnReadType.ruser is not yet supported!")
|
||||||
elif onread:
|
elif onread:
|
||||||
|
self.properties['sw_rd_wire'] = True
|
||||||
|
|
||||||
access_rtl['sw_read'][0].append(
|
access_rtl['sw_read'][0].append(
|
||||||
self.process_yaml(
|
self.process_yaml(
|
||||||
Field.templ_dict[str(onread)],
|
Field.templ_dict[str(onread)],
|
||||||
@ -636,7 +644,7 @@ class Field(Component):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Check if SW has write access to the field
|
# Check if SW has write access to the field
|
||||||
if self.obj.get_property('sw') in (AccessType.rw, AccessType.w):
|
if self.properties['sw_wr']:
|
||||||
swmod_assigns.append(
|
swmod_assigns.append(
|
||||||
self.process_yaml(
|
self.process_yaml(
|
||||||
Field.templ_dict['swmod_assign'],
|
Field.templ_dict['swmod_assign'],
|
||||||
@ -666,10 +674,13 @@ class Field(Component):
|
|||||||
swmod_props = ''
|
swmod_props = ''
|
||||||
|
|
||||||
if self.obj.get_property('swacc') and \
|
if self.obj.get_property('swacc') and \
|
||||||
self.obj.get_property('sw') in (AccessType.rw, AccessType.r):
|
(self.properties['sw_rd'] or self.properties['sw_wr']):
|
||||||
|
|
||||||
self.logger.debug("Field has swacc property")
|
self.logger.debug("Field has swacc property")
|
||||||
|
|
||||||
|
self.properties['swacc'] = True
|
||||||
|
self.properties['sw_wr_wire'] = True
|
||||||
|
self.properties['sw_rd_wire'] = True
|
||||||
|
|
||||||
swacc_props = self.process_yaml(
|
swacc_props = self.process_yaml(
|
||||||
Field.templ_dict['swacc_assign'],
|
Field.templ_dict['swacc_assign'],
|
||||||
{'path': self.path_underscored,
|
{'path': self.path_underscored,
|
||||||
@ -691,7 +702,7 @@ class Field(Component):
|
|||||||
|
|
||||||
def __add_interrupt(self):
|
def __add_interrupt(self):
|
||||||
if self.obj.get_property('intr'):
|
if self.obj.get_property('intr'):
|
||||||
self.intr = True
|
self.properties['intr'] = True
|
||||||
|
|
||||||
# Determine what causes the interrupt to get set, i.e.,
|
# Determine what causes the interrupt to get set, i.e.,
|
||||||
# is it a trigger that is passed to the module through an
|
# is it a trigger that is passed to the module through an
|
||||||
@ -791,21 +802,21 @@ class Field(Component):
|
|||||||
self.get_signal_name(haltmask)
|
self.get_signal_name(haltmask)
|
||||||
])
|
])
|
||||||
|
|
||||||
self.halt = True
|
self.properties['halt'] = True
|
||||||
elif haltenable := self.obj.get_property('haltenable'):
|
elif haltenable := self.obj.get_property('haltenable'):
|
||||||
self.itr_haltmasked = ' && '.join([
|
self.itr_haltmasked = ' && '.join([
|
||||||
self.register_name,
|
self.register_name,
|
||||||
self.get_signal_name(haltenable)
|
self.get_signal_name(haltenable)
|
||||||
])
|
])
|
||||||
|
|
||||||
self.halt = True
|
self.properties['halt'] = True
|
||||||
else:
|
else:
|
||||||
self.itr_haltmasked = self.register_name
|
self.itr_haltmasked = self.register_name
|
||||||
else:
|
else:
|
||||||
self.itr_masked = False
|
self.itr_masked = False
|
||||||
self.itr_haltmasked = False
|
self.itr_haltmasked = False
|
||||||
|
|
||||||
return self.intr
|
return self.properties['intr']
|
||||||
|
|
||||||
def __add_hw_access(self):
|
def __add_hw_access(self):
|
||||||
# Mutually exclusive. systemrdl-compiler performs check for this
|
# Mutually exclusive. systemrdl-compiler performs check for this
|
||||||
@ -957,7 +968,7 @@ class Field(Component):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def create_external_rtl(self):
|
def create_external_rtl(self):
|
||||||
if self.obj.get_property('sw') in (AccessType.rw, AccessType.w):
|
if self.properties['sw_wr']:
|
||||||
for i, alias in enumerate(self.path_underscored_vec):
|
for i, alias in enumerate(self.path_underscored_vec):
|
||||||
# Create bit-wise mask so that outside logic knows what
|
# Create bit-wise mask so that outside logic knows what
|
||||||
# bits it may change
|
# bits it may change
|
||||||
@ -989,7 +1000,7 @@ class Field(Component):
|
|||||||
}
|
}
|
||||||
))
|
))
|
||||||
|
|
||||||
if self.obj.get_property('sw') in (AccessType.rw, AccessType.r):
|
if self.properties['sw_rd']:
|
||||||
for i, alias in enumerate(self.path_underscored_vec):
|
for i, alias in enumerate(self.path_underscored_vec):
|
||||||
self.rtl_footer.append(self.process_yaml(
|
self.rtl_footer.append(self.process_yaml(
|
||||||
Field.templ_dict['external_rd_assignments'],
|
Field.templ_dict['external_rd_assignments'],
|
||||||
|
@ -42,9 +42,9 @@ class Register(Component):
|
|||||||
self.config,
|
self.config,
|
||||||
glbl_settings)
|
glbl_settings)
|
||||||
|
|
||||||
# Get certain properties from field that apply to whole register
|
# Get properties from field that apply to whole register
|
||||||
self.intr = self.intr or self.children[field_range].intr
|
for key in self.properties:
|
||||||
self.halt = self.halt or self.children[field_range].halt
|
self.properties[key] |= self.children[field_range].properties[key]
|
||||||
|
|
||||||
# Perform sanity check
|
# Perform sanity check
|
||||||
self.children[field_range].sanity_checks()
|
self.children[field_range].sanity_checks()
|
||||||
@ -111,7 +111,7 @@ class Register(Component):
|
|||||||
# no mask or enables are specified.
|
# no mask or enables are specified.
|
||||||
# c) The halt property shall only be present if haltmask or haltenable is
|
# c) The halt property shall only be present if haltmask or haltenable is
|
||||||
# specified on at least one field in the register.
|
# specified on at least one field in the register.
|
||||||
if self.intr:
|
if self.properties['intr']:
|
||||||
self.rtl_footer.append(Register.templ_dict['interrupt_comment']['rtl'])
|
self.rtl_footer.append(Register.templ_dict['interrupt_comment']['rtl'])
|
||||||
|
|
||||||
self.rtl_footer.append(
|
self.rtl_footer.append(
|
||||||
@ -125,7 +125,7 @@ class Register(Component):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
if self.halt:
|
if self.properties['halt']:
|
||||||
self.rtl_footer.append(
|
self.rtl_footer.append(
|
||||||
self.process_yaml(
|
self.process_yaml(
|
||||||
Register.templ_dict['interrupt_halt'],
|
Register.templ_dict['interrupt_halt'],
|
||||||
@ -328,38 +328,100 @@ class Register(Component):
|
|||||||
self.obj.current_idx = [0]
|
self.obj.current_idx = [0]
|
||||||
|
|
||||||
if self.total_dimensions:
|
if self.total_dimensions:
|
||||||
rw_wire_assign_field = 'rw_wire_assign_multi_dim'
|
access_wire_assign_field = 'access_wire_assign_multi_dim'
|
||||||
else:
|
else:
|
||||||
rw_wire_assign_field = 'rw_wire_assign_1_dim'
|
access_wire_assign_field = 'access_wire_assign_1_dim'
|
||||||
|
|
||||||
[self.rtl_header.append(
|
for i, x in enumerate(self.name_addr_mappings):
|
||||||
self.process_yaml(
|
self.rtl_header.append(
|
||||||
Register.templ_dict[rw_wire_assign_field],
|
self.process_yaml(
|
||||||
{'path': x[0],
|
Register.templ_dict['access_wire_comment'],
|
||||||
'addr': x[1],
|
{'path': x[0],
|
||||||
'alias': '(alias)' if i > 0 else '',
|
'alias': '(alias)' if i > 0 else '',
|
||||||
'genvars': self.genvars_str,
|
}
|
||||||
'genvars_sum': self.genvars_sum_str,
|
)
|
||||||
'depth': self.depth,
|
|
||||||
'field_type': self.field_type}
|
|
||||||
)
|
)
|
||||||
) for i, x in enumerate(self.name_addr_mappings)]
|
|
||||||
|
self.rtl_header.append(
|
||||||
|
self.process_yaml(
|
||||||
|
Register.templ_dict[access_wire_assign_field],
|
||||||
|
{'path': x[0],
|
||||||
|
'addr': x[1],
|
||||||
|
'genvars': self.genvars_str,
|
||||||
|
'genvars_sum': self.genvars_sum_str,
|
||||||
|
'depth': self.depth,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# A wire that indicates a read is required
|
||||||
|
if self.properties['sw_rd_wire']:
|
||||||
|
# Check if a read is actually possible. Otherwise provide a wire
|
||||||
|
# that is tied to 1'b0
|
||||||
|
if self.properties['sw_rd']:
|
||||||
|
self.rtl_header.append(
|
||||||
|
self.process_yaml(
|
||||||
|
Register.templ_dict['read_wire_assign'],
|
||||||
|
{'path': x[0],
|
||||||
|
'addr': x[1],
|
||||||
|
'genvars': self.genvars_str,
|
||||||
|
'genvars_sum': self.genvars_sum_str,
|
||||||
|
'depth': self.depth,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self.rtl_header.append(
|
||||||
|
self.process_yaml(
|
||||||
|
Register.templ_dict['read_wire_assign_0'],
|
||||||
|
{'path': x[0],
|
||||||
|
'genvars': self.genvars_str,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# A wire that indicates a write is required
|
||||||
|
if self.properties['sw_wr_wire']:
|
||||||
|
# Check if a write is actually possible. Otherwise provide a wire
|
||||||
|
# that is tied to 1'b0
|
||||||
|
if self.properties['sw_wr']:
|
||||||
|
self.rtl_header.append(
|
||||||
|
self.process_yaml(
|
||||||
|
Register.templ_dict['write_wire_assign'],
|
||||||
|
{'path': x[0],
|
||||||
|
'addr': x[1],
|
||||||
|
'genvars': self.genvars_str,
|
||||||
|
'genvars_sum': self.genvars_sum_str,
|
||||||
|
'depth': self.depth,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self.rtl_header.append(
|
||||||
|
self.process_yaml(
|
||||||
|
Register.templ_dict['write_wire_assign_0'],
|
||||||
|
{'path': x[0],
|
||||||
|
'genvars': self.genvars_str,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
# Add combined signal to be used for general access of the register
|
# Add combined signal to be used for general access of the register
|
||||||
self.rtl_header.append(
|
if self.properties['swacc']:
|
||||||
self.process_yaml(
|
self.rtl_header.append(
|
||||||
Register.templ_dict['rw_wire_assign_any_alias'],
|
self.process_yaml(
|
||||||
{'path': self.name_addr_mappings[0][0],
|
Register.templ_dict['rw_wire_assign_any_alias'],
|
||||||
'genvars': self.genvars_str,
|
{'path': self.name_addr_mappings[0][0],
|
||||||
'sw_rds_w_genvars': ' || '.join(
|
'genvars': self.genvars_str,
|
||||||
[''.join([x[0], '_sw_rd', self.genvars_str])
|
'sw_rds_w_genvars': ' || '.join(
|
||||||
for x in self.name_addr_mappings]),
|
[''.join([x[0], '_sw_rd', self.genvars_str])
|
||||||
'sw_wrs_w_genvars': ' || '.join(
|
for x in self.name_addr_mappings]),
|
||||||
[''.join([x[0], '_sw_wr', self.genvars_str])
|
'sw_wrs_w_genvars': ' || '.join(
|
||||||
for x in self.name_addr_mappings])
|
[''.join([x[0], '_sw_wr', self.genvars_str])
|
||||||
}
|
for x in self.name_addr_mappings])
|
||||||
|
}
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
|
|
||||||
def __add_signal_instantiations(self):
|
def __add_signal_instantiations(self):
|
||||||
# Add wire/register instantiations
|
# Add wire/register instantiations
|
||||||
|
@ -1,44 +1,55 @@
|
|||||||
---
|
---
|
||||||
rw_wire_assign_1_dim:
|
access_wire_comment:
|
||||||
rtl: |
|
|
||||||
|
|
||||||
// Register-activation for '{path}' {alias}
|
|
||||||
assign {path}_accss = b2r.addr == {addr};
|
|
||||||
assign {path}_sw_wr = {path}_accss && b2r.w_vld;
|
|
||||||
assign {path}_sw_rd = {path}_accss && b2r.r_vld;
|
|
||||||
signals:
|
|
||||||
- name: '{path}_sw_wr'
|
|
||||||
signal_type: 'logic'
|
|
||||||
- name: '{path}_sw_rd'
|
|
||||||
signal_type: 'logic'
|
|
||||||
- name: '{path}_accss'
|
|
||||||
signal_type: 'logic'
|
|
||||||
rw_wire_assign_multi_dim:
|
|
||||||
rtl: |-
|
rtl: |-
|
||||||
|
|
||||||
// Register-activation for '{path}' {alias}
|
// Register-activation for '{path}' {alias}
|
||||||
|
access_wire_assign_1_dim:
|
||||||
|
rtl: |-
|
||||||
|
assign {path}_accss = b2r.addr == {addr};
|
||||||
|
signals:
|
||||||
|
- name: '{path}_accss'
|
||||||
|
signal_type: 'logic'
|
||||||
|
access_wire_assign_multi_dim:
|
||||||
|
rtl: |-
|
||||||
assign {path}_accss{genvars} = b2r.addr == {addr}+({genvars_sum});
|
assign {path}_accss{genvars} = b2r.addr == {addr}+({genvars_sum});
|
||||||
assign {path}_sw_wr{genvars} = {path}_accss{genvars} && b2r.w_vld;
|
signals:
|
||||||
|
- name: '{path}_accss'
|
||||||
|
signal_type: 'logic'
|
||||||
|
read_wire_assign:
|
||||||
|
rtl: |-
|
||||||
assign {path}_sw_rd{genvars} = {path}_accss{genvars} && b2r.r_vld;
|
assign {path}_sw_rd{genvars} = {path}_accss{genvars} && b2r.r_vld;
|
||||||
|
signals:
|
||||||
|
- name: '{path}_sw_rd'
|
||||||
|
signal_type: 'logic'
|
||||||
|
read_wire_assign_0:
|
||||||
|
rtl: |-
|
||||||
|
assign {path}_sw_rd{genvars} = 0;
|
||||||
|
signals:
|
||||||
|
- name: '{path}_sw_rd'
|
||||||
|
signal_type: 'logic'
|
||||||
|
write_wire_assign:
|
||||||
|
rtl: |-
|
||||||
|
assign {path}_sw_wr{genvars} = {path}_accss{genvars} && b2r.w_vld;
|
||||||
signals:
|
signals:
|
||||||
- name: '{path}_sw_wr'
|
- name: '{path}_sw_wr'
|
||||||
signal_type: 'logic'
|
signal_type: 'logic'
|
||||||
- name: '{path}_sw_rd'
|
write_wire_assign_0:
|
||||||
|
rtl: |-
|
||||||
|
assign {path}_sw_wr{genvars} = 0;
|
||||||
|
signals:
|
||||||
|
- name: '{path}_sw_wr'
|
||||||
signal_type: 'logic'
|
signal_type: 'logic'
|
||||||
- name: '{path}_accss'
|
rw_wire_assign_any_alias:
|
||||||
signal_type: 'logic'
|
|
||||||
rw_wire_assign_any_alias:
|
|
||||||
rtl: |-
|
rtl: |-
|
||||||
|
|
||||||
// Combined register activation. These will become active
|
// Combined register activation. These will become active
|
||||||
// _any_ alias accesses a certain register.
|
|
||||||
assign {path}__any_alias_sw_wr{genvars} = {sw_wrs_w_genvars};
|
|
||||||
assign {path}__any_alias_sw_rd{genvars} = {sw_rds_w_genvars};
|
assign {path}__any_alias_sw_rd{genvars} = {sw_rds_w_genvars};
|
||||||
|
assign {path}__any_alias_sw_wr{genvars} = {sw_wrs_w_genvars};
|
||||||
signals:
|
signals:
|
||||||
- name: '{path}__any_alias_sw_wr'
|
|
||||||
signal_type: 'logic'
|
|
||||||
- name: '{path}__any_alias_sw_rd'
|
- name: '{path}__any_alias_sw_rd'
|
||||||
signal_type: 'logic'
|
signal_type: 'logic'
|
||||||
|
- name: '{path}__any_alias_sw_wr'
|
||||||
|
signal_type: 'logic'
|
||||||
reg_comment: |-
|
reg_comment: |-
|
||||||
|
|
||||||
/*******************************************************************
|
/*******************************************************************
|
||||||
|
Loading…
Reference in New Issue
Block a user