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