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