From 085e2ea2dc271a756f27f035e03b671449ea47a0 Mon Sep 17 00:00:00 2001 From: Dennis Date: Sun, 23 May 2021 17:46:48 +0200 Subject: [PATCH] Provide more advanced way of adding internal signals or ports Now, every snippet of RTL in the YAML file can also hold internal variables (i.e., signals), input or output ports. Furthermore, the input/output port lists are replaced by a dictionary to prevent duplicate entries. --- srdl2sv/components/addrmap.py | 23 +- srdl2sv/components/component.py | 82 +++++-- srdl2sv/components/field.py | 107 +++++---- srdl2sv/components/register.py | 61 +++-- srdl2sv/components/templates/addrmap.yaml | 4 +- srdl2sv/components/templates/fields.yaml | 277 +++++++++++++++------- srdl2sv/components/templates/regs.yaml | 45 +++- 7 files changed, 392 insertions(+), 207 deletions(-) diff --git a/srdl2sv/components/addrmap.py b/srdl2sv/components/addrmap.py index c906a0f..40503e5 100644 --- a/srdl2sv/components/addrmap.py +++ b/srdl2sv/components/addrmap.py @@ -33,6 +33,7 @@ class AddrMap(Component): # We need a dictionary since it might be required to access the objects later # by name (for example, in case of aliases) self.registers = dict() + self.rdl_nodes = dict() # Traverse through children for child in obj.children(): @@ -61,24 +62,26 @@ class AddrMap(Component): # Input ports input_ports_rtl = [ AddrMap.templ_dict['input_port'].format( - name = x.name, - packed_dim = x.packed_dim, + name = key, + signal_type = value[0], unpacked_dim = '[{}]'.format( ']['.join( - [str(y) for y in x.unpacked_dim])) - if x.unpacked_dim else '') - for x in self.get_ports('input')] + [str(y) for y in value[1]])) + if value[1] else '') + for (key, value) in self.get_ports('input').items() + ] # Output ports output_ports_rtl = [ AddrMap.templ_dict['output_port'].format( - name = x.name, - packed_dim = x.packed_dim, + name = key, + signal_type = value[0], unpacked_dim = '[{}]'.format( ']['.join( - [str(y) for y in x.unpacked_dim])) - if x.unpacked_dim else '') - for x in self.get_ports('output')] + [str(y) for y in value[1]])) + if value[1] else '') + for (key, value) in self.get_ports('output').items() + ] # Remove comma from last port entry output_ports_rtl[-1] = output_ports_rtl[-1].rstrip(',') diff --git a/srdl2sv/components/component.py b/srdl2sv/components/component.py index 7e9a694..f44eb03 100644 --- a/srdl2sv/components/component.py +++ b/srdl2sv/components/component.py @@ -7,10 +7,13 @@ from systemrdl import node from log.log import create_logger # Define NamedTuple -class Port(NamedTuple): +class TypeDefMembers(NamedTuple): name: str - packed_dim: str - unpacked_dim: list + member_type: str + +class TypeDef(NamedTuple): + name: str + members: list[TypeDefMembers] class Component(): def __init__(self): @@ -18,9 +21,10 @@ class Component(): self.rtl_footer = [] self.children = [] self.ports = dict() - self.ports['input'] = [] - self.ports['output'] = [] - self.ports['inout'] = [] + self.signals = dict() + self.ports['input'] = dict() + self.ports['output'] = dict() + self.field_type = '' def create_logger(self, name: str, config: dict): self.logger = create_logger( @@ -32,10 +36,19 @@ class Component(): def get_ports(self, port_type: str): self.logger.debug("Return port list") - return [ - *self.ports[port_type], - *list(chain(*[x.get_ports(port_type) for x in self.children])) - ] + + for x in self.children: + self.ports[port_type] |= x.get_ports(port_type) + + return self.ports[port_type] + + def get_signals(self): + self.logger.debug("Return signal list") + + for x in self.children: + self.signals |= x.get_signals() + + return self.signals def get_rtl(self, tab_width: int = 0, real_tabs: bool = False) -> str: self.logger.debug("Return RTL") @@ -102,25 +115,60 @@ class Component(): @staticmethod def split_dimensions(path: str): - new_path = re.match(r'(.*?)(\[.*\])?(.*)', path) - return (''.join([new_path.group(1), new_path.group(3)]), - new_path.group(2) if new_path.group(2) else '[0]') + re_dimensions = re.compile('(\[[^]]\])') + new_path = re_dimensions.sub('', path) + return (new_path, ''.join(re_dimensions.findall(path))) @staticmethod - def get_ref_name(obj): + def get_signal_name(obj): name = [] + try: + child_obj = obj.node + except AttributeError: + child_obj = obj + split_name = Component.split_dimensions( Component.get_underscored_path( - obj.get_path(), - obj.owning_addrmap.inst_name) + child_obj.get_path(), + child_obj.owning_addrmap.inst_name) ) name.append(split_name[0]) - if isinstance(obj, (node.FieldNode)): + if isinstance(obj, node.FieldNode): name.append('_q') + elif isinstance(obj, node.SignalNode): + pass + else: + name.append('_') + name.append(obj.name) name.append(split_name[1]) return ''.join(name) + + def yaml_signals_to_list(self, yaml_obj): + try: + for x in yaml_obj['signals']: + self.signals[x['name'].format(path = self.path_underscored)] =\ + (x['signal_type'].format(field_type = self.field_type), + self.array_dimensions) + except (TypeError, KeyError): + pass + + try: + for x in yaml_obj['input_ports']: + self.ports['input'][x['name'].format(path = self.path_underscored)] =\ + (x['signal_type'].format(field_type = self.field_type), + self.array_dimensions) + except (TypeError, KeyError): + pass + + try: + for x in yaml_obj['output_ports']: + self.ports['output'][x['name'].format(path = self.path_underscored)] =\ + (x['signal_type'].format(field_type = self.field_type), + self.array_dimensions) + except (TypeError, KeyError): + pass diff --git a/srdl2sv/components/field.py b/srdl2sv/components/field.py index 150ec59..314646c 100644 --- a/srdl2sv/components/field.py +++ b/srdl2sv/components/field.py @@ -7,7 +7,7 @@ from systemrdl.node import FieldNode from systemrdl.rdltypes import PrecedenceType, AccessType, OnReadType, OnWriteType # Local modules -from components.component import Component, Port +from components.component import Component from . import templates class Field(Component): @@ -16,11 +16,11 @@ class Field(Component): pkg_resources.read_text(templates, 'fields.yaml'), Loader=yaml.FullLoader) - def __init__(self, obj: node.FieldNode, dimensions: list, config:dict): + def __init__(self, obj: node.FieldNode, array_dimensions: list, config:dict): super().__init__() # Save and/or process important variables - self.__process_variables(obj, dimensions) + self.__process_variables(obj, array_dimensions) # Create logger object self.create_logger("{}.{}".format(self.owning_addrmap, self.path), config) @@ -40,49 +40,55 @@ class Field(Component): self.__add_access_rtl() self.__add_combo() self.__add_ports() + self.__prepend_signal_declarations() def __add_combo(self): operations = [] if self.obj.get_property('anded'): - operations.append(['anded', '&']) + operations.append(['&', 'assign_anded_operation']) if self.obj.get_property('ored'): - operations.append(['ored', '|']) + operations.append(['|', 'assign_ored_operation']) if self.obj.get_property('xored'): - operations.append(['xored', '^']) + operations.append(['^', 'assign_xored_operation']) if len(operations) > 0: self.rtl_header.append( - Field.templ_dict['combo_operation_comment'].format( + Field.templ_dict['combo_operation_comment']['rtl'].format( path = self.path_underscored)) self.rtl_header = [ *self.rtl_header, - *[Field.templ_dict['assign_combo_operation'].format( + *[Field.templ_dict[i[1]]['rtl'].format( path = self.path_underscored, genvars = self.genvars_str, - op_name = i[0], - op_verilog = i[1]) for i in operations] + op_verilog = i[0]) for i in operations] ] + [self.yaml_signals_to_list(Field.templ_dict[i[1]]) for i in operations] - def __process_variables(self, obj: node.RootNode, dimensions: list): + + def __process_variables(self, obj: node.RootNode, array_dimensions: list): # Save object self.obj = obj # Create full name self.owning_addrmap = obj.owning_addrmap.inst_name - self.path = obj.get_path()\ + self.full_path = obj.get_path().replace('[]', '') + self.path = self.full_path\ .replace('[]', '')\ .replace('{}.'.format(self.owning_addrmap), '') self.path_underscored = self.path.replace('.', '_') self.path_wo_field = '.'.join(self.path.split('.', -1)[0:-1]) + # Field type + self.field_type = 'logic' + # Save dimensions of unpacked dimension - self.dimensions = dimensions + self.array_dimensions = array_dimensions # Calculate how many genvars shall be added - genvars = ['[{}]'.format(chr(97+i)) for i in range(len(dimensions))] + genvars = ['[{}]'.format(chr(97+i)) for i in range(len(array_dimensions))] self.genvars_str = ''.join(genvars) # Write enable @@ -138,7 +144,7 @@ class Field(Component): # Add comment with summary on field's properties return \ - Field.templ_dict['field_comment'].format( + Field.templ_dict['field_comment']['rtl'].format( name = self.obj.inst_name, hw_access = str(self.hw_access)[11:], sw_access = str(self.sw_access)[11:], @@ -156,7 +162,7 @@ class Field(Component): sense_list = 'sense_list_rst' if self.rst['async'] else 'sense_list_no_rst' self.rtl_header.append( - Field.templ_dict[sense_list].format( + Field.templ_dict[sense_list]['rtl'].format( clk_name = "clk", rst_edge = self.rst['edge'], rst_name = self.rst['name'])) @@ -164,15 +170,24 @@ class Field(Component): # Add actual reset line if self.rst['name']: self.rtl_header.append( - Field.templ_dict['rst_field_assign'].format( + Field.templ_dict['rst_field_assign']['rtl'].format( path = self.path_underscored, rst_name = self.rst['name'], rst_negl = "!" if self.rst['active'] == "active_high" else "", rst_value = self.rst['value'], genvars = self.genvars_str)) + self.yaml_signals_to_list(Field.templ_dict['rst_field_assign']) + self.rtl_header.append("begin") + # Add name of actual field to Signal field + # TODO + + def __prepend_signal_declarations(self): + pass + + def __add_access_rtl(self): # Not all access types are required and the order might differ # depending on what types are defined and what precedence is @@ -191,19 +206,21 @@ class Field(Component): if self.hw_access in (AccessType.rw, AccessType.w): if self.we_or_wel: access_rtl['hw_write'].append( - Field.templ_dict['hw_access_we_wel'].format( + Field.templ_dict['hw_access_we_wel']['rtl'].format( negl = '!' if self.obj.get_property('wel') else '', path = self.path_underscored, genvars = self.genvars_str)) else: access_rtl['hw_write'].append( - Field.templ_dict['hw_access_no_we_wel']) + Field.templ_dict['hw_access_no_we_wel']['rtl']) access_rtl['hw_write'].append( - Field.templ_dict['hw_access_field'].format( + Field.templ_dict['hw_access_field']['rtl'].format( path = self.path_underscored, genvars = self.genvars_str)) + self.yaml_signals_to_list(Field.templ_dict['hw_access_field']) + # Define software access (if applicable) access_rtl['sw_write'] = [] @@ -213,19 +230,19 @@ class Field(Component): if isinstance(swwe, (node.FieldNode, node.SignalNode)): access_rtl['sw_write'].append( - Field.templ_dict['sw_access_field_swwe'].format( + Field.templ_dict['sw_access_field_swwe']['rtl'].format( path_wo_field = self.path_wo_field, genvars = self.genvars_str, - swwe = Component.get_ref_name(swwe))) + swwe = Component.get_signal_name(swwe))) elif isinstance(swwel, (node.FieldNode, node.SignalNode)): access_rtl['sw_write'].append( - Field.templ_dict['sw_access_field_swwel'].format( + Field.templ_dict['sw_access_field_swwel']['rtl'].format( path_wo_field = self.path_wo_field, genvars = self.genvars_str, - swwel = Component.get_ref_name(swwel))) + swwel = Component.get_signal_name(swwel))) else: access_rtl['sw_write'].append( - Field.templ_dict['sw_access_field'].format( + Field.templ_dict['sw_access_field']['rtl'].format( path_wo_field = self.path_wo_field, genvars = self.genvars_str)) @@ -237,7 +254,7 @@ class Field(Component): self.logger.warning("The OnReadType.wuser is not yet supported!") elif onwrite in (OnWriteType.wclr, OnWriteType.wset): access_rtl['sw_write'].append( - Field.templ_dict[str(onwrite)].format( + Field.templ_dict[str(onwrite)]['rtl'].format( path = self.path_underscored, genvars = self.genvars_str, path_wo_field = self.path_wo_field @@ -247,7 +264,7 @@ class Field(Component): # If field spans multiple bytes, every byte shall have a seperate enable! for j, i in enumerate(range(self.lsbyte, self.msbyte+1)): access_rtl['sw_write'].append( - Field.templ_dict[str(onwrite)].format( + Field.templ_dict[str(onwrite)]['rtl'].format( path = self.path_underscored, genvars = self.genvars_str, i = i, @@ -260,7 +277,7 @@ class Field(Component): # If field spans multiple bytes, every byte shall have a seperate enable! for j, i in enumerate(range(self.lsbyte, self.msbyte+1)): access_rtl['sw_write'].append( - Field.templ_dict['sw_access_byte'].format( + Field.templ_dict['sw_access_byte']['rtl'].format( path = self.path_underscored, genvars = self.genvars_str, i = i, @@ -279,7 +296,7 @@ class Field(Component): self.logger.warning("The OnReadType.ruser is not yet supported!") else: access_rtl['sw_read'].append( - Field.templ_dict[str(onread)].format( + Field.templ_dict[str(onread)]['rtl'].format( path = self.path_underscored, genvars = self.genvars_str, path_wo_field = self.path_wo_field @@ -289,7 +306,7 @@ class Field(Component): # Add singlepulse property if self.obj.get_property('singlepulse'): access_rtl['singlepulse'] = [ - Field.templ_dict['singlepulse'].format( + Field.templ_dict['singlepulse']['rtl'].format( path = self.path_underscored, genvars = self.genvars_str) ] @@ -335,40 +352,19 @@ class Field(Component): self.rtl_header = [*self.rtl_header, *order_list_rtl] self.rtl_header.append( - Field.templ_dict['end_field_ff'].format( + Field.templ_dict['end_field_ff']['rtl'].format( path = self.path_underscored)) def __add_ports(self): - # Port is writable by hardware --> Input port from hardware - if self.hw_access in (AccessType.rw, AccessType.w): - self.ports['input'].append( - Port("{}_in".format(self.path_underscored), - "", - self.dimensions - )) - - # Port has enable signal --> create such an enable - if self.we_or_wel: - self.ports['input'].append( - Port("{}_hw_wr".format(self.path_underscored), - "", - self.dimensions - )) - if self.hw_access in (AccessType.rw, AccessType.r): - self.ports['output'].append( - Port("{}_r".format(self.path_underscored), - "[{}:0]".format(self.obj.width-1) if self.obj.width > 1 else "", - self.dimensions - )) - # Connect flops to output port self.rtl_header.append( - Field.templ_dict['out_port_assign'].format( + Field.templ_dict['out_port_assign']['rtl'].format( genvars = self.genvars_str, path = self.path_underscored)) + self.yaml_signals_to_list(Field.templ_dict['out_port_assign']) def sanity_checks(self): # If hw=rw/sw=[r]w and hw has no we/wel, sw will never be able to write @@ -381,3 +377,6 @@ class Field(Component): "precedence for hardware will render software's "\ "write property useless since hardware will "\ "write every cycle.") + + + # TODO: Counter & hw=r shouldn't work diff --git a/srdl2sv/components/register.py b/srdl2sv/components/register.py index 935317d..7805edf 100644 --- a/srdl2sv/components/register.py +++ b/srdl2sv/components/register.py @@ -25,28 +25,6 @@ class Register(Component): self.create_logger("{}.{}".format(self.owning_addrmap, self.path), config) self.logger.debug('Starting to process register "{}"'.format(obj.inst_name)) - # Create comment and provide user information about register he/she - # is looking at. - self.rtl_header.append( - Register.templ_dict['reg_comment'].format( - name = obj.inst_name, - dimensions = self.dimensions, - depth = self.depth)) - - # Create wires every register - self.rtl_header.append( - Register.templ_dict['rw_wire_declare'].format( - path = self.path, - depth = self.depth)) - - # Create generate block for register and add comment - self.rtl_header.append("generate") - for i in range(self.dimensions): - self.rtl_header.append( - Register.templ_dict['generate_for_start'].format( - iterator = chr(97+i), - limit = self.array_dimensions[i])) - # Create RTL for fields # Fields should be in order in RTL,therefore, use list for field in obj.fields(): @@ -57,6 +35,15 @@ class Register(Component): self.children.append(field_obj) + # Create generate block for register and add comment + self.rtl_header.append("generate") + for i in range(self.dimensions): + self.rtl_header.append( + Register.templ_dict['generate_for_start'].format( + iterator = chr(97+i), + limit = self.array_dimensions[i])) + + # End loops for i in range(self.dimensions-1, -1, -1): self.rtl_footer.append( @@ -72,7 +59,7 @@ class Register(Component): rw_wire_assign_field = 'rw_wire_assign_1_dim' self.rtl_header.append( - Register.templ_dict[rw_wire_assign_field].format( + Register.templ_dict[rw_wire_assign_field]['rtl'].format( path = self.path, addr = self.obj.absolute_address, genvars = self.genvars_str, @@ -80,6 +67,34 @@ class Register(Component): stride = self.obj.array_stride, depth = self.depth)) + self.yaml_signals_to_list(Register.templ_dict[rw_wire_assign_field]) + + # Add wire/register instantiations + self.rtl_header = [ + *[ + Register.templ_dict['signal_declaration'].format( + name = key, + type = value[0], + unpacked_dim = '[{}]'.format( + ']['.join( + [str(y) for y in value[1]])) + if value[1] else '') + for (key, value) in self.get_signals().items()], + '', + *self.rtl_header, + ] + + # Create comment and provide user information about register he/she + # is looking at. + self.rtl_header = [ + Register.templ_dict['reg_comment'].format( + name = obj.inst_name, + dimensions = self.dimensions, + depth = self.depth), + *self.rtl_header + ] + + def __process_variables(self, obj: node.RootNode): # Save object self.obj = obj diff --git a/srdl2sv/components/templates/addrmap.yaml b/srdl2sv/components/templates/addrmap.yaml index d2ca989..a9a8610 100644 --- a/srdl2sv/components/templates/addrmap.yaml +++ b/srdl2sv/components/templates/addrmap.yaml @@ -11,6 +11,6 @@ module_declaration: |- {outputs} ); input_port: |- - input {packed_dim:15s}{name:25s} {unpacked_dim}, + input {signal_type:15s}{name:25s} {unpacked_dim}, output_port: |- - output {packed_dim:15s}{name:25s} {unpacked_dim}, + output {signal_type:15s}{name:25s} {unpacked_dim}, diff --git a/srdl2sv/components/templates/fields.yaml b/srdl2sv/components/templates/fields.yaml index 7be476a..40b0a49 100644 --- a/srdl2sv/components/templates/fields.yaml +++ b/srdl2sv/components/templates/fields.yaml @@ -1,99 +1,192 @@ --- -sense_list_rst: |- - always_ff @(posedge {clk_name} or {rst_edge} {rst_name}) -sense_list_no_rst: |- - always_ff @(posedge {clk_name}) -rst_field_assign: |- - if ({rst_negl}{rst_name}) - begin - {path}_q{genvars} <= {rst_value}; - end - else -sw_access_field: |- - if ({path_wo_field}_sw_wr{genvars}) - begin -sw_access_field_swwe: |- - if ({path_wo_field}_sw_wr{genvars} && {swwe}) // swwe property - begin -sw_access_field_swwel: |- - if ({path_wo_field}_sw_wr{genvars} && !{swwel}) // swwel property - begin -sw_access_byte: |- - if (byte_enable[{i}]) - begin - {path}_q{genvars}[{msb_field}-:{field_w}] <= sw_wr_bus[{msb_bus}-:{bus_w}]; - end +sense_list_rst: + rtl: |- + always_ff @(posedge {clk_name} or {rst_edge} {rst_name}) +sense_list_no_rst: + rtl: |- + always_ff @(posedge {clk_name}) +rst_field_assign: + rtl: |- + if ({rst_negl}{rst_name}) + begin + {path}_q{genvars} <= {rst_value}; + end + else + signals: + - name: '{path}_q' + signal_type: '{field_type}' +sw_access_field: + rtl: |- + if ({path_wo_field}_sw_wr{genvars}) + begin +sw_access_field_swwe: + rtl: |- + if ({path_wo_field}_sw_wr{genvars} && {swwe}) // swwe property + begin +sw_access_field_swwel: + rtl: |- + if ({path_wo_field}_sw_wr{genvars} && !{swwel}) // swwel property + begin +sw_access_byte: + rtl: |- + if (byte_enable[{i}]) + begin + {path}_q{genvars}[{msb_field}-:{field_w}] <= sw_wr_bus[{msb_bus}-:{bus_w}]; + end -hw_access_we_wel: |- - if ({negl}{path}_hw_wr{genvars}) -hw_access_no_we_wel: |- - // we or wel property not set -hw_access_field: |- - begin - {path}_q{genvars} <= {path}_in{genvars}; - end -end_field_ff: |- - end // of {path}'s always_ff -OnWriteType.woset: |- - if (byte_enable[{i}]) // woset property - begin - {path}_q{genvars}[{msb_field}-:{field_w}] <= {path}_q{genvars}[{msb_field}-:{field_w}] | sw_wr_bus[{msb_bus}-:{bus_w}]; - end -OnWriteType.woclr: |- - if (byte_enable[{i}]) // woclr property - begin - {path}_q{genvars}[{msb_field}-:{field_w}] <= {path}_q{genvars}[{msb_field}-:{field_w}] & ~sw_wr_bus[{msb_bus}-:{bus_w}]; - end -OnWriteType.wot: |- - if (byte_enable[{i}]) // wot property - begin - {path}_q{genvars}[{msb_field}-:{field_w}] <= {path}_q{genvars}[{msb_field}-:{field_w}] ^ sw_wr_bus[{msb_bus}-:{bus_w}]; - end -OnWriteType.wzs: |- - if (byte_enable[{i}]) // wzs property - begin - {path}_q{genvars}[{msb_field}-:{field_w}] <= {path}_q{genvars}[{msb_field}-:{field_w}] & sw_wr_bus[{msb_bus}-:{bus_w}]; - end -OnWriteType.wzt: |- - if (byte_enable[{i}]) // wzt property - begin - {path}_q{genvars}[{msb_field}-:{field_w}] <= {path}_q{genvars}[{msb_field}-:{field_w}] ~^ sw_wr_bus[{msb_bus}-:{bus_w}]; - end -OnWriteType.wclr: |- - {path}_q{genvars} <= {{width{{1'b0}}}}; -OnWriteType.wset: |- - {path}_q{genvars} <= {{width{{1'b1}}}}; -OnReadType.rclr: |- - if ({path_wo_field}_sw_rd{genvars}) // rclr property - begin - {path}_q{genvars} <= {{width{{1'b0}}}}; - end -OnReadType.rset: |- - if ({path_wo_field}_sw_rd{genvars}) // rset property - begin - {path}_q{genvars} <= {{width{{1'b1}}}}; - end +hw_access_we_wel: + rtl: |- + if ({negl}{path}_hw_wr{genvars}) +hw_access_no_we_wel: + rtl: |- + // we or wel property not set +hw_access_field: + rtl: |- + begin + {path}_q{genvars} <= {path}_in{genvars}; + end + signals: + - name: '{path}_q' + signal_type: '{field_type}' + input_ports: + - name: '{path}_in' + signal_type: '{field_type}' +end_field_ff: + rtl: |- + end // of {path}'s always_ff +OnWriteType.woset: + rtl: |- + if (byte_enable[{i}]) // woset property + begin + {path}_q{genvars}[{msb_field}-:{field_w}] <= {path}_q{genvars}[{msb_field}-:{field_w}] | sw_wr_bus[{msb_bus}-:{bus_w}]; + end +OnWriteType.woclr: + rtl: |- + if (byte_enable[{i}]) // woclr property + begin + {path}_q{genvars}[{msb_field}-:{field_w}] <= {path}_q{genvars}[{msb_field}-:{field_w}] & ~sw_wr_bus[{msb_bus}-:{bus_w}]; + end +OnWriteType.wot: + rtl: |- + if (byte_enable[{i}]) // wot property + begin + {path}_q{genvars}[{msb_field}-:{field_w}] <= {path}_q{genvars}[{msb_field}-:{field_w}] ^ sw_wr_bus[{msb_bus}-:{bus_w}]; + end +OnWriteType.wzs: + rtl: |- + if (byte_enable[{i}]) // wzs property + begin + {path}_q{genvars}[{msb_field}-:{field_w}] <= {path}_q{genvars}[{msb_field}-:{field_w}] & sw_wr_bus[{msb_bus}-:{bus_w}]; + end +OnWriteType.wzt: + rtl: |- + if (byte_enable[{i}]) // wzt property + begin + {path}_q{genvars}[{msb_field}-:{field_w}] <= {path}_q{genvars}[{msb_field}-:{field_w}] ~^ sw_wr_bus[{msb_bus}-:{bus_w}]; + end +OnWriteType.wclr: + rtl: |- + {path}_q{genvars} <= {{width{{1'b0}}}}; +OnWriteType.wset: + rtl: |- + {path}_q{genvars} <= {{width{{1'b1}}}}; +OnReadType.rclr: + rtl: |- + if ({path_wo_field}_sw_rd{genvars}) // rclr property + begin + {path}_q{genvars} <= {{width{{1'b0}}}}; + end +OnReadType.rset: + rtl: |- + if ({path_wo_field}_sw_rd{genvars}) // rset property + begin + {path}_q{genvars} <= {{width{{1'b1}}}}; + end + +field_comment: + rtl: |- + + //-----------------FIELD SUMMARY----------------- + // name : {name} ({path_wo_field}[{msb}:{lsb}]) + // access : hw = {hw_access} {hw_precedence} + // sw = {sw_access} {sw_precedence} + // reset : {rst_active} / {rst_type} + // flags : {misc_flags} + //----------------------------------------------- +combo_operation_comment: + rtl: |- + + // Combinational logic for {path} +assign_anded_operation: + rtl: |- + assign {path}_anded{genvars} = {op_verilog}{path}_q{genvars}; + output_ports: + - name: '{path}_anded' + signal_type: 'logic' +assign_ored_operation: + rtl: |- + assign {path}_ored{genvars} = {op_verilog}{path}_q{genvars}; + output_ports: + - name: '{path}_ored' + signal_type: 'logic' +assign_xored_operation: + rtl: |- + assign {path}_xored{genvars} = {op_verilog}{path}_q{genvars}; + output_ports: + - name: '{path}_xored' + signal_type: 'logic' +singlepulse: + rtl: |- + begin + {path}{genvars}_q <= 0; + end +out_port_assign: + rtl: |- + // Connect register to hardware output port + assign {path}_r{genvars} = {path}_q{genvars}; + output_ports: + - name: '{path}_r' + signal_type: '{field_type}' +counter: + rtl: |- + always_comb + begin + {path}_next{genvars} = {path}_q{genvars}; + {path}_update_cnt{genvars} = 0; + + {incr_counter} + + {decr_counter} + end +incr_counter: + rtl: |- + {incr_counter_condition} + begin + {path}_next{genvars} += {path}_{operation_str}_val{genvars}; + {path}_update_cnt{genvars} = 1; + end +decr_counter: + rtl: |- + {incr_counter_condition} + begin + {path}_next{genvars} += {path}_{operation_str}_val{genvars}; + {path}_update_cnt{genvars} = 1; + end +incr_counter_condition: + rtl: |- + if ({path}_incr{genvars}) +incr_sat_counter_condition: + rtl: |- + if ({path}_incr{genvars} && {path}_next{genvars} + {path}_incr_val{genvars} <= {sat_value}) +decr_counter_condition: + rtl: |- + if ({path}_decr{genvars}) +decr_sat_counter_condition: + rtl: |- + if ({path}_decr{genvars} && {path}_next{genvars} - {path}_decr_val{genvars} >= {sat_value}) + -field_comment: |- - //-----------------FIELD SUMMARY----------------- - // name : {name} ({path_wo_field}[{msb}:{lsb}]) - // access : hw = {hw_access} {hw_precedence} - // sw = {sw_access} {sw_precedence} - // reset : {rst_active} / {rst_type} - // flags : {misc_flags} - //----------------------------------------------- -combo_operation_comment: |- - // Combinational logic for {path} -assign_combo_operation: |- - assign {path}_{op_name}{genvars} = {op_verilog}{path}_q{genvars} -singlepulse: |- - begin - {path}{genvars} <= 0; - end -out_port_assign: |- - // Connect register to hardware output port - assign {path}_r{genvars} = {path}_q{genvars}; diff --git a/srdl2sv/components/templates/regs.yaml b/srdl2sv/components/templates/regs.yaml index 559283b..7650b6b 100644 --- a/srdl2sv/components/templates/regs.yaml +++ b/srdl2sv/components/templates/regs.yaml @@ -1,14 +1,39 @@ --- -rw_wire_declare: | - logic {path}_sw_wr {depth}; - logic {path}_sw_rd {depth}; -rw_wire_assign_1_dim: | - assign {path}_sw_wr{genvars} = addr == {addr} && r_vld; - assign {path}_sw_rd{genvars} = addr == {addr} && w_vld; -rw_wire_assign_multi_dim: | - assign {path}_sw_wr{genvars} = addr == ({addr}+({genvars_sum})*{stride}) && r_vld; - assign {path}_sw_rd{genvars} = addr == ({addr}+({genvars_sum})*{stride}) && w_vld; +rw_wire_assign_1_dim: + rtl: | + // Assign register-activation signals + assign {path}_reg_active{genvars} = addr == {addr}; + + assign {path}_sw_wr = {path}_reg_active && r_vld; + assign {path}_sw_rd = {path}_reg_active && w_vld; + signals: + - name: '{path}_sw_wr' + signal_type: 'logic' + - name: '{path}_sw_rd' + signal_type: 'logic' + - name: '{path}_reg_active' + signal_type: 'logic' + input_ports: + output_ports: +rw_wire_assign_multi_dim: + rtl: | + + // Assign register-activation signals + assign {path}_reg_active{genvars} = addr == ({addr}+({genvars_sum})*{stride}); + + assign {path}_sw_wr{genvars} = {path}_reg_active{genvars} && r_vld; + assign {path}_sw_rd{genvars} = {path}_reg_active{genvars} && w_vld; + signals: + - name: '{path}_sw_wr' + signal_type: 'logic' + - name: '{path}_sw_rd' + signal_type: 'logic' + - name: '{path}_reg_active' + signal_type: 'logic' + input_ports: + output_ports: reg_comment: |- + /******************************************************************* ******************************************************************* * REGISTER : {name} @@ -21,3 +46,5 @@ generate_for_start: |- begin generate_for_end: |- end // of for loop with iterator {dimension} +signal_declaration: |- + {type:10s}{name:20s} {unpacked_dim};