#include <iostream>
#include <set>
-#include <string>
#include <sstream>
+#include <string>
#include "arch/faults.hh"
+#include "base/bigint.hh"
+#include "base/cp_annotate.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 "cpu/exetrace.hh"
+#include "debug/InOrderDynInst.hh"
#include "mem/request.hh"
+#include "sim/full_system.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();
-}
+ : seqNum(seq_num), squashSeqNum(0), threadNumber(tid), asid(_asid),
+ virtProcNumber(0), staticInst(NULL), traceData(NULL), cpu(cpu),
+ thread(state), fault(NoFault), memData(NULL), loadData(0),
+ storeData(0), effAddr(0), physEffAddr(0), memReqFlags(0),
+ readyRegs(0), pc(0), predPC(0), memAddr(0), nextStage(0),
+ memTime(0), splitMemData(NULL), splitMemReq(NULL), totalSize(0),
+ split2ndSize(0), split2ndAddr(0), split2ndAccess(false),
+ split2ndDataPtr(NULL), split2ndFlags(0), splitInst(false),
+ splitFinishCnt(0), split2ndStoreDataPtr(NULL), splitInstSked(false),
+ inFrontEnd(true), frontSked(NULL), backSked(NULL),
+ squashingStage(0), predictTaken(false), procDelaySlotOnMispred(false),
+ fetchMemReq(NULL), dataMemReq(NULL), instEffAddr(0), eaCalcDone(false),
+ lqIdx(0), sqIdx(0), instListIt(NULL), onInstList(false)
+{
+ for(int i = 0; i < MaxInstSrcRegs; i++) {
+ _readySrcRegIdx[i] = false;
+ _srcRegIdx[i] = 0;
+ }
-InOrderDynInst::InOrderDynInst(StaticInstPtr &_staticInst)
- : seqNum(0), staticInst(_staticInst), traceData(NULL)
-{
- initVars();
-}
+ for(int j = 0; j < MaxInstDestRegs; j++) {
+ _destRegIdx[j] = 0;
+ _prevDestRegIdx[j] = 0;
+ }
+
+ ++instcount;
+ DPRINTF(InOrderDynInst, "DynInst: [tid:%i] [sn:%lli] Instruction created."
+ " (active insts: %i)\n", threadNumber, seqNum, instcount);
-InOrderDynInst::InOrderDynInst()
- : seqNum(0), traceData(NULL), cpu(cpu)
-{
- initVars();
}
int InOrderDynInst::instcount = 0;
+int
+InOrderDynInst::cpuId()
+{
+ return cpu->cpuId();
+}
void
-InOrderDynInst::setMachInst(ExtMachInst machInst)
+InOrderDynInst::setStaticInst(StaticInstPtr si)
{
- staticInst = StaticInst::decode(machInst, PC);
+ staticInst = si;
for (int i = 0; i < this->staticInst->numDestRegs(); i++) {
_destRegIdx[i] = this->staticInst->destRegIdx(i);
void
InOrderDynInst::initVars()
{
+ inFrontEnd = true;
+
fetchMemReq = NULL;
dataMemReq = NULL;
splitMemData = NULL;
+ split2ndAddr = 0;
split2ndAccess = false;
splitInst = false;
+ splitInstSked = false;
splitFinishCnt = 0;
effAddr = 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;
}
// Update Instruction Count for this instruction
- ++instcount;
- if (instcount > 500) {
+ if (instcount > 100) {
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);
+void
+InOrderDynInst::resetInstCount()
+{
+ instcount = 0;
}
InOrderDynInst::~InOrderDynInst()
{
- if (fetchMemReq != 0x0) {
- delete fetchMemReq;
- fetchMemReq = NULL;
- }
-
- if (dataMemReq != 0x0) {
- delete dataMemReq;
- dataMemReq = NULL;
- }
-
- if (traceData) {
+ if (traceData)
delete traceData;
- }
- if (splitMemData) {
- delete splitMemData;
- }
-
+ if (splitMemData)
+ delete [] splitMemData;
+
fault = NoFault;
--instcount;
- deleteStages();
-
- DPRINTF(InOrderDynInst, "DynInst: [tid:%i] [sn:%lli] Instruction destroyed. (active insts: %i)\n",
- threadNumber, seqNum, instcount);
+ DPRINTF(InOrderDynInst, "DynInst: [tid:%i] [sn:%lli] Instruction destroyed"
+ " (active insts: %i)\n", threadNumber, seqNum, instcount);
}
void
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()
{
}
-#if FULL_SYSTEM
-
Fault
InOrderDynInst::hwrei()
{
- panic("InOrderDynInst: hwrei: unimplemented\n");
+#if THE_ISA == ALPHA_ISA
+ // Can only do a hwrei when in pal mode.
+ if (!(this->instAddr() & 0x3))
+ return new AlphaISA::UnimplementedOpcodeFault;
+
+ // Set the next PC based on the value of the EXC_ADDR IPR.
+ AlphaISA::PCState pc = this->pcState();
+ pc.npc(this->cpu->readMiscRegNoEffect(AlphaISA::IPR_EXC_ADDR,
+ this->threadNumber));
+ this->pcState(pc);
+ if (CPA::available()) {
+ ThreadContext *tc = this->cpu->tcBase(this->threadNumber);
+ CPA::cpa()->swAutoBegin(tc, this->nextInstAddr());
+ }
+
+ // Tell CPU to clear any state it needs to if a hwrei is taken.
+ this->cpu->hwrei(this->threadNumber);
+#endif
return NoFault;
}
void
InOrderDynInst::trap(Fault fault)
{
- this->cpu->trap(fault, this->threadNumber);
+ this->cpu->trap(fault, this->threadNumber, this);
}
#endif
return this->cpu->simPalCheck(palFunc, this->threadNumber);
}
-#else
+
void
InOrderDynInst::syscall(int64_t callnum)
{
- cpu->syscall(callnum, this->threadNumber);
-}
-#endif
+ if (FullSystem)
+ panic("Syscall emulation isn't available in FS mode.\n");
-void
-InOrderDynInst::prefetch(Addr addr, unsigned flags)
-{
- cpu->prefetch(this);
+ syscallNum = callnum;
+ cpu->syscallContext(NoFault, this->threadNumber, 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;
+InOrderDynInst::setSquashInfo(unsigned stage_num)
+{
+ squashingStage = stage_num;
+
+ // If it's a fault, then we need to squash
+ // the faulting instruction too. Squash
+ // functions squash above a seqNum, so we
+ // decrement here for that case
+ if (fault != NoFault) {
+ squashSeqNum = seqNum - 1;
+ return;
+ } else
+ squashSeqNum = seqNum;
+
+#if ISA_HAS_DELAY_SLOT
+ if (staticInst && isControl()) {
+ TheISA::PCState nextPC = pc;
+ TheISA::advancePC(nextPC, staticInst);
+
+ // Check to see if we should squash after the
+ // branch or after a branch delay slot.
+ if (pc.nextInstAddr() == pc.instAddr() + sizeof(MachInst))
+ squashSeqNum = seqNum + 1;
+ else
+ squashSeqNum = seqNum;
+ }
+#endif
}
void
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());
+ DPRINTF(InOrderDynInst, "[tid:%u]: [sn:%i] Done with request "
+ "to %s.\n", threadNumber, seqNum, req->res->name());
reqList.erase(list_it);
return;
}
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;
+ DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] [src:%i] Int being set "
+ "to %#x.\n", threadNumber, seqNum, idx, val);
+ instSrc[idx].intVal = val;
}
/** Records an fp register being set to a value. */
void
InOrderDynInst::setFloatSrc(int idx, FloatReg val)
{
- instSrc[idx].dbl = val;
+ instSrc[idx].fpVal.f = val;
+ DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] [src:%i] FP being set "
+ "to %x, %08f...%08f\n", threadNumber, seqNum, idx,
+ instSrc[idx].fpVal.i, instSrc[idx].fpVal.f, val);
}
/** Records an fp register being set to an integer value. */
void
-InOrderDynInst::setFloatRegBitsSrc(int idx, uint64_t val)
+InOrderDynInst::setFloatRegBitsSrc(int idx, FloatRegBits val)
{
- instSrc[idx].integer = val;
+ instSrc[idx].fpVal.i = val;
+ DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] [src:%i] FPBits being set "
+ "to %x, %08f...%x\n", threadNumber, seqNum, idx,
+ instSrc[idx].fpVal.i, instSrc[idx].fpVal.f, 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;
+ DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] [src:%i] IntVal read as %#x.\n",
+ threadNumber, seqNum, idx, instSrc[idx].intVal);
+ return instSrc[idx].intVal;
}
/** Reads a FP register. */
FloatReg
InOrderDynInst::readFloatRegOperand(const StaticInst *si, int idx)
{
- return instSrc[idx].dbl;
+ DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] [src:%i] FPVal being read "
+ "as %x, %08f.\n", threadNumber, seqNum, idx,
+ instSrc[idx].fpVal.i, instSrc[idx].fpVal.f);
+ return instSrc[idx].fpVal.f;
}
FloatRegBits
InOrderDynInst::readFloatRegOperandBits(const StaticInst *si, int idx)
{
- return instSrc[idx].integer;
+ DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] [src:%i] FPBits being read "
+ "as %x, %08f.\n", threadNumber, seqNum, idx,
+ instSrc[idx].fpVal.i, instSrc[idx].fpVal.f);
+ return instSrc[idx].fpVal.i;
}
/** Reads a miscellaneous register. */
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);
+ DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] Misc. Reg Source Value %i"
+ " read as %#x.\n", threadNumber, seqNum, idx,
+ instSrc[idx].intVal);
+ return instSrc[idx].intVal;
}
-/** 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.
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);
+ instResult[idx].type = Integer;
+ instResult[idx].res.intVal = 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);
}
MiscReg
InOrderDynInst::setIntRegOperand(const StaticInst *si, int idx, IntReg val)
{
instResult[idx].type = Integer;
- instResult[idx].val.integer = val;
- instResult[idx].tick = curTick;
+ instResult[idx].res.intVal = val;
+ instResult[idx].tick = curTick();
+
+ DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] Setting Result Int Reg. %i "
+ "being set to %#x (result-tick:%i).\n",
+ threadNumber, seqNum, idx, val, instResult[idx].tick);
}
/** 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].res.fpVal.f = val;
+ instResult[idx].tick = curTick();
- instResult[idx].tick = curTick;
+ DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] Result Float Reg. %i "
+ "being set to %#x, %08f (result-tick:%i).\n",
+ threadNumber, seqNum, idx, val, val, instResult[idx].tick);
}
/** Sets a FP register as a integer. */
InOrderDynInst::setFloatRegOperandBits(const StaticInst *si, int idx,
FloatRegBits val)
{
- instResult[idx].type = Integer;
- instResult[idx].val.integer = val;
- instResult[idx].tick = curTick;
-}
+ instResult[idx].type = FloatBits;
+ instResult[idx].res.fpVal.i = 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);
+ DPRINTF(InOrderDynInst, "[tid:%i]: [sn:%i] Result Float Reg. Bits %i "
+ "being set to %#x (result-tick:%i).\n",
+ threadNumber, seqNum, idx, val, instResult[idx].tick);
}
/** Sets a misc. register, including any side-effects the write
this->cpu->deallocateContext(thread_num);
}
-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)
+InOrderDynInst::readMem(Addr addr, uint8_t *data,
+ unsigned size, unsigned flags)
{
- return write(*(uint64_t*)&data, addr, flags, res);
+ return cpu->read(this, addr, data, size, flags);
}
-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)
+InOrderDynInst::writeMem(uint8_t *data, unsigned size,
+ Addr addr, unsigned flags, uint64_t *res)
{
- return write((uint32_t)data, addr, flags, res);
+ return cpu->write(this, data, size, addr, flags, res);
}
void
InOrderDynInst::dump()
{
- cprintf("T%d : %#08d `", threadNumber, PC);
- cout << staticInst->disassemble(PC);
+ cprintf("T%d : %#08d `", threadNumber, pc.instAddr());
+ cout << staticInst->disassemble(pc.instAddr());
cprintf("'\n");
}
InOrderDynInst::dump(std::string &outstring)
{
std::ostringstream s;
- s << "T" << threadNumber << " : 0x" << PC << " "
- << staticInst->disassemble(PC);
+ s << "T" << threadNumber << " : " << pc << " "
+ << staticInst->disassemble(pc.instAddr());
outstring = s.str();
}
return hash;
}
-typedef m5::hash_map<const InOrderDynInst *, const InOrderDynInst *, MyHashFunc>
+typedef m5::hash_map<const InOrderDynInst *, const InOrderDynInst *,
+ MyHashFunc>
my_hash_t;
my_hash_t thishash;