simple_thread.hh revision 2680
1/* 2 * Copyright (c) 2001-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: Steve Reinhardt 29 * Nathan Binkert 30 */ 31 32#ifndef __CPU_CPU_EXEC_CONTEXT_HH__ 33#define __CPU_CPU_EXEC_CONTEXT_HH__ 34 35#include "arch/isa_traits.hh" 36#include "config/full_system.hh" 37#include "cpu/thread_context.hh" 38#include "mem/physical.hh" 39#include "mem/request.hh" 40#include "sim/byteswap.hh" 41#include "sim/eventq.hh" 42#include "sim/host.hh" 43#include "sim/serialize.hh" 44 45class BaseCPU; 46 47#if FULL_SYSTEM 48 49#include "sim/system.hh" 50#include "arch/tlb.hh" 51 52class FunctionProfile; 53class ProfileNode; 54class FunctionalPort; 55class PhysicalPort; 56 57 58namespace Kernel { 59 class Statistics; 60}; 61 62#else // !FULL_SYSTEM 63 64#include "sim/process.hh" 65#include "mem/page_table.hh" 66class TranslatingPort; 67 68 69#endif // FULL_SYSTEM 70 71// 72// The CPUExecContext object represents a functional context for 73// instruction execution. It incorporates everything required for 74// architecture-level functional simulation of a single thread. 75// 76 77class CPUExecContext 78{ 79 protected: 80 typedef TheISA::RegFile RegFile; 81 typedef TheISA::MachInst MachInst; 82 typedef TheISA::MiscRegFile MiscRegFile; 83 typedef TheISA::MiscReg MiscReg; 84 typedef TheISA::FloatReg FloatReg; 85 typedef TheISA::FloatRegBits FloatRegBits; 86 public: 87 typedef ThreadContext::Status Status; 88 89 private: 90 Status _status; 91 92 public: 93 Status status() const { return _status; } 94 95 void setStatus(Status newStatus) { _status = newStatus; } 96 97 /// Set the status to Active. Optional delay indicates number of 98 /// cycles to wait before beginning execution. 99 void activate(int delay = 1); 100 101 /// Set the status to Suspended. 102 void suspend(); 103 104 /// Set the status to Unallocated. 105 void deallocate(); 106 107 /// Set the status to Halted. 108 void halt(); 109 110 protected: 111 RegFile regs; // correct-path register context 112 113 public: 114 // pointer to CPU associated with this context 115 BaseCPU *cpu; 116 117 ProxyThreadContext<CPUExecContext> *tc; 118 119 // Current instruction 120 MachInst inst; 121 122 // Index of hardware thread context on the CPU that this represents. 123 int thread_num; 124 125 // ID of this context w.r.t. the System or Process object to which 126 // it belongs. For full-system mode, this is the system CPU ID. 127 int cpu_id; 128 129 Tick lastActivate; 130 Tick lastSuspend; 131 132 System *system; 133 134 135#if FULL_SYSTEM 136 AlphaITB *itb; 137 AlphaDTB *dtb; 138 139 /** A functional port outgoing only for functional accesses to physical 140 * addresses.*/ 141 FunctionalPort *physPort; 142 143 /** A functional port, outgoing only, for functional accesse to virtual 144 * addresses. That doen't require execution context information */ 145 VirtualPort *virtPort; 146 147 FunctionProfile *profile; 148 ProfileNode *profileNode; 149 Addr profilePC; 150 void dumpFuncProfile(); 151 152 EndQuiesceEvent *quiesceEvent; 153 154 EndQuiesceEvent *getQuiesceEvent() { return quiesceEvent; } 155 156 Tick readLastActivate() { return lastActivate; } 157 158 Tick readLastSuspend() { return lastSuspend; } 159 160 void profileClear(); 161 162 void profileSample(); 163 164 Kernel::Statistics *getKernelStats() { return kernelStats; } 165 166 Kernel::Statistics *kernelStats; 167#else 168 /// Port that syscalls can use to access memory (provides translation step). 169 TranslatingPort *port; 170 171 Process *process; 172 173 // Address space ID. Note that this is used for TIMING cache 174 // simulation only; all functional memory accesses should use 175 // one of the FunctionalMemory pointers above. 176 short asid; 177 178#endif 179 180 /** 181 * Temporary storage to pass the source address from copy_load to 182 * copy_store. 183 * @todo Remove this temporary when we have a better way to do it. 184 */ 185 Addr copySrcAddr; 186 /** 187 * Temp storage for the physical source address of a copy. 188 * @todo Remove this temporary when we have a better way to do it. 189 */ 190 Addr copySrcPhysAddr; 191 192 193 /* 194 * number of executed instructions, for matching with syscall trace 195 * points in EIO files. 196 */ 197 Counter func_exe_inst; 198 199 // 200 // Count failed store conditionals so we can warn of apparent 201 // application deadlock situations. 202 unsigned storeCondFailures; 203 204 // constructor: initialize context from given process structure 205#if FULL_SYSTEM 206 CPUExecContext(BaseCPU *_cpu, int _thread_num, System *_system, 207 AlphaITB *_itb, AlphaDTB *_dtb, 208 bool use_kernel_stats = true); 209#else 210 CPUExecContext(BaseCPU *_cpu, int _thread_num, Process *_process, int _asid, 211 MemObject *memobj); 212 // Constructor to use XC to pass reg file around. Not used for anything 213 // else. 214 CPUExecContext(RegFile *regFile); 215#endif 216 virtual ~CPUExecContext(); 217 218 virtual void takeOverFrom(ThreadContext *oldContext); 219 220 void regStats(const std::string &name); 221 222 void serialize(std::ostream &os); 223 void unserialize(Checkpoint *cp, const std::string §ion); 224 225 BaseCPU *getCpuPtr() { return cpu; } 226 227 ThreadContext *getTC() { return tc; } 228 229 int getThreadNum() { return thread_num; } 230 231#if FULL_SYSTEM 232 System *getSystemPtr() { return system; } 233 234 AlphaITB *getITBPtr() { return itb; } 235 236 AlphaDTB *getDTBPtr() { return dtb; } 237 238 int getInstAsid() { return regs.instAsid(); } 239 int getDataAsid() { return regs.dataAsid(); } 240 241 Fault translateInstReq(RequestPtr &req) 242 { 243 return itb->translate(req, tc); 244 } 245 246 Fault translateDataReadReq(RequestPtr &req) 247 { 248 return dtb->translate(req, tc, false); 249 } 250 251 Fault translateDataWriteReq(RequestPtr &req) 252 { 253 return dtb->translate(req, tc, true); 254 } 255 256 FunctionalPort *getPhysPort() { return physPort; } 257 258 /** Return a virtual port. If no thread context is specified then a static 259 * port is returned. Otherwise a port is created and returned. It must be 260 * deleted by deleteVirtPort(). */ 261 VirtualPort *getVirtPort(ThreadContext *tc); 262 263 void delVirtPort(VirtualPort *vp); 264 265#else 266 TranslatingPort *getMemPort() { return port; } 267 268 Process *getProcessPtr() { return process; } 269 270 int getInstAsid() { return asid; } 271 int getDataAsid() { return asid; } 272 273 Fault translateInstReq(RequestPtr &req) 274 { 275 return process->pTable->translate(req); 276 } 277 278 Fault translateDataReadReq(RequestPtr &req) 279 { 280 return process->pTable->translate(req); 281 } 282 283 Fault translateDataWriteReq(RequestPtr &req) 284 { 285 return process->pTable->translate(req); 286 } 287 288#endif 289 290/* 291 template <class T> 292 Fault read(RequestPtr &req, T &data) 293 { 294#if FULL_SYSTEM && THE_ISA == ALPHA_ISA 295 if (req->flags & LOCKED) { 296 req->xc->setMiscReg(TheISA::Lock_Addr_DepTag, req->paddr); 297 req->xc->setMiscReg(TheISA::Lock_Flag_DepTag, true); 298 } 299#endif 300 301 Fault error; 302 error = mem->prot_read(req->paddr, data, req->size); 303 data = LittleEndianGuest::gtoh(data); 304 return error; 305 } 306 307 template <class T> 308 Fault write(RequestPtr &req, T &data) 309 { 310#if FULL_SYSTEM && THE_ISA == ALPHA_ISA 311 ExecContext *xc; 312 313 // If this is a store conditional, act appropriately 314 if (req->flags & LOCKED) { 315 xc = req->xc; 316 317 if (req->flags & UNCACHEABLE) { 318 // Don't update result register (see stq_c in isa_desc) 319 req->result = 2; 320 xc->setStCondFailures(0);//Needed? [RGD] 321 } else { 322 bool lock_flag = xc->readMiscReg(TheISA::Lock_Flag_DepTag); 323 Addr lock_addr = xc->readMiscReg(TheISA::Lock_Addr_DepTag); 324 req->result = lock_flag; 325 if (!lock_flag || 326 ((lock_addr & ~0xf) != (req->paddr & ~0xf))) { 327 xc->setMiscReg(TheISA::Lock_Flag_DepTag, false); 328 xc->setStCondFailures(xc->readStCondFailures() + 1); 329 if (((xc->readStCondFailures()) % 100000) == 0) { 330 std::cerr << "Warning: " 331 << xc->readStCondFailures() 332 << " consecutive store conditional failures " 333 << "on cpu " << req->xc->readCpuId() 334 << std::endl; 335 } 336 return NoFault; 337 } 338 else xc->setStCondFailures(0); 339 } 340 } 341 342 // Need to clear any locked flags on other proccessors for 343 // this address. Only do this for succsful Store Conditionals 344 // and all other stores (WH64?). Unsuccessful Store 345 // Conditionals would have returned above, and wouldn't fall 346 // through. 347 for (int i = 0; i < system->execContexts.size(); i++){ 348 xc = system->execContexts[i]; 349 if ((xc->readMiscReg(TheISA::Lock_Addr_DepTag) & ~0xf) == 350 (req->paddr & ~0xf)) { 351 xc->setMiscReg(TheISA::Lock_Flag_DepTag, false); 352 } 353 } 354 355#endif 356 return mem->prot_write(req->paddr, (T)htog(data), req->size); 357 } 358*/ 359 virtual bool misspeculating(); 360 361 362 MachInst getInst() { return inst; } 363 364 void setInst(MachInst new_inst) 365 { 366 inst = new_inst; 367 } 368 369 Fault instRead(RequestPtr &req) 370 { 371 panic("instRead not implemented"); 372 // return funcPhysMem->read(req, inst); 373 return NoFault; 374 } 375 376 void setCpuId(int id) { cpu_id = id; } 377 378 int readCpuId() { return cpu_id; } 379 380 void copyArchRegs(ThreadContext *tc); 381 382 // 383 // New accessors for new decoder. 384 // 385 uint64_t readIntReg(int reg_idx) 386 { 387 return regs.readIntReg(reg_idx); 388 } 389 390 FloatReg readFloatReg(int reg_idx, int width) 391 { 392 return regs.readFloatReg(reg_idx, width); 393 } 394 395 FloatReg readFloatReg(int reg_idx) 396 { 397 return regs.readFloatReg(reg_idx); 398 } 399 400 FloatRegBits readFloatRegBits(int reg_idx, int width) 401 { 402 return regs.readFloatRegBits(reg_idx, width); 403 } 404 405 FloatRegBits readFloatRegBits(int reg_idx) 406 { 407 return regs.readFloatRegBits(reg_idx); 408 } 409 410 void setIntReg(int reg_idx, uint64_t val) 411 { 412 regs.setIntReg(reg_idx, val); 413 } 414 415 void setFloatReg(int reg_idx, FloatReg val, int width) 416 { 417 regs.setFloatReg(reg_idx, val, width); 418 } 419 420 void setFloatReg(int reg_idx, FloatReg val) 421 { 422 regs.setFloatReg(reg_idx, val); 423 } 424 425 void setFloatRegBits(int reg_idx, FloatRegBits val, int width) 426 { 427 regs.setFloatRegBits(reg_idx, val, width); 428 } 429 430 void setFloatRegBits(int reg_idx, FloatRegBits val) 431 { 432 regs.setFloatRegBits(reg_idx, val); 433 } 434 435 uint64_t readPC() 436 { 437 return regs.readPC(); 438 } 439 440 void setPC(uint64_t val) 441 { 442 regs.setPC(val); 443 } 444 445 uint64_t readNextPC() 446 { 447 return regs.readNextPC(); 448 } 449 450 void setNextPC(uint64_t val) 451 { 452 regs.setNextPC(val); 453 } 454 455 uint64_t readNextNPC() 456 { 457 return regs.readNextNPC(); 458 } 459 460 void setNextNPC(uint64_t val) 461 { 462 regs.setNextNPC(val); 463 } 464 465 466 MiscReg readMiscReg(int misc_reg) 467 { 468 return regs.readMiscReg(misc_reg); 469 } 470 471 MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault) 472 { 473 return regs.readMiscRegWithEffect(misc_reg, fault, tc); 474 } 475 476 Fault setMiscReg(int misc_reg, const MiscReg &val) 477 { 478 return regs.setMiscReg(misc_reg, val); 479 } 480 481 Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val) 482 { 483 return regs.setMiscRegWithEffect(misc_reg, val, tc); 484 } 485 486 unsigned readStCondFailures() { return storeCondFailures; } 487 488 void setStCondFailures(unsigned sc_failures) 489 { storeCondFailures = sc_failures; } 490 491 void clearArchRegs() { regs.clear(); } 492 493#if FULL_SYSTEM 494 int readIntrFlag() { return regs.intrflag; } 495 void setIntrFlag(int val) { regs.intrflag = val; } 496 Fault hwrei(); 497 bool inPalMode() { return AlphaISA::PcPAL(regs.readPC()); } 498 bool simPalCheck(int palFunc); 499#endif 500 501#if !FULL_SYSTEM 502 TheISA::IntReg getSyscallArg(int i) 503 { 504 return regs.readIntReg(TheISA::ArgumentReg0 + i); 505 } 506 507 // used to shift args for indirect syscall 508 void setSyscallArg(int i, TheISA::IntReg val) 509 { 510 regs.setIntReg(TheISA::ArgumentReg0 + i, val); 511 } 512 513 void setSyscallReturn(SyscallReturn return_value) 514 { 515 TheISA::setSyscallReturn(return_value, ®s); 516 } 517 518 void syscall(int64_t callnum) 519 { 520 process->syscall(callnum, tc); 521 } 522 523 Counter readFuncExeInst() { return func_exe_inst; } 524 525 void setFuncExeInst(Counter new_val) { func_exe_inst = new_val; } 526#endif 527 528 void changeRegFileContext(RegFile::ContextParam param, 529 RegFile::ContextVal val) 530 { 531 regs.changeContext(param, val); 532 } 533}; 534 535 536// for non-speculative execution context, spec_mode is always false 537inline bool 538CPUExecContext::misspeculating() 539{ 540 return false; 541} 542 543#endif // __CPU_CPU_EXEC_CONTEXT_HH__ 544