diff options
author | Louis Stermole <stermole@us.ibm.com> | 2018-11-21 14:30:46 -0600 |
---|---|---|
committer | Christian R. Geddes <crgeddes@us.ibm.com> | 2019-02-13 22:29:30 -0600 |
commit | 5421995274d7ca08f0948bef73a89190205ea4b9 (patch) | |
tree | f530d78266706415bebb6aa8a09a43eda9105013 /src/import/generic | |
parent | febbe519b1fc754554b6d94cf4e7b17548c32fe9 (diff) | |
download | talos-hostboot-5421995274d7ca08f0948bef73a89190205ea4b9.tar.gz talos-hostboot-5421995274d7ca08f0948bef73a89190205ea4b9.zip |
Add generic attribute accessor script and makefiles
Added makefiles for generic and ocmb/explorer attrs
Also add mssAccessorName tag to explorer attrs
Change-Id: Ie1ddcd10505bafde881a0fac5ca4580ba593bd24
Original-Change-Id: I738c44e9bdf1999eb2746e79d4849683204ae567
Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/69017
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Reviewed-by: Louis Stermole <stermole@us.ibm.com>
Tested-by: Hostboot CI <hostboot-ci+hostboot@us.ibm.com>
Reviewed-by: STEPHEN GLANCY <sglancy@us.ibm.com>
Reviewed-by: Christian R. Geddes <crgeddes@us.ibm.com>
Reviewed-by: Jennifer A. Stofer <stofer@us.ibm.com>
Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/71829
Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com>
Diffstat (limited to 'src/import/generic')
-rwxr-xr-x | src/import/generic/memory/tools/gen_accessors.pl | 217 | ||||
-rwxr-xr-x | src/import/generic/memory/tools/gen_accessors.pm | 1036 |
2 files changed, 1253 insertions, 0 deletions
diff --git a/src/import/generic/memory/tools/gen_accessors.pl b/src/import/generic/memory/tools/gen_accessors.pl new file mode 100755 index 000000000..b70cef8d7 --- /dev/null +++ b/src/import/generic/memory/tools/gen_accessors.pl @@ -0,0 +1,217 @@ +#!/usr/bin/perl +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/import/generic/memory/tools/gen_accessors.pl $ +# +# OpenPOWER HostBoot Project +# +# Contributors Listed Below - COPYRIGHT 2015,2019 +# [+] International Business Machines Corp. +# +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. See the License for the specific language governing +# permissions and limitations under the License. +# +# IBM_PROLOG_END_TAG + +# @file shmoo_2d_plot.pl +# @brief Calls the 2D plotting information +# +# *HWP HWP Owner: Louis Stermole <stermole@us.ibm.com> +# *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com> +# *HWP Team: Memory +# *HWP Level: 2 +# *HWP Consumed by: Memory + +use strict; +use warnings; + +# Gets the directory where the perl script is stored +# This allows the user to use a relative instead of a direct path for the include +my $pwd; + +BEGIN +{ + # Some scripts needs the directory the script was called from, save that here + #This keeps the directory intact. + my $callingPwd = ""; + chomp( $callingPwd = `cd .;pwd` ); + + # Now do the rest + my @tempArr = split( /\/+/, $0 ); + pop(@tempArr); # The script name + my $LIST_SEPARATOR = "/"; # Make it so the array below separates on / instead of space + #If it starts with a ., it's being called with relative path + if ( substr( $0, 0, 1 ) ne "/" ) + { + $pwd = $callingPwd; # Get where I got called from + $pwd = $pwd . "/" . "@tempArr"; # Now use the relative to find out where the script is + } + else + { # Absolute path + $pwd = "@tempArr"; + } + $LIST_SEPARATOR = " "; # Reset + chomp( $pwd = `cd $pwd;pwd` ); # Get to where this script resides +} + +use lib "$pwd"; +use lib $ENV{PROJECT_ROOT} . "/generic/memory/tools"; # EKB Path +use lib $ENV{PROJECT_ROOT} . "/src/import/generic/memory/tools"; # Hostboot Path + +use English; +use Carp qw( croak ); +use Getopt::Long; +use gen_accessors qw( get_array_dimensions format_attr_description generate_accessor_methods ); + +# +# @brief Print help text +# +sub print_help +{ + print( + "Usage: gen_acessors.pl --system=<system> --output-dir=<output dir> --output-file-prefix=<prefix> <attr-xml-file1> [<attr-xml-file2> ...]\n" + ); + print(" This perl script will parse attribute XML files and create the following files:\n"); + print(" - <prefix>_attribute_getters.H. Contains the attribute getters, based on the xml\n"); + print(" - <prefix>_attribute_setters.H. Contains the attribute setters, based on the xml\n"); + print(" Note that the system argument must be one of the following: NIMBUS, AXONE\n"); + exit(1); +} + +# Print out where we got the plotter module from (useful for debugging) +print "Using module gen_accessors from: " . $INC{"gen_accessors.pm"} . "\n"; + +#------------------------------------------------------------------------------ +# Print Command Line Help +#------------------------------------------------------------------------------ +my $arg_output_dir = undef; +my $arg_system = undef; +my $arg_output_file_prefix = undef; + +# Get the options from the command line - the rest of @ARGV will +# be filenames +GetOptions( + "output-dir=s" => \$arg_output_dir, + "output-file-prefix=s" => \$arg_output_file_prefix, + "system=s" => \$arg_system +); + +if ( ( scalar(@ARGV) < 1 ) + || !defined($arg_output_dir) + || !defined($arg_output_file_prefix) + || !defined($arg_system) ) +{ + print_help(); +} + +my $system = uc($arg_system); +if ( !grep( /^$system$/, keys( %{ +TARGET_TYPES } ) ) ) +{ + print("ERROR: unrecognized --system option: $arg_system\n"); + print_help(); +} + +#------------------------------------------------------------------------------ +# Specify perl modules to use +#------------------------------------------------------------------------------ +use XML::Simple; +my $xml = new XML::Simple( KeyAttr => [] ); + +# Uncomment to enable debug output +use Data::Dumper; + +#------------------------------------------------------------------------------ +# Set PREFERRED_PARSER to XML::Parser. Otherwise it uses XML::SAX which contains +# bugs that result in XML parse errors that can be fixed by adjusting white- +# space (i.e. parse errors that do not make sense). +#------------------------------------------------------------------------------ +$XML::Simple::PREFERRED_PARSER = 'XML::Parser'; + +my $getters_string = ""; +my $setters_string = ""; + +#------------------------------------------------------------------------------ +# For each XML file +#------------------------------------------------------------------------------ +foreach my $infile (@ARGV) +{ + # Hashes to keep track of the methods for the classes + my %getter_methods = (); + my %setter_methods = (); + + # read XML file. The ForceArray option ensures that there is an array of + # elements even if there is only one such element in the file + my $attributes = + $xml->XMLin( $infile, ForceArray => [ 'attribute', 'chip' ], SuppressEmpty => undef, NormaliseSpace => 2 ); + + #-------------------------------------------------------------------------- + # For each Attribute + #-------------------------------------------------------------------------- + + foreach my $attr ( @{ $attributes->{attribute} } ) + { + my $arrayDimensions = ""; + my @arrayDims = (); + + # Only create functions for attributes that have an accessor name + # This avoids creating functions for attributes we don't use + if ( !$attr->{mssAccessorName} ) + { + next; + } + + # If we have an array, lets do a little up front work to disect it + my $array_dimensions = get_array_dimensions( $attr, \@arrayDims ); + + # Make the description something nice we can use. + format_attr_description($attr); + + # Write accessors for things which are tied to the MEM_PORT or the OCMB_CHIP + generate_accessor_methods( $system, $attr, \@arrayDims, $array_dimensions, \%getter_methods, \%setter_methods ); + } #end foreach attr + + foreach my $method ( sort keys %getter_methods ) + { + $getters_string .= "$getter_methods{$method}\n"; + } + + foreach my $method ( sort keys %setter_methods ) + { + $setters_string .= "$setter_methods{$method}\n"; + } + +} #end foreach xml + +# Finally, print out the header file(s) +if ( $getters_string ne "" ) +{ + my $file_string = generate_header_file( GETTERS, $arg_output_dir, $arg_output_file_prefix, $getters_string ); + my $header_file_name = $arg_output_file_prefix . "_attribute_getters.H"; + my $header_file = $arg_output_dir . "/" . $header_file_name; + + open( my $fh, ">", $header_file ) || croak "Could not open attribute getter header file for writing: $header_file"; + print {$fh} $file_string; + close($fh); +} + +if ( $setters_string ne "" ) +{ + my $file_string = generate_header_file( SETTERS, $arg_output_dir, $arg_output_file_prefix, $setters_string ); + my $header_file_name = $arg_output_file_prefix . "_attribute_setters.H"; + my $header_file = $arg_output_dir . "/" . $header_file_name; + + open( my $fh, ">", $header_file ) || croak "Could not open attribute setter header file for writing: $header_file"; + print {$fh} $file_string; + close($fh); +} diff --git a/src/import/generic/memory/tools/gen_accessors.pm b/src/import/generic/memory/tools/gen_accessors.pm new file mode 100755 index 000000000..40999d503 --- /dev/null +++ b/src/import/generic/memory/tools/gen_accessors.pm @@ -0,0 +1,1036 @@ +#!/usr/bin/perl +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/import/generic/memory/tools/gen_accessors.pm $ +# +# OpenPOWER HostBoot Project +# +# Contributors Listed Below - COPYRIGHT 2015,2019 +# [+] International Business Machines Corp. +# +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. See the License for the specific language governing +# permissions and limitations under the License. +# +# IBM_PROLOG_END_TAG + +# @file gen_accessors.pm +# @brief Contains subroutines for generating attribute accessors from XML +# +# *HWP HWP Owner: Louis Stermole <stermole@us.ibm.com> +# *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com> +# *HWP Team: Memory +# *HWP Level: 2 +# *HWP Consumed by: Memory + +use strict; +use warnings; +use English; +use Carp qw( croak ); + +# Uncomment to enable debug output +use Data::Dumper; + +use constant { + TARGET_TYPES => { + AXONE => { + PORT_GROUP => 'TARGET_TYPE_OCMB_CHIP', + PORT => 'TARGET_TYPE_MEM_PORT', + DIMM => 'TARGET_TYPE_DIMM', + }, + NIMBUS => { + PORT_GROUP => 'TARGET_TYPE_MCS', + PORT => 'TARGET_TYPE_MCA', + DIMM => 'TARGET_TYPE_DIMM', + MC => 'TARGET_TYPE_MCBIST', + }, + }, + + DIMM_PER_PORT => { + AXONE => 2, + NIMBUS => 2, + }, + + PORTS_PER_GROUP => { + AXONE => 1, + NIMBUS => 2, + }, + + # Size, in bytes, of the various value-types + BYTE_SIZE => { + 'uint8' => 1, + 'uint16' => 2, + 'uint32' => 4, + 'uint64' => 8, + 'int8' => 1, + 'int16' => 2, + 'int32' => 4, + 'int64' => 8, + }, + + # Special attributes which are multi-demensional but the second dimension doesn't represent the DIMM but + # rather the data on the port + PER_PORT_ATTRIBUTES => { "ATTR_MSS_VPD_DQ_MAP" => 1 }, + + # Constants for code generation subroutines + NO_TARGET => 0, + ARRAY_DATA => 1, + SCALAR_DATA => 0, + NO_INDEX => 0, + NO_LOCALS => 0, + PORT => 1, + PORT_GROUP => 2, + PORT_AND_PORT_GROUP => 3, + GETTERS => 0, + SETTERS => 1, +}; + +# +# @brief Get array dimensions from an attribute reference +# @param[in] attr - reference to the attribute to process +# @param[out] dims_ref - reference to array of dimensions +# @return array dimensions string +# +sub get_array_dimensions +{ + # Gets input and checks to make sure it's valid + croak "Incorrect number of inputs passed into gen_accessors::get_array_dimensions" if ( @ARG != 2 ); + + my ( $attr, $dims_ref ) = @ARG; + + my $arrayDimensions = ""; + + if ( $attr->{array} ) + { + # Remove leading whitespace + my $dimText = $attr->{array}; + $dimText =~ s/^\s+//; + + # Split on commas or whitespace + @{$dims_ref} = split( /\s*,\s*|\s+/, $dimText ); + + foreach my $val ( @{$dims_ref} ) + { + $arrayDimensions .= "[${val}]"; + } + } + + return $arrayDimensions; +} + +# +# @brief Format attribute description from an attribute reference +# @param[in] attr - reference to the attribute to process +# +sub format_attr_description +{ + # Gets input and checks to make sure it's valid + croak "Incorrect number of inputs passed into gen_accessors::format_attr_description" if ( @ARG != 1 ); + + my ($attr) = @ARG; + + if ( !$attr->{description} ) + { + # Use "no description" if the resulting description is empty + $attr->{description} = "No description"; + } + else + { + # Remove all newline characters from the string + $attr->{description} =~ s/^\n\s*//; + $attr->{description} =~ s/\s*\n\s*/ /g; + + # Word wrap the string by consuming the first 79 characters, stopping at the next whitespace + $attr->{description} =~ s/(.{79}[^\s]*)\s+/$1\n/g; + + # Insert Doxy style comments at newlines + $attr->{description} =~ s!\n!\n /// !g; + } +} + +# +# @brief Generate Doxygen string and param list for accessor function +# @param[in] attr - reference to the attribute to process +# @param[in] target - target string if target is an input param, NO_TARGET if not +# @param[in] array - reference to output array dimensions if the accessor data is an array, SCALAR_DATA if it's a scalar value +# @param[in] subroutine_name - name of generator subroutine +# @param[in] g_parameter - reference to hash of getter parameters +# @param[in] s_parameter - reference to hash of setter parameters +# +sub create_params_doxy +{ + # Gets input and checks to make sure it's valid + croak "Incorrect number of inputs passed into gen_accessors::create_params_doxy" if ( @ARG != 6 ); + + my ( $attr, $target, $array, $subroutine_name, $g_parameter, $s_parameter ) = @ARG; + + if ( $target ne NO_TARGET ) + { + $g_parameter->{headerString} .= " /// \@param[in] const ref to the $target\n"; + $s_parameter->{headerString} .= " /// \@param[in] const ref to the $target\n"; + $g_parameter->{subString} .= "const fapi2::Target<fapi2::$target>& i_target, "; + $s_parameter->{subString} .= "const fapi2::Target<fapi2::$target>& i_target, "; + } + + if ( ref($array) ) + { + my $dims = ""; + foreach my $dim ( @{$array} ) + { + $dims .= "[$dim]"; + } + $g_parameter->{headerString} .= + " /// \@param[out] $attr->{valueType}_t&[] array reference to store the value\n"; + $s_parameter->{headerString} .= + " /// \@param[in] $attr->{valueType}_t&[] const ref to array of values to set\n"; + $g_parameter->{subString} .= "$attr->{valueType}_t (&o_array)$dims"; + $s_parameter->{subString} .= "const $attr->{valueType}_t (&i_array)$dims"; + } + else + { + $g_parameter->{headerString} .= " /// \@param[out] $attr->{valueType}_t& reference to store the value\n"; + $s_parameter->{headerString} .= " /// \@param[in] $attr->{valueType}_t the value to set\n"; + $g_parameter->{subString} .= "$attr->{valueType}_t& o_value"; + $s_parameter->{subString} .= "const $attr->{valueType}_t i_value"; + } + + $g_parameter->{headerString} .= " /// \@note Generated by gen_accessors.pl $subroutine_name\n"; + $s_parameter->{headerString} .= " /// \@note Generated by gen_accessors.pl $subroutine_name\n"; +} + +# +# @brief Generate code for attribute fetch and store +# @param[in] attr - reference to the attribute to process +# @param[in] target - attribute target variable string +# @param[in] array - ARRAY_DATA if data is an array, or SCALAR_DATA if data is a scalar value +# @param[in] index - array index of output value if the accessor data is a scalar, or NO_INDEX if not needed +# @param[in] g_parameter - reference to hash of getter parameters +# @param[in] s_parameter - reference to hash of setter parameters +# +sub create_attr_access_code +{ + # Gets input and checks to make sure it's valid + croak "Incorrect number of inputs passed into gen_accessors::create_attr_access_code" if ( @ARG != 6 ); + + my ( $attr, $target, $array, $index, $g_parameter, $s_parameter ) = @ARG; + + $g_parameter->{fetchString} .= "FAPI_ATTR_GET(fapi2::$attr->{id}, $target, "; + + if ( $array == ARRAY_DATA ) + { + $g_parameter->{fetchString} .= "l_value)"; + $s_parameter->{fetchString} .= "FAPI_ATTR_GET(fapi2::$attr->{id}, $target, l_value)"; + $s_parameter->{storeString} .= "FAPI_ATTR_SET(fapi2::$attr->{id}, $target, l_value)"; + } + else + { + if ( $index eq NO_INDEX ) + { + # Getter can just fetch to output param if it's not an array + $g_parameter->{fetchString} .= "o_value)"; + $g_parameter->{noLocals} = 1; + + # Setter can just write to the attr if data is not an array + $s_parameter->{storeString} .= "FAPI_ATTR_SET(fapi2::$attr->{id}, $target, i_value)"; + $s_parameter->{noLocals} = 1; + } + else + { + $g_parameter->{fetchString} .= "l_value)"; + $s_parameter->{fetchString} .= "FAPI_ATTR_GET(fapi2::$attr->{id}, $target, l_value)"; + $s_parameter->{storeString} .= "FAPI_ATTR_SET(fapi2::$attr->{id}, $target, l_value)"; + } + } +} + +# +# @brief Generate code for copying local variable data to output param if needed (and vice versa for setters) +# @param[in] array - reference string of beginning of local array, or SCALAR_DATA if data is a scalar value +# @param[in] size - array size in bytes if the accessor data is an array +# @param[in] index - array index of output value if the accessor data is a scalar, or NO_INDEX if not needed +# @param[in] g_parameter - reference to hash of getter parameters +# @param[in] s_parameter - reference to hash of setter parameters +# +sub create_execute_code +{ + # Gets input and checks to make sure it's valid + croak "Incorrect number of inputs passed into gen_accessors::create_execute_code" if ( @ARG != 5 ); + + my ( $array, $size, $index, $g_parameter, $s_parameter ) = @ARG; + + if ( $array ne SCALAR_DATA ) + { + $g_parameter->{exeString} = "memcpy(o_array, $array, $size);\n"; + $s_parameter->{exeString} = "memcpy($array, i_array, $size);\n"; + } + elsif ( $index ne NO_INDEX ) + { + $g_parameter->{exeString} = "o_value = $index;\n"; + $s_parameter->{exeString} = "$index = i_value;\n"; + } +} + +# +# @brief Generate code for local target variables if needed +# @param[in] system - system type +# @param[in] locals - selects which locals are needed, can be any of: NO_LOCALS, PORT, PORT_GROUP, PORT_AND_PORT_GROUP +# @param[in] g_parameter - reference to hash of getter parameters +# @param[in] s_parameter - reference to hash of setter parameters +# +sub create_locals_code +{ + # Gets input and checks to make sure it's valid + croak "Incorrect number of inputs passed into gen_accessors::create_locals_code" if ( @ARG != 4 ); + + my ( $system, $locals, $g_parameter, $s_parameter ) = @ARG; + + if ( $locals == PORT ) + { + my $target_type = ${ +TARGET_TYPES }{$system}{PORT}; + $g_parameter->{localsString} .= "const auto l_port = i_target.getParent<fapi2::$target_type>();\n"; + $s_parameter->{localsString} .= "const auto l_port = i_target.getParent<fapi2::$target_type>();\n"; + } + elsif ( $locals == PORT_GROUP ) + { + my $target_type = ${ +TARGET_TYPES }{$system}{PORT_GROUP}; + $g_parameter->{localsString} .= "const auto l_port_group = i_target.getParent<fapi2::$target_type>();\n"; + $s_parameter->{localsString} .= "const auto l_port_group = i_target.getParent<fapi2::$target_type>();\n"; + } + elsif ( $locals == PORT_AND_PORT_GROUP ) + { + my $target_type = ${ +TARGET_TYPES }{$system}{PORT}; + $g_parameter->{localsString} .= "const auto l_port = i_target.getParent<fapi2::$target_type>();\n"; + $s_parameter->{localsString} .= "const auto l_port = i_target.getParent<fapi2::$target_type>();\n"; + + $target_type = ${ +TARGET_TYPES }{$system}{PORT_GROUP}; + $g_parameter->{localsString} .= " const auto l_port_group = l_port.getParent<fapi2::$target_type>();\n"; + $s_parameter->{localsString} .= " const auto l_port_group = l_port.getParent<fapi2::$target_type>();\n"; + } +} + +# +# @brief Generate paramaters to create methods for 'other' attributes +# @param[in] system - system type +# @param[in] attr - reference to the attribute to process +# @param[in] dims_ref - reference to array of dimensions +# @param[in] g_parameters - reference to array of getter parameters +# @param[in] s_parameters - reference to array of setter parameters +# +sub generate_other_attr_params +{ + # Gets input and checks to make sure it's valid + croak "Incorrect number of inputs passed into gen_accessors::generate_other_attr_params" if ( @ARG != 5 ); + + my ( $system, $attr, $dims_ref, $g_parameters, $s_parameters ) = @ARG; + + my @dims = @{$dims_ref}; + + my $g_parameter = {}; + my $s_parameter = {}; + my $target_type = ""; + my $target_variable = ""; + + $g_parameter->{customErrTrace} .= " FAPI_ERR(\"failed getting $attr->{id}: 0x%lx\",\n"; + $g_parameter->{customErrTrace} .= " uint64_t(fapi2::current_err));\n"; + $s_parameter->{customErrTrace} .= " FAPI_ERR(\"failed setting $attr->{id}: 0x%lx\",\n"; + $s_parameter->{customErrTrace} .= " uint64_t(fapi2::current_err));\n"; + + # See what type of target we have, since we need slightly different code for system targets + if ( $attr->{targetType} eq "TARGET_TYPE_SYSTEM" ) + { + $target_type = NO_TARGET; + $target_variable = "fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>()"; + } + else + { + $target_type = $attr->{targetType}; + $target_variable = "i_target"; + } + + # If we have no array ... + if ( scalar(@dims) == 0 ) + { + create_params_doxy( $attr, $target_type, SCALAR_DATA, "generate_other_attr_params", $g_parameter, + $s_parameter ); + create_attr_access_code( $attr, $target_variable, SCALAR_DATA, NO_INDEX, $g_parameter, $s_parameter ); + create_execute_code( SCALAR_DATA, 0, NO_INDEX, $g_parameter, $s_parameter ); + create_locals_code( $system, NO_LOCALS, $g_parameter, $s_parameter ); + } + + # ... we have an array + else + { + my $size = 1; + + # Calculate the size of the last dimensions - these are all we'll copy + for my $dim_size (@dims) + { + $size *= $dim_size; + } + + # Our true size in bytes is multiplied by the size of our valueType + $size *= ${ +BYTE_SIZE }{ $attr->{valueType} }; + + create_params_doxy( $attr, $target_type, \@dims, "generate_other_attr_params", $g_parameter, $s_parameter ); + create_attr_access_code( $attr, $target_variable, ARRAY_DATA, NO_INDEX, $g_parameter, $s_parameter ); + create_execute_code( "&l_value", $size, NO_INDEX, $g_parameter, $s_parameter ); + create_locals_code( $system, NO_LOCALS, $g_parameter, $s_parameter ); + } + + push @{$g_parameters}, $g_parameter; + push @{$s_parameters}, $s_parameter; +} + +# +# @brief Generate paramaters to create methods for OCMB_CHIP and MEM_PORT attributes +# @param[in] system - system type +# @param[in] attr - reference to the attribute to process +# @param[in] dims_ref - reference to array of dimensions +# @param[in] g_parameters - reference to array of getter parameters +# @param[in] s_parameters - reference to array of setter parameters +# +sub generate_mc_port_params +{ + # Gets input and checks to make sure it's valid + croak "Incorrect number of inputs passed into gen_accessors::generate_mc_port_params" if ( @ARG != 5 ); + + my ( $system, $attr, $dims_ref, $g_parameters, $s_parameters ) = @ARG; + + my @dims = @{$dims_ref}; + + # Check to see how many array dimensions we have. A controller should have at most + # 2 - one for the port and one for the dimm. Other dimensions we don't know - they + # could be rank or they could be bits ... If we have more than 2 dimensions, we + # return back a pointer to the other dimensions. If a controller only has one port + # per phy or one dimm per port it will have one fewer dimension, so we calculate + # that here. + my $port_dimensions = ( ${ +DIMM_PER_PORT }{$system} > 1 ) ? 1 : 0; + my $port_group_dimensions = ( ${ +PORTS_PER_GROUP }{$system} > 1 ) ? $port_dimensions + 1 : $port_dimensions; + + if ( scalar(@dims) == 0 ) + { + my %g_parameter = (); + my %s_parameter = (); + + create_params_doxy( $attr, $attr->{targetType}, SCALAR_DATA, "generate_mc_port_params", \%g_parameter, + \%s_parameter ); + create_attr_access_code( $attr, "i_target", SCALAR_DATA, NO_INDEX, \%g_parameter, \%s_parameter ); + create_execute_code( SCALAR_DATA, 0, NO_INDEX, \%g_parameter, \%s_parameter ); + create_locals_code( $system, NO_LOCALS, \%g_parameter, \%s_parameter ); + + push @{$g_parameters}, \%g_parameter; + push @{$s_parameters}, \%s_parameter; + } + + # Array per DIMM elements with PORT_GROUP target + if ( ( $attr->{targetType} eq ${ +TARGET_TYPES }{$system}{PORT_GROUP} ) + && ( scalar(@dims) > $port_group_dimensions ) ) + { + # + # By DIMM + # + { + my %g_parameter = (); + my %s_parameter = (); + my $size = 1; + + # Calculate the size of the last dimensions - these are all we'll copy + my @dim_subset = @dims[ $port_group_dimensions .. ( scalar(@dims) - 1 ) ]; + for my $i (@dim_subset) + { + $size *= $i; + } + + # Our true size in bytes is multiplied by the size of our valueType + $size *= ${ +BYTE_SIZE }{ $attr->{valueType} }; + + create_params_doxy( $attr, ${ +TARGET_TYPES }{$system}{DIMM}, + \@dim_subset, "generate_mc_port_params", \%g_parameter, \%s_parameter ); + create_attr_access_code( $attr, "l_port_group", ARRAY_DATA, NO_INDEX, \%g_parameter, \%s_parameter ); + create_execute_code( "&(l_value[mss::index(l_port)][mss::index(i_target)][0])", + $size, NO_INDEX, \%g_parameter, \%s_parameter ); + create_locals_code( $system, PORT_AND_PORT_GROUP, \%g_parameter, \%s_parameter ); + + push @{$g_parameters}, \%g_parameter; + push @{$s_parameters}, \%s_parameter; + } + + # + # By Port + # + { + my %g_parameter = (); + my %s_parameter = (); + my $size = 1; + + # Calculate the size of the last dimensions - these are all we'll copy + my @dim_subset = @dims[ $port_dimensions .. ( scalar(@dims) - 1 ) ]; + for my $i (@dim_subset) + { + $size *= $i; + } + + # Our true size in bytes is multiplied by the size of our valueType + $size *= ${ +BYTE_SIZE }{ $attr->{valueType} }; + + create_params_doxy( $attr, ${ +TARGET_TYPES }{$system}{PORT}, + \@dim_subset, "generate_mc_port_params", \%g_parameter, \%s_parameter ); + create_attr_access_code( $attr, "l_port_group", ARRAY_DATA, NO_INDEX, \%g_parameter, \%s_parameter ); + create_execute_code( "&(l_value[mss::index(i_target)][0])", $size, NO_INDEX, \%g_parameter, \%s_parameter ); + create_locals_code( $system, PORT_GROUP, \%g_parameter, \%s_parameter ); + + push @{$g_parameters}, \%g_parameter; + push @{$s_parameters}, \%s_parameter; + } + + # + # The whole enchilada + # + { + my %g_parameter = (); + my %s_parameter = (); + my $size = 1; + + # Calculate the size of the last dimensions - these are all we'll copy + for my $dim_size (@dims) + { + $size *= $dim_size; + } + + # Our true size in bytes is multiplied by the size of our valueType + $size *= ${ +BYTE_SIZE }{ $attr->{valueType} }; + + create_params_doxy( $attr, ${ +TARGET_TYPES }{$system}{PORT_GROUP}, + \@dims, "generate_mc_port_params", \%g_parameter, \%s_parameter ); + create_attr_access_code( $attr, "i_target", ARRAY_DATA, NO_INDEX, \%g_parameter, \%s_parameter ); + create_execute_code( "&l_value", $size, NO_INDEX, \%g_parameter, \%s_parameter ); + create_locals_code( $system, NO_LOCALS, \%g_parameter, \%s_parameter ); + + push @{$g_parameters}, \%g_parameter; + push @{$s_parameters}, \%s_parameter; + } + } + + # Array per DIMM elements with PORT target + if ( ( $attr->{targetType} eq ${ +TARGET_TYPES }{$system}{PORT} ) + && ( scalar(@dims) > $port_dimensions ) ) + { + # + # By DIMM + # + { + my %g_parameter = (); + my %s_parameter = (); + my $size = 1; + + # Calculate the size of the last dimensions - these are all we'll copy + my @dim_subset = @dims[ $port_dimensions .. ( scalar(@dims) - 1 ) ]; + for my $i (@dim_subset) + { + $size *= $i; + } + + # Our true size in bytes is multiplied by the size of our valueType + $size *= ${ +BYTE_SIZE }{ $attr->{valueType} }; + + create_params_doxy( $attr, ${ +TARGET_TYPES }{$system}{DIMM}, + \@dim_subset, "generate_mc_port_params", \%g_parameter, \%s_parameter ); + create_attr_access_code( $attr, "l_port", ARRAY_DATA, NO_INDEX, \%g_parameter, \%s_parameter ); + create_execute_code( "&(l_value[mss::index(i_target)][0])", $size, NO_INDEX, \%g_parameter, \%s_parameter ); + create_locals_code( $system, PORT, \%g_parameter, \%s_parameter ); + + push @{$g_parameters}, \%g_parameter; + push @{$s_parameters}, \%s_parameter; + } + + # + # By Port + # + { + my %g_parameter = (); + my %s_parameter = (); + my $size = 1; + + # Calculate the size of the last dimensions - these are all we'll copy + for my $dim_size (@dims) + { + $size *= $dim_size; + } + + # Our true size in bytes is multiplied by the size of our valueType + $size *= ${ +BYTE_SIZE }{ $attr->{valueType} }; + + create_params_doxy( $attr, ${ +TARGET_TYPES }{$system}{PORT}, + \@dims, "generate_mc_port_params", \%g_parameter, \%s_parameter ); + create_attr_access_code( $attr, "i_target", ARRAY_DATA, NO_INDEX, \%g_parameter, \%s_parameter ); + create_execute_code( "&l_value", $size, NO_INDEX, \%g_parameter, \%s_parameter ); + create_locals_code( $system, NO_LOCALS, \%g_parameter, \%s_parameter ); + + push @{$g_parameters}, \%g_parameter; + push @{$s_parameters}, \%s_parameter; + } + } + + # Per Port elements with PORT_GROUP target + if ( ( $attr->{targetType} eq ${ +TARGET_TYPES }{$system}{PORT_GROUP} ) + && ( scalar(@dims) == $port_dimensions ) ) + { + # Canary to tell us if we have a per-controller attribute we're not handling + die "$attr->{targetType} is not indexed by port?" if !$attr->{mssAccessor} =~ m/PORT/; + + # + # Per Port + # + { + my %g_parameter = (); + my %s_parameter = (); + my $parent_type = ${ +TARGET_TYPES }{$system}{PORT_GROUP}; + + create_params_doxy( $attr, ${ +TARGET_TYPES }{$system}{PORT}, + SCALAR_DATA, "generate_mc_port_params", \%g_parameter, \%s_parameter ); + create_attr_access_code( + $attr, "i_target.getParent<fapi2::$parent_type>()", + SCALAR_DATA, "l_value[mss::index(i_target)]", + \%g_parameter, \%s_parameter + ); + create_execute_code( SCALAR_DATA, 0, "l_value[mss::index(i_target)]", \%g_parameter, \%s_parameter ); + create_locals_code( $system, NO_LOCALS, \%g_parameter, \%s_parameter ); + + push @{$g_parameters}, \%g_parameter; + push @{$s_parameters}, \%s_parameter; + } + + # + # Per DIMM (just return the value set for my port) + # + { + my %g_parameter = (); + my %s_parameter = (); + my $parent_type = ${ +TARGET_TYPES }{$system}{PORT_GROUP}; + + create_params_doxy( $attr, ${ +TARGET_TYPES }{$system}{DIMM}, + SCALAR_DATA, "generate_mc_port_params", \%g_parameter, \%s_parameter ); + create_attr_access_code( $attr, "l_port.getParent<fapi2::$parent_type>()", + SCALAR_DATA, "l_value[mss::index(l_port)]", \%g_parameter, \%s_parameter ); + create_execute_code( SCALAR_DATA, 0, "l_value[mss::index(l_port)]", \%g_parameter, \%s_parameter ); + create_locals_code( $system, PORT, \%g_parameter, \%s_parameter ); + + push @{$g_parameters}, \%g_parameter; + push @{$s_parameters}, \%s_parameter; + } + + # + # The whole enchilada + # + { + my %g_parameter = (); + my %s_parameter = (); + my $size = 1; + + # Calculate the size of the last dimensions - these are all we'll copy + for my $dim_size (@dims) + { + $size *= $dim_size; + } + + # Our true size in bytes is multiplied by the size of our valueType + $size *= ${ +BYTE_SIZE }{ $attr->{valueType} }; + + create_params_doxy( $attr, ${ +TARGET_TYPES }{$system}{PORT_GROUP}, + \@dims, "generate_mc_port_params", \%g_parameter, \%s_parameter ); + create_attr_access_code( $attr, "i_target", ARRAY_DATA, NO_INDEX, \%g_parameter, \%s_parameter ); + create_execute_code( "&l_value", $size, NO_INDEX, \%g_parameter, \%s_parameter ); + create_locals_code( $system, NO_LOCALS, \%g_parameter, \%s_parameter ); + + push @{$g_parameters}, \%g_parameter; + push @{$s_parameters}, \%s_parameter; + } + + } + + # Per dimm elements with PORT_GROUP target + if ( ( $attr->{targetType} eq ${ +TARGET_TYPES }{$system}{PORT_GROUP} ) + && ( scalar(@dims) == $port_group_dimensions ) ) + { + # + # By DIMM + # + { + # There are some attributes which are 2 dimensional arrays, but aren't [port][dimm] but rather + # [port][data], meaning they're 'per port' attributes. DQ mapping is one example; it doesn't make + # sense to map DQ different for DIMM on a port; they terminate in the same place on the MC. + # So check to see if we have one of those attributes, as we force the caller to ask for the attribute + # per-port as that's what the attribute represents. + if ( !${ +PER_PORT_ATTRIBUTES }{ $attr->{id} } ) + { + my %g_parameter = (); + my %s_parameter = (); + + create_params_doxy( $attr, ${ +TARGET_TYPES }{$system}{DIMM}, + SCALAR_DATA, "generate_mc_port_params", \%g_parameter, \%s_parameter ); + create_attr_access_code( $attr, "l_port_group", SCALAR_DATA, + "l_value[mss::index(l_port)][mss::index(i_target)]", + \%g_parameter, \%s_parameter ); + create_execute_code( SCALAR_DATA, 0, "l_value[mss::index(l_port)][mss::index(i_target)]", + \%g_parameter, \%s_parameter ); + create_locals_code( $system, PORT_AND_PORT_GROUP, \%g_parameter, \%s_parameter ); + + push @{$g_parameters}, \%g_parameter; + push @{$s_parameters}, \%s_parameter; + } + } + + # + # By Port + # + { + my %g_parameter = (); + my %s_parameter = (); + my $size = 1; + + # Calculate the size of the last dimensions - these are all we'll copy + my @dim_subset = @dims[ $port_dimensions .. ( scalar(@dims) - 1 ) ]; + for my $i (@dim_subset) + { + $size *= $i; + } + + # Our true size in bytes is multiplied by the size of our valueType + $size *= ${ +BYTE_SIZE }{ $attr->{valueType} }; + + create_params_doxy( $attr, ${ +TARGET_TYPES }{$system}{PORT}, + \@dim_subset, "generate_mc_port_params", \%g_parameter, \%s_parameter ); + create_attr_access_code( $attr, "l_port_group", ARRAY_DATA, NO_INDEX, \%g_parameter, \%s_parameter ); + create_execute_code( "&(l_value[mss::index(i_target)][0])", $size, NO_INDEX, \%g_parameter, \%s_parameter ); + create_locals_code( $system, PORT_GROUP, \%g_parameter, \%s_parameter ); + + push @{$g_parameters}, \%g_parameter; + push @{$s_parameters}, \%s_parameter; + } + + # + # The whole enchilada + # + { + my %g_parameter = (); + my %s_parameter = (); + my $size = 1; + + # Calculate the size of the last dimensions - these are all we'll copy + for my $dim_size (@dims) + { + $size *= $dim_size; + } + + # Our true size in bytes is multiplied by the size of our valueType + $size *= ${ +BYTE_SIZE }{ $attr->{valueType} }; + + create_params_doxy( $attr, ${ +TARGET_TYPES }{$system}{PORT_GROUP}, + \@dims, "generate_mc_port_params", \%g_parameter, \%s_parameter ); + create_attr_access_code( $attr, "i_target", ARRAY_DATA, NO_INDEX, \%g_parameter, \%s_parameter ); + create_execute_code( "&l_value", $size, NO_INDEX, \%g_parameter, \%s_parameter ); + create_locals_code( $system, NO_LOCALS, \%g_parameter, \%s_parameter ); + + push @{$g_parameters}, \%g_parameter; + push @{$s_parameters}, \%s_parameter; + } + } + + # Per dimm elements with PORT target + if ( ( $attr->{targetType} eq ${ +TARGET_TYPES }{$system}{PORT} ) + && ( scalar(@dims) == $port_dimensions ) ) + { + # + # By DIMM + # + { + # There are some attributes which are 2 dimensional arrays, but aren't [port][dimm] but rather + # [port][data], meaning they're 'per port' attributes. DQ mapping is one example; it doesn't make + # sense to map DQ different for DIMM on a port; they terminate in the same place on the MC. + # So check to see if we have one of those attributes, as we force the caller to ask for the attribute + # per-port as that's what the attribute represents. + if ( !${ +PER_PORT_ATTRIBUTES }{ $attr->{id} } ) + { + my %g_parameter = (); + my %s_parameter = (); + + create_params_doxy( $attr, ${ +TARGET_TYPES }{$system}{DIMM}, + SCALAR_DATA, "generate_mc_port_params", \%g_parameter, \%s_parameter ); + create_attr_access_code( $attr, "l_port", SCALAR_DATA, "l_value[mss::index(i_target)]", + \%g_parameter, \%s_parameter ); + create_execute_code( SCALAR_DATA, 0, "l_value[mss::index(i_target)]", \%g_parameter, \%s_parameter ); + create_locals_code( $system, PORT, \%g_parameter, \%s_parameter ); + + push @{$g_parameters}, \%g_parameter; + push @{$s_parameters}, \%s_parameter; + } + } + + # + # The whole enchilada + # + { + my %g_parameter = (); + my %s_parameter = (); + my $size = 1; + + # Calculate the size of the last dimensions - these are all we'll copy + for my $dim_size (@dims) + { + $size *= $dim_size; + } + + # Our true size in bytes is multiplied by the size of our valueType + $size *= ${ +BYTE_SIZE }{ $attr->{valueType} }; + + create_params_doxy( $attr, ${ +TARGET_TYPES }{$system}{PORT}, + \@dims, "generate_mc_port_params", \%g_parameter, \%s_parameter ); + create_attr_access_code( $attr, "i_target", ARRAY_DATA, NO_INDEX, \%g_parameter, \%s_parameter ); + create_execute_code( "&l_value", $size, NO_INDEX, \%g_parameter, \%s_parameter ); + create_locals_code( $system, NO_LOCALS, \%g_parameter, \%s_parameter ); + + push @{$g_parameters}, \%g_parameter; + push @{$s_parameters}, \%s_parameter; + } + + } +} + +# +# @brief Generate getter method from the paramaters +# @param[in] attr - reference to the attribute to process +# @param[in] dimString - string for array dimensions +# @param[in] parameters_ref - reference to array of accessor parameters +# @return attribute accessor getter string +# +sub generate_getters +{ + # Gets input and checks to make sure it's valid + croak "Incorrect number of inputs passed into gen_accessors::generate_getters" if ( @ARG != 3 ); + + my ( $attr, $dimString, $parameters_ref ) = @ARG; + + my @parameters = @{$parameters_ref}; + + my $getterString = ""; + + foreach my $parameter (@parameters) + { + $getterString .= " ///\n"; + $getterString .= " /// \@brief $attr->{id} getter\n"; + $getterString .= $parameter->{headerString}; + $getterString .= " /// \@return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK\n"; + $getterString .= " /// \@note $attr->{description}\n"; + $getterString .= " ///\n"; + + $getterString .= " inline fapi2::ReturnCode get_$attr->{mssAccessorName}(" . $parameter->{subString} . ")\n"; + $getterString .= " {\n"; + + $getterString .= " " . $attr->{valueType} . "_t l_value$dimString = {};\n" if !$parameter->{noLocals}; + $getterString .= " " . $parameter->{localsString} if $parameter->{localsString}; + $getterString .= "\n"; + + $getterString .= " FAPI_TRY( " . $parameter->{fetchString} . " );\n" if $parameter->{fetchString}; + $getterString .= " " . $parameter->{exeString} if $parameter->{exeString}; + $getterString .= " return fapi2::current_err;\n"; + $getterString .= "\n"; + $getterString .= " fapi_try_exit:\n"; + + if ( $parameter->{customErrTrace} ) + { + $getterString .= $parameter->{customErrTrace}; + } + else + { + $getterString .= " FAPI_ERR(\"failed getting $attr->{id}: 0x%lx (target: %s)\",\n"; + $getterString .= " uint64_t(fapi2::current_err), mss::c_str(i_target));\n"; + } + + $getterString .= " return fapi2::current_err;\n"; + $getterString .= " }\n\n"; + } + + return $getterString; + +} + +# +# @brief Generate setter method from the paramaters +# @param[in] attr - reference to the attribute to process +# @param[in] dimString - string for array dimensions +# @param[in] parameters_ref - reference to array of accessor parameters +# @return attribute accessor setter string +# +sub generate_setters +{ + # Gets input and checks to make sure it's valid + croak "Incorrect number of inputs passed into gen_accessors::generate_setters" if ( @ARG != 3 ); + + my ( $attr, $dimString, $parameters_ref ) = @ARG; + + my @parameters = @{$parameters_ref}; + + my $setterString = ""; + + foreach my $parameter (@parameters) + { + $setterString .= " ///\n"; + $setterString .= " /// \@brief $attr->{id} setter\n"; + $setterString .= $parameter->{headerString}; + $setterString .= " /// \@return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff set is OK\n"; + $setterString .= " /// \@note $attr->{description}\n"; + $setterString .= " ///\n"; + + $setterString .= " inline fapi2::ReturnCode set_$attr->{mssAccessorName}(" . $parameter->{subString} . ")\n"; + $setterString .= " {\n"; + + $setterString .= " " . $attr->{valueType} . "_t l_value$dimString = {};\n" if !$parameter->{noLocals}; + $setterString .= " " . $parameter->{localsString} if $parameter->{localsString}; + $setterString .= "\n"; + + $setterString .= " FAPI_TRY( " . $parameter->{fetchString} . " );\n" if $parameter->{fetchString}; + $setterString .= " " . $parameter->{exeString} if $parameter->{exeString}; + $setterString .= " FAPI_TRY( " . $parameter->{storeString} . " );\n" if $parameter->{storeString}; + $setterString .= " return fapi2::current_err;\n"; + $setterString .= "\n"; + $setterString .= " fapi_try_exit:\n"; + + if ( $parameter->{customErrTrace} ) + { + $setterString .= $parameter->{customErrTrace}; + } + else + { + $setterString .= " FAPI_ERR(\"failed setting $attr->{id}: 0x%lx (target: %s)\",\n"; + $setterString .= " uint64_t(fapi2::current_err), mss::c_str(i_target));\n"; + } + + $setterString .= " return fapi2::current_err;\n"; + $setterString .= " }\n\n"; + } + + return $setterString; + +} + +# +# @brief Generate accessor methods for a given attribute +# @param[in] system - system type +# @param[in] attr - reference to the attribute to process +# @param[in] dims_ref - reference to array of dimensions +# @param[in] array_dimensions - array dimensions string +# @param[in,out] getter_methods_ref - reference to hash of accessor methods +# @param[in,out] setter_methods_ref - reference to hash of setter methods +# +sub generate_accessor_methods +{ + # Gets input and checks to make sure it's valid + croak "Incorrect number of inputs passed into gen_accessors::generate_accessor_methods" if ( @ARG != 6 ); + + my ( $system, $attr, $dims_ref, $array_dimensions, $getter_methods_ref, $setter_methods_ref ) = @ARG; + + my @g_parameters = (); + my @s_parameters = (); + + # Generate parameter info depending on target type + my @target_types = (); + foreach my $type ( keys( %{ ${ +TARGET_TYPES }{$system} } ) ) + { + push( @target_types, ${ +TARGET_TYPES }{$system}{$type} ); + } + + my $attr_type = $attr->{targetType}; + if ( grep( /^$attr_type$/, @target_types ) ) + { + generate_mc_port_params( $system, $attr, $dims_ref, \@g_parameters, \@s_parameters ); + } + else + { + generate_other_attr_params( $system, $attr, $dims_ref, \@g_parameters, \@s_parameters ); + } + + # Generate getter method(s) + my $method_string = generate_getters( $attr, $array_dimensions, \@g_parameters ); + $getter_methods_ref->{ $attr->{targetType} } .= $method_string; + + # Generate setter method(s) only if the attribute has the writeable tag + if ( exists( $attr->{writeable} ) ) + { + $method_string = generate_setters( $attr, $array_dimensions, \@s_parameters ); + $setter_methods_ref->{ $attr->{targetType} } .= $method_string; + } +} + +# +# @brief Generate attribute file text +# @param[in] getters_or_setters - either GETTERS or SETTERS depending on which file to produce +# @param[in] output_dir - directory of output header file to write +# @param[in] output_file_prefix - filename prefix for output header file +# @param[in] method_string - string of getter methods +# @return entire file string to print to header file +# +sub generate_header_file +{ + # Gets input and checks to make sure it's valid + croak "Incorrect number of inputs passed into gen_accessors::print_header_file" if ( @ARG != 4 ); + + my ( $getters_or_setters, $output_dir, $output_file_prefix, $method_string ) = @ARG; + + # If we have no methods, just return + croak "ERROR: no methods found in method_string" if ( $method_string eq "" ); + + my $header_file_name = ""; + my $header_define = ""; + my $file_string = ""; + + if ( $getters_or_setters == GETTERS ) + { + $header_file_name = $output_file_prefix . "_attribute_getters.H"; + $header_define = uc( $output_file_prefix . "_ATTR_GETTERS_H_" ); + } + else + { + $header_file_name = $output_file_prefix . "_attribute_setters.H"; + $header_define = uc( $output_file_prefix . "_ATTR_SETTERS_H_" ); + } + + #------------------------------------------------------------------------------ + # Start of file information + #------------------------------------------------------------------------------ + $file_string .= "// " . $header_file_name . "\n"; + $file_string .= "#ifndef " . $header_define . "\n"; + $file_string .= "#define " . $header_define . "\n"; + $file_string .= "\n"; + $file_string .= "#include <fapi2.H>\n"; + $file_string .= "#include <generic/memory/lib/utils/index.H>\n"; + $file_string .= "#include <generic/memory/lib/utils/c_str.H>\n"; + $file_string .= "\n"; + $file_string .= "\n\nnamespace mss\n{\n"; + $file_string .= "namespace attr\n{\n"; + + #------------------------------------------------------------------------------ + # Getter Methods + #------------------------------------------------------------------------------ + $file_string .= $method_string; + + #------------------------------------------------------------------------------ + # End of file information + #------------------------------------------------------------------------------ + $file_string .= "} // attr\n"; + $file_string .= "} // mss\n\n"; + $file_string .= "#endif\n"; + + return $file_string; +} + +return 1; |