DMA: Add IOCache and fix bus bridge to optionally only send requests one
authorAli Saidi <saidi@eecs.umich.edu>
Fri, 10 Aug 2007 20:14:01 +0000 (16:14 -0400)
committerAli Saidi <saidi@eecs.umich.edu>
Fri, 10 Aug 2007 20:14:01 +0000 (16:14 -0400)
way so a cache can handle partial block requests for i/o devices.

--HG--
extra : convert_revision : a68b5ae826731bc87ed93eb7ef326a2393053964

16 files changed:
configs/common/Caches.py
configs/common/FSConfig.py
configs/example/fs.py
src/base/range_ops.hh [new file with mode: 0644]
src/dev/io_device.hh
src/mem/Bridge.py
src/mem/bridge.cc
src/mem/bridge.hh
src/mem/bus.cc
src/mem/bus.hh
src/mem/cache/BaseCache.py
src/mem/cache/base_cache.cc
src/mem/cache/base_cache.hh
src/mem/cache/cache.hh
src/mem/cache/cache_builder.cc
src/mem/cache/cache_impl.hh

index 43a1c6378fac90b4ce5aa61a5c06ebd1b74b6397..f1ea957b5403e0e2c9e2848af599711914b5a45f 100644 (file)
@@ -43,3 +43,10 @@ class L2Cache(BaseCache):
     mshrs = 20
     tgts_per_mshr = 12
 
+class IOCache(BaseCache):
+    assoc = 8
+    block_size = 64
+    latency = '10ns'
+    mshrs = 20
+    size = '1kB'
+    tgts_per_mshr = 12
index 6bcdafb14ef8c65a2991eba3ff05753571a5bd2e..9778be3f1884de0835db867bb4365db9cdc91ef7 100644 (file)
@@ -53,7 +53,7 @@ def makeLinuxAlphaSystem(mem_mode, mdesc = None):
     self.readfile = mdesc.script()
     self.iobus = Bus(bus_id=0)
     self.membus = Bus(bus_id=1)
-    self.bridge = Bridge(fix_partial_write_b=True, delay='50ns', nack_delay='4ns')
+    self.bridge = Bridge(delay='50ns', nack_delay='4ns')
     self.physmem = PhysicalMemory(range = AddrRange(mdesc.mem()))
     self.bridge.side_a = self.iobus.port
     self.bridge.side_b = self.membus.port
index e772a3ab1223bc43a3242360641de897da0af73a..ca1408970490852b16247f84a26d9c0dea102390 100644 (file)
@@ -121,7 +121,12 @@ for i in xrange(np):
     if options.caches:
         test_sys.cpu[i].addPrivateSplitL1Caches(L1Cache(size = '32kB'),
                                                 L1Cache(size = '64kB'))
-
+        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.cpu_side = test_sys.iobus.port
+        test_sys.iocache.mem_side = test_sys.membus.port
     if options.l2cache:
         test_sys.cpu[i].connectMemPorts(test_sys.tol2bus)
     else:
diff --git a/src/base/range_ops.hh b/src/base/range_ops.hh
new file mode 100644 (file)
index 0000000..f2b11b6
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2007 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: Ali Saidi
+ */
+
+#ifndef __BASE_RANGE_OPS_HH__
+#define __BASE_RANGE_OPS_HH__
+#include <list>
+#include <vector>
+
+#include "base/range.hh"
+
+template <class T>
+inline void
+FilterRangeList(std::vector<Range<T> > filter_list, std::list<Range<T> >
+        &range_list) {
+    typename std::list<Range<T> >::iterator i;
+    for (int x = 0; x < filter_list.size(); x++) {
+        for (i = range_list.begin(); i != range_list.end(); ) {
+            // Is the range within one of our filter ranges?
+            if (filter_list[x] == i->start || filter_list[x] == i->end)
+                range_list.erase(i++);
+            else
+                i++;
+        }
+    }
+}
+
+#endif //__BASE_RANGE_OPS_HH__
+
index e65400ca29de939bbf9153039f075a1b1f543403..876166adb5525765f0b0049c18462ab4ddd26731 100644 (file)
@@ -266,8 +266,7 @@ class DmaDevice : public PioDevice
 
     void dmaWrite(Addr addr, int size, Event *event, uint8_t *data)
     {
-        dmaPort->dmaAction(MemCmd::WriteInvalidateReq,
-                           addr, size, event, data);
+        dmaPort->dmaAction(MemCmd::WriteReq, addr, size, event, data);
     }
 
     void dmaRead(Addr addr, int size, Event *event, uint8_t *data)
index 8377221cdf2c3dba45243b958ba72a026b72d587..b48e1684d7db257965b449525855a2525cc2bd89 100644 (file)
@@ -40,5 +40,7 @@ class Bridge(MemObject):
     delay = Param.Latency('0ns', "The latency of this bridge")
     nack_delay = Param.Latency('0ns', "The latency of this bridge")
     write_ack = Param.Bool(False, "Should this bridge ack writes")
-    fix_partial_write_a = Param.Bool(False, "Should this bridge fixup partial block writes")
-    fix_partial_write_b = Param.Bool(False, "Should this bridge fixup partial block writes")
+    filter_ranges_a = VectorParam.AddrRange([],
+            "What addresses shouldn't be passed through the side of the bridge")
+    filter_ranges_b = VectorParam.AddrRange([],
+            "What addresses shouldn't be passed through the side of the bridge")
index 6cfa5a2ac3a2de7f84fc10720896f9e7fc69af1c..c502c5130102df2a137857fdb00fc23d30ed2ad0 100644 (file)
@@ -37,6 +37,7 @@
 
 #include <algorithm>
 
+#include "base/range_ops.hh"
 #include "base/trace.hh"
 #include "mem/bridge.hh"
 #include "params/Bridge.hh"
 Bridge::BridgePort::BridgePort(const std::string &_name,
                                Bridge *_bridge, BridgePort *_otherPort,
                                int _delay, int _nack_delay, int _req_limit,
-                               int _resp_limit, bool fix_partial_write)
+                               int _resp_limit,
+                               std::vector<Range<Addr> > filter_ranges)
     : Port(_name), bridge(_bridge), otherPort(_otherPort),
-      delay(_delay), nackDelay(_nack_delay), fixPartialWrite(fix_partial_write),
+      delay(_delay), nackDelay(_nack_delay), filterRanges(filter_ranges),
       outstandingResponses(0), queuedRequests(0), inRetry(false),
       reqQueueLimit(_req_limit), respQueueLimit(_resp_limit), sendEvent(this)
 {
@@ -55,9 +57,9 @@ Bridge::BridgePort::BridgePort(const std::string &_name,
 Bridge::Bridge(Params *p)
     : MemObject(p->name),
       portA(p->name + "-portA", this, &portB, p->delay, p->nack_delay,
-              p->req_size_a, p->resp_size_a, p->fix_partial_write_a),
+              p->req_size_a, p->resp_size_a, p->filter_ranges_a),
       portB(p->name + "-portB", this, &portA, p->delay, p->nack_delay,
-              p->req_size_b, p->resp_size_b, p->fix_partial_write_b),
+              p->req_size_b, p->resp_size_b, p->filter_ranges_b),
       ackWrites(p->write_ack), _params(p)
 {
     if (ackWrites)
@@ -243,17 +245,6 @@ Bridge::BridgePort::trySend()
 
     PacketPtr pkt = buf->pkt;
 
-    // Ugly! @todo When multilevel coherence works this will be removed
-    if (pkt->cmd == MemCmd::WriteInvalidateReq && fixPartialWrite &&
-            !pkt->wasNacked()) {
-        PacketPtr funcPkt = new Packet(pkt->req, MemCmd::WriteReq,
-                            Packet::Broadcast);
-        funcPkt->dataStatic(pkt->getPtr<uint8_t>());
-        sendFunctional(funcPkt);
-        pkt->cmd = MemCmd::WriteReq;
-        delete funcPkt;
-    }
-
     DPRINTF(BusBridge, "trySend: origSrc %d dest %d addr 0x%x\n",
             buf->origSrc, pkt->getDest(), pkt->getAddr());
 
@@ -313,17 +304,6 @@ Bridge::BridgePort::recvRetry()
 Tick
 Bridge::BridgePort::recvAtomic(PacketPtr pkt)
 {
-    // fix partial atomic writes... similar to the timing code that does the
-    // same... will be removed once our code gets this right
-    if (pkt->cmd == MemCmd::WriteInvalidateReq && fixPartialWrite) {
-
-        PacketPtr funcPkt = new Packet(pkt->req, MemCmd::WriteReq,
-                         Packet::Broadcast);
-        funcPkt->dataStatic(pkt->getPtr<uint8_t>());
-        otherPort->sendFunctional(funcPkt);
-        delete funcPkt;
-        pkt->cmd = MemCmd::WriteReq;
-    }
     return delay + otherPort->sendAtomic(pkt);
 }
 
@@ -355,6 +335,7 @@ Bridge::BridgePort::getDeviceAddressRanges(AddrRangeList &resp,
                                            bool &snoop)
 {
     otherPort->getPeerAddressRanges(resp, snoop);
+    FilterRangeList(filterRanges, resp);
     // we don't allow snooping across bridges
     snoop = false;
 }
index d3bbf2ddfd74e73baef4615d3d23c3ab630fc359..82001948e60071670a7072d434ce6957f23bc1c5 100644 (file)
@@ -70,7 +70,8 @@ class Bridge : public MemObject
         /** Min delay to respond to a nack. */
         Tick nackDelay;
 
-        bool fixPartialWrite;
+        /** Pass ranges from one side of the bridge to the other? */
+        std::vector<Range<Addr> > filterRanges;
 
         class PacketBuffer : public Packet::SenderState {
 
@@ -156,7 +157,8 @@ class Bridge : public MemObject
         /** Constructor for the BusPort.*/
         BridgePort(const std::string &_name, Bridge *_bridge,
                 BridgePort *_otherPort, int _delay, int _nack_delay,
-                int _req_limit, int _resp_limit, bool fix_partial_write);
+                int _req_limit, int _resp_limit,
+                std::vector<Range<Addr> > filter_ranges);
 
       protected:
 
index eba96b4d2f6615cc467fc5a6ac8ae040018ca494..42c4431bba4c3f2434714f92702db7cacb3aa0d3 100644 (file)
@@ -457,6 +457,10 @@ Bus::recvStatusChange(Port::Status status, int id)
     bool snoops;
     AddrRangeIter iter;
 
+    if (inRecvStatusChange.count(id))
+        return;
+    inRecvStatusChange.insert(id);
+
     assert(status == Port::RangeChange &&
            "The other statuses need to be implemented.");
 
@@ -524,6 +528,7 @@ Bus::recvStatusChange(Port::Status status, int id)
 
     if (id != defaultId && defaultPort)
         defaultPort->sendStatusChange(Port::RangeChange);
+    inRecvStatusChange.erase(id);
 }
 
 void
index 83a4f6a55c09ccfddfc74414a960b7c021a83c8c..0c594c4633eab4cef18ecd70635a3ebf6ae2545a 100644 (file)
@@ -38,6 +38,7 @@
 #define __MEM_BUS_HH__
 
 #include <string>
+#include <set>
 #include <list>
 #include <inttypes.h>
 
@@ -253,6 +254,7 @@ class Bus : public MemObject
     BusFreeEvent busIdle;
 
     bool inRetry;
+    std::set<int> inRecvStatusChange;
 
     /** max number of bus ids we've handed out so far */
     short maxId;
index 2bf44cdf9f9bab19b751505671c79a508d4098e4..f6d42b1ef3b80741d39d2499089c2c89990aa04b 100644 (file)
@@ -81,4 +81,8 @@ 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")
index b44468486cb14c271873363e55d770c1a5e5f032..0c8b02cb371ee0e9392722515da33963a1546003 100644 (file)
 
 using namespace std;
 
-BaseCache::CachePort::CachePort(const std::string &_name, BaseCache *_cache)
+BaseCache::CachePort::CachePort(const std::string &_name, BaseCache *_cache,
+        std::vector<Range<Addr> > filter_ranges)
     : SimpleTimingPort(_name, _cache), cache(_cache), otherPort(NULL),
-      blocked(false), mustSendRetry(false)
+      blocked(false), mustSendRetry(false), filterRanges(filter_ranges)
 {
 }
 
index 719ab0245c1a0d6c96a2e3022d8edb6e252fc5f2..6a4eec43ea5f59b53b54e784877838c7c9f16fdb 100644 (file)
@@ -98,7 +98,8 @@ class BaseCache : public MemObject
         BaseCache *cache;
 
       protected:
-        CachePort(const std::string &_name, BaseCache *_cache);
+        CachePort(const std::string &_name, BaseCache *_cache,
+                std::vector<Range<Addr> > filter_ranges);
 
         virtual void recvStatusChange(Status status);
 
@@ -124,6 +125,9 @@ 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);
@@ -367,15 +371,21 @@ class BaseCache : public MemObject
          */
         Counter maxMisses;
 
+        std::vector<Range<Addr> > cpuSideFilterRanges;
+        std::vector<Range<Addr> > memSideFilterRanges;
         /**
          * Construct an instance of this parameter class.
          */
         Params(int _hitLatency, int _blkSize,
                int _numMSHRs, int _numTargets, int _numWriteBuffers,
-               Counter _maxMisses)
+               Counter _maxMisses,
+               std::vector<Range<Addr> > cpu_side_filter_ranges,
+               std::vector<Range<Addr> > mem_side_filter_ranges)
             : hitLatency(_hitLatency), blkSize(_blkSize),
               numMSHRs(_numMSHRs), numTargets(_numTargets),
-              numWriteBuffers(_numWriteBuffers), maxMisses(_maxMisses)
+              numWriteBuffers(_numWriteBuffers), maxMisses(_maxMisses),
+              cpuSideFilterRanges(cpu_side_filter_ranges),
+              memSideFilterRanges(mem_side_filter_ranges)
         {
         }
     };
index 57028a05e1e42bf0de85ce081c08e79baef70c94..821fa970208199d6d357493b0ed93b760d80ff69 100644 (file)
@@ -72,7 +72,8 @@ class Cache : public BaseCache
     {
       public:
         CpuSidePort(const std::string &_name,
-                    Cache<TagStore> *_cache);
+                    Cache<TagStore> *_cache,
+                    std::vector<Range<Addr> > filterRanges);
 
         // BaseCache::CachePort just has a BaseCache *; this function
         // lets us get back the type info we lost when we stored the
@@ -95,7 +96,8 @@ class Cache : public BaseCache
     {
       public:
         MemSidePort(const std::string &_name,
-                    Cache<TagStore> *_cache);
+                    Cache<TagStore> *_cache,
+                    std::vector<Range<Addr> > filterRanges);
 
         // BaseCache::CachePort just has a BaseCache *; this function
         // lets us get back the type info we lost when we stored the
index 4c9592a1ba23e3c53c00ebe07c9d50238cd6a78a..0f8b52af299026c74be9eb64fb7a23c840b70e38 100644 (file)
@@ -241,7 +241,8 @@ BaseCacheParams::create()
     // Build BaseCache param object
     BaseCache::Params base_params(latency, block_size,
                                   mshrs, tgts_per_mshr, write_buffers,
-                                  max_miss_count);
+                                  max_miss_count, cpu_side_filter_ranges,
+                                  mem_side_filter_ranges);
 
     //Warnings about prefetcher policy
     if (prefetch_policy == Enums::none) {
index d144266ed60108d4340e894cadc2e10bdbaaad25..402e34db2104b96df3fdea11415bfc1322c21305 100644 (file)
@@ -39,6 +39,7 @@
 
 #include "sim/host.hh"
 #include "base/misc.hh"
+#include "base/range_ops.hh"
 
 #include "mem/cache/cache.hh"
 #include "mem/cache/cache_blk.hh"
@@ -61,8 +62,10 @@ Cache<TagStore>::Cache(const std::string &_name,
     tempBlock = new BlkType();
     tempBlock->data = new uint8_t[blkSize];
 
-    cpuSidePort = new CpuSidePort(_name + "-cpu_side_port", this);
-    memSidePort = new MemSidePort(_name + "-mem_side_port", this);
+    cpuSidePort = new CpuSidePort(_name + "-cpu_side_port", this,
+            params.baseParams.cpuSideFilterRanges);
+    memSidePort = new MemSidePort(_name + "-mem_side_port", this,
+            params.baseParams.memSideFilterRanges);
     cpuSidePort->setOtherPort(memSidePort);
     memSidePort->setOtherPort(cpuSidePort);
 
@@ -88,7 +91,8 @@ Cache<TagStore>::getPort(const std::string &if_name, int idx)
     } else if (if_name == "mem_side") {
         return memSidePort;
     } else if (if_name == "functional") {
-        return new CpuSidePort(name() + "-cpu_side_funcport", this);
+        return new CpuSidePort(name() + "-cpu_side_funcport", this,
+                std::vector<Range<Addr> >());
     } else {
         panic("Port name %s unrecognized\n", if_name);
     }
@@ -1221,6 +1225,7 @@ 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);
     snoop = false;
 }
 
@@ -1262,8 +1267,9 @@ Cache<TagStore>::CpuSidePort::recvFunctional(PacketPtr pkt)
 template<class TagStore>
 Cache<TagStore>::
 CpuSidePort::CpuSidePort(const std::string &_name,
-                         Cache<TagStore> *_cache)
-    : BaseCache::CachePort(_name, _cache)
+                         Cache<TagStore> *_cache, std::vector<Range<Addr> >
+                         filterRanges)
+    : BaseCache::CachePort(_name, _cache, filterRanges)
 {
 }
 
@@ -1279,6 +1285,8 @@ 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.
     snoop = true;
@@ -1416,8 +1424,9 @@ Cache<TagStore>::MemSidePort::processSendEvent()
 
 template<class TagStore>
 Cache<TagStore>::
-MemSidePort::MemSidePort(const std::string &_name, Cache<TagStore> *_cache)
-    : BaseCache::CachePort(_name, _cache)
+MemSidePort::MemSidePort(const std::string &_name, Cache<TagStore> *_cache,
+        std::vector<Range<Addr> > filterRanges)
+    : BaseCache::CachePort(_name, _cache, filterRanges)
 {
     // override default send event from SimpleTimingPort
     delete sendEvent;