From ce4782c11d66b2fac982ea48acad9ae1f0252a37 Mon Sep 17 00:00:00 2001 From: Dennis Date: Fri, 25 Jun 2021 01:20:32 +0200 Subject: [PATCH] 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. --- srdl2sv/components/regfile.py | 98 ++++++++++++++++++++-------------- srdl2sv/components/register.py | 39 ++++++++------ 2 files changed, 81 insertions(+), 56 deletions(-) diff --git a/srdl2sv/components/regfile.py b/srdl2sv/components/regfile.py index b031507..930bd11 100644 --- a/srdl2sv/components/regfile.py +++ b/srdl2sv/components/regfile.py @@ -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() diff --git a/srdl2sv/components/register.py b/srdl2sv/components/register.py index eef1d57..d66d23b 100644 --- a/srdl2sv/components/register.py +++ b/srdl2sv/components/register.py @@ -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():