gem5/cpu/beta_cpu/full_cpu.hh
Kevin Lim 04745696b6 Check in of new CPU. This checkin works under non-Fullsystem mode, with no caches.
SConscript:
    Added new CPU files to build.
arch/alpha/isa_desc:
    Changed rduniq and wruniq to be nonspeculative because the uniq register is not renamed.
arch/isa_parser.py:
    Added new CPU exec method.
base/statistics.hh:
    Minor change for namespace conflict.  Probably can change back one the new CPU files are cleaned up.
base/traceflags.py:
    Added new CPU trace flags.
cpu/static_inst.hh:
    Changed static inst to use a file that defines the execute functions.

--HG--
extra : convert_revision : bd4ce34361308280168324817fc1258dd253e519
2004-08-20 14:54:07 -04:00

323 lines
8.8 KiB
C++

//Todo: Add in a lot of the functions that are ISA specific. Also define
//the functions that currently exist within the base cpu class. Define
//everything for the simobject stuff so it can be serialized and
//instantiated, add in debugging statements everywhere. Have CPU schedule
//itself properly. Constructor. Derived alpha class. Threads!
// Avoid running stages and advancing queues if idle/stalled.
#ifndef __SIMPLE_FULL_CPU_HH__
#define __SIMPLE_FULL_CPU_HH__
#include <iostream>
#include <list>
#include "cpu/beta_cpu/comm.hh"
#include "base/statistics.hh"
#include "base/timebuf.hh"
#include "cpu/base_cpu.hh"
#include "cpu/beta_cpu/cpu_policy.hh"
#include "sim/process.hh"
using namespace std;
class FunctionalMemory;
class Process;
class BaseFullCPU : public BaseCPU
{
//Stuff that's pretty ISA independent will go here.
public:
#ifdef FULL_SYSTEM
BaseFullCPU(const std::string &_name, int _number_of_threads,
Counter max_insts_any_thread, Counter max_insts_all_threads,
Counter max_loads_any_thread, Counter max_loads_all_threads,
System *_system, Tick freq);
#else
BaseFullCPU(const std::string &_name, int _number_of_threads,
Counter max_insts_any_thread = 0,
Counter max_insts_all_threads = 0,
Counter max_loads_any_thread = 0,
Counter max_loads_all_threads = 0);
#endif // FULL_SYSTEM
};
template <class Impl>
class FullBetaCPU : public BaseFullCPU
{
public:
//Put typedefs from the Impl here.
typedef typename Impl::CPUPol CPUPolicy;
typedef typename Impl::Params Params;
typedef typename Impl::DynInst DynInst;
public:
enum Status {
Running,
Idle,
Halted,
Blocked // ?
};
Status _status;
private:
class TickEvent : public Event
{
private:
FullBetaCPU<Impl> *cpu;
public:
TickEvent(FullBetaCPU<Impl> *c);
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();
}
public:
void tick();
FullBetaCPU(Params &params);
~FullBetaCPU();
void init();
void activateContext(int thread_num, int delay);
void suspendContext(int thread_num);
void deallocateContext(int thread_num);
void haltContext(int thread_num);
void switchOut();
void takeOverFrom(BaseCPU *oldCPU);
/** Get the current instruction sequence number, and increment it. */
InstSeqNum getAndIncrementInstSeq();
#ifdef FULL_SYSTEM
/** Check if this address is a valid instruction address. */
bool validInstAddr(Addr addr) { return true; }
/** Check if this address is a valid data address. */
bool validDataAddr(Addr addr) { return true; }
/** Get instruction asid. */
int getInstAsid() { return ITB_ASN_ASN(regs.ipr[ISA::IPR_ITB_ASN]); }
/** Get data asid. */
int getDataAsid() { return DTB_ASN_ASN(regs.ipr[ISA::IPR_DTB_ASN]); }
#else
bool validInstAddr(Addr addr)
{ return process->validInstAddr(addr); }
bool validDataAddr(Addr addr)
{ return process->validDataAddr(addr); }
int getInstAsid() { return asid; }
int getDataAsid() { return asid; }
#endif
//
// New accessors for new decoder.
//
uint64_t readIntReg(int reg_idx);
float readFloatRegSingle(int reg_idx);
double readFloatRegDouble(int reg_idx);
uint64_t readFloatRegInt(int reg_idx);
void setIntReg(int reg_idx, uint64_t val);
void setFloatRegSingle(int reg_idx, float val);
void setFloatRegDouble(int reg_idx, double val);
void setFloatRegInt(int reg_idx, uint64_t val);
uint64_t readPC();
void setNextPC(uint64_t val);
void setPC(Addr new_PC);
/** Function to add instruction onto the head of the list of the
* instructions. Used when new instructions are fetched.
*/
void addInst(DynInst *inst);
/** Function to tell the CPU that an instruction has completed. */
void instDone();
/** Remove all instructions in back of the given instruction, but leave
* that instruction in the list. This is useful in a squash, when there
* are instructions in this list that don't exist in structures such as
* the ROB. The instruction doesn't have to be the last instruction in
* the list, but will be once this function completes.
* @todo: Remove only up until that inst? Squashed inst is most likely
* valid.
*/
void removeBackInst(DynInst *inst);
/** Remove an instruction from the front of the list. It is expected
* that there are no instructions in front of it (that is, none are older
* than the instruction being removed). Used when retiring instructions.
* @todo: Remove the argument to this function, and just have it remove
* last instruction once it's verified that commit has the same ordering
* as the instruction list.
*/
void removeFrontInst(DynInst *inst);
/** Remove all instructions that are not currently in the ROB. */
void removeInstsNotInROB();
/** Remove all instructions from the list. */
void removeAllInsts();
void dumpInsts();
/** Basically a wrapper function so that instructions executed at
* commit can tell the instruction queue that they have completed.
* Eventually this hack should be removed.
*/
void wakeDependents(DynInst *inst);
public:
/** List of all the instructions in flight. */
list<DynInst *> instList;
//not sure these should be private.
protected:
/** The fetch stage. */
typename CPUPolicy::Fetch fetch;
/** The fetch stage's status. */
typename CPUPolicy::Fetch::Status fetchStatus;
/** The decode stage. */
typename CPUPolicy::Decode decode;
/** The decode stage's status. */
typename CPUPolicy::Decode::Status decodeStatus;
/** The dispatch stage. */
typename CPUPolicy::Rename rename;
/** The dispatch stage's status. */
typename CPUPolicy::Rename::Status renameStatus;
/** The issue/execute/writeback stages. */
typename CPUPolicy::IEW iew;
/** The issue/execute/writeback stage's status. */
typename CPUPolicy::IEW::Status iewStatus;
/** The commit stage. */
typename CPUPolicy::Commit commit;
/** The fetch stage's status. */
typename CPUPolicy::Commit::Status commitStatus;
//Might want to just pass these objects in to the constructors of the
//appropriate stage. regFile is in iew, freeList in dispatch, renameMap
//in dispatch, and the rob in commit.
/** The register file. */
typename CPUPolicy::RegFile regFile;
/** The free list. */
typename CPUPolicy::FreeList freeList;
/** The rename map. */
typename CPUPolicy::RenameMap renameMap;
/** The re-order buffer. */
typename CPUPolicy::ROB rob;
public:
/** Typedefs from the Impl to get the structs that each of the
* time buffers should use.
*/
typedef typename Impl::TimeStruct TimeStruct;
typedef typename Impl::FetchStruct FetchStruct;
typedef typename Impl::DecodeStruct DecodeStruct;
typedef typename Impl::RenameStruct RenameStruct;
typedef typename Impl::IEWStruct IEWStruct;
/** The main time buffer to do backwards communication. */
TimeBuffer<TimeStruct> timeBuffer;
/** The fetch stage's instruction queue. */
TimeBuffer<FetchStruct> fetchQueue;
/** The decode stage's instruction queue. */
TimeBuffer<DecodeStruct> decodeQueue;
/** The rename stage's instruction queue. */
TimeBuffer<RenameStruct> renameQueue;
/** The IEW stage's instruction queue. */
TimeBuffer<IEWStruct> iewQueue;
public:
/** The temporary exec context to support older accessors. */
ExecContext *xc;
/** Temporary function to get pointer to exec context. */
ExecContext *xcBase() { return xc; }
InstSeqNum globalSeqNum;
#ifdef FULL_SYSTEM
System *system;
MemoryController *memCtrl;
PhysicalMemory *physmem;
AlphaITB *itb;
AlphaDTB *dtb;
// SWContext *swCtx;
#else
Process *process;
// Address space ID. Note that this is used for TIMING cache
// simulation only; all functional memory accesses should use
// one of the FunctionalMemory pointers above.
short asid;
#endif
FunctionalMemory *mem;
MemInterface *icacheInterface;
MemInterface *dcacheInterface;
bool deferRegistration;
Counter numInsts;
Counter funcExeInst;
};
#endif