?? floss_reasons.cc
字號:
/* * Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005 * The Regents of The University of Michigan * All Rights Reserved * * This code is part of the M5 simulator, developed by Nathan Binkert, * Erik Hallnor, Steve Raasch, and Steve Reinhardt, with contributions * from Ron Dreslinski, Dave Greene, Lisa Hsu, Kevin Lim, Ali Saidi, * and Andrew Schultz. * * Permission is granted to use, copy, create derivative works and * redistribute this software and such derivative works for any * purpose, so long as the copyright notice above, this grant of * permission, and the disclaimer below appear in all copies made; and * so long as the name of The University of Michigan is not used in * any advertising or publicity pertaining to the use or distribution * of this software without specific, written prior authorization. * * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE * UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND * WITHOUT WARRANTY BY THE UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER * EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE. THE REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE * LIABLE FOR ANY DAMAGES, INCLUDING DIRECT, SPECIAL, INDIRECT, * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM * ARISING OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH * DAMAGES. */#include <cassert>#include <iostream>#include <iomanip>#include <string>#include "base/callback.hh"#include "base/cprintf.hh"#include "base/misc.hh"#include "base/statistics.hh"#include "cpu/smt.hh"#include "encumbered/cpu/full/dyn_inst.hh"#include "encumbered/cpu/full/fetch.hh"#include "encumbered/cpu/full/floss_reasons.hh"#include "encumbered/cpu/full/cpu.hh"#include "encumbered/cpu/full/issue.hh"#include "encumbered/cpu/full/thread.hh"#include "mem/mem_cmd.hh"using namespace std;#define MAYBE_INLINE#define ENABLE_COUNTER_CHECKING 0#if ENABLE_COUNTER_CHECKINGstatic void check_counters(FullCPU *, FlossState *state);#endifstatic constchar * CommitEndDesc[NUM_COMMIT_END_CAUSES] = { "ROB_Empty", "Commit_BW", "StoreBuf", "MemBarrier", "meta: FU", "meta: DCache"};static constchar * IssueEndDesc[NUM_ISSUE_END_CAUSES] = { "NoInsts", "Queue", "IssueBW", "TooYoung", "IssueInorder", "meta: Deps", "meta: FU", "meta: Mem"};static constchar * DisEndDesc[NUM_DIS_END_CAUSES] = { "IREG_Full", "FPREG_Full", "No_Inst", "ROB_cap", "IQ_cap", "BW", "Policy", "Serializing", "Broken", "meta: IQ full", "meta: LSQ full", "meta: ROB full"};static constchar * FetchEndDesc[NUM_FETCH_END_CAUSES] = { "None", "Bandwidth", "BrLim", "InvPC", "BTB_Miss", "BrRecover", "FaultFlush", "Sync", "LowConf", "Policy", "Unknown", "Zero_Prio", "meta: ICache", "meta: QFull"};//// These *_split parameters are no longer supported in the simulator// itself, but we give them dummy values here so we can leave the// related floss_reasons intact, just in case we re-implement the// parameters at some later date.//const int fetch_split = 1;const int issue_split = 1;const int decode_split = 1;const int commit_split = 1;static const char **FUDesc;//// FlossState::clear()//// This routine is called prior to the begining of each cycle//voidFlossState::clear(){ for (int t = 0; t < SMT_MAX_THREADS; ++t) { commit_end_cause[t] = COMMIT_CAUSE_NOT_SET; issue_end_cause[t] = ISSUE_CAUSE_NOT_SET; // this has to be a "policy" since this will be the "end cause" // for all the threads that don't get to dispatch this cycle dispatch_end_cause = FLOSS_DIS_POLICY; // Can't do this, because we need the cause from last cycle... // machine_floss_state.fetch_end_cause[t] = FLOSS_CAUSE_NOT_SET; for (int j = 0; j < TheISA::MaxInstSrcRegs; ++j) { commit_fu[t][j] = No_OpClass; issue_fu[t][j] = No_OpClass; } // this will serve as "not set" commit_mem_result[t] = MA_NOT_PREDICTED; issue_mem_result[t] = MA_NOT_PREDICTED; fetch_mem_result[t] = MA_NOT_PREDICTED; }}/*-------------------------------------------------------------------*/static MAYBE_INLINE voidblame_fu(FullCPU *cpu, int thread, double total_loss, OpClass *fu_classes, FlossType type){ double fu_count = 0; for (int i = 0; i < TheISA::MaxInstSrcRegs; ++i) { if (fu_classes[i] != No_OpClass) { ++fu_count; } } double loss = total_loss / fu_count; for (int i = 0; i < TheISA::MaxInstSrcRegs; ++i) { if (fu_classes[i] != No_OpClass) { int fu = fu_classes[i]; switch (type) { case FLOSS_IQ_FU: cpu->floss_iqfull_fu[thread][fu] += loss; break; case FLOSS_LSQ_FU: cpu->floss_lsqfull_fu[thread][fu] += loss; break; case FLOSS_IQ_DEPS: cpu->floss_iqfull_deps[thread][fu] += loss; break; case FLOSS_LSQ_DEPS: cpu->floss_lsqfull_deps[thread][fu] += loss; break; case FLOSS_ROB: cpu->floss_robfull_fu[thread][fu] += loss; break; } } }}/*-------------------------------------------------------------------*/static MAYBE_INLINE voidblame_commit_stage(FullCPU *cpu, FlossState *state, int thread, double total_loss){ double blame_fraction[SMT_MAX_THREADS]; double loss_part; int commit_per_thread; int t, cause; int blame_threads = 1; // // If we are splitting bandwidth, we may blame several causes // if (commit_split > 1) { commit_per_thread = cpu->commit_width / commit_split; for (t = 0; t < cpu->number_of_threads; t++) { blame_fraction[t] = (double)(commit_per_thread - cpu->n_committed[t]) / (double)(cpu->commit_width - cpu->n_committed_total); } blame_threads = cpu->number_of_threads; } else { // we only use the zero-th element blame_fraction[0] = 1; } // Assign loss due to thread "t" to thread "thread" for (t=0; t<blame_threads; t++) { loss_part = total_loss * blame_fraction[t]; cause = state->commit_end_cause[t]; switch (cause) { case COMMIT_FU: blame_fu(cpu, thread, loss_part, state->commit_fu[t], FLOSS_ROB); break; case COMMIT_DMISS: cpu->floss_robfull_dcache[thread][state->commit_mem_result[t]] += loss_part; break; default: cpu->floss_robfull_other[thread][cause] += loss_part; break; } }}/*-------------------------------------------------------------------*/static MAYBE_INLINE voidblame_issue_stage(FullCPU *cpu, FlossState *state, int thread, double total_loss, bool lsq){ double blame_fraction[SMT_MAX_THREADS]; double loss_part; int issue_per_thread; int t, cause; int blame_threads = 1; // // If we are splitting bandwidth, we may blame several causes // if (issue_split > 1) { issue_per_thread = cpu->issue_width / issue_split; for (t = 0; t < cpu->number_of_threads; t++) { blame_fraction[t] = (double)(issue_per_thread - cpu->n_issued[t]) / (double)(cpu->issue_width - cpu->n_issued_total); blame_threads = cpu->number_of_threads; } } else { // we only use the zero-th element blame_fraction[0] = 1; } // Assign loss due to thread "t" to thread "thread" for (t = 0; t < blame_threads; t++) { loss_part = total_loss * blame_fraction[t]; cause = state->issue_end_cause[t]; switch (cause) { case ISSUE_DEPS: blame_fu(cpu, thread, loss_part, state->issue_fu[t], lsq ? FLOSS_LSQ_DEPS : FLOSS_IQ_DEPS); break; case ISSUE_FU: blame_fu(cpu, thread, loss_part, state->issue_fu[t], lsq ? FLOSS_LSQ_FU : FLOSS_IQ_FU); break; case ISSUE_MEM_BLOCKED: if (!lsq) { cpu->floss_iqfull_dcache[thread][state->issue_mem_result[t]] += loss_part; } else { cpu->floss_lsqfull_dcache[thread][state->issue_mem_result[t]] += loss_part; } break; default: if (!lsq) { cpu->floss_iqfull_other[thread][cause] += loss_part; } else { cpu->floss_iqfull_other[thread][cause] += loss_part; } break; } }}/*-------------------------------------------------------------------*/static MAYBE_INLINE voidblame_dispatch_stage(FullCPU *cpu, FlossState *state, int thread, double loss) { // // Having an MT front-end means that a thread can only be held // responsible for fetch loss is _itself_... threads do not interact // in the front-end (except for fetch bandwidth) // switch (state->dispatch_end_cause) { case FLOSS_DIS_IQ_FULL: // Blame the issue stage blame_issue_stage(cpu, state, thread, loss, true); break; case FLOSS_DIS_LSQ_FULL: // Blame the issue stage blame_issue_stage(cpu, state, thread, loss, false); break; case FLOSS_DIS_ROB_FULL: // Blame the commit stage blame_commit_stage(cpu, state, thread, loss); break; case FLOSS_DIS_CAUSE_NOT_SET: panic("FLOSS: dispatch blamed but no cause set"); break; default: // Just blame simple cause cpu->floss_qfull_other[thread][state->dispatch_end_cause] += loss; break; }}/*-------------------------------------------------------------------*/voidFullCPU::flossRecord(FlossState *state, int num_fetched[]){ int thread; double loss_to_blame = 0; // Per-thread int cause; int counter; // // Generally, we should only have one fetch_end_cause set... // However, if this is not the case, then the fetch stage is // indicating that we should split the loss across the threads // that have a reason specified. // // If fetch_split is active, use "max_to_fetch", otherwise, split // the loss evenly between threads with a reason specified. // if (fetch_split < 2) { int total_fetched = 0; counter = 0; for (thread = 0; thread < number_of_threads; thread++) { if (state->fetch_end_cause[thread] != FLOSS_FETCH_CAUSE_NOT_SET) counter++; total_fetched += num_fetched[thread]; }
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -