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