thread_context_impl.hh revision 3675:dc883b610345
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 §ion) 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 488