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