Move several methods to common Components ancestor

For example, most methods relating to dimensions or genvars were moved
to the Components class.

Furthermore, some more care was taken of _ or __ prefixes for methods:

    - No method-prefix: Public variable that is will be called by
                        non-related functions and methods.
    - _  method-prefix: Method will be called by class or class that
                        inerhits class
    - __ method-prefix: Method will be called by class itself only
This commit is contained in:
Dennis Potter 2021-10-24 00:07:59 -07:00
parent 20cec0c2a3
commit ec02290bbe
Signed by: Dennis
GPG Key ID: 186A8AD440942BAF
6 changed files with 345 additions and 366 deletions

View File

@ -24,22 +24,22 @@ class AddrMap(Component):
Loader=yaml.FullLoader) Loader=yaml.FullLoader)
def __init__(self, obj: node.RootNode, config: dict): def __init__(self, obj: node.RootNode, config: dict):
super().__init__(obj, config) super().__init__(
obj=obj,
config=config,
parents_strides=None,
parents_dimensions=None)
# Check if global resets are defined # Check if global resets are defined
glbl_settings = {} glbl_settings = {}
# Set defaults so that some of the common component methods work
self.total_dimensions = 0
self.total_array_dimensions = []
# Use global settings to define whether a component is already in a generate block # Use global settings to define whether a component is already in a generate block
glbl_settings['generate_active'] = False glbl_settings['generate_active'] = False
# Save whether 0, 1, or x must be set for reserved bits # Save whether 0, 1, or x must be set for reserved bits
if obj.get_property('rsvdset'): if self.obj.get_property('rsvdset'):
glbl_settings['rsvd_val'] = "1" glbl_settings['rsvd_val'] = "1"
elif obj.get_property('rsvdsetX'): elif self.obj.get_property('rsvdsetX'):
glbl_settings['rsvd_val'] = "x" glbl_settings['rsvd_val'] = "x"
else: else:
glbl_settings['rsvd_val'] = "0" glbl_settings['rsvd_val'] = "0"
@ -53,17 +53,28 @@ class AddrMap(Component):
self.regwidth = 0 self.regwidth = 0
# Traverse through children # Traverse through children
for child in obj.children(): for child in self.obj.children():
if isinstance(child, node.AddrmapNode): if isinstance(child, node.AddrmapNode):
# This addressmap opens a completely new scope. For example, # This addressmap opens a completely new scope. For example,
# a field_reset does not propagate through to this scope. # a field_reset does not propagate through to this scope.
self.logger.info('Found hierarchical addrmap. Entering it...') self.logger.info('Found hierarchical addrmap. Entering it...')
self.logger.error('Child addrmaps are not implemented yet!') self.logger.error('Child addrmaps are not implemented yet!')
elif isinstance(child, node.RegfileNode): elif isinstance(child, node.RegfileNode):
new_child = RegFile(child, [], [], config, glbl_settings) new_child = RegFile(
obj=child,
parents_dimensions=None,
parents_strides=None,
config=config,
glbl_settings=glbl_settings)
self.regfiles[child.inst_name] = new_child self.regfiles[child.inst_name] = new_child
elif isinstance(child, node.MemNode): elif isinstance(child, node.MemNode):
new_child = Memory(child, [], [], config, glbl_settings) new_child = Memory(
obj=child,
parents_dimensions=None,
parents_strides=None,
config=config,
glbl_settings=glbl_settings)
new_child.sanity_checks()
self.mems[child.inst_name] = new_child self.mems[child.inst_name] = new_child
elif isinstance(child, node.RegNode): elif isinstance(child, node.RegNode):
if child.inst.is_alias: if child.inst.is_alias:
@ -73,7 +84,12 @@ class AddrMap(Component):
self.registers[child.inst.alias_primary_inst.inst_name]\ self.registers[child.inst.alias_primary_inst.inst_name]\
.add_alias(child) .add_alias(child)
else: else:
new_child = Register(child, [], [], config, glbl_settings) new_child = Register(
obj=child,
parents_dimensions=None,
parents_strides=None,
config=config,
glbl_settings=glbl_settings)
self.registers[child.inst_name] = new_child self.registers[child.inst_name] = new_child
try: try:
@ -168,9 +184,9 @@ class AddrMap(Component):
] ]
try: try:
for x in self.get_package_names(): for pkg_name in self.__get_package_names():
import_package_list.append( import_package_list.append(
AddrMap.templ_dict['import_package']['rtl'].format(name = x) AddrMap.templ_dict['import_package']['rtl'].format(name = pkg_name)
) )
import_package_list.append('\n') import_package_list.append('\n')
@ -243,7 +259,7 @@ class AddrMap(Component):
list_of_cases.append(AddrMap.templ_dict['default_mux_case']['rtl']) list_of_cases.append(AddrMap.templ_dict['default_mux_case']['rtl'])
self.rtl_footer.append( self.rtl_footer.append(
self.process_yaml( self._process_yaml(
AddrMap.templ_dict['read_mux'], AddrMap.templ_dict['read_mux'],
{'list_of_cases': '\n'.join(list_of_cases)} {'list_of_cases': '\n'.join(list_of_cases)}
) )
@ -276,7 +292,7 @@ class AddrMap(Component):
pkg_resources.read_text(widgets, f"srdl2sv_{self.config['bus']}.yaml"), pkg_resources.read_text(widgets, f"srdl2sv_{self.config['bus']}.yaml"),
Loader=yaml.FullLoader) Loader=yaml.FullLoader)
return self.process_yaml( return self._process_yaml(
self.widget_templ_dict['module_instantiation'], self.widget_templ_dict['module_instantiation'],
{'bus_width': self.regwidth, {'bus_width': self.regwidth,
'no_byte_enable': 1 if self.config['no_byte_enable'] else 0, 'no_byte_enable': 1 if self.config['no_byte_enable'] else 0,
@ -297,7 +313,7 @@ class AddrMap(Component):
self.rtl_header.append(genvars_instantiation) self.rtl_header.append(genvars_instantiation)
def get_package_names(self) -> set(): def __get_package_names(self) -> set():
names = set() names = set()
for register in self.registers.values(): for register in self.registers.values():
@ -387,6 +403,3 @@ class AddrMap(Component):
real_tabs) real_tabs)
return rtl_return return rtl_return
def get_regwidth(self) -> int:
return self.regwidth

View File

@ -1,6 +1,7 @@
import re import re
import math
import sys import sys
from typing import NamedTuple from typing import NamedTuple, Optional
from dataclasses import dataclass from dataclasses import dataclass
from systemrdl import node from systemrdl import node
@ -27,7 +28,13 @@ class SWMuxEntryDimensioned():
dim: str dim: str
class Component(): class Component():
def __init__(self, obj, config): def __init__(
self,
obj,
config,
parents_dimensions: Optional[list] = None,
parents_strides: Optional[list] = None):
self.rtl_header = [] self.rtl_header = []
self.rtl_footer = [] self.rtl_footer = []
self.children = {} self.children = {}
@ -52,6 +59,18 @@ class Component():
# Save config # Save config
self.config = config.copy() self.config = config.copy()
# Generate all variables that have anything to do with dimensions or strides
self.__init_dimensions(parents_dimensions)
self.__init_strides(parents_strides)
# Save and/or process important variables
self.__init_variables()
# Create logger object
self.__create_logger(self.full_path, config)
self.logger.debug(f"Starting to process {self.__class__.__name__} '{obj.inst_name}'")
def __init_variables(self):
# By default, registers and fields are not interrupt registers # By default, registers and fields are not interrupt registers
self.properties = { self.properties = {
'intr': False, 'intr': False,
@ -64,11 +83,10 @@ class Component():
'sw_wr_wire': False, 'sw_wr_wire': False,
} }
# Create logger object self.genvars_str = ''
self.create_logger(self.full_path, config)
self.logger.debug(f"Starting to process {self.__class__.__name__} '{obj.inst_name}'")
def create_logger(self, name: str, config: dict):
def __create_logger(self, name: str, config: dict):
self.logger = create_logger( self.logger = create_logger(
name, name,
stream_log_level=config['stream_log_level'], stream_log_level=config['stream_log_level'],
@ -76,6 +94,51 @@ class Component():
file_name=config['file_log_location']) file_name=config['file_log_location'])
self.logger.propagate = False self.logger.propagate = False
def __init_dimensions(self, parents_dimensions):
# Determine dimensions of register
self.sel_arr = 'single'
self.total_array_dimensions = parents_dimensions if parents_dimensions else []
self.own_array_dimensions = []
try:
if self.obj.is_array:
self.sel_arr = 'array'
self.total_array_dimensions = [*self.total_array_dimensions,
*self.obj.array_dimensions]
self.own_array_dimensions = self.obj.array_dimensions
except AttributeError:
pass
# How many dimensions were already part of some higher up hierarchy?
self.parents_depths = len(parents_dimensions) if parents_dimensions else 0
# Calculate depth and number of dimensions
self.own_depth = '[{}]'.format(']['.join(f"{i}" for i in self.own_array_dimensions))
self.own_dimensions = len(self.own_array_dimensions)
self.total_dimensions = len(self.total_array_dimensions)
def __init_strides(self, parents_strides):
self.total_stride = parents_strides if parents_strides else []
try:
if self.obj.is_array:
# Merge parent's stride with stride of this regfile. Before doing so, the
# respective stride of the different dimensions shall be calculated
self.total_stride = [
*self.total_stride,
*[math.prod(self.own_array_dimensions[i+1:])
*self.obj.array_stride
for i, _ in enumerate(self.own_array_dimensions)]
]
except AttributeError:
# Not all Nodes can be an array. In that case, just take the parent's stride
pass
def _init_genvars(self):
# Calculate how many genvars shall be added
genvars = [f"[gv_{chr(97+i)}]" for i in range(self.total_dimensions)]
self.genvars_str = ''.join(genvars)
def get_resets(self): def get_resets(self):
self.logger.debug("Return reset list") self.logger.debug("Return reset list")
@ -190,14 +253,14 @@ class Component():
return '\n'.join(rtl_indented) return '\n'.join(rtl_indented)
@staticmethod @staticmethod
def get_underscored_path(path: str, owning_addrmap: str): def __get_underscored_path(path: str, owning_addrmap: str):
return path\ return path\
.replace('[]', '')\ .replace('[]', '')\
.replace(f"{owning_addrmap}.", '')\ .replace(f"{owning_addrmap}.", '')\
.replace('.', '__') .replace('.', '__')
@staticmethod @staticmethod
def split_dimensions(path: str): def __split_dimensions(path: str):
re_dimensions = re.compile(r'(\[[^]]*\])') re_dimensions = re.compile(r'(\[[^]]*\])')
new_path = re_dimensions.sub('', path) new_path = re_dimensions.sub('', path)
return (new_path, ''.join(re_dimensions.findall(path))) return (new_path, ''.join(re_dimensions.findall(path)))
@ -210,8 +273,8 @@ class Component():
except AttributeError: except AttributeError:
child_obj = obj child_obj = obj
split_name = Component.split_dimensions( split_name = self.__split_dimensions(
Component.get_underscored_path( self.__get_underscored_path(
child_obj.get_path(), child_obj.get_path(),
child_obj.owning_addrmap.inst_name) child_obj.owning_addrmap.inst_name)
) )
@ -243,7 +306,7 @@ class Component():
return ''.join(name) return ''.join(name)
def process_yaml(self, def _process_yaml(self,
yaml_obj, yaml_obj,
values: dict = {}, values: dict = {},
skip_signals: bool = False, skip_signals: bool = False,
@ -255,7 +318,8 @@ class Component():
for signal in yaml_obj['signals']: for signal in yaml_obj['signals']:
try: try:
array_dimensions = [] if signal['no_unpacked'] else self.total_array_dimensions array_dimensions = [] if signal['no_unpacked'] \
else self.total_array_dimensions
except KeyError: except KeyError:
array_dimensions = self.total_array_dimensions array_dimensions = self.total_array_dimensions
@ -269,14 +333,15 @@ class Component():
if skip_inputs: if skip_inputs:
raise KeyError raise KeyError
for input in yaml_obj['input_ports']: for input_p in yaml_obj['input_ports']:
try: try:
array_dimensions = [] if input['no_unpacked'] else self.total_array_dimensions array_dimensions = [] if input_p['no_unpacked'] \
else self.total_array_dimensions
except KeyError: except KeyError:
array_dimensions = self.total_array_dimensions array_dimensions = self.total_array_dimensions
self.ports['input'][input['name'].format(**values)] =\ self.ports['input'][input_p['name'].format(**values)] =\
(input['signal_type'].format(**values), (input_p['signal_type'].format(**values),
array_dimensions) array_dimensions)
except (TypeError, KeyError): except (TypeError, KeyError):
pass pass
@ -285,14 +350,15 @@ class Component():
if skip_outputs: if skip_outputs:
raise KeyError raise KeyError
for output in yaml_obj['output_ports']: for output_p in yaml_obj['output_ports']:
try: try:
array_dimensions = [] if output['no_unpacked'] else self.total_array_dimensions array_dimensions = [] if output_p['no_unpacked'] \
else self.total_array_dimensions
except KeyError: except KeyError:
array_dimensions = self.total_array_dimensions array_dimensions = self.total_array_dimensions
self.ports['output'][output['name'].format(**values)] =\ self.ports['output'][output_p['name'].format(**values)] =\
(output['signal_type'].format(**values), (output_p['signal_type'].format(**values),
array_dimensions) array_dimensions)
except (TypeError, KeyError): except (TypeError, KeyError):
pass pass
@ -300,32 +366,6 @@ class Component():
# Return RTL with values # Return RTL with values
return yaml_obj['rtl'].format(**values) return yaml_obj['rtl'].format(**values)
@staticmethod
def process_reset_signal(reset_signal):
rst = {}
try:
rst['name'] = reset_signal.inst_name
rst['async'] = reset_signal.get_property("async")
rst['type'] = "asynchronous" if rst['async'] else "synchronous"
# Active low or active high?
if reset_signal.get_property("activelow"):
rst['edge'] = "negedge"
rst['active'] = "active_low"
else:
rst['edge'] = "posedge"
rst['active'] = "active_high"
except:
rst['async'] = False
rst['name'] = None
rst['edge'] = None
rst['value'] = "'x"
rst['active'] = "-"
rst['type'] = "-"
return rst
def create_underscored_path(self): def create_underscored_path(self):
self.owning_addrmap, self.full_path, self.path, self.path_underscored =\ self.owning_addrmap, self.full_path, self.path, self.path_underscored =\
Component.create_underscored_path_static(self.obj) Component.create_underscored_path_static(self.obj)
@ -333,7 +373,7 @@ class Component():
@staticmethod @staticmethod
def create_underscored_path_static(obj): def create_underscored_path_static(obj):
owning_addrmap = obj.owning_addrmap.inst_name owning_addrmap = obj.owning_addrmap.inst_name
full_path = Component.split_dimensions(obj.get_path())[0] full_path = Component.__split_dimensions(obj.get_path())[0]
path = full_path.replace(f"{owning_addrmap}.", '') path = full_path.replace(f"{owning_addrmap}.", '')
path_underscored = path.replace('.', '__') path_underscored = path.replace('.', '__')
@ -349,3 +389,6 @@ class Component():
) )
return '' return ''
def get_regwidth(self) -> int:
return self.regwidth

View File

@ -2,6 +2,7 @@ import math
import importlib.resources as pkg_resources import importlib.resources as pkg_resources
import sys import sys
from typing import Optional
import yaml import yaml
from systemrdl.node import FieldNode, SignalNode from systemrdl.node import FieldNode, SignalNode
@ -21,16 +22,22 @@ class Field(Component):
def __init__( def __init__(
self, self,
obj: FieldNode, obj: FieldNode,
array_dimensions: list, parents_dimensions: Optional[list],
config:dict, config: dict):
glbl_settings: dict): super().__init__(
super().__init__(obj, config) obj=obj,
config=config,
parents_strides=None,
parents_dimensions=parents_dimensions)
# Generate all variables that have anything to do with dimensions or strides
self._init_genvars()
# Save and/or process important variables # Save and/or process important variables
self.__process_variables(obj, array_dimensions, glbl_settings) self.__init_variables(obj)
# Determine field types # Determine field types
self.__process_fieldtype() self.__init_fieldtype()
################################################################################## ##################################################################################
# LIMITATION: # LIMITATION:
@ -39,7 +46,7 @@ class Field(Component):
# can be found here: https://github.com/SystemRDL/systemrdl-compiler/issues/51 # can be found here: https://github.com/SystemRDL/systemrdl-compiler/issues/51
################################################################################## ##################################################################################
# Print a summary # Print a summary
self.rtl_header.append(self.summary()) self.rtl_header.append(self.__summary())
# Add description # Add description
self.rtl_header.append(self.get_description()) self.rtl_header.append(self.get_description())
@ -87,7 +94,7 @@ class Field(Component):
if isinstance(swwe, (FieldNode, SignalNode)): if isinstance(swwe, (FieldNode, SignalNode)):
access_rtl['sw_write'][0].append( access_rtl['sw_write'][0].append(
self.process_yaml( self._process_yaml(
Field.templ_dict['sw_access_field_swwe'], Field.templ_dict['sw_access_field_swwe'],
{'path_wo_field': path_wo_field, {'path_wo_field': path_wo_field,
'genvars': self.genvars_str, 'genvars': self.genvars_str,
@ -97,7 +104,7 @@ class Field(Component):
) )
elif isinstance(swwel, (FieldNode, SignalNode)): elif isinstance(swwel, (FieldNode, SignalNode)):
access_rtl['sw_write'][0].append( access_rtl['sw_write'][0].append(
self.process_yaml( self._process_yaml(
Field.templ_dict['sw_access_field_swwel'], Field.templ_dict['sw_access_field_swwel'],
{'path_wo_field': path_wo_field, {'path_wo_field': path_wo_field,
'genvars': self.genvars_str, 'genvars': self.genvars_str,
@ -107,7 +114,7 @@ class Field(Component):
) )
else: else:
access_rtl['sw_write'][0].append( access_rtl['sw_write'][0].append(
self.process_yaml( self._process_yaml(
Field.templ_dict['sw_access_field'], Field.templ_dict['sw_access_field'],
{'path_wo_field': path_wo_field, {'path_wo_field': path_wo_field,
'genvars': self.genvars_str, 'genvars': self.genvars_str,
@ -123,7 +130,7 @@ class Field(Component):
self.logger.warning("The OnWriteType.wuser is not yet supported!") self.logger.warning("The OnWriteType.wuser is not yet supported!")
elif onwrite in (OnWriteType.wclr, OnWriteType.wset): elif onwrite in (OnWriteType.wclr, OnWriteType.wset):
access_rtl['sw_write'][0].append( access_rtl['sw_write'][0].append(
self.process_yaml( self._process_yaml(
Field.templ_dict[str(onwrite)], Field.templ_dict[str(onwrite)],
{'path': path_underscored, {'path': path_underscored,
'genvars': self.genvars_str, 'genvars': self.genvars_str,
@ -139,7 +146,7 @@ class Field(Component):
lsb_bus = 8*i if i != self.lsbyte else obj.inst.lsb lsb_bus = 8*i if i != self.lsbyte else obj.inst.lsb
access_rtl['sw_write'][0].append( access_rtl['sw_write'][0].append(
self.process_yaml( self._process_yaml(
Field.templ_dict[str(onwrite)], Field.templ_dict[str(onwrite)],
{'path': path_underscored, {'path': path_underscored,
'genvars': self.genvars_str, 'genvars': self.genvars_str,
@ -161,7 +168,7 @@ class Field(Component):
lsb_bus = 8*i if i != self.lsbyte else obj.inst.lsb lsb_bus = 8*i if i != self.lsbyte else obj.inst.lsb
access_rtl['sw_write'][0].append( access_rtl['sw_write'][0].append(
self.process_yaml( self._process_yaml(
Field.templ_dict['sw_access_byte'], Field.templ_dict['sw_access_byte'],
{'path': self.path_underscored, {'path': self.path_underscored,
'genvars': self.genvars_str, 'genvars': self.genvars_str,
@ -192,7 +199,7 @@ class Field(Component):
self.properties['sw_rd_wire'] = True self.properties['sw_rd_wire'] = True
access_rtl['sw_read'][0].append( access_rtl['sw_read'][0].append(
self.process_yaml( self._process_yaml(
Field.templ_dict[str(onread)], Field.templ_dict[str(onread)],
{'width': obj.width, {'width': obj.width,
'path': path_underscored, 'path': path_underscored,
@ -205,7 +212,7 @@ class Field(Component):
# Property cannot be overwritten by alias # Property cannot be overwritten by alias
if obj.get_property('singlepulse'): if obj.get_property('singlepulse'):
self.access_rtl['singlepulse'] = ([ self.access_rtl['singlepulse'] = ([
self.process_yaml( self._process_yaml(
Field.templ_dict['singlepulse'], Field.templ_dict['singlepulse'],
{'path': self.path_underscored, {'path': self.path_underscored,
'genvars': self.genvars_str} 'genvars': self.genvars_str}
@ -297,7 +304,7 @@ class Field(Component):
incr_width_input = True incr_width_input = True
# Doesn't return RTL, only adds input port # Doesn't return RTL, only adds input port
self.process_yaml( self._process_yaml(
Field.templ_dict['counter_incr_val_input'], Field.templ_dict['counter_incr_val_input'],
{'path': self.path_underscored, {'path': self.path_underscored,
'genvars': self.genvars_str, 'genvars': self.genvars_str,
@ -339,7 +346,7 @@ class Field(Component):
# an internal signal. It is possible that this is tied to 0. # an internal signal. It is possible that this is tied to 0.
if not incr_width_input: if not incr_width_input:
self.rtl_footer.append( self.rtl_footer.append(
self.process_yaml( self._process_yaml(
Field.templ_dict['counter_internal_incr_val_signal'], Field.templ_dict['counter_internal_incr_val_signal'],
{'path': self.path_underscored, {'path': self.path_underscored,
'genvars': self.genvars_str, 'genvars': self.genvars_str,
@ -365,7 +372,7 @@ class Field(Component):
decr_width_input = True decr_width_input = True
# Doesn't return RTL, only adds input port # Doesn't return RTL, only adds input port
self.process_yaml( self._process_yaml(
Field.templ_dict['counter_decr_val_input'], Field.templ_dict['counter_decr_val_input'],
{'path': self.path_underscored, {'path': self.path_underscored,
'genvars': self.genvars_str, 'genvars': self.genvars_str,
@ -407,7 +414,7 @@ class Field(Component):
# an internal signal. It is possible that this is tied to 0. # an internal signal. It is possible that this is tied to 0.
if not decr_width_input: if not decr_width_input:
self.rtl_footer.append( self.rtl_footer.append(
self.process_yaml( self._process_yaml(
Field.templ_dict['counter_internal_decr_val_signal'], Field.templ_dict['counter_internal_decr_val_signal'],
{'path': self.path_underscored, {'path': self.path_underscored,
'genvars': self.genvars_str, 'genvars': self.genvars_str,
@ -432,13 +439,13 @@ class Field(Component):
if not incr: if not incr:
# Will only add input port but not return any RTL # Will only add input port but not return any RTL
self.process_yaml( self._process_yaml(
Field.templ_dict['counter_incr_input'], Field.templ_dict['counter_incr_input'],
{'path': self.path_underscored} {'path': self.path_underscored}
) )
else: else:
self.rtl_footer.append( self.rtl_footer.append(
self.process_yaml( self._process_yaml(
Field.templ_dict['counter_internal_incr_signal'], Field.templ_dict['counter_internal_incr_signal'],
{'path': self.path_underscored, {'path': self.path_underscored,
'genvars': self.genvars_str, 'genvars': self.genvars_str,
@ -459,7 +466,7 @@ class Field(Component):
else: else:
# Tie signal to 0 # Tie signal to 0
self.rtl_footer.append( self.rtl_footer.append(
self.process_yaml( self._process_yaml(
Field.templ_dict['counter_internal_incr_signal'], Field.templ_dict['counter_internal_incr_signal'],
{'path': self.path_underscored, {'path': self.path_underscored,
'genvars': self.genvars_str, 'genvars': self.genvars_str,
@ -473,13 +480,13 @@ class Field(Component):
if not self.obj.get_property('decr'): if not self.obj.get_property('decr'):
# Will only add input port but not return any RTL # Will only add input port but not return any RTL
self.process_yaml( self._process_yaml(
Field.templ_dict['counter_decr_input'], Field.templ_dict['counter_decr_input'],
{'path': self.path_underscored} {'path': self.path_underscored}
) )
else: else:
self.rtl_footer.append( self.rtl_footer.append(
self.process_yaml( self._process_yaml(
Field.templ_dict['counter_internal_decr_signal'], Field.templ_dict['counter_internal_decr_signal'],
{'path': self.path_underscored, {'path': self.path_underscored,
'genvars': self.genvars_str, 'genvars': self.genvars_str,
@ -500,7 +507,7 @@ class Field(Component):
else: else:
# Tie signal to 0 # Tie signal to 0
self.rtl_footer.append( self.rtl_footer.append(
self.process_yaml( self._process_yaml(
Field.templ_dict['counter_internal_decr_signal'], Field.templ_dict['counter_internal_decr_signal'],
{'path': self.path_underscored, {'path': self.path_underscored,
'genvars': self.genvars_str, 'genvars': self.genvars_str,
@ -512,7 +519,7 @@ class Field(Component):
# Handle saturation signals # Handle saturation signals
if not incr_sat_value: if not incr_sat_value:
self.rtl_footer.append( self.rtl_footer.append(
self.process_yaml( self._process_yaml(
Field.templ_dict['counter_incr_sat_tied'], Field.templ_dict['counter_incr_sat_tied'],
{'path': self.path_underscored, {'path': self.path_underscored,
'genvars': self.genvars_str, 'genvars': self.genvars_str,
@ -521,7 +528,7 @@ class Field(Component):
) )
else: else:
self.rtl_footer.append( self.rtl_footer.append(
self.process_yaml( self._process_yaml(
Field.templ_dict['counter_incr_sat'], Field.templ_dict['counter_incr_sat'],
{'path': self.path_underscored, {'path': self.path_underscored,
'genvars': self.genvars_str, 'genvars': self.genvars_str,
@ -534,7 +541,7 @@ class Field(Component):
if not decr_sat_value: if not decr_sat_value:
self.rtl_footer.append( self.rtl_footer.append(
self.process_yaml( self._process_yaml(
Field.templ_dict['counter_decr_sat_tied'], Field.templ_dict['counter_decr_sat_tied'],
{'path': self.path_underscored, {'path': self.path_underscored,
'genvars': self.genvars_str, 'genvars': self.genvars_str,
@ -543,7 +550,7 @@ class Field(Component):
) )
else: else:
self.rtl_footer.append( self.rtl_footer.append(
self.process_yaml( self._process_yaml(
Field.templ_dict['counter_decr_sat'], Field.templ_dict['counter_decr_sat'],
{'path': self.path_underscored, {'path': self.path_underscored,
'genvars': self.genvars_str, 'genvars': self.genvars_str,
@ -560,7 +567,7 @@ class Field(Component):
if incr_thr_value: if incr_thr_value:
self.rtl_footer.append( self.rtl_footer.append(
self.process_yaml( self._process_yaml(
Field.templ_dict['counter_incr_thr'], Field.templ_dict['counter_incr_thr'],
{'path': self.path_underscored, {'path': self.path_underscored,
'genvars': self.genvars_str, 'genvars': self.genvars_str,
@ -573,7 +580,7 @@ class Field(Component):
if decr_thr_value: if decr_thr_value:
self.rtl_footer.append( self.rtl_footer.append(
self.process_yaml( self._process_yaml(
Field.templ_dict['counter_decr_thr'], Field.templ_dict['counter_decr_thr'],
{'path': self.path_underscored, {'path': self.path_underscored,
'genvars': self.genvars_str, 'genvars': self.genvars_str,
@ -587,7 +594,7 @@ class Field(Component):
# Handle overflow & underflow signals # Handle overflow & underflow signals
if self.obj.get_property('overflow'): if self.obj.get_property('overflow'):
self.rtl_footer.append( self.rtl_footer.append(
self.process_yaml( self._process_yaml(
Field.templ_dict['counter_overflow'], Field.templ_dict['counter_overflow'],
{'path': self.path_underscored, {'path': self.path_underscored,
'genvars': self.genvars_str, 'genvars': self.genvars_str,
@ -600,7 +607,7 @@ class Field(Component):
if self.obj.get_property('underflow'): if self.obj.get_property('underflow'):
self.rtl_footer.append( self.rtl_footer.append(
self.process_yaml( self._process_yaml(
Field.templ_dict['counter_underflow'], Field.templ_dict['counter_underflow'],
{'path': self.path_underscored, {'path': self.path_underscored,
'genvars': self.genvars_str, 'genvars': self.genvars_str,
@ -613,7 +620,7 @@ class Field(Component):
# Implement actual counter logic # Implement actual counter logic
self.rtl_footer.append( self.rtl_footer.append(
self.process_yaml( self._process_yaml(
Field.templ_dict['counter'], Field.templ_dict['counter'],
{'path': self.path_underscored, {'path': self.path_underscored,
'genvars': self.genvars_str, 'genvars': self.genvars_str,
@ -621,8 +628,6 @@ class Field(Component):
) )
) )
def __add_swmod_swacc(self): def __add_swmod_swacc(self):
if self.obj.get_property('swmod'): if self.obj.get_property('swmod'):
self.logger.debug("Field has swmod property") self.logger.debug("Field has swmod property")
@ -632,7 +637,7 @@ class Field(Component):
# Check if read side-effects are defined. # Check if read side-effects are defined.
if self.obj.get_property('onread'): if self.obj.get_property('onread'):
swmod_assigns.append( swmod_assigns.append(
self.process_yaml( self._process_yaml(
Field.templ_dict['swmod_assign'], Field.templ_dict['swmod_assign'],
{'path': self.path_underscored, {'path': self.path_underscored,
'path_wo_field': self.path_wo_field, 'path_wo_field': self.path_wo_field,
@ -648,7 +653,7 @@ class Field(Component):
# Check if SW has write access to the field # Check if SW has write access to the field
if self.properties['sw_wr']: if self.properties['sw_wr']:
swmod_assigns.append( swmod_assigns.append(
self.process_yaml( self._process_yaml(
Field.templ_dict['swmod_assign'], Field.templ_dict['swmod_assign'],
{'path': self.path_underscored, {'path': self.path_underscored,
'path_wo_field': self.path_wo_field, 'path_wo_field': self.path_wo_field,
@ -661,7 +666,7 @@ class Field(Component):
) )
) )
swmod_props = self.process_yaml( swmod_props = self._process_yaml(
Field.templ_dict['swmod_always_comb'], Field.templ_dict['swmod_always_comb'],
{'path': self.path_underscored, {'path': self.path_underscored,
'genvars': self.genvars_str, 'genvars': self.genvars_str,
@ -683,7 +688,7 @@ class Field(Component):
self.properties['sw_wr_wire'] = True self.properties['sw_wr_wire'] = True
self.properties['sw_rd_wire'] = True self.properties['sw_rd_wire'] = True
swacc_props = self.process_yaml( swacc_props = self._process_yaml(
Field.templ_dict['swacc_assign'], Field.templ_dict['swacc_assign'],
{'path': self.path_underscored, {'path': self.path_underscored,
'path_wo_field': self.path_wo_field, 'path_wo_field': self.path_wo_field,
@ -719,7 +724,7 @@ class Field(Component):
trigger_signal = self.get_signal_name(next_val) trigger_signal = self.get_signal_name(next_val)
else: else:
trigger_signal =\ trigger_signal =\
self.process_yaml( self._process_yaml(
Field.templ_dict['trigger_input'], Field.templ_dict['trigger_input'],
{'path': self.path_underscored, {'path': self.path_underscored,
'field_type': self.field_type, 'field_type': self.field_type,
@ -728,7 +733,7 @@ class Field(Component):
if bit_type: if bit_type:
self.access_rtl['hw_write'] = ([ self.access_rtl['hw_write'] = ([
self.process_yaml( self._process_yaml(
Field.templ_dict[bit_type], Field.templ_dict[bit_type],
{'path': self.path_underscored, {'path': self.path_underscored,
'genvars': self.genvars_str, 'genvars': self.genvars_str,
@ -741,7 +746,7 @@ class Field(Component):
False) False)
self.rtl_footer.append( self.rtl_footer.append(
self.process_yaml( self._process_yaml(
Field.templ_dict[str(latch_signal)], Field.templ_dict[str(latch_signal)],
{'trigger_signal': trigger_signal, {'trigger_signal': trigger_signal,
'path': self.path_underscored, 'path': self.path_underscored,
@ -753,7 +758,6 @@ class Field(Component):
return (bit_type, trigger_signal) return (bit_type, trigger_signal)
def __add_interrupt(self): def __add_interrupt(self):
if self.obj.get_property('intr'): if self.obj.get_property('intr'):
@ -789,7 +793,7 @@ class Field(Component):
if intr_type != InterruptType.level: if intr_type != InterruptType.level:
if self.rst['name']: if self.rst['name']:
reset_intr_header = \ reset_intr_header = \
self.process_yaml( self._process_yaml(
Field.templ_dict['rst_intr_header'], Field.templ_dict['rst_intr_header'],
{'trigger_signal': trigger_signal, {'trigger_signal': trigger_signal,
'rst_name': self.rst['name'], 'rst_name': self.rst['name'],
@ -802,7 +806,7 @@ class Field(Component):
reset_intr_header = "" reset_intr_header = ""
self.rtl_footer.append( self.rtl_footer.append(
self.process_yaml( self._process_yaml(
Field.templ_dict['always_ff_block_intr'], Field.templ_dict['always_ff_block_intr'],
{'trigger_signal': trigger_signal, {'trigger_signal': trigger_signal,
'always_ff_header': self.always_ff_header, 'always_ff_header': self.always_ff_header,
@ -816,7 +820,7 @@ class Field(Component):
else: else:
self.access_rtl['hw_write'] = ([ self.access_rtl['hw_write'] = ([
self.process_yaml( self._process_yaml(
Field.templ_dict['nonsticky_intr'], Field.templ_dict['nonsticky_intr'],
{'path': self.path_underscored, {'path': self.path_underscored,
'assignment': trigger_signal, 'assignment': trigger_signal,
@ -878,7 +882,7 @@ class Field(Component):
if enable_mask: if enable_mask:
enable_mask_start_rtl = \ enable_mask_start_rtl = \
self.process_yaml( self._process_yaml(
Field.templ_dict['hw_enable_mask_start'], Field.templ_dict['hw_enable_mask_start'],
{'signal': self.get_signal_name(enable_mask), {'signal': self.get_signal_name(enable_mask),
'width': self.obj.width, 'width': self.obj.width,
@ -886,7 +890,7 @@ class Field(Component):
) )
enable_mask_end_rtl = \ enable_mask_end_rtl = \
self.process_yaml( self._process_yaml(
Field.templ_dict['hw_enable_mask_end'], Field.templ_dict['hw_enable_mask_end'],
{'width': self.obj.width} {'width': self.obj.width}
) )
@ -904,7 +908,7 @@ class Field(Component):
self.logger.info(f"Found {sticky} property.") self.logger.info(f"Found {sticky} property.")
elif self.obj.get_property('counter'): elif self.obj.get_property('counter'):
self.access_rtl['hw_write'] = ([ self.access_rtl['hw_write'] = ([
self.process_yaml( self._process_yaml(
Field.templ_dict['hw_access_counter'], Field.templ_dict['hw_access_counter'],
{'path': self.path_underscored, {'path': self.path_underscored,
'genvars': self.genvars_str, 'genvars': self.genvars_str,
@ -920,7 +924,7 @@ class Field(Component):
# if-line of hw-access # if-line of hw-access
self.access_rtl['hw_write'] = ([ self.access_rtl['hw_write'] = ([
self.process_yaml( self._process_yaml(
Field.templ_dict[write_condition], Field.templ_dict[write_condition],
{'negl': '!' if self.obj.get_property('wel') else '', {'negl': '!' if self.obj.get_property('wel') else '',
'path': self.path_underscored, 'path': self.path_underscored,
@ -948,7 +952,7 @@ class Field(Component):
# No special property. Assign input to register # No special property. Assign input to register
assignment = \ assignment = \
self.process_yaml( self._process_yaml(
Field.templ_dict['hw_access_field__assignment__input'], Field.templ_dict['hw_access_field__assignment__input'],
{'path': self.path_underscored, {'path': self.path_underscored,
'genvars': self.genvars_str, 'genvars': self.genvars_str,
@ -957,7 +961,7 @@ class Field(Component):
) )
self.access_rtl['hw_write'][0].append( self.access_rtl['hw_write'][0].append(
self.process_yaml( self._process_yaml(
Field.templ_dict['hw_access_field'], Field.templ_dict['hw_access_field'],
{'path': self.path_underscored, {'path': self.path_underscored,
'genvars': self.genvars_str, 'genvars': self.genvars_str,
@ -975,7 +979,7 @@ class Field(Component):
# Check if the hwset or hwclr option is set # Check if the hwset or hwclr option is set
if self.obj.get_property('hwset'): if self.obj.get_property('hwset'):
self.access_rtl['hw_setclr'] = ([ self.access_rtl['hw_setclr'] = ([
self.process_yaml( self._process_yaml(
Field.templ_dict['hw_access_hwset'], Field.templ_dict['hw_access_hwset'],
{'path': self.path_underscored, {'path': self.path_underscored,
'genvars': self.genvars_str, 'genvars': self.genvars_str,
@ -990,7 +994,7 @@ class Field(Component):
False) False)
elif self.obj.get_property('hwclr'): elif self.obj.get_property('hwclr'):
self.access_rtl['hw_setclr'] = ([ self.access_rtl['hw_setclr'] = ([
self.process_yaml( self._process_yaml(
Field.templ_dict['hw_access_hwclr'], Field.templ_dict['hw_access_hwclr'],
{'path': self.path_underscored, {'path': self.path_underscored,
'genvars': self.genvars_str, 'genvars': self.genvars_str,
@ -1010,7 +1014,7 @@ class Field(Component):
if self.obj.get_property('hw') in (AccessType.rw, AccessType.r): if self.obj.get_property('hw') in (AccessType.rw, AccessType.r):
# Connect flops to output port # Connect flops to output port
self.rtl_footer.append( self.rtl_footer.append(
self.process_yaml( self._process_yaml(
Field.templ_dict['out_port_assign'], Field.templ_dict['out_port_assign'],
{'genvars': self.genvars_str, {'genvars': self.genvars_str,
'path': self.path_underscored, 'path': self.path_underscored,
@ -1038,7 +1042,7 @@ class Field(Component):
width = width) width = width)
) )
self.rtl_footer.append(self.process_yaml( self.rtl_footer.append(self._process_yaml(
Field.templ_dict['external_wr_assignments'], Field.templ_dict['external_wr_assignments'],
{'path': alias, {'path': alias,
'path_wo_field': self.path_wo_field_vec[i], 'path_wo_field': self.path_wo_field_vec[i],
@ -1053,7 +1057,7 @@ class Field(Component):
if self.properties['sw_rd']: if self.properties['sw_rd']:
for i, alias in enumerate(self.path_underscored_vec): for i, alias in enumerate(self.path_underscored_vec):
self.rtl_footer.append(self.process_yaml( self.rtl_footer.append(self._process_yaml(
Field.templ_dict['external_rd_assignments'], Field.templ_dict['external_rd_assignments'],
{'path': alias, {'path': alias,
'path_wo_field': self.path_wo_field_vec[i], 'path_wo_field': self.path_wo_field_vec[i],
@ -1126,13 +1130,12 @@ class Field(Component):
self.rtl_header = [*self.rtl_header, *order_list_rtl] self.rtl_header = [*self.rtl_header, *order_list_rtl]
self.rtl_header.append( self.rtl_header.append(
self.process_yaml( self._process_yaml(
Field.templ_dict['end_field_ff'], Field.templ_dict['end_field_ff'],
{'path': self.path_underscored} {'path': self.path_underscored}
) )
) )
def __add_combo(self): def __add_combo(self):
operations = [] operations = []
if self.obj.get_property('anded'): if self.obj.get_property('anded'):
@ -1144,7 +1147,7 @@ class Field(Component):
if len(operations) > 0: if len(operations) > 0:
self.rtl_footer.append( self.rtl_footer.append(
self.process_yaml( self._process_yaml(
Field.templ_dict['combo_operation_comment'], Field.templ_dict['combo_operation_comment'],
{'path': self.path_underscored} {'path': self.path_underscored}
) )
@ -1152,7 +1155,7 @@ class Field(Component):
self.rtl_footer = [ self.rtl_footer = [
*self.rtl_footer, *self.rtl_footer,
*[self.process_yaml( *[self._process_yaml(
Field.templ_dict[i[1]], Field.templ_dict[i[1]],
{'path': self.path_underscored, {'path': self.path_underscored,
'genvars': self.genvars_str, 'genvars': self.genvars_str,
@ -1161,8 +1164,7 @@ class Field(Component):
) for i in operations] ) for i in operations]
] ]
def __init_fieldtype(self):
def __process_fieldtype(self):
try: try:
if not self.config['enums']: if not self.config['enums']:
raise AttributeError raise AttributeError
@ -1226,7 +1228,9 @@ class Field(Component):
# the field has a simple width # the field has a simple width
self.field_type = f"logic [{self.obj.width-1}:0]" self.field_type = f"logic [{self.obj.width-1}:0]"
def __process_variables(self, obj: FieldNode, array_dimensions: list, glbl_settings: dict): def __init_variables(
self,
obj: FieldNode):
# Create full name # Create full name
self.path_wo_field = '__'.join(self.path.split('.', -1)[0:-1]) self.path_wo_field = '__'.join(self.path.split('.', -1)[0:-1])
self.register_name = ''.join([self.path_underscored, '_q']) self.register_name = ''.join([self.path_underscored, '_q'])
@ -1242,15 +1246,6 @@ class Field(Component):
# is always required # is always required
self.properties['sw_rd_wire'] = self.config['external'] and self.properties['sw_rd'] self.properties['sw_rd_wire'] = self.config['external'] and self.properties['sw_rd']
# Save dimensions of unpacked dimension
self.array_dimensions = array_dimensions
self.total_array_dimensions = array_dimensions
self.total_dimensions = len(self.total_array_dimensions)
# Calculate how many genvars shall be added
genvars = [f"[gv_{chr(97+i)}]" for i in range(len(array_dimensions))]
self.genvars_str = ''.join(genvars)
# Write enable # Write enable
self.we_or_wel = self.obj.get_property('we') or self.obj.get_property('wel') self.we_or_wel = self.obj.get_property('we') or self.obj.get_property('wel')
@ -1266,8 +1261,7 @@ class Field(Component):
# Determine resets. This includes checking for async/sync resets, # Determine resets. This includes checking for async/sync resets,
# the reset value, and whether the field actually has a reset # the reset value, and whether the field actually has a reset
self.rst = Field.process_reset_signal( self.rst = Field.__process_reset_signal(obj.get_property("resetsignal"))
obj.get_property("resetsignal"))
if self.rst['name']: if self.rst['name']:
self.resets.add(self.rst['name']) self.resets.add(self.rst['name'])
@ -1289,7 +1283,7 @@ class Field(Component):
self.access_rtl['else'] = (["else"], False) self.access_rtl['else'] = (["else"], False)
self.access_rtl[''] = ([''], False) self.access_rtl[''] = ([''], False)
def summary(self): def __summary(self):
# Additional flags that are set # Additional flags that are set
# Use list, rather than set, to ensure the order stays the same # Use list, rather than set, to ensure the order stays the same
# when compiled multiple times # when compiled multiple times
@ -1326,7 +1320,7 @@ class Field(Component):
sense_list = 'sense_list_rst' if self.rst['async'] else 'sense_list_no_rst' sense_list = 'sense_list_rst' if self.rst['async'] else 'sense_list_no_rst'
self.always_ff_header = \ self.always_ff_header = \
self.process_yaml( self._process_yaml(
Field.templ_dict[sense_list], Field.templ_dict[sense_list],
{'rst_edge': self.rst['edge'], {'rst_edge': self.rst['edge'],
'rst_name': self.rst['name']} 'rst_name': self.rst['name']}
@ -1337,7 +1331,7 @@ class Field(Component):
# Add actual reset line # Add actual reset line
if self.rst['name']: if self.rst['name']:
self.rtl_header.append( self.rtl_header.append(
self.process_yaml( self._process_yaml(
Field.templ_dict['rst_field_assign'], Field.templ_dict['rst_field_assign'],
{'path': self.path_underscored, {'path': self.path_underscored,
'rst_name': self.rst['name'], 'rst_name': self.rst['name'],
@ -1377,3 +1371,31 @@ class Field(Component):
self.logger.error("It's not possible to combine the sticky(bit) "\ self.logger.error("It's not possible to combine the sticky(bit) "\
"property with the counter property. The counter property "\ "property with the counter property. The counter property "\
"will be ignored.") "will be ignored.")
@staticmethod
def __process_reset_signal(reset_signal):
rst = {}
try:
rst['name'] = reset_signal.inst_name
rst['async'] = reset_signal.get_property("async")
rst['type'] = "asynchronous" if rst['async'] else "synchronous"
# Active low or active high?
if reset_signal.get_property("activelow"):
rst['edge'] = "negedge"
rst['active'] = "active_low"
else:
rst['edge'] = "posedge"
rst['active'] = "active_high"
except AttributeError:
# Catch if reset_signal does not exist
rst['async'] = False
rst['name'] = None
rst['edge'] = None
rst['value'] = "'x"
rst['active'] = "-"
rst['type'] = "-"
return rst

View File

@ -21,13 +21,16 @@ class Memory(Component):
self, self,
obj: node.RegfileNode, obj: node.RegfileNode,
parents_dimensions: list, parents_dimensions: list,
parents_stride: list, parents_strides: list,
config: dict, config: dict):
glbl_settings: dict): super().__init__(
super().__init__(obj, config) obj=obj,
config=config,
parents_strides=parents_strides,
parents_dimensions=parents_dimensions)
# Save and/or process important variables # Save and/or process important variables
self.__process_variables(obj, parents_dimensions, parents_stride, glbl_settings) self._init_variables()
# Set object to 0 for easy addressing # Set object to 0 for easy addressing
self.obj.current_idx = [0] self.obj.current_idx = [0]
@ -37,7 +40,7 @@ class Memory(Component):
# fixed memory block # fixed memory block
self.rtl_header.append( self.rtl_header.append(
self.process_yaml( self._process_yaml(
Memory.templ_dict['memory_adr_assignments'], Memory.templ_dict['memory_adr_assignments'],
{'path': self.path_underscored, {'path': self.path_underscored,
'bytes_w': int(self.get_regwidth() / 8), 'bytes_w': int(self.get_regwidth() / 8),
@ -50,7 +53,7 @@ class Memory(Component):
if obj.get_property('sw') in (AccessType.rw, AccessType.r): if obj.get_property('sw') in (AccessType.rw, AccessType.r):
self.rtl_header.append( self.rtl_header.append(
self.process_yaml( self._process_yaml(
Memory.templ_dict['memory_rd_assignments'], Memory.templ_dict['memory_rd_assignments'],
{'path': self.path_underscored, {'path': self.path_underscored,
'data_w': self.get_regwidth() - 1, 'data_w': self.get_regwidth() - 1,
@ -60,7 +63,7 @@ class Memory(Component):
if obj.get_property('sw') in (AccessType.rw, AccessType.w): if obj.get_property('sw') in (AccessType.rw, AccessType.w):
self.rtl_header.append( self.rtl_header.append(
self.process_yaml( self._process_yaml(
Memory.templ_dict['memory_wr_assignments'], Memory.templ_dict['memory_wr_assignments'],
{'path': self.path_underscored, {'path': self.path_underscored,
'data_w': self.get_regwidth() - 1, 'data_w': self.get_regwidth() - 1,
@ -78,7 +81,7 @@ class Memory(Component):
# Create comment and provide user information about register he/she # Create comment and provide user information about register he/she
# is looking at. Also add a description, if applicable # is looking at. Also add a description, if applicable
self.rtl_header = [ self.rtl_header = [
self.process_yaml( self._process_yaml(
self.templ_dict['mem_comment'], self.templ_dict['mem_comment'],
{'inst_name': obj.inst_name, {'inst_name': obj.inst_name,
'type_name': obj.type_name, 'type_name': obj.type_name,
@ -91,26 +94,20 @@ class Memory(Component):
*self.rtl_header *self.rtl_header
] ]
def __process_variables(self, def _init_variables(self):
obj: node.RegfileNode, self.mementries = self.obj.get_property('mementries')
parents_dimensions: list, self.memwidth = self.obj.get_property('memwidth')
parents_stride: list,
glbl_settings: dict):
self.mementries = obj.get_property('mementries')
self.memwidth = obj.get_property('memwidth')
self.addr_w = self.mementries.bit_length() self.addr_w = self.mementries.bit_length()
def sanity_checks(self):
if not math.log2(self.memwidth).is_integer(): if not math.log2(self.memwidth).is_integer():
self.logger.fatal( "The defined memory width must be a power of 2. "\ self.logger.fatal( "The defined memory width must be a power of 2. "\
f"it is now defined as '{self.memwidth}'") f"it is now defined as '{self.memwidth}'")
sys.exit(1) sys.exit(1)
# Determine dimensions of register # Determine dimensions of register
if obj.is_array: if self.obj.is_array:
self.total_array_dimensions = [*parents_dimensions, *self.obj.array_dimensions]
self.array_dimensions = self.obj.array_dimensions
self.logger.warning("The memory is defined as array. The compiler not not "\ self.logger.warning("The memory is defined as array. The compiler not not "\
"provide any hooks to help here and expects that the user "\ "provide any hooks to help here and expects that the user "\
"handles this outside of the memory block.") "handles this outside of the memory block.")
@ -122,29 +119,21 @@ class Memory(Component):
f"{int(self.mementries * self.memwidth / 8)}). This must be "\ f"{int(self.mementries * self.memwidth / 8)}). This must be "\
"kept in mind when hooking up the memory interface to an "\ "kept in mind when hooking up the memory interface to an "\
"external memory block.") "external memory block.")
else:
self.total_array_dimensions = parents_dimensions
self.array_dimensions = []
self.total_stride = parents_stride
self.total_dimensions = len(self.total_array_dimensions)
self.depth = '[{}]'.format(']['.join(f"{i}" for i in self.array_dimensions))
self.dimensions = len(self.array_dimensions)
def __add_sw_mux_assignments(self): def __add_sw_mux_assignments(self):
# Create list of mux-inputs to later be picked up by carrying addrmap # Create list of mux-inputs to later be picked up by carrying addrmap
self.sw_mux_assignment_var_name = \ self.sw_mux_assignment_var_name = \
SWMuxEntry ( SWMuxEntry (
data_wire = self.process_yaml( data_wire = self._process_yaml(
Memory.templ_dict['sw_data_assignment_var_name'], Memory.templ_dict['sw_data_assignment_var_name'],
{'path': self.path_underscored, {'path': self.path_underscored,
'accesswidth': self.memwidth - 1} 'accesswidth': self.memwidth - 1}
), ),
rdy_wire = self.process_yaml( rdy_wire = self._process_yaml(
Memory.templ_dict['sw_rdy_assignment_var_name'], Memory.templ_dict['sw_rdy_assignment_var_name'],
{'path': self.path_underscored} {'path': self.path_underscored}
), ),
err_wire = self.process_yaml( err_wire = self._process_yaml(
Memory.templ_dict['sw_err_assignment_var_name'], Memory.templ_dict['sw_err_assignment_var_name'],
{'path': self.path_underscored} {'path': self.path_underscored}
), ),
@ -159,7 +148,7 @@ class Memory(Component):
access_type = 'sw_data_assignment_wo' access_type = 'sw_data_assignment_wo'
self.rtl_footer = [ self.rtl_footer = [
self.process_yaml( self._process_yaml(
self.templ_dict[access_type], self.templ_dict[access_type],
{'path': self.path_underscored, {'path': self.path_underscored,
'sw_data_assignment_var_name': self.sw_mux_assignment_var_name.data_wire, 'sw_data_assignment_var_name': self.sw_mux_assignment_var_name.data_wire,
@ -178,9 +167,6 @@ class Memory(Component):
) )
) )
def get_regwidth(self) -> int:
return self.memwidth
def __add_signal_instantiations(self): def __add_signal_instantiations(self):
# Add wire/register instantiations # Add wire/register instantiations
self.rtl_header = [ self.rtl_header = [
@ -204,3 +190,6 @@ class Memory(Component):
[str(y) for y in value[1]])) [str(y) for y in value[1]]))
if value[1] else '') if value[1] else '')
for (key, value) in dict_list] for (key, value) in dict_list]
def get_regwidth(self) -> int:
return self.memwidth

View File

@ -3,6 +3,8 @@ import sys
import math import math
import yaml import yaml
from typing import Optional
from systemrdl import node from systemrdl import node
from systemrdl.node import FieldNode from systemrdl.node import FieldNode
@ -21,15 +23,15 @@ class RegFile(Component):
def __init__( def __init__(
self, self,
obj: node.RegfileNode, obj: node.RegfileNode,
parents_dimensions: list,
parents_stride: list,
config: dict, config: dict,
parents_dimensions: Optional[list],
parents_strides: Optional[list],
glbl_settings: dict): glbl_settings: dict):
super().__init__(obj, config) super().__init__(
obj=obj,
# Save and/or process important variables config=config,
self.__process_variables(obj, parents_dimensions, parents_stride) parents_strides=parents_strides,
parents_dimensions=parents_dimensions)
# Empty dictionary of register objects # Empty dictionary of register objects
# We need a dictionary since it might be required to access the objects later # We need a dictionary since it might be required to access the objects later
@ -41,7 +43,7 @@ class RegFile(Component):
self.obj.current_idx = [0] self.obj.current_idx = [0]
# Determine whether this regfile must add a generate block and for-loop # Determine whether this regfile must add a generate block and for-loop
if self.dimensions and not glbl_settings['generate_active']: if self.own_dimensions and not glbl_settings['generate_active']:
self.generate_initiated = True self.generate_initiated = True
glbl_settings['generate_active'] = True glbl_settings['generate_active'] = True
else: else:
@ -60,11 +62,11 @@ class RegFile(Component):
self.obj.current_idx = [0] self.obj.current_idx = [0]
new_child = RegFile( new_child = RegFile(
child, obj=child,
self.total_array_dimensions, parents_dimensions=self.total_array_dimensions,
self.total_stride, parents_strides=self.total_stride,
config, config=config,
glbl_settings) glbl_settings=glbl_settings)
self.regfiles[child.inst_name] = new_child self.regfiles[child.inst_name] = new_child
elif isinstance(child, node.RegNode): elif isinstance(child, node.RegNode):
if child.inst.is_alias: if child.inst.is_alias:
@ -76,11 +78,11 @@ class RegFile(Component):
else: else:
self.obj.current_idx = [0] self.obj.current_idx = [0]
new_child = Register( new_child = Register(
child, obj=child,
self.total_array_dimensions, parents_dimensions=self.total_array_dimensions,
self.total_stride, parents_strides=self.total_stride,
config, config=config,
glbl_settings) glbl_settings=glbl_settings)
self.registers[child.inst_name] = new_child self.registers[child.inst_name] = new_child
try: try:
@ -115,30 +117,30 @@ class RegFile(Component):
# Create comment and provide user information about register he/she # Create comment and provide user information about register he/she
# is looking at. # is looking at.
self.rtl_header = [ self.rtl_header = [
self.process_yaml( self._process_yaml(
RegFile.templ_dict['regfile_comment'], RegFile.templ_dict['regfile_comment'],
{'name': obj.inst_name, {'name': obj.inst_name,
'dimensions': self.dimensions, 'dimensions': self.own_dimensions,
'depth': self.depth} 'depth': self.own_depth}
), ),
*self.rtl_header *self.rtl_header
] ]
# Create generate block for register and add comment # Create generate block for register and add comment
for i in range(self.dimensions-1, -1, -1): for i in range(self.own_dimensions-1, -1, -1):
self.rtl_footer.append( self.rtl_footer.append(
self.process_yaml( self._process_yaml(
RegFile.templ_dict['generate_for_end'], RegFile.templ_dict['generate_for_end'],
{'dimension': ''.join(['gv_', chr(97+i)])} {'dimension': ''.join(['gv_', chr(97+i)])}
) )
) )
for i in range(self.dimensions): for i in range(self.own_dimensions):
self.rtl_header.append( self.rtl_header.append(
self.process_yaml( self._process_yaml(
RegFile.templ_dict['generate_for_start'], RegFile.templ_dict['generate_for_start'],
{'iterator': ''.join(['gv_', chr(97+i+self.parents_depths)]), {'iterator': ''.join(['gv_', chr(97+i+self.parents_depths)]),
'limit': self.array_dimensions[i]} 'limit': self.own_array_dimensions[i]}
) )
) )
@ -148,82 +150,42 @@ class RegFile(Component):
self.rtl_footer.append("endgenerate") self.rtl_footer.append("endgenerate")
self.rtl_footer.append("") self.rtl_footer.append("")
def __process_variables(self,
obj: node.RegfileNode,
parents_dimensions: list,
parents_stride: list):
# Determine dimensions of register
if obj.is_array:
self.sel_arr = 'array'
self.total_array_dimensions = [*parents_dimensions, *self.obj.array_dimensions]
self.array_dimensions = self.obj.array_dimensions
# Merge parent's stride with stride of this regfile. Before doing so, the
# respective stride of the different dimensions shall be calculated
self.total_stride = [
*parents_stride,
*[math.prod(self.array_dimensions[i+1:])
*self.obj.array_stride
for i, _ in enumerate(self.array_dimensions)]
]
else:
self.sel_arr = 'single'
self.total_array_dimensions = parents_dimensions
self.array_dimensions = []
self.total_stride = parents_stride
# How many dimensions were already part of some higher up hierarchy?
self.parents_depths = len(parents_dimensions)
self.total_depth = '[{}]'.format(']['.join(f"{i}" for i in self.total_array_dimensions))
self.total_dimensions = len(self.total_array_dimensions)
self.depth = '[{}]'.format(']['.join(f"{i}" for i in self.array_dimensions))
self.dimensions = len(self.array_dimensions)
# Calculate how many genvars shall be added
genvars = ['[gv_{}]'.format(chr(97+i)) for i in range(self.dimensions)]
self.genvars_str = ''.join(genvars)
def create_mux_string(self): def create_mux_string(self):
for i in self.children.values(): for i in self.children.values():
yield from i.create_mux_string() yield from i.create_mux_string()
def get_signal_instantiations_list(self) -> set(): def get_signal_instantiations_list(self) -> set():
instantiations = list() instantiations = []
for i in self.children.values(): for child in self.children.values():
if isinstance(i, Register): if isinstance(child, Register):
instantiations.append("\n// Variables of register '{}'".format(i.name)) instantiations.append(f"\n// Variables of register '{child.name}'")
instantiations = [*instantiations, *i.get_signal_instantiations_list()] instantiations = [*instantiations, *child.get_signal_instantiations_list()]
return instantiations return instantiations
def get_package_names(self) -> set(): def get_package_names(self) -> set():
names = set() names = set()
for i in self.registers.values(): for register in self.registers.values():
for key, value in i.get_typedefs().items(): for typedef in register.get_typedefs().values():
names.add(value.scope) names.add(typedef.scope)
return names return names
def get_package_rtl(self) -> dict(): def get_package_rtl(self) -> {}:
if not self.config['enums']: if not self.config['enums']:
return None return None
# First go through all registers in this scope to generate a package # First go through all registers in this scope to generate a package
package_rtl = []
enum_rtl = {} enum_rtl = {}
rtl_return = []
# Need to keep track of enum names since they shall be unique # Need to keep track of enum names since they shall be unique
# per scope # per scope
enum_members = {} enum_members = {}
for i in self.registers.values(): for register in self.registers.values():
for key, value in i.get_typedefs().items(): for key, value in register.get_typedefs().items():
if value.scope not in enum_rtl: if value.scope not in enum_rtl:
enum_rtl[value.scope] = [] enum_rtl[value.scope] = []
@ -237,18 +199,15 @@ class RegFile(Component):
enum_members[var[0]] = "::".join([self.name, key]) enum_members[var[0]] = "::".join([self.name, key])
else: else:
self.logger.fatal( self.logger.fatal(
"Enum member '{}' was found at multiple locations in the same "\ f"Enum member '{var[0]}' was found at multiple locations in the same "\
"main scope: \n"\ "main scope: \n"\
" -- 1st occurance: '{}'\n"\ f" -- 1st occurance: '{enum_members[var[0]]}'\n"\
" -- 2nd occurance: '{}'\n\n"\ f" -- 2nd occurance: '{'::'.join([self.name, key])}'\n\n"\
"This is not legal because all these enums will be defined "\ "This is not legal because all these enums will be defined "\
"in the same SystemVerilog scope. To share the same enum among "\ "in the same SystemVerilog scope. To share the same enum among "\
"different registers, define them on a higher level in the "\ "different registers, define them on a higher level in the "\
"hierarchy.\n\n"\ "hierarchy.\n\n"\
"Exiting...".format( "Exiting...")
var[0],
enum_members[var[0]],
"::".join([value.scope, key])))
sys.exit(1) sys.exit(1)
@ -266,6 +225,3 @@ class RegFile(Component):
enum_var_list = ',\n'.join(variable_list))) enum_var_list = ',\n'.join(variable_list)))
return enum_rtl return enum_rtl
def get_regwidth(self) -> int:
return self.regwidth

View File

@ -1,6 +1,6 @@
import importlib.resources as pkg_resources import importlib.resources as pkg_resources
import math
import sys import sys
from typing import Optional
import yaml import yaml
from systemrdl import node from systemrdl import node
@ -19,27 +19,31 @@ class Register(Component):
def __init__( def __init__(
self, self,
obj: node.RegNode, obj: node.RegNode,
parents_dimensions: list,
parents_stride: list,
config: dict, config: dict,
parents_dimensions: Optional[list],
parents_strides: Optional[list],
glbl_settings: dict): glbl_settings: dict):
super().__init__(obj, config) super().__init__(
obj=obj,
config=config,
parents_strides=parents_strides,
parents_dimensions=parents_dimensions)
# Save and/or process important variables # Generate all variables that have anything to do with dimensions or strides
self.__process_variables(obj, parents_dimensions, parents_stride, glbl_settings) self.__init_genvars()
self.config['external'] = obj.external # Initialize all other variables
self.__init_variables(glbl_settings)
# Create RTL for fields of initial, non-alias register # Create RTL for fields of initial, non-alias register
for field in obj.fields(): for field in self.obj.fields():
# Use range to save field in an array. Reason is, names are allowed to # Use range to save field in an array. Reason is, names are allowed to
# change when using an alias # change when using an alias
field_range = ':'.join(map(str, [field.msb, field.lsb])) field_range = ':'.join(map(str, [field.msb, field.lsb]))
self.children[field_range] = Field(field, self.children[field_range] = Field(field,
self.total_array_dimensions, self.total_array_dimensions,
self.config, self.config)
glbl_settings)
# Get properties from field that apply to whole register # Get properties from field that apply to whole register
for key in self.properties: for key in self.properties:
@ -58,15 +62,15 @@ class Register(Component):
child.create_internal_rtl() child.create_internal_rtl()
# Create generate block for register and add comment # Create generate block for register and add comment
if self.dimensions and not self.generate_active: if self.own_dimensions and not self.generate_active:
self.rtl_header.append("generate") self.rtl_header.append("generate")
# Add N layers of for-loop starts # Add N layers of for-loop starts
for i in range(self.dimensions): for i in range(self.own_dimensions):
self.rtl_header.append( self.rtl_header.append(
Register.templ_dict['generate_for_start'].format( Register.templ_dict['generate_for_start'].format(
iterator = ''.join(['gv_', chr(97+i+self.parents_depths)]), iterator = ''.join(['gv_', chr(97+i+self.parents_depths)]),
limit = self.array_dimensions[i])) limit = self.own_array_dimensions[i]))
# Add decoders for all registers & aliases # Add decoders for all registers & aliases
self.__add_address_decoder() self.__add_address_decoder()
@ -80,12 +84,12 @@ class Register(Component):
self.__add_sw_mux_assignments() self.__add_sw_mux_assignments()
# Add N layers of for-loop end # Add N layers of for-loop end
for i in range(self.dimensions-1, -1, -1): for i in range(self.own_dimensions-1, -1, -1):
self.rtl_footer.append( self.rtl_footer.append(
Register.templ_dict['generate_for_end'].format( Register.templ_dict['generate_for_end'].format(
dimension = ''.join(['gv_', chr(97+i)]))) dimension = ''.join(['gv_', chr(97+i)])))
if self.dimensions and not self.generate_active: if self.own_dimensions and not self.generate_active:
self.rtl_footer.append("\nendgenerate\n") self.rtl_footer.append("\nendgenerate\n")
# Add wire instantiation # Add wire instantiation
@ -104,8 +108,8 @@ class Register(Component):
self.rtl_header = [ self.rtl_header = [
Register.templ_dict['reg_comment'].format( Register.templ_dict['reg_comment'].format(
name = self.obj.inst_name, name = self.obj.inst_name,
dimensions = self.dimensions, dimensions = self.own_dimensions,
depth = self.depth), depth = self.own_depth),
*self.rtl_header *self.rtl_header
] ]
@ -121,7 +125,7 @@ class Register(Component):
self.rtl_footer.append(Register.templ_dict['interrupt_comment']['rtl']) self.rtl_footer.append(Register.templ_dict['interrupt_comment']['rtl'])
self.rtl_footer.append( self.rtl_footer.append(
self.process_yaml( self._process_yaml(
Register.templ_dict['interrupt_intr'], Register.templ_dict['interrupt_intr'],
{'path': self.path_underscored, {'path': self.path_underscored,
'genvars': self.genvars_str, 'genvars': self.genvars_str,
@ -133,7 +137,7 @@ class Register(Component):
if self.properties['halt']: if self.properties['halt']:
self.rtl_footer.append( self.rtl_footer.append(
self.process_yaml( self._process_yaml(
Register.templ_dict['interrupt_halt'], Register.templ_dict['interrupt_halt'],
{'path': self.path_underscored, {'path': self.path_underscored,
'genvars': self.genvars_str, 'genvars': self.genvars_str,
@ -189,16 +193,16 @@ class Register(Component):
# Create list of mux-inputs to later be picked up by carrying addrmap # Create list of mux-inputs to later be picked up by carrying addrmap
self.sw_mux_assignment_var_name.append( self.sw_mux_assignment_var_name.append(
SWMuxEntry( SWMuxEntry(
data_wire = self.process_yaml( data_wire = self._process_yaml(
Register.templ_dict['sw_data_assignment_var_name'], Register.templ_dict['sw_data_assignment_var_name'],
{'path': na_map[0], {'path': na_map[0],
'accesswidth': accesswidth} 'accesswidth': accesswidth}
), ),
rdy_wire = self.process_yaml( rdy_wire = self._process_yaml(
Register.templ_dict['sw_rdy_assignment_var_name'], Register.templ_dict['sw_rdy_assignment_var_name'],
{'path': na_map[0]} {'path': na_map[0]}
), ),
err_wire = self.process_yaml( err_wire = self._process_yaml(
Register.templ_dict['sw_err_assignment_var_name'], Register.templ_dict['sw_err_assignment_var_name'],
{'path': na_map[0]} {'path': na_map[0]}
), ),
@ -216,7 +220,7 @@ class Register(Component):
sw_err_condition_vec = [] sw_err_condition_vec = []
sw_err_condition_vec.append(self.process_yaml( sw_err_condition_vec.append(self._process_yaml(
Register.templ_dict['sw_err_condition'], Register.templ_dict['sw_err_condition'],
{'rd_byte_list_ored': {'rd_byte_list_ored':
' || '.join(bytes_read_format) if bytes_read else "1'b0", ' || '.join(bytes_read_format) if bytes_read else "1'b0",
@ -228,7 +232,7 @@ class Register(Component):
if self.config['external']: if self.config['external']:
if bytes_read: if bytes_read:
for field in self.children.values(): for field in self.children.values():
sw_err_condition_vec.append(self.process_yaml( sw_err_condition_vec.append(self._process_yaml(
Register.templ_dict['external_err_condition'], Register.templ_dict['external_err_condition'],
{'path': '__'.join([na_map[0], field.name]), {'path': '__'.join([na_map[0], field.name]),
'genvars': self.genvars_str, 'genvars': self.genvars_str,
@ -238,7 +242,7 @@ class Register(Component):
if bytes_written: if bytes_written:
for field in self.children.values(): for field in self.children.values():
sw_err_condition_vec.append(self.process_yaml( sw_err_condition_vec.append(self._process_yaml(
Register.templ_dict['external_err_condition'], Register.templ_dict['external_err_condition'],
{'path': '__'.join([na_map[0], field.name]), {'path': '__'.join([na_map[0], field.name]),
'genvars': self.genvars_str, 'genvars': self.genvars_str,
@ -255,7 +259,7 @@ class Register(Component):
sw_rdy_condition_vec = ['('] sw_rdy_condition_vec = ['(']
for field in self.children.values(): for field in self.children.values():
sw_rdy_condition_vec.append(self.process_yaml( sw_rdy_condition_vec.append(self._process_yaml(
Register.templ_dict['external_rdy_condition'], Register.templ_dict['external_rdy_condition'],
{'path': '__'.join([na_map[0], field.name]), {'path': '__'.join([na_map[0], field.name]),
'genvars': self.genvars_str, 'genvars': self.genvars_str,
@ -275,7 +279,7 @@ class Register(Component):
sw_rdy_condition_vec.append('(') sw_rdy_condition_vec.append('(')
for field in self.children.values(): for field in self.children.values():
sw_rdy_condition_vec.append(self.process_yaml( sw_rdy_condition_vec.append(self._process_yaml(
Register.templ_dict['external_rdy_condition'], Register.templ_dict['external_rdy_condition'],
{'path': '__'.join([na_map[0], field.name]), {'path': '__'.join([na_map[0], field.name]),
'genvars': self.genvars_str, 'genvars': self.genvars_str,
@ -294,7 +298,7 @@ class Register(Component):
# Assign all values # Assign all values
self.rtl_footer.append( self.rtl_footer.append(
self.process_yaml( self._process_yaml(
Register.templ_dict['sw_data_assignment'], Register.templ_dict['sw_data_assignment'],
{'sw_data_assignment_var_name': self.sw_mux_assignment_var_name[-1].data_wire, {'sw_data_assignment_var_name': self.sw_mux_assignment_var_name[-1].data_wire,
'sw_rdy_assignment_var_name': self.sw_mux_assignment_var_name[-1].rdy_wire, 'sw_rdy_assignment_var_name': self.sw_mux_assignment_var_name[-1].rdy_wire,
@ -313,7 +317,7 @@ class Register(Component):
if self.total_array_dimensions: if self.total_array_dimensions:
vec = [0]*len(self.total_array_dimensions) vec = [0]*len(self.total_array_dimensions)
for dimension in Register.eval_genvars(vec, 0, self.total_array_dimensions): for dimension in Register.__eval_genvars(vec, 0, self.total_array_dimensions):
yield ( yield (
SWMuxEntryDimensioned( SWMuxEntryDimensioned(
mux_entry = mux_entry, mux_entry = mux_entry,
@ -329,21 +333,18 @@ class Register(Component):
) )
@staticmethod @staticmethod
def eval_genvars(vec, depth, dimensions): def __eval_genvars(vec, depth, dimensions):
for i in range(dimensions[depth]): for i in range(dimensions[depth]):
vec[depth] = i vec[depth] = i
if depth == len(dimensions) - 1: if depth == len(dimensions) - 1:
yield f"[{']['.join(map(str, vec))}]" yield f"[{']['.join(map(str, vec))}]"
else: else:
yield from Register.eval_genvars(vec, depth+1, dimensions) yield from Register.__eval_genvars(vec, depth+1, dimensions)
vec[depth] = 0 vec[depth] = 0
def __add_address_decoder(self): def __add_address_decoder(self):
# Assign variables from bus
self.obj.current_idx = [0]
if self.total_dimensions: if self.total_dimensions:
access_wire_assign_field = 'access_wire_assign_multi_dim' access_wire_assign_field = 'access_wire_assign_multi_dim'
else: else:
@ -351,7 +352,7 @@ class Register(Component):
for i, name_addr_map in enumerate(self.name_addr_mappings): for i, name_addr_map in enumerate(self.name_addr_mappings):
self.rtl_header.append( self.rtl_header.append(
self.process_yaml( self._process_yaml(
Register.templ_dict['access_wire_comment'], Register.templ_dict['access_wire_comment'],
{'path': name_addr_map[0], {'path': name_addr_map[0],
'alias': '(alias)' if i > 0 else '', 'alias': '(alias)' if i > 0 else '',
@ -360,13 +361,13 @@ class Register(Component):
) )
self.rtl_header.append( self.rtl_header.append(
self.process_yaml( self._process_yaml(
Register.templ_dict[access_wire_assign_field], Register.templ_dict[access_wire_assign_field],
{'path': name_addr_map[0], {'path': name_addr_map[0],
'addr': name_addr_map[1], 'addr': name_addr_map[1],
'genvars': self.genvars_str, 'genvars': self.genvars_str,
'genvars_sum': self.genvars_sum_str, 'genvars_sum': self.genvars_sum_str,
'depth': self.depth, 'depth': self.own_depth,
} }
) )
) )
@ -377,19 +378,19 @@ class Register(Component):
# that is tied to 1'b0 # that is tied to 1'b0
if self.properties['sw_rd']: if self.properties['sw_rd']:
self.rtl_header.append( self.rtl_header.append(
self.process_yaml( self._process_yaml(
Register.templ_dict['read_wire_assign'], Register.templ_dict['read_wire_assign'],
{'path': name_addr_map[0], {'path': name_addr_map[0],
'addr': name_addr_map[1], 'addr': name_addr_map[1],
'genvars': self.genvars_str, 'genvars': self.genvars_str,
'genvars_sum': self.genvars_sum_str, 'genvars_sum': self.genvars_sum_str,
'depth': self.depth, 'depth': self.own_depth,
} }
) )
) )
else: else:
self.rtl_header.append( self.rtl_header.append(
self.process_yaml( self._process_yaml(
Register.templ_dict['read_wire_assign_0'], Register.templ_dict['read_wire_assign_0'],
{'path': name_addr_map[0], {'path': name_addr_map[0],
'genvars': self.genvars_str, 'genvars': self.genvars_str,
@ -403,19 +404,19 @@ class Register(Component):
# that is tied to 1'b0 # that is tied to 1'b0
if self.properties['sw_wr']: if self.properties['sw_wr']:
self.rtl_header.append( self.rtl_header.append(
self.process_yaml( self._process_yaml(
Register.templ_dict['write_wire_assign'], Register.templ_dict['write_wire_assign'],
{'path': name_addr_map[0], {'path': name_addr_map[0],
'addr': name_addr_map[1], 'addr': name_addr_map[1],
'genvars': self.genvars_str, 'genvars': self.genvars_str,
'genvars_sum': self.genvars_sum_str, 'genvars_sum': self.genvars_sum_str,
'depth': self.depth, 'depth': self.own_depth,
} }
) )
) )
else: else:
self.rtl_header.append( self.rtl_header.append(
self.process_yaml( self._process_yaml(
Register.templ_dict['write_wire_assign_0'], Register.templ_dict['write_wire_assign_0'],
{'path': name_addr_map[0], {'path': name_addr_map[0],
'genvars': self.genvars_str, 'genvars': self.genvars_str,
@ -426,7 +427,7 @@ class Register(Component):
# Add combined signal to be used for general access of the register # Add combined signal to be used for general access of the register
if self.properties['swacc']: if self.properties['swacc']:
self.rtl_header.append( self.rtl_header.append(
self.process_yaml( self._process_yaml(
Register.templ_dict['rw_wire_assign_any_alias'], Register.templ_dict['rw_wire_assign_any_alias'],
{'path': self.name_addr_mappings[0][0], {'path': self.name_addr_mappings[0][0],
'genvars': self.genvars_str, 'genvars': self.genvars_str,
@ -484,27 +485,21 @@ class Register(Component):
sys.exit(1) sys.exit(1)
# Add name to list # Add name to list
self.obj.current_idx = [0]
self.name_addr_mappings.append( self.name_addr_mappings.append(
(self.create_underscored_path_static(obj)[3], obj.absolute_address)) (self.create_underscored_path_static(obj)[3], obj.absolute_address))
def __process_variables( def __init_variables(self, glbl_settings: dict):
self,
obj: node.RegNode,
parents_dimensions: list,
parents_stride: list,
glbl_settings: dict):
# Save name
self.obj.current_idx = [0] self.obj.current_idx = [0]
self.name = obj.inst_name
# Save global settings # Save global settings
self.glbl_settings = glbl_settings self.glbl_settings = glbl_settings
# Is this an external register?
self.config['external'] = self.obj.external
# Create mapping between (alias-) name and address # Create mapping between (alias-) name and address
self.name_addr_mappings = [ self.name_addr_mappings = [
(self.create_underscored_path_static(obj)[3], obj.absolute_address) (self.create_underscored_path_static(self.obj)[3], self.obj.absolute_address)
] ]
# Geneate already started? # Geneate already started?
@ -513,42 +508,11 @@ class Register(Component):
# Empty array for mux-input signals # Empty array for mux-input signals
self.sw_mux_assignment_var_name = [] self.sw_mux_assignment_var_name = []
# Determine dimensions of register def __init_genvars(self):
if obj.is_array: super()._init_genvars()
self.sel_arr = 'array'
self.total_array_dimensions = [*parents_dimensions, *self.obj.array_dimensions]
self.array_dimensions = self.obj.array_dimensions
# Merge parent's stride with stride of this regfile. Before doing so, the
# respective stride of the different dimensions shall be calculated
self.total_stride = [
*parents_stride,
*[math.prod(self.array_dimensions[i+1:])
*self.obj.array_stride
for i, _ in enumerate(self.array_dimensions)]
]
else:
self.sel_arr = 'single'
self.total_array_dimensions = parents_dimensions
self.array_dimensions = []
self.total_stride = parents_stride
# How many dimensions were already part of some higher up hierarchy?
self.parents_depths = len(parents_dimensions)
self.total_depth = '[{}]'.format(']['.join(f"{i}" for i in self.total_array_dimensions))
self.total_dimensions = len(self.total_array_dimensions)
self.depth = '[{}]'.format(']['.join(f"{i}" for i in self.array_dimensions))
self.dimensions = len(self.array_dimensions)
# Calculate how many genvars shall be added
genvars = [f"[gv_{chr(97+i)}]" for i in range(self.total_dimensions)]
self.genvars_str = ''.join(genvars)
# Determine value to compare address with # Determine value to compare address with
genvars_sum = [] genvars_sum = []
genvars_sum_vectorized = []
try: try:
for i, stride in enumerate(self.total_stride): for i, stride in enumerate(self.total_stride):
genvars_sum.append(''.join(['gv_', chr(97+i)])) genvars_sum.append(''.join(['gv_', chr(97+i)]))
@ -556,14 +520,7 @@ class Register(Component):
genvars_sum.append(str(stride)) genvars_sum.append(str(stride))
genvars_sum.append("+") genvars_sum.append("+")
genvars_sum_vectorized.append('vec[')
genvars_sum_vectorized.append(str(i))
genvars_sum_vectorized.append(']*')
genvars_sum_vectorized.append(str(stride))
genvars_sum_vectorized.append("+")
genvars_sum.pop() genvars_sum.pop()
genvars_sum_vectorized.pop()
self.logger.debug( self.logger.debug(
f"Multidimensional with dimensions '{self.total_array_dimensions}' " f"Multidimensional with dimensions '{self.total_array_dimensions}' "
@ -577,7 +534,6 @@ class Register(Component):
"Caugt expected IndexError because genvars_sum is empty") "Caugt expected IndexError because genvars_sum is empty")
self.genvars_sum_str = ''.join(genvars_sum) self.genvars_sum_str = ''.join(genvars_sum)
self.genvars_sum_str_vectorized = ''.join(genvars_sum_vectorized)
def get_regwidth(self) -> int: def get_regwidth(self) -> int:
return self.obj.get_property('regwidth') return self.obj.get_property('regwidth')