OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [tags/] [nog_patch_49/] [or1ksim/] [cpu/] [common/] [stats.c] - Rev 65

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"
 
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 mmustats_entry dmmu_stats;	/* data cache stats */
struct raw_stats raw_stats;		/* RAW hazard stats */
struct slp_stats slp_stats;		/* SLP stats */
 
/* Dependency */
 
int check_depend()
{
	debug("check_depend");
	if (depend_operands(icomplet[0].dependdst, iqueue[0].dependsrc1) +
	    depend_operands(icomplet[0].dependdst, iqueue[0].dependsrc2))
		return 1;
	else
		return 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 ((addr < (MEMORY_START + MEMORY_LEN - 4000)) &&
	    slp_stats.supercnt && (type == SLP_MEMWRITE)) {
		slp_stats.supercalls++;
		slp_stats.supercnt = 0;
	}
}
 
void slp_func_entry()
{
	if (++slp_stats.curdepth > slp_stats.maxdepth)
		slp_stats.maxdepth = slp_stats.curdepth;
 
	slp_stats.calls++;
	slp_stats.supercnt++;
}
 
void slp_func_exit()
{
	slp_stats.curdepth--;
}
 
void printstats(int which)
{
	int i, all = 0, dependall = 0;
 
	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]);
 
	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);
	}
 
	printf("SUM: %d instructions (dynamic, functional units stats)  depend: %d%%\n", all, (dependall * 100) / SD(all));
	printf("Byte ADD: %d instructions\n", mstats.byteadd);
	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);
	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);
	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);
	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);
	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);
}
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.