ff178f6d3ee56cc60119c8b0951737aa6892ca83
2 * Copyright (c) 2007 MIPS Technologies, Inc.
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.
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.
28 * Authors: Korey Sewell
37 #include "arch/faults.hh"
38 #include "base/bigint.hh"
39 #include "base/cp_annotate.hh"
40 #include "base/cprintf.hh"
41 #include "base/trace.hh"
42 #include "config/the_isa.hh"
43 #include "cpu/inorder/cpu.hh"
44 #include "cpu/inorder/inorder_dyn_inst.hh"
45 #include "cpu/exetrace.hh"
46 #include "debug/InOrderDynInst.hh"
47 #include "mem/request.hh"
50 using namespace TheISA
;
51 using namespace ThePipeline
;
53 InOrderDynInst::InOrderDynInst(InOrderCPU
*cpu
,
54 InOrderThreadState
*state
,
58 : seqNum(seq_num
), squashSeqNum(0), threadNumber(tid
), asid(_asid
),
59 virtProcNumber(0), staticInst(NULL
), traceData(NULL
), cpu(cpu
),
60 thread(state
), fault(NoFault
), memData(NULL
), loadData(0),
61 storeData(0), effAddr(0), physEffAddr(0), memReqFlags(0),
62 readyRegs(0), pc(0), predPC(0), memAddr(0), nextStage(0),
63 memTime(0), splitMemData(NULL
), splitMemReq(NULL
), totalSize(0),
64 split2ndSize(0), split2ndAddr(0), split2ndAccess(false),
65 split2ndDataPtr(NULL
), split2ndFlags(0), splitInst(false),
66 splitFinishCnt(0), split2ndStoreDataPtr(NULL
), splitInstSked(false),
67 inFrontEnd(true), frontSked(NULL
), backSked(NULL
),
68 squashingStage(0), predictTaken(false), procDelaySlotOnMispred(false),
69 fetchMemReq(NULL
), dataMemReq(NULL
), instEffAddr(0), eaCalcDone(false),
70 lqIdx(0), sqIdx(0), instListIt(NULL
), onInstList(false)
72 for(int i
= 0; i
< MaxInstSrcRegs
; i
++) {
73 _readySrcRegIdx
[i
] = false;
77 for(int j
= 0; j
< MaxInstDestRegs
; j
++) {
79 _prevDestRegIdx
[j
] = 0;
83 DPRINTF(InOrderDynInst
, "DynInst: [tid:%i] [sn:%lli] Instruction created."
84 " (active insts: %i)\n", threadNumber
, seqNum
, instcount
);
88 int InOrderDynInst::instcount
= 0;
91 InOrderDynInst::cpuId()
97 InOrderDynInst::setStaticInst(StaticInstPtr si
)
101 for (int i
= 0; i
< this->staticInst
->numDestRegs(); i
++) {
102 _destRegIdx
[i
] = this->staticInst
->destRegIdx(i
);
105 for (int i
= 0; i
< this->staticInst
->numSrcRegs(); i
++) {
106 _srcRegIdx
[i
] = this->staticInst
->srcRegIdx(i
);
107 this->_readySrcRegIdx
[i
] = 0;
112 InOrderDynInst::initVars()
120 split2ndAccess
= false;
122 splitInstSked
= false;
134 memAddrReady
= false;
137 predictTaken
= false;
138 procDelaySlotOnMispred
= false;
143 // Also make this a parameter, or perhaps get it from xc or cpu.
148 // Initialize the fault to be NoFault.
151 // Make sure to have the renamed register entries set to the same
152 // as the normal register entries. It will allow the IQ to work
153 // without any modifications.
154 if (this->staticInst
) {
155 for (int i
= 0; i
< this->staticInst
->numDestRegs(); i
++) {
156 _destRegIdx
[i
] = this->staticInst
->destRegIdx(i
);
159 for (int i
= 0; i
< this->staticInst
->numSrcRegs(); i
++) {
160 _srcRegIdx
[i
] = this->staticInst
->srcRegIdx(i
);
161 this->_readySrcRegIdx
[i
] = 0;
165 // Update Instruction Count for this instruction
166 if (instcount
> 100) {
167 fatal("Number of Active Instructions in CPU is too high. "
168 "(Not Dereferencing Ptrs. Correctly?)\n");
173 InOrderDynInst::resetInstCount()
179 InOrderDynInst::~InOrderDynInst()
185 delete [] splitMemData
;
191 DPRINTF(InOrderDynInst
, "DynInst: [tid:%i] [sn:%lli] Instruction destroyed"
192 " (active insts: %i)\n", threadNumber
, seqNum
, instcount
);
196 InOrderDynInst::setStaticInst(StaticInstPtr
&static_inst
)
198 this->staticInst
= static_inst
;
200 // Make sure to have the renamed register entries set to the same
201 // as the normal register entries. It will allow the IQ to work
202 // without any modifications.
203 if (this->staticInst
) {
204 for (int i
= 0; i
< this->staticInst
->numDestRegs(); i
++) {
205 _destRegIdx
[i
] = this->staticInst
->destRegIdx(i
);
208 for (int i
= 0; i
< this->staticInst
->numSrcRegs(); i
++) {
209 _srcRegIdx
[i
] = this->staticInst
->srcRegIdx(i
);
210 this->_readySrcRegIdx
[i
] = 0;
216 InOrderDynInst::execute()
218 // @todo: Pretty convoluted way to avoid squashing from happening
219 // when using the TC during an instruction's execution
220 // (specifically for instructions that have side-effects that use
221 // the TC). Fix this.
222 bool in_syscall
= this->thread
->inSyscall
;
223 this->thread
->inSyscall
= true;
225 this->fault
= this->staticInst
->execute(this, this->traceData
);
227 this->thread
->inSyscall
= in_syscall
;
233 InOrderDynInst::calcEA()
235 this->fault
= this->staticInst
->eaComp(this, this->traceData
);
240 InOrderDynInst::initiateAcc()
242 // @todo: Pretty convoluted way to avoid squashing from happening
243 // when using the TC during an instruction's execution
244 // (specifically for instructions that have side-effects that use
245 // the TC). Fix this.
246 bool in_syscall
= this->thread
->inSyscall
;
247 this->thread
->inSyscall
= true;
249 this->fault
= this->staticInst
->initiateAcc(this, this->traceData
);
251 this->thread
->inSyscall
= in_syscall
;
258 InOrderDynInst::completeAcc(Packet
*pkt
)
260 this->fault
= this->staticInst
->completeAcc(pkt
, this, this->traceData
);
266 InOrderDynInst::memAccess()
268 return initiateAcc();
275 InOrderDynInst::hwrei()
277 #if THE_ISA == ALPHA_ISA
278 // Can only do a hwrei when in pal mode.
279 if (!(this->instAddr() & 0x3))
280 return new AlphaISA::UnimplementedOpcodeFault
;
282 // Set the next PC based on the value of the EXC_ADDR IPR.
283 AlphaISA::PCState pc
= this->pcState();
284 pc
.npc(this->cpu
->readMiscRegNoEffect(AlphaISA::IPR_EXC_ADDR
,
285 this->threadNumber
));
287 if (CPA::available()) {
288 ThreadContext
*tc
= this->cpu
->tcBase(this->threadNumber
);
289 CPA::cpa()->swAutoBegin(tc
, this->nextInstAddr());
292 // Tell CPU to clear any state it needs to if a hwrei is taken.
293 this->cpu
->hwrei(this->threadNumber
);
300 InOrderDynInst::trap(Fault fault
)
302 this->cpu
->trap(fault
, this->threadNumber
, this);
307 InOrderDynInst::simPalCheck(int palFunc
)
309 #if THE_ISA != ALPHA_ISA
310 panic("simPalCheck called, but PAL only exists in Alpha!\n");
312 return this->cpu
->simPalCheck(palFunc
, this->threadNumber
);
317 InOrderDynInst::syscall(int64_t callnum
)
320 panic("Syscall emulation isn't available in FS mode.\n");
322 syscallNum
= callnum
;
323 cpu
->syscallContext(NoFault
, this->threadNumber
, this);
328 InOrderDynInst::setSquashInfo(unsigned stage_num
)
330 squashingStage
= stage_num
;
332 // If it's a fault, then we need to squash
333 // the faulting instruction too. Squash
334 // functions squash above a seqNum, so we
335 // decrement here for that case
336 if (fault
!= NoFault
) {
337 squashSeqNum
= seqNum
- 1;
340 squashSeqNum
= seqNum
;
342 #if ISA_HAS_DELAY_SLOT
343 if (staticInst
&& isControl()) {
344 TheISA::PCState nextPC
= pc
;
345 TheISA::advancePC(nextPC
, staticInst
);
347 // Check to see if we should squash after the
348 // branch or after a branch delay slot.
349 if (pc
.nextInstAddr() == pc
.instAddr() + sizeof(MachInst
))
350 squashSeqNum
= seqNum
+ 1;
352 squashSeqNum
= seqNum
;
358 InOrderDynInst::releaseReq(ResourceRequest
* req
)
360 std::list
<ResourceRequest
*>::iterator list_it
= reqList
.begin();
361 std::list
<ResourceRequest
*>::iterator list_end
= reqList
.end();
363 while(list_it
!= list_end
) {
364 if((*list_it
)->getResIdx() == req
->getResIdx() &&
365 (*list_it
)->getSlot() == req
->getSlot()) {
366 DPRINTF(InOrderDynInst
, "[tid:%u]: [sn:%i] Done with request "
367 "to %s.\n", threadNumber
, seqNum
, req
->res
->name());
368 reqList
.erase(list_it
);
374 panic("Releasing Res. Request That Isnt There!\n");
377 /** Records an integer source register being set to a value. */
379 InOrderDynInst::setIntSrc(int idx
, uint64_t val
)
381 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] [src:%i] Int being set "
382 "to %#x.\n", threadNumber
, seqNum
, idx
, val
);
383 instSrc
[idx
].intVal
= val
;
386 /** Records an fp register being set to a value. */
388 InOrderDynInst::setFloatSrc(int idx
, FloatReg val
)
390 instSrc
[idx
].fpVal
.f
= val
;
391 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] [src:%i] FP being set "
392 "to %x, %08f...%08f\n", threadNumber
, seqNum
, idx
,
393 instSrc
[idx
].fpVal
.i
, instSrc
[idx
].fpVal
.f
, val
);
396 /** Records an fp register being set to an integer value. */
398 InOrderDynInst::setFloatRegBitsSrc(int idx
, FloatRegBits val
)
400 instSrc
[idx
].fpVal
.i
= val
;
401 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] [src:%i] FPBits being set "
402 "to %x, %08f...%x\n", threadNumber
, seqNum
, idx
,
403 instSrc
[idx
].fpVal
.i
, instSrc
[idx
].fpVal
.f
, val
);
406 /** Reads a integer register. */
408 InOrderDynInst::readIntRegOperand(const StaticInst
*si
, int idx
, ThreadID tid
)
410 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] [src:%i] IntVal read as %#x.\n",
411 threadNumber
, seqNum
, idx
, instSrc
[idx
].intVal
);
412 return instSrc
[idx
].intVal
;
415 /** Reads a FP register. */
417 InOrderDynInst::readFloatRegOperand(const StaticInst
*si
, int idx
)
419 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] [src:%i] FPVal being read "
420 "as %x, %08f.\n", threadNumber
, seqNum
, idx
,
421 instSrc
[idx
].fpVal
.i
, instSrc
[idx
].fpVal
.f
);
422 return instSrc
[idx
].fpVal
.f
;
426 /** Reads a FP register as a integer. */
428 InOrderDynInst::readFloatRegOperandBits(const StaticInst
*si
, int idx
)
430 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] [src:%i] FPBits being read "
431 "as %x, %08f.\n", threadNumber
, seqNum
, idx
,
432 instSrc
[idx
].fpVal
.i
, instSrc
[idx
].fpVal
.f
);
433 return instSrc
[idx
].fpVal
.i
;
436 /** Reads a miscellaneous register. */
438 InOrderDynInst::readMiscReg(int misc_reg
)
440 return this->cpu
->readMiscReg(misc_reg
, threadNumber
);
444 /** Reads a misc. register, including any side-effects the read
445 * might have as defined by the architecture.
448 InOrderDynInst::readMiscRegOperand(const StaticInst
*si
, int idx
)
450 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] Misc. Reg Source Value %i"
451 " read as %#x.\n", threadNumber
, seqNum
, idx
,
452 instSrc
[idx
].intVal
);
453 return instSrc
[idx
].intVal
;
457 /** Sets a misc. register, including any side-effects the write
458 * might have as defined by the architecture.
461 InOrderDynInst::setMiscRegOperand(const StaticInst
*si
, int idx
,
464 instResult
[idx
].type
= Integer
;
465 instResult
[idx
].res
.intVal
= val
;
466 instResult
[idx
].tick
= curTick();
468 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] Setting Misc Reg. Operand %i "
469 "being set to %#x.\n", threadNumber
, seqNum
, idx
, val
);
473 InOrderDynInst::readRegOtherThread(unsigned reg_idx
, ThreadID tid
)
476 tid
= TheISA::getTargetThread(this->cpu
->tcBase(threadNumber
));
479 if (reg_idx
< FP_Base_DepTag
) { // Integer Register File
480 return this->cpu
->readIntReg(reg_idx
, tid
);
481 } else if (reg_idx
< Ctrl_Base_DepTag
) { // Float Register File
482 reg_idx
-= FP_Base_DepTag
;
483 return this->cpu
->readFloatRegBits(reg_idx
, tid
);
485 reg_idx
-= Ctrl_Base_DepTag
;
486 return this->cpu
->readMiscReg(reg_idx
, tid
); // Misc. Register File
490 /** Sets a Integer register. */
492 InOrderDynInst::setIntRegOperand(const StaticInst
*si
, int idx
, IntReg val
)
494 instResult
[idx
].type
= Integer
;
495 instResult
[idx
].res
.intVal
= val
;
496 instResult
[idx
].tick
= curTick();
498 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] Setting Result Int Reg. %i "
499 "being set to %#x (result-tick:%i).\n",
500 threadNumber
, seqNum
, idx
, val
, instResult
[idx
].tick
);
503 /** Sets a FP register. */
505 InOrderDynInst::setFloatRegOperand(const StaticInst
*si
, int idx
, FloatReg val
)
507 instResult
[idx
].type
= Float
;
508 instResult
[idx
].res
.fpVal
.f
= val
;
509 instResult
[idx
].tick
= curTick();
511 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] Result Float Reg. %i "
512 "being set to %#x, %08f (result-tick:%i).\n",
513 threadNumber
, seqNum
, idx
, val
, val
, instResult
[idx
].tick
);
516 /** Sets a FP register as a integer. */
518 InOrderDynInst::setFloatRegOperandBits(const StaticInst
*si
, int idx
,
521 instResult
[idx
].type
= FloatBits
;
522 instResult
[idx
].res
.fpVal
.i
= val
;
523 instResult
[idx
].tick
= curTick();
525 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] Result Float Reg. Bits %i "
526 "being set to %#x (result-tick:%i).\n",
527 threadNumber
, seqNum
, idx
, val
, instResult
[idx
].tick
);
530 /** Sets a misc. register, including any side-effects the write
531 * might have as defined by the architecture.
533 /* Alter this if/when wanting to *speculate* on Miscellaneous registers */
535 InOrderDynInst::setMiscReg(int misc_reg
, const MiscReg
&val
)
537 this->cpu
->setMiscReg(misc_reg
, val
, threadNumber
);
541 InOrderDynInst::setRegOtherThread(unsigned reg_idx
, const MiscReg
&val
,
544 if (tid
== InvalidThreadID
) {
545 tid
= TheISA::getTargetThread(this->cpu
->tcBase(threadNumber
));
548 if (reg_idx
< FP_Base_DepTag
) { // Integer Register File
549 this->cpu
->setIntReg(reg_idx
, val
, tid
);
550 } else if (reg_idx
< Ctrl_Base_DepTag
) { // Float Register File
551 reg_idx
-= FP_Base_DepTag
;
552 this->cpu
->setFloatRegBits(reg_idx
, val
, tid
);
554 reg_idx
-= Ctrl_Base_DepTag
;
555 this->cpu
->setMiscReg(reg_idx
, val
, tid
); // Misc. Register File
560 InOrderDynInst::deallocateContext(int thread_num
)
562 this->cpu
->deallocateContext(thread_num
);
566 InOrderDynInst::readMem(Addr addr
, uint8_t *data
,
567 unsigned size
, unsigned flags
)
569 return cpu
->read(this, addr
, data
, size
, flags
);
573 InOrderDynInst::writeMem(uint8_t *data
, unsigned size
,
574 Addr addr
, unsigned flags
, uint64_t *res
)
576 return cpu
->write(this, data
, size
, addr
, flags
, res
);
581 InOrderDynInst::dump()
583 cprintf("T%d : %#08d `", threadNumber
, pc
.instAddr());
584 cout
<< staticInst
->disassemble(pc
.instAddr());
589 InOrderDynInst::dump(std::string
&outstring
)
591 std::ostringstream s
;
592 s
<< "T" << threadNumber
<< " : " << pc
<< " "
593 << staticInst
->disassemble(pc
.instAddr());
602 #include "base/hashmap.hh"
604 unsigned int MyHashFunc(const InOrderDynInst
*addr
)
606 unsigned a
= (unsigned)addr
;
607 unsigned hash
= (((a
>> 14) ^ ((a
>> 2) & 0xffff))) & 0x7FFFFFFF;
612 typedef m5::hash_map
<const InOrderDynInst
*, const InOrderDynInst
*,