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