base_dyn_inst.hh revision 1061
12207SN/A/* 22207SN/A * Copyright (c) 2001-2004 The Regents of The University of Michigan 32207SN/A * All rights reserved. 42207SN/A * 52207SN/A * Redistribution and use in source and binary forms, with or without 62207SN/A * modification, are permitted provided that the following conditions are 72207SN/A * met: redistributions of source code must retain the above copyright 82207SN/A * notice, this list of conditions and the following disclaimer; 92207SN/A * redistributions in binary form must reproduce the above copyright 102207SN/A * notice, this list of conditions and the following disclaimer in the 112207SN/A * documentation and/or other materials provided with the distribution; 122207SN/A * neither the name of the copyright holders nor the names of its 132207SN/A * contributors may be used to endorse or promote products derived from 142207SN/A * this software without specific prior written permission. 152207SN/A * 162207SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172207SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182207SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192207SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202207SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212207SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222207SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232207SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242207SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252207SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262207SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272665Ssaidi@eecs.umich.edu */ 282665Ssaidi@eecs.umich.edu 292665Ssaidi@eecs.umich.edu#ifndef __BASE_DYN_INST_HH__ 302207SN/A#define __BASE_DYN_INST_HH__ 312207SN/A 325569Snate@binkert.org#include <vector> 335569Snate@binkert.org#include <string> 342207SN/A 3511800Sbrandon.potter@amd.com#include "base/fast_alloc.hh" 362474SN/A#include "base/trace.hh" 372207SN/A 3811851Sbrandon.potter@amd.com#include "cpu/static_inst.hh" 392207SN/A#include "cpu/beta_cpu/comm.hh" 407532Ssteve.reinhardt@amd.com#include "cpu/full_cpu/bpred_update.hh" 417532Ssteve.reinhardt@amd.com#include "mem/functional_mem/main_memory.hh" 427532Ssteve.reinhardt@amd.com#include "cpu/full_cpu/spec_memory.hh" 432474SN/A#include "cpu/inst_seq.hh" 4411851Sbrandon.potter@amd.com#include "cpu/full_cpu/op_class.hh" 452207SN/A#include "cpu/full_cpu/spec_state.hh" 4612186Sgabeblack@google.com 4711169Sandreas.hansson@arm.com/** 485759Shsul@eecs.umich.edu * @file 495759Shsul@eecs.umich.edu * Defines a dynamic instruction context. 505958Sgblack@eecs.umich.edu */ 515958Sgblack@eecs.umich.edu 5213614Sgabeblack@google.comnamespace Trace { 539552Sandreas.hansson@arm.com class InstRecord; 5411851Sbrandon.potter@amd.com}; 5513614Sgabeblack@google.com 5611169Sandreas.hansson@arm.com// Forward declaration. 5711169Sandreas.hansson@arm.comtemplate <class blah> 5811386Ssteve.reinhardt@amd.comclass StaticInstPtr; 5911851Sbrandon.potter@amd.com 6011386Ssteve.reinhardt@amd.comtemplate <class Impl> 6111386Ssteve.reinhardt@amd.comclass BaseDynInst : public FastAlloc, public RefCounted 622474SN/A{ 632474SN/A public: 645569Snate@binkert.org // 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 /** Clears this instruction as being ready to commit. */ 434 void clearCanCommit() { canCommit = false; } 435 436 /** Returns whether or not this instruction is ready to commit. */ 437 bool readyToCommit() const { return canCommit; } 438 439 /** Sets this instruction as squashed. */ 440 void setSquashed() { squashed = true; } 441 442 /** Returns whether or not this instruction is squashed. */ 443 bool isSquashed() const { return squashed; } 444 445 /** Sets this instruction as squashed in the IQ. */ 446 void setSquashedInIQ() { squashedInIQ = true; } 447 448 /** Returns whether or not this instruction is squashed in the IQ. */ 449 bool isSquashedInIQ() { return squashedInIQ; } 450 451 /** Returns the opclass of this instruction. */ 452 OpClass opClass() const { return staticInst->opClass(); } 453 454 /** Returns whether or not the BTB missed. */ 455 bool btbMiss() const { return btbMissed; } 456 457 /** Returns the branch target address. */ 458 Addr branchTarget() const { return staticInst->branchTarget(PC); } 459 460 // The register accessor methods provide the index of the 461 // instruction's operand (e.g., 0 or 1), not the architectural 462 // register index, to simplify the implementation of register 463 // renaming. We find the architectural register index by indexing 464 // into the instruction's own operand index table. Note that a 465 // raw pointer to the StaticInst is provided instead of a 466 // ref-counted StaticInstPtr to redice overhead. This is fine as 467 // long as these methods don't copy the pointer into any long-term 468 // storage (which is pretty hard to imagine they would have reason 469 // to do). 470 471 uint64_t readIntReg(StaticInst<ISA> *si, int idx) 472 { 473 return cpu->readIntReg(_srcRegIdx[idx]); 474 } 475 476 float readFloatRegSingle(StaticInst<ISA> *si, int idx) 477 { 478 return cpu->readFloatRegSingle(_srcRegIdx[idx]); 479 } 480 481 double readFloatRegDouble(StaticInst<ISA> *si, int idx) 482 { 483 return cpu->readFloatRegDouble(_srcRegIdx[idx]); 484 } 485 486 uint64_t readFloatRegInt(StaticInst<ISA> *si, int idx) 487 { 488 return cpu->readFloatRegInt(_srcRegIdx[idx]); 489 } 490 /** @todo: Make results into arrays so they can handle multiple dest 491 * registers. 492 */ 493 void setIntReg(StaticInst<ISA> *si, int idx, uint64_t val) 494 { 495 cpu->setIntReg(_destRegIdx[idx], val); 496 intResult = val; 497 } 498 499 void setFloatRegSingle(StaticInst<ISA> *si, int idx, float val) 500 { 501 cpu->setFloatRegSingle(_destRegIdx[idx], val); 502 floatResult = val; 503 } 504 505 void setFloatRegDouble(StaticInst<ISA> *si, int idx, double val) 506 { 507 cpu->setFloatRegDouble(_destRegIdx[idx], val); 508 doubleResult = val; 509 } 510 511 void setFloatRegInt(StaticInst<ISA> *si, int idx, uint64_t val) 512 { 513 cpu->setFloatRegInt(_destRegIdx[idx], val); 514 intResult = val; 515 } 516 517 /** Read the PC of this instruction. */ 518 Addr readPC() { return PC; } 519 520 /** Set the next PC of this instruction (its actual target). */ 521 void setNextPC(uint64_t val) { nextPC = val; } 522 523// bool misspeculating() { return cpu->misspeculating(); } 524 ExecContext *xcBase() { return xc; } 525}; 526 527template<class Impl> 528template<class T> 529inline Fault 530BaseDynInst<Impl>::read(Addr addr, T &data, unsigned flags) 531{ 532 MemReqPtr req = new MemReq(addr, xc, sizeof(T), flags); 533 req->asid = asid; 534 535 fault = cpu->translateDataReadReq(req); 536 537 // Record key MemReq parameters so we can generate another one 538 // just like it for the timing access without calling translate() 539 // again (which might mess up the TLB). 540 effAddr = req->vaddr; 541 physEffAddr = req->paddr; 542 memReqFlags = req->flags; 543 544 /** 545 * @todo 546 * Replace the disjoint functional memory with a unified one and remove 547 * this hack. 548 */ 549#ifndef FULL_SYSTEM 550 req->paddr = req->vaddr; 551#endif 552 553 if (fault == No_Fault) { 554 fault = cpu->read(req, data); 555 } 556 else { 557 // Return a fixed value to keep simulation deterministic even 558 // along misspeculated paths. 559 data = (T)-1; 560 } 561 562 if (traceData) { 563 traceData->setAddr(addr); 564 traceData->setData(data); 565 } 566 567 return fault; 568} 569 570template<class Impl> 571template<class T> 572inline Fault 573BaseDynInst<Impl>::write(T data, Addr addr, unsigned flags, uint64_t *res) 574{ 575 if (traceData) { 576 traceData->setAddr(addr); 577 traceData->setData(data); 578 } 579 580 storeSize = sizeof(T); 581 storeData = data; 582 if (specMode) 583 specMemWrite = true; 584 585 MemReqPtr req = new MemReq(addr, xc, sizeof(T), flags); 586 587 req->asid = asid; 588 589 fault = cpu->translateDataWriteReq(req); 590 591 // Record key MemReq parameters so we can generate another one 592 // just like it for the timing access without calling translate() 593 // again (which might mess up the TLB). 594 effAddr = req->vaddr; 595 physEffAddr = req->paddr; 596 memReqFlags = req->flags; 597 598 /** 599 * @todo 600 * Replace the disjoint functional memory with a unified one and remove 601 * this hack. 602 */ 603#ifndef FULL_SYSTEM 604 req->paddr = req->vaddr; 605#endif 606 607 if (fault == No_Fault) { 608 fault = cpu->write(req, data); 609 } 610 611 if (res) { 612 // always return some result to keep misspeculated paths 613 // (which will ignore faults) deterministic 614 *res = (fault == No_Fault) ? req->result : 0; 615 } 616 617 return fault; 618} 619 620#endif // __DYN_INST_HH__ 621