Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / verif / env / ilu_peu / vera / N2str / ilupeuMalReqPEUStr.vr
CommitLineData
86530b38
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: ilupeuMalReqPEUStr.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 ============================================
35class MalReqPEUStr extends PEUStrBase
36 {
37 local bit f_typeSpecified; // Was a bad-boy type supplied?
38 local bit [1:0] f_fmt; // The bad format
39 local bit [4:0] f_type; // The bad type
40 local bit f_lenSpecified; // Was a TLP length supplied?
41 local integer f_len; // A requested TLP length
42 local integer f_cross4K; // By what amount do we cross 4K
43 local integer f_adjustLen; // The delta to the true length
44 local integer f_errQueue; // A mailbox for bad pkt headers
45 local bit f_tdSpecified; // Was the TD supplied?
46 local bit f_tdFieldValue; // The TD value
47 local bit [7:0] f_msgcode; // Msg code (for Msg requests)
48 local bit f_mcSpecified; // Was the msg code supplied?
49 local bit [2:0] f_TC;
50 local bit f_TCSpecified;
51 local bit f_dwbeSpecified;
52 local bit [3:0] f_firstDWBE;
53 local bit [3:0] f_lastDWBE;
54 local bit f_QWbndy;
55
56 task new( PEUTestEnv a_env )
57 {
58 super.new( a_env );
59 f_typeSpecified = 0;
60 f_lenSpecified = 0;
61 f_errQueue = 0;
62 f_adjustLen = 0;
63 f_cross4K = 0;
64 f_dwbeSpecified = 0;
65 f_QWbndy = 1'bx;
66
67 f_tdSpecified = 0;
68 } /* end new */
69
70 function bit SetType( bit [1:0] a_fmt, bit [4:0] a_type )
71 {
72 bit isInvalid;
73
74 case ( a_fmt )
75 {
76 2'b00: isInvalid = !( PEC_PCI__TYPE_VALID_00 & ( 1 << a_type ) );
77 2'b01: isInvalid = !( PEC_PCI__TYPE_VALID_01 & ( 1 << a_type ) );
78 2'b10: isInvalid = !( PEC_PCI__TYPE_VALID_10 & ( 1 << a_type ) );
79 2'b11: isInvalid = !( PEC_PCI__TYPE_VALID_11 & ( 1 << a_type ) );
80 }
81 if ( isInvalid )
82 {
83 f_typeSpecified = 1;
84 f_type = a_type;
85 f_fmt = a_fmt;
86 }
87 SetType = isInvalid;
88 } /* end SetType */
89
90 task SetLength( integer a_length )
91 {
92 f_len= a_length;
93 f_lenSpecified = 1;
94 } /* end SetLength */
95
96 task AdjustLen( integer a_lengthDelta )
97 {
98 f_adjustLen = a_lengthDelta;
99 } /* end AdjustLen */
100
101 task Cross4K( integer a_dwCount )
102 {
103 f_cross4K = a_dwCount;
104 } /* end AdjustLen */
105
106 function bit SetDWBE( bit [3:0] firstDWBE, bit [3:0] lastDWBE,
107 (bit QWbndy=1'bx) )
108 {
109 bit isContiguous;
110 bit isInvalid;
111
112 // DWBEs are bad if lastDWBE != 0 and len = 1, or either = 0 and len > 1
113 // DWBEs are bad if not contiguous and len > 2 or len = 2 not on QW bndy
114 // We'll force a length to make the DWBE bad if one has not been specified
115 isContiguous = ( firstDWBE == 4'b1000 || firstDWBE == 4'b1100 ||
116 firstDWBE == 4'b1110 || firstDWBE == 4'b1111 )
117 && ( lastDWBE == 4'b0001 || lastDWBE == 4'b0011 ||
118 lastDWBE == 4'b0111 || lastDWBE == 4'b1111 );
119 if ( f_lenSpecified )
120 {
121 if ( f_len == 1 )
122 isInvalid = lastDWBE != 0;
123 else if ( f_len == 2 && QWbndy )
124 isInvalid = !firstDWBE || !lastDWBE;
125 else
126 isInvalid = !isContiguous;
127 }
128 else
129 {
130 f_lenSpecified = 1;
131 f_len = isContiguous ? 1 : 4;
132 isInvalid = 1;
133 }
134
135 if ( isInvalid )
136 {
137 f_dwbeSpecified = 1;
138 f_firstDWBE = firstDWBE;
139 f_lastDWBE = lastDWBE;
140 f_QWbndy = QWbndy;
141 if ( f_len == 2 && QWbndy !== 1'b1 ) f_QWbndy = 1'b0;
142 }
143
144 SetDWBE = isInvalid;
145 } /* end SetDWBE */
146
147 task SetErrQueue( integer a_queue )
148 {
149 f_errQueue = a_queue;
150 } /* end SetErrQueue */
151
152 task SetTD( bit a_TDValue )
153 {
154 f_tdFieldValue = a_TDValue;
155 f_tdSpecified = 1;
156 } /* end SetTD */
157
158 function bit SetField( string FieldName, bit [9:0] FieldValue )
159 {
160 // return value of 1'b1 indicates something went wrong
161 case ( FieldName ) {
162 "FmtType" : {
163 f_type = FieldValue[ 4:0 ];
164 f_fmt = FieldValue[ 6:5 ];
165 f_typeSpecified = 1;
166
167 case ( f_fmt ) {
168 2'b00: SetField = !( PEC_PCI__TYPE_VALID_00 & ( 1 << f_type ) );
169 2'b01: SetField = !( PEC_PCI__TYPE_VALID_01 & ( 1 << f_type ) );
170 2'b10: SetField = !( PEC_PCI__TYPE_VALID_10 & ( 1 << f_type ) );
171 2'b11: SetField = !( PEC_PCI__TYPE_VALID_11 & ( 1 << f_type ) );
172 }
173 }
174 "MsgCode" : {
175 f_msgcode = FieldValue;
176 f_mcSpecified = 1;
177 SetField = 1'b0;
178 }
179 "TC" : {
180 f_TC = FieldValue[ 2:0 ];
181 f_TCSpecified = 1;
182 SetField = 1'b0;
183 }
184 default :
185 SetField = 1'b1;
186 }
187 } /* end SetField */
188
189 task Execute()
190 {
191 bit genWrReq; // Is a write request in order?
192 bit[PEC_PCI__HDR] ingressHdr; // The ingress TLP's header
193 integer ingressData; // A payload descriptor
194 bit[7:0] ingressTag; // The tag for the TLP
195 bit[63:0] addr_bits;
196 bit[9:0] length_bits;
197 integer tlpLen;
198 bit [63:0] diagCsr;
199 bit [31:0] tempDenaliData;
200 bit [31:0] tempDenaliData1;
201
202 // First, get in line for a DMA tag...
203 f_env.allocDmaTag( ingressTag );
204 printf( "MalReq: tag=%h", ingressTag );
205 if ( f_lenSpecified ) printf( " len=%0d", f_len );
206 if ( f_cross4K != 0 ) printf( " cross4K=%0d", f_cross4K );
207 if ( f_dwbeSpecified ) printf( " firstDWBE=%b lastDWBE=%b",
208 f_firstDWBE, f_lastDWBE );
209 if( f_typeSpecified ) printf( " f_fmt=%0h ",f_fmt );
210 printf( "\n" );
211
212 // Then build a TLP.
213 // Either a write or a read (with or
214 // without data.
215 if ( f_typeSpecified )
216 {
217 ingressHdr[PEC_PCI__FMT] = f_fmt;
218 genWrReq = ingressHdr[PEC_PCI__FMT_DATA];
219 }
220 else
221 genWrReq = urandom() % 2;
222
223
224 //If this is a cross4K test then set the length so valid DWBE's are generated
225 if ( f_cross4K != 0 ) {
226 // f_cross4K specifies the number of DWs
227 // to cross the next 4KB boundary by
228 // pkt length greater than or equal to
229 // the amount to cross boundary by
230 length_bits = (urandom() % 15) + 1;
231 f_len = length_bits + f_cross4K;
232 f_lenSpecified = 1;
233 }
234
235
236
237
238 if ( genWrReq )
239 {
240 if ( f_lenSpecified )
241 f_env.genIngressWrReq( ingressTag, ingressHdr, ingressData, f_len );
242 else
243 f_env.genIngressWrReq( ingressTag, ingressHdr, ingressData );
244 }
245 else
246 {
247 if ( f_lenSpecified )
248 f_env.genIngressRdReq( ingressTag, ingressHdr, ingressData, f_len );
249 else
250 f_env.genIngressRdReq( ingressTag, ingressHdr, ingressData );
251 }
252 //Denali can hold a TLP from being transmitted if a previous TLP
253 // with the same tag and Request ID has not completed yet. This only
254 // should happen with error TLPs. To help with this make all bad REQs
255 // PEC_PCI__REQ_ID[0] = 1
256 ingressHdr[80] = 1'b1;
257
258
259 // ...and then pollute the request as
260 // directed by the caller.
261 if ( f_typeSpecified )
262 {
263 ingressHdr[PEC_PCI__FMT] = f_fmt;
264 ingressHdr[PEC_PCI__TYPE] = f_type;
265 }
266 if ( f_dwbeSpecified )
267 {
268 if ( f_QWbndy ) f_env.setAddrBndy( ingressHdr, 0, 8 );
269 if ( !f_QWbndy ) f_env.setAddrBndy( ingressHdr, 4, 8 );
270 ingressHdr[PEC_PCI__FIRST_DWBE] = f_firstDWBE;
271 ingressHdr[PEC_PCI__LAST_DWBE] = f_lastDWBE;
272 }
273 if ( f_cross4K != 0 ) {
274 if ( ingressHdr[PEC_PCI__TYPE] != PEC_PCI__TYPE_MEM )
275 {
276 printf( "Forcing req-type to 'memory' due to 4KB crossing\n" );
277 ingressHdr[PEC_PCI__TYPE] = PEC_PCI__TYPE_MEM;
278 }
279
280
281 // f_cross4K specifies the number of DWs
282 // to cross the next 4KB boundary by
283 // pkt length greater than or equal to
284 // the amount to cross boundary by
285/* Do this before calling genIngressXxReq so valid DWBEs get generated
286 length_bits = (urandom() % 15) + 1;
287 ingressHdr[PEC_PCI__LEN] = length_bits + f_cross4K;
288*/
289 ingressHdr[PEC_PCI__LEN] = f_len;
290 if( ingressHdr[PEC_PCI__FMT_4DW] ) {
291 addr_bits = ingressHdr[PEC_PCI__ADDR];
292 addr_bits[11:2] = 1024 - length_bits;
293 ingressHdr[PEC_PCI__ADDR] = addr_bits;
294 }
295 else {
296 addr_bits = {{32'h00000000},ingressHdr[PEC_PCI__ADDR32]};
297 addr_bits[11:2] = 1024 - length_bits;
298 addr_bits[1:0] = 0; //if f_typeSpecified make sure the lowest 2 addr bits are 0
299 ingressHdr[PEC_PCI__ADDR32] = addr_bits[31:0];
300 }
301 }
302
303 //If this is a memory request make sure lower 2 address bits are 0 for header capture
304 // since Denali sets them to 0 automatically
305 if( ingressHdr[PEC_PCI__TYPE] == PEC_PCI__TYPE_MEM ){
306 if( ingressHdr[PEC_PCI__FMT_4DW] ) {
307 ingressHdr[1:0] = 0;
308 }else{
309 ingressHdr[33:32] = 0;
310 }
311 }
312
313
314 if ( f_tdSpecified )
315 ingressHdr[PEC_PCI__TD] = f_tdFieldValue;
316
317 if ( f_mcSpecified ){
318 ingressHdr[PEC_PCI__MSG_CODE] = f_msgcode;
319 ingressHdr[PEC_PCI__ATTR] = 0;
320 ingressHdr[PEC_PCI__ADDR] = 0; //DW3 and DW4 = 0
321
322 if( f_msgcode == PEC_PCI__MSG_CODE_ASSERT_INTA ||
323 f_msgcode == PEC_PCI__MSG_CODE_ASSERT_INTB ||
324 f_msgcode == PEC_PCI__MSG_CODE_ASSERT_INTC ||
325 f_msgcode == PEC_PCI__MSG_CODE_ASSERT_INTD ||
326 f_msgcode == PEC_PCI__MSG_CODE_DEASSERT_INTA ||
327 f_msgcode == PEC_PCI__MSG_CODE_DEASSERT_INTB ||
328 f_msgcode == PEC_PCI__MSG_CODE_DEASSERT_INTC ||
329 f_msgcode == PEC_PCI__MSG_CODE_DEASSERT_INTD ){
330
331 ingressHdr[PEC_PCI__TYPE] = 5'b10100;
332 }
333 else if( f_msgcode == PEC_PCI__MSG_CODE_PM_PME ||
334 f_msgcode == PEC_PCI__MSG_CODE_ERR_COR ||
335 f_msgcode == PEC_PCI__MSG_CODE_ERR_NONFATAL ||
336 f_msgcode == PEC_PCI__MSG_CODE_ERR_FATAL ){
337 ingressHdr[PEC_PCI__TYPE] = 5'b10000;
338 }
339 else if( f_msgcode == PEC_PCI__MSG_CODE_PM_TO_ACK ){
340 ingressHdr[PEC_PCI__TYPE] = 5'b10101;
341 }
342
343 if( !ingressHdr[PEC_PCI__FMT_DATA] ){
344 ingressHdr[PEC_PCI__LEN] = 0;
345 }
346 }
347
348 if ( f_TCSpecified )
349 ingressHdr[PEC_PCI__TC] = f_TC;
350
351 // Don't allow the truncated TLP to be
352 // less than 3DW.
353 if ( f_adjustLen < 0 && !ingressHdr[PEC_PCI__FMT_DATA] )
354 {
355 tlpLen = 3 + ingressHdr[PEC_PCI__FMT_4DW] + ingressHdr[PEC_PCI__TD];
356 if ( tlpLen + f_adjustLen < 3 )
357 printf( "MalReq (cycle %0d) Adding TD/addr to TLP to reach 3DW...\n",
358 get_cycle() );
359 if ( tlpLen + f_adjustLen < 3 && !ingressHdr[PEC_PCI__TD] )
360 {
361 tlpLen = tlpLen + 1;
362 ingressHdr[PEC_PCI__TD] = 1;
363 }
364 if ( tlpLen + f_adjustLen < 3 ) ingressHdr[PEC_PCI__FMT_4DW] = 1;
365 }
366
367 //Check to see if any of the optional checks are disabled
368 // If they are then the transactin has to pass like a good packet
369 diagCsr = f_env.readCSRdirect( f_env.getCSRaddr( e_CSR_tlu_diag ) );
370
371 if( f_cross4K && diagCsr[37] == 1 ||
372 f_dwbeSpecified && diagCsr[36] ){
373 f_env.reserveIngressCredits( ingressHdr );
374 }
375
376 if( f_dwbeSpecified ){
377 f_env.Pod.FNXPCIEEnableTrans.tempSuppressDenaliErr( PCIE_TL_NONFATAL_TLP_MF_vlLastBE0 );
378 f_env.Pod.FNXPCIEEnableTrans.tempSuppressDenaliErr( PCIE_TL_NONFATAL_TLP_MF_vl1stBE );
379 f_env.Pod.FNXPCIEEnableTrans.tempSuppressDenaliErr( PCIE_TL_NONFATAL_TLP_MF_vlLastBE1 );
380 f_env.Pod.FNXPCIEEnableTrans.tempSuppressDenaliErr( PCIE_TL_NONFATAL_TLP_MF_vlNC1stBE );
381 f_env.Pod.FNXPCIEEnableTrans.tempSuppressDenaliErr( PCIE_TL_NONFATAL_TLP_MF_vlNClastBE );
382 f_env.Pod.FNXPCIEEnableTrans.tempSuppressDenaliErr( PCIE_TL_NONFATAL_TLP_MF_vlNC1stBE2 );
383 f_env.Pod.FNXPCIEEnableTrans.tempSuppressDenaliErr( PCIE_TL_NONFATAL_TLP_MF_vlNClastBE2 );
384 }
385
386 if( f_mcSpecified && f_TC ){
387 f_env.Pod.FNXPCIEEnableTrans.tempSuppressDenaliErr( PCIE_TL_NONFATAL_TLP_MF_vlINTxTC );
388 f_env.Pod.FNXPCIEEnableTrans.tempSuppressDenaliErr( PCIE_TL_NONFATAL_TLP_MF_vlPMTC );
389 f_env.Pod.FNXPCIEEnableTrans.tempSuppressDenaliErr( PCIE_TL_NONFATAL_TLP_MF_vlERRTC );
390 }
391
392 if( f_adjustLen ){
393 f_env.Pod.FNXPCIEEnableTrans.tempSuppressDenaliErr( PCIE_TL_NONFATAL_TLP_MF_vlSizeTotal );
394 }
395 //Denali may have an outstanding packet with the same tag because it was an error packet
396 f_env.Pod.FNXPCIEEnableTrans.tempSuppressDenaliErr( PCIE_TL_COR_TLP_USERTAG_2 );
397
398 //Give denali extra credits for Writes with big payloads or adjustments
399 // and remove them after
400 if( ( ingressHdr[PEC_PCI__LEN] > 512 || ingressHdr[PEC_PCI__LEN] == 0) &&
401 ingressHdr[PEC_PCI__FMT_DATA] && (ingressHdr[PEC_PCI__TYPE] == PEC_PCI__TYPE_MEM) ){
402 tempDenaliData[3:0] = PCIE_FCCTRL_get ;
403 tempDenaliData[7:4] = 4'h0 ;
404 tempDenaliData[11:8] = PCIE_VCID_VC0;
405 tempDenaliData[15:12] = PCIE_FCTYPE_PD;
406 tempDenaliData[19:16] = PCIE_FCID_TX_LIMIT;
407 tempDenaliData[31:20] = 12'h0;
408 //Posted Header - Memory Write
409
410 f_env.Pod.FNXPCIEEnableTrans.WriteDenaliReg( PCIE_REG_DEN_FC_CTRL,tempDenaliData );
411 tempDenaliData = f_env.Pod.FNXPCIEEnableTrans.ReadDenaliReg( PCIE_REG_DEN_FC_CTRL );
412 tempDenaliData[31:20] = tempDenaliData[31:20] +
413 (ingressHdr[PEC_PCI__LEN] == 0 ? 12'h400 : ingressHdr[PEC_PCI__LEN] ); //Extra Data credit
414 tempDenaliData[3:0] = PCIE_FCCTRL_set;
415 f_env.Pod.FNXPCIEEnableTrans.WriteDenaliReg( PCIE_REG_DEN_FC_CTRL,tempDenaliData );
416
417 }
418
419 // Just drive the TLP into the TLU.
420 // No need to worry about credits since
421 // the TLU shouldn't eat any unless the
422 // optional check is disabled
423 f_env.drivePCIE( ingressHdr, ingressData, f_adjustLen, *, *,
424 super.f_abortErrTlp );
425
426 f_env.Pod.FNXPCIEEnableTrans.unSuppressDenaliErr( PCIE_TL_COR_TLP_USERTAG_2 );
427 if( f_dwbeSpecified ){
428 f_env.Pod.FNXPCIEEnableTrans.unSuppressDenaliErr( PCIE_TL_NONFATAL_TLP_MF_vlLastBE0 );
429 f_env.Pod.FNXPCIEEnableTrans.unSuppressDenaliErr( PCIE_TL_NONFATAL_TLP_MF_vl1stBE );
430 f_env.Pod.FNXPCIEEnableTrans.unSuppressDenaliErr( PCIE_TL_NONFATAL_TLP_MF_vlLastBE1 );
431 f_env.Pod.FNXPCIEEnableTrans.unSuppressDenaliErr( PCIE_TL_NONFATAL_TLP_MF_vlNC1stBE );
432 f_env.Pod.FNXPCIEEnableTrans.unSuppressDenaliErr( PCIE_TL_NONFATAL_TLP_MF_vlNClastBE );
433 f_env.Pod.FNXPCIEEnableTrans.unSuppressDenaliErr( PCIE_TL_NONFATAL_TLP_MF_vlNC1stBE2 );
434 f_env.Pod.FNXPCIEEnableTrans.unSuppressDenaliErr( PCIE_TL_NONFATAL_TLP_MF_vlNClastBE2 );
435 }
436
437 if( f_mcSpecified && f_TC ){
438 f_env.Pod.FNXPCIEEnableTrans.unSuppressDenaliErr( PCIE_TL_NONFATAL_TLP_MF_vlINTxTC );
439 f_env.Pod.FNXPCIEEnableTrans.unSuppressDenaliErr( PCIE_TL_NONFATAL_TLP_MF_vlPMTC );
440 f_env.Pod.FNXPCIEEnableTrans.unSuppressDenaliErr( PCIE_TL_NONFATAL_TLP_MF_vlERRTC );
441 }
442
443 if( f_cross4K && diagCsr[37] == 1 ||
444 f_dwbeSpecified && diagCsr[36] ){
445 f_env.consumeIngressCredits( ingressHdr );
446 f_env.expectILU( ingressHdr, ingressData );
447 }
448 else{ //Return the credits that Denali thinks it has consumed
449 tempDenaliData[3:0] = PCIE_FCCTRL_get ;
450 tempDenaliData[7:4] = 4'h0 ;
451 tempDenaliData[11:8] = PCIE_VCID_VC0;
452 tempDenaliData[15:12] = PCIE_FCTYPE_PH;
453 tempDenaliData[19:16] = PCIE_FCID_TX_CONSUMED;
454 tempDenaliData[31:20] = 12'h0;
455 //Posted Header - Memory Write or Msg
456 if( (ingressHdr[PEC_PCI__FMT_DATA] && (ingressHdr[PEC_PCI__TYPE] == PEC_PCI__TYPE_MEM))
457 || ingressHdr[124] ){
458
459 f_env.Pod.FNXPCIEEnableTrans.WriteDenaliReg( PCIE_REG_DEN_FC_CTRL,tempDenaliData );
460 tempDenaliData = f_env.Pod.FNXPCIEEnableTrans.ReadDenaliReg( PCIE_REG_DEN_FC_CTRL );
461 tempDenaliData[27:20] = tempDenaliData[27:20] - 1; //Return Header credit
462 tempDenaliData[3:0] = PCIE_FCCTRL_set;
463 f_env.Pod.FNXPCIEEnableTrans.WriteDenaliReg( PCIE_REG_DEN_FC_CTRL,tempDenaliData );
464
465 //Return Data credit
466 if( ingressHdr[PEC_PCI__FMT_DATA] ){
467
468 tempDenaliData[15:12] = PCIE_FCTYPE_PD;
469 tempDenaliData[3:0] = PCIE_FCCTRL_get ;
470 f_env.Pod.FNXPCIEEnableTrans.WriteDenaliReg( PCIE_REG_DEN_FC_CTRL,tempDenaliData );
471 tempDenaliData = f_env.Pod.FNXPCIEEnableTrans.ReadDenaliReg( PCIE_REG_DEN_FC_CTRL);
472 //review - Need to add adjustlen
473 tempDenaliData[31:20] = tempDenaliData[31:20] - (ingressHdr[PEC_PCI__LEN] + 3 ) / 4;
474 tempDenaliData[3:0] = PCIE_FCCTRL_set;
475 f_env.Pod.FNXPCIEEnableTrans.WriteDenaliReg( PCIE_REG_DEN_FC_CTRL,tempDenaliData );
476 }
477 }
478 else{ //Return NonPosted Header credits
479
480 tempDenaliData[15:12] = PCIE_FCTYPE_NPH;
481 f_env.Pod.FNXPCIEEnableTrans.WriteDenaliReg( PCIE_REG_DEN_FC_CTRL,tempDenaliData );
482 tempDenaliData = f_env.Pod.FNXPCIEEnableTrans.ReadDenaliReg( PCIE_REG_DEN_FC_CTRL );
483 tempDenaliData[27:20] = tempDenaliData[27:20] - 1; //Return Header credit
484 tempDenaliData[3:0] = PCIE_FCCTRL_set;
485 f_env.Pod.FNXPCIEEnableTrans.WriteDenaliReg( PCIE_REG_DEN_FC_CTRL,tempDenaliData );
486 }
487 }
488
489 //Put back denali extra credits for Writes with big payloads or adjustments
490 if( (ingressHdr[PEC_PCI__LEN] > 512 || ingressHdr[PEC_PCI__LEN] == 0 ) &&
491 ingressHdr[PEC_PCI__FMT_DATA] && (ingressHdr[PEC_PCI__TYPE] == PEC_PCI__TYPE_MEM) ){
492 tempDenaliData[3:0] = PCIE_FCCTRL_get ;
493 tempDenaliData[7:4] = 4'h0 ;
494 tempDenaliData[11:8] = PCIE_VCID_VC0;
495 tempDenaliData[15:12] = PCIE_FCTYPE_PD;
496 tempDenaliData[19:16] = PCIE_FCID_TX_LIMIT;
497 tempDenaliData[31:20] = 12'h0;
498 //Posted Header - Memory Write
499
500 f_env.Pod.FNXPCIEEnableTrans.WriteDenaliReg( PCIE_REG_DEN_FC_CTRL,tempDenaliData );
501 tempDenaliData = f_env.Pod.FNXPCIEEnableTrans.ReadDenaliReg( PCIE_REG_DEN_FC_CTRL );
502 tempDenaliData[31:20] = tempDenaliData[31:20] -
503 (ingressHdr[PEC_PCI__LEN] == 0 ? 12'h400 : ingressHdr[PEC_PCI__LEN] );
504 tempDenaliData[3:0] = PCIE_FCCTRL_set;
505 f_env.Pod.FNXPCIEEnableTrans.WriteDenaliReg( PCIE_REG_DEN_FC_CTRL,tempDenaliData );
506
507 }
508
509
510
511 f_env.freeDmaTag( ingressTag );
512
513 // Wait for the bad boy(s) to be
514 // processed by the TLU...
515 printf( "MalReq (cycle %0d) Wait for malformed TLP (tag=%h) to enter TLU\n",
516 get_cycle(), ingressTag );
517 f_env.waitIngressLatency( ingressHdr, (f_adjustLen > 0) ? f_adjustLen : 0 );
518
519 // If the context wants, put the bad-boy
520 // header (and the cause) into a mailbox
521 if ( f_errQueue != 0 && f_adjustLen >= 0 )
522 {
523 // Any malformed request
524 // might generate a receiver overflow.
525 mailbox_put( f_errQueue, e_ERR_none );
526 mailbox_put( f_errQueue, 2 );
527 mailbox_put( f_errQueue, e_ERR_ue_mfp );
528 mailbox_put( f_errQueue, ingressHdr );
529 mailbox_put( f_errQueue, e_ERR_ue_rof );
530 mailbox_put( f_errQueue, 128'bx0 );
531 }
532
533 // If the length adjustment was negative
534 // then we can't expect a valid header
535 // in the log register, and we might get
536 // a second 'mfp' error from the TLU.
537 else if ( f_errQueue != 0 && f_adjustLen < 0 )
538 {
539 mailbox_put( f_errQueue, e_ERR_none );
540 mailbox_put( f_errQueue, 3 );
541 mailbox_put( f_errQueue, e_ERR_ue_rof );
542 mailbox_put( f_errQueue, 128'bx0 );
543 mailbox_put( f_errQueue, e_ERR_ue_mfp );
544 mailbox_put( f_errQueue, 128'bx ); // Don't check the logged data
545 mailbox_put( f_errQueue, e_ERR_ue_mfp );
546 mailbox_put( f_errQueue, 128'bx0 ); // Clear all logged-error bits
547 }
548
549 printf( "MalReq (cycle %0d) Done (tag=%h)\n", get_cycle(), ingressTag );
550 } /* end Execute */
551 } /* end MalReqPEUStr */
552