diff --git a/arch/alpha/isa_desc b/arch/alpha/isa_desc index 51bce65c2..d4636f609 100644 --- a/arch/alpha/isa_desc +++ b/arch/alpha/isa_desc @@ -1225,7 +1225,7 @@ declare {{ { } - Addr branchTarget(Addr branchPC) + Addr branchTarget(Addr branchPC) const { return branchPC + 4 + disp; } @@ -1287,7 +1287,7 @@ declare {{ { } - Addr branchTarget(ExecContext *xc) + Addr branchTarget(ExecContext *xc) const { Addr NPC = xc->readPC() + 4; uint64_t Rb = xc->readIntReg(_srcRegIdx[0]); @@ -2330,10 +2330,6 @@ decode OPCODE default Unknown::unknown() { // miscellaneous mem-format ops 0x18: decode MEMFUNC { format WarnUnimpl { - 0x0000: trapb(); - 0x0400: excb(); - 0x4000: mb(); - 0x4400: wmb(); 0x8000: fetch(); 0xa000: fetch_m(); 0xe800: ecb(); @@ -2347,6 +2343,27 @@ decode OPCODE default Unknown::unknown() { format BasicOperate { 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 @@ -2356,13 +2373,13 @@ decode OPCODE default Unknown::unknown() { if (!xc->misspeculating()) { xc->regs.intrflag = 0; } - }}, No_OpClass); + }}); 0xf000: rs({{ Ra = xc->regs.intrflag; if (!xc->misspeculating()) { xc->regs.intrflag = 1; } - }}, No_OpClass); + }}); } #else format FailUnimpl { @@ -2476,7 +2493,7 @@ decode OPCODE default Unknown::unknown() { if (!xc->misspeculating()) AlphaPseudo::m5exit(xc); }}, No_OpClass); - 0x30: initparam({{ Ra = xc->cpu->system->init_param; }}); + 0x30: initparam({{ Ra = cpu->system->init_param; }}); 0x40: resetstats({{ if (!xc->misspeculating()) AlphaPseudo::resetstats(xc); diff --git a/cpu/static_inst.hh b/cpu/static_inst.hh index f3fd6fa24..5f4bcae3d 100644 --- a/cpu/static_inst.hh +++ b/cpu/static_inst.hh @@ -78,6 +78,12 @@ class StaticInstBase : public RefCounted /// - If IsControl is set, then exactly one of IsDirectControl or /// IsIndirect Control will be set, and exactly one of /// 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 { IsNop, ///< Is a no-op (no effect at all). @@ -99,7 +105,12 @@ class StaticInstBase : public RefCounted IsCall, ///< Subroutine call. 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 }; @@ -178,6 +189,9 @@ class StaticInstBase : public RefCounted bool isUncondCtrl() const { return flags[IsUncondControl]; } 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. @@ -216,11 +230,11 @@ class StaticInst : public StaticInstBase /// Return logical index (architectural reg num) of i'th destination reg. /// 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. /// 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. /// 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() * should be true). */ - virtual Addr branchTarget(Addr branchPC) + virtual Addr branchTarget(Addr branchPC) const { panic("StaticInst::branchTarget() called on instruction " "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 * branch (i.e. isIndirectCtrl() should be true). */ - virtual Addr branchTarget(ExecContext *xc) + virtual Addr branchTarget(ExecContext *xc) const { panic("StaticInst::branchTarget() called on instruction " "that is not an indirect branch."); diff --git a/dev/etherlink.hh b/dev/etherlink.hh index 895bac2e1..e1a7957ee 100644 --- a/dev/etherlink.hh +++ b/dev/etherlink.hh @@ -89,7 +89,7 @@ class EtherLink : public SimObject Link(const std::string &name, double rate, EtherDump *dump); ~Link() {} - virtual std::string name() const { return objName; } + virtual const std::string name() const { return objName; } bool busy() const { return (bool)packet; } bool transmit(PacketPtr &packet); diff --git a/sim/eventq.hh b/sim/eventq.hh index 36cb402a8..31bf9d652 100644 --- a/sim/eventq.hh +++ b/sim/eventq.hh @@ -153,7 +153,7 @@ class Event : public Serializable, public FastAlloc ~Event() {} - virtual std::string name() const { + virtual const std::string name() const { return csprintf("Event_%x", (uintptr_t)this); } @@ -257,7 +257,7 @@ class EventQueue : public Serializable : 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 void schedule(Event *ev); diff --git a/sim/serialize.cc b/sim/serialize.cc index 180cc38a0..d836e7c20 100644 --- a/sim/serialize.cc +++ b/sim/serialize.cc @@ -186,7 +186,7 @@ INSTANTIATE_PARAM_TEMPLATES(string) class Globals : public Serializable { public: - string name() const; + const string name() const; void serialize(ostream& os); void unserialize(Checkpoint *cp); }; @@ -194,7 +194,7 @@ class Globals : public Serializable /// The one and only instance of the Globals class. Globals globals; -string +const string Globals::name() const { return "Globals"; diff --git a/sim/serialize.hh b/sim/serialize.hh index 9ab2fa833..43dbd2c85 100644 --- a/sim/serialize.hh +++ b/sim/serialize.hh @@ -111,7 +111,7 @@ class Serializable virtual ~Serializable() {} // 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 unserialize(Checkpoint *cp, const std::string §ion) {} diff --git a/sim/sim_object.hh b/sim/sim_object.hh index 165931b2b..aaaafc04b 100644 --- a/sim/sim_object.hh +++ b/sim/sim_object.hh @@ -63,7 +63,7 @@ class SimObject : public Serializable 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() virtual void init();