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