More major reorg of cache. Seems to work for atomic mode now,
authorSteve Reinhardt <stever@eecs.umich.edu>
Mon, 18 Jun 2007 00:27:53 +0000 (17:27 -0700)
committerSteve Reinhardt <stever@eecs.umich.edu>
Mon, 18 Jun 2007 00:27:53 +0000 (17:27 -0700)
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

45 files changed:
configs/example/memtest.py
src/cpu/memtest/memtest.cc
src/cpu/memtest/memtest.hh
src/mem/bridge.cc
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/blocking_buffer.cc [deleted file]
src/mem/cache/miss/blocking_buffer.hh [deleted file]
src/mem/cache/miss/miss_buffer.cc [deleted file]
src/mem/cache/miss/miss_buffer.hh [deleted file]
src/mem/cache/miss/miss_queue.cc [deleted file]
src/mem/cache/miss/miss_queue.hh [deleted file]
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

index 9fd943aaa75f886d7b7e2bf67e9cce31f024ac52..9027a9866e35a98078f8b50f41c308ccd8409379 100644 (file)
@@ -33,14 +33,32 @@ m5.AddToPath('../common')
 
 parser = optparse.OptionParser()
 
-parser.add_option("--caches", action="store_true")
-parser.add_option("-t", "--timing", action="store_true")
-parser.add_option("-m", "--maxtick", type="int")
-parser.add_option("-l", "--maxloads", default = "1000000000000", type="int")
-parser.add_option("-n", "--numtesters", default = "8", type="int")
-parser.add_option("-p", "--protocol",
-                  default="moesi",
-                  help="The coherence protocol to use for the L1'a (i.e. MOESI, MOSI)")
+parser.add_option("-c", "--cache-levels", type="int", default=2,
+                  metavar="LEVELS",
+                  help="Number of cache levels [default: %default]")
+parser.add_option("-a", "--atomic", action="store_true",
+                  help="Use atomic (non-timing) mode")
+parser.add_option("-b", "--blocking", action="store_true",
+                  help="Use blocking caches")
+parser.add_option("-l", "--maxloads", default="1G", metavar="N",
+                  help="Stop after N loads [default: %default]")
+parser.add_option("-m", "--maxtick", type="int", default=m5.MaxTick,
+                  metavar="T",
+                  help="Stop after T ticks")
+parser.add_option("-n", "--numtesters", type="int", default=8,
+                  metavar="N",
+                  help="Number of tester pseudo-CPUs [default: %default]")
+parser.add_option("-p", "--protocol", default="moesi",
+                  help="Coherence protocol [default: %default]")
+
+parser.add_option("-f", "--functional", type="int", default=0,
+                  metavar="PCT",
+                  help="Target percentage of functional accesses "
+                  "[default: %default]")
+parser.add_option("-u", "--uncacheable", type="int", default=0,
+                  metavar="PCT",
+                  help="Target percentage of uncacheable accesses "
+                  "[default: %default]")
 
 (options, args) = parser.parse_args()
 
@@ -48,14 +66,29 @@ if args:
      print "Error: script doesn't take any positional arguments"
      sys.exit(1)
 
+# Should generalize this someday... would be cool to have a loop that
+# just iterates, adding a level of caching each time.
+#if options.cache_levels != 2 and options.cache_levels != 0:
+#     print "Error: number of cache levels must be 0 or 2"
+#     sys.exit(1)
+
+if options.blocking:
+     num_l1_mshrs = 1
+     num_l2_mshrs = 1
+else:
+     num_l1_mshrs = 12
+     num_l2_mshrs = 92
+
+block_size = 64
+
 # --------------------
 # Base L1 Cache
 # ====================
 
 class L1(BaseCache):
     latency = '1ns'
-    block_size = 64
-    mshrs = 12
+    block_size = block_size
+    mshrs = num_l1_mshrs
     tgts_per_mshr = 8
     protocol = CoherenceProtocol(protocol=options.protocol)
 
@@ -64,29 +97,31 @@ class L1(BaseCache):
 # ----------------------
 
 class L2(BaseCache):
-    block_size = 64
+    block_size = block_size
     latency = '10ns'
-    mshrs = 92
+    mshrs = num_l2_mshrs
     tgts_per_mshr = 16
     write_buffers = 8
+    protocol = CoherenceProtocol(protocol=options.protocol)
 
-#MAX CORES IS 8 with the false sharing method
-if options.numtesters > 8:
-     print "Error: NUmber of testers limited to 8 because of false sharing"
-     sys,exit(1)
+if options.numtesters > block_size:
+     print "Error: Number of testers limited to %s because of false sharing" \
+           % (block_size)
+     sys.exit(1)
 
