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