Initial light-weight OoO CPU checkin, along with gcc-3.4 fixes.

SConscript:
    Include new files.
arch/alpha/isa_desc:
    Make the eaCompPtr and memAccPtr non-const so that execute() can be called on them.
arch/alpha/isa_traits.hh:
    Add enum for total number of data registers.
arch/isa_parser.py:
base/traceflags.py:
    Include new light-weight OoO CPU model.
cpu/base_dyn_inst.cc:
cpu/base_dyn_inst.hh:
    Changes to abstract more away from the base dyn inst class.
cpu/beta_cpu/2bit_local_pred.cc:
cpu/beta_cpu/2bit_local_pred.hh:
cpu/beta_cpu/tournament_pred.cc:
cpu/beta_cpu/tournament_pred.hh:
    Remove redundant SatCounter class.
cpu/beta_cpu/alpha_dyn_inst.cc:
cpu/beta_cpu/alpha_full_cpu.cc:
cpu/beta_cpu/alpha_full_cpu.hh:
cpu/beta_cpu/bpred_unit.cc:
cpu/beta_cpu/inst_queue.cc:
cpu/beta_cpu/mem_dep_unit.cc:
cpu/beta_cpu/ras.cc:
cpu/beta_cpu/rename_map.cc:
cpu/beta_cpu/rename_map.hh:
cpu/beta_cpu/rob.cc:
    Fix for gcc-3.4
cpu/beta_cpu/alpha_dyn_inst.hh:
cpu/beta_cpu/alpha_dyn_inst_impl.hh:
    Fixes for gcc-3.4.
    Include more variables and functions that are specific to AlphaDynInst which were once in BaseDynInst.
cpu/beta_cpu/alpha_full_cpu_builder.cc:
    Make params match the current params inherited from BaseCPU.
cpu/beta_cpu/alpha_full_cpu_impl.hh:
    Fixes for gcc-3.4
cpu/beta_cpu/full_cpu.cc:
    Use new params pointer in BaseCPU.
    Fix for gcc-3.4.
cpu/beta_cpu/full_cpu.hh:
    Use new params class from BaseCPU.
cpu/beta_cpu/iew_impl.hh:
    Remove unused function.
cpu/simple_cpu/simple_cpu.cc:
    Remove unused global variable.
cpu/static_inst.hh:
    Include OoODynInst for new lightweight OoO CPU

--HG--
extra : convert_revision : 34d9f2e64ca0313377391e0d059bf09c040286fa
This commit is contained in:
Kevin Lim 2005-02-25 18:00:49 -05:00
parent e8a564b0fd
commit 5c4714c1a9
37 changed files with 1324 additions and 602 deletions

View file

@ -51,6 +51,7 @@ base_sources = Split('''
arch/alpha/full_cpu_exec.cc
arch/alpha/faults.cc
arch/alpha/isa_traits.cc
arch/alpha/ooo_cpu_exec.cc
base/circlebuf.cc
base/copyright.cc
@ -114,6 +115,7 @@ base_sources = Split('''
cpu/beta_cpu/rename.cc
cpu/beta_cpu/rename_map.cc
cpu/beta_cpu/rob.cc
cpu/beta_cpu/sat_counter.cc
cpu/beta_cpu/store_set.cc
cpu/beta_cpu/tournament_pred.cc
cpu/fast_cpu/fast_cpu.cc
@ -136,30 +138,34 @@ base_sources = Split('''
cpu/full_cpu/ls_queue.cc
cpu/full_cpu/machine_queue.cc
cpu/full_cpu/pc_sample_profile.cc
cpu/full_cpu/pipetrace.cc
cpu/full_cpu/readyq.cc
cpu/full_cpu/reg_info.cc
cpu/full_cpu/rob_station.cc
cpu/full_cpu/spec_memory.cc
cpu/full_cpu/spec_state.cc
cpu/full_cpu/storebuffer.cc
cpu/full_cpu/writeback.cc
cpu/full_cpu/iq/iq_station.cc
cpu/full_cpu/iq/iqueue.cc
cpu/full_cpu/iq/segmented/chain_info.cc
cpu/full_cpu/iq/segmented/chain_wire.cc
cpu/full_cpu/iq/segmented/iq_seg.cc
cpu/full_cpu/iq/segmented/iq_segmented.cc
cpu/full_cpu/iq/segmented/seg_chain.cc
cpu/full_cpu/iq/seznec/iq_seznec.cc
cpu/full_cpu/iq/standard/iq_standard.cc
cpu/sampling_cpu/sampling_cpu.cc
cpu/simple_cpu/simple_cpu.cc
cpu/inorder_cpu/inorder_cpu.cc
cpu/trace/reader/mem_trace_reader.cc
cpu/trace/reader/ibm_reader.cc
cpu/trace/reader/itx_reader.cc
cpu/trace/reader/m5_reader.cc
cpu/full_cpu/pipetrace.cc
cpu/full_cpu/readyq.cc
cpu/full_cpu/reg_info.cc
cpu/full_cpu/rob_station.cc
cpu/full_cpu/spec_memory.cc
cpu/full_cpu/spec_state.cc
cpu/full_cpu/storebuffer.cc
cpu/full_cpu/writeback.cc
cpu/full_cpu/iq/iq_station.cc
cpu/full_cpu/iq/iqueue.cc
cpu/full_cpu/iq/segmented/chain_info.cc
cpu/full_cpu/iq/segmented/chain_wire.cc
cpu/full_cpu/iq/segmented/iq_seg.cc
cpu/full_cpu/iq/segmented/iq_segmented.cc
cpu/full_cpu/iq/segmented/seg_chain.cc
cpu/full_cpu/iq/seznec/iq_seznec.cc
cpu/full_cpu/iq/standard/iq_standard.cc
cpu/inorder_cpu/inorder_cpu.cc
cpu/ooo_cpu/ea_list.cc
cpu/ooo_cpu/ooo_cpu.cc
cpu/ooo_cpu/ooo_dyn_inst.cc
cpu/ooo_cpu/ooo_sim_obj.cc
cpu/sampling_cpu/sampling_cpu.cc
cpu/simple_cpu/simple_cpu.cc
cpu/trace/reader/mem_trace_reader.cc
cpu/trace/reader/ibm_reader.cc
cpu/trace/reader/itx_reader.cc
cpu/trace/reader/m5_reader.cc
mem/base_hier.cc
mem/base_mem.cc
@ -390,7 +396,8 @@ env.Command(Split('''arch/alpha/decoder.cc
arch/alpha/fast_cpu_exec.cc
arch/alpha/simple_cpu_exec.cc
arch/alpha/inorder_cpu_exec.cc
arch/alpha/full_cpu_exec.cc'''),
arch/alpha/full_cpu_exec.cc
arch/alpha/ooo_cpu_exec.cc'''),
Split('''arch/alpha/isa_desc
arch/isa_parser.py'''),
'$SRCDIR/arch/isa_parser.py $SOURCE $TARGET.dir arch/alpha')

View file

