Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | /* |
2 | * ========== Copyright Header Begin ========================================== | |
3 | * | |
4 | * OpenSPARC T2 Processor File: BL_CKSyndrome.h | |
5 | * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. | |
6 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES. | |
7 | * | |
8 | * The above named program is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU General Public | |
10 | * License version 2 as published by the Free Software Foundation. | |
11 | * | |
12 | * The above named program is distributed in the hope that it will be | |
13 | * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 | * General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public | |
18 | * License along with this work; if not, write to the Free Software | |
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. | |
20 | * | |
21 | * ========== Copyright Header End ============================================ | |
22 | */ | |
23 | /************************************************************************ | |
24 | ** | |
25 | ** Copyright (C) 2007, Sun Microsystems, Inc. | |
26 | ** | |
27 | ** Sun considers its source code as an unpublished, proprietary | |
28 | ** trade secret and it is available only under strict license provisions. | |
29 | ** This copyright notice is placed here only to protect Sun in the event | |
30 | ** the source is deemed a published work. Disassembly, decompilation, | |
31 | ** or other means of reducing the object code to human readable form | |
32 | ** is prohibited by the license agreement under which this code is | |
33 | ** provided to the user or company in possession of this copy. | |
34 | ** | |
35 | *************************************************************************/ | |
36 | #ifndef __BL_CKSyndrome_h__ | |
37 | #define __BL_CKSyndrome_h__ | |
38 | ||
39 | #include "BL_CKEcc.h" | |
40 | #include "BL_Utils.h" | |
41 | ||
42 | // Syndrome class for BL Chip-kill ECC | |
43 | // Class provides basic routines to determine whether there is an | |
44 | // ECC error, whether it is single, double, or multiple bit, and, if | |
45 | // it is a single bit error, is it a data bit or check bit error. | |
46 | class BL_CKSyndrome | |
47 | { | |
48 | public: | |
49 | BL_CKSyndrome(BL_CKEccFile::ChipKillLine line, uint64_t savedECC) : | |
50 | syndrome_(generateChipkillECC(line) ^ savedECC), | |
51 | badDataNibblePosition_(0), | |
52 | badCheckNibblePosition_(0), | |
53 | dataCorrectionMask_(0), | |
54 | checkCorrectionMask_(0) | |
55 | { | |
56 | if (syndrome_ > 0xffff) | |
57 | { | |
58 | fprintf(stderr,"BL_CKSyndrome::BL_CKSyndrome: bad syndrome"); | |
59 | exit(-1); | |
60 | } | |
61 | } | |
62 | ||
63 | ||
64 | ~BL_CKSyndrome() {} | |
65 | ||
66 | bool noError() const | |
67 | { | |
68 | return (syndrome_ == 0); | |
69 | } | |
70 | ||
71 | bool isUncorrectableError() | |
72 | { | |
73 | return !noError() && | |
74 | !isCorrectableDataBitError() && | |
75 | !isCorrectableCheckBitError(); | |
76 | } | |
77 | ||
78 | // Implemented based on Table A-10 in N2 PRM rev1.1 | |
79 | bool isCorrectableDataBitError() | |
80 | { | |
81 | if (noError()) | |
82 | { | |
83 | return false; | |
84 | } | |
85 | ||
86 | bool correctableDataBitError = false; | |
87 | uint32_t s3 = bit_shift(syndrome_,0,4); | |
88 | uint32_t s2 = bit_shift(syndrome_,4,4); | |
89 | uint32_t s1 = bit_shift(syndrome_,8,4); | |
90 | uint32_t s0 = bit_shift(syndrome_,12,4); | |
91 | // If nibble s0 == 0 - Row 4 of Table A-10 | |
92 | if (s0 == 0) | |
93 | { | |
94 | // The remaining three nibble should be non zero | |
95 | if ((s1 != 0) && (s2 != 0) && (s3 != 0)) | |
96 | { | |
97 | // And equal | |
98 | if ((s1 == s2) && (s1 == s3)) | |
99 | { | |
100 | // For it to be a valid single-bit correctable | |
101 | // data error | |
102 | correctableDataBitError = true; | |
103 | badDataNibblePosition_ = 30; | |
104 | // Mask to be XOR'ed with Nibble 30 to fix data | |
105 | dataCorrectionMask_ = s1; | |
106 | } | |
107 | } | |
108 | } | |
109 | // If nibble s1 == 0 - Case ab0c - Row 3 of Table A-10 | |
110 | else if (s1 == 0) | |
111 | { | |
112 | // The remaining three nibble should be non zero | |
113 | if ((s0 != 0) && (s2 != 0) && (s3 != 0)) | |
114 | { | |
115 | // And the value of syndrome nibble 3 should be | |
116 | // the same as the value in the matrix of synd0 | |
117 | // and synd2 | |
118 | if (ab0cErrorValidationMatrix[s2][s0] == s3) | |
119 | { | |
120 | // For it to be a valid single-bit correctable | |
121 | // data error | |
122 | correctableDataBitError = true; | |
123 | // Table A-13 | |
124 | badDataNibblePosition_ = | |
125 | ab0cErrorNibbleIdentityMatrix[s2][s0]; | |
126 | // Mask to be XOR'ed with the nibble indexed | |
127 | // by badDataNibblePosition_ to fix data | |
128 | dataCorrectionMask_ = s2; | |
129 | } | |
130 | } | |
131 | } | |
132 | // If nibble s2 == 0 - Case a0bc - Row 2 of Table A-10 | |
133 | else if (s2 == 0) | |
134 | { | |
135 | // The remaining three nibble should be non zero | |
136 | if ((s0 != 0) && (s1 != 0) && (s3 != 0)) | |
137 | { | |
138 | // And the value of syndrome nibble 3 should be | |
139 | // the same as the value in the matrix of synd0 | |
140 | // and synd1 | |
141 | if (a0bcErrorValidationMatrix[s1][s0] == s3) | |
142 | { | |
143 | // For it to be a valid single-bit correctable | |
144 | // data error | |
145 | correctableDataBitError = true; | |
146 | // Table A-11 | |
147 | badDataNibblePosition_ = | |
148 | a0bcErrorNibbleIdentityMatrix[s1][s0]; | |
149 | // Mask to be XOR'ed with nibble in | |
150 | // badDataNibblePosition_ above to fix data | |
151 | dataCorrectionMask_ = s1; | |
152 | } | |
153 | } | |
154 | } | |
155 | // If nibble s3 == 0 - Row 5 of Table A-10 | |
156 | else if (s3 == 0) | |
157 | { | |
158 | // The remaining three nibble should be non zero | |
159 | if ((s0 != 0) && (s1 != 0) && (s2 != 0)) | |
160 | { | |
161 | // And equal | |
162 | if ((s0 == s1) && (s0 == s2)) | |
163 | { | |
164 | // For it to be a valid single-bit correctable | |
165 | // data error | |
166 | correctableDataBitError = true; | |
167 | badDataNibblePosition_ = 31; | |
168 | // Mask to be XOR'ed with Nibble 31 to fix data | |
169 | dataCorrectionMask_ = s0; | |
170 | } | |
171 | } | |
172 | } | |
173 | return correctableDataBitError; | |
174 | } | |
175 | ||
176 | // Implemented based on Table A-10 in N2 PRM rev1.1 | |
177 | bool isCorrectableCheckBitError() | |
178 | { | |
179 | if (noError()) | |
180 | { | |
181 | return false; | |
182 | } | |
183 | ||
184 | bool correctableCheckBitError = false; | |
185 | uint32_t s3 = bit_shift(syndrome_,0,4); | |
186 | uint32_t s2 = bit_shift(syndrome_,4,4); | |
187 | uint32_t s1 = bit_shift(syndrome_,8,4); | |
188 | uint32_t s0 = bit_shift(syndrome_,12,4); | |
189 | // If nibble s0 != 0 - Row 6 of Table A-10 | |
190 | if (s0 != 0) | |
191 | { | |
192 | // The remaining three nibble should be zero | |
193 | if ((s1 == 0) && (s2 == 0) && (s3 == 0)) | |
194 | { | |
195 | // For it to be a valid single-bit correctable | |
196 | // check bit error | |
197 | correctableCheckBitError = true; | |
198 | // use big endian to index nibble position | |
199 | badCheckNibblePosition_ = 3; | |
200 | // This mask has to be XOR'ed with check nibble | |
201 | // identified above to restore valid ECC | |
202 | checkCorrectionMask_ = s0; | |
203 | } | |
204 | } | |
205 | // If nibble s1 != 0 - Row 7 of Table A-10 | |
206 | else if (s1 != 0) | |
207 | { | |
208 | // The remaining three nibble should be zero | |
209 | if ((s0 == 0) && (s2 == 0) && (s3 == 0)) | |
210 | { | |
211 | // For it to be a valid single-bit correctable | |
212 | // check bit error | |
213 | correctableCheckBitError = true; | |
214 | // use big endian to index nibble position | |
215 | badCheckNibblePosition_ = 2; | |
216 | checkCorrectionMask_ = s1; | |
217 | // This mask has to be XOR'ed with check nibble | |
218 | // identified above to restore valid ECC | |
219 | } | |
220 | } | |
221 | // If nibble s2 != 0 - Row 8 of Table A-10 | |
222 | else if (s2 != 0) | |
223 | { | |
224 | // The remaining three nibble should be zero | |
225 | if ((s0 == 0) && (s1 == 0) && (s3 == 0)) | |
226 | { | |
227 | // For it to be a valid single-bit correctable | |
228 | // check bit error | |
229 | correctableCheckBitError = true; | |
230 | // use big endian to index nibble position | |
231 | badCheckNibblePosition_ = 1; | |
232 | // This mask has to be XOR'ed with check nibble | |
233 | // identified above to restore valid ECC | |
234 | checkCorrectionMask_ = s2; | |
235 | } | |
236 | } | |
237 | // If nibble s3 != 0 - Row 9 of Table A-10 | |
238 | else if (s3 != 0) | |
239 | { | |
240 | // The remaining three nibble should be zero | |
241 | if ((s0 == 0) && (s1 == 0) && (s2 == 0)) | |
242 | { | |
243 | // For it to be a valid single-bit correctable | |
244 | // check bit error | |
245 | correctableCheckBitError = true; | |
246 | // use big endian to index nibble position | |
247 | badCheckNibblePosition_ = 0; | |
248 | // This mask has to be XOR'ed with check nibble | |
249 | // identified above to restore valid ECC | |
250 | checkCorrectionMask_ = s3; | |
251 | } | |
252 | } | |
253 | return correctableCheckBitError; | |
254 | } | |
255 | ||
256 | uint64_t getSyndrome() const { return syndrome_; } | |
257 | ||
258 | uint32_t getBadDataNibblePosition() | |
259 | { | |
260 | if (!isCorrectableDataBitError()) | |
261 | { | |
262 | fprintf(stderr,"BL_CKSyndrome::" | |
263 | "getBadDataNibblePosition(): " | |
264 | "not correctable data error"); | |
265 | exit(-1); | |
266 | } | |
267 | return badDataNibblePosition_; | |
268 | } | |
269 | ||
270 | uint32_t getBadCheckNibblePosition() | |
271 | { | |
272 | if (!isCorrectableCheckBitError()) | |
273 | { | |
274 | fprintf(stderr,"BL_CKSyndrome::" | |
275 | "getBadCheckNibblePosition(): " | |
276 | "not correctable check error"); | |
277 | exit(-1); | |
278 | } | |
279 | return badCheckNibblePosition_; | |
280 | } | |
281 | ||
282 | uint64_t getDataCorrectionMask() | |
283 | { | |
284 | if (!isCorrectableDataBitError()) | |
285 | { | |
286 | fprintf(stderr,"BL_CKSyndrome::" | |
287 | "getDataCorrectionMask(): " | |
288 | "not correctable data error"); | |
289 | exit(-1); | |
290 | } | |
291 | return dataCorrectionMask_; | |
292 | } | |
293 | ||
294 | uint64_t getCheckCorrectionMask() | |
295 | { | |
296 | if (!isCorrectableCheckBitError()) | |
297 | { | |
298 | fprintf(stderr,"BL_CKSyndrome::" | |
299 | "getCheckCorrectionMask(): " | |
300 | "not correctable check error"); | |
301 | exit(-1); | |
302 | } | |
303 | return checkCorrectionMask_; | |
304 | } | |
305 | ||
306 | bool correctChipKillLine(BL_CKEccFile::ChipKillLine &line) | |
307 | { | |
308 | if (!isCorrectableDataBitError()) | |
309 | { | |
310 | return false; | |
311 | } | |
312 | uint32_t nibbleNdx = getBadDataNibblePosition(); | |
313 | uint64_t nibbleMask = getDataCorrectionMask(); | |
314 | ||
315 | if (nibbleNdx < 16) | |
316 | { | |
317 | line.lsdw ^= nibbleMask << (4 * nibbleNdx); | |
318 | } | |
319 | else | |
320 | { | |
321 | line.msdw ^= nibbleMask << (4 * (nibbleNdx - 16)); | |
322 | } | |
323 | return true; | |
324 | } | |
325 | ||
326 | bool correctChipKillECC(uint64_t &ecc) | |
327 | { | |
328 | if (!isCorrectableCheckBitError()) | |
329 | { | |
330 | return false; | |
331 | } | |
332 | uint32_t nibbleNdx = getBadCheckNibblePosition(); | |
333 | uint64_t nibbleMask = getCheckCorrectionMask(); | |
334 | ||
335 | ecc ^= nibbleMask << (4 * nibbleNdx); | |
336 | return true; | |
337 | } | |
338 | ||
339 | protected: | |
340 | BL_CKSyndrome(); | |
341 | uint64_t syndrome_; | |
342 | uint32_t badDataNibblePosition_; | |
343 | uint32_t badCheckNibblePosition_; | |
344 | uint64_t dataCorrectionMask_; | |
345 | uint64_t checkCorrectionMask_; | |
346 | ||
347 | private: | |
348 | // The following 2 Dimensional Matrix implements Table A-12 of | |
349 | // N2 PRM rev1.1 First dimension is Syndrome0. Second | |
350 | // dimension is Syndrome1 The values contained in the matrix | |
351 | // are the possible values for Syndrome3 in hexadecimal for a | |
352 | // given [synd0,synd1], the value of synd3 should exactly | |
353 | // match the value present in this table for the data bit | |
354 | // error to be correctable (single bit) otherwise it is an | |
355 | // uncorrectable (multibit) error | |
356 | static const uint32_t a0bcErrorValidationMatrix[16][16]; | |
357 | ||
358 | // The following 2 Dimensional Matrix implements Table A-11 of | |
359 | // N2 PRM rev1.1 First dimension is Syndrome0. Second | |
360 | // dimension is Syndrome1 // The data present at the | |
361 | // intersection [synd0,synd1], represents the Data Nibble that | |
362 | // has the correctable error! // The correction mask is the | |
363 | // value of Syndrome1 | |
364 | static const uint32_t a0bcErrorNibbleIdentityMatrix[16][16]; | |
365 | ||
366 | // The following 2 Dimensional Matrix implements Table A-14 of | |
367 | // N2 PRM rev1.1 First dimension is Syndrome0. Second | |
368 | // dimension is Syndrome2 The values contained in the matrix | |
369 | // are the possible values for Syndrome3 in hexadecimal for a | |
370 | // given [synd0,synd2], the value of synd3 should exactly | |
371 | // match the value present in this table for the data bit | |
372 | // error to be correctable (single bit) otherwise it is an | |
373 | // uncorrectable (multibit) error | |
374 | static const uint32_t ab0cErrorValidationMatrix[16][16]; | |
375 | ||
376 | // The following 2 Dimensional Matrix implements Table A-13 of | |
377 | // N2 PRM rev1.1 First dimension is Syndrome0. Second | |
378 | // dimension is Syndrome2 // The data present at the | |
379 | // intersection [synd0,synd2], represents the Data Nibble that | |
380 | // has the correctable error! | |
381 | // The correction mask is the value of Syndrome2 | |
382 | static const uint32_t ab0cErrorNibbleIdentityMatrix[16][16]; | |
383 | }; | |
384 | #endif //__BL_CKSyndrome_h__ |