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;
128 nextInstStageNum
= 0;
130 for(int i
= 0; i
< MaxInstDestRegs
; i
++)
131 instResult
[i
].val
.integer
= 0;
135 memAddrReady
= false;
139 predictTaken
= false;
140 procDelaySlotOnMispred
= false;
145 // Also make this a parameter, or perhaps get it from xc or cpu.
150 // Initialize the fault to be NoFault.
153 // Make sure to have the renamed register entries set to the same
154 // as the normal register entries. It will allow the IQ to work
155 // without any modifications.
156 if (this->staticInst
) {
157 for (int i
= 0; i
< this->staticInst
->numDestRegs(); i
++) {
158 _destRegIdx
[i
] = this->staticInst
->destRegIdx(i
);
161 for (int i
= 0; i
< this->staticInst
->numSrcRegs(); i
++) {
162 _srcRegIdx
[i
] = this->staticInst
->srcRegIdx(i
);
163 this->_readySrcRegIdx
[i
] = 0;
167 // Update Instruction Count for this instruction
169 if (instcount
> 100) {
170 fatal("Number of Active Instructions in CPU is too high. "
171 "(Not Dereferencing Ptrs. Correctly?)\n");
176 DPRINTF(InOrderDynInst
, "DynInst: [tid:%i] [sn:%lli] Instruction created."
177 " (active insts: %i)\n", threadNumber
, seqNum
, instcount
);
181 InOrderDynInst::resetInstCount()
187 InOrderDynInst::~InOrderDynInst()
189 if (fetchMemReq
!= 0x0) {
194 if (dataMemReq
!= 0x0) {
204 delete [] splitMemData
;
213 DPRINTF(InOrderDynInst
, "DynInst: [tid:%i] [sn:%lli] Instruction destroyed"
214 " (active insts: %i)\n", threadNumber
, seqNum
, instcount
);
218 InOrderDynInst::setStaticInst(StaticInstPtr
&static_inst
)
220 this->staticInst
= static_inst
;
222 // Make sure to have the renamed register entries set to the same
223 // as the normal register entries. It will allow the IQ to work
224 // without any modifications.
225 if (this->staticInst
) {
226 for (int i
= 0; i
< this->staticInst
->numDestRegs(); i
++) {
227 _destRegIdx
[i
] = this->staticInst
->destRegIdx(i
);
230 for (int i
= 0; i
< this->staticInst
->numSrcRegs(); i
++) {
231 _srcRegIdx
[i
] = this->staticInst
->srcRegIdx(i
);
232 this->_readySrcRegIdx
[i
] = 0;
238 InOrderDynInst::execute()
240 // @todo: Pretty convoluted way to avoid squashing from happening
241 // when using the TC during an instruction's execution
242 // (specifically for instructions that have side-effects that use
243 // the TC). Fix this.
244 bool in_syscall
= this->thread
->inSyscall
;
245 this->thread
->inSyscall
= true;
247 this->fault
= this->staticInst
->execute(this, this->traceData
);
249 this->thread
->inSyscall
= in_syscall
;
255 InOrderDynInst::calcEA()
257 this->fault
= this->staticInst
->eaComp(this, this->traceData
);
262 InOrderDynInst::initiateAcc()
264 // @todo: Pretty convoluted way to avoid squashing from happening
265 // when using the TC during an instruction's execution
266 // (specifically for instructions that have side-effects that use
267 // the TC). Fix this.
268 bool in_syscall
= this->thread
->inSyscall
;
269 this->thread
->inSyscall
= true;
271 this->fault
= this->staticInst
->initiateAcc(this, this->traceData
);
273 this->thread
->inSyscall
= in_syscall
;
280 InOrderDynInst::completeAcc(Packet
*pkt
)
282 this->fault
= this->staticInst
->completeAcc(pkt
, this, this->traceData
);
287 InstStage
*InOrderDynInst::addStage()
289 this->currentInstStage
= new InstStage(this, nextInstStageNum
++);
290 instStageList
.push_back( this->currentInstStage
);
291 return this->currentInstStage
;
294 InstStage
*InOrderDynInst::addStage(int stage_num
)
296 nextInstStageNum
= stage_num
;
297 return InOrderDynInst::addStage();
300 void InOrderDynInst::deleteStages() {
301 std::list
<InstStage
*>::iterator list_it
= instStageList
.begin();
302 std::list
<InstStage
*>::iterator list_end
= instStageList
.end();
304 while(list_it
!= list_end
) {
311 InOrderDynInst::memAccess()
313 return initiateAcc();
320 InOrderDynInst::hwrei()
322 panic("InOrderDynInst: hwrei: unimplemented\n");
328 InOrderDynInst::trap(Fault fault
)
330 this->cpu
->trap(fault
, this->threadNumber
, this);
335 InOrderDynInst::simPalCheck(int palFunc
)
337 #if THE_ISA != ALPHA_ISA
338 panic("simPalCheck called, but PAL only exists in Alpha!\n");
340 return this->cpu
->simPalCheck(palFunc
, this->threadNumber
);
344 InOrderDynInst::syscall(int64_t callnum
)
346 cpu
->syscall(callnum
, this->threadNumber
);
351 InOrderDynInst::releaseReq(ResourceRequest
* req
)
353 std::list
<ResourceRequest
*>::iterator list_it
= reqList
.begin();
354 std::list
<ResourceRequest
*>::iterator list_end
= reqList
.end();
356 while(list_it
!= list_end
) {
357 if((*list_it
)->getResIdx() == req
->getResIdx() &&
358 (*list_it
)->getSlot() == req
->getSlot()) {
359 DPRINTF(InOrderDynInst
, "[tid:%u]: [sn:%i] Done with request "
360 "to %s.\n", threadNumber
, seqNum
, req
->res
->name());
361 reqList
.erase(list_it
);
367 panic("Releasing Res. Request That Isnt There!\n");
370 /** Records an integer source register being set to a value. */
372 InOrderDynInst::setIntSrc(int idx
, uint64_t val
)
374 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] Source Value %i being set "
375 "to %#x.\n", threadNumber
, seqNum
, idx
, val
);
376 instSrc
[idx
].integer
= val
;
379 /** Records an fp register being set to a value. */
381 InOrderDynInst::setFloatSrc(int idx
, FloatReg val
)
383 instSrc
[idx
].dbl
= val
;
386 /** Records an fp register being set to an integer value. */
388 InOrderDynInst::setFloatRegBitsSrc(int idx
, uint64_t val
)
390 instSrc
[idx
].integer
= val
;
393 /** Reads a integer register. */
395 InOrderDynInst::readIntRegOperand(const StaticInst
*si
, int idx
, ThreadID tid
)
397 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] Source Value %i read as %#x.\n",
398 threadNumber
, seqNum
, idx
, instSrc
[idx
].integer
);
399 return instSrc
[idx
].integer
;
402 /** Reads a FP register. */
404 InOrderDynInst::readFloatRegOperand(const StaticInst
*si
, int idx
)
406 return instSrc
[idx
].dbl
;
410 /** Reads a FP register as a integer. */
412 InOrderDynInst::readFloatRegOperandBits(const StaticInst
*si
, int idx
)
414 return instSrc
[idx
].integer
;
417 /** Reads a miscellaneous register. */
419 InOrderDynInst::readMiscReg(int misc_reg
)
421 return this->cpu
->readMiscReg(misc_reg
, threadNumber
);
425 /** Reads a misc. register, including any side-effects the read
426 * might have as defined by the architecture.
429 InOrderDynInst::readMiscRegOperand(const StaticInst
*si
, int idx
)
431 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] Misc. Reg Source Value %i"
432 " read as %#x.\n", threadNumber
, seqNum
, idx
,
433 instSrc
[idx
].integer
);
434 return instSrc
[idx
].integer
;
438 /** Sets a misc. register, including any side-effects the write
439 * might have as defined by the architecture.
442 InOrderDynInst::setMiscRegOperand(const StaticInst
*si
, int idx
,
445 instResult
[idx
].type
= Integer
;
446 instResult
[idx
].val
.integer
= val
;
447 instResult
[idx
].tick
= curTick();
449 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] Setting Misc Reg. Operand %i "
450 "being set to %#x.\n", threadNumber
, seqNum
, idx
, val
);
454 InOrderDynInst::readRegOtherThread(unsigned reg_idx
, ThreadID tid
)
457 tid
= TheISA::getTargetThread(this->cpu
->tcBase(threadNumber
));
460 if (reg_idx
< FP_Base_DepTag
) { // Integer Register File
461 return this->cpu
->readIntReg(reg_idx
, tid
);
462 } else if (reg_idx
< Ctrl_Base_DepTag
) { // Float Register File
463 reg_idx
-= FP_Base_DepTag
;
464 return this->cpu
->readFloatRegBits(reg_idx
, tid
);
466 reg_idx
-= Ctrl_Base_DepTag
;
467 return this->cpu
->readMiscReg(reg_idx
, tid
); // Misc. Register File
471 /** Sets a Integer register. */
473 InOrderDynInst::setIntRegOperand(const StaticInst
*si
, int idx
, IntReg val
)
475 instResult
[idx
].type
= Integer
;
476 instResult
[idx
].val
.integer
= val
;
477 instResult
[idx
].tick
= curTick();
479 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] Setting Result Int Reg. %i "
480 "being set to %#x (result-tick:%i).\n",
481 threadNumber
, seqNum
, idx
, val
, instResult
[idx
].tick
);
484 /** Sets a FP register. */
486 InOrderDynInst::setFloatRegOperand(const StaticInst
*si
, int idx
, FloatReg val
)
488 instResult
[idx
].val
.dbl
= val
;
489 instResult
[idx
].type
= Float
;
490 instResult
[idx
].tick
= curTick();
492 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] Setting Result Float Reg. %i "
493 "being set to %#x (result-tick:%i).\n",
494 threadNumber
, seqNum
, idx
, val
, instResult
[idx
].tick
);
497 /** Sets a FP register as a integer. */
499 InOrderDynInst::setFloatRegOperandBits(const StaticInst
*si
, int idx
,
502 instResult
[idx
].type
= Integer
;
503 instResult
[idx
].val
.integer
= val
;
504 instResult
[idx
].tick
= curTick();
506 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] Setting Result Float Reg. %i "
507 "being set to %#x (result-tick:%i).\n",
508 threadNumber
, seqNum
, idx
, val
, instResult
[idx
].tick
);
511 /** Sets a misc. register, including any side-effects the write
512 * might have as defined by the architecture.
514 /* Alter this if/when wanting to *speculate* on Miscellaneous registers */
516 InOrderDynInst::setMiscReg(int misc_reg
, const MiscReg
&val
)
518 this->cpu
->setMiscReg(misc_reg
, val
, threadNumber
);
522 InOrderDynInst::setRegOtherThread(unsigned reg_idx
, const MiscReg
&val
,
525 if (tid
== InvalidThreadID
) {
526 tid
= TheISA::getTargetThread(this->cpu
->tcBase(threadNumber
));
529 if (reg_idx
< FP_Base_DepTag
) { // Integer Register File
530 this->cpu
->setIntReg(reg_idx
, val
, tid
);
531 } else if (reg_idx
< Ctrl_Base_DepTag
) { // Float Register File
532 reg_idx
-= FP_Base_DepTag
;
533 this->cpu
->setFloatRegBits(reg_idx
, val
, tid
);
535 reg_idx
-= Ctrl_Base_DepTag
;
536 this->cpu
->setMiscReg(reg_idx
, val
, tid
); // Misc. Register File
541 InOrderDynInst::deallocateContext(int thread_num
)
543 this->cpu
->deallocateContext(thread_num
);
547 InOrderDynInst::readBytes(Addr addr
, uint8_t *data
,
548 unsigned size
, unsigned flags
)
550 return cpu
->read(this, addr
, data
, size
, flags
);
555 InOrderDynInst::read(Addr addr
, T
&data
, unsigned flags
)
558 traceData
->setAddr(addr
);
559 traceData
->setData(data
);
561 Fault fault
= readBytes(addr
, (uint8_t *)&data
, sizeof(T
), flags
);
562 data
= TheISA::gtoh(data
);
564 traceData
->setData(data
);
568 #ifndef DOXYGEN_SHOULD_SKIP_THIS
572 InOrderDynInst::read(Addr addr
, uint64_t &data
, unsigned flags
);
576 InOrderDynInst::read(Addr addr
, uint32_t &data
, unsigned flags
);
580 InOrderDynInst::read(Addr addr
, uint16_t &data
, unsigned flags
);
584 InOrderDynInst::read(Addr addr
, uint8_t &data
, unsigned flags
);
586 #endif //DOXYGEN_SHOULD_SKIP_THIS
590 InOrderDynInst::read(Addr addr
, double &data
, unsigned flags
)
592 return read(addr
, *(uint64_t*)&data
, flags
);
597 InOrderDynInst::read(Addr addr
, float &data
, unsigned flags
)
599 return read(addr
, *(uint32_t*)&data
, flags
);
604 InOrderDynInst::read(Addr addr
, int32_t &data
, unsigned flags
)
606 return read(addr
, (uint32_t&)data
, flags
);
610 InOrderDynInst::writeBytes(uint8_t *data
, unsigned size
,
611 Addr addr
, unsigned flags
, uint64_t *res
)
613 assert(sizeof(storeData
) >= size
);
614 memcpy(&storeData
, data
, size
);
615 return cpu
->write(this, (uint8_t *)&storeData
, size
, addr
, flags
, res
);
620 InOrderDynInst::write(T data
, Addr addr
, unsigned flags
, uint64_t *res
)
624 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] Setting store data to %#x.\n",
625 threadNumber
, seqNum
, storeData
);
627 traceData
->setAddr(addr
);
628 traceData
->setData(data
);
630 storeData
= TheISA::htog(data
);
631 return writeBytes((uint8_t*)&data
, sizeof(T
), addr
, flags
, res
);
634 #ifndef DOXYGEN_SHOULD_SKIP_THIS
637 InOrderDynInst::write(uint64_t data
, Addr addr
,
638 unsigned flags
, uint64_t *res
);
642 InOrderDynInst::write(uint32_t data
, Addr addr
,
643 unsigned flags
, uint64_t *res
);
647 InOrderDynInst::write(uint16_t data
, Addr addr
,
648 unsigned flags
, uint64_t *res
);
652 InOrderDynInst::write(uint8_t data
, Addr addr
,
653 unsigned flags
, uint64_t *res
);
655 #endif //DOXYGEN_SHOULD_SKIP_THIS
659 InOrderDynInst::write(double data
, Addr addr
, unsigned flags
, uint64_t *res
)
661 return write(*(uint64_t*)&data
, addr
, flags
, res
);
666 InOrderDynInst::write(float data
, Addr addr
, unsigned flags
, uint64_t *res
)
668 return write(*(uint32_t*)&data
, addr
, flags
, res
);
674 InOrderDynInst::write(int32_t data
, Addr addr
, unsigned flags
, uint64_t *res
)
676 return write((uint32_t)data
, addr
, flags
, res
);
681 InOrderDynInst::dump()
683 cprintf("T%d : %#08d `", threadNumber
, pc
.instAddr());
684 cout
<< staticInst
->disassemble(pc
.instAddr());
689 InOrderDynInst::dump(std::string
&outstring
)
691 std::ostringstream s
;
692 s
<< "T" << threadNumber
<< " : " << pc
<< " "
693 << staticInst
->disassemble(pc
.instAddr());
702 #include "base/hashmap.hh"
704 unsigned int MyHashFunc(const InOrderDynInst
*addr
)
706 unsigned a
= (unsigned)addr
;
707 unsigned hash
= (((a
>> 14) ^ ((a
>> 2) & 0xffff))) & 0x7FFFFFFF;
712 typedef m5::hash_map
<const InOrderDynInst
*, const InOrderDynInst
*,