@ -738,9 +738,9 @@ output header {{
/// Memory request flags. See mem_req_base.hh.
unsigned memAccessFlags;
/// Pointer to EAComp object.
const StaticInstPtr<AlphaISA> eaCompPtr;
StaticInstPtr<AlphaISA> eaCompPtr;
/// Pointer to MemAcc object.
const StaticInstPtr<AlphaISA> memAccPtr;
StaticInstPtr<AlphaISA> memAccPtr;
/// Constructor
Memory(const char *mnem, MachInst _machInst, OpClass __opClass,
@ -755,8 +755,8 @@ output header {{
public:
const StaticInstPtr<AlphaISA> &eaCompInst() const { return eaCompPtr; }
const StaticInstPtr<AlphaISA> &memAccInst() const { return memAccPtr; }
StaticInstPtr<AlphaISA> &eaCompInst() { return eaCompPtr; }
StaticInstPtr<AlphaISA> &memAccInst() { return memAccPtr; }
};
/**

View file

@ -148,6 +148,10 @@ static const Addr PageOffset = PageBytes - 1;
NumIntRegs + NumFloatRegs + NumMiscRegs + NumInternalProcRegs
};
enum {
TotalDataRegs = NumIntRegs + NumFloatRegs
};
typedef union {
IntReg intreg;
FloatReg fpreg;

View file

@ -642,6 +642,9 @@ CpuModel('FullCPU', 'full_cpu_exec.cc',
CpuModel('AlphaFullCPU', 'alpha_full_cpu_exec.cc',
'#include "cpu/beta_cpu/alpha_dyn_inst.hh"',
{ 'CPU_exec_context': 'AlphaDynInst<AlphaSimpleImpl>' })
CpuModel('OoOCPU', 'ooo_cpu_exec.cc',
'#include "cpu/ooo_cpu/ooo_dyn_inst.hh"',
{ 'CPU_exec_context': 'OoODynInst<OoOImpl>' })
# Expand template with CPU-specific references into a dictionary with
# an entry for each CPU model name. The entry key is the model name

View file

@ -138,7 +138,8 @@ baseFlags = [
'MemDepUnit',
'DynInst',
'FullCPU',
'CommitRate'
'CommitRate',
'OoOCPU'
]
#

View file

@ -26,8 +26,8 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __BASE_DYN_INST_CC__
#define __BASE_DYN_INST_CC__
#ifndef __CPU_BASE_DYN_INST_CC__
#define __CPU_BASE_DYN_INST_CC__
#include <iostream>
#include <string>
@ -43,6 +43,8 @@
#include "cpu/base_dyn_inst.hh"
#include "cpu/beta_cpu/alpha_impl.hh"
#include "cpu/beta_cpu/alpha_full_cpu.hh"
#include "cpu/ooo_cpu/ooo_impl.hh"
#include "cpu/ooo_cpu/ooo_cpu.hh"
using namespace std;
@ -74,90 +76,56 @@ BaseDynInst<Impl>::BaseDynInst(MachInst machInst, Addr inst_PC,
FullCPU *cpu)
: staticInst(machInst), traceData(NULL), cpu(cpu), xc(cpu->xcBase())
{
DPRINTF(FullCPU, "DynInst: Creating new DynInst.\n");
effAddr = MemReq::inval_addr;
physEffAddr = MemReq::inval_addr;
readyRegs = 0;
seqNum = seq_num;
// specMemWrite = false;
canIssue = false;
issued = false;
executed = false;
canCommit = false;
squashed = false;
squashedInIQ = false;
blockingInst = false;
recoverInst = false;
specMode = false;
// btbMissed = false;
// Eventually make this a parameter.
threadNumber = 0;
// Also make this a parameter.
specMode = true;
// Also make this a parameter, or perhaps get it from xc or cpu.
asid = 0;
// Initialize the fault to be unimplemented opcode.
fault = Unimplemented_Opcode_Fault;
PC = inst_PC;
nextPC = PC + sizeof(MachInst);
predPC = pred_PC;
// 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.
for (int i = 0; i < staticInst->numDestRegs(); i++)
{
_destRegIdx[i] = staticInst->destRegIdx(i);
}
for (int i = 0; i < staticInst->numSrcRegs(); i++)
{
_srcRegIdx[i] = staticInst->srcRegIdx(i);
_readySrcRegIdx[i] = 0;
}
++instcount;
// assert(instcount < 50);
DPRINTF(FullCPU, "DynInst: Instruction created. Instcount=%i\n",
instcount);
initVars();
}
template <class Impl>
BaseDynInst<Impl>::BaseDynInst(StaticInstPtr<ISA> &_staticInst)
: staticInst(_staticInst), traceData(NULL)
{
initVars();
}
template <class Impl>
void
BaseDynInst<Impl>::initVars()
{
effAddr = MemReq::inval_addr;
physEffAddr = MemReq::inval_addr;
// specMemWrite = false;
readyRegs = 0;
completed = false;
canIssue = false;
issued = false;
executed = false;
canCommit = false;
squashed = false;
squashedInIQ = false;
eaCalcDone = false;
blockingInst = false;
recoverInst = false;
specMode = false;
// btbMissed = false;
// 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.
for (int i = 0; i < staticInst->numDestRegs(); i++)
{
_destRegIdx[i] = staticInst->destRegIdx(i);
}
// Eventually make this a parameter.
threadNumber = 0;
for (int i = 0; i < staticInst->numSrcRegs(); i++)
{
_srcRegIdx[i] = staticInst->srcRegIdx(i);
}
// Also make this a parameter, or perhaps get it from xc or cpu.
asid = 0;
// Initialize the fault to be unimplemented opcode.
fault = Unimplemented_Opcode_Fault;
++instcount;
DPRINTF(FullCPU, "DynInst: Instruction created. Instcount=%i\n",
instcount);
}
template <class Impl>
@ -173,14 +141,14 @@ BaseDynInst<Impl>::~BaseDynInst()
DPRINTF(FullCPU, "DynInst: Instruction destroyed. Instcount=%i\n",
instcount);
}
/*
template <class Impl>
FunctionalMemory *
BaseDynInst<Impl>::getMemory(void)
{
return xc->mem;
}
/*
template <class Impl>
IntReg *
BaseDynInst<Impl>::getIntegerRegs(void)
@ -395,10 +363,35 @@ BaseDynInst<Impl>::mem_access(mem_cmd cmd, Addr addr, void *p, int nbytes)
#endif
template <class Impl>
bool
BaseDynInst<Impl>::eaSrcsReady()
{
// For now I am assuming that src registers 1..n-1 are the ones that the
// EA calc depends on. (i.e. src reg 0 is the source of the data to be
// stored)
// StaticInstPtr<ISA> eaInst = staticInst->eaCompInst();
for (int i = 1; i < numSrcRegs(); ++i)
{
if (!_readySrcRegIdx[i])
return false;
}
return true;
}
// Forward declaration...
template class BaseDynInst<AlphaSimpleImpl>;
template class BaseDynInst<OoOImpl>;
template <>
int
BaseDynInst<AlphaSimpleImpl>::instcount = 0;
// Forward declaration...
template BaseDynInst<AlphaSimpleImpl>;
template <>
int
BaseDynInst<OoOImpl>::instcount = 0;
#endif // __BASE_DYN_INST_CC__
#endif // __CPU_BASE_DYN_INST_CC__

View file

@ -26,35 +26,32 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __BASE_DYN_INST_HH__
#define __BASE_DYN_INST_HH__
#ifndef __CPU_BASE_DYN_INST_HH__
#define __CPU_BASE_DYN_INST_HH__
#include <vector>
#include <string>
#include <vector>
#include "base/fast_alloc.hh"
#include "base/trace.hh"
#include "cpu/static_inst.hh"
#include "cpu/beta_cpu/comm.hh"
#include "cpu/exetrace.hh"
#include "cpu/full_cpu/bpred_update.hh"
#include "mem/functional_mem/main_memory.hh"
#include "cpu/full_cpu/spec_memory.hh"
#include "cpu/inst_seq.hh"
#include "cpu/full_cpu/op_class.hh"
#include "cpu/full_cpu/spec_memory.hh"
#include "cpu/full_cpu/spec_state.hh"
#include "cpu/inst_seq.hh"
#include "cpu/static_inst.hh"
#include "mem/functional_mem/main_memory.hh"
/**
* @file
* Defines a dynamic instruction context.
*/
namespace Trace {
class InstRecord;
};
// Forward declaration.
template <class blah>
template <class ISA>
class StaticInstPtr;
template <class Impl>
@ -90,8 +87,6 @@ class BaseDynInst : public FastAlloc, public RefCounted
////////////////////////////////////////////
Trace::InstRecord *traceData;
// void setCPSeq(InstSeqNum seq);
template <class T>
Fault read(Addr addr, T &data, unsigned flags);
@ -99,15 +94,12 @@ class BaseDynInst : public FastAlloc, public RefCounted
Fault write(T data, Addr addr, unsigned flags,
uint64_t *res);
IntReg *getIntegerRegs(void);
FunctionalMemory *getMemory(void);
void prefetch(Addr addr, unsigned flags);
void writeHint(Addr addr, int size, unsigned flags);
Fault copySrcTranslate(Addr src);
Fault copy(Addr dest);
// Probably should be private...
public:
/** Is this instruction valid. */
bool valid;
@ -118,6 +110,9 @@ class BaseDynInst : public FastAlloc, public RefCounted
/** How many source registers are ready. */
unsigned readyRegs;
/** Is the instruction completed. */
bool completed;
/** Can this instruction issue. */
bool canIssue;
@ -145,18 +140,9 @@ class BaseDynInst : public FastAlloc, public RefCounted
/** Is this a thread syncrhonization instruction. */
bool threadsyncWait;
/** If the BTB missed. */
// bool btbMissed;
/** The global history of this instruction (branch). */
// unsigned globalHistory;
/** The thread this instruction is from. */
short threadNumber;
/** If instruction is speculative. */
short specMode;
/** data address space ID, for loads & stores. */
short asid;
@ -190,14 +176,16 @@ class BaseDynInst : public FastAlloc, public RefCounted
/** The data to be stored. */
IntReg storeData;
/** Result of this instruction, if an integer. */
uint64_t intResult;
union Result {
uint64_t integer;
float fp;
double dbl;
};
/** Result of this instruction, if a float. */
float floatResult;
/** Result of this instruction, if a double. */
double doubleResult;
/** The result of the instruction; assumes for now that there's only one
* destination register.
*/
Result instResult;
/** PC of this instruction. */
Addr PC;
@ -214,28 +202,11 @@ class BaseDynInst : public FastAlloc, public RefCounted
/** Count of total number of dynamic instructions. */
static int instcount;
/** Did this instruction do a spec write? */
// bool specMemWrite;
private:
/** Physical register index of the destination registers of this
* instruction.
/** Whether or not the source register is ready. Not sure this should be
* here vs. the derived class.
*/
PhysRegIndex _destRegIdx[MaxInstDestRegs];
/** Physical register index of the source registers of this
* instruction.
*/
PhysRegIndex _srcRegIdx[MaxInstSrcRegs];
/** Whether or not the source register is ready. */
bool _readySrcRegIdx[MaxInstSrcRegs];
/** Physical register index of the previous producers of the
* architected destinations.
*/
PhysRegIndex _prevDestRegIdx[MaxInstDestRegs];
public:
/** BaseDynInst constructor given a binary instruction. */
BaseDynInst(MachInst inst, Addr PC, Addr Pred_PC, InstSeqNum seq_num,
@ -247,14 +218,10 @@ class BaseDynInst : public FastAlloc, public RefCounted
/** BaseDynInst destructor. */
~BaseDynInst();
#if 0
Fault
mem_access(MemCmd cmd, // Read or Write access cmd
Addr addr, // virtual address of access
void *p, // input/output buffer
int nbytes); // access size
#endif
private:
void initVars();
public:
void
trace_mem(Fault fault, // last fault
MemCmd cmd, // last command
@ -278,7 +245,7 @@ class BaseDynInst : public FastAlloc, public RefCounted
bool doneTargCalc() { return false; }
/** Returns the calculated target of the branch. */
Addr readCalcTarg() { return nextPC; }
// Addr readCalcTarg() { return nextPC; }
Addr readNextPC() { return nextPC; }
@ -296,16 +263,6 @@ class BaseDynInst : public FastAlloc, public RefCounted
/** Returns whether the instruction mispredicted. */
bool mispredicted() { return (predPC != nextPC); }
/*
unsigned readGlobalHist() {
return globalHistory;
}
void setGlobalHist(unsigned history) {
globalHistory = history;
}
*/
//
// Instruction types. Forward checks to StaticInst object.
//
@ -331,6 +288,12 @@ class BaseDynInst : public FastAlloc, public RefCounted
bool isWriteBarrier() const { return staticInst->isWriteBarrier(); }
bool isNonSpeculative() const { return staticInst->isNonSpeculative(); }
/** Returns the opclass of this instruction. */
OpClass opClass() const { return staticInst->opClass(); }
/** Returns the branch target address. */
Addr branchTarget() const { return staticInst->branchTarget(PC); }
int8_t numSrcRegs() const { return staticInst->numSrcRegs(); }
int8_t numDestRegs() const { return staticInst->numDestRegs(); }
@ -351,52 +314,9 @@ class BaseDynInst : public FastAlloc, public RefCounted
return staticInst->srcRegIdx(i);
}
/** Returns the physical register index of the i'th destination
* register.
*/
PhysRegIndex renamedDestRegIdx(int idx) const
{
return _destRegIdx[idx];
}
/** Returns the physical register index of the i'th source register. */
PhysRegIndex renamedSrcRegIdx(int idx) const
{
return _srcRegIdx[idx];
}
bool isReadySrcRegIdx(int idx) const
{
return _readySrcRegIdx[idx];
}
/** Returns the physical register index of the previous physical register
* that remapped to the same logical register index.
*/
PhysRegIndex prevDestRegIdx(int idx) const
{
return _prevDestRegIdx[idx];
}
/** Renames a destination register to a physical register. Also records
* the previous physical register that the logical register mapped to.
*/
void renameDestReg(int idx,
PhysRegIndex renamed_dest,
PhysRegIndex previous_rename)
{
_destRegIdx[idx] = renamed_dest;
_prevDestRegIdx[idx] = previous_rename;
}
/** Renames a source logical register to the physical register which
* has/will produce that logical register's result.
* @todo: add in whether or not the source register is ready.
*/
void renameSrcReg(int idx, PhysRegIndex renamed_src)
{
_srcRegIdx[idx] = renamed_src;
}
uint64_t readIntResult() { return instResult.integer; }
float readFloatResult() { return instResult.fp; }
double readDoubleResult() { return instResult.dbl; }
//Push to .cc file.
/** Records that one of the source registers is ready. */
@ -419,6 +339,15 @@ class BaseDynInst : public FastAlloc, public RefCounted
}
}
bool isReadySrcRegIdx(int idx) const
{
return this->_readySrcRegIdx[idx];
}
void setCompleted() { completed = true; }
bool isCompleted() const { return completed; }
/** Sets this instruction as ready to issue. */
void setCanIssue() { canIssue = true; }
@ -429,13 +358,13 @@ class BaseDynInst : public FastAlloc, public RefCounted
void setIssued() { issued = true; }
/** Returns whether or not this instruction has issued. */
bool isIssued() { return issued; }
bool isIssued() const { return issued; }
/** Sets this instruction as executed. */
void setExecuted() { executed = true; }
/** Returns whether or not this instruction has executed. */
bool isExecuted() { return executed; }
bool isExecuted() const { return executed; }
/** Sets this instruction as ready to commit. */
void setCanCommit() { canCommit = true; }
@ -456,82 +385,25 @@ class BaseDynInst : public FastAlloc, public RefCounted
void setSquashedInIQ() { squashedInIQ = true; }
/** Returns whether or not this instruction is squashed in the IQ. */
bool isSquashedInIQ() { return squashedInIQ; }
/** Returns the opclass of this instruction. */
OpClass opClass() const { return staticInst->opClass(); }
/** Returns whether or not the BTB missed. */
// bool btbMiss() const { return btbMissed; }
/** Returns the branch target address. */
Addr branchTarget() const { return staticInst->branchTarget(PC); }
// The register accessor methods provide the index of the
// instruction's operand (e.g., 0 or 1), not the architectural
// register index, to simplify the implementation of register
// renaming. We find the architectural register index by indexing
// into the instruction's own operand index table. Note that a
// raw pointer to the StaticInst is provided instead of a
// ref-counted StaticInstPtr to redice overhead. This is fine as
// long as these methods don't copy the pointer into any long-term
// storage (which is pretty hard to imagine they would have reason
// to do).
uint64_t readIntReg(StaticInst<ISA> *si, int idx)
{
return cpu->readIntReg(_srcRegIdx[idx]);
}
float readFloatRegSingle(StaticInst<ISA> *si, int idx)
{
return cpu->readFloatRegSingle(_srcRegIdx[idx]);
}
double readFloatRegDouble(StaticInst<ISA> *si, int idx)
{
return cpu->readFloatRegDouble(_srcRegIdx[idx]);
}
uint64_t readFloatRegInt(StaticInst<ISA> *si, int idx)
{
return cpu->readFloatRegInt(_srcRegIdx[idx]);
}
/** @todo: Make results into arrays so they can handle multiple dest
* registers.
*/
void setIntReg(StaticInst<ISA> *si, int idx, uint64_t val)
{
cpu->setIntReg(_destRegIdx[idx], val);
intResult = val;
}
void setFloatRegSingle(StaticInst<ISA> *si, int idx, float val)
{
cpu->setFloatRegSingle(_destRegIdx[idx], val);
floatResult = val;
}
void setFloatRegDouble(StaticInst<ISA> *si, int idx, double val)
{
cpu->setFloatRegDouble(_destRegIdx[idx], val);
doubleResult = val;
}
void setFloatRegInt(StaticInst<ISA> *si, int idx, uint64_t val)
{
cpu->setFloatRegInt(_destRegIdx[idx], val);
intResult = val;
}
bool isSquashedInIQ() const { return squashedInIQ; }
/** Read the PC of this instruction. */
Addr readPC() { return PC; }
const Addr readPC() const { return PC; }
/** Set the next PC of this instruction (its actual target). */
void setNextPC(uint64_t val) { nextPC = val; }
// bool misspeculating() { return cpu->misspeculating(); }
ExecContext *xcBase() { return xc; }
private:
Addr instEffAddr;
bool eaCalcDone;
public:
void setEA(Addr &ea) { instEffAddr = ea; eaCalcDone = true; }
const Addr &getEA() const { return instEffAddr; }
bool doneEACalc() { return eaCalcDone; }
bool eaSrcsReady();
};
template<class Impl>
@ -589,8 +461,6 @@ BaseDynInst<Impl>::write(T data, Addr addr, unsigned flags, uint64_t *res)
storeSize = sizeof(T);
storeData = data;
// if (specMode)
// specMemWrite = true;
MemReqPtr req = new MemReq(addr, xc, sizeof(T), flags);
@ -627,4 +497,4 @@ BaseDynInst<Impl>::write(T data, Addr addr, unsigned flags, uint64_t *res)
return fault;
}
#endif // __DYN_INST_HH__
#endif // __CPU_BASE_DYN_INST_HH__

View file

@ -1,36 +1,6 @@
#include "base/trace.hh"
#include "cpu/beta_cpu/2bit_local_pred.hh"
DefaultBP::SatCounter::SatCounter(unsigned bits)
: maxVal((1 << bits) - 1), counter(0)
{
}
DefaultBP::SatCounter::SatCounter(unsigned bits, unsigned initial_val)
: maxVal((1 << bits) - 1), counter(initial_val)
{
// Check to make sure initial value doesn't exceed the max counter value.
if (initial_val > maxVal) {
panic("BP: Initial counter value exceeds max size.");
}
}
void
DefaultBP::SatCounter::increment()
{
if(counter < maxVal) {
++counter;
}
}
void
DefaultBP::SatCounter::decrement()
{
if(counter > 0) {
--counter;
}
}
DefaultBP::DefaultBP(unsigned _localPredictorSize,
unsigned _localCtrBits,
unsigned _instShiftAmt)
@ -46,7 +16,10 @@ DefaultBP::DefaultBP(unsigned _localPredictorSize,
DPRINTF(Fetch, "Branch predictor: index mask: %#x\n", indexMask);
// Setup the array of counters for the local predictor.
localCtrs = new SatCounter[localPredictorSize](localCtrBits);
localCtrs = new SatCounter[localPredictorSize];
for (int i = 0; i < localPredictorSize; ++i)
localCtrs[i].setBits(_localCtrBits);
DPRINTF(Fetch, "Branch predictor: local predictor size: %i\n",
localPredictorSize);

View file

@ -1,8 +1,9 @@
#ifndef __2BIT_LOCAL_PRED_HH__
#define __2BIT_LOCAL_PRED_HH__
#ifndef __CPU_BETA_CPU_2BIT_LOCAL_PRED_HH__
#define __CPU_BETA_CPU_2BIT_LOCAL_PRED_HH__
// For Addr type.
#include "arch/alpha/isa_traits.hh"
#include "cpu/beta_cpu/sat_counter.hh"
class DefaultBP
{
@ -34,52 +35,6 @@ class DefaultBP
inline unsigned getLocalIndex(Addr &PC);
/**
* Private counter class for the internal saturating counters.
* Implements an n bit saturating counter and provides methods to
* increment, decrement, and read it.
* @todo Consider making this something that more closely mimics a
* built in class so you can use ++ or --.
*/
class SatCounter
{
public:
/**
* Constructor for the counter.
* @param bits How many bits the counter will have.
*/
SatCounter(unsigned bits);
/**
* Constructor for the counter.
* @param bits How many bits the counter will have.
* @param initial_val Starting value for each counter.
*/
SatCounter(unsigned bits, unsigned initial_val);
/**
* Increments the counter's current value.
*/
void increment();
/**
* Decrements the counter's current value.
*/
void decrement();
/**
* Read the counter's value.
*/
uint8_t read()
{
return counter;
}
private:
uint8_t maxVal;
uint8_t counter;
};
/** Array of counters that make up the local predictor. */
SatCounter *localCtrs;
@ -96,4 +51,4 @@ class DefaultBP
unsigned indexMask;
};
#endif // __2BIT_LOCAL_PRED_HH__
#endif // __CPU_BETA_CPU_2BIT_LOCAL_PRED_HH__

View file

@ -4,4 +4,4 @@
// Force instantiation of AlphaDynInst for all the implementations that
// are needed.
template AlphaDynInst<AlphaSimpleImpl>;
template class AlphaDynInst<AlphaSimpleImpl>;

View file

@ -47,11 +47,11 @@ class AlphaDynInst : public BaseDynInst<Impl>
/** BaseDynInst constructor given a static inst pointer. */
AlphaDynInst(StaticInstPtr<AlphaISA> &_staticInst);
/** Executes the instruction. */
/** Executes the instruction. Why the hell did I put this here? */
Fault execute()
{
fault = staticInst->execute(this, traceData);
return fault;
this->fault = this->staticInst->execute(this, this->traceData);
return this->fault;
}
public:
@ -74,6 +74,135 @@ class AlphaDynInst : public BaseDynInst<Impl>
void syscall();
#endif
private:
/** Physical register index of the destination registers of this
* instruction.
*/
PhysRegIndex _destRegIdx[MaxInstDestRegs];
/** Physical register index of the source registers of this
* instruction.
*/
PhysRegIndex _srcRegIdx[MaxInstSrcRegs];
/** Physical register index of the previous producers of the
* architected destinations.
*/
PhysRegIndex _prevDestRegIdx[MaxInstDestRegs];
public:
// The register accessor methods provide the index of the
// instruction's operand (e.g., 0 or 1), not the architectural
// register index, to simplify the implementation of register
// renaming. We find the architectural register index by indexing
// into the instruction's own operand index table. Note that a
// raw pointer to the StaticInst is provided instead of a
// ref-counted StaticInstPtr to redice overhead. This is fine as
// long as these methods don't copy the pointer into any long-term
// storage (which is pretty hard to imagine they would have reason
// to do).
uint64_t readIntReg(StaticInst<ISA> *si, int idx)
{
return this->cpu->readIntReg(_srcRegIdx[idx]);
}
float readFloatRegSingle(StaticInst<ISA> *si, int idx)
{
return this->cpu->readFloatRegSingle(_srcRegIdx[idx]);
}
double readFloatRegDouble(StaticInst<ISA> *si, int idx)
{
return this->cpu->readFloatRegDouble(_srcRegIdx[idx]);
}
uint64_t readFloatRegInt(StaticInst<ISA> *si, int idx)
{
return this->cpu->readFloatRegInt(_srcRegIdx[idx]);
}
/** @todo: Make results into arrays so they can handle multiple dest
* registers.
*/
void setIntReg(StaticInst<ISA> *si, int idx, uint64_t val)
{
this->cpu->setIntReg(_destRegIdx[idx], val);
this->instResult.integer = val;
}
void setFloatRegSingle(StaticInst<ISA> *si, int idx, float val)
{
this->cpu->setFloatRegSingle(_destRegIdx[idx], val);
this->instResult.fp = val;
}
void setFloatRegDouble(StaticInst<ISA> *si, int idx, double val)
{
this->cpu->setFloatRegDouble(_destRegIdx[idx], val);
this->instResult.dbl = val;
}
void setFloatRegInt(StaticInst<ISA> *si, int idx, uint64_t val)
{
this->cpu->setFloatRegInt(_destRegIdx[idx], val);
this->instResult.integer = val;
}
/** Returns the physical register index of the i'th destination
* register.
*/
PhysRegIndex renamedDestRegIdx(int idx) const
{
return _destRegIdx[idx];
}
/** Returns the physical register index of the i'th source register. */
PhysRegIndex renamedSrcRegIdx(int idx) const
{
return _srcRegIdx[idx];
}
/** Returns the physical register index of the previous physical register
* that remapped to the same logical register index.
*/
PhysRegIndex prevDestRegIdx(int idx) const
{
return _prevDestRegIdx[idx];
}
/** Renames a destination register to a physical register. Also records
* the previous physical register that the logical register mapped to.
*/
void renameDestReg(int idx,
PhysRegIndex renamed_dest,
PhysRegIndex previous_rename)
{
_destRegIdx[idx] = renamed_dest;
_prevDestRegIdx[idx] = previous_rename;
}
/** Renames a source logical register to the physical register which
* has/will produce that logical register's result.
* @todo: add in whether or not the source register is ready.
*/
void renameSrcReg(int idx, PhysRegIndex renamed_src)
{
_srcRegIdx[idx] = renamed_src;
}
public:
Fault calcEA()
{
return this->staticInst->eaCompInst()->execute(this, this->traceData);
}
Fault memAccess()
{
return this->staticInst->memAccInst()->execute(this, this->traceData);
}
};
#endif // __CPU_BETA_CPU_ALPHA_DYN_INST_HH__

View file

@ -4,42 +4,68 @@
template <class Impl>
AlphaDynInst<Impl>::AlphaDynInst(MachInst inst, Addr PC, Addr Pred_PC,
InstSeqNum seq_num, FullCPU *cpu)
: BaseDynInst<AlphaSimpleImpl>(inst, PC, Pred_PC, seq_num, cpu)
: BaseDynInst<Impl>(inst, PC, Pred_PC, seq_num, cpu)
{
// 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.
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;
}
}
template <class Impl>
AlphaDynInst<Impl>::AlphaDynInst(StaticInstPtr<AlphaISA> &_staticInst)
: BaseDynInst<AlphaSimpleImpl>(_staticInst)
: BaseDynInst<Impl>(_staticInst)
{
// 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.
for (int i = 0; i < _staticInst->numDestRegs(); i++)
{
_destRegIdx[i] = _staticInst->destRegIdx(i);
}
for (int i = 0; i < _staticInst->numSrcRegs(); i++)
{
_srcRegIdx[i] = _staticInst->srcRegIdx(i);
}
}
template <class Impl>
uint64_t
AlphaDynInst<Impl>::readUniq()
{
return cpu->readUniq();
return this->cpu->readUniq();
}
template <class Impl>
void
AlphaDynInst<Impl>::setUniq(uint64_t val)
{
cpu->setUniq(val);
this->cpu->setUniq(val);
}
template <class Impl>
uint64_t
AlphaDynInst<Impl>::readFpcr()
{
return cpu->readFpcr();
return this->cpu->readFpcr();
}
template <class Impl>
void
AlphaDynInst<Impl>::setFpcr(uint64_t val)
{
cpu->setFpcr(val);
this->cpu->setFpcr(val);
}
#ifdef FULL_SYSTEM
@ -47,63 +73,63 @@ template <class Impl>
uint64_t
AlphaDynInst<Impl>::readIpr(int idx, Fault &fault)
{
return cpu->readIpr(idx, fault);
return this->cpu->readIpr(idx, fault);
}
template <class Impl>
Fault
AlphaDynInst<Impl>::setIpr(int idx, uint64_t val)
{
return cpu->setIpr(idx, val);
return this->cpu->setIpr(idx, val);
}
template <class Impl>
Fault
AlphaDynInst<Impl>::hwrei()
{
return cpu->hwrei();
return this->cpu->hwrei();
}
template <class Impl>
int
AlphaDynInst<Impl>::readIntrFlag()
{
return cpu->readIntrFlag();
return this->cpu->readIntrFlag();
}
template <class Impl>
void
AlphaDynInst<Impl>::setIntrFlag(int val)
{
cpu->setIntrFlag(val);
this->cpu->setIntrFlag(val);
}
template <class Impl>
bool
AlphaDynInst<Impl>::inPalMode()
{
return cpu->inPalMode();
return this->cpu->inPalMode();
}
template <class Impl>
void
AlphaDynInst<Impl>::trap(Fault fault)
{
cpu->trap(fault);
this->cpu->trap(fault);
}
template <class Impl>
bool
AlphaDynInst<Impl>::simPalCheck(int palFunc)
{
return cpu->simPalCheck(palFunc);
return this->cpu->simPalCheck(palFunc);
}
#else
template <class Impl>
void
AlphaDynInst<Impl>::syscall()
{
cpu->syscall();
this->cpu->syscall();
}
#endif

