// ========== Copyright Header Begin ==========================================
// OpenSPARC T2 Processor File: N2_FrfEcc.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 ============================================
/************************************************************************
** Copyright (C) 2006, 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 "BL_Hamming_32_7_Synd.h"
// This routine injects errors into single precision registers in FRF if and
// only if the "ene" & "frcu" bits are set in the error injection register
extern "C" SS_Vaddr
n2_frf_ras_inject(SS_Vaddr pc
,
assert (reg_nr
>= 0 && reg_nr
< 64);
N2_Strand
* n2_strand
= (N2_Strand
*)s
;
N2_Core
& n2_core
= n2_strand
->core
;
unsigned value
= n2_strand
->get_frf(SS_Strand::freg_idx2off(reg_nr
));
BL_EccBits ecc_obj
= BL_Hamming_32_7_Synd::calc_check_bits(value
);
unsigned ecc
= ecc_obj
.get();
if ((n2_core
.error_inject
.ene()) && (n2_core
.error_inject
.frcu()))
ecc
^= n2_core
.error_inject
.eccmask();
n2_strand
->frf_ecc
[reg_nr
] = ecc_obj
;
return 0; // Not sure if this is the right value to return
// This routine injects errors into double precision registers in FRF
extern "C" SS_Vaddr
n2_frf_dp_ras_inject(SS_Vaddr pc
,
n2_frf_ras_inject(pc
,npc
,s
,i
,reg_nr
);
n2_frf_ras_inject(pc
,npc
,s
,i
,(reg_nr
+ 1));
// This method detects any errors (injected or otherwise), associtated
// with single precision registers in FRF
extern "C" SS_Vaddr
n2_frf_ras_detect(SS_Vaddr pc
,
return n2_frf_ras_detect_wrapper(pc
,npc
,s
,i
,reg_nr
,0);
// This method detects any errors (injected or otherwise), associtated
// with double precision registers in FRF
extern "C" SS_Vaddr
n2_frf_dp_ras_detect(SS_Vaddr pc
,
assert(!s
->sim_state
.trap_taken());
SS_Vaddr trap_pc
= n2_frf_ras_detect_wrapper(pc
,npc
,s
,i
,reg_nr
,1);
if (s
->sim_state
.trap_taken())
return n2_frf_ras_detect_wrapper(pc
,npc
,s
,i
,(reg_nr
+ 1),0);
// The following routine is where the actual error detection for FRF occurs
// This routine is called by both the Single and double precision variants
// The parameter 'bit_significance' determines if this register contains the
// least significant (31:0) bits or the most significant (63:32) bits. A value
// of 0 corresponds to LSB and a value of 1 corresponds to MSB. For single
// precision registers, the bit_significance is always zero.
// NOTE: This parameter has got nothing to do with the register number (ever or
// odd), but rather deals with the content. Usually for double precision values,
// a even numbered register will have MSB and an odd numbered register will have
// the LSB. But for single precision values, there is no such correspondance
// between register number and content and hence the need for this additional
extern "C" SS_Vaddr
n2_frf_ras_detect_wrapper(SS_Vaddr pc
,
assert (reg_nr
>= 0 && reg_nr
< 64);
N2_Strand
* n2_strand
= (N2_Strand
*)s
;
N2_Core
& n2_core
= n2_strand
->core
;
// Error Detection happens only if the FRF bit in CERER is set
unsigned value
= n2_strand
->get_frf(SS_Strand::freg_idx2off(reg_nr
));
BL_EccBits ecc_obj
= n2_strand
->frf_ecc
[reg_nr
];
// Check if the ecc associated with this register is a valid ecc
// Syndrome is the difference between the stored and calculated ECC values
BL_Hamming_32_7_Synd syndrome
= BL_Hamming_32_7_Synd(value
,ecc_obj
);
unsigned long long temp_reg
= reg_nr
;
// If the syndrome is not zero, then it means an ECC error has occured.
// Errors are recorded only if the PSCCE bit is set in the SETER
if (n2_strand
->seter
.pscce())
if (syndrome
.isSingleBitError())
n2_strand
->data_sfsr
.error_type(4);
else if (syndrome
.isDoubleBitError() || syndrome
.isMultipleBitError())
n2_strand
->data_sfsr
.error_type(3);
unsigned long long native_add
= 0;
unsigned long long intermediate_err_add
;
// The syndrome of LSB (31:0) should be recorded in bits 12:6 of DSFAR
if (bit_significance
== 0)
intermediate_err_add
= (native_add
& ~0x1fc0ULL
) |
syndrome
.getSyndrome() << 6;
// The syndrome of MSB (63:32) should be recorded in bits 19:13 of DSFAR
else if (bit_significance
== 1)
intermediate_err_add
= (native_add
& ~0xfe000ULL
) |
syndrome
.getSyndrome() << 13;
// Capture the register number in bits 5:0 of DSFAR
unsigned long long error_add
= (intermediate_err_add
& ~0x3fULL
) |
n2_strand
->data_sfar
.error_addr(error_add
);
return (s
->trap
)(pc
,npc
,s
,i
,SS_Trap::INTERNAL_PROCESSOR_ERROR
);
// If the ecc associated with the register is invalid
// Not sure what the exact functioning should be in this case
// Should we calculate clean ecc and associate it with this reg (as in Riesling)
// unsigned ecc = N2_EccFile::calc_n2_FRF_checks(value);
// Or should the program just call it quits!
// cerr << " Invalid ECC: Aborting!" << endl;