cpu.hh revision 2332
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 "base/statistics.hh" 37#include "config/full_system.hh" 38#include "cpu/base.hh" 39#include "cpu/base_dyn_inst.hh" 40#include "cpu/cpu_exec_context.hh" 41#include "cpu/pc_event.hh" 42#include "cpu/static_inst.hh" 43#include "sim/eventq.hh" 44 45// forward declarations 46#if FULL_SYSTEM 47class Processor; 48class AlphaITB; 49class AlphaDTB; 50class PhysicalMemory; 51 52class RemoteGDB; 53class GDBListener; 54 55#else 56 57class Process; 58 59#endif // FULL_SYSTEM 60template <class> 61class BaseDynInst; 62class ExecContext; 63class MemInterface; 64class Checkpoint; 65class Sampler; 66 67class CheckerCPU : public BaseCPU 68{ 69 protected: 70 typedef TheISA::MachInst MachInst; 71 typedef TheISA::MiscReg MiscReg; 72 public: 73 // main simulation loop (one cycle) 74 virtual void init(); 75 76 struct Params : public BaseCPU::Params 77 { 78#if FULL_SYSTEM 79 AlphaITB *itb; 80 AlphaDTB *dtb; 81 FunctionalMemory *mem; 82#else 83 Process *process; 84#endif 85 bool exitOnError; 86 }; 87 88 public: 89 CheckerCPU(Params *p); 90 virtual ~CheckerCPU(); 91 92 void setMemory(FunctionalMemory *mem); 93 94 FunctionalMemory *memPtr; 95 96#if FULL_SYSTEM 97 void setSystem(System *system); 98 99 System *systemPtr; 100#endif 101 public: 102 // execution context 103 CPUExecContext *cpuXC; 104 105 ExecContext *xcProxy; 106 107 AlphaITB *itb; 108 AlphaDTB *dtb; 109 110#if FULL_SYSTEM 111 Addr dbg_vtophys(Addr addr); 112#endif 113 114 union Result { 115 uint64_t integer; 116 float fp; 117 double dbl; 118 }; 119 120 Result result; 121 122 // current instruction 123 MachInst machInst; 124 125 // Refcounted pointer to the one memory request. 126 MemReqPtr memReq; 127 128 StaticInstPtr curStaticInst; 129 130 // number of simulated instructions 131 Counter numInst; 132 Counter startNumInst; 133 134 std::queue<int> miscRegIdxs; 135 136 virtual Counter totalInstructions() const 137 { 138 return numInst - startNumInst; 139 } 140 141 // number of simulated loads 142 Counter numLoad; 143 Counter startNumLoad; 144 145 virtual void serialize(std::ostream &os); 146 virtual void unserialize(Checkpoint *cp, const std::string §ion); 147 148 template <class T> 149 Fault read(Addr addr, T &data, unsigned flags); 150 151 template <class T> 152 Fault write(T data, Addr addr, unsigned flags, uint64_t *res); 153 154 // These functions are only used in CPU models that split 155 // effective address computation from the actual memory access. 156 void setEA(Addr EA) { panic("SimpleCPU::setEA() not implemented\n"); } 157 Addr getEA() { panic("SimpleCPU::getEA() not implemented\n"); } 158 159 void prefetch(Addr addr, unsigned flags) 160 { 161 // need to do this... 162 } 163 164 void writeHint(Addr addr, int size, unsigned flags) 165 { 166 // need to do this... 167 } 168 169 Fault copySrcTranslate(Addr src); 170 171 Fault copy(Addr dest); 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 readIntReg(const StaticInst *si, int idx) 185 { 186 return cpuXC->readIntReg(si->srcRegIdx(idx)); 187 } 188 189 float readFloatRegSingle(const StaticInst *si, int idx) 190 { 191 int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; 192 return cpuXC->readFloatRegSingle(reg_idx); 193 } 194 195 double readFloatRegDouble(const StaticInst *si, int idx) 196 { 197 int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; 198 return cpuXC->readFloatRegDouble(reg_idx); 199 } 200 201 uint64_t readFloatRegInt(const StaticInst *si, int idx) 202 { 203 int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; 204 return cpuXC->readFloatRegInt(reg_idx); 205 } 206 207 void setIntReg(const StaticInst *si, int idx, uint64_t val) 208 { 209 cpuXC->setIntReg(si->destRegIdx(idx), val); 210 result.integer = val; 211 } 212 213 void setFloatRegSingle(const StaticInst *si, int idx, float val) 214 { 215 int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; 216 cpuXC->setFloatRegSingle(reg_idx, val); 217 result.fp = val; 218 } 219 220 void setFloatRegDouble(const StaticInst *si, int idx, double val) 221 { 222 int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; 223 cpuXC->setFloatRegDouble(reg_idx, val); 224 result.dbl = val; 225 } 226 227 void setFloatRegInt(const StaticInst *si, int idx, uint64_t val) 228 { 229 int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; 230 cpuXC->setFloatRegInt(reg_idx, val); 231 result.integer = val; 232 } 233 234 uint64_t readPC() { return cpuXC->readPC(); } 235 void setNextPC(uint64_t val) { 236 cpuXC->setNextPC(val); 237 } 238 239 MiscReg readMiscReg(int misc_reg) 240 { 241 return cpuXC->readMiscReg(misc_reg); 242 } 243 244 MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault) 245 { 246 return cpuXC->readMiscRegWithEffect(misc_reg, fault); 247 } 248 249 Fault setMiscReg(int misc_reg, const MiscReg &val) 250 { 251 result.integer = val; 252 miscRegIdxs.push(misc_reg); 253 return cpuXC->setMiscReg(misc_reg, val); 254 } 255 256 Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val) 257 { 258 miscRegIdxs.push(misc_reg); 259 return cpuXC->setMiscRegWithEffect(misc_reg, val); 260 } 261 262 void recordPCChange(uint64_t val) { changedPC = true; } 263 void recordNextPCChange(uint64_t val) { changedNextPC = true; } 264 265 bool translateInstReq(MemReqPtr &req); 266 void translateDataWriteReq(MemReqPtr &req); 267 void translateDataReadReq(MemReqPtr &req); 268 269#if FULL_SYSTEM 270 Fault hwrei() { return cpuXC->hwrei(); } 271 int readIntrFlag() { return cpuXC->readIntrFlag(); } 272 void setIntrFlag(int val) { cpuXC->setIntrFlag(val); } 273 bool inPalMode() { return cpuXC->inPalMode(); } 274 void ev5_trap(Fault fault) { fault->invoke(xcProxy); } 275 bool simPalCheck(int palFunc) { return cpuXC->simPalCheck(palFunc); } 276#else 277 // Assume that the normal CPU's call to syscall was successful. 278 // The checker's state would have already been updated by the syscall. 279 void syscall() { } 280#endif 281 282 void handleError() 283 { 284 if (exitOnError) 285 panic("Checker found error!"); 286 } 287 bool checkFlags(MemReqPtr &req); 288 289 ExecContext *xcBase() { return xcProxy; } 290 CPUExecContext *cpuXCBase() { return cpuXC; } 291 292 Result unverifiedResult; 293 MemReqPtr unverifiedReq; 294 295 bool changedPC; 296 bool willChangePC; 297 uint64_t newPC; 298 bool changedNextPC; 299 bool exitOnError; 300 301 InstSeqNum youngestSN; 302}; 303 304template <class DynInstPtr> 305class Checker : public CheckerCPU 306{ 307 public: 308 Checker(Params *p) 309 : CheckerCPU(p) 310 { } 311 312 void switchOut(Sampler *s); 313 void takeOverFrom(BaseCPU *oldCPU); 314 315 void tick(DynInstPtr &inst); 316 317 void validateInst(DynInstPtr &inst); 318 void validateExecution(DynInstPtr &inst); 319 void validateState(); 320 321 std::list<DynInstPtr> instList; 322 typedef typename std::list<DynInstPtr>::iterator InstListIt; 323 void dumpInsts(); 324}; 325 326#endif // __CPU_CHECKER_CPU_HH__ 327