View file

@ -6,4 +6,4 @@
// Force instantiation of AlphaFullCPU for all the implemntations that are
// needed. Consider merging this and alpha_dyn_inst.cc, and maybe all
// classes that depend on a certain impl, into one file (alpha_impl.cc?).
template AlphaFullCPU<AlphaSimpleImpl>;
template class AlphaFullCPU<AlphaSimpleImpl>;

View file

@ -87,22 +87,22 @@ class AlphaFullCPU : public FullBetaCPU<Impl>
// trying to rename source/destination registers...
uint64_t readUniq()
{
return regFile.readUniq();
return this->regFile.readUniq();
}
void setUniq(uint64_t val)
{
regFile.setUniq(val);
this->regFile.setUniq(val);
}
uint64_t readFpcr()
{
return regFile.readFpcr();
return this->regFile.readFpcr();
}
void setFpcr(uint64_t val)
{
regFile.setFpcr(val);
this->regFile.setFpcr(val);
}
#ifdef FULL_SYSTEM
@ -127,13 +127,13 @@ class AlphaFullCPU : public FullBetaCPU<Impl>
// set the register.
IntReg getSyscallArg(int i)
{
return xc->regs.intRegFile[AlphaISA::ArgumentReg0 + i];
return this->xc->regs.intRegFile[AlphaISA::ArgumentReg0 + i];
}
// used to shift args for indirect syscall
void setSyscallArg(int i, IntReg val)
{
xc->regs.intRegFile[AlphaISA::ArgumentReg0 + i] = val;
this->xc->regs.intRegFile[AlphaISA::ArgumentReg0 + i] = val;
}
void setSyscallReturn(int64_t return_value)
@ -144,12 +144,12 @@ class AlphaFullCPU : public FullBetaCPU<Impl>
const int RegA3 = 19; // only place this is used
if (return_value >= 0) {
// no error
xc->regs.intRegFile[RegA3] = 0;
xc->regs.intRegFile[AlphaISA::ReturnValueReg] = return_value;
this->xc->regs.intRegFile[RegA3] = 0;
this->xc->regs.intRegFile[AlphaISA::ReturnValueReg] = return_value;
} else {
// got an error, return details
xc->regs.intRegFile[RegA3] = (IntReg) -1;
xc->regs.intRegFile[AlphaISA::ReturnValueReg] = -return_value;
this->xc->regs.intRegFile[RegA3] = (IntReg) -1;
this->xc->regs.intRegFile[AlphaISA::ReturnValueReg] = -return_value;
}
}
@ -188,7 +188,7 @@ class AlphaFullCPU : public FullBetaCPU<Impl>
#endif
Fault error;
error = mem->read(req, data);
error = this->mem->read(req, data);
data = htoa(data);
return error;
}
@ -203,7 +203,7 @@ class AlphaFullCPU : public FullBetaCPU<Impl>
// If this is a store conditional, act appropriately
if (req->flags & LOCKED) {
cregs = &xc->regs.miscRegs;
cregs = &this->xc->regs.miscRegs;
if (req->flags & UNCACHEABLE) {
// Don't update result register (see stq_c in isa_desc)
@ -241,7 +241,7 @@ class AlphaFullCPU : public FullBetaCPU<Impl>
#endif
return mem->write(req, (T)htoa(data));
return this->mem->write(req, (T)htoa(data));
}
};

View file

@ -283,10 +283,10 @@ CREATE_SIM_OBJECT(BaseFullCPU)
params.mem = mem;
params.maxInstsAnyThread = max_insts_any_thread;
params.maxInstsAllThreads = max_insts_all_threads;
params.maxLoadsAnyThread = max_loads_any_thread;
params.maxLoadsAllThreads = max_loads_all_threads;
params.max_insts_any_thread = max_insts_any_thread;
params.max_insts_all_threads = max_insts_all_threads;
params.max_loads_any_thread = max_loads_any_thread;
params.max_loads_all_threads = max_loads_all_threads;
//
// Caches

View file

@ -14,17 +14,17 @@
template <class Impl>
AlphaFullCPU<Impl>::AlphaFullCPU(Params &params)
: FullBetaCPU<AlphaSimpleImpl>(params)
: FullBetaCPU<Impl>(params)
{
DPRINTF(FullCPU, "AlphaFullCPU: Creating AlphaFullCPU object.\n");
fetch.setCPU(this);
decode.setCPU(this);
rename.setCPU(this);
iew.setCPU(this);
commit.setCPU(this);
this->fetch.setCPU(this);
this->decode.setCPU(this);
this->rename.setCPU(this);
this->iew.setCPU(this);
this->commit.setCPU(this);
rob.setCPU(this);
this->rob.setCPU(this);
}
template <class Impl>
@ -32,12 +32,12 @@ void
AlphaFullCPU<Impl>::regStats()
{
// Register stats for everything that has stats.
fullCPURegStats();
fetch.regStats();
decode.regStats();
rename.regStats();
iew.regStats();
commit.regStats();
this->fullCPURegStats();
this->fetch.regStats();
this->decode.regStats();
this->rename.regStats();
this->iew.regStats();
this->commit.regStats();
}
#ifndef FULL_SYSTEM
@ -49,25 +49,25 @@ AlphaFullCPU<Impl>::syscall()
DPRINTF(FullCPU, "AlphaFullCPU: Syscall() called.\n\n");
// Commit stage needs to run as well.
commit.tick();
this->commit.tick();
squashStages();
// Temporarily increase this by one to account for the syscall
// instruction.
++funcExeInst;
++(this->funcExeInst);
// Copy over all important state to xc once all the unrolling is done.
copyToXC();
process->syscall(xc);
this->process->syscall(this->xc);
// Copy over all important state back to CPU.
copyFromXC();
// Decrease funcExeInst by one as the normal commit will handle
// incrememnting it.
--funcExeInst;
--(this->funcExeInst);
}
// This is not a pretty function, and should only be used if it is necessary
@ -77,40 +77,40 @@ template <class Impl>
void
AlphaFullCPU<Impl>::squashStages()
{
InstSeqNum rob_head = rob.readHeadSeqNum();
InstSeqNum rob_head = this->rob.readHeadSeqNum();
// Now hack the time buffer to put this sequence number in the places
// where the stages might read it.
for (int i = 0; i < 5; ++i)
{
timeBuffer.access(-i)->commitInfo.doneSeqNum = rob_head;
this->timeBuffer.access(-i)->commitInfo.doneSeqNum = rob_head;
}
fetch.squash(rob.readHeadNextPC());
fetchQueue.advance();
this->fetch.squash(this->rob.readHeadNextPC());
this->fetchQueue.advance();
decode.squash();
decodeQueue.advance();
this->decode.squash();
this->decodeQueue.advance();
rename.squash();
renameQueue.advance();
renameQueue.advance();
this->rename.squash();
this->renameQueue.advance();
this->renameQueue.advance();
// Be sure to advance the IEW queues so that the commit stage doesn't
// try to set an instruction as completed at the same time that it
// might be deleting it.
iew.squash();
iewQueue.advance();
iewQueue.advance();
this->iew.squash();
this->iewQueue.advance();
this->iewQueue.advance();
rob.squash(rob_head);
commit.setSquashing();
this->rob.squash(rob_head);
this->commit.setSquashing();
// Now hack the time buffer to clear the sequence numbers in the places
// where the stages might read it.?
for (int i = 0; i < 5; ++i)
{
timeBuffer.access(-i)->commitInfo.doneSeqNum = 0;
this->timeBuffer.access(-i)->commitInfo.doneSeqNum = 0;
}
}
@ -126,29 +126,31 @@ AlphaFullCPU<Impl>::copyToXC()
// First loop through the integer registers.
for (int i = 0; i < AlphaISA::NumIntRegs; ++i)
{
renamed_reg = renameMap.lookup(i);
xc->regs.intRegFile[i] = regFile.readIntReg(renamed_reg);
renamed_reg = this->renameMap.lookup(i);
this->xc->regs.intRegFile[i] = this->regFile.readIntReg(renamed_reg);
DPRINTF(FullCPU, "FullCPU: Copying register %i, has data %lli.\n",
renamed_reg, regFile.intRegFile[renamed_reg]);
renamed_reg, this->regFile.intRegFile[renamed_reg]);
}
// Then loop through the floating point registers.
for (int i = 0; i < AlphaISA::NumFloatRegs; ++i)
{
renamed_reg = renameMap.lookup(i + AlphaISA::FP_Base_DepTag);
xc->regs.floatRegFile.d[i] = regFile.readFloatRegDouble(renamed_reg);
xc->regs.floatRegFile.q[i] = regFile.readFloatRegInt(renamed_reg);
renamed_reg = this->renameMap.lookup(i + AlphaISA::FP_Base_DepTag);
this->xc->regs.floatRegFile.d[i] =
this->regFile.readFloatRegDouble(renamed_reg);
this->xc->regs.floatRegFile.q[i] =
this->regFile.readFloatRegInt(renamed_reg);
}
xc->regs.miscRegs.fpcr = regFile.miscRegs.fpcr;
xc->regs.miscRegs.uniq = regFile.miscRegs.uniq;
xc->regs.miscRegs.lock_flag = regFile.miscRegs.lock_flag;
xc->regs.miscRegs.lock_addr = regFile.miscRegs.lock_addr;
this->xc->regs.miscRegs.fpcr = this->regFile.miscRegs.fpcr;
this->xc->regs.miscRegs.uniq = this->regFile.miscRegs.uniq;
this->xc->regs.miscRegs.lock_flag = this->regFile.miscRegs.lock_flag;
this->xc->regs.miscRegs.lock_addr = this->regFile.miscRegs.lock_addr;
xc->regs.pc = rob.readHeadPC();
xc->regs.npc = xc->regs.pc+4;
this->xc->regs.pc = this->rob.readHeadPC();
this->xc->regs.npc = this->xc->regs.pc+4;
xc->func_exe_inst = funcExeInst;
this->xc->func_exe_inst = this->funcExeInst;
}
// This function will probably mess things up unless the ROB is empty and
@ -162,35 +164,37 @@ AlphaFullCPU<Impl>::copyFromXC()
// First loop through the integer registers.
for (int i = 0; i < AlphaISA::NumIntRegs; ++i)
{
renamed_reg = renameMap.lookup(i);
renamed_reg = this->renameMap.lookup(i);
DPRINTF(FullCPU, "FullCPU: Copying over register %i, had data %lli, "
"now has data %lli.\n",
renamed_reg, regFile.intRegFile[renamed_reg],
xc->regs.intRegFile[i]);
renamed_reg, this->regFile.intRegFile[renamed_reg],
this->xc->regs.intRegFile[i]);
regFile.setIntReg(renamed_reg, xc->regs.intRegFile[i]);
this->regFile.setIntReg(renamed_reg, this->xc->regs.intRegFile[i]);
}
// Then loop through the floating point registers.
for (int i = 0; i < AlphaISA::NumFloatRegs; ++i)
{
renamed_reg = renameMap.lookup(i + AlphaISA::FP_Base_DepTag);
regFile.setFloatRegDouble(renamed_reg, xc->regs.floatRegFile.d[i]);
regFile.setFloatRegInt(renamed_reg, xc->regs.floatRegFile.q[i]);
renamed_reg = this->renameMap.lookup(i + AlphaISA::FP_Base_DepTag);
this->regFile.setFloatRegDouble(renamed_reg,
this->xc->regs.floatRegFile.d[i]);
this->regFile.setFloatRegInt(renamed_reg,
this->xc->regs.floatRegFile.q[i]);
}
// Then loop through the misc registers.
regFile.miscRegs.fpcr = xc->regs.miscRegs.fpcr;
regFile.miscRegs.uniq = xc->regs.miscRegs.uniq;
regFile.miscRegs.lock_flag = xc->regs.miscRegs.lock_flag;
regFile.miscRegs.lock_addr = xc->regs.miscRegs.lock_addr;
this->regFile.miscRegs.fpcr = this->xc->regs.miscRegs.fpcr;
this->regFile.miscRegs.uniq = this->xc->regs.miscRegs.uniq;
this->regFile.miscRegs.lock_flag = this->xc->regs.miscRegs.lock_flag;
this->regFile.miscRegs.lock_addr = this->xc->regs.miscRegs.lock_addr;
// Then finally set the PC and the next PC.
// regFile.pc = xc->regs.pc;
// regFile.npc = xc->regs.npc;
funcExeInst = xc->func_exe_inst;
this->funcExeInst = this->xc->func_exe_inst;
}
#ifdef FULL_SYSTEM

