diff -r 87cafa076695 -r 344fbb5b00ff src/cpu/inorder/cpu.hh --- a/src/cpu/inorder/cpu.hh Thu Mar 08 02:10:03 2012 -0800 +++ b/src/cpu/inorder/cpu.hh Thu Mar 08 10:44:03 2012 -0500 @@ -67,6 +67,7 @@ #include "cpu/base.hh" #include "cpu/simple_thread.hh" #include "cpu/timebuf.hh" +#include "cpu/translation.hh" #include "mem/packet.hh" #include "mem/port.hh" #include "mem/request.hh" @@ -868,6 +869,13 @@ /** Update Thread , used for statistic purposes*/ inline void tickThreadStats(); + /** + * Finish a DTB translation. + * @param state The DTB translation state. + */ + // Copied from TimingSimpleCPU + void finishTranslation(WholeTranslationState *state); + /** Per-Thread Tick */ Stats::Vector threadCycles; diff -r 87cafa076695 -r 344fbb5b00ff src/cpu/inorder/cpu.cc --- a/src/cpu/inorder/cpu.cc Thu Mar 08 02:10:03 2012 -0800 +++ b/src/cpu/inorder/cpu.cc Thu Mar 08 10:44:03 2012 -0500 @@ -1798,3 +1798,28 @@ return resPool->getDataUnit()->write(inst, data, size, addr, flags, write_res); } + +void +InOrderCPU::finishTranslation(WholeTranslationState *state) +{ + _status = Running; + + if (state->getFault() != NoFault) { + if (state->isPrefetch()) { + state->setNoFault(); + } + delete [] state->data; + state->deleteReqs(); + + //translationFault(state->getFault()); + state->inst->fault = stage->getFault(); + } + + //@note: doCacheAccess needs to check state for a fault + // and mark translation finished to unstall + // subsequent instructions + resPool->getDataUnit()->doCacheAccess(state); + + //@note: must delete state in InOrderDynInst destructor + //delete state; +} diff -r 87cafa076695 -r 344fbb5b00ff src/cpu/inorder/resources/cache_unit.cc --- a/src/cpu/inorder/resources/cache_unit.cc Thu Mar 08 02:10:03 2012 -0800 +++ b/src/cpu/inorder/resources/cache_unit.cc Thu Mar 08 10:44:03 2012 -0500 @@ -38,9 +38,11 @@ #include "arch/utility.hh" #include "config/the_isa.hh" #include "cpu/inorder/resources/cache_unit.hh" +#include "cpu/inorder/resources/inorder_translation.hh" #include "cpu/inorder/cpu.hh" #include "cpu/inorder/pipeline_traits.hh" #include "cpu/inorder/resource_pool.hh" +#include "cpu/translation.hh" #include "debug/Activity.hh" #include "debug/AddrDep.hh" #include "debug/InOrderCachePort.hh" @@ -356,6 +358,7 @@ { ThreadID tid = inst->readTid(); + // This function doesn't look right; simpler to set up here setupMemRequest(inst, cache_req, acc_size, flags); //@todo: HACK: the DTB expects the correct PC in the ThreadContext @@ -365,6 +368,35 @@ PCState old_pc = tc->pcState(); tc->pcState() = inst->pcState(); + // Set up Translation object similarly to simple/timing.cc + // The data and res values in WholeTranslationState should not be needed + // as that is handled in doCacheAccess() later + if (cache_req->splitAccess) { + RequestPtr req1, req2; + cache_req->memReq->splitOnVaddr(inst->split2ndAddr, req1, req2); + WholeTranslationState *state = + new WholeTranslationState(cache_req->memReq, req1, req2, NULL, NULL, + tlb_mode); + //@note: who deallocates these? + InOrderTranslation *trans1 = + new InOrderTranslation(cpu, state, 0, tid, this); + InOrderTranslation *trans2 = + new InOrderTranslation(cpu, state, 1, tid, this); + + inst->fault = _tlb->translateTiming(req1, tc, trans1, tlb_mode); + if (inst->fault == NoFault){ + inst->fault = _tlb->translateTiming(req2, tc, trans2, tlb_mode); + } + } else { + WholeTranslationState *state = + new WholeTranslationState(cache_req->memReq, NULL, NULL, tlb_mode); + //@note: who deallocates this? + InOrderTranslation *trans = + new InOrderTranslation(cpu, state, tid, this); + + inst->fault = _tlb->translateTiming(cache_req->memReq, tc, trans, tlb_mode); + } + inst->fault = _tlb->translateAtomic(cache_req->memReq, tc, tlb_mode); tc->pcState() = old_pc; @@ -395,7 +427,8 @@ void CacheUnit::trap(Fault fault, ThreadID tid, DynInstPtr inst) { - tlbBlocked[tid] = false; + // Unblocking is done by InOrderDataTranslation + //tlbBlocked[tid] = false; } Fault @@ -670,7 +703,7 @@ } else { inst->initiateAcc(); } - + break; case InitSecondSplitRead: @@ -702,7 +735,13 @@ tid, inst->seqNum); - //@todo: timing translations need to check here... + if (tlbBlocked[tid]) + { + DPRINTF(InOrderCachePort, " Failed because ", + "translation ongoing\n"); + break; + } + assert(!inst->isInstPrefetch() && "Can't Handle Inst. Prefecthes"); if (cache_req->isMemAccComplete() || inst->isDataPrefetch()) { finishCacheUnitReq(inst, cache_req); @@ -721,7 +760,13 @@ tid, inst->seqNum); - //@todo: check that timing translation is finished here + if (tlbBlocked[tid]) + { + DPRINTF(InOrderCachePort, " Failed because ", + "translation ongoing\n"); + break; + } + RequestPtr mem_req = cache_req->memReq; if (mem_req->isCondSwap() || mem_req->isLLSC() || mem_req->isSwap()) { DPRINTF(InOrderCachePort, "Detected Conditional Store Inst.\n"); @@ -754,7 +799,13 @@ "[tid:%i]: [sn:%i]: Trying to Complete Split Data Read " "Access\n", tid, inst->seqNum); - //@todo: check that timing translation is finished here + if (tlbBlocked[tid]) + { + DPRINTF(InOrderCachePort, " Failed because ", + "translation ongoing\n"); + break; + } + assert(!inst->isInstPrefetch() && "Can't Handle Inst. Prefecthes"); if (cache_req->isMemAccComplete() || inst->isDataPrefetch()) { finishCacheUnitReq(inst, cache_req); @@ -779,10 +830,16 @@ cache_req->dataPkt->memReq = cache_req->memReq; } - //@todo: check that timing translation is finished here + if (tlbBlocked[tid]) + { + DPRINTF(InOrderCachePort, " Failed because ", + "translation ongoing\n"); + break; + } + finishCacheUnitReq(inst, cache_req); break; - + default: fatal("Unrecognized command to %s", resName); } @@ -998,7 +1055,7 @@ cache_pkt->cacheReq->getInst()->seqNum, cache_pkt->cacheReq->getInst()->getMemAddr()); } - + assert(cache_req); assert(cache_req == cache_pkt->cacheReq); @@ -1090,13 +1147,13 @@ cpu->threadModel == InOrderCPU::SwitchOnCacheMiss) { DPRINTF(InOrderCachePort, "[tid:%u] Waking up from Cache Miss.\n", tid); - + cpu->activateContext(tid); - + DPRINTF(ThreadModel, "Activating [tid:%i] after return from cache" "miss.\n", tid); } - + // Wake up the CPU (if it went to sleep and was waiting on this // completion event). cpu->wakeCPU(); @@ -1111,7 +1168,7 @@ CacheUnit::recvRetry() { DPRINTF(InOrderCachePort, "Unblocking Cache Port. \n"); - + assert(cachePortBlocked); // Clear the cache port for use again @@ -1127,6 +1184,11 @@ void CacheUnitEvent::process() { + // CacheUnitEvent is apparently deprecated, and process() shouldn't be + // called. + // process() can unset tlbBlocked[tid], which could be bad. + assert(0); + DynInstPtr inst = resource->reqs[slotIdx]->inst; int stage_num = resource->reqs[slotIdx]->getStageNum(); ThreadID tid = inst->threadNumber; diff -r 87cafa076695 -r 344fbb5b00ff src/cpu/inorder/resources/inorder_translation.hh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/cpu/inorder/resources/inorder_translation.hh Thu Mar 08 10:44:03 2012 -0500 @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2012 The University of Edinburgh + * 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. + * + * Author: Erik Tomusk + */ + +#ifndef __CPU_INORDER_TRANSLATION__ +#define __CPU_INORDER_TRANSLATION__ + +#include "cpu/translation.hh" +#include "sim/faults.hh" +#include "sim/tlb.hh" + +/** + * @todo: describe the class + */ + +template +class InOrderTranslation : public DataTranslation +{ + protected: + ThreadID tid; + CacheUnit *cacheUnit; + + public: + InOrderTranslation(ExecContextPtr _xc, WholeTranslationState* _state, + ThreadID _tid, CacheUnit *_cacheUnit) + : DataTranslation::DataTranslation(_xc, _state), + tid(_tid), cacheUnit(_cacheUnit) + { + } + + InOrderTranslation(ExecContextPtr _xc, WholeTranslationState* _state, + int _index, ThreadID _tid, CacheUnit *_cacheUnit) + : DataTranslation::DataTranslation(_xc, _state, _index), + tid(_tid), cacheUnit(_cacheUnit) + { + } + + /** + * Unblock the TLB in CacheUnit, then do same as DataTranslation version + */ + void + finish(Fault fault, RequestPtr req, ThreadContext *tc, + BaseTLB::Mode mode) + { + cacheUnit->tlbBlocked[tid] = false; + DataTranslation::finish(fault, req, tc, mode); + } +}; + +#endif // __CPU_INORDER_TRANSLATION__