summaryrefslogtreecommitdiff
path: root/src/cpu/inorder/resources
diff options
context:
space:
mode:
Diffstat (limited to 'src/cpu/inorder/resources')
-rw-r--r--src/cpu/inorder/resources/cache_unit.cc373
-rw-r--r--src/cpu/inorder/resources/cache_unit.hh85
-rw-r--r--src/cpu/inorder/resources/tlb_unit.hh4
3 files changed, 369 insertions, 93 deletions
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<CacheReqPtr>(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 <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)
{
@@ -241,21 +371,46 @@ 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",
@@ -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<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)
@@ -630,7 +799,17 @@ CacheUnit::squash(DynInstPtr inst, int stage_num,
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);
@@ -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 <list>
#include <string>
+#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 <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);
@@ -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;
- }
-
- // 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()
@@ -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;