thread_context_impl.hh revision 3776:4f88e76d8ebe
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 delete vp->getPeer(); 106 delete vp; 107} 108#endif 109 110template <class Impl> 111void 112O3ThreadContext<Impl>::activate(int delay) 113{ 114 DPRINTF(O3CPU, "Calling activate on Thread Context %d\n", 115 getThreadNum()); 116 117 if (thread->status() == ThreadContext::Active) 118 return; 119 120#if FULL_SYSTEM 121 thread->lastActivate = curTick; 122#endif 123 124 if (thread->status() == ThreadContext::Unallocated) { 125 cpu->activateWhenReady(thread->readTid()); 126 return; 127 } 128 129 thread->setStatus(ThreadContext::Active); 130 131 // status() == Suspended 132 cpu->activateContext(thread->readTid(), delay); 133} 134 135template <class Impl> 136void 137O3ThreadContext<Impl>::suspend() 138{ 139 DPRINTF(O3CPU, "Calling suspend on Thread Context %d\n", 140 getThreadNum()); 141 142 if (thread->status() == ThreadContext::Suspended) 143 return; 144 145#if FULL_SYSTEM 146 thread->lastActivate = curTick; 147 thread->lastSuspend = curTick; 148#endif 149/* 150#if FULL_SYSTEM 151 // Don't change the status from active if there are pending interrupts 152 if (cpu->check_interrupts()) { 153 assert(status() == ThreadContext::Active); 154 return; 155 } 156#endif 157*/ 158 thread->setStatus(ThreadContext::Suspended); 159 cpu->suspendContext(thread->readTid()); 160} 161 162template <class Impl> 163void 164O3ThreadContext<Impl>::deallocate(int delay) 165{ 166 DPRINTF(O3CPU, "Calling deallocate on Thread Context %d delay %d\n", 167 getThreadNum(), delay); 168 169 if (thread->status() == ThreadContext::Unallocated) 170 return; 171 172 thread->setStatus(ThreadContext::Unallocated); 173 cpu->deallocateContext(thread->readTid(), true, delay); 174} 175 176template <class Impl> 177void 178O3ThreadContext<Impl>::halt() 179{ 180 DPRINTF(O3CPU, "Calling halt on Thread Context %d\n", 181 getThreadNum()); 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 TheISA::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 §ion) 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 thread->profileClear(); 242} 243 244template <class Impl> 245void 246O3ThreadContext<Impl>::profileSample() 247{ 248 thread->profileSample(); 249} 250#endif 251 252template <class Impl> 253TheISA::MachInst 254O3ThreadContext<Impl>:: getInst() 255{ 256 return thread->getInst(); 257} 258 259template <class Impl> 260void 261O3ThreadContext<Impl>::copyArchRegs(ThreadContext *tc) 262{ 263 // This function will mess things up unless the ROB is empty and 264 // there are no instructions in the pipeline. 265 unsigned tid = thread->readTid(); 266 PhysRegIndex renamed_reg; 267 268 // First loop through the integer registers. 269 for (int i = 0; i < TheISA::NumIntRegs; ++i) { 270 renamed_reg = cpu->renameMap[tid].lookup(i); 271 272 DPRINTF(O3CPU, "Copying over register %i, had data %lli, " 273 "now has data %lli.\n", 274 renamed_reg, cpu->readIntReg(renamed_reg), 275 tc->readIntReg(i)); 276 277 cpu->setIntReg(renamed_reg, tc->readIntReg(i)); 278 } 279 280 // Then loop through the floating point registers. 281 for (int i = 0; i < TheISA::NumFloatRegs; ++i) { 282 renamed_reg = cpu->renameMap[tid].lookup(i + TheISA::FP_Base_DepTag); 283 cpu->setFloatRegBits(renamed_reg, 284 tc->readFloatRegBits(i)); 285 } 286 287 // Copy the misc regs. 288 TheISA::copyMiscRegs(tc, this); 289 290 // Then finally set the PC and the next PC. 291 cpu->setPC(tc->readPC(), tid); 292 cpu->setNextPC(tc->readNextPC(), tid); 293#if !FULL_SYSTEM 294 this->thread->funcExeInst = tc->readFuncExeInst(); 295#endif 296} 297 298template <class Impl> 299void 300O3ThreadContext<Impl>::clearArchRegs() 301{} 302 303template <class Impl> 304uint64_t 305O3ThreadContext<Impl>::readIntReg(int reg_idx) 306{ 307 reg_idx = TheISA::flattenIntIndex(this, reg_idx); 308 return cpu->readArchIntReg(reg_idx, thread->readTid()); 309} 310 311template <class Impl> 312TheISA::FloatReg 313O3ThreadContext<Impl>::readFloatReg(int reg_idx, int width) 314{ 315 switch(width) { 316 case 32: 317 return cpu->readArchFloatRegSingle(reg_idx, thread->readTid()); 318 case 64: 319 return cpu->readArchFloatRegDouble(reg_idx, thread->readTid()); 320 default: 321 panic("Unsupported width!"); 322 return 0; 323 } 324} 325 326template <class Impl> 327TheISA::FloatReg 328O3ThreadContext<Impl>::readFloatReg(int reg_idx) 329{ 330 return cpu->readArchFloatRegSingle(reg_idx, thread->readTid()); 331} 332 333template <class Impl> 334TheISA::FloatRegBits 335O3ThreadContext<Impl>::readFloatRegBits(int reg_idx, int width) 336{ 337 DPRINTF(Fault, "Reading floatint register through the TC!\n"); 338 return cpu->readArchFloatRegInt(reg_idx, thread->readTid()); 339} 340 341template <class Impl> 342TheISA::FloatRegBits 343O3ThreadContext<Impl>::readFloatRegBits(int reg_idx) 344{ 345 return cpu->readArchFloatRegInt(reg_idx, thread->readTid()); 346} 347 348template <class Impl> 349void 350O3ThreadContext<Impl>::setIntReg(int reg_idx, uint64_t val) 351{ 352 reg_idx = TheISA::flattenIntIndex(this, reg_idx); 353 cpu->setArchIntReg(reg_idx, val, thread->readTid()); 354 355 // Squash if we're not already in a state update mode. 356 if (!thread->trapPending && !thread->inSyscall) { 357 cpu->squashFromTC(thread->readTid()); 358 } 359} 360 361template <class Impl> 362void 363O3ThreadContext<Impl>::setFloatReg(int reg_idx, FloatReg val, int width) 364{ 365 switch(width) { 366 case 32: 367 cpu->setArchFloatRegSingle(reg_idx, val, thread->readTid()); 368 break; 369 case 64: 370 cpu->setArchFloatRegDouble(reg_idx, val, thread->readTid()); 371 break; 372 } 373 374 // Squash if we're not already in a state update mode. 375 if (!thread->trapPending && !thread->inSyscall) { 376 cpu->squashFromTC(thread->readTid()); 377 } 378} 379 380template <class Impl> 381void 382O3ThreadContext<Impl>::setFloatReg(int reg_idx, FloatReg val) 383{ 384 cpu->setArchFloatRegSingle(reg_idx, val, thread->readTid()); 385 386 if (!thread->trapPending && !thread->inSyscall) { 387 cpu->squashFromTC(thread->readTid()); 388 } 389} 390 391template <class Impl> 392void 393O3ThreadContext<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val, 394 int width) 395{ 396 DPRINTF(Fault, "Setting floatint register through the TC!\n"); 397 cpu->setArchFloatRegInt(reg_idx, val, thread->readTid()); 398 399 // Squash if we're not already in a state update mode. 400 if (!thread->trapPending && !thread->inSyscall) { 401 cpu->squashFromTC(thread->readTid()); 402 } 403} 404 405template <class Impl> 406void 407O3ThreadContext<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val) 408{ 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>::setPC(uint64_t val) 420{ 421 cpu->setPC(val, thread->readTid()); 422 423 // Squash if we're not already in a state update mode. 424 if (!thread->trapPending && !thread->inSyscall) { 425 cpu->squashFromTC(thread->readTid()); 426 } 427} 428 429template <class Impl> 430void 431O3ThreadContext<Impl>::setNextPC(uint64_t val) 432{ 433 cpu->setNextPC(val, thread->readTid()); 434 435 // Squash if we're not already in a state update mode. 436 if (!thread->trapPending && !thread->inSyscall) { 437 cpu->squashFromTC(thread->readTid()); 438 } 439} 440 441template <class Impl> 442void 443O3ThreadContext<Impl>::setMiscReg(int misc_reg, const MiscReg &val) 444{ 445 cpu->setMiscReg(misc_reg, val, thread->readTid()); 446 447 // Squash if we're not already in a state update mode. 448 if (!thread->trapPending && !thread->inSyscall) { 449 cpu->squashFromTC(thread->readTid()); 450 } 451} 452 453template <class Impl> 454void 455O3ThreadContext<Impl>::setMiscRegWithEffect(int misc_reg, 456 const MiscReg &val) 457{ 458 cpu->setMiscRegWithEffect(misc_reg, 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 466#if !FULL_SYSTEM 467 468template <class Impl> 469TheISA::IntReg 470O3ThreadContext<Impl>::getSyscallArg(int i) 471{ 472 return cpu->getSyscallArg(i, thread->readTid()); 473} 474 475template <class Impl> 476void 477O3ThreadContext<Impl>::setSyscallArg(int i, IntReg val) 478{ 479 cpu->setSyscallArg(i, val, thread->readTid()); 480} 481 482template <class Impl> 483void 484O3ThreadContext<Impl>::setSyscallReturn(SyscallReturn return_value) 485{ 486 cpu->setSyscallReturn(return_value, thread->readTid()); 487} 488 489#endif // FULL_SYSTEM 490 491