From f1d9ba26560e9a7634c887e4a66b2cbb94e9cf1c Mon Sep 17 00:00:00 2001 From: Dennis Date: Tue, 4 May 2021 00:23:14 +0200 Subject: [PATCH] Change way the order of RTL is determined By using a dictionary, it will be easier to mix & match the RTL order dependend on the properties of the field. This commit also adds anded/ored/xored properties. --- srdl2sv/components/field.py | 121 ++++++++++++++++------- srdl2sv/components/templates/fields.yaml | 7 ++ 2 files changed, 93 insertions(+), 35 deletions(-) diff --git a/srdl2sv/components/field.py b/srdl2sv/components/field.py index 11cc271..97276ce 100644 --- a/srdl2sv/components/field.py +++ b/srdl2sv/components/field.py @@ -1,10 +1,10 @@ -import yaml import math +import yaml from systemrdl import RDLCompiler, RDLCompileError, RDLWalker, RDLListener, node from systemrdl.node import FieldNode from systemrdl.rdltypes import PrecedenceType, AccessType - +from itertools import chain TAB = " " @@ -18,6 +18,10 @@ class Field: self.rtl = [] self.bytes = math.ceil(obj.width / 8) + # Make a list of I/O that shall be added to the addrmap + self.input_ports = [] + self.output_ports = [] + ################################################################################## # LIMITATION: # v1.x of the systemrdl-compiler does not support non-homogeneous arrays. @@ -43,7 +47,6 @@ class Field: rst_negl = "" rst_active = "active_high" - print(obj.get_property('reset')) # Value of reset? rst_value = '\'x' if obj.get_property("reset") == None else obj.get_property('reset') except: @@ -104,12 +107,23 @@ class Field: indent_lvl += 1 - # Define hardware access (if applicable) - hw_access_rtl = [] + # Not all access types are required and the order might differ + # depending on what types are defined and what precedence is + # set. Therefore, first add all RTL into a dictionary and + # later place it in the right order. + # + # The following RTL blocks are defined: + # - hw_write --> write access for the hardware interface + # - sw_write --> write access for the software interface + # + access_rtl = dict([]) - if hw_access == AccessType.rw or hw_access == AccessType.w: + # Define hardware access (if applicable) + access_rtl['hw_write'] = [] + + if hw_access in (AccessType.rw, AccessType.w): if obj.get_property('we') or obj.get_property('wel'): - hw_access_rtl.append( + access_rtl['hw_write'].append( Field.templ_dict['hw_access_we_wel'].format( negl = '!' if obj.get_property('wel') else '', reg_name = obj.parent.inst_name, @@ -117,7 +131,7 @@ class Field: genvars = genvars_str, indent = self.indent(indent_lvl))) - hw_access_rtl.append( + access_rtl['hw_write'].append( Field.templ_dict['hw_access_field'].format( reg_name = obj.parent.inst_name, field_name = obj.inst_name, @@ -125,45 +139,52 @@ class Field: indent = self.indent(indent_lvl))) # Define software access (if applicable) - sw_access_rtl = [] + access_rtl['sw_write'] = [] - # TODO: if sw_access_enabled - sw_access_rtl.append( - Field.templ_dict['sw_access_field'].format( - reg_name = obj.parent.inst_name, - field_name = obj.inst_name, - genvars = genvars_str, - indent = self.indent(indent_lvl))) - - indent_lvl += 1 - - # If field spans multiple bytes, every byte shall have a seperate enable! - for i in range(self.bytes): - sw_access_rtl.append( - Field.templ_dict['sw_access_byte'].format( + if sw_access in (AccessType.rw, AccessType.w): + access_rtl['sw_write'].append( + Field.templ_dict['sw_access_field'].format( reg_name = obj.parent.inst_name, field_name = obj.inst_name, genvars = genvars_str, - i = i, indent = self.indent(indent_lvl))) - sw_access_rtl.append("") + indent_lvl += 1 - indent_lvl -= 1 + # If field spans multiple bytes, every byte shall have a seperate enable! + for i in range(self.bytes): + access_rtl['sw_write'].append( + Field.templ_dict['sw_access_byte'].format( + reg_name = obj.parent.inst_name, + field_name = obj.inst_name, + genvars = genvars_str, + i = i, + indent = self.indent(indent_lvl))) - sw_access_rtl.append("{}end".format(self.indent(indent_lvl))) + indent_lvl -= 1 + + access_rtl['sw_write'].append("{}end".format(self.indent(indent_lvl))) + + # Define else with correct indentation and add to dictionary + access_rtl['else'] = ["{}else".format(self.indent(indent_lvl))] + + # Add empty string + access_rtl[''] = [''] # Check if hardware has precedence (default `precedence = sw`) if precedence == 'PrecedenceType.sw': - self.rtl = [*self.rtl, - *sw_access_rtl, - '{}else'.format(self.indent(indent_lvl)), - *hw_access_rtl] + rtl_order = ['sw_write', + 'else' if len(access_rtl['hw_write']) > 0 else '', + 'hw_write'] else: - self.rtl = [*self.rtl, - *sw_access_rtl, - '{}else'.format(self.indent(indent_lvl)), - *hw_access_rtl] + rtl_order = ['hw_write', + 'else' if len(access_rtl['sw_write']) > 0 else '', + 'sw_write'] + + # Add dictionary to main RTL list in correct order + self.rtl = [ + *self.rtl, + *chain.from_iterable([access_rtl[i] for i in rtl_order])] indent_lvl -= 1 @@ -173,6 +194,36 @@ class Field: field_name = obj.inst_name, indent = self.indent(indent_lvl))) + ##################### + # Add combo logic + ##################### + operations = [] + if obj.get_property('anded'): + operations.append(['anded', '&']) + if obj.get_property('ored'): + operations.append(['ored', '|']) + if obj.get_property('xored'): + operations.append(['xored', '^']) + + if len(operations) > 0: + self.rtl.append( + Field.templ_dict['combo_operation_comment'].format( + reg_name = obj.parent.inst_name, + field_name = obj.inst_name, + indent = self.indent(indent_lvl))) + + self.rtl = [ + *self.rtl, + *[Field.templ_dict['assign_combo_operation'].format( + field_name = obj.inst_name, + reg_name = obj.parent.inst_name, + genvars = genvars_str, + op_name = i[0], + op_verilog = i[1], + indent = self.indent(indent_lvl)) for i in operations]] + + # TODO: Set sanity checks. For example, having no we but precedence = hw + # will cause weird behavior. @staticmethod diff --git a/srdl2sv/components/templates/fields.yaml b/srdl2sv/components/templates/fields.yaml index dae102f..2fc3912 100644 --- a/srdl2sv/components/templates/fields.yaml +++ b/srdl2sv/components/templates/fields.yaml @@ -13,6 +13,7 @@ sw_access_field: |- sw_access_byte: |- {indent}if (byte_enable[{i}]) {indent} {reg_name}_{field_name}_q{genvars}[8*({i}+1)-1 -: 8] <= sw_wr_bus[8*({i}+1)-1 -: 8]; + hw_access_we_wel: |- {indent}if ({negl}{reg_name}_{field_name}_hw_wr{genvars}) hw_access_field: |- @@ -29,3 +30,9 @@ field_comment: |- {indent}// sw = {sw_access} {sw_precedence} {indent}// reset : {rst_active} / {rst_type} {indent}//----------------------------------------------- +combo_operation_comment: |- + + {indent}// Combinational logic for {reg_name}_{field_name} +assign_combo_operation: |- + {indent}assign {reg_name}_{field_name}_{op_name}{genvars} = {op_verilog}{reg_name}_{field_name}_q{genvars} +