200 lines
6.5 KiB
C
Executable File
200 lines
6.5 KiB
C
Executable File
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/mman.h>
|
|
#include <unistd.h>
|
|
|
|
#define DDR_MAX_CH 3
|
|
#define RBW_CNT_HIGH_MAX_VAL 0xFF
|
|
|
|
struct perf_info_t {
|
|
unsigned int rtrans_cnt;
|
|
unsigned int rbw_cnt;
|
|
unsigned int rlatency_cnt;
|
|
unsigned int wtrans_cnt;
|
|
unsigned int wbw_cnt;
|
|
unsigned int wlatency_cnt;
|
|
unsigned int rbw_cnt_hig;
|
|
unsigned int wbw_cnt_hig;
|
|
unsigned long long rbw;
|
|
unsigned long long wbw;
|
|
};
|
|
|
|
struct timespec64 {
|
|
long long tv_sec; /* seconds */
|
|
long tv_nsec; /* nanoseconds */
|
|
};
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
struct timespec64 *stv,*etv;
|
|
unsigned long long start_time, end_time;
|
|
unsigned int sample_it = 0, ms = 1000, ddr_clk;
|
|
double d_time, res_rbw[DDR_MAX_CH],res_wbw[DDR_MAX_CH],res_tbw = 0.0;
|
|
int fd = 0, i;
|
|
char *s = (char*)malloc(256);
|
|
char *e = (char*)malloc(256);
|
|
struct perf_info_t *spi = (struct perf_info_t *)malloc(DDR_MAX_CH *
|
|
sizeof(struct perf_info_t));
|
|
struct perf_info_t *epi = (struct perf_info_t *)malloc(DDR_MAX_CH *
|
|
sizeof(struct perf_info_t));
|
|
|
|
memset(s,0,256);
|
|
memset(e,0,256);
|
|
|
|
if (argc > 1) {
|
|
sample_it = atoi(argv[1]);
|
|
ddr_clk = atoi(argv[2]);
|
|
} else {
|
|
sample_it = 1;
|
|
ddr_clk = 1866;
|
|
printf("Usage:\r\n");
|
|
printf("./perfmon sample_interval_msecs ddr_data_rate\r\n");
|
|
printf("Default:\r\n");
|
|
printf("./perfmon 1 1866\r\n");
|
|
}
|
|
|
|
fd = open("/dev/perf",O_RDWR);
|
|
if (fd < 0) {
|
|
printf("open fail!\n");
|
|
return -1;
|
|
}
|
|
|
|
read(fd, s, DDR_MAX_CH * 4 * 8 + 8);
|
|
|
|
for (i = 0; i < DDR_MAX_CH; i++) {
|
|
spi[i].rtrans_cnt = *(unsigned int*)(s + (i << 5) + 0x00);
|
|
spi[i].rbw_cnt = *(unsigned int*)(s + (i << 5) + 0x04);
|
|
spi[i].rlatency_cnt = *(unsigned int*)(s + (i << 5) + 0x08);
|
|
spi[i].wtrans_cnt = *(unsigned int*)(s + (i << 5) + 0x0c);
|
|
spi[i].wbw_cnt = *(unsigned int*)(s + (i << 5) + 0x10);
|
|
spi[i].wlatency_cnt = *(unsigned int*)(s + (i << 5) + 0x14);
|
|
spi[i].rbw_cnt_hig = *(unsigned int*)(s + (i << 5) + 0x18);
|
|
spi[i].wbw_cnt_hig = *(unsigned int*)(s + (i << 5) + 0x1C);
|
|
spi[i].rbw = ((unsigned long long)spi[i].rbw_cnt_hig << 32) |
|
|
spi[i].rbw_cnt;
|
|
spi[i].wbw = ((unsigned long long)spi[i].wbw_cnt_hig << 32) |
|
|
spi[i].wbw_cnt;
|
|
#if 0
|
|
printf("CH[%d] 0x%08x 0x%08x\n", i, *(unsigned int*)(s +
|
|
(i << 5) + 0x00), spi[i].rtrans_cnt);
|
|
printf("CH[%d] 0x%08x 0x%08x\n", i, *(unsigned int*)(s +
|
|
(i << 5) + 0x04), spi[i].rbw_cnt);
|
|
printf("CH[%d] 0x%08x 0x%08x\n", i, *(unsigned int*)(s +
|
|
(i << 5) + 0x08), spi[i].rlatency_cnt);
|
|
printf("CH[%d] 0x%08x 0x%08x\n", i, *(unsigned int*)(s +
|
|
(i << 5) + 0x0c), spi[i].wtrans_cnt);
|
|
printf("CH[%d] 0x%08x 0x%08x\n", i, *(unsigned int*)(s +
|
|
(i << 5) + 0x10), spi[i].wbw_cnt);
|
|
printf("CH[%d] 0x%08x 0x%08x\n", i, *(unsigned int*)(s +
|
|
(i << 5) + 0x14), spi[i].wlatency_cnt);
|
|
printf("CH[%d] 0x%08x 0x%08x\n", i, *(unsigned int*)(s +
|
|
(i << 5) + 0x18), spi[i].rbw_cnt_hig);
|
|
printf("CH[%d] 0x%08x 0x%08x\n", i, *(unsigned int*)(s +
|
|
(i << 5) + 0x1C), spi[i].wbw_cnt_hig);
|
|
printf("CH[%d] 0x%016llx 0x%016llx\n", i, spi[i].rbw,
|
|
spi[i].wbw);
|
|
#endif
|
|
}
|
|
|
|
stv = (struct timespec64*)(s + (6 << 5) + 0x20);
|
|
//printf("%llu %lu\n", stv->tv_sec, stv->tv_nsec);
|
|
|
|
usleep(sample_it * ms);
|
|
|
|
read(fd, e, DDR_MAX_CH * 4 * 8 + 8);
|
|
|
|
for (i = 0; i < DDR_MAX_CH; i++) {
|
|
epi[i].rtrans_cnt = *(unsigned int*)(e + (i << 5) + 0x00);
|
|
epi[i].rbw_cnt = *(unsigned int*)(e + (i << 5) + 0x04);
|
|
epi[i].rlatency_cnt = *(unsigned int*)(e + (i << 5) + 0x08);
|
|
epi[i].wtrans_cnt = *(unsigned int*)(e + (i << 5) + 0x0c);
|
|
epi[i].wbw_cnt = *(unsigned int*)(e + (i << 5) + 0x10);
|
|
epi[i].wlatency_cnt = *(unsigned int*)(e + (i << 5) + 0x14);
|
|
epi[i].rbw_cnt_hig = *(unsigned int*)(e + (i << 5) + 0x18);
|
|
epi[i].wbw_cnt_hig = *(unsigned int*)(e + (i << 5) + 0x1C);
|
|
|
|
if (epi[i].rbw_cnt_hig < spi[i].rbw_cnt_hig)
|
|
epi[i].rbw_cnt_hig += (RBW_CNT_HIGH_MAX_VAL + 1);
|
|
|
|
if (epi[i].wbw_cnt_hig < spi[i].wbw_cnt_hig)
|
|
epi[i].wbw_cnt_hig += (RBW_CNT_HIGH_MAX_VAL + 1);
|
|
|
|
epi[i].rbw = ((unsigned long long)epi[i].rbw_cnt_hig << 32) |
|
|
epi[i].rbw_cnt;
|
|
epi[i].wbw = ((unsigned long long)epi[i].wbw_cnt_hig << 32) |
|
|
epi[i].wbw_cnt;
|
|
#if 0
|
|
printf("CH[%d] 0x%08x 0x%08x\n", i, *(unsigned int*)(e +
|
|
(i << 5) + 0x00), epi[i].rtrans_cnt);
|
|
printf("CH[%d] 0x%08x 0x%08x\n", i, *(unsigned int*)(e +
|
|
(i << 5) + 0x04), epi[i].rbw_cnt);
|
|
printf("CH[%d] 0x%08x 0x%08x\n", i, *(unsigned int*)(e +
|
|
(i << 5) + 0x08), epi[i].rlatency_cnt);
|
|
printf("CH[%d] 0x%08x 0x%08x\n", i, *(unsigned int*)(e +
|
|
(i << 5) + 0x0c), epi[i].wtrans_cnt);
|
|
printf("CH[%d] 0x%08x 0x%08x\n", i, *(unsigned int*)(e +
|
|
(i << 5) + 0x10), epi[i].wbw_cnt);
|
|
printf("CH[%d] 0x%08x 0x%08x\n", i, *(unsigned int*)(e +
|
|
(i << 5) + 0x14), epi[i].wlatency_cnt);
|
|
printf("CH[%d] 0x%08x 0x%08x\n", i, *(unsigned int*)(e +
|
|
(i << 5) + 0x18), epi[i].rbw_cnt_hig);
|
|
printf("CH[%d] 0x%08x 0x%08x\n", i, *(unsigned int*)(e +
|
|
(i << 5) + 0x1C), epi[i].wbw_cnt_hig);
|
|
printf("CH[%d] 0x%016llx 0x%016llx\n", i, epi[i].rbw,
|
|
epi[i].wbw);
|
|
#endif
|
|
}
|
|
etv = (struct timespec64*)(e + (6 << 5) + 0x20);
|
|
//printf("%llu %lu\n", etv->tv_sec, etv->tv_nsec);
|
|
|
|
start_time = (unsigned long long)stv->tv_sec * 1000000000 + stv->tv_nsec;
|
|
end_time = (unsigned long long)etv->tv_sec * 1000000000 + etv->tv_nsec;
|
|
printf("the start_time is %llu \n", start_time);
|
|
printf("the end_time is %llu \n", end_time);
|
|
d_time = (end_time - start_time) / 1000000000.0;
|
|
printf("interval time is %fs\n", d_time);
|
|
|
|
for (i = 0; i < DDR_MAX_CH; i++) {
|
|
res_rbw[i] = (epi[i].rbw - spi[i].rbw) / (d_time * 1000000.0);
|
|
res_wbw[i] = (epi[i].wbw - spi[i].wbw) / (d_time * 1000000.0);
|
|
res_tbw += (res_rbw[i] + res_wbw[i]);
|
|
printf("CH[%d] R : %0.2fMB/s\n", i, res_rbw[i]);
|
|
printf("CH[%d] W : %0.2fMB/s\n", i, res_wbw[i]);
|
|
|
|
if ((epi[i].rlatency_cnt <= spi[i].rlatency_cnt) ||
|
|
(epi[i].rtrans_cnt <= spi[i].rtrans_cnt)) {
|
|
printf("CH[%d] RL: Monitor OF \n", i);
|
|
} else {
|
|
printf("CH[%d] RL: %0.8fus \n", i,
|
|
1.0 * (epi[i].rlatency_cnt -
|
|
spi[i].rlatency_cnt) / (epi[i].rtrans_cnt -
|
|
spi[i].rtrans_cnt) / (1.0 * (ddr_clk >> 2)));
|
|
}
|
|
|
|
if ((epi[i].wlatency_cnt <= spi[i].wlatency_cnt) ||
|
|
(epi[i].wtrans_cnt <= spi[i].wtrans_cnt)) {
|
|
printf("CH[%d] WL: Monitor OF \n", i);
|
|
} else {
|
|
printf("CH[%d] WL: %0.8fus \n", i,
|
|
1.0 * (epi[i].wlatency_cnt -
|
|
spi[i].wlatency_cnt) / (epi[i].wtrans_cnt -
|
|
spi[i].wtrans_cnt) / (1.0 * (ddr_clk >> 2)));
|
|
}
|
|
}
|
|
|
|
printf("Total usage : %0.2fMB/s\n", res_tbw);
|
|
printf("DDR efficiency: %0.2f%%\n", 100 * res_tbw / (ddr_clk << 1));
|
|
|
|
free(spi);
|
|
free(epi);
|
|
free(s);
|
|
free(e);
|
|
close(fd);
|
|
return 0;
|
|
}
|
|
|