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