diff --git a/src/arch/alpha/isa/mem.isa b/src/arch/alpha/isa/mem.isa index 5bac4f758..fedfbf55d 100644 --- a/src/arch/alpha/isa/mem.isa +++ b/src/arch/alpha/isa/mem.isa @@ -53,10 +53,6 @@ output header {{ std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const; - - public: - - Request::Flags memAccFlags() { return memAccessFlags; } }; /** @@ -140,8 +136,6 @@ def template LoadStoreDeclare {{ %(InitiateAccDeclare)s %(CompleteAccDeclare)s - - %(MemAccSizeDeclare)s }; }}; @@ -160,19 +154,6 @@ def template CompleteAccDeclare {{ Trace::InstRecord *) const; }}; -def template MemAccSizeDeclare {{ - int memAccSize(%(CPU_exec_context)s *xc); -}}; - -def template LoadStoreMemAccSize {{ - int %(class_name)s::memAccSize(%(CPU_exec_context)s *xc) - { - // Return the memory access size in bytes - return (%(mem_acc_size)d / 8); - } -}}; - - def template LoadStoreConstructor {{ inline %(class_name)s::%(class_name)s(ExtMachInst machInst) : %(base_class)s("%(mnemonic)s", machInst, %(op_class)s) @@ -462,15 +443,6 @@ def template MiscCompleteAcc {{ } }}; -def template MiscMemAccSize {{ - int %(class_name)s::memAccSize(%(CPU_exec_context)s *xc) - { - return (%(mem_acc_size)d / 8); - panic("memAccSize undefined: Misc instruction does not support split " - "access method!"); - return 0; - } -}}; // load instructions use Ra as dest, so check for // Ra == 31 to detect nops @@ -541,11 +513,6 @@ def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, initiateAccTemplate = eval(exec_template_base + 'InitiateAcc') completeAccTemplate = eval(exec_template_base + 'CompleteAcc') - if (exec_template_base == 'Load' or exec_template_base == 'Store'): - memAccSizeTemplate = eval('LoadStoreMemAccSize') - else: - memAccSizeTemplate = eval('MiscMemAccSize') - # (header_output, decoder_output, decode_block, exec_output) return (LoadStoreDeclare.subst(iop), LoadStoreConstructor.subst(iop), @@ -553,8 +520,7 @@ def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, fullExecTemplate.subst(iop) + EACompExecute.subst(iop) + initiateAccTemplate.subst(iop) - + completeAccTemplate.subst(iop) - + memAccSizeTemplate.subst(memacc_iop)) + + completeAccTemplate.subst(iop)) }}; def format LoadOrNop(memacc_code, ea_code = {{ EA = Rb + disp; }}, diff --git a/src/cpu/SConscript b/src/cpu/SConscript index b14d606b7..80bc0986e 100644 --- a/src/cpu/SConscript +++ b/src/cpu/SConscript @@ -56,8 +56,6 @@ virtual Fault initiateAcc(%(type)s *xc, Trace::InstRecord *traceData) const virtual Fault completeAcc(Packet *pkt, %(type)s *xc, Trace::InstRecord *traceData) const { panic("completeAcc not defined!"); M5_DUMMY_RETURN }; -virtual int memAccSize(%(type)s *xc) -{ panic("memAccSize not defined!"); M5_DUMMY_RETURN }; ''' mem_ini_sig_template = ''' diff --git a/src/cpu/inorder/SConscript b/src/cpu/inorder/SConscript index 9403aa914..64f1b5481 100644 --- a/src/cpu/inorder/SConscript +++ b/src/cpu/inorder/SConscript @@ -75,7 +75,6 @@ if 'InOrderCPU' in env['CPU_MODELS']: Source('resources/decode_unit.cc') Source('resources/inst_buffer.cc') Source('resources/graduation_unit.cc') - Source('resources/tlb_unit.cc') Source('resources/fetch_seq_unit.cc') Source('resources/mult_div_unit.cc') Source('resource_pool.cc') diff --git a/src/cpu/inorder/cpu.cc b/src/cpu/inorder/cpu.cc index c522fc238..e901b475e 100644 --- a/src/cpu/inorder/cpu.cc +++ b/src/cpu/inorder/cpu.cc @@ -204,18 +204,6 @@ InOrderCPU::InOrderCPU(Params *params) fatal("Unable to find port for data.\n"); } - - // Hard-Code Bindings to ITB & DTB - itbIdx = resPool->getResIdx(name() + "." + "I-TLB"); - if (itbIdx == 0) { - fatal("Unable to find ITB resource.\n"); - } - - dtbIdx = resPool->getResIdx(name() + "." + "D-TLB"); - if (dtbIdx == 0) { - fatal("Unable to find DTB resource.\n"); - } - for (int i = 0; i < numThreads; ++i) { if (i < params->workload.size()) { DPRINTF(InOrderCPU, "Workload[%i] process is %#x\n", @@ -486,6 +474,7 @@ InOrderCPU::getPort(const std::string &if_name, int idx) void InOrderCPU::trap(Fault fault, unsigned tid, int delay) { + //@ Squash Pipeline during TRAP scheduleCpuEvent(Trap, fault, tid, 0/*vpe*/, delay); } @@ -502,7 +491,7 @@ InOrderCPU::scheduleCpuEvent(CPUEventType c_event, Fault fault, CPUEvent *cpu_event = new CPUEvent(this, c_event, fault, tid, vpe); if (delay >= 0) { - DPRINTF(InOrderCPU, "Scheduling CPU Event Type #%s for cycle %i.\n", + DPRINTF(InOrderCPU, "Scheduling CPU Event (%s) for cycle %i.\n", eventNames[c_event], curTick + delay); mainEventQueue.schedule(cpu_event,curTick + delay); } else { @@ -1266,20 +1255,6 @@ InOrderCPU::syscall(int64_t callnum, int tid) nonSpecInstActive[tid] = false; } -Fault -InOrderCPU::read(DynInstPtr inst) -{ - Resource *mem_res = resPool->getResource(dataPortIdx); - return mem_res->doDataAccess(inst); -} - -Fault -InOrderCPU::write(DynInstPtr inst, uint64_t *res) -{ - Resource *mem_res = resPool->getResource(dataPortIdx); - return mem_res->doDataAccess(inst, res); -} - void InOrderCPU::prefetch(DynInstPtr inst) { @@ -1298,7 +1273,8 @@ InOrderCPU::writeHint(DynInstPtr inst) TheISA::TLB* InOrderCPU::getITBPtr() { - TLBUnit *itb_res = dynamic_cast(resPool->getResource(itbIdx)); + CacheUnit *itb_res = + dynamic_cast(resPool->getResource(fetchPortIdx)); return itb_res->tlb(); } @@ -1306,6 +1282,136 @@ InOrderCPU::getITBPtr() TheISA::TLB* InOrderCPU::getDTBPtr() { - TLBUnit *dtb_res = dynamic_cast(resPool->getResource(dtbIdx)); + CacheUnit *dtb_res = + dynamic_cast(resPool->getResource(dataPortIdx)); return dtb_res->tlb(); } + +template +Fault +InOrderCPU::read(DynInstPtr inst, Addr addr, T &data, unsigned flags) +{ + //@TODO: Generalize name "CacheUnit" to "MemUnit" just in case + // you want to run w/out caches? + CacheUnit *cache_res = dynamic_cast(resPool->getResource(dataPortIdx)); + + return cache_res->read(inst, addr, data, flags); +} + +#ifndef DOXYGEN_SHOULD_SKIP_THIS + +template +Fault +InOrderCPU::read(DynInstPtr inst, Addr addr, Twin32_t &data, unsigned flags); + +template +Fault +InOrderCPU::read(DynInstPtr inst, Addr addr, Twin64_t &data, unsigned flags); + +template +Fault +InOrderCPU::read(DynInstPtr inst, Addr addr, uint64_t &data, unsigned flags); + +template +Fault +InOrderCPU::read(DynInstPtr inst, Addr addr, uint32_t &data, unsigned flags); + +template +Fault +InOrderCPU::read(DynInstPtr inst, Addr addr, uint16_t &data, unsigned flags); + +template +Fault +InOrderCPU::read(DynInstPtr inst, Addr addr, uint8_t &data, unsigned flags); + +#endif //DOXYGEN_SHOULD_SKIP_THIS + +template<> +Fault +InOrderCPU::read(DynInstPtr inst, Addr addr, double &data, unsigned flags) +{ + return read(inst, addr, *(uint64_t*)&data, flags); +} + +template<> +Fault +InOrderCPU::read(DynInstPtr inst, Addr addr, float &data, unsigned flags) +{ + return read(inst, addr, *(uint32_t*)&data, flags); +} + + +template<> +Fault +InOrderCPU::read(DynInstPtr inst, Addr addr, int32_t &data, unsigned flags) +{ + return read(inst, addr, (uint32_t&)data, flags); +} + +template +Fault +InOrderCPU::write(DynInstPtr inst, T data, Addr addr, unsigned flags, + uint64_t *write_res) +{ + //@TODO: Generalize name "CacheUnit" to "MemUnit" just in case + // you want to run w/out caches? + CacheUnit *cache_res = + dynamic_cast(resPool->getResource(dataPortIdx)); + return cache_res->write(inst, data, addr, flags, write_res); +} + +#ifndef DOXYGEN_SHOULD_SKIP_THIS + +template +Fault +InOrderCPU::write(DynInstPtr inst, Twin32_t data, Addr addr, + unsigned flags, uint64_t *res); + +template +Fault +InOrderCPU::write(DynInstPtr inst, Twin64_t data, Addr addr, + unsigned flags, uint64_t *res); + +template +Fault +InOrderCPU::write(DynInstPtr inst, uint64_t data, Addr addr, + unsigned flags, uint64_t *res); + +template +Fault +InOrderCPU::write(DynInstPtr inst, uint32_t data, Addr addr, + unsigned flags, uint64_t *res); + +template +Fault +InOrderCPU::write(DynInstPtr inst, uint16_t data, Addr addr, + unsigned flags, uint64_t *res); + +template +Fault +InOrderCPU::write(DynInstPtr inst, uint8_t data, Addr addr, + unsigned flags, uint64_t *res); + +#endif //DOXYGEN_SHOULD_SKIP_THIS + +template<> +Fault +InOrderCPU::write(DynInstPtr inst, double data, Addr addr, unsigned flags, uint64_t *res) +{ + return write(inst, *(uint64_t*)&data, addr, flags, res); +} + +template<> +Fault +InOrderCPU::write(DynInstPtr inst, float data, Addr addr, unsigned flags, uint64_t *res) +{ + return write(inst, *(uint32_t*)&data, addr, flags, res); +} + + +template<> +Fault +InOrderCPU::write(DynInstPtr inst, int32_t data, Addr addr, unsigned flags, uint64_t *res) +{ + return write(inst, (uint32_t)data, addr, flags, res); +} diff --git a/src/cpu/inorder/cpu.hh b/src/cpu/inorder/cpu.hh index ea5404c60..55b04f6a9 100644 --- a/src/cpu/inorder/cpu.hh +++ b/src/cpu/inorder/cpu.hh @@ -492,12 +492,15 @@ class InOrderCPU : public BaseCPU /** Forwards an instruction read to the appropriate data * resource (indexes into Resource Pool thru "dataPortIdx") */ - Fault read(DynInstPtr inst); + template + Fault read(DynInstPtr inst, Addr addr, T &data, unsigned flags); /** Forwards an instruction write. to the appropriate data * resource (indexes into Resource Pool thru "dataPortIdx") */ - Fault write(DynInstPtr inst, uint64_t *res = NULL); + template + Fault write(DynInstPtr inst, T data, Addr addr, unsigned flags, + uint64_t *write_res = NULL); /** Forwards an instruction prefetch to the appropriate data * resource (indexes into Resource Pool thru "dataPortIdx") diff --git a/src/cpu/inorder/inorder_dyn_inst.cc b/src/cpu/inorder/inorder_dyn_inst.cc index 3983821e7..ed63d9148 100644 --- a/src/cpu/inorder/inorder_dyn_inst.cc +++ b/src/cpu/inorder/inorder_dyn_inst.cc @@ -604,7 +604,7 @@ template inline Fault InOrderDynInst::read(Addr addr, T &data, unsigned flags) { - return cpu->read(this); + return cpu->read(this, addr, data, flags); } #ifndef DOXYGEN_SHOULD_SKIP_THIS @@ -657,7 +657,7 @@ InOrderDynInst::write(T data, Addr addr, unsigned flags, uint64_t *res) DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] Setting store data to %#x.\n", threadNumber, seqNum, memData); - return cpu->write(this, res); + return cpu->write(this, data, addr, flags, res); } #ifndef DOXYGEN_SHOULD_SKIP_THIS diff --git a/src/cpu/inorder/inorder_dyn_inst.hh b/src/cpu/inorder/inorder_dyn_inst.hh index 490992638..52465a712 100644 --- a/src/cpu/inorder/inorder_dyn_inst.hh +++ b/src/cpu/inorder/inorder_dyn_inst.hh @@ -652,10 +652,6 @@ class InOrderDynInst : public FastAlloc, public RefCounted Addr getMemAddr() { return memAddr; } - int getMemAccSize() { return staticInst->memAccSize(this); } - - int getMemFlags() { return staticInst->memAccFlags(); } - /** Sets the effective address. */ void setEA(Addr &ea) { instEffAddr = ea; eaCalcDone = true; } diff --git a/src/cpu/inorder/pipeline_traits.cc b/src/cpu/inorder/pipeline_traits.cc index 150115138..ed72ab1d0 100644 --- a/src/cpu/inorder/pipeline_traits.cc +++ b/src/cpu/inorder/pipeline_traits.cc @@ -69,7 +69,6 @@ void createFrontEndSchedule(DynInstPtr &inst) InstStage *E = inst->addStage(); I->needs(FetchSeq, FetchSeqUnit::AssignNextPC); - I->needs(ITLB, TLBUnit::FetchLookup); I->needs(ICache, CacheUnit::InitiateFetch); E->needs(ICache, CacheUnit::CompleteFetch); @@ -101,14 +100,10 @@ bool createBackEndSchedule(DynInstPtr &inst) } else if ( inst->isMemRef() ) { if ( inst->isLoad() ) { E->needs(AGEN, AGENUnit::GenerateAddr); - E->needs(DTLB, TLBUnit::DataReadLookup); E->needs(DCache, CacheUnit::InitiateReadData); } } else if (inst->opClass() == IntMultOp || inst->opClass() == IntDivOp) { E->needs(MDU, MultDivUnit::StartMultDiv); - - // ZERO-LATENCY Multiply: - // E->needs(MDU, MultDivUnit::MultDiv); } else { E->needs(ExecUnit, ExecutionUnit::ExecuteInst); } @@ -122,7 +117,6 @@ bool createBackEndSchedule(DynInstPtr &inst) } else if ( inst->isStore() ) { M->needs(RegManager, UseDefUnit::ReadSrcReg, 1); M->needs(AGEN, AGENUnit::GenerateAddr); - M->needs(DTLB, TLBUnit::DataWriteLookup); M->needs(DCache, CacheUnit::InitiateWriteData); } diff --git a/src/cpu/inorder/pipeline_traits.hh b/src/cpu/inorder/pipeline_traits.hh index 3c49143bc..5012553b0 100644 --- a/src/cpu/inorder/pipeline_traits.hh +++ b/src/cpu/inorder/pipeline_traits.hh @@ -56,7 +56,6 @@ namespace ThePipeline { // Enumerated List of Resources The Pipeline Uses enum ResourceList { FetchSeq = 0, - ITLB, ICache, Decode, BPred, @@ -65,7 +64,6 @@ namespace ThePipeline { AGEN, ExecUnit, MDU, - DTLB, DCache, Grad, FetchBuff2 diff --git a/src/cpu/inorder/resource.hh b/src/cpu/inorder/resource.hh index 0378c0f50..71270241f 100644 --- a/src/cpu/inorder/resource.hh +++ b/src/cpu/inorder/resource.hh @@ -140,15 +140,14 @@ class Resource { * if instruction is actually in resource before * trying to do access.Needs to be defined for derived units. */ - virtual Fault doDataAccess(DynInstPtr inst, uint64_t *res=NULL) - { panic("doDataAccess undefined for %s", name()); return NoFault; } + virtual Fault doCacheAccess(DynInstPtr inst, uint64_t *res=NULL) + { panic("doCacheAccess undefined for %s", name()); return NoFault; } virtual void prefetch(DynInstPtr inst) { panic("prefetch undefined for %s", name()); } virtual void writeHint(DynInstPtr inst) - { panic("doDataAccess undefined for %s", name()); } - + { panic("writeHint undefined for %s", name()); } /** Squash All Requests After This Seq Num */ virtual void squash(DynInstPtr inst, int stage_num, InstSeqNum squash_seq_num, unsigned tid); diff --git a/src/cpu/inorder/resource_pool.cc b/src/cpu/inorder/resource_pool.cc index 2187e2818..5cb55b89b 100644 --- a/src/cpu/inorder/resource_pool.cc +++ b/src/cpu/inorder/resource_pool.cc @@ -50,8 +50,6 @@ ResourcePool::ResourcePool(InOrderCPU *_cpu, ThePipeline::Params *params) // -------------------------------------------------- resources.push_back(new FetchSeqUnit("Fetch-Seq-Unit", FetchSeq, StageWidth * 2, 0, _cpu, params)); - resources.push_back(new TLBUnit("I-TLB", ITLB, StageWidth, 0, _cpu, params)); - memObjects.push_back(ICache); resources.push_back(new CacheUnit("icache_port", ICache, StageWidth * MaxThreads, 0, _cpu, params)); @@ -69,8 +67,6 @@ ResourcePool::ResourcePool(InOrderCPU *_cpu, ThePipeline::Params *params) resources.push_back(new MultDivUnit("Mult-Div-Unit", MDU, 5, 0, _cpu, params)); - resources.push_back(new TLBUnit("D-TLB", DTLB, StageWidth, 0, _cpu, params)); - memObjects.push_back(DCache); resources.push_back(new CacheUnit("dcache_port", DCache, StageWidth * MaxThreads, 0, _cpu, params)); @@ -205,7 +201,6 @@ ResourcePool::scheduleEvent(InOrderCPU::CPUEventType e_type, DynInstPtr inst, inst->bdelaySeqNum, inst->readTid()); mainEventQueue.schedule(res_pool_event, curTick + cpu->ticks(delay)); - } break; @@ -256,7 +251,7 @@ ResourcePool::scheduleEvent(InOrderCPU::CPUEventType e_type, DynInstPtr inst, break; default: - DPRINTF(Resource, "Ignoring Unrecognized CPU Event Type #%s.\n", InOrderCPU::eventNames[e_type]); + DPRINTF(Resource, "Ignoring Unrecognized CPU Event (%s).\n", InOrderCPU::eventNames[e_type]); ; // If Resource Pool doesnt recognize event, we ignore it. } } diff --git a/src/cpu/inorder/resources/cache_unit.cc b/src/cpu/inorder/resources/cache_unit.cc index c5d35dfb3..5d5d4d45d 100644 --- a/src/cpu/inorder/resources/cache_unit.cc +++ b/src/cpu/inorder/resources/cache_unit.cc @@ -86,6 +86,25 @@ CacheUnit::CacheUnit(string res_name, int res_id, int res_width, predecoder(NULL) { cachePort = new CachePort(this); + + // Hard-Code Selection For Now + if (res_name == "icache_port") + _tlb = params->itb; + else if (res_name == "dcache_port") + _tlb = params->dtb; + else + fatal("Unrecognized TLB name passed by user"); + + for (int i=0; i < MaxThreads; i++) { + tlbBlocked[i] = false; + } +} + +TheISA::TLB* +CacheUnit::tlb() +{ + return _tlb; + } Port * @@ -97,9 +116,23 @@ CacheUnit::getPort(const string &if_name, int idx) return NULL; } +void +CacheUnit::init() +{ + // Currently Used to Model TLB Latency. Eventually + // Switch to Timing TLB translations. + resourceEvent = new CacheUnitEvent[width]; + + initSlots(); +} + int CacheUnit::getSlot(DynInstPtr inst) { + if (tlbBlocked[inst->threadNumber]) { + return -1; + } + if (!inst->validMemAddr()) { panic("Mem. Addr. must be set before requesting cache access\n"); } @@ -156,45 +189,47 @@ CacheUnit::getRequest(DynInstPtr inst, int stage_num, int res_idx, panic("Mem. Addr. must be set before requesting cache access\n"); } - int req_size = 0; MemCmd::Command pkt_cmd; - if (sched_entry->cmd == InitiateReadData) { + switch (sched_entry->cmd) + { + case InitiateReadData: pkt_cmd = MemCmd::ReadReq; - req_size = inst->getMemAccSize(); DPRINTF(InOrderCachePort, - "[tid:%i]: %i byte Read request from [sn:%i] for addr %08p\n", - inst->readTid(), req_size, inst->seqNum, inst->getMemAddr()); - } else if (sched_entry->cmd == InitiateWriteData) { + "[tid:%i]: Read request from [sn:%i] for addr %08p\n", + inst->readTid(), inst->seqNum, inst->getMemAddr()); + break; + + case InitiateWriteData: pkt_cmd = MemCmd::WriteReq; - req_size = inst->getMemAccSize(); DPRINTF(InOrderCachePort, - "[tid:%i]: %i byte Write request from [sn:%i] for addr %08p\n", - inst->readTid(), req_size, inst->seqNum, inst->getMemAddr()); - } else if (sched_entry->cmd == InitiateFetch){ + "[tid:%i]: Write request from [sn:%i] for addr %08p\n", + inst->readTid(), inst->seqNum, inst->getMemAddr()); + break; + + case InitiateFetch: pkt_cmd = MemCmd::ReadReq; - req_size = sizeof(MachInst); DPRINTF(InOrderCachePort, - "[tid:%i]: %i byte Fetch request from [sn:%i] for addr %08p\n", - inst->readTid(), req_size, inst->seqNum, inst->getMemAddr()); - } else { + "[tid:%i]: Fetch request from [sn:%i] for addr %08p\n", + inst->readTid(), inst->seqNum, inst->getMemAddr()); + break; + + default: panic("%i: Unexpected request type (%i) to %s", curTick, sched_entry->cmd, name()); } return new CacheRequest(this, inst, stage_num, id, slot_num, - sched_entry->cmd, req_size, pkt_cmd, + sched_entry->cmd, 0, pkt_cmd, 0/*flags*/, this->cpu->readCpuId()); } void CacheUnit::requestAgain(DynInstPtr inst, bool &service_request) { - //service_request = false; - CacheReqPtr cache_req = dynamic_cast(findRequest(inst)); assert(cache_req); @@ -204,7 +239,7 @@ CacheUnit::requestAgain(DynInstPtr inst, bool &service_request) // If different, then update command in the request cache_req->cmd = inst->resSched.top()->cmd; DPRINTF(InOrderCachePort, - "[tid:%i]: [sn:%i]: the command for this instruction\n", + "[tid:%i]: [sn:%i]: Updating the command for this instruction\n", inst->readTid(), inst->seqNum); service_request = true; @@ -219,6 +254,101 @@ CacheUnit::requestAgain(DynInstPtr inst, bool &service_request) } } +Fault +CacheUnit::doTLBAccess(DynInstPtr inst, CacheReqPtr cache_req, int acc_size, + int flags, TheISA::TLB::Mode tlb_mode) +{ + int tid; + int seq_num; + Addr aligned_addr; + unsigned stage_num; + unsigned slot_idx; + + tid = inst->readTid(); + seq_num = inst->seqNum; + aligned_addr = inst->getMemAddr(); + stage_num = cache_req->getStageNum(); + slot_idx = cache_req->getSlot(); + + if (tlb_mode == TheISA::TLB::Execute) { + inst->fetchMemReq = new Request(inst->readTid(), aligned_addr, + acc_size, flags, inst->readPC(), + cpu->readCpuId(), inst->readTid()); + cache_req->memReq = inst->fetchMemReq; + } else { + inst->dataMemReq = new Request(inst->readTid(), aligned_addr, + acc_size, flags, inst->readPC(), + cpu->readCpuId(), inst->readTid()); + cache_req->memReq = inst->dataMemReq; + } + + + cache_req->fault = + _tlb->translateAtomic(cache_req->memReq, + cpu->thread[tid]->getTC(), tlb_mode); + + if (cache_req->fault != NoFault) { + DPRINTF(InOrderTLB, "[tid:%i]: %s encountered while translating " + "addr:%08p for [sn:%i].\n", tid, cache_req->fault->name(), + cache_req->memReq->getVaddr(), seq_num); + + cpu->pipelineStage[stage_num]->setResStall(cache_req, tid); + + tlbBlocked[tid] = true; + + cache_req->tlbStall = true; + + scheduleEvent(slot_idx, 1); + + cpu->trap(cache_req->fault, tid); + } else { + DPRINTF(InOrderTLB, "[tid:%i]: [sn:%i] virt. addr %08p translated " + "to phys. addr:%08p.\n", tid, seq_num, + cache_req->memReq->getVaddr(), + cache_req->memReq->getPaddr()); + } + + return cache_req->fault; +} + +template +Fault +CacheUnit::read(DynInstPtr inst, Addr addr, T &data, unsigned flags) +{ + CacheReqPtr cache_req = dynamic_cast(findRequest(inst)); + assert(cache_req); + + int acc_size = sizeof(T); + doTLBAccess(inst, cache_req, acc_size, flags, TheISA::TLB::Read); + + if (cache_req->fault == NoFault) { + cache_req->reqData = new uint8_t[acc_size]; + doCacheAccess(inst, NULL); + } + + return cache_req->fault; +} + +template +Fault +CacheUnit::write(DynInstPtr inst, T data, Addr addr, unsigned flags, + uint64_t *write_res) +{ + CacheReqPtr cache_req = dynamic_cast(findRequest(inst)); + assert(cache_req); + + int acc_size = sizeof(T); + doTLBAccess(inst, cache_req, acc_size, flags, TheISA::TLB::Write); + + if (cache_req->fault == NoFault) { + cache_req->reqData = new uint8_t[acc_size]; + doCacheAccess(inst, write_res); + } + + return cache_req->fault; +} + + void CacheUnit::execute(int slot_num) { @@ -241,21 +371,46 @@ CacheUnit::execute(int slot_num) switch (cache_req->cmd) { case InitiateFetch: + { + //@TODO: Switch to size of full cache block. Store in fetch buffer + int acc_size = sizeof(TheISA::MachInst); + + doTLBAccess(inst, cache_req, acc_size, 0, TheISA::TLB::Execute); + + // Only Do Access if no fault from TLB + if (cache_req->fault == NoFault) { + + DPRINTF(InOrderCachePort, + "[tid:%u]: Initiating fetch access to %s for addr. %08p\n", + tid, name(), cache_req->inst->getMemAddr()); + + cache_req->reqData = new uint8_t[acc_size]; + + inst->setCurResSlot(slot_num); + + doCacheAccess(inst); + } + + break; + } + + case InitiateReadData: + case InitiateWriteData: DPRINTF(InOrderCachePort, - "[tid:%u]: Initiating fetch access to %s for addr. %08p\n", + "[tid:%u]: Initiating data access to %s for addr. %08p\n", tid, name(), cache_req->inst->getMemAddr()); - DPRINTF(InOrderCachePort, - "[tid:%u]: Fetching new cache block from addr: %08p\n", - tid, cache_req->memReq->getVaddr()); - inst->setCurResSlot(slot_num); - doDataAccess(inst); + + if (inst->isDataPrefetch() || inst->isInstPrefetch()) { + inst->execute(); + } else { + inst->initiateAcc(); + } + break; case CompleteFetch: - // @TODO: MOVE Functionality of handling fetched data into 'fetch unit' - // let cache-unit just be responsible for transferring data. if (cache_req->isMemAccComplete()) { DPRINTF(InOrderCachePort, "[tid:%i]: Completing Fetch Access for [sn:%i]\n", @@ -278,22 +433,6 @@ CacheUnit::execute(int slot_num) } break; - case InitiateReadData: - case InitiateWriteData: - DPRINTF(InOrderCachePort, - "[tid:%u]: Initiating data access to %s for addr. %08p\n", - tid, name(), cache_req->inst->getMemAddr()); - - inst->setCurResSlot(slot_num); - - if (inst->isDataPrefetch() || inst->isInstPrefetch()) { - inst->execute(); - } else { - inst->initiateAcc(); - } - - break; - case CompleteReadData: case CompleteWriteData: DPRINTF(InOrderCachePort, @@ -355,8 +494,9 @@ CacheUnit::writeHint(DynInstPtr inst) inst->unsetMemAddr(); } +// @TODO: Split into doCacheRead() and doCacheWrite() Fault -CacheUnit::doDataAccess(DynInstPtr inst, uint64_t *write_res) +CacheUnit::doCacheAccess(DynInstPtr inst, uint64_t *write_res) { Fault fault = NoFault; int tid = 0; @@ -603,6 +743,35 @@ CacheUnit::recvRetry() } } +CacheUnitEvent::CacheUnitEvent() + : ResourceEvent() +{ } + +void +CacheUnitEvent::process() +{ + DynInstPtr inst = resource->reqMap[slotIdx]->inst; + int stage_num = resource->reqMap[slotIdx]->getStageNum(); + int tid = inst->threadNumber; + CacheReqPtr req_ptr = dynamic_cast(resource->reqMap[slotIdx]); + + DPRINTF(InOrderTLB, "Waking up from TLB Miss caused by [sn:%i].\n", + inst->seqNum); + + CacheUnit* tlb_res = dynamic_cast(resource); + assert(tlb_res); + + tlb_res->tlbBlocked[tid] = false; + + tlb_res->cpu->pipelineStage[stage_num]->unsetResStall(tlb_res->reqMap[slotIdx], tid); + + req_ptr->tlbStall = false; + + if (req_ptr->isSquashed()) { + req_ptr->done(); + } +} + void CacheUnit::squash(DynInstPtr inst, int stage_num, InstSeqNum squash_seq_num, unsigned tid) @@ -630,7 +799,17 @@ CacheUnit::squash(DynInstPtr inst, int stage_num, CacheReqPtr cache_req = dynamic_cast(req_ptr); assert(cache_req); - if (!cache_req->isMemAccPending()) { + int req_slot_num = req_ptr->getSlot(); + + if (cache_req->tlbStall) { + tlbBlocked[tid] = false; + + int stall_stage = reqMap[req_slot_num]->getStageNum(); + + cpu->pipelineStage[stall_stage]->unsetResStall(reqMap[req_slot_num], tid); + } + + if (!cache_req->tlbStall && !cache_req->isMemAccPending()) { // Mark request for later removal cpu->reqRemoveList.push(req_ptr); @@ -669,3 +848,109 @@ CacheUnit::getMemData(Packet *packet) } } +// Extra Template Definitions +#ifndef DOXYGEN_SHOULD_SKIP_THIS + +template +Fault +CacheUnit::read(DynInstPtr inst, Addr addr, Twin32_t &data, unsigned flags); + +template +Fault +CacheUnit::read(DynInstPtr inst, Addr addr, Twin64_t &data, unsigned flags); + +template +Fault +CacheUnit::read(DynInstPtr inst, Addr addr, uint64_t &data, unsigned flags); + +template +Fault +CacheUnit::read(DynInstPtr inst, Addr addr, uint32_t &data, unsigned flags); + +template +Fault +CacheUnit::read(DynInstPtr inst, Addr addr, uint16_t &data, unsigned flags); + +template +Fault +CacheUnit::read(DynInstPtr inst, Addr addr, uint8_t &data, unsigned flags); + +#endif //DOXYGEN_SHOULD_SKIP_THIS + +template<> +Fault +CacheUnit::read(DynInstPtr inst, Addr addr, double &data, unsigned flags) +{ + return read(inst, addr, *(uint64_t*)&data, flags); +} + +template<> +Fault +CacheUnit::read(DynInstPtr inst, Addr addr, float &data, unsigned flags) +{ + return read(inst, addr, *(uint32_t*)&data, flags); +} + + +template<> +Fault +CacheUnit::read(DynInstPtr inst, Addr addr, int32_t &data, unsigned flags) +{ + return read(inst, addr, (uint32_t&)data, flags); +} + +#ifndef DOXYGEN_SHOULD_SKIP_THIS + +template +Fault +CacheUnit::write(DynInstPtr inst, Twin32_t data, Addr addr, + unsigned flags, uint64_t *res); + +template +Fault +CacheUnit::write(DynInstPtr inst, Twin64_t data, Addr addr, + unsigned flags, uint64_t *res); + +template +Fault +CacheUnit::write(DynInstPtr inst, uint64_t data, Addr addr, + unsigned flags, uint64_t *res); + +template +Fault +CacheUnit::write(DynInstPtr inst, uint32_t data, Addr addr, + unsigned flags, uint64_t *res); + +template +Fault +CacheUnit::write(DynInstPtr inst, uint16_t data, Addr addr, + unsigned flags, uint64_t *res); + +template +Fault +CacheUnit::write(DynInstPtr inst, uint8_t data, Addr addr, + unsigned flags, uint64_t *res); + +#endif //DOXYGEN_SHOULD_SKIP_THIS + +template<> +Fault +CacheUnit::write(DynInstPtr inst, double data, Addr addr, unsigned flags, uint64_t *res) +{ + return write(inst, *(uint64_t*)&data, addr, flags, res); +} + +template<> +Fault +CacheUnit::write(DynInstPtr inst, float data, Addr addr, unsigned flags, uint64_t *res) +{ + return write(inst, *(uint32_t*)&data, addr, flags, res); +} + + +template<> +Fault +CacheUnit::write(DynInstPtr inst, int32_t data, Addr addr, unsigned flags, uint64_t *res) +{ + return write(inst, (uint32_t)data, addr, flags, res); +} diff --git a/src/cpu/inorder/resources/cache_unit.hh b/src/cpu/inorder/resources/cache_unit.hh index 226a35a52..aba5a1b0c 100644 --- a/src/cpu/inorder/resources/cache_unit.hh +++ b/src/cpu/inorder/resources/cache_unit.hh @@ -36,6 +36,7 @@ #include #include +#include "arch/tlb.hh" #include "arch/predecoder.hh" #include "cpu/inorder/resource.hh" #include "cpu/inorder/inorder_dyn_inst.hh" @@ -124,7 +125,7 @@ class CacheUnit : public Resource cacheAccessComplete }; - ///virtual void init(); + void init(); virtual ResourceRequest* getRequest(DynInstPtr _inst, int stage_num, int res_idx, int slot_num, @@ -159,10 +160,20 @@ class CacheUnit : public Resource /** Returns a specific port. */ Port *getPort(const std::string &if_name, int idx); + template + Fault read(DynInstPtr inst, Addr addr, T &data, unsigned flags); + + template + Fault write(DynInstPtr inst, T data, Addr addr, unsigned flags, + uint64_t *res); + + Fault doTLBAccess(DynInstPtr inst, CacheReqPtr cache_req, int acc_size, + int flags, TheISA::TLB::Mode tlb_mode); + /** Read/Write on behalf of an instruction. * curResSlot needs to be a valid value in instruction. */ - Fault doDataAccess(DynInstPtr inst, uint64_t *write_result=NULL); + Fault doCacheAccess(DynInstPtr inst, uint64_t *write_result=NULL); void prefetch(DynInstPtr inst); @@ -209,23 +220,28 @@ class CacheUnit : public Resource //unsigned fetchOffset[ThePipeline::MaxThreads]; TheISA::Predecoder predecoder; + + bool tlbBlocked[ThePipeline::MaxThreads]; + + TheISA::TLB* tlb(); + + TheISA::TLB *_tlb; }; -struct CacheSchedEntry : public ThePipeline::ScheduleEntry -{ - enum EntryType { - FetchAccess, - DataAccess - }; +class CacheUnitEvent : public ResourceEvent { + public: + const std::string name() const + { + return "CacheUnitEvent"; + } - CacheSchedEntry(int stage_num, int _priority, int res_num, - MemCmd::Command pkt_cmd, EntryType _type = FetchAccess) - : ScheduleEntry(stage_num, _priority, res_num), pktCmd(pkt_cmd), - type(_type) - { } - MemCmd::Command pktCmd; - EntryType type; + /** Constructs a resource event. */ + CacheUnitEvent(); + virtual ~CacheUnitEvent() {} + + /** Processes a resource event. */ + virtual void process(); }; class CacheRequest : public ResourceRequest @@ -235,43 +251,17 @@ class CacheRequest : public ResourceRequest int slot_num, unsigned cmd, int req_size, MemCmd::Command pkt_cmd, unsigned flags, int cpu_id) : ResourceRequest(cres, inst, stage_num, res_idx, slot_num, cmd), - pktCmd(pkt_cmd), memAccComplete(false), memAccPending(false) - { - if (cmd == CacheUnit::InitiateFetch || - cmd == CacheUnit::CompleteFetch || - cmd == CacheUnit::Fetch) { - memReq = inst->fetchMemReq; - } else { - memReq = inst->dataMemReq; - } + pktCmd(pkt_cmd), memReq(NULL), reqData(NULL), dataPkt(NULL), + retryPkt(NULL), memAccComplete(false), memAccPending(false), + tlbStall(false) + { } - //@ Only matters for Fetch / Read requests - // Don't allocate for Writes! - reqData = new uint8_t[req_size]; - retryPkt = NULL; - } virtual ~CacheRequest() { -#if 0 - delete reqData; - - // Can get rid of packet and packet request now - if (*dataPkt) { - if (*dataPkt->req) { - delete dataPkt->req; - } - delete dataPkt; + if (reqData) { + delete [] reqData; } - - // Can get rid of packet and packet request now - if (retryPkt) { - if (retryPkt->req) { - delete retryPkt->req; - } - delete retryPkt; - } -#endif } virtual PacketDataPtr getData() @@ -297,6 +287,7 @@ class CacheRequest : public ResourceRequest bool memAccComplete; bool memAccPending; + bool tlbStall; }; class CacheReqPacket : public Packet diff --git a/src/cpu/inorder/resources/tlb_unit.hh b/src/cpu/inorder/resources/tlb_unit.hh index 759fe14f1..8f0291b48 100644 --- a/src/cpu/inorder/resources/tlb_unit.hh +++ b/src/cpu/inorder/resources/tlb_unit.hh @@ -114,8 +114,8 @@ class TLBUnitRequest : public ResourceRequest { memReq = inst->fetchMemReq; } else { aligned_addr = inst->getMemAddr();; - req_size = inst->getMemAccSize(); - flags = inst->getMemFlags(); + req_size = 0; //inst->getMemAccSize(); + flags = 0; //inst->getMemFlags(); if (req_size == 0 && (inst->isDataPrefetch() || inst->isInstPrefetch())) { req_size = 8; diff --git a/src/cpu/static_inst.cc b/src/cpu/static_inst.cc index 01136bda1..2c4fc8ab9 100644 --- a/src/cpu/static_inst.cc +++ b/src/cpu/static_inst.cc @@ -106,13 +106,6 @@ StaticInst::branchTarget(ThreadContext *tc) const M5_DUMMY_RETURN; } -Request::Flags -StaticInst::memAccFlags() -{ - panic("StaticInst::memAccFlags called on non-memory instruction"); - return 0; -} - const string & StaticInst::disassemble(Addr pc, const SymbolTable *symtab) const { diff --git a/src/cpu/static_inst.hh b/src/cpu/static_inst.hh index cb32f2333..1dc148ce6 100644 --- a/src/cpu/static_inst.hh +++ b/src/cpu/static_inst.hh @@ -419,8 +419,6 @@ class StaticInst : public StaticInstBase */ bool hasBranchTarget(Addr pc, ThreadContext *tc, Addr &tgt) const; - virtual Request::Flags memAccFlags(); - /** * Return string representation of disassembled instruction. * The default version of this function will call the internal