inorder-tlb: squash insts in TLB correctly
TLB had a bug where if it was stalled and waiting , it would not squash all instructions older than squashed instruction correctly * * *
This commit is contained in:
parent
f1c97e830b
commit
3a057bdbb1
6 changed files with 87 additions and 8 deletions
|
@ -80,6 +80,22 @@ InOrderCPU::CPUEvent::CPUEvent(InOrderCPU *_cpu, CPUEventType e_type,
|
||||||
setEvent(e_type, fault, _tid, _vpe);
|
setEvent(e_type, fault, _tid, _vpe);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string InOrderCPU::eventNames[NumCPUEvents] =
|
||||||
|
{
|
||||||
|
"ActivateThread",
|
||||||
|
"DeallocateThread",
|
||||||
|
"SuspendThread",
|
||||||
|
"DisableThreads",
|
||||||
|
"EnableThreads",
|
||||||
|
"DisableVPEs",
|
||||||
|
"EnableVPEs",
|
||||||
|
"Trap",
|
||||||
|
"InstGraduated",
|
||||||
|
"SquashAll",
|
||||||
|
"UpdatePCs"
|
||||||
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
InOrderCPU::CPUEvent::process()
|
InOrderCPU::CPUEvent::process()
|
||||||
{
|
{
|
||||||
|
@ -486,8 +502,8 @@ InOrderCPU::scheduleCpuEvent(CPUEventType c_event, Fault fault,
|
||||||
CPUEvent *cpu_event = new CPUEvent(this, c_event, fault, tid, vpe);
|
CPUEvent *cpu_event = new CPUEvent(this, c_event, fault, tid, vpe);
|
||||||
|
|
||||||
if (delay >= 0) {
|
if (delay >= 0) {
|
||||||
DPRINTF(InOrderCPU, "Scheduling CPU Event Type #%i for cycle %i.\n",
|
DPRINTF(InOrderCPU, "Scheduling CPU Event Type #%s for cycle %i.\n",
|
||||||
c_event, curTick + delay);
|
eventNames[c_event], curTick + delay);
|
||||||
mainEventQueue.schedule(cpu_event,curTick + delay);
|
mainEventQueue.schedule(cpu_event,curTick + delay);
|
||||||
} else {
|
} else {
|
||||||
cpu_event->process();
|
cpu_event->process();
|
||||||
|
|
|
@ -175,6 +175,8 @@ class InOrderCPU : public BaseCPU
|
||||||
NumCPUEvents
|
NumCPUEvents
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static std::string eventNames[NumCPUEvents];
|
||||||
|
|
||||||
/** Define CPU Event */
|
/** Define CPU Event */
|
||||||
class CPUEvent : public Event
|
class CPUEvent : public Event
|
||||||
{
|
{
|
||||||
|
|
|
@ -304,8 +304,11 @@ Resource::squash(DynInstPtr inst, int stage_num, InstSeqNum squash_seq_num, unsi
|
||||||
req_ptr->getInst()->readTid(),
|
req_ptr->getInst()->readTid(),
|
||||||
req_ptr->getInst()->seqNum);
|
req_ptr->getInst()->seqNum);
|
||||||
|
|
||||||
|
req_ptr->setSquashed();
|
||||||
|
|
||||||
int req_slot_num = req_ptr->getSlot();
|
int req_slot_num = req_ptr->getSlot();
|
||||||
|
|
||||||
|
if (resourceEvent[req_slot_num].scheduled())
|
||||||
unscheduleEvent(req_slot_num);
|
unscheduleEvent(req_slot_num);
|
||||||
|
|
||||||
// Mark request for later removal
|
// Mark request for later removal
|
||||||
|
|
|
@ -256,7 +256,7 @@ ResourcePool::scheduleEvent(InOrderCPU::CPUEventType e_type, DynInstPtr inst,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
DPRINTF(Resource, "Ignoring Unrecognized CPU Event Type #%i.\n", e_type);
|
DPRINTF(Resource, "Ignoring Unrecognized CPU Event Type #%s.\n", InOrderCPU::eventNames[e_type]);
|
||||||
; // If Resource Pool doesnt recognize event, we ignore it.
|
; // If Resource Pool doesnt recognize event, we ignore it.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,7 @@ using namespace ThePipeline;
|
||||||
|
|
||||||
TLBUnit::TLBUnit(string res_name, int res_id, int res_width,
|
TLBUnit::TLBUnit(string res_name, int res_id, int res_width,
|
||||||
int res_latency, InOrderCPU *_cpu, ThePipeline::Params *params)
|
int res_latency, InOrderCPU *_cpu, ThePipeline::Params *params)
|
||||||
: InstBuffer(res_name, res_id, res_width, res_latency, _cpu, params)
|
: Resource(res_name, res_id, res_width, res_latency, _cpu)
|
||||||
{
|
{
|
||||||
// Hard-Code Selection For Now
|
// Hard-Code Selection For Now
|
||||||
if (res_name == "I-TLB")
|
if (res_name == "I-TLB")
|
||||||
|
@ -124,7 +124,9 @@ TLBUnit::execute(int slot_idx)
|
||||||
DPRINTF(InOrderTLB, "[tid:%i]: %s encountered while translating "
|
DPRINTF(InOrderTLB, "[tid:%i]: %s encountered while translating "
|
||||||
"addr:%08p for [sn:%i].\n", tid, tlb_req->fault->name(),
|
"addr:%08p for [sn:%i].\n", tid, tlb_req->fault->name(),
|
||||||
tlb_req->memReq->getVaddr(), seq_num);
|
tlb_req->memReq->getVaddr(), seq_num);
|
||||||
//insert(inst);
|
|
||||||
|
DPRINTF(InOrderTLB, "slot:%i sn:%i schedule event.\n", slot_idx, seq_num);
|
||||||
|
|
||||||
cpu->pipelineStage[stage_num]->setResStall(tlb_req, tid);
|
cpu->pipelineStage[stage_num]->setResStall(tlb_req, tid);
|
||||||
tlbBlocked[tid] = true;
|
tlbBlocked[tid] = true;
|
||||||
scheduleEvent(slot_idx, 1);
|
scheduleEvent(slot_idx, 1);
|
||||||
|
@ -210,7 +212,7 @@ TLBUnitEvent::process()
|
||||||
|
|
||||||
tlb_res->tlbBlocked[tid] = false;
|
tlb_res->tlbBlocked[tid] = false;
|
||||||
|
|
||||||
tlb_res->cpu->pipelineStage[stage_num]->unsetResStall(resource->reqMap[slotIdx], tid);
|
tlb_res->cpu->pipelineStage[stage_num]->unsetResStall(tlb_res->reqMap[slotIdx], tid);
|
||||||
|
|
||||||
// Effectively NOP the instruction but still allow it
|
// Effectively NOP the instruction but still allow it
|
||||||
// to commit
|
// to commit
|
||||||
|
@ -219,3 +221,56 @@ TLBUnitEvent::process()
|
||||||
//inst->resSched.pop();
|
//inst->resSched.pop();
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TLBUnit::squash(DynInstPtr inst, int stage_num,
|
||||||
|
InstSeqNum squash_seq_num, unsigned tid)
|
||||||
|
{
|
||||||
|
//@TODO: Figure out a way to consolidate common parts
|
||||||
|
// of this squash code
|
||||||
|
std::vector<int> slot_remove_list;
|
||||||
|
|
||||||
|
map<int, ResReqPtr>::iterator map_it = reqMap.begin();
|
||||||
|
map<int, ResReqPtr>::iterator map_end = reqMap.end();
|
||||||
|
|
||||||
|
while (map_it != map_end) {
|
||||||
|
ResReqPtr req_ptr = (*map_it).second;
|
||||||
|
|
||||||
|
if (req_ptr &&
|
||||||
|
req_ptr->getInst()->readTid() == tid &&
|
||||||
|
req_ptr->getInst()->seqNum > squash_seq_num) {
|
||||||
|
|
||||||
|
DPRINTF(Resource, "[tid:%i]: Squashing [sn:%i].\n",
|
||||||
|
req_ptr->getInst()->readTid(),
|
||||||
|
req_ptr->getInst()->seqNum);
|
||||||
|
|
||||||
|
req_ptr->setSquashed();
|
||||||
|
|
||||||
|
int req_slot_num = req_ptr->getSlot();
|
||||||
|
|
||||||
|
tlbBlocked[tid] = false;
|
||||||
|
|
||||||
|
int stall_stage = reqMap[req_slot_num]->getStageNum();
|
||||||
|
|
||||||
|
cpu->pipelineStage[stall_stage]->unsetResStall(reqMap[req_slot_num], tid);
|
||||||
|
|
||||||
|
if (resourceEvent[req_slot_num].scheduled())
|
||||||
|
unscheduleEvent(req_slot_num);
|
||||||
|
|
||||||
|
// Mark request for later removal
|
||||||
|
cpu->reqRemoveList.push(req_ptr);
|
||||||
|
|
||||||
|
// Mark slot for removal from resource
|
||||||
|
slot_remove_list.push_back(req_ptr->getSlot());
|
||||||
|
}
|
||||||
|
|
||||||
|
map_it++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now Delete Slot Entry from Req. Map
|
||||||
|
for (int i = 0; i < slot_remove_list.size(); i++) {
|
||||||
|
freeSlot(slot_remove_list[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,8 @@
|
||||||
#include "cpu/inorder/pipeline_traits.hh"
|
#include "cpu/inorder/pipeline_traits.hh"
|
||||||
#include "cpu/inorder/cpu.hh"
|
#include "cpu/inorder/cpu.hh"
|
||||||
|
|
||||||
class TLBUnit : public InstBuffer {
|
class TLBUnit : public Resource
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
typedef ThePipeline::DynInstPtr DynInstPtr;
|
typedef ThePipeline::DynInstPtr DynInstPtr;
|
||||||
|
|
||||||
|
@ -66,6 +67,8 @@ class TLBUnit : public InstBuffer {
|
||||||
|
|
||||||
virtual void execute(int slot_num);
|
virtual void execute(int slot_num);
|
||||||
|
|
||||||
|
void squash(DynInstPtr inst, int stage_num, InstSeqNum squash_seq_num, unsigned tid);
|
||||||
|
|
||||||
bool tlbBlocked[ThePipeline::MaxThreads];
|
bool tlbBlocked[ThePipeline::MaxThreads];
|
||||||
|
|
||||||
TheISA::TLB* tlb();
|
TheISA::TLB* tlb();
|
||||||
|
|
Loading…
Reference in a new issue