89362c6566b313c33946acaadf78d7fac19f648a
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
,
70 : traceData(NULL
), cpu(cpu
)
78 InOrderDynInst::InOrderDynInst(StaticInstPtr
&_staticInst
)
79 : staticInst(_staticInst
), traceData(NULL
)
85 InOrderDynInst::InOrderDynInst()
86 : traceData(NULL
), cpu(cpu
)
89 int InOrderDynInst::instcount
= 0;
93 InOrderDynInst::setMachInst(ExtMachInst machInst
)
95 staticInst
= StaticInst::decode(machInst
, PC
);
97 for (int i
= 0; i
< this->staticInst
->numDestRegs(); i
++) {
98 _destRegIdx
[i
] = this->staticInst
->destRegIdx(i
);
101 for (int i
= 0; i
< this->staticInst
->numSrcRegs(); i
++) {
102 _srcRegIdx
[i
] = this->staticInst
->srcRegIdx(i
);
103 this->_readySrcRegIdx
[i
] = 0;
108 InOrderDynInst::initVars()
117 nextInstStageNum
= 0;
119 for(int i
= 0; i
< MaxInstDestRegs
; i
++)
120 instResult
[i
].val
.integer
= 0;
124 memAddrReady
= false;
128 predictTaken
= false;
129 procDelaySlotOnMispred
= false;
134 // Also make this a parameter, or perhaps get it from xc or cpu.
139 // Initialize the fault to be NoFault.
142 // Make sure to have the renamed register entries set to the same
143 // as the normal register entries. It will allow the IQ to work
144 // without any modifications.
145 if (this->staticInst
) {
146 for (int i
= 0; i
< this->staticInst
->numDestRegs(); i
++) {
147 _destRegIdx
[i
] = this->staticInst
->destRegIdx(i
);
150 for (int i
= 0; i
< this->staticInst
->numSrcRegs(); i
++) {
151 _srcRegIdx
[i
] = this->staticInst
->srcRegIdx(i
);
152 this->_readySrcRegIdx
[i
] = 0;
156 // Update Instruction Count for this instruction
158 if (instcount
> 500) {
159 fatal("Number of Active Instructions in CPU is too high. "
160 "(Not Dereferencing Ptrs. Correctly?)\n");
165 DPRINTF(InOrderDynInst
, "DynInst: [tid:%i] [sn:%lli] Instruction created. (active insts: %i)\n",
166 threadNumber
, seqNum
, instcount
);
169 cpu
->snList
.insert(seqNum
);
174 InOrderDynInst::~InOrderDynInst()
190 DPRINTF(InOrderDynInst
, "DynInst: [tid:%i] [sn:%lli] Instruction destroyed. (active insts: %i)\n",
191 threadNumber
, seqNum
, instcount
);
193 cpu
->snList
.erase(seqNum
);
198 InOrderDynInst::setStaticInst(StaticInstPtr
&static_inst
)
200 this->staticInst
= static_inst
;
202 // Make sure to have the renamed register entries set to the same
203 // as the normal register entries. It will allow the IQ to work
204 // without any modifications.
205 if (this->staticInst
) {
206 for (int i
= 0; i
< this->staticInst
->numDestRegs(); i
++) {
207 _destRegIdx
[i
] = this->staticInst
->destRegIdx(i
);
210 for (int i
= 0; i
< this->staticInst
->numSrcRegs(); i
++) {
211 _srcRegIdx
[i
] = this->staticInst
->srcRegIdx(i
);
212 this->_readySrcRegIdx
[i
] = 0;
218 InOrderDynInst::execute()
220 // @todo: Pretty convoluted way to avoid squashing from happening
221 // when using the TC during an instruction's execution
222 // (specifically for instructions that have side-effects that use
223 // the TC). Fix this.
224 bool in_syscall
= this->thread
->inSyscall
;
225 this->thread
->inSyscall
= true;
227 this->fault
= this->staticInst
->execute(this, this->traceData
);
229 this->thread
->inSyscall
= in_syscall
;
235 InOrderDynInst::initiateAcc()
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
->initiateAcc(this, this->traceData
);
246 this->thread
->inSyscall
= in_syscall
;
253 InOrderDynInst::completeAcc(Packet
*pkt
)
255 this->fault
= this->staticInst
->completeAcc(pkt
, this, this->traceData
);
260 InstStage
*InOrderDynInst::addStage()
262 this->currentInstStage
= new InstStage(this, nextInstStageNum
++);
263 instStageList
.push_back( this->currentInstStage
);
264 return this->currentInstStage
;
267 InstStage
*InOrderDynInst::addStage(int stage_num
)
269 nextInstStageNum
= stage_num
;
270 return InOrderDynInst::addStage();
273 void InOrderDynInst::deleteStages() {
274 std::list
<InstStage
*>::iterator list_it
= instStageList
.begin();
275 std::list
<InstStage
*>::iterator list_end
= instStageList
.end();
277 while(list_it
!= list_end
) {
284 InOrderDynInst::calcEA()
286 return staticInst
->eaCompInst()->execute(this, this->traceData
);
290 InOrderDynInst::memAccess()
292 //return staticInst->memAccInst()->execute(this, this->traceData);
293 return initiateAcc( );
297 InOrderDynInst::syscall(int64_t callnum
)
299 cpu
->syscall(callnum
, this->threadNumber
);
303 InOrderDynInst::prefetch(Addr addr
, unsigned flags
)
305 // This is the "functional" implementation of prefetch. Not much
306 // happens here since prefetches don't affect the architectural
309 // Generate a MemReq so we can translate the effective address.
310 MemReqPtr req = new MemReq(addr, thread->getXCProxy(), 1, flags);
313 // Prefetches never cause faults.
316 // note this is a local, not InOrderDynInst::fault
317 Fault trans_fault = cpu->translateDataReadReq(req);
319 if (trans_fault == NoFault && !(req->flags & UNCACHEABLE)) {
320 // It's a valid address to cacheable space. Record key MemReq
321 // parameters so we can generate another one just like it for
322 // the timing access without calling translate() again (which
323 // might mess up the TLB).
324 effAddr = req->vaddr;
325 physEffAddr = req->paddr;
326 memReqFlags = req->flags;
328 // Bogus address (invalid or uncacheable space). Mark it by
329 // setting the eff_addr to InvalidAddr.
330 effAddr = physEffAddr = MemReq::inval_addr;
334 traceData->setAddr(addr);
340 InOrderDynInst::writeHint(Addr addr
, int size
, unsigned flags
)
342 // Not currently supported.
346 * @todo Need to find a way to get the cache block size here.
349 InOrderDynInst::copySrcTranslate(Addr src
)
351 // Not currently supported.
356 * @todo Need to find a way to get the cache block size here.
359 InOrderDynInst::copy(Addr dest
)
361 // Not currently supported.
366 InOrderDynInst::releaseReq(ResourceRequest
* req
)
368 std::list
<ResourceRequest
*>::iterator list_it
= reqList
.begin();
369 std::list
<ResourceRequest
*>::iterator list_end
= reqList
.end();
371 while(list_it
!= list_end
) {
372 if((*list_it
)->getResIdx() == req
->getResIdx() &&
373 (*list_it
)->getSlot() == req
->getSlot()) {
374 DPRINTF(InOrderDynInst
, "[tid:%u]: [sn:%i] Done with request to %s.\n",
375 threadNumber
, seqNum
, req
->res
->name());
376 reqList
.erase(list_it
);
382 panic("Releasing Res. Request That Isnt There!\n");
385 /** Records an integer source register being set to a value. */
387 InOrderDynInst::setIntSrc(int idx
, uint64_t val
)
389 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] Source Value %i being set to %#x.\n",
390 threadNumber
, seqNum
, idx
, val
);
391 instSrc
[idx
].integer
= val
;
394 /** Records an fp register being set to a value. */
396 InOrderDynInst::setFloatSrc(int idx
, FloatReg val
, int width
)
399 instSrc
[idx
].fp
= val
;
400 else if (width
== 64)
401 instSrc
[idx
].dbl
= val
;
403 panic("Unsupported width!");
406 /** Records an fp register being set to an integer value. */
408 InOrderDynInst::setFloatRegBitsSrc(int idx
, uint64_t val
)
410 instSrc
[idx
].integer
= val
;
413 /** Reads a integer register. */
415 InOrderDynInst::readIntRegOperand(const StaticInst
*si
, int idx
, unsigned tid
)
417 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] Source Value %i read as %#x.\n",
418 threadNumber
, seqNum
, idx
, instSrc
[idx
].integer
);
419 return instSrc
[idx
].integer
;
422 /** Reads a FP register. */
424 InOrderDynInst::readFloatRegOperand(const StaticInst
*si
, int idx
, int width
)
426 return instSrc
[idx
].fp
;
430 /** Reads a FP register as a integer. */
432 InOrderDynInst::readFloatRegOperandBits(const StaticInst
*si
, int idx
, int width
)
434 return instSrc
[idx
].integer
;
437 /** Reads a miscellaneous register. */
439 InOrderDynInst::readMiscReg(int misc_reg
)
441 return this->cpu
->readMiscReg(misc_reg
, threadNumber
);
444 /** Reads a misc. register, including any side-effects the read
445 * might have as defined by the architecture.
448 InOrderDynInst::readMiscRegNoEffect(int misc_reg
)
450 return this->cpu
->readMiscRegNoEffect(misc_reg
, threadNumber
);
453 /** Reads a miscellaneous register. */
455 InOrderDynInst::readMiscRegOperandNoEffect(const StaticInst
*si
, int idx
)
457 return this->cpu
->readMiscRegNoEffect(
458 si
->srcRegIdx(idx
) - TheISA::Ctrl_Base_DepTag
,
462 /** Reads a misc. register, including any side-effects the read
463 * might have as defined by the architecture.
466 InOrderDynInst::readMiscRegOperand(const StaticInst
*si
, int idx
)
468 return this->cpu
->readMiscReg(
469 si
->srcRegIdx(idx
) - TheISA::Ctrl_Base_DepTag
,
473 /** Sets a misc. register. */
475 InOrderDynInst::setMiscRegOperandNoEffect(const StaticInst
* si
, int idx
, const MiscReg
&val
)
477 instResult
[si
->destRegIdx(idx
)].val
.integer
= val
;
478 instResult
[si
->destRegIdx(idx
)].tick
= curTick
;
480 this->cpu
->setMiscRegNoEffect(
481 si
->destRegIdx(idx
) - TheISA::Ctrl_Base_DepTag
,
482 val
, this->threadNumber
);
485 /** Sets a misc. register, including any side-effects the write
486 * might have as defined by the architecture.
489 InOrderDynInst::setMiscRegOperand(const StaticInst
*si
, int idx
,
492 instResult
[si
->destRegIdx(idx
)].val
.integer
= val
;
493 instResult
[si
->destRegIdx(idx
)].tick
= curTick
;
495 this->cpu
->setMiscReg(
496 si
->destRegIdx(idx
) - TheISA::Ctrl_Base_DepTag
,
497 val
, this->threadNumber
);
501 InOrderDynInst::readRegOtherThread(unsigned reg_idx
, int tid
)
504 tid
= TheISA::getTargetThread(this->cpu
->tcBase(threadNumber
));
507 if (reg_idx
< FP_Base_DepTag
) { // Integer Register File
508 return this->cpu
->readIntReg(reg_idx
, tid
);
509 } else if (reg_idx
< Ctrl_Base_DepTag
) { // Float Register File
510 reg_idx
-= FP_Base_DepTag
;
511 return this->cpu
->readFloatRegBits(reg_idx
, tid
);
513 reg_idx
-= Ctrl_Base_DepTag
;
514 return this->cpu
->readMiscReg(reg_idx
, tid
); // Misc. Register File
518 /** Sets a Integer register. */
520 InOrderDynInst::setIntRegOperand(const StaticInst
*si
, int idx
, IntReg val
)
522 instResult
[idx
].val
.integer
= val
;
523 instResult
[idx
].tick
= curTick
;
526 /** Sets a FP register. */
528 InOrderDynInst::setFloatRegOperand(const StaticInst
*si
, int idx
, FloatReg val
, int width
)
531 instResult
[idx
].val
.fp
= val
;
532 else if (width
== 64)
533 instResult
[idx
].val
.dbl
= val
;
535 panic("Unsupported Floating Point Width!");
537 instResult
[idx
].tick
= curTick
;
540 /** Sets a FP register as a integer. */
542 InOrderDynInst::setFloatRegOperandBits(const StaticInst
*si
, int idx
,
543 FloatRegBits val
, int width
)
545 instResult
[idx
].val
.integer
= val
;
546 instResult
[idx
].tick
= curTick
;
549 /** Sets a misc. register. */
550 /* Alter this when wanting to *speculate* on Miscellaneous registers */
552 InOrderDynInst::setMiscRegNoEffect(int misc_reg
, const MiscReg
&val
)
554 this->cpu
->setMiscRegNoEffect(misc_reg
, val
, threadNumber
);
557 /** Sets a misc. register, including any side-effects the write
558 * might have as defined by the architecture.
560 /* Alter this if/when wanting to *speculate* on Miscellaneous registers */
562 InOrderDynInst::setMiscReg(int misc_reg
, const MiscReg
&val
)
564 this->cpu
->setMiscReg(misc_reg
, val
, threadNumber
);
568 InOrderDynInst::setRegOtherThread(unsigned reg_idx
, const MiscReg
&val
, int tid
)
571 tid
= TheISA::getTargetThread(this->cpu
->tcBase(threadNumber
));
574 if (reg_idx
< FP_Base_DepTag
) { // Integer Register File
575 this->cpu
->setIntReg(reg_idx
, val
, tid
);
576 } else if (reg_idx
< Ctrl_Base_DepTag
) { // Float Register File
577 reg_idx
-= FP_Base_DepTag
;
578 this->cpu
->setFloatRegBits(reg_idx
, val
, tid
);
580 reg_idx
-= Ctrl_Base_DepTag
;
581 this->cpu
->setMiscReg(reg_idx
, val
, tid
); // Misc. Register File
586 InOrderDynInst::deallocateContext(int thread_num
)
588 this->cpu
->deallocateContext(thread_num
);
592 InOrderDynInst::enableVirtProcElement(unsigned vpe
)
594 this->cpu
->enableVirtProcElement(vpe
);
598 InOrderDynInst::disableVirtProcElement(unsigned vpe
)
600 this->cpu
->disableVirtProcElement(threadNumber
, vpe
);
604 InOrderDynInst::enableMultiThreading(unsigned vpe
)
606 this->cpu
->enableMultiThreading(vpe
);
610 InOrderDynInst::disableMultiThreading(unsigned vpe
)
612 this->cpu
->disableMultiThreading(threadNumber
, vpe
);
616 InOrderDynInst::setThreadRescheduleCondition(uint32_t cond
)
618 this->cpu
->setThreadRescheduleCondition(cond
);
623 InOrderDynInst::read(Addr addr
, T
&data
, unsigned flags
)
625 return cpu
->read(this);
628 #ifndef DOXYGEN_SHOULD_SKIP_THIS
632 InOrderDynInst::read(Addr addr
, uint64_t &data
, unsigned flags
);
636 InOrderDynInst::read(Addr addr
, uint32_t &data
, unsigned flags
);
640 InOrderDynInst::read(Addr addr
, uint16_t &data
, unsigned flags
);
644 InOrderDynInst::read(Addr addr
, uint8_t &data
, unsigned flags
);
646 #endif //DOXYGEN_SHOULD_SKIP_THIS
650 InOrderDynInst::read(Addr addr
, double &data
, unsigned flags
)
652 return read(addr
, *(uint64_t*)&data
, flags
);
657 InOrderDynInst::read(Addr addr
, float &data
, unsigned flags
)
659 return read(addr
, *(uint32_t*)&data
, flags
);
664 InOrderDynInst::read(Addr addr
, int32_t &data
, unsigned flags
)
666 return read(addr
, (uint32_t&)data
, flags
);
671 InOrderDynInst::write(T data
, Addr addr
, unsigned flags
, uint64_t *res
)
673 //memcpy(memData, gtoh(data), sizeof(T));
676 DPRINTF(InOrderDynInst
, "[tid:%i]: [sn:%i] Setting store data to %#x.\n",
677 threadNumber
, seqNum
, memData
);
678 return cpu
->write(this);
681 #ifndef DOXYGEN_SHOULD_SKIP_THIS
684 InOrderDynInst::write(uint64_t data
, Addr addr
,
685 unsigned flags
, uint64_t *res
);
689 InOrderDynInst::write(uint32_t data
, Addr addr
,
690 unsigned flags
, uint64_t *res
);
694 InOrderDynInst::write(uint16_t data
, Addr addr
,
695 unsigned flags
, uint64_t *res
);
699 InOrderDynInst::write(uint8_t data
, Addr addr
,
700 unsigned flags
, uint64_t *res
);
702 #endif //DOXYGEN_SHOULD_SKIP_THIS
706 InOrderDynInst::write(double data
, Addr addr
, unsigned flags
, uint64_t *res
)
708 return write(*(uint64_t*)&data
, addr
, flags
, res
);
713 InOrderDynInst::write(float data
, Addr addr
, unsigned flags
, uint64_t *res
)
715 return write(*(uint32_t*)&data
, addr
, flags
, res
);
721 InOrderDynInst::write(int32_t data
, Addr addr
, unsigned flags
, uint64_t *res
)
723 return write((uint32_t)data
, addr
, flags
, res
);
728 InOrderDynInst::dump()
730 cprintf("T%d : %#08d `", threadNumber
, PC
);
731 cout
<< staticInst
->disassemble(PC
);
736 InOrderDynInst::dump(std::string
&outstring
)
738 std::ostringstream s
;
739 s
<< "T" << threadNumber
<< " : 0x" << PC
<< " "
740 << staticInst
->disassemble(PC
);
749 #include "base/hashmap.hh"
751 unsigned int MyHashFunc(const InOrderDynInst
*addr
)
753 unsigned a
= (unsigned)addr
;
754 unsigned hash
= (((a
>> 14) ^ ((a
>> 2) & 0xffff))) & 0x7FFFFFFF;
759 typedef m5::hash_map
<const InOrderDynInst
*, const InOrderDynInst
*, MyHashFunc
>
768 InOrderDynInst::dumpSNList()
770 std::set
<InstSeqNum
>::iterator sn_it
= cpu
->snList
.begin();
773 while (sn_it
!= cpu
->snList
.end()) {
774 cprintf("%i: [sn:%lli] not destroyed\n", count
, (*sn_it
));