Blocked_NoTargets,
Blocked_NoWBBuffers,
Blocked_Coherence,
- Blocked_Copy,
NUM_BLOCKED_CAUSES
};
CachePort(const std::string &_name, BaseCache *_cache, bool _isCpuSide);
protected:
- virtual bool recvTiming(Packet *pkt);
+ virtual bool recvTiming(PacketPtr pkt);
- virtual Tick recvAtomic(Packet *pkt);
+ virtual Tick recvAtomic(PacketPtr pkt);
- virtual void recvFunctional(Packet *pkt);
+ virtual void recvFunctional(PacketPtr pkt);
virtual void recvStatusChange(Status status);
void clearBlocked();
+ bool checkFunctional(PacketPtr pkt);
+
+ void checkAndSendFunctional(PacketPtr pkt);
+
+ bool canDrain() { return drainList.empty() && transmitList.empty(); }
+
bool blocked;
bool mustSendRetry;
bool waitingOnRetry;
- std::list<Packet *> drainList;
+ std::list<PacketPtr> drainList;
- Packet *cshrRetry;
+ std::list<std::pair<Tick,PacketPtr> > transmitList;
};
struct CacheEvent : public Event
{
CachePort *cachePort;
- Packet *pkt;
+ PacketPtr pkt;
+ bool newResponse;
- CacheEvent(CachePort *_cachePort);
- CacheEvent(CachePort *_cachePort, Packet *_pkt);
+ CacheEvent(CachePort *_cachePort, bool response);
void process();
const char *description();
};
- protected:
+ public: //Made public so coherence can get at it.
CachePort *cpuSidePort;
- CachePort *memSidePort;
- bool snoopRangesSent;
+ CacheEvent *sendEvent;
+ CacheEvent *memSendEvent;
+
+ protected:
+ CachePort *memSidePort;
public:
virtual Port *getPort(const std::string &if_name, int idx = -1);
private:
//To be defined in cache_impl.hh not in base class
- virtual bool doTimingAccess(Packet *pkt, CachePort *cachePort, bool isCpuSide)
+ virtual bool doTimingAccess(PacketPtr pkt, CachePort *cachePort, bool isCpuSide)
{
fatal("No implementation");
}
- virtual Tick doAtomicAccess(Packet *pkt, bool isCpuSide)
+ virtual Tick doAtomicAccess(PacketPtr pkt, bool isCpuSide)
{
fatal("No implementation");
}
- virtual void doFunctionalAccess(Packet *pkt, bool isCpuSide)
+ virtual void doFunctionalAccess(PacketPtr pkt, bool isCpuSide)
{
fatal("No implementation");
}
if (status == Port::RangeChange){
if (!isCpuSide) {
cpuSidePort->sendStatusChange(Port::RangeChange);
- if (!snoopRangesSent) {
- snoopRangesSent = true;
- memSidePort->sendStatusChange(Port::RangeChange);
- }
}
else {
memSidePort->sendStatusChange(Port::RangeChange);
}
}
- virtual Packet *getPacket()
+ virtual PacketPtr getPacket()
{
fatal("No implementation");
}
- virtual Packet *getCoherencePacket()
+ virtual PacketPtr getCoherencePacket()
{
fatal("No implementation");
}
- virtual void sendResult(Packet* &pkt, MSHR* mshr, bool success)
+ virtual void sendResult(PacketPtr &pkt, MSHR* mshr, bool success)
+ {
+
+ fatal("No implementation");
+ }
+
+ virtual void sendCoherenceResult(PacketPtr &pkt, MSHR* mshr, bool success)
{
fatal("No implementation");
protected:
- /** True if this cache is connected to the CPU. */
- bool topLevelCache;
-
-
/** Stores time the cache blocked for statistics. */
Tick blockedCycle;
/** The number of misses to trigger an exit event. */
Counter missCount;
+ /** The drain event. */
+ Event *drainEvent;
+
public:
// Statistics
/**
*/
BaseCache(const std::string &name, Params ¶ms)
: MemObject(name), blocked(0), blockedSnoop(0), masterRequests(0),
- slaveRequests(0), topLevelCache(false), blkSize(params.blkSize),
- missCount(params.maxMisses)
+ slaveRequests(0), blkSize(params.blkSize),
+ missCount(params.maxMisses), drainEvent(NULL)
{
//Start ports at null if more than one is created we should panic
cpuSidePort = NULL;
memSidePort = NULL;
- snoopRangesSent = false;
+ }
+
+ ~BaseCache()
+ {
+ delete sendEvent;
+ delete memSendEvent;
}
virtual void init();
return blkSize;
}
- /**
- * Returns true if this cache is connect to the CPU.
- * @return True if this is a L1 cache.
- */
- bool isTopLevel()
- {
- return topLevelCache;
- }
-
/**
* Returns true if the cache is blocked for accesses.
*/
{
if (!doMasterRequest() && !memSidePort->waitingOnRetry)
{
- BaseCache::CacheEvent * reqCpu = new BaseCache::CacheEvent(memSidePort);
+ BaseCache::CacheEvent * reqCpu =
+ new BaseCache::CacheEvent(memSidePort, false);
reqCpu->schedule(time);
}
uint8_t flag = 1<<cause;
{
uint8_t flag = 1<<cause;
masterRequests &= ~flag;
+ checkDrain();
}
/**
*/
void setSlaveRequest(RequestCause cause, Tick time)
{
+ if (!doSlaveRequest() && !cpuSidePort->waitingOnRetry)
+ {
+ BaseCache::CacheEvent * reqCpu =
+ new BaseCache::CacheEvent(cpuSidePort, false);
+ reqCpu->schedule(time);
+ }
uint8_t flag = 1<<cause;
slaveRequests |= flag;
- assert("Implement\n" && 0);
-// si->pktuest(time);
}
/**
{
uint8_t flag = 1<<cause;
slaveRequests &= ~flag;
+ checkDrain();
}
/**
* @param pkt The request being responded to.
* @param time The time the response is ready.
*/
- void respond(Packet *pkt, Tick time)
+ void respond(PacketPtr pkt, Tick time)
{
+ assert(time >= curTick);
if (pkt->needsResponse()) {
- CacheEvent *reqCpu = new CacheEvent(cpuSidePort, pkt);
+/* CacheEvent *reqCpu = new CacheEvent(cpuSidePort, pkt);
reqCpu->schedule(time);
+*/
+ if (cpuSidePort->transmitList.empty()) {
+ assert(!sendEvent->scheduled());
+ sendEvent->schedule(time);
+ cpuSidePort->transmitList.push_back(std::pair<Tick,PacketPtr>
+ (time,pkt));
+ return;
+ }
+
+ // something is on the list and this belongs at the end
+ if (time >= cpuSidePort->transmitList.back().first) {
+ cpuSidePort->transmitList.push_back(std::pair<Tick,PacketPtr>
+ (time,pkt));
+ return;
+ }
+ // Something is on the list and this belongs somewhere else
+ std::list<std::pair<Tick,PacketPtr> >::iterator i =
+ cpuSidePort->transmitList.begin();
+ std::list<std::pair<Tick,PacketPtr> >::iterator end =
+ cpuSidePort->transmitList.end();
+ bool done = false;
+
+ while (i != end && !done) {
+ if (time < i->first) {
+ if (i == cpuSidePort->transmitList.begin()) {
+ //Inserting at begining, reschedule
+ sendEvent->reschedule(time);
+ }
+ cpuSidePort->transmitList.insert(i,std::pair<Tick,PacketPtr>
+ (time,pkt));
+ done = true;
+ }
+ i++;
+ }
}
else {
- if (pkt->cmd == Packet::Writeback) delete pkt->req;
- delete pkt;
+ if (pkt->cmd != Packet::UpgradeReq)
+ {
+ delete pkt->req;
+ delete pkt;
+ }
}
}
* @param pkt The request to respond to.
* @param time The time the response is ready.
*/
- void respondToMiss(Packet *pkt, Tick time)
+ void respondToMiss(PacketPtr pkt, Tick time)
{
+ assert(time >= curTick);
if (!pkt->req->isUncacheable()) {
- missLatency[pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/] += time - pkt->time;
+ missLatency[pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/] +=
+ time - pkt->time;
}
if (pkt->needsResponse()) {
- CacheEvent *reqCpu = new CacheEvent(cpuSidePort, pkt);
+/* CacheEvent *reqCpu = new CacheEvent(cpuSidePort, pkt);
reqCpu->schedule(time);
+*/
+ if (cpuSidePort->transmitList.empty()) {
+ assert(!sendEvent->scheduled());
+ sendEvent->schedule(time);
+ cpuSidePort->transmitList.push_back(std::pair<Tick,PacketPtr>
+ (time,pkt));
+ return;
+ }
+
+ // something is on the list and this belongs at the end
+ if (time >= cpuSidePort->transmitList.back().first) {
+ cpuSidePort->transmitList.push_back(std::pair<Tick,PacketPtr>
+ (time,pkt));
+ return;
+ }
+ // Something is on the list and this belongs somewhere else
+ std::list<std::pair<Tick,PacketPtr> >::iterator i =
+ cpuSidePort->transmitList.begin();
+ std::list<std::pair<Tick,PacketPtr> >::iterator end =
+ cpuSidePort->transmitList.end();
+ bool done = false;
+
+ while (i != end && !done) {
+ if (time < i->first) {
+ if (i == cpuSidePort->transmitList.begin()) {
+ //Inserting at begining, reschedule
+ sendEvent->reschedule(time);
+ }
+ cpuSidePort->transmitList.insert(i,std::pair<Tick,PacketPtr>
+ (time,pkt));
+ done = true;
+ }
+ i++;
+ }
}
else {
- if (pkt->cmd == Packet::Writeback) delete pkt->req;
- delete pkt;
+ if (pkt->cmd != Packet::UpgradeReq)
+ {
+ delete pkt->req;
+ delete pkt;
+ }
}
}
* Suppliess the data if cache to cache transfers are enabled.
* @param pkt The bus transaction to fulfill.
*/
- void respondToSnoop(Packet *pkt, Tick time)
+ void respondToSnoop(PacketPtr pkt, Tick time)
{
-// assert("Implement\n" && 0);
-// mi->respond(pkt,curTick + hitLatency);
+ assert(time >= curTick);
assert (pkt->needsResponse());
- CacheEvent *reqMem = new CacheEvent(memSidePort, pkt);
+/* CacheEvent *reqMem = new CacheEvent(memSidePort, pkt);
reqMem->schedule(time);
+*/
+ if (memSidePort->transmitList.empty()) {
+ assert(!memSendEvent->scheduled());
+ memSendEvent->schedule(time);
+ memSidePort->transmitList.push_back(std::pair<Tick,PacketPtr>
+ (time,pkt));
+ return;
+ }
+
+ // something is on the list and this belongs at the end
+ if (time >= memSidePort->transmitList.back().first) {
+ memSidePort->transmitList.push_back(std::pair<Tick,PacketPtr>
+ (time,pkt));
+ return;
+ }
+ // Something is on the list and this belongs somewhere else
+ std::list<std::pair<Tick,PacketPtr> >::iterator i =
+ memSidePort->transmitList.begin();
+ std::list<std::pair<Tick,PacketPtr> >::iterator end =
+ memSidePort->transmitList.end();
+ bool done = false;
+
+ while (i != end && !done) {
+ if (time < i->first) {
+ if (i == memSidePort->transmitList.begin()) {
+ //Inserting at begining, reschedule
+ memSendEvent->reschedule(time);
+ }
+ memSidePort->transmitList.insert(i,std::pair<Tick,PacketPtr>(time,pkt));
+ done = true;
+ }
+ i++;
+ }
}
/**
{
//This is where snoops get updated
AddrRangeList dummy;
-// if (!topLevelCache)
-// {
- cpuSidePort->getPeerAddressRanges(dummy, snoop);
-// }
-// else
-// {
-// snoop.push_back(RangeSize(0,-1));
-// }
-
+ cpuSidePort->getPeerAddressRanges(dummy, snoop);
return;
}
}
+
+ virtual unsigned int drain(Event *de);
+
+ void checkDrain()
+ {
+ if (drainEvent && canDrain()) {
+ drainEvent->process();
+ changeState(SimObject::Drained);
+ // Clear the drain event
+ drainEvent = NULL;
+ }
+ }
+
+ bool canDrain()
+ {
+ if (doMasterRequest() || doSlaveRequest()) {
+ return false;
+ } else if (memSidePort && !memSidePort->canDrain()) {
+ return false;
+ } else if (cpuSidePort && !cpuSidePort->canDrain()) {
+ return false;
+ }
+ return true;
+ }
};
#endif //__BASE_CACHE_HH__