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