📄 bw_monitor.c
字号:
#define ALLOW_OS_CODE 1#include "../rmdef/rmdef.h"#include "../rmcore/include/rmcore.h"#include "../rua/include/rua.h"#include "../rua/include/rua_property.h"#include "get_key.h"#include <stdio.h>#include <unistd.h>#define CONTROLLER_COUNT 2#define GRAPHIC_MODE_WIDTH 64#define ACTIVE_CHAR '#'#define UNACTIVE_CHAR '-'#define MAX_CHAR '@'#define MAX_BANDWIDTH 1200#define ORIGIN_TO_CHAR(_org) ((_org==bw_monitor_sample_origin_global)?'T':((_org==bw_monitor_sample_origin_selection)?'S':'?'))/** TYPE DEFINITIONS **/enum bw_monitor_ouput_mode{ bw_monitor_ouput_mode_bw, bw_monitor_ouput_mode_bar, bw_monitor_ouput_mode_peak, bw_monitor_ouput_mode_raw,};enum bw_monitor_sample_origin{ bw_monitor_sample_origin_global, bw_monitor_sample_origin_selection,};struct channel_desc { RMascii name[32]; RMuint8 value;};struct monitor_params { struct SystemBlock_BWMonitorSelection_type selection; struct SystemBlock_BWMonitorEnable_type enable; RMbool dump_total; RMbool dump_selected;};/** GLOBAL VARIABLES **/static enum bw_monitor_ouput_mode out_mode = bw_monitor_ouput_mode_bw;static RMascii bar[GRAPHIC_MODE_WIDTH + 1];static struct monitor_params config[CONTROLLER_COUNT]; /* one per controller *//* see at the end of this file for a script that generates this table */static const struct channel_desc channel_table[] = { {name: "VOID", value:BWM_VOID}, {name: "ALL_BUSES_W", value:BWM_ALL_BUSES_W}, {name: "ALL_BUSES_R", value:BWM_ALL_BUSES_R}, {name: "MBUS_HOST0_R", value:BWM_MBUS_HOST0_R}, {name: "MBUS_HOST1_R", value:BWM_MBUS_HOST1_R}, {name: "MBUS_AUDIO0_R", value:BWM_MBUS_AUDIO0_R}, {name: "MBUS_AUDIO1_R", value:BWM_MBUS_AUDIO1_R}, {name: "MBUS_TRANSPORT_R", value:BWM_MBUS_TRANSPORT_R}, {name: "MBUS_VIDEO_MISC0_R", value:BWM_MBUS_VIDEO_MISC0_R}, {name: "MBUS_VIDEO_MISC1_R", value:BWM_MBUS_VIDEO_MISC1_R}, {name: "MBUS_VIDEO_DBLK0_R", value:BWM_MBUS_VIDEO_DBLK0_R}, {name: "MBUS_VIDEO_DBLK1_R", value:BWM_MBUS_VIDEO_DBLK1_R}, {name: "MBUS_VIDEO_STORE0_R", value:BWM_MBUS_VIDEO_STORE0_R}, {name: "MBUS_VIDEO_STORE1_R", value:BWM_MBUS_VIDEO_STORE1_R}, {name: "MBUS_ALL_R", value:BWM_MBUS_ALL_R}, {name: "MBUS_HOST0_W", value:BWM_MBUS_HOST0_W}, {name: "MBUS_HOST1_W", value:BWM_MBUS_HOST1_W}, {name: "MBUS_AUDIO0_W", value:BWM_MBUS_AUDIO0_W}, {name: "MBUS_AUDIO1_W", value:BWM_MBUS_AUDIO1_W}, {name: "MBUS_TRANSPORT_W", value:BWM_MBUS_TRANSPORT_W}, {name: "MBUS_VIDEO_MISC0_W", value:BWM_MBUS_VIDEO_MISC0_W}, {name: "MBUS_VIDEO_MISC1_W", value:BWM_MBUS_VIDEO_MISC1_W}, {name: "MBUS_VIDEO_DBLK0_W", value:BWM_MBUS_VIDEO_DBLK0_W}, {name: "MBUS_VIDEO_DBLK1_W", value:BWM_MBUS_VIDEO_DBLK1_W}, {name: "MBUS_VIDEO_STORE0_W", value:BWM_MBUS_VIDEO_STORE0_W}, {name: "MBUS_VIDEO_STORE1_W", value:BWM_MBUS_VIDEO_STORE1_W}, {name: "MBUS_ALL_W", value:BWM_MBUS_ALL_W}, {name: "VBUS_MV_L_R", value:BWM_VBUS_MV_L_R}, {name: "VBUS_MV_C_R", value:BWM_VBUS_MV_C_R}, {name: "VBUS_VCR_L_R", value:BWM_VBUS_VCR_L_R}, {name: "VBUS_VCR_C_R", value:BWM_VBUS_VCR_C_R}, {name: "VBUS_VP_R", value:BWM_VBUS_VP_R}, {name: "VBUS_HDSD_R", value:BWM_VBUS_HDSD_R}, {name: "VBUS_GFX_L_R", value:BWM_VBUS_GFX_L_R}, {name: "VBUS_GFX_C_R", value:BWM_VBUS_GFX_C_R}, {name: "VBUS_OSD_R", value:BWM_VBUS_OSD_R}, {name: "VBUS_SPU_R", value:BWM_VBUS_SPU_R}, {name: "VBUS_GACC_Y_R", value:BWM_VBUS_GACC_Y_R}, {name: "VBUS_GACC_X_R", value:BWM_VBUS_GACC_X_R}, {name: "VBUS_ALL_R", value:BWM_VBUS_ALL_R}, {name: "VBUS_GRAPH_IN_W", value:BWM_VBUS_GRAPH_IN_W}, {name: "VBUS_VIDEO_IN_W", value:BWM_VBUS_VIDEO_IN_W}, {name: "VBUS_GACC_W", value:BWM_VBUS_GACC_W}, {name: "VBUS_HDSD_W", value:BWM_VBUS_HDSD_W}, {name: "VBUS_ALL_W", value:BWM_VBUS_ALL_W}, {name: "GBUS_R", value:BWM_GBUS_R}, {name: "GBUS_W", value:BWM_GBUS_W},};/** STATIC FUNCTIONS **/static void print_usage(RMascii * progname){ RMuint32 i; fprintf(stderr, "Usage: %s [-o output_mode] [-dram N [c0 [c1 [c2 [c3]]]] [-nt]]...\n\n" "Prints a dynamic real-time view of the system's memory bandwidth load\n\n" "-dram N enables monitoring of DRAM controller N (0..1)\n\n" "-nt disables reporting the total bandwidth for controller specified by\n" "the last -dram option\n\n" "-o <bar|bw|raw|peak>: Selects the output mode. Default is\"bw\"\n" "\tbar: prints a bar representing the bandwidth usage relative to the estimated limit\n" "\tbw: prints the consumed bandwidth in kB/sec\n" "\traw: prints the number of the accessed bytes and the measurement interval in usecs\n" "\tpeak: prints the maximum instantaneous bandwidth measured so far\n\n" "c0, c1, c2, c3 are the channel names of the channels to monitor on the\n" "controller specified by tha last -dram option\n" "When no channel names are specified, only the global bandwidth is output\n\n" "Available channelid are:\n", progname); for (i = 0; i < sizeof(channel_table) / sizeof(struct channel_desc); i++) { fprintf(stderr, "\t%s\n", channel_table[i].name); }}static RMstatus parse_cmdline(RMuint32 argc, RMascii ** argv){ RMuint32 dram_id = CONTROLLER_COUNT, arg = 1, i; RMuint32 parsing_channels = 4; if(argc < 2){ fprintf(stderr, "Too few options!\n%s -help for usage description\n", argv[0]); return RM_ERROR; } for (dram_id = 0; dram_id < CONTROLLER_COUNT; dram_id++) { config[dram_id].enable.DRAMControllerId = dram_id; config[dram_id].enable.Enable = FALSE; config[dram_id].selection.DRAMControllerId = dram_id; config[dram_id].selection.AddressHi = 0x0; config[dram_id].selection.AddressLo = 0x0; config[dram_id].selection.ConfigId = 0x0; config[dram_id].selection.ChannelA = BWM_VOID; config[dram_id].selection.ChannelB = BWM_VOID; config[dram_id].selection.ChannelC = BWM_VOID; config[dram_id].selection.ChannelD = BWM_VOID; config[dram_id].dump_total = TRUE; config[dram_id].dump_selected = FALSE; } while (arg < argc) { if (RMCompareAscii(argv[arg], "-help")) { print_usage(argv[0]); return RM_ERROR; } else if (RMCompareAscii(argv[arg], "-o")) { if (arg + 1 < argc) { if(RMCompareAscii(argv[arg+1], "bw")) out_mode = bw_monitor_ouput_mode_bw; else if(RMCompareAscii(argv[arg+1], "bar")) out_mode = bw_monitor_ouput_mode_bar; else if(RMCompareAscii(argv[arg+1], "raw")) out_mode = bw_monitor_ouput_mode_raw; else if(RMCompareAscii(argv[arg+1], "peak")) out_mode = bw_monitor_ouput_mode_peak; else{ fprintf(stderr, "Invalid output mode \"%s\"!\n",argv[arg+1]); return RM_ERROR; } } else { fprintf(stderr, "-o takes an argument\n"); return RM_ERROR; } arg += 2; } else if (RMCompareAscii(argv[arg], "-dram")) { if (arg + 1 < argc) { RMasciiToUInt32(argv[arg + 1], &(dram_id)); /* WARNING: there's no way to tell if the user passed a valid number */ if (dram_id > (CONTROLLER_COUNT - 1)) { fprintf(stderr, "Invalid dram id %ld\n", dram_id); return RM_ERROR; } } else { fprintf(stderr, "-dram takes a numeric parameter\n"); return RM_ERROR; } config[dram_id].enable.Enable = TRUE; parsing_channels = 4; arg += 2; } else if (RMCompareAscii(argv[arg], "-nt")) { if (dram_id < CONTROLLER_COUNT) { config[dram_id].dump_total = FALSE; } else { for (dram_id = 0; dram_id < CONTROLLER_COUNT; dram_id++) { config[dram_id].dump_total = FALSE; } } arg++; } else if ((argv[arg][0] != '-') && (parsing_channels)) { for (i = 0; i < sizeof(channel_table) / sizeof(struct channel_desc); i++) { if (RMCompareAscii(argv[arg], channel_table[i].name)) { break; } } if (i == sizeof(channel_table) / sizeof(struct channel_desc)) { fprintf(stderr, "I don't know about channelid \"%s\"!\n%s -help for a list of valid channel ids\n", argv[arg], argv[0]); return RM_ERROR; } config[dram_id].dump_selected = TRUE; switch (parsing_channels) { case 4: config[dram_id].selection.ChannelA = channel_table[i].value; break; case 3: config[dram_id].selection.ChannelB = channel_table[i].value; break; case 2: config[dram_id].selection.ChannelC = channel_table[i].value; break; case 1: config[dram_id].selection.ChannelD = channel_table[i].value; break; } parsing_channels--; arg++; } else{ fprintf(stderr, "Sorry, I don't understand \"%s\"!\n%s -help for a list of valid options\n", argv[arg], argv[0]); return RM_ERROR; } } return RM_OK;}static void print_sample(RMuint32 bytes, RMuint32 interval, RMuint32 dram_id, enum bw_monitor_sample_origin origin){ RMbool new_max = FALSE; RMuint32 i; RMuint32 instant_bw = 0 , max_id = 0, bar_active; static RMuint32 max_bw[CONTROLLER_COUNT*2] = {0,}; if(out_mode != bw_monitor_ouput_mode_raw){ if (interval >> 2 == 0) /* this should not happen */ return; instant_bw = (bytes << 4) / (interval >> 2); instant_bw *= 15625; /* (1000000/(16*4)) */ max_id = 2*dram_id + ((origin == bw_monitor_sample_origin_global)?0:1); if(instant_bw > max_bw[max_id]){ new_max = TRUE; max_bw[max_id] = instant_bw; } } switch(out_mode){ case bw_monitor_ouput_mode_bw: fprintf(stdout, "%c_dram%ld %09ldkbps (%04ldMBps)\n", ORIGIN_TO_CHAR(origin), dram_id, instant_bw >> 10, instant_bw >> 20); break; case bw_monitor_ouput_mode_bar: bar_active = instant_bw / ((1024 * 1024 * MAX_BANDWIDTH) / GRAPHIC_MODE_WIDTH); for (i = 0; i < GRAPHIC_MODE_WIDTH; i++) { if (i < bar_active) { bar[i] = ACTIVE_CHAR; } else { bar[i] = UNACTIVE_CHAR; } } bar[i] = '\0'; fprintf(stdout, "[%c%ld]%s (%04ldMBps)\n", ORIGIN_TO_CHAR(origin), dram_id, bar, instant_bw >> 20); break; case bw_monitor_ouput_mode_peak: if(new_max){ fprintf(stdout, "%c_dram%ld %09ldkbps (%04ldMBps)\n", ORIGIN_TO_CHAR(origin), dram_id, max_bw[max_id]>>10, max_bw[max_id] >> 20); } break; case bw_monitor_ouput_mode_raw: fprintf(stdout, "%c:%ld:%010ld:%010ld\n", ORIGIN_TO_CHAR(origin), dram_id, bytes, interval); break; }}int main(int argc, char **argv){ struct RUA *pRUA = NULL; RMstatus err; RMuint32 dram_id; struct EMhwlibBWMonitorSample entry; err = parse_cmdline(argc, argv); if (RMFAILED(err)) { return -1; } err = RUACreateInstance(&pRUA, 0); if (RMFAILED(err)) { fprintf(stderr, "Error creating RUA instance! %d\n", err); return -1; } for (dram_id = 0; dram_id < CONTROLLER_COUNT; dram_id++) { while (RUASetProperty(pRUA, SystemBlock, RMSystemBlockPropertyID_BWMonitorSelection, &(config[dram_id].selection), sizeof(config[dram_id].selection), 0) == RM_PENDING) { } while (RUASetProperty(pRUA, SystemBlock, RMSystemBlockPropertyID_BWMonitorEnable, &(config[dram_id].enable), sizeof(config[dram_id].enable), 0) == RM_PENDING) { } } RMTermInit(TRUE); RMSignalInit(NULL, NULL); while (TRUE) { if (RMKeyAvailable()) { if(RMGetKey() == 'q') break; } while (RUAGetProperty(pRUA, SystemBlock, RMSystemBlockPropertyID_BWMonitorSample, &entry, sizeof(entry)) == RM_OK) { if (config[entry.DRAMControllerId].dump_total) { print_sample(entry.TotalTransfers, entry.Interval, entry.DRAMControllerId, bw_monitor_sample_origin_global); } if (config[entry.DRAMControllerId].dump_selected) { print_sample(entry.SelectedTransfers, entry.Interval, entry.DRAMControllerId, bw_monitor_sample_origin_selection); } } usleep(500000); } RMTermExit(); for (dram_id = 0; dram_id < CONTROLLER_COUNT; dram_id++) { config[dram_id].enable.Enable = FALSE; while (RUASetProperty(pRUA, SystemBlock, RMSystemBlockPropertyID_BWMonitorEnable, &(config[dram_id].enable), sizeof(config[dram_id].enable), 0) == RM_PENDING); } /* flush the sample fifo */ while (RUAGetProperty(pRUA, SystemBlock, RMSystemBlockPropertyID_BWMonitorSample, &entry, sizeof(entry)) == RM_OK); err = RUADestroyInstance(pRUA); if (RMFAILED(err)) { fprintf(stderr, "Cannot destroy RUA instance %d\n", err); return -1; } return 0;}/* script to generate the channel table structure *//* echo \{; for channel_label in $(cat emhwlib_globaltypes.h | grep BWM_ | cut -d ' ' -f 2) ;do echo \{name:\"${channel_label:4}\", value:${channel_label} \}, ;done;echo \}; */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -