Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2007 MIPS Technologies, Inc. |
| 3 | * All rights reserved. |
| 4 | * |
| 5 | * Redistribution and use in source and binary forms, with or without |
| 6 | * modification, are permitted provided that the following conditions are |
| 7 | * met: redistributions of source code must retain the above copyright |
| 8 | * notice, this list of conditions and the following disclaimer; |
| 9 | * redistributions in binary form must reproduce the above copyright |
| 10 | * notice, this list of conditions and the following disclaimer in the |
| 11 | * documentation and/or other materials provided with the distribution; |
| 12 | * neither the name of the copyright holders nor the names of its |
| 13 | * contributors may be used to endorse or promote products derived from |
| 14 | * this software without specific prior written permission. |
| 15 | * |
| 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 17 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 18 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 19 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 20 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 21 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 22 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 23 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 26 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | * |
| 28 | * Authors: Korey Sewell |
| 29 | * |
| 30 | */ |
| 31 | |
Nathan Binkert | 47877cf | 2009-05-26 09:23:13 -0700 | [diff] [blame] | 32 | #include <algorithm> |
Steve Reinhardt | 14808ec | 2009-04-17 16:54:58 -0700 | [diff] [blame] | 33 | |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 34 | #include "arch/utility.hh" |
Nathan Binkert | 47877cf | 2009-05-26 09:23:13 -0700 | [diff] [blame] | 35 | #include "config/full_system.hh" |
Nathan Binkert | d9f39c8 | 2009-09-23 08:34:21 -0700 | [diff] [blame] | 36 | #include "config/the_isa.hh" |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 37 | #include "cpu/activity.hh" |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 38 | #include "cpu/base.hh" |
Nathan Binkert | d9f39c8 | 2009-09-23 08:34:21 -0700 | [diff] [blame] | 39 | #include "cpu/exetrace.hh" |
| 40 | #include "cpu/inorder/cpu.hh" |
| 41 | #include "cpu/inorder/first_stage.hh" |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 42 | #include "cpu/inorder/inorder_dyn_inst.hh" |
Nathan Binkert | d9f39c8 | 2009-09-23 08:34:21 -0700 | [diff] [blame] | 43 | #include "cpu/inorder/pipeline_traits.hh" |
| 44 | #include "cpu/inorder/resource_pool.hh" |
| 45 | #include "cpu/inorder/resources/resource_list.hh" |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 46 | #include "cpu/inorder/thread_context.hh" |
| 47 | #include "cpu/inorder/thread_state.hh" |
Nathan Binkert | d9f39c8 | 2009-09-23 08:34:21 -0700 | [diff] [blame] | 48 | #include "cpu/simple_thread.hh" |
| 49 | #include "cpu/thread_context.hh" |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 50 | #include "mem/translating_port.hh" |
Nathan Binkert | d9f39c8 | 2009-09-23 08:34:21 -0700 | [diff] [blame] | 51 | #include "params/InOrderCPU.hh" |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 52 | #include "sim/process.hh" |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 53 | #include "sim/stat_control.hh" |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 54 | |
Korey Sewell | badb238 | 2009-09-15 01:44:48 -0400 | [diff] [blame] | 55 | #if FULL_SYSTEM |
| 56 | #include "cpu/quiesce_event.hh" |
| 57 | #include "sim/system.hh" |
| 58 | #endif |
| 59 | |
| 60 | #if THE_ISA == ALPHA_ISA |
| 61 | #include "arch/alpha/osfpal.hh" |
| 62 | #endif |
| 63 | |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 64 | using namespace std; |
| 65 | using namespace TheISA; |
| 66 | using namespace ThePipeline; |
| 67 | |
| 68 | InOrderCPU::TickEvent::TickEvent(InOrderCPU *c) |
| 69 | : Event(CPU_Tick_Pri), cpu(c) |
| 70 | { } |
| 71 | |
| 72 | |
| 73 | void |
| 74 | InOrderCPU::TickEvent::process() |
| 75 | { |
| 76 | cpu->tick(); |
| 77 | } |
| 78 | |
| 79 | |
| 80 | const char * |
| 81 | InOrderCPU::TickEvent::description() |
| 82 | { |
| 83 | return "InOrderCPU tick event"; |
| 84 | } |
| 85 | |
| 86 | InOrderCPU::CPUEvent::CPUEvent(InOrderCPU *_cpu, CPUEventType e_type, |
Korey Sewell | 4a945aa | 2010-01-31 18:26:26 -0500 | [diff] [blame] | 87 | Fault fault, ThreadID _tid, DynInstPtr inst, |
| 88 | unsigned event_pri_offset) |
| 89 | : Event(Event::Priority((unsigned int)CPU_Tick_Pri + event_pri_offset)), |
| 90 | cpu(_cpu) |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 91 | { |
Korey Sewell | d8e0935 | 2010-01-31 18:26:03 -0500 | [diff] [blame] | 92 | setEvent(e_type, fault, _tid, inst); |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 93 | } |
| 94 | |
Korey Sewell | 3a057bd | 2009-05-12 15:01:16 -0400 | [diff] [blame] | 95 | |
| 96 | std::string InOrderCPU::eventNames[NumCPUEvents] = |
| 97 | { |
| 98 | "ActivateThread", |
Korey Sewell | e1fcc64 | 2010-01-31 18:26:32 -0500 | [diff] [blame] | 99 | "ActivateNextReadyThread", |
| 100 | "DeactivateThread", |
Korey Sewell | 5e0b833 | 2010-01-31 18:28:05 -0500 | [diff] [blame] | 101 | "HaltThread", |
Korey Sewell | 3a057bd | 2009-05-12 15:01:16 -0400 | [diff] [blame] | 102 | "SuspendThread", |
Korey Sewell | 3a057bd | 2009-05-12 15:01:16 -0400 | [diff] [blame] | 103 | "Trap", |
| 104 | "InstGraduated", |
Korey Sewell | d9eaa2f | 2010-01-31 18:26:40 -0500 | [diff] [blame] | 105 | "SquashFromMemStall", |
Korey Sewell | 3a057bd | 2009-05-12 15:01:16 -0400 | [diff] [blame] | 106 | "UpdatePCs" |
| 107 | }; |
| 108 | |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 109 | void |
| 110 | InOrderCPU::CPUEvent::process() |
| 111 | { |
| 112 | switch (cpuEventType) |
| 113 | { |
| 114 | case ActivateThread: |
| 115 | cpu->activateThread(tid); |
| 116 | break; |
| 117 | |
Korey Sewell | e1fcc64 | 2010-01-31 18:26:32 -0500 | [diff] [blame] | 118 | case ActivateNextReadyThread: |
| 119 | cpu->activateNextReadyThread(); |
| 120 | break; |
| 121 | |
| 122 | case DeactivateThread: |
| 123 | cpu->deactivateThread(tid); |
| 124 | break; |
| 125 | |
Korey Sewell | 5e0b833 | 2010-01-31 18:28:05 -0500 | [diff] [blame] | 126 | case HaltThread: |
| 127 | cpu->haltThread(tid); |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 128 | break; |
| 129 | |
Korey Sewell | d9eaa2f | 2010-01-31 18:26:40 -0500 | [diff] [blame] | 130 | case SuspendThread: |
| 131 | cpu->suspendThread(tid); |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 132 | break; |
| 133 | |
Korey Sewell | eac5eac | 2010-01-31 18:26:13 -0500 | [diff] [blame] | 134 | case SquashFromMemStall: |
| 135 | cpu->squashDueToMemStall(inst->squashingStage, inst->seqNum, tid); |
| 136 | break; |
| 137 | |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 138 | case Trap: |
Gabe Black | 6833ca7 | 2010-09-13 19:26:03 -0700 | [diff] [blame] | 139 | cpu->trapCPU(fault, tid, inst); |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 140 | break; |
| 141 | |
| 142 | default: |
Korey Sewell | 5e0b833 | 2010-01-31 18:28:05 -0500 | [diff] [blame] | 143 | fatal("Unrecognized Event Type %s", eventNames[cpuEventType]); |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 144 | } |
Korey Sewell | 7b3b362 | 2010-01-31 17:18:15 -0500 | [diff] [blame] | 145 | |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 146 | cpu->cpuEventRemoveList.push(this); |
| 147 | } |
| 148 | |
Korey Sewell | 7b3b362 | 2010-01-31 17:18:15 -0500 | [diff] [blame] | 149 | |
| 150 | |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 151 | const char * |
| 152 | InOrderCPU::CPUEvent::description() |
| 153 | { |
| 154 | return "InOrderCPU event"; |
| 155 | } |
| 156 | |
| 157 | void |
| 158 | InOrderCPU::CPUEvent::scheduleEvent(int delay) |
| 159 | { |
Steve Reinhardt | d60c293 | 2011-01-07 21:50:29 -0800 | [diff] [blame] | 160 | assert(!scheduled() || squashed()); |
Steve Reinhardt | 6f11879 | 2011-01-07 21:50:29 -0800 | [diff] [blame^] | 161 | cpu->reschedule(this, cpu->nextCycle(curTick() + cpu->ticks(delay)), true); |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 162 | } |
| 163 | |
| 164 | void |
| 165 | InOrderCPU::CPUEvent::unscheduleEvent() |
| 166 | { |
| 167 | if (scheduled()) |
| 168 | squash(); |
| 169 | } |
| 170 | |
| 171 | InOrderCPU::InOrderCPU(Params *params) |
| 172 | : BaseCPU(params), |
| 173 | cpu_id(params->cpu_id), |
Korey Sewell | 9e1dc7f | 2009-03-04 22:37:45 -0500 | [diff] [blame] | 174 | coreType("default"), |
| 175 | _status(Idle), |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 176 | tickEvent(this), |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 177 | timeBuffer(2 , 2), |
| 178 | removeInstsThisCycle(false), |
| 179 | activityRec(params->name, NumStages, 10, params->activity), |
Korey Sewell | badb238 | 2009-09-15 01:44:48 -0400 | [diff] [blame] | 180 | #if FULL_SYSTEM |
| 181 | system(params->system), |
| 182 | physmem(system->physmem), |
| 183 | #endif // FULL_SYSTEM |
Korey Sewell | 7b3b362 | 2010-01-31 17:18:15 -0500 | [diff] [blame] | 184 | #ifdef DEBUG |
| 185 | cpuEventNum(0), |
| 186 | resReqCount(0), |
| 187 | #endif // DEBUG |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 188 | switchCount(0), |
| 189 | deferRegistration(false/*params->deferRegistration*/), |
Korey Sewell | 0b29c2d | 2010-01-31 18:28:59 -0500 | [diff] [blame] | 190 | stageTracing(params->stageTracing), |
| 191 | instsPerSwitch(0) |
Korey Sewell | 0e96798 | 2010-01-31 18:25:13 -0500 | [diff] [blame] | 192 | { |
Korey Sewell | badb238 | 2009-09-15 01:44:48 -0400 | [diff] [blame] | 193 | ThreadID active_threads; |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 194 | cpu_params = params; |
| 195 | |
| 196 | resPool = new ResourcePool(this, params); |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 197 | |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 198 | // Resize for Multithreading CPUs |
| 199 | thread.resize(numThreads); |
| 200 | |
Korey Sewell | badb238 | 2009-09-15 01:44:48 -0400 | [diff] [blame] | 201 | #if FULL_SYSTEM |
| 202 | active_threads = 1; |
| 203 | #else |
| 204 | active_threads = params->workload.size(); |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 205 | |
| 206 | if (active_threads > MaxThreads) { |
| 207 | panic("Workload Size too large. Increase the 'MaxThreads'" |
| 208 | "in your InOrder implementation or " |
| 209 | "edit your workload size."); |
| 210 | } |
Korey Sewell | 0e96798 | 2010-01-31 18:25:13 -0500 | [diff] [blame] | 211 | |
Korey Sewell | 1a89e8f | 2010-01-31 18:29:59 -0500 | [diff] [blame] | 212 | |
Korey Sewell | 0e96798 | 2010-01-31 18:25:13 -0500 | [diff] [blame] | 213 | if (active_threads > 1) { |
| 214 | threadModel = (InOrderCPU::ThreadModel) params->threadModel; |
Korey Sewell | e1fcc64 | 2010-01-31 18:26:32 -0500 | [diff] [blame] | 215 | |
| 216 | if (threadModel == SMT) { |
| 217 | DPRINTF(InOrderCPU, "Setting Thread Model to SMT.\n"); |
| 218 | } else if (threadModel == SwitchOnCacheMiss) { |
| 219 | DPRINTF(InOrderCPU, "Setting Thread Model to " |
| 220 | "Switch On Cache Miss\n"); |
| 221 | } |
| 222 | |
Korey Sewell | 0e96798 | 2010-01-31 18:25:13 -0500 | [diff] [blame] | 223 | } else { |
| 224 | threadModel = Single; |
| 225 | } |
| 226 | |
| 227 | |
| 228 | |
Korey Sewell | badb238 | 2009-09-15 01:44:48 -0400 | [diff] [blame] | 229 | #endif |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 230 | |
| 231 | // Bind the fetch & data ports from the resource pool. |
| 232 | fetchPortIdx = resPool->getPortIdx(params->fetchMemPort); |
| 233 | if (fetchPortIdx == 0) { |
Korey Sewell | 1c8dfd9 | 2009-05-12 15:01:13 -0400 | [diff] [blame] | 234 | fatal("Unable to find port to fetch instructions from.\n"); |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 235 | } |
| 236 | |
| 237 | dataPortIdx = resPool->getPortIdx(params->dataMemPort); |
| 238 | if (dataPortIdx == 0) { |
Korey Sewell | 1c8dfd9 | 2009-05-12 15:01:13 -0400 | [diff] [blame] | 239 | fatal("Unable to find port for data.\n"); |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 240 | } |
| 241 | |
Nathan Binkert | 47877cf | 2009-05-26 09:23:13 -0700 | [diff] [blame] | 242 | for (ThreadID tid = 0; tid < numThreads; ++tid) { |
Korey Sewell | badb238 | 2009-09-15 01:44:48 -0400 | [diff] [blame] | 243 | #if FULL_SYSTEM |
| 244 | // SMT is not supported in FS mode yet. |
Korey Sewell | f09f84d | 2009-10-01 09:35:06 -0400 | [diff] [blame] | 245 | assert(numThreads == 1); |
| 246 | thread[tid] = new Thread(this, 0); |
Korey Sewell | badb238 | 2009-09-15 01:44:48 -0400 | [diff] [blame] | 247 | #else |
Nathan Binkert | 6faf377 | 2009-06-04 23:21:12 -0700 | [diff] [blame] | 248 | if (tid < (ThreadID)params->workload.size()) { |
Korey Sewell | 30cd2d2 | 2009-03-04 13:17:08 -0500 | [diff] [blame] | 249 | DPRINTF(InOrderCPU, "Workload[%i] process is %#x\n", |
Korey Sewell | f09f84d | 2009-10-01 09:35:06 -0400 | [diff] [blame] | 250 | tid, params->workload[tid]->prog_fname); |
| 251 | thread[tid] = |
Gabe Black | c9a27d8 | 2009-07-08 23:02:22 -0700 | [diff] [blame] | 252 | new Thread(this, tid, params->workload[tid]); |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 253 | } else { |
| 254 | //Allocate Empty thread so M5 can use later |
| 255 | //when scheduling threads to CPU |
Korey Sewell | 30cd2d2 | 2009-03-04 13:17:08 -0500 | [diff] [blame] | 256 | Process* dummy_proc = params->workload[0]; |
Korey Sewell | f09f84d | 2009-10-01 09:35:06 -0400 | [diff] [blame] | 257 | thread[tid] = new Thread(this, tid, dummy_proc); |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 258 | } |
Korey Sewell | 1a89e8f | 2010-01-31 18:29:59 -0500 | [diff] [blame] | 259 | |
| 260 | // Eventually set this with parameters... |
| 261 | asid[tid] = tid; |
Korey Sewell | badb238 | 2009-09-15 01:44:48 -0400 | [diff] [blame] | 262 | #endif |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 263 | |
| 264 | // Setup the TC that will serve as the interface to the threads/CPU. |
| 265 | InOrderThreadContext *tc = new InOrderThreadContext; |
| 266 | tc->cpu = this; |
Nathan Binkert | 47877cf | 2009-05-26 09:23:13 -0700 | [diff] [blame] | 267 | tc->thread = thread[tid]; |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 268 | |
| 269 | // Give the thread the TC. |
Nathan Binkert | 47877cf | 2009-05-26 09:23:13 -0700 | [diff] [blame] | 270 | thread[tid]->tc = tc; |
| 271 | thread[tid]->setFuncExeInst(0); |
| 272 | globalSeqNum[tid] = 1; |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 273 | |
| 274 | // Add the TC to the CPU's list of TC's. |
| 275 | this->threadContexts.push_back(tc); |
| 276 | } |
| 277 | |
| 278 | // Initialize TimeBuffer Stage Queues |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 279 | for (int stNum=0; stNum < NumStages - 1; stNum++) { |
| 280 | stageQueue[stNum] = new StageQueue(NumStages, NumStages); |
Korey Sewell | 846f953 | 2009-03-04 13:16:49 -0500 | [diff] [blame] | 281 | stageQueue[stNum]->id(stNum); |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 282 | } |
| 283 | |
| 284 | |
| 285 | // Set Up Pipeline Stages |
| 286 | for (int stNum=0; stNum < NumStages; stNum++) { |
| 287 | if (stNum == 0) |
| 288 | pipelineStage[stNum] = new FirstStage(params, stNum); |
| 289 | else |
| 290 | pipelineStage[stNum] = new PipelineStage(params, stNum); |
| 291 | |
| 292 | pipelineStage[stNum]->setCPU(this); |
| 293 | pipelineStage[stNum]->setActiveThreads(&activeThreads); |
| 294 | pipelineStage[stNum]->setTimeBuffer(&timeBuffer); |
| 295 | |
| 296 | // Take Care of 1st/Nth stages |
| 297 | if (stNum > 0) |
| 298 | pipelineStage[stNum]->setPrevStageQueue(stageQueue[stNum - 1]); |
Korey Sewell | f69b018 | 2009-03-04 13:17:07 -0500 | [diff] [blame] | 299 | if (stNum < NumStages - 1) |
| 300 | pipelineStage[stNum]->setNextStageQueue(stageQueue[stNum]); |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 301 | } |
| 302 | |
| 303 | // Initialize thread specific variables |
Nathan Binkert | 47877cf | 2009-05-26 09:23:13 -0700 | [diff] [blame] | 304 | for (ThreadID tid = 0; tid < numThreads; tid++) { |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 305 | archRegDepMap[tid].setCPU(this); |
| 306 | |
| 307 | nonSpecInstActive[tid] = false; |
| 308 | nonSpecSeqNum[tid] = 0; |
| 309 | |
| 310 | squashSeqNum[tid] = MaxAddr; |
| 311 | lastSquashCycle[tid] = 0; |
| 312 | |
Gabe Black | a480ba0 | 2009-07-08 23:02:20 -0700 | [diff] [blame] | 313 | memset(intRegs[tid], 0, sizeof(intRegs[tid])); |
Gabe Black | 0cb180e | 2009-07-08 23:02:20 -0700 | [diff] [blame] | 314 | memset(floatRegs.i[tid], 0, sizeof(floatRegs.i[tid])); |
Gabe Black | 32daf6f | 2009-07-08 23:02:20 -0700 | [diff] [blame] | 315 | isa[tid].clear(); |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 316 | |
Korey Sewell | d9eaa2f | 2010-01-31 18:26:40 -0500 | [diff] [blame] | 317 | isa[tid].expandForMultithreading(numThreads, 1/*numVirtProcs*/); |
Korey Sewell | 1a89e8f | 2010-01-31 18:29:59 -0500 | [diff] [blame] | 318 | |
| 319 | // Define dummy instructions and resource requests to be used. |
| 320 | dummyInst[tid] = new InOrderDynInst(this, |
| 321 | thread[tid], |
| 322 | 0, |
| 323 | tid, |
| 324 | asid[tid]); |
| 325 | |
| 326 | dummyReq[tid] = new ResourceRequest(resPool->getResource(0), |
| 327 | dummyInst[tid], |
| 328 | 0, |
| 329 | 0, |
| 330 | 0, |
| 331 | 0); |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 332 | } |
| 333 | |
Korey Sewell | 9357e35 | 2010-01-31 18:30:48 -0500 | [diff] [blame] | 334 | dummyReqInst = new InOrderDynInst(this, NULL, 0, 0, 0); |
| 335 | dummyReqInst->setSquashed(); |
| 336 | |
| 337 | dummyBufferInst = new InOrderDynInst(this, NULL, 0, 0, 0); |
| 338 | dummyBufferInst->setSquashed(); |
| 339 | |
Steve Reinhardt | 6f11879 | 2011-01-07 21:50:29 -0800 | [diff] [blame^] | 340 | lastRunningCycle = curTick(); |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 341 | |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 342 | // Reset CPU to reset state. |
| 343 | #if FULL_SYSTEM |
| 344 | Fault resetFault = new ResetFault(); |
| 345 | resetFault->invoke(tcBase()); |
| 346 | #else |
| 347 | reset(); |
| 348 | #endif |
| 349 | |
Korey Sewell | 9357e35 | 2010-01-31 18:30:48 -0500 | [diff] [blame] | 350 | dummyBufferInst->resetInstCount(); |
| 351 | |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 352 | // Schedule First Tick Event, CPU will reschedule itself from here on out. |
| 353 | scheduleTickEvent(0); |
| 354 | } |
| 355 | |
Korey Sewell | f3bc2df | 2010-01-31 18:30:08 -0500 | [diff] [blame] | 356 | InOrderCPU::~InOrderCPU() |
| 357 | { |
| 358 | delete resPool; |
| 359 | } |
| 360 | |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 361 | |
| 362 | void |
| 363 | InOrderCPU::regStats() |
| 364 | { |
| 365 | /* Register the Resource Pool's stats here.*/ |
| 366 | resPool->regStats(); |
| 367 | |
Korey Sewell | ffa9ecb | 2010-01-31 18:28:51 -0500 | [diff] [blame] | 368 | /* Register for each Pipeline Stage */ |
| 369 | for (int stage_num=0; stage_num < ThePipeline::NumStages; stage_num++) { |
| 370 | pipelineStage[stage_num]->regStats(); |
| 371 | } |
| 372 | |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 373 | /* Register any of the InOrderCPU's stats here.*/ |
Korey Sewell | 0b29c2d | 2010-01-31 18:28:59 -0500 | [diff] [blame] | 374 | instsPerCtxtSwitch |
| 375 | .name(name() + ".instsPerContextSwitch") |
| 376 | .desc("Instructions Committed Per Context Switch") |
| 377 | .prereq(instsPerCtxtSwitch); |
| 378 | |
| 379 | numCtxtSwitches |
| 380 | .name(name() + ".contextSwitches") |
| 381 | .desc("Number of context switches"); |
Korey Sewell | 9f0d8f2 | 2010-06-23 18:18:20 -0400 | [diff] [blame] | 382 | |
| 383 | comLoads |
| 384 | .name(name() + ".comLoads") |
| 385 | .desc("Number of Load instructions committed"); |
| 386 | |
| 387 | comStores |
| 388 | .name(name() + ".comStores") |
| 389 | .desc("Number of Store instructions committed"); |
| 390 | |
| 391 | comBranches |
| 392 | .name(name() + ".comBranches") |
| 393 | .desc("Number of Branches instructions committed"); |
| 394 | |
| 395 | comNops |
| 396 | .name(name() + ".comNops") |
| 397 | .desc("Number of Nop instructions committed"); |
| 398 | |
| 399 | comNonSpec |
| 400 | .name(name() + ".comNonSpec") |
| 401 | .desc("Number of Non-Speculative instructions committed"); |
| 402 | |
| 403 | comInts |
| 404 | .name(name() + ".comInts") |
| 405 | .desc("Number of Integer instructions committed"); |
| 406 | |
| 407 | comFloats |
| 408 | .name(name() + ".comFloats") |
| 409 | .desc("Number of Floating Point instructions committed"); |
Korey Sewell | 0b29c2d | 2010-01-31 18:28:59 -0500 | [diff] [blame] | 410 | |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 411 | timesIdled |
| 412 | .name(name() + ".timesIdled") |
| 413 | .desc("Number of times that the entire CPU went into an idle state and" |
| 414 | " unscheduled itself") |
| 415 | .prereq(timesIdled); |
| 416 | |
| 417 | idleCycles |
| 418 | .name(name() + ".idleCycles") |
Korey Sewell | ea89099 | 2010-01-31 18:30:24 -0500 | [diff] [blame] | 419 | .desc("Number of cycles cpu's stages were not processed"); |
| 420 | |
| 421 | runCycles |
| 422 | .name(name() + ".runCycles") |
| 423 | .desc("Number of cycles cpu stages are processed."); |
| 424 | |
| 425 | activity |
| 426 | .name(name() + ".activity") |
| 427 | .desc("Percentage of cycles cpu is active") |
| 428 | .precision(6); |
| 429 | activity = (runCycles / numCycles) * 100; |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 430 | |
| 431 | threadCycles |
| 432 | .init(numThreads) |
| 433 | .name(name() + ".threadCycles") |
| 434 | .desc("Total Number of Cycles A Thread Was Active in CPU (Per-Thread)"); |
| 435 | |
| 436 | smtCycles |
| 437 | .name(name() + ".smtCycles") |
Korey Sewell | 7b3b362 | 2010-01-31 17:18:15 -0500 | [diff] [blame] | 438 | .desc("Total number of cycles that the CPU was in SMT-mode"); |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 439 | |
| 440 | committedInsts |
| 441 | .init(numThreads) |
| 442 | .name(name() + ".committedInsts") |
| 443 | .desc("Number of Instructions Simulated (Per-Thread)"); |
| 444 | |
| 445 | smtCommittedInsts |
| 446 | .init(numThreads) |
| 447 | .name(name() + ".smtCommittedInsts") |
| 448 | .desc("Number of SMT Instructions Simulated (Per-Thread)"); |
| 449 | |
| 450 | totalCommittedInsts |
| 451 | .name(name() + ".committedInsts_total") |
| 452 | .desc("Number of Instructions Simulated (Total)"); |
| 453 | |
| 454 | cpi |
| 455 | .name(name() + ".cpi") |
| 456 | .desc("CPI: Cycles Per Instruction (Per-Thread)") |
| 457 | .precision(6); |
Korey Sewell | 9f0d8f2 | 2010-06-23 18:18:20 -0400 | [diff] [blame] | 458 | cpi = numCycles / committedInsts; |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 459 | |
| 460 | smtCpi |
| 461 | .name(name() + ".smt_cpi") |
| 462 | .desc("CPI: Total SMT-CPI") |
| 463 | .precision(6); |
| 464 | smtCpi = smtCycles / smtCommittedInsts; |
| 465 | |
| 466 | totalCpi |
| 467 | .name(name() + ".cpi_total") |
| 468 | .desc("CPI: Total CPI of All Threads") |
| 469 | .precision(6); |
Korey Sewell | e4aa4ca | 2009-03-04 13:16:48 -0500 | [diff] [blame] | 470 | totalCpi = numCycles / totalCommittedInsts; |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 471 | |
| 472 | ipc |
| 473 | .name(name() + ".ipc") |
| 474 | .desc("IPC: Instructions Per Cycle (Per-Thread)") |
| 475 | .precision(6); |
Korey Sewell | 9f0d8f2 | 2010-06-23 18:18:20 -0400 | [diff] [blame] | 476 | ipc = committedInsts / numCycles; |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 477 | |
| 478 | smtIpc |
| 479 | .name(name() + ".smt_ipc") |
| 480 | .desc("IPC: Total SMT-IPC") |
| 481 | .precision(6); |
| 482 | smtIpc = smtCommittedInsts / smtCycles; |
| 483 | |
| 484 | totalIpc |
| 485 | .name(name() + ".ipc_total") |
| 486 | .desc("IPC: Total IPC of All Threads") |
| 487 | .precision(6); |
Korey Sewell | e4aa4ca | 2009-03-04 13:16:48 -0500 | [diff] [blame] | 488 | totalIpc = totalCommittedInsts / numCycles; |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 489 | |
| 490 | BaseCPU::regStats(); |
| 491 | } |
| 492 | |
| 493 | |
| 494 | void |
| 495 | InOrderCPU::tick() |
| 496 | { |
| 497 | DPRINTF(InOrderCPU, "\n\nInOrderCPU: Ticking main, InOrderCPU.\n"); |
| 498 | |
| 499 | ++numCycles; |
| 500 | |
Korey Sewell | ea89099 | 2010-01-31 18:30:24 -0500 | [diff] [blame] | 501 | bool pipes_idle = true; |
| 502 | |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 503 | //Tick each of the stages |
| 504 | for (int stNum=NumStages - 1; stNum >= 0 ; stNum--) { |
| 505 | pipelineStage[stNum]->tick(); |
Korey Sewell | ea89099 | 2010-01-31 18:30:24 -0500 | [diff] [blame] | 506 | |
| 507 | pipes_idle = pipes_idle && pipelineStage[stNum]->idle; |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 508 | } |
| 509 | |
Korey Sewell | ea89099 | 2010-01-31 18:30:24 -0500 | [diff] [blame] | 510 | if (pipes_idle) |
| 511 | idleCycles++; |
| 512 | else |
| 513 | runCycles++; |
| 514 | |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 515 | // Now advance the time buffers one tick |
| 516 | timeBuffer.advance(); |
| 517 | for (int sqNum=0; sqNum < NumStages - 1; sqNum++) { |
| 518 | stageQueue[sqNum]->advance(); |
| 519 | } |
| 520 | activityRec.advance(); |
Korey Sewell | ea89099 | 2010-01-31 18:30:24 -0500 | [diff] [blame] | 521 | |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 522 | // Any squashed requests, events, or insts then remove them now |
| 523 | cleanUpRemovedReqs(); |
| 524 | cleanUpRemovedEvents(); |
| 525 | cleanUpRemovedInsts(); |
| 526 | |
| 527 | // Re-schedule CPU for this cycle |
| 528 | if (!tickEvent.scheduled()) { |
| 529 | if (_status == SwitchedOut) { |
| 530 | // increment stat |
Steve Reinhardt | 6f11879 | 2011-01-07 21:50:29 -0800 | [diff] [blame^] | 531 | lastRunningCycle = curTick(); |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 532 | } else if (!activityRec.active()) { |
| 533 | DPRINTF(InOrderCPU, "sleeping CPU.\n"); |
Steve Reinhardt | 6f11879 | 2011-01-07 21:50:29 -0800 | [diff] [blame^] | 534 | lastRunningCycle = curTick(); |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 535 | timesIdled++; |
| 536 | } else { |
Steve Reinhardt | 6f11879 | 2011-01-07 21:50:29 -0800 | [diff] [blame^] | 537 | //Tick next_tick = curTick() + cycles(1); |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 538 | //tickEvent.schedule(next_tick); |
Steve Reinhardt | 6f11879 | 2011-01-07 21:50:29 -0800 | [diff] [blame^] | 539 | schedule(&tickEvent, nextCycle(curTick() + 1)); |
Korey Sewell | 7b3b362 | 2010-01-31 17:18:15 -0500 | [diff] [blame] | 540 | DPRINTF(InOrderCPU, "Scheduled CPU for next tick @ %i.\n", |
Steve Reinhardt | 6f11879 | 2011-01-07 21:50:29 -0800 | [diff] [blame^] | 541 | nextCycle(curTick() + 1)); |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 542 | } |
| 543 | } |
| 544 | |
| 545 | tickThreadStats(); |
| 546 | updateThreadPriority(); |
| 547 | } |
| 548 | |
| 549 | |
| 550 | void |
| 551 | InOrderCPU::init() |
| 552 | { |
| 553 | if (!deferRegistration) { |
| 554 | registerThreadContexts(); |
| 555 | } |
| 556 | |
| 557 | // Set inSyscall so that the CPU doesn't squash when initially |
| 558 | // setting up registers. |
Nathan Binkert | 47877cf | 2009-05-26 09:23:13 -0700 | [diff] [blame] | 559 | for (ThreadID tid = 0; tid < numThreads; ++tid) |
| 560 | thread[tid]->inSyscall = true; |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 561 | |
Steve Reinhardt | 14808ec | 2009-04-17 16:54:58 -0700 | [diff] [blame] | 562 | #if FULL_SYSTEM |
Nathan Binkert | 47877cf | 2009-05-26 09:23:13 -0700 | [diff] [blame] | 563 | for (ThreadID tid = 0; tid < numThreads; tid++) { |
Steve Reinhardt | 14808ec | 2009-04-17 16:54:58 -0700 | [diff] [blame] | 564 | ThreadContext *src_tc = threadContexts[tid]; |
| 565 | TheISA::initCPU(src_tc, src_tc->contextId()); |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 566 | } |
Steve Reinhardt | 14808ec | 2009-04-17 16:54:58 -0700 | [diff] [blame] | 567 | #endif |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 568 | |
| 569 | // Clear inSyscall. |
Nathan Binkert | 47877cf | 2009-05-26 09:23:13 -0700 | [diff] [blame] | 570 | for (ThreadID tid = 0; tid < numThreads; ++tid) |
| 571 | thread[tid]->inSyscall = false; |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 572 | |
| 573 | // Call Initializiation Routine for Resource Pool |
| 574 | resPool->init(); |
| 575 | } |
| 576 | |
| 577 | void |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 578 | InOrderCPU::reset() |
| 579 | { |
Gabe Black | 32daf6f | 2009-07-08 23:02:20 -0700 | [diff] [blame] | 580 | for (int i = 0; i < numThreads; i++) { |
| 581 | isa[i].reset(coreType, numThreads, |
Korey Sewell | d9eaa2f | 2010-01-31 18:26:40 -0500 | [diff] [blame] | 582 | 1/*numVirtProcs*/, dynamic_cast<BaseCPU*>(this)); |
Gabe Black | 32daf6f | 2009-07-08 23:02:20 -0700 | [diff] [blame] | 583 | } |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 584 | } |
| 585 | |
| 586 | Port* |
| 587 | InOrderCPU::getPort(const std::string &if_name, int idx) |
| 588 | { |
| 589 | return resPool->getPort(if_name, idx); |
| 590 | } |
| 591 | |
Korey Sewell | badb238 | 2009-09-15 01:44:48 -0400 | [diff] [blame] | 592 | #if FULL_SYSTEM |
| 593 | Fault |
| 594 | InOrderCPU::hwrei(ThreadID tid) |
| 595 | { |
| 596 | panic("hwrei: Unimplemented"); |
| 597 | |
| 598 | return NoFault; |
| 599 | } |
| 600 | |
| 601 | |
| 602 | bool |
| 603 | InOrderCPU::simPalCheck(int palFunc, ThreadID tid) |
| 604 | { |
| 605 | panic("simPalCheck: Unimplemented"); |
| 606 | |
| 607 | return true; |
| 608 | } |
| 609 | |
| 610 | |
| 611 | Fault |
| 612 | InOrderCPU::getInterrupts() |
| 613 | { |
| 614 | // Check if there are any outstanding interrupts |
| 615 | return this->interrupts->getInterrupt(this->threadContexts[0]); |
| 616 | } |
| 617 | |
| 618 | |
| 619 | void |
| 620 | InOrderCPU::processInterrupts(Fault interrupt) |
| 621 | { |
| 622 | // Check for interrupts here. For now can copy the code that |
| 623 | // exists within isa_fullsys_traits.hh. Also assume that thread 0 |
| 624 | // is the one that handles the interrupts. |
| 625 | // @todo: Possibly consolidate the interrupt checking code. |
| 626 | // @todo: Allow other threads to handle interrupts. |
| 627 | |
| 628 | assert(interrupt != NoFault); |
| 629 | this->interrupts->updateIntrInfo(this->threadContexts[0]); |
| 630 | |
| 631 | DPRINTF(InOrderCPU, "Interrupt %s being handled\n", interrupt->name()); |
Gabe Black | ab8d7ee | 2010-09-20 02:46:42 -0700 | [diff] [blame] | 632 | static StaticInstPtr dummyStatic(TheISA::NoopMachInst, 0); |
| 633 | static DynInstPtr dummyDyn = new Impl::DynInst(dummyStatic); |
| 634 | this->trap(interrupt, dummyDyn); |
Korey Sewell | badb238 | 2009-09-15 01:44:48 -0400 | [diff] [blame] | 635 | } |
| 636 | |
| 637 | |
| 638 | void |
| 639 | InOrderCPU::updateMemPorts() |
| 640 | { |
| 641 | // Update all ThreadContext's memory ports (Functional/Virtual |
| 642 | // Ports) |
| 643 | ThreadID size = thread.size(); |
| 644 | for (ThreadID i = 0; i < size; ++i) |
| 645 | thread[i]->connectMemPorts(thread[i]->getTC()); |
| 646 | } |
| 647 | #endif |
| 648 | |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 649 | void |
Gabe Black | 6833ca7 | 2010-09-13 19:26:03 -0700 | [diff] [blame] | 650 | InOrderCPU::trap(Fault fault, ThreadID tid, DynInstPtr inst, int delay) |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 651 | { |
Korey Sewell | db2b721 | 2009-05-12 15:01:16 -0400 | [diff] [blame] | 652 | //@ Squash Pipeline during TRAP |
Gabe Black | 6833ca7 | 2010-09-13 19:26:03 -0700 | [diff] [blame] | 653 | scheduleCpuEvent(Trap, fault, tid, inst, delay); |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 654 | } |
| 655 | |
| 656 | void |
Gabe Black | 6833ca7 | 2010-09-13 19:26:03 -0700 | [diff] [blame] | 657 | InOrderCPU::trapCPU(Fault fault, ThreadID tid, DynInstPtr inst) |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 658 | { |
Gabe Black | 6833ca7 | 2010-09-13 19:26:03 -0700 | [diff] [blame] | 659 | fault->invoke(tcBase(tid), inst->staticInst); |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 660 | } |
| 661 | |
Korey Sewell | eac5eac | 2010-01-31 18:26:13 -0500 | [diff] [blame] | 662 | void |
| 663 | InOrderCPU::squashFromMemStall(DynInstPtr inst, ThreadID tid, int delay) |
| 664 | { |
| 665 | scheduleCpuEvent(SquashFromMemStall, NoFault, tid, inst, delay); |
| 666 | } |
| 667 | |
| 668 | |
| 669 | void |
Korey Sewell | f95430d | 2010-06-24 15:34:12 -0400 | [diff] [blame] | 670 | InOrderCPU::squashDueToMemStall(int stage_num, InstSeqNum seq_num, |
| 671 | ThreadID tid) |
Korey Sewell | eac5eac | 2010-01-31 18:26:13 -0500 | [diff] [blame] | 672 | { |
| 673 | DPRINTF(InOrderCPU, "Squashing Pipeline Stages Due to Memory Stall...\n"); |
| 674 | |
| 675 | // Squash all instructions in each stage including |
| 676 | // instruction that caused the squash (seq_num - 1) |
| 677 | // NOTE: The stage bandwidth needs to be cleared so thats why |
| 678 | // the stalling instruction is squashed as well. The stalled |
| 679 | // instruction is previously placed in another intermediate buffer |
| 680 | // while it's stall is being handled. |
| 681 | InstSeqNum squash_seq_num = seq_num - 1; |
| 682 | |
| 683 | for (int stNum=stage_num; stNum >= 0 ; stNum--) { |
| 684 | pipelineStage[stNum]->squashDueToMemStall(squash_seq_num, tid); |
| 685 | } |
| 686 | } |
| 687 | |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 688 | void |
| 689 | InOrderCPU::scheduleCpuEvent(CPUEventType c_event, Fault fault, |
Korey Sewell | d8e0935 | 2010-01-31 18:26:03 -0500 | [diff] [blame] | 690 | ThreadID tid, DynInstPtr inst, |
Korey Sewell | 4a945aa | 2010-01-31 18:26:26 -0500 | [diff] [blame] | 691 | unsigned delay, unsigned event_pri_offset) |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 692 | { |
Korey Sewell | 4a945aa | 2010-01-31 18:26:26 -0500 | [diff] [blame] | 693 | CPUEvent *cpu_event = new CPUEvent(this, c_event, fault, tid, inst, |
| 694 | event_pri_offset); |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 695 | |
Steve Reinhardt | 6f11879 | 2011-01-07 21:50:29 -0800 | [diff] [blame^] | 696 | Tick sked_tick = nextCycle(curTick() + ticks(delay)); |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 697 | if (delay >= 0) { |
Korey Sewell | 4a945aa | 2010-01-31 18:26:26 -0500 | [diff] [blame] | 698 | DPRINTF(InOrderCPU, "Scheduling CPU Event (%s) for cycle %i, [tid:%i].\n", |
Steve Reinhardt | 6f11879 | 2011-01-07 21:50:29 -0800 | [diff] [blame^] | 699 | eventNames[c_event], curTick() + delay, tid); |
Steve Reinhardt | 214cc0f | 2011-01-07 21:50:29 -0800 | [diff] [blame] | 700 | schedule(cpu_event, sked_tick); |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 701 | } else { |
| 702 | cpu_event->process(); |
| 703 | cpuEventRemoveList.push(cpu_event); |
| 704 | } |
| 705 | |
| 706 | // Broadcast event to the Resource Pool |
Korey Sewell | e1fcc64 | 2010-01-31 18:26:32 -0500 | [diff] [blame] | 707 | // Need to reset tid just in case this is a dummy instruction |
| 708 | inst->setTid(tid); |
Korey Sewell | d8e0935 | 2010-01-31 18:26:03 -0500 | [diff] [blame] | 709 | resPool->scheduleEvent(c_event, inst, 0, 0, tid); |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 710 | } |
| 711 | |
Korey Sewell | 96b493d | 2010-01-31 18:26:47 -0500 | [diff] [blame] | 712 | bool |
Nathan Binkert | 47877cf | 2009-05-26 09:23:13 -0700 | [diff] [blame] | 713 | InOrderCPU::isThreadActive(ThreadID tid) |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 714 | { |
Nathan Binkert | 47877cf | 2009-05-26 09:23:13 -0700 | [diff] [blame] | 715 | list<ThreadID>::iterator isActive = |
| 716 | std::find(activeThreads.begin(), activeThreads.end(), tid); |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 717 | |
| 718 | return (isActive != activeThreads.end()); |
| 719 | } |
| 720 | |
Korey Sewell | 96b493d | 2010-01-31 18:26:47 -0500 | [diff] [blame] | 721 | bool |
| 722 | InOrderCPU::isThreadReady(ThreadID tid) |
| 723 | { |
| 724 | list<ThreadID>::iterator isReady = |
| 725 | std::find(readyThreads.begin(), readyThreads.end(), tid); |
| 726 | |
| 727 | return (isReady != readyThreads.end()); |
| 728 | } |
| 729 | |
| 730 | bool |
| 731 | InOrderCPU::isThreadSuspended(ThreadID tid) |
| 732 | { |
| 733 | list<ThreadID>::iterator isSuspended = |
| 734 | std::find(suspendedThreads.begin(), suspendedThreads.end(), tid); |
| 735 | |
| 736 | return (isSuspended != suspendedThreads.end()); |
| 737 | } |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 738 | |
| 739 | void |
Korey Sewell | e1fcc64 | 2010-01-31 18:26:32 -0500 | [diff] [blame] | 740 | InOrderCPU::activateNextReadyThread() |
| 741 | { |
| 742 | if (readyThreads.size() >= 1) { |
| 743 | ThreadID ready_tid = readyThreads.front(); |
| 744 | |
| 745 | // Activate in Pipeline |
| 746 | activateThread(ready_tid); |
| 747 | |
| 748 | // Activate in Resource Pool |
| 749 | resPool->activateAll(ready_tid); |
| 750 | |
| 751 | list<ThreadID>::iterator ready_it = |
| 752 | std::find(readyThreads.begin(), readyThreads.end(), ready_tid); |
| 753 | readyThreads.erase(ready_it); |
| 754 | } else { |
| 755 | DPRINTF(InOrderCPU, |
Korey Sewell | 96b493d | 2010-01-31 18:26:47 -0500 | [diff] [blame] | 756 | "Attempting to activate new thread, but No Ready Threads to" |
| 757 | "activate.\n"); |
Korey Sewell | 90d3b45 | 2010-01-31 18:27:38 -0500 | [diff] [blame] | 758 | DPRINTF(InOrderCPU, |
| 759 | "Unable to switch to next active thread.\n"); |
Korey Sewell | e1fcc64 | 2010-01-31 18:26:32 -0500 | [diff] [blame] | 760 | } |
| 761 | } |
| 762 | |
| 763 | void |
Nathan Binkert | 47877cf | 2009-05-26 09:23:13 -0700 | [diff] [blame] | 764 | InOrderCPU::activateThread(ThreadID tid) |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 765 | { |
Korey Sewell | 96b493d | 2010-01-31 18:26:47 -0500 | [diff] [blame] | 766 | if (isThreadSuspended(tid)) { |
| 767 | DPRINTF(InOrderCPU, |
| 768 | "Removing [tid:%i] from suspended threads list.\n", tid); |
| 769 | |
| 770 | list<ThreadID>::iterator susp_it = |
| 771 | std::find(suspendedThreads.begin(), suspendedThreads.end(), |
| 772 | tid); |
| 773 | suspendedThreads.erase(susp_it); |
| 774 | } |
| 775 | |
Korey Sewell | e1fcc64 | 2010-01-31 18:26:32 -0500 | [diff] [blame] | 776 | if (threadModel == SwitchOnCacheMiss && |
| 777 | numActiveThreads() == 1) { |
| 778 | DPRINTF(InOrderCPU, |
Korey Sewell | 96b493d | 2010-01-31 18:26:47 -0500 | [diff] [blame] | 779 | "Ignoring activation of [tid:%i], since [tid:%i] is " |
| 780 | "already running.\n", tid, activeThreadId()); |
| 781 | |
Korey Sewell | 90d3b45 | 2010-01-31 18:27:38 -0500 | [diff] [blame] | 782 | DPRINTF(InOrderCPU,"Placing [tid:%i] on ready threads list\n", |
Korey Sewell | 96b493d | 2010-01-31 18:26:47 -0500 | [diff] [blame] | 783 | tid); |
Korey Sewell | e1fcc64 | 2010-01-31 18:26:32 -0500 | [diff] [blame] | 784 | |
| 785 | readyThreads.push_back(tid); |
| 786 | |
Korey Sewell | 96b493d | 2010-01-31 18:26:47 -0500 | [diff] [blame] | 787 | } else if (!isThreadActive(tid)) { |
Nathan Binkert | 47877cf | 2009-05-26 09:23:13 -0700 | [diff] [blame] | 788 | DPRINTF(InOrderCPU, |
Korey Sewell | 96b493d | 2010-01-31 18:26:47 -0500 | [diff] [blame] | 789 | "Adding [tid:%i] to active threads list.\n", tid); |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 790 | activeThreads.push_back(tid); |
Korey Sewell | 96b493d | 2010-01-31 18:26:47 -0500 | [diff] [blame] | 791 | |
Korey Sewell | 90d3b45 | 2010-01-31 18:27:38 -0500 | [diff] [blame] | 792 | activateThreadInPipeline(tid); |
Korey Sewell | 069b38c | 2010-01-31 18:27:58 -0500 | [diff] [blame] | 793 | |
Steve Reinhardt | 6f11879 | 2011-01-07 21:50:29 -0800 | [diff] [blame^] | 794 | thread[tid]->lastActivate = curTick(); |
Korey Sewell | 069b38c | 2010-01-31 18:27:58 -0500 | [diff] [blame] | 795 | |
Korey Sewell | b4e0ef7 | 2010-01-31 18:28:12 -0500 | [diff] [blame] | 796 | tcBase(tid)->setStatus(ThreadContext::Active); |
| 797 | |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 798 | wakeCPU(); |
Korey Sewell | 0b29c2d | 2010-01-31 18:28:59 -0500 | [diff] [blame] | 799 | |
| 800 | numCtxtSwitches++; |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 801 | } |
| 802 | } |
| 803 | |
| 804 | void |
Korey Sewell | 90d3b45 | 2010-01-31 18:27:38 -0500 | [diff] [blame] | 805 | InOrderCPU::activateThreadInPipeline(ThreadID tid) |
| 806 | { |
| 807 | for (int stNum=0; stNum < NumStages; stNum++) { |
| 808 | pipelineStage[stNum]->activateThread(tid); |
| 809 | } |
| 810 | } |
| 811 | |
| 812 | void |
Korey Sewell | d9eaa2f | 2010-01-31 18:26:40 -0500 | [diff] [blame] | 813 | InOrderCPU::deactivateContext(ThreadID tid, int delay) |
| 814 | { |
| 815 | DPRINTF(InOrderCPU,"[tid:%i]: Deactivating ...\n", tid); |
| 816 | |
Korey Sewell | 1a89e8f | 2010-01-31 18:29:59 -0500 | [diff] [blame] | 817 | scheduleCpuEvent(DeactivateThread, NoFault, tid, dummyInst[tid], delay); |
Korey Sewell | d9eaa2f | 2010-01-31 18:26:40 -0500 | [diff] [blame] | 818 | |
| 819 | // Be sure to signal that there's some activity so the CPU doesn't |
| 820 | // deschedule itself. |
| 821 | activityRec.activity(); |
| 822 | |
| 823 | _status = Running; |
| 824 | } |
| 825 | |
| 826 | void |
Nathan Binkert | 47877cf | 2009-05-26 09:23:13 -0700 | [diff] [blame] | 827 | InOrderCPU::deactivateThread(ThreadID tid) |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 828 | { |
| 829 | DPRINTF(InOrderCPU, "[tid:%i]: Calling deactivate thread.\n", tid); |
| 830 | |
| 831 | if (isThreadActive(tid)) { |
| 832 | DPRINTF(InOrderCPU,"[tid:%i]: Removing from active threads list\n", |
| 833 | tid); |
Nathan Binkert | 47877cf | 2009-05-26 09:23:13 -0700 | [diff] [blame] | 834 | list<ThreadID>::iterator thread_it = |
| 835 | std::find(activeThreads.begin(), activeThreads.end(), tid); |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 836 | |
| 837 | removePipelineStalls(*thread_it); |
| 838 | |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 839 | activeThreads.erase(thread_it); |
Korey Sewell | b4e0ef7 | 2010-01-31 18:28:12 -0500 | [diff] [blame] | 840 | |
| 841 | // Ideally, this should be triggered from the |
| 842 | // suspendContext/Thread functions |
| 843 | tcBase(tid)->setStatus(ThreadContext::Suspended); |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 844 | } |
Korey Sewell | 96b493d | 2010-01-31 18:26:47 -0500 | [diff] [blame] | 845 | |
| 846 | assert(!isThreadActive(tid)); |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 847 | } |
| 848 | |
| 849 | void |
Nathan Binkert | 47877cf | 2009-05-26 09:23:13 -0700 | [diff] [blame] | 850 | InOrderCPU::removePipelineStalls(ThreadID tid) |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 851 | { |
| 852 | DPRINTF(InOrderCPU,"[tid:%i]: Removing all pipeline stalls\n", |
| 853 | tid); |
| 854 | |
| 855 | for (int stNum = 0; stNum < NumStages ; stNum++) { |
| 856 | pipelineStage[stNum]->removeStalls(tid); |
| 857 | } |
| 858 | |
| 859 | } |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 860 | |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 861 | void |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 862 | InOrderCPU::updateThreadPriority() |
| 863 | { |
| 864 | if (activeThreads.size() > 1) |
| 865 | { |
| 866 | //DEFAULT TO ROUND ROBIN SCHEME |
| 867 | //e.g. Move highest priority to end of thread list |
Nathan Binkert | 47877cf | 2009-05-26 09:23:13 -0700 | [diff] [blame] | 868 | list<ThreadID>::iterator list_begin = activeThreads.begin(); |
| 869 | list<ThreadID>::iterator list_end = activeThreads.end(); |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 870 | |
| 871 | unsigned high_thread = *list_begin; |
| 872 | |
| 873 | activeThreads.erase(list_begin); |
| 874 | |
| 875 | activeThreads.push_back(high_thread); |
| 876 | } |
| 877 | } |
| 878 | |
| 879 | inline void |
| 880 | InOrderCPU::tickThreadStats() |
| 881 | { |
| 882 | /** Keep track of cycles that each thread is active */ |
Nathan Binkert | 47877cf | 2009-05-26 09:23:13 -0700 | [diff] [blame] | 883 | list<ThreadID>::iterator thread_it = activeThreads.begin(); |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 884 | while (thread_it != activeThreads.end()) { |
| 885 | threadCycles[*thread_it]++; |
| 886 | thread_it++; |
| 887 | } |
| 888 | |
| 889 | // Keep track of cycles where SMT is active |
| 890 | if (activeThreads.size() > 1) { |
| 891 | smtCycles++; |
| 892 | } |
| 893 | } |
| 894 | |
| 895 | void |
Nathan Binkert | 47877cf | 2009-05-26 09:23:13 -0700 | [diff] [blame] | 896 | InOrderCPU::activateContext(ThreadID tid, int delay) |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 897 | { |
| 898 | DPRINTF(InOrderCPU,"[tid:%i]: Activating ...\n", tid); |
| 899 | |
Korey Sewell | 1a89e8f | 2010-01-31 18:29:59 -0500 | [diff] [blame] | 900 | |
| 901 | scheduleCpuEvent(ActivateThread, NoFault, tid, dummyInst[tid], delay); |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 902 | |
| 903 | // Be sure to signal that there's some activity so the CPU doesn't |
| 904 | // deschedule itself. |
| 905 | activityRec.activity(); |
| 906 | |
| 907 | _status = Running; |
| 908 | } |
| 909 | |
Korey Sewell | e1fcc64 | 2010-01-31 18:26:32 -0500 | [diff] [blame] | 910 | void |
| 911 | InOrderCPU::activateNextReadyContext(int delay) |
| 912 | { |
| 913 | DPRINTF(InOrderCPU,"Activating next ready thread\n"); |
| 914 | |
| 915 | // NOTE: Add 5 to the event priority so that we always activate |
| 916 | // threads after we've finished deactivating, squashing,etc. |
| 917 | // other threads |
Korey Sewell | 1a89e8f | 2010-01-31 18:29:59 -0500 | [diff] [blame] | 918 | scheduleCpuEvent(ActivateNextReadyThread, NoFault, 0/*tid*/, dummyInst[0], |
Korey Sewell | e1fcc64 | 2010-01-31 18:26:32 -0500 | [diff] [blame] | 919 | delay, 5); |
| 920 | |
| 921 | // Be sure to signal that there's some activity so the CPU doesn't |
| 922 | // deschedule itself. |
| 923 | activityRec.activity(); |
| 924 | |
| 925 | _status = Running; |
| 926 | } |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 927 | |
| 928 | void |
Korey Sewell | d9eaa2f | 2010-01-31 18:26:40 -0500 | [diff] [blame] | 929 | InOrderCPU::haltContext(ThreadID tid, int delay) |
| 930 | { |
Korey Sewell | 5e0b833 | 2010-01-31 18:28:05 -0500 | [diff] [blame] | 931 | DPRINTF(InOrderCPU, "[tid:%i]: Calling Halt Context...\n", tid); |
| 932 | |
Korey Sewell | 1a89e8f | 2010-01-31 18:29:59 -0500 | [diff] [blame] | 933 | scheduleCpuEvent(HaltThread, NoFault, tid, dummyInst[tid], delay); |
Korey Sewell | 5e0b833 | 2010-01-31 18:28:05 -0500 | [diff] [blame] | 934 | |
| 935 | activityRec.activity(); |
| 936 | } |
| 937 | |
| 938 | void |
| 939 | InOrderCPU::haltThread(ThreadID tid) |
| 940 | { |
| 941 | DPRINTF(InOrderCPU, "[tid:%i]: Placing on Halted Threads List...\n", tid); |
| 942 | deactivateThread(tid); |
| 943 | squashThreadInPipeline(tid); |
| 944 | haltedThreads.push_back(tid); |
| 945 | |
Korey Sewell | b4e0ef7 | 2010-01-31 18:28:12 -0500 | [diff] [blame] | 946 | tcBase(tid)->setStatus(ThreadContext::Halted); |
| 947 | |
Korey Sewell | 5e0b833 | 2010-01-31 18:28:05 -0500 | [diff] [blame] | 948 | if (threadModel == SwitchOnCacheMiss) { |
| 949 | activateNextReadyContext(); |
| 950 | } |
Korey Sewell | d9eaa2f | 2010-01-31 18:26:40 -0500 | [diff] [blame] | 951 | } |
| 952 | |
| 953 | void |
Nathan Binkert | 47877cf | 2009-05-26 09:23:13 -0700 | [diff] [blame] | 954 | InOrderCPU::suspendContext(ThreadID tid, int delay) |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 955 | { |
Korey Sewell | 1a89e8f | 2010-01-31 18:29:59 -0500 | [diff] [blame] | 956 | scheduleCpuEvent(SuspendThread, NoFault, tid, dummyInst[tid], delay); |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 957 | } |
| 958 | |
| 959 | void |
Nathan Binkert | 47877cf | 2009-05-26 09:23:13 -0700 | [diff] [blame] | 960 | InOrderCPU::suspendThread(ThreadID tid) |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 961 | { |
Korey Sewell | f95430d | 2010-06-24 15:34:12 -0400 | [diff] [blame] | 962 | DPRINTF(InOrderCPU, "[tid:%i]: Placing on Suspended Threads List...\n", |
| 963 | tid); |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 964 | deactivateThread(tid); |
Korey Sewell | e1fcc64 | 2010-01-31 18:26:32 -0500 | [diff] [blame] | 965 | suspendedThreads.push_back(tid); |
Steve Reinhardt | 6f11879 | 2011-01-07 21:50:29 -0800 | [diff] [blame^] | 966 | thread[tid]->lastSuspend = curTick(); |
Korey Sewell | b4e0ef7 | 2010-01-31 18:28:12 -0500 | [diff] [blame] | 967 | |
| 968 | tcBase(tid)->setStatus(ThreadContext::Suspended); |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 969 | } |
| 970 | |
| 971 | void |
Nathan Binkert | 47877cf | 2009-05-26 09:23:13 -0700 | [diff] [blame] | 972 | InOrderCPU::squashThreadInPipeline(ThreadID tid) |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 973 | { |
| 974 | //Squash all instructions in each stage |
| 975 | for (int stNum=NumStages - 1; stNum >= 0 ; stNum--) { |
| 976 | pipelineStage[stNum]->squash(0 /*seq_num*/, tid); |
| 977 | } |
| 978 | } |
| 979 | |
Korey Sewell | 1c8dfd9 | 2009-05-12 15:01:13 -0400 | [diff] [blame] | 980 | PipelineStage* |
| 981 | InOrderCPU::getPipeStage(int stage_num) |
| 982 | { |
| 983 | return pipelineStage[stage_num]; |
| 984 | } |
| 985 | |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 986 | uint64_t |
Nathan Binkert | 47877cf | 2009-05-26 09:23:13 -0700 | [diff] [blame] | 987 | InOrderCPU::readIntReg(int reg_idx, ThreadID tid) |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 988 | { |
Gabe Black | a480ba0 | 2009-07-08 23:02:20 -0700 | [diff] [blame] | 989 | return intRegs[tid][reg_idx]; |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 990 | } |
| 991 | |
| 992 | FloatReg |
Gabe Black | 25884a8 | 2009-07-08 23:02:20 -0700 | [diff] [blame] | 993 | InOrderCPU::readFloatReg(int reg_idx, ThreadID tid) |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 994 | { |
Gabe Black | 0cb180e | 2009-07-08 23:02:20 -0700 | [diff] [blame] | 995 | return floatRegs.f[tid][reg_idx]; |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 996 | } |
| 997 | |
| 998 | FloatRegBits |
Gabe Black | 25884a8 | 2009-07-08 23:02:20 -0700 | [diff] [blame] | 999 | InOrderCPU::readFloatRegBits(int reg_idx, ThreadID tid) |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1000 | {; |
Gabe Black | 0cb180e | 2009-07-08 23:02:20 -0700 | [diff] [blame] | 1001 | return floatRegs.i[tid][reg_idx]; |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1002 | } |
| 1003 | |
| 1004 | void |
Nathan Binkert | 47877cf | 2009-05-26 09:23:13 -0700 | [diff] [blame] | 1005 | InOrderCPU::setIntReg(int reg_idx, uint64_t val, ThreadID tid) |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1006 | { |
Gabe Black | a480ba0 | 2009-07-08 23:02:20 -0700 | [diff] [blame] | 1007 | intRegs[tid][reg_idx] = val; |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1008 | } |
| 1009 | |
| 1010 | |
| 1011 | void |
Gabe Black | 25884a8 | 2009-07-08 23:02:20 -0700 | [diff] [blame] | 1012 | InOrderCPU::setFloatReg(int reg_idx, FloatReg val, ThreadID tid) |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1013 | { |
Gabe Black | 0cb180e | 2009-07-08 23:02:20 -0700 | [diff] [blame] | 1014 | floatRegs.f[tid][reg_idx] = val; |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1015 | } |
| 1016 | |
| 1017 | |
| 1018 | void |
Gabe Black | 25884a8 | 2009-07-08 23:02:20 -0700 | [diff] [blame] | 1019 | InOrderCPU::setFloatRegBits(int reg_idx, FloatRegBits val, ThreadID tid) |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1020 | { |
Gabe Black | 0cb180e | 2009-07-08 23:02:20 -0700 | [diff] [blame] | 1021 | floatRegs.i[tid][reg_idx] = val; |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1022 | } |
| 1023 | |
| 1024 | uint64_t |
Nathan Binkert | 47877cf | 2009-05-26 09:23:13 -0700 | [diff] [blame] | 1025 | InOrderCPU::readRegOtherThread(unsigned reg_idx, ThreadID tid) |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1026 | { |
| 1027 | // If Default value is set, then retrieve target thread |
Nathan Binkert | 47877cf | 2009-05-26 09:23:13 -0700 | [diff] [blame] | 1028 | if (tid == InvalidThreadID) { |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1029 | tid = TheISA::getTargetThread(tcBase(tid)); |
| 1030 | } |
| 1031 | |
Korey Sewell | 7b3b362 | 2010-01-31 17:18:15 -0500 | [diff] [blame] | 1032 | if (reg_idx < FP_Base_DepTag) { |
| 1033 | // Integer Register File |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1034 | return readIntReg(reg_idx, tid); |
Korey Sewell | 7b3b362 | 2010-01-31 17:18:15 -0500 | [diff] [blame] | 1035 | } else if (reg_idx < Ctrl_Base_DepTag) { |
| 1036 | // Float Register File |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1037 | reg_idx -= FP_Base_DepTag; |
| 1038 | return readFloatRegBits(reg_idx, tid); |
| 1039 | } else { |
| 1040 | reg_idx -= Ctrl_Base_DepTag; |
| 1041 | return readMiscReg(reg_idx, tid); // Misc. Register File |
| 1042 | } |
| 1043 | } |
| 1044 | void |
Nathan Binkert | 47877cf | 2009-05-26 09:23:13 -0700 | [diff] [blame] | 1045 | InOrderCPU::setRegOtherThread(unsigned reg_idx, const MiscReg &val, |
| 1046 | ThreadID tid) |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1047 | { |
| 1048 | // If Default value is set, then retrieve target thread |
Nathan Binkert | 47877cf | 2009-05-26 09:23:13 -0700 | [diff] [blame] | 1049 | if (tid == InvalidThreadID) { |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1050 | tid = TheISA::getTargetThread(tcBase(tid)); |
| 1051 | } |
| 1052 | |
| 1053 | if (reg_idx < FP_Base_DepTag) { // Integer Register File |
| 1054 | setIntReg(reg_idx, val, tid); |
| 1055 | } else if (reg_idx < Ctrl_Base_DepTag) { // Float Register File |
| 1056 | reg_idx -= FP_Base_DepTag; |
| 1057 | setFloatRegBits(reg_idx, val, tid); |
| 1058 | } else { |
| 1059 | reg_idx -= Ctrl_Base_DepTag; |
| 1060 | setMiscReg(reg_idx, val, tid); // Misc. Register File |
| 1061 | } |
| 1062 | } |
| 1063 | |
| 1064 | MiscReg |
Nathan Binkert | 47877cf | 2009-05-26 09:23:13 -0700 | [diff] [blame] | 1065 | InOrderCPU::readMiscRegNoEffect(int misc_reg, ThreadID tid) |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1066 | { |
Gabe Black | 32daf6f | 2009-07-08 23:02:20 -0700 | [diff] [blame] | 1067 | return isa[tid].readMiscRegNoEffect(misc_reg); |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1068 | } |
| 1069 | |
| 1070 | MiscReg |
Nathan Binkert | 47877cf | 2009-05-26 09:23:13 -0700 | [diff] [blame] | 1071 | InOrderCPU::readMiscReg(int misc_reg, ThreadID tid) |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1072 | { |
Gabe Black | 32daf6f | 2009-07-08 23:02:20 -0700 | [diff] [blame] | 1073 | return isa[tid].readMiscReg(misc_reg, tcBase(tid)); |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1074 | } |
| 1075 | |
| 1076 | void |
Nathan Binkert | 47877cf | 2009-05-26 09:23:13 -0700 | [diff] [blame] | 1077 | InOrderCPU::setMiscRegNoEffect(int misc_reg, const MiscReg &val, ThreadID tid) |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1078 | { |
Gabe Black | 32daf6f | 2009-07-08 23:02:20 -0700 | [diff] [blame] | 1079 | isa[tid].setMiscRegNoEffect(misc_reg, val); |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1080 | } |
| 1081 | |
| 1082 | void |
Nathan Binkert | 47877cf | 2009-05-26 09:23:13 -0700 | [diff] [blame] | 1083 | InOrderCPU::setMiscReg(int misc_reg, const MiscReg &val, ThreadID tid) |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1084 | { |
Gabe Black | 32daf6f | 2009-07-08 23:02:20 -0700 | [diff] [blame] | 1085 | isa[tid].setMiscReg(misc_reg, val, tcBase(tid)); |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1086 | } |
| 1087 | |
| 1088 | |
| 1089 | InOrderCPU::ListIt |
| 1090 | InOrderCPU::addInst(DynInstPtr &inst) |
| 1091 | { |
Nathan Binkert | 47877cf | 2009-05-26 09:23:13 -0700 | [diff] [blame] | 1092 | ThreadID tid = inst->readTid(); |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1093 | |
| 1094 | instList[tid].push_back(inst); |
| 1095 | |
| 1096 | return --(instList[tid].end()); |
| 1097 | } |
| 1098 | |
Korey Sewell | 0b29c2d | 2010-01-31 18:28:59 -0500 | [diff] [blame] | 1099 | void |
| 1100 | InOrderCPU::updateContextSwitchStats() |
| 1101 | { |
| 1102 | // Set Average Stat Here, then reset to 0 |
| 1103 | instsPerCtxtSwitch = instsPerSwitch; |
| 1104 | instsPerSwitch = 0; |
| 1105 | } |
| 1106 | |
| 1107 | |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1108 | void |
Nathan Binkert | 47877cf | 2009-05-26 09:23:13 -0700 | [diff] [blame] | 1109 | InOrderCPU::instDone(DynInstPtr inst, ThreadID tid) |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1110 | { |
Korey Sewell | 7b3b362 | 2010-01-31 17:18:15 -0500 | [diff] [blame] | 1111 | // Set the CPU's PCs - This contributes to the precise state of the CPU |
Korey Sewell | 069b38c | 2010-01-31 18:27:58 -0500 | [diff] [blame] | 1112 | // which can be used when restoring a thread to the CPU after after any |
| 1113 | // type of context switching activity (fork, exception, etc.) |
Gabe Black | 6f4bd2c | 2010-10-31 00:07:20 -0700 | [diff] [blame] | 1114 | pcState(inst->pcState(), tid); |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1115 | |
Korey Sewell | 069b38c | 2010-01-31 18:27:58 -0500 | [diff] [blame] | 1116 | if (inst->isControl()) { |
| 1117 | thread[tid]->lastGradIsBranch = true; |
Gabe Black | 6f4bd2c | 2010-10-31 00:07:20 -0700 | [diff] [blame] | 1118 | thread[tid]->lastBranchPC = inst->pcState(); |
| 1119 | TheISA::advancePC(thread[tid]->lastBranchPC, inst->staticInst); |
Korey Sewell | 069b38c | 2010-01-31 18:27:58 -0500 | [diff] [blame] | 1120 | } else { |
| 1121 | thread[tid]->lastGradIsBranch = false; |
| 1122 | } |
| 1123 | |
| 1124 | |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1125 | // Finalize Trace Data For Instruction |
| 1126 | if (inst->traceData) { |
Steve Reinhardt | 6f11879 | 2011-01-07 21:50:29 -0800 | [diff] [blame^] | 1127 | //inst->traceData->setCycle(curTick()); |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1128 | inst->traceData->setFetchSeq(inst->seqNum); |
| 1129 | //inst->traceData->setCPSeq(cpu->tcBase(tid)->numInst); |
| 1130 | inst->traceData->dump(); |
| 1131 | delete inst->traceData; |
| 1132 | inst->traceData = NULL; |
| 1133 | } |
| 1134 | |
Korey Sewell | 0b29c2d | 2010-01-31 18:28:59 -0500 | [diff] [blame] | 1135 | // Increment active thread's instruction count |
| 1136 | instsPerSwitch++; |
| 1137 | |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1138 | // Increment thread-state's instruction count |
| 1139 | thread[tid]->numInst++; |
| 1140 | |
| 1141 | // Increment thread-state's instruction stats |
| 1142 | thread[tid]->numInsts++; |
| 1143 | |
| 1144 | // Count committed insts per thread stats |
| 1145 | committedInsts[tid]++; |
| 1146 | |
| 1147 | // Count total insts committed stat |
| 1148 | totalCommittedInsts++; |
| 1149 | |
| 1150 | // Count SMT-committed insts per thread stat |
| 1151 | if (numActiveThreads() > 1) { |
| 1152 | smtCommittedInsts[tid]++; |
| 1153 | } |
| 1154 | |
Korey Sewell | 9f0d8f2 | 2010-06-23 18:18:20 -0400 | [diff] [blame] | 1155 | // Instruction-Mix Stats |
| 1156 | if (inst->isLoad()) { |
| 1157 | comLoads++; |
| 1158 | } else if (inst->isStore()) { |
| 1159 | comStores++; |
| 1160 | } else if (inst->isControl()) { |
| 1161 | comBranches++; |
| 1162 | } else if (inst->isNop()) { |
| 1163 | comNops++; |
| 1164 | } else if (inst->isNonSpeculative()) { |
| 1165 | comNonSpec++; |
| 1166 | } else if (inst->isInteger()) { |
| 1167 | comInts++; |
| 1168 | } else if (inst->isFloating()) { |
| 1169 | comFloats++; |
| 1170 | } |
| 1171 | |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1172 | // Check for instruction-count-based events. |
| 1173 | comInstEventQueue[tid]->serviceEvents(thread[tid]->numInst); |
| 1174 | |
| 1175 | // Broadcast to other resources an instruction |
| 1176 | // has been completed |
Korey Sewell | 7b3b362 | 2010-01-31 17:18:15 -0500 | [diff] [blame] | 1177 | resPool->scheduleEvent((CPUEventType)ResourcePool::InstGraduated, inst, |
Korey Sewell | 069b38c | 2010-01-31 18:27:58 -0500 | [diff] [blame] | 1178 | 0, 0, tid); |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1179 | |
| 1180 | // Finally, remove instruction from CPU |
| 1181 | removeInst(inst); |
| 1182 | } |
| 1183 | |
Korey Sewell | 9357e35 | 2010-01-31 18:30:48 -0500 | [diff] [blame] | 1184 | // currently unused function, but substitute repetitive code w/this function |
| 1185 | // call |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1186 | void |
| 1187 | InOrderCPU::addToRemoveList(DynInstPtr &inst) |
| 1188 | { |
| 1189 | removeInstsThisCycle = true; |
Korey Sewell | c7f6e26 | 2010-01-31 18:30:59 -0500 | [diff] [blame] | 1190 | if (!inst->isRemoveList()) { |
Gabe Black | 6f4bd2c | 2010-10-31 00:07:20 -0700 | [diff] [blame] | 1191 | DPRINTF(InOrderCPU, "Pushing instruction [tid:%i] PC %s " |
Korey Sewell | c7f6e26 | 2010-01-31 18:30:59 -0500 | [diff] [blame] | 1192 | "[sn:%lli] to remove list\n", |
Gabe Black | 6f4bd2c | 2010-10-31 00:07:20 -0700 | [diff] [blame] | 1193 | inst->threadNumber, inst->pcState(), inst->seqNum); |
Korey Sewell | c7f6e26 | 2010-01-31 18:30:59 -0500 | [diff] [blame] | 1194 | inst->setRemoveList(); |
| 1195 | removeList.push(inst->getInstListIt()); |
| 1196 | } else { |
Gabe Black | 6f4bd2c | 2010-10-31 00:07:20 -0700 | [diff] [blame] | 1197 | DPRINTF(InOrderCPU, "Ignoring instruction removal for [tid:%i] PC %s " |
Korey Sewell | c7f6e26 | 2010-01-31 18:30:59 -0500 | [diff] [blame] | 1198 | "[sn:%lli], already remove list\n", |
Gabe Black | 6f4bd2c | 2010-10-31 00:07:20 -0700 | [diff] [blame] | 1199 | inst->threadNumber, inst->pcState(), inst->seqNum); |
Korey Sewell | c7f6e26 | 2010-01-31 18:30:59 -0500 | [diff] [blame] | 1200 | } |
| 1201 | |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1202 | } |
| 1203 | |
| 1204 | void |
| 1205 | InOrderCPU::removeInst(DynInstPtr &inst) |
| 1206 | { |
Gabe Black | 6f4bd2c | 2010-10-31 00:07:20 -0700 | [diff] [blame] | 1207 | DPRINTF(InOrderCPU, "Removing graduated instruction [tid:%i] PC %s " |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1208 | "[sn:%lli]\n", |
Gabe Black | 6f4bd2c | 2010-10-31 00:07:20 -0700 | [diff] [blame] | 1209 | inst->threadNumber, inst->pcState(), inst->seqNum); |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1210 | |
| 1211 | removeInstsThisCycle = true; |
| 1212 | |
| 1213 | // Remove the instruction. |
Korey Sewell | c7f6e26 | 2010-01-31 18:30:59 -0500 | [diff] [blame] | 1214 | if (!inst->isRemoveList()) { |
Gabe Black | 6f4bd2c | 2010-10-31 00:07:20 -0700 | [diff] [blame] | 1215 | DPRINTF(InOrderCPU, "Pushing instruction [tid:%i] PC %s " |
Korey Sewell | c7f6e26 | 2010-01-31 18:30:59 -0500 | [diff] [blame] | 1216 | "[sn:%lli] to remove list\n", |
Gabe Black | 6f4bd2c | 2010-10-31 00:07:20 -0700 | [diff] [blame] | 1217 | inst->threadNumber, inst->pcState(), inst->seqNum); |
Korey Sewell | c7f6e26 | 2010-01-31 18:30:59 -0500 | [diff] [blame] | 1218 | inst->setRemoveList(); |
| 1219 | removeList.push(inst->getInstListIt()); |
| 1220 | } else { |
Gabe Black | 6f4bd2c | 2010-10-31 00:07:20 -0700 | [diff] [blame] | 1221 | DPRINTF(InOrderCPU, "Ignoring instruction removal for [tid:%i] PC %s " |
Korey Sewell | c7f6e26 | 2010-01-31 18:30:59 -0500 | [diff] [blame] | 1222 | "[sn:%lli], already on remove list\n", |
Gabe Black | 6f4bd2c | 2010-10-31 00:07:20 -0700 | [diff] [blame] | 1223 | inst->threadNumber, inst->pcState(), inst->seqNum); |
Korey Sewell | c7f6e26 | 2010-01-31 18:30:59 -0500 | [diff] [blame] | 1224 | } |
Korey Sewell | 9357e35 | 2010-01-31 18:30:48 -0500 | [diff] [blame] | 1225 | |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1226 | } |
| 1227 | |
| 1228 | void |
Nathan Binkert | 47877cf | 2009-05-26 09:23:13 -0700 | [diff] [blame] | 1229 | InOrderCPU::removeInstsUntil(const InstSeqNum &seq_num, ThreadID tid) |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1230 | { |
| 1231 | //assert(!instList[tid].empty()); |
| 1232 | |
| 1233 | removeInstsThisCycle = true; |
| 1234 | |
| 1235 | ListIt inst_iter = instList[tid].end(); |
| 1236 | |
| 1237 | inst_iter--; |
| 1238 | |
Korey Sewell | 9357e35 | 2010-01-31 18:30:48 -0500 | [diff] [blame] | 1239 | DPRINTF(InOrderCPU, "Squashing instructions from CPU instruction " |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1240 | "list that are from [tid:%i] and above [sn:%lli] (end=%lli).\n", |
| 1241 | tid, seq_num, (*inst_iter)->seqNum); |
| 1242 | |
| 1243 | while ((*inst_iter)->seqNum > seq_num) { |
| 1244 | |
| 1245 | bool break_loop = (inst_iter == instList[tid].begin()); |
| 1246 | |
| 1247 | squashInstIt(inst_iter, tid); |
| 1248 | |
| 1249 | inst_iter--; |
| 1250 | |
| 1251 | if (break_loop) |
| 1252 | break; |
| 1253 | } |
| 1254 | } |
| 1255 | |
| 1256 | |
| 1257 | inline void |
Nathan Binkert | 47877cf | 2009-05-26 09:23:13 -0700 | [diff] [blame] | 1258 | InOrderCPU::squashInstIt(const ListIt &instIt, ThreadID tid) |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1259 | { |
| 1260 | if ((*instIt)->threadNumber == tid) { |
| 1261 | DPRINTF(InOrderCPU, "Squashing instruction, " |
Gabe Black | 6f4bd2c | 2010-10-31 00:07:20 -0700 | [diff] [blame] | 1262 | "[tid:%i] [sn:%lli] PC %s\n", |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1263 | (*instIt)->threadNumber, |
| 1264 | (*instIt)->seqNum, |
Gabe Black | 6f4bd2c | 2010-10-31 00:07:20 -0700 | [diff] [blame] | 1265 | (*instIt)->pcState()); |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1266 | |
| 1267 | (*instIt)->setSquashed(); |
| 1268 | |
Korey Sewell | c7f6e26 | 2010-01-31 18:30:59 -0500 | [diff] [blame] | 1269 | if (!(*instIt)->isRemoveList()) { |
Gabe Black | 6f4bd2c | 2010-10-31 00:07:20 -0700 | [diff] [blame] | 1270 | DPRINTF(InOrderCPU, "Pushing instruction [tid:%i] PC %s " |
Korey Sewell | c7f6e26 | 2010-01-31 18:30:59 -0500 | [diff] [blame] | 1271 | "[sn:%lli] to remove list\n", |
Gabe Black | 6f4bd2c | 2010-10-31 00:07:20 -0700 | [diff] [blame] | 1272 | (*instIt)->threadNumber, (*instIt)->pcState(), |
Korey Sewell | c7f6e26 | 2010-01-31 18:30:59 -0500 | [diff] [blame] | 1273 | (*instIt)->seqNum); |
| 1274 | (*instIt)->setRemoveList(); |
| 1275 | removeList.push(instIt); |
| 1276 | } else { |
Korey Sewell | f95430d | 2010-06-24 15:34:12 -0400 | [diff] [blame] | 1277 | DPRINTF(InOrderCPU, "Ignoring instruction removal for [tid:%i]" |
Gabe Black | 6f4bd2c | 2010-10-31 00:07:20 -0700 | [diff] [blame] | 1278 | " PC %s [sn:%lli], already on remove list\n", |
| 1279 | (*instIt)->threadNumber, (*instIt)->pcState(), |
Korey Sewell | c7f6e26 | 2010-01-31 18:30:59 -0500 | [diff] [blame] | 1280 | (*instIt)->seqNum); |
| 1281 | } |
| 1282 | |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1283 | } |
Korey Sewell | c7f6e26 | 2010-01-31 18:30:59 -0500 | [diff] [blame] | 1284 | |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1285 | } |
| 1286 | |
| 1287 | |
| 1288 | void |
| 1289 | InOrderCPU::cleanUpRemovedInsts() |
| 1290 | { |
| 1291 | while (!removeList.empty()) { |
| 1292 | DPRINTF(InOrderCPU, "Removing instruction, " |
Gabe Black | 6f4bd2c | 2010-10-31 00:07:20 -0700 | [diff] [blame] | 1293 | "[tid:%i] [sn:%lli] PC %s\n", |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1294 | (*removeList.front())->threadNumber, |
| 1295 | (*removeList.front())->seqNum, |
Gabe Black | 6f4bd2c | 2010-10-31 00:07:20 -0700 | [diff] [blame] | 1296 | (*removeList.front())->pcState()); |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1297 | |
| 1298 | DynInstPtr inst = *removeList.front(); |
Nathan Binkert | 47877cf | 2009-05-26 09:23:13 -0700 | [diff] [blame] | 1299 | ThreadID tid = inst->threadNumber; |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1300 | |
| 1301 | // Make Sure Resource Schedule Is Emptied Out |
| 1302 | ThePipeline::ResSchedule *inst_sched = &inst->resSched; |
| 1303 | while (!inst_sched->empty()) { |
Korey Sewell | 6bfd766 | 2010-06-25 17:42:34 -0400 | [diff] [blame] | 1304 | ScheduleEntry* sch_entry = inst_sched->top(); |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1305 | inst_sched->pop(); |
| 1306 | delete sch_entry; |
| 1307 | } |
| 1308 | |
| 1309 | // Remove From Register Dependency Map, If Necessary |
| 1310 | archRegDepMap[(*removeList.front())->threadNumber]. |
| 1311 | remove((*removeList.front())); |
| 1312 | |
| 1313 | |
| 1314 | // Clear if Non-Speculative |
| 1315 | if (inst->staticInst && |
| 1316 | inst->seqNum == nonSpecSeqNum[tid] && |
| 1317 | nonSpecInstActive[tid] == true) { |
| 1318 | nonSpecInstActive[tid] = false; |
| 1319 | } |
| 1320 | |
| 1321 | instList[tid].erase(removeList.front()); |
| 1322 | |
| 1323 | removeList.pop(); |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1324 | } |
| 1325 | |
| 1326 | removeInstsThisCycle = false; |
| 1327 | } |
| 1328 | |
| 1329 | void |
| 1330 | InOrderCPU::cleanUpRemovedReqs() |
| 1331 | { |
| 1332 | while (!reqRemoveList.empty()) { |
| 1333 | ResourceRequest *res_req = reqRemoveList.front(); |
| 1334 | |
Korey Sewell | 7695d4c | 2010-06-23 18:14:59 -0400 | [diff] [blame] | 1335 | DPRINTF(RefCount, "[tid:%i] [sn:%lli]: Removing Request " |
Korey Sewell | 9357e35 | 2010-01-31 18:30:48 -0500 | [diff] [blame] | 1336 | "[stage_num:%i] [res:%s] [slot:%i] [completed:%i].\n", |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1337 | res_req->inst->threadNumber, |
| 1338 | res_req->inst->seqNum, |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1339 | res_req->getStageNum(), |
| 1340 | res_req->res->name(), |
Korey Sewell | f95430d | 2010-06-24 15:34:12 -0400 | [diff] [blame] | 1341 | (res_req->isCompleted()) ? |
| 1342 | res_req->getComplSlot() : res_req->getSlot(), |
Korey Sewell | 9357e35 | 2010-01-31 18:30:48 -0500 | [diff] [blame] | 1343 | res_req->isCompleted()); |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1344 | |
| 1345 | reqRemoveList.pop(); |
| 1346 | |
| 1347 | delete res_req; |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1348 | } |
| 1349 | } |
| 1350 | |
| 1351 | void |
| 1352 | InOrderCPU::cleanUpRemovedEvents() |
| 1353 | { |
| 1354 | while (!cpuEventRemoveList.empty()) { |
| 1355 | Event *cpu_event = cpuEventRemoveList.front(); |
| 1356 | cpuEventRemoveList.pop(); |
| 1357 | delete cpu_event; |
| 1358 | } |
| 1359 | } |
| 1360 | |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1361 | |
| 1362 | void |
| 1363 | InOrderCPU::dumpInsts() |
| 1364 | { |
| 1365 | int num = 0; |
| 1366 | |
| 1367 | ListIt inst_list_it = instList[0].begin(); |
| 1368 | |
| 1369 | cprintf("Dumping Instruction List\n"); |
| 1370 | |
| 1371 | while (inst_list_it != instList[0].end()) { |
Gabe Black | 6f4bd2c | 2010-10-31 00:07:20 -0700 | [diff] [blame] | 1372 | cprintf("Instruction:%i\nPC:%s\n[tid:%i]\n[sn:%lli]\nIssued:%i\n" |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1373 | "Squashed:%i\n\n", |
Gabe Black | 6f4bd2c | 2010-10-31 00:07:20 -0700 | [diff] [blame] | 1374 | num, (*inst_list_it)->pcState(), |
| 1375 | (*inst_list_it)->threadNumber, |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1376 | (*inst_list_it)->seqNum, (*inst_list_it)->isIssued(), |
| 1377 | (*inst_list_it)->isSquashed()); |
| 1378 | inst_list_it++; |
| 1379 | ++num; |
| 1380 | } |
| 1381 | } |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1382 | |
| 1383 | void |
| 1384 | InOrderCPU::wakeCPU() |
| 1385 | { |
| 1386 | if (/*activityRec.active() || */tickEvent.scheduled()) { |
| 1387 | DPRINTF(Activity, "CPU already running.\n"); |
| 1388 | return; |
| 1389 | } |
| 1390 | |
| 1391 | DPRINTF(Activity, "Waking up CPU\n"); |
| 1392 | |
Steve Reinhardt | 6f11879 | 2011-01-07 21:50:29 -0800 | [diff] [blame^] | 1393 | Tick extra_cycles = tickToCycles((curTick() - 1) - lastRunningCycle); |
Korey Sewell | ffa9ecb | 2010-01-31 18:28:51 -0500 | [diff] [blame] | 1394 | |
| 1395 | idleCycles += extra_cycles; |
| 1396 | for (int stage_num = 0; stage_num < NumStages; stage_num++) { |
| 1397 | pipelineStage[stage_num]->idleCycles += extra_cycles; |
| 1398 | } |
| 1399 | |
| 1400 | numCycles += extra_cycles; |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1401 | |
Steve Reinhardt | 6f11879 | 2011-01-07 21:50:29 -0800 | [diff] [blame^] | 1402 | schedule(&tickEvent, nextCycle(curTick())); |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1403 | } |
| 1404 | |
Korey Sewell | badb238 | 2009-09-15 01:44:48 -0400 | [diff] [blame] | 1405 | #if FULL_SYSTEM |
| 1406 | |
| 1407 | void |
| 1408 | InOrderCPU::wakeup() |
| 1409 | { |
| 1410 | if (this->thread[0]->status() != ThreadContext::Suspended) |
| 1411 | return; |
| 1412 | |
| 1413 | this->wakeCPU(); |
| 1414 | |
| 1415 | DPRINTF(Quiesce, "Suspended Processor woken\n"); |
| 1416 | this->threadContexts[0]->activate(); |
| 1417 | } |
| 1418 | #endif |
| 1419 | |
| 1420 | #if !FULL_SYSTEM |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1421 | void |
Nathan Binkert | 47877cf | 2009-05-26 09:23:13 -0700 | [diff] [blame] | 1422 | InOrderCPU::syscall(int64_t callnum, ThreadID tid) |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1423 | { |
| 1424 | DPRINTF(InOrderCPU, "[tid:%i] Executing syscall().\n\n", tid); |
| 1425 | |
| 1426 | DPRINTF(Activity,"Activity: syscall() called.\n"); |
| 1427 | |
| 1428 | // Temporarily increase this by one to account for the syscall |
| 1429 | // instruction. |
| 1430 | ++(this->thread[tid]->funcExeInst); |
| 1431 | |
| 1432 | // Execute the actual syscall. |
| 1433 | this->thread[tid]->syscall(callnum); |
| 1434 | |
| 1435 | // Decrease funcExeInst by one as the normal commit will handle |
| 1436 | // incrementing it. |
| 1437 | --(this->thread[tid]->funcExeInst); |
| 1438 | |
| 1439 | // Clear Non-Speculative Block Variable |
| 1440 | nonSpecInstActive[tid] = false; |
| 1441 | } |
Korey Sewell | badb238 | 2009-09-15 01:44:48 -0400 | [diff] [blame] | 1442 | #endif |
Korey Sewell | 973d8b8 | 2009-02-10 15:49:29 -0800 | [diff] [blame] | 1443 | |
Korey Sewell | 5127ea2 | 2009-05-12 15:01:14 -0400 | [diff] [blame] | 1444 | TheISA::TLB* |
Korey Sewell | 1c8dfd9 | 2009-05-12 15:01:13 -0400 | [diff] [blame] | 1445 | InOrderCPU::getITBPtr() |
| 1446 | { |
Korey Sewell | db2b721 | 2009-05-12 15:01:16 -0400 | [diff] [blame] | 1447 | CacheUnit *itb_res = |
| 1448 | dynamic_cast<CacheUnit*>(resPool->getResource(fetchPortIdx)); |
Korey Sewell | 5127ea2 | 2009-05-12 15:01:14 -0400 | [diff] [blame] | 1449 | return itb_res->tlb(); |
Korey Sewell | 1c8dfd9 | 2009-05-12 15:01:13 -0400 | [diff] [blame] | 1450 | } |
| 1451 | |
| 1452 | |
Korey Sewell | 5127ea2 | 2009-05-12 15:01:14 -0400 | [diff] [blame] | 1453 | TheISA::TLB* |
Korey Sewell | 1c8dfd9 | 2009-05-12 15:01:13 -0400 | [diff] [blame] | 1454 | InOrderCPU::getDTBPtr() |
| 1455 | { |
Korey Sewell | db2b721 | 2009-05-12 15:01:16 -0400 | [diff] [blame] | 1456 | CacheUnit *dtb_res = |
| 1457 | dynamic_cast<CacheUnit*>(resPool->getResource(dataPortIdx)); |
Korey Sewell | 5127ea2 | 2009-05-12 15:01:14 -0400 | [diff] [blame] | 1458 | return dtb_res->tlb(); |
Korey Sewell | 1c8dfd9 | 2009-05-12 15:01:13 -0400 | [diff] [blame] | 1459 | } |
Korey Sewell | db2b721 | 2009-05-12 15:01:16 -0400 | [diff] [blame] | 1460 | |
Korey Sewell | db2b721 | 2009-05-12 15:01:16 -0400 | [diff] [blame] | 1461 | Fault |
Gabe Black | aa8c6e9 | 2010-08-13 06:16:02 -0700 | [diff] [blame] | 1462 | InOrderCPU::read(DynInstPtr inst, Addr addr, |
| 1463 | uint8_t *data, unsigned size, unsigned flags) |
Korey Sewell | db2b721 | 2009-05-12 15:01:16 -0400 | [diff] [blame] | 1464 | { |
| 1465 | //@TODO: Generalize name "CacheUnit" to "MemUnit" just in case |
| 1466 | // you want to run w/out caches? |
Korey Sewell | 7b3b362 | 2010-01-31 17:18:15 -0500 | [diff] [blame] | 1467 | CacheUnit *cache_res = |
| 1468 | dynamic_cast<CacheUnit*>(resPool->getResource(dataPortIdx)); |
Korey Sewell | db2b721 | 2009-05-12 15:01:16 -0400 | [diff] [blame] | 1469 | |
Gabe Black | aa8c6e9 | 2010-08-13 06:16:02 -0700 | [diff] [blame] | 1470 | return cache_res->read(inst, addr, data, size, flags); |
Korey Sewell | db2b721 | 2009-05-12 15:01:16 -0400 | [diff] [blame] | 1471 | } |
| 1472 | |
Korey Sewell | db2b721 | 2009-05-12 15:01:16 -0400 | [diff] [blame] | 1473 | Fault |
Gabe Black | aa8c6e9 | 2010-08-13 06:16:02 -0700 | [diff] [blame] | 1474 | InOrderCPU::write(DynInstPtr inst, uint8_t *data, unsigned size, |
| 1475 | Addr addr, unsigned flags, uint64_t *write_res) |
Korey Sewell | db2b721 | 2009-05-12 15:01:16 -0400 | [diff] [blame] | 1476 | { |
| 1477 | //@TODO: Generalize name "CacheUnit" to "MemUnit" just in case |
| 1478 | // you want to run w/out caches? |
| 1479 | CacheUnit *cache_res = |
| 1480 | dynamic_cast<CacheUnit*>(resPool->getResource(dataPortIdx)); |
Gabe Black | aa8c6e9 | 2010-08-13 06:16:02 -0700 | [diff] [blame] | 1481 | return cache_res->write(inst, data, size, addr, flags, write_res); |
Korey Sewell | db2b721 | 2009-05-12 15:01:16 -0400 | [diff] [blame] | 1482 | } |