Add support for "serializing" instructions that flush
execution pipeline (Alpha trapb & excb). Add support for write memory barriers (mostly impacts store buffer). Add StaticInst flag to indicate memory barriers, though this is not modeled in the pipeline yet. arch/alpha/isa_desc: Implement trapb, excb, mb, and wmb as insts with no execution effect (empty execute() function) but with flags that indicate their side effects. Also make sure every instruction that needs to go to the execute stage has a real opClass value, since we are now using No_OpClass to signal insts that can get dropped at dispatch. StaticInst::branchTarget() is now a const method. cpu/static_inst.hh: Add flags to indicate serializing insts (trapb, excb) and memory and write barriers. Also declare some StaticInst methods as const methods. dev/etherlink.hh: sim/eventq.hh: sim/serialize.cc: sim/serialize.hh: sim/sim_object.hh: Make name() return value const. --HG-- extra : convert_revision : 39520e71469fa20e0a7446b2e06b494eec17a02c
This commit is contained in:
parent
3e5070a3f1
commit
b6ff600bca
7 changed files with 52 additions and 21 deletions
|
@ -1225,7 +1225,7 @@ declare {{
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Addr branchTarget(Addr branchPC)
|
Addr branchTarget(Addr branchPC) const
|
||||||
{
|
{
|
||||||
return branchPC + 4 + disp;
|
return branchPC + 4 + disp;
|
||||||
}
|
}
|
||||||
|
@ -1287,7 +1287,7 @@ declare {{
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Addr branchTarget(ExecContext *xc)
|
Addr branchTarget(ExecContext *xc) const
|
||||||
{
|
{
|
||||||
Addr NPC = xc->readPC() + 4;
|
Addr NPC = xc->readPC() + 4;
|
||||||
uint64_t Rb = xc->readIntReg(_srcRegIdx[0]);
|
uint64_t Rb = xc->readIntReg(_srcRegIdx[0]);
|
||||||
|
@ -2330,10 +2330,6 @@ decode OPCODE default Unknown::unknown() {
|
||||||
// miscellaneous mem-format ops
|
// miscellaneous mem-format ops
|
||||||
0x18: decode MEMFUNC {
|
0x18: decode MEMFUNC {
|
||||||
format WarnUnimpl {
|
format WarnUnimpl {
|
||||||
0x0000: trapb();
|
|
||||||
0x0400: excb();
|
|
||||||
0x4000: mb();
|
|
||||||
0x4400: wmb();
|
|
||||||
0x8000: fetch();
|
0x8000: fetch();
|
||||||
0xa000: fetch_m();
|
0xa000: fetch_m();
|
||||||
0xe800: ecb();
|
0xe800: ecb();
|
||||||
|
@ -2347,6 +2343,27 @@ decode OPCODE default Unknown::unknown() {
|
||||||
|
|
||||||
format BasicOperate {
|
format BasicOperate {
|
||||||
0xc000: rpcc({{ Ra = curTick; }});
|
0xc000: rpcc({{ Ra = curTick; }});
|
||||||
|
|
||||||
|
// All of the barrier instructions below do nothing in
|
||||||
|
// their execute() methods (hence the empty code blocks).
|
||||||
|
// All of their functionality is hard-coded in the
|
||||||
|
// pipeline based on the flags IsSerializing,
|
||||||
|
// IsMemBarrier, and IsWriteBarrier. In the current
|
||||||
|
// detailed CPU model, the execute() function only gets
|
||||||
|
// called at fetch, so there's no way to generate pipeline
|
||||||
|
// behavior at any other stage. Once we go to an
|
||||||
|
// exec-in-exec CPU model we should be able to get rid of
|
||||||
|
// these flags and implement this behavior via the
|
||||||
|
// execute() methods.
|
||||||
|
|
||||||
|
// trapb is just a barrier on integer traps, where excb is
|
||||||
|
// a barrier on integer and FP traps. "EXCB is thus a
|
||||||
|
// superset of TRAPB." (Alpha ARM, Sec 4.11.4) We treat
|
||||||
|
// them the same though.
|
||||||
|
0x0000: trapb({{ }}, IsSerializing, No_OpClass);
|
||||||
|
0x0400: excb({{ }}, IsSerializing, No_OpClass);
|
||||||
|
0x4000: mb({{ }}, IsMemBarrier);
|
||||||
|
0x4400: wmb({{ }}, IsWriteBarrier);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef FULL_SYSTEM
|
#ifdef FULL_SYSTEM
|
||||||
|
@ -2356,13 +2373,13 @@ decode OPCODE default Unknown::unknown() {
|
||||||
if (!xc->misspeculating()) {
|
if (!xc->misspeculating()) {
|
||||||
xc->regs.intrflag = 0;
|
xc->regs.intrflag = 0;
|
||||||
}
|
}
|
||||||
}}, No_OpClass);
|
}});
|
||||||
0xf000: rs({{
|
0xf000: rs({{
|
||||||
Ra = xc->regs.intrflag;
|
Ra = xc->regs.intrflag;
|
||||||
if (!xc->misspeculating()) {
|
if (!xc->misspeculating()) {
|
||||||
xc->regs.intrflag = 1;
|
xc->regs.intrflag = 1;
|
||||||
}
|
}
|
||||||
}}, No_OpClass);
|
}});
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
format FailUnimpl {
|
format FailUnimpl {
|
||||||
|
@ -2476,7 +2493,7 @@ decode OPCODE default Unknown::unknown() {
|
||||||
if (!xc->misspeculating())
|
if (!xc->misspeculating())
|
||||||
AlphaPseudo::m5exit(xc);
|
AlphaPseudo::m5exit(xc);
|
||||||
}}, No_OpClass);
|
}}, No_OpClass);
|
||||||
0x30: initparam({{ Ra = xc->cpu->system->init_param; }});
|
0x30: initparam({{ Ra = cpu->system->init_param; }});
|
||||||
0x40: resetstats({{
|
0x40: resetstats({{
|
||||||
if (!xc->misspeculating())
|
if (!xc->misspeculating())
|
||||||
AlphaPseudo::resetstats(xc);
|
AlphaPseudo::resetstats(xc);
|
||||||
|
|
|
@ -78,6 +78,12 @@ class StaticInstBase : public RefCounted
|
||||||
/// - If IsControl is set, then exactly one of IsDirectControl or
|
/// - If IsControl is set, then exactly one of IsDirectControl or
|
||||||
/// IsIndirect Control will be set, and exactly one of
|
/// IsIndirect Control will be set, and exactly one of
|
||||||
/// IsCondControl or IsUncondControl will be set.
|
/// IsCondControl or IsUncondControl will be set.
|
||||||
|
/// - IsSerializing, IsMemBarrier, and IsWriteBarrier are
|
||||||
|
/// implemented as flags since in the current model there's no
|
||||||
|
/// other way for instructions to inject behavior into the
|
||||||
|
/// pipeline outside of fetch. Once we go to an exec-in-exec CPU
|
||||||
|
/// model we should be able to get rid of these flags and
|
||||||
|
/// implement this behavior via the execute() methods.
|
||||||
///
|
///
|
||||||
enum Flags {
|
enum Flags {
|
||||||
IsNop, ///< Is a no-op (no effect at all).
|
IsNop, ///< Is a no-op (no effect at all).
|
||||||
|
@ -99,7 +105,12 @@ class StaticInstBase : public RefCounted
|
||||||
IsCall, ///< Subroutine call.
|
IsCall, ///< Subroutine call.
|
||||||
IsReturn, ///< Subroutine return.
|
IsReturn, ///< Subroutine return.
|
||||||
|
|
||||||
IsThreadSync, ///< Thread synchronization operation.
|
IsThreadSync, ///< Thread synchronization operation.
|
||||||
|
|
||||||
|
IsSerializing, ///< Serializes pipeline: won't until all
|
||||||
|
/// older instructions have committed.
|
||||||
|
IsMemBarrier, ///< Is a memory barrier
|
||||||
|
IsWriteBarrier, ///< Is a write barrier
|
||||||
|
|
||||||
NumFlags
|
NumFlags
|
||||||
};
|
};
|
||||||
|
@ -178,6 +189,9 @@ class StaticInstBase : public RefCounted
|
||||||
bool isUncondCtrl() const { return flags[IsUncondControl]; }
|
bool isUncondCtrl() const { return flags[IsUncondControl]; }
|
||||||
|
|
||||||
bool isThreadSync() const { return flags[IsThreadSync]; }
|
bool isThreadSync() const { return flags[IsThreadSync]; }
|
||||||
|
bool isSerializing() const { return flags[IsSerializing]; }
|
||||||
|
bool isMemBarrier() const { return flags[IsMemBarrier]; }
|
||||||
|
bool isWriteBarrier() const { return flags[IsWriteBarrier]; }
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
/// Operation class. Used to select appropriate function unit in issue.
|
/// Operation class. Used to select appropriate function unit in issue.
|
||||||
|
@ -216,11 +230,11 @@ class StaticInst : public StaticInstBase
|
||||||
|
|
||||||
/// Return logical index (architectural reg num) of i'th destination reg.
|
/// Return logical index (architectural reg num) of i'th destination reg.
|
||||||
/// Only the entries from 0 through numDestRegs()-1 are valid.
|
/// Only the entries from 0 through numDestRegs()-1 are valid.
|
||||||
RegIndex destRegIdx(int i) { return _destRegIdx[i]; }
|
RegIndex destRegIdx(int i) const { return _destRegIdx[i]; }
|
||||||
|
|
||||||
/// Return logical index (architectural reg num) of i'th source reg.
|
/// Return logical index (architectural reg num) of i'th source reg.
|
||||||
/// Only the entries from 0 through numSrcRegs()-1 are valid.
|
/// Only the entries from 0 through numSrcRegs()-1 are valid.
|
||||||
RegIndex srcRegIdx(int i) { return _srcRegIdx[i]; }
|
RegIndex srcRegIdx(int i) const { return _srcRegIdx[i]; }
|
||||||
|
|
||||||
/// Pointer to a statically allocated "null" instruction object.
|
/// Pointer to a statically allocated "null" instruction object.
|
||||||
/// Used to give eaCompInst() and memAccInst() something to return
|
/// Used to give eaCompInst() and memAccInst() something to return
|
||||||
|
@ -305,7 +319,7 @@ class StaticInst : public StaticInstBase
|
||||||
* Invalid if not a PC-relative branch (i.e. isDirectCtrl()
|
* Invalid if not a PC-relative branch (i.e. isDirectCtrl()
|
||||||
* should be true).
|
* should be true).
|
||||||
*/
|
*/
|
||||||
virtual Addr branchTarget(Addr branchPC)
|
virtual Addr branchTarget(Addr branchPC) const
|
||||||
{
|
{
|
||||||
panic("StaticInst::branchTarget() called on instruction "
|
panic("StaticInst::branchTarget() called on instruction "
|
||||||
"that is not a PC-relative branch.");
|
"that is not a PC-relative branch.");
|
||||||
|
@ -318,7 +332,7 @@ class StaticInst : public StaticInstBase
|
||||||
* execute the branch in question. Invalid if not an indirect
|
* execute the branch in question. Invalid if not an indirect
|
||||||
* branch (i.e. isIndirectCtrl() should be true).
|
* branch (i.e. isIndirectCtrl() should be true).
|
||||||
*/
|
*/
|
||||||
virtual Addr branchTarget(ExecContext *xc)
|
virtual Addr branchTarget(ExecContext *xc) const
|
||||||
{
|
{
|
||||||
panic("StaticInst::branchTarget() called on instruction "
|
panic("StaticInst::branchTarget() called on instruction "
|
||||||
"that is not an indirect branch.");
|
"that is not an indirect branch.");
|
||||||
|
|
|
@ -89,7 +89,7 @@ class EtherLink : public SimObject
|
||||||
Link(const std::string &name, double rate, EtherDump *dump);
|
Link(const std::string &name, double rate, EtherDump *dump);
|
||||||
~Link() {}
|
~Link() {}
|
||||||
|
|
||||||
virtual std::string name() const { return objName; }
|
virtual const std::string name() const { return objName; }
|
||||||
|
|
||||||
bool busy() const { return (bool)packet; }
|
bool busy() const { return (bool)packet; }
|
||||||
bool transmit(PacketPtr &packet);
|
bool transmit(PacketPtr &packet);
|
||||||
|
|
|
@ -153,7 +153,7 @@ class Event : public Serializable, public FastAlloc
|
||||||
|
|
||||||
~Event() {}
|
~Event() {}
|
||||||
|
|
||||||
virtual std::string name() const {
|
virtual const std::string name() const {
|
||||||
return csprintf("Event_%x", (uintptr_t)this);
|
return csprintf("Event_%x", (uintptr_t)this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -257,7 +257,7 @@ class EventQueue : public Serializable
|
||||||
: objName(n), head(NULL)
|
: objName(n), head(NULL)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
virtual std::string name() const { return objName; }
|
virtual const std::string name() const { return objName; }
|
||||||
|
|
||||||
// schedule the given event on this queue
|
// schedule the given event on this queue
|
||||||
void schedule(Event *ev);
|
void schedule(Event *ev);
|
||||||
|
|
|
@ -186,7 +186,7 @@ INSTANTIATE_PARAM_TEMPLATES(string)
|
||||||
class Globals : public Serializable
|
class Globals : public Serializable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
string name() const;
|
const string name() const;
|
||||||
void serialize(ostream& os);
|
void serialize(ostream& os);
|
||||||
void unserialize(Checkpoint *cp);
|
void unserialize(Checkpoint *cp);
|
||||||
};
|
};
|
||||||
|
@ -194,7 +194,7 @@ class Globals : public Serializable
|
||||||
/// The one and only instance of the Globals class.
|
/// The one and only instance of the Globals class.
|
||||||
Globals globals;
|
Globals globals;
|
||||||
|
|
||||||
string
|
const string
|
||||||
Globals::name() const
|
Globals::name() const
|
||||||
{
|
{
|
||||||
return "Globals";
|
return "Globals";
|
||||||
|
|
|
@ -111,7 +111,7 @@ class Serializable
|
||||||
virtual ~Serializable() {}
|
virtual ~Serializable() {}
|
||||||
|
|
||||||
// manditory virtual function, so objects must provide names
|
// manditory virtual function, so objects must provide names
|
||||||
virtual std::string name() const = 0;
|
virtual const std::string name() const = 0;
|
||||||
|
|
||||||
virtual void serialize(std::ostream& os) {}
|
virtual void serialize(std::ostream& os) {}
|
||||||
virtual void unserialize(Checkpoint *cp, const std::string §ion) {}
|
virtual void unserialize(Checkpoint *cp, const std::string §ion) {}
|
||||||
|
|
|
@ -63,7 +63,7 @@ class SimObject : public Serializable
|
||||||
|
|
||||||
virtual ~SimObject() {}
|
virtual ~SimObject() {}
|
||||||
|
|
||||||
virtual std::string name() const { return objName; }
|
virtual const std::string name() const { return objName; }
|
||||||
|
|
||||||
// initialization pass of all objects. Gets invoked by SimInit()
|
// initialization pass of all objects. Gets invoked by SimInit()
|
||||||
virtual void init();
|
virtual void init();
|
||||||
|
|
Loading…
Reference in a new issue