inorder: bug in mdu
segfault was caused by squashed multiply thats in the process of an event. use isProcessing flag to handle this and cleanup the MDU code
This commit is contained in:
parent
4c979f9325
commit
c95fe261ab
5 changed files with 78 additions and 55 deletions
|
@ -297,16 +297,18 @@ Resource::setupSquash(DynInstPtr inst, int stage_num, ThreadID tid)
|
||||||
cpu->resPool->scheduleEvent(
|
cpu->resPool->scheduleEvent(
|
||||||
(InOrderCPU::CPUEventType)ResourcePool::SquashAll, inst, 0);
|
(InOrderCPU::CPUEventType)ResourcePool::SquashAll, inst, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Resource::squash(DynInstPtr inst, int stage_num, InstSeqNum squash_seq_num,
|
Resource::squash(DynInstPtr inst, int stage_num, InstSeqNum squash_seq_num,
|
||||||
ThreadID tid)
|
ThreadID tid)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < width; i++) {
|
for (int i = 0; i < width; i++) {
|
||||||
ResReqPtr req_ptr = reqs[i];
|
ResReqPtr req_ptr = reqs[i];
|
||||||
|
DynInstPtr inst = req_ptr->getInst();
|
||||||
|
|
||||||
if (req_ptr->valid &&
|
if (req_ptr->valid &&
|
||||||
req_ptr->getInst()->readTid() == tid &&
|
inst->readTid() == tid &&
|
||||||
req_ptr->getInst()->seqNum > squash_seq_num) {
|
inst->seqNum > squash_seq_num) {
|
||||||
|
|
||||||
DPRINTF(Resource, "[tid:%i]: Squashing [sn:%i].\n",
|
DPRINTF(Resource, "[tid:%i]: Squashing [sn:%i].\n",
|
||||||
req_ptr->getInst()->readTid(),
|
req_ptr->getInst()->readTid(),
|
||||||
|
|
|
@ -389,7 +389,7 @@ class ResourceRequest
|
||||||
|
|
||||||
/** Get/Set IsProcessing variables */
|
/** Get/Set IsProcessing variables */
|
||||||
bool isProcessing() { return processing; }
|
bool isProcessing() { return processing; }
|
||||||
void setProcessing() { processing = true; }
|
void setProcessing(bool cond = true) { processing = cond; }
|
||||||
|
|
||||||
/** Get/Set IsWaiting variables */
|
/** Get/Set IsWaiting variables */
|
||||||
bool isMemStall() { return memStall; }
|
bool isMemStall() { return memStall; }
|
||||||
|
|
|
@ -79,7 +79,10 @@ ResourcePool::ResourcePool(InOrderCPU *_cpu, ThePipeline::Params *params)
|
||||||
stage_width, 0, _cpu, params));
|
stage_width, 0, _cpu, params));
|
||||||
|
|
||||||
resources.push_back(new MultDivUnit("mult_div_unit", MDU,
|
resources.push_back(new MultDivUnit("mult_div_unit", MDU,
|
||||||
stage_width * 2, 0, _cpu, params));
|
stage_width * 2,
|
||||||
|
0,
|
||||||
|
_cpu,
|
||||||
|
params));
|
||||||
|
|
||||||
memObjects.push_back(DCache);
|
memObjects.push_back(DCache);
|
||||||
resources.push_back(new CacheUnit("dcache_port", DCache,
|
resources.push_back(new CacheUnit("dcache_port", DCache,
|
||||||
|
|
|
@ -86,25 +86,6 @@ MultDivUnit::init()
|
||||||
initSlots();
|
initSlots();
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
MultDivUnit::findSlot(DynInstPtr inst)
|
|
||||||
{
|
|
||||||
DPRINTF(InOrderMDU, "Finding slot for inst:%i\n | slots-free:%i | "
|
|
||||||
"slots-used:%i\n", inst->seqNum, slotsAvail(), slotsInUse());
|
|
||||||
|
|
||||||
return Resource::findSlot(inst);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
MultDivUnit::freeSlot(int slot_idx)
|
|
||||||
{
|
|
||||||
DPRINTF(InOrderMDU, "Freeing slot for inst:%i\n | slots-free:%i | "
|
|
||||||
"slots-used:%i\n", reqs[slot_idx]->getInst()->seqNum,
|
|
||||||
slotsAvail(), slotsInUse());
|
|
||||||
|
|
||||||
Resource::freeSlot(slot_idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
//@TODO: Should we push this behavior into base-class to generically
|
//@TODO: Should we push this behavior into base-class to generically
|
||||||
// accomodate all multicyle resources?
|
// accomodate all multicyle resources?
|
||||||
void
|
void
|
||||||
|
@ -124,7 +105,7 @@ MultDivUnit::requestAgain(DynInstPtr inst, bool &service_request)
|
||||||
"[tid:%i]: [sn:%i]: Updating the command for this "
|
"[tid:%i]: [sn:%i]: Updating the command for this "
|
||||||
"instruction\n", inst->readTid(), inst->seqNum);
|
"instruction\n", inst->readTid(), inst->seqNum);
|
||||||
} else {
|
} else {
|
||||||
// If same command, just check to see if memory access was completed
|
// If same command, just check to see if access was completed
|
||||||
// but dont try to re-execute
|
// but dont try to re-execute
|
||||||
DPRINTF(InOrderMDU,
|
DPRINTF(InOrderMDU,
|
||||||
"[tid:%i]: [sn:%i]: requesting this resource again\n",
|
"[tid:%i]: [sn:%i]: requesting this resource again\n",
|
||||||
|
@ -212,41 +193,47 @@ MultDivUnit::execute(int slot_num)
|
||||||
ResourceRequest* mult_div_req = reqs[slot_num];
|
ResourceRequest* mult_div_req = reqs[slot_num];
|
||||||
DynInstPtr inst = reqs[slot_num]->inst;
|
DynInstPtr inst = reqs[slot_num]->inst;
|
||||||
|
|
||||||
|
DPRINTF(InOrderMDU, "Executing [sn:%i] ...\n", slot_num);
|
||||||
|
|
||||||
switch (mult_div_req->cmd)
|
switch (mult_div_req->cmd)
|
||||||
{
|
{
|
||||||
case StartMultDiv:
|
case StartMultDiv:
|
||||||
DPRINTF(InOrderMDU, "Start MDU called ...\n");
|
{
|
||||||
|
DPRINTF(InOrderMDU, "Start MDU called ...\n");
|
||||||
|
|
||||||
if (inst->opClass() == IntMultOp) {
|
OpClass op_class = inst->opClass();
|
||||||
scheduleEvent(slot_num, multLatency);
|
if (op_class == IntMultOp) {
|
||||||
} else if (inst->opClass() == IntDivOp) {
|
scheduleEvent(slot_num, multLatency);
|
||||||
int op_size = getDivOpSize(inst);
|
} else if (op_class == IntDivOp) {
|
||||||
|
int op_size = getDivOpSize(inst);
|
||||||
|
|
||||||
switch (op_size)
|
switch (op_size)
|
||||||
{
|
{
|
||||||
case 8:
|
case 8:
|
||||||
scheduleEvent(slot_num, div8Latency);
|
scheduleEvent(slot_num, div8Latency);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 16:
|
case 16:
|
||||||
scheduleEvent(slot_num, div16Latency);
|
scheduleEvent(slot_num, div16Latency);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 24:
|
case 24:
|
||||||
scheduleEvent(slot_num, div24Latency);
|
scheduleEvent(slot_num, div24Latency);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 32:
|
case 32:
|
||||||
scheduleEvent(slot_num, div32Latency);
|
scheduleEvent(slot_num, div32Latency);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
lastDivSize = op_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
lastDivSize = op_size;
|
// Allow to pass through to next stage while
|
||||||
|
// event processes
|
||||||
|
mult_div_req->setProcessing();
|
||||||
|
mult_div_req->setCompleted();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allow to pass through to next stage while
|
|
||||||
// event processes
|
|
||||||
mult_div_req->setCompleted();
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MultDiv:
|
case MultDiv:
|
||||||
|
@ -264,7 +251,7 @@ MultDivUnit::execute(int slot_num)
|
||||||
// counting down the time
|
// counting down the time
|
||||||
{
|
{
|
||||||
DPRINTF(InOrderMDU, "End MDU called ...\n");
|
DPRINTF(InOrderMDU, "End MDU called ...\n");
|
||||||
if (mult_div_req->getInst()->isExecuted()) {
|
if (!mult_div_req->isProcessing()) {
|
||||||
DPRINTF(InOrderMDU, "Mult/Div finished.\n");
|
DPRINTF(InOrderMDU, "Mult/Div finished.\n");
|
||||||
mult_div_req->done();
|
mult_div_req->done();
|
||||||
} else {
|
} else {
|
||||||
|
@ -295,7 +282,6 @@ MultDivUnit::exeMulDiv(int slot_num)
|
||||||
|
|
||||||
if (inst->fault == NoFault) {
|
if (inst->fault == NoFault) {
|
||||||
inst->setExecuted();
|
inst->setExecuted();
|
||||||
mult_div_req->setCompleted();
|
|
||||||
|
|
||||||
DPRINTF(InOrderMDU, "[tid:%i]: The result of execution is 0x%x.\n",
|
DPRINTF(InOrderMDU, "[tid:%i]: The result of execution is 0x%x.\n",
|
||||||
inst->readTid(), inst->readIntResult(0));
|
inst->readTid(), inst->readIntResult(0));
|
||||||
|
@ -303,8 +289,40 @@ MultDivUnit::exeMulDiv(int slot_num)
|
||||||
DPRINTF(InOrderMDU, "[tid:%i]: [sn:%i]: had a %s "
|
DPRINTF(InOrderMDU, "[tid:%i]: [sn:%i]: had a %s "
|
||||||
"fault.\n", inst->readTid(), inst->seqNum, inst->fault->name());
|
"fault.\n", inst->readTid(), inst->seqNum, inst->fault->name());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mult_div_req->setProcessing(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MultDivUnit::squash(DynInstPtr inst, int stage_num, InstSeqNum squash_seq_num,
|
||||||
|
ThreadID tid)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < width; i++) {
|
||||||
|
ResReqPtr req_ptr = reqs[i];
|
||||||
|
DynInstPtr inst = req_ptr->getInst();
|
||||||
|
|
||||||
|
if (req_ptr->valid &&
|
||||||
|
inst->readTid() == tid &&
|
||||||
|
inst->seqNum > squash_seq_num) {
|
||||||
|
|
||||||
|
DPRINTF(InOrderMDU, "[tid:%i]: Squashing [sn:%i].\n",
|
||||||
|
req_ptr->getInst()->readTid(),
|
||||||
|
req_ptr->getInst()->seqNum);
|
||||||
|
|
||||||
|
req_ptr->setSquashed();
|
||||||
|
|
||||||
|
int req_slot_num = req_ptr->getSlot();
|
||||||
|
|
||||||
|
if (req_ptr->isProcessing())
|
||||||
|
DPRINTF(InOrderMDU, "[tid:%i]: Squashed [sn:%i], but "
|
||||||
|
"waiting for MDU operation to complete.\n",
|
||||||
|
req_ptr->getInst()->readTid(),
|
||||||
|
req_ptr->getInst()->seqNum);
|
||||||
|
else
|
||||||
|
freeSlot(req_slot_num);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MDUEvent::MDUEvent()
|
MDUEvent::MDUEvent()
|
||||||
: ResourceEvent()
|
: ResourceEvent()
|
||||||
|
@ -319,7 +337,8 @@ MDUEvent::process()
|
||||||
|
|
||||||
ResourceRequest* mult_div_req = resource->reqs[slotIdx];
|
ResourceRequest* mult_div_req = resource->reqs[slotIdx];
|
||||||
|
|
||||||
mult_div_req->done();
|
if (mult_div_req->isSquashed())
|
||||||
|
mdu_res->freeSlot(slotIdx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -65,10 +65,6 @@ class MultDivUnit : public Resource {
|
||||||
*/
|
*/
|
||||||
int getSlot(DynInstPtr inst);
|
int getSlot(DynInstPtr inst);
|
||||||
|
|
||||||
int findSlot(DynInstPtr inst);
|
|
||||||
|
|
||||||
void freeSlot(int slot_idx);
|
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
|
|
||||||
/** Get Operand Size For A Division Operation */
|
/** Get Operand Size For A Division Operation */
|
||||||
|
@ -84,6 +80,9 @@ class MultDivUnit : public Resource {
|
||||||
|
|
||||||
void requestAgain(DynInstPtr inst, bool &try_request);
|
void requestAgain(DynInstPtr inst, bool &try_request);
|
||||||
|
|
||||||
|
void squash(DynInstPtr inst, int stage_num, InstSeqNum squash_seq_num,
|
||||||
|
ThreadID tid);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/** Latency & Repeat Rate for Multiply Insts */
|
/** Latency & Repeat Rate for Multiply Insts */
|
||||||
unsigned multRepeatRate;
|
unsigned multRepeatRate;
|
||||||
|
|
Loading…
Reference in a new issue