View file

@ -3,4 +3,4 @@
#include "cpu/beta_cpu/alpha_impl.hh"
#include "cpu/beta_cpu/alpha_dyn_inst.hh"
template TwobitBPredUnit<AlphaSimpleImpl>;
template class TwobitBPredUnit<AlphaSimpleImpl>;

View file

@ -15,22 +15,10 @@
using namespace std;
#ifdef FULL_SYSTEM
BaseFullCPU::BaseFullCPU(Params &params)
: BaseCPU(params.name, params.numberOfThreads,
params.maxInstsAnyThread, params.maxInstsAllThreads,
params.maxLoadsAnyThread, params.maxLoadsAllThreads,
params._system, params.freq)
: BaseCPU(&params)
{
}
#else
BaseFullCPU::BaseFullCPU(Params &params)
: BaseCPU(params.name, params.numberOfThreads,
params.maxInstsAnyThread, params.maxInstsAllThreads,
params.maxLoadsAnyThread, params.maxLoadsAllThreads)
{
}
#endif // FULL_SYSTEM
template <class Impl>
FullBetaCPU<Impl>::TickEvent::TickEvent(FullBetaCPU<Impl> *c)
@ -515,6 +503,6 @@ FullBetaCPU<Impl>::wakeDependents(DynInstPtr &inst)
}
// Forward declaration of FullBetaCPU.
template FullBetaCPU<AlphaSimpleImpl>;
template class FullBetaCPU<AlphaSimpleImpl>;
#endif // __SIMPLE_FULL_CPU_HH__

