Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / verif / env / niu / txc_sat / vera / niu_tx_test_class.vr
// ========== Copyright Header Begin ==========================================
//
// OpenSPARC T2 Processor File: niu_tx_test_class.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 <vera_defines.vrh>
#include "niu_gen_pio.vrh"
#include "niu_tx_descp.vrh"
#include "niu_tx_port.vrh"
#include "niu_tx_test_control.vrh"
#include "cMesg.vrh"
#include "txc_util.vrh"
#include "specweb_traffic_pattern.vrh"
extern niu_gen_pio gen_pio_drv;
extern Mesg be_msg;
extern txc_util_class txc_util;
extern event TX_rvcd_allpkts[4];
#include "dmc_memory_map.vri"
#define TIME {get_time(HI), get_time(LO)}
class niu_tx_test_class {
integer id;
integer cnt;
integer mk_count[24];
// integer no_of_pkts;
integer no_of_pkts_p0;
integer no_of_pkts_p1;
integer no_of_pkts_p2;
integer no_of_pkts_p3;
integer rand_num_pkts[24];
integer no_of_txdmas;
integer pkts_done[4];
integer port0_enb = 0;
integer port1_enb = 0;
integer port2_enb = 0;
integer port3_enb = 0;
bit [23:0] dmas_ids_p0;
bit [23:0] dmas_ids_p1;
bit [23:0] dmas_ids_p2;
bit [23:0] dmas_ids_p3;
integer group_from_dma_channel[32]; // niu_dmc_virt.vr will populate this if required
integer err_detected = 0;
integer tx_kick_done[4];
integer tx_ports_sync_semaphore;
integer rx_ports_sync_semaphore;
integer total_tx_ports;
CMacTxPort MacTxPort[4];
TxPacketGenConfig PktGenConfig[24];
flow_desc flow1[24];
niu_tx_test_control tx_control;
Cspecweb_traffic_pattern specweb_traffic_pattern_tx;
task get_dmaid(integer dma_id);
task Rd_Pkt_Prt_Err_Set();
task Rd_Pkt_Prt_Err_Clr();
task Rd_TDMC_Intr_Dbg();
task Wr_1toC_TxCs();
task SetTDMCIntrDbg(bit [63:0] data);
// task reset_dma();
task reset_dma((integer skip_chk = 0), (integer skip_rst = 1));
task get_txc_isr_count (integer count);
task new((integer tx_ports_sync_semaphore_in = -1),
(integer rx_ports_sync_semaphore_in = -1),
(integer total_tx_ports_in = -1));
task kick_all_4ports();
task set_flow(integer pkt_type, integer dma_id, integer mac_id);
task set_pktconfig(flow_desc flow1, integer dma_id, integer mac_id);
// task tx_dma_init(integer mac_id, bit [23:0] dma_ids, integer ring_len[24]);
task tx_dma_init(integer mac_id, integer ring_len, integer dma_id);
task generate_pkts(integer no_of_pkts, integer mac_id, integer dma_id, (integer last_pkt
=0));
task kick_dmas(integer no_of_pkts, integer mac_id, bit [23:0] dma_ids, integer port_enb);
task set_pkt_len(integer pkt_len_param, integer mac_id, integer pkt_num);
task set_pad_bytes(integer dma_id, integer pkt_num);
task kick_all(integer no_of_pkts, integer mac_id, bit[23:0] dma_ids);
task kick_npkts(integer no_of_pkts, integer mac_id, bit[23:0] dma_ids);
task kick_rnum_pkts(integer no_of_pkts, integer mac_id, bit[23:0] dma_ids);
task setup_random_dmabinds(var bit [23:0] dmas_port0, var bit [23:0] dmas_port1,
var bit [23:0] dmas_port2, var bit [23:0] dmas_port3);
task call_gen_txgatherpkts(TxPacketGenConfig PktGenConfig, integer mac_id, integer pkt_num, integer dma_id);
// task InitTxDMA(integer no_of_pkts,integer mac_id,bit[23:0] dma_ids);
task InitTxDMA(integer no_of_pkts,integer mac_id, integer dma_id);
task mailbox_update(integer mac_id, integer dma_id);
task mailbox_read(integer mac_id, integer dma_id);
task sync_on_pkts_done(integer mac_id);
task check_tx_cs(integer mac_id, integer dma_id, string err_code,(integer chk_set=0),(integer chk_clr= 0));
task clear_mk(integer dma_id);
task set_max_burst(integer mac_id, integer dma_id);
task set_port_control(integer p0_enb, integer p1_enb, integer p2_enb, integer p3_enb);
task BindDmaIntrDev(DMAChannel TxDma, integer i);
task random_reset_reinit(integer mac_id, integer dma_id, integer no_of_pkts, var integer pkts_xmttd);
task kick_all_wrreset(integer no_of_pkts, integer mac_id, bit[23:0] dma_ids);
function integer get_num_of_dmas_bport(bit [23:0] dma_ids);
task get_numpkts_based_onconfig();
task random_stop_start_dma(integer mac_id, integer dma_id);
}
task niu_tx_test_class :: new((integer tx_ports_sync_semaphore_in = -1),
(integer rx_ports_sync_semaphore_in = -1),
(integer total_tx_ports_in = -1))
{
integer i;
integer mac_id0;
integer mac_id1;
integer mac_id2;
integer mac_id3;
mac_id0 = 0;
mac_id1 = 1;
mac_id2 = 2;
mac_id3 = 3;
MacTxPort[mac_id0] = new(mac_id0);
MacTxPort[mac_id1] = new(mac_id1);
tx_control = new();
for(i=0;i<24;i++)
rand_num_pkts[i] = 0;
// no_of_pkts = tx_control.no_of_pkts;
no_of_txdmas = tx_control.no_of_dmas;
printf("TX_TEST_CL : no_of_txdmas %0d\n",no_of_txdmas);
if(tx_control.random_dmabinds == 0) {
dmas_ids_p0 = tx_control.port0_dmas;
dmas_ids_p1 = tx_control.port1_dmas;
dmas_ids_p2 = tx_control.port2_dmas;
dmas_ids_p3 = tx_control.port3_dmas;
dmas_ids_p0 = {8'h0,dmas_ids_p0[15:0]};
dmas_ids_p1 = {8'h0,dmas_ids_p1[15:0]};
} else {
// call the random dma bind function
setup_random_dmabinds(dmas_ids_p0,dmas_ids_p1,dmas_ids_p2,dmas_ids_p3);
dmas_ids_p0 = {8'h0,dmas_ids_p0[15:0]};
dmas_ids_p1 = {8'h0,dmas_ids_p1[15:0]};
}
tx_ports_sync_semaphore = tx_ports_sync_semaphore_in;
rx_ports_sync_semaphore = rx_ports_sync_semaphore_in;
total_tx_ports = total_tx_ports_in;
fork
{
sync_on_pkts_done(0);
}
{
sync_on_pkts_done(1);
}
{
sync_on_pkts_done(2);
}
{
sync_on_pkts_done(3);
}
join none
for(i=0;i<32;i++)
group_from_dma_channel[i] = -1;
if(tx_control.specweb_enabled)
specweb_traffic_pattern_tx = new("TX" /*RX or TX*/);
}
task niu_tx_test_class :: get_dmaid(integer dma_id)
{
id = dma_id;
}
task niu_tx_test_class :: reset_dma((integer skip_chk = 0),(integer skip_rst = 1))
{
// read the TX_CS reg and determin what to do
bit [39:0] address;
bit [63:0] r_data;
bit [63:0] w_data = 64'h8000_0000;
integer rst_done = 0;
integer count = 0;
// if fatal error detected reset the dma
if(err_detected || !skip_rst ) {
address = TX_CS + id*40'h200;
printf(" DEBUG-- niu_tx_test_class id - %d addrsss - %x w_data - %x Time - %d \n",id,address,w_data,{get_time(HI), get_time(LO)});
gen_pio_drv.pio_wr(address,w_data);
// perform a read from the register to make sure
// tdmc is in the rst_done state before programming
// the other config regs
if(!skip_chk) {
printf("TX_TEST_CL : check if rst_done\n");
while(!rst_done) {
address = TX_CS + id*40'h200;
gen_pio_drv.pio_rd(address,r_data);
printf(" DEBUG-- niu_tx_test_class id - %d addrsss - %x r_data - %x Time - %d \n",id,address,r_data,{get_time(HI), get_time(LO)});
if(r_data[30]) {
rst_done = 1;
be_msg.print(e_mesg_info,"niu_tx_descp","SetTxCs","RST_STATE set for DMA %0d\n",id);
} else {
if(count > 100) {
be_msg.print(e_mesg_error,"niu_tx_descp","SetTxCs","ERROR : RST_STATE not set for DMA %0d\n",id);
rst_done = 1;
} else {
count++;
rst_done = 0;
repeat(50) @(posedge CLOCK);
}
}
}
}
err_detected = 0;
}
}
task niu_tx_test_class :: SetTDMCIntrDbg(bit [63:0] data)
{
bit [39:0] address;
address = TDMC_INTR_DBG + id*40'h200;
gen_pio_drv.pio_wr(address,data);
}
task niu_tx_test_class :: Rd_TDMC_Intr_Dbg()
{
bit [39:0] address;
bit [63:0] rd_data;
printf("VAL_OF_ID in TST_CLASS %d\n",id);
address = TDMC_INTR_DBG + id*40'h200;
gen_pio_drv.pio_rd(address,rd_data);
if(rd_data[0])
be_msg.print(e_mesg_error,"intr_test","Rd_TDMC_Intr_Dbg","Src_Pkt_Prt_Err not cleared for DMA %0d\n",id);
}
task niu_tx_test_class :: Rd_Pkt_Prt_Err_Set()
{
bit [39:0] address;
bit [63:0] rd_data;
printf("VAL_OF_ID in TST_CLASS %d\n",id);
address = TX_CS + id*40'h200;
gen_pio_drv.pio_rd(address,rd_data);
if(~rd_data[0])
be_msg.print(e_mesg_error,"intr_test","Rd_Pkt_Prt_Err_Set","Pkt_Prt_Err not set for DMA %0d\n",id);
}
task niu_tx_test_class :: Rd_Pkt_Prt_Err_Clr()
{
bit [39:0] address;
bit [63:0] rd_data;
address = TX_CS + id*40'h200;
gen_pio_drv.pio_rd(address,rd_data);
if(rd_data[0])
be_msg.print(e_mesg_error,"intr_test","Rd_Pkt_Prt_Err_Clr","Pkt_Prt_Err not cleared for DMA %0d\n",id);
}
task niu_tx_test_class :: Wr_1toC_TxCs()
{
bit [39:0] address;
bit [63:0] rd_data;
bit [63:0] mask;
bit [63:0] wr_data;
// first read to get the data
address = TX_CS + id*40'h200;
gen_pio_drv.pio_rd(address,rd_data);
mask = 64'hffff_ffff_ffff_fffe;
rd_data = rd_data & mask;
// this is specific for pkt_prt_err
// wr_data = rd_data | 64'h4000_0001;
wr_data = 64'hc000_0001;
gen_pio_drv.pio_wr(address,wr_data);
}
task niu_tx_test_class :: get_txc_isr_count (integer count)
{
cnt = count;
}
task niu_tx_test_class :: kick_all_4ports()
{
integer mac_id0;
integer mac_id1;
integer mac_id2;
integer mac_id3;
// integer rng_len;
bit mb_enb;
mac_id0 = 0;
mac_id1 = 1;
mac_id2 = 2;
mac_id3 = 3;
mb_enb = tx_control.enable_mb;
port0_enb = tx_control.port0_enb;
port1_enb = tx_control.port1_enb;
port2_enb = tx_control.port2_enb;
port3_enb = tx_control.port3_enb;
// check if we need to sync all tx dmas
// if so disable the txc-mac interface
if(tx_control.sync_dmas)
txc_util.txc_init(64'h0);
else
set_port_control(port0_enb,port1_enb,port2_enb,port3_enb);
if(tx_control.tx_uniform_pkt_distribution)
get_numpkts_based_onconfig();
//------ TXC init ---------------//
repeat(10) @(posedge CLOCK);
fork
{
if(tx_control.tx_uniform_pkt_distribution)
kick_dmas(no_of_pkts_p0,0,dmas_ids_p0,port0_enb);
else
kick_dmas(tx_control.no_of_pkts,0,dmas_ids_p0,port0_enb);
}
{
if(tx_control.tx_uniform_pkt_distribution)
kick_dmas(no_of_pkts_p1,1,dmas_ids_p1,port1_enb);
else
kick_dmas(tx_control.no_of_pkts,1,dmas_ids_p1,port1_enb);
}
{
repeat(5) @(posedge CLOCK);
}
{
repeat(5) @(posedge CLOCK);
}
join all
}
// add task to bind the dmas to mac_port
task niu_tx_test_class :: BindDmaIntrDev(DMAChannel TxDma, integer i) {
integer j = 0;
integer mac_id = 0;
integer mac_ports;
mac_ports = 2;
for(j=0; j< mac_ports ;j++) {
case(j) {
0 : {
mac_id = 0;
if(dmas_ids_p0[i]) {
MacTxPort[mac_id].BindDmaIntrDev(TxDma,i);
set_max_burst(mac_id,i);
}
}
1 : {
mac_id = 1;
if(dmas_ids_p1[i]) {
MacTxPort[mac_id].BindDmaIntrDev(TxDma,i);
set_max_burst(mac_id,i);
}
}
2 : {
mac_id = 2;
if(dmas_ids_p2[i]) {
MacTxPort[mac_id].BindDmaIntrDev(TxDma,i);
set_max_burst(mac_id,i);
}
}
3 : {
mac_id = 3;
if(dmas_ids_p3[i]) {
MacTxPort[mac_id].BindDmaIntrDev(TxDma,i);
set_max_burst(mac_id,i);
}
}
}
}
}
//--- task to set the flow and pkt type -----//
task niu_tx_test_class :: set_flow(integer pkt_type, integer dma_id, integer mac_id)
{
flow1[dma_id] = new;
//----- Packet flow description -------//
flow1[dma_id].src_node.l2_addr = 48'haaaa_1111_0000;
flow1[dma_id].src_node.tci = random();
flow1[dma_id].src_node.src_port = 20'h00001;
// flow1[dma_id].dst_node.l2_addr = 48'hdddd_bbbb_0000;
flow1[dma_id].dst_node.tci = random();
flow1[dma_id].dst_node.src_port = 20'h00001;
flow1[dma_id].tup.src_tcp_udp_port = random();
flow1[dma_id].tup.dst_tcp_udp_port = random();
flow1[dma_id].frame.type = -1;
flow1[dma_id].frame.class_mask = 0;
flow1[dma_id].frame.class_funct = CLF_SRC;
flow1[dma_id].frame.data_type = DAT_SEQ|DAT_LEN_EXACT ;
flow1[dma_id].frame.data_seed = 0;
flow1[dma_id].flow_no = 0;
flow1[dma_id].rx_param.rcv_isn = 32'hA5A5_F5F5;
flow1[dma_id].fl_state.tcp_flags = 6'b00_0010;
flow1[dma_id].src_node.ip_addr = random();
flow1[dma_id].dst_node.ip_addr = random();
flow1[dma_id].src_node.ipv6_addr = random();
flow1[dma_id].dst_node.ipv6_addr = random();
// case statement for l2 DA
case(mac_id) {
0 : flow1[dma_id].dst_node.l2_addr = 48'h0100_FFFF_0000;
1 : flow1[dma_id].dst_node.l2_addr = 48'h0100_FFFF_0001;
2 : flow1[dma_id].dst_node.l2_addr = 48'h0100_FFFF_0002;
3 : flow1[dma_id].dst_node.l2_addr = 48'h0100_FFFF_0003;
}
case(pkt_type) {
1 : {
flow1[dma_id].frame.frame_type = 5'h0;
flow1[dma_id].frame.frame_class = CL_ARP;
}
2 : {
flow1[dma_id].frame.frame_type = 5'h0;
flow1[dma_id].frame.frame_class = CL_RARP;
}
3 : {
flow1[dma_id].frame.frame_type = 5'h2;
flow1[dma_id].frame.frame_class = CL_IP;
}
4 : {
flow1[dma_id].frame.frame_type = 5'h2;
flow1[dma_id].frame.frame_class = CL_IP;
flow1[dma_id].frame.header_length = 5 + random()%11;
}
5 : {
flow1[dma_id].frame.frame_type = 5'h2;
flow1[dma_id].frame.frame_class = CL_TCP;
flow1[dma_id].frame.header_length = 5 + random()%11;
}
6 : {
flow1[dma_id].frame.frame_type = 5'h2;
flow1[dma_id].frame.frame_class = CL_UDP;
flow1[dma_id].frame.header_length = 5 + random()%11;
}
7 : {
flow1[dma_id].frame.frame_type = 5'h6;
flow1[dma_id].frame.frame_class = CL_IP;
flow1[dma_id].frame.header_length = 5 + random()%11;
}
8 : {
flow1[dma_id].frame.frame_type = 5'h6;
flow1[dma_id].frame.frame_class = CL_TCP;
flow1[dma_id].frame.header_length = 5 + random()%11;
}
9 : {
flow1[dma_id].frame.frame_type = 5'h6;
flow1[dma_id].frame.frame_class = CL_UDP;
flow1[dma_id].frame.header_length = 5 + random()%11;
}
10 : {
flow1[dma_id].frame.frame_type = 5'h3;
flow1[dma_id].frame.frame_class = CL_IP;
flow1[dma_id].frame.header_length = 5 + random()%11;
}
11 : {
flow1[dma_id].frame.frame_type = 5'h3;
flow1[dma_id].frame.frame_class = CL_TCP;
flow1[dma_id].frame.header_length = 5 + random()%11;
}
12 : {
flow1[dma_id].frame.frame_type = 5'h3;
flow1[dma_id].frame.frame_class = CL_UDP;
flow1[dma_id].frame.header_length = 5 + random()%11;
}
13 : {
flow1[dma_id].frame.frame_type = 5'h7;
flow1[dma_id].frame.frame_class = CL_IP;
flow1[dma_id].frame.header_length = 5 + random()%11;
}
14 : {
flow1[dma_id].frame.frame_type = 5'h7;
flow1[dma_id].frame.frame_class = CL_TCP;
flow1[dma_id].frame.header_length = 5 + random()%11;
}
15 : {
flow1[dma_id].frame.frame_type = 5'h7;
flow1[dma_id].frame.frame_class = CL_UDP;
flow1[dma_id].frame.header_length = 5 + random()%11;
}
16 : {
flow1[dma_id].frame.frame_type = 5'ha;
flow1[dma_id].frame.frame_class = CL_IP_V6;
}
17 : {
flow1[dma_id].frame.frame_type = 5'ha;
flow1[dma_id].frame.frame_class = CL_TCP_IP_V6;
}
18 : {
flow1[dma_id].frame.frame_type = 5'ha;
flow1[dma_id].frame.frame_class = CL_UDP_IP_V6;
}
19 : {
flow1[dma_id].frame.frame_type = 5'he;
flow1[dma_id].frame.frame_class = CL_IP_V6;
}
20 : {
flow1[dma_id].frame.frame_type = 5'he;
flow1[dma_id].frame.frame_class = CL_TCP_IP_V6;
}
21 : {
flow1[dma_id].frame.frame_type = 5'he;
flow1[dma_id].frame.frame_class = CL_UDP_IP_V6;
}
22 : {
flow1[dma_id].frame.frame_type = 5'hb;
flow1[dma_id].frame.frame_class = CL_IP_V6;
}
23 : {
flow1[dma_id].frame.frame_type = 5'hb;
flow1[dma_id].frame.frame_class = CL_TCP_IP_V6;
}
24 : {
flow1[dma_id].frame.frame_type = 5'hb;
flow1[dma_id].frame.frame_class = CL_UDP_IP_V6;
}
25 : {
flow1[dma_id].frame.frame_type = 5'hf;
flow1[dma_id].frame.frame_class = CL_IP_V6;
}
26 : {
flow1[dma_id].frame.frame_type = 5'hf;
flow1[dma_id].frame.frame_class = CL_TCP_IP_V6;
}
27 : {
flow1[dma_id].frame.frame_type = 5'hf;
flow1[dma_id].frame.frame_class = CL_UDP_IP_V6;
}
}
}
task niu_tx_test_class :: set_pktconfig(flow_desc flow1, integer dma_id, integer mac_id)
{
PktGenConfig[dma_id] = new();
PktGenConfig[dma_id].mac_id = mac_id;
PktGenConfig[dma_id].flow = flow1;
}
task niu_tx_test_class :: tx_dma_init(integer mac_id,integer ring_len, integer dma_id)
{
bit [39:0] rng_st_addr;
integer tx_func_num;
/*FOR VIRT PIO*/
if (group_from_dma_channel[dma_id] != -1) // niu_dmc_virt.vr will populate this table
MacTxPort[mac_id].dma[dma_id].bind_to_group(group_from_dma_channel[dma_id]);
else if(tx_control.tx_vir_pio)
MacTxPort[mac_id].dma[dma_id].bind_to_group(dma_id);
// get the func num from the run command
tx_func_num = tx_control.tx_func_num;
// initialize the dma
MacTxPort[mac_id].dma[dma_id].xlate_on = 1;
MacTxPort[mac_id].dma[dma_id].InitTXDMA(ring_len,rng_st_addr,0,tx_func_num);
// based on command arg, enable or disable mask
if(tx_control.enb_intr)
MacTxPort[mac_id].dma[dma_id].SetTxEventMask(64'h0);
}
task niu_tx_test_class :: generate_pkts(integer no_of_pkts, integer mac_id, integer dma_id,
(integer last_pkt = 0))
{
integer j;
integer k = 1;
integer p_type;
for(j=0;j<no_of_pkts;j++) {
// set the mark bit count to zero
if(j == 0)
mk_count[dma_id] = 0;
// set pkt_type
if(tx_control.pkt_type == 0) {
p_type = 1 + random()%27;
printf("GEN_PKT : pkt_type %0d for pkt %0d\n",p_type,j);
set_flow(p_type,dma_id,mac_id);
} else set_flow(tx_control.pkt_type,dma_id,mac_id);
set_pktconfig(flow1[dma_id],dma_id,mac_id);
// set the pkt len for the pkt
if(specweb_traffic_pattern_tx !== null)
tx_control.pkt_len = specweb_traffic_pattern_tx.get_pkt_len();
set_pkt_len(tx_control.pkt_len,dma_id,j);
// set mark bit
if((j+1)%tx_control.mb_pkts == 0) {
PktGenConfig[dma_id].mark_bit = 1;
mk_count[dma_id]++;
} else
PktGenConfig[dma_id].mark_bit = 0;
// set gather mode
PktGenConfig[dma_id].g_mode = tx_control.gather_mode;
// insert pad bytes between the control hdr and l2 header
set_pad_bytes(dma_id,j);
// this is only for loop_back_mode
if(last_pkt) {
PktGenConfig[dma_id].loop_back_rxdma_num = mac_id;
PktGenConfig[dma_id].loop_back_rx_lastpacket = 1;
}
if((tx_control.random_gmode) || (tx_control.pkt_len == 0))
// call gen_txgather pkts function
call_gen_txgatherpkts(PktGenConfig[dma_id],mac_id,j,dma_id);
else
MacTxPort[mac_id].dma[dma_id].gen_txpacket(j*(dma_id + 1),PktGenConfig[dma_id]);
}
}
task niu_tx_test_class :: kick_dmas(integer no_of_pkts, integer mac_id, bit[23:0] dma_ids,integer port_enb)
{
integer i,j,i1;
bit [63:0] kick_limit[24] = 64'h0;
bit [63:0] accum_kick[24] = 64'h0;
bit [63:0] hd_ptr[24] = 64'h0;
bit [23:0] kick_done = 24'h0;
// integer kick_all = 1;
// based on the kick mode from the control file kick appropriately
if(port_enb) {
if(tx_control.kick_mode == 1) {
if(tx_control.random_rst)
kick_all_wrreset(no_of_pkts,mac_id,dma_ids);
else
kick_all(no_of_pkts,mac_id,dma_ids);
} else if(tx_control.kick_mode == 2) {
kick_npkts(no_of_pkts,mac_id,dma_ids);
} else if(tx_control.kick_mode == 3){
kick_rnum_pkts(no_of_pkts,mac_id,dma_ids);
}
} else repeat(2) @(posedge CLOCK);
}
//---- Task to Initial DMAS --------//
task niu_tx_test_class :: InitTxDMA(integer no_of_pkts,integer mac_id,integer dma_id)
{
integer j;
integer rng_len;
j = dma_id;
//------ TDMC init -------------//
if(tx_control.kick_mode == 2) {
if(tx_control.gather_mode || tx_control.random_gmode || (tx_control.pkt_len == 0))
rng_len = tx_control.kmode2_npkts*15%8 ? tx_control.kmode2_npkts*15/8 + 1 : tx_control.kmode2_npkts*15/8;
else
rng_len = tx_control.kmode2_npkts/8 + 2;
} else if(tx_control.kick_mode == 3) {
if(tx_control.gather_mode || tx_control.random_gmode || (tx_control.pkt_len == 0))
rng_len = 2 + random()%255;
else
rng_len = tx_control.ring_len;
} else {
if(tx_control.random_num_pkts) {
rand_num_pkts[j] = 1 + no_of_pkts/2 + random()%no_of_pkts/2;
printf("TX_TEST_CL : no_of_pkts for DMA %d is %d\n",dma_id,rand_num_pkts[j]);
if(tx_control.gather_mode || tx_control.random_gmode || (tx_control.pkt_len == 0))
rng_len = (rand_num_pkts[j]*15)%8 ? (rand_num_pkts[j]*15)/8 + 1 : (rand_num_pkts[j]*15)/8;
else
rng_len = rand_num_pkts[j]%8 ? rand_num_pkts[j]/8 + 1 : rand_num_pkts[j]/8;
} else {
if(tx_control.gather_mode || tx_control.random_gmode || (tx_control.pkt_len == 0)) {
if(tx_control.ring_len > 0)
rng_len = tx_control.ring_len;
else
rng_len = (no_of_pkts*15)%8 ? (no_of_pkts*15)/8 + 1 : (no_of_pkts*15)/8;
} else {
if(tx_control.ring_len > 0)
rng_len = tx_control.ring_len;
else
rng_len = no_of_pkts%8 ? no_of_pkts/8 + 1 : no_of_pkts/8;
}
}
}
be_msg.print(e_mesg_info,"tx_test_class","init_dmas","Ring_Length of DMA %d is %d\n",dma_id,rng_len);
tx_dma_init(mac_id,rng_len,dma_id);
}
//---- Task to kick all pkts at one go ------------//
task niu_tx_test_class :: kick_all(integer no_of_pkts, integer mac_id, bit[23:0] dma_ids)
{
shadow integer i1;
integer j;
integer dma_id;
bit [63:0] data;
bit done = 1'b0;
integer list;
integer sync_pkt_chk = 0;
integer num_dmas_bp = 0;
//--- New the Macport and assign the dma list to the mac port
list = dma_ids;
// MacTxPort[mac_id] = new(mac_id);
// add channels to the port for verif
if(tx_control.enb_intr) {
// this bind is taken care in the test
} else {
for(j=0;j<no_of_txdmas;j++) {
if(dma_ids[j]) {
MacTxPort[mac_id].add_channels(j);
set_max_burst(mac_id,j);
}
}
}
// bind the dmas to the port
MacTxPort[mac_id].SetActive(list);
tx_kick_done[mac_id] = 0;
//-- generate the pkts and kick all pkts ------//
for(i1=0;i1<no_of_txdmas;i1++) {
repeat(50) @(posedge CLOCK);
fork {
if(dma_ids[i1]) {
dma_id = i1;
InitTxDMA(no_of_pkts,mac_id,i1);
if(tx_control.random_num_pkts)
generate_pkts(rand_num_pkts[i1],mac_id,i1);
else
generate_pkts(no_of_pkts,mac_id,i1);
// unstall the DMA
MacTxPort[mac_id].dma[i1].SetTxCs(64'h2000_0000);
// add the start stop task here
if(tx_control.stop_unstall) {
fork
{
MacTxPort[mac_id].dma[i1].stop_unstall_dma(pkts_done[mac_id]);
}
join none
}
if(tx_ports_sync_semaphore != -1) {
semaphore_put(tx_ports_sync_semaphore, 1);
semaphore_get(WAIT, tx_ports_sync_semaphore, total_tx_ports);
semaphore_put(tx_ports_sync_semaphore, total_tx_ports);
printf("niu_tx_test_class got tx_ports_sync_semaphore :%0d, total_tx_ports:%0d\n",
tx_ports_sync_semaphore, total_tx_ports);
}
if(rx_ports_sync_semaphore != -1) {
semaphore_get(WAIT, rx_ports_sync_semaphore, total_tx_ports);
semaphore_put(rx_ports_sync_semaphore, total_tx_ports);
printf("niu_tx_test_class got rx_ports_sync_semaphore :%0d, total_tx_ports:%0d\n",
rx_ports_sync_semaphore, total_tx_ports);
}
MacTxPort[mac_id].dma[i1].setTxRingKick(MacTxPort[mac_id].dma[i1].desc_ring.ring_current_addr);
printf("DMA_id %d kicked at time %d\n", i1, TIME);
// add this to sync the pkt_cnt check
sync_pkt_chk++;
if(tx_control.sync_dmas) {
if(dma_ids[23] == 1'b1)
txc_util.txc_init(64'h1f);
}
repeat(2) @(posedge CLOCK);
if(tx_control.enb_intr) {
// do nothing taken care in ISR
} else {
fork {
mailbox_update(mac_id,i1);
}
join none
}
}
} join none
}
tx_kick_done[mac_id] = 1;
num_dmas_bp = get_num_of_dmas_bport(dma_ids);
// wait till sync_pkt_chk goes > 0
if(dma_ids == 24'h0)
// sync_pkt_chk++;
sync_pkt_chk = 0;
while(sync_pkt_chk != num_dmas_bp) {
repeat(100) @(posedge CLOCK);
}
if(tx_control.random_num_pkts)
MacTxPort[mac_id].check_randompkt_cnt(rand_num_pkts,tx_control.pktcnt_rd_intv);
else
MacTxPort[mac_id].check_pkt_cnt(no_of_pkts,tx_control.pktcnt_rd_intv);
if(get_plus_arg( CHECK, "MAC_LOOP_BACK=")) {
for(j=0;j<no_of_txdmas;j++) {
if(dma_ids[j] & ~done) {
done = 1;
dma_id = j;
generate_pkts(1,mac_id,dma_id,1);
MacTxPort[mac_id].dma[j].setTxRingKick(MacTxPort[mac_id].dma[j].desc_ring.ring_current_addr);
printf("TX_TEST_CL : LOOP_BACK_MODE last_pkt gentd for dma %d\n",dma_ids[j]);
}
}
}
if(get_plus_arg(CHECK,"BYPASS_TXDRR")) {
// do nothing
} else {
MacTxPort[mac_id].check_exit_status();
}
}
//---- Task to setup n pkts at a time and kick npkts ------------//
task niu_tx_test_class :: kick_npkts(integer no_of_pkts, integer mac_id, bit[23:0] dma_ids)
{
shadow integer i1;
integer npkts = tx_control.kmode2_npkts;
integer pkts_tobe_gentd[24];
bit [23:0] kick_done = 24'h0;
integer total_pkts[24];
bit [63:0] hd_ptr[24] = 64'h0;
bit [63:0] tail_ptr[24] = 64'h0;
integer list,j;
integer tot_pkts[24];
integer pkts_toreclaim[24];
integer loop_cnt[24];
integer wrap_cnt[24];
integer dect_pose[24];
integer dect_neg[24];
integer start[24];
integer count[24];
integer tail_wrap[24];
integer rd_tx_rng_hdl_delay = 50;
list = dma_ids;
// MacTxPort[mac_id] = new(mac_id);
// add channels to the port for verif
if(tx_control.enb_intr) {
// this bind is taken care in the test
} else {
for(j=0;j<no_of_txdmas;j++) {
if(dma_ids[j]) {
MacTxPort[mac_id].add_channels(j);
set_max_burst(mac_id,j);
}
}
}
// bind the dmas to the port
MacTxPort[mac_id].SetActive(list);
for(i1=0;i1<no_of_txdmas;i1++) {
fork {
tot_pkts[i1] = 0;
pkts_toreclaim[i1] = 0;
loop_cnt[i1] = 0;
wrap_cnt[i1] = 0;
dect_pose[i1] = 0;
dect_neg[i1] = 1;
start[i1] = 0;
count[i1] = 0;
tail_wrap[i1] = 0;
// hd_wrap[i1] = 0;
if(dma_ids[i1]) {
InitTxDMA(no_of_pkts,mac_id,i1);
// unstall the DMA
MacTxPort[mac_id].dma[i1].SetTxCs(64'h0);
total_pkts[i1] = 0;
// add the start stop task here
if(tx_control.stop_unstall) {
fork
{
MacTxPort[mac_id].dma[i1].stop_unstall_dma(pkts_done[mac_id]);
}
join none
}
while(~kick_done[i1]) {
loop_cnt[i1]++;
count[i1] = 0;
printf("TX_TEST_CL : loop count %0d\n",loop_cnt[i1]);
if(total_pkts[i1] < no_of_pkts) {
if((no_of_pkts - total_pkts[i1]) > npkts) {
if(tx_control.random_num_pkts)
pkts_tobe_gentd[i1] = 1 + random()%npkts;
else
pkts_tobe_gentd[i1] = npkts;
generate_pkts(pkts_tobe_gentd[i1],mac_id,i1);
if(tx_control.kick_partial)
tail_ptr[i1] = MacTxPort[mac_id].dma[i1].desc_ring.ring_current_addr - 64'h20;
else
tail_ptr[i1] = MacTxPort[mac_id].dma[i1].desc_ring.ring_current_addr;
} else {
pkts_tobe_gentd[i1] = no_of_pkts - total_pkts[i1];
generate_pkts(pkts_tobe_gentd[i1],mac_id,i1);
tail_ptr[i1] = MacTxPort[mac_id].dma[i1].desc_ring.ring_current_addr;
}
printf("Tx_test_cl : Kick_mode2, pkts_gen_in current kick %d for dma %d\n",pkts_tobe_gentd[i1],i1);
printf("Tail_PTR %0h\n",tail_ptr[i1]);
if(tx_ports_sync_semaphore != -1) {
semaphore_put(tx_ports_sync_semaphore, 1);
semaphore_get(WAIT, tx_ports_sync_semaphore, total_tx_ports);
semaphore_put(tx_ports_sync_semaphore, total_tx_ports);
printf("niu_tx_test_class got tx_ports_sync_semaphore :%0d, total_tx_ports:%0d\n",
tx_ports_sync_semaphore, total_tx_ports);
}
if(rx_ports_sync_semaphore != -1) {
semaphore_get(WAIT, rx_ports_sync_semaphore, total_tx_ports);
semaphore_put(rx_ports_sync_semaphore, total_tx_ports);
printf("niu_tx_test_class got rx_ports_sync_semaphore :%0d, total_tx_ports:%0d\n",
rx_ports_sync_semaphore, total_tx_ports);
}
MacTxPort[mac_id].dma[i1].setTxRingKick(tail_ptr[i1]);
tail_wrap[i1] = MacTxPort[mac_id].dma[i1].desc_ring.ring_wrapped;
total_pkts[i1] = total_pkts[i1] + pkts_tobe_gentd[i1];
// printf("TX_TEST_CL : TOT_PKTS is %0d for dma %0d\n",total_pkts[i1],i1);
MacTxPort[mac_id].dma[i1].RdTxRngHDL(hd_ptr[i1]);
// hd_wrap[i1] = hd_ptr[i1][19];
// wait until certain diff between hd and tail ptr
// while((tail_ptr[i1][18:3] - hd_ptr[i1][18:3] != 0) && (count[i1] < 50))
while(tail_ptr[i1][18:3] - hd_ptr[i1][18:3] != 0) {
MacTxPort[mac_id].dma[i1].RdTxRngHDL(hd_ptr[i1]);
if(get_plus_arg(CHECK,"RD_TX_RNG_HDL_DELAY"))
rd_tx_rng_hdl_delay = get_plus_arg(NUM,"RD_TX_RNG_HDL_DELAY");
repeat(rd_tx_rng_hdl_delay) @(posedge CLOCK);
count[i1]++;
}
printf("TX_TEST CL : head_ptr %d\n",hd_ptr[i1][18:3]);
printf("TX_TEST CL : head_ptr_wrap %d\n",hd_ptr[i1][19]);
if(dect_pose[i1] == 0) {
if(hd_ptr[i1][19]) {
wrap_cnt[i1]++;
dect_pose[i1] = 1;
dect_neg[i1] = 0;
}
}
if(dect_neg[i1] == 0) {
if(~hd_ptr[i1][19]) {
wrap_cnt[i1]++;
dect_pose[i1] = 0;
dect_neg[i1] = 1;
}
}
// read the pkt_cnt
// MacTxPort[mac_id].dma[i1].RdTxPktCnt(tot_pkts);
tot_pkts[i1] = wrap_cnt[i1]*tx_control.ring_len*8 + hd_ptr[i1][18:3];
pkts_toreclaim[i1] = tot_pkts[i1] - pkts_toreclaim[i1];
// call the task to reclaim the buffers
if(start[i1] == 0) {
MacTxPort[mac_id].dma[i1].reclaim_buffers(1,pkts_toreclaim[i1]-1);
start[i1] = 1;
} else MacTxPort[mac_id].dma[i1].reclaim_buffers(1,pkts_toreclaim[i1]);
pkts_toreclaim[i1] = tot_pkts[i1];
} else {
kick_done[i1] = 1'b1;
}
}
// MacTxPort[mac_id].dma[i1].reclaim_buffers(1,loop_cnt[i1]-1);
} else repeat(2) @(posedge CLOCK);
} join none
}
// wait_child();
MacTxPort[mac_id].check_pkt_cnt(no_of_pkts,tx_control.pktcnt_rd_intv);
if(get_plus_arg(CHECK,"BYPASS_TXDRR")) {
// do nothing
} else {
MacTxPort[mac_id].check_exit_status();
}
}
//---- Task to setup and kick random number of pkts ------------//
//--- without waiting for head_ptr == tail_ptr -----------------//
task niu_tx_test_class :: kick_rnum_pkts(integer no_of_pkts, integer mac_id, bit[23:0] dma_ids)
{
shadow integer i1,k;
integer npkts;
integer pkts_tobe_gentd[24];
bit [23:0] kick_done = 24'h0;
integer total_pkts[24];
bit [63:0] hd_ptr[24];
bit [63:0] tail_ptr[24];
// bit [63:0] kick_ptr[24];
integer kick_ptr[24];
integer list,j;
integer hd_wrap[24];
integer tail_wrap[24];
integer tot_pkts[24];
integer pkts_toreclaim[24];
integer loop_cnt[24];
integer wrap_cnt[24];
integer dect_pose[24];
integer dect_neg[24];
integer start[24];
integer count[24];
list = dma_ids;
// MacTxPort[mac_id] = new(mac_id);
// add channels to the port for verif
if(tx_control.enb_intr) {
// this bind is taken care in the test
} else {
for(j=0;j<no_of_txdmas;j++) {
if(dma_ids[j]) {
MacTxPort[mac_id].add_channels(j);
set_max_burst(mac_id,j);
}
}
}
// bind the dmas to the port
MacTxPort[mac_id].SetActive(list);
for(i1=0;i1<no_of_txdmas;i1++) {
fork {
tot_pkts[i1] = 0;
pkts_toreclaim[i1] = 0;
loop_cnt[i1] = 0;
wrap_cnt[i1] = 0;
dect_pose[i1] = 0;
dect_neg[i1] = 1;
start[i1] = 0;
count[i1] = 0;
hd_ptr[i1] = 64'h0;
tail_ptr[i1] = 64'h0;
kick_ptr[i1] = 0;
hd_wrap[i1] = 0;
tail_wrap[i1] = 0;
if(dma_ids[i1]) {
InitTxDMA(no_of_pkts,mac_id,i1);
// unstall the DMA
MacTxPort[mac_id].dma[i1].SetTxCs(64'h0);
printf("TX_TEST_CL : kick_done for dma %0d is %0b\n",i1,kick_done[i1]);
total_pkts[i1] = 0;
printf("TX_TEST_CL : Total_pkts for dma %0d is %0d\n",i1,total_pkts[i1]);
// add the start stop task here
if(tx_control.stop_unstall) {
fork
{
for(k=0;k<no_of_pkts;k++) {
repeat(random()%100) @(posedge CLOCK);
random_stop_start_dma(mac_id,i1);
}
// MacTxPort[mac_id].dma[i1].stop_unstall_dma(100);
}
join none
}
while(~kick_done[i1]) {
loop_cnt[i1]++;
count[i1] = 0;
printf("TX_TEST_CL : loop count %0d\n",loop_cnt[i1]);
if(total_pkts[i1] < no_of_pkts) {
MacTxPort[mac_id].dma[i1].RdTxRngHDL(hd_ptr[i1]);
hd_wrap[i1] = hd_ptr[i1][19];
if(tail_ptr[i1][18:3] > hd_ptr[i1][18:3])
kick_ptr[i1] = MacTxPort[mac_id].dma[i1].ring_size*8 - tail_ptr[i1][18:3] + hd_ptr[i1][18:3];
else if(tail_ptr[i1][18:3] < hd_ptr[i1][18:3])
kick_ptr[i1] = hd_ptr[i1][18:3] - tail_ptr[i1][18:3];
else if(tail_ptr[i1][18:3] == hd_ptr[i1][18:3]) {
if(tail_wrap[i1] == hd_wrap[i1])
kick_ptr[i1] = MacTxPort[mac_id].dma[i1].ring_size*8;
else
kick_ptr[i1] = 0;
}
if(tx_control.gather_mode || tx_control.random_gmode || (tx_control.pkt_len == 0)) {
npkts = kick_ptr[i1]/15;
} else {
npkts = kick_ptr[i1];
}
if(npkts > (no_of_pkts - total_pkts[i1]))
npkts = no_of_pkts - total_pkts[i1];
printf("TX_TEST_CL : random_kicks , pkts kicked %d for DMA %d\n", npkts,i1);
if(npkts > 0)
pkts_tobe_gentd[i1] = 1 + random()%npkts;
else
pkts_tobe_gentd[i1] = 0;
if(pkts_tobe_gentd[i1] > 0) {
generate_pkts(pkts_tobe_gentd[i1],mac_id,i1);
tail_ptr[i1] = MacTxPort[mac_id].dma[i1].desc_ring.ring_current_addr;
printf("Tail_PTR %0h\n",tail_ptr[i1]);
if(tx_ports_sync_semaphore != -1) {
semaphore_put(tx_ports_sync_semaphore, 1);
semaphore_get(WAIT, tx_ports_sync_semaphore, total_tx_ports);
semaphore_put(tx_ports_sync_semaphore, total_tx_ports);
printf("niu_tx_test_class got tx_ports_sync_semaphore :%0d, total_tx_ports:%0d\n",
tx_ports_sync_semaphore, total_tx_ports);
}
if(rx_ports_sync_semaphore != -1) {
semaphore_get(WAIT, rx_ports_sync_semaphore, total_tx_ports);
semaphore_put(rx_ports_sync_semaphore, total_tx_ports);
printf("niu_tx_test_class got rx_ports_sync_semaphore :%0d, total_tx_ports:%0d\n",
rx_ports_sync_semaphore, total_tx_ports);
}
MacTxPort[mac_id].dma[i1].setTxRingKick(tail_ptr[i1]);
}
tail_wrap[i1] = MacTxPort[mac_id].dma[i1].desc_ring.ring_wrapped;
total_pkts[i1] = total_pkts[i1] + pkts_tobe_gentd[i1];
// printf("TX_TEST_CL : TOT_PKTS is %0d for dma %0d\n",total_pkts[i1],i1);
if(dect_pose[i1] == 0) {
if(hd_ptr[i1][19]) {
wrap_cnt[i1]++;
dect_pose[i1] = 1;
dect_neg[i1] = 0;
}
}
if(dect_neg[i1] == 0) {
if(~hd_ptr[i1][19]) {
wrap_cnt[i1]++;
dect_pose[i1] = 0;
dect_neg[i1] = 1;
}
}
// MacTxPort[mac_id].dma[i1].RdTxPktCnt(tot_pkts[i1]);
tot_pkts[i1] = wrap_cnt[i1]*MacTxPort[mac_id].dma[i1].ring_size*8 + hd_ptr[i1][18:3];
pkts_toreclaim[i1] = tot_pkts[i1] - pkts_toreclaim[i1];
// call the task to reclaim the buffers
if(pkts_toreclaim[i1] > 0) {
if(start[i1] == 0) {
MacTxPort[mac_id].dma[i1].reclaim_buffers(1,pkts_toreclaim[i1]-1);
start[i1] = 1;
} else MacTxPort[mac_id].dma[i1].reclaim_buffers(1,pkts_toreclaim[i1]);
}
pkts_toreclaim[i1] = tot_pkts[i1];
} else {
kick_done[i1] = 1'b1;
}
repeat(random()%200) @(posedge CLOCK);
}
// MacTxPort[mac_id].dma[i1].reclaim_buffers(1,loop_cnt[i1]-1);
} else repeat(2) @(posedge CLOCK);
} join none
}
// wait_child();
MacTxPort[mac_id].check_pkt_cnt(no_of_pkts,tx_control.pktcnt_rd_intv);
if(get_plus_arg(CHECK,"BYPASS_TXDRR")) {
// do nothing
} else {
MacTxPort[mac_id].check_exit_status();
}
}
//---- Task to setup pkt_len----------------//
task niu_tx_test_class :: set_pkt_len(integer pkt_len_param, integer dma_id, integer pkt_num) {
// set the pkt len for the pkt
case(pkt_len_param) {
0 : {
// PktGenConfig[dma_id].data_length = 128 + random()%9189;
randcase {
27: PktGenConfig[dma_id].data_length = urandom_range(500, 128);
13: PktGenConfig[dma_id].data_length = urandom_range(1000, 500);
40: PktGenConfig[dma_id].data_length = urandom_range(1600, 1000);
10: PktGenConfig[dma_id].data_length = urandom_range(4000, 1600);
10: PktGenConfig[dma_id].data_length = urandom_range(9200, 4000);
}
}
1 : PktGenConfig[dma_id].data_length = 64 + pkt_num;
2 : PktGenConfig[dma_id].data_length = 500 + pkt_num;
3 : PktGenConfig[dma_id].data_length = 1000+ pkt_num;
4 : PktGenConfig[dma_id].data_length = 1500 + pkt_num;
5 : PktGenConfig[dma_id].data_length = 2000 + pkt_num;
6 : PktGenConfig[dma_id].data_length = 2500 + pkt_num;
7 : PktGenConfig[dma_id].data_length = 3000 + pkt_num;
8 : PktGenConfig[dma_id].data_length = 3500 + pkt_num;
9 : PktGenConfig[dma_id].data_length = 4000 + pkt_num;
10 : PktGenConfig[dma_id].data_length = 4500 + pkt_num;
11 : PktGenConfig[dma_id].data_length = 5000 + pkt_num;
12 : PktGenConfig[dma_id].data_length = 5500 + pkt_num;
13 : PktGenConfig[dma_id].data_length = 6000 + pkt_num;
14 : PktGenConfig[dma_id].data_length = 6500 + pkt_num;
15 : PktGenConfig[dma_id].data_length = 7000 + pkt_num;
16 : PktGenConfig[dma_id].data_length = 7500 + pkt_num;
17 : PktGenConfig[dma_id].data_length = 8000 + pkt_num;
18 : PktGenConfig[dma_id].data_length = 8500 + pkt_num;
19 : PktGenConfig[dma_id].data_length = 9000 + pkt_num;
default : {
// added this piece of code to protect pkt_lens > 9588
if(pkt_len_param > 9588)
PktGenConfig[dma_id].data_length = 9588;
else
PktGenConfig[dma_id].data_length = pkt_len_param;
}
}
}
task niu_tx_test_class :: set_pad_bytes(integer dma_id, integer pkt_num) {
// set pad bytes
case(tx_control.insert_pad) {
0 : PktGenConfig[dma_id].pad = 0;
1 : PktGenConfig[dma_id].pad = pkt_num%8; // sweep the pad bytes
2 : PktGenConfig[dma_id].pad = random()%8;
3 : PktGenConfig[dma_id].pad = tx_control.pad_bytes;
}
// printf("TX_TEST_CL : Pad offset is %0d for pkt %0d\n",PktGenConfig[dma_id].pad,pkt_num);
}
task niu_tx_test_class :: setup_random_dmabinds(var bit [23:0] dmas_port0, var bit [23:0] dmas_port1,
var bit [23:0] dmas_port2, var bit [23:0] dmas_port3)
{
integer i,dma_num;
integer no_of_port0_dmas;
integer no_of_port1_dmas;
integer no_of_port2_dmas;
integer no_of_port3_dmas;
integer no_of_dmas_unused;
bit [23:0] mask = 24'h0;
bit [23:0] in_dmas_port0 = 24'h0;
bit [23:0] in_dmas_port1 = 24'h0;
bit [23:0] in_dmas_port2 = 24'h0;
bit [23:0] in_dmas_port3 = 24'h0;
no_of_port0_dmas = 1 + random()%no_of_txdmas;
printf("RAND_DMA_BIND : No_of Dmas bound to Port0 is %0d\n",no_of_port0_dmas);
for(i=0;i<no_of_port0_dmas;i++) {
dma_num = random()%no_of_txdmas;
while(mask[dma_num] == 1'b1) {
dma_num = random()%no_of_txdmas;
}
printf("RAND_DMA_BIND : Dma_Num %0d bound to Port0\n",dma_num);
in_dmas_port0[dma_num] = 1'b1;
mask = mask | in_dmas_port0;
}
printf("RAND_DMA_BIND : MASK after port0 assign %0h\n",mask);
no_of_dmas_unused = no_of_txdmas - no_of_port0_dmas;
if(no_of_txdmas == 16) {
if(no_of_dmas_unused == 0)
no_of_port1_dmas = 0;
else
// no_of_port1_dmas = 1 + random()%no_of_dmas_unused;
// assign the remaining DMAs to port1
no_of_port1_dmas = no_of_dmas_unused;
printf("RAND_DMA_BIND : No_of Dmas bound to Port1 is %0d\n",no_of_port1_dmas);
for(i=0;i<no_of_port1_dmas;i++) {
dma_num = random()%no_of_txdmas;
while(mask[dma_num] == 1'b1) {
dma_num = random()%no_of_txdmas;
}
printf("RAND_DMA_BIND : Dma_Num %0d bound to Port1\n",dma_num);
in_dmas_port1[dma_num] = 1'b1;
mask = mask | in_dmas_port1;
}
printf("RAND_DMA_BIND : MASK after port1 assign %0h\n",mask);
dmas_port0 = in_dmas_port0;
dmas_port1 = in_dmas_port1;
printf("RAND_DMA_BIND : port 0 DMA_BIND %0h\n",dmas_port0);
printf("RAND_DMA_BIND : port 1 DMA_BIND %0h\n",dmas_port1);
} else if(no_of_txdmas == 24) {
if(no_of_dmas_unused == 0) {
no_of_port1_dmas = 0;
no_of_port2_dmas = 0;
no_of_port3_dmas = 0;
in_dmas_port1 = 24'h0;
in_dmas_port2 = 24'h0;
in_dmas_port3 = 24'h0;
} else {
no_of_port1_dmas = 1 + random()%no_of_dmas_unused;
printf("RAND_DMA_BIND : No_of Dmas bound to Port1 is %0d\n",no_of_port1_dmas);
for(i=0;i<no_of_port1_dmas;i++) {
dma_num = random()%no_of_txdmas;
while(mask[dma_num] == 1'b1) {
dma_num = random()%no_of_txdmas;
}
printf("RAND_DMA_BIND : Dma_Num %0d bound to Port1\n",dma_num);
in_dmas_port1[dma_num] = 1'b1;
mask = mask | in_dmas_port1;
}
printf("RAND_DMA_BIND : MASK after port1 assign %0h\n",mask);
no_of_dmas_unused = no_of_dmas_unused - no_of_port1_dmas;
if(no_of_dmas_unused == 0) {
no_of_port2_dmas = 0;
no_of_port3_dmas = 0;
in_dmas_port2 = 24'h0;
in_dmas_port3 = 24'h0;
} else {
no_of_port2_dmas = 1 + random()%no_of_dmas_unused;
printf("RAND_DMA_BIND : No_of Dmas bound to Port2 is %0d\n",no_of_port2_dmas);
for(i=0;i<no_of_port2_dmas;i++) {
dma_num = random()%no_of_txdmas;
while(mask[dma_num] == 1'b1) {
dma_num = random()%no_of_txdmas;
}
printf("RAND_DMA_BIND : Dma_Num %0d bound to Port2\n",dma_num);
in_dmas_port2[dma_num] = 1'b1;
mask = mask | in_dmas_port2;
}
printf("RAND_DMA_BIND : MASK after port2 assign %0h\n",mask);
no_of_dmas_unused = no_of_dmas_unused - no_of_port2_dmas;
if(no_of_dmas_unused == 0) {
no_of_port3_dmas = 0;
in_dmas_port3 = 24'h0;
} else {
no_of_port3_dmas = no_of_dmas_unused;
printf("RAND_DMA_BIND : No_of Dmas bound to Port3 is %0d\n",no_of_port3_dmas);
for(i=0;i<no_of_port3_dmas;i++) {
dma_num = random()%no_of_txdmas;
while(mask[dma_num] == 1'b1) {
dma_num = random()%no_of_txdmas;
}
printf("RAND_DMA_BIND : Dma_Num %0d bound to Port3\n",dma_num);
in_dmas_port3[dma_num] = 1'b1;
mask = mask | in_dmas_port3;
}
printf("RAND_DMA_BIND : MASK after port3 assign %0h\n",mask);
}
}
}
dmas_port0 = in_dmas_port0;
dmas_port1 = in_dmas_port1;
dmas_port2 = in_dmas_port2;
dmas_port3 = in_dmas_port3;
printf("RAND_DMA_BIND : port 0 DMA_BIND %0h\n",dmas_port0);
printf("RAND_DMA_BIND : port 1 DMA_BIND %0h\n",dmas_port1);
printf("RAND_DMA_BIND : port 2 DMA_BIND %0h\n",dmas_port2);
printf("RAND_DMA_BIND : port 3 DMA_BIND %0h\n",dmas_port3);
}
}
task niu_tx_test_class :: call_gen_txgatherpkts(TxPacketGenConfig PktGenConfig, integer mac_id, integer pkt_num, integer dma_id)
{
integer i;
integer no_of_gathers;
integer avg_len_pbuff;
integer len_remaining;
integer pkt_page_id;
@(posedge CLOCK);
// no_of_gathers = 1 + random()%15;
// printf("RAND_GTHR : no_of_gathers %0d\n",no_of_gathers);
// avg_len_pbuff = PktGenConfig.data_length%no_of_gathers + 1;
len_remaining = PktGenConfig.data_length - 4; // crc not included
// check if len greater than 8100 bytes change the no_gathers
if(len_remaining > 8100)
no_of_gathers = 3 + random()%13;
// no_of_gathers = 3;
else if(len_remaining > 4060)
no_of_gathers = 2 + random()%14;
// no_of_gathers = 2;
else no_of_gathers = 1 + random()%15;
printf("RAND_GTHR : no_of_gathers %0d\n",no_of_gathers);
avg_len_pbuff = PktGenConfig.data_length%no_of_gathers + 1;
// PktGenConfig.gConfig_noOfDesc = no_of_gathers;
PktGenConfig.gConfig_mode = 1;
for(i=0;i<no_of_gathers;i++) {
// randomize the addroffset except the first descriptor
if(tx_control.random_addroffset) {
if(i==0)
PktGenConfig.gConfig_alignment[i] = 16;
else
PktGenConfig.gConfig_alignment[i] = 1;
} else {
// PktGenConfig.gConfig_alignment[i] = 16;
PktGenConfig.gConfig_alignment[i] = tx_control.byte_align;
}
printf("RAND_GTHR : address_offset for gather %0d is %0d\n",i,PktGenConfig.gConfig_alignment[i]);
if(no_of_gathers == 1)
PktGenConfig.gConfig_length[i] = PktGenConfig.data_length - 4;
else if(i == (no_of_gathers - 1))
PktGenConfig.gConfig_length[i] = len_remaining;
else if(i == (no_of_gathers - 3)) {
if(len_remaining > 8160)
PktGenConfig.gConfig_length[i] = 4060;
else {
if(i == 0) {
if(get_plus_arg(CHECK,"FDESC_SLINE_BYTE_ALIGN"))
PktGenConfig.gConfig_length[i] = 1 + random()%4060;
else
PktGenConfig.gConfig_length[i] = 16 + random()%4045;
} else {
PktGenConfig.gConfig_length[i] = 1 + random()%4080;
}
if(PktGenConfig.gConfig_length[i] >= len_remaining) {
PktGenConfig.gConfig_length[i] = len_remaining;
no_of_gathers = i + 1;
}
}
} else if(i == (no_of_gathers - 2)) {
if(len_remaining > 4060)
PktGenConfig.gConfig_length[i] = 4060;
else {
if(i == 0) {
if(get_plus_arg(CHECK,"FDESC_SLINE_BYTE_ALIGN"))
PktGenConfig.gConfig_length[i] = 1 + random()%4060;
else
PktGenConfig.gConfig_length[i] = 16 + random()%4065;
} else {
PktGenConfig.gConfig_length[i] = 1 + random()%4080;
}
if(PktGenConfig.gConfig_length[i] >= len_remaining) {
PktGenConfig.gConfig_length[i] = len_remaining;
no_of_gathers = i + 1;
}
}
} else {
if(i == 0) {
if(get_plus_arg(CHECK,"FDESC_SLINE_BYTE_ALIGN"))
PktGenConfig.gConfig_length[i] = 1 + random()%4060;
else
PktGenConfig.gConfig_length[i] = 16 + random()%4045;
} else {
PktGenConfig.gConfig_length[i] = 1 + random()%4060;
}
if(PktGenConfig.gConfig_length[i] >= len_remaining) {
PktGenConfig.gConfig_length[i] = len_remaining;
no_of_gathers = i + 1;
}
}
printf("RAND_GTHR : length_of_gather %0d\n",PktGenConfig.gConfig_length[i]);
len_remaining = len_remaining - PktGenConfig.gConfig_length[i];
printf("RAND_GTHR : remainder pkt_len %0d\n",len_remaining);
}
PktGenConfig.gConfig_noOfDesc = no_of_gathers;
printf("RAND_GTHR : Actual no_of_gathers %0d\n",no_of_gathers);
pkt_page_id = random()%2 ? MacTxPort[mac_id].dma[dma_id].page1_id : MacTxPort[mac_id].dma[dma_id].page0_id;
MacTxPort[mac_id].dma[dma_id].gen_txGatherPackets(PktGenConfig,pkt_page_id);
}
task niu_tx_test_class :: mailbox_update(integer mac_id, integer dma_id)
{
bit [63:0] data;
bit [63:0] rd_data;
while (!pkts_done[mac_id]) {
// enable the mailbox update
// do a read modify write
MacTxPort[mac_id].dma[dma_id].Read_TxCs(rd_data);
if(rd_data[31])
data = 64'h8000_0000;
else {
data = {rd_data[63:30],1'b1,rd_data[28:0]};
MacTxPort[mac_id].dma[dma_id].SetTxCs(data);
mailbox_read(mac_id,dma_id);
}
}
}
task niu_tx_test_class :: mailbox_read(integer mac_id, integer dma_id)
{
bit [39:0] address;
bit [63:0] rd_data;
integer mbox_to = 100;
integer done = 0;
while(!done && !pkts_done[mac_id]) {
if(get_plus_arg(CHECK,"TX_MB_READ_TO"))
mbox_to = get_plus_arg(NUM,"TX_MB_READ_TO");
repeat (mbox_to) @(posedge CLOCK);
// address = TX_CS + dma_id*40'h200;
// gen_pio_drv.pio_rd(address,rd_data);
MacTxPort[mac_id].dma[dma_id].Read_TxCs(rd_data);
if(~rd_data[29]) {
done = 1;
} else {
done = 0;
}
}
}
task niu_tx_test_class :: clear_mk(integer dma_id)
{
bit [39:0] address;
bit [63:0] rd_data;
bit [63:0] wr_data;
address = TX_CS + dma_id*40'h200;
gen_pio_drv.pio_rd(address,rd_data);
}
task niu_tx_test_class :: sync_on_pkts_done(integer mac_id)
{
pkts_done[mac_id] = 0;
sync(ALL,TX_rvcd_allpkts[mac_id]);
pkts_done[mac_id] = 1;
}
// add task to set the maxburst for
task niu_tx_test_class :: set_max_burst(integer mac_id, integer dma_id)
{
bit [63:0] max_burst;
if(tx_control.random_maxburst) {
max_burst = 64 + random()%16000;
printf("TX_TEST_CL : Max_burst for DMA %0d is %0h\n",dma_id,max_burst);
} else {
case(mac_id) {
0 : max_burst = tx_control.port0_max_burst;
1 : max_burst = tx_control.port1_max_burst;
2 : max_burst = tx_control.port2_max_burst;
3 : max_burst = tx_control.port3_max_burst;
}
}
MacTxPort[mac_id].dma[dma_id].SetTxMaxBurst(max_burst);
}
// add task to read when expecting error cases
task niu_tx_test_class :: check_tx_cs(integer mac_id, integer dma_id, string err_code, (integer
chk_set=0),(integer chk_clr = 0))
{
bit [39:0] address;
bit [63:0] rd_data;
bit [63:0] wr_data;
case(err_code) {
"Mbox_Error" : {
// call the read to the tx_cs register
if(chk_set) {
address = TX_CS + dma_id*40'h200;
gen_pio_drv.pio_rd(address,rd_data);
// check to see if the mbox_err bit set
if(~rd_data[7])
printf("ERROR MBOX_ERR bit not set\n");
else {
err_detected = 1;
printf("INFO MBOX_ERR bit SET\n");
}
}
// do a read back to check if mbox err cleared
if(chk_clr) {
address = TX_CS + dma_id*40'h200;
gen_pio_drv.pio_rd(address,rd_data);
if(rd_data[7])
printf("ERROR MBOX_ERR bit not Cleared\n");
else printf("INFO MBOX_ERR bit CLRD\n");
}
}
"Nack_Pref_Error" : {
// check to see if the mbox_err bit set
if(chk_set) {
address = TX_CS + dma_id*40'h200;
gen_pio_drv.pio_rd(address,rd_data);
if(~rd_data[3])
printf("ERROR NACK_PREF_ERR bit not set\n");
else {
err_detected = 1;
printf("INFO NACK_PREF_ERR bit SET\n");
}
}
// do a read back to check if nack_pref err cleared
if(chk_clr) {
address = TX_CS + dma_id*40'h200;
gen_pio_drv.pio_rd(address,rd_data);
if(rd_data[3])
printf("ERROR NACK_PREF_ERR bit not Cleared\n");
else printf("INFO NACK_PREF_ERR bit CLRD\n");
}
}
"Conf_Part_Error" : {
// check to see if the mbox_err bit set
if(chk_set) {
address = TX_CS + dma_id*40'h200;
gen_pio_drv.pio_rd(address,rd_data);
if(~rd_data[1])
printf("ERROR CONF_PART_ERR bit not set\n");
else {
err_detected = 1;
printf("INFO CONF_PART_ERR bit SET\n");
}
}
// do a read back to check if nack_pref err cleared
if(chk_clr) {
address = TX_CS + dma_id*40'h200;
gen_pio_drv.pio_rd(address,rd_data);
if(rd_data[1])
printf("ERROR CONF_PART_ERR bit not Cleared\n");
else printf("INFO CONF_PART_ERR bit CLRD\n");
}
}
"PSize_Error" : {
// check to see if the pkt_sz_err bit set
if(chk_set) {
address = TX_CS + dma_id*40'h200;
gen_pio_drv.pio_rd(address,rd_data);
if(~rd_data[6])
printf("ERROR PKT_SZ_ERR bit not set\n");
else {
err_detected = 1;
printf("INFO PKT_SZ_ERR bit SET\n");
}
}
// do a read back to check if pkt_sz_err cleared
if(chk_clr) {
address = TX_CS + dma_id*40'h200;
gen_pio_drv.pio_rd(address,rd_data);
if(rd_data[6])
printf("ERROR PKT_SZ_ERR bit not Cleared\n");
else printf("INFO PKT_SZ_ERR bit CLRD\n");
}
}
}
}
task niu_tx_test_class :: set_port_control(integer p0_enb, integer p1_enb, integer p2_enb, integer p3_enb)
{
bit [63:0] ctrl_data;
bit [3:0] port_enb;
port_enb[0] = p0_enb;
port_enb[1] = p1_enb;
port_enb[2] = p2_enb;
port_enb[3] = p3_enb;
ctrl_data = {59'h0,1'b1,port_enb};
txc_util.txc_init(ctrl_data);
}
task niu_tx_test_class :: random_reset_reinit(integer mac_id, integer dma_id, integer no_of_pkts, var integer pkts_xmttd)
{
integer i;
MacTxPort[mac_id].dma[dma_id].reset_dma();
pkts_xmttd = MacTxPort[mac_id].dma[dma_id].getPktCnt();
printf("reset_reinit : pkts_xmttd %d\n",pkts_xmttd);
MacTxPort[mac_id].delete_channels(dma_id);
MacTxPort[mac_id].add_channels(dma_id);
InitTxDMA(no_of_pkts,mac_id,dma_id);
set_max_burst(mac_id,dma_id);
generate_pkts(no_of_pkts,mac_id,dma_id);
// unstall the DMA
MacTxPort[mac_id].dma[dma_id].SetTxCs(64'h2000_0000);
MacTxPort[mac_id].dma[dma_id].setTxRingKick(MacTxPort[mac_id].dma[dma_id].desc_ring.ring_current_addr);
}
task niu_tx_test_class :: random_stop_start_dma(integer mac_id, integer dma_id) {
MacTxPort[mac_id].dma[dma_id].stop_dma();
repeat (random()%500) @(posedge CLOCK);
MacTxPort[mac_id].dma[dma_id].SetTxCs(64'h0);
}
//---- Task to kick all pkts at one go ------------//
task niu_tx_test_class :: kick_all_wrreset(integer no_of_pkts, integer mac_id, bit[23:0] dma_ids)
{
shadow integer i1,k;
integer j;
integer dma_id;
bit [63:0] data;
bit done = 1'b0;
integer list;
integer pkt_cnt[24];
integer t_pkt_cnt[24];
bit [23:0] sync_pkt_chk;
//--- New the Macport and assign the dma list to the mac port
list = dma_ids;
// add channels to the port for verif
if(tx_control.enb_intr) {
// this bind is taken care in the test
} else {
for(j=0;j<no_of_txdmas;j++) {
if(dma_ids[j]) {
MacTxPort[mac_id].add_channels(j);
set_max_burst(mac_id,j);
}
}
}
// initialize the t_pkt_cnt
for(j=0;j<24;j++) {
t_pkt_cnt[j] = 0;
sync_pkt_chk[j] = 0;
}
// bind the dmas to the port
MacTxPort[mac_id].SetActive(list);
tx_kick_done[mac_id] = 0;
//-- generate the pkts and kick all pkts ------//
for(i1=0;i1<no_of_txdmas;i1++) {
repeat(50) @(posedge CLOCK);
fork {
if(dma_ids[i1]) {
dma_id = i1;
t_pkt_cnt[i1] = 0;
sync_pkt_chk[i1] = 0;
InitTxDMA(no_of_pkts,mac_id,i1);
if(tx_control.random_num_pkts)
generate_pkts(rand_num_pkts[i1],mac_id,i1);
else
generate_pkts(no_of_pkts,mac_id,i1);
// unstall the DMA
MacTxPort[mac_id].dma[i1].SetTxCs(64'h2000_0000);
MacTxPort[mac_id].dma[i1].setTxRingKick(MacTxPort[mac_id].dma[i1].desc_ring.ring_current_addr);
printf("DMA_id %d kicked at time %d\n", i1, TIME);
if(tx_control.sync_dmas) {
if(dma_ids[23] == 1'b1)
txc_util.txc_init(64'h1f);
}
// repeat(2) @(posedge CLOCK);
/* fork
{
if(tx_control.enb_intr) {
// do nothing taken care in ISR
} else {
mailbox_update(mac_id,i1);
}
} join none */
fork
{
for(k=0;k<5;k++) {
repeat(1500) @(posedge CLOCK);
random_reset_reinit(mac_id,i1,no_of_pkts,pkt_cnt[i1]);
t_pkt_cnt[i1] = t_pkt_cnt[i1] + pkt_cnt[i1];
// printf("Tx_test_cl : In random reset loop\n");
// printf("Tx_test_cl reinit : total_pkt_cnt %d for DMA %d\n",t_pkt_cnt[i1],i1);
}
// add this to sync the pkt_cnt check
t_pkt_cnt[i1] = t_pkt_cnt[i1] + no_of_pkts;
printf("Tx_test_cl reinit : total_pkt_cnt %d for DMA %d\n",t_pkt_cnt[i1],i1);
sync_pkt_chk[i1] = 1;
} join none
}
} join none
}
tx_kick_done[mac_id] = 1;
// wait till sync_pkt_chk goes > 0
if(dma_ids == 24'h0)
sync_pkt_chk = 24'h0;
while((sync_pkt_chk & dma_ids) != dma_ids) {
repeat(100) @(posedge CLOCK);
}
if(tx_control.random_num_pkts)
MacTxPort[mac_id].check_randompkt_cnt(rand_num_pkts,tx_control.pktcnt_rd_intv);
else
// MacTxPort[mac_id].check_pkt_cnt(no_of_pkts,tx_control.pktcnt_rd_intv);
MacTxPort[mac_id].check_randompkt_cnt(t_pkt_cnt,tx_control.pktcnt_rd_intv);
if(get_plus_arg( CHECK, "MAC_LOOP_BACK=")) {
for(j=0;j<no_of_txdmas;j++) {
if(dma_ids[j] & ~done) {
done = 1;
dma_id = j;
generate_pkts(1,mac_id,dma_id,1);
MacTxPort[mac_id].dma[j].setTxRingKick(MacTxPort[mac_id].dma[j].desc_ring.ring_current_addr);
printf("TX_TEST_CL : LOOP_BACK_MODE last_pkt gentd for dma %d\n",dma_ids[j]);
}
}
}
if(get_plus_arg(CHECK,"BYPASS_TXDRR")) {
// do nothing
} else {
MacTxPort[mac_id].check_exit_status();
}
}
function integer niu_tx_test_class :: get_num_of_dmas_bport(bit [23:0] dma_ids)
{
integer i = 0;
integer count = 0;
for(i=0; i< no_of_txdmas; i++) {
if(dma_ids[i])
count++;
}
get_num_of_dmas_bport = count;
}
//--- adding this task for generating num_pks
//--- based on the configuration
task niu_tx_test_class :: get_numpkts_based_onconfig()
{
integer dmas_p0;
integer dmas_p1;
integer dmas_p2;
integer dmas_p3;
integer ratio_p0p1_div_p2p3;
if((tx_control.mac_speed0 == 10000) && (tx_control.mac_speed1 == 10000)
&& (tx_control.mac_speed2 == 1000) && (tx_control.mac_speed3 == 1000)) {
dmas_p0 = get_num_of_dmas_bport(dmas_ids_p0);
dmas_p1 = get_num_of_dmas_bport(dmas_ids_p1);
dmas_p2 = get_num_of_dmas_bport(dmas_ids_p2);
dmas_p3 = get_num_of_dmas_bport(dmas_ids_p3);
ratio_p0p1_div_p2p3 = 5;
if(ratio_p0p1_div_p2p3 < 5) {
no_of_pkts_p0 = 10*tx_control.no_of_pkts;
no_of_pkts_p1 = 10*tx_control.no_of_pkts;
no_of_pkts_p2 = tx_control.no_of_pkts;
no_of_pkts_p3 = tx_control.no_of_pkts;
} else {
no_of_pkts_p0 = tx_control.no_of_pkts;
no_of_pkts_p1 = tx_control.no_of_pkts;
no_of_pkts_p2 = tx_control.no_of_pkts;
no_of_pkts_p3 = tx_control.no_of_pkts;
}
} else {
no_of_pkts_p0 = tx_control.no_of_pkts;
no_of_pkts_p1 = tx_control.no_of_pkts;
no_of_pkts_p2 = tx_control.no_of_pkts;
no_of_pkts_p3 = tx_control.no_of_pkts;
}
}