📄 ms_stats.c
字号:
/* * Copyright (C) 1996-1998 by the Board of Trustees * of Leland Stanford Junior University. * * This file is part of the SimOS distribution. * See LICENSE file for terms of the license. * */ /* * ms_stats - Collect statistics on a per procedure basis during * the running of the simulator. * * Contains the functions push_stats and pop_stats, and the * routine print_stats, called on program exit. * * The PROCSTATS flag, if set, forces per procedure statistics to * be kept and output at end. * * Jim Bennett * 1994 */#include <stdlib.h>#include "ms.h"#include "./ms_stats.h"#include "sim_error.h"#include "cpu_state.h"#include "mipsy.h"#include "hw_events.h"#include "statrecord.h"static double convert_stat (struct s_cpu_state *st, int st_index, int mode);static double convert_stat_sum (struct s_cpu_state *st, int st_index);static void PRINT(char *format, ...){ va_list ap; CPUPrint("%MXS:"); va_start(ap,format); vCPUPrint(format,ap); va_end(ap);}/***************************************************************** * STAT RECORD ROUTINES * * All hardware events that should be tracked by statrecord go here. *****************************************************************/struct MSEventsBucket { StatRecordFieldDesc dMXSL1Stall; StatRecordFieldDesc dMXSL2Stall; StatRecordFieldDesc dMXSUpgradeStall; StatRecordFieldDesc iMXSL1Stall; StatRecordFieldDesc iMXSL2Stall; StatRecordFieldDesc pipelineMXSStall;} msEventBucket;#define DEF_FIELD(_field,_fl) (msEventBucket._field = StatRecordDefineField(# _field,_fl))#define STAT_RECORD(_f, _inc) \ StatRecordEntry(cpuNum, pc, vAddr, msEventBucket._f, _inc);#define STAT_RECORD_I(_f, _inc) \ StatRecordEntry(cpuNum, pc, 0, msEventBucket._f, _inc);#define STAT_RECORD_D(_f, _inc) \ StatRecordEntry(cpuNum, 0, vAddr, msEventBucket._f, _inc);void ms_events_init(void){ /* MXS-related counters */ DEF_FIELD(dMXSL1Stall, STATRECORD_INSTRUCTION|STATRECORD_DATA); DEF_FIELD(dMXSL2Stall, STATRECORD_INSTRUCTION|STATRECORD_DATA); DEF_FIELD(iMXSL1Stall, STATRECORD_INSTRUCTION); DEF_FIELD(iMXSL2Stall, STATRECORD_INSTRUCTION); DEF_FIELD(dMXSUpgradeStall, STATRECORD_INSTRUCTION|STATRECORD_DATA); DEF_FIELD(pipelineMXSStall, STATRECORD_INSTRUCTION);}void ms_attribute_stall(int cpuNum, int vAddr, int pc, int stall, int stallType){ if (stallType & E_PIPELINE) { STAT_RECORD_I(pipelineMXSStall,stall); return; } if (stallType & E_D) { if (stallType & E_L1) { STAT_RECORD(dMXSL1Stall,stall); return; } if (((stallType & E_L1) && (stallType & E_UPGRADE)) || ((stallType & E_L2) && (stallType & E_UPGRADE))) { STAT_RECORD(dMXSUpgradeStall,stall); return; } ASSERT(stallType & E_L2); STAT_RECORD(dMXSL2Stall,stall); } else { ASSERT(vAddr==pc); ASSERT(stallType & E_I); if (stallType & E_L1) { STAT_RECORD(iMXSL1Stall,stall); } else { ASSERT(stallType & E_L2); STAT_RECORD(iMXSL2Stall,stall); } }}/*----------------------------------------------------------------------*//* *//* ms_exec never returns, but exits when the app calls exit. *//* But just before exiting, the following routine gets called *//* to print out the collected statistics. *//* *//*----------------------------------------------------------------------*/void print_stats (struct s_cpu_state *st) { } /* * convert_stat - Convert statistic to double precision * floating point number. */static double convert_stat (struct s_cpu_state *st, int st_index, int mode) { double t; t = (double) (st->stats[mode][st_index]); return (t); } /* * convert_stat_sum - Convert statistic to double precision * floating point number. */static double convert_stat_sum (struct s_cpu_state *st, int st_index) { return (convert_stat(st,st_index,0) + convert_stat(st,st_index,1) + convert_stat(st,st_index,2) + convert_stat(st,st_index,3)); }void dump_stats (struct s_cpu_state *st){ int i, mode; if ((st->work_ticks == 0) && (st->work_cycle == 0)) { /* Must not of run yet. */ return; } for (mode = 0; mode < NUM_MODES; mode++) { { CPUState *P = (CPUState *) (st->mipsyPtr); PRINT( "DUMPSTATS: CPU %d MODE %d @ %lld %9d%0.5d\n", P->myNum,mode, (uint64)MipsyReadTime(P->myNum), st->work_ticks, st->work_cycle); }/* Then output gathered statistics */ for (i = 0; i < ST_NTYPES; i++) { if (sh_stat_names[i][0] == 0) continue;#define PRINT_IF_NOT_ZERO(_format, _name, _value) \ if ((_value) != 0) PRINT(_format, _name, (double)(_value)) PRINT_IF_NOT_ZERO( "%s: %.0f\n", sh_stat_names[i], convert_stat(st,i, mode)); }#undef PRINT_IF_NOT_ZERO#define PRINT_IF_NOT_ZERO(_format, _index, _value) \ if ((_value) != 0) PRINT(_format, _index, (double)(_value)) PRINT_IF_NOT_ZERO("SAMPLE: %d %.0f\n",mode,st->sample_stats[mode].samples); for (i = 0; i < (sizeof(st->sample_stats[mode].nthreads_hist) / sizeof(st->sample_stats[mode].nthreads_hist[0])); i++) { PRINT_IF_NOT_ZERO("NTHREADS_HIST: %d %.0f\n",i,st->sample_stats[mode].nthreads_hist[i]); } for (i = 0; i < (sizeof(st->sample_stats[mode].reg_hist) / sizeof(st->sample_stats[mode].reg_hist[0])); i++) { PRINT_IF_NOT_ZERO("REGS_HIST: %d %.0f\n",i,st->sample_stats[mode].reg_hist[i]); } for (i = 0; i < (sizeof(st->sample_stats[mode].iwin_hist) / sizeof(st->sample_stats[mode].iwin_hist[0])); i++) { PRINT_IF_NOT_ZERO("IWIN_INST_HIST: %d %.0f\n",i, st->sample_stats[mode].iwin_hist[i].inst); PRINT_IF_NOT_ZERO("IWIN_SPECINST_HIST: %d %.0f\n",i, st->sample_stats[mode].iwin_hist[i].specInst); PRINT_IF_NOT_ZERO("IWIN_LDST_HIST: %d %.0f\n",i, st->sample_stats[mode].iwin_hist[i].ldstInst); PRINT_IF_NOT_ZERO("IWIN_LDSTDEP_HIST: %d %.0f\n",i, st->sample_stats[mode].iwin_hist[i].ldstdepInst); PRINT_IF_NOT_ZERO("IWIN_REGDEP_HIST: %d %.0f\n",i, st->sample_stats[mode].iwin_hist[i].regdepInst); PRINT_IF_NOT_ZERO("IWIN_SQUASH_HIST: %d %.0f\n",i, st->sample_stats[mode].iwin_hist[i].squashInst); } for (i = 0; i < (sizeof(st->sample_stats[mode].ldst_hist) / sizeof(st->sample_stats[mode].ldst_hist[0])); i++) { PRINT_IF_NOT_ZERO("LDST_INST_HIST: %d %.0f\n",i, st->sample_stats[mode].ldst_hist[i].inst); PRINT_IF_NOT_ZERO("LDST_DONE_INST_HIST: %d %.0f\n",i, st->sample_stats[mode].ldst_hist[i].doneInst); PRINT_IF_NOT_ZERO("LDST_PEND_INST_HIST: %d %.0f\n",i, st->sample_stats[mode].ldst_hist[i].pendInst); PRINT_IF_NOT_ZERO("LDST_CONFLICT_INST_HIST: %d %.0f\n",i, st->sample_stats[mode].ldst_hist[i].conflictInst); PRINT_IF_NOT_ZERO("LDST_FAILED_INST_HIST: %d %.0f\n",i, st->sample_stats[mode].ldst_hist[i].failedInst); PRINT_IF_NOT_ZERO("LDST_STALL_INST_HIST: %d %.0f\n",i, st->sample_stats[mode].ldst_hist[i].stallInst); } }}void MxsPrintStatus(struct s_cpu_state *st) { return;#ifdef BANREMOVE double grad_insts, grad_squashed, cond_br_correct, cond_br_incorrect, ind_br_correct, ind_br_incorrect; double igrad_insts, igrad_squashed, icond_br_correct, icond_br_incorrect, iind_br_correct, iind_br_incorrect; CPUState *P = (CPUState *) (st->mipsyPtr); static struct { double grad_insts, grad_squashed, cond_br_correct, cond_br_incorrect, ind_br_correct, ind_br_incorrect; } old[MIPSY_MAX_CPUS]; if ((st->work_ticks == 0) && (st->work_cycle == 0)) { /* Must not of run yet. */ return; } cond_br_correct = convert_stat_sum (st, ST_CORRECT_FALLTHRU) + convert_stat_sum (st, ST_CORRECT_W_FALLTHRU) + convert_stat_sum (st, ST_CORRECT_W_TAKEN) + convert_stat_sum (st, ST_CORRECT_TAKEN); cond_br_incorrect = convert_stat_sum (st, ST_INCORRECT_FALLTHRU) + convert_stat_sum (st, ST_INCORRECT_W_FALLTHRU) + convert_stat_sum (st, ST_INCORRECT_W_TAKEN) + convert_stat_sum (st, ST_INCORRECT_TAKEN); ind_br_correct = convert_stat_sum (st, ST_CORRECT_IND_BR); ind_br_incorrect = convert_stat_sum (st, ST_INCORRECT_IND_BR); grad_insts = (double) P->numInstructions; grad_squashed = convert_stat_sum (st, ST_GRAD_SQUASHED); icond_br_correct = cond_br_correct - old[P->myNum].cond_br_correct; icond_br_incorrect = cond_br_incorrect - old[P->myNum].cond_br_incorrect; iind_br_correct = ind_br_correct - old[P->myNum].ind_br_correct; iind_br_incorrect = ind_br_incorrect - old[P->myNum].ind_br_incorrect; igrad_insts = grad_insts - old[P->myNum].grad_insts; igrad_squashed = grad_squashed - old[P->myNum].grad_squashed; PRINT ("CPU%d BR (%3.1f%%) JR (%3.1f%%) Squash (%3.1f%%)\n",P->myNum, 100.0*icond_br_correct/(icond_br_correct + icond_br_incorrect + .0000001), 100.0*iind_br_correct/(iind_br_correct + iind_br_incorrect + .0000001), 100.0*igrad_squashed/(igrad_squashed + igrad_insts + .0000001)); old[P->myNum].grad_insts = grad_insts; old[P->myNum].grad_squashed = grad_squashed; old[P->myNum].cond_br_correct = cond_br_correct; old[P->myNum].cond_br_incorrect = cond_br_incorrect; old[P->myNum].ind_br_correct = ind_br_correct; old[P->myNum].ind_br_incorrect = ind_br_incorrect;#endif}void MxsSampleStats(struct s_cpu_state *st, int mode) { int inum, r; struct s_ldst_buffer *entry; int instInWindow , specInstInWindow , ldstInstInWindow , ldstdepInstInWindow , regdepInstInWindow , squashInstInWindow; int ldstBufferInst, ldstDoneInst , ldstConflictInst , ldstFailedInst, ldstStallInst, ldstPendInst; int regBusyCount; st->sample_stats[mode].samples++; st->sample_stats[mode].nthreads_hist[st->nthreads]++; regBusyCount = 0; for (r = 0; r < MAX_PREG/2; r++) { if (st->reg_rstat[r].reg_status & REG_BUSY) regBusyCount++; } st->sample_stats[mode].reg_hist[regBusyCount]++; instInWindow = specInstInWindow = ldstInstInWindow = ldstdepInstInWindow = regdepInstInWindow = squashInstInWindow = 0; inum = st->iwin_headgrad; while (inum >= 0) { int flags = st->iwin_flags[inum]; instInWindow++; if (flags & IWIN_SPEC) specInstInWindow++; if (flags & IWIN_LDST) ldstInstInWindow++; if (flags & IWIN_LDST_DEP) ldstdepInstInWindow++; if (flags & (IWIN_DEP2|IWIN_DEP3)) regdepInstInWindow++; if (flags & IWIN_SQUASH) squashInstInWindow++; inum = st->iwin_grad[inum]; } st->sample_stats[mode].iwin_hist[instInWindow].inst++; st->sample_stats[mode].iwin_hist[specInstInWindow].specInst++; st->sample_stats[mode].iwin_hist[ldstInstInWindow].ldstInst++; st->sample_stats[mode].iwin_hist[ldstdepInstInWindow].ldstdepInst++; st->sample_stats[mode].iwin_hist[regdepInstInWindow].regdepInst++; st->sample_stats[mode].iwin_hist[squashInstInWindow].squashInst++; ldstBufferInst = ldstDoneInst = ldstConflictInst = ldstFailedInst = ldstStallInst = ldstPendInst = 0; for (entry = st->ldst_head; entry; entry = entry->next) { int status = entry->ls->status; ldstBufferInst++; if (status & LS_ST_DONE) { ldstDoneInst++; continue; } if (status & LS_ST_PEND) ldstPendInst++; if (status & LS_ST_CONFLICT) ldstConflictInst++; if (status & LS_ST_FAILED) ldstFailedInst++; if (status & LS_ST_STALL) ldstStallInst++; } st->sample_stats[mode].ldst_hist[ldstBufferInst].inst++; st->sample_stats[mode].ldst_hist[ldstDoneInst].doneInst++; st->sample_stats[mode].ldst_hist[ldstPendInst].pendInst++; st->sample_stats[mode].ldst_hist[ldstConflictInst].conflictInst++; st->sample_stats[mode].ldst_hist[ldstFailedInst].failedInst++; st->sample_stats[mode].ldst_hist[ldstStallInst].stallInst++;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -