Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / cpus / vonk / n2 / lib / ras / src / N2_MemErrDetector.h
CommitLineData
920dae64
AT
1/*
2* ========== Copyright Header Begin ==========================================
3*
4* OpenSPARC T2 Processor File: N2_MemErrDetector.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#ifndef _N2_MEMERRDETECTOR_H
24#define _N2_MEMERRDETECTOR_H
25/************************************************************************
26**
27** Copyright (C) 2005, Sun Microsystems, Inc.
28**
29** Sun considers its source code as an unpublished, proprietary
30** trade secret and it is available only under strict license provisions.
31** This copyright notice is placed here only to protect Sun in the event
32** the source is deemed a published work. Disassembly, decompilation,
33** or other means of reducing the object code to human readable form
34** is prohibited by the license agreement under which this code is
35** provided to the user or company in possession of this copy.
36**
37*************************************************************************/
38#include "MemoryTransaction.h"
39#include "SS_MemErrDetector.h"
40#include "BL_Memory.h"
41#include "SS_CsrAccess.h"
42
43#include "N2_Strand.h"
44#include "BL_CKEcc.h"
45#include "BL_CKSyndrome.h"
46#include "BL_HammingEcc.h"
47#include "BL_Hamming_32_7_Synd.h"
48
49#include "N2_L2AddressingFields.h"
50#include "N2_L2CacheFlushAddrFields.h"
51#include "N2_L2DiagDataAddressingFields.h"
52#include "N2_L2ErrorEnMem.h"
53#include "N2_L2ErrorStatusReg.h"
54#include "N2_L2ControlReg.h"
55#include "N2_L2ErrorAddressReg.h"
56#include "N2_L2DiagDataMem.h"
57#include "N2_L2DiagTagMem.h"
58#include "N2_L2DiagVdMem.h"
59#include "N2_L2DiagUaMem.h"
60#include "N2_L2NotdataErrorReg.h"
61
62#include "N2_DramErrorStatusMem.h"
63#include "N2_DramErrorInjectMem.h"
64#include "N2_DramErrorCounterMem.h"
65#include "N2_DramErrorLocMem.h"
66#include "N2_DramFbdInjectedErrSrcReg.h"
67#include "N2_DramFbdCountReg.h"
68#include "N2_DramFbdErrorSyndromeReg.h"
69
70#include "N2_SocErrorInjectReg.h"
71#include "N2_SocErrorStatusReg.h"
72#include "N2_SocPendingErrStatusReg.h"
73#include "N2_SocErrorLogEnableReg.h"
74#include "N2_SocErrorIntrEnReg.h"
75#include "N2_SocFatalErrorEnableReg.h"
76#include "N2_SocErrorSteeringReg.h"
77
78class N2_Model;
79
80/**
81 * The N2_MemErrDetector class is used to detect injected RAS errors
82 * associated with the memory hierarchy. In particular, it models and
83 * detects errors in the primary and secondary caches and DRAM.
84 */
85
86#define RAS_OSTR debugOutput_ && cerr
87
88// Memory Error Detector for RAS
89//
90// Detects RAS error related to memory access: primary cache,
91// secondary cache, DRAM and FBDIMM errors.
92class N2_Core;
93
94class N2_MemErrDetector : public SS_MemErrDetector {
95
96 public:
97 // Extend class to include update() method which guarantees (or rather,
98 // approximates) writing to the L2 Error Status Register.
99 class N2_CheckedL2ESRAccess : public SS_CsrAccess<N2_L2ErrorStatusReg> {
100 public:
101
102 N2_CheckedL2ESRAccess(SS_Csr& csr):
103 SS_CsrAccess<N2_L2ErrorStatusReg>(csr) {}
104 ~N2_CheckedL2ESRAccess() {}
105 const N2_CheckedL2ESRAccess &
106 operator=( const N2_CheckedL2ESRAccess &rhs ) {
107 fprintf(stderr, "Unimplemented function." );
108 exit(-1);
109 return *this;
110 }
111
112 // add update checking to insure the MEC, MEU, etc. bits are set
113 // correctly. Returns true if the N2_L2ErrorAddressReg associated
114 // with the error should also be updated.
115 bool access(uint64_t ndx, N2_L2ErrorStatusReg &csr, bool isRead);
116
117 private:
118 N2_CheckedL2ESRAccess();
119 };
120
121 // Extend N2_L2DiagVdMem class to include ECC and syndrome calculators
122 class N2_L2DiagVdMemWithECC : public N2_L2DiagVdMem {
123 public:
124 N2_L2DiagVdMemWithECC() {}
125 N2_L2DiagVdMemWithECC( const N2_L2DiagVdMemWithECC& obj ) :
126 N2_L2DiagVdMem(obj)
127 {}
128
129 ~N2_L2DiagVdMemWithECC() {}
130
131 // Shifts used to convert VD diag data into dirty and valid bits with ECC
132 static const N2_L2_DIAG_VD_ACCESS_VALID_SHIFT = 16;
133 static const N2_L2_DIAG_VD_ACCESS_DIRTY_SHIFT = 0;
134 static const N2_L2_DIAG_VD_ACCESS_ECC_SHIFT = 0;
135
136 uint32_t getVD() const
137 {
138 return (getVALID() << N2_L2_DIAG_VD_ACCESS_VALID_SHIFT) |
139 getDIRTY();
140 }
141
142 void setVD(uint32_t vd)
143 {
144 setDIRTY(vd);
145 setVALID(vd >> N2_L2_DIAG_VD_ACCESS_VALID_SHIFT);
146 }
147
148 uint32_t calcECC(void) const
149 {
150 return (BL_Hamming_32_7_Synd::calc_check_bits(getVD())).get();
151 }
152
153 BL_Hamming_32_7_Synd getSyndrome(void) const
154 {
155
156 return BL_Hamming_32_7_Synd(getVD(), getVDECC());
157 }
158 };
159
160 struct N2_L2VaudSyndrome {
161 N2_L2VaudSyndrome() :
162 vdSyndrome_(0),
163 uaSyndrome_(0){}
164
165 ~N2_L2VaudSyndrome() {}
166
167 N2_L2VaudSyndrome(uint32_t vdSyndrome,uint32_t uaSyndrome) :
168 vdSyndrome_(vdSyndrome),
169 uaSyndrome_(uaSyndrome){}
170 BL_Hamming_32_7_Synd vdSyndrome_;
171 BL_Hamming_32_7_Synd uaSyndrome_;
172 };
173
174
175 // Extend N2_L2DiagUaMem class to include ECC and syndrome calculators
176 class N2_L2DiagUaMemWithECC : public N2_L2DiagUaMem {
177 public:
178 N2_L2DiagUaMemWithECC() {}
179 N2_L2DiagUaMemWithECC( const N2_L2DiagUaMemWithECC& obj ) :
180 N2_L2DiagUaMem(obj)
181 {}
182
183 ~N2_L2DiagUaMemWithECC() {}
184
185 // Shifts used to convert VD diag data into dirty and valid bits with ECC
186 static const N2_L2_DIAG_UA_ACCESS_USED_SHIFT = 16;
187 static const N2_L2_DIAG_UA_ACCESS_ALLOC_SHIFT = 0;
188 static const N2_L2_DIAG_UA_ACCESS_ECC_SHIFT = 0;
189
190 uint32_t getUA() const
191 {
192 return (getUSED() << N2_L2_DIAG_UA_ACCESS_USED_SHIFT) |
193 getALLOC();
194 }
195
196 void setUA(uint32_t vd)
197 {
198 setALLOC(vd);
199 setUSED(vd >> N2_L2_DIAG_UA_ACCESS_USED_SHIFT);
200 }
201
202 uint32_t calcECC(void) const
203 {
204 return (BL_Hamming_32_7_Synd::calc_check_bits(getUA())).get();
205 }
206
207 BL_Hamming_32_7_Synd getSyndrome(void) const
208 {
209
210 return BL_Hamming_32_7_Synd(getUA(), getUAECC());
211 }
212 };
213
214
215 // Extend N2_L2DiagDataMem class to include ECC and syndrome calculators
216 class N2_L2DiagDataMemWithECC : public N2_L2DiagDataMem {
217 public:
218 N2_L2DiagDataMemWithECC() {}
219 N2_L2DiagDataMemWithECC( const N2_L2DiagDataMemWithECC& obj ) :
220 N2_L2DiagDataMem(obj)
221 {}
222 ~N2_L2DiagDataMemWithECC() {}
223
224 uint32_t calcECC(void) const
225 {
226 return (BL_Hamming_32_7_Synd::calc_check_bits(getDATA())).get();
227 }
228
229 BL_Hamming_32_7_Synd getSyndrome(void) const
230 {
231 return BL_Hamming_32_7_Synd(getDATA(), getECC());
232 }
233
234 static const uint64_t L2_NOT_DATA = 0x7f;
235 };
236
237
238 // This class captures the error status of an L2 cache data quarter
239 // line.
240 // The ECC syndromes for 4 32-bit words are captured in the
241 // qLineSyndrome_ field and the physical address corresponding to the
242 // ECC error, if any, is in the errorPaddr_ field.
243 class N2_L2CacheLineError {
244 public:
245 typedef enum {
246 NO_ERROR,
247 CORRECTABLE_ERROR,
248 UNCORRECTABLE_ERROR,
249 NOT_DATA
250 } errorType_t;
251
252 N2_L2CacheLineError(uint64_t errorPaddr) :
253 errorType_(NO_ERROR),
254 qLineSyndrome_(0),
255 errorPaddr_(errorPaddr),
256 wordNdx_(0)
257 {}
258
259 virtual ~N2_L2CacheLineError() {}
260
261 /*
262 * Assignment operator
263 *
264 * @param rhs The right hand side of the assignment operator.
265 * @return The lvalue of the assignment.
266 */
267 const N2_L2CacheLineError &
268 operator=( const N2_L2CacheLineError &rhs )
269 {
270 errorType_ = rhs.errorType_;
271 qLineSyndrome_ = rhs.qLineSyndrome_;
272 errorPaddr_ = rhs.errorPaddr_;
273 wordNdx_ = rhs.wordNdx_;
274 return *this;
275 }
276
277 // if qLineSyndrome, not qLineSyndrome_, compiler bug?!?
278 bool isError() const { return qLineSyndrome_ != 0; }
279
280 uint32_t qLineSyndrome() const { return qLineSyndrome_; }
281
282 uint64_t errorPaddr() const { return errorPaddr_; }
283
284 bool isCorrectable() const { return isError() &&
285 errorType_ == CORRECTABLE_ERROR; }
286
287 bool isUncorrectable() const { return isError() &&
288 (errorType_ == UNCORRECTABLE_ERROR ||
289 errorType_ == NOT_DATA); }
290
291 bool isNotData() const { return isError() &&
292 errorType_ == NOT_DATA; }
293
294 void addQuarterLine(BL_Hamming_32_7_Synd wordSyndrome) {
295 qLineSyndrome_ |= (wordSyndrome.getSyndrome() << ( 7 * wordNdx_++));
296
297 // dispatch on current worst cache line error type.
298 // Incorportate error from current word into quarter line's
299 // error type.
300 switch (errorType_) {
301 case NO_ERROR: // any new error bad
302 if (!wordSyndrome.noError()) {
303 errorType_ = CORRECTABLE_ERROR;
304 }
305 /* consider NotData or uncorrectable possibility by
306 falling through */
307 /* FALLTHROUGH*/
308 case CORRECTABLE_ERROR: // is new uncorrectable?
309 if (wordSyndrome.isUncorrectableError()) {
310 errorType_ = UNCORRECTABLE_ERROR;
311 }
312 /* consider NotData possibility by falling through */
313 /* FALLTHROUGH*/
314 case UNCORRECTABLE_ERROR: // only NOT_DATA is worse
315 if (wordSyndrome.getSyndrome() ==
316 N2_L2DiagDataMemWithECC::L2_NOT_DATA) {
317 errorType_ = NOT_DATA;
318 }
319 break;
320 case NOT_DATA: // can't get any worse than this
321 break;
322 default:
323 fprintf(stderr, "N2_L2CacheLineError::addQuarterLine "
324 "bad errorType_ 0x%x", errorType_);
325 exit(-1);
326 }
327 }
328
329 private:
330 N2_L2CacheLineError() {}
331
332 errorType_t errorType_;
333
334 uint32_t qLineSyndrome_;
335
336 uint64_t errorPaddr_;
337
338 uint_t wordNdx_;
339 };
340
341
342 class N2_CererWithBitMux : public N2_Cerer {
343 public:
344 ~N2_CererWithBitMux() {}
345 N2_CererWithBitMux(const N2_CererWithBitMux &obj) :
346 N2_Cerer(obj) {}
347 N2_CererWithBitMux(const N2_Cerer &obj) :
348 N2_Cerer(obj) {}
349
350 bool checkOneL2Cbit(const MemoryTransaction &memXact) {
351 return
352 (this->l2c_socc() && memXact.tablewalk()) ||
353 (icl2c() &&
354 memXact.referenceType() == MemoryTransaction::INSTR) ||
355 (dcl2c() &&
356 memXact.referenceType() == MemoryTransaction::DATA);
357 }
358
359 bool checkAnyL2Cbit() {
360 return icl2c() || dcl2c();
361 }
362
363 private:
364 N2_CererWithBitMux() :
365 N2_Cerer(){}
366 };
367
368 N2_MemErrDetector(SS_Model *model) :
369 n2_model(model),
370 L2ControlRegAccess_(((N2_Model*)n2_model)->csr),
371 L2ErrorStatusRegAccess_(((N2_Model*)n2_model)->csr),
372 L2ErrorAddressRegAccess_(((N2_Model*)n2_model)->csr),
373 L2ErrorEnMemAccess_(((N2_Model*)n2_model)->csr),
374 L2DiagDataMemAccess_(((N2_Model*)n2_model)->csr),
375 L2DiagTagMemAccess_(((N2_Model*)n2_model)->csr),
376 L2DiagVdMemAccess_(((N2_Model*)n2_model)->csr),
377 L2DiagUaMemAccess_(((N2_Model*)n2_model)->csr),
378 L2NotdataErrorRegAccess_(((N2_Model*)n2_model)->csr),
379 DramErrorStatusMemAccess_(((N2_Model*)n2_model)->csr),
380 DramErrorInjectMemAccess_(((N2_Model*)n2_model)->csr),
381 DramErrorCounterMemAccess_(((N2_Model*)n2_model)->csr),
382 DramErrorLocMemAccess_(((N2_Model*)n2_model)->csr),
383 DramFbdInjectedErrSrcRegAccess_(((N2_Model*)n2_model)->csr),
384 DramFbdCountRegAccess_(((N2_Model*)n2_model)->csr),
385 DramFbdErrorSyndromeRegAccess_(((N2_Model*)n2_model)->csr),
386 socErrorInjectRegAccess_(((N2_Model*)n2_model)->csr),
387 socErrorStatusRegAccess_(((N2_Model*)n2_model)->csr),
388 socPendingErrStatusRegAccess_(((N2_Model*)n2_model)->csr),
389 socErrorLogEnableRegAccess_(((N2_Model*)n2_model)->csr),
390 socErrorIntrEnRegAccess_(((N2_Model*)n2_model)->csr),
391 socFatalErrorEnableRegAccess_(((N2_Model*)n2_model)->csr),
392 socErrorSteeringRegAccess_(((N2_Model*)n2_model)->csr),
393 debugOutput_(getenv("RAS_DEBUG") != NULL),
394 debugChipKill_(getenv("CHIPKILL_DEBUG") != NULL)
395 {
396 for (int bank = 0; bank < N2_L2_CACHE_NR_BANKS; ++bank) {
397 L2CacheWaysNRUPtr_[bank] = 0;
398 }
399 step_hook = n2_step_hook;
400 //tick_err_detector = n2_tick_cmpr_disrupting_err_detector;
401
402 }
403
404 /**
405 * Copy constructor
406 *
407 * @param orig The MemErrDetector object to copy.
408 */
409 N2_MemErrDetector( const N2_MemErrDetector &orig ) :
410 n2_model(orig.n2_model),
411 L2ControlRegAccess_(orig.L2ControlRegAccess_),
412 L2ErrorStatusRegAccess_(orig.L2ErrorStatusRegAccess_),
413 L2ErrorAddressRegAccess_(orig.L2ErrorAddressRegAccess_),
414 L2ErrorEnMemAccess_(orig.L2ErrorEnMemAccess_),
415 L2DiagDataMemAccess_(orig.L2DiagDataMemAccess_),
416 L2DiagTagMemAccess_(orig.L2DiagTagMemAccess_),
417 L2DiagVdMemAccess_(orig.L2DiagVdMemAccess_),
418 L2DiagUaMemAccess_(orig.L2DiagUaMemAccess_),
419 L2NotdataErrorRegAccess_(orig.L2NotdataErrorRegAccess_),
420 DramErrorStatusMemAccess_(orig.DramErrorStatusMemAccess_),
421 DramErrorInjectMemAccess_(orig.DramErrorInjectMemAccess_),
422 DramErrorCounterMemAccess_(orig.DramErrorCounterMemAccess_),
423 DramErrorLocMemAccess_(orig.DramErrorLocMemAccess_),
424 DramFbdInjectedErrSrcRegAccess_(orig.DramFbdInjectedErrSrcRegAccess_),
425 DramFbdCountRegAccess_(orig.DramFbdCountRegAccess_),
426 DramFbdErrorSyndromeRegAccess_(orig.DramFbdErrorSyndromeRegAccess_),
427 socErrorInjectRegAccess_(orig.socErrorInjectRegAccess_),
428 socErrorStatusRegAccess_(orig.socErrorStatusRegAccess_),
429 socPendingErrStatusRegAccess_(orig.socPendingErrStatusRegAccess_),
430 socErrorLogEnableRegAccess_(orig.socErrorLogEnableRegAccess_),
431 socErrorIntrEnRegAccess_(orig.socErrorIntrEnRegAccess_),
432 socFatalErrorEnableRegAccess_(orig.socFatalErrorEnableRegAccess_),
433 socErrorSteeringRegAccess_(orig.socErrorSteeringRegAccess_),
434 debugOutput_(orig.debugOutput_),
435 debugChipKill_(orig.debugChipKill_)
436 {
437 for (int bank = 0; bank < N2_L2_CACHE_NR_BANKS; ++bank) {
438 L2CacheWaysNRUPtr_[bank] = orig.L2CacheWaysNRUPtr_[bank] ;
439 }
440 }
441
442 /**
443 * Destructor
444 */
445 virtual ~N2_MemErrDetector() {}
446
447 /**
448 * Equality operator
449 *
450 * @param rhs The right hand side of the equality operator
451 * @return Return true if this objec and rhs are equal,
452 * otherwise return false
453 */
454 bool operator==( const N2_MemErrDetector &rhs ) const;
455
456 /**
457 * Assignment operator
458 *
459 * @param rhs The right hand side of the assignment operator.
460 * @return The lvalue of the assignment.
461 */
462 const N2_MemErrDetector & operator=( const N2_MemErrDetector &rhs );
463
464
465 SS_Trap::Type detect_fetch_err( MemoryLevel level,
466 SS_Vaddr pc,
467 SS_Vaddr npc, SS_Strand* s, SS_Paddr pa) ;
468
469 SS_Trap::Type detect_load_err( MemoryLevel level,
470 SS_Vaddr pc, SS_Vaddr npc,
471 SS_Strand* s, SS_Instr* line,
472 SS_Paddr pa) ;
473
474 SS_Trap::Type inject_store_err( MemoryLevel level,
475 SS_Vaddr pc, SS_Vaddr npc,
476 SS_Strand* s, SS_Instr* line,
477 SS_Paddr pa,
478 uint64_t data) ;
479
480 BL_EccBits N2_MemErrDetector::n2_tick_cmpr_err_injector(SS_Strand* s,
481 uint64_t data);
482
483 SS_Trap::Type N2_MemErrDetector::n2_tick_cmpr_precise_err_detector(SS_Strand* s,
484 N2_TickAccess::TickAccessIndex array_index);
485
486 static bool n2_tick_cmpr_disrupting_err_detector(SS_Strand* s);
487
488 // Returns whether an prefetch instruction is a prefetchICE
489 bool is_prefetchICE(SS_Opcode& opc)
490 {
491 return opc.get_fcn() == 0x18;
492 }
493
494 // Routine to flush L2 cache
495 void prefetchICE(SS_Paddr pa);
496
497 SS_Trap::Type ras_flush( SS_Vaddr pc, SS_Vaddr npc,
498 SS_Strand* s,
499 SS_Instr* line,
500 SS_Paddr pa,
501 uint64_t size,
502 CacheType type)
503 { return SS_Trap::NO_TRAP; }
504
505 void ras_flush( SS_Strand*s, SS_Strand* requesting_strand, SS_Paddr pa, uint64_t size, CacheType type);
506
507 static SS_Trap::Type n2_step_hook(SS_Strand* s);
508
509
510 /**
511 * detectErr() throws traps and furballs when an RAS error
512 * has been injected in the memory hierarchy.
513 */
514
515 SS_Trap::Type detectErr(const MemoryTransaction &memXact);
516
517 /**
518 * L2CacheFill takes a memory transaction and fills the
519 * L-cache as needed with data used by the transaction.
520 */
521
522 SS_Trap::Type L2CacheFill(const MemoryTransaction &memXact);
523
524 void L2CacheFlush(N2_L2CacheFlushAddrFields flushAddr);
525
526 // In cache look-up routines, setting the way to this value
527 // means a miss or "no way" matched
528 const static int NO_WAY = -1;
529
530 // SWIG routines for controlling debugging output
531 void startDebugOutput() { debugOutput_ = true; }
532 void stopDebugOutput() { debugOutput_ = false; }
533
534 protected:
535
536 private:
537 //
538 // N2 PRM Rev 1.1 Sect B.5.1
539 // Basic L2 cache size parameters
540 // The number of sets per bank is:
541 // 4MB/8s = 512K bytes per bank
542 // 512K/64B = 8K lines per bank
543 // 8K/16 = 512 sets per bank
544
545 SS_Model *n2_model;
546
547 static const N2_L2_CACHE_LINE_SIZE = 64;
548 static const N2_L2_CACHE_NR_BANKS = 8;
549 static const N2_L2_CACHE_NR_SETS_PER_BANK = 512;
550
551 uint32_t L2CacheWaysNRUPtr_[N2_L2_CACHE_NR_BANKS];
552 std::map<uint64_t,uint64_t> dramECCMap_;
553
554 void L2FixTags(N2_L2AddressingFields paddr);
555
556 void L2FixTagsAndTrap(N2_Strand *strand,
557 N2_L2AddressingFields paddr,
558 const MemoryTransaction &memXact);
559
560 bool L2FixTag(uint32_t diagNdx);
561 N2_L2VaudSyndrome L2FixVUAD(N2_L2AddressingFields paddr,
562 N2_L2DiagVdMemWithECC &diagVD);
563
564 N2_L2DiagVdMemWithECC L2FixVUADAndTrap(N2_Strand *strand,
565 N2_L2AddressingFields paddr,
566 const MemoryTransaction &memXact);
567
568 int L2FindWay(N2_L2AddressingFields paddr,
569 N2_L2DiagVdMemWithECC diagVD);
570
571 SS_Trap::Type L2CacheMiss(N2_Strand *strand,
572 const MemoryTransaction &memXact,
573 N2_L2DiagVdMemWithECC &diagVD);
574
575 SS_Trap::Type L2CacheHit(N2_Strand *strand,
576 const MemoryTransaction &memXact,
577 N2_L2DiagVdMemWithECC &diagVD,
578 int hit_way);
579
580 N2_L2CacheLineError L2ProcessCacheLine(N2_L2AddressingFields paddr,
581 uint32_t way,
582 bool isRead);
583 N2_L2CacheLineError L2ProcessQuarterLine(N2_L2AddressingFields paddr,
584 uint32_t way,
585 bool isRead);
586
587 SS_Trap::Type ThrowL2DataTrap(const MemoryTransaction &memXact,
588 N2_Strand *strand,
589 uint32_t bank,
590 N2_L2CacheLineError lineError);
591
592 void ThrowL2DataCorrectableTrap(const MemoryTransaction &memXact,
593 N2_Strand *strand,
594 uint32_t bank,
595 N2_L2CacheLineError lineError);
596
597
598 SS_Trap::Type ThrowL2DataUncorrectableTrap(const MemoryTransaction &memXact,
599 N2_Strand *strand,
600 uint32_t bank,
601 N2_L2CacheLineError lineError);
602
603 void ThrowL2DataWriteBackTrap(const MemoryTransaction &memXact,
604 N2_Strand *strand,
605 uint32_t bank,
606 N2_L2CacheLineError lineError);
607
608 void poisonL2Line(N2_L2AddressingFields paddr, int way);
609
610 //
611 // Diagnostic access and modification routines.
612 //
613 typedef void (N2_L2ErrorStatusReg::*ErrorStatusRegBitSetFn)(uint64_t);
614
615 void setL2ErrorStatusReg(uint32_t bank,
616 ErrorStatusRegBitSetFn bitSetFunction,
617 bool isCorrectable,
618 uint32_t vcid,
619 uint32_t syndrome,
620 uint64_t errorAddr);
621
622 void setL2NotdataErrorReg(uint32_t bank,
623 uint32_t vcid,
624 uint64_t errorAddress);
625
626
627 // trapToErrorSteer() posts a trap to the ERRORSTEER core/strand
628 // associated with bank.
629 void trapToErrorSteer(N2_Strand *strand, uint32_t bank,
630 SS_Interrupt::Bit trapNr) {
631 N2_Strand *target_strand = (N2_Strand*)n2_model->cpu[0]->strand[getErrorSteer(bank)];
632 // Figure out which strand gets the trap from the L2 Control
633 // Register's ERRORSTEER field.
634 if(trapNr == SS_Interrupt::BIT_HW_CORRECTED_ERROR){
635 if(!strand->seter.dhcce())
636 return;
637 }
638 else if(trapNr == SS_Interrupt::BIT_SW_RECOVERABLE_ERROR){
639 if(!strand->seter.de())
640 return;
641 }
642 strand->irq.raise(target_strand,trapNr);
643 }
644
645 void setDESR(uint_t strandId,bool sw_recoverable_trap,
646 uint32_t errorType, uint32_t errorAddr)
647 {
648 N2_Strand *strand = (N2_Strand*)n2_model->cpu[0]->strand[strandId];
649 N2_Desr *desr = &(strand->desr);
650 if (!desr->f() )
651 {
652 // sets the Strand's desr; not a copy
653 desr->f(1); // full bit
654 // S <- 1 for SW_recoverable_trap
655 // S <- 0 for HW_corrected_error
656 desr->s(sw_recoverable_trap);
657 desr->errtype(errorType); // error code
658 desr->erraddr(errorAddr); // error address
659 }
660 else
661 { // set multiple error bit
662 desr->me(1);
663 }
664 }
665
666
667 // Get the CEEN bit from the L2$ error enable register
668 uint32_t getCEEN(uint32_t bank) {
669 N2_L2ErrorEnMem L2ErrorEnableReg;
670 L2ErrorEnMemAccess_.access(bank, L2ErrorEnableReg, true);
671
672 return L2ErrorEnableReg.getCEEN();
673 }
674
675 // Get the NCEEN bit from the L2$ error enable register
676 bool getNCEEN(uint32_t bank) {
677 N2_L2ErrorEnMem L2ErrorEnableReg;
678 L2ErrorEnMemAccess_.access(bank, L2ErrorEnableReg, true);
679
680 return L2ErrorEnableReg.getNCEEN();
681 }
682
683 // Get the ERRORSTEER core/strand id from the L2$ error control reg
684 uint_t getErrorSteer(uint32_t bank) {
685 N2_L2ControlReg L2ControlReg;
686 L2ControlRegAccess_.access(bank, L2ControlReg, true);
687
688 return L2ControlReg.getERRORSTEER();
689 }
690
691 // get a set-bank index into a diagnostic csr array from a
692 // physical address
693 static uint64_t paddrToSetBankNdx(N2_L2AddressingFields paddr)
694 {
695 uint64_t diagNdx = paddr.getSET();
696 diagNdx <<= N2_L2AddressingFields::bitSizeBANK;
697 return (diagNdx | paddr.getBANK());
698 }
699
700 // get a way-set-bank index into a diagnostic csr array from a
701 // physical address
702 static uint64_t paddrToWaySetBankNdx(N2_L2AddressingFields paddr,
703 uint32_t way)
704 {
705 uint64_t diagNdx = way;
706 diagNdx <<= N2_L2AddressingFields::bitSizeSET;
707 diagNdx |= paddr.getSET();
708 diagNdx <<= N2_L2AddressingFields::bitSizeBANK;
709 return (diagNdx | paddr.getBANK());
710 }
711
712
713 void DramThrowCorrectableTrap(N2_Strand *strand,
714 const MemoryTransaction &memXact,
715 uint32_t bank);
716
717 SS_Trap::Type DramThrowUncorrectableTrap(N2_Strand *strand,
718 const MemoryTransaction &memXact,
719 uint32_t bank);
720
721 static const uint64_t N2_DRAM_PADDR_MCU_SHIFT = 6;
722 static const uint64_t N2_DRAM_PADDR_NR_MCU_LOG2 = 2;
723 static const uint64_t N2_DRAM_PADDR_NR_MCU =
724 (1<< N2_DRAM_PADDR_NR_MCU_LOG2);
725
726 // Diagnostic access and modification routines.
727 SS_Trap::Type dramProcessMemOp(N2_Strand *strand,
728 const MemoryTransaction &memXact,
729 N2_L2AddressingFields paddr,bool &);
730
731 void dramUpdateECC(N2_L2AddressingFields paddr, bool isNotData);
732
733 // Soc Error Detection and Correction Routines
734 void processSocFbdError(N2_Strand &strand,
735 N2_L2AddressingFields paddress,
736 N2_SocErrorReg::SocErrRegBitGetFn getFBR);
737
738 // Accessor Templates for L2$ Control Registers and Diag Access
739 SS_CsrAccess<N2_L2ControlReg> L2ControlRegAccess_;
740 N2_CheckedL2ESRAccess L2ErrorStatusRegAccess_;
741 SS_CsrAccess<N2_L2ErrorAddressReg> L2ErrorAddressRegAccess_;
742 SS_CsrAccess<N2_L2ErrorEnMem> L2ErrorEnMemAccess_;
743
744 SS_CsrAccess<N2_L2DiagDataMem> L2DiagDataMemAccess_;
745 SS_CsrAccess<N2_L2DiagTagMem> L2DiagTagMemAccess_;
746 SS_CsrAccess<N2_L2DiagVdMemWithECC> L2DiagVdMemAccess_;
747 SS_CsrAccess<N2_L2DiagUaMemWithECC> L2DiagUaMemAccess_;
748 SS_CsrAccess<N2_L2NotdataErrorReg> L2NotdataErrorRegAccess_;
749 // Accessor Templates for Dram Control Registers
750 SS_CsrAccess<N2_DramErrorStatusMem> DramErrorStatusMemAccess_;
751 SS_CsrAccess<N2_DramErrorInjectMem> DramErrorInjectMemAccess_;
752 SS_CsrAccess<N2_DramErrorCounterMem> DramErrorCounterMemAccess_;
753 SS_CsrAccess<N2_DramErrorLocMem> DramErrorLocMemAccess_;
754 SS_CsrAccess<N2_DramFbdInjectedErrSrcReg>
755 DramFbdInjectedErrSrcRegAccess_;
756 SS_CsrAccess<N2_DramFbdCountReg> DramFbdCountRegAccess_;
757 SS_CsrAccess<N2_DramFbdErrorSyndromeReg>
758 DramFbdErrorSyndromeRegAccess_;
759
760 // Accessor Templates for Soc Error Control Registers
761 SS_CsrAccess<N2_SocErrorInjectReg> socErrorInjectRegAccess_;
762 SS_CsrAccess<N2_SocErrorStatusReg> socErrorStatusRegAccess_;
763 SS_CsrAccess<N2_SocPendingErrStatusReg> socPendingErrStatusRegAccess_;
764 SS_CsrAccess<N2_SocErrorLogEnableReg> socErrorLogEnableRegAccess_;
765 SS_CsrAccess<N2_SocErrorIntrEnReg> socErrorIntrEnRegAccess_;
766 SS_CsrAccess<N2_SocFatalErrorEnableReg> socFatalErrorEnableRegAccess_;
767 SS_CsrAccess<N2_SocErrorSteeringReg> socErrorSteeringRegAccess_;
768
769 bool debugOutput_;
770
771 // set to artificially inject Chip-Kill errors. Note that this
772 // can't be used with "real" CK error injection because it
773 // could result in uncorrectable double nibble errors.
774 bool debugChipKill_;
775
776
777};
778
779#endif /* _N2_MEMERRDETECTOR_H */