diff options
author | Korey Sewell <ksewell@umich.edu> | 2011-06-19 21:43:38 -0400 |
---|---|---|
committer | Korey Sewell <ksewell@umich.edu> | 2011-06-19 21:43:38 -0400 |
commit | c95fe261abab85bee247737a3d171378689891e0 (patch) | |
tree | 75569e5baa06a7bd25870505a48a3ddf24916475 | |
parent | 4c979f9325f0c82f3284ce0fb0cc118d77268cb5 (diff) | |
download | gem5-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
-rw-r--r-- | src/cpu/inorder/resource.cc | 6 | ||||
-rw-r--r-- | src/cpu/inorder/resource.hh | 2 | ||||
-rw-r--r-- | src/cpu/inorder/resource_pool.cc | 5 | ||||
-rw-r--r-- | src/cpu/inorder/resources/mult_div_unit.cc | 123 | ||||
-rw-r--r-- | src/cpu/inorder/resources/mult_div_unit.hh | 7 |
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; |