// ========== Copyright Header Begin ==========================================
// OpenSPARC T2 Processor File: pg_top_pp.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
// ========== Copyright Header End ============================================
#include <vera_defines.vrh>
#include "pcg_defines.vri"
#include "flow_db_tasks.vrh"
#include "mbox_class.vrh"
#include "get_mbox_id.vrh"
// extern pack_db_entry pack_db[];
extern flow_db_entry flow_db[];
extern mbox_class mbox_id;
extern pg ptr_to_first_pg;
extern "C" task InitpgSeed(integer seed);
extern "C" function bit[31:0] pgRand();
function bit[7:0] nextdata() {
local integer warning_count=0;
local integer pg_done =0;
local integer error_count=0;
local bit [63:0] clock_counter;
l3_class_desc l3_class[61];
l3_class_mask l3_mask[40];
local integer pckt_num= -1;
local integer new_flow=0;
local integer order_seq=0;
local integer pkt_gen_sync;
local integer queue_lock;
static bit[19:0] pg_used_ports=0;
bit [31:0] cfg_reg[CFG_LAST_ENTRY];
local bit [15:0] ifedx_control;
local bit [63:0] last_tx_time;
local bit [63:0] prev_current_time=0; //hummer
local integer port_speed ;
local integer mac_speed ;
// local event pkt_gen_lock ;
local integer wait_send_fake;
local integer rxdv_set=0;
local event pg_random_event;
integer debug_mii_rx = 0;
integer debug_mii_tx = 0;
integer debug_xgmii_tx = 1;
integer debug_xgmii_rx = 0;
integer debug_gmii_rx = 0;
integer debug_db_out = 0;
integer debug_checker = 0;
integer debug_out_token = 1;
task config(integer what, bit [31:0] data) ;
task gen_buf( pack_db_entry pack_db, byte_array buf, var integer ptr ) ;
function byte_array new_gen_buf(pack_db_entry pack_db, var bit[31:0] pkt_fields[*]);
task pkt_gen( flow_desc flow, integer data_length, integer ttl, var CpgToken pgToken, ( bit[63:0] options=0) );
task data_gen(integer type, integer seed, integer len, byte_array buf, var integer offset, bit[63:0] options,pg my_root, integer tagged, integer ifedx);
task display_buf( byte_array buf, integer hwlen, (integer ifedx=0)) ;
task display_class(byte_array buf, var integer ptr) ;
task display_class_ipv6(byte_array buf, var integer ptr) ;
task display_data(byte_array buf, var integer ptr, integer len) ;
task display_id(bit [79:0] id) ;
task display_db(pack_db_entry pack_db) ;
task display_flow(integer flow_id) ;
task send_packet(bit [3:0] ptype, byte_array buf, integer len, bit [63:0] options) ;
task assert_col_tx (mii_def port_bind, bit [63:0] options) ;
task assert_mii_err (mii_def port_bind ) ;
task send_packet_mii (mii_def port_bind, bit [3:0] ptype, byte_array buf, integer len, bit [63:0] options) ;
task assert_gmii_err (gmii_def port_bind) ;
task send_packet_gmii (gmii_def port_bind, bit [3:0] ptype, byte_array buf, integer len, bit [63:0] options) ;
task assert_xgmii_err (xgmii_def port_bind) ;
task send_packet_xgmii (xgmii_def port_bind,bit [3:0] ptype, byte_array buf, integer len, bit [63:0] options) ;
task wait_clk(integer count) ;
task wait_tx_clk(integer count) ;
task wait_tx_clk_if ( mii_def port_bind, integer count) ;
task wait_rx_clk(integer count) ;
task wait_rx_clk_if ( mii_def port_bind, integer count) ;
task config_tx (mii_def port_bind, integer mac_speed ) ;
task new(integer my_porti, (bit [3:0] ptype=0)) ;
task build_frame (integer itoken, pack_db_entry pack_db, byte_array buf, var integer len,(integer header_id=-1),(integer new_crc=0));
function bit [15:0] ipv4_cksum( byte_array m, integer len) ;
function bit [15:0] ip_datagram_chksum(byte_array d, integer start, integer len);
function bit [15:0] tcp_chksum( pack_db_entry pack_db, byte_array d, integer start, integer len, integer pkt_type,integer chk_sum_location );
function bit [31:0] crc_gen(byte_array p, integer start, integer len) ;
local function bit [31:0] crc32_add(bit [7:0] data, bit [31:0] crc) ;
function integer check_option(bit [63:0] option, bit [63:0] flag) ;
function bit [7:0] class_mask(integer funct, bit[7:0] a, bit[7:0] b) ;
function bit[15:0] partial_cksum(byte_array packet, integer start_offset, integer pkt_len);
task pg::gen_buf( pack_db_entry pack_db, byte_array buf, var integer ptr ) {
integer header_len_w_options;
// List of inputs to this function passed through a struct
integer frame_class_mask;
bit [128:0] src_ipv6_addr,dst_ipv6_addr;
bit [31:0] src_ip_addr,dst_ip_addr;
bit [15:0] src_port,dst_port;
integer chk_sum_location;
// Assign the inputs here TMP only
flow_id = pack_db.flow.flow_no;
l2_da = pack_db.dst_node.l2_addr;
l2_sa = pack_db.src_node.l2_addr;
frame_type = pack_db.frame.frame_type;
tpid = pack_db.frame.tpid;
tci = pack_db.src_node.tci;
frame_class = pack_db.frame.frame_class;
data_length = pack_db.data_length;
class_funct = pack_db.frame.class_funct;
frame_class_mask = pack_db.frame.class_mask;
header_length = pack_db.frame.header_length ;
spi = pack_db.src_node.spi;
nxthdr = pack_db.src_node.nxthdr;
tos = pack_db.src_node.tos;
type = pack_db.frame.type;
src_ipv6_addr = pack_db.src_node.ipv6_addr;
dst_ipv6_addr = pack_db.dst_node.ipv6_addr;
src_ip_addr = pack_db.src_node.ip_addr;
dst_ip_addr = pack_db.dst_node.ip_addr;
src_port = pack_db.tup.src_tcp_udp_port;
dst_port = pack_db.tup.dst_tcp_udp_port;
tcp_flags = pack_db.fl_state.tcp_flags;
rcv_isn = pack_db.rx_param.rcv_isn;
//last_seqno = flow_db[flow_id].tx_param.last_seqno;
data_type = pack_db.frame.data_type;
data_seed = pack_db.frame.data_seed;
options = pack_db.options;
// DONE Assign the inputs here
'{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++],
buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } = l2_da;
'{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++],
buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } = l2_sa;
if( frame_type[2] ) { // 802.1Q 18 bytes long header
'{ buf.val[ptr++], buf.val[ptr++]} = tpid;
'{ buf.val[ptr++], buf.val[ptr++]} = TPID_8021Q;
'{ buf.val[ptr++], buf.val[ptr++]} = tci;
if((frame_type[1] == 1) || (frame_type[4] == 1)) { // include ip header or tunneling options
if( frame_type[0] == 1) { // if LLC SNAP IP Header
if( check_option( pack_db.options, O_CUSTOM_LS) ) {
tmp32 = cfg_reg[CFG_CUST_LS];
'{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++]} = tmp32[23:0];
'{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++]} = LLC_SNAP;
buf.val[ptr++] = H_UNDEF;
buf.val[ptr++] = H_UNDEF;
buf.val[ptr++] = H_UNDEF;
if( frame_type[3] == 1 && frame_class < CL_TCP_OPT ) // IPV6 Header
if( frame_type[3] == 0 ) { // IPV4 Header
if ( (frame_type[0] == 1 ) && (frame_type[2] == 1 )) { // LLC_SNAP and 802.1Q Tagged
} else if (frame_type[2] == 1 ) { // ONLY 802.1Q Tagged
} else if (frame_type[0] == 1 ) { // ONLY LLC_SNAP
} else{ // NONE of the above
ip_length = data_length -4 -(l2_length) ;
pack_db.ipp.ip_hdr_len = ip_length;
printf("pg::gen_buf The IP length is %0h , ptr - %d \n", ip_length,ptr);
buf.val[ptr++] = class_mask( class_funct, l3_class[frame_class].val[n], l3_mask[frame_class_mask].val[n] );
// add header option field here
buf.val[ptr] = class_mask( class_funct, l3_class[frame_class].val[2],
l3_mask[frame_class_mask].val[2] );
if((buf.val[ptr] & 8'h40) == 8'h40) { // if IPV4
buf.val[ptr++] = 8'h40 | ( header_length & 4'hf) ;
buf.val[ptr++] = ip_length[15:8];
buf.val[ptr++] = ip_length[7:0];
// Fill in rest of the header bytes
buf.val[ptr++] = class_mask( class_funct, l3_class[frame_class].val[n],
l3_mask[frame_class_mask].val[n] );
// This appears to be programmed by the user to override the automatically generated type field
if(type != -1) // This should be moved up? ....
'{buf.val[ptr-14], buf.val[ptr-13]} = type;
// This should be moved up? ....
if(ttl != -1) buf.val[ptr-2] = ttl;
'{buf.val[ptr++],buf.val[ptr++]} = 16'h0000; // 0s for header checksum
'{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } = src_ip_addr;
'{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } = dst_ip_addr;
header_len_w_options = ( (buf.val[ptr -20 /*14*/ ] & 8'h40 )== 8'h40) ? header_length : 0;
printf(" DEBUG-- header_len_w_options - %d buf value - %x \n",header_len_w_options,buf.val[ptr -20 /*14*/ ] );
for(n=0;n< (4*header_len_w_options - 20); n++) {
buf.val[ptr++] = 8'ha0 + n;
// printf(" DEBUG-- ptr - %d val - %x \n",ptr,buf.val[ptr -1]);
tmp16_ipck = ipv4_cksum(buf,ptr);
// Write back computed checksum
'{buf.val[ptr-10 - (4*header_len_w_options - 20) ],buf.val[ptr-9 - (4*header_len_w_options - 20) ]} = tmp16_ipck;
if( frame_class == CL_IP_SEC_ESP) {
'{buf.val[ptr++],buf.val[ptr++],buf.val[ptr++],buf.val[ptr++]} = spi;
'{buf.val[ptr++],buf.val[ptr++]} = 16'h0000;
'{buf.val[ptr++],buf.val[ptr++]} = 16'h0000;
'{buf.val[ptr++],buf.val[ptr++]} = 16'h0000;
'{buf.val[ptr++],buf.val[ptr++]} = 16'h0000;
if( frame_class == CL_IP_SEC_AH) {
//buf.val[ptr++] = 8'h06;//Assumes TCP
buf.val[ptr++] = 8'h03;//LenHdr-2 (32bit Words)
'{buf.val[ptr++],buf.val[ptr++]} = 16'h0000;
'{buf.val[ptr++],buf.val[ptr++],buf.val[ptr++],buf.val[ptr++]} = spi;
'{buf.val[ptr++],buf.val[ptr++]} = 16'h0000;
'{buf.val[ptr++],buf.val[ptr++]} = 16'h0000;
else if ( frame_type[3] == 1 ) { // IPV6 Packet
// printf("pcg_fa.vr: Bulding IPv6 Packet \n");
if( (frame_type[2] == 1 ) && (frame_type[0] == 1)) {
} else if (frame_type[2] == 1 ) {
} else if (frame_type[0] == 1 ) {
ipv6_length = data_length - 40 -4 -(l2_length);
pack_db.ipp.ip_hdr_len = ipv6_length;
printf("pg::gen_buf The val of ip_length is %0d\n",ipv6_length);
buf.val[ptr++] = class_mask( class_funct,
l3_class[frame_class].val[n],
l3_mask[frame_class_mask].val[n] );
buf.val[ptr++] = {4'h6,tos[7:4]};
buf.val[ptr++] = {tos[3:0],4'h0};
buf.val[ptr++] = class_mask( class_funct,
l3_class[frame_class].val[n],
l3_mask[frame_class_mask].val[n] );
buf.val[ptr++] = ipv6_length[15:8];
buf.val[ptr++] = ipv6_length[7:0];
buf.val[ptr++] = class_mask( class_funct,
l3_class[frame_class].val[n],
l3_mask[frame_class_mask].val[n] );
'{buf.val[ptr-10], buf.val[ptr-9]} = type;
if(ttl != -1) buf.val[ptr-1] = ttl;
'{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++],
buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++],
buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++],
buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } = src_ipv6_addr;
'{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++],
buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++],
buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++],
buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } = dst_ipv6_addr;
if( frame_class == CL_IP_V6_SEC_ESP) {
'{buf.val[ptr++],buf.val[ptr++],buf.val[ptr++],buf.val[ptr++]} = spi;
'{buf.val[ptr++],buf.val[ptr++]} = 16'h0000;
'{buf.val[ptr++],buf.val[ptr++]} = 16'h0000;
'{buf.val[ptr++],buf.val[ptr++]} = 16'h0000;
'{buf.val[ptr++],buf.val[ptr++]} = 16'h0000;
if( frame_class == CL_IP_V6_SEC_AH) {
buf.val[ptr++] = 8'h06;//Assumes TCP
buf.val[ptr++] = 8'h03;//LenHdr-2 (32bit Words)
'{buf.val[ptr++],buf.val[ptr++]} = 16'h0000;
'{buf.val[ptr++],buf.val[ptr++],buf.val[ptr++],buf.val[ptr++]} = spi;
'{buf.val[ptr++],buf.val[ptr++]} = 16'h0000;
'{buf.val[ptr++],buf.val[ptr++]} = 16'h0000;
printf("pg::gen_buf : Frame_class: %d frame_type - %x \n" , frame_class,frame_type );
if( frame_class == CL_UDP | frame_class == CL_UDP_OPT |
frame_class == CL_UDP_FRAG | frame_class == CL_UDP_IP_V6 |
frame_class == CL_UDP_OPT_IP_V6 | frame_class == CL_UDP_FRAG_IP_V6 ) {
if ( frame_type[3] == 1 ) { // IPV6
udp_length = data_length - 40 -4 -(l2_length); }
if( frame_type[3] == 0 ) { // IPV4
udp_length = data_length - (4*header_len_w_options) -4 -(l2_length); // printf("DEBUG udp length - %d \n",udp_length);
udp_psu_hdr = {src_ip_addr, dst_ip_addr, 8'h00,8'h17,udp_length};
pack_db.psu_hdr= (udp_psu_hdr);
'{ buf.val[ptr++], buf.val[ptr++] } = src_port;
'{ buf.val[ptr++], buf.val[ptr++] } = dst_port;
buf.val[ptr++] = udp_length[15:8];
buf.val[ptr++] = udp_length[7:0];
'{ buf.val[ptr++], buf.val[ptr++] } = 16'h00;
else if ( frame_class == CL_TCP | frame_class == CL_TCP_OPT |
frame_class == CL_TCP_FRAG | frame_class == CL_TCP_IP_V6 |
frame_class == CL_TCP_OPT_IP_V6 | frame_class == CL_TCP_FRAG_IP_V6 ) {
//printf("pcg_fa.vr: Adding TCP Header \n");
tcp_psu_hdr = {src_ip_addr, dst_ip_addr, 8'h00,8'h06,16'h0000};
pack_db.psu_hdr= (tcp_psu_hdr);
'{ buf.val[ptr++], buf.val[ptr++] } = src_port;
'{ buf.val[ptr++], buf.val[ptr++] } = dst_port;
if( tcp_flags == 2'h2 ) {
'{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } = rcv_isn;
'{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } = flow_db[flow_id].tx_param.last_seqno;
flow_db[flow_id].rx_param.rcv_isn = flow_db[flow_id].tx_param.last_seqno;
if(frame_class != CL_TCP_OPT & frame_class != CL_TCP_OPT_IP_V6)
{ cfg_reg[CFG_TCP_LEN] = 4'b0101; }
'{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } = cfg_reg[CFG_TCP_ACK];
tmp32[15:0] = {cfg_reg[CFG_TCP_LEN], 6'b000000, tcp_flags} ;
'{ buf.val[ptr++], buf.val[ptr++] } = tmp32[15:0];
tmp32 = cfg_reg[CFG_TCP_WIN];
'{ buf.val[ptr++], buf.val[ptr++] } = tmp32[15:0];
'{ buf.val[ptr++], buf.val[ptr++] } = 16'h00;
tmp32 = cfg_reg[CFG_TCP_URG];
'{ buf.val[ptr++], buf.val[ptr++] } = tmp32[15:0];
if ( (cfg_reg[CFG_TCP_LEN] ) > 5 ) {
extra_tcp_hdr = (cfg_reg[CFG_TCP_LEN] - 5 ) * 4;
pack_db.mac.extra_tcp_hdr = extra_tcp_hdr;
for ( n =0; n< extra_tcp_hdr; n++) {
pack_db.mac.extra_tcp_hdr = extra_tcp_hdr;
} // endif include ip header or tunneling option
printf("pg::gen_buf : No L3 header selected\n");
if( frame_type[0] == 1) { // LLC_SNAP
if( check_option( pack_db.options, O_CUSTOM_LS) ) {
tmp32 = cfg_reg[CFG_CUST_LS];
'{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++]} = tmp32[23:0];
'{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++]} = LLC_SNAP;
buf.val[ptr++] = H_UNDEF;
buf.val[ptr++] = H_UNDEF;
buf.val[ptr++] = H_UNDEF;
'{buf.val[ptr++],buf.val[ptr++]} = 16'h0008;
} // endif else of include ip header
he = ptr-1; // header length
tcp_length = data_length -he -4;
tcp_seg_len = data_length - ptr - 4;
if(data_type != DAT_FC_PAUSE)
'{buf.val[ptr++], buf.val[ptr++]} = gId;
if(LLC_HACK & ( (pack_db.frame.frame_type== 5'h3 )| (pack_db.frame.frame_type== 5'h7) )) {
printf("gen_buf LLC_HACK!!! data_len - %d \n",pack_db.data_length);
if(pack_db.flow.frame.frame_type== 5'h3) {
llc_length = pack_db.data_length - 4/*CRC*/ - 12/*L2HEADERS*/ -2/*Type/Length*/ ;
buf.val[12] = llc_length[15:8];
buf.val[13] = llc_length[7:0];
llc_length = pack_db.data_length - 4/*CRC*/ - 12/*L2HEADERS*/ -4/*VLAN ID*/ -2/*Type/Length*/ ;
buf.val[16] = llc_length[15:8];
buf.val[17] = llc_length[7:0];
/* Generate data payload */
data_gen(data_type, data_seed, data_length, buf, ptr, pack_db.options, this, tagged, INTER_FEDX);
// printf("DEBUG--- After data_gen len - %d \n",len);
// printf("DEBUG---type - %d %d %d \n",type,ptr, he);
if( check_option( pack_db.options, O_FRM_LEN_ERR1) )
'{buf.val[len], buf.val[len+1] } = cfg_reg[CFG_FRM_LEN];
'{buf.val[len], buf.val[len+1] } = ptr - (he+1);
'{buf.val[len], buf.val[len+1] } = type;
if( frame_class == CL_TCP | frame_class == CL_TCP_OPT |
frame_class == CL_TCP_FRAG | frame_class == CL_TCP_IP_V6 |
frame_class == CL_TCP_OPT_IP_V6 | frame_class == CL_TCP_FRAG_IP_V6 ) {
// Calculate TCP checksum
flow_db[flow_id].data_length = tcp_seg_len;
flow_db[flow_id].tx_param.last_seqno = (flow_db[flow_id].rx_param.rcv_isn) + flow_db[flow_id].data_length;
chk_sum_location = he-extra_tcp_hdr-3;
tmp16_tcpck = tcp_chksum(pack_db,buf,tcp_hdr_start,ptr,1, chk_sum_location );
printf("gen_buf-- tcp_chksum - %x tcp_hdr_start - %d chk_sum_location - %d \n",tmp16_tcpck,tcp_hdr_start,chk_sum_location);
if( check_option( pack_db.options, O_TCPCKSUM_ERR) ){
tmp16_tcpck = tmp16_tcpck ^ cfg_reg[CFG_TCPCKSUM_MASK];
'{buf.val[he-extra_tcp_hdr-3],buf.val[he-extra_tcp_hdr-2]} = tmp16_tcpck;
pack_db.ipp.tcp_cksum = tmp16_tcpck;
if(frame_class == CL_UDP | frame_class == CL_UDP_OPT |
frame_class == CL_UDP_FRAG | frame_class == CL_UDP_IP_V6 |
frame_class == CL_UDP_OPT_IP_V6 | frame_class == CL_UDP_FRAG_IP_V6 ) {
// Calculate UDP checksum
chk_sum_location = he -1;
tmp16_udpck = tcp_chksum(pack_db,buf,udp_hdr_start,ptr,0,chk_sum_location);
printf("gen_buf-- udp_chksum - %x udp_hdr_start - %d chk_sum_location - %d \n",tmp16_udpck,udp_hdr_start,chk_sum_location);
'{buf.val[he-1],buf.val[he-0]} = tmp16_udpck;
ip_hdr_start = l2_length ;
if (frame_type[1] == 1) { // IPV4
tmp16_ipdck =ip_datagram_chksum(buf,ip_hdr_start,ptr);
pack_db.ipp.ip_datagram_cksum = tmp16_ipdck;
pack_db.add_header(buf,0,he);
if(LLC_HACK & ( (pack_db.frame.frame_type== 5'h3 )| (pack_db.frame.frame_type== 5'h7) )) {
printf("LLC_HACK!!! \n");
if(pack_db.flow.frame.frame_type== 5'h3) {
llc_length = pack_db.data_length - 4/*CRC*/ - 12/*L2HEADERS*/ -2/*Type/Length*/ ;
buf.val[12] = llc_length[15:8];
buf.val[13] = llc_length[7:0];
llc_length = pack_db.data_length - 4/*CRC*/ - 12/*L2HEADERS*/ -4/*VLAN ID*/ -2/*Type/Length*/ ;
buf.val[16] = llc_length[15:8];
buf.val[17] = llc_length[7:0];
tmp32 = crc_gen(buf, 0, ptr);
if( check_option( pack_db.options, O_CRC_ERR) ) tmp32 = tmp32 ^ cfg_reg[CFG_CRC_MASK];
'{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } = tmp32;
pack_db.pack_crc = tmp32;
// printf(" end of gen_buf - ptr - %d \n",ptr);
function bit [15:0] pg::ipv4_cksum( byte_array m, integer len){
printf ("pg::ipv4_cksum: The val of len is %d\n",len);
for ( i=j; i< (j+20); i=i+2) {
tmp[i] = {m.val[i], m.val[(i+1)]};
// printf("The val of buffer is %0h\n",tmp[i]);
printf(" pg::ipv4_cksum: chksum - %x \n",ipv4_cksum);
function bit [15:0] pg::ip_datagram_chksum( byte_array d, \
integer start, integer len){
printf ("pg::ip_datagram_chksum: The val of ip hdr start and len is %0d and %0d\n", start,len);
for (i=start;i<len+pad;i=i+2) {
tmp[i] = {d.val[i],d.val[i+1]};
//printf("The val of buffer is %0h\n",tmp[i]);
//printf("The val of sum of payld is is %0h\n",ipsum);
ip_datagram_chksum = ~ipsum;
printf("pg::ip_datagram_chksum: The val of IP Datagram Checksum is %0h \n",ip_datagram_chksum);
function bit [15:0] pg::tcp_chksum( pack_db_entry pack_db, byte_array d, integer start, integer len, integer pkt_type, integer chk_sum_location ){
bit [31:0] tcp_proto_sum;
partial_chksum = pack_db.flow.partial_chksum;
d.val[chk_sum_location] = pack_db.flow.psu_hdr[0];
d.val[chk_sum_location + 1] = pack_db.flow.psu_hdr[1];
printf(" pg::tcp_chksum partial checksum location - %d hdr[0]- %x hdr[1] - %x \n",chk_sum_location,pack_db.flow.psu_hdr[0],pack_db.flow.psu_hdr[1]);
sum = partial_cksum( d,start,len );
printf(" pg::tcp_chksum partial checksum - %x \n",sum);
printf("pg::tcp_chksum start - %d len - %d \n",start,len);
if (pack_db.frame.frame_type[3] == 0){
psu_hdr = {pack_db.src_node.ip_addr, pack_db.dst_node.ip_addr, 8'h00,8'h06,16'h0000};
// printf("The val of psu header is %0h\n",psu_hdr);
for (i=start;i<len+pad;i=i+2) {
tmp[i] = {d.val[i],d.val[i+1]};
if (pack_db.frame.frame_type[3] == 0){
ip_src_sum = pack_db.src_node.ip_addr[15:0] + pack_db.src_node.ip_addr[31:16];
if (ip_src_sum[16] ==1) {
ip_src_sum = ip_src_sum[15:0] + 1;
ip_dst_sum = pack_db.dst_node.ip_addr[15:0] + pack_db.dst_node.ip_addr[31:16];
if (ip_dst_sum[16] ==1) {
ip_dst_sum = ip_dst_sum[15:0] + 1;
tcp_proto_sum = 16'h0006 + tcp_len;
tcp_proto_sum = 16'h0011 + tcp_len;
if (tcp_proto_sum[16] ==1) {
tcp_proto_sum = tcp_proto_sum[15:0] + 1;
sum = sum + tcp_proto_sum;
//printf("The val of sum of payld & tcp_proto is is %0h\n",sum);
if (pack_db.frame.frame_type[3] == 1){
ipv6_src = pack_db.src_node.ipv6_addr;
ipv6_dst = pack_db.dst_node.ipv6_addr;
//printf("The val of ipv6 src is %0h\n", ipv6_src );
for ( k= 0 ; k < 8; k++ ) {
tmp0[k] = {ipv6_src[j:j-7], ipv6_src[j-8:j-15]};
//printf("The val of src buffer is %0h\n",tmp0[k]);
//printf("The val of sum at src is %0h\n", sum);
for ( k= 0 ; k < 8; k++ ) {
tmp1[k] = {ipv6_dst[j:j-7], ipv6_dst[j-8:j-15]};
//printf("The val of dst buffer is %0h\n",tmp1[k]);
//printf("The val of sum at dst is %0h\n", sum);
tcp_proto_sum = 16'h0006 + tcp_len;
tcp_proto_sum = 16'h0011 + tcp_len;
if (tcp_proto_sum[16] ==1) {
tcp_proto_sum = tcp_proto_sum[15:0] + 1;
sum = sum + tcp_proto_sum;
// printf("The val of start and len are %0d and %0d\n",start,len);
// printf("The FINAL val of sum is %0h\n", sum);
task pg::pkt_gen( flow_desc flow, integer data_length, integer ttl, var CpgToken pgToken,
integer current_flow_num;
printf("pg::pkt_gen called Time - %d \n", {get_time(HI),get_time(LO)});
semaphore_get(WAIT,pkt_gen_lock,1);
printf("pg::pkt_gen after sem called Time - %d \n", {get_time(HI),get_time(LO)});
// sync(ALL,pkt_gen_lock);
// trigger(OFF,pkt_gen_lock);
current_flow_num = flow.flow_no;
printf("pg::pkt_gen: WARNING: PG: Port %0d is invalid (only used to satisfy fflp testsuite).\n",my_port);
printf("pg::pkt_gen: No action is taken.\n");
token = pckt_num; // TOADS
if (flow.fl_state.tcp_flags == 6'h02)
case({ check_option(options, O_ORDER_START),
check_option(options, O_ORDER_CONT),
check_option(options, O_ORDER_END) }) {
if(flow.src_node.src_port[my_port] != 1) {
printf("pg::pkt_gen PG: Specified src_node may not be used as source for this port. Continuing anyway ...\n");
pack_db = new(pckt_num );
pack_db.preamble_cnt = flow.preamble_cnt;
// printf("DEBUG pack_db.options - %x preamble_cnt - %d sfd - %d \n",pack_db.options,pack_db.preamble_cnt,pack_db.sfd);
id = pack_db.add(my_port, flow, flow.frame, flow.src_node, flow.dst_node, flow.tup, flow.rx_param, flow.tx_param, flow.fl_state, data_length,ttl, options | flow.options , order_seq,
pckt_num, ifedx_control);
pack_db.port_type = port_type;
if( pack_db.fl_state.tcp_flags == 2'h2 ) {
flow_db_add_entry( my_port, data_length, flow, flow.tup, flow.rx_param, flow.tx_param, flow.fl_state, options, current_flow_num );
if(debug_db_in) display_db(pack_db);
printf("Before mailbox_put mb_q - time - %d \n",{get_time(HI),get_time(LO)});
mailbox_put(mb_q, pack_db);
printf("pg::pkt_gen: Waiting for packet to go out ...(port type: %h), token# %0d\n",port_type, token);
printf("pg::pkt_gen: Waiting for packet to go out wait_send_fake - %d Time - %d \n",wait_send_fake,{get_time(HI),get_time(LO)});
printf("pg::pkt_gen: Waiting for packet to go oui options - %d Time - %d \n", pack_db.options,{get_time(HI),get_time(LO)});
if( check_option( pack_db.options, O_WAIT_SEND_FAKE) ) {
while(wait_send_fake==0) @(posedge CLOCK);
if( check_option( pack_db.options, O_WAIT_SEND) ) {
while(pg_done!=1) @(posedge CLOCK);
printf("pg::pkt_gen: before terminate timeout - %d pg_done - %d \n",time_out,pg_done);
printf("PG: Timed out waiting for done bit (waited %0d cycles)...\n",time_out);
printf(" This only happens with fake ports when we wait for someone\n");
printf(" to acknowladge that the packet was processed (Port: %0d).\n",my_port);
printf(" Token: %0d, Time: %0d\n",token,{get_time(HI),get_time(LO)});
pgToken.pack_db = new pack_db;
pgToken.port_id = my_port;
mailbox_get(WAIT,pkt_gen_sync,tmpbuf);
pgToken.buf = new tmpbuf;
// display_buf(pgToken.buf,data_length);
// printf(" in pkt_gen -- length - %d \n", pack_db.header_len[0]);
printf("pg::pkt_gen: Waiting End of pkt_gen !!! Time - %d \n",{get_time(HI),get_time(LO)});
// trigger(ON,pkt_gen_lock);
semaphore_put(pkt_gen_lock,1);
function byte_array pg::new_gen_buf(pack_db_entry pack_db, var bit[31:0] pkt_fields[*]){
len = pack_db.data_length;
printf("byte_array pg::new_gen_buf function id - %d !! Time - %d \n",my_port,{get_time(HI),get_time(LO)});
cPg.genPacket(0,len, pack_db.flow, payload,pkt_fields);
for( i = 0; i < len + pack_db.flow.frame.l2_pad_length;i++) {
buf.val[i] = payload[i] & 8'hff;
// printf(" PKT buf - %x index - %d \n", buf.val[i],i);
bit[31:0] pkt_fields[*] ;
trigger(ON,lock_send_packet);
sync(ALL,lock_send_packet);
trigger(OFF,lock_send_packet);
printf(" Before mailbox_get mb_q Time - %d \n",{get_time(HI),get_time(LO)} );
mailbox_get(WAIT, mb_q, pack_db);
printf(" After mailbox_get mb_q Time - %d \n",{get_time(HI),get_time(LO)} );
if(debug_db_out) display_db(pack_db);
// gen_buf( pack_db, buf, len );
len = pack_db.data_length + pack_db.flow.frame.l2_pad_length;
buf = new_gen_buf(pack_db,pkt_fields);
pgToken = new (pack_db.gId);
pgToken.pack_db = new pack_db;
pgToken.port_id = my_port;
pgToken.pkt_fields = new[SIZE_OF_PKT_FIELDS];
for(i=0;i<SIZE_OF_PKT_FIELDS;i++) {
pgToken.pkt_fields[i] = pkt_fields[i];
mailbox_put(pkt_gen_sync,tmpbuf);
if( !check_option( pack_db.options, O_NO_OUT_TOKEN) ) {
printf("pg::pkt_auto_tx: INFO: PG[%0d]: Sending token (%0d) to outgoing mailbox. (Time: %d)\n", my_port, token, {get_time(HI),get_time(LO)} );
mailbox_put(mbox_id.pg_mb[my_port], pgToken);
printf("pg::pkt_auto_tx:pg[%0d]: Transmitting packet ...\n",my_port);
// printf("options fake out: %d\n",check_option( pack_db.options, O_FAKE_OUT) );
if( !(check_option( pack_db.options, O_FAKE_OUT )) & !port_type[2] ) {
printf("pg::pkt_auto_tx:INFO: PG[%0d]: Sending out packet token:%0d at time %0d \n",my_port,pack_db.gId , {get_time(HI),get_time(LO)});
if( check_option(pack_db.options, O_PREAMB_ERR) ) cfg_reg[CFG_PRAMB_CNT] = pack_db.preamble_cnt;
if( check_option(pack_db.options, O_SFD_ERR) ) cfg_reg[CFG_SFD_TOKEN] = pack_db.sfd;
// printf("DEBUG pack_db.options - %x preamble_cnt - %d sfd - %d \n",pack_db.options,cfg_reg[CFG_PRAMB_CNT],cfg_reg[CFG_SFD_TOKEN]);
send_packet(port_type, buf, len, pack_db.options);
// printf("pg::pkt_auto_tx:INFO: PG[%0d]: Packet token %0d sent done at time=%0d \n",my_port, token,{get_time(HI),get_time(LO)});
printf("pg::pkt_auto_tx:pg[%0d]: Done Transmitting packet ...\n",my_port);
trigger(ON,lock_send_packet);
task pg::build_frame(integer itoken,pack_db_entry pack_db, byte_array buf, var integer len,(integer header_id=-1),(integer new_crc=0)) {
integer my_port, org_port;
integer data_len, header_len;
printf("DEBUG: build_frame: Started Build-Frame. (Input: Token: %0d, Len: %0d Hdr: %0d, NewCRC: %0d Port: %0d)\n",
token,len,header_id,new_crc,my_port);
// printf(" data_len from build_frame - %d \n",pack_db.data_length);
my_port = pack_db.org_port;
org_port = pack_db.org_port;
if(header_id != -1) my_port = header_id;
if(debug) printf("DEBUG: build_frame: (1)ptr: %0d\n",ptr);
// printf(" in build frame header_d - %d \n",header_id);
header_len = pack_db.header_len[ pack_db.use_hdr ];
// printf(" in build frame header_len - %d use_header - %d \n",header_len,pack_db.use_hdr);
for(n=0;n< header_len ;n++)
buf.val[ptr++] = pack_db.header[ pack_db.use_hdr ].val[n];
#define out_use_header pack_db.out_header[header_id].use_header
if( assoc_index(CHECK,pack_db.out_header,header_id) &
assoc_index(CHECK,pack_db.out_header[header_id].header, out_use_header) ) {
header_len = pack_db.out_header[header_id].header_len[ out_use_header ];
// printf(" in build frame header_len - %d \n",header_len,out_use_header);
for(n=0; n < header_len ; n++)
buf.val[ptr++] =pack_db.out_header[header_id].header[out_use_header].val[n];
printf("pg::build_frame: ERROR: PG LIB: build_frame: out header invalid. (Token:%0d, Out header id: %0d).\n",
if(debug) printf("DEBUG: build_frame: header_len: %0d\n",header_len);
if(debug) printf("DEBUG: build_frame: (2)ptr: %0d\n",ptr);
if(pack_db.frame.data_type != DAT_FC_PAUSE)
'{buf.val[ptr++], buf.val[ptr++]} = token; // Store token in payload
if(pack_db.org_port<17 & my_port>16) adj_len += 6;
if(pack_db.org_port>16 & my_port<17) adj_len -= 6;
if(debug) printf("DEBUG: build_frame: adj_len: %0d\n",adj_len);
if( pack_db.frame.frame_type[2] ) tagged = 1;
if(debug) printf("DEBUG: build_frame: (3)ptr: DAT_LEN_EXACT: %0d\n",
check_option(pack_db.frame.data_type, DAT_LEN_EXACT) );
if(pack_db.data_length<0) {
case(pack_db.data_length) {
-1: pack_db.data_length = 64;
-2: pack_db.data_length = 128;
-3: pack_db.data_length = 256;
-4: pack_db.data_length = 512;
-5: pack_db.data_length = 1024;
-6: pack_db.data_length = (tagged) ? 1522 : 1518;
// pack_db.data_length = random(pack_db.frame.data_seed); // Vera supports only one random
pack_db.data_length = random();
max = (tagged) ? 1522 : 1518;
while(pack_db.data_length<min | pack_db.data_length>max)
pack_db.data_length = random();
-8: pack_db.data_length = 63;
-9: pack_db.data_length = 65;
-10: pack_db.data_length = (tagged) ? 1521 : 1517;
-11: pack_db.data_length = (tagged) ? 1523 : 1519;
pack_db.frame.data_type = pack_db.frame.data_type | DAT_LEN_EXACT;
if( check_option(pack_db.frame.data_type, DAT_LEN_EXACT) ) {
// Convert exact length to actual data length, clear exact flag and use that data length from now on.
// data_len = pack_db.data_length + header_len - pack_db.header_len[0] + adj_len;
data_len = pack_db.data_length - header_len - 4; // data_len - header_len - crc_len
if(INTER_FEDX) data_len = data_len - 6;
pack_db.data_length = data_len;
pack_db.frame.data_type = pack_db.frame.data_type & DAT_TYPE_MASK;
data_len = pack_db.data_length;
if(debug) printf("DEBUG: build_frame: (3)ptr: %0d\n",ptr);
if(debug) printf("DEBUG: build_frame: data_len: %0d\n",data_len);
if(LLC_HACK & ( (pack_db.frame.frame_type== 5'h3 )| (pack_db.frame.frame_type== 5'h7) )) {
printf(" build_frame LLC_HACK!!! data_len - %d \n",pack_db.data_length);
if(pack_db.flow.frame.frame_type== 5'h3) {
llc_length = ( pack_db.data_length + header_len + 4) - 4/*CRC*/ - 12/*L2HEADERS*/ -2/*Type/Length*/ ;
buf.val[12] = llc_length[15:8];
buf.val[13] = llc_length[7:0];
llc_length = ( pack_db.data_length + header_len + 4) - 4/*CRC*/ - 12/*L2HEADERS*/ -4/*VLAN ID*/ -2/*Type/Length*/ ;
buf.val[16] = llc_length[15:8];
buf.val[17] = llc_length[7:0];
if( pack_db.frame.frame_type[2] ) tagged = 1;
data_gen( pack_db.frame.data_type,
buf, ptr, pack_db.options, this, tagged, INTER_FEDX);
if(debug) printf("DEBUG: build_frame: (4)ptr: %0d\n",ptr);
tmp32 = crc_gen(buf, 2, ptr); // Skip Interfedx Control Word
tmp32 = crc_gen(buf, 0, ptr);
if( check_option( pack_db.options, O_CRC_ERR) )
tmp32 = tmp32 ^ cfg_reg[CFG_CRC_MASK];
'{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } = pack_db.pack_crc;
if ( (org_port==17) | (org_port==18) ) {
'{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } = pack_db.pack_crc;
tx_status = pack_db.mac.tx_status;
'{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } = pack_db.pack_crc;
else '{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } = tmp32;
} //end of if ( (org_port==17) | (org_port==18) )
'{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } = pack_db.pack_crc;
else '{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } = tmp32;
if(debug) printf("DEBUG: build_frame: (5)ptr: %0d\n",ptr);
if(debug) printf("DEBUG: build_frame: Done.\n");
// display_buf( buf,len);
task pg::data_gen(integer type, integer seed, integer len, byte_array buf, var integer offset, bit[63:0] options,
pg my_root, integer tagged, integer ifedx) {
if(debug_dg) printf("DEBUG: pg::data_gen: input: type: %0d (%h), len: %0d, offset: %0d, tagged: %0d, ifedx: %0d\n",
type,type,len,offset,tagged,ifedx);
exact_len = (type & DAT_LEN_EXACT) ? 1 : 0;
exact_len = ptr_to_first_pg.check_option(type, DAT_LEN_EXACT);
type = type & DAT_TYPE_MASK;
-6: len = (tagged) ? 1522 : 1518;
max = (tagged) ? 1522 : 1518;
while(len<min | len>max) len = random();
-10: len = (tagged) ? 1521 : 1517;
-11: len = (tagged) ? 1523 : 1519;
if(!quiet_on) printf("PG[%0d]: WARNING: Data length (payload) is zero.\n",my_port);
be_msg.print(e_mesg_error, "pg::date_gen", "", "PG[%0d]: Data length (payload) is zero TESTBENCH ERROR \n", my_port);
if( my_root != null & check_option(options, O_FRM_LEN_ERR2) )
len = cfg_reg[CFG_FRM_LEN] - offset -4;
if(debug_dg) printf("DEBUG: pg::data_gen: offset: %0d, len: %0d type: %0d\n",o,len,type);
sync(ALL,pg_random_event);
trigger(OFF,pg_random_event);
buf.val[offset++]= pg_random.nextdata();
trigger(ON,pg_random_event);
buf.val[offset++]=seed++;
if(b>7) tmp8[15-b++] = 1;
buf.val[offset++] = tmp8;
if(b>7) tmp8[15-b++] = 0;
buf.val[offset++] = tmp8;
for(n=0;n<len;n++) buf.val[offset++] = 0;
'{buf.val[o++], buf.val[o++]} = FC_PAUSE_OPCODE;
'{buf.val[o++], buf.val[o++]} = seed;
bit [15:0] tmp16 = cfg_reg[CFG_CRC_MASK];
for(n=0;n<len;n++) buf.val[offset++] = 0;
'{buf.val[o++], buf.val[o++]} = FC_PAUSE_OPCODE ^ tmp16;
'{buf.val[o++], buf.val[o++]} = seed;
printf("pg::data_gen: invalid type (%0d)\n",type);
printf("pg::data_gen: buf[%0d]: %h\n",o+n,buf.val[o+n]);
function bit [31:0] pg::crc32_add(bit [7:0] data, bit [31:0] crc) {
feedback = crc[31] ^ data[i];
crc[26] = crc[25] ^ feedback;
crc[23] = crc[22] ^ feedback;
crc[22] = crc[21] ^ feedback;
crc[16] = crc[15] ^ feedback;
crc[12] = crc[11] ^ feedback;
crc[11] = crc[10] ^ feedback;
crc[10] = crc[9] ^ feedback;
crc[8] = crc[7] ^ feedback;
crc[7] = crc[6] ^ feedback;
crc[5] = crc[4] ^ feedback;
crc[4] = crc[3] ^ feedback;
crc[2] = crc[1] ^ feedback;
crc[1] = crc[0] ^ feedback;
function integer pg::check_option(bit [63:0] option, bit [63:0] flag) {
if((option[63:0] & flag[63:0]) > 64'h0) check_option = 1;
function bit [7:0] pg::class_mask(integer funct, bit[7:0] a, bit[7:0] b) {
CLF_OR: class_mask = a && b;
CLF_AND: class_mask = a || b;
default: class_mask = 8'h00;
task pg::send_packet(bit [3:0] ptype, byte_array buf, integer len, bit [63:0] options) {
send_packet_xgmii (xgm0,ptype, buf, len, options);
else if (port_speed == 3)
send_packet_gmii (gm0, ptype, buf, len, options);
send_packet_mii (m0,ptype, buf, len, options);
send_packet_xgmii (xgm1,ptype, buf, len, options);
else if (port_speed == 3)
send_packet_gmii (gm1, ptype, buf, len, options);
send_packet_mii (m1, ptype, buf, len, options);
send_packet_gmii (gm2, ptype, buf, len, options);
send_packet_mii (m2, ptype, buf, len, options);
send_packet_gmii (gm3, ptype, buf, len, options);
send_packet_mii (m3, ptype, buf, len, options);
task pg::assert_col_tx (mii_def port_bind, bit [63:0] options) {
while(rxdv_set == 0) @(posedge port_bind.$rxclk);
if( check_option( options, O_RX_COL) & cfg_reg[CFG_COL_LEN]>0 & !tx_done ) {
itmp = cfg_reg[CFG_COL_DEL];
while(itmp>0 & !tx_done) {
@(posedge port_bind.$rxclk);
port_bind.$rxcol = 1 async;
itmp = cfg_reg[CFG_COL_LEN];
while(itmp>0 & !tx_done) {
@(posedge port_bind.$rxclk);
port_bind.$rxcol = 0 async;
task pg::assert_mii_err (mii_def port_bind ) {
if(tx_err_start==-1) return;
printf("PG: WARNING: tx_err injection length to short. (Start: %0d, Length: %0d)\n",
tx_err_start,tx_err_len);
while(cnt++ < tx_err_start & !tx_done)
@(posedge port_bind.$rxclk);
while(cnt++ < tx_err_len & !tx_done)
@(posedge port_bind.$rxclk);
printf("PG: WARNING: Packet was sent before tx_err could be assrted.(Start: %0d, Length: %0d)\n",
tx_err_start,tx_err_len);
task pg::send_packet_mii (mii_def port_bind, bit [3:0] ptype, byte_array buf, integer len, bit [63:0] options) {
bit [63:0] min_gap, time_tmp;
printf("DEBUG: PG low tx started: current_time: %0d\n", {get_time(HI),get_time(LO)} );
current_time = {get_time(HI),get_time(LO)};
if(port_speed==1) min_gap = 800 * MII_IP_GAP;
else min_gap = 80 * MII_IP_GAP;
time_tmp = current_time - last_tx_time;
printf("DEBUG: PG low tx: last_time: %0d, current_time: %0d, diff: %0d\n",
last_tx_time,current_time,time_tmp);
if((time_tmp < min_gap) & !check_option(options, O_NO_IP_GAP_FIX) & !check_option(options, O_CUSTOM_IP_GAP) ) {
time_tmp = min_gap - time_tmp;
if(debug_mii_tx) printf("DEBUG: PG low tx: Min_gap: %0d, gap_diff: %0d\n",min_gap,time_tmp);
if(port_speed==1) time_tmp = time_tmp / 400;
else time_tmp = time_tmp / 40;
if(debug_mii_tx) printf("DEBUG: PG low tx: waiting additional %0d cycles\n",time_tmp);
repeat(time_tmp) @(posedge port_bind.$rxclk);
if( check_option(options, O_CUSTOM_IP_GAP) ) {
repeat(cfg_reg[CFG_IP_GAP]) @(posedge port_bind.$rxclk);
// assert_mii_err (get_bind( port_bind ));
assert_mii_err ( port_bind );
if( check_option(options, O_PREAMB_ERR) ) cnt = cfg_reg[CFG_PRAMB_CNT];
port_bind.$rxd = tmp[3:0];
@(posedge port_bind.$rxclk);
port_bind.$rxd = tmp[7:4];
@(posedge port_bind.$rxclk);
if( check_option(options, O_SFD_ERR) ) tmp = cfg_reg[CFG_SFD_TOKEN];
port_bind.$rxd = tmp[3:0];
@(posedge port_bind.$rxclk);
port_bind.$rxd = tmp[7:4];
@(posedge port_bind.$rxclk);
if(debug_mii==1) printf("MII: Sending Byte[%0d]: %h\n", n, buf.val[n] );
port_bind.$rxd = tmp[3:0];
@(posedge port_bind.$rxclk);
if(n != (len-1) | !check_option(options, O_NIBBLE_ERR) ) {
port_bind.$rxd = tmp[7:4];
@(posedge port_bind.$rxclk);
port_bind.$rxd = tmp[3:0];
@(posedge port_bind.$rxclk);
last_tx_time = {get_time(HI),get_time(LO)};
task pg::assert_gmii_err (gmii_def port_bind) {
if(tx_err_start==-1) return;
printf("PG: WARNING: tx_err injection length to short. (Start: %0d, Length: %0d)\n",
tx_err_start,tx_err_len);
while(cnt++ < tx_err_start & !tx_done)
@(posedge port_bind.$rxclk);
while(cnt++ < tx_err_len & !tx_done)
@(posedge port_bind.$rxclk);
printf("PG: WARNING: Packet was sent before tx_err could be assrted.(Start: %0d, Length: %0d)\n",
tx_err_start,tx_err_len);
task pg::send_packet_gmii (gmii_def port_bind, bit [3:0] ptype, byte_array buf, integer len, bit [63:0] options) {
bit [63:0] min_gap, time_tmp;
integer align_cycles; //hummer
integer need_extra_clocks;
//current_time = {get_time(HI),get_time(LO)};
current_time = clock_counter;
min_gap = GMII_IP_GAP - 1;
// PORT2 gets the IPG given by the plusarg PKTGEN_PORT2_1G_IPG
if (get_plus_arg (CHECK, "PKTGEN_PORT2_1G_IPG") && (my_port==2))
min_gap = get_plus_arg (NUM, "PKTGEN_PORT2_1G_IPG");
// PORT3 gets the IPG given by the plusarg PKTGEN_PORT3_1G_IPG
if (get_plus_arg (CHECK, "PKTGEN_PORT3_1G_IPG") && (my_port==3))
min_gap = get_plus_arg (NUM, "PKTGEN_PORT3_1G_IPG");
time_tmp = current_time - last_tx_time;
ipg_diffs = time_tmp; // 800 ps
ipg_clock_diffs = 0; //hummer
if(ipg_diffs < min_gap) {
ipg_clock_diffs = min_gap - ipg_diffs;
else need_extra_clocks = 0;
//////////////////align logic>>>>>>>>>>>>>>>>
//first calculate where the align point is?
align_cycles = 4-(((current_time-prev_current_time))%4);
//see if the align point is beyond IPG
//if so, lets move the IPG to align point
if(align_cycles >= ipg_clock_diffs) {
ipg_clock_diffs = align_cycles;
//if align is before IPG, we need to go to next align point
//this next align point is 4-(difference of the current align-ipg)
if(align_cycles < ipg_clock_diffs) {
//also make sure the IPG is not a multiple of next align
if((ipg_clock_diffs-align_cycles)%4)
ipg_clock_diffs += 4-(ipg_clock_diffs-align_cycles)%4;
//////////////////align logic<<<<<<<<<<<<<<<<
printf("DEBUG: PG low tx: last_time: %0d, current_time: %0d, diff: %0d\n",
last_tx_time,current_time,time_tmp);
if( !check_option(options, O_NO_IP_GAP_FIX) & !check_option(options, O_CUSTOM_IP_GAP) & need_extra_clocks ) {
repeat(ipg_clock_diffs) @(posedge port_bind.$rxclk);
if( check_option(options, O_CUSTOM_IP_GAP) ) {
repeat(cfg_reg[CFG_IP_GAP]) @(posedge port_bind.$rxclk);
// assert_gmii_err (get_bind( port_bind));
assert_gmii_err ( port_bind);
prev_current_time = clock_counter;
//port_bind.$rxd = XGMII_SOP;
/* @(posedge port_bind.$rxclk); */
if( check_option(options, O_PREAMB_ERR) ) cnt = cfg_reg[CFG_PRAMB_CNT];
port_bind.$rxd = GMII_PREAMBLE;
@(posedge port_bind.$rxclk);
// printf("DEBUG pack_db.options - %x preamble_cnt - %d sfd - %d \n",options,cfg_reg[CFG_PRAMB_CNT],cfg_reg[CFG_SFD_TOKEN]);
if( check_option(options, O_SFD_ERR) ) {
sfd = cfg_reg[CFG_SFD_TOKEN];
port_bind.$rxd = cfg_reg[CFG_SFD_TOKEN];
@(posedge port_bind.$rxclk);
printf("SKIP SFD GENERATION!!\n");
port_bind.$rxd = GMII_SOF;
@(posedge port_bind.$rxclk);
if(debug_gmii==1) printf("GMII: Sending Byte[%0d]: %h\n", n, buf.val[n] );
if(n != (len-1) | !check_option(options, O_NIBBLE_ERR) ) {
port_bind.$rxd = buf.val[n];
@(posedge port_bind.$rxclk);
last_tx_time = clock_counter;
port_bind.$rxd = GMII_PREAMBLE;
@(posedge port_bind.$rxclk);
//last_tx_time = {get_time(HI),get_time(LO)};
task pg::assert_xgmii_err (xgmii_def port_bind) {
if(tx_err_start==-1) return;
printf("PG: WARNING: tx_err injection length to short. (Start: %0d, Length: %0d)\n",
tx_err_start,tx_err_len);
while(cnt++ < tx_err_start & !tx_done)
@(posedge port_bind.$rxclk_int);
while(cnt++ < tx_err_len & !tx_done)
@(posedge port_bind.$rxclk_int);
printf("PG: WARNING: Packet was sent before tx_err could be assrted.(Start: %0d, Length: %0d)\n",
tx_err_start,tx_err_len);
task pg::send_packet_xgmii (xgmii_def port_bind,bit [3:0] ptype, byte_array buf, integer len, bit [63:0] options) {
bit [63:0] min_gap, time_tmp;
integer align_cycles; //hummer
integer need_extra_clocks;
printf("send_packet_xgmii - Enteri Time - %d \n",{get_time(HI),get_time(LO)});
// current_time = {get_time(HI),get_time(LO)};
current_time = clock_counter;
min_gap = 8 * XGMII_IP_GAP ; // TOADS----
// both ports at the same IPG, if the plusarg PKTGEN_10G_IPG is specified
// this plusarg is really a redundant after we had PKTGEN_PORT0_10G_IPG/PKTGEN_PORT1_10G_IPG
// but want to keep this for some old test runs which use this
if (get_plus_arg (CHECK, "PKTGEN_10G_IPG"))
min_gap = get_plus_arg (NUM, "PKTGEN_10G_IPG");
// PORT0 gets the IPG given by the plusarg PKTGEN_PORT0_10G_IPG
if (get_plus_arg (CHECK, "PKTGEN_PORT0_10G_IPG") && (my_port==0))
min_gap = get_plus_arg (NUM, "PKTGEN_PORT0_10G_IPG");
// PORT1 gets the IPG given by the plusarg PKTGEN_PORT1_10G_IPG
if (get_plus_arg (CHECK, "PKTGEN_PORT1_10G_IPG") && (my_port==1))
min_gap = get_plus_arg (NUM, "PKTGEN_PORT1_10G_IPG");
time_tmp = current_time - last_tx_time;
ipg_diffs = time_tmp; // 800 ps
ipg_clock_diffs = 0; //hummer
if(ipg_diffs < min_gap) {
ipg_clock_diffs = min_gap - ipg_diffs;
else need_extra_clocks = 0;
//////////////////align logic>>>>>>>>>>>>>>>>
//first calculate where the align point is?
align_cycles = 4-(((current_time-prev_current_time))%4);
//see if the align point is beyond IPG
//if so, lets move the IPG to align point
if(align_cycles >= ipg_clock_diffs) {
ipg_clock_diffs = align_cycles;
//if align is before IPG, we need to go to next align point
//this next align point is 4-(difference of the current align-ipg)
if(align_cycles < ipg_clock_diffs) {
//also make sure the IPG is not a multiple of next align
if((ipg_clock_diffs-align_cycles)%4)
ipg_clock_diffs += 4-(ipg_clock_diffs-align_cycles)%4;
//////////////////align logic<<<<<<<<<<<<<<<<
printf("pg::send_packet_xgmii: DEBUG--len - %d \n",len);
printf("pg::send_packet_xgmii: DEBUG--IPG ipg_diff - %d ipg_clock_diffs - %d need_extra_clocks - %d \n",ipg_diffs,ipg_clock_diffs,need_extra_clocks);
printf("DEBUG: PG low tx: last_time: %0d, current_time: %0d, diff: %0d options = %x \n",
last_tx_time,current_time,time_tmp,options);
if( !check_option(options, O_NO_IP_GAP_FIX) & !check_option(options, O_CUSTOM_IP_GAP) & need_extra_clocks ) {
repeat(ipg_clock_diffs) @(posedge port_bind.$rxclk_int);
} else if( check_option(options, O_CUSTOM_IP_GAP) ) {
repeat(cfg_reg[CFG_IP_GAP]) @(posedge port_bind.$rxclk_int);
// assert_xgmii_err (get_bind( port_bind ) );
assert_xgmii_err (port_bind );
// prev_current_time = {get_time(HI),get_time(LO)}; //hummer
prev_current_time = clock_counter;
port_bind.$rxd = XGMII_SOP;
@(posedge port_bind.$rxclk_int);
if( check_option(options, O_PREAMB_ERR) ) cnt = cfg_reg[CFG_PRAMB_CNT];
port_bind.$rxd = XGMII_PREAMBLE;
@(posedge port_bind.$rxclk_int);
// printf("DEBUG pack_db.options - %x preamble_cnt - %d sfd - %d \n",options,cfg_reg[CFG_PRAMB_CNT],cfg_reg[CFG_SFD_TOKEN]);
if( check_option(options, O_SFD_ERR) ) {
sfd = cfg_reg[CFG_SFD_TOKEN];
port_bind.$rxd = cfg_reg[CFG_SFD_TOKEN];
@(posedge port_bind.$rxclk_int);
printf("SKIP SFD GENERATION!!\n");
port_bind.$rxd = XGMII_SOF;
@(posedge port_bind.$rxclk_int);
// printf("XGMII: Sending Byte[%0d]: %h\n", n, buf.val[n] );
if(n != (len-1) | !check_option(options, O_NIBBLE_ERR) ) {
port_bind.$rxd = buf.val[n];
@(posedge port_bind.$rxclk_int);
port_bind.$rxd = XGMII_EOP;
@(posedge port_bind.$rxclk_int);
// last_tx_time = {get_time(HI),get_time(LO)};
last_tx_time = clock_counter;
port_bind.$rxd = XGMII_IDLE;
@(posedge port_bind.$rxclk_int);
//prev_current_time = current_time; //hummer
printf("send_packet_xgmii - Exit Time - %d \n",{get_time(HI),get_time(LO)});
task pg::wait_clk(integer count) {
repeat(count) @(posedge CLOCK);
task pg::wait_tx_clk(integer count) {
0: wait_tx_clk_if (m0 , count);
1: wait_tx_clk_if (m1 , count);
2: wait_tx_clk_if (m2 , count);
3: wait_tx_clk_if (m3 , count);
task pg::wait_tx_clk_if ( mii_def port_bind, integer count) {
repeat(count) @(posedge port_bind.$txclk);
task pg::wait_rx_clk(integer count) {
0: wait_tx_clk_if (m0 , count);
1: wait_tx_clk_if (m1 , count);
2: wait_tx_clk_if (m2 , count);
3: wait_tx_clk_if (m3 , count);
task pg::wait_rx_clk_if ( mii_def port_bind, integer count) {
repeat(count) @(posedge port_bind.$rxclk);
task pg::new(integer my_porti, (bit [3:0] ptype=0)) {
ifedx_control = 16'h0001;
// trigger(ON,pkt_gen_lock);
pkt_gen_lock = alloc(SEMAPHORE,0,1,0);
semaphore_put(pkt_gen_lock,1);
trigger(ON,pg_random_event);
printf("PG: INIT: Warning: Port %0d is invalid or out of range.\n", my_port);
printf("INFO: Packet Generator attaching to port %0d\n",my_port);
if(pg_used_ports[my_port] == 1) {
printf("PG: INIT: Port %0d already in use.\n", my_port);
pg_used_ports[my_port] = 1;
queue_lock = alloc(SEMAPHORE,0,1,1);
printf("PG: INIT: Could not allocate spaphore queue_lock.\n");
mb_q = alloc(MAILBOX, 0, 1);
pkt_gen_sync = alloc(MAILBOX, 0, 1);
printf("PG: INIT: Could not allocate mailbox mb_q.\n");
mbox_id.pg_mb[my_port] = alloc(MAILBOX, 0, 1);
if(mbox_id.pg_mb[my_port] == 0) {
printf("PG: INIT: Could not allocate mailbox mbox_id.pg_mb[%0d].\n",my_port);
if(ptr_to_first_pg==null) ptr_to_first_pg = this;
last_tx_time = {get_time(HI),get_time(LO)};
for(n=0;n<CFG_LAST_ENTRY;n++) cfg_reg[n] = 0;
l3_mask[n].val[i] = 8'hff;
for(n=CL_RSVP;n<CL_USER1;n++) {
l3_class[n].val[0] = 8'h08;
l3_class[n].val[2] = 8'h45;
l3_class[CL_ARP].val[0] = 8'h08;
l3_class[CL_ARP].val[1] = 8'h06;
l3_class[CL_RARP].val[0] = 8'h80;
l3_class[CL_RARP].val[1] = 8'h35;
l3_class[CL_RSVP].val[0] = 8'h08;
l3_class[CL_RSVP].val[11] = 8'h2e;
l3_class[CL_IGMP].val[0] = 8'h08;
l3_class[CL_IGMP].val[11] = 8'h02;
l3_class[CL_ICMP].val[0] = 8'h08;
l3_class[CL_ICMP].val[11] = 8'h01;
l3_class[CL_GRE].val[0] = 8'h08;
l3_class[CL_GRE].val[11] = 8'h2F;
l3_class[CL_PIM].val[0] = 8'h08;
l3_class[CL_PIM].val[11] = 8'h67;
l3_class[CL_IP_TUN_V4_V4].val[0] = 8'h08;
l3_class[CL_IP_TUN_V4_V4].val[2] = 8'h45;
l3_class[CL_IP_TUN_V4_V4].val[11] = 8'h04;
l3_class[CL_IP_TUN_V4_V6].val[0] = 8'h08;
l3_class[CL_IP_TUN_V4_V6].val[2] = 8'h45;
l3_class[CL_IP_TUN_V4_V6].val[11] = 8'h29;
l3_class[CL_IP].val[0] = 8'h08;
l3_class[CL_IP].val[2] = 8'h45;
l3_class[CL_IP_FRAG].val[0] = 8'h08;
l3_class[CL_IP_FRAG].val[2] = 8'h45;
l3_class[CL_IP_FRAG].val[8] = 8'h20;
l3_class[CL_IP_FRAG].val[11] = 8'h12;
l3_mask[CL_IP_FRAG].val[8] = 8'h00;
l3_mask[CL_IP_FRAG].val[9] = 8'h00;
l3_class[CL_IP_SEC_AH].val[0] = 8'h08;
l3_class[CL_IP_SEC_AH].val[2] = 8'h48;
l3_class[CL_IP_SEC_AH].val[11]= 8'h33;
l3_class[CL_IP_SEC_ESP].val[0]= 8'h08;
l3_class[CL_IP_SEC_ESP].val[2]= 8'h48;
l3_class[CL_IP_SEC_ESP].val[11]= 8'h32;
l3_class[CL_IP_OPT].val[0] = 8'h08;
l3_class[CL_IP_OPT].val[2] = 8'h48;
l3_class[CL_UDP].val[0] = 8'h08;
l3_class[CL_UDP].val[2] = 8'h45;
l3_class[CL_UDP].val[11] = 8'h11;
l3_class[CL_UDP_OPT].val[2] = 8'h48;
l3_class[CL_UDP_OPT].val[11] = 8'h11;
l3_class[CL_UDP_FRAG].val[0] = 8'h08;
l3_class[CL_UDP_FRAG].val[2] = 8'h45;
l3_class[CL_UDP_FRAG].val[8] = 8'h01;
l3_class[CL_UDP_FRAG].val[9] = 8'h00;
l3_class[CL_UDP_FRAG].val[11] = 8'h11;
l3_mask[CL_UDP_FRAG].val[8] = 8'h00;
l3_mask[CL_UDP_FRAG].val[9] = 8'h00;
l3_class[CL_TCP].val[0] = 8'h08;
l3_class[CL_TCP].val[2] = 8'h45;
l3_class[CL_TCP].val[11] = 8'h06;
l3_class[CL_TCP_OPT].val[0] = 8'h08;
l3_class[CL_TCP_OPT].val[2] = 8'h45;
l3_class[CL_TCP_OPT].val[11] = 8'h06;
l3_class[CL_TCP_FRAG].val[0] = 8'h08;
l3_class[CL_TCP_FRAG].val[2] = 8'h45;
l3_class[CL_TCP_FRAG].val[8] = 8'h21;
l3_class[CL_TCP_FRAG].val[9] = 8'h00;
l3_class[CL_TCP_FRAG].val[11] = 8'h06;
l3_mask[CL_TCP_FRAG].val[8] = 8'h00;
l3_mask[CL_TCP_FRAG].val[9] = 8'h00;
l3_class[CL_IP_V6].val[0] = 8'h86;
l3_class[CL_IP_V6].val[1] = 8'hdd;
l3_class[CL_IP_V6].val[2] = 8'h60;
l3_class[CL_ICMP_IP_V6].val[0] = 8'h86;
l3_class[CL_ICMP_IP_V6].val[1] = 8'hdd;
l3_class[CL_ICMP_IP_V6].val[2] = 8'h60;
l3_class[CL_ICMP_IP_V6].val[8] = 8'h01;
l3_class[CL_IGMP_IP_V6].val[0] = 8'h86;
l3_class[CL_IGMP_IP_V6].val[1] = 8'hdd;
l3_class[CL_IGMP_IP_V6].val[2] = 8'h60;
l3_class[CL_IGMP_IP_V6].val[8] = 8'h02;
l3_class[CL_RSVP_IP_V6].val[0] = 8'h86;
l3_class[CL_RSVP_IP_V6].val[1] = 8'hdd;
l3_class[CL_RSVP_IP_V6].val[2] = 8'h60;
l3_class[CL_RSVP_IP_V6].val[8] = 8'h2E;
l3_class[CL_GRE_IP_V6].val[0] = 8'h86;
l3_class[CL_GRE_IP_V6].val[1] = 8'hdd;
l3_class[CL_GRE_IP_V6].val[2] = 8'h60;
l3_class[CL_GRE_IP_V6].val[8] = 8'h2F;
l3_class[CL_PIM_IP_V6].val[0] = 8'h86;
l3_class[CL_PIM_IP_V6].val[1] = 8'hdd;
l3_class[CL_PIM_IP_V6].val[2] = 8'h60;
l3_class[CL_PIM_IP_V6].val[8] = 8'h67;
l3_class[CL_IP_V6_SEC_AH].val[0] = 8'h86;
l3_class[CL_IP_V6_SEC_AH].val[1] = 8'hdd;
l3_class[CL_IP_V6_SEC_AH].val[2] = 8'h60;
l3_class[CL_IP_V6_SEC_AH].val[8] = 8'h33;
l3_class[CL_IP_V6_SEC_ESP].val[0] = 8'h86;
l3_class[CL_IP_V6_SEC_ESP].val[1] = 8'hdd;
l3_class[CL_IP_V6_SEC_ESP].val[2] = 8'h60;
l3_class[CL_IP_V6_SEC_ESP].val[8] = 8'h32;
l3_class[CL_IP_TUN_V6_V6].val[0] = 8'h86;
l3_class[CL_IP_TUN_V6_V6].val[1] = 8'hdd;
l3_class[CL_IP_TUN_V6_V6].val[8] = 8'h29;
l3_class[CL_IP_TUN_V6_V4].val[0] = 8'h86;
l3_class[CL_IP_TUN_V6_V4].val[1] = 8'hdd;
l3_class[CL_IP_TUN_V6_V4].val[8] = 8'h04;
l3_class[CL_UDP_IP_V6].val[0] = 8'h86;
l3_class[CL_UDP_IP_V6].val[1] = 8'hDD;
l3_class[CL_UDP_IP_V6].val[2] = 8'h60;
l3_class[CL_UDP_IP_V6].val[8] = 8'h11;
l3_class[CL_UDP_OPT_IP_V6].val[0] = 8'h86;
l3_class[CL_UDP_OPT_IP_V6].val[2] = 8'h48;
l3_class[CL_UDP_OPT_IP_V6].val[8] = 8'h11;
l3_class[CL_UDP_FRAG_IP_V6].val[0] = 8'h86;
l3_class[CL_UDP_FRAG_IP_V6].val[2] = 8'h45;
l3_class[CL_UDP_FRAG_IP_V6].val[8] = 8'h01;
l3_class[CL_UDP_FRAG_IP_V6].val[5] = 8'h12;
l3_class[CL_UDP_FRAG_IP_V6].val[6] = 8'h12;
l3_class[CL_UDP_FRAG_IP_V6].val[8] = 8'h11;
l3_mask[CL_UDP_FRAG_IP_V6].val[8] = 8'h00;
l3_mask[CL_UDP_FRAG_IP_V6].val[9] = 8'h00;
l3_class[CL_TCP_IP_V6].val[0] = 8'h86;
l3_class[CL_TCP_IP_V6].val[1] = 8'hDD;
l3_class[CL_TCP_IP_V6].val[2] = 8'h60;
l3_class[CL_TCP_IP_V6].val[8] = 8'h06;
l3_class[CL_TCP_OPT_IP_V6].val[0] = 8'h86;
l3_class[CL_TCP_OPT_IP_V6].val[1] = 8'hDD;
l3_class[CL_TCP_OPT_IP_V6].val[2] = 8'h60;
l3_class[CL_TCP_OPT_IP_V6].val[8] = 8'h06;
l3_class[CL_TCP_FRAG_IP_V6].val[0] = 8'h86;
l3_class[CL_TCP_FRAG_IP_V6].val[2] = 8'h45;
l3_class[CL_TCP_FRAG_IP_V6].val[5] = 8'h12;
l3_class[CL_TCP_FRAG_IP_V6].val[8] = 8'h06;
l3_mask[CL_TCP_FRAG_IP_V6].val[5] = 8'h00;
l3_mask[CL_TCP_FRAG_IP_V6].val[6] = 8'h00;
cfg_reg[CFG_UDP_LEN] = 0;
cfg_reg[CFG_UDP_CSM] = 0;
cfg_reg[CFG_TCP_SEQ] = 0;
cfg_reg[CFG_TCP_ACK] = 0;
cfg_reg[CFG_TCP_LEN] = 4'b0101;
cfg_reg[CFG_TCP_FLAG]= 0;
cfg_reg[CFG_TCP_WIN] = 0;
cfg_reg[CFG_TCP_CSM] = 0;
cfg_reg[CFG_TCP_URG] = 0;
0: if (get_plus_arg(CHECK, "MAC_SPEED0=")) {
mac_speed = get_plus_arg(NUM,"MAC_SPEED0=");
config_tx (m0 , mac_speed);
1: if (get_plus_arg(CHECK, "MAC_SPEED1=")) {
mac_speed = get_plus_arg(NUM,"MAC_SPEED1=");
config_tx (m1 , mac_speed);
2: if (get_plus_arg(CHECK, "MAC_SPEED2=")) {
mac_speed = get_plus_arg(NUM,"MAC_SPEED2=");
config_tx (m2 , mac_speed);
3: if (get_plus_arg(CHECK, "MAC_SPEED3=")) {
mac_speed = get_plus_arg(NUM,"MAC_SPEED3=");
config_tx (m3 , mac_speed);
// This is just a HACK to get going
0: if (port_speed == 4) {
@(posedge xgm0.$rxclk_int); clock_counter = clock_counter + 1;
} else if (port_speed == 3) {
@(posedge gm0.$rxclk); clock_counter = clock_counter + 1;
@(posedge m0.$rxclk); clock_counter = clock_counter + 1;
1: if (port_speed == 4) {
@(posedge xgm1.$rxclk_int); clock_counter = clock_counter + 1;
} else if (port_speed == 3) {
@(posedge gm1.$rxclk); clock_counter = clock_counter + 1;
@(posedge m1.$rxclk); clock_counter = clock_counter + 1;
2: if (port_speed == 4) {
} else if (port_speed == 3) {
@(posedge gm2.$rxclk); clock_counter = clock_counter + 1;
@(posedge m2.$rxclk); clock_counter = clock_counter + 1;
3: if (port_speed == 4) {
} else if (port_speed == 3) {
@(posedge gm3.$rxclk); clock_counter = clock_counter + 1;
@(posedge m3.$rxclk); clock_counter = clock_counter + 1;
task pg::config_tx (mii_def port_bind, integer mac_speed ) {
if(mac_speed == 10000) port_bind.$rx_config = 4;
if(mac_speed == 1000) port_bind.$rx_config = 3;
if(mac_speed == 100) port_bind.$rx_config = 2;
else port_bind.$rx_config = 1;
if(mac_speed == 10000) port_speed = 4;
if(mac_speed == 1000) port_speed = 3;
if(mac_speed == 100) port_speed = 2;
function bit [31:0] pg::crc_gen(byte_array p, integer start, integer len) {
//printf("CRC Function is called \n");
for(i=start;i<len;i=i+1) begin
tmp0 = crc32_add( p.val[i], tmp0 );
crc_gen[31:24] = tmp0[07:00];
crc_gen[23:16] = tmp0[15:08];
crc_gen[15:08] = tmp0[23:16];
crc_gen[07:00] = tmp0[31:24];
printf("------------------------------\n");
printf("PG[%0d]: Status Report:\n",my_port);
printf(" Encountered %0d ERRORS\n",error_count);
printf(" Encountered %0d WARNINGS\n",warning_count);
printf(" Sent %0d packets\n",pckt_num);
printf("------------------------------\n\n");
task pg::config(integer what, bit [31:0] data) {
printf("WARNING: Packet Generator[%0d]: ", my_port);
printf("ERROR: Packet Generator[%0d] time:%0d : ", my_port, {get_time(HI), get_time(LO)});
task pg::display_buf( byte_array buf, integer hwlen, (integer ifedx=0)) {
integer tunneling_ipv4 = 0;
integer tunneling_ipv6 = 0;
integer ah_transp_ipv4 = 0;
integer ah_transp_ipv6 = 0;
integer esp_transp_ipv4 = 0;
integer esp_transp_ipv6 = 0;
integer ipv4_header_length;
printf("\n\n______________________________________________________________\n");
printf("vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n\n");
printf("____________ Hex Dump ____________\n");
if( !(n % 16) ) printf("\n%d: ",n);
printf("%h ", buf.val[ptr++]);
printf("\n__________________________________\n\n");
printf("+---------------\n");
printf("| Destination Address: %h.%h.%h.%h.%h.%h\n", buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] );
printf("| Source Address: %h.%h.%h.%h.%h.%h\n", buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] );
len = {buf.val[ptr++], buf.val[ptr++]};
if( len == TPID_8021Q ) {
if( {buf.val[ptr+4], buf.val[ptr+5], buf.val[ptr+6]} == LLC_SNAP ) {
printf("| L2 Header Type: 802.1Q Tagged LLC-SNAP Ethernet Header\n");
printf("| TPID: %0h\n", len );
printf("| TCI: %h\n", {buf.val[ptr++], buf.val[ptr++]} );
len = {buf.val[ptr++], buf.val[ptr++]};
printf("| LEN/TYPE: 0x%h(%0d)\n", len, len );
printf("| LLC: %h\n", {buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] });
printf("| SNAP: %h\n", {buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } );
len = {buf.val[ptr - 2], buf.val[ptr - 1]};
} else { // if not LLC SNAP
printf("| L2 Header Type: 802.1Q Tagged Ethernet Header\n");
printf("| TPID: %0h\n", len );
printf("| TCI: %h\n", {buf.val[ptr++], buf.val[ptr++]} );
len = {buf.val[ptr++], buf.val[ptr++]};
printf("| TYPE/LEN: 0x%h(%d)\n", len, len);
}/*endifTPID_8021Q*/ else if ( len == CNTL_FRAME ) {
printf("| L2 Header Type: MAC Control Frame Header\n");
printf("| Type: %h\n", len );
} else { // endif control frame
if( {buf.val[ptr], buf.val[ptr+1], buf.val[ptr+2]} == LLC_SNAP ) {
printf("| L2 Header Type: LLC-SNAP Ethernet Header\n");
printf("| Data Length: 0x%h(%0d)\n", len, len);
printf("| LLC: %h\n", {buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] });
printf("| SNAP: %h\n", {buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } );
if( buf.val[ptr-2] == 8'h08 ) {
if( buf.val[ptr - 11 ] == TCP_PROTO){
if( buf.val[ptr-2] == 8'h86 ) { ptr +=40;
if( buf.val[ptr - 34 ] == TCP_PROTO){
} /*endif LLC_SANP*/ else {
printf("| L2 Header Type: 802.3 Ethernet Header\n");
printf("| Data Length/Type: 0x%h(%0d)\n", len, len);
if( ((buf.val[ptr] & 8'h40)==8'h40 ) & ( (buf.val[ptr] & 8'hf)>5)) {
ipv4_header_length = (buf.val[ptr] & 8'hf);
token = { buf.val[ptr + ( (4*ipv4_header_length) -20 ) ], buf.val[ptr + ( (4*ipv4_header_length) -20 ) +1] };
token = { buf.val[ptr], buf.val[ptr+1] };
printf(" DEBUG- token - %d \n",token);
if((len>16'h0600 & len != CNTL_FRAME) || ((len == RARP_FRAME) &(len != CNTL_FRAME))){
// ptr here points to the first byte of ip datagram
if((buf.val[ptr - 2 ] == 8'h08 ) || (( buf.val[ptr-2] == 8'h80) && (buf.val[ptr-1] == 8'h35))) { // IP datagram or RARP
if( buf.val[ptr + 9] == AH_PROTO) {
printf("+-------------------------------------\n");
printf(" L3 Header-- Type: IPv4, IPSec: AH\n");
printf("+--------------------------------------\n");
} else if( buf.val[ptr + 9] == ESP_PROTO) {
printf("+-------------------------------------\n");
printf(" L3 Header-- Type: IPv4, IPSec: ESP\n");
printf("+--------------------------------------\n");
} else if( buf.val[ptr + 9] == IP_V4_PROTO) {
printf("+-------------------------------------\n");
printf(" L3 Header-- Type: Tunnel (IPv4/IPv4)\n");
printf("+--------------------------------------\n");
printf("| IP Header Tunnel Layer 1: IPv4\n| \n");
} else if( buf.val[ptr + 9] == IP_V6_PROTO) {
printf("+-------------------------------------\n");
printf(" L3 Header-- Type: Tunnel (IPv4/IPv6)\n");
printf("+--------------------------------------\n");
printf("| IP Header Tunnel Layer 1: IPv4\n| \n");
printf("+-------------------------------------\n");
printf(" L3 Header-- Type: IPv4\n");
printf("+--------------------------------------\n");
ipv4_header_length = (buf.val[ptr] & 8'hf);
// printf("DEBUG- ipv4_header_length - %d \n",ipv4_header_length);
//ptr here points to type/len field
// looks like display class increments the ptr to the beginning of IP src address..
printf("| IPV4 Payload Len: %h%h\n", buf.val[ptr-10], buf.val[ptr-9] );
printf("| IPV4 Checksum: %h%h\n", buf.val[ptr-2], buf.val[ptr-1] );
if(ipv4_header_length>5) {
printf("| IPV4 Header Length: %d \n", ipv4_header_length);
printf("| IP SRC Address: %h.%h.%h.%h\n", buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] );
printf("| IP DST Address: %h.%h.%h.%h\n", buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] );
for(i=0;i< (ipv4_header_length -5); i ++) {
printf("| IP Options: %h.%h.%h.%h\n", buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] );
printf("| ESP SPI : %h.%h.%h.%h\n", buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] );
printf("| AH SPI : %h.%h.%h.%h\n", buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] );
printf("| ----------- \n|\n");
printf("| IP Header Tunnel Layer 2: IPv4:\n");
printf("| IP SRC Address: %h.%h.%h.%h\n", buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] );
printf("| IP DST Address: %h.%h.%h.%h\n", buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] );
} else if( tunneling_ipv6) {
printf("| ----------- \n|\n");
printf("| IP Header Tunnel Layer 2: IPv6:\n");
display_class_ipv6(buf, ptr);
printf("| Payload Len: 0x%h(%d)\n", buf.val[ptr++], buf.val[ptr++]);
printf("| Next Header: 0x%h\n", buf.val[ptr++]);
printf("| Hop Limit : 0x%h\n", buf.val[ptr++]);
printf("| IP SRC Address: %h%h:%h%h:%h%h:%h%h:%h%h:%h%h:%h%h:%h%h\n", buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++],
buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++],
buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] );
printf("| IP DST Address: %h%h:%h%h:%h%h:%h%h:%h%h:%h%h:%h%h:%h%h\n", buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++],
buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++],
buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] );
buf_shift = 11 + 4*(ipv4_header_length -5) ;
if( buf.val[ptr - buf_shift ] == UDP_PROTO) {
printf("+-------------------------------------\n");
printf(" L4 Header-- Type: UDP \n");
printf("+--------------------------------------\n");
printf("| UDP SRC Port: %h\n", {buf.val[ptr++], buf.val[ptr++]} );
printf("| UDP DST Port: %h\n", {buf.val[ptr++], buf.val[ptr++]} );
printf("| UDP LEN : %h\n", {buf.val[ptr++], buf.val[ptr++]} );
printf("| UDP Chksum : %h\n", {buf.val[ptr++], buf.val[ptr++]} );
// - ptr here is the first byte of UDP data
token = { buf.val[ptr + 0], buf.val[ptr + 1] };
printf(" DEBUG- UDP token - %d \n",token);
} else if( buf.val[ptr - buf_shift ] == TCP_PROTO) {
printf("+-------------------------------------\n");
printf(" L4 Header-- Type: TCP\n");
printf("+--------------------------------------\n");
printf("| TCP SRC Port: %h\n", {buf.val[ptr++], buf.val[ptr++]} );
printf("| TCP DST Port: %h\n", {buf.val[ptr++], buf.val[ptr++]} );
printf("| TCP Sequence #: %h\n", {buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++]} );
printf("| TCP ACK #: %h\n", {buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++]} );
flag_bit = buf.val[ptr++];
printf("| TCP Flag bits: URG:%b ACK:%b PSH:%b RST:%b SYN:%b FIN:%b\n", flag_bit[5], flag_bit[4], flag_bit[3], flag_bit[2], flag_bit[1], flag_bit[0]);
printf("| Window Size: %h\n", {buf.val[ptr++], buf.val[ptr++]});
printf("| TCP Checksum: %h\n", {buf.val[ptr++], buf.val[ptr++]});
if(cfg_reg[CFG_TCP_LEN] > 5 ) { //
printf("| TCP Option : ");
for(n=0; n<(cfg_reg[CFG_TCP_LEN]-5); n++) {
printf("%h%h%h%h ", buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++]);
} // end if checking option value
printf("+---------------\n");
// - ptr here is the first byte of TCP data
token = { buf.val[ptr + 2], buf.val[ptr+3] };
printf(" DEBUG- TCP token ptr - %d - %d \n",token,ptr);
} else if (esp_transp_ipv4) {
token = { buf.val[ptr], buf.val[ptr+1] };
} else if (ah_transp_ipv4) {
token = { buf.val[ptr], buf.val[ptr+1] };
token = { buf.val[ptr], buf.val[ptr+1] };
} /*endif IP datagram or RARP*/ else { /*IPV6*/
if( buf.val[ptr + 6] == AH_PROTO) {
printf("+-------------------------------------\n");
printf(" L3 Header-- Type: IPv6, IPSec: AH\n");
printf("+--------------------------------------\n");
} else if( buf.val[ptr + 6] == ESP_PROTO) {
printf("+-------------------------------------\n");
printf(" L3 Header-- Type: IPv6, IPSec: ESP\n");
printf("+--------------------------------------\n");
} else if( buf.val[ptr + 6] == IP_V4_PROTO) {
printf("+-------------------------------------\n");
printf(" L3 Header-- Type: Tunnel (IPv6/IPv4)\n");
printf("+--------------------------------------\n");
printf("| IP Header Tunnel Layer 1: IPv6\n");
} else if( buf.val[ptr + 6] == IP_V6_PROTO) {
printf("+-------------------------------------\n");
printf(" L3 Header-- Type: Tunnel (IPv6/IPv6)\n");
printf("+--------------------------------------\n");
printf("| IP Header Tunnel Layer 1: IPv6\n");
printf("+-------------------------------------\n");
printf(" L3 Header-- Type: IPv6\n");
printf("+--------------------------------------\n");
display_class_ipv6(buf, ptr);
printf("| Payload Len: 0x%h(%d)\n", buf.val[ptr++], buf.val[ptr++]);
printf("| Next Header: 0x%h\n", buf.val[ptr++]);
printf("| Hop Limit : 0x%h\n", buf.val[ptr++]);
printf("| IP SRC Address: %h%h:%h%h:%h%h:%h%h:%h%h:%h%h:%h%h:%h%h\n", buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++],
buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++],
buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] );
printf("| IP DST Address: %h%h:%h%h:%h%h:%h%h:%h%h:%h%h:%h%h:%h%h\n", buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++],
buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++],
buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] );
printf("| ESP SPI : %h.%h.%h.%h\n", buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] );
printf("| AH SPI : %h.%h.%h.%h\n", buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] );
printf("| ----------- \n|\n");
printf("| IP Header Tunnel Layer 2: IPv4:\n");
printf("| IP SRC Address: %h.%h.%h.%h\n", buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] );
printf("| IP DST Address: %h.%h.%h.%h\n", buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] );
} else if( tunneling_ipv6) {
printf("| ----------- \n|\n");
printf("| IP Header Tunnel Layer 2: IPv6:\n");
display_class_ipv6(buf, ptr);
printf("| Payload Len: 0x%h(%d)\n", buf.val[ptr++], buf.val[ptr++]);
printf("| Next Header: 0x%h\n", buf.val[ptr++]);
printf("| Hop Limit : 0x%h\n", buf.val[ptr++]);
printf("| IP SRC Address: %h%h:%h%h:%h%h:%h%h:%h%h:%h%h:%h%h:%h%h\n", buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++],
buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++],
buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] );
printf("| IP DST Address: %h%h:%h%h:%h%h:%h%h:%h%h:%h%h:%h%h:%h%h\n", buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++],
buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++],
buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] );
buf_shift = 11 + 4*(ipv4_header_length -5) ;
if( buf.val[ptr - buf_shift ] == UDP_PROTO) {
printf("+-------------------------------------\n");
printf(" L4 Header-- Type: UDP \n");
printf("+--------------------------------------\n");
printf("| UDP SRC Port: %h\n", {buf.val[ptr++], buf.val[ptr++]} );
printf("| UDP DST Port: %h\n", {buf.val[ptr++], buf.val[ptr++]} );
printf("| UDP LEN : %h\n", {buf.val[ptr++], buf.val[ptr++]} );
printf("| UDP Chksum : %h\n", {buf.val[ptr++], buf.val[ptr++]} );
token = { buf.val[ptr + 0], buf.val[ptr + 1] };
} else if( buf.val[ptr - buf_shift ] == TCP_PROTO) {
printf("+-------------------------------------\n");
printf(" L4 Header-- Type: TCP\n");
printf("+--------------------------------------\n");
printf("| TCP SRC Port: %h\n", {buf.val[ptr++], buf.val[ptr++]} );
printf("| TCP DST Port: %h\n", {buf.val[ptr++], buf.val[ptr++]} );
printf("| TCP Sequence #: %h\n", {buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++]} );
printf("| TCP ACK #: %h\n", {buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++]} );
flag_bit = buf.val[ptr++];
printf("| TCP Flag bits: URG:%b ACK:%b PSH:%b RST:%b SYN:%b FIN:%b\n", flag_bit[5], flag_bit[4], flag_bit[3], flag_bit[2], flag_bit[1], flag_bit[0]);
printf("| Window Size: %h\n", {buf.val[ptr++], buf.val[ptr++]});
printf("| TCP Checksum: %h\n", {buf.val[ptr++], buf.val[ptr++]});
if(cfg_reg[CFG_TCP_LEN] > 5 ) {
printf("| TCP Option : ");
for(n=0; n<(cfg_reg[CFG_TCP_LEN]-5); n++) {
printf("%h%h%h%h ", buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++]);
printf("+---------------\n");
token = { buf.val[ptr + 2], buf.val[ptr+3] };
} else if (esp_transp_ipv6) {
token = { buf.val[ptr], buf.val[ptr+1] };
} else if (ah_transp_ipv6) {
token = { buf.val[ptr], buf.val[ptr+1] };
token = { buf.val[ptr], buf.val[ptr+1] };
} /*end if((len>16'h0600 & len != CNTL_FRAME) || ((len == RARP_FRAME) &(len != CNTL_FRAME))) */
printf("\npg::display_buf Time: %0d\n",{get_time(HI),get_time(LO)});
printf("Token: %0d\n", token);
display_data(buf, ptr, hwlen-ptr-4 );
printf("CRC: %h\n", { buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } );
printf("\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n");
printf("--------------------------------------------------------------\n\n");
task pg::display_class(byte_array buf, var integer ptr) {
for(n=0;n<14;n++) printf("%h ", buf.val[ptr+n] );
if( {buf.val[ptr], buf.val[ptr+1]} < 16'h0600)
printf("| Length: %0d\n|\n", {buf.val[ptr++], buf.val[ptr++]} );
printf("| Type: %0h\n|\n", {buf.val[ptr++], buf.val[ptr++]} );
task pg::display_class_ipv6(byte_array buf, var integer ptr) {
for(n=0;n<10;n++) printf("%h ", buf.val[ptr+n] );
if( {buf.val[ptr], buf.val[ptr+1]} < 16'h0600)
printf("| Length: %0d\n|\n", {buf.val[ptr++], buf.val[ptr++]} );
printf("| Type: %0h\n|\n", {buf.val[ptr++], buf.val[ptr++]} );
task pg::display_data(byte_array buf, var integer ptr, integer len) {
printf("+---------------");
printf("\n| No Payload ...");
if( !(n % 16) ) printf("\n| %d: ",n);
printf("%h ", buf.val[ptr++]);
printf("\n+---------------\n");
task pg::display_id(bit [79:0] id) {
printf("+---------------\n");
printf("| Src port: %0d\n", id[79:75] );
printf("| Dst port: %0h\n", id[74:35] );
printf("| Order Type: %0h\n", id[34:33] );
printf("| Order Sequnce: %0d\n", id[32:27] );
printf("| Packet number: %0d\n", id[26:11] );
printf("| Data Type: %0d\n", id[10:8] );
printf("| Data Seed: %0d\n", id[7:0] );
printf("+---------------\n");
task pg::display_db(pack_db_entry pack_db ) {
printf("\n========== Display DB Entry %0d ========== \n",pack_db.gId);
printf("This entry is not allocated ...\n");
printf("\tframe.frame_type: %h\n",pack_db.frame.frame_type);
printf("\tframe.frame_class: %h\n",pack_db.frame.frame_class);
printf("\tframe.class_mask: %h\n",pack_db.frame.class_mask);
printf("\tframe.class_funct: %h\n",pack_db.frame.class_funct);
printf("\tframe.data_type: %h\n",pack_db.frame.data_type);
printf("\tframe.data_seed: %h\n",pack_db.frame.data_seed);
printf("\tframe.data_length: %h\n",pack_db.data_length);
printf("\tsrc_node.l2_addr: %h\n",pack_db.src_node.l2_addr);
printf("\tsrc_node.tci: %h\n",pack_db.src_node.tci);
printf("\tsrc_node.ip_addr: %h\n",pack_db.src_node.ip_addr);
printf("\tsrc_node.ipv6_addr: %h\n",pack_db.src_node.ipv6_addr);
printf("\tdst_node.l2_addr: %h\n",pack_db.dst_node.l2_addr);
printf("\tdst_node.tci: %h\n",pack_db.dst_node.tci);
printf("\tdst_node.ip_addr: %h\n",pack_db.dst_node.ip_addr);
printf("\tdst_node.ipv6_addr: %h\n",pack_db.dst_node.ipv6_addr);
printf("\ttup.src_tcp_udp_port: %h\n",pack_db.tup.src_tcp_udp_port);
printf("\ttup.dst_tcp_udp_port: %h\n",pack_db.tup.dst_tcp_udp_port);
printf("\trcv_isn: %0h\n",pack_db.rx_param.rcv_isn);
printf("\tlast_ackno: %0h\n",pack_db.rx_param.last_ackno);
printf("\tadv_isn: %0h\n",pack_db.tx_param.adv_isn);
printf("\tlast_seqno: %0h\n",pack_db.tx_param.last_seqno);
printf("\torg_port: %0d\n",pack_db.org_port);
printf("\torder_seq: %0d\n",pack_db.order_seq);
printf("\tpckt_num: %0d\n",pack_db.pckt_num);
printf("\toptions: %h\n",pack_db.options);
printf("========================================== \n\n");
task pg::display_flow(integer flow_id) {
printf("\n========== Display FLOW DB Entry %0d ========== \n",flow_id);
if(flow_db[flow_id] == null) {
printf("This entry is not allocated ...\n");
printf("\tframe.data_length: %h\n",flow_db[flow_id].data_length);
printf("\ttup.src_tcp_udp_port: %h\n",flow_db[flow_id].tup.src_tcp_udp_port);
printf("\ttup.dst_tcp_udp_port: %h\n",flow_db[flow_id].tup.dst_tcp_udp_port);
printf("\torg_port: %0d\n",flow_db[flow_id].org_port);
printf("\trcv_isn: %0h\n",flow_db[flow_id].rx_param.rcv_isn);
printf("\tlast_ackno: %0h\n",flow_db[flow_id].rx_param.last_ackno);
printf("\tadv_isn: %0h\n",flow_db[flow_id].tx_param.adv_isn);
printf("\tlast_seqno: %0h\n",flow_db[flow_id].tx_param.last_seqno);
printf("========================================== \n\n");
function bit[15:0] pg::partial_cksum(byte_array packet, integer start_offset, integer pkt_len) {
bit [16:0] chksum_tmp = 0;
for(i = start_offset; i < pkt_len;)
chksum_tmp = chksum_tmp + {packet.val[i],8'h0};
chksum_tmp = chksum_tmp + chksum_tmp[16];
chksum_tmp = chksum_tmp + {packet.val[i],packet.val[i+1]};
chksum_tmp = chksum_tmp + chksum_tmp[16];
partial_cksum = chksum_tmp[15:0];