mirror of
https://github.com/Silicon1602/srdl2sv.git
synced 2024-12-21 22:48:41 +00:00
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:
parent
20cec0c2a3
commit
ec02290bbe
@ -24,22 +24,22 @@ class AddrMap(Component):
|
||||
Loader=yaml.FullLoader)
|
||||
|
||||
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
|
||||
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
|
||||
glbl_settings['generate_active'] = False
|
||||
|
||||
# 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"
|
||||
elif obj.get_property('rsvdsetX'):
|
||||
elif self.obj.get_property('rsvdsetX'):
|
||||
glbl_settings['rsvd_val'] = "x"
|
||||
else:
|
||||
glbl_settings['rsvd_val'] = "0"
|
||||
@ -53,17 +53,28 @@ class AddrMap(Component):
|
||||
self.regwidth = 0
|
||||
|
||||
# Traverse through children
|
||||
for child in obj.children():
|
||||
for child in self.obj.children():
|
||||
if isinstance(child, node.AddrmapNode):
|
||||
# This addressmap opens a completely new scope. For example,
|
||||
# a field_reset does not propagate through to this scope.
|
||||
self.logger.info('Found hierarchical addrmap. Entering it...')
|
||||
self.logger.error('Child addrmaps are not implemented yet!')
|
||||
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
|
||||
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
|
||||
elif isinstance(child, node.RegNode):
|
||||
if child.inst.is_alias:
|
||||
@ -73,7 +84,12 @@ class AddrMap(Component):
|
||||
self.registers[child.inst.alias_primary_inst.inst_name]\
|
||||
.add_alias(child)
|
||||
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
|
||||
|
||||
try:
|
||||
@ -168,9 +184,9 @@ class AddrMap(Component):
|
||||
]
|
||||
|
||||
try:
|
||||
for x in self.get_package_names():
|
||||
for pkg_name in self.__get_package_names():
|
||||
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')
|
||||
@ -243,7 +259,7 @@ class AddrMap(Component):
|
||||
list_of_cases.append(AddrMap.templ_dict['default_mux_case']['rtl'])
|
||||
|
||||
self.rtl_footer.append(
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
AddrMap.templ_dict['read_mux'],
|
||||
{'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"),
|
||||
Loader=yaml.FullLoader)
|
||||
|
||||
return self.process_yaml(
|
||||
return self._process_yaml(
|
||||
self.widget_templ_dict['module_instantiation'],
|
||||
{'bus_width': self.regwidth,
|
||||
'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)
|
||||
|
||||
def get_package_names(self) -> set():
|
||||
def __get_package_names(self) -> set():
|
||||
names = set()
|
||||
|
||||
for register in self.registers.values():
|
||||
@ -387,6 +403,3 @@ class AddrMap(Component):
|
||||
real_tabs)
|
||||
|
||||
return rtl_return
|
||||
|
||||
def get_regwidth(self) -> int:
|
||||
return self.regwidth
|
||||
|
@ -1,6 +1,7 @@
|
||||
import re
|
||||
import math
|
||||
import sys
|
||||
from typing import NamedTuple
|
||||
from typing import NamedTuple, Optional
|
||||
from dataclasses import dataclass
|
||||
|
||||
from systemrdl import node
|
||||
@ -27,7 +28,13 @@ class SWMuxEntryDimensioned():
|
||||
dim: str
|
||||
|
||||
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_footer = []
|
||||
self.children = {}
|
||||
@ -52,6 +59,18 @@ class Component():
|
||||
# Save config
|
||||
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
|
||||
self.properties = {
|
||||
'intr': False,
|
||||
@ -64,11 +83,10 @@ class Component():
|
||||
'sw_wr_wire': False,
|
||||
}
|
||||
|
||||
# Create logger object
|
||||
self.create_logger(self.full_path, config)
|
||||
self.logger.debug(f"Starting to process {self.__class__.__name__} '{obj.inst_name}'")
|
||||
self.genvars_str = ''
|
||||
|
||||
def create_logger(self, name: str, config: dict):
|
||||
|
||||
def __create_logger(self, name: str, config: dict):
|
||||
self.logger = create_logger(
|
||||
name,
|
||||
stream_log_level=config['stream_log_level'],
|
||||
@ -76,6 +94,51 @@ class Component():
|
||||
file_name=config['file_log_location'])
|
||||
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):
|
||||
self.logger.debug("Return reset list")
|
||||
|
||||
@ -145,7 +208,7 @@ class Component():
|
||||
indent_lvl_next = 0
|
||||
|
||||
# Define tab style
|
||||
tab = "\t" if real_tabs else " "
|
||||
tab = "\t" if real_tabs else " "
|
||||
tab = tab_width * tab
|
||||
|
||||
# Define triggers for which the indentation level will increment or
|
||||
@ -190,14 +253,14 @@ class Component():
|
||||
return '\n'.join(rtl_indented)
|
||||
|
||||
@staticmethod
|
||||
def get_underscored_path(path: str, owning_addrmap: str):
|
||||
def __get_underscored_path(path: str, owning_addrmap: str):
|
||||
return path\
|
||||
.replace('[]', '')\
|
||||
.replace(f"{owning_addrmap}.", '')\
|
||||
.replace('.', '__')
|
||||
|
||||
@staticmethod
|
||||
def split_dimensions(path: str):
|
||||
def __split_dimensions(path: str):
|
||||
re_dimensions = re.compile(r'(\[[^]]*\])')
|
||||
new_path = re_dimensions.sub('', path)
|
||||
return (new_path, ''.join(re_dimensions.findall(path)))
|
||||
@ -210,8 +273,8 @@ class Component():
|
||||
except AttributeError:
|
||||
child_obj = obj
|
||||
|
||||
split_name = Component.split_dimensions(
|
||||
Component.get_underscored_path(
|
||||
split_name = self.__split_dimensions(
|
||||
self.__get_underscored_path(
|
||||
child_obj.get_path(),
|
||||
child_obj.owning_addrmap.inst_name)
|
||||
)
|
||||
@ -243,7 +306,7 @@ class Component():
|
||||
|
||||
return ''.join(name)
|
||||
|
||||
def process_yaml(self,
|
||||
def _process_yaml(self,
|
||||
yaml_obj,
|
||||
values: dict = {},
|
||||
skip_signals: bool = False,
|
||||
@ -255,7 +318,8 @@ class Component():
|
||||
|
||||
for signal in yaml_obj['signals']:
|
||||
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:
|
||||
array_dimensions = self.total_array_dimensions
|
||||
|
||||
@ -269,14 +333,15 @@ class Component():
|
||||
if skip_inputs:
|
||||
raise KeyError
|
||||
|
||||
for input in yaml_obj['input_ports']:
|
||||
for input_p in yaml_obj['input_ports']:
|
||||
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:
|
||||
array_dimensions = self.total_array_dimensions
|
||||
|
||||
self.ports['input'][input['name'].format(**values)] =\
|
||||
(input['signal_type'].format(**values),
|
||||
self.ports['input'][input_p['name'].format(**values)] =\
|
||||
(input_p['signal_type'].format(**values),
|
||||
array_dimensions)
|
||||
except (TypeError, KeyError):
|
||||
pass
|
||||
@ -285,14 +350,15 @@ class Component():
|
||||
if skip_outputs:
|
||||
raise KeyError
|
||||
|
||||
for output in yaml_obj['output_ports']:
|
||||
for output_p in yaml_obj['output_ports']:
|
||||
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:
|
||||
array_dimensions = self.total_array_dimensions
|
||||
|
||||
self.ports['output'][output['name'].format(**values)] =\
|
||||
(output['signal_type'].format(**values),
|
||||
self.ports['output'][output_p['name'].format(**values)] =\
|
||||
(output_p['signal_type'].format(**values),
|
||||
array_dimensions)
|
||||
except (TypeError, KeyError):
|
||||
pass
|
||||
@ -300,32 +366,6 @@ class Component():
|
||||
# Return RTL with 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):
|
||||
self.owning_addrmap, self.full_path, self.path, self.path_underscored =\
|
||||
Component.create_underscored_path_static(self.obj)
|
||||
@ -333,7 +373,7 @@ class Component():
|
||||
@staticmethod
|
||||
def create_underscored_path_static(obj):
|
||||
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_underscored = path.replace('.', '__')
|
||||
@ -349,3 +389,6 @@ class Component():
|
||||
)
|
||||
|
||||
return ''
|
||||
|
||||
def get_regwidth(self) -> int:
|
||||
return self.regwidth
|
||||
|
@ -2,6 +2,7 @@ import math
|
||||
|
||||
import importlib.resources as pkg_resources
|
||||
import sys
|
||||
from typing import Optional
|
||||
import yaml
|
||||
|
||||
from systemrdl.node import FieldNode, SignalNode
|
||||
@ -21,16 +22,22 @@ class Field(Component):
|
||||
def __init__(
|
||||
self,
|
||||
obj: FieldNode,
|
||||
array_dimensions: list,
|
||||
config:dict,
|
||||
glbl_settings: dict):
|
||||
super().__init__(obj, config)
|
||||
parents_dimensions: Optional[list],
|
||||
config: dict):
|
||||
super().__init__(
|
||||
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
|
||||
self.__process_variables(obj, array_dimensions, glbl_settings)
|
||||
self.__init_variables(obj)
|
||||
|
||||
# Determine field types
|
||||
self.__process_fieldtype()
|
||||
self.__init_fieldtype()
|
||||
|
||||
##################################################################################
|
||||
# LIMITATION:
|
||||
@ -39,7 +46,7 @@ class Field(Component):
|
||||
# can be found here: https://github.com/SystemRDL/systemrdl-compiler/issues/51
|
||||
##################################################################################
|
||||
# Print a summary
|
||||
self.rtl_header.append(self.summary())
|
||||
self.rtl_header.append(self.__summary())
|
||||
|
||||
# Add description
|
||||
self.rtl_header.append(self.get_description())
|
||||
@ -87,7 +94,7 @@ class Field(Component):
|
||||
|
||||
if isinstance(swwe, (FieldNode, SignalNode)):
|
||||
access_rtl['sw_write'][0].append(
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Field.templ_dict['sw_access_field_swwe'],
|
||||
{'path_wo_field': path_wo_field,
|
||||
'genvars': self.genvars_str,
|
||||
@ -97,7 +104,7 @@ class Field(Component):
|
||||
)
|
||||
elif isinstance(swwel, (FieldNode, SignalNode)):
|
||||
access_rtl['sw_write'][0].append(
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Field.templ_dict['sw_access_field_swwel'],
|
||||
{'path_wo_field': path_wo_field,
|
||||
'genvars': self.genvars_str,
|
||||
@ -107,7 +114,7 @@ class Field(Component):
|
||||
)
|
||||
else:
|
||||
access_rtl['sw_write'][0].append(
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Field.templ_dict['sw_access_field'],
|
||||
{'path_wo_field': path_wo_field,
|
||||
'genvars': self.genvars_str,
|
||||
@ -123,7 +130,7 @@ class Field(Component):
|
||||
self.logger.warning("The OnWriteType.wuser is not yet supported!")
|
||||
elif onwrite in (OnWriteType.wclr, OnWriteType.wset):
|
||||
access_rtl['sw_write'][0].append(
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Field.templ_dict[str(onwrite)],
|
||||
{'path': path_underscored,
|
||||
'genvars': self.genvars_str,
|
||||
@ -139,7 +146,7 @@ class Field(Component):
|
||||
lsb_bus = 8*i if i != self.lsbyte else obj.inst.lsb
|
||||
|
||||
access_rtl['sw_write'][0].append(
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Field.templ_dict[str(onwrite)],
|
||||
{'path': path_underscored,
|
||||
'genvars': self.genvars_str,
|
||||
@ -161,7 +168,7 @@ class Field(Component):
|
||||
lsb_bus = 8*i if i != self.lsbyte else obj.inst.lsb
|
||||
|
||||
access_rtl['sw_write'][0].append(
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Field.templ_dict['sw_access_byte'],
|
||||
{'path': self.path_underscored,
|
||||
'genvars': self.genvars_str,
|
||||
@ -192,7 +199,7 @@ class Field(Component):
|
||||
self.properties['sw_rd_wire'] = True
|
||||
|
||||
access_rtl['sw_read'][0].append(
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Field.templ_dict[str(onread)],
|
||||
{'width': obj.width,
|
||||
'path': path_underscored,
|
||||
@ -205,7 +212,7 @@ class Field(Component):
|
||||
# Property cannot be overwritten by alias
|
||||
if obj.get_property('singlepulse'):
|
||||
self.access_rtl['singlepulse'] = ([
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Field.templ_dict['singlepulse'],
|
||||
{'path': self.path_underscored,
|
||||
'genvars': self.genvars_str}
|
||||
@ -297,7 +304,7 @@ class Field(Component):
|
||||
incr_width_input = True
|
||||
|
||||
# Doesn't return RTL, only adds input port
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Field.templ_dict['counter_incr_val_input'],
|
||||
{'path': self.path_underscored,
|
||||
'genvars': self.genvars_str,
|
||||
@ -339,7 +346,7 @@ class Field(Component):
|
||||
# an internal signal. It is possible that this is tied to 0.
|
||||
if not incr_width_input:
|
||||
self.rtl_footer.append(
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Field.templ_dict['counter_internal_incr_val_signal'],
|
||||
{'path': self.path_underscored,
|
||||
'genvars': self.genvars_str,
|
||||
@ -365,7 +372,7 @@ class Field(Component):
|
||||
decr_width_input = True
|
||||
|
||||
# Doesn't return RTL, only adds input port
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Field.templ_dict['counter_decr_val_input'],
|
||||
{'path': self.path_underscored,
|
||||
'genvars': self.genvars_str,
|
||||
@ -407,7 +414,7 @@ class Field(Component):
|
||||
# an internal signal. It is possible that this is tied to 0.
|
||||
if not decr_width_input:
|
||||
self.rtl_footer.append(
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Field.templ_dict['counter_internal_decr_val_signal'],
|
||||
{'path': self.path_underscored,
|
||||
'genvars': self.genvars_str,
|
||||
@ -432,13 +439,13 @@ class Field(Component):
|
||||
|
||||
if not incr:
|
||||
# Will only add input port but not return any RTL
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Field.templ_dict['counter_incr_input'],
|
||||
{'path': self.path_underscored}
|
||||
)
|
||||
else:
|
||||
self.rtl_footer.append(
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Field.templ_dict['counter_internal_incr_signal'],
|
||||
{'path': self.path_underscored,
|
||||
'genvars': self.genvars_str,
|
||||
@ -459,7 +466,7 @@ class Field(Component):
|
||||
else:
|
||||
# Tie signal to 0
|
||||
self.rtl_footer.append(
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Field.templ_dict['counter_internal_incr_signal'],
|
||||
{'path': self.path_underscored,
|
||||
'genvars': self.genvars_str,
|
||||
@ -473,13 +480,13 @@ class Field(Component):
|
||||
|
||||
if not self.obj.get_property('decr'):
|
||||
# Will only add input port but not return any RTL
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Field.templ_dict['counter_decr_input'],
|
||||
{'path': self.path_underscored}
|
||||
)
|
||||
else:
|
||||
self.rtl_footer.append(
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Field.templ_dict['counter_internal_decr_signal'],
|
||||
{'path': self.path_underscored,
|
||||
'genvars': self.genvars_str,
|
||||
@ -500,7 +507,7 @@ class Field(Component):
|
||||
else:
|
||||
# Tie signal to 0
|
||||
self.rtl_footer.append(
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Field.templ_dict['counter_internal_decr_signal'],
|
||||
{'path': self.path_underscored,
|
||||
'genvars': self.genvars_str,
|
||||
@ -512,7 +519,7 @@ class Field(Component):
|
||||
# Handle saturation signals
|
||||
if not incr_sat_value:
|
||||
self.rtl_footer.append(
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Field.templ_dict['counter_incr_sat_tied'],
|
||||
{'path': self.path_underscored,
|
||||
'genvars': self.genvars_str,
|
||||
@ -521,7 +528,7 @@ class Field(Component):
|
||||
)
|
||||
else:
|
||||
self.rtl_footer.append(
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Field.templ_dict['counter_incr_sat'],
|
||||
{'path': self.path_underscored,
|
||||
'genvars': self.genvars_str,
|
||||
@ -534,7 +541,7 @@ class Field(Component):
|
||||
|
||||
if not decr_sat_value:
|
||||
self.rtl_footer.append(
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Field.templ_dict['counter_decr_sat_tied'],
|
||||
{'path': self.path_underscored,
|
||||
'genvars': self.genvars_str,
|
||||
@ -543,7 +550,7 @@ class Field(Component):
|
||||
)
|
||||
else:
|
||||
self.rtl_footer.append(
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Field.templ_dict['counter_decr_sat'],
|
||||
{'path': self.path_underscored,
|
||||
'genvars': self.genvars_str,
|
||||
@ -560,7 +567,7 @@ class Field(Component):
|
||||
|
||||
if incr_thr_value:
|
||||
self.rtl_footer.append(
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Field.templ_dict['counter_incr_thr'],
|
||||
{'path': self.path_underscored,
|
||||
'genvars': self.genvars_str,
|
||||
@ -573,7 +580,7 @@ class Field(Component):
|
||||
|
||||
if decr_thr_value:
|
||||
self.rtl_footer.append(
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Field.templ_dict['counter_decr_thr'],
|
||||
{'path': self.path_underscored,
|
||||
'genvars': self.genvars_str,
|
||||
@ -587,7 +594,7 @@ class Field(Component):
|
||||
# Handle overflow & underflow signals
|
||||
if self.obj.get_property('overflow'):
|
||||
self.rtl_footer.append(
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Field.templ_dict['counter_overflow'],
|
||||
{'path': self.path_underscored,
|
||||
'genvars': self.genvars_str,
|
||||
@ -600,7 +607,7 @@ class Field(Component):
|
||||
|
||||
if self.obj.get_property('underflow'):
|
||||
self.rtl_footer.append(
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Field.templ_dict['counter_underflow'],
|
||||
{'path': self.path_underscored,
|
||||
'genvars': self.genvars_str,
|
||||
@ -613,7 +620,7 @@ class Field(Component):
|
||||
|
||||
# Implement actual counter logic
|
||||
self.rtl_footer.append(
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Field.templ_dict['counter'],
|
||||
{'path': self.path_underscored,
|
||||
'genvars': self.genvars_str,
|
||||
@ -621,8 +628,6 @@ class Field(Component):
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
|
||||
def __add_swmod_swacc(self):
|
||||
if self.obj.get_property('swmod'):
|
||||
self.logger.debug("Field has swmod property")
|
||||
@ -632,7 +637,7 @@ class Field(Component):
|
||||
# Check if read side-effects are defined.
|
||||
if self.obj.get_property('onread'):
|
||||
swmod_assigns.append(
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Field.templ_dict['swmod_assign'],
|
||||
{'path': self.path_underscored,
|
||||
'path_wo_field': self.path_wo_field,
|
||||
@ -648,7 +653,7 @@ class Field(Component):
|
||||
# Check if SW has write access to the field
|
||||
if self.properties['sw_wr']:
|
||||
swmod_assigns.append(
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Field.templ_dict['swmod_assign'],
|
||||
{'path': self.path_underscored,
|
||||
'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'],
|
||||
{'path': self.path_underscored,
|
||||
'genvars': self.genvars_str,
|
||||
@ -683,7 +688,7 @@ class Field(Component):
|
||||
self.properties['sw_wr_wire'] = True
|
||||
self.properties['sw_rd_wire'] = True
|
||||
|
||||
swacc_props = self.process_yaml(
|
||||
swacc_props = self._process_yaml(
|
||||
Field.templ_dict['swacc_assign'],
|
||||
{'path': self.path_underscored,
|
||||
'path_wo_field': self.path_wo_field,
|
||||
@ -719,7 +724,7 @@ class Field(Component):
|
||||
trigger_signal = self.get_signal_name(next_val)
|
||||
else:
|
||||
trigger_signal =\
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Field.templ_dict['trigger_input'],
|
||||
{'path': self.path_underscored,
|
||||
'field_type': self.field_type,
|
||||
@ -728,7 +733,7 @@ class Field(Component):
|
||||
|
||||
if bit_type:
|
||||
self.access_rtl['hw_write'] = ([
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Field.templ_dict[bit_type],
|
||||
{'path': self.path_underscored,
|
||||
'genvars': self.genvars_str,
|
||||
@ -741,7 +746,7 @@ class Field(Component):
|
||||
False)
|
||||
|
||||
self.rtl_footer.append(
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Field.templ_dict[str(latch_signal)],
|
||||
{'trigger_signal': trigger_signal,
|
||||
'path': self.path_underscored,
|
||||
@ -753,7 +758,6 @@ class Field(Component):
|
||||
|
||||
return (bit_type, trigger_signal)
|
||||
|
||||
|
||||
def __add_interrupt(self):
|
||||
if self.obj.get_property('intr'):
|
||||
|
||||
@ -789,7 +793,7 @@ class Field(Component):
|
||||
if intr_type != InterruptType.level:
|
||||
if self.rst['name']:
|
||||
reset_intr_header = \
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Field.templ_dict['rst_intr_header'],
|
||||
{'trigger_signal': trigger_signal,
|
||||
'rst_name': self.rst['name'],
|
||||
@ -802,7 +806,7 @@ class Field(Component):
|
||||
reset_intr_header = ""
|
||||
|
||||
self.rtl_footer.append(
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Field.templ_dict['always_ff_block_intr'],
|
||||
{'trigger_signal': trigger_signal,
|
||||
'always_ff_header': self.always_ff_header,
|
||||
@ -816,7 +820,7 @@ class Field(Component):
|
||||
|
||||
else:
|
||||
self.access_rtl['hw_write'] = ([
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Field.templ_dict['nonsticky_intr'],
|
||||
{'path': self.path_underscored,
|
||||
'assignment': trigger_signal,
|
||||
@ -878,7 +882,7 @@ class Field(Component):
|
||||
|
||||
if enable_mask:
|
||||
enable_mask_start_rtl = \
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Field.templ_dict['hw_enable_mask_start'],
|
||||
{'signal': self.get_signal_name(enable_mask),
|
||||
'width': self.obj.width,
|
||||
@ -886,7 +890,7 @@ class Field(Component):
|
||||
)
|
||||
|
||||
enable_mask_end_rtl = \
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Field.templ_dict['hw_enable_mask_end'],
|
||||
{'width': self.obj.width}
|
||||
)
|
||||
@ -904,7 +908,7 @@ class Field(Component):
|
||||
self.logger.info(f"Found {sticky} property.")
|
||||
elif self.obj.get_property('counter'):
|
||||
self.access_rtl['hw_write'] = ([
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Field.templ_dict['hw_access_counter'],
|
||||
{'path': self.path_underscored,
|
||||
'genvars': self.genvars_str,
|
||||
@ -920,7 +924,7 @@ class Field(Component):
|
||||
|
||||
# if-line of hw-access
|
||||
self.access_rtl['hw_write'] = ([
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Field.templ_dict[write_condition],
|
||||
{'negl': '!' if self.obj.get_property('wel') else '',
|
||||
'path': self.path_underscored,
|
||||
@ -948,7 +952,7 @@ class Field(Component):
|
||||
|
||||
# No special property. Assign input to register
|
||||
assignment = \
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Field.templ_dict['hw_access_field__assignment__input'],
|
||||
{'path': self.path_underscored,
|
||||
'genvars': self.genvars_str,
|
||||
@ -957,7 +961,7 @@ class Field(Component):
|
||||
)
|
||||
|
||||
self.access_rtl['hw_write'][0].append(
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Field.templ_dict['hw_access_field'],
|
||||
{'path': self.path_underscored,
|
||||
'genvars': self.genvars_str,
|
||||
@ -975,7 +979,7 @@ class Field(Component):
|
||||
# Check if the hwset or hwclr option is set
|
||||
if self.obj.get_property('hwset'):
|
||||
self.access_rtl['hw_setclr'] = ([
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Field.templ_dict['hw_access_hwset'],
|
||||
{'path': self.path_underscored,
|
||||
'genvars': self.genvars_str,
|
||||
@ -990,7 +994,7 @@ class Field(Component):
|
||||
False)
|
||||
elif self.obj.get_property('hwclr'):
|
||||
self.access_rtl['hw_setclr'] = ([
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Field.templ_dict['hw_access_hwclr'],
|
||||
{'path': self.path_underscored,
|
||||
'genvars': self.genvars_str,
|
||||
@ -1010,7 +1014,7 @@ class Field(Component):
|
||||
if self.obj.get_property('hw') in (AccessType.rw, AccessType.r):
|
||||
# Connect flops to output port
|
||||
self.rtl_footer.append(
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Field.templ_dict['out_port_assign'],
|
||||
{'genvars': self.genvars_str,
|
||||
'path': self.path_underscored,
|
||||
@ -1038,7 +1042,7 @@ class Field(Component):
|
||||
width = width)
|
||||
)
|
||||
|
||||
self.rtl_footer.append(self.process_yaml(
|
||||
self.rtl_footer.append(self._process_yaml(
|
||||
Field.templ_dict['external_wr_assignments'],
|
||||
{'path': alias,
|
||||
'path_wo_field': self.path_wo_field_vec[i],
|
||||
@ -1053,7 +1057,7 @@ class Field(Component):
|
||||
|
||||
if self.properties['sw_rd']:
|
||||
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'],
|
||||
{'path': alias,
|
||||
'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.append(
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Field.templ_dict['end_field_ff'],
|
||||
{'path': self.path_underscored}
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def __add_combo(self):
|
||||
operations = []
|
||||
if self.obj.get_property('anded'):
|
||||
@ -1144,7 +1147,7 @@ class Field(Component):
|
||||
|
||||
if len(operations) > 0:
|
||||
self.rtl_footer.append(
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Field.templ_dict['combo_operation_comment'],
|
||||
{'path': self.path_underscored}
|
||||
)
|
||||
@ -1152,7 +1155,7 @@ class Field(Component):
|
||||
|
||||
self.rtl_footer = [
|
||||
*self.rtl_footer,
|
||||
*[self.process_yaml(
|
||||
*[self._process_yaml(
|
||||
Field.templ_dict[i[1]],
|
||||
{'path': self.path_underscored,
|
||||
'genvars': self.genvars_str,
|
||||
@ -1161,8 +1164,7 @@ class Field(Component):
|
||||
) for i in operations]
|
||||
]
|
||||
|
||||
|
||||
def __process_fieldtype(self):
|
||||
def __init_fieldtype(self):
|
||||
try:
|
||||
if not self.config['enums']:
|
||||
raise AttributeError
|
||||
@ -1226,7 +1228,9 @@ class Field(Component):
|
||||
# the field has a simple width
|
||||
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
|
||||
self.path_wo_field = '__'.join(self.path.split('.', -1)[0:-1])
|
||||
self.register_name = ''.join([self.path_underscored, '_q'])
|
||||
@ -1242,15 +1246,6 @@ class Field(Component):
|
||||
# is always required
|
||||
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
|
||||
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,
|
||||
# the reset value, and whether the field actually has a reset
|
||||
self.rst = Field.process_reset_signal(
|
||||
obj.get_property("resetsignal"))
|
||||
self.rst = Field.__process_reset_signal(obj.get_property("resetsignal"))
|
||||
|
||||
if 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[''] = ([''], False)
|
||||
|
||||
def summary(self):
|
||||
def __summary(self):
|
||||
# Additional flags that are set
|
||||
# Use list, rather than set, to ensure the order stays the same
|
||||
# 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'
|
||||
|
||||
self.always_ff_header = \
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Field.templ_dict[sense_list],
|
||||
{'rst_edge': self.rst['edge'],
|
||||
'rst_name': self.rst['name']}
|
||||
@ -1337,7 +1331,7 @@ class Field(Component):
|
||||
# Add actual reset line
|
||||
if self.rst['name']:
|
||||
self.rtl_header.append(
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Field.templ_dict['rst_field_assign'],
|
||||
{'path': self.path_underscored,
|
||||
'rst_name': self.rst['name'],
|
||||
@ -1377,3 +1371,31 @@ class Field(Component):
|
||||
self.logger.error("It's not possible to combine the sticky(bit) "\
|
||||
"property with the counter property. The counter property "\
|
||||
"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
|
||||
|
||||
|
@ -21,13 +21,16 @@ class Memory(Component):
|
||||
self,
|
||||
obj: node.RegfileNode,
|
||||
parents_dimensions: list,
|
||||
parents_stride: list,
|
||||
config: dict,
|
||||
glbl_settings: dict):
|
||||
super().__init__(obj, config)
|
||||
parents_strides: list,
|
||||
config: dict):
|
||||
super().__init__(
|
||||
obj=obj,
|
||||
config=config,
|
||||
parents_strides=parents_strides,
|
||||
parents_dimensions=parents_dimensions)
|
||||
|
||||
# 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
|
||||
self.obj.current_idx = [0]
|
||||
@ -37,7 +40,7 @@ class Memory(Component):
|
||||
# fixed memory block
|
||||
|
||||
self.rtl_header.append(
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Memory.templ_dict['memory_adr_assignments'],
|
||||
{'path': self.path_underscored,
|
||||
'bytes_w': int(self.get_regwidth() / 8),
|
||||
@ -50,7 +53,7 @@ class Memory(Component):
|
||||
|
||||
if obj.get_property('sw') in (AccessType.rw, AccessType.r):
|
||||
self.rtl_header.append(
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Memory.templ_dict['memory_rd_assignments'],
|
||||
{'path': self.path_underscored,
|
||||
'data_w': self.get_regwidth() - 1,
|
||||
@ -60,7 +63,7 @@ class Memory(Component):
|
||||
|
||||
if obj.get_property('sw') in (AccessType.rw, AccessType.w):
|
||||
self.rtl_header.append(
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Memory.templ_dict['memory_wr_assignments'],
|
||||
{'path': self.path_underscored,
|
||||
'data_w': self.get_regwidth() - 1,
|
||||
@ -78,7 +81,7 @@ class Memory(Component):
|
||||
# Create comment and provide user information about register he/she
|
||||
# is looking at. Also add a description, if applicable
|
||||
self.rtl_header = [
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
self.templ_dict['mem_comment'],
|
||||
{'inst_name': obj.inst_name,
|
||||
'type_name': obj.type_name,
|
||||
@ -91,26 +94,20 @@ class Memory(Component):
|
||||
*self.rtl_header
|
||||
]
|
||||
|
||||
def __process_variables(self,
|
||||
obj: node.RegfileNode,
|
||||
parents_dimensions: list,
|
||||
parents_stride: list,
|
||||
glbl_settings: dict):
|
||||
|
||||
self.mementries = obj.get_property('mementries')
|
||||
self.memwidth = obj.get_property('memwidth')
|
||||
def _init_variables(self):
|
||||
self.mementries = self.obj.get_property('mementries')
|
||||
self.memwidth = self.obj.get_property('memwidth')
|
||||
self.addr_w = self.mementries.bit_length()
|
||||
|
||||
|
||||
def sanity_checks(self):
|
||||
if not math.log2(self.memwidth).is_integer():
|
||||
self.logger.fatal( "The defined memory width must be a power of 2. "\
|
||||
f"it is now defined as '{self.memwidth}'")
|
||||
sys.exit(1)
|
||||
|
||||
# Determine dimensions of register
|
||||
if obj.is_array:
|
||||
self.total_array_dimensions = [*parents_dimensions, *self.obj.array_dimensions]
|
||||
self.array_dimensions = self.obj.array_dimensions
|
||||
|
||||
if self.obj.is_array:
|
||||
self.logger.warning("The memory is defined as array. The compiler not not "\
|
||||
"provide any hooks to help here and expects that the user "\
|
||||
"handles this outside of the memory block.")
|
||||
@ -122,29 +119,21 @@ class Memory(Component):
|
||||
f"{int(self.mementries * self.memwidth / 8)}). This must be "\
|
||||
"kept in mind when hooking up the memory interface to an "\
|
||||
"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):
|
||||
# Create list of mux-inputs to later be picked up by carrying addrmap
|
||||
self.sw_mux_assignment_var_name = \
|
||||
SWMuxEntry (
|
||||
data_wire = self.process_yaml(
|
||||
data_wire = self._process_yaml(
|
||||
Memory.templ_dict['sw_data_assignment_var_name'],
|
||||
{'path': self.path_underscored,
|
||||
'accesswidth': self.memwidth - 1}
|
||||
),
|
||||
rdy_wire = self.process_yaml(
|
||||
rdy_wire = self._process_yaml(
|
||||
Memory.templ_dict['sw_rdy_assignment_var_name'],
|
||||
{'path': self.path_underscored}
|
||||
),
|
||||
err_wire = self.process_yaml(
|
||||
err_wire = self._process_yaml(
|
||||
Memory.templ_dict['sw_err_assignment_var_name'],
|
||||
{'path': self.path_underscored}
|
||||
),
|
||||
@ -159,7 +148,7 @@ class Memory(Component):
|
||||
access_type = 'sw_data_assignment_wo'
|
||||
|
||||
self.rtl_footer = [
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
self.templ_dict[access_type],
|
||||
{'path': self.path_underscored,
|
||||
'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):
|
||||
# Add wire/register instantiations
|
||||
self.rtl_header = [
|
||||
@ -204,3 +190,6 @@ class Memory(Component):
|
||||
[str(y) for y in value[1]]))
|
||||
if value[1] else '')
|
||||
for (key, value) in dict_list]
|
||||
|
||||
def get_regwidth(self) -> int:
|
||||
return self.memwidth
|
||||
|
@ -3,6 +3,8 @@ import sys
|
||||
import math
|
||||
import yaml
|
||||
|
||||
from typing import Optional
|
||||
|
||||
from systemrdl import node
|
||||
from systemrdl.node import FieldNode
|
||||
|
||||
@ -21,15 +23,15 @@ class RegFile(Component):
|
||||
def __init__(
|
||||
self,
|
||||
obj: node.RegfileNode,
|
||||
parents_dimensions: list,
|
||||
parents_stride: list,
|
||||
config: dict,
|
||||
config: dict,
|
||||
parents_dimensions: Optional[list],
|
||||
parents_strides: Optional[list],
|
||||
glbl_settings: dict):
|
||||
super().__init__(obj, config)
|
||||
|
||||
# Save and/or process important variables
|
||||
self.__process_variables(obj, parents_dimensions, parents_stride)
|
||||
|
||||
super().__init__(
|
||||
obj=obj,
|
||||
config=config,
|
||||
parents_strides=parents_strides,
|
||||
parents_dimensions=parents_dimensions)
|
||||
|
||||
# Empty dictionary of register objects
|
||||
# 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]
|
||||
|
||||
# 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
|
||||
glbl_settings['generate_active'] = True
|
||||
else:
|
||||
@ -60,11 +62,11 @@ class RegFile(Component):
|
||||
self.obj.current_idx = [0]
|
||||
|
||||
new_child = RegFile(
|
||||
child,
|
||||
self.total_array_dimensions,
|
||||
self.total_stride,
|
||||
config,
|
||||
glbl_settings)
|
||||
obj=child,
|
||||
parents_dimensions=self.total_array_dimensions,
|
||||
parents_strides=self.total_stride,
|
||||
config=config,
|
||||
glbl_settings=glbl_settings)
|
||||
self.regfiles[child.inst_name] = new_child
|
||||
elif isinstance(child, node.RegNode):
|
||||
if child.inst.is_alias:
|
||||
@ -76,11 +78,11 @@ class RegFile(Component):
|
||||
else:
|
||||
self.obj.current_idx = [0]
|
||||
new_child = Register(
|
||||
child,
|
||||
self.total_array_dimensions,
|
||||
self.total_stride,
|
||||
config,
|
||||
glbl_settings)
|
||||
obj=child,
|
||||
parents_dimensions=self.total_array_dimensions,
|
||||
parents_strides=self.total_stride,
|
||||
config=config,
|
||||
glbl_settings=glbl_settings)
|
||||
self.registers[child.inst_name] = new_child
|
||||
|
||||
try:
|
||||
@ -115,30 +117,30 @@ class RegFile(Component):
|
||||
# Create comment and provide user information about register he/she
|
||||
# is looking at.
|
||||
self.rtl_header = [
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
RegFile.templ_dict['regfile_comment'],
|
||||
{'name': obj.inst_name,
|
||||
'dimensions': self.dimensions,
|
||||
'depth': self.depth}
|
||||
'dimensions': self.own_dimensions,
|
||||
'depth': self.own_depth}
|
||||
),
|
||||
*self.rtl_header
|
||||
]
|
||||
|
||||
# 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.process_yaml(
|
||||
self._process_yaml(
|
||||
RegFile.templ_dict['generate_for_end'],
|
||||
{'dimension': ''.join(['gv_', chr(97+i)])}
|
||||
)
|
||||
)
|
||||
|
||||
for i in range(self.dimensions):
|
||||
for i in range(self.own_dimensions):
|
||||
self.rtl_header.append(
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
RegFile.templ_dict['generate_for_start'],
|
||||
{'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("")
|
||||
|
||||
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):
|
||||
for i in self.children.values():
|
||||
yield from i.create_mux_string()
|
||||
|
||||
def get_signal_instantiations_list(self) -> set():
|
||||
instantiations = list()
|
||||
instantiations = []
|
||||
|
||||
for i in self.children.values():
|
||||
if isinstance(i, Register):
|
||||
instantiations.append("\n// Variables of register '{}'".format(i.name))
|
||||
instantiations = [*instantiations, *i.get_signal_instantiations_list()]
|
||||
for child in self.children.values():
|
||||
if isinstance(child, Register):
|
||||
instantiations.append(f"\n// Variables of register '{child.name}'")
|
||||
instantiations = [*instantiations, *child.get_signal_instantiations_list()]
|
||||
|
||||
return instantiations
|
||||
|
||||
def get_package_names(self) -> set():
|
||||
names = set()
|
||||
|
||||
for i in self.registers.values():
|
||||
for key, value in i.get_typedefs().items():
|
||||
names.add(value.scope)
|
||||
for register in self.registers.values():
|
||||
for typedef in register.get_typedefs().values():
|
||||
names.add(typedef.scope)
|
||||
|
||||
return names
|
||||
|
||||
def get_package_rtl(self) -> dict():
|
||||
def get_package_rtl(self) -> {}:
|
||||
if not self.config['enums']:
|
||||
return None
|
||||
|
||||
# First go through all registers in this scope to generate a package
|
||||
package_rtl = []
|
||||
enum_rtl = {}
|
||||
rtl_return = []
|
||||
|
||||
# Need to keep track of enum names since they shall be unique
|
||||
# per scope
|
||||
enum_members = {}
|
||||
|
||||
for i in self.registers.values():
|
||||
for key, value in i.get_typedefs().items():
|
||||
for register in self.registers.values():
|
||||
for key, value in register.get_typedefs().items():
|
||||
if value.scope not in enum_rtl:
|
||||
enum_rtl[value.scope] = []
|
||||
|
||||
@ -237,18 +199,15 @@ class RegFile(Component):
|
||||
enum_members[var[0]] = "::".join([self.name, key])
|
||||
else:
|
||||
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"\
|
||||
" -- 1st occurance: '{}'\n"\
|
||||
" -- 2nd occurance: '{}'\n\n"\
|
||||
f" -- 1st occurance: '{enum_members[var[0]]}'\n"\
|
||||
f" -- 2nd occurance: '{'::'.join([self.name, key])}'\n\n"\
|
||||
"This is not legal because all these enums will be defined "\
|
||||
"in the same SystemVerilog scope. To share the same enum among "\
|
||||
"different registers, define them on a higher level in the "\
|
||||
"hierarchy.\n\n"\
|
||||
"Exiting...".format(
|
||||
var[0],
|
||||
enum_members[var[0]],
|
||||
"::".join([value.scope, key])))
|
||||
"Exiting...")
|
||||
|
||||
sys.exit(1)
|
||||
|
||||
@ -266,6 +225,3 @@ class RegFile(Component):
|
||||
enum_var_list = ',\n'.join(variable_list)))
|
||||
|
||||
return enum_rtl
|
||||
|
||||
def get_regwidth(self) -> int:
|
||||
return self.regwidth
|
||||
|
@ -1,6 +1,6 @@
|
||||
import importlib.resources as pkg_resources
|
||||
import math
|
||||
import sys
|
||||
from typing import Optional
|
||||
import yaml
|
||||
|
||||
from systemrdl import node
|
||||
@ -19,27 +19,31 @@ class Register(Component):
|
||||
def __init__(
|
||||
self,
|
||||
obj: node.RegNode,
|
||||
parents_dimensions: list,
|
||||
parents_stride: list,
|
||||
config: dict,
|
||||
parents_dimensions: Optional[list],
|
||||
parents_strides: Optional[list],
|
||||
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
|
||||
self.__process_variables(obj, parents_dimensions, parents_stride, glbl_settings)
|
||||
# Generate all variables that have anything to do with dimensions or strides
|
||||
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
|
||||
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
|
||||
# change when using an alias
|
||||
field_range = ':'.join(map(str, [field.msb, field.lsb]))
|
||||
|
||||
self.children[field_range] = Field(field,
|
||||
self.total_array_dimensions,
|
||||
self.config,
|
||||
glbl_settings)
|
||||
self.config)
|
||||
|
||||
# Get properties from field that apply to whole register
|
||||
for key in self.properties:
|
||||
@ -58,15 +62,15 @@ class Register(Component):
|
||||
child.create_internal_rtl()
|
||||
|
||||
# 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")
|
||||
|
||||
# Add N layers of for-loop starts
|
||||
for i in range(self.dimensions):
|
||||
for i in range(self.own_dimensions):
|
||||
self.rtl_header.append(
|
||||
Register.templ_dict['generate_for_start'].format(
|
||||
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
|
||||
self.__add_address_decoder()
|
||||
@ -80,12 +84,12 @@ class Register(Component):
|
||||
self.__add_sw_mux_assignments()
|
||||
|
||||
# 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(
|
||||
Register.templ_dict['generate_for_end'].format(
|
||||
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")
|
||||
|
||||
# Add wire instantiation
|
||||
@ -104,8 +108,8 @@ class Register(Component):
|
||||
self.rtl_header = [
|
||||
Register.templ_dict['reg_comment'].format(
|
||||
name = self.obj.inst_name,
|
||||
dimensions = self.dimensions,
|
||||
depth = self.depth),
|
||||
dimensions = self.own_dimensions,
|
||||
depth = self.own_depth),
|
||||
*self.rtl_header
|
||||
]
|
||||
|
||||
@ -121,7 +125,7 @@ class Register(Component):
|
||||
self.rtl_footer.append(Register.templ_dict['interrupt_comment']['rtl'])
|
||||
|
||||
self.rtl_footer.append(
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Register.templ_dict['interrupt_intr'],
|
||||
{'path': self.path_underscored,
|
||||
'genvars': self.genvars_str,
|
||||
@ -133,7 +137,7 @@ class Register(Component):
|
||||
|
||||
if self.properties['halt']:
|
||||
self.rtl_footer.append(
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Register.templ_dict['interrupt_halt'],
|
||||
{'path': self.path_underscored,
|
||||
'genvars': self.genvars_str,
|
||||
@ -189,16 +193,16 @@ class Register(Component):
|
||||
# Create list of mux-inputs to later be picked up by carrying addrmap
|
||||
self.sw_mux_assignment_var_name.append(
|
||||
SWMuxEntry(
|
||||
data_wire = self.process_yaml(
|
||||
data_wire = self._process_yaml(
|
||||
Register.templ_dict['sw_data_assignment_var_name'],
|
||||
{'path': na_map[0],
|
||||
'accesswidth': accesswidth}
|
||||
),
|
||||
rdy_wire = self.process_yaml(
|
||||
rdy_wire = self._process_yaml(
|
||||
Register.templ_dict['sw_rdy_assignment_var_name'],
|
||||
{'path': na_map[0]}
|
||||
),
|
||||
err_wire = self.process_yaml(
|
||||
err_wire = self._process_yaml(
|
||||
Register.templ_dict['sw_err_assignment_var_name'],
|
||||
{'path': na_map[0]}
|
||||
),
|
||||
@ -216,7 +220,7 @@ class Register(Component):
|
||||
|
||||
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'],
|
||||
{'rd_byte_list_ored':
|
||||
' || '.join(bytes_read_format) if bytes_read else "1'b0",
|
||||
@ -228,7 +232,7 @@ class Register(Component):
|
||||
if self.config['external']:
|
||||
if bytes_read:
|
||||
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'],
|
||||
{'path': '__'.join([na_map[0], field.name]),
|
||||
'genvars': self.genvars_str,
|
||||
@ -238,7 +242,7 @@ class Register(Component):
|
||||
|
||||
if bytes_written:
|
||||
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'],
|
||||
{'path': '__'.join([na_map[0], field.name]),
|
||||
'genvars': self.genvars_str,
|
||||
@ -255,7 +259,7 @@ class Register(Component):
|
||||
sw_rdy_condition_vec = ['(']
|
||||
|
||||
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'],
|
||||
{'path': '__'.join([na_map[0], field.name]),
|
||||
'genvars': self.genvars_str,
|
||||
@ -275,7 +279,7 @@ class Register(Component):
|
||||
sw_rdy_condition_vec.append('(')
|
||||
|
||||
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'],
|
||||
{'path': '__'.join([na_map[0], field.name]),
|
||||
'genvars': self.genvars_str,
|
||||
@ -294,7 +298,7 @@ class Register(Component):
|
||||
|
||||
# Assign all values
|
||||
self.rtl_footer.append(
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Register.templ_dict['sw_data_assignment'],
|
||||
{'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,
|
||||
@ -313,7 +317,7 @@ class Register(Component):
|
||||
if 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 (
|
||||
SWMuxEntryDimensioned(
|
||||
mux_entry = mux_entry,
|
||||
@ -329,21 +333,18 @@ class Register(Component):
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def eval_genvars(vec, depth, dimensions):
|
||||
def __eval_genvars(vec, depth, dimensions):
|
||||
for i in range(dimensions[depth]):
|
||||
vec[depth] = i
|
||||
|
||||
if depth == len(dimensions) - 1:
|
||||
yield f"[{']['.join(map(str, vec))}]"
|
||||
else:
|
||||
yield from Register.eval_genvars(vec, depth+1, dimensions)
|
||||
yield from Register.__eval_genvars(vec, depth+1, dimensions)
|
||||
|
||||
vec[depth] = 0
|
||||
|
||||
def __add_address_decoder(self):
|
||||
# Assign variables from bus
|
||||
self.obj.current_idx = [0]
|
||||
|
||||
if self.total_dimensions:
|
||||
access_wire_assign_field = 'access_wire_assign_multi_dim'
|
||||
else:
|
||||
@ -351,7 +352,7 @@ class Register(Component):
|
||||
|
||||
for i, name_addr_map in enumerate(self.name_addr_mappings):
|
||||
self.rtl_header.append(
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Register.templ_dict['access_wire_comment'],
|
||||
{'path': name_addr_map[0],
|
||||
'alias': '(alias)' if i > 0 else '',
|
||||
@ -360,13 +361,13 @@ class Register(Component):
|
||||
)
|
||||
|
||||
self.rtl_header.append(
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Register.templ_dict[access_wire_assign_field],
|
||||
{'path': name_addr_map[0],
|
||||
'addr': name_addr_map[1],
|
||||
'genvars': self.genvars_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
|
||||
if self.properties['sw_rd']:
|
||||
self.rtl_header.append(
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Register.templ_dict['read_wire_assign'],
|
||||
{'path': name_addr_map[0],
|
||||
'addr': name_addr_map[1],
|
||||
'genvars': self.genvars_str,
|
||||
'genvars_sum': self.genvars_sum_str,
|
||||
'depth': self.depth,
|
||||
'depth': self.own_depth,
|
||||
}
|
||||
)
|
||||
)
|
||||
else:
|
||||
self.rtl_header.append(
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Register.templ_dict['read_wire_assign_0'],
|
||||
{'path': name_addr_map[0],
|
||||
'genvars': self.genvars_str,
|
||||
@ -403,19 +404,19 @@ class Register(Component):
|
||||
# that is tied to 1'b0
|
||||
if self.properties['sw_wr']:
|
||||
self.rtl_header.append(
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Register.templ_dict['write_wire_assign'],
|
||||
{'path': name_addr_map[0],
|
||||
'addr': name_addr_map[1],
|
||||
'genvars': self.genvars_str,
|
||||
'genvars_sum': self.genvars_sum_str,
|
||||
'depth': self.depth,
|
||||
'depth': self.own_depth,
|
||||
}
|
||||
)
|
||||
)
|
||||
else:
|
||||
self.rtl_header.append(
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Register.templ_dict['write_wire_assign_0'],
|
||||
{'path': name_addr_map[0],
|
||||
'genvars': self.genvars_str,
|
||||
@ -426,7 +427,7 @@ class Register(Component):
|
||||
# Add combined signal to be used for general access of the register
|
||||
if self.properties['swacc']:
|
||||
self.rtl_header.append(
|
||||
self.process_yaml(
|
||||
self._process_yaml(
|
||||
Register.templ_dict['rw_wire_assign_any_alias'],
|
||||
{'path': self.name_addr_mappings[0][0],
|
||||
'genvars': self.genvars_str,
|
||||
@ -484,27 +485,21 @@ class Register(Component):
|
||||
sys.exit(1)
|
||||
|
||||
# Add name to list
|
||||
self.obj.current_idx = [0]
|
||||
self.name_addr_mappings.append(
|
||||
(self.create_underscored_path_static(obj)[3], obj.absolute_address))
|
||||
|
||||
def __process_variables(
|
||||
self,
|
||||
obj: node.RegNode,
|
||||
parents_dimensions: list,
|
||||
parents_stride: list,
|
||||
glbl_settings: dict):
|
||||
|
||||
# Save name
|
||||
def __init_variables(self, glbl_settings: dict):
|
||||
self.obj.current_idx = [0]
|
||||
self.name = obj.inst_name
|
||||
|
||||
# Save global settings
|
||||
self.glbl_settings = glbl_settings
|
||||
|
||||
# Is this an external register?
|
||||
self.config['external'] = self.obj.external
|
||||
|
||||
# Create mapping between (alias-) name and address
|
||||
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?
|
||||
@ -513,42 +508,11 @@ class Register(Component):
|
||||
# Empty array for mux-input signals
|
||||
self.sw_mux_assignment_var_name = []
|
||||
|
||||
# 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 = [f"[gv_{chr(97+i)}]" for i in range(self.total_dimensions)]
|
||||
self.genvars_str = ''.join(genvars)
|
||||
def __init_genvars(self):
|
||||
super()._init_genvars()
|
||||
|
||||
# Determine value to compare address with
|
||||
genvars_sum = []
|
||||
genvars_sum_vectorized = []
|
||||
try:
|
||||
for i, stride in enumerate(self.total_stride):
|
||||
genvars_sum.append(''.join(['gv_', chr(97+i)]))
|
||||
@ -556,14 +520,7 @@ class Register(Component):
|
||||
genvars_sum.append(str(stride))
|
||||
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_vectorized.pop()
|
||||
|
||||
self.logger.debug(
|
||||
f"Multidimensional with dimensions '{self.total_array_dimensions}' "
|
||||
@ -577,7 +534,6 @@ class Register(Component):
|
||||
"Caugt expected IndexError because genvars_sum is empty")
|
||||
|
||||
self.genvars_sum_str = ''.join(genvars_sum)
|
||||
self.genvars_sum_str_vectorized = ''.join(genvars_sum_vectorized)
|
||||
|
||||
def get_regwidth(self) -> int:
|
||||
return self.obj.get_property('regwidth')
|
||||
|
Loading…
Reference in New Issue
Block a user