Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / verif / env / niu / rxc_sat / vera / rxdma / niu_rxdmc.vr
CommitLineData
86530b38
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: niu_rxdmc.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 "niu_rx_descp.vrh"
39#include "niu_rxtoken.vrh"
40#include "mbox_class.vrh"
41#include "get_mbox_id.vrh"
42extern mbox_class mbox_id;
43extern niu_gen_pio gen_pio_drv;
44extern CSparseMem SparseMem;
45
46/* These classes/file is to embedd the DMA classes, DRR, and other stuff related to RDMC
47 the inputs into this class would be the mbox from pktgen and output would be the stream going
48 into the memory checker
49
50
51*/
52
53
54class CRdmcToken {
55 CRxToken RxToken; // This comes from pktgen
56
57 // To add more fields
58}
59MakeVeraList(CRdmcToken) // list of descriptors
60
61class CRxPortDRRInterface {
62 bit [3:0] ports_active; // No of active ports
63 integer NoOfPorts; // No of Ports attached
64 integer started ;
65 integer enable_sb =0;
66
67 local integer PortDRRWeight[4];
68 local integer PortDRRDeficit[4];
69
70 VeraList_CRdmcToken DrrTokenList[4];
71 VeraList_CRdmcToken DrrResultList;
72
73 task new( bit [3:0] ports) {
74 integer i;
75 ports_active = ports ;
76 NoOfPorts = 2;// to be derived at the config time
77 started = 0;
78 for(i=0;i<NoOfPorts; i ++) {
79 DrrTokenList[i] = new();
80 PortDRRWeight[i] = 16'h400*16;
81 }
82 DrrResultList = new();
83
84 fork {
85 getRxToken();
86 PortDRR();
87 } join none
88
89 started = 1;
90
91 if (get_plus_arg (CHECK, "RX_DROP_PKT_CHECK"))
92 enable_sb = 1;
93 else
94 enable_sb = 0;
95
96 }
97
98 // local function integer getTokenHead( var CRdmcToken RdmcToken, integer id);
99 task SetPortsActive(integer num);
100 task ProgramDRRWeight(integer port_num, integer weight);
101 local task getRxToken();
102 local task addToken( CRdmcToken RdmcToken, integer i);
103 local task getToken(integer i);
104 local task PortDRR();
105 local function integer check_active(integer id,integer port_id);
106 local function integer update_deficit(integer id, integer length);
107 local function bit[3:0] getActiveList();
108
109 local task add_drr_credits(integer i);
110
111 function integer getDRRResult( var CRdmcToken RdmcToken );
112 task SetPortDrrWeight(integer w, integer id) {
113 PortDRRWeight[id] = w*16;
114 }
115
116}
117
118function integer CRxPortDRRInterface::check_active ( integer j, integer activeList) {
119 // returns 1 if jth bit in the ActiveList is set else returns 0
120 integer tmp;
121 tmp = 1 <<j;
122 if(activeList & tmp) check_active = (1);
123 else check_active = (0);
124
125}
126function integer CRxPortDRRInterface::update_deficit(integer id, integer length) {
127 PortDRRDeficit[id] = PortDRRDeficit[id] - length;
128 printf(" RxDRR DEBUG Credits Spent for PORT %d New Credits = %d \n",id,PortDRRDeficit[id]);
129 if(PortDRRDeficit[id] <=0) update_deficit = 0;
130 else update_deficit = 1;
131}
132task CRxPortDRRInterface::add_drr_credits(integer i) {
133 if(PortDRRWeight[i] == -1) {
134 printf("ERROR-- DRR Weights Not programmed for PORT %d \n",i);
135 }
136 PortDRRDeficit[i] = PortDRRDeficit[i] + PortDRRWeight[i] ;
137 // printf(" RxDRR DEBUG Added Credits to PORT %d New Credits = %d \n",i,PortDRRDeficit[i]);
138}
139
140function bit[3:0] CRxPortDRRInterface::getActiveList() {
141
142integer i;
143bit[3:0] active_list;
144active_list = 0;
145
146 for(i =0;i<NoOfPorts;i++) {
147 active_list[i] = ( DrrTokenList[i].empty()!=1) ;
148 }
149 getActiveList = active_list;
150 //printf("CRxPortDRRInterface::getActiveList - %x \n",getActiveList);
151
152}
153
154function integer CRxPortDRRInterface::getDRRResult( var CRdmcToken RdmcToken) {
155
156 integer status;
157 if(DrrResultList.empty() ) {
158 status = 0;
159 RdmcToken = null;
160 } else {
161 RdmcToken = DrrResultList.front();
162 DrrResultList.pop_front();
163 printf(" RxDRR POP from port# -Token - id - %d Size - %d \n",RdmcToken.RxToken.id,DrrResultList.size());
164
165 status = 1;
166 }
167 getDRRResult = status;
168
169// Need to expand this
170
171
172
173}
174
175
176task CRxPortDRRInterface::getRxToken() {
177
178// Read from mbox from pkt gen and add it to DrrTokenList
179
180/*
181
182 while(1) {
183 for(each port_id) {
184 fork {
185 RxToken = mailbox_get();
186 // do any misc checking if needed
187 DrrTokenList[port_id].push_back();
188 } join none
189 }
190 }
191
192*/
193
194 shadow integer i;
195
196 for(i = 0;i < NoOfPorts; i ++) {
197 if(ports_active[i]) {
198 fork {
199 getToken(i);
200 } join none
201 }
202 }
203}
204
205task CRxPortDRRInterface::addToken( CRdmcToken RdmcToken, integer i) {
206
207 DrrTokenList[i].push_back(RdmcToken);
208 printf(" Current Size of DrrTokenList - %d for Port %d \n",DrrTokenList[i].size(),i);
209
210}
211
212
213task CRxPortDRRInterface::getToken(integer i) {
214
215 CRxToken RxToken;
216 CRxToken RxToken_sb;
217 CRdmcToken RdmcToken;
218 integer no_of_tkns;
219
220 printf(" Start getToken in RDMC for Port %d \n",i);
221
222 while(1) {
223 no_of_tkns = mailbox_get(WAIT,mbox_id.niu_rxpath_mb[i], RxToken);
224 printf(" No of Tokens left for port %d = %d \n",i, no_of_tkns);
225
226 if(RxToken == null) {
227 printf("ERROR CRxPortDRRInterface::getToken -Failed for port id %d\n",i);
228 return;
229 }
230
231 if(enable_sb) {
232 RxToken_sb = RxToken.object_copy();
233 mailbox_put(mbox_id.niu_rxpath_sb[i],RxToken_sb);
234
235 } else {
236 RdmcToken = new();
237 RdmcToken.RxToken = new RxToken;
238 addToken(RdmcToken,i);
239 }
240
241 }
242
243
244}
245task CRxPortDRRInterface::PortDRR() {
246
247 /*
248
249 for each port {
250 status = RxDrrIntf.getTokenHead( head, port_id) ;
251 weight associated with the port is in PortDRRWeight[id]
252 if(status== VALID) {
253 //Arbitrate---- This is implementaion dependent
254
255 }
256 SendOutput to DrrResultList
257 }
258 */
259CRdmcToken RdmcToken ;
260integer port_id;
261bit[3:0] active_list = 0;
262integer arb_id,old_arb_id;
263integer i,match_found;
264integer iter;
265integer status;
266integer maintain_active_state;
267integer length;
268
269
270// In the absence of DRR
271old_arb_id = 0;
272for(i =0;i<NoOfPorts;i++) {
273 PortDRRDeficit[i] = 0;
274}
275
276 while(1) {
277
278 // active_list = wait_for_active();
279 active_list = getActiveList();
280 while(active_list == 4'h0 ) { // Wait here if none of these had any packet
281 @(posedge CLOCK);
282 active_list = getActiveList();
283 }
284
285 ports_active = 0;
286 for(i = 0; i < NoOfPorts; i ++) {
287 if(active_list[i]) {
288 ports_active = ( ports_active | ( 1<< i ));
289 if(PortDRRDeficit[i]<=0) {
290 add_drr_credits(i);
291 }
292 } else {
293 // printf("Rx TokenList Empty\n");
294 }
295 }
296
297 while(ports_active) {
298 arb_id = old_arb_id ;
299 port_id = -1;
300 match_found =0;
301 iter =0;
302
303 printf("RxDRR DEBUG:Before While Arb id - %d iter - %d ports_active - %x \n",arb_id,iter,ports_active);
304 while( (iter <NoOfPorts /*MAX_NO_OF_PORTS*/) & ( !match_found)) {
305 if(check_active(arb_id,ports_active)) {
306 port_id = arb_id;
307 match_found = 1;
308
309 }
310 arb_id = (arb_id + 1)%NoOfPorts;
311 iter++;
312 //printf("RxDRR DEBUG: Arb id - %d iter - %d ports_active - %x \n",arb_id,iter,ports_active);
313 } // At the end of this there should be at least one port_id selected
314
315 if( (port_id == -1) ) {
316
317 exit(0);
318 return;
319 }
320
321 if(DrrTokenList[port_id].empty() ) {
322 status = 0;
323 ports_active = 0;
324 }else {
325 RdmcToken = DrrTokenList[port_id].front();
326 status = 1; // Status will be set to -1, if any errors are to be detected
327 // and the ports is set to inactive
328 }
329
330 maintain_active_state = 1;
331 if(status == -1) {
332 maintain_active_state = 0;
333 } else if(status ==1 ){
334 if(PortDRRDeficit[port_id] > 0) {
335 length = RdmcToken.RxToken.pkt_length;
336 maintain_active_state = update_deficit(port_id,length); //
337 printf(" RxDRR Received Token - id - %d dma_num - %d \n",RdmcToken.RxToken.id,RdmcToken.RxToken.dma_num);
338 DrrTokenList[port_id].pop_front();
339 DrrResultList.push_back(RdmcToken);
340 printf(" RxDRR Sent from port# - %d Token - id - %d Size - %d \n",port_id,RdmcToken.RxToken.id,DrrResultList.size());
341 } else {
342 maintain_active_state = 0;
343 printf("RxDRR DEBUG PORT# %d In deficit Need more credit \n",port_id);
344 }
345 }
346
347 if(maintain_active_state==0) {
348 // printf(" RxDRR DEBUG - Before deleting ports_active = %x \n",ports_active);
349 ports_active = ports_active ^ ( 1 << port_id );
350 // printf(" RxDRR DEBUG - After deleting ports_active = %x \n",ports_active);
351 old_arb_id = (port_id + 1) %NoOfPorts ;
352 }
353 }
354 @(posedge CLOCK);
355 // old_arb_id = 0;
356
357 }
358}
359
360task CRxPortDRRInterface::ProgramDRRWeight(integer port_num, integer weight) {
361
362 case(port_num) {
363 0: { gen_pio_drv.pio_wr(PT_DRR_WT0,weight);
364 PortDRRWeight[port_num] = 16*weight;
365 }
366 1: { gen_pio_drv.pio_wr(PT_DRR_WT1,weight);
367 PortDRRWeight[port_num] = 16*weight;
368 }
369 2: { gen_pio_drv.pio_wr(PT_DRR_WT2,weight);
370 PortDRRWeight[port_num] = 16*weight;
371 }
372 3: { gen_pio_drv.pio_wr(PT_DRR_WT3,weight);
373 PortDRRWeight[port_num] = 16*weight;
374 }
375 default: { }
376 }
377}
378
379class CRDMC {
380 bit [3:0] active_ports;
381 bit [3:0] PortDefDma[4]; // 4 Registers present in RDMC
382 bit [3:0] L2DefDma[4]; // 4 Registers present in ZCP
383 RxDMAChannel rx_dma[32];
384 CRxPortDRRInterface RxDrrIntf;
385 local VeraList_CRdmcToken RdmcTokens;
386 local task ProcessDRROutput();
387 local task SendTokenForCheck(CRxToken RxToken);
388
389 task SetPortsActive(integer num);
390 task new();
391 task start(bit [3:0] port_list);
392 task InitRXDMA(integer dma_ch_num, integer desc_ring_length, integer compl_ring_len, bit [63:0] rbr_config_B_data, bit [15:0] initial_kick, (integer xlation = 1));
393 task SetPage0Registers (integer dma_chnl, bit [31:0] mask,bit [31:0] value, bit [31:0] reloc);
394 task BindDmaIntrDev( RxDMAChannel RxDma, integer i );
395 task ProgramPortDefDma(bit [1:0] port_id, bit [3:0] dma_num);
396 task ProgramL2DefDma(bit [1:0] port_id, bit [3:0] dma_num);
397 function bit [3:0] getPortDefDma(bit [1:0] port_id);
398 function bit [3:0] getL2DefDma(bit [1:0] port_id);
399 task resetDMA(integer dma_num);
400}
401
402task CRDMC::new() {
403
404 integer i;
405 string init_mac_ports,temp_port;
406 bit[31:0] get_mac_port;
407 bit [3:0] ports_active;
408
409 for(i = 0 ; i < 32; i ++) {
410 rx_dma[i]=new(i,"Rx"); // power up as inactive
411 }
412
413if (get_plus_arg( CHECK, "CHKR_AUTO_UPDATE_RCR_HEAD")) {
414 for(i = 0 ; i < 32; i ++) {
415 if(mbox_id.niu_rxpath_rcr_update[i] == -1) {
416 mbox_id.niu_rxpath_rcr_update[i] = alloc(MAILBOX,0,1);
417 }
418 }
419}
420
421 RdmcTokens = new();
422 active_ports = 0;
423 if( get_plus_arg( CHECK, "GET_MAC_PORTS="))
424 get_mac_port = get_plus_arg( STR, "GET_MAC_PORTS=");
425 init_mac_ports.bittostr(get_mac_port);
426 for (i=0; i<init_mac_ports.len();i++) {
427 temp_port =init_mac_ports.substr(i,i);
428 ports_active[i]=( temp_port.atoi()== i) ;
429 }
430
431 printf ("niu_rxdmc.vr: From +GET_MAC_PORTS, ports_active = %b\n", ports_active);
432 active_ports = 4'b0011;
433 for(i = 0 ; i < 4; i ++) {
434 PortDefDma[i] = 0;
435 L2DefDma[i] = 0;
436 }
437 printf ("niu_rxdmc.vr: final active_ports = %b\n", active_ports);
438 RxDrrIntf = new(active_ports);
439 fork {
440 ProcessDRROutput ();
441 } join none
442
443}
444
445task CRDMC::resetDMA(integer dma_num) {
446 bit [39:0] address;
447 bit [63:0] rd_data;
448 bit rst_done = 0;
449 integer ret;
450
451 address = RXDMA_CFIG1 + dma_num*40'h200;
452 rd_data = 64'h0;
453 rd_data[30] = 1; // reset bit
454 gen_pio_drv.pio_wr(address,rd_data);
455 printf ("RxDMAChannel::resetRxDma() Time %0d, DMA - %0d was just reset\n", {get_time(HI),get_time(LO)}, dma_num);
456
457 printf ("RxDMAChannel::resetRxDma() Time %0d, Polling on reset_done ... DMA - %0d\n", {get_time(HI),get_time(LO)}, dma_num);
458
459 while(!rst_done) {
460 repeat(100) @(posedge CLOCK);
461 address = RXDMA_CFIG1 + dma_num*40'h200;
462 gen_pio_drv.pio_rd(address,rd_data);
463 rst_done = !rd_data[30];
464 }
465 printf ("RxDMAChannel::resetRxDma() Time %0d, Reset_done! Flushing the Verif State for DMA - %0d\n",
466 {get_time(HI),get_time(LO)}, dma_num);
467
468 rx_dma[dma_num] = new(dma_num,"Rx");
469 ret = SparseMem.delete_page_contexts(64+(2*dma_num));
470 ret = SparseMem.delete_page_contexts(64+(2*dma_num+1));
471
472}
473
474task CRDMC::ProgramPortDefDma(bit [1:0] port_id, bit [3:0] dma_num){
475 // Initiate the PIO Write to RTL, and update the shadow as well
476 case(port_id){
477 0: gen_pio_drv.pio_wr(DEF_PTO_RDC, {60'h0,dma_num});
478 1: gen_pio_drv.pio_wr(DEF_PT1_RDC, {60'h0,dma_num});
479 default: printf ("WARNING: CRDMC::ProgramPortDefDma() Invalid port_id %0d\n", port_id);
480 }
481 // Update the shadow
482 PortDefDma[port_id] = dma_num;
483}
484
485function bit [3:0] CRDMC::getPortDefDma(bit [1:0] port_id){
486 getPortDefDma = PortDefDma[port_id];
487}
488
489task CRDMC::BindDmaIntrDev( RxDMAChannel RxDma, integer i ){
490 rx_dma[i]= RxDma;
491 printf(" CRDMC::BindDmaIntrDev RxDMA Channel - %d Bound as Logical DeviceId - %d \n",i,rx_dma[i].dev_id);
492}
493task CRDMC::start(bit [3:0] port_list) {
494
495 integer i;
496 active_ports = port_list;
497/* DUMMY DO NOT USE*/
498
499}
500
501
502task CRDMC::SendTokenForCheck(CRxToken RxToken) {
503 mailbox_put(mbox_id.niu_rxpacket_memchk_mb,RxToken);
504}
505
506task CRDMC::ProcessDRROutput () {
507
508/*
509
510 gets the tokens from DRR , based upon the dma number- checks with the DMA class about the
511 its status
512 The functions in the DMA class has to return the address and the status associated with this
513
514
515 while(1) {
516
517 while(DrrResultList == empty) {
518 wait();
519 }
520
521 DRRstatus = RxDrrIntf.getDRRResult(RxToken);
522 if(DRRstatus == VALID) {
523
524 dma_num = RxToken.dma_num;
525
526 status = RxDma[dma_num].checkStatus(token);
527
528 if(status == DMA_NOT_ENABLED) {
529 //Take appropriate action -- such as choose default dma - ?
530
531 SetTokenToDropPacket();
532 } else if( status == COMPLETION_FULL) {
533 //Take appropriate action -- such as choose default dma - ?
534
535 SetTokenToDropPacket();
536
537 } else if(status == VALID) {
538
539 AddressStatus = RxDma[dma_num].GetPacketAddress(Token);
540 // CheckStatus for caselike not more descriptor?
541 // etc etc.
542
543 SetAddress(Token);
544 ForwardToken(Token);
545 }
546 }
547 }
548
549
550*/
551
552
553CRdmcToken RdmcToken;
554integer DMAState;
555integer dma_num;
556
557integer address_status;
558
559bit [63:0] packet_start_address;
560bit [63:0] packet_end_address;
561integer status;
562
563while(RxDrrIntf.started == 0) {
564// wait
565@(posedge CLOCK);
566}
567
568while(1) {
569
570
571 status = 0;
572 while (status ==0) {
573 status = RxDrrIntf.getDRRResult(RdmcToken);
574 // if(status == 1) {
575 // printf(" Status - 1 Token Received from DRR - id - %d - dma - %d \n",RdmcToken.RxToken.id,RdmcToken.RxToken.dma_num);
576 // }
577 @(posedge CLOCK);
578 }
579 printf(" Token Received from DRR - id - %d - dma - %d \n",RdmcToken.RxToken.id,RdmcToken.RxToken.dma_num);
580
581 dma_num = RdmcToken.RxToken.dma_num;
582 if(RdmcToken.RxToken.pkt_length<=56) {
583 printf("<%0d> CRxPortDRRInterface::getToken: rtl will drop runt pkts len<=56B, pkt ID %0d, pkt length:%0d\n",
584 get_time(LO),RdmcToken.RxToken.pgToken.gId, RdmcToken.RxToken.pkt_length);
585 RdmcToken.RxToken.pkt_type = RUNT_DROP_RxPKT;
586 DMAState = 0;
587 } else {
588 DMAState = rx_dma[dma_num].CheckDMAStatus(RdmcToken.RxToken);
589 if(DMAState) {
590 printf(" RDMC DEBUG - DMA %d is active - Packets to be forwarded Further - \n",dma_num);
591 } else {
592 printf(" RDMC DEBUG - DMA %d is not active - Packets to be dropped \n",dma_num);
593 // Need more cases here
594 }
595
596 }
597
598 if(DMAState)
599 address_status = rx_dma[dma_num].getPacketAddress(RdmcToken.RxToken);
600
601// address_status here can be used as a status to indicate if DMC will be writing
602// packets.. ie to filter out any errors -- as a place holder
603
604// If the status is correct and everything is updated - send this token to the other
605// side and let the packet checker check this
606
607// This should be used only when packets are going to be checked without parsing the
608// completion ring.
609
610
611 SendTokenForCheck(RdmcToken.RxToken);
612
613 }
614
615}
616
617task CRDMC::SetPage0Registers(integer dma_chnl, bit [31:0] mask,bit [31:0] value, bit [31:0] reloc) {
618 bit [39:0] address;
619
620 address = RX_LOG_PAGE_MASK1 + dma_chnl*8'h40;
621 gen_pio_drv.pio_wr(address,{32'h0,mask});
622
623 address = RX_LOG_PAGE_VALUE1 + dma_chnl*8'h40;
624 gen_pio_drv.pio_wr(address,{32'h0,value});
625
626 address = RX_LOG_PAGE_RELO1 + dma_chnl*8'h40;
627 gen_pio_drv.pio_wr(address,{32'h0,reloc});
628
629}
630
631task CRDMC::InitRXDMA(integer dma_chnl, integer desc_ring_length, integer compl_ring_len, bit [63:0] rbr_config_B_data, bit [15:0] initial_kick, (integer xlation = 1)) {
632// Activate the Ports 0, 1, 2 and/or 3.
633 // start(3);
634// Call the init function for the particular DMA channel
635 rx_dma[dma_chnl].InitDMAChan(dma_chnl, desc_ring_length, compl_ring_len, rbr_config_B_data, initial_kick, xlation);
636}
637
638