URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
[/] [or1k/] [tags/] [nog_patch_49/] [or1ksim/] [cpu/] [common/] [stats.c] - Rev 221
Go to most recent revision | Compare with Previous | Blame | View Log
/* stats.c -- Various statistics about instruction scheduling etc. Copyright (C) 1999 Damjan Lampret, lampret@opencores.org This file is part of OpenRISC 1000 Architectural Simulator. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <stdio.h> #include <ctype.h> #include <string.h> #include "abstract.h" #include "stats.h" #include "sim-config.h" #include "spr_defs.h" const char func_unit_str[30][30] = { "unknown", "arith", "shift", "compare", "branch", "jump", "load", "store", "movimm", "move", "extend", "nop" }; struct dstats_entry dstats[DSTATS_LEN]; /* dependency stats */ struct sstats_entry sstats[SSTATS_LEN]; /* single stats */ struct fstats_entry fstats[FSTATS_LEN]; /* functional units stats */ struct mstats_entry mstats; /* misc units stats */ struct cachestats_entry ic_stats; /* instruction cache stats */ struct cachestats_entry dc_stats; /* data cache stats */ struct immustats_entry immu_stats; /* insn mmu stats */ struct dmmustats_entry dmmu_stats; /* data mmu stats */ struct raw_stats raw_stats; /* RAW hazard stats */ struct slp_stats slp_stats; /* SLP stats */ /* Dependency */ int check_depend() { debug("check_depend"); return depend_operands(&icomplet[0], &iqueue[0]); } void addsstats(char *item, int cnt_dynamic, int cnt_static) { int i = 0; while(strcmp(sstats[i].insn, item) && (sstats[i].cnt_static > 0) && (sstats[i].cnt_static > 0) && (i < SSTATS_LEN)) i++; if (i >= SSTATS_LEN - 1) return; if (strcmp(sstats[i].insn, item) == 0) { sstats[i].cnt_dynamic += cnt_dynamic; sstats[i].cnt_static += cnt_static; } else { strcpy(sstats[i].insn, item); sstats[i].cnt_dynamic = cnt_dynamic; sstats[i].cnt_static = cnt_static; } } void adddstats(char *item1, char *item2, int cnt_dynamic, int depend) { int i = 0; debug("adddstats start\n"); while((strcmp(dstats[i].insn1, item1) || strcmp(dstats[i].insn2, item2)) && (strlen(dstats[i].insn1)) && (i < DSTATS_LEN)) i++; if (i >= DSTATS_LEN - 1) return; if ((strcmp(dstats[i].insn1, item1) == 0) && (strcmp(dstats[i].insn2, item2) == 0)) { dstats[i].cnt_dynamic += cnt_dynamic; dstats[i].depend += depend; } else { strcpy(dstats[i].insn1, item1); strcpy(dstats[i].insn2, item2); dstats[i].cnt_dynamic = cnt_dynamic; dstats[i].depend = depend; } } void addfstats(enum insn_type item1, enum insn_type item2, int cnt_dynamic, int depend) { int i = 0; while(((fstats[i].insn1 != item1) || (fstats[i].insn2 != item2)) && (fstats[i].insn1 != unknown) && (i < FSTATS_LEN)) i++; if (i >= FSTATS_LEN - 1) return; if ((fstats[i].insn1 == item1) && (fstats[i].insn2 == item2)) { fstats[i].cnt_dynamic += cnt_dynamic; fstats[i].depend += depend; } else { fstats[i].insn1 = item1; fstats[i].insn2 = item2; fstats[i].cnt_dynamic = cnt_dynamic; fstats[i].depend = depend; } } void initstats() { memset(sstats, 0, sizeof(sstats)); memset(dstats, 0, sizeof(dstats)); memset(fstats, 0, sizeof(fstats)); memset(&mstats, 0, sizeof(mstats)); memset(&ic_stats, 0, sizeof(ic_stats)); memset(&dc_stats, 0, sizeof(dc_stats)); memset(&raw_stats, 0, sizeof(raw_stats)); memset(&slp_stats, 0, sizeof(slp_stats)); } /* SLP 1: R 2: R 3: R OK 1: W 2: R 3: R flush 2 3 1: R 2: W 3: R OK 1: R 2: W 3: R flush 3 flushing: don't flush if written location hasn't change after the write since original read got correct data. */ void slp_checkaccess(unsigned long addr, char type) { if (!config.slp) return; if (/*(addr < (MEMORY_START + MEMORY_LEN - 4000)) && MM1709: we have no knowledge of this anymore */ slp_stats.supercnt && (type == SLP_MEMWRITE)) { slp_stats.supercalls++; slp_stats.supercnt = 0; } } void slp_func_entry() { if (!config.slp) return; if (++slp_stats.curdepth > slp_stats.maxdepth) slp_stats.maxdepth = slp_stats.curdepth; slp_stats.calls++; slp_stats.supercnt++; } void slp_func_exit() { if (!config.slp) return; slp_stats.curdepth--; } void printistats(int which) { int i, all = 0, dependall = 0; if (!config.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 printslpstats(int which) { int i, all = 0, dependall = 0; if (!config.slp) { printf("SLP analysis disabled. Enable it to see analysis results.\n"); return; } if (which == 6) { printf("SLP:\n"); printf("maxdepth: %6d calls: %6d\n", slp_stats.maxdepth, slp_stats.calls); printf("calls: %6d supercalls: %6d\n", slp_stats.calls, slp_stats.supercalls); } } void printotherstats(int which) { int i, all = 0, dependall = 0; if (config.bp.bpb_sim) { printf("bnf: %d (%d%%) taken,", mstats.beqz.taken, (mstats.beqz.taken * 100) / SD(mstats.beqz.taken + mstats.beqz.nottaken)); printf(" %d (%d%%) not taken,", mstats.beqz.nottaken, (mstats.beqz.nottaken * 100) / SD(mstats.beqz.taken + mstats.beqz.nottaken)); printf(" %d (%d%%) forward,", mstats.beqz.forward, (mstats.beqz.forward * 100) / SD(mstats.beqz.forward + mstats.beqz.backward)); printf(" %d (%d%%) backward\n", mstats.beqz.backward, (mstats.beqz.backward * 100) / SD(mstats.beqz.forward + mstats.beqz.backward)); printf("bf: %d (%d%%) taken,", mstats.bnez.taken, (mstats.bnez.taken * 100) / SD(mstats.bnez.taken + mstats.bnez.nottaken)); printf(" %d (%d%%) not taken,", mstats.bnez.nottaken, (mstats.bnez.nottaken * 100) / SD(mstats.bnez.taken + mstats.bnez.nottaken)); printf(" %d (%d%%) forward,", mstats.bnez.forward, (mstats.bnez.forward * 100) / SD(mstats.bnez.forward + mstats.bnez.backward)); printf(" %d (%d%%) backward\n", mstats.bnez.backward, (mstats.bnez.backward * 100) / SD(mstats.bnez.forward + mstats.bnez.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)); printf("BPB: hit %d (correct %d%%), miss %d\n", mstats.bpb.hit, (mstats.bpb.correct * 100) / SD(mstats.bpb.hit), mstats.bpb.miss); } else printf("BPB simulation disabled. Enable it to see BPB analysis\n"); if (config.bp.btic_sim) { printf("BTIC: hit %d(%d%%), miss %d\n", mstats.btic.hit, (mstats.btic.hit * 100) / SD(mstats.btic.hit + mstats.btic.miss), mstats.btic.miss); } else printf("BTIC simulation disabled. Enabled it to see BTIC analysis\n"); if (testsprbits(SPR_UPR, SPR_UPR_ICP)) { printf("IC read: hit %d(%d%%), miss %d\n", ic_stats.readhit, (ic_stats.readhit * 100) / SD(ic_stats.readhit + ic_stats.readmiss), ic_stats.readmiss); } else printf("No ICache. Set UPR[ICP]\n"); if (testsprbits(SPR_UPR, SPR_UPR_DCP)) { printf("DC read: hit %d(%d%%), miss %d\n", dc_stats.readhit, (dc_stats.readhit * 100) / SD(dc_stats.readhit + dc_stats.readmiss), dc_stats.readmiss); printf("DC write: hit %d(%d%%), miss %d\n", dc_stats.writehit, (dc_stats.writehit * 100) / SD(dc_stats.writehit + dc_stats.writemiss), dc_stats.writemiss); } else printf("No DCache. Set UPR[DCP]\n"); if (testsprbits(SPR_UPR, SPR_UPR_IMP)) { printf("IMMU read: hit %d(%d%%), miss %d\n", immu_stats.fetch_tlbhit, (immu_stats.fetch_tlbhit * 100) / SD(immu_stats.fetch_tlbhit + immu_stats.fetch_tlbmiss), immu_stats.fetch_tlbmiss); } else printf("No IMMU. Set UPR[IMP]\n"); 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); } else printf("No DMMU. Set UPR[DMP]\n"); } void printstats(int which) { printistats(which); printslpstats(which); if (which == 5) printotherstats(which); }
Go to most recent revision | Compare with Previous | Blame | View Log