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