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():