From f2d94b5f809410300fe10dc9d0786790018463a0 Mon Sep 17 00:00:00 2001 From: Shakeeb Date: Sat, 27 Aug 2016 10:50:49 -0500 Subject: SBE code restructure: sbe -> src rename Change-Id: I6e4378d0e71a00ed2b239658d43f180df2a9b748 RTC:159709 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/28875 Tested-by: Jenkins Server Tested-by: FSP CI Jenkins Reviewed-by: RAJA DAS Reviewed-by: Sachin Gupta --- src/tools/debug/simics/makefile | 53 + src/tools/debug/simics/sbe_standalone.simics | 2 + src/tools/debug/simics/sbe_startup.simics | 14 + src/tools/debug/simics/simics-debug-framework.py | 88 ++ src/tools/hooks/addCopyright | 1167 +++++++++++++++ src/tools/hooks/gerrit-hostname | 78 + src/tools/hooks/post-commit | 32 + src/tools/hooks/pre-commit | 38 + src/tools/hooks/pre-commit-actions | 48 + src/tools/hooks/pre-commit-prologs | 46 + src/tools/hooks/setupgithooks.sh | 63 + src/tools/hooks/verify-commit | 358 +++++ src/tools/image/Makefile | 86 ++ src/tools/image/sbe_default_tool.c | 310 ++++ src/tools/ppetracepp/Makefile | 37 + src/tools/ppetracepp/cmvc/makefile | 28 + src/tools/ppetracepp/jhash.h | 166 ++ src/tools/ppetracepp/ppe2fsp.c | 532 +++++++ src/tools/ppetracepp/ppe2fsp.h | 33 + src/tools/ppetracepp/ppe2fsp_cmd.c | 138 ++ src/tools/ppetracepp/ppetracepp.C | 949 ++++++++++++ src/tools/ppetracepp/trac_interface.h | 369 +++++ src/tools/ppetracepp/tracehash.pl | 896 +++++++++++ src/tools/scripts/parseErrorInfo.pl | 1663 +++++++++++++++++++++ src/tools/scripts/ppeCreateAttrGetSetMacros.pl | 571 +++++++ src/tools/scripts/ppeCreateIfAttrService.pl | 240 +++ src/tools/scripts/ppeParseAttrGetSetMacros.pl | 286 ++++ src/tools/scripts/ppeParseAttributeInfo.pl | 746 +++++++++ src/tools/scripts/ppeParseProcSbeFixed.pl | 318 ++++ src/tools/scripts/ppeSetFixed.pl | 259 ++++ src/tools/scripts/src/fapi2PlatAttributeService.H | 1416 ++++++++++++++++++ 31 files changed, 11030 insertions(+) create mode 100755 src/tools/debug/simics/makefile create mode 100755 src/tools/debug/simics/sbe_standalone.simics create mode 100755 src/tools/debug/simics/sbe_startup.simics create mode 100755 src/tools/debug/simics/simics-debug-framework.py create mode 100755 src/tools/hooks/addCopyright create mode 100755 src/tools/hooks/gerrit-hostname create mode 100755 src/tools/hooks/post-commit create mode 100755 src/tools/hooks/pre-commit create mode 100755 src/tools/hooks/pre-commit-actions create mode 100755 src/tools/hooks/pre-commit-prologs create mode 100755 src/tools/hooks/setupgithooks.sh create mode 100755 src/tools/hooks/verify-commit create mode 100644 src/tools/image/Makefile create mode 100644 src/tools/image/sbe_default_tool.c create mode 100644 src/tools/ppetracepp/Makefile create mode 100644 src/tools/ppetracepp/cmvc/makefile create mode 100755 src/tools/ppetracepp/jhash.h create mode 100755 src/tools/ppetracepp/ppe2fsp.c create mode 100644 src/tools/ppetracepp/ppe2fsp.h create mode 100644 src/tools/ppetracepp/ppe2fsp_cmd.c create mode 100755 src/tools/ppetracepp/ppetracepp.C create mode 100755 src/tools/ppetracepp/trac_interface.h create mode 100755 src/tools/ppetracepp/tracehash.pl create mode 100755 src/tools/scripts/parseErrorInfo.pl create mode 100755 src/tools/scripts/ppeCreateAttrGetSetMacros.pl create mode 100755 src/tools/scripts/ppeCreateIfAttrService.pl create mode 100644 src/tools/scripts/ppeParseAttrGetSetMacros.pl create mode 100755 src/tools/scripts/ppeParseAttributeInfo.pl create mode 100755 src/tools/scripts/ppeParseProcSbeFixed.pl create mode 100755 src/tools/scripts/ppeSetFixed.pl create mode 100644 src/tools/scripts/src/fapi2PlatAttributeService.H (limited to 'src/tools') diff --git a/src/tools/debug/simics/makefile b/src/tools/debug/simics/makefile new file mode 100755 index 00000000..473c0088 --- /dev/null +++ b/src/tools/debug/simics/makefile @@ -0,0 +1,53 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/tools/debug/simics/makefile $ +# +# OpenPOWER sbe Project +# +# Contributors Listed Below - COPYRIGHT 2016 +# +# +# 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 +# +# FSP Destination: obj/ppc/sbei/sbfw/simics/makefile +# +# NOTE: Do NOT modify this file in CMVC directly! It comes from the SBE +# repository and will be overwritten. + +.include <${RULES_MK}> + +OTHERS = copy_scripts + +SBE_SIMICS_PATH = ${MAKETOP}simu/scripts/sbfw/ + +SBE_SRC_PATHS = ${.PATH:M*src*sbei*sbfw*simics*} ${.PATH:M*obj*sbei*sbfw*simics*} +SBE_SRC_DIRS = ${SBE_SRC_PATHS:XD} +SBE_SRC_FILES = ${:!${SBE_SRC_DIRS:@path@ls ${path};@}!} + +SBE_SCRIPTS_TO_COPY = ${SBE_SRC_FILES:Nmakefile} +SBE_SCRIPTS_PATHS = ${SBE_SCRIPTS_TO_COPY:p} + +SBE_COPY_COMMAND = \ + ${SBE_SCRIPTS_PATHS:@file@cp -r ${file} ${SBE_SIMICS_PATH}; @} +SBE_REMOVE_COMMAND = \ + ${SBE_SCRIPTS_TO_COPY:@file@rm -rf ${SBE_SIMICS_PATH}${file}; @} + +copy_scripts: + mkdir -p ${SBE_SIMICS_PATH} + ${SBE_COPY_COMMAND} + +clobber_copy_scripts: + ${SBE_REMOVE_COMMAND} diff --git a/src/tools/debug/simics/sbe_standalone.simics b/src/tools/debug/simics/sbe_standalone.simics new file mode 100755 index 00000000..8fd3bdb0 --- /dev/null +++ b/src/tools/debug/simics/sbe_standalone.simics @@ -0,0 +1,2 @@ +echo "SBE standalone Tools" + diff --git a/src/tools/debug/simics/sbe_startup.simics b/src/tools/debug/simics/sbe_startup.simics new file mode 100755 index 00000000..5d466a20 --- /dev/null +++ b/src/tools/debug/simics/sbe_startup.simics @@ -0,0 +1,14 @@ +echo "Attempting to register SBE Tools" + +# Load SBE debug tools. +try { + $sbe_startup_path = (lookup-file sbfw/simics-debug-framework.py); + $sbe_script_location = (python "''.join(map('/'.__add__,\""+$sbe_startup_path+"\"[1:].split('/')[0:-1]))") + python "os.environ['SBE_TOOLS_PATH'] = \""+$sbe_script_location+"\"" + echo $sbe_script_location; + run-python-file (lookup-file sbfw/simics-debug-framework.py) + # Set mailbox scratch registers so that the SBE starts in plck mode + # p9Proc0.proc_chip.invoke parallel_store SCOM 0x5003F "20000000_00000000" 64 + # p9Proc0.proc_chip.invoke parallel_store SCOM 0x5003A "00000000_00000000" 64 +} except { echo "ERROR: Failed to load SBE debug tools." } + diff --git a/src/tools/debug/simics/simics-debug-framework.py b/src/tools/debug/simics/simics-debug-framework.py new file mode 100755 index 00000000..87d3656b --- /dev/null +++ b/src/tools/debug/simics/simics-debug-framework.py @@ -0,0 +1,88 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/tools/debug/simics/simics-debug-framework.py $ +# +# OpenPOWER sbe Project +# +# Contributors Listed Below - COPYRIGHT 2016 +# +# +# 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 +import os +import os.path +import subprocess +import re +import random +import sys +import imp +testIstepAuto = imp.load_source("testIstepAuto", os.environ['SBE_TOOLS_PATH'] + "/testIstepAuto.py") +err = False + +syms = {}; + +def check_sbe_tools_path (): + global SBE_TOOLS_PATH + SBE_TOOLS_PATH = os.environ['SBE_TOOLS_PATH']; + +def register_sbe_debug_framework_tools(): + check_sbe_tools_path () + fillSymTable() + # Create command hook. + new_command("sbe-istep",testIstepAuto.sbe_istep_func, + args = [arg(int_t, "major"), arg(int_t, "minor")], + alias = "istep", + type = ["sbe-commands"], + short = "Runs the debug framework for istep ", + doc = "") + new_command("sbe-trace", collectTrace, + args = [arg(int_t, "procNr")], + alias = "strace", + type = ["sbe-commands"], + short = "Runs the debug framework for trace ", + doc = "") + print "SBE Debug Framework: Registered tool:", "sbe-istep" + print "SBE Debug Framework: Registered tool:", "sbe-trace" + + +def fillSymTable(): +# symFile = os.environ['SBE_IMG_OUT_LOC'] + "/sbe.syms" + symFile = SBE_TOOLS_PATH + "/sbe.syms" +# symFile = os.environ['sb'] + "/../obj/ppc/sbei/sbfw/simics/sbe.syms" + f = open( symFile, 'r') + for line in f: + words = line.split() + if( len( words ) == 4 ): + syms[words[3]] = [words[0], words[1]] + +def collectTrace ( procNr ): + fileName = "sbe_" + `procNr` + "_tracMERG" + cmd1 = "pipe \"p9Proc" + `procNr` + ".sbe.mibo_space.x 0x" + syms['g_pk_trace_buf'][0] + " 0x2028\" \"sed 's/^p:0x........ //g' | sed 's/ ................$//g' | sed 's/ //g' | xxd -r -p> ppetrace.bin\"" + cmd2 = "shell \"" + SBE_TOOLS_PATH + "/ppe2fsp ppetrace.bin sbetrace.bin \"" + cmd3 = "shell \"" + SBE_TOOLS_PATH + "/fsp-trace -s " + SBE_TOOLS_PATH + "/sbeStringFile sbetrace.bin >" + fileName + "\"" + cmd4 = "shell \"" + "cat " + fileName + "\"" + + ( rc, out ) = quiet_run_command( cmd1, output_modes.regular ) + if ( rc ): + print "simics ERROR running %s: %d "%( cmd1, rc ) + + SIM_run_alone( run_command, cmd2 ) + SIM_run_alone( run_command, cmd3 ) + SIM_run_alone( run_command, cmd4 ) + + +# Run the registration automatically whenever this script is loaded. +register_sbe_debug_framework_tools() + diff --git a/src/tools/hooks/addCopyright b/src/tools/hooks/addCopyright new file mode 100755 index 00000000..13867e7e --- /dev/null +++ b/src/tools/hooks/addCopyright @@ -0,0 +1,1167 @@ +#!/usr/bin/perl +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: sbe/tools/hooks/addCopyright.pl $ +# +# OpenPOWER sbe Project +# +# Contributors Listed Below - COPYRIGHT 2016 +# [+] 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 +#################################### ABOUT #################################### +# Forked from: # +# Author: Mark Jerde (mjerde@us.ibm.com) # +# Date: Fri Mar 19 17:40:32 2010 UTC # +# # +# addCopyright will automatically insert appropriate copyright statements # +# in source files following the IBM copyright guidelines (and templates) # +# referenced below : # +# FSP ClearCase Architecture # +# Version 1.9 # +# 10/12/2010 # +# Editor: Alan Hlava # +# # +# Section 3.14.1 of the above doc has templates for different files # +# # +# NOTE: FSP uses the phrase "OCO Source materials" in their copyright # +# block, which is classified as 'p1' . We will use the same # +# classification here. # +# NOTE: to list all files in src EXCEPT the build dir, run: # +# make clean # remove autogenerated files # +# find src -path 'src/build' -prune -o ! -type d -print | tr '\n' ' ' # +# # +# addCopyright does not support piping, but you can send these # +# to a file, add "addCopyright update" to the beginning of the line, # +# and run the file to update all # +############################################################################### + +use strict; +use warnings; +use POSIX; +use Getopt::Long; +use File::Basename; +use lib dirname (__FILE__); +use Cwd; + +#------------------------------------------------------------------------------ +# Project-specific settings. +#------------------------------------------------------------------------------ +my $ReleaseYear = `date +%Y`; +chomp( $ReleaseYear ); +$ReleaseYear = $ENV{'DATE_OVERRIDE'} if defined $ENV{'DATE_OVERRIDE'}; + +my $copyrightSymbol = ""; +# my $copyrightSymbol = "(C)"; # Uncomment if unable to use  character. + +# set by environment variable in project env.bash +my $projectName = $ENV{'PROJECT_NAME'}; +my $copyrightPrefix = "Contributors Listed Below - "; +my $copyrightStr = $copyrightPrefix."COPYRIGHT"; +my $projectRoot = $ENV{'SBEROOT'}; +# Relative path of import tree from project root +my $importPrefix = $ENV{'IMPORT_REL_PATH'}."/"; + +## note that these use single ticks so that the escape chars are NOT evaluated yet. +my $OLD_DELIMITER_END = 'IBM_PROLOG_END'; +my $DELIMITER_END = 'IBM_PROLOG_END_TAG'; +my $DELIMITER_BEGIN = 'IBM_PROLOG_BEGIN_TAG'; + +my $SOURCE_BEGIN_TAG = "\$Source:"; +my $SOURCE_END_TAG = "\$"; + +# Desired License, set by environment variable in project env.bash +my $LicenseFile = $ENV{'LICENSE'}; +use constant LICENSE_PROLOG => "LICENSE_PROLOG"; + +#------------------------------------------------------------------------------ +# Contributer info +#------------------------------------------------------------------------------ + +# Constants for company's copyright +# When adding a new company add constant here and to %fileContributorsCompany +use constant IBM => 'International Business Machines Corp.'; +use constant GOOGLE => 'Google Inc.'; + +# Create mapping for git contrubitors to companies +my %fileContributorsCompany = ( + "ibm.com" => IBM, + "ozlabs.org" => IBM, + "google.com" => GOOGLE, + "Google Shared Technology" => GOOGLE, +); + +#------------------------------------------------------------------------------ +# Constants +#------------------------------------------------------------------------------ +use constant RC_INVALID_PARAMETERS => 1; +use constant RC_NO_COPYRIGHT_BLOCK => 2; +use constant RC_BAD_CONTRIBUTORS_BLOCK => 3; +use constant RC_INVALID_FILETYPE => 4; +use constant RC_DIFFERS_FROM_LICENSE_PROLOG => 5; +use constant RC_NO_LICENSE_PROLOG_FILE => 6; + +#------------------------------------------------------------------------------ +# Global Vars +#------------------------------------------------------------------------------ +my $opt_help = 0; +my $opt_debug = 0; +my $operation = ""; +my $opt_logfile = ""; + +my $DelimiterBegin = ""; +my $CopyrightBlock = ""; +my $DelimiterEnd = ""; +my $CopyRightString = ""; +my $copyright_check = 0; + +my $TempFile = ""; +my @Files = (); + +my $rc = 0; + +# NOTE: $OLD_DELIMITER_END is a subset of $DELIMITER_END so must match +# $DELIMITER_END first in order to return the entire string. +my $g_end_del_re = "($DELIMITER_END|$OLD_DELIMITER_END)"; +my $g_prolog_re = "($DELIMITER_BEGIN)((.|\n)+?)$g_end_del_re"; + +####################################################################### +# Main +####################################################################### +if (scalar(@ARGV) < 2) +{ + ## needs at least one filename and an operation as a parameter + usage(); +} + + +my @SaveArgV = @ARGV; +#------------------------------------------------------------------------------ +# Parse optional input arguments +#------------------------------------------------------------------------------ +GetOptions( "help|?" => \$opt_help, + "validate" => sub { $operation="validate"; }, + "update" => sub { $operation="update"; }, + "copyright-check" => \$copyright_check, + "log-failed-files=s" => \$opt_logfile, + "debug" => \$opt_debug, + ); + +## scan through remaining args and store all files in @Files +## check for old-type parms, just in case +foreach ( @ARGV ) +{ + ## print $_; + if ( m/^debug$/ ) { $opt_debug = 1; next; } + if ( m/^update$/ ) { $operation = $_; next; } + if ( m/^validate$/ ) { $operation = $_; next; } + + push @Files, $_ ; +} + + +if ( $opt_debug ) +{ + print STDERR __LINE__, " : ---- DEBUG -----\n"; + print STDERR "help = $opt_help\n"; + print STDERR "debug = $opt_debug\n"; + print STDERR "operation = $operation\n"; + print STDERR "log-failed-files = $opt_logfile\n"; + + ## dump files specified + print STDERR "Files:\n"; + print STDERR join( ' ', @Files ), "\n"; + + print STDERR "ReleaseYear = $ReleaseYear\n"; + + print "\n"; +} + +if ( $operation eq "" ) +{ + print STDOUT "No operation specified\n"; + usage(); + exit RC_INVALID_PARAMETERS; +} + +if ( ( $opt_logfile ne "" ) + ## && ( $operation eq "validate" ) + ) +{ + my $logdate = `date +%Y-%m-%d:%H%M`; + chomp $logdate; + open( LOGFH, "> $opt_logfile" ) or die "ERROR $?: Failed to open $opt_logfile: $!"; + print LOGFH "## logfile generated $logdate from command line:\n"; + print LOGFH $0, " ", join( ' ', @SaveArgV ); + print LOGFH "\nFAILING files:\n"; +} + +######################################################################## +## MAIN +######################################################################## +# Loop through all files and process. +foreach ( @Files ) +{ + + ## clear global vars + $DelimiterBegin = ""; + $CopyrightBlock = ""; + $DelimiterEnd = ""; + $CopyRightString = ""; + $rc = 0; + + + ## get filetype + my $filetype = filetype($_); + print STDOUT "File $_: Type $filetype\n"; + + ## set Temporary file name. + $TempFile = "$_.gitCPYWRT"; + if ( $opt_debug ) { print STDERR __LINE__, ": Temporary file name = $TempFile\n"; } + + ## + ## Special case is this file, just return 0 and add copyright manually. + ## + if ( m/addCopyright/ ) + { + print STDOUT "---------------------------------------------------------\n"; + print STDOUT "Skipping special case file: $_\n"; + print STDOUT " Please add the copyright prolog manually.\n"; + print STDOUT "---------------------------------------------------------\n"; + next; + } + + ## + ## Gerrit submissions can include deleted files, just warn and continue + if ( ! -e $_ ) + { + print STDOUT "---------------------------------------------------------\n"; + print STDOUT "Skipping deleted file: $_\n"; + print STDOUT "---------------------------------------------------------\n"; + next; + } + + ## + ## Unknown files are valid, but should generate a warning. + if ("Unknown" eq $filetype) + { + print STDOUT "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"; + print STDOUT "WARNING:: File $_ :Unknown Filetype: $filetype\n"; + print STDOUT " Skipping this file and continuing.\n"; + print STDOUT " Please add the copyright prolog manually.\n"; + print STDOUT "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"; + + next; + } + + ## + ## text files are valid, but should generate a warning. + if (("txt" eq $filetype) || "Initfile" eq $filetype) + { + print STDOUT "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"; + print STDOUT "WARNING:: File $_ : Filetype: $filetype\n"; + print STDOUT " Skipping this file and continuing.\n"; + print STDOUT " If needed, Please add the copyright \n"; + print STDOUT " prolog manually.\n"; + print STDOUT "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"; + + next; + } + + ## + ## Check if any parent directory below $projectRoot has a LICENSE_PROLOG file + ## Backtrack from the directory where the file lives and find the first + ## custom LICENSE_PROLOG file. + my $path = cwd."/".$_; + do + { + # Remove everything after last slash + $path =~ s|/[^/]*$||; + # Check if path has LICENSE_PROLOG file + my $custom_license_file = $path."/".LICENSE_PROLOG; + if (-e $custom_license_file) + { + # Set LicenseFile to closest custom LICENSE_PROLOG to file. + $LicenseFile = $custom_license_file; + # Exit loop, 'last' breaks out of both loops. + $path = $projectRoot; + } + } while ($path ne $projectRoot); + + $CopyrightBlock = extractCopyrightBlock( $_ ); + + ## + ## validate the file. + ## if $logfile exists, print failing filename to $logfile and + ## keep going. + ## Otherwise, exit with $rc + ## + if ( $operation =~ m/validate/i ) + { + $rc = validate( $_ ); + if ( $rc ) + { + print STDOUT "$_ FAILED copyright validation: $rc \n"; + if ( $opt_logfile ne "" ) + { + print LOGFH "$_ # FAILED $rc \n"; + } + else + { + exit $rc; + } + } + + ## continue to next file + next; + } ## endif validate + + ## + ## update + ## + if ($operation =~ m/update/i) + { + $rc = update( $_, $filetype ); + if ( $rc ) + { + print STDOUT "$_ FAILED copyright update: $rc \n"; + exit $rc; + } + + ## continue to next file + next; + } ## endif update + +} # end foreach + +if ( $opt_logfile ne "" ) +{ + close( LOGFH ); +} + +######################################################################### +## Subroutines +######################################################################### + +####################################### +## usage: print usage and quit +####################################### +sub usage +{ + print STDOUT "Usage: addCopyright { update | validate } \n"; + print STDOUT " [ --log-failed-files ]\n"; + print STDOUT " [ --debug ] \n"; + print STDOUT " file1 file2 ...\n"; + +} + +####################################### +## validate the file +## param[in] $filename to validate +## returns 0 success, nonzero failure +## See constants above for values of failure +####################################### +sub validate +{ + my ( $filename ) = @_; + my $rc = 0; + + if ( $CopyrightBlock eq "" ) + { + print STDOUT "WARNING: No copyright block.\n"; + return RC_NO_COPYRIGHT_BLOCK; + } + + $rc = checkCopyrightBlock( $CopyrightBlock, $filename); + + # good file + return $rc; +} + +## +## @sub update the copyright block. +## +## @param[in] filename +## @param[in] filetype +## +## @return success or failure (currently only return success) +## +sub update +{ + my ( $filename, $filetype ) = @_; + my $olddelimiter = 0; + my $localrc = 0; + $localrc = validate( $filename ); + + if ( $localrc != 0 ) + { + print STDOUT "Copyright Block check returned $localrc , fixing...\n"; + + if ( $localrc != RC_NO_COPYRIGHT_BLOCK ) + { + if ( $opt_debug) { print STDERR __LINE__, ": remove old copyright block...\n"; } + removeCopyrightBlock( $filename, $filetype ); + } + + if ($opt_debug) { print STDERR __LINE__, ": Add empty copyright block...\n"; } + addEmptyCopyrightBlock( $filename, $filetype, $localrc ); + + if ( $opt_debug ) { print STDERR __LINE__, ": fill in new copyright block...\n"; } + fillinEmptyCopyrightBlock( $filename, $filetype); + } + + ## return OK by default. + return 0; +} + + +##################################### +## Analyze file and return a text string of the file type +##################################### +sub filetype +{ + my $filename = shift; + my $fileinfo = `file $filename | sed 's/^.*: //'`; + chomp $fileinfo; + + # Sorted by anticipated frequency of occurrence. + if ( $filename =~ m/\.xml$/i ) + # Added XML file to the top of the list because some comments in + # an XML file cause older versions of 'file' to incorrectly return + # "ASCII C++ program text" even though the file is obviously XML. + # Specifically we are seeing "' ); + } + elsif ( "Assembly" eq $filetype ) + { + $data = removeProlog( $data, '\#', '' ); + } + elsif ( ("Autoconf" eq $filetype) or + ("Automake" eq $filetype) or + ("CVS" eq $filetype) or + ("Makefile" eq $filetype) or + ("Perl" eq $filetype) or + ("PrdRuleFile" eq $filetype) or + ("Python" eq $filetype) or + ("Shellscript" eq $filetype) or + ("Tcl" eq $filetype) + ) + { + # Don't wipe the the '#!' line at the top. + $data = removeProlog( $data, '\#', '' ); + } + else + { + print STDOUT "ERROR: Don't know how to remove old block from $filetype file.\n"; + close OUTPUT; + return RC_INVALID_FILETYPE; + } + + print OUTPUT $data; + + ## finish up the files + close( OUTPUT ) or die " $? can't close $TempFile: $!" ; + rename( $filename, "$savedbgfile" ) or die " $? can't rename $filename: $!" ; + rename( $TempFile, $filename ) or die " $? can't rename $TempFile: $!" ; + if ( !$opt_debug ) + { + ## leave the files around for debug + unlink( $savedbgfile ) or die " $? can't delete $savedbgfile: $!"; + + } +} + +################################### +## Add an empty copyright block to the file, for example (C/C++ files): +## +## // IBM_PROLOG_BEGIN_TAG IBM_PROLOG_END_TAG +## +## - The block will be filled-in in the next step. +## +## @param[in] - filename to modify +## @param[in] - filetype +## @param[in] - returncode from validate +## +## @return none +## +## - Makes up a debug file called ".empty" +################################## +sub addEmptyCopyrightBlock +{ + my ( $filename, $filetype, $validaterc ) = @_; + my $line; + + ## Modify file in place with temp file Perl Cookbook 7.8 + my $savedbgfile = "$filename.empty"; + system( "cp -p $filename $TempFile" ) ; ## preserve permissions + open( INPUT, "< $filename" ) or die " $? can't open $filename: $!" ; + open( OUTPUT, "> $TempFile" ) or die " $? can't open $TempFile: $!" ; + select( OUTPUT ); ## new default filehandle for print + + if (("Autoconf" eq $filetype) or + ("Automake" eq $filetype) or + ("CVS" eq $filetype) or + ("Perl" eq $filetype) or + ("Python" eq $filetype) or + ("Shellscript" eq $filetype) or + ("Tcl" eq $filetype)) + { + ## All files with a "shebang" at the beginning + $line = ; + # Keep the '#!' line at the top. + ## The following says : if the first line is a "shebang" line + ## (e.g. "#!/usr/bin/perl"), then print it _before_ the copyright + ## block, otherwise (the unless line), print it _after_ the copyright + ## block. + if ($line =~ m/^#!/) + { + print OUTPUT $line; + } + print OUTPUT "$DELIMITER_BEGIN $DELIMITER_END\n"; + unless ($line =~ m/^#!/) + { + print OUTPUT $line; + } + } + else + { + print OUTPUT "$DELIMITER_BEGIN $DELIMITER_END\n"; + } + + # Copy rest of file + while (defined($line = )) + { + print OUTPUT $line; + } + + ## finish up the files + close( INPUT ) or die " $? can't close $filename: $!" ; + close( OUTPUT ) or die " $? can't close $TempFile: $!" ; + rename( $filename, "$savedbgfile" ) or die " $? can't rename $filename: $!" ; + rename( $TempFile, $filename ) or die " $? can't rename $TempFile: $!" ; + if ( !$opt_debug ) + { + ## leave the files around for debug + unlink( $savedbgfile ) or die " $? can't delete $savedbgfile: $!"; + } +} + +############################################ +## Helper functions for fillinEmptyCopyrightBlock() +############################################ +sub addPrologComments +{ + my ( $data, $begin, $end ) = @_; + + my @lines = split( /\n/, $data ); + + $data = ''; + for my $line ( @lines ) + { + # If there is an block comment end tag, fill the end of the line with + # spaces. + if ( $end ) + { + my $max_line_len = 70; + my $len = length($line); + if ( $len < $max_line_len ) + { + my $fill = ' ' x ($max_line_len - $len); + $line .= $fill; + } + } + + # NOTE: CMVC prologs with inline comments will have a single trailing + # space at the end of the line. This is undesirable for most + # developers so it will not be added. + if ( $line =~ m/$DELIMITER_BEGIN/) + { + $line = "$line $end" if ( $end ); + $line = "$begin $line\n"; + } + elsif ( $line =~ m/$DELIMITER_END/ ) + { + $line = "$line $end" if ( $end ); + $line = "$begin $line"; + } + else + { + if ( not $end and not $line ) + { + # Compensate for blank lines with no end delimeter. + $line = "$begin\n"; + } + else + { + $line = "$begin $line"; + $line = "$line $end" if ( $end ); + $line = "$line\n"; + } + } + + $data .= $line; + } + + return $data; +} + +############################################ +## Generates final copyright block +## +## @parma[in] filename +## +## @return final copyright block string +############################################ +sub genCopyrightBlock +{ + my ($filename, $filetype) = @_; + + my $copyrightYear = createYearString( $filename ); + + # Get copyright contributors based on hash so no duplicates + my %fileContributors = getFileContributors( $filename ); + my $copyright_Contributors = ""; + + foreach my $key (sort keys %fileContributors) + { + $copyright_Contributors .= "[+] ".$key."\n"; + } + + ## Get desired license + my $LicenseContent = ""; + open(LICENSE, "< $LicenseFile") or die " $? can't open $LicenseFile: $!" ; + while (my $line = ) + { + my $evalLine = eval "qq($line)"; + $LicenseContent .= $evalLine; + } + close(LICENSE); + + ## define the final copyright block template here. + my $IBMCopyrightBlock = <'); + } + else + { + print STDOUT "ERROR: Can\'t handle filetype: $filetype\n"; + return RC_INVALID_FILETYPE; + } + + return $IBMCopyrightBlock; +} + +############################################ +## fill in the empty copyright block +## Copyright guidelines from: +## FSP ClearCase Architecture +## Version 1.9 +## 10/12/2010 +## Editor: Alan Hlava +## +## Section 3.14.1 has templates for different files +## +############################################ +sub fillinEmptyCopyrightBlock +{ + my ( $filename, $filetype ) = @_; + + my $copyrightYear = createYearString( $filename ); + + ## define the final copyright block template here. + my $IBMCopyrightBlock = genCopyrightBlock($filename,$filetype); + + ## Modify file in place with temp file Perl Cookbook 7.8 + my $savedbgfile = "$filename.fillin"; + system( "cp -p $filename $TempFile" ); ## preserve file permissions + open( INPUT, "< $filename" ) or die " $? can't open $filename: $!" ; + my $newline; + my $lines = ""; + while ( defined($newline = ) ) { $lines .= $newline; } + + # Replace existing block with the current content. + $lines =~ s/$DELIMITER_BEGIN[^\$]*$DELIMITER_END/$IBMCopyrightBlock/s; + + open( OUTPUT, "> $TempFile" ) or die " $? can't open $TempFile: $!" ; + select( OUTPUT ); ## new default filehandle for print + print OUTPUT $lines; + + ## finish up the files + close( INPUT ) or die " $? can't close $filename: $!" ; + close( OUTPUT ) or die " $? can't close $TempFile: $!" ; + rename( $filename, "$savedbgfile" ) or die " $? can't rename $filename: $!" ; + rename( $TempFile, $filename ) or die " $? can't rename $TempFile: $!" ; + if ( !$opt_debug ) + { + ## leave the files around for debug + unlink( $savedbgfile ) or die " $? can't delete $savedbgfile: $!"; + } +} + +####################################### +## Gets file contirbutors based on git log of a file +## +## @parma[in] filename +## +## @return hash of contributors (key,value) => (name/company, 1) +####################################### +sub getFileContributors +{ + my ( $filename ) = @_; + # Create a "set like" hash for file contributors to handle duplicates + # so key is the only important information + my %fileContributors = (); + + # Check file for company Origin + my $gitDomain = `git log --follow --find-copies-harder -C85% -M85% -- $filename | grep Origin: | sort | uniq`; + my @gitDomain = split('\n', $gitDomain); + foreach my $origin (@gitDomain) + { + chomp($origin); + # Remove all characters through word "Origin:" + $origin =~ s/[^:]*\://; + # Remove white space after colon + $origin =~ s/^\s+//; + if (exists($fileContributorsCompany{$origin})) + { + # Add company info for copyright contribution + $fileContributors{$fileContributorsCompany{$origin}} = 1; + } + } + + # Check file for all contributors + my $gitAuthors = `git log --follow --find-copies-harder -C85% -M85% --pretty="%aN <%aE>" -- $filename | sort | uniq`; + my @gitAuthors = split('\n', $gitAuthors); + + # Get commit's author + # # If running copyright_check run 'git log' as a commit is not taking place + # # Else we currently have no way of getting the current author. Because + # # this is a pre-commit hook, the commit staged to be committed does not + # # show up in 'git log' until commit has completed. We cannot look up + # # current user's info because the user pushing the commit may not be + # # the author. + + if($copyright_check) + { + my $curAuthorEmail = `git log -n1 --pretty=format:"%aN <%aE>"`; + chomp($curAuthorEmail); + push(@gitAuthors, $curAuthorEmail); + } + # Internal mirror, add IBM as contributor + elsif (defined $ENV{'MIRROR'}) + { + push(@gitAuthors, "\@ibm.com>"); + } + + foreach my $contributor (@gitAuthors) + { + my $companyExists = 0; + chomp($contributor); + # Grab company domain out of contributor's email + my $domain = substr ($contributor, index($contributor, '@') + 1, -1); + + # Due to multiple prefixes for IBM like us, in, linux, etc will try + # removing characters up to each period (.) until correct domain + # address found + my @domainSections = split(/\./,$domain); + for (my $i = 0; $i < @domainSections; $i++) + { + if (exists($fileContributorsCompany{$domain})) + { + $companyExists = 1; + last; + } + # Remove all characters upto & including the first period (.) seen + $domain =~ s/[^.]*\.//; + } + + #Check if contributor's company exists + if ($companyExists) + { + # Add company info for copyright contribution + $fileContributors{$fileContributorsCompany{$domain}} = 1; + } + else + { + my $name = substr ($contributor, 0, index($contributor, '<') -1); + if($name) + { + # Add individual info for copyright contribution + $fileContributors{$name} = 1; + } + else + { + die("Cannot find name of contributor in git commit"); + } + } + } + return %fileContributors; +} diff --git a/src/tools/hooks/gerrit-hostname b/src/tools/hooks/gerrit-hostname new file mode 100755 index 00000000..58c68d63 --- /dev/null +++ b/src/tools/hooks/gerrit-hostname @@ -0,0 +1,78 @@ +#!/usr/bin/perl +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/tools/hooks/gerrit-hostname $ +# +# OpenPOWER sbe Project +# +# Contributors Listed Below - COPYRIGHT 2016 +# +# +# 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 + +## Usage +# It is imperative that there are no prints other than the die command or +# "export GERRIT_SRV=$host" as this script is evaluated by env.bash and not +# called directly + +use strict; + +my $homeDir = $ENV{'HOME'}; +my $sshConfigFile = $homeDir."/.ssh/config"; +# If the server changes location these will change +my $gerritHostname = "ralgit01.raleigh.ibm.com"; +my $gerritPort = "29418"; + +open(CONFIG, "< $sshConfigFile") or die " $? can't open $sshConfigFile: $!" ; + +my $host = ""; +my $hostname = ""; +my $port = ""; +while (my $line = ) +{ + # Whitespace after each constant is important + if ($line =~ m/^Host [^\s]/) + { + ($host) = $line =~ m/^Host (.*?)\s/ + } + elsif ($line =~ m/Hostname [^\s]/) + { + ($hostname) = $line =~ m/^*Hostname (.*)/; + } + elsif ($line =~ m/Port [^\s]/) + { + ($port) = $line =~ m/^*Port (.*)/; + } + + # Check if we found the gerrit host name + if ($host ne "" && + $hostname eq $gerritHostname && + $port eq $gerritPort) + { + last; + } +} +close(CONFIG); + +if ($host eq "") +{ + die "Error> Could not find gerrit host in $sshConfigFile"; +} +else +{ + # Set gerrit server env variable by returning command to env.bash + print "export GERRIT_SRV=$host\n"; +} diff --git a/src/tools/hooks/post-commit b/src/tools/hooks/post-commit new file mode 100755 index 00000000..21751582 --- /dev/null +++ b/src/tools/hooks/post-commit @@ -0,0 +1,32 @@ +#!/bin/sh +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/tools/hooks/post-commit $ +# +# OpenPOWER sbe Project +# +# Contributors Listed Below - COPYRIGHT 2016 +# +# +# 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 + +# NOTE: pre-commit hook and its associated helper functions are all +# maintained same as that of Hoostboot except for minor changes to +# suit the PPE environment. + +if [ -z $MIRROR ]; then + $TOOLSDIR/verify-commit +fi diff --git a/src/tools/hooks/pre-commit b/src/tools/hooks/pre-commit new file mode 100755 index 00000000..9e05432f --- /dev/null +++ b/src/tools/hooks/pre-commit @@ -0,0 +1,38 @@ +#!/bin/sh +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/tools/hooks/pre-commit $ +# +# OpenPOWER sbe Project +# +# Contributors Listed Below - COPYRIGHT 2016 +# +# +# 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 + +# NOTE: pre-commit hook and its associated helper functions are all +# maintained same as that of Hoostboot except for minor changes to +# suit the PPE environment. + +if [ -f $TOOLSDIR/pre-commit-actions ]; then + $TOOLSDIR/pre-commit-actions +# Legacy support for older releases +elif [ -f $TOOLSDIR/pre-commit-prologs ]; then + $TOOLSDIR/pre-commit-prologs +else + echo "Missing pre-commit files" + exit -1 +fi diff --git a/src/tools/hooks/pre-commit-actions b/src/tools/hooks/pre-commit-actions new file mode 100755 index 00000000..821e78de --- /dev/null +++ b/src/tools/hooks/pre-commit-actions @@ -0,0 +1,48 @@ +#!/usr/bin/perl +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/tools/hooks/pre-commit-actions $ +# +# OpenPOWER sbe Project +# +# Contributors Listed Below - COPYRIGHT 2016 +# +# +# 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 +# This hook is used to add or update copyright prolog statements and run +# the code beautifier astyle. + +my $copyrightScript = "addCopyright"; + +## Make up a list of all staged files ( --cached --name-only ) +## Filter for only Added or Modified ( --diff-filter=AM ) +chomp( my @fileList = `git diff --cached --name-only --diff-filter=AM` ); + + +if ( @fileList ) +{ + print "run $copyrightScript update ...\n"; + print " $_\n" foreach @fileList; + print "\n"; + + system "$ENV{'TOOLSDIR'}/$copyrightScript update @fileList"; + die("$?") if ($? != 0); + + system "git add @fileList"; + exit 1 if ($? != 0); +} + +exit 0; diff --git a/src/tools/hooks/pre-commit-prologs b/src/tools/hooks/pre-commit-prologs new file mode 100755 index 00000000..eb53e316 --- /dev/null +++ b/src/tools/hooks/pre-commit-prologs @@ -0,0 +1,46 @@ +#!/usr/bin/perl +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/tools/hooks/pre-commit-prologs $ +# +# OpenPOWER sbe Project +# +# Contributors Listed Below - COPYRIGHT 2016 +# +# +# 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 +# This hook is used to add or update copyright prolog statements + +my $script = "addCopyright"; + +## Make up a list of all staged files ( --cached --name-only ) +## Filter for only Added or Modified ( --diff-filter=AM ) +chomp( my @fileList = `git diff --cached --name-only --diff-filter=AM` ); + +if ( @fileList ) +{ + print "run $script update ...\n"; + print " $_\n" foreach @fileList; + print "\n"; + + system "$ENV{'TOOLS_DIR'}/$script update @fileList"; + die("$?") if ($? != 0); + + system "git add @fileList"; + exit 1 if ($? != 0); +} + +exit 0; diff --git a/src/tools/hooks/setupgithooks.sh b/src/tools/hooks/setupgithooks.sh new file mode 100755 index 00000000..ae38b253 --- /dev/null +++ b/src/tools/hooks/setupgithooks.sh @@ -0,0 +1,63 @@ +#!/bin/sh +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/tools/hooks/setupgithooks.sh $ +# +# OpenPOWER sbe Project +# +# Contributors Listed Below - COPYRIGHT 2016 +# +# +# 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 + +# Each developer runs this from the git_repo base dir, where it will copy the +# needed scripts into .git/hooks/ directory and make them executable. + +if [ -d $HOOKSDIR ] +then + + # Get hooks from Gerrit, if needed. + if [ ! -f $HOOKSDIR/commit-msg ] + then + echo "Copying Gerrit hooks..." + scp -p -q $GERRIT_SRV:hooks/commit-msg $HOOKSDIR + fi + + # Copy custom pre/post commit hooks from tools directory. + if [ -f "$TOOLSDIR/pre-commit" -a \ + -f "$TOOLSDIR/post-commit" ] + then + echo "Copying pre/post commit hooks..." + + cp $TOOLSDIR/pre-commit $HOOKSDIR/ + cp $TOOLSDIR/pre-commit $HOOKSDIR/pre-applypatch + cp $TOOLSDIR/post-commit $HOOKSDIR/ + + chmod u+x $HOOKSDIR/pre-commit + chmod u+x $HOOKSDIR/pre-applypatch + chmod u+x $HOOKSDIR/post-commit + + else + echo "Cannot find or access pre or post commit scripts" + exit 1 + fi + +else + echo "Cannot find or access .git/hooks directory" + exit 1 +fi + +exit 0 diff --git a/src/tools/hooks/verify-commit b/src/tools/hooks/verify-commit new file mode 100755 index 00000000..68beebf5 --- /dev/null +++ b/src/tools/hooks/verify-commit @@ -0,0 +1,358 @@ +#!/usr/bin/perl +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/tools/hooks/verify-commit $ +# +# OpenPOWER sbe Project +# +# Contributors Listed Below - COPYRIGHT 2016 +# +# +# 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 + +use strict; + +my $issueFound = 0; +my $errorFound = 0; + +my $projectName = $ENV{'PROJECT_NAME'}; +# Relative path of import tree from project root +my $importPrefix = $ENV{'IMPORT_REL_PATH'}."/"; + +verifyPatchSet(); # Verify the patch contents. +verifyCommitMsg(); # Verify the commit message. + +# Finish out the divider. +if ($issueFound) +{ + print "------------------------------------------------------------\n"; +} + +# Return a bad RC if we found an error. Let warnings pass. +exit ($errorFound ? -1 : 0); + + +########################### Subroutines ################################ + +# @sub verifyPatchSet +# +# Extract the contents (lines changed) from the patch set and verify. +# +sub verifyPatchSet +{ + # git-diff options: + # * Diff against the previous commit (HEAD~1) + # * Filter only added and modified files (AM). + # * Show only the lines changed, with no context (U0). + # Grep only the lines marked with "+" (instead of "-") to find just the + # actions done by this patchset and not the content removed. + open PATCH_CONTENTS, "git diff HEAD~1 --diff-filter=AM -U0 | ". + "grep -e \"^+\" -e \"^@@.*+[0-9]\\+\" |"; + + my %fileContents = (); + + my $lastFile = ""; + my $fileLines = (); + my $lineCount = 0; + while (my $line = ) + { + chomp $line; + + # Line starting with "+++ b/path/to/file" indicate a new file. + if ($line =~ m/^\+\+\+ b\/(.*)/) + { + # Save previous file into the map. + if ($lastFile ne "") + { + $fileContents{$lastFile} = $fileLines; + $fileLines = (); + $lineCount = 0; + } + $lastFile = $1; + } + # Lines starting with "@@" indicates a seek in the file, so update + # line numbers. + elsif ($line =~ m/^@@.*\+([0-9]+)/) + { + $lineCount = $1 - 1; + } + else + { + $line =~ s/^\+//; # filter off the leading + symbol. + $lineCount++; + push @{$fileLines}, [$line, $lineCount]; + } + } + if ($lastFile ne "") # Save last file into the map. + { + $fileContents{$lastFile} = $fileLines; + $fileLines = (); + } + + # Verify each line of each file. + foreach my $file (sort keys %fileContents) + { + foreach my $line (@{$fileContents{$file}}) + { + verifyFileLine($file, @{$line}[0], @{$line}[1]); + } + } +} + +# @sub verifyFileLine +# +# Checks a particular line of the file for the following issues: +# * Warning: Lines longer than 80 characters, except in trace statement. +# * Warning: Trailing whitespace. +# * Warning: Tab characters outside of makefiles. +# * Warning: TODO or FIXME type tag without a corresponding RTC number. +# * Warning: NOMERGE tag found. +# +sub verifyFileLine +{ + my ($file,$line,$count) = @_; + + # Check if file was mirrored + my $mirror = 0; + if ($file =~ m/^$importPrefix/) + { + $mirror = 1; + } + + # Check line length. + if (length($line) > 80) + { + # Allow trace statements to slide. + if (($line =~ m/TRAC[DSFU]/) || + ($line =~m/TS_FAIL/) || + ($line =~m/printk/) || + ($line =~m/displayf/) || + ($line =~ m/FAPI_(INF|IMP|ERR|DBG|SCAN)/)) + { + } + else + { + warning($file,$line,$count, + (sprintf "Length is more than 80 characters (%d).", + length($line)) + ); + } + } + + # Check trailing whitespace. + if ($line =~ m/\s$/) + { + warning($file,$line,$count, + "Trailing whitespace found."); + } + + # Check tabs. + if ($line =~ m/\t/) + { + # Makefiles are ok (require tabs). + if (not (($file =~ m/makefile/) || ($file =~ m/\.mk/))) + { + warning($file,$line,$count, + "Tab character found."); + } + } + + # Check "TODO" or "FIXME" type comments. + if (($line =~ m/TODO/i) || ($line =~ m/FIXME/i)) + { + if ( (not ($line =~ m/RTC[\s:]\s*[0-9]+/)) && + (not ($line =~ m/CQ[\s:]\s*[A-Z][A-Z][0-9]+/))) + { + warning($file,$line,$count, + "TODO/FIXME tag without corresponding RTC or CQ number."); + } + } + + # Check "NOMERGE" type comment. + if ($line =~ m/NOMERGE/i) + { + warning($file,$line,$count, + "NOMERGE tag found."); + } + + # Check for "Confidential", unless it's a mirrored commit + if ($line =~ m/Confidential/i && $projectName =~ m/HostBoot/i && !$mirror) + { + unless (($file =~ m/verify-commit/) || + ($file =~ m/addCopyright/)) + { + error($file,$line,$count, + "File contains 'Confidential'."); + } + } +} + +# @sub verifyCommitMsg +# +# Looks at the commit message to verify the following items: +# * Topic is exactly 1 line long. +# * Lines are less than 80 characters. +# * No trailing whitespace. +# * Tags, such as 'RTC:', are only found in the footer. +# * Untagged lines are not found in the footer. +# * RTC tag is formatted correctly. +# * Warning for lacking RTC tag. +# +sub verifyCommitMsg +{ + open COMMIT_CONTENTS, "git log -n1 --pretty=format:%B |"; + my $lineCount = 0; + my $rtcTag = ""; + my $cqTag = ""; + my $taggedLine = ""; + my $untaggedLine = ""; + + while (my $line = ) + { + $lineCount++; + chomp $line; + + # Check line length over 80 characters. + if (length($line) > 80) + { + error("Commit Message",$line,$lineCount, + (sprintf "Length is more than 80 characters (%d).", + length($line)) + ); + } + + # Check trailing whitespace. + if ($line =~ m/[^\s]+\s$/) + { + error("Commit Message",$line,$lineCount, + "Trailing whitespace found."); + } + + # Blank line indicates a new "section". + if ($line =~ m/^$/) + { + # Check for tags outside of the footer. + # (new section implies previous section was not a footer) + if ("" ne $taggedLine) + { + error("Commit Message",$taggedLine,$lineCount, + "Tagged line found outside commit-msg footer."); + } + + $rtcTag = ""; + $cqTag = ""; + $untaggedLine = ""; + $taggedLine = ""; + } + else + { + # Check for multi-line topic. + if ($lineCount == 2) + { + error("Commit Message",$line,$lineCount, + "Topic must be only one line long."); + } + } + + # Verify format of RTC message. + if ($line =~ m/^\s*RTC:\s*[0-9]+(.*)/) + { + if ("" ne $rtcTag) + { + error("Commit Message",$line,$lineCount, + "Duplicate RTC tag found."); + } + + $rtcTag = $line; + if ("" ne $1) + { + error("Commit Message",$line,$lineCount, + (sprintf "RTC tag format incorrect (%s).", $1)); + } + } + + if ($line =~ m/^\s*CQ:\s*[A-Z][A-Z][0-9]+(.*)/) + { + if ("" ne $cqTag) + { + error("Commit Message",$line,$lineCount, + "Duplicate CQ tag found."); + } + + $cqTag = $line; + if ("" ne $1) + { + error("Commit Message",$line,$lineCount, + (sprintf "CQ tag format incorrect (%s).", $1)); + } + } + + # Identify if this is a tagged line or a non-tagged line and store + # away. + if ($line =~ m/^\s*[A-Za-z0-9\-_]+:[^:]/) + { + # We allow lines that look like tags in the topic like... + # "FOO: Adding support for BAR." + if ($lineCount > 1) + { + $taggedLine = $line; + } + } + else + { + $untaggedLine = $line; + } + } + + # Warn for missing RTC tag. + if (("" eq $rtcTag) && ("" eq $cqTag)) + { + warning("Commit Message","",$lineCount, + "Neither RTC nor CQ tag found."); + } + + # Error for a mix of tag / untagged in the last section (ie. untagged + # lines in the footer). + if (("" ne $untaggedLine) && ("" ne $taggedLine)) + { + error("Commit Message",$untaggedLine,$lineCount, + "Untagged line found in footer."); + } +} + +sub warning +{ + my ($file, $line, $count, $statement) = @_; + print "------------------------------------------------------------\n"; + print "WARNING: $statement\n"; + print " $file:$count\n"; + print " $line\n"; + + $issueFound = 1; +} + +sub error +{ + my ($file, $line, $count, $statement) = @_; + print "------------------------------------------------------------\n"; + print "ERROR: $statement\n"; + print " $file:$count\n"; + print " $line\n"; + + $issueFound = 1; + $errorFound = 1; +} + diff --git a/src/tools/image/Makefile b/src/tools/image/Makefile new file mode 100644 index 00000000..fab89e66 --- /dev/null +++ b/src/tools/image/Makefile @@ -0,0 +1,86 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/tools/image/Makefile $ +# +# OpenPOWER sbe Project +# +# Contributors Listed Below - COPYRIGHT 2015,2016 +# +# +# 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 +############################################################################ + +# Makefile for image tools +# works on X86 Linux hosts. + +# Make targets: + +# all : utilities +# +# utilities : Build utility programs and procedures +# +# clean : Removes generated files +# + +############################################################################ +include img_defs.mk + +# Under Linux the scheme is to use a common compiler to create procedures. +# However, the common compiler can be VERY slow, so if the system compiler is +# also 4.1.2 we're using that one instead. Also, the Linux FAPI libraries we +# link with are 32-bit only so we need to force 32-bit mode. + +ifeq ($(wildcard /etc/ldap.conf), ) + GSACELL = ausgsa +else + GSACELL = $(shell cat /etc/ldap.conf | grep "host " | \ + cut -d" " -f2 | cut -d. -f1) +endif + +GCC-RELEASE = 4.8.2 +GCC-VERSION = $(shell gcc -v 2>&1 | grep "$(GCC-RELEASE)") + +ifeq ($(GCC-VERSION),) +$(error wrong compiler version. Use $(GCC-RELEASE) compiler. Try: "scl enable devtoolset-2 bash") +else +CXX = g++ +endif + +UTILITIES-SOURCES = sbe_default_tool.c +UTILITIES = sbe_default_tool + +# Utility targets +UTILITIES-OBJc = $(patsubst %.c,$(BASE_OBJDIR)/%.o,$(UTILITIES-SOURCES)) +UTILITIES-OBJECTS += $(patsubst %.C,$(BASE_OBJDIR)/%.o,$(UTILITIES-OBJc)) +UTILITIES-DEPENDENCIES = $(patsubst %.o,%.d,$(UTILITIES-OBJECTS)) +UTILITIES-EXECUTABLES = $(patsubst %,$(BASE_OBJDIR)/%,$(UTILITIES)) + +.PHONY : all utilities clean + +all: utilities + +utilities: $(UTILITIES-EXECUTABLES) + +CXXFLAGS+=-DFAPI2_NO_FFDC + +$(BASE_OBJDIR)/%.o: %.c + $(CXX) -std=c++11 $(INCLUDES) $(CXXFLAGS) -c -o $@ $< + +$(BASE_OBJDIR)/sbe_default_tool: $(P9_XIP_BINDIR)/p9_xip_image.o $(BASE_OBJDIR)/sbe_default_tool.o + $(CXX) $(CXXFLAGS) ${INCLUDES} -o $@ $^ + +clean: + rm -f $(BASE_OBJDIR)/sbe_default_tool* diff --git a/src/tools/image/sbe_default_tool.c b/src/tools/image/sbe_default_tool.c new file mode 100644 index 00000000..ae2bbf53 --- /dev/null +++ b/src/tools/image/sbe_default_tool.c @@ -0,0 +1,310 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/tools/image/sbe_default_tool.c $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ +/* */ +/* */ +/* 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 sbe_default_tool.c +/// \brief P9-XIP image setter tool for attributes in fixed section +/// +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + + +#define __PPE__ +#include "fapi2.H" +#include "proc_sbe_fixed.H" +#include "p9_xip_image.h" + +const char* g_usage = +"Usage: sbe_default_tool \n" +"The 'image' is the binary image with fixed section.\n" +"\n" +"The 'attribute' is the attribute to be set.\n" +"\n" +"The 'value' is the value of the attribute to be set.\n" +"\n" +"The 'target type' is the type of the target. The following targets are defined:\n" +"TARGET_TYPE_SYSTEM: system target\n" +"TARGET_TYPE_PROC_CHIP: chip target\n" +"TARGET_TYPE_PERV: pervasive target\n" +"TARGET_TYPE_CORE: core target\n" +"TARGET_TYPE_EQ: eq target\n" +"TARGET_TYPE_EX: ex target\n" +"\n" +"The 'index' is the index of the value. Checking is performed.\n" +"example:\n" +"./sbe_default_tool ./sbe_main.bin ATTR_PLL_RING 0x33CAFE34 TARGET_TYPE_PERV 0\n" +"./sbe_default_tool ./sbe_main.bin ATTR_SCRATCH_UINT8_1 12 TARGET_TYPE_PROC_CHIP 0\n" + ; + + +void assertTarget(const char* str, unsigned int index) +{ + + if(strcmp(str, "TARGET_TYPE_SYSTEM") == 0 || (strcmp(str, "TARGET_TYPE_PROC_CHIP") == 0)) { + if (index > 0) { + fprintf(stderr, "sbe_default_tool: index (%d) is larger than 0\n", index); + exit(1); + } + } else if(strcmp(str, "TARGET_TYPE_EX") == 0) { + if (index > EX_TARGET_COUNT) { + fprintf(stderr, "sbe_default_tool: index (%d) is larger than EX_TARGET_COUNT (%d)\n", + index, EX_TARGET_COUNT); + exit(1); + } + } else if(strcmp(str, "TARGET_TYPE_EQ") == 0) { + if (index > EQ_TARGET_COUNT) { + fprintf(stderr, "sbe_default_tool: index (%d) is larger than EQ_TARGET_COUNT (%d)\n", + index, EQ_TARGET_COUNT); + exit(1); + } + } else if(strcmp(str, "TARGET_TYPE_CORE") == 0) { + if (index > CORE_TARGET_COUNT) { + fprintf(stderr, "sbe_default_tool: index (%d) is larger than CORE_TARGET_COUNT (%d)\n", + index, CORE_TARGET_COUNT); + exit(1); + } + } else if(strcmp(str, "TARGET_TYPE_PERV") == 0) { + if (index > PERV_TARGET_COUNT) { + fprintf(stderr, "sbe_default_tool: index (%d) is larger than PERV_TARGET_COUNT (%d)\n", + index, PERV_TARGET_COUNT); + exit(1); + } + } else { + if (index >= PERV_TARGET_COUNT) { + fprintf(stderr, "sbe_default_tool: target not supported:"); + fprintf(stderr, " %s\n", str); + exit(1); + } + } + return; +} + +void setAttribute(void* image, const char* attribute, unsigned int index, uint64_t val) { + + + P9XipItem item; + void *thePointer; + int rc; + + rc = p9_xip_find(image, attribute, &item); + if (rc) { + fprintf(stderr, "sbe_default_tool: attribute not existing:"); + fprintf(stderr, " %s", attribute); + exit(1); + } + + // debug purpose + //printf("offset in string section: 0x%x \n", be32toh(item.iv_toc->iv_id)); + //printf("address: 0x%x index: %2d 0x%x\n", item.iv_address, index, index); + + p9_xip_image2host(image, item.iv_address, &thePointer); + + // debug purpose + //printf("pointer1: 0x%x val: 0x%llx \n", thePointer, val); + + if(item.iv_toc->iv_type == P9_XIP_UINT8) { + + *((uint8_t*)thePointer + index) = (uint8_t)val; + + } else if(item.iv_toc->iv_type == P9_XIP_INT8) { + + *((int8_t*)thePointer + index) = (int8_t)val; + + } else if(item.iv_toc->iv_type == P9_XIP_UINT16) { + + *((uint16_t*)thePointer + index) = htobe16((uint16_t)val); + + } else if(item.iv_toc->iv_type == P9_XIP_INT16) { + + *((int16_t*)thePointer + index) = htobe16((int16_t)val); + + } else if(item.iv_toc->iv_type == P9_XIP_UINT32) { + + *((uint32_t*)thePointer + index) = htobe32((uint32_t)val); + + } else if(item.iv_toc->iv_type == P9_XIP_INT32) { + + *((int32_t*)thePointer + index) = htobe32((int32_t)val); + + } else if(item.iv_toc->iv_type == P9_XIP_UINT64) { + + *((uint64_t*)thePointer + index) = htobe64((uint64_t)val); + + } else if(item.iv_toc->iv_type == P9_XIP_INT64) { + + *((int64_t*)thePointer + index) = htobe64((int64_t)val); + + } else { + fprintf(stderr, "sbe_default_tool: type not available"); + exit(1); + } + + + + + P9_XIP_SECTION_NAMES(section_name); + P9_XIP_TYPE_STRINGS(type_name); + + // debug purpose + //printf("pointer2: 0x%x \n", thePointer + index); + //printf("elements: %d \n", item.iv_elements); + //printf("section id: %s \n", section_name[item.iv_toc->iv_section]); + //printf("location in section: 0x%x \n", be32toh(item.iv_toc->iv_data)); + //printf("type name: %s \n", type_name[item.iv_toc->iv_type]); + + return; +} + + +uint64_t getAttribute(void* image, const char* attribute, unsigned int index) { + + uint64_t val = 0; + + P9XipItem item; + void *thePointer; + int rc; + + rc = p9_xip_find(image, attribute, &item); + if (rc) { + fprintf(stderr, "sbe_default_tool: attribute not existing:"); + fprintf(stderr, " %s", attribute); + exit(1); + } + + p9_xip_image2host(image, item.iv_address, &thePointer); + + if(item.iv_toc->iv_type == P9_XIP_UINT8) { + + val = *((uint8_t*)thePointer + index); + + } else if(item.iv_toc->iv_type == P9_XIP_INT8) { + + val = *((int8_t*)thePointer + index); + val &= 0xFF; + + } else if(item.iv_toc->iv_type == P9_XIP_UINT16) { + + val = htobe16(*((uint16_t*)thePointer + index)); + + } else if(item.iv_toc->iv_type == P9_XIP_INT16) { + + val = htobe16(*((int16_t*)thePointer + index)); + val &= 0xFFFF; + + } else if(item.iv_toc->iv_type == P9_XIP_UINT32) { + + val = htobe32(*((uint32_t*)thePointer + (index))); + + } else if(item.iv_toc->iv_type == P9_XIP_INT32) { + + val = htobe32(*((int32_t*)thePointer + index)); + val &= 0xFFFFFFFF; + + } else if(item.iv_toc->iv_type == P9_XIP_UINT64) { + + val = htobe64(*((uint64_t*)thePointer + index)); + + } else if(item.iv_toc->iv_type == P9_XIP_INT64) { + + val = htobe64(*((int64_t*)thePointer + index)); + + } else { + fprintf(stderr, "sbe_default_tool: type not available"); + exit(1); + } + + + + return val; +} + +int main(int argc, const char** argv) +{ + + int fileFd, rc; + void* image; + struct stat buf; + + if(argc != 6) { + fprintf(stderr, "sbe_default_tool: argument missing\n"); + fprintf(stderr, g_usage); + exit(1); + } + + printf("sbe_default_tool %s %s %s %s %s\n", argv[1], argv[2], argv[3], argv[4], argv[5]); + + fileFd = open(argv[1], O_RDWR); + if (fileFd < 0) { + fprintf(stderr, "sbe_default_tool: open() of the file to be appended failed"); + exit(1); + } + + rc = fstat(fileFd, &buf); + if (rc) { + fprintf(stderr, "sbe_default_tool: fstat() of the file to be appended failed"); + exit(1); + } + + image = mmap(0, buf.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fileFd, 0); + if (image == MAP_FAILED) { + fprintf(stderr, "sbe_default_tool: mmap() of the file to be appended failed"); + exit(1); + } + + + uint64_t val=strtoull(argv[3], 0, 0); + + unsigned int index = strtoul(argv[5], 0, 10); + + assertTarget(argv[4], index); + + setAttribute(image, argv[2], index, val); + + uint64_t check = getAttribute(image, argv[2], index); + + if((check & val) != check) { + + fprintf(stderr, "sbe_default_tool: set and get values not equal -> "); + fprintf(stderr, "%lx != %lx\n", check, val); + exit(1); + + } + + rc = close(fileFd); + if (rc) { + fprintf(stderr, "sbe_default_tool: close() of modified image failed"); + exit(1); + } + + + return 0; +} diff --git a/src/tools/ppetracepp/Makefile b/src/tools/ppetracepp/Makefile new file mode 100644 index 00000000..eec6da6a --- /dev/null +++ b/src/tools/ppetracepp/Makefile @@ -0,0 +1,37 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/tools/ppetracepp/Makefile $ +# +# OpenPOWER sbe Project +# +# Contributors Listed Below - COPYRIGHT 2015,2016 +# +# +# 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 +include img_defs.mk + +all: ppetracepp ppe2fsp + +ppetracepp: ppetracepp.C + g++ -m32 -O3 -w -g -I./ ppetracepp.C -o $(PPETRACEPP_BIN_DIR)/ppetracepp +# g++ -O3 -w -x c++ -fPIC -g -I./ ppetracepp.C -o ppetracepp + +ppe2fsp: ppe2fsp.c ppe2fsp_cmd.c + gcc -m32 -w -g -I./ -I$(PK_SRCDIR)/trace ppe2fsp.c ppe2fsp_cmd.c -o $(PPETRACEPP_BIN_DIR)/ppe2fsp + +clean: + rm $(PPETRACEPP_BIN_DIR)/ppetracepp $(PPETRACEPP_BIN_DIR)/ppe2fsp + diff --git a/src/tools/ppetracepp/cmvc/makefile b/src/tools/ppetracepp/cmvc/makefile new file mode 100644 index 00000000..cf2ad437 --- /dev/null +++ b/src/tools/ppetracepp/cmvc/makefile @@ -0,0 +1,28 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/tools/ppetracepp/cmvc/makefile $ +# +# OpenPOWER sbe Project +# +# Contributors Listed Below - COPYRIGHT 2016 +# +# +# 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 +PROGRAMS += ppe2fsp +ppe2fsp_OFILES = ppe2fsp.o ppe2fsp_cmd.o + +.include <${RULES_MK}> + diff --git a/src/tools/ppetracepp/jhash.h b/src/tools/ppetracepp/jhash.h new file mode 100755 index 00000000..0dcc3bf3 --- /dev/null +++ b/src/tools/ppetracepp/jhash.h @@ -0,0 +1,166 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/tools/ppetracepp/jhash.h $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016 */ +/* */ +/* */ +/* 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 */ +#ifndef _LINUX_JHASH_H +#define _LINUX_JHASH_H + +/* jhash.h: Jenkins hash support. + * + * Copyright (C) 1996 Bob Jenkins (bob_jenkins@burtleburtle.net) + * + * http://burtleburtle.net/bob/hash/ + * + * These are the credits from Bob's sources: + * + * lookup2.c, by Bob Jenkins, December 1996, Public Domain. + * hash(), hash2(), hash3, and mix() are externally useful functions. + * Routines to test the hash are included if SELF_TEST is defined. + * You can use this free for any purpose. It has no warranty. + * + * Copyright (C) 2003 David S. Miller (davem@redhat.com) + * + * I've modified Bob's hash to be useful in the Linux kernel, and + * any bugs present are surely my fault. -DaveM + */ + +/* NOTE: Arguments are modified. */ +#define __jhash_mix(a, b, c) \ +{ \ + a -= b; a -= c; a ^= (c>>13); \ + b -= c; b -= a; b ^= (a<<8); \ + c -= a; c -= b; c ^= (b>>13); \ + a -= b; a -= c; a ^= (c>>12); \ + b -= c; b -= a; b ^= (a<<16); \ + c -= a; c -= b; c ^= (b>>5); \ + a -= b; a -= c; a ^= (c>>3); \ + b -= c; b -= a; b ^= (a<<10); \ + c -= a; c -= b; c ^= (b>>15); \ +} + +/* The golden ration: an arbitrary value */ +#define JHASH_GOLDEN_RATIO 0x9e3779b9 + +/* The most generic version, hashes an arbitrary sequence + * of bytes. No alignment or length assumptions are made about + * the input key. + */ +static inline u32 jhash(const void *key, u32 length, u32 initval) +{ + u32 a, b, c, len; + const u8 *k = (const u8*)key; + + len = length; + a = b = JHASH_GOLDEN_RATIO; + c = initval; + + while (len >= 12) { + a += (k[0] +((u32)k[1]<<8) +((u32)k[2]<<16) +((u32)k[3]<<24)); + b += (k[4] +((u32)k[5]<<8) +((u32)k[6]<<16) +((u32)k[7]<<24)); + c += (k[8] +((u32)k[9]<<8) +((u32)k[10]<<16)+((u32)k[11]<<24)); + + __jhash_mix(a,b,c); + + k += 12; + len -= 12; + } + + c += length; + switch (len) { + case 11: c += ((u32)k[10]<<24); + case 10: c += ((u32)k[9]<<16); + case 9 : c += ((u32)k[8]<<8); + case 8 : b += ((u32)k[7]<<24); + case 7 : b += ((u32)k[6]<<16); + case 6 : b += ((u32)k[5]<<8); + case 5 : b += k[4]; + case 4 : a += ((u32)k[3]<<24); + case 3 : a += ((u32)k[2]<<16); + case 2 : a += ((u32)k[1]<<8); + case 1 : a += k[0]; + }; + + __jhash_mix(a,b,c); + + return c; +} + +/* A special optimized version that handles 1 or more of u32s. + * The length parameter here is the number of u32s in the key. + */ +static inline u32 jhash2(const u32 *k, u32 length, u32 initval) +{ + u32 a, b, c, len; + + a = b = JHASH_GOLDEN_RATIO; + c = initval; + len = length; + + while (len >= 3) { + a += k[0]; + b += k[1]; + c += k[2]; + __jhash_mix(a, b, c); + k += 3; len -= 3; + } + + c += length * 4; + + switch (len) { + case 2 : b += k[1]; + case 1 : a += k[0]; + }; + + __jhash_mix(a,b,c); + + return c; +} + + +/* A special ultra-optimized versions that knows they are hashing exactly + * 3, 2 or 1 word(s). + * + * NOTE: In partilar the "c += length; __jhash_mix(a,b,c);" normally + * done at the end is not done here. + */ +static inline u32 jhash_3words(u32 a, u32 b, u32 c, u32 initval) +{ + a += JHASH_GOLDEN_RATIO; + b += JHASH_GOLDEN_RATIO; + c += initval; + + __jhash_mix(a, b, c); + + return c; +} + +static inline u32 jhash_2words(u32 a, u32 b, u32 initval) +{ + return jhash_3words(a, b, 0, initval); +} + +static inline u32 jhash_1word(u32 a, u32 initval) +{ + return jhash_3words(a, 0, 0, initval); +} + +#endif /* _LINUX_JHASH_H */ diff --git a/src/tools/ppetracepp/ppe2fsp.c b/src/tools/ppetracepp/ppe2fsp.c new file mode 100755 index 00000000..d681b147 --- /dev/null +++ b/src/tools/ppetracepp/ppe2fsp.c @@ -0,0 +1,532 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/tools/ppetracepp/ppe2fsp.c $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ +/* */ +/* */ +/* 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 */ +#include "pk_trace.h" +#include "ppe2fsp.h" +#include "trac_interface.h" +#include +#include +#include + +#define TRACE_BUF_VERSION 0x01 /*!< Trace buffer version */ +#define TRACE_FIELDTRACE 0x4654 /*!< Field Trace - "FT" */ +#define TRACE_FIELDBIN 0x4644 /*!< Binary Field Trace - "FD" */ + +#define TRAC_TIME_REAL 0 // upper 32 = seconds, lower 32 = nanoseconds +#define TRAC_TIME_50MHZ 1 +#define TRAC_TIME_200MHZ 2 +#define TRAC_TIME_167MHZ 3 // 166666667Hz + +typedef struct +{ + trace_entry_stamp_t stamp; + trace_entry_head_t head; + union + { + uint8_t data[PK_TRACE_MAX_BINARY + 1]; //add 1 byte for padding + uint32_t parms[PK_TRACE_MAX_PARMS]; + }; + uint32_t size; +}largest_fsp_entry_t; + +typedef struct +{ + union + { + uint8_t binary_data[PK_TRACE_MAX_BINARY + 1]; + struct + { + uint8_t rsvd[(PK_TRACE_MAX_BINARY + 1) - (PK_TRACE_MAX_PARMS * sizeof(uint32_t))]; + uint32_t parms[PK_TRACE_MAX_PARMS]; + }; + }; + PkTraceEntryFooter footer; +}LargestPpeEntry; + +//convert a ppe timestamp to an fsp trace timestamp +uint64_t ppe2fsp_time(uint64_t ppe_time, uint32_t hz) +{ + uint32_t seconds; + uint32_t remainder; + uint32_t nseconds; + + //convert from ppe ticks to seconds and nanoseconds + seconds = ppe_time / hz; + remainder = ppe_time - (((uint64_t)seconds) * hz); + nseconds = (((uint64_t)remainder) * 1000000000) / hz; + return (((uint64_t)seconds) << 32) | nseconds; +} + +//Writes an fsp trace entry to the fsp trace buffer +void fsp_put_entry(trace_buf_head_t* tb, largest_fsp_entry_t* fte, size_t entry_size, uint32_t bytes_left) +{ + char* buffer = ((char*)tb) + sizeof(trace_buf_head_t); + char* tb_start; + char* fte_start; + uint32_t copy_bytes; + + if(entry_size <= bytes_left) + { + tb_start = buffer + bytes_left - entry_size; + fte_start = (char*)fte; + copy_bytes = entry_size; + } + else + { + tb_start = buffer; + fte_start = ((char*)fte) + (entry_size - bytes_left); + copy_bytes = bytes_left; + } + + memcpy(tb_start, fte_start, copy_bytes); +} + + +//convert a ppe trace entry to an fsp trace entry +size_t pte2fte(PkTraceBuffer* ptb, + LargestPpeEntry* pte, + size_t pte_size, + largest_fsp_entry_t* fte, + uint64_t ppe_time64) +{ + size_t entry_size; + PkTraceGeneric* pte_footer = &pte->footer.generic; + uint32_t format; + uint32_t hash32; + uint32_t hash32_partial; + uint32_t* parm_start; + uint32_t parm_bytes; + uint64_t fsp_time64; + + //convert the ppe trace time to an fsp trace time + fsp_time64 = ppe2fsp_time(ppe_time64, ntohl(ptb->hz)); + + //fill in the 64 bit timestamp + fte->stamp.tbh = htonl((uint32_t)(fsp_time64 >> 32)); + fte->stamp.tbl = htonl((uint32_t)(fsp_time64 & 0x00000000ffffffffull)); + + //use the ppe instance id as the thread id. + fte->stamp.tid = htonl((uint32_t)ntohs(ptb->instance_id)); + + //merge the hash prefix and the string_id fields together for a 32 bit hash value + hash32 = ((uint32_t)ntohs(ptb->hash_prefix)) << 16; + hash32 |= pte_footer->string_id; + fte->head.hash = htonl(hash32); + + //generate the 32bit hash value for a partial trace entry in case it's needed + hash32_partial = ((uint32_t)ntohs(ptb->hash_prefix)) << 16; + hash32_partial |= ntohs(ptb->partial_trace_hash); + + //set the line number to 1 + fte->head.line = htonl(1); + + //determine the FSP trace format + format = PK_GET_TRACE_FORMAT(pte_footer->time_format.word32); + if(format == PK_TRACE_FORMAT_BINARY) + { + fte->head.tag = htons(TRACE_FIELDBIN); + } + else + { + fte->head.tag = htons(TRACE_FIELDTRACE); + } + + parm_start = (uint32_t*)(((char*)pte) + (sizeof(LargestPpeEntry) - pte_size)); + + //fill in the parameters/binary data and size at the end + switch(format) + { + + case PK_TRACE_FORMAT_TINY: + //one or 0 parameters + entry_size = sizeof(trace_entry_stamp_t) + + sizeof(trace_entry_head_t) + + sizeof(uint32_t); + fte->parms[0] = htonl((uint32_t)(pte_footer->parm16)); + fte->head.length = htons(sizeof(uint32_t)); + parm_bytes = 0; + break; + + case PK_TRACE_FORMAT_BIG: + //1 - 4 parameters + // + //If the trace entry data is incomplete (not all parm data + //had been written at the time the trace was captured) then + //we will write a trace to the fsp buffer that says + //"PARTIAL TRACE ENTRY. HASH_ID = %d" + if(pte_footer->complete) + { + parm_bytes = pte_footer->bytes_or_parms_count * sizeof(uint32_t); + fte->head.length = htons(parm_bytes + sizeof(uint32_t)); + entry_size = sizeof(trace_entry_stamp_t) + + sizeof(trace_entry_head_t) + + parm_bytes + sizeof(uint32_t); + } + else + { + parm_bytes = 0; + entry_size = sizeof(trace_entry_stamp_t) + + sizeof(trace_entry_head_t) + + sizeof(uint32_t); + fte->parms[0] = fte->head.hash; //already corrected for endianess + fte->head.hash = htonl(hash32_partial); + fte->head.length = htons(sizeof(uint32_t)); + } + break; + + case PK_TRACE_FORMAT_BINARY: + //If the trace entry data is incomplete (not all parm data + //had been written at the time the trace was captured) then + //we will write a trace to the fsp buffer that says + //"PARTIAL TRACE ENTRY. HASH_ID = %d" + if(pte_footer->complete) + { + parm_bytes = pte_footer->bytes_or_parms_count; + fte->head.length = htons((uint16_t)parm_bytes); + entry_size = sizeof(trace_entry_stamp_t) + + sizeof(trace_entry_head_t) + + parm_bytes; + + //pad to 4 byte boundary + entry_size = (entry_size + 3) & ~3; + } + else + { + parm_bytes = 0; + entry_size = sizeof(trace_entry_stamp_t) + + sizeof(trace_entry_head_t) + + sizeof(uint32_t); + fte->parms[0] = fte->head.hash; + fte->head.hash = htonl(hash32_partial); + fte->head.length = htons(sizeof(uint32_t)); + fte->head.tag = htons(TRACE_FIELDTRACE); + } + break; + + + default: + entry_size = 0; + parm_bytes = 0; + break; + } + + //copy parameter bytes to the fsp entry if necessary + if(parm_bytes) + { + memcpy(fte->data, parm_start, parm_bytes); + } + + //add the entry size to the end + if(entry_size) + { + uint32_t new_entry_size = entry_size + sizeof(uint32_t); + *((uint32_t*)(((char*)fte) + entry_size)) = htonl(new_entry_size); + entry_size = new_entry_size; + } + + return entry_size; +} + +//retrieve a ppe trace entry from a ppe trace buffer +size_t ppe_get_entry(PkTraceBuffer* tb, uint32_t offset, LargestPpeEntry* pte) +{ + uint32_t mask = ntohs(tb->size) - 1; + PkTraceEntryFooter* footer; + size_t entry_size; + size_t parm_size; + char* dest = (char*)pte; + uint32_t format; + uint32_t start_index; + uint32_t bytes_left; + uint32_t bytes_to_copy; + + //Find the footer in the circular buffer + footer = (PkTraceEntryFooter*)(&tb->cb[(offset - sizeof(PkTraceEntryFooter)) & mask]); + + //always correct endianess for the time and string id words + pte->footer.generic.time_format.word32 = ntohl(footer->generic.time_format.word32); + pte->footer.generic.string_id = ntohs(footer->generic.string_id); + + //only need to byte swap the parm16 value if this is a tiny format + pte->footer.generic.parm16 = footer->generic.parm16; + + //use footer data to determine the length of the binary data or parameters + format = PK_GET_TRACE_FORMAT(pte->footer.generic.time_format.word32); + switch(format) + { + case PK_TRACE_FORMAT_TINY: + pte->footer.generic.parm16 = ntohs(pte->footer.generic.parm16); + parm_size = 0; + entry_size = sizeof(PkTraceEntryFooter); + break; + + case PK_TRACE_FORMAT_BIG: + parm_size = pte->footer.generic.bytes_or_parms_count * sizeof(uint32_t); + entry_size = sizeof(PkTraceEntryFooter); + break; + + case PK_TRACE_FORMAT_BINARY: + parm_size = pte->footer.generic.bytes_or_parms_count; + entry_size = sizeof(PkTraceEntryFooter); + break; + + default: + entry_size = 0; + parm_size = 0; + break; + } + + //pad to 8 byte boundary + parm_size = (parm_size + 7) & ~0x00000007ul; + + //add the parameter size to the total entry size + entry_size += parm_size; + + //copy the entry from the circular buffer to pte + start_index = (offset - entry_size) & mask; + bytes_left = ntohs(tb->size) - start_index; + + //only copy up to the end of the circular buffer + if(parm_size < bytes_left) + { + bytes_to_copy = parm_size; + } + else + { + bytes_to_copy = bytes_left; + } + + dest += sizeof(LargestPpeEntry) - entry_size; + memcpy(dest, &tb->cb[start_index], bytes_to_copy); + + //now copy the rest of the data starting from the beginning of the + //circular buffer. + if(bytes_to_copy < parm_size) + { + memcpy(dest + bytes_to_copy, tb->cb, parm_size - bytes_to_copy); + } + + //return the size of the entry + return entry_size; +} + +//convert a ppe trace buffer to an fsp trace buffer +int ppe2fsp(void* in, size_t in_size, void* out, size_t* io_size) +{ + PkTraceBuffer* ptb = (PkTraceBuffer*)in; + trace_buf_head_t* ftb = (trace_buf_head_t*)out; + uint32_t ppe_bytes_left; + uint32_t fsp_bytes_left; + int rc = 0; + uint32_t ptb_offset; + uint64_t ppe_time64; + uint32_t fte_size, pte_size; + uint32_t fsp_te_count = 0; + uint32_t time_diff32, prev_time32, new_time32; + PkTraceGeneric* pte_footer; + largest_fsp_entry_t fte; + LargestPpeEntry pte; + uint64_t time_adj64; + + do + { + if(!ptb || !ftb || !io_size) + { + rc = P2F_NULL_POINTER; + break; + } + + if(ntohs(ptb->version) != PK_TRACE_VERSION) + { + rc = P2F_INVALID_VERSION; + break; + } + + //check that the input buffer is large enough to have a ppe trace buffer + if(in_size < (((uintptr_t)(&ptb->cb[0])) - (uintptr_t)(ptb))) + { + rc = P2F_INPUT_BUFFER_TOO_SMALL; + break; + } + + //initialize some locals + fsp_bytes_left = *io_size - sizeof(trace_buf_head_t); + ppe_bytes_left = ntohs(ptb->size); + ptb_offset = ntohl(ptb->state.offset); + if(htonl(1) == 1) + { + time_adj64 = ptb->time_adj64; + } + else + { + time_adj64 = ntohl((uint32_t)(ptb->time_adj64 >> 32)); + time_adj64 |= ((uint64_t)(ntohl((uint32_t)(ptb->time_adj64 & 0x00000000ffffffff)))) << 32; + } + + //make sure the ppe buffer size is a power of two + if((ppe_bytes_left - 1) & ppe_bytes_left) + { + //size is not a power of two + rc = P2F_INVALID_INPUT_SIZE; + break; + } + + //The ppe bytes field should always be a multiple of 8 + if(ptb_offset & 0x7) + { + rc = P2F_INVALID_PPE_OFFSET; + break; + } + + //make sure there is enough room for the fsp header + if(*io_size < sizeof(trace_buf_head_t)) + { + rc = P2F_OUTPUT_BUFFER_TOO_SMALL; + break; + } + + + //initialize the fsp header + ftb->ver = TRACE_BUF_VERSION; + ftb->hdr_len = sizeof(trace_buf_head_t); + ftb->time_flg = TRAC_TIME_REAL; + ftb->endian_flg = 'B'; //big endian + memcpy(ftb->comp, ptb->image_str, sizeof(ftb->comp)); + ftb->times_wrap = htonl(1); + ftb->size = htonl(sizeof(trace_buf_head_t) + sizeof(uint32_t)); + ftb->next_free = htonl(sizeof(trace_buf_head_t)); + ftb->extracted = htonl(0); + ftb->te_count = htonl(0); + + //find the latest timestamp so that we can work back from there + ppe_time64 = ((uint64_t)(ntohl(ptb->state.tbu32) & 0xefffffff)) << 32; + pte_size = ppe_get_entry(ptb, ptb_offset, &pte); + prev_time32 = PK_GET_TRACE_TIME(pte.footer.generic.time_format.word32); + ppe_time64 |= prev_time32; + + //process all of the input bytes one trace entry at a time + //from newest to oldest (backwards) until we run out of input bytes or + //we run out of output space. + while(1) + { + //check if we have enough data for a ppe footer + if(ppe_bytes_left < sizeof(PkTraceEntryFooter)) + { + break; + } + + //get the next ppe entry + pte_size = ppe_get_entry(ptb, ptb_offset, &pte); + + //Stop if there are no more entries to retrieve from the ppe trace buffer + if(!pte_size) + { + break; + } + pte_footer = &pte.footer.generic; + + //mark the entry as incomplete if we didn't have enough data + //for the entire entry + if(pte_size > ppe_bytes_left) + { + pte_footer->complete = 0; + ppe_bytes_left = 0; + } + else + { + ppe_bytes_left -= pte_size; + ptb_offset -= pte_size; + } + + //Calculate the 64 bit timestamp for this entry.... + //On PPE, getting the timestamp is not done atomically with writing + //the entry to the buffer. This means that an entry with an older + //timestamp could possibly be added to the buffer after an entry + //with a newer timestamp. Detect this condition by checking if the + //time difference is bigger than the max difference. The max + //difference is enforced by the PPE having a trace added on a + //shorter time boundary (using a timer). + new_time32 = PK_GET_TRACE_TIME(pte_footer->time_format.word32); + time_diff32 = prev_time32 - new_time32; + + if(time_diff32 > ntohl(ptb->max_time_change)) + { + time_diff32 = new_time32 - prev_time32; + ppe_time64 += time_diff32; + } + else + { + ppe_time64 -= time_diff32; + } + + //save off the lower 32bit timestamp for the next iteration + prev_time32 = new_time32; + + //convert the ppe trace entry to an fsp trace entry + fte_size = pte2fte(ptb, &pte, pte_size, &fte, ppe_time64 + time_adj64); + + //fit as much of the entry into the fsp trace buffer as possible + fsp_put_entry(ftb, &fte, fte_size, fsp_bytes_left); + + //update the fsp trace entry count + fsp_te_count++; + + //stop if there is no more room left in the fsp trace buffer + if(fte_size >= fsp_bytes_left) + { + fsp_bytes_left = 0; + ftb->times_wrap = htonl(1); + break; + } + else + { + fsp_bytes_left -= fte_size; + } + }//while(1) + + + //shift the trace data up if there is space to do so + if(fsp_bytes_left) + { + char* dest = ((char*)ftb) + sizeof(trace_buf_head_t); + char* src = dest + fsp_bytes_left; + size_t data_size = *io_size - sizeof(trace_buf_head_t) - fsp_bytes_left; + memmove(dest, src, data_size); + } + + //update the fsp header to reflect the true size and entry count + ftb->te_count = htonl(fsp_te_count); + + //inform the caller of how many bytes were actually used + *io_size -= fsp_bytes_left; + + //shrink the size field to what we actually ended up using + ftb->size = htonl(*io_size); + + }while(0); + + return rc; +} + + + diff --git a/src/tools/ppetracepp/ppe2fsp.h b/src/tools/ppetracepp/ppe2fsp.h new file mode 100644 index 00000000..2abb146c --- /dev/null +++ b/src/tools/ppetracepp/ppe2fsp.h @@ -0,0 +1,33 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/tools/ppetracepp/ppe2fsp.h $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ +/* */ +/* */ +/* 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 */ +#include + +#define P2F_NULL_POINTER 1 +#define P2F_INVALID_INPUT_SIZE 2 +#define P2F_INVALID_PPE_OFFSET 3 +#define P2F_OUTPUT_BUFFER_TOO_SMALL 4 +#define P2F_INPUT_BUFFER_TOO_SMALL 5 +#define P2F_INVALID_VERSION 6 + +int ppe2fsp(void* in, size_t in_size, void* out, size_t* io_size); diff --git a/src/tools/ppetracepp/ppe2fsp_cmd.c b/src/tools/ppetracepp/ppe2fsp_cmd.c new file mode 100644 index 00000000..c36d735c --- /dev/null +++ b/src/tools/ppetracepp/ppe2fsp_cmd.c @@ -0,0 +1,138 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/tools/ppetracepp/ppe2fsp_cmd.c $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016 */ +/* */ +/* */ +/* 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 */ +#include +#include "ppe2fsp.h" +#include "pk_trace.h" + +#define MAX_INPUT_SIZE 0x2040 //8k +#define MAX_OUTPUT_SIZE (4 * MAX_INPUT_SIZE) + +char* inbuf[MAX_INPUT_SIZE]; +char* outbuf[MAX_OUTPUT_SIZE]; +; +int main(int argc, char** argv) +{ + FILE* in; + FILE* out; + size_t input_size; + size_t output_size; + size_t bytes_written; + int rc = -1; + + do + { + if(argc > 3) + { + fprintf(stderr, "Usage: %s [input file] [output file]\n", argv[0]); + } + + if(argc < 3) + { + out = stdout; + } + else + { + //open the output file for writing + out = fopen(argv[2], "w"); + if(!out) + { + perror("failed to open file for writing"); + break; + } + } + + if(argc < 2) + { + in = stdin; + } + else + { + //open the input file for reading + in = fopen(argv[1], "r"); + if(!in) + { + perror("failed to open file for reading"); + break; + } + } + + //read the input stream until we reach EOF or the max size + input_size = fread(inbuf, 1, MAX_INPUT_SIZE, in); + if(!feof(in)) + { + if(ferror(in)) + { + perror("failed to read input file"); + break; + } + else + { + fprintf(stderr, "Input stream exceeds max size of %d bytes. Exiting.\n", MAX_INPUT_SIZE); + break; + } + } + + output_size = MAX_OUTPUT_SIZE; + + //Actual size of output buffer will be set upon successful completion + rc = ppe2fsp(inbuf, input_size, outbuf, &output_size); + if(rc) + { + fprintf(stderr, "Failed converting ppe trace to fsp trace. rc = %d\n", rc); + if(rc == P2F_INVALID_VERSION) + { + fprintf(stderr, "PPE trace buffer must be version %d.\n", PK_TRACE_VERSION); + } + break; + } + + rc = -1; + //operation was successful. Write out the fsp trace data + bytes_written = fwrite(outbuf, 1, output_size, out); + if(bytes_written != output_size) + { + if(ferror(out)) + { + perror("Failed to write output stream"); + break; + } + fprintf(stderr, "Failure: Only able to write %d of %d bytes to output stream\n", bytes_written, output_size); + break; + } + + fclose(in); + fclose(out); + fclose(stderr); + + rc = 0; + }while(0); + + return rc; +} + + + + + + diff --git a/src/tools/ppetracepp/ppetracepp.C b/src/tools/ppetracepp/ppetracepp.C new file mode 100755 index 00000000..2829e4dd --- /dev/null +++ b/src/tools/ppetracepp/ppetracepp.C @@ -0,0 +1,949 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/tools/ppetracepp/ppetracepp.C $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ +/* */ +/* */ +/* 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 */ + +/* +# *** ppetracepp - a fsp/common Linux trace pre processor +# this one replaces the trace strings by the corresponding hash value +# (i.e. the complete call to trace_ppe_hash is replaced) + +# *** Usage +# +# prepend compiler call with the call of this pre processor, i.e if you have +# $(CC) $(CFLAGS) -o $@ $< +# in your Makefile change it to this: +# ppetracepp $(CC) $(CFLAGS) -o $@ $< +# ppetracepp will use "$(CC) -E" to call the C pre processor "cpp". +# you can set a env var "REALCPP" to the name of a program to select +# a different programm as cpp +# +# ppetracepp creates a file "$target.ppe.hash" with the trace strings and the hash values. +# +# to enable debug mode set envvar PPETRACEPPDEBUG to 1 or give '-d' as first arg + +# *** Change History +# +# 2003-02-26 RBa created from scratch +# 2003-02-28 RBa add C++ support (C++ interface uses own type for the hash) +# 2003-05-28 RBa if cc should link instead of compile just call compiler +# 2003-07-11 AGe Change search alg. slightly and put just format back +# 2003-07-25 RBa just call gcc if called to link instead to compile +# eat argument for option -x +# 2003-11-26 RBa fix c/c++ algo: compile as c++ if realcc=*g++ +# 2004-02-02 RBa remove explicit test whether source file is readable +# it is obsolete and might lead to an error if afs is used +# 2004-02-13 RBa add support for dependency generation (-MD/-MG, -MF) +# don't prepend './' to object filename +# 2006-04-19 RBa rewrite trace_ppe_write_all support, handle C and C++ the same +# 2006-05-24 RBa fix handling of missing -o ; add TRAC_PPVER for macro/API version +# 2006-09-15 RBa add handling of \" in trace format strings ; reduce non-error output +# put object file in current dir if no -o given +# 2007-03-22 RBa handle more gcc options (-i) ; protect " in call to shell +# store output of cpp as "unmodified" output for debug +# only write string/hash file if strings found +# 2012-09-24 hlava Rewritten as C program for better build performance (was perl) +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +typedef u_int32_t u32 ; +typedef u_int8_t u8 ; +#include + +using namespace std; + +static string version = "2.0"; +static string macro_version = "1"; + +static bool debug = false; +#define dprintf(format, ...) if (debug) { printf(format, ##__VA_ARGS__); fflush(stdout); } +static map hashtab; +static string hashtype; +static string hashtype_suffix; + +static string tmp; +static string cmd; +static FILE* CPP = NULL; // pipe from preprocessor +static FILE* CC = NULL; // pipe to compiler +static FILE* DEBUG = NULL; +static FILE* DEBUGIN = NULL; + +//***************************************************************************** +// replace_substr +//***************************************************************************** +void replace_substr(std::string& str, const std::string& oldStr, const std::string& newStr) +{ + size_t pos = 0; + while((pos = str.find(oldStr, pos)) != std::string::npos) + { + str.replace(pos, oldStr.length(), newStr); + pos += newStr.length(); + } + +} + +//***************************************************************************** +// fileparse +//***************************************************************************** +void fileparse(const string& in_str, string& name, string& dir, string& suff) +{ + string str(in_str); + size_t pos; + name = ""; + dir = ""; + suff = ""; + pos = str.find_last_of('.'); + if (pos != string::npos) + { + suff = str.substr(pos); + str = str.substr(0, pos); + } + pos = str.find_last_of('/'); + if (pos != string::npos) + { + name = str.substr(pos+1); + str = str.substr(0, pos+1); + } + dir = str; +} + +static const size_t TRACE_PPE_HASH_LEN = 13; +//***************************************************************************** +// chop_up_line +//***************************************************************************** +bool chop_up_line(string& in_line, string& prefix, string& strings, string& salt, string& suffix) +{ + // First see if this line matches the pattern we're looking for + // Since this will return false 95%+ of the time this function it called, we do it + // before doing any other init for performance reasons. + size_t pos = in_line.find("trace_ppe_hash"); + if (pos == string::npos) { return(false); } + + // trace_ppe_hash ( "..." ".." "..." , 2 ) + // regex: PREFIX 'trace_ppe_hash' space '(' space STRINGS space ',' space NUMBER space ')' SUFFIX + // STRINGS: '"' .* '"' space? + + + // Original perl magic incantation: + // while($line =~ m/^(.*?)trace_ppe_hash\s*\(\s*((".*?(? $1 = everything up to the word "trace_ppe_hash" + // trace_ppe_hash = delimiter + // \s*\(\s* = delimiter = <0-n whitespace chars>, left paren, <0-n whitespace chars> + // ((".*?(? $2 = double-quote, some chars up to last closing double-quote ($3 used for nested regex) + // ,\s* = delimiter = comma followed by some whitespace + // (-?\d+)\s*\)(.*) => $4 and $5 + // $/) = end of the line input string + string line(in_line); + prefix = ""; + strings = ""; + salt = ""; + suffix = ""; + size_t pos1; + size_t pos2; + size_t pos3; + + pos1 = pos + 14; // pos1 = after "trace_ppe_hash" + pos2 = line.find("(", pos1); + if (pos2 == string::npos) { return(false); } + ++pos2; + pos3 = line.find("\"", pos2); + if (pos3 == string::npos) { return(false); } + dprintf("--------\nchop_up_line: Passed basic checks. line= %s\n", line.c_str()); + dprintf("pos1=%d, pos2=%d, pos3=%d\n", pos1, pos2, pos3); + if ((pos1 != (pos2-1)) && (line.find_first_not_of(" \t", pos1, (pos2-pos1)+1) != string::npos)) { return(false); } //non-whitespace? + if ((pos2 != pos3) && (line.find_first_not_of(" \t", pos2, (pos3-pos2)) != string::npos)) { return(false); } //non-whitespace? + + // Get the prefix data + dprintf(">chop_up_line(\"%s\",...)\n", line.c_str()); + prefix = line.substr(0, pos); + line = line.substr(pos + TRACE_PPE_HASH_LEN); + dprintf(" prefix=\"%s\"\n", prefix.c_str()); + + // Get the strings and join/fix them: Store all strings between paired double-quotes up to the + // first comma not inside a string + pos = line.find_first_of('('); + if (pos == string::npos) { return(false); } + line = line.substr(pos + 1); + strings = ""; + while(!line.empty()) + { + pos = line.find_first_of(','); + pos1 = line.find_first_of('"'); + if ((pos1 == string::npos) || ((pos != string::npos) && (pos < pos1))) { break; } // found comma before next quote + pos2 = line.find_first_of('"', (pos1+1)); + if (pos2 == string::npos) { return(false); } // unbalanced quotes! + while(line[pos2-1] == '\\') // skip escaped quotes in the string (they're not the ending quote) + { + pos2 = line.find_first_of('"', (pos2+1)); + if (pos2 == string::npos) { return(false); } // unbalanced quotes! + } + if (!strings.empty()) { strings += " "; } + strings += line.substr(pos1, (pos2-pos1)+1); + line = line.substr(pos2+1); + } + replace_substr(strings, "\" \"", ""); + replace_substr(strings, "\\\"", "ESCAPEDQUOTE"); + replace_substr(strings, "\"", ""); + replace_substr(strings, "ESCAPEDQUOTE", "\""); + // Remove trailing whitespace ah20130717 + pos = strings.find_last_not_of(" \t\n"); + if ((pos != string::npos) && (pos < (strings.length()-1))) + { + strings = strings.substr(0, pos+1); + } + + dprintf(" strings>%s<\n", strings.c_str()); + + // Get the salt + pos = line.find(","); + if (pos != string::npos) { line = line.substr(pos+1); } + pos = line.find_first_of(')'); + if (pos == string::npos) { return(false); } + salt = line.substr(0, pos); + line = line.substr(pos+1); + //dprintf(" salt=\"%s\"\n", salt.c_str()); + pos = salt.find_first_not_of(" \t\n"); + if (pos == string::npos) { return(false); } + salt = salt.substr(pos); + pos = salt.find_last_not_of(" \t\n"); + if (pos == string::npos) { return(false); } + salt = salt.substr(0, pos+1); + dprintf(" salt=\"%s\"\n", salt.c_str()); + + // Get the suffix (i.e. the rest) + suffix = line; + if (suffix[suffix.length()-1] == '\n') { suffix = suffix.substr(0, suffix.length()-1); } + dprintf(" suffix=\"%s\"\nget_hash(\"%s\",%d)\n", str.c_str(), salt_num); + + // Call jhash function to get the hash value + hash_num = jhash((void*)str.c_str(), str.length(), salt_num); + dprintf("jhash() returned: %u\n", hash_num); + sprintf(buf, "%u", hash_num & 0x0000ffff); + hash16 = buf; + sprintf(buf, "%u", ((salt_num << 16) | (hash_num & 0x0000ffff))); + hash32 = buf; + + // validate the hash value + size_t pos = hash32.find_first_not_of("0123456789"); + if (pos != string::npos) + { + fprintf(stderr, "trexhash error: %s\n", hash32.c_str()); + fprintf(stderr, "for call <<%s>>\n", cmd.c_str()); + exit(1); + } + +//removing this since it doesn't seem to have any affect on the output +#if 0 + // If hash is empty, use the sum of the ord values in the original string + if ((hash == "")||(hash == "0")) + { + unsigned int len = str.length(); + unsigned int hash_num = 0; + //unsigned char conv_buf[2] = { '\0', '\0' }; + u_int8_t conv_num; + for (unsigned int i=0; i < len; ++i) + { + //conv_buf[0] = str[i]; + conv_num = (u_int8_t)str[i]; + hash_num += (unsigned int)conv_num; + } + } +#endif + + dprintf("& rhash, string& line, string& out_line) +{ + // NOTE: "line" arg may get modified by this function! Caller must not assume it's unchanged. + string format; + string prefix; + string strings; + string tmp; + string salt; + string hash16; + string hash32; + int salt_num; + int format_salt; + string suffix; + string write_all_suffix; + size_t pos; + + out_line = ""; + // trace_ppe_hash ( "..." ".." "..." , 2 ) + // regex: PREFIX 'trace_ppe_hash' space '(' space STRINGS space ',' space NUMBER space ')' SUFFIX + // STRINGS: '"' .* '"' space? + + //while($line =~ m/^(.*?)trace_ppe_hash\s*\(\s*((".*?(? 1) arg = argv[1]; + if ((argc < 2) || (arg == "-h")) + { + fprintf(stderr, "usage: %s realcompiler compileroptions -o target source\n", argv[0]); + exit(9); + } + string realcc(argv[argi++]); + string cctype("c++"); + bool optx_found = false; + + if (realcc == "-d") + { + debug = true; + realcc = argv[argi++]; + } + + // wait until -d options is handled before checking $debug + dprintf("ppetracepp version %s - API/macro version %s\n", version.c_str(), macro_version.c_str()); + + p_env = getenv("REALCPP"); + string realcpp; + if (p_env) + realcpp = p_env; + if (realcpp.empty()) + { + dprintf("cannot find cpp, using -E\n"); + realcpp = realcc; + realcpp += " -E"; + } + dprintf("realcpp is %s\n", realcpp.c_str()); + +//------------------------------------------------------------------------------ +// parse all the arguments +//------------------------------------------------------------------------------ +string source; +string object; +vector ccopts; +vector cppopts; +bool dodeps = false; +string depfile; +string pfx; +string sfx; +int origargi = argi; +for( ; argi < argc; ++argi) +{ + arg = argv[argi]; + dprintf("Processing argv[%d]: \"%s\"\n", argi, arg.c_str()); + if (arg.length() > 2) + { + pfx = arg.substr(0,2); + sfx = arg.substr(arg.length()-2); + } + else + { + pfx = arg; + sfx = arg; + } + dprintf(" pfx: \"%s\" sfx: \"%s\"\n", pfx.c_str(), sfx.c_str()); + + if (pfx == "-o") + { + if (! object.empty()) + { + fprintf(stderr, "two -o options, aborting\n"); + exit(1); + } + if (arg.length() > 2) + { + object = sfx; + } + else + { + object = argv[++argi]; + } + dprintf("object is now %s\n", object.c_str()); + } + else if (arg == "-c") + { + // don't call cpp with -c, this is for the compiler + ccopts.push_back(arg); + dprintf("found -c option\n"); + } + else if (pfx == "-l") + { + // cpp doesn't need library arguments + cppopts.push_back(arg); + } + else if (pfx == "-i") + { + // option takes an argument, handle it too + optarg = argv[argi++]; + ccopts.push_back(arg); + ccopts.push_back(optarg); + cppopts.push_back(arg); + cppopts.push_back(optarg); + dprintf("found option '%s %s'\n", arg.c_str(), optarg.c_str()); + } + else if ((arg == "-L") || + (arg == "-I") || + (arg == "-x") || + (arg == "-b") || + (arg == "-B") || + (arg == "-V") || + (arg == "-D") || + (arg == "--param") || + (arg == "-MQ") || + (arg == "-MT")) + { + // option takes an argument, handle it too + optarg = argv[argi++]; + ccopts.push_back(arg); + ccopts.push_back(optarg); + cppopts.push_back(arg); + cppopts.push_back(optarg); + dprintf("found option '%s %s'\n", arg.c_str(), optarg.c_str()); + if (arg == "-x") + { + // option x sets the language - c or c++ + if ((optarg != "c") && (optarg != "c++") && (optarg != "assembler-with-cpp")) + { + fprintf(stderr, "cannot process language '%s', aborting\n", optarg.c_str()); + exit(1); + } + cctype = optarg; + optx_found = true; + } + } + else if ((arg == "-MD")||(arg == "-MG")) + { + // gen deps + dodeps = true; + dprintf("found %s, creating dependencies\n", arg.c_str()); + } + else if (arg == "-MF") + { + // set dependencies file + depfile = argv[argi++]; + dprintf("set dependencies file to '%s'\n", depfile.c_str()); + } + else if (arg[0] == '-') + { + // arg starts with - so it's an option + ccopts.push_back(arg); + cppopts.push_back(arg); + dprintf("found option '%s'\n", arg.c_str()); + } + else if ((sfx == ".a") || + (sfx == ".o")) + { + // an object or archive, ignore this but give it to cc + ccopts.push_back(arg); + dprintf("found object/archive '%s'\n", arg.c_str()); + } + else if ((sfx == ".c") || + (sfx == ".C") || + (sfx == ".S") || + (arg.substr(arg.length()-4) == ".cpp") || + (arg.substr(arg.length()-4) == ".cxx")) + { + // the source file(s). we should only get one + if (!source.empty()) + { + fprintf(stderr, "don't know to handle two source files, aborting\n"); + exit(1); + } + source = arg; + // put the - (for read-from-stdin) where the source file was + // (order is important!) + ccopts.push_back("-"); + dprintf("found source file %s\n", source.c_str()); + } + else if (access(arg.c_str(), F_OK)) + { + // option but not a file, an unknown option? + ccopts.push_back(arg); + cppopts.push_back(arg); + dprintf("found unknown option '%s'\n", arg.c_str()); + } +} + +//------------------------------------------------------------------------------ +// set other parameters based on arguments specified +//------------------------------------------------------------------------------ +if (source.empty()) +{ + // this might be a call to link a program instead of compile a source (or asm source) + dprintf("NOTME: starting as cc '%s ...'\n", realcc.c_str()); + execvp(realcc.c_str(), &(argv[origargi])); + fprintf(stderr, "ERROR: returned from execvp() call to run %s\n", realcc.c_str()); +} +if (object.empty()) +{ + dprintf("no object file given, default to source name\n"); + // gcc builds object name from source name if no -o given, replacing + // suffix with .o. The file is placed in the current directory, + // not in the source directory! + string n; + string d; + string s; + fileparse(source, n, d, s); + if (!n.empty() && !s.empty()) + { + object = n + ".o"; + dprintf("tracpp: guessing object name %s\n", object.c_str()); + dprintf(" from source name %s\n", source.c_str()); + } + else + { + fprintf(stderr, "Unable to determine Source File Name\n"); + exit(1);; + } +} + +// set value of trace hash according to language +// check source file extension if no explicit -x option given +if (!optx_found) +{ + if (realcc.find("g++") != string::npos) + { + dprintf("compiler language: C++ (from compiler name)\n"); + cctype = "c++"; + } + else + { + if (source.substr(source.length()-2) == ".c") + { + dprintf("compiler language: C (from source file extension)\n"); + cctype = "c"; + } + else if (source.substr(source.length()-2) == ".S") + { + dprintf("compiler language: assembly (from source file extension)\n"); + cctype = "assembler-with-cpp"; + } + else + { + dprintf("compiler language: C++ (default)\n"); + cctype = "c++"; + } + } +} +else +{ + dprintf("compiler language: %s (from option '-x')\n", cctype.c_str()); +} + +if (cctype == "c") +{ + hashtype = "(unsigned short)"; + hashtype_suffix = "U"; +} +else if (cctype == "assembler-with-cpp") +{ + hashtype = ""; + hashtype_suffix = ""; +} +else +{ + hashtype = "(trace_hash_val)"; + hashtype_suffix = "U"; +} +// define TRAC_PPETRACEPP for macros +tmp = "-DTRAC_PPETRACEPP -DTRAC_PPVER="; +tmp += macro_version; +cppopts.push_back(tmp); +if (dodeps) +{ + if (depfile.empty()) + { + if ((p_env = getenv("DEPENDENCIES_OUTPUT")) != NULL) + { + depfile = p_env; + } + else if ((p_env = getenv("SUNPRO_DEPENDENCIES")) != NULL) + { + depfile = p_env; + } + else + { + depfile = object; + if (depfile.substr(depfile.length()-2) == ".o") + { + depfile = depfile.substr(0, depfile.length()-2); + depfile += ".d"; + } + } + } + tmp = "-MD -MF "; + tmp += depfile; + cppopts.push_back(tmp); +} + +//------------------------------------------------------------------------------ +// start cpp +//------------------------------------------------------------------------------ +cmd = realcpp; +for(vector::iterator p = cppopts.begin(); p != cppopts.end(); ++p) +{ + cmd += " "; + cmd += *p; +} +cmd += " "; +cmd += source; +cmd += " -o-"; +dprintf("starting as cpp '%s'\n", cmd.c_str()); +CPP = popen(cmd.c_str(), "r"); +if (CPP == NULL) +{ + fprintf(stderr, "cannot start cpp '%s'\n", realcpp.c_str()); + perror(""); + exit(1); +} + +//------------------------------------------------------------------------------ +// start cc. manually set language as source file extension not available to cc +//------------------------------------------------------------------------------ +string type_str = ""; +if (!optx_found) +{ + // no option -x given by caller, set manually + type_str = "-x "; + type_str += cctype; +} +cmd = realcc; +cmd += " "; +cmd += type_str; +for(vector::iterator p = ccopts.begin(); p != ccopts.end(); ++p) +{ + cmd += " "; + cmd += *p; +} +cmd += " -o "; +cmd += object; +dprintf("starting as cc '%s'\n", cmd.c_str()); +CC = popen(cmd.c_str(), "w"); +if (CC == NULL) +{ + fprintf(stderr, "cannot start cc '%s'\n", realcc.c_str()); + perror(""); + exit(1); +} + +string modifiedfile; +string unmodifiedfile; +if (debug) +{ + modifiedfile = object + ".debug"; + DEBUG = fopen(modifiedfile.c_str(), "w"); + if (DEBUG == NULL) + { + string msg = "cannot open file "; + msg += modifiedfile; + perror(msg.c_str()); + modifiedfile = ""; + } + else + { + fprintf(stderr, "writing preprocessed source to %s\n", modifiedfile.c_str()); + } + unmodifiedfile = object + ".debug_in"; + DEBUGIN = fopen(unmodifiedfile.c_str(), "w"); + if (DEBUGIN == NULL) + { + string msg = "cannot open file "; + msg += unmodifiedfile; + perror(msg.c_str()); + unmodifiedfile = ""; + } + else + { + fprintf(stderr, "writing unprocessed source to %s\n", unmodifiedfile.c_str()); + } +} + +string oldline; +string newline; +static const int MAX_BUFFER = 51200; +char buf[MAX_BUFFER]; +while (!feof(CPP)) +{ + if (fgets(buf, MAX_BUFFER, CPP) != NULL) + { + oldline = buf; + if (DEBUGIN) { fprintf(DEBUGIN, "%s", oldline.c_str()); } + parse_line(hashtab, oldline, newline); + //#print "oldline = $oldline"; + //#print "newline = $newline"; + if (newline.empty()) + { + fprintf(stderr, "hash error in/with file %s\n", source.c_str()); + exit(1); + } + //#print "newline = $newline\n"; + fprintf(CC, "%s", newline.c_str()); + if (DEBUG) { fprintf(DEBUG, "%s", newline.c_str()); } + } +} +if (DEBUG) { fclose(DEBUG); } +if (DEBUGIN) { fclose(DEBUGIN); } +int cmd_rc = pclose(CPP); +if (cmd_rc) +{ + fprintf(stderr, "error from cpp\n"); + if (cmd_rc & 127) + { + fprintf(stderr, "cpp got signal %d\n", (cmd_rc & 127)); + exit(1); + } + else if (cmd_rc >> 8) + { + fprintf(stderr, "cpp returned %d\n", (cmd_rc >> 8)); + exit(cmd_rc >> 8); + } +} +cmd_rc = pclose(CC); +if (cmd_rc) +{ + fprintf(stderr, "error from cc\n"); + if (cmd_rc & 127) + { + fprintf(stderr, "cc got signal %d\n", (cmd_rc & 127)); + exit(1); + } + else if (cmd_rc >> 8) + { + fprintf(stderr, "cc returned %d\n", (cmd_rc >> 8)); + exit(cmd_rc >> 8); + } +} + +if (!hashtab.empty()) +{ + string stringfile = object; + stringfile += ".ppe.hash"; + // open trace string file + FILE* TRC = fopen(stringfile.c_str(), "w"); + if (TRC == NULL) + { + fprintf(stderr, "cannot write trace string file '%s'\n", stringfile.c_str()); + exit(1); + } + dprintf("Writing to file %s\n", stringfile.c_str()); + + string pwd; + FILE* PWD = popen("pwd", "r"); + fgets(buf, MAX_BUFFER, PWD); + pwd = buf; + pclose(PWD); + time_t tt = time(NULL); + sprintf(buf, "%s", asctime(localtime(&tt))); + buf[strlen(buf)-1] = '\0'; // chop off extra newline + fprintf(TRC, "#FSP_TRACE_v2|||%s|||BUILD:%s", buf, pwd.c_str()); + + string srch_str = "||"; + srch_str += source; + int srch_str_len = srch_str.length(); + size_t pos; + for(map::iterator p = hashtab.begin(); p != hashtab.end(); ++p) + { + pos = (p->second).find(srch_str); + if ((pos != string::npos) && ((pos + srch_str_len) == (p->second).length())) + { + // source file name is already part of the string + fprintf(TRC, "%s||%s\n", (p->first).c_str(), (p->second).c_str()); + } + else + { + fprintf(TRC, "%s||%s||%s\n", (p->first).c_str(), (p->second).c_str(), source.c_str()); + } + //#print TRC "$key||$source||$hashtab{$key}\n"; + } + fclose(TRC); +} +else +{ + dprintf("No trace calls/strings found, not writing hash file\n"); +} +} // end main diff --git a/src/tools/ppetracepp/trac_interface.h b/src/tools/ppetracepp/trac_interface.h new file mode 100755 index 00000000..2ff9dff0 --- /dev/null +++ b/src/tools/ppetracepp/trac_interface.h @@ -0,0 +1,369 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/tools/ppetracepp/trac_interface.h $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016 */ +/* */ +/* */ +/* 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 trac_interface.h +// @brief Interface codes for TRAC component. +*/ +/****************************************************************************** + * + * @page ChangeLogs Change Logs + * @section _trac_interface_h trac_interface.h + * @verbatim + * + * Flag Def/Fea Userid Date Description + * ------- ---------- -------- ---------- ---------------------------------- + * TEAM 06/16/2010 Port + * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments + * @pb00E pbavari 03/11/2012 Added correct include file + * @at009 859308 alvinwan 10/15/2012 Added tracepp support + * @ai005 860268 ailutsar 11/20/2012 Create trace test applet + * @rc005 864101 rickylie 12/12/2012 add small circ buffer to handle ISR semaphore conflict + * + * @endverbatim + * + *///*************************************************************************/ + +#ifndef _TRAC_INTERFACE_H +#define _TRAC_INTERFACE_H + +/** \defgroup Trace Trace Component + * Port of the trace code used in the fsp and tpmd. + */ + +//************************************************************************* +// Includes +//************************************************************************* + +//************************************************************************* +// Externs +//************************************************************************* + +//************************************************************************* +// Macros +//************************************************************************* +/** + * \defgroup TracMacros Trace Component Macro Interfaces + * \ingroup Trace + * Used to trace 0 - 5 arguments or a binary buffer when using a hash value. + */ +/*@{*/ + + +// @at009c - start +#define TRACE(i_td,i_string,args...) \ + trace_adal_write_all(i_td,trace_adal_hash(i_string,-1),__LINE__,0,##args) + +#define TRACEBIN(i_td,i_string,i_ptr,i_size) \ + trac_write_bin(i_td,trace_adal_hash(i_string,0),__LINE__,i_ptr,i_size) + +#ifndef NO_TRAC_STRINGS + +#define FIELD(a) \ + printf("%s",a) + +#define FIELD1(a,b) \ + printf("%s%lx",a,(unsigned long)b) + +#else // NO_TRAC_STRINGS + +#define FIELD(a) + +#define FIELD1(a,b) + +#endif // NO_TRAC_STRINGS + +#define SUCCESS 0 +// @at009c - end + + + +/*@}*/ + +//************************************************************************* +// Defines/Enums +//************************************************************************* +#define TRACE_MAX_ARGS 5 /*!< Maximum number of args to trace */ + +typedef uint32_t trace_hash_val; + +// NOTE! Increment this when new components are added! +#define TRAC_NUM_TRACE_COMPONENTS 1 + + +#define TRACE_BUFFER_SIZE 8192 // @ai005a + +#define CIRCULAR_BUFFER_SIZE 4 // @rc005a + +typedef uint32_t UINT32; +typedef int32_t INT32; +typedef uint8_t UCHAR; +typedef uint8_t UINT8; +typedef int8_t INT8; +typedef uint16_t UINT16; +typedef int16_t INT16; +typedef char CHAR; +typedef unsigned int UINT; +typedef unsigned long ULONG; +typedef int INT; +typedef void VOID; + +//************************************************************************* +// Structures +//************************************************************************* +/* + * @brief Structure is put at beginning of all trace buffers + */ +typedef struct trace_buf_head { + UCHAR ver; /*!< version of this struct (1) */ + UCHAR hdr_len; /*!< size of this struct in bytes */ + UCHAR time_flg; /*!< meaning of timestamp entry field */ + UCHAR endian_flg; /*!< flag for big ('B') or little ('L') endian */ + CHAR comp[16]; /*!< the buffer name as specified in init call */ + UINT32 size; /*!< size of buffer, including this struct */ + UINT32 times_wrap; /*!< how often the buffer wrapped */ + UINT32 next_free; /*!< offset of the byte behind the latest entry */ + UINT32 te_count; /*!< Updated each time a trace is done */ + UINT32 extracted; /*!< Not currently used */ +}trace_buf_head_t; + +/*! + * @brief Timestamp and thread id for each trace entry. + */ +typedef struct trace_entry_stamp { + UINT32 tbh; /*!< timestamp upper part */ + UINT32 tbl; /*!< timestamp lower part */ + UINT32 tid; /*!< process/thread id */ +}trace_entry_stamp_t; + +/* + * @brief Structure is used by adal app. layer to fill in trace info. + */ +typedef struct trace_entry_head { + UINT16 length; /*!< size of trace entry */ + UINT16 tag; /*!< type of entry: xTRACE xDUMP, (un)packed */ + UINT32 hash; /*!< a value for the (format) string */ + UINT32 line; /*!< source file line number of trace call */ +}trace_entry_head_t; + +/* + * @brief Parameter traces can be all contained in one write. + */ +typedef struct trace_entire_entry { + trace_entry_stamp_t stamp; + trace_entry_head_t head; + UINT32 args[TRACE_MAX_ARGS + 1]; +} trace_entire_entry_t; + + +/* + * @brief Binary first writes header and time stamp. + */ +typedef struct trace_bin_entry { + trace_entry_stamp_t stamp; + trace_entry_head_t head; +} trace_bin_entry_t; + +/** + * @brief Used as input to traces to get to correct buffer. + */ +typedef trace_buf_head_t * tracDesc_t; + +/* + * @brief Structure is used to hold array of all trace descriptors + */ +typedef struct trace_descriptor_array +{ + tracDesc_t *entry; /*!< Pointer to trace descriptor */ + CHAR *comp; /*!< Pointer to component name */ +}trace_descriptor_array_t; + +// @rc005a - start +typedef struct circular_buf_head +{ + UINT32 head; // pointer to head + UINT32 tail; // pointer to tail + UINT32 entryCount; // nums of entry +} circular_buf_header_t; + + +typedef struct circular_entire_data { + UINT32 len; + CHAR comp[4]; + trace_entire_entry_t entry; +} circular_entire_data_t; + +// @rc005a - end + +//************************************************************************* +// Globals +//************************************************************************* +// All TPMF component trace descriptors. +extern tracDesc_t g_trac_inf; // @at009a +extern tracDesc_t g_trac_err; // @at009a +extern tracDesc_t g_trac_imp; // @at009a + +extern const trace_descriptor_array_t g_des_array[]; + +//************************************************************************* +// Function Prototypes +//************************************************************************* + +/** + * \defgroup TracIntefaces Trace Component Interfaces for External Use + * \ingroup Trace + */ +/*@{*/ + + +/** + * @brief Allocate and initialize all trace buffers in memory. + * + * This function will allocate memory for each of the pre-defined trace + * buffers, initilize the buffers with starting data, and setup the + * trace descriptors which each component will use to trace. + * + * This function must be called first before any components try to trace! + * + * @return Non-zero return code on error. + */ +UINT TRAC_init_buffers(void); + +/** + * @brief Retrieve full trace buffer for component i_comp + * + * This function assumes memory has already been allocated for + * the full trace buffer in o_data. + * + * @param i_td_ptr Trace descriptor of buffer to retrieve. + * @param o_data Pre-allocated pointer to where data will be stored. + * + * @return Non-zero return code on error + */ +UINT TRAC_get_buffer(const tracDesc_t i_td_ptr, + void *o_data); + +/** + * @brief Retrieve partial trace buffer for component i_comp + * + * This function assumes memory has already been allocated for + * the trace buffer (size io_size). This function will copy + * in up to io_size in bytes to the buffer and set io_size + * to the exact size that is copied in. + * + * @param i_td_ptr Trace descriptor of buffer to retrieve. + * @param o_data Pre-allocated pointer to where data will be stored. + * @param io_size Size of trace data to retrieve (input) + * Actual size of trace data stored (output) + * + * @return Non-zero return code on error + */ +UINT TRAC_get_buffer_partial(const tracDesc_t i_td_ptr, + void *o_data, + UINT *io_size); + +/** + * @brief Retrieve trace descriptor for input component name + * + * @param i_comp Component name to retrieve trace descriptor for. + * + * @return Valid trace descriptor on success, NULL on failure. + */ +tracDesc_t TRAC_get_td(const char *i_comp); + +/** + * @brief Reset all trace buffers + * + * @return Non-zero return code on error + */ +UINT TRAC_reset_buf(void); + +/*@}*/ // Ending tag for external interface module in doxygen + + +/** + * @brief Trace input integers to trace buffer. + * + * This function assumes i_td has been initialized. + * + * @param io_td Intialized trace descriptor point to buffer to trace to. + * @param i_hash Hash value to be recorded for this trace. + * @param i_fmt Output format + * @param i_line Line number trace is occurring on. + * @param i_type trace type. filed or debug. + * @param ... parames that are limited to a size of 4 bytes, i.e. int, uint32_t, nnn* + * + * @return Non-zero return code on error. + */ +UINT trace_adal_write_all(tracDesc_t io_td,const trace_hash_val i_hash, + const char *i_fmt,const ULONG i_line, const ULONG i_type,...); + + +/** + * @brief Trace input integers to trace buffer. + * + * This function assumes i_td has been initialized. + * + * @param io_td Intialized trace descriptor point to buffer to trace to. + * @param i_hash Hash value to be recorded for this trace. + * @param i_line Line number trace is occurring on. + * @param i_num_args Number of arguments to trace. + * @param i_1 Input Parameter 1 + * @param i_2 Input Parameter 2 + * @param i_3 Input Parameter 3 + * @param i_4 Input Parameter 4 + * @param i_5 Input Parameter 5 + * + * @return Non-zero return code on error. + */ +UINT trac_write_int(tracDesc_t io_td,const trace_hash_val i_hash, + const ULONG i_line, + const UINT i_num_args, + const ULONG i_1,const ULONG i_2,const ULONG i_3, + const ULONG i_4,const ULONG i_5 + ); + + + /** + * @brief Trace binary data to buffer. + * + * This function assumes i_td has been initialized. + * + * @param io_td Intialized trace descriptor point to buffer to trace to. + * @param i_hash Hash value to be recorded for this trace. + * @param i_line Line number trace is occurring on. + * @param i_ptr Pointer to binary data to trace. + * @param i_size Size of data to copy from i_ptr. + * + * @return Non-zero return code on error. + */ +UINT trac_write_bin(tracDesc_t io_td,const trace_hash_val i_hash, + const ULONG i_line, + const void *i_ptr, + const ULONG i_size); + +//************************************************************************* +// Functions +//************************************************************************* + +#endif //_TRAC_INTERFACE_H diff --git a/src/tools/ppetracepp/tracehash.pl b/src/tools/ppetracepp/tracehash.pl new file mode 100755 index 00000000..8855adee --- /dev/null +++ b/src/tools/ppetracepp/tracehash.pl @@ -0,0 +1,896 @@ +#!/usr/bin/perl -w +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/tools/ppetracepp/tracehash.pl $ +# +# OpenPOWER sbe Project +# +# Contributors Listed Below - COPYRIGHT 2015,2016 +# +# +# 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 tracehash.pl created by B J Zander. + +use strict; + +sub determine_args(); +sub launch_cpp_and_parse($$); +sub cpp_dir($); +sub read_string_file(); +sub collect_files($); +sub assimilate_file($); +sub hash_strings(); +sub write_string_file(); +sub help(); + +select (STDERR); +$| = 1; # Make all prints to STDERR flush the buffer immediately +select (STDOUT); +$| = 1; # Make all prints to STDOUT flush the buffer immediately + +# Constants +my $HEAD_SEP = "|||"; +my $HEAD_EYE_CATCHER = "#FSP_TRACE_v"; +my $HEAD_BUILD_FLAG = "BUILD:"; +my $HEAD_VER_FLAG = 2; +my $BB_STRING_FILE = "/opt/fsp/etc/BB_StringFile"; + +# Global Variables +my $debug = 0; +my $seperator = "&&&&"; +my $file_name = "sbeStringFile"; +my $in_sand; +my ($backing) = $ENV{'bb'}; +my $hash_prog = "trexhash"; #default to in path +my $build = ""; +my ($sandbox) = $ENV{'SANDBOX'} || ""; +my ($context) = $ENV{'CONTEXT'} || ""; +my ($sandboxbase) = $ENV{'SANDBOXBASE'} || ""; +my ($bb); +my ($sourcebase) = "$sandboxbase/src"; +my ($version) = $HEAD_VER_FLAG; # default to oldest version +my ($collect) = 0; +my ($INCLUDE, $Arg, $file, $dir, $string_file); +my $args = ""; + +my $fail_on_collision = 0; # 1 = exit with error if hash collision occurs +my $hash_filename_too = 0; # 1 = hash is calculated over format string + filename + +print "sourcebase = $sourcebase\n" if $debug; +print "sandbox = $sandbox\n" if $debug; +print "backing = $backing\n" if $debug; +print "context = $context\n" if $debug; + +if ($context =~ /x86/) +{ + $bb = "i586-pc-linux-gnu"; +} +else +{ + $bb = "powerpc-linux"; +} + +if(($sourcebase =~ /\w+/) && ($sandbox =~ /\w+/)) +{ + $INCLUDE = "-I $sandboxbase/export/$context/fips/include -I $backing/export/$context/fips/include -I /opt/fsp/$bb/include/fsp -I/opt/fsp/$bb/include/ -include /opt/fsp/$bb/include/fsp/tracinterface.H"; +} +else +{ + print "Not in Sandbox so guessing Include Paths...\n" if $debug; + $INCLUDE = "-I/opt/fsp/i586-pc-linux-gnu/include/fsp -I/opt/fsp/i586-pc-linux-gnu/include/ -include /opt/fsp/i586-pc-linux-gnu/include/fsp/tracinterface.H"; +} + +# I/P Series work in ODE sandbox env. +if ($sandboxbase =~ /\w+/) +{ + $in_sand = 1; + print "backing = $backing\n" if $debug; +} +else +{ + $in_sand = 0; +} + + + +# Parse the input parameters. + +while (@ARGV) { + $Arg = shift; + + if ($Arg eq "-h" || $Arg eq "-H") { + help(); + exit(127); + } + if ($Arg eq "-f") { + $file = shift; + next; + } + if ($Arg eq "-d") { + $dir = shift; + next; + } + if ($Arg eq "-s") { + $string_file = shift; + next; + } + if ($Arg eq "-c") { + $collect = 1; + next; + } + if ($Arg eq "-v") { + $debug = 1; + print "debug on\n" if $debug; + next; + } + if ($Arg eq "-C") { # fail if a hash collision is detected + $fail_on_collision = 1; + next; + } + if ($Arg eq "-F") { # hash is calculated over format string + file name + $hash_filename_too = 1; + next; + } + if ($Arg eq "-S") { + $BB_STRING_FILE = ""; + next; + } + + #just pass it onto compiler + $args = $args . " " . $Arg; +} + +print "args = $args\n" if $debug; + +if (!$file && !$dir && !$in_sand) { + help(); + exit(127); +} + +################################# +# M A I N # +################################# + +my $clock = `date`; + +$build = $HEAD_EYE_CATCHER . "$HEAD_VER_FLAG" . $HEAD_SEP . $clock . $HEAD_SEP . $HEAD_BUILD_FLAG; + +$build =~ s/\n//g; + +# Global array to hold the parsed TRAC macro calls. +my @strings = (); + +# Assoc. arrays to hold hash|string values. +my %string_file_array = (); +my %hash_strings_array = (); + +# Check all provided arguments and look for defaults if not provided by user +determine_args(); + +# Scan the appropriate files or directories for TRAC macro calls. + +if (defined $dir) +{ + + $build = $build . $dir; # default to put at top of string file + if($collect) + { + collect_files($dir); + } + else + { + cpp_dir($dir); + # Hash the string that have been scanned. + %hash_strings_array = hash_strings(); + } +} +else +{ + $build = $build . $file; # default to put at top of string file + + if($collect) + { + assimilate_file($file); + } + else + { + # make sure include path includes directory that file is in + if($file =~ /^(.+)\/[^\/]+\.C$/) + { + + launch_cpp_and_parse($file,$1); + } + else + { + # No path in front of file so it has to be local dir + launch_cpp_and_parse($file,"./"); + } + # Hash the string that have been scanned. + %hash_strings_array = hash_strings(); + } +} + +# Read the existing string file into memory. +%string_file_array = read_string_file(); + +# Write out the new string file. check for collisions of new/old string here +write_string_file(); + +print "Hashing Started at $clock\n"; +$clock = `date`; +print "Hashing Finished at $clock\n"; + +exit 0; + + +################################# +# S U B R O U T I N E S # +################################# + +#============================================================================= +# Enhance usability by figuring out which build env. we are in +#============================================================================= +sub determine_args() { + + + # Find trexhash program + # but only if needed (i.e. not in collect mode) + if (!$collect) { + my $tmp = `which $hash_prog`; + chomp $tmp; + + if ($tmp eq '') { + print STDOUT "\nWarning: Program trexhash does not exist in path.\n" if $debug; + $hash_prog = "./trexhash"; + + $tmp = `which $hash_prog`; + chomp $tmp; + if ($tmp eq '') { + print STDOUT "\nError: Unable to find trexhash \n"; + exit(127); + } + } + } + + # Verify input values. + if ((!defined $file) && (!defined $dir)) { + if(!($in_sand)) + { + print STDOUT "\nError: No input directory or file provided as input to scan\n"; + exit(127); + } + + # Assume they want sandbox scanned + if($collect) + { + # collect all string files generated by tracepp and merge + $dir = "$sandboxbase/obj/"; + } + else + { + # generate our own string file by pre-compiling all source code + $dir = "$sandboxbase/src/"; + } + print STDOUT "\n-f or -d not found...scanning $dir by default\n\n"; + } + + if (!defined $string_file) + { + if ($in_sand) + { + + # Copy the current string file from backing build into our sandbox + system ("cp $backing/obj/$file_name $sandboxbase/obj/$file_name") + if !(-e "$sandboxbase/obj/$file_name"); + + $string_file = "$sandboxbase/obj/$file_name"; + } + else + { + $string_file = "./$file_name"; + } + print STDOUT "-sf not specified, using $string_file instead...\n\n" if $debug; + + } + + # Try Creating the string file + `touch $string_file`; + + if (! -f $string_file) { + print STDOUT "\nError: File $string_file does not exist. Current directory may not be writable.\n\n"; + help(); + exit(127); + } + + # Make sure sbeStringFile is readable/writeable + system("chmod ugo+rw $string_file"); + +} + +#============================================================================= +# Launch cpp script and grab input from it looking for trace calls. +#============================================================================= +sub launch_cpp_and_parse($$) { + + my ($l_loc, $l_dir) = @_; + + print "Processing file $l_loc\n" if $debug; + my $cmd = "/usr/bin/cpp $INCLUDE -I $l_dir $args $l_loc|"; + print "$cmd\n" if $debug; + open(FH,"$cmd") + or die ("Cannot open $_:$!,stopped"); + + # Read through all lines in the file.. + my $line = ; + while (defined $line) + { + chop $line; # remove EOL + $line =~ s/^\s*//; # remove unneccesary beginning white space. + $line =~ s/\s*$//; # remove unneccesary ending white space. + # Look for lines that are trace macro calls. + #if (/(trace_adal_hash)(\()( *)(".+")(,)(\d)/) + #if ($line =~ /(.*?)(trace_adal_hash)(\()( *)(".+")(,)(\d)\)+(.*\d.*)/) + while($line =~ m/^(.*?)trace_adal_hash\s*\(\s*(("[^"]*"\s*)+),\s*(\d+)\s*\)(.*)$/) + { + my ($prefix, $strings, $salt, $suffix) = ($1, $2, $4, $5); + print STDOUT "$strings $salt\n" if $debug; + $strings =~ s/"\s*$//; # remove trailing " and space + $strings =~ s/^"//; # remove leading " + $strings =~ s/"\s*"//g; + # Check to see if it's contained on a single line, or if we + # have to combine lines to get a complete trace call. + + # Save the macro call so it can be hashed later.. + push (@strings, [$l_loc, $strings, $salt]); + $line = $suffix; # check rest of line for a second trace call + } + my $nextline = ; + last if !defined $nextline; + # if a trace call is spread over multiple lines we have to add the next + # line from the source. the only problem is the definition/declaration + # of trace_adal_hash: we have to ignore that. we catch that by requiring + # a " after the function name. hopefully nobody writes a comment with + # a " after the function declaration ... + if ($line =~ /trace_adal_hash.*"/) { + $line .= $nextline; + } else { + $line = $nextline; + } + } + close(FH); +} + +#============================================================================= +# run cpp on all files in this directory and return the output +#============================================================================= +sub cpp_dir($) { + + my ($l_dir) = @_; + my @dir_entry; + my $l_entry; + + # Open the directory and read all entry names. + opendir ( DH , "$l_dir") + or die ("Cannot open $l_dir: $!, stopped"); + + print STDOUT "Processing directory $l_dir\n" if $debug; + @dir_entry = readdir(DH); + closedir(DH); + + while (@dir_entry) { + $l_entry = shift(@dir_entry); + + if ($l_dir =~ m"/$") { + $l_entry = "$l_dir$l_entry"; + } + else { + $l_entry = "$l_dir/$l_entry"; + } + + # Is the entry a directory? + if (-d $l_entry) { + + if($l_entry =~ m"/?([^/]+)$") + { + # check dir we are going into + print "dir = $1\n" if $debug; + # should we recurse into this directory. + if ($1 =~ m/^(\.\.?|sim[ou]|bldv)$/) + { + next; # skip '.', '..' and some fips dirs + } + cpp_dir($l_entry); + } + else + { + # unable to determine name of dir (no / in filename) + # should we recurse into this directory. + if ($l_entry =~ m/^(\.\.?|sim[ou]|bldv)$/) + { + next; # skip '.', '..' and some fips dirs + } + cpp_dir($l_entry); + } + } + # Is the entry a file? + elsif ((-f $l_entry) && ($l_entry =~ m/\.C$/)) { + # it's a file so + launch_cpp_and_parse($l_entry,$l_dir); + } + else { + # Not a file or directory so ignore it... + } + } +} + +#============================================================================= +# Read in strings from the existing trace string file.... +#============================================================================= +sub read_string_file() { + + my %o_strings; + my ($line) = ""; + my ($l_hash) = ""; + my ($l_str) = ""; + my ($cur_build) = ""; + my ($l_file) = ""; + + + # Make sure we can open each file. + open ( FH , "<$string_file") + or die ("Cannot open $_: $!, stopped"); + + $line = ; + + print "first line in sbeStringFile= $line\n" if $debug; + + if((defined $line) && ($line =~ /^$HEAD_EYE_CATCHER(\d)/)) + { + $version = $1; + + print "version = $version\n" if $debug; + + #Always put latest version in file + $line =~ s/^$HEAD_EYE_CATCHER\d/${HEAD_EYE_CATCHER}${HEAD_VER_FLAG}/; + + # Take previous version in file and use it. + $build = $line; + chomp($build); + $line = ; + + while (defined $line) { + chomp $line; # remove EOL + if($version eq "1") + { + ($l_hash, $l_file ,$l_str) = split(/\|\|/, $line); + } + elsif($version eq "2") + { + ($l_hash, $l_str ,$l_file) = split(/\|\|/, $line); + } + else + { + print "Unknown version of stringfile $version\n"; + exit(127); + } + $o_strings{$l_hash} = $l_str . "||" . $l_file; + $line = ; + } + + } + else + { # If there is a file then we are dealing with the first + # version of sbeStringFile so don't look for file name. + if ($debug) { + print "version 0 stringfile detected: $string_file\n"; + } + + # there is a file and it doesn't have a header + $version = 0; + + while (defined $line) { + chomp $line; # remove EOL + ($l_hash,$l_str) = split(/\|\|/, $line); + $o_strings{$l_hash} =$l_str . "||" . "NO FILE"; + $line = ; + } + } + + close(FH); + + #Time to look for a building block string file + if($BB_STRING_FILE ne "" and $string_file ne $BB_STRING_FILE and -f $BB_STRING_FILE) + { + + # Make sure we can open the file. + open ( FH , "<$BB_STRING_FILE") + or die ("Cannot open $_: $!, stopped"); + + $line = ; + + print "first line in BB_StringFile = $line\n" if $debug; + if((defined $line) && ($line =~ /^$HEAD_EYE_CATCHER(\d)/)) + { + $version = $1; + + $line = ; + while (defined $line) + { + chop $line; # remove EOL + if($version eq "1") + { + ($l_hash, $l_file ,$l_str) = split(/\|\|/, $line); + } + elsif($version eq "2") + { + ($l_hash, $l_str ,$l_file) = split(/\|\|/, $line); + } + #($l_hash, $l_file ,$l_str) = split(/\|\|/, $line); + $o_strings{$l_hash} = $l_str . "||" . $l_file ; + $line = ; + } + } + else + { + print "*** ERROR: BB_StringFile '$BB_STRING_FILE' should always have version!!!\n" + } + + } + else + { + print "$BB_STRING_FILE is not available\n" if $debug; + } + #All files are latest version now. + $version = $HEAD_VER_FLAG; + return %o_strings; +} + +#============================================================================= +# Read in strings from the existing trace string file.... +#============================================================================= +sub collect_files($) { + + my ($l_dir) = @_; + my (@dir_entry); + my ($l_entry) = ""; + + # Open the directory and read all entry names. + opendir ( DH , "$l_dir") + or die ("Cannot open $l_dir: $!, stopped"); + + print STDOUT "Processing directory $l_dir\n" if $debug; + @dir_entry = readdir(DH); + closedir(DH); + + while (@dir_entry) { + $l_entry = shift(@dir_entry); + + if ($l_dir =~ m"/$") { + $l_entry = "$l_dir$l_entry"; + } + else { + $l_entry = "$l_dir/$l_entry"; + } + + # Is the entry a directory? + if (-d $l_entry) { + + # should we recurse into this directory. + if ($l_entry =~ m/\/(\.\.?|sim[ou]|bldv)$/) + { + next; # skip '.', '..' and some fips dirs + } + collect_files($l_entry); + } + # Is the entry a file? + elsif ((-f $l_entry) && ($l_entry =~ m"\.hash$")) { + # it's a file so + assimilate_file($l_entry); + } + else { + # Not a file or directory so ignore it... + } + } + +} + +#============================================================================= +# Read in data from file and add to master one +#============================================================================= +sub assimilate_file($) { + + my ($l_loc) = @_; + + my (%o_strings); + my ($line) = ""; + my ($l_hash) = ""; + my ($l_str) = ""; + my ($l_file) = ""; + + # Make sure we can open each file. + open ( FH , "<$l_loc") + or die ("Cannot open $_: $!, stopped"); + + $line = ; + + print "Assimilate: first line in $l_loc = $line" if $debug; + + if((defined $line) && ($line =~ /^$HEAD_EYE_CATCHER(\d)/)) + { + $version = $1; + if ($version eq "1") { + if ($hash_filename_too) { + print "*** ERROR: hash_filename_too (-F) isn't possible with trace version 1\n"; + print " please rebuild all .hash files and global sbeStringFile\n"; + print " version 1 file is '$l_loc'\n"; + exit(127); + } + } elsif ($version ne "2") { + print "Unknown version of stringfile $version\n"; + exit(127); + } + + $line = ; + + + while (defined $line) { + chop $line; # remove EOL + if($version eq "1") + { + ($l_hash, $l_file ,$l_str) = split(/\|\|/, $line); + } + elsif($version eq "2") + { + ($l_hash, $l_str ,$l_file) = split(/\|\|/, $line); + } + my $newstring = $l_str . "||" . $l_file; + if (exists $hash_strings_array{$l_hash}) { + my $hashstr1 = $hash_strings_array{$l_hash}; + my $hashstr2 = $newstring; + if (!$hash_filename_too) { + # hash was made over format string only, remove file name + $hashstr1 =~ s/\|\|.*$//; + $hashstr2 = $l_str; + } + if ($debug) { + print "a_f: compare $hashstr1\n", + " vs. $hashstr2\n"; + } + if ($hashstr1 ne $hashstr2) + { + print "*** ERROR: HASH Collision! (a_f)\n", + " Two different strings have the same hash value ($l_hash)\n", + " String 1: $hash_strings_array{$l_hash}\n", + " String 2: $newstring\n"; + if ($fail_on_collision) { + exit(1); + } + } + } + $hash_strings_array{$l_hash} = $newstring; + $line = ; + } + + } + else + { # If there is a file then we are dealing with the first + # version of sbeStringFile so don't look for file name. + # these files shouldn't be there anymore. we don't check for collisions here + if ($debug) { + print "version 0 stringfile detected: $string_file\n"; + } + + if(defined $line) + { + # there is a file and it doesn't have a header + $version = 0; + } + + while (defined $line) { + chop $line; # remove EOL + ($l_hash,$l_str) = split(/\|\|/, $line); + $hash_strings_array{$l_hash} = $l_str . "||" . "NO FILE"; + $line = ; + } + } + $version = $HEAD_VER_FLAG; + close(FH); +} + +#============================================================================= + +#============================================================================= +sub hash_strings() { + + my ($hash_val, $l_key, $l_hash, %l_hash_strings); + my ($line_feed) = chr(10); + my ($l_file_name) = "NO FILENAME"; + print "\nHashing printf strings.\n\n"; + + foreach my $str (@strings) { + my $printf_string; + $l_file_name = $str->[0]; + $printf_string = $str->[1]; + $l_key = $str->[2]; + print "printf_string = $printf_string\n" if $debug; + $printf_string =~ s/"\s?"//g; #multi line traces will have extra " in them + $printf_string =~ s/`/\\`/g; # excape ' + $printf_string =~ s/\\n/$line_feed/g; # escape \n + if ($hash_filename_too) { + $printf_string .= "||" . $l_file_name; + } + + # call the hasher. + print "$hash_prog \"$printf_string\" $l_key\n" if $debug; + $hash_val = `$hash_prog \"$printf_string\" $l_key`; + if ($?) { + my ($hp_ret, $hp_sig) = ($? >> 8, $? & 127); + if ($hp_sig) { + print "*** ERROR: $hash_prog died with signal $hp_sig\n"; + } elsif ($hp_ret) { + print "*** ERROR: $hash_prog returned the error $hp_ret\n"; + if ($hash_val) { + print " error from $hash_prog:\n$hash_val"; + } + } + exit(1); + } + print "printf_string = $printf_string l_key = $l_key hash val = $hash_val\n" if $debug; + + # undo escaping + $printf_string =~ s/$line_feed/\\n/g; + $printf_string =~ s/\\`/`/g; + + if (exists $l_hash_strings{$hash_val}) + { + # hash val was found before. check if it's the same string + # else we have a hash collision + my $l_tmp = $l_hash_strings{$hash_val}; + if (!$hash_filename_too) { + $l_tmp =~ s/\|\|.*$//; + } + if ($l_tmp ne $printf_string) + { + print "*** ERROR: HASH Collision! (h_s)\n", + " Two different strings have the same hash value ($hash_val)\n", + " String 1: $l_hash_strings{$hash_val}\n", + " String 2: $printf_string (file $l_file_name)\n"; + if ($fail_on_collision) { + exit(1); + } + } + } + # this will overwrite an old string with a new one if a collision occurred + # but we might want to bail out in this case anyway + $printf_string = $printf_string . "||" . $l_file_name; + $l_hash_strings{$hash_val} = $printf_string; + } + return %l_hash_strings; +} +#============================================================================= + +#============================================================================= +sub write_string_file() { + + my (@keys) = (); + my ($l_key) = ""; + + # Combine the contents of the existing string file with the trace calls + # that we have just hashed. + print STDOUT "\nCombining Hash strings...\n\n"; + + @keys = keys(%hash_strings_array); + + foreach $l_key (@keys) { + my $l_tmp = $hash_strings_array{$l_key}; # freshly collected strings + if (exists $string_file_array{$l_key}) + { # hash exists in list from sbeStringFile + my $l_tmp2 = $string_file_array{$l_key}; + if (!$hash_filename_too) { + $l_tmp =~ s/\|\|.*$//; + $l_tmp2 =~ s/\|\|.*$//; + } + + # Check for hash collisions. + if ($l_tmp ne $l_tmp2) + { + print "*** ERROR: HASH Collision! (w_s_f)\n", + " Two different strings have the same hash value ($l_key)\n", + " String 1: $hash_strings_array{$l_key}\n", + " String 2: $string_file_array{$l_key}\n"; + if ($fail_on_collision) { + exit(1); + } + # don't fail, write new one + } + } + if($version > 0) + { + # add/replace the new string to the string_file_array. + $string_file_array{$l_key} = $hash_strings_array{$l_key} + } + else + { + # old version so only write out format string (not file name to) + $string_file_array{$l_key} = $l_tmp; + } + } + + # Write out the updated string file. + print STDOUT "\nWriting updated hash||string file...\n\n"; + + @keys = sort(keys(%string_file_array)); + + open ( FH , ">$string_file") + or die ("Cannot open $_: $!, stopped"); + + if($version > 0) + { + print FH "$build\n"; # only print version if newer then version 0 + } + foreach $l_key (@keys) { + print FH "$l_key||$string_file_array{$l_key}\n"; + } + close FH; +} +#============================================================================= + +#============================================================================= +# Display command invokation help for this program... +#============================================================================= +sub help() { + print << "EOF"; +tracehash.pl - create a trace string file from sources or collect tracepp files +Usage: tracehash.pl [options] + General options: + -h - Print this help text. + -v - Be verbose, tell what's going on (debug output) + Operation modes + -c - Collect StringFiles created by tracepp and merge. + default - Scan source files for trace calls. + +Collect mode: tracehash.pl -c [-vFCS] [-d ] [-s ] + tracehash.pl -c [-vFCS] [-f ] [-s ] + Collect string files created by tracepp (.hash) from directory tree at + or read them from string file and write to file + , adding entries already in this file. + -f - String file to read and write/add to . + -d - Start of directory tree to scan for .hash files. Default = . + -s - File with trace strings (and hashes) to read from and write to + default = ./sbeStringFile + -F - hash is calculated over trace string and source file name, + otherwise without source file name + -C - report an error if a hash collisions occurs + -S - don't read global FLD-2.2 string file ($BB_STRING_FILE) + If tracehash.pl is called in a FipS build sandbox without -d and -f + defaults for the sandbox will be used. + +Scan mode: tracehash.pl [-vFCS] [-d ] [-s ] [ccpopts] + tracehash.pl [-vFCS] [-f ] [-s ] [cppopts] + Scan all files in directory tree or scan file and write + strings to file . Strings already in this file will be merged. + -f - Source file to scan for trace entries. + -d - Source directory to scan for trace entries. + -s - File with trace strings (and hashes) to read from and write to. + default = ./sbeStringFile + -F - hash for string was build from format string + source file name + -C - report an error if hash collisions occur + -S - don't read global FLD-2.2 string file ($BB_STRING_FILE) + All other arguments will be passed verbatim to cpp +EOF +} +#============================================================================= + diff --git a/src/tools/scripts/parseErrorInfo.pl b/src/tools/scripts/parseErrorInfo.pl new file mode 100755 index 00000000..839a836c --- /dev/null +++ b/src/tools/scripts/parseErrorInfo.pl @@ -0,0 +1,1663 @@ +#!/usr/bin/perl +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/tools/scripts/parseErrorInfo.pl $ +# +# OpenPOWER sbe Project +# +# Contributors Listed Below - COPYRIGHT 2015,2016 +# +# +# 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 parseErrorInfo.pl +# @brief This perl script will parse HWP Error XML files and generate required +# FAPI code to create and error log and add FFDC to the error. +# +# *HWP HWP Owner: N/A +# *HWP FW Owner: Thi Tran +# *HWP Team: N/A +# *HWP Level: 1 +# *HWP Consumed by: HB +# +# Usage: +# parseErrorInfo.pl ... + +use strict; + +#------------------------------------------------------------------------------ +# 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'; + +#------------------------------------------------------------------------------ +# Specify perl modules to use +#------------------------------------------------------------------------------ +use Digest::MD5 qw(md5_hex); +use XML::Simple; +my $xml = new XML::Simple (KeyAttr=>[]); + +# Uncomment to enable debug output +use Data::Dumper; +use Getopt::Long; + +my $target_ffdc_type = "fapi2::Target"; +my $buffer_ffdc_type = "fapi2::buffer"; +my $variable_buffer_ffdc_type = "fapi2::variable_buffer"; +my $ffdc_type = "fapi2::ffdc_t"; +my $mcast_type = "fapi2::mcast_t"; + +# We want to keep the signatures for the ffdc gathering hwp so that +# we can create members of the proper types for the ffdc classes. +my %signatures = ("proc_extract_pore_halt_ffdc" => ["por_base_state", + "por_halt_type_t", + "por_ffdc_offset_t"], + "hwpTestFfdc1" => [$target_ffdc_type], + "proc_extract_pore_base_ffdc" => ["por_base_state", "por_sbe_base_state"], + "proc_tp_collect_dbg_data" => [$target_ffdc_type], + ); + +# There are some names used in the XML files which exist in either +# c++ keywords (case, for example) or macros (DOMAIN). The one's which +# cause problems and need to be changed are here. +# +# DOMAIN is defined to 1 in math.h +my %mangle_names = ("DOMAIN" => "FAPI2_DOMAIN"); + +# A list of deprecated elements. These will report messages to the +# user, and not define anything. They have not been found to be used, +# but that doesn't mean they're not ... +my %deprecated = ("RC_PROCPM_PMCINIT_TIMEOUT" => "CHIP_IN_ERROR is defined as a callout procedure"); + +#------------------------------------------------------------------------------ +# Print Command Line Help +#------------------------------------------------------------------------------ +my $arg_empty_ffdc = undef; +my $arg_local_ffdc = undef; +my $arg_output_dir = undef; +my $arg_use_variable_buffers = undef; + +# Get the options from the command line - the rest of @ARGV will +# be filenames +GetOptions("empty-ffdc-classes" => \$arg_empty_ffdc, + "local-ffdc" => \$arg_local_ffdc, + "output-dir=s" => \$arg_output_dir, + "use-variable-buffers" => \$arg_use_variable_buffers); + +my $numArgs = $#ARGV + 1; +if (($numArgs < 1) || ($arg_output_dir eq undef)) +{ + print ("Usage: parseErrorInfo.pl [--empty-ffdc-classes] [--use-variable-buffers] --output-dir= ...\n"); + print (" This perl script will parse HWP Error XML files and creates\n"); + print (" the following files:\n"); + print (" - hwp_return_codes.H. HwpReturnCode enumeration (HWP generated errors)\n"); + print (" - hwp_error_info.H. Error information (used by FAPI_SET_HWP_ERROR\n"); + print (" when a HWP generates an error)\n"); + print (" - collect_reg_ffdc.H. Function to collect register FFDC\n"); + print (" - set_sbe_error.H. Macro to create an SBE error\n"); + print (" The --empty-ffdc-classes option is for platforms which don't collect ffdc.\n"); + exit(1); +} + +#------------------------------------------------------------------------------ +# Hashes containing error names/enum-values +#------------------------------------------------------------------------------ +my %errNameToValueHash; +my %errValuePresentHash; + +#------------------------------------------------------------------------------ +# Hashes containing ffdc names/enum-values +#------------------------------------------------------------------------------ +my %ffdcNameToValueHash; +my %ffdcValuePresentHash; + +#------------------------------------------------------------------------------ +# Subroutine that checks if an entry exists in an array. If it doesn't exist +# then it is added. The index of the entry within the array is returned +#------------------------------------------------------------------------------ +sub addEntryToArray +{ + my ($arrayref, $entry ) = @_; + + my $match = 0; + my $index = 0; + + foreach my $element (@$arrayref) + { + if ($element eq $entry) + { + $match = 1; + last; + } + else + { + $index++; + } + } + + if (!($match)) + { + push(@$arrayref, $entry); + } + + return $index; +} + +#------------------------------------------------------------------------------ +# Subroutine that figures out an error enum value from an error name and stores +# it in global hashes +#------------------------------------------------------------------------------ +sub setErrorEnumValue +{ + my $name = $_[0]; + + #-------------------------------------------------------------------------- + # Check that the error name is not a duplicate + #-------------------------------------------------------------------------- + if (exists($errNameToValueHash{$name})) + { + # Two different errors with the same name! + print ("fapiParseErrorInfo.pl ERROR. Duplicate error name ", $name, "\n"); + exit(1); + } + + #-------------------------------------------------------------------------- + # Figure out the error enum-value. This is a hash value generated from + # the error name. A hash is used for Cronus so that if a HWP is not + # recompiled against a new eCMD/Cronus version where the errors have + # changed then there will not be a mismatch in error values. + # This is a 24bit hash value because FAPI has a requirement that the + # top byte of the 32 bit error value be zero to store flags indicating + # the creator of the error + #-------------------------------------------------------------------------- + my $errHash128Bit = md5_hex($name); + my $errHash24Bit = substr($errHash128Bit, 0, 6); + + #-------------------------------------------------------------------------- + # Check that the error enum-value is not a duplicate + #-------------------------------------------------------------------------- + if (exists($errValuePresentHash{$errHash24Bit})) + { + # Two different errors generate the same hash-value! + print ("fapiParseAttributeInfo.pl ERROR. Duplicate error hash value\n"); + exit(1); + } + + #-------------------------------------------------------------------------- + # Update the hashes with the error name and ID + #-------------------------------------------------------------------------- + $errValuePresentHash{$errHash24Bit} = 1; + $errNameToValueHash{$name} = $errHash24Bit; +} + +#------------------------------------------------------------------------------ +# Subroutine that figures out an FFDC ID value from an FFDC name and stores it +# in global hashes for use when creating the enumeration of FFDC IDs +#------------------------------------------------------------------------------ +sub setFfdcIdValue +{ + my $name = $_[0]; + + #-------------------------------------------------------------------------- + # Check that the FFDC name is not a duplicate + #-------------------------------------------------------------------------- + if (exists($ffdcNameToValueHash{$name})) + { + # Two different FFDCs with the same name! + print ("fapiParseErrorInfo.pl ERROR. Duplicate FFDC name ", $name, "\n"); + exit(1); + } + + #-------------------------------------------------------------------------- + # Figure out the FFDC enum-value. This is a hash value generated from + # the FFDC name. + #-------------------------------------------------------------------------- + my $ffdcHash128Bit = md5_hex($name); + my $ffdcHash32Bit = substr($ffdcHash128Bit, 0, 8); + + #-------------------------------------------------------------------------- + # Check that the error enum-value is not a duplicate + #-------------------------------------------------------------------------- + if (exists($ffdcValuePresentHash{$ffdcHash32Bit})) + { + # Two different FFDCs generate the same hash-value! + print ("fapiParseAttributeInfo.pl ERROR. Duplicate FFDC hash value\n"); + exit(1); + } + + #-------------------------------------------------------------------------- + # Update the hashes with the error name and ID + #-------------------------------------------------------------------------- + $ffdcValuePresentHash{$ffdcHash32Bit} = 1; + $ffdcNameToValueHash{$name} = $ffdcHash32Bit; +} + +#------------------------------------------------------------------------------ +# Subroutine to create ffdc methods +#------------------------------------------------------------------------------ +sub addFfdcMethod +{ + my $methods = shift; + my $ffdc_uc = shift; + my $class_name = shift; + my $type = shift; + my $objectNumber = shift; + + # Remove the leading *_ + $class_name = (split (/_/, $class_name, 2))[1]; + + # If we didn't get a type passed in, this element will get an ffdc_t pair. + $type = $ffdc_type if ($type eq undef); + + # Mangle the uppercase name if needed + $ffdc_uc = $mangle_names{$ffdc_uc} if ($mangle_names{$ffdc_uc} ne undef); + + my $key = $ffdc_uc.$type; + my $key_target = $ffdc_uc.$target_ffdc_type; + my $key_ffdc = $ffdc_uc.$ffdc_type; + + # Check to see if this element already has been recorded with this + # type or a target type. Note the effect we're shooting for here is + # to define the member if it's not been defined before *or* it's + # changing from an ffdc_t to a target due to other information in the xml + return if ($methods->{$key}{type} eq $type); + return if ($methods->{$key_target}{type} eq $target_ffdc_type); + + # Just leave if this is a variable_buffer ans we're not supporting that. + return if (($type eq $variable_buffer_ffdc_type) && ($arg_use_variable_buffers eq undef)); + + # Set the proper type, and clear out any previous members/methods if + # we're going from an ffdc_t to a target. + $methods->{$key}{type} = $type; + delete $methods->{$key_ffdc} if ($type eq $target_ffdc_type); + + my $method = ""; + my $method_body = ""; + + # If we're generating empty classes, not using an argument name will avoid the unused parameter warnings + my $param = ($arg_empty_ffdc eq undef) ? "i_value" : ""; + + if ($type eq $ffdc_type) + { + $method = "\ttemplate< typename T >\n"; + $method .= "\tinline $class_name& set_$ffdc_uc(const T& $param)\n"; + + if(!$arg_local_ffdc) + { + $method_body = " {$ffdc_uc.ptr() = &i_value; $ffdc_uc.size() ="; + $method_body .= " fapi2::getErrorInfoFfdcSize(i_value); return *this;}\n\n"; + $methods->{$key}{member} = "$ffdc_type $ffdc_uc;\n "; + } + else + { + # need to use the objectNumber here so when we decode the info at the hwsv/hb side we have a reference, they will + # be copied into/out of the sbe buffer in the correct order + $method_body .= "\t{\n\t\tfapi2::g_FfdcData.ffdcData[$objectNumber].data= convertType(i_value);\n"; + $method_body .= "\t\tfapi2::g_FfdcData.ffdcData[$objectNumber].size ="; + $method_body .=" fapi2::getErrorInfoFfdcSize(i_value);\n"; + $method_body .= "\t\tfapi2::g_FfdcData.ffdcLength += sizeof(sbeFfdc_t);\n"; + $method_body .= "\t\treturn *this;\n\t};\n\n"; + } + + } + elsif ($type eq $mcast_type ) + { +# uncomment once multicast is understood more +# $method = "\n\t\ttemplate< typename T >\n"; +# $method .= "\t\tinline $class_name& set_$ffdc_uc(const T& $param)\n"; +# +# if(!$arg_local_ffdc) +# { +# $method_body = " {$ffdc_uc.ptr() = &i_value; $ffdc_uc.size() = fapi2::getErrorInfoFfdcSize(i_value); return *this;}\n\n"; +# $methods->{$key}{member} = "$mcast_type $ffdc_uc;\n "; +# } +# else +# { +# $method_body .= "\t\t{\n\t\t\tfapi2::g_ErrorInfoFfdc[$objectNumber].iv_ffdcId = fapi2::EI_TYPE_FFDC;\n"; +# $method_body .= "\t\t\tfapi2::g_ErrorInfoFfdc[$objectNumber].iv_ffdc.ptr() = &i_value;\n"; +# $method_body .= "\t\t\tfapi2::g_ErrorInfoFfdc[$objectNumber].iv_ffdc.size() = fapi2::getErrorInfoFfdcSize(i_value);"; +# $method_body .= "\n\t\t\treturn *this;\n\t\t};\n\n"; +# } +# + } + elsif ($type eq $buffer_ffdc_type) + { + # Two methods - one for integral buffers and one for variable_buffers + $method = "\n template< typename T >\n"; + $method .= " inline $class_name& set_$ffdc_uc(const fapi2::buffer& $param)\n"; + $method_body = " {$ffdc_uc.ptr() = &i_value(); $ffdc_uc.size() = i_value.template getLength(); return *this;}\n\n"; + + $methods->{$key}{member} = "$ffdc_type $ffdc_uc;\n "; + } + + elsif ($type eq $variable_buffer_ffdc_type) + { + $method = "\n inline $class_name& set_$ffdc_uc(const fapi2::variable_buffer& $param)\n"; + $method_body = " {$ffdc_uc.ptr() = &i_value(); $ffdc_uc.size() = i_value.template getLength(); return *this;}\n\n"; + + # No need to add the member here, it was added with fapi2::buffer. And we can't have variable + # buffer support with out integral buffer support (can we?) + } + + elsif ($type eq $target_ffdc_type) + { + $method = "\n template< TargetType T >\n"; + $method .= " inline $class_name& set_$ffdc_uc(const $type& $param)\n"; + $method_body .= " {$ffdc_uc.ptr() = &i_value; $ffdc_uc.size() = fapi2::getErrorInfoFfdcSize(i_value); return *this;}\n\n"; + + $methods->{$key}{member} = "$ffdc_type $ffdc_uc;\n "; + } + + else + { + print ("ffdc type $type is unknown\n"); + exit(1); + } + + $method .= ($arg_empty_ffdc eq undef) ? $method_body : " {return *this;}\n\n"; + $methods->{$key}{method} = $method; +} + +#------------------------------------------------------------------------------ +# Open output files for writing +#------------------------------------------------------------------------------ +my $rcFile = $arg_output_dir; +$rcFile .= "/"; +$rcFile .= "hwp_return_codes.H"; +open(RCFILE, ">", $rcFile); + +my $eiFile = $arg_output_dir; +$eiFile .= "/"; +$eiFile .= "hwp_error_info.H"; +open(EIFILE, ">", $eiFile); + +my $ecFile = $arg_output_dir; +$ecFile .= "/"; +$ecFile .= "hwp_ffdc_classes.H"; +open(ECFILE, ">", $ecFile); + +my $crFile = $arg_output_dir; +$crFile .= "/"; +$crFile .= "collect_reg_ffdc.H"; +open(CRFILE, ">", $crFile); + +my $sbFile = $arg_output_dir; +$sbFile .= "/"; +$sbFile .= "set_sbe_error.H"; +open(SBFILE, ">", $sbFile); + +#------------------------------------------------------------------------------ +# Print start of file information to hwp_error_info.H +#------------------------------------------------------------------------------ +print EIFILE "// hwp_error_info.H\n"; +print EIFILE "// This file is generated by the perl script parseErrorInfo.pl\n\n"; +print EIFILE "#ifndef FAPI2_HWPERRORINFO_H_\n"; +print EIFILE "#define FAPI2_HWPERRORINFO_H_\n\n"; +print EIFILE "#include \n"; +print EIFILE "#include \n"; +print EIFILE "#include \n"; +print EIFILE "#include \n"; +print EIFILE "/**\n"; +print EIFILE " * \@brief Error Information macros and HwpFfdcId enumeration\n"; +print EIFILE " *\/\n"; +#------------------------------------------------------------------------------ +# Print start of file information to hwp_ffdc_classes.H +#------------------------------------------------------------------------------ +print ECFILE "// hwp_ffdc_classes.H\n"; +print ECFILE "// This file is generated by the perl script parseErrorInfo.pl\n\n"; +print ECFILE "#ifndef FAPI2_HWP_FFDC_CLASSES_H_\n"; +print ECFILE "#define FAPI2_HWP_FFDC_CLASSES_H_\n\n"; +print ECFILE "#include \n"; +print ECFILE "#include \n"; +print ECFILE "#include \n" if ($arg_use_variable_buffers ne undef); +print ECFILE "#include \n"; +print ECFILE "#include \n"; +print ECFILE "#include \n"; +print ECFILE "#if !defined(FAPI2_NO_FFDC) && !defined(MINIMUM_FFDC)\n"; +#print ECFILE "#include \n"; +print ECFILE "#endif\n"; +#print ECFILE "#include \n\n"; +print ECFILE "/**\n"; +print ECFILE " * \@brief FFDC gathering classes\n"; +print ECFILE " *\/\n"; +print ECFILE "namespace fapi2\n{\n"; +if($arg_local_ffdc) +{ + print ECFILE "extern SbeFfdcData_t g_FfdcData; \n"; +} +#------------------------------------------------------------------------------ +# Print start of file information to collectRegFfdc.H +#------------------------------------------------------------------------------ +print CRFILE "// collect_reg_ffdc.H\n"; +print CRFILE "// This file is generated by the perl script parseErrorInfo.pl\n\n"; +print CRFILE "#ifndef FAPI2_COLLECT_REG_FFDC_H_\n"; +print CRFILE "#define FAPI2_COLLECT_REG_FFDC_H_\n"; +print CRFILE "#include \n"; +print CRFILE "#include \n"; +print CRFILE "#include \n"; +print CRFILE "#include \n"; +print CRFILE "#include \n"; +print CRFILE "#include \n"; +print CRFILE "#include \n"; +print CRFILE "#include \n"; +print CRFILE "#include \n"; +print CRFILE "#include \n"; +print CRFILE "namespace fapi2\n"; +print CRFILE "{\n"; +print CRFILE "template< TargetType C, TargetType P >\n"; +print CRFILE "void collectRegFfdc(const fapi2::ffdc_t& i_target,\n"; +print CRFILE " const fapi2::HwpFfdcId i_ffdcId,\n"; +print CRFILE " fapi2::ReturnCode & o_rc,\n"; +print CRFILE " uint32_t i_childOffsetMult = 0)\n"; +print CRFILE "{\n"; +print CRFILE " FAPI_INF(\"collectRegFfdc. FFDC ID: 0x%x\", i_ffdcId);\n"; +print CRFILE " fapi2::ReturnCode l_rc;\n"; +print CRFILE " fapi2::buffer l_buf;\n"; +print CRFILE " uint32_t l_cfamData = 0;\n"; +print CRFILE " uint64_t l_scomData = 0;\n"; +print CRFILE " std::vector l_cfamAddresses;\n"; +print CRFILE " std::vector l_scomAddresses;\n"; +print CRFILE " uint32_t l_ffdcSize = 0;\n\n"; +print CRFILE " switch (i_ffdcId)\n"; +print CRFILE " {\n"; +print CRFILE " // void statments for the unused variables\n"; +print CRFILE " static_cast(l_cfamData);\n"; +print CRFILE " static_cast(l_scomData);\n"; +print CRFILE " static_cast(l_ffdcSize);\n"; +print CRFILE " static_cast(i_target);\n"; +print CRFILE " static_cast(o_rc);\n"; +print CRFILE " static_cast(i_childOffsetMult);\n"; +#------------------------------------------------------------------------------ +# Print start of file information to setSbeError.H +#------------------------------------------------------------------------------ +print SBFILE "// setSbeError.H\n"; +print SBFILE "// This file is generated by the perl script parseErrorInfo.pl\n\n"; +print SBFILE "// When SBE code creates an error, it produces an error value\n"; +print SBFILE "// that matches a value in the HwpReturnCode enum in\n"; +print SBFILE "// fapiHwpReturnCodes.H. The SBE uses the __ASSEMBLER__\n"; +print SBFILE "// primitives in hwpReturnCodes.H to do this. The function\n"; +print SBFILE "// that extracts the error value from the SBE needs to call\n"; +print SBFILE "// FAPI_SET_HWP_ERROR to create the error and get all the\n"; +print SBFILE "// actions in the error XML file performed, but that macro can\n"; +print SBFILE "// only be called with the enumerator, not the value. This\n"; +print SBFILE "// FAPI_SET_SBE_ERROR macro can be called instead, it calls\n"; +print SBFILE "// FAPI_SET_HWP_ERROR with the correct error enumerator.\n"; +print SBFILE "// Errors containing in their XML are supported\n"; +print SBFILE "// in this macro.\n\n"; +print SBFILE "// Note that it is expected that this macro will be called\n"; +print SBFILE "// in one place (the function that extracts the error from\n"; +print SBFILE "// the SBE), if this changes and it is called in multiple\n"; +print SBFILE "// places then the macro could be turned into a function to\n"; +print SBFILE "// avoid the code size increase of expanding the macro in\n"; +print SBFILE "// multiple places. The function approach is slightly more\n"; +print SBFILE "// complicated, there is an extra C file and the function\n"; +print SBFILE "// must take a parameter for the generic chip ID in the error\n"; +print SBFILE "// XML.\n\n"; +print SBFILE "#ifndef FAPI2_SETSBEERROR_H_\n"; +print SBFILE "#define FAPI2_SETSBEERROR_H_\n\n"; +print SBFILE "#define FAPI_SET_SBE_ERROR(RC, ERRVAL, FFDC_BUFFER)\\\n"; +print SBFILE "{\\\n"; +print SBFILE "switch (ERRVAL)\\\n"; +print SBFILE "{\\\n"; + +#------------------------------------------------------------------------------ +# For each XML file +#------------------------------------------------------------------------------ +foreach my $argnum (0 .. $#ARGV) +{ + my $infile = $ARGV[$argnum]; + my $count = 0; + + #-------------------------------------------------------------------------- + # Read XML file. The ForceArray option ensures that there is an array of + # elements even if there is only one element + #-------------------------------------------------------------------------- + my $errors = $xml->XMLin($infile, ForceArray => + ['hwpError', 'collectFfdc', 'ffdc','mcastId', 'callout', 'deconfigure', 'gard', + 'registerFfdc', 'collectRegisterFfdc', 'cfamRegister', 'scomRegister', + 'id','collectTrace', 'buffer']); + + # Uncomment to get debug output of all errors + #print "\nFile: ", $infile, "\n", Dumper($errors), "\n"; + + #-------------------------------------------------------------------------- + # For each Error + #-------------------------------------------------------------------------- + foreach my $err (@{$errors->{hwpError}}) + { + my $objectStr = ""; + # Hash of methods for the ffdc-gathering class + my %methods; + + #---------------------------------------------------------------------- + # Check that expected fields are present + #---------------------------------------------------------------------- + if (! exists $err->{rc}) + { + print ("parseErrorInfo.pl ERROR. rc missing\n"); + exit(1); + } + + if (! exists $err->{description}) + { + print ("parseErrorInfo.pl ERROR in $err->{rc}. description missing\n"); + exit(1); + } + + #---------------------------------------------------------------------- + # Check that this rc hasn't been deprecated + #---------------------------------------------------------------------- + if ($deprecated{$err->{rc}} ne undef) + { + print "WARNING: $err->{rc} has been deprecated because $deprecated{$err->{rc}}\n"; + next; + } + + #---------------------------------------------------------------------- + # Set the error enum value in a global hash + #--------------------------------------------------------------------- + setErrorEnumValue($err->{rc}); + + + #---------------------------------------------------------------------- + # Print the CALL_FUNCS_TO_COLLECT_FFDC macro to hwp_error_info.H + #---------------------------------------------------------------------- + print EIFILE "#define $err->{rc}_CALL_FUNCS_TO_COLLECT_FFDC(RC) "; + + # For now, this code is removed. It appears to work just fine but + # will require more of the fapi2 infrastructure to be in place. + # Because the ffdc collection classes create members with real types, + # the declarations of the types need to be visible - and they're not + # right now. When we get further along, we can enable this code. + $count = 0; + foreach my $collectFfdc (@{$err->{collectFfdc}}) + { + if ($count == 0) + { + print EIFILE "{ fapi2::ReturnCode l_tempRc; "; + } + $count++; + + print EIFILE "FAPI_EXEC_HWP(l_tempRc, $collectFfdc, RC); "; + + # collectFfdc is a string we're going to stuff into FAPI_EXEC_HWP + # but we need to create the arguments in the ffdc class. The first + # element inthe collectFfdc string is the function to call. + my @elements = split /,/, $collectFfdc; +# my @signature = @{$signatures{@elements[0]}}; +# +# $TODO for SBE errors we need to get the parameters from the FFDC_BUFFER passed + for (my $i = 1; $i <= $#elements; $i++) + { + @elements[$i] =~ s/^\s+|\s+$//g; + addFfdcMethod(\%methods, @elements[$i], $err->{rc}); + } + } + + if ($count > 0) + { + print EIFILE "}"; + } + print EIFILE "\n"; + + #---------------------------------------------------------------------- + # Print the CALL_FUNCS_TO_COLLECT_REG_FFDC macro to hwp_error_info.H + #---------------------------------------------------------------------- + print EIFILE "#define $err->{rc}_CALL_FUNCS_TO_COLLECT_REG_FFDC(RC) "; + + if(!$arg_local_ffdc) + { + foreach my $collectRegisterFfdc (@{$err->{collectRegisterFfdc}}) + { + #------------------------------------------------------------------ + # Check that expected fields are present + #------------------------------------------------------------------ + if (! exists $collectRegisterFfdc->{id}[0]) + { + print ("parseErrorInfo.pl ERROR in $err->{rc}. id(s) missing from collectRegisterFfdc\n"); + exit(1); + } +=begin + foreach my $id (@{$collectRegisterFfdc->{id}}) + { + #--------------------------------------------------------------------------------- + # Check FFDC register collection type: target, child, or based on present children + #--------------------------------------------------------------------------------- + if (exists $collectRegisterFfdc->{target}) + { + print EIFILE "fapi2::collectRegFfdc($collectRegisterFfdc->{target}, "; + print EIFILE "fapi2::$id, RC); "; + addFfdcMethod(\%methods, $collectRegisterFfdc->{target}, + $err->{rc}, $target_ffdc_type); + } + elsif (exists $collectRegisterFfdc->{childTargets}) + { + if (! exists $collectRegisterFfdc->{childTargets}->{parent}) + { + print ("parseErrorInfo.pl ERROR: parent missing from collectRegisterFfdc\n"); + exit(1); + } + if (! exists $collectRegisterFfdc->{childTargets}->{childType}) + { + print ("parseErrorInfo.pl ERROR: childType missing from collectRegisterFfdc\n"); + exit(1); + } + print EIFILE "fapi2::collectRegFfdc{childTargets}->{childType}, fapi2::TARGET_TYPE_NONE>"; + print EIFILE "($collectRegisterFfdc->{childTargets}->{parent}, fapi2::$id, RC); "; + addFfdcMethod(\%methods, $collectRegisterFfdc->{childTargets}->{parent}, + $err->{rc}, $target_ffdc_type); + } + elsif (exists $collectRegisterFfdc->{basedOnPresentChildren}) + { + if (! exists $collectRegisterFfdc->{basedOnPresentChildren}->{target}) + { + print ("parseErrorInfo.pl ERROR: target missing from collectRegisterFfdc\n"); + exit(1); + } + if (! exists $collectRegisterFfdc->{basedOnPresentChildren}->{childType}) + { + print ("parseErrorInfo.pl ERROR: childType missing from collectRegisterFfdc\n"); + exit(1); + } + if (! exists $collectRegisterFfdc->{basedOnPresentChildren}->{childPosOffsetMultiplier}) + { + print ("parseErrorInfo.pl ERROR: childPosOffsetMultiplier missing from collectRegisterFfdc\n"); + exit(1); + } + print EIFILE "fapi2::collectRegFfdc{basedOnPresentChildren}->{childType}, fapi2::TARGET_TYPE_NONE>"; + print EIFILE "($collectRegisterFfdc->{basedOnPresentChildren}->{target}, fapi2::$id, RC, "; + print EIFILE "$collectRegisterFfdc->{basedOnPresentChildren}->{childPosOffsetMultiplier}); "; + addFfdcMethod(\%methods, $collectRegisterFfdc->{basedOnPresentChildren}->{target}, + $err->{rc}, $target_ffdc_type); + } + else + { + print ("parseErrorInfo.pl ERROR: Invalid collectRegisterFfdc configuration\n"); + exit(1); + } + } +=cut + } + + } + print EIFILE "\n"; + + #---------------------------------------------------------------------- + # Print the ADD_ERROR_INFO macro to hwp_error_info.H + #---------------------------------------------------------------------- + print EIFILE "#define $err->{rc}_ADD_ERROR_INFO(RC) "; + + # Array of EI Objects + my @eiObjects; + + my $eiEntryStr = ""; + my $eiObjectMap = ""; #object names to buffer address mapping + my $eiObjectStr = "const void * l_objects[] = {"; + my $executeStr = ""; + my $eiEntryCount = 0; + my %cdgTargetHash; # Records the callout/deconfigure/gards for Targets + my %cdgChildHash; # Records the callout/deconfigure/gards for Children + + # collect firmware trace + foreach my $collectTrace (@{$err->{collectTrace}}) + { + # Add an EI entry to eiEntryStr + $eiEntryStr .= " l_entries[$eiEntryCount].iv_type = fapi2::EI_TYPE_COLLECT_TRACE; \\\n"; + $eiEntryStr .= " l_entries[$eiEntryCount].collect_trace.iv_eieTraceId = fapi2::CollectTraces::$collectTrace; \\\n"; + $eiEntryCount++; + } + # Local FFDC + foreach my $ffdc (@{$err->{ffdc}}) + { + + # Set the FFDC ID value in a global hash. The name is _ + my $ffdcName = $err->{rc} . "_"; + $ffdcName = $ffdcName . $ffdc; + setFfdcIdValue($ffdcName); + + # Add the FFDC data to the EI Object array if it doesn't already exist + my $objNum = addEntryToArray(\@eiObjects, $ffdc); + + # Add a method to the ffdc-gathering class + addFfdcMethod(\%methods, $ffdc, $err->{rc},$ffdc_type,$objNum); + + $ffdc = $mangle_names{$ffdc} if ($mangle_names{$ffdc} ne undef); + + # Add an EI entry to eiEntryStr + $eiEntryStr .= " l_entries[$eiEntryCount].iv_type = fapi2::EI_TYPE_FFDC; \\\n"; + $eiEntryStr .= " l_entries[$eiEntryCount].ffdc.iv_ffdcObjIndex = $objNum; \\\n"; + $eiEntryStr .= " l_entries[$eiEntryCount].ffdc.iv_ffdcId = fapi2::$ffdcName; \\\n"; + $eiEntryStr .= " l_entries[$eiEntryCount].ffdc.iv_ffdcSize = $ffdc.size(); \\\n"; + $eiEntryCount++; + } + + # Multicast ID + foreach my $mcast (@{$err->{mcastId}}) + { + # Set the FFDC ID value in a global hash. The name is _ + my $ffdcName = $err->{rc} . "_"; + $ffdcName = $ffdcName . $mcast; + setFfdcIdValue($ffdcName); + + # Add the FFDC data to the EI Object array if it doesn't already exist + my $objNum = addEntryToArray(\@eiObjects, $mcast); + + # Add a method to the ffdc-gathering class + addFfdcMethod(\%methods, $mcast, $err->{rc},$mcast_type,$objNum); + + $mcast = $mangle_names{$mcast} if ($mangle_names{$mcast} ne undef); + + # Add an EI entry to eiEntryStr + $eiEntryStr .= " l_entries[$eiEntryCount].iv_type = fapi2::EI_TYPE_FFDC; \\\n"; + $eiEntryStr .= " l_entries[$eiEntryCount].ffdc.iv_ffdcObjIndex = $objNum; \\\n"; + $eiEntryStr .= " l_entries[$eiEntryCount].ffdc.iv_ffdcId = fapi2::$ffdcName; \\\n"; + $eiEntryStr .= " l_entries[$eiEntryCount].ffdc.iv_ffdcSize = 4; \\\n"; + $eiEntryCount++; + } + + if(!$arg_local_ffdc) + { + # Buffers, looks a lot like local ffdc + foreach my $buffer (@{$err->{buffer}}) + { + # Set the FFDC ID value in a global hash. The name is _ + my $bufferName = $err->{rc} . "_"; + $bufferName = $bufferName . $buffer; + setFfdcIdValue($bufferName); + + # Add the FFDC data to the EI Object array if it doesn't already exist + my $objNum = addEntryToArray(\@eiObjects, $buffer); + + # Add a method to the ffdc-gathering class - one for each buffer type + addFfdcMethod(\%methods, $buffer, $err->{rc}, $buffer_ffdc_type); + addFfdcMethod(\%methods, $buffer, $err->{rc}, $variable_buffer_ffdc_type); + + # Add an EI entry to eiEntryStr + $eiEntryStr .= " l_entries[$eiEntryCount].iv_type = fapi2::EI_TYPE_FFDC; \\\n"; + $eiEntryStr .= " l_entries[$eiEntryCount].ffdc.iv_ffdcObjIndex = $objNum; \\\n"; + $eiEntryStr .= " l_entries[$eiEntryCount].ffdc.iv_ffdcId = fapi2::$bufferName; \\\n"; + $eiEntryStr .= " l_entries[$eiEntryCount].ffdc.iv_ffdcSize = fapi2::getErrorInfoFfdcSize($buffer); \\\n"; + $eiEntryCount++; + } + + # Procedure/Target/Bus/Child callouts + foreach my $callout (@{$err->{callout}}) + { + if (! exists $callout->{priority}) + { + print ("parseErrorInfo.pl ERROR in $err->{rc}. Callout priority missing\n"); + exit(1); + } + + my $elementsFound = 0; + if (exists $callout->{hw}) + { + # HW Callout + if (! exists $callout->{hw}->{hwid}) + { + print ("parseErrorInfo.pl ERROR in $err->{rc}. HW Callout hwid missing\n"); + exit(1); + } + + # Check that those HW callouts that need reference targets have them + if (($callout->{hw}->{hwid} eq "TOD_CLOCK") || + ($callout->{hw}->{hwid} eq "MEM_REF_CLOCK") || + ($callout->{hw}->{hwid} eq "PROC_REF_CLOCK") || + ($callout->{hw}->{hwid} eq "PCI_REF_CLOCK")) + { + if (! exists $callout->{hw}->{refTarget}) + { + print ("parseErrorInfo.pl ERROR in $err->{rc}. Callout missing refTarget\n"); + exit(1); + } + } + + # Add an EI entry to eiEntryStr + $eiEntryStr .= " l_entries[$eiEntryCount].iv_type = fapi2::EI_TYPE_HW_CALLOUT; \\\n"; + $eiEntryStr .= " l_entries[$eiEntryCount].hw_callout.iv_hw = fapi2::HwCallouts::$callout->{hw}->{hwid}; \\\n"; + $eiEntryStr .= " l_entries[$eiEntryCount].hw_callout.iv_calloutPriority = fapi2::CalloutPriorities::$callout->{priority}; \\\n"; + if (exists $callout->{hw}->{refTarget}) + { + # Add the Targets to the objectlist if they don't already exist + my $objNum = addEntryToArray(\@eiObjects, $callout->{hw}->{refTarget}); + $eiEntryStr .= " l_entries[$eiEntryCount].hw_callout.iv_refObjIndex = $objNum; \\\n"; + + # Add a method to the ffdc-gathering class + addFfdcMethod(\%methods, $callout->{hw}->{refTarget}, $err->{rc}); + } + else + { + $eiEntryStr .= " l_entries[$eiEntryCount].hw_callout.iv_refObjIndex = 0xff; \\\n"; + } + $eiEntryCount++; + $elementsFound++; + } + if (exists $callout->{procedure}) + { + # Procedure Callout + # Add an EI entry to eiEntryStr + $eiEntryStr .= " l_entries[$eiEntryCount].iv_type = fapi2::EI_TYPE_PROCEDURE_CALLOUT; \\\n"; + $eiEntryStr .= " l_entries[$eiEntryCount].proc_callout.iv_procedure = fapi2::ProcedureCallouts::$callout->{procedure}; \\\n"; + $eiEntryStr .= " l_entries[$eiEntryCount].proc_callout.iv_calloutPriority = fapi2::CalloutPriorities::$callout->{priority}; \\\n"; + $eiEntryCount++; + $elementsFound++; + } + if (exists $callout->{bus}) + { + # A Bus Callout consists of two targets separated by + # commas/spaces + my @targets = split(/\s*,\s*|\s+/, $callout->{bus}); + + if (scalar @targets != 2) + { + print ("parseErrorInfo.pl ERROR in $err->{rc}. did not find two targets in bus callout\n"); + exit(1); + } + + # Add the Targets to the objectlist if they don't already exist + my $objNum1 = addEntryToArray(\@eiObjects, $targets[0]); + + my $objNum2 = addEntryToArray(\@eiObjects, $targets[1]); + + # Add a method to the ffdc-gathering class + addFfdcMethod(\%methods, $targets[0], $err->{rc}, $target_ffdc_type); + addFfdcMethod(\%methods, $targets[1], $err->{rc}, $target_ffdc_type); + + # Add an EI entry to eiEntryStr + $eiEntryStr .= " l_entries[$eiEntryCount].iv_type = fapi2::EI_TYPE_BUS_CALLOUT; \\\n"; + $eiEntryStr .= " l_entries[$eiEntryCount].bus_callout.iv_endpoint1ObjIndex = $objNum1; \\\n"; + $eiEntryStr .= " l_entries[$eiEntryCount].bus_callout.iv_endpoint2ObjIndex = $objNum2; \\\n"; + $eiEntryStr .= " l_entries[$eiEntryCount].bus_callout.iv_calloutPriority = fapi2::CalloutPriorities::$callout->{priority}; \\\n"; + $eiEntryCount++; + $elementsFound++; + } + if (exists $callout->{target}) + { + # Add the Target to cdgTargetHash to be processed with any + # deconfigure and GARD requests + $cdgTargetHash{$callout->{target}}{callout} = 1; + $cdgTargetHash{$callout->{target}}{priority} = + $callout->{priority}; + + $elementsFound++; + } + if (exists $callout->{childTargets}) + { + # Check that the parent and childType subelements exist + if (! exists $callout->{childTargets}->{parent}) + { + print ("parseErrorInfo.pl ERROR in $err->{rc}. Child Callout parent missing\n"); + exit(1); + } + + if (! exists $callout->{childTargets}->{childType}) + { + print ("parseErrorInfo.pl ERROR in $err->{rc}. Child Callout childType missing\n"); + exit(1); + } + + # Add the child info to cdgChildHash to be processed with + # any deconfigure and GARD requests + my $parent = $callout->{childTargets}->{parent}; + my $childType = $callout->{childTargets}->{childType}; + $cdgChildHash{$parent}{$childType}{callout} = 1; + $cdgChildHash{$parent}{$childType}{priority} = + $callout->{priority}; + + $elementsFound++; + + if (exists $callout->{childTargets}->{childPort}) + { + my $childPort = $callout->{childTargets}->{childPort}; + + $cdgChildHash{$parent}{$childType}{childPort} = $childPort; + } + + if (exists $callout->{childTargets}->{childNumber}) + { + my $childNum = $callout->{childTargets}->{childNumber}; + $cdgChildHash{$parent}{$childType}{childNumber} = $childNum; + } + + } + if ($elementsFound == 0) + { + print ("parseErrorInfo.pl ERROR in $err->{rc}. Callout incomplete\n"); + exit(1); + } + elsif ($elementsFound > 1) + { + print ("parseErrorInfo.pl ERROR in $err->{rc}. Callout has multiple elements\n"); + exit(1); + } + } # callout + + # Target/Child deconfigures + foreach my $deconfigure (@{$err->{deconfigure}}) + { + my $elementsFound = 0; + if (exists $deconfigure->{target}) + { + # Add the Target to cdgTargetHash to be processed with any + # callout and GARD requests + $cdgTargetHash{$deconfigure->{target}}{deconf} = 1; + $elementsFound++; + } + if (exists $deconfigure->{childTargets}) + { + # Check that the parent and childType subelements exist + if (! exists $deconfigure->{childTargets}->{parent}) + { + print ("parseErrorInfo.pl ERROR in $err->{rc}. Child Deconfigure parent missing\n"); + exit(1); + } + if (! exists $deconfigure->{childTargets}->{childType}) + { + print ("parseErrorInfo.pl ERROR in $err->{rc}. Child Deconfigure childType missing\n"); + exit(1); + } + + # Add the child info to cdgChildHash to be processed with + # any callout and GARD requests + my $parent = $deconfigure->{childTargets}->{parent}; + my $childType = $deconfigure->{childTargets}->{childType}; + $cdgChildHash{$parent}{$childType}{deconf} = 1; + + $elementsFound++; + + if ( exists $deconfigure->{childTargets}->{childPort}) + { + my $childPort = $deconfigure->{childTargets}->{childPort}; + + $cdgChildHash{$parent}{$childType}{childPort} = $childPort; + } + + if ( exists $deconfigure->{childTargets}->{childNumber}) + { + my $childNum = $deconfigure->{childTargets}->{childNumber}; + $cdgChildHash{$parent}{$childType}{childNumber} = $childNum; + + } + } + if ($elementsFound == 0) + { + print ("parseErrorInfo.pl ERROR in $err->{rc}. Deconfigure incomplete\n"); + exit(1); + } + elsif ($elementsFound > 1) + { + print ("parseErrorInfo.pl ERROR in $err->{rc}. Deconfigure has multiple elements\n"); + exit(1); + } + } # deconfigure + + # Target/Child Gards + foreach my $gard (@{$err->{gard}}) + { + my $elementsFound = 0; + if (exists $gard->{target}) + { + # Add the Target to cdgTargetHash to be processed with any + # callout and deconfigure requests + $cdgTargetHash{$gard->{target}}{gard} = 1; + $elementsFound++; + } + if (exists $gard->{childTargets}) + { + # Check that the parent and childType subelements exist + if (! exists $gard->{childTargets}->{parent}) + { + print ("parseErrorInfo.pl ERROR in $err->{rc}. Child GARD parent missing\n"); + exit(1); + } + if (! exists $gard->{childTargets}->{childType}) + { + print ("parseErrorInfo.pl ERROR in $err->{rc}. Child GARD childType missing\n"); + exit(1); + } + + # Add the child info to cdgChildHash to be processed with + # any callout and deconfigure requests + my $parent = $gard->{childTargets}->{parent}; + my $childType = $gard->{childTargets}->{childType}; + $cdgChildHash{$parent}{$childType}{gard} = 1; + + $elementsFound++; + + if ( exists $gard->{childTargets}->{childPort}) + { + my $childPort = $gard->{childTargets}->{childPort}; + + $cdgChildHash{$parent}{$childType}{childPort} = $childPort; + + } + + if ( exists $gard->{childTargets}->{childNumber}) + { + my $childNum = $gard->{childTargets}->{childNumber}; + $cdgChildHash{$parent}{$childType}{childNumber} = $childNum; + } + } + if ($elementsFound == 0) + { + print ("parseErrorInfo.pl ERROR in $err->{rc}. GARD incomplete\n"); + exit(1); + } + elsif ($elementsFound > 1) + { + print ("parseErrorInfo.pl ERROR in $err->{rc}. GARD has multiple elements\n"); + exit(1); + } + } # gard + + # Process the callout, deconfigures and GARDs for each Target + foreach my $cdg (keys %cdgTargetHash) + { + my $callout = 0; + my $priority = 'LOW'; + my $deconf = 0; + my $gard = 0; + + if (exists $cdgTargetHash{$cdg}->{callout}) + { + $callout = 1; + } + if (exists $cdgTargetHash{$cdg}->{priority}) + { + $priority = $cdgTargetHash{$cdg}->{priority}; + } + if (exists $cdgTargetHash{$cdg}->{deconf}) + { + $deconf = 1; + } + if (exists $cdgTargetHash{$cdg}->{gard}) + { + $gard = 1; + } + + # Add the Target to the objectlist if it doesn't already exist + my $objNum = addEntryToArray(\@eiObjects, $cdg); + + # Add a method to the ffdc-gathering class + addFfdcMethod(\%methods, $cdg, $err->{rc}, $target_ffdc_type); + + # Add an EI entry to eiEntryStr + $eiEntryStr .= " l_entries[$eiEntryCount].iv_type = fapi2::EI_TYPE_CDG; \\\n"; + $eiEntryStr .= " l_entries[$eiEntryCount].target_cdg.iv_targetObjIndex = $objNum; \\\n"; + $eiEntryStr .= " l_entries[$eiEntryCount].target_cdg.iv_callout = $callout; \\\n"; + $eiEntryStr .= " l_entries[$eiEntryCount].target_cdg.iv_deconfigure = $deconf; \\\n"; + $eiEntryStr .= " l_entries[$eiEntryCount].target_cdg.iv_gard = $gard; \\\n"; + $eiEntryStr .= " l_entries[$eiEntryCount].target_cdg.iv_calloutPriority = fapi2::CalloutPriorities::$priority; \\\n"; + $eiEntryCount++; + } + + # Process the callout, deconfigures and GARDs for Child Targets + foreach my $parent (keys %cdgChildHash) + { + foreach my $childType (keys %{$cdgChildHash{$parent}}) + { + my $callout = 0; + my $priority = 'LOW'; + my $deconf = 0; + my $gard = 0; + my $childPort = 0xFF; + my $childNumber = 0xFF; + + if (exists $cdgChildHash{$parent}{$childType}->{callout}) + { + $callout = 1; + } + if (exists $cdgChildHash{$parent}->{$childType}->{priority}) + { + $priority = + $cdgChildHash{$parent}->{$childType}->{priority}; + } + if (exists $cdgChildHash{$parent}->{$childType}->{deconf}) + { + $deconf = 1; + } + if (exists $cdgChildHash{$parent}->{$childType}->{childPort}) + { + $childPort = + $cdgChildHash{$parent}->{$childType}->{childPort} ; + addFfdcMethod(\%methods, $childPort, $err->{rc}); + } + if (exists $cdgChildHash{$parent}->{$childType}->{childNumber}) + { + $childNumber = + $cdgChildHash{$parent}->{$childType}->{childNumber} ; + addFfdcMethod(\%methods, $childNumber, $err->{rc}); + } + if (exists $cdgChildHash{$parent}->{$childType}->{gard}) + { + $gard = 1; + } + + + # Add the Target to the objectlist if it doesn't already exist + my $objNum = addEntryToArray(\@eiObjects, $parent); + addFfdcMethod(\%methods, $parent, $err->{rc}, $target_ffdc_type); + + # Add an EI entry to eiEntryStr + $eiEntryStr .= + " l_entries[$eiEntryCount].iv_type = fapi2::EI_TYPE_CHILDREN_CDG; \\\n"; + $eiEntryStr .= + " l_entries[$eiEntryCount].children_cdg.iv_parentObjIndex = $objNum; \\\n"; + $eiEntryStr .= + " l_entries[$eiEntryCount].children_cdg.iv_callout = $callout; \\\n"; + $eiEntryStr .= + " l_entries[$eiEntryCount].children_cdg.iv_deconfigure = $deconf; \\\n"; + $eiEntryStr .= + " l_entries[$eiEntryCount].children_cdg.iv_childType = fapi2::$childType; \\\n"; + $eiEntryStr .= + " l_entries[$eiEntryCount].children_cdg.iv_childPort = $childPort; \\\n"; + $eiEntryStr .= + " l_entries[$eiEntryCount].children_cdg.iv_childNumber = $childNumber; \\\n"; + $eiEntryStr .= + " l_entries[$eiEntryCount].children_cdg.iv_gard = $gard; \\\n"; + $eiEntryStr .= + " l_entries[$eiEntryCount].children_cdg.iv_calloutPriority = fapi2::CalloutPriorities::$priority; \\\n"; + $eiEntryCount++; + } + } + } + # Add all objects to $eiObjectStr + my $objCount = 0; + + foreach my $eiObject (@eiObjects) + { + if ($objCount > 0) + { + $eiObjectStr .= ", "; + } + + if ($mangle_names{$eiObject} eq undef) + { + $eiObjectStr .= "$eiObject"; + + if ((exists $err->{sbeError}) ) + { + $objectStr .= "\t\tfapi2::ffdc_t $eiObject = getFfdcData(FFDC_BUFFER[$objCount]); \\\n"; + } + } + else + { + $eiObjectStr .= $mangle_names{$eiObject}; + } + + $objCount++; + } + $eiObjectStr .= "};"; + + + # Print info to file + if ($eiEntryCount > 0) + { + print EIFILE "\\\n{ \\\n $eiObjectStr \\\n"; + print EIFILE " fapi2::ErrorInfoEntry l_entries[$eiEntryCount]; \\\n"; + print EIFILE "$eiEntryStr"; + print EIFILE " RC.addErrorInfo(l_objects, l_entries, $eiEntryCount); \\\n}"; + } + + print EIFILE "\n"; + + #---------------------------------------------------------------------- + # Print the return code class to hwp_error_info.H + #---------------------------------------------------------------------- + # Remove the repeated whitespace and newlines other characters from the description + $err->{description} =~ s/^\s+|\s+$|"//g; + $err->{description} =~ tr{\n}{ }; + $err->{description} =~ s/\h+/ /g; + + #---------------------------------------------------------------------- + # Print the return code class to hwp_error_info.H + #---------------------------------------------------------------------- + my $class_name = $err->{rc}; + # Remove everything upto and including the first _. This makes the ffdc class + # names different from the error code value enum names. + $class_name = (split (/_/, $class_name, 2))[1]; + + # Class declaration + print ECFILE "\nclass $class_name\n{\n public:\n"; + + # Constructor. This traces the description. If this is too much, we can + # remove it. + if ($arg_empty_ffdc eq undef) + { + if(!$arg_local_ffdc) + { + print ECFILE " $class_name(fapi2::errlSeverity_t i_sev = fapi2::FAPI2_ERRL_SEV_UNRECOVERABLE, fapi2::ReturnCode& i_rc = fapi2::current_err):\n"; + print ECFILE " iv_rc(i_rc),\n"; + print ECFILE " iv_sev(i_sev)\n"; + print ECFILE " { FAPI_ERR(\"$err->{description}\"); }\n"; + } + else + { + print ECFILE " $class_name()\n"; + print ECFILE " {\n\t\tfapi2::current_err = RC_$class_name;\n\t\tFAPI_ERR(\"$err->{description}\");\n"; + print ECFILE " \tfapi2::g_FfdcData.fapiRc = RC_$class_name;\n\t}\n\n"; + } + } + else + { + # Void expression keeps the compiler from complaining about the unused arguments. + # We want to set the i_rc to the RC if we're empty. This otherwise gets done in _setHwpError() + print ECFILE " $class_name(fapi2::errlSeverity_t i_sev = fapi2::FAPI2_ERRL_SEV_UNRECOVERABLE, fapi2::ReturnCode& i_rc = fapi2::current_err)\n"; + print ECFILE " {\n"; + print ECFILE " static_cast(i_sev);\n"; + print ECFILE " i_rc = $err->{rc};\n"; + print ECFILE " }\n\n"; + } + + my $method_count = 0; + # Methods + foreach my $key (keys %methods) + { + print ECFILE $methods{$key}{method}; + $method_count++; + } + if(!$arg_local_ffdc) + { + # add a method to adjust the severity if desired + print ECFILE " inline void setSev(const fapi2::errlSeverity_t i_sev)\n"; + if ($arg_empty_ffdc eq undef) + { + print ECFILE " { iv_sev = i_sev; };\n\n"; + } + else + { + print ECFILE " { static_cast(i_sev); };\n\n"; + } + + # add a method to read the severity if desired + print ECFILE " inline fapi2::errlSeverity_t getSev() const\n"; + if ($arg_empty_ffdc eq undef) + { + print ECFILE " { return iv_sev; };\n\n"; + } + else + { + print ECFILE " { return fapi2::FAPI2_ERRL_SEV_UNDEFINED; };\n\n"; + } + + } + + if( $arg_local_ffdc eq undef ) + { + # Stick the execute method at the end of the other methods. We allow + # passing in of the severity so that macros which call execute() can over-ride + # the default severity. + print ECFILE " void execute(fapi2::errlSeverity_t" . + " i_sev = fapi2::FAPI2_ERRL_SEV_UNDEFINED," . + "bool commit = false )\n"; + if ($arg_empty_ffdc eq undef ) + { + print ECFILE " {\n"; + print ECFILE " FAPI_SET_HWP_ERROR(iv_rc, $err->{rc});\n"; + print ECFILE " if( commit )\n"; + print ECFILE " {\n"; + print ECFILE " fapi2::logError(iv_rc, " . + "(i_sev == fapi2::FAPI2_ERRL_SEV_UNDEFINED)" . + " ? iv_sev : i_sev);\n"; + print ECFILE " }\n"; + print ECFILE " }\n"; + + } + else + { + print ECFILE " {\n"; + print ECFILE " static_cast(i_sev);\n"; + print ECFILE " static_cast(commit);\n"; + print ECFILE " }\n\n"; + } + + # Instance variables + if ($arg_empty_ffdc eq undef) + { + print ECFILE " public:\n "; + foreach my $key (keys %methods) + { + print ECFILE $methods{$key}{member}; + } + + print ECFILE "fapi2::ReturnCode& iv_rc;\n"; + print ECFILE " fapi2::errlSeverity_t iv_sev;\n"; + } + + } + else + { + print ECFILE " void execute()\n"; + print ECFILE " {\n"; + print ECFILE "$executeStr\n"; + print ECFILE " }\n"; + } + + print ECFILE "};\n\n"; + + #---------------------------------------------------------------------- + # If this is an SBE error, add it to set_sbe_error.H + #---------------------------------------------------------------------- + if (exists $err->{sbeError}) + { + print SBFILE "\tcase fapi2::$err->{rc}: \\\n"; + print SBFILE "\t{ \\\n$objectStr"; + print SBFILE "\t\tFAPI_SET_HWP_ERROR(RC, $err->{rc});\\\n"; + print SBFILE " break; \\\n\t} \\\n"; + } + + } + +=pos + # + #-------------------------------------------------------------------------- + # For each registerFfdc. + #-------------------------------------------------------------------------- + foreach my $registerFfdc (@{$errors->{registerFfdc}}) + { + #---------------------------------------------------------------------- + # Check that expected fields are present + #---------------------------------------------------------------------- + if (! exists $registerFfdc->{id}[0]) + { + print ("parseErrorInfo.pl ERROR. id missing from registerFfdc\n"); + exit(1); + } + + if (scalar @{$registerFfdc->{id}} > 1) + { + print ("parseErrorInfo.pl ERROR. multiple ids in registerFfdc\n"); + exit(1); + } + + #---------------------------------------------------------------------- + # Set the FFDC ID value in a global hash + #---------------------------------------------------------------------- + setFfdcIdValue($registerFfdc->{id}[0]); + + #---------------------------------------------------------------------- + # Generate code to capture the registers in collect_reg_ffdc.C + #---------------------------------------------------------------------- + print CRFILE " case $registerFfdc->{id}[0]:\n"; + +# TODO: RTC 132226 +=begin NEED_P9_REGISTERS + # Look for CFAM Register addresses + foreach my $cfamRegister (@{$registerFfdc->{cfamRegister}}) + { + print CRFILE " l_cfamAddresses.push_back($cfamRegister);\n"; + print CRFILE " l_ffdcSize += sizeof(l_cfamData);\n"; + } + + # Look for SCOM Register addresses + foreach my $scomRegister (@{$registerFfdc->{scomRegister}}) + { + print CRFILE " l_scomAddresses.push_back($scomRegister);\n"; + print CRFILE " l_ffdcSize += sizeof(l_scomData);\n"; + } +=cut NEED_P9_REGISTERS + +print CRFILE " break;\n"; + } +=cut +} + +#------------------------------------------------------------------------------ +# Print end of file information to collect_reg_ffdc.C +#------------------------------------------------------------------------------ +print CRFILE " default:\n"; +print CRFILE " FAPI_ERR(\"collect_reg_ffdc.C: Invalid FFDC ID 0x%x\", "; +print CRFILE "i_ffdcId);\n"; +print CRFILE " return;\n"; +print CRFILE " }\n\n"; + +# TODO: RTC 132226 +=begin NEED_P9_REGISTERS +print CRFILE " uint8_t * l_pBuf = NULL;\n"; +print CRFILE " uint8_t * l_pData = NULL;\n"; +print CRFILE " std::vector l_targets;\n"; +print CRFILE " uint32_t l_chipletPos32 = 0;\n"; + +#--------------------------------------------------------------------------------------------------------- +# Populate chiplet vectors (if required by register collection method) and adjust buffer sizes accordingly +#--------------------------------------------------------------------------------------------------------- +print CRFILE " if (C != TARGET_TYPE_NONE)\n"; +print CRFILE " {\n"; +print CRFILE " l_rc = fapiGetChildChiplets(i_target, i_child, l_targets, TARGET_STATE_FUNCTIONAL);\n"; +print CRFILE " if (l_rc)\n"; +print CRFILE " {\n"; +print CRFILE " FAPI_ERR(\"collect_reg_ffdc.C: Error: fapiGetChildChiplets: failed to get chiplets.\");\n"; +print CRFILE " return;\n"; +print CRFILE " }\n"; +print CRFILE " if (l_targets.empty())\n"; +print CRFILE " {\n"; +print CRFILE " FAPI_INF(\"collect_reg_ffdc.C: Error: No functional chiplets found. \");\n"; +print CRFILE " return;\n"; +print CRFILE " }\n"; +print CRFILE " l_ffdcSize += sizeof(l_chipletPos32);\n"; +print CRFILE " l_ffdcSize *= l_targets.size();\n"; +print CRFILE " l_pBuf = new uint8_t[l_ffdcSize];\n"; +print CRFILE " l_pData = l_pBuf;\n"; +print CRFILE " }\n"; +print CRFILE " else if (P != TARGET_TYPE_NONE)\n"; +print CRFILE " {\n"; +print CRFILE " l_rc = fapiGetChildChiplets(i_target, i_presChild, l_targets, TARGET_STATE_PRESENT);\n"; +print CRFILE " if (l_rc)\n"; +print CRFILE " {\n"; +print CRFILE " FAPI_ERR(\"collect_reg_ffdc.C: Error: fapiGetChildChiplets: failed to get chiplets.\");\n"; +print CRFILE " return;\n"; +print CRFILE " }\n"; +print CRFILE " if (l_targets.empty())\n"; +print CRFILE " {\n"; +print CRFILE " FAPI_INF(\"collect_reg_ffdc.C: Error: No functional chiplets found. \");\n"; +print CRFILE " return;\n"; +print CRFILE " }\n"; +print CRFILE " l_ffdcSize += sizeof(l_chipletPos32);\n"; +print CRFILE " l_ffdcSize *= l_targets.size();\n"; +print CRFILE " l_pBuf = new uint8_t[l_ffdcSize];\n"; +print CRFILE " l_pData = l_pBuf;\n"; +print CRFILE " }\n"; +print CRFILE " else\n"; +print CRFILE " {\n"; +print CRFILE " l_ffdcSize += sizeof(l_chipletPos32);\n"; +print CRFILE " l_pBuf = new uint8_t[l_ffdcSize];\n"; +print CRFILE " l_pData = l_pBuf;\n"; +print CRFILE " l_targets.push_back(i_target);\n"; +print CRFILE " }\n\n"; + +#--------------------------------------------------------------------------------------------------------- +# Obtain target position and insert as the first word in the buffer +#--------------------------------------------------------------------------------------------------------- +print CRFILE " bool l_targIsChiplet = i_target.isChiplet();\n\n"; +print CRFILE " for (std::vector::const_iterator targetIter = l_targets.begin();\n"; +print CRFILE " targetIter != l_targets.end(); ++targetIter)\n"; +print CRFILE " {\n"; +print CRFILE " if ((fapi2::TARGET_TYPE_NONE != i_child) ||\n"; +print CRFILE " (fapi2::TARGET_TYPE_NONE != i_presChild) ||\n"; +print CRFILE " (true == l_targIsChiplet))\n"; +print CRFILE " {\n"; +print CRFILE " uint8_t l_chipletPos = 0;\n"; +print CRFILE " l_rc = FAPI_ATTR_GET(ATTR_CHIP_UNIT_POS, &(*targetIter), l_chipletPos);\n"; +print CRFILE " if (l_rc)\n"; +print CRFILE " {\n"; +print CRFILE " FAPI_ERR(\"collect_reg_ffdc.C: Error getting chiplet position\");\n"; +print CRFILE " l_chipletPos = 0xFF;\n"; +print CRFILE " }\n"; + #------------------------------------------------------------------------- + # We print the target's position in the error log whether the target is a + # chip or chiplet, so we need to store the chiplet position in a uint32_t + # to have consitency in the buffer as ATTR_POS below returns a uint32_t + #------------------------------------------------------------------------- +print CRFILE " l_chipletPos32 = l_chipletPos;\n"; +print CRFILE " }\n"; +print CRFILE " else\n"; +print CRFILE " {\n"; +print CRFILE " l_rc = FAPI_ATTR_GET(ATTR_POS, &(*targetIter), l_chipletPos32);\n"; +print CRFILE " if (l_rc)\n"; +print CRFILE " {\n"; +print CRFILE " FAPI_ERR(\"collect_reg_ffdc.C: Error getting chip position\");\n"; +print CRFILE " l_chipletPos32 = 0xFFFFFFFF;\n"; +print CRFILE " }\n"; +print CRFILE " }\n"; +print CRFILE " *(reinterpret_cast(l_pData)) = l_chipletPos32;\n"; +print CRFILE " l_pData += sizeof(l_chipletPos32);\n"; +#--------------------------------------------------------------------------------------------------------- +# Instert cfam data (if any) related to this chip / chiplet into the buffer +# If collecting FFDC based on present children, adjust the register address by the appropriate offset +#--------------------------------------------------------------------------------------------------------- +print CRFILE " for (std::vector::const_iterator cfamIter = l_cfamAddresses.begin();\n"; +print CRFILE " cfamIter != l_cfamAddresses.end(); ++cfamIter)\n"; +print CRFILE " {\n"; +print CRFILE " if (fapi2::TARGET_TYPE_NONE != i_presChild)\n"; +print CRFILE " {\n"; +print CRFILE " l_rc = fapiGetCfamRegister(i_target, (*cfamIter + (l_chipletPos32 * i_childOffsetMult)), l_buf);\n"; +print CRFILE " }\n"; +print CRFILE " else\n"; +print CRFILE " {\n"; +print CRFILE " l_rc = fapiGetCfamRegister(*targetIter, *cfamIter, l_buf);\n"; +print CRFILE " }\n"; +print CRFILE " if (l_rc)\n"; +print CRFILE " {\n"; +print CRFILE " FAPI_ERR(\"collect_reg_ffdc.C: CFAM error for 0x%x\","; +print CRFILE "*cfamIter);\n"; +print CRFILE " l_cfamData = 0xbaddbadd;\n"; +print CRFILE " }\n"; +print CRFILE " else\n"; +print CRFILE " {\n"; +print CRFILE " l_cfamData = l_buf.getWord(0);\n"; +print CRFILE " }\n"; +print CRFILE " *(reinterpret_cast(l_pData)) = l_cfamData;\n"; +print CRFILE " l_pData += sizeof(l_cfamData);\n"; +print CRFILE " }\n\n"; +#--------------------------------------------------------------------------------------------------------- +# Instert any scom data (if any) related to this chip / chiplet into the buffer +# If collecting FFDC based on present children, adjust the register address by the appropriate offset +#--------------------------------------------------------------------------------------------------------- +print CRFILE " for (std::vector::const_iterator scomIter = l_scomAddresses.begin();\n"; +print CRFILE " scomIter != l_scomAddresses.end(); ++scomIter)\n"; +print CRFILE " {\n"; +print CRFILE " if (fapi2::TARGET_TYPE_NONE != i_presChild)\n"; +print CRFILE " {\n"; +print CRFILE " l_rc = fapiGetScom(i_target, (*scomIter + (l_chipletPos32 * i_childOffsetMult)), l_buf);\n"; +print CRFILE " }\n"; +print CRFILE " else\n"; +print CRFILE " {\n"; +print CRFILE " l_rc = fapiGetScom(*targetIter, *scomIter, l_buf);\n"; +print CRFILE " }\n"; +print CRFILE " if (l_rc)\n"; +print CRFILE " {\n"; +print CRFILE " FAPI_ERR(\"collect_reg_ffdc.C: SCOM error for 0x%llx\","; +print CRFILE "*scomIter);\n"; +print CRFILE " l_scomData = 0xbaddbaddbaddbaddULL;\n"; +print CRFILE " }\n"; +print CRFILE " else\n"; +print CRFILE " {\n"; +print CRFILE " l_scomData = l_buf.getDoubleWord(0);\n"; +print CRFILE " }\n"; +print CRFILE " *(reinterpret_cast(l_pData)) = l_scomData;\n"; +print CRFILE " l_pData += sizeof(l_scomData);\n"; +print CRFILE " }\n"; +print CRFILE " }\n\n"; +print CRFILE " o_rc.addEIFfdc(i_ffdcId, l_pBuf, l_ffdcSize);\n"; +print CRFILE " delete [] l_pBuf;\n"; + +=cut NEED_P9_REGISTERS + +print CRFILE "}\n"; +print CRFILE "}\n"; +print CRFILE "#endif\n"; + +#------------------------------------------------------------------------------ +# Print the fapiHwpReturnCodes.H file +#------------------------------------------------------------------------------ +print RCFILE "// fapiHwpReturnCodes.H\n"; +print RCFILE "// This file is generated by perl script parseErrorInfo.pl\n\n"; +print RCFILE "#ifndef FAPI2_HWPRETURNCODES_H_\n"; +print RCFILE "#define FAPI2_HWPRETURNCODES_H_\n\n"; +print RCFILE "#ifndef __ASSEMBLER__\n"; +print RCFILE "namespace fapi2\n"; +print RCFILE "{\n\n"; +print RCFILE "/**\n"; +print RCFILE " * \@brief Enumeration of HWP return codes\n"; +print RCFILE " *\/\n"; +print RCFILE "enum HwpReturnCode\n"; +print RCFILE "{\n"; +foreach my $key (keys %errNameToValueHash) +{ + print RCFILE " $key = 0x$errNameToValueHash{$key},\n"; +} +print RCFILE "};\n\n"; +print RCFILE "}\n\n"; +print RCFILE "#else\n"; +foreach my $key (keys %errNameToValueHash) +{ + print RCFILE " .set $key, 0x$errNameToValueHash{$key}\n"; +} +print RCFILE "#endif\n"; +print RCFILE "#endif\n"; + +#------------------------------------------------------------------------------ +# Print the HwpFfdcId enumeration to hwp_error_info.H +#------------------------------------------------------------------------------ +print EIFILE "namespace fapi2\n"; +print EIFILE "{\n\n"; +if($arg_local_ffdc) +{ + print EIFILE " extern SbeFfdcData_t g_FfdcData;\n"; +} +print EIFILE "/**\n"; +print EIFILE " * \@brief Enumeration of FFDC identifiers\n"; +print EIFILE " *\/\n"; +print EIFILE "enum HwpFfdcId\n"; +print EIFILE "{\n"; +foreach my $key (keys %ffdcNameToValueHash) +{ + print EIFILE " $key = 0x$ffdcNameToValueHash{$key},\n"; +} +print EIFILE "};\n\n"; +print EIFILE "}\n\n"; + +#------------------------------------------------------------------------------ +# Print end of file information to hwp_error_info.H +#------------------------------------------------------------------------------ +print EIFILE "\n\n#endif\n"; + +#------------------------------------------------------------------------------ +# Print end of file information to hwp_ffdc_classes.H +#------------------------------------------------------------------------------ +print ECFILE "\n};\n"; # close the namespace +print ECFILE "\n\n#endif\n"; + +#------------------------------------------------------------------------------ +# Print end of file information to set_sbe_error.H +#------------------------------------------------------------------------------ +print SBFILE " default:\\\n"; +#print SBFILE " FAPI_SET_HWP_ERROR(RC, RC_SBE_UNKNOWN_ERROR,0);\\\n"; +print SBFILE " break;\\\n"; +print SBFILE "}\\\n"; +print SBFILE "}\n\n"; +print SBFILE "#endif\n"; + +#------------------------------------------------------------------------------ +# Close output files +#------------------------------------------------------------------------------ +close(RCFILE); +close(EIFILE); +close(ECFILE); +close(CRFILE); +close(SBFILE); diff --git a/src/tools/scripts/ppeCreateAttrGetSetMacros.pl b/src/tools/scripts/ppeCreateAttrGetSetMacros.pl new file mode 100755 index 00000000..72ae2aa8 --- /dev/null +++ b/src/tools/scripts/ppeCreateAttrGetSetMacros.pl @@ -0,0 +1,571 @@ +#!/usr/bin/perl -w +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/tools/scripts/ppeCreateAttrGetSetMacros.pl $ +# +# OpenPOWER sbe Project +# +# Contributors Listed Below - COPYRIGHT 2015,2016 +# +# +# 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 +#find enums in AttributeId +#for each enum check for ${enum}_Type +#check for type and array values +#Check Plat file for ${enum}_GETMACRO and ${enum}_SETMACRO +#If they do not exist add apporpriate _SETMACRO and _GETMACRO to Plat file + +use strict; +use File::Copy; +use Getopt::Long; + +sub enumParser ($); +sub help; + +my $DEBUG = 0; +my $VERBOSE = 0; + +my $state = 0; +my $last_value = -1; +my $current_entry; +my $current_enum_name; + +my %enums; + +my %attributeTypes; +my %attributeArrayTypes; + +my %getMacros; +my %setMacros; +my %targetMacros; + + + +my $fapiAttributeIdsFile = "fapi2AttributeIds.H"; +my $fapiPlatAttributeServiceFile= "fapi2PlatAttributeService.H"; + + +my $includePath = "./"; +my $srcPath = "./"; + +my @newAttributeDefines; +my @newTargetDefines; +my @newTargetImplementations; + + +my $servicePath; +my $help; + +GetOptions ("verbose" => \$VERBOSE, + "help" => \$help, + "debug" => \$DEBUG, + "path=s" => \$servicePath, + "inc=s" => \$includePath, + "src=s" => \$srcPath, +); + +help() if $help; + +open (FILE, $includePath . "/" . $fapiAttributeIdsFile) or die "ERROR:: could not open $fapiAttributeIdsFile\n"; + +while () { + # attempt to parse attributes from current line in file + enumParser($_); + + # see if the line describes an attribute + if (m/\s*typedef\s+(\w+)\s+(\w+)_Type(\S*)\s*;/) { + my $type = $1; + my $attribute = $2; + my $arrayType = $3; + + if ($DEBUG) { print "DEBUG:: type = $type : attribute = $attribute : arrayType = $arrayType\n"; } + + # save attribute type and if it is an array and its size + $attributeTypes{$attribute} = $type; + if ($arrayType) { + $attributeArrayTypes{$attribute} = $arrayType; + } else { + $attributeArrayTypes{$attribute} = "none"; + } + } + + # look for MACROs + # look for: #define ATTR_CHIP_HAS_SBE_GETMACRO ATTRIBUTE_NOT_WRITABLE + if (m/\s*#define\s+(\w+)_GETMACRO\s+(\S+)\s*/) { + $getMacros{$1} = $2; + if ($DEBUG) { print "DEBUG:: attribute = $1 : GETMACRO = $2\n"; } + # look for: #define ATTR_CHIP_EC_FEATURE_TEST1_GETMACRO(ID, PTARGET, VAL) fapi::fapiQueryChipEcFeature(ID, PTARGET, VAL) + } elsif (m/\s*#define\s+(\w+)_GETMACRO\(ID\,\sPTARGET\,\sVAL\)\s(.+)/) { + $getMacros{$1} = $2; + if ($DEBUG) { print "DEBUG:: attribute = $1 : GETMACRO = $2\n"; } + # look for: #define ATTR_CHIP_HAS_SBE_SETMACRO ATTRIBUTE_NOT_WRITABLE + } elsif (m/\s*#define\s+(\w+)_SETMACRO\s+(\S+)\s*/) { + $setMacros{$1} = $2; + if ($DEBUG) { print "DEBUG:: attribute = $1 : SETMACRO = $2\n"; } + # look for: #define ATTR_CHIP_EC_FEATURE_TEST2_SETMACRO(ID, PTARGET, VAL) CHIP_EC_FEATURE_ATTRIBUTE_NOT_WRITABLE + } elsif (m/\s*#define\s+(\w+)_SETMACRO\(ID\,\sPTARGET\,\sVAL\)\s(.+)/) { + $setMacros{$1} = $2; + if ($DEBUG) { print "DEBUG:: attribute = $1 : SETMACRO = $2\n"; } + } elsif (m/\s*const\s*TargetType\s+(\w+)_TargetTypes\s*=\s*(\S+)\s*;\s*/) { + $targetMacros{$1} = $2; +# print "DEBUG:: attribute = $1 : TARGET = $2\n"; + if ($DEBUG) { print "DEBUG:: attribute = $1 : TARGET = $2\n"; } + } +} + +close (FILE); + +#find copy of fapiPlatAttributeService.H +if (!$servicePath) { + #$CTEPATH/tools/ecmd/$ECMD_RELEASE/ext/fapi/capi + my $ctepath = $ENV{CTEPATH}; + my $ecmd_release = $ENV{ECMD_RELEASE}; + if ($DEBUG) { print "DEBUG:: ctepath = $ctepath\n"; } + if ($DEBUG) { print "DEBUG:: ecmd_release = $ecmd_release\n"; } + if (!$ctepath) { + print "ERROR:: environment variable CTEPATH not defined!\n"; + exit 1; + } + if (!$ecmd_release) { + print "ERROR:: environment variable ECMD_RELEASE not defined!\n"; + exit 1; + } + $servicePath = "$ctepath/tools/ecmd/$ecmd_release/ext/fapi/capi"; +} + +if ($DEBUG) { print "DEBUG:: servicePath = $servicePath\n"; } + +# test that servicePath exists +if (!-d $servicePath) { + print "ERROR:: path $servicePath does not exist!\n"; + exit 1; +} + +# test that fapiPlatAttributeService.H is in that directory +if (!-f "$servicePath/$fapiPlatAttributeServiceFile") { + print "ERROR:: $fapiPlatAttributeServiceFile does not exist in $servicePath\n"; + exit 1; +} + +# copy fapiPlatAttributeService.H to local dir +#my $systemRc = system("cp $servicePath/$fapiPlatAttributeServiceFile $includePath"); +copy("$servicePath/$fapiPlatAttributeServiceFile","$includePath") or die "Copy failed: $!"; + +#if ($systemRc) { +# print "ERROR:: error copying $fapiPlatAttributeServiceFile from $servicePath\n"; +# exit 1; +#} + + + +# look in fapiPlatAttributeService.H for MACROs +open (FILE, $includePath . "/". $fapiPlatAttributeServiceFile) or die "ERROR:: could not open $fapiPlatAttributeServiceFile\n"; +while () { + if (m/\s*#define\s+(\w+)_GETMACRO\s+(\S+)\s*/) { + $getMacros{$1} = $2; + if ($DEBUG) { print "DEBUG:: attribute = $1 : GETMACRO = $2\n"; } + } elsif (m/\s*#define\s+(\w+)_SETMACRO\s+(\S+)\s*/) { + $setMacros{$1} = $2; + if ($DEBUG) { print "DEBUG:: attribute = $1 : SETMACRO = $2\n"; } + } elsif (m/\s*const\s*TargetType\s+(\w+)_TargetTypes\s*=\s*(\S+)\s*;\s*/) { + $targetMacros{$1} = $2; + if ($DEBUG) { print "DEBUG:: attribute = $1 : TARGET = $2\n"; } + } +} +close (FILE); + +# go through attributes found in file +for my $attribute (sort keys %{$enums{AttributeId}}) { + if ($DEBUG) { print "DEBUG:: attribute = $attribute\n"; } + my $type; + my $arrayType; + my $dimension = 0; + + # check that each attribute has attributeType + if ($attributeTypes{$attribute}) { + if ($attributeArrayTypes{$attribute}) { + $type = $attributeTypes{$attribute}; + $arrayType = $attributeArrayTypes{$attribute}; + } else { + print "ERROR:: arrayType not found for $attribute\n"; + next; + } + } else { + print "ERROR:: type not found for $attribute\n"; + next; + } + + # determine if attribute is an array + if ($arrayType =~ m/none/) { + if ($DEBUG) { print "DEBUG:: $attribute = $type\n"; } + } else { + # find dimension for array + my $tempArrayType = $arrayType; + while ($tempArrayType =~ m/\[\d*\].*/) { + $dimension++; + $tempArrayType =~ s/\[\d*\]//; + } + if ($DEBUG) { print "DEBUG:: $attribute = $type$arrayType dimension = $dimension\n"; } + } + + my $setMacro = $setMacros{$attribute}; + my $getMacro = $getMacros{$attribute}; + my $targetMacro = $targetMacros{$attribute}; + +# print "$attribute $setMacro $getMacro $targetMacro \n"; + + # if an attribute is missing the SET or GET MACRO add to list in insert into file later + if (!($getMacro && $setMacro)) { + my $macroPrefix = "PLAT_ATTR_"; + my $macroPostfix = ""; + + if ($dimension == 0) { + $macroPostfix = "_GLOBAL_INT"; + } else { + if ($type =~ m/uint8_t/) { + $macroPostfix = "_UINT8_" . $dimension . "D_ARRAY"; + } elsif ($type =~ m/uint16_t/) { + $macroPostfix = "_UINT16_" . $dimension . "D_ARRAY"; + } elsif ($type =~ m/uint32_t/) { + $macroPostfix = "_UINT32_" . $dimension . "D_ARRAY"; + } elsif ($type =~ m/uint64_t/) { + $macroPostfix = "_UINT64_" . $dimension . "D_ARRAY"; + } elsif ($type =~ m/int8_t/) { + $macroPostfix = "_INT8_" . $dimension . "D_ARRAY"; + } elsif ($type =~ m/int16_t/) { + $macroPostfix = "_INT16_" . $dimension . "D_ARRAY"; + } elsif ($type =~ m/int32_t/) { + $macroPostfix = "_INT32_" . $dimension . "D_ARRAY"; + } elsif ($type =~ m/int64_t/) { + $macroPostfix = "_INT64_" . $dimension . "D_ARRAY"; + } else { + print "ERROR:: unknown type $type for attribute $attribute\n"; + next; + } + } + + my $macroTarget = ""; + if(defined $targetMacro) { + if($targetMacro eq "TARGET_TYPE_SYSTEM") { + $macroTarget = "SystemAttributes_t"; + } elsif ($targetMacro eq "TARGET_TYPE_PROC_CHIP") { + $macroTarget = "ProcChipAttributes_t"; + } elsif ($targetMacro eq "TARGET_TYPE_CORE") { + $macroTarget = "CoreAttributes_t"; + } elsif ($targetMacro eq "TARGET_TYPE_EX") { + $macroTarget = "EXAttributes_t"; + } elsif ($targetMacro eq "TARGET_TYPE_EQ") { + $macroTarget = "EQAttributes_t"; + } elsif ($targetMacro eq "TARGET_TYPE_PERV") { + $macroTarget = "PervAttributes_t"; + } else { + print "ERROR:: unknown type $targetMacro for attribute $attribute\n"; + next; + } + } + + if (!$getMacro) { + if ($VERBOSE) { print "INFO:: did not find ${attribute}_GETMACRO\n"; } + my $attributeDefine = "#define ${attribute}_GETMACRO ${macroPrefix}GET${macroPostfix}"; + push(@newAttributeDefines, $attributeDefine); + + if(defined $targetMacro) { + + + my $targetFunction = "template<> inline void __get ( const fapi2::Target& i_ptarget, const fapi2attr::$macroTarget* object, const fapi2::AttributeId attrid, $type* o_pvalue )"; + push(@newTargetDefines, $targetFunction . ";"); + + my $targetImplementation = ""; + if($targetMacro eq "TARGET_TYPE_PROC_CHIP" | $targetMacro eq "TARGET_TYPE_SYSTEM") { + + $targetImplementation .= "\n" . $targetFunction . "\n{\n *o_pvalue = object->fapi2attr::${macroTarget}::${attribute};\n}\n"; + + } elsif($targetMacro eq "TARGET_TYPE_PERV") { + + $targetImplementation .= "\n" . $targetFunction . +"\n{ + *o_pvalue = object->fapi2attr::${macroTarget}::${attribute}[getPervAttrIndex(i_ptarget)]; +}\n"; + + } else { +$targetImplementation .= "\n" . $targetFunction . "\n{\n uint32_t index = i_ptarget.getTargetNumber();\n *o_pvalue = object->fapi2attr::${macroTarget}::${attribute}[index];\n}\n" + } + push(@newTargetImplementations, $targetImplementation); + } + } + if (!$setMacro) { + if ($VERBOSE) { print "INFO:: did not find ${attribute}_SETMACRO\n"; } + my $attributeDefine = "#define ${attribute}_SETMACRO ${macroPrefix}SET${macroPostfix}"; + push(@newAttributeDefines, $attributeDefine); + + if(defined $targetMacro) { + + my $targetFunction = "template<> inline void __set ( const fapi2::Target& i_ptarget, fapi2attr::$macroTarget* object, const fapi2::AttributeId attrid, const $type& i_pvalue )"; + push(@newTargetDefines, $targetFunction . ";"); + + my $targetImplementation = ""; + + if($targetMacro eq "TARGET_TYPE_PROC_CHIP" | $targetMacro eq "TARGET_TYPE_SYSTEM") { + + $targetImplementation = "\n" . $targetFunction . "\n{\n object->fapi2attr::${macroTarget}::${attribute} = i_pvalue;\n}\n"; + } else { + $targetImplementation = "\n" . $targetFunction . "\n{\n uint32_t index = i_ptarget.getTargetNumber();\n object->fapi2attr::${macroTarget}::${attribute}[index] = i_pvalue;\n}\n"; + } + + push(@newTargetImplementations, $targetImplementation); + } + } + } +} + +# if file is missing any GET or SET MACROs +if (@newAttributeDefines != 0) { + + my $updatedFapiPlatAttributeServiceFile = "$fapiPlatAttributeServiceFile.temp"; + open (OUTFILE, ">$updatedFapiPlatAttributeServiceFile") or die "ERROR:: could not open $updatedFapiPlatAttributeServiceFile\n"; + open (FILE, $includePath . "/" . $fapiPlatAttributeServiceFile) or die "ERROR:: could not open $fapiPlatAttributeServiceFile\n"; + + my $insertTagFound = 0; + + while () { + print OUTFILE $_; + # search for tag to insert after + if (m/\/\*.*INSERT NEW ATTRIBUTES HERE.*\*\//) { + $insertTagFound = 1; + # insert missing GET or SET MACROs + print OUTFILE "\n"; + foreach my $attributeDefine (@newAttributeDefines) { + print OUTFILE "$attributeDefine\n"; + if ($VERBOSE) { print "INFO:: adding $attributeDefine\n"; } + } + } + + if (m/\/\*.*INSERT NEW GETTER AND SETTER FUNCTIONS HERE.*\*\//) { + + $insertTagFound = 1; + # insert missing GET or SET MACROs + print OUTFILE "\n"; + foreach my $targetDefine (@newTargetDefines) { + print OUTFILE "$targetDefine\n"; + if ($VERBOSE) { print "INFO:: adding getter setter method\n"; } + } + print OUTFILE " + __attribute__((always_inline)) inline uint32_t getPervAttrIndex(const fapi2::Target &i_target) + { + uint32_t l_index = i_target.getTargetNumber(); + if(PPE_TARGET_TYPE_EQ & i_target.getTargetType()) + { + l_index += (EQ_TARGET_OFFSET); + } + else if(PPE_TARGET_TYPE_CORE & i_target.getTargetType()) + { + l_index += (CORE_TARGET_OFFSET); + } + else if(PPE_TARGET_TYPE_MCBIST & i_target.getTargetType()) + { + l_index += (MCBIST_TARGET_OFFSET); + } + else + { + l_index += (NEST_GROUP1_TARGET_OFFSET); + } + return (l_index - NEST_GROUP1_TARGET_OFFSET); + } + "; + + + foreach my $impl (@newTargetImplementations) { + + print OUTFILE $impl; + + } + } + + + } + close (FILE); + close (OUTFILE); + + if ($insertTagFound == 0) { + # remove file that we did not update + system("rm $updatedFapiPlatAttributeServiceFile"); + print ("WARNING:: did not find tag \"INSERT NEW ATTRIBUTES HERE\" in $fapiPlatAttributeServiceFile. no updates performed.\n"); + } else { + # copy new file over the old one + system("mv $updatedFapiPlatAttributeServiceFile $includePath/$fapiPlatAttributeServiceFile"); + } +} + + + + +exit; + +# enumParser state machine +# "enum" "enum_name" "{" "entry" "}" +# [0] ------> [1] -------------> [2] ---> [3] -----------> [4] -------------------------------------> [7] +# "," "=" "value" "}" +# [3] <----------- [4] ----> [5] --------> [6] -------------> [7] +# "}" ";" +# [3] -----------------------------------------------------> [7] ---> [0] +# "," +# +# [3] <----------------------------------- [6] +# + +sub enumParser ($){ + my $line = $_[0]; + chomp($line); + + if ($DEBUG) { print "DEBUG:: state = $state : line = \"$line\"\n"; } + + if ($state == 0) { + # find enum as first word + if ($line =~ m/\s*enum\s*.*/) { + if ($DEBUG) { print "DEBUG:: found enum in $line\n"; } + $state = 1; + # reset last_value + $last_value = -1; + # reset current_entry + $current_entry = ""; + # reset current_enum_name; + $current_enum_name = ""; + # remove enum from line recheck + $line =~ s/\s*enum\s*//; + enumParser($line); + } + } elsif ($state == 1) { + # find ENUM_NAME as first word + if ($line =~ m/\s*(\w+)\s*.*/) { + if ($DEBUG) { print "DEBUG:: found ENUM_NAME $1 in $line\n"; } + $state = 2; + my $enum_name = $1; + $current_enum_name = $enum_name; + # remove ENUM_NAME from line + $line =~ s/\s*$enum_name\s*//; + #recheck + enumParser($line); + } + } elsif ($state == 2) { + # find { as first word + if ($line =~ m/\s*{\s*.*/) { + if ($DEBUG) { print "DEBUG:: found { in $line\n"; } + $state = 3; + # remove { from line recheck + $line =~ s/\s*{\s*//; + enumParser($line); + } + } elsif ($state == 3) { + # find ENTRY as first word + if ($line =~ m/\s*(\w+)\s*.*/) { + if ($DEBUG) { print "DEBUG:: found ENTRY $1 in $line\n"; } + my $entry = $1; + $current_entry = $entry; + # remove ENTRY from line + $line =~ s/\s*$entry\s*//; + $state = 4; + #recheck + enumParser($line); + } + # find } as first word + elsif ($line =~ m/\s*}\s*.*/) { + if ($DEBUG) { print "DEBUG:: found } in $line\n"; } + $state = 7; + # remove } from line recheck + $line =~ s/\s*}\s*//; + enumParser($line); + } + } elsif ($state == 4) { + # find = as first word + if ($line =~ m/\s*=\s*.*/) { + if ($DEBUG) { print "DEBUG:: found = in $line\n"; } + $state = 5; + # remove = from line recheck + $line =~ s/\s*=\s*//; + enumParser($line); + } + # find , as first word + elsif ($line =~ m/\s*,\s*.*/) { + if ($DEBUG) { print "DEBUG:: found , in $line\n"; } + $state = 3; + # assign next last_value to entry + $last_value++; + my $value = $last_value; + if ($DEBUG) { print "DEBUG:: default VALUE $value assigned to $current_entry\n"; } + $enums{$current_enum_name}{$current_entry} = $value; + # remove , from line recheck + $line =~ s/\s*,\s*//; + enumParser($line); + } + # find } as first word + elsif ($line =~ m/\s*}\s*.*/) { + if ($DEBUG) { print "DEBUG:: found } in $line\n"; } + $state = 7; + # remove } from line recheck + $line =~ s/\s*}\s*//; + enumParser($line); + } + } elsif ($state == 5) { + # find VALUE as first word + if ($line =~ m/\s*(\w+)\s*.*/) { + if ($DEBUG) { print "DEBUG:: found VALUE $1 in $line\n"; } + my $value = $1; + $last_value = $value; + # assign value to entry + if ($DEBUG) { print "DEBUG:: VALUE $value assigned to $current_entry\n"; } + $enums{$current_enum_name}{$current_entry} = $value; + # remove VALUE from line + $line =~ s/\s*$value\s*//; + $state = 6; + #recheck + enumParser($line); + } + } elsif ($state == 6) { + # find , as first word + if ($line =~ m/\s*,\s*.*/) { + if ($DEBUG) { print "DEBUG:: found , in $line\n"; } + $state = 3; + # remove , from line recheck + $line =~ s/\s*,\s*//; + enumParser($line); + } + # find } as first word + elsif ($line =~ m/\s*}\s*.*/) { + if ($DEBUG) { print "DEBUG:: found } in $line\n"; } + $state = 7; + # remove } from line recheck + $line =~ s/\s*}\s*//; + enumParser($line); + } + } elsif ($state == 7) { + # find ; as first word + if ($line =~ m/\s*;\s*.*/) { + if ($DEBUG) { print "DEBUG:: found ; in $line\n"; } + $state = 0; + # remove ; from line recheck + $line =~ s/\s*;\s*//; + enumParser($line); + } + } +} + +sub help { + printf("Usage: ppeCreateAttrGetSetMacros.pl [--path ] [--verbose] [--help] [--src ] [--inc Option to enable specifying alternate path to fapi headers\n"); + printf("-v | -verbose Inform user of findings and changes\n"); + printf("-h | -help print this message\n"); + exit(0); +} diff --git a/src/tools/scripts/ppeCreateIfAttrService.pl b/src/tools/scripts/ppeCreateIfAttrService.pl new file mode 100755 index 00000000..1202505a --- /dev/null +++ b/src/tools/scripts/ppeCreateIfAttrService.pl @@ -0,0 +1,240 @@ +#!/usr/bin/perl +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/tools/scripts/ppeCreateIfAttrService.pl $ +# +# OpenPOWER sbe Project +# +# Contributors Listed Below - COPYRIGHT 2016 +# +# +# 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 +# Purpose: This perl script will parse HWP Attribute XML files and +# initfile attr files and create the fapiGetInitFileAttr() function +# in a file called fapi2AttributeService.C + +use strict; + +#------------------------------------------------------------------------------ +# Print Command Line Help +#------------------------------------------------------------------------------ +my $numArgs = $#ARGV + 1; +if ($numArgs < 3) +{ + print ("Usage: fapi2CreateIfAttrService.pl \n"); + print (" [ ...]\n"); + print (" -a [ ...]\n"); + print (" This perl script will parse if-attr files (containing the\n"); + print (" attributes used by the initfile) and attribute XML files\n"); + print (" (containing all HWPF attributes) and create the\n"); + print (" fapiGetInitFileAttr() function in a file called\n"); + print (" fapiAttributeService.C. Only the attributes specified in\n"); + print (" the if-attr files are supported. If no if-attr files are\n"); + print (" specified then all attributes are supported\n"); + exit(1); +} + +#------------------------------------------------------------------------------ +# Specify perl modules to use +#------------------------------------------------------------------------------ +use XML::Simple; +my $xml = new XML::Simple (KeyAttr=>[]); + +# Uncomment to enable debug output +#use Data::Dumper; + +#------------------------------------------------------------------------------ +# Open output file for writing +#------------------------------------------------------------------------------ +my $asFile = $ARGV[0]; +$asFile .= "/"; +$asFile .= "fapi2AttributeService.C"; +open(ASFILE, ">", $asFile); + +#------------------------------------------------------------------------------ +# Print Start of file information to fapiAttributeService.C +#------------------------------------------------------------------------------ +print ASFILE "// fapi2AttributeService.C\n"; +print ASFILE "// This file is generated by perl script fapi2CreateIfAttrService.pl\n\n"; +print ASFILE "#include \n"; +print ASFILE "//#include \n"; +print ASFILE "//#include \n\n"; +print ASFILE "namespace fapi2\n"; +print ASFILE "{\n\n"; +print ASFILE "ReturnCode fapiGetInitFileAttr(const AttributeId i_id,\n"; +print ASFILE " const Target * i_pTarget,\n"; +print ASFILE " uint64_t & o_val,\n"; +print ASFILE " const uint32_t i_arrayIndex1,\n"; +print ASFILE " const uint32_t i_arrayIndex2,\n"; +print ASFILE " const uint32_t i_arrayIndex3,\n"; +print ASFILE " const uint32_t i_arrayIndex4)\n"; +print ASFILE "{\n"; +print ASFILE " ReturnCode l_rc;\n\n"; + +my $xmlFiles = 0; +my $attCount = 0; +my $numIfAttrFiles = 0; +my @attrIds; + +#------------------------------------------------------------------------------ +# Element names +#------------------------------------------------------------------------------ +my $attribute = 'attribute'; + +#------------------------------------------------------------------------------ +# For each argument +#------------------------------------------------------------------------------ +my $argfile = $ARGV[1]; +my $entries = $xml->XMLin($argfile, ForceArray => ['entry']); +foreach my $entr (@{$entries->{entry}}) { + + my $inname = $entr->{name}; + + # 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 + + foreach my $argnum (2 .. $#ARGV) + { + my $infile = $ARGV[$argnum]; + + my $attributes = $xml->XMLin($infile, ForceArray => ['attribute']); + + # Uncomment to get debug output of all attributes + #print "\nFile: ", $infile, "\n", Dumper($attributes), "\n"; + + #-------------------------------------------------------------------------- + # For each Attribute + #-------------------------------------------------------------------------- + foreach my $attr (@{$attributes->{attribute}}) + { + + + + if($attr->{id} eq $inname) { + + #------------------------------------------------------------------ + # Check that the AttributeId exists + #------------------------------------------------------------------ + if (! exists $attr->{id}) + { + print ("fapiParseAttributeInfo.pl ERROR. Att 'id' missing\n"); + exit(1); + } + + + #------------------------------------------------------------------ + # Figure out the number of attribute array dimensions + #------------------------------------------------------------------ + my $numArrayDimensions = 0; + if ($attr->{array}) + { + # Remove leading whitespace + my $dimText = $attr->{array}; + $dimText =~ s/^\s+//; + + # Split on commas or whitespace + my @vals = split(/\s*,\s*|\s+/, $dimText); + + $numArrayDimensions=@vals; + } + + #------------------------------------------------------------------ + # Print the attribute get code to fapiAttributeService.C + #------------------------------------------------------------------ + if ($attCount > 0) + { + print ASFILE " else "; + } + else + { + print ASFILE " "; + } + $attCount++; + + print ASFILE "if (i_id == $attr->{id})\n"; + print ASFILE " {\n"; + print ASFILE " $attr->{id}_Type l_attr;\n"; + + if (exists $attr->{privileged}) + { + print ASFILE " l_rc = FAPI_ATTR_GET_PRIVILEGED($attr->{id}, i_pTarget, l_attr);\n"; + } + else + { + print ASFILE " l_rc = FAPI_ATTR_GET($attr->{id}, i_pTarget, l_attr);\n"; + } + print ASFILE " o_val = l_attr"; + + if ($numArrayDimensions >= 5) + { + print ("fapiParseAttributeInfo.pl ERROR. More than 4 array dimensions!!\n"); + exit(1); + } + else + { + for (my $i = 0; $i < $numArrayDimensions; $i++) + { + print ASFILE "[i_arrayIndex"; + print ASFILE $i+1; + print ASFILE "]"; + } + } + + print ASFILE ";\n"; + print ASFILE " }\n"; + + + + } + } + } + +} + +#------------------------------------------------------------------------------ +# Print End of file information to fapiAttributeService.C +#-------------------------------------------------------------------------- +if ($attCount > 0) +{ + print ASFILE " else\n"; +} +print ASFILE " {\n"; +print ASFILE " FAPI_ERR(\"fapiGetInitFileAttr: Unrecognized attr ID: 0x%x\", i_id);\n"; +print ASFILE " l_rc.setFapiError(FAPI_RC_INVALID_ATTR_GET);\n"; +print ASFILE " l_rc.addEIFfdc(0, &i_id, sizeof(i_id));\n"; +print ASFILE " }\n\n"; +print ASFILE " if (l_rc)\n"; +print ASFILE " {\n"; +print ASFILE " if (i_pTarget)\n"; +print ASFILE " {\n"; +print ASFILE " FAPI_ERR(\"fapiGetInitFileAttr: Error getting attr ID 0x%x from targType 0x%x\",\n"; +print ASFILE " i_id, i_pTarget->getType());\n"; +print ASFILE " }\n"; +print ASFILE " else\n"; +print ASFILE " {\n"; +print ASFILE " FAPI_ERR(\"fapiGetInitFileAttr: Error getting attr ID 0x%x from system target\",\n"; +print ASFILE " i_id);\n"; +print ASFILE " }\n"; +print ASFILE " }\n\n"; +print ASFILE " return l_rc;\n"; +print ASFILE "}\n\n"; +print ASFILE "}\n"; + + +#------------------------------------------------------------------------------ +# Close output file +#------------------------------------------------------------------------------ +close(ASFILE); diff --git a/src/tools/scripts/ppeParseAttrGetSetMacros.pl b/src/tools/scripts/ppeParseAttrGetSetMacros.pl new file mode 100644 index 00000000..013cad96 --- /dev/null +++ b/src/tools/scripts/ppeParseAttrGetSetMacros.pl @@ -0,0 +1,286 @@ +#!/usr/bin/perl +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/tools/scripts/ppeParseAttrGetSetMacros.pl $ +# +# OpenPOWER sbe Project +# +# Contributors Listed Below - COPYRIGHT 2016 +# +# +# 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 +# Purpose: This perl script will parse HWP Attribute XML files and +# initfile attr files and create the fapiGetInitFileAttr() function +# in a file called fapiAttributeService.C + +use strict; + +#------------------------------------------------------------------------------ +# Print Command Line Help +#------------------------------------------------------------------------------ +my $numArgs = $#ARGV + 1; +if ($numArgs < 3) +{ + print ("Usage: ppeParseAttrGetSetMacros.pl \n"); + print (" [ ...]\n"); + print (" -a [ ...]\n"); + print (" This perl script will parse if-attr files (containing the\n"); + print (" attributes used by the initfile) and attribute XML files\n"); + print (" (containing all HWPF attributes) and create the\n"); + print (" fapiGetInitFileAttr() function in a file called\n"); + print (" fapiAttributeService.C. Only the attributes specified in\n"); + print (" the if-attr files are supported. If no if-attr files are\n"); + print (" specified then all attributes are supported\n"); + exit(1); +} + +#------------------------------------------------------------------------------ +# Specify perl modules to use +#------------------------------------------------------------------------------ +use XML::Simple; +my $xml = new XML::Simple (KeyAttr=>[]); + +# Uncomment to enable debug output +#use Data::Dumper; + +#------------------------------------------------------------------------------ +# Open output file for writing +#------------------------------------------------------------------------------ +my $chipFile = $ARGV[0]; +$chipFile .= "/"; +$chipFile .= "proc_sbe_fixed_proc_chip.H"; +open(CHFILE, ">", $chipFile); + +my $exFile = $ARGV[0]; +$exFile .= "/"; +$exFile .= "proc_sbe_fixed_ex.H"; +open(EXFILE, ">", $exFile); + +my $coreFile = $ARGV[0]; +$coreFile .= "/"; +$coreFile .= "proc_sbe_fixed_core.H"; +open(COFILE, ">", $coreFile); + +my $eqFile = $ARGV[0]; +$eqFile .= "/"; +$eqFile .= "proc_sbe_fixed_eq.H"; +open(EQFILE, ">", $eqFile); + +my $pervFile = $ARGV[0]; +$pervFile .= "/"; +$pervFile .= "proc_sbe_fixed_perv.H"; +open(PEFILE, ">", $pervFile); + + +#------------------------------------------------------------------------------ +# Print Start of file information to fapiAttributeService.C +#------------------------------------------------------------------------------ +#print ASFILE "// proc_sbe_func.H\n"; +#print ASFILE "// This file is generated by perl script fapi2ParseProcSbeFixed.pl\n\n"; +#print ASFILE "#ifndef __PROC_SBE_FIXED_H__\n"; +#print ASFILE "#define __PROC_SBE_FIXED_H__\n"; +#print ASFILE "#include \"p9_sbe.H\"\n"; +#print ASFILE "#include \"plat_target_parms.H\"\n"; +#print ASFILE "#include \"fapi2AttributeIds.H\"\n\n"; + + +my $xmlFiles = 0; +my $attCount = 0; +my $numIfAttrFiles = 0; +my @attrSystemIds; +my @attrChipIds; +my @attrExIds; +my @attrCoreIds; +my @attrEqIds; +my @attrPervIds; + + + +#------------------------------------------------------------------------------ +# Element names +#------------------------------------------------------------------------------ +my $attribute = 'attribute'; + +#------------------------------------------------------------------------------ +# For each argument +#------------------------------------------------------------------------------ +my $argfile = $ARGV[1]; +my $entries = $xml->XMLin($argfile, ForceArray => ['entry']); +foreach my $entr (@{$entries->{entry}}) { + + my $inname = $entr->{name}; + + # 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 + + foreach my $argnum (2 .. $#ARGV) + { + my $infile = $ARGV[$argnum]; + + my $attributes = $xml->XMLin($infile, ForceArray => ['attribute']); + + # Uncomment to get debug output of all attributes + #print "\nFile: ", $infile, "\n", Dumper($attributes), "\n"; + + #-------------------------------------------------------------------------- + # For each Attribute + #-------------------------------------------------------------------------- + foreach my $attr (@{$attributes->{attribute}}) + { + + if($attr->{id} eq $inname) { + + #------------------------------------------------------------------ + # Check that the AttributeId exists + #------------------------------------------------------------------ + if (! exists $attr->{id}) + { + print ("ppeParseGetSetMacros.pl ERROR. Att 'id' missing\n"); + exit(1); + } + + if($attr->{targetType} eq "TARGET_TYPE_SYSTEM") { + + push(@attrSystemIds, $attr); + + } elsif($attr->{targetType} eq "TARGET_TYPE_PROC_CHIP") { + + push(@attrChipIds, $attr); + + } elsif($attr->{targetType} eq "TARGET_TYPE_CORE") { + + push(@attrCoreIds, $attr); + + } elsif($attr->{targetType} eq "TARGET_TYPE_EQ") { + + push(@attrEqIds, $attr); + + } elsif($attr->{targetType} eq "TARGET_TYPE_EX") { + + push(@attrExIds, $attr); + + } elsif($attr->{targetType} eq "TARGET_TYPE_PERV") { + +# push(@attrPervIds, $attr->{id}); + push(@attrPervIds, $attr); + + } else { + + print ("ppeParseAttrGetSetMacros.pl ERROR. Wrong attribute type: $attr->{targetType}\n"); + exit(1); + + } + + } + } + } +} + +print SYFILE "// proc_sbe_fixed_system.H\n"; +print SYFILE "// This file is generated by perl script ppeParseAttrGetSetMacros.pl\n\n"; +print SYFILE "#ifndef __PROC_SBE_FIXED_SYSTEM_H__\n"; +print SYFILE "#define __PROC_SBE_FIXED_SYSTEM_H__\n\n"; +foreach my $attr (@attrSystemIds) +{ + + my $value = uc $attr->{valueType}; + print SYFILE "PROC_SBE_FIXED_$value($attr->{id});\n" + + +} +print SYFILE "\n#endif // __PROC_SBE_FIXED_SYSTEM_H__"; + +print CHFILE "// proc_sbe_fixed_proc_chip.H\n"; +print CHFILE "// This file is generated by perl script ppeParseAttrGetSetMacros.pl\n\n"; +print CHFILE "#ifndef __PROC_SBE_FIXED_PROC_CHIP_H__\n"; +print CHFILE "#define __PROC_SBE_FIXED_PROC_CHIP_H__\n\n"; +foreach my $attr (@attrChipIds) +{ + + my $value = uc $attr->{valueType}; + print CHFILE "PROC_SBE_FIXED_$value($attr->{id});\n" + + +} +print CHFILE "\n#endif // __PROC_SBE_FIXED_PROC_CHIP_H__"; + +print EXFILE "// proc_sbe_fixed_ex.H\n"; +print EXFILE "// This file is generated by perl script ppeParseAttrGetSetMacros.pl\n\n"; +print EXFILE "#ifndef __PROC_SBE_FIXED_EX_H__\n"; +print EXFILE "#define __PROC_SBE_FIXED_EX_H__\n"; +foreach my $attr (@attrExIds) +{ + + my $value = uc $attr->{valueType}; + print EXFILE "PROC_SBE_FIXED_TARGET_$value($attr->{id}, EX_TARGET_COUNT);\n" + + +} +print EXFILE "\n#endif // __PROC_SBE_FIXED_EX_H__"; + +print COFILE "// proc_sbe_fixed_co.H\n"; +print COFILE "// This file is generated by perl script ppeParseAttrGetSetMacros.pl\n\n"; +print COFILE "#ifndef __PROC_SBE_FIXED_CO_H__\n"; +print COFILE "#define __PROC_SBE_FIXED_CO_H__\n"; +foreach my $attr (@attrCoreIds) +{ + + my $value = uc $attr->{valueType}; + print COFILE "PROC_SBE_FIXED_TARGET_$value($attr->{id}, CORE_TARGET_COUNT);\n" + + +} +print COFILE "\n#endif // __PROC_SBE_FIXED_CO_H__"; + +print EQFILE "// proc_sbe_fixed_eq.H\n"; +print EQFILE "// This file is generated by perl script ppeParseAttrGetSetMacros.pl\n\n"; +print EQFILE "#ifndef __PROC_SBE_FIXED_EQ_H__\n"; +print EQFILE "#define __PROC_SBE_FIXED_EQ_H__\n"; +foreach my $attr (@attrEqIds) +{ + + my $value = uc $attr->{valueType}; + print EQFILE "PROC_SBE_FIXED_TARGET_$value($attr->{id}, EQ_TARGET_COUNT);\n" + + +} +print EQFILE "\n#endif // __PROC_SBE_FIXED_EQ_H__"; + +print PEFILE "// proc_sbe_fixed_perv.H\n"; +print PEFILE "// This file is generated by perl script ppeParseAttrGetSetMacros.pl\n\n"; +print PEFILE "#ifndef __PROC_SBE_FIXED_PERV_H__\n"; +print PEFILE "#define __PROC_SBE_FIXED_PERV_H__\n"; +foreach my $attr (@attrPervIds) +{ + + my $value = uc $attr->{valueType}; + print PEFILE "PROC_SBE_FIXED_TARGET_$value($attr->{id}, PERV_TARGET_COUNT);\n" + + +} +print PEFILE "\n#endif // __PROC_SBE_FIXED_PERV_H__"; + +#print ASFILE "#endif // __PROC_SBE_FIXED_H__"; + +#------------------------------------------------------------------------------ +# Close output file +#------------------------------------------------------------------------------ +close(CHFILE); +close(COFILE); +close(EXFILE); +close(PEFILE); +close(EQFILE); + diff --git a/src/tools/scripts/ppeParseAttributeInfo.pl b/src/tools/scripts/ppeParseAttributeInfo.pl new file mode 100755 index 00000000..1b881a4d --- /dev/null +++ b/src/tools/scripts/ppeParseAttributeInfo.pl @@ -0,0 +1,746 @@ +#!/usr/bin/perl -w +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/tools/scripts/ppeParseAttributeInfo.pl $ +# +# OpenPOWER sbe Project +# +# Contributors Listed Below - COPYRIGHT 2015,2016 +# +# +# 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 +# Purpose: This perl script will parse HWP Attribute XML files +# and add attribute information to a file called fapi2AttributeIds.H + +use strict; + +sub help { + print ("Usage: ppeParseAttributeInfo.pl [ ...]\n"); + print (" This perl script will parse attribute XML files and create the following files:\n"); + print (" - fapi2AttributeIds.H. Contains IDs, type, value enums and other information\n"); + print (" - fapi2ChipEcFeature.C. Contains a function to query chip EC features\n"); + print (" - fapi2AttributePlatCheck.H. Contains compile time checks that all attributes are\n"); + print (" handled by the platform\n"); + print (" - fapi2AttributesSupported.html Contains the HWPF attributes supported\n"); + print (" - fapi2AttrInfo.csv Used to process Attribute Override Text files\n"); + print (" - fapi2AttrEnumInfo.csv Used to process Attribute Override Text files\n"); +} + +my $DEBUG = 0; +my $VERBOSE = 0; +my $help = 0; + +#------------------------------------------------------------------------------ +# Print Command Line Help +#------------------------------------------------------------------------------ +my $numArgs = $#ARGV + 1; +if ($numArgs < 2) +{ + print ("Invalid number of arguments\n\n"); + help(); + exit(1); +} + +#------------------------------------------------------------------------------ +# Specify perl modules to use +#------------------------------------------------------------------------------ +use Getopt::Long; +use Digest::MD5 qw(md5_hex); +use XML::Simple; +my $xml = new XML::Simple (KeyAttr=>[]); + +GetOptions ("verbose" => \$VERBOSE, + "help" => \$help, + "debug" => \$DEBUG, + ); + +if ($help) +{ + help(); + exit(0); +} + +if ($DEBUG) +{ + print "DEBUG enabled!!!!\n"; +} + +# 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'; + +#------------------------------------------------------------------------------ +# Open output files for writing +#------------------------------------------------------------------------------ +my $aiFile = $ARGV[0]; +$aiFile .= "/"; +$aiFile .= "fapi2AttributeIds.H"; +open(AIFILE, ">", $aiFile); + +my $echFile = $ARGV[0]; +$echFile .= "/"; +$echFile .= "fapi2ChipEcFeature.H"; +open(ECHFILE, ">", $echFile); + +my $acFile = $ARGV[0]; +$acFile .= "/"; +$acFile .= "fapi2AttributePlatCheck.H"; +open(ACFILE, ">", $acFile); + +my $asFile = $ARGV[0]; +$asFile .= "/"; +$asFile .= "fapi2AttributesSupported.html"; +open(ASFILE, ">", $asFile); + +my $itFile = $ARGV[0]; +$itFile .= "/"; +$itFile .= "fapi2AttrInfo.csv"; +open(ITFILE, ">", $itFile); + +my $etFile = $ARGV[0]; +$etFile .= "/"; +$etFile .= "fapi2AttrEnumInfo.csv"; +open(ETFILE, ">", $etFile); + +#------------------------------------------------------------------------------ +# Print Start of file information to fapiAttributeIds.H +#------------------------------------------------------------------------------ +print AIFILE "// fapi2AttributeIds.H\n"; +print AIFILE "// This file is generated by perl script fapiParseAttributeInfo.pl\n\n"; +print AIFILE "#ifndef FAPI2ATTRIBUTEIDS_H_\n"; +print AIFILE "#define FAPI2ATTRIBUTEIDS_H_\n\n"; +print AIFILE "#ifndef __ASSEMBLER__\n\n"; +print AIFILE "#include \n"; +print AIFILE "#include \n\n"; +print AIFILE "namespace fapi2\n"; +print AIFILE "{\n\n"; +print AIFILE "\/**\n"; +print AIFILE " * \@brief Enumeration of attribute IDs\n"; +print AIFILE " *\/\n"; +print AIFILE "enum AttributeId\n{\n"; + +#------------------------------------------------------------------------------ +# Print Start of file information to fapi2_chip_ec_feature.H +#------------------------------------------------------------------------------ +print ECHFILE "// This file is generated by perl script parseAttributeInfo.pl\n"; +print ECHFILE "// It implements the fapi2_chip_ec_feature function\n\n"; +print ECHFILE "#ifndef __FAPI2_CHIP_EC_FEATURE_H_\n"; +print ECHFILE "#define __FAPI2_CHIP_EC_FEATURE_H_\n"; +print ECHFILE "#include \n"; +print ECHFILE "#include \n"; +print ECHFILE "namespace fapi2\n"; +print ECHFILE "{\n\n"; +print ECHFILE "// create a unique type from an int ( or attribute id) \n"; +print ECHFILE "template\n"; +print ECHFILE "struct int2Type {\n"; +print ECHFILE "enum { value = I };\n"; +print ECHFILE "};\n"; +print ECHFILE "ReturnCode queryChipEcAndName(\n"; +print ECHFILE " const Target& i_target,\n"; +print ECHFILE " fapi2::ATTR_NAME_Type& , fapi2::ATTR_EC_Type & );\n\n"; +print ECHFILE "template\n"; +print ECHFILE "ReturnCode queryChipEcFeature(int2Type id,\n"; +print ECHFILE " const Target& i_target,\n"; +print ECHFILE " uint8_t & o_hasFeature)\n"; +print ECHFILE "{\n"; +print ECHFILE " fapi2::ATTR_NAME_Type l_chipName;\n"; +print ECHFILE " fapi2::ATTR_EC_Type l_chipEc;\n\n"; +print ECHFILE " o_hasFeature = 0;\n\n"; +print ECHFILE " ReturnCode l_rc = queryChipEcAndName(i_target, l_chipName, l_chipEc);\n"; +print ECHFILE " if (l_rc)\n"; +print ECHFILE " {\n"; +print ECHFILE " FAPI_ERR(\"queryChipEcFeature: error getting chip name\");\n"; +print ECHFILE " }\n"; +print ECHFILE " else\n"; +print ECHFILE " {\n"; +print ECHFILE " o_hasFeature = hasFeature(int2Type(), l_chipName, l_chipEc);\n"; +print ECHFILE " }\n"; +print ECHFILE " return l_rc;\n"; +print ECHFILE "}\n\n"; + +#------------------------------------------------------------------------------ +# Print Start of file information to fapiAttributePlatCheck.H +#------------------------------------------------------------------------------ +print ACFILE "// fapiAttributePlatCheck.H\n"; +print ACFILE "// This file is generated by perl script fapiParseAttributeInfo.pl\n"; +print ACFILE "// A platform can include it to ensure that it handles all HWPF\n"; +print ACFILE "// attributes\n\n"; +print ACFILE "#ifndef FAPIATTRIBUTEPLATCHECK_H_\n"; +print ACFILE "#define FAPIATTRIBUTEPLATCHECK_H_\n\n"; + +#------------------------------------------------------------------------------ +# Print Start of file information to fapiAttributesSupported.html +#------------------------------------------------------------------------------ +print ASFILE "\n"; +print ASFILE "\n\n"; +print ASFILE "\n"; +print ASFILE "\n"; +print ASFILE "\n\n"; +print ASFILE "

HWPF Attributes supported by this build.

\n"; +print ASFILE "\n"; +print ASFILE ""; + +#------------------------------------------------------------------------------ +# Print Start of file information to fapiAttrInfo.csv +#------------------------------------------------------------------------------ +print ITFILE "# fapiAttrInfo.csv\n"; +print ITFILE "# This file is generated by perl script fapiParseAttributeInfo.pl\n"; +print ITFILE "# It lists information about FAPI attributes and is used to\n"; +print ITFILE "# process FAPI Attribute text files (overrides/syncs)\n"; +print ITFILE "# Format:\n"; +print ITFILE "# ,,,\n"; +print ITFILE "# Note that for the AttributeTanks at the FAPI layer, the\n"; +print ITFILE "# FAPI-ATTR-ID-STR and LAYER-ATTR-ID-STR will be identical\n"; + +#------------------------------------------------------------------------------ +# Print Start of file information to fapiAttrEnumInfo.csv +#------------------------------------------------------------------------------ +print ETFILE "# fapiAttrEnumInfo.csv\n"; +print ETFILE "# This file is generated by perl script fapiParseAttributeInfo.pl\n"; +print ETFILE "# It lists information about FAPI attribute enumeratorss and is\n"; +print ETFILE "# used to process FAPI Attribute text files (overrides/syncs)\n"; +print ETFILE "# Format:\n"; +print ETFILE "# ,\n"; + +my %attrIdHash; # Records which Attribute IDs have been used +my %attrValHash; # Records which Attribute values have been used + +#------------------------------------------------------------------------------ +# For each XML file +#------------------------------------------------------------------------------ +#my $argfile = "p9_ppe_attributes.xml"; +my $argfile = $ARGV[1]; +if ($DEBUG) { print "DEBUG:: XML filter file - $argfile\n" } +my $entries = $xml->XMLin($argfile, ForceArray => ['entry']); +foreach my $entr (@{$entries->{entry}}) { + + my $inname = $entr->{name}; + if ($DEBUG) { print "DEBUG:: entr->file = $entr->{file}; \n" } + + foreach my $argnum (2 .. $#ARGV) + { + my $infile = $ARGV[$argnum]; + + # 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']); + + if ($DEBUG) { print "DEBUG:: File: ", $infile, "\n", Dumper($attributes), "\n"; } + + #-------------------------------------------------------------------------- + # For each Attribute + #-------------------------------------------------------------------------- + foreach my $attr (@{$attributes->{attribute}}) + { + + #print "? $attr->{id}, $inname\n"; + + if($attr->{id} eq $inname) { + + #print "yes $attr->{id}, $inname\n"; + + #---------------------------------------------------------------------- + # Print the Attribute ID and calculated value to fapiAttributeIds.H and + # fapiAttributeIds.txt. The value for an attribute is a hash value + # generated from the attribute name, this ties a specific value to a + # specific attribute name. This is done for Cronus so that if a HWP is + # not recompiled against a new eCMD/Cronus version where the attributes + # have changed then there will not be a mismatch in enumerator values. + # This is a 28bit hash value because the Initfile compiler has a + # requirement that the top nibble of the 32 bit attribute ID be zero to + # store flags + #---------------------------------------------------------------------- + if (! exists $attr->{id}) + { + print ("fapiParseAttributeInfo.pl ERROR. Attribute 'id' missing in $infile\n"); + exit(1); + } + + if (exists($attrIdHash{$attr->{id}})) + { + # Two different attributes with the same id! + print ("fapiParseAttributeInfo.pl ERROR. Duplicate Attribute id $attr->{id} in $infile\\n"); + exit(1); + } + + # Calculate a 28 bit hash value. + my $attrHash128Bit = md5_hex($attr->{id}); + my $attrHash28Bit = substr($attrHash128Bit, 0, 7); + + # Print the attribute ID/value to fapiAttributeIds.H + print AIFILE " $attr->{id} = 0x$attrHash28Bit,\n"; + + if (exists($attrValHash{$attrHash28Bit})) + { + # Two different attributes generate the same hash-value! + print ("fapiParseAttributeInfo.pl ERROR. Duplicate attr id hash value for $attr->{id} in $infile\ \n"); + exit(1); + } + + $attrIdHash{$attr->{id}} = $attrHash28Bit; + $attrValHash{$attrHash28Bit} = 1; + } + }; + } +} + +#------------------------------------------------------------------------------ +# Print AttributeId enumeration end to fapiAttributeIds.H +#------------------------------------------------------------------------------ +print AIFILE "};\n\n"; + +#------------------------------------------------------------------------------ +# Print Attribute Information comment to fapiAttributeIds.H +#------------------------------------------------------------------------------ +print AIFILE "\/**\n"; +print AIFILE " * \@brief Attribute Information\n"; +print AIFILE " *\/\n"; + + +foreach my $entr (@{$entries->{entry}}) { + +# print " $entr->{file}, $entr->{name}\n"; + +# my $infile = $entr->{file}; + my $inname = $entr->{name}; + + # 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 + + foreach my $argnum (2 .. $#ARGV) + { + my $infile = $ARGV[$argnum]; + + my $attributes = $xml->XMLin($infile, ForceArray => ['attribute', 'chip']); + + # Uncomment to get debug output of all attributes + if ($DEBUG) { print "DEBUG:: File: ", $infile, "\n", Dumper($attributes), "\n"; } + + #-------------------------------------------------------------------------- + # For each Attribute + #-------------------------------------------------------------------------- + foreach my $attr (@{$attributes->{attribute}}) + { + + if($attr->{id} eq $inname) { + + #---------------------------------------------------------------------- + # Print a comment with the attribute ID fapiAttributeIds.H + #---------------------------------------------------------------------- + print AIFILE "/* $attr->{id} */\n"; + + #---------------------------------------------------------------------- + # Print the AttributeId and description to fapiAttributesSupported.html + #---------------------------------------------------------------------- + if (! exists $attr->{description}) + { + print ("fapiParseAttributeInfo.pl ERROR. Attribute 'description' missing for $attr->{id} in $infile\n"); + exit(1); + } + + + #---------------------------------------------------------------------- + # Figure out the attribute array dimensions (if array) + #---------------------------------------------------------------------- + my $arrayDimensions = ""; + my $numArrayDimensions = 0; + if ($attr->{array}) + { + # Remove leading whitespace + my $dimText = $attr->{array}; + $dimText =~ s/^\s+//; + + # Split on commas or whitespace + my @vals = split(/\s*,\s*|\s+/, $dimText); + + foreach my $val (@vals) + { + $arrayDimensions .= "[${val}]"; + $numArrayDimensions++; + } + } + + #---------------------------------------------------------------------- + # Print the typedef for each attribute's val type to fapiAttributeIds.H + # Print the attribute information to fapiAttrInfo.csv + #---------------------------------------------------------------------- + if (exists $attr->{chipEcFeature}) + { + # The value type of chip EC feature attributes is uint8_t + print AIFILE "typedef uint8_t $attr->{id}_Type;\n"; + print ITFILE "$attr->{id},$attr->{id},0x$attrIdHash{$attr->{id}},u8\n" + } + else + { + if (! exists $attr->{valueType}) + { + print ("fapiParseAttributeInfo.pl ERROR. Att 'valueType' missing for $attr->{id} in $infile\n"); + exit(1); + } + + if ($attr->{valueType} eq 'uint8') + { + print AIFILE "typedef uint8_t $attr->{id}_Type$arrayDimensions;\n"; + print ITFILE "$attr->{id},$attr->{id},0x$attrIdHash{$attr->{id}},u8" . + "$arrayDimensions\n"; + } + elsif ($attr->{valueType} eq 'uint16') + { + print AIFILE "typedef uint16_t $attr->{id}_Type$arrayDimensions;\n"; + print ITFILE "$attr->{id},$attr->{id},0x$attrIdHash{$attr->{id}},u8" . + "$arrayDimensions\n"; + } + elsif ($attr->{valueType} eq 'uint32') + { + print AIFILE "typedef uint32_t $attr->{id}_Type$arrayDimensions;\n"; + print ITFILE "$attr->{id},$attr->{id},0x$attrIdHash{$attr->{id}},u32" . + "$arrayDimensions\n"; + } + elsif ($attr->{valueType} eq 'uint64') + { + print AIFILE "typedef uint64_t $attr->{id}_Type$arrayDimensions;\n"; + print ITFILE "$attr->{id},$attr->{id},0x$attrIdHash{$attr->{id}},u64" . + "$arrayDimensions\n"; + } + elsif ($attr->{valueType} eq 'int8') + { + print AIFILE "typedef int8_t $attr->{id}_Type$arrayDimensions;\n"; + print ITFILE "$attr->{id},$attr->{id},0x$attrIdHash{$attr->{id}},8" . + "$arrayDimensions\n"; + } + elsif ($attr->{valueType} eq 'int16') + { + print AIFILE "typedef int16_t $attr->{id}_Type$arrayDimensions;\n"; + print ITFILE "$attr->{id},$attr->{id},0x$attrIdHash{$attr->{id}},32" . + "$arrayDimensions\n"; + } + elsif ($attr->{valueType} eq 'int32') + { + print AIFILE "typedef int32_t $attr->{id}_Type$arrayDimensions;\n"; + print ITFILE "$attr->{id},$attr->{id},0x$attrIdHash{$attr->{id}},32" . + "$arrayDimensions\n"; + } + elsif ($attr->{valueType} eq 'int64') + { + print AIFILE "typedef int64_t $attr->{id}_Type$arrayDimensions;\n"; + print ITFILE "$attr->{id},$attr->{id},0x$attrIdHash{$attr->{id}},64" . + "$arrayDimensions\n"; + } + else + { + print ("fapi2ParseAttributeInfo.pl ERROR. valueType not recognized: "); + print $attr->{valueType}, " for $attr->{id} in $infile\n"; + exit(1); + } + } + + #---------------------------------------------------------------------- + # Print if the attribute is privileged + #---------------------------------------------------------------------- + if (exists $attr->{privileged}) + { + print AIFILE "const bool $attr->{id}_Privileged = true;\n"; + } + else + { + print AIFILE "const bool $attr->{id}_Privileged = false;\n"; + } + + #---------------------------------------------------------------------- + # Print the target type(s) that the attribute is associated with + #---------------------------------------------------------------------- + if (! exists $attr->{targetType}) + { + print ("fapiParseAttributeInfo.pl ERROR. Att 'targetType' missing for $attr->{id} in $infile\n"); + exit(1); + } + + print AIFILE "const TargetType $attr->{id}_TargetTypes = "; + + # Split on commas + my @targTypes = split(',', $attr->{targetType}); + my $targType = $targTypes[0]; + + foreach my $targType (@targTypes) + { + # Remove newlines and leading/trailing whitespace + $targType =~ s/\n//; + $targType =~ s/^\s+//; + $targType =~ s/\s+$//; + + # Consider only supported target types. The rest are ignored + if($targType ~~ ["TARGET_TYPE_PROC_CHIP", "TARGET_TYPE_SYSTEM", + "TARGET_TYPE_CORE", "TARGET_TYPE_MCS", "TARGET_TYPE_PERV", + "TARGET_TYPE_EQ", "TARGET_TYPE_EX"]) + { + print AIFILE "$targType"; + last; + } + else + { + next; + } + } + print AIFILE ";\n"; + + #---------------------------------------------------------------------- + # Print if the attribute is a platInit attribute + #---------------------------------------------------------------------- + if (exists $attr->{platInit}) + { + print AIFILE "const bool $attr->{id}_PlatInit = true;\n"; + } + else + { + print AIFILE "const bool $attr->{id}_PlatInit = false;\n"; + } + + #---------------------------------------------------------------------- + # Print if the attribute is a initToZero attribute + #---------------------------------------------------------------------- + if (exists $attr->{initToZero}) + { + print AIFILE "const bool $attr->{id}_InitToZero = true;\n"; + } + else + { + print AIFILE "const bool $attr->{id}_InitToZero = false;\n"; + } + + #---------------------------------------------------------------------- + # Print the value enumeration (if specified) to fapiAttributeIds.H and + # fapiAttributeEnums.txt + #---------------------------------------------------------------------- + if (exists $attr->{enum}) + { + print AIFILE "enum $attr->{id}_Enum\n{\n"; + + # Values must be separated by commas to allow for values to be + # specified: VAL_A = 3, VAL_B = 5, VAL_C = 0x23 + my @vals = split(',', $attr->{enum}); + + foreach my $val (@vals) + { + # Remove newlines and leading/trailing whitespace + $val =~ s/\n//; + $val =~ s/^\s+//; + $val =~ s/\s+$//; + + # Print the attribute enum to fapiAttributeIds.H + print AIFILE " ENUM_$attr->{id}_${val}"; + + # Print the attribute enum to fapiAttrEnumInfo.csv + my $attrEnumTxt = "$attr->{id}_${val}\n"; + $attrEnumTxt =~ s/ = /,/; + print ETFILE $attrEnumTxt; + + if ($attr->{valueType} eq 'uint64') + { + print AIFILE "ULL"; + } + + print AIFILE ",\n"; + } + + print AIFILE "};\n"; + } + + #---------------------------------------------------------------------- + # Print _GETMACRO and _SETMACRO where appropriate to fapiAttributeIds.H + #---------------------------------------------------------------------- + if (exists $attr->{chipEcFeature}) + { + #------------------------------------------------------------------ + # The attribute is a Chip EC Feature, define _GETMACRO to call a + # fapi function and define _SETMACRO to something that will cause a + # compile failure if a set is attempted + #------------------------------------------------------------------ + print AIFILE "#define $attr->{id}_GETMACRO(ID, PTARGET, VAL) \\\n"; + print AIFILE " PLAT_GET_CHIP_EC_FEATURE_OVERRIDE(ID, PTARGET, VAL) ? fapi2::FAPI2_RC_SUCCESS : \\\n"; + print AIFILE " fapi2::queryChipEcFeature(fapi2::int2Type(), PTARGET, VAL)\n"; + print AIFILE "#define $attr->{id}_SETMACRO(ID, PTARGET, VAL) "; + print AIFILE "CHIP_EC_FEATURE_ATTRIBUTE_NOT_WRITABLE\n"; + } + elsif (! exists $attr->{writeable}) + { + #------------------------------------------------------------------ + # The attribute is read-only, define the _SETMACRO to something + # that will cause a compile failure if a set is attempted + #------------------------------------------------------------------ + if (! exists $attr->{writeable}) + { + print AIFILE "#define $attr->{id}_SETMACRO ATTRIBUTE_NOT_WRITABLE\n"; + } + } + + #---------------------------------------------------------------------- + # If the attribute is a Chip EC Feature, print the chip EC feature + # query to fapi2_chip_ec_feature.H + #---------------------------------------------------------------------- + # Each EC attribute will generate a new inline overloaded version of + # hasFeature with the attribute specific logic + if (exists $attr->{chipEcFeature}) + { + my $chipCount = 0; + print ECHFILE " inline uint8_t hasFeature(int2Type<$attr->{id}>,\n"; + print ECHFILE " fapi2::ATTR_NAME_Type i_name,\n"; + print ECHFILE " fapi2::ATTR_EC_Type i_ec)\n"; + print ECHFILE " {\n"; + print ECHFILE " uint8_t hasFeature = 0;\n\n"; + print ECHFILE " if("; + + foreach my $chip (@{$attr->{chipEcFeature}->{chip}}) + { + if (! exists $chip->{name}) + { + print ("parseAttributeInfo.pl ERROR. Att 'name' missing\n"); + exit(1); + } + + if (! exists $chip->{ec}) + { + print ("parseAttributeInfo.pl ERROR. Att 'ec' missing\n"); + exit(1); + } + + if (! exists $chip->{ec}->{value}) + { + print ("parseAttributeInfo.pl ERROR. Att 'value' missing\n"); + exit(1); + } + + if (! exists $chip->{ec}->{test}) + { + print ("parseAttributeInfo.pl ERROR. Att 'test' missing\n"); + exit(1); + } + + if($chip->{name} eq 'ENUM_ATTR_NAME_CENTAUR') + { + # Skip Centaur chip + next; + } + + $chipCount++; + my $test; + if ($chip->{ec}->{test} eq 'EQUAL') + { + $test = '=='; + } + elsif ($chip->{ec}->{test} eq 'GREATER_THAN') + { + $test = '>'; + } + elsif ($chip->{ec}->{test} eq 'GREATER_THAN_OR_EQUAL') + { + $test = '>='; + } + elsif ($chip->{ec}->{test} eq 'LESS_THAN') + { + $test = '<'; + } + elsif ($chip->{ec}->{test} eq 'LESS_THAN_OR_EQUAL') + { + $test = '<='; + } + else + { + print ("parseAttributeInfo.pl ERROR. test '$chip->{ec}->{test}' unrecognized\n"); + exit(1); + } + + if ($chipCount > 1) + { + print ECHFILE " ||\n\t"; + } + print ECHFILE "((i_name == $chip->{name}) && "; + print ECHFILE " (i_ec $test $chip->{ec}->{value}))"; + } + print ECHFILE ")\n"; + print ECHFILE " {\n"; + print ECHFILE " hasFeature = 1;\n"; + print ECHFILE " }\n"; + print ECHFILE " return hasFeature;\n"; + print ECHFILE " };\n"; + } + + #---------------------------------------------------------------------- + # Print the platform attribute checks to fapiAttributePlatCheck.H + #---------------------------------------------------------------------- + if (exists $attr->{writeable}) + { + print ACFILE "#ifndef $attr->{id}_SETMACRO\n"; + print ACFILE "#error Platform does not support set of HWPF attr $attr->{id}\n"; + print ACFILE "#endif\n"; + } + + print ACFILE "#ifndef $attr->{id}_GETMACRO\n"; + print ACFILE "#error Platform does not support get of HWPF attr $attr->{id}\n"; + print ACFILE "#endif\n\n"; + + #---------------------------------------------------------------------- + # Print newline between each attribute's info to fapiAttributeIds.H + #---------------------------------------------------------------------- + print AIFILE "\n"; + + + + + + } + }; + } +} + +#------------------------------------------------------------------------------ +# Print End of file information to fapiAttributeIds.H +#------------------------------------------------------------------------------ +print AIFILE "} //fapi2 \n\n"; +print AIFILE "#endif // __ASSEMBLER__\n\n"; +print AIFILE "#endif\n"; + +print ECHFILE "}\n"; +print ECHFILE "#endif\n"; + + +#------------------------------------------------------------------------------ +# Print End of file information to fapiAttributePlatCheck.H +#------------------------------------------------------------------------------ +print ACFILE "#endif\n"; + +#------------------------------------------------------------------------------ +# Print End of file information to fapiAttributesSupported.html +#------------------------------------------------------------------------------ +print ASFILE "
Attribute IDAttribute Description
\n\n"; +print ASFILE "\n"; +print ASFILE "\n"; + + +#------------------------------------------------------------------------------ +# Close output files +#------------------------------------------------------------------------------ +close(AIFILE); +close(ECHFILE); +close(ACFILE); +close(ASFILE); +close(ITFILE); +close(ETFILE); diff --git a/src/tools/scripts/ppeParseProcSbeFixed.pl b/src/tools/scripts/ppeParseProcSbeFixed.pl new file mode 100755 index 00000000..4279ca3b --- /dev/null +++ b/src/tools/scripts/ppeParseProcSbeFixed.pl @@ -0,0 +1,318 @@ +#!/usr/bin/perl +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/tools/scripts/ppeParseProcSbeFixed.pl $ +# +# OpenPOWER sbe Project +# +# Contributors Listed Below - COPYRIGHT 2015,2016 +# +# +# 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 +# Purpose: This perl script will parse HWP Attribute XML files and +# initfile attr files and create the fapiGetInitFileAttr() function +# in a file called fapiAttributeService.C + +use strict; + +#------------------------------------------------------------------------------ +# Print Command Line Help +#------------------------------------------------------------------------------ +my $numArgs = $#ARGV + 1; +if ($numArgs < 3) +{ + print ("Usage: ppeParseProcSbeFixed.pl \n"); + print (" [ ...]\n"); + print (" -a [ ...]\n"); + print (" This perl script will parse if-attr files (containing the\n"); + print (" attributes used by the initfile) and attribute XML files\n"); + print (" (containing all HWPF attributes) and create the\n"); + print (" fapiGetInitFileAttr() function in a file called\n"); + print (" fapiAttributeService.C. Only the attributes specified in\n"); + print (" the if-attr files are supported. If no if-attr files are\n"); + print (" specified then all attributes are supported\n"); + exit(1); +} + +#------------------------------------------------------------------------------ +# Specify perl modules to use +#------------------------------------------------------------------------------ +use XML::Simple; +my $xml = new XML::Simple (KeyAttr=>[]); + +# Uncomment to enable debug output +#use Data::Dumper; + +#------------------------------------------------------------------------------ +# Open output file for writing +#------------------------------------------------------------------------------ +my $sysFile = $ARGV[0]; +$sysFile .= "/"; +$sysFile .= "proc_sbe_fixed_system.H"; +open(SYFILE, ">", $sysFile); + +my $chipFile = $ARGV[0]; +$chipFile .= "/"; +$chipFile .= "proc_sbe_fixed_proc_chip.H"; +open(CHFILE, ">", $chipFile); + +my $exFile = $ARGV[0]; +$exFile .= "/"; +$exFile .= "proc_sbe_fixed_ex.H"; +open(EXFILE, ">", $exFile); + +my $coreFile = $ARGV[0]; +$coreFile .= "/"; +$coreFile .= "proc_sbe_fixed_core.H"; +open(COFILE, ">", $coreFile); + +my $eqFile = $ARGV[0]; +$eqFile .= "/"; +$eqFile .= "proc_sbe_fixed_eq.H"; +open(EQFILE, ">", $eqFile); + +my $pervFile = $ARGV[0]; +$pervFile .= "/"; +$pervFile .= "proc_sbe_fixed_perv.H"; +open(PEFILE, ">", $pervFile); + + + +my $xmlFiles = 0; +my $attCount = 0; +my $numIfAttrFiles = 0; +my @attrSystemIds; +my @attrChipIds; +my @attrExIds; +my @attrCoreIds; +my @attrEqIds; +my @attrPervIds; + + + +#------------------------------------------------------------------------------ +# Element names +#------------------------------------------------------------------------------ +my $attribute = 'attribute'; + +#------------------------------------------------------------------------------ +# For each argument +#------------------------------------------------------------------------------ +my $argfile = $ARGV[1]; +my $entries = $xml->XMLin($argfile, ForceArray => ['entry']); +foreach my $entr (@{$entries->{entry}}) { + + my $inname = $entr->{name}; + + # Skip virtual attributes + if(exists $entr->{virtual}) + { + next; + } + + # 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 + + foreach my $argnum (2 .. $#ARGV) + { + my $infile = $ARGV[$argnum]; + + my $attributes = $xml->XMLin($infile, ForceArray => ['attribute']); + + # Uncomment to get debug output of all attributes + #print "\nFile: ", $infile, "\n", Dumper($attributes), "\n"; + + #-------------------------------------------------------------------------- + # For each Attribute + #-------------------------------------------------------------------------- + foreach my $attr (@{$attributes->{attribute}}) + { + + if($attr->{id} eq $inname) { + + #------------------------------------------------------------------ + # Check that the AttributeId exists + #------------------------------------------------------------------ + if (! exists $attr->{id}) + { + print ("fapiParseAttributeInfo.pl ERROR. Att 'id' missing\n"); + exit(1); + } + + my @targets = split(",", $attr->{targetType}); + my $targetTypeMatched = 0; + + foreach my $target (@targets) + { + + if ($target eq "TARGET_TYPE_SYSTEM") { + + push(@attrSystemIds, $attr); + $targetTypeMatched = 1; + last; + + } elsif ($target eq "TARGET_TYPE_PROC_CHIP") { + + push(@attrChipIds, $attr); + $targetTypeMatched = 1; + last; + + } elsif ($target eq "TARGET_TYPE_CORE") { + + push(@attrCoreIds, $attr); + $targetTypeMatched = 1; + last; + + } elsif ($target eq "TARGET_TYPE_EQ") { + + push(@attrEqIds, $attr); + $targetTypeMatched = 1; + last; + + } elsif ($target eq "TARGET_TYPE_EX") { + + push(@attrExIds, $attr); + $targetTypeMatched = 1; + last; + + } elsif ($target eq "TARGET_TYPE_PERV") { + + push(@attrPervIds, $attr); + $targetTypeMatched = 1; + last; + + } else { + + print ("ppeParseProcSbeFixed.pl WARNING. Unsupported ". + "target type: $target for attribute $inname in $infile\n"); + next; + + } + } + if($targetTypeMatched eq 0) + { + print ("ppeParseProcSbeFixed.pl ERROR. Unsupported ". + "target type: $attr->{targetType} for attribute $inname in $infile\n"); + exit(1); + } + } + } + } +} + + +print SYFILE "// proc_sbe_fixed_system.H\n"; +print SYFILE "// This file is generated by perl script ppeParseProcSbeFixed.pl\n\n"; +print SYFILE "#ifndef __PROC_SBE_FIXED_SYSTEM_H__\n"; +print SYFILE "#define __PROC_SBE_FIXED_SYSTEM_H__\n\n"; +foreach my $attr (@attrSystemIds) +{ + + my $value = uc $attr->{valueType}; + print SYFILE "PROC_SBE_FIXED_$value($attr->{id});\n" + + +} +print SYFILE "\n#endif // __PROC_SBE_FIXED_SYSTEM_H__"; + +print CHFILE "// proc_sbe_fixed_proc_chip.H\n"; +print CHFILE "// This file is generated by perl script ppeParseProcSbeFixed.pl\n\n"; +print CHFILE "#ifndef __PROC_SBE_FIXED_PROC_CHIP_H__\n"; +print CHFILE "#define __PROC_SBE_FIXED_PROC_CHIP_H__\n\n"; +foreach my $attr (@attrChipIds) +{ + + my $value = uc $attr->{valueType}; + print CHFILE "PROC_SBE_FIXED_$value($attr->{id});\n" + + +} +print CHFILE "\n#endif // __PROC_SBE_FIXED_PROC_CHIP_H__"; + +print EXFILE "// proc_sbe_fixed_ex.H\n"; +print EXFILE "// This file is generated by perl script ppeParseProcSbeFixed.pl\n\n"; +print EXFILE "#ifndef __PROC_SBE_FIXED_EX_H__\n"; +print EXFILE "#define __PROC_SBE_FIXED_EX_H__\n"; +foreach my $attr (@attrExIds) +{ + + my $value = uc $attr->{valueType}; + print EXFILE "PROC_SBE_FIXED_TARGET_$value($attr->{id}, EX_TARGET_COUNT);\n" + + +} +print EXFILE "\n#endif // __PROC_SBE_FIXED_EX_H__"; + + +print COFILE "// proc_sbe_fixed_co.H\n"; +print COFILE "// This file is generated by perl script ppeParseProcSbeFixed.pl\n\n"; +print COFILE "#ifndef __PROC_SBE_FIXED_CO_H__\n"; +print COFILE "#define __PROC_SBE_FIXED_CO_H__\n"; +foreach my $attr (@attrCoreIds) +{ + + my $value = uc $attr->{valueType}; + print COFILE "PROC_SBE_FIXED_TARGET_$value($attr->{id}, CORE_TARGET_COUNT);\n" + + +} +print COFILE "\n#endif // __PROC_SBE_FIXED_CO_H__"; + + + +print EQFILE "// proc_sbe_fixed_eq.H\n"; +print EQFILE "// This file is generated by perl script ppeParseProcSbeFixed.pl\n\n"; +print EQFILE "#ifndef __PROC_SBE_FIXED_EQ_H__\n"; +print EQFILE "#define __PROC_SBE_FIXED_EQ_H__\n"; +foreach my $attr (@attrEqIds) +{ + + my $value = uc $attr->{valueType}; + print EQFILE "PROC_SBE_FIXED_TARGET_$value($attr->{id}, EQ_TARGET_COUNT);\n" + + +} +print EQFILE "\n#endif // __PROC_SBE_FIXED_EQ_H__"; + + + +print PEFILE "// proc_sbe_fixed_perv.H\n"; +print PEFILE "// This file is generated by perl script ppeParseProcSbeFixed.pl\n\n"; +print PEFILE "#ifndef __PROC_SBE_FIXED_PERV_H__\n"; +print PEFILE "#define __PROC_SBE_FIXED_PERV_H__\n"; +foreach my $attr (@attrPervIds) +{ + + my $value = uc $attr->{valueType}; + print PEFILE "PROC_SBE_FIXED_TARGET_$value($attr->{id}, PERV_TARGET_COUNT);\n" + + +} +print PEFILE "\n#endif // __PROC_SBE_FIXED_PERV_H__"; + + +#print ASFILE "#endif // __PROC_SBE_FIXED_H__"; + + +#------------------------------------------------------------------------------ +# Close output file +#------------------------------------------------------------------------------ +close(CHFILE); +close(COFILE); +close(EXFILE); +close(PEFILE); +close(EQFILE); + diff --git a/src/tools/scripts/ppeSetFixed.pl b/src/tools/scripts/ppeSetFixed.pl new file mode 100755 index 00000000..ab92ec42 --- /dev/null +++ b/src/tools/scripts/ppeSetFixed.pl @@ -0,0 +1,259 @@ +#!/usr/bin/perl +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/tools/scripts/ppeSetFixed.pl $ +# +# OpenPOWER sbe Project +# +# Contributors Listed Below - COPYRIGHT 2015,2016 +# +# +# 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 +# Purpose: This perl script will parse the attribute and default list and +# and set the default values into the image. + +use strict; + +my $attrpath = "../../importtemp/xml"; +my $sbedefaultpath = "../../script/image"; + +#------------------------------------------------------------------------------ +# Print Command Line Help +#------------------------------------------------------------------------------ +my $numArgs = $#ARGV + 1; +if ($numArgs < 3) +{ + print ("Usage: ppeSetFixed.pl ...\n"); + print (" This perl script will the attributes and default list to lookup the defaults\n"); + print (" and parse the attribute file to lookup the types.\n"); + print (" The default values will be set in the image.\n"); + print ("example:\n"); + print ("./ppeSetFixed.pl \\\n" ); + print (". \\\n" ); + print (" ../../obj/seeprom_main.bin \\\n" ); + print ("$attrpath/p9_ppe_attributes.xml \\\n" ); + print ("$attrpath/attribute_info/perv_attributes.xml \\\n" ); + print ("$attrpath/attribute_info/proc_attributes.xml \\\n" ); + print ("$attrpath/attribute_info/ex_attributes.xml \\\n" ); + print ("$attrpath/attribute_info/eq_attributes.xml \\\n" ); + print ("$attrpath/attribute_info/core_attributes.xml \\ \n"); + print ("$attrpath/attribute_info/nest_attributes.xml \n"); + exit(1); +} + +#------------------------------------------------------------------------------ +# Specify perl modules to use +#------------------------------------------------------------------------------ +use XML::Simple; +my $xml = new XML::Simple (KeyAttr=>[]); + + +my $xmlFiles = 0; +my $attCount = 0; +my $numIfAttrFiles = 0; +my @attrSystemIds; +my @attrChipIds; +my @attrExIds; +my @attrCoreIds; +my @attrEqIds; +my @attrPervIds; + + + +#------------------------------------------------------------------------------ +# Element names +#------------------------------------------------------------------------------ +my $attribute = 'attribute'; + +#------------------------------------------------------------------------------ +# For each argument +#------------------------------------------------------------------------------ +my $sbedefaultpath = $ARGV[0]; +my $image = $ARGV[1]; +my $argfile = $ARGV[2]; +my $entries = $xml->XMLin($argfile, ForceArray => ['entry']); + +if ( ! -e $image) {die "ppeSetFixed.pl: $image $!"}; + +foreach my $entr (@{$entries->{entry}}) { + + # Skip virtual attributes + if(exists $entr->{virtual}) + { + next; + } + + my $inname = $entr->{name}; + + # 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 + + foreach my $argnum (3 .. $#ARGV) + { + my $infile = $ARGV[$argnum]; + + if ( ! -e $infile) {die "ppeSetFixed.pl: $infile $!"}; + + my $attributes = $xml->XMLin($infile, ForceArray => ['attribute']); + + #-------------------------------------------------------------------------- + # For each Attribute + #-------------------------------------------------------------------------- + foreach my $attr (@{$attributes->{attribute}}) + { + if($attr->{id} eq $inname) { + + #------------------------------------------------------------------ + # Check that the AttributeId exists + #------------------------------------------------------------------ + if (! exists $attr->{id}) + { + print ("ppeSbeFixed.pl ERROR. Att 'id' missing\n"); + exit(1); + } + + my @targets = split(",", $attr->{targetType}); + + my $targetTypeMatched = 0; + + foreach my $target (@targets) + { + if($target eq "TARGET_TYPE_SYSTEM") { + + push(@attrSystemIds, $entr); + $targetTypeMatched = 1; + last; + + } elsif($target eq "TARGET_TYPE_PROC_CHIP") { + + push(@attrChipIds, $entr); + $targetTypeMatched = 1; + last; + + } elsif($target eq "TARGET_TYPE_CORE") { + + push(@attrCoreIds, $entr); + $targetTypeMatched = 1; + last; + + } elsif($target eq "TARGET_TYPE_EQ") { + + push(@attrEqIds, $entr); + $targetTypeMatched = 1; + last; + + } elsif($target eq "TARGET_TYPE_EX") { + + push(@attrExIds, $entr); + $targetTypeMatched = 1; + last; + + } elsif($target eq "TARGET_TYPE_PERV") { + + push(@attrPervIds, $entr); + $targetTypeMatched = 1; + last; + + } else { + + print ("ppeSetFixed.pl WARNING. Ignoring unsupported". + " target type: $target for attribute: $inname\n"); + next; + + } + } + if($targetTypeMatched eq 0) + { + print ("ppeSetFixed.pl ERROR. No matching target type ". + "found for attribute: $inname\n"); + exit(1); + } + + } + } + } +} + + +setFixed("TARGET_TYPE_SYSTEM", @attrSystemIds); +setFixed("TARGET_TYPE_PROC_CHIP", @attrChipIds); +setFixed("TARGET_TYPE_CORE", @attrCoreIds); +setFixed("TARGET_TYPE_EQ", @attrEqIds); +setFixed("TARGET_TYPE_EX", @attrExIds); +setFixed("TARGET_TYPE_PERV", @attrPervIds); + + + +sub setFixed { + + my ($string, @entries) = @_; + + foreach my $attr (@entries) + { + + my $inname = $attr->{name}; + + my @values = $attr->{value}; + + + if(scalar @values > 0) { + foreach my $val (@values) + { + + if(defined $val && ref($val) eq "") { + + if ($val =~ /(0x)?[0-9a-fA-F]+/) { + + my $systemRc = system("$sbedefaultpath/sbe_default_tool $image $inname $val $string 0"); + + if ($systemRc) { + print "sbe_default_tool: error in execution\n"; + exit 1; + } + + } else { + print ("ppeSetFixed.pl ERROR. not hex\n"); + exit(1); + } + + } elsif(defined $val && ref($val) eq "ARRAY") { + + my $index = 0; + + foreach my $arr (@{$val}) { + + if(defined $arr && ref($arr) eq "") { + if ($arr =~ /(0x)?[0-9a-fA-F]+/) { + + my $systemRc = system("$sbedefaultpath/sbe_default_tool $image $inname $arr $string $index"); + + if ($systemRc) { + print "sbe_default_tool: error in execution\n"; + exit 1; + } + + + } + } + $index++; + } + } + } + } + } +} + + diff --git a/src/tools/scripts/src/fapi2PlatAttributeService.H b/src/tools/scripts/src/fapi2PlatAttributeService.H new file mode 100644 index 00000000..7c992d65 --- /dev/null +++ b/src/tools/scripts/src/fapi2PlatAttributeService.H @@ -0,0 +1,1416 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/tools/scripts/src/fapi2PlatAttributeService.H $ */ +/* */ +/* OpenPOWER sbe Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015,2016 */ +/* */ +/* */ +/* 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 fapiPlatAttributeService.H + * + * @brief Defines the PLAT attribute access macros and defines which macro + * handles each attribute. + * + */ + + +#ifndef FAPI2PLATATTRIBUTESERVICE_H_ +#define FAPI2PLATATTRIBUTESERVICE_H_ + +#include +#include +#include +#include +#include +#include +#include "proc_sbe_fixed.H" +#include "plat_target_parms.H" + +#define PLAT_GET_CHIP_EC_FEATURE_OVERRIDE(ID, PTARGET, VAL) \ + _getEcFeatureOverride(ID, PTARGET, VAL) + +/* INSERT NEW ATTRIBUTES HERE */ + + +/******************************************************************************/ +/* * Global macros * */ +/* These macros are called by the macros above to invoke the appropriate API. */ +/* These macros do not need to change when a new attribute is introduced. */ +/******************************************************************************/ + +/* global get uint8_t 1D array macro */ +#define PLAT_ATTR_GET_UINT8_1D_ARRAY(ID, PTARGET, VAL) \ + _getAttributeArrayShort(ID##_TargetTypes), ID> \ + (ID, PTARGET, VAL) + +/* global set uint8_t 1D array macro */ +#define PLAT_ATTR_SET_UINT8_1D_ARRAY(ID, PTARGET, VAL) \ + _setAttributeArrayShort(ID##_TargetTypes), ID> \ + (ID, PTARGET, VAL) + +/* global get uint8_t 2D array macro */ +#define PLAT_ATTR_GET_UINT8_2D_ARRAY(ID, PTARGET, VAL) \ + _getAttributeArrayShort(ID, PTARGET, VAL[0]) +/* global set uint8_t 2D array macro */ +#define PLAT_ATTR_SET_UINT8_2D_ARRAY(ID, PTARGET, VAL) \ + _setAttributeArrayShort(ID, PTARGET, VAL[0]) + +/* global get uint8_t 3D array macro */ +#define PLAT_ATTR_GET_UINT8_3D_ARRAY(ID, PTARGET, VAL) \ + _getAttributeArrayShort(ID, PTARGET, VAL[0][0]) +/* global set uint8_t 3D array macro */ +#define PLAT_ATTR_SET_UINT8_3D_ARRAY(ID, PTARGET, VAL) \ + _setAttributeArrayShort(ID, PTARGET, VAL[0][0]) + +/* global get uint8_t 4D array macro */ +#define PLAT_ATTR_GET_UINT8_4D_ARRAY(ID, PTARGET, VAL) \ + _getAttributeArrayShort(ID, PTARGET, VAL[0][0][0]) +/* global set uint8_t 4D array macro */ +#define PLAT_ATTR_SET_UINT8_4D_ARRAY(ID, PTARGET, VAL) \ + _setAttributeArrayShort(ID, PTARGET, VAL[0][0][0]) + +/* global get uint32_t 1D array macro */ +#define PLAT_ATTR_GET_UINT32_1D_ARRAY(ID, PTARGET, VAL) \ + _getAttributeArrayWord(ID, PTARGET, VAL) +/* global set uint32_t 1D array macro */ +#define PLAT_ATTR_SET_UINT32_1D_ARRAY(ID, PTARGET, VAL) \ + _setAttributeArrayWord(ID, PTARGET, VAL) + +/* global get uint32_t 2D array macro */ +#define PLAT_ATTR_GET_UINT32_2D_ARRAY(ID, PTARGET, VAL) \ + _getAttributeArrayWord(ID, PTARGET, VAL[0]) +/* global set uint32_t 2D array macro */ +#define PLAT_ATTR_SET_UINT32_2D_ARRAY(ID, PTARGET, VAL) \ + _setAttributeArrayWord(ID, PTARGET, VAL[0]) + +/* global get uint32_t 3D array macro */ +#define PLAT_ATTR_GET_UINT32_3D_ARRAY(ID, PTARGET, VAL) \ + _getAttributeArrayWord(ID, PTARGET, VAL[0][0]) +/* global set uint32_t 3D array macro */ +#define PLAT_ATTR_SET_UINT32_3D_ARRAY(ID, PTARGET, VAL) \ + _setAttributeArrayWord(ID, PTARGET, VAL[0][0]) + +/* global get uint32_t 4D array macro */ +#define PLAT_ATTR_GET_UINT32_4D_ARRAY(ID, PTARGET, VAL) \ + _getAttributeArrayWord(ID, PTARGET, VAL[0][0][0]) +/* global set uint32_t 4D array macro */ +#define PLAT_ATTR_SET_UINT32_4D_ARRAY(ID, PTARGET, VAL) \ + _setAttributeArrayWord(ID, PTARGET, VAL[0][0][0]) + + +/* global get uint64_t 1D array macro */ +#define PLAT_ATTR_GET_UINT64_1D_ARRAY(ID, PTARGET, VAL) \ + _getAttributeArrayDoubleWord(ID, PTARGET, VAL) +/* global set uint64_t 1D array macro */ +#define PLAT_ATTR_SET_UINT64_1D_ARRAY(ID, PTARGET, VAL) \ + _setAttributeArrayDoubleWord(ID, PTARGET, VAL) + +/* global get uint64_t 2D array macro */ +#define PLAT_ATTR_GET_UINT64_2D_ARRAY(ID, PTARGET, VAL) \ + _getAttributeArrayDoubleWord(ID, PTARGET, VAL[0]) +/* global set uint64_t 2D array macro */ +#define PLAT_ATTR_SET_UINT64_2D_ARRAY(ID, PTARGET, VAL) \ + _setAttributeArrayDoubleWord(ID, PTARGET, VAL[0]) + +/* global get uint64_t 3D array macro */ +#define PLAT_ATTR_GET_UINT64_3D_ARRAY(ID, PTARGET, VAL) \ + _getAttributeArrayDoubleWord(ID, PTARGET, VAL[0][0]) +/* global set uint64_t 3D array macro */ +#define PLAT_ATTR_SET_UINT64_3D_ARRAY(ID, PTARGET, VAL) \ + _setAttributeArrayDoubleWord(ID, PTARGET, VAL[0][0]) + +/* global get uint64_t 4D array macro */ +#define PLAT_ATTR_GET_UINT64_4D_ARRAY(ID, PTARGET, VAL) \ + _getAttributeArrayDoubleWord(ID, PTARGET, VAL[0][0][0]) +/* global set uint64_t 4D array macro */ +#define PLAT_ATTR_SET_UINT64_4D_ARRAY(ID, PTARGET, VAL) \ + _setAttributeArrayDoubleWord(ID, PTARGET, VAL[0][0][0]) + +/* global get int macro (uint8_t, 16, 32 and 64) */ +#define PLAT_ATTR_GET_GLOBAL_INT(ID, PTARGET, VAL) \ + _get(ID##_TargetTypes), ID> \ + (ID, PTARGET, VAL) + +/* global set int macro (uint8_t, 16, 32 and 64) */ +#define PLAT_ATTR_SET_GLOBAL_INT(ID, PTARGET, VAL) \ + _set(ID##_TargetTypes), ID> \ + (ID, PTARGET, VAL) + + +//here + +/******************************************************************************/ +// Get Override Macros +/******************************************************************************/ +/* global get override uint8_t 1D array macro */ +#define PLAT_ATTR_GET_OVERRIDE_UINT8_1D_ARRAY(ID, PTARGET, VAL) \ + _getAttributeOverrideArrayShort(ID, PTARGET, VAL) +/* global get override uint8_t 2D array macro */ +#define PLAT_ATTR_GET_OVERRIDE_UINT8_2D_ARRAY(ID, PTARGET, VAL) \ + _getAttributeOverrideArrayShort(ID, PTARGET, VAL[0]) +/* global get override uint8_t 3D array macro */ +#define PLAT_ATTR_GET_OVERRIDE_UINT8_3D_ARRAY(ID, PTARGET, VAL) \ + _getAttributeOverrideArrayShort(ID, PTARGET, VAL[0][0]) +/* global get override uint8_t 4D array macro */ +#define PLAT_ATTR_GET_OVERRIDE_UINT8_4D_ARRAY(ID, PTARGET, VAL) \ + _getAttributeOverrideArrayShort(ID, PTARGET, VAL[0][0][0]) + + +/* global get override uint32_t 1D array macro */ +#define PLAT_ATTR_GET_OVERRIDE_UINT32_1D_ARRAY(ID, PTARGET, VAL) \ + _getAttributeOverrideArrayWord(ID, PTARGET, VAL) +/* global get override uint32_t 2D array macro */ +#define PLAT_ATTR_GET_OVERRIDE_UINT32_2D_ARRAY(ID, PTARGET, VAL) \ + _getAttributeOverrideArrayWord(ID, PTARGET, VAL[0]) +/* global get override uint32_t 3D array macro */ +#define PLAT_ATTR_GET_OVERRIDE_UINT32_3D_ARRAY(ID, PTARGET, VAL) \ + _getAttributeOverrideArrayWord(ID, PTARGET, VAL[0][0]) +/* global get override uint32_t 4D array macro */ +#define PLAT_ATTR_GET_OVERRIDE_UINT32_4D_ARRAY(ID, PTARGET, VAL) \ + _getAttributeOverrideArrayWord(ID, PTARGET, VAL[0][0][0]) + + +/* global get override uint64_t 1D array macro */ +#define PLAT_ATTR_GET_OVERRIDE_UINT64_1D_ARRAY(ID, PTARGET, VAL) \ + _getAttributeOverrideArrayDoubleWord(ID, PTARGET, VAL) +/* global get override uint64_t 2D array macro */ +#define PLAT_ATTR_GET_OVERRIDE_UINT64_2D_ARRAY(ID, PTARGET, VAL) \ + _getAttributeOverrideArrayDoubleWord(ID, PTARGET, VAL[0]) +/* global get override uint64_t 3D array macro */ +#define PLAT_ATTR_GET_OVERRIDE_UINT64_3D_ARRAY(ID, PTARGET, VAL) \ + _getAttributeOverrideArrayDoubleWord(ID, PTARGET, VAL[0][0]) +/* global get override uint64_t 4D array macro */ +#define PLAT_ATTR_GET_OVERRIDE_UINT64_4D_ARRAY(ID, PTARGET, VAL) \ + _getAttributeOverrideArrayDoubleWord(ID, PTARGET, VAL[0][0][0]) + +/* global get override int macro (uint8_t, 32 and 64) */ +#define PLAT_ATTR_GET_OVERRIDE_GLOBAL_INT(ID, PTARGET, VAL) \ + _getOverride(ID, PTARGET, VAL) + +/******************************************************************************/ +// Get string +/******************************************************************************/ + +extern "C" +{ + extern fapi2attr::SystemAttributes_t G_system_attributes asm("G_system_attributes") __attribute__ ((section (".fixed"))); + extern fapi2attr::ProcChipAttributes_t G_proc_chip_attributes asm("G_proc_chip_attributes") __attribute__ ((section (".fixed"))); + extern fapi2attr::PervAttributes_t G_perv_attributes asm("G_perv_attributes") __attribute__ ((section (".fixed"))); + extern fapi2attr::CoreAttributes_t G_core_attributes asm("G_core_attributes") __attribute__ ((section (".fixed"))); + extern fapi2attr::EQAttributes_t G_eq_attributes asm("G_eq_attributes") __attribute__ ((section (".fixed"))); + extern fapi2attr::EXAttributes_t G_ex_attributes asm("G_ex_attributes") __attribute__ ((section (".fixed"))); + + extern fapi2attr::SystemAttributes_t* G_system_attributes_ptr; + extern fapi2attr::ProcChipAttributes_t* G_proc_chip_attributes_ptr; + extern fapi2attr::PervAttributes_t* G_perv_attributes_ptr; + extern fapi2attr::CoreAttributes_t* G_core_attributes_ptr; + extern fapi2attr::EQAttributes_t* G_eq_attributes_ptr; + extern fapi2attr::EXAttributes_t* G_ex_attributes_ptr; + +} + +namespace fapi2 +{ + + +// Parameters are done as pointers (vs references) to allow the attribute +// storage to be relocated +template +void __set( const Target& i_ptarget, TAttrStruct* object, const AttributeId attrid, const TValue& value ); + +template +void __get( const Target& i_ptarget, const TAttrStruct* object, const AttributeId attrid, TValue* value ); + + +/* INSERT NEW GETTER AND SETTER FUNCTIONS HERE */ + + + +//****************************************************************************** +// Get base template +//****************************************************************************** +template +ReturnCode _get(const AttributeId i_id, + const Target & i_pTarget, + T& o_value) +{ + return FAPI2_RC_SUCCESS; +} + +//****************************************************************************** +// Get uint8_t +//****************************************************************************** +template +ReturnCode _get(const AttributeId i_id, + const Target & i_pTarget, + uint8_t& o_value) +{ + static_assert(std::is_same::value, "Attribute type mismatch"); + + if(K & TARGET_TYPE_SYSTEM) + { + __get( i_pTarget, G_system_attributes_ptr, i_id, &o_value ); + } + + if(K & TARGET_TYPE_PROC_CHIP) + { + __get( i_pTarget, G_proc_chip_attributes_ptr, i_id, &o_value ); + } + + if(K & TARGET_TYPE_PERV) + { + __get( i_pTarget, G_perv_attributes_ptr, i_id, &o_value ); + } + + if(K & TARGET_TYPE_CORE) + { + __get( i_pTarget, G_core_attributes_ptr, i_id, &o_value ); + } + + if(K & TARGET_TYPE_EQ) + { + __get( i_pTarget, G_eq_attributes_ptr, i_id, &o_value ); + } + + if(K & TARGET_TYPE_EX) + { + __get( i_pTarget, G_ex_attributes_ptr, i_id, &o_value ); + } + + return FAPI2_RC_SUCCESS; +} + +//****************************************************************************** +// Get uint16_t +//****************************************************************************** +template +ReturnCode _get(const AttributeId i_id, + const Target & i_pTarget, + uint16_t& o_value) +{ + static_assert(std::is_same::value, "Attribute type mismatch"); + + if(K & TARGET_TYPE_SYSTEM) + { + __get( i_pTarget, G_system_attributes_ptr, i_id, &o_value ); + } + + if(K & TARGET_TYPE_PROC_CHIP) + { + __get( i_pTarget, G_proc_chip_attributes_ptr, i_id, &o_value ); + } + + if(K & TARGET_TYPE_PERV) + { + __get( i_pTarget, G_perv_attributes_ptr, i_id, &o_value ); + } + + if(K & TARGET_TYPE_CORE) + { + __get( i_pTarget, G_core_attributes_ptr, i_id, &o_value ); + } + + if(K & TARGET_TYPE_EQ) + { + __get( i_pTarget, G_eq_attributes_ptr, i_id, &o_value ); + } + + if(K & TARGET_TYPE_EX) + { + __get( i_pTarget, G_ex_attributes_ptr, i_id, &o_value ); + } + + return FAPI2_RC_SUCCESS; +} + + +//****************************************************************************** +// Get uint32_t +//****************************************************************************** +template +ReturnCode _get(const AttributeId i_id, + const Target & i_pTarget, + uint32_t& o_value) +{ + static_assert(std::is_same::value, "Attribute type mismatch"); + + if(K & TARGET_TYPE_SYSTEM) + { + __get( i_pTarget, G_system_attributes_ptr, i_id, &o_value ); + } + + if(K & TARGET_TYPE_PROC_CHIP) + { + __get( i_pTarget, G_proc_chip_attributes_ptr, i_id, &o_value ); + } + + if(K & TARGET_TYPE_PERV) + { + __get( i_pTarget, G_perv_attributes_ptr, i_id, &o_value ); + } + + if(K & TARGET_TYPE_CORE) + { + __get( i_pTarget, G_core_attributes_ptr, i_id, &o_value ); + } + + if(K & TARGET_TYPE_EQ) + { + __get( i_pTarget, G_eq_attributes_ptr, i_id, &o_value ); + } + + if(K & TARGET_TYPE_EX) + { + __get( i_pTarget, G_ex_attributes_ptr, i_id, &o_value ); + } + + return FAPI2_RC_SUCCESS; +} + + +//****************************************************************************** +// Get uint64_t +//****************************************************************************** +template +ReturnCode _get(const AttributeId i_id, + const Target & i_pTarget, + uint64_t& o_value) +{ + static_assert(std::is_same::value, "Attribute type mismatch"); + + if(K & TARGET_TYPE_SYSTEM) + { + __get( i_pTarget, G_system_attributes_ptr, i_id, &o_value ); + } + + if(K & TARGET_TYPE_PROC_CHIP) + { + __get( i_pTarget, G_proc_chip_attributes_ptr, i_id, &o_value ); + } + + if(K & TARGET_TYPE_PERV) + { + __get( i_pTarget, G_perv_attributes_ptr, i_id, &o_value ); + } + + if(K & TARGET_TYPE_CORE) + { + __get( i_pTarget, G_core_attributes_ptr, i_id, &o_value ); + } + + if(K & TARGET_TYPE_EQ) + { + __get( i_pTarget, G_eq_attributes_ptr, i_id, &o_value ); + } + + if(K & TARGET_TYPE_EX) + { + __get( i_pTarget, G_ex_attributes_ptr, i_id, &o_value ); + } + + return FAPI2_RC_SUCCESS; +} + + +//****************************************************************************** +// Get Override uint8_t +//****************************************************************************** +template +ReturnCode _getOverride(const AttributeId i_id, + const Target & i_pTarget, + uint8_t& o_value) +{ + static_assert(std::is_same::value, "Attribute type mismatch"); + + return FAPI2_RC_SUCCESS; +} + + +//****************************************************************************** +// Get Override uint16_t +//****************************************************************************** +template +ReturnCode _getOverride(const AttributeId i_id, + const Target & i_pTarget, + uint16_t& o_value) +{ + static_assert(std::is_same::value, "Attribute type mismatch"); + + return FAPI2_RC_SUCCESS; +} + + +//****************************************************************************** +// Get Override uint32_t +//****************************************************************************** +template +ReturnCode _getOverride(const AttributeId i_id, + const Target & i_pTarget, + uint32_t& o_value) +{ + static_assert(std::is_same::value, "Attribute type mismatch"); + + return FAPI2_RC_SUCCESS; +} + + +//****************************************************************************** +// Get Override uint64_t +//****************************************************************************** +template +ReturnCode _getOverride(const AttributeId i_id, + const Target & i_pTarget, + uint64_t& o_value) +{ + static_assert(std::is_same::value, "Attribute type mismatch"); + + return FAPI2_RC_SUCCESS; +} + + +//****************************************************************************** +// Get override EC Feature (uint8_t) +//****************************************************************************** +template +ReturnCode _getEcFeatureOverride(const AttributeId i_id, + const Target & i_pTarget, + uint8_t& o_value) +{ + static_assert(std::is_same::value, "Attribute type mismatch"); + + // The way this is implemented, we want to return a non-zero return code if we found an override. + // Return 0 if there was an error. + // This is how it's implemented: + // PLAT_GET_CHIP_EC_FEATURE_OVERRIDE(ID, PTARGET, VAL) ? fapi::FAPI_RC_SUCCESS : fapi::fapiQueryChipEcFeature(fapi::ID, PTARGET, VAL) + + return FAPI2_RC_SUCCESS; +} + + +//****************************************************************************** +// Get uint8_t array +//****************************************************************************** +template +ReturnCode _getAttributeArrayShort(const AttributeId i_id, + const Target & i_pTarget, + uint8_t * o_pValues) +{ +// fapi2::Attributeta o_data; +// fapi2::ReturnCode l_fapi_rc(FAPI2_RC_SUCCESS); +// uint32_t l_ecmd_rc = ECMD_SUCCESS; +// +// ecmdChipTarget l_ecmd_target; +// fapiTargetPointerToEcmdTarget(i_pTarget, l_ecmd_target); +// +// o_data.faValidMask = FAPI_ATTRIBUTE_TYPE_UINT8ARY; +// o_data.faUint8ary = o_pValues; +// +// l_ecmd_rc = fapi2GetAttribute(l_ecmd_target, i_id, o_data); +// if (l_ecmd_rc) +// { +// l_fapi_rc = (ReturnCodes) l_ecmd_rc; +// } +// return l_fapi_rc; + return FAPI2_RC_SUCCESS; +} + +//****************************************************************************** +// Set uint8_t array +//****************************************************************************** +template +ReturnCode _setAttributeArrayShort(const AttributeId i_id, + const Target & i_pTarget, + uint8_t * i_pValues) +{ + if(K & TARGET_TYPE_SYSTEM) + { + __set( i_pTarget, G_system_attributes_ptr, i_id, *i_pValues ); + } + + if(K & TARGET_TYPE_PROC_CHIP) + { + __set( i_pTarget, G_proc_chip_attributes_ptr, *i_pValues ); + } + + if(K & TARGET_TYPE_PERV) + { + __set( i_pTarget, G_perv_attributes_ptr, *i_pValues ); + } + + if(K & TARGET_TYPE_CORE) + { + __set( i_pTarget, G_core_attributes_ptr, *i_pValues ); + } + + if(K & TARGET_TYPE_EQ) + { + __set( i_pTarget, G_eq_attributes_ptr, *i_pValues ); + } + + if(K & TARGET_TYPE_EX) + { + __set( i_pTarget, G_ex_attributes_ptr, *i_pValues ); + } + + return FAPI2_RC_SUCCESS; +} + +//****************************************************************************** +// Get uint16_t array +//****************************************************************************** +template +ReturnCode _getAttributeArrayWord(const AttributeId i_id, + const Target & i_pTarget, + uint16_t * o_pValues) +{ + return FAPI2_RC_SUCCESS; +} + +//****************************************************************************** +// Set uint16_t array +//****************************************************************************** +template +ReturnCode _setAttributeArrayWord(const AttributeId i_id, + const Target & i_pTarget, + uint16_t * i_pValues) +{ + return FAPI2_RC_SUCCESS; +} + +//****************************************************************************** +// Get uint32_t array +//****************************************************************************** +template +ReturnCode _getAttributeArrayWord(const AttributeId i_id, + const Target & i_pTarget, + uint32_t * o_pValues) +{ + return FAPI2_RC_SUCCESS; +} + +//****************************************************************************** +// Set uint32_t array +//****************************************************************************** +template +ReturnCode _setAttributeArrayWord(const AttributeId i_id, + const Target & i_pTarget, + uint32_t * i_pValues) +{ + return FAPI2_RC_SUCCESS; +} + + +//****************************************************************************** +// Get uint64_t array +//****************************************************************************** +template +ReturnCode _getAttributeArrayDoubleWord(const AttributeId i_id, + const Target & i_pTarget, + uint64_t * o_pValues) +{ + return FAPI2_RC_SUCCESS; +} + +//****************************************************************************** +// Set uint64_t array +//****************************************************************************** +template +ReturnCode _setAttributeArrayDoubleWord(const AttributeId i_id, + const Target & i_pTarget, + uint64_t * i_pValues) +{ + return FAPI2_RC_SUCCESS; +} + +//****************************************************************************** +// Get Override uint8_t array +//****************************************************************************** +template +ReturnCode _getAttributeOverrideArrayShort(const AttributeId i_id, + const Target & i_pTarget, + uint8_t * o_pValues) +{ + return FAPI2_RC_SUCCESS; +} + +//****************************************************************************** +// Get Override uint16_t array +//****************************************************************************** +template +ReturnCode _getAttributeOverrideArrayWord(const AttributeId i_id, + const Target & i_pTarget, + uint16_t * o_pValues) +{ + return FAPI2_RC_SUCCESS; +} + +//****************************************************************************** +// Get Override uint32_t array +//****************************************************************************** +template +ReturnCode _getAttributeOverrideArrayWord(const AttributeId i_id, + const Target & i_pTarget, + uint32_t * o_pValues) +{ + return FAPI2_RC_SUCCESS; +} + +//****************************************************************************** +// Get Override uint64_t array +//****************************************************************************** +template +ReturnCode _getAttributeOverrideArrayDoubleWord(const AttributeId i_id, + const Target & i_pTarget, + uint64_t * o_pValues) +{ + return FAPI2_RC_SUCCESS; +} + + +//****************************************************************************** +// Set base template +//****************************************************************************** +template +ReturnCode _set(const AttributeId i_id, + const Target & i_pTarget, + const T& i_value) +{ + return FAPI2_RC_SUCCESS; +} + + + +//****************************************************************************** +// Set uint8_t +//****************************************************************************** +template +ReturnCode _set(const AttributeId i_id, + const Target & i_pTarget, + const uint8_t& i_value) +{ + static_assert(std::is_same::value, "Attribute type mismatch"); // May need to remove + + if(K & TARGET_TYPE_SYSTEM) + { + __set( i_pTarget, G_system_attributes_ptr, i_id, i_value ); + } + + if(K & TARGET_TYPE_PROC_CHIP) + { + __set( i_pTarget, G_proc_chip_attributes_ptr, i_id, i_value ); + } + + if(K & TARGET_TYPE_PERV) + { + __set( i_pTarget, G_perv_attributes_ptr, i_id, i_value ); + } + + if(K & TARGET_TYPE_CORE) + { + __set( i_pTarget, G_core_attributes_ptr, i_id, i_value ); + } + + if(K & TARGET_TYPE_EQ) + { + __set( i_pTarget, G_eq_attributes_ptr, i_id, i_value ); + } + + if(K & TARGET_TYPE_EX) + { + __set( i_pTarget, G_ex_attributes_ptr, i_id, i_value ); + } + + return FAPI2_RC_SUCCESS; +} + + +//****************************************************************************** +// Set uint16_t +//****************************************************************************** +template +ReturnCode _set(const AttributeId i_id, + const Target & i_pTarget, + const uint16_t& i_value) +{ + static_assert(std::is_same::value, "Attribute type mismatch"); // May need to remove + + if(K & TARGET_TYPE_SYSTEM) + { + __set( i_pTarget, G_system_attributes_ptr, i_id, i_value ); + } + + if(K & TARGET_TYPE_PROC_CHIP) + { + __set( i_pTarget, G_proc_chip_attributes_ptr, i_id, i_value ); + } + + if(K & TARGET_TYPE_PERV) + { + __set( i_pTarget, G_perv_attributes_ptr, i_id, i_value ); + } + + if(K & TARGET_TYPE_CORE) + { + __set( i_pTarget, G_core_attributes_ptr, i_id, i_value ); + } + + if(K & TARGET_TYPE_EQ) + { + __set( i_pTarget, G_eq_attributes_ptr, i_id, i_value ); + } + + if(K & TARGET_TYPE_EX) + { + __set( i_pTarget, G_ex_attributes_ptr, i_id, i_value ); + } + + return FAPI2_RC_SUCCESS; +} + +//****************************************************************************** +// Set uint32_t +//****************************************************************************** +template +ReturnCode _set(const AttributeId i_id, + const Target & i_pTarget, + const uint32_t& i_value) +{ + static_assert(std::is_same::value, "Attribute type mismatch"); // May need to remove + + if(K & TARGET_TYPE_SYSTEM) + { + __set( i_pTarget, G_system_attributes_ptr, i_id, i_value ); + } + + if(K & TARGET_TYPE_PROC_CHIP) + { + __set( i_pTarget, G_proc_chip_attributes_ptr, i_id, i_value ); + } + + if(K & TARGET_TYPE_PERV) + { + __set( i_pTarget, G_perv_attributes_ptr, i_id, i_value ); + } + + if(K & TARGET_TYPE_CORE) + { + __set( i_pTarget, G_core_attributes_ptr, i_id, i_value ); + } + + if(K & TARGET_TYPE_EQ) + { + __set( i_pTarget, G_eq_attributes_ptr, i_id,i_value ); + } + + if(K & TARGET_TYPE_EX) + { + __set( i_pTarget, G_ex_attributes_ptr, i_id, i_value ); + } + + return FAPI2_RC_SUCCESS; +} + + +//****************************************************************************** +// Set uint64_t +//****************************************************************************** + +template +ReturnCode _set(const AttributeId i_id, + const Target & i_pTarget, + const uint64_t & i_value) +{ + static_assert(std::is_same::value, "Attribute type mismatch"); // May need to remove + + if(K & TARGET_TYPE_SYSTEM) + { + __set( i_pTarget, G_system_attributes_ptr, i_id, i_value ); + } + + if(K & TARGET_TYPE_PROC_CHIP) + { + __set( i_pTarget, G_proc_chip_attributes_ptr, i_id, i_value ); + } + + if(K & TARGET_TYPE_PERV) + { + __set( i_pTarget, G_perv_attributes_ptr, i_id, i_value ); + } + + if(K & TARGET_TYPE_CORE) + { + __set( i_pTarget, G_core_attributes_ptr, i_id, i_value ); + } + + if(K & TARGET_TYPE_EQ) + { + __set( i_pTarget, G_eq_attributes_ptr, i_id, i_value ); + } + + if(K & TARGET_TYPE_EX) + { + __set( i_pTarget, G_ex_attributes_ptr, i_id, i_value ); + } + + return FAPI2_RC_SUCCESS; +} + + +//****************************************************************************** +// Get int8_t +//****************************************************************************** +template +ReturnCode _get(const AttributeId i_id, + const Target & i_pTarget, + int8_t& o_value) +{ + static_assert(std::is_same::value, "Attribute type mismatch"); + + if(K & TARGET_TYPE_SYSTEM) + { + __get( i_pTarget, G_system_attributes_ptr, i_id, &o_value ); + } + + if(K & TARGET_TYPE_PROC_CHIP) + { + __get( i_pTarget, G_proc_chip_attributes_ptr, i_id, &o_value ); + } + + if(K & TARGET_TYPE_PERV) + { + __get( i_pTarget, G_perv_attributes_ptr, i_id, &o_value ); + } + + if(K & TARGET_TYPE_CORE) + { + __get( i_pTarget, G_core_attributes_ptr, i_id, &o_value ); + } + + if(K & TARGET_TYPE_EQ) + { + __get( i_pTarget, G_eq_attributes_ptr, i_id, &o_value ); + } + + if(K & TARGET_TYPE_EX) + { + __get( i_pTarget, G_ex_attributes_ptr, i_id, &o_value ); + } + + return FAPI2_RC_SUCCESS; +} + +//****************************************************************************** +// Get int16_t +//****************************************************************************** +template +ReturnCode _get(const AttributeId i_id, + const Target & i_pTarget, + int16_t& o_value) +{ + static_assert(std::is_same::value, "Attribute type mismatch"); + + if(K & TARGET_TYPE_SYSTEM) + { + __get( i_pTarget, G_system_attributes_ptr, i_id, &o_value ); + } + + if(K & TARGET_TYPE_PROC_CHIP) + { + __get( i_pTarget, G_proc_chip_attributes_ptr, i_id, &o_value ); + } + + if(K & TARGET_TYPE_PERV) + { + __get( i_pTarget, G_perv_attributes_ptr, i_id, &o_value ); + } + + if(K & TARGET_TYPE_CORE) + { + __get( i_pTarget, G_core_attributes_ptr, i_id, &o_value ); + } + + if(K & TARGET_TYPE_EQ) + { + __get( i_pTarget, G_eq_attributes_ptr, i_id, &o_value ); + } + + if(K & TARGET_TYPE_EX) + { + __get( i_pTarget, G_ex_attributes_ptr, i_id, &o_value ); + } + + return FAPI2_RC_SUCCESS; +} + + +//****************************************************************************** +// Get int32_t +//****************************************************************************** +template +ReturnCode _get(const AttributeId i_id, + const Target & i_pTarget, + int32_t& o_value) +{ + static_assert(std::is_same::value, "Attribute type mismatch"); + + if(K & TARGET_TYPE_SYSTEM) + { + __get( i_pTarget, G_system_attributes_ptr, i_id, &o_value ); + } + + if(K & TARGET_TYPE_PROC_CHIP) + { + __get( i_pTarget, G_proc_chip_attributes_ptr, i_id, &o_value ); + } + + if(K & TARGET_TYPE_PERV) + { + __get( i_pTarget, G_perv_attributes_ptr, i_id, &o_value ); + } + + if(K & TARGET_TYPE_CORE) + { + __get( i_pTarget, G_core_attributes_ptr, i_id, &o_value ); + } + + if(K & TARGET_TYPE_EQ) + { + __get( i_pTarget, G_eq_attributes_ptr, i_id, &o_value ); + } + + if(K & TARGET_TYPE_EX) + { + __get( i_pTarget, G_ex_attributes_ptr, i_id, &o_value ); + } + + return FAPI2_RC_SUCCESS; +} + + +//****************************************************************************** +// Get int64_t +//****************************************************************************** +template +ReturnCode _get(const AttributeId i_id, + const Target & i_pTarget, + int64_t& o_value) +{ + static_assert(std::is_same::value, "Attribute type mismatch"); + + if(K & TARGET_TYPE_SYSTEM) + { + __set( i_pTarget, G_system_attributes_ptr, i_id, &o_value ); + } + + if(K & TARGET_TYPE_PROC_CHIP) + { + __get( i_pTarget, G_proc_chip_attributes_ptr, i_id, &o_value ); + } + + if(K & TARGET_TYPE_PERV) + { + __get( i_pTarget, G_perv_attributes_ptr, i_id, &o_value ); + } + + if(K & TARGET_TYPE_CORE) + { + __get( i_pTarget, G_core_attributes_ptr, i_id, &o_value ); + } + + if(K & TARGET_TYPE_EQ) + { + __get( i_pTarget, G_eq_attributes_ptr, i_id, &o_value ); + } + + if(K & TARGET_TYPE_EX) + { + __get( i_pTarget, G_ex_attributes_ptr, i_id, &o_value ); + } + + return FAPI2_RC_SUCCESS; +} + + +//****************************************************************************** +// Get Override int8_t +//****************************************************************************** +template +ReturnCode _getOverride(const AttributeId i_id, + const Target & i_pTarget, + int8_t& o_value) +{ + static_assert(std::is_same::value, "Attribute type mismatch"); + + return FAPI2_RC_SUCCESS; +} + +//****************************************************************************** +// Get Override int16_t +//****************************************************************************** +template +ReturnCode _getOverride(const AttributeId i_id, + const Target & i_pTarget, + int16_t& o_value) +{ + static_assert(std::is_same::value, "Attribute type mismatch"); + + return FAPI2_RC_SUCCESS; +} + +//****************************************************************************** +// Get Override int32_t +//****************************************************************************** +template +ReturnCode _getOverride(const AttributeId i_id, + const Target & i_pTarget, + int32_t& o_value) +{ + static_assert(std::is_same::value, "Attribute type mismatch"); + + return FAPI2_RC_SUCCESS; +} + +//****************************************************************************** +// Get Override int64_t +//****************************************************************************** +template +ReturnCode _getOverride(const AttributeId i_id, + const Target & i_pTarget, + int64_t& o_value) +{ + static_assert(std::is_same::value, "Attribute type mismatch"); + + return FAPI2_RC_SUCCESS; +} + + +//****************************************************************************** +// Get int8_t array +//****************************************************************************** +template +ReturnCode _getAttributeArraySignedShort(const AttributeId i_id, + const Target & i_pTarget, + int8_t * o_pValues) +{ + return FAPI2_RC_SUCCESS; +} + + +//****************************************************************************** +// Set int8_t array +//****************************************************************************** +template +ReturnCode _setAttributeArraySignedShort(const AttributeId i_id, + const Target & i_pTarget, + int8_t * i_pValues) +{ + return FAPI2_RC_SUCCESS; +} + +//****************************************************************************** +// Get int16_t array +//****************************************************************************** +template +ReturnCode _getAttributeArraySignedWord(const AttributeId i_id, + const Target & i_pTarget, + int16_t * o_pValues) +{ + return FAPI2_RC_SUCCESS; +} + + +//****************************************************************************** +// Set int16_t array +//****************************************************************************** +template +ReturnCode _setAttributeArraySignedWord(const AttributeId i_id, + const Target & i_pTarget, + int16_t * i_pValues) +{ + return FAPI2_RC_SUCCESS; +} + +//****************************************************************************** +// Get int32_t array +//****************************************************************************** +template +ReturnCode _getAttributeArraySignedWord(const AttributeId i_id, + const Target & i_pTarget, + int32_t * o_pValues) +{ + return FAPI2_RC_SUCCESS; +} + + +//****************************************************************************** +// Set int32_t array +//****************************************************************************** +template +ReturnCode _setAttributeArraySignedWord(const AttributeId i_id, + const Target & i_pTarget, + int32_t * i_pValues) +{ + return FAPI2_RC_SUCCESS; +} + + +//****************************************************************************** +// Get int64_t array +//****************************************************************************** +template +ReturnCode _getAttributeArraySignedDoubleWord(const AttributeId i_id, + const Target & i_pTarget, + int64_t * o_pValues) +{ + return FAPI2_RC_SUCCESS; +} + +//****************************************************************************** +// Set int64_t array +//****************************************************************************** +template +ReturnCode _setAttributeArraySignedDoubleWord(const AttributeId i_id, + const Target & i_pTarget, + int64_t * i_pValues) +{ + return FAPI2_RC_SUCCESS; +} + +//****************************************************************************** +// Get Override int8_t array +//****************************************************************************** +template +ReturnCode _getAttributeOverrideArraySignedShort(const AttributeId i_id, + const Target & i_pTarget, + int8_t * o_pValues) +{ + return FAPI2_RC_SUCCESS; +} + +//****************************************************************************** +// Get Override int16_t array +//****************************************************************************** +template +ReturnCode _getAttributeOverrideArraySignedWord(const AttributeId i_id, + const Target & i_pTarget, + int16_t * o_pValues) +{ + return FAPI2_RC_SUCCESS; +} + +//****************************************************************************** +// Get Override int32_t array +//****************************************************************************** +template +ReturnCode _getAttributeOverrideArraySignedWord(const AttributeId i_id, + const Target & i_pTarget, + int32_t * o_pValues) +{ + return FAPI2_RC_SUCCESS; +} + + +//****************************************************************************** +// Get Override int64_t array +//****************************************************************************** +template +ReturnCode _getAttributeOverrideArraySignedDoubleWord(const AttributeId i_id, + const Target & i_pTarget, + int64_t * o_pValues) +{ + return FAPI2_RC_SUCCESS; +} + + +//****************************************************************************** +// Set int8_t +//****************************************************************************** +template +ReturnCode _set(const AttributeId i_id, + const Target & i_pTarget, + const int8_t& i_value) +{ + static_assert(std::is_same::value, "Attribute type mismatch"); // May need to remove + + if(K & TARGET_TYPE_SYSTEM) + { + __set( i_pTarget, G_system_attributes_ptr, i_id, i_value ); + } + + if(K & TARGET_TYPE_PROC_CHIP) + { + __set( i_pTarget, G_proc_chip_attributes_ptr, i_id, i_value ); + } + + if(K & TARGET_TYPE_PERV) + { + __set( i_pTarget, G_perv_attributes_ptr, i_id, i_value ); + } + + if(K & TARGET_TYPE_CORE) + { + __set( i_pTarget, G_core_attributes_ptr, i_id, i_value ); + } + + if(K & TARGET_TYPE_EQ) + { + __set( i_pTarget, G_eq_attributes_ptr, i_id, i_value ); + } + + if(K & TARGET_TYPE_EX) + { + __set( i_pTarget, G_ex_attributes_ptr, i_id, i_value ); + } + + return FAPI2_RC_SUCCESS; +} + +//****************************************************************************** +// Set int16_t +//****************************************************************************** +template +ReturnCode _set(const AttributeId i_id, + const Target & i_pTarget, + const int16_t& i_value) +{ + static_assert(std::is_same::value, "Attribute type mismatch"); // May need to remove + + if(K & TARGET_TYPE_SYSTEM) + { + __set( i_pTarget, G_system_attributes_ptr, i_id, i_value ); + } + + if(K & TARGET_TYPE_PROC_CHIP) + { + __set( i_pTarget, G_proc_chip_attributes_ptr, i_id, i_value ); + } + + if(K & TARGET_TYPE_PERV) + { + __set( i_pTarget, G_perv_attributes_ptr, i_id, i_value ); + } + + if(K & TARGET_TYPE_CORE) + { + __set( i_pTarget, G_core_attributes_ptr, i_id, i_value ); + } + + if(K & TARGET_TYPE_EQ) + { + __set( i_pTarget, G_eq_attributes_ptr, i_id, i_value ); + } + + if(K & TARGET_TYPE_EX) + { + __set( i_pTarget, G_ex_attributes_ptr, i_id, i_value ); + } + + return FAPI2_RC_SUCCESS; +} + +//****************************************************************************** +// Set int32_t +//****************************************************************************** +template +ReturnCode _set(const AttributeId i_id, + const Target & i_pTarget, + const int32_t& i_value) +{ + static_assert(std::is_same::value, "Attribute type mismatch"); // May need to remove + + if(K & TARGET_TYPE_SYSTEM) + { + __set( i_pTarget, G_system_attributes_ptr, i_id, i_value ); + } + + if(K & TARGET_TYPE_PROC_CHIP) + { + __set( i_pTarget, G_proc_chip_attributes_ptr, i_id, i_value ); + } + + if(K & TARGET_TYPE_PERV) + { + __set( i_pTarget, G_perv_attributes_ptr, i_id, i_value ); + } + + if(K & TARGET_TYPE_CORE) + { + __set( i_pTarget, G_core_attributes_ptr, i_id, i_value ); + } + + if(K & TARGET_TYPE_EQ) + { + __set( i_pTarget, G_eq_attributes_ptr, i_id, i_value ); + } + + if(K & TARGET_TYPE_EX) + { + __set( i_pTarget, G_ex_attributes_ptr, i_id, i_value ); + } + + return FAPI2_RC_SUCCESS; +} + + +//****************************************************************************** +// Set int64_t +//****************************************************************************** +template +ReturnCode _set(const AttributeId i_id, + const Target & i_pTarget, + const int64_t & i_value) +{ + static_assert(std::is_same::value, "Attribute type mismatch"); // May need to remove + + if(K & TARGET_TYPE_SYSTEM) + { + __set( i_pTarget, G_system_attributes_ptr, i_id, i_value ); + } + + if(K & TARGET_TYPE_PROC_CHIP) + { + __set( i_pTarget, G_proc_chip_attributes_ptr, i_id, i_value ); + } + + if(K & TARGET_TYPE_PERV) + { + __set( i_pTarget, G_perv_attributes_ptr, i_id, i_value ); + } + + if(K & TARGET_TYPE_CORE) + { + __set( i_pTarget, G_core_attributes_ptr, i_id, i_value ); + } + + if(K & TARGET_TYPE_EQ) + { + __set( i_pTarget, G_eq_attributes_ptr, i_id, i_value ); + } + + if(K & TARGET_TYPE_EX) + { + __set( i_pTarget, G_ex_attributes_ptr, i_id, i_value ); + } + + return FAPI2_RC_SUCCESS; +} + + +} // namespace fapi2 +#endif // FAPIPLATATTRIBUTESERVICE_H_ -- cgit v1.2.1