13ec7a3fff325bffd81cab5f975a98deb68bf86f
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
, Addr inst_PC
,
51 Addr pred_PC
, InstSeqNum seq_num
,
53 : staticInst(machInst
, inst_PC
), traceData(NULL
), cpu(cpu
)
58 nextPC
= PC
+ sizeof(MachInst
);
59 nextNPC
= nextPC
+ sizeof(MachInst
);
65 InOrderDynInst::InOrderDynInst(InOrderCPU
*cpu
,
66 InOrderThreadState
*state
,
70 : traceData(NULL
), cpu(cpu
)
79 InOrderDynInst::InOrderDynInst(StaticInstPtr
&_staticInst
)
80 : seqNum(0), staticInst(_staticInst
), traceData(NULL
)
85 InOrderDynInst::InOrderDynInst()
86 : seqNum(0), traceData(NULL
), cpu(cpu
)
91 int InOrderDynInst::instcount
= 0;
95 InOrderDynInst::setMachInst(ExtMachInst machInst
)
97 staticInst
= StaticInst::decode(machInst
, PC
);
99 for (int i
= 0; i
< this->staticInst
->numDestRegs(); i
++) {
100 _destRegIdx
[i
] = this->staticInst
->destRegIdx(i
);
103 for (int i
= 0; i
< this->staticInst
->numSrcRegs(); i
++) {
104 _srcRegIdx
[i
] = this->staticInst
->srcRegIdx(i
);
105 this->_readySrcRegIdx
[i
] = 0;
110 InOrderDynInst::initVars()
116 split2ndAccess
= false;
118 splitInstSked
= false;
127 nextInstStageNum
= 0;
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
;
212 DPRINTF(InOrderDynInst
, "DynInst: [tid:%i] [sn:%lli] Instruction destroyed"
213 " (active insts: %i)\n", threadNumber
, seqNum
, instcount
);
217 InOrderDynInst::setStaticInst(StaticInstPtr
&static_inst
)
219 this->staticInst
= static_inst
;
221 // Make sure to have the renamed register entries set to the same
222 // as the normal register entries. It will allow the IQ to work
223 // without any modifications.
224 if (this->staticInst
) {
225 for (int i
= 0; i
< this->staticInst
->numDestRegs(); i
++) {
226 _destRegIdx
[i
] = this->staticInst
->destRegIdx(i
);
229 for (int i
= 0; i
< this->staticInst
->numSrcRegs(); i
++) {
230 _srcRegIdx
[i
] = this->staticInst
->srcRegIdx(i
);
231 this->_readySrcRegIdx
[i
] = 0;
237 InOrderDynInst::execute()
239 // @todo: Pretty convoluted way to avoid squashing from happening
240 // when using the TC during an instruction's execution
241 // (specifically for instructions that have side-effects that use
242 // the TC). Fix this.
243 bool in_syscall
= this->thread
->inSyscall
;
244 this->thread
->inSyscall
= true;
246 this->fault
= this->staticInst
->execute(this, this->traceData
);
248 this->thread
->inSyscall
= in_syscall
;
254 InOrderDynInst::calcEA()
256 this->fault
= this->staticInst
->eaComp(this, this->traceData
);
261 InOrderDynInst::initiateAcc()
263 // @todo: Pretty convoluted way to avoid squashing from happening
264 // when using the TC during an instruction's execution
265 // (specifically for instructions that have side-effects that use
266 // the TC). Fix this.
267 bool in_syscall
= this->thread
->inSyscall
;
268 this->thread
->inSyscall
= true;
270 this->fault
= this->staticInst
->initiateAcc(this, this->traceData
);
272 this->thread
->inSyscall
= in_syscall
;
279 InOrderDynInst::completeAcc(Packet
*pkt
)
281 this->fault
= this->staticInst
->completeAcc(pkt
, this, this->traceData
);
286 InstStage
*InOrderDynInst::addStage()
288 this->currentInstStage
= new InstStage(this, nextInstStageNum
++);
289 instStageList
.push_back( this->currentInstStage
);
290 return this->currentInstStage
;
293 InstStage
*InOrderDynInst::addStage(int stage_num
)
295 nextInstStageNum
= stage_num
;
296 return InOrderDynInst::addStage();
299 void InOrderDynInst::deleteStages() {
300 std::list
<InstStage
*>::iterator list_it
= instStageList
.begin();
301 std::list
<InstStage
*>::iterator list_end
= instStageList
.end();
303 while(list_it
!= list_end
) {
310 InOrderDynInst::memAccess()
312 return initiateAcc();
319 InOrderDynInst::hwrei()
321 panic("InOrderDynInst: hwrei: unimplemented\n");
327 InOrderDynInst::trap(Fault fault
)
329 this->cpu
->trap(fault
, this->threadNumber
);
334 InOrderDynInst::simPalCheck(int palFunc
)
336 #if THE_ISA != ALPHA_ISA
337 panic("simPalCheck called, but PAL only exists in Alpha!\n");
339 return this->cpu
->simPalCheck(palFunc
, this->threadNumber
);
343 InOrderDynInst::syscall(int64_t callnum
)
345 cpu
->syscall(callnum
, this->threadNumber
);
350 InOrderDynInst::prefetch(Addr addr
, unsigned flags
)
356 InOrderDynInst::writeHint(Addr addr
, int size
, unsigned flags
)
358 cpu
->writeHint(this);
362 * @todo Need to find a way to get the cache block size here.
365 InOrderDynInst::copySrcTranslate(Addr src
)
367 // Not currently supported.
372 * @todo Need to find a way to get the cache block size here.
375 InOrderDynInst::copy(Addr dest
)
377 // Not currently supported.
382 InOrderDynInst::releaseReq(ResourceRequest
* req
)
384 std::list
<ResourceRequest
*>::iterator list_it
= reqList
.begin();
385 std::list
<ResourceRequest
*>::iterator list_end
= reqList
.end();
387 while(list_it
!= list_end
) {
388 if((*list_it
)->getResIdx() == req
->getResIdx() &&
389 (*list_it
)->getSlot() == req
->getSlot()) {
390 DPRINTF(InOrderDynInst
, "[tid:%u]: [sn:%i] Done with request "
391 "to %s.\n", threadNumber
, seqNum
, req
->res
->name());
392 reqList
.erase(list_it
);
398 panic("Releasing Res. Request That Isnt There!\n");
401 /** Records an integer source register being set to a value. */
403 InOrderDynInst::setIntSrc(int idx
, uint64_t val
)
405 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] Source Value %i being set "
406 "to %#x.\n", threadNumber
, seqNum
, idx
, val
);
407 instSrc
[idx
].integer
= val
;
410 /** Records an fp register being set to a value. */
412 InOrderDynInst::setFloatSrc(int idx
, FloatReg val
)
414 instSrc
[idx
].dbl
= val
;
417 /** Records an fp register being set to an integer value. */
419 InOrderDynInst::setFloatRegBitsSrc(int idx
, uint64_t val
)
421 instSrc
[idx
].integer
= val
;
424 /** Reads a integer register. */
426 InOrderDynInst::readIntRegOperand(const StaticInst
*si
, int idx
, ThreadID tid
)
428 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] Source Value %i read as %#x.\n",
429 threadNumber
, seqNum
, idx
, instSrc
[idx
].integer
);
430 return instSrc
[idx
].integer
;
433 /** Reads a FP register. */
435 InOrderDynInst::readFloatRegOperand(const StaticInst
*si
, int idx
)
437 return instSrc
[idx
].dbl
;
441 /** Reads a FP register as a integer. */
443 InOrderDynInst::readFloatRegOperandBits(const StaticInst
*si
, int idx
)
445 return instSrc
[idx
].integer
;
448 /** Reads a miscellaneous register. */
450 InOrderDynInst::readMiscReg(int misc_reg
)
452 return this->cpu
->readMiscReg(misc_reg
, threadNumber
);
455 /** Reads a misc. register, including any side-effects the read
456 * might have as defined by the architecture.
459 InOrderDynInst::readMiscRegNoEffect(int misc_reg
)
461 return this->cpu
->readMiscRegNoEffect(misc_reg
, threadNumber
);
464 /** Reads a miscellaneous register. */
466 InOrderDynInst::readMiscRegOperandNoEffect(const StaticInst
*si
, int idx
)
468 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] Misc. Reg Source Value %i"
469 " read as %#x.\n", threadNumber
, seqNum
, idx
,
470 instSrc
[idx
].integer
);
471 return instSrc
[idx
].integer
;
474 /** Reads a misc. register, including any side-effects the read
475 * might have as defined by the architecture.
478 InOrderDynInst::readMiscRegOperand(const StaticInst
*si
, int idx
)
480 // For In-Order, the side-effect of reading a register happens
481 // when explicitly executing a "ReadSrc" command. This simply returns
483 return readMiscRegOperandNoEffect(si
, idx
);
486 /** Sets a misc. register. */
488 InOrderDynInst::setMiscRegOperandNoEffect(const StaticInst
* si
, int idx
,
491 instResult
[idx
].type
= Integer
;
492 instResult
[idx
].val
.integer
= val
;
493 instResult
[idx
].tick
= curTick
;
495 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] Setting Misc Reg. Operand %i "
496 "being set to %#x.\n", threadNumber
, seqNum
, idx
, val
);
499 /** Sets a misc. register, including any side-effects the write
500 * might have as defined by the architecture.
503 InOrderDynInst::setMiscRegOperand(const StaticInst
*si
, int idx
,
506 // For In-Order, the side-effect of setting a register happens
507 // when explicitly writing back the register value. This
508 // simply maintains the operand value.
509 setMiscRegOperandNoEffect(si
, idx
, val
);
513 InOrderDynInst::readRegOtherThread(unsigned reg_idx
, ThreadID tid
)
516 tid
= TheISA::getTargetThread(this->cpu
->tcBase(threadNumber
));
519 if (reg_idx
< FP_Base_DepTag
) { // Integer Register File
520 return this->cpu
->readIntReg(reg_idx
, tid
);
521 } else if (reg_idx
< Ctrl_Base_DepTag
) { // Float Register File
522 reg_idx
-= FP_Base_DepTag
;
523 return this->cpu
->readFloatRegBits(reg_idx
, tid
);
525 reg_idx
-= Ctrl_Base_DepTag
;
526 return this->cpu
->readMiscReg(reg_idx
, tid
); // Misc. Register File
530 /** Sets a Integer register. */
532 InOrderDynInst::setIntRegOperand(const StaticInst
*si
, int idx
, IntReg val
)
534 instResult
[idx
].type
= Integer
;
535 instResult
[idx
].val
.integer
= val
;
536 instResult
[idx
].tick
= curTick
;
538 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] Setting Result Int Reg. %i "
539 "being set to %#x (result-tick:%i).\n",
540 threadNumber
, seqNum
, idx
, val
, instResult
[idx
].tick
);
543 /** Sets a FP register. */
545 InOrderDynInst::setFloatRegOperand(const StaticInst
*si
, int idx
, FloatReg val
)
547 instResult
[idx
].val
.dbl
= val
;
548 instResult
[idx
].type
= Float
;
549 instResult
[idx
].tick
= curTick
;
551 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] Setting Result Float Reg. %i "
552 "being set to %#x (result-tick:%i).\n",
553 threadNumber
, seqNum
, idx
, val
, instResult
[idx
].tick
);
556 /** Sets a FP register as a integer. */
558 InOrderDynInst::setFloatRegOperandBits(const StaticInst
*si
, int idx
,
561 instResult
[idx
].type
= Integer
;
562 instResult
[idx
].val
.integer
= val
;
563 instResult
[idx
].tick
= curTick
;
565 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] Setting Result Float Reg. %i "
566 "being set to %#x (result-tick:%i).\n",
567 threadNumber
, seqNum
, idx
, val
, instResult
[idx
].tick
);
570 /** Sets a misc. register. */
571 /* Alter this when wanting to *speculate* on Miscellaneous registers */
573 InOrderDynInst::setMiscRegNoEffect(int misc_reg
, const MiscReg
&val
)
575 this->cpu
->setMiscRegNoEffect(misc_reg
, val
, threadNumber
);
578 /** Sets a misc. register, including any side-effects the write
579 * might have as defined by the architecture.
581 /* Alter this if/when wanting to *speculate* on Miscellaneous registers */
583 InOrderDynInst::setMiscReg(int misc_reg
, const MiscReg
&val
)
585 this->cpu
->setMiscReg(misc_reg
, val
, threadNumber
);
589 InOrderDynInst::setRegOtherThread(unsigned reg_idx
, const MiscReg
&val
,
592 if (tid
== InvalidThreadID
) {
593 tid
= TheISA::getTargetThread(this->cpu
->tcBase(threadNumber
));
596 if (reg_idx
< FP_Base_DepTag
) { // Integer Register File
597 this->cpu
->setIntReg(reg_idx
, val
, tid
);
598 } else if (reg_idx
< Ctrl_Base_DepTag
) { // Float Register File
599 reg_idx
-= FP_Base_DepTag
;
600 this->cpu
->setFloatRegBits(reg_idx
, val
, tid
);
602 reg_idx
-= Ctrl_Base_DepTag
;
603 this->cpu
->setMiscReg(reg_idx
, val
, tid
); // Misc. Register File
608 InOrderDynInst::deallocateContext(int thread_num
)
610 this->cpu
->deallocateContext(thread_num
);
615 InOrderDynInst::read(Addr addr
, T
&data
, unsigned flags
)
618 traceData
->setAddr(addr
);
619 traceData
->setData(data
);
622 return cpu
->read(this, addr
, data
, flags
);
625 #ifndef DOXYGEN_SHOULD_SKIP_THIS
629 InOrderDynInst::read(Addr addr
, uint64_t &data
, unsigned flags
);
633 InOrderDynInst::read(Addr addr
, uint32_t &data
, unsigned flags
);
637 InOrderDynInst::read(Addr addr
, uint16_t &data
, unsigned flags
);
641 InOrderDynInst::read(Addr addr
, uint8_t &data
, unsigned flags
);
643 #endif //DOXYGEN_SHOULD_SKIP_THIS
647 InOrderDynInst::read(Addr addr
, double &data
, unsigned flags
)
649 return read(addr
, *(uint64_t*)&data
, flags
);
654 InOrderDynInst::read(Addr addr
, float &data
, unsigned flags
)
656 return read(addr
, *(uint32_t*)&data
, flags
);
661 InOrderDynInst::read(Addr addr
, int32_t &data
, unsigned flags
)
663 return read(addr
, (uint32_t&)data
, flags
);
668 InOrderDynInst::write(T data
, Addr addr
, unsigned flags
, uint64_t *res
)
671 traceData
->setAddr(addr
);
672 traceData
->setData(data
);
677 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] Setting store data to %#x.\n",
678 threadNumber
, seqNum
, storeData
);
679 return cpu
->write(this, data
, addr
, flags
, res
);
682 #ifndef DOXYGEN_SHOULD_SKIP_THIS
685 InOrderDynInst::write(uint64_t data
, Addr addr
,
686 unsigned flags
, uint64_t *res
);
690 InOrderDynInst::write(uint32_t data
, Addr addr
,
691 unsigned flags
, uint64_t *res
);
695 InOrderDynInst::write(uint16_t data
, Addr addr
,
696 unsigned flags
, uint64_t *res
);
700 InOrderDynInst::write(uint8_t data
, Addr addr
,
701 unsigned flags
, uint64_t *res
);
703 #endif //DOXYGEN_SHOULD_SKIP_THIS
707 InOrderDynInst::write(double data
, Addr addr
, unsigned flags
, uint64_t *res
)
709 return write(*(uint64_t*)&data
, addr
, flags
, res
);
714 InOrderDynInst::write(float data
, Addr addr
, unsigned flags
, uint64_t *res
)
716 return write(*(uint32_t*)&data
, addr
, flags
, res
);
722 InOrderDynInst::write(int32_t data
, Addr addr
, unsigned flags
, uint64_t *res
)
724 return write((uint32_t)data
, addr
, flags
, res
);
729 InOrderDynInst::dump()
731 cprintf("T%d : %#08d `", threadNumber
, PC
);
732 cout
<< staticInst
->disassemble(PC
);
737 InOrderDynInst::dump(std::string
&outstring
)
739 std::ostringstream s
;
740 s
<< "T" << threadNumber
<< " : 0x" << PC
<< " "
741 << staticInst
->disassemble(PC
);
750 #include "base/hashmap.hh"
752 unsigned int MyHashFunc(const InOrderDynInst
*addr
)
754 unsigned a
= (unsigned)addr
;
755 unsigned hash
= (((a
>> 14) ^ ((a
>> 2) & 0xffff))) & 0x7FFFFFFF;
760 typedef m5::hash_map
<const InOrderDynInst
*, const InOrderDynInst
*,