summaryrefslogtreecommitdiff
path: root/src/cpu/inorder/resources/mult_div_unit.cc
diff options
context:
space:
mode:
authorAndreas Hansson <andreas.hansson@arm.com>2015-04-20 12:46:35 -0400
committerAndreas Hansson <andreas.hansson@arm.com>2015-04-20 12:46:35 -0400
commitcd76e34056afab83697beef1d1ced94ee671a20d (patch)
tree8adaa80ba72593bdf67103ad5cd0a072b95e8acb /src/cpu/inorder/resources/mult_div_unit.cc
parent076ea249ae47b935bea424954174f33fdecb7fcc (diff)
downloadgem5-cd76e34056afab83697beef1d1ced94ee671a20d.tar.xz
cpu: Remove the InOrderCPU from the tree
This patch takes the final step in removing the InOrderCPU from the tree. Rest in peace. The MinorCPU is now used to model an in-order microarchitecture, and long term the MinorCPU will eventually be renamed InOrderCPU.
Diffstat (limited to 'src/cpu/inorder/resources/mult_div_unit.cc')
-rw-r--r--src/cpu/inorder/resources/mult_div_unit.cc353
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);
-}
-
-