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