thread_context.hh revision 56
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 machine.def) 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 this 243 // address 244 // Only do this for succsful Store Conditionals and all other 245 // stores (WH64?) 246 // Unsuccesful Store Conditionals would have returned above, 247 // and wouldn't fall through 248 for(int i = 0; i < system->num_cpus; i++){ 249 cregs = &system->xc_array[i]->regs.miscRegs; 250 if((cregs->lock_addr & ~0xf) == (req->paddr & ~0xf)) { 251 cregs->lock_flag = false; 252 } 253 } 254 255#endif 256 return mem->write(req, data); 257 } 258 259 virtual bool misspeculating(); 260 261 262 // 263 // New accessors for new decoder. 264 // 265 uint64_t readIntReg(int reg_idx) 266 { 267 return regs.intRegFile[reg_idx]; 268 } 269 270 float readFloatRegSingle(int reg_idx) 271 { 272 return (float)regs.floatRegFile.d[reg_idx]; 273 } 274 275 double readFloatRegDouble(int reg_idx) 276 { 277 return regs.floatRegFile.d[reg_idx]; 278 } 279 280 uint64_t readFloatRegInt(int reg_idx) 281 { 282 return regs.floatRegFile.q[reg_idx]; 283 } 284 285 void setIntReg(int reg_idx, uint64_t val) 286 { 287 regs.intRegFile[reg_idx] = val; 288 } 289 290 void setFloatRegSingle(int reg_idx, float val) 291 { 292 regs.floatRegFile.d[reg_idx] = (double)val; 293 } 294 295 void setFloatRegDouble(int reg_idx, double val) 296 { 297 regs.floatRegFile.d[reg_idx] = val; 298 } 299 300 void setFloatRegInt(int reg_idx, uint64_t val) 301 { 302 regs.floatRegFile.q[reg_idx] = val; 303 } 304 305 uint64_t readPC() 306 { 307 return regs.pc; 308 } 309 310 void setNextPC(uint64_t val) 311 { 312 regs.npc = val; 313 } 314 315 uint64_t readUniq() 316 { 317 return regs.miscRegs.uniq; 318 } 319 320 void setUniq(uint64_t val) 321 { 322 regs.miscRegs.uniq = val; 323 } 324 325 uint64_t readFpcr() 326 { 327 return regs.miscRegs.fpcr; 328 } 329 330 void setFpcr(uint64_t val) 331 { 332 regs.miscRegs.fpcr = val; 333 } 334 335#ifdef FULL_SYSTEM 336 uint64_t readIpr(int idx, Fault &fault); 337 Fault setIpr(int idx, uint64_t val); 338 Fault hwrei(); 339 void ev5_trap(Fault fault); 340 bool simPalCheck(int palFunc); 341#endif 342 343#ifndef FULL_SYSTEM 344 void syscall() 345 { 346 process->syscall(this); 347 } 348#endif 349}; 350 351 352// for non-speculative execution context, spec_mode is always false 353inline bool 354ExecContext::misspeculating() 355{ 356 return false; 357} 358 359#endif // __EXEC_CONTEXT_HH__ 360