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