inorder: SE mode TLB faults
handle them like we do in FS mode, by blocking the TLB until the fault is handled by the fault->invoke()
This commit is contained in:
parent
3cb23bd3a2
commit
078f914e69
4 changed files with 41 additions and 36 deletions
|
@ -46,7 +46,8 @@ using namespace std;
|
|||
Resource::Resource(string res_name, int res_id, int res_width,
|
||||
int res_latency, InOrderCPU *_cpu)
|
||||
: resName(res_name), id(res_id),
|
||||
width(res_width), latency(res_latency), cpu(_cpu)
|
||||
width(res_width), latency(res_latency), cpu(_cpu),
|
||||
resourceEvent(NULL)
|
||||
{
|
||||
reqs.resize(width);
|
||||
|
||||
|
@ -75,15 +76,13 @@ Resource::init()
|
|||
// If the resource has a zero-cycle (no latency)
|
||||
// function, then no reason to have events
|
||||
// that will process them for the right tick
|
||||
if (latency > 0) {
|
||||
if (latency > 0)
|
||||
resourceEvent = new ResourceEvent[width];
|
||||
} else {
|
||||
resourceEvent = NULL;
|
||||
}
|
||||
|
||||
for (int i = 0; i < width; i++) {
|
||||
|
||||
for (int i = 0; i < width; i++)
|
||||
reqs[i] = new ResourceRequest(this);
|
||||
}
|
||||
|
||||
|
||||
initSlots();
|
||||
}
|
||||
|
|
|
@ -178,10 +178,6 @@ CacheUnit::init()
|
|||
reqs[i] = new CacheRequest(this);
|
||||
}
|
||||
|
||||
// Currently Used to Model TLB Latency. Eventually
|
||||
// Switch to Timing TLB translations.
|
||||
resourceEvent = new CacheUnitEvent[width];
|
||||
|
||||
cacheBlkSize = this->cachePort->peerBlockSize();
|
||||
cacheBlkMask = cacheBlkSize - 1;
|
||||
|
||||
|
@ -433,30 +429,22 @@ CacheUnit::doTLBAccess(DynInstPtr inst, CacheReqPtr cache_req, int acc_size,
|
|||
ThreadContext *tc = cpu->thread[tid]->getTC();
|
||||
PCState old_pc = tc->pcState();
|
||||
tc->pcState() = inst->pcState();
|
||||
|
||||
inst->fault =
|
||||
_tlb->translateAtomic(cache_req->memReq, tc, tlb_mode);
|
||||
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(),
|
||||
"addr:%08p for [sn:%i].\n", tid, tlb_fault->name(),
|
||||
cache_req->memReq->getVaddr(), inst->seqNum);
|
||||
|
||||
tlbBlocked[tid] = true;
|
||||
tlbBlockSeqNum[tid] = inst->seqNum;
|
||||
|
||||
#if !FULL_SYSTEM
|
||||
unsigned stage_num = cache_req->getStageNum();
|
||||
|
||||
cpu->pipelineStage[stage_num]->setResStall(cache_req, tid);
|
||||
cache_req->tlbStall = true;
|
||||
|
||||
// schedule a time to process the tlb miss.
|
||||
// latency hardcoded to 1 (for now), but will be updated
|
||||
// when timing translation gets added in
|
||||
unsigned slot_idx = cache_req->getSlot();
|
||||
scheduleEvent(slot_idx, 1);
|
||||
#endif
|
||||
// Make sure nothing gets executed until after this faulting
|
||||
// instruction gets handled.
|
||||
inst->setSerializeAfter();
|
||||
|
||||
// Mark it as complete so it can pass through next stage.
|
||||
// Fault Handling will happen at commit/graduation
|
||||
|
@ -467,9 +455,16 @@ CacheUnit::doTLBAccess(DynInstPtr inst, CacheReqPtr cache_req, int acc_size,
|
|||
cache_req->memReq->getVaddr(),
|
||||
cache_req->memReq->getPaddr());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#if !FULL_SYSTEM
|
||||
void
|
||||
CacheUnit::trap(Fault fault, ThreadID tid, DynInstPtr inst)
|
||||
{
|
||||
tlbBlocked[tid] = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
Fault
|
||||
CacheUnit::read(DynInstPtr inst, Addr addr,
|
||||
uint8_t *data, unsigned size, unsigned flags)
|
||||
|
@ -703,6 +698,14 @@ CacheUnit::execute(int slot_num)
|
|||
return;
|
||||
}
|
||||
|
||||
if (inst->isSquashed()) {
|
||||
DPRINTF(InOrderCachePort,
|
||||
"[tid:%i]: [sn:%i]: Detected squashed instruction "
|
||||
"next stage.\n", inst->readTid(), inst->seqNum);
|
||||
finishCacheUnitReq(inst, cache_req);
|
||||
return;
|
||||
}
|
||||
|
||||
#if TRACING_ON
|
||||
ThreadID tid = inst->readTid();
|
||||
std::string acc_type = "write";
|
||||
|
|
|
@ -157,6 +157,9 @@ class CacheUnit : public Resource
|
|||
|
||||
bool processSquash(CacheReqPacket *cache_pkt);
|
||||
|
||||
#if !FULL_SYSTEM
|
||||
void trap(Fault fault, ThreadID tid, DynInstPtr inst);
|
||||
#endif
|
||||
void recvRetry();
|
||||
|
||||
/** Returns a specific port. */
|
||||
|
|
|
@ -159,15 +159,6 @@ UseDefUnit::execute(int slot_idx)
|
|||
InstSeqNum seq_num = inst->seqNum;
|
||||
int ud_idx = ud_req->useDefIdx;
|
||||
|
||||
if (inst->fault != NoFault) {
|
||||
DPRINTF(InOrderUseDef,
|
||||
"[tid:%i]: [sn:%i]: Detected %s fault @ %x. Forwarding to "
|
||||
"next stage.\n", inst->readTid(), inst->seqNum, inst->fault->name(),
|
||||
inst->pcState());
|
||||
ud_req->done();
|
||||
return;
|
||||
}
|
||||
|
||||
if (serializeOnNextInst[tid] &&
|
||||
seq_num > serializeAfterSeqNum[tid]) {
|
||||
inst->setSerializeBefore();
|
||||
|
@ -187,6 +178,15 @@ UseDefUnit::execute(int slot_idx)
|
|||
serializeAfterSeqNum[tid] = seq_num;
|
||||
}
|
||||
|
||||
if (inst->fault != NoFault) {
|
||||
DPRINTF(InOrderUseDef,
|
||||
"[tid:%i]: [sn:%i]: Detected %s fault @ %x. Forwarding to "
|
||||
"next stage.\n", inst->readTid(), inst->seqNum, inst->fault->name(),
|
||||
inst->pcState());
|
||||
ud_req->done();
|
||||
return;
|
||||
}
|
||||
|
||||
// If there is a non-speculative instruction
|
||||
// in the pipeline then stall instructions here
|
||||
// ---
|
||||
|
|
Loading…
Reference in a new issue