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