mirror of
https://github.com/Silicon1602/srdl2sv.git
synced 2025-04-19 13:02:57 +00:00
122 lines
4.1 KiB
Python
122 lines
4.1 KiB
Python
import importlib.resources as pkg_resources
|
|
import yaml
|
|
|
|
from systemrdl import RDLCompiler, RDLCompileError, RDLWalker, RDLListener, node
|
|
from systemrdl.node import FieldNode
|
|
|
|
# Local modules
|
|
from log.log import create_logger
|
|
from components.component import Component
|
|
from components.field import Field
|
|
from . import templates
|
|
|
|
class Register(Component):
|
|
# Save YAML template as class variable
|
|
templ_dict = yaml.load(
|
|
pkg_resources.read_text(templates, 'regs.yaml'),
|
|
Loader=yaml.FullLoader)
|
|
|
|
def __init__(self, obj: node.RootNode, config: dict):
|
|
super().__init__()
|
|
|
|
# Save and/or process important variables
|
|
self.__process_variables(obj)
|
|
|
|
# Create logger object
|
|
self.create_logger("{}.{}".format(self.owning_addrmap, self.path), config)
|
|
self.logger.debug('Starting to process register "{}"'.format(obj.inst_name))
|
|
|
|
# Create comment and provide user information about register he/she
|
|
# is looking at.
|
|
self.rtl_header.append(
|
|
Register.templ_dict['reg_comment'].format(
|
|
name = obj.inst_name,
|
|
dimensions = self.dimensions,
|
|
depth = self.depth))
|
|
|
|
# Create wires every register
|
|
self.rtl_header.append(
|
|
Register.templ_dict['rw_wire_declare'].format(
|
|
path = self.path,
|
|
depth = self.depth))
|
|
|
|
# Create generate block for register and add comment
|
|
self.rtl_header.append("generate")
|
|
for i in range(self.dimensions):
|
|
self.rtl_header.append(
|
|
Register.templ_dict['generate_for_start'].format(
|
|
iterator = chr(97+i),
|
|
limit = self.array_dimensions[i]))
|
|
|
|
# Create RTL for fields
|
|
# Fields should be in order in RTL,therefore, use list
|
|
for field in obj.fields():
|
|
field_obj = Field(field, self.array_dimensions, config)
|
|
|
|
if not config['disable_sanity']:
|
|
field_obj.sanity_checks()
|
|
|
|
self.children.append(field_obj)
|
|
|
|
# End loops
|
|
for i in range(self.dimensions-1, -1, -1):
|
|
self.rtl_footer.append(
|
|
Register.templ_dict['generate_for_end'].format(
|
|
dimension = chr(97+i)))
|
|
|
|
# Assign variables from bus
|
|
self.obj.current_idx = [0]
|
|
|
|
self.rtl_header.append(
|
|
Register.templ_dict['rw_wire_assign'].format(
|
|
path = self.path,
|
|
addr = self.obj.absolute_address,
|
|
genvars = self.genvars_str,
|
|
genvars_sum =self.genvars_sum_str,
|
|
stride = self.obj.array_stride,
|
|
depth = self.depth))
|
|
|
|
def __process_variables(self, obj: node.RootNode):
|
|
# Save object
|
|
self.obj = obj
|
|
|
|
# Save name
|
|
self.name = obj.inst_name
|
|
|
|
# Create full name
|
|
self.owning_addrmap = obj.owning_addrmap.inst_name
|
|
self.path = obj.get_path()\
|
|
.replace('[]', '')\
|
|
.replace('{}.'.format(self.owning_addrmap), '')
|
|
|
|
self.path_underscored = self.path.replace('.', '_')
|
|
|
|
# Determine dimensions of register
|
|
if obj.is_array:
|
|
self.sel_arr = 'array'
|
|
self.array_dimensions = self.obj.array_dimensions
|
|
else:
|
|
self.sel_arr = 'single'
|
|
self.array_dimensions = [1]
|
|
|
|
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 = ['[{}]'.format(chr(97+i)) for i in range(self.dimensions)]
|
|
self.genvars_str = ''.join(genvars)
|
|
|
|
# Determine value to compare address with
|
|
genvars_sum = []
|
|
for i in range(self.dimensions):
|
|
if i != 0:
|
|
genvars_sum.append("+")
|
|
genvars_sum.append("*".join(map(str,self.array_dimensions[self.dimensions-i:])))
|
|
genvars_sum.append("*")
|
|
|
|
genvars_sum.append(chr(97+self.dimensions-1-i))
|
|
|
|
self.genvars_sum_str = ''.join(genvars_sum)
|
|
print(self.genvars_sum_str)
|
|
|