base_dyn_inst.hh revision 1060
1/* 2 * Copyright (c) 2001-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 __BASE_DYN_INST_HH__ 30#define __BASE_DYN_INST_HH__ 31 32#include <vector> 33#include <string> 34 35#include "base/fast_alloc.hh" 36#include "base/trace.hh" 37 38#include "cpu/static_inst.hh" 39#include "cpu/beta_cpu/comm.hh" 40#include "cpu/full_cpu/bpred_update.hh" 41#include "mem/functional_mem/main_memory.hh" 42#include "cpu/full_cpu/spec_memory.hh" 43#include "cpu/inst_seq.hh" 44#include "cpu/full_cpu/op_class.hh" 45#include "cpu/full_cpu/spec_state.hh" 46 47/** 48 * @file 49 * Defines a dynamic instruction context. 50 */ 51 52namespace Trace { 53 class InstRecord; 54}; 55 56class BaseInst 57{ 58}; 59 60template <class Impl> 61class BaseDynInst : public FastAlloc 62{ 63 public: 64 // Typedef for the CPU. 65 typedef typename Impl::FullCPU FullCPU; 66 67 //Typedef to get the ISA. 68 typedef typename Impl::ISA ISA; 69 70 /// Binary machine instruction type. 71 typedef typename ISA::MachInst MachInst; 72 /// Memory address type. 73 typedef typename ISA::Addr Addr; 74 /// Logical register index type. 75 typedef typename ISA::RegIndex RegIndex; 76 /// Integer register index type. 77 typedef typename ISA::IntReg IntReg; 78 79 enum { 80 MaxInstSrcRegs = ISA::MaxInstSrcRegs, //< Max source regs 81 MaxInstDestRegs = ISA::MaxInstDestRegs, //< Max dest regs 82 }; 83 84 StaticInstPtr<ISA> staticInst; 85 86 //////////////////////////////////////////// 87 // 88 // INSTRUCTION EXECUTION 89 // 90 //////////////////////////////////////////// 91 Trace::InstRecord *traceData; 92 93// void setCPSeq(InstSeqNum seq); 94 95 template <class T> 96 Fault read(Addr addr, T &data, unsigned flags); 97 98 template <class T> 99 Fault write(T data, Addr addr, unsigned flags, 100 uint64_t *res); 101 102 103 IntReg *getIntegerRegs(void); 104 FunctionalMemory *getMemory(void); 105 106 void prefetch(Addr addr, unsigned flags); 107 void writeHint(Addr addr, int size, unsigned flags); 108 Fault copySrcTranslate(Addr src); 109 Fault copy(Addr dest); 110 111 public: 112 /** Is this instruction valid. */ 113 bool valid; 114 115 /** The sequence number of the instruction. */ 116 InstSeqNum seqNum; 117 118 /** How many source registers are ready. */ 119 unsigned readyRegs; 120 121 /** Can this instruction issue. */ 122 bool canIssue; 123 124 /** Has this instruction issued. */ 125 bool issued; 126 127 /** Has this instruction executed (or made it through execute) yet. */ 128 bool executed; 129 130 /** Can this instruction commit. */ 131 bool canCommit; 132 133 /** Is this instruction squashed. */ 134 bool squashed; 135 136 /** Is this instruction squashed in the instruction queue. */ 137 bool squashedInIQ; 138 139 /** Is this a recover instruction. */ 140 bool recoverInst; 141 142 /** Is this a thread blocking instruction. */ 143 bool blockingInst; /* this inst has called thread_block() */ 144 145 /** Is this a thread syncrhonization instruction. */ 146 bool threadsyncWait; 147 148 /** If the BTB missed. */ 149 bool btbMissed; 150 151 /** The thread this instruction is from. */ 152 short threadNumber; 153 154 /** If instruction is speculative. */ 155 short specMode; 156 157 /** data address space ID, for loads & stores. */ 158 short asid; 159 160 /** Pointer to the FullCPU object. */ 161 FullCPU *cpu; 162 163 /** Pointer to the exec context. Will not exist in the final version. */ 164 ExecContext *xc; 165 166 /** The kind of fault this instruction has generated. */ 167 Fault fault; 168 169 /** The effective virtual address (lds & stores only). */ 170 Addr effAddr; 171 172 /** The effective physical address. */ 173 Addr physEffAddr; 174 175 /** Effective virtual address for a copy source. */ 176 Addr copySrcEffAddr; 177 178 /** Effective physical address for a copy source. */ 179 Addr copySrcPhysEffAddr; 180 181 /** The memory request flags (from translation). */ 182 unsigned memReqFlags; 183 184 /** The size of the data to be stored. */ 185 int storeSize; 186 187 /** The data to be stored. */ 188 IntReg storeData; 189 190 /** Result of this instruction, if an integer. */ 191 uint64_t intResult; 192 193 /** Result of this instruction, if a float. */ 194 float floatResult; 195 196 /** Result of this instruction, if a double. */ 197 double doubleResult; 198 199 /** PC of this instruction. */ 200 Addr PC; 201 202 /** Next non-speculative PC. It is not filled in at fetch, but rather 203 * once the target of the branch is truly known (either decode or 204 * execute). 205 */ 206 Addr nextPC; 207 208 /** Predicted next PC. */ 209 Addr predPC; 210 211 /** Count of total number of dynamic instructions. */ 212 static int instcount; 213 214 /** Did this instruction do a spec write? */ 215 bool specMemWrite; 216 217 private: 218 /** Physical register index of the destination registers of this 219 * instruction. 220 */ 221 PhysRegIndex _destRegIdx[MaxInstDestRegs]; 222 223 /** Physical register index of the source registers of this 224 * instruction. 225 */ 226 PhysRegIndex _srcRegIdx[MaxInstSrcRegs]; 227 228 /** Whether or not the source register is ready. */ 229 bool _readySrcRegIdx[MaxInstSrcRegs]; 230 231 /** Physical register index of the previous producers of the 232 * architected destinations. 233 */ 234 PhysRegIndex _prevDestRegIdx[MaxInstDestRegs]; 235 236 public: 237 /** BaseDynInst constructor given a binary instruction. */ 238 BaseDynInst(MachInst inst, Addr PC, Addr Pred_PC, InstSeqNum seq_num, 239 FullCPU *cpu); 240 241 /** BaseDynInst constructor given a static inst pointer. */ 242 BaseDynInst(StaticInstPtr<ISA> &_staticInst); 243 244 /** BaseDynInst destructor. */ 245 ~BaseDynInst(); 246 247#if 0 248 Fault 249 mem_access(MemCmd cmd, // Read or Write access cmd 250 Addr addr, // virtual address of access 251 void *p, // input/output buffer 252 int nbytes); // access size 253#endif 254 255 void 256 trace_mem(Fault fault, // last fault 257 MemCmd cmd, // last command 258 Addr addr, // virtual address of access 259 void *p, // memory accessed 260 int nbytes); // access size 261 262 /** Dumps out contents of this BaseDynInst. */ 263 void dump(); 264 265 /** Dumps out contents of this BaseDynInst into given string. */ 266 void dump(std::string &outstring); 267 268 /** Returns the fault type. */ 269 Fault getFault() { return fault; } 270 271 /** Checks whether or not this instruction has had its branch target 272 * calculated yet. For now it is not utilized and is hacked to be 273 * always false. 274 */ 275 bool doneTargCalc() { return false; } 276 277 /** Returns the calculated target of the branch. */ 278 Addr readCalcTarg() { return nextPC; } 279 280 Addr readNextPC() { return nextPC; } 281 282 /** Set the predicted target of this current instruction. */ 283 void setPredTarg(Addr predicted_PC) { predPC = predicted_PC; } 284 285 /** Returns the predicted target of the branch. */ 286 Addr readPredTarg() { return predPC; } 287 288 /** Returns whether the instruction was predicted taken or not. */ 289 bool predTaken() { 290// DPRINTF(FullCPU, "PC: %08p\n", PC); 291// DPRINTF(FullCPU, "predPC: %08p\n", predPC); 292 293 return( predPC != (PC + sizeof(MachInst) ) ); 294 } 295 296 /** Returns whether the instruction mispredicted. */ 297 bool mispredicted() { return (predPC != nextPC); } 298 299 // 300 // Instruction types. Forward checks to StaticInst object. 301 // 302 bool isNop() const { return staticInst->isNop(); } 303 bool isMemRef() const { return staticInst->isMemRef(); } 304 bool isLoad() const { return staticInst->isLoad(); } 305 bool isStore() const { return staticInst->isStore(); } 306 bool isInstPrefetch() const { return staticInst->isInstPrefetch(); } 307 bool isDataPrefetch() const { return staticInst->isDataPrefetch(); } 308 bool isCopy() const { return staticInst->isCopy(); } 309 bool isInteger() const { return staticInst->isInteger(); } 310 bool isFloating() const { return staticInst->isFloating(); } 311 bool isControl() const { return staticInst->isControl(); } 312 bool isCall() const { return staticInst->isCall(); } 313 bool isReturn() const { return staticInst->isReturn(); } 314 bool isDirectCtrl() const { return staticInst->isDirectCtrl(); } 315 bool isIndirectCtrl() const { return staticInst->isIndirectCtrl(); } 316 bool isCondCtrl() const { return staticInst->isCondCtrl(); } 317 bool isUncondCtrl() const { return staticInst->isUncondCtrl(); } 318 bool isThreadSync() const { return staticInst->isThreadSync(); } 319 bool isSerializing() const { return staticInst->isSerializing(); } 320 bool isMemBarrier() const { return staticInst->isMemBarrier(); } 321 bool isWriteBarrier() const { return staticInst->isWriteBarrier(); } 322 bool isNonSpeculative() const { return staticInst->isNonSpeculative(); } 323 324 int8_t numSrcRegs() const { return staticInst->numSrcRegs(); } 325 int8_t numDestRegs() const { return staticInst->numDestRegs(); } 326 327 // the following are used to track physical register usage 328 // for machines with separate int & FP reg files 329 int8_t numFPDestRegs() const { return staticInst->numFPDestRegs(); } 330 int8_t numIntDestRegs() const { return staticInst->numIntDestRegs(); } 331 332 /** Returns the logical register index of the i'th destination register. */ 333 RegIndex destRegIdx(int i) const 334 { 335 return staticInst->destRegIdx(i); 336 } 337 338 /** Returns the logical register index of the i'th source register. */ 339 RegIndex srcRegIdx(int i) const 340 { 341 return staticInst->srcRegIdx(i); 342 } 343 344 /** Returns the physical register index of the i'th destination 345 * register. 346 */ 347 PhysRegIndex renamedDestRegIdx(int idx) const 348 { 349 return _destRegIdx[idx]; 350 } 351 352 /** Returns the physical register index of the i'th source register. */ 353 PhysRegIndex renamedSrcRegIdx(int idx) const 354 { 355 return _srcRegIdx[idx]; 356 } 357 358 bool isReadySrcRegIdx(int idx) const 359 { 360 return _readySrcRegIdx[idx]; 361 } 362 363 /** Returns the physical register index of the previous physical register 364 * that remapped to the same logical register index. 365 */ 366 PhysRegIndex prevDestRegIdx(int idx) const 367 { 368 return _prevDestRegIdx[idx]; 369 } 370 371 /** Renames a destination register to a physical register. Also records 372 * the previous physical register that the logical register mapped to. 373 */ 374 void renameDestReg(int idx, 375 PhysRegIndex renamed_dest, 376 PhysRegIndex previous_rename) 377 { 378 _destRegIdx[idx] = renamed_dest; 379 _prevDestRegIdx[idx] = previous_rename; 380 } 381 382 /** Renames a source logical register to the physical register which 383 * has/will produce that logical register's result. 384 * @todo: add in whether or not the source register is ready. 385 */ 386 void renameSrcReg(int idx, PhysRegIndex renamed_src) 387 { 388 _srcRegIdx[idx] = renamed_src; 389 } 390 391 //Push to .cc file. 392 /** Records that one of the source registers is ready. */ 393 void markSrcRegReady() 394 { 395 ++readyRegs; 396 if(readyRegs == numSrcRegs()) { 397 canIssue = true; 398 } 399 } 400 401 void markSrcRegReady(RegIndex src_idx) 402 { 403 ++readyRegs; 404 405 _readySrcRegIdx[src_idx] = 1; 406 407 if(readyRegs == numSrcRegs()) { 408 canIssue = true; 409 } 410 } 411 412 /** Sets this instruction as ready to issue. */ 413 void setCanIssue() { canIssue = true; } 414 415 /** Returns whether or not this instruction is ready to issue. */ 416 bool readyToIssue() const { return canIssue; } 417 418 /** Sets this instruction as issued from the IQ. */ 419 void setIssued() { issued = true; } 420 421 /** Returns whether or not this instruction has issued. */ 422 bool isIssued() { return issued; } 423 424 /** Sets this instruction as executed. */ 425 void setExecuted() { executed = true; } 426 427 /** Returns whether or not this instruction has executed. */ 428 bool isExecuted() { return executed; } 429 430 /** Sets this instruction as ready to commit. */ 431 void setCanCommit() { canCommit = true; } 432 433 /** Returns whether or not this instruction is ready to commit. */ 434 bool readyToCommit() const { return canCommit; } 435 436 /** Sets this instruction as squashed. */ 437 void setSquashed() { squashed = true; } 438 439 /** Returns whether or not this instruction is squashed. */ 440 bool isSquashed() const { return squashed; } 441 442 /** Sets this instruction as squashed in the IQ. */ 443 void setSquashedInIQ() { squashedInIQ = true; } 444 445 /** Returns whether or not this instruction is squashed in the IQ. */ 446 bool isSquashedInIQ() { return squashedInIQ; } 447 448 /** Returns the opclass of this instruction. */ 449 OpClass opClass() const { return staticInst->opClass(); } 450 451 /** Returns whether or not the BTB missed. */ 452 bool btbMiss() const { return btbMissed; } 453 454 /** Returns the branch target address. */ 455 Addr branchTarget() const { return staticInst->branchTarget(PC); } 456 457 // The register accessor methods provide the index of the 458 // instruction's operand (e.g., 0 or 1), not the architectural 459 // register index, to simplify the implementation of register 460 // renaming. We find the architectural register index by indexing 461 // into the instruction's own operand index table. Note that a 462 // raw pointer to the StaticInst is provided instead of a 463 // ref-counted StaticInstPtr to redice overhead. This is fine as 464 // long as these methods don't copy the pointer into any long-term 465 // storage (which is pretty hard to imagine they would have reason 466 // to do). 467 468 uint64_t readIntReg(StaticInst<ISA> *si, int idx) 469 { 470 return cpu->readIntReg(_srcRegIdx[idx]); 471 } 472 473 float readFloatRegSingle(StaticInst<ISA> *si, int idx) 474 { 475 return cpu->readFloatRegSingle(_srcRegIdx[idx]); 476 } 477 478 double readFloatRegDouble(StaticInst<ISA> *si, int idx) 479 { 480 return cpu->readFloatRegDouble(_srcRegIdx[idx]); 481 } 482 483 uint64_t readFloatRegInt(StaticInst<ISA> *si, int idx) 484 { 485 return cpu->readFloatRegInt(_srcRegIdx[idx]); 486 } 487 /** @todo: Make results into arrays so they can handle multiple dest 488 * registers. 489 */ 490 void setIntReg(StaticInst<ISA> *si, int idx, uint64_t val) 491 { 492 cpu->setIntReg(_destRegIdx[idx], val); 493 intResult = val; 494 } 495 496 void setFloatRegSingle(StaticInst<ISA> *si, int idx, float val) 497 { 498 cpu->setFloatRegSingle(_destRegIdx[idx], val); 499 floatResult = val; 500 } 501 502 void setFloatRegDouble(StaticInst<ISA> *si, int idx, double val) 503 { 504 cpu->setFloatRegDouble(_destRegIdx[idx], val); 505 doubleResult = val; 506 } 507 508 void setFloatRegInt(StaticInst<ISA> *si, int idx, uint64_t val) 509 { 510 cpu->setFloatRegInt(_destRegIdx[idx], val); 511 intResult = val; 512 } 513 514 /** Read the PC of this instruction. */ 515 Addr readPC() { return PC; } 516 517 /** Set the next PC of this instruction (its actual target). */ 518 void setNextPC(uint64_t val) { nextPC = val; } 519 520// bool misspeculating() { return cpu->misspeculating(); } 521 ExecContext *xcBase() { return xc; } 522}; 523 524template<class Impl> 525template<class T> 526inline Fault 527BaseDynInst<Impl>::read(Addr addr, T &data, unsigned flags) 528{ 529 MemReqPtr req = new MemReq(addr, xc, sizeof(T), flags); 530 req->asid = asid; 531 532 fault = cpu->translateDataReadReq(req); 533 534 // Record key MemReq parameters so we can generate another one 535 // just like it for the timing access without calling translate() 536 // again (which might mess up the TLB). 537 effAddr = req->vaddr; 538 physEffAddr = req->paddr; 539 memReqFlags = req->flags; 540 541 /** 542 * @todo 543 * Replace the disjoint functional memory with a unified one and remove 544 * this hack. 545 */ 546#ifndef FULL_SYSTEM 547 req->paddr = req->vaddr; 548#endif 549 550 if (fault == No_Fault) { 551 fault = cpu->read(req, data); 552 } 553 else { 554 // Return a fixed value to keep simulation deterministic even 555 // along misspeculated paths. 556 data = (T)-1; 557 } 558 559 if (traceData) { 560 traceData->setAddr(addr); 561 traceData->setData(data); 562 } 563 564 return fault; 565} 566 567template<class Impl> 568template<class T> 569inline Fault 570BaseDynInst<Impl>::write(T data, Addr addr, unsigned flags, uint64_t *res) 571{ 572 if (traceData) { 573 traceData->setAddr(addr); 574 traceData->setData(data); 575 } 576 577 storeSize = sizeof(T); 578 storeData = data; 579 if (specMode) 580 specMemWrite = true; 581 582 MemReqPtr req = new MemReq(addr, xc, sizeof(T), flags); 583 584 req->asid = asid; 585 586 fault = cpu->translateDataWriteReq(req); 587 588 // Record key MemReq parameters so we can generate another one 589 // just like it for the timing access without calling translate() 590 // again (which might mess up the TLB). 591 effAddr = req->vaddr; 592 physEffAddr = req->paddr; 593 memReqFlags = req->flags; 594 595 /** 596 * @todo 597 * Replace the disjoint functional memory with a unified one and remove 598 * this hack. 599 */ 600#ifndef FULL_SYSTEM 601 req->paddr = req->vaddr; 602#endif 603 604 if (fault == No_Fault) { 605 fault = cpu->write(req, data); 606 } 607 608 if (res) { 609 // always return some result to keep misspeculated paths 610 // (which will ignore faults) deterministic 611 *res = (fault == No_Fault) ? req->result : 0; 612 } 613 614 return fault; 615} 616 617#endif // __DYN_INST_HH__ 618