summaryrefslogtreecommitdiff
path: root/src/cpu
diff options
context:
space:
mode:
authorKorey Sewell <ksewell@umich.edu>2011-06-19 21:43:38 -0400
committerKorey Sewell <ksewell@umich.edu>2011-06-19 21:43:38 -0400
commitc95fe261abab85bee247737a3d171378689891e0 (patch)
tree75569e5baa06a7bd25870505a48a3ddf24916475 /src/cpu
parent4c979f9325f0c82f3284ce0fb0cc118d77268cb5 (diff)
downloadgem5-c95fe261abab85bee247737a3d171378689891e0.tar.xz
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
Diffstat (limited to 'src/cpu')
-rw-r--r--src/cpu/inorder/resource.cc6
-rw-r--r--src/cpu/inorder/resource.hh2
-rw-r--r--src/cpu/inorder/resource_pool.cc5
-rw-r--r--src/cpu/inorder/resources/mult_div_unit.cc123
-rw-r--r--src/cpu/inorder/resources/mult_div_unit.hh7
5 files changed, 83 insertions, 60 deletions
diff --git a/src/cpu/inorder/resource.cc b/src/cpu/inorder/resource.cc
index 8d3f3daac..a21536676 100644
--- a/src/cpu/inorder/resource.cc
+++ b/src/cpu/inorder/resource.cc
@@ -297,16 +297,18 @@ Resource::setupSquash(DynInstPtr inst, int stage_num, ThreadID tid)
cpu->resPool->scheduleEvent(
(InOrderCPU::CPUEventType)ResourcePool::SquashAll, inst, 0);
}
+
void
Resource::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 &&
- req_ptr->getInst()->readTid() == tid &&
- req_ptr->getInst()->seqNum > squash_seq_num) {
+ inst->readTid() == tid &&
+ inst->seqNum > squash_seq_num) {
DPRINTF(Resource, "[tid:%i]: Squashing [sn:%i].\n",
req_ptr->getInst()->readTid(),
diff --git a/src/cpu/inorder/resource.hh b/src/cpu/inorder/resource.hh
index fcf01065a..91d144a64 100644
--- a/src/cpu/inorder/resource.hh
+++ b/src/cpu/inorder/resource.hh
@@ -389,7 +389,7 @@ class ResourceRequest
/** Get/Set IsProcessing variables */
bool isProcessing() { return processing; }
- void setProcessing() { processing = true; }
+ void setProcessing(bool cond = true) { processing = cond; }
/** Get/Set IsWaiting variables */
bool isMemStall() { return memStall; }
diff --git a/src/cpu/inorder/resource_pool.cc b/src/cpu/inorder/resource_pool.cc
index a8a26f51e..0e89a7650 100644
--- a/src/cpu/inorder/resource_pool.cc
+++ b/src/cpu/inorder/resource_pool.cc
@@ -79,7 +79,10 @@ ResourcePool::ResourcePool(InOrderCPU *_cpu, ThePipeline::Params *params)
stage_width, 0, _cpu, params));
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);
resources.push_back(new CacheUnit("dcache_port", DCache,
diff --git a/src/cpu/inorder/resources/mult_div_unit.cc b/src/cpu/inorder/resources/mult_div_unit.cc
index 49df901e3..fc27276d5 100644
--- a/src/cpu/inorder/resources/mult_div_unit.cc
+++ b/src/cpu/inorder/resources/mult_div_unit.cc
@@ -86,25 +86,6 @@ MultDivUnit::init()
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
// accomodate all multicyle resources?
void
@@ -124,7 +105,7 @@ MultDivUnit::requestAgain(DynInstPtr inst, bool &service_request)
"[tid:%i]: [sn:%i]: Updating the command for this "
"instruction\n", inst->readTid(), inst->seqNum);
} 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
DPRINTF(InOrderMDU,
"[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];
DynInstPtr inst = reqs[slot_num]->inst;
+ DPRINTF(InOrderMDU, "Executing [sn:%i] ...\n", slot_num);
+
switch (mult_div_req->cmd)
{
case StartMultDiv:
- DPRINTF(InOrderMDU, "Start MDU called ...\n");
-
- if (inst->opClass() == IntMultOp) {
- scheduleEvent(slot_num, multLatency);
- } else if (inst->opClass() == IntDivOp) {
- int op_size = getDivOpSize(inst);
-
- switch (op_size)
- {
- case 8:
- scheduleEvent(slot_num, div8Latency);
- break;
-
- case 16:
- scheduleEvent(slot_num, div16Latency);
- break;
-
- case 24:
- scheduleEvent(slot_num, div24Latency);
- break;
-
- case 32:
- scheduleEvent(slot_num, div32Latency);
- break;
+ {
+ DPRINTF(InOrderMDU, "Start MDU called ...\n");
+
+ OpClass op_class = inst->opClass();
+ if (op_class == IntMultOp) {
+ scheduleEvent(slot_num, multLatency);
+ } else if (op_class == IntDivOp) {
+ int op_size = getDivOpSize(inst);
+
+ switch (op_size)
+ {
+ case 8:
+ scheduleEvent(slot_num, div8Latency);
+ break;
+
+ case 16:
+ scheduleEvent(slot_num, div16Latency);
+ break;
+
+ case 24:
+ scheduleEvent(slot_num, div24Latency);
+ break;
+
+ case 32:
+ scheduleEvent(slot_num, div32Latency);
+ 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;
case MultDiv:
@@ -264,7 +251,7 @@ MultDivUnit::execute(int slot_num)
// counting down the time
{
DPRINTF(InOrderMDU, "End MDU called ...\n");
- if (mult_div_req->getInst()->isExecuted()) {
+ if (!mult_div_req->isProcessing()) {
DPRINTF(InOrderMDU, "Mult/Div finished.\n");
mult_div_req->done();
} else {
@@ -295,7 +282,6 @@ MultDivUnit::exeMulDiv(int slot_num)
if (inst->fault == NoFault) {
inst->setExecuted();
- mult_div_req->setCompleted();
DPRINTF(InOrderMDU, "[tid:%i]: The result of execution is 0x%x.\n",
inst->readTid(), inst->readIntResult(0));
@@ -303,8 +289,40 @@ MultDivUnit::exeMulDiv(int slot_num)
DPRINTF(InOrderMDU, "[tid:%i]: [sn:%i]: had a %s "
"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()
: ResourceEvent()
@@ -319,7 +337,8 @@ MDUEvent::process()
ResourceRequest* mult_div_req = resource->reqs[slotIdx];
- mult_div_req->done();
+ if (mult_div_req->isSquashed())
+ mdu_res->freeSlot(slotIdx);
}
diff --git a/src/cpu/inorder/resources/mult_div_unit.hh b/src/cpu/inorder/resources/mult_div_unit.hh
index 753bc64a6..7d179bdce 100644
--- a/src/cpu/inorder/resources/mult_div_unit.hh
+++ b/src/cpu/inorder/resources/mult_div_unit.hh
@@ -64,10 +64,6 @@ class MultDivUnit : public Resource {
* valid mult/div sequence is being maintained
*/
int getSlot(DynInstPtr inst);
-
- int findSlot(DynInstPtr inst);
-
- void freeSlot(int slot_idx);
void init();
@@ -84,6 +80,9 @@ class MultDivUnit : public Resource {
void requestAgain(DynInstPtr inst, bool &try_request);
+ void squash(DynInstPtr inst, int stage_num, InstSeqNum squash_seq_num,
+ ThreadID tid);
+
protected:
/** Latency & Repeat Rate for Multiply Insts */
unsigned multRepeatRate;