Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / verif / env / niu / txc_sat / vera / niu_tx_descp.vr
CommitLineData
86530b38
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: niu_tx_descp.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 <ListMacros.vrh>
37#include "niu_mem.vrh"
38#include "ippkt_gen.vri"
39#include "dmc_memory_map.vri"
40#include "txc_memory_map.vri"
41#include "tx_descp_defines.vri"
42#include "niu_error_dfn.vri"
43
44#include "niu_dma.vrh"
45#include "pcg_token.vrh"
46#include "niu_txtoken.vrh"
47#include "niu_txcntrl_wd.vrh"
48#include "niu_tx_pktconfig.vrh"
49#include "cMesg.vrh"
50#include "hostErrInjTab.vrh"
51#include "hostRdCbMgr.vrh"
52#include "niu_cbclass.vrh"
53#include "pgIdgen.vrh"
54#include "niu_tx_errors.vrh"
55
56#ifdef N2_FC
57#include "fc_niu_ev2a.vrh"
58#endif
59
60#define TIME {get_time(HI), get_time(LO)}
61
62extern CSparseMem SparseMem;
63extern mbox_class mbox_id;
64extern Mesg be_msg;
65extern CHostErrInjTab HostErrInj;
66
67extern CHostRdCbMgr hostRdCbMgr;
68
69extern niu_gen_pio gen_pio_drv;
70
71extern CNiuDMABind NiuDMABind;
72
73MakeVeraList(TxPacketGenConfig)
74
75class DMAChannel extends CDMA {
76
77 integer id;
78 string type;
79 integer max_burst_weight;
80 integer current_deficit;
81 integer current_deficit_old;
82 integer current_deficitSnapShot;
83
84 integer desc_ring_head_ptr;
85 integer no_of_descriptors;
86 bit [63:0] ring_start_addr;
87 bit [63:0] ring_current_addr;
88 integer ring_size;
89 integer tx_port_num=0;
90 integer gather_mode = 0;
91 integer cont_kick_done= 0;
92 integer page0_id;
93 integer page1_id;
94 integer xlate_on = 0;
95 integer alignment;
96 bit [11:0] pkt_cnt;
97 bit [63:0] mailbox_addr;
98 bit [63:0] rl_mailbox_addr;
99 integer dis_pio_virt=0;
100 integer USE_CALL_BACKS;
101 integer host_mtu;
102 integer dma_enable = 0;
103 integer do_not_check_packet = 0;
104 integer pkt_part_err_seen = 0;
105
106 integer conf_part_err = 0;
107 integer conf_part_err_seen = 0;
108 integer is_nack_pref_err = 0;
109 bit [63:0] nack_pref_err_addr;
110 bit [63:0] nack_pref_err_pcaddr;
111
112 local integer last_kicked_tail = 0;
113 local integer last_kicked_tail_wrap = 0;
114 local integer last_head_read = 0;
115 local integer last_head_wrap_read = 0;
116 local integer desc_random_kick_semid = -1;
117
118 CpgIdgen pgIdgen;
119 CSetTxError SetTxError;
120
121 integer start;
122 CTxToken curr_kick_lentry;
123 integer list_empty = 0;
124
125 // this piece of code
126 // added for cache model
127 bit [63:0] gb_kick_data = 64'h0;
128 bit [63:0] lkick_data = 64'h0;
129 integer rng_wrp_cnt = 0;
130 integer wrp_enb = 0;
131 integer t_data = 0;
132 bit st = 1'b0;
133
134
135 // partition support shadow variables
136 bit [63:0] ring_lpvalid;
137 bit [63:0] ring_lpmask1;
138 bit [63:0] ring_lpvalue1;
139 bit [63:0] ring_lpmask2;
140 bit [63:0] ring_lpvalue2;
141 bit [63:0] ring_lprelo1;
142 bit [63:0] ring_lprelo2;
143 bit [63:0] ring_lphandle;
144
145
146 // list of tokens which will be used by the DRR logic
147 VeraList_CTxToken TxTokenList;
148
149 // this list used for Cache Model
150 VeraList_CTxToken M_TxTokenList;
151
152 // list for cont random kick
153 VeraList_TxPacketGenConfig PktGenConfigQueue;
154 integer descriptors_queued=0;
155 integer reset_done;
156
157 // descriptor_ring -- -
158 CTxDescrRing desc_ring;
159 virtual function integer isr( ( bit[1:0] ldf_flags = 0) ){}
160 task new(integer i,string t,(integer intr_dev_id = 0));
161 task gen_txpacket(integer ii,TxPacketGenConfig PktGenConfig);
162 task gen_txGatherPackets(TxPacketGenConfig PktGenConfig, (integer pkt_page_id=0) );
163 task set_host_err_callback(bit [39:0] call_bk_addr, integer host_err_code);
164 task incPktCnt() {
165 pkt_cnt = pkt_cnt +1;
166 }
167 function bit[11:0] getPktCnt() {
168 getPktCnt = pkt_cnt;
169 }
170
171 task ContTxPacketGen(TxPacketGenConfig PktGenConfig) ;
172 function integer getMaxTobeKicked() ;
173 task ContRandomKick(integer maxthreshold, integer min_head_tail_diff) ;
174 function integer getHeadTailDiff() ;
175 task chng_no_of_desc_qued(integer val,integer what) ;
176
177 function byte_array generate_packets(TxPacketGenConfig PktGenConfig,CTxToken TxToken ) ;
178 task generate_tokens(integer port_id,integer token, CTxToken TxToken);
179 task create_descriptor(var CTxdescriptor desc, bit [13:0] length,bit[43:0] address, bit [3:0] num_of_desc, bit sop, bit mark, (integer pkt_page_id = 0));
180 task WritePackets( byte_array packets, bit[43:0] start_address,bit [13:0] pkt_length, integer curr_ptr_indx, var integer last_ptr_indx,(integer page_id = 0) );
181 task WriteTxControlWord( bit [43:0] address, TxPacketControlWord control_word, (integer pkt_page_id = 0)) ;
182 function bit [95:0] gen_debug_header( bit [63:0] a,bit [63:0] r,bit [13:0] l);
183
184 task bind_to_txport(integer n) {
185 tx_port_num = n;
186 if(function_no==-1) // Do this only if this is not bounded
187 function_no = tx_port_num;
188 // Override this with a +args
189
190 if(get_plus_arg( CHECK, "RXTX_PIO_STRESS_BINDING=")) {
191 function_no = get_plus_arg( NUM, "RXTX_PIO_STRESS_BINDING=");
192 function_no = function_no % 4;
193 }
194
195
196 SetDefFunc(function_no);
197 printf(" DMA id %d is now bound to TxPort Number - %d \n",id,n);
198 }
199
200 task unbind_from_txport(integer n) {
201 tx_port_num = -1;
202 printf(" DMA id %d is unbinded from TxPort Number %d\n",id,n);
203 }
204
205 // functions to update DMA Tx Kick Registers
206 task setTxRingConfig(bit [63:0] data,(bit read_back = 1'b0));
207 task setTxRingKick(bit [63:0] data);
208 task readTxRingHead(var bit [63:0] data);
209 task SetTxCs(bit [63:0] data);
210 task SetTxCs_DBG(bit [63:0] data);
211 task RdTxCs_DBG();
212 task SetTxMaxBurst ( bit[63:0] data);
213 // functions for Tx partition support
214 task SetTxLPValid(bit [63:0] data);
215 task SetTxLPMask1(bit [63:0] data);
216 task SetTxLPValue1(bit [63:0] data);
217 task SetTxLPMask2(bit [63:0] data);
218 task SetTxLPValue2(bit [63:0] data);
219 task SetTxLPRELOC1(bit [63:0] data);
220 task SetTxLPRELOC2(bit [63:0] data);
221 task SetTxLPHANDLE(bit [63:0] data);
222 task SetTxMBOX(bit [63:0] data);
223 task SetTxEventMask(bit [63:0] data);
224 task RdTxCs((integer sel = 0));
225 task RdTxPktCnt(var integer rtl_pkt_cnt);
226 task RdTxRngHDL(var bit [63:0] hd_ptr);
227 task RdTxRngSHHD(var bit [63:0] hd_ptr);
228
229 task InjTdmcParErr(bit [63:0] data);
230 // functions for tx init DMA tasK
231 task InitTXDMA(integer desc_ring_length, var bit[39:0] ring_start_address, (integer err_code = 0), (integer func_num = 0));
232 task SetPage0Registers(bit [31:0] mask,bit [31:0] value, bit [31:0] reloc);
233 task SetPage1Registers(bit [31:0] mask,bit [31:0] value, bit [31:0] reloc);
234 task SetPageEnables(bit page0_enable, bit page1_enable, integer func_num);
235 task setRngConfig(bit [39:0] ring_st_addr, bit[12:0] length, (integer ring_page_id=0));
236 task stuff_psu_hdr_chksum(byte_array ip_packets, TxPacketGenConfig PktGenConfig);
237 function bit[15:0] partial_cksum(byte_array ip_packets, TxPacketGenConfig PktGenConfig, integer index);
238 function integer get_index_base(TxPacketGenConfig PktGenConfig);
239 task mailbox_update(integer mk_bit_count);
240 // add reclaim buffers task
241 task reclaim_buffers((integer reclaim =1), integer num_bufs_toreclaim);
242 task model_cache();
243 task add_drr_credits() ;
244 task SnapShotDRRState() ;
245 task LoadDRRState() ;
246 function integer update_deficit(integer length) ;
247 function integer get_current_token(var CTxToken txtoken) ;
248 task push_back_token(CTxToken txtoken) ;
249 function integer get_current_token_from_Mcache(var CTxToken txtoken) ;
250 function integer enableTokens(bit [63:0] data);
251 function integer checkTokenHeadValid() ;
252 function integer checkTokenHeadValid_from_Mcache() ;
253 task bind_to_group( integer g);
254 task reset_bind_to_group( (integer dummy_g=0));
255 task check_rstdone((integer wait_count = 100));
256
257 task Read_TxCs(var bit [63:0] rd_data);
258 task Read_Err_LogH(var bit [63:0] rd_data);
259 task Read_Err_LogL(var bit [63:0] rd_data);
260 task Rd_Errlog_after_rst();
261 task stop_unstall_dma(integer no_of_times);
262 task stop_dma();
263 task reset_dma();
264 task reinit_dma(integer ring_len);
265 task reset_reinit_dma(integer ring_len, integer no_of_times);
266
267 task Rd_MaxBurst_Len(var bit[63:0] rd_data);
268 task Wr_MaxBurst_Len(bit[63:0] wr_data);
269 task Check_TxCs(string err_code, (integer chk_set=0),(integer chk_clr = 0));
270 task Wr_TDMCIntrDbg(bit [63:0] data);
271
272 task RdTxRngKick(var bit [63:0] tail_ptr);
273
274 task read_mailbox_addr();
275
276
277}
278
279task DMAChannel::new(integer i,string t,(integer intr_dev_id = 0)){
280 integer j;
281 super.new(i,0,intr_dev_id);
282 address_incr = 8;
283#ifdef N2_FC
284 dma_enable = 1;
285#else
286 dma_enable = 0;
287#endif
288 do_not_check_packet = 0;
289 pkt_part_err_seen = 0;
290 conf_part_err_seen = 0;
291 id = i;
292 start = 0;
293 pkt_cnt = 0;
294 pgIdgen = new();
295 if(xlate_on) {
296 page0_id = 2*i;
297 page1_id = page0_id + 1;
298 } else {
299 page0_id = 0;
300 page1_id = 0;
301 }
302 tx_port_num = -1;
303 max_burst_weight = -1;
304 current_deficit = 0;
305 current_deficit_old = 0;
306 type = t;
307 desc_ring = new();
308 dis_pio_virt=1;
309 TxTokenList = new();
310 M_TxTokenList = new();
311 SetTxError = new();
312 last_kicked_tail = 0;
313 last_kicked_tail_wrap = 0;
314 last_head_read = 0;
315 last_head_wrap_read = 0;
316 PktGenConfigQueue = new();
317 desc_random_kick_semid = alloc(SEMAPHORE, 0, 1, 1);
318 reset_done =0;
319 printf("DMAChannel :: new reset_done - %d %d \n",id,reset_done);
320
321 // new cache tokenlist &
322 // call the model cache
323 if (get_plus_arg(CHECK,"WCACHE_MODEL")) {
324
325 fork {
326 model_cache();
327 }
328 join none
329 }
330
331 // get byte align from command line
332 if (get_plus_arg(CHECK,"BYTE_ALIGNMENT="))
333 alignment = get_plus_arg(NUM,"BYTE_ALIGNMENT=");
334 else
335 alignment = 16;
336
337 be_msg.print(e_mesg_info,"niu_tx_descp","new","byte_alignment %0d\n", alignment);
338
339 if( get_plus_arg( CHECK, "NW_DRR_MODEL")) {
340 USE_CALL_BACKS = 1;
341 } else USE_CALL_BACKS = 0;
342
343 // get host MTU size
344
345 if (get_plus_arg (CHECK,"PEU_MAX_READ_REQ_SIZE"))
346 host_mtu = get_plus_arg(NUM,"PEU_MAX_READ_REQ_SIZE");
347 else
348 host_mtu = 64;
349
350
351 for(j=0;j<4;j++) {
352 if(mbox_id.niu_tx_cb[j] == -1) {
353 // Alocate Mailbox
354 mbox_id.niu_tx_cb[j] = alloc(MAILBOX,0,1);
355 // Check if we were succesfull allocating the mailbox
356 if(mbox_id.niu_tx_cb[j] == 0) {
357 printf("ERROR Could not allocate the outgoing mailbox port %d \n",j);
358 mbox_id.niu_tx_cb[j] = -1;
359 return;
360 }
361 }
362 }
363
364 for(j=0;j<4;j++) {
365 if(mbox_id.niu_txdrr[j] == -1) {
366 // Alocate Mailbox
367 mbox_id.niu_txdrr[j] = alloc(MAILBOX,0,1);
368 // Check if we were succesfull allocating the mailbox
369 if(mbox_id.niu_txdrr[j] == 0) {
370 printf("ERROR Could not allocate the outgoing mailbox port %d \n",j);
371 mbox_id.niu_txdrr[j] = -1;
372 return;
373 }
374 }
375 }
376 }
377
378task DMAChannel::add_drr_credits() {
379 if(dma_enable) {
380 if(max_burst_weight == -1) {
381 printf("ERROR-- MAX Burst Not programmed for DMA %d \n",id);
382 }
383 if(current_deficit<=0)
384 current_deficit = current_deficit + max_burst_weight;
385 printf(" DRR DEBUG Added Credits to DMA %d New Credits = %d \n",id,current_deficit);
386 }
387}
388task DMAChannel::LoadDRRState() {
389 current_deficit= current_deficitSnapShot ;
390}
391task DMAChannel::SnapShotDRRState() {
392 current_deficitSnapShot = current_deficit;
393}
394
395function integer DMAChannel::update_deficit(integer length) {
396
397 current_deficit = current_deficit - length;
398
399 printf(" DRR DEBUG Credits Spent for DMA %d New Credits = %d \n",id,current_deficit);
400 // CHANGE if(current_deficit <=0) update_deficit = 0;
401 if(current_deficit <0) update_deficit = 0;
402 else update_deficit = 1;
403}
404function integer DMAChannel::get_current_token(var CTxToken txtoken) {
405 if(TxTokenList.empty() ) {
406 printf( " DRR DEBUG -- TokenList is empty Done with all the valid tokens for DMA %d \n",id);
407 get_current_token = -1;
408 } else {
409 txtoken = TxTokenList.front();
410 if(txtoken.valid==0) {
411 printf( " DRR DEBUG TxToken at descriptor address %x Not yet kicked \n", txtoken.descriptor_address);
412 get_current_token = -1;
413 } else {
414 // TxTokenList.pop_front();
415 get_current_token = 1;
416 printf("calling get_current_token task\n");
417 }
418 }
419}
420task DMAChannel::push_back_token(CTxToken txtoken) {
421 TxTokenList.push_front(txtoken);
422}
423
424 // adding this function similar to get_current_token
425 // this function to be used when cache_model is used
426
427function integer DMAChannel::get_current_token_from_Mcache(var CTxToken txtoken) {
428 if(M_TxTokenList.empty() ) {
429 printf( " DRR DEBUG -- TokenList is empty Done with all the valid tokens for DMA %d \n",id);
430 get_current_token_from_Mcache = -1;
431 } else {
432 txtoken = M_TxTokenList.front();
433 if(txtoken.valid==0) {
434 printf( " DRR DEBUG TxToken at descriptor address %x Not yet kicked \n", txtoken.descriptor_address);
435 get_current_token_from_Mcache = -1;
436 } else {
437 get_current_token_from_Mcache = 1;
438 printf("calling get_current_token_from_Mcache task\n");
439 }
440 }
441}
442
443function integer DMAChannel::checkTokenHeadValid() {
444CTxToken txtoken;
445 if(TxTokenList.empty() ){
446 checkTokenHeadValid = 0;
447 } else {
448 txtoken = TxTokenList.front();
449 checkTokenHeadValid = txtoken.valid;
450 printf("DRR_DEBUG: CheckTokenVaild txtoken.valid %d\n",txtoken.valid);
451 printf("DRR DEBUG - CheckTokenVaild Matches token id - %d \n",txtoken.id);
452
453 }
454}
455
456// added this function for model cache token list
457// this is used when model cache used.
458
459function integer DMAChannel::checkTokenHeadValid_from_Mcache() {
460CTxToken txtoken;
461 if(M_TxTokenList.empty() ){
462 checkTokenHeadValid_from_Mcache = 0;
463 } else {
464 txtoken = M_TxTokenList.front();
465 checkTokenHeadValid_from_Mcache = txtoken.valid;
466 printf("DRR_DEBUG: CheckTokenVaild txtoken.valid %d\n",txtoken.valid);
467 }
468}
469
470
471function integer DMAChannel::enableTokens(bit [63:0] data) {
472
473// A delay may have to be added here to sync with the hardware
474
475 integer error;
476 VeraListIterator_CTxToken item, next_item;
477 integer entry_found;
478 bit match;
479 CTxToken Entry;
480 bit [63:0] match_descaddr;
481
482 printf("DRR DEBUG Inside enableTokens - DMA- %d address - %x Size - %d \n",id,data,TxTokenList.size());
483 if(TxTokenList.empty() ){
484 enableTokens = -1;
485 printf(" DRR DEBUG - Token List empty for dmaid = %d \n",id);
486 } else {
487
488 // Scan through all the entries untill (entry.descriptor_address == data)
489 // for all those entries set valid = 1;
490 // if no entry found return -1
491
492 entry_found =0;
493 match = 0;
494// This is really needed to prevent user errors
495 item = TxTokenList.start();
496 while(!match & item.neq(TxTokenList.finish())) {
497 Entry = item.data();
498 Entry.print();
499 if(desc_ring.rg_wrapp) {
500 if(data == 0)
501 match_descaddr = ring_size*64 - 8;
502 // match_descaddr = 0;
503 else
504 match_descaddr = data - 8;
505 } else match_descaddr = data - 8;
506
507 printf("ENB_DESC_DATA %0h\n",Entry.descriptor_address);
508 printf("MATCH_DESCADDR %0h\n",match_descaddr);
509
510 if((Entry.descriptor_address === match_descaddr) ||
511 (Entry.last_descriptor_address === match_descaddr)/* TOADS FIX THIS*/) {
512 match = 1;
513 entry_found = 1;
514 printf(" DRR DEBUG - Entry found Address - %x Matches token id - %d \n",data,Entry.id);
515 printf(" DRR DEBUG - First DESC Address - %x\n",Entry.descriptor_address);
516 printf(" DRR DEBUG - last DESC Address - %x\n",Entry.last_descriptor_address);
517 }
518 item.next();
519 }
520
521 if(entry_found) {
522 // Update the valid bit for the appropriate entries
523 match = 0;
524 item = TxTokenList.start();
525 while(!match & item.neq(TxTokenList.finish())) {
526 Entry = item.data();
527 if(is_nack_pref_err) {
528 if((Entry.xlate_desc_addr[63:6] == nack_pref_err_addr[63:6]) ||
529 (Entry.xlate_desc_addr[63:6] == nack_pref_err_pcaddr[63:6])) {
530 Entry.pgToken.do_not_check = 1;
531 printf("niu_tx_desc, setting do_not_check for token id %d\n",Entry.pgToken.gId);
532 printf("niu_tx_desc, xlate_addr %x, nack_pref_err_addr %x\n",Entry.xlate_desc_addr,nack_pref_err_pcaddr);
533 printf("niu_tx_desc, xlate_addr %x, nack_pref_err_addr %x\n",Entry.xlate_desc_addr,nack_pref_err_addr);
534 }
535 }
536 next_item = TxTokenList.erase(item);
537 Entry.valid = 1;
538 printf(" DRR DEBUG - DMA -%d Validating Entry: Token id - %d Size - %d \n",id,Entry.id,TxTokenList.size());
539 TxTokenList.insert(next_item,Entry);
540 printf(" DRR DEBUG - Done with Inserting Entry: Token id - %d Size - %d \n",Entry.id,TxTokenList.size());
541 if((Entry.descriptor_address === match_descaddr) ||
542 (Entry.last_descriptor_address === match_descaddr)/*FIX THIS*/) {
543 match = 1;
544 if (get_plus_arg(CHECK,"RAND_KMCD")) {
545 curr_kick_lentry = Entry;
546 printf("Last Entry of curr_kick %d for DMA_id %d\n",Entry.pgToken.gId,this.id);
547 }
548 }
549 item = next_item;
550 }
551 }
552 }
553 enableTokens = entry_found;
554
555}
556
557task DMAChannel::SetTxMaxBurst(bit[63:0] data) {
558
559 bit [39:0] address;
560 bit [63:0] w_data;
561 bit [11:0] port_offset;
562 bit [7:0] i;
563
564
565 // loop for programming the txc max burst
566
567
568 /* case(this.id) {
569 0 : address = TXC_DMA0_BASE + TXC_DMA_MAXBURST;
570 1 : address = TXC_DMA1_BASE + TXC_DMA_MAXBURST;
571 2 : address = TXC_DMA2_BASE + TXC_DMA_MAXBURST;
572 3 : address = TXC_DMA3_BASE + TXC_DMA_MAXBURST;
573 4 : address = TXC_DMA4_BASE + TXC_DMA_MAXBURST;
574 5 : address = TXC_DMA5_BASE + TXC_DMA_MAXBURST;
575 6 : address = TXC_DMA6_BASE + TXC_DMA_MAXBURST;
576 7 : address = TXC_DMA7_BASE + TXC_DMA_MAXBURST;
577 8 : address = TXC_DMA8_BASE + TXC_DMA_MAXBURST;
578 9 : address = TXC_DMA9_BASE + TXC_DMA_MAXBURST;
579 10 : address = TXC_DMA10_BASE + TXC_DMA_MAXBURST;
580 11 : address = TXC_DMA11_BASE + TXC_DMA_MAXBURST;
581 12 : address = TXC_DMA12_BASE + TXC_DMA_MAXBURST;
582 13 : address = TXC_DMA13_BASE + TXC_DMA_MAXBURST;
583 14 : address = TXC_DMA14_BASE + TXC_DMA_MAXBURST;
584 15 : address = TXC_DMA15_BASE + TXC_DMA_MAXBURST;
585 16 : address = TXC_DMA16_BASE + TXC_DMA_MAXBURST;
586 17 : address = TXC_DMA17_BASE + TXC_DMA_MAXBURST;
587 18 : address = TXC_DMA18_BASE + TXC_DMA_MAXBURST;
588 19 : address = TXC_DMA19_BASE + TXC_DMA_MAXBURST;
589 20 : address = TXC_DMA20_BASE + TXC_DMA_MAXBURST;
590 21 : address = TXC_DMA21_BASE + TXC_DMA_MAXBURST;
591 22 : address = TXC_DMA22_BASE + TXC_DMA_MAXBURST;
592 23 : address = TXC_DMA23_BASE + TXC_DMA_MAXBURST;
593 24 : address = TXC_DMA24_BASE + TXC_DMA_MAXBURST;
594 25 : address = TXC_DMA25_BASE + TXC_DMA_MAXBURST;
595 26 : address = TXC_DMA26_BASE + TXC_DMA_MAXBURST;
596 27 : address = TXC_DMA27_BASE + TXC_DMA_MAXBURST;
597 28 : address = TXC_DMA28_BASE + TXC_DMA_MAXBURST;
598 29 : address = TXC_DMA29_BASE + TXC_DMA_MAXBURST;
599 30 : address = TXC_DMA30_BASE + TXC_DMA_MAXBURST;
600 31 : address = TXC_DMA31_BASE + TXC_DMA_MAXBURST;
601 } */
602
603 address = TXC_DMA0_BASE + this.id*4096 + TXC_DMA_MAXBURST;
604 w_data = data;
605 max_burst_weight = data[19:0];
606
607 // clear the deficit of the channel when
608 // the max burst is updated
609
610 current_deficit = 0;
611
612 printf("DMAChannel::SetTxMaxBurst DMA - %d max_burst_weight - %d current_deficit - %d\n",id,max_burst_weight,current_deficit);
613 gen_pio_drv.pio_wr(address,w_data);
614
615}
616
617
618// task to read & write max burst len transmitted by dma
619
620task DMAChannel:: Rd_MaxBurst_Len(var bit[63:0] rd_data) {
621
622 bit [39:0] address;
623
624 address = TXC_DMA0_BASE + this.id*4096 + TXC_DMA_MAX_LEN;
625 gen_pio_drv.pio_rd(address,rd_data);
626
627}
628
629task DMAChannel:: Wr_MaxBurst_Len(bit[63:0] wr_data) {
630
631 bit [39:0] address;
632
633 address = TXC_DMA0_BASE + this.id*4096 + TXC_DMA_MAX_LEN;
634 gen_pio_drv.pio_wr(address,wr_data);
635
636}
637
638task DMAChannel::setTxRingConfig(bit [63:0] data, (bit read_back = 1'b0)){
639
640 bit [39:0] address;
641 integer status;
642 bit [63:0] config_data;
643 bit [63:0] rd_data;
644 bit [5:0] rand_num;
645 integer ring_page_id =0;
646 bit [63:0] data_tmp0;
647 bit [63:0] Rdata0;
648 bit [63:0] memArray_addr;
649 bit [7:0] be = 8'hff;
650
651
652 // TX_RNG_CFIG address is a function of dma channel
653
654 //-- address = TBR_CFIG_A + id*40'h200;
655 rand_num = random()%64;
656 ring_size = data[63:48];
657 desc_ring.initRing(ring_start_addr, ring_size, xlate_on, ring_page_id, 1);
658 desc_ring.xlate_on = xlate_on;
659 address = TX_RNG_CFIG + id*40'h200;
660 printf("RNG_STADDR %0h\n",ring_start_addr);
661 config_data = {data[63:48],4'hf,ring_start_addr[43:6],rand_num};
662 // ncu_driver.write_data(address,data);
663 gen_pio_drv.pio_wr(getPIOAddress(address,dis_pio_virt) ,config_data);
664
665#ifdef N2_FC
666 Fc_Niu_Ev2a_setTxRingConfig (config_data);
667#endif
668
669 if(read_back) {
670 repeat(10) @(posedge CLOCK);
671 gen_pio_drv.pio_rd(getPIOAddress(address,dis_pio_virt) ,rd_data);
672 }
673
674}
675
676
677// added this on 02/21/05
678
679task DMAChannel::setRngConfig(bit [39:0] ring_st_addr, bit[12:0] length, (integer ring_page_id=0)) {
680
681 bit [39:0] address;
682 integer status;
683 bit [63:0] config_data;
684 bit [63:0] rd_data;
685 bit [5:0] rand_num;
686 bit [63:0] data_tmp0;
687 bit [63:0] Rdata0;
688 bit [63:0] memArray_addr;
689 bit [7:0] be = 8'hff;
690
691 // TX_RNG_CFIG address is a function of dma channel
692
693 //-- address = TBR_CFIG_A + id*40'h200;
694 rand_num = random()%64;
695 // ring_size = data[63:48];
696 ring_size = length;
697 printf("RNG_SIZE %0d\n",ring_size);
698 // desc_ring.initRing(ring_st_addr, ring_size);
699 desc_ring.initRing(ring_st_addr,ring_size,xlate_on,ring_page_id,1);
700 desc_ring.xlate_on = xlate_on;
701 address = TX_RNG_CFIG + id*40'h200;
702 printf("RNG_STADDR %0h\n",ring_st_addr);
703
704 if(conf_part_err == CONF_PART_ERROR) {
705 ring_st_addr = ring_st_addr ^ 40'hff_ffff_ffff;
706 conf_part_err_seen = 1;
707 }
708
709 config_data = {3'h0,length,4'h0,4'h0,ring_st_addr[39:6],rand_num};
710
711 gen_pio_drv.pio_wr(getPIOAddress(address,dis_pio_virt) ,config_data);
712
713#ifdef N2_FC
714 Fc_Niu_Ev2a_setTxRingConfig (config_data);
715#endif
716
717
718 /* if(read_back) {
719 repeat(10) @(posedge CLOCK);
720 gen_pio_drv.pio_rd(address,rd_data);
721 } */
722
723}
724
725task DMAChannel::readTxRingHead(var bit [63:0] data){
726 bit [39:0] address;
727 integer status;
728 // TX_RNG_HEAD address is a function of dma channel
729
730 // This should be called once at the config time and then hardware updates it.
731 //-- address = TX_RING_HD + id*40'h200;
732 address = TX_RING_HDH + id*40'h200;
733 // ncu_driver.read_data(address,data,status);
734 gen_pio_drv.pio_rd(getPIOAddress(address,dis_pio_virt) ,data);
735
736}
737
738task DMAChannel::setTxRingKick(bit [63:0] data){
739 bit [39:0] address;
740 integer status;
741 bit [63:0] ac_data;
742 CTxDrrTr drr_trigger;
743 bit [63:0] data_tmp0;
744 bit [63:0] Rdata0;
745 bit [63:0] memArray_addr;
746 bit [7:0] be = 8'hff;
747
748 if (get_plus_arg(CHECK,"RAND_KMCD")) {
749 printf("In SetTxRingKick @time %d for DMA_id %d\n",TIME,this.id);
750 printf("In SetTxRingKick start_val %d for DMA_id %d\n",start,this.id);
751
752 if(start == 1) {
753 printf("Last Entry of curr_kick in setTxRingKick %d for DMA_id %d\n",curr_kick_lentry.pgToken.gId,this.id);
754 if(curr_kick_lentry.pgToken.tx_request_seen) {
755 list_empty = 1;
756 printf("setTxRingKick : Value of Token_id %d & DMA_id %d\n",curr_kick_lentry.pgToken.gId,this.id);
757 } else
758 list_empty = 0;
759 } else {
760 list_empty = 0;
761 curr_kick_lentry = new();
762 }
763
764 start = 1;
765 }
766
767
768
769 ac_data[RSVD] = random();
770 ac_data[WRAP] = desc_ring.ring_wrapped;
771 ac_data[TAIL] = data[TAIL];
772 ac_data[RSVD2] = random();
773
774 // just to simplify
775 last_kicked_tail = data[TAIL];
776 last_kicked_tail_wrap = desc_ring.ring_wrapped;
777
778
779 // TX_RING_KICK address is a function of dma channel
780
781 address = TX_RING_KICK + id*40'h200;
782 // ncu_driver.write_data(address,data);
783 gen_pio_drv.pio_wr(getPIOAddress(address,dis_pio_virt) ,ac_data);
784
785 gb_kick_data = ac_data;
786 lkick_data = data;
787
788 // piece of code used only by m_cache
789
790 case(st) {
791 1'b0 : {
792 if(gb_kick_data[19]) {
793 rng_wrp_cnt++;
794 wrp_enb = 1;
795 st = 1'b1;
796 } else {
797 st = 1'b0;
798 }
799 }
800 1'b1 : {
801 if(~gb_kick_data[19]) {
802 rng_wrp_cnt++;
803 st = 1'b0;
804 } else {
805 st = 1'b1;
806 }
807 }
808 }
809
810 if(wrp_enb)
811 t_data = ((desc_ring.ring_size*8)*rng_wrp_cnt) + gb_kick_data[18:3];
812 else
813 t_data = gb_kick_data[18:3];
814
815 printf("TAIL_DATA %d\n",t_data);
816
817#ifdef N2_FC
818 Fc_Niu_Ev2a_setTxRingKick (ac_data);
819#endif
820
821 if (get_plus_arg(CHECK,"WCACHE_MODEL")) {
822 // this thing taken care in cache model
823 } else {
824 if (get_plus_arg(CHECK,"RAND_KMCD")) {
825 if(!list_empty) {
826 status = enableTokens( data );
827 if(status == -1) {
828 printf(" ERROR - Packets for descriptor address - %x Not yet generated \n",data);
829 }
830 }
831 } else {
832 status = enableTokens( data );
833 if(status == -1) {
834 printf(" ERROR - Packets for descriptor address - %x Not yet generated \n",data);
835 }
836 }
837 }
838
839 if(USE_CALL_BACKS) {
840 drr_trigger = new();
841 drr_trigger.NewKickSeen = 1;
842 drr_trigger.NewKickDMA = id;
843 mailbox_put(mbox_id.niu_txdrr[tx_port_num] , drr_trigger);
844 }
845
846}
847
848
849// add transmit channel control and status reg
850
851task DMAChannel:: SetTxCs(bit [63:0] data)
852{
853 bit [39:0] address;
854 bit [63:0] r_data;
855 integer rst_done = 0;
856 integer count = 0;
857
858 address = TX_CS + id*40'h200;
859 gen_pio_drv.pio_wr(getPIOAddress(address,dis_pio_virt) ,data);
860 dma_enable = ~data[30];
861
862 if(dma_enable)
863 cont_kick_done= 0; // enable kicking due to reset
864
865 // perform a read from the register to make sure
866 // tdmc is in the rst_done state before programming
867 // the other config regs
868
869 if(data[31]) { // do a read back only if reset
870
871 while(!rst_done) {
872 address = TX_CS + id*40'h200;
873 gen_pio_drv.pio_rd(getPIOAddress(address,dis_pio_virt) ,r_data);
874 if(r_data[30]) {
875 rst_done = 1;
876 count = 0;
877 be_msg.print(e_mesg_info,"niu_tx_descp","SetTxCs","RST_STATE set for DMA %d\n",this.id);
878 } else {
879
880 if(count > 100) {
881 rst_done = 1;
882 count = 0;
883 be_msg.print(e_mesg_error,"niu_tx_descp","SetTxCs","ERROR : RST_STATE not set for DMA %d\n",this.id);
884 } else {
885 count++;
886 rst_done = 0;
887 repeat(50) @(posedge CLOCK);
888 }
889
890 }
891
892 }
893
894 }
895}
896
897task DMAChannel:: SetTxCs_DBG(bit [63:0] data)
898{
899 bit [39:0] address;
900
901 address = TX_CS_DBG + id*40'h200;
902 gen_pio_drv.pio_wr(getPIOAddress(address,dis_pio_virt) ,data);
903
904}
905
906task DMAChannel:: RdTxCs_DBG()
907{
908 bit [39:0] address;
909 bit [63:0] r_data;
910
911 address = TX_CS_DBG + id*40'h200;
912 gen_pio_drv.pio_rd(getPIOAddress(address,dis_pio_virt) ,r_data);
913
914}
915
916
917task DMAChannel :: SetTxLPValid(bit [63:0] data)
918{
919 bit [39:0] address;
920 bit [63:0] data_tmp0;
921 bit [63:0] Rdata0;
922 bit [63:0] memArray_addr;
923 bit [7:0] be = 8'hff;
924
925 address = TX_LOG_PAGE_VLD + id*40'h200;
926 gen_pio_drv.pio_wr(getPIOAddress(address,dis_pio_virt) ,data);
927
928#ifdef N2_FC
929
930Fc_Niu_Ev2a_SetTxLPValid (data);
931#endif
932
933 ring_lpvalid = data;
934}
935
936task DMAChannel :: SetTxLPMask1(bit [63:0] data)
937{
938 bit [39:0] address;
939 bit [63:0] data_tmp0;
940 bit [63:0] Rdata0;
941 bit [63:0] memArray_addr;
942 bit [7:0] be = 8'hff;
943
944 address = TX_LOG_MASK1 + id*40'h200;
945 gen_pio_drv.pio_wr(getPIOAddress(address,dis_pio_virt) ,data);
946
947#ifdef N2_FC
948Fc_Niu_Ev2a_SetTxLPMask1(data);
949#endif
950
951 ring_lpmask1 = data;
952}
953
954task DMAChannel :: SetTxLPValue1(bit [63:0] data)
955{
956 bit [39:0] address;
957 bit [63:0] data_tmp0;
958 bit [63:0] Rdata0;
959 bit [63:0] memArray_addr;
960 bit [7:0] be = 8'hff;
961
962 address = TX_LOG_VALUE1 + id*40'h200;
963 gen_pio_drv.pio_wr(getPIOAddress(address,dis_pio_virt) ,data);
964#ifdef N2_FC
965Fc_Niu_Ev2a_SetTxLPValue1(data);
966#endif
967
968 ring_lpvalue1 = data;
969}
970
971task DMAChannel :: SetTxLPMask2(bit [63:0] data)
972{
973 bit [39:0] address;
974 bit [63:0] data_tmp0;
975 bit [63:0] Rdata0;
976 bit [63:0] memArray_addr;
977 bit [7:0] be = 8'hff;
978
979 address = TX_LOG_MASK2 + id*40'h200;
980 gen_pio_drv.pio_wr(getPIOAddress(address,dis_pio_virt) ,data);
981#ifdef N2_FC
982Fc_Niu_Ev2a_SetTxLPMask2(data);
983#endif
984 ring_lpmask2 = data;
985}
986
987task DMAChannel :: SetTxLPValue2(bit [63:0] data)
988{
989 bit [39:0] address;
990 bit [63:0] data_tmp0;
991 bit [63:0] Rdata0;
992 bit [63:0] memArray_addr;
993 bit [7:0] be = 8'hff;
994
995 address = TX_LOG_VALUE2 + id*40'h200;
996 gen_pio_drv.pio_wr(getPIOAddress(address,dis_pio_virt) ,data);
997#ifdef N2_FC
998Fc_Niu_Ev2a_SetTxLPValue2(data);
999#endif
1000
1001 ring_lpvalue2 = data;
1002}
1003
1004task DMAChannel :: SetTxLPRELOC1(bit [63:0] data)
1005{
1006 bit [39:0] address;
1007 bit [63:0] data_tmp0;
1008 bit [63:0] Rdata0;
1009 bit [63:0] memArray_addr;
1010 bit [7:0] be = 8'hff;
1011
1012 address = TX_LOG_PAGE_RELO1 + id*40'h200;
1013 gen_pio_drv.pio_wr(getPIOAddress(address,dis_pio_virt) ,data);
1014
1015#ifdef N2_FC
1016Fc_Niu_Ev2a_SetTxLPRELOC1(data);
1017#endif
1018
1019 ring_lprelo1 = data;
1020
1021}
1022
1023task DMAChannel :: SetTxLPRELOC2(bit [63:0] data)
1024{
1025 bit [39:0] address;
1026 bit [63:0] data_tmp0;
1027 bit [63:0] Rdata0;
1028 bit [63:0] memArray_addr;
1029 bit [7:0] be = 8'hff;
1030
1031 address = TX_LOG_PAGE_RELO2 + id*40'h200;
1032 gen_pio_drv.pio_wr(getPIOAddress(address,dis_pio_virt) ,data);
1033
1034#ifdef N2_FC
1035Fc_Niu_Ev2a_SetTxLPRELOC2(data);
1036#endif
1037
1038 ring_lprelo2 = data;
1039}
1040
1041task DMAChannel :: SetTxLPHANDLE(bit [63:0] data)
1042{
1043 bit [39:0] address;
1044 address = TX_LOG_PAGE_HDL + id*40'h200;
1045 gen_pio_drv.pio_wr(getPIOAddress(address,dis_pio_virt) ,data);
1046 ring_lphandle = data;
1047}
1048
1049task DMAChannel :: SetTxMBOX(bit [63:0] data)
1050{
1051 bit [39:0] address;
1052 bit [63:0] data_h;
1053 bit [63:0] data_l;
1054
1055 data_h = {42'h0,data[43:32]};
1056 address = TXDMA_MBH + id*40'h200;
1057 gen_pio_drv.pio_wr(getPIOAddress(address,dis_pio_virt) ,data_h);
1058
1059#ifdef N2_FC
1060#else
1061 repeat(10) @(posedge CLOCK);
1062#endif
1063
1064 data_l = {32'h0,data[31:6],6'h0};
1065 address = TXDMA_MBL + id*40'h200;
1066 gen_pio_drv.pio_wr(getPIOAddress(address,dis_pio_virt) ,data_l);
1067}
1068
1069task DMAChannel :: SetTxEventMask(bit [63:0] data)
1070{
1071 bit [39:0] address;
1072
1073 address = TX_ENT_MASK + id*40'h200;
1074 gen_pio_drv.pio_wr(getPIOAddress(address,dis_pio_virt) ,data);
1075}
1076
1077task DMAChannel :: InjTdmcParErr(bit [63:0] data)
1078{
1079 bit [39:0] address;
1080
1081 address = TDMC_INJ_PAR_ERR;
1082 gen_pio_drv.pio_wr(getPIOAddress(address,dis_pio_virt) ,data);
1083}
1084
1085task DMAChannel :: Read_TxCs(var bit [63:0] rd_data)
1086{
1087 bit [39:0] address;
1088
1089 address = TX_CS + id*40'h200;
1090 gen_pio_drv.pio_rd(getPIOAddress(address,dis_pio_virt) ,rd_data);
1091
1092}
1093
1094task DMAChannel :: Read_Err_LogH(var bit [63:0] rd_data)
1095{
1096 bit [39:0] address;
1097
1098 address = TX_RNG_ERR_LOGH + id*40'h200;
1099 gen_pio_drv.pio_rd(getPIOAddress(address,dis_pio_virt) ,rd_data);
1100}
1101
1102task DMAChannel :: Read_Err_LogL(var bit [63:0] rd_data)
1103{
1104 bit [39:0] address;
1105
1106 address = TX_RNG_ERR_LOGL + id*40'h200;
1107 gen_pio_drv.pio_rd(getPIOAddress(address,dis_pio_virt) ,rd_data);
1108}
1109
1110task DMAChannel :: Rd_Errlog_after_rst()
1111{
1112 bit [63:0] r_data;
1113
1114 Read_Err_LogH(r_data);
1115 if(r_data != 32'h0) {
1116 be_msg.print(e_mesg_error,"niu_tx_descp","Rd_Errlog_after_rst","ERR_LOGH not RESET\n");
1117 } else {
1118 be_msg.print(e_mesg_info,"niu_tx_descp","Rd_Errlog_after_rst","ERR_LOGH RESET\n");
1119 }
1120
1121 Read_Err_LogL(r_data);
1122 if(r_data != 32'h0) {
1123 be_msg.print(e_mesg_error,"niu_tx_descp","Rd_Errlog_after_rst","ERR_LOGL not RESET\n");
1124 } else {
1125 be_msg.print(e_mesg_info,"niu_tx_descp","Rd_Errlog_after_rst","ERR_LOGL RESET\n");
1126 }
1127
1128}
1129
1130
1131
1132task DMAChannel :: RdTxCs((integer sel = 0))
1133{
1134 bit [39:0] address;
1135 bit [63:0] rd_data;
1136 integer done = 0;
1137 integer cnt = 0;
1138
1139 if(sel == 0) { // check the status reg after mailbox update
1140
1141 while(!done) {
1142 @(posedge CLOCK);
1143
1144 repeat (50) @(posedge CLOCK);
1145 address = TX_CS + id*40'h200;
1146 gen_pio_drv.pio_rd(getPIOAddress(address,dis_pio_virt) ,rd_data);
1147
1148 if(~rd_data[29]) {
1149 done = 1;
1150 cnt = 0;
1151 } else {
1152 cnt++;
1153 if(cnt > 1000) { // assuming that the update ack come later than 2000ns from SIU_STUB
1154 be_msg.print(e_mesg_error,"niu_tx_descp","RdTxCs","MB bit not cleared after mailbox update\n");
1155 done = 1;
1156 }
1157 }
1158 }
1159
1160 } else if(sel == 1) { // check the status reg after reset update
1161 address = TX_CS + id*40'h200;
1162 gen_pio_drv.pio_rd(getPIOAddress(address,dis_pio_virt) ,rd_data);
1163 if(~rd_data[30] && rd_data[31])
1164 be_msg.print(e_mesg_error,"niu_tx_descp","RdTxCs","RST bit not cleared and/or RST_STATE not set\n");
1165
1166 } else if(sel == 2) { // check for mmk register bit
1167
1168 address = TX_CS + id*40'h200;
1169 gen_pio_drv.pio_rd(getPIOAddress(address,dis_pio_virt) ,rd_data);
1170 if(rd_data[29])
1171 be_msg.print(e_mesg_error,"niu_tx_descp","RdTxCs","MB bit not cleared after mb update\n");
1172
1173
1174 if(~rd_data[15])
1175 be_msg.print(e_mesg_error,"niu_tx_descp","RdTxCs","MK bit not set for DMA %0d\n",id);
1176
1177 if(~rd_data[14])
1178 be_msg.print(e_mesg_error,"niu_tx_descp","RdTxCs","MMK bit not set for DMA %0d\n",id);
1179 } else if(sel == 3) { // check for stop_go_State
1180
1181 while(!done) {
1182 @(posedge CLOCK);
1183
1184 repeat (50) @(posedge CLOCK);
1185 address = TX_CS + id*40'h200;
1186 gen_pio_drv.pio_rd(getPIOAddress(address,dis_pio_virt) ,rd_data);
1187
1188 if(rd_data[27]) {
1189 done = 1;
1190 cnt = 0;
1191 be_msg.print(e_mesg_info,"niu_tx_descp","RdTxCs","SNG_STATE set for DMA %0d\n",id);
1192 } else {
1193 cnt++;
1194 if(cnt >= 1000) {
1195 be_msg.print(e_mesg_error,"niu_tx_descp","RdTxCs","SNG_STATE bit not set for DMA %0d\n",id);
1196 done = 1;
1197 }
1198 }
1199 }
1200
1201 // clear the current deficit of the DMA
1202
1203 current_deficit = 0;
1204
1205 } else if(sel == 4) { // check for stop_go_State to be cleared
1206
1207 address = TX_CS + id*40'h200;
1208 gen_pio_drv.pio_rd(getPIOAddress(address,dis_pio_virt) ,rd_data);
1209 if(rd_data[27])
1210 be_msg.print(e_mesg_error,"niu_tx_descp","RdTxCs","SNG_STATE bit not reset for DMA %0d\n",id);
1211 } else if(sel == 5) { // wait until mk bit is set
1212
1213 while(!done) {
1214 @(posedge CLOCK);
1215
1216 repeat (50) @(posedge CLOCK);
1217 address = TX_CS + id*40'h200;
1218 gen_pio_drv.pio_rd(getPIOAddress(address,dis_pio_virt) ,rd_data);
1219
1220 if(rd_data[15]) {
1221 done = 1;
1222 cnt = 0;
1223 } else {
1224 cnt++;
1225 if(cnt >= 100) {
1226 be_msg.print(e_mesg_error,"niu_tx_descp","RdTxCs","MK bit not set for DMA %0d\n",id);
1227 done = 1;
1228 }
1229 }
1230 }
1231 } else if(sel == 6) { // check if mk bit gets cleared on read
1232
1233 repeat (5) @(posedge CLOCK);
1234 address = TX_CS + id*40'h200;
1235 gen_pio_drv.pio_rd(getPIOAddress(address,dis_pio_virt) ,rd_data);
1236
1237 if(rd_data[15])
1238 be_msg.print(e_mesg_error,"niu_tx_descp","RdTxCs","MK not Cleared for DMA %0d\n",id);
1239
1240 } else if(sel == 7) { // check if mk bit does not get cleared on when write to 1
1241 repeat (5) @(posedge CLOCK);
1242 address = TX_CS + id*40'h200;
1243 gen_pio_drv.pio_rd(getPIOAddress(address,dis_pio_virt) ,rd_data);
1244
1245 if(~rd_data[15])
1246 be_msg.print(e_mesg_error,"niu_tx_descp","RdTxCs","MK Cleared for DMA %0d\n",id);
1247 } else if(sel == 8) { // check both mk and mmk bit is cleared on Read
1248
1249 repeat (5) @(posedge CLOCK);
1250 address = TX_CS + id*40'h200;
1251 gen_pio_drv.pio_rd(getPIOAddress(address,dis_pio_virt) ,rd_data);
1252
1253 if(rd_data[15])
1254 be_msg.print(e_mesg_error,"niu_tx_descp","RdTxCs","MK not Cleared for DMA %0d\n",id);
1255
1256 if(rd_data[14])
1257 be_msg.print(e_mesg_error,"niu_tx_descp","RdTxCs","MMK not Cleared for DMA %0d\n",id);
1258 } else if(sel == 9) { // check if only mmk is cleared and mk is set after W1C
1259
1260 repeat (5) @(posedge CLOCK);
1261
1262 address = TX_CS + id*40'h200;
1263 gen_pio_drv.pio_rd(getPIOAddress(address,dis_pio_virt) ,rd_data);
1264
1265 if(~rd_data[15])
1266 be_msg.print(e_mesg_error,"niu_tx_descp","RdTxCs","MK Cleared for DMA %0d\n",id);
1267
1268 if(rd_data[14])
1269 be_msg.print(e_mesg_error,"niu_tx_descp","RdTxCs","MMK not Cleared for DMA %0d\n",id);
1270 } else if(sel == 10) {
1271 repeat (5) @(posedge CLOCK);
1272 address = TX_CS + id*40'h200;
1273 gen_pio_drv.pio_rd(getPIOAddress(address,dis_pio_virt) ,rd_data);
1274 }
1275
1276}
1277
1278
1279task DMAChannel :: RdTxPktCnt(var integer rtl_pkt_cnt)
1280{
1281 bit [39:0] address;
1282 bit [63:0] rd_data;
1283
1284 address = TX_CS + id*40'h200;
1285 gen_pio_drv.pio_rd(getPIOAddress(address,dis_pio_virt) ,rd_data);
1286
1287 rtl_pkt_cnt = rd_data[59:48];
1288}
1289
1290task DMAChannel :: RdTxRngHDL(var bit [63:0] hd_ptr)
1291{
1292 bit [39:0] address;
1293 bit [63:0] rd_data;
1294
1295 address = TX_RING_HDL + id*40'h200;
1296 gen_pio_drv.pio_rd(getPIOAddress(address,dis_pio_virt) ,rd_data);
1297 last_head_read = rd_data[18:3];
1298 last_head_wrap_read = rd_data[19];
1299
1300 hd_ptr = rd_data;
1301}
1302
1303task DMAChannel :: RdTxRngKick(var bit [63:0] tail_ptr)
1304{
1305 bit [39:0] address;
1306 bit [63:0] rd_data;
1307
1308 address = TX_RING_KICK + id*40'h200;
1309 gen_pio_drv.pio_rd(getPIOAddress(address,dis_pio_virt) ,rd_data);
1310 tail_ptr = rd_data;
1311}
1312
1313task DMAChannel :: RdTxRngSHHD(var bit [63:0] hd_ptr)
1314{
1315 bit [39:0] address;
1316 bit [63:0] rd_data;
1317
1318 address = TX_DMA_PRE_ST + id*40'h200;
1319 gen_pio_drv.pio_rd(getPIOAddress(address,dis_pio_virt) ,rd_data);
1320
1321 hd_ptr = rd_data;
1322}
1323
1324
1325
1326
1327task DMAChannel::create_descriptor(var CTxdescriptor desc, bit [13:0] length,bit[43:0] address, bit [3:0] num_of_desc, bit sop, bit mark, (integer pkt_page_id = 0) ){
1328
1329 desc = new(0,pkt_page_id);
1330 desc.sop = sop;
1331 desc.mark = mark;
1332 desc.num_ptr = num_of_desc;
1333 desc.tr_len = length;
1334 desc.sad = address;
1335 desc.valid = 1;
1336 printf(" SOP - %b\n", sop);
1337 printf(" MARK - %b\n", mark);
1338 printf(" NUM_PTR - %h\n", num_of_desc);
1339 printf(" DESC_ADDR - %h\n", address);
1340 printf(" Length - %d \n",length);
1341
1342}
1343
1344
1345
1346task DMAChannel::WritePackets( byte_array packets, bit[43:0] start_address,bit [13:0] length, integer curr_ptr_indx, var integer last_ptr_indx, (integer page_id=0) ) {
1347
1348
1349 integer last_word_offset;
1350 integer no_of_8bytes;
1351 integer ptr;
1352 integer i,j;
1353 bit [43:0] address;
1354 bit [43:0] tmp_address;
1355 bit [63:0] data,tmp_data;
1356 bit [7:0] be;
1357 integer first_address_offset;
1358 bit [7:0] first_address_be;
1359 integer no_of_bytes_first_line;
1360 integer stop_after_first_line;
1361 integer first_line_only;
1362 integer no_of_zbytes = 0;
1363 integer offset = 0;
1364 bit [7:0] tmp_pkt_buf[4096];
1365 integer total_len = 0;
1366 integer no_of_8byte_w = 0;
1367 integer z_ptr = 0;
1368
1369
1370 //-- ptr =0;
1371 ptr = curr_ptr_indx;
1372 address = start_address;
1373 offset = address[3:0];
1374
1375 if(offset !=0)
1376 tmp_address = address - offset;
1377 else
1378 tmp_address = address;
1379
1380 no_of_zbytes = offset/8 ? 8 + offset%8 : offset%8;
1381 printf("WriteP, no_of_Zbytes %0d\n",no_of_zbytes);
1382
1383 if(no_of_zbytes != 0)
1384 total_len = length + no_of_zbytes;
1385 else
1386 total_len = length;
1387
1388 printf("WriteP, Total_len %0d\n",total_len);
1389
1390 for(i=0;i<total_len;i++)
1391 {
1392 if(no_of_zbytes != 0) {
1393 if(i<no_of_zbytes)
1394 tmp_pkt_buf[i] = 8'h0;
1395 else
1396 tmp_pkt_buf[i] = packets.val[ptr++];
1397 } else {
1398 tmp_pkt_buf[i] = packets.val[ptr++];
1399 }
1400 }
1401
1402 no_of_8byte_w = total_len%8 ? total_len/8 + 1 : total_len/8;
1403
1404 for(j=0;j<no_of_8byte_w;j++)
1405 {
1406 data = {tmp_pkt_buf[z_ptr+7],tmp_pkt_buf[z_ptr+6],
1407 tmp_pkt_buf[z_ptr+5],tmp_pkt_buf[z_ptr+4],
1408 tmp_pkt_buf[z_ptr+3],tmp_pkt_buf[z_ptr+2],
1409 tmp_pkt_buf[z_ptr+1],tmp_pkt_buf[z_ptr]};
1410 SparseMem.WriteVMem({tmp_address[43:3],3'h0}, data,8'hff,xlate_on,page_id);
1411 tmp_address = tmp_address + 8;
1412 z_ptr = z_ptr + 8;
1413 }
1414
1415
1416 /* first_address_offset = address%8;
1417 first_address_be = 0;
1418 for(i=0;i<first_address_offset; i ++)
1419 first_address_be = first_address_be | (1<<i);
1420
1421 first_address_be = 8'hff ^ first_address_be;
1422 no_of_bytes_first_line = ( first_address_offset==0) ? 0 : (8 - first_address_offset);
1423 first_line_only = (length <8) & ( no_of_bytes_first_line >= length);
1424
1425 if(first_line_only) {
1426 tmp_data[63:0] = 64'h0;
1427 for(j=0;j<no_of_bytes_first_line;j++){
1428 tmp_data = tmp_data<<8;
1429 tmp_data = tmp_data | packets.val[ptr++];
1430 }
1431 data = {tmp_data[7:0], tmp_data[15:8], tmp_data[23:16], tmp_data[31:24], \
1432 tmp_data[39:32], tmp_data[47:40], tmp_data[55:48], tmp_data[63:56] };
1433
1434 SparseMem.WriteVMem({address[43:3],3'h0}, data,8'hff,xlate_on,page_id);
1435 // printf("DMAChannel::WritePackets DEBUG Address - %x data - %x \n",address,data);
1436 address = address + 8;
1437 } else {
1438
1439 length = length - no_of_bytes_first_line;
1440 last_word_offset = length % 8;
1441 no_of_8bytes = length/8 ;
1442 tmp_data[63:0] = 64'h0;
1443 for(j=0;j<no_of_bytes_first_line;j++){
1444 tmp_data = tmp_data<<8;
1445 tmp_data = tmp_data | packets.val[ptr++];
1446 }
1447 data = {tmp_data[7:0], tmp_data[15:8], tmp_data[23:16], tmp_data[31:24], \
1448 tmp_data[39:32], tmp_data[47:40], tmp_data[55:48], tmp_data[63:56] };
1449
1450 if(no_of_bytes_first_line!=0) {
1451 SparseMem.WriteVMem({address[43:3],3'h0}, data,8'hff,xlate_on,page_id);
1452 // printf("DMAChannel::WritePackets DEBUG Address - %x data - %x \n",address,data);
1453 address = address + 8;
1454 }
1455
1456
1457 if(length >= 8) {
1458 for( i=0;i<no_of_8bytes;i++) {
1459 tmp_data[63:0] = 0;
1460 for(j=0;j<8;j++){
1461 tmp_data = tmp_data<<8;
1462 tmp_data = tmp_data | packets.val[ptr++];
1463 }
1464 data = {tmp_data[7:0], tmp_data[15:8], tmp_data[23:16], tmp_data[31:24], \
1465 tmp_data[39:32], tmp_data[47:40], tmp_data[55:48], tmp_data[63:56] };
1466
1467 SparseMem.WriteVMem({address[43:3],3'h0}, data,8'hff,xlate_on,page_id);
1468 address = address + 8;
1469 }
1470 }
1471
1472 tmp_data[63:0] = 0;
1473 for(i=0;i<last_word_offset;i++) {
1474 tmp_data = tmp_data<<8;
1475 tmp_data = tmp_data | packets.val[ptr++];
1476 }
1477 for(i=last_word_offset;i<8;i++) {
1478 tmp_data = tmp_data<<8;
1479 }
1480 data = {tmp_data[7:0], tmp_data[15:8], tmp_data[23:16], tmp_data[31:24], \
1481 tmp_data[39:32], tmp_data[47:40], tmp_data[55:48], tmp_data[63:56] };
1482 // printf("DMAChannel::WritePackets DEBUG data - %x tmp - %x \n",data,tmp_data);
1483 if(last_word_offset) {
1484 be = last_word_offset;
1485 SparseMem.WriteVMem({address[43:3],3'h0}, data,8'hff,xlate_on,page_id);
1486 }
1487
1488 } */
1489 /* printf("DMAChannel::WritePackets DEBUG first_address_offset - %d no_of_bytes_first_line - %d start_address - %x length - %d first_address_be - %x last_word_offset - %d no_of_8bytes - %d \n" ,first_address_offset,no_of_bytes_first_line,start_address,length,first_address_be,last_word_offset,no_of_8bytes ); */
1490
1491 last_ptr_indx = ptr;
1492
1493}
1494task DMAChannel::WriteTxControlWord( bit [43:0] address, TxPacketControlWord control_word, (integer page_id=0) ) {
1495
1496 bit [127:0] data;
1497 data = control_word.get_header();
1498 SparseMem.WriteVMem(address, data[63:0],8'hff,xlate_on,page_id);
1499 SparseMem.WriteVMem(address + 8, data[127:64],8'hff,xlate_on,page_id);
1500
1501
1502}
1503
1504task DMAChannel::generate_tokens(integer my_port,integer token,CTxToken TxToken ) {
1505
1506 if(mbox_id.tx_dma_mb[id] == -1) {
1507 // Alocate Mailbox
1508 mbox_id.tx_dma_mb[id] = alloc(MAILBOX,0,1);
1509 // Check if we were succesfull allocating the mailbox
1510 if(mbox_id.tx_dma_mb[id] == 0) {
1511 printf("ERROR Could not allocate the outgoing mailbox\n",my_port);
1512 mbox_id.tx_dma_mb[id] = -1;
1513 return;
1514 }
1515 }
1516
1517 TxToken.id = token;
1518 TxToken.dma_num = id;
1519 TxTokenList.push_back(TxToken);
1520 printf(" DEBUG Sending Token -- id for DMA %d = %d\n",TxToken.id,id);
1521
1522
1523 mailbox_put( mbox_id.tx_dma_mb[id],TxToken.pgToken);
1524 printf(" Sending Token %d to tx_dma_mb - %d\n",TxToken.id,id);
1525}
1526
1527function bit [95:0] DMAChannel::gen_debug_header( bit [63:0] a,bit [63:0] r,bit [13:0] l) {
1528 bit [1:0] p;
1529 bit [4:0] d;
1530 p = this.tx_port_num; // port num
1531 d = this.id; // dma_num
1532 gen_debug_header = {d,p,a[31:0],l,r[31:0],11'h0 };
1533}
1534
1535
1536task DMAChannel :: SetPage0Registers(bit [31:0] mask,bit [31:0] value, bit [31:0] reloc)
1537{
1538 SetTxLPMask1(mask);
1539 SetTxLPValue1(value);
1540 SetTxLPRELOC1(reloc);
1541
1542}
1543
1544task DMAChannel :: SetPage1Registers(bit [31:0] mask,bit [31:0] value, bit [31:0] reloc)
1545{
1546 SetTxLPMask2(mask);
1547 SetTxLPValue2(value);
1548 SetTxLPRELOC2(reloc);
1549
1550}
1551
1552task DMAChannel :: SetPageEnables(bit page0_enable, bit page1_enable, integer func_num)
1553{
1554 bit [1:0] func;
1555
1556 func = func_num;
1557
1558 SetTxLPValid({60'h0,func,page1_enable,page0_enable});
1559
1560}
1561
1562task DMAChannel :: reset_bind_to_group( (integer dummy_g=0)) {
1563 if(NiuDMABind.tx_dma_func_bind[id] != -1) {
1564 ResetDMAGroupBind(NiuDMABind.tx_dma_func_bind[id]);
1565 }
1566}
1567
1568task DMAChannel :: bind_to_group( integer g) {
1569 bit [1:0] func_num;
1570 bit [39:0] address;
1571 bit [63:0] rd_data;
1572 bit [63:0] wr_data;
1573
1574 dis_pio_virt = 0;
1575
1576
1577 address = TX_LOG_PAGE_VLD + id*40'h200;
1578 gen_pio_drv.pio_rd(getPIOAddress(address,dis_pio_virt) ,rd_data);
1579
1580 SetDMAGroupBind(g);
1581
1582 func_num = function_no;
1583
1584 wr_data = {rd_data[63:4],func_num,rd_data[1:0]};
1585
1586 SetTxLPValid(wr_data);
1587
1588}
1589
1590task DMAChannel:: InitTXDMA(integer desc_ring_length, var bit[39:0] xlate_ring_start_address, (integer err_code = 0),(integer func_num = 0))
1591{
1592
1593bit [19:0] handle;
1594integer status0;
1595integer status1;
1596integer status2;
1597integer status3;
1598bit [31:0] mask0,value0,reloc0;
1599bit [31:0] mask1,value1,reloc1;
1600bit [39:0] ring_start_address;
1601bit [39:0] ring_staddr_4ka;
1602bit [39:0] ring_endaddr_4ka;
1603integer done = 0;
1604integer offset_64B = 0;
1605integer byte_alignment;
1606integer ring_page_id;
1607// bit [63:0] mailbox_addr;
1608integer no_of_blks_ppages = 0;
1609integer no_of_blks_fring = 0;
1610
1611no_of_blks_fring = (desc_ring_length*64)%4096 ? (desc_ring_length*64)/4096 + 1 : (desc_ring_length*64)/4096;
1612
1613no_of_blks_ppages = 2*desc_ring_length*8 + no_of_blks_fring + 1; // this one for ring and for mailbox address
1614
1615printf("InitTXDMA : total_blks_ppages for dma_id %d is no_of_blks_ppages %d\n", this.id, no_of_blks_ppages);
1616printf("InitTXDMA : num_of_blks for ring dma_id %d is no_of_blks_fring %d\n", this.id, no_of_blks_fring);
1617
1618
1619
1620func_num = function_no;// get from base class
1621
1622// set the page id
1623
1624 if(xlate_on) {
1625 page0_id = 2*id;
1626 page1_id = page0_id + 1;
1627 } else {
1628 page0_id = 0;
1629 page1_id = 0;
1630 }
1631
1632 if(xlate_on) {
1633
1634 handle = SparseMem.get_page_handle();
1635 printf("VAL_OF_PAGE HANDLE %0h\n",handle);
1636
1637 status2 = SparseMem.delete_page_contexts(page0_id);
1638
1639 // get mask,value and reloc for page0
1640
1641 if (get_plus_arg(CHECK,"TX_KICK_MODE="))
1642 status0 = SparseMem.get_page_mask(no_of_blks_ppages,0,page0_id,mask0,value0,reloc0);
1643 else
1644 status0 = SparseMem.get_page_mask(1024,0,page0_id,mask0,value0,reloc0);
1645
1646 if(status0 == -1) {
1647 return;
1648 printf("TB_ERROR\n");
1649 } else {
1650 // add the task set page0 registers
1651 printf("PG0_MASK %0h, PG0_VALUE0 %0h, PG0_RELOC0 %0h, PG0_PAGE0_ID %0h\n",
1652 mask0,value0,reloc0,page0_id);
1653
1654 // call task setpage0 registers
1655 // check for the error code and flip the
1656 // mask when error code is CONF_PART_ERR
1657
1658 // if(err_code == CONF_PART_ERROR)
1659 // SetPage0Registers(~mask0,value0,reloc0);
1660 // else
1661 SetPage0Registers(mask0,value0,reloc0);
1662 }
1663
1664 status3 = SparseMem.delete_page_contexts(page1_id);
1665
1666 // get mask,value and reloc for page1
1667
1668 if (get_plus_arg(CHECK,"TX_KICK_MODE="))
1669 status1= SparseMem.get_page_mask(no_of_blks_ppages,0,page1_id,mask1,value1,reloc1);
1670 else
1671 status1= SparseMem.get_page_mask(1024,0,page1_id,mask1,value1,reloc1);
1672
1673 if(status1== -1) {
1674 return;
1675 printf("TB_ERROR\n");
1676 } else {
1677 // add the task set page0 registers
1678 printf("PG1_MASK %0h, PG1_VALUE0 %0h, PG1_RELOC0 %0h, PG1_PAGE0_ID %0h\n",
1679 mask1,value1,reloc1,page1_id);
1680
1681 // call task page1 registers
1682 // check for the error code and flip the
1683 // mask when error code is CONF_PART_ERR
1684
1685 // if(err_code == CONF_PART_ERROR)
1686 // SetPage1Registers(~mask1,value1,reloc1);
1687 // else
1688 SetPage1Registers(mask1,value1,reloc1);
1689 }
1690
1691 // call page enable task
1692
1693// PUT a PLUS ARGS HERE
1694
1695if(get_plus_arg (CHECK,"XLATE_ERR")) {
1696 // error cases
1697 // Set up Ring Start Address
1698 byte_alignment = 64;
1699
1700 if (get_plus_arg (CHECK,"DISABLE_pg0")) {
1701 SetPageEnables(0,1,func_num);
1702 ring_page_id = page0_id;
1703
1704 if (get_plus_arg(CHECK,"TX_KICK_MODE="))
1705 ring_start_address = SparseMem.get_address(no_of_blks_fring,ring_page_id,byte_alignment);
1706 else
1707 ring_start_address = SparseMem.get_address(10,ring_page_id,byte_alignment);
1708
1709 mailbox_addr = SparseMem.get_address(1,ring_page_id,byte_alignment);
1710 } else if(get_plus_arg (CHECK,"DISABLE_pg1")) {
1711 SetPageEnables(1,0,func_num);
1712 ring_page_id = page1_id;
1713
1714 if (get_plus_arg(CHECK,"TX_KICK_MODE="))
1715 ring_start_address = SparseMem.get_address(no_of_blks_fring,ring_page_id,byte_alignment);
1716 else
1717 ring_start_address = SparseMem.get_address(10,ring_page_id,byte_alignment);
1718
1719 mailbox_addr = SparseMem.get_address(1,ring_page_id,byte_alignment);
1720 } else if(get_plus_arg (CHECK,"DISABLE_PAGES")) {
1721 SetPageEnables(0,0,func_num);
1722 ring_page_id = page0_id;
1723
1724 if (get_plus_arg(CHECK,"TX_KICK_MODE="))
1725 ring_start_address = SparseMem.get_address(no_of_blks_fring,ring_page_id,byte_alignment);
1726 else
1727 ring_start_address = SparseMem.get_address(10,ring_page_id,byte_alignment);
1728
1729 mailbox_addr = SparseMem.get_address(1,ring_page_id,byte_alignment);
1730 } else {
1731 SetPageEnables(1,1,func_num);
1732 ring_page_id = page0_id;
1733 ring_start_address = 40'h1000;
1734 mailbox_addr = SparseMem.get_address(1,ring_page_id,byte_alignment);
1735 }
1736
1737} else {
1738 // non error cases
1739 if (get_plus_arg (CHECK,"DISABLE_pg0")) {
1740 SetPageEnables(0,1,func_num);
1741 ring_page_id = page1_id;
1742 } else if(get_plus_arg (CHECK,"DISABLE_pg1")) {
1743 SetPageEnables(1,0,func_num);
1744 ring_page_id = page0_id;
1745 } else {
1746 SetPageEnables(1,1,func_num);
1747 ring_page_id = random()%2 ? page1_id : page0_id;
1748 }
1749
1750 // Set up Ring Start Address
1751
1752 if (get_plus_arg(CHECK,"TX_KICK_MODE=")) {
1753 byte_alignment = 4096;
1754 // ring_start_address = SparseMem.get_address(no_of_blks_fring,ring_page_id,byte_alignment);
1755 ring_staddr_4ka = SparseMem.get_address(no_of_blks_fring,ring_page_id,byte_alignment);
1756 ring_endaddr_4ka = ring_staddr_4ka + no_of_blks_fring*4096;
1757 while(!done) {
1758 offset_64B = random()%64;
1759 if((ring_staddr_4ka + offset_64B*64 + desc_ring_length*64) <= ring_endaddr_4ka) {
1760 done = 1;
1761 ring_start_address = ring_staddr_4ka + offset_64B*64;
1762 }
1763 }
1764 } else {
1765 byte_alignment = 64;
1766 ring_start_address = SparseMem.get_address(10,ring_page_id,byte_alignment);
1767 }
1768
1769 mailbox_addr = SparseMem.get_address(1,ring_page_id,byte_alignment);
1770 rl_mailbox_addr = SparseMem.xlate_addr(mailbox_addr,ring_page_id,0);
1771}
1772
1773 printf("Ring_start_addr for DMA_ID %d is %0h\n",this.id,ring_start_address);
1774
1775 if(ring_start_address === 40'hzz_zzzz_zzzz) {
1776 printf("TESTBENCH ERROR\n");
1777 return;
1778 }
1779
1780 // call ring config function
1781
1782 setRngConfig(ring_start_address,desc_ring_length,ring_page_id);
1783
1784 xlate_ring_start_address = SparseMem.xlate_addr(ring_start_address,ring_page_id);
1785
1786 // programe the mailbox start address
1787
1788 SetTxMBOX(mailbox_addr);
1789
1790 } else {
1791
1792 mask0 = 32'h0;
1793 // value0 = random()%1048576;
1794 value0 = 32'h0;
1795 reloc0 = random()%1048576;
1796 SetPage0Registers(mask0,value0,reloc0);
1797
1798 mask1= 32'h0;
1799 // value1 = random()%1048576;
1800 value1 = 32'h0;
1801 reloc1 = random()%1048576;
1802 SetPage1Registers(mask1,value1,reloc1);
1803
1804 SetPageEnables(1,1,func_num);
1805
1806 ring_page_id = page0_id;
1807 byte_alignment = 64;
1808
1809 // ring_start_address = SparseMem.get_address(10,ring_page_id,byte_alignment);
1810
1811 if (get_plus_arg(CHECK,"TX_KICK_MODE="))
1812 ring_start_address = SparseMem.get_address(no_of_blks_fring,ring_page_id,byte_alignment);
1813 else
1814 ring_start_address = SparseMem.get_address(10,ring_page_id,byte_alignment);
1815
1816
1817 // call ring config function
1818
1819 setRngConfig(ring_start_address,desc_ring_length,ring_page_id);
1820
1821 }
1822
1823
1824}
1825
1826task DMAChannel:: read_mailbox_addr()
1827{
1828 integer i = 0;
1829 bit [63:0] rd_addr;
1830 bit [63:0] rd_data;
1831
1832 for(i=0;i<8;i++) {
1833 rd_addr = rl_mailbox_addr + 8*i;
1834 SparseMem.ReadMem(rd_addr,rd_data,8'h0);
1835 printf("Mailbox_data %h at address %h for iteration %d\n",rd_data,rd_addr,i);
1836 }
1837}
1838
1839
1840task DMAChannel:: mailbox_update(integer mk_bit_count)
1841{
1842 bit [63:0] data;
1843 integer mbup_cnt = 0;
1844
1845 while (mbup_cnt < mk_bit_count) {
1846 // enable the mailbox update
1847 data = 64'h2000_0000;
1848 SetTxCs(data);
1849 RdTxCs(0);
1850 mbup_cnt++;
1851
1852 printf("mailbox_update : mb_update count %d for DMA %d\n",mbup_cnt,id);
1853 }
1854}
1855
1856task DMAChannel :: set_host_err_callback(bit [39:0] call_bk_addr, integer host_err_code)
1857{
1858
1859 integer status;
1860 CcbErrDfn HostErrorDfn;
1861
1862 HostErrorDfn = new();
1863 HostErrorDfn.address = {24'h0,call_bk_addr};
1864 // HostErrorDfn.error_code = SIU_CtagEccErr;
1865 HostErrorDfn.error_code = host_err_code;
1866 status = HostErrInj.SetErrorDfn(HostErrorDfn);
1867 printf("set_host_err_callback: Address - %x code - %d \n",call_bk_addr,host_err_code);
1868
1869}
1870
1871task DMAChannel :: reclaim_buffers(( integer reclaim =1), integer num_bufs_toreclaim ) {
1872
1873 if(reclaim) {
1874 desc_ring.reclaim_buffers(num_bufs_toreclaim);
1875 }
1876}
1877
1878
1879task DMAChannel :: check_rstdone((integer wait_count = 100))
1880{
1881 bit [39:0] address;
1882 bit [63:0] r_data;
1883 integer rst_done = 0;
1884 integer count = 0;
1885
1886 while(!rst_done) {
1887 address = TX_CS + id*40'h200;
1888 gen_pio_drv.pio_rd(getPIOAddress(address,dis_pio_virt) ,r_data);
1889 if(r_data[30]) {
1890 rst_done = 1;
1891 count = 0;
1892 be_msg.print(e_mesg_info,"niu_tx_descp","SetTxCs","RST_STATE set\n");
1893 } else {
1894
1895 if(count > wait_count) {
1896 rst_done = 1;
1897 count = 0;
1898 be_msg.print(e_mesg_error,"niu_tx_descp","SetTxCs","ERROR : RST_STATE not set\n");
1899 } else {
1900 count++;
1901 rst_done = 0;
1902 }
1903
1904 }
1905
1906 repeat(100) @(posedge CLOCK);
1907 }
1908
1909}
1910
1911
1912task DMAChannel :: model_cache()
1913{
1914 integer space_avail;
1915 integer kick;
1916 integer min_num;
1917 integer iter = 0;
1918 integer h_data;
1919 integer start = 0;
1920 integer count = 0;
1921 bit [39:0] call_bk_addr;
1922 bit [39:0] phy_call_bk_addr;
1923 bit [39:0] nw_phy_addr[3];
1924 integer semId[3];
1925 CcbMem cb;
1926 integer i,last_addr,no_semids,bytes_reqed;
1927
1928 VeraListIterator_CTxToken item, next_item;
1929 CTxToken Entry = new();
1930
1931 while(1) {
1932
1933 iter = 0;
1934 min_num = 0;
1935
1936 // space_avail = 16 - M_TxTokenList.size();
1937 // printf("SPACE_AVAIL %d\n",space_avail);
1938
1939 if((t_data - count) != 0){
1940
1941 if(start == 0) {
1942 h_data = 0;
1943 start = 1;
1944 item = TxTokenList.start();
1945 Entry = item.data();
1946 call_bk_addr = desc_ring.ring_start_addr + Entry.descriptor_address;
1947 phy_call_bk_addr = SparseMem.xlate_addr(call_bk_addr,desc_ring.ring_page_id,0);
1948 printf("CALL_BACK_ADDR %h in start_portion\n",phy_call_bk_addr);
1949 } else {
1950
1951 item = TxTokenList.start();
1952 Entry = item.data();
1953 call_bk_addr = desc_ring.ring_start_addr + Entry.descriptor_address;
1954 phy_call_bk_addr = SparseMem.xlate_addr(call_bk_addr,desc_ring.ring_page_id,0);
1955 printf("CALL_BACK_ADDR %h\n",phy_call_bk_addr);
1956 h_data = count;
1957 printf("H_DATA %d\n",h_data);
1958
1959 }
1960
1961 // wait until the call-back is done
1962
1963 /* semId = alloc(SEMAPHORE,0,1,0);
1964 cb = new(semId);
1965 cb.set({24'h0,phy_call_bk_addr},GOOD_PACKET);
1966 hostRdCbMgr.setCallBack(cb);
1967 printf("set_call_back in M_cache\n");
1968
1969 while(semaphore_get(WAIT,semId,1) == 0 ) {
1970 repeat(10) @(posedge CLOCK);
1971 } */
1972
1973
1974 space_avail = 16 - M_TxTokenList.size();
1975
1976 if(space_avail >= 8)
1977 space_avail = 16 - M_TxTokenList.size();
1978 else
1979 space_avail = 0;
1980
1981 kick = t_data - h_data;
1982 printf("k_DATA %d\n",kick);
1983
1984 if(kick < space_avail)
1985 min_num = kick;
1986 else
1987 min_num = space_avail;
1988
1989 printf("THE MIN_NUM %0d\n",min_num);
1990
1991 // get num of sub-reqs
1992
1993 // if(phy_call_bk_addr[5:0] == 6'h0)
1994 // last_addr = 0;
1995 // else
1996 last_addr = phy_call_bk_addr[5:0];
1997
1998 bytes_reqed = last_addr + min_num*8;
1999 no_semids = bytes_reqed%host_mtu ? bytes_reqed/host_mtu + 1 : bytes_reqed/host_mtu;
2000
2001 printf("Number of semids needed %0d\n",no_semids);
2002
2003 // wait until the call-back is done
2004
2005 for(i=0;i<no_semids;i++) {
2006 nw_phy_addr[i] = {phy_call_bk_addr[39:6],6'h0} + i*host_mtu;
2007
2008 semId[i] = alloc(SEMAPHORE,0,1,0);
2009 cb = new(semId[i]);
2010 cb.set({24'h0,nw_phy_addr[i]},GOOD_PACKET);
2011 hostRdCbMgr.setCallBack(cb);
2012 printf("set_call_back in M_cache for address %h\n",nw_phy_addr[i]);
2013 }
2014
2015 for(i=0;i<no_semids;i++) {
2016 fork {
2017 while(semaphore_get(WAIT,semId[i],1) == 0 ) {
2018 repeat(10) @(posedge CLOCK);
2019 }
2020 }
2021 join all
2022 }
2023
2024
2025
2026 // repeat(10) @(posedge CLOCK);
2027
2028 // printf("THE MIN_NUM %0d\n",min_num);
2029
2030 while(iter < min_num) {
2031
2032 // item = TxTokenList.start();
2033 // Entry = item.data();
2034 Entry = TxTokenList.front();
2035 Entry.valid = 1;
2036
2037 M_TxTokenList.push_back(Entry);
2038 TxTokenList.pop_front();
2039
2040 // item.next();
2041 iter = iter + Entry.NoofGathers;
2042 count = count + Entry.NoofGathers;
2043
2044 }
2045 printf("CNT_OF_DESC READ %0d\n",count);
2046
2047 }
2048 @(posedge CLOCK);
2049 }
2050}
2051
2052task DMAChannel :: stop_unstall_dma(integer no_of_times)
2053{
2054
2055integer i = 0;
2056bit [63:0] rd_data;
2057bit [63:0] wr_data;
2058
2059 while(!no_of_times) {
2060 // wait for random time
2061 repeat (random()%500) @(posedge CLOCK);
2062
2063 // rd modify write
2064
2065 Read_TxCs(rd_data);
2066
2067 wr_data = {rd_data[63:29],1'b1,rd_data[27:0]};
2068
2069 // stop the dma
2070 // SetTxCs(64'h0000_0000_1000_0000);
2071 SetTxCs(wr_data);
2072
2073 // wait for the dma to go to stop_state
2074 RdTxCs(3);
2075
2076 // rd modify write
2077
2078 Read_TxCs(rd_data);
2079
2080 wr_data = {rd_data[63:29],1'b0,rd_data[27:0]};
2081
2082 // wait for random time to unstall
2083 repeat (random()%500) @(posedge CLOCK);
2084
2085 // SetTxCs(64'h0000_0000_0000_0000);
2086 SetTxCs(wr_data);
2087
2088 i++;
2089 }
2090}
2091
2092
2093task DMAChannel :: stop_dma()
2094{
2095
2096 bit [39:0] address;
2097 bit [63:0] r_data;
2098 bit [63:0] w_data;
2099
2100 address = TX_CS + id*40'h200;
2101 gen_pio_drv.pio_rd(getPIOAddress(address,dis_pio_virt),r_data);
2102
2103 w_data = r_data | 64'h0000_0000_1000_0000;
2104
2105 // stop the dma
2106 SetTxCs(w_data);
2107
2108 // wait for the dma to go to stop_state
2109 RdTxCs(3);
2110
2111}
2112
2113task DMAChannel :: reset_dma()
2114{
2115 bit [39:0] address;
2116 bit [63:0] r_data;
2117 bit [63:0] w_data;
2118 integer rst_done = 0;
2119 integer count = 0;
2120
2121 cont_kick_done= 1; // stop kicking due to reset
2122
2123 address = TX_CS + id*40'h200;
2124 gen_pio_drv.pio_rd(getPIOAddress(address,dis_pio_virt),r_data);
2125
2126 w_data = (r_data | 64'h8000_0000) & 64'hffff_ffff_efff_ffff;
2127
2128
2129 SetTxCs(w_data);
2130
2131 reset_done = 1;
2132 printf("DMAChannel :: reset_dma reset_done - %d %d \n",id,reset_done);
2133
2134}
2135
2136
2137task DMAChannel :: reinit_dma(integer ring_len)
2138{
2139 bit [39:0] brng_addr;
2140
2141 xlate_on = 1;
2142 InitTXDMA(ring_len,brng_addr);
2143}
2144
2145task DMAChannel :: reset_reinit_dma(integer ring_len, integer no_of_times)
2146{
2147
2148 integer j = 0;
2149
2150 while(j != no_of_times) {
2151 // reset the dma
2152 repeat (random()%20) @(posedge CLOCK);
2153
2154 reset_dma();
2155
2156 // reinit the dma
2157
2158 repeat (random()%20) @(posedge CLOCK);
2159 reinit_dma(ring_len);
2160
2161 j++;
2162
2163}
2164}
2165
2166task DMAChannel :: Check_TxCs(string err_code, (integer chk_set=0),(integer chk_clr = 0))
2167{
2168
2169 bit [63:0] rd_data;
2170
2171 case(err_code) {
2172 "Mbox_Error" : {
2173
2174 if(chk_set) {
2175 Read_TxCs(rd_data);
2176 // check to see if the mbox_err bit set
2177 if(~rd_data[7])
2178 be_msg.print(e_mesg_error,"niu_tx_descp","Check_TxCs","Mbox_Err not set\n");
2179 }
2180
2181 if(chk_clr) {
2182 Read_TxCs(rd_data);
2183 // do a read back to check if mbox err cleared
2184 if(rd_data[7])
2185 be_msg.print(e_mesg_error,"niu_tx_descp","Check_TxCs","Mbox_Err not Clrd\n");
2186 }
2187 }
2188
2189 "Nack_Pref_Error" : {
2190
2191 if(chk_set) {
2192 Read_TxCs(rd_data);
2193 // check to see if the nack_pref_err bit set
2194 if(~rd_data[3])
2195 be_msg.print(e_mesg_error,"niu_tx_descp","Check_TxCs","Nack_pref_Err not set\n");
2196 }
2197
2198 if(chk_clr) {
2199 Read_TxCs(rd_data);
2200 // do a read back to check if nack_repf err cleared
2201 if(rd_data[7])
2202 be_msg.print(e_mesg_error,"niu_tx_descp","Check_TxCs","Nack_pref_Err not Clrd\n");
2203 }
2204
2205 }
2206 "Conf_Part_Error" : {
2207
2208 if(chk_set) {
2209 Read_TxCs(rd_data);
2210 // check to see if the conf_part_err bit set
2211 if(~rd_data[1])
2212 be_msg.print(e_mesg_error,"niu_tx_descp","Check_TxCs","Conf_Part_Err not set\n");
2213 }
2214
2215 // do a read back to check if nack_pref err cleared
2216 if(chk_clr) {
2217 Read_TxCs(rd_data);
2218 // check to see if the conf_part_err bit clrd
2219 if(rd_data[1])
2220 be_msg.print(e_mesg_error,"niu_tx_descp","Check_TxCs","Conf_Part_Err not clrd\n");
2221 }
2222
2223 }
2224 "PSize_Error" : {
2225 // check to see if the pkt_sz_err bit set
2226 if(chk_set) {
2227 Read_TxCs(rd_data);
2228 // check to see if the pkt_sz_err bit set
2229 if(~rd_data[6])
2230 be_msg.print(e_mesg_error,"niu_tx_descp","Check_TxCs","Pkt_Sz_Err not set\n");
2231 }
2232
2233 // do a read back to check if pkt_sz_err cleared
2234 if(chk_clr) {
2235 Read_TxCs(rd_data);
2236 // do a read back to check if pkt_sz_err cleared
2237 if(rd_data[6])
2238 be_msg.print(e_mesg_error,"niu_tx_descp","Check_TxCs","Pkt_Sz_Err not Clrd\n");
2239 }
2240 }
2241 }
2242}
2243
2244task DMAChannel :: Wr_TDMCIntrDbg(bit [63:0] data)
2245{
2246 bit [39:0] address;
2247
2248 address = TDMC_INTR_DBG + id*40'h200;
2249 gen_pio_drv.pio_wr(address,data);
2250}
2251
2252task DMAChannel:: chng_no_of_desc_qued(integer val,integer what) {
2253
2254 semaphore_get(WAIT, desc_random_kick_semid, 1);
2255 if(what==0) {
2256 descriptors_queued = descriptors_queued - val;
2257 } else {
2258 descriptors_queued = descriptors_queued + val;
2259 }
2260 printf(" DMA - %d descriptors_queued - %d what = %d val - %d \n",id,descriptors_queued,what,val);
2261
2262 semaphore_put(desc_random_kick_semid, 1);
2263
2264
2265}
2266task DMAChannel:: ContTxPacketGen(TxPacketGenConfig PktGenConfig) {
2267 if(!cont_kick_done) {
2268 PktGenConfig.SetGatherFields();
2269 // PktGenConfig.printGatherFields();
2270
2271 chng_no_of_desc_qued(PktGenConfig.gConfig_noOfDesc,1);
2272 PktGenConfigQueue.push_back(PktGenConfig);
2273 }
2274}
2275function integer DMAChannel:: getMaxTobeKicked() {
2276 integer ring_is_empty,ring_is_full;
2277
2278 ring_is_empty = (last_kicked_tail_wrap==last_head_wrap_read) && ( last_kicked_tail==last_head_read);
2279 ring_is_full = (last_kicked_tail_wrap!=last_head_wrap_read) && ( last_kicked_tail==last_head_read);
2280 if(ring_is_empty) {
2281 getMaxTobeKicked = 8*ring_size;
2282 } else if(ring_is_full) {
2283 getMaxTobeKicked = 0;
2284 } else {
2285 if(last_kicked_tail_wrap==last_head_wrap_read) {
2286 getMaxTobeKicked = 8*ring_size - (last_kicked_tail-last_head_read);
2287 } else {
2288 getMaxTobeKicked = last_head_read-last_kicked_tail;
2289 }
2290 }
2291}
2292function integer DMAChannel:: getHeadTailDiff() {
2293 bit[63:0] h;
2294 RdTxRngHDL(h); // This can heppen through a mailbox read or a pio read
2295 printf("last_kicked_tail - %d last_head_read - %d\n",last_kicked_tail,last_head_read);
2296 if(last_kicked_tail_wrap==last_head_wrap_read) {
2297 getHeadTailDiff = (last_kicked_tail-last_head_read);
2298 } else {
2299 getHeadTailDiff = 8*ring_size - (last_head_read-last_kicked_tail);
2300 }
2301
2302}
2303
2304task DMAChannel:: ContRandomKick(integer maxthreshold, integer min_head_tail_diff) {
2305
2306 integer max_pkts_availableforkick,descriptorstobekicked,kick,max_desc_tobekicked;
2307 integer reached_end,descriptors_kicked_sofar;
2308 integer head_tail_diff;
2309 bit [63:0] h,t;
2310 TxPacketGenConfig PktGenConfig;
2311 integer pkt_page_id;
2312
2313 while(!cont_kick_done) {
2314 while(PktGenConfigQueue.empty()) {
2315 repeat(100)@(posedge CLOCK);
2316 }
2317 // list has data
2318 // find out how much can be kicked
2319 // This is tail -head
2320
2321 max_desc_tobekicked= getMaxTobeKicked();
2322
2323
2324 // max_pkts_availableforkick = PktGenConfigQueue.size();
2325 max_pkts_availableforkick = descriptors_queued;
2326
2327 // descriptorstobekicked = minimum( maxthreshold,max_desc_tobekicked,max_pkts_availableforkick);
2328 printf("DEBUG DMA - %d maxthreshold -%d max_desc_tobekicked -%d max_pkts_availableforkick -%d \n",id,maxthreshold,max_desc_tobekicked,max_pkts_availableforkick);
2329 if(maxthreshold>max_desc_tobekicked) {
2330 if(max_pkts_availableforkick>max_desc_tobekicked) {
2331 descriptorstobekicked = max_desc_tobekicked;
2332 } else {
2333 descriptorstobekicked = max_pkts_availableforkick;
2334 }
2335 } else {
2336 if(max_pkts_availableforkick>maxthreshold) {
2337 descriptorstobekicked = maxthreshold;
2338 } else {
2339 descriptorstobekicked = max_pkts_availableforkick;
2340 }
2341 }
2342
2343 kick = random()%descriptorstobekicked;
2344 printf("kick determied - %d \n",kick);
2345
2346 // start poping from PktGenConfigQueue, for every pktgenconfig find out how many descriptors are needed and have
2347 // a running counter
2348 reached_end = 0;
2349 descriptors_kicked_sofar = 0;
2350 while(!reached_end) {
2351 PktGenConfig = PktGenConfigQueue.front();
2352// This is a tmp hack only
2353
2354 pkt_page_id = (random()%2) ? page0_id : page1_id;
2355 no_of_descriptors = PktGenConfig.gConfig_noOfDesc;
2356
2357 if ((descriptors_kicked_sofar+no_of_descriptors)>kick) {
2358
2359 if((descriptors_kicked_sofar+no_of_descriptors)>descriptorstobekicked) {
2360
2361 reached_end = 1;
2362 // next time. do not kick this time
2363 printf("quiting!! DMA - %d descriptors_kicked_sofar - %d no_of_descriptors- %d descriptorstobekicked - %d\n",id,descriptors_kicked_sofar,no_of_descriptors,descriptorstobekicked);
2364
2365 } else {
2366
2367 semaphore_get(WAIT,mbox_id.semphore_txpktgen_id,1);
2368 gen_txGatherPackets(PktGenConfig,pkt_page_id);
2369 semaphore_put(mbox_id.semphore_txpktgen_id,1);
2370
2371 descriptors_kicked_sofar= descriptors_kicked_sofar + no_of_descriptors;
2372 PktGenConfigQueue.pop_front();
2373 chng_no_of_desc_qued(PktGenConfig.gConfig_noOfDesc,0);
2374
2375 }
2376 } else {
2377
2378 semaphore_get(WAIT,mbox_id.semphore_txpktgen_id,1);
2379 gen_txGatherPackets(PktGenConfig,pkt_page_id);
2380 semaphore_put(mbox_id.semphore_txpktgen_id,1);
2381
2382 descriptors_kicked_sofar= descriptors_kicked_sofar + no_of_descriptors;
2383 PktGenConfigQueue.pop_front();
2384 chng_no_of_desc_qued(PktGenConfig.gConfig_noOfDesc,0);
2385
2386 }
2387 printf("DMA - %d descriptors_kicked_sofar - %x max - %d no_of_descriptors - %d queue size - %d \n",id,descriptors_kicked_sofar,kick,no_of_descriptors,PktGenConfigQueue.size());
2388 if(descriptors_kicked_sofar>=kick) {
2389 // exit
2390 reached_end = 1;
2391 } // else continue
2392 if(PktGenConfigQueue.empty()) {
2393 // exit at the end of the queue
2394 reached_end = 1;
2395 }
2396 }
2397 setTxRingKick(desc_ring.ring_current_addr);
2398 // wait for head pointer to move before moving on
2399
2400 head_tail_diff = getHeadTailDiff();
2401 printf("Head- Tail Diff - %d \n",head_tail_diff);
2402 while(head_tail_diff >=min_head_tail_diff) {
2403 // wait
2404 repeat(1000)@(posedge CLOCK);
2405 head_tail_diff = getHeadTailDiff();
2406 printf("Head- Tail Diff - %d \n",head_tail_diff);
2407 }
2408 repeat(100)@(posedge CLOCK);
2409 }
2410}