Line 25... |
Line 25... |
#include "stats.h"
|
#include "stats.h"
|
#include "sim-config.h"
|
#include "sim-config.h"
|
#include "sprs.h"
|
#include "sprs.h"
|
#include "spr_defs.h"
|
#include "spr_defs.h"
|
|
|
const char func_unit_str[30][30] = { "unknown", "arith", "shift", "compare",
|
struct branchstat {
|
"branch", "jump", "load", "store", "movimm", "move", "extend", "nop" };
|
int taken;
|
|
int nottaken;
|
|
int forward;
|
|
int backward;
|
|
};
|
|
|
|
/* See also enum insn_type in abstract.h */
|
|
const char func_unit_str[30][30] = { "unknown", "exception", "arith", "shift", "compare",
|
|
"branch", "jump", "load", "store", "movimm", "move", "extend", "nop", "mac" };
|
|
|
struct dstats_entry dstats[DSTATS_LEN]; /* dependency stats */
|
struct dstats_entry dstats[DSTATS_LEN]; /* dependency stats */
|
struct sstats_entry sstats[SSTATS_LEN]; /* single stats */
|
struct sstats_entry sstats[SSTATS_LEN]; /* single stats */
|
struct fstats_entry fstats[FSTATS_LEN]; /* functional units stats */
|
struct fstats_entry fstats[FSTATS_LEN]; /* functional units stats */
|
struct mstats_entry mstats; /* misc units stats */
|
struct mstats_entry mstats; /* misc units stats */
|
Line 46... |
Line 54... |
{
|
{
|
debug(5,"check_depend\n");
|
debug(5,"check_depend\n");
|
return depend_operands(&icomplet[0], &iqueue[0]);
|
return depend_operands(&icomplet[0], &iqueue[0]);
|
}
|
}
|
|
|
void addsstats(char *item, int cnt_dynamic, int cnt_static)
|
void addsstats(int item, int cnt_dynamic)
|
{
|
{
|
int i = 0;
|
int i = 0;
|
|
|
while(strcmp(sstats[i].insn, item) && (sstats[i].cnt_static > 0) &&
|
while(sstats[i].insn != item && sstats[i].insn >= 0 && i < SSTATS_LEN) i++;
|
(sstats[i].cnt_static > 0) && (i < SSTATS_LEN))
|
|
i++;
|
|
|
|
if (i >= SSTATS_LEN - 1) return;
|
if (i >= SSTATS_LEN - 1) return;
|
|
|
if (strcmp(sstats[i].insn, item) == 0) {
|
if (sstats[i].insn >= 0) {
|
sstats[i].cnt_dynamic += cnt_dynamic;
|
sstats[i].cnt_dynamic += cnt_dynamic;
|
sstats[i].cnt_static += cnt_static;
|
} else {
|
}
|
sstats[i].insn = item;
|
else {
|
|
strcpy(sstats[i].insn, item);
|
|
sstats[i].cnt_dynamic = cnt_dynamic;
|
sstats[i].cnt_dynamic = cnt_dynamic;
|
sstats[i].cnt_static = cnt_static;
|
|
}
|
}
|
}
|
}
|
|
|
void adddstats(char *item1, char *item2, int cnt_dynamic, int depend)
|
void adddstats(int item1, int item2, int cnt_dynamic, int depend)
|
{
|
{
|
int i = 0;
|
int i = 0;
|
|
|
debug(3,"adddstats start\n");
|
debug(3,"adddstats start\n");
|
|
|
while((strcmp(dstats[i].insn1, item1) || strcmp(dstats[i].insn2, item2)) &&
|
while((dstats[i].insn1 != item1 || dstats[i].insn2 != item2) && (i < DSTATS_LEN) && dstats[i].insn1 >= 0) i++;
|
(strlen(dstats[i].insn1)) &&
|
|
(i < DSTATS_LEN))
|
|
i++;
|
|
|
|
if (i >= DSTATS_LEN - 1) return;
|
if (i >= DSTATS_LEN - 1) return;
|
|
|
if ((strcmp(dstats[i].insn1, item1) == 0) &&
|
if (dstats[i].insn1 >= 0) {
|
(strcmp(dstats[i].insn2, item2) == 0)) {
|
|
dstats[i].cnt_dynamic += cnt_dynamic;
|
dstats[i].cnt_dynamic += cnt_dynamic;
|
dstats[i].depend += depend;
|
dstats[i].depend += depend;
|
}
|
} else {
|
else {
|
dstats[i].insn1 = item1;
|
strcpy(dstats[i].insn1, item1);
|
dstats[i].insn2 = item2;
|
strcpy(dstats[i].insn2, item2);
|
|
dstats[i].cnt_dynamic = cnt_dynamic;
|
dstats[i].cnt_dynamic = cnt_dynamic;
|
dstats[i].depend = depend;
|
dstats[i].depend = depend;
|
}
|
}
|
}
|
}
|
|
|
Line 119... |
Line 117... |
}
|
}
|
}
|
}
|
|
|
void initstats()
|
void initstats()
|
{
|
{
|
|
int i;
|
memset(sstats, 0, sizeof(sstats));
|
memset(sstats, 0, sizeof(sstats));
|
|
for (i = 0; i < DSTATS_LEN; i++)
|
|
sstats[i].insn = -1;
|
memset(dstats, 0, sizeof(dstats));
|
memset(dstats, 0, sizeof(dstats));
|
|
for (i = 0; i < DSTATS_LEN; i++)
|
|
dstats[i].insn1 = dstats[i].insn2 = -1;
|
memset(fstats, 0, sizeof(fstats));
|
memset(fstats, 0, sizeof(fstats));
|
memset(&mstats, 0, sizeof(mstats));
|
memset(&mstats, 0, sizeof(mstats));
|
memset(&ic_stats, 0, sizeof(ic_stats));
|
memset(&ic_stats, 0, sizeof(ic_stats));
|
memset(&dc_stats, 0, sizeof(dc_stats));
|
memset(&dc_stats, 0, sizeof(dc_stats));
|
memset(&raw_stats, 0, sizeof(raw_stats));
|
memset(&raw_stats, 0, sizeof(raw_stats));
|
}
|
}
|
|
|
void printistats(int which)
|
|
{
|
|
int i, all = 0, dependall = 0;
|
|
|
|
if (!config.cpu.dependstats) {
|
|
printf("Hazard analysis disabled. Enable it to see analysis results.\n");
|
|
return;
|
|
}
|
|
|
|
for(i = 0; i < SSTATS_LEN; i++)
|
|
all += sstats[i].cnt_static;
|
|
|
|
for(i = 0; i < SSTATS_LEN; i++)
|
|
if (sstats[i].cnt_static && (which == 1))
|
|
printf(" %s\t\tused %6dx (%2d%%)\n", sstats[i].insn, sstats[i].cnt_static, (sstats[i].cnt_static * 100)/all);
|
|
|
|
printf("SUM: %d instructions (static, single stats)\n", all);
|
|
|
|
all = 0;
|
|
|
|
for(i = 0; i < SSTATS_LEN; i++)
|
|
all += sstats[i].cnt_dynamic;
|
|
|
|
for(i = 0; i < SSTATS_LEN; i++)
|
|
if (sstats[i].cnt_dynamic && (which == 2))
|
|
printf(" %s\t\tused %6dx (%2d%%)\n", sstats[i].insn, sstats[i].cnt_dynamic, (sstats[i].cnt_dynamic * 100)/all);
|
|
|
|
printf("SUM: %d instructions (dynamic, single stats)\n", all);
|
|
|
|
all = 0;
|
|
dependall = 0;
|
|
for(i = 0; i < DSTATS_LEN; i++) {
|
|
all += dstats[i].cnt_dynamic;
|
|
dependall += dstats[i].depend;
|
|
}
|
|
|
|
for(i = 0; i < DSTATS_LEN; i++)
|
|
if (dstats[i].cnt_dynamic && (which == 3)) {
|
|
printf(" %s, %s ", dstats[i].insn1, dstats[i].insn2);
|
|
printf("\t\t\t%6dx (%2d%%)", dstats[i].cnt_dynamic, (dstats[i].cnt_dynamic * 100)/all);
|
|
printf(" depend: %3d%%\n", (dstats[i].depend * 100) / dstats[i].cnt_dynamic);
|
|
}
|
|
|
|
printf("SUM: %d instructions (dynamic, dependency stats) depend: %d%%\n", all, (dependall * 100) / all);
|
|
|
|
all = 0;
|
|
dependall = 0;
|
|
for(i = 0; i < FSTATS_LEN; i++) {
|
|
all += fstats[i].cnt_dynamic;
|
|
dependall += fstats[i].depend;
|
|
}
|
|
|
|
for(i = 0; i < FSTATS_LEN; i++)
|
|
if (fstats[i].cnt_dynamic && (which == 4)) {
|
|
printf(" %s,", func_unit_str[fstats[i].insn1]);
|
|
printf(" %s", func_unit_str[fstats[i].insn2]);
|
|
printf("\t\t\t%6dx (%2d%%)", fstats[i].cnt_dynamic, (fstats[i].cnt_dynamic * 100)/all);
|
|
printf(" depend: %3d%%\n", (fstats[i].depend * 100) / fstats[i].cnt_dynamic);
|
|
}
|
|
|
|
for(i = 0; (i < RAW_RANGE) && (which == 5); i++)
|
|
printf(" Register set and reused in %d. cycle: %d cases\n", i, raw_stats.range[i]);
|
|
|
|
printf("SUM: %d instructions (dynamic, functional units stats) depend: %d%%\n", all, (dependall * 100) / SD(all));
|
|
printf("Byte ADD: %d instructions\n", mstats.byteadd);
|
|
|
|
}
|
|
|
|
void printotherstats(int which)
|
void printotherstats(int which)
|
{
|
{
|
int i, all = 0, dependall = 0;
|
int i, all = 0, dependall = 0;
|
|
|
|
printf ("\n");
|
if (config.cpu.bpb) {
|
if (config.cpu.bpb) {
|
printf("bnf: %d (%d%%) taken,", mstats.beqz.taken, (mstats.beqz.taken * 100) / SD(mstats.beqz.taken + mstats.beqz.nottaken));
|
struct branchstat bf;
|
printf(" %d (%d%%) not taken,", mstats.beqz.nottaken, (mstats.beqz.nottaken * 100) / SD(mstats.beqz.taken + mstats.beqz.nottaken));
|
struct branchstat bnf;
|
printf(" %d (%d%%) forward,", mstats.beqz.forward, (mstats.beqz.forward * 100) / SD(mstats.beqz.forward + mstats.beqz.backward));
|
long bf_all, bnf_all;
|
printf(" %d (%d%%) backward\n", mstats.beqz.backward, (mstats.beqz.backward * 100) / SD(mstats.beqz.forward + mstats.beqz.backward));
|
bf.taken = mstats.bf[1][0] + mstats.bf[1][1];
|
printf("bf: %d (%d%%) taken,", mstats.bnez.taken, (mstats.bnez.taken * 100) / SD(mstats.bnez.taken + mstats.bnez.nottaken));
|
bf.nottaken = mstats.bf[0][0] + mstats.bf[0][1];
|
printf(" %d (%d%%) not taken,", mstats.bnez.nottaken, (mstats.bnez.nottaken * 100) / SD(mstats.bnez.taken + mstats.bnez.nottaken));
|
bf.forward = mstats.bf[0][1] + mstats.bf[1][1];
|
printf(" %d (%d%%) forward,", mstats.bnez.forward, (mstats.bnez.forward * 100) / SD(mstats.bnez.forward + mstats.bnez.backward));
|
bf.backward = mstats.bf[0][0] + mstats.bf[1][0];
|
printf(" %d (%d%%) backward\n", mstats.bnez.backward, (mstats.bnez.backward * 100) / SD(mstats.bnez.forward + mstats.bnez.backward));
|
bf_all = bf.forward + bf.backward;
|
printf("StaticBP bnf: correct %d%% (forward)\n", (mstats.sbp_bnf.correct * 100) / SD(mstats.sbp_bnf.all));
|
|
printf("StaticBP bf: correct %d%% (backward)\n", (mstats.sbp_bf.correct * 100) / SD(mstats.sbp_bf.all));
|
bnf.taken = mstats.bnf[1][0] + mstats.bf[1][1];
|
|
bnf.nottaken = mstats.bnf[0][0] + mstats.bf[0][1];
|
|
bnf.forward = mstats.bnf[0][1] + mstats.bf[1][1];
|
|
bnf.backward = mstats.bnf[0][0] + mstats.bf[1][0];
|
|
bnf_all = bnf.forward + bnf.backward;
|
|
|
|
printf("bnf: %d (%d%%) taken,", bf.taken, (bf.taken * 100) / SD(bf_all));
|
|
printf(" %d (%d%%) not taken,", bf.nottaken, (bf.nottaken * 100) / SD(bf_all));
|
|
printf(" %d (%d%%) forward,", bf.forward, (bf.forward * 100) / SD(bf_all));
|
|
printf(" %d (%d%%) backward\n", bf.backward, (bf.backward * 100) / SD(bf_all));
|
|
printf("bf: %d (%d%%) taken,", bnf.taken, (bnf.taken * 100) / SD(bnf_all));
|
|
printf(" %d (%d%%) not taken,", bnf.nottaken, (bnf.nottaken * 100) / SD(bnf_all));
|
|
printf(" %d (%d%%) forward,", bnf.forward, (bnf.forward * 100) / SD(bnf_all));
|
|
printf(" %d (%d%%) backward\n", bnf.backward, (bnf.backward * 100) / SD(bnf_all));
|
|
|
|
printf("StaticBP bnf(%s): correct %d%%\n", config.cpu.sbp_bnf_fwd ? "forward" : "backward",
|
|
(mstats.bnf[0][config.cpu.sbp_bnf_fwd] * 100) / SD(bnf_all));
|
|
printf("StaticBP bf(%s): correct %d%%\n", config.cpu.sbp_bf_fwd ? "forward" : "backward",
|
|
(mstats.bnf[1][config.cpu.sbp_bf_fwd] * 100) / SD(bf_all));
|
printf("BPB: hit %d (correct %d%%), miss %d\n", mstats.bpb.hit, (mstats.bpb.correct * 100) / SD(mstats.bpb.hit), mstats.bpb.miss);
|
printf("BPB: hit %d (correct %d%%), miss %d\n", mstats.bpb.hit, (mstats.bpb.correct * 100) / SD(mstats.bpb.hit), mstats.bpb.miss);
|
} else
|
} else
|
printf("BPB simulation disabled. Enable it to see BPB analysis\n");
|
printf("BPB simulation disabled. Enable it to see BPB analysis\n");
|
|
|
if (config.cpu.btic) {
|
if (config.cpu.btic) {
|
Line 240... |
Line 194... |
|
|
if (testsprbits(SPR_UPR, SPR_UPR_DMP)) {
|
if (testsprbits(SPR_UPR, SPR_UPR_DMP)) {
|
printf("DMMU read: hit %d(%d%%), miss %d\n", dmmu_stats.loads_tlbhit, (dmmu_stats.loads_tlbhit * 100) / SD(dmmu_stats.loads_tlbhit + dmmu_stats.loads_tlbmiss), dmmu_stats.loads_tlbmiss);
|
printf("DMMU read: hit %d(%d%%), miss %d\n", dmmu_stats.loads_tlbhit, (dmmu_stats.loads_tlbhit * 100) / SD(dmmu_stats.loads_tlbhit + dmmu_stats.loads_tlbmiss), dmmu_stats.loads_tlbmiss);
|
} else
|
} else
|
printf("No DMMU. Set UPR[DMP]\n");
|
printf("No DMMU. Set UPR[DMP]\n");
|
|
|
|
{
|
|
extern int loadcycles, storecycles, nops, nop_maxperiod;
|
|
printf("Additional LOAD CYCLES: %u STORE CYCLES: %u\n", loadcycles, storecycles);
|
|
printf("l.nop count: %u maxgap: %u\n", nops, nop_maxperiod);
|
|
}
|
}
|
}
|
|
|
void printstats(int which)
|
void printstats(int which)
|
{
|
{
|
printistats(which);
|
int i, all = 0, dependall = 0;
|
if (which == 5)
|
|
|
if (which >= 1 && which <= 5 && !config.cpu.dependstats) {
|
|
printf("Hazard analysis disabled. Enable it to see analysis results.\n");
|
|
return;
|
|
}
|
|
|
|
switch (which) {
|
|
case 1:
|
|
printf("stats 1: Misc stats\n");
|
printotherstats(which);
|
printotherstats(which);
|
|
break;
|
|
case 2:
|
|
printf ("stats 2: Instruction usage\n");
|
|
for(i = 0; i < SSTATS_LEN; i++)
|
|
all += sstats[i].cnt_dynamic;
|
|
|
|
for(i = 0; i < SSTATS_LEN; i++)
|
|
if (sstats[i].cnt_dynamic)
|
|
printf(" %-15s used %6dx (%5.1f%%)\n", insn_name(sstats[i].insn), sstats[i].cnt_dynamic, (sstats[i].cnt_dynamic * 100.)/SD(all));
|
|
|
|
printf("%d instructions (dynamic, single stats)\n", all);
|
|
break;
|
|
|
|
case 3:
|
|
printf ("stats 3: Instruction dependencies\n");
|
|
for(i = 0; i < DSTATS_LEN; i++) {
|
|
all += dstats[i].cnt_dynamic;
|
|
dependall += dstats[i].depend;
|
|
}
|
|
|
|
for(i = 0; i < DSTATS_LEN; i++)
|
|
if (dstats[i].cnt_dynamic) {
|
|
char temp[100];
|
|
sprintf(temp, "%s, %s ", insn_name(dstats[i].insn1), insn_name(dstats[i].insn2));
|
|
printf(" %-30s %6dx (%5.1f%%)", temp, dstats[i].cnt_dynamic, (dstats[i].cnt_dynamic * 100.)/SD(all));
|
|
printf(" depend: %5.1f%%\n", (dstats[i].depend * 100.) / dstats[i].cnt_dynamic);
|
|
}
|
|
|
|
printf("%d instructions (dynamic, dependency stats) depend: %d%%\n", all, (dependall * 100) / SD(all));
|
|
break;
|
|
|
|
case 4:
|
|
printf("stats 4: Functional units dependencies\n");
|
|
for(i = 0; i < FSTATS_LEN; i++) {
|
|
all += fstats[i].cnt_dynamic;
|
|
dependall += fstats[i].depend;
|
|
}
|
|
|
|
for(i = 0; i < FSTATS_LEN; i++)
|
|
if (fstats[i].cnt_dynamic) {
|
|
char temp[100];
|
|
sprintf(temp, "%s, %s", func_unit_str[fstats[i].insn1], func_unit_str[fstats[i].insn2]);
|
|
printf(" %-30s %6dx (%5.1f%%)", temp, fstats[i].cnt_dynamic, (fstats[i].cnt_dynamic * 100.)/SD(all));
|
|
printf(" depend: %5.1f%%\n", (fstats[i].depend * 100.) / fstats[i].cnt_dynamic);
|
|
}
|
|
printf ("%d instructions (dynamic, functional units stats) depend: %d%%\n\n", all, (dependall * 100) / SD(all));
|
|
break;
|
|
|
|
case 5:
|
|
printf("stats 5: Raw register usege over time\n");
|
|
for(i = 0; (i < config.cpu.raw_range); i++)
|
|
printf(" Register set and reused in %d. cycle: %d cases\n", i, raw_stats.range[i]);
|
|
break;
|
|
default:
|
|
printf ("Please specify a stats group (1-5).\n");
|
|
break;
|
|
}
|
|
#if 0
|
|
printf("Byte ADD: %d instructions\n", mstats.byteadd);
|
|
#endif
|
}
|
}
|
|
|
No newline at end of file
|
No newline at end of file
|