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