cpu.hh revision 2669
1/* 2 * Copyright (c) 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_CHECKER_CPU_HH__ 30#define __CPU_CHECKER_CPU_HH__ 31 32#include <list> 33#include <queue> 34#include <map> 35 36#include "arch/types.hh" 37#include "base/statistics.hh" 38#include "config/full_system.hh" 39#include "cpu/base.hh" 40#include "cpu/base_dyn_inst.hh" 41#include "cpu/cpu_exec_context.hh" 42#include "cpu/pc_event.hh" 43#include "cpu/static_inst.hh" 44#include "sim/eventq.hh" 45 46// forward declarations 47#if FULL_SYSTEM 48class Processor; 49class AlphaITB; 50class AlphaDTB; 51class PhysicalMemory; 52 53class RemoteGDB; 54class GDBListener; 55 56#else 57 58class Process; 59 60#endif // FULL_SYSTEM 61template <class> 62class BaseDynInst; 63class ExecContext; 64class MemInterface; 65class Checkpoint; 66class Request; 67class Sampler; 68 69class CheckerCPU : public BaseCPU 70{ 71 protected: 72 typedef TheISA::MachInst MachInst; 73 typedef TheISA::FloatReg FloatReg; 74 typedef TheISA::FloatRegBits FloatRegBits; 75 typedef TheISA::MiscReg MiscReg; 76 public: 77 // main simulation loop (one cycle) 78 virtual void init(); 79 80 struct Params : public BaseCPU::Params 81 { 82#if FULL_SYSTEM 83 AlphaITB *itb; 84 AlphaDTB *dtb; 85 FunctionalMemory *mem; 86#else 87 Process *process; 88#endif 89 bool exitOnError; 90 }; 91 92 public: 93 CheckerCPU(Params *p); 94 virtual ~CheckerCPU(); 95 96 void setMemory(MemObject *mem); 97 98 MemObject *memPtr; 99 100#if FULL_SYSTEM 101 void setSystem(System *system); 102 103 System *systemPtr; 104#endif 105 public: 106 // execution context 107 CPUExecContext *cpuXC; 108 109 ExecContext *xcProxy; 110 111 AlphaITB *itb; 112 AlphaDTB *dtb; 113 114#if FULL_SYSTEM 115 Addr dbg_vtophys(Addr addr); 116#endif 117 118 union Result { 119 uint64_t integer; 120 float fp; 121 double dbl; 122 }; 123 124 Result result; 125 126 // current instruction 127 MachInst machInst; 128 129 // Refcounted pointer to the one memory request. 130 Request *memReq; 131 132 StaticInstPtr curStaticInst; 133 134 // number of simulated instructions 135 Counter numInst; 136 Counter startNumInst; 137 138 std::queue<int> miscRegIdxs; 139 140 virtual Counter totalInstructions() const 141 { 142 return numInst - startNumInst; 143 } 144 145 // number of simulated loads 146 Counter numLoad; 147 Counter startNumLoad; 148 149 virtual void serialize(std::ostream &os); 150 virtual void unserialize(Checkpoint *cp, const std::string §ion); 151 152 template <class T> 153 Fault read(Addr addr, T &data, unsigned flags); 154 155 template <class T> 156 Fault write(T data, Addr addr, unsigned flags, uint64_t *res); 157 158 // These functions are only used in CPU models that split 159 // effective address computation from the actual memory access. 160 void setEA(Addr EA) { panic("SimpleCPU::setEA() not implemented\n"); } 161 Addr getEA() { panic("SimpleCPU::getEA() not implemented\n"); } 162 163 void prefetch(Addr addr, unsigned flags) 164 { 165 // need to do this... 166 } 167 168 void writeHint(Addr addr, int size, unsigned flags) 169 { 170 // need to do this... 171 } 172 173 Fault copySrcTranslate(Addr src); 174 175 Fault copy(Addr dest); 176 177 // The register accessor methods provide the index of the 178 // instruction's operand (e.g., 0 or 1), not the architectural 179 // register index, to simplify the implementation of register 180 // renaming. We find the architectural register index by indexing 181 // into the instruction's own operand index table. Note that a 182 // raw pointer to the StaticInst is provided instead of a 183 // ref-counted StaticInstPtr to redice overhead. This is fine as 184 // long as these methods don't copy the pointer into any long-term 185 // storage (which is pretty hard to imagine they would have reason 186 // to do). 187 188 uint64_t readIntReg(const StaticInst *si, int idx) 189 { 190 return cpuXC->readIntReg(si->srcRegIdx(idx)); 191 } 192 193 FloatReg readFloatReg(const StaticInst *si, int idx, int width) 194 { 195 int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; 196 return cpuXC->readFloatReg(reg_idx, width); 197 } 198 199 FloatReg readFloatReg(const StaticInst *si, int idx) 200 { 201 int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; 202 return cpuXC->readFloatReg(reg_idx); 203 } 204 205 FloatRegBits readFloatRegBits(const StaticInst *si, int idx, int width) 206 { 207 int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; 208 return cpuXC->readFloatRegBits(reg_idx, width); 209 } 210 211 FloatRegBits readFloatRegBits(const StaticInst *si, int idx) 212 { 213 int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; 214 return cpuXC->readFloatRegBits(reg_idx); 215 } 216 217 void setIntReg(const StaticInst *si, int idx, uint64_t val) 218 { 219 cpuXC->setIntReg(si->destRegIdx(idx), val); 220 result.integer = val; 221 } 222 223 void setFloatReg(const StaticInst *si, int idx, FloatReg val, int width) 224 { 225 int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; 226 cpuXC->setFloatReg(reg_idx, val, width); 227 switch(width) { 228 case 32: 229 result.fp = val; 230 break; 231 case 64: 232 result.dbl = val; 233 break; 234 }; 235 } 236 237 void setFloatReg(const StaticInst *si, int idx, FloatReg val) 238 { 239 int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; 240 cpuXC->setFloatReg(reg_idx, val); 241 result.fp = val; 242 } 243 244 void setFloatRegBits(const StaticInst *si, int idx, FloatRegBits val, 245 int width) 246 { 247 int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; 248 cpuXC->setFloatRegBits(reg_idx, val, width); 249 result.integer = val; 250 } 251 252 void setFloatRegBits(const StaticInst *si, int idx, FloatRegBits val) 253 { 254 int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; 255 cpuXC->setFloatRegBits(reg_idx, val); 256 result.integer = val; 257 } 258 259 uint64_t readPC() { return cpuXC->readPC(); } 260 261 uint64_t readNextPC() { return cpuXC->readNextPC(); } 262 263 void setNextPC(uint64_t val) { 264 cpuXC->setNextPC(val); 265 } 266 267 MiscReg readMiscReg(int misc_reg) 268 { 269 return cpuXC->readMiscReg(misc_reg); 270 } 271 272 MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault) 273 { 274 return cpuXC->readMiscRegWithEffect(misc_reg, fault); 275 } 276 277 Fault setMiscReg(int misc_reg, const MiscReg &val) 278 { 279 result.integer = val; 280 miscRegIdxs.push(misc_reg); 281 return cpuXC->setMiscReg(misc_reg, val); 282 } 283 284 Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val) 285 { 286 miscRegIdxs.push(misc_reg); 287 return cpuXC->setMiscRegWithEffect(misc_reg, val); 288 } 289 290 void recordPCChange(uint64_t val) { changedPC = true; } 291 void recordNextPCChange(uint64_t val) { changedNextPC = true; } 292 293 bool translateInstReq(Request *req); 294 void translateDataWriteReq(Request *req); 295 void translateDataReadReq(Request *req); 296 297#if FULL_SYSTEM 298 Fault hwrei() { return cpuXC->hwrei(); } 299 int readIntrFlag() { return cpuXC->readIntrFlag(); } 300 void setIntrFlag(int val) { cpuXC->setIntrFlag(val); } 301 bool inPalMode() { return cpuXC->inPalMode(); } 302 void ev5_trap(Fault fault) { fault->invoke(xcProxy); } 303 bool simPalCheck(int palFunc) { return cpuXC->simPalCheck(palFunc); } 304#else 305 // Assume that the normal CPU's call to syscall was successful. 306 // The checker's state would have already been updated by the syscall. 307 void syscall(uint64_t callnum) { } 308#endif 309 310 void handleError() 311 { 312 if (exitOnError) 313 panic("Checker found error!"); 314 } 315 bool checkFlags(Request *req); 316 317 ExecContext *xcBase() { return xcProxy; } 318 CPUExecContext *cpuXCBase() { return cpuXC; } 319 320 Result unverifiedResult; 321 Request *unverifiedReq; 322 323 bool changedPC; 324 bool willChangePC; 325 uint64_t newPC; 326 bool changedNextPC; 327 bool exitOnError; 328 329 InstSeqNum youngestSN; 330}; 331 332template <class DynInstPtr> 333class Checker : public CheckerCPU 334{ 335 public: 336 Checker(Params *p) 337 : CheckerCPU(p) 338 { } 339 340 void switchOut(Sampler *s); 341 void takeOverFrom(BaseCPU *oldCPU); 342 343 void tick(DynInstPtr &inst); 344 345 void validateInst(DynInstPtr &inst); 346 void validateExecution(DynInstPtr &inst); 347 void validateState(); 348 349 std::list<DynInstPtr> instList; 350 typedef typename std::list<DynInstPtr>::iterator InstListIt; 351 void dumpInsts(); 352}; 353 354#endif // __CPU_CHECKER_CPU_HH__ 355