cpu.hh revision 2350
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 }; 102 103 public: 104 CheckerCPU(Params *p); 105 virtual ~CheckerCPU(); 106 107 void setMemory(FunctionalMemory *mem); 108 109 FunctionalMemory *memPtr; 110 111#if FULL_SYSTEM 112 void setSystem(System *system); 113 114 System *systemPtr; 115#endif 116 public: 117 // execution context 118 CPUExecContext *cpuXC; 119 120 ExecContext *xcProxy; 121 122 AlphaITB *itb; 123 AlphaDTB *dtb; 124 125#if FULL_SYSTEM 126 Addr dbg_vtophys(Addr addr); 127#endif 128 129 union Result { 130 uint64_t integer; 131 float fp; 132 double dbl; 133 }; 134 135 Result result; 136 137 // current instruction 138 MachInst machInst; 139 140 // Refcounted pointer to the one memory request. 141 MemReqPtr memReq; 142 143 StaticInstPtr curStaticInst; 144 145 // number of simulated instructions 146 Counter numInst; 147 Counter startNumInst; 148 149 std::queue<int> miscRegIdxs; 150 151 virtual Counter totalInstructions() const 152 { 153 return numInst - startNumInst; 154 } 155 156 // number of simulated loads 157 Counter numLoad; 158 Counter startNumLoad; 159 160 virtual void serialize(std::ostream &os); 161 virtual void unserialize(Checkpoint *cp, const std::string §ion); 162 163 template <class T> 164 Fault read(Addr addr, T &data, unsigned flags); 165 166 template <class T> 167 Fault write(T data, Addr addr, unsigned flags, uint64_t *res); 168 169 // These functions are only used in CPU models that split 170 // effective address computation from the actual memory access. 171 void setEA(Addr EA) { panic("SimpleCPU::setEA() not implemented\n"); } 172 Addr getEA() { panic("SimpleCPU::getEA() not implemented\n"); } 173 174 void prefetch(Addr addr, unsigned flags) 175 { 176 // need to do this... 177 } 178 179 void writeHint(Addr addr, int size, unsigned flags) 180 { 181 // need to do this... 182 } 183 184 Fault copySrcTranslate(Addr src); 185 186 Fault copy(Addr dest); 187 188 // The register accessor methods provide the index of the 189 // instruction's operand (e.g., 0 or 1), not the architectural 190 // register index, to simplify the implementation of register 191 // renaming. We find the architectural register index by indexing 192 // into the instruction's own operand index table. Note that a 193 // raw pointer to the StaticInst is provided instead of a 194 // ref-counted StaticInstPtr to redice overhead. This is fine as 195 // long as these methods don't copy the pointer into any long-term 196 // storage (which is pretty hard to imagine they would have reason 197 // to do). 198 199 uint64_t readIntReg(const StaticInst *si, int idx) 200 { 201 return cpuXC->readIntReg(si->srcRegIdx(idx)); 202 } 203 204 float readFloatRegSingle(const StaticInst *si, int idx) 205 { 206 int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; 207 return cpuXC->readFloatRegSingle(reg_idx); 208 } 209 210 double readFloatRegDouble(const StaticInst *si, int idx) 211 { 212 int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; 213 return cpuXC->readFloatRegDouble(reg_idx); 214 } 215 216 uint64_t readFloatRegInt(const StaticInst *si, int idx) 217 { 218 int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; 219 return cpuXC->readFloatRegInt(reg_idx); 220 } 221 222 void setIntReg(const StaticInst *si, int idx, uint64_t val) 223 { 224 cpuXC->setIntReg(si->destRegIdx(idx), val); 225 result.integer = val; 226 } 227 228 void setFloatRegSingle(const StaticInst *si, int idx, float val) 229 { 230 int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; 231 cpuXC->setFloatRegSingle(reg_idx, val); 232 result.fp = val; 233 } 234 235 void setFloatRegDouble(const StaticInst *si, int idx, double val) 236 { 237 int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; 238 cpuXC->setFloatRegDouble(reg_idx, val); 239 result.dbl = val; 240 } 241 242 void setFloatRegInt(const StaticInst *si, int idx, uint64_t val) 243 { 244 int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; 245 cpuXC->setFloatRegInt(reg_idx, val); 246 result.integer = val; 247 } 248 249 uint64_t readPC() { return cpuXC->readPC(); } 250 void setNextPC(uint64_t val) { 251 cpuXC->setNextPC(val); 252 } 253 254 MiscReg readMiscReg(int misc_reg) 255 { 256 return cpuXC->readMiscReg(misc_reg); 257 } 258 259 MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault) 260 { 261 return cpuXC->readMiscRegWithEffect(misc_reg, fault); 262 } 263 264 Fault setMiscReg(int misc_reg, const MiscReg &val) 265 { 266 result.integer = val; 267 miscRegIdxs.push(misc_reg); 268 return cpuXC->setMiscReg(misc_reg, val); 269 } 270 271 Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val) 272 { 273 miscRegIdxs.push(misc_reg); 274 return cpuXC->setMiscRegWithEffect(misc_reg, val); 275 } 276 277 void recordPCChange(uint64_t val) { changedPC = true; } 278 void recordNextPCChange(uint64_t val) { changedNextPC = true; } 279 280 bool translateInstReq(MemReqPtr &req); 281 void translateDataWriteReq(MemReqPtr &req); 282 void translateDataReadReq(MemReqPtr &req); 283 284#if FULL_SYSTEM 285 Fault hwrei() { return cpuXC->hwrei(); } 286 int readIntrFlag() { return cpuXC->readIntrFlag(); } 287 void setIntrFlag(int val) { cpuXC->setIntrFlag(val); } 288 bool inPalMode() { return cpuXC->inPalMode(); } 289 void ev5_trap(Fault fault) { fault->invoke(xcProxy); } 290 bool simPalCheck(int palFunc) { return cpuXC->simPalCheck(palFunc); } 291#else 292 // Assume that the normal CPU's call to syscall was successful. 293 // The checker's state would have already been updated by the syscall. 294 void syscall() { } 295#endif 296 297 void handleError() 298 { 299 if (exitOnError) 300 panic("Checker found error!"); 301 } 302 bool checkFlags(MemReqPtr &req); 303 304 ExecContext *xcBase() { return xcProxy; } 305 CPUExecContext *cpuXCBase() { return cpuXC; } 306 307 Result unverifiedResult; 308 MemReqPtr unverifiedReq; 309 310 bool changedPC; 311 bool willChangePC; 312 uint64_t newPC; 313 bool changedNextPC; 314 bool exitOnError; 315 316 InstSeqNum youngestSN; 317}; 318 319/** 320 * Templated Checker class. This Checker class is templated on the 321 * DynInstPtr of the instruction type that will be verified. Proper 322 * template instantiations of the Checker must be placed at the bottom 323 * of checker/cpu.cc. 324 */ 325template <class DynInstPtr> 326class Checker : public CheckerCPU 327{ 328 public: 329 Checker(Params *p) 330 : CheckerCPU(p) 331 { } 332 333 void switchOut(Sampler *s); 334 void takeOverFrom(BaseCPU *oldCPU); 335 336 void tick(DynInstPtr &inst); 337 338 void validateInst(DynInstPtr &inst); 339 void validateExecution(DynInstPtr &inst); 340 void validateState(); 341 342 std::list<DynInstPtr> instList; 343 typedef typename std::list<DynInstPtr>::iterator InstListIt; 344 void dumpInsts(); 345}; 346 347#endif // __CPU_CHECKER_CPU_HH__ 348