thread_context_impl.hh revision 6658
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/registers.hh" 33#include "config/the_isa.hh" 34#include "cpu/o3/thread_context.hh" 35#include "cpu/quiesce_event.hh" 36 37#if FULL_SYSTEM 38template <class Impl> 39VirtualPort * 40O3ThreadContext<Impl>::getVirtPort() 41{ 42 return thread->getVirtPort(); 43} 44 45template <class Impl> 46void 47O3ThreadContext<Impl>::dumpFuncProfile() 48{ 49 thread->dumpFuncProfile(); 50} 51#endif 52 53template <class Impl> 54void 55O3ThreadContext<Impl>::takeOverFrom(ThreadContext *old_context) 56{ 57 // some things should already be set up 58 assert(getSystemPtr() == old_context->getSystemPtr()); 59#if !FULL_SYSTEM 60 assert(getProcessPtr() == old_context->getProcessPtr()); 61#endif 62 63 // copy over functional state 64 setStatus(old_context->status()); 65 copyArchRegs(old_context); 66 setContextId(old_context->contextId()); 67 setThreadId(old_context->threadId()); 68 69#if !FULL_SYSTEM 70 thread->funcExeInst = old_context->readFuncExeInst(); 71#else 72 EndQuiesceEvent *other_quiesce = old_context->getQuiesceEvent(); 73 if (other_quiesce) { 74 // Point the quiesce event's TC at this TC so that it wakes up 75 // the proper CPU. 76 other_quiesce->tc = this; 77 } 78 if (thread->quiesceEvent) { 79 thread->quiesceEvent->tc = this; 80 } 81 82 // Transfer kernel stats from one CPU to the other. 83 thread->kernelStats = old_context->getKernelStats(); 84// storeCondFailures = 0; 85 cpu->lockFlag = false; 86#endif 87 88 old_context->setStatus(ThreadContext::Halted); 89 90 thread->inSyscall = false; 91 thread->trapPending = false; 92} 93 94template <class Impl> 95void 96O3ThreadContext<Impl>::activate(int delay) 97{ 98 DPRINTF(O3CPU, "Calling activate on Thread Context %d\n", 99 threadId()); 100 101 if (thread->status() == ThreadContext::Active) 102 return; 103 104#if FULL_SYSTEM 105 thread->lastActivate = curTick; 106#endif 107 108 thread->setStatus(ThreadContext::Active); 109 110 // status() == Suspended 111 cpu->activateContext(thread->threadId(), delay); 112} 113 114template <class Impl> 115void 116O3ThreadContext<Impl>::suspend(int delay) 117{ 118 DPRINTF(O3CPU, "Calling suspend on Thread Context %d\n", 119 threadId()); 120 121 if (thread->status() == ThreadContext::Suspended) 122 return; 123 124#if FULL_SYSTEM 125 thread->lastActivate = curTick; 126 thread->lastSuspend = curTick; 127#endif 128/* 129#if FULL_SYSTEM 130 // Don't change the status from active if there are pending interrupts 131 if (cpu->checkInterrupts()) { 132 assert(status() == ThreadContext::Active); 133 return; 134 } 135#endif 136*/ 137 thread->setStatus(ThreadContext::Suspended); 138 cpu->suspendContext(thread->threadId()); 139} 140 141template <class Impl> 142void 143O3ThreadContext<Impl>::halt(int delay) 144{ 145 DPRINTF(O3CPU, "Calling halt on Thread Context %d\n", 146 threadId()); 147 148 if (thread->status() == ThreadContext::Halted) 149 return; 150 151 thread->setStatus(ThreadContext::Halted); 152 cpu->haltContext(thread->threadId()); 153} 154 155template <class Impl> 156void 157O3ThreadContext<Impl>::regStats(const std::string &name) 158{ 159#if FULL_SYSTEM 160 thread->kernelStats = new TheISA::Kernel::Statistics(cpu->system); 161 thread->kernelStats->regStats(name + ".kern"); 162#endif 163} 164 165template <class Impl> 166void 167O3ThreadContext<Impl>::serialize(std::ostream &os) 168{ 169#if FULL_SYSTEM 170 if (thread->kernelStats) 171 thread->kernelStats->serialize(os); 172#endif 173 174} 175 176template <class Impl> 177void 178O3ThreadContext<Impl>::unserialize(Checkpoint *cp, const std::string §ion) 179{ 180#if FULL_SYSTEM 181 if (thread->kernelStats) 182 thread->kernelStats->unserialize(cp, section); 183#endif 184 185} 186 187#if FULL_SYSTEM 188template <class Impl> 189Tick 190O3ThreadContext<Impl>::readLastActivate() 191{ 192 return thread->lastActivate; 193} 194 195template <class Impl> 196Tick 197O3ThreadContext<Impl>::readLastSuspend() 198{ 199 return thread->lastSuspend; 200} 201 202template <class Impl> 203void 204O3ThreadContext<Impl>::profileClear() 205{ 206 thread->profileClear(); 207} 208 209template <class Impl> 210void 211O3ThreadContext<Impl>::profileSample() 212{ 213 thread->profileSample(); 214} 215#endif 216 217template <class Impl> 218TheISA::MachInst 219O3ThreadContext<Impl>:: getInst() 220{ 221 return thread->getInst(); 222} 223 224template <class Impl> 225void 226O3ThreadContext<Impl>::copyArchRegs(ThreadContext *tc) 227{ 228 // This function will mess things up unless the ROB is empty and 229 // there are no instructions in the pipeline. 230 ThreadID tid = thread->threadId(); 231 PhysRegIndex renamed_reg; 232 233 // First loop through the integer registers. 234 for (int i = 0; i < TheISA::NumIntRegs; ++i) { 235 renamed_reg = cpu->renameMap[tid].lookup(i); 236 237 DPRINTF(O3CPU, "Copying over register %i, had data %lli, " 238 "now has data %lli.\n", 239 renamed_reg, cpu->readIntReg(renamed_reg), 240 tc->readIntReg(i)); 241 242 cpu->setIntReg(renamed_reg, tc->readIntReg(i)); 243 } 244 245 // Then loop through the floating point registers. 246 for (int i = 0; i < TheISA::NumFloatRegs; ++i) { 247 renamed_reg = cpu->renameMap[tid].lookup(i + TheISA::FP_Base_DepTag); 248 cpu->setFloatRegBits(renamed_reg, 249 tc->readFloatRegBits(i)); 250 } 251 252 // Copy the misc regs. 253 TheISA::copyMiscRegs(tc, this); 254 255 // Then finally set the PC, the next PC, the nextNPC, the micropc, and the 256 // next micropc. 257 cpu->setPC(tc->readPC(), tid); 258 cpu->setNextPC(tc->readNextPC(), tid); 259 cpu->setNextNPC(tc->readNextNPC(), tid); 260 cpu->setMicroPC(tc->readMicroPC(), tid); 261 cpu->setNextMicroPC(tc->readNextMicroPC(), tid); 262#if !FULL_SYSTEM 263 this->thread->funcExeInst = tc->readFuncExeInst(); 264#endif 265} 266 267template <class Impl> 268void 269O3ThreadContext<Impl>::clearArchRegs() 270{} 271 272template <class Impl> 273uint64_t 274O3ThreadContext<Impl>::readIntReg(int reg_idx) 275{ 276 reg_idx = cpu->isa[thread->threadId()].flattenIntIndex(reg_idx); 277 return cpu->readArchIntReg(reg_idx, thread->threadId()); 278} 279 280template <class Impl> 281TheISA::FloatReg 282O3ThreadContext<Impl>::readFloatReg(int reg_idx) 283{ 284 reg_idx = cpu->isa[thread->threadId()].flattenFloatIndex(reg_idx); 285 return cpu->readArchFloatReg(reg_idx, thread->threadId()); 286} 287 288template <class Impl> 289TheISA::FloatRegBits 290O3ThreadContext<Impl>::readFloatRegBits(int reg_idx) 291{ 292 reg_idx = cpu->isa[thread->threadId()].flattenFloatIndex(reg_idx); 293 return cpu->readArchFloatRegInt(reg_idx, thread->threadId()); 294} 295 296template <class Impl> 297void 298O3ThreadContext<Impl>::setIntReg(int reg_idx, uint64_t val) 299{ 300 reg_idx = cpu->isa[thread->threadId()].flattenIntIndex(reg_idx); 301 cpu->setArchIntReg(reg_idx, val, thread->threadId()); 302 303 // Squash if we're not already in a state update mode. 304 if (!thread->trapPending && !thread->inSyscall) { 305 cpu->squashFromTC(thread->threadId()); 306 } 307} 308 309template <class Impl> 310void 311O3ThreadContext<Impl>::setFloatReg(int reg_idx, FloatReg val) 312{ 313 reg_idx = cpu->isa[thread->threadId()].flattenFloatIndex(reg_idx); 314 cpu->setArchFloatReg(reg_idx, val, thread->threadId()); 315 316 if (!thread->trapPending && !thread->inSyscall) { 317 cpu->squashFromTC(thread->threadId()); 318 } 319} 320 321template <class Impl> 322void 323O3ThreadContext<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val) 324{ 325 reg_idx = cpu->isa[thread->threadId()].flattenFloatIndex(reg_idx); 326 cpu->setArchFloatRegInt(reg_idx, val, thread->threadId()); 327 328 // Squash if we're not already in a state update mode. 329 if (!thread->trapPending && !thread->inSyscall) { 330 cpu->squashFromTC(thread->threadId()); 331 } 332} 333 334template <class Impl> 335void 336O3ThreadContext<Impl>::setPC(uint64_t val) 337{ 338 cpu->setPC(val, thread->threadId()); 339 340 // Squash if we're not already in a state update mode. 341 if (!thread->trapPending && !thread->inSyscall) { 342 cpu->squashFromTC(thread->threadId()); 343 } 344} 345 346template <class Impl> 347void 348O3ThreadContext<Impl>::setNextPC(uint64_t val) 349{ 350 cpu->setNextPC(val, thread->threadId()); 351 352 // Squash if we're not already in a state update mode. 353 if (!thread->trapPending && !thread->inSyscall) { 354 cpu->squashFromTC(thread->threadId()); 355 } 356} 357 358template <class Impl> 359void 360O3ThreadContext<Impl>::setMicroPC(uint64_t val) 361{ 362 cpu->setMicroPC(val, thread->threadId()); 363 364 // Squash if we're not already in a state update mode. 365 if (!thread->trapPending && !thread->inSyscall) { 366 cpu->squashFromTC(thread->threadId()); 367 } 368} 369 370template <class Impl> 371void 372O3ThreadContext<Impl>::setNextMicroPC(uint64_t val) 373{ 374 cpu->setNextMicroPC(val, thread->threadId()); 375 376 // Squash if we're not already in a state update mode. 377 if (!thread->trapPending && !thread->inSyscall) { 378 cpu->squashFromTC(thread->threadId()); 379 } 380} 381 382template <class Impl> 383int 384O3ThreadContext<Impl>::flattenIntIndex(int reg) 385{ 386 return cpu->isa[thread->threadId()].flattenIntIndex(reg); 387} 388 389template <class Impl> 390int 391O3ThreadContext<Impl>::flattenFloatIndex(int reg) 392{ 393 return cpu->isa[thread->threadId()].flattenFloatIndex(reg); 394} 395 396template <class Impl> 397void 398O3ThreadContext<Impl>::setMiscRegNoEffect(int misc_reg, const MiscReg &val) 399{ 400 cpu->setMiscRegNoEffect(misc_reg, val, thread->threadId()); 401 402 // Squash if we're not already in a state update mode. 403 if (!thread->trapPending && !thread->inSyscall) { 404 cpu->squashFromTC(thread->threadId()); 405 } 406} 407 408template <class Impl> 409void 410O3ThreadContext<Impl>::setMiscReg(int misc_reg, 411 const MiscReg &val) 412{ 413 cpu->setMiscReg(misc_reg, val, thread->threadId()); 414 415 // Squash if we're not already in a state update mode. 416 if (!thread->trapPending && !thread->inSyscall) { 417 cpu->squashFromTC(thread->threadId()); 418 } 419} 420 421