gem5/cpu/static_inst.hh
Kevin Lim e3fb9afa79 Update to make multiple instruction issue and different latencies work.
Also change to ref counted DynInst.

SConscript:
    Add branch predictor, BTB, load store queue, and storesets.
arch/isa_parser.py:
    Specify the template parameter for AlphaDynInst
base/traceflags.py:
    Add load store queue, store set, and mem dependence unit to the
    list of trace flags.
cpu/base_dyn_inst.cc:
    Change formating, add in debug statement.
cpu/base_dyn_inst.hh:
    Change DynInst to be RefCounted, add flag to clear whether or not this
    instruction can commit.  This is likely to be removed in the future.
cpu/beta_cpu/alpha_dyn_inst.cc:
    AlphaDynInst has been changed to be templated, so now this CC file
    is just used to force instantiations of AlphaDynInst.
cpu/beta_cpu/alpha_dyn_inst.hh:
    Changed AlphaDynInst to be templated on Impl.  Removed some unnecessary
    functions.
cpu/beta_cpu/alpha_full_cpu.cc:
    AlphaFullCPU has been changed to be templated, so this CC file is now
    just used to force instantation of AlphaFullCPU.
cpu/beta_cpu/alpha_full_cpu.hh:
    Change AlphaFullCPU to be templated on Impl.
cpu/beta_cpu/alpha_impl.hh:
    Update it to reflect AlphaDynInst and AlphaFullCPU being templated
    on Impl.  Also removed time buffers from here, as they are really
    a part of the CPU and are thus in the CPU policy now.
cpu/beta_cpu/alpha_params.hh:
    Make AlphaSimpleParams inherit from the BaseFullCPU so that it doesn't
    need to specifically declare any parameters that are already in the
    BaseFullCPU.
cpu/beta_cpu/comm.hh:
    Changed the structure of the time buffer communication structs.  Now
    they include the size of the packet of instructions it is sending.
    Added some parameters to the backwards communication struct, mainly
    for squashing.
cpu/beta_cpu/commit.hh:
    Update typenames to reflect change in location of time buffer structs.
    Update DynInst to DynInstPtr (it is refcounted now).
cpu/beta_cpu/commit_impl.hh:
    Formatting changes mainly.  Also sends back proper information
    on branch mispredicts so that the bpred unit can update itself.
    Updated behavior for non-speculative instructions (stores, any
    other non-spec instructions): once they reach the head of the ROB,
    the ROB signals back to the IQ that it can go ahead and issue the
    non-speculative instruction.  The instruction itself is updated so that
    commit won't try to commit it again until it is done executing.
cpu/beta_cpu/cpu_policy.hh:
    Added branch prediction unit, mem dependence prediction unit, load
    store queue.  Moved time buffer structs from AlphaSimpleImpl to here.
cpu/beta_cpu/decode.hh:
    Changed typedefs to reflect change in location of time buffer structs
    and also the change from DynInst to ref counted DynInstPtr.
cpu/beta_cpu/decode_impl.hh:
    Continues to buffer instructions even while unblocking now.  Changed
    how it loops through groups of instructions so it can properly block
    during the middle of a group of instructions.
cpu/beta_cpu/fetch.hh:
    Changed typedefs to reflect change in location of time buffer structs
    and the change to ref counted DynInsts.  Also added in branch
    brediction unit.
cpu/beta_cpu/fetch_impl.hh:
    Add in branch prediction.  Changed how fetch checks inputs and its
    current state to make for easier logic.
cpu/beta_cpu/free_list.cc:
    Changed int regs and float regs to logically use one flat namespace.
    Future change will be moving them to a single scoreboard to conserve
    space.
cpu/beta_cpu/free_list.hh:
    Mostly debugging statements.  Might be removed for performance in future.
cpu/beta_cpu/full_cpu.cc:
    Added in some debugging statements.  Updated BaseFullCPU to take
    a params object.
cpu/beta_cpu/full_cpu.hh:
    Added params class within BaseCPU that other param classes will be
    able to inherit from.  Updated typedefs to reflect change in location
    of time buffer structs and ref counted DynInst.
cpu/beta_cpu/iew.hh:
    Updated typedefs to reflect change in location of time buffer structs
    and use of ref counted DynInsts.
cpu/beta_cpu/iew_impl.hh:
    Added in load store queue, updated iew to be able to execute non-
    speculative instructions, instead of having them execute in commit.
