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