| /* |
| * 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 "arch/isa_traits.hh" |
| #include "cpu/inorder/pipeline_traits.hh" |
| #include "cpu/inorder/reg_dep_map.hh" |
| #include "cpu/inorder/inorder_dyn_inst.hh" |
| #include "cpu/inorder/cpu.hh" |
| |
| using namespace std; |
| using namespace TheISA; |
| using namespace ThePipeline; |
| |
| RegDepMap::RegDepMap(int size) |
| { |
| regMap.resize(size); |
| } |
| |
| string |
| RegDepMap::name() |
| { |
| return cpu->name() + ".RegDepMap"; |
| } |
| |
| void |
| RegDepMap::setCPU(InOrderCPU *_cpu) |
| { |
| cpu = _cpu; |
| } |
| |
| void |
| RegDepMap::clear() |
| { |
| regMap.clear(); |
| } |
| |
| void |
| RegDepMap::insert(DynInstPtr inst) |
| { |
| int dest_regs = inst->numDestRegs(); |
| |
| DPRINTF(RegDepMap, "Setting Output Dependencies for [sn:%i] " |
| ", %s (dest. regs = %i).\n", |
| inst->seqNum, |
| inst->staticInst->getName(), |
| dest_regs); |
| |
| for (int i = 0; i < dest_regs; i++) { |
| int idx = inst->destRegIdx(i); |
| |
| //if (inst->numFPDestRegs()) |
| // idx += TheISA::FP_Base_DepTag; |
| |
| insert(idx, inst); |
| } |
| } |
| |
| |
| void |
| RegDepMap::insert(unsigned idx, DynInstPtr inst) |
| { |
| DPRINTF(RegDepMap, "Inserting [sn:%i] onto dep. list for reg. idx %i.\n", |
| inst->seqNum, idx); |
| |
| regMap[idx].push_back(inst); |
| |
| inst->setRegDepEntry(); |
| } |
| |
| void |
| RegDepMap::remove(DynInstPtr inst) |
| { |
| if (inst->isRegDepEntry()) { |
| DPRINTF(RegDepMap, "Removing [sn:%i]'s entries from reg. dep. map.\n", |
| inst->seqNum); |
| |
| int dest_regs = inst->numDestRegs(); |
| |
| for (int i = 0; i < dest_regs; i++) { |
| int idx = inst->destRegIdx(i); |
| remove(idx, inst); |
| } |
| } |
| } |
| |
| void |
| RegDepMap::remove(unsigned idx, DynInstPtr inst) |
| { |
| std::list<DynInstPtr>::iterator list_it = regMap[idx].begin(); |
| std::list<DynInstPtr>::iterator list_end = regMap[idx].end(); |
| |
| while (list_it != list_end) { |
| if((*list_it) == inst) { |
| regMap[idx].erase(list_it); |
| break; |
| } |
| |
| list_it++; |
| } |
| } |
| |
| void |
| RegDepMap::removeFront(unsigned idx, DynInstPtr inst) |
| { |
| std::list<DynInstPtr>::iterator list_it = regMap[idx].begin(); |
| |
| DPRINTF(RegDepMap, "[tid:%u]: Removing dependency entry on phys. reg." |
| "%i for [sn:%i].\n", inst->readTid(), idx, inst->seqNum); |
| |
| assert(list_it != regMap[idx].end()); |
| |
| assert(inst == (*list_it)); |
| |
| regMap[idx].erase(list_it); |
| } |
| |
| bool |
| RegDepMap::canRead(unsigned idx, DynInstPtr inst) |
| { |
| if (regMap[idx].size() == 0) |
| return true; |
| |
| std::list<DynInstPtr>::iterator list_it = regMap[idx].begin(); |
| |
| if (inst->seqNum <= (*list_it)->seqNum) { |
| return true; |
| } else { |
| DPRINTF(RegDepMap, "[sn:%i] Can't read from RegFile, [sn:%i] has not written" |
| " it's value back yet.\n", inst->seqNum, (*list_it)->seqNum); |
| return false; |
| } |
| } |
| |
| ThePipeline::DynInstPtr |
| RegDepMap::canForward(unsigned reg_idx, unsigned src_idx, DynInstPtr inst) |
| { |
| std::list<DynInstPtr>::iterator list_it = regMap[reg_idx].begin(); |
| std::list<DynInstPtr>::iterator list_end = regMap[reg_idx].end(); |
| |
| DynInstPtr forward_inst = NULL; |
| |
| // Look for first, oldest instruction |
| while (list_it != list_end && |
| (*list_it)->seqNum < inst->seqNum) { |
| forward_inst = (*list_it); |
| list_it++; |
| } |
| |
| if (forward_inst) { |
| if (forward_inst->isExecuted() && |
| forward_inst->readResultTime(src_idx) < curTick) { |
| return forward_inst; |
| } else { |
| DPRINTF(RegDepMap, "[sn:%i] Can't get value through forwarding, " |
| " [sn:%i] has not been executed yet.\n", |
| inst->seqNum, forward_inst->seqNum); |
| return NULL; |
| } |
| } else { |
| DPRINTF(RegDepMap, "[sn:%i] No instruction found to forward from.\n", |
| inst->seqNum); |
| return NULL; |
| } |
| } |
| |
| bool |
| RegDepMap::canWrite(unsigned idx, DynInstPtr inst) |
| { |
| if (regMap[idx].size() == 0) |
| return true; |
| |
| std::list<DynInstPtr>::iterator list_it = regMap[idx].begin(); |
| |
| if (inst->seqNum <= (*list_it)->seqNum) { |
| return true; |
| } else { |
| DPRINTF(RegDepMap, "[sn:%i] Can't write from RegFile: [sn:%i] has not written" |
| " it's value back yet.\n", inst->seqNum, (*list_it)->seqNum); |
| } |
| |
| return false; |
| } |
| |
| int |
| RegDepMap::depSize(unsigned idx) |
| { |
| return regMap[idx].size(); |
| } |
| |
| ThePipeline::DynInstPtr |
| RegDepMap::findBypassInst(unsigned idx) |
| { |
| std::list<DynInstPtr>::iterator list_it = regMap[idx].begin(); |
| |
| if (depSize(idx) == 1) |
| return NULL; |
| |
| list_it++; |
| |
| while (list_it != regMap[idx].end()) { |
| if((*list_it)->isExecuted()) { |
| return *list_it; |
| break; |
| } |
| } |
| |
| return NULL; |
| } |