View file

@ -27,27 +27,7 @@ class BaseFullCPU : public BaseCPU
{
//Stuff that's pretty ISA independent will go here.
public:
class Params
{
public:
#ifdef FULL_SYSTEM
std::string name;
int numberOfThreads;
Counter maxInstsAnyThread;
Counter maxInstsAllThreads;
Counter maxLoadsAnyThread;
Counter maxLoadsAllThreads;
System *_system;
Tick freq;
#else
std::string name;
int numberOfThreads;
Counter maxInstsAnyThread;
Counter maxInstsAllThreads;
Counter maxLoadsAnyThread;
Counter maxLoadsAllThreads;
#endif // FULL_SYSTEM
};
typedef BaseCPU::Params Params;
#ifdef FULL_SYSTEM
BaseFullCPU(Params &params);

View file

@ -244,10 +244,10 @@ SimpleIEW<Impl, IQ>::squashDueToBranch(DynInstPtr &inst)
// Also send PC update information back to prior stages.
toCommit->squashedSeqNum = inst->seqNum;
toCommit->mispredPC = inst->readPC();
toCommit->nextPC = inst->readCalcTarg();
toCommit->nextPC = inst->readNextPC();
toCommit->branchMispredict = true;
// Prediction was incorrect, so send back inverse.
toCommit->branchTaken = inst->readCalcTarg() !=
toCommit->branchTaken = inst->readNextPC() !=
(inst->readPC() + sizeof(MachInst));
}
@ -265,7 +265,7 @@ SimpleIEW<Impl, IQ>::squashDueToMem(DynInstPtr &inst)
toCommit->squash = true;
// Also send PC update information back to prior stages.
toCommit->squashedSeqNum = inst->seqNum;
toCommit->nextPC = inst->readCalcTarg();
toCommit->nextPC = inst->readNextPC();
}
template <class Impl, class IQ>

View file

@ -4,7 +4,8 @@
#include "cpu/beta_cpu/inst_queue_impl.hh"
// Force instantiation of InstructionQueue.
template InstructionQueue<AlphaSimpleImpl>;
template class InstructionQueue<AlphaSimpleImpl>;
template<>
unsigned
InstructionQueue<AlphaSimpleImpl>::DependencyEntry::mem_alloc_counter = 0;

View file

@ -6,4 +6,4 @@
// Force instantation of memory dependency unit using store sets and
// AlphaSimpleImpl.
template MemDepUnit<StoreSet, AlphaSimpleImpl>;
template class MemDepUnit<StoreSet, AlphaSimpleImpl>;

View file

@ -4,7 +4,10 @@ ReturnAddrStack::ReturnAddrStack(unsigned _numEntries)
: numEntries(_numEntries), usedEntries(0),
tos(0)
{
addrStack = new Addr[numEntries](0);
addrStack = new Addr[numEntries];
for (int i = 0; i < numEntries; ++i)
addrStack[i] = 0;
}
void

View file

@ -1,6 +1,10 @@
#include <vector>
#include "cpu/beta_cpu/rename_map.hh"
using namespace std;
// Todo: Consider making functions inline. Avoid having things that are
// using the zero register or misc registers from adding on the registers
// to the free list. Possibly remove the direct communication between

View file

@ -64,8 +64,8 @@ class SimpleRenameMap
void setEntry(RegIndex arch_reg, PhysRegIndex renamed_reg);
void squash(vector<RegIndex> freed_regs,
vector<UnmapInfo> unmaps);
void squash(std::vector<RegIndex> freed_regs,
std::vector<UnmapInfo> unmaps);
int numFreeEntries();

View file

@ -4,4 +4,4 @@
#include "cpu/beta_cpu/rob_impl.hh"
// Force instantiation of InstructionQueue.
template ROB<AlphaSimpleImpl>;
template class ROB<AlphaSimpleImpl>;

View file

@ -0,0 +1,43 @@
#include "base/misc.hh"
#include "cpu/beta_cpu/sat_counter.hh"
SatCounter::SatCounter()
: maxVal(0), counter(0)
{
}
SatCounter::SatCounter(unsigned bits)
: maxVal((1 << bits) - 1), counter(0)
{
}
SatCounter::SatCounter(unsigned bits, unsigned initial_val)
: maxVal((1 << bits) - 1), counter(initial_val)
{
// Check to make sure initial value doesn't exceed the max counter value.
if (initial_val > maxVal) {
panic("BP: Initial counter value exceeds max size.");
}
}
void
SatCounter::setBits(unsigned bits)
{
maxVal = (1 << bits) - 1;
}
void
SatCounter::increment()
{
if(counter < maxVal) {
++counter;
}
}
void
SatCounter::decrement()
{
if(counter > 0) {
--counter;
}
}

View file

@ -0,0 +1,62 @@
#ifndef __CPU_BETA_CPU_SAT_COUNTER_HH__
#define __CPU_BETA_CPU_SAT_COUNTER_HH__
#include <stdint.h>
/**
* Private counter class for the internal saturating counters.
* Implements an n bit saturating counter and provides methods to
* increment, decrement, and read it.
* @todo Consider making this something that more closely mimics a
* built in class so you can use ++ or --.
*/
class SatCounter
{
public:
/**
* Constructor for the counter.
*/
SatCounter();
/**
* Constructor for the counter.
* @param bits How many bits the counter will have.
*/
SatCounter(unsigned bits);
/**
* Constructor for the counter.
* @param bits How many bits the counter will have.
* @param initial_val Starting value for each counter.
*/
SatCounter(unsigned bits, unsigned initial_val);
/**
* Sets the number of bits.
*/
void setBits(unsigned bits);
/**
* Increments the counter's current value.
*/
void increment();
/**
* Decrements the counter's current value.
*/
void decrement();
/**
* Read the counter's value.
*/
const uint8_t read() const
{
return counter;
}
private:
uint8_t maxVal;
uint8_t counter;
};
#endif // __CPU_BETA_CPU_SAT_COUNTER_HH__

View file

