Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / verif / env / niu / rxc_sat / vera / rxdma / niu_rx_test_util.vr
CommitLineData
86530b38
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: niu_rx_test_util.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 "niu_gen_pio.vrh"
37#include "niu_rx_descp.vrh"
38#include "niu_rxdmc.vrh"
39#include "cMesg.vrh"
40#include "mac_pio_class.vrh"
41#include "xpcs_memory_map.vri"
42#include "dmc_memory_map.vri"
43#include "ipp_memory_map.vri"
44#include "xmac_util.vrh"
45#include "bmac_util.vrh"
46#include "dmc_memory_map.vri"
47//#include "niu_rxdma_wr_chk.vrh"
48
49extern niu_gen_pio gen_pio_drv;
50extern Mesg be_msg;
51extern mac_util_class mac_util;
52extern bmac_util_class bmac_util;
53extern mac_pio_cl mac_pio_class;
54extern CRDMC rdmc;
55//extern Cniu_rxdma_wr_chkr niu_rxdma_wrchk;
56
57
58class niu_rx_test_util {
59
60 bit [31:0] xmac_hist7_cntr[2]; // shadow to remember this clear-on-read cntr
61
62 task new() {
63 printf ("class niu_rx_test_util newed.\n");
64 xmac_hist7_cntr[0] = 0;
65 xmac_hist7_cntr[1] = 0;
66 }
67
68 function integer getXPCSPktCnt (integer port_id, integer sent_pkt_cnt);
69 function integer getXMACPktCnt (integer port_id);
70 task flush_rcr (integer dma_num);
71 function integer getRdmcDropCnt (integer dma_num);
72 function integer getIppDropCnt (integer port_num);
73 function integer getMacDropCnt (integer port_num, integer sent_pkt_cnt);
74 task RX_MISC_START_pio_rd(bit [63:0] address, var bit [63:0] data, integer dma);
75 task RED_DIS_CNT_START_pio_rd(bit [63:0] address, var bit [63:0] data, integer dma);
76 task RCR_CFIG_B_pio_wr(bit [63:0] address, var bit [63:0] data, integer dma);
77 task RCR_CFIG_B_pio_rd(bit [63:0] address, var bit [63:0] data, integer dma);
78 task RCR_QLEN_pio_rd(bit [63:0] address, var bit [63:0] data, integer dma);
79 task XMAC_STATUS_pio_rd(integer port_id, var bit [63:0] data);
80 task BMAC_STATUS_pio_rd(integer port_id, var bit [63:0] data);
81 function integer get_rcr_qlen(integer dma);
82 task enable_rcr_timer(integer dma);
83 task cleanup_dma_interrupts(bit [31:0] dma_list);
84 function integer isTherePendingInterrupt(integer dma);
85 task wait_to_send_last_pkt(integer mac_id);
86
87}
88
89task niu_rx_test_util::wait_to_send_last_pkt(integer mac_id) {
90integer fifo_empty = 0;
91bit [63:0] rd_ptr, wr_ptr;
92
93 while (!fifo_empty) {
94 // read the IPP fifo read/write pointers for this port
95 case(mac_id){
96 0: gen_pio_drv.pio_rd(IPP0_BASE+20'h0_0110, rd_ptr);
97 1: gen_pio_drv.pio_rd(IPP1_BASE+20'h0_0110, rd_ptr);
98 2: gen_pio_drv.pio_rd(IPP2_BASE+20'h0_0110, rd_ptr);
99 3: gen_pio_drv.pio_rd(IPP3_BASE+20'h0_0110, rd_ptr);
100 }
101 case(mac_id){
102 0: gen_pio_drv.pio_rd(IPP0_BASE+20'h0_0118, wr_ptr);
103 1: gen_pio_drv.pio_rd(IPP1_BASE+20'h0_0118, wr_ptr);
104 2: gen_pio_drv.pio_rd(IPP2_BASE+20'h0_0118, wr_ptr);
105 3: gen_pio_drv.pio_rd(IPP3_BASE+20'h0_0118, wr_ptr);
106 }
107
108 // if read and write pointers are equal, the fifo is empty. Then release semaphore to send last_pkt
109 if (rd_ptr === wr_ptr) {
110 fifo_empty = 1;
111 printf("[%0d] IPP fifo pointers are equal, DFIFO is empty for port %0d. Now send last_pkt.\n",get_time(LO),mac_id);
112 }
113 else {
114 printf("[%0d] waiting for DFIFO to be empty for port %0d\n", get_time(LO), mac_id);
115 repeat(500) @(posedge CLOCK);
116 }
117 }
118}
119
120
121// This register supports read-to-clear
122function integer niu_rx_test_util::getIppDropCnt (integer port_num)
123{
124 bit [63:0] addr,data;
125 static integer ipp_drop_count[];
126
127 getIppDropCnt = 99999; // dummy value
128
129 if(ipp_drop_count[port_num] === 'hX) { ipp_drop_count[port_num] = 0; }
130
131 if((port_num==0)||(port_num==1)) {
132
133 // case (port_num) {
134 // 0 : addr = FZC_IPP_BASE_ADDRESS + IPP_PORT_STEP*0 + IPP_DISCARD_PKT_COUNTER;
135 // 1 : addr = FZC_IPP_BASE_ADDRESS + IPP_PORT_STEP*2 + IPP_DISCARD_PKT_COUNTER;
136 // }
137 addr = FZC_IPP_BASE_ADDRESS + IPP_PORT_STEP*port_num + IPP_DISCARD_PKT_COUNTER;
138 gen_pio_drv.pio_rd(addr, data, 1'b0);
139 printf ("niu_rx_test_util::getIppDropCnt() IPP Drop Packet Count = %0d for Port - %0d\n", data, port_num);
140 ipp_drop_count[port_num] += data;
141 }
142 else {
143 printf("ERROR niu_rx_test_util.getIppDropCnt() Port number %0d INVALID\n", port_num);
144 return;
145 }
146
147 getIppDropCnt = ipp_drop_count[port_num];
148}
149
150// The difference between pkt in and pkt out will result in Mac Drop count
151function integer niu_rx_test_util::getMacDropCnt (integer port_num, integer sent_pkt_cnt)
152{
153 getMacDropCnt = getXPCSPktCnt(port_num, sent_pkt_cnt) - getXMACPktCnt(port_num);
154}
155
156// This register does not support read-to-clear
157function integer niu_rx_test_util::getRdmcDropCnt (integer dma_num)
158{
159 bit [63:0] addr,data1,data2;
160
161 addr = RX_MISC_START + RXDMA_STEP*dma_num;
162 //gen_pio_drv.pio_rd(addr, data1, 1'b0);
163 RX_MISC_START_pio_rd(addr, data1, dma_num);
164
165
166 addr = RED_DIS_CNT_START + RED_DIS_CNT_STEP*dma_num;
167 //gen_pio_drv.pio_rd(addr, data2, 1'b0);
168 RED_DIS_CNT_START_pio_rd(addr, data2, dma_num);
169
170 // Take care of rtl issue which increments both red and misc counters for same pkts if crc error pkts are sent.
171 if(get_plus_arg(CHECK,"IGNORE_RED_DIS_CNT_START"))
172 data2 = 0;
173
174 printf ("niu_rx_test_util::getRdmcDropCnt() Drop Packet Count = %0d for DMA - %0d\n", data1+data2, dma_num);
175 getRdmcDropCnt = data1+data2;
176}
177
178
179// This register supports read-to-clear
180function integer niu_rx_test_util::getXPCSPktCnt (integer port_id, integer sent_pkt_cnt)
181{
182 bit [31:0] cfg_rd_data;
183 bit [31:0] rd_data;
184 integer base_addr;
185 static integer pcs_pkt_cnt[];
186
187 getXPCSPktCnt = 99999; // dummy value
188
189 if(pcs_pkt_cnt[port_id] === 'hX) { pcs_pkt_cnt[port_id] = 0; }
190
191 if (port_id ==0){
192 base_addr = bmac_util.get_mac_reg_base(0);
193 mac_pio_class.xmac_pio_rd( base_addr + XMAC_CONFIG,
194 cfg_rd_data,1'b0 );
195 if (cfg_rd_data[28:27] == 2'b01) { // checking for 1G or 10G
196 //mac_pio_class.bmac_pio_rd(PCS0_BASE +
197 // PCS_PACKET_COUNTER,rd_data, 1'b0);
198 //pcs_pkt_cnt[port_id] += rd_data[26:16];
199 pcs_pkt_cnt[port_id] = sent_pkt_cnt;
200 }
201 else if (cfg_rd_data[28:27] == 2'b00) {
202 mac_pio_class.xmac_pio_rd(XPCS0_BASE +
203 XPCS_PACKET_COUNTER,rd_data, 1'b0);
204 pcs_pkt_cnt[port_id] = rd_data[15:0];
205 }
206 }
207 else if (port_id ==1){
208 base_addr = bmac_util.get_mac_reg_base(1);
209 mac_pio_class.xmac_pio_rd( base_addr + XMAC_CONFIG,
210 cfg_rd_data,1'b0 );
211 if (cfg_rd_data[28:27] == 2'b01) { // checking for 1G or 10G
212 //mac_pio_class.bmac_pio_rd(PCS1_BASE +
213 // PCS_PACKET_COUNTER,rd_data, 1'b0);
214 //pcs_pkt_cnt[port_id] += rd_data[26:16];
215 pcs_pkt_cnt[port_id] = sent_pkt_cnt;
216 }
217 else if (cfg_rd_data[28:27] == 2'b00) {
218 mac_pio_class.xmac_pio_rd(XPCS1_BASE +
219 XPCS_PACKET_COUNTER,rd_data, 1'b0);
220 pcs_pkt_cnt[port_id] = rd_data[15:0];
221 }
222 }
223 else if (port_id ==2){
224 //base_addr = bmac_util.get_mac_reg_base(2);
225 // mac_pio_class.bmac_pio_rd(PCS2_BASE +
226 // PCS_PACKET_COUNTER,rd_data, 1'b0);
227 // pcs_pkt_cnt[port_id] += rd_data[26:16];
228 pcs_pkt_cnt[port_id] = sent_pkt_cnt;
229 }
230 else if (port_id ==3){
231 //base_addr = bmac_util.get_mac_reg_base(3);
232 // mac_pio_class.bmac_pio_rd(PCS3_BASE +
233 // PCS_PACKET_COUNTER,rd_data, 1'b0);
234 // pcs_pkt_cnt[port_id] += rd_data[26:16];
235 pcs_pkt_cnt[port_id] = sent_pkt_cnt;
236 }
237
238
239 getXPCSPktCnt = pcs_pkt_cnt[port_id];
240 printf("niu_rx_test_util::getXPCSPktCnt port_id %0d, getXPCSPktCnt %0d\n", port_id, getXPCSPktCnt);
241}
242
243
244// This register supports read-to-clear
245function integer niu_rx_test_util ::getXMACPktCnt (integer port_id)
246{
247 bit [31:0] rd_data;
248 bit [31:0] hist1=0;
249 bit [31:0] hist2=0;
250 bit [31:0] hist3=0;
251 bit [31:0] hist4=0;
252 bit [31:0] hist5=0;
253 bit [31:0] hist6=0;
254 bit [31:0] hist7=0;
255 static integer mac_pkt_cnt[];
256
257
258 integer base_addr;
259
260 getXMACPktCnt = 99999; // dummy value
261 if(mac_pkt_cnt[port_id] === 'hX) { mac_pkt_cnt[port_id] = 0; } // reset
262
263 if (port_id ==0){ // clear on read registers
264 base_addr = bmac_util.get_mac_reg_base(0);
265 //mac_pio_class.xmac_pio_rd(base_addr + RxMAC_HIST_CNT1, hist1,1'b0);
266 //mac_pio_class.xmac_pio_rd(base_addr + RxMAC_HIST_CNT2, hist2,1'b0);
267 //mac_pio_class.xmac_pio_rd(base_addr + RxMAC_HIST_CNT3, hist3,1'b0);
268 //mac_pio_class.xmac_pio_rd(base_addr + RxMAC_HIST_CNT4, hist4,1'b0);
269 //mac_pio_class.xmac_pio_rd(base_addr + RxMAC_HIST_CNT5, hist5,1'b0);
270 //mac_pio_class.xmac_pio_rd(base_addr + RxMAC_HIST_CNT6, hist6,1'b0);
271 mac_pio_class.xmac_pio_rd(base_addr + RxMAC_HIST_CNT7, hist7,1'b0);
272 xmac_hist7_cntr[port_id] = hist7;
273 printf("niu_rx_test_util::port0 :getXMACPktCnt() hist1, hist2, hist3, hist4, hist5, hist6, hist7 = %0d, %0d, %0d, %0d, %0d %0d and %0d\n", hist1, hist2, hist3, hist4, hist5, hist6, hist7);
274 mac_pkt_cnt[port_id] += hist1 + hist2 + hist3 + hist4 + hist5 +hist6 +hist7;
275 }
276 else if (port_id ==1){ // clear on read registers
277 base_addr = bmac_util.get_mac_reg_base(1);
278 //mac_pio_class.xmac_pio_rd(base_addr + RxMAC_HIST_CNT1, hist1,1'b0);
279 //mac_pio_class.xmac_pio_rd(base_addr + RxMAC_HIST_CNT2, hist2,1'b0);
280 //mac_pio_class.xmac_pio_rd(base_addr + RxMAC_HIST_CNT3, hist3,1'b0);
281 //mac_pio_class.xmac_pio_rd(base_addr + RxMAC_HIST_CNT4, hist4,1'b0);
282 //mac_pio_class.xmac_pio_rd(base_addr + RxMAC_HIST_CNT5, hist5,1'b0);
283 //mac_pio_class.xmac_pio_rd(base_addr + RxMAC_HIST_CNT6, hist6,1'b0);
284 mac_pio_class.xmac_pio_rd(base_addr + RxMAC_HIST_CNT7, hist7,1'b0);
285 xmac_hist7_cntr[port_id] = hist7;
286 printf("niu_rx_test_util::port1: getXMACPktCnt() hist1, hist2, hist3, hist4, hist5, hist6, hist7 = %0d, %0d, %0d, %0d, %0d, %0d and %0d\n", hist1, hist2, hist3, hist4, hist5, hist6, hist7);
287 mac_pkt_cnt[port_id] += hist1 + hist2 + hist3 + hist4 + hist5 +hist6 +hist7;
288 }
289 else if (port_id ==2){ // not clear on read register
290 bmac_util.rd_ipp_mac_reg(port_id, BRxMAC_FRM_CNT, rd_data, 1'b0);
291 mac_pkt_cnt[port_id] = rd_data;
292 }
293 else if (port_id ==3){ // not clear on read register
294 bmac_util.rd_ipp_mac_reg(port_id, BRxMAC_FRM_CNT, rd_data, 1'b0);
295 mac_pkt_cnt[port_id] = rd_data;
296 }
297
298 getXMACPktCnt = mac_pkt_cnt[port_id];
299
300 printf("niu_rx_test_util::getXMACPktCnt port_id %0d, getXMACPktCnt %0d\n", port_id, getXMACPktCnt);
301
302}
303
304task niu_rx_test_util::flush_rcr (integer dma_num)
305{
306 // RCR flush
307 //1gen_pio_drv.pio_wr(RCR_FLUSH_START + 12'h200*dma_num, 64'h1);
308 gen_pio_drv.pio_wr(rdmc.rx_dma[dma_num].getPIOAddress(RCR_FLUSH_START + 12'h200*dma_num,
309 rdmc.rx_dma[dma_num].dis_pio_virt), 64'h1);
310 printf ("niu_rx_test_util::flush_rcr() Flushed the RCR Entry for DMA - %0d\n", dma_num);
311
312}
313
314task niu_rx_test_util::RX_MISC_START_pio_rd(bit [63:0] address, var bit [63:0] data, integer dma) {
315 gen_pio_drv.pio_rd(rdmc.rx_dma[dma].getPIOAddress(address, rdmc.rx_dma[dma].dis_pio_virt), data, 1'b0);
316}
317
318task niu_rx_test_util::RED_DIS_CNT_START_pio_rd(bit [63:0] address, var bit [63:0] data, integer dma) {
319 gen_pio_drv.pio_rd(rdmc.rx_dma[dma].getPIOAddress(address, rdmc.rx_dma[dma].dis_pio_virt), data, 1'b0);
320}
321
322task niu_rx_test_util::RCR_CFIG_B_pio_rd(bit [63:0] address, var bit [63:0] data, integer dma){
323 gen_pio_drv.pio_rd(rdmc.rx_dma[dma].getPIOAddress(address, rdmc.rx_dma[dma].dis_pio_virt), data);
324}
325
326task niu_rx_test_util::RCR_CFIG_B_pio_wr(bit [63:0] address, var bit [63:0] data, integer dma){
327 gen_pio_drv.pio_wr(rdmc.rx_dma[dma].getPIOAddress(address, rdmc.rx_dma[dma].dis_pio_virt), data);
328}
329
330task niu_rx_test_util::RCR_QLEN_pio_rd(bit [63:0] address, var bit [63:0] data, integer dma){
331 gen_pio_drv.pio_rd(rdmc.rx_dma[dma].getPIOAddress(address, rdmc.rx_dma[dma].dis_pio_virt), data, 1'b0);
332}
333
334function integer niu_rx_test_util::get_rcr_qlen(integer dma){
335bit [63:0] addr,data;
336 addr = RCR_STAT_A_START + RXDMA_STEP * dma;
337 RCR_QLEN_pio_rd(addr, data, dma);
338get_rcr_qlen = data;
339}
340
341task niu_rx_test_util::enable_rcr_timer(integer dma){
342bit [63:0] addr,data;
343 // program TIMEOUT_EN=1
344 addr = RCR_CFIG_B_START + RXDMA_STEP * dma;
345 RCR_CFIG_B_pio_rd(addr, data, dma);
346 data[15] = 1;
347 RCR_CFIG_B_pio_wr(addr, data, dma);
348}
349
350task niu_rx_test_util::cleanup_dma_interrupts(bit [31:0] dma_list) {
351integer i;
352
353 for(i=0;i<16;i++){
354 if(dma_list[i]) {
355 if (get_rcr_qlen(i))
356 enable_rcr_timer(i);
357 }
358 }
359}
360
361function integer niu_rx_test_util::isTherePendingInterrupt(integer dma) {
362bit [63:0] rd_data, mask, interrupts;
363
364 // read the status register from this dma
365 rdmc.rx_dma[dma].pio_rd_RX_DMA_CTL_STAT_START(rd_data);
366
367 // mask off the non-interrupt bits from the status register
368 mask = 64'hffff_ffff_ffff_ffff;
369 mask[RX_DMA_CTL_STAT_PKTREAD] = 0;
370 mask[RX_DMA_CTL_STAT_PTRREAD] = 0;
371 mask[RX_DMA_CTL_STAT_MEX] = 0;
372
373 interrupts = rd_data & mask;
374
375 if (|interrupts)
376 isTherePendingInterrupt = 1;
377 else
378 isTherePendingInterrupt = 0;
379
380 printf ("niu_rx_test_util::isTherePendingInterrupt interrupts=0x%h, isTherePendingInterrupt=%b\n",
381 interrupts, isTherePendingInterrupt);
382}
383
384task niu_rx_test_util::XMAC_STATUS_pio_rd(integer port_id, var bit [63:0] data) {
385 integer base_addr;
386 base_addr = bmac_util.get_mac_reg_base(port_id);
387
388 case(port_id) {
389 0: gen_pio_drv.pio_rd(base_addr+XRxMAC_STATUS, data, 1'b0);
390 1: gen_pio_drv.pio_rd(base_addr+XRxMAC_STATUS, data, 1'b0);
391 default: printf ("ERROR port_id should be only 0 or 1 for xmac\n");
392 }
393}
394
395task niu_rx_test_util::BMAC_STATUS_pio_rd(integer port_id, var bit [63:0] data) {
396 integer base_addr;
397 base_addr = bmac_util.get_mac_reg_base(port_id);
398
399 case(port_id) {
400 2: gen_pio_drv.pio_rd(base_addr+BRxMAC_STATUS, data, 1'b0);
401 3: gen_pio_drv.pio_rd(base_addr+BRxMAC_STATUS, data, 1'b0);
402 default: printf ("ERROR port_id should be only 2 or 3 for bmac\n");
403 }
404}