1/* 2 * Copyright (c) 2013-2014 ARM Limited 3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software 9 * licensed hereunder. You may use the software subject to the license 10 * terms below provided that you ensure that this notice is replicated 11 * unmodified and in its entirety in all distributions of the software, 12 * modified or unmodified, in source code or in binary form. 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions are 16 * met: redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer; 18 * redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution; 21 * neither the name of the copyright holders nor the names of its 22 * contributors may be used to endorse or promote products derived from 23 * this software without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 * 37 * Authors: Andrew Bardsley 38 */ 39
|
43#include "cpu/reg_class.hh" 44#include "debug/MinorScoreboard.hh" 45#include "debug/MinorTiming.hh" 46 47namespace Minor 48{ 49 50bool 51Scoreboard::findIndex(RegIndex reg, Index &scoreboard_index) 52{ 53 RegClass reg_class = regIdxToClass(reg); 54 bool ret = false; 55 56 if (reg == TheISA::ZeroReg) { 57 /* Don't bother with the zero register */ 58 ret = false; 59 } else { 60 switch (reg_class) 61 { 62 case IntRegClass: 63 scoreboard_index = reg; 64 ret = true; 65 break; 66 case FloatRegClass: 67 scoreboard_index = TheISA::NumIntRegs + TheISA::NumCCRegs + 68 reg - TheISA::FP_Reg_Base; 69 ret = true; 70 break; 71 case CCRegClass: 72 scoreboard_index = TheISA::NumIntRegs + reg - TheISA::FP_Reg_Base; 73 ret = true; 74 break; 75 case MiscRegClass: 76 /* Don't bother with Misc registers */ 77 ret = false; 78 break; 79 } 80 } 81 82 return ret; 83} 84 85/** Flatten a RegIndex, irrespective of what reg type it's pointing to */ 86static TheISA::RegIndex 87flattenRegIndex(TheISA::RegIndex reg, ThreadContext *thread_context) 88{ 89 RegClass reg_class = regIdxToClass(reg); 90 TheISA::RegIndex ret = reg; 91 92 switch (reg_class) 93 { 94 case IntRegClass: 95 ret = thread_context->flattenIntIndex(reg); 96 break; 97 case FloatRegClass: 98 ret = thread_context->flattenFloatIndex(reg); 99 break; 100 case CCRegClass: 101 ret = thread_context->flattenCCIndex(reg); 102 break; 103 case MiscRegClass: 104 /* Don't bother to flatten misc regs as we don't need them here */ 105 /* return thread_context->flattenMiscIndex(reg); */ 106 ret = reg; 107 break; 108 } 109 110 return ret; 111} 112 113void 114Scoreboard::markupInstDests(MinorDynInstPtr inst, Cycles retire_time, 115 ThreadContext *thread_context, bool mark_unpredictable) 116{ 117 if (inst->isFault()) 118 return; 119 120 StaticInstPtr staticInst = inst->staticInst; 121 unsigned int num_dests = staticInst->numDestRegs(); 122 123 /** Mark each destination register */ 124 for (unsigned int dest_index = 0; dest_index < num_dests; 125 dest_index++) 126 { 127 RegIndex reg = flattenRegIndex( 128 staticInst->destRegIdx(dest_index), thread_context); 129 Index index; 130 131 if (findIndex(reg, index)) { 132 if (mark_unpredictable) 133 numUnpredictableResults[index]++; 134 135 inst->flatDestRegIdx[dest_index] = reg; 136 137 numResults[index]++; 138 returnCycle[index] = retire_time; 139 /* We should be able to rely on only being given accending 140 * execSeqNums, but sanity check */ 141 if (inst->id.execSeqNum > writingInst[index]) { 142 writingInst[index] = inst->id.execSeqNum; 143 fuIndices[index] = inst->fuIndex; 144 } 145 146 DPRINTF(MinorScoreboard, "Marking up inst: %s" 147 " regIndex: %d final numResults: %d returnCycle: %d\n", 148 *inst, index, numResults[index], returnCycle[index]); 149 } else { 150 /* Use ZeroReg to mark invalid/untracked dests */ 151 inst->flatDestRegIdx[dest_index] = TheISA::ZeroReg; 152 } 153 } 154} 155 156InstSeqNum 157Scoreboard::execSeqNumToWaitFor(MinorDynInstPtr inst, 158 ThreadContext *thread_context) 159{ 160 InstSeqNum ret = 0; 161 162 if (inst->isFault()) 163 return ret; 164 165 StaticInstPtr staticInst = inst->staticInst; 166 unsigned int num_srcs = staticInst->numSrcRegs(); 167 168 for (unsigned int src_index = 0; src_index < num_srcs; src_index++) { 169 RegIndex reg = flattenRegIndex(staticInst->srcRegIdx(src_index), 170 thread_context); 171 unsigned short int index; 172 173 if (findIndex(reg, index)) { 174 if (writingInst[index] > ret) 175 ret = writingInst[index]; 176 } 177 } 178 179 DPRINTF(MinorScoreboard, "Inst: %s depends on execSeqNum: %d\n", 180 *inst, ret); 181 182 return ret; 183} 184 185void 186Scoreboard::clearInstDests(MinorDynInstPtr inst, bool clear_unpredictable) 187{ 188 if (inst->isFault()) 189 return; 190 191 StaticInstPtr staticInst = inst->staticInst; 192 unsigned int num_dests = staticInst->numDestRegs(); 193 194 /** Mark each destination register */ 195 for (unsigned int dest_index = 0; dest_index < num_dests; 196 dest_index++) 197 { 198 RegIndex reg = inst->flatDestRegIdx[dest_index]; 199 Index index; 200 201 if (findIndex(reg, index)) { 202 if (clear_unpredictable && numUnpredictableResults[index] != 0) 203 numUnpredictableResults[index] --; 204 205 numResults[index] --; 206 207 if (numResults[index] == 0) { 208 returnCycle[index] = Cycles(0); 209 writingInst[index] = 0; 210 fuIndices[index] = -1; 211 } 212 213 DPRINTF(MinorScoreboard, "Clearing inst: %s" 214 " regIndex: %d final numResults: %d\n", 215 *inst, index, numResults[index]); 216 } 217 } 218} 219 220bool 221Scoreboard::canInstIssue(MinorDynInstPtr inst, 222 const std::vector<Cycles> *src_reg_relative_latencies, 223 const std::vector<bool> *cant_forward_from_fu_indices, 224 Cycles now, ThreadContext *thread_context) 225{ 226 /* Always allow fault to be issued */ 227 if (inst->isFault()) 228 return true; 229 230 StaticInstPtr staticInst = inst->staticInst; 231 unsigned int num_srcs = staticInst->numSrcRegs(); 232 233 /* Default to saying you can issue */ 234 bool ret = true; 235 236 unsigned int num_relative_latencies = 0; 237 Cycles default_relative_latency = Cycles(0); 238 239 /* Where relative latencies are given, the default is the last 240 * one as that allows the rel. lat. list to be shorted than the 241 * number of src. regs */ 242 if (src_reg_relative_latencies && 243 src_reg_relative_latencies->size() != 0) 244 { 245 num_relative_latencies = src_reg_relative_latencies->size(); 246 default_relative_latency = (*src_reg_relative_latencies) 247 [num_relative_latencies-1]; 248 } 249 250 /* For each source register, find the latest result */ 251 unsigned int src_index = 0; 252 while (src_index < num_srcs && /* More registers */ 253 ret /* Still possible */) 254 { 255 RegIndex reg = flattenRegIndex(staticInst->srcRegIdx(src_index), 256 thread_context); 257 unsigned short int index; 258 259 if (findIndex(reg, index)) { 260 bool cant_forward = fuIndices[index] != 1 && 261 cant_forward_from_fu_indices && 262 index < cant_forward_from_fu_indices->size() && 263 (*cant_forward_from_fu_indices)[index]; 264 265 Cycles relative_latency = (cant_forward ? Cycles(0) : 266 (src_index >= num_relative_latencies ? 267 default_relative_latency : 268 (*src_reg_relative_latencies)[src_index])); 269 270 if (returnCycle[index] > (now + relative_latency) || 271 numUnpredictableResults[index] != 0) 272 { 273 ret = false; 274 } 275 } 276 src_index++; 277 } 278 279 if (DTRACE(MinorTiming)) { 280 if (ret && num_srcs > num_relative_latencies && 281 num_relative_latencies != 0) 282 { 283 DPRINTF(MinorTiming, "Warning, inst: %s timing extra decode has" 284 " more src. regs: %d than relative latencies: %d\n", 285 staticInst->disassemble(0), num_srcs, num_relative_latencies); 286 } 287 } 288 289 return ret; 290} 291 292void 293Scoreboard::minorTrace() const 294{ 295 std::ostringstream result_stream; 296 297 bool printed_element = false; 298 299 unsigned int i = 0; 300 while (i < numRegs) { 301 unsigned short int num_results = numResults[i]; 302 unsigned short int num_unpredictable_results = 303 numUnpredictableResults[i]; 304 305 if (!(num_results == 0 && num_unpredictable_results == Cycles(0))) { 306 if (printed_element) 307 result_stream << ','; 308 309 result_stream << '(' << i << ',' 310 << num_results << '/' 311 << num_unpredictable_results << '/' 312 << returnCycle[i] << '/' 313 << writingInst[i] << ')'; 314 315 printed_element = true; 316 } 317 318 i++; 319 } 320 321 MINORTRACE("busy=%s\n", result_stream.str()); 322} 323 324}
|