simple_thread.hh revision 137
1/* 2 * Copyright (c) 2003 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 __EXEC_CONTEXT_HH__ 30#define __EXEC_CONTEXT_HH__ 31 32#include "sim/host.hh" 33#include "targetarch/mem_req.hh" 34 35// forward declaration: see functional_memory.hh 36class FunctionalMemory; 37class PhysicalMemory; 38class BaseCPU; 39 40#ifdef FULL_SYSTEM 41 42#include "targetarch/alpha_memory.hh" 43class MemoryController; 44 45#include "kern/tru64/kernel_stats.hh" 46#include "sim/system.hh" 47 48#else // !FULL_SYSTEM 49 50#include "sim/prog.hh" 51 52#endif // FULL_SYSTEM 53 54// 55// The ExecContext object represents a functional context for 56// instruction execution. It incorporates everything required for 57// architecture-level functional simulation of a single thread. 58// 59 60class ExecContext 61{ 62 public: 63 enum Status { Unallocated, Active, Suspended, Halted }; 64 65 private: 66 Status _status; 67 68 public: 69 Status status() const { return _status; } 70 void setStatus(Status new_status); 71 72#ifdef FULL_SYSTEM 73 public: 74 KernelStats kernelStats; 75#endif 76 77 public: 78 RegFile regs; // correct-path register context 79 80 // pointer to CPU associated with this context 81 BaseCPU *cpu; 82 83 // Index of hardware thread context on the CPU that this represents. 84 int thread_num; 85 86#ifdef FULL_SYSTEM 87 88 FunctionalMemory *mem; 89 AlphaItb *itb; 90 AlphaDtb *dtb; 91 int cpu_id; 92 System *system; 93 94 // the following two fields are redundant, since we can always 95 // look them up through the system pointer, but we'll leave them 96 // here for now for convenience 97 MemoryController *memCtrl; 98 PhysicalMemory *physmem; 99 100#else 101 Process *process; 102 103 FunctionalMemory *mem; // functional storage for process address space 104 105 // Address space ID. Note that this is used for TIMING cache 106 // simulation only; all functional memory accesses should use 107 // one of the FunctionalMemory pointers above. 108 short asid; 109 110#endif 111 112 113 /* 114 * number of executed instructions, for matching with syscall trace 115 * points in EIO files. 116 */ 117 Counter func_exe_insn; 118 119 // 120 // Count failed store conditionals so we can warn of apparent 121 // application deadlock situations. 122 unsigned storeCondFailures; 123 124 // constructor: initialize context from given process structure 125#ifdef FULL_SYSTEM 126 ExecContext(BaseCPU *_cpu, int _thread_num, System *_system, 127 AlphaItb *_itb, AlphaDtb *_dtb, FunctionalMemory *_dem, 128 int _cpu_id); 129#else 130 ExecContext(BaseCPU *_cpu, int _thread_num, Process *_process, int _asid); 131 ExecContext(BaseCPU *_cpu, int _thread_num, FunctionalMemory *_mem, 132 int _asid); 133#endif 134 virtual ~ExecContext() {} 135 136 void regStats(const std::string &name); 137 138#ifdef FULL_SYSTEM 139 bool validInstAddr(Addr addr) { return true; } 140 bool validDataAddr(Addr addr) { return true; } 141 int getInstAsid() { return ITB_ASN_ASN(regs.ipr[TheISA::IPR_ITB_ASN]); } 142 int getDataAsid() { return DTB_ASN_ASN(regs.ipr[TheISA::IPR_DTB_ASN]); } 143 144 Fault translateInstReq(MemReqPtr req) 145 { 146 return itb->translate(req); 147 } 148 149 Fault translateDataReadReq(MemReqPtr req) 150 { 151 return dtb->translate(req, false); 152 } 153 154 Fault translateDataWriteReq(MemReqPtr req) 155 { 156 return dtb->translate(req, true); 157 } 158 159 160#else 161 bool validInstAddr(Addr addr) 162 { return process->validInstAddr(addr); } 163 164 bool validDataAddr(Addr addr) 165 { return process->validDataAddr(addr); } 166 167 int getInstAsid() { return asid; } 168 int getDataAsid() { return asid; } 169 170 Fault dummyTranslation(MemReqPtr req) 171 { 172#if 0 173 assert((req->vaddr >> 48 & 0xffff) == 0); 174#endif 175 176 // put the asid in the upper 16 bits of the paddr 177 req->paddr = req->vaddr & ~((Addr)0xffff << sizeof(Addr) * 8 - 16); 178 req->paddr = req->paddr | (Addr)req->asid << sizeof(Addr) * 8 - 16; 179 return No_Fault; 180 } 181 Fault translateInstReq(MemReqPtr req) 182 { 183 return dummyTranslation(req); 184 } 185 Fault translateDataReadReq(MemReqPtr req) 186 { 187 return dummyTranslation(req); 188 } 189 Fault translateDataWriteReq(MemReqPtr req) 190 { 191 return dummyTranslation(req); 192 } 193 194#endif 195 196 template <class T> 197 Fault read(MemReqPtr req, T& data) 198 { 199#if defined(TARGET_ALPHA) && defined(FULL_SYSTEM) 200 if (req->flags & LOCKED) { 201 MiscRegFile *cregs = &req->xc->regs.miscRegs; 202 cregs->lock_addr = req->paddr; 203 cregs->lock_flag = true; 204 } 205#endif 206 return mem->read(req, data); 207 } 208 209 template <class T> 210 Fault write(MemReqPtr req, T& data) 211 { 212#if defined(TARGET_ALPHA) && defined(FULL_SYSTEM) 213 214 MiscRegFile *cregs; 215 216 // If this is a store conditional, act appropriately 217 if (req->flags & LOCKED) { 218 cregs = &req->xc->regs.miscRegs; 219 220 if (req->flags & UNCACHEABLE) { 221 // Don't update result register (see stq_c in isa_desc) 222 req->result = 2; 223 req->xc->storeCondFailures = 0;//Needed? [RGD] 224 } else { 225 req->result = cregs->lock_flag; 226 if (!cregs->lock_flag || 227 ((cregs->lock_addr & ~0xf) != (req->paddr & ~0xf))) { 228 cregs->lock_flag = false; 229 if (((++req->xc->storeCondFailures) % 100000) == 0) { 230 std::cerr << "Warning: " 231 << req->xc->storeCondFailures 232 << " consecutive store conditional failures " 233 << "on cpu " << req->xc->cpu_id 234 << std::endl; 235 } 236 return No_Fault; 237 } 238 else req->xc->storeCondFailures = 0; 239 } 240 } 241 242 // Need to clear any locked flags on other proccessors for 243 // this address. Only do this for succsful Store Conditionals 244 // and all other stores (WH64?). Unsuccessful Store 245 // Conditionals would have returned above, and wouldn't fall 246 // through. 247 for (int i = 0; i < system->xcvec.size(); i++){ 248 cregs = &system->xcvec[i]->regs.miscRegs; 249 if ((cregs->lock_addr & ~0xf) == (req->paddr & ~0xf)) { 250 cregs->lock_flag = false; 251 } 252 } 253 254#endif 255 return mem->write(req, data); 256 } 257 258 virtual bool misspeculating(); 259 260 261 // 262 // New accessors for new decoder. 263 // 264 uint64_t readIntReg(int reg_idx) 265 { 266 return regs.intRegFile[reg_idx]; 267 } 268 269 float readFloatRegSingle(int reg_idx) 270 { 271 return (float)regs.floatRegFile.d[reg_idx]; 272 } 273 274 double readFloatRegDouble(int reg_idx) 275 { 276 return regs.floatRegFile.d[reg_idx]; 277 } 278 279 uint64_t readFloatRegInt(int reg_idx) 280 { 281 return regs.floatRegFile.q[reg_idx]; 282 } 283 284 void setIntReg(int reg_idx, uint64_t val) 285 { 286 regs.intRegFile[reg_idx] = val; 287 } 288 289 void setFloatRegSingle(int reg_idx, float val) 290 { 291 regs.floatRegFile.d[reg_idx] = (double)val; 292 } 293 294 void setFloatRegDouble(int reg_idx, double val) 295 { 296 regs.floatRegFile.d[reg_idx] = val; 297 } 298 299 void setFloatRegInt(int reg_idx, uint64_t val) 300 { 301 regs.floatRegFile.q[reg_idx] = val; 302 } 303 304 uint64_t readPC() 305 { 306 return regs.pc; 307 } 308 309 void setNextPC(uint64_t val) 310 { 311 regs.npc = val; 312 } 313 314 uint64_t readUniq() 315 { 316 return regs.miscRegs.uniq; 317 } 318 319 void setUniq(uint64_t val) 320 { 321 regs.miscRegs.uniq = val; 322 } 323 324 uint64_t readFpcr() 325 { 326 return regs.miscRegs.fpcr; 327 } 328 329 void setFpcr(uint64_t val) 330 { 331 regs.miscRegs.fpcr = val; 332 } 333 334#ifdef FULL_SYSTEM 335 uint64_t readIpr(int idx, Fault &fault); 336 Fault setIpr(int idx, uint64_t val); 337 Fault hwrei(); 338 void ev5_trap(Fault fault); 339 bool simPalCheck(int palFunc); 340#endif 341 342#ifndef FULL_SYSTEM 343 void syscall() 344 { 345 process->syscall(this); 346 } 347#endif 348}; 349 350 351// for non-speculative execution context, spec_mode is always false 352inline bool 353ExecContext::misspeculating() 354{ 355 return false; 356} 357 358#endif // __EXEC_CONTEXT_HH__ 359