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