Commit | Line | Data |
---|---|---|
86530b38 AT |
1 | // ========== Copyright Header Begin ========================================== |
2 | // | |
3 | // OpenSPARC T2 Processor File: mac_mon.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 | #include "mac_mon_if.vri" | |
37 | //#include "cMesg.vrh" | |
38 | ||
39 | // constants that needs to be varied based on observations | |
40 | #define MAC_MON_TIMESCALE_ADJUST 1 // to make it nsec | |
41 | ||
42 | // getting the following defines from plus args way. | |
43 | ||
44 | ||
45 | extern bit [3:0] rtl_mac; | |
46 | extern bit reset_complete; | |
47 | extern event RX_chk_done; | |
48 | extern event TX_rvcd_allpkts[4]; | |
49 | //extern Mesg be_msg; | |
50 | ||
51 | class MacMonitorStats { | |
52 | ||
53 | string name = "MacMonStats"; | |
54 | integer time_offset = -1; | |
55 | ||
56 | integer index=0; // also can be used as pkt count | |
57 | ||
58 | // counters for each transaction | |
59 | bit [63:0] raw_time_stamp[1024*16]; | |
60 | bit [63:0] raw_byte_count[1024*16]; | |
61 | bit [63:0] raw_bw[1024*16]; | |
62 | ||
63 | bit [63:0] time_stamp[]; | |
64 | bit [63:0] byte_count[]; | |
65 | ||
66 | bit [63:0] raw_bandwidth[1024*16]; | |
67 | bit [63:0] raw_total_byte_count=0; | |
68 | ||
69 | bit [3:0] status[]; | |
70 | integer moving_average_bandwidth[]; | |
71 | bit skip_flag[]; // used to skip unstable bw at the end | |
72 | ||
73 | // over all statistics after skipping start and end unsstable bandwidths | |
74 | bit [63:0] total_time=0; | |
75 | bit [63:0] total_byte_count=0; | |
76 | bit [63:0] total_bandwidth=0; | |
77 | ||
78 | integer percent_bw_skip; | |
79 | integer moving_average_window; | |
80 | ||
81 | task display_transaction((integer index = -1)); | |
82 | task display_transaction_short((integer index = -1)); | |
83 | task display_short((integer index = -1)); | |
84 | task calculate_moving_average_bandwidth(); | |
85 | task update_total_time(); | |
86 | task update_total_byte_count(); | |
87 | task update_total_bandwidth(); | |
88 | task update_raw_bandwidth(); | |
89 | function bit [63:0] get_time_in_nsec(); | |
90 | function bit [63:0] get_moving_average_time(); | |
91 | function bit [63:0] get_moving_average_byte_count(); | |
92 | function bit [63:0] get_difference(integer val1, integer val2); | |
93 | ||
94 | task new(string name_in, integer percent_bw_skip_in, integer moving_average_window_in) { | |
95 | integer i; | |
96 | name = name_in; | |
97 | percent_bw_skip = percent_bw_skip_in; | |
98 | moving_average_window = moving_average_window_in; | |
99 | } | |
100 | ||
101 | } // class MacMonitorStats | |
102 | ||
103 | // skip calculations until bandwidth stabilizes | |
104 | // Example : preBw = 20, currBw = 40, skipPercent = 10 | |
105 | // if (currBw-prevBw)*100/currBw > skipPercent) then skip bw calculations | |
106 | task MacMonitorStats::calculate_moving_average_bandwidth() { | |
107 | ||
108 | integer i; | |
109 | ||
110 | if(index<=moving_average_window) { | |
111 | skip_flag[index] = 1; | |
112 | moving_average_bandwidth[index] = 0; | |
113 | return; | |
114 | } else { | |
115 | skip_flag[index] = 0; | |
116 | } | |
117 | ||
118 | // -ve and divide by zero error | |
119 | if(get_moving_average_time()<=0) { | |
120 | moving_average_bandwidth[index] = moving_average_bandwidth[index-1]; | |
121 | skip_flag[index] = skip_flag[index-1]; | |
122 | return; | |
123 | } | |
124 | ||
125 | moving_average_bandwidth[index] = (get_moving_average_byte_count() * 1000 * 8) / // Mbps | |
126 | get_moving_average_time(); | |
127 | ||
128 | } | |
129 | ||
130 | function bit [63:0] MacMonitorStats::get_difference(integer val1, integer val2) { | |
131 | if(val1 < val2) get_difference = val2 - val1; | |
132 | else get_difference = val1 - val2; | |
133 | } | |
134 | ||
135 | function bit [63:0] MacMonitorStats::get_moving_average_time() { | |
136 | integer i; | |
137 | get_moving_average_time = 0; | |
138 | if(index<=moving_average_window) return; | |
139 | get_moving_average_time = time_stamp[index] - | |
140 | time_stamp[index-moving_average_window]; | |
141 | } | |
142 | ||
143 | function bit [63:0] MacMonitorStats::get_moving_average_byte_count() { | |
144 | integer i; | |
145 | get_moving_average_byte_count = 0; | |
146 | if(index<=moving_average_window) return; | |
147 | for(i=index-moving_average_window+1;i<=index;i++) | |
148 | get_moving_average_byte_count += byte_count[i]; | |
149 | } | |
150 | ||
151 | task MacMonitorStats::update_total_time() { | |
152 | if(index<=moving_average_window) { total_time = 0; return; } | |
153 | if(skip_flag[index]) return; | |
154 | total_time = time_stamp[index]; | |
155 | } | |
156 | ||
157 | task MacMonitorStats::update_total_byte_count() { | |
158 | if(index<moving_average_window) { total_byte_count = 0; return; } | |
159 | if(skip_flag[index]) return; | |
160 | total_byte_count += byte_count[index]; | |
161 | } | |
162 | ||
163 | task MacMonitorStats::update_total_bandwidth() { | |
164 | if(index<=moving_average_window) { total_bandwidth = 0; return; } | |
165 | if(skip_flag[index]) return; | |
166 | // -ve and divide by zero error | |
167 | if(total_time <= 0) { total_bandwidth = 0; return; } | |
168 | total_bandwidth = (total_byte_count * 1000 * 8) / total_time ; // Mbps | |
169 | if(total_bandwidth<0) { | |
170 | printf("<%0d> %s: ERROR: update_total_bandwidth: negative bandwidth detected!\n", | |
171 | get_time(LO), name); | |
172 | printf("total_bandwidth:%0d total_byte_count:%0d total_time:%0d\n", | |
173 | total_bandwidth, total_byte_count, total_time); | |
174 | } | |
175 | //printf("DEBUG: total_byte_count:%0d total_time:%0d total_bandwidth:%0d, index:%0d\n", | |
176 | // total_byte_count, total_time, total_bandwidth, index); | |
177 | } | |
178 | ||
179 | task MacMonitorStats::update_raw_bandwidth() { | |
180 | // -ve and divide by zero error | |
181 | if(get_time_in_nsec() <= 0) { raw_bandwidth[index] = 0; return; } | |
182 | raw_bandwidth[index] = (raw_total_byte_count * 1000*8) / get_time_in_nsec(); // Mbps | |
183 | if(total_bandwidth<0) { | |
184 | printf("<%0d> %s: ERROR: update_raw_bandwidth: negative bandwidth detected!\n", | |
185 | get_time(LO), name); | |
186 | printf("raw_bandwidth[%0d]:%0d raw_total_byte_count:%0d total_time:%0d\n", | |
187 | index, raw_bandwidth[index], raw_total_byte_count, get_time_in_nsec()); | |
188 | } | |
189 | } | |
190 | ||
191 | task MacMonitorStats::display_transaction((integer index_in = -1)) { | |
192 | integer i; | |
193 | if(index_in == -1) { index_in = index; } | |
194 | printf("===============================================================\n"); | |
195 | printf("<%0d> %s: transaction statistics for index:%0d\n", | |
196 | get_time(LO), name, index_in); | |
197 | printf("time_stamp:%0d usec, length:%0d, status:%0d, skip_flag[%0d]:%b, rawBw:%0d\n", | |
198 | time_stamp[index_in], byte_count[index_in], | |
199 | status[index_in], index_in, skip_flag[index_in], raw_bandwidth[index_in]); | |
200 | printf("tot_time:%0d usce tot_byte_cnt:%0d, tot_bw:%0d Mbps, MA_bw:%0d Mbps\n", | |
201 | total_time, total_byte_count, total_bandwidth, moving_average_bandwidth[index_in]); | |
202 | printf("===============================================================\n"); | |
203 | } | |
204 | ||
205 | task MacMonitorStats::display_transaction_short((integer index_in = -1)) { | |
206 | integer i; | |
207 | bit [63:0] bits=0, time_diff; | |
208 | integer moving_average_window_for_display; | |
209 | if(index_in == -1) { index_in = index; } | |
210 | ||
211 | if(index_in < (moving_average_window*2)) { | |
212 | raw_bw[index_in] = 0; | |
213 | } | |
214 | else { | |
215 | for(i=moving_average_window;i<=index_in-moving_average_window-1;i++) { | |
216 | bits += raw_byte_count[i]*8; | |
217 | } | |
218 | // Equation | |
219 | // BW = SumOfLengths(MAW, index-MAW-1) / differenceInTime(index-MAW, MAW) | |
220 | // | |
221 | ||
222 | time_diff = raw_time_stamp[index_in-moving_average_window] - | |
223 | raw_time_stamp[moving_average_window]; | |
224 | ||
225 | // divide by zero error | |
226 | if(time_diff <= 0) { | |
227 | raw_bw[index_in] = 0; | |
228 | } else { | |
229 | raw_bw[index_in] = (bits*1000) / time_diff; | |
230 | } | |
231 | } | |
232 | ||
233 | ||
234 | if(index_in-moving_average_window < 0) { | |
235 | moving_average_window_for_display = index_in; | |
236 | } else { | |
237 | moving_average_window_for_display = moving_average_window; | |
238 | } | |
239 | ||
240 | printf("<%0d> %s: index:%0d, start_time:%0d (ns), end_time:%0d (ns), lenght:%0d (bits), bw:%0d (Mbps)\n", | |
241 | get_time(LO), name, index_in, raw_time_stamp[moving_average_window_for_display], | |
242 | raw_time_stamp[index_in-moving_average_window_for_display], bits, raw_bw[index_in] ); | |
243 | } | |
244 | ||
245 | task MacMonitorStats::display_short((integer index_in = -1)) { | |
246 | integer i; | |
247 | if(index_in == -1) { index_in = index; } | |
248 | if(index_in == 0) { | |
249 | printf("================= stats for %s ==================\n", name); | |
250 | printf("index\tbyteCnt\ttime-us\tTotBw\tMA_BW\tskpFlg\tRawBw\tname:%0s\n", name); | |
251 | } | |
252 | ||
253 | printf("%0d\t%0d\t%0d\t%0d\t%0d\t%b\t%0d\t%s\n", | |
254 | index_in,total_byte_count,total_time,total_bandwidth, | |
255 | moving_average_bandwidth[index_in], | |
256 | skip_flag[index_in],raw_bandwidth[index_in],name); | |
257 | } | |
258 | ||
259 | function bit [63:0] MacMonitorStats::get_time_in_nsec() { | |
260 | if(time_offset == -1) { get_time_in_nsec = 0; time_offset = get_time(LO);} | |
261 | else get_time_in_nsec = (get_time(LO)-time_offset) / MAC_MON_TIMESCALE_ADJUST; | |
262 | } | |
263 | ||
264 | class MacMonitor { | |
265 | ||
266 | integer debugLevel; | |
267 | string name = "MAC_MON"; | |
268 | bit [3:0] valid_mac_ports; // from vera_top.vr @ env/vera/top/vera_top.vr | |
269 | integer total_port_weights; | |
270 | integer percent_bw_skip; | |
271 | integer moving_average_window; | |
272 | integer index; | |
273 | integer total_num_packets_per_port = 0; | |
274 | integer total_num_valid_mac_ports = 0; | |
275 | integer report_bandwidth_mismatch_error = 0; | |
276 | integer number_of_pkts_sent[4]; | |
277 | integer number_of_pkts_rcvd[4]; | |
278 | integer prev_length[4]; | |
279 | string direction = "Rx"; // Tx/Rx | |
280 | ||
281 | //mac_mon_port myPort; | |
282 | MacMonitorStats macMonStats[]; // index is: 0: port0 | |
283 | // ........ | |
284 | // 3: port3 | |
285 | // 4: dma0 | |
286 | // ........ | |
287 | // 19: dma15 | |
288 | // 20: total | |
289 | ||
290 | task run4everMonitorMacInterface(mac_mon_port myPort, bit[1:0] port_num, bit dv_asserted_high); | |
291 | function bit [63:0] diff_values(integer val1, integer val2); | |
292 | task display_results(); | |
293 | task new ((integer debugLevelIn = 10), (string directionIn = "Rx")); | |
294 | task store_transactions(bit [1:0] port_num, | |
295 | bit [4:0] dma_num, | |
296 | bit [13:0] length, | |
297 | bit [3:0] status); | |
298 | task report_bandwidth((bit one_time = 0)); | |
299 | task report_bandwidth_periodically((integer period /*in us*/ = 100)); | |
300 | ||
301 | } // class MacMonitor | |
302 | ||
303 | task MacMonitor::new ((integer debugLevelIn = 10), (string directionIn = "Rx")) { | |
304 | ||
305 | string name_tmp; | |
306 | integer i; | |
307 | direction = directionIn; | |
308 | debugLevel = debugLevelIn; | |
309 | //myPort = mac_mon_port_bind; | |
310 | ||
311 | sprintf(name,"%s:%s", name, direction); | |
312 | ||
313 | while(reset_complete == 0) { repeat(100) @(posedge CLOCK); } | |
314 | ||
315 | if(get_plus_arg(CHECK,"MAC_MON_PERCENT_BW_SKIP=")) | |
316 | percent_bw_skip = get_plus_arg(NUM,"MAC_MON_PERCENT_BW_SKIP="); | |
317 | else | |
318 | percent_bw_skip = 30; // default | |
319 | ||
320 | if(get_plus_arg(CHECK,"MAC_MON_MV_AVG_WINDOW=")) | |
321 | moving_average_window = get_plus_arg(NUM,"MAC_MON_MV_AVG_WINDOW="); | |
322 | else | |
323 | moving_average_window = 30; // default | |
324 | ||
325 | if(get_plus_arg(CHECK,"MAC_MON_ENABLE_BANDWIDTH_MISMATCH_ERROR")) | |
326 | report_bandwidth_mismatch_error = 1; | |
327 | else | |
328 | report_bandwidth_mismatch_error = 0; // default | |
329 | ||
330 | for(index=0;index<=3;index++) { | |
331 | if(index>=0 && index<4) { sprintf(name_tmp,"macMon%0sPort%0dStats", direction, index); } | |
332 | macMonStats[index] = new(name_tmp, percent_bw_skip, moving_average_window); | |
333 | } | |
334 | ||
335 | // default values | |
336 | number_of_pkts_sent[0] = 0; | |
337 | number_of_pkts_sent[1] = 0; | |
338 | number_of_pkts_sent[2] = 0; | |
339 | number_of_pkts_sent[3] = 0; | |
340 | ||
341 | number_of_pkts_rcvd[0] = 0; | |
342 | number_of_pkts_rcvd[1] = 0; | |
343 | number_of_pkts_rcvd[2] = 0; | |
344 | number_of_pkts_rcvd[3] = 0; | |
345 | ||
346 | prev_length[0] = 0; | |
347 | prev_length[1] = 0; | |
348 | prev_length[2] = 0; | |
349 | prev_length[3] = 0; | |
350 | ||
351 | valid_mac_ports = rtl_mac; // from vera_top.vr @ env/vera/top/vera_top.vr | |
352 | ||
353 | for(i=0;i<4;i++) | |
354 | if(valid_mac_ports[i]) | |
355 | total_num_valid_mac_ports++; | |
356 | ||
357 | // divide by zero error check | |
358 | if(total_num_valid_mac_ports <= 0) { | |
359 | printf("<%0d> %s: ERROR : total_num_packets_per_port=%0d, rtl_mac:%b\n", | |
360 | get_time(LO), name, total_num_packets_per_port, rtl_mac); | |
361 | return; | |
362 | } | |
363 | ||
364 | if(get_plus_arg(CHECK,"RXMAC_PKTCNT=")) | |
365 | total_num_packets_per_port = get_plus_arg(NUM,"RXMAC_PKTCNT=")/total_num_valid_mac_ports; | |
366 | ||
367 | if(get_plus_arg(CHECK,"RXMAC_PORT0_PKTCNT=")) | |
368 | number_of_pkts_sent[0] = get_plus_arg(NUM,"RXMAC_PORT0_PKTCNT="); | |
369 | if(get_plus_arg(CHECK,"RXMAC_PORT1_PKTCNT=")) | |
370 | number_of_pkts_sent[1] = get_plus_arg(NUM,"RXMAC_PORT1_PKTCNT="); | |
371 | if(get_plus_arg(CHECK,"RXMAC_PORT2_PKTCNT=")) | |
372 | number_of_pkts_sent[2] = get_plus_arg(NUM,"RXMAC_PORT2_PKTCNT="); | |
373 | if(get_plus_arg(CHECK,"RXMAC_PORT3_PKTCNT=")) | |
374 | number_of_pkts_sent[3] = get_plus_arg(NUM,"RXMAC_PORT3_PKTCNT="); | |
375 | ||
376 | for(i=0;i<4;i++) | |
377 | if(!valid_mac_ports[i]) | |
378 | number_of_pkts_sent[i] = 0; | |
379 | ||
380 | // divide by zero error | |
381 | if(total_port_weights <= 0) { total_port_weights = 1; } | |
382 | ||
383 | ||
384 | printf("<%0d> %s: ====================== instantiating ... ====================\n", | |
385 | get_time(LO), name); | |
386 | printf("%s moving average window:%0d, skip percentage :%0d, valid_mac_ports:%b\n", | |
387 | name, moving_average_window, percent_bw_skip, valid_mac_ports); | |
388 | printf("<%0d> %s: ====================== instantiating done ===================\n", | |
389 | get_time(LO), name); | |
390 | ||
391 | fork | |
392 | // Rx | |
393 | if(valid_mac_ports[0] && (direction == "Rx")) { | |
394 | run4everMonitorMacInterface(mac_mon_m0_rx_bind, 0, 0); | |
395 | } | |
396 | if(valid_mac_ports[1] && (direction == "Rx")) { | |
397 | run4everMonitorMacInterface(mac_mon_m1_rx_bind, 1, 0); | |
398 | } | |
399 | // Tx | |
400 | if(valid_mac_ports[0] && (direction == "Tx")) { | |
401 | run4everMonitorMacInterface(mac_mon_m0_tx_bind, 0, 0); | |
402 | } | |
403 | if(valid_mac_ports[1] && (direction == "Tx")) { | |
404 | run4everMonitorMacInterface(mac_mon_m1_tx_bind, 1, 0); | |
405 | } | |
406 | join none | |
407 | ||
408 | fork | |
409 | report_bandwidth(); | |
410 | join none | |
411 | fork | |
412 | report_bandwidth_periodically(); | |
413 | join none | |
414 | ||
415 | } | |
416 | ||
417 | task MacMonitor::run4everMonitorMacInterface(mac_mon_port myPort, bit [1:0] port_num, bit dv_asserted_high) { | |
418 | integer collect_data = 0; | |
419 | integer packet_length = 0; | |
420 | ||
421 | while(1) { | |
422 | @(posedge myPort.$clk); | |
423 | if(dv_asserted_high == 0) { // 10G ports behavior | |
424 | if(myPort.$dv == 0) { | |
425 | collect_data = 1; | |
426 | } else { | |
427 | if(packet_length >= 64) { | |
428 | packet_length = packet_length - 7; // remove Preamble | |
429 | store_transactions(port_num, 0, packet_length, 0); | |
430 | } | |
431 | collect_data = 0; | |
432 | packet_length = 0; | |
433 | } | |
434 | } else { // 1G port behavior | |
435 | if(myPort.$dv == 1) { | |
436 | collect_data = 1; | |
437 | } else { | |
438 | if(packet_length >= 64) { | |
439 | packet_length = packet_length - 7; // remove Preamble | |
440 | store_transactions(port_num, 0, packet_length, 0); | |
441 | } | |
442 | collect_data = 0; | |
443 | packet_length = 0; | |
444 | } | |
445 | } | |
446 | ||
447 | if(collect_data == 1) { | |
448 | packet_length++; | |
449 | } | |
450 | } // while | |
451 | } | |
452 | ||
453 | task MacMonitor::store_transactions(bit [1:0] port_num, | |
454 | bit [4:0] dma_num, | |
455 | bit [13:0] length, | |
456 | bit [3:0] status) { | |
457 | integer index; | |
458 | ||
459 | ||
460 | // counters for each transaction | |
461 | printf("%s:store_transaction: port_num:%0d dma_num:%0d length:%0d time:%0d\n", | |
462 | name, port_num, dma_num, length, {get_time(HI), get_time(LO)}); | |
463 | ||
464 | // update pkt cnt | |
465 | if(prev_length[port_num] < 4096) { // Needed this since for Jumbo pkts we get 3 transations | |
466 | number_of_pkts_rcvd[port_num]++; | |
467 | prev_length[port_num] = length; | |
468 | } | |
469 | ||
470 | ||
471 | // update port stats | |
472 | index = macMonStats[port_num].index; | |
473 | macMonStats[port_num].raw_time_stamp[index] = {get_time(HI), get_time(LO)}; | |
474 | macMonStats[port_num].raw_byte_count[index] = length; | |
475 | macMonStats[port_num].time_stamp[index] = macMonStats[port_num].get_time_in_nsec(); | |
476 | macMonStats[port_num].byte_count[index] = length; | |
477 | macMonStats[port_num].raw_total_byte_count += length; | |
478 | macMonStats[port_num].status[index] = status; | |
479 | ||
480 | macMonStats[port_num].calculate_moving_average_bandwidth(); | |
481 | ||
482 | macMonStats[port_num].update_total_byte_count(); | |
483 | macMonStats[port_num].update_total_time(); | |
484 | macMonStats[port_num].update_total_bandwidth(); | |
485 | macMonStats[port_num].update_raw_bandwidth(); | |
486 | ||
487 | //macMonStats[port_num].display_transaction(); | |
488 | macMonStats[port_num].display_transaction_short(); | |
489 | macMonStats[port_num].display_short(); | |
490 | ||
491 | ||
492 | macMonStats[port_num].index++; | |
493 | ||
494 | } // task MacMonitor::store_transactions | |
495 | ||
496 | ||
497 | function bit [63:0] MacMonitor::diff_values(integer val1, integer val2) { | |
498 | if(val1 > val2) { diff_values = val1 - val2; } | |
499 | else { diff_values = val2 - val1; } | |
500 | } | |
501 | ||
502 | task MacMonitor::report_bandwidth_periodically((integer period /*in us*/ = 100)) { | |
503 | integer iterations = 1; | |
504 | printf("<%0d> %s:report_bandwidth_periodically enabled. with period:%0d us \n", | |
505 | get_time(LO), name, period); | |
506 | while(1) { | |
507 | while({get_time(HI), get_time(LO)} < | |
508 | ((period*1000/MAC_MON_TIMESCALE_ADJUST) * (iterations))) | |
509 | repeat(period) @(posedge CLOCK); | |
510 | report_bandwidth(1); | |
511 | iterations++; | |
512 | repeat(100) @(posedge CLOCK); // to avoid infinite loop | |
513 | } | |
514 | } | |
515 | ||
516 | task MacMonitor::report_bandwidth ((bit one_time = 0)) { | |
517 | integer port_pkt_length[]; | |
518 | integer port_speed[]; | |
519 | integer port_ipg[]; | |
520 | bit [63:0] port_ideal_bw[4]; | |
521 | bit [63:0] port_actual_bw[4]; | |
522 | bit [63:0] total_ideal_bw=0; | |
523 | bit [63:0] total_actual_bw=0; | |
524 | integer i; | |
525 | integer percentage_bw_to_ignore = 5; | |
526 | integer percentage_bw_difference = 0; | |
527 | ||
528 | // reset values | |
529 | for(i=0;i<4;i++) { | |
530 | port_pkt_length[i] = 64; | |
531 | if(i<2) port_speed[i] = 10000; | |
532 | if(i>1) port_speed[i] = 1000; | |
533 | port_ipg[i] = 11; | |
534 | port_ideal_bw[i] = 0; | |
535 | port_actual_bw[i] = 0; | |
536 | } | |
537 | ||
538 | // wait for test to end the sim. | |
539 | // Rx | |
540 | if(one_time == 0 && direction == "Rx") { | |
541 | printf("<%0d> %s: report_bandwidth : Waiting for RX_chk_done\n", get_time(LO), name); | |
542 | sync (ALL, RX_chk_done); | |
543 | printf("<%0d> %s: report_bandwidth : Done. Waiting for RX_chk_done\n", get_time(LO), name); | |
544 | } | |
545 | ||
546 | // Tx | |
547 | if(one_time == 0 && direction == "Tx") { | |
548 | printf("<%0d> %s: report_bandwidth : Waiting for TX_rvcd_allpkts\n", get_time(LO), name); | |
549 | if(rtl_mac[0]) { sync (ALL, TX_rvcd_allpkts[0]); } | |
550 | //if(rtl_mac[1]) { sync (ALL, TX_rvcd_allpkts[1]); } | |
551 | //if(rtl_mac[2]) { sync (ALL, TX_rvcd_allpkts[2]); } | |
552 | //if(rtl_mac[3]) { sync (ALL, TX_rvcd_allpkts[3]); } | |
553 | printf("<%0d> %s: report_bandwidth : Done. Waiting for TX_rvcd_allpkts\n", get_time(LO), name); | |
554 | } | |
555 | ||
556 | // get plus arg parameters | |
557 | if(get_plus_arg(CHECK,"MAC_SPEED0=")) | |
558 | port_speed[0] = get_plus_arg(NUM,"MAC_SPEED0="); | |
559 | ||
560 | if(get_plus_arg(CHECK,"MAC_SPEED1=")) | |
561 | port_speed[1] = get_plus_arg(NUM,"MAC_SPEED1="); | |
562 | ||
563 | if(get_plus_arg(CHECK,"MAC_SPEED2=")) | |
564 | port_speed[2] = get_plus_arg(NUM,"MAC_SPEED2="); | |
565 | ||
566 | if(get_plus_arg(CHECK,"MAC_SPEED3=")) | |
567 | port_speed[3] = get_plus_arg(NUM,"MAC_SPEED3="); | |
568 | ||
569 | if(get_plus_arg(CHECK,"MAC_PKT_LEN=")) { | |
570 | port_pkt_length[0] = get_plus_arg(NUM,"MAC_PKT_LEN="); | |
571 | port_pkt_length[1] = get_plus_arg(NUM,"MAC_PKT_LEN="); | |
572 | port_pkt_length[2] = get_plus_arg(NUM,"MAC_PKT_LEN="); | |
573 | port_pkt_length[3] = get_plus_arg(NUM,"MAC_PKT_LEN="); | |
574 | } | |
575 | ||
576 | // Over write if packets lengths are per port basis. | |
577 | if (get_plus_arg (CHECK, "MAC_PORT0_PKT_LEN")) | |
578 | port_pkt_length[0] = get_plus_arg (NUM, "MAC_PORT0_PKT_LEN"); | |
579 | if (get_plus_arg (CHECK, "MAC_PORT1_PKT_LEN")) | |
580 | port_pkt_length[1] = get_plus_arg (NUM, "MAC_PORT1_PKT_LEN"); | |
581 | if (get_plus_arg (CHECK, "MAC_PORT2_PKT_LEN")) | |
582 | port_pkt_length[2] = get_plus_arg (NUM, "MAC_PORT2_PKT_LEN"); | |
583 | if (get_plus_arg (CHECK, "MAC_PORT3_PKT_LEN")) | |
584 | port_pkt_length[3] = get_plus_arg (NUM, "MAC_PORT3_PKT_LEN"); | |
585 | ||
586 | ||
587 | if(get_plus_arg(CHECK,"PKTGEN_PORT0_10G_IPG=")) | |
588 | port_ipg[0] = get_plus_arg(NUM,"PKTGEN_PORT0_10G_IPG="); | |
589 | ||
590 | if(get_plus_arg(CHECK,"PKTGEN_PORT1_10G_IPG=")) | |
591 | port_ipg[1] = get_plus_arg(NUM,"PKTGEN_PORT1_10G_IPG="); | |
592 | ||
593 | if(get_plus_arg(CHECK,"PKTGEN_PORT2_1G_IPG=")) | |
594 | port_ipg[2] = get_plus_arg(NUM,"PKTGEN_PORT2_1G_IPG="); | |
595 | ||
596 | if(get_plus_arg(CHECK,"PKTGEN_PORT3_1G_IPG=")) | |
597 | port_ipg[3] = get_plus_arg(NUM,"PKTGEN_PORT3_1G_IPG="); | |
598 | ||
599 | // IPG correction | |
600 | for(i=0;i<4;i++) { | |
601 | port_ipg[i] += 9; // since env adds 8+1 byte ipg into actual passed value | |
602 | } | |
603 | // calculate ideal bw | |
604 | // get ideal bw | |
605 | for(i=0;i<4;i++) { | |
606 | if(rtl_mac[i]) { | |
607 | if(port_pkt_length[i]+port_ipg[i] > 0) | |
608 | port_ideal_bw[i] = (port_pkt_length[i] * port_speed[i]) / | |
609 | (port_pkt_length[i]+port_ipg[i]); | |
610 | else | |
611 | port_ideal_bw[i] = 0; | |
612 | total_ideal_bw += port_ideal_bw[i]; | |
613 | } | |
614 | } | |
615 | ||
616 | // get actual bw | |
617 | for(i=0;i<4;i++) { | |
618 | if(rtl_mac[i]) { | |
619 | if(macMonStats[i].index > 0) { | |
620 | port_actual_bw[i] = macMonStats[i].raw_bw[macMonStats[i].index-1]; | |
621 | } else { | |
622 | port_actual_bw[i] = 0; | |
623 | } | |
624 | total_actual_bw += port_actual_bw[i]; | |
625 | } | |
626 | } | |
627 | ||
628 | ||
629 | // report errors | |
630 | if(total_actual_bw <= 0) total_actual_bw = 1; // dive by zero error | |
631 | if(total_ideal_bw <= 0) total_ideal_bw = 1; // dive by zero error | |
632 | ||
633 | if(total_ideal_bw < total_actual_bw) | |
634 | percentage_bw_difference = (total_ideal_bw * 100) / total_actual_bw ; | |
635 | else | |
636 | percentage_bw_difference = (total_actual_bw * 100) / total_ideal_bw ; | |
637 | ||
638 | percentage_bw_difference = diff_values(100, percentage_bw_difference); | |
639 | ||
640 | if(percentage_bw_difference > percentage_bw_to_ignore) { | |
641 | if(report_bandwidth_mismatch_error && (one_time == 0)) { | |
642 | printf("<%0d> %s : ERROR: report_bandwidth : bandwidth mismatch expected=%0d Mbps actual=%0d Mbps, difference=%0d percent\n", | |
643 | get_time(LO), name, total_ideal_bw, total_actual_bw, percentage_bw_difference); | |
644 | } else { | |
645 | printf("<%0d> %s : NOTE: report_bandwidth : bandwidth mismatch expected=%0d Mbps actual=%0d Mbps, difference=%0d percent\n", | |
646 | get_time(LO), name, total_ideal_bw, total_actual_bw, percentage_bw_difference); | |
647 | } | |
648 | } else { | |
649 | printf("<%0d> %s : NOTE: report_bandwidth : bandwidth mismatch expected=%0d Mbps actual=%0d Mbps, difference=%0d percent\n", | |
650 | get_time(LO), name, total_ideal_bw, total_actual_bw, percentage_bw_difference); | |
651 | } | |
652 | ||
653 | printf("<%0d> =============== %s REPORT_BW =======================\n", get_time(LO), name); | |
654 | printf("%s REPORT_BW Port#\t\tPort0\tPort1\tPort2\tPort3\n", name); | |
655 | printf("%s REPORT_BW Speed\t\t%0d\t%0d\t%0d\t%0d\n", | |
656 | name, port_speed[0], port_speed[1], port_speed[2], port_speed[3]); | |
657 | printf("%s REPORT_BW PktLen\t\t%0d\t%0d\t%0d\t%0d\n", | |
658 | name, port_pkt_length[0], port_pkt_length[1], port_pkt_length[2], port_pkt_length[3]); | |
659 | printf("%s REPORT_BW SentPktCnt\t\t%0d\t%0d\t%0d\t%0d\n", | |
660 | name, | |
661 | number_of_pkts_sent[0], number_of_pkts_sent[1], | |
662 | number_of_pkts_sent[2], number_of_pkts_sent[3]); | |
663 | printf("%s REPORT_BW RcvdPktCnt\t\t%0d\t%0d\t%0d\t%0d\n", | |
664 | name, | |
665 | number_of_pkts_rcvd[0], number_of_pkts_rcvd[1], | |
666 | number_of_pkts_rcvd[2], number_of_pkts_rcvd[3]); | |
667 | printf("%s REPORT_BW IPG\t\t%0d\t%0d\t%0d\t%0d\n", | |
668 | name, port_ipg[0], port_ipg[1], port_ipg[2], port_ipg[3]); | |
669 | printf("%s REPORT_BW IdealBw\t\t%0d\t%0d\t%0d\t%0d\n", | |
670 | name, port_ideal_bw[0], port_ideal_bw[1], port_ideal_bw[2], port_ideal_bw[3]); | |
671 | printf("%s REPORT_BW ActualBw\t\t%0d\t%0d\t%0d\t%0d\n\n", | |
672 | name, port_actual_bw[0], port_actual_bw[1], port_actual_bw[2], port_actual_bw[3]); | |
673 | printf("%s REPORT_BW TotalIdealBw:\t%0d\n", name, total_ideal_bw); | |
674 | printf("%s REPORT_BW TotalActualBw:\t%0d\n", name, total_actual_bw); | |
675 | printf("<%0d> =============== %s REPORT_BW =======================\n", get_time(LO), name); | |
676 | } | |
677 | ||
678 | task MacMonitor::display_results() { | |
679 | } | |
680 | ||
681 |