diff options
Diffstat (limited to 'src/cpu/ozone/back_end_impl.hh')
-rw-r--r-- | src/cpu/ozone/back_end_impl.hh | 1919 |
1 files changed, 0 insertions, 1919 deletions
diff --git a/src/cpu/ozone/back_end_impl.hh b/src/cpu/ozone/back_end_impl.hh deleted file mode 100644 index a72cf67c0..000000000 --- a/src/cpu/ozone/back_end_impl.hh +++ /dev/null @@ -1,1919 +0,0 @@ -/* - * Copyright (c) 2006 The Regents of The University of Michigan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Kevin Lim - */ - -#ifndef __CPU_OZONE_BACK_END_IMPL_HH__ -#define __CPU_OZONE_BACK_END_IMPL_HH__ - -#include "cpu/ozone/back_end.hh" -#include "encumbered/cpu/full/op_class.hh" - -template <class Impl> -BackEnd<Impl>::InstQueue::InstQueue(Params *params) - : size(params->numIQEntries), numInsts(0), width(params->issueWidth) -{ -} - -template <class Impl> -std::string -BackEnd<Impl>::InstQueue::name() const -{ - return be->name() + ".iq"; -} - -template <class Impl> -void -BackEnd<Impl>::InstQueue::regStats() -{ - using namespace Stats; - - occ_dist - .init(1, 0, size, 2) - .name(name() + "occ_dist") - .desc("IQ Occupancy per cycle") - .flags(total | cdf) - ; - - inst_count - .init(1) - .name(name() + "cum_num_insts") - .desc("Total occupancy") - .flags(total) - ; - - peak_inst_count - .init(1) - .name(name() + "peak_occupancy") - .desc("Peak IQ occupancy") - .flags(total) - ; - - current_count - .name(name() + "current_count") - .desc("Occupancy this cycle") - ; - - empty_count - .name(name() + "empty_count") - .desc("Number of empty cycles") - ; - - fullCount - .name(name() + "full_count") - .desc("Number of full cycles") - ; - - - occ_rate - .name(name() + "occ_rate") - .desc("Average occupancy") - .flags(total) - ; - occ_rate = inst_count / be->cpu->numCycles; - - avg_residency - .name(name() + "avg_residency") - .desc("Average IQ residency") - .flags(total) - ; - avg_residency = occ_rate / be->cpu->numCycles; - - empty_rate - .name(name() + "empty_rate") - .desc("Fraction of cycles empty") - ; - empty_rate = 100 * empty_count / be->cpu->numCycles; - - full_rate - .name(name() + "full_rate") - .desc("Fraction of cycles full") - ; - full_rate = 100 * fullCount / be->cpu->numCycles; -} - -template <class Impl> -void -BackEnd<Impl>::InstQueue::setIssueExecQueue(TimeBuffer<IssueToExec> *i2e_queue) -{ - i2e = i2e_queue; - numIssued = i2e->getWire(0); -} - -template <class Impl> -void -BackEnd<Impl>::InstQueue::insert(DynInstPtr &inst) -{ - numInsts++; - inst_count[0]++; - if (!inst->isNonSpeculative()) { - DPRINTF(BE, "Instruction [sn:%lli] added to IQ\n", inst->seqNum); - if (inst->readyToIssue()) { - toBeScheduled.push_front(inst); - inst->iqIt = toBeScheduled.begin(); - inst->iqItValid = true; - } else { - iq.push_front(inst); - inst->iqIt = iq.begin(); - inst->iqItValid = true; - } - } else { - DPRINTF(BE, "Nonspeculative instruction [sn:%lli] added to IQ\n", inst->seqNum); - nonSpec.push_front(inst); - inst->iqIt = nonSpec.begin(); - inst->iqItValid = true; - } -} - -template <class Impl> -void -BackEnd<Impl>::InstQueue::scheduleReadyInsts() -{ - int scheduled = numIssued->size; - InstListIt iq_it = --toBeScheduled.end(); - InstListIt iq_end_it = toBeScheduled.end(); - - while (iq_it != iq_end_it && scheduled < width) { -// if ((*iq_it)->readyToIssue()) { - DPRINTF(BE, "Instruction [sn:%lli] PC:%#x is ready\n", - (*iq_it)->seqNum, (*iq_it)->readPC()); - readyQueue.push(*iq_it); - readyList.push_front(*iq_it); - - (*iq_it)->iqIt = readyList.begin(); - - toBeScheduled.erase(iq_it--); - - ++scheduled; -// } else { -// iq_it++; -// } - } - - numIssued->size+= scheduled; -} - -template <class Impl> -void -BackEnd<Impl>::InstQueue::scheduleNonSpec(const InstSeqNum &sn) -{ -/* - InstListIt non_spec_it = nonSpec.begin(); - InstListIt non_spec_end_it = nonSpec.end(); - - while ((*non_spec_it)->seqNum != sn) { - non_spec_it++; - assert(non_spec_it != non_spec_end_it); - } -*/ - DynInstPtr inst = nonSpec.back(); - - DPRINTF(BE, "Nonspeculative instruction [sn:%lli] scheduled\n", inst->seqNum); - - assert(inst->seqNum == sn); - - assert(find(NonSpec, inst->iqIt)); - nonSpec.erase(inst->iqIt); - readyList.push_front(inst); - inst->iqIt = readyList.begin(); - readyQueue.push(inst); - numIssued->size++; -} - -template <class Impl> -typename Impl::DynInstPtr -BackEnd<Impl>::InstQueue::getReadyInst() -{ - assert(!readyList.empty()); - - DynInstPtr inst = readyQueue.top(); - readyQueue.pop(); - assert(find(ReadyList, inst->iqIt)); - readyList.erase(inst->iqIt); - inst->iqItValid = false; -// if (!inst->isMemRef()) - --numInsts; - return inst; -} - -template <class Impl> -void -BackEnd<Impl>::InstQueue::squash(const InstSeqNum &sn) -{ - InstListIt iq_it = iq.begin(); - InstListIt iq_end_it = iq.end(); - - while (iq_it != iq_end_it && (*iq_it)->seqNum > sn) { - DPRINTF(BE, "Instruction [sn:%lli] removed from IQ\n", (*iq_it)->seqNum); - (*iq_it)->iqItValid = false; - iq.erase(iq_it++); - --numInsts; - } - - iq_it = nonSpec.begin(); - iq_end_it = nonSpec.end(); - - while (iq_it != iq_end_it && (*iq_it)->seqNum > sn) { - DPRINTF(BE, "Instruction [sn:%lli] removed from IQ\n", (*iq_it)->seqNum); - (*iq_it)->iqItValid = false; - nonSpec.erase(iq_it++); - --numInsts; - } - - iq_it = replayList.begin(); - iq_end_it = replayList.end(); - - while (iq_it != iq_end_it) { - if ((*iq_it)->seqNum > sn) { - DPRINTF(BE, "Instruction [sn:%lli] removed from IQ\n", (*iq_it)->seqNum); - (*iq_it)->iqItValid = false; - replayList.erase(iq_it++); - --numInsts; - } else { - iq_it++; - } - } - - assert(numInsts >= 0); -/* - InstListIt ready_it = readyList.begin(); - InstListIt ready_end_it = readyList.end(); - - while (ready_it != ready_end_it) { - if ((*ready_it)->seqNum > sn) { - readyList.erase(ready_it++); - } else { - ready_it++; - } - } -*/ -} - -template <class Impl> -int -BackEnd<Impl>::InstQueue::wakeDependents(DynInstPtr &inst) -{ - assert(!inst->isSquashed()); - std::vector<DynInstPtr> &dependents = inst->getDependents(); - int num_outputs = dependents.size(); - - DPRINTF(BE, "Waking instruction [sn:%lli] dependents in IQ\n", inst->seqNum); - - for (int i = 0; i < num_outputs; i++) { - DynInstPtr dep_inst = dependents[i]; - dep_inst->markSrcRegReady(); - DPRINTF(BE, "Marking source reg ready [sn:%lli] in IQ\n", dep_inst->seqNum); - - if (dep_inst->readyToIssue() && dep_inst->iqItValid) { - if (dep_inst->isNonSpeculative()) { - assert(find(NonSpec, dep_inst->iqIt)); - nonSpec.erase(dep_inst->iqIt); - } else { - assert(find(IQ, dep_inst->iqIt)); - iq.erase(dep_inst->iqIt); - } - - toBeScheduled.push_front(dep_inst); - dep_inst->iqIt = toBeScheduled.begin(); - } - } - return num_outputs; -} - -template <class Impl> -void -BackEnd<Impl>::InstQueue::rescheduleMemInst(DynInstPtr &inst) -{ - DPRINTF(BE, "Rescheduling memory instruction [sn:%lli]\n", inst->seqNum); - assert(!inst->iqItValid); - replayList.push_front(inst); - inst->iqIt = replayList.begin(); - inst->iqItValid = true; - ++numInsts; -} - -template <class Impl> -void -BackEnd<Impl>::InstQueue::replayMemInst(DynInstPtr &inst) -{ - DPRINTF(BE, "Replaying memory instruction [sn:%lli]\n", inst->seqNum); - assert(find(ReplayList, inst->iqIt)); - InstListIt iq_it = --replayList.end(); - InstListIt iq_end_it = replayList.end(); - while (iq_it != iq_end_it) { - DynInstPtr rescheduled_inst = (*iq_it); - - DPRINTF(BE, "Memory instruction [sn:%lli] also replayed\n", inst->seqNum); - replayList.erase(iq_it--); - toBeScheduled.push_front(rescheduled_inst); - rescheduled_inst->iqIt = toBeScheduled.begin(); - } -} - -template <class Impl> -void -BackEnd<Impl>::InstQueue::completeMemInst(DynInstPtr &inst) -{ - panic("Not implemented."); -} - -template <class Impl> -bool -BackEnd<Impl>::InstQueue::find(queue q, InstListIt it) -{ - InstListIt iq_it, iq_end_it; - switch(q) { - case NonSpec: - iq_it = nonSpec.begin(); - iq_end_it = nonSpec.end(); - break; - case IQ: - iq_it = iq.begin(); - iq_end_it = iq.end(); - break; - case ToBeScheduled: - iq_it = toBeScheduled.begin(); - iq_end_it = toBeScheduled.end(); - break; - case ReadyList: - iq_it = readyList.begin(); - iq_end_it = readyList.end(); - break; - case ReplayList: - iq_it = replayList.begin(); - iq_end_it = replayList.end(); - } - - while (iq_it != it && iq_it != iq_end_it) { - iq_it++; - } - if (iq_it == it) { - return true; - } else { - return false; - } -} - -template <class Impl> -void -BackEnd<Impl>::InstQueue::dumpInsts() -{ - cprintf("IQ size: %i\n", iq.size()); - - InstListIt inst_list_it = --iq.end(); - - int num = 0; - int valid_num = 0; - while (inst_list_it != iq.end()) - { - cprintf("Instruction:%i\n", - num); - if (!(*inst_list_it)->isSquashed()) { - if (!(*inst_list_it)->isIssued()) { - ++valid_num; - cprintf("Count:%i\n", valid_num); - } else if ((*inst_list_it)->isMemRef() && - !(*inst_list_it)->memOpDone) { - // Loads that have not been marked as executed still count - // towards the total instructions. - ++valid_num; - cprintf("Count:%i\n", valid_num); - } - } - - cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n" - "Issued:%i\nSquashed:%i\n", - (*inst_list_it)->readPC(), - (*inst_list_it)->seqNum, - (*inst_list_it)->threadNumber, - (*inst_list_it)->isIssued(), - (*inst_list_it)->isSquashed()); - - if ((*inst_list_it)->isMemRef()) { - cprintf("MemOpDone:%i\n", (*inst_list_it)->memOpDone); - } - - cprintf("\n"); - - inst_list_it--; - ++num; - } - - cprintf("nonSpec size: %i\n", nonSpec.size()); - - inst_list_it = --nonSpec.end(); - - while (inst_list_it != nonSpec.end()) - { - cprintf("Instruction:%i\n", - num); - if (!(*inst_list_it)->isSquashed()) { - if (!(*inst_list_it)->isIssued()) { - ++valid_num; - cprintf("Count:%i\n", valid_num); - } else if ((*inst_list_it)->isMemRef() && - !(*inst_list_it)->memOpDone) { - // Loads that have not been marked as executed still count - // towards the total instructions. - ++valid_num; - cprintf("Count:%i\n", valid_num); - } - } - - cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n" - "Issued:%i\nSquashed:%i\n", - (*inst_list_it)->readPC(), - (*inst_list_it)->seqNum, - (*inst_list_it)->threadNumber, - (*inst_list_it)->isIssued(), - (*inst_list_it)->isSquashed()); - - if ((*inst_list_it)->isMemRef()) { - cprintf("MemOpDone:%i\n", (*inst_list_it)->memOpDone); - } - - cprintf("\n"); - - inst_list_it--; - ++num; - } - - cprintf("toBeScheduled size: %i\n", toBeScheduled.size()); - - inst_list_it = --toBeScheduled.end(); - - while (inst_list_it != toBeScheduled.end()) - { - cprintf("Instruction:%i\n", - num); - if (!(*inst_list_it)->isSquashed()) { - if (!(*inst_list_it)->isIssued()) { - ++valid_num; - cprintf("Count:%i\n", valid_num); - } else if ((*inst_list_it)->isMemRef() && - !(*inst_list_it)->memOpDone) { - // Loads that have not been marked as executed still count - // towards the total instructions. - ++valid_num; - cprintf("Count:%i\n", valid_num); - } - } - - cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n" - "Issued:%i\nSquashed:%i\n", - (*inst_list_it)->readPC(), - (*inst_list_it)->seqNum, - (*inst_list_it)->threadNumber, - (*inst_list_it)->isIssued(), - (*inst_list_it)->isSquashed()); - - if ((*inst_list_it)->isMemRef()) { - cprintf("MemOpDone:%i\n", (*inst_list_it)->memOpDone); - } - - cprintf("\n"); - - inst_list_it--; - ++num; - } - - cprintf("readyList size: %i\n", readyList.size()); - - inst_list_it = --readyList.end(); - - while (inst_list_it != readyList.end()) - { - cprintf("Instruction:%i\n", - num); - if (!(*inst_list_it)->isSquashed()) { - if (!(*inst_list_it)->isIssued()) { - ++valid_num; - cprintf("Count:%i\n", valid_num); - } else if ((*inst_list_it)->isMemRef() && - !(*inst_list_it)->memOpDone) { - // Loads that have not been marked as executed still count - // towards the total instructions. - ++valid_num; - cprintf("Count:%i\n", valid_num); - } - } - - cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n" - "Issued:%i\nSquashed:%i\n", - (*inst_list_it)->readPC(), - (*inst_list_it)->seqNum, - (*inst_list_it)->threadNumber, - (*inst_list_it)->isIssued(), - (*inst_list_it)->isSquashed()); - - if ((*inst_list_it)->isMemRef()) { - cprintf("MemOpDone:%i\n", (*inst_list_it)->memOpDone); - } - - cprintf("\n"); - - inst_list_it--; - ++num; - } -} - -template<class Impl> -BackEnd<Impl>::LdWritebackEvent::LdWritebackEvent(DynInstPtr &_inst, - BackEnd<Impl> *_be) - : Event(&mainEventQueue), inst(_inst), be(_be) -{ - this->setFlags(Event::AutoDelete); -} - -template<class Impl> -void -BackEnd<Impl>::LdWritebackEvent::process() -{ - DPRINTF(BE, "Load writeback event [sn:%lli]\n", inst->seqNum); -// DPRINTF(Activity, "Activity: Ld Writeback event [sn:%lli]\n", inst->seqNum); - - //iewStage->ldstQueue.removeMSHR(inst->threadNumber,inst->seqNum); - -// iewStage->wakeCPU(); - - if (inst->isSquashed()) { - inst = NULL; - return; - } - - if (!inst->isExecuted()) { - inst->setExecuted(); - - // Execute again to copy data to proper place. - inst->completeAcc(); - } - - // Need to insert instruction into queue to commit - be->instToCommit(inst); - - //wroteToTimeBuffer = true; -// iewStage->activityThisCycle(); - - inst = NULL; -} - -template<class Impl> -const char * -BackEnd<Impl>::LdWritebackEvent::description() const -{ - return "Load writeback"; -} - - -template <class Impl> -BackEnd<Impl>::DCacheCompletionEvent::DCacheCompletionEvent(BackEnd *_be) - : Event(&mainEventQueue, CPU_Tick_Pri), be(_be) -{ -} - -template <class Impl> -void -BackEnd<Impl>::DCacheCompletionEvent::process() -{ -} - -template <class Impl> -const char * -BackEnd<Impl>::DCacheCompletionEvent::description() const -{ - return "Cache completion"; -} - -template <class Impl> -BackEnd<Impl>::BackEnd(Params *params) - : d2i(5, 5), i2e(5, 5), e2c(5, 5), numInstsToWB(5, 5), - xcSquash(false), IQ(params), - cacheCompletionEvent(this), width(params->backEndWidth), - exactFullStall(true) -{ - numROBEntries = params->numROBEntries; - numInsts = 0; - numDispatchEntries = 32; - IQ.setBE(this); - LSQ.setBE(this); - - // Setup IQ and LSQ with their parameters here. - instsToDispatch = d2i.getWire(-1); - - instsToExecute = i2e.getWire(-1); - - IQ.setIssueExecQueue(&i2e); - - dispatchWidth = params->dispatchWidth ? params->dispatchWidth : width; - issueWidth = params->issueWidth ? params->issueWidth : width; - wbWidth = params->wbWidth ? params->wbWidth : width; - commitWidth = params->commitWidth ? params->commitWidth : width; - - LSQ.init(params, params->LQEntries, params->SQEntries, 0); - - dispatchStatus = Running; -} - -template <class Impl> -std::string -BackEnd<Impl>::name() const -{ - return cpu->name() + ".backend"; -} - -template <class Impl> -void -BackEnd<Impl>::regStats() -{ - using namespace Stats; - rob_cap_events - .init(cpu->numThreads) - .name(name() + ".ROB:cap_events") - .desc("number of cycles where ROB cap was active") - .flags(total) - ; - - rob_cap_inst_count - .init(cpu->numThreads) - .name(name() + ".ROB:cap_inst") - .desc("number of instructions held up by ROB cap") - .flags(total) - ; - - iq_cap_events - .init(cpu->numThreads) - .name(name() +".IQ:cap_events" ) - .desc("number of cycles where IQ cap was active") - .flags(total) - ; - - iq_cap_inst_count - .init(cpu->numThreads) - .name(name() + ".IQ:cap_inst") - .desc("number of instructions held up by IQ cap") - .flags(total) - ; - - - exe_inst - .init(cpu->numThreads) - .name(name() + ".ISSUE:count") - .desc("number of insts issued") - .flags(total) - ; - - exe_swp - .init(cpu->numThreads) - .name(name() + ".ISSUE:swp") - .desc("number of swp insts issued") - .flags(total) - ; - - exe_nop - .init(cpu->numThreads) - .name(name() + ".ISSUE:nop") - .desc("number of nop insts issued") - .flags(total) - ; - - exe_refs - .init(cpu->numThreads) - .name(name() + ".ISSUE:refs") - .desc("number of memory reference insts issued") - .flags(total) - ; - - exe_loads - .init(cpu->numThreads) - .name(name() + ".ISSUE:loads") - .desc("number of load insts issued") - .flags(total) - ; - - exe_branches - .init(cpu->numThreads) - .name(name() + ".ISSUE:branches") - .desc("Number of branches issued") - .flags(total) - ; - - issued_ops - .init(cpu->numThreads) - .name(name() + ".ISSUE:op_count") - .desc("number of insts issued") - .flags(total) - ; - -/* - 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(cpu->numThreads) - .name(name() + ".LSQ:forw_loads") - .desc("number of loads forwarded via LSQ") - .flags(total) - ; - - inv_addr_loads - .init(cpu->numThreads) - .name(name() + ".ISSUE:addr_loads") - .desc("number of invalid-address loads") - .flags(total) - ; - - inv_addr_swpfs - .init(cpu->numThreads) - .name(name() + ".ISSUE:addr_swpfs") - .desc("number of invalid-address SW prefetches") - .flags(total) - ; - - lsq_blocked_loads - .init(cpu->numThreads) - .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") - ; - - n_issued_dist - .init(issueWidth + 1) - .name(name() + ".ISSUE:issued_per_cycle") - .desc("Number of insts issued each cycle") - .flags(total | pdf | dist) - ; - issue_delay_dist - .init(Num_OpClasses,0,99,2) - .name(name() + ".ISSUE:") - .desc("cycles from operands ready to issue") - .flags(pdf | cdf) - ; - - 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]); - } - - writeback_count - .init(cpu->numThreads) - .name(name() + ".WB:count") - .desc("cumulative count of insts written-back") - .flags(total) - ; - - producer_inst - .init(cpu->numThreads) - .name(name() + ".WB:producers") - .desc("num instructions producing a value") - .flags(total) - ; - - consumer_inst - .init(cpu->numThreads) - .name(name() + ".WB:consumers") - .desc("num instructions consuming a value") - .flags(total) - ; - - wb_penalized - .init(cpu->numThreads) - .name(name() + ".WB:penalized") - .desc("number of instrctions required to write to 'other' IQ") - .flags(total) - ; - - - 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 / cpu->numCycles; - - stat_com_inst - .init(cpu->numThreads) - .name(name() + ".COM:count") - .desc("Number of instructions committed") - .flags(total) - ; - - stat_com_swp - .init(cpu->numThreads) - .name(name() + ".COM:swp_count") - .desc("Number of s/w prefetches committed") - .flags(total) - ; - - stat_com_refs - .init(cpu->numThreads) - .name(name() + ".COM:refs") - .desc("Number of memory references committed") - .flags(total) - ; - - stat_com_loads - .init(cpu->numThreads) - .name(name() + ".COM:loads") - .desc("Number of loads committed") - .flags(total) - ; - - stat_com_membars - .init(cpu->numThreads) - .name(name() + ".COM:membars") - .desc("Number of memory barriers committed") - .flags(total) - ; - - stat_com_branches - .init(cpu->numThreads) - .name(name() + ".COM:branches") - .desc("Number of branches committed") - .flags(total) - ; - n_committed_dist - .init(0,commitWidth,1) - .name(name() + ".COM:committed_per_cycle") - .desc("Number of insts commited each cycle") - .flags(pdf) - ; - - // - // Commit-Eligible instructions... - // - // -> The number of instructions eligible to commit in those - // cycles where we reached our commit BW limit (less the number - // actually committed) - // - // -> The average value is computed over ALL CYCLES... not just - // the BW limited cycles - // - // -> The standard deviation is computed only over cycles where - // we reached the BW limit - // - commit_eligible - .init(cpu->numThreads) - .name(name() + ".COM:bw_limited") - .desc("number of insts not committed due to BW limits") - .flags(total) - ; - - commit_eligible_samples - .name(name() + ".COM:bw_lim_events") - .desc("number cycles where commit BW limit reached") - ; - - ROB_fcount - .name(name() + ".ROB:full_count") - .desc("number of cycles where ROB was full") - ; - - ROB_count - .init(cpu->numThreads) - .name(name() + ".ROB:occupancy") - .desc(name() + ".ROB occupancy (cumulative)") - .flags(total) - ; - - ROB_full_rate - .name(name() + ".ROB:full_rate") - .desc("ROB full per cycle") - ; - ROB_full_rate = ROB_fcount / cpu->numCycles; - - ROB_occ_rate - .name(name() + ".ROB:occ_rate") - .desc("ROB occupancy rate") - .flags(total) - ; - ROB_occ_rate = ROB_count / cpu->numCycles; - - ROB_occ_dist - .init(cpu->numThreads, 0, numROBEntries, 2) - .name(name() + ".ROB:occ_dist") - .desc("ROB Occupancy per cycle") - .flags(total | cdf) - ; - - IQ.regStats(); -} - -template <class Impl> -void -BackEnd<Impl>::setCommBuffer(TimeBuffer<CommStruct> *_comm) -{ - comm = _comm; - toIEW = comm->getWire(0); - fromCommit = comm->getWire(-1); -} - -template <class Impl> -void -BackEnd<Impl>::tick() -{ - DPRINTF(BE, "Ticking back end\n"); - - ROB_count[0]+= numInsts; - - wbCycle = 0; - - if (xcSquash) { - squashFromXC(); - } - - // Read in any done instruction information and update the IQ or LSQ. - updateStructures(); - - if (dispatchStatus != Blocked) { - d2i.advance(); - dispatchInsts(); - } else { - checkDispatchStatus(); - } - - i2e.advance(); - scheduleReadyInsts(); - - e2c.advance(); - executeInsts(); - - numInstsToWB.advance(); - writebackInsts(); - - commitInsts(); - - DPRINTF(BE, "IQ entries in use: %i, ROB entries in use: %i, LSQ loads: %i, LSQ stores: %i\n", - IQ.numInsts, numInsts, LSQ.numLoads(), LSQ.numStores()); - - assert(numInsts == instList.size()); -} - -template <class Impl> -void -BackEnd<Impl>::updateStructures() -{ - if (fromCommit->doneSeqNum) { - IQ.commit(fromCommit->doneSeqNum); - LSQ.commitLoads(fromCommit->doneSeqNum); - LSQ.commitStores(fromCommit->doneSeqNum); - } - - if (fromCommit->nonSpecSeqNum) { - if (fromCommit->uncached) { - LSQ.executeLoad(fromCommit->lqIdx); - } else { - IQ.scheduleNonSpec( - fromCommit->nonSpecSeqNum); - } - } -} - -template <class Impl> -void -BackEnd<Impl>::addToIQ(DynInstPtr &inst) -{ - // Do anything IQ specific here? - IQ.insert(inst); -} - -template <class Impl> -void -BackEnd<Impl>::addToLSQ(DynInstPtr &inst) -{ - // Do anything LSQ specific here? - LSQ.insert(inst); -} - -template <class Impl> -void -BackEnd<Impl>::dispatchInsts() -{ - DPRINTF(BE, "Trying to dispatch instructions.\n"); - - // Pull instructions out of the front end. - int disp_width = dispatchWidth ? dispatchWidth : width; - - // Could model dispatching time, but in general 1 cycle is probably - // good enough. - - if (dispatchSize < numDispatchEntries) { - for (int i = 0; i < disp_width; i++) { - // Get instructions - DynInstPtr inst = frontEnd->getInst(); - - if (!inst) { - // No more instructions to get - break; - } - - DPRINTF(BE, "Processing instruction [sn:%lli] PC:%#x\n", - inst->seqNum, inst->readPC()); - - for (int i = 0; i < inst->numDestRegs(); ++i) - renameTable[inst->destRegIdx(i)] = inst; - - // Add to queue to be dispatched. - dispatch.push_back(inst); - - d2i[0].size++; - ++dispatchSize; - } - } - - assert(dispatch.size() < 64); - - for (int i = 0; i < instsToDispatch->size; ++i) { - assert(!dispatch.empty()); - // Get instruction from front of time buffer - DynInstPtr inst = dispatch.front(); - dispatch.pop_front(); - --dispatchSize; - - if (inst->isSquashed()) - continue; - - ++numInsts; - instList.push_back(inst); - - DPRINTF(BE, "Dispatching instruction [sn:%lli] PC:%#x\n", - inst->seqNum, inst->readPC()); - - addToIQ(inst); - - if (inst->isMemRef()) { - addToLSQ(inst); - } - - if (inst->isNonSpeculative()) { - inst->setCanCommit(); - } - - // Check if IQ or LSQ is full. If so we'll need to break and stop - // removing instructions. Also update the number of insts to remove - // from the queue. - if (exactFullStall) { - bool stall = false; - if (IQ.isFull()) { - DPRINTF(BE, "IQ is full!\n"); - stall = true; - } else if (LSQ.isFull()) { - DPRINTF(BE, "LSQ is full!\n"); - stall = true; - } else if (isFull()) { - DPRINTF(BE, "ROB is full!\n"); - stall = true; - ROB_fcount++; - } - if (stall) { - instsToDispatch->size-= i+1; - dispatchStall(); - return; - } - } - } - - // Check if IQ or LSQ is full. If so we'll need to break and stop - // removing instructions. Also update the number of insts to remove - // from the queue. Check here if we don't care about exact stall - // conditions. - - bool stall = false; - if (IQ.isFull()) { - DPRINTF(BE, "IQ is full!\n"); - stall = true; - } else if (LSQ.isFull()) { - DPRINTF(BE, "LSQ is full!\n"); - stall = true; - } else if (isFull()) { - DPRINTF(BE, "ROB is full!\n"); - stall = true; - ROB_fcount++; - } - if (stall) { - d2i.advance(); - dispatchStall(); - return; - } -} - -template <class Impl> -void -BackEnd<Impl>::dispatchStall() -{ - dispatchStatus = Blocked; - if (!cpu->decoupledFrontEnd) { - // Tell front end to stall here through a timebuffer, or just tell - // it directly. - } -} - -template <class Impl> -void -BackEnd<Impl>::checkDispatchStatus() -{ - DPRINTF(BE, "Checking dispatch status\n"); - assert(dispatchStatus == Blocked); - if (!IQ.isFull() && !LSQ.isFull() && !isFull()) { - DPRINTF(BE, "Dispatch no longer blocked\n"); - dispatchStatus = Running; - dispatchInsts(); - } -} - -template <class Impl> -void -BackEnd<Impl>::scheduleReadyInsts() -{ - // Tell IQ to put any ready instructions into the instruction list. - // Probably want to have a list of DynInstPtrs returned here. Then I - // can choose to either put them into a time buffer to simulate - // IQ scheduling time, or hand them directly off to the next stage. - // Do you ever want to directly hand it off to the next stage? - DPRINTF(BE, "Trying to schedule ready instructions\n"); - IQ.scheduleReadyInsts(); -} - -template <class Impl> -void -BackEnd<Impl>::executeInsts() -{ - int insts_to_execute = instsToExecute->size; - - issued_ops[0]+= insts_to_execute; - n_issued_dist[insts_to_execute]++; - - DPRINTF(BE, "Trying to execute %i instructions\n", insts_to_execute); - - fetchRedirect[0] = false; - - while (insts_to_execute > 0) { - // Get ready instruction from the IQ (or queue coming out of IQ) - // Execute the ready instruction. - // Wakeup any dependents if it's done. - DynInstPtr inst = IQ.getReadyInst(); - - DPRINTF(BE, "Executing inst [sn:%lli] PC: %#x\n", - inst->seqNum, inst->readPC()); - - ++funcExeInst; - - // Check if the instruction is squashed; if so then skip it - // and don't count it towards the FU usage. - if (inst->isSquashed()) { - DPRINTF(BE, "Execute: Instruction was squashed.\n"); - - // Not sure how to handle this plus the method of sending # of - // instructions to use. Probably will just have to count it - // towards the bandwidth usage, but not the FU usage. - --insts_to_execute; - - // Consider this instruction executed so that commit can go - // ahead and retire the instruction. - inst->setExecuted(); - - // Not sure if I should set this here or just let commit try to - // commit any squashed instructions. I like the latter a bit more. - inst->setCanCommit(); - -// ++iewExecSquashedInsts; - - continue; - } - - Fault fault = NoFault; - - // Execute instruction. - // Note that if the instruction faults, it will be handled - // at the commit stage. - if (inst->isMemRef() && - (!inst->isDataPrefetch() && !inst->isInstPrefetch())) { - DPRINTF(BE, "Execute: Initiating access for memory " - "reference.\n"); - - // Tell the LDSTQ to execute this instruction (if it is a load). - if (inst->isLoad()) { - // Loads will mark themselves as executed, and their writeback - // event adds the instruction to the queue to commit - fault = LSQ.executeLoad(inst); - -// ++iewExecLoadInsts; - } else if (inst->isStore()) { - LSQ.executeStore(inst); - -// ++iewExecStoreInsts; - - if (!(inst->req->isLLSC())) { - inst->setExecuted(); - - instToCommit(inst); - } - // Store conditionals will mark themselves as executed, and - // their writeback event will add the instruction to the queue - // to commit. - } else { - panic("Unexpected memory type!\n"); - } - - } else { - inst->execute(); - -// ++iewExecutedInsts; - - inst->setExecuted(); - - instToCommit(inst); - } - - updateExeInstStats(inst); - - // Probably should have some sort of function for this. - // More general question of how to handle squashes? Have some sort of - // squash unit that controls it? Probably... - // Check if branch was correct. This check happens after the - // instruction is added to the queue because even if the branch - // is mispredicted, the branch instruction itself is still valid. - // Only handle this if there hasn't already been something that - // redirects fetch in this group of instructions. - - // This probably needs to prioritize the redirects if a different - // scheduler is used. Currently the scheduler schedules the oldest - // instruction first, so the branch resolution order will be correct. - ThreadID tid = inst->threadNumber; - - if (!fetchRedirect[tid]) { - - if (inst->mispredicted()) { - fetchRedirect[tid] = true; - - DPRINTF(BE, "Execute: Branch mispredict detected.\n"); - DPRINTF(BE, "Execute: Redirecting fetch to PC: %#x.\n", - inst->nextPC); - - // If incorrect, then signal the ROB that it must be squashed. - squashDueToBranch(inst); - - if (inst->predTaken()) { -// predictedTakenIncorrect++; - } else { -// predictedNotTakenIncorrect++; - } - } else if (LSQ.violation()) { - fetchRedirect[tid] = true; - - // Get the DynInst that caused the violation. Note that this - // clears the violation signal. - DynInstPtr violator; - violator = LSQ.getMemDepViolator(); - - DPRINTF(BE, "LDSTQ detected a violation. Violator PC: " - "%#x, inst PC: %#x. Addr is: %#x.\n", - violator->readPC(), inst->readPC(), inst->physEffAddr); - - // Tell the instruction queue that a violation has occured. -// IQ.violation(inst, violator); - - // Squash. -// squashDueToMemOrder(inst,tid); - squashDueToBranch(inst); - -// ++memOrderViolationEvents; - } else if (LSQ.loadBlocked()) { - fetchRedirect[tid] = true; - - DPRINTF(BE, "Load operation couldn't execute because the " - "memory system is blocked. PC: %#x [sn:%lli]\n", - inst->readPC(), inst->seqNum); - - squashDueToMemBlocked(inst); - } - } - -// instList.pop_front(); - - --insts_to_execute; - - // keep an instruction count - thread->numInst++; - thread->numInsts++; - } - - assert(insts_to_execute >= 0); -} - -template<class Impl> -void -BackEnd<Impl>::instToCommit(DynInstPtr &inst) -{ - int wb_width = wbWidth; - // First check the time slot that this instruction will write - // to. If there are free write ports at the time, then go ahead - // and write the instruction to that time. If there are not, - // keep looking back to see where's the first time there's a - // free slot. What happens if you run out of free spaces? - // For now naively assume that all instructions take one cycle. - // Otherwise would have to look into the time buffer based on the - // latency of the instruction. - - DPRINTF(BE, "Sending instructions to commit [sn:%lli] PC %#x.\n", - inst->seqNum, inst->readPC()); - - while (numInstsToWB[wbCycle].size >= wb_width) { - ++wbCycle; - - assert(wbCycle < 5); - } - - // Add finished instruction to queue to commit. - writeback.push_back(inst); - numInstsToWB[wbCycle].size++; - - if (wbCycle) - wb_penalized[0]++; -} - -template <class Impl> -void -BackEnd<Impl>::writebackInsts() -{ - int wb_width = wbWidth; - // Using this method I'm not quite sure how to prevent an - // instruction from waking its own dependents multiple times, - // without the guarantee that commit always has enough bandwidth - // to accept all instructions being written back. This guarantee - // might not be too unrealistic. - InstListIt wb_inst_it = writeback.begin(); - InstListIt wb_end_it = writeback.end(); - int inst_num = 0; - int consumer_insts = 0; - - for (; inst_num < wb_width && - wb_inst_it != wb_end_it; inst_num++) { - DynInstPtr inst = (*wb_inst_it); - - // Some instructions will be sent to commit without having - // executed because they need commit to handle them. - // E.g. Uncached loads have not actually executed when they - // are first sent to commit. Instead commit must tell the LSQ - // when it's ready to execute the uncached load. - if (!inst->isSquashed()) { - DPRINTF(BE, "Writing back instruction [sn:%lli] PC %#x.\n", - inst->seqNum, inst->readPC()); - - inst->setCanCommit(); - inst->setResultReady(); - - if (inst->isExecuted()) { - int dependents = IQ.wakeDependents(inst); - if (dependents) { - producer_inst[0]++; - consumer_insts+= dependents; - } - } - } - - writeback.erase(wb_inst_it++); - } - LSQ.writebackStores(); - consumer_inst[0]+= consumer_insts; - writeback_count[0]+= inst_num; -} - -template <class Impl> -bool -BackEnd<Impl>::commitInst(int inst_num) -{ - // Read instruction from the head of the ROB - DynInstPtr inst = instList.front(); - - // Make sure instruction is valid - assert(inst); - - if (!inst->readyToCommit()) - return false; - - DPRINTF(BE, "Trying to commit instruction [sn:%lli] PC:%#x\n", - inst->seqNum, inst->readPC()); - - // If the instruction is not executed yet, then it is a non-speculative - // or store inst. Signal backwards that it should be executed. - if (!inst->isExecuted()) { - // Keep this number correct. We have not yet actually executed - // and committed this instruction. -// thread->funcExeInst--; - - if (inst->isNonSpeculative()) { - // Hack to make sure syscalls aren't executed until all stores - // write back their data. This direct communication shouldn't - // be used for anything other than this. - if (inst_num > 0 || LSQ.hasStoresToWB()) { - DPRINTF(BE, "Waiting for all stores to writeback.\n"); - return false; - } - - DPRINTF(BE, "Encountered a store or non-speculative " - "instruction at the head of the ROB, PC %#x.\n", - inst->readPC()); - - // Send back the non-speculative instruction's sequence number. - toIEW->nonSpecSeqNum = inst->seqNum; - - // Change the instruction so it won't try to commit again until - // it is executed. - inst->clearCanCommit(); - -// ++commitNonSpecStalls; - - return false; - } else if (inst->isLoad()) { - DPRINTF(BE, "[sn:%lli]: Uncached load, PC %#x.\n", - inst->seqNum, inst->readPC()); - - // Send back the non-speculative instruction's sequence - // number. Maybe just tell the lsq to re-execute the load. - toIEW->nonSpecSeqNum = inst->seqNum; - toIEW->uncached = true; - toIEW->lqIdx = inst->lqIdx; - - inst->clearCanCommit(); - - return false; - } else { - panic("Trying to commit un-executed instruction " - "of unknown type!\n"); - } - } - - // Now check if it's one of the special trap or barrier or - // serializing instructions. - if (inst->isThreadSync()) - { - // Not handled for now. - panic("Barrier instructions are not handled yet.\n"); - } - - // Check if the instruction caused a fault. If so, trap. - Fault inst_fault = inst->getFault(); - - if (inst_fault != NoFault) { - if (!inst->isNop()) { - DPRINTF(BE, "Inst [sn:%lli] PC %#x has a fault\n", - inst->seqNum, inst->readPC()); - -// assert(!thread->noSquashFromTC); - -// thread->noSquashFromTC = true; - - // Consider holding onto the trap and waiting until the trap event - // happens for this to be executed. - inst_fault->invoke(thread->getXCProxy()); - - // Exit state update mode to avoid accidental updating. -// thread->noSquashFromTC = false; - -// commitStatus = TrapPending; - - // Generate trap squash event. -// generateTrapEvent(); - - return false; - } - } - - if (inst->isControl()) { -// ++commitCommittedBranches; - } - - int freed_regs = 0; - - for (int i = 0; i < inst->numDestRegs(); ++i) { - DPRINTF(BE, "Commit rename map setting register %i to [sn:%lli]\n", - (int)inst->destRegIdx(i), inst->seqNum); - thread->renameTable[inst->destRegIdx(i)] = inst; - ++freed_regs; - } - - if (inst->traceData) { - inst->traceData->finalize(); - inst->traceData = NULL; - } - - inst->clearDependents(); - - frontEnd->addFreeRegs(freed_regs); - - instList.pop_front(); - - --numInsts; - cpu->numInst++; - thread->numInsts++; - ++thread->funcExeInst; - thread->PC = inst->readNextPC(); - updateComInstStats(inst); - - // Write the done sequence number here. - toIEW->doneSeqNum = inst->seqNum; - - int count = 0; - Addr oldpc; - do { - if (count == 0) - assert(!thread->noSquashFromTC && !thread->trapPending); - oldpc = thread->readPC(); - cpu->system->pcEventQueue.service( - thread->getXCProxy()); - count++; - } while (oldpc != thread->readPC()); - if (count > 1) { - DPRINTF(BE, "PC skip function event, stopping commit\n"); -// completed_last_inst = false; -// squashPending = true; - return false; - } - return true; -} - -template <class Impl> -void -BackEnd<Impl>::commitInsts() -{ - int commit_width = commitWidth ? commitWidth : width; - - // Not sure this should be a loop or not. - int inst_num = 0; - while (!instList.empty() && inst_num < commit_width) { - if (instList.front()->isSquashed()) { - panic("No squashed insts should still be on the list!"); - instList.front()->clearDependents(); - instList.pop_front(); - continue; - } - - if (!commitInst(inst_num++)) { - break; - } - } - n_committed_dist.sample(inst_num); -} - -template <class Impl> -void -BackEnd<Impl>::squash(const InstSeqNum &sn) -{ - IQ.squash(sn); - LSQ.squash(sn); - - int freed_regs = 0; - InstListIt dispatch_end = dispatch.end(); - InstListIt insts_it = dispatch.end(); - insts_it--; - - while (insts_it != dispatch_end && (*insts_it)->seqNum > sn) - { - if ((*insts_it)->isSquashed()) { - --insts_it; - continue; - } - DPRINTF(BE, "Squashing instruction on dispatch list PC %#x, [sn:%lli].\n", - (*insts_it)->readPC(), - (*insts_it)->seqNum); - - // Mark the instruction as squashed, and ready to commit so that - // it can drain out of the pipeline. - (*insts_it)->setSquashed(); - - (*insts_it)->setCanCommit(); - - // Be careful with IPRs and such here - for (int i = 0; i < (*insts_it)->numDestRegs(); ++i) { - DynInstPtr prev_dest = (*insts_it)->getPrevDestInst(i); - DPRINTF(BE, "Commit rename map setting register %i to [sn:%lli]\n", - (int)(*insts_it)->destRegIdx(i), prev_dest); - renameTable[(*insts_it)->destRegIdx(i)] = prev_dest; - ++freed_regs; - } - - (*insts_it)->clearDependents(); - - --insts_it; - } - - insts_it = instList.end(); - insts_it--; - - while (!instList.empty() && (*insts_it)->seqNum > sn) - { - if ((*insts_it)->isSquashed()) { - --insts_it; - continue; - } - DPRINTF(BE, "Squashing instruction on inst list PC %#x, [sn:%lli].\n", - (*insts_it)->readPC(), - (*insts_it)->seqNum); - - // Mark the instruction as squashed, and ready to commit so that - // it can drain out of the pipeline. - (*insts_it)->setSquashed(); - - (*insts_it)->setCanCommit(); - - for (int i = 0; i < (*insts_it)->numDestRegs(); ++i) { - DynInstPtr prev_dest = (*insts_it)->getPrevDestInst(i); - DPRINTF(BE, "Commit rename map setting register %i to [sn:%lli]\n", - (int)(*insts_it)->destRegIdx(i), prev_dest); - renameTable[(*insts_it)->destRegIdx(i)] = prev_dest; - ++freed_regs; - } - - (*insts_it)->clearDependents(); - - instList.erase(insts_it--); - --numInsts; - } - - frontEnd->addFreeRegs(freed_regs); -} - -template <class Impl> -void -BackEnd<Impl>::squashFromXC() -{ - xcSquash = true; -} - -template <class Impl> -void -BackEnd<Impl>::squashDueToBranch(DynInstPtr &inst) -{ - // Update the branch predictor state I guess - squash(inst->seqNum); - frontEnd->squash(inst->seqNum, inst->readNextPC(), - true, inst->mispredicted()); -} - -template <class Impl> -void -BackEnd<Impl>::squashDueToMemBlocked(DynInstPtr &inst) -{ - DPRINTF(IEW, "Memory blocked, squashing load and younger insts, " - "PC: %#x [sn:%i].\n", inst->readPC(), inst->seqNum); - - squash(inst->seqNum - 1); - frontEnd->squash(inst->seqNum - 1, inst->readPC()); -} - -template <class Impl> -void -BackEnd<Impl>::fetchFault(Fault &fault) -{ - faultFromFetch = fault; -} - -template <class Impl> -void -BackEnd<Impl>::updateExeInstStats(DynInstPtr &inst) -{ - ThreadID tid = inst->threadNumber; - - exe_inst[tid]++; - - // - // Control operations - // - if (inst->isControl()) - exe_branches[tid]++; - - // - // Memory operations - // - if (inst->isMemRef()) { - exe_refs[tid]++; - - if (inst->isLoad()) - exe_loads[tid]++; - } -} - -template <class Impl> -void -BackEnd<Impl>::updateComInstStats(DynInstPtr &inst) -{ - ThreadID tid = inst->threadNumber; - - // - // Pick off the software prefetches - // -#ifdef TARGET_ALPHA - if (inst->isDataPrefetch()) { - stat_com_swp[tid]++; - } else { - stat_com_inst[tid]++; - } -#else - stat_com_inst[tid]++; -#endif - - // - // Control Instructions - // - if (inst->isControl()) - stat_com_branches[tid]++; - - // - // Memory references - // - if (inst->isMemRef()) { - stat_com_refs[tid]++; - - if (inst->isLoad()) { - stat_com_loads[tid]++; - } - } - - if (inst->isMemBarrier()) { - stat_com_membars[tid]++; - } -} - -template <class Impl> -void -BackEnd<Impl>::dumpInsts() -{ - int num = 0; - int valid_num = 0; - - InstListIt inst_list_it = instList.begin(); - - cprintf("Inst list size: %i\n", instList.size()); - - while (inst_list_it != instList.end()) - { - cprintf("Instruction:%i\n", - num); - if (!(*inst_list_it)->isSquashed()) { - if (!(*inst_list_it)->isIssued()) { - ++valid_num; - cprintf("Count:%i\n", valid_num); - } else if ((*inst_list_it)->isMemRef() && - !(*inst_list_it)->memOpDone) { - // Loads that have not been marked as executed still count - // towards the total instructions. - ++valid_num; - cprintf("Count:%i\n", valid_num); - } - } - - cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n" - "Issued:%i\nSquashed:%i\n", - (*inst_list_it)->readPC(), - (*inst_list_it)->seqNum, - (*inst_list_it)->threadNumber, - (*inst_list_it)->isIssued(), - (*inst_list_it)->isSquashed()); - - if ((*inst_list_it)->isMemRef()) { - cprintf("MemOpDone:%i\n", (*inst_list_it)->memOpDone); - } - - cprintf("\n"); - - inst_list_it++; - ++num; - } - - cprintf("Dispatch list size: %i\n", dispatch.size()); - - inst_list_it = dispatch.begin(); - - while (inst_list_it != dispatch.end()) - { - cprintf("Instruction:%i\n", - num); - if (!(*inst_list_it)->isSquashed()) { - if (!(*inst_list_it)->isIssued()) { - ++valid_num; - cprintf("Count:%i\n", valid_num); - } else if ((*inst_list_it)->isMemRef() && - !(*inst_list_it)->memOpDone) { - // Loads that have not been marked as executed still count - // towards the total instructions. - ++valid_num; - cprintf("Count:%i\n", valid_num); - } - } - - cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n" - "Issued:%i\nSquashed:%i\n", - (*inst_list_it)->readPC(), - (*inst_list_it)->seqNum, - (*inst_list_it)->threadNumber, - (*inst_list_it)->isIssued(), - (*inst_list_it)->isSquashed()); - - if ((*inst_list_it)->isMemRef()) { - cprintf("MemOpDone:%i\n", (*inst_list_it)->memOpDone); - } - - cprintf("\n"); - - inst_list_it++; - ++num; - } - - cprintf("Writeback list size: %i\n", writeback.size()); - - inst_list_it = writeback.begin(); - - while (inst_list_it != writeback.end()) - { - cprintf("Instruction:%i\n", - num); - if (!(*inst_list_it)->isSquashed()) { - if (!(*inst_list_it)->isIssued()) { - ++valid_num; - cprintf("Count:%i\n", valid_num); - } else if ((*inst_list_it)->isMemRef() && - !(*inst_list_it)->memOpDone) { - // Loads that have not been marked as executed still count - // towards the total instructions. - ++valid_num; - cprintf("Count:%i\n", valid_num); - } - } - - cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n" - "Issued:%i\nSquashed:%i\n", - (*inst_list_it)->readPC(), - (*inst_list_it)->seqNum, - (*inst_list_it)->threadNumber, - (*inst_list_it)->isIssued(), - (*inst_list_it)->isSquashed()); - - if ((*inst_list_it)->isMemRef()) { - cprintf("MemOpDone:%i\n", (*inst_list_it)->memOpDone); - } - - cprintf("\n"); - - inst_list_it++; - ++num; - } -} - -#endif//__CPU_OZONE_BACK_END_IMPL_HH__ |