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/cprintf.hh"
40 #include "base/trace.hh"
41 #include "config/the_isa.hh"
42 #include "cpu/inorder/cpu.hh"
43 #include "cpu/inorder/inorder_dyn_inst.hh"
44 #include "cpu/exetrace.hh"
45 #include "debug/InOrderDynInst.hh"
46 #include "mem/request.hh"
49 using namespace TheISA
;
50 using namespace ThePipeline
;
52 InOrderDynInst::InOrderDynInst(InOrderCPU
*cpu
,
53 InOrderThreadState
*state
,
57 : seqNum(seq_num
), bdelaySeqNum(0), threadNumber(tid
), asid(_asid
),
58 virtProcNumber(0), staticInst(NULL
), traceData(NULL
), cpu(cpu
),
59 thread(state
), fault(NoFault
), memData(NULL
), loadData(0),
60 storeData(0), effAddr(0), physEffAddr(0), memReqFlags(0),
61 readyRegs(0), pc(0), predPC(0), memAddr(0), nextStage(0),
62 memTime(0), splitMemData(NULL
), splitMemReq(NULL
), totalSize(0),
63 split2ndSize(0), split2ndAddr(0), split2ndAccess(false),
64 split2ndDataPtr(NULL
), split2ndFlags(0), splitInst(false),
65 splitFinishCnt(0), split2ndStoreDataPtr(NULL
), splitInstSked(false),
66 inFrontEnd(true), frontSked(NULL
), backSked(NULL
),
67 squashingStage(0), predictTaken(false), procDelaySlotOnMispred(false),
68 fetchMemReq(NULL
), dataMemReq(NULL
), instEffAddr(0), eaCalcDone(false),
69 lqIdx(0), sqIdx(0), instListIt(NULL
)
71 for(int i
= 0; i
< MaxInstSrcRegs
; i
++) {
72 instSrc
[i
].integer
= 0;
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::setMachInst(ExtMachInst machInst
)
94 staticInst
= StaticInst::decode(machInst
, pc
.instAddr());
96 for (int i
= 0; i
< this->staticInst
->numDestRegs(); i
++) {
97 _destRegIdx
[i
] = this->staticInst
->destRegIdx(i
);
100 for (int i
= 0; i
< this->staticInst
->numSrcRegs(); i
++) {
101 _srcRegIdx
[i
] = this->staticInst
->srcRegIdx(i
);
102 this->_readySrcRegIdx
[i
] = 0;
107 InOrderDynInst::initVars()
115 split2ndAccess
= false;
117 splitInstSked
= false;
127 for(int i
= 0; i
< MaxInstDestRegs
; i
++)
128 instResult
[i
].val
.integer
= 0;
132 memAddrReady
= false;
135 predictTaken
= false;
136 procDelaySlotOnMispred
= false;
141 // Also make this a parameter, or perhaps get it from xc or cpu.
146 // Initialize the fault to be NoFault.
149 // Make sure to have the renamed register entries set to the same
150 // as the normal register entries. It will allow the IQ to work
151 // without any modifications.
152 if (this->staticInst
) {
153 for (int i
= 0; i
< this->staticInst
->numDestRegs(); i
++) {
154 _destRegIdx
[i
] = this->staticInst
->destRegIdx(i
);
157 for (int i
= 0; i
< this->staticInst
->numSrcRegs(); i
++) {
158 _srcRegIdx
[i
] = this->staticInst
->srcRegIdx(i
);
159 this->_readySrcRegIdx
[i
] = 0;
163 // Update Instruction Count for this instruction
164 if (instcount
> 100) {
165 fatal("Number of Active Instructions in CPU is too high. "
166 "(Not Dereferencing Ptrs. Correctly?)\n");
171 InOrderDynInst::resetInstCount()
177 InOrderDynInst::~InOrderDynInst()
179 if (fetchMemReq
!= 0x0) {
184 if (dataMemReq
!= 0x0) {
189 if (splitMemReq
!= 0x0) {
198 delete [] splitMemData
;
204 DPRINTF(InOrderDynInst
, "DynInst: [tid:%i] [sn:%lli] Instruction destroyed"
205 " (active insts: %i)\n", threadNumber
, seqNum
, instcount
);
209 InOrderDynInst::setStaticInst(StaticInstPtr
&static_inst
)
211 this->staticInst
= static_inst
;
213 // Make sure to have the renamed register entries set to the same
214 // as the normal register entries. It will allow the IQ to work
215 // without any modifications.
216 if (this->staticInst
) {
217 for (int i
= 0; i
< this->staticInst
->numDestRegs(); i
++) {
218 _destRegIdx
[i
] = this->staticInst
->destRegIdx(i
);
221 for (int i
= 0; i
< this->staticInst
->numSrcRegs(); i
++) {
222 _srcRegIdx
[i
] = this->staticInst
->srcRegIdx(i
);
223 this->_readySrcRegIdx
[i
] = 0;
229 InOrderDynInst::execute()
231 // @todo: Pretty convoluted way to avoid squashing from happening
232 // when using the TC during an instruction's execution
233 // (specifically for instructions that have side-effects that use
234 // the TC). Fix this.
235 bool in_syscall
= this->thread
->inSyscall
;
236 this->thread
->inSyscall
= true;
238 this->fault
= this->staticInst
->execute(this, this->traceData
);
240 this->thread
->inSyscall
= in_syscall
;
246 InOrderDynInst::calcEA()
248 this->fault
= this->staticInst
->eaComp(this, this->traceData
);
253 InOrderDynInst::initiateAcc()
255 // @todo: Pretty convoluted way to avoid squashing from happening
256 // when using the TC during an instruction's execution
257 // (specifically for instructions that have side-effects that use
258 // the TC). Fix this.
259 bool in_syscall
= this->thread
->inSyscall
;
260 this->thread
->inSyscall
= true;
262 this->fault
= this->staticInst
->initiateAcc(this, this->traceData
);
264 this->thread
->inSyscall
= in_syscall
;
271 InOrderDynInst::completeAcc(Packet
*pkt
)
273 this->fault
= this->staticInst
->completeAcc(pkt
, this, this->traceData
);
279 InOrderDynInst::memAccess()
281 return initiateAcc();
288 InOrderDynInst::hwrei()
290 panic("InOrderDynInst: hwrei: unimplemented\n");
296 InOrderDynInst::trap(Fault fault
)
298 this->cpu
->trap(fault
, this->threadNumber
, this);
303 InOrderDynInst::simPalCheck(int palFunc
)
305 #if THE_ISA != ALPHA_ISA
306 panic("simPalCheck called, but PAL only exists in Alpha!\n");
308 return this->cpu
->simPalCheck(palFunc
, this->threadNumber
);
312 InOrderDynInst::syscall(int64_t callnum
)
314 cpu
->syscall(callnum
, this->threadNumber
);
319 InOrderDynInst::releaseReq(ResourceRequest
* req
)
321 std::list
<ResourceRequest
*>::iterator list_it
= reqList
.begin();
322 std::list
<ResourceRequest
*>::iterator list_end
= reqList
.end();
324 while(list_it
!= list_end
) {
325 if((*list_it
)->getResIdx() == req
->getResIdx() &&
326 (*list_it
)->getSlot() == req
->getSlot()) {
327 DPRINTF(InOrderDynInst
, "[tid:%u]: [sn:%i] Done with request "
328 "to %s.\n", threadNumber
, seqNum
, req
->res
->name());
329 reqList
.erase(list_it
);
335 panic("Releasing Res. Request That Isnt There!\n");
338 /** Records an integer source register being set to a value. */
340 InOrderDynInst::setIntSrc(int idx
, uint64_t val
)
342 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] Source Value %i being set "
343 "to %#x.\n", threadNumber
, seqNum
, idx
, val
);
344 instSrc
[idx
].integer
= val
;
347 /** Records an fp register being set to a value. */
349 InOrderDynInst::setFloatSrc(int idx
, FloatReg val
)
351 instSrc
[idx
].dbl
= val
;
354 /** Records an fp register being set to an integer value. */
356 InOrderDynInst::setFloatRegBitsSrc(int idx
, uint64_t val
)
358 instSrc
[idx
].integer
= val
;
361 /** Reads a integer register. */
363 InOrderDynInst::readIntRegOperand(const StaticInst
*si
, int idx
, ThreadID tid
)
365 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] Source Value %i read as %#x.\n",
366 threadNumber
, seqNum
, idx
, instSrc
[idx
].integer
);
367 return instSrc
[idx
].integer
;
370 /** Reads a FP register. */
372 InOrderDynInst::readFloatRegOperand(const StaticInst
*si
, int idx
)
374 return instSrc
[idx
].dbl
;
378 /** Reads a FP register as a integer. */
380 InOrderDynInst::readFloatRegOperandBits(const StaticInst
*si
, int idx
)
382 return instSrc
[idx
].integer
;
385 /** Reads a miscellaneous register. */
387 InOrderDynInst::readMiscReg(int misc_reg
)
389 return this->cpu
->readMiscReg(misc_reg
, threadNumber
);
393 /** Reads a misc. register, including any side-effects the read
394 * might have as defined by the architecture.
397 InOrderDynInst::readMiscRegOperand(const StaticInst
*si
, int idx
)
399 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] Misc. Reg Source Value %i"
400 " read as %#x.\n", threadNumber
, seqNum
, idx
,
401 instSrc
[idx
].integer
);
402 return instSrc
[idx
].integer
;
406 /** Sets a misc. register, including any side-effects the write
407 * might have as defined by the architecture.
410 InOrderDynInst::setMiscRegOperand(const StaticInst
*si
, int idx
,
413 instResult
[idx
].type
= Integer
;
414 instResult
[idx
].val
.integer
= val
;
415 instResult
[idx
].tick
= curTick();
417 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] Setting Misc Reg. Operand %i "
418 "being set to %#x.\n", threadNumber
, seqNum
, idx
, val
);
422 InOrderDynInst::readRegOtherThread(unsigned reg_idx
, ThreadID tid
)
425 tid
= TheISA::getTargetThread(this->cpu
->tcBase(threadNumber
));
428 if (reg_idx
< FP_Base_DepTag
) { // Integer Register File
429 return this->cpu
->readIntReg(reg_idx
, tid
);
430 } else if (reg_idx
< Ctrl_Base_DepTag
) { // Float Register File
431 reg_idx
-= FP_Base_DepTag
;
432 return this->cpu
->readFloatRegBits(reg_idx
, tid
);
434 reg_idx
-= Ctrl_Base_DepTag
;
435 return this->cpu
->readMiscReg(reg_idx
, tid
); // Misc. Register File
439 /** Sets a Integer register. */
441 InOrderDynInst::setIntRegOperand(const StaticInst
*si
, int idx
, IntReg val
)
443 instResult
[idx
].type
= Integer
;
444 instResult
[idx
].val
.integer
= val
;
445 instResult
[idx
].tick
= curTick();
447 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] Setting Result Int Reg. %i "
448 "being set to %#x (result-tick:%i).\n",
449 threadNumber
, seqNum
, idx
, val
, instResult
[idx
].tick
);
452 /** Sets a FP register. */
454 InOrderDynInst::setFloatRegOperand(const StaticInst
*si
, int idx
, FloatReg val
)
456 instResult
[idx
].val
.dbl
= val
;
457 instResult
[idx
].type
= Float
;
458 instResult
[idx
].tick
= curTick();
460 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] Setting Result Float Reg. %i "
461 "being set to %#x (result-tick:%i).\n",
462 threadNumber
, seqNum
, idx
, val
, instResult
[idx
].tick
);
465 /** Sets a FP register as a integer. */
467 InOrderDynInst::setFloatRegOperandBits(const StaticInst
*si
, int idx
,
470 instResult
[idx
].type
= Integer
;
471 instResult
[idx
].val
.integer
= val
;
472 instResult
[idx
].tick
= curTick();
474 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] Setting Result Float Reg. %i "
475 "being set to %#x (result-tick:%i).\n",
476 threadNumber
, seqNum
, idx
, val
, instResult
[idx
].tick
);
479 /** Sets a misc. register, including any side-effects the write
480 * might have as defined by the architecture.
482 /* Alter this if/when wanting to *speculate* on Miscellaneous registers */
484 InOrderDynInst::setMiscReg(int misc_reg
, const MiscReg
&val
)
486 this->cpu
->setMiscReg(misc_reg
, val
, threadNumber
);
490 InOrderDynInst::setRegOtherThread(unsigned reg_idx
, const MiscReg
&val
,
493 if (tid
== InvalidThreadID
) {
494 tid
= TheISA::getTargetThread(this->cpu
->tcBase(threadNumber
));
497 if (reg_idx
< FP_Base_DepTag
) { // Integer Register File
498 this->cpu
->setIntReg(reg_idx
, val
, tid
);
499 } else if (reg_idx
< Ctrl_Base_DepTag
) { // Float Register File
500 reg_idx
-= FP_Base_DepTag
;
501 this->cpu
->setFloatRegBits(reg_idx
, val
, tid
);
503 reg_idx
-= Ctrl_Base_DepTag
;
504 this->cpu
->setMiscReg(reg_idx
, val
, tid
); // Misc. Register File
509 InOrderDynInst::deallocateContext(int thread_num
)
511 this->cpu
->deallocateContext(thread_num
);
515 InOrderDynInst::readBytes(Addr addr
, uint8_t *data
,
516 unsigned size
, unsigned flags
)
518 return cpu
->read(this, addr
, data
, size
, flags
);
523 InOrderDynInst::read(Addr addr
, T
&data
, unsigned flags
)
526 traceData
->setAddr(addr
);
527 traceData
->setData(data
);
529 Fault fault
= readBytes(addr
, (uint8_t *)&data
, sizeof(T
), flags
);
530 data
= TheISA::gtoh(data
);
532 traceData
->setData(data
);
536 #ifndef DOXYGEN_SHOULD_SKIP_THIS
540 InOrderDynInst::read(Addr addr
, Twin32_t
&data
, unsigned flags
);
544 InOrderDynInst::read(Addr addr
, Twin64_t
&data
, unsigned flags
);
548 InOrderDynInst::read(Addr addr
, uint64_t &data
, unsigned flags
);
552 InOrderDynInst::read(Addr addr
, uint32_t &data
, unsigned flags
);
556 InOrderDynInst::read(Addr addr
, uint16_t &data
, unsigned flags
);
560 InOrderDynInst::read(Addr addr
, uint8_t &data
, unsigned flags
);
562 #endif //DOXYGEN_SHOULD_SKIP_THIS
566 InOrderDynInst::read(Addr addr
, double &data
, unsigned flags
)
568 return read(addr
, *(uint64_t*)&data
, flags
);
573 InOrderDynInst::read(Addr addr
, float &data
, unsigned flags
)
575 return read(addr
, *(uint32_t*)&data
, flags
);
580 InOrderDynInst::read(Addr addr
, int32_t &data
, unsigned flags
)
582 return read(addr
, (uint32_t&)data
, flags
);
586 InOrderDynInst::writeBytes(uint8_t *data
, unsigned size
,
587 Addr addr
, unsigned flags
, uint64_t *res
)
589 assert(sizeof(storeData
) >= size
);
590 memcpy(&storeData
, data
, size
);
591 return cpu
->write(this, (uint8_t *)&storeData
, size
, addr
, flags
, res
);
596 InOrderDynInst::write(T data
, Addr addr
, unsigned flags
, uint64_t *res
)
600 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] Setting store data to %#x.\n",
601 threadNumber
, seqNum
, storeData
);
603 traceData
->setAddr(addr
);
604 traceData
->setData(data
);
606 storeData
= TheISA::htog(data
);
607 return writeBytes((uint8_t*)&data
, sizeof(T
), addr
, flags
, res
);
610 #ifndef DOXYGEN_SHOULD_SKIP_THIS
614 InOrderDynInst::write(Twin32_t data
, Addr addr
,
615 unsigned flags
, uint64_t *res
);
619 InOrderDynInst::write(Twin64_t data
, Addr addr
,
620 unsigned flags
, uint64_t *res
);
623 InOrderDynInst::write(uint64_t data
, Addr addr
,
624 unsigned flags
, uint64_t *res
);
628 InOrderDynInst::write(uint32_t data
, Addr addr
,
629 unsigned flags
, uint64_t *res
);
633 InOrderDynInst::write(uint16_t data
, Addr addr
,
634 unsigned flags
, uint64_t *res
);
638 InOrderDynInst::write(uint8_t data
, Addr addr
,
639 unsigned flags
, uint64_t *res
);
641 #endif //DOXYGEN_SHOULD_SKIP_THIS
645 InOrderDynInst::write(double data
, Addr addr
, unsigned flags
, uint64_t *res
)
647 return write(*(uint64_t*)&data
, addr
, flags
, res
);
652 InOrderDynInst::write(float data
, Addr addr
, unsigned flags
, uint64_t *res
)
654 return write(*(uint32_t*)&data
, addr
, flags
, res
);
660 InOrderDynInst::write(int32_t data
, Addr addr
, unsigned flags
, uint64_t *res
)
662 return write((uint32_t)data
, addr
, flags
, res
);
667 InOrderDynInst::dump()
669 cprintf("T%d : %#08d `", threadNumber
, pc
.instAddr());
670 cout
<< staticInst
->disassemble(pc
.instAddr());
675 InOrderDynInst::dump(std::string
&outstring
)
677 std::ostringstream s
;
678 s
<< "T" << threadNumber
<< " : " << pc
<< " "
679 << staticInst
->disassemble(pc
.instAddr());
688 #include "base/hashmap.hh"
690 unsigned int MyHashFunc(const InOrderDynInst
*addr
)
692 unsigned a
= (unsigned)addr
;
693 unsigned hash
= (((a
>> 14) ^ ((a
>> 2) & 0xffff))) & 0x7FFFFFFF;
698 typedef m5::hash_map
<const InOrderDynInst
*, const InOrderDynInst
*,