base.hh revision 2390
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 { cpu->processCacheCompletion(pkt); return true; } 84 85 virtual Tick recvAtomic(Packet &pkt) 86 { panic("CPU doesn't expect callback!"); return curTick; } 87 88 virtual void recvFunctional(Packet &pkt) 89 { panic("CPU doesn't expect callback!"); } 90 91 virtual void recvStatusChange(Status status) 92 { cpu->recvStatusChange(status); } 93 94 virtual Packet *recvRetry() { return cpu->processRetry(); } 95 }; 96 97 CpuPort icachePort; 98 CpuPort dcachePort; 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 IcacheRetry, 142 IcacheWaitResponse, 143 IcacheAccessComplete, 144 DcacheRetry, 145 DcacheWaitResponse, 146 DcacheWaitSwitch, 147 SwitchedOut 148 }; 149 150 private: 151 Status _status; 152 153 public: 154 void post_interrupt(int int_num, int index); 155 156 void zero_fill_64(Addr addr) { 157 static int warned = 0; 158 if (!warned) { 159 warn ("WH64 is not implemented"); 160 warned = 1; 161 } 162 }; 163 164 public: 165 struct Params : public BaseCPU::Params 166 { 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 // current instruction 193 MachInst inst; 194 195 CpuRequest *req; 196 Packet *pkt; 197 198 // Pointer to the sampler that is telling us to switchover. 199 // Used to signal the completion of the pipe drain and schedule 200 // the next switchover 201 Sampler *sampler; 202 203 StaticInstPtr<TheISA> curStaticInst; 204 205 Status status() const { return _status; } 206 207 virtual void activateContext(int thread_num, int delay); 208 virtual void suspendContext(int thread_num); 209 virtual void deallocateContext(int thread_num); 210 virtual void haltContext(int thread_num); 211 212 // statistics 213 virtual void regStats(); 214 virtual void resetStats(); 215 216 // number of simulated instructions 217 Counter numInst; 218 Counter startNumInst; 219 Stats::Scalar<> numInsts; 220 221 virtual Counter totalInstructions() const 222 { 223 return numInst - startNumInst; 224 } 225 226 // number of simulated memory references 227 Stats::Scalar<> numMemRefs; 228 229 // number of simulated loads 230 Counter numLoad; 231 Counter startNumLoad; 232 233 // number of idle cycles 234 Stats::Average<> notIdleFraction; 235 Stats::Formula idleFraction; 236 237 // number of cycles stalled for I-cache responses 238 Stats::Scalar<> icacheStallCycles; 239 Counter lastIcacheStall; 240 241 // number of cycles stalled for I-cache retries 242 Stats::Scalar<> icacheRetryCycles; 243 Counter lastIcacheRetry; 244 245 // number of cycles stalled for D-cache responses 246 Stats::Scalar<> dcacheStallCycles; 247 Counter lastDcacheStall; 248 249 // number of cycles stalled for D-cache retries 250 Stats::Scalar<> dcacheRetryCycles; 251 Counter lastDcacheRetry; 252 253 void sendIcacheRequest(); 254 void sendDcacheRequest(); 255 void processResponse(Packet *response); 256 257 virtual void serialize(std::ostream &os); 258 virtual void unserialize(Checkpoint *cp, const std::string §ion); 259 260 template <class T> 261 Fault read(Addr addr, T &data, unsigned flags); 262 263 template <class T> 264 Fault write(T data, Addr addr, unsigned flags, uint64_t *res); 265 266 // These functions are only used in CPU models that split 267 // effective address computation from the actual memory access. 268 void setEA(Addr EA) { panic("SimpleCPU::setEA() not implemented\n"); } 269 Addr getEA() { panic("SimpleCPU::getEA() not implemented\n"); } 270 271 void prefetch(Addr addr, unsigned flags) 272 { 273 // need to do this... 274 } 275 276 void writeHint(Addr addr, int size, unsigned flags) 277 { 278 // need to do this... 279 } 280 281 Fault copySrcTranslate(Addr src); 282 283 Fault copy(Addr dest); 284 285 // The register accessor methods provide the index of the 286 // instruction's operand (e.g., 0 or 1), not the architectural 287 // register index, to simplify the implementation of register 288 // renaming. We find the architectural register index by indexing 289 // into the instruction's own operand index table. Note that a 290 // raw pointer to the StaticInst is provided instead of a 291 // ref-counted StaticInstPtr to redice overhead. This is fine as 292 // long as these methods don't copy the pointer into any long-term 293 // storage (which is pretty hard to imagine they would have reason 294 // to do). 295 296 uint64_t readIntReg(const StaticInst<TheISA> *si, int idx) 297 { 298 return xc->readIntReg(si->srcRegIdx(idx)); 299 } 300 301 float readFloatRegSingle(const StaticInst<TheISA> *si, int idx) 302 { 303 int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; 304 return xc->readFloatRegSingle(reg_idx); 305 } 306 307 double readFloatRegDouble(const StaticInst<TheISA> *si, int idx) 308 { 309 int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; 310 return xc->readFloatRegDouble(reg_idx); 311 } 312 313 uint64_t readFloatRegInt(const StaticInst<TheISA> *si, int idx) 314 { 315 int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; 316 return xc->readFloatRegInt(reg_idx); 317 } 318 319 void setIntReg(const StaticInst<TheISA> *si, int idx, uint64_t val) 320 { 321 xc->setIntReg(si->destRegIdx(idx), val); 322 } 323 324 void setFloatRegSingle(const StaticInst<TheISA> *si, int idx, float val) 325 { 326 int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; 327 xc->setFloatRegSingle(reg_idx, val); 328 } 329 330 void setFloatRegDouble(const StaticInst<TheISA> *si, int idx, double val) 331 { 332 int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; 333 xc->setFloatRegDouble(reg_idx, val); 334 } 335 336 void setFloatRegInt(const StaticInst<TheISA> *si, int idx, uint64_t val) 337 { 338 int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; 339 xc->setFloatRegInt(reg_idx, val); 340 } 341 342 uint64_t readPC() { return xc->readPC(); } 343 void setNextPC(uint64_t val) { xc->setNextPC(val); } 344 345 uint64_t readUniq() { return xc->readUniq(); } 346 void setUniq(uint64_t val) { xc->setUniq(val); } 347 348 uint64_t readFpcr() { return xc->readFpcr(); } 349 void setFpcr(uint64_t val) { xc->setFpcr(val); } 350 351#if FULL_SYSTEM 352 uint64_t readIpr(int idx, Fault &fault) { return xc->readIpr(idx, fault); } 353 Fault setIpr(int idx, uint64_t val) { return xc->setIpr(idx, val); } 354 Fault hwrei() { return xc->hwrei(); } 355 int readIntrFlag() { return xc->readIntrFlag(); } 356 void setIntrFlag(int val) { xc->setIntrFlag(val); } 357 bool inPalMode() { return xc->inPalMode(); } 358 void ev5_trap(Fault fault) { xc->ev5_trap(fault); } 359 bool simPalCheck(int palFunc) { return xc->simPalCheck(palFunc); } 360#else 361 void syscall() { xc->syscall(); } 362#endif 363 364 bool misspeculating() { return xc->misspeculating(); } 365 ExecContext *xcBase() { return xc; } 366}; 367 368#endif // __CPU_SIMPLE_CPU_SIMPLE_CPU_HH__ 369