summaryrefslogtreecommitdiff
path: root/src/mem/cache/base_cache.cc
diff options
context:
space:
mode:
authorSteve Reinhardt <stever@eecs.umich.edu>2007-06-17 17:27:53 -0700
committerSteve Reinhardt <stever@eecs.umich.edu>2007-06-17 17:27:53 -0700
commit35cf19d441ed15d054d00674ec67ab5bc769f6d7 (patch)
tree86a97bf419e3c46834a446039ef8f4a85f74b7cc /src/mem/cache/base_cache.cc
parenta9b7c558fd6c00dacbdf36f4617c03a19c198b08 (diff)
downloadgem5-35cf19d441ed15d054d00674ec67ab5bc769f6d7.tar.xz
More major reorg of cache. Seems to work for atomic mode now,
timing mode still broken. configs/example/memtest.py: Revamp options. src/cpu/memtest/memtest.cc: No need for memory initialization. No need to make atomic response... memory system should do that now. src/cpu/memtest/memtest.hh: MemTest really doesn't want to snoop. src/mem/bridge.cc: checkFunctional() cleanup. src/mem/bus.cc: src/mem/bus.hh: src/mem/cache/base_cache.cc: src/mem/cache/base_cache.hh: src/mem/cache/cache.cc: src/mem/cache/cache.hh: src/mem/cache/cache_blk.hh: src/mem/cache/cache_builder.cc: src/mem/cache/cache_impl.hh: src/mem/cache/coherence/coherence_protocol.cc: src/mem/cache/coherence/coherence_protocol.hh: src/mem/cache/coherence/simple_coherence.hh: src/mem/cache/miss/SConscript: src/mem/cache/miss/mshr.cc: src/mem/cache/miss/mshr.hh: src/mem/cache/miss/mshr_queue.cc: src/mem/cache/miss/mshr_queue.hh: src/mem/cache/prefetch/base_prefetcher.cc: src/mem/cache/tags/fa_lru.cc: src/mem/cache/tags/fa_lru.hh: src/mem/cache/tags/iic.cc: src/mem/cache/tags/iic.hh: src/mem/cache/tags/lru.cc: src/mem/cache/tags/lru.hh: src/mem/cache/tags/split.cc: src/mem/cache/tags/split.hh: src/mem/cache/tags/split_lifo.cc: src/mem/cache/tags/split_lifo.hh: src/mem/cache/tags/split_lru.cc: src/mem/cache/tags/split_lru.hh: src/mem/packet.cc: src/mem/packet.hh: src/mem/physical.cc: src/mem/physical.hh: src/mem/tport.cc: More major reorg. Seems to work for atomic mode now, timing mode still broken. --HG-- extra : convert_revision : 7e70dfc4a752393b911880ff028271433855ae87
Diffstat (limited to 'src/mem/cache/base_cache.cc')
-rw-r--r--src/mem/cache/base_cache.cc413
1 files changed, 286 insertions, 127 deletions
diff --git a/src/mem/cache/base_cache.cc b/src/mem/cache/base_cache.cc
index a47c19e60..c7006550b 100644
--- a/src/mem/cache/base_cache.cc
+++ b/src/mem/cache/base_cache.cc
@@ -41,18 +41,23 @@
using namespace std;
BaseCache::CachePort::CachePort(const std::string &_name, BaseCache *_cache)
- : Port(_name, _cache), cache(_cache), otherPort(NULL)
+ : SimpleTimingPort(_name, _cache), cache(_cache), otherPort(NULL),
+ blocked(false), waitingOnRetry(false), mustSendRetry(false),
+ requestCauses(0)
{
- blocked = false;
- waitingOnRetry = false;
}
BaseCache::BaseCache(const std::string &name, Params &params)
: MemObject(name),
- blocked(0), blockedSnoop(0),
+ mshrQueue(params.numMSHRs, 4),
+ writeBuffer(params.numWriteBuffers, params.numMSHRs+1000),
blkSize(params.blkSize),
- missCount(params.maxMisses), drainEvent(NULL)
+ numTarget(params.numTargets),
+ blocked(0),
+ noTargetMSHR(NULL),
+ missCount(params.maxMisses),
+ drainEvent(NULL)
{
}
@@ -71,139 +76,21 @@ BaseCache::CachePort::deviceBlockSize()
return cache->getBlockSize();
}
-bool
-BaseCache::CachePort::checkFunctional(PacketPtr pkt)
-{
- //Check storage here first
- list<PacketPtr>::iterator i = drainList.begin();
- list<PacketPtr>::iterator iend = drainList.end();
- bool notDone = true;
- while (i != iend && notDone) {
- PacketPtr target = *i;
- // If the target contains data, and it overlaps the
- // probed request, need to update data
- if (target->intersect(pkt)) {
- DPRINTF(Cache, "Functional %s access to blk_addr %x intersects a drain\n",
- pkt->cmdString(), pkt->getAddr() & ~(cache->getBlockSize() - 1));
- notDone = fixPacket(pkt, target);
- }
- i++;
- }
- //Also check the response not yet ready to be on the list
- std::list<std::pair<Tick,PacketPtr> >::iterator j = transmitList.begin();
- std::list<std::pair<Tick,PacketPtr> >::iterator jend = transmitList.end();
-
- while (j != jend && notDone) {
- PacketPtr target = j->second;
- // If the target contains data, and it overlaps the
- // probed request, need to update data
- if (target->intersect(pkt)) {
- DPRINTF(Cache, "Functional %s access to blk_addr %x intersects a response\n",
- pkt->cmdString(), pkt->getAddr() & ~(cache->getBlockSize() - 1));
- notDone = fixDelayedResponsePacket(pkt, target);
- }
- j++;
- }
- return notDone;
-}
void
BaseCache::CachePort::checkAndSendFunctional(PacketPtr pkt)
{
- bool notDone = checkFunctional(pkt);
- if (notDone)
+ checkFunctional(pkt);
+ if (pkt->result != Packet::Success)
sendFunctional(pkt);
}
-void
-BaseCache::CachePort::respond(PacketPtr pkt, Tick time)
-{
- assert(time >= curTick);
- if (pkt->needsResponse()) {
- if (transmitList.empty()) {
- assert(!responseEvent->scheduled());
- responseEvent->schedule(time);
- transmitList.push_back(std::pair<Tick,PacketPtr>(time,pkt));
- return;
- }
-
- // something is on the list and this belongs at the end
- if (time >= transmitList.back().first) {
- 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 =
- transmitList.begin();
- std::list<std::pair<Tick,PacketPtr> >::iterator end =
- transmitList.end();
- bool done = false;
-
- while (i != end && !done) {
- if (time < i->first) {
- if (i == transmitList.begin()) {
- //Inserting at begining, reschedule
- responseEvent->reschedule(time);
- }
- transmitList.insert(i,std::pair<Tick,PacketPtr>(time,pkt));
- done = true;
- }
- i++;
- }
- }
- else {
- assert(0);
- // this code was on the cpuSidePort only... do we still need it?
- if (pkt->cmd != MemCmd::UpgradeReq)
- {
- delete pkt->req;
- delete pkt;
- }
- }
-}
-
-bool
-BaseCache::CachePort::drainResponse()
-{
- DPRINTF(CachePort,
- "%s attempting to send a retry for response (%i waiting)\n",
- name(), drainList.size());
- //We have some responses to drain first
- PacketPtr pkt = drainList.front();
- if (sendTiming(pkt)) {
- drainList.pop_front();
- DPRINTF(CachePort, "%s sucessful in sending a retry for"
- "response (%i still waiting)\n", name(), drainList.size());
- if (!drainList.empty() || isBusRequested()) {
-
- DPRINTF(CachePort, "%s has more responses/requests\n", name());
- return false;
- }
- } else {
- waitingOnRetry = true;
- DPRINTF(CachePort, "%s now waiting on a retry\n", name());
- }
- return true;
-}
-
-
bool
BaseCache::CachePort::recvRetryCommon()
{
assert(waitingOnRetry);
waitingOnRetry = false;
- if (!drainList.empty()) {
- if (!drainResponse()) {
- // more responses to drain... re-request bus
- scheduleRequestEvent(curTick + 1);
- }
- // Check if we're done draining once this list is empty
- if (drainList.empty()) {
- cache->checkDrain();
- }
- return true;
- }
return false;
}
@@ -451,17 +338,289 @@ BaseCache::regStats()
.desc("number of cache copies performed")
;
+ writebacks
+ .init(maxThreadsPerCPU)
+ .name(name() + ".writebacks")
+ .desc("number of writebacks")
+ .flags(total)
+ ;
+
+ // MSHR statistics
+ // MSHR hit statistics
+ for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
+ MemCmd cmd(access_idx);
+ const string &cstr = cmd.toString();
+
+ mshr_hits[access_idx]
+ .init(maxThreadsPerCPU)
+ .name(name() + "." + cstr + "_mshr_hits")
+ .desc("number of " + cstr + " MSHR hits")
+ .flags(total | nozero | nonan)
+ ;
+ }
+
+ demandMshrHits
+ .name(name() + ".demand_mshr_hits")
+ .desc("number of demand (read+write) MSHR hits")
+ .flags(total)
+ ;
+ demandMshrHits = mshr_hits[MemCmd::ReadReq] + mshr_hits[MemCmd::WriteReq];
+
+ overallMshrHits
+ .name(name() + ".overall_mshr_hits")
+ .desc("number of overall MSHR hits")
+ .flags(total)
+ ;
+ overallMshrHits = demandMshrHits + mshr_hits[MemCmd::SoftPFReq] +
+ mshr_hits[MemCmd::HardPFReq];
+
+ // MSHR miss statistics
+ for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
+ MemCmd cmd(access_idx);
+ const string &cstr = cmd.toString();
+
+ mshr_misses[access_idx]
+ .init(maxThreadsPerCPU)
+ .name(name() + "." + cstr + "_mshr_misses")
+ .desc("number of " + cstr + " MSHR misses")
+ .flags(total | nozero | nonan)
+ ;
+ }
+
+ demandMshrMisses
+ .name(name() + ".demand_mshr_misses")
+ .desc("number of demand (read+write) MSHR misses")
+ .flags(total)
+ ;
+ demandMshrMisses = mshr_misses[MemCmd::ReadReq] + mshr_misses[MemCmd::WriteReq];
+
+ overallMshrMisses
+ .name(name() + ".overall_mshr_misses")
+ .desc("number of overall MSHR misses")
+ .flags(total)
+ ;
+ overallMshrMisses = demandMshrMisses + mshr_misses[MemCmd::SoftPFReq] +
+ mshr_misses[MemCmd::HardPFReq];
+
+ // MSHR miss latency statistics
+ for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
+ MemCmd cmd(access_idx);
+ const string &cstr = cmd.toString();
+
+ mshr_miss_latency[access_idx]
+ .init(maxThreadsPerCPU)
+ .name(name() + "." + cstr + "_mshr_miss_latency")
+ .desc("number of " + cstr + " MSHR miss cycles")
+ .flags(total | nozero | nonan)
+ ;
+ }
+
+ demandMshrMissLatency
+ .name(name() + ".demand_mshr_miss_latency")
+ .desc("number of demand (read+write) MSHR miss cycles")
+ .flags(total)
+ ;
+ demandMshrMissLatency = mshr_miss_latency[MemCmd::ReadReq]
+ + mshr_miss_latency[MemCmd::WriteReq];
+
+ overallMshrMissLatency
+ .name(name() + ".overall_mshr_miss_latency")
+ .desc("number of overall MSHR miss cycles")
+ .flags(total)
+ ;
+ overallMshrMissLatency = demandMshrMissLatency +
+ mshr_miss_latency[MemCmd::SoftPFReq] + mshr_miss_latency[MemCmd::HardPFReq];
+
+ // MSHR uncacheable statistics
+ for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
+ MemCmd cmd(access_idx);
+ const string &cstr = cmd.toString();
+
+ mshr_uncacheable[access_idx]
+ .init(maxThreadsPerCPU)
+ .name(name() + "." + cstr + "_mshr_uncacheable")
+ .desc("number of " + cstr + " MSHR uncacheable")
+ .flags(total | nozero | nonan)
+ ;
+ }
+
+ overallMshrUncacheable
+ .name(name() + ".overall_mshr_uncacheable_misses")
+ .desc("number of overall MSHR uncacheable misses")
+ .flags(total)
+ ;
+ overallMshrUncacheable = mshr_uncacheable[MemCmd::ReadReq]
+ + mshr_uncacheable[MemCmd::WriteReq] + mshr_uncacheable[MemCmd::SoftPFReq]
+ + mshr_uncacheable[MemCmd::HardPFReq];
+
+ // MSHR miss latency statistics
+ for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
+ MemCmd cmd(access_idx);
+ const string &cstr = cmd.toString();
+
+ mshr_uncacheable_lat[access_idx]
+ .init(maxThreadsPerCPU)
+ .name(name() + "." + cstr + "_mshr_uncacheable_latency")
+ .desc("number of " + cstr + " MSHR uncacheable cycles")
+ .flags(total | nozero | nonan)
+ ;
+ }
+
+ overallMshrUncacheableLatency
+ .name(name() + ".overall_mshr_uncacheable_latency")
+ .desc("number of overall MSHR uncacheable cycles")
+ .flags(total)
+ ;
+ overallMshrUncacheableLatency = mshr_uncacheable_lat[MemCmd::ReadReq]
+ + mshr_uncacheable_lat[MemCmd::WriteReq]
+ + mshr_uncacheable_lat[MemCmd::SoftPFReq]
+ + mshr_uncacheable_lat[MemCmd::HardPFReq];
+
+#if 0
+ // MSHR access formulas
+ for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
+ MemCmd cmd(access_idx);
+ const string &cstr = cmd.toString();
+
+ mshrAccesses[access_idx]
+ .name(name() + "." + cstr + "_mshr_accesses")
+ .desc("number of " + cstr + " mshr accesses(hits+misses)")
+ .flags(total | nozero | nonan)
+ ;
+ mshrAccesses[access_idx] =
+ mshr_hits[access_idx] + mshr_misses[access_idx]
+ + mshr_uncacheable[access_idx];
+ }
+
+ demandMshrAccesses
+ .name(name() + ".demand_mshr_accesses")
+ .desc("number of demand (read+write) mshr accesses")
+ .flags(total | nozero | nonan)
+ ;
+ demandMshrAccesses = demandMshrHits + demandMshrMisses;
+
+ overallMshrAccesses
+ .name(name() + ".overall_mshr_accesses")
+ .desc("number of overall (read+write) mshr accesses")
+ .flags(total | nozero | nonan)
+ ;
+ overallMshrAccesses = overallMshrHits + overallMshrMisses
+ + overallMshrUncacheable;
+#endif
+
+ // MSHR miss rate formulas
+ for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
+ MemCmd cmd(access_idx);
+ const string &cstr = cmd.toString();
+
+ mshrMissRate[access_idx]
+ .name(name() + "." + cstr + "_mshr_miss_rate")
+ .desc("mshr miss rate for " + cstr + " accesses")
+ .flags(total | nozero | nonan)
+ ;
+
+ mshrMissRate[access_idx] =
+ mshr_misses[access_idx] / accesses[access_idx];
+ }
+
+ demandMshrMissRate
+ .name(name() + ".demand_mshr_miss_rate")
+ .desc("mshr miss rate for demand accesses")
+ .flags(total)
+ ;
+ demandMshrMissRate = demandMshrMisses / demandAccesses;
+
+ overallMshrMissRate
+ .name(name() + ".overall_mshr_miss_rate")
+ .desc("mshr miss rate for overall accesses")
+ .flags(total)
+ ;
+ overallMshrMissRate = overallMshrMisses / overallAccesses;
+
+ // mshrMiss latency formulas
+ for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
+ MemCmd cmd(access_idx);
+ const string &cstr = cmd.toString();
+
+ avgMshrMissLatency[access_idx]
+ .name(name() + "." + cstr + "_avg_mshr_miss_latency")
+ .desc("average " + cstr + " mshr miss latency")
+ .flags(total | nozero | nonan)
+ ;
+
+ avgMshrMissLatency[access_idx] =
+ mshr_miss_latency[access_idx] / mshr_misses[access_idx];
+ }
+
+ demandAvgMshrMissLatency
+ .name(name() + ".demand_avg_mshr_miss_latency")
+ .desc("average overall mshr miss latency")
+ .flags(total)
+ ;
+ demandAvgMshrMissLatency = demandMshrMissLatency / demandMshrMisses;
+
+ overallAvgMshrMissLatency
+ .name(name() + ".overall_avg_mshr_miss_latency")
+ .desc("average overall mshr miss latency")
+ .flags(total)
+ ;
+ overallAvgMshrMissLatency = overallMshrMissLatency / overallMshrMisses;
+
+ // mshrUncacheable latency formulas
+ for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
+ MemCmd cmd(access_idx);
+ const string &cstr = cmd.toString();
+
+ avgMshrUncacheableLatency[access_idx]
+ .name(name() + "." + cstr + "_avg_mshr_uncacheable_latency")
+ .desc("average " + cstr + " mshr uncacheable latency")
+ .flags(total | nozero | nonan)
+ ;
+
+ avgMshrUncacheableLatency[access_idx] =
+ mshr_uncacheable_lat[access_idx] / mshr_uncacheable[access_idx];
+ }
+
+ overallAvgMshrUncacheableLatency
+ .name(name() + ".overall_avg_mshr_uncacheable_latency")
+ .desc("average overall mshr uncacheable latency")
+ .flags(total)
+ ;
+ overallAvgMshrUncacheableLatency = overallMshrUncacheableLatency / overallMshrUncacheable;
+
+ mshr_cap_events
+ .init(maxThreadsPerCPU)
+ .name(name() + ".mshr_cap_events")
+ .desc("number of times MSHR cap was activated")
+ .flags(total)
+ ;
+
+ //software prefetching stats
+ soft_prefetch_mshr_full
+ .init(maxThreadsPerCPU)
+ .name(name() + ".soft_prefetch_mshr_full")
+ .desc("number of mshr full events for SW prefetching instrutions")
+ .flags(total)
+ ;
+
+ mshr_no_allocate_misses
+ .name(name() +".no_allocate_misses")
+ .desc("Number of misses that were no-allocate")
+ ;
+
}
unsigned int
BaseCache::drain(Event *de)
{
+ int count = memSidePort->drain(de) + cpuSidePort->drain(de);
+
// Set status
- if (!canDrain()) {
+ if (count != 0) {
drainEvent = de;
changeState(SimObject::Draining);
- return 1;
+ return count;
}
changeState(SimObject::Drained);