Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / verif / env / common / vera / niu_ippktgen / pg_top_pp.vr
CommitLineData
86530b38
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: pg_top_pp.vr
4// Copyright (C) 1995-2007 Sun Microsystems, Inc. All Rights Reserved
5// 4150 Network Circle, Santa Clara, California 95054, U.S.A.
6//
7// * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8//
9// This program is free software; you can redistribute it and/or modify
10// it under the terms of the GNU General Public License as published by
11// the Free Software Foundation; version 2 of the License.
12//
13// This program is distributed in the hope that it will be useful,
14// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16// GNU General Public License for more details.
17//
18// You should have received a copy of the GNU General Public License
19// along with this program; if not, write to the Free Software
20// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21//
22// For the avoidance of doubt, and except that if any non-GPL license
23// choice is available it will apply instead, Sun elects to use only
24// the General Public License version 2 (GPLv2) at this time for any
25// software where a choice of GPL license versions is made
26// available with the language indicating that GPLv2 or any later version
27// may be used, or where a choice of which version of the GPL is applied is
28// otherwise unspecified.
29//
30// Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
31// CA 95054 USA or visit www.sun.com if you need additional information or
32// have any questions.
33//
34// ========== Copyright Header End ============================================
35#include <vera_defines.vrh>
36
37#include "pcg_defines.vri"
38#include "pcg_ports.vri"
39#include "pack_db.vrh"
40#include "flow_db.vrh"
41#include "flow_db_tasks.vrh"
42#include "mbox_class.vrh"
43#include "get_mbox_id.vrh"
44
45#include "cPgIf.vrh"
46
47#include "pcg_token.vrh"
48#include "cMesg.vrh"
49
50extern Mesg be_msg;
51
52
53// extern pack_db_entry pack_db[];
54extern flow_db_entry flow_db[];
55extern mbox_class mbox_id;
56extern integer quiet_on;
57extern class pg;
58extern pg ptr_to_first_pg;
59extern pg pack_gen[16];
60
61extern "C" task InitpgSeed(integer seed);
62extern "C" function bit[31:0] pgRand();
63
64class CpgRandom {
65
66 bit[31:0] seed;
67
68 task new(integer i) {
69 InitpgSeed(i);
70 }
71 function bit[7:0] nextdata() {
72 bit [31:0] d;
73 d = pgRand();
74 nextdata = d[7:0];
75 }
76
77}
78
79class pg {
80 local integer warning_count=0;
81 local integer pg_done =0;
82 local integer error_count=0;
83 bit [3:0] port_type;
84 local bit [63:0] clock_counter;
85 local integer my_port;
86 l3_class_desc l3_class[61];
87 l3_class_mask l3_mask[40];
88 local integer pckt_num= -1;
89 local integer new_flow=0;
90 local integer order_seq=0;
91 local integer mb_q;
92 local integer pkt_gen_sync;
93 local integer queue_lock;
94 static bit[19:0] pg_used_ports=0;
95 bit [31:0] cfg_reg[CFG_LAST_ENTRY];
96 local bit [15:0] ifedx_control;
97 local bit [63:0] last_tx_time;
98 local bit [63:0] prev_current_time=0; //hummer
99 local integer port_speed ;
100 local integer mac_speed ;
101 // local event pkt_gen_lock ;
102 integer pkt_gen_lock;
103 local integer tx_done=0;
104 local integer wait_send_fake;
105 local integer rxdv_set=0;
106 local event pg_random_event;
107
108 integer tx_err_start=-1;
109 integer tx_err_len;
110
111 integer debug_xgmii = 0;
112 integer debug_gmii = 0;
113 integer debug_mii = 0;
114 integer debug_fa = 0;
115 integer debug_mii_rx = 0;
116 integer debug_mii_tx = 0;
117 integer debug_xgmii_tx = 1;
118 integer debug_xgmii_rx = 0;
119 integer debug_gmii_rx = 0;
120 integer debug_rx = 0;
121 integer debug_dg = 0;
122 integer debug_db_in = 0;
123 integer debug_db_out = 0;
124 integer debug_checker = 0;
125 integer debug_out_token = 1;
126
127 task config(integer what, bit [31:0] data) ;
128 task print_warn() ;
129 task print_err() ;
130 task gen_buf( pack_db_entry pack_db, byte_array buf, var integer ptr ) ;
131 function byte_array new_gen_buf(pack_db_entry pack_db, var bit[31:0] pkt_fields[*]);
132 task pkt_gen( flow_desc flow, integer data_length, integer ttl, var CpgToken pgToken, ( bit[63:0] options=0) );
133 task pkt_auto_tx() ;
134 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);
135 task display_buf( byte_array buf, integer hwlen, (integer ifedx=0)) ;
136 task display_class(byte_array buf, var integer ptr) ;
137 task display_class_ipv6(byte_array buf, var integer ptr) ;
138 task display_data(byte_array buf, var integer ptr, integer len) ;
139 task display_id(bit [79:0] id) ;
140 task display_db(pack_db_entry pack_db) ;
141 task display_flow(integer flow_id) ;
142 task send_packet(bit [3:0] ptype, byte_array buf, integer len, bit [63:0] options) ;
143 task assert_col_tx (mii_def port_bind, bit [63:0] options) ;
144 task assert_mii_err (mii_def port_bind ) ;
145 task send_packet_mii (mii_def port_bind, bit [3:0] ptype, byte_array buf, integer len, bit [63:0] options) ;
146 task assert_gmii_err (gmii_def port_bind) ;
147 task send_packet_gmii (gmii_def port_bind, bit [3:0] ptype, byte_array buf, integer len, bit [63:0] options) ;
148 task assert_xgmii_err (xgmii_def port_bind) ;
149 task send_packet_xgmii (xgmii_def port_bind,bit [3:0] ptype, byte_array buf, integer len, bit [63:0] options) ;
150 task wait_clk(integer count) ;
151 task count_clock() ;
152 task wait_tx_clk(integer count) ;
153 task wait_tx_clk_if ( mii_def port_bind, integer count) ;
154 task wait_rx_clk(integer count) ;
155 task wait_rx_clk_if ( mii_def port_bind, integer count) ;
156 task config_tx (mii_def port_bind, integer mac_speed ) ;
157 task status() ;
158 task new(integer my_porti, (bit [3:0] ptype=0)) ;
159 task build_frame (integer itoken, pack_db_entry pack_db, byte_array buf, var integer len,(integer header_id=-1),(integer new_crc=0));
160
161 function bit [15:0] ipv4_cksum( byte_array m, integer len) ;
162 function bit [15:0] ip_datagram_chksum(byte_array d, integer start, integer len);
163 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 );
164 function bit [31:0] crc_gen(byte_array p, integer start, integer len) ;
165 local function bit [31:0] crc32_add(bit [7:0] data, bit [31:0] crc) ;
166 function integer check_option(bit [63:0] option, bit [63:0] flag) ;
167 function bit [7:0] class_mask(integer funct, bit[7:0] a, bit[7:0] b) ;
168
169 function bit[15:0] partial_cksum(byte_array packet, integer start_offset, integer pkt_len);
170
171}
172
173
174
175task pg::gen_buf( pack_db_entry pack_db, byte_array buf, var integer ptr ) {
176
177 integer len = -1;
178 integer n;
179 integer he;
180 integer flow_id;
181 integer ipv4_ptr;
182 integer ipv6_ptr;
183
184 integer tcp_hdr_start;
185 integer udp_hdr_start;
186 integer ip_hdr_start;
187 integer extra_tcp_hdr=0;
188 integer tcp_seg_len;
189
190 bit [15:0] tcp_length;
191 bit [15:0] udp_length;
192 bit [15:0] ip_length;
193 bit [15:0] ipv6_length;
194 bit [15:0] l2_length;
195 bit [31:0] tmp32, mask;
196 bit [15:0] tmp16 ;
197 bit [15:0] tmp16_ipck ;
198 bit [15:0] tmp16_tcpck ;
199 bit [15:0] tmp16_udpck ;
200 bit [15:0] tmp16_ipdck ;
201 bit [31:0] isn_tmp;
202 bit [47:0] da_tmp;
203 bit [95:0] tcp_psu_hdr;
204 bit [95:0] udp_psu_hdr;
205 bit [15:0] ipv4_hdr[10];
206 integer tagged = 0;
207 bit [32:0] addr;
208 bit dv;
209 integer header_len_w_options;
210
211// List of inputs to this function passed through a struct
212 bit[47:0] l2_da,l2_sa;
213 bit [4:0] frame_type;
214 integer tpid;
215 bit [15:0] tci;
216 integer frame_class;
217 integer data_length;
218 integer class_funct;
219 integer frame_class_mask;
220 integer header_length;
221 integer ttl;
222 bit [31:0] spi;
223 bit [7:0] nxthdr;
224 bit [7:0] tos;
225 integer type;
226 bit [128:0] src_ipv6_addr,dst_ipv6_addr;
227 bit [31:0] src_ip_addr,dst_ip_addr;
228 bit [15:0] src_port,dst_port;
229 bit [5:0] tcp_flags;
230 bit [31:0] rcv_isn;
231 bit [31:0] last_seqno;
232 integer data_type;
233 integer data_seed;
234 integer gId;
235 integer chk_sum_location;
236 bit [63:0] options;
237 bit[15:0] llc_length;
238 integer LLC_HACK= 1;
239
240 // Assign the inputs here TMP only
241 flow_id = pack_db.flow.flow_no;
242 l2_da = pack_db.dst_node.l2_addr;
243 l2_sa = pack_db.src_node.l2_addr;
244 frame_type = pack_db.frame.frame_type;
245 tpid = pack_db.frame.tpid;
246 tci = pack_db.src_node.tci;
247 frame_class = pack_db.frame.frame_class;
248 data_length = pack_db.data_length;
249 class_funct = pack_db.frame.class_funct;
250 frame_class_mask = pack_db.frame.class_mask;
251
252 header_length = pack_db.frame.header_length ;
253 ttl = pack_db.ttl;
254 spi = pack_db.src_node.spi;
255 nxthdr = pack_db.src_node.nxthdr;
256 tos = pack_db.src_node.tos;
257 type = pack_db.frame.type;
258 src_ipv6_addr = pack_db.src_node.ipv6_addr;
259 dst_ipv6_addr = pack_db.dst_node.ipv6_addr;
260 src_ip_addr = pack_db.src_node.ip_addr;
261 dst_ip_addr = pack_db.dst_node.ip_addr;
262 src_port = pack_db.tup.src_tcp_udp_port;
263 dst_port = pack_db.tup.dst_tcp_udp_port;
264 tcp_flags = pack_db.fl_state.tcp_flags;
265 rcv_isn = pack_db.rx_param.rcv_isn;
266 //last_seqno = flow_db[flow_id].tx_param.last_seqno;
267
268data_type = pack_db.frame.data_type;
269data_seed = pack_db.frame.data_seed;
270
271 gId = pack_db.gId;
272 options = pack_db.options;
273
274 // DONE Assign the inputs here
275
276
277
278 ptr=0;
279 // L2 address
280 '{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++],
281 buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } = l2_da;
282 '{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++],
283 buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } = l2_sa;
284
285
286 if( frame_type[2] ) { // 802.1Q 18 bytes long header
287 tagged = 1;
288 if( tpid != -1) //
289 '{ buf.val[ptr++], buf.val[ptr++]} = tpid;
290 else
291 '{ buf.val[ptr++], buf.val[ptr++]} = TPID_8021Q;
292 '{ buf.val[ptr++], buf.val[ptr++]} = tci;
293 }
294
295
296
297
298 if((frame_type[1] == 1) || (frame_type[4] == 1)) { // include ip header or tunneling options
299 if( frame_type[0] == 1) { // if LLC SNAP IP Header
300 len = ptr;
301 ptr = ptr+2;
302 if( check_option( pack_db.options, O_CUSTOM_LS) ) {
303 tmp32 = cfg_reg[CFG_CUST_LS];
304 '{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++]} = tmp32[23:0];
305 } else
306 '{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++]} = LLC_SNAP;
307 buf.val[ptr++] = H_UNDEF;
308 buf.val[ptr++] = H_UNDEF;
309 buf.val[ptr++] = H_UNDEF;
310 } else {
311 len = - 1;
312 }
313
314 if( frame_type[3] == 1 && frame_class < CL_TCP_OPT ) // IPV6 Header
315 frame_class += DELTA;
316
317 if( frame_type[3] == 0 ) { // IPV4 Header
318
319 if ( (frame_type[0] == 1 ) && (frame_type[2] == 1 )) { // LLC_SNAP and 802.1Q Tagged
320 l2_length = 26;
321 } else if (frame_type[2] == 1 ) { // ONLY 802.1Q Tagged
322 l2_length = 18;
323 } else if (frame_type[0] == 1 ) { // ONLY LLC_SNAP
324 l2_length = 22;
325 } else{ // NONE of the above
326 l2_length = 14;
327 }
328
329 ip_length = data_length -4 -(l2_length) ;
330
331
332
333 pack_db.ipp.ip_hdr_len = ip_length;
334 printf("pg::gen_buf The IP length is %0h , ptr - %d \n", ip_length,ptr);
335
336 for( n=0; n<2; n++) {
337 buf.val[ptr++] = class_mask( class_funct, l3_class[frame_class].val[n], l3_mask[frame_class_mask].val[n] );
338 }
339 // add header option field here
340 buf.val[ptr] = class_mask( class_funct, l3_class[frame_class].val[2],
341 l3_mask[frame_class_mask].val[2] );
342 if((buf.val[ptr] & 8'h40) == 8'h40) { // if IPV4
343 buf.val[ptr++] = 8'h40 | ( header_length & 4'hf) ;
344 }
345
346 buf.val[ptr++] = tos;
347 buf.val[ptr++] = ip_length[15:8];
348 buf.val[ptr++] = ip_length[7:0];
349
350 for( n=6; n<12; n++) {
351 // Fill in rest of the header bytes
352 buf.val[ptr++] = class_mask( class_funct, l3_class[frame_class].val[n],
353 l3_mask[frame_class_mask].val[n] );
354 }
355
356 // This appears to be programmed by the user to override the automatically generated type field
357 if(type != -1) // This should be moved up? ....
358 '{buf.val[ptr-14], buf.val[ptr-13]} = type;
359
360 // This should be moved up? ....
361 if(ttl != -1) buf.val[ptr-2] = ttl;
362
363
364
365
366 '{buf.val[ptr++],buf.val[ptr++]} = 16'h0000; // 0s for header checksum
367
368 '{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } = src_ip_addr;
369 '{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } = dst_ip_addr;
370
371 // Add options here
372
373 header_len_w_options = ( (buf.val[ptr -20 /*14*/ ] & 8'h40 )== 8'h40) ? header_length : 0;
374 printf(" DEBUG-- header_len_w_options - %d buf value - %x \n",header_len_w_options,buf.val[ptr -20 /*14*/ ] );
375
376 for(n=0;n< (4*header_len_w_options - 20); n++) {
377 buf.val[ptr++] = 8'ha0 + n;
378 // printf(" DEBUG-- ptr - %d val - %x \n",ptr,buf.val[ptr -1]);
379 }
380
381 tmp16_ipck = ipv4_cksum(buf,ptr);
382
383
384 // Write back computed checksum
385 '{buf.val[ptr-10 - (4*header_len_w_options - 20) ],buf.val[ptr-9 - (4*header_len_w_options - 20) ]} = tmp16_ipck;
386
387 if( frame_class == CL_IP_SEC_ESP) {
388 '{buf.val[ptr++],buf.val[ptr++],buf.val[ptr++],buf.val[ptr++]} = spi;
389 '{buf.val[ptr++],buf.val[ptr++]} = 16'h0000;
390 '{buf.val[ptr++],buf.val[ptr++]} = 16'h0000;
391 '{buf.val[ptr++],buf.val[ptr++]} = 16'h0000;
392 '{buf.val[ptr++],buf.val[ptr++]} = 16'h0000;
393 }
394 if( frame_class == CL_IP_SEC_AH) {
395 //buf.val[ptr++] = 8'h06;//Assumes TCP
396 buf.val[ptr++] = nxthdr;
397 buf.val[ptr++] = 8'h03;//LenHdr-2 (32bit Words)
398 '{buf.val[ptr++],buf.val[ptr++]} = 16'h0000;
399 '{buf.val[ptr++],buf.val[ptr++],buf.val[ptr++],buf.val[ptr++]} = spi;
400 '{buf.val[ptr++],buf.val[ptr++]} = 16'h0000;
401 '{buf.val[ptr++],buf.val[ptr++]} = 16'h0000;
402 }
403 } // endif IPV4 packet
404 else if ( frame_type[3] == 1 ) { // IPV6 Packet
405 // printf("pcg_fa.vr: Bulding IPv6 Packet \n");
406
407 if( (frame_type[2] == 1 ) && (frame_type[0] == 1)) {
408 l2_length = 26;
409 } else if (frame_type[2] == 1 ) {
410 l2_length = 18;
411 } else if (frame_type[0] == 1 ) {
412 l2_length = 22;
413 } else{
414 l2_length = 14;
415 }
416 ipv6_length = data_length - 40 -4 -(l2_length);
417
418 pack_db.ipp.ip_hdr_len = ipv6_length;
419
420 printf("pg::gen_buf The val of ip_length is %0d\n",ipv6_length);
421
422 for( n=0; n<2; n++)
423 buf.val[ptr++] = class_mask( class_funct,
424 l3_class[frame_class].val[n],
425 l3_mask[frame_class_mask].val[n] );
426
427 buf.val[ptr++] = {4'h6,tos[7:4]};
428 buf.val[ptr++] = {tos[3:0],4'h0};
429
430 for( n=4; n<6; n++)
431 buf.val[ptr++] = class_mask( class_funct,
432 l3_class[frame_class].val[n],
433 l3_mask[frame_class_mask].val[n] );
434
435
436
437 buf.val[ptr++] = ipv6_length[15:8];
438 buf.val[ptr++] = ipv6_length[7:0];
439
440 for( n=8; n<10; n++)
441 buf.val[ptr++] = class_mask( class_funct,
442 l3_class[frame_class].val[n],
443 l3_mask[frame_class_mask].val[n] );
444
445 if(type != -1)
446 '{buf.val[ptr-10], buf.val[ptr-9]} = type;
447
448
449 if(ttl != -1) buf.val[ptr-1] = ttl;
450
451
452 '{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++],
453 buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++],
454 buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++],
455 buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } = src_ipv6_addr;
456
457 '{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++],
458 buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++],
459 buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++],
460 buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } = dst_ipv6_addr;
461
462 if( frame_class == CL_IP_V6_SEC_ESP) {
463
464 '{buf.val[ptr++],buf.val[ptr++],buf.val[ptr++],buf.val[ptr++]} = spi;
465
466 '{buf.val[ptr++],buf.val[ptr++]} = 16'h0000;
467 '{buf.val[ptr++],buf.val[ptr++]} = 16'h0000;
468 '{buf.val[ptr++],buf.val[ptr++]} = 16'h0000;
469 '{buf.val[ptr++],buf.val[ptr++]} = 16'h0000;
470 }
471
472 if( frame_class == CL_IP_V6_SEC_AH) {
473
474 buf.val[ptr++] = 8'h06;//Assumes TCP
475 buf.val[ptr++] = 8'h03;//LenHdr-2 (32bit Words)
476 '{buf.val[ptr++],buf.val[ptr++]} = 16'h0000;
477 '{buf.val[ptr++],buf.val[ptr++],buf.val[ptr++],buf.val[ptr++]} = spi;
478
479 '{buf.val[ptr++],buf.val[ptr++]} = 16'h0000;
480 '{buf.val[ptr++],buf.val[ptr++]} = 16'h0000;
481 }
482 } // endif IPV6
483
484 printf("pg::gen_buf : Frame_class: %d frame_type - %x \n" , frame_class,frame_type );
485
486 if( frame_class == CL_UDP | frame_class == CL_UDP_OPT |
487 frame_class == CL_UDP_FRAG | frame_class == CL_UDP_IP_V6 |
488 frame_class == CL_UDP_OPT_IP_V6 | frame_class == CL_UDP_FRAG_IP_V6 ) {
489
490
491 if ( frame_type[3] == 1 ) { // IPV6
492 udp_length = data_length - 40 -4 -(l2_length); }
493 if( frame_type[3] == 0 ) { // IPV4
494 udp_length = data_length - (4*header_len_w_options) -4 -(l2_length); // printf("DEBUG udp length - %d \n",udp_length);
495 }
496
497 udp_psu_hdr = {src_ip_addr, dst_ip_addr, 8'h00,8'h17,udp_length};
498 udp_hdr_start = ptr ;
499 pack_db.psu_hdr= (udp_psu_hdr);
500
501 '{ buf.val[ptr++], buf.val[ptr++] } = src_port;
502 '{ buf.val[ptr++], buf.val[ptr++] } = dst_port;
503
504
505 buf.val[ptr++] = udp_length[15:8];
506 buf.val[ptr++] = udp_length[7:0];
507
508 '{ buf.val[ptr++], buf.val[ptr++] } = 16'h00;
509
510 }/*endif CL_UDP*/
511 else if ( frame_class == CL_TCP | frame_class == CL_TCP_OPT |
512 frame_class == CL_TCP_FRAG | frame_class == CL_TCP_IP_V6 |
513 frame_class == CL_TCP_OPT_IP_V6 | frame_class == CL_TCP_FRAG_IP_V6 ) {
514 //printf("pcg_fa.vr: Adding TCP Header \n");
515
516 tcp_psu_hdr = {src_ip_addr, dst_ip_addr, 8'h00,8'h06,16'h0000};
517 pack_db.psu_hdr= (tcp_psu_hdr);
518 tcp_hdr_start = ptr ;
519
520 '{ buf.val[ptr++], buf.val[ptr++] } = src_port;
521 '{ buf.val[ptr++], buf.val[ptr++] } = dst_port;
522
523 if( tcp_flags == 2'h2 ) {
524 '{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } = rcv_isn;
525 } else {
526 '{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } = flow_db[flow_id].tx_param.last_seqno;
527 flow_db[flow_id].rx_param.rcv_isn = flow_db[flow_id].tx_param.last_seqno;
528 }
529
530 if(frame_class != CL_TCP_OPT & frame_class != CL_TCP_OPT_IP_V6)
531 { cfg_reg[CFG_TCP_LEN] = 4'b0101; }
532 '{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } = cfg_reg[CFG_TCP_ACK];
533 tmp32[15:0] = {cfg_reg[CFG_TCP_LEN], 6'b000000, tcp_flags} ;
534 '{ buf.val[ptr++], buf.val[ptr++] } = tmp32[15:0];
535 tmp32 = cfg_reg[CFG_TCP_WIN];
536 '{ buf.val[ptr++], buf.val[ptr++] } = tmp32[15:0];
537
538 '{ buf.val[ptr++], buf.val[ptr++] } = 16'h00;
539 tmp32 = cfg_reg[CFG_TCP_URG];
540 '{ buf.val[ptr++], buf.val[ptr++] } = tmp32[15:0];
541
542 //TCP option
543 if ( (cfg_reg[CFG_TCP_LEN] ) > 5 ) {
544 extra_tcp_hdr = (cfg_reg[CFG_TCP_LEN] - 5 ) * 4;
545 pack_db.mac.extra_tcp_hdr = extra_tcp_hdr;
546 for ( n =0; n< extra_tcp_hdr; n++) {
547 buf.val[ptr++] = 8'ha5;
548 }
549 } else {
550 extra_tcp_hdr = 0;
551 pack_db.mac.extra_tcp_hdr = extra_tcp_hdr;
552 }
553 } // endif CL_TCP*
554 } // endif include ip header or tunneling option
555 else {
556 printf("pg::gen_buf : No L3 header selected\n");
557 if( frame_type[0] == 1) { // LLC_SNAP
558 len = ptr;
559 ptr = ptr+2;
560 if( check_option( pack_db.options, O_CUSTOM_LS) ) {
561 tmp32 = cfg_reg[CFG_CUST_LS];
562 '{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++]} = tmp32[23:0];
563 } else
564 '{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++]} = LLC_SNAP;
565 buf.val[ptr++] = H_UNDEF;
566 buf.val[ptr++] = H_UNDEF;
567 buf.val[ptr++] = H_UNDEF;
568 '{buf.val[ptr++],buf.val[ptr++]} = 16'h0008;
569 } else {
570 len = ptr;
571 ptr = ptr+2;
572 }
573 } // endif else of include ip header
574
575 he = ptr-1; // header length
576 tcp_length = data_length -he -4;
577 tcp_seg_len = data_length - ptr - 4;
578
579 if(data_type != DAT_FC_PAUSE)
580 '{buf.val[ptr++], buf.val[ptr++]} = gId;
581
582 if(LLC_HACK & ( (pack_db.frame.frame_type== 5'h3 )| (pack_db.frame.frame_type== 5'h7) )) {
583 printf("gen_buf LLC_HACK!!! data_len - %d \n",pack_db.data_length);
584 if(pack_db.flow.frame.frame_type== 5'h3) {
585 llc_length = pack_db.data_length - 4/*CRC*/ - 12/*L2HEADERS*/ -2/*Type/Length*/ ;
586 buf.val[12] = llc_length[15:8];
587 buf.val[13] = llc_length[7:0];
588 }
589 else {
590 llc_length = pack_db.data_length - 4/*CRC*/ - 12/*L2HEADERS*/ -4/*VLAN ID*/ -2/*Type/Length*/ ;
591 buf.val[16] = llc_length[15:8];
592 buf.val[17] = llc_length[7:0];
593 }
594
595 }
596
597
598
599
600 /* Generate data payload */
601 data_gen(data_type, data_seed, data_length, buf, ptr, pack_db.options, this, tagged, INTER_FEDX);
602 // printf("DEBUG--- After data_gen len - %d \n",len);
603 // printf("DEBUG---type - %d %d %d \n",type,ptr, he);
604
605 // Add L2 Length here
606 if( len > 0 ) {
607 if( check_option( pack_db.options, O_FRM_LEN_ERR1) )
608 '{buf.val[len], buf.val[len+1] } = cfg_reg[CFG_FRM_LEN];
609 else {
610 if(type == -1) {
611 '{buf.val[len], buf.val[len+1] } = ptr - (he+1);
612 } else
613 '{buf.val[len], buf.val[len+1] } = type;
614 }
615 }
616
617 if( frame_class == CL_TCP | frame_class == CL_TCP_OPT |
618 frame_class == CL_TCP_FRAG | frame_class == CL_TCP_IP_V6 |
619 frame_class == CL_TCP_OPT_IP_V6 | frame_class == CL_TCP_FRAG_IP_V6 ) {
620
621 // Calculate TCP checksum
622 flow_db[flow_id].data_length = tcp_seg_len;
623 flow_db[flow_id].tx_param.last_seqno = (flow_db[flow_id].rx_param.rcv_isn) + flow_db[flow_id].data_length;
624
625 chk_sum_location = he-extra_tcp_hdr-3;
626
627 tmp16_tcpck = tcp_chksum(pack_db,buf,tcp_hdr_start,ptr,1, chk_sum_location );
628 printf("gen_buf-- tcp_chksum - %x tcp_hdr_start - %d chk_sum_location - %d \n",tmp16_tcpck,tcp_hdr_start,chk_sum_location);
629
630 if( check_option( pack_db.options, O_TCPCKSUM_ERR) ){
631 tmp16_tcpck = tmp16_tcpck ^ cfg_reg[CFG_TCPCKSUM_MASK];
632 }
633 '{buf.val[he-extra_tcp_hdr-3],buf.val[he-extra_tcp_hdr-2]} = tmp16_tcpck;
634 pack_db.ipp.tcp_cksum = tmp16_tcpck;
635 } // C
636
637 if(frame_class == CL_UDP | frame_class == CL_UDP_OPT |
638 frame_class == CL_UDP_FRAG | frame_class == CL_UDP_IP_V6 |
639 frame_class == CL_UDP_OPT_IP_V6 | frame_class == CL_UDP_FRAG_IP_V6 ) {
640 // Calculate UDP checksum
641
642 chk_sum_location = he -1;
643 tmp16_udpck = tcp_chksum(pack_db,buf,udp_hdr_start,ptr,0,chk_sum_location);
644 printf("gen_buf-- udp_chksum - %x udp_hdr_start - %d chk_sum_location - %d \n",tmp16_udpck,udp_hdr_start,chk_sum_location);
645
646 '{buf.val[he-1],buf.val[he-0]} = tmp16_udpck;
647 }
648
649 ip_hdr_start = l2_length ;
650
651 if (frame_type[1] == 1) { // IPV4
652 tmp16_ipdck =ip_datagram_chksum(buf,ip_hdr_start,ptr);
653 pack_db.ipp.ip_datagram_cksum = tmp16_ipdck;
654 }
655
656 pack_db.add_header(buf,0,he);
657
658 if(LLC_HACK & ( (pack_db.frame.frame_type== 5'h3 )| (pack_db.frame.frame_type== 5'h7) )) {
659 printf("LLC_HACK!!! \n");
660 if(pack_db.flow.frame.frame_type== 5'h3) {
661 llc_length = pack_db.data_length - 4/*CRC*/ - 12/*L2HEADERS*/ -2/*Type/Length*/ ;
662 buf.val[12] = llc_length[15:8];
663 buf.val[13] = llc_length[7:0];
664 }
665 else {
666 llc_length = pack_db.data_length - 4/*CRC*/ - 12/*L2HEADERS*/ -4/*VLAN ID*/ -2/*Type/Length*/ ;
667 buf.val[16] = llc_length[15:8];
668 buf.val[17] = llc_length[7:0];
669 }
670 }
671
672 tmp32 = crc_gen(buf, 0, ptr);
673
674 if( check_option( pack_db.options, O_CRC_ERR) ) tmp32 = tmp32 ^ cfg_reg[CFG_CRC_MASK];
675 '{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } = tmp32;
676
677 pack_db.pack_crc = tmp32;
678 pack_db.frame_len = ptr;
679 // printf(" end of gen_buf - ptr - %d \n",ptr);
680}
681
682
683
684function bit [15:0] pg::ipv4_cksum( byte_array m, integer len){
685
686 integer i,j;
687 bit [15:0] tmp[];
688 bit [31:0] cksum;
689
690 j = len -20;
691 cksum = 0;
692
693 printf ("pg::ipv4_cksum: The val of len is %d\n",len);
694 for ( i=j; i< (j+20); i=i+2) {
695 tmp[i] = {m.val[i], m.val[(i+1)]};
696 // printf("The val of buffer is %0h\n",tmp[i]);
697 cksum = cksum + tmp[i];
698
699 if (cksum[16] ==1) {
700 cksum = cksum[15:0] + 1;
701 }
702 }
703
704
705 ipv4_cksum = ~cksum;
706 printf(" pg::ipv4_cksum: chksum - %x \n",ipv4_cksum);
707
708}
709
710function bit [15:0] pg::ip_datagram_chksum( byte_array d, \
711 integer start, integer len){
712
713 integer i,j,k;
714 bit [15:0] tmp[];
715 bit [31:0] ipsum;
716 integer ip_len;
717 integer pad;
718
719 ip_len = len - start;
720
721 ipsum = 0;
722
723
724 printf ("pg::ip_datagram_chksum: The val of ip hdr start and len is %0d and %0d\n", start,len);
725
726 if (ip_len %2 != 0) {
727 pad =1;
728 }else {
729 pad = 0;
730 }
731
732 for (i=start;i<len+pad;i=i+2) {
733 d.val[len] = 0;
734 tmp[i] = {d.val[i],d.val[i+1]};
735 ipsum = ipsum + tmp[i];
736 //printf("The val of buffer is %0h\n",tmp[i]);
737 //printf("The val of sum of payld is is %0h\n",ipsum);
738
739 if (ipsum[16] ==1) {
740 ipsum = ipsum[15:0] + 1;
741 }
742 }
743 ip_datagram_chksum = ~ipsum;
744
745 printf("pg::ip_datagram_chksum: The val of IP Datagram Checksum is %0h \n",ip_datagram_chksum);
746
747}
748
749
750function 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 ){
751
752 integer i,j,k;
753 bit [15:0] tmp[];
754 bit [15:0] tmp0[];
755 bit [15:0] tmp1[];
756 bit [15:0] sum_hdr;
757 bit [31:0] ip_src_sum;
758 bit [31:0] ip_dst_sum;
759 bit [127:0] ipv6_src;
760 bit [127:0] ipv6_dst;
761 bit [31:0] tcp_proto_sum;
762 bit [95:0] psu_hdr;
763 bit [31:0] sum;
764 integer tcp_len;
765 integer pad;
766
767 integer partial_chksum;
768
769
770 partial_chksum = pack_db.flow.partial_chksum;
771
772 if(partial_chksum) {
773 d.val[chk_sum_location] = pack_db.flow.psu_hdr[0];
774 d.val[chk_sum_location + 1] = pack_db.flow.psu_hdr[1];
775 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]);
776 sum = partial_cksum( d,start,len );
777 printf(" pg::tcp_chksum partial checksum - %x \n",sum);
778 } else {
779
780 tcp_len = len - start;
781 sum = 0;
782 printf("pg::tcp_chksum start - %d len - %d \n",start,len);
783
784 if (pack_db.frame.frame_type[3] == 0){
785 psu_hdr = {pack_db.src_node.ip_addr, pack_db.dst_node.ip_addr, 8'h00,8'h06,16'h0000};
786 // printf("The val of psu header is %0h\n",psu_hdr);
787 }
788 if (tcp_len %2 != 0) {
789 pad =1;
790 }else {
791 pad = 0;
792 }
793
794 for (i=start;i<len+pad;i=i+2) {
795 d.val[len] = 0;
796 tmp[i] = {d.val[i],d.val[i+1]};
797 sum = sum + tmp[i];
798 if (sum[16] ==1) {
799 sum = sum[15:0] + 1;
800 }
801 }
802 if (pack_db.frame.frame_type[3] == 0){
803 ip_src_sum = pack_db.src_node.ip_addr[15:0] + pack_db.src_node.ip_addr[31:16];
804 if (ip_src_sum[16] ==1) {
805 ip_src_sum = ip_src_sum[15:0] + 1;
806 }
807 sum = sum + ip_src_sum;
808 if (sum[16] ==1) {
809 sum = sum[15:0] + 1;
810 }
811 ip_dst_sum = pack_db.dst_node.ip_addr[15:0] + pack_db.dst_node.ip_addr[31:16];
812 if (ip_dst_sum[16] ==1) {
813 ip_dst_sum = ip_dst_sum[15:0] + 1;
814 }
815 sum = sum + ip_dst_sum;
816 if (sum[16] ==1) {
817 sum = sum[15:0] + 1;
818 }
819 if(pkt_type == 1)
820 {
821 tcp_proto_sum = 16'h0006 + tcp_len;
822 }
823 else
824 {
825 tcp_proto_sum = 16'h0011 + tcp_len;
826 }
827
828 if (tcp_proto_sum[16] ==1) {
829 tcp_proto_sum = tcp_proto_sum[15:0] + 1;
830 }
831
832 sum = sum + tcp_proto_sum;
833
834 if (sum[16] ==1) {
835 sum = sum[15:0] + 1;
836
837 }
838 //printf("The val of sum of payld & tcp_proto is is %0h\n",sum);
839
840 }
841
842 if (pack_db.frame.frame_type[3] == 1){
843
844
845 ipv6_src = pack_db.src_node.ipv6_addr;
846 ipv6_dst = pack_db.dst_node.ipv6_addr;
847
848 //printf("The val of ipv6 src is %0h\n", ipv6_src );
849
850
851
852 j = 127;
853
854 for ( k= 0 ; k < 8; k++ ) {
855 tmp0[k] = {ipv6_src[j:j-7], ipv6_src[j-8:j-15]};
856 //printf("The val of src buffer is %0h\n",tmp0[k]);
857 sum = sum + tmp0[k];
858 if (sum[16] ==1) {
859 sum = sum[15:0] + 1;
860
861 }
862 j = j -16 ;
863
864 }
865
866 //printf("The val of sum at src is %0h\n", sum);
867 j = 127;
868
869 for ( k= 0 ; k < 8; k++ ) {
870 tmp1[k] = {ipv6_dst[j:j-7], ipv6_dst[j-8:j-15]};
871 //printf("The val of dst buffer is %0h\n",tmp1[k]);
872 sum = sum + tmp1[k];
873 if (sum[16] ==1) {
874 sum = sum[15:0] + 1;
875
876 }
877
878 j = j -16 ;
879 }
880
881 //printf("The val of sum at dst is %0h\n", sum);
882
883
884 if (pkt_type == 1) {
885 tcp_proto_sum = 16'h0006 + tcp_len;
886 } else {
887 tcp_proto_sum = 16'h0011 + tcp_len;
888 }
889
890
891 if (tcp_proto_sum[16] ==1) {
892 tcp_proto_sum = tcp_proto_sum[15:0] + 1;
893 }
894
895 sum = sum + tcp_proto_sum;
896
897 if (sum[16] ==1) {
898 sum = sum[15:0] + 1;
899 }
900 }
901
902
903 // printf("The val of start and len are %0d and %0d\n",start,len);
904
905 // printf("The FINAL val of sum is %0h\n", sum);
906
907 }
908 tcp_chksum = ~sum;
909
910}
911
912task pg::pkt_gen( flow_desc flow, integer data_length, integer ttl, var CpgToken pgToken,
913 (bit[63:0] options=0) ){
914
915 integer time_out = 0;
916
917 integer current_flow_num;
918 integer flow_id;
919 pack_db_entry pack_db;
920 integer id;
921 integer token;
922 byte_array tmpbuf;
923 printf("pg::pkt_gen called Time - %d \n", {get_time(HI),get_time(LO)});
924 semaphore_get(WAIT,pkt_gen_lock,1);
925 printf("pg::pkt_gen after sem called Time - %d \n", {get_time(HI),get_time(LO)});
926
927 // sync(ALL,pkt_gen_lock);
928 // trigger(OFF,pkt_gen_lock);
929
930 current_flow_num = flow.flow_no;
931
932
933
934 if(my_port > 15 ) {
935 printf("pg::pkt_gen: WARNING: PG: Port %0d is invalid (only used to satisfy fflp testsuite).\n",my_port);
936 printf("pg::pkt_gen: No action is taken.\n");
937 return;
938 }
939
940 pckt_num++;
941 token = pckt_num; // TOADS
942
943 if (flow.fl_state.tcp_flags == 6'h02)
944 new_flow++;
945
946
947 case({ check_option(options, O_ORDER_START),
948 check_option(options, O_ORDER_CONT),
949 check_option(options, O_ORDER_END) }) {
950 3'b100: order_seq = 0;
951 3'b010: order_seq++;
952 3'b001: order_seq++;
953 }
954
955 if(flow.src_node.src_port[my_port] != 1) {
956 print_warn();
957 printf("pg::pkt_gen PG: Specified src_node may not be used as source for this port. Continuing anyway ...\n");
958 }
959
960
961 pack_db = new(pckt_num );
962 pack_db.preamble_cnt = flow.preamble_cnt;
963 pack_db.sfd = flow.sfd;
964 // printf("DEBUG pack_db.options - %x preamble_cnt - %d sfd - %d \n",pack_db.options,pack_db.preamble_cnt,pack_db.sfd);
965
966 pg_done = 0;
967 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,
968 pckt_num, ifedx_control);
969 pack_db.port_type = port_type;
970 if( pack_db.fl_state.tcp_flags == 2'h2 ) {
971 // TOADS
972 flow_db_add_entry( my_port, data_length, flow, flow.tup, flow.rx_param, flow.tx_param, flow.fl_state, options, current_flow_num );
973 }
974 if(debug_db_in) display_db(pack_db);
975 wait_send_fake=0;
976
977
978 // TOADS---
979 printf("Before mailbox_put mb_q - time - %d \n",{get_time(HI),get_time(LO)});
980
981 mailbox_put(mb_q, pack_db);
982
983 printf("pg::pkt_gen: Waiting for packet to go out ...(port type: %h), token# %0d\n",port_type, token);
984 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)});
985 printf("pg::pkt_gen: Waiting for packet to go oui options - %d Time - %d \n", pack_db.options,{get_time(HI),get_time(LO)});
986
987
988 if( check_option( pack_db.options, O_WAIT_SEND_FAKE) ) {
989 while(wait_send_fake==0) @(posedge CLOCK);
990 }
991
992
993
994 if( check_option( pack_db.options, O_WAIT_SEND) ) {
995
996 fork
997 while(time_out<10000) {
998 wait_rx_clk(1);
999 time_out++;
1000 }
1001
1002 while(pg_done!=1) @(posedge CLOCK);
1003 join any
1004 printf("pg::pkt_gen: before terminate timeout - %d pg_done - %d \n",time_out,pg_done);
1005
1006 terminate;
1007
1008
1009 if(pg_done!=1) {
1010 pg_done=1;
1011 print_warn();
1012 printf("PG: Timed out waiting for done bit (waited %0d cycles)...\n",time_out);
1013 printf(" This only happens with fake ports when we wait for someone\n");
1014 printf(" to acknowladge that the packet was processed (Port: %0d).\n",my_port);
1015 printf(" Token: %0d, Time: %0d\n",token,{get_time(HI),get_time(LO)});
1016 }
1017
1018 }
1019
1020
1021 pgToken = new (id);
1022 pgToken.pack_db = new pack_db;
1023 pgToken.port_id = my_port;
1024 mailbox_get(WAIT,pkt_gen_sync,tmpbuf);
1025 pgToken.buf = new tmpbuf;
1026 // display_buf(pgToken.buf,data_length);
1027
1028 // printf(" in pkt_gen -- length - %d \n", pack_db.header_len[0]);
1029 printf("pg::pkt_gen: Waiting End of pkt_gen !!! Time - %d \n",{get_time(HI),get_time(LO)});
1030 // trigger(ON,pkt_gen_lock);
1031 semaphore_put(pkt_gen_lock,1);
1032}
1033
1034function byte_array pg::new_gen_buf(pack_db_entry pack_db, var bit[31:0] pkt_fields[*]){
1035
1036 bit [7:0] payload[*];
1037 integer i,size;
1038 CPgIf cPg;
1039 integer len;
1040 byte_array buf;
1041
1042 cPg = new();
1043 len = pack_db.data_length;
1044 printf("byte_array pg::new_gen_buf function id - %d !! Time - %d \n",my_port,{get_time(HI),get_time(LO)});
1045
1046 cPg.genPacket(0,len, pack_db.flow, payload,pkt_fields);
1047 buf = new();
1048 for( i = 0; i < len + pack_db.flow.frame.l2_pad_length;i++) {
1049 buf.val[i] = payload[i] & 8'hff;
1050 // printf(" PKT buf - %x index - %d \n", buf.val[i],i);
1051 }
1052 new_gen_buf = buf;
1053}
1054task pg::pkt_auto_tx() {
1055 integer len;
1056 byte_array buf;
1057 integer token;
1058 pack_db_entry pack_db;
1059 event lock_send_packet;
1060 CpgToken pgToken;
1061 byte_array tmpbuf;
1062 bit[31:0] pkt_fields[*] ;
1063
1064 integer i;
1065
1066 trigger(ON,lock_send_packet);
1067
1068
1069 while(1) {
1070
1071 sync(ALL,lock_send_packet);
1072 trigger(OFF,lock_send_packet);
1073 printf(" Before mailbox_get mb_q Time - %d \n",{get_time(HI),get_time(LO)} );
1074
1075 mailbox_get(WAIT, mb_q, pack_db);
1076 printf(" After mailbox_get mb_q Time - %d \n",{get_time(HI),get_time(LO)} );
1077 if(debug_db_out) display_db(pack_db);
1078
1079 buf = new();
1080 // gen_buf( pack_db, buf, len );
1081 len = pack_db.data_length + pack_db.flow.frame.l2_pad_length;
1082 buf = new_gen_buf(pack_db,pkt_fields);
1083
1084 wait_send_fake=1;
1085
1086 pgToken = new (pack_db.gId);
1087 pgToken.pack_db = new pack_db;
1088 pgToken.port_id = my_port;
1089 pgToken.pkt_fields = new[SIZE_OF_PKT_FIELDS];
1090 for(i=0;i<SIZE_OF_PKT_FIELDS;i++) {
1091 pgToken.pkt_fields[i] = pkt_fields[i];
1092 }
1093
1094 tmpbuf = new buf;
1095 mailbox_put(pkt_gen_sync,tmpbuf);
1096
1097
1098
1099 if( !check_option( pack_db.options, O_NO_OUT_TOKEN) ) {
1100 if(debug_out_token)
1101 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)} );
1102 mailbox_put(mbox_id.pg_mb[my_port], pgToken);
1103 }
1104
1105
1106 printf("pg::pkt_auto_tx:pg[%0d]: Transmitting packet ...\n",my_port);
1107 // printf("options fake out: %d\n",check_option( pack_db.options, O_FAKE_OUT) );
1108 if( !(check_option( pack_db.options, O_FAKE_OUT )) & !port_type[2] ) {
1109 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)});
1110// HACK HACK HACK
1111
1112 if( check_option(pack_db.options, O_PREAMB_ERR) ) cfg_reg[CFG_PRAMB_CNT] = pack_db.preamble_cnt;
1113 if( check_option(pack_db.options, O_SFD_ERR) ) cfg_reg[CFG_SFD_TOKEN] = pack_db.sfd;
1114 // 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]);
1115
1116
1117 send_packet(port_type, buf, len, pack_db.options);
1118 pg_done = 1;
1119
1120 // 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)});
1121 }
1122 printf("pg::pkt_auto_tx:pg[%0d]: Done Transmitting packet ...\n",my_port);
1123 trigger(ON,lock_send_packet);
1124 }
1125}
1126
1127
1128task pg::build_frame(integer itoken,pack_db_entry pack_db, byte_array buf, var integer len,(integer header_id=-1),(integer new_crc=0)) {
1129 integer n;
1130 integer ptr=0;
1131 integer tagged = 0;
1132 integer my_port, org_port;
1133 bit [31:0] tmp32;
1134 integer data_len, header_len;
1135 integer debug = 0;
1136 integer token;
1137 integer adj_len=0;
1138 integer min,max;
1139 bit [15:0] tx_status;
1140 integer LLC_HACK = 1;
1141 bit[15:0] llc_length;
1142
1143 tmp32 = itoken;
1144 token = tmp32[25:0];
1145
1146 if(debug)
1147 printf("DEBUG: build_frame: Started Build-Frame. (Input: Token: %0d, Len: %0d Hdr: %0d, NewCRC: %0d Port: %0d)\n",
1148 token,len,header_id,new_crc,my_port);
1149 // display_db(pack_db);
1150 // printf(" data_len from build_frame - %d \n",pack_db.data_length);
1151
1152 my_port = pack_db.org_port;
1153 org_port = pack_db.org_port;
1154 if(header_id != -1) my_port = header_id;
1155
1156
1157
1158 if(debug) printf("DEBUG: build_frame: (1)ptr: %0d\n",ptr);
1159 // printf(" in build frame header_d - %d \n",header_id);
1160
1161 if(header_id==-1) {
1162 header_len = pack_db.header_len[ pack_db.use_hdr ];
1163 // printf(" in build frame header_len - %d use_header - %d \n",header_len,pack_db.use_hdr);
1164
1165 for(n=0;n< header_len ;n++)
1166 buf.val[ptr++] = pack_db.header[ pack_db.use_hdr ].val[n];
1167 } else {
1168
1169#define out_use_header pack_db.out_header[header_id].use_header
1170
1171 if( assoc_index(CHECK,pack_db.out_header,header_id) &
1172 assoc_index(CHECK,pack_db.out_header[header_id].header, out_use_header) ) {
1173
1174 header_len = pack_db.out_header[header_id].header_len[ out_use_header ];
1175 // printf(" in build frame header_len - %d \n",header_len,out_use_header);
1176
1177 for(n=0; n < header_len ; n++)
1178 buf.val[ptr++] =pack_db.out_header[header_id].header[out_use_header].val[n];
1179 } else {
1180 printf("pg::build_frame: ERROR: PG LIB: build_frame: out header invalid. (Token:%0d, Out header id: %0d).\n",
1181 token,header_id);
1182 len = 0;
1183 buf = null;
1184 return;
1185 }
1186 }
1187
1188 if(debug) printf("DEBUG: build_frame: header_len: %0d\n",header_len);
1189 if(debug) printf("DEBUG: build_frame: (2)ptr: %0d\n",ptr);
1190
1191
1192 if(pack_db.frame.data_type != DAT_FC_PAUSE)
1193 '{buf.val[ptr++], buf.val[ptr++]} = token; // Store token in payload
1194
1195
1196 if(pack_db.org_port<17 & my_port>16) adj_len += 6;
1197 if(pack_db.org_port>16 & my_port<17) adj_len -= 6;
1198
1199 if(debug) printf("DEBUG: build_frame: adj_len: %0d\n",adj_len);
1200
1201
1202 if( pack_db.frame.frame_type[2] ) tagged = 1;
1203
1204 if(debug) printf("DEBUG: build_frame: (3)ptr: DAT_LEN_EXACT: %0d\n",
1205 check_option(pack_db.frame.data_type, DAT_LEN_EXACT) );
1206
1207
1208 if(pack_db.data_length<0) {
1209
1210 case(pack_db.data_length) {
1211 -1: pack_db.data_length = 64;
1212 -2: pack_db.data_length = 128;
1213 -3: pack_db.data_length = 256;
1214 -4: pack_db.data_length = 512;
1215 -5: pack_db.data_length = 1024;
1216 -6: pack_db.data_length = (tagged) ? 1522 : 1518;
1217 -7: {
1218 // pack_db.data_length = random(pack_db.frame.data_seed); // Vera supports only one random
1219
1220 pack_db.data_length = random();
1221 min = 64;
1222 max = (tagged) ? 1522 : 1518;
1223 while(pack_db.data_length<min | pack_db.data_length>max)
1224 pack_db.data_length = random();
1225 }
1226 -8: pack_db.data_length = 63;
1227 -9: pack_db.data_length = 65;
1228 -10: pack_db.data_length = (tagged) ? 1521 : 1517;
1229 -11: pack_db.data_length = (tagged) ? 1523 : 1519;
1230 }
1231
1232 pack_db.frame.data_type = pack_db.frame.data_type | DAT_LEN_EXACT;
1233 }
1234
1235
1236 if( check_option(pack_db.frame.data_type, DAT_LEN_EXACT) ) {
1237
1238 // Convert exact length to actual data length, clear exact flag and use that data length from now on.
1239 // data_len = pack_db.data_length + header_len - pack_db.header_len[0] + adj_len;
1240
1241 data_len = pack_db.data_length - header_len - 4; // data_len - header_len - crc_len
1242
1243
1244 if(INTER_FEDX) data_len = data_len - 6;
1245
1246 pack_db.data_length = data_len;
1247 pack_db.frame.data_type = pack_db.frame.data_type & DAT_TYPE_MASK;
1248 }
1249 else
1250 data_len = pack_db.data_length;
1251
1252
1253 if(debug) printf("DEBUG: build_frame: (3)ptr: %0d\n",ptr);
1254 if(debug) printf("DEBUG: build_frame: data_len: %0d\n",data_len);
1255
1256 if(LLC_HACK & ( (pack_db.frame.frame_type== 5'h3 )| (pack_db.frame.frame_type== 5'h7) )) {
1257 printf(" build_frame LLC_HACK!!! data_len - %d \n",pack_db.data_length);
1258 if(pack_db.flow.frame.frame_type== 5'h3) {
1259 llc_length = ( pack_db.data_length + header_len + 4) - 4/*CRC*/ - 12/*L2HEADERS*/ -2/*Type/Length*/ ;
1260 buf.val[12] = llc_length[15:8];
1261 buf.val[13] = llc_length[7:0];
1262 }
1263 else {
1264 llc_length = ( pack_db.data_length + header_len + 4) - 4/*CRC*/ - 12/*L2HEADERS*/ -4/*VLAN ID*/ -2/*Type/Length*/ ;
1265 buf.val[16] = llc_length[15:8];
1266 buf.val[17] = llc_length[7:0];
1267 }
1268 }
1269
1270 if( pack_db.frame.frame_type[2] ) tagged = 1;
1271 data_gen( pack_db.frame.data_type,
1272 pack_db.frame.data_seed,
1273 data_len,
1274 buf, ptr, pack_db.options, this, tagged, INTER_FEDX);
1275
1276 if(debug) printf("DEBUG: build_frame: (4)ptr: %0d\n",ptr);
1277
1278
1279
1280 if(INTER_FEDX)
1281 tmp32 = crc_gen(buf, 2, ptr); // Skip Interfedx Control Word
1282 else
1283 tmp32 = crc_gen(buf, 0, ptr);
1284
1285
1286 if( check_option( pack_db.options, O_CRC_ERR) )
1287 tmp32 = tmp32 ^ cfg_reg[CFG_CRC_MASK];
1288
1289
1290 if(!new_crc)
1291 '{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } = pack_db.pack_crc;
1292 else {
1293 if ( (org_port==17) | (org_port==18) ) {
1294 if(INTER_FEDX) {
1295 '{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } = pack_db.pack_crc;
1296 }
1297 else {
1298
1299 tx_status = pack_db.mac.tx_status;
1300
1301 if(tx_status[14])
1302 '{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } = pack_db.pack_crc;
1303 else '{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } = tmp32;
1304 }
1305 } //end of if ( (org_port==17) | (org_port==18) )
1306 else {
1307 if(INTER_FEDX)
1308 '{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } = pack_db.pack_crc;
1309 else '{ buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } = tmp32;
1310 }
1311 }
1312
1313
1314 if(debug) printf("DEBUG: build_frame: (5)ptr: %0d\n",ptr);
1315 if(debug) printf("DEBUG: build_frame: Done.\n");
1316 len = ptr;
1317
1318 // display_buf( buf,len);
1319}
1320
1321
1322task pg::data_gen(integer type, integer seed, integer len, byte_array buf, var integer offset, bit[63:0] options,
1323 pg my_root, integer tagged, integer ifedx) {
1324 integer min,max,n,o,b,l;
1325 bit [15:0] tmp16;
1326 bit [7:0] tmp8,s;
1327 integer exact_len;
1328 CpgRandom pg_random;
1329 integer debug_dg = 0;
1330
1331 if(debug_dg) printf("DEBUG: pg::data_gen: input: type: %0d (%h), len: %0d, offset: %0d, tagged: %0d, ifedx: %0d\n",
1332 type,type,len,offset,tagged,ifedx);
1333
1334
1335 exact_len = (type & DAT_LEN_EXACT) ? 1 : 0;
1336 exact_len = ptr_to_first_pg.check_option(type, DAT_LEN_EXACT);
1337 type = type & DAT_TYPE_MASK;
1338
1339 if(len<0) exact_len = 1;
1340
1341 case(len) {
1342 -1: len = 64;
1343 -2: len = 128;
1344 -3: len = 256;
1345 -4: len = 512;
1346 -5: len = 1024;
1347 -6: len = (tagged) ? 1522 : 1518;
1348 -7: {
1349 // len = random(seed);
1350 len = random();
1351 min = 64;
1352 max = (tagged) ? 1522 : 1518;
1353 while(len<min | len>max) len = random();
1354 }
1355 -8: len = 63-offset-4;
1356 -9: len = 65-offset-4;
1357 -10: len = (tagged) ? 1521 : 1517;
1358 -11: len = (tagged) ? 1523 : 1519;
1359 }
1360
1361 if(exact_len) {
1362 len = len-offset-4;
1363 if(ifedx) len = len - 4;
1364 } else len = len - 2;
1365
1366 if(len<0) {
1367 len = 0;
1368 if(!quiet_on) printf("PG[%0d]: WARNING: Data length (payload) is zero.\n",my_port);
1369 be_msg.print(e_mesg_error, "pg::date_gen", "", "PG[%0d]: Data length (payload) is zero TESTBENCH ERROR \n", my_port);
1370
1371 }
1372
1373 o=offset;
1374 b = seed;
1375
1376 if( my_root != null & check_option(options, O_FRM_LEN_ERR2) )
1377 len = cfg_reg[CFG_FRM_LEN] - offset -4;
1378
1379 if(debug_dg) printf("DEBUG: pg::data_gen: offset: %0d, len: %0d type: %0d\n",o,len,type);
1380
1381 l = 1;
1382 case(type) {
1383 DAT_RAND:{
1384 sync(ALL,pg_random_event);
1385 trigger(OFF,pg_random_event);
1386 pg_random = new(seed);
1387 for(n=0;n<len;n++){
1388 buf.val[offset++]= pg_random.nextdata();
1389 }
1390 trigger(ON,pg_random_event);
1391 }
1392
1393 DAT_SEQ:
1394 for(n=0;n<len;n++) {
1395
1396 buf.val[offset++]=seed++;
1397 }
1398
1399 DAT_W1:
1400 for(n=0;n<len;n++) {
1401 tmp8 = 0;
1402 tmp16=n;
1403 if(l==1) {
1404 l=0;
1405 if(b<8) tmp8[7-b++] = 1;
1406 s = tmp8;
1407 } else {
1408 l=1;
1409 if( s==0 )
1410 if(b>7) tmp8[15-b++] = 1;
1411 }
1412 if(b>15) b = 0;
1413 buf.val[offset++] = tmp8;
1414 }
1415 DAT_W0:
1416 for(n=0;n<len;n++) {
1417 tmp8 = 8'hff;
1418 if(l==1) {
1419 l=0;
1420 if(b<8) tmp8[7-b++] = 0;
1421 s = tmp8;
1422 } else {
1423 l=1;
1424 if( s==8'hff )
1425 if(b>7) tmp8[15-b++] = 0;
1426 }
1427 if(b>15) b = 0;
1428 buf.val[offset++] = tmp8;
1429 }
1430 DAT_FC_PAUSE:
1431 {
1432 len = 64-offset-4;
1433 o = offset;
1434 for(n=0;n<len;n++) buf.val[offset++] = 0;
1435 '{buf.val[o++], buf.val[o++]} = FC_PAUSE_OPCODE;
1436 '{buf.val[o++], buf.val[o++]} = seed;
1437 }
1438 DAT_FC_PAUSE_ERR:
1439 {
1440 bit [15:0] tmp16 = cfg_reg[CFG_CRC_MASK];
1441 len = 64-offset-4;
1442 o = offset;
1443 for(n=0;n<len;n++) buf.val[offset++] = 0;
1444 '{buf.val[o++], buf.val[o++]} = FC_PAUSE_OPCODE ^ tmp16;
1445 '{buf.val[o++], buf.val[o++]} = seed;
1446 }
1447 DAT_ALL0:
1448 {
1449 for(n=0;n<len;n++) {
1450
1451 buf.val[offset++]=8'hff;
1452 }
1453 }
1454 DAT_ALL1:
1455 {
1456 for(n=0;n<len;n++) {
1457
1458 buf.val[offset++]=8'h00;
1459 }
1460 }
1461 default:
1462 {
1463 print_err();
1464 printf("pg::data_gen: invalid type (%0d)\n",type);
1465 }
1466 }
1467
1468 if(debug_dg & 0)
1469 for(n=0;n<len;n++)
1470 printf("pg::data_gen: buf[%0d]: %h\n",o+n,buf.val[o+n]);
1471}
1472
1473
1474
1475function bit [31:0] pg::crc32_add(bit [7:0] data, bit [31:0] crc) {
1476 bit feedback;
1477 integer i;
1478
1479 for(i=0;i<8;i=i+1) begin
1480
1481
1482 feedback = crc[31] ^ data[i];
1483 crc[31:27] = crc[30:26];
1484 crc[26] = crc[25] ^ feedback;
1485 crc[25] = crc[24];
1486 crc[24] = crc[23];
1487 crc[23] = crc[22] ^ feedback;
1488 crc[22] = crc[21] ^ feedback;
1489 crc[21:17] = crc[20:16];
1490 crc[16] = crc[15] ^ feedback;
1491 crc[15:13] = crc[14:12];
1492 crc[12] = crc[11] ^ feedback;
1493 crc[11] = crc[10] ^ feedback;
1494 crc[10] = crc[9] ^ feedback;
1495 crc[9] = crc[8];
1496 crc[8] = crc[7] ^ feedback;
1497 crc[7] = crc[6] ^ feedback;
1498 crc[6] = crc[5];
1499 crc[5] = crc[4] ^ feedback;
1500 crc[4] = crc[3] ^ feedback;
1501 crc[3] = crc[2];
1502 crc[2] = crc[1] ^ feedback;
1503 crc[1] = crc[0] ^ feedback;
1504 crc[0] = feedback;
1505 end
1506
1507 crc32_add = crc;
1508
1509}
1510
1511function integer pg::check_option(bit [63:0] option, bit [63:0] flag) {
1512 if((option[63:0] & flag[63:0]) > 64'h0) check_option = 1;
1513 else check_option = 0;
1514}
1515
1516
1517function bit [7:0] pg::class_mask(integer funct, bit[7:0] a, bit[7:0] b) {
1518 case(funct) {
1519 CLF_SRC: class_mask = a;
1520 CLF_DST: class_mask = b;
1521 CLF_OR: class_mask = a && b;
1522 CLF_AND: class_mask = a || b;
1523 default: class_mask = 8'h00;
1524 }
1525}
1526
1527
1528
1529
1530
1531task pg::send_packet(bit [3:0] ptype, byte_array buf, integer len, bit [63:0] options) {
1532 integer n;
1533
1534 case(my_port) {
1535 0: {
1536 if (port_speed == 4)
1537 send_packet_xgmii (xgm0,ptype, buf, len, options);
1538 else if (port_speed == 3)
1539 send_packet_gmii (gm0, ptype, buf, len, options);
1540 else
1541 send_packet_mii (m0,ptype, buf, len, options);
1542 }
1543
1544 1: {
1545 if (port_speed == 4)
1546 send_packet_xgmii (xgm1,ptype, buf, len, options);
1547 else if (port_speed == 3)
1548 send_packet_gmii (gm1, ptype, buf, len, options);
1549 else
1550 send_packet_mii (m1, ptype, buf, len, options);
1551 }
1552 2: {
1553 if (port_speed == 3)
1554 send_packet_gmii (gm2, ptype, buf, len, options);
1555 else
1556 send_packet_mii (m2, ptype, buf, len, options);
1557 }
1558 3: {
1559 if (port_speed == 3)
1560 send_packet_gmii (gm3, ptype, buf, len, options);
1561 else
1562 send_packet_mii (m3, ptype, buf, len, options);
1563 }
1564
1565 }
1566}
1567
1568
1569task pg::assert_col_tx (mii_def port_bind, bit [63:0] options) {
1570 integer itmp;
1571
1572
1573 while(rxdv_set == 0) @(posedge port_bind.$rxclk);
1574
1575
1576
1577 if( check_option( options, O_RX_COL) & cfg_reg[CFG_COL_LEN]>0 & !tx_done ) {
1578 itmp = cfg_reg[CFG_COL_DEL];
1579 while(itmp>0 & !tx_done) {
1580 itmp--;
1581 @(posedge port_bind.$rxclk);
1582 }
1583 port_bind.$rxcol = 1 async;
1584 itmp = cfg_reg[CFG_COL_LEN];
1585 while(itmp>0 & !tx_done) {
1586 itmp--;
1587 @(posedge port_bind.$rxclk);
1588 }
1589 port_bind.$rxcol = 0 async;
1590 }
1591
1592}
1593
1594
1595task pg::assert_mii_err (mii_def port_bind ) {
1596 integer cnt=0;
1597
1598 if(tx_err_start==-1) return;
1599
1600 if(tx_err_len<1) {
1601 printf("PG: WARNING: tx_err injection length to short. (Start: %0d, Length: %0d)\n",
1602 tx_err_start,tx_err_len);
1603 return;
1604 }
1605
1606 while(cnt++ < tx_err_start & !tx_done)
1607 @(posedge port_bind.$rxclk);
1608
1609 if(!tx_done) {
1610 port_bind.$rxerr = 1;
1611 cnt=0;
1612 while(cnt++ < tx_err_len & !tx_done)
1613 @(posedge port_bind.$rxclk);
1614 port_bind.$rxerr = 0;
1615 } else
1616 printf("PG: WARNING: Packet was sent before tx_err could be assrted.(Start: %0d, Length: %0d)\n",
1617 tx_err_start,tx_err_len);
1618
1619 tx_err_start = -1;
1620}
1621
1622task pg::send_packet_mii (mii_def port_bind, bit [3:0] ptype, byte_array buf, integer len, bit [63:0] options) {
1623 integer n, cnt;
1624 bit [7:0] tmp;
1625 bit [63:0] current_time;
1626 bit [63:0] min_gap, time_tmp;
1627
1628 tx_done = 0;
1629
1630 if(debug_mii==1)
1631 printf("DEBUG: PG low tx started: current_time: %0d\n", {get_time(HI),get_time(LO)} );
1632
1633
1634 current_time = {get_time(HI),get_time(LO)};
1635 if(port_speed==1) min_gap = 800 * MII_IP_GAP;
1636 else min_gap = 80 * MII_IP_GAP;
1637 time_tmp = current_time - last_tx_time;
1638 if(debug_mii_tx)
1639 printf("DEBUG: PG low tx: last_time: %0d, current_time: %0d, diff: %0d\n",
1640 last_tx_time,current_time,time_tmp);
1641 if((time_tmp < min_gap) & !check_option(options, O_NO_IP_GAP_FIX) & !check_option(options, O_CUSTOM_IP_GAP) ) {
1642 time_tmp = min_gap - time_tmp;
1643 if(debug_mii_tx) printf("DEBUG: PG low tx: Min_gap: %0d, gap_diff: %0d\n",min_gap,time_tmp);
1644 if(port_speed==1) time_tmp = time_tmp / 400;
1645 else time_tmp = time_tmp / 40;
1646 if(debug_mii_tx) printf("DEBUG: PG low tx: waiting additional %0d cycles\n",time_tmp);
1647 repeat(time_tmp) @(posedge port_bind.$rxclk);
1648 } else
1649 if( check_option(options, O_CUSTOM_IP_GAP) ) {
1650 repeat(cfg_reg[CFG_IP_GAP]) @(posedge port_bind.$rxclk);
1651 }
1652
1653 fork {
1654 // assert_mii_err (get_bind( port_bind ));
1655 assert_mii_err ( port_bind );
1656 }
1657 join none
1658
1659
1660 port_bind.$rxdv = 1;
1661 rxdv_set = 1;
1662
1663
1664 if( check_option(options, O_PREAMB_ERR) ) cnt = cfg_reg[CFG_PRAMB_CNT];
1665 else cnt = 7;
1666
1667
1668 for(n=0;n<cnt;n++) {
1669 tmp = MII_PREAMBLE;
1670 port_bind.$rxd = tmp[3:0];
1671 @(posedge port_bind.$rxclk);
1672 port_bind.$rxd = tmp[7:4];
1673 @(posedge port_bind.$rxclk);
1674 }
1675
1676 if( check_option(options, O_SFD_ERR) ) tmp = cfg_reg[CFG_SFD_TOKEN];
1677 else tmp = MII_SOF;
1678
1679 port_bind.$rxd = tmp[3:0];
1680 @(posedge port_bind.$rxclk);
1681 port_bind.$rxd = tmp[7:4];
1682 @(posedge port_bind.$rxclk);
1683
1684 for(n=0;n<len;n++) {
1685 if(debug_mii==1) printf("MII: Sending Byte[%0d]: %h\n", n, buf.val[n] );
1686 tmp = buf.val[n];
1687 port_bind.$rxd = tmp[3:0];
1688 @(posedge port_bind.$rxclk);
1689
1690 if(n != (len-1) | !check_option(options, O_NIBBLE_ERR) ) {
1691 port_bind.$rxd = tmp[7:4];
1692 @(posedge port_bind.$rxclk);
1693 }
1694 }
1695
1696 port_bind.$rxdv = 0;
1697 rxdv_set = 0;
1698
1699 tmp = MII_PREAMBLE;
1700 port_bind.$rxd = tmp[3:0];
1701
1702 @(posedge port_bind.$rxclk);
1703 tx_done = 1;
1704 last_tx_time = {get_time(HI),get_time(LO)};
1705
1706}
1707
1708
1709task pg::assert_gmii_err (gmii_def port_bind) {
1710 integer cnt=0;
1711
1712 if(tx_err_start==-1) return;
1713
1714 if(tx_err_len<1) {
1715 printf("PG: WARNING: tx_err injection length to short. (Start: %0d, Length: %0d)\n",
1716 tx_err_start,tx_err_len);
1717 return;
1718 }
1719
1720 while(cnt++ < tx_err_start & !tx_done)
1721 @(posedge port_bind.$rxclk);
1722
1723 if(!tx_done) {
1724 port_bind.$rxerr = 1;
1725 cnt=0;
1726 while(cnt++ < tx_err_len & !tx_done)
1727 @(posedge port_bind.$rxclk);
1728 port_bind.$rxerr = 0;
1729 } else
1730 printf("PG: WARNING: Packet was sent before tx_err could be assrted.(Start: %0d, Length: %0d)\n",
1731 tx_err_start,tx_err_len);
1732
1733 tx_err_start = -1;
1734}
1735
1736task pg::send_packet_gmii (gmii_def port_bind, bit [3:0] ptype, byte_array buf, integer len, bit [63:0] options) {
1737 integer n, cnt;
1738 bit [7:0] tmp;
1739 bit [63:0] current_time;
1740 bit [63:0] min_gap, time_tmp;
1741 integer ipg_clock_diffs;
1742 integer align_cycles; //hummer
1743 bit [63:0] ipg_diffs;
1744 integer need_extra_clocks;
1745 integer sfd;
1746
1747 tx_done = 0;
1748
1749 //current_time = {get_time(HI),get_time(LO)};
1750 current_time = clock_counter;
1751 min_gap = GMII_IP_GAP - 1;
1752
1753 // PORT2 gets the IPG given by the plusarg PKTGEN_PORT2_1G_IPG
1754 if (get_plus_arg (CHECK, "PKTGEN_PORT2_1G_IPG") && (my_port==2))
1755 min_gap = get_plus_arg (NUM, "PKTGEN_PORT2_1G_IPG");
1756
1757 // PORT3 gets the IPG given by the plusarg PKTGEN_PORT3_1G_IPG
1758 if (get_plus_arg (CHECK, "PKTGEN_PORT3_1G_IPG") && (my_port==3))
1759 min_gap = get_plus_arg (NUM, "PKTGEN_PORT3_1G_IPG");
1760
1761 time_tmp = current_time - last_tx_time;
1762
1763 ipg_diffs = time_tmp; // 800 ps
1764 ipg_clock_diffs = 0; //hummer
1765 if(ipg_diffs < min_gap) {
1766 need_extra_clocks = 1;
1767 ipg_clock_diffs = min_gap - ipg_diffs;
1768 }
1769 else need_extra_clocks = 0;
1770
1771 //hummer
1772 //////////////////align logic>>>>>>>>>>>>>>>>
1773 //first calculate where the align point is?
1774 align_cycles = 4-(((current_time-prev_current_time))%4);
1775 //see if the align point is beyond IPG
1776 //if so, lets move the IPG to align point
1777 if(align_cycles >= ipg_clock_diffs) {
1778 ipg_clock_diffs = align_cycles;
1779 need_extra_clocks = 1;
1780 }
1781 else
1782 //if align is before IPG, we need to go to next align point
1783 //this next align point is 4-(difference of the current align-ipg)
1784 if(align_cycles < ipg_clock_diffs) {
1785 //also make sure the IPG is not a multiple of next align
1786 if((ipg_clock_diffs-align_cycles)%4)
1787 ipg_clock_diffs += 4-(ipg_clock_diffs-align_cycles)%4;
1788 }
1789 //////////////////align logic<<<<<<<<<<<<<<<<
1790
1791 if(debug_mii_tx)
1792 printf("DEBUG: PG low tx: last_time: %0d, current_time: %0d, diff: %0d\n",
1793 last_tx_time,current_time,time_tmp);
1794
1795
1796 if( !check_option(options, O_NO_IP_GAP_FIX) & !check_option(options, O_CUSTOM_IP_GAP) & need_extra_clocks ) {
1797 repeat(ipg_clock_diffs) @(posedge port_bind.$rxclk);
1798 } else
1799 if( check_option(options, O_CUSTOM_IP_GAP) ) {
1800 repeat(cfg_reg[CFG_IP_GAP]) @(posedge port_bind.$rxclk);
1801 }
1802
1803 fork
1804 // assert_gmii_err (get_bind( port_bind));
1805 assert_gmii_err ( port_bind);
1806 join none
1807
1808 prev_current_time = clock_counter;
1809
1810 //port_bind.$rxd = XGMII_SOP;
1811 port_bind.$rxdv = 1;
1812 /* @(posedge port_bind.$rxclk); */
1813
1814 if( check_option(options, O_PREAMB_ERR) ) cnt = cfg_reg[CFG_PRAMB_CNT];
1815 else cnt = 7;
1816
1817
1818 for(n=0;n<cnt;n++) {
1819 port_bind.$rxd = GMII_PREAMBLE;
1820 @(posedge port_bind.$rxclk);
1821 }
1822
1823
1824 port_bind.$rxdv = 1;
1825
1826 // printf("DEBUG pack_db.options - %x preamble_cnt - %d sfd - %d \n",options,cfg_reg[CFG_PRAMB_CNT],cfg_reg[CFG_SFD_TOKEN]);
1827 if( check_option(options, O_SFD_ERR) ) {
1828 sfd = cfg_reg[CFG_SFD_TOKEN];
1829 if(sfd!=-1) {
1830 port_bind.$rxd = cfg_reg[CFG_SFD_TOKEN];
1831 @(posedge port_bind.$rxclk);
1832 } else {
1833 printf("SKIP SFD GENERATION!!\n");
1834 }
1835 }
1836 else{
1837 port_bind.$rxd = GMII_SOF;
1838 @(posedge port_bind.$rxclk);
1839 }
1840
1841 for(n=0;n<len;n++) {
1842 if(debug_gmii==1) printf("GMII: Sending Byte[%0d]: %h\n", n, buf.val[n] );
1843 if(n != (len-1) | !check_option(options, O_NIBBLE_ERR) ) {
1844 port_bind.$rxd = buf.val[n];
1845 @(posedge port_bind.$rxclk);
1846 }
1847 }
1848
1849 last_tx_time = clock_counter;
1850 port_bind.$rxdv = 0;
1851 port_bind.$rxd = GMII_PREAMBLE;
1852
1853 tx_done = 1;
1854 port_bind.$rxerr = 0;
1855 @(posedge port_bind.$rxclk);
1856 //last_tx_time = {get_time(HI),get_time(LO)};
1857
1858}
1859
1860
1861task pg::assert_xgmii_err (xgmii_def port_bind) {
1862 integer cnt=0;
1863
1864 if(tx_err_start==-1) return;
1865
1866 if(tx_err_len<1) {
1867 printf("PG: WARNING: tx_err injection length to short. (Start: %0d, Length: %0d)\n",
1868 tx_err_start,tx_err_len);
1869 return;
1870 }
1871
1872 while(cnt++ < tx_err_start & !tx_done)
1873 @(posedge port_bind.$rxclk_int);
1874
1875 if(!tx_done) {
1876 port_bind.$rxerr = 1;
1877 cnt=0;
1878 while(cnt++ < tx_err_len & !tx_done)
1879 @(posedge port_bind.$rxclk_int);
1880 port_bind.$rxerr = 0;
1881 } else
1882 printf("PG: WARNING: Packet was sent before tx_err could be assrted.(Start: %0d, Length: %0d)\n",
1883 tx_err_start,tx_err_len);
1884
1885 tx_err_start = -1;
1886}
1887
1888
1889task pg::send_packet_xgmii (xgmii_def port_bind,bit [3:0] ptype, byte_array buf, integer len, bit [63:0] options) {
1890 integer n, cnt;
1891 bit [7:0] tmp;
1892 bit [63:0] current_time;
1893 bit [63:0] min_gap, time_tmp;
1894 integer ipg_clock_diffs;
1895 integer align_cycles; //hummer
1896 bit [63:0] ipg_diffs;
1897 integer need_extra_clocks;
1898 integer sfd;
1899
1900 tx_done = 0;
1901 printf("send_packet_xgmii - Enteri Time - %d \n",{get_time(HI),get_time(LO)});
1902 // current_time = {get_time(HI),get_time(LO)};
1903 current_time = clock_counter;
1904 min_gap = 8 * XGMII_IP_GAP ; // TOADS----
1905
1906 min_gap = 4;
1907
1908 // both ports at the same IPG, if the plusarg PKTGEN_10G_IPG is specified
1909 // this plusarg is really a redundant after we had PKTGEN_PORT0_10G_IPG/PKTGEN_PORT1_10G_IPG
1910 // but want to keep this for some old test runs which use this
1911 if (get_plus_arg (CHECK, "PKTGEN_10G_IPG"))
1912 min_gap = get_plus_arg (NUM, "PKTGEN_10G_IPG");
1913
1914 // PORT0 gets the IPG given by the plusarg PKTGEN_PORT0_10G_IPG
1915 if (get_plus_arg (CHECK, "PKTGEN_PORT0_10G_IPG") && (my_port==0))
1916 min_gap = get_plus_arg (NUM, "PKTGEN_PORT0_10G_IPG");
1917
1918 // PORT1 gets the IPG given by the plusarg PKTGEN_PORT1_10G_IPG
1919 if (get_plus_arg (CHECK, "PKTGEN_PORT1_10G_IPG") && (my_port==1))
1920 min_gap = get_plus_arg (NUM, "PKTGEN_PORT1_10G_IPG");
1921
1922
1923 time_tmp = current_time - last_tx_time;
1924
1925 ipg_diffs = time_tmp; // 800 ps
1926 ipg_clock_diffs = 0; //hummer
1927 if(ipg_diffs < min_gap) {
1928 need_extra_clocks = 1;
1929 ipg_clock_diffs = min_gap - ipg_diffs;
1930 }
1931 else need_extra_clocks = 0;
1932
1933 //hummer
1934 //////////////////align logic>>>>>>>>>>>>>>>>
1935 //first calculate where the align point is?
1936 align_cycles = 4-(((current_time-prev_current_time))%4);
1937 //see if the align point is beyond IPG
1938 //if so, lets move the IPG to align point
1939 if(align_cycles >= ipg_clock_diffs) {
1940 ipg_clock_diffs = align_cycles;
1941 need_extra_clocks = 1;
1942 }
1943 else
1944 //if align is before IPG, we need to go to next align point
1945 //this next align point is 4-(difference of the current align-ipg)
1946 if(align_cycles < ipg_clock_diffs) {
1947 //also make sure the IPG is not a multiple of next align
1948 if((ipg_clock_diffs-align_cycles)%4)
1949 ipg_clock_diffs += 4-(ipg_clock_diffs-align_cycles)%4;
1950 }
1951 //////////////////align logic<<<<<<<<<<<<<<<<
1952
1953
1954 printf("pg::send_packet_xgmii: DEBUG--len - %d \n",len);
1955 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);
1956
1957 if(debug_xgmii_tx)
1958 printf("DEBUG: PG low tx: last_time: %0d, current_time: %0d, diff: %0d options = %x \n",
1959 last_tx_time,current_time,time_tmp,options);
1960 if( !check_option(options, O_NO_IP_GAP_FIX) & !check_option(options, O_CUSTOM_IP_GAP) & need_extra_clocks ) {
1961 repeat(ipg_clock_diffs) @(posedge port_bind.$rxclk_int);
1962
1963 } else if( check_option(options, O_CUSTOM_IP_GAP) ) {
1964
1965 repeat(cfg_reg[CFG_IP_GAP]) @(posedge port_bind.$rxclk_int);
1966 }
1967
1968 fork
1969 // assert_xgmii_err (get_bind( port_bind ) );
1970 assert_xgmii_err (port_bind );
1971 join none
1972
1973 port_bind.$rxdv = 1;
1974
1975
1976 // prev_current_time = {get_time(HI),get_time(LO)}; //hummer
1977 prev_current_time = clock_counter;
1978
1979
1980 port_bind.$rxd = XGMII_SOP;
1981 port_bind.$rxdv = 1;
1982 @(posedge port_bind.$rxclk_int);
1983
1984 if( check_option(options, O_PREAMB_ERR) ) cnt = cfg_reg[CFG_PRAMB_CNT];
1985 else cnt = 6;
1986
1987 for(n=0;n<cnt;n++) {
1988 port_bind.$rxd = XGMII_PREAMBLE;
1989 port_bind.$rxdv = 0;
1990
1991 @(posedge port_bind.$rxclk_int);
1992 }
1993
1994
1995 port_bind.$rxdv = 0;
1996 // printf("DEBUG pack_db.options - %x preamble_cnt - %d sfd - %d \n",options,cfg_reg[CFG_PRAMB_CNT],cfg_reg[CFG_SFD_TOKEN]);
1997 if( check_option(options, O_SFD_ERR) ) {
1998 sfd = cfg_reg[CFG_SFD_TOKEN];
1999 if(sfd!=-1) {
2000 port_bind.$rxd = cfg_reg[CFG_SFD_TOKEN];
2001 @(posedge port_bind.$rxclk_int);
2002 } else {
2003 printf("SKIP SFD GENERATION!!\n");
2004 }
2005 }
2006 else{
2007 port_bind.$rxd = XGMII_SOF;
2008 @(posedge port_bind.$rxclk_int);
2009 }
2010
2011
2012 for(n=0;n<len;n++) {
2013 // printf("XGMII: Sending Byte[%0d]: %h\n", n, buf.val[n] );
2014 if(n != (len-1) | !check_option(options, O_NIBBLE_ERR) ) {
2015 port_bind.$rxd = buf.val[n];
2016 @(posedge port_bind.$rxclk_int);
2017 }
2018 }
2019
2020 port_bind.$rxdv = 1;
2021
2022 port_bind.$rxd = XGMII_EOP;
2023 @(posedge port_bind.$rxclk_int);
2024
2025 // last_tx_time = {get_time(HI),get_time(LO)};
2026 last_tx_time = clock_counter;
2027 port_bind.$rxd = XGMII_IDLE;
2028 port_bind.$rxdv = 1;
2029
2030 tx_done = 1;
2031 port_bind.$rxerr = 0;
2032 @(posedge port_bind.$rxclk_int);
2033 //prev_current_time = current_time; //hummer
2034 printf("send_packet_xgmii - Exit Time - %d \n",{get_time(HI),get_time(LO)});
2035}
2036
2037
2038task pg::wait_clk(integer count) {
2039 repeat(count) @(posedge CLOCK);
2040}
2041
2042task pg::wait_tx_clk(integer count) {
2043 case(my_port) {
2044 0: wait_tx_clk_if (m0 , count);
2045 1: wait_tx_clk_if (m1 , count);
2046 2: wait_tx_clk_if (m2 , count);
2047 3: wait_tx_clk_if (m3 , count);
2048 }
2049}
2050task pg::wait_tx_clk_if ( mii_def port_bind, integer count) {
2051 repeat(count) @(posedge port_bind.$txclk);
2052}
2053
2054task pg::wait_rx_clk(integer count) {
2055 case(my_port) {
2056 0: wait_tx_clk_if (m0 , count);
2057 1: wait_tx_clk_if (m1 , count);
2058 2: wait_tx_clk_if (m2 , count);
2059 3: wait_tx_clk_if (m3 , count);
2060 }
2061}
2062
2063task pg::wait_rx_clk_if ( mii_def port_bind, integer count) {
2064 repeat(count) @(posedge port_bind.$rxclk);
2065}
2066
2067
2068task pg::new(integer my_porti, (bit [3:0] ptype=0)) {
2069 integer n,i;
2070
2071 my_port = my_porti;
2072 port_type = ptype;
2073
2074 ifedx_control = 16'h0001;
2075 // trigger(ON,pkt_gen_lock);
2076 pkt_gen_lock = alloc(SEMAPHORE,0,1,0);
2077
2078 semaphore_put(pkt_gen_lock,1);
2079 trigger(ON,pg_random_event);
2080
2081
2082 if(my_port>15) {
2083 printf("PG: INIT: Warning: Port %0d is invalid or out of range.\n", my_port);
2084 }
2085
2086 if(!quiet_on)
2087 printf("INFO: Packet Generator attaching to port %0d\n",my_port);
2088
2089
2090 if(pg_used_ports[my_port] == 1) {
2091 printf("PG: INIT: Port %0d already in use.\n", my_port);
2092
2093 terminate;
2094 }
2095 pg_used_ports[my_port] = 1;
2096
2097
2098 for(n=0;n<60;n++) {
2099 l3_class[n] = new;
2100 }
2101 for(n=0;n<40;n++) {
2102 l3_mask[n] = new;
2103 }
2104
2105
2106 queue_lock = alloc(SEMAPHORE,0,1,1);
2107 if(queue_lock == 0) {
2108 printf("PG: INIT: Could not allocate spaphore queue_lock.\n");
2109 }
2110
2111
2112 mb_q = alloc(MAILBOX, 0, 1);
2113 pkt_gen_sync = alloc(MAILBOX, 0, 1);
2114 if(mb_q == 0) {
2115 printf("PG: INIT: Could not allocate mailbox mb_q.\n");
2116 }
2117 mbox_id.pg_mb[my_port] = alloc(MAILBOX, 0, 1);
2118 if(mbox_id.pg_mb[my_port] == 0) {
2119 printf("PG: INIT: Could not allocate mailbox mbox_id.pg_mb[%0d].\n",my_port);
2120 }
2121
2122
2123 fork
2124 pkt_auto_tx();
2125 join none
2126
2127
2128 if(ptr_to_first_pg==null) ptr_to_first_pg = this;
2129
2130
2131 last_tx_time = {get_time(HI),get_time(LO)};
2132
2133 for(n=0;n<CFG_LAST_ENTRY;n++) cfg_reg[n] = 0;
2134
2135
2136
2137 for(n=0;n<40; n++)
2138 for(i=0;i<12;i++) {
2139 l3_mask[n].val[i] = 8'hff;
2140 }
2141 for(n=0;n<60;n++)
2142 for(i=0;i<12;i++) {
2143 l3_class[n].val[i] = 0;
2144 }
2145 for(n=CL_RSVP;n<CL_USER1;n++) {
2146 l3_class[n].val[0] = 8'h08;
2147 l3_class[n].val[2] = 8'h45;
2148 }
2149
2150
2151
2152
2153 l3_class[CL_ARP].val[0] = 8'h08;
2154 l3_class[CL_ARP].val[1] = 8'h06;
2155 l3_class[CL_RARP].val[0] = 8'h80;
2156 l3_class[CL_RARP].val[1] = 8'h35;
2157 l3_class[CL_RSVP].val[0] = 8'h08;
2158 l3_class[CL_RSVP].val[11] = 8'h2e;
2159 l3_class[CL_IGMP].val[0] = 8'h08;
2160 l3_class[CL_IGMP].val[11] = 8'h02;
2161 l3_class[CL_ICMP].val[0] = 8'h08;
2162 l3_class[CL_ICMP].val[11] = 8'h01;
2163 l3_class[CL_GRE].val[0] = 8'h08;
2164 l3_class[CL_GRE].val[11] = 8'h2F;
2165 l3_class[CL_PIM].val[0] = 8'h08;
2166 l3_class[CL_PIM].val[11] = 8'h67;
2167
2168
2169
2170 l3_class[CL_IP_TUN_V4_V4].val[0] = 8'h08;
2171 l3_class[CL_IP_TUN_V4_V4].val[2] = 8'h45;
2172 l3_class[CL_IP_TUN_V4_V4].val[11] = 8'h04;
2173
2174
2175 l3_class[CL_IP_TUN_V4_V6].val[0] = 8'h08;
2176 l3_class[CL_IP_TUN_V4_V6].val[2] = 8'h45;
2177 l3_class[CL_IP_TUN_V4_V6].val[11] = 8'h29;
2178
2179 l3_class[CL_IP].val[0] = 8'h08;
2180 l3_class[CL_IP].val[2] = 8'h45;
2181
2182
2183 l3_class[CL_IP_FRAG].val[0] = 8'h08;
2184 l3_class[CL_IP_FRAG].val[2] = 8'h45;
2185 l3_class[CL_IP_FRAG].val[8] = 8'h20;
2186
2187 l3_class[CL_IP_FRAG].val[11] = 8'h12;
2188
2189 l3_mask[CL_IP_FRAG].val[8] = 8'h00;
2190 l3_mask[CL_IP_FRAG].val[9] = 8'h00;
2191
2192 l3_class[CL_IP_SEC_AH].val[0] = 8'h08;
2193 l3_class[CL_IP_SEC_AH].val[2] = 8'h48;
2194 l3_class[CL_IP_SEC_AH].val[11]= 8'h33;
2195 l3_class[CL_IP_SEC_ESP].val[0]= 8'h08;
2196 l3_class[CL_IP_SEC_ESP].val[2]= 8'h48;
2197 l3_class[CL_IP_SEC_ESP].val[11]= 8'h32;
2198 l3_class[CL_IP_OPT].val[0] = 8'h08;
2199 l3_class[CL_IP_OPT].val[2] = 8'h48;
2200
2201
2202 l3_class[CL_UDP].val[0] = 8'h08;
2203 l3_class[CL_UDP].val[2] = 8'h45;
2204 l3_class[CL_UDP].val[11] = 8'h11;
2205 l3_class[CL_UDP_OPT].val[2] = 8'h48;
2206 l3_class[CL_UDP_OPT].val[11] = 8'h11;
2207 l3_class[CL_UDP_FRAG].val[0] = 8'h08;
2208 l3_class[CL_UDP_FRAG].val[2] = 8'h45;
2209 l3_class[CL_UDP_FRAG].val[8] = 8'h01;
2210 l3_class[CL_UDP_FRAG].val[9] = 8'h00;
2211 l3_class[CL_UDP_FRAG].val[11] = 8'h11;
2212 l3_mask[CL_UDP_FRAG].val[8] = 8'h00;
2213 l3_mask[CL_UDP_FRAG].val[9] = 8'h00;
2214
2215
2216 l3_class[CL_TCP].val[0] = 8'h08;
2217 l3_class[CL_TCP].val[2] = 8'h45;
2218 l3_class[CL_TCP].val[11] = 8'h06;
2219 l3_class[CL_TCP_OPT].val[0] = 8'h08;
2220 l3_class[CL_TCP_OPT].val[2] = 8'h45;
2221 l3_class[CL_TCP_OPT].val[11] = 8'h06;
2222 l3_class[CL_TCP_FRAG].val[0] = 8'h08;
2223 l3_class[CL_TCP_FRAG].val[2] = 8'h45;
2224 l3_class[CL_TCP_FRAG].val[8] = 8'h21;
2225 l3_class[CL_TCP_FRAG].val[9] = 8'h00;
2226 l3_class[CL_TCP_FRAG].val[11] = 8'h06;
2227 l3_mask[CL_TCP_FRAG].val[8] = 8'h00;
2228 l3_mask[CL_TCP_FRAG].val[9] = 8'h00;
2229
2230
2231
2232
2233 l3_class[CL_IP_V6].val[0] = 8'h86;
2234 l3_class[CL_IP_V6].val[1] = 8'hdd;
2235 l3_class[CL_IP_V6].val[2] = 8'h60;
2236 l3_class[CL_ICMP_IP_V6].val[0] = 8'h86;
2237 l3_class[CL_ICMP_IP_V6].val[1] = 8'hdd;
2238 l3_class[CL_ICMP_IP_V6].val[2] = 8'h60;
2239 l3_class[CL_ICMP_IP_V6].val[8] = 8'h01;
2240 l3_class[CL_IGMP_IP_V6].val[0] = 8'h86;
2241 l3_class[CL_IGMP_IP_V6].val[1] = 8'hdd;
2242 l3_class[CL_IGMP_IP_V6].val[2] = 8'h60;
2243 l3_class[CL_IGMP_IP_V6].val[8] = 8'h02;
2244 l3_class[CL_RSVP_IP_V6].val[0] = 8'h86;
2245 l3_class[CL_RSVP_IP_V6].val[1] = 8'hdd;
2246 l3_class[CL_RSVP_IP_V6].val[2] = 8'h60;
2247 l3_class[CL_RSVP_IP_V6].val[8] = 8'h2E;
2248 l3_class[CL_GRE_IP_V6].val[0] = 8'h86;
2249 l3_class[CL_GRE_IP_V6].val[1] = 8'hdd;
2250 l3_class[CL_GRE_IP_V6].val[2] = 8'h60;
2251 l3_class[CL_GRE_IP_V6].val[8] = 8'h2F;
2252 l3_class[CL_PIM_IP_V6].val[0] = 8'h86;
2253 l3_class[CL_PIM_IP_V6].val[1] = 8'hdd;
2254 l3_class[CL_PIM_IP_V6].val[2] = 8'h60;
2255 l3_class[CL_PIM_IP_V6].val[8] = 8'h67;
2256 l3_class[CL_IP_V6_SEC_AH].val[0] = 8'h86;
2257 l3_class[CL_IP_V6_SEC_AH].val[1] = 8'hdd;
2258 l3_class[CL_IP_V6_SEC_AH].val[2] = 8'h60;
2259 l3_class[CL_IP_V6_SEC_AH].val[8] = 8'h33;
2260 l3_class[CL_IP_V6_SEC_ESP].val[0] = 8'h86;
2261 l3_class[CL_IP_V6_SEC_ESP].val[1] = 8'hdd;
2262 l3_class[CL_IP_V6_SEC_ESP].val[2] = 8'h60;
2263 l3_class[CL_IP_V6_SEC_ESP].val[8] = 8'h32;
2264
2265
2266 l3_class[CL_IP_TUN_V6_V6].val[0] = 8'h86;
2267 l3_class[CL_IP_TUN_V6_V6].val[1] = 8'hdd;
2268 l3_class[CL_IP_TUN_V6_V6].val[8] = 8'h29;
2269
2270
2271 l3_class[CL_IP_TUN_V6_V4].val[0] = 8'h86;
2272 l3_class[CL_IP_TUN_V6_V4].val[1] = 8'hdd;
2273 l3_class[CL_IP_TUN_V6_V4].val[8] = 8'h04;
2274
2275
2276 l3_class[CL_UDP_IP_V6].val[0] = 8'h86;
2277 l3_class[CL_UDP_IP_V6].val[1] = 8'hDD;
2278 l3_class[CL_UDP_IP_V6].val[2] = 8'h60;
2279 l3_class[CL_UDP_IP_V6].val[8] = 8'h11;
2280 l3_class[CL_UDP_OPT_IP_V6].val[0] = 8'h86;
2281 l3_class[CL_UDP_OPT_IP_V6].val[2] = 8'h48;
2282 l3_class[CL_UDP_OPT_IP_V6].val[8] = 8'h11;
2283 l3_class[CL_UDP_FRAG_IP_V6].val[0] = 8'h86;
2284 l3_class[CL_UDP_FRAG_IP_V6].val[2] = 8'h45;
2285 l3_class[CL_UDP_FRAG_IP_V6].val[8] = 8'h01;
2286 l3_class[CL_UDP_FRAG_IP_V6].val[5] = 8'h12;
2287 l3_class[CL_UDP_FRAG_IP_V6].val[6] = 8'h12;
2288 l3_class[CL_UDP_FRAG_IP_V6].val[8] = 8'h11;
2289 l3_mask[CL_UDP_FRAG_IP_V6].val[8] = 8'h00;
2290 l3_mask[CL_UDP_FRAG_IP_V6].val[9] = 8'h00;
2291
2292
2293
2294 l3_class[CL_TCP_IP_V6].val[0] = 8'h86;
2295 l3_class[CL_TCP_IP_V6].val[1] = 8'hDD;
2296 l3_class[CL_TCP_IP_V6].val[2] = 8'h60;
2297 l3_class[CL_TCP_IP_V6].val[8] = 8'h06;
2298 l3_class[CL_TCP_OPT_IP_V6].val[0] = 8'h86;
2299 l3_class[CL_TCP_OPT_IP_V6].val[1] = 8'hDD;
2300 l3_class[CL_TCP_OPT_IP_V6].val[2] = 8'h60;
2301 l3_class[CL_TCP_OPT_IP_V6].val[8] = 8'h06;
2302
2303 l3_class[CL_TCP_FRAG_IP_V6].val[0] = 8'h86;
2304 l3_class[CL_TCP_FRAG_IP_V6].val[2] = 8'h45;
2305 l3_class[CL_TCP_FRAG_IP_V6].val[5] = 8'h12;
2306 l3_class[CL_TCP_FRAG_IP_V6].val[8] = 8'h06;
2307 l3_mask[CL_TCP_FRAG_IP_V6].val[5] = 8'h00;
2308 l3_mask[CL_TCP_FRAG_IP_V6].val[6] = 8'h00;
2309
2310
2311
2312
2313
2314 cfg_reg[CFG_IP_GAP] = 0;
2315 cfg_reg[CFG_UDP_LEN] = 0;
2316 cfg_reg[CFG_UDP_CSM] = 0;
2317 cfg_reg[CFG_TCP_SEQ] = 0;
2318 cfg_reg[CFG_TCP_ACK] = 0;
2319 cfg_reg[CFG_TCP_LEN] = 4'b0101;
2320 cfg_reg[CFG_TCP_FLAG]= 0;
2321 cfg_reg[CFG_TCP_WIN] = 0;
2322 cfg_reg[CFG_TCP_CSM] = 0;
2323 cfg_reg[CFG_TCP_URG] = 0;
2324
2325
2326
2327
2328
2329
2330 fork
2331 case(my_port) {
2332
2333 0: if (get_plus_arg(CHECK, "MAC_SPEED0=")) {
2334 mac_speed = get_plus_arg(NUM,"MAC_SPEED0=");
2335 config_tx (m0 , mac_speed);
2336 }
2337
2338 1: if (get_plus_arg(CHECK, "MAC_SPEED1=")) {
2339 mac_speed = get_plus_arg(NUM,"MAC_SPEED1=");
2340 config_tx (m1 , mac_speed);
2341 }
2342
2343 2: if (get_plus_arg(CHECK, "MAC_SPEED2=")) {
2344 mac_speed = get_plus_arg(NUM,"MAC_SPEED2=");
2345 config_tx (m2 , mac_speed);
2346 }
2347
2348 3: if (get_plus_arg(CHECK, "MAC_SPEED3=")) {
2349 mac_speed = get_plus_arg(NUM,"MAC_SPEED3=");
2350 config_tx (m3 , mac_speed);
2351 }
2352
2353 }
2354
2355
2356
2357 join none
2358 fork {
2359 count_clock();
2360 }
2361 join none
2362
2363}
2364
2365
2366task pg::count_clock() {
2367
2368// This is just a HACK to get going
2369clock_counter = 0;
2370case(my_port) {
2371 0: if (port_speed == 4) {
2372 while(1) {
2373 @(posedge xgm0.$rxclk_int); clock_counter = clock_counter + 1;
2374 }
2375 } else if (port_speed == 3) {
2376 while(1) {
2377 @(posedge gm0.$rxclk); clock_counter = clock_counter + 1;
2378 }
2379 } else {
2380 while(1) {
2381 @(posedge m0.$rxclk); clock_counter = clock_counter + 1;
2382 }
2383 }
2384
2385 1: if (port_speed == 4) {
2386 while(1) {
2387 @(posedge xgm1.$rxclk_int); clock_counter = clock_counter + 1;
2388 }
2389 } else if (port_speed == 3) {
2390 while(1) {
2391 @(posedge gm1.$rxclk); clock_counter = clock_counter + 1;
2392 }
2393 } else {
2394 while(1) {
2395 @(posedge m1.$rxclk); clock_counter = clock_counter + 1;
2396 }
2397 }
2398 2: if (port_speed == 4) {
2399 } else if (port_speed == 3) {
2400 while(1) {
2401 @(posedge gm2.$rxclk); clock_counter = clock_counter + 1;
2402 }
2403 } else {
2404 while(1) {
2405 @(posedge m2.$rxclk); clock_counter = clock_counter + 1;
2406 }
2407 }
2408 3: if (port_speed == 4) {
2409 } else if (port_speed == 3) {
2410 while(1) {
2411 @(posedge gm3.$rxclk); clock_counter = clock_counter + 1;
2412 }
2413 } else {
2414 while(1) {
2415 @(posedge m3.$rxclk); clock_counter = clock_counter + 1;
2416 }
2417 }
2418 }
2419}
2420
2421
2422task pg::config_tx (mii_def port_bind, integer mac_speed ) {
2423 if(mac_speed == 10000) port_bind.$rx_config = 4;
2424 else
2425 if(mac_speed == 1000) port_bind.$rx_config = 3;
2426 else
2427 if(mac_speed == 100) port_bind.$rx_config = 2;
2428 else port_bind.$rx_config = 1;
2429
2430 if(mac_speed == 10000) port_speed = 4;
2431 else
2432 if(mac_speed == 1000) port_speed = 3;
2433 else
2434 if(mac_speed == 100) port_speed = 2;
2435 else port_speed = 1;
2436
2437
2438 if(mac_speed == 10000) {
2439 port_bind.$rxdv = 1;
2440 } else {
2441 port_bind.$rxdv = 0;
2442 }
2443
2444 port_bind.$rxd = 07;
2445 port_bind.$rxerr = 0;
2446 port_bind.$rxcrs = 0;
2447 port_bind.$rxcol = 0;
2448}
2449
2450
2451function bit [31:0] pg::crc_gen(byte_array p, integer start, integer len) {
2452 bit [31:0] tmp0, poly;
2453 integer i;
2454
2455 //printf("CRC Function is called \n");
2456
2457 tmp0 = 32'hffff_ffff;
2458
2459 for(i=start;i<len;i=i+1) begin
2460 tmp0 = crc32_add( p.val[i], tmp0 );
2461 end
2462 tmp0 = ~tmp0;
2463
2464
2465 for(i=0;i<32;i=i+1)
2466 crc_gen[i] = tmp0[31-i];
2467
2468 tmp0 = crc_gen;
2469 crc_gen[31:24] = tmp0[07:00];
2470 crc_gen[23:16] = tmp0[15:08];
2471 crc_gen[15:08] = tmp0[23:16];
2472 crc_gen[07:00] = tmp0[31:24];
2473
2474}
2475
2476
2477task pg::status() {
2478 printf("\n");
2479 printf("------------------------------\n");
2480 printf("PG[%0d]: Status Report:\n",my_port);
2481 printf(" Encountered %0d ERRORS\n",error_count);
2482 printf(" Encountered %0d WARNINGS\n",warning_count);
2483 printf(" Sent %0d packets\n",pckt_num);
2484 printf("------------------------------\n\n");
2485}
2486
2487
2488
2489
2490
2491task pg::config(integer what, bit [31:0] data) {
2492 cfg_reg[what] = data;
2493}
2494
2495
2496task pg::print_warn() {
2497 printf("WARNING: Packet Generator[%0d]: ", my_port);
2498}
2499
2500
2501task pg::print_err() {
2502 printf("ERROR: Packet Generator[%0d] time:%0d : ", my_port, {get_time(HI), get_time(LO)});
2503}
2504
2505task pg::display_buf( byte_array buf, integer hwlen, (integer ifedx=0)) {
2506 integer ptr=0;
2507 integer tunneling_ipv4 = 0;
2508 integer tunneling_ipv6 = 0;
2509 integer ah_transp_ipv4 = 0;
2510 integer ah_transp_ipv6 = 0;
2511 integer esp_transp_ipv4 = 0;
2512 integer esp_transp_ipv6 = 0;
2513 integer ipv4_header_length;
2514
2515 integer buf_shift;
2516 integer n;
2517 integer i;
2518
2519 bit [15:0] len;
2520 bit [7:0] flag_bit;
2521 bit [79:0] id;
2522 integer token;
2523
2524 printf("\n\n______________________________________________________________\n");
2525 printf("vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n\n");
2526
2527
2528 printf("____________ Hex Dump ____________\n");
2529 for(n=0;n<hwlen;n++) {
2530 if( !(n % 16) ) printf("\n%d: ",n);
2531 printf("%h ", buf.val[ptr++]);
2532 }
2533 printf("\n__________________________________\n\n");
2534
2535 ptr=0;
2536
2537 printf(" L2 Header\n");
2538 printf("+---------------\n");
2539 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++] );
2540 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++] );
2541
2542 len = {buf.val[ptr++], buf.val[ptr++]};
2543
2544 if( len == TPID_8021Q ) {
2545 if( {buf.val[ptr+4], buf.val[ptr+5], buf.val[ptr+6]} == LLC_SNAP ) {
2546 printf("| L2 Header Type: 802.1Q Tagged LLC-SNAP Ethernet Header\n");
2547 printf("| TPID: %0h\n", len );
2548 printf("| TCI: %h\n", {buf.val[ptr++], buf.val[ptr++]} );
2549 len = {buf.val[ptr++], buf.val[ptr++]};
2550 printf("| LEN/TYPE: 0x%h(%0d)\n", len, len );
2551 printf("| LLC: %h\n", {buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] });
2552 printf("| SNAP: %h\n", {buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } );
2553 len = {buf.val[ptr - 2], buf.val[ptr - 1]};
2554 } else { // if not LLC SNAP
2555 printf("| L2 Header Type: 802.1Q Tagged Ethernet Header\n");
2556 printf("| TPID: %0h\n", len );
2557 printf("| TCI: %h\n", {buf.val[ptr++], buf.val[ptr++]} );
2558 len = {buf.val[ptr++], buf.val[ptr++]};
2559 printf("| TYPE/LEN: 0x%h(%d)\n", len, len);
2560 }
2561 }/*endifTPID_8021Q*/ else if ( len == CNTL_FRAME ) {
2562 printf("| L2 Header Type: MAC Control Frame Header\n");
2563 printf("| Type: %h\n", len );
2564 } else { // endif control frame
2565 if( {buf.val[ptr], buf.val[ptr+1], buf.val[ptr+2]} == LLC_SNAP ) {
2566 printf("| L2 Header Type: LLC-SNAP Ethernet Header\n");
2567 printf("| Data Length: 0x%h(%0d)\n", len, len);
2568 printf("| LLC: %h\n", {buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] });
2569 printf("| SNAP: %h\n", {buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } );
2570 if( buf.val[ptr-2] == 8'h08 ) {
2571 ptr +=20;
2572 if( buf.val[ptr - 11 ] == TCP_PROTO){
2573 ptr +=20;
2574 }
2575 }
2576 if( buf.val[ptr-2] == 8'h86 ) { ptr +=40;
2577 if( buf.val[ptr - 34 ] == TCP_PROTO){
2578 ptr +=20;
2579 }
2580 }
2581 } /*endif LLC_SANP*/ else {
2582 printf("| L2 Header Type: 802.3 Ethernet Header\n");
2583 printf("| Data Length/Type: 0x%h(%0d)\n", len, len);
2584 }
2585 } // endif!TPID_8021Q
2586
2587 if( ((buf.val[ptr] & 8'h40)==8'h40 ) & ( (buf.val[ptr] & 8'hf)>5)) {
2588
2589 ipv4_header_length = (buf.val[ptr] & 8'hf);
2590
2591 token = { buf.val[ptr + ( (4*ipv4_header_length) -20 ) ], buf.val[ptr + ( (4*ipv4_header_length) -20 ) +1] };
2592
2593 } else
2594 token = { buf.val[ptr], buf.val[ptr+1] };
2595
2596 printf(" DEBUG- token - %d \n",token);
2597
2598 if((len>16'h0600 & len != CNTL_FRAME) || ((len == RARP_FRAME) &(len != CNTL_FRAME))){
2599 len = -1;
2600// ptr here points to the first byte of ip datagram
2601 if((buf.val[ptr - 2 ] == 8'h08 ) || (( buf.val[ptr-2] == 8'h80) && (buf.val[ptr-1] == 8'h35))) { // IP datagram or RARP
2602 if( buf.val[ptr + 9] == AH_PROTO) {
2603 printf("+-------------------------------------\n");
2604 printf(" L3 Header-- Type: IPv4, IPSec: AH\n");
2605 printf("+--------------------------------------\n");
2606 ah_transp_ipv4 = 1;
2607 } else if( buf.val[ptr + 9] == ESP_PROTO) {
2608 printf("+-------------------------------------\n");
2609 printf(" L3 Header-- Type: IPv4, IPSec: ESP\n");
2610 printf("+--------------------------------------\n");
2611 esp_transp_ipv4 = 1;
2612 } else if( buf.val[ptr + 9] == IP_V4_PROTO) {
2613 printf("+-------------------------------------\n");
2614 printf(" L3 Header-- Type: Tunnel (IPv4/IPv4)\n");
2615 printf("+--------------------------------------\n");
2616 printf("| IP Header Tunnel Layer 1: IPv4\n| \n");
2617 tunneling_ipv4 = 1;
2618 } else if( buf.val[ptr + 9] == IP_V6_PROTO) {
2619 printf("+-------------------------------------\n");
2620 printf(" L3 Header-- Type: Tunnel (IPv4/IPv6)\n");
2621 printf("+--------------------------------------\n");
2622 printf("| IP Header Tunnel Layer 1: IPv4\n| \n");
2623 tunneling_ipv6 = 1;
2624 } else {
2625 printf("+-------------------------------------\n");
2626 printf(" L3 Header-- Type: IPv4\n");
2627 printf("+--------------------------------------\n");
2628 }
2629 ipv4_header_length = (buf.val[ptr] & 8'hf);
2630 // printf("DEBUG- ipv4_header_length - %d \n",ipv4_header_length);
2631 ptr--;
2632 ptr--;
2633//ptr here points to type/len field
2634 display_class(buf, ptr);
2635// looks like display class increments the ptr to the beginning of IP src address..
2636
2637 printf("| IPV4 Payload Len: %h%h\n", buf.val[ptr-10], buf.val[ptr-9] );
2638 printf("| IPV4 Checksum: %h%h\n", buf.val[ptr-2], buf.val[ptr-1] );
2639 if(ipv4_header_length>5) {
2640 printf("| IPV4 Header Length: %d \n", ipv4_header_length);
2641 }
2642 printf("| IP SRC Address: %h.%h.%h.%h\n", buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] );
2643 printf("| IP DST Address: %h.%h.%h.%h\n", buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] );
2644 for(i=0;i< (ipv4_header_length -5); i ++) {
2645 printf("| IP Options: %h.%h.%h.%h\n", buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] );
2646 }
2647 if (esp_transp_ipv4) {
2648 printf("| ESP SPI : %h.%h.%h.%h\n", buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] );
2649 }
2650
2651 if (ah_transp_ipv4) {
2652 ptr += 4;
2653 printf("| AH SPI : %h.%h.%h.%h\n", buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] );
2654 }
2655
2656 if( tunneling_ipv4 ) {
2657 printf("| ----------- \n|\n");
2658 printf("| IP Header Tunnel Layer 2: IPv4:\n");
2659 printf("| \n");
2660 ptr--;
2661 ptr--;
2662 display_class(buf, ptr);
2663 printf("| IP SRC Address: %h.%h.%h.%h\n", buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] );
2664 printf("| IP DST Address: %h.%h.%h.%h\n", buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] );
2665 } else if( tunneling_ipv6) {
2666 printf("| ----------- \n|\n");
2667 printf("| IP Header Tunnel Layer 2: IPv6:\n");
2668 printf("| \n");
2669 ptr--;
2670 ptr--;
2671 display_class_ipv6(buf, ptr);
2672 printf("| Payload Len: 0x%h(%d)\n", buf.val[ptr++], buf.val[ptr++]);
2673 printf("| Next Header: 0x%h\n", buf.val[ptr++]);
2674 printf("| Hop Limit : 0x%h\n", buf.val[ptr++]);
2675 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++],
2676 buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++],
2677 buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] );
2678
2679 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++],
2680 buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++],
2681 buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] );
2682 }
2683
2684
2685 if( tunneling_ipv6 )
2686 buf_shift = 34;
2687 else
2688 buf_shift = 11 + 4*(ipv4_header_length -5) ;
2689
2690
2691 if( buf.val[ptr - buf_shift ] == UDP_PROTO) {
2692 printf("+-------------------------------------\n");
2693 printf(" L4 Header-- Type: UDP \n");
2694 printf("+--------------------------------------\n");
2695 printf("| UDP SRC Port: %h\n", {buf.val[ptr++], buf.val[ptr++]} );
2696 printf("| UDP DST Port: %h\n", {buf.val[ptr++], buf.val[ptr++]} );
2697 printf("| UDP LEN : %h\n", {buf.val[ptr++], buf.val[ptr++]} );
2698 printf("| UDP Chksum : %h\n", {buf.val[ptr++], buf.val[ptr++]} );
2699
2700 // - ptr here is the first byte of UDP data
2701 token = { buf.val[ptr + 0], buf.val[ptr + 1] };
2702 printf(" DEBUG- UDP token - %d \n",token);
2703
2704 } else if( buf.val[ptr - buf_shift ] == TCP_PROTO) {
2705 printf("+-------------------------------------\n");
2706 printf(" L4 Header-- Type: TCP\n");
2707 printf("+--------------------------------------\n");
2708 printf("| TCP SRC Port: %h\n", {buf.val[ptr++], buf.val[ptr++]} );
2709 printf("| TCP DST Port: %h\n", {buf.val[ptr++], buf.val[ptr++]} );
2710 printf("| TCP Sequence #: %h\n", {buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++]} );
2711 printf("| TCP ACK #: %h\n", {buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++]} );
2712
2713 ptr += 1;
2714 flag_bit = buf.val[ptr++];
2715 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]);
2716 printf("| Window Size: %h\n", {buf.val[ptr++], buf.val[ptr++]});
2717 printf("| TCP Checksum: %h\n", {buf.val[ptr++], buf.val[ptr++]});
2718
2719 if(cfg_reg[CFG_TCP_LEN] > 5 ) { //
2720 printf("| TCP Option : ");
2721 ptr = ptr + 2;
2722 for(n=0; n<(cfg_reg[CFG_TCP_LEN]-5); n++) {
2723 printf("%h%h%h%h ", buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++]);
2724 }
2725 printf("\n");
2726 ptr = ptr - 2;
2727 } // end if checking option value
2728 printf("+---------------\n");
2729 // - ptr here is the first byte of TCP data
2730 token = { buf.val[ptr + 2], buf.val[ptr+3] };
2731 printf(" DEBUG- TCP token ptr - %d - %d \n",token,ptr);
2732 } else if (esp_transp_ipv4) {
2733 ptr += 8;
2734 token = { buf.val[ptr], buf.val[ptr+1] };
2735 } else if (ah_transp_ipv4) {
2736 ptr += 4;
2737 token = { buf.val[ptr], buf.val[ptr+1] };
2738 } else {
2739 token = { buf.val[ptr], buf.val[ptr+1] };
2740 }
2741 } /*endif IP datagram or RARP*/ else { /*IPV6*/
2742 if( buf.val[ptr + 6] == AH_PROTO) {
2743 printf("+-------------------------------------\n");
2744 printf(" L3 Header-- Type: IPv6, IPSec: AH\n");
2745 printf("+--------------------------------------\n");
2746 ah_transp_ipv6 = 1;
2747 } else if( buf.val[ptr + 6] == ESP_PROTO) {
2748 printf("+-------------------------------------\n");
2749 printf(" L3 Header-- Type: IPv6, IPSec: ESP\n");
2750 printf("+--------------------------------------\n");
2751 esp_transp_ipv6 = 1;
2752 } else if( buf.val[ptr + 6] == IP_V4_PROTO) {
2753 printf("+-------------------------------------\n");
2754 printf(" L3 Header-- Type: Tunnel (IPv6/IPv4)\n");
2755 printf("+--------------------------------------\n");
2756 printf("| IP Header Tunnel Layer 1: IPv6\n");
2757 printf("| \n");
2758 tunneling_ipv4 = 1;
2759 } else if( buf.val[ptr + 6] == IP_V6_PROTO) {
2760 printf("+-------------------------------------\n");
2761 printf(" L3 Header-- Type: Tunnel (IPv6/IPv6)\n");
2762 printf("+--------------------------------------\n");
2763 printf("| IP Header Tunnel Layer 1: IPv6\n");
2764 printf("| \n");
2765 tunneling_ipv6 = 1;
2766 } else {
2767 printf("+-------------------------------------\n");
2768 printf(" L3 Header-- Type: IPv6\n");
2769 printf("+--------------------------------------\n");
2770 }
2771 ptr--;
2772 ptr--;
2773
2774 display_class_ipv6(buf, ptr);
2775 printf("| Payload Len: 0x%h(%d)\n", buf.val[ptr++], buf.val[ptr++]);
2776 printf("| Next Header: 0x%h\n", buf.val[ptr++]);
2777 printf("| Hop Limit : 0x%h\n", buf.val[ptr++]);
2778 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++],
2779 buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++],
2780 buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] );
2781 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++],
2782 buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++],
2783 buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] );
2784
2785 if (esp_transp_ipv6) {
2786 printf("| ESP SPI : %h.%h.%h.%h\n", buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] );
2787 }
2788 if (ah_transp_ipv6) {
2789 ptr += 4;
2790 printf("| AH SPI : %h.%h.%h.%h\n", buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] );
2791 }
2792
2793 if( tunneling_ipv4 ) {
2794 printf("| ----------- \n|\n");
2795 printf("| IP Header Tunnel Layer 2: IPv4:\n");
2796 printf("| \n");
2797 ptr--;
2798 ptr--;
2799 display_class(buf, ptr);
2800 printf("| IP SRC Address: %h.%h.%h.%h\n", buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] );
2801 printf("| IP DST Address: %h.%h.%h.%h\n", buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] );
2802
2803 } else if( tunneling_ipv6) {
2804 printf("| ----------- \n|\n");
2805 printf("| IP Header Tunnel Layer 2: IPv6:\n");
2806 printf("| \n");
2807 ptr--;
2808 ptr--;
2809 display_class_ipv6(buf, ptr);
2810 printf("| Payload Len: 0x%h(%d)\n", buf.val[ptr++], buf.val[ptr++]);
2811 printf("| Next Header: 0x%h\n", buf.val[ptr++]);
2812 printf("| Hop Limit : 0x%h\n", buf.val[ptr++]);
2813 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++],
2814 buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++],
2815 buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] );
2816 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++],
2817 buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++],
2818 buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] );
2819 }
2820
2821 if( tunneling_ipv4 )
2822 buf_shift = 11 + 4*(ipv4_header_length -5) ;
2823 // buf_shift = 11;
2824 else
2825 buf_shift = 34;
2826 if( buf.val[ptr - buf_shift ] == UDP_PROTO) {
2827 printf("+-------------------------------------\n");
2828 printf(" L4 Header-- Type: UDP \n");
2829 printf("+--------------------------------------\n");
2830 printf("| UDP SRC Port: %h\n", {buf.val[ptr++], buf.val[ptr++]} );
2831 printf("| UDP DST Port: %h\n", {buf.val[ptr++], buf.val[ptr++]} );
2832 printf("| UDP LEN : %h\n", {buf.val[ptr++], buf.val[ptr++]} );
2833 printf("| UDP Chksum : %h\n", {buf.val[ptr++], buf.val[ptr++]} );
2834
2835 token = { buf.val[ptr + 0], buf.val[ptr + 1] };
2836 } else if( buf.val[ptr - buf_shift ] == TCP_PROTO) {
2837 printf("+-------------------------------------\n");
2838 printf(" L4 Header-- Type: TCP\n");
2839 printf("+--------------------------------------\n");
2840 printf("| TCP SRC Port: %h\n", {buf.val[ptr++], buf.val[ptr++]} );
2841 printf("| TCP DST Port: %h\n", {buf.val[ptr++], buf.val[ptr++]} );
2842 printf("| TCP Sequence #: %h\n", {buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++]} );
2843 printf("| TCP ACK #: %h\n", {buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++]} );
2844 ptr += 1;
2845 flag_bit = buf.val[ptr++];
2846 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]);
2847 printf("| Window Size: %h\n", {buf.val[ptr++], buf.val[ptr++]});
2848 printf("| TCP Checksum: %h\n", {buf.val[ptr++], buf.val[ptr++]});
2849 if(cfg_reg[CFG_TCP_LEN] > 5 ) {
2850 printf("| TCP Option : ");
2851 ptr = ptr + 2;
2852 for(n=0; n<(cfg_reg[CFG_TCP_LEN]-5); n++) {
2853 printf("%h%h%h%h ", buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++]);
2854 }
2855 printf("\n");
2856 ptr = ptr - 2;
2857 }
2858 printf("+---------------\n");
2859 token = { buf.val[ptr + 2], buf.val[ptr+3] };
2860 } else if (esp_transp_ipv6) {
2861 ptr += 8;
2862 token = { buf.val[ptr], buf.val[ptr+1] };
2863 } else if (ah_transp_ipv6) {
2864 ptr += 4;
2865 token = { buf.val[ptr], buf.val[ptr+1] };
2866 } else {
2867 token = { buf.val[ptr], buf.val[ptr+1] };
2868 }
2869 }
2870 } /*end if((len>16'h0600 & len != CNTL_FRAME) || ((len == RARP_FRAME) &(len != CNTL_FRAME))) */
2871
2872 if(len<0) len = hwlen;
2873
2874 printf("\npg::display_buf Time: %0d\n",{get_time(HI),get_time(LO)});
2875 printf("Token: %0d\n", token);
2876 printf("\n");
2877 display_data(buf, ptr, hwlen-ptr-4 );
2878 printf("\n");
2879 printf("CRC: %h\n", { buf.val[ptr++], buf.val[ptr++], buf.val[ptr++], buf.val[ptr++] } );
2880 printf("\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n");
2881 printf("--------------------------------------------------------------\n\n");
2882
2883}
2884
2885
2886task pg::display_class(byte_array buf, var integer ptr) {
2887 integer n,last;
2888 last = ptr+14;
2889 printf("| Class: ");
2890 for(n=0;n<14;n++) printf("%h ", buf.val[ptr+n] );
2891 printf("\n");
2892 if( {buf.val[ptr], buf.val[ptr+1]} < 16'h0600)
2893 printf("| Length: %0d\n|\n", {buf.val[ptr++], buf.val[ptr++]} );
2894 else
2895 printf("| Type: %0h\n|\n", {buf.val[ptr++], buf.val[ptr++]} );
2896 ptr=last;
2897}
2898
2899
2900task pg::display_class_ipv6(byte_array buf, var integer ptr) {
2901 integer n,last;
2902
2903 last = ptr+6;
2904
2905 printf("| Class: ");
2906
2907
2908 for(n=0;n<10;n++) printf("%h ", buf.val[ptr+n] );
2909 printf("\n");
2910
2911 if( {buf.val[ptr], buf.val[ptr+1]} < 16'h0600)
2912 printf("| Length: %0d\n|\n", {buf.val[ptr++], buf.val[ptr++]} );
2913 else
2914 printf("| Type: %0h\n|\n", {buf.val[ptr++], buf.val[ptr++]} );
2915
2916 ptr=last;
2917}
2918
2919
2920
2921task pg::display_data(byte_array buf, var integer ptr, integer len) {
2922 integer n;
2923
2924 printf(" Data:\n");
2925 printf("+---------------");
2926
2927 if(len<1)
2928 printf("\n| No Payload ...");
2929 else
2930
2931 for(n=0;n< len ;n++) {
2932 if( !(n % 16) ) printf("\n| %d: ",n);
2933 printf("%h ", buf.val[ptr++]);
2934 }
2935 printf("\n+---------------\n");
2936}
2937
2938
2939task pg::display_id(bit [79:0] id) {
2940
2941 printf(" ID Tags:\n");
2942 printf("+---------------\n");
2943 printf("| Src port: %0d\n", id[79:75] );
2944 printf("| Dst port: %0h\n", id[74:35] );
2945 printf("| Order Type: %0h\n", id[34:33] );
2946 printf("| Order Sequnce: %0d\n", id[32:27] );
2947 printf("| Packet number: %0d\n", id[26:11] );
2948 printf("| Data Type: %0d\n", id[10:8] );
2949 printf("| Data Seed: %0d\n", id[7:0] );
2950 printf("+---------------\n");
2951}
2952
2953
2954task pg::display_db(pack_db_entry pack_db ) {
2955
2956 printf("\n========== Display DB Entry %0d ========== \n",pack_db.gId);
2957 if(pack_db == null) {
2958 printf("This entry is not allocated ...\n");
2959 } else {
2960
2961 printf("\tframe.frame_type: %h\n",pack_db.frame.frame_type);
2962 printf("\tframe.frame_class: %h\n",pack_db.frame.frame_class);
2963 printf("\tframe.class_mask: %h\n",pack_db.frame.class_mask);
2964 printf("\tframe.class_funct: %h\n",pack_db.frame.class_funct);
2965 printf("\tframe.data_type: %h\n",pack_db.frame.data_type);
2966 printf("\tframe.data_seed: %h\n",pack_db.frame.data_seed);
2967 printf("\tframe.data_length: %h\n",pack_db.data_length);
2968 printf("\n");
2969 printf("\tsrc_node.l2_addr: %h\n",pack_db.src_node.l2_addr);
2970 printf("\tsrc_node.tci: %h\n",pack_db.src_node.tci);
2971 printf("\tsrc_node.ip_addr: %h\n",pack_db.src_node.ip_addr);
2972 printf("\tsrc_node.ipv6_addr: %h\n",pack_db.src_node.ipv6_addr);
2973 printf("\n");
2974 printf("\tdst_node.l2_addr: %h\n",pack_db.dst_node.l2_addr);
2975 printf("\tdst_node.tci: %h\n",pack_db.dst_node.tci);
2976 printf("\tdst_node.ip_addr: %h\n",pack_db.dst_node.ip_addr);
2977 printf("\tdst_node.ipv6_addr: %h\n",pack_db.dst_node.ipv6_addr);
2978 printf("\n");
2979 printf("\ttup.src_tcp_udp_port: %h\n",pack_db.tup.src_tcp_udp_port);
2980 printf("\ttup.dst_tcp_udp_port: %h\n",pack_db.tup.dst_tcp_udp_port);
2981 printf("\n");
2982 printf("\trcv_isn: %0h\n",pack_db.rx_param.rcv_isn);
2983 printf("\tlast_ackno: %0h\n",pack_db.rx_param.last_ackno);
2984 printf("\tadv_isn: %0h\n",pack_db.tx_param.adv_isn);
2985 printf("\tlast_seqno: %0h\n",pack_db.tx_param.last_seqno);
2986 printf("\n");
2987 printf("\torg_port: %0d\n",pack_db.org_port);
2988 printf("\torder_seq: %0d\n",pack_db.order_seq);
2989 printf("\tpckt_num: %0d\n",pack_db.pckt_num);
2990 printf("\toptions: %h\n",pack_db.options);
2991 }
2992 printf("========================================== \n\n");
2993}
2994
2995task pg::display_flow(integer flow_id) {
2996
2997 printf("\n========== Display FLOW DB Entry %0d ========== \n",flow_id);
2998 if(flow_db[flow_id] == null) {
2999 printf("This entry is not allocated ...\n");
3000 } else {
3001 printf("\tframe.data_length: %h\n",flow_db[flow_id].data_length);
3002 printf("\n");
3003 printf("\ttup.src_tcp_udp_port: %h\n",flow_db[flow_id].tup.src_tcp_udp_port);
3004 printf("\ttup.dst_tcp_udp_port: %h\n",flow_db[flow_id].tup.dst_tcp_udp_port);
3005 printf("\n");
3006 printf("\torg_port: %0d\n",flow_db[flow_id].org_port);
3007 printf("\trcv_isn: %0h\n",flow_db[flow_id].rx_param.rcv_isn);
3008 printf("\tlast_ackno: %0h\n",flow_db[flow_id].rx_param.last_ackno);
3009 printf("\tadv_isn: %0h\n",flow_db[flow_id].tx_param.adv_isn);
3010 printf("\tlast_seqno: %0h\n",flow_db[flow_id].tx_param.last_seqno);
3011
3012
3013 }
3014 printf("========================================== \n\n");
3015}
3016
3017
3018function bit[15:0] pg::partial_cksum(byte_array packet, integer start_offset, integer pkt_len) {
3019
3020 integer i;
3021 bit [16:0] chksum_tmp = 0;
3022
3023 for(i = start_offset; i < pkt_len;)
3024 {
3025 if(i == pkt_len - 1) {
3026 chksum_tmp = chksum_tmp + {packet.val[i],8'h0};
3027 chksum_tmp = chksum_tmp + chksum_tmp[16];
3028 chksum_tmp[16] = 1'b0;
3029 } else {
3030 chksum_tmp = chksum_tmp + {packet.val[i],packet.val[i+1]};
3031 chksum_tmp = chksum_tmp + chksum_tmp[16];
3032 chksum_tmp[16] = 1'b0;
3033 }
3034 i = i+2;
3035 }
3036
3037 partial_cksum = chksum_tmp[15:0];
3038
3039}
3040