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