Commit | Line | Data |
---|---|---|
86530b38 AT |
1 | // ========== Copyright Header Begin ========================================== |
2 | // | |
3 | // OpenSPARC T2 Processor File: ilupeuErrChkPEUStr.vr | |
4 | // Copyright (C) 1995-2007 Sun Microsystems, Inc. All Rights Reserved | |
5 | // 4150 Network Circle, Santa Clara, California 95054, U.S.A. | |
6 | // | |
7 | // * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
8 | // | |
9 | // This program is free software; you can redistribute it and/or modify | |
10 | // it under the terms of the GNU General Public License as published by | |
11 | // the Free Software Foundation; version 2 of the License. | |
12 | // | |
13 | // This program is distributed in the hope that it will be useful, | |
14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | // GNU General Public License for more details. | |
17 | // | |
18 | // You should have received a copy of the GNU General Public License | |
19 | // along with this program; if not, write to the Free Software | |
20 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
21 | // | |
22 | // For the avoidance of doubt, and except that if any non-GPL license | |
23 | // choice is available it will apply instead, Sun elects to use only | |
24 | // the General Public License version 2 (GPLv2) at this time for any | |
25 | // software where a choice of GPL license versions is made | |
26 | // available with the language indicating that GPLv2 or any later version | |
27 | // may be used, or where a choice of which version of the GPL is applied is | |
28 | // otherwise unspecified. | |
29 | // | |
30 | // Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, | |
31 | // CA 95054 USA or visit www.sun.com if you need additional information or | |
32 | // have any questions. | |
33 | // | |
34 | // ========== Copyright Header End ============================================ | |
35 | #include "report_info.vrh" | |
36 | ||
37 | #define _REPORT_ERR(msg) Report.report(RTYP_TEST_ERROR,"ErrChkPEUStr (cycle %0d) %s\n", get_cycle(),msg) | |
38 | #define ERR_INFO(msg) printf("%s\n",msg) | |
39 | ||
40 | class ErrChkPEUStr extends PEUStrBase | |
41 | { | |
42 | local integer f_errQueue; // A mailbox for bad pkt headers | |
43 | local integer f_errCount; // The number of expected errors | |
44 | static integer f_ueQueue = 0; // An old UE mailbox | |
45 | static integer f_oeQueue = 0; // An old OE mailbox | |
46 | ReportClass Report; | |
47 | ||
48 | task new( PEUTestEnv a_env, integer a_queue, integer a_errCount ) | |
49 | { | |
50 | super.new( a_env ); | |
51 | f_errQueue = a_queue; | |
52 | f_errCount = a_errCount; | |
53 | Report = a_env.Report; | |
54 | } /* end new */ | |
55 | ||
56 | local task allocQueues( var integer ueQueue, var integer oeQueue ) | |
57 | { | |
58 | if ( f_ueQueue == 0 ) | |
59 | ueQueue = alloc( MAILBOX, 0, 1 ); | |
60 | else | |
61 | ueQueue = f_ueQueue; | |
62 | f_ueQueue = 0; | |
63 | ||
64 | if ( f_oeQueue == 0 ) | |
65 | oeQueue = alloc( MAILBOX, 0, 1 ); | |
66 | else | |
67 | oeQueue = f_oeQueue; | |
68 | f_oeQueue = 0; | |
69 | } | |
70 | ||
71 | local task freeQueues( integer ueQueue, integer oeQueue ) | |
72 | { | |
73 | bit garb; | |
74 | ||
75 | while( mailbox_get( NO_WAIT, ueQueue, garb ) ) { /* empty the queue */ } | |
76 | while( mailbox_get( NO_WAIT, oeQueue, garb ) ) { /* empty the queue */ } | |
77 | f_ueQueue = ueQueue; | |
78 | f_oeQueue = oeQueue; | |
79 | } | |
80 | ||
81 | local task CheckLoggedHdr( integer errQueue, | |
82 | bit[127:0] tlpHdr, bit[127:0] txHdr, | |
83 | string errClass ) | |
84 | { | |
85 | bit gotX; | |
86 | bit[127:0] errHdr; | |
87 | bit[127:0] reqHdr; | |
88 | PEC_ERRtype errType; | |
89 | ||
90 | ||
91 | // Ignore the TD bit in the | |
92 | // "tlpHdr". | |
93 | tlpHdr[ PEC_PCI__TD ] = 1'b0; | |
94 | ||
95 | // Expected headers will be put | |
96 | // back to our "errQueue". | |
97 | // A "none" error marks the end | |
98 | // of the original contents. | |
99 | mailbox_put( errQueue, e_ERR_none ); | |
100 | ||
101 | // Look at all the different | |
102 | // error-packets... | |
103 | gotX = 0; | |
104 | mailbox_get( NO_WAIT, errQueue, errType ); | |
105 | while( errType != e_ERR_none ) | |
106 | { | |
107 | mailbox_get( NO_WAIT, errQueue, errHdr ); | |
108 | mailbox_get( NO_WAIT, errQueue, reqHdr ); | |
109 | ||
110 | // A time-out? Check the header | |
111 | // from the error-queue against | |
112 | // the logged request header. | |
113 | if ( errType == e_ERR_ue_cto || errType == e_ERR_oe_cto ) | |
114 | { | |
115 | if ( errHdr === 128'bx ) | |
116 | gotX = 1; | |
117 | else if ( txHdr[PEC_PCI__FMT_4DW] ) | |
118 | { | |
119 | if ( txHdr == errHdr ) return; | |
120 | mailbox_put( errQueue, errHdr ); | |
121 | } | |
122 | else | |
123 | { | |
124 | if ( txHdr[127:32] == errHdr[127:32] ) return; | |
125 | mailbox_put( errQueue, errHdr ); | |
126 | } | |
127 | } | |
128 | ||
129 | // If the header is "X", then | |
130 | // anything is OK. | |
131 | else if ( errHdr === 128'bx ) | |
132 | { | |
133 | gotX = 1; | |
134 | } | |
135 | ||
136 | // Otherwise, check to see if | |
137 | // we've got one of the bad-boy | |
138 | // packet headers in the log. | |
139 | else if ( tlpHdr[PEC_PCI__FMT_4DW] ) | |
140 | { | |
141 | errHdr[ PEC_PCI__TD ] = 1'b0; | |
142 | if ( tlpHdr == errHdr ) | |
143 | { | |
144 | if ( reqHdr !== 128'bx ) | |
145 | { | |
146 | if ( reqHdr[PEC_PCI__FMT_4DW] ? ( reqHdr != txHdr ) | |
147 | : ( reqHdr[127:32] != txHdr[127:32] )) | |
148 | { | |
149 | _REPORT_ERR( "Incorrect PIO request header logged" ); | |
150 | ERR_INFO( psprintf( "Actual: %h", txHdr ) ); | |
151 | ERR_INFO( psprintf( "Expect: %h", reqHdr ) ); | |
152 | } | |
153 | } | |
154 | return; | |
155 | } | |
156 | mailbox_put( errQueue, errHdr ); | |
157 | } | |
158 | else | |
159 | { | |
160 | errHdr[ PEC_PCI__TD ] = 1'b0; | |
161 | if ( tlpHdr[127:32] == errHdr[127:32] ) | |
162 | { | |
163 | if ( reqHdr !== 128'bx ) | |
164 | { | |
165 | if ( reqHdr[PEC_PCI__FMT_4DW] ? ( reqHdr != txHdr ) | |
166 | : ( reqHdr[127:32] != txHdr[127:32] )) | |
167 | { | |
168 | _REPORT_ERR( "Incorrect PIO request header logged" ); | |
169 | ERR_INFO( psprintf( "Actual: %h", txHdr ) ); | |
170 | ERR_INFO( psprintf( "Expect: %h", reqHdr ) ); | |
171 | } | |
172 | } | |
173 | return; | |
174 | } | |
175 | mailbox_put( errQueue, errHdr ); | |
176 | } | |
177 | ||
178 | // Get the next guy in the queue | |
179 | mailbox_get( NO_WAIT, errQueue, errType ); | |
180 | } | |
181 | ||
182 | // If we got here, then none of | |
183 | // the erroneous TLP headers | |
184 | // matched. Complain if none | |
185 | // of them was an "X". | |
186 | if ( !gotX ) | |
187 | { | |
188 | _REPORT_ERR( psprintf("Incorrect %s header logged", errClass) ); | |
189 | if ( tlpHdr[PEC_PCI__FMT_4DW] ) | |
190 | ERR_INFO( psprintf("Actual: %h", tlpHdr) ); | |
191 | else | |
192 | ERR_INFO( psprintf("Actual: %h", tlpHdr[127:32]) ); | |
193 | while( mailbox_get( NO_WAIT, errQueue, errHdr ) ) | |
194 | { | |
195 | if ( errHdr[PEC_PCI__FMT_4DW] ) | |
196 | ERR_INFO( psprintf("Expect: %h", errHdr) ); | |
197 | else | |
198 | ERR_INFO( psprintf("Expect: %h", errHdr[127:32]) ); | |
199 | } | |
200 | } | |
201 | ||
202 | } /* end CheckLoggedHdr */ | |
203 | ||
204 | local function | |
205 | bit CheckErrorStatus( bit[63:0] errCSR, //Actual Error | |
206 | bit[63:0] logEnab, | |
207 | bit[63:0] intEnab, | |
208 | bit[63:0] intCSR, | |
209 | bit[63:0] intMask, | |
210 | var bit[31:0] primaryErr, //Expected Error | |
211 | var bit[31:0] secondaryErr, //Expected Error | |
212 | string errType ) | |
213 | { | |
214 | string msg; | |
215 | bit [31:0] primaryLog; | |
216 | bit [31:0] secondaryLog; | |
217 | bit [31:0] secondaryOvfl; | |
218 | ||
219 | // Determine which primary errors | |
220 | // should be logged. | |
221 | primaryLog = primaryErr & logEnab[31:0]; | |
222 | ||
223 | // Primary errors which aren't | |
224 | // recorded in the status register | |
225 | // become secondary errors. | |
226 | // This only applies to primary errors | |
227 | // which are in the "data log" group. | |
228 | secondaryOvfl = primaryLog & ~errCSR[31:0]; | |
229 | primaryLog = primaryLog & errCSR[31:0]; | |
230 | ||
231 | // All logged secondary errors must be | |
232 | // mentioned in the error status CSR. | |
233 | // The primary and secondary log-enables | |
234 | // are the same! | |
235 | secondaryLog = (secondaryErr | secondaryOvfl) & logEnab[31:0]; | |
236 | if ( (secondaryLog & errCSR[63:32]) != secondaryLog ) | |
237 | { | |
238 | sprintf( msg, "Expected %s error status bits are not set", errType ); | |
239 | _REPORT_ERR( msg ); | |
240 | sprintf( msg, " Primary errors..... %h", primaryErr ); | |
241 | ERR_INFO( msg ); | |
242 | sprintf( msg, " Secondary errors... %h", secondaryErr ); | |
243 | ERR_INFO( msg ); | |
244 | sprintf( msg, " Error status CSR... %h", errCSR ); | |
245 | ERR_INFO( msg ); | |
246 | sprintf( msg, " Log enable CSR..... %h", logEnab ); | |
247 | ERR_INFO( msg ); | |
248 | } | |
249 | ||
250 | // If that looks OK, then make sure that | |
251 | // an interrupt is presented to the top | |
252 | // level error/interrupt register AS A | |
253 | // RESULT OF THESE ERRORS. | |
254 | else if ( ({secondaryLog,primaryLog} & intEnab) | |
255 | && !(intCSR & intMask) ) | |
256 | { | |
257 | sprintf( msg, "PEC error register does not reflect %s errors", errType ); | |
258 | _REPORT_ERR( msg ); | |
259 | sprintf( msg, " PEC error status...... %h", intCSR ); | |
260 | ERR_INFO( msg ); | |
261 | sprintf( msg, " Logged errors......... %h", errCSR ); | |
262 | ERR_INFO( msg ); | |
263 | sprintf( msg, " Enabled interrupts.... %h", intEnab ); | |
264 | ERR_INFO( msg ); | |
265 | sprintf( msg, " Primary errors........ %h", primaryErr ); | |
266 | ERR_INFO( msg ); | |
267 | sprintf( msg, " Secondary errors...... %h", secondaryErr ); | |
268 | ERR_INFO( msg ); | |
269 | sprintf( msg, " secondaryLog= %h primaryLog=%h intMask=%h", secondaryLog,primaryLog,intMask ); | |
270 | ERR_INFO( msg ); | |
271 | } | |
272 | ||
273 | // Do we expect an interrupt as a result | |
274 | // of these errors? | |
275 | CheckErrorStatus = ({secondaryLog,primaryLog} & intEnab) | |
276 | && (intCSR & intMask); | |
277 | ||
278 | // Expected errors which are logged | |
279 | // must be cleared. | |
280 | primaryErr = primaryLog & errCSR[31:0]; | |
281 | secondaryErr = secondaryLog & errCSR[63:32]; | |
282 | } /* end CheckErrorStatus */ | |
283 | ||
284 | task Execute() | |
285 | { | |
286 | integer oeErrQueue; // OEs from "f_errQueue" | |
287 | integer ueErrQueue; // UEs from "f_errQueue" | |
288 | integer errTotal; // # of errors expected | |
289 | integer errCount; // # of errors seen so far | |
290 | integer multErrCount; // # of errors from one strat'y | |
291 | PEC_ERRtype errType; // The sort of error | |
292 | bit[127:0] errHdr; // The offending TLP's header | |
293 | bit[127:0] reqHdr; // A transmitted request? | |
294 | bit[31:0] primaryILU; | |
295 | bit[31:0] primaryUE; | |
296 | bit[31:0] primaryCE; | |
297 | bit[31:0] primaryOE; | |
298 | bit[31:0] primaryDLPL; | |
299 | bit[31:0] secondaryILU; | |
300 | bit[31:0] secondaryUE; | |
301 | bit[31:0] secondaryCE; | |
302 | bit[31:0] secondaryOE; | |
303 | bit[31:0] secondaryDLPL; //Should never be anything but 0 | |
304 | bit[31:0] optionalILU; | |
305 | bit[31:0] optionalUE; | |
306 | bit[31:0] optionalCE; | |
307 | bit[31:0] optionalOE; | |
308 | bit[31:0] optionalDLPL; | |
309 | bit[63:0] pecErr; | |
310 | bit[63:0] logErr; | |
311 | bit[63:0] logEnab; | |
312 | bit[63:0] intEnab; | |
313 | bit[63:0] logHdr1; | |
314 | bit[63:0] logHdr2; | |
315 | bit[63:0] reqHdr1; | |
316 | bit[63:0] reqHdr2; | |
317 | bit iluInt = 0; | |
318 | bit ueInt = 0; | |
319 | bit ceInt = 0; | |
320 | bit oeInt = 0; | |
321 | bit optIluInt = 0; | |
322 | bit optUeInt = 0; | |
323 | bit optCeInt = 0; | |
324 | bit optOeInt = 0; | |
325 | integer errBit; | |
326 | string msg; | |
327 | integer timerErrQueue; | |
328 | ||
329 | // Build other mailboxes to hold the | |
330 | // descriptors for the expected | |
331 | // UE and OE errors. | |
332 | allocQueues( ueErrQueue, oeErrQueue ); | |
333 | ||
334 | // There are two entries in the | |
335 | // "f_errQueue" for every error. | |
336 | // We're going to take errors from the | |
337 | // "f_errQueue" and mark a "primary" | |
338 | // bit if the error is expected, and a | |
339 | // "secondary" bit if it's expected to | |
340 | // happen more than once. | |
341 | errCount = 0; | |
342 | primaryILU = 32'b0; | |
343 | primaryUE = 32'b0; | |
344 | primaryCE = 32'b0; | |
345 | primaryOE = 32'b0; | |
346 | primaryDLPL = 32'b0; | |
347 | secondaryILU = 32'b0; | |
348 | secondaryUE = 32'b0; | |
349 | secondaryCE = 32'b0; | |
350 | secondaryOE = 32'b0; | |
351 | secondaryDLPL = 32'b0; | |
352 | optionalILU = 32'b0; | |
353 | optionalUE = 32'b0; | |
354 | optionalCE = 32'b0; | |
355 | optionalOE = 32'b0; | |
356 | optionalDLPL = 32'b0; | |
357 | reqHdr = 128'bx; | |
358 | ||
359 | errTotal = f_errCount; | |
360 | while( errCount < errTotal ) | |
361 | { | |
362 | ||
363 | fork | |
364 | { | |
365 | void = mailbox_get( WAIT, f_errQueue, errType ); | |
366 | } | |
367 | { | |
368 | //Timeout if errors never make it to f_errQueue | |
369 | timerErrQueue = 10000; | |
370 | while( timerErrQueue ){ | |
371 | @(posedge CLOCK); | |
372 | timerErrQueue--; | |
373 | } | |
374 | } | |
375 | join any | |
376 | if( !timerErrQueue ){ | |
377 | Report.report(RTYP_TEST_ERROR,"ErrChkPEUStr timed out waiting for mailbox_get of f_errQueue\n"); | |
378 | } | |
379 | terminate; | |
380 | // If the error is "none", then what | |
381 | // follows is the actual number of | |
382 | // errors generated by a strategy. | |
383 | if ( errType == e_ERR_none ) | |
384 | { | |
385 | void = mailbox_get( WAIT, f_errQueue, multErrCount ); | |
386 | if ( multErrCount < 0 ) | |
387 | void = mailbox_get( WAIT, f_errQueue, reqHdr ); | |
388 | else | |
389 | errTotal = errTotal + multErrCount - 1; | |
390 | continue; | |
391 | } | |
392 | ||
393 | // Otherwise, put the error and the | |
394 | // associated header in the local FIFO. | |
395 | void = mailbox_get( WAIT, f_errQueue, errHdr ); | |
396 | if ( PEC_ERR_isUE(errType) && errHdr !== 128'bx0 ) | |
397 | { | |
398 | mailbox_put( ueErrQueue, errType ); | |
399 | mailbox_put( ueErrQueue, errHdr ); | |
400 | mailbox_put( ueErrQueue, reqHdr ); | |
401 | } | |
402 | else if ( PEC_ERR_isOE(errType) && errHdr !== 128'bx0 ) | |
403 | { | |
404 | mailbox_put( oeErrQueue, errType ); | |
405 | mailbox_put( oeErrQueue, errHdr ); | |
406 | mailbox_put( oeErrQueue, reqHdr ); | |
407 | } | |
408 | reqHdr = 128'bx; | |
409 | errCount = errCount + 1; | |
410 | ||
411 | // Mark the error-status bit associated | |
412 | // with this error as expected. | |
413 | errBit = PEC_ERR_bitIndex(errType); | |
414 | if ( errBit < 0 ) | |
415 | _REPORT_ERR( "Internal BUG! Invalid error type?!?" ); | |
416 | else if ( PEC_ERR_isILU(errType) ) | |
417 | { | |
418 | if ( errHdr === 128'bx0 ) | |
419 | optionalILU[errBit] = 1'b1; | |
420 | else if ( primaryILU[errBit] ) | |
421 | secondaryILU[errBit] = 1'b1; | |
422 | else | |
423 | primaryILU[errBit] = 1'b1; | |
424 | } | |
425 | else if ( PEC_ERR_isUE(errType) ) | |
426 | { | |
427 | if ( errHdr === 128'bx0 ) | |
428 | optionalUE[errBit] = 1'b1; | |
429 | else if ( primaryUE[errBit] ) | |
430 | secondaryUE[errBit] = 1'b1; | |
431 | else | |
432 | primaryUE[errBit] = 1'b1; | |
433 | } | |
434 | else if ( PEC_ERR_isCE(errType) ) | |
435 | { | |
436 | if ( errHdr === 128'bx0 ) | |
437 | optionalCE[errBit] = 1'b1; | |
438 | else if ( primaryCE[errBit] ) | |
439 | secondaryCE[errBit] = 1'b1; | |
440 | else | |
441 | primaryCE[errBit] = 1'b1; | |
442 | } | |
443 | else if ( PEC_ERR_isOE(errType) ) | |
444 | { | |
445 | if ( errHdr === 128'bx0 ) | |
446 | optionalOE[errBit] = 1'b1; | |
447 | else if ( errBit === 11 ) //LIN is primary only | |
448 | primaryOE[errBit] = 1'b1; | |
449 | else if ( primaryOE[errBit] ) | |
450 | secondaryOE[errBit] = 1'b1; | |
451 | else | |
452 | primaryOE[errBit] = 1'b1; | |
453 | } | |
454 | else if ( PEC_ERR_isDLPL(errType) ) | |
455 | { | |
456 | ||
457 | if ( errHdr === 128'bx0 ) | |
458 | optionalDLPL[errBit] = 1'b1; | |
459 | else //There are only primary errors in the DLPL register | |
460 | primaryDLPL[errBit] = 1'b1; | |
461 | } | |
462 | } | |
463 | ||
464 | Report.report( RTYP_INFO, "ErrChkPEUStr errTotal=%0d received pILU=%0h pUE=%0h pCE=%0h pOE=%0h sILU=%0h sUE=%0h sCE=%0h sOE=%0h \n", errTotal,primaryILU,primaryUE,primaryCE,primaryOE,secondaryILU,secondaryUE,secondaryCE,secondaryOE ); | |
465 | Report.report( RTYP_INFO, "ErrChkPEUStr oILU=%0h oUE=%0h oCE=%0h oOE=%0h \n", optionalILU,optionalUE,optionalCE,optionalOE ); | |
466 | ||
467 | // We've received all the errors that | |
468 | // we expect. Now check that the | |
469 | // errors were recorded correctly by | |
470 | // the DUT. First, make sure that the | |
471 | // ILU/UE/CE/OE bit(s) are correct. | |
472 | #ifdef N2_IOS | |
473 | pecErr = readPECRegister(); | |
474 | #else | |
475 | pecErr = f_env.readCSR( f_env.getCSRaddr( e_CSR_pec_err ) ); | |
476 | #endif | |
477 | ||
478 | ||
479 | // Make sure that the individual | |
480 | // error bits are set correctly. | |
481 | // and that the "pecErr" is set if any | |
482 | // error is enabled for both logging | |
483 | // and for interrupts! | |
484 | // Be sure to check the secondary bits! | |
485 | if ( primaryILU || optionalILU ) | |
486 | { | |
487 | logErr = f_env.readCSRdirect( f_env.getCSRaddr( e_CSR_ilu_err ) ); | |
488 | logEnab = f_env.readCSRdirect( f_env.getCSRaddr( e_CSR_ilu_log_en ) ); | |
489 | intEnab = f_env.readCSRdirect( f_env.getCSRaddr( e_CSR_ilu_int_en ) ); | |
490 | ||
491 | if( primaryILU ){ | |
492 | iluInt = CheckErrorStatus( logErr, logEnab, intEnab, | |
493 | pecErr, PEC_ERR_ILU_mask, | |
494 | primaryILU, secondaryILU, "ILU" ); | |
495 | }else if( optionalILU ){ | |
496 | //Check for optional errors that are log and interrupt enabled | |
497 | optIluInt = |( {optionalILU,optionalILU} & | |
498 | logErr & | |
499 | {logEnab[31:0],logEnab[31:0]} & | |
500 | intEnab ); | |
501 | } | |
502 | } | |
503 | ||
504 | // Are we expecting a UE? | |
505 | if ( primaryUE || optionalUE ) | |
506 | { | |
507 | // Get the UE error status | |
508 | logErr = f_env.readCSRdirect( f_env.getCSRaddr( e_CSR_ue_err ) ); | |
509 | logEnab = f_env.readCSRdirect( f_env.getCSRaddr( e_CSR_ue_log_en ) ); | |
510 | intEnab = f_env.readCSRdirect( f_env.getCSRaddr( e_CSR_ue_int_en ) ); | |
511 | ||
512 | // Make sure the error status agrees | |
513 | // with the errors that have been | |
514 | // stimulated, and those that have | |
515 | // been logged. | |
516 | if( primaryUE ){ | |
517 | ueInt = CheckErrorStatus( logErr, logEnab, intEnab, | |
518 | pecErr, PEC_ERR_UE_mask, | |
519 | primaryUE, secondaryUE, "'uncorrectable'" ); | |
520 | ||
521 | // If one of our UEs was logged, then | |
522 | // make sure that the captured TLP | |
523 | // header is correct. | |
524 | if( primaryUE ){ | |
525 | logHdr1 = f_env.readCSRdirect( f_env.getCSRaddr( e_CSR_ue_recv_hdr1 ) ); | |
526 | logHdr2 = f_env.readCSRdirect( f_env.getCSRaddr( e_CSR_ue_recv_hdr2 ) ); | |
527 | reqHdr1 = f_env.readCSRdirect( f_env.getCSRaddr( e_CSR_ue_xmit_hdr1 ) ); | |
528 | reqHdr2 = f_env.readCSRdirect( f_env.getCSRaddr( e_CSR_ue_xmit_hdr2 ) ); | |
529 | CheckLoggedHdr( ueErrQueue, { logHdr1, logHdr2 }, {reqHdr1, reqHdr2}, | |
530 | "uncorrectable" ); | |
531 | } | |
532 | }else if( optionalUE ){ | |
533 | //Check for optional errors that are log and interrupt enabled | |
534 | optUeInt = |( {optionalUE,optionalUE} & | |
535 | logErr & | |
536 | {logEnab[31:0],logEnab[31:0]} & | |
537 | intEnab ); | |
538 | } | |
539 | } | |
540 | ||
541 | if ( primaryCE || optionalCE ) | |
542 | { | |
543 | logErr = f_env.readCSRdirect( f_env.getCSRaddr( e_CSR_ce_err ) ); | |
544 | logEnab = f_env.readCSRdirect( f_env.getCSRaddr( e_CSR_ce_log_en ) ); | |
545 | intEnab = f_env.readCSRdirect( f_env.getCSRaddr( e_CSR_ce_int_en ) ); | |
546 | ||
547 | if( primaryCE ){ | |
548 | ceInt = CheckErrorStatus( logErr, logEnab, intEnab, | |
549 | pecErr, PEC_ERR_CE_mask, | |
550 | primaryCE, secondaryCE, "'correctable'" ); | |
551 | }else if( optionalCE ){ | |
552 | //Check for optional errors that are log and interrupt enabled | |
553 | optCeInt = |( {optionalCE,optionalCE} & | |
554 | logErr & | |
555 | {logEnab[31:0],logEnab[31:0]} & | |
556 | intEnab ); | |
557 | } | |
558 | } | |
559 | ||
560 | if ( primaryOE || optionalOE ) | |
561 | { | |
562 | logErr = f_env.readCSRdirect( f_env.getCSRaddr( e_CSR_oe_err ) ); | |
563 | logEnab = f_env.readCSRdirect( f_env.getCSRaddr( e_CSR_oe_log_en ) ); | |
564 | intEnab = f_env.readCSRdirect( f_env.getCSRaddr( e_CSR_oe_int_en ) ); | |
565 | ||
566 | if( primaryOE ){ | |
567 | oeInt = CheckErrorStatus( logErr, logEnab, intEnab, | |
568 | pecErr, PEC_ERR_OE_mask, | |
569 | primaryOE, secondaryOE, "'other'" ); | |
570 | ||
571 | // If one of our OEs was logged, then | |
572 | // make sure that the captured TLP | |
573 | // header is correct. | |
574 | if ( primaryOE ) | |
575 | { | |
576 | logHdr1 = f_env.readCSRdirect( f_env.getCSRaddr( e_CSR_oe_recv_hdr1 ) ); | |
577 | logHdr2 = f_env.readCSRdirect( f_env.getCSRaddr( e_CSR_oe_recv_hdr2 ) ); | |
578 | reqHdr1 = f_env.readCSRdirect( f_env.getCSRaddr( e_CSR_oe_xmit_hdr1 ) ); | |
579 | reqHdr2 = f_env.readCSRdirect( f_env.getCSRaddr( e_CSR_oe_xmit_hdr2 ) ); | |
580 | CheckLoggedHdr( oeErrQueue, { logHdr1, logHdr2 }, { reqHdr1, reqHdr2 }, | |
581 | "other" ); | |
582 | } | |
583 | }else if( optionalOE ){ | |
584 | //Check for optional errors that are log and interrupt enabled | |
585 | optOeInt = |( {optionalOE,optionalOE} & | |
586 | logErr & | |
587 | {logEnab[31:0],logEnab[31:0]} & | |
588 | intEnab ); | |
589 | } | |
590 | } | |
591 | ||
592 | if ( primaryDLPL ) | |
593 | { | |
594 | logErr = f_env.readCSRdirect( f_env.getCSRaddr( e_CSR_dlpl_ee_err ) ); | |
595 | logEnab = f_env.readCSRdirect( f_env.getCSRaddr( e_CSR_dlpl_ee_log_en ) ); | |
596 | intEnab = f_env.readCSRdirect( f_env.getCSRaddr( e_CSR_dlpl_ee_int_en ) ); | |
597 | ||
598 | //DLPL errors will also generate a OE Link error that will generate | |
599 | // the interrupt | |
600 | //Only check the errors and not the events | |
601 | void = CheckErrorStatus( (logErr & 32'h3ffff), logEnab, intEnab, | |
602 | pecErr, PEC_ERR_OE_mask, | |
603 | primaryDLPL, secondaryDLPL, "'DLPL'" ); | |
604 | } | |
605 | ||
606 | //If there were no primary interrupts expected then check for any optional errors | |
607 | // that could cause an interrupt | |
608 | if( iluInt | ueInt | ceInt | oeInt ){ | |
609 | // Make sure an interrupt was presented. | |
610 | Report.report( RTYP_DEBUG_3, "ErrChkPEUStr call f_env.expectInterrupt iluInt=%0h ueInt=%0h ceInt=%0h oeInt=%0h \n",iluInt,ueInt,ceInt,oeInt ); | |
611 | void = f_env.expectInterrupt( 1 ); | |
612 | }else if( optIluInt | optUeInt | optCeInt | optOeInt ){ | |
613 | // Make sure an optional interrupt was presented if no primary. | |
614 | Report.report( RTYP_DEBUG_3, "ErrChkPEUStr call f_env.expectInterrupt optIluInt=%0h optUeInt=%0h optCeInt=%0h optOeInt=%0h \n",optIluInt,optUeInt,optCeInt,optOeInt ); | |
615 | void = f_env.expectInterrupt( 1 ); | |
616 | } | |
617 | ||
618 | ||
619 | ||
620 | ||
621 | // Clear the logged error bits. | |
622 | #ifdef N2_IOS | |
623 | if ( primaryILU | secondaryILU | optionalILU ) | |
624 | { | |
625 | f_env.writeCSRdirect( f_env.getCSRaddr( e_CSR_ilu_err ), | |
626 | { secondaryILU | optionalILU, primaryILU | optionalILU }); | |
627 | } | |
628 | ||
629 | if ( primaryUE | secondaryUE | optionalUE ) | |
630 | { | |
631 | f_env.writeCSRdirect( f_env.getCSRaddr( e_CSR_ue_err ), | |
632 | { secondaryUE | optionalUE, primaryUE | optionalUE } ); | |
633 | } | |
634 | ||
635 | if ( primaryCE | secondaryCE | optionalCE ) | |
636 | { | |
637 | f_env.writeCSRdirect( f_env.getCSRaddr( e_CSR_ce_err ), | |
638 | { secondaryCE | optionalCE, primaryCE | optionalCE } ); | |
639 | } | |
640 | ||
641 | //DLPL Errors must be cleared before OE so Link Up bit gets cleared | |
642 | if ( primaryDLPL | secondaryDLPL | optionalDLPL ) | |
643 | { | |
644 | f_env.writeCSRdirect( f_env.getCSRaddr( e_CSR_dlpl_ee_err ), | |
645 | { secondaryDLPL | optionalDLPL, primaryDLPL | optionalDLPL } ); | |
646 | } | |
647 | ||
648 | if ( primaryOE | secondaryOE | optionalOE ) | |
649 | { | |
650 | f_env.writeCSRdirect( f_env.getCSRaddr( e_CSR_oe_err ), | |
651 | { secondaryOE | optionalOE, primaryOE | optionalOE } ); | |
652 | } | |
653 | ||
654 | #else | |
655 | if ( primaryILU | secondaryILU | optionalILU ) | |
656 | { | |
657 | f_env.writeCSR( f_env.getCSRaddr( e_CSR_ilu_err ), | |
658 | { secondaryILU | optionalILU, primaryILU | optionalILU }); | |
659 | } | |
660 | ||
661 | if ( primaryUE | secondaryUE | optionalUE ) | |
662 | { | |
663 | f_env.writeCSR( f_env.getCSRaddr( e_CSR_ue_err ), | |
664 | { secondaryUE | optionalUE, primaryUE | optionalUE } ); | |
665 | } | |
666 | ||
667 | if ( primaryCE | secondaryCE | optionalCE ) | |
668 | { | |
669 | f_env.writeCSR( f_env.getCSRaddr( e_CSR_ce_err ), | |
670 | { secondaryCE | optionalCE, primaryCE | optionalCE } ); | |
671 | } | |
672 | ||
673 | //DLPL Errors must be cleared before OE so Link Up bit gets cleared | |
674 | if ( primaryDLPL | secondaryDLPL | optionalDLPL ) | |
675 | { | |
676 | f_env.writeCSR( f_env.getCSRaddr( e_CSR_dlpl_ee_err ), | |
677 | { secondaryDLPL | optionalDLPL, primaryDLPL | optionalDLPL } ); | |
678 | } | |
679 | ||
680 | if ( primaryOE | secondaryOE | optionalOE ) | |
681 | { | |
682 | f_env.writeCSR( f_env.getCSRaddr( e_CSR_oe_err ), | |
683 | { secondaryOE | optionalOE, primaryOE | optionalOE } ); | |
684 | } | |
685 | ||
686 | #endif | |
687 | // All done! | |
688 | f_env.enableInterrupt(); | |
689 | freeQueues( ueErrQueue, oeErrQueue ); | |
690 | ||
691 | } /* end Execute */ | |
692 | ||
693 | virtual function bit [63:0] readPECRegister() { | |
694 | ||
695 | } | |
696 | } /* end ErrChkPEUStr */ | |
697 |