📄 writeback.cc
字号:
// Recover RS_LINKs used by this instruction // for (int i = 0; i < TheISA::MaxInstDestRegs; i++) { // blow away the consuming op list DepLink *dep_node, *dep_node_next; for (int q = 0; q < numIQueues; ++q) { for (dep_node = ROB_entry->odep_list[i][q]; dep_node != NULL; dep_node = dep_node_next) { dep_node->iq_consumer->idep_ptr[dep_node->idep_num] = 0; dep_node_next = dep_node->next(); delete dep_node; } } } ROB_entry->squash(); remove_ROB_element(ROB_entry); } } // FIXME: could reset functional units at squash time // squash any instructions in the fetch_to_decode queue decodeQueue->squash(branch_thread); // squash instructions and restart execution at the recover PC fetch_squash(branch_thread);}//==========================================================================//// Branch-Recovery Event...//BranchRecoveryEvent::BranchRecoveryEvent(FullCPU *_cpu, ROBStation *rs, int thread, SpecStateList::ss_iterator sstate, int spec_mode) : Event(&mainEventQueue), cpu(_cpu), thread_number(thread), branch_entry(rs), correct_PC(rs->inst->Next_PC), branch_PC(rs->inst->PC), dir_update(rs->inst->dir_update), staticInst(rs->inst->staticInst), this_spec_mode(spec_mode), spec_state(sstate){ setFlags(AutoDelete);}BranchRecoveryEvent::~BranchRecoveryEvent(){ if (spec_state.notnull()) cpu->state_list.dump(spec_state);}voidBranchRecoveryEvent::process(){ SpecExecContext *xc = cpu->thread[thread_number]; cpu->recover(branch_entry, thread_number); // // If the ROB entry has not committed yet... // (1) mark that we have already recovered for this instruction // (2) // if (branch_entry != NULL) { branch_entry->inst->recover_inst = false; branch_entry->recovery_event = 0; } /* Put the PC back on track */ xc->regs.pc = correct_PC; xc->regs.npc = correct_PC + sizeof(MachInst); if (staticInst->isControl() && cpu->branch_pred) cpu->branch_pred->recover(thread_number, branch_PC, &dir_update); // // Only clear the pending flag if this event is the lowest // spec-level event // if (cpu->thread_info[thread_number].recovery_spec_level == this_spec_mode) { cpu->thread_info[thread_number].recovery_event_pending = false; cpu->thread_info[thread_number].recovery_spec_level = 0; } // Set the global spec_mode[] value... xc->spec_mode = this_spec_mode; // // Clear out speculative state if this was the last level of // misspeculation. // // This CLEAR_MAP step SHOULD be unnecessary given that the // COPY step should always be correct. // cpu->state_list.release(spec_state); // delete spec_state; spec_state = 0; // don't try to delete this more than once... if (xc->spec_mode == 0) { /* reset use_spec_? reg maps and speculative memory state */ xc->reset_spec_state(); // since reset_spec_state() doesn't do this... cpu->create_vector[thread_number].clear_spec(); }}const char *BranchRecoveryEvent::description(){ return "branch recovery";}//==========================================================================//// Writeback Event...//// This event is scheduled for the first (possibly ONLY) writeback// for an instruction//WritebackEvent::WritebackEvent(FullCPU *_cpu, ROBStation *target_rs) : Event(&_cpu->writebackEventQueue), cpu(_cpu), rob_entry(target_rs), tag(target_rs->seq), req(NULL){ setFlags(AutoDelete);}WritebackEvent::WritebackEvent(FullCPU *_cpu, ROBStation *target_rs, MemReqPtr &_req) : Event(&_cpu->writebackEventQueue), cpu(_cpu), rob_entry(target_rs), tag(target_rs->seq), req(_req){ setFlags(AutoDelete);}voidWritebackEvent::trace(const char *action){ DPRINTFN("WritebackEvent for inst %d %s @ %d\n", rob_entry->seq, action, when());}const char *WritebackEvent::description(){ return "writeback";}//// Process a writeback event to the IQ indicated//// This event will schedule DelayedWritebackEvent's if necessary//voidWritebackEvent::process(){ // grab this here, since writeback() may change it bool ea_comp_inst = rob_entry->eaCompPending; cpu->writeback_count[rob_entry->inst->thread_number]++; if (DTRACE(Pipeline)) { string s; rob_entry->inst->dump(s); DPRINTF(Pipeline, "Writeback %s\n", s); } // // Recover instructions do not generate two writeback events. // They write-back to all IQ's during the same cycle (ie. their // "home" queue is written-back late) // if (rob_entry->inst->recover_inst) { unsigned wb_to_other = 0; for (unsigned q = 0; q < cpu->numIQueues; ++q) { unsigned c = rob_entry->writeback(cpu, q); if (q != rob_entry->queue_num) wb_to_other += c; } // update stats cpu->wb_penalized[rob_entry->inst->thread_number] += wb_to_other; } else { // // "Normal" instructions use the two-phase writeback // rob_entry->writeback(cpu, rob_entry->queue_num); } // // If we are writing back to more than one IQ, we have to pay a // penalty for all but the IQ/FU where this instruction executed // // here we schedule a writeback event for the OTHER queues... // // Again, note that recover instructions are DONE after this event // if (!ea_comp_inst) { if (cpu->numIQueues > 1 && !rob_entry->inst->recover_inst) { DelayedWritebackEvent *ev = new DelayedWritebackEvent(cpu, rob_entry); rob_entry->delayed_wb_event = ev; ev->schedule(curTick + cpu->cycles(cpu->iq_comm_latency)); } else rob_entry->completed = true; } // indicate that this pointer is becoming invalid rob_entry->wb_event = 0; if (req) req = NULL; // EGH Fix Me: do I need this}//==========================================================================//// Delayed Writeback Event...//// This event is scheduled to writeback values to clusters OTHER than the// cluster in which the instruction executed. It is only used when// modeling a multi-clustered machine//DelayedWritebackEvent::DelayedWritebackEvent(FullCPU *_cpu, ROBStation *target_rs) : Event(&_cpu->writebackEventQueue, Delayed_Writeback_Pri), cpu(_cpu), rob_entry(target_rs), tag(target_rs->seq){ setFlags(AutoDelete);}//// Process a delayed writeback event//// TO ALL BUT THE INDICATED Queue!!!//voidDelayedWritebackEvent::process(){ unsigned wb_to_other = 0; // writeback to all remote IQ's for (unsigned c = 0; c < cpu->numIQueues; ++c) if (rob_entry->queue_num != c) wb_to_other += rob_entry->writeback(cpu, c); // update stats cpu->wb_penalized[rob_entry->inst->thread_number] += wb_to_other; // EA-Comp instructions should never get here... rob_entry->completed = true; // indicate that this pointer is becoming invalid rob_entry->delayed_wb_event = 0;}//////////////////////////////////////////////////////////////////voidFullCPU::writebackRegStats(){ using namespace Stats; writeback_count .init(number_of_threads) .name(name() + ".WB:count") .desc("cumulative count of insts written-back") .flags(total) ; producer_inst .init(number_of_threads) .name(name() + ".WB:producers") .desc("num instructions producing a value") .flags(total) ; consumer_inst .init(number_of_threads) .name(name() + ".WB:consumers") .desc("num instructions consuming a value") .flags(total) ; wb_penalized .init(number_of_threads) .name(name() + ".WB:penalized") .desc("number of instrctions required to write to 'other' IQ") .flags(total) ; pred_wb_error_dist .init(-10,100,1) .name(name() + ".WB:pred_error") .desc("error in predicted writeback times") .flags(pdf | cdf) ;}voidFullCPU::writebackRegFormulas(){ using namespace Stats; wb_penalized_rate .name(name() + ".WB:penalized_rate") .desc ("fraction of instructions written-back that wrote to 'other' IQ") .flags(total) ; wb_penalized_rate = wb_penalized / writeback_count; wb_fanout .name(name() + ".WB:fanout") .desc("average fanout of values written-back") .flags(total) ; wb_fanout = producer_inst / consumer_inst; wb_rate .name(name() + ".WB:rate") .desc("insts written-back per cycle") .flags(total) ; wb_rate = writeback_count / numCycles;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -