mem: use single BadAddr responder per system.
authorSteve Reinhardt <Steve.Reinhardt@amd.com>
Wed, 16 Jul 2008 18:10:33 +0000 (11:10 -0700)
committerSteve Reinhardt <Steve.Reinhardt@amd.com>
Wed, 16 Jul 2008 18:10:33 +0000 (11:10 -0700)
Previously there was one per bus, which caused some coherence problems
when more than one decided to respond.  Now there is just one on
the main memory bus.  The default bus responder on all other buses
is now the downstream cache's cpu_side port.  Caches no longer need
to do address range filtering; instead, we just have a simple flag
to prevent snoops from propagating to the I/O bus.

17 files changed:
configs/common/Caches.py
configs/common/FSConfig.py
configs/example/fs.py
src/dev/Device.py
src/mem/Bus.py
src/mem/bus.cc
src/mem/cache/BaseCache.py
src/mem/cache/base.cc
src/mem/cache/base.hh
src/mem/cache/cache.hh
src/mem/cache/cache_impl.hh
tests/configs/tsunami-o3-dual.py
tests/configs/tsunami-o3.py
tests/configs/tsunami-simple-atomic-dual.py
tests/configs/tsunami-simple-atomic.py
tests/configs/tsunami-simple-timing-dual.py
tests/configs/tsunami-simple-timing.py

index f1ea957b5403e0e2c9e2848af599711914b5a45f..1c3b089c799d28e678994da5c683cf0205ea9a57 100644 (file)
@@ -50,3 +50,4 @@ class IOCache(BaseCache):
     mshrs = 20
     size = '1kB'
     tgts_per_mshr = 12
+    forward_snoops = False
index 974003005e26507d4e00a131f966a03273a7e8b8..a9cd24ba3847e348b9580d3f3d174ff693cbf7af 100644 (file)
@@ -38,6 +38,11 @@ class CowIdeDisk(IdeDisk):
     def childImage(self, ci):
         self.image.child.image_file = ci
 
+class MemBus(Bus):
+    badaddr_responder = BadAddr()
+    default = Self.badaddr_responder.pio
+
+
 def makeLinuxAlphaSystem(mem_mode, mdesc = None):
     class BaseTsunami(Tsunami):
         ethernet = NSGigE(pci_bus=0, pci_dev=1, pci_func=0)
@@ -50,7 +55,7 @@ def makeLinuxAlphaSystem(mem_mode, mdesc = None):
         mdesc = SysConfig()
     self.readfile = mdesc.script()
     self.iobus = Bus(bus_id=0)
-    self.membus = Bus(bus_id=1)
+    self.membus = MemBus(bus_id=1)
     self.bridge = Bridge(delay='50ns', nack_delay='4ns')
     self.physmem = PhysicalMemory(range = AddrRange(mdesc.mem()))
     self.bridge.side_a = self.iobus.port
@@ -90,7 +95,7 @@ def makeSparcSystem(mem_mode, mdesc = None):
         mdesc = SysConfig()
     self.readfile = mdesc.script()
     self.iobus = Bus(bus_id=0)
-    self.membus = Bus(bus_id=1)
+    self.membus = MemBus(bus_id=1)
     self.bridge = Bridge(delay='50ns', nack_delay='4ns')
     self.t1000 = T1000()
     self.t1000.attachOnChipIO(self.membus)
@@ -130,7 +135,7 @@ def makeLinuxMipsSystem(mem_mode, mdesc = None):
         mdesc = SysConfig()
     self.readfile = mdesc.script()
     self.iobus = Bus(bus_id=0)
-    self.membus = Bus(bus_id=1)
+    self.membus = MemBus(bus_id=1)
     self.bridge = Bridge(delay='50ns', nack_delay='4ns')
     self.physmem = PhysicalMemory(range = AddrRange('1GB'))
     self.bridge.side_a = self.iobus.port
@@ -170,7 +175,7 @@ def makeX86System(mem_mode, mdesc = None, self = None):
     self.readfile = mdesc.script()
 
     # Physical memory
