mirror of
https://github.com/Silicon1602/srdl2sv.git
synced 2024-12-22 06:58: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)
|
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
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
|
||||||
|
@ -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')
|
||||||
|
Loading…
Reference in New Issue
Block a user