Commit | Line | Data |
---|---|---|
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 | ||
50 | extern Mesg be_msg; | |
51 | ||
52 | ||
53 | // extern pack_db_entry pack_db[]; | |
54 | extern flow_db_entry flow_db[]; | |
55 | extern mbox_class mbox_id; | |
56 | extern integer quiet_on; | |
57 | extern class pg; | |
58 | extern pg ptr_to_first_pg; | |
59 | extern pg pack_gen[16]; | |
60 | ||
61 | extern "C" task InitpgSeed(integer seed); | |
62 | extern "C" function bit[31:0] pgRand(); | |
63 | ||
64 | class 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 | ||
79 | class 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 | ||
175 | task 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 | ||
268 | data_type = pack_db.frame.data_type; | |
269 | data_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 | ||
684 | function 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 | ||
710 | function 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 | ||
750 | function bit [15:0] pg::tcp_chksum( pack_db_entry pack_db, byte_array d, integer start, integer len, integer pkt_type, integer chk_sum_location ){ | |
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 | ||
912 | task 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 | ||
1034 | function 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 | } | |
1054 | task 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 | ||
1128 | task pg::build_frame(integer itoken,pack_db_entry pack_db, byte_array buf, var integer len,(integer header_id=-1),(integer new_crc=0)) { | |
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 | ||
1322 | task 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 | ||
1475 | function 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 | ||
1511 | function 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 | ||
1517 | function 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 | ||
1531 | task 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 | ||
1569 | task 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 | ||
1595 | task 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 | ||
1622 | task 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 | ||
1709 | task 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 | ||
1736 | task 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 | ||
1861 | task 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 | ||
1889 | task 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 | ||
2038 | task pg::wait_clk(integer count) { | |
2039 | repeat(count) @(posedge CLOCK); | |
2040 | } | |
2041 | ||
2042 | task 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 | } | |
2050 | task pg::wait_tx_clk_if ( mii_def port_bind, integer count) { | |
2051 | repeat(count) @(posedge port_bind.$txclk); | |
2052 | } | |
2053 | ||
2054 | task 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 | ||
2063 | task pg::wait_rx_clk_if ( mii_def port_bind, integer count) { | |
2064 | repeat(count) @(posedge port_bind.$rxclk); | |
2065 | } | |
2066 | ||
2067 | ||
2068 | task 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 | ||
2366 | task pg::count_clock() { | |
2367 | ||
2368 | // This is just a HACK to get going | |
2369 | clock_counter = 0; | |
2370 | case(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 | ||
2422 | task 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 | ||
2451 | function 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 | ||
2477 | task 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 | ||
2491 | task pg::config(integer what, bit [31:0] data) { | |
2492 | cfg_reg[what] = data; | |
2493 | } | |
2494 | ||
2495 | ||
2496 | task pg::print_warn() { | |
2497 | printf("WARNING: Packet Generator[%0d]: ", my_port); | |
2498 | } | |
2499 | ||
2500 | ||
2501 | task pg::print_err() { | |
2502 | printf("ERROR: Packet Generator[%0d] time:%0d : ", my_port, {get_time(HI), get_time(LO)}); | |
2503 | } | |
2504 | ||
2505 | task 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 | ||
2886 | task 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 | ||
2900 | task 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 | ||
2921 | task 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 | ||
2939 | task 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 | ||
2954 | task 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 | ||
2995 | task 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 | ||
3018 | function 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 |