@ -1,35 +1,5 @@
#include "cpu/beta_cpu/tournament_pred.hh"
TournamentBP::SatCounter::SatCounter(unsigned bits)
: maxVal((1 << bits) - 1), counter(0)
{
}
TournamentBP::SatCounter::SatCounter(unsigned bits, unsigned initial_val)
: maxVal((1 << bits) - 1), counter(initial_val)
{
// Check to make sure initial value doesn't exceed the max counter value.
if (initial_val > maxVal) {
panic("BP: Initial counter value exceeds max size.");
}
}
void
TournamentBP::SatCounter::increment()
{
if (counter < maxVal) {
++counter;
}
}
void
TournamentBP::SatCounter::decrement()
{
if (counter > 0) {
--counter;
}
}
TournamentBP::TournamentBP(unsigned _local_predictor_size,
unsigned _local_ctr_bits,
unsigned _local_history_table_size,
@ -54,21 +24,36 @@ TournamentBP::TournamentBP(unsigned _local_predictor_size,
//Should do checks here to make sure sizes are correct (powers of 2)
//Setup the array of counters for the local predictor
local_ctrs = new SatCounter[local_predictor_size](local_ctr_bits);
local_ctrs = new SatCounter[local_predictor_size];
for (int i = 0; i < local_predictor_size; ++i)
local_ctrs[i].setBits(local_ctr_bits);
//Setup the history table for the local table
local_history_table = new unsigned[local_history_table_size](0);
local_history_table = new unsigned[local_history_table_size];
for (int i = 0; i < local_history_table_size; ++i)
local_history_table[i] = 0;
// Setup the local history mask
localHistoryMask = (1 << local_history_bits) - 1;
//Setup the array of counters for the global predictor
global_ctrs = new SatCounter[global_predictor_size](global_ctr_bits);
global_ctrs = new SatCounter[global_predictor_size];
for (int i = 0; i < global_predictor_size; ++i)
global_ctrs[i].setBits(global_ctr_bits);
//Clear the global history
global_history = 0;
// Setup the global history mask
globalHistoryMask = (1 << global_history_bits) - 1;
//Setup the array of counters for the choice predictor
choice_ctrs = new SatCounter[choice_predictor_size](choice_ctr_bits);
choice_ctrs = new SatCounter[choice_predictor_size];
for (int i = 0; i < choice_predictor_size; ++i)
choice_ctrs[i].setBits(choice_ctr_bits);
threshold = (1 << (local_ctr_bits - 1)) - 1;
threshold = threshold / 2;

View file

@ -1,8 +1,9 @@
#ifndef __TOURNAMENT_PRED_HH__
#define __TOURNAMENT_PRED_HH__
#ifndef __CPU_BETA_CPU_TOURNAMENT_PRED_HH__
#define __CPU_BETA_CPU_TOURNAMENT_PRED_HH__
// For Addr type.
#include "arch/alpha/isa_traits.hh"
#include "cpu/beta_cpu/sat_counter.hh"
class TournamentBP
{
@ -48,52 +49,6 @@ class TournamentBP
inline void updateHistoriesNotTaken(unsigned local_history_idx);
/**
* Private counter class for the internal saturating counters.
* Implements an n bit saturating counter and provides methods to
* increment, decrement, and read it.
* @todo Consider making this something that more closely mimics a
* built in class so you can use ++ or --.
*/
class SatCounter
{
public:
/**
* Constructor for the counter.
* @param bits How many bits the counter will have.
*/
SatCounter(unsigned bits);
/**
* Constructor for the counter.
* @param bits How many bits the counter will have.
* @param initial_val Starting value for each counter.
*/
SatCounter(unsigned bits, unsigned initial_val);
/**
* Increments the counter's current value.
*/
void increment();
/**
* Decrements the counter's current value.
*/
void decrement();
/**
* Read the counter's value.
*/
uint8_t read()
{
return counter;
}
private:
uint8_t maxVal;
uint8_t counter;
};
/** Local counters. */
SatCounter *local_ctrs;
@ -157,4 +112,4 @@ class TournamentBP
unsigned threshold;
};
#endif // __TOURNAMENT_PRED_HH__
#endif // __CPU_BETA_CPU_TOURNAMENT_PRED_HH__

50
cpu/ooo_cpu/ea_list.cc Normal file
View file

@ -0,0 +1,50 @@
#include "arch/alpha/isa_traits.hh"
#include "cpu/inst_seq.hh"
#include "cpu/ooo_cpu/ea_list.hh"
void
EAList::addAddr(const InstSeqNum &new_sn, const Addr &new_ea)
{
instEA newEA(new_sn, new_ea);
eaList.push_back(newEA);
}
void
EAList::clearAddr(const InstSeqNum &sn_to_clear, const Addr &ea_to_clear)
{
eaListIt list_it = eaList.begin();
while (list_it != eaList.end() && (*list_it).first != sn_to_clear) {
assert((*list_it).second == ea_to_clear);
}
}
bool
EAList::checkConflict(const InstSeqNum &check_sn, const Addr &check_ea) const
{
const constEAListIt list_it = eaList.begin();
while (list_it != eaList.end() && (*list_it).first < check_sn) {
if ((*list_it).second == check_ea) {
return true;
}
}
return false;
}
void
EAList::clear()
{
eaList.clear();
}
void
EAList::commit(const InstSeqNum &commit_sn)
{
while (!eaList.empty() && eaList.front().first <= commit_sn) {
eaList.pop_front();
}
}

44
cpu/ooo_cpu/ea_list.hh Normal file
View file

@ -0,0 +1,44 @@
#ifndef __CPU_EA_LIST_HH__
#define __CPU_EA_LIST_HH__
#include <list>
#include <utility>
#include "arch/alpha/isa_traits.hh"
#include "cpu/inst_seq.hh"
/**
* Simple class to hold onto a list of pairs, each pair having a memory
* instruction's sequence number and effective addr. This list can be used
* for memory disambiguation. However, if I ever want to forward results, I
* may have to use a list that holds DynInstPtrs. Hence this may change in
* the future.
*/
class EAList {
private:
typedef std::pair<InstSeqNum, Addr> instEA;
typedef std::list<instEA>::iterator eaListIt;
typedef std::list<instEA>::const_iterator constEAListIt;
std::list<instEA> eaList;
public:
EAList() { }
~EAList() { }
void addAddr(const InstSeqNum &new_sn, const Addr &new_ea);
void clearAddr(const InstSeqNum &sn_to_clear, const Addr &ea_to_clear);
/** Checks if any instructions older than check_sn have a conflicting
* address with check_ea. Note that this function does not handle the
* sequence number rolling over.
*/
bool checkConflict(const InstSeqNum &check_sn, const Addr &check_ea) const;
void clear();
void commit(const InstSeqNum &commit_sn);
};
#endif // __CPU_EA_LIST_HH__

6
cpu/ooo_cpu/ooo_cpu.cc Normal file
View file

@ -0,0 +1,6 @@
#include "cpu/ooo_cpu/ooo_cpu_impl.hh"
#include "cpu/ooo_cpu/ooo_dyn_inst.hh"
#include "cpu/ooo_cpu/ooo_impl.hh"
template class OoOCPU<OoOImpl>;

613
cpu/ooo_cpu/ooo_cpu.hh Normal file
View file

@ -0,0 +1,613 @@
/*
* Copyright (c) 2002-2005 The Regents of The University of Michigan
* 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.
*/
#ifndef __CPU_OOO_CPU_OOO_CPU_HH__
#define __CPU_OOO_CPU_OOO_CPU_HH__
#include "base/statistics.hh"
#include "cpu/base_cpu.hh"
#include "cpu/exec_context.hh"
#include "cpu/full_cpu/fu_pool.hh"
#include "cpu/ooo_cpu/ea_list.hh"
#include "cpu/pc_event.hh"
#include "cpu/static_inst.hh"
#include "mem/mem_interface.hh"
#include "sim/eventq.hh"
// forward declarations
#ifdef FULL_SYSTEM
class Processor;
class AlphaITB;
class AlphaDTB;
class PhysicalMemory;
class RemoteGDB;
class GDBListener;
#else
class Process;
#endif // FULL_SYSTEM
class Checkpoint;
class MemInterface;
namespace Trace {
class InstRecord;
}
/**
* Declaration of Out-of-Order CPU class. Basically it is a SimpleCPU with
* simple out-of-order capabilities added to it. It is still a 1 CPI machine
* (?), but is capable of handling cache misses. Basically it models having
* a ROB/IQ by only allowing a certain amount of instructions to execute while
* the cache miss is outstanding.
*/
template <class Impl>
class OoOCPU : public BaseCPU
{
private:
typedef typename Impl::DynInst DynInst;
typedef typename Impl::DynInstPtr DynInstPtr;
typedef typename Impl::ISA ISA;
public:
// main simulation loop (one cycle)
void tick();
private:
struct TickEvent : public Event
{
OoOCPU *cpu;
int width;
TickEvent(OoOCPU *c, int w);
void process();
const char *description();
};
TickEvent tickEvent;
/// Schedule tick event, regardless of its current state.
void scheduleTickEvent(int delay)
{
if (tickEvent.squashed())
tickEvent.reschedule(curTick + delay);
else if (!tickEvent.scheduled())
tickEvent.schedule(curTick + delay);
}
/// Unschedule tick event, regardless of its current state.
void unscheduleTickEvent()
{
if (tickEvent.scheduled())
tickEvent.squash();
}
private:
Trace::InstRecord *traceData;
template<typename T>
void trace_data(T data);
public:
//
enum Status {
Running,
Idle,
IcacheMissStall,
IcacheMissComplete,
DcacheMissStall,
SwitchedOut
};
private:
Status _status;
public:
void post_interrupt(int int_num, int index);
void zero_fill_64(Addr addr) {
static int warned = 0;
if (!warned) {
warn ("WH64 is not implemented");
warned = 1;
}
};
struct Params : public BaseCPU::Params
{
MemInterface *icache_interface;
MemInterface *dcache_interface;
int width;
#ifdef FULL_SYSTEM
AlphaITB *itb;
AlphaDTB *dtb;
FunctionalMemory *mem;
#else
Process *process;
#endif
int issueWidth;
};
OoOCPU(Params *params);
virtual ~OoOCPU();
private:
void copyFromXC();
public:
// execution context
ExecContext *xc;
void switchOut();
void takeOverFrom(BaseCPU *oldCPU);
#ifdef FULL_SYSTEM
Addr dbg_vtophys(Addr addr);
bool interval_stats;
#endif
// L1 instruction cache
MemInterface *icacheInterface;
// L1 data cache
MemInterface *dcacheInterface;
FuncUnitPool *fuPool;
// Refcounted pointer to the one memory request.
MemReqPtr cacheMemReq;
class ICacheCompletionEvent : public Event
{
private:
OoOCPU *cpu;
public:
ICacheCompletionEvent(OoOCPU *_cpu);
virtual void process();
virtual const char *description();
};
// Will need to create a cache completion event upon any memory miss.
ICacheCompletionEvent iCacheCompletionEvent;
class DCacheCompletionEvent : public Event
{
private:
OoOCPU *cpu;
DynInstPtr inst;
public:
DCacheCompletionEvent(OoOCPU *_cpu, DynInstPtr &_inst);
virtual void process();
virtual const char *description();
};
friend class DCacheCompletionEvent;
Status status() const { return _status; }
virtual void activateContext(int thread_num, int delay);
virtual void suspendContext(int thread_num);
virtual void deallocateContext(int thread_num);
virtual void haltContext(int thread_num);
// statistics
virtual void regStats();
virtual void resetStats();
// number of simulated instructions
Counter numInst;
Counter startNumInst;
Stats::Scalar<> numInsts;
virtual Counter totalInstructions() const
{
return numInst - startNumInst;
}
// number of simulated memory references
Stats::Scalar<> numMemRefs;
// number of simulated loads
Counter numLoad;
Counter startNumLoad;
// number of idle cycles
Stats::Average<> notIdleFraction;
Stats::Formula idleFraction;
// number of cycles stalled for I-cache misses
Stats::Scalar<> icacheStallCycles;
Counter lastIcacheStall;
// number of cycles stalled for D-cache misses
Stats::Scalar<> dcacheStallCycles;
Counter lastDcacheStall;
void processICacheCompletion();
virtual void serialize(std::ostream &os);
virtual void unserialize(Checkpoint *cp, const std::string &section);
#ifdef FULL_SYSTEM
bool validInstAddr(Addr addr) { return true; }
bool validDataAddr(Addr addr) { return true; }
int getInstAsid() { return xc->regs.instAsid(); }
int getDataAsid() { return xc->regs.dataAsid(); }
Fault translateInstReq(MemReqPtr &req)
{
return itb->translate(req);
}
Fault translateDataReadReq(MemReqPtr &req)
{
return dtb->translate(req, false);
}
Fault translateDataWriteReq(MemReqPtr &req)
{
return dtb->translate(req, true);
}
#else
bool validInstAddr(Addr addr)
{ return xc->validInstAddr(addr); }
bool validDataAddr(Addr addr)
{ return xc->validDataAddr(addr); }
int getInstAsid() { return xc->asid; }
int getDataAsid() { return xc->asid; }
Fault dummyTranslation(MemReqPtr &req)
{
#if 0
assert((req->vaddr >> 48 & 0xffff) == 0);
#endif
// put the asid in the upper 16 bits of the paddr
req->paddr = req->vaddr & ~((Addr)0xffff << sizeof(Addr) * 8 - 16);
req->paddr = req->paddr | (Addr)req->asid << sizeof(Addr) * 8 - 16;
return No_Fault;
}
Fault translateInstReq(MemReqPtr &req)
{
return dummyTranslation(req);
}
Fault translateDataReadReq(MemReqPtr &req)
{
return dummyTranslation(req);
}
Fault translateDataWriteReq(MemReqPtr &req)
{
return dummyTranslation(req);
}
#endif
template <class T>
Fault read(Addr addr, T &data, unsigned flags, DynInstPtr inst);
template <class T>
Fault write(T data, Addr addr, unsigned flags,
uint64_t *res, DynInstPtr inst);
void prefetch(Addr addr, unsigned flags)
{
// need to do this...
}
void writeHint(Addr addr, int size, unsigned flags)
{
// need to do this...
}
Fault copySrcTranslate(Addr src);
Fault copy(Addr dest);
private:
bool executeInst(DynInstPtr &inst);
void renameInst(DynInstPtr &inst);
void addInst(DynInstPtr &inst);
void commitHeadInst();
bool grabInst();
Fault fetchCacheLine();
InstSeqNum getAndIncrementInstSeq();
bool ambigMemAddr;
private:
InstSeqNum globalSeqNum;
DynInstPtr renameTable[ISA::TotalNumRegs];
DynInstPtr commitTable[ISA::TotalNumRegs];
// Might need a table of the shadow registers as well.
#ifdef FULL_SYSTEM
DynInstPtr palShadowTable[ISA::NumIntRegs];
#endif
public:
// The register accessor methods provide the index of the
// instruction's operand (e.g., 0 or 1), not the architectural
// register index, to simplify the implementation of register
// renaming. We find the architectural register index by indexing
// into the instruction's own operand index table. Note that a
// raw pointer to the StaticInst is provided instead of a
// ref-counted StaticInstPtr to redice overhead. This is fine as
// long as these methods don't copy the pointer into any long-term
// storage (which is pretty hard to imagine they would have reason
// to do).
// In the OoO case these shouldn't read from the XC but rather from the
// rename table of DynInsts. Also these likely shouldn't be called very
// often, other than when adding things into the xc during say a syscall.
uint64_t readIntReg(StaticInst<TheISA> *si, int idx)
{
return xc->readIntReg(si->srcRegIdx(idx));
}
float readFloatRegSingle(StaticInst<TheISA> *si, int idx)
{
int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
return xc->readFloatRegSingle(reg_idx);
}
double readFloatRegDouble(StaticInst<TheISA> *si, int idx)
{
int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
return xc->readFloatRegDouble(reg_idx);
}
uint64_t readFloatRegInt(StaticInst<TheISA> *si, int idx)
{
int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
return xc->readFloatRegInt(reg_idx);
}
void setIntReg(StaticInst<TheISA> *si, int idx, uint64_t val)
{
xc->setIntReg(si->destRegIdx(idx), val);
}
void setFloatRegSingle(StaticInst<TheISA> *si, int idx, float val)
{
int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
xc->setFloatRegSingle(reg_idx, val);
}
void setFloatRegDouble(StaticInst<TheISA> *si, int idx, double val)
{
int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
xc->setFloatRegDouble(reg_idx, val);
}
void setFloatRegInt(StaticInst<TheISA> *si, int idx, uint64_t val)
{
int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
xc->setFloatRegInt(reg_idx, val);
}
uint64_t readPC() { return PC; }
void setNextPC(Addr val) { nextPC = val; }
private:
Addr PC;
Addr nextPC;
unsigned issueWidth;
bool fetchRedirExcp;
bool fetchRedirBranch;
/** Mask to get a cache block's address. */
Addr cacheBlkMask;
unsigned cacheBlkSize;
Addr cacheBlkPC;
/** The cache line being fetched. */
uint8_t *cacheData;
protected:
bool cacheBlkValid;
private:
// Align an address (typically a PC) to the start of an I-cache block.
// We fold in the PISA 64- to 32-bit conversion here as well.
Addr icacheBlockAlignPC(Addr addr)
{
addr = ISA::realPCToFetchPC(addr);
return (addr & ~(cacheBlkMask));
}
unsigned instSize;
// ROB tracking stuff.
DynInstPtr robHeadPtr;
DynInstPtr robTailPtr;
unsigned robInsts;
// List of outstanding EA instructions.
protected:
EAList eaList;
public:
void branchToTarget(Addr val)
{
if (!fetchRedirExcp) {
fetchRedirBranch = true;
PC = val;
}
}
// ISA stuff:
uint64_t readUniq() { return xc->readUniq(); }
void setUniq(uint64_t val) { xc->setUniq(val); }
uint64_t readFpcr() { return xc->readFpcr(); }
void setFpcr(uint64_t val) { xc->setFpcr(val); }
#ifdef FULL_SYSTEM
uint64_t readIpr(int idx, Fault &fault) { return xc->readIpr(idx, fault); }
Fault setIpr(int idx, uint64_t val) { return xc->setIpr(idx, val); }
Fault hwrei() { return xc->hwrei(); }
int readIntrFlag() { return xc->readIntrFlag(); }
void setIntrFlag(int val) { xc->setIntrFlag(val); }
bool inPalMode() { return xc->inPalMode(); }
void ev5_trap(Fault fault) { xc->ev5_trap(fault); }
bool simPalCheck(int palFunc) { return xc->simPalCheck(palFunc); }
#else
void syscall() { xc->syscall(); }
#endif
ExecContext *xcBase() { return xc; }
};
// precise architected memory state accessor macros
template <class Impl>
template <class T>
Fault
OoOCPU<Impl>::read(Addr addr, T &data, unsigned flags, DynInstPtr inst)
{
MemReqPtr readReq = new MemReq();
readReq->xc = xc;
readReq->asid = 0;
readReq->data = new uint8_t[64];
readReq->reset(addr, sizeof(T), flags);
// translate to physical address - This might be an ISA impl call
Fault fault = translateDataReadReq(readReq);
// do functional access
if (fault == No_Fault)
fault = xc->mem->read(readReq, data);
#if 0
if (traceData) {
traceData->setAddr(addr);
if (fault == No_Fault)
traceData->setData(data);
}
#endif
// if we have a cache, do cache access too
if (fault == No_Fault && dcacheInterface) {
readReq->cmd = Read;
readReq->completionEvent = NULL;
readReq->time = curTick;
/*MemAccessResult result = */dcacheInterface->access(readReq);
if (dcacheInterface->doEvents()) {
readReq->completionEvent = new DCacheCompletionEvent(this, inst);
lastDcacheStall = curTick;
unscheduleTickEvent();
_status = DcacheMissStall;
}
}
if (!dcacheInterface && (readReq->flags & UNCACHEABLE))
recordEvent("Uncached Read");
return fault;
}
template <class Impl>
template <class T>
Fault
OoOCPU<Impl>::write(T data, Addr addr, unsigned flags,
uint64_t *res, DynInstPtr inst)
{
MemReqPtr writeReq = new MemReq();
writeReq->xc = xc;
writeReq->asid = 0;
writeReq->data = new uint8_t[64];
#if 0
if (traceData) {
traceData->setAddr(addr);
traceData->setData(data);
}
#endif
writeReq->reset(addr, sizeof(T), flags);
// translate to physical address
Fault fault = xc->translateDataWriteReq(writeReq);
// do functional access
if (fault == No_Fault)
fault = xc->write(writeReq, data);
if (fault == No_Fault && dcacheInterface) {
writeReq->cmd = Write;
memcpy(writeReq->data,(uint8_t *)&data,writeReq->size);
writeReq->completionEvent = NULL;
writeReq->time = curTick;
/*MemAccessResult result = */dcacheInterface->access(writeReq);
if (dcacheInterface->doEvents()) {
writeReq->completionEvent = new DCacheCompletionEvent(this, inst);
lastDcacheStall = curTick;
unscheduleTickEvent();
_status = DcacheMissStall;
}
}
if (res && (fault == No_Fault))
*res = writeReq->result;
if (!dcacheInterface && (writeReq->flags & UNCACHEABLE))
recordEvent("Uncached Write");
return fault;
}
#endif // __CPU_OOO_CPU_OOO_CPU_HH__

21
cpu/ooo_cpu/ooo_impl.hh Normal file
View file

@ -0,0 +1,21 @@
#ifndef __CPU_OOO_CPU_OOO_IMPL_HH__
#define __CPU_OOO_CPU_OOO_IMPL_HH__
#include "arch/alpha/isa_traits.hh"
template <class Impl>
class OoOCPU;
template <class Impl>
class OoODynInst;
struct OoOImpl {
typedef AlphaISA ISA;
typedef OoOCPU<OoOImpl> OoOCPU;
typedef OoOCPU FullCPU;
typedef OoODynInst<OoOImpl> DynInst;
typedef RefCountingPtr<DynInst> DynInstPtr;
};
#endif // __CPU_OOO_CPU_OOO_IMPL_HH__

View file

@ -562,9 +562,6 @@ SimpleCPU::dbg_vtophys(Addr addr)
}
#endif // FULL_SYSTEM
Tick save_cycle = 0;
void
SimpleCPU::processCacheCompletion()
{

View file

@ -26,8 +26,8 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __STATIC_INST_HH__
#define __STATIC_INST_HH__
#ifndef __CPU_STATIC_INST_HH__
#define __CPU_STATIC_INST_HH__
#include <bitset>
#include <string>
@ -41,11 +41,16 @@
// forward declarations
struct AlphaSimpleImpl;
struct OoOImpl;
class ExecContext;
class DynInst;
template <class Impl>
class AlphaDynInst;
template <class Impl>
class OoODynInst;
class FastCPU;
class SimpleCPU;
class InorderCPU;
@ -255,7 +260,7 @@ class StaticInst : public StaticInstBase
* obtain the dependence info (numSrcRegs and srcRegIdx[]) for
* just the EA computation.
*/
virtual const
virtual
StaticInstPtr<ISA> &eaCompInst() const { return nullStaticInstPtr; }
/**
@ -264,7 +269,7 @@ class StaticInst : public StaticInstBase
* obtain the dependence info (numSrcRegs and srcRegIdx[]) for
* just the memory access (not the EA computation).
*/
virtual const
virtual
StaticInstPtr<ISA> &memAccInst() const { return nullStaticInstPtr; }
/// The binary machine instruction.
@ -445,4 +450,4 @@ class StaticInstPtr : public RefCountingPtr<StaticInst<ISA> >
}
};
#endif // __STATIC_INST_HH__
#endif // __CPU_STATIC_INST_HH__