blob: 3d7d713e8366a8d1fc976566e1c4c9ac89db2760 [file] [log] [blame]
Korey Sewell973d8b82009-02-10 15:49:29 -08001/*
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 Binkert47877cf2009-05-26 09:23:13 -070032#include <algorithm>
Steve Reinhardt14808ec2009-04-17 16:54:58 -070033
Korey Sewell973d8b82009-02-10 15:49:29 -080034#include "arch/utility.hh"
Nathan Binkert47877cf2009-05-26 09:23:13 -070035#include "config/full_system.hh"
Korey Sewell973d8b82009-02-10 15:49:29 -080036#include "cpu/exetrace.hh"
37#include "cpu/activity.hh"
38#include "cpu/simple_thread.hh"
39#include "cpu/thread_context.hh"
40#include "cpu/base.hh"
41#include "cpu/inorder/inorder_dyn_inst.hh"
42#include "cpu/inorder/thread_context.hh"
43#include "cpu/inorder/thread_state.hh"
44#include "cpu/inorder/cpu.hh"
45#include "params/InOrderCPU.hh"
46#include "cpu/inorder/pipeline_traits.hh"
47#include "cpu/inorder/first_stage.hh"
48#include "cpu/inorder/resources/resource_list.hh"
49#include "cpu/inorder/resource_pool.hh"
50#include "mem/translating_port.hh"
51#include "sim/process.hh"
Korey Sewell973d8b82009-02-10 15:49:29 -080052#include "sim/stat_control.hh"
Korey Sewell973d8b82009-02-10 15:49:29 -080053
54using namespace std;
55using namespace TheISA;
56using namespace ThePipeline;
57
58InOrderCPU::TickEvent::TickEvent(InOrderCPU *c)
59 : Event(CPU_Tick_Pri), cpu(c)
60{ }
61
62
63void
64InOrderCPU::TickEvent::process()
65{
66 cpu->tick();
67}
68
69
70const char *
71InOrderCPU::TickEvent::description()
72{
73 return "InOrderCPU tick event";
74}
75
76InOrderCPU::CPUEvent::CPUEvent(InOrderCPU *_cpu, CPUEventType e_type,
Nathan Binkert47877cf2009-05-26 09:23:13 -070077 Fault fault, ThreadID _tid, unsigned _vpe)
Korey Sewell973d8b82009-02-10 15:49:29 -080078 : Event(CPU_Tick_Pri), cpu(_cpu)
79{
80 setEvent(e_type, fault, _tid, _vpe);
81}
82
Korey Sewell3a057bd2009-05-12 15:01:16 -040083
84std::string InOrderCPU::eventNames[NumCPUEvents] =
85{
86 "ActivateThread",
87 "DeallocateThread",
88 "SuspendThread",
89 "DisableThreads",
90 "EnableThreads",
91 "DisableVPEs",
92 "EnableVPEs",
93 "Trap",
94 "InstGraduated",
95 "SquashAll",
96 "UpdatePCs"
97};
98
Korey Sewell973d8b82009-02-10 15:49:29 -080099void
100InOrderCPU::CPUEvent::process()
101{
102 switch (cpuEventType)
103 {
104 case ActivateThread:
105 cpu->activateThread(tid);
106 break;
107
108 //@TODO: Consider Implementing "Suspend Thread" as Separate from Deallocate
109 case SuspendThread: // Suspend & Deallocate are same for now.
110 //cpu->suspendThread(tid);
111 //break;
112 case DeallocateThread:
113 cpu->deallocateThread(tid);
114 break;
115
116 case EnableVPEs:
117 cpu->enableVPEs(vpe);
118 break;
119
120 case DisableVPEs:
121 cpu->disableVPEs(tid, vpe);
122 break;
123
124 case EnableThreads:
125 cpu->enableThreads(vpe);
126 break;
127
128 case DisableThreads:
129 cpu->disableThreads(tid, vpe);
130 break;
131
132 case Trap:
133 cpu->trapCPU(fault, tid);
134 break;
135
136 default:
137 fatal("Unrecognized Event Type %d", cpuEventType);
138 }
139
140 cpu->cpuEventRemoveList.push(this);
141}
142
143const char *
144InOrderCPU::CPUEvent::description()
145{
146 return "InOrderCPU event";
147}
148
149void
150InOrderCPU::CPUEvent::scheduleEvent(int delay)
151{
152 if (squashed())
153 mainEventQueue.reschedule(this,curTick + cpu->ticks(delay));
154 else if (!scheduled())
155 mainEventQueue.schedule(this,curTick + cpu->ticks(delay));
156}
157
158void
159InOrderCPU::CPUEvent::unscheduleEvent()
160{
161 if (scheduled())
162 squash();
163}
164
165InOrderCPU::InOrderCPU(Params *params)
166 : BaseCPU(params),
167 cpu_id(params->cpu_id),
Korey Sewell9e1dc7f2009-03-04 22:37:45 -0500168 coreType("default"),
169 _status(Idle),
Korey Sewell973d8b82009-02-10 15:49:29 -0800170 tickEvent(this),
171 miscRegFile(this),
172 timeBuffer(2 , 2),
173 removeInstsThisCycle(false),
174 activityRec(params->name, NumStages, 10, params->activity),
175 switchCount(0),
176 deferRegistration(false/*params->deferRegistration*/),
177 stageTracing(params->stageTracing),
Korey Sewell973d8b82009-02-10 15:49:29 -0800178 numVirtProcs(1)
179{
180 cpu_params = params;
181
182 resPool = new ResourcePool(this, params);
Korey Sewell973d8b82009-02-10 15:49:29 -0800183
Korey Sewell973d8b82009-02-10 15:49:29 -0800184 // Resize for Multithreading CPUs
185 thread.resize(numThreads);
186
Nathan Binkert6faf3772009-06-04 23:21:12 -0700187 ThreadID active_threads = params->workload.size();
Korey Sewell973d8b82009-02-10 15:49:29 -0800188
189 if (active_threads > MaxThreads) {
190 panic("Workload Size too large. Increase the 'MaxThreads'"
191 "in your InOrder implementation or "
192 "edit your workload size.");
193 }
194
195 // Bind the fetch & data ports from the resource pool.
196 fetchPortIdx = resPool->getPortIdx(params->fetchMemPort);
197 if (fetchPortIdx == 0) {
Korey Sewell1c8dfd92009-05-12 15:01:13 -0400198 fatal("Unable to find port to fetch instructions from.\n");
Korey Sewell973d8b82009-02-10 15:49:29 -0800199 }
200
201 dataPortIdx = resPool->getPortIdx(params->dataMemPort);
202 if (dataPortIdx == 0) {
Korey Sewell1c8dfd92009-05-12 15:01:13 -0400203 fatal("Unable to find port for data.\n");
Korey Sewell973d8b82009-02-10 15:49:29 -0800204 }
205
Nathan Binkert47877cf2009-05-26 09:23:13 -0700206 for (ThreadID tid = 0; tid < numThreads; ++tid) {
Nathan Binkert6faf3772009-06-04 23:21:12 -0700207 if (tid < (ThreadID)params->workload.size()) {
Korey Sewell30cd2d22009-03-04 13:17:08 -0500208 DPRINTF(InOrderCPU, "Workload[%i] process is %#x\n",
Nathan Binkert47877cf2009-05-26 09:23:13 -0700209 tid, this->thread[tid]);
210 this->thread[tid] =
211 new Thread(this, tid, params->workload[tid], tid);
Korey Sewell973d8b82009-02-10 15:49:29 -0800212 } else {
213 //Allocate Empty thread so M5 can use later
214 //when scheduling threads to CPU
Korey Sewell30cd2d22009-03-04 13:17:08 -0500215 Process* dummy_proc = params->workload[0];
Nathan Binkert47877cf2009-05-26 09:23:13 -0700216 this->thread[tid] = new Thread(this, tid, dummy_proc, tid);
Korey Sewell973d8b82009-02-10 15:49:29 -0800217 }
218
219 // Setup the TC that will serve as the interface to the threads/CPU.
220 InOrderThreadContext *tc = new InOrderThreadContext;
221 tc->cpu = this;
Nathan Binkert47877cf2009-05-26 09:23:13 -0700222 tc->thread = thread[tid];
Korey Sewell973d8b82009-02-10 15:49:29 -0800223
224 // Give the thread the TC.
Nathan Binkert47877cf2009-05-26 09:23:13 -0700225 thread[tid]->tc = tc;
226 thread[tid]->setFuncExeInst(0);
227 globalSeqNum[tid] = 1;
Korey Sewell973d8b82009-02-10 15:49:29 -0800228
229 // Add the TC to the CPU's list of TC's.
230 this->threadContexts.push_back(tc);
231 }
232
233 // Initialize TimeBuffer Stage Queues
Korey Sewell973d8b82009-02-10 15:49:29 -0800234 for (int stNum=0; stNum < NumStages - 1; stNum++) {
235 stageQueue[stNum] = new StageQueue(NumStages, NumStages);
Korey Sewell846f9532009-03-04 13:16:49 -0500236 stageQueue[stNum]->id(stNum);
Korey Sewell973d8b82009-02-10 15:49:29 -0800237 }
238
239
240 // Set Up Pipeline Stages
241 for (int stNum=0; stNum < NumStages; stNum++) {
242 if (stNum == 0)
243 pipelineStage[stNum] = new FirstStage(params, stNum);
244 else
245 pipelineStage[stNum] = new PipelineStage(params, stNum);
246
247 pipelineStage[stNum]->setCPU(this);
248 pipelineStage[stNum]->setActiveThreads(&activeThreads);
249 pipelineStage[stNum]->setTimeBuffer(&timeBuffer);
250
251 // Take Care of 1st/Nth stages
252 if (stNum > 0)
253 pipelineStage[stNum]->setPrevStageQueue(stageQueue[stNum - 1]);
Korey Sewellf69b0182009-03-04 13:17:07 -0500254 if (stNum < NumStages - 1)
255 pipelineStage[stNum]->setNextStageQueue(stageQueue[stNum]);
Korey Sewell973d8b82009-02-10 15:49:29 -0800256 }
257
258 // Initialize thread specific variables
Nathan Binkert47877cf2009-05-26 09:23:13 -0700259 for (ThreadID tid = 0; tid < numThreads; tid++) {
Korey Sewell973d8b82009-02-10 15:49:29 -0800260 archRegDepMap[tid].setCPU(this);
261
262 nonSpecInstActive[tid] = false;
263 nonSpecSeqNum[tid] = 0;
264
265 squashSeqNum[tid] = MaxAddr;
266 lastSquashCycle[tid] = 0;
267
268 intRegFile[tid].clear();
269 floatRegFile[tid].clear();
270 }
271
272 // Update miscRegFile if necessary
273 if (numThreads > 1) {
274 miscRegFile.expandForMultithreading(numThreads, numVirtProcs);
275 }
276
277 miscRegFile.clear();
278
279 lastRunningCycle = curTick;
280 contextSwitch = false;
281
282 // Define dummy instructions and resource requests to be used.
283 DynInstPtr dummyBufferInst = new InOrderDynInst(this, NULL, 0, 0);
284 dummyReq = new ResourceRequest(NULL, NULL, 0, 0, 0, 0);
285
286 // Reset CPU to reset state.
287#if FULL_SYSTEM
288 Fault resetFault = new ResetFault();
289 resetFault->invoke(tcBase());
290#else
291 reset();
292#endif
293
294 // Schedule First Tick Event, CPU will reschedule itself from here on out.
295 scheduleTickEvent(0);
296}
297
298
299void
300InOrderCPU::regStats()
301{
302 /* Register the Resource Pool's stats here.*/
303 resPool->regStats();
304
305 /* Register any of the InOrderCPU's stats here.*/
306 timesIdled
307 .name(name() + ".timesIdled")
308 .desc("Number of times that the entire CPU went into an idle state and"
309 " unscheduled itself")
310 .prereq(timesIdled);
311
312 idleCycles
313 .name(name() + ".idleCycles")
314 .desc("Total number of cycles that the CPU has spent unscheduled due "
315 "to idling")
316 .prereq(idleCycles);
317
318 threadCycles
319 .init(numThreads)
320 .name(name() + ".threadCycles")
321 .desc("Total Number of Cycles A Thread Was Active in CPU (Per-Thread)");
322
323 smtCycles
324 .name(name() + ".smtCycles")
325 .desc("Total number of cycles that the CPU was simultaneous multithreading.(SMT)");
326
327 committedInsts
328 .init(numThreads)
329 .name(name() + ".committedInsts")
330 .desc("Number of Instructions Simulated (Per-Thread)");
331
332 smtCommittedInsts
333 .init(numThreads)
334 .name(name() + ".smtCommittedInsts")
335 .desc("Number of SMT Instructions Simulated (Per-Thread)");
336
337 totalCommittedInsts
338 .name(name() + ".committedInsts_total")
339 .desc("Number of Instructions Simulated (Total)");
340
341 cpi
342 .name(name() + ".cpi")
343 .desc("CPI: Cycles Per Instruction (Per-Thread)")
344 .precision(6);
345 cpi = threadCycles / committedInsts;
346
347 smtCpi
348 .name(name() + ".smt_cpi")
349 .desc("CPI: Total SMT-CPI")
350 .precision(6);
351 smtCpi = smtCycles / smtCommittedInsts;
352
353 totalCpi
354 .name(name() + ".cpi_total")
355 .desc("CPI: Total CPI of All Threads")
356 .precision(6);
Korey Sewelle4aa4ca2009-03-04 13:16:48 -0500357 totalCpi = numCycles / totalCommittedInsts;
Korey Sewell973d8b82009-02-10 15:49:29 -0800358
359 ipc
360 .name(name() + ".ipc")
361 .desc("IPC: Instructions Per Cycle (Per-Thread)")
362 .precision(6);
363 ipc = committedInsts / threadCycles;
364
365 smtIpc
366 .name(name() + ".smt_ipc")
367 .desc("IPC: Total SMT-IPC")
368 .precision(6);
369 smtIpc = smtCommittedInsts / smtCycles;
370
371 totalIpc
372 .name(name() + ".ipc_total")
373 .desc("IPC: Total IPC of All Threads")
374 .precision(6);
Korey Sewelle4aa4ca2009-03-04 13:16:48 -0500375 totalIpc = totalCommittedInsts / numCycles;
Korey Sewell973d8b82009-02-10 15:49:29 -0800376
377 BaseCPU::regStats();
378}
379
380
381void
382InOrderCPU::tick()
383{
384 DPRINTF(InOrderCPU, "\n\nInOrderCPU: Ticking main, InOrderCPU.\n");
385
386 ++numCycles;
387
388 //Tick each of the stages
389 for (int stNum=NumStages - 1; stNum >= 0 ; stNum--) {
390 pipelineStage[stNum]->tick();
391 }
392
393 // Now advance the time buffers one tick
394 timeBuffer.advance();
395 for (int sqNum=0; sqNum < NumStages - 1; sqNum++) {
396 stageQueue[sqNum]->advance();
397 }
398 activityRec.advance();
399
400 // Any squashed requests, events, or insts then remove them now
401 cleanUpRemovedReqs();
402 cleanUpRemovedEvents();
403 cleanUpRemovedInsts();
404
405 // Re-schedule CPU for this cycle
406 if (!tickEvent.scheduled()) {
407 if (_status == SwitchedOut) {
408 // increment stat
409 lastRunningCycle = curTick;
410 } else if (!activityRec.active()) {
411 DPRINTF(InOrderCPU, "sleeping CPU.\n");
412 lastRunningCycle = curTick;
413 timesIdled++;
414 } else {
415 //Tick next_tick = curTick + cycles(1);
416 //tickEvent.schedule(next_tick);
417 mainEventQueue.schedule(&tickEvent, nextCycle(curTick + 1));
418 DPRINTF(InOrderCPU, "Scheduled CPU for next tick @ %i.\n", nextCycle() + curTick);
419 }
420 }
421
422 tickThreadStats();
423 updateThreadPriority();
424}
425
426
427void
428InOrderCPU::init()
429{
430 if (!deferRegistration) {
431 registerThreadContexts();
432 }
433
434 // Set inSyscall so that the CPU doesn't squash when initially
435 // setting up registers.
Nathan Binkert47877cf2009-05-26 09:23:13 -0700436 for (ThreadID tid = 0; tid < numThreads; ++tid)
437 thread[tid]->inSyscall = true;
Korey Sewell973d8b82009-02-10 15:49:29 -0800438
Steve Reinhardt14808ec2009-04-17 16:54:58 -0700439#if FULL_SYSTEM
Nathan Binkert47877cf2009-05-26 09:23:13 -0700440 for (ThreadID tid = 0; tid < numThreads; tid++) {
Steve Reinhardt14808ec2009-04-17 16:54:58 -0700441 ThreadContext *src_tc = threadContexts[tid];
442 TheISA::initCPU(src_tc, src_tc->contextId());
Korey Sewell973d8b82009-02-10 15:49:29 -0800443 }
Steve Reinhardt14808ec2009-04-17 16:54:58 -0700444#endif
Korey Sewell973d8b82009-02-10 15:49:29 -0800445
446 // Clear inSyscall.
Nathan Binkert47877cf2009-05-26 09:23:13 -0700447 for (ThreadID tid = 0; tid < numThreads; ++tid)
448 thread[tid]->inSyscall = false;
Korey Sewell973d8b82009-02-10 15:49:29 -0800449
450 // Call Initializiation Routine for Resource Pool
451 resPool->init();
452}
453
454void
455InOrderCPU::readFunctional(Addr addr, uint32_t &buffer)
456{
457 tcBase()->getMemPort()->readBlob(addr, (uint8_t*)&buffer, sizeof(uint32_t));
458 buffer = gtoh(buffer);
459}
460
461void
462InOrderCPU::reset()
463{
464 miscRegFile.reset(coreType, numThreads, numVirtProcs, dynamic_cast<BaseCPU*>(this));
465}
466
467Port*
468InOrderCPU::getPort(const std::string &if_name, int idx)
469{
470 return resPool->getPort(if_name, idx);
471}
472
473void
Nathan Binkert47877cf2009-05-26 09:23:13 -0700474InOrderCPU::trap(Fault fault, ThreadID tid, int delay)
Korey Sewell973d8b82009-02-10 15:49:29 -0800475{
Korey Sewelldb2b7212009-05-12 15:01:16 -0400476 //@ Squash Pipeline during TRAP
Korey Sewell973d8b82009-02-10 15:49:29 -0800477 scheduleCpuEvent(Trap, fault, tid, 0/*vpe*/, delay);
478}
479
480void
Nathan Binkert47877cf2009-05-26 09:23:13 -0700481InOrderCPU::trapCPU(Fault fault, ThreadID tid)
Korey Sewell973d8b82009-02-10 15:49:29 -0800482{
483 fault->invoke(tcBase(tid));
484}
485
486void
487InOrderCPU::scheduleCpuEvent(CPUEventType c_event, Fault fault,
Nathan Binkert47877cf2009-05-26 09:23:13 -0700488 ThreadID tid, unsigned vpe, unsigned delay)
Korey Sewell973d8b82009-02-10 15:49:29 -0800489{
490 CPUEvent *cpu_event = new CPUEvent(this, c_event, fault, tid, vpe);
491
492 if (delay >= 0) {
Korey Sewelldb2b7212009-05-12 15:01:16 -0400493 DPRINTF(InOrderCPU, "Scheduling CPU Event (%s) for cycle %i.\n",
Korey Sewell3a057bd2009-05-12 15:01:16 -0400494 eventNames[c_event], curTick + delay);
Korey Sewell973d8b82009-02-10 15:49:29 -0800495 mainEventQueue.schedule(cpu_event,curTick + delay);
496 } else {
497 cpu_event->process();
498 cpuEventRemoveList.push(cpu_event);
499 }
500
501 // Broadcast event to the Resource Pool
Nathan Binkert47877cf2009-05-26 09:23:13 -0700502 DynInstPtr dummy_inst =
503 new InOrderDynInst(this, NULL, getNextEventNum(), tid);
Korey Sewell973d8b82009-02-10 15:49:29 -0800504 resPool->scheduleEvent(c_event, dummy_inst, 0, 0, tid);
505}
506
507inline bool
Nathan Binkert47877cf2009-05-26 09:23:13 -0700508InOrderCPU::isThreadActive(ThreadID tid)
Korey Sewell973d8b82009-02-10 15:49:29 -0800509{
Nathan Binkert47877cf2009-05-26 09:23:13 -0700510 list<ThreadID>::iterator isActive =
511 std::find(activeThreads.begin(), activeThreads.end(), tid);
Korey Sewell973d8b82009-02-10 15:49:29 -0800512
513 return (isActive != activeThreads.end());
514}
515
516
517void
Nathan Binkert47877cf2009-05-26 09:23:13 -0700518InOrderCPU::activateThread(ThreadID tid)
Korey Sewell973d8b82009-02-10 15:49:29 -0800519{
520 if (!isThreadActive(tid)) {
Nathan Binkert47877cf2009-05-26 09:23:13 -0700521 DPRINTF(InOrderCPU,
522 "Adding Thread %i to active threads list in CPU.\n", tid);
Korey Sewell973d8b82009-02-10 15:49:29 -0800523 activeThreads.push_back(tid);
524
525 wakeCPU();
526 }
527}
528
529void
Nathan Binkert47877cf2009-05-26 09:23:13 -0700530InOrderCPU::deactivateThread(ThreadID tid)
Korey Sewell973d8b82009-02-10 15:49:29 -0800531{
532 DPRINTF(InOrderCPU, "[tid:%i]: Calling deactivate thread.\n", tid);
533
534 if (isThreadActive(tid)) {
535 DPRINTF(InOrderCPU,"[tid:%i]: Removing from active threads list\n",
536 tid);
Nathan Binkert47877cf2009-05-26 09:23:13 -0700537 list<ThreadID>::iterator thread_it =
538 std::find(activeThreads.begin(), activeThreads.end(), tid);
Korey Sewell973d8b82009-02-10 15:49:29 -0800539
540 removePipelineStalls(*thread_it);
541
542 //@TODO: change stage status' to Idle?
543
544 activeThreads.erase(thread_it);
545 }
546}
547
548void
Nathan Binkert47877cf2009-05-26 09:23:13 -0700549InOrderCPU::removePipelineStalls(ThreadID tid)
Korey Sewell973d8b82009-02-10 15:49:29 -0800550{
551 DPRINTF(InOrderCPU,"[tid:%i]: Removing all pipeline stalls\n",
552 tid);
553
554 for (int stNum = 0; stNum < NumStages ; stNum++) {
555 pipelineStage[stNum]->removeStalls(tid);
556 }
557
558}
559bool
Nathan Binkert47877cf2009-05-26 09:23:13 -0700560InOrderCPU::isThreadInCPU(ThreadID tid)
Korey Sewell973d8b82009-02-10 15:49:29 -0800561{
Nathan Binkert47877cf2009-05-26 09:23:13 -0700562 list<ThreadID>::iterator isCurrent =
563 std::find(currentThreads.begin(), currentThreads.end(), tid);
Korey Sewell973d8b82009-02-10 15:49:29 -0800564
565 return (isCurrent != currentThreads.end());
566}
567
568void
Nathan Binkert47877cf2009-05-26 09:23:13 -0700569InOrderCPU::addToCurrentThreads(ThreadID tid)
Korey Sewell973d8b82009-02-10 15:49:29 -0800570{
571 if (!isThreadInCPU(tid)) {
572 DPRINTF(InOrderCPU, "Adding Thread %i to current threads list in CPU.\n",
573 tid);
574 currentThreads.push_back(tid);
575 }
576}
577
578void
Nathan Binkert47877cf2009-05-26 09:23:13 -0700579InOrderCPU::removeFromCurrentThreads(ThreadID tid)
Korey Sewell973d8b82009-02-10 15:49:29 -0800580{
581 if (isThreadInCPU(tid)) {
Nathan Binkert47877cf2009-05-26 09:23:13 -0700582 DPRINTF(InOrderCPU,
583 "Adding Thread %i to current threads list in CPU.\n", tid);
584 list<ThreadID>::iterator isCurrent =
585 std::find(currentThreads.begin(), currentThreads.end(), tid);
Korey Sewell973d8b82009-02-10 15:49:29 -0800586 currentThreads.erase(isCurrent);
587 }
588}
589
590bool
Nathan Binkert47877cf2009-05-26 09:23:13 -0700591InOrderCPU::isThreadSuspended(ThreadID tid)
Korey Sewell973d8b82009-02-10 15:49:29 -0800592{
Nathan Binkert47877cf2009-05-26 09:23:13 -0700593 list<ThreadID>::iterator isSuspended =
594 std::find(suspendedThreads.begin(), suspendedThreads.end(), tid);
Korey Sewell973d8b82009-02-10 15:49:29 -0800595
596 return (isSuspended!= suspendedThreads.end());
597}
598
599void
600InOrderCPU::enableVirtProcElement(unsigned vpe)
601{
602 DPRINTF(InOrderCPU, "[vpe:%i]: Scheduling "
603 "Enabling of concurrent virtual processor execution",
604 vpe);
605
606 scheduleCpuEvent(EnableVPEs, NoFault, 0/*tid*/, vpe);
607}
608
609void
610InOrderCPU::enableVPEs(unsigned vpe)
611{
612 DPRINTF(InOrderCPU, "[vpe:%i]: Enabling Concurrent Execution "
613 "virtual processors %i", vpe);
614
Nathan Binkert47877cf2009-05-26 09:23:13 -0700615 list<ThreadID>::iterator thread_it = currentThreads.begin();
Korey Sewell973d8b82009-02-10 15:49:29 -0800616
617 while (thread_it != currentThreads.end()) {
618 if (!isThreadSuspended(*thread_it)) {
619 activateThread(*thread_it);
620 }
621 thread_it++;
622 }
623}
624
625void
Nathan Binkert47877cf2009-05-26 09:23:13 -0700626InOrderCPU::disableVirtProcElement(ThreadID tid, unsigned vpe)
Korey Sewell973d8b82009-02-10 15:49:29 -0800627{
628 DPRINTF(InOrderCPU, "[vpe:%i]: Scheduling "
629 "Disabling of concurrent virtual processor execution",
630 vpe);
631
632 scheduleCpuEvent(DisableVPEs, NoFault, 0/*tid*/, vpe);
633}
634
635void
Nathan Binkert47877cf2009-05-26 09:23:13 -0700636InOrderCPU::disableVPEs(ThreadID tid, unsigned vpe)
Korey Sewell973d8b82009-02-10 15:49:29 -0800637{
638 DPRINTF(InOrderCPU, "[vpe:%i]: Disabling Concurrent Execution of "
639 "virtual processors %i", vpe);
640
641 unsigned base_vpe = TheISA::getVirtProcNum(tcBase(tid));
642
Nathan Binkert47877cf2009-05-26 09:23:13 -0700643 list<ThreadID>::iterator thread_it = activeThreads.begin();
Korey Sewell973d8b82009-02-10 15:49:29 -0800644
Nathan Binkert47877cf2009-05-26 09:23:13 -0700645 vector<list<ThreadID>::iterator> removeList;
Korey Sewell973d8b82009-02-10 15:49:29 -0800646
647 while (thread_it != activeThreads.end()) {
648 if (base_vpe != vpe) {
649 removeList.push_back(thread_it);
650 }
651 thread_it++;
652 }
653
654 for (int i = 0; i < removeList.size(); i++) {
655 activeThreads.erase(removeList[i]);
656 }
657}
658
659void
660InOrderCPU::enableMultiThreading(unsigned vpe)
661{
662 // Schedule event to take place at end of cycle
663 DPRINTF(InOrderCPU, "[vpe:%i]: Scheduling Enable Multithreading on "
664 "virtual processor %i", vpe);
665
666 scheduleCpuEvent(EnableThreads, NoFault, 0/*tid*/, vpe);
667}
668
669void
670InOrderCPU::enableThreads(unsigned vpe)
671{
672 DPRINTF(InOrderCPU, "[vpe:%i]: Enabling Multithreading on "
673 "virtual processor %i", vpe);
674
Nathan Binkert47877cf2009-05-26 09:23:13 -0700675 list<ThreadID>::iterator thread_it = currentThreads.begin();
Korey Sewell973d8b82009-02-10 15:49:29 -0800676
677 while (thread_it != currentThreads.end()) {
678 if (TheISA::getVirtProcNum(tcBase(*thread_it)) == vpe) {
679 if (!isThreadSuspended(*thread_it)) {
680 activateThread(*thread_it);
681 }
682 }
683 thread_it++;
684 }
685}
686void
Nathan Binkert47877cf2009-05-26 09:23:13 -0700687InOrderCPU::disableMultiThreading(ThreadID tid, unsigned vpe)
Korey Sewell973d8b82009-02-10 15:49:29 -0800688{
689 // Schedule event to take place at end of cycle
690 DPRINTF(InOrderCPU, "[tid:%i]: Scheduling Disable Multithreading on "
691 "virtual processor %i", tid, vpe);
692
693 scheduleCpuEvent(DisableThreads, NoFault, tid, vpe);
694}
695
696void
Nathan Binkert47877cf2009-05-26 09:23:13 -0700697InOrderCPU::disableThreads(ThreadID tid, unsigned vpe)
Korey Sewell973d8b82009-02-10 15:49:29 -0800698{
699 DPRINTF(InOrderCPU, "[tid:%i]: Disabling Multithreading on "
700 "virtual processor %i", tid, vpe);
701
Nathan Binkert47877cf2009-05-26 09:23:13 -0700702 list<ThreadID>::iterator thread_it = activeThreads.begin();
Korey Sewell973d8b82009-02-10 15:49:29 -0800703
Nathan Binkert47877cf2009-05-26 09:23:13 -0700704 vector<list<ThreadID>::iterator> removeList;
Korey Sewell973d8b82009-02-10 15:49:29 -0800705
706 while (thread_it != activeThreads.end()) {
707 if (TheISA::getVirtProcNum(tcBase(*thread_it)) == vpe) {
708 removeList.push_back(thread_it);
709 }
710 thread_it++;
711 }
712
713 for (int i = 0; i < removeList.size(); i++) {
714 activeThreads.erase(removeList[i]);
715 }
716}
717
718void
719InOrderCPU::updateThreadPriority()
720{
721 if (activeThreads.size() > 1)
722 {
723 //DEFAULT TO ROUND ROBIN SCHEME
724 //e.g. Move highest priority to end of thread list
Nathan Binkert47877cf2009-05-26 09:23:13 -0700725 list<ThreadID>::iterator list_begin = activeThreads.begin();
726 list<ThreadID>::iterator list_end = activeThreads.end();
Korey Sewell973d8b82009-02-10 15:49:29 -0800727
728 unsigned high_thread = *list_begin;
729
730 activeThreads.erase(list_begin);
731
732 activeThreads.push_back(high_thread);
733 }
734}
735
736inline void
737InOrderCPU::tickThreadStats()
738{
739 /** Keep track of cycles that each thread is active */
Nathan Binkert47877cf2009-05-26 09:23:13 -0700740 list<ThreadID>::iterator thread_it = activeThreads.begin();
Korey Sewell973d8b82009-02-10 15:49:29 -0800741 while (thread_it != activeThreads.end()) {
742 threadCycles[*thread_it]++;
743 thread_it++;
744 }
745
746 // Keep track of cycles where SMT is active
747 if (activeThreads.size() > 1) {
748 smtCycles++;
749 }
750}
751
752void
Nathan Binkert47877cf2009-05-26 09:23:13 -0700753InOrderCPU::activateContext(ThreadID tid, int delay)
Korey Sewell973d8b82009-02-10 15:49:29 -0800754{
755 DPRINTF(InOrderCPU,"[tid:%i]: Activating ...\n", tid);
756
757 scheduleCpuEvent(ActivateThread, NoFault, tid, 0/*vpe*/, delay);
758
759 // Be sure to signal that there's some activity so the CPU doesn't
760 // deschedule itself.
761 activityRec.activity();
762
763 _status = Running;
764}
765
766
767void
Nathan Binkert47877cf2009-05-26 09:23:13 -0700768InOrderCPU::suspendContext(ThreadID tid, int delay)
Korey Sewell973d8b82009-02-10 15:49:29 -0800769{
770 scheduleCpuEvent(SuspendThread, NoFault, tid, 0/*vpe*/, delay);
771 //_status = Idle;
772}
773
774void
Nathan Binkert47877cf2009-05-26 09:23:13 -0700775InOrderCPU::suspendThread(ThreadID tid)
Korey Sewell973d8b82009-02-10 15:49:29 -0800776{
777 DPRINTF(InOrderCPU,"[tid: %i]: Suspended ...\n", tid);
778 deactivateThread(tid);
779}
780
781void
Nathan Binkert47877cf2009-05-26 09:23:13 -0700782InOrderCPU::deallocateContext(ThreadID tid, int delay)
Korey Sewell973d8b82009-02-10 15:49:29 -0800783{
784 scheduleCpuEvent(DeallocateThread, NoFault, tid, 0/*vpe*/, delay);
785}
786
787void
Nathan Binkert47877cf2009-05-26 09:23:13 -0700788InOrderCPU::deallocateThread(ThreadID tid)
Korey Sewell973d8b82009-02-10 15:49:29 -0800789{
790 DPRINTF(InOrderCPU,"[tid:%i]: Deallocating ...", tid);
791
Korey Sewell973d8b82009-02-10 15:49:29 -0800792 removeFromCurrentThreads(tid);
793
794 deactivateThread(tid);
795
796 squashThreadInPipeline(tid);
797}
798
799void
Nathan Binkert47877cf2009-05-26 09:23:13 -0700800InOrderCPU::squashThreadInPipeline(ThreadID tid)
Korey Sewell973d8b82009-02-10 15:49:29 -0800801{
802 //Squash all instructions in each stage
803 for (int stNum=NumStages - 1; stNum >= 0 ; stNum--) {
804 pipelineStage[stNum]->squash(0 /*seq_num*/, tid);
805 }
806}
807
808void
Nathan Binkert47877cf2009-05-26 09:23:13 -0700809InOrderCPU::haltContext(ThreadID tid, int delay)
Korey Sewell973d8b82009-02-10 15:49:29 -0800810{
811 DPRINTF(InOrderCPU, "[tid:%i]: Halt context called.\n", tid);
812
813 // Halt is same thing as deallocate for now
814 // @TODO: Differentiate between halt & deallocate in the CPU
815 // model
816 deallocateContext(tid, delay);
817}
818
819void
Nathan Binkert47877cf2009-05-26 09:23:13 -0700820InOrderCPU::insertThread(ThreadID tid)
Korey Sewell973d8b82009-02-10 15:49:29 -0800821{
822 panic("Unimplemented Function\n.");
823}
824
825void
Nathan Binkert47877cf2009-05-26 09:23:13 -0700826InOrderCPU::removeThread(ThreadID tid)
Korey Sewell973d8b82009-02-10 15:49:29 -0800827{
828 DPRINTF(InOrderCPU, "Removing Thread %i from CPU.\n", tid);
829
830 /** Broadcast to CPU resources*/
831}
832
Korey Sewell1c8dfd92009-05-12 15:01:13 -0400833PipelineStage*
834InOrderCPU::getPipeStage(int stage_num)
835{
836 return pipelineStage[stage_num];
837}
838
839
Korey Sewell973d8b82009-02-10 15:49:29 -0800840void
Nathan Binkert47877cf2009-05-26 09:23:13 -0700841InOrderCPU::activateWhenReady(ThreadID tid)
Korey Sewell973d8b82009-02-10 15:49:29 -0800842{
843 panic("Unimplemented Function\n.");
844}
845
846
Korey Sewell973d8b82009-02-10 15:49:29 -0800847uint64_t
Nathan Binkert47877cf2009-05-26 09:23:13 -0700848InOrderCPU::readPC(ThreadID tid)
Korey Sewell973d8b82009-02-10 15:49:29 -0800849{
850 return PC[tid];
851}
852
853
854void
Nathan Binkert47877cf2009-05-26 09:23:13 -0700855InOrderCPU::setPC(Addr new_PC, ThreadID tid)
Korey Sewell973d8b82009-02-10 15:49:29 -0800856{
857 PC[tid] = new_PC;
858}
859
860
861uint64_t
Nathan Binkert47877cf2009-05-26 09:23:13 -0700862InOrderCPU::readNextPC(ThreadID tid)
Korey Sewell973d8b82009-02-10 15:49:29 -0800863{
864 return nextPC[tid];
865}
866
867
868void
Nathan Binkert47877cf2009-05-26 09:23:13 -0700869InOrderCPU::setNextPC(uint64_t new_NPC, ThreadID tid)
Korey Sewell973d8b82009-02-10 15:49:29 -0800870{
871 nextPC[tid] = new_NPC;
872}
873
874
875uint64_t
Nathan Binkert47877cf2009-05-26 09:23:13 -0700876InOrderCPU::readNextNPC(ThreadID tid)
Korey Sewell973d8b82009-02-10 15:49:29 -0800877{
878 return nextNPC[tid];
879}
880
881
882void
Nathan Binkert47877cf2009-05-26 09:23:13 -0700883InOrderCPU::setNextNPC(uint64_t new_NNPC, ThreadID tid)
Korey Sewell973d8b82009-02-10 15:49:29 -0800884{
885 nextNPC[tid] = new_NNPC;
886}
887
888uint64_t
Nathan Binkert47877cf2009-05-26 09:23:13 -0700889InOrderCPU::readIntReg(int reg_idx, ThreadID tid)
Korey Sewell973d8b82009-02-10 15:49:29 -0800890{
891 return intRegFile[tid].readReg(reg_idx);
892}
893
894FloatReg
Nathan Binkert47877cf2009-05-26 09:23:13 -0700895InOrderCPU::readFloatReg(int reg_idx, ThreadID tid, int width)
Korey Sewell973d8b82009-02-10 15:49:29 -0800896{
897
898 return floatRegFile[tid].readReg(reg_idx, width);
899}
900
901FloatRegBits
Nathan Binkert47877cf2009-05-26 09:23:13 -0700902InOrderCPU::readFloatRegBits(int reg_idx, ThreadID tid, int width)
Korey Sewell973d8b82009-02-10 15:49:29 -0800903{;
904 return floatRegFile[tid].readRegBits(reg_idx, width);
905}
906
907void
Nathan Binkert47877cf2009-05-26 09:23:13 -0700908InOrderCPU::setIntReg(int reg_idx, uint64_t val, ThreadID tid)
Korey Sewell973d8b82009-02-10 15:49:29 -0800909{
910 intRegFile[tid].setReg(reg_idx, val);
911}
912
913
914void
Nathan Binkert47877cf2009-05-26 09:23:13 -0700915InOrderCPU::setFloatReg(int reg_idx, FloatReg val, ThreadID tid, int width)
Korey Sewell973d8b82009-02-10 15:49:29 -0800916{
917 floatRegFile[tid].setReg(reg_idx, val, width);
918}
919
920
921void
Nathan Binkert47877cf2009-05-26 09:23:13 -0700922InOrderCPU::setFloatRegBits(int reg_idx, FloatRegBits val, ThreadID tid,
923 int width)
Korey Sewell973d8b82009-02-10 15:49:29 -0800924{
925 floatRegFile[tid].setRegBits(reg_idx, val, width);
926}
927
928uint64_t
Nathan Binkert47877cf2009-05-26 09:23:13 -0700929InOrderCPU::readRegOtherThread(unsigned reg_idx, ThreadID tid)
Korey Sewell973d8b82009-02-10 15:49:29 -0800930{
931 // If Default value is set, then retrieve target thread
Nathan Binkert47877cf2009-05-26 09:23:13 -0700932 if (tid == InvalidThreadID) {
Korey Sewell973d8b82009-02-10 15:49:29 -0800933 tid = TheISA::getTargetThread(tcBase(tid));
934 }
935
936 if (reg_idx < FP_Base_DepTag) { // Integer Register File
937 return readIntReg(reg_idx, tid);
938 } else if (reg_idx < Ctrl_Base_DepTag) { // Float Register File
939 reg_idx -= FP_Base_DepTag;
940 return readFloatRegBits(reg_idx, tid);
941 } else {
942 reg_idx -= Ctrl_Base_DepTag;
943 return readMiscReg(reg_idx, tid); // Misc. Register File
944 }
945}
946void
Nathan Binkert47877cf2009-05-26 09:23:13 -0700947InOrderCPU::setRegOtherThread(unsigned reg_idx, const MiscReg &val,
948 ThreadID tid)
Korey Sewell973d8b82009-02-10 15:49:29 -0800949{
950 // If Default value is set, then retrieve target thread
Nathan Binkert47877cf2009-05-26 09:23:13 -0700951 if (tid == InvalidThreadID) {
Korey Sewell973d8b82009-02-10 15:49:29 -0800952 tid = TheISA::getTargetThread(tcBase(tid));
953 }
954
955 if (reg_idx < FP_Base_DepTag) { // Integer Register File
956 setIntReg(reg_idx, val, tid);
957 } else if (reg_idx < Ctrl_Base_DepTag) { // Float Register File
958 reg_idx -= FP_Base_DepTag;
959 setFloatRegBits(reg_idx, val, tid);
960 } else {
961 reg_idx -= Ctrl_Base_DepTag;
962 setMiscReg(reg_idx, val, tid); // Misc. Register File
963 }
964}
965
966MiscReg
Nathan Binkert47877cf2009-05-26 09:23:13 -0700967InOrderCPU::readMiscRegNoEffect(int misc_reg, ThreadID tid)
Korey Sewell973d8b82009-02-10 15:49:29 -0800968{
969 return miscRegFile.readRegNoEffect(misc_reg, tid);
970}
971
972MiscReg
Nathan Binkert47877cf2009-05-26 09:23:13 -0700973InOrderCPU::readMiscReg(int misc_reg, ThreadID tid)
Korey Sewell973d8b82009-02-10 15:49:29 -0800974{
975 return miscRegFile.readReg(misc_reg, tcBase(tid), tid);
976}
977
978void
Nathan Binkert47877cf2009-05-26 09:23:13 -0700979InOrderCPU::setMiscRegNoEffect(int misc_reg, const MiscReg &val, ThreadID tid)
Korey Sewell973d8b82009-02-10 15:49:29 -0800980{
981 miscRegFile.setRegNoEffect(misc_reg, val, tid);
982}
983
984void
Nathan Binkert47877cf2009-05-26 09:23:13 -0700985InOrderCPU::setMiscReg(int misc_reg, const MiscReg &val, ThreadID tid)
Korey Sewell973d8b82009-02-10 15:49:29 -0800986{
987 miscRegFile.setReg(misc_reg, val, tcBase(tid), tid);
988}
989
990
991InOrderCPU::ListIt
992InOrderCPU::addInst(DynInstPtr &inst)
993{
Nathan Binkert47877cf2009-05-26 09:23:13 -0700994 ThreadID tid = inst->readTid();
Korey Sewell973d8b82009-02-10 15:49:29 -0800995
996 instList[tid].push_back(inst);
997
998 return --(instList[tid].end());
999}
1000
1001void
Nathan Binkert47877cf2009-05-26 09:23:13 -07001002InOrderCPU::instDone(DynInstPtr inst, ThreadID tid)
Korey Sewell973d8b82009-02-10 15:49:29 -08001003{
1004 // Set the CPU's PCs - This contributes to the precise state of the CPU which can be used
1005 // when restoring a thread to the CPU after a fork or after an exception
1006 // @TODO: Set-Up Grad-Info/Committed-Info to let ThreadState know if it's a branch or not
1007 setPC(inst->readPC(), tid);
1008 setNextPC(inst->readNextPC(), tid);
1009 setNextNPC(inst->readNextNPC(), tid);
1010
1011 // Finalize Trace Data For Instruction
1012 if (inst->traceData) {
1013 //inst->traceData->setCycle(curTick);
1014 inst->traceData->setFetchSeq(inst->seqNum);
1015 //inst->traceData->setCPSeq(cpu->tcBase(tid)->numInst);
1016 inst->traceData->dump();
1017 delete inst->traceData;
1018 inst->traceData = NULL;
1019 }
1020
1021 // Set Last Graduated Instruction In Thread State
1022 //thread[tid]->lastGradInst = inst;
1023
1024 // Increment thread-state's instruction count
1025 thread[tid]->numInst++;
1026
1027 // Increment thread-state's instruction stats
1028 thread[tid]->numInsts++;
1029
1030 // Count committed insts per thread stats
1031 committedInsts[tid]++;
1032
1033 // Count total insts committed stat
1034 totalCommittedInsts++;
1035
1036 // Count SMT-committed insts per thread stat
1037 if (numActiveThreads() > 1) {
1038 smtCommittedInsts[tid]++;
1039 }
1040
1041 // Check for instruction-count-based events.
1042 comInstEventQueue[tid]->serviceEvents(thread[tid]->numInst);
1043
1044 // Broadcast to other resources an instruction
1045 // has been completed
1046 resPool->scheduleEvent((CPUEventType)ResourcePool::InstGraduated, inst, tid);
1047
1048 // Finally, remove instruction from CPU
1049 removeInst(inst);
1050}
1051
1052void
1053InOrderCPU::addToRemoveList(DynInstPtr &inst)
1054{
1055 removeInstsThisCycle = true;
1056
1057 removeList.push(inst->getInstListIt());
1058}
1059
1060void
1061InOrderCPU::removeInst(DynInstPtr &inst)
1062{
1063 DPRINTF(InOrderCPU, "Removing graduated instruction [tid:%i] PC %#x "
1064 "[sn:%lli]\n",
1065 inst->threadNumber, inst->readPC(), inst->seqNum);
1066
1067 removeInstsThisCycle = true;
1068
1069 // Remove the instruction.
1070 removeList.push(inst->getInstListIt());
1071}
1072
1073void
Nathan Binkert47877cf2009-05-26 09:23:13 -07001074InOrderCPU::removeInstsUntil(const InstSeqNum &seq_num, ThreadID tid)
Korey Sewell973d8b82009-02-10 15:49:29 -08001075{
1076 //assert(!instList[tid].empty());
1077
1078 removeInstsThisCycle = true;
1079
1080 ListIt inst_iter = instList[tid].end();
1081
1082 inst_iter--;
1083
1084 DPRINTF(InOrderCPU, "Deleting instructions from CPU instruction "
1085 "list that are from [tid:%i] and above [sn:%lli] (end=%lli).\n",
1086 tid, seq_num, (*inst_iter)->seqNum);
1087
1088 while ((*inst_iter)->seqNum > seq_num) {
1089
1090 bool break_loop = (inst_iter == instList[tid].begin());
1091
1092 squashInstIt(inst_iter, tid);
1093
1094 inst_iter--;
1095
1096 if (break_loop)
1097 break;
1098 }
1099}
1100
1101
1102inline void
Nathan Binkert47877cf2009-05-26 09:23:13 -07001103InOrderCPU::squashInstIt(const ListIt &instIt, ThreadID tid)
Korey Sewell973d8b82009-02-10 15:49:29 -08001104{
1105 if ((*instIt)->threadNumber == tid) {
1106 DPRINTF(InOrderCPU, "Squashing instruction, "
1107 "[tid:%i] [sn:%lli] PC %#x\n",
1108 (*instIt)->threadNumber,
1109 (*instIt)->seqNum,
1110 (*instIt)->readPC());
1111
1112 (*instIt)->setSquashed();
1113
1114 removeList.push(instIt);
1115 }
1116}
1117
1118
1119void
1120InOrderCPU::cleanUpRemovedInsts()
1121{
1122 while (!removeList.empty()) {
1123 DPRINTF(InOrderCPU, "Removing instruction, "
1124 "[tid:%i] [sn:%lli] PC %#x\n",
1125 (*removeList.front())->threadNumber,
1126 (*removeList.front())->seqNum,
1127 (*removeList.front())->readPC());
1128
1129 DynInstPtr inst = *removeList.front();
Nathan Binkert47877cf2009-05-26 09:23:13 -07001130 ThreadID tid = inst->threadNumber;
Korey Sewell973d8b82009-02-10 15:49:29 -08001131
1132 // Make Sure Resource Schedule Is Emptied Out
1133 ThePipeline::ResSchedule *inst_sched = &inst->resSched;
1134 while (!inst_sched->empty()) {
1135 ThePipeline::ScheduleEntry* sch_entry = inst_sched->top();
1136 inst_sched->pop();
1137 delete sch_entry;
1138 }
1139
1140 // Remove From Register Dependency Map, If Necessary
1141 archRegDepMap[(*removeList.front())->threadNumber].
1142 remove((*removeList.front()));
1143
1144
1145 // Clear if Non-Speculative
1146 if (inst->staticInst &&
1147 inst->seqNum == nonSpecSeqNum[tid] &&
1148 nonSpecInstActive[tid] == true) {
1149 nonSpecInstActive[tid] = false;
1150 }
1151
1152 instList[tid].erase(removeList.front());
1153
1154 removeList.pop();
1155
1156 DPRINTF(RefCount, "pop from remove list: [sn:%i]: Refcount = %i.\n",
1157 inst->seqNum,
1158 0/*inst->curCount()*/);
1159
1160 }
1161
1162 removeInstsThisCycle = false;
1163}
1164
1165void
1166InOrderCPU::cleanUpRemovedReqs()
1167{
1168 while (!reqRemoveList.empty()) {
1169 ResourceRequest *res_req = reqRemoveList.front();
1170
1171 DPRINTF(RefCount, "[tid:%i]: Removing Request, "
1172 "[sn:%lli] [slot:%i] [stage_num:%i] [res:%s] [refcount:%i].\n",
1173 res_req->inst->threadNumber,
1174 res_req->inst->seqNum,
1175 res_req->getSlot(),
1176 res_req->getStageNum(),
1177 res_req->res->name(),
1178 0/*res_req->inst->curCount()*/);
1179
1180 reqRemoveList.pop();
1181
1182 delete res_req;
1183
1184 DPRINTF(RefCount, "after remove request: [sn:%i]: Refcount = %i.\n",
1185 res_req->inst->seqNum,
1186 0/*res_req->inst->curCount()*/);
1187 }
1188}
1189
1190void
1191InOrderCPU::cleanUpRemovedEvents()
1192{
1193 while (!cpuEventRemoveList.empty()) {
1194 Event *cpu_event = cpuEventRemoveList.front();
1195 cpuEventRemoveList.pop();
1196 delete cpu_event;
1197 }
1198}
1199
Korey Sewell973d8b82009-02-10 15:49:29 -08001200
1201void
1202InOrderCPU::dumpInsts()
1203{
1204 int num = 0;
1205
1206 ListIt inst_list_it = instList[0].begin();
1207
1208 cprintf("Dumping Instruction List\n");
1209
1210 while (inst_list_it != instList[0].end()) {
1211 cprintf("Instruction:%i\nPC:%#x\n[tid:%i]\n[sn:%lli]\nIssued:%i\n"
1212 "Squashed:%i\n\n",
1213 num, (*inst_list_it)->readPC(), (*inst_list_it)->threadNumber,
1214 (*inst_list_it)->seqNum, (*inst_list_it)->isIssued(),
1215 (*inst_list_it)->isSquashed());
1216 inst_list_it++;
1217 ++num;
1218 }
1219}
Korey Sewell973d8b82009-02-10 15:49:29 -08001220
1221void
1222InOrderCPU::wakeCPU()
1223{
1224 if (/*activityRec.active() || */tickEvent.scheduled()) {
1225 DPRINTF(Activity, "CPU already running.\n");
1226 return;
1227 }
1228
1229 DPRINTF(Activity, "Waking up CPU\n");
1230
Korey Sewell30cd2d22009-03-04 13:17:08 -05001231 //@todo: figure out how to count idleCycles correctly
Korey Sewell973d8b82009-02-10 15:49:29 -08001232 //idleCycles += (curTick - 1) - lastRunningCycle;
1233
1234 mainEventQueue.schedule(&tickEvent, curTick);
1235}
1236
1237void
Nathan Binkert47877cf2009-05-26 09:23:13 -07001238InOrderCPU::syscall(int64_t callnum, ThreadID tid)
Korey Sewell973d8b82009-02-10 15:49:29 -08001239{
1240 DPRINTF(InOrderCPU, "[tid:%i] Executing syscall().\n\n", tid);
1241
1242 DPRINTF(Activity,"Activity: syscall() called.\n");
1243
1244 // Temporarily increase this by one to account for the syscall
1245 // instruction.
1246 ++(this->thread[tid]->funcExeInst);
1247
1248 // Execute the actual syscall.
1249 this->thread[tid]->syscall(callnum);
1250
1251 // Decrease funcExeInst by one as the normal commit will handle
1252 // incrementing it.
1253 --(this->thread[tid]->funcExeInst);
1254
1255 // Clear Non-Speculative Block Variable
1256 nonSpecInstActive[tid] = false;
1257}
1258
Korey Sewell1c7e9882009-05-12 15:01:15 -04001259void
1260InOrderCPU::prefetch(DynInstPtr inst)
1261{
1262 Resource *mem_res = resPool->getResource(dataPortIdx);
1263 return mem_res->prefetch(inst);
1264}
1265
1266void
1267InOrderCPU::writeHint(DynInstPtr inst)
1268{
1269 Resource *mem_res = resPool->getResource(dataPortIdx);
1270 return mem_res->writeHint(inst);
1271}
1272
1273
Korey Sewell5127ea22009-05-12 15:01:14 -04001274TheISA::TLB*
Korey Sewell1c8dfd92009-05-12 15:01:13 -04001275InOrderCPU::getITBPtr()
1276{
Korey Sewelldb2b7212009-05-12 15:01:16 -04001277 CacheUnit *itb_res =
1278 dynamic_cast<CacheUnit*>(resPool->getResource(fetchPortIdx));
Korey Sewell5127ea22009-05-12 15:01:14 -04001279 return itb_res->tlb();
Korey Sewell1c8dfd92009-05-12 15:01:13 -04001280}
1281
1282
Korey Sewell5127ea22009-05-12 15:01:14 -04001283TheISA::TLB*
Korey Sewell1c8dfd92009-05-12 15:01:13 -04001284InOrderCPU::getDTBPtr()
1285{
Korey Sewelldb2b7212009-05-12 15:01:16 -04001286 CacheUnit *dtb_res =
1287 dynamic_cast<CacheUnit*>(resPool->getResource(dataPortIdx));
Korey Sewell5127ea22009-05-12 15:01:14 -04001288 return dtb_res->tlb();
Korey Sewell1c8dfd92009-05-12 15:01:13 -04001289}
Korey Sewelldb2b7212009-05-12 15:01:16 -04001290
1291template <class T>
1292Fault
1293InOrderCPU::read(DynInstPtr inst, Addr addr, T &data, unsigned flags)
1294{
1295 //@TODO: Generalize name "CacheUnit" to "MemUnit" just in case
1296 // you want to run w/out caches?
1297 CacheUnit *cache_res = dynamic_cast<CacheUnit*>(resPool->getResource(dataPortIdx));
1298
1299 return cache_res->read(inst, addr, data, flags);
1300}
1301
1302#ifndef DOXYGEN_SHOULD_SKIP_THIS
1303
1304template
1305Fault
1306InOrderCPU::read(DynInstPtr inst, Addr addr, Twin32_t &data, unsigned flags);
1307
1308template
1309Fault
1310InOrderCPU::read(DynInstPtr inst, Addr addr, Twin64_t &data, unsigned flags);
1311
1312template
1313Fault
1314InOrderCPU::read(DynInstPtr inst, Addr addr, uint64_t &data, unsigned flags);
1315
1316template
1317Fault
1318InOrderCPU::read(DynInstPtr inst, Addr addr, uint32_t &data, unsigned flags);
1319
1320template
1321Fault
1322InOrderCPU::read(DynInstPtr inst, Addr addr, uint16_t &data, unsigned flags);
1323
1324template
1325Fault
1326InOrderCPU::read(DynInstPtr inst, Addr addr, uint8_t &data, unsigned flags);
1327
1328#endif //DOXYGEN_SHOULD_SKIP_THIS
1329
1330template<>
1331Fault
1332InOrderCPU::read(DynInstPtr inst, Addr addr, double &data, unsigned flags)
1333{
1334 return read(inst, addr, *(uint64_t*)&data, flags);
1335}
1336
1337template<>
1338Fault
1339InOrderCPU::read(DynInstPtr inst, Addr addr, float &data, unsigned flags)
1340{
1341 return read(inst, addr, *(uint32_t*)&data, flags);
1342}
1343
1344
1345template<>
1346Fault
1347InOrderCPU::read(DynInstPtr inst, Addr addr, int32_t &data, unsigned flags)
1348{
1349 return read(inst, addr, (uint32_t&)data, flags);
1350}
1351
1352template <class T>
1353Fault
1354InOrderCPU::write(DynInstPtr inst, T data, Addr addr, unsigned flags,
1355 uint64_t *write_res)
1356{
1357 //@TODO: Generalize name "CacheUnit" to "MemUnit" just in case
1358 // you want to run w/out caches?
1359 CacheUnit *cache_res =
1360 dynamic_cast<CacheUnit*>(resPool->getResource(dataPortIdx));
1361 return cache_res->write(inst, data, addr, flags, write_res);
1362}
1363
1364#ifndef DOXYGEN_SHOULD_SKIP_THIS
1365
1366template
1367Fault
1368InOrderCPU::write(DynInstPtr inst, Twin32_t data, Addr addr,
1369 unsigned flags, uint64_t *res);
1370
1371template
1372Fault
1373InOrderCPU::write(DynInstPtr inst, Twin64_t data, Addr addr,
1374 unsigned flags, uint64_t *res);
1375
1376template
1377Fault
1378InOrderCPU::write(DynInstPtr inst, uint64_t data, Addr addr,
1379 unsigned flags, uint64_t *res);
1380
1381template
1382Fault
1383InOrderCPU::write(DynInstPtr inst, uint32_t data, Addr addr,
1384 unsigned flags, uint64_t *res);
1385
1386template
1387Fault
1388InOrderCPU::write(DynInstPtr inst, uint16_t data, Addr addr,
1389 unsigned flags, uint64_t *res);
1390
1391template
1392Fault
1393InOrderCPU::write(DynInstPtr inst, uint8_t data, Addr addr,
1394 unsigned flags, uint64_t *res);
1395
1396#endif //DOXYGEN_SHOULD_SKIP_THIS
1397
1398template<>
1399Fault
1400InOrderCPU::write(DynInstPtr inst, double data, Addr addr, unsigned flags, uint64_t *res)
1401{
1402 return write(inst, *(uint64_t*)&data, addr, flags, res);
1403}
1404
1405template<>
1406Fault
1407InOrderCPU::write(DynInstPtr inst, float data, Addr addr, unsigned flags, uint64_t *res)
1408{
1409 return write(inst, *(uint32_t*)&data, addr, flags, res);
1410}
1411
1412
1413template<>
1414Fault
1415InOrderCPU::write(DynInstPtr inst, int32_t data, Addr addr, unsigned flags, uint64_t *res)
1416{
1417 return write(inst, (uint32_t)data, addr, flags, res);
1418}