base.hh revision 2107
1/* 2 * Copyright (c) 2002-2005 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_SIMPLE_CPU_SIMPLE_CPU_HH__ 30#define __CPU_SIMPLE_CPU_SIMPLE_CPU_HH__ 31 32#include "base/statistics.hh" 33#include "config/full_system.hh" 34#include "cpu/base.hh" 35#include "cpu/exec_context.hh" 36#include "cpu/pc_event.hh" 37#include "cpu/sampler/sampler.hh" 38#include "cpu/static_inst.hh" 39#include "sim/eventq.hh" 40 41// forward declarations 42#if FULL_SYSTEM 43class Processor; 44class AlphaITB; 45class AlphaDTB; 46class PhysicalMemory; 47 48class RemoteGDB; 49class GDBListener; 50 51#else 52 53class Process; 54 55#endif // FULL_SYSTEM 56 57class MemInterface; 58class Checkpoint; 59 60namespace Trace { 61 class InstRecord; 62} 63 64class SimpleCPU : public BaseCPU 65{ 66 protected: 67 typedef TheISA::MachInst MachInst; 68 public: 69 // main simulation loop (one cycle) 70 void tick(); 71 72 private: 73 struct TickEvent : public Event 74 { 75 SimpleCPU *cpu; 76 int width; 77 78 TickEvent(SimpleCPU *c, int w); 79 void process(); 80 const char *description(); 81 }; 82 83 TickEvent tickEvent; 84 85 /// Schedule tick event, regardless of its current state. 86 void scheduleTickEvent(int numCycles) 87 { 88 if (tickEvent.squashed()) 89 tickEvent.reschedule(curTick + cycles(numCycles)); 90 else if (!tickEvent.scheduled()) 91 tickEvent.schedule(curTick + cycles(numCycles)); 92 } 93 94 /// Unschedule tick event, regardless of its current state. 95 void unscheduleTickEvent() 96 { 97 if (tickEvent.scheduled()) 98 tickEvent.squash(); 99 } 100 101 private: 102 Trace::InstRecord *traceData; 103 104 public: 105 // 106 enum Status { 107 Running, 108 Idle, 109 IcacheMissStall, 110 IcacheMissComplete, 111 DcacheMissStall, 112 DcacheMissSwitch, 113 SwitchedOut 114 }; 115 116 private: 117 Status _status; 118 119 public: 120 void post_interrupt(int int_num, int index); 121 122 void zero_fill_64(Addr addr) { 123 static int warned = 0; 124 if (!warned) { 125 warn ("WH64 is not implemented"); 126 warned = 1; 127 } 128 }; 129 130 public: 131 struct Params : public BaseCPU::Params 132 { 133 MemInterface *icache_interface; 134 MemInterface *dcache_interface; 135 int width; 136#if FULL_SYSTEM 137 AlphaITB *itb; 138 AlphaDTB *dtb; 139 FunctionalMemory *mem; 140#else 141 Process *process; 142#endif 143 }; 144 SimpleCPU(Params *params); 145 virtual ~SimpleCPU(); 146 147 public: 148 // execution context 149 ExecContext *xc; 150 151 void switchOut(Sampler *s); 152 void takeOverFrom(BaseCPU *oldCPU); 153 154#if FULL_SYSTEM 155 Addr dbg_vtophys(Addr addr); 156 157 bool interval_stats; 158#endif 159 160 // L1 instruction cache 161 MemInterface *icacheInterface; 162 163 // L1 data cache 164 MemInterface *dcacheInterface; 165 166 // current instruction 167 MachInst inst; 168 169 // Refcounted pointer to the one memory request. 170 MemReqPtr memReq; 171 172 // Pointer to the sampler that is telling us to switchover. 173 // Used to signal the completion of the pipe drain and schedule 174 // the next switchover 175 Sampler *sampler; 176 177 StaticInstPtr curStaticInst; 178 179 class CacheCompletionEvent : public Event 180 { 181 private: 182 SimpleCPU *cpu; 183 184 public: 185 CacheCompletionEvent(SimpleCPU *_cpu); 186 187 virtual void process(); 188 virtual const char *description(); 189 }; 190 191 CacheCompletionEvent cacheCompletionEvent; 192 193 Status status() const { return _status; } 194 195 virtual void activateContext(int thread_num, int delay); 196 virtual void suspendContext(int thread_num); 197 virtual void deallocateContext(int thread_num); 198 virtual void haltContext(int thread_num); 199 200 // statistics 201 virtual void regStats(); 202 virtual void resetStats(); 203 204 // number of simulated instructions 205 Counter numInst; 206 Counter startNumInst; 207 Stats::Scalar<> numInsts; 208 209 virtual Counter totalInstructions() const 210 { 211 return numInst - startNumInst; 212 } 213 214 // number of simulated memory references 215 Stats::Scalar<> numMemRefs; 216 217 // number of simulated loads 218 Counter numLoad; 219 Counter startNumLoad; 220 221 // number of idle cycles 222 Stats::Average<> notIdleFraction; 223 Stats::Formula idleFraction; 224 225 // number of cycles stalled for I-cache misses 226 Stats::Scalar<> icacheStallCycles; 227 Counter lastIcacheStall; 228 229 // number of cycles stalled for D-cache misses 230 Stats::Scalar<> dcacheStallCycles; 231 Counter lastDcacheStall; 232 233 void processCacheCompletion(); 234 235 virtual void serialize(std::ostream &os); 236 virtual void unserialize(Checkpoint *cp, const std::string §ion); 237 238 template <class T> 239 Fault * read(Addr addr, T &data, unsigned flags); 240 241 template <class T> 242 Fault * write(T data, Addr addr, unsigned flags, uint64_t *res); 243 244 // These functions are only used in CPU models that split 245 // effective address computation from the actual memory access. 246 void setEA(Addr EA) { panic("SimpleCPU::setEA() not implemented\n"); } 247 Addr getEA() { panic("SimpleCPU::getEA() not implemented\n"); } 248 249 void prefetch(Addr addr, unsigned flags) 250 { 251 // need to do this... 252 } 253 254 void writeHint(Addr addr, int size, unsigned flags) 255 { 256 // need to do this... 257 } 258 259 Fault * copySrcTranslate(Addr src); 260 261 Fault * copy(Addr dest); 262 263 // The register accessor methods provide the index of the 264 // instruction's operand (e.g., 0 or 1), not the architectural 265 // register index, to simplify the implementation of register 266 // renaming. We find the architectural register index by indexing 267 // into the instruction's own operand index table. Note that a 268 // raw pointer to the StaticInst is provided instead of a 269 // ref-counted StaticInstPtr to redice overhead. This is fine as 270 // long as these methods don't copy the pointer into any long-term 271 // storage (which is pretty hard to imagine they would have reason 272 // to do). 273 274 uint64_t readIntReg(const StaticInst *si, int idx) 275 { 276 return xc->readIntReg(si->srcRegIdx(idx)); 277 } 278 279 float readFloatRegSingle(const StaticInst *si, int idx) 280 { 281 int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; 282 return xc->readFloatRegSingle(reg_idx); 283 } 284 285 double readFloatRegDouble(const StaticInst *si, int idx) 286 { 287 int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; 288 return xc->readFloatRegDouble(reg_idx); 289 } 290 291 uint64_t readFloatRegInt(const StaticInst *si, int idx) 292 { 293 int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; 294 return xc->readFloatRegInt(reg_idx); 295 } 296 297 void setIntReg(const StaticInst *si, int idx, uint64_t val) 298 { 299 xc->setIntReg(si->destRegIdx(idx), val); 300 } 301 302 void setFloatRegSingle(const StaticInst *si, int idx, float val) 303 { 304 int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; 305 xc->setFloatRegSingle(reg_idx, val); 306 } 307 308 void setFloatRegDouble(const StaticInst *si, int idx, double val) 309 { 310 int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; 311 xc->setFloatRegDouble(reg_idx, val); 312 } 313 314 void setFloatRegInt(const StaticInst *si, int idx, uint64_t val) 315 { 316 int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; 317 xc->setFloatRegInt(reg_idx, val); 318 } 319 320 uint64_t readPC() { return xc->readPC(); } 321 void setNextPC(uint64_t val) { xc->setNextPC(val); } 322 323 uint64_t readUniq() { return xc->readUniq(); } 324 void setUniq(uint64_t val) { xc->setUniq(val); } 325 326 uint64_t readFpcr() { return xc->readFpcr(); } 327 void setFpcr(uint64_t val) { xc->setFpcr(val); } 328 329#if FULL_SYSTEM 330 uint64_t readIpr(int idx, Fault * &fault) { return xc->readIpr(idx, fault); } 331 Fault * setIpr(int idx, uint64_t val) { return xc->setIpr(idx, val); } 332 Fault * hwrei() { return xc->hwrei(); } 333 int readIntrFlag() { return xc->readIntrFlag(); } 334 void setIntrFlag(int val) { xc->setIntrFlag(val); } 335 bool inPalMode() { return xc->inPalMode(); } 336 void ev5_trap(Fault * fault) { xc->ev5_trap(fault); } 337 bool simPalCheck(int palFunc) { return xc->simPalCheck(palFunc); } 338#else 339 void syscall() { xc->syscall(); } 340#endif 341 342 bool misspeculating() { return xc->misspeculating(); } 343 ExecContext *xcBase() { return xc; } 344}; 345 346#endif // __CPU_SIMPLE_CPU_SIMPLE_CPU_HH__ 347