Move Dcache port creation from LSQUnit to LSQ in order to support Ron's recent changes, and using the O3CPU in SMT mode.
src/cpu/o3/lsq.hh: Update to have LSQ work with only one dcache port for all LSQ Units. LSQ has the dcache port, and the LSQ Units must tell the LSQ if the cache has become blocked. src/cpu/o3/lsq_impl.hh: Updates to have the LSQ work with only one dcache port for all LSQUnits. src/cpu/o3/lsq_unit.hh: src/cpu/o3/lsq_unit_impl.hh: Update for LSQ to create dcache port instead of LSQUnits. Now LSQUnits are given the dcache port from the LSQ, and also must check the LSQ if the cache is blocked prior to accessing the cache. --HG-- extra : convert_revision : 2708adbf323f4e7647dc0c1e31ef5bb4596b89f8
This commit is contained in:
parent
2af213022c
commit
1e4acb8e01
4 changed files with 139 additions and 112 deletions
|
@ -70,7 +70,7 @@ class LSQ {
|
|||
* to work. For now it just returns the port from one of the
|
||||
* threads.
|
||||
*/
|
||||
Port *getDcachePort() { return thread[0].getDcachePort(); }
|
||||
Port *getDcachePort() { return &dcachePort; }
|
||||
|
||||
/** Sets the pointer to the list of active threads. */
|
||||
void setActiveThreads(std::list<unsigned> *at_ptr);
|
||||
|
@ -258,6 +258,15 @@ class LSQ {
|
|||
bool willWB(unsigned tid)
|
||||
{ return thread[tid].willWB(); }
|
||||
|
||||
/** Returns if the cache is currently blocked. */
|
||||
bool cacheBlocked()
|
||||
{ return retryTid != -1; }
|
||||
|
||||
/** Sets the retry thread id, indicating that one of the LSQUnits
|
||||
* tried to access the cache but the cache was blocked. */
|
||||
void setRetryTid(int tid)
|
||||
{ retryTid = tid; }
|
||||
|
||||
/** Debugging function to print out all instructions. */
|
||||
void dumpInsts();
|
||||
/** Debugging function to print out instructions from a specific thread. */
|
||||
|
@ -274,7 +283,49 @@ class LSQ {
|
|||
template <class T>
|
||||
Fault write(RequestPtr req, T &data, int store_idx);
|
||||
|
||||
private:
|
||||
/** DcachePort class for this LSQ. Handles doing the
|
||||
* communication with the cache/memory.
|
||||
*/
|
||||
class DcachePort : public Port
|
||||
{
|
||||
protected:
|
||||
/** Pointer to LSQ. */
|
||||
LSQ *lsq;
|
||||
|
||||
public:
|
||||
/** Default constructor. */
|
||||
DcachePort(LSQ *_lsq)
|
||||
: lsq(_lsq)
|
||||
{ }
|
||||
|
||||
protected:
|
||||
/** Atomic version of receive. Panics. */
|
||||
virtual Tick recvAtomic(PacketPtr pkt);
|
||||
|
||||
/** Functional version of receive. Panics. */
|
||||
virtual void recvFunctional(PacketPtr pkt);
|
||||
|
||||
/** Receives status change. Other than range changing, panics. */
|
||||
virtual void recvStatusChange(Status status);
|
||||
|
||||
/** Returns the address ranges of this device. */
|
||||
virtual void getDeviceAddressRanges(AddrRangeList &resp,
|
||||
AddrRangeList &snoop)
|
||||
{ resp.clear(); snoop.clear(); }
|
||||
|
||||
/** Timing version of receive. Handles writing back and
|
||||
* completing the load or store that has returned from
|
||||
* memory. */
|
||||
virtual bool recvTiming(PacketPtr pkt);
|
||||
|
||||
/** Handles doing a retry of the previous send. */
|
||||
virtual void recvRetry();
|
||||
};
|
||||
|
||||
/** D-cache port. */
|
||||
DcachePort dcachePort;
|
||||
|
||||
protected:
|
||||
/** The LSQ policy for SMT mode. */
|
||||
LSQPolicy lsqPolicy;
|
||||
|
||||
|
@ -303,6 +354,10 @@ class LSQ {
|
|||
|
||||
/** Number of Threads. */
|
||||
unsigned numThreads;
|
||||
|
||||
/** The thread id of the LSQ Unit that is currently waiting for a
|
||||
* retry. */
|
||||
int retryTid;
|
||||
};
|
||||
|
||||
template <class Impl>
|
||||
|
|
|
@ -35,10 +35,54 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
template <class Impl>
|
||||
Tick
|
||||
LSQ<Impl>::DcachePort::recvAtomic(PacketPtr pkt)
|
||||
{
|
||||
panic("O3CPU model does not work with atomic mode!");
|
||||
return curTick;
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
LSQ<Impl>::DcachePort::recvFunctional(PacketPtr pkt)
|
||||
{
|
||||
panic("O3CPU doesn't expect recvFunctional callback!");
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
LSQ<Impl>::DcachePort::recvStatusChange(Status status)
|
||||
{
|
||||
if (status == RangeChange)
|
||||
return;
|
||||
|
||||
panic("O3CPU doesn't expect recvStatusChange callback!");
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
bool
|
||||
LSQ<Impl>::DcachePort::recvTiming(PacketPtr pkt)
|
||||
{
|
||||
lsq->thread[pkt->req->getThreadNum()].completeDataAccess(pkt);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
LSQ<Impl>::DcachePort::recvRetry()
|
||||
{
|
||||
lsq->thread[lsq->retryTid].recvRetry();
|
||||
// Speculatively clear the retry Tid. This will get set again if
|
||||
// the LSQUnit was unable to complete its access.
|
||||
lsq->retryTid = -1;
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
LSQ<Impl>::LSQ(Params *params)
|
||||
: LQEntries(params->LQEntries), SQEntries(params->SQEntries),
|
||||
numThreads(params->numberOfThreads)
|
||||
: dcachePort(this), LQEntries(params->LQEntries),
|
||||
SQEntries(params->SQEntries), numThreads(params->numberOfThreads),
|
||||
retryTid(-1)
|
||||
{
|
||||
DPRINTF(LSQ, "Creating LSQ object.\n");
|
||||
|
||||
|
@ -94,7 +138,8 @@ LSQ<Impl>::LSQ(Params *params)
|
|||
|
||||
//Initialize LSQs
|
||||
for (int tid=0; tid < numThreads; tid++) {
|
||||
thread[tid].init(params, maxLQEntries, maxSQEntries, tid);
|
||||
thread[tid].init(params, this, maxLQEntries, maxSQEntries, tid);
|
||||
thread[tid].setDcachePort(&dcachePort);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -130,6 +175,8 @@ LSQ<Impl>::setCPU(O3CPU *cpu_ptr)
|
|||
{
|
||||
cpu = cpu_ptr;
|
||||
|
||||
dcachePort.setName(name());
|
||||
|
||||
for (int tid=0; tid < numThreads; tid++) {
|
||||
thread[tid].setCPU(cpu_ptr);
|
||||
}
|
||||
|
|
|
@ -64,6 +64,7 @@ class LSQUnit {
|
|||
typedef typename Impl::O3CPU O3CPU;
|
||||
typedef typename Impl::DynInstPtr DynInstPtr;
|
||||
typedef typename Impl::CPUPol::IEW IEW;
|
||||
typedef typename Impl::CPUPol::LSQ LSQ;
|
||||
typedef typename Impl::CPUPol::IssueStruct IssueStruct;
|
||||
|
||||
public:
|
||||
|
@ -71,17 +72,12 @@ class LSQUnit {
|
|||
LSQUnit();
|
||||
|
||||
/** Initializes the LSQ unit with the specified number of entries. */
|
||||
void init(Params *params, unsigned maxLQEntries,
|
||||
void init(Params *params, LSQ *lsq_ptr, unsigned maxLQEntries,
|
||||
unsigned maxSQEntries, unsigned id);
|
||||
|
||||
/** Returns the name of the LSQ unit. */
|
||||
std::string name() const;
|
||||
|
||||
/** Returns the dcache port.
|
||||
* @todo: Remove this once the port moves up to the LSQ level.
|
||||
*/
|
||||
Port *getDcachePort() { return dcachePort; }
|
||||
|
||||
/** Registers statistics. */
|
||||
void regStats();
|
||||
|
||||
|
@ -92,6 +88,10 @@ class LSQUnit {
|
|||
void setIEW(IEW *iew_ptr)
|
||||
{ iewStage = iew_ptr; }
|
||||
|
||||
/** Sets the pointer to the dcache port. */
|
||||
void setDcachePort(Port *dcache_port)
|
||||
{ dcachePort = dcache_port; }
|
||||
|
||||
/** Switches out LSQ unit. */
|
||||
void switchOut();
|
||||
|
||||
|
@ -211,6 +211,9 @@ class LSQUnit {
|
|||
!storeQueue[storeWBIdx].completed &&
|
||||
!isStoreBlocked; }
|
||||
|
||||
/** Handles doing the retry. */
|
||||
void recvRetry();
|
||||
|
||||
private:
|
||||
/** Writes back the instruction, sending it to IEW. */
|
||||
void writeback(DynInstPtr &inst, PacketPtr pkt);
|
||||
|
@ -221,9 +224,6 @@ class LSQUnit {
|
|||
/** Completes the store at the specified index. */
|
||||
void completeStore(int store_idx);
|
||||
|
||||
/** Handles doing the retry. */
|
||||
void recvRetry();
|
||||
|
||||
/** Increments the given store index (circular queue). */
|
||||
inline void incrStIdx(int &store_idx);
|
||||
/** Decrements the given store index (circular queue). */
|
||||
|
@ -244,54 +244,11 @@ class LSQUnit {
|
|||
/** Pointer to the IEW stage. */
|
||||
IEW *iewStage;
|
||||
|
||||
/** Pointer to memory object. */
|
||||
MemObject *mem;
|
||||
/** Pointer to the LSQ. */
|
||||
LSQ *lsq;
|
||||
|
||||
/** DcachePort class for this LSQ Unit. Handles doing the
|
||||
* communication with the cache/memory.
|
||||
* @todo: Needs to be moved to the LSQ level and have some sort
|
||||
* of arbitration.
|
||||
*/
|
||||
class DcachePort : public Port
|
||||
{
|
||||
protected:
|
||||
/** Pointer to CPU. */
|
||||
O3CPU *cpu;
|
||||
/** Pointer to LSQ. */
|
||||
LSQUnit *lsq;
|
||||
|
||||
public:
|
||||
/** Default constructor. */
|
||||
DcachePort(O3CPU *_cpu, LSQUnit *_lsq)
|
||||
: Port(_lsq->name() + "-dport"), cpu(_cpu), lsq(_lsq)
|
||||
{ }
|
||||
|
||||
protected:
|
||||
/** Atomic version of receive. Panics. */
|
||||
virtual Tick recvAtomic(PacketPtr pkt);
|
||||
|
||||
/** Functional version of receive. Panics. */
|
||||
virtual void recvFunctional(PacketPtr pkt);
|
||||
|
||||
/** Receives status change. Other than range changing, panics. */
|
||||
virtual void recvStatusChange(Status status);
|
||||
|
||||
/** Returns the address ranges of this device. */
|
||||
virtual void getDeviceAddressRanges(AddrRangeList &resp,
|
||||
AddrRangeList &snoop)
|
||||
{ resp.clear(); snoop.clear(); }
|
||||
|
||||
/** Timing version of receive. Handles writing back and
|
||||
* completing the load or store that has returned from
|
||||
* memory. */
|
||||
virtual bool recvTiming(PacketPtr pkt);
|
||||
|
||||
/** Handles doing a retry of the previous send. */
|
||||
virtual void recvRetry();
|
||||
};
|
||||
|
||||
/** Pointer to the D-cache. */
|
||||
DcachePort *dcachePort;
|
||||
/** Pointer to the dcache port. Used only for sending. */
|
||||
Port *dcachePort;
|
||||
|
||||
/** Derived class to hold any sender state the LSQ needs. */
|
||||
class LSQSenderState : public Packet::SenderState
|
||||
|
@ -658,7 +615,7 @@ LSQUnit<Impl>::read(Request *req, T &data, int load_idx)
|
|||
}
|
||||
|
||||
// If there's no forwarding case, then go access memory
|
||||
DPRINTF(LSQUnit, "Doing functional access for inst [sn:%lli] PC %#x\n",
|
||||
DPRINTF(LSQUnit, "Doing memory access for inst [sn:%lli] PC %#x\n",
|
||||
load_inst->seqNum, load_inst->readPC());
|
||||
|
||||
assert(!load_inst->memData);
|
||||
|
@ -666,9 +623,6 @@ LSQUnit<Impl>::read(Request *req, T &data, int load_idx)
|
|||
|
||||
++usedPorts;
|
||||
|
||||
DPRINTF(LSQUnit, "Doing timing access for inst PC %#x\n",
|
||||
load_inst->readPC());
|
||||
|
||||
PacketPtr data_pkt = new Packet(req, Packet::ReadReq, Packet::Broadcast);
|
||||
data_pkt->dataStatic(load_inst->memData);
|
||||
|
||||
|
@ -678,8 +632,18 @@ LSQUnit<Impl>::read(Request *req, T &data, int load_idx)
|
|||
state->inst = load_inst;
|
||||
data_pkt->senderState = state;
|
||||
|
||||
// if we have a cache, do cache access too
|
||||
// if we the cache is not blocked, do cache access
|
||||
if (!lsq->cacheBlocked()) {
|
||||
if (!dcachePort->sendTiming(data_pkt)) {
|
||||
// If the access didn't succeed, tell the LSQ by setting
|
||||
// the retry thread id.
|
||||
lsq->setRetryTid(lsqID);
|
||||
}
|
||||
}
|
||||
|
||||
// If the cache was blocked, or has become blocked due to the access,
|
||||
// handle it.
|
||||
if (lsq->cacheBlocked()) {
|
||||
++lsqCacheBlocked;
|
||||
// There's an older load that's already going to squash.
|
||||
if (isLoadBlocked && blockedLoadSeqNum < load_inst->seqNum)
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
|
||||
#include "config/use_checker.hh"
|
||||
|
||||
#include "cpu/o3/lsq.hh"
|
||||
#include "cpu/o3/lsq_unit.hh"
|
||||
#include "base/str.hh"
|
||||
#include "mem/packet.hh"
|
||||
|
@ -95,46 +96,6 @@ LSQUnit<Impl>::completeDataAccess(PacketPtr pkt)
|
|||
delete pkt;
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
Tick
|
||||
LSQUnit<Impl>::DcachePort::recvAtomic(PacketPtr pkt)
|
||||
{
|
||||
panic("O3CPU model does not work with atomic mode!");
|
||||
return curTick;
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
LSQUnit<Impl>::DcachePort::recvFunctional(PacketPtr pkt)
|
||||
{
|
||||
panic("O3CPU doesn't expect recvFunctional callback!");
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
LSQUnit<Impl>::DcachePort::recvStatusChange(Status status)
|
||||
{
|
||||
if (status == RangeChange)
|
||||
return;
|
||||
|
||||
panic("O3CPU doesn't expect recvStatusChange callback!");
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
bool
|
||||
LSQUnit<Impl>::DcachePort::recvTiming(PacketPtr pkt)
|
||||
{
|
||||
lsq->completeDataAccess(pkt);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
LSQUnit<Impl>::DcachePort::recvRetry()
|
||||
{
|
||||
lsq->recvRetry();
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
LSQUnit<Impl>::LSQUnit()
|
||||
: loads(0), stores(0), storesToWB(0), stalled(false),
|
||||
|
@ -145,13 +106,15 @@ LSQUnit<Impl>::LSQUnit()
|
|||
|
||||
template<class Impl>
|
||||
void
|
||||
LSQUnit<Impl>::init(Params *params, unsigned maxLQEntries,
|
||||
LSQUnit<Impl>::init(Params *params, LSQ *lsq_ptr, unsigned maxLQEntries,
|
||||
unsigned maxSQEntries, unsigned id)
|
||||
{
|
||||
DPRINTF(LSQUnit, "Creating LSQUnit%i object.\n",id);
|
||||
|
||||
switchedOut = false;
|
||||
|
||||
lsq = lsq_ptr;
|
||||
|
||||
lsqID = id;
|
||||
|
||||
// Add 1 for the sentinel entry (they are circular queues).
|
||||
|
@ -168,8 +131,6 @@ LSQUnit<Impl>::init(Params *params, unsigned maxLQEntries,
|
|||
usedPorts = 0;
|
||||
cachePorts = params->cachePorts;
|
||||
|
||||
mem = params->mem;
|
||||
|
||||
memDepViolator = NULL;
|
||||
|
||||
blockedLoadSeqNum = 0;
|
||||
|
@ -180,7 +141,6 @@ void
|
|||
LSQUnit<Impl>::setCPU(O3CPU *cpu_ptr)
|
||||
{
|
||||
cpu = cpu_ptr;
|
||||
dcachePort = new DcachePort(cpu, this);
|
||||
|
||||
#if USE_CHECKER
|
||||
if (cpu->checker) {
|
||||
|
@ -588,7 +548,7 @@ LSQUnit<Impl>::writebackStores()
|
|||
storeQueue[storeWBIdx].canWB &&
|
||||
usedPorts < cachePorts) {
|
||||
|
||||
if (isStoreBlocked) {
|
||||
if (isStoreBlocked || lsq->cacheBlocked()) {
|
||||
DPRINTF(LSQUnit, "Unable to write back any more stores, cache"
|
||||
" is blocked!\n");
|
||||
break;
|
||||
|
@ -911,6 +871,7 @@ LSQUnit<Impl>::recvRetry()
|
|||
} else {
|
||||
// Still blocked!
|
||||
++lsqCacheBlocked;
|
||||
lsq->setRetryTid(lsqID);
|
||||
}
|
||||
} else if (isLoadBlocked) {
|
||||
DPRINTF(LSQUnit, "Loads squash themselves and all younger insts, "
|
||||
|
|
Loading…
Reference in a new issue