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