b61beece2558fe1bdf8c76977810d5fb3a1acd7e
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"
48 #include "sim/full_system.hh"
51 using namespace TheISA
;
52 using namespace ThePipeline
;
54 InOrderDynInst::InOrderDynInst(InOrderCPU
*cpu
,
55 InOrderThreadState
*state
,
59 : seqNum(seq_num
), squashSeqNum(0), threadNumber(tid
), asid(_asid
),
60 virtProcNumber(0), staticInst(NULL
), traceData(NULL
), cpu(cpu
),
61 thread(state
), fault(NoFault
), memData(NULL
), loadData(0),
62 storeData(0), effAddr(0), physEffAddr(0), memReqFlags(0),
63 readyRegs(0), pc(0), predPC(0), memAddr(0), nextStage(0),
64 memTime(0), splitMemData(NULL
), splitMemReq(NULL
), totalSize(0),
65 split2ndSize(0), split2ndAddr(0), split2ndAccess(false),
66 split2ndDataPtr(NULL
), split2ndFlags(0), splitInst(false),
67 splitFinishCnt(0), split2ndStoreDataPtr(NULL
), splitInstSked(false),
68 inFrontEnd(true), frontSked(NULL
), backSked(NULL
),
69 squashingStage(0), predictTaken(false), procDelaySlotOnMispred(false),
70 fetchMemReq(NULL
), dataMemReq(NULL
), instEffAddr(0), eaCalcDone(false),
71 lqIdx(0), sqIdx(0), instListIt(NULL
), onInstList(false)
73 for(int i
= 0; i
< MaxInstSrcRegs
; i
++) {
74 _readySrcRegIdx
[i
] = false;
78 for(int j
= 0; j
< MaxInstDestRegs
; j
++) {
80 _prevDestRegIdx
[j
] = 0;
84 DPRINTF(InOrderDynInst
, "DynInst: [tid:%i] [sn:%lli] Instruction created."
85 " (active insts: %i)\n", threadNumber
, seqNum
, instcount
);
89 int InOrderDynInst::instcount
= 0;
92 InOrderDynInst::cpuId()
98 InOrderDynInst::setStaticInst(StaticInstPtr si
)
102 for (int i
= 0; i
< this->staticInst
->numDestRegs(); i
++) {
103 _destRegIdx
[i
] = this->staticInst
->destRegIdx(i
);
106 for (int i
= 0; i
< this->staticInst
->numSrcRegs(); i
++) {
107 _srcRegIdx
[i
] = this->staticInst
->srcRegIdx(i
);
108 this->_readySrcRegIdx
[i
] = 0;
113 InOrderDynInst::initVars()
121 split2ndAccess
= false;
123 splitInstSked
= false;
135 memAddrReady
= false;
138 predictTaken
= false;
139 procDelaySlotOnMispred
= false;
144 // Also make this a parameter, or perhaps get it from xc or cpu.
149 // Initialize the fault to be NoFault.
152 // Make sure to have the renamed register entries set to the same
153 // as the normal register entries. It will allow the IQ to work
154 // without any modifications.
155 if (this->staticInst
) {
156 for (int i
= 0; i
< this->staticInst
->numDestRegs(); i
++) {
157 _destRegIdx
[i
] = this->staticInst
->destRegIdx(i
);
160 for (int i
= 0; i
< this->staticInst
->numSrcRegs(); i
++) {
161 _srcRegIdx
[i
] = this->staticInst
->srcRegIdx(i
);
162 this->_readySrcRegIdx
[i
] = 0;
166 // Update Instruction Count for this instruction
167 if (instcount
> 100) {
168 fatal("Number of Active Instructions in CPU is too high. "
169 "(Not Dereferencing Ptrs. Correctly?)\n");
174 InOrderDynInst::resetInstCount()
180 InOrderDynInst::~InOrderDynInst()
186 delete [] splitMemData
;
192 DPRINTF(InOrderDynInst
, "DynInst: [tid:%i] [sn:%lli] Instruction destroyed"
193 " (active insts: %i)\n", threadNumber
, seqNum
, instcount
);
197 InOrderDynInst::setStaticInst(StaticInstPtr
&static_inst
)
199 this->staticInst
= static_inst
;
201 // Make sure to have the renamed register entries set to the same
202 // as the normal register entries. It will allow the IQ to work
203 // without any modifications.
204 if (this->staticInst
) {
205 for (int i
= 0; i
< this->staticInst
->numDestRegs(); i
++) {
206 _destRegIdx
[i
] = this->staticInst
->destRegIdx(i
);
209 for (int i
= 0; i
< this->staticInst
->numSrcRegs(); i
++) {
210 _srcRegIdx
[i
] = this->staticInst
->srcRegIdx(i
);
211 this->_readySrcRegIdx
[i
] = 0;
217 InOrderDynInst::execute()
219 // @todo: Pretty convoluted way to avoid squashing from happening
220 // when using the TC during an instruction's execution
221 // (specifically for instructions that have side-effects that use
222 // the TC). Fix this.
223 bool in_syscall
= this->thread
->inSyscall
;
224 this->thread
->inSyscall
= true;
226 this->fault
= this->staticInst
->execute(this, this->traceData
);
228 this->thread
->inSyscall
= in_syscall
;
234 InOrderDynInst::calcEA()
236 this->fault
= this->staticInst
->eaComp(this, this->traceData
);
241 InOrderDynInst::initiateAcc()
243 // @todo: Pretty convoluted way to avoid squashing from happening
244 // when using the TC during an instruction's execution
245 // (specifically for instructions that have side-effects that use
246 // the TC). Fix this.
247 bool in_syscall
= this->thread
->inSyscall
;
248 this->thread
->inSyscall
= true;
250 this->fault
= this->staticInst
->initiateAcc(this, this->traceData
);
252 this->thread
->inSyscall
= in_syscall
;
259 InOrderDynInst::completeAcc(Packet
*pkt
)
261 this->fault
= this->staticInst
->completeAcc(pkt
, this, this->traceData
);
267 InOrderDynInst::memAccess()
269 return initiateAcc();
274 InOrderDynInst::hwrei()
276 #if THE_ISA == ALPHA_ISA
277 // Can only do a hwrei when in pal mode.
278 if (!(this->instAddr() & 0x3))
279 return new AlphaISA::UnimplementedOpcodeFault
;
281 // Set the next PC based on the value of the EXC_ADDR IPR.
282 AlphaISA::PCState pc
= this->pcState();
283 pc
.npc(this->cpu
->readMiscRegNoEffect(AlphaISA::IPR_EXC_ADDR
,
284 this->threadNumber
));
286 if (CPA::available()) {
287 ThreadContext
*tc
= this->cpu
->tcBase(this->threadNumber
);
288 CPA::cpa()->swAutoBegin(tc
, this->nextInstAddr());
291 // Tell CPU to clear any state it needs to if a hwrei is taken.
292 this->cpu
->hwrei(this->threadNumber
);
299 InOrderDynInst::trap(Fault fault
)
301 this->cpu
->trap(fault
, this->threadNumber
, this);
306 InOrderDynInst::simPalCheck(int palFunc
)
308 #if THE_ISA != ALPHA_ISA
309 panic("simPalCheck called, but PAL only exists in Alpha!\n");
311 return this->cpu
->simPalCheck(palFunc
, this->threadNumber
);
315 InOrderDynInst::syscall(int64_t callnum
)
318 panic("Syscall emulation isn't available in FS mode.\n");
320 syscallNum
= callnum
;
321 cpu
->syscallContext(NoFault
, this->threadNumber
, this);
325 InOrderDynInst::setSquashInfo(unsigned stage_num
)
327 squashingStage
= stage_num
;
329 // If it's a fault, then we need to squash
330 // the faulting instruction too. Squash
331 // functions squash above a seqNum, so we
332 // decrement here for that case
333 if (fault
!= NoFault
) {
334 squashSeqNum
= seqNum
- 1;
337 squashSeqNum
= seqNum
;
339 #if ISA_HAS_DELAY_SLOT
340 if (staticInst
&& isControl()) {
341 TheISA::PCState nextPC
= pc
;
342 TheISA::advancePC(nextPC
, staticInst
);
344 // Check to see if we should squash after the
345 // branch or after a branch delay slot.
346 if (pc
.nextInstAddr() == pc
.instAddr() + sizeof(MachInst
))
347 squashSeqNum
= seqNum
+ 1;
349 squashSeqNum
= seqNum
;
355 InOrderDynInst::releaseReq(ResourceRequest
* req
)
357 std::list
<ResourceRequest
*>::iterator list_it
= reqList
.begin();
358 std::list
<ResourceRequest
*>::iterator list_end
= reqList
.end();
360 while(list_it
!= list_end
) {
361 if((*list_it
)->getResIdx() == req
->getResIdx() &&
362 (*list_it
)->getSlot() == req
->getSlot()) {
363 DPRINTF(InOrderDynInst
, "[tid:%u]: [sn:%i] Done with request "
364 "to %s.\n", threadNumber
, seqNum
, req
->res
->name());
365 reqList
.erase(list_it
);
371 panic("Releasing Res. Request That Isnt There!\n");
374 /** Records an integer source register being set to a value. */
376 InOrderDynInst::setIntSrc(int idx
, uint64_t val
)
378 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] [src:%i] Int being set "
379 "to %#x.\n", threadNumber
, seqNum
, idx
, val
);
380 instSrc
[idx
].intVal
= val
;
383 /** Records an fp register being set to a value. */
385 InOrderDynInst::setFloatSrc(int idx
, FloatReg val
)
387 instSrc
[idx
].fpVal
.f
= val
;
388 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] [src:%i] FP being set "
389 "to %x, %08f...%08f\n", threadNumber
, seqNum
, idx
,
390 instSrc
[idx
].fpVal
.i
, instSrc
[idx
].fpVal
.f
, val
);
393 /** Records an fp register being set to an integer value. */
395 InOrderDynInst::setFloatRegBitsSrc(int idx
, FloatRegBits val
)
397 instSrc
[idx
].fpVal
.i
= val
;
398 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] [src:%i] FPBits being set "
399 "to %x, %08f...%x\n", threadNumber
, seqNum
, idx
,
400 instSrc
[idx
].fpVal
.i
, instSrc
[idx
].fpVal
.f
, val
);
403 /** Reads a integer register. */
405 InOrderDynInst::readIntRegOperand(const StaticInst
*si
, int idx
, ThreadID tid
)
407 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] [src:%i] IntVal read as %#x.\n",
408 threadNumber
, seqNum
, idx
, instSrc
[idx
].intVal
);
409 return instSrc
[idx
].intVal
;
412 /** Reads a FP register. */
414 InOrderDynInst::readFloatRegOperand(const StaticInst
*si
, int idx
)
416 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] [src:%i] FPVal being read "
417 "as %x, %08f.\n", threadNumber
, seqNum
, idx
,
418 instSrc
[idx
].fpVal
.i
, instSrc
[idx
].fpVal
.f
);
419 return instSrc
[idx
].fpVal
.f
;
423 /** Reads a FP register as a integer. */
425 InOrderDynInst::readFloatRegOperandBits(const StaticInst
*si
, int idx
)
427 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] [src:%i] FPBits being read "
428 "as %x, %08f.\n", threadNumber
, seqNum
, idx
,
429 instSrc
[idx
].fpVal
.i
, instSrc
[idx
].fpVal
.f
);
430 return instSrc
[idx
].fpVal
.i
;
433 /** Reads a miscellaneous register. */
435 InOrderDynInst::readMiscReg(int misc_reg
)
437 return this->cpu
->readMiscReg(misc_reg
, threadNumber
);
441 /** Reads a misc. register, including any side-effects the read
442 * might have as defined by the architecture.
445 InOrderDynInst::readMiscRegOperand(const StaticInst
*si
, int idx
)
447 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] Misc. Reg Source Value %i"
448 " read as %#x.\n", threadNumber
, seqNum
, idx
,
449 instSrc
[idx
].intVal
);
450 return instSrc
[idx
].intVal
;
454 /** Sets a misc. register, including any side-effects the write
455 * might have as defined by the architecture.
458 InOrderDynInst::setMiscRegOperand(const StaticInst
*si
, int idx
,
461 instResult
[idx
].type
= Integer
;
462 instResult
[idx
].res
.intVal
= val
;
463 instResult
[idx
].tick
= curTick();
465 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] Setting Misc Reg. Operand %i "
466 "being set to %#x.\n", threadNumber
, seqNum
, idx
, val
);
470 InOrderDynInst::readRegOtherThread(unsigned reg_idx
, ThreadID tid
)
473 tid
= TheISA::getTargetThread(this->cpu
->tcBase(threadNumber
));
476 if (reg_idx
< FP_Base_DepTag
) { // Integer Register File
477 return this->cpu
->readIntReg(reg_idx
, tid
);
478 } else if (reg_idx
< Ctrl_Base_DepTag
) { // Float Register File
479 reg_idx
-= FP_Base_DepTag
;
480 return this->cpu
->readFloatRegBits(reg_idx
, tid
);
482 reg_idx
-= Ctrl_Base_DepTag
;
483 return this->cpu
->readMiscReg(reg_idx
, tid
); // Misc. Register File
487 /** Sets a Integer register. */
489 InOrderDynInst::setIntRegOperand(const StaticInst
*si
, int idx
, IntReg val
)
491 instResult
[idx
].type
= Integer
;
492 instResult
[idx
].res
.intVal
= val
;
493 instResult
[idx
].tick
= curTick();
495 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] Setting Result Int Reg. %i "
496 "being set to %#x (result-tick:%i).\n",
497 threadNumber
, seqNum
, idx
, val
, instResult
[idx
].tick
);
500 /** Sets a FP register. */
502 InOrderDynInst::setFloatRegOperand(const StaticInst
*si
, int idx
, FloatReg val
)
504 instResult
[idx
].type
= Float
;
505 instResult
[idx
].res
.fpVal
.f
= val
;
506 instResult
[idx
].tick
= curTick();
508 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] Result Float Reg. %i "
509 "being set to %#x, %08f (result-tick:%i).\n",
510 threadNumber
, seqNum
, idx
, val
, val
, instResult
[idx
].tick
);
513 /** Sets a FP register as a integer. */
515 InOrderDynInst::setFloatRegOperandBits(const StaticInst
*si
, int idx
,
518 instResult
[idx
].type
= FloatBits
;
519 instResult
[idx
].res
.fpVal
.i
= val
;
520 instResult
[idx
].tick
= curTick();
522 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] Result Float Reg. Bits %i "
523 "being set to %#x (result-tick:%i).\n",
524 threadNumber
, seqNum
, idx
, val
, instResult
[idx
].tick
);
527 /** Sets a misc. register, including any side-effects the write
528 * might have as defined by the architecture.
530 /* Alter this if/when wanting to *speculate* on Miscellaneous registers */
532 InOrderDynInst::setMiscReg(int misc_reg
, const MiscReg
&val
)
534 this->cpu
->setMiscReg(misc_reg
, val
, threadNumber
);
538 InOrderDynInst::setRegOtherThread(unsigned reg_idx
, const MiscReg
&val
,
541 if (tid
== InvalidThreadID
) {
542 tid
= TheISA::getTargetThread(this->cpu
->tcBase(threadNumber
));
545 if (reg_idx
< FP_Base_DepTag
) { // Integer Register File
546 this->cpu
->setIntReg(reg_idx
, val
, tid
);
547 } else if (reg_idx
< Ctrl_Base_DepTag
) { // Float Register File
548 reg_idx
-= FP_Base_DepTag
;
549 this->cpu
->setFloatRegBits(reg_idx
, val
, tid
);
551 reg_idx
-= Ctrl_Base_DepTag
;
552 this->cpu
->setMiscReg(reg_idx
, val
, tid
); // Misc. Register File
557 InOrderDynInst::deallocateContext(int thread_num
)
559 this->cpu
->deallocateContext(thread_num
);
563 InOrderDynInst::readMem(Addr addr
, uint8_t *data
,
564 unsigned size
, unsigned flags
)
566 return cpu
->read(this, addr
, data
, size
, flags
);
570 InOrderDynInst::writeMem(uint8_t *data
, unsigned size
,
571 Addr addr
, unsigned flags
, uint64_t *res
)
573 return cpu
->write(this, data
, size
, addr
, flags
, res
);
578 InOrderDynInst::dump()
580 cprintf("T%d : %#08d `", threadNumber
, pc
.instAddr());
581 cout
<< staticInst
->disassemble(pc
.instAddr());
586 InOrderDynInst::dump(std::string
&outstring
)
588 std::ostringstream s
;
589 s
<< "T" << threadNumber
<< " : " << pc
<< " "
590 << staticInst
->disassemble(pc
.instAddr());
599 #include "base/hashmap.hh"
601 unsigned int MyHashFunc(const InOrderDynInst
*addr
)
603 unsigned a
= (unsigned)addr
;
604 unsigned hash
= (((a
>> 14) ^ ((a
>> 2) & 0xffff))) & 0x7FFFFFFF;
609 typedef m5::hash_map
<const InOrderDynInst
*, const InOrderDynInst
*,