From 520e2dae589df58d9e50f8d6a3828d620e4c4783 Mon Sep 17 00:00:00 2001 From: Prachi Gupta Date: Wed, 20 Aug 2014 15:25:18 -0500 Subject: ISDIMM to C4 DQ/DQS standalone compression tool (Rosetta Stone) Change-Id: I8e5adf282d82085f504e64a0ffc8d913b7cb237b RTC:109474 Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/12907 Tested-by: Jenkins Server Reviewed-by: STEPHEN M. CPREK Reviewed-by: A. Patrick Williams III --- .../usr/hwpf/hwp/mvpd_accessors/DQCompressionLib.H | 72 ++++ .../compressionTool/DQCompressionConsts.H | 48 +++ .../compressionTool/DQCompressionLib.C | 392 +++++++++++++++++++++ .../compressionTool/DQCompressionReasonCodes.H | 39 ++ .../compressionTool/EncodeDQMapping.C | 292 +++++++++++++++ .../hwp/mvpd_accessors/compressionTool/makefile | 47 +++ src/usr/hwpf/hwp/mvpd_accessors/mvpd.mk | 6 +- src/usr/hwpf/test/hwpDQCompressionTest.H | 224 ++++++++++++ src/usr/hwpf/test/makefile | 1 + 9 files changed, 1119 insertions(+), 2 deletions(-) create mode 100644 src/include/usr/hwpf/hwp/mvpd_accessors/DQCompressionLib.H create mode 100644 src/usr/hwpf/hwp/mvpd_accessors/compressionTool/DQCompressionConsts.H create mode 100644 src/usr/hwpf/hwp/mvpd_accessors/compressionTool/DQCompressionLib.C create mode 100644 src/usr/hwpf/hwp/mvpd_accessors/compressionTool/DQCompressionReasonCodes.H create mode 100644 src/usr/hwpf/hwp/mvpd_accessors/compressionTool/EncodeDQMapping.C create mode 100644 src/usr/hwpf/hwp/mvpd_accessors/compressionTool/makefile create mode 100644 src/usr/hwpf/test/hwpDQCompressionTest.H (limited to 'src') diff --git a/src/include/usr/hwpf/hwp/mvpd_accessors/DQCompressionLib.H b/src/include/usr/hwpf/hwp/mvpd_accessors/DQCompressionLib.H new file mode 100644 index 000000000..6b14c5081 --- /dev/null +++ b/src/include/usr/hwpf/hwp/mvpd_accessors/DQCompressionLib.H @@ -0,0 +1,72 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/include/usr/hwpf/hwp/mvpd_accessors/DQCompressionLib.H $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2014 */ +/* [+] 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 */ +//$Id: DQCompressionLib.H,v 1.7 2014/11/12 20:03:25 pragupta Exp $ + +/* @file DQCompressionLib.H + * + * @brief Header file DQCompressionLib + * + */ + +#ifndef __DQCOMPRESSIONLIB_H +#define __DQCOMPRESSIONLIB_H + +#include +#include +#include +#include +#include +#ifdef DQCOMPRESSION_TEST +#define DQ_TRAC(fmt,args...) FAPI_INF (fmt, ##args) +#else +#define DQ_TRAC(fmt,args...) printf(fmt, ##args) +#endif +namespace DQCompression +{ + //ERROR CODES + //Mapping of these error codes to error messages + //are in DQCompressionReasonCodes.H + enum ErrCodes + { + NO_ERR = 0, + ECMD_OPER_ERROR, + INVALID_INPUT, + INVALID_ARRAY_TYPE, + LAST_ERR, + }; +/** + * @brief Calculates the encoding for DQ or DQS arrays for one port + * to be stored in VPD + * @param i_data DQ or DQS array as a vector + * @param i_arrayType type of array being passed in (DQ/DQS) + * @param o_encodeData: 17 bytes of data for DQ and + * 2 bytes of data for DQS + * @retval ErrCodes Values + */ + int encodeDQ (std::vector& i_data, + uint32_t i_arrayType, ecmdDataBufferBase& o_encodedData); +} +#endif + diff --git a/src/usr/hwpf/hwp/mvpd_accessors/compressionTool/DQCompressionConsts.H b/src/usr/hwpf/hwp/mvpd_accessors/compressionTool/DQCompressionConsts.H new file mode 100644 index 000000000..6eafef167 --- /dev/null +++ b/src/usr/hwpf/hwp/mvpd_accessors/compressionTool/DQCompressionConsts.H @@ -0,0 +1,48 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/hwpf/working/hwp/mvpd_accessors/compressionTool/DQCompressionConsts.H,v $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2014 */ +/* [+] 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 */ +// $Id: DQCompressionConsts.H,v 1.1 2014/11/12 19:55:07 pragupta Exp $ +#ifndef _DQCOMPRESSIONCONSTS_H_ +#define _DQCOMPRESSIONCONSTS_H_ + +namespace DQCompression +{ +/* Constants to be used by compression and decompression */ + const uint32_t DQarray_size = 80; + const uint32_t DQSarray_size = 20; + const uint32_t BYTE_LENGTH = 8; + const uint32_t BYTE_CODE_LENGTH = 3; //bytes + const uint32_t NIBBLE_SWAP_LENGTH = 2; //bytes + const uint32_t NIBBLE_PERM_LENGTH = 5; //bits + const uint32_t DQ_CODE_LENGTH = 17;//bytes + const uint32_t DQS_CODE_LENGTH = 2; //bytes + const uint32_t SIX_BIT_ZERO_PADDING = 6; + + const uint32_t DQ_GROUP_SIZE = 8; + const uint32_t DQS_GROUP_SIZE = 2; + //DQ and DQS Flag - to determine the input type + const uint8_t DQ = 1; + const uint8_t DQS= 2; +} +#endif diff --git a/src/usr/hwpf/hwp/mvpd_accessors/compressionTool/DQCompressionLib.C b/src/usr/hwpf/hwp/mvpd_accessors/compressionTool/DQCompressionLib.C new file mode 100644 index 000000000..e4f7f81e0 --- /dev/null +++ b/src/usr/hwpf/hwp/mvpd_accessors/compressionTool/DQCompressionLib.C @@ -0,0 +1,392 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/hwpf/working/hwp/mvpd_accessors/compressionTool/DQCompressionLib.C,v $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2014 */ +/* [+] 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 */ +//$Id: DQCompressionLib.C,v 1.6 2014/11/12 19:53:08 pragupta Exp $ +/** + * @file DQCompressionLib.C + * @brief Defines utility functions which calculates the encoding for DQ + * or DQS arrays + * + * Wiring Rules: + * - On a port any byte may be wired to any byte on the DIMM connector + * i.e. bytes must remain whole and undivided + * + * - In a Byte the Upper and Lower Nibble my be swapped. + * This includes the DQ and the DQS + * + * - In a Nibble any connection of the DQ is allowed. + * i.e. Nibbles must remain whole and undivided + * + * - The DQS may be swapped from the upper and lower nibbles + * in a byte without swapping the DQ. + */ +#include +#include "DQCompressionConsts.H" + +using namespace DQCompression; +/** + * @brief Checks whether the input follows the wiring rules or not + * @param i_data DQ or DQS array as a vector + * @param i_arrayType DQ = 1 and DQS = 2 + */ +int validateInputData (const std::vector& i_data, + uint32_t i_arrayType) +{ + int l_rc = NO_ERR; + do + { + l_rc = ((i_data.size() == 80) || (i_data.size() == 20)) ? + NO_ERR : INVALID_INPUT; + if (l_rc != NO_ERR) + { + DQ_TRAC("Input data size is: %d. Size should be 80 or 20\n", + (int)i_data.size()); + break; + } + uint32_t l_grpSize = (i_arrayType == DQS) ? 2: BYTE_LENGTH; + + //Check that the bytes are whole and undivided + //Check that the nibbles are whole and undivided + std::vector l_data (i_data); + + std::vector::iterator l_itBegin = l_data.begin(); + std::vector::iterator l_itMiddle = l_itBegin + (l_grpSize/2); + std::vector::iterator l_itEnd = l_itBegin + l_grpSize; + + uint32_t l_loopCnts = l_data.size()-l_grpSize; + for(uint32_t i = 0; (i < l_loopCnts); i += l_grpSize) + { + //Sort nibbles at a time + std::sort(l_itBegin, l_itMiddle); + std::sort(l_itMiddle,l_itEnd); + + //Check the first nibble + for (std::vector::iterator j = l_itBegin; + j < l_itMiddle-1; j++) + { + if (*(j+1) != (*j)+1) + { + l_rc = INVALID_INPUT; + DQ_TRAC("First nibble of byte %d is not together\n",i); + break; + } + } + if (l_rc) + { + break; + } + + //Check the second nibble + for (std::vector::iterator j = l_itMiddle; + (j < l_itEnd-1); j++) + { + if (*(j+1) != (*j)+1) + { + l_rc = INVALID_INPUT; + DQ_TRAC("Second nibble of byte %d is not together\n",i); + break; + } + } + if (l_rc) + { + break; + } + + //Check that first and second nibble are part of the same byte + uint8_t l_inc = l_grpSize/2; + if (((*l_itBegin+l_inc) != *l_itMiddle) && + ((*l_itBegin-l_inc) != *l_itMiddle)) + { + l_rc = INVALID_INPUT; + DQ_TRAC("Byte %d is not together\n", i); + break; + } + + l_itBegin += l_grpSize; + l_itMiddle+= l_grpSize; + l_itEnd += l_grpSize; + } //end for loop + } while (0); + return l_rc; +} + + +/** + * @brief Calculates the byte-to-byte mapping for ISDIMM to Centaur + * @param i_data DQ or DQS array as a vector + * @param o_byteMap: vector that will hold the byte-to-byte mapping + */ +void byte_mapping (std::vector& i_data, + std::vector& o_byteMap) +{ + uint32_t l_size = i_data.size() - BYTE_LENGTH; + + for(uint32_t i = 0; i < l_size; i += BYTE_LENGTH) + { + o_byteMap.push_back(i_data[i]/BYTE_LENGTH); + } +} + +/** + * @brief Calculates the permutation of a sequence between two iterators + * @param i_itBegin iterator to the beginning of the sequence + * @param i_itEnd iterator to the end of the sequence + * @retval uint32_t code: 24 bits of code for byte permuatation + * and 5 bits of code for nibble permutation + */ +uint32_t permutation (const std::vector::iterator i_itBegin, + const std::vector::iterator i_itEnd) +{ + std::vector l_sequence (i_itBegin, i_itEnd); + std::vector l_permutation; + std::vector l_index (l_sequence); + size_t l_seqSize = l_sequence.size(); + + //We want the sorted list of sequence to determine + //the index for lehmer's code + std::sort(l_index.begin(), l_index.end()); + + for(uint32_t i = 0; i < l_seqSize; i++) + { + //find the index of the value in sequence in the index array + std::vector ::iterator it = std::find (l_index.begin(), + l_index.end(), l_sequence.at(i)); + + //Add that index to another array + uint8_t l_idx = it-l_index.begin(); + l_permutation.push_back(l_idx); + + //Delete that value from the array and shift + //This will change the indices for the rest of + //the values each iteration + l_index.erase(l_index.begin() + l_idx); + } + + //Skip the last element as it is always zero + l_permutation.pop_back(); + + uint32_t l_code = 0; + uint32_t l_factorial = 1; + + //Generate the variable base code + //Since, the last element will always be zero. + //we start multiplying by 1! + for (uint32_t i = 1; i < l_seqSize; i++) + { + l_factorial *= i; + l_code += l_factorial * l_permutation.back(); + l_permutation.pop_back(); + } + return l_code; +} + +/** + * @brief Figures out if the nibbles within a byte are swapped or not + * @param i_data DQ or DQS array as a vector + * @param l_grpSize: 8 for DQ and 2 for DQS + * @retval uint32_t which has 1 for the byte whose nibble is swapped + * or 0 if the nibbles are not swapped + */ +uint32_t nibble_swap (std::vector& i_data, uint32_t l_grpSize) +{ + uint32_t o_swap = 0; + //Skip the last one as it is unused + for(uint32_t i = 0; i < i_data.size() - l_grpSize; i+= l_grpSize) + { + if (i_data.at(i) > i_data.at(i+(l_grpSize/2))) + { + o_swap |= 1; + } + o_swap <<= 1; + } + return (o_swap>>1); +} + +/** + * @brief Insert data in ecmdDataBuffer one byte at a time to preserve + * endianess + * @param o_encodedData: buffer to insert the data into + * @param i_data: value to be inserted in ecmdDataBuffer + * @param i_size: number of bytes to insert + * @param i_startBit: Bit to start inserting the data from + * @retval errl: NULL for no-err and BUFFER_OVERFLOW + * if error inserting in ecmdDataBuffer + */ +int insertEncodedData (ecmdDataBufferBase& o_encodedData, uint32_t i_data, + uint32_t i_size, uint32_t i_startBit) +{ + DQ_TRAC("Entering insertEncodedData i_data:%X, i_size:%d, i_startBit:%d\n", + i_data, i_size, i_startBit); + int l_rc = NO_ERR; + //Insert one byte at a time to take care of endianess + for(int i = i_size; i > 0; i--) + { + uint32_t l_datatobeinserted = (i_data>>((i-1)*BYTE_LENGTH))&0xFF; + l_rc = o_encodedData.insertFromRight(l_datatobeinserted, + i_startBit, BYTE_LENGTH); + if (l_rc) + { + l_rc = ECMD_OPER_ERROR; + DQ_TRAC("ECMD errored while writing %d data ;startbit=%d\n", + l_datatobeinserted, i_startBit); + break; + } + i_startBit += BYTE_LENGTH; + } + return l_rc; +} + +/** + * @brief Calculates the encoding for ISDIMM to C4DQ or C4DQS + * @param i_data DQ or DQS array as a vector + * @param i_arrayType DQ = 1 and DQS = 2 + * @param o_encodedData buffer to insert the encoded data into + * @retval error codes + */ +int DQCompression::encodeDQ (std::vector& i_data, + uint32_t i_arrayType, ecmdDataBufferBase& o_encodedData) +{ + int l_rc = NO_ERR; + uint8_t l_grpSize; + + DQ_TRAC("Entering encodeDQ\n"); + do + { + l_rc = validateInputData (i_data, i_arrayType); + if(l_rc) + { + DQ_TRAC ("validateInputData errored\n"); + break; + } + if (i_arrayType == DQ) + { + l_grpSize = DQ_GROUP_SIZE; + //allocate the buffers with right length + o_encodedData.setByteLength(DQ_CODE_LENGTH); + + //Determine the byte-to-byte mapping + std::vector l_byteMap; + byte_mapping(i_data, l_byteMap); + + //Determine the permutation for byte mapping + uint32_t l_byteCode = permutation(l_byteMap.begin(), + l_byteMap.end()); + + //Check if the nibbles are swapped within a byte + uint32_t l_nibbleSwap = nibble_swap(i_data, l_grpSize); + + //Copy everything into the o_encodedData buffer + //Copy encoded data for byte-to-byte mapping + uint32_t l_startBit = 0; + DQ_TRAC("Writing byte-to-byte mapping to ecmdBuffer\n"); + l_rc = insertEncodedData (o_encodedData, l_byteCode, + BYTE_CODE_LENGTH,l_startBit); + if (l_rc) + { + DQ_TRAC("Error writing byte-to-byte mapping to ecmdBuffer\n"); + break; + } + + //Copy the data for nibbleSwap + DQ_TRAC("Writing nibbleSwap data to ecmdBuffer\n"); + l_startBit += (BYTE_CODE_LENGTH * BYTE_LENGTH); + l_rc = insertEncodedData (o_encodedData, l_nibbleSwap, + NIBBLE_SWAP_LENGTH,l_startBit); + if (l_rc) + { + DQ_TRAC("Error writing nibbleSwap data to ecmdBuffer\n"); + break; + } + + //Nibble Permutations - setup + std::vector::iterator l_itBegin = i_data.begin(); + std::vector::iterator l_itEnd = l_itBegin + + (l_grpSize/2); + + int l_numNibbles = ((i_data.size()/l_grpSize) - 1)*2; + l_startBit += NIBBLE_SWAP_LENGTH*BYTE_LENGTH; + + //Add 0 padding - to round up the nibble perms to next byte + DQ_TRAC("Writing the 0 padding\n"); + uint32_t l_temp = 0; + l_rc = o_encodedData.insertFromRight(l_temp,l_startBit, + SIX_BIT_ZERO_PADDING); + if (l_rc) + { + DQ_TRAC("Error writing 6-bit 0 padding to ecmdDataBuffer\n"); + break; + } + l_startBit += SIX_BIT_ZERO_PADDING; + + DQ_TRAC("Starting nibble permutations\n"); + for(int i = 0; i < l_numNibbles; i++) + { + //Find the permutation of the nibble + uint32_t l_nibblePerm = permutation(l_itBegin, l_itEnd); + //Store it in the encode data buffer + l_rc = o_encodedData.insertFromRight(l_nibblePerm, + l_startBit,NIBBLE_PERM_LENGTH); + if (l_rc) + { + DQ_TRAC("Error writing nibblePerm data to ecmdBuffer\n", + i); + break; + } + l_startBit += NIBBLE_PERM_LENGTH; + + //Setup iterators for the next iteration + l_itBegin += (l_grpSize/2); + l_itEnd += (l_grpSize/2); + } + + if (l_rc) + { + break; + } + } + else if (i_arrayType == DQS) + { + l_grpSize = DQS_GROUP_SIZE; + + o_encodedData.setByteLength(DQS_CODE_LENGTH); + uint32_t l_nibbleSwap = nibble_swap(i_data, l_grpSize); + l_rc = insertEncodedData (o_encodedData, l_nibbleSwap, + NIBBLE_SWAP_LENGTH,0); + if (l_rc) + { + DQ_TRAC("Error writing DQS data to ecmdDataBuffer\n"); + break; + } + } + else + { + l_rc = INVALID_ARRAY_TYPE; + DQ_TRAC("Data type does not match DQ or DQS\n"); + break; + } + } while (0); + + DQ_TRAC("Exiting encodeDQ\n"); + return l_rc; +} diff --git a/src/usr/hwpf/hwp/mvpd_accessors/compressionTool/DQCompressionReasonCodes.H b/src/usr/hwpf/hwp/mvpd_accessors/compressionTool/DQCompressionReasonCodes.H new file mode 100644 index 000000000..ce519624f --- /dev/null +++ b/src/usr/hwpf/hwp/mvpd_accessors/compressionTool/DQCompressionReasonCodes.H @@ -0,0 +1,39 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/hwpf/working/hwp/mvpd_accessors/compressionTool/DQCompressionReasonCodes.H,v $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2014 */ +/* [+] 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 */ +//$Id: DQCompressionReasonCodes.H,v 1.4 2014/11/12 19:53:08 pragupta Exp $ +/* @file DQCompressionReasonCodes.H + * + * @brief Reason Codes files for DQCompressionLib + */ +#ifndef __DQCOMPRESSIONREASONCODES_H +#define __DQCOMPRESSIONREASONCODES_H + const char* ReasonCodes [] = + { + "NO_ERR", + "ECMD_OPER_ERROR", + "INVALID_INPUT", + "INVALID_ARRAY_TYPE" + }; +#endif diff --git a/src/usr/hwpf/hwp/mvpd_accessors/compressionTool/EncodeDQMapping.C b/src/usr/hwpf/hwp/mvpd_accessors/compressionTool/EncodeDQMapping.C new file mode 100644 index 000000000..d2d861308 --- /dev/null +++ b/src/usr/hwpf/hwp/mvpd_accessors/compressionTool/EncodeDQMapping.C @@ -0,0 +1,292 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/hwpf/working/hwp/mvpd_accessors/compressionTool/EncodeDQMapping.C,v $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2014 */ +/* [+] 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 */ +//$Id: EncodeDQMapping.C,v 1.5 2014/11/12 19:53:08 pragupta Exp $ + +/* + * @file EncodeDQMapping.C + * @brief computes the encoding for ISDIMM to DQ or DQS mapping + * + * + * @param first input is a csv file that has the contents of DQ or DQS array + * It can have upto 4 ports. If there are less than 4 ports passed in, + * the algorithm will assume one-to-one mapping for the rest of the + * ports, meaning zeros for encoded data. + * + * + * @param second input is a file that will hold the encoded data + * (one byte of hex data separated with a space) + * + * + */ +#include +#include "DQCompressionReasonCodes.H" +#include "DQCompressionConsts.H" +#include + +using namespace DQCompression; + +void parseInput (FILE* i_ptrFile, std::vector >& i_dqData, + std::vector >& i_dqsData) +{ + const uint32_t l_MAX_STR_LENGTH = 300; + char l_inputStr [l_MAX_STR_LENGTH]; + char* l_splitStr; + + int l_dqRowNum = 0; + int l_dqsRowNum = 0; + uint8_t l_arrayType = 0; + + //Read the file + while (fgets(l_inputStr,l_MAX_STR_LENGTH,i_ptrFile)) + { + //convert l_inputStr to a vector of uint8_t + l_splitStr = strtok (l_inputStr, ","); + //# means it is a comment: the comment can say whether it is DQ or DQS + if (*l_splitStr == '#') + { + //Look for DQ or DQS in the comment + char* l_dqPos = strstr(l_splitStr, "DQ"); + if (l_dqPos != NULL) + { + l_arrayType = (*(l_dqPos+2) == 'S') ? DQS : DQ; + } + } + //Skip empty lines + else if (*l_splitStr != '\n') + { + std::vector l_col; + //Add DQ arrays to the i_dqData vector + if(l_arrayType == DQ) + { + i_dqData.push_back (l_col); + while (l_splitStr != NULL) + { + i_dqData.at(l_dqRowNum).push_back(atoi(l_splitStr)); + l_splitStr = strtok (NULL, ","); + } + l_dqRowNum += 1; + } + + else if(l_arrayType == DQS) + { + //Add DQS arrays to the i_dqsData vector + i_dqsData.push_back (l_col); + while (l_splitStr != NULL) + { + i_dqsData.at(l_dqsRowNum).push_back(atoi(l_splitStr)); + l_splitStr = strtok (NULL, ","); + } + l_dqsRowNum += 1; + } + else + { + fprintf(stderr,"Couldn't determixe DQ or DQS from comment\n"); + exit(1); + } + } // end outer else if + } //end while +} +int writeEncodedData (FILE* i_ptrFile, + std::vector >& i_data, uint8_t i_arrayType) +{ + size_t l_numPorts = i_data.size(); + uint32_t l_dataSize; + int l_rc = 0; + for (uint32_t i = 0; i < l_numPorts; i++) + { + DQ_TRAC ("Input Data: \n"); + for (uint32_t j = 0; j < i_data.at(i).size(); j++) + { + DQ_TRAC("%d ", i_data.at(i).at(j)); + } + DQ_TRAC ("\n"); + + + ecmdDataBufferBase l_encodedData; + l_rc = encodeDQ (i_data.at(i), i_arrayType, + l_encodedData); + if(l_rc) + { + //Check l_rc and print meaningful msgs + fprintf(stderr, "Error Encoding Data %s \n", ReasonCodes[l_rc]); + exit(1); + } + + l_dataSize = l_encodedData.getByteLength(); + char l_buffer [4]; + //Write the data to a text file + for (uint32_t j = 0; j < l_dataSize; j++) + { + if (j == 0) + { + sprintf(l_buffer,"%02X", l_encodedData.getByte(j)); + } + else + { + sprintf(l_buffer," %02X", l_encodedData.getByte(j)); + } + l_rc = fputs(l_buffer, i_ptrFile); + if (l_rc == EOF) + { + DQ_TRAC("Unable to write data to the output file.\n"); + break; + } + } + if (l_rc == EOF) + { + break; + } + l_rc = fputs("\n", i_ptrFile); + if (l_rc == EOF) + { + DQ_TRAC("Unable to write newline char to the output file\n"); + break; + } + } + + //If less than 4 ports are passed in as an input, we assume + //that the rest of the ports have one to one mapping, which + //leads to all zeros for the encoded data. + if (l_numPorts < 4) + { + for (uint32_t i = 0; i < (4 - l_numPorts); i++) + { + for (uint32_t j = 0; j < l_dataSize; j++) + { + if(j == 0) + { + l_rc = fputs("00", i_ptrFile); + if (l_rc == EOF) + { + DQ_TRAC("Unable to write data '00' to the output file"); + break; + } + } + else + { + l_rc = fputs(" 00", i_ptrFile); + if (l_rc == EOF) + { + DQ_TRAC("Unable to write data '00' to the output file"); + break; + } + } + } //end inner for loop + if (l_rc == EOF) + { + break; + } + l_rc = fputs("\n", i_ptrFile); + if (l_rc == EOF) + { + DQ_TRAC("Unable to write newline char to the output file"); + break; + } + } //end for loop + } // end if statement +} + + + +int main (int argc, char* argv []) +{ + int l_rc = 0; + do { + if (argc > 3) + { + fprintf(stderr, "There should only be two parameters\n"); + exit(1); + } + //Open the input file + FILE* l_prInFile = fopen (argv[1], "r"); + if (l_prInFile == NULL) + { + fprintf(stderr, "Can't open the input file for reading\n"); + exit(1); + } + + //parse the inputs + std::vector > l_dqData; + std::vector > l_dqsData; + parseInput(l_prInFile, l_dqData, l_dqsData); + fclose(l_prInFile); + + //Open the output file + FILE* l_prOutFile = fopen (argv[2], "w"); + if (l_prOutFile == NULL) + { + fprintf(stderr, "Can't open the output file for writing\n"); + exit(1); + } + + //process DQ arrays + if (!(l_dqData.empty())) + { + l_rc = fputs("DQ\n", l_prOutFile); + if (l_rc == EOF) + { + DQ_TRAC("Unable to write DQ to the file\n"); + break; + } + if(l_dqData.at(0).size() != DQarray_size) + { + fprintf(stderr, "DQ arrays must have 80 elements\n"); + exit(1); + } + l_rc = writeEncodedData (l_prOutFile, l_dqData, DQ); + if (l_rc == EOF) + { + DQ_TRAC ("writeEncodedData for DQ failed l_rc: %d\n", l_rc); + break; + } + } + + //process DQS arrays + if (!(l_dqsData.empty())) + { + l_rc = fputs("DQS\n", l_prOutFile); + if (l_rc == EOF) + { + DQ_TRAC("Unable to write DQS to the file\n"); + break; + } + if(l_dqsData.at(0).size() != DQSarray_size) + { + fprintf(stderr, "DQS arrays must have 20 elements\n"); + exit(1); + } + l_rc = writeEncodedData (l_prOutFile, l_dqsData, DQS); + if (l_rc == EOF) + { + DQ_TRAC("writeEncodedData for DQS failed\n"); + break; + } + } + + fclose(l_prOutFile); + } while (0); + + return ((l_rc == EOF) ? EOF : 0); +} diff --git a/src/usr/hwpf/hwp/mvpd_accessors/compressionTool/makefile b/src/usr/hwpf/hwp/mvpd_accessors/compressionTool/makefile new file mode 100644 index 000000000..ad4f49996 --- /dev/null +++ b/src/usr/hwpf/hwp/mvpd_accessors/compressionTool/makefile @@ -0,0 +1,47 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/usr/hwpf/hwp/mvpd_accessors/compressionTool/makefile $ +# +# OpenPOWER HostBoot Project +# +# Contributors Listed Below - COPYRIGHT 2014 +# [+] 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 +ROOTPATH = ../../../../../.. + +OUT_FILE += $(ROOTPATH)/obj/modules/compression/compression + +GEN_PASS_BODY += compression +CLEAN_TARGETS += $(OUT_FILE) compression.o + +INC_DIRS += $(ROOTPATH)/src/include/usr/ecmddatabuffer +INC_DIRS += $(ROOTPATH)/src/include/usr/hwpf/hwp/mvpd_accessors +INC_DIRS += $(ROOTPATH)/src/usr/hwpf/hwp/mvpd_accessors/compressionTool +vpath %.C $(ROOTPATH)/src/usr/ecmddatabuffer + +HCFLAGS += -DPRDF_COMPRESSBUFFER_COMPRESS_FUNCTIONS=1 +HCFLAGS += -DPRDF_COMPRESSBUFFER_UNCOMPRESS_FUNCTIONS=1 +HCFLAGS += -lz +HCFLAGS += -Di386=1 + +include $(ROOTPATH)/config.mk + +compression: ecmdDataBufferBase.C DQCompressionLib.C EncodeDQMapping.C + $(C2) " CC $(notdir $@)" + $(C1)$(CCACHE) $(HOST_PREFIX)g++ -O3 -g $^ -o $(OUT_FILE)\ + $(foreach dir,$(INC_DIRS), -I $(dir)) $(HCFLAGS) diff --git a/src/usr/hwpf/hwp/mvpd_accessors/mvpd.mk b/src/usr/hwpf/hwp/mvpd_accessors/mvpd.mk index 447584e3c..985327bea 100644 --- a/src/usr/hwpf/hwp/mvpd_accessors/mvpd.mk +++ b/src/usr/hwpf/hwp/mvpd_accessors/mvpd.mk @@ -22,11 +22,13 @@ # permissions and limitations under the License. # # IBM_PROLOG_END_TAG +CFLAGS += -DDQCOMPRESSION_TEST=1 + EXTRAINCDIR += ${ROOTPATH}/src/usr/hwpf/hwp/mvpd_accessors EXTRAINCDIR += ${ROOTPATH}/src/include/usr/hwpf/hwp/mvpd_accessors VPATH += ${HWPPATH}/mvpd_accessors - +VPATH += ${HWPPATH}/mvpd_accessors/compressionTool OBJS += getMvpdRing.o OBJS += getMBvpdRing.o OBJS += setMvpdRing.o @@ -44,4 +46,4 @@ OBJS += getControlCapableData.o OBJS += accessMBvpdL4BankDelete.o OBJS += getDecompressedISDIMMAttrs.o OBJS += getISDIMMTOC4DAttrs.o - +OBJS += DQCompressionLib.o diff --git a/src/usr/hwpf/test/hwpDQCompressionTest.H b/src/usr/hwpf/test/hwpDQCompressionTest.H new file mode 100644 index 000000000..7da111eba --- /dev/null +++ b/src/usr/hwpf/test/hwpDQCompressionTest.H @@ -0,0 +1,224 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/hwpf/test/hwpDQCompressionTest.H $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2014 */ +/* [+] 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 */ +#ifndef _HWPDQCOMPRESSIONTEST_H +#define _HWPDQCOMPRESSIONTEST_H + +/** + * @file hwpDQCompressionTest.H + * + * @brief Tests for DQ and DQS compression and decompression + * + */ + +#include +#include +#include "../hwp/mvpd_accessors/compressionTool/DQCompressionReasonCodes.H" +#include "../hwp/mvpd_accessors/compressionTool/DQCompressionConsts.H" +#include + +#include +#include +#include + +using namespace TARGETING; +using namespace DQCompression; + +class HwpDQCompressionTest: public CxxTest::TestSuite +{ +public: + void testDQCompression1() + { + int l_errl = NO_ERR; + do + { + TRACFCOMP(g_trac_targeting, "Starting DQ Test 1"); + //Input DQ array + uint8_t l_isdimmToC4DQ_P0 [DQarray_size]={8,9,10,11,12,13,14,15, + 0,1,2,3,4,5,6,7, + 16,17,18,19,20,21,22,23, + 64,65,66,67,68,69,70,71, + 32,33,34,35,36,37,38,39, + 40,41,42,43,44,45,46,47, + 48,49,50,51,52,53,54,55, + 56,57,58,59,60,61,62,63, + 24,25,26,27,28,29,30,31, + 255,255,255,255,255,255, + 255,255}; + + //convert array to a vector + std::vector l_isdimmToC4DQ_0 (l_isdimmToC4DQ_P0, + l_isdimmToC4DQ_P0+(sizeof(l_isdimmToC4DQ_P0)/ + sizeof(uint8_t))); + + //Pass the vector to the encode function + ecmdDataBufferBase l_encodedDQData; + l_errl = encodeDQ(l_isdimmToC4DQ_0, DQ, l_encodedDQData); + + if (l_errl) + { + TS_FAIL("Error Encoding DQ Data set1 %s", + ReasonCodes[l_errl]); + break; + } + + //Input DQS Array + uint8_t l_isdimmToC4DQS_P0 [DQSarray_size]= {2,3,0,1, + 4,5,16,17, + 8,9,10,11, + 12,13,14,15, + 6,7,255,255}; + //Convert DQS array to a vector + std::vector l_isdimmToC4DQS_0 (l_isdimmToC4DQS_P0, + l_isdimmToC4DQS_P0+(sizeof(l_isdimmToC4DQS_P0)/ + sizeof(uint8_t))); + + //encode + ecmdDataBufferBase l_encodedDQSData; + l_errl = encodeDQ(l_isdimmToC4DQS_0, DQS, l_encodedDQSData); + if (l_errl) + { + TS_FAIL("Error Encoding DQS Data1 %s", + ReasonCodes[l_errl]); + break; + } + + //Pass the output to decode + uint8_t l_decDQArray [DQarray_size]; + uint8_t l_decDQSArray[DQSarray_size]; + decodeISDIMMAttrs(l_encodedDQData, l_encodedDQSData, + l_decDQArray, l_decDQSArray); + + //Check if the initial vector is obtained. + //If not, throw an error + //First, check DQ + for (uint8_t i = 0; i < DQarray_size; i++) + { + if(l_decDQArray[i] != l_isdimmToC4DQ_P0[i]) + { + TS_FAIL("Decoded Output differs from initial array DQ test1"); + break; + } + } + + //Check DQS + for (uint8_t i = 0; i < DQSarray_size; i++) + { + if(l_decDQSArray[i] != l_isdimmToC4DQS_P0[i]) + { + TS_FAIL("Decoded Output differs from initial array DQS test1"); + break; + } + } + + TRACFCOMP(g_trac_targeting, "DQ Test 1 ended successfully"); + } while (0); + + } + + void testDQCompression2 () + { + int l_errl = NO_ERR; + do + { + TRACFCOMP(g_trac_targeting, "Starting DQ Test 2"); + uint8_t l_isdimmToC4DQ_P1[DQarray_size]={24,25,26,27,28,29,30,31, + 4,5,6,7,0,1,2,3, + 20,21,22,23,16,17,18,19, + 68,69,70,71,64,65,66,67, + 36,37,38,39,32,33,34,35, + 43,41,42,40,44,45,46,47, + 48,49,50,51,52,53,54,55, + 56,57,58,59,60,61,62,63, + 15,13,14,12,10,9,11,8, + 255,255,255,255,255,255, + 255,255}; + + //Convert to a vector + std::vector l_isdimmToC4DQ_1 (l_isdimmToC4DQ_P1, + l_isdimmToC4DQ_P1+(sizeof(l_isdimmToC4DQ_P1)/ + sizeof(uint8_t))); + + //Pass the vector to encode function + ecmdDataBufferBase l_encodedDQData; + l_errl = encodeDQ(l_isdimmToC4DQ_1, DQ, l_encodedDQData); + + if (l_errl) + { + TS_FAIL("Error Encoding DQ Data2 %s", + ReasonCodes[l_errl]); + break; + } + uint8_t l_isdimmToC4DQS_P1 [DQSarray_size]= {7,6,1,0, + 4,5,17,16, + 9,8,10,11, + 13,12,14,15, + 2,3,255,255}; + std::vector l_isdimmToC4DQS_1 (l_isdimmToC4DQS_P1, + l_isdimmToC4DQS_P1+(sizeof(l_isdimmToC4DQS_P1)/sizeof + (uint8_t))); + + //encode + ecmdDataBufferBase l_encodedDQSData; + l_errl = encodeDQ(l_isdimmToC4DQS_1, DQS, l_encodedDQSData); + if (l_errl) + { + TS_FAIL("Error Encoding DQS Data2 %s", + ReasonCodes[l_errl]); + break; + } + + //Pass the output to decode + uint8_t l_decDQArray [DQarray_size]; + uint8_t l_decDQSArray[DQSarray_size]; + decodeISDIMMAttrs (l_encodedDQData, l_encodedDQSData, + l_decDQArray, l_decDQSArray); + + //Check if the initial vector is obtained. + //If not, throw an error + //First, check DQ + for (uint8_t i = 0; i < DQarray_size; i++) + { + if(l_decDQArray[i] != l_isdimmToC4DQ_P1[i]) + { + TS_FAIL("Decoded Output differs initial array DQ test2"); + break; + } + } + + //Check DQS + for (uint8_t i = 0; i < DQSarray_size; i++) + { + if(l_decDQSArray[i] != l_isdimmToC4DQS_P1[i]) + { + TS_FAIL("Decoded Output differs initial array DQS test2"); + break; + } + } + + TRACFCOMP(g_trac_targeting, "DQ Test 2 ended successfully"); + } while (0); + } +}; +#endif diff --git a/src/usr/hwpf/test/makefile b/src/usr/hwpf/test/makefile index f1760b904..05f04c657 100644 --- a/src/usr/hwpf/test/makefile +++ b/src/usr/hwpf/test/makefile @@ -34,6 +34,7 @@ TESTS += hwpftest.H TESTS += hwpisteperrortest.H TESTS += hwpMBvpdAccessorTest.H TESTS += hwpMvpdAccessorTest.H +TESTS += hwpDQCompressionTest.H TESTS += $(if $(CONFIG_HTMGT),occAccessTest.H) SUBDIRS += runtime.d -- cgit v1.2.1