base.hh revision 5496
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 * Authors: Steve Reinhardt 29 * Dave Greene 30 * Nathan Binkert 31 */ 32 33#ifndef __CPU_SIMPLE_BASE_HH__ 34#define __CPU_SIMPLE_BASE_HH__ 35 36#include "arch/predecoder.hh" 37#include "base/statistics.hh" 38#include "config/full_system.hh" 39#include "cpu/base.hh" 40#include "cpu/simple_thread.hh" 41#include "cpu/pc_event.hh" 42#include "cpu/static_inst.hh" 43#include "mem/packet.hh" 44#include "mem/port.hh" 45#include "mem/request.hh" 46#include "sim/eventq.hh" 47#include "sim/system.hh" 48 49// forward declarations 50#if FULL_SYSTEM 51class Processor; 52namespace TheISA 53{ 54 class ITB; 55 class DTB; 56} 57class MemObject; 58 59#else 60 61class Process; 62 63#endif // FULL_SYSTEM 64 65class RemoteGDB; 66class GDBListener; 67 68namespace TheISA 69{ 70 class Predecoder; 71} 72class ThreadContext; 73class Checkpoint; 74 75namespace Trace { 76 class InstRecord; 77} 78 79 80class BaseSimpleCPU : public BaseCPU 81{ 82 protected: 83 typedef TheISA::MiscReg MiscReg; 84 typedef TheISA::FloatReg FloatReg; 85 typedef TheISA::FloatRegBits FloatRegBits; 86 87 protected: 88 Trace::InstRecord *traceData; 89 90 inline void checkPcEventQueue() { 91 Addr oldpc; 92 do { 93 oldpc = thread->readPC(); 94 system->pcEventQueue.service(tc); 95 } while (oldpc != thread->readPC()); 96 } 97 98 public: 99 void post_interrupt(int int_num, int index); 100 101 void zero_fill_64(Addr addr) { 102 static int warned = 0; 103 if (!warned) { 104 warn ("WH64 is not implemented"); 105 warned = 1; 106 } 107 }; 108 109 public: 110 struct Params : public BaseCPU::Params 111 { 112 TheISA::ITB *itb; 113 TheISA::DTB *dtb; 114#if !FULL_SYSTEM 115 Process *process; 116#endif 117 }; 118 BaseSimpleCPU(Params *params); 119 virtual ~BaseSimpleCPU(); 120 121 public: 122 /** SimpleThread object, provides all the architectural state. */ 123 SimpleThread *thread; 124 125 /** ThreadContext object, provides an interface for external 126 * objects to modify this thread's state. 127 */ 128 ThreadContext *tc; 129 protected: 130 int cpuId; 131 132 enum Status { 133 Idle, 134 Running, 135 IcacheRetry, 136 IcacheWaitResponse, 137 IcacheWaitSwitch, 138 DcacheRetry, 139 DcacheWaitResponse, 140 DcacheWaitSwitch, 141 SwitchedOut 142 }; 143 144 Status _status; 145 146 public: 147 148#if FULL_SYSTEM 149 Addr dbg_vtophys(Addr addr); 150 151 bool interval_stats; 152#endif 153 154 // current instruction 155 TheISA::MachInst inst; 156 157 // The predecoder 158 TheISA::Predecoder predecoder; 159 160 StaticInstPtr curStaticInst; 161 StaticInstPtr curMacroStaticInst; 162 163 //This is the offset from the current pc that fetch should be performed at 164 Addr fetchOffset; 165 //This flag says to stay at the current pc. This is useful for 166 //instructions which go beyond MachInst boundaries. 167 bool stayAtPC; 168 169 void checkForInterrupts(); 170 Fault setupFetchRequest(Request *req); 171 void preExecute(); 172 void postExecute(); 173 void advancePC(Fault fault); 174 175 virtual void deallocateContext(int thread_num); 176 virtual void haltContext(int thread_num); 177 178 // statistics 179 virtual void regStats(); 180 virtual void resetStats(); 181 182 // number of simulated instructions 183 Counter numInst; 184 Counter startNumInst; 185 Stats::Scalar<> numInsts; 186 187 void countInst() 188 { 189 numInst++; 190 numInsts++; 191 192 thread->funcExeInst++; 193 } 194 195 virtual Counter totalInstructions() const 196 { 197 return numInst - startNumInst; 198 } 199 200 // Mask to align PCs to MachInst sized boundaries 201 static const Addr PCMask = ~((Addr)sizeof(TheISA::MachInst) - 1); 202 203 // number of simulated memory references 204 Stats::Scalar<> numMemRefs; 205 206 // number of simulated loads 207 Counter numLoad; 208 Counter startNumLoad; 209 210 // number of idle cycles 211 Stats::Average<> notIdleFraction; 212 Stats::Formula idleFraction; 213 214 // number of cycles stalled for I-cache responses 215 Stats::Scalar<> icacheStallCycles; 216 Counter lastIcacheStall; 217 218 // number of cycles stalled for I-cache retries 219 Stats::Scalar<> icacheRetryCycles; 220 Counter lastIcacheRetry; 221 222 // number of cycles stalled for D-cache responses 223 Stats::Scalar<> dcacheStallCycles; 224 Counter lastDcacheStall; 225 226 // number of cycles stalled for D-cache retries 227 Stats::Scalar<> dcacheRetryCycles; 228 Counter lastDcacheRetry; 229 230 virtual void serialize(std::ostream &os); 231 virtual void unserialize(Checkpoint *cp, const std::string §ion); 232 233 // These functions are only used in CPU models that split 234 // effective address computation from the actual memory access. 235 void setEA(Addr EA) { panic("BaseSimpleCPU::setEA() not implemented\n"); } 236 Addr getEA() { panic("BaseSimpleCPU::getEA() not implemented\n"); 237 M5_DUMMY_RETURN} 238 239 void prefetch(Addr addr, unsigned flags) 240 { 241 // need to do this... 242 } 243 244 void writeHint(Addr addr, int size, unsigned flags) 245 { 246 // need to do this... 247 } 248 249 250 Fault copySrcTranslate(Addr src); 251 252 Fault copy(Addr dest); 253 254 // The register accessor methods provide the index of the 255 // instruction's operand (e.g., 0 or 1), not the architectural 256 // register index, to simplify the implementation of register 257 // renaming. We find the architectural register index by indexing 258 // into the instruction's own operand index table. Note that a 259 // raw pointer to the StaticInst is provided instead of a 260 // ref-counted StaticInstPtr to redice overhead. This is fine as 261 // long as these methods don't copy the pointer into any long-term 262 // storage (which is pretty hard to imagine they would have reason 263 // to do). 264 265 uint64_t readIntRegOperand(const StaticInst *si, int idx) 266 { 267 return thread->readIntReg(si->srcRegIdx(idx)); 268 } 269 270 FloatReg readFloatRegOperand(const StaticInst *si, int idx, int width) 271 { 272 int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; 273 return thread->readFloatReg(reg_idx, width); 274 } 275 276 FloatReg readFloatRegOperand(const StaticInst *si, int idx) 277 { 278 int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; 279 return thread->readFloatReg(reg_idx); 280 } 281 282 FloatRegBits readFloatRegOperandBits(const StaticInst *si, int idx, 283 int width) 284 { 285 int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; 286 return thread->readFloatRegBits(reg_idx, width); 287 } 288 289 FloatRegBits readFloatRegOperandBits(const StaticInst *si, int idx) 290 { 291 int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; 292 return thread->readFloatRegBits(reg_idx); 293 } 294 295 void setIntRegOperand(const StaticInst *si, int idx, uint64_t val) 296 { 297 thread->setIntReg(si->destRegIdx(idx), val); 298 } 299 300 void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val, 301 int width) 302 { 303 int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; 304 thread->setFloatReg(reg_idx, val, width); 305 } 306 307 void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val) 308 { 309 int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; 310 thread->setFloatReg(reg_idx, val); 311 } 312 313 void setFloatRegOperandBits(const StaticInst *si, int idx, 314 FloatRegBits val, int width) 315 { 316 int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; 317 thread->setFloatRegBits(reg_idx, val, width); 318 } 319 320 void setFloatRegOperandBits(const StaticInst *si, int idx, 321 FloatRegBits val) 322 { 323 int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; 324 thread->setFloatRegBits(reg_idx, val); 325 } 326 327 uint64_t readPC() { return thread->readPC(); } 328 uint64_t readMicroPC() { return thread->readMicroPC(); } 329 uint64_t readNextPC() { return thread->readNextPC(); } 330 uint64_t readNextMicroPC() { return thread->readNextMicroPC(); } 331 uint64_t readNextNPC() { return thread->readNextNPC(); } 332 333 void setPC(uint64_t val) { thread->setPC(val); } 334 void setMicroPC(uint64_t val) { thread->setMicroPC(val); } 335 void setNextPC(uint64_t val) { thread->setNextPC(val); } 336 void setNextMicroPC(uint64_t val) { thread->setNextMicroPC(val); } 337 void setNextNPC(uint64_t val) { thread->setNextNPC(val); } 338 339 MiscReg readMiscRegNoEffect(int misc_reg) 340 { 341 return thread->readMiscRegNoEffect(misc_reg); 342 } 343 344 MiscReg readMiscReg(int misc_reg) 345 { 346 return thread->readMiscReg(misc_reg); 347 } 348 349 void setMiscRegNoEffect(int misc_reg, const MiscReg &val) 350 { 351 return thread->setMiscRegNoEffect(misc_reg, val); 352 } 353 354 void setMiscReg(int misc_reg, const MiscReg &val) 355 { 356 return thread->setMiscReg(misc_reg, val); 357 } 358 359 MiscReg readMiscRegOperandNoEffect(const StaticInst *si, int idx) 360 { 361 int reg_idx = si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag; 362 return thread->readMiscRegNoEffect(reg_idx); 363 } 364 365 MiscReg readMiscRegOperand(const StaticInst *si, int idx) 366 { 367 int reg_idx = si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag; 368 return thread->readMiscReg(reg_idx); 369 } 370 371 void setMiscRegOperandNoEffect(const StaticInst *si, int idx, const MiscReg &val) 372 { 373 int reg_idx = si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag; 374 return thread->setMiscRegNoEffect(reg_idx, val); 375 } 376 377 void setMiscRegOperand( 378 const StaticInst *si, int idx, const MiscReg &val) 379 { 380 int reg_idx = si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag; 381 return thread->setMiscReg(reg_idx, val); 382 } 383 384 void demapPage(Addr vaddr, uint64_t asn) 385 { 386 thread->demapPage(vaddr, asn); 387 } 388 389 void demapInstPage(Addr vaddr, uint64_t asn) 390 { 391 thread->demapInstPage(vaddr, asn); 392 } 393 394 void demapDataPage(Addr vaddr, uint64_t asn) 395 { 396 thread->demapDataPage(vaddr, asn); 397 } 398 399 unsigned readStCondFailures() { 400 return thread->readStCondFailures(); 401 } 402 403 void setStCondFailures(unsigned sc_failures) { 404 thread->setStCondFailures(sc_failures); 405 } 406 407 MiscReg readRegOtherThread(int regIdx, int tid = -1) 408 { 409 panic("Simple CPU models do not support multithreaded " 410 "register access.\n"); 411 } 412 413 void setRegOtherThread(int regIdx, const MiscReg &val, int tid = -1) 414 { 415 panic("Simple CPU models do not support multithreaded " 416 "register access.\n"); 417 } 418 419 //Fault CacheOp(uint8_t Op, Addr EA); 420 421#if FULL_SYSTEM 422 Fault hwrei() { return thread->hwrei(); } 423 void ev5_trap(Fault fault) { fault->invoke(tc); } 424 bool simPalCheck(int palFunc) { return thread->simPalCheck(palFunc); } 425#else 426 void syscall(int64_t callnum) { thread->syscall(callnum); } 427#endif 428 429 bool misspeculating() { return thread->misspeculating(); } 430 ThreadContext *tcBase() { return tc; } 431}; 432 433#endif // __CPU_SIMPLE_BASE_HH__ 434