Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / cpus / vonk / bl / lib / ecc / src / BL_CKSyndrome.h
/*
* ========== Copyright Header Begin ==========================================
*
* OpenSPARC T2 Processor File: BL_CKSyndrome.h
* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
*
* The above named program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License version 2 as published by the Free Software Foundation.
*
* The above named program is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this work; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*
* ========== Copyright Header End ============================================
*/
/************************************************************************
**
** Copyright (C) 2007, Sun Microsystems, Inc.
**
** Sun considers its source code as an unpublished, proprietary
** trade secret and it is available only under strict license provisions.
** This copyright notice is placed here only to protect Sun in the event
** the source is deemed a published work. Disassembly, decompilation,
** or other means of reducing the object code to human readable form
** is prohibited by the license agreement under which this code is
** provided to the user or company in possession of this copy.
**
*************************************************************************/
#ifndef __BL_CKSyndrome_h__
#define __BL_CKSyndrome_h__
#include "BL_CKEcc.h"
#include "BL_Utils.h"
// Syndrome class for BL Chip-kill ECC
// Class provides basic routines to determine whether there is an
// ECC error, whether it is single, double, or multiple bit, and, if
// it is a single bit error, is it a data bit or check bit error.
class BL_CKSyndrome
{
public:
BL_CKSyndrome(BL_CKEccFile::ChipKillLine line, uint64_t savedECC) :
syndrome_(generateChipkillECC(line) ^ savedECC),
badDataNibblePosition_(0),
badCheckNibblePosition_(0),
dataCorrectionMask_(0),
checkCorrectionMask_(0)
{
if (syndrome_ > 0xffff)
{
fprintf(stderr,"BL_CKSyndrome::BL_CKSyndrome: bad syndrome");
exit(-1);
}
}
~BL_CKSyndrome() {}
bool noError() const
{
return (syndrome_ == 0);
}
bool isUncorrectableError()
{
return !noError() &&
!isCorrectableDataBitError() &&
!isCorrectableCheckBitError();
}
// Implemented based on Table A-10 in N2 PRM rev1.1
bool isCorrectableDataBitError()
{
if (noError())
{
return false;
}
bool correctableDataBitError = false;
uint32_t s3 = bit_shift(syndrome_,0,4);
uint32_t s2 = bit_shift(syndrome_,4,4);
uint32_t s1 = bit_shift(syndrome_,8,4);
uint32_t s0 = bit_shift(syndrome_,12,4);
// If nibble s0 == 0 - Row 4 of Table A-10
if (s0 == 0)
{
// The remaining three nibble should be non zero
if ((s1 != 0) && (s2 != 0) && (s3 != 0))
{
// And equal
if ((s1 == s2) && (s1 == s3))
{
// For it to be a valid single-bit correctable
// data error
correctableDataBitError = true;
badDataNibblePosition_ = 30;
// Mask to be XOR'ed with Nibble 30 to fix data
dataCorrectionMask_ = s1;
}
}
}
// If nibble s1 == 0 - Case ab0c - Row 3 of Table A-10
else if (s1 == 0)
{
// The remaining three nibble should be non zero
if ((s0 != 0) && (s2 != 0) && (s3 != 0))
{
// And the value of syndrome nibble 3 should be
// the same as the value in the matrix of synd0
// and synd2
if (ab0cErrorValidationMatrix[s2][s0] == s3)
{
// For it to be a valid single-bit correctable
// data error
correctableDataBitError = true;
// Table A-13
badDataNibblePosition_ =
ab0cErrorNibbleIdentityMatrix[s2][s0];
// Mask to be XOR'ed with the nibble indexed
// by badDataNibblePosition_ to fix data
dataCorrectionMask_ = s2;
}
}
}
// If nibble s2 == 0 - Case a0bc - Row 2 of Table A-10
else if (s2 == 0)
{
// The remaining three nibble should be non zero
if ((s0 != 0) && (s1 != 0) && (s3 != 0))
{
// And the value of syndrome nibble 3 should be
// the same as the value in the matrix of synd0
// and synd1
if (a0bcErrorValidationMatrix[s1][s0] == s3)
{
// For it to be a valid single-bit correctable
// data error
correctableDataBitError = true;
// Table A-11
badDataNibblePosition_ =
a0bcErrorNibbleIdentityMatrix[s1][s0];
// Mask to be XOR'ed with nibble in
// badDataNibblePosition_ above to fix data
dataCorrectionMask_ = s1;
}
}
}
// If nibble s3 == 0 - Row 5 of Table A-10
else if (s3 == 0)
{
// The remaining three nibble should be non zero
if ((s0 != 0) && (s1 != 0) && (s2 != 0))
{
// And equal
if ((s0 == s1) && (s0 == s2))
{
// For it to be a valid single-bit correctable
// data error
correctableDataBitError = true;
badDataNibblePosition_ = 31;
// Mask to be XOR'ed with Nibble 31 to fix data
dataCorrectionMask_ = s0;
}
}
}
return correctableDataBitError;
}
// Implemented based on Table A-10 in N2 PRM rev1.1
bool isCorrectableCheckBitError()
{
if (noError())
{
return false;
}
bool correctableCheckBitError = false;
uint32_t s3 = bit_shift(syndrome_,0,4);
uint32_t s2 = bit_shift(syndrome_,4,4);
uint32_t s1 = bit_shift(syndrome_,8,4);
uint32_t s0 = bit_shift(syndrome_,12,4);
// If nibble s0 != 0 - Row 6 of Table A-10
if (s0 != 0)
{
// The remaining three nibble should be zero
if ((s1 == 0) && (s2 == 0) && (s3 == 0))
{
// For it to be a valid single-bit correctable
// check bit error
correctableCheckBitError = true;
// use big endian to index nibble position
badCheckNibblePosition_ = 3;
// This mask has to be XOR'ed with check nibble
// identified above to restore valid ECC
checkCorrectionMask_ = s0;
}
}
// If nibble s1 != 0 - Row 7 of Table A-10
else if (s1 != 0)
{
// The remaining three nibble should be zero
if ((s0 == 0) && (s2 == 0) && (s3 == 0))
{
// For it to be a valid single-bit correctable
// check bit error
correctableCheckBitError = true;
// use big endian to index nibble position
badCheckNibblePosition_ = 2;
checkCorrectionMask_ = s1;
// This mask has to be XOR'ed with check nibble
// identified above to restore valid ECC
}
}
// If nibble s2 != 0 - Row 8 of Table A-10
else if (s2 != 0)
{
// The remaining three nibble should be zero
if ((s0 == 0) && (s1 == 0) && (s3 == 0))
{
// For it to be a valid single-bit correctable
// check bit error
correctableCheckBitError = true;
// use big endian to index nibble position
badCheckNibblePosition_ = 1;
// This mask has to be XOR'ed with check nibble
// identified above to restore valid ECC
checkCorrectionMask_ = s2;
}
}
// If nibble s3 != 0 - Row 9 of Table A-10
else if (s3 != 0)
{
// The remaining three nibble should be zero
if ((s0 == 0) && (s1 == 0) && (s2 == 0))
{
// For it to be a valid single-bit correctable
// check bit error
correctableCheckBitError = true;
// use big endian to index nibble position
badCheckNibblePosition_ = 0;
// This mask has to be XOR'ed with check nibble
// identified above to restore valid ECC
checkCorrectionMask_ = s3;
}
}
return correctableCheckBitError;
}
uint64_t getSyndrome() const { return syndrome_; }
uint32_t getBadDataNibblePosition()
{
if (!isCorrectableDataBitError())
{
fprintf(stderr,"BL_CKSyndrome::"
"getBadDataNibblePosition(): "
"not correctable data error");
exit(-1);
}
return badDataNibblePosition_;
}
uint32_t getBadCheckNibblePosition()
{
if (!isCorrectableCheckBitError())
{
fprintf(stderr,"BL_CKSyndrome::"
"getBadCheckNibblePosition(): "
"not correctable check error");
exit(-1);
}
return badCheckNibblePosition_;
}
uint64_t getDataCorrectionMask()
{
if (!isCorrectableDataBitError())
{
fprintf(stderr,"BL_CKSyndrome::"
"getDataCorrectionMask(): "
"not correctable data error");
exit(-1);
}
return dataCorrectionMask_;
}
uint64_t getCheckCorrectionMask()
{
if (!isCorrectableCheckBitError())
{
fprintf(stderr,"BL_CKSyndrome::"
"getCheckCorrectionMask(): "
"not correctable check error");
exit(-1);
}
return checkCorrectionMask_;
}
bool correctChipKillLine(BL_CKEccFile::ChipKillLine &line)
{
if (!isCorrectableDataBitError())
{
return false;
}
uint32_t nibbleNdx = getBadDataNibblePosition();
uint64_t nibbleMask = getDataCorrectionMask();
if (nibbleNdx < 16)
{
line.lsdw ^= nibbleMask << (4 * nibbleNdx);
}
else
{
line.msdw ^= nibbleMask << (4 * (nibbleNdx - 16));
}
return true;
}
bool correctChipKillECC(uint64_t &ecc)
{
if (!isCorrectableCheckBitError())
{
return false;
}
uint32_t nibbleNdx = getBadCheckNibblePosition();
uint64_t nibbleMask = getCheckCorrectionMask();
ecc ^= nibbleMask << (4 * nibbleNdx);
return true;
}
protected:
BL_CKSyndrome();
uint64_t syndrome_;
uint32_t badDataNibblePosition_;
uint32_t badCheckNibblePosition_;
uint64_t dataCorrectionMask_;
uint64_t checkCorrectionMask_;
private:
// The following 2 Dimensional Matrix implements Table A-12 of
// N2 PRM rev1.1 First dimension is Syndrome0. Second
// dimension is Syndrome1 The values contained in the matrix
// are the possible values for Syndrome3 in hexadecimal for a
// given [synd0,synd1], the value of synd3 should exactly
// match the value present in this table for the data bit
// error to be correctable (single bit) otherwise it is an
// uncorrectable (multibit) error
static const uint32_t a0bcErrorValidationMatrix[16][16];
// The following 2 Dimensional Matrix implements Table A-11 of
// N2 PRM rev1.1 First dimension is Syndrome0. Second
// dimension is Syndrome1 // The data present at the
// intersection [synd0,synd1], represents the Data Nibble that
// has the correctable error! // The correction mask is the
// value of Syndrome1
static const uint32_t a0bcErrorNibbleIdentityMatrix[16][16];
// The following 2 Dimensional Matrix implements Table A-14 of
// N2 PRM rev1.1 First dimension is Syndrome0. Second
// dimension is Syndrome2 The values contained in the matrix
// are the possible values for Syndrome3 in hexadecimal for a
// given [synd0,synd2], the value of synd3 should exactly
// match the value present in this table for the data bit
// error to be correctable (single bit) otherwise it is an
// uncorrectable (multibit) error
static const uint32_t ab0cErrorValidationMatrix[16][16];
// The following 2 Dimensional Matrix implements Table A-13 of
// N2 PRM rev1.1 First dimension is Syndrome0. Second
// dimension is Syndrome2 // The data present at the
// intersection [synd0,synd2], represents the Data Nibble that
// has the correctable error!
// The correction mask is the value of Syndrome2
static const uint32_t ab0cErrorNibbleIdentityMatrix[16][16];
};
#endif //__BL_CKSyndrome_h__