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