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