// ========== Copyright Header Begin ========================================== // // OpenSPARC T2 Processor File: niu_rxdma_pkttab.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_rxtoken.vrh" #include "mbox_class.vrh" #include "get_mbox_id.vrh" extern mbox_class mbox_id; #define TIME {get_time(HI), get_time(LO)} class CRxPacketScoreBoard { integer port_id; integer no_of_packets_qued, no_of_bytes_qued; integer no_of_packets_dqued, no_of_bytes_dqued; integer no_of_packets_checked, no_of_bytes_checked; integer no_of_packets_dropped, no_of_bytes_dropped; integer no_of_packets_l2_errors, no_of_bytes_l2_errors; integer no_of_packets_ext_l2_errors, no_of_bytes_ext_l2_errors; integer no_of_packets_ext_cksum_errors, no_of_bytes_ext_cksum_errors; integer no_of_packets_ext_runts,no_of_bytes_ext_runts; integer hist1_count; integer hist2_count; integer hist3_count; integer hist4_count; integer hist5_count; integer hist6_count; integer hist7_count; integer max_pkt_err_count; integer min_pkt_err_count; integer mcast_pkt_count; integer bcast_pkt_count; integer code_viol_err_count; integer bmac_align_err_count; integer xmac_byte_cnt; bit last_pkt_rcvd; // Token with (last_packet == 1 )receivced // queu of packets CRxToken RxTokenQue[]; CRxToken DeletedRxTokenQue[]; task print_stats( ( integer interval = 10000), (bit one_time = 0) ); task new(integer p) { port_id = p; last_pkt_rcvd = 1'b0; if(mbox_id.niu_rxpath_sb[p] == -1) { mbox_id.niu_rxpath_sb[p] = alloc(MAILBOX,0,1); // Check if we were succesfull allocating the mailbox if(mbox_id.niu_rxpath_sb[p] == 0) { printf("ERROR Could not allocate the scoreboard mailbox port %d \n",p); mbox_id.niu_rxpath_sb[p] = -1; return; } } no_of_packets_qued = 0; no_of_packets_dqued = 0; no_of_packets_checked = 0; no_of_packets_dropped = 0; no_of_packets_l2_errors = 0; no_of_packets_ext_l2_errors =0; no_of_packets_ext_cksum_errors=0; no_of_bytes_ext_l2_errors=0; no_of_bytes_ext_cksum_errors =0; no_of_packets_ext_runts =0; no_of_bytes_ext_runts =0; hist1_count = 0; hist2_count = 0; hist3_count = 0; hist4_count = 0; hist5_count = 0; hist6_count = 0; hist7_count = 0; xmac_byte_cnt = 0; max_pkt_err_count = 0; min_pkt_err_count = 0; mcast_pkt_count = 0; bcast_pkt_count = 0; code_viol_err_count = 0; bmac_align_err_count = 0; no_of_bytes_qued = 0; no_of_bytes_dqued = 0; no_of_bytes_checked = 0; no_of_bytes_dropped = 0; no_of_bytes_l2_errors = 0; fork wait_for_packets(); join none fork print_stats(100000); join none } function integer addPackets(CRxToken RxToken); function integer getPacket(integer id, var CRxToken RxToken,integer dma_no,integer dma_no_from_pkt) ; local function integer CheckDeletedQueue(integer id, var CRxToken RxToken); function integer getNoOfEntries() ; task incPacketStats(CRxToken RxToken); task wait_for_packets(); } task CRxPacketScoreBoard::incPacketStats(CRxToken RxToken ) { integer pg_error_code; integer rxtoken_error_code; no_of_packets_qued ++; no_of_bytes_qued = no_of_bytes_qued + RxToken.pkt_length; // xmac byte counter ceils to the multiple of 8 bytes if (RxToken.pkt_length%8) xmac_byte_cnt = RxToken.pkt_length/8 + 1; else xmac_byte_cnt = RxToken.pkt_length/8; // ext errors pg_error_code = RxToken.pgToken.pack_db.frame.error_code; // if ext l2 errors if((pg_error_code&PG_CRC_ERR) /*What about PG_TYPE_LEN_ERR?*/) { no_of_packets_ext_l2_errors++; no_of_bytes_ext_l2_errors = no_of_bytes_ext_l2_errors + RxToken.pkt_length; } // if ext cksum errors if((pg_error_code&PG_CHKSUM_ERR) /**/) { no_of_packets_ext_cksum_errors++; no_of_bytes_ext_cksum_errors = no_of_bytes_ext_cksum_errors + RxToken.pkt_length; } if( RxToken.pkt_length<64) { no_of_packets_ext_runts++; no_of_bytes_ext_runts = no_of_bytes_ext_runts + RxToken.pkt_length; } if (RxToken.pkt_length==64) hist1_count ++ ; if (RxToken.pkt_length>=65 && RxToken.pkt_length<128) hist2_count ++ ; if (RxToken.pkt_length>=128 && RxToken.pkt_length<256) hist3_count ++ ; if (RxToken.pkt_length>=256 && RxToken.pkt_length<512) hist4_count ++ ; if (RxToken.pkt_length>=512 && RxToken.pkt_length<1024) hist5_count ++ ; if (RxToken.pkt_length>=1024 && RxToken.pkt_length<1523) hist6_count ++ ; hist7_count ++ ; // total packet counter if (RxToken.pgToken.pack_db.flow.dst_node.l2_addr == 48'hffff_ffff_ffff) bcast_pkt_count ++ ; } function integer CRxPacketScoreBoard::addPackets(CRxToken RxToken) { integer id; id = RxToken.id; if(RxToken.port_num!=port_id) { printf("ERROR Incorrect Packet port num received !! \n"); addPackets = -1; } else if(assoc_index(CHECK,RxTokenQue,id)) { // check if this entry already exists printf(" packet id - %d exists in the queue - TB ERROR \n"); addPackets = -1; } else { // Now add the packet RxTokenQue[id] = RxToken; incPacketStats(RxToken); printf("CRxPacketScoreBoard::addPackets packet id - %d added in the queue - Port id - %d No Sofar - %d\n",id,port_id,no_of_packets_qued); } if(RxToken.last_packet) { last_pkt_rcvd = 1'b1; printf("%d CRxPacketScoreBoard::addPackets packet id - %d Received Last packet for Port id - %d \n",TIME, id,port_id); } } function integer CRxPacketScoreBoard::CheckDeletedQueue(integer id, var CRxToken RxToken){ integer status; if(assoc_index(CHECK,DeletedRxTokenQue,id)) { CheckDeletedQueue = 0; RxToken = DeletedRxTokenQue[id].object_copy(); status = assoc_index(DELETE,DeletedRxTokenQue,id); printf("CRxPacketScoreBoard::CheckDeletedQueue: id - %d port_id - %d found in deleted entry !!\n",id,port_id); } else { CheckDeletedQueue = 1; } } function integer CRxPacketScoreBoard::getPacket(integer id, var CRxToken RxToken,integer dma_no,integer dma_no_from_pkt) { integer status; integer first_id; integer iid,j; integer dma_no_to_compare; // find out how many entries are there before this one. // Among these are any of the entries expected to be dropped due to intentional errors // such as CRC, FIFO Errors etc // If not - mark them as potentially dropped due to backpressure and check if the testcase // was intending to do back-pressure. // Check if this id is for a packet already deleted. If so the only time this can come would be // when default dma is different from what was intended status = CheckDeletedQueue(id, RxToken); if(status==0) { // entry found - decrement counter no_of_packets_dropped--; no_of_packets_dqued++; getPacket = 1; printf("CRxPacketScoreBoard::getPacket: CheckDeletedQueue PacketId - %d Port - %d dma_no - %d Dropped - So far - %d \n",id,port_id,dma_no_from_pkt,no_of_packets_dropped); // no_of_bytes_dropped = no_of_bytes_dropped +RxTokenQue[iid].pkt_length; // no_of_bytes_dqued = no_of_bytes_dqued + RxToken.pkt_length; } else { // check if the id exists status = assoc_index(FIRST,RxTokenQue,first_id); if(status==0) { printf("PacketQue Empty !!! Illegal packet received Port No -%d \n",port_id); getPacket = -1; } else if(assoc_index(CHECK,RxTokenQue,id)) { if(id== first_id) { printf(" Packet Received Matches with the first one- No Packets dropped until now PortNo- %d PacketId - %d \n",port_id,id); } else { // scan through the que until we find the packet dma_no_to_compare = dma_no; status = assoc_index(FIRST,RxTokenQue,first_id); iid = first_id; while(id!=iid) { // find out if next exists if(RxTokenQue[iid].dma_num== dma_no_to_compare) { no_of_packets_dropped++; no_of_bytes_dropped = no_of_bytes_dropped +RxTokenQue[iid].pkt_length; printf("CRxPacketScoreBoard::getPacket: PacketId - %d Port - %d dma_no - %d Dropped - So far - %d \n",iid,port_id,dma_no_to_compare,no_of_packets_dropped); j=iid; status = assoc_index(NEXT,RxTokenQue,j); if(status) { /*printf("delete found next\n");*/} else { if (id!=j) printf("ERROR IN FINDING NEXT\n"); } DeletedRxTokenQue[iid] = RxTokenQue[iid].object_copy(); status = assoc_index(DELETE,RxTokenQue,iid); iid = j; } else { j=iid; status = assoc_index(NEXT,RxTokenQue,j); if(status) { /*printf("found next\n");*/} else { if (id!=j) printf("ERROR IN FINDING NEXT\n"); } iid = j; } } printf(" RxTokenQue[%d] Expected DMa No - %d Matched with id - %d \n",port_id,dma_no,iid); }// end else RxToken = new(); RxToken = RxTokenQue[id].object_copy(); status = assoc_index(DELETE,RxTokenQue,id); no_of_packets_dqued++; no_of_bytes_dqued = no_of_bytes_dqued + RxToken.pkt_length; getPacket = 1; } else { printf(" Packet Id doesnt exist!!! Illegal packet received \n"); getPacket = -1; } } } function integer CRxPacketScoreBoard::getNoOfEntries() { getNoOfEntries = no_of_packets_qued - no_of_packets_dqued; } task CRxPacketScoreBoard::wait_for_packets() { CRxToken RxToken; integer no_of_tkns,status; while(1) { no_of_tkns = mailbox_get(WAIT,mbox_id.niu_rxpath_sb[port_id], RxToken); status = addPackets(RxToken); if(status==-1){ printf(" ERROR in adding packets to scoreboard \n"); return; } } } task CRxPacketScoreBoard::print_stats( ( integer interval = 10000), (bit one_time = 0) ) { integer count; integer packets_remaining,packets_checked,total_packets_sent,packets_dropped,packets_l2_errors; count = 0; while(1) { printf("###START CURRENT STATS####!! TIME - %d Port - %d \n",TIME,port_id); packets_remaining = getNoOfEntries(); packets_checked = no_of_packets_dqued; total_packets_sent = no_of_packets_qued; packets_dropped = no_of_packets_dropped; packets_l2_errors = no_of_packets_l2_errors; printf("###STATS SOFAR#### Port=%0d packets_remaining=%0d packets_checked=%0d total_packets_sent=%0d\n", port_id, packets_remaining, packets_checked, total_packets_sent); printf("###STATS SOFAR#### Port=%0d bytes_checked=%0d total_bytes_sent=%0d\n", port_id, no_of_bytes_dqued, no_of_bytes_qued); printf("###STATS SOFAR#### Port=%0d packets dropped due to L2Error=%0d bytes=%0d\n", port_id, no_of_packets_l2_errors, no_of_bytes_l2_errors); printf("###END CURRENT STATS####!! TIME - %d Port - %d \n",TIME,port_id); if(one_time) return; repeat(interval + 10*port_id ) @(posedge CLOCK); } }