MemTest::CpuPort::recvFunctional(Packet *pkt)
{
//Do nothing if we see one come through
+ if (curTick != 0)//Supress warning durring initialization
+ warn("Functional Writes not implemented in MemTester\n");
+ //Need to find any response values that intersect and update
return;
}
memtest->doRetry();
}
+void
+MemTest::sendPkt(Packet *pkt) {
+ if (atomic) {
+ cachePort.sendAtomic(pkt);
+ pkt->makeAtomicResponse();
+ completeRequest(pkt);
+ }
+ else if (!cachePort.sendTiming(pkt)) {
+ accessRetry = true;
+ retryPkt = pkt;
+ }
+
+}
+
MemTest::MemTest(const string &name,
// MemInterface *_cache_interface,
// PhysicalMemory *main_mem,
unsigned _percentSourceUnaligned,
unsigned _percentDestUnaligned,
Addr _traceAddr,
- Counter _max_loads)
+ Counter _max_loads,
+ bool _atomic)
: MemObject(name),
tickEvent(this),
cachePort("test", this),
nextProgressMessage(_progressInterval),
percentSourceUnaligned(_percentSourceUnaligned),
percentDestUnaligned(percentDestUnaligned),
- maxLoads(_max_loads)
+ maxLoads(_max_loads),
+ atomic(_atomic)
{
vector<string> cmd;
cmd.push_back("/bin/ls");
completeRequest(pkt);
} else {
// req->completionEvent = new MemCompleteEvent(req, result, this);
- if (!cachePort.sendTiming(pkt)) {
- accessRetry = true;
- retryPkt = pkt;
- }
+ sendPkt(pkt);
}
} else {
// write
if (probe) {
cachePort.sendFunctional(pkt);
-// completeRequest(req, NULL);
+ completeRequest(pkt);
} else {
// req->completionEvent = new MemCompleteEvent(req, NULL, this);
- if (!cachePort.sendTiming(pkt)) {
- accessRetry = true;
- retryPkt = pkt;
- }
+ sendPkt(pkt);
}
}
/* else {
Param<unsigned> percent_dest_unaligned;
Param<Addr> trace_addr;
Param<Counter> max_loads;
+ Param<bool> atomic;
END_DECLARE_SIM_OBJECT_PARAMS(MemTest)
INIT_PARAM(percent_dest_unaligned,
"percent of copy dest address that are unaligned"),
INIT_PARAM(trace_addr, "address to trace"),
- INIT_PARAM(max_loads, "terminate when we have reached this load count")
+ INIT_PARAM(max_loads, "terminate when we have reached this load count"),
+ INIT_PARAM(atomic, "Is the tester testing atomic mode (or timing)")
END_INIT_SIM_OBJECT_PARAMS(MemTest)
/*check_mem,*/ memory_size, percent_reads, /*percent_copies,*/
percent_uncacheable, progress_interval,
percent_source_unaligned, percent_dest_unaligned,
- trace_addr, max_loads);
+ trace_addr, max_loads, atomic);
}
REGISTER_SIM_OBJECT("MemTest", MemTest)
unsigned _percentSourceUnaligned,
unsigned _percentDestUnaligned,
Addr _traceAddr,
- Counter _max_loads);
+ Counter _max_loads,
+ bool _atomic);
virtual void init();
uint64_t numReads;
uint64_t maxLoads;
+
+ bool atomic;
+
Stats::Scalar<> numReadsStat;
Stats::Scalar<> numWritesStat;
Stats::Scalar<> numCopiesStat;
// called by MemCompleteEvent::process()
void completeRequest(Packet *pkt);
+ void sendPkt(Packet *pkt);
+
void doRetry();
friend class MemCompleteEvent;
return ports;
}
-void
+Tick
Bus::atomicSnoop(Packet *pkt)
{
std::vector<int> ports = findSnoopPorts(pkt->getAddr(), pkt->getSrc());
+ Tick response_time = 0;
while (!ports.empty())
{
- interfaces[ports.back()]->sendAtomic(pkt);
+ Tick response = interfaces[ports.back()]->sendAtomic(pkt);
+ if (response) {
+ assert(!response_time); //Multiple responders
+ response_time = response;
+ }
ports.pop_back();
}
+ return response_time;
}
void
DPRINTF(Bus, "recvAtomic: packet src %d dest %d addr 0x%x cmd %s\n",
pkt->getSrc(), pkt->getDest(), pkt->getAddr(), pkt->cmdString());
assert(pkt->getDest() == Packet::Broadcast);
- atomicSnoop(pkt);
- return findPort(pkt->getAddr(), pkt->getSrc())->sendAtomic(pkt);
+ Tick snoopTime = atomicSnoop(pkt);
+ if (snoopTime)
+ return snoopTime; //Snoop satisfies it
+ else
+ return findPort(pkt->getAddr(), pkt->getSrc())->sendAtomic(pkt);
}
/** Function called by the port when the bus is receiving a Functional
std::vector<int> findSnoopPorts(Addr addr, int id);
/** Snoop all relevant ports atomicly. */
- void atomicSnoop(Packet *pkt);
+ Tick atomicSnoop(Packet *pkt);
/** Snoop all relevant ports functionally. */
void functionalSnoop(Packet *pkt);
if (pkt->isResponse())
handleResponse(pkt);
else
- snoopProbe(pkt);
+ return snoopProbe(pkt);
}
//Fix this timing info
return hitLatency;
prefetchAccess(params.prefetchAccess),
tags(params.tags), missQueue(params.missQueue),
coherence(params.coherence), prefetcher(params.prefetcher),
- doCopy(params.doCopy), blockOnCopy(params.blockOnCopy)
+ doCopy(params.doCopy), blockOnCopy(params.blockOnCopy),
+ hitLatency(params.hitLatency)
{
//FIX BUS POINTERS
// if (params.in == NULL) {
BlkType *blk = tags->findBlock(pkt);
CacheBlk::State old_state = (blk) ? blk->status : 0;
CacheBlk::State new_state = coherence->getNewState(pkt,old_state);
- DPRINTF(Cache, "Block for blk addr %x moving from state %i to %i\n",
- pkt->getAddr() & (((ULL(1))<<48)-1), old_state, new_state);
+ if (old_state != new_state)
+ DPRINTF(Cache, "Block for blk addr %x moving from state %i to %i\n",
+ pkt->getAddr() & (((ULL(1))<<48)-1), old_state, new_state);
//Set the state on the upgrade
memcpy(pkt->getPtr<uint8_t>(), blk->data, blkSize);
PacketList writebacks;
CacheBlk::State old_state = (blk) ? blk->status : 0;
PacketList writebacks;
CacheBlk::State new_state = coherence->getNewState(pkt,old_state);
- DPRINTF(Cache, "Block for blk addr %x moving from state %i to %i\n",
- pkt->getAddr() & (((ULL(1))<<48)-1), old_state, new_state);
+ if (old_state != new_state)
+ DPRINTF(Cache, "Block for blk addr %x moving from state %i to %i\n",
+ pkt->getAddr() & (((ULL(1))<<48)-1), old_state, new_state);
blk = tags->handleFill(blk, (MSHR*)pkt->senderState,
new_state, writebacks, pkt);
while (!writebacks.empty()) {
int lat;
BlkType *blk = tags->handleAccess(pkt, lat, writebacks, update);
+ DPRINTF(Cache, "%s %x %s blk_addr: %x\n", pkt->cmdString(),
+ pkt->getAddr() & (((ULL(1))<<48)-1), (blk) ? "hit" : "miss",
+ pkt->getAddr() & ~((Addr)blkSize - 1));
+
if (!blk) {
// Need to check for outstanding misses and writes
Addr blk_addr = pkt->getAddr() & ~(blkSize - 1);
busPkt->time = curTick;
+ DPRINTF(Cache, "Sending a atomic %s for %x blk_addr: %x\n",
+ busPkt->cmdString(),
+ busPkt->getAddr() & (((ULL(1))<<48)-1),
+ busPkt->getAddr() & ~((Addr)blkSize - 1));
+
lat = memSidePort->sendAtomic(busPkt);
//Be sure to flip the response to a request for coherence
*/ misses[pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/]++;
CacheBlk::State old_state = (blk) ? blk->status : 0;
+ CacheBlk::State new_state = coherence->getNewState(busPkt, old_state);
+ DPRINTF(Cache, "Receive response:%s for blk addr %x in state %i\n",
+ busPkt->cmdString(),
+ busPkt->getAddr() & (((ULL(1))<<48)-1), old_state);
+ if (old_state != new_state)
+ DPRINTF(Cache, "Block for blk addr %x moving from state %i to %i\n",
+ busPkt->getAddr() & (((ULL(1))<<48)-1), old_state, new_state);
+
tags->handleFill(blk, busPkt,
- coherence->getNewState(busPkt, old_state),
+ new_state,
writebacks, pkt);
+ //Free the packet
+ delete busPkt;
+
// Handle writebacks if needed
while (!writebacks.empty()){
- memSidePort->sendAtomic(writebacks.front());
+ Packet *wbPkt = writebacks.front();
+ memSidePort->sendAtomic(wbPkt);
writebacks.pop_front();
+ delete wbPkt;
}
return lat + hitLatency;
} else {
// Still need to change data in all locations.
otherSidePort->sendFunctional(pkt);
}
- return curTick + lat;
+ return hitLatency;
}
fatal("Probe not handled.\n");
return 0;
static const std::string ReadReqString("ReadReq");
static const std::string WriteReqString("WriteReq");
-static const std::string WriteReqNoAckString("WriteReqNoAck");
+static const std::string WriteReqNoAckString("WriteReqNoAck|Writeback");
static const std::string ReadRespString("ReadResp");
static const std::string WriteRespString("WriteResp");
+static const std::string SoftPFReqString("SoftPFReq");
+static const std::string SoftPFRespString("SoftPFResp");
+static const std::string HardPFReqString("HardPFReq");
+static const std::string HardPFRespString("HardPFResp");
+static const std::string InvalidateReqString("InvalidateReq");
+static const std::string WriteInvalidateReqString("WriteInvalidateReq");
+static const std::string UpgradeReqString("UpgradeReq");
+static const std::string ReadExReqString("ReadExReq");
+static const std::string ReadExRespString("ReadExResp");
static const std::string OtherCmdString("<other>");
const std::string &
case WriteReqNoAck: return WriteReqNoAckString;
case ReadResp: return ReadRespString;
case WriteResp: return WriteRespString;
+ case SoftPFReq: return SoftPFReqString;
+ case SoftPFResp: return SoftPFRespString;
+ case HardPFReq: return HardPFReqString;
+ case HardPFResp: return HardPFRespString;
+ case InvalidateReq: return InvalidateReqString;
+ case WriteInvalidateReq:return WriteInvalidateReqString;
+ case UpgradeReq: return UpgradeReqString;
+ case ReadExReq: return ReadExReqString;
+ case ReadExResp: return ReadExRespString;
default: return OtherCmdString;
}
}
case WriteReqNoAck: return WriteReqNoAckString;
case ReadResp: return ReadRespString;
case WriteResp: return WriteRespString;
+ case SoftPFReq: return SoftPFReqString;
+ case SoftPFResp: return SoftPFRespString;
+ case HardPFReq: return HardPFReqString;
+ case HardPFResp: return HardPFRespString;
+ case InvalidateReq: return InvalidateReqString;
+ case WriteInvalidateReq:return WriteInvalidateReqString;
+ case UpgradeReq: return UpgradeReqString;
+ case ReadExReq: return ReadExReqString;
+ case ReadExResp: return ReadExRespString;
default: return OtherCmdString;
}
}
class MemTest(SimObject):
type = 'MemTest'
max_loads = Param.Counter("number of loads to execute")
+ atomic = Param.Bool(False, "Execute tester in atomic mode? (or timing)\n")
memory_size = Param.Int(65536, "memory size")
percent_dest_unaligned = Param.Percent(50,
"percent of copy dest address that are unaligned")