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