TLBUnit no longer used and we also get rid of memAccSize and memAccFlags functions added to ISA and StaticInst
since TLB is not a separate resource to acquire. Instead, TLB access is done before any read/write to memory
and the result is checked before it's sent out to memory.
* * *
std::string
generateDisassembly(Addr pc, const SymbolTable *symtab) const;
-
- public:
-
- Request::Flags memAccFlags() { return memAccessFlags; }
};
/**
%(InitiateAccDeclare)s
%(CompleteAccDeclare)s
-
- %(MemAccSizeDeclare)s
};
}};
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)
}
}};
-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
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),
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; }},
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 = '''
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')
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",
void
InOrderCPU::trap(Fault fault, unsigned tid, int delay)
{
+ //@ Squash Pipeline during TRAP
scheduleCpuEvent(Trap, fault, tid, 0/*vpe*/, delay);
}
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 {
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)
{
TheISA::TLB*
InOrderCPU::getITBPtr()
{
- TLBUnit *itb_res = dynamic_cast<TLBUnit*>(resPool->getResource(itbIdx));
+ CacheUnit *itb_res =
+ dynamic_cast<CacheUnit*>(resPool->getResource(fetchPortIdx));
return itb_res->tlb();
}
TheISA::TLB*
InOrderCPU::getDTBPtr()
{
- TLBUnit *dtb_res = dynamic_cast<TLBUnit*>(resPool->getResource(dtbIdx));
+ CacheUnit *dtb_res =
+ dynamic_cast<CacheUnit*>(resPool->getResource(dataPortIdx));
return dtb_res->tlb();
}
+
+template <class T>
+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<CacheUnit*>(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 <class T>
+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<CacheUnit*>(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);
+}
/** Forwards an instruction read to the appropriate data
* resource (indexes into Resource Pool thru "dataPortIdx")
*/
- Fault read(DynInstPtr inst);
+ template <class T>
+ 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 <class T>
+ 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")
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
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
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; }
InstStage *E = inst->addStage();
I->needs(FetchSeq, FetchSeqUnit::AssignNextPC);
- I->needs(ITLB, TLBUnit::FetchLookup);
I->needs(ICache, CacheUnit::InitiateFetch);
E->needs(ICache, CacheUnit::CompleteFetch);
} 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);
}
} 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);
}
// Enumerated List of Resources The Pipeline Uses
enum ResourceList {
FetchSeq = 0,
- ITLB,
ICache,
Decode,
BPred,
AGEN,
ExecUnit,
MDU,
- DTLB,
DCache,
Grad,
FetchBuff2
* 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);
// --------------------------------------------------
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));
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));
inst->bdelaySeqNum,
inst->readTid());
mainEventQueue.schedule(res_pool_event, curTick + cpu->ticks(delay));
-
}
break;
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.
}
}
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 *
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");
}
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<CacheReqPtr>(findRequest(inst));
assert(cache_req);
// 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;
}
}
+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 <class T>
+Fault
+CacheUnit::read(DynInstPtr inst, Addr addr, T &data, unsigned flags)
+{
+ CacheReqPtr cache_req = dynamic_cast<CacheReqPtr>(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 <class T>
+Fault
+CacheUnit::write(DynInstPtr inst, T data, Addr addr, unsigned flags,
+ uint64_t *write_res)
+{
+ CacheReqPtr cache_req = dynamic_cast<CacheReqPtr>(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)
{
switch (cache_req->cmd)
{
case InitiateFetch:
- DPRINTF(InOrderCachePort,
- "[tid:%u]: Initiating fetch access to %s for addr. %08p\n",
- tid, name(), cache_req->inst->getMemAddr());
+ {
+ //@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]: Fetching new cache block from addr: %08p\n",
- tid, cache_req->memReq->getVaddr());
+ "[tid:%u]: Initiating data access to %s for addr. %08p\n",
+ tid, name(), cache_req->inst->getMemAddr());
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",
}
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,
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;
}
}
+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<CacheReqPtr>(resource->reqMap[slotIdx]);
+
+ DPRINTF(InOrderTLB, "Waking up from TLB Miss caused by [sn:%i].\n",
+ inst->seqNum);
+
+ CacheUnit* tlb_res = dynamic_cast<CacheUnit*>(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)
CacheReqPtr cache_req = dynamic_cast<CacheReqPtr>(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);
}
}
+// 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);
+}
#include <list>
#include <string>
+#include "arch/tlb.hh"
#include "arch/predecoder.hh"
#include "cpu/inorder/resource.hh"
#include "cpu/inorder/inorder_dyn_inst.hh"
cacheAccessComplete
};
- ///virtual void init();
+ void init();
virtual ResourceRequest* getRequest(DynInstPtr _inst, int stage_num,
int res_idx, int slot_num,
/** Returns a specific port. */
Port *getPort(const std::string &if_name, int idx);
+ template <class T>
+ Fault read(DynInstPtr inst, Addr addr, T &data, unsigned flags);
+
+ template <class T>
+ 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);
//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
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;
- }
-
- // Can get rid of packet and packet request now
- if (retryPkt) {
- if (retryPkt->req) {
- delete retryPkt->req;
- }
- delete retryPkt;
+ if (reqData) {
+ delete [] reqData;
}
-#endif
}
virtual PacketDataPtr getData()
bool memAccComplete;
bool memAccPending;
+ bool tlbStall;
};
class CacheReqPacket : public Packet
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;
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
{
*/
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