thread_context_impl.hh revision 3686:fa8d8b90cd8a
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 if (vp != thread->getVirtPort()) { 105 delete vp->getPeer(); 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() 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() 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 and the next PC. 292 cpu->setPC(tc->readPC(), tid); 293 cpu->setNextPC(tc->readNextPC(), tid); 294#if !FULL_SYSTEM 295 this->thread->funcExeInst = tc->readFuncExeInst(); 296#endif 297} 298 299template <class Impl> 300void 301O3ThreadContext<Impl>::clearArchRegs() 302{} 303 304template <class Impl> 305uint64_t 306O3ThreadContext<Impl>::readIntReg(int reg_idx) 307{ 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 cpu->setArchIntReg(reg_idx, val, thread->readTid()); 353 354 // Squash if we're not already in a state update mode. 355 if (!thread->trapPending && !thread->inSyscall) { 356 cpu->squashFromTC(thread->readTid()); 357 } 358} 359 360template <class Impl> 361void 362O3ThreadContext<Impl>::setFloatReg(int reg_idx, FloatReg val, int width) 363{ 364 switch(width) { 365 case 32: 366 cpu->setArchFloatRegSingle(reg_idx, val, thread->readTid()); 367 break; 368 case 64: 369 cpu->setArchFloatRegDouble(reg_idx, val, thread->readTid()); 370 break; 371 } 372 373 // Squash if we're not already in a state update mode. 374 if (!thread->trapPending && !thread->inSyscall) { 375 cpu->squashFromTC(thread->readTid()); 376 } 377} 378 379template <class Impl> 380void 381O3ThreadContext<Impl>::setFloatReg(int reg_idx, FloatReg val) 382{ 383 cpu->setArchFloatRegSingle(reg_idx, val, thread->readTid()); 384 385 if (!thread->trapPending && !thread->inSyscall) { 386 cpu->squashFromTC(thread->readTid()); 387 } 388} 389 390template <class Impl> 391void 392O3ThreadContext<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val, 393 int width) 394{ 395 DPRINTF(Fault, "Setting floatint register through the TC!\n"); 396 cpu->setArchFloatRegInt(reg_idx, val, thread->readTid()); 397 398 // Squash if we're not already in a state update mode. 399 if (!thread->trapPending && !thread->inSyscall) { 400 cpu->squashFromTC(thread->readTid()); 401 } 402} 403 404template <class Impl> 405void 406O3ThreadContext<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val) 407{ 408 cpu->setArchFloatRegInt(reg_idx, val, thread->readTid()); 409 410 // Squash if we're not already in a state update mode. 411 if (!thread->trapPending && !thread->inSyscall) { 412 cpu->squashFromTC(thread->readTid()); 413 } 414} 415 416template <class Impl> 417void 418O3ThreadContext<Impl>::setPC(uint64_t val) 419{ 420 cpu->setPC(val, thread->readTid()); 421 422 // Squash if we're not already in a state update mode. 423 if (!thread->trapPending && !thread->inSyscall) { 424 cpu->squashFromTC(thread->readTid()); 425 } 426} 427 428template <class Impl> 429void 430O3ThreadContext<Impl>::setNextPC(uint64_t val) 431{ 432 cpu->setNextPC(val, thread->readTid()); 433 434 // Squash if we're not already in a state update mode. 435 if (!thread->trapPending && !thread->inSyscall) { 436 cpu->squashFromTC(thread->readTid()); 437 } 438} 439 440template <class Impl> 441void 442O3ThreadContext<Impl>::setMiscReg(int misc_reg, const MiscReg &val) 443{ 444 cpu->setMiscReg(misc_reg, val, thread->readTid()); 445 446 // Squash if we're not already in a state update mode. 447 if (!thread->trapPending && !thread->inSyscall) { 448 cpu->squashFromTC(thread->readTid()); 449 } 450} 451 452template <class Impl> 453void 454O3ThreadContext<Impl>::setMiscRegWithEffect(int misc_reg, 455 const MiscReg &val) 456{ 457 cpu->setMiscRegWithEffect(misc_reg, val, thread->readTid()); 458 459 // Squash if we're not already in a state update mode. 460 if (!thread->trapPending && !thread->inSyscall) { 461 cpu->squashFromTC(thread->readTid()); 462 } 463} 464 465#if !FULL_SYSTEM 466 467template <class Impl> 468TheISA::IntReg 469O3ThreadContext<Impl>::getSyscallArg(int i) 470{ 471 return cpu->getSyscallArg(i, thread->readTid()); 472} 473 474template <class Impl> 475void 476O3ThreadContext<Impl>::setSyscallArg(int i, IntReg val) 477{ 478 cpu->setSyscallArg(i, val, thread->readTid()); 479} 480 481template <class Impl> 482void 483O3ThreadContext<Impl>::setSyscallReturn(SyscallReturn return_value) 484{ 485 cpu->setSyscallReturn(return_value, thread->readTid()); 486} 487 488#endif // FULL_SYSTEM 489 490