753 lines
19 KiB
C++
753 lines
19 KiB
C++
/*
|
|
* Copyright (c) 2007 MIPS Technologies, Inc.
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are
|
|
* met: redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer;
|
|
* redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution;
|
|
* neither the name of the copyright holders nor the names of its
|
|
* contributors may be used to endorse or promote products derived from
|
|
* this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
* Authors: Korey Sewell
|
|
*
|
|
*/
|
|
|
|
#include <iostream>
|
|
#include <set>
|
|
#include <string>
|
|
#include <sstream>
|
|
|
|
#include "arch/faults.hh"
|
|
#include "base/cprintf.hh"
|
|
#include "base/trace.hh"
|
|
#include "config/the_isa.hh"
|
|
#include "cpu/exetrace.hh"
|
|
#include "cpu/inorder/cpu.hh"
|
|
#include "cpu/inorder/inorder_dyn_inst.hh"
|
|
#include "mem/request.hh"
|
|
|
|
using namespace std;
|
|
using namespace TheISA;
|
|
using namespace ThePipeline;
|
|
|
|
InOrderDynInst::InOrderDynInst(TheISA::ExtMachInst machInst, Addr inst_PC,
|
|
Addr pred_PC, InstSeqNum seq_num,
|
|
InOrderCPU *cpu)
|
|
: staticInst(machInst, inst_PC), traceData(NULL), cpu(cpu)
|
|
{
|
|
seqNum = seq_num;
|
|
|
|
PC = inst_PC;
|
|
nextPC = PC + sizeof(MachInst);
|
|
nextNPC = nextPC + sizeof(MachInst);
|
|
predPC = pred_PC;
|
|
|
|
initVars();
|
|
}
|
|
|
|
InOrderDynInst::InOrderDynInst(InOrderCPU *cpu,
|
|
InOrderThreadState *state,
|
|
InstSeqNum seq_num,
|
|
ThreadID tid,
|
|
unsigned _asid)
|
|
: traceData(NULL), cpu(cpu)
|
|
{
|
|
seqNum = seq_num;
|
|
thread = state;
|
|
threadNumber = tid;
|
|
asid = _asid;
|
|
initVars();
|
|
}
|
|
|
|
InOrderDynInst::InOrderDynInst(StaticInstPtr &_staticInst)
|
|
: seqNum(0), staticInst(_staticInst), traceData(NULL)
|
|
{
|
|
initVars();
|
|
}
|
|
|
|
InOrderDynInst::InOrderDynInst()
|
|
: seqNum(0), traceData(NULL), cpu(cpu)
|
|
{
|
|
initVars();
|
|
}
|
|
|
|
int InOrderDynInst::instcount = 0;
|
|
|
|
|
|
void
|
|
InOrderDynInst::setMachInst(ExtMachInst machInst)
|
|
{
|
|
staticInst = StaticInst::decode(machInst, PC);
|
|
|
|
for (int i = 0; i < this->staticInst->numDestRegs(); i++) {
|
|
_destRegIdx[i] = this->staticInst->destRegIdx(i);
|
|
}
|
|
|
|
for (int i = 0; i < this->staticInst->numSrcRegs(); i++) {
|
|
_srcRegIdx[i] = this->staticInst->srcRegIdx(i);
|
|
this->_readySrcRegIdx[i] = 0;
|
|
}
|
|
}
|
|
|
|
void
|
|
InOrderDynInst::initVars()
|
|
{
|
|
fetchMemReq = NULL;
|
|
dataMemReq = NULL;
|
|
|
|
effAddr = 0;
|
|
physEffAddr = 0;
|
|
|
|
readyRegs = 0;
|
|
|
|
nextStage = 0;
|
|
nextInstStageNum = 0;
|
|
|
|
for(int i = 0; i < MaxInstDestRegs; i++)
|
|
instResult[i].val.integer = 0;
|
|
|
|
status.reset();
|
|
|
|
memAddrReady = false;
|
|
eaCalcDone = false;
|
|
memOpDone = false;
|
|
|
|
predictTaken = false;
|
|
procDelaySlotOnMispred = false;
|
|
|
|
lqIdx = -1;
|
|
sqIdx = -1;
|
|
|
|
// Also make this a parameter, or perhaps get it from xc or cpu.
|
|
asid = 0;
|
|
|
|
virtProcNumber = 0;
|
|
|
|
// Initialize the fault to be NoFault.
|
|
fault = NoFault;
|
|
|
|
// Make sure to have the renamed register entries set to the same
|
|
// as the normal register entries. It will allow the IQ to work
|
|
// without any modifications.
|
|
if (this->staticInst) {
|
|
for (int i = 0; i < this->staticInst->numDestRegs(); i++) {
|
|
_destRegIdx[i] = this->staticInst->destRegIdx(i);
|
|
}
|
|
|
|
for (int i = 0; i < this->staticInst->numSrcRegs(); i++) {
|
|
_srcRegIdx[i] = this->staticInst->srcRegIdx(i);
|
|
this->_readySrcRegIdx[i] = 0;
|
|
}
|
|
}
|
|
|
|
// Update Instruction Count for this instruction
|
|
++instcount;
|
|
if (instcount > 500) {
|
|
fatal("Number of Active Instructions in CPU is too high. "
|
|
"(Not Dereferencing Ptrs. Correctly?)\n");
|
|
}
|
|
|
|
|
|
|
|
DPRINTF(InOrderDynInst, "DynInst: [tid:%i] [sn:%lli] Instruction created. (active insts: %i)\n",
|
|
threadNumber, seqNum, instcount);
|
|
}
|
|
|
|
|
|
InOrderDynInst::~InOrderDynInst()
|
|
{
|
|
if (fetchMemReq != 0x0) {
|
|
delete fetchMemReq;
|
|
fetchMemReq = NULL;
|
|
}
|
|
|
|
if (dataMemReq != 0x0) {
|
|
delete dataMemReq;
|
|
dataMemReq = NULL;
|
|
}
|
|
|
|
if (traceData) {
|
|
delete traceData;
|
|
}
|
|
|
|
fault = NoFault;
|
|
|
|
--instcount;
|
|
|
|
deleteStages();
|
|
|
|
DPRINTF(InOrderDynInst, "DynInst: [tid:%i] [sn:%lli] Instruction destroyed. (active insts: %i)\n",
|
|
threadNumber, seqNum, instcount);
|
|
}
|
|
|
|
void
|
|
InOrderDynInst::setStaticInst(StaticInstPtr &static_inst)
|
|
{
|
|
this->staticInst = static_inst;
|
|
|
|
// Make sure to have the renamed register entries set to the same
|
|
// as the normal register entries. It will allow the IQ to work
|
|
// without any modifications.
|
|
if (this->staticInst) {
|
|
for (int i = 0; i < this->staticInst->numDestRegs(); i++) {
|
|
_destRegIdx[i] = this->staticInst->destRegIdx(i);
|
|
}
|
|
|
|
for (int i = 0; i < this->staticInst->numSrcRegs(); i++) {
|
|
_srcRegIdx[i] = this->staticInst->srcRegIdx(i);
|
|
this->_readySrcRegIdx[i] = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
Fault
|
|
InOrderDynInst::execute()
|
|
{
|
|
// @todo: Pretty convoluted way to avoid squashing from happening
|
|
// when using the TC during an instruction's execution
|
|
// (specifically for instructions that have side-effects that use
|
|
// the TC). Fix this.
|
|
bool in_syscall = this->thread->inSyscall;
|
|
this->thread->inSyscall = true;
|
|
|
|
this->fault = this->staticInst->execute(this, this->traceData);
|
|
|
|
this->thread->inSyscall = in_syscall;
|
|
|
|
return this->fault;
|
|
}
|
|
|
|
Fault
|
|
InOrderDynInst::calcEA()
|
|
{
|
|
this->fault = this->staticInst->eaComp(this, this->traceData);
|
|
return this->fault;
|
|
}
|
|
|
|
Fault
|
|
InOrderDynInst::initiateAcc()
|
|
{
|
|
// @todo: Pretty convoluted way to avoid squashing from happening
|
|
// when using the TC during an instruction's execution
|
|
// (specifically for instructions that have side-effects that use
|
|
// the TC). Fix this.
|
|
bool in_syscall = this->thread->inSyscall;
|
|
this->thread->inSyscall = true;
|
|
|
|
this->fault = this->staticInst->initiateAcc(this, this->traceData);
|
|
|
|
this->thread->inSyscall = in_syscall;
|
|
|
|
return this->fault;
|
|
}
|
|
|
|
|
|
Fault
|
|
InOrderDynInst::completeAcc(Packet *pkt)
|
|
{
|
|
this->fault = this->staticInst->completeAcc(pkt, this, this->traceData);
|
|
|
|
return this->fault;
|
|
}
|
|
|
|
InstStage *InOrderDynInst::addStage()
|
|
{
|
|
this->currentInstStage = new InstStage(this, nextInstStageNum++);
|
|
instStageList.push_back( this->currentInstStage );
|
|
return this->currentInstStage;
|
|
}
|
|
|
|
InstStage *InOrderDynInst::addStage(int stage_num)
|
|
{
|
|
nextInstStageNum = stage_num;
|
|
return InOrderDynInst::addStage();
|
|
}
|
|
|
|
void InOrderDynInst::deleteStages() {
|
|
std::list<InstStage*>::iterator list_it = instStageList.begin();
|
|
std::list<InstStage*>::iterator list_end = instStageList.end();
|
|
|
|
while(list_it != list_end) {
|
|
delete *list_it;
|
|
list_it++;
|
|
}
|
|
}
|
|
|
|
Fault
|
|
InOrderDynInst::memAccess()
|
|
{
|
|
return initiateAcc();
|
|
}
|
|
|
|
|
|
#if FULL_SYSTEM
|
|
|
|
Fault
|
|
InOrderDynInst::hwrei()
|
|
{
|
|
panic("InOrderDynInst: hwrei: unimplemented\n");
|
|
return NoFault;
|
|
}
|
|
|
|
|
|
void
|
|
InOrderDynInst::trap(Fault fault)
|
|
{
|
|
this->cpu->trap(fault, this->threadNumber);
|
|
}
|
|
|
|
|
|
bool
|
|
InOrderDynInst::simPalCheck(int palFunc)
|
|
{
|
|
#if THE_ISA != ALPHA_ISA
|
|
panic("simPalCheck called, but PAL only exists in Alpha!\n");
|
|
#endif
|
|
return this->cpu->simPalCheck(palFunc, this->threadNumber);
|
|
}
|
|
#else
|
|
void
|
|
InOrderDynInst::syscall(int64_t callnum)
|
|
{
|
|
cpu->syscall(callnum, this->threadNumber);
|
|
}
|
|
#endif
|
|
|
|
void
|
|
InOrderDynInst::prefetch(Addr addr, unsigned flags)
|
|
{
|
|
cpu->prefetch(this);
|
|
}
|
|
|
|
void
|
|
InOrderDynInst::writeHint(Addr addr, int size, unsigned flags)
|
|
{
|
|
cpu->writeHint(this);
|
|
}
|
|
|
|
/**
|
|
* @todo Need to find a way to get the cache block size here.
|
|
*/
|
|
Fault
|
|
InOrderDynInst::copySrcTranslate(Addr src)
|
|
{
|
|
// Not currently supported.
|
|
return NoFault;
|
|
}
|
|
|
|
/**
|
|
* @todo Need to find a way to get the cache block size here.
|
|
*/
|
|
Fault
|
|
InOrderDynInst::copy(Addr dest)
|
|
{
|
|
// Not currently supported.
|
|
return NoFault;
|
|
}
|
|
|
|
void
|
|
InOrderDynInst::releaseReq(ResourceRequest* req)
|
|
{
|
|
std::list<ResourceRequest*>::iterator list_it = reqList.begin();
|
|
std::list<ResourceRequest*>::iterator list_end = reqList.end();
|
|
|
|
while(list_it != list_end) {
|
|
if((*list_it)->getResIdx() == req->getResIdx() &&
|
|
(*list_it)->getSlot() == req->getSlot()) {
|
|
DPRINTF(InOrderDynInst, "[tid:%u]: [sn:%i] Done with request to %s.\n",
|
|
threadNumber, seqNum, req->res->name());
|
|
reqList.erase(list_it);
|
|
return;
|
|
}
|
|
list_it++;
|
|
}
|
|
|
|
panic("Releasing Res. Request That Isnt There!\n");
|
|
}
|
|
|
|
/** Records an integer source register being set to a value. */
|
|
void
|
|
InOrderDynInst::setIntSrc(int idx, uint64_t val)
|
|
{
|
|
DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] Source Value %i being set to %#x.\n",
|
|
threadNumber, seqNum, idx, val);
|
|
instSrc[idx].integer = val;
|
|
}
|
|
|
|
/** Records an fp register being set to a value. */
|
|
void
|
|
InOrderDynInst::setFloatSrc(int idx, FloatReg val)
|
|
{
|
|
instSrc[idx].dbl = val;
|
|
}
|
|
|
|
/** Records an fp register being set to an integer value. */
|
|
void
|
|
InOrderDynInst::setFloatRegBitsSrc(int idx, uint64_t val)
|
|
{
|
|
instSrc[idx].integer = val;
|
|
}
|
|
|
|
/** Reads a integer register. */
|
|
IntReg
|
|
InOrderDynInst::readIntRegOperand(const StaticInst *si, int idx, ThreadID tid)
|
|
{
|
|
DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] Source Value %i read as %#x.\n",
|
|
threadNumber, seqNum, idx, instSrc[idx].integer);
|
|
return instSrc[idx].integer;
|
|
}
|
|
|
|
/** Reads a FP register. */
|
|
FloatReg
|
|
InOrderDynInst::readFloatRegOperand(const StaticInst *si, int idx)
|
|
{
|
|
return instSrc[idx].dbl;
|
|
}
|
|
|
|
|
|
/** Reads a FP register as a integer. */
|
|
FloatRegBits
|
|
InOrderDynInst::readFloatRegOperandBits(const StaticInst *si, int idx)
|
|
{
|
|
return instSrc[idx].integer;
|
|
}
|
|
|
|
/** Reads a miscellaneous register. */
|
|
MiscReg
|
|
InOrderDynInst::readMiscReg(int misc_reg)
|
|
{
|
|
return this->cpu->readMiscReg(misc_reg, threadNumber);
|
|
}
|
|
|
|
/** Reads a misc. register, including any side-effects the read
|
|
* might have as defined by the architecture.
|
|
*/
|
|
MiscReg
|
|
InOrderDynInst::readMiscRegNoEffect(int misc_reg)
|
|
{
|
|
return this->cpu->readMiscRegNoEffect(misc_reg, threadNumber);
|
|
}
|
|
|
|
/** Reads a miscellaneous register. */
|
|
MiscReg
|
|
InOrderDynInst::readMiscRegOperandNoEffect(const StaticInst *si, int idx)
|
|
{
|
|
DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] Misc. Reg Source Value %i"
|
|
" read as %#x.\n", threadNumber, seqNum, idx,
|
|
instSrc[idx].integer);
|
|
return instSrc[idx].integer;
|
|
}
|
|
|
|
/** Reads a misc. register, including any side-effects the read
|
|
* might have as defined by the architecture.
|
|
*/
|
|
MiscReg
|
|
InOrderDynInst::readMiscRegOperand(const StaticInst *si, int idx)
|
|
{
|
|
// For In-Order, the side-effect of reading a register happens
|
|
// when explicitly executing a "ReadSrc" command. This simply returns
|
|
// a value.
|
|
return readMiscRegOperandNoEffect(si, idx);
|
|
}
|
|
|
|
/** Sets a misc. register. */
|
|
void
|
|
InOrderDynInst::setMiscRegOperandNoEffect(const StaticInst * si, int idx,
|
|
const MiscReg &val)
|
|
{
|
|
instResult[idx].type = Integer;
|
|
instResult[idx].val.integer = val;
|
|
instResult[idx].tick = curTick;
|
|
|
|
DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] Setting Misc Reg. Operand %i "
|
|
"being set to %#x.\n", threadNumber, seqNum, idx, val);
|
|
}
|
|
|
|
/** Sets a misc. register, including any side-effects the write
|
|
* might have as defined by the architecture.
|
|
*/
|
|
void
|
|
InOrderDynInst::setMiscRegOperand(const StaticInst *si, int idx,
|
|
const MiscReg &val)
|
|
{
|
|
// For In-Order, the side-effect of setting a register happens
|
|
// when explicitly writing back the register value. This
|
|
// simply maintains the operand value.
|
|
setMiscRegOperandNoEffect(si, idx, val);
|
|
}
|
|
|
|
MiscReg
|
|
InOrderDynInst::readRegOtherThread(unsigned reg_idx, ThreadID tid)
|
|
{
|
|
if (tid == -1) {
|
|
tid = TheISA::getTargetThread(this->cpu->tcBase(threadNumber));
|
|
}
|
|
|
|
if (reg_idx < FP_Base_DepTag) { // Integer Register File
|
|
return this->cpu->readIntReg(reg_idx, tid);
|
|
} else if (reg_idx < Ctrl_Base_DepTag) { // Float Register File
|
|
reg_idx -= FP_Base_DepTag;
|
|
return this->cpu->readFloatRegBits(reg_idx, tid);
|
|
} else {
|
|
reg_idx -= Ctrl_Base_DepTag;
|
|
return this->cpu->readMiscReg(reg_idx, tid); // Misc. Register File
|
|
}
|
|
}
|
|
|
|
/** Sets a Integer register. */
|
|
void
|
|
InOrderDynInst::setIntRegOperand(const StaticInst *si, int idx, IntReg val)
|
|
{
|
|
instResult[idx].type = Integer;
|
|
instResult[idx].val.integer = val;
|
|
instResult[idx].tick = curTick;
|
|
}
|
|
|
|
/** Sets a FP register. */
|
|
void
|
|
InOrderDynInst::setFloatRegOperand(const StaticInst *si, int idx, FloatReg val)
|
|
{
|
|
instResult[idx].val.dbl = val;
|
|
instResult[idx].type = Float;
|
|
|
|
instResult[idx].tick = curTick;
|
|
}
|
|
|
|
/** Sets a FP register as a integer. */
|
|
void
|
|
InOrderDynInst::setFloatRegOperandBits(const StaticInst *si, int idx,
|
|
FloatRegBits val)
|
|
{
|
|
instResult[idx].type = Integer;
|
|
instResult[idx].val.integer = val;
|
|
instResult[idx].tick = curTick;
|
|
}
|
|
|
|
/** Sets a misc. register. */
|
|
/* Alter this when wanting to *speculate* on Miscellaneous registers */
|
|
void
|
|
InOrderDynInst::setMiscRegNoEffect(int misc_reg, const MiscReg &val)
|
|
{
|
|
this->cpu->setMiscRegNoEffect(misc_reg, val, threadNumber);
|
|
}
|
|
|
|
/** Sets a misc. register, including any side-effects the write
|
|
* might have as defined by the architecture.
|
|
*/
|
|
/* Alter this if/when wanting to *speculate* on Miscellaneous registers */
|
|
void
|
|
InOrderDynInst::setMiscReg(int misc_reg, const MiscReg &val)
|
|
{
|
|
this->cpu->setMiscReg(misc_reg, val, threadNumber);
|
|
}
|
|
|
|
void
|
|
InOrderDynInst::setRegOtherThread(unsigned reg_idx, const MiscReg &val,
|
|
ThreadID tid)
|
|
{
|
|
if (tid == InvalidThreadID) {
|
|
tid = TheISA::getTargetThread(this->cpu->tcBase(threadNumber));
|
|
}
|
|
|
|
if (reg_idx < FP_Base_DepTag) { // Integer Register File
|
|
this->cpu->setIntReg(reg_idx, val, tid);
|
|
} else if (reg_idx < Ctrl_Base_DepTag) { // Float Register File
|
|
reg_idx -= FP_Base_DepTag;
|
|
this->cpu->setFloatRegBits(reg_idx, val, tid);
|
|
} else {
|
|
reg_idx -= Ctrl_Base_DepTag;
|
|
this->cpu->setMiscReg(reg_idx, val, tid); // Misc. Register File
|
|
}
|
|
}
|
|
|
|
void
|
|
InOrderDynInst::deallocateContext(int thread_num)
|
|
{
|
|
this->cpu->deallocateContext(thread_num);
|
|
}
|
|
|
|
void
|
|
InOrderDynInst::enableVirtProcElement(unsigned vpe)
|
|
{
|
|
this->cpu->enableVirtProcElement(vpe);
|
|
}
|
|
|
|
void
|
|
InOrderDynInst::disableVirtProcElement(unsigned vpe)
|
|
{
|
|
this->cpu->disableVirtProcElement(threadNumber, vpe);
|
|
}
|
|
|
|
void
|
|
InOrderDynInst::enableMultiThreading(unsigned vpe)
|
|
{
|
|
this->cpu->enableMultiThreading(vpe);
|
|
}
|
|
|
|
void
|
|
InOrderDynInst::disableMultiThreading(unsigned vpe)
|
|
{
|
|
this->cpu->disableMultiThreading(threadNumber, vpe);
|
|
}
|
|
|
|
template<class T>
|
|
inline Fault
|
|
InOrderDynInst::read(Addr addr, T &data, unsigned flags)
|
|
{
|
|
return cpu->read(this, addr, data, flags);
|
|
}
|
|
|
|
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
|
|
|
template
|
|
Fault
|
|
InOrderDynInst::read(Addr addr, uint64_t &data, unsigned flags);
|
|
|
|
template
|
|
Fault
|
|
InOrderDynInst::read(Addr addr, uint32_t &data, unsigned flags);
|
|
|
|
template
|
|
Fault
|
|
InOrderDynInst::read(Addr addr, uint16_t &data, unsigned flags);
|
|
|
|
template
|
|
Fault
|
|
InOrderDynInst::read(Addr addr, uint8_t &data, unsigned flags);
|
|
|
|
#endif //DOXYGEN_SHOULD_SKIP_THIS
|
|
|
|
template<>
|
|
Fault
|
|
InOrderDynInst::read(Addr addr, double &data, unsigned flags)
|
|
{
|
|
return read(addr, *(uint64_t*)&data, flags);
|
|
}
|
|
|
|
template<>
|
|
Fault
|
|
InOrderDynInst::read(Addr addr, float &data, unsigned flags)
|
|
{
|
|
return read(addr, *(uint32_t*)&data, flags);
|
|
}
|
|
|
|
template<>
|
|
Fault
|
|
InOrderDynInst::read(Addr addr, int32_t &data, unsigned flags)
|
|
{
|
|
return read(addr, (uint32_t&)data, flags);
|
|
}
|
|
|
|
template<class T>
|
|
inline Fault
|
|
InOrderDynInst::write(T data, Addr addr, unsigned flags, uint64_t *res)
|
|
{
|
|
//memcpy(memData, gtoh(data), sizeof(T));
|
|
storeData = data;
|
|
|
|
DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] Setting store data to %#x.\n",
|
|
threadNumber, seqNum, memData);
|
|
return cpu->write(this, data, addr, flags, res);
|
|
}
|
|
|
|
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
|
template
|
|
Fault
|
|
InOrderDynInst::write(uint64_t data, Addr addr,
|
|
unsigned flags, uint64_t *res);
|
|
|
|
template
|
|
Fault
|
|
InOrderDynInst::write(uint32_t data, Addr addr,
|
|
unsigned flags, uint64_t *res);
|
|
|
|
template
|
|
Fault
|
|
InOrderDynInst::write(uint16_t data, Addr addr,
|
|
unsigned flags, uint64_t *res);
|
|
|
|
template
|
|
Fault
|
|
InOrderDynInst::write(uint8_t data, Addr addr,
|
|
unsigned flags, uint64_t *res);
|
|
|
|
#endif //DOXYGEN_SHOULD_SKIP_THIS
|
|
|
|
template<>
|
|
Fault
|
|
InOrderDynInst::write(double data, Addr addr, unsigned flags, uint64_t *res)
|
|
{
|
|
return write(*(uint64_t*)&data, addr, flags, res);
|
|
}
|
|
|
|
template<>
|
|
Fault
|
|
InOrderDynInst::write(float data, Addr addr, unsigned flags, uint64_t *res)
|
|
{
|
|
return write(*(uint32_t*)&data, addr, flags, res);
|
|
}
|
|
|
|
|
|
template<>
|
|
Fault
|
|
InOrderDynInst::write(int32_t data, Addr addr, unsigned flags, uint64_t *res)
|
|
{
|
|
return write((uint32_t)data, addr, flags, res);
|
|
}
|
|
|
|
|
|
void
|
|
InOrderDynInst::dump()
|
|
{
|
|
cprintf("T%d : %#08d `", threadNumber, PC);
|
|
cout << staticInst->disassemble(PC);
|
|
cprintf("'\n");
|
|
}
|
|
|
|
void
|
|
InOrderDynInst::dump(std::string &outstring)
|
|
{
|
|
std::ostringstream s;
|
|
s << "T" << threadNumber << " : 0x" << PC << " "
|
|
<< staticInst->disassemble(PC);
|
|
|
|
outstring = s.str();
|
|
}
|
|
|
|
|
|
#define NOHASH
|
|
#ifndef NOHASH
|
|
|
|
#include "base/hashmap.hh"
|
|
|
|
unsigned int MyHashFunc(const InOrderDynInst *addr)
|
|
{
|
|
unsigned a = (unsigned)addr;
|
|
unsigned hash = (((a >> 14) ^ ((a >> 2) & 0xffff))) & 0x7FFFFFFF;
|
|
|
|
return hash;
|
|
}
|
|
|
|
typedef m5::hash_map<const InOrderDynInst *, const InOrderDynInst *, MyHashFunc>
|
|
my_hash_t;
|
|
|
|
my_hash_t thishash;
|
|
#endif
|