Add basic interrupt framework

Up to this point, interrupt outputs are generated and intr, enable,
mask, haltenable, and haltmask are supported. stick, stikcybit and the
different types of interrupts are not yet supported.

This commit also removes the option to turn off santiy checking. This is
a bad idea anyway...
This commit is contained in:
Dennis Potter 2021-09-25 20:49:39 -07:00
parent 8ea1ad97da
commit c52e59abd0
Signed by: Dennis
GPG Key ID: 186A8AD440942BAF
6 changed files with 125 additions and 17 deletions

View File

@ -51,13 +51,6 @@ class CliArguments():
help="If set, the dependency directories will be\
searched recursively.")
self.parser.add_argument(
"-x",
"--disable_sanity",
action="store_true",
help="Disable sanity checks or components. This might speed\
up the compiler but is generally not recommended!")
self.parser.add_argument(
"-e",
"--disable_enums",
@ -141,10 +134,6 @@ class CliArguments():
config['list_args'].append('Use Real Tabs : {}'.format(config['real_tabs']))
config['list_args'].append('Tab Width : {}'.format(config['tab_width']))
# Sanity check related
config['disable_sanity'] = args.disable_sanity
config['list_args'].append('Sanity Disabled : {}'.format(config['disable_sanity']))
# Set enums
config['enums'] = not args.disable_enums
config['list_args'].append('Enums Enabled : {}'.format(config['enums']))

View File

@ -39,6 +39,10 @@ class Component():
# Save config
self.config = config.copy()
# By default, registers and fields are not interrupt registers
self.intr = False
self.halt = False
# Create logger object
self.create_logger("{}".format(self.full_path), config)
self.logger.debug('Starting to process {} "{}"'.format(
@ -210,7 +214,9 @@ class Component():
name.append(obj.name)
# This is a property. Check if the original field actually has this property
if not obj.node.get_property(obj.name):
if obj.name == "intr" or obj.name == "halt":
pass
elif not obj.node.get_property(obj.name):
self.logger.fatal("Reference to the property '{}' of instance '{}' found. "
"This instance does hold the reference property! Please "
"fix this if you want me to do my job properly."

View File

@ -47,6 +47,7 @@ class Field(Component):
if not self.config['external']:
self.__add_always_ff()
self.__add_hw_access()
self.__add_interrupt()
self.__add_combo()
self.__add_swmod_swacc()
self.__add_counter()
@ -685,6 +686,47 @@ class Field(Component):
self.rtl_footer = [*self.rtl_footer, swmod_props, swacc_props]
def __add_interrupt(self):
if self.obj.get_property('intr'):
self.intr = True
# Generate masked & enabled version of interrupt to be
# picked up by the register at the top level
if mask := self.obj.get_property('mask'):
self.itr_masked = ' && !'.join([
self.register_name,
self.get_signal_name(mask)
])
elif enable := self.obj.get_property('enable'):
self.itr_masked = ' && '.join([
self.register_name,
self.get_signal_name(enable)
])
else:
self.itr_masked = self.register_name
# Generate haltmasked & haltenabled version of interrupt to be
# picked up by the register at the top level
if haltmask := self.obj.get_property('haltmask'):
self.itr_haltmasked = ' && !'.join([
self.register_name,
self.get_signal_name(haltmask)
])
self.halt = True
elif haltenable := self.obj.get_property('haltenable'):
self.itr_haltmasked = ' && '.join([
self.register_name,
self.get_signal_name(haltenable)
])
self.halt = True
else:
self.itr_haltmasked = self.register_name
else:
self.itr_masked = False
self.itr_haltmasked = False
def __add_hw_access(self):
# Mutually exclusive. systemrdl-compiler performs check for this
enable_mask_negl = ''
@ -1037,6 +1079,7 @@ class Field(Component):
def __process_variables(self, obj: FieldNode, array_dimensions: list, glbl_settings: dict):
# Create full name
self.path_wo_field = '__'.join(self.path.split('.', -1)[0:-1])
self.register_name = ''.join([self.path_underscored, '_q'])
self.path_underscored_vec = []
self.path_wo_field_vec = []
@ -1153,3 +1196,11 @@ class Field(Component):
# TODO: Counter & hw=r shouldn't work
# If hw=ro and the next property is set, throw a fatal
if self.obj.get_property('hw') == AccessType.r\
and self.obj.get_property('next'):
self.logger.error("Hardware property of field is set to read-only "\
"but simultanously, the next property is set. Since "\
"this would reflect wrong behavior in documentation, "\
"the next property is ignored.")

View File

@ -42,8 +42,12 @@ class Register(Component):
self.config,
glbl_settings)
if not config['disable_sanity']:
self.children[field_range].sanity_checks()
# 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
# Perform sanity check
self.children[field_range].sanity_checks()
def create_rtl(self):
# Create RTL of children
@ -68,6 +72,9 @@ class Register(Component):
# Fields will be added by get_rtl()
# Add interrupt logic
self.__add_interrupts()
# Add assignment of read-wires
self.__add_sw_mux_assignments()
@ -95,6 +102,42 @@ class Register(Component):
*self.rtl_header
]
def __add_interrupts(self):
# Semantics on the intr and halt property:
# a) The intr and halt register properties are outputs; they should only
# occur on the right-hand side of an assignment in SystemRDL.
# b) The intr property shall always be present on a intr register even if
# 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:
self.rtl_footer.append(Register.templ_dict['interrupt_comment']['rtl'])
self.rtl_footer.append(
self.process_yaml(
Register.templ_dict['interrupt_intr'],
{'path': self.path_underscored,
'genvars': self.genvars_str,
'list': ') || ('.join([
x.itr_masked for x in self.children.values() if x.itr_masked])
}
)
)
if self.halt:
self.rtl_footer.append(
self.process_yaml(
Register.templ_dict['interrupt_halt'],
{'path': self.path_underscored,
'genvars': self.genvars_str,
'list': ') || ('.join([
x.itr_haltmasked for x in self.children.values() if x.itr_haltmasked])
}
)
)
def __add_sw_mux_assignments(self):
accesswidth = self.obj.get_property('accesswidth') - 1
self.rtl_footer.append("")
@ -383,9 +426,6 @@ class Register(Component):
(self.create_underscored_path_static(obj)[3], obj.absolute_address)
]
# Create full name
self.create_underscored_path()
# Gnerate already started?
self.generate_active = glbl_settings['generate_active']

View File

@ -54,7 +54,9 @@ hw_access_we_wel:
signal_type: 'logic'
hw_access_no_we_wel:
rtl: |-
<<INDENT>>
// we or wel property not set
<<UNINDENT>>
hw_access_hwset:
rtl: |-
if ({path}_hwset{genvars})

View File

@ -122,3 +122,23 @@ external_err_condition:
signal_type: 'logic'
- name: '{path}_ext_{rd_or_wr}_ack'
signal_type: 'logic'
interrupt_comment:
rtl: |-
/**************************************
* Register contains interrupts *
**************************************/
interrupt_intr:
rtl: |-
// Register has at least one interrupt field
assign {path}_intr{genvars} = ({list});
output_ports:
- name: '{path}_intr'
signal_type: 'logic'
interrupt_halt:
rtl: |-
// Register has at least one interrupt field with halt property set
assign {path}_halt{genvars} = {list};
output_ports:
- name: '{path}_halt'
signal_type: 'logic'