📄 issue.cc
字号:
#endif // // RR for FU pool if there isn't a 1:1 match between // Queues and FU pools... // if (numIQueues != numFUPools) current_fu_pool = (current_fu_pool + 1) % numFUPools; ++n_issued; ++issued_by_thread[thread]; ++expected_inorder_seq_num; issue_delay_dist[inst->opClass()] .sample(curTick - ready_ts); queue_res_dist[inst->opClass()] .sample(curTick - dispatch_ts); // // Update INSTRUCTION statistics // if (source == iq) update_exe_inst_stats(inst); // // Update OPERATION statistics // ++issued_ops[thread]; } } // // STEP #5: // // Rotate through the IQ's // (first to check to see if this ready-list is empty) // if (source == iq) { bool no_rdy_insts = iq_rq_iterator[current_iq].isnull(); bool no_bw = (IQ[current_iq]->issue_bw() == 0); if (no_rdy_insts || no_bw) { // mark this queue done, check for all done done_with_iq = done_list.markDone(current_iq); if (no_rdy_insts) { if (IQ[current_iq]->iw_count()) { // iq not empty, but no ready insts... if (floss_state.issue_end_cause[0] == ISSUE_CAUSE_NOT_SET) { // // Either the oldest instruction is waiting for // it's inputs or some other IQ-related problem // evil_inst = IQ[current_iq]->oldest(); if (!evil_inst->ops_ready()) { floss_state.issue_end_cause[0] = ISSUE_DEPS; if (!find_idep_to_blame(evil_inst, 0)) floss_state.issue_end_cause[0] = ISSUE_IQ; } else { floss_state.issue_end_cause[0] = ISSUE_IQ; } } } else { // iq empty SET_FIRST_FLOSS_CAUSE(floss_state.issue_end_cause[0], ISSUE_NO_INSN); } } else { // // Must have been BW... // SET_FIRST_FLOSS_CAUSE(floss_state.issue_end_cause[0], ISSUE_BW); } }#if ISSUE_OLDEST == 0 if (!done_with_iq) current_iq = (current_iq + 1) % numIQueues;#endif } // // STEP #6: // // When we run out of bandwidth, indicate // that we are done issuing from the IQ & LSQ // if (n_issued >= issue_width) { done_with_iq = true; done_with_lsq = true; } } while (!done_with_iq || !done_with_sb || !done_with_lsq); // // Delete the allocated lists... // delete[] iq_rq_iterator; delete[] hp_rq_it_list; delete[] hp_done;#if DUMP_ISSUE if (!issued_list.empty()) { issued_list.sort(); list<issue_info>::iterator i = issued_list.begin(); list<issue_info>::iterator end = issued_list.end(); for (; i != end; ++i) { cerr << " #" << i->seq << " (clust " << i->clust << ") " << i->inst << endl; } }#endif // // // We've issued n_issued instructions from the IQ or LSQ // n_issued_dist[n_issued]++; if (n_issued == issue_width) { // // Issue BW limit reached... blame loss on BW only if there are // no ready instructions // if (floss_state.issue_end_cause[0] != ISSUE_IQ) { // // NOTE: these causes over-ride any previously-set cause // if (n_ready == 0) { if (IQNumInstructions() != 0) { floss_state.issue_end_cause[0] = ISSUE_DEPS; evil_inst = IQOldestInstruction(); if (!find_idep_to_blame(evil_inst, 0)) { floss_state.issue_end_cause[0] = ISSUE_IQ; } } else { floss_state.issue_end_cause[0] = ISSUE_NO_INSN; } } else { floss_state.issue_end_cause[0] = ISSUE_BW; } } } else { // // We have issue BW left: // (1) We must have tried to issue from the IQ // ==> issue_end_cause is set in Sep #1 // (2) OR, we must have tried to issue from the LSQ // ==> issue_end_cause may not be set // -> No instructions // -> No instructions ready // -> issue trouble... cause will be set in lsq_issue // (3) OR, we only issued from the SB // ==> issue_end_cause is set in Sep #1 // (4) OR, we were issuing inorder // ==> ISSUE_INORDER // if (floss_state.issue_end_cause[0] == ISSUE_CAUSE_NOT_SET) { if (LSQ->count() != 0) { floss_state.issue_end_cause[0] = ISSUE_DEPS; evil_inst = LSQ->oldest(); if (!find_idep_to_blame(evil_inst, 0)) floss_state.issue_end_cause[0] = ISSUE_IQ; } else { floss_state.issue_end_cause[0] = ISSUE_NO_INSN; } } }#if DEBUG_FLOSS if (floss_state.issue_end_cause[0] == ISSUE_CAUSE_NOT_SET) panic("cause not set");#endif}// voidFullCPU::issue_init(){ int i;#if 0 for (i = 0; i < SMT_MAX_THREADS; i++) store_info[i] = new(lsq_store_info_t)[LSQ_size];#endif for (i = 0; i < Num_OpClasses; ++i) unissued_names[i] = opClassStrings[i]; unissued_names[Num_OpClasses] = "DCache_Blocked"; unissued_names[Num_OpClasses + 1] = "Too_Young";#if REMOVE_WP_LOADS cerr << "NOT Issuing misspeculated loads..." << endl;#endif}voidFullCPU::issueRegStats(){ using namespace Stats; com_inst.resize(number_of_threads); com_loads.resize(number_of_threads); for (int i = 0; i < number_of_threads; ++i) { com_inst[i] = 0; com_loads[i] = 0; } stat_com_inst .init(number_of_threads) .name(name() + ".COM:count") .desc("Number of instructions committed") .flags(total) ; stat_com_swp .init(number_of_threads) .name(name() + ".COM:swp_count") .desc("Number of s/w prefetches committed") .flags(total) ; stat_com_refs .init(number_of_threads) .name(name() + ".COM:refs") .desc("Number of memory references committed") .flags(total) ; stat_com_loads .init(number_of_threads) .name(name() + ".COM:loads") .desc("Number of loads committed") .flags(total) ; stat_com_membars .init(number_of_threads) .name(name() + ".COM:membars") .desc("Number of memory barriers committed") .flags(total) ; stat_com_branches .init(number_of_threads) .name(name() + ".COM:branches") .desc("Number of branches committed") .flags(total) ; // // these will count the number of PROGRAM instructions // (NOT "operations") issued... ie. EA-Comp ops are not counted // exe_inst .init(number_of_threads) .name(name() + ".ISSUE:count") .desc("number of insts issued") .flags(total) ; exe_swp .init(number_of_threads) .name(name() + ".ISSUE:swp") .desc("number of swp insts issued") .flags(total) ; exe_nop .init(number_of_threads) .name(name() + ".ISSUE:nop") .desc("number of nop insts issued") .flags(total) ; exe_refs .init(number_of_threads) .name(name() + ".ISSUE:refs") .desc("number of memory reference insts issued") .flags(total) ; exe_loads .init(number_of_threads) .name(name() + ".ISSUE:loads") .desc("number of load insts issued") .flags(total) ; exe_branches .init(number_of_threads) .name(name() + ".ISSUE:branches") .desc("Number of branches issued") .flags(total) ; issued_ops .init(number_of_threads) .name(name() + ".ISSUE:op_count") .desc("number of insts issued") .flags(total) ; n_issued_dist .init(issue_width + 1) .name(name() + ".ISSUE:issued_per_cycle") .desc("Number of insts issued each cycle") .flags(total | pdf | dist) ; fu_busy .init(number_of_threads) .name(name() + ".ISSUE:fu_busy_cnt") .desc("FU busy when requested") .flags(total) ; stat_fu_busy .init(Num_OpClasses) .name(name() + ".ISSUE:fu_full") .desc("attempts to use FU when none available") .flags(pdf | dist) ; for (int i=0; i < Num_OpClasses; ++i) { stat_fu_busy.subname(i, opClassStrings[i]); } stat_fuBusy .init(numIQueues, Num_OpClasses) .name(name() + ".ISSUE:IQ") .flags(pdf | dist) ; for (int q = 0; q < numIQueues; ++q) { stringstream label,desc; label << q << ":fu_full"; desc << " attempts to issue to FU from pool #" << q << "when none available"; stat_fuBusy .subname(q, label.str()) .subdesc(q, desc.str()) ; } stat_fuBusy.ysubnames(opClassStrings); dist_unissued .init(Num_OpClasses+2) .name(name() + ".ISSUE:unissued_cause") .desc("Reason ready instruction not issued") .flags(pdf | dist) ; for (int i=0; i < (Num_OpClasses + 2); ++i) { dist_unissued.subname(i, unissued_names[i]); } stat_issued_inst_type .init(number_of_threads,Num_OpClasses) .name(name() + ".ISSUE:FU_type") .desc("Type of FU issued") .flags(total | pdf | dist) ; stat_issued_inst_type.ysubnames(opClassStrings); // // How long did instructions for a particular FU type wait prior to issue // issue_delay_dist .init(Num_OpClasses,0,99,2) .name(name() + ".ISSUE:") .desc("cycles from operands ready to issue") .flags(pdf | cdf) ; for (int i=0; i<Num_OpClasses; ++i) { stringstream subname; subname << opClassStrings[i] << "_delay"; issue_delay_dist.subname(i, subname.str()); } // // Other stats // lsq_forw_loads .init(number_of_threads) .name(name() + ".LSQ:forw_loads") .desc("number of loads forwarded via LSQ") .flags(total) ; inv_addr_loads .init(number_of_threads) .name(name() + ".ISSUE:addr_loads") .desc("number of invalid-address loads") .flags(total) ; inv_addr_swpfs .init(number_of_threads) .name(name() + ".ISSUE:addr_swpfs") .desc("number of invalid-address SW prefetches") .flags(total) ; queue_res_dist .init(Num_OpClasses, 0, 99, 2) .name(name() + ".IQ:residence:") .desc("cycles from dispatch to issue") .flags(total | pdf | cdf ) ; for (int i = 0; i < Num_OpClasses; ++i) { queue_res_dist.subname(i, opClassStrings[i]); } lsq_blocked_loads .init(number_of_threads) .name(name() + ".LSQ:blocked_loads") .desc("number of ready loads not issued due to memory disambiguation") .flags(total) ; lsqInversion .name(name() + ".ISSUE:lsq_invert") .desc("Number of times LSQ instruction issued early") ;}voidFullCPU::issueRegFormulas(){ using namespace Stats; misspec_cnt .name(name() + ".ISSUE:misspec_cnt") .desc("Number of misspeculated insts issued") .flags(total) ; misspec_cnt = exe_inst - stat_com_inst; misspec_ipc .name(name() + ".ISSUE:MSIPC") .desc("Misspec issue rate") .flags(total) ; misspec_ipc = misspec_cnt / numCycles; issue_rate .name(name() + ".ISSUE:rate") .desc("Inst issue rate") .flags(total) ; issue_rate = exe_inst / numCycles; issue_stores .name(name() + ".ISSUE:stores") .desc("Number of stores issued") .flags(total) ; issue_stores = exe_refs - exe_loads; issue_op_rate .name(name() + ".ISSUE:op_rate") .desc("Operation issue rate") .flags(total) ; issue_op_rate = issued_ops / numCycles; fu_busy_rate .name(name() + ".ISSUE:fu_busy_rate") .desc("FU busy rate (busy events/executed inst)") .flags(total) ; fu_busy_rate = fu_busy / exe_inst; // // Commit-stage statistics // (we include these here because we _count_ them here) // commit_stores .name(name() + ".COM:stores") .desc("Number of stores committed") .flags(total) ; commit_stores = stat_com_refs - stat_com_loads; commit_ipc .name(name() + ".COM:IPC") .desc("Committed instructions per cycle") .flags(total) ; commit_ipc = stat_com_inst / numCycles; commit_ipb .name(name() + ".COM:IPB") .desc("Committed instructions per branch") .flags(total) ; commit_ipb = stat_com_inst / stat_com_branches; lsq_inv_rate .name(name() + ".ISSUE:lsq_inv_rate") .desc("Early LSQ issues per cycle") ; lsq_inv_rate = lsqInversion / numCycles;}/************************************************************** * * * Collect instruction statistics * * * **************************************************************/voidFullCPU::update_exe_inst_stats(DynInst *inst){ int thread_number = inst->thread_number; // // Pick off the software prefetches //#ifdef TARGET_ALPHA if (inst->isDataPrefetch()) exe_swp[thread_number]++; else exe_inst[thread_number]++;#else exe_inst[thread_number]++;#endif // // Control operations // if (inst->isControl()) exe_branches[thread_number]++; // // Memory operations // if (inst->isMemRef()) { exe_refs[thread_number]++; if (inst->isLoad()) exe_loads[thread_number]++; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -