inorder: implement split stores
This commit is contained in:
parent
6939482c49
commit
be6724f7e7
4 changed files with 117 additions and 31 deletions
|
@ -112,6 +112,7 @@ InOrderDynInst::initVars()
|
||||||
fetchMemReq = NULL;
|
fetchMemReq = NULL;
|
||||||
dataMemReq = NULL;
|
dataMemReq = NULL;
|
||||||
splitMemData = NULL;
|
splitMemData = NULL;
|
||||||
|
split2ndAddr = 0;
|
||||||
split2ndAccess = false;
|
split2ndAccess = false;
|
||||||
splitInst = false;
|
splitInst = false;
|
||||||
splitFinishCnt = 0;
|
splitFinishCnt = 0;
|
||||||
|
@ -192,7 +193,7 @@ InOrderDynInst::~InOrderDynInst()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (splitMemData) {
|
if (splitMemData) {
|
||||||
delete splitMemData;
|
delete [] splitMemData;
|
||||||
}
|
}
|
||||||
|
|
||||||
fault = NoFault;
|
fault = NoFault;
|
||||||
|
|
|
@ -341,7 +341,7 @@ class InOrderDynInst : public FastAlloc, public RefCounted
|
||||||
unsigned split2ndFlags;
|
unsigned split2ndFlags;
|
||||||
bool splitInst;
|
bool splitInst;
|
||||||
int splitFinishCnt;
|
int splitFinishCnt;
|
||||||
|
uint64_t *split2ndStoreDataPtr;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
|
|
|
@ -283,6 +283,14 @@ CacheUnit::getRequest(DynInstPtr inst, int stage_num, int res_idx,
|
||||||
inst->readTid(), inst->seqNum, inst->getMemAddr());
|
inst->readTid(), inst->seqNum, inst->getMemAddr());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case InitSecondSplitWrite:
|
||||||
|
pkt_cmd = MemCmd::WriteReq;
|
||||||
|
|
||||||
|
DPRINTF(InOrderCachePort,
|
||||||
|
"[tid:%i]: Write request from [sn:%i] for addr %08p\n",
|
||||||
|
inst->readTid(), inst->seqNum, inst->split2ndAddr);
|
||||||
|
break;
|
||||||
|
|
||||||
case InitiateWriteData:
|
case InitiateWriteData:
|
||||||
pkt_cmd = MemCmd::WriteReq;
|
pkt_cmd = MemCmd::WriteReq;
|
||||||
|
|
||||||
|
@ -327,7 +335,8 @@ CacheUnit::requestAgain(DynInstPtr inst, bool &service_request)
|
||||||
"instruction\n ", inst->readTid(), inst->seqNum);
|
"instruction\n ", inst->readTid(), inst->seqNum);
|
||||||
|
|
||||||
service_request = true;
|
service_request = true;
|
||||||
} else if (inst->resSched.top()->idx != CacheUnit::InitSecondSplitRead) {
|
} else if (inst->resSched.top()->idx != CacheUnit::InitSecondSplitRead &&
|
||||||
|
inst->resSched.top()->idx != CacheUnit::InitSecondSplitWrite) {
|
||||||
// If same command, just check to see if memory access was completed
|
// If same command, just check to see if memory access was completed
|
||||||
// but dont try to re-execute
|
// but dont try to re-execute
|
||||||
DPRINTF(InOrderCachePort,
|
DPRINTF(InOrderCachePort,
|
||||||
|
@ -406,7 +415,7 @@ Fault
|
||||||
CacheUnit::read(DynInstPtr inst, Addr addr, T &data, unsigned flags)
|
CacheUnit::read(DynInstPtr inst, Addr addr, T &data, unsigned flags)
|
||||||
{
|
{
|
||||||
CacheReqPtr cache_req = dynamic_cast<CacheReqPtr>(findRequest(inst));
|
CacheReqPtr cache_req = dynamic_cast<CacheReqPtr>(findRequest(inst));
|
||||||
assert(cache_req);
|
assert(cache_req && "Can't Find Instruction for Read!");
|
||||||
|
|
||||||
// The block size of our peer
|
// The block size of our peer
|
||||||
unsigned blockSize = this->cachePort->peerBlockSize();
|
unsigned blockSize = this->cachePort->peerBlockSize();
|
||||||
|
@ -456,7 +465,8 @@ CacheUnit::read(DynInstPtr inst, Addr addr, T &data, unsigned flags)
|
||||||
inst->resSched.push(new ScheduleEntry(stage_num + 1,
|
inst->resSched.push(new ScheduleEntry(stage_num + 1,
|
||||||
1/*stage_pri*/,
|
1/*stage_pri*/,
|
||||||
cpu->resPool->getResIdx(DCache),
|
cpu->resPool->getResIdx(DCache),
|
||||||
CacheUnit::CompleteSecondSplitRead, 1)
|
CacheUnit::CompleteSecondSplitRead,
|
||||||
|
1)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
@ -473,12 +483,8 @@ CacheUnit::read(DynInstPtr inst, Addr addr, T &data, unsigned flags)
|
||||||
inst->split2ndFlags = flags;
|
inst->split2ndFlags = flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
//cout << "h1" << endl;
|
|
||||||
|
|
||||||
doTLBAccess(inst, cache_req, dataSize, flags, TheISA::TLB::Read);
|
doTLBAccess(inst, cache_req, dataSize, flags, TheISA::TLB::Read);
|
||||||
|
|
||||||
//cout << "h2" << endl;
|
|
||||||
|
|
||||||
if (cache_req->fault == NoFault) {
|
if (cache_req->fault == NoFault) {
|
||||||
if (!cache_req->splitAccess) {
|
if (!cache_req->splitAccess) {
|
||||||
cache_req->reqData = new uint8_t[dataSize];
|
cache_req->reqData = new uint8_t[dataSize];
|
||||||
|
@ -494,8 +500,6 @@ CacheUnit::read(DynInstPtr inst, Addr addr, T &data, unsigned flags)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//cout << "h3" << endl;
|
|
||||||
|
|
||||||
return cache_req->fault;
|
return cache_req->fault;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -505,7 +509,7 @@ CacheUnit::write(DynInstPtr inst, T data, Addr addr, unsigned flags,
|
||||||
uint64_t *write_res)
|
uint64_t *write_res)
|
||||||
{
|
{
|
||||||
CacheReqPtr cache_req = dynamic_cast<CacheReqPtr>(findRequest(inst));
|
CacheReqPtr cache_req = dynamic_cast<CacheReqPtr>(findRequest(inst));
|
||||||
assert(cache_req);
|
assert(cache_req && "Can't Find Instruction for Write!");
|
||||||
|
|
||||||
// The block size of our peer
|
// The block size of our peer
|
||||||
unsigned blockSize = this->cachePort->peerBlockSize();
|
unsigned blockSize = this->cachePort->peerBlockSize();
|
||||||
|
@ -513,22 +517,75 @@ CacheUnit::write(DynInstPtr inst, T data, Addr addr, unsigned flags,
|
||||||
//The size of the data we're trying to read.
|
//The size of the data we're trying to read.
|
||||||
int dataSize = sizeof(T);
|
int dataSize = sizeof(T);
|
||||||
|
|
||||||
|
if (inst->split2ndAccess) {
|
||||||
|
dataSize = inst->split2ndSize;
|
||||||
|
cache_req->splitAccess = true;
|
||||||
|
cache_req->split2ndAccess = true;
|
||||||
|
|
||||||
|
DPRINTF(InOrderCachePort, "%i: sn[%i] Split Write 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
|
//The address of the second part of this access if it needs to be split
|
||||||
//across a cache line boundary.
|
//across a cache line boundary.
|
||||||
Addr secondAddr = roundDown(addr + dataSize - 1, blockSize);
|
Addr secondAddr = roundDown(addr + dataSize - 1, blockSize);
|
||||||
|
|
||||||
if (secondAddr > addr) {
|
if (secondAddr > addr && !inst->split2ndAccess) {
|
||||||
assert(0 && "Need Split Write Code!");
|
DPRINTF(InOrderCachePort, "%i: sn[%i] Split Write Access (1 of 2) for (%#x, %#x).\n", curTick, inst->seqNum,
|
||||||
}
|
addr, secondAddr);
|
||||||
|
|
||||||
int acc_size = sizeof(T);
|
// Save All "Total" Split Information
|
||||||
doTLBAccess(inst, cache_req, acc_size, flags, TheISA::TLB::Write);
|
// ==============================
|
||||||
|
inst->splitInst = true;
|
||||||
|
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::InitSecondSplitWrite,
|
||||||
|
1)
|
||||||
|
);
|
||||||
|
|
||||||
|
inst->resSched.push(new ScheduleEntry(stage_num + 1,
|
||||||
|
1/*stage_pri*/,
|
||||||
|
cpu->resPool->getResIdx(DCache),
|
||||||
|
CacheUnit::CompleteSecondSplitWrite,
|
||||||
|
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->split2ndStoreDataPtr = &cache_req->inst->storeData;
|
||||||
|
inst->split2ndStoreDataPtr += dataSize;
|
||||||
|
inst->split2ndFlags = flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
doTLBAccess(inst, cache_req, dataSize, flags, TheISA::TLB::Write);
|
||||||
|
|
||||||
if (cache_req->fault == NoFault) {
|
if (cache_req->fault == NoFault) {
|
||||||
cache_req->reqData = new uint8_t[acc_size];
|
if (!cache_req->splitAccess) {
|
||||||
doCacheAccess(inst, write_res);
|
// Remove this line since storeData is saved in INST?
|
||||||
|
cache_req->reqData = new uint8_t[dataSize];
|
||||||
|
doCacheAccess(inst, write_res);
|
||||||
|
} else {
|
||||||
|
doCacheAccess(inst, write_res, cache_req);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return cache_req->fault;
|
return cache_req->fault;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -596,9 +653,6 @@ CacheUnit::execute(int slot_num)
|
||||||
inst->execute();
|
inst->execute();
|
||||||
} else {
|
} else {
|
||||||
inst->initiateAcc();
|
inst->initiateAcc();
|
||||||
//if (inst->splitAccess) {
|
|
||||||
// assert(0 && " Marked as spill inst");
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -608,6 +662,7 @@ CacheUnit::execute(int slot_num)
|
||||||
"[tid:%u]: [sn:%i] Initiating split data read access to %s for addr. %08p\n",
|
"[tid:%u]: [sn:%i] Initiating split data read access to %s for addr. %08p\n",
|
||||||
tid, inst->seqNum, name(), cache_req->inst->split2ndAddr);
|
tid, inst->seqNum, name(), cache_req->inst->split2ndAddr);
|
||||||
inst->split2ndAccess = true;
|
inst->split2ndAccess = true;
|
||||||
|
assert(inst->split2ndAddr != 0);
|
||||||
read(inst, inst->split2ndAddr, inst->split2ndData, inst->split2ndFlags);
|
read(inst, inst->split2ndAddr, inst->split2ndData, inst->split2ndFlags);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -615,9 +670,10 @@ CacheUnit::execute(int slot_num)
|
||||||
DPRINTF(InOrderCachePort,
|
DPRINTF(InOrderCachePort,
|
||||||
"[tid:%u]: [sn:%i] Initiating split data write access to %s for addr. %08p\n",
|
"[tid:%u]: [sn:%i] Initiating split data write access to %s for addr. %08p\n",
|
||||||
tid, inst->seqNum, name(), cache_req->inst->getMemAddr());
|
tid, inst->seqNum, name(), cache_req->inst->getMemAddr());
|
||||||
assert(0);
|
|
||||||
inst->split2ndAccess = true;
|
inst->split2ndAccess = true;
|
||||||
//write(inst, inst->split2ndAddr, inst->split2ndData, inst->split2ndFlags);
|
assert(inst->split2ndAddr != 0);
|
||||||
|
write(inst, inst->split2ndAddr, inst->split2ndData, inst->split2ndFlags, NULL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
@ -682,6 +738,24 @@ CacheUnit::execute(int slot_num)
|
||||||
cache_req->setMemStall(true);
|
cache_req->setMemStall(true);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case CompleteSecondSplitWrite:
|
||||||
|
DPRINTF(InOrderCachePort,
|
||||||
|
"[tid:%i]: [sn:%i]: Trying to Complete Split Data Write 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:
|
default:
|
||||||
fatal("Unrecognized command to %s", resName);
|
fatal("Unrecognized command to %s", resName);
|
||||||
|
@ -761,9 +835,13 @@ CacheUnit::doCacheAccess(DynInstPtr inst, uint64_t *write_res, CacheReqPtr split
|
||||||
|
|
||||||
if (cache_req->dataPkt->isRead()) {
|
if (cache_req->dataPkt->isRead()) {
|
||||||
cache_req->dataPkt->dataStatic(cache_req->reqData);
|
cache_req->dataPkt->dataStatic(cache_req->reqData);
|
||||||
} else if (cache_req->dataPkt->isWrite()) {
|
} else if (cache_req->dataPkt->isWrite()) {
|
||||||
cache_req->dataPkt->dataStatic(&cache_req->inst->storeData);
|
if (inst->split2ndAccess) {
|
||||||
|
cache_req->dataPkt->dataStatic(inst->split2ndStoreDataPtr);
|
||||||
|
} else {
|
||||||
|
cache_req->dataPkt->dataStatic(&cache_req->inst->storeData);
|
||||||
|
}
|
||||||
|
|
||||||
if (cache_req->memReq->isCondSwap()) {
|
if (cache_req->memReq->isCondSwap()) {
|
||||||
assert(write_res);
|
assert(write_res);
|
||||||
cache_req->memReq->setExtraData(*write_res);
|
cache_req->memReq->setExtraData(*write_res);
|
||||||
|
@ -910,7 +988,6 @@ CacheUnit::processCacheCompletion(PacketPtr pkt)
|
||||||
inst->splitFinishCnt++;
|
inst->splitFinishCnt++;
|
||||||
|
|
||||||
if (inst->splitFinishCnt == 2) {
|
if (inst->splitFinishCnt == 2) {
|
||||||
|
|
||||||
cache_req->memReq->setVirt(0/*inst->tid*/,
|
cache_req->memReq->setVirt(0/*inst->tid*/,
|
||||||
inst->getMemAddr(),
|
inst->getMemAddr(),
|
||||||
inst->splitTotalSize,
|
inst->splitTotalSize,
|
||||||
|
@ -919,7 +996,14 @@ CacheUnit::processCacheCompletion(PacketPtr pkt)
|
||||||
|
|
||||||
Packet split_pkt(cache_req->memReq, cache_req->pktCmd,
|
Packet split_pkt(cache_req->memReq, cache_req->pktCmd,
|
||||||
Packet::Broadcast);
|
Packet::Broadcast);
|
||||||
split_pkt.dataStatic(inst->splitMemData);
|
|
||||||
|
|
||||||
|
if (inst->isLoad()) {
|
||||||
|
split_pkt.dataStatic(inst->splitMemData);
|
||||||
|
} else {
|
||||||
|
split_pkt.dataStatic(&inst->storeData);
|
||||||
|
}
|
||||||
|
|
||||||
inst->completeAcc(&split_pkt);
|
inst->completeAcc(&split_pkt);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -75,7 +75,8 @@ class CacheUnit : public Resource
|
||||||
WriteData,
|
WriteData,
|
||||||
InitSecondSplitRead,
|
InitSecondSplitRead,
|
||||||
InitSecondSplitWrite,
|
InitSecondSplitWrite,
|
||||||
CompleteSecondSplitRead
|
CompleteSecondSplitRead,
|
||||||
|
CompleteSecondSplitWrite
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
Loading…
Reference in a new issue