Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / verif / env / niu / rxc_sat / vera / rxdma / niu_rx_descp_sch.vr
CommitLineData
86530b38
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: niu_rx_descp_sch.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_rxtoken.vrh"
39#include "niu_dmc_descr_ring.vrh"
40
41extern CSparseMem SparseMem;
42
43#define DESCR_DONE 1
44#define DESCR_NOT_DONE 0
45
46class CRxDescSch extends CRxdescriptor {
47
48 // This is the place holder for the descriptor before scheduling one
49 integer id;
50 bit [63:0]address;// Address of this descriptor
51 bit [63:0] virtaddress;// Address of this descriptor
52 integer valid;
53 integer blk_size;
54 integer buf_size;
55 integer bytes_allocated;
56 integer index;
57
58
59 task new( ( integer i =0)) {
60 id = 0;
61 valid = 0;
62 bytes_allocated = 0;
63 index = 0;
64 }
65
66 function bit[63:0] getAddress ( integer length, var bit[63:0] vaddr ) {
67 getAddress = address + bytes_allocated;
68 vaddr = virtaddress + bytes_allocated;
69 bytes_allocated = bytes_allocated + buf_size;
70 printf(" RDMC DEBUG - buf_size- %d bytes_allocated - %d Address - %x\n",buf_size,bytes_allocated,getAddress);
71 if(bytes_allocated >blk_size) {
72 printf(" ERROR Potential Programming error or Testbench ERROR -- \n");
73 }
74 }
75
76 function integer checkState () {
77 if(bytes_allocated == blk_size) {
78 checkState = DESCR_DONE;
79 printf(" RDMC DEBUG - DONE WITH THIS DESCRIPTOR \n");
80 } else { checkState = DESCR_NOT_DONE;
81 }
82 }
83}
84
85
86MakeVeraList(CRxDescSch) // list of descriptors
87
88class CRxDescrSchRing extends CDescrRing {
89
90 VeraList_CRxDescSch desc_ring;
91 integer index;
92 task new(integer i = 0) {
93 id = i;
94 index =0;
95 desc_ring = new();
96 }
97 function CRxDescSch front() {
98 front = desc_ring.front();
99 }
100 task pop_front(){
101 desc_ring.pop_front();
102 }
103 task push_back( CRxDescSch desc ) {
104 desc.index = index++;
105 desc_ring.push_back(desc);
106 //printf(" in CRxDescSch: Size - - %d \n",desc_ring.size());
107 }
108 function CRxDescSch back() {
109 back = desc_ring.back();
110 printf(" in CRxDescSch: address - %x \n",back.blk_addr);
111 }
112 function integer get_ring_size() {
113 get_ring_size = desc_ring.size();
114 }
115
116// Something fishy here---
117 function integer isRingEmpty() {
118 if(get_ring_size()) isRingEmpty = 0;
119 else isRingEmpty = 1;
120 }
121}
122
123class CRxdescpScheduler {
124
125 integer valid;
126 integer id;
127 // Variables needed for carving logic to work
128 bit vld0,vld1,vld2;
129 integer blk_size;
130 integer bufsz0,bufsz1,bufsz2;
131
132 CRxDescrSchRing desc_ring;
133
134 CRxDescSch RxDescSchSMALL;
135 CRxDescSch RxDescSchMEDIUM;
136 CRxDescSch RxDescSchLARGE;
137 static bit [2:0] RxDescState[32]; // indicates which ones are popped out and are valid
138 integer reclaim_index;
139 integer last_reclaim_index;
140
141
142
143 task new(integer i) {
144 id = i;
145 vld0 = 0;
146 vld1 = 0;
147 vld2 = 0;
148 reclaim_index = 0;
149 last_reclaim_index = 0;
150 desc_ring = new();
151 RxDescState[i] = 0;
152 // printf(" CRxdescpScheduler- Newd\n");
153 }
154
155 task set_blk_size(bit [1:0] s) ;
156 task set_bufsz0(bit [1:0] s,integer v) ;
157 task set_bufsz1(bit [1:0] s,integer v) ;
158 task set_bufsz2(bit [1:0] s,integer v) ;
159 task print() {
160 printf("CRxdescpScheduler DMA-%d - bufsz0 - %d bufz1 - %d bufz2 - %d vld0 - %d vld1 - %d vld2 - %d \n",id,bufsz0,bufsz1,bufsz2, vld0,vld1,vld2 );
161 }
162
163
164
165 function integer get_reclaim_index ( ) { get_reclaim_index = reclaim_index; }
166 task pushDescForSch( bit [31:0] address, (integer pkt_page_id = 0) ) ;
167 local function integer getNextDesc( var CRxDescSch RxDescSch, var integer type);
168 local function integer popDescrs();
169 local task allocJumboPackets ( CRxToken RxToken, integer NoOfDescrNeeded );
170 local task SetIndexForReclaim();
171 function integer getAddress ( CRxToken RxToken );
172 local task setDescType( CRxDescSch RxDescSch, integer type) {
173 if(type == 2) {
174 RxDescSchLARGE = new RxDescSch;
175 } else if( type ==1) {
176 RxDescSchMEDIUM = new RxDescSch;
177 } else if( type ==0) {
178 RxDescSchSMALL = new RxDescSch;
179 } else {
180 printf(" ERROR in setDescType \n");
181 }
182
183 }
184
185}
186task CRxdescpScheduler::set_blk_size(bit [1:0] s) {
187 case(s) {
188 2'b00 : blk_size = 4096;
189 2'b01 : blk_size = 8192;
190 2'b10 : blk_size = 16384;
191 2'b11 : blk_size = 32768;
192 }
193}
194task CRxdescpScheduler::set_bufsz0(bit [1:0] s, integer v) {
195 bufsz0 = 256 * ( 1<<s ) ;
196 vld0 = v;
197}
198task CRxdescpScheduler::set_bufsz1(bit [1:0] s, integer v) {
199 bufsz1 = 1024 * ( 1<<s ) ;
200 vld1 = v;
201}
202task CRxdescpScheduler::set_bufsz2(bit [1:0] s, integer v) {
203 bufsz2 = 2048 * (1<< s) ;
204 vld2 = v;
205}
206
207task CRxdescpScheduler::pushDescForSch( bit [31:0] address, (integer pkt_page_id = 0) ) {
208
209 CRxDescSch RxDescSch;
210 bit [39:0] xlate_address;
211 bit [31:0] xlate_address_page;
212 xlate_address = SparseMem.xlate_addr({address,12'h0},pkt_page_id);
213 xlate_address_page = xlate_address[39:12];
214 RxDescSch = new();
215 // printf(" Pushing descriptor for DMA%d Descriptor - orig %x xlate - %x \n",id,address,xlate_address[39:12]);
216
217 case(blk_size) {
218 4096 : RxDescSch.address = {20'h0,xlate_address_page[31:0],12'h0};
219 8192 : RxDescSch.address = {20'h0,xlate_address_page[31:1],13'h0};
220 16384 : RxDescSch.address = {20'h0,xlate_address_page[31:2],14'h0};
221 32768 : RxDescSch.address = {20'h0,xlate_address_page[31:3],15'h0};
222 }
223
224 case(blk_size) {
225 4096 : RxDescSch.virtaddress = {20'h0,address[31:0],12'h0};
226 8192 : RxDescSch.virtaddress = {20'h0,address[31:1],13'h0};
227 16384 : RxDescSch.virtaddress = {20'h0,address[31:2],14'h0};
228 32768 : RxDescSch.virtaddress = {20'h0,address[31:3],15'h0};
229 }
230 // replace this with page handle
231
232 desc_ring.push_back(RxDescSch);
233
234}
235
236task CRxdescpScheduler::SetIndexForReclaim() {
237
238 // first check the state
239 // for each of the pop'd descriptor get the index
240 // compute min of all of these and compare against the last accessed index
241
242 integer index_small;
243 integer index_medium;
244 integer index_large;
245 integer index_min;
246 bit[2:0] State;
247 // start with a large value
248 index_small = 32'hffffff;
249 index_medium = 32'hffffff;
250 index_large = 32'hffffff;
251
252 State = RxDescState[id];
253
254 index_small = (State[0])? RxDescSchSMALL.index: index_small;
255 index_medium = (State[1])? RxDescSchMEDIUM.index: index_medium;
256 index_large = (State[2])? RxDescSchLARGE.index: index_large;
257
258 // min value
259 index_min = (index_small<index_medium) ? index_small: index_medium;
260 index_min = (index_min<index_large) ? index_min : index_large;
261
262 reclaim_index = (last_reclaim_index > index_min ) ? index_min : last_reclaim_index;
263
264}
265
266
267
268function integer CRxdescpScheduler::getNextDesc( var CRxDescSch RxDescSch, var integer type) {
269
270 integer size;
271 bit [2:0] State;
272
273 size = desc_ring.get_ring_size();
274 printf(" CRxdescpScheduler::getNextDesc: DMA- %d ring size - %d isRingEmpty - %d \n",id,size,desc_ring.isRingEmpty());
275 if(desc_ring.isRingEmpty() ) {
276 getNextDesc = -1; // Ring is empty - packet to be dropped
277 type = -1;
278 return;
279
280 } else {
281 RxDescSch = desc_ring.front();
282 printf(" CRxdescpScheduler::getNextDesc DMA- %d Address - %x Index - %d\n", id,RxDescSch.address,RxDescSch.index);
283 getNextDesc = size;
284 desc_ring.pop_front();
285 }
286
287 // Mark this descriptor as either of S,M,L
288
289 // check various enables -
290 State = RxDescState[id];
291
292 if(vld2 & ~State[2] ) {
293 // Mark this as large
294 RxDescSch.buf_size = bufsz2;
295 RxDescSch.blk_size = blk_size;
296 RxDescSch.valid = 1;
297 State[2] = 1;
298 type = 2;
299 } else if(vld1 & ~State[1] ) {
300 RxDescSch.buf_size = bufsz1;
301 RxDescSch.blk_size = blk_size;
302 RxDescSch.valid = 1;
303 State[1] = 1;
304 type = 1;
305 } else if(vld0 & ~State[0] ) {
306 RxDescSch.buf_size = bufsz0;
307 RxDescSch.blk_size = blk_size;
308 RxDescSch.valid = 1;
309 State[0] = 1;
310 type = 0;
311 } else {
312 printf(" ERROR--- MOST Likely testbench ERROR -- FIX IT \n");
313 getNextDesc = -1;
314 }
315
316 RxDescState[id] = State;
317 printf(" CRxdescpScheduler::getNextDesc DMA- %d State - %b\n",id,State);
318
319}
320
321function integer CRxdescpScheduler::popDescrs() {
322
323// This function always keeps various descriptors blocks available
324
325 integer done;
326 CRxDescSch RxDescSch;
327 integer status,type;
328 bit[2:0] State;
329 State = RxDescState[id];
330
331 if (vld2|vld1|vld0)
332 done = (State == {vld2,vld1,vld0});
333 else {
334 popDescrs = -1;
335 return;
336 }
337 printf( "CRxdescpScheduler::popDescrs DMA %d State- %b Valid - %b\n",id,State,{vld2,vld1,vld0} );
338 while(!done) {
339 printf( "CRxdescpScheduler::popDescrs DMA %d State- %b done - %d Valid - %b\n",id,State, done, {vld2,vld1,vld0});
340
341 status = getNextDesc(RxDescSch,type);
342 if(status == -1) {
343 popDescrs = -1; // None available
344 return;
345 }
346 setDescType( RxDescSch,type);
347 State = RxDescState[id];
348 if (vld2|vld1|vld0)
349 done = (State == {vld2,vld1,vld0});
350 else {
351 popDescrs = -1;
352 return;
353 }
354 printf( "CRxdescpScheduler::popDescrs DMA %d State- %b done - %d Valid - %b \n",id,State, done,{vld2,vld1,vld0} );
355 }
356 popDescrs = done;
357
358}
359
360
361task CRxdescpScheduler::allocJumboPackets ( CRxToken RxToken, integer NoOfDescrNeeded ) {
362
363 integer i;
364 CRxDescSch RxDescSch,RxDescSchUseForFirstBuf;
365 integer bytes_remaining;
366 bit [63:0] packet_end_address;
367 bit [63:0] address;
368 bit [63:0] vaddr;
369
370
371 bytes_remaining = RxToken.pkt_length + RxToken.header_length;
372
373
374 for(i = 0; i < NoOfDescrNeeded; i ++ ) {
375 RxDescSch = desc_ring.front();
376 desc_ring.pop_front();
377 address = RxDescSch.getAddress( blk_size, vaddr );
378 RxToken.packet_start_address[i] = address;
379 RxToken.packet_virtaddress[i] = vaddr;
380 packet_end_address = (bytes_remaining>blk_size) ? (address + blk_size) : ( address + bytes_remaining);
381 if (bytes_remaining >8)
382 packet_end_address = packet_end_address -8 ;
383 RxToken.bytesperchunk[i] = (bytes_remaining>blk_size) ? blk_size : bytes_remaining;
384 RxToken.packet_end_address[i] = {packet_end_address[63:3],3'h0};
385 printf("CRxdescpScheduler::allocJumboPackets: RDMC DEBUG DMA - %d - SCHEDULER ALLOC ADDRESS - %x FOR JUMBO Scatter# - %d, PktType Set to %d Bytes- %d \n",id,RxToken.packet_start_address[i],i,RxToken.pkt_type,RxToken.bytesperchunk[i]);
386
387 bytes_remaining = bytes_remaining - blk_size;
388 }
389 RxToken.NoOfScatter = NoOfDescrNeeded;
390 printf("CRxdescpScheduler::allocJumboPackets: RDMC DEBUG DMA - %d - SCHEDULER ALLOC ADDRESS - %x FOR JUMB NoOfDescrNeeded # - %d, PktType Set to %d Bytes- %d \n",id,RxToken.packet_start_address[NoOfDescrNeeded -1],NoOfDescrNeeded,RxToken.pkt_type,RxToken.bytesperchunk[NoOfDescrNeeded -1]);
391
392
393}
394
395function integer CRxdescpScheduler::getAddress ( CRxToken RxToken ) {
396
397
398
399
400
401/*
402
403 1. Check if enough descriptors are available- else get more descriptors
404 2. Check the packet size and see which descriptor can be chosen ( among S, M, L )
405 3. Once the descriptor is choosen, look at the bytes allocated to see space is available
406 else get more. Iterate untill this is done
407
408
409
410*/
411
412 integer size;
413 integer length;
414 integer type;
415 integer descp_state;
416 integer status;
417 CRxDescSch RxDescSch;
418 bit [63:0] address,vaddr;
419 integer offset;
420 integer largest_available_pkt_buf;
421 integer jumbo_packet;
422 integer NoOfDescrNeeded;
423 integer i;
424 bit [2:0] State;
425
426 integer done;
427
428 length = RxToken.pkt_length + RxToken.header_length;
429 printf("RDMC DEBUG In Dma id - %d CRxdescpScheduler::getAddress Length - %d \n", RxToken.dma_num,length);
430 printf( "RDMC DEBUG In Dma id - %d CRxdescpScheduler::getAddress Current Descriptors poped out - %b \n",id,RxDescState[id]);
431
432
433 done = 0;
434 status = popDescrs();
435 printf( "RDMC DEBUG In Dma id - %d CRxdescpScheduler::getAddress Descriptors poped out %b \n",id,RxDescState[id]);
436 if(status == -1) {
437 getAddress = -1; // None available -- packet to be dropped
438
439 if(!(vld0|vld1|vld2)) {
440 RxToken.pkt_type = VALID_DISABLED_DROP_RxPKT;
441 printf("RDMC DEBUG - Packet to be dropped - All 3 buf_size_valids are disabled\n");
442 }
443 else {
444 RxToken.pkt_type = RNGFULL_DROP_RxPKT;
445 printf("RDMC DEBUG - Packet to be dropped - Either Ring is FULL or EMPTY- \n");
446 }
447
448 done = 1;
449 return;
450 }
451
452 RxToken.pkt_type = GOOD_RxPKT;
453 RxToken.bufsz = 3;
454
455 // determine if this packet is a jumbo packet
456
457
458 largest_available_pkt_buf = vld2 ? bufsz2 : (
459 vld1 ? bufsz1: (
460 vld0 ? bufsz0: 0) );
461
462
463 if(length > largest_available_pkt_buf ) {
464 jumbo_packet = 1;
465 } else jumbo_packet = 0;
466
467 // check if this packet really qualifies as a jumbo packet ie
468 // how many buffer will this occupy
469
470 if(!done & ( length > 3 * blk_size )) {
471 // this packet needs to be dropped
472 // mark this packet bad and exit
473 RxToken.pkt_type = BUFFSIZE_EXCEEDED_DROP_RxPKT;
474 RxToken.jumbo_pkt = 1;
475 done = 1;
476 getAddress = 0; // None available
477 return;
478 } else {
479 // this is the section to see how the descriptors are to be used
480 if(jumbo_packet) {
481 // Find out how many descriptors are needed for this length. It has to be <= 3
482 NoOfDescrNeeded = ( length/blk_size ) + ((length%blk_size) ? 1 :0);
483 if(NoOfDescrNeeded == 0) {
484 // should not happen --
485 printf(" TESTBENCH ERROR -- FIX IT\n");
486 }
487 // Check if at least these many descriptors are available in the ring
488 // if not drop the packet
489 if(desc_ring.get_ring_size() >= NoOfDescrNeeded) {
490 // Now split the packets and start writing into the memory
491
492 // Keep poping the descriptor and allocating into the address untill
493 // all the bytes are written
494
495
496 allocJumboPackets( RxToken , NoOfDescrNeeded);
497
498 // for(i=0;i<RxToken.NoOfScatter;i++) {
499 // printf(" After allocJumboPackets- endaddress - %x i - %d\n",RxToken.packet_end_address[i],i);
500 // }
501 RxToken.pkt_type = GOOD_RxPKT;
502 RxToken.jumbo_pkt = 1;
503 getAddress = 1;
504 done = 1;
505 return;
506
507 } else {
508 // packet to be dropped !!!!
509 RxToken.pkt_type = BUFFSIZE_EXCEEDED_DROP_RxPKT;
510 RxToken.jumbo_pkt = 1;
511 getAddress = 0; // None available
512 done = 1;
513 return;
514 }
515 }
516
517}
518 // for(i=0;i<RxToken.NoOfScatter;i++) {
519 // printf(" in getaddress after allocJumboPackets- endaddress - %x i - %d\n",RxToken.packet_end_address[i],i);
520 // }
521 // Here the packet is not a jumbo packet and is within the limits of the pkt_buffer
522 // scan through available descriptors and choose the address
523
524 if(!done) {
525
526 State = RxDescState[id];
527 // printf(" I am here== before small\n");
528 if ( (length <= bufsz0) & vld0) {
529 // check if small descriptor is available
530 if ( State[0] ) {
531 address = RxDescSchSMALL.getAddress(length,vaddr);
532 descp_state = RxDescSchSMALL.checkState(); // Is this descriptor done?
533 if(descp_state == DESCR_DONE) {
534 // keep the next descriptor ready
535
536 SetIndexForReclaim();
537 RxDescSchSMALL = null;
538 State[0] = 0;
539 // status = popDescrs();
540 if(status == -1 ) {
541 printf("CRxdescpScheduler::getAddress:RDMC DEBUG DMA - %d - DONE With SMALL descriptors!! \n",id);
542 }
543 }
544 RxToken.bufsz = 0;
545 } else {
546 // Drop this packet
547 RxToken.pkt_type = RNGFULL_DROP_RxPKT;
548 }
549 } else if ( (length <= bufsz1) & vld1) {
550 // check if Medium descriptor is available
551 // printf(" I am here== before medium\n");
552 if ( State[1] ) {
553 address = RxDescSchMEDIUM.getAddress(length,vaddr);
554 descp_state = RxDescSchMEDIUM.checkState(); // Is this descriptor done?
555 if(descp_state == DESCR_DONE) {
556 // keep the next descriptor ready
557
558 SetIndexForReclaim();
559 RxDescSchMEDIUM = null;
560 State[1] = 0;
561 // status = popDescrs();
562 if(status != -1) {
563 printf("CRxdescpScheduler::getAddress:RDMC DEBUG DMA - %d - DONE With MEDIUM the descriptors!! \n",id);
564 }
565 }
566 RxToken.bufsz = 1;
567 } else {
568 // Drop this packet
569 RxToken.pkt_type = RNGFULL_DROP_RxPKT;
570 }
571 } else if( (length <= bufsz2) & vld2) {
572 // check if small descriptor is available
573 // printf(" I am here== before large\n");
574 if ( State[2] ) {
575 address = RxDescSchLARGE.getAddress(length,vaddr);
576 descp_state = RxDescSchLARGE.checkState(); // Is this descriptor done?
577 if(descp_state == DESCR_DONE) {
578 // keep the next descriptor ready
579
580 SetIndexForReclaim();
581 RxDescSchLARGE = null;
582 State[2] = 0;
583 // status = popDescrs();
584 if(status != -1) {
585 printf("CRxdescpScheduler::getAddress:RDMC DEBUG DMA - %d - DONE With LARGE the descriptors!! \n");
586 }
587 }
588 RxToken.bufsz = 2;
589 } else {
590 // Drop this packet
591 RxToken.pkt_type = RNGFULL_DROP_RxPKT;
592 }
593 } else {
594 // This is what none of the descriptors are available
595// Set packet to be dropped
596 getAddress = -1; // None available
597 done = 1;
598 RxToken.pkt_type = RNGFULL_DROP_RxPKT;
599 }
600
601 RxToken.packet_start_address[0] = address;
602 RxToken.packet_virtaddress[0] = vaddr;
603 address = address + length -8 ; // this needs to be 64 bit aligned for SIU Model's memory?
604 RxToken.packet_end_address[0] = {address[63:3],3'h0} ;
605 printf("CRxdescpScheduler::getAddress DMA - %d DEBUG in getaddress before exit- endaddress - %x \n",id,address);
606 RxToken.NoOfScatter = 1;
607 RxToken.bytesperchunk[0] = length;
608 RxDescState[id] = State;
609}
610
611 // for(i=0;i<RxToken.NoOfScatter;i++) {
612 // printf(" in getaddress before exit- endaddress - %x i - %d\n",RxToken.packet_end_address[i],i);
613 // }
614
615}