diff options
Diffstat (limited to 'src/cpu/inorder/resources/mult_div_unit.cc')
-rw-r--r-- | src/cpu/inorder/resources/mult_div_unit.cc | 353 |
1 files changed, 0 insertions, 353 deletions
diff --git a/src/cpu/inorder/resources/mult_div_unit.cc b/src/cpu/inorder/resources/mult_div_unit.cc deleted file mode 100644 index 5a4d4bb55..000000000 --- a/src/cpu/inorder/resources/mult_div_unit.cc +++ /dev/null @@ -1,353 +0,0 @@ -/* - * Copyright (c) 2007 MIPS Technologies, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer; - * redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution; - * neither the name of the copyright holders nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Authors: Korey Sewell - * - */ - -#include <list> -#include <vector> - -#include "cpu/inorder/resources/mult_div_unit.hh" -#include "cpu/inorder/cpu.hh" -#include "cpu/inorder/resource_pool.hh" -#include "cpu/op_class.hh" -#include "debug/InOrderMDU.hh" -#include "debug/Resource.hh" - -using namespace std; -using namespace ThePipeline; - -MultDivUnit::MultDivUnit(string res_name, int res_id, int res_width, - Cycles res_latency, InOrderCPU *_cpu, - ThePipeline::Params *params) - : Resource(res_name, res_id, res_width, res_latency, _cpu), - multRepeatRate(params->multRepeatRate), - multLatency(params->multLatency), - div8RepeatRate(params->div8RepeatRate), - div8Latency(params->div8Latency), - div16RepeatRate(params->div16RepeatRate), - div16Latency(params->div16Latency), - div24RepeatRate(params->div24RepeatRate), - div24Latency(params->div24Latency), - div32RepeatRate(params->div32RepeatRate), - div32Latency(params->div32Latency), - lastMDUCycle(0), lastOpType(No_OpClass) -{ } - -void -MultDivUnit::regStats() -{ - multiplies - .name(name() + ".multiplies") - .desc("Number of Multipy Operations Executed"); - - divides - .name(name() + ".divides") - .desc("Number of Divide Operations Executed"); - - Resource::regStats(); -} - -void -MultDivUnit::init() -{ - // Set Up Resource Events to Appropriate Resource BandWidth - resourceEvent = new MDUEvent[width]; - - for (int i = 0; i < width; i++) { - reqs[i] = new ResourceRequest(this); - } - - initSlots(); -} - -//@TODO: Should we push this behavior into base-class to generically -// accomodate all multicyle resources? -void -MultDivUnit::requestAgain(DynInstPtr inst, bool &service_request) -{ - ResReqPtr mult_div_req = findRequest(inst); - assert(mult_div_req); - - service_request = true; - - // Check to see if this instruction is requesting the same command - // or a different one - if (mult_div_req->cmd != inst->curSkedEntry->cmd) { - // If different, then update command in the request - mult_div_req->cmd = inst->curSkedEntry->cmd; - DPRINTF(InOrderMDU, - "[tid:%i]: [sn:%i]: Updating the command for this " - "instruction\n", inst->readTid(), inst->seqNum); - } else { - // 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", - inst->readTid(), inst->seqNum); - } -} -int -MultDivUnit::getSlot(DynInstPtr inst) -{ - // If MDU already has instruction, return current slot. - int slot_num = findSlot(inst); - - // If we have this instruction's request already then return - if (slot_num != -1 && - inst->curSkedEntry->cmd == reqs[slot_num]->cmd) - return slot_num; - - unsigned repeat_rate = 0; - - /** Enforce MDU dependencies after a multiply is seen last */ - if (lastOpType == IntMultOp) { - repeat_rate = multRepeatRate; - } - - /** Enforce dependencies after a divide is seen last */ - if (lastOpType == IntDivOp) { - switch (lastDivSize) { - case 8: - repeat_rate = div8RepeatRate; - break; - - case 16: - repeat_rate = div16RepeatRate; - break; - - case 24: - repeat_rate = div24RepeatRate; - break; - - case 32: - repeat_rate = div32RepeatRate; - break; - } - } - - if (lastMDUCycle + repeat_rate > curTick()) { - DPRINTF(InOrderMDU, "MDU not ready to process another inst. until %i, " - "denying request.\n", lastMDUCycle + repeat_rate); - return -1; - } else { - int rval = Resource::getSlot(inst); - DPRINTF(InOrderMDU, "MDU request should pass: %i.\n", - rval); - - if (rval != -1) { - lastMDUCycle = curTick(); - lastOpType = inst->opClass(); - lastInstName = inst->staticInst->getName(); - } - - return rval; - } -} - -int -MultDivUnit::getDivOpSize(DynInstPtr inst) -{ - // Get RT Register from instruction (index #1) - uint32_t div_op = inst->readIntSrc(1); - - if (div_op <= 0xFF) { - return 8; - } else if (div_op <= 0xFFFF) { - return 16; - } else if (div_op <= 0xFFFFFF) { - return 24; - } else { - return 32; - } -} - -void -MultDivUnit::execute(int slot_num) -{ - ResourceRequest* mult_div_req = reqs[slot_num]; - DynInstPtr inst = reqs[slot_num]->inst; - if (inst->fault != NoFault) { - DPRINTF(InOrderMDU, - "[tid:%i]: [sn:%i]: Detected %s fault @ %x. Forwarding to " - "next stage.\n", inst->readTid(), inst->seqNum, inst->fault->name(), - inst->pcState()); - mult_div_req->done(); - return; - } - - DPRINTF(InOrderMDU, "Executing [sn:%i] ...\n", slot_num); - - switch (mult_div_req->cmd) - { - case StartMultDiv: - { - 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; - } - - // Allow to pass through to next stage while - // event processes - mult_div_req->setProcessing(); - mult_div_req->setCompleted(); - } - break; - - case MultDiv: - DPRINTF(InOrderMDU, "Execute MDU called ...\n"); - exeMulDiv(slot_num); - mult_div_req->done(); - break; - - - case EndMultDiv: - //@TODO: Why not allow high-latency requests to sleep - // within stage until event wakes up???? - // Seems wasteful to continually check to see if - // this is done when we have a event in parallel - // counting down the time - { - DPRINTF(InOrderMDU, "End MDU called ...\n"); - if (!mult_div_req->isProcessing()) { - DPRINTF(InOrderMDU, "Mult/Div finished.\n"); - mult_div_req->done(); - } else { - mult_div_req->setCompleted(false); - } - - } - break; - - default: - fatal("Unrecognized command to %s", resName); - } -} - -void -MultDivUnit::exeMulDiv(int slot_num) -{ - ResourceRequest* mult_div_req = reqs[slot_num]; - DynInstPtr inst = reqs[slot_num]->inst; - - inst->fault = inst->execute(); - - if (inst->opClass() == IntMultOp) { - multiplies++; - } else if (inst->opClass() == IntDivOp) { - divides++; - } - - if (inst->fault == NoFault) { - inst->setExecuted(); - - DPRINTF(InOrderMDU, "[tid:%i]: The result of execution is 0x%x.\n", - inst->readTid(), inst->readIntResult(0)); - } else { - DPRINTF(InOrderMDU, "[tid:%i]: [sn:%i]: had a %s " - "fault.\n", inst->readTid(), inst->seqNum, inst->fault->name()); - } - - mult_div_req->setProcessing(false); - cpu->wakeCPU(); -} - -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() -{ } - -void -MDUEvent::process() -{ - MultDivUnit* mdu_res = reinterpret_cast<MultDivUnit*>(resource); - - mdu_res->exeMulDiv(slotIdx); - - ResourceRequest* mult_div_req = resource->reqs[slotIdx]; - - if (mult_div_req->isSquashed()) - mdu_res->freeSlot(slotIdx); -} - - |