280740116112d4d0030180d53bdb3571f3693a7f
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 "base/cprintf.hh"
38 #include "base/trace.hh"
40 #include "arch/faults.hh"
41 #include "cpu/exetrace.hh"
42 #include "mem/request.hh"
44 #include "cpu/inorder/inorder_dyn_inst.hh"
45 #include "cpu/inorder/cpu.hh"
48 using namespace TheISA
;
49 using namespace ThePipeline
;
51 InOrderDynInst::InOrderDynInst(TheISA::ExtMachInst machInst
, Addr inst_PC
,
52 Addr pred_PC
, InstSeqNum seq_num
,
54 : staticInst(machInst
, inst_PC
), traceData(NULL
), cpu(cpu
)
59 nextPC
= PC
+ sizeof(MachInst
);
60 nextNPC
= nextPC
+ sizeof(MachInst
);
66 InOrderDynInst::InOrderDynInst(InOrderCPU
*cpu
,
67 InOrderThreadState
*state
,
71 : traceData(NULL
), cpu(cpu
)
80 InOrderDynInst::InOrderDynInst(StaticInstPtr
&_staticInst
)
81 : seqNum(0), staticInst(_staticInst
), traceData(NULL
)
86 InOrderDynInst::InOrderDynInst()
87 : seqNum(0), traceData(NULL
), cpu(cpu
)
92 int InOrderDynInst::instcount
= 0;
96 InOrderDynInst::setMachInst(ExtMachInst machInst
)
98 staticInst
= StaticInst::decode(machInst
, PC
);
100 for (int i
= 0; i
< this->staticInst
->numDestRegs(); i
++) {
101 _destRegIdx
[i
] = this->staticInst
->destRegIdx(i
);
104 for (int i
= 0; i
< this->staticInst
->numSrcRegs(); i
++) {
105 _srcRegIdx
[i
] = this->staticInst
->srcRegIdx(i
);
106 this->_readySrcRegIdx
[i
] = 0;
111 InOrderDynInst::initVars()
122 nextInstStageNum
= 0;
124 for(int i
= 0; i
< MaxInstDestRegs
; i
++)
125 instResult
[i
].val
.integer
= 0;
129 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
163 if (instcount
> 500) {
164 fatal("Number of Active Instructions in CPU is too high. "
165 "(Not Dereferencing Ptrs. Correctly?)\n");
170 DPRINTF(InOrderDynInst
, "DynInst: [tid:%i] [sn:%lli] Instruction created. (active insts: %i)\n",
171 threadNumber
, seqNum
, instcount
);
175 InOrderDynInst::~InOrderDynInst()
177 if (fetchMemReq
!= 0x0) {
182 if (dataMemReq
!= 0x0) {
197 DPRINTF(InOrderDynInst
, "DynInst: [tid:%i] [sn:%lli] Instruction destroyed. (active insts: %i)\n",
198 threadNumber
, seqNum
, instcount
);
202 InOrderDynInst::setStaticInst(StaticInstPtr
&static_inst
)
204 this->staticInst
= static_inst
;
206 // Make sure to have the renamed register entries set to the same
207 // as the normal register entries. It will allow the IQ to work
208 // without any modifications.
209 if (this->staticInst
) {
210 for (int i
= 0; i
< this->staticInst
->numDestRegs(); i
++) {
211 _destRegIdx
[i
] = this->staticInst
->destRegIdx(i
);
214 for (int i
= 0; i
< this->staticInst
->numSrcRegs(); i
++) {
215 _srcRegIdx
[i
] = this->staticInst
->srcRegIdx(i
);
216 this->_readySrcRegIdx
[i
] = 0;
222 InOrderDynInst::execute()
224 // @todo: Pretty convoluted way to avoid squashing from happening
225 // when using the TC during an instruction's execution
226 // (specifically for instructions that have side-effects that use
227 // the TC). Fix this.
228 bool in_syscall
= this->thread
->inSyscall
;
229 this->thread
->inSyscall
= true;
231 this->fault
= this->staticInst
->execute(this, this->traceData
);
233 this->thread
->inSyscall
= in_syscall
;
239 InOrderDynInst::calcEA()
241 this->fault
= this->staticInst
->eaComp(this, this->traceData
);
246 InOrderDynInst::initiateAcc()
248 // @todo: Pretty convoluted way to avoid squashing from happening
249 // when using the TC during an instruction's execution
250 // (specifically for instructions that have side-effects that use
251 // the TC). Fix this.
252 bool in_syscall
= this->thread
->inSyscall
;
253 this->thread
->inSyscall
= true;
255 this->fault
= this->staticInst
->initiateAcc(this, this->traceData
);
257 this->thread
->inSyscall
= in_syscall
;
264 InOrderDynInst::completeAcc(Packet
*pkt
)
266 this->fault
= this->staticInst
->completeAcc(pkt
, this, this->traceData
);
271 InstStage
*InOrderDynInst::addStage()
273 this->currentInstStage
= new InstStage(this, nextInstStageNum
++);
274 instStageList
.push_back( this->currentInstStage
);
275 return this->currentInstStage
;
278 InstStage
*InOrderDynInst::addStage(int stage_num
)
280 nextInstStageNum
= stage_num
;
281 return InOrderDynInst::addStage();
284 void InOrderDynInst::deleteStages() {
285 std::list
<InstStage
*>::iterator list_it
= instStageList
.begin();
286 std::list
<InstStage
*>::iterator list_end
= instStageList
.end();
288 while(list_it
!= list_end
) {
295 InOrderDynInst::memAccess()
297 return initiateAcc();
301 InOrderDynInst::syscall(int64_t callnum
)
303 cpu
->syscall(callnum
, this->threadNumber
);
307 InOrderDynInst::prefetch(Addr addr
, unsigned flags
)
313 InOrderDynInst::writeHint(Addr addr
, int size
, unsigned flags
)
315 cpu
->writeHint(this);
319 * @todo Need to find a way to get the cache block size here.
322 InOrderDynInst::copySrcTranslate(Addr src
)
324 // Not currently supported.
329 * @todo Need to find a way to get the cache block size here.
332 InOrderDynInst::copy(Addr dest
)
334 // Not currently supported.
339 InOrderDynInst::releaseReq(ResourceRequest
* req
)
341 std::list
<ResourceRequest
*>::iterator list_it
= reqList
.begin();
342 std::list
<ResourceRequest
*>::iterator list_end
= reqList
.end();
344 while(list_it
!= list_end
) {
345 if((*list_it
)->getResIdx() == req
->getResIdx() &&
346 (*list_it
)->getSlot() == req
->getSlot()) {
347 DPRINTF(InOrderDynInst
, "[tid:%u]: [sn:%i] Done with request to %s.\n",
348 threadNumber
, seqNum
, req
->res
->name());
349 reqList
.erase(list_it
);
355 panic("Releasing Res. Request That Isnt There!\n");
358 /** Records an integer source register being set to a value. */
360 InOrderDynInst::setIntSrc(int idx
, uint64_t val
)
362 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] Source Value %i being set to %#x.\n",
363 threadNumber
, seqNum
, idx
, val
);
364 instSrc
[idx
].integer
= val
;
367 /** Records an fp register being set to a value. */
369 InOrderDynInst::setFloatSrc(int idx
, FloatReg val
, int width
)
372 instSrc
[idx
].dbl
= val
;
373 else if (width
== 64)
374 instSrc
[idx
].dbl
= val
;
376 panic("Unsupported width!");
379 /** Records an fp register being set to an integer value. */
381 InOrderDynInst::setFloatRegBitsSrc(int idx
, uint64_t val
)
383 instSrc
[idx
].integer
= val
;
386 /** Reads a integer register. */
388 InOrderDynInst::readIntRegOperand(const StaticInst
*si
, int idx
, unsigned tid
)
390 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] Source Value %i read as %#x.\n",
391 threadNumber
, seqNum
, idx
, instSrc
[idx
].integer
);
392 return instSrc
[idx
].integer
;
395 /** Reads a FP register. */
397 InOrderDynInst::readFloatRegOperand(const StaticInst
*si
, int idx
, int width
)
400 return (float)instSrc
[idx
].dbl
;
401 else if (width
== 64)
402 return instSrc
[idx
].dbl
;
404 panic("Unsupported Floating Point Width!");
410 /** Reads a FP register as a integer. */
412 InOrderDynInst::readFloatRegOperandBits(const StaticInst
*si
, int idx
, int width
)
414 return instSrc
[idx
].integer
;
417 /** Reads a miscellaneous register. */
419 InOrderDynInst::readMiscReg(int misc_reg
)
421 return this->cpu
->readMiscReg(misc_reg
, threadNumber
);
424 /** Reads a misc. register, including any side-effects the read
425 * might have as defined by the architecture.
428 InOrderDynInst::readMiscRegNoEffect(int misc_reg
)
430 return this->cpu
->readMiscRegNoEffect(misc_reg
, threadNumber
);
433 /** Reads a miscellaneous register. */
435 InOrderDynInst::readMiscRegOperandNoEffect(const StaticInst
*si
, int idx
)
437 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] Misc. Reg Source Value %i"
438 " read as %#x.\n", threadNumber
, seqNum
, idx
,
439 instSrc
[idx
].integer
);
440 return instSrc
[idx
].integer
;
443 /** Reads a misc. register, including any side-effects the read
444 * might have as defined by the architecture.
447 InOrderDynInst::readMiscRegOperand(const StaticInst
*si
, int idx
)
449 // For In-Order, the side-effect of reading a register happens
450 // when explicitly executing a "ReadSrc" command. This simply returns
452 return readMiscRegOperandNoEffect(si
, idx
);
455 /** Sets a misc. register. */
457 InOrderDynInst::setMiscRegOperandNoEffect(const StaticInst
* si
, int idx
,
460 instResult
[idx
].type
= Integer
;
461 instResult
[idx
].val
.integer
= val
;
462 instResult
[idx
].tick
= curTick
;
464 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] Setting Misc Reg. Operand %i "
465 "being set to %#x.\n", threadNumber
, seqNum
, idx
, val
);
468 /** Sets a misc. register, including any side-effects the write
469 * might have as defined by the architecture.
472 InOrderDynInst::setMiscRegOperand(const StaticInst
*si
, int idx
,
475 // For In-Order, the side-effect of setting a register happens
476 // when explicitly writing back the register value. This
477 // simply maintains the operand value.
478 setMiscRegOperandNoEffect(si
, idx
, val
);
482 InOrderDynInst::readRegOtherThread(unsigned reg_idx
, int tid
)
485 tid
= TheISA::getTargetThread(this->cpu
->tcBase(threadNumber
));
488 if (reg_idx
< FP_Base_DepTag
) { // Integer Register File
489 return this->cpu
->readIntReg(reg_idx
, tid
);
490 } else if (reg_idx
< Ctrl_Base_DepTag
) { // Float Register File
491 reg_idx
-= FP_Base_DepTag
;
492 return this->cpu
->readFloatRegBits(reg_idx
, tid
);
494 reg_idx
-= Ctrl_Base_DepTag
;
495 return this->cpu
->readMiscReg(reg_idx
, tid
); // Misc. Register File
499 /** Sets a Integer register. */
501 InOrderDynInst::setIntRegOperand(const StaticInst
*si
, int idx
, IntReg val
)
503 instResult
[idx
].type
= Integer
;
504 instResult
[idx
].val
.integer
= val
;
505 instResult
[idx
].tick
= curTick
;
508 /** Sets a FP register. */
510 InOrderDynInst::setFloatRegOperand(const StaticInst
*si
, int idx
, FloatReg val
, int width
)
513 instResult
[idx
].val
.dbl
= (float)val
;
514 instResult
[idx
].type
= Float
;
515 } else if (width
== 64) {
516 instResult
[idx
].val
.dbl
= val
;
517 instResult
[idx
].type
= Double
;
519 panic("Unsupported Floating Point Width!");
522 instResult
[idx
].tick
= curTick
;
525 /** Sets a FP register as a integer. */
527 InOrderDynInst::setFloatRegOperandBits(const StaticInst
*si
, int idx
,
528 FloatRegBits val
, int width
)
531 instResult
[idx
].type
= Float
;
532 else if (width
== 64)
533 instResult
[idx
].type
= Double
;
535 instResult
[idx
].val
.integer
= val
;
536 instResult
[idx
].tick
= curTick
;
539 /** Sets a misc. register. */
540 /* Alter this when wanting to *speculate* on Miscellaneous registers */
542 InOrderDynInst::setMiscRegNoEffect(int misc_reg
, const MiscReg
&val
)
544 this->cpu
->setMiscRegNoEffect(misc_reg
, val
, threadNumber
);
547 /** Sets a misc. register, including any side-effects the write
548 * might have as defined by the architecture.
550 /* Alter this if/when wanting to *speculate* on Miscellaneous registers */
552 InOrderDynInst::setMiscReg(int misc_reg
, const MiscReg
&val
)
554 this->cpu
->setMiscReg(misc_reg
, val
, threadNumber
);
558 InOrderDynInst::setRegOtherThread(unsigned reg_idx
, const MiscReg
&val
, int tid
)
561 tid
= TheISA::getTargetThread(this->cpu
->tcBase(threadNumber
));
564 if (reg_idx
< FP_Base_DepTag
) { // Integer Register File
565 this->cpu
->setIntReg(reg_idx
, val
, tid
);
566 } else if (reg_idx
< Ctrl_Base_DepTag
) { // Float Register File
567 reg_idx
-= FP_Base_DepTag
;
568 this->cpu
->setFloatRegBits(reg_idx
, val
, tid
);
570 reg_idx
-= Ctrl_Base_DepTag
;
571 this->cpu
->setMiscReg(reg_idx
, val
, tid
); // Misc. Register File
576 InOrderDynInst::deallocateContext(int thread_num
)
578 this->cpu
->deallocateContext(thread_num
);
582 InOrderDynInst::enableVirtProcElement(unsigned vpe
)
584 this->cpu
->enableVirtProcElement(vpe
);
588 InOrderDynInst::disableVirtProcElement(unsigned vpe
)
590 this->cpu
->disableVirtProcElement(threadNumber
, vpe
);
594 InOrderDynInst::enableMultiThreading(unsigned vpe
)
596 this->cpu
->enableMultiThreading(vpe
);
600 InOrderDynInst::disableMultiThreading(unsigned vpe
)
602 this->cpu
->disableMultiThreading(threadNumber
, vpe
);
607 InOrderDynInst::read(Addr addr
, T
&data
, unsigned flags
)
609 return cpu
->read(this);
612 #ifndef DOXYGEN_SHOULD_SKIP_THIS
616 InOrderDynInst::read(Addr addr
, uint64_t &data
, unsigned flags
);
620 InOrderDynInst::read(Addr addr
, uint32_t &data
, unsigned flags
);
624 InOrderDynInst::read(Addr addr
, uint16_t &data
, unsigned flags
);
628 InOrderDynInst::read(Addr addr
, uint8_t &data
, unsigned flags
);
630 #endif //DOXYGEN_SHOULD_SKIP_THIS
634 InOrderDynInst::read(Addr addr
, double &data
, unsigned flags
)
636 return read(addr
, *(uint64_t*)&data
, flags
);
641 InOrderDynInst::read(Addr addr
, float &data
, unsigned flags
)
643 return read(addr
, *(uint32_t*)&data
, flags
);
648 InOrderDynInst::read(Addr addr
, int32_t &data
, unsigned flags
)
650 return read(addr
, (uint32_t&)data
, flags
);
655 InOrderDynInst::write(T data
, Addr addr
, unsigned flags
, uint64_t *res
)
657 //memcpy(memData, gtoh(data), sizeof(T));
660 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] Setting store data to %#x.\n",
661 threadNumber
, seqNum
, memData
);
662 return cpu
->write(this);
665 #ifndef DOXYGEN_SHOULD_SKIP_THIS
668 InOrderDynInst::write(uint64_t data
, Addr addr
,
669 unsigned flags
, uint64_t *res
);
673 InOrderDynInst::write(uint32_t data
, Addr addr
,
674 unsigned flags
, uint64_t *res
);
678 InOrderDynInst::write(uint16_t data
, Addr addr
,
679 unsigned flags
, uint64_t *res
);
683 InOrderDynInst::write(uint8_t data
, Addr addr
,
684 unsigned flags
, uint64_t *res
);
686 #endif //DOXYGEN_SHOULD_SKIP_THIS
690 InOrderDynInst::write(double data
, Addr addr
, unsigned flags
, uint64_t *res
)
692 return write(*(uint64_t*)&data
, addr
, flags
, res
);
697 InOrderDynInst::write(float data
, Addr addr
, unsigned flags
, uint64_t *res
)
699 return write(*(uint32_t*)&data
, addr
, flags
, res
);
705 InOrderDynInst::write(int32_t data
, Addr addr
, unsigned flags
, uint64_t *res
)
707 return write((uint32_t)data
, addr
, flags
, res
);
712 InOrderDynInst::dump()
714 cprintf("T%d : %#08d `", threadNumber
, PC
);
715 cout
<< staticInst
->disassemble(PC
);
720 InOrderDynInst::dump(std::string
&outstring
)
722 std::ostringstream s
;
723 s
<< "T" << threadNumber
<< " : 0x" << PC
<< " "
724 << staticInst
->disassemble(PC
);
733 #include "base/hashmap.hh"
735 unsigned int MyHashFunc(const InOrderDynInst
*addr
)
737 unsigned a
= (unsigned)addr
;
738 unsigned hash
= (((a
>> 14) ^ ((a
>> 2) & 0xffff))) & 0x7FFFFFFF;
743 typedef m5::hash_map
<const InOrderDynInst
*, const InOrderDynInst
*, MyHashFunc
>