diff options
Diffstat (limited to 'src/cpu/o3')
-rw-r--r-- | src/cpu/o3/fetch.hh | 4 | ||||
-rw-r--r-- | src/cpu/o3/fetch_impl.hh | 23 | ||||
-rw-r--r-- | src/cpu/o3/iew_impl.hh | 21 | ||||
-rw-r--r-- | src/cpu/o3/inst_queue.hh | 28 | ||||
-rw-r--r-- | src/cpu/o3/inst_queue_impl.hh | 53 | ||||
-rw-r--r-- | src/cpu/o3/lsq_unit_impl.hh | 10 |
6 files changed, 131 insertions, 8 deletions
diff --git a/src/cpu/o3/fetch.hh b/src/cpu/o3/fetch.hh index 92691720b..647c48a76 100644 --- a/src/cpu/o3/fetch.hh +++ b/src/cpu/o3/fetch.hh @@ -137,6 +137,10 @@ class DefaultFetch {} void + markDelayed() + {} + + void finish(Fault fault, RequestPtr req, ThreadContext *tc, BaseTLB::Mode mode) { diff --git a/src/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh index d0c83d586..d2cde496e 100644 --- a/src/cpu/o3/fetch_impl.hh +++ b/src/cpu/o3/fetch_impl.hh @@ -604,6 +604,9 @@ DefaultFetch<Impl>::finishTranslation(Fault fault, RequestPtr mem_req) ThreadID tid = mem_req->threadId(); Addr block_PC = mem_req->getVaddr(); + // Wake up CPU if it was idle + cpu->wakeCPU(); + // If translation was successful, attempt to read the icache block. if (fault == NoFault) { // Build packet here. @@ -654,6 +657,9 @@ DefaultFetch<Impl>::finishTranslation(Fault fault, RequestPtr mem_req) instruction->fault = fault; wroteToTimeBuffer = true; + DPRINTF(Activity, "Activity this cycle.\n"); + cpu->activityThisCycle(); + fetchStatus[tid] = TrapPending; DPRINTF(Fetch, "[tid:%i]: Blocked, need to handle the trap.\n", tid); @@ -1064,6 +1070,8 @@ DefaultFetch<Impl>::fetch(bool &status_change) Addr pcOffset = fetchOffset[tid]; Addr fetchAddr = (thisPC.instAddr() + pcOffset) & BaseCPU::PCMask; + bool inRom = isRomMicroPC(thisPC.microPC()); + // If returning from the delay of a cache miss, then update the status // to running, otherwise do the cache access. Possibly move this up // to tick() function. @@ -1077,7 +1085,7 @@ DefaultFetch<Impl>::fetch(bool &status_change) Addr block_PC = icacheBlockAlignPC(fetchAddr); // Unless buffer already got the block, fetch it from icache. - if (!cacheDataValid[tid] || block_PC != cacheDataPC[tid]) { + if (!(cacheDataValid[tid] && block_PC == cacheDataPC[tid]) && !inRom) { DPRINTF(Fetch, "[tid:%i]: Attempting to translate and read " "instruction, starting at PC %s.\n", tid, thisPC); @@ -1149,7 +1157,7 @@ DefaultFetch<Impl>::fetch(bool &status_change) !predictedBranch) { // If we need to process more memory, do it now. - if (!curMacroop && !predecoder.extMachInstReady()) { + if (!(curMacroop || inRom) && !predecoder.extMachInstReady()) { if (ISA_HAS_DELAY_SLOT && pcOffset == 0) { // Walk past any annulled delay slot instructions. Addr pcAddr = thisPC.instAddr() & BaseCPU::PCMask; @@ -1175,7 +1183,7 @@ DefaultFetch<Impl>::fetch(bool &status_change) // Extract as many instructions and/or microops as we can from // the memory we've processed so far. do { - if (!curMacroop) { + if (!(curMacroop || inRom)) { if (predecoder.extMachInstReady()) { ExtMachInst extMachInst; @@ -1196,8 +1204,13 @@ DefaultFetch<Impl>::fetch(bool &status_change) break; } } - if (curMacroop) { - staticInst = curMacroop->fetchMicroop(thisPC.microPC()); + if (curMacroop || inRom) { + if (inRom) { + staticInst = cpu->microcodeRom.fetchMicroop( + thisPC.microPC(), curMacroop); + } else { + staticInst = curMacroop->fetchMicroop(thisPC.microPC()); + } if (staticInst->isLastMicroop()) { curMacroop = NULL; pcOffset = 0; diff --git a/src/cpu/o3/iew_impl.hh b/src/cpu/o3/iew_impl.hh index 3f3761ff3..03f73c798 100644 --- a/src/cpu/o3/iew_impl.hh +++ b/src/cpu/o3/iew_impl.hh @@ -1241,12 +1241,33 @@ DefaultIEW<Impl>::executeInsts() // Loads will mark themselves as executed, and their writeback // event adds the instruction to the queue to commit fault = ldstQueue.executeLoad(inst); + + if (inst->isTranslationDelayed() && + fault == NoFault) { + // A hw page table walk is currently going on; the + // instruction must be deferred. + DPRINTF(IEW, "Execute: Delayed translation, deferring " + "load.\n"); + instQueue.deferMemInst(inst); + continue; + } + if (inst->isDataPrefetch() || inst->isInstPrefetch()) { fault = NoFault; } } else if (inst->isStore()) { fault = ldstQueue.executeStore(inst); + if (inst->isTranslationDelayed() && + fault == NoFault) { + // A hw page table walk is currently going on; the + // instruction must be deferred. + DPRINTF(IEW, "Execute: Delayed translation, deferring " + "store.\n"); + instQueue.deferMemInst(inst); + continue; + } + // If the store had a fault then it may not have a mem req if (fault != NoFault || inst->readPredicate() == false || !inst->isStoreConditional()) { diff --git a/src/cpu/o3/inst_queue.hh b/src/cpu/o3/inst_queue.hh index be936e204..64df35743 100644 --- a/src/cpu/o3/inst_queue.hh +++ b/src/cpu/o3/inst_queue.hh @@ -1,4 +1,16 @@ /* + * Copyright (c) 2011 ARM Limited + * All rights reserved. + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2004-2006 The Regents of The University of Michigan * All rights reserved. * @@ -180,6 +192,11 @@ class InstructionQueue */ DynInstPtr getInstToExecute(); + /** Returns a memory instruction that was referred due to a delayed DTB + * translation if it is now ready to execute. + */ + DynInstPtr getDeferredMemInstToExecute(); + /** * Records the instruction as the producer of a register without * adding it to the rest of the IQ. @@ -223,6 +240,12 @@ class InstructionQueue /** Completes a memory operation. */ void completeMemInst(DynInstPtr &completed_inst); + /** + * Defers a memory instruction when its DTB translation incurs a hw + * page table walk. + */ + void deferMemInst(DynInstPtr &deferred_inst); + /** Indicates an ordering violation between a store and a load. */ void violation(DynInstPtr &store, DynInstPtr &faulting_load); @@ -284,6 +307,11 @@ class InstructionQueue /** List of instructions that are ready to be executed. */ std::list<DynInstPtr> instsToExecute; + /** List of instructions waiting for their DTB translation to + * complete (hw page table walk in progress). + */ + std::list<DynInstPtr> deferredMemInsts; + /** * Struct for comparing entries to be added to the priority queue. * This gives reverse ordering to the instructions in terms of diff --git a/src/cpu/o3/inst_queue_impl.hh b/src/cpu/o3/inst_queue_impl.hh index 91cb2f0c8..aa21a0edc 100644 --- a/src/cpu/o3/inst_queue_impl.hh +++ b/src/cpu/o3/inst_queue_impl.hh @@ -1,4 +1,16 @@ /* + * Copyright (c) 2011 ARM Limited + * All rights reserved. + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2004-2006 The Regents of The University of Michigan * All rights reserved. * @@ -397,6 +409,7 @@ InstructionQueue<Impl>::resetState() } nonSpecInsts.clear(); listOrder.clear(); + deferredMemInsts.clear(); } template <class Impl> @@ -733,6 +746,15 @@ InstructionQueue<Impl>::scheduleReadyInsts() IssueStruct *i2e_info = issueToExecuteQueue->access(0); + DynInstPtr deferred_mem_inst; + int total_deferred_mem_issued = 0; + while (total_deferred_mem_issued < totalWidth && + (deferred_mem_inst = getDeferredMemInstToExecute()) != 0) { + issueToExecuteQueue->access(0)->size++; + instsToExecute.push_back(deferred_mem_inst); + total_deferred_mem_issued++; + } + // Have iterator to head of the list // While I haven't exceeded bandwidth or reached the end of the list, // Try to get a FU that can do what this op needs. @@ -745,7 +767,7 @@ InstructionQueue<Impl>::scheduleReadyInsts() ListOrderIt order_end_it = listOrder.end(); int total_issued = 0; - while (total_issued < totalWidth && + while (total_issued < (totalWidth - total_deferred_mem_issued) && iewStage->canIssue() && order_it != order_end_it) { OpClass op_class = (*order_it).queueType; @@ -858,7 +880,7 @@ InstructionQueue<Impl>::scheduleReadyInsts() iqInstsIssued+= total_issued; // If we issued any instructions, tell the CPU we had activity. - if (total_issued) { + if (total_issued || total_deferred_mem_issued) { cpu->activityThisCycle(); } else { DPRINTF(IQ, "Not able to schedule any instructions.\n"); @@ -1021,6 +1043,11 @@ void InstructionQueue<Impl>::rescheduleMemInst(DynInstPtr &resched_inst) { DPRINTF(IQ, "Rescheduling mem inst [sn:%lli]\n", resched_inst->seqNum); + + // Reset DTB translation state + resched_inst->translationStarted = false; + resched_inst->translationCompleted = false; + resched_inst->clearCanIssue(); memDepUnit[resched_inst->threadNumber].reschedule(resched_inst); } @@ -1051,6 +1078,28 @@ InstructionQueue<Impl>::completeMemInst(DynInstPtr &completed_inst) template <class Impl> void +InstructionQueue<Impl>::deferMemInst(DynInstPtr &deferred_inst) +{ + deferredMemInsts.push_back(deferred_inst); +} + +template <class Impl> +typename Impl::DynInstPtr +InstructionQueue<Impl>::getDeferredMemInstToExecute() +{ + for (ListIt it = deferredMemInsts.begin(); it != deferredMemInsts.end(); + ++it) { + if ((*it)->translationCompleted) { + DynInstPtr ret = *it; + deferredMemInsts.erase(it); + return ret; + } + } + return NULL; +} + +template <class Impl> +void InstructionQueue<Impl>::violation(DynInstPtr &store, DynInstPtr &faulting_load) { diff --git a/src/cpu/o3/lsq_unit_impl.hh b/src/cpu/o3/lsq_unit_impl.hh index dd3604ffe..b5d337935 100644 --- a/src/cpu/o3/lsq_unit_impl.hh +++ b/src/cpu/o3/lsq_unit_impl.hh @@ -445,12 +445,16 @@ LSQUnit<Impl>::executeLoad(DynInstPtr &inst) Fault load_fault = NoFault; DPRINTF(LSQUnit, "Executing load PC %s, [sn:%lli]\n", - inst->pcState(),inst->seqNum); + inst->pcState(), inst->seqNum); assert(!inst->isSquashed()); load_fault = inst->initiateAcc(); + if (inst->isTranslationDelayed() && + load_fault == NoFault) + return load_fault; + // If the instruction faulted or predicated false, then we need to send it // along to commit without the instruction completing. if (load_fault != NoFault || inst->readPredicate() == false) { @@ -532,6 +536,10 @@ LSQUnit<Impl>::executeStore(DynInstPtr &store_inst) Fault store_fault = store_inst->initiateAcc(); + if (store_inst->isTranslationDelayed() && + store_fault == NoFault) + return store_fault; + if (store_inst->readPredicate() == false) store_inst->forwardOldRegs(); |