summaryrefslogtreecommitdiff
path: root/src/cpu
diff options
context:
space:
mode:
authorKorey Sewell <ksewell@umich.edu>2010-01-31 18:30:35 -0500
committerKorey Sewell <ksewell@umich.edu>2010-01-31 18:30:35 -0500
commit6939482c49b489ad8811364ec52ad10ae421fb44 (patch)
tree6eb023749052c773df869d189965a3d8ee07070a /src/cpu
parentea8909925fd0e7a33feabc9e17f83b85cd7c6039 (diff)
downloadgem5-6939482c49b489ad8811364ec52ad10ae421fb44.tar.xz
inorder: implement split loads
Diffstat (limited to 'src/cpu')
-rw-r--r--src/cpu/inorder/inorder_dyn_inst.cc10
-rw-r--r--src/cpu/inorder/inorder_dyn_inst.hh18
-rw-r--r--src/cpu/inorder/pipeline_traits.hh6
-rw-r--r--src/cpu/inorder/resource.cc13
-rw-r--r--src/cpu/inorder/resource_pool.cc19
-rw-r--r--src/cpu/inorder/resource_pool.hh1
-rw-r--r--src/cpu/inorder/resources/cache_unit.cc312
-rw-r--r--src/cpu/inorder/resources/cache_unit.hh36
8 files changed, 374 insertions, 41 deletions
diff --git a/src/cpu/inorder/inorder_dyn_inst.cc b/src/cpu/inorder/inorder_dyn_inst.cc
index 79f8de05d..9c0313721 100644
--- a/src/cpu/inorder/inorder_dyn_inst.cc
+++ b/src/cpu/inorder/inorder_dyn_inst.cc
@@ -111,7 +111,11 @@ InOrderDynInst::initVars()
{
fetchMemReq = NULL;
dataMemReq = NULL;
-
+ splitMemData = NULL;
+ split2ndAccess = false;
+ splitInst = false;
+ splitFinishCnt = 0;
+
effAddr = 0;
physEffAddr = 0;
@@ -187,6 +191,10 @@ InOrderDynInst::~InOrderDynInst()
delete traceData;
}
+ if (splitMemData) {
+ delete splitMemData;
+ }
+
fault = NoFault;
--instcount;
diff --git a/src/cpu/inorder/inorder_dyn_inst.hh b/src/cpu/inorder/inorder_dyn_inst.hh
index b573c1029..6f5b7c0e9 100644
--- a/src/cpu/inorder/inorder_dyn_inst.hh
+++ b/src/cpu/inorder/inorder_dyn_inst.hh
@@ -330,6 +330,19 @@ class InOrderDynInst : public FastAlloc, public RefCounted
public:
Tick memTime;
+ PacketDataPtr splitMemData;
+ RequestPtr splitMemReq;
+ int splitTotalSize;
+ int split2ndSize;
+ Addr split2ndAddr;
+ bool split2ndAccess;
+ uint8_t split2ndData;
+ PacketDataPtr split2ndDataPtr;
+ unsigned split2ndFlags;
+ bool splitInst;
+ int splitFinishCnt;
+
+
////////////////////////////////////////////////////////////
//
// BASE INSTRUCTION INFORMATION.
@@ -468,7 +481,10 @@ class InOrderDynInst : public FastAlloc, public RefCounted
if (!resSched.empty()) {
ThePipeline::ScheduleEntry* sked = resSched.top();
resSched.pop();
- delete sked;
+ if (sked != 0) {
+ delete sked;
+
+ }
}
}
diff --git a/src/cpu/inorder/pipeline_traits.hh b/src/cpu/inorder/pipeline_traits.hh
index ddc8a3ad7..f039b9e5d 100644
--- a/src/cpu/inorder/pipeline_traits.hh
+++ b/src/cpu/inorder/pipeline_traits.hh
@@ -53,8 +53,8 @@ namespace ThePipeline {
const unsigned StageWidth = 1;
const unsigned BackEndStartStage = 2;
- // Enumerated List of Resources The Pipeline Uses
- enum ResourceList {
+ // List of Resources The Pipeline Uses
+ enum ResourceId {
FetchSeq = 0,
ICache,
Decode,
@@ -94,6 +94,7 @@ namespace ThePipeline {
stageNum(stage_num), resNum(res_num), cmd(_cmd),
idx(_idx), priority(_priority)
{ }
+
virtual ~ScheduleEntry(){}
// Stage number to perform this service.
@@ -159,7 +160,6 @@ namespace ThePipeline {
stageNum, nextTaskPriority++, unit, request, param
));
}
-
};
};
diff --git a/src/cpu/inorder/resource.cc b/src/cpu/inorder/resource.cc
index e5fd4f70e..dcf5f3117 100644
--- a/src/cpu/inorder/resource.cc
+++ b/src/cpu/inorder/resource.cc
@@ -262,15 +262,22 @@ Resource::findRequest(DynInstPtr inst)
map<int, ResReqPtr>::iterator map_it = reqMap.begin();
map<int, ResReqPtr>::iterator map_end = reqMap.end();
+ bool found = false;
+ ResReqPtr req = NULL;
+
while (map_it != map_end) {
if ((*map_it).second &&
- (*map_it).second->getInst() == inst) {
- return (*map_it).second;
+ (*map_it).second->getInst() == inst) {
+ req = (*map_it).second;
+ //return (*map_it).second;
+ assert(found == false);
+ found = true;
}
map_it++;
}
- return NULL;
+ return req;
+ //return NULL;
}
void
diff --git a/src/cpu/inorder/resource_pool.cc b/src/cpu/inorder/resource_pool.cc
index 1f15a2c96..74bf4f03b 100644
--- a/src/cpu/inorder/resource_pool.cc
+++ b/src/cpu/inorder/resource_pool.cc
@@ -181,6 +181,25 @@ ResourcePool::getResIdx(const std::string &res_name)
return idx;
}
+ panic("Can't find resource idx for: %s\n", res_name);
+ return 0;
+}
+
+unsigned
+ResourcePool::getResIdx(const ThePipeline::ResourceId &res_id)
+{
+ int num_resources = resources.size();
+
+ for (int idx = 0; idx < num_resources; idx++) {
+ if (resources[idx]->getId() == res_id)
+ return idx;
+ }
+
+ // todo: change return value to int and return a -1 here
+ // maybe even have enumerated type
+ // panic for now...
+ panic("Can't find resource idx for: %i\n", res_id);
+
return 0;
}
diff --git a/src/cpu/inorder/resource_pool.hh b/src/cpu/inorder/resource_pool.hh
index ce7167b87..60d35ab61 100644
--- a/src/cpu/inorder/resource_pool.hh
+++ b/src/cpu/inorder/resource_pool.hh
@@ -141,6 +141,7 @@ class ResourcePool {
/** Returns a specific resource. */
unsigned getResIdx(const std::string &res_name);
+ unsigned getResIdx(const ThePipeline::ResourceId &res_id);
/** Returns a pointer to a resource */
Resource* getResource(int res_idx) { return resources[res_idx]; }
diff --git a/src/cpu/inorder/resources/cache_unit.cc b/src/cpu/inorder/resources/cache_unit.cc
index 275d9a7e8..85ef18a55 100644
--- a/src/cpu/inorder/resources/cache_unit.cc
+++ b/src/cpu/inorder/resources/cache_unit.cc
@@ -40,6 +40,7 @@
#include "cpu/inorder/resources/cache_unit.hh"
#include "cpu/inorder/pipeline_traits.hh"
#include "cpu/inorder/cpu.hh"
+#include "cpu/inorder/resource_pool.hh"
#include "mem/request.hh"
using namespace std;
@@ -136,7 +137,9 @@ CacheUnit::getSlot(DynInstPtr inst)
return -1;
}
- if (!inst->validMemAddr()) {
+ // For a Split-Load, the instruction would have processed once already
+ // causing the address to be unset.
+ if (!inst->validMemAddr() && !inst->splitInst) {
panic("Mem. Addr. must be set before requesting cache access\n");
}
@@ -159,12 +162,24 @@ CacheUnit::getSlot(DynInstPtr inst)
inst->readTid(), inst->seqNum, req_addr);
return new_slot;
} else {
- DPRINTF(InOrderCachePort,
+ // Allow same instruction multiple accesses to same address
+ if (addrMap[tid][req_addr] == inst->seqNum) {
+ int new_slot = Resource::getSlot(inst);
+
+ if (new_slot == -1)
+ return -1;
+
+ return new_slot;
+ } else {
+ DPRINTF(InOrderCachePort,
"[tid:%i] Denying request because there is an outstanding"
" request to/for addr. %08p. by [sn:%i] @ tick %i\n",
inst->readTid(), req_addr, addrMap[tid][req_addr], inst->memTime);
- return -1;
+ return -1;
+ }
}
+
+ return -1;
}
void
@@ -175,18 +190,70 @@ CacheUnit::freeSlot(int slot_num)
vector<Addr>::iterator vect_it =
find(addrList[tid].begin(), addrList[tid].end(),
reqMap[slot_num]->inst->getMemAddr());
- assert(vect_it != addrList[tid].end());
+
+ assert(vect_it != addrList[tid].end() ||
+ reqMap[slot_num]->inst->splitInst);
DPRINTF(InOrderCachePort,
"[tid:%i]: Address %08p removed from dependency list\n",
reqMap[slot_num]->inst->readTid(), (*vect_it));
- addrList[tid].erase(vect_it);
+ if (vect_it != addrList[tid].end()) {
+
+ DPRINTF(InOrderCachePort,
+ "[tid:%i]: Address %08p removed from dependency list\n",
+ reqMap[slot_num]->inst->readTid(), (*vect_it));
+
+ addrList[tid].erase(vect_it);
+ }
Resource::freeSlot(slot_num);
}
ResReqPtr
+CacheUnit::findRequest(DynInstPtr inst)
+{
+ map<int, ResReqPtr>::iterator map_it = reqMap.begin();
+ map<int, ResReqPtr>::iterator map_end = reqMap.end();
+
+ while (map_it != map_end) {
+ CacheRequest* cache_req = dynamic_cast<CacheRequest*>((*map_it).second);
+ assert(cache_req);
+
+ if (cache_req &&
+ cache_req->getInst() == inst &&
+ cache_req->instIdx == inst->resSched.top()->idx) {
+ return cache_req;
+ }
+ map_it++;
+ }
+
+ return NULL;
+}
+
+ResReqPtr
+CacheUnit::findSplitRequest(DynInstPtr inst, int idx)
+{
+ map<int, ResReqPtr>::iterator map_it = reqMap.begin();
+ map<int, ResReqPtr>::iterator map_end = reqMap.end();
+
+ while (map_it != map_end) {
+ CacheRequest* cache_req = dynamic_cast<CacheRequest*>((*map_it).second);
+ assert(cache_req);
+
+ if (cache_req &&
+ cache_req->getInst() == inst &&
+ cache_req->instIdx == idx) {
+ return cache_req;
+ }
+ map_it++;
+ }
+
+ return NULL;
+}
+
+
+ResReqPtr
CacheUnit::getRequest(DynInstPtr inst, int stage_num, int res_idx,
int slot_num, unsigned cmd)
{
@@ -200,6 +267,14 @@ CacheUnit::getRequest(DynInstPtr inst, int stage_num, int res_idx,
switch (sched_entry->cmd)
{
+ case InitSecondSplitRead:
+ pkt_cmd = MemCmd::ReadReq;
+
+ DPRINTF(InOrderCachePort,
+ "[tid:%i]: Read request from [sn:%i] for addr %08p\n",
+ inst->readTid(), inst->seqNum, inst->split2ndAddr);
+ break;
+
case InitiateReadData:
pkt_cmd = MemCmd::ReadReq;
@@ -231,7 +306,8 @@ CacheUnit::getRequest(DynInstPtr inst, int stage_num, int res_idx,
return new CacheRequest(this, inst, stage_num, id, slot_num,
sched_entry->cmd, 0, pkt_cmd,
- 0/*flags*/, this->cpu->readCpuId());
+ 0/*flags*/, this->cpu->readCpuId(),
+ inst->resSched.top()->idx);
}
void
@@ -242,7 +318,8 @@ CacheUnit::requestAgain(DynInstPtr inst, bool &service_request)
// Check to see if this instruction is requesting the same command
// or a different one
- if (cache_req->cmd != inst->resSched.top()->cmd) {
+ if (cache_req->cmd != inst->resSched.top()->cmd &&
+ cache_req->instIdx == inst->resSched.top()->idx) {
// If different, then update command in the request
cache_req->cmd = inst->resSched.top()->cmd;
DPRINTF(InOrderCachePort,
@@ -250,7 +327,7 @@ CacheUnit::requestAgain(DynInstPtr inst, bool &service_request)
"instruction\n ", inst->readTid(), inst->seqNum);
service_request = true;
- } else {
+ } else if (inst->resSched.top()->idx != CacheUnit::InitSecondSplitRead) {
// If same command, just check to see if memory access was completed
// but dont try to re-execute
DPRINTF(InOrderCachePort,
@@ -276,12 +353,25 @@ CacheUnit::doTLBAccess(DynInstPtr inst, CacheReqPtr cache_req, int acc_size,
cpu->readCpuId(), inst->readTid());
cache_req->memReq = inst->fetchMemReq;
} else {
- inst->dataMemReq = new Request(inst->readTid(), aligned_addr,
+ if (!cache_req->is2ndSplit()) {
+ inst->dataMemReq = new Request(cpu->asid[tid], aligned_addr,
acc_size, flags, inst->readPC(),
cpu->readCpuId(), inst->readTid());
cache_req->memReq = inst->dataMemReq;
+ } else {
+ assert(inst->splitInst);
+
+ inst->splitMemReq = new Request(cpu->asid[tid],
+ inst->split2ndAddr,
+ acc_size,
+ flags,
+ inst->readPC(),
+ cpu->readCpuId(),
+ tid);
+ cache_req->memReq = inst->splitMemReq;
+ }
}
-
+
cache_req->fault =
_tlb->translateAtomic(cache_req->memReq,
@@ -318,14 +408,94 @@ 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);
+ // The block size of our peer
+ unsigned blockSize = this->cachePort->peerBlockSize();
+
+ //The size of the data we're trying to read.
+ int dataSize = sizeof(T);
+
+ if (inst->split2ndAccess) {
+ dataSize = inst->split2ndSize;
+ cache_req->splitAccess = true;
+ cache_req->split2ndAccess = true;
+
+ DPRINTF(InOrderCachePort, "%i: sn[%i] Split Read Access (2 of 2) for (%#x, %#x).\n", curTick, inst->seqNum,
+ inst->getMemAddr(), inst->split2ndAddr);
+ }
+
+
+ //The address of the second part of this access if it needs to be split
+ //across a cache line boundary.
+ Addr secondAddr = roundDown(addr + dataSize - 1, blockSize);
+
+
+ if (secondAddr > addr && !inst->split2ndAccess) {
+ DPRINTF(InOrderCachePort, "%i: sn[%i] Split Read Access (1 of 2) for (%#x, %#x).\n", curTick, inst->seqNum,
+ addr, secondAddr);
+
+ // Save All "Total" Split Information
+ // ==============================
+ inst->splitInst = true;
+ inst->splitMemData = new uint8_t[dataSize];
+ inst->splitTotalSize = dataSize;
+
+
+ // Schedule Split Read/Complete for Instruction
+ // ==============================
+ int stage_num = cache_req->getStageNum();
+
+ int stage_pri = ThePipeline::getNextPriority(inst, stage_num);
+
+ inst->resSched.push(new ScheduleEntry(stage_num,
+ stage_pri,
+ cpu->resPool->getResIdx(DCache),
+ CacheUnit::InitSecondSplitRead,
+ 1)
+ );
+
+ inst->resSched.push(new ScheduleEntry(stage_num + 1,
+ 1/*stage_pri*/,
+ cpu->resPool->getResIdx(DCache),
+ CacheUnit::CompleteSecondSplitRead, 1)
+ );
+
+
+ // Split Information for First Access
+ // ==============================
+ dataSize = secondAddr - addr;
+ cache_req->splitAccess = true;
+
+ // Split Information for Second Access
+ // ==============================
+ inst->split2ndSize = addr + sizeof(T) - secondAddr;
+ inst->split2ndAddr = secondAddr;
+ inst->split2ndDataPtr = inst->splitMemData + dataSize;
+ inst->split2ndFlags = flags;
+ }
+
+ //cout << "h1" << endl;
+
+ doTLBAccess(inst, cache_req, dataSize, flags, TheISA::TLB::Read);
+
+ //cout << "h2" << endl;
if (cache_req->fault == NoFault) {
- cache_req->reqData = new uint8_t[acc_size];
- doCacheAccess(inst, NULL);
+ if (!cache_req->splitAccess) {
+ cache_req->reqData = new uint8_t[dataSize];
+ doCacheAccess(inst, NULL);
+ } else {
+ if (!inst->split2ndAccess) {
+ cache_req->reqData = inst->splitMemData;
+ } else {
+ cache_req->reqData = inst->split2ndDataPtr;
+ }
+
+ doCacheAccess(inst, NULL, cache_req);
+ }
}
+ //cout << "h3" << endl;
+
return cache_req->fault;
}
@@ -337,6 +507,20 @@ CacheUnit::write(DynInstPtr inst, T data, Addr addr, unsigned flags,
CacheReqPtr cache_req = dynamic_cast<CacheReqPtr>(findRequest(inst));
assert(cache_req);
+ // The block size of our peer
+ unsigned blockSize = this->cachePort->peerBlockSize();
+
+ //The size of the data we're trying to read.
+ int dataSize = sizeof(T);
+
+ //The address of the second part of this access if it needs to be split
+ //across a cache line boundary.
+ Addr secondAddr = roundDown(addr + dataSize - 1, blockSize);
+
+ if (secondAddr > addr) {
+ assert(0 && "Need Split Write Code!");
+ }
+
int acc_size = sizeof(T);
doTLBAccess(inst, cache_req, acc_size, flags, TheISA::TLB::Write);
@@ -364,6 +548,8 @@ CacheUnit::execute(int slot_num)
#if TRACING_ON
ThreadID tid = inst->readTid();
int seq_num = inst->seqNum;
+ std::string acc_type = "write";
+
#endif
cache_req->fault = NoFault;
@@ -395,10 +581,14 @@ CacheUnit::execute(int slot_num)
}
case InitiateReadData:
+#if TRACING_ON
+ acc_type = "read";
+#endif
case InitiateWriteData:
+
DPRINTF(InOrderCachePort,
- "[tid:%u]: Initiating data access to %s for addr. %08p\n",
- tid, name(), cache_req->inst->getMemAddr());
+ "[tid:%u]: [sn:%i] Initiating data %s access to %s for addr. %08p\n",
+ tid, inst->seqNum, acc_type, name(), cache_req->inst->getMemAddr());
inst->setCurResSlot(slot_num);
@@ -406,10 +596,31 @@ CacheUnit::execute(int slot_num)
inst->execute();
} else {
inst->initiateAcc();
+ //if (inst->splitAccess) {
+ // assert(0 && " Marked as spill inst");
+ //}
}
+
+ break;
+ case InitSecondSplitRead:
+ DPRINTF(InOrderCachePort,
+ "[tid:%u]: [sn:%i] Initiating split data read access to %s for addr. %08p\n",
+ tid, inst->seqNum, name(), cache_req->inst->split2ndAddr);
+ inst->split2ndAccess = true;
+ read(inst, inst->split2ndAddr, inst->split2ndData, inst->split2ndFlags);
break;
+ case InitSecondSplitWrite:
+ DPRINTF(InOrderCachePort,
+ "[tid:%u]: [sn:%i] Initiating split data write access to %s for addr. %08p\n",
+ tid, inst->seqNum, name(), cache_req->inst->getMemAddr());
+ assert(0);
+ inst->split2ndAccess = true;
+ //write(inst, inst->split2ndAddr, inst->split2ndData, inst->split2ndFlags);
+ break;
+
+
case CompleteFetch:
if (cache_req->isMemAccComplete()) {
DPRINTF(InOrderCachePort,
@@ -425,7 +636,7 @@ CacheUnit::execute(int slot_num)
cache_req->done();
} else {
DPRINTF(InOrderCachePort,
- "[tid:%i]: [sn:%i]: Unable to Complete Fetch Access\n",
+ "[tid:%i]: [sn:%i]: Unable to Complete Fetch Access\n",
tid, inst->seqNum);
DPRINTF(InOrderStall,
"STALL: [tid:%i]: Fetch miss from %08p\n",
@@ -454,6 +665,24 @@ CacheUnit::execute(int slot_num)
}
break;
+ case CompleteSecondSplitRead:
+ DPRINTF(InOrderCachePort,
+ "[tid:%i]: [sn:%i]: Trying to Complete Split Data Read Access\n",
+ tid, inst->seqNum);
+
+ if (cache_req->isMemAccComplete() ||
+ inst->isDataPrefetch() ||
+ inst->isInstPrefetch()) {
+ cache_req->setMemStall(false);
+ cache_req->done();
+ } else {
+ DPRINTF(InOrderStall, "STALL: [tid:%i]: Data miss from %08p\n",
+ tid, cache_req->inst->split2ndAddr);
+ cache_req->setCompleted(false);
+ cache_req->setMemStall(true);
+ }
+ break;
+
default:
fatal("Unrecognized command to %s", resName);
}
@@ -498,15 +727,21 @@ CacheUnit::writeHint(DynInstPtr inst)
// @TODO: Split into doCacheRead() and doCacheWrite()
Fault
-CacheUnit::doCacheAccess(DynInstPtr inst, uint64_t *write_res)
+CacheUnit::doCacheAccess(DynInstPtr inst, uint64_t *write_res, CacheReqPtr split_req)
{
Fault fault = NoFault;
#if TRACING_ON
ThreadID tid = inst->readTid();
#endif
- CacheReqPtr cache_req
- = dynamic_cast<CacheReqPtr>(reqMap[inst->getCurResSlot()]);
+ CacheReqPtr cache_req;
+
+ if (split_req == NULL) {
+ cache_req = dynamic_cast<CacheReqPtr>(reqMap[inst->getCurResSlot()]);
+ } else{
+ cache_req = split_req;
+ }
+
assert(cache_req);
// Check for LL/SC and if so change command
@@ -522,7 +757,7 @@ CacheUnit::doCacheAccess(DynInstPtr inst, uint64_t *write_res)
}
cache_req->dataPkt = new CacheReqPacket(cache_req, cache_req->pktCmd,
- Packet::Broadcast);
+ Packet::Broadcast, cache_req->instIdx);
if (cache_req->dataPkt->isRead()) {
cache_req->dataPkt->dataStatic(cache_req->reqData);
@@ -615,7 +850,16 @@ CacheUnit::processCacheCompletion(PacketPtr pkt)
// Cast to correct request type
CacheRequest *cache_req = dynamic_cast<CacheReqPtr>(
- findRequest(cache_pkt->cacheReq->getInst()));
+ findSplitRequest(cache_pkt->cacheReq->getInst(), cache_pkt->instIdx));
+
+ if (!cache_req) {
+ warn(
+ "[tid:%u]: [sn:%i]: Can't find slot for cache access to addr. %08p\n",
+ cache_pkt->cacheReq->getInst()->readTid(),
+ cache_pkt->cacheReq->getInst()->seqNum,
+ cache_pkt->cacheReq->getInst()->getMemAddr());
+ }
+
assert(cache_req);
@@ -661,9 +905,27 @@ CacheUnit::processCacheCompletion(PacketPtr pkt)
DPRINTF(InOrderCachePort,
"[tid:%u]: [sn:%i]: Processing cache access\n",
tid, inst->seqNum);
-
- inst->completeAcc(pkt);
-
+
+ if (inst->splitInst) {
+ inst->splitFinishCnt++;
+
+ if (inst->splitFinishCnt == 2) {
+
+ cache_req->memReq->setVirt(0/*inst->tid*/,
+ inst->getMemAddr(),
+ inst->splitTotalSize,
+ 0,
+ 0);
+
+ Packet split_pkt(cache_req->memReq, cache_req->pktCmd,
+ Packet::Broadcast);
+ split_pkt.dataStatic(inst->splitMemData);
+ inst->completeAcc(&split_pkt);
+ }
+ } else {
+ inst->completeAcc(pkt);
+ }
+
if (inst->isLoad()) {
assert(cache_pkt->isRead());
diff --git a/src/cpu/inorder/resources/cache_unit.hh b/src/cpu/inorder/resources/cache_unit.hh
index 50cb47519..715ebd878 100644
--- a/src/cpu/inorder/resources/cache_unit.hh
+++ b/src/cpu/inorder/resources/cache_unit.hh
@@ -72,7 +72,10 @@ class CacheUnit : public Resource
CompleteWriteData,
Fetch,
ReadData,
- WriteData
+ WriteData,
+ InitSecondSplitRead,
+ InitSecondSplitWrite,
+ CompleteSecondSplitRead
};
public:
@@ -124,6 +127,9 @@ class CacheUnit : public Resource
int res_idx, int slot_num,
unsigned cmd);
+ ResReqPtr findRequest(DynInstPtr inst);
+ ResReqPtr findSplitRequest(DynInstPtr inst, int idx);
+
void requestAgain(DynInstPtr inst, bool &try_request);
int getSlot(DynInstPtr inst);
@@ -155,7 +161,7 @@ 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);
@@ -169,7 +175,7 @@ class CacheUnit : public Resource
/** Read/Write on behalf of an instruction.
* curResSlot needs to be a valid value in instruction.
*/
- Fault doCacheAccess(DynInstPtr inst, uint64_t *write_result=NULL);
+ Fault doCacheAccess(DynInstPtr inst, uint64_t *write_result=NULL, CacheReqPtr split_req=NULL);
void prefetch(DynInstPtr inst);
@@ -237,17 +243,18 @@ class CacheRequest : public ResourceRequest
public:
CacheRequest(CacheUnit *cres, DynInstPtr inst, int stage_num, int res_idx,
int slot_num, unsigned cmd, int req_size,
- MemCmd::Command pkt_cmd, unsigned flags, int cpu_id)
+ MemCmd::Command pkt_cmd, unsigned flags, int cpu_id, int idx)
: ResourceRequest(cres, inst, stage_num, res_idx, slot_num, cmd),
pktCmd(pkt_cmd), memReq(NULL), reqData(NULL), dataPkt(NULL),
retryPkt(NULL), memAccComplete(false), memAccPending(false),
- tlbStall(false)
+ tlbStall(false), splitAccess(false), splitAccessNum(-1),
+ split2ndAccess(false), instIdx(idx)
{ }
virtual ~CacheRequest()
{
- if (reqData) {
+ if (reqData && !splitAccess) {
delete [] reqData;
}
}
@@ -261,6 +268,11 @@ class CacheRequest : public ResourceRequest
memAccComplete = completed;
}
+ bool is2ndSplit()
+ {
+ return split2ndAccess;
+ }
+
bool isMemAccComplete() { return memAccComplete; }
void setMemAccPending(bool pending = true) { memAccPending = pending; }
@@ -276,19 +288,27 @@ class CacheRequest : public ResourceRequest
bool memAccComplete;
bool memAccPending;
bool tlbStall;
+
+ bool splitAccess;
+ int splitAccessNum;
+ bool split2ndAccess;
+ int instIdx;
+
};
class CacheReqPacket : public Packet
{
public:
CacheReqPacket(CacheRequest *_req,
- Command _cmd, short _dest)
- : Packet(_req->memReq, _cmd, _dest), cacheReq(_req)
+ Command _cmd, short _dest, int _idx = 0)
+ : Packet(_req->memReq, _cmd, _dest), cacheReq(_req), instIdx(_idx)
{
}
CacheRequest *cacheReq;
+ int instIdx;
+
};
#endif //__CPU_CACHE_UNIT_HH__