009970f59b
Cleanup the serialization code for the simple CPUs and the O3 CPU. The CPU-specific code has been replaced with a (un)serializeThread that serializes the thread state / context of a specific thread. Assuming that the thread state class uses the CPU-specific thread state uses the base thread state serialization code, this allows us to restore a checkpoint with any of the CPU models.
846 lines
26 KiB
C++
846 lines
26 KiB
C++
/*
|
|
* Copyright (c) 2011-2012 ARM Limited
|
|
* All rights reserved
|
|
*
|
|
* The license below extends only to copyright in the software and shall
|
|
* not be construed as granting a license to any other intellectual
|
|
* property including but not limited to intellectual property relating
|
|
* to a hardware implementation of the functionality of the software
|
|
* licensed hereunder. You may use the software subject to the license
|
|
* terms below provided that you ensure that this notice is replicated
|
|
* unmodified and in its entirety in all distributions of the software,
|
|
* modified or unmodified, in source code or in binary form.
|
|
*
|
|
* Copyright (c) 2004-2005 The Regents of The University of Michigan
|
|
* Copyright (c) 2011 Regents of the University of California
|
|
* 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.
|
|
*
|
|
* Authors: Kevin Lim
|
|
* Korey Sewell
|
|
* Rick Strong
|
|
*/
|
|
|
|
#ifndef __CPU_O3_CPU_HH__
|
|
#define __CPU_O3_CPU_HH__
|
|
|
|
#include <iostream>
|
|
#include <list>
|
|
#include <queue>
|
|
#include <set>
|
|
#include <vector>
|
|
|
|
#include "arch/types.hh"
|
|
#include "base/statistics.hh"
|
|
#include "config/the_isa.hh"
|
|
#include "cpu/o3/comm.hh"
|
|
#include "cpu/o3/cpu_policy.hh"
|
|
#include "cpu/o3/scoreboard.hh"
|
|
#include "cpu/o3/thread_state.hh"
|
|
#include "cpu/activity.hh"
|
|
#include "cpu/base.hh"
|
|
#include "cpu/simple_thread.hh"
|
|
#include "cpu/timebuf.hh"
|
|
//#include "cpu/o3/thread_context.hh"
|
|
#include "params/DerivO3CPU.hh"
|
|
#include "sim/process.hh"
|
|
|
|
template <class>
|
|
class Checker;
|
|
class ThreadContext;
|
|
template <class>
|
|
class O3ThreadContext;
|
|
|
|
class Checkpoint;
|
|
class MemObject;
|
|
class Process;
|
|
|
|
struct BaseCPUParams;
|
|
|
|
class BaseO3CPU : public BaseCPU
|
|
{
|
|
//Stuff that's pretty ISA independent will go here.
|
|
public:
|
|
BaseO3CPU(BaseCPUParams *params);
|
|
|
|
void regStats();
|
|
};
|
|
|
|
/**
|
|
* FullO3CPU class, has each of the stages (fetch through commit)
|
|
* within it, as well as all of the time buffers between stages. The
|
|
* tick() function for the CPU is defined here.
|
|
*/
|
|
template <class Impl>
|
|
class FullO3CPU : public BaseO3CPU
|
|
{
|
|
public:
|
|
// Typedefs from the Impl here.
|
|
typedef typename Impl::CPUPol CPUPolicy;
|
|
typedef typename Impl::DynInstPtr DynInstPtr;
|
|
typedef typename Impl::O3CPU O3CPU;
|
|
|
|
typedef O3ThreadState<Impl> ImplState;
|
|
typedef O3ThreadState<Impl> Thread;
|
|
|
|
typedef typename std::list<DynInstPtr>::iterator ListIt;
|
|
|
|
friend class O3ThreadContext<Impl>;
|
|
|
|
public:
|
|
enum Status {
|
|
Running,
|
|
Idle,
|
|
Halted,
|
|
Blocked,
|
|
SwitchedOut
|
|
};
|
|
|
|
TheISA::TLB * itb;
|
|
TheISA::TLB * dtb;
|
|
|
|
/** Overall CPU status. */
|
|
Status _status;
|
|
|
|
private:
|
|
|
|
/**
|
|
* IcachePort class for instruction fetch.
|
|
*/
|
|
class IcachePort : public CpuPort
|
|
{
|
|
protected:
|
|
/** Pointer to fetch. */
|
|
DefaultFetch<Impl> *fetch;
|
|
|
|
public:
|
|
/** Default constructor. */
|
|
IcachePort(DefaultFetch<Impl> *_fetch, FullO3CPU<Impl>* _cpu)
|
|
: CpuPort(_cpu->name() + ".icache_port", _cpu), fetch(_fetch)
|
|
{ }
|
|
|
|
protected:
|
|
|
|
/** Timing version of receive. Handles setting fetch to the
|
|
* proper status to start fetching. */
|
|
virtual bool recvTimingResp(PacketPtr pkt);
|
|
virtual void recvTimingSnoopReq(PacketPtr pkt) { }
|
|
|
|
/** Handles doing a retry of a failed fetch. */
|
|
virtual void recvRetry();
|
|
};
|
|
|
|
/**
|
|
* DcachePort class for the load/store queue.
|
|
*/
|
|
class DcachePort : public CpuPort
|
|
{
|
|
protected:
|
|
|
|
/** Pointer to LSQ. */
|
|
LSQ<Impl> *lsq;
|
|
|
|
public:
|
|
/** Default constructor. */
|
|
DcachePort(LSQ<Impl> *_lsq, FullO3CPU<Impl>* _cpu)
|
|
: CpuPort(_cpu->name() + ".dcache_port", _cpu), lsq(_lsq)
|
|
{ }
|
|
|
|
protected:
|
|
|
|
/** Timing version of receive. Handles writing back and
|
|
* completing the load or store that has returned from
|
|
* memory. */
|
|
virtual bool recvTimingResp(PacketPtr pkt);
|
|
virtual void recvTimingSnoopReq(PacketPtr pkt);
|
|
|
|
/** Handles doing a retry of the previous send. */
|
|
virtual void recvRetry();
|
|
|
|
/**
|
|
* As this CPU requires snooping to maintain the load store queue
|
|
* change the behaviour from the base CPU port.
|
|
*
|
|
* @return true since we have to snoop
|
|
*/
|
|
virtual bool isSnooping() const { return true; }
|
|
};
|
|
|
|
class TickEvent : public Event
|
|
{
|
|
private:
|
|
/** Pointer to the CPU. */
|
|
FullO3CPU<Impl> *cpu;
|
|
|
|
public:
|
|
/** Constructs a tick event. */
|
|
TickEvent(FullO3CPU<Impl> *c);
|
|
|
|
/** Processes a tick event, calling tick() on the CPU. */
|
|
void process();
|
|
/** Returns the description of the tick event. */
|
|
const char *description() const;
|
|
};
|
|
|
|
/** The tick event used for scheduling CPU ticks. */
|
|
TickEvent tickEvent;
|
|
|
|
/** Schedule tick event, regardless of its current state. */
|
|
void scheduleTickEvent(Cycles delay)
|
|
{
|
|
if (tickEvent.squashed())
|
|
reschedule(tickEvent, clockEdge(delay));
|
|
else if (!tickEvent.scheduled())
|
|
schedule(tickEvent, clockEdge(delay));
|
|
}
|
|
|
|
/** Unschedule tick event, regardless of its current state. */
|
|
void unscheduleTickEvent()
|
|
{
|
|
if (tickEvent.scheduled())
|
|
tickEvent.squash();
|
|
}
|
|
|
|
class ActivateThreadEvent : public Event
|
|
{
|
|
private:
|
|
/** Number of Thread to Activate */
|
|
ThreadID tid;
|
|
|
|
/** Pointer to the CPU. */
|
|
FullO3CPU<Impl> *cpu;
|
|
|
|
public:
|
|
/** Constructs the event. */
|
|
ActivateThreadEvent();
|
|
|
|
/** Initialize Event */
|
|
void init(int thread_num, FullO3CPU<Impl> *thread_cpu);
|
|
|
|
/** Processes the event, calling activateThread() on the CPU. */
|
|
void process();
|
|
|
|
/** Returns the description of the event. */
|
|
const char *description() const;
|
|
};
|
|
|
|
/** Schedule thread to activate , regardless of its current state. */
|
|
void
|
|
scheduleActivateThreadEvent(ThreadID tid, Cycles delay)
|
|
{
|
|
// Schedule thread to activate, regardless of its current state.
|
|
if (activateThreadEvent[tid].squashed())
|
|
reschedule(activateThreadEvent[tid],
|
|
clockEdge(delay));
|
|
else if (!activateThreadEvent[tid].scheduled()) {
|
|
Tick when = clockEdge(delay);
|
|
|
|
// Check if the deallocateEvent is also scheduled, and make
|
|
// sure they do not happen at same time causing a sleep that
|
|
// is never woken from.
|
|
if (deallocateContextEvent[tid].scheduled() &&
|
|
deallocateContextEvent[tid].when() == when) {
|
|
when++;
|
|
}
|
|
|
|
schedule(activateThreadEvent[tid], when);
|
|
}
|
|
}
|
|
|
|
/** Unschedule actiavte thread event, regardless of its current state. */
|
|
void
|
|
unscheduleActivateThreadEvent(ThreadID tid)
|
|
{
|
|
if (activateThreadEvent[tid].scheduled())
|
|
activateThreadEvent[tid].squash();
|
|
}
|
|
|
|
/** The tick event used for scheduling CPU ticks. */
|
|
ActivateThreadEvent activateThreadEvent[Impl::MaxThreads];
|
|
|
|
class DeallocateContextEvent : public Event
|
|
{
|
|
private:
|
|
/** Number of Thread to deactivate */
|
|
ThreadID tid;
|
|
|
|
/** Should the thread be removed from the CPU? */
|
|
bool remove;
|
|
|
|
/** Pointer to the CPU. */
|
|
FullO3CPU<Impl> *cpu;
|
|
|
|
public:
|
|
/** Constructs the event. */
|
|
DeallocateContextEvent();
|
|
|
|
/** Initialize Event */
|
|
void init(int thread_num, FullO3CPU<Impl> *thread_cpu);
|
|
|
|
/** Processes the event, calling activateThread() on the CPU. */
|
|
void process();
|
|
|
|
/** Sets whether the thread should also be removed from the CPU. */
|
|
void setRemove(bool _remove) { remove = _remove; }
|
|
|
|
/** Returns the description of the event. */
|
|
const char *description() const;
|
|
};
|
|
|
|
/** Schedule cpu to deallocate thread context.*/
|
|
void
|
|
scheduleDeallocateContextEvent(ThreadID tid, bool remove, Cycles delay)
|
|
{
|
|
// Schedule thread to activate, regardless of its current state.
|
|
if (deallocateContextEvent[tid].squashed())
|
|
reschedule(deallocateContextEvent[tid],
|
|
clockEdge(delay));
|
|
else if (!deallocateContextEvent[tid].scheduled())
|
|
schedule(deallocateContextEvent[tid],
|
|
clockEdge(delay));
|
|
}
|
|
|
|
/** Unschedule thread deallocation in CPU */
|
|
void
|
|
unscheduleDeallocateContextEvent(ThreadID tid)
|
|
{
|
|
if (deallocateContextEvent[tid].scheduled())
|
|
deallocateContextEvent[tid].squash();
|
|
}
|
|
|
|
/** The tick event used for scheduling CPU ticks. */
|
|
DeallocateContextEvent deallocateContextEvent[Impl::MaxThreads];
|
|
|
|
/**
|
|
* Check if the pipeline has drained and signal the DrainManager.
|
|
*
|
|
* This method checks if a drain has been requested and if the CPU
|
|
* has drained successfully (i.e., there are no instructions in
|
|
* the pipeline). If the CPU has drained, it deschedules the tick
|
|
* event and signals the drain manager.
|
|
*
|
|
* @return False if a drain hasn't been requested or the CPU
|
|
* hasn't drained, true otherwise.
|
|
*/
|
|
bool tryDrain();
|
|
|
|
/**
|
|
* Perform sanity checks after a drain.
|
|
*
|
|
* This method is called from drain() when it has determined that
|
|
* the CPU is fully drained when gem5 is compiled with the NDEBUG
|
|
* macro undefined. The intention of this method is to do more
|
|
* extensive tests than the isDrained() method to weed out any
|
|
* draining bugs.
|
|
*/
|
|
void drainSanityCheck() const;
|
|
|
|
/** Check if a system is in a drained state. */
|
|
bool isDrained() const;
|
|
|
|
public:
|
|
/** Constructs a CPU with the given parameters. */
|
|
FullO3CPU(DerivO3CPUParams *params);
|
|
/** Destructor. */
|
|
~FullO3CPU();
|
|
|
|
/** Registers statistics. */
|
|
void regStats();
|
|
|
|
void demapPage(Addr vaddr, uint64_t asn)
|
|
{
|
|
this->itb->demapPage(vaddr, asn);
|
|
this->dtb->demapPage(vaddr, asn);
|
|
}
|
|
|
|
void demapInstPage(Addr vaddr, uint64_t asn)
|
|
{
|
|
this->itb->demapPage(vaddr, asn);
|
|
}
|
|
|
|
void demapDataPage(Addr vaddr, uint64_t asn)
|
|
{
|
|
this->dtb->demapPage(vaddr, asn);
|
|
}
|
|
|
|
/** Ticks CPU, calling tick() on each stage, and checking the overall
|
|
* activity to see if the CPU should deschedule itself.
|
|
*/
|
|
void tick();
|
|
|
|
/** Initialize the CPU */
|
|
void init();
|
|
|
|
void startup();
|
|
|
|
/** Returns the Number of Active Threads in the CPU */
|
|
int numActiveThreads()
|
|
{ return activeThreads.size(); }
|
|
|
|
/** Add Thread to Active Threads List */
|
|
void activateThread(ThreadID tid);
|
|
|
|
/** Remove Thread from Active Threads List */
|
|
void deactivateThread(ThreadID tid);
|
|
|
|
/** Setup CPU to insert a thread's context */
|
|
void insertThread(ThreadID tid);
|
|
|
|
/** Remove all of a thread's context from CPU */
|
|
void removeThread(ThreadID tid);
|
|
|
|
/** Count the Total Instructions Committed in the CPU. */
|
|
virtual Counter totalInsts() const;
|
|
|
|
/** Count the Total Ops (including micro ops) committed in the CPU. */
|
|
virtual Counter totalOps() const;
|
|
|
|
/** Add Thread to Active Threads List. */
|
|
void activateContext(ThreadID tid, Cycles delay);
|
|
|
|
/** Remove Thread from Active Threads List */
|
|
void suspendContext(ThreadID tid);
|
|
|
|
/** Remove Thread from Active Threads List &&
|
|
* Possibly Remove Thread Context from CPU.
|
|
*/
|
|
bool scheduleDeallocateContext(ThreadID tid, bool remove,
|
|
Cycles delay = Cycles(1));
|
|
|
|
/** Remove Thread from Active Threads List &&
|
|
* Remove Thread Context from CPU.
|
|
*/
|
|
void haltContext(ThreadID tid);
|
|
|
|
/** Activate a Thread When CPU Resources are Available. */
|
|
void activateWhenReady(ThreadID tid);
|
|
|
|
/** Add or Remove a Thread Context in the CPU. */
|
|
void doContextSwitch();
|
|
|
|
/** Update The Order In Which We Process Threads. */
|
|
void updateThreadPriority();
|
|
|
|
/** Is the CPU draining? */
|
|
bool isDraining() const { return getDrainState() == Drainable::Draining; }
|
|
|
|
void serializeThread(std::ostream &os, ThreadID tid);
|
|
|
|
void unserializeThread(Checkpoint *cp, const std::string §ion,
|
|
ThreadID tid);
|
|
|
|
public:
|
|
/** Executes a syscall.
|
|
* @todo: Determine if this needs to be virtual.
|
|
*/
|
|
void syscall(int64_t callnum, ThreadID tid);
|
|
|
|
/** Starts draining the CPU's pipeline of all instructions in
|
|
* order to stop all memory accesses. */
|
|
unsigned int drain(DrainManager *drain_manager);
|
|
|
|
/** Resumes execution after a drain. */
|
|
void drainResume();
|
|
|
|
/**
|
|
* Commit has reached a safe point to drain a thread.
|
|
*
|
|
* Commit calls this method to inform the pipeline that it has
|
|
* reached a point where it is not executed microcode and is about
|
|
* to squash uncommitted instructions to fully drain the pipeline.
|
|
*/
|
|
void commitDrained(ThreadID tid);
|
|
|
|
/** Switches out this CPU. */
|
|
virtual void switchOut();
|
|
|
|
/** Takes over from another CPU. */
|
|
virtual void takeOverFrom(BaseCPU *oldCPU);
|
|
|
|
/** Get the current instruction sequence number, and increment it. */
|
|
InstSeqNum getAndIncrementInstSeq()
|
|
{ return globalSeqNum++; }
|
|
|
|
/** Traps to handle given fault. */
|
|
void trap(Fault fault, ThreadID tid, StaticInstPtr inst);
|
|
|
|
/** HW return from error interrupt. */
|
|
Fault hwrei(ThreadID tid);
|
|
|
|
bool simPalCheck(int palFunc, ThreadID tid);
|
|
|
|
/** Returns the Fault for any valid interrupt. */
|
|
Fault getInterrupts();
|
|
|
|
/** Processes any an interrupt fault. */
|
|
void processInterrupts(Fault interrupt);
|
|
|
|
/** Halts the CPU. */
|
|
void halt() { panic("Halt not implemented!\n"); }
|
|
|
|
/** 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; }
|
|
|
|
/** Register accessors. Index refers to the physical register index. */
|
|
|
|
/** Reads a miscellaneous register. */
|
|
TheISA::MiscReg readMiscRegNoEffect(int misc_reg, ThreadID tid);
|
|
|
|
/** Reads a misc. register, including any side effects the read
|
|
* might have as defined by the architecture.
|
|
*/
|
|
TheISA::MiscReg readMiscReg(int misc_reg, ThreadID tid);
|
|
|
|
/** Sets a miscellaneous register. */
|
|
void setMiscRegNoEffect(int misc_reg, const TheISA::MiscReg &val,
|
|
ThreadID tid);
|
|
|
|
/** Sets a misc. register, including any side effects the write
|
|
* might have as defined by the architecture.
|
|
*/
|
|
void setMiscReg(int misc_reg, const TheISA::MiscReg &val,
|
|
ThreadID tid);
|
|
|
|
uint64_t readIntReg(int reg_idx);
|
|
|
|
TheISA::FloatReg readFloatReg(int reg_idx);
|
|
|
|
TheISA::FloatRegBits readFloatRegBits(int reg_idx);
|
|
|
|
void setIntReg(int reg_idx, uint64_t val);
|
|
|
|
void setFloatReg(int reg_idx, TheISA::FloatReg val);
|
|
|
|
void setFloatRegBits(int reg_idx, TheISA::FloatRegBits val);
|
|
|
|
uint64_t readArchIntReg(int reg_idx, ThreadID tid);
|
|
|
|
float readArchFloatReg(int reg_idx, ThreadID tid);
|
|
|
|
uint64_t readArchFloatRegInt(int reg_idx, ThreadID tid);
|
|
|
|
/** Architectural register accessors. Looks up in the commit
|
|
* rename table to obtain the true physical index of the
|
|
* architected register first, then accesses that physical
|
|
* register.
|
|
*/
|
|
void setArchIntReg(int reg_idx, uint64_t val, ThreadID tid);
|
|
|
|
void setArchFloatReg(int reg_idx, float val, ThreadID tid);
|
|
|
|
void setArchFloatRegInt(int reg_idx, uint64_t val, ThreadID tid);
|
|
|
|
/** Sets the commit PC state of a specific thread. */
|
|
void pcState(const TheISA::PCState &newPCState, ThreadID tid);
|
|
|
|
/** Reads the commit PC state of a specific thread. */
|
|
TheISA::PCState pcState(ThreadID tid);
|
|
|
|
/** Reads the commit PC of a specific thread. */
|
|
Addr instAddr(ThreadID tid);
|
|
|
|
/** Reads the commit micro PC of a specific thread. */
|
|
MicroPC microPC(ThreadID tid);
|
|
|
|
/** Reads the next PC of a specific thread. */
|
|
Addr nextInstAddr(ThreadID tid);
|
|
|
|
/** Initiates a squash of all in-flight instructions for a given
|
|
* thread. The source of the squash is an external update of
|
|
* state through the TC.
|
|
*/
|
|
void squashFromTC(ThreadID tid);
|
|
|
|
/** Function to add instruction onto the head of the list of the
|
|
* instructions. Used when new instructions are fetched.
|
|
*/
|
|
ListIt addInst(DynInstPtr &inst);
|
|
|
|
/** Function to tell the CPU that an instruction has completed. */
|
|
void instDone(ThreadID tid, DynInstPtr &inst);
|
|
|
|
/** Remove an instruction from the front end of the list. There's
|
|
* no restriction on location of the instruction.
|
|
*/
|
|
void removeFrontInst(DynInstPtr &inst);
|
|
|
|
/** Remove all instructions that are not currently in the ROB.
|
|
* There's also an option to not squash delay slot instructions.*/
|
|
void removeInstsNotInROB(ThreadID tid);
|
|
|
|
/** Remove all instructions younger than the given sequence number. */
|
|
void removeInstsUntil(const InstSeqNum &seq_num, ThreadID tid);
|
|
|
|
/** Removes the instruction pointed to by the iterator. */
|
|
inline void squashInstIt(const ListIt &instIt, ThreadID tid);
|
|
|
|
/** Cleans up all instructions on the remove list. */
|
|
void cleanUpRemovedInsts();
|
|
|
|
/** Debug function to print all instructions on the list. */
|
|
void dumpInsts();
|
|
|
|
public:
|
|
#ifndef NDEBUG
|
|
/** Count of total number of dynamic instructions in flight. */
|
|
int instcount;
|
|
#endif
|
|
|
|
/** List of all the instructions in flight. */
|
|
std::list<DynInstPtr> instList;
|
|
|
|
/** List of all the instructions that will be removed at the end of this
|
|
* cycle.
|
|
*/
|
|
std::queue<ListIt> removeList;
|
|
|
|
#ifdef DEBUG
|
|
/** Debug structure to keep track of the sequence numbers still in
|
|
* flight.
|
|
*/
|
|
std::set<InstSeqNum> snList;
|
|
#endif
|
|
|
|
/** Records if instructions need to be removed this cycle due to
|
|
* being retired or squashed.
|
|
*/
|
|
bool removeInstsThisCycle;
|
|
|
|
protected:
|
|
/** The fetch stage. */
|
|
typename CPUPolicy::Fetch fetch;
|
|
|
|
/** The decode stage. */
|
|
typename CPUPolicy::Decode decode;
|
|
|
|
/** The dispatch stage. */
|
|
typename CPUPolicy::Rename rename;
|
|
|
|
/** The issue/execute/writeback stages. */
|
|
typename CPUPolicy::IEW iew;
|
|
|
|
/** The commit stage. */
|
|
typename CPUPolicy::Commit commit;
|
|
|
|
/** The register file. */
|
|
typename CPUPolicy::RegFile regFile;
|
|
|
|
/** The free list. */
|
|
typename CPUPolicy::FreeList freeList;
|
|
|
|
/** The rename map. */
|
|
typename CPUPolicy::RenameMap renameMap[Impl::MaxThreads];
|
|
|
|
/** The commit rename map. */
|
|
typename CPUPolicy::RenameMap commitRenameMap[Impl::MaxThreads];
|
|
|
|
/** The re-order buffer. */
|
|
typename CPUPolicy::ROB rob;
|
|
|
|
/** Active Threads List */
|
|
std::list<ThreadID> activeThreads;
|
|
|
|
/** Integer Register Scoreboard */
|
|
Scoreboard scoreboard;
|
|
|
|
std::vector<TheISA::ISA *> isa;
|
|
|
|
/** Instruction port. Note that it has to appear after the fetch stage. */
|
|
IcachePort icachePort;
|
|
|
|
/** Data port. Note that it has to appear after the iew stages */
|
|
DcachePort dcachePort;
|
|
|
|
public:
|
|
/** Enum to give each stage a specific index, so when calling
|
|
* activateStage() or deactivateStage(), they can specify which stage
|
|
* is being activated/deactivated.
|
|
*/
|
|
enum StageIdx {
|
|
FetchIdx,
|
|
DecodeIdx,
|
|
RenameIdx,
|
|
IEWIdx,
|
|
CommitIdx,
|
|
NumStages };
|
|
|
|
/** Typedefs from the Impl to get the structs that each of the
|
|
* time buffers should use.
|
|
*/
|
|
typedef typename CPUPolicy::TimeStruct TimeStruct;
|
|
|
|
typedef typename CPUPolicy::FetchStruct FetchStruct;
|
|
|
|
typedef typename CPUPolicy::DecodeStruct DecodeStruct;
|
|
|
|
typedef typename CPUPolicy::RenameStruct RenameStruct;
|
|
|
|
typedef typename CPUPolicy::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;
|
|
|
|
private:
|
|
/** The activity recorder; used to tell if the CPU has any
|
|
* activity remaining or if it can go to idle and deschedule
|
|
* itself.
|
|
*/
|
|
ActivityRecorder activityRec;
|
|
|
|
public:
|
|
/** Records that there was time buffer activity this cycle. */
|
|
void activityThisCycle() { activityRec.activity(); }
|
|
|
|
/** Changes a stage's status to active within the activity recorder. */
|
|
void activateStage(const StageIdx idx)
|
|
{ activityRec.activateStage(idx); }
|
|
|
|
/** Changes a stage's status to inactive within the activity recorder. */
|
|
void deactivateStage(const StageIdx idx)
|
|
{ activityRec.deactivateStage(idx); }
|
|
|
|
/** Wakes the CPU, rescheduling the CPU if it's not already active. */
|
|
void wakeCPU();
|
|
|
|
virtual void wakeup();
|
|
|
|
/** Gets a free thread id. Use if thread ids change across system. */
|
|
ThreadID getFreeTid();
|
|
|
|
public:
|
|
/** Returns a pointer to a thread context. */
|
|
ThreadContext *
|
|
tcBase(ThreadID tid)
|
|
{
|
|
return thread[tid]->getTC();
|
|
}
|
|
|
|
/** The global sequence number counter. */
|
|
InstSeqNum globalSeqNum;//[Impl::MaxThreads];
|
|
|
|
/** Pointer to the checker, which can dynamically verify
|
|
* instruction results at run time. This can be set to NULL if it
|
|
* is not being used.
|
|
*/
|
|
Checker<Impl> *checker;
|
|
|
|
/** Pointer to the system. */
|
|
System *system;
|
|
|
|
/** DrainManager to notify when draining has completed. */
|
|
DrainManager *drainManager;
|
|
|
|
/** Pointers to all of the threads in the CPU. */
|
|
std::vector<Thread *> thread;
|
|
|
|
/** Is there a context switch pending? */
|
|
bool contextSwitch;
|
|
|
|
/** Threads Scheduled to Enter CPU */
|
|
std::list<int> cpuWaitList;
|
|
|
|
/** The cycle that the CPU was last running, used for statistics. */
|
|
Cycles lastRunningCycle;
|
|
|
|
/** The cycle that the CPU was last activated by a new thread*/
|
|
Tick lastActivatedCycle;
|
|
|
|
/** Mapping for system thread id to cpu id */
|
|
std::map<ThreadID, unsigned> threadMap;
|
|
|
|
/** Available thread ids in the cpu*/
|
|
std::vector<ThreadID> tids;
|
|
|
|
/** CPU read function, forwards read to LSQ. */
|
|
Fault read(RequestPtr &req, RequestPtr &sreqLow, RequestPtr &sreqHigh,
|
|
uint8_t *data, int load_idx)
|
|
{
|
|
return this->iew.ldstQueue.read(req, sreqLow, sreqHigh,
|
|
data, load_idx);
|
|
}
|
|
|
|
/** CPU write function, forwards write to LSQ. */
|
|
Fault write(RequestPtr &req, RequestPtr &sreqLow, RequestPtr &sreqHigh,
|
|
uint8_t *data, int store_idx)
|
|
{
|
|
return this->iew.ldstQueue.write(req, sreqLow, sreqHigh,
|
|
data, store_idx);
|
|
}
|
|
|
|
/** Used by the fetch unit to get a hold of the instruction port. */
|
|
virtual CpuPort &getInstPort() { return icachePort; }
|
|
|
|
/** Get the dcache port (used to find block size for translations). */
|
|
virtual CpuPort &getDataPort() { return dcachePort; }
|
|
|
|
/** Stat for total number of times the CPU is descheduled. */
|
|
Stats::Scalar timesIdled;
|
|
/** Stat for total number of cycles the CPU spends descheduled. */
|
|
Stats::Scalar idleCycles;
|
|
/** Stat for total number of cycles the CPU spends descheduled due to a
|
|
* quiesce operation or waiting for an interrupt. */
|
|
Stats::Scalar quiesceCycles;
|
|
/** Stat for the number of committed instructions per thread. */
|
|
Stats::Vector committedInsts;
|
|
/** Stat for the number of committed ops (including micro ops) per thread. */
|
|
Stats::Vector committedOps;
|
|
/** Stat for the total number of committed instructions. */
|
|
Stats::Scalar totalCommittedInsts;
|
|
/** Stat for the CPI per thread. */
|
|
Stats::Formula cpi;
|
|
/** Stat for the total CPI. */
|
|
Stats::Formula totalCpi;
|
|
/** Stat for the IPC per thread. */
|
|
Stats::Formula ipc;
|
|
/** Stat for the total IPC. */
|
|
Stats::Formula totalIpc;
|
|
|
|
//number of integer register file accesses
|
|
Stats::Scalar intRegfileReads;
|
|
Stats::Scalar intRegfileWrites;
|
|
//number of float register file accesses
|
|
Stats::Scalar fpRegfileReads;
|
|
Stats::Scalar fpRegfileWrites;
|
|
//number of misc
|
|
Stats::Scalar miscRegfileReads;
|
|
Stats::Scalar miscRegfileWrites;
|
|
};
|
|
|
|
#endif // __CPU_O3_CPU_HH__
|