base.hh revision 2566
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 MemObject; 50 51class RemoteGDB; 52class GDBListener; 53 54#else 55 56class Process; 57 58#endif // FULL_SYSTEM 59 60class ExecContext; 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 protected: 80 typedef TheISA::MachInst MachInst; 81 typedef TheISA::MiscReg MiscReg; 82 typedef TheISA::FloatReg FloatReg; 83 typedef TheISA::FloatRegBits FloatRegBits; 84 class CpuPort : public Port 85 { 86 87 SimpleCPU *cpu; 88 89 public: 90 91 CpuPort(SimpleCPU *_cpu) 92 : cpu(_cpu) 93 { } 94 95 protected: 96 97 virtual bool recvTiming(Packet &pkt); 98 99 virtual Tick recvAtomic(Packet &pkt); 100 101 virtual void recvFunctional(Packet &pkt); 102 103 virtual void recvStatusChange(Status status); 104 105 virtual Packet *recvRetry(); 106 }; 107 108 MemObject *mem; 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 MemObject *mem; 182#if FULL_SYSTEM 183 AlphaITB *itb; 184 AlphaDTB *dtb; 185#else 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 // Static data storage 211 TheISA::IntReg dataReg; 212 213#if SIMPLE_CPU_MEM_TIMING 214 Packet *retry_pkt; 215#elif SIMPLE_CPU_MEM_ATOMIC || SIMPLE_CPU_MEM_IMMEDIATE 216 Request *ifetch_req; 217 Packet *ifetch_pkt; 218 Request *data_read_req; 219 Packet *data_read_pkt; 220 Request *data_write_req; 221 Packet *data_write_pkt; 222#endif 223 224 // Pointer to the sampler that is telling us to switchover. 225 // Used to signal the completion of the pipe drain and schedule 226 // the next switchover 227 Sampler *sampler; 228 229 StaticInstPtr curStaticInst; 230 231 Status status() const { return _status; } 232 233 virtual void activateContext(int thread_num, int delay); 234 virtual void suspendContext(int thread_num); 235 virtual void deallocateContext(int thread_num); 236 virtual void haltContext(int thread_num); 237 238 // statistics 239 virtual void regStats(); 240 virtual void resetStats(); 241 242 // number of simulated instructions 243 Counter numInst; 244 Counter startNumInst; 245 Stats::Scalar<> numInsts; 246 247 virtual Counter totalInstructions() const 248 { 249 return numInst - startNumInst; 250 } 251 252 // number of simulated memory references 253 Stats::Scalar<> numMemRefs; 254 255 // number of simulated loads 256 Counter numLoad; 257 Counter startNumLoad; 258 259 // number of idle cycles 260 Stats::Average<> notIdleFraction; 261 Stats::Formula idleFraction; 262 263 // number of cycles stalled for I-cache responses 264 Stats::Scalar<> icacheStallCycles; 265 Counter lastIcacheStall; 266 267 // number of cycles stalled for I-cache retries 268 Stats::Scalar<> icacheRetryCycles; 269 Counter lastIcacheRetry; 270 271 // number of cycles stalled for D-cache responses 272 Stats::Scalar<> dcacheStallCycles; 273 Counter lastDcacheStall; 274 275 // number of cycles stalled for D-cache retries 276 Stats::Scalar<> dcacheRetryCycles; 277 Counter lastDcacheRetry; 278 279 void sendIcacheRequest(Packet *pkt); 280 void sendDcacheRequest(Packet *pkt); 281 void processResponse(Packet &response); 282 283 Packet * processRetry(); 284 void recvStatusChange(Port::Status status) {} 285 286 virtual void serialize(std::ostream &os); 287 virtual void unserialize(Checkpoint *cp, const std::string §ion); 288 289 template <class T> 290 Fault read(Addr addr, T &data, unsigned flags); 291 292 template <class T> 293 Fault write(T data, Addr addr, unsigned flags, uint64_t *res); 294 295 // These functions are only used in CPU models that split 296 // effective address computation from the actual memory access. 297 void setEA(Addr EA) { panic("SimpleCPU::setEA() not implemented\n"); } 298 Addr getEA() { panic("SimpleCPU::getEA() not implemented\n"); } 299 300 void prefetch(Addr addr, unsigned flags) 301 { 302 // need to do this... 303 } 304 305 void writeHint(Addr addr, int size, unsigned flags) 306 { 307 // need to do this... 308 } 309 310 Fault copySrcTranslate(Addr src); 311 312 Fault copy(Addr dest); 313 314 // The register accessor methods provide the index of the 315 // instruction's operand (e.g., 0 or 1), not the architectural 316 // register index, to simplify the implementation of register 317 // renaming. We find the architectural register index by indexing 318 // into the instruction's own operand index table. Note that a 319 // raw pointer to the StaticInst is provided instead of a 320 // ref-counted StaticInstPtr to redice overhead. This is fine as 321 // long as these methods don't copy the pointer into any long-term 322 // storage (which is pretty hard to imagine they would have reason 323 // to do). 324 325 uint64_t readIntReg(const StaticInst *si, int idx) 326 { 327 return cpuXC->readIntReg(si->srcRegIdx(idx)); 328 } 329 330 FloatReg readFloatReg(const StaticInst *si, int idx, int width) 331 { 332 int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; 333 return cpuXC->readFloatReg(reg_idx, width); 334 } 335 336 FloatReg readFloatReg(const StaticInst *si, int idx) 337 { 338 int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; 339 return cpuXC->readFloatReg(reg_idx); 340 } 341 342 FloatRegBits readFloatRegBits(const StaticInst *si, int idx, int width) 343 { 344 int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; 345 return cpuXC->readFloatRegBits(reg_idx, width); 346 } 347 348 FloatRegBits readFloatRegBits(const StaticInst *si, int idx) 349 { 350 int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; 351 return cpuXC->readFloatRegBits(reg_idx); 352 } 353 354 void setIntReg(const StaticInst *si, int idx, uint64_t val) 355 { 356 cpuXC->setIntReg(si->destRegIdx(idx), val); 357 } 358 359 void setFloatReg(const StaticInst *si, int idx, FloatReg val, int width) 360 { 361 int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; 362 cpuXC->setFloatReg(reg_idx, val, width); 363 } 364 365 void setFloatReg(const StaticInst *si, int idx, FloatReg val) 366 { 367 int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; 368 cpuXC->setFloatReg(reg_idx, val); 369 } 370 371 void setFloatRegBits(const StaticInst *si, int idx, 372 FloatRegBits val, int width) 373 { 374 int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; 375 cpuXC->setFloatRegBits(reg_idx, val, width); 376 } 377 378 void setFloatRegBits(const StaticInst *si, int idx, FloatRegBits val) 379 { 380 int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; 381 cpuXC->setFloatRegBits(reg_idx, val); 382 } 383 384 uint64_t readPC() { return cpuXC->readPC(); } 385 uint64_t readNextPC() { return cpuXC->readNextPC(); } 386 uint64_t readNextNPC() { return cpuXC->readNextNPC(); } 387 388 void setPC(uint64_t val) { cpuXC->setPC(val); } 389 void setNextPC(uint64_t val) { cpuXC->setNextPC(val); } 390 void setNextNPC(uint64_t val) { cpuXC->setNextNPC(val); } 391 392 MiscReg readMiscReg(int misc_reg) 393 { 394 return cpuXC->readMiscReg(misc_reg); 395 } 396 397 MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault) 398 { 399 return cpuXC->readMiscRegWithEffect(misc_reg, fault); 400 } 401 402 Fault setMiscReg(int misc_reg, const MiscReg &val) 403 { 404 return cpuXC->setMiscReg(misc_reg, val); 405 } 406 407 Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val) 408 { 409 return cpuXC->setMiscRegWithEffect(misc_reg, val); 410 } 411 412#if FULL_SYSTEM 413 Fault hwrei() { return cpuXC->hwrei(); } 414 int readIntrFlag() { return cpuXC->readIntrFlag(); } 415 void setIntrFlag(int val) { cpuXC->setIntrFlag(val); } 416 bool inPalMode() { return cpuXC->inPalMode(); } 417 void ev5_trap(Fault fault) { fault->invoke(xcProxy); } 418 bool simPalCheck(int palFunc) { return cpuXC->simPalCheck(palFunc); } 419#else 420 void syscall(int64_t callnum) { cpuXC->syscall(callnum); } 421#endif 422 423 bool misspeculating() { return cpuXC->misspeculating(); } 424 ExecContext *xcBase() { return xcProxy; } 425}; 426 427#endif // __CPU_SIMPLE_CPU_SIMPLE_CPU_HH__ 428