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