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