thread_context_impl.hh revision 5250
14202Sbinkertn@umich.edu/* 24202Sbinkertn@umich.edu * Copyright (c) 2004-2006 The Regents of The University of Michigan 34202Sbinkertn@umich.edu * All rights reserved. 44202Sbinkertn@umich.edu * 54202Sbinkertn@umich.edu * Redistribution and use in source and binary forms, with or without 64202Sbinkertn@umich.edu * modification, are permitted provided that the following conditions are 74202Sbinkertn@umich.edu * met: redistributions of source code must retain the above copyright 84202Sbinkertn@umich.edu * notice, this list of conditions and the following disclaimer; 94202Sbinkertn@umich.edu * redistributions in binary form must reproduce the above copyright 104202Sbinkertn@umich.edu * notice, this list of conditions and the following disclaimer in the 114202Sbinkertn@umich.edu * documentation and/or other materials provided with the distribution; 124202Sbinkertn@umich.edu * neither the name of the copyright holders nor the names of its 134202Sbinkertn@umich.edu * contributors may be used to endorse or promote products derived from 144202Sbinkertn@umich.edu * this software without specific prior written permission. 154202Sbinkertn@umich.edu * 164202Sbinkertn@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 174202Sbinkertn@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 184202Sbinkertn@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 194202Sbinkertn@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 204202Sbinkertn@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 214202Sbinkertn@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 224202Sbinkertn@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 234202Sbinkertn@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 244202Sbinkertn@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 254202Sbinkertn@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 264202Sbinkertn@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 274202Sbinkertn@umich.edu * 284202Sbinkertn@umich.edu * Authors: Kevin Lim 294202Sbinkertn@umich.edu * Korey Sewell 304202Sbinkertn@umich.edu */ 314202Sbinkertn@umich.edu 324202Sbinkertn@umich.edu#include "arch/regfile.hh" 3310996Sandreas.sandberg@arm.com#include "cpu/o3/thread_context.hh" 3410996Sandreas.sandberg@arm.com#include "cpu/quiesce_event.hh" 359398Sandreas.hansson@arm.com 369850Sandreas.hansson@arm.com#if FULL_SYSTEM 379259SAli.Saidi@ARM.comtemplate <class Impl> 384486Sbinkertn@umich.eduVirtualPort * 3910146Sandreas.hansson@arm.comO3ThreadContext<Impl>::getVirtPort(ThreadContext *src_tc) 4010478SAndrew.Bardsley@arm.com{ 4110478SAndrew.Bardsley@arm.com if (!src_tc) 426165Ssanchezd@stanford.edu return thread->getVirtPort(); 439850Sandreas.hansson@arm.com 4410405Sandreas.hansson@arm.com VirtualPort *vp; 4511184Serfan.azarkhish@unibo.it 4611185Serfan.azarkhish@unibo.it vp = new VirtualPort("tc-vport", src_tc); 4712802Sandreas.sandberg@arm.com thread->connectToMemFunc(vp); 486168Snate@binkert.org return vp; 499850Sandreas.hansson@arm.com} 509259SAli.Saidi@ARM.com 514202Sbinkertn@umich.edutemplate <class Impl> 5210405Sandreas.hansson@arm.comvoid 5310431SOmar.Naji@arm.comO3ThreadContext<Impl>::dumpFuncProfile() 5410146Sandreas.hansson@arm.com{ 5510478SAndrew.Bardsley@arm.com thread->dumpFuncProfile(); 5610478SAndrew.Bardsley@arm.com} 574202Sbinkertn@umich.edu#endif 588761Sgblack@eecs.umich.edu 5910405Sandreas.hansson@arm.comtemplate <class Impl> 604202Sbinkertn@umich.eduvoid 614202Sbinkertn@umich.eduO3ThreadContext<Impl>::takeOverFrom(ThreadContext *old_context) 628914Sandreas.hansson@arm.com{ 6310405Sandreas.hansson@arm.com // some things should already be set up 6410405Sandreas.hansson@arm.com#if FULL_SYSTEM 6510405Sandreas.hansson@arm.com assert(getSystemPtr() == old_context->getSystemPtr()); 6610405Sandreas.hansson@arm.com#else 6710614Skanishk.sugand@arm.com assert(getProcessPtr() == old_context->getProcessPtr()); 684202Sbinkertn@umich.edu#endif 6910405Sandreas.hansson@arm.com 7011184Serfan.azarkhish@unibo.it // copy over functional state 7111185Serfan.azarkhish@unibo.it setStatus(old_context->status()); 7212802Sandreas.sandberg@arm.com copyArchRegs(old_context); 736168Snate@binkert.org setCpuId(old_context->readCpuId()); 749850Sandreas.hansson@arm.com 759850Sandreas.hansson@arm.com#if !FULL_SYSTEM 769850Sandreas.hansson@arm.com thread->funcExeInst = old_context->readFuncExeInst(); 778763Sgblack@eecs.umich.edu#else 787768SAli.Saidi@ARM.com EndQuiesceEvent *other_quiesce = old_context->getQuiesceEvent(); 7910131Sandreas.hansson@arm.com if (other_quiesce) { 8010131Sandreas.hansson@arm.com // Point the quiesce event's TC at this TC so that it wakes up 8110131Sandreas.hansson@arm.com // the proper CPU. 8210131Sandreas.hansson@arm.com other_quiesce->tc = this; 8310066Sandreas.hansson@arm.com } 8410612SMarco.Elver@ARM.com if (thread->quiesceEvent) { 8510612SMarco.Elver@ARM.com thread->quiesceEvent->tc = this; 8610612SMarco.Elver@ARM.com } 8710612SMarco.Elver@ARM.com 8810405Sandreas.hansson@arm.com // Transfer kernel stats from one CPU to the other. 8910405Sandreas.hansson@arm.com thread->kernelStats = old_context->getKernelStats(); 9010405Sandreas.hansson@arm.com// storeCondFailures = 0; 9110405Sandreas.hansson@arm.com cpu->lockFlag = false; 9210399Sstephan.diestelhorst@arm.com#endif 9310405Sandreas.hansson@arm.com 9410405Sandreas.hansson@arm.com old_context->setStatus(ThreadContext::Unallocated); 959036Sandreas.hansson@arm.com 969164Sandreas.hansson@arm.com thread->inSyscall = false; 978981Sandreas.hansson@arm.com thread->trapPending = false; 989243Sandreas.hansson@arm.com} 9910247Sandreas.hansson@arm.com 10010208Sandreas.hansson@arm.com#if FULL_SYSTEM 10110478SAndrew.Bardsley@arm.comtemplate <class Impl> 1028335Snate@binkert.orgvoid 1038335Snate@binkert.orgO3ThreadContext<Impl>::delVirtPort(VirtualPort *vp) 1048335Snate@binkert.org{ 1058914Sandreas.hansson@arm.com if (vp != thread->getVirtPort()) { 10610614Skanishk.sugand@arm.com vp->removeConn(); 10710066Sandreas.hansson@arm.com delete vp; 10811184Serfan.azarkhish@unibo.it } 10911185Serfan.azarkhish@unibo.it} 11010612SMarco.Elver@ARM.com#endif 11110612SMarco.Elver@ARM.com 11210612SMarco.Elver@ARM.comtemplate <class Impl> 113void 114O3ThreadContext<Impl>::activate(int delay) 115{ 116 DPRINTF(O3CPU, "Calling activate on Thread Context %d\n", 117 getThreadNum()); 118 119 if (thread->status() == ThreadContext::Active) 120 return; 121 122#if FULL_SYSTEM 123 thread->lastActivate = curTick; 124#endif 125 126 if (thread->status() == ThreadContext::Unallocated) { 127 cpu->activateWhenReady(thread->readTid()); 128 return; 129 } 130 131 thread->setStatus(ThreadContext::Active); 132 133 // status() == Suspended 134 cpu->activateContext(thread->readTid(), delay); 135} 136 137template <class Impl> 138void 139O3ThreadContext<Impl>::suspend(int delay) 140{ 141 DPRINTF(O3CPU, "Calling suspend on Thread Context %d\n", 142 getThreadNum()); 143 144 if (thread->status() == ThreadContext::Suspended) 145 return; 146 147#if FULL_SYSTEM 148 thread->lastActivate = curTick; 149 thread->lastSuspend = curTick; 150#endif 151/* 152#if FULL_SYSTEM 153 // Don't change the status from active if there are pending interrupts 154 if (cpu->check_interrupts()) { 155 assert(status() == ThreadContext::Active); 156 return; 157 } 158#endif 159*/ 160 thread->setStatus(ThreadContext::Suspended); 161 cpu->suspendContext(thread->readTid()); 162} 163 164template <class Impl> 165void 166O3ThreadContext<Impl>::deallocate(int delay) 167{ 168 DPRINTF(O3CPU, "Calling deallocate on Thread Context %d delay %d\n", 169 getThreadNum(), delay); 170 171 if (thread->status() == ThreadContext::Unallocated) 172 return; 173 174 thread->setStatus(ThreadContext::Unallocated); 175 cpu->deallocateContext(thread->readTid(), true, delay); 176} 177 178template <class Impl> 179void 180O3ThreadContext<Impl>::halt(int delay) 181{ 182 DPRINTF(O3CPU, "Calling halt on Thread Context %d\n", 183 getThreadNum()); 184 185 if (thread->status() == ThreadContext::Halted) 186 return; 187 188 thread->setStatus(ThreadContext::Halted); 189 cpu->haltContext(thread->readTid()); 190} 191 192template <class Impl> 193void 194O3ThreadContext<Impl>::regStats(const std::string &name) 195{ 196#if FULL_SYSTEM 197 thread->kernelStats = new TheISA::Kernel::Statistics(cpu->system); 198 thread->kernelStats->regStats(name + ".kern"); 199#endif 200} 201 202template <class Impl> 203void 204O3ThreadContext<Impl>::serialize(std::ostream &os) 205{ 206#if FULL_SYSTEM 207 if (thread->kernelStats) 208 thread->kernelStats->serialize(os); 209#endif 210 211} 212 213template <class Impl> 214void 215O3ThreadContext<Impl>::unserialize(Checkpoint *cp, const std::string §ion) 216{ 217#if FULL_SYSTEM 218 if (thread->kernelStats) 219 thread->kernelStats->unserialize(cp, section); 220#endif 221 222} 223 224#if FULL_SYSTEM 225template <class Impl> 226Tick 227O3ThreadContext<Impl>::readLastActivate() 228{ 229 return thread->lastActivate; 230} 231 232template <class Impl> 233Tick 234O3ThreadContext<Impl>::readLastSuspend() 235{ 236 return thread->lastSuspend; 237} 238 239template <class Impl> 240void 241O3ThreadContext<Impl>::profileClear() 242{ 243 thread->profileClear(); 244} 245 246template <class Impl> 247void 248O3ThreadContext<Impl>::profileSample() 249{ 250 thread->profileSample(); 251} 252#endif 253 254template <class Impl> 255TheISA::MachInst 256O3ThreadContext<Impl>:: getInst() 257{ 258 return thread->getInst(); 259} 260 261template <class Impl> 262void 263O3ThreadContext<Impl>::copyArchRegs(ThreadContext *tc) 264{ 265 // This function will mess things up unless the ROB is empty and 266 // there are no instructions in the pipeline. 267 unsigned tid = thread->readTid(); 268 PhysRegIndex renamed_reg; 269 270 // First loop through the integer registers. 271 for (int i = 0; i < TheISA::NumIntRegs; ++i) { 272 renamed_reg = cpu->renameMap[tid].lookup(i); 273 274 DPRINTF(O3CPU, "Copying over register %i, had data %lli, " 275 "now has data %lli.\n", 276 renamed_reg, cpu->readIntReg(renamed_reg), 277 tc->readIntReg(i)); 278 279 cpu->setIntReg(renamed_reg, tc->readIntReg(i)); 280 } 281 282 // Then loop through the floating point registers. 283 for (int i = 0; i < TheISA::NumFloatRegs; ++i) { 284 renamed_reg = cpu->renameMap[tid].lookup(i + TheISA::FP_Base_DepTag); 285 cpu->setFloatRegBits(renamed_reg, 286 tc->readFloatRegBits(i)); 287 } 288 289 // Copy the misc regs. 290 TheISA::copyMiscRegs(tc, this); 291 292 // Then finally set the PC and the next PC. 293 cpu->setPC(tc->readPC(), tid); 294 cpu->setNextPC(tc->readNextPC(), tid); 295#if !FULL_SYSTEM 296 this->thread->funcExeInst = tc->readFuncExeInst(); 297#endif 298} 299 300template <class Impl> 301void 302O3ThreadContext<Impl>::clearArchRegs() 303{} 304 305template <class Impl> 306uint64_t 307O3ThreadContext<Impl>::readIntReg(int reg_idx) 308{ 309 reg_idx = TheISA::flattenIntIndex(this, reg_idx); 310 return cpu->readArchIntReg(reg_idx, thread->readTid()); 311} 312 313template <class Impl> 314TheISA::FloatReg 315O3ThreadContext<Impl>::readFloatReg(int reg_idx, int width) 316{ 317 switch(width) { 318 case 32: 319 return cpu->readArchFloatRegSingle(reg_idx, thread->readTid()); 320 case 64: 321 return cpu->readArchFloatRegDouble(reg_idx, thread->readTid()); 322 default: 323 panic("Unsupported width!"); 324 return 0; 325 } 326} 327 328template <class Impl> 329TheISA::FloatReg 330O3ThreadContext<Impl>::readFloatReg(int reg_idx) 331{ 332 return cpu->readArchFloatRegSingle(reg_idx, thread->readTid()); 333} 334 335template <class Impl> 336TheISA::FloatRegBits 337O3ThreadContext<Impl>::readFloatRegBits(int reg_idx, int width) 338{ 339 DPRINTF(Fault, "Reading floatint register through the TC!\n"); 340 return cpu->readArchFloatRegInt(reg_idx, thread->readTid()); 341} 342 343template <class Impl> 344TheISA::FloatRegBits 345O3ThreadContext<Impl>::readFloatRegBits(int reg_idx) 346{ 347 return cpu->readArchFloatRegInt(reg_idx, thread->readTid()); 348} 349 350template <class Impl> 351void 352O3ThreadContext<Impl>::setIntReg(int reg_idx, uint64_t val) 353{ 354 reg_idx = TheISA::flattenIntIndex(this, reg_idx); 355 cpu->setArchIntReg(reg_idx, val, thread->readTid()); 356 357 // Squash if we're not already in a state update mode. 358 if (!thread->trapPending && !thread->inSyscall) { 359 cpu->squashFromTC(thread->readTid()); 360 } 361} 362 363template <class Impl> 364void 365O3ThreadContext<Impl>::setFloatReg(int reg_idx, FloatReg val, int width) 366{ 367 switch(width) { 368 case 32: 369 cpu->setArchFloatRegSingle(reg_idx, val, thread->readTid()); 370 break; 371 case 64: 372 cpu->setArchFloatRegDouble(reg_idx, val, thread->readTid()); 373 break; 374 } 375 376 // Squash if we're not already in a state update mode. 377 if (!thread->trapPending && !thread->inSyscall) { 378 cpu->squashFromTC(thread->readTid()); 379 } 380} 381 382template <class Impl> 383void 384O3ThreadContext<Impl>::setFloatReg(int reg_idx, FloatReg val) 385{ 386 cpu->setArchFloatRegSingle(reg_idx, val, thread->readTid()); 387 388 if (!thread->trapPending && !thread->inSyscall) { 389 cpu->squashFromTC(thread->readTid()); 390 } 391} 392 393template <class Impl> 394void 395O3ThreadContext<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val, 396 int width) 397{ 398 DPRINTF(Fault, "Setting floatint register through the TC!\n"); 399 cpu->setArchFloatRegInt(reg_idx, val, thread->readTid()); 400 401 // Squash if we're not already in a state update mode. 402 if (!thread->trapPending && !thread->inSyscall) { 403 cpu->squashFromTC(thread->readTid()); 404 } 405} 406 407template <class Impl> 408void 409O3ThreadContext<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val) 410{ 411 cpu->setArchFloatRegInt(reg_idx, val, thread->readTid()); 412 413 // Squash if we're not already in a state update mode. 414 if (!thread->trapPending && !thread->inSyscall) { 415 cpu->squashFromTC(thread->readTid()); 416 } 417} 418 419template <class Impl> 420void 421O3ThreadContext<Impl>::setPC(uint64_t val) 422{ 423 cpu->setPC(val, thread->readTid()); 424 425 // Squash if we're not already in a state update mode. 426 if (!thread->trapPending && !thread->inSyscall) { 427 cpu->squashFromTC(thread->readTid()); 428 } 429} 430 431template <class Impl> 432void 433O3ThreadContext<Impl>::setNextPC(uint64_t val) 434{ 435 cpu->setNextPC(val, thread->readTid()); 436 437 // Squash if we're not already in a state update mode. 438 if (!thread->trapPending && !thread->inSyscall) { 439 cpu->squashFromTC(thread->readTid()); 440 } 441} 442 443template <class Impl> 444void 445O3ThreadContext<Impl>::setMiscRegNoEffect(int misc_reg, const MiscReg &val) 446{ 447 cpu->setMiscRegNoEffect(misc_reg, val, thread->readTid()); 448 449 // Squash if we're not already in a state update mode. 450 if (!thread->trapPending && !thread->inSyscall) { 451 cpu->squashFromTC(thread->readTid()); 452 } 453} 454 455template <class Impl> 456void 457O3ThreadContext<Impl>::setMiscReg(int misc_reg, 458 const MiscReg &val) 459{ 460 cpu->setMiscReg(misc_reg, val, thread->readTid()); 461 462 // Squash if we're not already in a state update mode. 463 if (!thread->trapPending && !thread->inSyscall) { 464 cpu->squashFromTC(thread->readTid()); 465 } 466} 467 468#if !FULL_SYSTEM 469 470template <class Impl> 471TheISA::IntReg 472O3ThreadContext<Impl>::getSyscallArg(int i) 473{ 474 return cpu->getSyscallArg(i, thread->readTid()); 475} 476 477template <class Impl> 478void 479O3ThreadContext<Impl>::setSyscallArg(int i, IntReg val) 480{ 481 cpu->setSyscallArg(i, val, thread->readTid()); 482} 483 484template <class Impl> 485void 486O3ThreadContext<Impl>::setSyscallReturn(SyscallReturn return_value) 487{ 488 cpu->setSyscallReturn(return_value, thread->readTid()); 489} 490 491#endif // FULL_SYSTEM 492 493