summaryrefslogtreecommitdiffstats
path: root/src/import/generic
diff options
context:
space:
mode:
authorLouis Stermole <stermole@us.ibm.com>2018-11-21 14:30:46 -0600
committerChristian R. Geddes <crgeddes@us.ibm.com>2019-02-13 22:29:30 -0600
commit5421995274d7ca08f0948bef73a89190205ea4b9 (patch)
treef530d78266706415bebb6aa8a09a43eda9105013 /src/import/generic
parentfebbe519b1fc754554b6d94cf4e7b17548c32fe9 (diff)
downloadtalos-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-xsrc/import/generic/memory/tools/gen_accessors.pl217
-rwxr-xr-xsrc/import/generic/memory/tools/gen_accessors.pm1036
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;
OpenPOWER on IntegriCloud