cpu/beta_cpu/inst_queue.hh:
    Updated change to ref counted DynInsts.  Changed inst queue to hold
    non-speculative instructions as well, which are issued only when
    commit signals backwards that a nonspeculative instruction is at
    the head of the ROB.
cpu/beta_cpu/inst_queue_impl.hh:
    Updated to allow for non-speculative instructions to be in the inst
    queue.  Also added some debug functions.
cpu/beta_cpu/regfile.hh:
    Added debugging statements, changed formatting.
cpu/beta_cpu/rename.hh:
    Updated typedefs, added some functions to clean up code.
cpu/beta_cpu/rename_impl.hh:
    Moved some code into functions to make it easier to read.
cpu/beta_cpu/rename_map.cc:
    Changed int and float reg behavior to use a single flat namespace.  In
    the future, the rename maps can be combined to a single rename map to
    save space.
cpu/beta_cpu/rename_map.hh:
    Added destructor.
cpu/beta_cpu/rob.hh:
    Updated it with change from DynInst to ref counted DynInst.
cpu/beta_cpu/rob_impl.hh:
    Formatting, updated to use ref counted DynInst.
cpu/static_inst.hh:
    Updated forward declaration for AlphaDynInst now that it is templated.

--HG--
extra : convert_revision : 1045f240ee9b6a4bd368e1806aca029ebbdc6dd3
2004-09-23 14:06:03 -04:00

447 lines
15 KiB
C++

