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