90134f533b9d281a87376ab828a40ad7cfff3654
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/cprintf.hh"
39 #include "base/trace.hh"
40 #include "config/the_isa.hh"
41 #include "cpu/inorder/cpu.hh"
42 #include "cpu/inorder/inorder_dyn_inst.hh"
43 #include "cpu/exetrace.hh"
44 #include "mem/request.hh"
47 using namespace TheISA
;
48 using namespace ThePipeline
;
50 InOrderDynInst::InOrderDynInst(InOrderCPU
*cpu
,
51 InOrderThreadState
*state
,
55 : seqNum(seq_num
), bdelaySeqNum(0), threadNumber(tid
), asid(_asid
),
56 virtProcNumber(0), staticInst(NULL
), traceData(NULL
), cpu(cpu
),
57 thread(state
), fault(NoFault
), memData(NULL
), loadData(0),
58 storeData(0), effAddr(0), physEffAddr(0), memReqFlags(0),
59 readyRegs(0), pc(0), predPC(0), memAddr(0), nextStage(0),
60 memTime(0), splitMemData(NULL
), splitMemReq(NULL
), totalSize(0),
61 split2ndSize(0), split2ndAddr(0), split2ndAccess(false),
62 split2ndDataPtr(NULL
), split2ndFlags(0), splitInst(false),
63 splitFinishCnt(0), split2ndStoreDataPtr(NULL
), splitInstSked(false),
64 inFrontEnd(true), frontSked(NULL
), backSked(NULL
),
65 squashingStage(0), predictTaken(false), procDelaySlotOnMispred(false),
66 fetchMemReq(NULL
), dataMemReq(NULL
), instEffAddr(0), eaCalcDone(false),
67 lqIdx(0), sqIdx(0), instListIt(NULL
)
69 for(int i
= 0; i
< MaxInstSrcRegs
; i
++) {
70 instSrc
[i
].integer
= 0;
72 _readySrcRegIdx
[i
] = false;
76 for(int j
= 0; j
< MaxInstDestRegs
; j
++) {
78 _prevDestRegIdx
[j
] = 0;
82 DPRINTF(InOrderDynInst
, "DynInst: [tid:%i] [sn:%lli] Instruction created."
83 " (active insts: %i)\n", threadNumber
, seqNum
, instcount
);
87 int InOrderDynInst::instcount
= 0;
90 InOrderDynInst::setMachInst(ExtMachInst machInst
)
92 staticInst
= StaticInst::decode(machInst
, pc
.instAddr());
94 for (int i
= 0; i
< this->staticInst
->numDestRegs(); i
++) {
95 _destRegIdx
[i
] = this->staticInst
->destRegIdx(i
);
98 for (int i
= 0; i
< this->staticInst
->numSrcRegs(); i
++) {
99 _srcRegIdx
[i
] = this->staticInst
->srcRegIdx(i
);
100 this->_readySrcRegIdx
[i
] = 0;
105 InOrderDynInst::initVars()
113 split2ndAccess
= false;
115 splitInstSked
= false;
125 for(int i
= 0; i
< MaxInstDestRegs
; i
++)
126 instResult
[i
].val
.integer
= 0;
130 memAddrReady
= false;
133 predictTaken
= false;
134 procDelaySlotOnMispred
= false;
139 // Also make this a parameter, or perhaps get it from xc or cpu.
144 // Initialize the fault to be NoFault.
147 // Make sure to have the renamed register entries set to the same
148 // as the normal register entries. It will allow the IQ to work
149 // without any modifications.
150 if (this->staticInst
) {
151 for (int i
= 0; i
< this->staticInst
->numDestRegs(); i
++) {
152 _destRegIdx
[i
] = this->staticInst
->destRegIdx(i
);
155 for (int i
= 0; i
< this->staticInst
->numSrcRegs(); i
++) {
156 _srcRegIdx
[i
] = this->staticInst
->srcRegIdx(i
);
157 this->_readySrcRegIdx
[i
] = 0;
161 // Update Instruction Count for this instruction
162 if (instcount
> 100) {
163 fatal("Number of Active Instructions in CPU is too high. "
164 "(Not Dereferencing Ptrs. Correctly?)\n");
169 InOrderDynInst::resetInstCount()
175 InOrderDynInst::~InOrderDynInst()
177 if (fetchMemReq
!= 0x0) {
182 if (dataMemReq
!= 0x0) {
187 if (splitMemReq
!= 0x0) {
196 delete [] splitMemData
;
202 DPRINTF(InOrderDynInst
, "DynInst: [tid:%i] [sn:%lli] Instruction destroyed"
203 " (active insts: %i)\n", threadNumber
, seqNum
, instcount
);
207 InOrderDynInst::setStaticInst(StaticInstPtr
&static_inst
)
209 this->staticInst
= static_inst
;
211 // Make sure to have the renamed register entries set to the same
212 // as the normal register entries. It will allow the IQ to work
213 // without any modifications.
214 if (this->staticInst
) {
215 for (int i
= 0; i
< this->staticInst
->numDestRegs(); i
++) {
216 _destRegIdx
[i
] = this->staticInst
->destRegIdx(i
);
219 for (int i
= 0; i
< this->staticInst
->numSrcRegs(); i
++) {
220 _srcRegIdx
[i
] = this->staticInst
->srcRegIdx(i
);
221 this->_readySrcRegIdx
[i
] = 0;
227 InOrderDynInst::execute()
229 // @todo: Pretty convoluted way to avoid squashing from happening
230 // when using the TC during an instruction's execution
231 // (specifically for instructions that have side-effects that use
232 // the TC). Fix this.
233 bool in_syscall
= this->thread
->inSyscall
;
234 this->thread
->inSyscall
= true;
236 this->fault
= this->staticInst
->execute(this, this->traceData
);
238 this->thread
->inSyscall
= in_syscall
;
244 InOrderDynInst::calcEA()
246 this->fault
= this->staticInst
->eaComp(this, this->traceData
);
251 InOrderDynInst::initiateAcc()
253 // @todo: Pretty convoluted way to avoid squashing from happening
254 // when using the TC during an instruction's execution
255 // (specifically for instructions that have side-effects that use
256 // the TC). Fix this.
257 bool in_syscall
= this->thread
->inSyscall
;
258 this->thread
->inSyscall
= true;
260 this->fault
= this->staticInst
->initiateAcc(this, this->traceData
);
262 this->thread
->inSyscall
= in_syscall
;
269 InOrderDynInst::completeAcc(Packet
*pkt
)
271 this->fault
= this->staticInst
->completeAcc(pkt
, this, this->traceData
);
277 InOrderDynInst::memAccess()
279 return initiateAcc();
286 InOrderDynInst::hwrei()
288 panic("InOrderDynInst: hwrei: unimplemented\n");
294 InOrderDynInst::trap(Fault fault
)
296 this->cpu
->trap(fault
, this->threadNumber
, this);
301 InOrderDynInst::simPalCheck(int palFunc
)
303 #if THE_ISA != ALPHA_ISA
304 panic("simPalCheck called, but PAL only exists in Alpha!\n");
306 return this->cpu
->simPalCheck(palFunc
, this->threadNumber
);
310 InOrderDynInst::syscall(int64_t callnum
)
312 cpu
->syscall(callnum
, this->threadNumber
);
317 InOrderDynInst::releaseReq(ResourceRequest
* req
)
319 std::list
<ResourceRequest
*>::iterator list_it
= reqList
.begin();
320 std::list
<ResourceRequest
*>::iterator list_end
= reqList
.end();
322 while(list_it
!= list_end
) {
323 if((*list_it
)->getResIdx() == req
->getResIdx() &&
324 (*list_it
)->getSlot() == req
->getSlot()) {
325 DPRINTF(InOrderDynInst
, "[tid:%u]: [sn:%i] Done with request "
326 "to %s.\n", threadNumber
, seqNum
, req
->res
->name());
327 reqList
.erase(list_it
);
333 panic("Releasing Res. Request That Isnt There!\n");
336 /** Records an integer source register being set to a value. */
338 InOrderDynInst::setIntSrc(int idx
, uint64_t val
)
340 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] Source Value %i being set "
341 "to %#x.\n", threadNumber
, seqNum
, idx
, val
);
342 instSrc
[idx
].integer
= val
;
345 /** Records an fp register being set to a value. */
347 InOrderDynInst::setFloatSrc(int idx
, FloatReg val
)
349 instSrc
[idx
].dbl
= val
;
352 /** Records an fp register being set to an integer value. */
354 InOrderDynInst::setFloatRegBitsSrc(int idx
, uint64_t val
)
356 instSrc
[idx
].integer
= val
;
359 /** Reads a integer register. */
361 InOrderDynInst::readIntRegOperand(const StaticInst
*si
, int idx
, ThreadID tid
)
363 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] Source Value %i read as %#x.\n",
364 threadNumber
, seqNum
, idx
, instSrc
[idx
].integer
);
365 return instSrc
[idx
].integer
;
368 /** Reads a FP register. */
370 InOrderDynInst::readFloatRegOperand(const StaticInst
*si
, int idx
)
372 return instSrc
[idx
].dbl
;
376 /** Reads a FP register as a integer. */
378 InOrderDynInst::readFloatRegOperandBits(const StaticInst
*si
, int idx
)
380 return instSrc
[idx
].integer
;
383 /** Reads a miscellaneous register. */
385 InOrderDynInst::readMiscReg(int misc_reg
)
387 return this->cpu
->readMiscReg(misc_reg
, threadNumber
);
391 /** Reads a misc. register, including any side-effects the read
392 * might have as defined by the architecture.
395 InOrderDynInst::readMiscRegOperand(const StaticInst
*si
, int idx
)
397 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] Misc. Reg Source Value %i"
398 " read as %#x.\n", threadNumber
, seqNum
, idx
,
399 instSrc
[idx
].integer
);
400 return instSrc
[idx
].integer
;
404 /** Sets a misc. register, including any side-effects the write
405 * might have as defined by the architecture.
408 InOrderDynInst::setMiscRegOperand(const StaticInst
*si
, int idx
,
411 instResult
[idx
].type
= Integer
;
412 instResult
[idx
].val
.integer
= val
;
413 instResult
[idx
].tick
= curTick();
415 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] Setting Misc Reg. Operand %i "
416 "being set to %#x.\n", threadNumber
, seqNum
, idx
, val
);
420 InOrderDynInst::readRegOtherThread(unsigned reg_idx
, ThreadID tid
)
423 tid
= TheISA::getTargetThread(this->cpu
->tcBase(threadNumber
));
426 if (reg_idx
< FP_Base_DepTag
) { // Integer Register File
427 return this->cpu
->readIntReg(reg_idx
, tid
);
428 } else if (reg_idx
< Ctrl_Base_DepTag
) { // Float Register File
429 reg_idx
-= FP_Base_DepTag
;
430 return this->cpu
->readFloatRegBits(reg_idx
, tid
);
432 reg_idx
-= Ctrl_Base_DepTag
;
433 return this->cpu
->readMiscReg(reg_idx
, tid
); // Misc. Register File
437 /** Sets a Integer register. */
439 InOrderDynInst::setIntRegOperand(const StaticInst
*si
, int idx
, IntReg val
)
441 instResult
[idx
].type
= Integer
;
442 instResult
[idx
].val
.integer
= val
;
443 instResult
[idx
].tick
= curTick();
445 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] Setting Result Int Reg. %i "
446 "being set to %#x (result-tick:%i).\n",
447 threadNumber
, seqNum
, idx
, val
, instResult
[idx
].tick
);
450 /** Sets a FP register. */
452 InOrderDynInst::setFloatRegOperand(const StaticInst
*si
, int idx
, FloatReg val
)
454 instResult
[idx
].val
.dbl
= val
;
455 instResult
[idx
].type
= Float
;
456 instResult
[idx
].tick
= curTick();
458 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] Setting Result Float Reg. %i "
459 "being set to %#x (result-tick:%i).\n",
460 threadNumber
, seqNum
, idx
, val
, instResult
[idx
].tick
);
463 /** Sets a FP register as a integer. */
465 InOrderDynInst::setFloatRegOperandBits(const StaticInst
*si
, int idx
,
468 instResult
[idx
].type
= Integer
;
469 instResult
[idx
].val
.integer
= val
;
470 instResult
[idx
].tick
= curTick();
472 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] Setting Result Float Reg. %i "
473 "being set to %#x (result-tick:%i).\n",
474 threadNumber
, seqNum
, idx
, val
, instResult
[idx
].tick
);
477 /** Sets a misc. register, including any side-effects the write
478 * might have as defined by the architecture.
480 /* Alter this if/when wanting to *speculate* on Miscellaneous registers */
482 InOrderDynInst::setMiscReg(int misc_reg
, const MiscReg
&val
)
484 this->cpu
->setMiscReg(misc_reg
, val
, threadNumber
);
488 InOrderDynInst::setRegOtherThread(unsigned reg_idx
, const MiscReg
&val
,
491 if (tid
== InvalidThreadID
) {
492 tid
= TheISA::getTargetThread(this->cpu
->tcBase(threadNumber
));
495 if (reg_idx
< FP_Base_DepTag
) { // Integer Register File
496 this->cpu
->setIntReg(reg_idx
, val
, tid
);
497 } else if (reg_idx
< Ctrl_Base_DepTag
) { // Float Register File
498 reg_idx
-= FP_Base_DepTag
;
499 this->cpu
->setFloatRegBits(reg_idx
, val
, tid
);
501 reg_idx
-= Ctrl_Base_DepTag
;
502 this->cpu
->setMiscReg(reg_idx
, val
, tid
); // Misc. Register File
507 InOrderDynInst::deallocateContext(int thread_num
)
509 this->cpu
->deallocateContext(thread_num
);
513 InOrderDynInst::readBytes(Addr addr
, uint8_t *data
,
514 unsigned size
, unsigned flags
)
516 return cpu
->read(this, addr
, data
, size
, flags
);
521 InOrderDynInst::read(Addr addr
, T
&data
, unsigned flags
)
524 traceData
->setAddr(addr
);
525 traceData
->setData(data
);
527 Fault fault
= readBytes(addr
, (uint8_t *)&data
, sizeof(T
), flags
);
528 data
= TheISA::gtoh(data
);
530 traceData
->setData(data
);
534 #ifndef DOXYGEN_SHOULD_SKIP_THIS
538 InOrderDynInst::read(Addr addr
, uint64_t &data
, unsigned flags
);
542 InOrderDynInst::read(Addr addr
, uint32_t &data
, unsigned flags
);
546 InOrderDynInst::read(Addr addr
, uint16_t &data
, unsigned flags
);
550 InOrderDynInst::read(Addr addr
, uint8_t &data
, unsigned flags
);
552 #endif //DOXYGEN_SHOULD_SKIP_THIS
556 InOrderDynInst::read(Addr addr
, double &data
, unsigned flags
)
558 return read(addr
, *(uint64_t*)&data
, flags
);
563 InOrderDynInst::read(Addr addr
, float &data
, unsigned flags
)
565 return read(addr
, *(uint32_t*)&data
, flags
);
570 InOrderDynInst::read(Addr addr
, int32_t &data
, unsigned flags
)
572 return read(addr
, (uint32_t&)data
, flags
);
576 InOrderDynInst::writeBytes(uint8_t *data
, unsigned size
,
577 Addr addr
, unsigned flags
, uint64_t *res
)
579 assert(sizeof(storeData
) >= size
);
580 memcpy(&storeData
, data
, size
);
581 return cpu
->write(this, (uint8_t *)&storeData
, size
, addr
, flags
, res
);
586 InOrderDynInst::write(T data
, Addr addr
, unsigned flags
, uint64_t *res
)
590 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] Setting store data to %#x.\n",
591 threadNumber
, seqNum
, storeData
);
593 traceData
->setAddr(addr
);
594 traceData
->setData(data
);
596 storeData
= TheISA::htog(data
);
597 return writeBytes((uint8_t*)&data
, sizeof(T
), addr
, flags
, res
);
600 #ifndef DOXYGEN_SHOULD_SKIP_THIS
603 InOrderDynInst::write(uint64_t data
, Addr addr
,
604 unsigned flags
, uint64_t *res
);
608 InOrderDynInst::write(uint32_t data
, Addr addr
,
609 unsigned flags
, uint64_t *res
);
613 InOrderDynInst::write(uint16_t data
, Addr addr
,
614 unsigned flags
, uint64_t *res
);
618 InOrderDynInst::write(uint8_t data
, Addr addr
,
619 unsigned flags
, uint64_t *res
);
621 #endif //DOXYGEN_SHOULD_SKIP_THIS
625 InOrderDynInst::write(double data
, Addr addr
, unsigned flags
, uint64_t *res
)
627 return write(*(uint64_t*)&data
, addr
, flags
, res
);
632 InOrderDynInst::write(float data
, Addr addr
, unsigned flags
, uint64_t *res
)
634 return write(*(uint32_t*)&data
, addr
, flags
, res
);
640 InOrderDynInst::write(int32_t data
, Addr addr
, unsigned flags
, uint64_t *res
)
642 return write((uint32_t)data
, addr
, flags
, res
);
647 InOrderDynInst::dump()
649 cprintf("T%d : %#08d `", threadNumber
, pc
.instAddr());
650 cout
<< staticInst
->disassemble(pc
.instAddr());
655 InOrderDynInst::dump(std::string
&outstring
)
657 std::ostringstream s
;
658 s
<< "T" << threadNumber
<< " : " << pc
<< " "
659 << staticInst
->disassemble(pc
.instAddr());
668 #include "base/hashmap.hh"
670 unsigned int MyHashFunc(const InOrderDynInst
*addr
)
672 unsigned a
= (unsigned)addr
;
673 unsigned hash
= (((a
>> 14) ^ ((a
>> 2) & 0xffff))) & 0x7FFFFFFF;
678 typedef m5::hash_map
<const InOrderDynInst
*, const InOrderDynInst
*,