Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / verif / env / fc / vera / stubs / fc_l2_sio_stub.vr
CommitLineData
86530b38
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: fc_l2_sio_stub.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 <vera_defines.vrh>
36#include <VeraListProgram.vrh>
37#include <ListMacros.vrh>
38#include <fc_top.if.vrh>
39#include "std_display_class.vrh"
40#include "ios_l2_stub.if.vrh"
41#include "ios_l2_stub_ports_binds.vrh"
42
43// the following is needed by the std_display_defines.vri
44#define STD_DISP dbg
45
46// call to check memory with Riesling
47#ifndef GATESIM
48extern hdl_task mem_check ( bit [39:0] pa,
49 bit [(64*8)-1:0] data
50 );
51#endif
52extern integer fc_peu_dma_cnt;
53
54class fc_peu_dma_mem {
55 bit [31:0] data;
56 bit [39:0] address;
57 bit [4:0] d_ptr;
58 bit [8:0] pkt_tag;
59 integer dma_ptr;
60 bit [3:0] cl_ptr;
61 integer dma_dw_idx;
62 string name = "fc_peu_dma_mem";
63
64 task new (bit [31:0] data, bit [39:0] address, bit [4:0] d_ptr,
65 bit [8:0] pkt_tag, StandardDisplay dbg, integer dma_ptr,
66 bit [3:0] cl_ptr, integer dma_dw_idx)
67 {
68 this.data = data;
69 this.address = address;
70 this.d_ptr = d_ptr;
71 this.pkt_tag = pkt_tag;
72 this.dma_ptr = dma_ptr;
73 this.cl_ptr = cl_ptr;
74 this.dma_dw_idx = dma_dw_idx;
75
76 PR_INFO(name, MON_INFO, psprintf ("new() Addr %h data %h d_ptr %0h, pkt_tag %h, dma_ptr %0d, cl_ptr %0d, dma_dw_idx %0d",
77 address, data, d_ptr, pkt_tag, dma_ptr, cl_ptr, dma_dw_idx ));
78 }
79
80 task dis_info (StandardDisplay dbg)
81 {
82 PR_INFO(name, MON_INFO, psprintf ("dis_info() Addr %h data %h d_ptr %0h, pkt_tag %h, dma_ptr %0d, cl_ptr %0d, dma_dw_idx %0d",
83 address, data, d_ptr, pkt_tag, dma_ptr, cl_ptr, dma_dw_idx ));
84 }
85}
86
87MakeVeraList(fc_peu_dma_mem);
88
89
90class fc_l2_sio_stub {
91 bit [511:0] rtn_l2_cl[]; // contains data of cache line, index with l2_cl_idx
92 bit [39:0] req_cl_add[]; // contains address of cache line, index with l2_cl_idx
93 bit [8:0] rtn_pkt_tag[]; // contain packet cl_sts and pkt_tag of dmc_tag[8] for cl_sts, bit [4:0] for pkt_tag.
94 bit [8:0] req_pkt_tag[]; // contain packet cl_sts and pkt_tag of dmc_tag[8] for cl_sts, bit [4:0] for pkt_tag.
95 bit [4:0] l2_cl_idx =0;
96
97
98//#ifndef GATESIM
99
100 integer data_semph_id;
101 integer reqst_semph_id;
102 integer cl_idx_region_id;
103
104 VeraList_fc_peu_dma_mem dma_mem_list[];
105 string name = "fc_l2_sio_stub";
106
107 StandardDisplay dbg;
108
109 task new (StandardDisplay dbg );
110 task l2_sio_intf (string myname,
111 fc_l2_sio_port l2port,
112 fc_l2_sio_port_fcerr Fcerr_port);
113
114/* task l2_sio_intf_fcerr (string myname,
115 fc_l2_sio_port_fcerr l2port);*/
116
117
118
119 task l2_sii_intf (string myname,
120 l2_stub_port l2port );
121 task reassemble_dma_pkt (string myname,
122 integer length,
123 bit [63:0] address,
124 integer dma_ptr );
125 task read_mem (string myname,
126 bit [63:0] address,
127 var bit [31:0] data,
128 integer dma_ptr );
129 task save_data_to_list (string myname,
130 bit [511:0] data,
131 bit [8:0] pkt_tag,
132 bit [4:0] d_ptr );
133 task save_add_to_list (string myname,
134 bit [39:0] add,
135 bit [8:0] pkt_tag,
136 bit [4:0] d_ptr );
137 task free_data_semaphore (string myname,
138 integer dma_ptr );
139 task wait_for_dma_rdd (bit [4:0] l2_cl_idx,
140 integer dma_ptr );
141 task wait_for_l2_rdd_resp (bit [4:0] l2_cl_idx,
142 integer dma_ptr );
143 task get_a_cache_line (bit [39:0] address,
144 integer index,
145 bit [ 4:0] cl_idx,
146 integer dma_ptr );
147
148 function bit [63:0] hashpa (bit [63:0] pa) {
149 if (probe_if.hashing && ~pa[39])
150 hashpa = {pa[63:18], pa[32:28] ^ pa[17:13], pa[19:18] ^ pa[12:11], pa[10:0]};
151 else
152 hashpa = pa;
153 }
154}
155
156
157////////////////////////////////////////////////////////////////////////////////
158// new()
159// Allocates the data_semph_id semaphore and starts up the monitoring of
160// SIU -> L2 and L2 -> SIU traffic.
161////////////////////////////////////////////////////////////////////////////////
162task fc_l2_sio_stub :: new (StandardDisplay dbg){
163 data_semph_id = alloc(SEMAPHORE, 0, 1,1);
164 reqst_semph_id = alloc(SEMAPHORE, 0, 1,1);
165 cl_idx_region_id = alloc(REGION, 0, 32);
166 this.dbg = dbg;
167 fork
168 l2_sio_intf ("BANK0", fc_l2_sio_bind0,fc_l2_sio_fc_err_bind0);
169 l2_sio_intf ("BANK1", fc_l2_sio_bind1,fc_l2_sio_fc_err_bind1);
170 l2_sio_intf ("BANK2", fc_l2_sio_bind2,fc_l2_sio_fc_err_bind2);
171 l2_sio_intf ("BANK3", fc_l2_sio_bind3,fc_l2_sio_fc_err_bind3);
172 l2_sio_intf ("BANK4", fc_l2_sio_bind4,fc_l2_sio_fc_err_bind4);
173 l2_sio_intf ("BANK5", fc_l2_sio_bind5,fc_l2_sio_fc_err_bind5);
174 l2_sio_intf ("BANK6", fc_l2_sio_bind6,fc_l2_sio_fc_err_bind6);
175 l2_sio_intf ("BANK7", fc_l2_sio_bind7,fc_l2_sio_fc_err_bind7);
176
177 l2_sii_intf ("BANK0", l2_stub_bind0);
178 l2_sii_intf ("BANK1", l2_stub_bind1);
179 l2_sii_intf ("BANK2", l2_stub_bind2);
180 l2_sii_intf ("BANK3", l2_stub_bind3);
181 l2_sii_intf ("BANK4", l2_stub_bind4);
182 l2_sii_intf ("BANK5", l2_stub_bind5);
183 l2_sii_intf ("BANK6", l2_stub_bind6);
184 l2_sii_intf ("BANK7", l2_stub_bind7);
185 join none
186}
187
188
189////////////////////////////////////////////////////////////////////////////////
190// read_mem()
191//
192//
193////////////////////////////////////////////////////////////////////////////////
194task fc_l2_sio_stub :: read_mem(string myname,
195 bit [63:0] address,
196 var bit [31:0] data,
197 integer dma_ptr)
198{
199 fc_peu_dma_mem dma_mem;
200
201 if (dma_mem_list[dma_ptr].empty()){
202 PR_ERROR(name, MON_ERR, psprintf ("%s read_mem() dma_mem_list[%0d] is empty\n", myname, dma_ptr));
203 }
204 dma_mem = dma_mem_list[dma_ptr].front();
205 dma_mem_list[dma_ptr].pop_front();
206 dma_mem.dis_info(dbg);
207 data = dma_mem.data;
208
209 if (address !== dma_mem.address){
210 PR_ERROR(name, MON_ERR, psprintf ("%s read_mem() Address mismatch! request addr %h, Addr in model %h, dma_ptr %0d\n",
211 myname, address, dma_mem.address, dma_ptr));
212 }
213 else {
214 PR_INFO(name, MON_INFO, psprintf ("%s read_mem() addr %h, data %h, dma_ptr %0d", myname, address, data, dma_ptr));
215 }
216}
217
218
219////////////////////////////////////////////////////////////////////////////////
220// reassemble_dma_pkt()
221//
222//
223////////////////////////////////////////////////////////////////////////////////
224task fc_l2_sio_stub :: reassemble_dma_pkt (string myname,
225 integer length, // in DWs
226 bit [63:0] addr,
227 integer dma_ptr) // unique ID for each dma rd
228{
229 integer index = 0;
230 bit [ 39:0] address = addr[39:0];
231
232 PR_INFO(name, MON_INFO, psprintf ("reassemble_dma_pkt() Wait for semaphore token. addr %h length %0d dma_ptr %0d", addr, length, dma_ptr ));
233
234 semaphore_get (WAIT, data_semph_id, 1);
235 dma_mem_list[dma_ptr] = new;
236
237 while ( address < (addr[39:0] + length*4 - 1) ){
238 fork {
239 get_a_cache_line(address, index, l2_cl_idx, dma_ptr);
240 }
241 join none
242
243 @(posedge fc_l2b0_sio.clk);
244 address = {address[39:6],6'b0} + 64;
245 index = index+16;
246 l2_cl_idx++;
247 } // while
248
249 semaphore_put (data_semph_id, 1);
250 PR_INFO(name, MON_INFO, psprintf ("reassemble_dma_pkt() semaphore token is put back, dma_ptr %0d", dma_ptr));
251
252 wait_child(); // wait for all the cachelines to be requested & returned
253
254 PR_NORMAL(name, MON_NORMAL, psprintf ("reassemble_dma_pkt() all cachelines read, dma_ptr %0d", dma_ptr));
255}
256
257
258////////////////////////////////////////////////////////////////////////////////
259// get_a_cache_line()
260//
261//
262////////////////////////////////////////////////////////////////////////////////
263task fc_l2_sio_stub :: get_a_cache_line ( bit [39:0] address,
264 integer index,
265 bit [ 4:0] cl_idx,
266 integer dma_ptr)
267{
268 bit [ 4:0] cl_ptr = 0;
269 bit [511:0] tmp_rtn_l2_cl;
270 bit [ 31:0] tmp_data;
271 bit [ 8:0] tmp_req_pkt_tag;
272 bit [ 8:0] tmp_rtn_pkt_tag;
273 bit [ 39:0] tmp_req_cl_add;
274 bit [ 39:0] tmp_hashpa;
275 bit tmp_bit;
276 fc_peu_dma_mem dma_mem;
277
278 region_enter(WAIT, cl_idx_region_id, cl_idx);
279
280 wait_for_dma_rdd(cl_idx, dma_ptr);
281
282 tmp_req_cl_add = req_cl_add[cl_idx];
283 tmp_req_pkt_tag = req_pkt_tag[cl_idx];
284 tmp_bit = assoc_index (DELETE, req_cl_add, cl_idx);
285 tmp_bit = assoc_index (DELETE, req_pkt_tag, cl_idx);
286
287 region_exit(cl_idx_region_id, cl_idx);
288
289 tmp_hashpa = hashpa(address);
290 if (tmp_req_cl_add[39:6] !== tmp_hashpa[39:6]) {
291 PR_ERROR(name, MON_ERR, psprintf ("get_a_cache_line() SII REQ ADD %h does not belong to DMA! add %h, cl_idx %0d, dma_ptr %0d index %0d \n", tmp_req_cl_add, address, cl_idx, dma_ptr, index));
292 }
293
294 wait_for_l2_rdd_resp(cl_idx, dma_ptr);
295
296 tmp_rtn_l2_cl = rtn_l2_cl[cl_idx];
297 tmp_rtn_pkt_tag = rtn_pkt_tag[cl_idx];
298
299 tmp_bit = assoc_index (DELETE, rtn_l2_cl,cl_idx);
300 tmp_bit = assoc_index (DELETE, rtn_pkt_tag,cl_idx);
301
302 if (tmp_req_pkt_tag !== tmp_rtn_pkt_tag){
303 PR_ERROR(name, MON_ERR, psprintf ("get_a_cache_line() REQ and RES dmc_tag mismatch! rtn_pkt_tag %h, req_pkt_tag %0h, cl_idx %0d, dma_ptr %0d\n", tmp_rtn_pkt_tag, tmp_req_pkt_tag, cl_idx, dma_ptr));
304 }
305
306 PR_INFO(name, MON_INFO, psprintf ("get_a_cache_line() Data is read from buff: rtn_l2_cl[%0d] %h , cl_ptr %0d, address %h, index %0d, dma_ptr %0d", cl_idx, tmp_rtn_l2_cl, cl_ptr, address, index, dma_ptr));
307
308#ifndef GATESIM
309 // call Riesling command here
310 mem_check( {address[39:6], 6'b0}, tmp_rtn_l2_cl);
311#endif
312
313 // because cache lines can come back out of order, make sure they
314 // are inserted into the list in the correct order.
315 if (dma_mem_list[dma_ptr].empty()) {
316 for(cl_ptr = address[5:2]; cl_ptr < 16; cl_ptr++) {
317 tmp_data = tmp_rtn_l2_cl[511- 32 * cl_ptr : 512 - 32 * (cl_ptr +1)];
318 dma_mem = new (tmp_data, address, cl_idx, tmp_rtn_pkt_tag, dbg, dma_ptr, cl_ptr, index);
319 dma_mem_list[dma_ptr].push_back(dma_mem);
320
321 PR_INFO(name, MON_INFO, psprintf ("get_a_cache_line() Save data1: Address %h d_ptr %0d data %h, dma_ptr %0d", address, cl_ptr, tmp_data, dma_ptr));
322
323 address = address + 4;
324 index++;
325 }
326 }
327 else {
328 VeraListIterator_fc_peu_dma_mem dma_mem_iter;
329
330 // look thru the list until we reach the end or an element
331 // with an address greater than what we want to insert
332 dma_mem_iter = dma_mem_list[dma_ptr].start();
333 dma_mem = dma_mem_iter.data();
334 while( !dma_mem_iter.eq(dma_mem_list[dma_ptr].finish()) && (dma_mem.address < address) ) {
335 dma_mem_iter.next();
336 dma_mem = dma_mem_iter.data();
337 }
338
339 for(cl_ptr = address[5:2]; cl_ptr < 16; cl_ptr++) {
340 tmp_data = tmp_rtn_l2_cl[511- 32 * cl_ptr : 512 - 32 * (cl_ptr +1)];
341 dma_mem = new (tmp_data, address, cl_idx, tmp_rtn_pkt_tag, dbg, dma_ptr, cl_ptr, index);
342 dma_mem_list[dma_ptr].insert(dma_mem_iter, dma_mem); // inserts before the element pointed to
343
344 PR_INFO(name, MON_INFO, psprintf ("get_a_cache_line() Save data2: Address %h d_ptr %0d data %h, dma_ptr %0d", address, cl_ptr, tmp_data, dma_ptr));
345
346 address = address + 4;
347 index++;
348 }
349 }
350}
351
352
353////////////////////////////////////////////////////////////////////////////////
354// wait_for_dma_rdd()
355//
356//
357////////////////////////////////////////////////////////////////////////////////
358task fc_l2_sio_stub :: wait_for_dma_rdd (bit [4:0] cl_idx,
359 integer dma_ptr)
360{
361 bit [31:0] timeout = 0;
362
363 PR_INFO(name, MON_INFO, psprintf ("wait_for_dma_rdd() Waiting for SII DMA REQ , cl_idx %0d, dma_ptr %0d", cl_idx, dma_ptr));
364 while (!assoc_index(CHECK, req_cl_add, cl_idx)){
365 @(posedge fc_l2b0_sio.clk);
366
367 if (timeout > 32'h000fffff){
368 dbg.dispmon(name, MON_ERR, psprintf ("wait_for_dma_rdd() TIMEOUT for waiting DMA REQ from SII, dma_ptr %0d \n", cl_idx, dma_ptr));
369 }
370
371 timeout++;
372 }
373 PR_INFO(name, MON_INFO, psprintf ("wait_for_dma_rdd() Waiting for SII DMA REQ done!, cl_idx %0d, dma_ptr %0d", cl_idx, dma_ptr));
374}
375
376
377
378////////////////////////////////////////////////////////////////////////////////
379// wait_for_l2_rdd_resp()
380//
381//
382////////////////////////////////////////////////////////////////////////////////
383task fc_l2_sio_stub :: wait_for_l2_rdd_resp (bit [4:0] cl_idx,
384 integer dma_ptr)
385{
386 bit [31:0] timeout = 0;
387
388 PR_INFO(name, MON_INFO, psprintf ("wait_for_l2_rdd_resp() Waiting for rtn_l2_cl[%0d], dma_ptr %0d", cl_idx, dma_ptr ));
389 timeout = 0;
390 while (!assoc_index(CHECK, rtn_l2_cl, cl_idx))
391 {
392 @(posedge fc_l2b0_sio.clk);
393 if (timeout > 32'h000fffff){
394 PR_ERROR(name, MON_ERR, psprintf ("wait_for_l2_rdd_resp() TIMEOUT for waiting rtn_l2_cl[%0d] addr %h dma_ptr %0d , index %0d, dma_ptr %0d\n", cl_idx, dma_ptr));
395 }
396 timeout++;
397 }
398 PR_INFO(name, MON_INFO, psprintf ("wait_for_l2_rdd_resp() Waiting for rtn_l2_cl[%0d] done, dma_ptr %0d", cl_idx, dma_ptr ));
399}
400
401
402
403////////////////////////////////////////////////////////////////////////////////
404// save_data_to_list()
405//
406//
407////////////////////////////////////////////////////////////////////////////////
408task fc_l2_sio_stub :: save_data_to_list (string myname,
409 bit [511:0] data,
410 bit [8:0] pkt_tag,
411 bit [4:0] d_ptr)
412{
413 bit [31:0] timeout = 0;
414
415 PR_INFO(name, MON_INFO, psprintf ("%s save_data_to_list() Waiting for rtn_l2_cl[%0d] free starting ", myname, d_ptr));
416
417 while (assoc_index(CHECK, rtn_l2_cl, d_ptr))
418 {
419 @(posedge fc_l2b0_sio.clk);
420 if (timeout > 32'h00000fff){
421 PR_ERROR(name, MON_ERR, psprintf ("%s save_data_to_list() TIMEOUT for waiting rtn_l2_cl[%0d] free \n", myname, d_ptr));
422 }
423 timeout++;
424 }
425 PR_INFO(name, MON_INFO, psprintf ("%s save_data_to_list() Waiting for rtn_l2_cl[%0d] free done ", myname, d_ptr ));
426 rtn_l2_cl[d_ptr] = data;
427 rtn_pkt_tag[d_ptr] = pkt_tag;
428
429 PR_INFO(name, MON_INFO, psprintf ("%s save_data_to_list() Save data to rtn_l2_cl %0h, d_ptr %0d rtn_pkt_tag %h", myname, data, d_ptr, pkt_tag));
430}
431
432
433////////////////////////////////////////////////////////////////////////////////
434// l2_sio_intf()
435// This is forked by new(), and runs forever. It monitors the L2 -> SIU i/f
436// for dma read returns, and captures the data and tag coming back from the L2.
437//
438// This used to monitor inside the SIU, but this caused problems with the
439// mem_check call for Riesling to compare the data coming out of the cache with
440// its memory model. So now the data is captured inside the l2b just before
441// it gets sent to SIU.
442////////////////////////////////////////////////////////////////////////////////
443task fc_l2_sio_stub :: l2_sio_intf (string myname,
444 fc_l2_sio_port l2port,
445 fc_l2_sio_port_fcerr Fcerr_port)
446{
447 bit [511:0] tmp_rtn_l2_cl;
448 bit [ 8:0] tmp_pkt_tag;
449 bit [ 4:0] d_ptr =0 ;
450 bit siu_mon_l2err = 0;
451 if (get_plus_arg(CHECK,"siu_mon_l2err")){
452 PR_INFO(name, MON_INFO, psprintf("SIU MON For FC err Diags.\n"));
453 siu_mon_l2err = 1;
454 }
455
456if(!siu_mon_l2err) {
457
458
459#ifndef GATESIM
460 integer data_idx;
461
462 while (1){
463 @(posedge l2port.$clk);
464
465 if (l2port.$ctag_vld) {
466
467 // collect ctag info
468 if ((l2port.$ctag[23:16] == 8'b10010001) && ~l2port.$ctag[15]) {
469 d_ptr = l2port.$ctag[10:6];
470 tmp_pkt_tag = {l2port.$ctag[0], 3'h0, l2port.$ctag[5:1]};
471 PR_INFO(name, MON_INFO, psprintf ("%s l2_sio_intf() ctag valid : d_ptr %0d rtn_pkt_tag %h", myname, d_ptr, tmp_pkt_tag));
472
473 @(posedge l2port.$clk); // wait a cycle for data valid
474
475 // collect data (seperate from ecc bits) if it gets written
476 tmp_rtn_l2_cl = 0;
477
478 if (l2port.$data_vld) {
479 for (data_idx=0; data_idx < 16; data_idx++) {
480 tmp_rtn_l2_cl[ 512-32*data_idx-1 : 512 - 32*(data_idx+1) ] =
481 l2port.$data[624-39*data_idx-1 : 624 - 39*(data_idx+1) + 7];
482 }
483 }
484 PR_INFO(name, MON_INFO, psprintf ("%s l2_sio_intf calling save_data_to_list() data %0h idx %0d", myname, l2port.$data, data_idx));
485
486 fork
487 save_data_to_list (myname, tmp_rtn_l2_cl, tmp_pkt_tag, d_ptr);
488 join none
489 }
490 }
491 }
492#else
493///// This is the old routine /////
494///// Fu: used by non-riseling sim (Gate sim) /////
495 bit [ 3:0] data_idx = 0;
496 bit collect_data_flag =0;
497
498 while (1){
499 @(posedge l2port.$clk);
500 if (collect_data_flag){
501 tmp_rtn_l2_cl[512-32*data_idx-1 : 512 - 32* (data_idx+1)] = l2port.$data;
502 PR_INFO(name, MON_INFO, psprintf ("%s l2_sio_intf calling save_data_to_list() data %0h idx %0d", myname, l2port.$data, data_idx));
503 if (data_idx == 15){
504 collect_data_flag = 0;
505
506 fork
507 save_data_to_list (myname, tmp_rtn_l2_cl, tmp_pkt_tag, d_ptr);
508 join none
509
510 }
511 data_idx++;
512 }
513 if (l2port.$ctag_vld && (l2port.$data[23:16] == 8'b10010001) && ~l2port.$data[15]){
514 d_ptr = l2port.$data[10:6];
515 collect_data_flag = 1;
516 tmp_pkt_tag = {l2port.$data[0], 3'h0, l2port.$data[5:1]};
517 PR_INFO(name, MON_INFO, psprintf ("%s save_data_to_list() ctag valid : d_ptr %0d rtn_pkt_tag %h", myname, d_ptr, tmp_pkt_tag));
518 }
519 }
520#endif
521}
522else {
523///// This is the old routine /////
524///// AK: used by Fc RAS Diags /////
525 bit [ 3:0] data_idx = 0;
526 bit collect_data_flag =0;
527
528 while (1){
529 @(posedge Fcerr_port.$clk);
530 if (collect_data_flag){
531 tmp_rtn_l2_cl[512-32*data_idx-1 : 512 - 32* (data_idx+1)] = Fcerr_port.$data;
532 PR_INFO(name, MON_INFO, psprintf ("%s l2_sio_intf calling save_data_to_list() data %0h idx %0d", myname, Fcerr_port.$data, data_idx));
533 if (data_idx == 15){
534 collect_data_flag = 0;
535
536 fork
537 save_data_to_list (myname, tmp_rtn_l2_cl, tmp_pkt_tag, d_ptr);
538 join none
539
540 }
541 data_idx++;
542 }
543 if (Fcerr_port.$ctag_vld && (Fcerr_port.$data[23:16] == 8'b10010001) && ~Fcerr_port.$data[15]){
544 d_ptr = Fcerr_port.$data[10:6];
545 collect_data_flag = 1;
546 tmp_pkt_tag = {Fcerr_port.$data[0], 3'h0, Fcerr_port.$data[5:1]};
547 PR_INFO(name, MON_INFO, psprintf ("%s save_data_to_list() ctag valid : d_ptr %0d rtn_pkt_tag %h", myname, d_ptr, tmp_pkt_tag));
548 }
549 }
550
551}
552}
553
554////////////////////////////////////////////////////////////////////////////////
555// l2_sii_intf()
556// This is forked by new(), and runs forever. It monitors the SIU -> L2 i/f
557// and captures the address and tag of the request going to the L2.
558////////////////////////////////////////////////////////////////////////////////
559task fc_l2_sio_stub :: l2_sii_intf (string myname, l2_stub_port l2port)
560{
561 bit [39:0] address=0;
562 bit [ 4:0] d_ptr =0 ;
563 bit collect_data_flag =0;
564 bit [ 8:0] cl_pkt_tag =0;
565
566 while (1){
567 @(posedge l2port.$clk);
568 if (collect_data_flag){
569 collect_data_flag = 0;
570 address[31:0] = l2port.$req;
571
572 PR_INFO(name, MON_INFO, psprintf ("%s l2_sii_intf() addr %h d_ptr %0d cl_pkt_tag %h", myname, address, d_ptr, cl_pkt_tag));
573
574 fork
575 save_add_to_list (myname, address, cl_pkt_tag, d_ptr);
576 join none
577 }
578
579 // bits [23:8] are the tag from dmc, [7:0] are upper 8 bits of addr
580 if (l2port.$req_vld && l2port.$req[31:24] == 8'b01001001){
581 if (l2port.$req[23:23] == 1'b0){ // tag[15]==0 is DMA RD
582 collect_data_flag = 1;
583 cl_pkt_tag[4:0] = l2port.$req[13:9];
584 cl_pkt_tag[8] = l2port.$req[8];
585 address[39:32] = l2port.$req[7:0];
586 }
587 d_ptr = l2port.$req[18:14];
588 }
589 }
590}
591
592////////////////////////////////////////////////////////////////////////////////
593// save_add_to_list()
594//
595//
596////////////////////////////////////////////////////////////////////////////////
597task fc_l2_sio_stub :: save_add_to_list (string myname,
598 bit [39:0] add,
599 bit [8:0] pkt_tag,
600 bit [4:0] d_ptr)
601{
602 bit [31:0] timeout = 0;
603
604 PR_INFO(name, MON_INFO, psprintf ("%s save_add_to_list() Waiting for req_cl_add[%0d] free ", myname, d_ptr ));
605 while (assoc_index(CHECK, req_cl_add, d_ptr))
606 {
607 @(posedge fc_l2b0_sio.clk);
608 if (timeout > 32'h0000ffff){
609 PR_ERROR(name, MON_ERR, psprintf ("%s save_add_to_list() TIMEOUT waiting for cache_line[%0d] free \n", myname, d_ptr));
610 }
611 timeout++;
612 }
613 PR_INFO(name, MON_INFO, psprintf ("%s save_add_to_list() Waiting for req_cl_add[%0d] free done", myname, d_ptr ));
614 req_cl_add[d_ptr] = add;
615 req_pkt_tag[d_ptr] = pkt_tag;
616 PR_INFO(name, MON_INFO, psprintf ("%s save_add_to_list() Save add to req_cl_add %0h, d_ptr %0d req_pkt_tag %h, req_pktr_tag %h", myname, add, d_ptr, pkt_tag, req_pkt_tag[d_ptr]));
617}
618
619
620////////////////////////////////////////////////////////////////////////////////
621// free_data_semaphore()
622// if the process running reassemble_dma_pkt is terminated, then this makes
623// sure that the semaphore is freed.
624////////////////////////////////////////////////////////////////////////////////
625task fc_l2_sio_stub :: free_data_semaphore (string myname,
626 integer dma_ptr)
627{
628 integer cl_idx;
629
630 integer sema_avail = semaphore_get (NO_WAIT, data_semph_id, 1);
631 semaphore_put (data_semph_id, 1);
632 PR_INFO(name, MON_INFO, psprintf ("%s free_data_semaphore() freed data_semph_id, sema_avail=%0d, d_ptr %0d", myname, sema_avail, dma_ptr));
633
634 // free any regions that are in use
635 for(cl_idx=0; cl_idx<32; cl_idx++) {
636 region_exit(cl_idx_region_id, cl_idx);
637 }
638
639 // clean out the associative arrays
640 assoc_index(DELETE, rtn_l2_cl );
641 assoc_index(DELETE, req_cl_add );
642 assoc_index(DELETE, rtn_pkt_tag );
643 assoc_index(DELETE, req_pkt_tag );
644
645 // reset cl ptr
646 l2_cl_idx = 0;
647}