// ========== Copyright Header Begin ========================================== // // OpenSPARC T2 Processor File: niu_rx_descp_sch.vr // Copyright (C) 1995-2007 Sun Microsystems, Inc. All Rights Reserved // 4150 Network Circle, Santa Clara, California 95054, U.S.A. // // * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // For the avoidance of doubt, and except that if any non-GPL license // choice is available it will apply instead, Sun elects to use only // the General Public License version 2 (GPLv2) at this time for any // software where a choice of GPL license versions is made // available with the language indicating that GPLv2 or any later version // may be used, or where a choice of which version of the GPL is applied is // otherwise unspecified. // // Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, // CA 95054 USA or visit www.sun.com if you need additional information or // have any questions. // // ========== Copyright Header End ============================================ #include #include #include "niu_mem.vrh" #include "niu_rxtoken.vrh" #include "niu_dmc_descr_ring.vrh" extern CSparseMem SparseMem; #define DESCR_DONE 1 #define DESCR_NOT_DONE 0 class CRxDescSch extends CRxdescriptor { // This is the place holder for the descriptor before scheduling one integer id; bit [63:0]address;// Address of this descriptor bit [63:0] virtaddress;// Address of this descriptor integer valid; integer blk_size; integer buf_size; integer bytes_allocated; integer index; task new( ( integer i =0)) { id = 0; valid = 0; bytes_allocated = 0; index = 0; } function bit[63:0] getAddress ( integer length, var bit[63:0] vaddr ) { getAddress = address + bytes_allocated; vaddr = virtaddress + bytes_allocated; bytes_allocated = bytes_allocated + buf_size; printf(" RDMC DEBUG - buf_size- %d bytes_allocated - %d Address - %x\n",buf_size,bytes_allocated,getAddress); if(bytes_allocated >blk_size) { printf(" ERROR Potential Programming error or Testbench ERROR -- \n"); } } function integer checkState () { if(bytes_allocated == blk_size) { checkState = DESCR_DONE; printf(" RDMC DEBUG - DONE WITH THIS DESCRIPTOR \n"); } else { checkState = DESCR_NOT_DONE; } } } MakeVeraList(CRxDescSch) // list of descriptors class CRxDescrSchRing extends CDescrRing { VeraList_CRxDescSch desc_ring; integer index; task new(integer i = 0) { id = i; index =0; desc_ring = new(); } function CRxDescSch front() { front = desc_ring.front(); } task pop_front(){ desc_ring.pop_front(); } task push_back( CRxDescSch desc ) { desc.index = index++; desc_ring.push_back(desc); //printf(" in CRxDescSch: Size - - %d \n",desc_ring.size()); } function CRxDescSch back() { back = desc_ring.back(); printf(" in CRxDescSch: address - %x \n",back.blk_addr); } function integer get_ring_size() { get_ring_size = desc_ring.size(); } // Something fishy here--- function integer isRingEmpty() { if(get_ring_size()) isRingEmpty = 0; else isRingEmpty = 1; } } class CRxdescpScheduler { integer valid; integer id; // Variables needed for carving logic to work bit vld0,vld1,vld2; integer blk_size; integer bufsz0,bufsz1,bufsz2; CRxDescrSchRing desc_ring; CRxDescSch RxDescSchSMALL; CRxDescSch RxDescSchMEDIUM; CRxDescSch RxDescSchLARGE; static bit [2:0] RxDescState[32]; // indicates which ones are popped out and are valid integer reclaim_index; integer last_reclaim_index; task new(integer i) { id = i; vld0 = 0; vld1 = 0; vld2 = 0; reclaim_index = 0; last_reclaim_index = 0; desc_ring = new(); RxDescState[i] = 0; // printf(" CRxdescpScheduler- Newd\n"); } task set_blk_size(bit [1:0] s) ; task set_bufsz0(bit [1:0] s,integer v) ; task set_bufsz1(bit [1:0] s,integer v) ; task set_bufsz2(bit [1:0] s,integer v) ; task print() { printf("CRxdescpScheduler DMA-%d - bufsz0 - %d bufz1 - %d bufz2 - %d vld0 - %d vld1 - %d vld2 - %d \n",id,bufsz0,bufsz1,bufsz2, vld0,vld1,vld2 ); } function integer get_reclaim_index ( ) { get_reclaim_index = reclaim_index; } task pushDescForSch( bit [31:0] address, (integer pkt_page_id = 0) ) ; local function integer getNextDesc( var CRxDescSch RxDescSch, var integer type); local function integer popDescrs(); local task allocJumboPackets ( CRxToken RxToken, integer NoOfDescrNeeded ); local task SetIndexForReclaim(); function integer getAddress ( CRxToken RxToken ); local task setDescType( CRxDescSch RxDescSch, integer type) { if(type == 2) { RxDescSchLARGE = new RxDescSch; } else if( type ==1) { RxDescSchMEDIUM = new RxDescSch; } else if( type ==0) { RxDescSchSMALL = new RxDescSch; } else { printf(" ERROR in setDescType \n"); } } } task CRxdescpScheduler::set_blk_size(bit [1:0] s) { case(s) { 2'b00 : blk_size = 4096; 2'b01 : blk_size = 8192; 2'b10 : blk_size = 16384; 2'b11 : blk_size = 32768; } } task CRxdescpScheduler::set_bufsz0(bit [1:0] s, integer v) { bufsz0 = 256 * ( 1< index_min ) ? index_min : last_reclaim_index; } function integer CRxdescpScheduler::getNextDesc( var CRxDescSch RxDescSch, var integer type) { integer size; bit [2:0] State; size = desc_ring.get_ring_size(); printf(" CRxdescpScheduler::getNextDesc: DMA- %d ring size - %d isRingEmpty - %d \n",id,size,desc_ring.isRingEmpty()); if(desc_ring.isRingEmpty() ) { getNextDesc = -1; // Ring is empty - packet to be dropped type = -1; return; } else { RxDescSch = desc_ring.front(); printf(" CRxdescpScheduler::getNextDesc DMA- %d Address - %x Index - %d\n", id,RxDescSch.address,RxDescSch.index); getNextDesc = size; desc_ring.pop_front(); } // Mark this descriptor as either of S,M,L // check various enables - State = RxDescState[id]; if(vld2 & ~State[2] ) { // Mark this as large RxDescSch.buf_size = bufsz2; RxDescSch.blk_size = blk_size; RxDescSch.valid = 1; State[2] = 1; type = 2; } else if(vld1 & ~State[1] ) { RxDescSch.buf_size = bufsz1; RxDescSch.blk_size = blk_size; RxDescSch.valid = 1; State[1] = 1; type = 1; } else if(vld0 & ~State[0] ) { RxDescSch.buf_size = bufsz0; RxDescSch.blk_size = blk_size; RxDescSch.valid = 1; State[0] = 1; type = 0; } else { printf(" ERROR--- MOST Likely testbench ERROR -- FIX IT \n"); getNextDesc = -1; } RxDescState[id] = State; printf(" CRxdescpScheduler::getNextDesc DMA- %d State - %b\n",id,State); } function integer CRxdescpScheduler::popDescrs() { // This function always keeps various descriptors blocks available integer done; CRxDescSch RxDescSch; integer status,type; bit[2:0] State; State = RxDescState[id]; if (vld2|vld1|vld0) done = (State == {vld2,vld1,vld0}); else { popDescrs = -1; return; } printf( "CRxdescpScheduler::popDescrs DMA %d State- %b Valid - %b\n",id,State,{vld2,vld1,vld0} ); while(!done) { printf( "CRxdescpScheduler::popDescrs DMA %d State- %b done - %d Valid - %b\n",id,State, done, {vld2,vld1,vld0}); status = getNextDesc(RxDescSch,type); if(status == -1) { popDescrs = -1; // None available return; } setDescType( RxDescSch,type); State = RxDescState[id]; if (vld2|vld1|vld0) done = (State == {vld2,vld1,vld0}); else { popDescrs = -1; return; } printf( "CRxdescpScheduler::popDescrs DMA %d State- %b done - %d Valid - %b \n",id,State, done,{vld2,vld1,vld0} ); } popDescrs = done; } task CRxdescpScheduler::allocJumboPackets ( CRxToken RxToken, integer NoOfDescrNeeded ) { integer i; CRxDescSch RxDescSch,RxDescSchUseForFirstBuf; integer bytes_remaining; bit [63:0] packet_end_address; bit [63:0] address; bit [63:0] vaddr; bytes_remaining = RxToken.pkt_length + RxToken.header_length; for(i = 0; i < NoOfDescrNeeded; i ++ ) { RxDescSch = desc_ring.front(); desc_ring.pop_front(); address = RxDescSch.getAddress( blk_size, vaddr ); RxToken.packet_start_address[i] = address; RxToken.packet_virtaddress[i] = vaddr; packet_end_address = (bytes_remaining>blk_size) ? (address + blk_size) : ( address + bytes_remaining); if (bytes_remaining >8) packet_end_address = packet_end_address -8 ; RxToken.bytesperchunk[i] = (bytes_remaining>blk_size) ? blk_size : bytes_remaining; RxToken.packet_end_address[i] = {packet_end_address[63:3],3'h0}; 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]); bytes_remaining = bytes_remaining - blk_size; } RxToken.NoOfScatter = NoOfDescrNeeded; 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]); } function integer CRxdescpScheduler::getAddress ( CRxToken RxToken ) { /* 1. Check if enough descriptors are available- else get more descriptors 2. Check the packet size and see which descriptor can be chosen ( among S, M, L ) 3. Once the descriptor is choosen, look at the bytes allocated to see space is available else get more. Iterate untill this is done */ integer size; integer length; integer type; integer descp_state; integer status; CRxDescSch RxDescSch; bit [63:0] address,vaddr; integer offset; integer largest_available_pkt_buf; integer jumbo_packet; integer NoOfDescrNeeded; integer i; bit [2:0] State; integer done; length = RxToken.pkt_length + RxToken.header_length; printf("RDMC DEBUG In Dma id - %d CRxdescpScheduler::getAddress Length - %d \n", RxToken.dma_num,length); printf( "RDMC DEBUG In Dma id - %d CRxdescpScheduler::getAddress Current Descriptors poped out - %b \n",id,RxDescState[id]); done = 0; status = popDescrs(); printf( "RDMC DEBUG In Dma id - %d CRxdescpScheduler::getAddress Descriptors poped out %b \n",id,RxDescState[id]); if(status == -1) { getAddress = -1; // None available -- packet to be dropped if(!(vld0|vld1|vld2)) { RxToken.pkt_type = VALID_DISABLED_DROP_RxPKT; printf("RDMC DEBUG - Packet to be dropped - All 3 buf_size_valids are disabled\n"); } else { RxToken.pkt_type = RNGFULL_DROP_RxPKT; printf("RDMC DEBUG - Packet to be dropped - Either Ring is FULL or EMPTY- \n"); } done = 1; return; } RxToken.pkt_type = GOOD_RxPKT; RxToken.bufsz = 3; // determine if this packet is a jumbo packet largest_available_pkt_buf = vld2 ? bufsz2 : ( vld1 ? bufsz1: ( vld0 ? bufsz0: 0) ); if(length > largest_available_pkt_buf ) { jumbo_packet = 1; } else jumbo_packet = 0; // check if this packet really qualifies as a jumbo packet ie // how many buffer will this occupy if(!done & ( length > 3 * blk_size )) { // this packet needs to be dropped // mark this packet bad and exit RxToken.pkt_type = BUFFSIZE_EXCEEDED_DROP_RxPKT; RxToken.jumbo_pkt = 1; done = 1; getAddress = 0; // None available return; } else { // this is the section to see how the descriptors are to be used if(jumbo_packet) { // Find out how many descriptors are needed for this length. It has to be <= 3 NoOfDescrNeeded = ( length/blk_size ) + ((length%blk_size) ? 1 :0); if(NoOfDescrNeeded == 0) { // should not happen -- printf(" TESTBENCH ERROR -- FIX IT\n"); } // Check if at least these many descriptors are available in the ring // if not drop the packet if(desc_ring.get_ring_size() >= NoOfDescrNeeded) { // Now split the packets and start writing into the memory // Keep poping the descriptor and allocating into the address untill // all the bytes are written allocJumboPackets( RxToken , NoOfDescrNeeded); // for(i=0;i