-cpus = [ MemTest(atomic=not options.timing, max_loads=options.maxloads,
-                 percent_functional=50, percent_uncacheable=10,
+cpus = [ MemTest(atomic=options.atomic, max_loads=options.maxloads,
+                 percent_functional=options.functional,
+                 percent_uncacheable=options.uncacheable,
                  progress_interval=1000)
          for i in xrange(options.numtesters) ]
 
 # system simulated
 system = System(cpu = cpus, funcmem = PhysicalMemory(),
-                physmem = PhysicalMemory(latency = "50ps"),
+                physmem = PhysicalMemory(latency = "100ns"),
                 membus = Bus(clock="500MHz", width=16))
 
 # l2cache & bus
-if options.caches:
+if options.cache_levels == 2:
     system.toL2Bus = Bus(clock="500MHz", width=16)
     system.l2c = L2(size='64kB', assoc=8)
     system.l2c.cpu_side = system.toL2Bus.port
@@ -96,10 +131,14 @@ if options.caches:
 
 # add L1 caches
 for cpu in cpus:
-    if options.caches:
+    if options.cache_levels == 2:
          cpu.l1c = L1(size = '32kB', assoc = 4)
          cpu.test = cpu.l1c.cpu_side
          cpu.l1c.mem_side = system.toL2Bus.port
+    elif options.cache_levels == 1:
+         cpu.l1c = L1(size = '32kB', assoc = 4)
+         cpu.test = cpu.l1c.cpu_side
+         cpu.l1c.mem_side = system.membus.port
     else:
          cpu.test = system.membus.port
     system.funcmem.port = cpu.functional
@@ -113,10 +152,10 @@ system.physmem.port = system.membus.port
 # -----------------------
 
 root = Root( system = system )
-if options.timing:
-    root.system.mem_mode = 'timing'
-else:
+if options.atomic:
     root.system.mem_mode = 'atomic'
+else:
+    root.system.mem_mode = 'timing'
 
 # Not much point in this being higher than the L1 latency
 m5.ticks.setGlobalFrequency('1ns')
@@ -125,9 +164,6 @@ m5.ticks.setGlobalFrequency('1ns')
 m5.instantiate(root)
 
 # simulate until program terminates
-if options.maxtick:
-    exit_event = m5.simulate(options.maxtick)
-else:
-    exit_event = m5.simulate(10000000000000)
+exit_event = m5.simulate(options.maxtick)
 
 print 'Exiting @ tick', m5.curTick(), 'because', exit_event.getCause()
index 607cf10662623ddc429a1bb5b4bb1a7cf91e473b..5d89f1b827adeb9121e37dc8562d35882c385622 100644 (file)
@@ -102,7 +102,6 @@ void
 MemTest::sendPkt(PacketPtr pkt) {
     if (atomic) {
         cachePort.sendAtomic(pkt);
-        pkt->makeAtomicResponse();
         completeRequest(pkt);
     }
     else if (!cachePort.sendTiming(pkt)) {
@@ -165,8 +164,6 @@ MemTest::MemTest(const string &name,
     tickEvent.schedule(0);
 
     id = TESTER_ALLOCATOR++;
-    if (TESTER_ALLOCATOR > 8)
-        panic("False sharing memtester only allows up to 8 testers");
 
     accessRetry = false;
 }
@@ -190,14 +187,8 @@ MemTest::init()
     blockAddrMask = blockSize - 1;
     traceBlockAddr = blockAddr(traceBlockAddr);
 
-    // set up intial memory contents here
-
-    cachePort.memsetBlob(baseAddr1, 1, size);
-    funcPort.memsetBlob(baseAddr1, 1, size);
-    cachePort.memsetBlob(baseAddr2, 2, size);
-    funcPort.memsetBlob(baseAddr2, 2, size);
-    cachePort.memsetBlob(uncacheAddr, 3, size);
-    funcPort.memsetBlob(uncacheAddr, 3, size);
+    // initial memory contents for both physical memory and functional
+    // memory should be 0; no need to initialize them.
 }
 
 static void
@@ -230,15 +221,10 @@ MemTest::completeRequest(PacketPtr pkt)
       case MemCmd::ReadResp:
 
         if (memcmp(pkt_data, data, pkt->getSize()) != 0) {
-            cerr << name() << ": on read of 0x" << hex << req->getPaddr()
-                 << " (0x" << hex << blockAddr(req->getPaddr()) << ")"
-                 << "@ cycle " << dec << curTick
-                 << ", cache returns 0x";
-            printData(cerr, pkt_data, pkt->getSize());
-            cerr << ", expected 0x";
-            printData(cerr, data, pkt->getSize());
-            cerr << endl;
-            fatal("");
+            panic("%s: read of %x (blk %x) @ cycle %d "
+                  "returns %x, expected %x\n", name(),
+                  req->getPaddr(), blockAddr(req->getPaddr()), curTick,
+                  *pkt_data, *data);
         }
 
         numReads++;
@@ -267,7 +253,7 @@ MemTest::completeRequest(PacketPtr pkt)
         break;
 */
       default:
-        panic("invalid command");
+        panic("invalid command %s (%d)", pkt->cmdString(), pkt->cmd.toInt());
     }
 
     if (blockAddr(req->getPaddr()) == traceBlockAddr) {
index a6b08d61c7600f7d2dfafbdb6129a2b67490335e..565fafb7799d19297d03496ff0db64d15a5a4886 100644 (file)
@@ -116,7 +116,7 @@ class MemTest : public MemObject
 
         virtual void getDeviceAddressRanges(AddrRangeList &resp,
                                             bool &snoop)
-        { resp.clear(); snoop = true; }
+        { resp.clear(); snoop = false; }
     };
 
     CpuPort cachePort;
index eebf91a859edd4573c5726d7c8400fad637cb58b..fb457484462bb4e050e2e0f0c806ed01acb3742e 100644 (file)
@@ -339,17 +339,14 @@ void
 Bridge::BridgePort::recvFunctional(PacketPtr pkt)
 {
     std::list<PacketBuffer*>::iterator i;
-    bool pktContinue = true;
 
     for (i = sendQueue.begin();  i != sendQueue.end(); ++i) {
-        if (pkt->intersect((*i)->pkt)) {
-            pktContinue &= fixPacket(pkt, (*i)->pkt);
-        }
+        if (pkt->checkFunctional((*i)->pkt))
+            return;
     }
 
-    if (pktContinue) {
-        otherPort->sendFunctional(pkt);
-    }
+    // fall through if pkt still not satisfied
+    otherPort->sendFunctional(pkt);
 }
 
 /** Function called by the port when the bus is receiving a status change.*/
index ec33bd4c57440a8485d8889cc2783710f6a64729..bde90c83f3a1b9d5cac6ac69ee8940e3b1abc659 100644 (file)
@@ -33,7 +33,7 @@
  * Definition of a bus object.
  */
 
-
+#include <algorithm>
 #include <limits>
 
 #include "base/misc.hh"
@@ -182,8 +182,7 @@ Bus::recvTiming(PacketPtr pkt)
 
     // If the bus is busy, or other devices are in line ahead of the current
     // one, put this device on the retry list.
-    if (!(pkt->flags & EXPRESS_SNOOP) &&
-        tickNextIdle > curTick ||
+    if (tickNextIdle > curTick ||
         (retryList.size() && (!inRetry || pktPort != retryList.front())))
     {
         addToRetryList(pktPort);
@@ -199,7 +198,7 @@ Bus::recvTiming(PacketPtr pkt)
         port = findPort(pkt->getAddr(), pkt->getSrc());
         timingSnoop(pkt, port ? port : interfaces[pkt->getSrc()]);
 
-        if (pkt->flags & SATISFIED) {
+        if (pkt->memInhibitAsserted()) {
             //Cache-Cache transfer occuring
             if (inRetry) {
                 retryList.front()->onRetryList(false);
@@ -321,27 +320,6 @@ Bus::findPort(Addr addr, int id)
     return interfaces[dest_id];
 }
 
-Tick
-Bus::atomicSnoop(PacketPtr pkt, Port *responder)
-{
-    Tick response_time = 0;
-
-    for (SnoopIter s_iter = snoopPorts.begin();
-         s_iter != snoopPorts.end();
-         s_iter++) {
-        BusPort *p = *s_iter;
-        if (p != responder && p->getId() != pkt->getSrc()) {
-            Tick response = p->sendAtomic(pkt);
-            if (response) {
-                assert(!response_time);  //Multiple responders
-                response_time = response;
-            }
-        }
-    }
-
-    return response_time;
-}
-
 void
 Bus::functionalSnoop(PacketPtr pkt, Port *responder)
 {
@@ -390,19 +368,56 @@ Bus::recvAtomic(PacketPtr pkt)
             pkt->getSrc(), pkt->getDest(), pkt->getAddr(), pkt->cmdString());
     assert(pkt->getDest() == Packet::Broadcast);
 
-    // Assume one bus cycle in order to get through.  This may have
-    // some clock skew issues yet again...
-    pkt->finishTime = curTick + clock;
+    // Variables for recording original command and snoop response (if
+    // any)... if a snooper respondes, we will need to restore
+    // original command so that additional snoops can take place
+    // properly
+    MemCmd orig_cmd = pkt->cmd;
+    Packet::Result response_result = Packet::Unknown;
+    MemCmd response_cmd = MemCmd::InvalidCmd;
 
-    Port *port = findPort(pkt->getAddr(), pkt->getSrc());
-    Tick snoopTime = atomicSnoop(pkt, port ? port : interfaces[pkt->getSrc()]);
+    Port *target_port = findPort(pkt->getAddr(), pkt->getSrc());
 
-    if (snoopTime)
-        return snoopTime;  //Snoop satisfies it
-    else if (port)
-        return port->sendAtomic(pkt);
-    else
-        return 0;
+    SnoopIter s_end = snoopPorts.end();
+    for (SnoopIter s_iter = snoopPorts.begin(); s_iter != s_end; s_iter++) {
+        BusPort *p = *s_iter;
+        // same port should not have both target addresses and snooping
+        assert(p != target_port);
+        if (p->getId() != pkt->getSrc()) {
+            p->sendAtomic(pkt);
+            if (pkt->result != Packet::Unknown) {
+                // response from snoop agent
+                assert(pkt->cmd != orig_cmd);
+                assert(pkt->memInhibitAsserted());
+                assert(pkt->isResponse());
+                // should only happen once
+                assert(response_result == Packet::Unknown);
+                assert(response_cmd == MemCmd::InvalidCmd);
+                // save response state
+                response_result = pkt->result;
+                response_cmd = pkt->cmd;
+                // restore original packet state for remaining snoopers
+                pkt->cmd = orig_cmd;
+                pkt->result = Packet::Unknown;
+            }
+        }
+    }
+
+    Tick response_time = target_port->sendAtomic(pkt);
+
+    // if we got a response from a snooper, restore it here
+    if (response_result != Packet::Unknown) {
+        assert(response_cmd != MemCmd::InvalidCmd);
+        // no one else should have responded
+        assert(pkt->result == Packet::Unknown);
+        assert(pkt->cmd == orig_cmd);
+        pkt->cmd = response_cmd;
+        pkt->result = response_result;
+    }
+
+    // why do we have this packet field and the return value both???
+    pkt->finishTime = std::max(response_time, curTick + clock);
+    return pkt->finishTime;
 }
 
 /** Function called by the port when the bus is receiving a Functional
index 5dd98c07edffffcd268517b55df226bc0fc29480..33619bf45dd2f1a491dfa9dd57ced3b8b7b5ba49 100644 (file)
@@ -182,9 +182,6 @@ class Bus : public MemObject
      */
     Port *findPort(Addr addr, int id);
 
-    /** Snoop all relevant ports atomicly. */
-    Tick atomicSnoop(PacketPtr pkt, Port* responder);
-
     /** Snoop all relevant ports functionally. */
     void functionalSnoop(PacketPtr pkt, Port *responder);
 
index a47c19e60ab35eb04431d9426709ff0917eefe65..c7006550bbe6eb44eecea077ec0ac529acb72ac1 100644 (file)
 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);
index a27ac1788408f39ef3e43273977291d90ec48326..5969b4b3f19f2ba0486acb22ac4b8121167a73bd 100644 (file)
 #include "base/misc.hh"
 #include "base/statistics.hh"
 #include "base/trace.hh"
+#include "mem/cache/miss/mshr_queue.hh"
 #include "mem/mem_object.hh"
 #include "mem/packet.hh"
-#include "mem/port.hh"
+#include "mem/tport.hh"
 #include "mem/request.hh"
 #include "sim/eventq.hh"
+#include "sim/sim_exit.hh"
 
 /**
  * Reasons for Caches to be Blocked.
@@ -79,7 +81,7 @@ class MSHR;
  */
 class BaseCache : public MemObject
 {
-    class CachePort : public Port
+    class CachePort : public SimpleTimingPort
     {
       public:
         BaseCache *cache;
@@ -102,77 +104,76 @@ class BaseCache : public MemObject
 
         void clearBlocked();
 
-        bool checkFunctional(PacketPtr pkt);
-
         void checkAndSendFunctional(PacketPtr pkt);
 
-        bool canDrain() { return drainList.empty() && transmitList.empty(); }
-
-        bool drainResponse();
-
         CachePort *otherPort;
 
         bool blocked;
 
-        bool mustSendRetry;
-
         bool waitingOnRetry;
 
+        bool mustSendRetry;
+
         /**
          * Bit vector for the outstanding requests for the master interface.
          */
         uint8_t requestCauses;
 
-        std::list<PacketPtr> drainList;
-
-        std::list<std::pair<Tick,PacketPtr> > transmitList;
-
         bool isBusRequested() { return requestCauses != 0; }
 
-        // These need to be virtual since the Event objects depend on
-        // cache template parameters.
-        virtual void scheduleRequestEvent(Tick t) = 0;
-
         void requestBus(RequestCause cause, Tick time)
         {
+            DPRINTF(Cache, "Asserting bus request for cause %d\n", cause);
             if (!isBusRequested() && !waitingOnRetry) {
-                scheduleRequestEvent(time);
+                assert(!sendEvent->scheduled());
+                sendEvent->schedule(time);
             }
             requestCauses |= (1 << cause);
         }
 
         void deassertBusRequest(RequestCause cause)
         {
+            DPRINTF(Cache, "Deasserting bus request for cause %d\n", cause);
             requestCauses &= ~(1 << cause);
         }
 
-        void respond(PacketPtr pkt, Tick time);
+        void respond(PacketPtr pkt, Tick time) {
+            schedSendTiming(pkt, time);
+        }
     };
 
   public: //Made public so coherence can get at it.
     CachePort *cpuSidePort;
     CachePort *memSidePort;
 
-  private:
+  protected:
+
+    /** Miss status registers */
+    MSHRQueue mshrQueue;
+
+    /** Write/writeback buffer */
+    MSHRQueue writeBuffer;
+
+    /** Block size of this cache */
+    const int blkSize;
+
+    /** The number of targets for each MSHR. */
+    const int numTarget;
+
+    /** Increasing order number assigned to each incoming request. */
+    uint64_t order;
+
     /**
      * Bit vector of the blocking reasons for the access path.
      * @sa #BlockedCause
      */
     uint8_t blocked;
 
-    /**
-     * Bit vector for the blocking reasons for the snoop path.
-     * @sa #BlockedCause
-     */
-    uint8_t blockedSnoop;
-
-  protected:
-
     /** Stores time the cache blocked for statistics. */
     Tick blockedCycle;
 
-    /** Block size of this cache */
-    const int blkSize;
+    /** Pointer to the MSHR that has no targets. */
+    MSHR *noTargetMSHR;
 
     /** The number of misses to trigger an exit event. */
     Counter missCount;
@@ -246,6 +247,73 @@ class BaseCache : public MemObject
     /** The number of cache copies performed. */
     Stats::Scalar<> cacheCopies;
 
+    /** Number of blocks written back per thread. */
+    Stats::Vector<> writebacks;
+
+    /** Number of misses that hit in the MSHRs per command and thread. */
+    Stats::Vector<> mshr_hits[MemCmd::NUM_MEM_CMDS];
+    /** Demand misses that hit in the MSHRs. */
+    Stats::Formula demandMshrHits;
+    /** Total number of misses that hit in the MSHRs. */
+    Stats::Formula overallMshrHits;
+
+    /** Number of misses that miss in the MSHRs, per command and thread. */
+    Stats::Vector<> mshr_misses[MemCmd::NUM_MEM_CMDS];
+    /** Demand misses that miss in the MSHRs. */
+    Stats::Formula demandMshrMisses;
+    /** Total number of misses that miss in the MSHRs. */
+    Stats::Formula overallMshrMisses;
+
+    /** Number of misses that miss in the MSHRs, per command and thread. */
+    Stats::Vector<> mshr_uncacheable[MemCmd::NUM_MEM_CMDS];
+    /** Total number of misses that miss in the MSHRs. */
+    Stats::Formula overallMshrUncacheable;
+
+    /** Total cycle latency of each MSHR miss, per command and thread. */
+    Stats::Vector<> mshr_miss_latency[MemCmd::NUM_MEM_CMDS];
+    /** Total cycle latency of demand MSHR misses. */
+    Stats::Formula demandMshrMissLatency;
+    /** Total cycle latency of overall MSHR misses. */
+    Stats::Formula overallMshrMissLatency;
+
+    /** Total cycle latency of each MSHR miss, per command and thread. */
+    Stats::Vector<> mshr_uncacheable_lat[MemCmd::NUM_MEM_CMDS];
+    /** Total cycle latency of overall MSHR misses. */
+    Stats::Formula overallMshrUncacheableLatency;
+
+    /** The total number of MSHR accesses per command and thread. */
+    Stats::Formula mshrAccesses[MemCmd::NUM_MEM_CMDS];
+    /** The total number of demand MSHR accesses. */
+    Stats::Formula demandMshrAccesses;
+    /** The total number of MSHR accesses. */
+    Stats::Formula overallMshrAccesses;
+
+    /** The miss rate in the MSHRs pre command and thread. */
+    Stats::Formula mshrMissRate[MemCmd::NUM_MEM_CMDS];
+    /** The demand miss rate in the MSHRs. */
+    Stats::Formula demandMshrMissRate;
+    /** The overall miss rate in the MSHRs. */
+    Stats::Formula overallMshrMissRate;
+
+    /** The average latency of an MSHR miss, per command and thread. */
+    Stats::Formula avgMshrMissLatency[MemCmd::NUM_MEM_CMDS];
+    /** The average latency of a demand MSHR miss. */
+    Stats::Formula demandAvgMshrMissLatency;
+    /** The average overall latency of an MSHR miss. */
+    Stats::Formula overallAvgMshrMissLatency;
+
+    /** The average latency of an MSHR miss, per command and thread. */
+    Stats::Formula avgMshrUncacheableLatency[MemCmd::NUM_MEM_CMDS];
+    /** The average overall latency of an MSHR miss. */
+    Stats::Formula overallAvgMshrUncacheableLatency;
+
+    /** The number of times a thread hit its MSHR cap. */
+    Stats::Vector<> mshr_cap_events;
+    /** The number of times software prefetches caused the MSHR to block. */
+    Stats::Vector<> soft_prefetch_mshr_full;
+
+    Stats::Scalar<> mshr_no_allocate_misses;
+
     /**
      * @}
      */
@@ -260,12 +328,13 @@ class BaseCache : public MemObject
     class Params
     {
       public:
-        /** List of address ranges of this cache. */
-        std::vector<Range<Addr> > addrRange;
         /** The hit latency for this cache. */
         int hitLatency;
         /** The block size of this cache. */
         int blkSize;
+        int numMSHRs;
+        int numTargets;
+        int numWriteBuffers;
         /**
          * The maximum number of misses this cache should handle before
          * ending the simulation.
@@ -275,10 +344,12 @@ class BaseCache : public MemObject
         /**
          * Construct an instance of this parameter class.
          */
-        Params(std::vector<Range<Addr> > addr_range,
-               int hit_latency, int _blkSize, Counter max_misses)
-            : addrRange(addr_range), hitLatency(hit_latency), blkSize(_blkSize),
-              maxMisses(max_misses)
+        Params(int _hitLatency, int _blkSize,
+               int _numMSHRs, int _numTargets, int _numWriteBuffers,
+               Counter _maxMisses)
+            : hitLatency(_hitLatency), blkSize(_blkSize),
+              numMSHRs(_numMSHRs), numTargets(_numTargets),
+              numWriteBuffers(_numWriteBuffers), maxMisses(_maxMisses)
         {
         }
     };
@@ -307,6 +378,10 @@ class BaseCache : public MemObject
         return blkSize;
     }
 
+
+    Addr blockAlign(Addr addr) const { return (addr & ~(blkSize - 1)); }
+
+
     /**
      * Returns true if the cache is blocked for accesses.
      */
@@ -315,14 +390,6 @@ class BaseCache : public MemObject
         return blocked != 0;
     }
 
-    /**
-     * Returns true if the cache is blocked for snoops.
-     */
-    bool isBlockedForSnoop()
-    {
-        return blockedSnoop != 0;
-    }
-
     /**
      * Marks the access path of the cache as blocked for the given cause. This
      * also sets the blocked flag in the slave interface.
@@ -345,23 +412,6 @@ class BaseCache : public MemObject
         }
     }
 
-    /**
-     * Marks the snoop path of the cache as blocked for the given cause. This
-     * also sets the blocked flag in the master interface.
-     * @param cause The reason to block the snoop path.
-     */
-    void setBlockedForSnoop(BlockedCause cause)
-    {
-        uint8_t flag = 1 << cause;
-        uint8_t old_state = blockedSnoop;
-        if (!(blockedSnoop & flag)) {
-            //Wasn't already blocked for this cause
-            blockedSnoop |= flag;
-            if (!old_state)
-                memSidePort->setBlocked();
-        }
-    }
-
     /**
      * Marks the cache as unblocked for the given cause. This also clears the
      * blocked flags in the appropriate interfaces.
@@ -383,13 +433,6 @@ class BaseCache : public MemObject
                 cpuSidePort->clearBlocked();
             }
         }
-        if (blockedSnoop & flag)
-        {
-            blockedSnoop &= ~flag;
-            if (!isBlockedForSnoop()) {
-                memSidePort->clearBlocked();
-            }
-        }
     }
 
     /**
@@ -418,55 +461,26 @@ class BaseCache : public MemObject
     void deassertMemSideBusRequest(RequestCause cause)
     {
         memSidePort->deassertBusRequest(cause);
-        checkDrain();
+        // checkDrain();
     }
 
-    /**
-     * Send a response to the slave interface.
-     * @param pkt The request being responded to.
-     * @param time The time the response is ready.
-     */
-    void respond(PacketPtr pkt, Tick time)
-    {
-        cpuSidePort->respond(pkt, time);
-    }
+    virtual unsigned int drain(Event *de);
 
-    /**
-     * Suppliess the data if cache to cache transfers are enabled.
-     * @param pkt The bus transaction to fulfill.
-     */
-    void respondToSnoop(PacketPtr pkt, Tick time)
-    {
-        memSidePort->respond(pkt, time);
-    }
+    virtual bool inCache(Addr addr) = 0;
 
-    virtual unsigned int drain(Event *de);
+    virtual bool inMissQueue(Addr addr) = 0;
 
-    void checkDrain()
+    void incMissCount(PacketPtr pkt)
     {
-        if (drainEvent && canDrain()) {
-            drainEvent->process();
-            changeState(SimObject::Drained);
-            // Clear the drain event
-            drainEvent = NULL;
-        }
-    }
+        misses[pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/]++;
 
-    bool canDrain()
-    {
-        if (isMemSideBusRequested()) {
-            return false;
-        } else if (memSidePort && !memSidePort->canDrain()) {
-            return false;
-        } else if (cpuSidePort && !cpuSidePort->canDrain()) {
-            return false;
+        if (missCount) {
+            --missCount;
+            if (missCount == 0)
+                exitSimLoop("A cache reached the maximum miss count");
         }
-        return true;
     }
 
-    virtual bool inCache(Addr addr) = 0;
-
-    virtual bool inMissQueue(Addr addr) = 0;
 };
 
 #endif //__BASE_CACHE_HH__
index 2b4e7b9c8066e731729aacdebf936c6e6670fffe..96f9a2e11151d311741e8639e3a467d6033a784a 100644 (file)
@@ -58,9 +58,6 @@
 #include "mem/cache/tags/split_lifo.hh"
 #endif
 
-#include "mem/cache/miss/miss_queue.hh"
-#include "mem/cache/miss/blocking_buffer.hh"
-
 #include "mem/cache/coherence/simple_coherence.hh"
 
 #include "mem/cache/cache_impl.hh"
index e14b2efe87835dc0ffb2f434b018a2b5d5eaa319..16d15cf8600135366a139410ea2fc3a4a99e9cc6 100644 (file)
 
 #include "mem/cache/base_cache.hh"
 #include "mem/cache/cache_blk.hh"
-#include "mem/cache/miss/miss_buffer.hh"
+#include "mem/cache/miss/mshr.hh"
 
 #include "sim/eventq.hh"
 
 //Forward decleration
-class MSHR;
 class BasePrefetcher;
 
 /**
@@ -86,29 +85,14 @@ class Cache : public BaseCache
             return static_cast<Cache<TagStore,Coherence> *>(cache);
         }
 
-        void processRequestEvent();
-        void processResponseEvent();
-
         virtual void getDeviceAddressRanges(AddrRangeList &resp,
                                             bool &snoop);
 
         virtual bool recvTiming(PacketPtr pkt);
 
-        virtual void recvRetry();
-
         virtual Tick recvAtomic(PacketPtr pkt);
 
         virtual void recvFunctional(PacketPtr pkt);
-
-        typedef EventWrapper<CpuSidePort, &CpuSidePort::processResponseEvent>
-                ResponseEvent;
-
-        typedef EventWrapper<CpuSidePort, &CpuSidePort::processRequestEvent>
-                RequestEvent;
-
-        virtual void scheduleRequestEvent(Tick t) {
-            new RequestEvent(this, t);
-        }
     };
 
     class MemSidePort : public CachePort
@@ -124,8 +108,9 @@ class Cache : public BaseCache
             return static_cast<Cache<TagStore,Coherence> *>(cache);
         }
 
-        void processRequestEvent();
-        void processResponseEvent();
+        void sendPacket();
+
+        void processSendEvent();
 
         virtual void getDeviceAddressRanges(AddrRangeList &resp,
                                             bool &snoop);
@@ -138,21 +123,13 @@ class Cache : public BaseCache
 
         virtual void recvFunctional(PacketPtr pkt);
 
-        typedef EventWrapper<MemSidePort, &MemSidePort::processResponseEvent>
-                ResponseEvent;
-
-        typedef EventWrapper<MemSidePort, &MemSidePort::processRequestEvent>
-                RequestEvent;
-
-        virtual void scheduleRequestEvent(Tick t) {
-            new RequestEvent(this, t);
-        }
+        typedef EventWrapper<MemSidePort, &MemSidePort::processSendEvent>
+                SendEvent;
     };
 
     /** Tag and data Storage */
     TagStore *tags;
-    /** Miss and Writeback handler */
-    MissBuffer *missQueue;
+
     /** Coherence protocol. */
     Coherence *coherence;
 
@@ -176,23 +153,6 @@ class Cache : public BaseCache
      */
     int hitLatency;
 
-     /**
-      * A permanent mem req to always be used to cause invalidations.
-      * Used to append to target list, to cause an invalidation.
-      */
-    PacketPtr invalidatePkt;
-    Request *invalidateReq;
-
-    /**
-     * Policy class for performing compression.
-     */
-    CompressionAlgorithm *compressionAlg;
-
-    /**
-     * The block size of this cache. Set to value in the Tags object.
-     */
-    const int16_t blkSize;
-
     /**
      * Can this cache should allocate a block on a line-sized write miss.
      */
@@ -200,50 +160,6 @@ class Cache : public BaseCache
 
     const bool prefetchMiss;
 
-    /**
-     * Can the data can be stored in a compressed form.
-     */
-    const bool storeCompressed;
-
-    /**
-     * Do we need to compress blocks on writebacks (i.e. because
-     * writeback bus is compressed but storage is not)?
-     */
-    const bool compressOnWriteback;
-
-    /**
-     * The latency of a compression operation.
-     */
-    const int16_t compLatency;
-
-    /**
-     * Should we use an adaptive compression scheme.
-     */
-    const bool adaptiveCompression;
-
-    /**
-     * Do writebacks need to be compressed (i.e. because writeback bus
-     * is compressed), whether or not they're already compressed for
-     * storage.
-     */
-    const bool writebackCompressed;
-
-    /**
-     * Compare the internal block data to the fast access block data.
-     * @param blk The cache block to check.
-     * @return True if the data is the same.
-     */
-    bool verifyData(BlkType *blk);
-
-    /**
-     * Update the internal data of the block. The data to write is assumed to
-     * be in the fast access data.
-     * @param blk The block with the data to update.
-     * @param writebacks A list to store any generated writebacks.
-     * @param compress_block True if we should compress this block
-     */
-    void updateData(BlkType *blk, PacketList &writebacks, bool compress_block);
-
     /**
      * Handle a replacement for the given request.
      * @param blk A pointer to the block, usually NULL
@@ -251,7 +167,7 @@ class Cache : public BaseCache
      * @param new_state The new state of the block.
      * @param writebacks A list to store any generated writebacks.
      */
-    BlkType* doReplacement(BlkType *blk, PacketPtr &pkt,
+    BlkType* doReplacement(BlkType *blk, PacketPtr pkt,
                            CacheBlk::State new_state, PacketList &writebacks);
 
     /**
@@ -263,59 +179,38 @@ class Cache : public BaseCache
      * @return Pointer to the cache block touched by the request. NULL if it
      * was a miss.
      */
-    BlkType* handleAccess(PacketPtr &pkt, int & lat,
-                          PacketList & writebacks, bool update = true);
-
+    bool access(PacketPtr pkt, BlkType *blk, int & lat);
 
     /**
      *Handle doing the Compare and Swap function for SPARC.
      */
-    void cmpAndSwap(BlkType *blk, PacketPtr &pkt);
-
-    /**
-     * Populates a cache block and handles all outstanding requests for the
-     * satisfied fill request. This version takes an MSHR pointer and uses its
-     * request to fill the cache block, while repsonding to its targets.
-     * @param blk The cache block if it already exists.
-     * @param mshr The MSHR that contains the fill data and targets to satisfy.
-     * @param new_state The state of the new cache block.
-     * @param writebacks List for any writebacks that need to be performed.
-     * @return Pointer to the new cache block.
-     */
-    BlkType* handleFill(BlkType *blk, MSHR * mshr, CacheBlk::State new_state,
-                        PacketList & writebacks, PacketPtr pkt);
+    void cmpAndSwap(BlkType *blk, PacketPtr pkt);
 
     /**
      * Populates a cache block and handles all outstanding requests for the
      * satisfied fill request. This version takes two memory requests. One
      * contains the fill data, the other is an optional target to satisfy.
      * Used for Cache::probe.
-     * @param blk The cache block if it already exists.
      * @param pkt The memory request with the fill data.
-     * @param new_state The state of the new cache block.
+     * @param blk The cache block if it already exists.
      * @param writebacks List for any writebacks that need to be performed.
-     * @param target The memory request to perform after the fill.
      * @return Pointer to the new cache block.
      */
-    BlkType* handleFill(BlkType *blk, PacketPtr &pkt,
-                        CacheBlk::State new_state,
-                        PacketList & writebacks, PacketPtr target = NULL);
+    BlkType *handleFill(PacketPtr pkt, BlkType *blk,
+                        PacketList &writebacks);
 
-    /**
-     * Sets the blk to the new state and handles the given request.
-     * @param blk The cache block being snooped.
-     * @param new_state The new coherence state for the block.
-     * @param pkt The request to satisfy
-     */
-    void handleSnoop(BlkType *blk, CacheBlk::State new_state,
-                     PacketPtr &pkt);
+    bool satisfyCpuSideRequest(PacketPtr pkt, BlkType *blk);
+    bool satisfyTarget(MSHR::Target *target, BlkType *blk);
+    void satisfyMSHR(MSHR *mshr, PacketPtr pkt, BlkType *blk);
+
+    void doTimingSupplyResponse(PacketPtr req_pkt, uint8_t *blk_data);
 
     /**
      * Sets the blk to the new state.
      * @param blk The cache block being snooped.
      * @param new_state The new coherence state for the block.
      */
-    void handleSnoop(BlkType *blk, CacheBlk::State new_state);
+    void handleSnoop(PacketPtr ptk, BlkType *blk, bool is_timing);
 
     /**
      * Create a writeback request for the given block.
@@ -330,44 +225,24 @@ class Cache : public BaseCache
     {
       public:
         TagStore *tags;
-        MissBuffer *missQueue;
         Coherence *coherence;
         BaseCache::Params baseParams;
         BasePrefetcher*prefetcher;
         bool prefetchAccess;
-        int hitLatency;
-        CompressionAlgorithm *compressionAlg;
-        const int16_t blkSize;
         const bool doFastWrites;
         const bool prefetchMiss;
-        const bool storeCompressed;
-        const bool compressOnWriteback;
-        const int16_t compLatency;
-        const bool adaptiveCompression;
-        const bool writebackCompressed;
 
-        Params(TagStore *_tags, MissBuffer *mq, Coherence *coh,
+        Params(TagStore *_tags, Coherence *coh,
                BaseCache::Params params,
                BasePrefetcher *_prefetcher,
                bool prefetch_access, int hit_latency,
                bool do_fast_writes,
-               bool store_compressed, bool adaptive_compression,
-               bool writeback_compressed,
-               CompressionAlgorithm *_compressionAlg, int comp_latency,
                bool prefetch_miss)
-            : tags(_tags), missQueue(mq), coherence(coh),
+            : tags(_tags), coherence(coh),
               baseParams(params),
               prefetcher(_prefetcher), prefetchAccess(prefetch_access),
-              hitLatency(hit_latency),
-              compressionAlg(_compressionAlg),
-              blkSize(_tags->getBlockSize()),
               doFastWrites(do_fast_writes),
-              prefetchMiss(prefetch_miss),
-              storeCompressed(store_compressed),
-              compressOnWriteback(!store_compressed && writeback_compressed),
-              compLatency(comp_latency),
-              adaptiveCompression(adaptive_compression),
-              writebackCompressed(writeback_compressed)
+              prefetchMiss(prefetch_miss)
         {
         }
     };
@@ -385,85 +260,105 @@ class Cache : public BaseCache
      * @param pkt The request to perform.
      * @return The result of the access.
      */
-    bool access(PacketPtr &pkt);
+    bool timingAccess(PacketPtr pkt);
 
     /**
-     * Selects a request to send on the bus.
-     * @return The memory request to service.
+     * Performs the access specified by the request.
+     * @param pkt The request to perform.
+     * @return The result of the access.
      */
-    PacketPtr getPacket();
+    Tick atomicAccess(PacketPtr pkt);
 
     /**
-     * Was the request was sent successfully?
-     * @param pkt The request.
-     * @param success True if the request was sent successfully.
+     * Performs the access specified by the request.
+     * @param pkt The request to perform.
+     * @return The result of the access.
      */
-    void sendResult(PacketPtr &pkt, MSHR* mshr, bool success);
+    void functionalAccess(PacketPtr pkt, CachePort *otherSidePort);
 
     /**
      * Handles a response (cache line fill/write ack) from the bus.
      * @param pkt The request being responded to.
      */
-    void handleResponse(PacketPtr &pkt);
+    void handleResponse(PacketPtr pkt);
 
     /**
      * Snoops bus transactions to maintain coherence.
      * @param pkt The current bus transaction.
      */
-    void snoop(PacketPtr &pkt);
+    void snoopTiming(PacketPtr pkt);
 
-    void snoopResponse(PacketPtr &pkt);
+    /**
+     * Snoop for the provided request in the cache and return the estimated
+     * time of completion.
+     * @param pkt The memory request to snoop
+     * @return The estimated completion time.
+     */
+    Tick snoopAtomic(PacketPtr pkt);
 
     /**
      * Squash all requests associated with specified thread.
      * intended for use by I-cache.
      * @param threadNum The thread to squash.
      */
-    void squash(int threadNum)
-    {
-        missQueue->squash(threadNum);
-    }
+    void squash(int threadNum);
 
     /**
-     * Return the number of outstanding misses in a Cache.
-     * Default returns 0.
-     *
-     * @retval unsigned The number of missing still outstanding.
+     * Allocate a new MSHR or write buffer to handle a miss.
+     * @param pkt The access that missed.
+     * @param time The time to continue processing the miss.
+     * @param isFill Whether to fetch & allocate a block
+     *               or just forward the request.
      */
-    unsigned outstandingMisses() const
-    {
-        return missQueue->getMisses();
-    }
+    MSHR *allocateBuffer(PacketPtr pkt, Tick time, bool isFill,
+                         bool requestBus);
 
     /**
-     * Perform the access specified in the request and return the estimated
-     * time of completion. This function can either update the hierarchy state
-     * or just perform the access wherever the data is found depending on the
-     * state of the update flag.
-     * @param pkt The memory request to satisfy
-     * @param update If true, update the hierarchy, otherwise just perform the
-     * request.
-     * @return The estimated completion time.
+     * Selects a outstanding request to service.
+     * @return The request to service, NULL if none found.
      */
-    Tick probe(PacketPtr &pkt, bool update, CachePort * otherSidePort);
+    MSHR *getNextMSHR();
+    PacketPtr getPacket();
 
     /**
-     * Snoop for the provided request in the cache and return the estimated
-     * time of completion.
-     * @todo Can a snoop probe not change state?
-     * @param pkt The memory request to satisfy
-     * @param update If true, update the hierarchy, otherwise just perform the
-     * request.
-     * @return The estimated completion time.
+     * Marks a request as in service (sent on the bus). This can have side
+     * effect since storage for no response commands is deallocated once they
+     * are successfully sent.
+     * @param pkt The request that was sent on the bus.
      */
-    Tick snoopProbe(PacketPtr &pkt);
+    void markInService(MSHR *mshr);
+
+    /**
+     * Collect statistics and free resources of a satisfied request.
+     * @param pkt The request that has been satisfied.
+     * @param time The time when the request is satisfied.
+     */
+    void handleResponse(PacketPtr pkt, Tick time);
+
+    /**
+     * Perform the given writeback request.
+     * @param pkt The writeback request.
+     */
+    void doWriteback(PacketPtr pkt);
+
+    /**
+     * Return whether there are any outstanding misses.
+     */
+    bool outstandingMisses() const
+    {
+        return mshrQueue.allocated != 0;
+    }
+
+    CacheBlk *findBlock(Addr addr) {
+        return tags->findBlock(addr);
+    }
 
     bool inCache(Addr addr) {
         return (tags->findBlock(addr) != 0);
     }
 
     bool inMissQueue(Addr addr) {
-        return (missQueue->findMSHR(addr) != 0);
+        return (mshrQueue.findMatch(addr) != 0);
     }
 };
 
index fa00a0f5af5e670e0fc6df0f7dca7f0357501134..d2aba948022ae94411075c526a92589cabd9b718 100644 (file)
@@ -39,6 +39,7 @@
 
 #include "sim/core.hh"         // for Tick
 #include "arch/isa_traits.hh"  // for Addr
+#include "mem/packet.hh"
 #include "mem/request.hh"
 
 /**
@@ -51,8 +52,6 @@ enum CacheBlkStatusBits {
     BlkWritable =      0x02,
     /** dirty (modified) */
     BlkDirty =         0x04,
-    /** compressed */
-    BlkCompressed =    0x08,
     /** block was referenced */
     BlkReferenced =    0x10,
     /** block was a hardware prefetch yet unaccessed*/
@@ -174,20 +173,11 @@ class CacheBlk
      * Check to see if a block has been written.
      * @return True if the block is dirty.
      */
-    bool isModified() const
+    bool isDirty() const
     {
         return (status & BlkDirty) != 0;
     }
 
-    /**
-     * Check to see if this block contains compressed data.
-     * @return True iF the block's data is compressed.
-     */
-    bool isCompressed() const
-    {
-        return (status & BlkCompressed) != 0;
-    }
-
     /**
      * Check if this block has been referenced.
      * @return True if the block has been referenced.
@@ -213,10 +203,10 @@ class CacheBlk
      * redundant records on the list, but that's OK, as they'll all
      * get blown away at the next store.
      */
-    void trackLoadLocked(Request *req)
+    void trackLoadLocked(PacketPtr pkt)
     {
-        assert(req->isLocked());
-        lockList.push_front(Lock(req));
+        assert(pkt->isLocked());
+        lockList.push_front(Lock(pkt->req));
     }
 
     /**
@@ -230,9 +220,10 @@ class CacheBlk
      * @return True if write should proceed, false otherwise.  Returns
      * false only in the case of a failed store conditional.
      */
-    bool checkWrite(Request *req)
+    bool checkWrite(PacketPtr pkt)
     {
-        if (req->isLocked()) {
+        Request *req = pkt->req;
+        if (pkt->isLocked()) {
             // it's a store conditional... have to check for matching
             // load locked.
             bool success = false;
index bc1a8a775c2761c8a4ca16fe9db0f8663616f23d..307c851a2dedb8fee4f50da9a14c9ccd8c0963b7 100644 (file)
 #include "base/compression/null_compression.hh"
 #include "base/compression/lzss_compression.hh"
 
-// MissQueue Templates
-#include "mem/cache/miss/miss_queue.hh"
-#include "mem/cache/miss/blocking_buffer.hh"
-
 // Coherence Templates
 #include "mem/cache/coherence/simple_coherence.hh"
 
@@ -207,13 +203,9 @@ END_INIT_SIM_OBJECT_PARAMS(BaseCache)
         else {                                                          \
             BUILD_NULL_PREFETCHER(TAGS);                                \
         }                                                               \
-        Cache<TAGS, c>::Params params(tags, mq, coh, base_params,       \
+        Cache<TAGS, c>::Params params(tags, coh, base_params,       \
                                       pf, prefetch_access, latency, \
                                       true,                             \
-                                      store_compressed,                 \
-                                      adaptive_compression,             \
-                                      compressed_bus,                   \
-                                      compAlg, compression_latency,     \
                                       prefetch_miss);                   \
         Cache<TAGS, c> *retval =                                        \
             new Cache<TAGS, c>(getInstanceName(), params);              \
@@ -301,8 +293,6 @@ END_INIT_SIM_OBJECT_PARAMS(BaseCache)
     } while (0)
 
 #define BUILD_COHERENCE(b) do {                                                \
-        SimpleCoherence *coh = new SimpleCoherence(protocol);           \
-        BUILD_CACHES(SimpleCoherence);                                  \
     } while (0)
 
 #if defined(USE_TAGGED)
@@ -369,8 +359,9 @@ CREATE_SIM_OBJECT(BaseCache)
     }
 
     // Build BaseCache param object
-    BaseCache::Params base_params(addr_range, latency,
-                                  block_size, max_miss_count);
+    BaseCache::Params base_params(latency, block_size,
+                                  mshrs, tgts_per_mshr, write_buffers,
+                                  max_miss_count);
 
     //Warnings about prefetcher policy
     if (pf_policy == "none" && (prefetch_miss || prefetch_access)) {
@@ -408,14 +399,8 @@ CREATE_SIM_OBJECT(BaseCache)
     const void *repl = NULL;
 #endif
 
-    if (mshrs == 1 /*|| out_bus->doEvents() == false*/) {
-        BlockingBuffer *mq = new BlockingBuffer(true);
-        BUILD_COHERENCE(BlockingBuffer);
-    } else {
-        MissQueue *mq = new MissQueue(mshrs, tgts_per_mshr, write_buffers,
-                                      true, prefetch_miss);
-        BUILD_COHERENCE(MissQueue);
-    }
+    SimpleCoherence *coh = new SimpleCoherence(protocol);
+    BUILD_CACHES(SimpleCoherence);
     return NULL;
 }
 
index a7f96603ed4c4bf3e441581424efb2f0f8abae0d..0f66e613c77315d3417477944d8bdd5038e1db1e 100644 (file)
  * Cache definitions.
  */
 
-#include <assert.h>
-#include <math.h>
-
-#include <cassert>
-#include <iostream>
-#include <cstring>
-#include <string>
-
 #include "sim/host.hh"
 #include "base/misc.hh"
-#include "cpu/smt.hh"
 
 #include "mem/cache/cache.hh"
 #include "mem/cache/cache_blk.hh"
 
 #include "sim/sim_exit.hh" // for SimExitEvent
 
-bool SIGNAL_NACK_HACK;
 
 template<class TagStore, class Coherence>
 Cache<TagStore,Coherence>::Cache(const std::string &_name,
                                  Cache<TagStore,Coherence>::Params &params)
     : BaseCache(_name, params.baseParams),
       prefetchAccess(params.prefetchAccess),
-      tags(params.tags), missQueue(params.missQueue),
+      tags(params.tags),
       coherence(params.coherence), prefetcher(params.prefetcher),
-      hitLatency(params.hitLatency),
-      compressionAlg(params.compressionAlg),
-      blkSize(params.blkSize),
       doFastWrites(params.doFastWrites),
-      prefetchMiss(params.prefetchMiss),
-      storeCompressed(params.storeCompressed),
-      compressOnWriteback(params.compressOnWriteback),
-      compLatency(params.compLatency),
-      adaptiveCompression(params.adaptiveCompression),
-      writebackCompressed(params.writebackCompressed)
+      prefetchMiss(params.prefetchMiss)
 {
     cpuSidePort = new CpuSidePort(_name + "-cpu_side_port", this);
     memSidePort = new MemSidePort(_name + "-mem_side_port", this);
@@ -82,12 +64,8 @@ Cache<TagStore,Coherence>::Cache(const std::string &_name,
     memSidePort->setOtherPort(cpuSidePort);
 
     tags->setCache(this);
-    missQueue->setCache(this);
-    missQueue->setPrefetcher(prefetcher);
     coherence->setCache(this);
     prefetcher->setCache(this);
-    invalidateReq = new Request((Addr) NULL, blkSize, 0);
-    invalidatePkt = new Packet(invalidateReq, MemCmd::InvalidateReq, 0);
 }
 
 template<class TagStore, class Coherence>
@@ -96,51 +74,221 @@ Cache<TagStore,Coherence>::regStats()
 {
     BaseCache::regStats();
     tags->regStats(name());
-    missQueue->regStats(name());
     coherence->regStats(name());
     prefetcher->regStats(name());
 }
 
 template<class TagStore, class Coherence>
-typename Cache<TagStore,Coherence>::BlkType*
-Cache<TagStore,Coherence>::handleAccess(PacketPtr &pkt, int & lat,
-                                        PacketList & writebacks, bool update)
+Port *
+Cache<TagStore,Coherence>::getPort(const std::string &if_name, int idx)
+{
+    if (if_name == "" || if_name == "cpu_side") {
+        return cpuSidePort;
+    } else if (if_name == "mem_side") {
+        return memSidePort;
+    } else if (if_name == "functional") {
+        return new CpuSidePort(name() + "-cpu_side_funcport", this);
+    } else {
+        panic("Port name %s unrecognized\n", if_name);
+    }
+}
+
+template<class TagStore, class Coherence>
+void
+Cache<TagStore,Coherence>::deletePortRefs(Port *p)
+{
+    if (cpuSidePort == p || memSidePort == p)
+        panic("Can only delete functional ports\n");
+
+    delete p;
+}
+
+
+template<class TagStore, class Coherence>
+void
+Cache<TagStore,Coherence>::cmpAndSwap(BlkType *blk, PacketPtr pkt)
 {
-    // Set the block offset here
+    uint64_t overwrite_val;
+    bool overwrite_mem;
+    uint64_t condition_val64;
+    uint32_t condition_val32;
+
     int offset = tags->extractBlkOffset(pkt->getAddr());
+    uint8_t *blk_data = blk->data + offset;
+
+    assert(sizeof(uint64_t) >= pkt->getSize());
+
+    overwrite_mem = true;
+    // keep a copy of our possible write value, and copy what is at the
+    // memory address into the packet
+    pkt->writeData((uint8_t *)&overwrite_val);
+    pkt->setData(blk_data);
+
+    if (pkt->req->isCondSwap()) {
+        if (pkt->getSize() == sizeof(uint64_t)) {
+            condition_val64 = pkt->req->getExtraData();
+            overwrite_mem = !std::memcmp(&condition_val64, blk_data,
+                                         sizeof(uint64_t));
+        } else if (pkt->getSize() == sizeof(uint32_t)) {
+            condition_val32 = (uint32_t)pkt->req->getExtraData();
+            overwrite_mem = !std::memcmp(&condition_val32, blk_data,
+                                         sizeof(uint32_t));
+        } else
+            panic("Invalid size for conditional read/write\n");
+    }
+
+    if (overwrite_mem)
+        std::memcpy(blk_data, &overwrite_val, pkt->getSize());
+}
+
+
+/////////////////////////////////////////////////////
+//
+// MSHR helper functions
+//
+/////////////////////////////////////////////////////
+
+
+template<class TagStore, class Coherence>
+MSHR *
+Cache<TagStore,Coherence>::allocateBuffer(PacketPtr pkt, Tick time,
+                                          bool isFill, bool requestBus)
+{
+    int  size = isFill ? blkSize : pkt->getSize();
+    Addr addr = isFill ? tags->blkAlign(pkt->getAddr()) : pkt->getAddr();
+
+    MSHR *mshr = NULL;
+
+    if (pkt->isWrite()) {
+        /**
+         * @todo Add write merging here.
+         */
+        mshr = writeBuffer.allocate(addr, size, pkt, isFill);
+        mshr->order = order++;
 
-    BlkType *blk = NULL;
-    if (update) {
-        blk = tags->findBlock(pkt->getAddr(), lat);
+        if (writeBuffer.isFull()) {
+            setBlocked(Blocked_NoWBBuffers);
+        }
+
+        if (requestBus) {
+            requestMemSideBus(Request_WB, time);
+        }
     } else {
-        blk = tags->findBlock(pkt->getAddr());
-        lat = 0;
+        mshr = mshrQueue.allocate(addr, size, pkt, isFill);
+        mshr->order = order++;
+        if (mshrQueue.isFull()) {
+            setBlocked(Blocked_NoMSHRs);
+        }
+        if (requestBus) {
+            requestMemSideBus(Request_MSHR, time);
+        }
     }
-    if (blk != NULL) {
 
-        if (!update) {
+    assert(mshr != NULL);
+    return mshr;
+}
 
-            if (pkt->isWrite()){
-                assert(offset < blkSize);
-                assert(pkt->getSize() <= blkSize);
-                assert(offset+pkt->getSize() <= blkSize);
-                std::memcpy(blk->data + offset, pkt->getPtr<uint8_t>(),
-                       pkt->getSize());
-            } else if (pkt->isReadWrite()) {
-                cmpAndSwap(blk, pkt);
-            } else if (!(pkt->flags & SATISFIED)) {
-                pkt->flags |= SATISFIED;
-                pkt->result = Packet::Success;
-                assert(offset < blkSize);
-                assert(pkt->getSize() <= blkSize);
-                assert(offset + pkt->getSize() <=blkSize);
-                std::memcpy(pkt->getPtr<uint8_t>(), blk->data + offset,
-                       pkt->getSize());
+
+template<class TagStore, class Coherence>
+void
+Cache<TagStore,Coherence>::markInService(MSHR *mshr)
+{
+    bool unblock = false;
+    BlockedCause cause = NUM_BLOCKED_CAUSES;
+
+    /**
+     * @todo Should include MSHRQueue pointer in MSHR to select the correct
+     * one.
+     */
+    if (mshr->queue == &writeBuffer) {
+        // Forwarding a write/ writeback, don't need to change
+        // the command
+        unblock = writeBuffer.isFull();
+        writeBuffer.markInService(mshr);
+        if (!writeBuffer.havePending()){
+            deassertMemSideBusRequest(Request_WB);
+        }
+        if (unblock) {
+            // Do we really unblock?
+            unblock = !writeBuffer.isFull();
+            cause = Blocked_NoWBBuffers;
+        }
+    } else {
+        assert(mshr->queue == &mshrQueue);
+        unblock = mshrQueue.isFull();
+        mshrQueue.markInService(mshr);
+        if (!mshrQueue.havePending()){
+            deassertMemSideBusRequest(Request_MSHR);
+        }
+#if 0
+        if (mshr->originalCmd == MemCmd::HardPFReq) {
+            DPRINTF(HWPrefetch, "%s:Marking a HW_PF in service\n",
+                    name());
+            //Also clear pending if need be
+            if (!prefetcher->havePending())
+            {
+                deassertMemSideBusRequest(Request_PF);
             }
-            return blk;
         }
+#endif
+        if (unblock) {
+            unblock = !mshrQueue.isFull();
+            cause = Blocked_NoMSHRs;
+        }
+    }
+    if (unblock) {
+        clearBlocked(cause);
+    }
+}
+
+
+template<class TagStore, class Coherence>
+void
+Cache<TagStore,Coherence>::squash(int threadNum)
+{
+    bool unblock = false;
+    BlockedCause cause = NUM_BLOCKED_CAUSES;
 
-        // Hit
+    if (noTargetMSHR && noTargetMSHR->threadNum == threadNum) {
+        noTargetMSHR = NULL;
+        unblock = true;
+        cause = Blocked_NoTargets;
+    }
+    if (mshrQueue.isFull()) {
+        unblock = true;
+        cause = Blocked_NoMSHRs;
+    }
+    mshrQueue.squash(threadNum);
+    if (!mshrQueue.havePending()) {
+        deassertMemSideBusRequest(Request_MSHR);
+    }
+    if (unblock && !mshrQueue.isFull()) {
+        clearBlocked(cause);
+    }
+}
+
+/////////////////////////////////////////////////////
+//
+// Access path: requests coming in from the CPU side
+//
+/////////////////////////////////////////////////////
+
+template<class TagStore, class Coherence>
+bool
+Cache<TagStore,Coherence>::access(PacketPtr pkt, BlkType *blk, int &lat)
+{
+    bool satisfied = false;  // assume the worst
+
+    if (prefetchAccess) {
+        //We are determining prefetches on access stream, call prefetcher
+        prefetcher->handleMiss(pkt, curTick);
+    }
+
+    DPRINTF(Cache, "%s %x %s\n", pkt->cmdString(), pkt->getAddr(),
+            (blk) ? "hit" : "miss");
+
+    if (blk != NULL) {
+        // HIT
         if (blk->isPrefetch()) {
             //Signal that this was a hit under prefetch (no need for
             //use prefetch (only can get here if true)
@@ -154,639 +302,620 @@ Cache<TagStore,Coherence>::handleAccess(PacketPtr &pkt, int & lat,
             }
         }
 
-        if ((pkt->isReadWrite() && blk->isWritable()) ||
-            (pkt->isWrite() && blk->isWritable()) ||
-            (pkt->isRead() && blk->isValid())) {
-
-            // We are satisfying the request
-            pkt->flags |= SATISFIED;
-
-            if (blk->isCompressed()) {
-                // If the data is compressed, need to increase the latency
-                lat += (compLatency/4);
-            }
-
-            bool write_data = false;
-
-            assert(verifyData(blk));
-
-            assert(offset < blkSize);
-            assert(pkt->getSize() <= blkSize);
-            assert(offset+pkt->getSize() <= blkSize);
+        if (pkt->needsExclusive() ? blk->isWritable() : blk->isValid()) {
+            // OK to satisfy access
+            hits[pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/]++;
+            satisfied = true;
 
-            if (pkt->isWrite()) {
-                if (blk->checkWrite(pkt->req)) {
-                    write_data = true;
+            if (pkt->cmd == MemCmd::SwapReq) {
+                cmpAndSwap(blk, pkt);
+            } else if (pkt->isWrite()) {
+                if (blk->checkWrite(pkt)) {
                     blk->status |= BlkDirty;
-                    std::memcpy(blk->data + offset, pkt->getPtr<uint8_t>(),
-                           pkt->getSize());
+                    pkt->writeDataToBlock(blk->data, blkSize);
                 }
-            } else if (pkt->isReadWrite()) {
-                cmpAndSwap(blk, pkt);
             } else {
                 assert(pkt->isRead());
-                if (pkt->req->isLocked()) {
-                    blk->trackLoadLocked(pkt->req);
+                if (pkt->isLocked()) {
+                    blk->trackLoadLocked(pkt);
                 }
-                std::memcpy(pkt->getPtr<uint8_t>(), blk->data + offset,
-                            pkt->getSize());
-            }
-
-            if (write_data ||
-                (adaptiveCompression && blk->isCompressed()))
-            {
-                // If we wrote data, need to update the internal block
-                // data.
-                updateData(blk, writebacks,
-                           !(adaptiveCompression &&
-                             blk->isReferenced()));
+                pkt->setDataFromBlock(blk->data, blkSize);
             }
         } else {
-            // permission violation, treat it as a miss
-            blk = NULL;
+            // permission violation... nothing to do here, leave unsatisfied
+            // for statistics purposes this counts like a complete miss
+            incMissCount(pkt);
         }
     } else {
         // complete miss (no matching block)
-        if (pkt->req->isLocked() && pkt->isWrite()) {
+        incMissCount(pkt);
+
+        if (pkt->isLocked() && pkt->isWrite()) {
             // miss on store conditional... just give up now
             pkt->req->setExtraData(0);
-            pkt->flags |= SATISFIED;
+            satisfied = true;
         }
     }
 
-    return blk;
+    return satisfied;
 }
 
-template<class TagStore, class Coherence>
-void
-Cache<TagStore,Coherence>::cmpAndSwap(BlkType *blk, PacketPtr &pkt){
-            uint64_t overwrite_val;
-            bool overwrite_mem;
-            uint64_t condition_val64;
-            uint32_t condition_val32;
-
-            int offset = tags->extractBlkOffset(pkt->getAddr());
-
-            assert(sizeof(uint64_t) >= pkt->getSize());
-
-            overwrite_mem = true;
-            // keep a copy of our possible write value, and copy what is at the
-            // memory address into the packet
-            std::memcpy(&overwrite_val, pkt->getPtr<uint8_t>(), pkt->getSize());
-            std::memcpy(pkt->getPtr<uint8_t>(), blk->data + offset,
-                        pkt->getSize());
-
-            if (pkt->req->isCondSwap()) {
-                if (pkt->getSize() == sizeof(uint64_t)) {
-                    condition_val64 = pkt->req->getExtraData();
-                    overwrite_mem = !std::memcmp(&condition_val64, blk->data + offset,
-                                                 sizeof(uint64_t));
-                } else if (pkt->getSize() == sizeof(uint32_t)) {
-                    condition_val32 = (uint32_t)pkt->req->getExtraData();
-                    overwrite_mem = !std::memcmp(&condition_val32, blk->data + offset,
-                                                 sizeof(uint32_t));
-                } else
-                    panic("Invalid size for conditional read/write\n");
-            }
-
-            if (overwrite_mem)
-                std::memcpy(blk->data + offset,
-                            &overwrite_val, pkt->getSize());
-
-}
 
 template<class TagStore, class Coherence>
-typename Cache<TagStore,Coherence>::BlkType*
-Cache<TagStore,Coherence>::handleFill(BlkType *blk, PacketPtr &pkt,
-                                      CacheBlk::State new_state,
-                                      PacketList & writebacks,
-                                      PacketPtr target)
+bool
+Cache<TagStore,Coherence>::timingAccess(PacketPtr pkt)
 {
-#ifndef NDEBUG
-    BlkType *tmp_blk = tags->findBlock(pkt->getAddr());
-    assert(tmp_blk == blk);
-#endif
-    blk = doReplacement(blk, pkt, new_state, writebacks);
+//@todo Add back in MemDebug Calls
+//    MemDebug::cacheAccess(pkt);
 
+    // we charge hitLatency for doing just about anything here
+    Tick time =  curTick + hitLatency;
 
-    if (pkt->isRead()) {
-        std::memcpy(blk->data, pkt->getPtr<uint8_t>(), blkSize);
+    if (pkt->req->isUncacheable()) {
+        allocateBuffer(pkt, time, false, true);
+        assert(pkt->needsResponse()); // else we should delete it here??
+        return true;
     }
 
-        blk->whenReady = pkt->finishTime;
+    PacketList writebacks;
+    int lat = hitLatency;
+    BlkType *blk = tags->findBlock(pkt->getAddr(), lat);
+    bool satisfied = false;
+
+    Addr blk_addr = pkt->getAddr() & ~(Addr(blkSize-1));
 
-    // Respond to target, if any
-    if (target) {
+    MSHR *mshr = mshrQueue.findMatch(blk_addr);
 
-        target->flags |= SATISFIED;
+    if (!mshr) {
+        // no outstanding access to this block, look up in cache
+        // (otherwise if we allow reads while there's an outstanding
+        // write miss, the read could return stale data out of the
+        // cache block... a more aggressive system could detect the
+        // overlap (if any) and forward data out of the MSHRs, but we
+        // don't do that yet)
+        satisfied = access(pkt, blk, lat);
+    }
 
-        if (target->cmd == MemCmd::InvalidateReq) {
-            tags->invalidateBlk(blk);
-            blk = NULL;
+#if 0
+    // If this is a block size write/hint (WH64) allocate the block here
+    // if the coherence protocol allows it.
+    /** @todo make the fast write alloc (wh64) work with coherence. */
+    /** @todo Do we want to do fast writes for writebacks as well? */
+    if (!blk && pkt->getSize() >= blkSize && coherence->allowFastWrites() &&
+        (pkt->cmd == MemCmd::WriteReq
+         || pkt->cmd == MemCmd::WriteInvalidateReq) ) {
+        // not outstanding misses, can do this
+        MSHR *outstanding_miss = mshrQueue.findMatch(pkt->getAddr());
+        if (pkt->cmd == MemCmd::WriteInvalidateReq || !outstanding_miss) {
+            if (outstanding_miss) {
+                warn("WriteInv doing a fastallocate"
+                     "with an outstanding miss to the same address\n");
+            }
+            blk = handleFill(NULL, pkt, BlkValid | BlkWritable,
+                                   writebacks);
+            ++fastWrites;
         }
+    }
+#endif
 
-        if (blk && ((target->isWrite() || target->isReadWrite()) ?
-                    blk->isWritable() : blk->isValid())) {
-            assert(target->isWrite() || target->isReadWrite() || target->isRead());
-            assert(target->getOffset(blkSize) + target->getSize() <= blkSize);
-            if (target->isWrite()) {
-                if (blk->checkWrite(pkt->req)) {
-                    blk->status |= BlkDirty;
-                    std::memcpy(blk->data + target->getOffset(blkSize),
-                           target->getPtr<uint8_t>(), target->getSize());
-                }
-            } else if (target->isReadWrite()) {
-                cmpAndSwap(blk, target);
-            } else {
-                if (pkt->req->isLocked()) {
-                    blk->trackLoadLocked(pkt->req);
-                }
-                std::memcpy(target->getPtr<uint8_t>(),
-                       blk->data + target->getOffset(blkSize),
-                       target->getSize());
+    // copy writebacks to write buffer
+    while (!writebacks.empty()) {
+        PacketPtr wbPkt = writebacks.front();
+        allocateBuffer(wbPkt, time, false, true);
+        writebacks.pop_front();
+    }
+
+    bool needsResponse = pkt->needsResponse();
+
+    if (satisfied) {
+        assert(needsResponse);
+        pkt->makeTimingResponse();
+        cpuSidePort->respond(pkt, curTick+lat);
+    } else {
+        // miss
+        if (prefetchMiss)
+            prefetcher->handleMiss(pkt, time);
+
+        if (mshr) {
+            // MSHR hit
+            //@todo remove hw_pf here
+            mshr_hits[pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/]++;
+            if (mshr->threadNum != 0/*pkt->req->getThreadNum()*/) {
+                mshr->threadNum = -1;
             }
+            mshr->allocateTarget(pkt, true);
+            if (mshr->getNumTargets() == numTarget) {
+                noTargetMSHR = mshr;
+                setBlocked(Blocked_NoTargets);
+                mshrQueue.moveToFront(mshr);
+            }
+        } else {
+            // no MSHR
+            mshr_misses[pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/]++;
+            // always mark as cache fill for now... if we implement
+            // no-write-allocate or bypass accesses this will have to
+            // be changed.
+            allocateBuffer(pkt, time, true, true);
         }
     }
 
-    if (blk) {
-        // Need to write the data into the block
-        updateData(blk, writebacks, !adaptiveCompression || true);
+    if (!needsResponse) {
+        // Need to clean up the packet on a writeback miss, but leave
+        // the request for the next level.
+        delete pkt;
     }
-    return blk;
+
+    return true;
 }
 
+
 template<class TagStore, class Coherence>
-typename Cache<TagStore,Coherence>::BlkType*
-Cache<TagStore,Coherence>::handleFill(BlkType *blk, MSHR * mshr,
-                                      CacheBlk::State new_state,
-                                      PacketList & writebacks, PacketPtr pkt)
+Tick
+Cache<TagStore,Coherence>::atomicAccess(PacketPtr pkt)
 {
-/*
-#ifndef NDEBUG
-    BlkType *tmp_blk = findBlock(mshr->pkt->getAddr());
-    assert(tmp_blk == blk);
-#endif
-    PacketPtr pkt = mshr->pkt;*/
-    blk = doReplacement(blk, pkt, new_state, writebacks);
+    // should assert here that there are no outstanding MSHRs or
+    // writebacks... that would mean that someone used an atomic
+    // access in timing mode
 
-    if (pkt->isRead()) {
-        std::memcpy(blk->data, pkt->getPtr<uint8_t>(), blkSize);
+    if (pkt->req->isUncacheable()) {
+        // Uncacheables just go through
+        return memSidePort->sendAtomic(pkt);
     }
 
-    blk->whenReady = pkt->finishTime;
+    PacketList writebacks;
+    int lat = hitLatency;
+    BlkType *blk = tags->findBlock(pkt->getAddr(), lat);
+    bool satisfied = access(pkt, blk, lat);
 
+    if (!satisfied) {
+        // MISS
+        CacheBlk::State old_state = (blk) ? blk->status : 0;
+        MemCmd cmd = coherence->getBusCmd(pkt->cmd, old_state);
+        Packet busPkt = Packet(pkt->req, cmd, Packet::Broadcast, blkSize);
+        busPkt.allocate();
 
-    // respond to MSHR targets, if any
+        DPRINTF(Cache, "Sending a atomic %s for %x\n",
+                busPkt.cmdString(), busPkt.getAddr());
 
-    // First offset for critical word first calculations
-    int initial_offset = 0;
+        lat += memSidePort->sendAtomic(&busPkt);
 
-    if (mshr->hasTargets()) {
-        initial_offset = mshr->getTarget()->getOffset(blkSize);
+        DPRINTF(Cache, "Receive response: %s for addr %x in state %i\n",
+                busPkt.cmdString(), busPkt.getAddr(), old_state);
+
+        blk = handleFill(&busPkt, blk, writebacks);
+        bool status = satisfyCpuSideRequest(pkt, blk);
+        assert(status);
     }
 
-    while (mshr->hasTargets()) {
-        PacketPtr target = mshr->getTarget();
+    // We now have the block one way or another (hit or completed miss)
 
-        target->flags |= SATISFIED;
+    // Handle writebacks if needed
+    while (!writebacks.empty()){
+        PacketPtr wbPkt = writebacks.front();
+        memSidePort->sendAtomic(wbPkt);
+        writebacks.pop_front();
+        delete wbPkt;
+    }
 
-        // How many bytes pass the first request is this one
-        int transfer_offset = target->getOffset(blkSize) - initial_offset;
-        if (transfer_offset < 0) {
-            transfer_offset += blkSize;
-        }
+    if (pkt->needsResponse()) {
+        pkt->makeAtomicResponse();
+        pkt->result = Packet::Success;
+    }
 
-        // If critical word (no offset) return first word time
-        Tick completion_time = tags->getHitLatency() +
-            transfer_offset ? pkt->finishTime : pkt->firstWordTime;
+    return lat;
+}
 
-        if (target->cmd == MemCmd::InvalidateReq) {
-            //Mark the blk as invalid now, if it hasn't been already
-            if (blk) {
-                tags->invalidateBlk(blk);
-                blk = NULL;
-            }
 
-            //Also get rid of the invalidate
-            mshr->popTarget();
+template<class TagStore, class Coherence>
+void
+Cache<TagStore,Coherence>::functionalAccess(PacketPtr pkt,
+                                            CachePort *otherSidePort)
+{
+    Addr blk_addr = pkt->getAddr() & ~(blkSize - 1);
+    BlkType *blk = tags->findBlock(pkt->getAddr());
 
-            DPRINTF(Cache, "Popping off a Invalidate for addr %x\n",
-                    pkt->getAddr());
+    if (blk && pkt->checkFunctional(blk_addr, blkSize, blk->data)) {
+        // request satisfied from block
+        return;
+    }
 
-            continue;
-        }
+    // Need to check for outstanding misses and writes
 
-        if (blk && ((target->isWrite() || target->isReadWrite()) ?
-            blk->isWritable() : blk->isValid())) {
-            assert(target->isWrite() || target->isRead() || target->isReadWrite() );
-            assert(target->getOffset(blkSize) + target->getSize() <= blkSize);
-            if (target->isWrite()) {
-                if (blk->checkWrite(pkt->req)) {
-                    blk->status |= BlkDirty;
-                    std::memcpy(blk->data + target->getOffset(blkSize),
-                           target->getPtr<uint8_t>(), target->getSize());
-                }
-            } else if (target->isReadWrite()) {
-                cmpAndSwap(blk, target);
-            } else {
-                if (target->req->isLocked()) {
-                    blk->trackLoadLocked(target->req);
-                }
-                std::memcpy(target->getPtr<uint8_t>(),
-                       blk->data + target->getOffset(blkSize),
-                       target->getSize());
-            }
-        } else {
-            // Invalid access, need to do another request
-            // can occur if block is invalidated, or not correct
-            // permissions
-//            mshr->pkt = pkt;
-            break;
-        }
-        if (!target->req->isUncacheable()) {
-            missLatency[target->cmdToIndex()][0/*pkt->req->getThreadNum()*/] +=
-                completion_time - target->time;
+    // There can only be one matching outstanding miss.
+    MSHR *mshr = mshrQueue.findMatch(blk_addr);
+    if (mshr) {
+        MSHR::TargetList *targets = mshr->getTargetList();
+        MSHR::TargetList::iterator i = targets->begin();
+        MSHR::TargetList::iterator end = targets->end();
+        for (; i != end; ++i) {
+            PacketPtr targetPkt = i->pkt;
+            if (pkt->checkFunctional(targetPkt))
+                return;
         }
-        respond(target, completion_time);
-        mshr->popTarget();
     }
 
-    if (blk) {
-        // Need to write the data into the block
-        updateData(blk, writebacks, !adaptiveCompression || true);
+    // There can be many matching outstanding writes.
+    std::vector<MSHR*> writes;
+    writeBuffer.findMatches(blk_addr, writes);
+    for (int i = 0; i < writes.size(); ++i) {
+        MSHR *mshr = writes[i];
+        if (pkt->checkFunctional(mshr->addr, mshr->size, mshr->writeData))
+            return;
     }
 
-    return blk;
+    otherSidePort->checkAndSendFunctional(pkt);
 }
 
 
+/////////////////////////////////////////////////////
+//
+// Response handling: responses from the memory side
+//
+/////////////////////////////////////////////////////
+
 template<class TagStore, class Coherence>
 void
-Cache<TagStore,Coherence>::handleSnoop(BlkType *blk,
-                                       CacheBlk::State new_state,
-                                       PacketPtr &pkt)
+Cache<TagStore,Coherence>::handleResponse(PacketPtr pkt, Tick time)
 {
-    //Must have the block to supply
-    assert(blk);
-    // Can only supply data, and if it hasn't already been supllied
-    assert(pkt->isRead());
-    assert(!(pkt->flags & SATISFIED));
-    pkt->flags |= SATISFIED;
-    Addr offset = pkt->getOffset(blkSize);
-    assert(offset < blkSize);
-    assert(pkt->getSize() <= blkSize);
-    assert(offset + pkt->getSize() <=blkSize);
-    std::memcpy(pkt->getPtr<uint8_t>(), blk->data + offset, pkt->getSize());
-
-    handleSnoop(blk, new_state);
+    MSHR *mshr = dynamic_cast<MSHR*>(pkt->senderState);
+#ifndef NDEBUG
+    int num_targets = mshr->getNumTargets();
+#endif
+
+    bool unblock = false;
+    bool unblock_target = false;
+    BlockedCause cause = NUM_BLOCKED_CAUSES;
+
+    if (mshr->isCacheFill) {
+#if 0
+        mshr_miss_latency[mshr->originalCmd.toInt()][0/*pkt->req->getThreadNum()*/] +=
+            curTick - pkt->time;
+#endif
+        // targets were handled in the cache tags
+        if (mshr == noTargetMSHR) {
+            // we always clear at least one target
+            unblock_target = true;
+            cause = Blocked_NoTargets;
+            noTargetMSHR = NULL;
+        }
+
+        if (mshr->hasTargets()) {
+            // Didn't satisfy all the targets, need to resend
+            mshrQueue.markPending(mshr);
+            mshr->order = order++;
+            requestMemSideBus(Request_MSHR, time);
+        }
+        else {
+            unblock = mshrQueue.isFull();
+            mshrQueue.deallocate(mshr);
+            if (unblock) {
+                unblock = !mshrQueue.isFull();
+                cause = Blocked_NoMSHRs;
+            }
+        }
+    } else {
+        if (pkt->req->isUncacheable()) {
+            mshr_uncacheable_lat[pkt->cmd.toInt()][0/*pkt->req->getThreadNum()*/] +=
+                curTick - pkt->time;
+        }
+        if (mshr->hasTargets() && pkt->req->isUncacheable()) {
+            // Should only have 1 target if we had any
+            assert(num_targets == 1);
+            MSHR::Target *target = mshr->getTarget();
+            assert(target->cpuSide);
+            mshr->popTarget();
+            if (pkt->isRead()) {
+                target->pkt->setData(pkt->getPtr<uint8_t>());
+            }
+            cpuSidePort->respond(target->pkt, time);
+            assert(!mshr->hasTargets());
+        }
+        else if (mshr->hasTargets()) {
+            //Must be a no_allocate with possibly more than one target
+            assert(!mshr->isCacheFill);
+            while (mshr->hasTargets()) {
+                MSHR::Target *target = mshr->getTarget();
+                assert(target->isCpuSide());
+                mshr->popTarget();
+                if (pkt->isRead()) {
+                    target->pkt->setData(pkt->getPtr<uint8_t>());
+                }
+                cpuSidePort->respond(target->pkt, time);
+            }
+        }
+
+        if (pkt->isWrite()) {
+            // If the wrtie buffer is full, we might unblock now
+            unblock = writeBuffer.isFull();
+            writeBuffer.deallocate(mshr);
+            if (unblock) {
+                // Did we really unblock?
+                unblock = !writeBuffer.isFull();
+                cause = Blocked_NoWBBuffers;
+            }
+        } else {
+            unblock = mshrQueue.isFull();
+            mshrQueue.deallocate(mshr);
+            if (unblock) {
+                unblock = !mshrQueue.isFull();
+                cause = Blocked_NoMSHRs;
+            }
+        }
+    }
+    if (unblock || unblock_target) {
+        clearBlocked(cause);
+    }
 }
 
+
 template<class TagStore, class Coherence>
 void
-Cache<TagStore,Coherence>::handleSnoop(BlkType *blk,
-                                       CacheBlk::State new_state)
+Cache<TagStore,Coherence>::handleResponse(PacketPtr pkt)
 {
-    if (blk && blk->status != new_state) {
-        if ((new_state && BlkValid) == 0) {
-            tags->invalidateBlk(blk);
-        } else {
-            assert(new_state >= 0 && new_state < 128);
-            blk->status = new_state;
+    Tick time = curTick + hitLatency;
+    MSHR *mshr = dynamic_cast<MSHR*>(pkt->senderState);
+    assert(mshr);
+    if (pkt->result == Packet::Nacked) {
+        //pkt->reinitFromRequest();
+        warn("NACKs from devices not connected to the same bus "
+             "not implemented\n");
+        return;
+    }
+    assert(pkt->result != Packet::BadAddress);
+    assert(pkt->result == Packet::Success);
+    DPRINTF(Cache, "Handling reponse to %x\n", pkt->getAddr());
+
+    if (mshr->isCacheFill) {
+        DPRINTF(Cache, "Block for addr %x being updated in Cache\n",
+                pkt->getAddr());
+        BlkType *blk = tags->findBlock(pkt->getAddr());
+        PacketList writebacks;
+        blk = handleFill(pkt, blk, writebacks);
+        satisfyMSHR(mshr, pkt, blk);
+        // copy writebacks to write buffer
+        while (!writebacks.empty()) {
+            PacketPtr wbPkt = writebacks.front();
+            allocateBuffer(wbPkt, time, false, true);
+            writebacks.pop_front();
         }
     }
+    handleResponse(pkt, time);
 }
 
+
+
+
 template<class TagStore, class Coherence>
 PacketPtr
 Cache<TagStore,Coherence>::writebackBlk(BlkType *blk)
 {
-    assert(blk && blk->isValid() && blk->isModified());
-    int data_size = blkSize;
-    data_size = blk->size;
-    if (compressOnWriteback) {
-        // not already compressed
-        // need to compress to ship it
-        assert(data_size == blkSize);
-        uint8_t *tmp_data = new uint8_t[blkSize];
-        data_size = compressionAlg->compress(tmp_data,blk->data,
-                                      data_size);
-        delete [] tmp_data;
-    }
+    assert(blk && blk->isValid() && blk->isDirty());
 
-/*    PacketPtr writeback =
-        buildWritebackReq(tags->regenerateBlkAddr(blk->tag, blk->set),
-                          blk->asid, blkSize,
-                          blk->data, data_size);
-*/
+    writebacks[0/*pkt->req->getThreadNum()*/]++;
 
     Request *writebackReq =
         new Request(tags->regenerateBlkAddr(blk->tag, blk->set), blkSize, 0);
     PacketPtr writeback = new Packet(writebackReq, MemCmd::Writeback, -1);
     writeback->allocate();
-    std::memcpy(writeback->getPtr<uint8_t>(),blk->data,blkSize);
+    std::memcpy(writeback->getPtr<uint8_t>(), blk->data, blkSize);
 
     blk->status &= ~BlkDirty;
     return writeback;
 }
 
 
-template<class TagStore, class Coherence>
-bool
-Cache<TagStore,Coherence>::verifyData(BlkType *blk)
-{
-    bool retval;
-    // The data stored in the blk
-    uint8_t *blk_data = new uint8_t[blkSize];
-    tags->readData(blk, blk_data);
-    // Pointer for uncompressed data, assumed uncompressed
-    uint8_t *tmp_data = blk_data;
-    // The size of the data being stored, assumed uncompressed
-    int data_size = blkSize;
-
-    // If the block is compressed need to uncompress to access
-    if (blk->isCompressed()){
-        // Allocate new storage for the data
-        tmp_data = new uint8_t[blkSize];
-        data_size = compressionAlg->uncompress(tmp_data,blk_data, blk->size);
-        assert(data_size == blkSize);
-        // Don't need to keep blk_data around
-        delete [] blk_data;
-    } else {
-        assert(blkSize == blk->size);
-    }
-
-    retval = std::memcmp(tmp_data, blk->data, blkSize) == 0;
-    delete [] tmp_data;
-    return retval;
-}
-
-template<class TagStore, class Coherence>
-void
-Cache<TagStore,Coherence>::updateData(BlkType *blk, PacketList &writebacks,
-                                        bool compress_block)
-{
-    if (storeCompressed && compress_block) {
-        uint8_t *comp_data = new uint8_t[blkSize];
-        int new_size = compressionAlg->compress(comp_data, blk->data, blkSize);
-        if (new_size > (blkSize - tags->getSubBlockSize())){
-            // no benefit to storing it compressed
-            blk->status &= ~BlkCompressed;
-            tags->writeData(blk, blk->data, blkSize,
-                          writebacks);
-        } else {
-            // Store the data compressed
-            blk->status |= BlkCompressed;
-            tags->writeData(blk, comp_data, new_size,
-                          writebacks);
-        }
-        delete [] comp_data;
-    } else {
-        blk->status &= ~BlkCompressed;
-        tags->writeData(blk, blk->data, blkSize, writebacks);
-    }
-}
-
+// Note that the reason we return a list of writebacks rather than
+// inserting them directly in the write buffer is that this function
+// is called by both atomic and timing-mode accesses, and in atomic
+// mode we don't mess with the write buffer (we just perform the
+// writebacks atomically once the original request is complete).
 template<class TagStore, class Coherence>
 typename Cache<TagStore,Coherence>::BlkType*
-Cache<TagStore,Coherence>::doReplacement(BlkType *blk, PacketPtr &pkt,
-                                         CacheBlk::State new_state,
-                                         PacketList &writebacks)
+Cache<TagStore,Coherence>::handleFill(PacketPtr pkt, BlkType *blk,
+                                      PacketList &writebacks)
 {
+    Addr addr = pkt->getAddr();
+
     if (blk == NULL) {
+
         // need to do a replacement
-        BlkList compress_list;
-        blk = tags->findReplacement(pkt, writebacks, compress_list);
-        while (adaptiveCompression && !compress_list.empty()) {
-            updateData(compress_list.front(), writebacks, true);
-            compress_list.pop_front();
-        }
+        blk = tags->findReplacement(addr, writebacks);
         if (blk->isValid()) {
             DPRINTF(Cache, "replacement: replacing %x with %x: %s\n",
-                    tags->regenerateBlkAddr(blk->tag,blk->set), pkt->getAddr(),
-                    (blk->isModified()) ? "writeback" : "clean");
+                    tags->regenerateBlkAddr(blk->tag, blk->set), addr,
+                    blk->isDirty() ? "writeback" : "clean");
 
-            if (blk->isModified()) {
-                // Need to write the data back
+            if (blk->isDirty()) {
+                // Save writeback packet for handling by caller
                 writebacks.push_back(writebackBlk(blk));
             }
         }
-        blk->tag = tags->extractTag(pkt->getAddr(), blk);
+
+        blk->tag = tags->extractTag(addr);
+        blk->status = coherence->getNewState(pkt);
+        assert(pkt->isRead());
     } else {
-        // must be a status change
-        // assert(blk->status != new_state);
-        if (blk->status == new_state) warn("Changing state to same value\n");
+        // existing block... probably an upgrade
+        assert(blk->tag == tags->extractTag(addr));
+        // either we're getting new data or the block should already be valid
+        assert(pkt->isRead() || blk->isValid());
+        CacheBlk::State old_state = blk->status;
+        blk->status = coherence->getNewState(pkt, old_state);
+        if (blk->status != old_state)
+            DPRINTF(Cache, "Block addr %x moving from state %i to %i\n",
+                    addr, old_state, blk->status);
+        else
+            warn("Changing state to same value\n");
     }
 
-    blk->status = new_state;
+    // if we got new data, copy it in
+    if (pkt->isRead()) {
+        std::memcpy(blk->data, pkt->getPtr<uint8_t>(), blkSize);
+    }
+
+    blk->whenReady = pkt->finishTime;
+
     return blk;
 }
 
 
 template<class TagStore, class Coherence>
 bool
-Cache<TagStore,Coherence>::access(PacketPtr &pkt)
+Cache<TagStore,Coherence>::satisfyCpuSideRequest(PacketPtr pkt, BlkType *blk)
 {
-//@todo Add back in MemDebug Calls
-//    MemDebug::cacheAccess(pkt);
-    BlkType *blk = NULL;
-    PacketList writebacks;
-    int size = blkSize;
-    int lat = hitLatency;
-    if (prefetchAccess) {
-        //We are determining prefetches on access stream, call prefetcher
-        prefetcher->handleMiss(pkt, curTick);
-    }
-
-    Addr blk_addr = pkt->getAddr() & ~(Addr(blkSize-1));
-
-    if (!pkt->req->isUncacheable()) {
-        if (!missQueue->findMSHR(blk_addr)) {
-            blk = handleAccess(pkt, lat, writebacks);
-        }
-    } else {
-        size = pkt->getSize();
-    }
-    // If this is a block size write/hint (WH64) allocate the block here
-    // if the coherence protocol allows it.
-    /** @todo make the fast write alloc (wh64) work with coherence. */
-    /** @todo Do we want to do fast writes for writebacks as well? */
-    if (!blk && pkt->getSize() >= blkSize && coherence->allowFastWrites() &&
-        (pkt->cmd == MemCmd::WriteReq
-         || pkt->cmd == MemCmd::WriteInvalidateReq) ) {
-        // not outstanding misses, can do this
-        MSHR* outstanding_miss = missQueue->findMSHR(pkt->getAddr());
-        if (pkt->cmd == MemCmd::WriteInvalidateReq || !outstanding_miss) {
-            if (outstanding_miss) {
-                warn("WriteInv doing a fastallocate"
-                     "with an outstanding miss to the same address\n");
+    if (blk && (pkt->needsExclusive() ? blk->isWritable() : blk->isValid())) {
+        assert(pkt->isWrite() || pkt->isReadWrite() || pkt->isRead());
+        assert(pkt->getOffset(blkSize) + pkt->getSize() <= blkSize);
+
+        if (pkt->isWrite()) {
+            if (blk->checkWrite(pkt)) {
+                blk->status |= BlkDirty;
+                pkt->writeDataToBlock(blk->data, blkSize);
             }
-            blk = handleFill(NULL, pkt, BlkValid | BlkWritable,
-                                   writebacks);
-            ++fastWrites;
+        } else if (pkt->isReadWrite()) {
+            cmpAndSwap(blk, pkt);
+        } else {
+            if (pkt->isLocked()) {
+                blk->trackLoadLocked(pkt);
+            }
+            pkt->setDataFromBlock(blk->data, blkSize);
         }
+
+        return true;
+    } else {
+        return false;
     }
-    while (!writebacks.empty()) {
-        PacketPtr wbPkt = writebacks.front();
-        missQueue->doWriteback(wbPkt);
-        writebacks.pop_front();
-        delete wbPkt;
-    }
+}
+
+
+template<class TagStore, class Coherence>
+bool
+Cache<TagStore,Coherence>::satisfyTarget(MSHR::Target *target, BlkType *blk)
+{
+    assert(target != NULL);
+    assert(target->isCpuSide());
+    return satisfyCpuSideRequest(target->pkt, blk);
+}
+
+template<class TagStore, class Coherence>
+void
+Cache<TagStore,Coherence>::satisfyMSHR(MSHR *mshr, PacketPtr pkt,
+                                       BlkType *blk)
+{
+    // respond to MSHR targets, if any
 
-    DPRINTF(Cache, "%s %x %s\n", pkt->cmdString(), pkt->getAddr(),
-            (blk) ? "hit" : "miss");
+    // First offset for critical word first calculations
+    int initial_offset = 0;
 
-    if (blk) {
-        // Hit
-        hits[pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/]++;
-        // clear dirty bit if write through
-        respond(pkt, curTick+lat);
-        return true;
+    if (mshr->hasTargets()) {
+        initial_offset = mshr->getTarget()->pkt->getOffset(blkSize);
     }
 
-    // Miss
-    if (!pkt->req->isUncacheable()) {
-        misses[pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/]++;
-        /** @todo Move miss count code into BaseCache */
-        if (missCount) {
-            --missCount;
-            if (missCount == 0)
-                exitSimLoop("A cache reached the maximum miss count");
-        }
-    }
+    while (mshr->hasTargets()) {
+        MSHR::Target *target = mshr->getTarget();
 
-    if (pkt->flags & SATISFIED) {
-        // happens when a store conditional fails because it missed
-        // the cache completely
-        respond(pkt, curTick+lat);
-    } else {
-        missQueue->handleMiss(pkt, size, curTick + hitLatency);
-    }
+        if (!satisfyTarget(target, blk)) {
+            // Invalid access, need to do another request
+            // can occur if block is invalidated, or not correct
+            // permissions
+            break;
+        }
 
-    if (!pkt->needsResponse()) {
-        //Need to clean up the packet on a writeback miss, but leave the request
-        //for the next level.
-        delete pkt;
-    }
 
-    return true;
-}
+        // How many bytes pass the first request is this one
+        int transfer_offset = target->pkt->getOffset(blkSize) - initial_offset;
+        if (transfer_offset < 0) {
+            transfer_offset += blkSize;
+        }
 
+        // If critical word (no offset) return first word time
+        Tick completion_time = tags->getHitLatency() +
+            transfer_offset ? pkt->finishTime : pkt->firstWordTime;
 
-template<class TagStore, class Coherence>
-PacketPtr
-Cache<TagStore,Coherence>::getPacket()
-{
-    assert(missQueue->havePending());
-    PacketPtr pkt = missQueue->getPacket();
-    if (pkt) {
-        if (!pkt->req->isUncacheable()) {
-            if (pkt->cmd == MemCmd::HardPFReq)
-                misses[MemCmd::HardPFReq][0/*pkt->req->getThreadNum()*/]++;
-            BlkType *blk = tags->findBlock(pkt->getAddr());
-            MemCmd cmd =
-                coherence->getBusCmd(pkt->cmd, (blk) ? blk->status : 0);
-            missQueue->setBusCmd(pkt, cmd);
+        if (!target->pkt->req->isUncacheable()) {
+            missLatency[target->pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/] +=
+                completion_time - target->time;
         }
+        target->pkt->makeTimingResponse();
+        cpuSidePort->respond(target->pkt, completion_time);
+        mshr->popTarget();
     }
-
-    assert(!isMemSideBusRequested() || missQueue->havePending());
-    assert(!pkt || pkt->time <= curTick);
-    SIGNAL_NACK_HACK = false;
-    return pkt;
 }
 
+
+/////////////////////////////////////////////////////
+//
+// Snoop path: requests coming in from the memory side
+//
+/////////////////////////////////////////////////////
+
 template<class TagStore, class Coherence>
 void
-Cache<TagStore,Coherence>::sendResult(PacketPtr &pkt, MSHR* mshr,
-                                                bool success)
+Cache<TagStore,Coherence>::doTimingSupplyResponse(PacketPtr req_pkt,
+                                                  uint8_t *blk_data)
 {
-    if (success && !(SIGNAL_NACK_HACK)) {
-        //Remember if it was an upgrade because writeback MSHR's are removed
-        //in Mark in Service
-        bool upgrade = (mshr->pkt && mshr->pkt->cmd == MemCmd::UpgradeReq);
-
-        missQueue->markInService(mshr->pkt, mshr);
-
-        //Temp Hack for UPGRADES
-        if (upgrade) {
-            assert(pkt);  //Upgrades need to be fixed
-            pkt->flags &= ~CACHE_LINE_FILL;
-            BlkType *blk = tags->findBlock(pkt->getAddr());
-            CacheBlk::State old_state = (blk) ? blk->status : 0;
-            CacheBlk::State new_state = coherence->getNewState(pkt,old_state);
-            if (old_state != new_state)
-                DPRINTF(Cache, "Block for blk addr %x moving from state "
-                        "%i to %i\n", pkt->getAddr(), old_state, new_state);
-            //Set the state on the upgrade
-            std::memcpy(pkt->getPtr<uint8_t>(), blk->data, blkSize);
-            PacketList writebacks;
-            handleFill(blk, mshr, new_state, writebacks, pkt);
-            assert(writebacks.empty());
-            missQueue->handleResponse(pkt, curTick + hitLatency);
-        }
-    } else if (pkt && !pkt->req->isUncacheable()) {
-        pkt->flags &= ~NACKED_LINE;
-        SIGNAL_NACK_HACK = false;
-        pkt->flags &= ~SATISFIED;
-
-//Rmove copy from mshr
-        delete mshr->pkt;
-        mshr->pkt = pkt;
-
-        missQueue->restoreOrigCmd(pkt);
-    }
+    // timing-mode snoop responses require a new packet
+    PacketPtr pkt = new Packet(req_pkt);
+    pkt->allocate();
+    pkt->makeTimingResponse();
+    pkt->setDataFromBlock(blk_data, blkSize);
+    memSidePort->respond(pkt, curTick + hitLatency);
 }
 
 template<class TagStore, class Coherence>
 void
-Cache<TagStore,Coherence>::handleResponse(PacketPtr &pkt)
+Cache<TagStore,Coherence>::handleSnoop(PacketPtr pkt, BlkType *blk,
+                                       bool is_timing)
 {
-    BlkType *blk = NULL;
-    if (pkt->senderState) {
-        //Delete temp copy in MSHR, restore it.
-        delete ((MSHR*)pkt->senderState)->pkt;
-        ((MSHR*)pkt->senderState)->pkt = pkt;
-        if (pkt->result == Packet::Nacked) {
-            //pkt->reinitFromRequest();
-            warn("NACKs from devices not connected to the same bus "
-                 "not implemented\n");
-            return;
-        }
-        if (pkt->result == Packet::BadAddress) {
-            //Make the response a Bad address and send it
+    if (!blk || !blk->isValid()) {
+        return;
+    }
+
+    // we may end up modifying both the block state and the packet (if
+    // we respond in atomic mode), so just figure out what to do now
+    // and then do it later
+    bool supply = blk->isDirty() && pkt->isRead();
+    bool invalidate = pkt->isInvalidate();
+
+    if (pkt->isRead() && !pkt->isInvalidate()) {
+        assert(!pkt->needsExclusive());
+        pkt->assertShared();
+        int bits_to_clear = BlkWritable;
+        const bool haveOwnershipState = true; // for now
+        if (!haveOwnershipState) {
+            // if we don't support pure ownership (dirty && !writable),
+            // have to clear dirty bit here, assume memory snarfs data
+            // on cache-to-cache xfer
+            bits_to_clear |= BlkDirty;
         }
-//     MemDebug::cacheResponse(pkt);
-        DPRINTF(Cache, "Handling reponse to %x\n", pkt->getAddr());
-
-        if (pkt->isCacheFill() && !pkt->isNoAllocate()) {
-            DPRINTF(Cache, "Block for addr %x being updated in Cache\n",
-                    pkt->getAddr());
-            blk = tags->findBlock(pkt->getAddr());
-            CacheBlk::State old_state = (blk) ? blk->status : 0;
-            PacketList writebacks;
-            CacheBlk::State new_state = coherence->getNewState(pkt,old_state);
-            if (old_state != new_state)
-                DPRINTF(Cache, "Block for blk addr %x moving from "
-                        "state %i to %i\n",
-                        pkt->getAddr(),
-                        old_state, new_state);
-            blk = handleFill(blk, (MSHR*)pkt->senderState,
-                                   new_state, writebacks, pkt);
-            while (!writebacks.empty()) {
-                PacketPtr wbPkt = writebacks.front();
-                missQueue->doWriteback(wbPkt);
-                writebacks.pop_front();
-                delete wbPkt;
-            }
+        blk->status &= ~bits_to_clear;
+    }
+
+    if (supply) {
+        pkt->assertMemInhibit();
+        if (is_timing) {
+            doTimingSupplyResponse(pkt, blk->data);
+        } else {
+            pkt->makeAtomicResponse();
+            pkt->setDataFromBlock(blk->data, blkSize);
         }
-        missQueue->handleResponse(pkt, curTick + hitLatency);
     }
+
+    // Do this last in case it deallocates block data or something
+    // like that
+    if (invalidate) {
+        tags->invalidateBlk(blk);
+    }
+
+    DPRINTF(Cache, "snooped a %s request for addr %x, %snew state is %i\n",
+            pkt->cmdString(), blockAlign(pkt->getAddr()),
+            supply ? "supplying data, " : "", blk->status);
 }
 
 
 template<class TagStore, class Coherence>
 void
-Cache<TagStore,Coherence>::snoop(PacketPtr &pkt)
+Cache<TagStore,Coherence>::snoopTiming(PacketPtr pkt)
 {
     if (pkt->req->isUncacheable()) {
         //Can't get a hit on an uncacheable address
@@ -794,351 +923,190 @@ Cache<TagStore,Coherence>::snoop(PacketPtr &pkt)
         return;
     }
 
-    ///// PROPAGATE SNOOP UPWARD HERE
+    BlkType *blk = tags->findBlock(pkt->getAddr());
 
     Addr blk_addr = pkt->getAddr() & ~(Addr(blkSize-1));
-    BlkType *blk = tags->findBlock(pkt->getAddr());
-    MSHR *mshr = missQueue->findMSHR(blk_addr);
-    if (coherence->hasProtocol() || pkt->isInvalidate()) {
-        //@todo Move this into handle bus req
-        //If we find an mshr, and it is in service, we need to NACK or
-        //invalidate
-        if (mshr) {
-            if (mshr->inService) {
-                if ((mshr->pkt->isInvalidate() || !mshr->pkt->isCacheFill())
-                    && (pkt->cmd != MemCmd::InvalidateReq
-                        && pkt->cmd != MemCmd::WriteInvalidateReq)) {
-                    //If the outstanding request was an invalidate
-                    //(upgrade,readex,..)  Then we need to ACK the request
-                    //until we get the data Also NACK if the outstanding
-                    //request is not a cachefill (writeback)
-                    assert(!(pkt->flags & SATISFIED));
-                    pkt->flags |= SATISFIED;
-                    pkt->flags |= NACKED_LINE;
-                    SIGNAL_NACK_HACK = true;
-                    ///@todo NACK's from other levels
-                    //warn("NACKs from devices not connected to the same bus "
-                    //"not implemented\n");
-                    //respondToSnoop(pkt, curTick + hitLatency);
-                    return;
-                }
-                else {
-                    //The supplier will be someone else, because we are
-                    //waiting for the data.  This should cause this cache to
-                    //be forced to go to the shared state, not the exclusive
-                    //even though the shared line won't be asserted.  But for
-                    //now we will just invlidate ourselves and allow the other
-                    //cache to go into the exclusive state.  @todo Make it so
-                    //a read to a pending read doesn't invalidate.  @todo Make
-                    //it so that a read to a pending read can't be exclusive
-                    //now.
-
-                    //Set the address so find match works
-                    //panic("Don't have invalidates yet\n");
-                    invalidatePkt->addrOverride(pkt->getAddr());
-
-                    //Append the invalidate on
-                    missQueue->addTarget(mshr,invalidatePkt);
-                    DPRINTF(Cache, "Appending Invalidate to addr: %x\n",
-                            pkt->getAddr());
-                    return;
+    MSHR *mshr = mshrQueue.findMatch(blk_addr);
+    // better not be snooping a request that conflicts with something
+    // we have outstanding...
+    assert(!mshr || !mshr->inService);
+
+    //We also need to check the writeback buffers and handle those
+    std::vector<MSHR *> writebacks;
+    if (writeBuffer.findMatches(blk_addr, writebacks)) {
+        DPRINTF(Cache, "Snoop hit in writeback to addr: %x\n",
+                pkt->getAddr());
+
+        //Look through writebacks for any non-uncachable writes, use that
+        for (int i=0; i<writebacks.size(); i++) {
+            mshr = writebacks[i];
+            assert(!mshr->isUncacheable());
+
+            if (pkt->isRead()) {
+                pkt->assertMemInhibit();
+                if (!pkt->needsExclusive()) {
+                    pkt->assertShared();
+                } else {
+                    // if we're not asserting the shared line, we need to
+                    // invalidate our copy.  we'll do that below as long as
+                    // the packet's invalidate flag is set...
+                    assert(pkt->isInvalidate());
                 }
+                doTimingSupplyResponse(pkt, mshr->writeData);
             }
-        }
-        //We also need to check the writeback buffers and handle those
-        std::vector<MSHR *> writebacks;
-        if (missQueue->findWrites(blk_addr, writebacks)) {
-            DPRINTF(Cache, "Snoop hit in writeback to addr: %x\n",
-                    pkt->getAddr());
-
-            //Look through writebacks for any non-uncachable writes, use that
-            for (int i=0; i<writebacks.size(); i++) {
-                mshr = writebacks[i];
-
-                if (!mshr->pkt->req->isUncacheable()) {
-                    if (pkt->isRead()) {
-                        //Only Upgrades don't get here
-                        //Supply the data
-                        assert(!(pkt->flags & SATISFIED));
-                        pkt->flags |= SATISFIED;
-
-                        //If we are in an exclusive protocol, make it ask again
-                        //to get write permissions (upgrade), signal shared
-                        pkt->flags |= SHARED_LINE;
-
-                        assert(pkt->isRead());
-                        Addr offset = pkt->getAddr() & (blkSize - 1);
-                        assert(offset < blkSize);
-                        assert(pkt->getSize() <= blkSize);
-                        assert(offset + pkt->getSize() <=blkSize);
-                        std::memcpy(pkt->getPtr<uint8_t>(), mshr->pkt->getPtr<uint8_t>() + offset, pkt->getSize());
-
-                        respondToSnoop(pkt, curTick + hitLatency);
-                    }
-
-                    if (pkt->isInvalidate()) {
-                        //This must be an upgrade or other cache will take
-                        //ownership
-                        missQueue->markInService(mshr->pkt, mshr);
-                    }
-                    return;
-                }
+
+            if (pkt->isInvalidate()) {
+                // Invalidation trumps our writeback... discard here
+                assert(0);
+                markInService(mshr);
             }
+            return;
         }
     }
-    CacheBlk::State new_state;
-    bool satisfy = coherence->handleBusRequest(pkt,blk,mshr, new_state);
-
-    if (blk && mshr && !mshr->inService && new_state == 0) {
-            //There was a outstanding write to a shared block, not need ReadEx
-            //not update, so change No Allocate param in MSHR
-            mshr->pkt->flags &= ~NO_ALLOCATE;
-    }
-
-    if (satisfy) {
-        DPRINTF(Cache, "Cache snooped a %s request for addr %x and "
-                "now supplying data, new state is %i\n",
-                pkt->cmdString(), blk_addr, new_state);
-
-        handleSnoop(blk, new_state, pkt);
-        respondToSnoop(pkt, curTick + hitLatency);
-        return;
-    }
-    if (blk)
-        DPRINTF(Cache, "Cache snooped a %s request for addr %x, "
-                "new state is %i\n", pkt->cmdString(), blk_addr, new_state);
 
-    handleSnoop(blk, new_state);
+    handleSnoop(pkt, blk, true);
 }
 
+
 template<class TagStore, class Coherence>
-void
-Cache<TagStore,Coherence>::snoopResponse(PacketPtr &pkt)
+Tick
+Cache<TagStore,Coherence>::snoopAtomic(PacketPtr pkt)
 {
-    //Need to handle the response, if NACKED
-    if (pkt->flags & NACKED_LINE) {
-        //Need to mark it as not in service, and retry for bus
-        assert(0); //Yeah, we saw a NACK come through
-
-        //For now this should never get called, we return false when we see a
-        //NACK instead, by doing this we allow the bus_blocked mechanism to
-        //handle the retry For now it retrys in just 2 cycles, need to figure
-        //out how to change that Eventually we will want to also have success
-        //come in as a parameter Need to make sure that we handle the
-        //functionality that happens on successufl return of the sendAddr
-        //function
+    if (pkt->req->isUncacheable()) {
+        // Can't get a hit on an uncacheable address
+        // Revisit this for multi level coherence
+        return hitLatency;
     }
+
+    BlkType *blk = tags->findBlock(pkt->getAddr());
+    handleSnoop(pkt, blk, false);
+    return hitLatency;
 }
 
 
-/**
- * @todo Fix to not assume write allocate
- */
 template<class TagStore, class Coherence>
-Tick
-Cache<TagStore,Coherence>::probe(PacketPtr &pkt, bool update,
-                                           CachePort* otherSidePort)
+MSHR *
+Cache<TagStore,Coherence>::getNextMSHR()
 {
-//    MemDebug::cacheProbe(pkt);
-    if (!pkt->req->isUncacheable()) {
-        if (pkt->isInvalidate() && !pkt->isRead() && !pkt->isWrite()) {
-            //Upgrade or Invalidate, satisfy it, don't forward
-            DPRINTF(Cache, "%s %x ?\n", pkt->cmdString(), pkt->getAddr());
-            pkt->flags |= SATISFIED;
-            return 0;
-        }
-    }
+    // Check both MSHR queue and write buffer for potential requests
+    MSHR *miss_mshr  = mshrQueue.getNextMSHR();
+    MSHR *write_mshr = writeBuffer.getNextMSHR();
 
-    if (!update && (otherSidePort == cpuSidePort)) {
-        // Still need to change data in all locations.
-        otherSidePort->checkAndSendFunctional(pkt);
-        if (pkt->isRead() && pkt->result == Packet::Success)
-            return 0;
+    // Now figure out which one to send... some cases are easy
+    if (miss_mshr && !write_mshr) {
+        return miss_mshr;
+    }
+    if (write_mshr && !miss_mshr) {
+        return write_mshr;
     }
 
-    PacketList writebacks;
-    int lat;
-
-    BlkType *blk = handleAccess(pkt, lat, writebacks, update);
-
-    DPRINTF(Cache, "%s %x %s\n", pkt->cmdString(),
-            pkt->getAddr(), (blk) ? "hit" : "miss");
-
-
-    // Need to check for outstanding misses and writes
-    Addr blk_addr = pkt->getAddr() & ~(blkSize - 1);
-
-    // There can only be one matching outstanding miss.
-    MSHR* mshr = missQueue->findMSHR(blk_addr);
-
-    // There can be many matching outstanding writes.
-    std::vector<MSHR*> writes;
-    missQueue->findWrites(blk_addr, writes);
-
-    if (!update) {
-        bool notDone = !(pkt->flags & SATISFIED); //Hit in cache (was a block)
-        // Check for data in MSHR and writebuffer.
-        if (mshr) {
-            MSHR::TargetList *targets = mshr->getTargetList();
-            MSHR::TargetList::iterator i = targets->begin();
-            MSHR::TargetList::iterator end = targets->end();
-            for (; i != end && notDone; ++i) {
-                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 MSHR\n",
-                            pkt->cmdString(), blk_addr);
-                    notDone = fixPacket(pkt, target);
-                }
-            }
-        }
-        for (int i = 0; i < writes.size() && notDone; ++i) {
-            PacketPtr write = writes[i]->pkt;
-            if (write->intersect(pkt)) {
-                DPRINTF(Cache, "Functional %s access to blk_addr %x intersects a writeback\n",
-                        pkt->cmdString(), blk_addr);
-                notDone = fixPacket(pkt, write);
-            }
-        }
-        if (notDone && otherSidePort == memSidePort) {
-            otherSidePort->checkAndSendFunctional(pkt);
-            assert(pkt->result == Packet::Success);
-        }
-        return 0;
-    } else if (!blk && !(pkt->flags & SATISFIED)) {
-        // update the cache state and statistics
-        if (mshr || !writes.empty()){
-            // Can't handle it, return request unsatisfied.
-            panic("Atomic access ran into outstanding MSHR's or WB's!");
-        }
-        if (!pkt->req->isUncacheable() /*Uncacheables just go through*/
-            && (pkt->cmd != MemCmd::Writeback)/*Writebacks on miss fall through*/) {
-                // Fetch the cache block to fill
-            BlkType *blk = tags->findBlock(pkt->getAddr());
-            MemCmd temp_cmd =
-                coherence->getBusCmd(pkt->cmd, (blk) ? blk->status : 0);
-
-            PacketPtr busPkt = new Packet(pkt->req,temp_cmd, -1, blkSize);
-
-            busPkt->allocate();
-
-            busPkt->time = curTick;
-
-            DPRINTF(Cache, "Sending a atomic %s for %x\n",
-                    busPkt->cmdString(), busPkt->getAddr());
-
-            lat = memSidePort->sendAtomic(busPkt);
-
-            //Be sure to flip the response to a request for coherence
-            if (busPkt->needsResponse()) {
-                busPkt->makeAtomicResponse();
+    if (miss_mshr && write_mshr) {
+        // We have one of each... normally we favor the miss request
+        // unless the write buffer is full
+        if (writeBuffer.isFull() && writeBuffer.inServiceEntries == 0) {
+            // Write buffer is full, so we'd like to issue a write;
+            // need to search MSHR queue for conflicting earlier miss.
+            MSHR *conflict_mshr =
+                mshrQueue.findPending(write_mshr->addr, write_mshr->size);
+
+            if (conflict_mshr && conflict_mshr->order < write_mshr->order) {
+                // Service misses in order until conflict is cleared.
+                return conflict_mshr;
             }
 
-/*             if (!(busPkt->flags & SATISFIED)) {
-// blocked at a higher level, just return
-return 0;
-}
-
-*/             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 addr %x in state %i\n",
-                    busPkt->cmdString(), busPkt->getAddr(), old_state);
-            if (old_state != new_state)
-                DPRINTF(Cache, "Block for blk addr %x moving from state "
-                        "%i to %i\n", busPkt->getAddr(), old_state, new_state);
-
-            handleFill(blk, busPkt, new_state, writebacks, pkt);
-            //Free the packet
-            delete busPkt;
-
-            // Handle writebacks if needed
-            while (!writebacks.empty()){
-                PacketPtr wbPkt = writebacks.front();
-                memSidePort->sendAtomic(wbPkt);
-                writebacks.pop_front();
-                delete wbPkt;
-            }
-                return lat + hitLatency;
-        } else {
-            return memSidePort->sendAtomic(pkt);
+            // No conflicts; issue write
+            return write_mshr;
         }
-    } else {
-        if (blk) {
-            // There was a cache hit.
-            // Handle writebacks if needed
-            while (!writebacks.empty()){
-                PacketPtr wbPkt = writebacks.front();
-                memSidePort->sendAtomic(wbPkt);
-                writebacks.pop_front();
-                delete wbPkt;
-            }
 
-            hits[pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/]++;
+        // Write buffer isn't full, but need to check it for
+        // conflicting earlier writeback
+        MSHR *conflict_mshr =
+            writeBuffer.findPending(miss_mshr->addr, miss_mshr->size);
+        if (conflict_mshr) {
+            // not sure why we don't check order here... it was in the
+            // original code but commented out.
+
+            // The only way this happens is if we are
+            // doing a write and we didn't have permissions
+            // then subsequently saw a writeback (owned got evicted)
+            // We need to make sure to perform the writeback first
+            // To preserve the dirty data, then we can issue the write
+
+            // should we return write_mshr here instead?  I.e. do we
+            // have to flush writes in order?  I don't think so... not
+            // for Alpha anyway.  Maybe for x86?
+            return conflict_mshr;
         }
 
-        return hitLatency;
+        // No conclifts; issue read
+        return miss_mshr;
+    }
+
+    // fall through... no pending requests.  Try a prefetch.
+    assert(!miss_mshr && !write_mshr);
+    if (!mshrQueue.isFull()) {
+        // If we have a miss queue slot, we can try a prefetch
+        PacketPtr pkt = prefetcher->getPacket();
+        if (pkt) {
+            // Update statistic on number of prefetches issued
+            // (hwpf_mshr_misses)
+            mshr_misses[pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/]++;
+            // Don't request bus, since we already have it
+            return allocateBuffer(pkt, curTick, true, false);
+        }
     }
 
-    return 0;
+    return NULL;
 }
 
+
 template<class TagStore, class Coherence>
-Tick
-Cache<TagStore,Coherence>::snoopProbe(PacketPtr &pkt)
+PacketPtr
+Cache<TagStore,Coherence>::getPacket()
 {
-    ///// PROPAGATE SNOOP UPWARD HERE
+    MSHR *mshr = getNextMSHR();
 
-    Addr blk_addr = pkt->getAddr() & ~(Addr(blkSize-1));
-    BlkType *blk = tags->findBlock(pkt->getAddr());
-    MSHR *mshr = missQueue->findMSHR(blk_addr);
-    CacheBlk::State new_state = 0;
-    bool satisfy = coherence->handleBusRequest(pkt,blk,mshr, new_state);
-    if (satisfy) {
-        DPRINTF(Cache, "Cache snooped a %s request for addr %x and "
-                "now supplying data, new state is %i\n",
-                pkt->cmdString(), blk_addr, new_state);
-
-            handleSnoop(blk, new_state, pkt);
-            return hitLatency;
+    if (mshr == NULL) {
+        return NULL;
     }
-    if (blk)
-        DPRINTF(Cache, "Cache snooped a %s request for addr %x, "
-                "new state is %i\n",
-                    pkt->cmdString(), blk_addr, new_state);
-    handleSnoop(blk, new_state);
-    return 0;
-}
 
-template<class TagStore, class Coherence>
-Port *
-Cache<TagStore,Coherence>::getPort(const std::string &if_name, int idx)
-{
-    if (if_name == "" || if_name == "cpu_side") {
-        return cpuSidePort;
-    } else if (if_name == "mem_side") {
-        return memSidePort;
-    } else if (if_name == "functional") {
-        return new CpuSidePort(name() + "-cpu_side_funcport", this);
+    BlkType *blk = tags->findBlock(mshr->addr);
+
+    // use request from 1st target
+    MSHR::Target *tgt1 = mshr->getTarget();
+    PacketPtr tgt1_pkt = tgt1->pkt;
+    PacketPtr pkt;
+
+    if (mshr->isCacheFill) {
+        MemCmd cmd;
+        if (blk && blk->isValid()) {
+            // only reason to be here is that blk is shared
+            // (read-only) and we need exclusive
+            assert(mshr->needsExclusive && !blk->isWritable());
+            cmd = MemCmd::UpgradeReq;
+        } else {
+            // block is invalid
+            cmd = mshr->needsExclusive ? MemCmd::ReadExReq : MemCmd::ReadReq;
+        }
+        pkt = new Packet(tgt1_pkt->req, cmd, Packet::Broadcast);
     } else {
-        panic("Port name %s unrecognized\n", if_name);
+        assert(blk == NULL);
+        assert(mshr->getNumTargets() == 1);
+        pkt = new Packet(tgt1_pkt->req, tgt1_pkt->cmd, Packet::Broadcast);
     }
-}
-
-template<class TagStore, class Coherence>
-void
-Cache<TagStore,Coherence>::deletePortRefs(Port *p)
-{
-    if (cpuSidePort == p || memSidePort == p)
-        panic("Can only delete functional ports\n");
 
-    delete p;
+    pkt->senderState = mshr;
+    pkt->allocate();
+    return pkt;
 }
 
 
+///////////////
+//
+// CpuSidePort
+//
+///////////////
+
 template<class TagStore, class Coherence>
 void
 Cache<TagStore,Coherence>::CpuSidePort::
@@ -1155,131 +1123,57 @@ template<class TagStore, class Coherence>
 bool
 Cache<TagStore,Coherence>::CpuSidePort::recvTiming(PacketPtr pkt)
 {
-    assert(pkt->result != Packet::Nacked);
-
-    if (!pkt->req->isUncacheable()
-        && pkt->isInvalidate()
-        && !pkt->isRead() && !pkt->isWrite()) {
-        //Upgrade or Invalidate
-        //Look into what happens if two slave caches on bus
-        DPRINTF(Cache, "%s %x ?\n", pkt->cmdString(), pkt->getAddr());
-
-        assert(!(pkt->flags & SATISFIED));
-        pkt->flags |= SATISFIED;
-        //Invalidates/Upgrades need no response if they get the bus
-        return true;
-    }
-
-    if (pkt->isRequest() && blocked)
-    {
+    if (pkt->isRequest() && blocked) {
         DPRINTF(Cache,"Scheduling a retry while blocked\n");
         mustSendRetry = true;
         return false;
     }
 
-    if (pkt->isWrite() && (pkt->req->isLocked())) {
-        pkt->req->setExtraData(1);
-    }
-    myCache()->access(pkt);
+    myCache()->timingAccess(pkt);
     return true;
 }
 
 
 template<class TagStore, class Coherence>
-void
-Cache<TagStore,Coherence>::CpuSidePort::recvRetry()
-{
-    recvRetryCommon();
-}
-
-
-template<class TagStore, class Coherence>
-void
-Cache<TagStore,Coherence>::CpuSidePort::processRequestEvent()
+Tick
+Cache<TagStore,Coherence>::CpuSidePort::recvAtomic(PacketPtr pkt)
 {
-    if (waitingOnRetry)
-        return;
-    //We have some responses to drain first
-    if (!drainList.empty()) {
-        if (!drainResponse()) {
-            // more responses to drain... re-request bus
-            scheduleRequestEvent(curTick + 1);
-        }
-    }
+    return myCache()->atomicAccess(pkt);
 }
 
 
 template<class TagStore, class Coherence>
 void
-Cache<TagStore,Coherence>::CpuSidePort::processResponseEvent()
+Cache<TagStore,Coherence>::CpuSidePort::recvFunctional(PacketPtr pkt)
 {
-    assert(transmitList.size());
-    assert(transmitList.front().first <= curTick);
-    PacketPtr pkt = transmitList.front().second;
-    transmitList.pop_front();
-    if (!transmitList.empty()) {
-        Tick time = transmitList.front().first;
-        responseEvent->schedule(time <= curTick ? curTick+1 : time);
-    }
-
-    if (pkt->flags & NACKED_LINE)
-        pkt->result = Packet::Nacked;
-    else
-        pkt->result = Packet::Success;
-    pkt->makeTimingResponse();
-    DPRINTF(CachePort, "%s attempting to send a response\n", name());
-    if (!drainList.empty() || waitingOnRetry) {
-        //Already have a list, just append
-        drainList.push_back(pkt);
-        DPRINTF(CachePort, "%s appending response onto drain list\n", name());
-    }
-    else if (!sendTiming(pkt)) {
-        //It failed, save it to list of drain events
-        DPRINTF(CachePort, "%s now waiting for a retry\n", name());
-        drainList.push_back(pkt);
-        waitingOnRetry = true;
-    }
-
-    // Check if we're done draining once this list is empty
-    if (drainList.empty() && transmitList.empty())
-        myCache()->checkDrain();
+    checkFunctional(pkt);
+    if (pkt->result != Packet::Success)
+        myCache()->functionalAccess(pkt, cache->memSidePort);
 }
 
 
 template<class TagStore, class Coherence>
-Tick
-Cache<TagStore,Coherence>::CpuSidePort::recvAtomic(PacketPtr pkt)
-{
-    myCache()->probe(pkt, true, NULL);
-    //TEMP ALWAYS SUCCES FOR NOW
-    pkt->result = Packet::Success;
-    //Fix this timing info
-    return myCache()->hitLatency;
-}
-
-template<class TagStore, class Coherence>
-void
-Cache<TagStore,Coherence>::CpuSidePort::recvFunctional(PacketPtr pkt)
+Cache<TagStore,Coherence>::
+CpuSidePort::CpuSidePort(const std::string &_name,
+                         Cache<TagStore,Coherence> *_cache)
+    : BaseCache::CachePort(_name, _cache)
 {
-    if (checkFunctional(pkt)) {
-        //TEMP USE CPU?THREAD 0 0
-        pkt->req->setThreadContext(0,0);
-
-        myCache()->probe(pkt, false, cache->memSidePort);
-        //TEMP ALWAYS SUCCESFUL FOR NOW
-        pkt->result = Packet::Success;
-    }
 }
 
+///////////////
+//
+// MemSidePort
+//
+///////////////
 
 template<class TagStore, class Coherence>
 void
 Cache<TagStore,Coherence>::MemSidePort::
 getDeviceAddressRanges(AddrRangeList &resp, bool &snoop)
 {
-    // Memory-side port always snoops.
-    bool dummy;
-    otherPort->getPeerAddressRanges(resp, dummy);
+    otherPort->getPeerAddressRanges(resp, snoop);
+    // Memory-side port always snoops, so unconditionally set flag for
+    // caller.
     snoop = true;
 }
 
@@ -1303,177 +1197,115 @@ Cache<TagStore,Coherence>::MemSidePort::recvTiming(PacketPtr pkt)
     if (pkt->isResponse()) {
         myCache()->handleResponse(pkt);
     } else {
-        myCache()->snoop(pkt);
+        myCache()->snoopTiming(pkt);
     }
     return true;
 }
 
+
 template<class TagStore, class Coherence>
-void
-Cache<TagStore,Coherence>::MemSidePort::recvRetry()
+Tick
+Cache<TagStore,Coherence>::MemSidePort::recvAtomic(PacketPtr pkt)
 {
-    if (recvRetryCommon()) {
-        return;
-    }
-
-    DPRINTF(CachePort, "%s attempting to send a retry for MSHR\n", name());
-    if (!cache->isMemSideBusRequested()) {
-        //This can happen if I am the owner of a block and see an upgrade
-        //while the block was in my WB Buffers.  I just remove the
-        //wb and de-assert the masterRequest
-        waitingOnRetry = false;
-        return;
-    }
-    PacketPtr pkt = myCache()->getPacket();
-    MSHR* mshr = (MSHR*) pkt->senderState;
-    //Copy the packet, it may be modified/destroyed elsewhere
-    PacketPtr copyPkt = new Packet(*pkt);
-    copyPkt->dataStatic<uint8_t>(pkt->getPtr<uint8_t>());
-    mshr->pkt = copyPkt;
-
-    bool success = sendTiming(pkt);
-    DPRINTF(Cache, "Address %x was %s in sending the timing request\n",
-            pkt->getAddr(), success ? "succesful" : "unsuccesful");
-
-    waitingOnRetry = !success;
-    if (waitingOnRetry) {
-        DPRINTF(CachePort, "%s now waiting on a retry\n", name());
-    }
+    // in atomic mode, responses go back to the sender via the
+    // function return from sendAtomic(), not via a separate
+    // sendAtomic() from the responder.  Thus we should never see a
+    // response packet in recvAtomic() (anywhere, not just here).
+    assert(!pkt->isResponse());
+    return myCache()->snoopAtomic(pkt);
+}
 
-    myCache()->sendResult(pkt, mshr, success);
 
-    if (success && cache->isMemSideBusRequested())
-    {
-        DPRINTF(CachePort, "%s has more requests\n", name());
-        //Still more to issue, rerequest in 1 cycle
-        new RequestEvent(this, curTick + 1);
-    }
+template<class TagStore, class Coherence>
+void
+Cache<TagStore,Coherence>::MemSidePort::recvFunctional(PacketPtr pkt)
+{
+    checkFunctional(pkt);
+    if (pkt->result != Packet::Success)
+        myCache()->functionalAccess(pkt, cache->cpuSidePort);
 }
 
 
+
 template<class TagStore, class Coherence>
 void
-Cache<TagStore,Coherence>::MemSidePort::processRequestEvent()
+Cache<TagStore,Coherence>::MemSidePort::sendPacket()
 {
-    if (waitingOnRetry)
-        return;
-    //We have some responses to drain first
-    if (!drainList.empty()) {
-        if (!drainResponse()) {
-            // more responses to drain... re-request bus
-            scheduleRequestEvent(curTick + 1);
-        }
-        return;
-    }
+    // if we have responses that are ready, they take precedence
+    if (deferredPacketReady()) {
+        bool success = sendTiming(transmitList.front().pkt);
 
-    DPRINTF(CachePort, "%s trying to send a MSHR request\n", name());
-    if (!isBusRequested()) {
-        //This can happen if I am the owner of a block and see an upgrade
-        //while the block was in my WB Buffers.  I just remove the
-        //wb and de-assert the masterRequest
-        return;
-    }
+        if (success) {
+            //send successful, remove packet
+            transmitList.pop_front();
+        }
 
-    PacketPtr pkt = myCache()->getPacket();
-    MSHR* mshr = (MSHR*) pkt->senderState;
-    //Copy the packet, it may be modified/destroyed elsewhere
-    PacketPtr copyPkt = new Packet(*pkt);
-    copyPkt->dataStatic<uint8_t>(pkt->getPtr<uint8_t>());
-    mshr->pkt = copyPkt;
+        waitingOnRetry = !success;
+    } else {
+        // check for non-response packets (requests & writebacks)
+        PacketPtr pkt = myCache()->getPacket();
+        MSHR *mshr = dynamic_cast<MSHR*>(pkt->senderState);
 
-    bool success = sendTiming(pkt);
-    DPRINTF(Cache, "Address %x was %s in sending the timing request\n",
-            pkt->getAddr(), success ? "succesful" : "unsuccesful");
+        bool success = sendTiming(pkt);
+        DPRINTF(Cache, "Address %x was %s in sending the timing request\n",
+                pkt->getAddr(), success ? "successful" : "unsuccessful");
 
-    waitingOnRetry = !success;
-    if (waitingOnRetry) {
-        DPRINTF(CachePort, "%s now waiting on a retry\n", name());
+        waitingOnRetry = !success;
+        if (waitingOnRetry) {
+            DPRINTF(CachePort, "%s now waiting on a retry\n", name());
+        } else {
+            myCache()->markInService(mshr);
+        }
     }
 
-    myCache()->sendResult(pkt, mshr, success);
-    if (success && isBusRequested())
-    {
-        DPRINTF(CachePort, "%s still more MSHR requests to send\n", name());
-        //Still more to issue, rerequest in 1 cycle
-        scheduleRequestEvent(curTick+1);
+
+    // tried to send packet... if it was successful (no retry), see if
+    // we need to rerequest bus or not
+    if (!waitingOnRetry) {
+        if (isBusRequested()) {
+            // more requests/writebacks: rerequest ASAP
+            DPRINTF(CachePort, "%s still more MSHR requests to send\n",
+                    name());
+            sendEvent->schedule(curTick+1);
+        } else if (!transmitList.empty()) {
+            // deferred packets: rerequest bus, but possibly not until later
+            Tick time = transmitList.front().tick;
+            sendEvent->schedule(time <= curTick ? curTick+1 : time);
+        } else {
+            // no more to send right now: if we're draining, we may be done
+            if (drainEvent) {
+                drainEvent->process();
+                drainEvent = NULL;
+            }
+        }
     }
 }
 
-
 template<class TagStore, class Coherence>
 void
-Cache<TagStore,Coherence>::MemSidePort::processResponseEvent()
+Cache<TagStore,Coherence>::MemSidePort::recvRetry()
 {
-    assert(transmitList.size());
-    assert(transmitList.front().first <= curTick);
-    PacketPtr pkt = transmitList.front().second;
-    transmitList.pop_front();
-    if (!transmitList.empty()) {
-        Tick time = transmitList.front().first;
-        responseEvent->schedule(time <= curTick ? curTick+1 : time);
-    }
-
-    if (pkt->flags & NACKED_LINE)
-        pkt->result = Packet::Nacked;
-    else
-        pkt->result = Packet::Success;
-    pkt->makeTimingResponse();
-    DPRINTF(CachePort, "%s attempting to send a response\n", name());
-    if (!drainList.empty() || waitingOnRetry) {
-        //Already have a list, just append
-        drainList.push_back(pkt);
-        DPRINTF(CachePort, "%s appending response onto drain list\n", name());
-    }
-    else if (!sendTiming(pkt)) {
-        //It failed, save it to list of drain events
-        DPRINTF(CachePort, "%s now waiting for a retry\n", name());
-        drainList.push_back(pkt);
-        waitingOnRetry = true;
-    }
-
-    // Check if we're done draining once this list is empty
-    if (drainList.empty() && transmitList.empty())
-        myCache()->checkDrain();
+    assert(waitingOnRetry);
+    sendPacket();
 }
 
 
-template<class TagStore, class Coherence>
-Tick
-Cache<TagStore,Coherence>::MemSidePort::recvAtomic(PacketPtr pkt)
-{
-    if (pkt->isResponse())
-        myCache()->handleResponse(pkt);
-    else
-        return myCache()->snoopProbe(pkt);
-    //Fix this timing info
-    return myCache()->hitLatency;
-}
-
 template<class TagStore, class Coherence>
 void
-Cache<TagStore,Coherence>::MemSidePort::recvFunctional(PacketPtr pkt)
+Cache<TagStore,Coherence>::MemSidePort::processSendEvent()
 {
-    myCache()->probe(pkt, false, cache->cpuSidePort);
-    if (pkt->result != Packet::Success)
-        checkFunctional(pkt);
+    assert(!waitingOnRetry);
+    sendPacket();
 }
 
 
-template<class TagStore, class Coherence>
-Cache<TagStore,Coherence>::
-CpuSidePort::CpuSidePort(const std::string &_name,
-                         Cache<TagStore,Coherence> *_cache)
-    : BaseCache::CachePort(_name, _cache)
-{
-    responseEvent = new ResponseEvent(this);
-}
-
 template<class TagStore, class Coherence>
 Cache<TagStore,Coherence>::
 MemSidePort::MemSidePort(const std::string &_name,
                          Cache<TagStore,Coherence> *_cache)
     : BaseCache::CachePort(_name, _cache)
 {
-    responseEvent = new ResponseEvent(this);
+    // override default send event from SimpleTimingPort
+    delete sendEvent;
+    sendEvent = new SendEvent(this);
 }
-
index bc8de0d26b10e2fa2956279253d72ead33e71a3c..3fd17c8c79115f731bd1a027cf2424349a23ecc3 100644 (file)
@@ -139,31 +139,6 @@ CoherenceProtocol::regStats()
         .desc("readEx snoops on exclusive blocks")
         ;
 
-    snoopCount[Shared][MemCmd::InvalidateReq]
-        .name(name() + ".snoop_inv_shared")
-        .desc("Invalidate snoops on shared blocks")
-        ;
-
-    snoopCount[Owned][MemCmd::InvalidateReq]
-        .name(name() + ".snoop_inv_owned")
-        .desc("Invalidate snoops on owned blocks")
-        ;
-
-    snoopCount[Exclusive][MemCmd::InvalidateReq]
-        .name(name() + ".snoop_inv_exclusive")
-        .desc("Invalidate snoops on exclusive blocks")
-        ;
-
-    snoopCount[Modified][MemCmd::InvalidateReq]
-        .name(name() + ".snoop_inv_modified")
-        .desc("Invalidate snoops on modified blocks")
-        ;
-
-    snoopCount[Invalid][MemCmd::InvalidateReq]
-        .name(name() + ".snoop_inv_invalid")
-        .desc("Invalidate snoops on invalid blocks")
-        ;
-
     snoopCount[Shared][MemCmd::WriteInvalidateReq]
         .name(name() + ".snoop_writeinv_shared")
         .desc("WriteInvalidate snoops on shared blocks")
@@ -219,7 +194,7 @@ CoherenceProtocol::supplyAndGotoSharedTrans(BaseCache *cache, PacketPtr &pkt,
                                             CacheBlk::State & new_state)
 {
     new_state = (blk->status & ~stateMask) | Shared;
-    pkt->flags |= SHARED_LINE;
+    pkt->assertShared();
     return supplyTrans(cache, pkt, blk, mshr, new_state);
 }
 
@@ -231,7 +206,7 @@ CoherenceProtocol::supplyAndGotoOwnedTrans(BaseCache *cache, PacketPtr &pkt,
                                            CacheBlk::State & new_state)
 {
     new_state = (blk->status & ~stateMask) | Owned;
-    pkt->flags |= SHARED_LINE;
+    pkt->assertShared();
     return supplyTrans(cache, pkt, blk, mshr, new_state);
 }
 
@@ -253,7 +228,7 @@ CoherenceProtocol::assertShared(BaseCache *cache, PacketPtr &pkt,
                                             CacheBlk::State & new_state)
 {
     new_state = (blk->status & ~stateMask) | Shared;
-    pkt->flags |= SHARED_LINE;
+    pkt->assertShared();
     return false;
 }
 
@@ -336,12 +311,10 @@ CoherenceProtocol::CoherenceProtocol(const string &name,
     //
     tt[Invalid][MC::ReadReq].onSnoop(nullTransition);
     tt[Invalid][MC::ReadExReq].onSnoop(nullTransition);
-    tt[Invalid][MC::InvalidateReq].onSnoop(invalidateTrans);
     tt[Invalid][MC::WriteInvalidateReq].onSnoop(invalidateTrans);
     tt[Shared][MC::ReadReq].onSnoop(hasExclusive
                                    ? assertShared : nullTransition);
     tt[Shared][MC::ReadExReq].onSnoop(invalidateTrans);
-    tt[Shared][MC::InvalidateReq].onSnoop(invalidateTrans);
     tt[Shared][MC::WriteInvalidateReq].onSnoop(invalidateTrans);
     if (doUpgrades) {
         tt[Invalid][MC::UpgradeReq].onSnoop(nullTransition);
@@ -351,13 +324,11 @@ CoherenceProtocol::CoherenceProtocol(const string &name,
     tt[Modified][MC::ReadReq].onSnoop(hasOwned
                                      ? supplyAndGotoOwnedTrans
                                      : supplyAndGotoSharedTrans);
-    tt[Modified][MC::InvalidateReq].onSnoop(invalidateTrans);
     tt[Modified][MC::WriteInvalidateReq].onSnoop(invalidateTrans);
 
     if (hasExclusive) {
         tt[Exclusive][MC::ReadReq].onSnoop(assertShared);
         tt[Exclusive][MC::ReadExReq].onSnoop(invalidateTrans);
-        tt[Exclusive][MC::InvalidateReq].onSnoop(invalidateTrans);
         tt[Exclusive][MC::WriteInvalidateReq].onSnoop(invalidateTrans);
     }
 
@@ -365,7 +336,6 @@ CoherenceProtocol::CoherenceProtocol(const string &name,
         tt[Owned][MC::ReadReq].onSnoop(supplyAndGotoOwnedTrans);
         tt[Owned][MC::ReadExReq].onSnoop(supplyAndInvalidateTrans);
         tt[Owned][MC::UpgradeReq].onSnoop(invalidateTrans);
-        tt[Owned][MC::InvalidateReq].onSnoop(invalidateTrans);
         tt[Owned][MC::WriteInvalidateReq].onSnoop(invalidateTrans);
     }
 
@@ -394,7 +364,7 @@ CoherenceProtocol::getBusCmd(MemCmd cmdIn, CacheBlk::State state,
 
 
 CacheBlk::State
-CoherenceProtocol::getNewState(PacketPtr &pkt, CacheBlk::State oldState)
+CoherenceProtocol::getNewState(PacketPtr pkt, CacheBlk::State oldState)
 {
     CacheBlk::State state = oldState & stateMask;
     int cmd_idx = pkt->cmdToIndex();
@@ -406,7 +376,7 @@ CoherenceProtocol::getNewState(PacketPtr &pkt, CacheBlk::State oldState)
 
     //Check if it's exclusive and the shared line was asserted,
     //then  goto shared instead
-    if (newState == Exclusive && (pkt->flags & SHARED_LINE)) {
+    if (newState == Exclusive && pkt->sharedAsserted()) {
         newState = Shared;
     }
 
index 775bc807a7f866cf0e2faf5ca5ec0ad1e6da69f8..4b80245820389b3ab3ec24b336ea634be2acdeb2 100644 (file)
@@ -89,8 +89,8 @@ class CoherenceProtocol : public SimObject
      * @param oldState The current block state.
      * @return The new state.
      */
-    CacheBlk::State getNewState(PacketPtr &pkt,
-                                CacheBlk::State oldState);
+    CacheBlk::State getNewState(PacketPtr pkt,
+                                CacheBlk::State oldState = 0);
 
     /**
      * Handle snooped bus requests.
index 095260ca4b48f38958b7738e1624c5408fb62f9b..214828ca7ae7e79f94eccbc779d29e5e080881b8 100644 (file)
@@ -94,25 +94,14 @@ class SimpleCoherence
         return NULL;
     }
 
-    /**
-     * Was the CSHR request was sent successfully?
-     * @param pkt The request.
-     * @param success True if the request was sent successfully.
-     */
-    void sendResult(PacketPtr &pkt, MSHR* cshr, bool success)
-    {
-        //Don't do coherence
-        return;
-    }
-
-
     /**
      * Return the proper state given the current state and the bus response.
      * @param pkt The bus response.
      * @param current The current block state.
      * @return The new state.
      */
-    CacheBlk::State getNewState(PacketPtr &pkt, CacheBlk::State current)
+    CacheBlk::State getNewState(PacketPtr pkt,
+                                CacheBlk::State current = 0)
     {
         return protocol->getNewState(pkt, current);
     }
index 0f81a2570edd6fd10f8e3d98c7ea9a0ef4f9d9f8..376d670cd41ff63244bc8d10f21c841277c14e18 100644 (file)
@@ -30,8 +30,5 @@
 
 Import('*')
 
-Source('blocking_buffer.cc')
-Source('miss_buffer.cc')
-Source('miss_queue.cc')
 Source('mshr.cc')
 Source('mshr_queue.cc')
diff --git a/src/mem/cache/miss/blocking_buffer.cc b/src/mem/cache/miss/blocking_buffer.cc
deleted file mode 100644 (file)
index 281328c..0000000
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * Copyright (c) 2003-2005 The Regents of The University of Michigan
- * 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: Erik Hallnor
- */
-
-/**
- * @file
- * Definitions of a simple buffer for a blocking cache.
- */
-#include <cstring>
-
-#include "mem/cache/base_cache.hh"
-#include "mem/cache/miss/blocking_buffer.hh"
-#include "mem/cache/prefetch/base_prefetcher.hh"
-#include "mem/request.hh"
-
-/**
- * @todo Move writebacks into shared BaseBuffer class.
- */
-void
-BlockingBuffer::regStats(const std::string &name)
-{
-    MissBuffer::regStats(name);
-}
-
-
-void
-BlockingBuffer::handleMiss(PacketPtr &pkt, int blk_size, Tick time)
-{
-    Addr blk_addr = pkt->getAddr() & ~(Addr)(blk_size - 1);
-    if (pkt->isWrite() && (pkt->req->isUncacheable() || !writeAllocate ||
-                               !pkt->needsResponse())) {
-        if (!pkt->needsResponse()) {
-            wb.allocateAsBuffer(pkt);
-        } else {
-            wb.allocate(pkt->cmd, blk_addr, blk_size, pkt);
-        }
-
-        std::memcpy(wb.pkt->getPtr<uint8_t>(), pkt->getPtr<uint8_t>(), blk_size);
-
-        cache->setBlocked(Blocked_NoWBBuffers);
-        cache->requestMemSideBus(Request_WB, time);
-        return;
-    }
-
-    if (!pkt->needsResponse()) {
-        miss.allocateAsBuffer(pkt);
-    } else {
-        miss.allocate(pkt->cmd, blk_addr, blk_size, pkt);
-    }
-    if (!pkt->req->isUncacheable()) {
-        miss.pkt->flags |= CACHE_LINE_FILL;
-    }
-    cache->setBlocked(Blocked_NoMSHRs);
-    cache->requestMemSideBus(Request_MSHR, time);
-}
-
-PacketPtr
-BlockingBuffer::getPacket()
-{
-    if (miss.pkt && !miss.inService) {
-        return miss.pkt;
-    }
-    return wb.pkt;
-}
-
-void
-BlockingBuffer::setBusCmd(PacketPtr &pkt, MemCmd cmd)
-{
-    MSHR *mshr = (MSHR*) pkt->senderState;
-    mshr->originalCmd = pkt->cmd;
-    if (pkt->isCacheFill())
-        pkt->cmdOverride(cmd);
-}
-
-void
-BlockingBuffer::restoreOrigCmd(PacketPtr &pkt)
-{
-    pkt->cmdOverride(((MSHR*)(pkt->senderState))->originalCmd);
-}
-
-void
-BlockingBuffer::markInService(PacketPtr &pkt, MSHR* mshr)
-{
-    if (!pkt->isCacheFill() && pkt->isWrite()) {
-        // Forwarding a write/ writeback, don't need to change
-        // the command
-        assert(mshr == &wb);
-        cache->deassertMemSideBusRequest(Request_WB);
-        if (!pkt->needsResponse()) {
-            assert(wb.getNumTargets() == 0);
-            wb.deallocate();
-            cache->clearBlocked(Blocked_NoWBBuffers);
-        } else {
-            wb.inService = true;
-        }
-    } else {
-        assert(mshr == &miss);
-        cache->deassertMemSideBusRequest(Request_MSHR);
-        if (!pkt->needsResponse()) {
-            assert(miss.getNumTargets() == 0);
-            miss.deallocate();
-            cache->clearBlocked(Blocked_NoMSHRs);
-        } else {
-            //mark in service
-            miss.inService = true;
-        }
-    }
-}
-
-void
-BlockingBuffer::handleResponse(PacketPtr &pkt, Tick time)
-{
-    if (pkt->isCacheFill()) {
-        // targets were handled in the cache tags
-        assert((MSHR*)pkt->senderState == &miss);
-        miss.deallocate();
-        cache->clearBlocked(Blocked_NoMSHRs);
-    } else {
-        if (((MSHR*)(pkt->senderState))->hasTargets()) {
-            // Should only have 1 target if we had any
-            assert(((MSHR*)(pkt->senderState))->getNumTargets() == 1);
-            PacketPtr target = ((MSHR*)(pkt->senderState))->getTarget();
-            ((MSHR*)(pkt->senderState))->popTarget();
-            if (pkt->isRead()) {
-                std::memcpy(target->getPtr<uint8_t>(), pkt->getPtr<uint8_t>(), target->getSize());
-            }
-            cache->respond(target, time);
-            assert(!((MSHR*)(pkt->senderState))->hasTargets());
-        }
-
-        if (pkt->isWrite()) {
-            assert(((MSHR*)(pkt->senderState)) == &wb);
-            wb.deallocate();
-            cache->clearBlocked(Blocked_NoWBBuffers);
-        } else {
-            miss.deallocate();
-            cache->clearBlocked(Blocked_NoMSHRs);
-        }
-    }
-}
-
-void
-BlockingBuffer::squash(int threadNum)
-{
-    if (miss.threadNum == threadNum) {
-        PacketPtr target = miss.getTarget();
-        miss.popTarget();
-        assert(0/*target->req->getThreadNum()*/ == threadNum);
-        target = NULL;
-        assert(!miss.hasTargets());
-        miss.ntargets=0;
-        if (!miss.inService) {
-            miss.deallocate();
-            cache->clearBlocked(Blocked_NoMSHRs);
-            cache->deassertMemSideBusRequest(Request_MSHR);
-        }
-    }
-}
-
-void
-BlockingBuffer::doWriteback(Addr addr,
-                            int size, uint8_t *data, bool compressed)
-{
-    // Generate request
-    Request * req = new Request(addr, size, 0);
-    PacketPtr pkt = new Packet(req, MemCmd::Writeback, -1);
-    pkt->allocate();
-    if (data) {
-        std::memcpy(pkt->getPtr<uint8_t>(), data, size);
-    }
-
-    if (compressed) {
-        pkt->flags |= COMPRESSED;
-    }
-
-    ///All writebacks charged to same thread @todo figure this out
-    writebacks[0/*pkt->req->getThreadNum()*/]++;
-
-    wb.allocateAsBuffer(pkt);
-    cache->requestMemSideBus(Request_WB, curTick);
-    cache->setBlocked(Blocked_NoWBBuffers);
-}
-
-
-
-void
-BlockingBuffer::doWriteback(PacketPtr &pkt)
-{
-    writebacks[0/*pkt->req->getThreadNum()*/]++;
-
-    wb.allocateAsBuffer(pkt);
-
-    // Since allocate as buffer copies the request,
-    // need to copy data here.
-    std::memcpy(wb.pkt->getPtr<uint8_t>(), pkt->getPtr<uint8_t>(), pkt->getSize());
-
-    cache->setBlocked(Blocked_NoWBBuffers);
-    cache->requestMemSideBus(Request_WB, curTick);
-}
-
-
-MSHR *
-BlockingBuffer::findMSHR(Addr addr)
-{
-    if (miss.addr == addr && miss.pkt)
-        return &miss;
-    return NULL;
-}
-
-
-bool
-BlockingBuffer::findWrites(Addr addr, std::vector<MSHR*>& writes)
-{
-    if (wb.addr == addr && wb.pkt) {
-        writes.push_back(&wb);
-        return true;
-    }
-    return false;
-}
diff --git a/src/mem/cache/miss/blocking_buffer.hh b/src/mem/cache/miss/blocking_buffer.hh
deleted file mode 100644 (file)
index 86b24d5..0000000
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * Copyright (c) 2003-2005 The Regents of The University of Michigan
- * 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: Erik Hallnor
- */
-
-/**
- * @file
- * Declaration of a simple buffer for a blocking cache.
- */
-
-#ifndef __BLOCKING_BUFFER_HH__
-#define __BLOCKING_BUFFER_HH__
-
-#include <vector>
-
-#include "base/misc.hh" // for fatal()
-#include "mem/cache/miss/miss_buffer.hh"
-#include "mem/cache/miss/mshr.hh"
-
-/**
- * Miss and writeback storage for a blocking cache.
- */
-class BlockingBuffer : public MissBuffer
-{
-protected:
-    /** Miss storage. */
-    MSHR miss;
-    /** WB storage. */
-    MSHR wb;
-
-public:
-    /**
-     * Builds and initializes this buffer.
-     * @param write_allocate If true, treat write misses the same as reads.
-     */
-    BlockingBuffer(bool write_allocate)
-        : MissBuffer(write_allocate)
-    {
-    }
-
-    /**
-     * Register statistics for this object.
-     * @param name The name of the parent cache.
-     */
-    void regStats(const std::string &name);
-
-    /**
-     * Handle a cache miss properly. Requests the bus and marks the cache as
-     * blocked.
-     * @param pkt The request that missed in the cache.
-     * @param blk_size The block size of the cache.
-     * @param time The time the miss is detected.
-     */
-    void handleMiss(PacketPtr &pkt, int blk_size, Tick time);
-
-    /**
-     * Fetch the block for the given address and buffer the given target.
-     * @param addr The address to fetch.
-     * @param asid The address space of the address.
-     * @param blk_size The block size of the cache.
-     * @param time The time the miss is detected.
-     * @param target The target for the fetch.
-     */
-    MSHR* fetchBlock(Addr addr, int blk_size, Tick time,
-                     PacketPtr &target)
-    {
-        fatal("Unimplemented");
-        M5_DUMMY_RETURN
-    }
-
-    /**
-     * Selects a outstanding request to service.
-     * @return The request to service, NULL if none found.
-     */
-    PacketPtr getPacket();
-
-    /**
-     * Set the command to the given bus command.
-     * @param pkt The request to update.
-     * @param cmd The bus command to use.
-     */
-    void setBusCmd(PacketPtr &pkt, MemCmd cmd);
-
-    /**
-     * Restore the original command in case of a bus transmission error.
-     * @param pkt The request to reset.
-     */
-    void restoreOrigCmd(PacketPtr &pkt);
-
-    /**
-     * Marks a request as in service (sent on the bus). This can have side
-     * effect since storage for no response commands is deallocated once they
-     * are successfully sent.
-     * @param pkt The request that was sent on the bus.
-     */
-    void markInService(PacketPtr &pkt, MSHR* mshr);
-
-    /**
-     * Frees the resources of the request and unblock the cache.
-     * @param pkt The request that has been satisfied.
-     * @param time The time when the request is satisfied.
-     */
-    void handleResponse(PacketPtr &pkt, Tick time);
-
-    /**
-     * Removes all outstanding requests for a given thread number. If a request
-     * has been sent to the bus, this function removes all of its targets.
-     * @param threadNum The thread number of the requests to squash.
-     */
-    void squash(int threadNum);
-
-    /**
-     * Return the current number of outstanding misses.
-     * @return the number of outstanding misses.
-     */
-    int getMisses()
-    {
-        return miss.getNumTargets();
-    }
-
-    /**
-     * Searches for the supplied address in the miss "queue".
-     * @param addr The address to look for.
-     * @param asid The address space id.
-     * @return A pointer to miss if it matches.
-     */
-    MSHR* findMSHR(Addr addr);
-
-    /**
-     * Searches for the supplied address in the write buffer.
-     * @param addr The address to look for.
-     * @param asid The address space id.
-     * @param writes List of pointers to the matching writes.
-     * @return True if there is a matching write.
-     */
-    bool findWrites(Addr addr, std::vector<MSHR*>& writes);
-
-    /**
-     * Perform a writeback of dirty data to the given address.
-     * @param addr The address to write to.
-     * @param asid The address space id.
-     * @param size The number of bytes to write.
-     * @param data The data to write, can be NULL.
-     * @param compressed True if the data is compressed.
-     */
-    void doWriteback(Addr addr,
-                     int size, uint8_t *data, bool compressed);
-
-    /**
-     * Perform a writeback request.
-     * @param pkt The writeback request.
-     */
-    void doWriteback(PacketPtr &pkt);
-
-    /**
-     * Returns true if there are outstanding requests.
-     * @return True if there are outstanding requests.
-     */
-    bool havePending()
-    {
-        return !miss.inService || !wb.inService;
-    }
-
-    /**
-     * Add a target to the given MSHR. This assumes it is in the miss queue.
-     * @param mshr The mshr to add a target to.
-     * @param pkt The target to add.
-     */
-    void addTarget(MSHR *mshr, PacketPtr &pkt)
-    {
-        fatal("Shouldn't call this on a blocking buffer.");
-    }
-
-    /**
-     * Dummy implmentation.
-     */
-    MSHR* allocateTargetList(Addr addr)
-    {
-        fatal("Unimplemented");
-        M5_DUMMY_RETURN
-    }
-};
-
-#endif // __BLOCKING_BUFFER_HH__
diff --git a/src/mem/cache/miss/miss_buffer.cc b/src/mem/cache/miss/miss_buffer.cc
deleted file mode 100644 (file)
index 4d9cd09..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2003-2006 The Regents of The University of Michigan
- * 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: Erik Hallnor
- */
-
-#include "cpu/smt.hh" //for maxThreadsPerCPU
-#include "mem/cache/base_cache.hh"
-#include "mem/cache/miss/miss_buffer.hh"
-#include "mem/cache/prefetch/base_prefetcher.hh"
-
-/**
- * @todo Move writebacks into shared BaseBuffer class.
- */
-void
-MissBuffer::regStats(const std::string &name)
-{
-    using namespace Stats;
-    writebacks
-        .init(maxThreadsPerCPU)
-        .name(name + ".writebacks")
-        .desc("number of writebacks")
-        .flags(total)
-        ;
-}
-
-void
-MissBuffer::setCache(BaseCache *_cache)
-{
-    cache = _cache;
-    blkSize = cache->getBlockSize();
-}
-
-void
-MissBuffer::setPrefetcher(BasePrefetcher *_prefetcher)
-{
-    prefetcher = _prefetcher;
-}
diff --git a/src/mem/cache/miss/miss_buffer.hh b/src/mem/cache/miss/miss_buffer.hh
deleted file mode 100644 (file)
index 9a86db3..0000000
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * Copyright (c) 2003-2006 The Regents of The University of Michigan
- * 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: Steve Reinhardt
- */
-
-/**
- * @file
- * MissBuffer declaration.
- */
-
-#ifndef __MISS_BUFFER_HH__
-#define __MISS_BUFFER_HH__
-
-class BaseCache;
-class BasePrefetcher;
-class MSHR;
-
-/**
- * Abstract base class for cache miss buffering.
- */
-class MissBuffer
-{
-  protected:
-    /** True if the cache should allocate on a write miss. */
-    const bool writeAllocate;
-
-    /** Pointer to the parent cache. */
-    BaseCache *cache;
-
-    /** The Prefetcher */
-    BasePrefetcher *prefetcher;
-
-    /** Block size of the parent cache. */
-    int blkSize;
-
-    // Statistics
-    /**
-     * @addtogroup CacheStatistics
-     * @{
-     */
-    /** Number of blocks written back per thread. */
-    Stats::Vector<> writebacks;
-
-    /**
-     * @}
-     */
-
-  public:
-    MissBuffer(bool write_allocate)
-        : writeAllocate(write_allocate)
-    {
-    }
-
-    virtual ~MissBuffer() {}
-
-    /**
-     * Called by the parent cache to set the back pointer.
-     * @param _cache A pointer to the parent cache.
-     */
-    void setCache(BaseCache *_cache);
-
-    void setPrefetcher(BasePrefetcher *_prefetcher);
-
-    /**
-     * Register statistics for this object.
-     * @param name The name of the parent cache.
-     */
-    virtual void regStats(const std::string &name);
-
-    /**
-     * Handle a cache miss properly. Either allocate an MSHR for the request,
-     * or forward it through the write buffer.
-     * @param pkt The request that missed in the cache.
-     * @param blk_size The block size of the cache.
-     * @param time The time the miss is detected.
-     */
-    virtual void handleMiss(PacketPtr &pkt, int blk_size, Tick time) = 0;
-
-    /**
-     * Fetch the block for the given address and buffer the given target.
-     * @param addr The address to fetch.
-     * @param asid The address space of the address.
-     * @param blk_size The block size of the cache.
-     * @param time The time the miss is detected.
-     * @param target The target for the fetch.
-     */
-    virtual MSHR *fetchBlock(Addr addr, int blk_size, Tick time,
-                             PacketPtr &target) = 0;
-
-    /**
-     * Selects a outstanding request to service.
-     * @return The request to service, NULL if none found.
-     */
-    virtual PacketPtr getPacket() = 0;
-
-    /**
-     * Set the command to the given bus command.
-     * @param pkt The request to update.
-     * @param cmd The bus command to use.
-     */
-    virtual void setBusCmd(PacketPtr &pkt, MemCmd cmd) = 0;
-
-    /**
-     * Restore the original command in case of a bus transmission error.
-     * @param pkt The request to reset.
-     */
-    virtual void restoreOrigCmd(PacketPtr &pkt) = 0;
-
-    /**
-     * Marks a request as in service (sent on the bus). This can have side
-     * effect since storage for no response commands is deallocated once they
-     * are successfully sent.
-     * @param pkt The request that was sent on the bus.
-     */
-    virtual void markInService(PacketPtr &pkt, MSHR* mshr) = 0;
-
-    /**
-     * Collect statistics and free resources of a satisfied request.
-     * @param pkt The request that has been satisfied.
-     * @param time The time when the request is satisfied.
-     */
-    virtual void handleResponse(PacketPtr &pkt, Tick time) = 0;
-
-    /**
-     * Removes all outstanding requests for a given thread number. If a request
-     * has been sent to the bus, this function removes all of its targets.
-     * @param threadNum The thread number of the requests to squash.
-     */
-    virtual void squash(int threadNum) = 0;
-
-    /**
-     * Return the current number of outstanding misses.
-     * @return the number of outstanding misses.
-     */
-    virtual int getMisses() = 0;
-
-    /**
-     * Searches for the supplied address in the miss queue.
-     * @param addr The address to look for.
-     * @param asid The address space id.
-     * @return The MSHR that contains the address, NULL if not found.
-     * @warning Currently only searches the miss queue. If non write allocate
-     * might need to search the write buffer for coherence.
-     */
-    virtual MSHR* findMSHR(Addr addr) = 0;
-
-    /**
-     * Searches for the supplied address in the write buffer.
-     * @param addr The address to look for.
-     * @param asid The address space id.
-     * @param writes The list of writes that match the address.
-     * @return True if any writes are found
-     */
-    virtual bool findWrites(Addr addr, std::vector<MSHR*>& writes) = 0;
-
-    /**
-     * Perform a writeback of dirty data to the given address.
-     * @param addr The address to write to.
-     * @param asid The address space id.
-     * @param xc The execution context of the address space.
-     * @param size The number of bytes to write.
-     * @param data The data to write, can be NULL.
-     * @param compressed True if the data is compressed.
-     */
-    virtual void doWriteback(Addr addr, int size, uint8_t *data,
-                             bool compressed) = 0;
-
-    /**
-     * Perform the given writeback request.
-     * @param pkt The writeback request.
-     */
-    virtual void doWriteback(PacketPtr &pkt) = 0;
-
-    /**
-     * Returns true if there are outstanding requests.
-     * @return True if there are outstanding requests.
-     */
-    virtual bool havePending() = 0;
-
-    /**
-     * Add a target to the given MSHR. This assumes it is in the miss queue.
-     * @param mshr The mshr to add a target to.
-     * @param pkt The target to add.
-     */
-    virtual void addTarget(MSHR *mshr, PacketPtr &pkt) = 0;
-
-    /**
-     * Allocate a MSHR to hold a list of targets to a block involved in a copy.
-     * If the block is marked done then the MSHR already holds the data to
-     * fill the block. Otherwise the block needs to be fetched.
-     * @param addr The address to buffer.
-     * @param asid The address space ID.
-     * @return A pointer to the allocated MSHR.
-     */
-    virtual MSHR* allocateTargetList(Addr addr) = 0;
-};
-
-#endif //__MISS_BUFFER_HH__
diff --git a/src/mem/cache/miss/miss_queue.cc b/src/mem/cache/miss/miss_queue.cc
deleted file mode 100644 (file)
index 67036ed..0000000
+++ /dev/null
@@ -1,752 +0,0 @@
-/*
- * Copyright (c) 2003-2005 The Regents of The University of Michigan
- * 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: Erik Hallnor
- *          Ron Dreslinski
- */
-
-/**
- * @file
- * Miss and writeback queue definitions.
- */
-
-#include "cpu/smt.hh" //for maxThreadsPerCPU
-#include "mem/cache/base_cache.hh"
-#include "mem/cache/miss/miss_queue.hh"
-#include "mem/cache/prefetch/base_prefetcher.hh"
-
-using namespace std;
-
-// simple constructor
-/**
- * @todo Remove the +16 from the write buffer constructor once we handle
- * stalling on writebacks do to compression writes.
- */
-MissQueue::MissQueue(int numMSHRs, int numTargets, int write_buffers,
-                     bool write_allocate, bool prefetch_miss)
-    : MissBuffer(write_allocate),
-      mq(numMSHRs, 4), wb(write_buffers,numMSHRs+1000), numMSHR(numMSHRs),
-      numTarget(numTargets), writeBuffers(write_buffers),
-      order(0), prefetchMiss(prefetch_miss)
-{
-    noTargetMSHR = NULL;
-}
-
-
-MissQueue::~MissQueue()
-{
-}
-
-
-void
-MissQueue::regStats(const string &name)
-{
-    MissBuffer::regStats(name);
-
-    using namespace Stats;
-
-    // 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] / cache->accesses[access_idx];
-    }
-
-    demandMshrMissRate
-        .name(name + ".demand_mshr_miss_rate")
-        .desc("mshr miss rate for demand accesses")
-        .flags(total)
-        ;
-    demandMshrMissRate = demandMshrMisses / cache->demandAccesses;
-
-    overallMshrMissRate
-        .name(name + ".overall_mshr_miss_rate")
-        .desc("mshr miss rate for overall accesses")
-        .flags(total)
-        ;
-    overallMshrMissRate = overallMshrMisses / cache->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")
-        ;
-
-}
-
-
-MSHR*
-MissQueue::allocateMiss(PacketPtr &pkt, int size, Tick time)
-{
-    MSHR* mshr = mq.allocate(pkt, size);
-    mshr->order = order++;
-    if (!pkt->req->isUncacheable() ){//&& !pkt->isNoAllocate()) {
-        // Mark this as a cache line fill
-        mshr->pkt->flags |= CACHE_LINE_FILL;
-    }
-    if (mq.isFull()) {
-        cache->setBlocked(Blocked_NoMSHRs);
-    }
-    if (pkt->cmd != MemCmd::HardPFReq) {
-        //If we need to request the bus (not on HW prefetch), do so
-        cache->requestMemSideBus(Request_MSHR, time);
-    }
-    return mshr;
-}
-
-
-MSHR*
-MissQueue::allocateWrite(PacketPtr &pkt, int size, Tick time)
-{
-    MSHR* mshr = wb.allocate(pkt,size);
-    mshr->order = order++;
-
-//REMOVING COMPRESSION FOR NOW
-#if 0
-    if (pkt->isCompressed()) {
-        mshr->pkt->deleteData();
-        mshr->pkt->actualSize = pkt->actualSize;
-        mshr->pkt->data = new uint8_t[pkt->actualSize];
-        memcpy(mshr->pkt->data, pkt->data, pkt->actualSize);
-    } else {
-#endif
-        memcpy(mshr->pkt->getPtr<uint8_t>(), pkt->getPtr<uint8_t>(), pkt->getSize());
-  //{
-
-    if (wb.isFull()) {
-        cache->setBlocked(Blocked_NoWBBuffers);
-    }
-
-    cache->requestMemSideBus(Request_WB, time);
-
-    return mshr;
-}
-
-
-/**
- * @todo Remove SW prefetches on mshr hits.
- */
-void
-MissQueue::handleMiss(PacketPtr &pkt, int blkSize, Tick time)
-{
-//    if (!cache->isTopLevel())
-    if (prefetchMiss) prefetcher->handleMiss(pkt, time);
-
-    int size = blkSize;
-    Addr blkAddr = pkt->getAddr() & ~(Addr)(blkSize-1);
-    MSHR* mshr = NULL;
-    if (!pkt->req->isUncacheable()) {
-        mshr = mq.findMatch(blkAddr);
-        if (mshr) {
-            //@todo remove hw_pf here
-            mshr_hits[pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/]++;
-            if (mshr->threadNum != 0/*pkt->req->getThreadNum()*/) {
-                mshr->threadNum = -1;
-            }
-            mq.allocateTarget(mshr, pkt);
-            if (mshr->pkt->isNoAllocate() && !pkt->isNoAllocate()) {
-                //We are adding an allocate after a no-allocate
-                mshr->pkt->flags &= ~NO_ALLOCATE;
-            }
-            if (mshr->getNumTargets() == numTarget) {
-                noTargetMSHR = mshr;
-                cache->setBlocked(Blocked_NoTargets);
-                mq.moveToFront(mshr);
-            }
-            return;
-        }
-        if (pkt->isNoAllocate()) {
-            //Count no-allocate requests differently
-            mshr_no_allocate_misses++;
-        }
-        else {
-            mshr_misses[pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/]++;
-        }
-    } else {
-        //Count uncacheable accesses
-        mshr_uncacheable[pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/]++;
-        size = pkt->getSize();
-    }
-    if (pkt->isWrite() && (pkt->req->isUncacheable() || !writeAllocate ||
-                               !pkt->needsResponse())) {
-        /**
-         * @todo Add write merging here.
-         */
-        mshr = allocateWrite(pkt, pkt->getSize(), time);
-        return;
-    }
-
-    mshr = allocateMiss(pkt, blkSize, time);
-}
-
-MSHR*
-MissQueue::fetchBlock(Addr addr, int blk_size, Tick time,
-                      PacketPtr &target)
-{
-    Addr blkAddr = addr & ~(Addr)(blk_size - 1);
-    assert(mq.findMatch(addr) == NULL);
-    MSHR *mshr = mq.allocateFetch(blkAddr, blk_size, target);
-    mshr->order = order++;
-    mshr->pkt->flags |= CACHE_LINE_FILL;
-    if (mq.isFull()) {
-        cache->setBlocked(Blocked_NoMSHRs);
-    }
-    cache->requestMemSideBus(Request_MSHR, time);
-    return mshr;
-}
-
-PacketPtr
-MissQueue::getPacket()
-{
-    PacketPtr pkt = mq.getReq();
-    if (((wb.isFull() && wb.inServiceMSHRs == 0) || !pkt ||
-         pkt->time > curTick) && wb.havePending()) {
-        pkt = wb.getReq();
-        // Need to search for earlier miss.
-        MSHR *mshr = mq.findPending(pkt);
-        if (mshr && mshr->order < ((MSHR*)(pkt->senderState))->order) {
-            // Service misses in order until conflict is cleared.
-            return mq.getReq();
-        }
-    }
-    if (pkt) {
-        MSHR* mshr = wb.findPending(pkt);
-        if (mshr /*&& mshr->order < pkt->senderState->order*/) {
-            // The only way this happens is if we are
-            // doing a write and we didn't have permissions
-            // then subsequently saw a writeback(owned got evicted)
-            // We need to make sure to perform the writeback first
-            // To preserve the dirty data, then we can issue the write
-            return wb.getReq();
-        }
-    }
-    else if (!mq.isFull()){
-        //If we have a miss queue slot, we can try a prefetch
-        pkt = prefetcher->getPacket();
-        if (pkt) {
-            //Update statistic on number of prefetches issued (hwpf_mshr_misses)
-            mshr_misses[pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/]++;
-            //It will request the bus for the future, but should clear that immedieatley
-            allocateMiss(pkt, pkt->getSize(), curTick);
-            pkt = mq.getReq();
-            assert(pkt); //We should get back a req b/c we just put one in
-        }
-    }
-    return pkt;
-}
-
-void
-MissQueue::setBusCmd(PacketPtr &pkt, MemCmd cmd)
-{
-    assert(pkt->senderState != 0);
-    MSHR * mshr = (MSHR*)pkt->senderState;
-    mshr->originalCmd = pkt->cmd;
-    if (cmd == MemCmd::UpgradeReq || cmd == MemCmd::InvalidateReq) {
-        pkt->flags |= NO_ALLOCATE;
-        pkt->flags &= ~CACHE_LINE_FILL;
-    }
-    else if (!pkt->req->isUncacheable() && !pkt->isNoAllocate() &&
-             cmd.needsResponse()) {
-        pkt->flags |= CACHE_LINE_FILL;
-    }
-    if (pkt->isCacheFill() || pkt->isNoAllocate())
-        pkt->cmd = cmd;
-}
-
-void
-MissQueue::restoreOrigCmd(PacketPtr &pkt)
-{
-    pkt->cmd = ((MSHR*)(pkt->senderState))->originalCmd;
-}
-
-void
-MissQueue::markInService(PacketPtr &pkt, MSHR* mshr)
-{
-    bool unblock = false;
-    BlockedCause cause = NUM_BLOCKED_CAUSES;
-
-    /**
-     * @todo Should include MSHRQueue pointer in MSHR to select the correct
-     * one.
-     */
-    if ((!pkt->isCacheFill() && pkt->isWrite())) {
-        // Forwarding a write/ writeback, don't need to change
-        // the command
-        unblock = wb.isFull();
-        wb.markInService(mshr);
-        if (!wb.havePending()){
-            cache->deassertMemSideBusRequest(Request_WB);
-        }
-        if (unblock) {
-            // Do we really unblock?
-            unblock = !wb.isFull();
-            cause = Blocked_NoWBBuffers;
-        }
-    } else {
-        unblock = mq.isFull();
-        mq.markInService(mshr);
-        if (!mq.havePending()){
-            cache->deassertMemSideBusRequest(Request_MSHR);
-        }
-        if (mshr->originalCmd == MemCmd::HardPFReq) {
-            DPRINTF(HWPrefetch, "%s:Marking a HW_PF in service\n",
-                    cache->name());
-            //Also clear pending if need be
-            if (!prefetcher->havePending())
-            {
-                cache->deassertMemSideBusRequest(Request_PF);
-            }
-        }
-        if (unblock) {
-            unblock = !mq.isFull();
-            cause = Blocked_NoMSHRs;
-        }
-    }
-    if (unblock) {
-        cache->clearBlocked(cause);
-    }
-}
-
-
-void
-MissQueue::handleResponse(PacketPtr &pkt, Tick time)
-{
-    MSHR* mshr = (MSHR*)pkt->senderState;
-    if (((MSHR*)(pkt->senderState))->originalCmd == MemCmd::HardPFReq) {
-        DPRINTF(HWPrefetch, "%s:Handling the response to a HW_PF\n",
-                cache->name());
-    }
-#ifndef NDEBUG
-    int num_targets = mshr->getNumTargets();
-#endif
-
-    bool unblock = false;
-    bool unblock_target = false;
-    BlockedCause cause = NUM_BLOCKED_CAUSES;
-
-    if (pkt->isCacheFill() && !pkt->isNoAllocate()) {
-        mshr_miss_latency[mshr->originalCmd.toInt()][0/*pkt->req->getThreadNum()*/] +=
-            curTick - pkt->time;
-        // targets were handled in the cache tags
-        if (mshr == noTargetMSHR) {
-            // we always clear at least one target
-            unblock_target = true;
-            cause = Blocked_NoTargets;
-            noTargetMSHR = NULL;
-        }
-
-        if (mshr->hasTargets()) {
-            // Didn't satisfy all the targets, need to resend
-            MemCmd cmd = mshr->getTarget()->cmd;
-            mshr->pkt->setDest(Packet::Broadcast);
-            mshr->pkt->result = Packet::Unknown;
-            mshr->pkt->req = mshr->getTarget()->req;
-            mq.markPending(mshr, cmd);
-            mshr->order = order++;
-            cache->requestMemSideBus(Request_MSHR, time);
-        }
-        else {
-            unblock = mq.isFull();
-            mq.deallocate(mshr);
-            if (unblock) {
-                unblock = !mq.isFull();
-                cause = Blocked_NoMSHRs;
-            }
-        }
-    } else {
-        if (pkt->req->isUncacheable()) {
-            mshr_uncacheable_lat[pkt->cmd.toInt()][0/*pkt->req->getThreadNum()*/] +=
-                curTick - pkt->time;
-        }
-        if (mshr->hasTargets() && pkt->req->isUncacheable()) {
-            // Should only have 1 target if we had any
-            assert(num_targets == 1);
-            PacketPtr target = mshr->getTarget();
-            mshr->popTarget();
-            if (pkt->isRead()) {
-                memcpy(target->getPtr<uint8_t>(), pkt->getPtr<uint8_t>(),
-                       target->getSize());
-            }
-            cache->respond(target, time);
-            assert(!mshr->hasTargets());
-        }
-        else if (mshr->hasTargets()) {
-            //Must be a no_allocate with possibly more than one target
-            assert(mshr->pkt->isNoAllocate());
-            while (mshr->hasTargets()) {
-                PacketPtr target = mshr->getTarget();
-                mshr->popTarget();
-                if (pkt->isRead()) {
-                    memcpy(target->getPtr<uint8_t>(), pkt->getPtr<uint8_t>(),
-                           target->getSize());
-                }
-                cache->respond(target, time);
-            }
-        }
-
-        if (pkt->isWrite()) {
-            // If the wrtie buffer is full, we might unblock now
-            unblock = wb.isFull();
-            wb.deallocate(mshr);
-            if (unblock) {
-                // Did we really unblock?
-                unblock = !wb.isFull();
-                cause = Blocked_NoWBBuffers;
-            }
-        } else {
-            unblock = mq.isFull();
-            mq.deallocate(mshr);
-            if (unblock) {
-                unblock = !mq.isFull();
-                cause = Blocked_NoMSHRs;
-            }
-        }
-    }
-    if (unblock || unblock_target) {
-        cache->clearBlocked(cause);
-    }
-}
-
-void
-MissQueue::squash(int threadNum)
-{
-    bool unblock = false;
-    BlockedCause cause = NUM_BLOCKED_CAUSES;
-
-    if (noTargetMSHR && noTargetMSHR->threadNum == threadNum) {
-        noTargetMSHR = NULL;
-        unblock = true;
-        cause = Blocked_NoTargets;
-    }
-    if (mq.isFull()) {
-        unblock = true;
-        cause = Blocked_NoMSHRs;
-    }
-    mq.squash(threadNum);
-    if (!mq.havePending()) {
-        cache->deassertMemSideBusRequest(Request_MSHR);
-    }
-    if (unblock && !mq.isFull()) {
-        cache->clearBlocked(cause);
-    }
-
-}
-
-MSHR*
-MissQueue::findMSHR(Addr addr)
-{
-    return mq.findMatch(addr);
-}
-
-bool
-MissQueue::findWrites(Addr addr, vector<MSHR*> &writes)
-{
-    return wb.findMatches(addr,writes);
-}
-
-void
-MissQueue::doWriteback(Addr addr,
-                       int size, uint8_t *data, bool compressed)
-{
-    // Generate request
-    Request * req = new Request(addr, size, 0);
-    PacketPtr pkt = new Packet(req, MemCmd::Writeback, -1);
-    pkt->allocate();
-    if (data) {
-        memcpy(pkt->getPtr<uint8_t>(), data, size);
-    }
-
-    if (compressed) {
-        pkt->flags |= COMPRESSED;
-    }
-
-    ///All writebacks charged to same thread @todo figure this out
-    writebacks[0/*pkt->req->getThreadNum()*/]++;
-
-    allocateWrite(pkt, 0, curTick);
-}
-
-
-void
-MissQueue::doWriteback(PacketPtr &pkt)
-{
-    writebacks[0/*pkt->req->getThreadNum()*/]++;
-    allocateWrite(pkt, 0, curTick);
-}
-
-
-MSHR*
-MissQueue::allocateTargetList(Addr addr)
-{
-   MSHR* mshr = mq.allocateTargetList(addr, blkSize);
-   mshr->pkt->flags |= CACHE_LINE_FILL;
-   if (mq.isFull()) {
-       cache->setBlocked(Blocked_NoMSHRs);
-   }
-   return mshr;
-}
-
-bool
-MissQueue::havePending()
-{
-    return mq.havePending() || wb.havePending() || prefetcher->havePending();
-}
diff --git a/src/mem/cache/miss/miss_queue.hh b/src/mem/cache/miss/miss_queue.hh
deleted file mode 100644 (file)
index d3560ff..0000000
+++ /dev/null
@@ -1,327 +0,0 @@
-/*
- * Copyright (c) 2003-2005 The Regents of The University of Michigan
- * 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: Erik Hallnor
- */
-
-/**
- * @file
- * Miss and writeback queue declarations.
- */
-
-#ifndef __MISS_QUEUE_HH__
-#define __MISS_QUEUE_HH__
-
-#include <vector>
-
-#include "mem/cache/miss/miss_buffer.hh"
-#include "mem/cache/miss/mshr.hh"
-#include "mem/cache/miss/mshr_queue.hh"
-#include "base/statistics.hh"
-
-/**
- * Manages cache misses and writebacks. Contains MSHRs to store miss data
- * and the writebuffer for writes/writebacks.
- * @todo need to handle data on writes better (encapsulate).
- * @todo need to make replacements/writebacks happen in Cache::access
- */
-class MissQueue : public MissBuffer
-{
-  protected:
-    /** The MSHRs. */
-    MSHRQueue mq;
-    /** Write Buffer. */
-    MSHRQueue wb;
-
-    // PARAMTERS
-
-    /** The number of MSHRs in the miss queue. */
-    const int numMSHR;
-    /** The number of targets for each MSHR. */
-    const int numTarget;
-    /** The number of write buffers. */
-    const int writeBuffers;
-
-    /** Increasing order number assigned to each incoming request. */
-    uint64_t order;
-
-    bool prefetchMiss;
-
-    // Statistics
-    /**
-     * @addtogroup CacheStatistics
-     * @{
-     */
-    /** Number of misses that hit in the MSHRs per command and thread. */
-    Stats::Vector<> mshr_hits[MemCmd::NUM_MEM_CMDS];
-    /** Demand misses that hit in the MSHRs. */
-    Stats::Formula demandMshrHits;
-    /** Total number of misses that hit in the MSHRs. */
-    Stats::Formula overallMshrHits;
-
-    /** Number of misses that miss in the MSHRs, per command and thread. */
-    Stats::Vector<> mshr_misses[MemCmd::NUM_MEM_CMDS];
-    /** Demand misses that miss in the MSHRs. */
-    Stats::Formula demandMshrMisses;
-    /** Total number of misses that miss in the MSHRs. */
-    Stats::Formula overallMshrMisses;
-
-    /** Number of misses that miss in the MSHRs, per command and thread. */
-    Stats::Vector<> mshr_uncacheable[MemCmd::NUM_MEM_CMDS];
-    /** Total number of misses that miss in the MSHRs. */
-    Stats::Formula overallMshrUncacheable;
-
-    /** Total cycle latency of each MSHR miss, per command and thread. */
-    Stats::Vector<> mshr_miss_latency[MemCmd::NUM_MEM_CMDS];
-    /** Total cycle latency of demand MSHR misses. */
-    Stats::Formula demandMshrMissLatency;
-    /** Total cycle latency of overall MSHR misses. */
-    Stats::Formula overallMshrMissLatency;
-
-    /** Total cycle latency of each MSHR miss, per command and thread. */
-    Stats::Vector<> mshr_uncacheable_lat[MemCmd::NUM_MEM_CMDS];
-    /** Total cycle latency of overall MSHR misses. */
-    Stats::Formula overallMshrUncacheableLatency;
-
-    /** The total number of MSHR accesses per command and thread. */
-    Stats::Formula mshrAccesses[MemCmd::NUM_MEM_CMDS];
-    /** The total number of demand MSHR accesses. */
-    Stats::Formula demandMshrAccesses;
-    /** The total number of MSHR accesses. */
-    Stats::Formula overallMshrAccesses;
-
-    /** The miss rate in the MSHRs pre command and thread. */
-    Stats::Formula mshrMissRate[MemCmd::NUM_MEM_CMDS];
-    /** The demand miss rate in the MSHRs. */
-    Stats::Formula demandMshrMissRate;
-    /** The overall miss rate in the MSHRs. */
-    Stats::Formula overallMshrMissRate;
-
-    /** The average latency of an MSHR miss, per command and thread. */
-    Stats::Formula avgMshrMissLatency[MemCmd::NUM_MEM_CMDS];
-    /** The average latency of a demand MSHR miss. */
-    Stats::Formula demandAvgMshrMissLatency;
-    /** The average overall latency of an MSHR miss. */
-    Stats::Formula overallAvgMshrMissLatency;
-
-    /** The average latency of an MSHR miss, per command and thread. */
-    Stats::Formula avgMshrUncacheableLatency[MemCmd::NUM_MEM_CMDS];
-    /** The average overall latency of an MSHR miss. */
-    Stats::Formula overallAvgMshrUncacheableLatency;
-
-    /** The number of times a thread hit its MSHR cap. */
-    Stats::Vector<> mshr_cap_events;
-    /** The number of times software prefetches caused the MSHR to block. */
-    Stats::Vector<> soft_prefetch_mshr_full;
-
-    Stats::Scalar<> mshr_no_allocate_misses;
-
-    /**
-     * @}
-     */
-
-  private:
-    /** Pointer to the MSHR that has no targets. */
-    MSHR* noTargetMSHR;
-
-    /**
-     * Allocate a new MSHR to handle the provided miss.
-     * @param pkt The miss to buffer.
-     * @param size The number of bytes to fetch.
-     * @param time The time the miss occurs.
-     * @return A pointer to the new MSHR.
-     */
-    MSHR* allocateMiss(PacketPtr &pkt, int size, Tick time);
-
-    /**
-     * Allocate a new WriteBuffer to handle the provided write.
-     * @param pkt The write to handle.
-     * @param size The number of bytes to write.
-     * @param time The time the write occurs.
-     * @return A pointer to the new write buffer.
-     */
-    MSHR* allocateWrite(PacketPtr &pkt, int size, Tick time);
-
-  public:
-    /**
-     * Simple Constructor. Initializes all needed internal storage and sets
-     * parameters.
-     * @param numMSHRs The number of outstanding misses to handle.
-     * @param numTargets The number of outstanding targets to each miss.
-     * @param write_buffers The number of outstanding writes to handle.
-     * @param write_allocate If true, treat write misses the same as reads.
-     */
-    MissQueue(int numMSHRs, int numTargets, int write_buffers,
-              bool write_allocate, bool prefetch_miss);
-
-    /**
-     * Deletes all allocated internal storage.
-     */
-    ~MissQueue();
-
-    /**
-     * Register statistics for this object.
-     * @param name The name of the parent cache.
-     */
-    void regStats(const std::string &name);
-
-    /**
-     * Handle a cache miss properly. Either allocate an MSHR for the request,
-     * or forward it through the write buffer.
-     * @param pkt The request that missed in the cache.
-     * @param blk_size The block size of the cache.
-     * @param time The time the miss is detected.
-     */
-    void handleMiss(PacketPtr &pkt, int blk_size, Tick time);
-
-    /**
-     * Fetch the block for the given address and buffer the given target.
-     * @param addr The address to fetch.
-     * @param asid The address space of the address.
-     * @param blk_size The block size of the cache.
-     * @param time The time the miss is detected.
-     * @param target The target for the fetch.
-     */
-    MSHR* fetchBlock(Addr addr, int blk_size, Tick time,
-                     PacketPtr &target);
-
-    /**
-     * Selects a outstanding request to service.
-     * @return The request to service, NULL if none found.
-     */
-    PacketPtr getPacket();
-
-    /**
-     * Set the command to the given bus command.
-     * @param pkt The request to update.
-     * @param cmd The bus command to use.
-     */
-    void setBusCmd(PacketPtr &pkt, MemCmd cmd);
-
-    /**
-     * Restore the original command in case of a bus transmission error.
-     * @param pkt The request to reset.
-     */
-    void restoreOrigCmd(PacketPtr &pkt);
-
-    /**
-     * Marks a request as in service (sent on the bus). This can have side
-     * effect since storage for no response commands is deallocated once they
-     * are successfully sent.
-     * @param pkt The request that was sent on the bus.
-     */
-    void markInService(PacketPtr &pkt, MSHR* mshr);
-
-    /**
-     * Collect statistics and free resources of a satisfied request.
-     * @param pkt The request that has been satisfied.
-     * @param time The time when the request is satisfied.
-     */
-    void handleResponse(PacketPtr &pkt, Tick time);
-
-    /**
-     * Removes all outstanding requests for a given thread number. If a request
-     * has been sent to the bus, this function removes all of its targets.
-     * @param threadNum The thread number of the requests to squash.
-     */
-    void squash(int threadNum);
-
-    /**
-     * Return the current number of outstanding misses.
-     * @return the number of outstanding misses.
-     */
-    int getMisses()
-    {
-        return mq.getAllocatedTargets();
-    }
-
-    /**
-     * Searches for the supplied address in the miss queue.
-     * @param addr The address to look for.
-     * @param asid The address space id.
-     * @return The MSHR that contains the address, NULL if not found.
-     * @warning Currently only searches the miss queue. If non write allocate
-     * might need to search the write buffer for coherence.
-     */
-    MSHR* findMSHR(Addr addr);
-
-    /**
-     * Searches for the supplied address in the write buffer.
-     * @param addr The address to look for.
-     * @param asid The address space id.
-     * @param writes The list of writes that match the address.
-     * @return True if any writes are found
-     */
-    bool findWrites(Addr addr, std::vector<MSHR*>& writes);
-
-    /**
-     * Perform a writeback of dirty data to the given address.
-     * @param addr The address to write to.
-     * @param asid The address space id.
-     * @param xc The execution context of the address space.
-     * @param size The number of bytes to write.
-     * @param data The data to write, can be NULL.
-     * @param compressed True if the data is compressed.
-     */
-    void doWriteback(Addr addr,
-                     int size, uint8_t *data, bool compressed);
-
-    /**
-     * Perform the given writeback request.
-     * @param pkt The writeback request.
-     */
-    void doWriteback(PacketPtr &pkt);
-
-    /**
-     * Returns true if there are outstanding requests.
-     * @return True if there are outstanding requests.
-     */
-    bool havePending();
-
-    /**
-     * Add a target to the given MSHR. This assumes it is in the miss queue.
-     * @param mshr The mshr to add a target to.
-     * @param pkt The target to add.
-     */
-    void addTarget(MSHR *mshr, PacketPtr &pkt)
-    {
-        mq.allocateTarget(mshr, pkt);
-    }
-
-    /**
-     * Allocate a MSHR to hold a list of targets to a block involved in a copy.
-     * If the block is marked done then the MSHR already holds the data to
-     * fill the block. Otherwise the block needs to be fetched.
-     * @param addr The address to buffer.
-     * @param asid The address space ID.
-     * @return A pointer to the allocated MSHR.
-     */
-    MSHR* allocateTargetList(Addr addr);
-
-};
-
-#endif //__MISS_QUEUE_HH__
index 74dad658b4ed6a9baaf39649b548ce64282d5fd7..218d423393083981691e024ae70f8e97d72fd02a 100644 (file)
@@ -54,45 +54,20 @@ MSHR::MSHR()
 }
 
 void
-MSHR::allocate(MemCmd cmd, Addr _addr, int size,
-               PacketPtr &target)
+MSHR::allocate(Addr _addr, int _size, PacketPtr target, bool cacheFill)
 {
     addr = _addr;
-    if (target)
-    {
-        //Have a request, just use it
-        pkt = new Packet(target->req, cmd, Packet::Broadcast, size);
-        pkt->time = curTick;
-        pkt->allocate();
-        pkt->senderState = (Packet::SenderState *)this;
-        allocateTarget(target);
-    }
-    else
-    {
-        //need a request first
-        Request * req = new Request();
-        req->setPhys(addr, size, 0);
-        //Thread context??
-        pkt = new Packet(req, cmd, Packet::Broadcast, size);
-        pkt->time = curTick;
-        pkt->allocate();
-        pkt->senderState = (Packet::SenderState *)this;
-    }
-}
-
-// Since we aren't sure if data is being used, don't copy here.
-/**
- * @todo When we have a "global" data flag, might want to copy data here.
- */
-void
-MSHR::allocateAsBuffer(PacketPtr &target)
-{
-    addr = target->getAddr();
-    threadNum = 0/*target->req->getThreadNum()*/;
-    pkt = new Packet(target->req, target->cmd, -1);
-    pkt->allocate();
-    pkt->senderState = (Packet::SenderState*)this;
-    pkt->time = curTick;
+    size = _size;
+    assert(target);
+    isCacheFill = cacheFill;
+    needsExclusive = target->needsExclusive();
+    _isUncacheable = target->req->isUncacheable();
+    inService = false;
+    threadNum = 0;
+    ntargets = 1;
+    // Don't know of a case where we would allocate a new MSHR for a
+    // snoop (mem0-side request), so set cpuSide to true here.
+    targets.push_back(Target(target, true));
 }
 
 void
@@ -100,8 +75,6 @@ MSHR::deallocate()
 {
     assert(targets.empty());
     assert(ntargets == 0);
-    delete pkt;
-    pkt = NULL;
     inService = false;
     //allocIter = NULL;
     //readyIter = NULL;
@@ -111,16 +84,17 @@ MSHR::deallocate()
  * Adds a target to an MSHR
  */
 void
-MSHR::allocateTarget(PacketPtr &target)
+MSHR::allocateTarget(PacketPtr target, bool cpuSide)
 {
     //If we append an invalidate and we issued a read to the bus,
     //but now have some pending writes, we need to move
     //the invalidate to before the first non-read
-    if (inService && pkt->isRead() && target->isInvalidate()) {
-        std::list<PacketPtr> temp;
+    if (inService && !inServiceForExclusive && needsExclusive
+        && !cpuSide && target->isInvalidate()) {
+        std::list<Target> temp;
 
         while (!targets.empty()) {
-            if (!targets.front()->isRead()) break;
+            if (targets.front().pkt->needsExclusive()) break;
             //Place on top of temp stack
             temp.push_front(targets.front());
             //Remove from targets
@@ -129,7 +103,7 @@ MSHR::allocateTarget(PacketPtr &target)
 
         //Now that we have all the reads off until first non-read, we can
         //place the invalidate on
-        targets.push_front(target);
+        targets.push_front(Target(target, cpuSide));
 
         //Now we pop off the temp_stack and put them back
         while (!temp.empty()) {
@@ -138,22 +112,16 @@ MSHR::allocateTarget(PacketPtr &target)
         }
     }
     else {
-        targets.push_back(target);
+        targets.push_back(Target(target, cpuSide));
     }
 
     ++ntargets;
     assert(targets.size() == ntargets);
-    /**
-     * @todo really prioritize the target commands.
-     */
 
-    if (!inService && target->isWrite()) {
-        pkt->cmd = MemCmd::WriteReq;
-    }
+    needsExclusive = needsExclusive || target->needsExclusive();
 }
 
 
-
 void
 MSHR::dump()
 {
@@ -167,8 +135,8 @@ MSHR::dump()
     for (int i = 0; i < ntargets; i++) {
         assert(tar_it != targets.end());
 
-        ccprintf(cerr, "\t%d: Addr: %x cmd: %d\n",
-                 i, (*tar_it)->getAddr(), (*tar_it)->cmdToIndex());
+        ccprintf(cerr, "\t%d: Addr: %x cmd: %s\n",
+                 i, tar_it->pkt->getAddr(), tar_it->pkt->cmdString());
 
         tar_it++;
     }
@@ -177,6 +145,4 @@ MSHR::dump()
 
 MSHR::~MSHR()
 {
-    if (pkt)
-        pkt = NULL;
 }
index d0410acdaa8733dfed0f25760823696960571aa3..b38b69c52a863d70d50cb96492334006d510d348 100644 (file)
 #ifndef __MSHR_HH__
 #define __MSHR_HH__
 
-#include "mem/packet.hh"
 #include <list>
-#include <deque>
 
-class MSHR;
+#include "mem/packet.hh"
+
+class CacheBlk;
+class MSHRQueue;
 
 /**
  * Miss Status and handling Register. This class keeps all the information
  * needed to handle a cache miss including a list of target requests.
  */
-class MSHR {
+class MSHR : public Packet::SenderState
+{
+
   public:
+
+    class Target {
+      public:
+        Tick time;      //!< Time when request was received (for stats)
+        PacketPtr pkt;  //!< Pending request packet.
+        bool cpuSide;   //!< Did request come from cpu side or mem side?
+
+        bool isCpuSide() { return cpuSide; }
+
+        Target(PacketPtr _pkt, bool _cpuSide, Tick _time = curTick)
+            : time(_time), pkt(_pkt), cpuSide(_cpuSide)
+        {}
+    };
+
     /** Defines the Data structure of the MSHR targetlist. */
-    typedef std::list<PacketPtr> TargetList;
+    typedef std::list<Target> TargetList;
     /** Target list iterator. */
-    typedef std::list<PacketPtr>::iterator TargetListIterator;
+    typedef std::list<Target>::iterator TargetListIterator;
     /** A list of MSHRs. */
     typedef std::list<MSHR *> List;
     /** MSHR list iterator. */
@@ -59,20 +76,35 @@ class MSHR {
     /** MSHR list const_iterator. */
     typedef List::const_iterator ConstIterator;
 
-    /** Address of the miss. */
+    /** Pointer to queue containing this MSHR. */
+    MSHRQueue *queue;
+
+    /** Address of the request. */
     Addr addr;
-    /** Adress space id of the miss. */
-    short asid;
+
+    /** Size of the request. */
+    int size;
+
+    /** Data associated with the request (if a write). */
+    uint8_t *writeData;
+
     /** True if the request has been sent to the bus. */
     bool inService;
+
+    /** True if we will be putting the returned block in the cache */
+    bool isCacheFill;
+    /** True if we need to get an exclusive copy of the block. */
+    bool needsExclusive;
+    /** True if the request is uncacheable */
+    bool _isUncacheable;
+
+    /** True if the request that has been sent to the bus is for en
+     * exclusive copy. */
+    bool inServiceForExclusive;
     /** Thread number of the miss. */
-    int threadNum;
-    /** The request that is forwarded to the next level of the hierarchy. */
-    PacketPtr pkt;
+    short threadNum;
     /** The number of currently allocated targets. */
     short ntargets;
-    /** The original requesting command. */
-    MemCmd originalCmd;
     /** Order number of assigned by the miss queue. */
     uint64_t order;
 
@@ -81,6 +113,7 @@ class MSHR {
      * @sa MissQueue, MSHRQueue::readyList
      */
     Iterator readyIter;
+
     /**
      * Pointer to this MSHR on the allocated list.
      * @sa MissQueue, MSHRQueue::allocatedList
@@ -92,6 +125,9 @@ private:
     TargetList targets;
 
 public:
+
+    bool isUncacheable() { return _isUncacheable; }
+
     /**
      * Allocate a miss to this MSHR.
      * @param cmd The requesting command.
@@ -100,14 +136,13 @@ public:
      * @param size The number of bytes to request.
      * @param pkt  The original miss.
      */
-    void allocate(MemCmd cmd, Addr addr, int size,
-                  PacketPtr &pkt);
+    void allocate(Addr addr, int size, PacketPtr pkt, bool isFill);
 
     /**
      * Allocate this MSHR as a buffer for the given request.
      * @param target The memory request to buffer.
      */
-    void allocateAsBuffer(PacketPtr &target);
+    void allocateAsBuffer(PacketPtr target);
 
     /**
      * Mark this MSHR as free.
@@ -118,7 +153,7 @@ public:
      * Add a request to the list of targets.
      * @param target The target.
      */
-    void allocateTarget(PacketPtr &target);
+    void allocateTarget(PacketPtr target, bool cpuSide);
 
     /** A simple constructor. */
     MSHR();
@@ -131,7 +166,7 @@ public:
      */
     int getNumTargets()
     {
-        return(ntargets);
+        return ntargets;
     }
 
     /**
@@ -147,9 +182,9 @@ public:
      * Returns a reference to the first target.
      * @return A pointer to the first target.
      */
-    PacketPtr getTarget()
+    Target *getTarget()
     {
-        return targets.front();
+        return &targets.front();
     }
 
     /**
index e9aa89bf8409970c495a98d8c3ef33c3be92b20c..d58594798eae4c2c3a72162d592da5814779f14a 100644 (file)
  */
 
 /** @file
- * Definition of the MSHRQueue.
+ * Definition of MSHRQueue class functions.
  */
 
 #include "mem/cache/miss/mshr_queue.hh"
-#include "sim/eventq.hh"
 
 using namespace std;
 
-MSHRQueue::MSHRQueue(int num_mshrs, int reserve)
-    : numMSHRs(num_mshrs + reserve - 1), numReserve(reserve)
+MSHRQueue::MSHRQueue(int num_entries, int reserve)
+    : numEntries(num_entries + reserve - 1), numReserve(reserve)
 {
     allocated = 0;
-    inServiceMSHRs = 0;
-    allocatedTargets = 0;
-    registers = new MSHR[numMSHRs];
-    for (int i = 0; i < numMSHRs; ++i) {
+    inServiceEntries = 0;
+    registers = new MSHR[numEntries];
+    for (int i = 0; i < numEntries; ++i) {
+        registers[i].queue = this;
         freeList.push_back(&registers[i]);
     }
 }
@@ -54,7 +53,7 @@ MSHRQueue::~MSHRQueue()
     delete [] registers;
 }
 
-MSHR*
+MSHR *
 MSHRQueue::findMatch(Addr addr) const
 {
     MSHR::ConstIterator i = allocatedList.begin();
@@ -87,19 +86,19 @@ MSHRQueue::findMatches(Addr addr, vector<MSHR*>& matches) const
 
 }
 
-MSHR*
-MSHRQueue::findPending(PacketPtr &pkt) const
+MSHR *
+MSHRQueue::findPending(Addr addr, int size) const
 {
     MSHR::ConstIterator i = pendingList.begin();
     MSHR::ConstIterator end = pendingList.end();
     for (; i != end; ++i) {
         MSHR *mshr = *i;
-        if (mshr->addr < pkt->getAddr()) {
-            if (mshr->addr + mshr->pkt->getSize() > pkt->getAddr()) {
+        if (mshr->addr < addr) {
+            if (mshr->addr + mshr->size > addr) {
                 return mshr;
             }
         } else {
-            if (pkt->getAddr() + pkt->getSize() > mshr->addr) {
+            if (addr + size > mshr->addr) {
                 return mshr;
             }
         }
@@ -107,21 +106,15 @@ MSHRQueue::findPending(PacketPtr &pkt) const
     return NULL;
 }
 
-MSHR*
-MSHRQueue::allocate(PacketPtr &pkt, int size)
+MSHR *
+MSHRQueue::allocate(Addr addr, int size, PacketPtr &pkt, bool isFill)
 {
-    Addr aligned_addr = pkt->getAddr() & ~((Addr)size - 1);
     assert(!freeList.empty());
     MSHR *mshr = freeList.front();
     assert(mshr->getNumTargets() == 0);
     freeList.pop_front();
 
-    if (!pkt->needsResponse()) {
-        mshr->allocateAsBuffer(pkt);
-    } else {
-        mshr->allocate(pkt->cmd, aligned_addr, size, pkt);
-        allocatedTargets += 1;
-    }
+    mshr->allocate(addr, size, pkt, isFill);
     mshr->allocIter = allocatedList.insert(allocatedList.end(), mshr);
     mshr->readyIter = pendingList.insert(pendingList.end(), mshr);
 
@@ -129,51 +122,21 @@ MSHRQueue::allocate(PacketPtr &pkt, int size)
     return mshr;
 }
 
-MSHR*
-MSHRQueue::allocateFetch(Addr addr, int size, PacketPtr &target)
-{
-    MSHR *mshr = freeList.front();
-    assert(mshr->getNumTargets() == 0);
-    freeList.pop_front();
-    mshr->allocate(MemCmd::ReadReq, addr, size, target);
-    mshr->allocIter = allocatedList.insert(allocatedList.end(), mshr);
-    mshr->readyIter = pendingList.insert(pendingList.end(), mshr);
-
-    allocated += 1;
-    return mshr;
-}
-
-MSHR*
-MSHRQueue::allocateTargetList(Addr addr, int size)
-{
-    MSHR *mshr = freeList.front();
-    assert(mshr->getNumTargets() == 0);
-    freeList.pop_front();
-    PacketPtr dummy;
-    mshr->allocate(MemCmd::ReadReq, addr, size, dummy);
-    mshr->allocIter = allocatedList.insert(allocatedList.end(), mshr);
-    mshr->inService = true;
-    ++inServiceMSHRs;
-    ++allocated;
-    return mshr;
-}
-
 
 void
-MSHRQueue::deallocate(MSHRmshr)
+MSHRQueue::deallocate(MSHR *mshr)
 {
     deallocateOne(mshr);
 }
 
 MSHR::Iterator
-MSHRQueue::deallocateOne(MSHRmshr)
+MSHRQueue::deallocateOne(MSHR *mshr)
 {
     MSHR::Iterator retval = allocatedList.erase(mshr->allocIter);
     freeList.push_front(mshr);
     allocated--;
-    allocatedTargets -= mshr->getNumTargets();
     if (mshr->inService) {
-        inServiceMSHRs--;
+        inServiceEntries--;
     } else {
         pendingList.erase(mshr->readyIter);
     }
@@ -192,29 +155,29 @@ MSHRQueue::moveToFront(MSHR *mshr)
 }
 
 void
-MSHRQueue::markInService(MSHRmshr)
+MSHRQueue::markInService(MSHR *mshr)
 {
     //assert(mshr == pendingList.front());
+#if 0
     if (!mshr->pkt->needsResponse() && !(mshr->pkt->cmd == MemCmd::UpgradeReq)) {
         assert(mshr->getNumTargets() == 0);
         deallocate(mshr);
         return;
     }
+#endif
     mshr->inService = true;
     pendingList.erase(mshr->readyIter);
     //mshr->readyIter = NULL;
-    inServiceMSHRs += 1;
+    inServiceEntries += 1;
     //pendingList.pop_front();
 }
 
 void
-MSHRQueue::markPending(MSHR* mshr, MemCmd cmd)
+MSHRQueue::markPending(MSHR *mshr)
 {
     //assert(mshr->readyIter == NULL);
-    mshr->pkt->cmd = cmd;
-    mshr->pkt->flags &= ~SATISFIED;
     mshr->inService = false;
-    --inServiceMSHRs;
+    --inServiceEntries;
     /**
      * @ todo might want to add rerequests to front of pending list for
      * performance.
@@ -231,11 +194,8 @@ MSHRQueue::squash(int threadNum)
         MSHR *mshr = *i;
         if (mshr->threadNum == threadNum) {
             while (mshr->hasTargets()) {
-                PacketPtr target = mshr->getTarget();
                 mshr->popTarget();
-
                 assert(0/*target->req->getThreadNum()*/ == threadNum);
-                target = NULL;
             }
             assert(!mshr->hasTargets());
             assert(mshr->ntargets==0);
index 5069db6616cbfd4e86fa315148a3572446a81329..182dfd5b21bca956893362f4e96d4719fa70f670 100644 (file)
  * Declaration of a structure to manage MSHRs.
  */
 
-#ifndef __MSHR_QUEUE_HH__
-#define __MSHR_QUEUE_HH__
+#ifndef __MEM__CACHE__MISS__MSHR_QUEUE_HH__
+#define __MEM__CACHE__MISS__MSHR_QUEUE_HH__
 
 #include <vector>
+
+#include "mem/packet.hh"
 #include "mem/cache/miss/mshr.hh"
 
 /**
  * A Class for maintaining a list of pending and allocated memory requests.
  */
-class MSHRQueue {
+class MSHRQueue
+{
   private:
     /**  MSHR storage. */
-    MSHRregisters;
-    /** Holds pointers to all allocated MSHRs. */
+    MSHR *registers;
+    /** Holds pointers to all allocated entries. */
     MSHR::List allocatedList;
-    /** Holds pointers to MSHRs that haven't been sent to the bus. */
+    /** Holds pointers to entries that haven't been sent to the bus. */
     MSHR::List pendingList;
-    /** Holds non allocated MSHRs. */
+    /** Holds non allocated entries. */
     MSHR::List freeList;
 
     // Parameters
     /**
-     * The total number of MSHRs in this queue. This number is set as the
-     * number of MSHRs requested plus (numReserve - 1). This allows for
-     * the same number of effective MSHRs while still maintaining the reserve.
+     * The total number of entries in this queue. This number is set as the
+     * number of entries requested plus (numReserve - 1). This allows for
+     * the same number of effective entries while still maintaining the reserve.
      */
-    const int numMSHRs;
+    const int numEntries;
 
     /**
-     * The number of MSHRs to hold in reserve. This is needed because copy
-     * operations can allocate upto 4 MSHRs at one time.
+     * The number of entries to hold in reserve. This is needed because copy
+     * operations can allocate upto 4 entries at one time.
      */
     const int numReserve;
 
   public:
-    /** The number of allocated MSHRs. */
+    /** The number of allocated entries. */
     int allocated;
-    /** The number of MSHRs that have been forwarded to the bus. */
-    int inServiceMSHRs;
-    /** The number of targets waiting for response. */
-    int allocatedTargets;
+    /** The number of entries that have been forwarded to the bus. */
+    int inServiceEntries;
 
     /**
-     * Create a queue with a given number of MSHRs.
-     * @param num_mshrs The number of MSHRs in this queue.
-     * @param reserve The minimum number of MSHRs needed to satisfy any access.
+     * Create a queue with a given number of entries.
+     * @param num_entrys The number of entries in this queue.
+     * @param reserve The minimum number of entries needed to satisfy
+     * any access.
      */
-    MSHRQueue(int num_mshrs, int reserve = 1);
+    MSHRQueue(int num_entries, int reserve = 1);
 
     /** Destructor */
     ~MSHRQueue();
 
     /**
-     * Find the first MSHR that matches the provide address and asid.
+     * Find the first MSHR that matches the provided address.
      * @param addr The address to find.
-     * @param asid The address space id.
      * @return Pointer to the matching MSHR, null if not found.
      */
-    MSHRfindMatch(Addr addr) const;
+    MSHR *findMatch(Addr addr) const;
 
     /**
-     * Find and return all the matching MSHRs in the provided vector.
+     * Find and return all the matching entries in the provided vector.
      * @param addr The address to find.
-     * @param asid The address space ID.
-     * @param matches The vector to return pointers to the matching MSHRs.
+     * @param matches The vector to return pointers to the matching entries.
      * @return True if any matches are found, false otherwise.
      * @todo Typedef the vector??
      */
@@ -107,7 +107,7 @@ class MSHRQueue {
      * @param pkt The request to find.
      * @return A pointer to the earliest matching MSHR.
      */
-    MSHR* findPending(PacketPtr &pkt) const;
+    MSHR *findPending(Addr addr, int size) const;
 
     /**
      * Allocates a new MSHR for the request and size. This places the request
@@ -116,60 +116,29 @@ class MSHRQueue {
      * @param size The number in bytes to fetch from memory.
      * @return The a pointer to the MSHR allocated.
      *
-     * @pre There are free MSHRs.
+     * @pre There are free entries.
      */
-    MSHR* allocate(PacketPtr &pkt, int size = 0);
-
-    /**
-     * Allocate a read request for the given address, and places the given
-     * target on the target list.
-     * @param addr The address to fetch.
-     * @param asid The address space for the fetch.
-     * @param size The number of bytes to request.
-     * @param target The first target for the request.
-     * @return Pointer to the new MSHR.
-     */
-    MSHR* allocateFetch(Addr addr, int size, PacketPtr &target);
-
-    /**
-     * Allocate a target list for the given address.
-     * @param addr The address to fetch.
-     * @param asid The address space for the fetch.
-     * @param size The number of bytes to request.
-     * @return Pointer to the new MSHR.
-     */
-    MSHR* allocateTargetList(Addr addr, int size);
+    MSHR *allocate(Addr addr, int size, PacketPtr &pkt, bool isFill);
 
     /**
      * Removes the given MSHR from the queue. This places the MSHR on the
      * free list.
      * @param mshr
      */
-    void deallocate(MSHR* mshr);
-
-    /**
-     * Allocates a target to the given MSHR. Used to keep track of the number
-     * of outstanding targets.
-     * @param mshr The MSHR to allocate the target to.
-     * @param pkt The target request.
-     */
-    void allocateTarget(MSHR* mshr, PacketPtr &pkt)
-    {
-        mshr->allocateTarget(pkt);
-        allocatedTargets += 1;
-    }
+    void deallocate(MSHR *mshr);
 
     /**
-     * Remove a MSHR from the queue. Returns an iterator into the allocatedList
-     * for faster squash implementation.
+     * Remove a MSHR from the queue. Returns an iterator into the
+     * allocatedList for faster squash implementation.
      * @param mshr The MSHR to remove.
      * @return An iterator to the next entry in the allocatedList.
      */
-    MSHR::Iterator deallocateOne(MSHRmshr);
+    MSHR::Iterator deallocateOne(MSHR *mshr);
 
     /**
-     * Moves the MSHR to the front of the pending list if it is not in service.
-     * @param mshr The mshr to move.
+     * Moves the MSHR to the front of the pending list if it is not
+     * in service.
+     * @param mshr The entry to move.
      */
     void moveToFront(MSHR *mshr);
 
@@ -178,14 +147,13 @@ class MSHRQueue {
      * pendingList. Deallocates the MSHR if it does not expect a response.
      * @param mshr The MSHR to mark in service.
      */
-    void markInService(MSHRmshr);
+    void markInService(MSHR *mshr);
 
     /**
-     * Mark an in service mshr as pending, used to resend a request.
+     * Mark an in service entry as pending, used to resend a request.
      * @param mshr The MSHR to resend.
-     * @param cmd The command to resend.
      */
-    void markPending(MSHR* mshr, MemCmd cmd);
+    void markPending(MSHR *mshr);
 
     /**
      * Squash outstanding requests with the given thread number. If a request
@@ -204,36 +172,25 @@ class MSHRQueue {
     }
 
     /**
-     * Returns true if there are no free MSHRs.
+     * Returns true if there are no free entries.
      * @return True if this queue is full.
      */
     bool isFull() const
     {
-        return (allocated > numMSHRs - numReserve);
+        return (allocated > numEntries - numReserve);
     }
 
     /**
-     * Returns the request at the head of the pendingList.
+     * Returns the MSHR at the head of the pendingList.
      * @return The next request to service.
      */
-    PacketPtr getReq() const
+    MSHR *getNextMSHR() const
     {
         if (pendingList.empty()) {
             return NULL;
         }
-        MSHR* mshr = pendingList.front();
-        return mshr->pkt;
+        return pendingList.front();
     }
-
-    /**
-     * Returns the number of outstanding targets.
-     * @return the number of allocated targets.
-     */
-    int getAllocatedTargets() const
-    {
-        return allocatedTargets;
-    }
-
 };
 
-#endif //__MSHR_QUEUE_HH__
+#endif //__MEM__CACHE__MISS__MSHR_QUEUE_HH__
index 966f7d005aa719815d976f88efc79f86b2398ddf..d03cfe3ae2927adf27e20fe1ab1862c318d2b412 100644 (file)
@@ -241,7 +241,6 @@ BasePrefetcher::handleMiss(PacketPtr &pkt, Tick time)
             }
 
             pf.push_back(prefetch);
-            prefetch->flags |= CACHE_LINE_FILL;
 
             //Make sure to request the bus, with proper delay
             cache->requestMemSideBus(Request_PF, prefetch->time);
index 42a1fe34fa90a495bc0a4cad1f1572571b4247e9..607e89a75093f0bc4de2810b33dec61f8db8993a 100644 (file)
@@ -215,14 +215,13 @@ FALRU::findBlock(Addr addr) const
 }
 
 FALRUBlk*
-FALRU::findReplacement(PacketPtr &pkt, PacketList &writebacks,
-                       BlkList &compress_blocks)
+FALRU::findReplacement(Addr addr, PacketList &writebacks)
 {
     FALRUBlk * blk = tail;
     assert(blk->inCache == 0);
     moveToHead(blk);
     tagHash.erase(blk->tag);
-    tagHash[blkAlign(pkt->getAddr())] = blk;
+    tagHash[blkAlign(addr)] = blk;
     if (blk->isValid()) {
         replacements[0]++;
     } else {
index dabbda7407e5593a9f8cae309888913514748f43..8cbc798130f22a35508b00626ad4146b041f0ad8 100644 (file)
@@ -201,11 +201,9 @@ public:
      * Find a replacement block for the address provided.
      * @param pkt The request to a find a replacement candidate for.
      * @param writebacks List for any writebacks to be performed.
-     * @param compress_blocks List of blocks to compress, for adaptive comp.
      * @return The block to place the replacement in.
      */
-    FALRUBlk* findReplacement(PacketPtr &pkt, PacketList & writebacks,
-                              BlkList &compress_blocks);
+    FALRUBlk* findReplacement(Addr addr, PacketList & writebacks);
 
     /**
      * Return the hit latency of this cache.
@@ -248,10 +246,9 @@ public:
      * Generate the tag from the addres. For fully associative this is just the
      * block address.
      * @param addr The address to get the tag from.
-     * @param blk ignored here
      * @return The tag.
      */
-    Addr extractTag(Addr addr, FALRUBlk *blk) const
+    Addr extractTag(Addr addr) const
     {
         return blkAlign(addr);
     }
index 9c802d0dc69db44a5cdce206534bf0fa436c30f0..2f95cdb0f05bdd7aef1ceccb0ba462132ce7c01c 100644 (file)
@@ -303,11 +303,10 @@ IIC::findBlock(Addr addr) const
 
 
 IICTag*
-IIC::findReplacement(PacketPtr &pkt, PacketList &writebacks,
-                     BlkList &compress_blocks)
+IIC::findReplacement(Addr addr, PacketList &writebacks)
 {
-    DPRINTF(IIC, "Finding Replacement for %x\n", pkt->getAddr());
-    unsigned set = hash(pkt->getAddr());
+    DPRINTF(IIC, "Finding Replacement for %x\n", addr);
+    unsigned set = hash(addr);
     IICTag *tag_ptr;
     unsigned long *tmp_data = new unsigned long[numSub];
 
@@ -332,12 +331,14 @@ IIC::findReplacement(PacketPtr &pkt, PacketList &writebacks,
 
     list<unsigned long> tag_indexes;
     repl->doAdvance(tag_indexes);
+/*
     while (!tag_indexes.empty()) {
         if (!tagStore[tag_indexes.front()].isCompressed()) {
             compress_blocks.push_back(&tagStore[tag_indexes.front()]);
         }
         tag_indexes.pop_front();
     }
+*/
 
     tag_ptr->re = (void*)repl->add(tag_ptr-tagStore);
 
@@ -355,7 +356,7 @@ IIC::freeReplacementBlock(PacketList & writebacks)
 
     DPRINTF(Cache, "Replacing %x in IIC: %s\n",
             regenerateBlkAddr(tag_ptr->tag,0),
-            tag_ptr->isModified() ? "writeback" : "clean");
+            tag_ptr->isDirty() ? "writeback" : "clean");
     /* write back replaced block data */
     if (tag_ptr && (tag_ptr->isValid())) {
         replacements[0]++;
@@ -363,7 +364,7 @@ IIC::freeReplacementBlock(PacketList & writebacks)
         ++sampledRefs;
         tag_ptr->refCount = 0;
 
-        if (tag_ptr->isModified()) {
+        if (tag_ptr->isDirty()) {
 /*         PacketPtr writeback =
                 buildWritebackReq(regenerateBlkAddr(tag_ptr->tag, 0),
                                   tag_ptr->req->asid, tag_ptr->xc, blkSize,
@@ -618,24 +619,6 @@ IIC::secondaryChain(Addr tag, unsigned long chain_ptr,
     return NULL;
 }
 
-void
-IIC::decompressBlock(unsigned long index)
-{
-    IICTag *tag_ptr = &tagStore[index];
-    if (tag_ptr->isCompressed()) {
-        // decompress the data here.
-    }
-}
-
-void
-IIC::compressBlock(unsigned long index)
-{
-    IICTag *tag_ptr = &tagStore[index];
-    if (!tag_ptr->isCompressed()) {
-        // Compress the data here.
-    }
-}
-
 void
 IIC::invalidateBlk(IIC::BlkType *tag_ptr)
 {
@@ -672,7 +655,6 @@ void
 IIC::writeData(IICTag *blk, uint8_t *write_data, int size,
                PacketList & writebacks)
 {
-    assert(size < blkSize || !blk->isCompressed());
     DPRINTF(IIC, "Writing %d bytes to %x\n", size,
             blk->tag<<tagShift);
     // Find the number of subblocks needed, (round up)
index d0663d3301af9e5e1e953df809fe4864af988503..082b3d15eaae7241d9ab16c25bfd4011c443b834 100644 (file)
@@ -345,17 +345,6 @@ class IIC : public BaseTags
         return hitLatency;
     }
 
-    /**
-     * Generate the tag from the address.
-     * @param addr The address to a get a tag for.
-     * @param blk Ignored here.
-     * @return the tag.
-     */
-    Addr extractTag(Addr addr, IICTag *blk) const
-    {
-        return (addr >> tagShift);
-    }
-
      /**
      * Generate the tag from the address.
      * @param addr The address to a get a tag for.
@@ -422,18 +411,6 @@ class IIC : public BaseTags
         return tmp;
     }
 
-    /**
-     * Decompress a block if it is compressed.
-     * @param index The tag store index for the block to uncompress.
-     */
-    void decompressBlock(unsigned long index);
-
-    /**
-     * Try and compress a block if it is not already compressed.
-     * @param index The tag store index for the block to compress.
-     */
-    void compressBlock(unsigned long index);
-
     /**
      * Invalidate a block.
      * @param blk The block to invalidate.
@@ -462,11 +439,9 @@ class IIC : public BaseTags
      * Find a replacement block for the address provided.
      * @param pkt The request to a find a replacement candidate for.
      * @param writebacks List for any writebacks to be performed.
-     * @param compress_blocks List of blocks to compress, for adaptive comp.
      * @return The block to place the replacement in.
      */
-    IICTag* findReplacement(PacketPtr &pkt, PacketList &writebacks,
-                            BlkList &compress_blocks);
+    IICTag* findReplacement(Addr addr, PacketList &writebacks);
 
     /**
      * Read the data from the internal storage of the given cache block.
index 8e87797744c5582294a29260f68650a2ab8bbb35..334312aaf04d0f0ff20bcf92ee055690843080f3 100644 (file)
@@ -194,10 +194,9 @@ LRU::findBlock(Addr addr) const
 }
 
 LRUBlk*
-LRU::findReplacement(PacketPtr &pkt, PacketList &writebacks,
-                     BlkList &compress_blocks)
+LRU::findReplacement(Addr addr, PacketList &writebacks)
 {
-    unsigned set = extractSet(pkt->getAddr());
+    unsigned set = extractSet(addr);
     // grab a replacement candidate
     LRUBlk *blk = sets[set].blks[assoc-1];
     sets[set].moveToHead(blk);
index 75272544c4d7fe469fabbbbf67732a85ff33a8d6..26038d709029ab2bdedf127840a323998211b259 100644 (file)
@@ -189,11 +189,9 @@ public:
      * Find a replacement block for the address provided.
      * @param pkt The request to a find a replacement candidate for.
      * @param writebacks List for any writebacks to be performed.
-     * @param compress_blocks List of blocks to compress, for adaptive comp.
      * @return The block to place the replacement in.
      */
-    LRUBlk* findReplacement(PacketPtr &pkt, PacketList &writebacks,
-                            BlkList &compress_blocks);
+    LRUBlk* findReplacement(Addr addr, PacketList &writebacks);
 
     /**
      * Generate the tag from the given address.
@@ -205,17 +203,6 @@ public:
         return (addr >> tagShift);
     }
 
-   /**
-     * Generate the tag from the given address.
-     * @param addr The address to get the tag from.
-     * @param blk Ignored.
-     * @return The tag of the address.
-     */
-    Addr extractTag(Addr addr, LRUBlk *blk) const
-    {
-        return (addr >> tagShift);
-    }
-
     /**
      * Calculate the set index from the address.
      * @param addr The address to get the set from.
index 5ac87eaba150a177f58357d0c41bc57cf8598d1c..e22ccbb96223ea59a8f00d86d7c3d760f0a5691e 100644 (file)
@@ -298,27 +298,25 @@ Split::findBlock(Addr addr) const
 }
 
 SplitBlk*
-Split::findReplacement(PacketPtr &pkt, PacketList &writebacks,
-                     BlkList &compress_blocks)
+Split::findReplacement(Addr addr, PacketList &writebacks)
 {
     SplitBlk *blk;
 
+    assert(0);
+#if 0
     if (pkt->nic_pkt()) {
         DPRINTF(Split, "finding a replacement for nic_req\n");
         nic_repl++;
         if (lifo && lifo_net)
-            blk = lifo_net->findReplacement(pkt, writebacks,
-                                             compress_blocks);
+            blk = lifo_net->findReplacement(addr, writebacks);
         else if (lru_net)
-            blk = lru_net->findReplacement(pkt, writebacks,
-                                            compress_blocks);
+            blk = lru_net->findReplacement(addr, writebacks);
         // in this case, this is an LRU only cache, it's non partitioned
         else
-            blk = lru->findReplacement(pkt, writebacks, compress_blocks);
+            blk = lru->findReplacement(addr, writebacks);
     } else {
         DPRINTF(Split, "finding replacement for cpu_req\n");
-        blk = lru->findReplacement(pkt, writebacks,
-                                    compress_blocks);
+        blk = lru->findReplacement(addr, writebacks);
         cpu_repl++;
     }
 
@@ -346,6 +344,7 @@ Split::findReplacement(PacketPtr &pkt, PacketList &writebacks,
     // blk attributes for the new blk coming IN
     blk->ts = curTick;
     blk->isNIC = (pkt->nic_pkt()) ? true : false;
+#endif
 
     return blk;
 }
@@ -400,8 +399,13 @@ Split::regenerateBlkAddr(Addr tag, int set) const
 }
 
 Addr
-Split::extractTag(Addr addr, SplitBlk *blk) const
+Split::extractTag(Addr addr) const
 {
+    // need to fix this if we want to use it... old interface of
+    // passing in blk was too weird
+    assert(0);
+    return 0;
+/*
     if (blk->part == 2) {
         if (lifo_net)
             return lifo_net->extractTag(addr);
@@ -411,5 +415,6 @@ Split::extractTag(Addr addr, SplitBlk *blk) const
             panic("this shouldn't happen");
     } else
         return lru->extractTag(addr);
+*/
 }
 
index 840b689403fe5c2c6b82fc437b1e44fb3c38b18b..ab48ce769ebb4fade4fae7d9ae99ef8ad5350d5c 100644 (file)
@@ -212,20 +212,17 @@ class Split : public BaseTags
      * Find a replacement block for the address provided.
      * @param pkt The request to a find a replacement candidate for.
      * @param writebacks List for any writebacks to be performed.
-     * @param compress_blocks List of blocks to compress, for adaptive comp.
      * @return The block to place the replacement in.
      */
-    SplitBlk* findReplacement(PacketPtr &pkt, PacketList &writebacks,
-                            BlkList &compress_blocks);
+    SplitBlk* findReplacement(Addr addr, PacketList &writebacks);
 
 
     /**
      * Generate the tag from the given address.
      * @param addr The address to get the tag from.
-     * @param blk The block to find the partition it's in
      * @return The tag of the address.
      */
-    Addr extractTag(Addr addr, SplitBlk *blk) const;
+    Addr extractTag(Addr addr) const;
 
     /**
      * Calculate the set index from the address.
index d71d1a3efde25d1ad33ced9ef779017f801264ed..4ee2473a44be60af0a3c991ddd0a014cac164701 100644 (file)
@@ -266,10 +266,9 @@ SplitLIFO::findBlock(Addr addr) const
 }
 
 SplitBlk*
-SplitLIFO::findReplacement(PacketPtr &pkt, PacketList &writebacks,
-                           BlkList &compress_blocks)
+SplitLIFO::findReplacement(Addr addr, PacketList &writebacks)
 {
-    unsigned set = extractSet(pkt->getAddr());
+    unsigned set = extractSet(addr);
 
     SplitBlk *firstIn = sets[set].firstIn;
     SplitBlk *lastIn = sets[set].lastIn;
@@ -289,7 +288,7 @@ SplitLIFO::findReplacement(PacketPtr &pkt, PacketList &writebacks,
     }
 
     DPRINTF(Split, "just assigned %#x addr into LIFO, replacing %#x status %#x\n",
-            pkt->getAddr(), regenerateBlkAddr(blk->tag, set), blk->status);
+            addr, regenerateBlkAddr(blk->tag, set), blk->status);
     if (blk->isValid()) {
         replacements[0]++;
         totalRefs += blk->refCount;
index 0f8adf18d344987879e93c7b1dd3998f0ffdd16b..13ccf7ef407dc34aa7084665e164070d221b661c 100644 (file)
@@ -212,11 +212,9 @@ public:
      * Find a replacement block for the address provided.
      * @param pkt The request to a find a replacement candidate for.
      * @param writebacks List for any writebacks to be performed.
-     * @param compress_blocks List of blocks to compress, for adaptive comp.
      * @return The block to place the replacement in.
      */
-    SplitBlk* findReplacement(PacketPtr &pkt, PacketList &writebacks,
-                            BlkList &compress_blocks);
+    SplitBlk* findReplacement(Addr addr, PacketList &writebacks);
 
     /**
      * Generate the tag from the given address.
@@ -228,17 +226,6 @@ public:
         return (addr >> tagShift);
     }
 
-     /**
-     * Generate the tag from the given address.
-     * @param addr The address to get the tag from.
-     * @param blk Ignored
-     * @return The tag of the address.
-     */
-    Addr extractTag(Addr addr, SplitBlk *blk) const
-    {
-        return (addr >> tagShift);
-    }
-
    /**
      * Calculate the set index from the address.
      * @param addr The address to get the set from.
index 7227fb5c19ff2672ebc171595729608551077b11..4d271a92ad9b5db54d54cc36052057cdee0974ad 100644 (file)
@@ -213,10 +213,9 @@ SplitLRU::findBlock(Addr addr) const
 }
 
 SplitBlk*
-SplitLRU::findReplacement(PacketPtr &pkt, PacketList &writebacks,
-                     BlkList &compress_blocks)
+SplitLRU::findReplacement(Addr addr, PacketList &writebacks)
 {
-    unsigned set = extractSet(pkt->getAddr());
+    unsigned set = extractSet(addr);
     // grab a replacement candidate
     SplitBlk *blk = sets[set].blks[assoc-1];
     sets[set].moveToHead(blk);
index eb65445ea72a8263f2cfe0a075fd5116ed37001c..a708ef740ad8759d456a4bb4af650c2d4b7e2f1b 100644 (file)
@@ -195,11 +195,9 @@ public:
      * Find a replacement block for the address provided.
      * @param pkt The request to a find a replacement candidate for.
      * @param writebacks List for any writebacks to be performed.
-     * @param compress_blocks List of blocks to compress, for adaptive comp.
      * @return The block to place the replacement in.
      */
-    SplitBlk* findReplacement(PacketPtr &pkt, PacketList &writebacks,
-                            BlkList &compress_blocks);
+    SplitBlk* findReplacement(Addr addr, PacketList &writebacks);
 
     /**
      * Generate the tag from the given address.
@@ -211,17 +209,6 @@ public:
         return (addr >> tagShift);
     }
 
-    /**
-     * Generate the tag from the given address.
-     * @param addr The address to get the tag from.
-     * @param blk Ignored.
-     * @return The tag of the address.
-     */
-    Addr extractTag(Addr addr, SplitBlk *blk) const
-    {
-        return (addr >> tagShift);
-    }
-
     /**
      * Calculate the set index from the address.
      * @param addr The address to get the set from.
index a257e16ab3f39715cd3f6b1417639dd75b263c1c..57c6a638125bebb4beb1ad692fba87a7d3f3bdc0 100644 (file)
@@ -59,15 +59,15 @@ MemCmd::commandInfo[] =
     /* ReadResp */
     { SET3(IsRead, IsResponse, HasData), InvalidCmd, "ReadResp" },
     /* WriteReq */
-    { SET4(IsWrite, IsRequest, NeedsResponse, HasData),
+    { SET5(IsWrite, NeedsExclusive, IsRequest, NeedsResponse, HasData),
             WriteResp, "WriteReq" },
     /* WriteResp */
-    { SET2(IsWrite, IsResponse), InvalidCmd, "WriteResp" },
+    { SET3(IsWrite, NeedsExclusive, IsResponse), InvalidCmd, "WriteResp" },
     /* Writeback */
-    { SET4(IsWrite, IsRequest, HasData, NeedsResponse),
+    { SET5(IsWrite, NeedsExclusive, IsRequest, HasData, NeedsResponse),
             WritebackAck, "Writeback" },
     /* WritebackAck */
-    { SET2(IsWrite, IsResponse), InvalidCmd, "WritebackAck" },
+    { SET3(IsWrite, NeedsExclusive, IsResponse), InvalidCmd, "WritebackAck" },
     /* SoftPFReq */
     { SET4(IsRead, IsRequest, IsSWPrefetch, NeedsResponse),
             SoftPFResp, "SoftPFReq" },
@@ -80,27 +80,39 @@ MemCmd::commandInfo[] =
     /* HardPFResp */
     { SET4(IsRead, IsResponse, IsHWPrefetch, HasData),
             InvalidCmd, "HardPFResp" },
-    /* InvalidateReq */
-    { SET2(IsInvalidate, IsRequest), InvalidCmd, "InvalidateReq" },
     /* WriteInvalidateReq */
-    { SET5(IsWrite, IsInvalidate, IsRequest, HasData, NeedsResponse),
+    { SET6(IsWrite, NeedsExclusive, IsInvalidate,
+           IsRequest, HasData, NeedsResponse),
             WriteInvalidateResp, "WriteInvalidateReq" },
     /* WriteInvalidateResp */
-    { SET3(IsWrite, IsInvalidate, IsResponse),
+    { SET4(IsWrite, NeedsExclusive, IsInvalidate, IsResponse),
             InvalidCmd, "WriteInvalidateResp" },
     /* UpgradeReq */
     { SET3(IsInvalidate, IsRequest, IsUpgrade), InvalidCmd, "UpgradeReq" },
     /* ReadExReq */
-    { SET4(IsRead, IsInvalidate, IsRequest, NeedsResponse),
+    { SET5(IsRead, NeedsExclusive, IsInvalidate, IsRequest, NeedsResponse),
             ReadExResp, "ReadExReq" },
     /* ReadExResp */
-    { SET4(IsRead, IsInvalidate, IsResponse, HasData),
+    { SET5(IsRead, NeedsExclusive, IsInvalidate, IsResponse, HasData),
             InvalidCmd, "ReadExResp" },
+    /* LoadLockedReq */
+    { SET4(IsRead, IsLocked, IsRequest, NeedsResponse),
+            ReadResp, "LoadLockedReq" },
+    /* LoadLockedResp */
+    { SET4(IsRead, IsLocked, IsResponse, HasData),
+            InvalidCmd, "LoadLockedResp" },
+    /* StoreCondReq */
+    { SET6(IsWrite, NeedsExclusive, IsLocked,
+           IsRequest, NeedsResponse, HasData),
+            StoreCondResp, "StoreCondReq" },
+    /* StoreCondResp */
+    { SET4(IsWrite, NeedsExclusive, IsLocked, IsResponse),
+            InvalidCmd, "StoreCondResp" },
     /* SwapReq -- for Swap ldstub type operations */
-    { SET4(IsReadWrite, IsRequest, HasData, NeedsResponse),
+    { SET6(IsRead, IsWrite, NeedsExclusive, IsRequest, HasData, NeedsResponse),
         SwapResp, "SwapReq" },
     /* SwapResp -- for Swap ldstub type operations */
-    { SET3(IsReadWrite, IsResponse, HasData),
+    { SET5(IsRead, IsWrite, NeedsExclusive, IsResponse, HasData),
         InvalidCmd, "SwapResp" }
 };
 
@@ -171,27 +183,28 @@ fixDelayedResponsePacket(PacketPtr func, PacketPtr timing)
 }
 
 bool
-fixPacket(PacketPtr func, PacketPtr timing)
+Packet::checkFunctional(Addr addr, int size, uint8_t *data)
 {
-    Addr funcStart      = func->getAddr();
-    Addr funcEnd        = func->getAddr() + func->getSize() - 1;
-    Addr timingStart    = timing->getAddr();
-    Addr timingEnd      = timing->getAddr() + timing->getSize() - 1;
+    Addr func_start = getAddr();
+    Addr func_end   = getAddr() + getSize() - 1;
+    Addr val_start  = addr;
+    Addr val_end    = val_start + size - 1;
 
-    assert(!(funcStart > timingEnd || timingStart > funcEnd));
+    if (func_start > val_end || val_start > func_end) {
+        // no intersection
+        return false;
+    }
 
-    // this packet can't solve our problem, continue on
-    if (!timing->hasData())
-        return true;
+    // offset of functional request into supplied value (could be
+    // negative if partial overlap)
+    int offset = func_start - val_start;
 
-    if (func->isRead()) {
-        if (funcStart >= timingStart && funcEnd <= timingEnd) {
-            func->allocate();
-            std::memcpy(func->getPtr<uint8_t>(), timing->getPtr<uint8_t>() +
-                    funcStart - timingStart, func->getSize());
-            func->result = Packet::Success;
-            func->flags |= SATISFIED;
-            return false;
+    if (isRead()) {
+        if (func_start >= val_start && func_end <= val_end) {
+            allocate();
+            std::memcpy(getPtr<uint8_t>(), data + offset, getSize());
+            result = Packet::Success;
+            return true;
         } else {
             // In this case the timing packet only partially satisfies
             // the request, so we would need more information to make
@@ -199,25 +212,21 @@ fixPacket(PacketPtr func, PacketPtr timing)
             // something, so the request could continue and get this
             // bit of possibly newer data along with the older data
             // not written to yet.
-            panic("Timing packet only partially satisfies the functional"
-                    "request. Now what?");
+            panic("Memory value only partially satisfies the functional "
+                  "request. Now what?");
         }
-    } else if (func->isWrite()) {
-        if (funcStart >= timingStart) {
-            std::memcpy(timing->getPtr<uint8_t>() + (funcStart - timingStart),
-                   func->getPtr<uint8_t>(),
-                   (std::min(funcEnd, timingEnd) - funcStart) + 1);
-        } else { // timingStart > funcStart
-            std::memcpy(timing->getPtr<uint8_t>(),
-                   func->getPtr<uint8_t>() + (timingStart - funcStart),
-                   (std::min(funcEnd, timingEnd) - timingStart) + 1);
+    } else if (isWrite()) {
+        if (offset >= 0) {
+            std::memcpy(data + offset, getPtr<uint8_t>(),
+                        (std::min(func_end, val_end) - func_start) + 1);
+        } else { // val_start > func_start
+            std::memcpy(data, getPtr<uint8_t>() - offset,
+                        (std::min(func_end, val_end) - val_start) + 1);
         }
         // we always want to keep going with a write
-        return true;
+        return false;
     } else
-        panic("Don't know how to handle command type %#x\n",
-                func->cmdToIndex());
-
+        panic("Don't know how to handle command %s\n", cmdString());
 }
 
 
@@ -247,8 +256,6 @@ operator<<(std::ostream &o, const Packet &p)
         o << "Read ";
     if (p.isWrite())
         o << "Write ";
-    if (p.isReadWrite())
-        o << "Read/Write ";
     if (p.isInvalidate())
         o << "Invalidate ";
     if (p.isRequest())
index e2349e42f2f646a4b6ce075701997f9b98988544..ca186d8757b1ad2888e5f1634bea70aab5995cb0 100644 (file)
@@ -54,16 +54,6 @@ typedef Packet *PacketPtr;
 typedef uint8_t* PacketDataPtr;
 typedef std::list<PacketPtr> PacketList;
 
-//Coherence Flags
-#define NACKED_LINE     (1 << 0)
-#define SATISFIED       (1 << 1)
-#define SHARED_LINE     (1 << 2)
-#define CACHE_LINE_FILL (1 << 3)
-#define COMPRESSED      (1 << 4)
-#define NO_ALLOCATE     (1 << 5)
-
-#define EXPRESS_SNOOP   (1 << 7)
-
 class MemCmd
 {
   public:
@@ -82,12 +72,15 @@ class MemCmd
         HardPFReq,
         SoftPFResp,
         HardPFResp,
-        InvalidateReq,
         WriteInvalidateReq,
         WriteInvalidateResp,
         UpgradeReq,
         ReadExReq,
         ReadExResp,
+        LoadLockedReq,
+        LoadLockedResp,
+        StoreCondReq,
+        StoreCondResp,
         SwapReq,
         SwapResp,
         NUM_MEM_CMDS
@@ -97,18 +90,19 @@ class MemCmd
     /** List of command attributes. */
     enum Attribute
     {
-        IsRead,
-        IsWrite,
-        IsPrefetch,
+        IsRead,         //!< Data flows from responder to requester
+        IsWrite,        //!< Data flows from requester to responder
+        IsPrefetch,     //!< Not a demand access
         IsInvalidate,
-        IsRequest,
-        IsResponse,
-        NeedsResponse,
+        NeedsExclusive, //!< Requires exclusive copy to complete in-cache
+        IsRequest,      //!< Issued by requester
+        IsResponse,     //!< Issue by responder
+        NeedsResponse,  //!< Requester needs response from target
         IsSWPrefetch,
         IsHWPrefetch,
         IsUpgrade,
-        HasData,
-        IsReadWrite,
+        IsLocked,       //!< Alpha/MIPS LL or SC access
+        HasData,        //!< There is an associated payload
         NUM_COMMAND_ATTRIBUTES
     };
 
@@ -141,10 +135,12 @@ class MemCmd
     bool isWrite()  const       { return testCmdAttrib(IsWrite); }
     bool isRequest() const      { return testCmdAttrib(IsRequest); }
     bool isResponse() const     { return testCmdAttrib(IsResponse); }
+    bool needsExclusive() const  { return testCmdAttrib(NeedsExclusive); }
     bool needsResponse() const  { return testCmdAttrib(NeedsResponse); }
     bool isInvalidate() const   { return testCmdAttrib(IsInvalidate); }
     bool hasData() const        { return testCmdAttrib(HasData); }
-    bool isReadWrite() const    { return testCmdAttrib(IsReadWrite); }
+    bool isReadWrite() const    { return isRead() && isWrite(); }
+    bool isLocked() const       { return testCmdAttrib(IsLocked); }
 
     const Command responseCommand() const {
         return commandInfo[cmd].response;
@@ -188,9 +184,6 @@ class Packet
 
     typedef MemCmd::Command Command;
 
-    /** Temporary FLAGS field until cache gets working, this should be in coherence/sender state. */
-    uint64_t flags;
-
   private:
    /** A pointer to the data being transfered.  It can be differnt
     *    sizes at each level of the heirarchy so it belongs in the
@@ -235,6 +228,14 @@ class Packet
     /** Is the 'src' field valid? */
     bool srcValid;
 
+    enum SnoopFlag {
+        MemInhibit,
+        Shared,
+        NUM_SNOOP_FLAGS
+    };
+
+    /** Coherence snoopFlags for snooping */
+    std::bitset<NUM_SNOOP_FLAGS> snoopFlags;
 
   public:
 
@@ -301,14 +302,17 @@ class Packet
     bool isWrite()  const       { return cmd.isWrite(); }
     bool isRequest() const      { return cmd.isRequest(); }
     bool isResponse() const     { return cmd.isResponse(); }
+    bool needsExclusive() const  { return cmd.needsExclusive(); }
     bool needsResponse() const  { return cmd.needsResponse(); }
     bool isInvalidate() const   { return cmd.isInvalidate(); }
     bool hasData() const        { return cmd.hasData(); }
     bool isReadWrite() const    { return cmd.isReadWrite(); }
+    bool isLocked() const       { return cmd.isLocked(); }
 
-    bool isCacheFill() const    { return (flags & CACHE_LINE_FILL) != 0; }
-    bool isNoAllocate() const   { return (flags & NO_ALLOCATE) != 0; }
-    bool isCompressed() const   { return (flags & COMPRESSED) != 0; }
+    void assertMemInhibit()     { snoopFlags[MemInhibit] = true; }
+    void assertShared()         { snoopFlags[Shared] = true; }
+    bool memInhibitAsserted()   { return snoopFlags[MemInhibit]; }
+    bool sharedAsserted()       { return snoopFlags[Shared]; }
 
     bool nic_pkt() { panic("Unimplemented"); M5_DUMMY_RETURN }
 
@@ -327,6 +331,8 @@ class Packet
     /** Accessor function that returns the source index of the packet. */
     short getSrc() const { assert(srcValid); return src; }
     void setSrc(short _src) { src = _src; srcValid = true; }
+    /** Reset source field, e.g. to retransmit packet on different bus. */
+    void clearSrc() { srcValid = false; }
 
     /** Accessor function that returns the destination index of
         the packet. */
@@ -347,13 +353,12 @@ class Packet
     Packet(Request *_req, MemCmd _cmd, short _dest)
         :  data(NULL), staticData(false), dynamicData(false), arrayData(false),
            addr(_req->paddr), size(_req->size), dest(_dest),
-           addrSizeValid(_req->validPaddr),
-           srcValid(false),
+           addrSizeValid(_req->validPaddr), srcValid(false),
+           snoopFlags(0),
+           time(curTick),
            req(_req), coherence(NULL), senderState(NULL), cmd(_cmd),
            result(Unknown)
     {
-        flags = 0;
-        time = curTick;
     }
 
     /** Alternate constructor if you are trying to create a packet with
@@ -361,14 +366,32 @@ class Packet
      *  this allows for overriding the size/addr of the req.*/
     Packet(Request *_req, MemCmd _cmd, short _dest, int _blkSize)
         :  data(NULL), staticData(false), dynamicData(false), arrayData(false),
-           addr(_req->paddr & ~(_blkSize - 1)), size(_blkSize),
-           dest(_dest),
+           addr(_req->paddr & ~(_blkSize - 1)), size(_blkSize), dest(_dest),
            addrSizeValid(_req->validPaddr), srcValid(false),
+           snoopFlags(0),
+           time(curTick),
            req(_req), coherence(NULL), senderState(NULL), cmd(_cmd),
            result(Unknown)
     {
-        flags = 0;
-        time = curTick;
+    }
+
+    /** Alternate constructor for copying a packet.  Copy all fields
+     * *except* set data allocation as static... even if the original
+     * packet's data was dynamic, we don't want to free it when the
+     * new packet is deallocated.  Note that if original packet used
+     * dynamic data, user must guarantee that the new packet's
+     * lifetime is less than that of the original packet. */
+    Packet(Packet *origPkt)
+        :  data(NULL), staticData(false), dynamicData(false), arrayData(false),
+           addr(origPkt->addr), size(origPkt->size),
+           dest(origPkt->dest),
+           addrSizeValid(origPkt->addrSizeValid), srcValid(origPkt->srcValid),
+           snoopFlags(origPkt->snoopFlags),
+           time(curTick),
+           req(origPkt->req), coherence(origPkt->coherence),
+           senderState(origPkt->senderState), cmd(origPkt->cmd),
+           result(origPkt->result)
+    {
     }
 
     /** Destructor. */
@@ -382,7 +405,7 @@ class Packet
      *   multiple transactions. */
     void reinitFromRequest() {
         assert(req->validPaddr);
-        flags = 0;
+        snoopFlags = 0;
         addr = req->paddr;
         size = req->size;
         time = req->time;
@@ -395,29 +418,40 @@ class Packet
         }
     }
 
-    /** Take a request packet and modify it in place to be suitable
-     *   for returning as a response to that request.  Used for timing
-     *   accesses only.  For atomic and functional accesses, the
-     *   request packet is always implicitly passed back *without*
-     *   modifying the destination fields, so this function
-     *   should not be called. */
-    void makeTimingResponse() {
+    /**
+     * Take a request packet and modify it in place to be suitable for
+     * returning as a response to that request.  The source and
+     * destination fields are *not* modified, as is appropriate for
+     * atomic accesses.
+     */
+    void makeAtomicResponse()
+    {
         assert(needsResponse());
         assert(isRequest());
+        assert(result == Unknown);
         cmd = cmd.responseCommand();
+        result = Success;
+    }
+
+    /**
+     * Perform the additional work required for timing responses above
+     * and beyond atomic responses; i.e., change the destination to
+     * point back to the requester and clear the source field.
+     */
+    void convertAtomicToTimingResponse()
+    {
         dest = src;
         srcValid = false;
     }
 
     /**
      * Take a request packet and modify it in place to be suitable for
-     * returning as a response to that request.
+     * returning as a response to a timing request.
      */
-    void makeAtomicResponse()
+    void makeTimingResponse()
     {
-        assert(needsResponse());
-        assert(isRequest());
-        cmd = cmd.responseCommand();
+        makeAtomicResponse();
+        convertAtomicToTimingResponse();
     }
 
     /**
@@ -493,6 +527,40 @@ class Packet
     template <typename T>
     void set(T v);
 
+    /**
+     * Copy data into the packet from the provided pointer.
+     */
+    void setData(uint8_t *p)
+    {
+        std::memcpy(getPtr<uint8_t>(), p, getSize());
+    }
+
+    /**
+     * Copy data into the packet from the provided block pointer,
+     * which is aligned to the given block size.
+     */
+    void setDataFromBlock(uint8_t *blk_data, int blkSize)
+    {
+        setData(blk_data + getOffset(blkSize));
+    }
+
+    /**
+     * Copy data from the packet to the provided block pointer, which
+     * is aligned to the given block size.
+     */
+    void writeData(uint8_t *p)
+    {
+        std::memcpy(p, getPtr<uint8_t>(), getSize());
+    }
+
+    /**
+     * Copy data from the packet to the memory at the provided pointer.
+     */
+    void writeDataToBlock(uint8_t *blk_data, int blkSize)
+    {
+        writeData(blk_data + getOffset(blkSize));
+    }
+
     /**
      * delete the data pointed to in the data pointer. Ok to call to
      * matter how data was allocted.
@@ -504,15 +572,35 @@ class Packet
 
     /** Do the packet modify the same addresses. */
     bool intersect(PacketPtr p);
+
+    /**
+     * Check a functional request against a memory value represented
+     * by a base/size pair and an associated data array.  If the
+     * functional request is a read, it may be satisfied by the memory
+     * value.  If the functional request is a write, it may update the
+     * memory value.
+     */
+    bool checkFunctional(Addr base, int size, uint8_t *data);
+
+    /**
+     * Check a functional request against a memory value stored in
+     * another packet (i.e. an in-transit request or response).
+     */
+    bool checkFunctional(PacketPtr otherPkt) {
+        return (otherPkt->hasData() &&
+                checkFunctional(otherPkt->getAddr(), otherPkt->getSize(),
+                                otherPkt->getPtr<uint8_t>()));
+    }
 };
 
-/** This function given a functional packet and a timing packet either
- * satisfies the timing packet, or updates the timing packet to
- * reflect the updated state in the timing packet. It returns if the
- * functional packet should continue to traverse the memory hierarchy
- * or not.
+
+
+/** Temporary for backwards compatibility.
  */
-bool fixPacket(PacketPtr func, PacketPtr timing);
+inline
+bool fixPacket(PacketPtr func, PacketPtr timing) {
+    return !func->checkFunctional(timing);
+}
 
 /** This function is a wrapper for the fixPacket field that toggles
  * the hasData bit it is used when a response is waiting in the
index 9d840fe692333547c286ed4eecc41b86f37c053c..93cba96c4c0a95b294fa3531e677f44f515ca6f1 100644 (file)
@@ -58,8 +58,9 @@ PhysicalMemory::PhysicalMemory(Params *p)
         panic("Memory Size not divisible by page size\n");
 
     int map_flags = MAP_ANON | MAP_PRIVATE;
-    pmemAddr = (uint8_t *)mmap(NULL, params()->addrRange.size(), PROT_READ | PROT_WRITE,
-            map_flags, -1, 0);
+    pmemAddr =
+        (uint8_t *)mmap(NULL, params()->addrRange.size(),
+                        PROT_READ | PROT_WRITE, map_flags, -1, 0);
 
     if (pmemAddr == (void *)MAP_FAILED) {
         perror("mmap");
@@ -121,8 +122,9 @@ PhysicalMemory::calculateLatency(PacketPtr pkt)
 // Add load-locked to tracking list.  Should only be called if the
 // operation is a load and the LOCKED flag is set.
 void
-PhysicalMemory::trackLoadLocked(Request *req)
+PhysicalMemory::trackLoadLocked(PacketPtr pkt)
 {
+    Request *req = pkt->req;
     Addr paddr = LockedAddr::mask(req->getPaddr());
 
     // first we check if we already have a locked addr for this
@@ -151,10 +153,11 @@ PhysicalMemory::trackLoadLocked(Request *req)
 // conflict with locked addresses, and for success/failure of store
 // conditionals.
 bool
-PhysicalMemory::checkLockedAddrList(Request *req)
+PhysicalMemory::checkLockedAddrList(PacketPtr pkt)
 {
+    Request *req = pkt->req;
     Addr paddr = LockedAddr::mask(req->getPaddr());
-    bool isLocked = req->isLocked();
+    bool isLocked = pkt->isLocked();
 
     // Initialize return value.  Non-conditional stores always
     // succeed.  Assume conditional stores will fail until proven
@@ -198,74 +201,50 @@ PhysicalMemory::checkLockedAddrList(Request *req)
     return success;
 }
 
-void
-PhysicalMemory::doFunctionalAccess(PacketPtr pkt)
+
+#if TRACING_ON
+
+#define CASE(A, T)                                                      \
+  case sizeof(T):                                                       \
+    DPRINTF(MemoryAccess, A " of size %i on address 0x%x data 0x%x\n",  \
+            pkt->getSize(), pkt->getAddr(), pkt->get<T>());             \
+  break
+
+
+#define TRACE_PACKET(A)                                                 \
+    do {                                                                \
+        switch (pkt->getSize()) {                                       \
+          CASE(A, uint64_t);                                            \
+          CASE(A, uint32_t);                                            \
+          CASE(A, uint16_t);                                            \
+          CASE(A, uint8_t);                                             \
+          default:                                                      \
+            DPRINTF(MemoryAccess, A " of size %i on address 0x%x\n",    \
+                    pkt->getSize(), pkt->getAddr());                    \
+        }                                                               \
+    } while (0)
+
+#else
+
+#define TRACE_PACKET(A)
+
+#endif
+
+Tick
+PhysicalMemory::doAtomicAccess(PacketPtr pkt)
 {
     assert(pkt->getAddr() >= start() &&
            pkt->getAddr() + pkt->getSize() <= start() + size());
 
-    if (pkt->isRead()) {
-        if (pkt->req->isLocked()) {
-            trackLoadLocked(pkt->req);
-        }
-        memcpy(pkt->getPtr<uint8_t>(), pmemAddr + pkt->getAddr() - start(),
-               pkt->getSize());
-#if TRACING_ON
-        switch (pkt->getSize()) {
-          case sizeof(uint64_t):
-            DPRINTF(MemoryAccess, "Read of size %i on address 0x%x data 0x%x\n",
-                    pkt->getSize(), pkt->getAddr(),pkt->get<uint64_t>());
-            break;
-          case sizeof(uint32_t):
-            DPRINTF(MemoryAccess, "Read of size %i on address 0x%x data 0x%x\n",
-                    pkt->getSize(), pkt->getAddr(),pkt->get<uint32_t>());
-            break;
-          case sizeof(uint16_t):
-            DPRINTF(MemoryAccess, "Read of size %i on address 0x%x data 0x%x\n",
-                    pkt->getSize(), pkt->getAddr(),pkt->get<uint16_t>());
-            break;
-          case sizeof(uint8_t):
-            DPRINTF(MemoryAccess, "Read of size %i on address 0x%x data 0x%x\n",
-                    pkt->getSize(), pkt->getAddr(),pkt->get<uint8_t>());
-            break;
-          default:
-            DPRINTF(MemoryAccess, "Read of size %i on address 0x%x\n",
-                    pkt->getSize(), pkt->getAddr());
-        }
-#endif
+    if (pkt->memInhibitAsserted()) {
+        DPRINTF(MemoryAccess, "mem inhibited on 0x%x: not responding\n",
+                pkt->getAddr());
+        return 0;
     }
-    else if (pkt->isWrite()) {
-        if (writeOK(pkt->req)) {
-                memcpy(pmemAddr + pkt->getAddr() - start(), pkt->getPtr<uint8_t>(),
-                        pkt->getSize());
-#if TRACING_ON
-            switch (pkt->getSize()) {
-              case sizeof(uint64_t):
-                DPRINTF(MemoryAccess, "Write of size %i on address 0x%x data 0x%x\n",
-                        pkt->getSize(), pkt->getAddr(),pkt->get<uint64_t>());
-                break;
-              case sizeof(uint32_t):
-                DPRINTF(MemoryAccess, "Write of size %i on address 0x%x data 0x%x\n",
-                        pkt->getSize(), pkt->getAddr(),pkt->get<uint32_t>());
-                break;
-              case sizeof(uint16_t):
-                DPRINTF(MemoryAccess, "Write of size %i on address 0x%x data 0x%x\n",
-                        pkt->getSize(), pkt->getAddr(),pkt->get<uint16_t>());
-                break;
-              case sizeof(uint8_t):
-                DPRINTF(MemoryAccess, "Write of size %i on address 0x%x data 0x%x\n",
-                        pkt->getSize(), pkt->getAddr(),pkt->get<uint8_t>());
-                break;
-              default:
-                DPRINTF(MemoryAccess, "Write of size %i on address 0x%x\n",
-                        pkt->getSize(), pkt->getAddr());
-            }
-#endif
-        }
-    } else if (pkt->isInvalidate()) {
-        //upgrade or invalidate
-        pkt->flags |= SATISFIED;
-    } else if (pkt->isReadWrite()) {
+
+    uint8_t *hostAddr = pmemAddr + pkt->getAddr() - start();
+
+    if (pkt->cmd == MemCmd::SwapReq) {
         IntReg overwrite_val;
         bool overwrite_mem;
         uint64_t condition_val64;
@@ -277,66 +256,76 @@ PhysicalMemory::doFunctionalAccess(PacketPtr pkt)
         // keep a copy of our possible write value, and copy what is at the
         // memory address into the packet
         std::memcpy(&overwrite_val, pkt->getPtr<uint8_t>(), pkt->getSize());
-        std::memcpy(pkt->getPtr<uint8_t>(), pmemAddr + pkt->getAddr() - start(),
-               pkt->getSize());
+        std::memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize());
 
         if (pkt->req->isCondSwap()) {
             if (pkt->getSize() == sizeof(uint64_t)) {
                 condition_val64 = pkt->req->getExtraData();
-                overwrite_mem = !std::memcmp(&condition_val64, pmemAddr +
-                        pkt->getAddr() - start(), sizeof(uint64_t));
+                overwrite_mem = !std::memcmp(&condition_val64, hostAddr,
+                                             sizeof(uint64_t));
             } else if (pkt->getSize() == sizeof(uint32_t)) {
                 condition_val32 = (uint32_t)pkt->req->getExtraData();
-                overwrite_mem = !std::memcmp(&condition_val32, pmemAddr +
-                        pkt->getAddr() - start(), sizeof(uint32_t));
+                overwrite_mem = !std::memcmp(&condition_val32, hostAddr,
+                                             sizeof(uint32_t));
             } else
                 panic("Invalid size for conditional read/write\n");
         }
 
         if (overwrite_mem)
-            std::memcpy(pmemAddr + pkt->getAddr() - start(),
-               &overwrite_val, pkt->getSize());
+            std::memcpy(hostAddr, &overwrite_val, pkt->getSize());
 
-#if TRACING_ON
-        switch (pkt->getSize()) {
-          case sizeof(uint64_t):
-            DPRINTF(MemoryAccess, "Read/Write of size %i on address 0x%x old data 0x%x\n",
-                    pkt->getSize(), pkt->getAddr(),pkt->get<uint64_t>());
-            DPRINTF(MemoryAccess, "New Data 0x%x %s conditional (0x%x) and %s \n",
-                    overwrite_mem, pkt->req->isCondSwap() ? "was" : "wasn't",
-                    condition_val64, overwrite_mem ? "happened" : "didn't happen");
-            break;
-          case sizeof(uint32_t):
-            DPRINTF(MemoryAccess, "Read/Write of size %i on address 0x%x old data 0x%x\n",
-                    pkt->getSize(), pkt->getAddr(),pkt->get<uint32_t>());
-            DPRINTF(MemoryAccess, "New Data 0x%x %s conditional (0x%x) and %s \n",
-                    overwrite_mem, pkt->req->isCondSwap() ? "was" : "wasn't",
-                    condition_val32, overwrite_mem ? "happened" : "didn't happen");
-            break;
-          case sizeof(uint16_t):
-            DPRINTF(MemoryAccess, "Read/Write of size %i on address 0x%x old data 0x%x\n",
-                    pkt->getSize(), pkt->getAddr(),pkt->get<uint16_t>());
-            DPRINTF(MemoryAccess, "New Data 0x%x wasn't conditional and happned\n",
-                    overwrite_mem);
-            break;
-          case sizeof(uint8_t):
-            DPRINTF(MemoryAccess, "Read/Write of size %i on address 0x%x old data 0x%x\n",
-                    pkt->getSize(), pkt->getAddr(),pkt->get<uint8_t>());
-            DPRINTF(MemoryAccess, "New Data 0x%x wasn't conditional and happned\n",
-                    overwrite_mem);
-            break;
-          default:
-            DPRINTF(MemoryAccess, "Read/Write of size %i on address 0x%x\n",
-                    pkt->getSize(), pkt->getAddr());
+        TRACE_PACKET("Read/Write");
+    } else if (pkt->isRead()) {
+        assert(!pkt->isWrite());
+        if (pkt->isLocked()) {
+            trackLoadLocked(pkt);
+        }
+        memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize());
+        TRACE_PACKET("Read");
+    } else if (pkt->isWrite()) {
+        if (writeOK(pkt)) {
+            memcpy(hostAddr, pkt->getPtr<uint8_t>(), pkt->getSize());
+            TRACE_PACKET("Write");
+        }
+    } else if (pkt->isInvalidate()) {
+        //upgrade or invalidate
+        if (pkt->needsResponse()) {
+            pkt->makeAtomicResponse();
         }
-#endif
     } else {
         panic("unimplemented");
     }
 
+    if (pkt->needsResponse()) {
+        pkt->makeAtomicResponse();
+    }
+    return calculateLatency(pkt);
+}
+
+
+void
+PhysicalMemory::doFunctionalAccess(PacketPtr pkt)
+{
+    assert(pkt->getAddr() >= start() &&
+           pkt->getAddr() + pkt->getSize() <= start() + size());
+
+    uint8_t *hostAddr = pmemAddr + pkt->getAddr() - start();
+
+    if (pkt->cmd == MemCmd::ReadReq) {
+        memcpy(pkt->getPtr<uint8_t>(), hostAddr, pkt->getSize());
+        TRACE_PACKET("Read");
+    } else if (pkt->cmd == MemCmd::WriteReq) {
+        memcpy(hostAddr, pkt->getPtr<uint8_t>(), pkt->getSize());
+        TRACE_PACKET("Write");
+    } else {
+        panic("PhysicalMemory: unimplemented functional command %s",
+              pkt->cmdString());
+    }
+
     pkt->result = Packet::Success;
 }
 
+
 Port *
 PhysicalMemory::getPort(const std::string &if_name, int idx)
 {
@@ -407,8 +396,7 @@ PhysicalMemory::MemoryPort::deviceBlockSize()
 Tick
 PhysicalMemory::MemoryPort::recvAtomic(PacketPtr pkt)
 {
-    memory->doFunctionalAccess(pkt);
-    return memory->calculateLatency(pkt);
+    return memory->doAtomicAccess(pkt);
 }
 
 void
index b9af5d3343ba49f7ce544e23f95fdc2f8e0d6b1b..8b13d32c1381c8339f1fd5fe8a7d1c27b05d1575 100644 (file)
@@ -112,12 +112,12 @@ class PhysicalMemory : public MemObject
     // inline a quick check for an empty locked addr list (hopefully
     // the common case), and do the full list search (if necessary) in
     // this out-of-line function
-    bool checkLockedAddrList(Request *req);
+    bool checkLockedAddrList(PacketPtr pkt);
 
     // Record the address of a load-locked operation so that we can
     // clear the execution context's lock flag if a matching store is
     // performed
-    void trackLoadLocked(Request *req);
+    void trackLoadLocked(PacketPtr pkt);
 
     // Compare a store address with any locked addresses so we can
     // clear the lock flag appropriately.  Return value set to 'false'
@@ -126,17 +126,18 @@ class PhysicalMemory : public MemObject
     // requesting execution context), 'true' otherwise.  Note that
     // this method must be called on *all* stores since even
     // non-conditional stores must clear any matching lock addresses.
-    bool writeOK(Request *req) {
+    bool writeOK(PacketPtr pkt) {
+        Request *req = pkt->req;
         if (lockedAddrList.empty()) {
             // no locked addrs: nothing to check, store_conditional fails
-            bool isLocked = req->isLocked();
+            bool isLocked = pkt->isLocked();
             if (isLocked) {
                 req->setExtraData(0);
             }
             return !isLocked; // only do write if not an sc
         } else {
             // iterate over list...
-            return checkLockedAddrList(req);
+            return checkLockedAddrList(pkt);
         }
     }
 
@@ -175,6 +176,7 @@ class PhysicalMemory : public MemObject
     unsigned int drain(Event *de);
 
   protected:
+    Tick doAtomicAccess(PacketPtr pkt);
     void doFunctionalAccess(PacketPtr pkt);
     virtual Tick calculateLatency(PacketPtr pkt);
     void recvStatusChange(Port::Status status);
index ed4c0c17237850f1a0546cb95e003774eb98b637..2644a504c3bb76be40736df41dff4ab9fb7576f9 100644 (file)
@@ -67,14 +67,17 @@ SimpleTimingPort::recvTiming(PacketPtr pkt)
     // code to hanldle nacks here, but I'm pretty sure it didn't work
     // correctly with the drain code, so that would need to be fixed
     // if we ever added it back.
-    assert(pkt->result != Packet::Nacked);
+    assert(pkt->isRequest());
+    assert(pkt->result == Packet::Unknown);
+    bool needsResponse = pkt->needsResponse();
     Tick latency = recvAtomic(pkt);
     // turn packet around to go back to requester if response expected
-    if (pkt->needsResponse()) {
-        pkt->makeTimingResponse();
+    if (needsResponse) {
+        // recvAtomic() should already have turned packet into atomic response
+        assert(pkt->isResponse());
+        pkt->convertAtomicToTimingResponse();
         schedSendTiming(pkt, curTick + latency);
-    }
-    else if (pkt->cmd != MemCmd::UpgradeReq) {
+    } else {
         delete pkt->req;
         delete pkt;
     }