-    self.membus = Bus(bus_id=1)
+    self.membus = MemBus(bus_id=1)
     self.physmem = PhysicalMemory(range = AddrRange(mdesc.mem()))
     self.physmem.port = self.membus.port
 
index c155d0222129adcd7c324b1857f5f3a13b101de4..c013a97aea6aecb1ebe8ec439071ff8d9fe68ebb 100644 (file)
@@ -126,8 +126,7 @@ test_sys.cpu = [TestCPUClass(cpu_id=i) for i in xrange(np)]
 if options.caches:
     test_sys.bridge.filter_ranges_a=[AddrRange(0, Addr.max)]
     test_sys.bridge.filter_ranges_b=[AddrRange(0, size='8GB')]
-    test_sys.iocache = IOCache(mem_side_filter_ranges=[AddrRange(0, Addr.max)],
-                       cpu_side_filter_ranges=[AddrRange(0x8000000000, Addr.max)])
+    test_sys.iocache = IOCache(addr_range=AddrRange(0, size='8GB'))
     test_sys.iocache.cpu_side = test_sys.iobus.port
     test_sys.iocache.mem_side = test_sys.membus.port
 
index adf262f26d4294f5d97c6904586e9c535e2914fe..4babffa18803476e9ce0c425ab45893a35657769 100644 (file)
@@ -66,6 +66,7 @@ class IsaFake(BasicPioDevice):
     warn_access = Param.String("", "String to print when device is accessed")
 
 class BadAddr(IsaFake):
+    pio_addr = 0
     ret_bad_addr = Param.Bool(True, "Return pkt status bad address on access")
 
 
index f4ea9a73bf7a6994e2c8830736fd5078476448f3..0f113cc09de2729c5d4b7ea98bb367d1b1d8647e 100644 (file)
@@ -43,8 +43,4 @@ class Bus(MemObject):
     width = Param.Int(64, "bus width (bytes)")
     responder_set = Param.Bool(False, "Did the user specify a default responder.")
     block_size = Param.Int(64, "The default block size if one isn't set by a device attached to the bus.")
-    if build_env['FULL_SYSTEM']:
-        responder = BadAddr(pio_addr=0x0, pio_latency="1ps")
-        default = Port(Self.responder.pio, "Default port for requests that aren't handled by a device.")
-    else:
-        default = Port("Default port for requests that aren't handled by a device.")
+    default = Port("Default port for requests that aren't handled by a device.")
index 2eb8230514bebec9ba3e684a4f48bc1454357a8f..b9cdff242309edb744f7281feab29753721ffa83 100644 (file)
@@ -219,7 +219,7 @@ Bus::recvTiming(PacketPtr pkt)
             }
         }
     } else {
-        assert(dest >= 0 && dest < maxId);
+        assert(dest < maxId);
         assert(dest != src); // catch infinite loops
         dest_port_id = dest;
         if (dest_port_id == defaultId)
@@ -238,7 +238,6 @@ Bus::recvTiming(PacketPtr pkt)
     if (dest_port_id == src) {
         // Must be forwarded snoop up from below...
         assert(dest == Packet::Broadcast);
-        assert(src != defaultId); // catch infinite loops
     } else {
         // send to actual target
         if (!dest_port->sendTiming(pkt))  {
index bef1b45d2b8923432ae94d89d51db46ce3ea4da7..bdef07cb4de7a07a043d895fa135babf2967052a 100644 (file)
@@ -45,6 +45,8 @@ class BaseCache(MemObject):
         "always service demand misses first")
     repl = Param.Repl(NULL, "replacement policy")
     size = Param.MemorySize("capacity in bytes")
+    forward_snoops = Param.Bool(True,
+        "forward snoops from mem side to cpu side")
     subblock_size = Param.Int(0,
         "Size of subblock in IIC used for compression")
     tgts_per_mshr = Param.Int("max number of accesses per MSHR")
@@ -74,8 +76,4 @@ class BaseCache(MemObject):
          "Only prefetch on data not on instruction accesses")
     cpu_side = Port("Port on side closer to CPU")
     mem_side = Port("Port on side closer to MEM")
-    cpu_side_filter_ranges = VectorParam.AddrRange([],
-            "What addresses shouldn't be passed through the side of the bridge")
-    mem_side_filter_ranges = VectorParam.AddrRange([],
-            "What addresses shouldn't be passed through the side of the bridge")
-    addr_range = VectorParam.AddrRange(AllMemory, "The address range in bytes")
+    addr_range = Param.AddrRange(AllMemory, "The address range for the CPU-side port")
index 95637553014bbeb488ff4558d8e22f96dfd39928..29fa9754448409ca9a162ce6293748d7ab66e276 100644 (file)
 using namespace std;
 
 BaseCache::CachePort::CachePort(const std::string &_name, BaseCache *_cache,
-                                const std::string &_label,
-                                std::vector<Range<Addr> > filter_ranges)
+                                const std::string &_label)
     : SimpleTimingPort(_name, _cache), cache(_cache),
       label(_label), otherPort(NULL),
