diff -r a7a72f42919e -r ce270085759a configs/common/Simulation.py --- a/configs/common/Simulation.py Fri Aug 10 13:50:42 2012 -0500 +++ b/configs/common/Simulation.py Mon Aug 20 02:24:01 2012 -0400 @@ -34,7 +34,7 @@ from m5.defines import buildEnv from m5.objects import * from m5.util import * -from O3_ARM_v7a import * +#from O3_ARM_v7a import * addToPath('../common') diff -r a7a72f42919e -r ce270085759a src/cpu/inorder/SConscript --- a/src/cpu/inorder/SConscript Fri Aug 10 13:50:42 2012 -0500 +++ b/src/cpu/inorder/SConscript Mon Aug 20 02:24:01 2012 -0400 @@ -75,6 +75,7 @@ Source('resources/branch_predictor.cc') Source('resources/cache_unit.cc') Source('resources/fetch_unit.cc') + Source('resources/inorder_translation.cc') Source('resources/use_def.cc') Source('resources/decode_unit.cc') Source('resources/inst_buffer.cc') diff -r a7a72f42919e -r ce270085759a src/cpu/inorder/cpu.hh --- a/src/cpu/inorder/cpu.hh Fri Aug 10 13:50:42 2012 -0500 +++ b/src/cpu/inorder/cpu.hh Mon Aug 20 02:24:01 2012 -0400 @@ -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" diff -r a7a72f42919e -r ce270085759a src/cpu/inorder/cpu.cc --- a/src/cpu/inorder/cpu.cc Fri Aug 10 13:50:42 2012 -0500 +++ b/src/cpu/inorder/cpu.cc Mon Aug 20 02:24:01 2012 -0400 @@ -1793,3 +1793,4 @@ return resPool->getDataUnit()->write(inst, data, size, addr, flags, write_res); } + diff -r a7a72f42919e -r ce270085759a src/cpu/inorder/inorder_dyn_inst.hh --- a/src/cpu/inorder/inorder_dyn_inst.hh Fri Aug 10 13:50:42 2012 -0500 +++ b/src/cpu/inorder/inorder_dyn_inst.hh Mon Aug 20 02:24:01 2012 -0400 @@ -48,6 +48,7 @@ #include "cpu/inorder/pipeline_traits.hh" #include "cpu/inorder/resource.hh" #include "cpu/inorder/resource_sked.hh" +#include "cpu/inorder/resources/inorder_translation.hh" #include "cpu/inorder/thread_state.hh" #include "cpu/exetrace.hh" #include "cpu/inst_seq.hh" @@ -71,6 +72,7 @@ // Forward declaration. class ResourceRequest; class Packet; +class InOrderTranslationState; class InOrderDynInst : public RefCounted { @@ -176,6 +178,10 @@ /** Pointer to the thread state. */ InOrderThreadState *thread; + /** Pointer to translation information */ + //@note: do we need separate states for inst/data translation? + InOrderTranslationState *state; + /** The kind of fault this instruction has generated. */ Fault fault; diff -r a7a72f42919e -r ce270085759a src/cpu/inorder/inorder_dyn_inst.cc --- a/src/cpu/inorder/inorder_dyn_inst.cc Fri Aug 10 13:50:42 2012 -0500 +++ b/src/cpu/inorder/inorder_dyn_inst.cc Mon Aug 20 02:24:01 2012 -0400 @@ -52,13 +52,13 @@ using namespace ThePipeline; InOrderDynInst::InOrderDynInst(InOrderCPU *cpu, - InOrderThreadState *state, + InOrderThreadState *_state, InstSeqNum seq_num, ThreadID tid, unsigned _asid) : seqNum(seq_num), squashSeqNum(0), threadNumber(tid), asid(_asid), virtProcNumber(0), staticInst(NULL), traceData(NULL), cpu(cpu), - thread(state), fault(NoFault), memData(NULL), loadData(0), + thread(_state), state(NULL), fault(NoFault), memData(NULL), loadData(0), storeData(0), effAddr(0), physEffAddr(0), memReqFlags(0), readyRegs(0), pc(0), predPC(0), memAddr(0), nextStage(0), memTime(0), splitMemData(NULL), splitMemReq(NULL), totalSize(0), diff -r a7a72f42919e -r ce270085759a src/cpu/inorder/resource.cc --- a/src/cpu/inorder/resource.cc Fri Aug 10 13:50:42 2012 -0500 +++ b/src/cpu/inorder/resource.cc Mon Aug 20 02:24:01 2012 -0400 @@ -480,13 +480,13 @@ void ResourceRequest::done(bool completed) { - DPRINTF(Resource, "done with request from " - "[sn:%i] [tid:%i].\n", - inst->seqNum, inst->readTid()); - setCompleted(completed); doneInResource = true; + + DPRINTF(Resource, "done with request from " + "[sn:%i] [tid:%i] [completed:%i].\n", + inst->seqNum, inst->readTid(), isCompleted()); } ResourceEvent::ResourceEvent() diff -r a7a72f42919e -r ce270085759a src/cpu/inorder/resources/cache_unit.hh --- a/src/cpu/inorder/resources/cache_unit.hh Fri Aug 10 13:50:42 2012 -0500 +++ b/src/cpu/inorder/resources/cache_unit.hh Mon Aug 20 02:24:01 2012 -0400 @@ -49,6 +49,7 @@ #include "sim/sim_object.hh" class CacheReqPacket; +class WholeTranslationState; typedef CacheReqPacket* CacheReqPktPtr; class CacheUnit : public Resource @@ -125,6 +126,9 @@ void doTLBAccess(DynInstPtr inst, CacheReqPtr cache_req, int acc_size, int flags, TheISA::TLB::Mode tlb_mode); + /** Finish a TLB translation */ + virtual void finishTranslation(WholeTranslationState *state); + /** Read/Write on behalf of an instruction. * curResSlot needs to be a valid value in instruction. */ @@ -233,6 +237,7 @@ RequestPtr memReq; PacketDataPtr reqData; CacheReqPacket *dataPkt; + uint64_t *writeRes; bool memAccComplete; bool memAccPending; diff -r a7a72f42919e -r ce270085759a src/cpu/inorder/resources/cache_unit.cc --- a/src/cpu/inorder/resources/cache_unit.cc Fri Aug 10 13:50:42 2012 -0500 +++ b/src/cpu/inorder/resources/cache_unit.cc Mon Aug 20 02:24:01 2012 -0400 @@ -37,9 +37,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" @@ -122,7 +124,8 @@ { ThreadID tid = inst->readTid(); if (tlbBlocked[tid]) { - return -1; + DPRINTF(InOrderTLB, "Can not acquire slot because the TLB is blocked.\n"); + return -1; } // For a Split-Load, the instruction would have processed once already @@ -345,6 +348,9 @@ tid); } + //@todo: double-check this isnt a memory leak... + // maybe add the splitMemReq as a cache_req + // object to clean this up? cache_req->memReq = inst->splitMemReq; } } @@ -354,7 +360,6 @@ int flags, TheISA::TLB::Mode tlb_mode) { ThreadID tid = inst->readTid(); - setupMemRequest(inst, cache_req, acc_size, flags); //@todo: HACK: the DTB expects the correct PC in the ThreadContext @@ -364,36 +369,95 @@ PCState old_pc = tc->pcState(); tc->pcState() = inst->pcState(); - inst->fault = - _tlb->translateAtomic(cache_req->memReq, tc, tlb_mode); + if (cache_req->splitAccess) { + assert(0 && "Timing Translation for Split Access Not Working Yet."); + } else { + inst->state = new InOrderTranslationState(cache_req, NULL, NULL, tlb_mode); + inst->state->translationStarted = true; + inst->state->inst = inst; + + DataTranslation *trans = new DataTranslation(this, inst->state); + _tlb->translateTiming(cache_req->memReq, tc, trans, tlb_mode); + } + + // reset PC due to above hack tc->pcState() = old_pc; +} - if (inst->fault != NoFault) { - DPRINTF(InOrderTLB, "[tid:%i]: %s encountered while translating " - "addr:%08p for [sn:%i].\n", tid, inst->fault->name(), +void +CacheUnit::finishTranslation(WholeTranslationState *state) +{ + InOrderTranslationState *trans_state = dynamic_cast(state); + assert(trans_state); + CacheReqPtr cache_req = trans_state->cacheReq; + DynInstPtr inst = trans_state->inst; + ThreadID tid = inst->readTid(); + int size = cache_req->memReq->getSize(); + + //Now that the translation is done, go ahead and do the cache access + //@note: ok to mark finished here if split access? maybe count finishes? + trans_state->translationFinished = true; + if (state->getFault() != NoFault) { + inst->fault = state->getFault(); + + if (!state->isPrefetch()) { + DPRINTF(InOrderTLB, "[tid:%i]: %s encountered while translating " + "addr:%08p for [sn:%i].\n", tid, state->getFault()->name(), cache_req->memReq->getVaddr(), inst->seqNum); - tlbBlocked[tid] = true; - tlbBlockSeqNum[tid] = inst->seqNum; + if (!tlbBlocked[tid]) { + tlbBlocked[tid] = true; + tlbBlockSeqNum[tid] = inst->seqNum; + DPRINTF(InOrderTLB, "[tid:%i]: Setting TLB to Blocked.\n", tid); + } - // Make sure nothing gets executed until after this faulting - // instruction gets handled. - inst->setSerializeAfter(); - + // Make sure nothing gets executed until after this faulting + // instruction gets handled. + inst->setSerializeAfter(); + } else { + DPRINTF(InOrderTLB, "[tid:%i]: Ignoring %s encountered while translating " + "addr:%08p for [sn:%i].\n", tid, state->getFault()->name(), + cache_req->memReq->getVaddr(), inst->seqNum); + } // Mark it as complete so it can pass through next stage. // Fault Handling will happen at commit/graduation cache_req->setCompleted(); } else { - DPRINTF(InOrderTLB, "[tid:%i]: [sn:%i] virt. addr %08p translated " - "to phys. addr:%08p.\n", tid, inst->seqNum, - cache_req->memReq->getVaddr(), - cache_req->memReq->getPaddr()); + DPRINTF(InOrderTLB, "[tid:%i]: [sn:%i] virt. addr %08p translated " + "to phys. addr:%08p.\n", tid, inst->seqNum, + cache_req->memReq->getVaddr(), + cache_req->memReq->getPaddr()); + + if (trans_state->isRead()) { + if (!cache_req->splitAccess) { + cache_req->reqData = new uint8_t[size]; + doCacheAccess(inst, NULL); + } else { + if (!inst->split2ndAccess) { + cache_req->reqData = inst->splitMemData; + } else { + cache_req->reqData = inst->split2ndDataPtr; + } + + doCacheAccess(inst, NULL, cache_req); + } + } else if (trans_state->isWrite()) { + if (!cache_req->splitAccess) { + doCacheAccess(inst, cache_req->writeRes); + } else { + doCacheAccess(inst, cache_req->writeRes, cache_req); + } + } } } void CacheUnit::trap(Fault fault, ThreadID tid, DynInstPtr inst) { + // The TLB can be blocked if there is a fault from a + // non-prefetch instruction. That fault will carry all + // down to the graduation stage where the CPU will trap + // on that fault...then this will unblock the TLB tlbBlocked[tid] = false; } @@ -474,21 +538,7 @@ doTLBAccess(inst, cache_req, size, flags, TheISA::TLB::Read); - if (inst->fault == NoFault) { - if (!cache_req->splitAccess) { - cache_req->reqData = new uint8_t[size]; - doCacheAccess(inst, NULL); - } else { - if (!inst->split2ndAccess) { - cache_req->reqData = inst->splitMemData; - } else { - cache_req->reqData = inst->split2ndDataPtr; - } - - doCacheAccess(inst, NULL, cache_req); - } - } - + //@note: is it possible to have a fault here w/timing translation? return inst->fault; } @@ -582,24 +632,15 @@ inst->split2ndFlags = flags; inst->splitInstSked = true; } - + + cache_req->writeRes = write_res; + if (!cache_req->splitAccess) { + cache_req->reqData = new uint8_t[size]; + memcpy(cache_req->reqData, data, size); + } doTLBAccess(inst, cache_req, size, flags, TheISA::TLB::Write); - if (inst->fault == NoFault) { - if (!cache_req->splitAccess) { - cache_req->reqData = new uint8_t[size]; - memcpy(cache_req->reqData, data, size); - - //inst->split2ndStoreDataPtr = cache_req->reqData; - //inst->split2ndStoreDataPtr += size; - - doCacheAccess(inst, write_res); - } else { - doCacheAccess(inst, write_res, cache_req); - } - - } - + //@note: is it possible to have a fault here w/timing translation? return inst->fault; } @@ -669,7 +710,6 @@ } else { inst->initiateAcc(); } - break; case InitSecondSplitRead: @@ -700,8 +740,12 @@ "[tid:%i]: [sn:%i]: Trying to Complete Data Read Access\n", tid, inst->seqNum); + if (!inst->state->translationFinished) + { + DPRINTF(InOrderCachePort, "Failed because translation ongoing\n"); + break; + } - //@todo: timing translations need to check here... assert(!inst->isInstPrefetch() && "Can't Handle Inst. Prefecthes"); if (cache_req->isMemAccComplete() || inst->isDataPrefetch()) { finishCacheUnitReq(inst, cache_req); @@ -719,8 +763,12 @@ "[tid:%i]: [sn:%i]: Trying to Complete Data Write Access\n", tid, inst->seqNum); + if (!inst->state->translationFinished) + { + DPRINTF(InOrderCachePort, "Failed because translation ongoing\n"); + break; + } - //@todo: check that timing translation is finished here RequestPtr mem_req = cache_req->memReq; if (mem_req->isCondSwap() || mem_req->isLLSC() || mem_req->isSwap()) { DPRINTF(InOrderCachePort, "Detected Conditional Store Inst.\n"); @@ -753,7 +801,12 @@ "[tid:%i]: [sn:%i]: Trying to Complete Split Data Read " "Access\n", tid, inst->seqNum); - //@todo: check that timing translation is finished here + if (!inst->state->translationFinished) + { + 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); @@ -773,15 +826,20 @@ assert(!cache_req->memReq->isSwap() && !cache_req->memReq->isCondSwap() && !cache_req->memReq->isLLSC()); + if (!inst->state->translationFinished) + { + DPRINTF(InOrderCachePort, "Failed because translation ongoing\n"); + break; + } + if (cache_req->isMemAccPending()) { cache_req->dataPkt->reqData = cache_req->reqData; cache_req->dataPkt->memReq = cache_req->memReq; } - //@todo: check that timing translation is finished here finishCacheUnitReq(inst, cache_req); break; - + default: fatal("Unrecognized command to %s", resName); } @@ -890,6 +948,8 @@ "[tid:%i] [sn:%i] is now waiting for cache response\n", tid, inst->seqNum); cache_req->setCompleted(); + + //@todo: Set Pending on Timing TLB Access cache_req->setMemAccPending(); cachePortBlocked = false; } @@ -996,7 +1056,7 @@ cache_pkt->cacheReq->getInst()->seqNum, cache_pkt->cacheReq->getInst()->getMemAddr()); } - + assert(cache_req); assert(cache_req == cache_pkt->cacheReq); @@ -1087,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(); @@ -1108,7 +1168,7 @@ CacheUnit::recvRetry() { DPRINTF(InOrderCachePort, "Unblocking Cache Port. \n"); - + assert(cachePortBlocked); // Clear the cache port for use again @@ -1124,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; @@ -1274,6 +1339,7 @@ memReq = NULL; reqData = NULL; + writeRes = NULL; dataPkt = NULL; memAccComplete = false; memAccPending = false; diff -r a7a72f42919e -r ce270085759a src/cpu/inorder/resources/fetch_unit.hh --- a/src/cpu/inorder/resources/fetch_unit.hh Fri Aug 10 13:50:42 2012 -0500 +++ b/src/cpu/inorder/resources/fetch_unit.hh Mon Aug 20 02:24:01 2012 -0400 @@ -83,6 +83,8 @@ int res_idx, int slot_num, unsigned cmd); + void finishTranslation(WholeTranslationState *state); + /** Executes one of the commands from the "Command" enum */ void execute(int slot_num); @@ -124,6 +126,8 @@ void clearFetchBuffer(); + void decrPending(Addr block_addr, ThreadID asid); + int instSize; int fetchBuffSize; diff -r a7a72f42919e -r ce270085759a src/cpu/inorder/resources/fetch_unit.cc --- a/src/cpu/inorder/resources/fetch_unit.cc Fri Aug 10 13:50:42 2012 -0500 +++ b/src/cpu/inorder/resources/fetch_unit.cc Mon Aug 20 02:24:01 2012 -0400 @@ -157,8 +157,6 @@ new Request(tid, aligned_addr, acc_size, flags, cpu->instMasterId(), inst->instAddr(), cpu->readCpuId(), tid); - DPRINTF(InOrderCachePort, "[sn:%i] Created memReq @%x, ->%x\n", - inst->seqNum, &cache_req->memReq, cache_req->memReq); } } @@ -230,6 +228,49 @@ } void +FetchUnit::decrPending(Addr block_addr, ThreadID asid) +{ + std::list::iterator block_it = findBlock(pendingFetch, + asid, + block_addr); + if (block_it != pendingFetch.end()) { + (*block_it)->cnt--; + DPRINTF(InOrderCachePort, "Removing Pending Access " + "for Pending Buffer Block %08p (cnt=%i)\n", + block_addr, (*block_it)->cnt); + assert((*block_it)->cnt >= 0); + if ((*block_it)->cnt == 0) { + // Delete Data if we have any + if ((*block_it)->block) { + delete [] (*block_it)->block; + } + + // Delete FetchBlock Structure + delete *block_it; + + // Finally, Remove from List + pendingFetch.erase(block_it); + } + } +} + +void +FetchUnit::finishTranslation(WholeTranslationState *state) +{ + + CacheUnit::finishTranslation(state); + if (state->getFault() != NoFault) { + InOrderTranslationState *trans_state = dynamic_cast(state); + assert(trans_state); + Addr block_addr = cacheBlockAlign(trans_state->inst->getMemAddr()); + int asid = cpu->asid[trans_state->inst->readTid()]; + decrPending(block_addr, asid); + } + + +} + +void FetchUnit::clearFetchBuffer() { std::list::iterator fetch_it = fetchBuffer.begin(); @@ -317,27 +358,14 @@ return; } + inst->setCurResSlot(slot_num); + pendingFetch.push_back(new FetchBlock(asid, block_addr)); + + DPRINTF(InOrderCachePort, + "[tid:%u]: Initiating fetch access to %s for " + "addr:%#x (block:%#x)\n", tid, name(), + cache_req->inst->getMemAddr(), block_addr); doTLBAccess(inst, cache_req, cacheBlkSize, Request::INST_FETCH, TheISA::TLB::Execute); - - if (inst->fault == NoFault) { - DPRINTF(InOrderCachePort, - "[tid:%u]: Initiating fetch access to %s for " - "addr:%#x (block:%#x)\n", tid, name(), - cache_req->inst->getMemAddr(), block_addr); - - cache_req->reqData = new uint8_t[cacheBlkSize]; - - inst->setCurResSlot(slot_num); - - doCacheAccess(inst); - - if (cache_req->isMemAccPending()) { - pendingFetch.push_back(new FetchBlock(asid, block_addr)); - - // mark replacement block - } - } - break; } @@ -551,24 +579,7 @@ block_addr, (*buff_it)->cnt); assert((*buff_it)->cnt >= 0); } else { - std::list::iterator block_it = findBlock(pendingFetch, - asid, - block_addr); - if (block_it != pendingFetch.end()) { - (*block_it)->cnt--; - DPRINTF(InOrderCachePort, "[sn:%i] Removing Pending Access " - "for Pending Buffer Block %08p (cnt=%i)\n", - inst->seqNum, - block_addr, (*block_it)->cnt); - assert((*block_it)->cnt >= 0); - if ((*block_it)->cnt == 0) { - if ((*block_it)->block) { - delete [] (*block_it)->block; - } - delete *block_it; - pendingFetch.erase(block_it); - } - } + decrPending(block_addr, asid); } CacheUnit::squashCacheRequest(req_ptr); @@ -577,16 +588,12 @@ void FetchUnit::trap(Fault fault, ThreadID tid, DynInstPtr inst) { - //@todo: per thread? decoder[tid]->reset(); - //@todo: squash using dummy inst seq num squash(NULL, NumStages - 1, 0, tid); - //@todo: make sure no blocks are in use assert(blocksInUse() == 0); assert(pendingFetch.size() == 0); - //@todo: clear pendingFetch and fetchBuffer clearFetchBuffer(); } diff -r a7a72f42919e -r ce270085759a src/cpu/inorder/resources/graduation_unit.cc --- a/src/cpu/inorder/resources/graduation_unit.cc Fri Aug 10 13:50:42 2012 -0500 +++ b/src/cpu/inorder/resources/graduation_unit.cc Mon Aug 20 02:24:01 2012 -0400 @@ -81,7 +81,8 @@ case CheckFault: { // Handle Any Faults Before Graduating Instruction - if (inst->fault != NoFault) { + bool is_mem_prefetch = inst->staticInst && (inst->isInstPrefetch() || inst->isDataPrefetch()); + if (inst->fault != NoFault && !is_mem_prefetch) { DPRINTF(InOrderGraduation, "[tid:%i]: [sn:%i]: fault %s found for %s\n", tid, inst->seqNum, inst->fault->name(), inst->instName()); @@ -89,10 +90,15 @@ lastFaultTick[tid] = cur_tick; grad_req->done(false); return; + } else if (inst->fault != NoFault && is_mem_prefetch) { + DPRINTF(InOrderGraduation, "[tid:%i]: [sn:%i]: Ignoring prefetch fault %s found for %s\n", + tid, inst->seqNum, inst->fault->name(), + inst->instName()); + } else { + DPRINTF(InOrderGraduation, "[tid:%i] [sn:%i]: No fault found for %s\n", + tid, inst->seqNum, inst->instName()); } - DPRINTF(InOrderGraduation, "[tid:%i] [sn:%i]: No fault found for %s\n", - tid, inst->seqNum, inst->instName()); grad_req->done(); } break; diff -r a7a72f42919e -r ce270085759a 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 Mon Aug 20 02:24:01 2012 -0400 @@ -0,0 +1,70 @@ +/* + * 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 + * Korey Sewell + */ + +#ifndef __CPU_INORDER_TRANSLATION__ +#define __CPU_INORDER_TRANSLATION__ + +#include "cpu/inorder/resources/cache_unit.hh" +#include "cpu/inorder/pipeline_traits.hh" +#include "cpu/translation.hh" +#include "sim/faults.hh" +#include "sim/tlb.hh" + +/** + * @todo: describe the class + */ +class InOrderTranslationState : public WholeTranslationState +{ + protected: + ThreadID tid; + + public: + typedef ThePipeline::DynInstPtr DynInstPtr; + DynInstPtr inst; + CacheReqPtr cacheReq; + bool translationStarted; + bool translationFinished; + + InOrderTranslationState(CacheReqPtr cache_req, uint8_t *_data, uint64_t *_res, + BaseTLB::Mode _mode); + + InOrderTranslationState(CacheReqPtr cache_req, RequestPtr _req, RequestPtr _sreqLow, + RequestPtr _sreqHigh, uint8_t *_data, uint64_t *_res, + BaseTLB::Mode _mode); + + inline bool isDelayed() { return delay; } + inline bool isStarted() { return translationStarted; } + inline bool isFinished() { return translationFinished; } + inline bool isRead() { return (mode == BaseTLB::Read || mode == BaseTLB::Execute); } + inline bool isWrite() { return (mode == BaseTLB::Write); } +}; + +#endif // __CPU_INORDER_TRANSLATION__ diff -r a7a72f42919e -r ce270085759a src/cpu/inorder/resources/inorder_translation.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/cpu/inorder/resources/inorder_translation.cc Mon Aug 20 02:24:01 2012 -0400 @@ -0,0 +1,46 @@ +/* + * 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 + * Korey Sewell + */ + +#include "cpu/inorder/resources/cache_unit.hh" +#include "cpu/inorder/resources/inorder_translation.hh" + +InOrderTranslationState::InOrderTranslationState(CacheReqPtr cache_req, uint8_t *_data, uint64_t *_res, + BaseTLB::Mode _mode) + : WholeTranslationState(cache_req->memReq, _data, _res, _mode), + cacheReq(cache_req), translationStarted(false), translationFinished(false) +{ } + +InOrderTranslationState::InOrderTranslationState(CacheReqPtr cache_req, RequestPtr _req, RequestPtr _sreqLow, + RequestPtr _sreqHigh, uint8_t *_data, uint64_t *_res, + BaseTLB::Mode _mode) + : WholeTranslationState(_req, _sreqLow, _sreqHigh, _data, _res, _mode), + cacheReq(cache_req), translationStarted(false), translationFinished(false) +{ } diff -r a7a72f42919e -r ce270085759a src/cpu/translation.hh --- a/src/cpu/translation.hh Fri Aug 10 13:50:42 2012 -0500 +++ b/src/cpu/translation.hh Mon Aug 20 02:24:01 2012 -0400 @@ -84,7 +84,8 @@ sreqLow(NULL), sreqHigh(NULL), data(_data), res(_res), mode(_mode) { faults[0] = faults[1] = NoFault; - assert(mode == BaseTLB::Read || mode == BaseTLB::Write); + //@CHECK: This assert isn't valid if a ITB can use this... + //assert(mode == BaseTLB::Read || mode == BaseTLB::Write); } /** @@ -100,9 +101,11 @@ mode(_mode) { faults[0] = faults[1] = NoFault; - assert(mode == BaseTLB::Read || mode == BaseTLB::Write); + //@CHECK: This assert isn't valid if a ITB can use this... + //assert(mode == BaseTLB::Read || mode == BaseTLB::Write); } + virtual ~WholeTranslationState() {} /** * Finish part of a translation. If there is only one request then this * translation is completed. If the request has been split in two then