Deleted Added
sdiff udiff text old ( 2817:273f7fb94f83 ) new ( 2834:c8342a71404b )
full compact
1/*
2 * Copyright (c) 2004-2006 The Regents of The University of Michigan
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: Kevin Lim
29 * Korey Sewell
30 */
31
32#include "cpu/o3/thread_context.hh"
33#include "cpu/quiesce_event.hh"
34
35using namespace TheISA;
36
37#if FULL_SYSTEM
38template <class Impl>
39VirtualPort *
40O3ThreadContext<Impl>::getVirtPort(ThreadContext *src_tc)
41{
42 if (!src_tc)
43 return thread->getVirtPort();
44
45 VirtualPort *vp;
46 Port *mem_port;
47
48 vp = new VirtualPort("tc-vport", src_tc);
49 mem_port = cpu->system->physmem->getPort("functional");
50 mem_port->setPeer(vp);
51 vp->setPeer(mem_port);
52 return vp;
53}
54
55template <class Impl>
56void
57O3ThreadContext<Impl>::dumpFuncProfile()
58{
59 // Currently not supported
60}
61#endif
62
63template <class Impl>
64void
65O3ThreadContext<Impl>::takeOverFrom(ThreadContext *old_context)
66{
67 // some things should already be set up
68#if FULL_SYSTEM
69 assert(getSystemPtr() == old_context->getSystemPtr());
70#else
71 assert(getProcessPtr() == old_context->getProcessPtr());
72#endif
73
74 // copy over functional state
75 setStatus(old_context->status());
76 copyArchRegs(old_context);
77 setCpuId(old_context->readCpuId());
78
79#if !FULL_SYSTEM
80 thread->funcExeInst = old_context->readFuncExeInst();
81#else
82 EndQuiesceEvent *other_quiesce = old_context->getQuiesceEvent();
83 if (other_quiesce) {
84 // Point the quiesce event's TC at this TC so that it wakes up
85 // the proper CPU.
86 other_quiesce->tc = this;
87 }
88 if (thread->quiesceEvent) {
89 thread->quiesceEvent->tc = this;
90 }
91
92 // Transfer kernel stats from one CPU to the other.
93 thread->kernelStats = old_context->getKernelStats();
94// storeCondFailures = 0;
95 cpu->lockFlag = false;
96#endif
97
98 old_context->setStatus(ThreadContext::Unallocated);
99
100 thread->inSyscall = false;
101 thread->trapPending = false;
102}
103
104#if FULL_SYSTEM
105template <class Impl>
106void
107O3ThreadContext<Impl>::delVirtPort(VirtualPort *vp)
108{
109 delete vp->getPeer();
110 delete vp;
111}
112#endif
113
114template <class Impl>
115void
116O3ThreadContext<Impl>::activate(int delay)
117{
118 DPRINTF(O3CPU, "Calling activate on AlphaTC\n");
119
120 if (thread->status() == ThreadContext::Active)
121 return;
122
123#if FULL_SYSTEM
124 thread->lastActivate = curTick;
125#endif
126
127 if (thread->status() == ThreadContext::Unallocated) {
128 cpu->activateWhenReady(thread->readTid());
129 return;
130 }
131
132 thread->setStatus(ThreadContext::Active);
133
134 // status() == Suspended
135 cpu->activateContext(thread->readTid(), delay);
136}
137
138template <class Impl>
139void
140O3ThreadContext<Impl>::suspend()
141{
142 DPRINTF(O3CPU, "Calling suspend on AlphaTC\n");
143
144 if (thread->status() == ThreadContext::Suspended)
145 return;
146
147#if FULL_SYSTEM
148 thread->lastActivate = curTick;
149 thread->lastSuspend = curTick;
150#endif
151/*
152#if FULL_SYSTEM
153 // Don't change the status from active if there are pending interrupts
154 if (cpu->check_interrupts()) {
155 assert(status() == ThreadContext::Active);
156 return;
157 }
158#endif
159*/
160 thread->setStatus(ThreadContext::Suspended);
161 cpu->suspendContext(thread->readTid());
162}
163
164template <class Impl>
165void
166O3ThreadContext<Impl>::deallocate()
167{
168 DPRINTF(O3CPU, "Calling deallocate on AlphaTC\n");
169
170 if (thread->status() == ThreadContext::Unallocated)
171 return;
172
173 thread->setStatus(ThreadContext::Unallocated);
174 cpu->deallocateContext(thread->readTid());
175}
176
177template <class Impl>
178void
179O3ThreadContext<Impl>::halt()
180{
181 DPRINTF(O3CPU, "Calling halt on AlphaTC\n");
182
183 if (thread->status() == ThreadContext::Halted)
184 return;
185
186 thread->setStatus(ThreadContext::Halted);
187 cpu->haltContext(thread->readTid());
188}
189
190template <class Impl>
191void
192O3ThreadContext<Impl>::regStats(const std::string &name)
193{
194#if FULL_SYSTEM
195 thread->kernelStats = new Kernel::Statistics(cpu->system);
196 thread->kernelStats->regStats(name + ".kern");
197#endif
198}
199
200template <class Impl>
201void
202O3ThreadContext<Impl>::serialize(std::ostream &os)
203{
204#if FULL_SYSTEM
205 if (thread->kernelStats)
206 thread->kernelStats->serialize(os);
207#endif
208
209}
210
211template <class Impl>
212void
213O3ThreadContext<Impl>::unserialize(Checkpoint *cp, const std::string &section)
214{
215#if FULL_SYSTEM
216 if (thread->kernelStats)
217 thread->kernelStats->unserialize(cp, section);
218#endif
219
220}
221
222#if FULL_SYSTEM
223template <class Impl>
224Tick
225O3ThreadContext<Impl>::readLastActivate()
226{
227 return thread->lastActivate;
228}
229
230template <class Impl>
231Tick
232O3ThreadContext<Impl>::readLastSuspend()
233{
234 return thread->lastSuspend;
235}
236
237template <class Impl>
238void
239O3ThreadContext<Impl>::profileClear()
240{}
241
242template <class Impl>
243void
244O3ThreadContext<Impl>::profileSample()
245{}
246#endif
247
248template <class Impl>
249TheISA::MachInst
250O3ThreadContext<Impl>:: getInst()
251{
252 return thread->getInst();
253}
254
255template <class Impl>
256void
257O3ThreadContext<Impl>::copyArchRegs(ThreadContext *tc)
258{
259 // This function will mess things up unless the ROB is empty and
260 // there are no instructions in the pipeline.
261 unsigned tid = thread->readTid();
262 PhysRegIndex renamed_reg;
263
264 // First loop through the integer registers.
265 for (int i = 0; i < TheISA::NumIntRegs; ++i) {
266 renamed_reg = cpu->renameMap[tid].lookup(i);
267
268 DPRINTF(O3CPU, "Copying over register %i, had data %lli, "
269 "now has data %lli.\n",
270 renamed_reg, cpu->readIntReg(renamed_reg),
271 tc->readIntReg(i));
272
273 cpu->setIntReg(renamed_reg, tc->readIntReg(i));
274 }
275
276 // Then loop through the floating point registers.
277 for (int i = 0; i < TheISA::NumFloatRegs; ++i) {
278 renamed_reg = cpu->renameMap[tid].lookup(i + TheISA::FP_Base_DepTag);
279 cpu->setFloatRegBits(renamed_reg,
280 tc->readFloatRegBits(i));
281 }
282
283 // Copy the misc regs.
284 copyMiscRegs(tc, this);
285
286 // Then finally set the PC and the next PC.
287 cpu->setPC(tc->readPC(), tid);
288 cpu->setNextPC(tc->readNextPC(), tid);
289#if !FULL_SYSTEM
290 this->thread->funcExeInst = tc->readFuncExeInst();
291#endif
292}
293
294template <class Impl>
295void
296O3ThreadContext<Impl>::clearArchRegs()
297{}
298
299template <class Impl>
300uint64_t
301O3ThreadContext<Impl>::readIntReg(int reg_idx)
302{
303 return cpu->readArchIntReg(reg_idx, thread->readTid());
304}
305
306template <class Impl>
307FloatReg
308O3ThreadContext<Impl>::readFloatReg(int reg_idx, int width)
309{
310 switch(width) {
311 case 32:
312 return cpu->readArchFloatRegSingle(reg_idx, thread->readTid());
313 case 64:
314 return cpu->readArchFloatRegDouble(reg_idx, thread->readTid());
315 default:
316 panic("Unsupported width!");
317 return 0;
318 }
319}
320
321template <class Impl>
322FloatReg
323O3ThreadContext<Impl>::readFloatReg(int reg_idx)
324{
325 return cpu->readArchFloatRegSingle(reg_idx, thread->readTid());
326}
327
328template <class Impl>
329FloatRegBits
330O3ThreadContext<Impl>::readFloatRegBits(int reg_idx, int width)
331{
332 DPRINTF(Fault, "Reading floatint register through the TC!\n");
333 return cpu->readArchFloatRegInt(reg_idx, thread->readTid());
334}
335
336template <class Impl>
337FloatRegBits
338O3ThreadContext<Impl>::readFloatRegBits(int reg_idx)
339{
340 return cpu->readArchFloatRegInt(reg_idx, thread->readTid());
341}
342
343template <class Impl>
344void
345O3ThreadContext<Impl>::setIntReg(int reg_idx, uint64_t val)
346{
347 cpu->setArchIntReg(reg_idx, val, thread->readTid());
348
349 // Squash if we're not already in a state update mode.
350 if (!thread->trapPending && !thread->inSyscall) {
351 cpu->squashFromTC(thread->readTid());
352 }
353}
354
355template <class Impl>
356void
357O3ThreadContext<Impl>::setFloatReg(int reg_idx, FloatReg val, int width)
358{
359 switch(width) {
360 case 32:
361 cpu->setArchFloatRegSingle(reg_idx, val, thread->readTid());
362 break;
363 case 64:
364 cpu->setArchFloatRegDouble(reg_idx, val, thread->readTid());
365 break;
366 }
367
368 // Squash if we're not already in a state update mode.
369 if (!thread->trapPending && !thread->inSyscall) {
370 cpu->squashFromTC(thread->readTid());
371 }
372}
373
374template <class Impl>
375void
376O3ThreadContext<Impl>::setFloatReg(int reg_idx, FloatReg val)
377{
378 cpu->setArchFloatRegSingle(reg_idx, val, thread->readTid());
379
380 if (!thread->trapPending && !thread->inSyscall) {
381 cpu->squashFromTC(thread->readTid());
382 }
383}
384
385template <class Impl>
386void
387O3ThreadContext<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val,
388 int width)
389{
390 DPRINTF(Fault, "Setting floatint register through the TC!\n");
391 cpu->setArchFloatRegInt(reg_idx, val, thread->readTid());
392
393 // Squash if we're not already in a state update mode.
394 if (!thread->trapPending && !thread->inSyscall) {
395 cpu->squashFromTC(thread->readTid());
396 }
397}
398
399template <class Impl>
400void
401O3ThreadContext<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val)
402{
403 cpu->setArchFloatRegInt(reg_idx, val, thread->readTid());
404
405 // Squash if we're not already in a state update mode.
406 if (!thread->trapPending && !thread->inSyscall) {
407 cpu->squashFromTC(thread->readTid());
408 }
409}
410
411template <class Impl>
412void
413O3ThreadContext<Impl>::setPC(uint64_t val)
414{
415 cpu->setPC(val, thread->readTid());
416
417 // Squash if we're not already in a state update mode.
418 if (!thread->trapPending && !thread->inSyscall) {
419 cpu->squashFromTC(thread->readTid());
420 }
421}
422
423template <class Impl>
424void
425O3ThreadContext<Impl>::setNextPC(uint64_t val)
426{
427 cpu->setNextPC(val, thread->readTid());
428
429 // Squash if we're not already in a state update mode.
430 if (!thread->trapPending && !thread->inSyscall) {
431 cpu->squashFromTC(thread->readTid());
432 }
433}
434
435template <class Impl>
436Fault
437O3ThreadContext<Impl>::setMiscReg(int misc_reg, const MiscReg &val)
438{
439 Fault ret_fault = cpu->setMiscReg(misc_reg, val, thread->readTid());
440
441 // Squash if we're not already in a state update mode.
442 if (!thread->trapPending && !thread->inSyscall) {
443 cpu->squashFromTC(thread->readTid());
444 }
445
446 return ret_fault;
447}
448
449template <class Impl>
450Fault
451O3ThreadContext<Impl>::setMiscRegWithEffect(int misc_reg,
452 const MiscReg &val)
453{
454 Fault ret_fault = cpu->setMiscRegWithEffect(misc_reg, val,
455 thread->readTid());
456
457 // Squash if we're not already in a state update mode.
458 if (!thread->trapPending && !thread->inSyscall) {
459 cpu->squashFromTC(thread->readTid());
460 }
461
462 return ret_fault;
463}
464
465#if !FULL_SYSTEM
466
467template <class Impl>
468TheISA::IntReg
469O3ThreadContext<Impl>::getSyscallArg(int i)
470{
471 return cpu->getSyscallArg(i, thread->readTid());
472}
473
474template <class Impl>
475void
476O3ThreadContext<Impl>::setSyscallArg(int i, IntReg val)
477{
478 cpu->setSyscallArg(i, val, thread->readTid());
479}
480
481template <class Impl>
482void
483O3ThreadContext<Impl>::setSyscallReturn(SyscallReturn return_value)
484{
485 cpu->setSyscallReturn(return_value, thread->readTid());
486}
487
488#endif // FULL_SYSTEM
489