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