e9deb7625525bf84ea17dda5211d6d0d2e7b8501
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/exetrace.hh"
42 #include "cpu/inorder/cpu.hh"
43 #include "cpu/inorder/inorder_dyn_inst.hh"
44 #include "mem/request.hh"
47 using namespace TheISA
;
48 using namespace ThePipeline
;
50 InOrderDynInst::InOrderDynInst(TheISA::ExtMachInst machInst
,
51 const TheISA::PCState
&instPC
,
52 const TheISA::PCState
&_predPC
,
53 InstSeqNum seq_num
, InOrderCPU
*cpu
)
54 : staticInst(machInst
, instPC
.instAddr()), traceData(NULL
), cpu(cpu
)
64 InOrderDynInst::InOrderDynInst(InOrderCPU
*cpu
,
65 InOrderThreadState
*state
,
69 : traceData(NULL
), cpu(cpu
)
78 InOrderDynInst::InOrderDynInst(StaticInstPtr
&_staticInst
)
79 : seqNum(0), staticInst(_staticInst
), traceData(NULL
)
84 InOrderDynInst::InOrderDynInst()
85 : seqNum(0), traceData(NULL
), cpu(cpu
)
90 int InOrderDynInst::instcount
= 0;
94 InOrderDynInst::setMachInst(ExtMachInst machInst
)
96 staticInst
= StaticInst::decode(machInst
, pc
.instAddr());
98 for (int i
= 0; i
< this->staticInst
->numDestRegs(); i
++) {
99 _destRegIdx
[i
] = this->staticInst
->destRegIdx(i
);
102 for (int i
= 0; i
< this->staticInst
->numSrcRegs(); i
++) {
103 _srcRegIdx
[i
] = this->staticInst
->srcRegIdx(i
);
104 this->_readySrcRegIdx
[i
] = 0;
109 InOrderDynInst::initVars()
117 split2ndAccess
= false;
119 splitInstSked
= false;
129 for(int i
= 0; i
< MaxInstDestRegs
; i
++)
130 instResult
[i
].val
.integer
= 0;
134 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
168 if (instcount
> 100) {
169 fatal("Number of Active Instructions in CPU is too high. "
170 "(Not Dereferencing Ptrs. Correctly?)\n");
175 DPRINTF(InOrderDynInst
, "DynInst: [tid:%i] [sn:%lli] Instruction created."
176 " (active insts: %i)\n", threadNumber
, seqNum
, instcount
);
180 InOrderDynInst::resetInstCount()
186 InOrderDynInst::~InOrderDynInst()
188 if (fetchMemReq
!= 0x0) {
193 if (dataMemReq
!= 0x0) {
203 delete [] splitMemData
;
210 DPRINTF(InOrderDynInst
, "DynInst: [tid:%i] [sn:%lli] Instruction destroyed"
211 " (active insts: %i)\n", threadNumber
, seqNum
, instcount
);
215 InOrderDynInst::setStaticInst(StaticInstPtr
&static_inst
)
217 this->staticInst
= static_inst
;
219 // Make sure to have the renamed register entries set to the same
220 // as the normal register entries. It will allow the IQ to work
221 // without any modifications.
222 if (this->staticInst
) {
223 for (int i
= 0; i
< this->staticInst
->numDestRegs(); i
++) {
224 _destRegIdx
[i
] = this->staticInst
->destRegIdx(i
);
227 for (int i
= 0; i
< this->staticInst
->numSrcRegs(); i
++) {
228 _srcRegIdx
[i
] = this->staticInst
->srcRegIdx(i
);
229 this->_readySrcRegIdx
[i
] = 0;
235 InOrderDynInst::execute()
237 // @todo: Pretty convoluted way to avoid squashing from happening
238 // when using the TC during an instruction's execution
239 // (specifically for instructions that have side-effects that use
240 // the TC). Fix this.
241 bool in_syscall
= this->thread
->inSyscall
;
242 this->thread
->inSyscall
= true;
244 this->fault
= this->staticInst
->execute(this, this->traceData
);
246 this->thread
->inSyscall
= in_syscall
;
252 InOrderDynInst::calcEA()
254 this->fault
= this->staticInst
->eaComp(this, this->traceData
);
259 InOrderDynInst::initiateAcc()
261 // @todo: Pretty convoluted way to avoid squashing from happening
262 // when using the TC during an instruction's execution
263 // (specifically for instructions that have side-effects that use
264 // the TC). Fix this.
265 bool in_syscall
= this->thread
->inSyscall
;
266 this->thread
->inSyscall
= true;
268 this->fault
= this->staticInst
->initiateAcc(this, this->traceData
);
270 this->thread
->inSyscall
= in_syscall
;
277 InOrderDynInst::completeAcc(Packet
*pkt
)
279 this->fault
= this->staticInst
->completeAcc(pkt
, this, this->traceData
);
285 InOrderDynInst::memAccess()
287 return initiateAcc();
294 InOrderDynInst::hwrei()
296 panic("InOrderDynInst: hwrei: unimplemented\n");
302 InOrderDynInst::trap(Fault fault
)
304 this->cpu
->trap(fault
, this->threadNumber
, this);
309 InOrderDynInst::simPalCheck(int palFunc
)
311 #if THE_ISA != ALPHA_ISA
312 panic("simPalCheck called, but PAL only exists in Alpha!\n");
314 return this->cpu
->simPalCheck(palFunc
, this->threadNumber
);
318 InOrderDynInst::syscall(int64_t callnum
)
320 cpu
->syscall(callnum
, this->threadNumber
);
325 InOrderDynInst::releaseReq(ResourceRequest
* req
)
327 std::list
<ResourceRequest
*>::iterator list_it
= reqList
.begin();
328 std::list
<ResourceRequest
*>::iterator list_end
= reqList
.end();
330 while(list_it
!= list_end
) {
331 if((*list_it
)->getResIdx() == req
->getResIdx() &&
332 (*list_it
)->getSlot() == req
->getSlot()) {
333 DPRINTF(InOrderDynInst
, "[tid:%u]: [sn:%i] Done with request "
334 "to %s.\n", threadNumber
, seqNum
, req
->res
->name());
335 reqList
.erase(list_it
);
341 panic("Releasing Res. Request That Isnt There!\n");
344 /** Records an integer source register being set to a value. */
346 InOrderDynInst::setIntSrc(int idx
, uint64_t val
)
348 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] Source Value %i being set "
349 "to %#x.\n", threadNumber
, seqNum
, idx
, val
);
350 instSrc
[idx
].integer
= val
;
353 /** Records an fp register being set to a value. */
355 InOrderDynInst::setFloatSrc(int idx
, FloatReg val
)
357 instSrc
[idx
].dbl
= val
;
360 /** Records an fp register being set to an integer value. */
362 InOrderDynInst::setFloatRegBitsSrc(int idx
, uint64_t val
)
364 instSrc
[idx
].integer
= val
;
367 /** Reads a integer register. */
369 InOrderDynInst::readIntRegOperand(const StaticInst
*si
, int idx
, ThreadID tid
)
371 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] Source Value %i read as %#x.\n",
372 threadNumber
, seqNum
, idx
, instSrc
[idx
].integer
);
373 return instSrc
[idx
].integer
;
376 /** Reads a FP register. */
378 InOrderDynInst::readFloatRegOperand(const StaticInst
*si
, int idx
)
380 return instSrc
[idx
].dbl
;
384 /** Reads a FP register as a integer. */
386 InOrderDynInst::readFloatRegOperandBits(const StaticInst
*si
, int idx
)
388 return instSrc
[idx
].integer
;
391 /** Reads a miscellaneous register. */
393 InOrderDynInst::readMiscReg(int misc_reg
)
395 return this->cpu
->readMiscReg(misc_reg
, threadNumber
);
399 /** Reads a misc. register, including any side-effects the read
400 * might have as defined by the architecture.
403 InOrderDynInst::readMiscRegOperand(const StaticInst
*si
, int idx
)
405 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] Misc. Reg Source Value %i"
406 " read as %#x.\n", threadNumber
, seqNum
, idx
,
407 instSrc
[idx
].integer
);
408 return instSrc
[idx
].integer
;
412 /** Sets a misc. register, including any side-effects the write
413 * might have as defined by the architecture.
416 InOrderDynInst::setMiscRegOperand(const StaticInst
*si
, int idx
,
419 instResult
[idx
].type
= Integer
;
420 instResult
[idx
].val
.integer
= val
;
421 instResult
[idx
].tick
= curTick();
423 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] Setting Misc Reg. Operand %i "
424 "being set to %#x.\n", threadNumber
, seqNum
, idx
, val
);
428 InOrderDynInst::readRegOtherThread(unsigned reg_idx
, ThreadID tid
)
431 tid
= TheISA::getTargetThread(this->cpu
->tcBase(threadNumber
));
434 if (reg_idx
< FP_Base_DepTag
) { // Integer Register File
435 return this->cpu
->readIntReg(reg_idx
, tid
);
436 } else if (reg_idx
< Ctrl_Base_DepTag
) { // Float Register File
437 reg_idx
-= FP_Base_DepTag
;
438 return this->cpu
->readFloatRegBits(reg_idx
, tid
);
440 reg_idx
-= Ctrl_Base_DepTag
;
441 return this->cpu
->readMiscReg(reg_idx
, tid
); // Misc. Register File
445 /** Sets a Integer register. */
447 InOrderDynInst::setIntRegOperand(const StaticInst
*si
, int idx
, IntReg val
)
449 instResult
[idx
].type
= Integer
;
450 instResult
[idx
].val
.integer
= val
;
451 instResult
[idx
].tick
= curTick();
453 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] Setting Result Int Reg. %i "
454 "being set to %#x (result-tick:%i).\n",
455 threadNumber
, seqNum
, idx
, val
, instResult
[idx
].tick
);
458 /** Sets a FP register. */
460 InOrderDynInst::setFloatRegOperand(const StaticInst
*si
, int idx
, FloatReg val
)
462 instResult
[idx
].val
.dbl
= val
;
463 instResult
[idx
].type
= Float
;
464 instResult
[idx
].tick
= curTick();
466 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] Setting Result Float Reg. %i "
467 "being set to %#x (result-tick:%i).\n",
468 threadNumber
, seqNum
, idx
, val
, instResult
[idx
].tick
);
471 /** Sets a FP register as a integer. */
473 InOrderDynInst::setFloatRegOperandBits(const StaticInst
*si
, int idx
,
476 instResult
[idx
].type
= Integer
;
477 instResult
[idx
].val
.integer
= val
;
478 instResult
[idx
].tick
= curTick();
480 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] Setting Result Float Reg. %i "
481 "being set to %#x (result-tick:%i).\n",
482 threadNumber
, seqNum
, idx
, val
, instResult
[idx
].tick
);
485 /** Sets a misc. register, including any side-effects the write
486 * might have as defined by the architecture.
488 /* Alter this if/when wanting to *speculate* on Miscellaneous registers */
490 InOrderDynInst::setMiscReg(int misc_reg
, const MiscReg
&val
)
492 this->cpu
->setMiscReg(misc_reg
, val
, threadNumber
);
496 InOrderDynInst::setRegOtherThread(unsigned reg_idx
, const MiscReg
&val
,
499 if (tid
== InvalidThreadID
) {
500 tid
= TheISA::getTargetThread(this->cpu
->tcBase(threadNumber
));
503 if (reg_idx
< FP_Base_DepTag
) { // Integer Register File
504 this->cpu
->setIntReg(reg_idx
, val
, tid
);
505 } else if (reg_idx
< Ctrl_Base_DepTag
) { // Float Register File
506 reg_idx
-= FP_Base_DepTag
;
507 this->cpu
->setFloatRegBits(reg_idx
, val
, tid
);
509 reg_idx
-= Ctrl_Base_DepTag
;
510 this->cpu
->setMiscReg(reg_idx
, val
, tid
); // Misc. Register File
515 InOrderDynInst::deallocateContext(int thread_num
)
517 this->cpu
->deallocateContext(thread_num
);
521 InOrderDynInst::readBytes(Addr addr
, uint8_t *data
,
522 unsigned size
, unsigned flags
)
524 return cpu
->read(this, addr
, data
, size
, flags
);
529 InOrderDynInst::read(Addr addr
, T
&data
, unsigned flags
)
532 traceData
->setAddr(addr
);
533 traceData
->setData(data
);
535 Fault fault
= readBytes(addr
, (uint8_t *)&data
, sizeof(T
), flags
);
536 data
= TheISA::gtoh(data
);
538 traceData
->setData(data
);
542 #ifndef DOXYGEN_SHOULD_SKIP_THIS
546 InOrderDynInst::read(Addr addr
, uint64_t &data
, unsigned flags
);
550 InOrderDynInst::read(Addr addr
, uint32_t &data
, unsigned flags
);
554 InOrderDynInst::read(Addr addr
, uint16_t &data
, unsigned flags
);
558 InOrderDynInst::read(Addr addr
, uint8_t &data
, unsigned flags
);
560 #endif //DOXYGEN_SHOULD_SKIP_THIS
564 InOrderDynInst::read(Addr addr
, double &data
, unsigned flags
)
566 return read(addr
, *(uint64_t*)&data
, flags
);
571 InOrderDynInst::read(Addr addr
, float &data
, unsigned flags
)
573 return read(addr
, *(uint32_t*)&data
, flags
);
578 InOrderDynInst::read(Addr addr
, int32_t &data
, unsigned flags
)
580 return read(addr
, (uint32_t&)data
, flags
);
584 InOrderDynInst::writeBytes(uint8_t *data
, unsigned size
,
585 Addr addr
, unsigned flags
, uint64_t *res
)
587 assert(sizeof(storeData
) >= size
);
588 memcpy(&storeData
, data
, size
);
589 return cpu
->write(this, (uint8_t *)&storeData
, size
, addr
, flags
, res
);
594 InOrderDynInst::write(T data
, Addr addr
, unsigned flags
, uint64_t *res
)
598 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] Setting store data to %#x.\n",
599 threadNumber
, seqNum
, storeData
);
601 traceData
->setAddr(addr
);
602 traceData
->setData(data
);
604 storeData
= TheISA::htog(data
);
605 return writeBytes((uint8_t*)&data
, sizeof(T
), addr
, flags
, res
);
608 #ifndef DOXYGEN_SHOULD_SKIP_THIS
611 InOrderDynInst::write(uint64_t data
, Addr addr
,
612 unsigned flags
, uint64_t *res
);
616 InOrderDynInst::write(uint32_t data
, Addr addr
,
617 unsigned flags
, uint64_t *res
);
621 InOrderDynInst::write(uint16_t data
, Addr addr
,
622 unsigned flags
, uint64_t *res
);
626 InOrderDynInst::write(uint8_t data
, Addr addr
,
627 unsigned flags
, uint64_t *res
);
629 #endif //DOXYGEN_SHOULD_SKIP_THIS
633 InOrderDynInst::write(double data
, Addr addr
, unsigned flags
, uint64_t *res
)
635 return write(*(uint64_t*)&data
, addr
, flags
, res
);
640 InOrderDynInst::write(float data
, Addr addr
, unsigned flags
, uint64_t *res
)
642 return write(*(uint32_t*)&data
, addr
, flags
, res
);
648 InOrderDynInst::write(int32_t data
, Addr addr
, unsigned flags
, uint64_t *res
)
650 return write((uint32_t)data
, addr
, flags
, res
);
655 InOrderDynInst::dump()
657 cprintf("T%d : %#08d `", threadNumber
, pc
.instAddr());
658 cout
<< staticInst
->disassemble(pc
.instAddr());
663 InOrderDynInst::dump(std::string
&outstring
)
665 std::ostringstream s
;
666 s
<< "T" << threadNumber
<< " : " << pc
<< " "
667 << staticInst
->disassemble(pc
.instAddr());
676 #include "base/hashmap.hh"
678 unsigned int MyHashFunc(const InOrderDynInst
*addr
)
680 unsigned a
= (unsigned)addr
;
681 unsigned hash
= (((a
>> 14) ^ ((a
>> 2) & 0xffff))) & 0x7FFFFFFF;
686 typedef m5::hash_map
<const InOrderDynInst
*, const InOrderDynInst
*,