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