Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / cpus / vonk / n2 / lib / ras / src / N2_MemErrDetector.h
/*
* ========== Copyright Header Begin ==========================================
*
* OpenSPARC T2 Processor File: N2_MemErrDetector.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 ============================================
*/
#ifndef _N2_MEMERRDETECTOR_H
#define _N2_MEMERRDETECTOR_H
/************************************************************************
**
** Copyright (C) 2005, 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.
**
*************************************************************************/
#include "MemoryTransaction.h"
#include "SS_MemErrDetector.h"
#include "BL_Memory.h"
#include "SS_CsrAccess.h"
#include "N2_Strand.h"
#include "BL_CKEcc.h"
#include "BL_CKSyndrome.h"
#include "BL_HammingEcc.h"
#include "BL_Hamming_32_7_Synd.h"
#include "N2_L2AddressingFields.h"
#include "N2_L2CacheFlushAddrFields.h"
#include "N2_L2DiagDataAddressingFields.h"
#include "N2_L2ErrorEnMem.h"
#include "N2_L2ErrorStatusReg.h"
#include "N2_L2ControlReg.h"
#include "N2_L2ErrorAddressReg.h"
#include "N2_L2DiagDataMem.h"
#include "N2_L2DiagTagMem.h"
#include "N2_L2DiagVdMem.h"
#include "N2_L2DiagUaMem.h"
#include "N2_L2NotdataErrorReg.h"
#include "N2_DramErrorStatusMem.h"
#include "N2_DramErrorInjectMem.h"
#include "N2_DramErrorCounterMem.h"
#include "N2_DramErrorLocMem.h"
#include "N2_DramFbdInjectedErrSrcReg.h"
#include "N2_DramFbdCountReg.h"
#include "N2_DramFbdErrorSyndromeReg.h"
#include "N2_SocErrorInjectReg.h"
#include "N2_SocErrorStatusReg.h"
#include "N2_SocPendingErrStatusReg.h"
#include "N2_SocErrorLogEnableReg.h"
#include "N2_SocErrorIntrEnReg.h"
#include "N2_SocFatalErrorEnableReg.h"
#include "N2_SocErrorSteeringReg.h"
class N2_Model;
/**
* The N2_MemErrDetector class is used to detect injected RAS errors
* associated with the memory hierarchy. In particular, it models and
* detects errors in the primary and secondary caches and DRAM.
*/
#define RAS_OSTR debugOutput_ && cerr
// Memory Error Detector for RAS
//
// Detects RAS error related to memory access: primary cache,
// secondary cache, DRAM and FBDIMM errors.
class N2_Core;
class N2_MemErrDetector : public SS_MemErrDetector {
public:
// Extend class to include update() method which guarantees (or rather,
// approximates) writing to the L2 Error Status Register.
class N2_CheckedL2ESRAccess : public SS_CsrAccess<N2_L2ErrorStatusReg> {
public:
N2_CheckedL2ESRAccess(SS_Csr& csr):
SS_CsrAccess<N2_L2ErrorStatusReg>(csr) {}
~N2_CheckedL2ESRAccess() {}
const N2_CheckedL2ESRAccess &
operator=( const N2_CheckedL2ESRAccess &rhs ) {
fprintf(stderr, "Unimplemented function." );
exit(-1);
return *this;
}
// add update checking to insure the MEC, MEU, etc. bits are set
// correctly. Returns true if the N2_L2ErrorAddressReg associated
// with the error should also be updated.
bool access(uint64_t ndx, N2_L2ErrorStatusReg &csr, bool isRead);
private:
N2_CheckedL2ESRAccess();
};
// Extend N2_L2DiagVdMem class to include ECC and syndrome calculators
class N2_L2DiagVdMemWithECC : public N2_L2DiagVdMem {
public:
N2_L2DiagVdMemWithECC() {}
N2_L2DiagVdMemWithECC( const N2_L2DiagVdMemWithECC& obj ) :
N2_L2DiagVdMem(obj)
{}
~N2_L2DiagVdMemWithECC() {}
// Shifts used to convert VD diag data into dirty and valid bits with ECC
static const N2_L2_DIAG_VD_ACCESS_VALID_SHIFT = 16;
static const N2_L2_DIAG_VD_ACCESS_DIRTY_SHIFT = 0;
static const N2_L2_DIAG_VD_ACCESS_ECC_SHIFT = 0;
uint32_t getVD() const
{
return (getVALID() << N2_L2_DIAG_VD_ACCESS_VALID_SHIFT) |
getDIRTY();
}
void setVD(uint32_t vd)
{
setDIRTY(vd);
setVALID(vd >> N2_L2_DIAG_VD_ACCESS_VALID_SHIFT);
}
uint32_t calcECC(void) const
{
return (BL_Hamming_32_7_Synd::calc_check_bits(getVD())).get();
}
BL_Hamming_32_7_Synd getSyndrome(void) const
{
return BL_Hamming_32_7_Synd(getVD(), getVDECC());
}
};
struct N2_L2VaudSyndrome {
N2_L2VaudSyndrome() :
vdSyndrome_(0),
uaSyndrome_(0){}
~N2_L2VaudSyndrome() {}
N2_L2VaudSyndrome(uint32_t vdSyndrome,uint32_t uaSyndrome) :
vdSyndrome_(vdSyndrome),
uaSyndrome_(uaSyndrome){}
BL_Hamming_32_7_Synd vdSyndrome_;
BL_Hamming_32_7_Synd uaSyndrome_;
};
// Extend N2_L2DiagUaMem class to include ECC and syndrome calculators
class N2_L2DiagUaMemWithECC : public N2_L2DiagUaMem {
public:
N2_L2DiagUaMemWithECC() {}
N2_L2DiagUaMemWithECC( const N2_L2DiagUaMemWithECC& obj ) :
N2_L2DiagUaMem(obj)
{}
~N2_L2DiagUaMemWithECC() {}
// Shifts used to convert VD diag data into dirty and valid bits with ECC
static const N2_L2_DIAG_UA_ACCESS_USED_SHIFT = 16;
static const N2_L2_DIAG_UA_ACCESS_ALLOC_SHIFT = 0;
static const N2_L2_DIAG_UA_ACCESS_ECC_SHIFT = 0;
uint32_t getUA() const
{
return (getUSED() << N2_L2_DIAG_UA_ACCESS_USED_SHIFT) |
getALLOC();
}
void setUA(uint32_t vd)
{
setALLOC(vd);
setUSED(vd >> N2_L2_DIAG_UA_ACCESS_USED_SHIFT);
}
uint32_t calcECC(void) const
{
return (BL_Hamming_32_7_Synd::calc_check_bits(getUA())).get();
}
BL_Hamming_32_7_Synd getSyndrome(void) const
{
return BL_Hamming_32_7_Synd(getUA(), getUAECC());
}
};
// Extend N2_L2DiagDataMem class to include ECC and syndrome calculators
class N2_L2DiagDataMemWithECC : public N2_L2DiagDataMem {
public:
N2_L2DiagDataMemWithECC() {}
N2_L2DiagDataMemWithECC( const N2_L2DiagDataMemWithECC& obj ) :
N2_L2DiagDataMem(obj)
{}
~N2_L2DiagDataMemWithECC() {}
uint32_t calcECC(void) const
{
return (BL_Hamming_32_7_Synd::calc_check_bits(getDATA())).get();
}
BL_Hamming_32_7_Synd getSyndrome(void) const
{
return BL_Hamming_32_7_Synd(getDATA(), getECC());
}
static const uint64_t L2_NOT_DATA = 0x7f;
};
// This class captures the error status of an L2 cache data quarter
// line.
// The ECC syndromes for 4 32-bit words are captured in the
// qLineSyndrome_ field and the physical address corresponding to the
// ECC error, if any, is in the errorPaddr_ field.
class N2_L2CacheLineError {
public:
typedef enum {
NO_ERROR,
CORRECTABLE_ERROR,
UNCORRECTABLE_ERROR,
NOT_DATA
} errorType_t;
N2_L2CacheLineError(uint64_t errorPaddr) :
errorType_(NO_ERROR),
qLineSyndrome_(0),
errorPaddr_(errorPaddr),
wordNdx_(0)
{}
virtual ~N2_L2CacheLineError() {}
/*
* Assignment operator
*
* @param rhs The right hand side of the assignment operator.
* @return The lvalue of the assignment.
*/
const N2_L2CacheLineError &
operator=( const N2_L2CacheLineError &rhs )
{
errorType_ = rhs.errorType_;
qLineSyndrome_ = rhs.qLineSyndrome_;
errorPaddr_ = rhs.errorPaddr_;
wordNdx_ = rhs.wordNdx_;
return *this;
}
// if qLineSyndrome, not qLineSyndrome_, compiler bug?!?
bool isError() const { return qLineSyndrome_ != 0; }
uint32_t qLineSyndrome() const { return qLineSyndrome_; }
uint64_t errorPaddr() const { return errorPaddr_; }
bool isCorrectable() const { return isError() &&
errorType_ == CORRECTABLE_ERROR; }
bool isUncorrectable() const { return isError() &&
(errorType_ == UNCORRECTABLE_ERROR ||
errorType_ == NOT_DATA); }
bool isNotData() const { return isError() &&
errorType_ == NOT_DATA; }
void addQuarterLine(BL_Hamming_32_7_Synd wordSyndrome) {
qLineSyndrome_ |= (wordSyndrome.getSyndrome() << ( 7 * wordNdx_++));
// dispatch on current worst cache line error type.
// Incorportate error from current word into quarter line's
// error type.
switch (errorType_) {
case NO_ERROR: // any new error bad
if (!wordSyndrome.noError()) {
errorType_ = CORRECTABLE_ERROR;
}
/* consider NotData or uncorrectable possibility by
falling through */
/* FALLTHROUGH*/
case CORRECTABLE_ERROR: // is new uncorrectable?
if (wordSyndrome.isUncorrectableError()) {
errorType_ = UNCORRECTABLE_ERROR;
}
/* consider NotData possibility by falling through */
/* FALLTHROUGH*/
case UNCORRECTABLE_ERROR: // only NOT_DATA is worse
if (wordSyndrome.getSyndrome() ==
N2_L2DiagDataMemWithECC::L2_NOT_DATA) {
errorType_ = NOT_DATA;
}
break;
case NOT_DATA: // can't get any worse than this
break;
default:
fprintf(stderr, "N2_L2CacheLineError::addQuarterLine "
"bad errorType_ 0x%x", errorType_);
exit(-1);
}
}
private:
N2_L2CacheLineError() {}
errorType_t errorType_;
uint32_t qLineSyndrome_;
uint64_t errorPaddr_;
uint_t wordNdx_;
};
class N2_CererWithBitMux : public N2_Cerer {
public:
~N2_CererWithBitMux() {}
N2_CererWithBitMux(const N2_CererWithBitMux &obj) :
N2_Cerer(obj) {}
N2_CererWithBitMux(const N2_Cerer &obj) :
N2_Cerer(obj) {}
bool checkOneL2Cbit(const MemoryTransaction &memXact) {
return
(this->l2c_socc() && memXact.tablewalk()) ||
(icl2c() &&
memXact.referenceType() == MemoryTransaction::INSTR) ||
(dcl2c() &&
memXact.referenceType() == MemoryTransaction::DATA);
}
bool checkAnyL2Cbit() {
return icl2c() || dcl2c();
}
private:
N2_CererWithBitMux() :
N2_Cerer(){}
};
N2_MemErrDetector(SS_Model *model) :
n2_model(model),
L2ControlRegAccess_(((N2_Model*)n2_model)->csr),
L2ErrorStatusRegAccess_(((N2_Model*)n2_model)->csr),
L2ErrorAddressRegAccess_(((N2_Model*)n2_model)->csr),
L2ErrorEnMemAccess_(((N2_Model*)n2_model)->csr),
L2DiagDataMemAccess_(((N2_Model*)n2_model)->csr),
L2DiagTagMemAccess_(((N2_Model*)n2_model)->csr),
L2DiagVdMemAccess_(((N2_Model*)n2_model)->csr),
L2DiagUaMemAccess_(((N2_Model*)n2_model)->csr),
L2NotdataErrorRegAccess_(((N2_Model*)n2_model)->csr),
DramErrorStatusMemAccess_(((N2_Model*)n2_model)->csr),
DramErrorInjectMemAccess_(((N2_Model*)n2_model)->csr),
DramErrorCounterMemAccess_(((N2_Model*)n2_model)->csr),
DramErrorLocMemAccess_(((N2_Model*)n2_model)->csr),
DramFbdInjectedErrSrcRegAccess_(((N2_Model*)n2_model)->csr),
DramFbdCountRegAccess_(((N2_Model*)n2_model)->csr),
DramFbdErrorSyndromeRegAccess_(((N2_Model*)n2_model)->csr),
socErrorInjectRegAccess_(((N2_Model*)n2_model)->csr),
socErrorStatusRegAccess_(((N2_Model*)n2_model)->csr),
socPendingErrStatusRegAccess_(((N2_Model*)n2_model)->csr),
socErrorLogEnableRegAccess_(((N2_Model*)n2_model)->csr),
socErrorIntrEnRegAccess_(((N2_Model*)n2_model)->csr),
socFatalErrorEnableRegAccess_(((N2_Model*)n2_model)->csr),
socErrorSteeringRegAccess_(((N2_Model*)n2_model)->csr),
debugOutput_(getenv("RAS_DEBUG") != NULL),
debugChipKill_(getenv("CHIPKILL_DEBUG") != NULL)
{
for (int bank = 0; bank < N2_L2_CACHE_NR_BANKS; ++bank) {
L2CacheWaysNRUPtr_[bank] = 0;
}
step_hook = n2_step_hook;
//tick_err_detector = n2_tick_cmpr_disrupting_err_detector;
}
/**
* Copy constructor
*
* @param orig The MemErrDetector object to copy.
*/
N2_MemErrDetector( const N2_MemErrDetector &orig ) :
n2_model(orig.n2_model),
L2ControlRegAccess_(orig.L2ControlRegAccess_),
L2ErrorStatusRegAccess_(orig.L2ErrorStatusRegAccess_),
L2ErrorAddressRegAccess_(orig.L2ErrorAddressRegAccess_),
L2ErrorEnMemAccess_(orig.L2ErrorEnMemAccess_),
L2DiagDataMemAccess_(orig.L2DiagDataMemAccess_),
L2DiagTagMemAccess_(orig.L2DiagTagMemAccess_),
L2DiagVdMemAccess_(orig.L2DiagVdMemAccess_),
L2DiagUaMemAccess_(orig.L2DiagUaMemAccess_),
L2NotdataErrorRegAccess_(orig.L2NotdataErrorRegAccess_),
DramErrorStatusMemAccess_(orig.DramErrorStatusMemAccess_),
DramErrorInjectMemAccess_(orig.DramErrorInjectMemAccess_),
DramErrorCounterMemAccess_(orig.DramErrorCounterMemAccess_),
DramErrorLocMemAccess_(orig.DramErrorLocMemAccess_),
DramFbdInjectedErrSrcRegAccess_(orig.DramFbdInjectedErrSrcRegAccess_),
DramFbdCountRegAccess_(orig.DramFbdCountRegAccess_),
DramFbdErrorSyndromeRegAccess_(orig.DramFbdErrorSyndromeRegAccess_),
socErrorInjectRegAccess_(orig.socErrorInjectRegAccess_),
socErrorStatusRegAccess_(orig.socErrorStatusRegAccess_),
socPendingErrStatusRegAccess_(orig.socPendingErrStatusRegAccess_),
socErrorLogEnableRegAccess_(orig.socErrorLogEnableRegAccess_),
socErrorIntrEnRegAccess_(orig.socErrorIntrEnRegAccess_),
socFatalErrorEnableRegAccess_(orig.socFatalErrorEnableRegAccess_),
socErrorSteeringRegAccess_(orig.socErrorSteeringRegAccess_),
debugOutput_(orig.debugOutput_),
debugChipKill_(orig.debugChipKill_)
{
for (int bank = 0; bank < N2_L2_CACHE_NR_BANKS; ++bank) {
L2CacheWaysNRUPtr_[bank] = orig.L2CacheWaysNRUPtr_[bank] ;
}
}
/**
* Destructor
*/
virtual ~N2_MemErrDetector() {}
/**
* Equality operator
*
* @param rhs The right hand side of the equality operator
* @return Return true if this objec and rhs are equal,
* otherwise return false
*/
bool operator==( const N2_MemErrDetector &rhs ) const;
/**
* Assignment operator
*
* @param rhs The right hand side of the assignment operator.
* @return The lvalue of the assignment.
*/
const N2_MemErrDetector & operator=( const N2_MemErrDetector &rhs );
SS_Trap::Type detect_fetch_err( MemoryLevel level,
SS_Vaddr pc,
SS_Vaddr npc, SS_Strand* s, SS_Paddr pa) ;
SS_Trap::Type detect_load_err( MemoryLevel level,
SS_Vaddr pc, SS_Vaddr npc,
SS_Strand* s, SS_Instr* line,
SS_Paddr pa) ;
SS_Trap::Type inject_store_err( MemoryLevel level,
SS_Vaddr pc, SS_Vaddr npc,
SS_Strand* s, SS_Instr* line,
SS_Paddr pa,
uint64_t data) ;
BL_EccBits N2_MemErrDetector::n2_tick_cmpr_err_injector(SS_Strand* s,
uint64_t data);
SS_Trap::Type N2_MemErrDetector::n2_tick_cmpr_precise_err_detector(SS_Strand* s,
N2_TickAccess::TickAccessIndex array_index);
static bool n2_tick_cmpr_disrupting_err_detector(SS_Strand* s);
// Returns whether an prefetch instruction is a prefetchICE
bool is_prefetchICE(SS_Opcode& opc)
{
return opc.get_fcn() == 0x18;
}
// Routine to flush L2 cache
void prefetchICE(SS_Paddr pa);
SS_Trap::Type ras_flush( SS_Vaddr pc, SS_Vaddr npc,
SS_Strand* s,
SS_Instr* line,
SS_Paddr pa,
uint64_t size,
CacheType type)
{ return SS_Trap::NO_TRAP; }
void ras_flush( SS_Strand*s, SS_Strand* requesting_strand, SS_Paddr pa, uint64_t size, CacheType type);
static SS_Trap::Type n2_step_hook(SS_Strand* s);
/**
* detectErr() throws traps and furballs when an RAS error
* has been injected in the memory hierarchy.
*/
SS_Trap::Type detectErr(const MemoryTransaction &memXact);
/**
* L2CacheFill takes a memory transaction and fills the
* L-cache as needed with data used by the transaction.
*/
SS_Trap::Type L2CacheFill(const MemoryTransaction &memXact);
void L2CacheFlush(N2_L2CacheFlushAddrFields flushAddr);
// In cache look-up routines, setting the way to this value
// means a miss or "no way" matched
const static int NO_WAY = -1;
// SWIG routines for controlling debugging output
void startDebugOutput() { debugOutput_ = true; }
void stopDebugOutput() { debugOutput_ = false; }
protected:
private:
//
// N2 PRM Rev 1.1 Sect B.5.1
// Basic L2 cache size parameters
// The number of sets per bank is:
// 4MB/8s = 512K bytes per bank
// 512K/64B = 8K lines per bank
// 8K/16 = 512 sets per bank
SS_Model *n2_model;
static const N2_L2_CACHE_LINE_SIZE = 64;
static const N2_L2_CACHE_NR_BANKS = 8;
static const N2_L2_CACHE_NR_SETS_PER_BANK = 512;
uint32_t L2CacheWaysNRUPtr_[N2_L2_CACHE_NR_BANKS];
std::map<uint64_t,uint64_t> dramECCMap_;
void L2FixTags(N2_L2AddressingFields paddr);
void L2FixTagsAndTrap(N2_Strand *strand,
N2_L2AddressingFields paddr,
const MemoryTransaction &memXact);
bool L2FixTag(uint32_t diagNdx);
N2_L2VaudSyndrome L2FixVUAD(N2_L2AddressingFields paddr,
N2_L2DiagVdMemWithECC &diagVD);
N2_L2DiagVdMemWithECC L2FixVUADAndTrap(N2_Strand *strand,
N2_L2AddressingFields paddr,
const MemoryTransaction &memXact);
int L2FindWay(N2_L2AddressingFields paddr,
N2_L2DiagVdMemWithECC diagVD);
SS_Trap::Type L2CacheMiss(N2_Strand *strand,
const MemoryTransaction &memXact,
N2_L2DiagVdMemWithECC &diagVD);
SS_Trap::Type L2CacheHit(N2_Strand *strand,
const MemoryTransaction &memXact,
N2_L2DiagVdMemWithECC &diagVD,
int hit_way);
N2_L2CacheLineError L2ProcessCacheLine(N2_L2AddressingFields paddr,
uint32_t way,
bool isRead);
N2_L2CacheLineError L2ProcessQuarterLine(N2_L2AddressingFields paddr,
uint32_t way,
bool isRead);
SS_Trap::Type ThrowL2DataTrap(const MemoryTransaction &memXact,
N2_Strand *strand,
uint32_t bank,
N2_L2CacheLineError lineError);
void ThrowL2DataCorrectableTrap(const MemoryTransaction &memXact,
N2_Strand *strand,
uint32_t bank,
N2_L2CacheLineError lineError);
SS_Trap::Type ThrowL2DataUncorrectableTrap(const MemoryTransaction &memXact,
N2_Strand *strand,
uint32_t bank,
N2_L2CacheLineError lineError);
void ThrowL2DataWriteBackTrap(const MemoryTransaction &memXact,
N2_Strand *strand,
uint32_t bank,
N2_L2CacheLineError lineError);
void poisonL2Line(N2_L2AddressingFields paddr, int way);
//
// Diagnostic access and modification routines.
//
typedef void (N2_L2ErrorStatusReg::*ErrorStatusRegBitSetFn)(uint64_t);
void setL2ErrorStatusReg(uint32_t bank,
ErrorStatusRegBitSetFn bitSetFunction,
bool isCorrectable,
uint32_t vcid,
uint32_t syndrome,
uint64_t errorAddr);
void setL2NotdataErrorReg(uint32_t bank,
uint32_t vcid,
uint64_t errorAddress);
// trapToErrorSteer() posts a trap to the ERRORSTEER core/strand
// associated with bank.
void trapToErrorSteer(N2_Strand *strand, uint32_t bank,
SS_Interrupt::Bit trapNr) {
N2_Strand *target_strand = (N2_Strand*)n2_model->cpu[0]->strand[getErrorSteer(bank)];
// Figure out which strand gets the trap from the L2 Control
// Register's ERRORSTEER field.
if(trapNr == SS_Interrupt::BIT_HW_CORRECTED_ERROR){
if(!strand->seter.dhcce())
return;
}
else if(trapNr == SS_Interrupt::BIT_SW_RECOVERABLE_ERROR){
if(!strand->seter.de())
return;
}
strand->irq.raise(target_strand,trapNr);
}
void setDESR(uint_t strandId,bool sw_recoverable_trap,
uint32_t errorType, uint32_t errorAddr)
{
N2_Strand *strand = (N2_Strand*)n2_model->cpu[0]->strand[strandId];
N2_Desr *desr = &(strand->desr);
if (!desr->f() )
{
// sets the Strand's desr; not a copy
desr->f(1); // full bit
// S <- 1 for SW_recoverable_trap
// S <- 0 for HW_corrected_error
desr->s(sw_recoverable_trap);
desr->errtype(errorType); // error code
desr->erraddr(errorAddr); // error address
}
else
{ // set multiple error bit
desr->me(1);
}
}
// Get the CEEN bit from the L2$ error enable register
uint32_t getCEEN(uint32_t bank) {
N2_L2ErrorEnMem L2ErrorEnableReg;
L2ErrorEnMemAccess_.access(bank, L2ErrorEnableReg, true);
return L2ErrorEnableReg.getCEEN();
}
// Get the NCEEN bit from the L2$ error enable register
bool getNCEEN(uint32_t bank) {
N2_L2ErrorEnMem L2ErrorEnableReg;
L2ErrorEnMemAccess_.access(bank, L2ErrorEnableReg, true);
return L2ErrorEnableReg.getNCEEN();
}
// Get the ERRORSTEER core/strand id from the L2$ error control reg
uint_t getErrorSteer(uint32_t bank) {
N2_L2ControlReg L2ControlReg;
L2ControlRegAccess_.access(bank, L2ControlReg, true);
return L2ControlReg.getERRORSTEER();
}
// get a set-bank index into a diagnostic csr array from a
// physical address
static uint64_t paddrToSetBankNdx(N2_L2AddressingFields paddr)
{
uint64_t diagNdx = paddr.getSET();
diagNdx <<= N2_L2AddressingFields::bitSizeBANK;
return (diagNdx | paddr.getBANK());
}
// get a way-set-bank index into a diagnostic csr array from a
// physical address
static uint64_t paddrToWaySetBankNdx(N2_L2AddressingFields paddr,
uint32_t way)
{
uint64_t diagNdx = way;
diagNdx <<= N2_L2AddressingFields::bitSizeSET;
diagNdx |= paddr.getSET();
diagNdx <<= N2_L2AddressingFields::bitSizeBANK;
return (diagNdx | paddr.getBANK());
}
void DramThrowCorrectableTrap(N2_Strand *strand,
const MemoryTransaction &memXact,
uint32_t bank);
SS_Trap::Type DramThrowUncorrectableTrap(N2_Strand *strand,
const MemoryTransaction &memXact,
uint32_t bank);
static const uint64_t N2_DRAM_PADDR_MCU_SHIFT = 6;
static const uint64_t N2_DRAM_PADDR_NR_MCU_LOG2 = 2;
static const uint64_t N2_DRAM_PADDR_NR_MCU =
(1<< N2_DRAM_PADDR_NR_MCU_LOG2);
// Diagnostic access and modification routines.
SS_Trap::Type dramProcessMemOp(N2_Strand *strand,
const MemoryTransaction &memXact,
N2_L2AddressingFields paddr,bool &);
void dramUpdateECC(N2_L2AddressingFields paddr, bool isNotData);
// Soc Error Detection and Correction Routines
void processSocFbdError(N2_Strand &strand,
N2_L2AddressingFields paddress,
N2_SocErrorReg::SocErrRegBitGetFn getFBR);
// Accessor Templates for L2$ Control Registers and Diag Access
SS_CsrAccess<N2_L2ControlReg> L2ControlRegAccess_;
N2_CheckedL2ESRAccess L2ErrorStatusRegAccess_;
SS_CsrAccess<N2_L2ErrorAddressReg> L2ErrorAddressRegAccess_;
SS_CsrAccess<N2_L2ErrorEnMem> L2ErrorEnMemAccess_;
SS_CsrAccess<N2_L2DiagDataMem> L2DiagDataMemAccess_;
SS_CsrAccess<N2_L2DiagTagMem> L2DiagTagMemAccess_;
SS_CsrAccess<N2_L2DiagVdMemWithECC> L2DiagVdMemAccess_;
SS_CsrAccess<N2_L2DiagUaMemWithECC> L2DiagUaMemAccess_;
SS_CsrAccess<N2_L2NotdataErrorReg> L2NotdataErrorRegAccess_;
// Accessor Templates for Dram Control Registers
SS_CsrAccess<N2_DramErrorStatusMem> DramErrorStatusMemAccess_;
SS_CsrAccess<N2_DramErrorInjectMem> DramErrorInjectMemAccess_;
SS_CsrAccess<N2_DramErrorCounterMem> DramErrorCounterMemAccess_;
SS_CsrAccess<N2_DramErrorLocMem> DramErrorLocMemAccess_;
SS_CsrAccess<N2_DramFbdInjectedErrSrcReg>
DramFbdInjectedErrSrcRegAccess_;
SS_CsrAccess<N2_DramFbdCountReg> DramFbdCountRegAccess_;
SS_CsrAccess<N2_DramFbdErrorSyndromeReg>
DramFbdErrorSyndromeRegAccess_;
// Accessor Templates for Soc Error Control Registers
SS_CsrAccess<N2_SocErrorInjectReg> socErrorInjectRegAccess_;
SS_CsrAccess<N2_SocErrorStatusReg> socErrorStatusRegAccess_;
SS_CsrAccess<N2_SocPendingErrStatusReg> socPendingErrStatusRegAccess_;
SS_CsrAccess<N2_SocErrorLogEnableReg> socErrorLogEnableRegAccess_;
SS_CsrAccess<N2_SocErrorIntrEnReg> socErrorIntrEnRegAccess_;
SS_CsrAccess<N2_SocFatalErrorEnableReg> socFatalErrorEnableRegAccess_;
SS_CsrAccess<N2_SocErrorSteeringReg> socErrorSteeringRegAccess_;
bool debugOutput_;
// set to artificially inject Chip-Kill errors. Note that this
// can't be used with "real" CK error injection because it
// could result in uncorrectable double nibble errors.
bool debugChipKill_;
};
#endif /* _N2_MEMERRDETECTOR_H */