-      blocked(false), mustSendRetry(false), filterRanges(filter_ranges)
+      blocked(false), mustSendRetry(false)
 {
 }
 
@@ -58,10 +57,12 @@ BaseCache::BaseCache(const Params *p)
       blkSize(p->block_size),
       hitLatency(p->latency),
       numTarget(p->tgts_per_mshr),
+      forwardSnoops(p->forward_snoops),
       blocked(0),
       noTargetMSHR(NULL),
       missCount(p->max_miss_count),
-      drainEvent(NULL)
+      drainEvent(NULL),
+      addrRange(p->addr_range)
 {
 }
 
index 4319717e5b3714237840f5c3fc386d3a70110734..d33c655d73d74f5afaa685499d3dacfa2b52527c 100644 (file)
@@ -100,8 +100,7 @@ class BaseCache : public MemObject
 
       protected:
         CachePort(const std::string &_name, BaseCache *_cache,
-                  const std::string &_label,
-                  std::vector<Range<Addr> > filter_ranges);
+                  const std::string &_label);
 
         virtual void recvStatusChange(Status status);
 
@@ -129,9 +128,6 @@ class BaseCache : public MemObject
 
         bool mustSendRetry;
 
-        /** filter ranges */
-        std::vector<Range<Addr> > filterRanges;
-
         void requestBus(RequestCause cause, Tick time)
         {
             DPRINTF(CachePort, "Asserting bus request for cause %d\n", cause);
@@ -194,8 +190,8 @@ class BaseCache : public MemObject
     /** The number of targets for each MSHR. */
     const int numTarget;
 
-    /** Increasing order number assigned to each incoming request. */
-    uint64_t order;
+    /** Do we forward snoops from mem side port through to cpu side port? */
+    bool forwardSnoops;
 
     /**
      * Bit vector of the blocking reasons for the access path.
@@ -203,6 +199,9 @@ class BaseCache : public MemObject
      */
     uint8_t blocked;
 
+    /** Increasing order number assigned to each incoming request. */
+    uint64_t order;
+
     /** Stores time the cache blocked for statistics. */
     Tick blockedCycle;
 
@@ -215,6 +214,11 @@ class BaseCache : public MemObject
     /** The drain event. */
     Event *drainEvent;
 
+    /**
+     * The address range to which the cache responds on the CPU side.
+     * Normally this is all possible memory addresses. */
+    Range<Addr> addrRange;
+
   public:
     // Statistics
     /**
@@ -377,6 +381,8 @@ class BaseCache : public MemObject
     Addr blockAlign(Addr addr) const { return (addr & ~(blkSize - 1)); }
 
 
+    const Range<Addr> &getAddrRange() const { return addrRange; }
+
     MSHR *allocateMissBuffer(PacketPtr pkt, Tick time, bool requestBus)
     {
         assert(!pkt->req->isUncacheable());
index 4570b067b69d5a44f8702d4158928344995d3753..6cb6233f59f8c5083867c2944d4e32e1b284afe9 100644 (file)
@@ -71,8 +71,7 @@ class Cache : public BaseCache
       public:
         CpuSidePort(const std::string &_name,
                     Cache<TagStore> *_cache,
-                    const std::string &_label,
-                    std::vector<Range<Addr> > filterRanges);
+                    const std::string &_label);
 
         // BaseCache::CachePort just has a BaseCache *; this function
         // lets us get back the type info we lost when we stored the
@@ -96,8 +95,7 @@ class Cache : public BaseCache
       public:
         MemSidePort(const std::string &_name,
                     Cache<TagStore> *_cache,
-                    const std::string &_label,
-                    std::vector<Range<Addr> > filterRanges);
+                    const std::string &_label);
 
         // BaseCache::CachePort just has a BaseCache *; this function
         // lets us get back the type info we lost when we stored the
index ea8ae00460008db90540dcdc77baa10949b7cc31..82db7750c9bdc408f8e8b6906ec8882aad2f43ae 100644 (file)
@@ -40,7 +40,7 @@
 #include "sim/host.hh"
 #include "base/fast_alloc.hh"
 #include "base/misc.hh"
-#include "base/range_ops.hh"
+#include "base/range.hh"
 
 #include "mem/cache/cache.hh"
 #include "mem/cache/blk.hh"
@@ -62,11 +62,9 @@ Cache<TagStore>::Cache(const Params *p, TagStore *tags, BasePrefetcher *pf)
     tempBlock->data = new uint8_t[blkSize];
 
     cpuSidePort = new CpuSidePort(p->name + "-cpu_side_port", this,
-                                  "CpuSidePort",
-                                  p->cpu_side_filter_ranges);
+                                  "CpuSidePort");
     memSidePort = new MemSidePort(p->name + "-mem_side_port", this,
-                                  "MemSidePort",
-                                  p->mem_side_filter_ranges);
+                                  "MemSidePort");
     cpuSidePort->setOtherPort(memSidePort);
     memSidePort->setOtherPort(cpuSidePort);
 
@@ -96,8 +94,7 @@ Cache<TagStore>::getPort(const std::string &if_name, int idx)
     } else if (if_name == "functional") {
         CpuSidePort *funcPort =
             new CpuSidePort(name() + "-cpu_side_funcport", this,
-                            "CpuSideFuncPort",
-                            std::vector<Range<Addr> >());
+                            "CpuSideFuncPort");
         funcPort->setOtherPort(memSidePort);
         return funcPort;
     } else {
@@ -1063,35 +1060,37 @@ Cache<TagStore>::handleSnoop(PacketPtr pkt, BlkType *blk,
     assert(!(pending_inval && !is_deferred));
     assert(pkt->isRequest());
 
-    // first propagate snoop upward to see if anyone above us wants to
-    // handle it.  save & restore packet src since it will get
-    // rewritten to be relative to cpu-side bus (if any)
-    bool alreadyResponded = pkt->memInhibitAsserted();
-    if (is_timing) {
-        Packet *snoopPkt = new Packet(pkt, true);  // clear flags
-        snoopPkt->setExpressSnoop();
-        snoopPkt->senderState = new ForwardResponseRecord(pkt, this);
-        cpuSidePort->sendTiming(snoopPkt);
-        if (snoopPkt->memInhibitAsserted()) {
-            // cache-to-cache response from some upper cache
-            assert(!alreadyResponded);
-            pkt->assertMemInhibit();
+    if (forwardSnoops) {
+        // first propagate snoop upward to see if anyone above us wants to
+        // handle it.  save & restore packet src since it will get
+        // rewritten to be relative to cpu-side bus (if any)
+        bool alreadyResponded = pkt->memInhibitAsserted();
+        if (is_timing) {
+            Packet *snoopPkt = new Packet(pkt, true);  // clear flags
+            snoopPkt->setExpressSnoop();
+            snoopPkt->senderState = new ForwardResponseRecord(pkt, this);
+            cpuSidePort->sendTiming(snoopPkt);
+            if (snoopPkt->memInhibitAsserted()) {
+                // cache-to-cache response from some upper cache
+                assert(!alreadyResponded);
+                pkt->assertMemInhibit();
+            } else {
+                delete snoopPkt->senderState;
+            }
+            if (snoopPkt->sharedAsserted()) {
+                pkt->assertShared();
+            }
+            delete snoopPkt;
         } else {
-            delete snoopPkt->senderState;
-        }
-        if (snoopPkt->sharedAsserted()) {
-            pkt->assertShared();
-        }
-        delete snoopPkt;
-    } else {
-        int origSrc = pkt->getSrc();
-        cpuSidePort->sendAtomic(pkt);
-        if (!alreadyResponded && pkt->memInhibitAsserted()) {
-            // cache-to-cache response from some upper cache:
-            // forward response to original requester
-            assert(pkt->isResponse());
+            int origSrc = pkt->getSrc();
+            cpuSidePort->sendAtomic(pkt);
+            if (!alreadyResponded && pkt->memInhibitAsserted()) {
+                // cache-to-cache response from some upper cache:
+                // forward response to original requester
+                assert(pkt->isResponse());
+            }
+            pkt->setSrc(origSrc);
         }
-        pkt->setSrc(origSrc);
     }
 
     if (!blk || !blk->isValid()) {
@@ -1385,11 +1384,10 @@ void
 Cache<TagStore>::CpuSidePort::
 getDeviceAddressRanges(AddrRangeList &resp, bool &snoop)
 {
-    // CPU side port doesn't snoop; it's a target only.
-    bool dummy;
-    otherPort->getPeerAddressRanges(resp, dummy);
-    FilterRangeList(filterRanges, resp);
+    // CPU side port doesn't snoop; it's a target only.  It can
+    // potentially respond to any address.
     snoop = false;
+    resp.push_back(myCache()->getAddrRange());
 }
 
 
@@ -1428,9 +1426,8 @@ Cache<TagStore>::CpuSidePort::recvFunctional(PacketPtr pkt)
 template<class TagStore>
 Cache<TagStore>::
 CpuSidePort::CpuSidePort(const std::string &_name, Cache<TagStore> *_cache,
-                         const std::string &_label,
-                         std::vector<Range<Addr> > filterRanges)
-    : BaseCache::CachePort(_name, _cache, _label, filterRanges)
+                         const std::string &_label)
+    : BaseCache::CachePort(_name, _cache, _label)
 {
 }
 
@@ -1445,11 +1442,9 @@ void
 Cache<TagStore>::MemSidePort::
 getDeviceAddressRanges(AddrRangeList &resp, bool &snoop)
 {
-    otherPort->getPeerAddressRanges(resp, snoop);
-    FilterRangeList(filterRanges, resp);
-
-    // Memory-side port always snoops, so unconditionally set flag for
-    // caller.
+    // Memory-side port always snoops, but never passes requests
+    // through to targets on the cpu side (so we don't add anything to
+    // the address range list).
     snoop = true;
 }
 
@@ -1581,9 +1576,8 @@ Cache<TagStore>::MemSidePort::processSendEvent()
 template<class TagStore>
 Cache<TagStore>::
 MemSidePort::MemSidePort(const std::string &_name, Cache<TagStore> *_cache,
-                         const std::string &_label,
-                         std::vector<Range<Addr> > filterRanges)
-    : BaseCache::CachePort(_name, _cache, _label, filterRanges)
+                         const std::string &_label)
+    : BaseCache::CachePort(_name, _cache, _label)
 {
     // override default send event from SimpleTimingPort
     delete sendEvent;
index 5dbfa5a8b11a766a317dca46ab1b6034c867966f..3044f54335a5cdccd9e8d8add61ca7e63a5f1e2f 100644 (file)
@@ -63,8 +63,8 @@ class IOCache(BaseCache):
     mshrs = 20
     size = '1kB'
     tgts_per_mshr = 12
-    mem_side_filter_ranges=[AddrRange(0, Addr.max)]
-    cpu_side_filter_ranges=[AddrRange(0x8000000000, Addr.max)]
+    addr_range=AddrRange(0, size='8GB')
+    forward_snoops = False
 
 #cpu
 cpus = [ DerivO3CPU(cpu_id=i) for i in xrange(2) ]
index ee60ea8ae90530fb3fa39cf95e0b88e5a08a6fe3..34fa235bd68729fa2810a98c7fec55e096415e06 100644 (file)
@@ -63,8 +63,8 @@ class IOCache(BaseCache):
     mshrs = 20
     size = '1kB'
     tgts_per_mshr = 12
-    mem_side_filter_ranges=[AddrRange(0, Addr.max)]
-    cpu_side_filter_ranges=[AddrRange(0x8000000000, Addr.max)]
+    addr_range=AddrRange(0, size='8GB')
+    forward_snoops = False
 
 #cpu
 cpu = DerivO3CPU(cpu_id=0)
index 0e58d39af5fe1e856d16530b9566f9618ab723bc..593b026801ed820f58252064dcfa7c96d1493aa5 100644 (file)
@@ -62,8 +62,8 @@ class IOCache(BaseCache):
     mshrs = 20
     size = '1kB'
     tgts_per_mshr = 12
-    mem_side_filter_ranges=[AddrRange(0, Addr.max)]
-    cpu_side_filter_ranges=[AddrRange(0x8000000000, Addr.max)]
+    addr_range=AddrRange(0, size='8GB')
+    forward_snoops = False
 
 #cpu
 cpus = [ AtomicSimpleCPU(cpu_id=i) for i in xrange(2) ]
index 2374734ec54361a8429e84e6fcb0d35ef26a386b..0c6feaeace1b3dff234e93c6aa336efd5a84d752 100644 (file)
@@ -62,8 +62,8 @@ class IOCache(BaseCache):
     mshrs = 20
     size = '1kB'
     tgts_per_mshr = 12
-    mem_side_filter_ranges=[AddrRange(0, Addr.max)]
-    cpu_side_filter_ranges=[AddrRange(0x8000000000, Addr.max)]
+    addr_range=AddrRange(0, size='8GB')
+    forward_snoops = False
 
 #cpu
 cpu = AtomicSimpleCPU(cpu_id=0)
index d7c4bb6e8e5ffff36b5a5d872be33c6c0fafe5c9..21244991415bcc8f1b2cb1e5bb202558bf47c6bf 100644 (file)
@@ -62,8 +62,8 @@ class IOCache(BaseCache):
     mshrs = 20
     size = '1kB'
     tgts_per_mshr = 12
-    mem_side_filter_ranges=[AddrRange(0, Addr.max)]
-    cpu_side_filter_ranges=[AddrRange(0x8000000000, Addr.max)]
+    addr_range=AddrRange(0, size='8GB')
+    forward_snoops = False
 
 #cpu
 cpus = [ TimingSimpleCPU(cpu_id=i) for i in xrange(2) ]
index 96cd27111a718f7f49504d7eb1edf2574f464756..f0eaa08d7d6dfa7507407ce8a27007a8b4ff6dbb 100644 (file)
@@ -63,8 +63,8 @@ class IOCache(BaseCache):
     mshrs = 20
     size = '1kB'
     tgts_per_mshr = 12
-    mem_side_filter_ranges=[AddrRange(0, Addr.max)]
-    cpu_side_filter_ranges=[AddrRange(0x8000000000, Addr.max)]
+    addr_range=AddrRange(0, size='8GB')
+    forward_snoops = False
 
 #cpu
 cpu = TimingSimpleCPU(cpu_id=0)