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