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