simple_thread.hh revision 2683
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_SIMPLE_THREAD_HH__ 33#define __CPU_SIMPLE_THREAD_HH__ 34 35#include "arch/isa_traits.hh" 36#include "config/full_system.hh" 37#include "cpu/thread_context.hh" 38#include "cpu/thread_state.hh" 39#include "mem/physical.hh" 40#include "mem/request.hh" 41#include "sim/byteswap.hh" 42#include "sim/eventq.hh" 43#include "sim/host.hh" 44#include "sim/serialize.hh" 45 46class BaseCPU; 47 48#if FULL_SYSTEM 49 50#include "sim/system.hh" 51#include "arch/tlb.hh" 52 53class FunctionProfile; 54class ProfileNode; 55class FunctionalPort; 56class PhysicalPort; 57 58namespace Kernel { 59 class Statistics; 60}; 61 62#else // !FULL_SYSTEM 63 64#include "sim/process.hh" 65#include "mem/page_table.hh" 66class TranslatingPort; 67 68#endif // FULL_SYSTEM 69 70/** 71 * The SimpleThread object provides a combination of the ThreadState 72 * object and the ThreadContext interface. It implements the 73 * ThreadContext interface so that a ProxyThreadContext class can be 74 * made using SimpleThread as the template parameter (see 75 * thread_context.hh). It adds to the ThreadState object by adding all 76 * the objects needed for simple functional execution, including a 77 * simple architectural register file, and pointers to the ITB and DTB 78 * in full system mode. For CPU models that do not need more advanced 79 * ways to hold state (i.e. a separate physical register file, or 80 * separate fetch and commit PC's), this SimpleThread class provides 81 * all the necessary state for full architecture-level functional 82 * simulation. See the AtomicSimpleCPU or TimingSimpleCPU for 83 * examples. 84 */ 85 86class SimpleThread : public ThreadState 87{ 88 protected: 89 typedef TheISA::RegFile RegFile; 90 typedef TheISA::MachInst MachInst; 91 typedef TheISA::MiscRegFile MiscRegFile; 92 typedef TheISA::MiscReg MiscReg; 93 typedef TheISA::FloatReg FloatReg; 94 typedef TheISA::FloatRegBits FloatRegBits; 95 public: 96 typedef ThreadContext::Status Status; 97 98 protected: 99 RegFile regs; // correct-path register context 100 101 public: 102 // pointer to CPU associated with this SimpleThread 103 BaseCPU *cpu; 104 105 ProxyThreadContext<SimpleThread> *tc; 106 107 System *system; 108 109#if FULL_SYSTEM 110 AlphaITB *itb; 111 AlphaDTB *dtb; 112#endif 113 114 // constructor: initialize SimpleThread from given process structure 115#if FULL_SYSTEM 116 SimpleThread(BaseCPU *_cpu, int _thread_num, System *_system, 117 AlphaITB *_itb, AlphaDTB *_dtb, 118 bool use_kernel_stats = true); 119#else 120 SimpleThread(BaseCPU *_cpu, int _thread_num, Process *_process, int _asid, 121 MemObject *memobj); 122 // Constructor to use SimpleThread to pass reg file around. Not 123 // used for anything else. 124 SimpleThread(RegFile *regFile); 125#endif 126 virtual ~SimpleThread(); 127 128 virtual void takeOverFrom(ThreadContext *oldContext); 129 130 void regStats(const std::string &name); 131 132 void serialize(std::ostream &os); 133 void unserialize(Checkpoint *cp, const std::string §ion); 134 135 /*************************************************************** 136 * SimpleThread functions to provide CPU with access to various 137 * state, and to provide address translation methods. 138 **************************************************************/ 139 140 /** Returns the pointer to this SimpleThread's ThreadContext. Used 141 * when a ThreadContext must be passed to objects outside of the 142 * CPU. 143 */ 144 ThreadContext *getTC() { return tc; } 145 146#if FULL_SYSTEM 147 int getInstAsid() { return regs.instAsid(); } 148 int getDataAsid() { return regs.dataAsid(); } 149 150 Fault translateInstReq(RequestPtr &req) 151 { 152 return itb->translate(req, tc); 153 } 154 155 Fault translateDataReadReq(RequestPtr &req) 156 { 157 return dtb->translate(req, tc, false); 158 } 159 160 Fault translateDataWriteReq(RequestPtr &req) 161 { 162 return dtb->translate(req, tc, true); 163 } 164 165 void dumpFuncProfile(); 166 167 int readIntrFlag() { return regs.intrflag; } 168 void setIntrFlag(int val) { regs.intrflag = val; } 169 Fault hwrei(); 170 171 bool simPalCheck(int palFunc); 172#else 173 Fault translateInstReq(RequestPtr &req) 174 { 175 return process->pTable->translate(req); 176 } 177 178 Fault translateDataReadReq(RequestPtr &req) 179 { 180 return process->pTable->translate(req); 181 } 182 183 Fault translateDataWriteReq(RequestPtr &req) 184 { 185 return process->pTable->translate(req); 186 } 187#endif 188 189 /******************************************* 190 * ThreadContext interface functions. 191 ******************************************/ 192 193 BaseCPU *getCpuPtr() { return cpu; } 194 195 int getThreadNum() { return tid; } 196 197#if FULL_SYSTEM 198 System *getSystemPtr() { return system; } 199 200 AlphaITB *getITBPtr() { return itb; } 201 202 AlphaDTB *getDTBPtr() { return dtb; } 203 204 FunctionalPort *getPhysPort() { return physPort; } 205 206 /** Return a virtual port. If no thread context is specified then a static 207 * port is returned. Otherwise a port is created and returned. It must be 208 * deleted by deleteVirtPort(). */ 209 VirtualPort *getVirtPort(ThreadContext *tc); 210 211 void delVirtPort(VirtualPort *vp); 212#endif 213 214 Status status() const { return _status; } 215 216 void setStatus(Status newStatus) { _status = newStatus; } 217 218 /// Set the status to Active. Optional delay indicates number of 219 /// cycles to wait before beginning execution. 220 void activate(int delay = 1); 221 222 /// Set the status to Suspended. 223 void suspend(); 224 225 /// Set the status to Unallocated. 226 void deallocate(); 227 228 /// Set the status to Halted. 229 void halt(); 230 231/* 232 template <class T> 233 Fault read(RequestPtr &req, T &data) 234 { 235#if FULL_SYSTEM && THE_ISA == ALPHA_ISA 236 if (req->flags & LOCKED) { 237 req->xc->setMiscReg(TheISA::Lock_Addr_DepTag, req->paddr); 238 req->xc->setMiscReg(TheISA::Lock_Flag_DepTag, true); 239 } 240#endif 241 242 Fault error; 243 error = mem->prot_read(req->paddr, data, req->size); 244 data = LittleEndianGuest::gtoh(data); 245 return error; 246 } 247 248 template <class T> 249 Fault write(RequestPtr &req, T &data) 250 { 251#if FULL_SYSTEM && THE_ISA == ALPHA_ISA 252 ExecContext *xc; 253 254 // If this is a store conditional, act appropriately 255 if (req->flags & LOCKED) { 256 xc = req->xc; 257 258 if (req->flags & UNCACHEABLE) { 259 // Don't update result register (see stq_c in isa_desc) 260 req->result = 2; 261 xc->setStCondFailures(0);//Needed? [RGD] 262 } else { 263 bool lock_flag = xc->readMiscReg(TheISA::Lock_Flag_DepTag); 264 Addr lock_addr = xc->readMiscReg(TheISA::Lock_Addr_DepTag); 265 req->result = lock_flag; 266 if (!lock_flag || 267 ((lock_addr & ~0xf) != (req->paddr & ~0xf))) { 268 xc->setMiscReg(TheISA::Lock_Flag_DepTag, false); 269 xc->setStCondFailures(xc->readStCondFailures() + 1); 270 if (((xc->readStCondFailures()) % 100000) == 0) { 271 std::cerr << "Warning: " 272 << xc->readStCondFailures() 273 << " consecutive store conditional failures " 274 << "on cpu " << req->xc->readCpuId() 275 << std::endl; 276 } 277 return NoFault; 278 } 279 else xc->setStCondFailures(0); 280 } 281 } 282 283 // Need to clear any locked flags on other proccessors for 284 // this address. Only do this for succsful Store Conditionals 285 // and all other stores (WH64?). Unsuccessful Store 286 // Conditionals would have returned above, and wouldn't fall 287 // through. 288 for (int i = 0; i < system->execContexts.size(); i++){ 289 xc = system->execContexts[i]; 290 if ((xc->readMiscReg(TheISA::Lock_Addr_DepTag) & ~0xf) == 291 (req->paddr & ~0xf)) { 292 xc->setMiscReg(TheISA::Lock_Flag_DepTag, false); 293 } 294 } 295 296#endif 297 return mem->prot_write(req->paddr, (T)htog(data), req->size); 298 } 299*/ 300 virtual bool misspeculating(); 301 302 Fault instRead(RequestPtr &req) 303 { 304 panic("instRead not implemented"); 305 // return funcPhysMem->read(req, inst); 306 return NoFault; 307 } 308 309 void copyArchRegs(ThreadContext *tc); 310 311 void clearArchRegs() { regs.clear(); } 312 313 // 314 // New accessors for new decoder. 315 // 316 uint64_t readIntReg(int reg_idx) 317 { 318 return regs.readIntReg(reg_idx); 319 } 320 321 FloatReg readFloatReg(int reg_idx, int width) 322 { 323 return regs.readFloatReg(reg_idx, width); 324 } 325 326 FloatReg readFloatReg(int reg_idx) 327 { 328 return regs.readFloatReg(reg_idx); 329 } 330 331 FloatRegBits readFloatRegBits(int reg_idx, int width) 332 { 333 return regs.readFloatRegBits(reg_idx, width); 334 } 335 336 FloatRegBits readFloatRegBits(int reg_idx) 337 { 338 return regs.readFloatRegBits(reg_idx); 339 } 340 341 void setIntReg(int reg_idx, uint64_t val) 342 { 343 regs.setIntReg(reg_idx, val); 344 } 345 346 void setFloatReg(int reg_idx, FloatReg val, int width) 347 { 348 regs.setFloatReg(reg_idx, val, width); 349 } 350 351 void setFloatReg(int reg_idx, FloatReg val) 352 { 353 regs.setFloatReg(reg_idx, val); 354 } 355 356 void setFloatRegBits(int reg_idx, FloatRegBits val, int width) 357 { 358 regs.setFloatRegBits(reg_idx, val, width); 359 } 360 361 void setFloatRegBits(int reg_idx, FloatRegBits val) 362 { 363 regs.setFloatRegBits(reg_idx, val); 364 } 365 366 uint64_t readPC() 367 { 368 return regs.readPC(); 369 } 370 371 void setPC(uint64_t val) 372 { 373 regs.setPC(val); 374 } 375 376 uint64_t readNextPC() 377 { 378 return regs.readNextPC(); 379 } 380 381 void setNextPC(uint64_t val) 382 { 383 regs.setNextPC(val); 384 } 385 386 uint64_t readNextNPC() 387 { 388 return regs.readNextNPC(); 389 } 390 391 void setNextNPC(uint64_t val) 392 { 393 regs.setNextNPC(val); 394 } 395 396 MiscReg readMiscReg(int misc_reg) 397 { 398 return regs.readMiscReg(misc_reg); 399 } 400 401 MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault) 402 { 403 return regs.readMiscRegWithEffect(misc_reg, fault, tc); 404 } 405 406 Fault setMiscReg(int misc_reg, const MiscReg &val) 407 { 408 return regs.setMiscReg(misc_reg, val); 409 } 410 411 Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val) 412 { 413 return regs.setMiscRegWithEffect(misc_reg, val, tc); 414 } 415 416 unsigned readStCondFailures() { return storeCondFailures; } 417 418 void setStCondFailures(unsigned sc_failures) 419 { storeCondFailures = sc_failures; } 420 421#if FULL_SYSTEM 422 bool inPalMode() { return AlphaISA::PcPAL(regs.readPC()); } 423#endif 424 425#if !FULL_SYSTEM 426 TheISA::IntReg getSyscallArg(int i) 427 { 428 return regs.readIntReg(TheISA::ArgumentReg0 + i); 429 } 430 431 // used to shift args for indirect syscall 432 void setSyscallArg(int i, TheISA::IntReg val) 433 { 434 regs.setIntReg(TheISA::ArgumentReg0 + i, val); 435 } 436 437 void setSyscallReturn(SyscallReturn return_value) 438 { 439 TheISA::setSyscallReturn(return_value, ®s); 440 } 441 442 void syscall(int64_t callnum) 443 { 444 process->syscall(callnum, tc); 445 } 446#endif 447 448 void changeRegFileContext(RegFile::ContextParam param, 449 RegFile::ContextVal val) 450 { 451 regs.changeContext(param, val); 452 } 453}; 454 455 456// for non-speculative execution context, spec_mode is always false 457inline bool 458SimpleThread::misspeculating() 459{ 460 return false; 461} 462 463#endif // __CPU_CPU_EXEC_CONTEXT_HH__ 464