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};