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