Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / verif / env / ilu_peu / vera / N2fc / N2fcilupeuIngressDmaRdStr.vr
CommitLineData
86530b38
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: N2fcilupeuIngressDmaRdStr.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 ============================================
35extern integer fc_peu_dma_ptr;
36
37class N2fcDmaRdPEUStr extends PEUStrBase {
38
39 local bit [63:0] N2fcSAddr;
40 local bit [63:0] N2fcEAddr;
41 local bit N2fcAddrSpecified;
42 local bit [31:0] length;
43 local bit [31:0] dat;
44
45 integer f_len; // The packet's payload length
46 bit[3:0] f_firstDWBE; // It's "first DWBE" field
47 bit[3:0] f_lastDWBE; // It's "last DWBE" field
48 integer f_bndy; // The address' boundary
49 bit f_lenSpecified; // Was a length specified?
50 bit f_firstSpecified; // Was a "firstDWBE" specified?
51 bit f_lastSpecified; // Was a "lastDWBE" specified?
52 bit f_bndySpecified; // Was an addr bndy specified?
53 bit f_poison; // Is the completion poisoned?
54 bit f_UR; // Is the completion UR?
55 bit f_CA; // Is the completion CA?
56 bit f_INTx; // Do an INTx after completion?
57 bit f_dma_read_lk; // Do a DMA Read Lock
58 bit f_drop_cmpl; // Drop the completion
59 string intx_cmd;
60 N2fcIommuMgr MMU;
61 bit [7:0] bus_id;
62 integer f_tc; // The packet's traffic class
63
64 task new( PEUTestEnv a_env )
65 {
66 super.new( a_env );
67 f_lenSpecified = 0;
68 f_firstSpecified = 0;
69 f_lastSpecified = 0;
70 f_bndySpecified = 0;
71 f_poison = 0;
72 f_UR = 0;
73 f_CA = 0;
74 f_INTx = 0;
75 f_dma_read_lk = 0;
76 f_drop_cmpl = 0;
77 f_tc = -1;
78 MMU = new();
79
80 printf ("%0d- N2fcDmaRdPEUStr:new first random # = %0h\n", get_time(LO), random() );
81 }
82
83 task SetLen( integer a_len )
84 {
85 f_len = a_len;
86 f_lenSpecified = 1;
87 }
88
89 task SetFirstDWBE( bit[3:0] a_dwbe )
90 {
91 f_firstDWBE = a_dwbe;
92 f_firstSpecified = 1;
93 }
94
95 task SetLastDWBE( bit[3:0] a_dwbe )
96 {
97 f_lastDWBE = a_dwbe;
98 f_lastSpecified = 1;
99 }
100
101 task SetAddrBndy( integer a_bndy )
102 {
103 f_bndy = a_bndy;
104 f_bndySpecified = 1;
105 }
106
107 task SetPoisonedPayload()
108 {
109 f_poison = 1;
110 }
111
112 task SetUC( bit isUR )
113 {
114 if ( isUR )
115 f_UR = 1;
116 else
117 f_CA = 1;
118 }
119
120 task DoIntxAfterCompletion(string cmd)
121 {
122 f_INTx = 1;
123 intx_cmd = cmd;
124 }
125
126 task SetRdLk()
127 {
128 f_dma_read_lk = 1;
129 }
130
131 task DropCmpl()
132 {
133 f_drop_cmpl = 1;
134 }
135
136
137 task N2fcSetAddr( bit [63:0] i_saddr, bit [63:0] i_eaddr )
138 {
139 N2fcAddrSpecified = 1;
140 N2fcSAddr = i_saddr;
141 N2fcEAddr = i_eaddr;
142 }
143
144
145 task Execute()
146 {
147 bit [63:0] address = 64'b0; // Virtual address
148 bit [39:0] pa = 40'b0; // Physical address
149 bit hdr_4dw;
150
151 bit[PEC_PCI__HDR] ingressHdr; // The ingress TLP's header
152 integer ingressData; // A payload descriptor
153 bit[7:0] ingressTag; // The tag for the TLP
154 bit[7:0] egressAddr; // The payload's DOU address
155 integer dwTotal; // #DWs required for completion
156 integer dwDone; // #DWs completed so far
157 bit zero_len_read;
158
159 shadow bit[PEC_PCI__HDR] egressHdr; // The egress TLP's header
160 shadow integer egressData; // The completion payload
161 shadow integer dma_ptr; // dma id
162
163 if (N2fcAddrSpecified == 1) {
164 address = N2fcSAddr;
165 }
166 else {
167 error ("N2fcDmaRdPEUStr::Execute() : the start and end address must be specifed\n");
168 }
169
170 // First, get in line for a DMA tag...
171 f_env.allocDmaTag( ingressTag );
172
173 // Then build a TLP
174 if ( f_lenSpecified )
175 f_env.genIngressRdReq( ingressTag, ingressHdr, ingressData, f_len );
176 else
177 error ("N2fcDmaRdPEUStr::Execute() : the length must be specifed\n");
178
179 // Special case for DMA RD LK
180 if ( f_dma_read_lk ) {
181 ingressHdr[PEC_PCI__TYPE] = PEC_PCI__TYPE_MEM_LK;
182 ingressHdr[PEC_PCI__TC] = 0;
183
184 f_env.Pod.FNXPCIEEnableTrans.tempSuppressDenaliErr( PCIE_TL_NONFATAL_TLP_MF_vlLkReq );
185 f_env.Pod.FNXPCIEEnableTrans.tempSuppressDenaliErr( PCIE_TL_NONFATAL_TLP_MF_vlLkEP );
186 f_env.Pod.FNXPCIEEnableTrans.tempSuppressDenaliErr( PCIE_TL_NONFATAL_TLP_CPLST_LKUR_2 );
187 }
188
189 // set the Traffic Class (for non - DMA RD LK)
190 else if( f_tc != -1 ) {
191 ingressHdr[PEC_PCI__TC] = f_tc;
192 }
193
194 if( address[63:32] != 32'h00000000 ) {
195 ingressHdr[PEC_PCI__FMT_4DW] = 1; // 4DW hdr fmt, 64-bit address
196 ingressHdr[PEC_PCI__ADDR] = address;
197 }
198 else {
199 ingressHdr[PEC_PCI__FMT_4DW] = 0; // 3DW hdr fmt, 32-bit address
200 ingressHdr[PEC_PCI__ADDR32] = address[31:0];
201 }
202
203 printf ("%0d- UDEBUG N2fcDmaRdPEUStr:Execute Address = %0h Byp = %0h, Len = 'd%0d\n",
204 get_time(LO), address, address[63:39], f_len);
205
206 // ...and set fields as requested
207 // by the caller.
208
209 if ( f_bndySpecified )
210 f_env.setAddrBndy( ingressHdr, f_bndy, 4 );
211
212 //N2 Set the DWBE after setAddrBndy since it adjusts the DWBE now
213 if ( f_firstSpecified )
214 ingressHdr[PEC_PCI__FIRST_DWBE] = f_firstDWBE;
215 if ( f_lastSpecified )
216 ingressHdr[PEC_PCI__LAST_DWBE] = f_lastDWBE;
217
218 // Send the read-request through the
219 // ingress pipeline.
220 f_env.drivePCIE( ingressHdr, ingressData,*,*,*,*,*,1 );
221
222
223 zero_len_read = (ingressHdr[PEC_PCI__LEN] == 1) &&
224 (ingressHdr[PEC_PCI__FIRST_DWBE] == 0) &&
225 (ingressHdr[PEC_PCI__LAST_DWBE] == 0) ;
226 bus_id = ingressHdr[ILUPEU_TLP_HDR_REQ_BUS_NUM_BITS];
227
228 fork {
229
230 f_env.MMU.get_mmu_cntl_reg();
231 if (!MMU.get_physical_address(address, pa, bus_id, 1)) {
232 f_CA = 1;
233 }
234
235 // get the l2sio_stub lock, to serialize new requests
236 semaphore_get (WAIT, l2sio_stub.reqst_semph_id, 1);
237
238 // Now send a completion to our original request through the
239 // egress pipeline.
240 if ( f_drop_cmpl )
241 {
242 // no completion was requested, probably due to
243 // error injection. However, the siu<->l2 monitor needs to
244 // know to expect the RDD and rd return packets.
245 dma_ptr = fc_peu_dma_ptr++;
246 // l2sio_stub.l2_cl_idx = l2sio_stub.l2_cl_idx + 1;
247 fork
248 l2sio_stub.reassemble_dma_pkt("N2fcDmaRdPEUStr::Execute",
249 ingressHdr[PEC_PCI__LEN],
250 address,
251 dma_ptr);
252 join none
253 repeat (1) @(posedge CLOCK);
254 }
255 else if ( f_UR || f_CA )
256 {
257 printf ("UDEBUG : N2fcDmaRdPEUStr UR or CA\n");
258 f_env.genEgressCpl( ingressHdr, egressHdr, egressData );
259 egressHdr[PEC_PCI__FMT_DATA] = 0;
260 egressHdr[PEC_PCI__LEN] = 0;
261 egressHdr[PEC_PCI__CPL_ID] = 0;
262 if ( f_UR )
263 egressHdr[PEC_PCI__CPL_STATUS] = PEC_PCI__CPL_STATUS_UR;
264 else {
265 egressHdr[PEC_PCI__CPL_STATUS] = PEC_PCI__CPL_STATUS_CA;
266 f_env.Pod.FNXPCIEEnableTrans.tempSuppressDenaliErr( PCIE_TL_NONFATAL_TLP_CPLST_CA_2 );
267 }
268 fork
269 f_env.expectPCIE( egressHdr, egressData, *, 1 );
270 join none
271 repeat (1) @(posedge CLOCK);
272 }
273 else if ( ingressHdr[PEC_PCI__LEN] > 0 &&
274 4*ingressHdr[PEC_PCI__LEN] <= f_env.getMaxPayloadSize() ||
275 f_dma_read_lk)
276 {
277 f_env.genEgressCpl( ingressHdr, egressHdr, egressData );
278 if ( f_poison ) {
279 f_env.poisonPayload( egressData );
280 egressHdr[PEC_PCI__EP] = 1;
281 f_env.Pod.FNXPCIEEnableTrans.tempSuppressDenaliErr( PCIE_TL_NONFATAL_TLP_CPL_Poison );
282 }
283 else if ( f_dma_read_lk ) {
284 egressHdr[PEC_PCI__TYPE] = PEC_PCI__TYPE_CPL_LK;
285 egressHdr[PEC_PCI__FMT ] = PEC_PCI__FMT_NO_DATA_3DW;
286 egressHdr[PEC_PCI__LEN] = 0;
287 egressHdr[PEC_PCI__CPL_STATUS] = PEC_PCI__CPL_STATUS_UR;
288 egressHdr[PEC_PCI__BYTECOUNT] = 12'hxxx; //ingressHdr[PEC_PCI__LEN] * 4;
289 egressHdr[PEC_PCI__LOWADDR] = 7'hxx;
290 }
291 egressHdr [PEC_PCI__CPL_ID] = 0;
292
293 dma_ptr = fc_peu_dma_ptr++;
294 fork
295 f_env.expectPCIE( egressHdr, egressData, *, 1 , dma_ptr);
296 join none
297 repeat (1) @(posedge CLOCK);
298 }
299 // ...or as many as it takes for a
300 // complex ('bulk') request.
301 else
302 {
303 dwTotal = ingressHdr[PEC_PCI__LEN];
304 if ( dwTotal == 0 ) dwTotal = 1024;
305 dwDone = 0;
306 while( dwTotal > dwDone )
307 {
308 f_env.genEgressPartialCpl( ingressHdr, egressHdr, egressData, dwDone );
309 dwDone = dwDone + egressHdr[PEC_PCI__LEN];
310 if ( f_poison ) {
311 f_env.poisonPayload( egressData );
312 egressHdr[PEC_PCI__EP] = 1;
313 f_env.Pod.FNXPCIEEnableTrans.tempSuppressDenaliErr( PCIE_TL_NONFATAL_TLP_CPL_Poison );
314 }
315
316 egressHdr [PEC_PCI__CPL_ID] = 0;
317
318 dma_ptr = fc_peu_dma_ptr++;
319 fork
320 f_env.expectPCIE( egressHdr, egressData, *, 1, dma_ptr );
321 join none
322 @(posedge CLOCK);
323 }
324 }
325
326 if ( f_poison ) {
327 f_env.Pod.FNXPCIEEnableTrans.unSuppressDenaliErr( PCIE_TL_NONFATAL_TLP_CPL_Poison );
328 }
329 if ( f_CA ) {
330 f_env.Pod.FNXPCIEEnableTrans.unSuppressDenaliErr( PCIE_TL_NONFATAL_TLP_CPLST_CA_2 );
331 }
332 // The environment frees the completion's DOU space
333 // So we only have to free the tag.
334 f_env.freeDmaTag( ingressTag );
335
336 // release the l2sio_stub lock
337 semaphore_put (l2sio_stub.reqst_semph_id, 1);
338
339 // Does the cpu want an interrupt when the DMARD is done?
340 if (f_INTx) {
341 N2fcIntxStr intxStr;
342
343 // wait for read completion
344 wait_child();
345
346 // now do an INTx ASSERT command to let the cpu know the dmard is completed
347 intxStr = new(f_env, intx_cmd, "ASSERT");
348 }
349
350 } join none
351
352 } /* end Execute */
353
354} /* end DmaRdPECStr class*/