Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / cpus / vonk / n2 / lib / ras / src / N2_FrfEcc.cc
CommitLineData
920dae64
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: N2_FrfEcc.cc
4// Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
5// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
6//
7// The above named program is free software; you can redistribute it and/or
8// modify it under the terms of the GNU General Public
9// License version 2 as published by the Free Software Foundation.
10//
11// The above named program is distributed in the hope that it will be
12// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14// General Public License for more details.
15//
16// You should have received a copy of the GNU General Public
17// License along with this work; if not, write to the Free Software
18// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
19//
20// ========== Copyright Header End ============================================
21/************************************************************************
22**
23** Copyright (C) 2006, Sun Microsystems, Inc.
24**
25** Sun considers its source code as an unpublished, proprietary
26** trade secret and it is available only under strict license provisions.
27** This copyright notice is placed here only to protect Sun in the event
28** the source is deemed a published work. Disassembly, decompilation,
29** or other means of reducing the object code to human readable form
30** is prohibited by the license agreement under which this code is
31** provided to the user or company in possession of this copy.
32**
33*************************************************************************/
34
35#include "N2_Core.h"
36#include "N2_Strand.h"
37#include "N2_FrfEcc.h"
38#include "BL_Hamming_32_7_Synd.h"
39
40// This routine injects errors into single precision registers in FRF if and
41// only if the "ene" & "frcu" bits are set in the error injection register
42extern "C" SS_Vaddr n2_frf_ras_inject(SS_Vaddr pc,
43 SS_Vaddr npc,
44 SS_Strand* s,
45 SS_Instr* i,
46 int reg_nr)
47{
48 assert (reg_nr >= 0 && reg_nr < 64);
49 N2_Strand* n2_strand = (N2_Strand *)s;
50 N2_Core& n2_core = n2_strand->core;
51
52 unsigned value = n2_strand->get_frf(SS_Strand::freg_idx2off(reg_nr));
53 BL_EccBits ecc_obj = BL_Hamming_32_7_Synd::calc_check_bits(value);
54 unsigned ecc = ecc_obj.get();
55 if ((n2_core.error_inject.ene()) && (n2_core.error_inject.frcu()))
56 {
57 ecc ^= n2_core.error_inject.eccmask();
58 }
59 ecc_obj.set(ecc);
60 n2_strand->frf_ecc[reg_nr] = ecc_obj;
61 return 0; // Not sure if this is the right value to return
62}
63
64// This routine injects errors into double precision registers in FRF
65extern "C" SS_Vaddr n2_frf_dp_ras_inject(SS_Vaddr pc,
66 SS_Vaddr npc,
67 SS_Strand* s,
68 SS_Instr* i,
69 int reg_nr)
70{
71 n2_frf_ras_inject(pc,npc,s,i,reg_nr);
72 n2_frf_ras_inject(pc,npc,s,i,(reg_nr + 1));
73 return 0;
74}
75
76// This method detects any errors (injected or otherwise), associtated
77// with single precision registers in FRF
78extern "C" SS_Vaddr n2_frf_ras_detect(SS_Vaddr pc,
79 SS_Vaddr npc,
80 SS_Strand* s,
81 SS_Instr* i,
82 int reg_nr)
83{
84 return n2_frf_ras_detect_wrapper(pc,npc,s,i,reg_nr,0);
85}
86
87// This method detects any errors (injected or otherwise), associtated
88// with double precision registers in FRF
89extern "C" SS_Vaddr n2_frf_dp_ras_detect(SS_Vaddr pc,
90 SS_Vaddr npc,
91 SS_Strand* s,
92 SS_Instr* i,
93 int reg_nr)
94{
95 assert(!s->sim_state.trap_taken());
96 SS_Vaddr trap_pc = n2_frf_ras_detect_wrapper(pc,npc,s,i,reg_nr,1);
97 if (s->sim_state.trap_taken())
98 return trap_pc;
99 else
100 return n2_frf_ras_detect_wrapper(pc,npc,s,i,(reg_nr + 1),0);
101}
102
103// The following routine is where the actual error detection for FRF occurs
104// This routine is called by both the Single and double precision variants
105// of error detectors
106// The parameter 'bit_significance' determines if this register contains the
107// least significant (31:0) bits or the most significant (63:32) bits. A value
108// of 0 corresponds to LSB and a value of 1 corresponds to MSB. For single
109// precision registers, the bit_significance is always zero.
110// NOTE: This parameter has got nothing to do with the register number (ever or
111// odd), but rather deals with the content. Usually for double precision values,
112// a even numbered register will have MSB and an odd numbered register will have
113// the LSB. But for single precision values, there is no such correspondance
114// between register number and content and hence the need for this additional
115// parameter
116extern "C" SS_Vaddr n2_frf_ras_detect_wrapper(SS_Vaddr pc,
117 SS_Vaddr npc,
118 SS_Strand* s,
119 SS_Instr* i,
120 int reg_nr,
121 int bit_significance)
122{
123 assert (reg_nr >= 0 && reg_nr < 64);
124 N2_Strand* n2_strand = (N2_Strand *)s;
125 N2_Core& n2_core = n2_strand->core;
126
127 // Error Detection happens only if the FRF bit in CERER is set
128 if (n2_core.cerer.frf())
129 {
130 unsigned value = n2_strand->get_frf(SS_Strand::freg_idx2off(reg_nr));
131 BL_EccBits ecc_obj = n2_strand->frf_ecc[reg_nr];
132 // Check if the ecc associated with this register is a valid ecc
133 if (ecc_obj.valid())
134 {
135 // Syndrome is the difference between the stored and calculated ECC values
136 BL_Hamming_32_7_Synd syndrome = BL_Hamming_32_7_Synd(value,ecc_obj);
137 unsigned long long temp_reg = reg_nr;
138 // If the syndrome is not zero, then it means an ECC error has occured.
139 if (!syndrome.noError())
140 {
141 // Errors are recorded only if the PSCCE bit is set in the SETER
142 if (n2_strand->seter.pscce())
143 {
144 if (syndrome.isSingleBitError())
145 n2_strand->data_sfsr.error_type(4);
146 else if (syndrome.isDoubleBitError() || syndrome.isMultipleBitError())
147 n2_strand->data_sfsr.error_type(3);
148 unsigned long long native_add = 0;
149 unsigned long long intermediate_err_add;
150 // The syndrome of LSB (31:0) should be recorded in bits 12:6 of DSFAR
151 if (bit_significance == 0)
152 {
153 intermediate_err_add = (native_add & ~0x1fc0ULL) |
154 syndrome.getSyndrome() << 6;
155 }
156 // The syndrome of MSB (63:32) should be recorded in bits 19:13 of DSFAR
157 else if (bit_significance == 1)
158 {
159 intermediate_err_add = (native_add & ~0xfe000ULL) |
160 syndrome.getSyndrome() << 13;
161 }
162 // Capture the register number in bits 5:0 of DSFAR
163 unsigned long long error_add = (intermediate_err_add & ~0x3fULL) |
164 temp_reg;
165 n2_strand->data_sfar.error_addr(error_add);
166 return (s->trap)(pc,npc,s,i,SS_Trap::INTERNAL_PROCESSOR_ERROR);
167 }
168 }
169 }
170 // If the ecc associated with the register is invalid
171 else
172 {
173 // Not sure what the exact functioning should be in this case
174 // Should we calculate clean ecc and associate it with this reg (as in Riesling)
175 // unsigned ecc = N2_EccFile::calc_n2_FRF_checks(value);
176 // setECC(reg, ecc);
177 // Or should the program just call it quits!
178 // cerr << " Invalid ECC: Aborting!" << endl;
179 // exit(-1);
180 }
181 }
182}