*
*/
-#include <vector>
#include <list>
+#include <vector>
+
#include "arch/isa_traits.hh"
-#include "cpu/inorder/pipeline_traits.hh"
+#include "config/the_isa.hh"
#include "cpu/inorder/resources/tlb_unit.hh"
#include "cpu/inorder/cpu.hh"
+#include "cpu/inorder/first_stage.hh"
+#include "cpu/inorder/pipeline_traits.hh"
using namespace std;
using namespace TheISA;
using namespace ThePipeline;
TLBUnit::TLBUnit(string res_name, int res_id, int res_width,
- int res_latency, InOrderCPU *_cpu, ThePipeline::Params *params)
- : InstBuffer(res_name, res_id, res_width, res_latency, _cpu, params)
+ Cycles res_latency, InOrderCPU *_cpu,
+ ThePipeline::Params *params)
+: Resource(res_name, res_id, res_width, res_latency, _cpu)
{
+ // Hard-Code Selection For Now
+ if (res_name == "I-TLB")
+ _tlb = params->itb;
+ else if (res_name == "D-TLB")
+ _tlb = params->dtb;
+ else
+ fatal("Unrecognized TLB name passed by user");
+
for (int i=0; i < MaxThreads; i++) {
tlbBlocked[i] = false;
}
}
+TheISA::TLB*
+TLBUnit::tlb()
+{
+ return _tlb;
+
+}
+
void
TLBUnit::init()
{
resourceEvent = new TLBUnitEvent[width];
+ for (int i = 0; i < width; i++) {
+ reqs[i] = new TLBUnitRequest(this);
+ }
+
initSlots();
}
int res_idx, int slot_num,
unsigned cmd)
{
- return new TLBUnitRequest(this, _inst, stage_num, res_idx, slot_num,
- cmd);
+ TLBUnitRequest *tlb_req = dynamic_cast<TLBUnitRequest*>(reqs[slot_num]);
+ tlb_req->setRequest(inst, stage_num, id, slot_num, cmd);
+ return ud_req;
}
void
{
// After this is working, change this to a reinterpret cast
// for performance considerations
- TLBUnitRequest* tlb_req = dynamic_cast<TLBUnitRequest*>(reqMap[slot_idx]);
- assert(tlb_req);
+ TLBUnitRequest* tlb_req = dynamic_cast<TLBUnitRequest*>(reqs[slot_idx]);
+ assert(tlb_req != 0x0);
DynInstPtr inst = tlb_req->inst;
- int tid, seq_num, stage_num;
-
- tid = inst->readTid();
- seq_num = inst->seqNum;
- stage_num = tlb_req->getStageNum();
+ ThreadID tid = inst->readTid();
+ InstSeqNum seq_num = inst->seqNum;
+ int stage_num = tlb_req->getStageNum();
tlb_req->fault = NoFault;
+ assert(cpu->thread[tid]->getTC() != 0x0);
+ assert(cpu->pipelineStage[stage_num] != 0x0);
+
switch (tlb_req->cmd)
{
case FetchLookup:
{
tlb_req->fault =
- this->cpu->translateInstReq(tlb_req->memReq, cpu->thread[tid]);
+ _tlb->translateAtomic(tlb_req->memReq,
+ cpu->thread[tid]->getTC(), TheISA::TLB::Execute);
if (tlb_req->fault != NoFault) {
- DPRINTF(Resource, "[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(),
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);
tlbBlocked[tid] = true;
scheduleEvent(slot_idx, 1);
// Let CPU handle the fault
cpu->trap(tlb_req->fault, tid);
} else {
- DPRINTF(Resource, "[tid:%i]: [sn:%i] virt. addr %08p translated "
+ DPRINTF(InOrderTLB, "[tid:%i]: [sn:%i] virt. addr %08p translated "
"to phys. addr:%08p.\n", tid, seq_num,
tlb_req->memReq->getVaddr(),
tlb_req->memReq->getPaddr());
}
break;
- case DataLookup:
+ case DataReadLookup:
+ case DataWriteLookup:
{
- DPRINTF(Resource, "[tid:%i]: [sn:%i]: Attempting to translate %08p.\n",
+ DPRINTF(InOrderTLB, "[tid:%i]: [sn:%i]: Attempting to translate %08p.\n",
tid, seq_num, tlb_req->memReq->getVaddr());
+
+ TheISA::TLB::Mode tlb_mode = (tlb_req->cmd == DataReadLookup) ?
+ TheISA::TLB::Read : TheISA::TLB::Write;
+
tlb_req->fault =
- this->cpu->translateInstReq(tlb_req->memReq, cpu->thread[tid]);
+ _tlb->translateAtomic(tlb_req->memReq,
+ cpu->thread[tid]->getTC(), tlb_mode);
if (tlb_req->fault != NoFault) {
- DPRINTF(Resource, "[tid:%i]: %s encountered while translating "
- "addr:%08p for [sn:%i].\n", tid, tlb_req->fault->name(),
- tlb_req->memReq->getVaddr(), seq_num);
- //insert(inst);
- cpu->pipelineStage[stage_num]->setResStall(tlb_req, tid);
- tlbBlocked[tid] = true;
- scheduleEvent(slot_idx, 1);
+ DPRINTF(InOrderTLB, "[tid:%i]: %s encountered while translating "
+ "addr:%08p for [sn:%i] %s.\n", tid, tlb_req->fault->name(),
+ tlb_req->memReq->getVaddr(), seq_num, inst->instName());
- // Let CPU handle the fault
- cpu->trap(tlb_req->fault, tid);
+ if (inst->isDataPrefetch()) {
+ DPRINTF(InOrderTLB, "Ignoring %s fault for data prefetch\n",
+ tlb_req->fault->name());
+
+ tlb_req->fault = NoFault;
+
+ tlb_req->done();
+ } else {
+ cpu->pipelineStage[stage_num]->setResStall(tlb_req, tid);
+ tlbBlocked[tid] = true;
+ scheduleEvent(slot_idx, 1);
+
+ // Let CPU handle the fault
+ cpu->trap(tlb_req->fault, tid, inst);
+ }
} else {
- DPRINTF(Resource, "[tid:%i]: [sn:%i] virt. addr %08p translated "
+ DPRINTF(InOrderTLB, "[tid:%i]: [sn:%i] virt. addr %08p translated "
"to phys. addr:%08p.\n", tid, seq_num,
tlb_req->memReq->getVaddr(),
tlb_req->memReq->getPaddr());
void
TLBUnitEvent::process()
{
- DynInstPtr inst = resource->reqMap[slotIdx]->inst;
- int stage_num = resource->reqMap[slotIdx]->getStageNum();
- int tid = inst->threadNumber;
+ DynInstPtr inst = resource->reqs[slotIdx]->inst;
+ int stage_num = resource->reqs[slotIdx]->getStageNum();
+ ThreadID tid = inst->threadNumber;
- DPRINTF(Resource, "Waking up from TLB Miss caused by [sn:%i].\n",
+ DPRINTF(InOrderTLB, "Waking up from TLB Miss caused by [sn:%i].\n",
inst->seqNum);
TLBUnit* tlb_res = dynamic_cast<TLBUnit*>(resource);
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->reqs[slotIdx], tid);
+}
+
+void
+TLBUnit::squash(DynInstPtr inst, int stage_num,
+ InstSeqNum squash_seq_num, ThreadID tid)
+{
+ for (int i = 0; i < width; i++) {
+ ResReqPtr req_ptr = reqs[i];
- // Effectively NOP the instruction but still allow it
- // to commit
- //while (!inst->resSched.empty() &&
- // inst->resSched.top()->stageNum != ThePipeline::NumStages - 1) {
- //inst->resSched.pop();
- //}
+ if (req_ptr->valid &&
+ 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 = reqs[req_slot_num]->getStageNum();
+
+ cpu->pipelineStage[stall_stage]->
+ unsetResStall(reqs[req_slot_num], tid);
+
+ if (resourceEvent[req_slot_num].scheduled())
+ unscheduleEvent(req_slot_num);
+
+ freeSlot(req_slot_num);
+ }
+ }
}
+
+