/*
* Copyright (c) 2003-2004 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 __STATIC_INST_HH__
#define __STATIC_INST_HH__
#include <bitset>
#include <string>
#include "sim/host.hh"
#include "base/hashmap.hh"
#include "base/refcnt.hh"
#include "cpu/full_cpu/op_class.hh"
#include "targetarch/isa_traits.hh"
// forward declarations
struct AlphaSimpleImpl;
class ExecContext;
class DynInst;
template <class Impl>
class AlphaDynInst;
class FastCPU;
class SimpleCPU;
class SymbolTable;
namespace Trace {
class InstRecord;
}
/**
* Base, ISA-independent static instruction class.
*
* The main component of this class is the vector of flags and the
* associated methods for reading them. Any object that can rely
* solely on these flags can process instructions without being
* recompiled for multiple ISAs.
*/
class StaticInstBase : public RefCounted
{
protected:
/// Set of boolean static instruction properties.
///
/// Notes:
/// - The IsInteger and IsFloating flags are based on the class of
/// registers accessed by the instruction. Although most
/// instructions will have exactly one of these two flags set, it
/// is possible for an instruction to have neither (e.g., direct
/// unconditional branches, memory barriers) or both (e.g., an
/// FP/int conversion).
/// - If IsMemRef is set, then exactly one of IsLoad or IsStore
/// will be set.
/// - 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).
IsInteger, ///< References integer regs.
IsFloating, ///< References FP regs.
IsMemRef, ///< References memory (load, store, or prefetch).
IsLoad, ///< Reads from memory (load or prefetch).
IsStore, ///< Writes to memory.
IsInstPrefetch, ///< Instruction-cache prefetch.
IsDataPrefetch, ///< Data-cache prefetch.
IsCopy, ///< Fast Cache block copy
IsControl, ///< Control transfer instruction.
IsDirectControl, ///< PC relative control transfer.
IsIndirectControl, ///< Register indirect control transfer.
IsCondControl, ///< Conditional control transfer.
IsUncondControl, ///< Unconditional control transfer.
IsCall, ///< Subroutine call.
IsReturn, ///< Subroutine return.
IsThreadSync, ///< Thread synchronization operation.
IsSerializing, ///< Serializes pipeline: won't execute until all
/// older instructions have committed.
IsMemBarrier, ///< Is a memory barrier
IsWriteBarrier, ///< Is a write barrier
IsNonSpeculative, ///< Should not be executed speculatively
NumFlags
};
/// Flag values for this instruction.
std::bitset<NumFlags> flags;
/// See opClass().
OpClass _opClass;
/// See numSrcRegs().
int8_t _numSrcRegs;
/// See numDestRegs().
int8_t _numDestRegs;
/// The following are used to track physical register usage
/// for machines with separate int & FP reg files.
//@{
int8_t _numFPDestRegs;
int8_t _numIntDestRegs;
//@}
/// Constructor.
/// It's important to initialize everything here to a sane
/// default, since the decoder generally only overrides
/// the fields that are meaningful for the particular
/// instruction.
StaticInstBase(OpClass __opClass)
: _opClass(__opClass), _numSrcRegs(0), _numDestRegs(0),
_numFPDestRegs(0), _numIntDestRegs(0)
{
}
public:
/// @name Register information.
/// The sum of numFPDestRegs() and numIntDestRegs() equals
/// numDestRegs(). The former two functions are used to track
/// physical register usage for machines with separate int & FP
/// reg files.
//@{
/// Number of source registers.
int8_t numSrcRegs() const { return _numSrcRegs; }
/// Number of destination registers.
int8_t numDestRegs() const { return _numDestRegs; }
/// Number of floating-point destination regs.
int8_t numFPDestRegs() const { return _numFPDestRegs; }
/// Number of integer destination regs.
int8_t numIntDestRegs() const { return _numIntDestRegs; }
//@}
/// @name Flag accessors.
/// These functions are used to access the values of the various
/// instruction property flags. See StaticInstBase::Flags for descriptions
/// of the individual flags.
//@{
bool isNop() const { return flags[IsNop]; }
bool isMemRef() const { return flags[IsMemRef]; }
bool isLoad() const { return flags[IsLoad]; }
bool isStore() const { return flags[IsStore]; }
bool isInstPrefetch() const { return flags[IsInstPrefetch]; }
bool isDataPrefetch() const { return flags[IsDataPrefetch]; }
bool isCopy() const { return flags[IsCopy];}
bool isInteger() const { return flags[IsInteger]; }
bool isFloating() const { return flags[IsFloating]; }
bool isControl() const { return flags[IsControl]; }
bool isCall() const { return flags[IsCall]; }
bool isReturn() const { return flags[IsReturn]; }
bool isDirectCtrl() const { return flags[IsDirectControl]; }
bool isIndirectCtrl() const { return flags[IsIndirectControl]; }
bool isCondCtrl() const { return flags[IsCondControl]; }
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]; }
bool isNonSpeculative() const { return flags[IsNonSpeculative]; }
//@}
/// Operation class. Used to select appropriate function unit in issue.
OpClass opClass() const { return _opClass; }
};
// forward declaration
template <class ISA>
class StaticInstPtr;
/**
* Generic yet ISA-dependent static instruction class.
*
* This class builds on StaticInstBase, defining fields and interfaces
* that are generic across all ISAs but that differ in details
* according to the specific ISA being used.
*/
template <class ISA>
class StaticInst : public StaticInstBase
{
public:
/// Binary machine instruction type.
typedef typename ISA::MachInst MachInst;
/// Memory address type.
typedef typename ISA::Addr Addr;
/// Logical register index type.
typedef typename ISA::RegIndex RegIndex;
enum {
MaxInstSrcRegs = ISA::MaxInstSrcRegs, //< Max source regs
MaxInstDestRegs = ISA::MaxInstDestRegs, //< Max dest regs
};
/// 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) 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) const { return _srcRegIdx[i]; }
/// Pointer to a statically allocated "null" instruction object.
/// Used to give eaCompInst() and memAccInst() something to return
/// when called on non-memory instructions.
static StaticInstPtr<ISA> nullStaticInstPtr;
/**
* Memory references only: returns "fake" instruction representing
* the effective address part of the memory operation. Used to
* obtain the dependence info (numSrcRegs and srcRegIdx[]) for
* just the EA computation.
*/
virtual const
StaticInstPtr<ISA> &eaCompInst() const { return nullStaticInstPtr; }
/**
* Memory references only: returns "fake" instruction representing
* the memory access part of the memory operation. Used to
* obtain the dependence info (numSrcRegs and srcRegIdx[]) for
* just the memory access (not the EA computation).
*/
virtual const
StaticInstPtr<ISA> &memAccInst() const { return nullStaticInstPtr; }
/// The binary machine instruction.
const MachInst machInst;
protected:
/// See destRegIdx().
RegIndex _destRegIdx[MaxInstDestRegs];
/// See srcRegIdx().
RegIndex _srcRegIdx[MaxInstSrcRegs];
/**
* Base mnemonic (e.g., "add"). Used by generateDisassembly()
* methods. Also useful to readily identify instructions from
* within the debugger when #cachedDisassembly has not been
* initialized.
*/
const char *mnemonic;
/**
* String representation of disassembly (lazily evaluated via
* disassemble()).
*/
std::string *cachedDisassembly;
/**
* Internal function to generate disassembly string.
*/
virtual std::string generateDisassembly(Addr pc,
const SymbolTable *symtab) = 0;
/// Constructor.
StaticInst(const char *_mnemonic, MachInst _machInst, OpClass __opClass)
: StaticInstBase(__opClass),
machInst(_machInst), mnemonic(_mnemonic), cachedDisassembly(0)
{
}
public:
virtual ~StaticInst()
{
if (cachedDisassembly)
delete cachedDisassembly;
}
#include "static_inst_impl.hh"
/**
* Return the target address for a PC-relative branch.
* Invalid if not a PC-relative branch (i.e. isDirectCtrl()
* should be true).
*/
virtual Addr branchTarget(Addr branchPC) const
{
panic("StaticInst::branchTarget() called on instruction "
"that is not a PC-relative branch.");
}
/**
* Return the target address for an indirect branch (jump). The
* register value is read from the supplied execution context, so
* the result is valid only if the execution context is about to
* execute the branch in question. Invalid if not an indirect
* branch (i.e. isIndirectCtrl() should be true).
*/
virtual Addr branchTarget(ExecContext *xc) const
{
panic("StaticInst::branchTarget() called on instruction "
"that is not an indirect branch.");
}
/**
* Return true if the instruction is a control transfer, and if so,
* return the target address as well.
*/
bool hasBranchTarget(Addr pc, ExecContext *xc, Addr &tgt);
/**
* Return string representation of disassembled instruction.
* The default version of this function will call the internal
* virtual generateDisassembly() function to get the string,
* then cache it in #cachedDisassembly. If the disassembly
* should not be cached, this function should be overridden directly.
*/
virtual const std::string &disassemble(Addr pc,
const SymbolTable *symtab = 0)
{
if (!cachedDisassembly)
cachedDisassembly =
new std::string(generateDisassembly(pc, symtab));
return *cachedDisassembly;
}
/// Decoded instruction cache type.
/// For now we're using a generic hash_map; this seems to work
/// pretty well.
typedef m5::hash_map<MachInst, StaticInstPtr<ISA> > DecodeCache;
/// A cache of decoded instruction objects.
static DecodeCache decodeCache;
/**
* Dump some basic stats on the decode cache hash map.
* Only gets called if DECODE_CACHE_HASH_STATS is defined.
*/
static void dumpDecodeCacheStats();
/// Decode a machine instruction.
/// @param mach_inst The binary instruction to decode.
/// @retval A pointer to the corresponding StaticInst object.
static
StaticInstPtr<ISA> decode(MachInst mach_inst)
{
#ifdef DECODE_CACHE_HASH_STATS
// Simple stats on decode hash_map. Turns out the default
// hash function is as good as anything I could come up with.
const int dump_every_n = 10000000;
static int decodes_til_dump = dump_every_n;
if (--decodes_til_dump == 0) {
dumpDecodeCacheStats();
decodes_til_dump = dump_every_n;
}
#endif
typename DecodeCache::iterator iter = decodeCache.find(mach_inst);
if (iter != decodeCache.end()) {
return iter->second;
}
StaticInstPtr<ISA> si = ISA::decodeInst(mach_inst);
decodeCache[mach_inst] = si;
return si;
}
};
typedef RefCountingPtr<StaticInstBase> StaticInstBasePtr;
/// Reference-counted pointer to a StaticInst object.
/// This type should be used instead of "StaticInst<ISA> *" so that
/// StaticInst objects can be properly reference-counted.
template <class ISA>
class StaticInstPtr : public RefCountingPtr<StaticInst<ISA> >
{
public:
/// Constructor.
StaticInstPtr()
: RefCountingPtr<StaticInst<ISA> >()
{
}
/// Conversion from "StaticInst<ISA> *".
StaticInstPtr(StaticInst<ISA> *p)
: RefCountingPtr<StaticInst<ISA> >(p)
{
}
/// Copy constructor.
StaticInstPtr(const StaticInstPtr &r)
: RefCountingPtr<StaticInst<ISA> >(r)
{
}
/// Construct directly from machine instruction.
/// Calls StaticInst<ISA>::decode().
StaticInstPtr(typename ISA::MachInst mach_inst)
: RefCountingPtr<StaticInst<ISA> >(StaticInst<ISA>::decode(mach_inst))
{
}
/// Convert to pointer to StaticInstBase class.
operator const StaticInstBasePtr()
{
return get();
}
};
#endif // __STATIC_INST_HH__