// ========== Copyright Header Begin ==========================================
// OpenSPARC T2 Processor File: SS_CKMemory.cc
// 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 ============================================
SS_CKMemory::SS_CKMemory(SS_Memory
*mem
)/*{{{*/
debug_CK(getenv("CK_CHIPKILL_DEBUG") != NULL
)
SS_CKMemory::~SS_CKMemory()/*{{{*/
uint64_t SS_CKMemory::ras_ld_buf( uint64_t addr
, uint_t size
)/*{{{*/
mem_xact
.access(MemoryTransaction::READ
);
mem_xact
.referenceType(MemoryTransaction::DATA
);
read_dram_error_corrected(mem_xact
);
return mem_xact
.getData();
void SS_CKMemory::ras_ld( uint64_t addr
, uint_t size
, uint64_t* data
)/*{{{*/
mem_xact
.access(MemoryTransaction::READ
);
mem_xact
.referenceType(MemoryTransaction::DATA
);
read_dram_error_corrected(mem_xact
);
for (uint_t i
=0; size
; i
++, size
-= 8)
data
[i
]= mem_xact
.getData(i
);
uint32_t SS_CKMemory::fetch32( uint64_t addr
)/*{{{*/
mem_xact
.access(MemoryTransaction::READ
);
mem_xact
.referenceType(MemoryTransaction::INSTR
);
read_dram_error_corrected(mem_xact
);
return mem_xact
.getData();
void SS_CKMemory::fetch256( uint64_t addr
, uint64_t data
[4] )/*{{{*/
mem_xact
.access(MemoryTransaction::READ
);
mem_xact
.referenceType(MemoryTransaction::INSTR
);
read_dram_error_corrected(mem_xact
);
for (uint_t i
=0; size
; i
++, size
-= 8)
data
[i
]= mem_xact
.getData(i
);
void SS_CKMemory::fetch512( uint64_t addr
, uint64_t data
[8] )/*{{{*/
mem_xact
.access(MemoryTransaction::READ
);
mem_xact
.referenceType(MemoryTransaction::INSTR
);
read_dram_error_corrected(mem_xact
);
for (uint_t i
=0; size
; i
++, size
-= 8)
data
[i
]= mem_xact
.getData(i
);
void SS_CKMemory::st8( uint64_t addr
, uint8_t data
)/*{{{*/
void SS_CKMemory::st16( uint64_t addr
, uint16_t data
)/*{{{*/
void SS_CKMemory::st32( uint64_t addr
, uint32_t data
)/*{{{*/
void SS_CKMemory::st64( uint64_t addr
, uint64_t data
)/*{{{*/
void SS_CKMemory::st128( uint64_t addr
, uint64_t data
[2] )/*{{{*/
ss_mem
->st128(addr
,data
);
void SS_CKMemory::st512( uint64_t addr
, uint64_t data
[8] )/*{{{*/
ss_mem
->st512(addr
,data
);
uint8_t SS_CKMemory::ld8u ( uint64_t addr
)/*{{{*/
return ras_ld_buf(addr
,1);
int8_t SS_CKMemory::ld8s( uint64_t addr
)/*{{{*/
return ras_ld_buf(addr
,1);
uint16_t SS_CKMemory::ld16u( uint64_t addr
)/*{{{*/
return ras_ld_buf(addr
,2);
int16_t SS_CKMemory::ld16s( uint64_t addr
)/*{{{*/
return ras_ld_buf(addr
,2);
uint32_t SS_CKMemory::ld32u( uint64_t addr
)/*{{{*/
return ras_ld_buf(addr
,4);
int32_t SS_CKMemory::ld32s( uint64_t addr
)/*{{{*/
return ras_ld_buf(addr
,4);
uint64_t SS_CKMemory::ld64( uint64_t addr
)/*{{{*/
return ras_ld_buf(addr
,8);
void SS_CKMemory::ld128( uint64_t addr
, uint64_t data
[2] ) /*{{{*/
void SS_CKMemory::ld256( uint64_t addr
, uint64_t data
[4] )/*{{{*/
void SS_CKMemory::ld512( uint64_t addr
, uint64_t data
[8] )/*{{{*/
void SS_CKMemory::st64partial( uint64_t addr
, uint64_t data
, uint64_t mask
) /*{{{*/
ss_mem
->st64partial(addr
,data
,mask
);
void SS_CKMemory::ld128atomic( uint64_t addr
, uint64_t data
[2] )/*{{{*/
uint8_t SS_CKMemory::ldstub( uint64_t addr
)/*{{{*/
mem_xact
.referenceType(MemoryTransaction::DATA
);
mem_xact
.access(MemoryTransaction::READ
|MemoryTransaction::ATOMIC
);
read_dram_error_corrected(mem_xact
);
uint64_t data
= mem_xact
.getData();
ss_mem
->poke8(addr
,0xff);
uint32_t SS_CKMemory::swap( uint64_t addr
, uint32_t rd
)/*{{{*/
mem_xact
.referenceType(MemoryTransaction::DATA
);
mem_xact
.access(MemoryTransaction::READ
|MemoryTransaction::ATOMIC
);
read_dram_error_corrected(mem_xact
);
uint64_t data
= mem_xact
.getData();
uint64_t SS_CKMemory::casx( uint64_t addr
, uint64_t rd
, uint64_t rs2
)/*{{{*/
mem_xact
.referenceType(MemoryTransaction::DATA
);
mem_xact
.access(MemoryTransaction::READ
|MemoryTransaction::ATOMIC
);
read_dram_error_corrected(mem_xact
);
uint64_t data
= mem_xact
.getData();
uint32_t SS_CKMemory::cas( uint64_t addr
, uint32_t rd
, uint32_t rs2
)/*{{{*/
mem_xact
.referenceType(MemoryTransaction::DATA
);
mem_xact
.access(MemoryTransaction::READ
|MemoryTransaction::ATOMIC
);
read_dram_error_corrected(mem_xact
);
uint32_t data
= mem_xact
.getData();
// read_dram_error_corrected() reads the memory specified in a
// MemoryTransaction, memXact, and applies Chip-Kill error correction
// to the data as needed.
// Returns false if memXact specifies no Chip-Kill correction or if the
// access is to the I/O space (where CK doesn't apply).
bool SS_CKMemory::read_dram_error_corrected(MemoryTransaction
&memXact
)/*{{{*/
if (memXact
.writeXact()) {
fprintf(stderr
, "SS_CKMemory::corrrectDramError() "
"WRITE or READ_WRITE memXact.");
if( memXact
.size() < 8 ){
memXact
.setData(read_short_corrected_dram_data(memXact
.paddr(),
if( memXact
.size() % 8 ){
fprintf(stderr
, "Read of size %d, is not a multiple of 8 bytes",
uint_t size
= memXact
.size() / 8;
for( uint_t i
= 0; i
< size
; ++i
){
uint64_t data
= read_corrected_dram_data(memXact
.paddr() + i
* 8, 8);
memXact
.setData(i
, data
);
// read_corrected_dram_data() reads Chip-Kill corrected data from
// paddress. Allowed sizes are 1, 2, 4, and multiples of 8.
uint64_t SS_CKMemory::read_corrected_dram_data(uint64_t paddress
,
return read_short_corrected_dram_data(paddress
, size
);
fprintf(stderr
, "SS_CKMemory::readCorrectedDramData: read of "
"size %d, is not a multiple of 8 bytes", size
);
uint64_t ckPaddr
= paddress
& ~(DRAM_LINE_LENGTH
- 1);
BL_CKEccFile::ChipKillLine line
= read_raw_CK_line(ckPaddr
);
if (ecc_exists(ckPaddr
)) {
uint64_t storedECC
= fetch_ecc(ckPaddr
);
uint64_t old_msdw
= line
.msdw
;
uint64_t old_lsdw
= line
.lsdw
;
// if debugging Chip-Kill, inject data errors
line
.msdw
^= ((random() % 16) << (4*(random() % 16)));
line
.lsdw
^= ((random() % 16) << (4*(random() % 16)));
BL_CKSyndrome
ckSyndrome(line
, storedECC
);
// if there is no error for this CK line, remove its ECC value
if (ckSyndrome
.noError()) {
dram_ecc_map
.erase(ckPaddr
);
} else { // try to fix the line
ckSyndrome
.correctChipKillLine(line
);
// if the error weren't fixed, die
if (debug_CK
&& old_msdw
!= line
.msdw
&& old_lsdw
!= line
.lsdw
) {
fprintf(stderr
,"SS_CKMemory::"
"readCorrectedDramData(): "
return (paddress
& (DRAM_LINE_LENGTH
/2)) ? line
.lsdw
: line
.msdw
;
// read_short_corrected_dram_data() reads Chip-Kill corrected data from
// paddress. Allowed sizes are 1, 2, 4.
uint64_t SS_CKMemory::read_short_corrected_dram_data(uint64_t paddress
,
uint64_t data
= read_corrected_dram_data(paddress
& ~0x07ULL
, 8);
data
= ( data
>> ( 32 - (paddress
& 0x04ULL
) * 8)) & 0x0ffffffff;
data
= ( data
>> ( 48 - (paddress
& 0x06ULL
) * 8)) & 0x0ffff;
data
= ( data
>> ( 56 - (paddress
& 0x07ULL
) * 8)) & 0x0ff;
fprintf(stderr
, "Read of size %d is not supported. Reads must be "
"1, 2, 4, or 8 bytes.", size
);
/*fprintf(stderr, "Read of %d bytes of data from 0x%0.16llx data=%0.16llx\n",
size, paddress, data );*/