pipeline.cc revision 10259:ebb376f73dd2
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 40#include <algorithm> 41 42#include "cpu/minor/decode.hh" 43#include "cpu/minor/execute.hh" 44#include "cpu/minor/fetch1.hh" 45#include "cpu/minor/fetch2.hh" 46#include "cpu/minor/pipeline.hh" 47#include "debug/Drain.hh" 48#include "debug/MinorCPU.hh" 49#include "debug/MinorTrace.hh" 50#include "debug/Quiesce.hh" 51 52namespace Minor 53{ 54 55Pipeline::Pipeline(MinorCPU &cpu_, MinorCPUParams ¶ms) : 56 Ticked(cpu_, &(cpu_.BaseCPU::numCycles)), 57 cpu(cpu_), 58 allow_idling(params.enableIdling), 59 f1ToF2(cpu.name() + ".f1ToF2", "lines", 60 params.fetch1ToFetch2ForwardDelay), 61 f2ToF1(cpu.name() + ".f2ToF1", "prediction", 62 params.fetch1ToFetch2BackwardDelay, true), 63 f2ToD(cpu.name() + ".f2ToD", "insts", 64 params.fetch2ToDecodeForwardDelay), 65 dToE(cpu.name() + ".dToE", "insts", 66 params.decodeToExecuteForwardDelay), 67 eToF1(cpu.name() + ".eToF1", "branch", 68 params.executeBranchDelay), 69 execute(cpu.name() + ".execute", cpu, params, 70 dToE.output(), eToF1.input()), 71 decode(cpu.name() + ".decode", cpu, params, 72 f2ToD.output(), dToE.input(), execute.inputBuffer), 73 fetch2(cpu.name() + ".fetch2", cpu, params, 74 f1ToF2.output(), eToF1.output(), f2ToF1.input(), f2ToD.input(), 75 decode.inputBuffer), 76 fetch1(cpu.name() + ".fetch1", cpu, params, 77 eToF1.output(), f1ToF2.input(), f2ToF1.output(), fetch2.inputBuffer), 78 activityRecorder(cpu.name() + ".activity", Num_StageId, 79 /* The max depth of inter-stage FIFOs */ 80 std::max(params.fetch1ToFetch2ForwardDelay, 81 std::max(params.fetch2ToDecodeForwardDelay, 82 std::max(params.decodeToExecuteForwardDelay, 83 params.executeBranchDelay)))), 84 needToSignalDrained(false) 85{ 86 if (params.fetch1ToFetch2ForwardDelay < 1) { 87 fatal("%s: fetch1ToFetch2ForwardDelay must be >= 1 (%d)\n", 88 cpu.name(), params.fetch1ToFetch2ForwardDelay); 89 } 90 91 if (params.fetch2ToDecodeForwardDelay < 1) { 92 fatal("%s: fetch2ToDecodeForwardDelay must be >= 1 (%d)\n", 93 cpu.name(), params.fetch2ToDecodeForwardDelay); 94 } 95 96 if (params.decodeToExecuteForwardDelay < 1) { 97 fatal("%s: decodeToExecuteForwardDelay must be >= 1 (%d)\n", 98 cpu.name(), params.decodeToExecuteForwardDelay); 99 } 100 101 if (params.executeBranchDelay < 1) { 102 fatal("%s: executeBranchDelay must be >= 1\n", 103 cpu.name(), params.executeBranchDelay); 104 } 105} 106 107void 108Pipeline::minorTrace() const 109{ 110 fetch1.minorTrace(); 111 f1ToF2.minorTrace(); 112 f2ToF1.minorTrace(); 113 fetch2.minorTrace(); 114 f2ToD.minorTrace(); 115 decode.minorTrace(); 116 dToE.minorTrace(); 117 execute.minorTrace(); 118 eToF1.minorTrace(); 119 activityRecorder.minorTrace(); 120} 121 122void 123Pipeline::evaluate() 124{ 125 /* Note that it's important to evaluate the stages in order to allow 126 * 'immediate', 0-time-offset TimeBuffer activity to be visible from 127 * later stages to earlier ones in the same cycle */ 128 execute.evaluate(); 129 decode.evaluate(); 130 fetch2.evaluate(); 131 fetch1.evaluate(); 132 133 if (DTRACE(MinorTrace)) 134 minorTrace(); 135 136 /* Update the time buffers after the stages */ 137 f1ToF2.evaluate(); 138 f2ToF1.evaluate(); 139 f2ToD.evaluate(); 140 dToE.evaluate(); 141 eToF1.evaluate(); 142 143 /* The activity recorder must be be called after all the stages and 144 * before the idler (which acts on the advice of the activity recorder */ 145 activityRecorder.evaluate(); 146 147 if (allow_idling) { 148 /* Become idle if we can but are not draining */ 149 if (!activityRecorder.active() && !needToSignalDrained) { 150 DPRINTF(Quiesce, "Suspending as the processor is idle\n"); 151 stop(); 152 } 153 154 /* Deactivate all stages. Note that the stages *could* 155 * activate and deactivate themselves but that's fraught 156 * with additional difficulty. 157 * As organised herre */ 158 activityRecorder.deactivateStage(Pipeline::CPUStageId); 159 activityRecorder.deactivateStage(Pipeline::Fetch1StageId); 160 activityRecorder.deactivateStage(Pipeline::Fetch2StageId); 161 activityRecorder.deactivateStage(Pipeline::DecodeStageId); 162 activityRecorder.deactivateStage(Pipeline::ExecuteStageId); 163 } 164 165 if (needToSignalDrained) /* Must be draining */ 166 { 167 DPRINTF(Drain, "Still draining\n"); 168 if (isDrained()) { 169 DPRINTF(Drain, "Signalling end of draining\n"); 170 cpu.signalDrainDone(); 171 needToSignalDrained = false; 172 stop(); 173 } 174 } 175} 176 177MinorCPU::MinorCPUPort & 178Pipeline::getInstPort() 179{ 180 return fetch1.getIcachePort(); 181} 182 183MinorCPU::MinorCPUPort & 184Pipeline::getDataPort() 185{ 186 return execute.getDcachePort(); 187} 188 189void 190Pipeline::wakeupFetch() 191{ 192 execute.wakeupFetch(); 193} 194 195unsigned int 196Pipeline::drain(DrainManager *manager) 197{ 198 DPRINTF(MinorCPU, "Draining pipeline by halting inst fetches. " 199 " Execution should drain naturally\n"); 200 201 execute.drain(); 202 203 /* Make sure that needToSignalDrained isn't accidentally set if we 204 * are 'pre-drained' */ 205 bool drained = isDrained(); 206 needToSignalDrained = !drained; 207 208 return (drained ? 0 : 1); 209} 210 211void 212Pipeline::drainResume() 213{ 214 DPRINTF(Drain, "Drain resume\n"); 215 execute.drainResume(); 216} 217 218bool 219Pipeline::isDrained() 220{ 221 bool fetch1_drained = fetch1.isDrained(); 222 bool fetch2_drained = fetch2.isDrained(); 223 bool decode_drained = decode.isDrained(); 224 bool execute_drained = execute.isDrained(); 225 226 bool f1_to_f2_drained = f1ToF2.empty(); 227 bool f2_to_f1_drained = f2ToF1.empty(); 228 bool f2_to_d_drained = f2ToD.empty(); 229 bool d_to_e_drained = dToE.empty(); 230 231 bool ret = fetch1_drained && fetch2_drained && 232 decode_drained && execute_drained && 233 f1_to_f2_drained && f2_to_f1_drained && 234 f2_to_d_drained && d_to_e_drained; 235 236 DPRINTF(MinorCPU, "Pipeline undrained stages state:%s%s%s%s%s%s%s%s\n", 237 (fetch1_drained ? "" : " Fetch1"), 238 (fetch2_drained ? "" : " Fetch2"), 239 (decode_drained ? "" : " Decode"), 240 (execute_drained ? "" : " Execute"), 241 (f1_to_f2_drained ? "" : " F1->F2"), 242 (f2_to_f1_drained ? "" : " F2->F1"), 243 (f2_to_d_drained ? "" : " F2->D"), 244 (d_to_e_drained ? "" : " D->E") 245 ); 246 247 return ret; 248} 249 250} 251