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()
|
||||
|
||||
# By default, registers and fields are not interrupt registers
|
||||
self.intr = False
|
||||
self.halt = False
|
||||
self.properties = {
|
||||
'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
|
||||
self.create_logger("{}".format(self.full_path), config)
|
||||
|
@ -76,6 +76,10 @@ class Field(Component):
|
||||
# Append to list of registers that can write
|
||||
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')
|
||||
swwel = obj.get_property('swwel')
|
||||
|
||||
@ -114,7 +118,7 @@ class Field(Component):
|
||||
|
||||
if onwrite:
|
||||
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):
|
||||
access_rtl['sw_write'][0].append(
|
||||
self.process_yaml(
|
||||
@ -177,10 +181,14 @@ class Field(Component):
|
||||
# Append to list of registers that can read
|
||||
self.readable_by.add(path_wo_field)
|
||||
|
||||
self.properties['sw_wr'] = True
|
||||
|
||||
# Set onread properties
|
||||
if onread == OnReadType.ruser:
|
||||
self.logger.error("The OnReadType.ruser is not yet supported!")
|
||||
elif onread:
|
||||
self.properties['sw_rd_wire'] = True
|
||||
|
||||
access_rtl['sw_read'][0].append(
|
||||
self.process_yaml(
|
||||
Field.templ_dict[str(onread)],
|
||||
@ -636,7 +644,7 @@ class Field(Component):
|
||||
)
|
||||
|
||||
# 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(
|
||||
self.process_yaml(
|
||||
Field.templ_dict['swmod_assign'],
|
||||
@ -666,10 +674,13 @@ class Field(Component):
|
||||
swmod_props = ''
|
||||
|
||||
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.properties['swacc'] = True
|
||||
self.properties['sw_wr_wire'] = True
|
||||
self.properties['sw_rd_wire'] = True
|
||||
|
||||
swacc_props = self.process_yaml(
|
||||
Field.templ_dict['swacc_assign'],
|
||||
{'path': self.path_underscored,
|
||||
@ -691,7 +702,7 @@ class Field(Component):
|
||||
|
||||
def __add_interrupt(self):
|
||||
if self.obj.get_property('intr'):
|
||||
self.intr = True
|
||||
self.properties['intr'] = True
|
||||
|
||||
# Determine what causes the interrupt to get set, i.e.,
|
||||
# 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.halt = True
|
||||
self.properties['halt'] = True
|
||||
elif haltenable := self.obj.get_property('haltenable'):
|
||||
self.itr_haltmasked = ' && '.join([
|
||||
self.register_name,
|
||||
self.get_signal_name(haltenable)
|
||||
])
|
||||
|
||||
self.halt = True
|
||||
self.properties['halt'] = True
|
||||
else:
|
||||
self.itr_haltmasked = self.register_name
|
||||
else:
|
||||
self.itr_masked = False
|
||||
self.itr_haltmasked = False
|
||||
|
||||
return self.intr
|
||||
return self.properties['intr']
|
||||
|
||||
def __add_hw_access(self):
|
||||
# Mutually exclusive. systemrdl-compiler performs check for this
|
||||
@ -957,7 +968,7 @@ class Field(Component):
|
||||
)
|
||||
|
||||
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):
|
||||
# Create bit-wise mask so that outside logic knows what
|
||||
# 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):
|
||||
self.rtl_footer.append(self.process_yaml(
|
||||
Field.templ_dict['external_rd_assignments'],
|
||||
|
@ -42,9 +42,9 @@ class Register(Component):
|
||||
self.config,
|
||||
glbl_settings)
|
||||
|
||||
# Get certain properties from field that apply to whole register
|
||||
self.intr = self.intr or self.children[field_range].intr
|
||||
self.halt = self.halt or self.children[field_range].halt
|
||||
# Get properties from field that apply to whole register
|
||||
for key in self.properties:
|
||||
self.properties[key] |= self.children[field_range].properties[key]
|
||||
|
||||
# Perform sanity check
|
||||
self.children[field_range].sanity_checks()
|
||||
@ -111,7 +111,7 @@ class Register(Component):
|
||||
# no mask or enables are specified.
|
||||
# c) The halt property shall only be present if haltmask or haltenable is
|
||||
# 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(
|
||||
@ -125,7 +125,7 @@ class Register(Component):
|
||||
)
|
||||
)
|
||||
|
||||
if self.halt:
|
||||
if self.properties['halt']:
|
||||
self.rtl_footer.append(
|
||||
self.process_yaml(
|
||||
Register.templ_dict['interrupt_halt'],
|
||||
@ -328,24 +328,86 @@ class Register(Component):
|
||||
self.obj.current_idx = [0]
|
||||
|
||||
if self.total_dimensions:
|
||||
rw_wire_assign_field = 'rw_wire_assign_multi_dim'
|
||||
access_wire_assign_field = 'access_wire_assign_multi_dim'
|
||||
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.rtl_header.append(
|
||||
self.process_yaml(
|
||||
Register.templ_dict[rw_wire_assign_field],
|
||||
Register.templ_dict['access_wire_comment'],
|
||||
{'path': x[0],
|
||||
'alias': '(alias)' if i > 0 else '',
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
self.rtl_header.append(
|
||||
self.process_yaml(
|
||||
Register.templ_dict[access_wire_assign_field],
|
||||
{'path': x[0],
|
||||
'addr': x[1],
|
||||
'alias': '(alias)' if i > 0 else '',
|
||||
'genvars': self.genvars_str,
|
||||
'genvars_sum': self.genvars_sum_str,
|
||||
'depth': self.depth,
|
||||
'field_type': self.field_type}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
# 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,
|
||||
}
|
||||
)
|
||||
)
|
||||
) for i, x in enumerate(self.name_addr_mappings)]
|
||||
|
||||
# Add combined signal to be used for general access of the register
|
||||
if self.properties['swacc']:
|
||||
self.rtl_header.append(
|
||||
self.process_yaml(
|
||||
Register.templ_dict['rw_wire_assign_any_alias'],
|
||||
|
@ -1,44 +1,55 @@
|
||||
---
|
||||
rw_wire_assign_1_dim:
|
||||
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:
|
||||
access_wire_comment:
|
||||
rtl: |-
|
||||
|
||||
// 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}_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;
|
||||
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:
|
||||
- name: '{path}_sw_wr'
|
||||
signal_type: 'logic'
|
||||
- name: '{path}_sw_rd'
|
||||
signal_type: 'logic'
|
||||
- name: '{path}_accss'
|
||||
write_wire_assign_0:
|
||||
rtl: |-
|
||||
assign {path}_sw_wr{genvars} = 0;
|
||||
signals:
|
||||
- name: '{path}_sw_wr'
|
||||
signal_type: 'logic'
|
||||
rw_wire_assign_any_alias:
|
||||
rtl: |-
|
||||
|
||||
// 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_wr{genvars} = {sw_wrs_w_genvars};
|
||||
signals:
|
||||
- name: '{path}__any_alias_sw_wr'
|
||||
signal_type: 'logic'
|
||||
- name: '{path}__any_alias_sw_rd'
|
||||
signal_type: 'logic'
|
||||
- name: '{path}__any_alias_sw_wr'
|
||||
signal_type: 'logic'
|
||||
reg_comment: |-
|
||||
|
||||
/*******************************************************************
|
||||
|
Loading…
Reference in New Issue
Block a user