Pull declaration of variables outside of generate scope

This ensures that code is compilation clean again. Prior to this change,
the multiplexer was reading from variables that were declared inside of
generate-scopes.

Furthermore, a small bug regarding the dimension detection of registers
was fixed. If a register wasn't multidimensional itself, but its parent
is, the multidimensionalness wasn't detected.
This commit is contained in:
Dennis Potter 2021-06-25 01:20:32 +02:00
parent 3089edc20d
commit ce4782c11d
Signed by: Dennis
GPG Key ID: 186A8AD440942BAF
2 changed files with 81 additions and 56 deletions

View File

@ -31,42 +31,6 @@ class RegFile(Component):
# Save and/or process important variables
self.__process_variables(obj, parents_dimensions, parents_stride)
# Create comment and provide user information about register he/she
# is looking at.
self.rtl_header = [
self.process_yaml(
RegFile.templ_dict['regfile_comment'],
{'name': obj.inst_name,
'dimensions': self.dimensions,
'depth': self.depth}
),
*self.rtl_header
]
# Create generate block for register and add comment
for i in range(self.dimensions-1, -1, -1):
self.rtl_footer.append(
self.process_yaml(
RegFile.templ_dict['generate_for_end'],
{'dimension': chr(97+i)}
)
)
if self.dimensions and not glbl_settings['generate_active']:
self.rtl_header.append("generate")
self.generate_initiated = True
glbl_settings['generate_active'] = True
else:
self.generate_initiated = False
for i in range(self.dimensions):
self.rtl_header.append(
self.process_yaml(
RegFile.templ_dict['generate_for_start'],
{'iterator': chr(97+i+self.parents_depths),
'limit': self.array_dimensions[i]}
)
)
# Empty dictionary of register objects
# We need a dictionary since it might be required to access the objects later
@ -77,6 +41,14 @@ class RegFile(Component):
# Set object to 0 for easy addressing
self.obj.current_idx = [0]
# Determine whether this regfile must add a generate block and for-loop
if self.dimensions and not glbl_settings['generate_active']:
self.generate_initiated = True
glbl_settings['generate_active'] = True
else:
self.generate_initiated = False
# Traverse through children
for child in obj.children():
if isinstance(child, node.AddrmapNode):
@ -115,15 +87,53 @@ class RegFile(Component):
# to account for all possible alias combinations
self.children = {**self.regfiles, **self.registers}
# Create RTL of all registers
[x.create_rtl() for x in self.registers.values()]
self.logger.info("Done generating all child-regfiles/registers")
# If this regfile create a generate-block, all the register's wires must
# be declared outside of that block
if self.generate_initiated:
self.rtl_header = [*self.rtl_header, *self.get_signal_instantiations_list()]
self.rtl_header.append("")
self.rtl_header.append("generate")
# Create comment and provide user information about register he/she
# is looking at.
self.rtl_header = [
self.process_yaml(
RegFile.templ_dict['regfile_comment'],
{'name': obj.inst_name,
'dimensions': self.dimensions,
'depth': self.depth}
),
*self.rtl_header
]
# Create generate block for register and add comment
for i in range(self.dimensions-1, -1, -1):
self.rtl_footer.append(
self.process_yaml(
RegFile.templ_dict['generate_for_end'],
{'dimension': chr(97+i)}
)
)
for i in range(self.dimensions):
self.rtl_header.append(
self.process_yaml(
RegFile.templ_dict['generate_for_start'],
{'iterator': chr(97+i+self.parents_depths),
'limit': self.array_dimensions[i]}
)
)
# End generate loop
if self.generate_initiated:
glbl_settings['generate_active'] = False
self.rtl_footer.append("endgenerate")
# Create RTL of all registers
[x.create_rtl() for x in self.registers.values()]
self.rtl_footer.append("")
def __process_variables(self,
obj: node.RegfileNode,
@ -167,6 +177,16 @@ class RegFile(Component):
for i in self.children.values():
yield from i.create_mux_string()
def get_signal_instantiations_list(self) -> set():
instantiations = list()
for i in self.children.values():
if isinstance(i, Register):
instantiations.append("\n// Variables of register '{}'".format(i.name))
instantiations = [*instantiations, *i.get_signal_instantiations_list()]
return instantiations
def get_package_names(self) -> set():
names = set()

View File

@ -76,7 +76,10 @@ class Register(Component):
self.__add_sw_read_assignments()
# Add wire instantiation
self.__add_signal_instantiations()
if not self.generate_active:
# We can/should only do this if there is no encapsulating
# regfile which create a generate
self.__add_signal_instantiations()
# Create comment and provide user information about register he/she is looking at
self.rtl_header = [
@ -159,7 +162,7 @@ class Register(Component):
# Assign variables from bus
self.obj.current_idx = [0]
if self.dimensions:
if self.total_dimensions:
rw_wire_assign_field = 'rw_wire_assign_multi_dim'
else:
rw_wire_assign_field = 'rw_wire_assign_1_dim'
@ -179,27 +182,29 @@ class Register(Component):
def __add_signal_instantiations(self):
# Add wire/register instantiations
self.rtl_header = [
*self.get_signal_instantiations_list(),
'',
*self.rtl_header
]
def get_signal_instantiations_list(self):
dict_list = [(key, value) for (key, value) in self.get_signals().items()]
signal_width = min(max([len(value[0]) for (_, value) in dict_list]), 40)
name_width = min(max([len(key) for (key, _) in dict_list]), 40)
self.rtl_header = [
*[
Register.templ_dict['signal_declaration'].format(
name = key,
type = value[0],
signal_width = signal_width,
name_width = name_width,
unpacked_dim = '[{}]'.format(
']['.join(
[str(y) for y in value[1]]))
if value[1] else '')
for (key, value) in dict_list],
'',
*self.rtl_header,
]
return [Register.templ_dict['signal_declaration'].format(
name = key,
type = value[0],
signal_width = signal_width,
name_width = name_width,
unpacked_dim = '[{}]'.format(
']['.join(
[str(y) for y in value[1]]))
if value[1] else '')
for (key, value) in dict_list]
def add_alias(self, obj: node.RegNode):
for field in obj.fields():