mem-cache: Add match functions to QueueEntry
authorDaniel R. Carvalho <odanrc@yahoo.com.br>
Thu, 24 Jan 2019 14:00:18 +0000 (15:00 +0100)
committerDaniel Carvalho <odanrc@yahoo.com.br>
Fri, 19 Apr 2019 16:34:00 +0000 (16:34 +0000)
Having the caller decide the matching logic is error-prone, and
frequently ends up with the secure bit being forgotten. This
change adds matching functions to the QueueEntry to avoid this
problem.

As a side effect the signature of findPending has been changed.

Change-Id: I6e494a821c1e6e841ab103ec69632c0e1b269a08
Signed-off-by: Daniel R. Carvalho <odanrc@yahoo.com.br>
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/17530
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Nikos Nikoleris <nikos.nikoleris@arm.com>
Maintainer: Nikos Nikoleris <nikos.nikoleris@arm.com>

src/mem/cache/base.cc
src/mem/cache/mshr.cc
src/mem/cache/mshr.hh
src/mem/cache/queue.hh
src/mem/cache/queue_entry.hh
src/mem/cache/write_queue_entry.cc
src/mem/cache/write_queue_entry.hh

index ddcfd80a72761a4bb3cda980d2615d130978e91d..2a6bc2a5697933406365535e3c89a1e8ebcf8cb7 100644 (file)
@@ -729,9 +729,7 @@ BaseCache::getNextQueueEntry()
     // full write buffer, otherwise we favour the miss requests
     if (wq_entry && (writeBuffer.isFull() || !miss_mshr)) {
         // need to search MSHR queue for conflicting earlier miss.
-        MSHR *conflict_mshr =
-            mshrQueue.findPending(wq_entry->blkAddr,
-                                  wq_entry->isSecure);
+        MSHR *conflict_mshr = mshrQueue.findPending(wq_entry);
 
         if (conflict_mshr && conflict_mshr->order < wq_entry->order) {
             // Service misses in order until conflict is cleared.
@@ -744,9 +742,7 @@ BaseCache::getNextQueueEntry()
         return wq_entry;
     } else if (miss_mshr) {
         // need to check for conflicting earlier writeback
-        WriteQueueEntry *conflict_mshr =
-            writeBuffer.findPending(miss_mshr->blkAddr,
-                                    miss_mshr->isSecure);
+        WriteQueueEntry *conflict_mshr = writeBuffer.findPending(miss_mshr);
         if (conflict_mshr) {
             // not sure why we don't check order here... it was in the
             // original code but commented out.
index 8db7c2997c31567f588cd1913f692a2f94d815d9..13a50169c4a7c7c31994221b9c8eaae0720c7f07 100644 (file)
@@ -273,6 +273,9 @@ MSHR::allocate(Addr blk_addr, unsigned blk_size, PacketPtr target,
     Target::Source source = (target->cmd == MemCmd::HardPFReq) ?
         Target::FromPrefetcher : Target::FromCPU;
     targets.add(target, when_ready, _order, source, true, alloc_on_fill);
+
+    // All targets must refer to the same block
+    assert(target->matchBlockAddr(targets.front().pkt, blkSize));
 }
 
 
@@ -685,3 +688,24 @@ MSHR::print() const
     print(str);
     return str.str();
 }
+
+bool
+MSHR::matchBlockAddr(const Addr addr, const bool is_secure) const
+{
+    assert(hasTargets());
+    return (blkAddr == addr) && (isSecure == is_secure);
+}
+
+bool
+MSHR::matchBlockAddr(const PacketPtr pkt) const
+{
+    assert(hasTargets());
+    return pkt->matchBlockAddr(blkAddr, isSecure, blkSize);
+}
+
+bool
+MSHR::conflictAddr(const QueueEntry* entry) const
+{
+    assert(hasTargets());
+    return entry->matchBlockAddr(blkAddr, isSecure);
+}
index e9505ebdce2ee164a7f1e9ba324647b2d02f902d..4b054894d6417e5a168dae2b164efca9d8ee427b 100644 (file)
@@ -531,6 +531,10 @@ class MSHR : public QueueEntry, public Printable
      * @return string with mshr fields + [deferred]targets
      */
     std::string print() const;
+
+    bool matchBlockAddr(const Addr addr, const bool is_secure) const override;
+    bool matchBlockAddr(const PacketPtr pkt) const override;
+    bool conflictAddr(const QueueEntry* entry) const override;
 };
 
 #endif // __MEM_CACHE_MSHR_HH__
index 6c8a192655ecc8c99d8c411c17fb58ff16f05cfd..30fe4bad6a8f2710559f829d1e900d511c16767a 100644 (file)
@@ -174,7 +174,7 @@ class Queue : public Drainable
             // cacheable accesses being added to an WriteQueueEntry
             // serving an uncacheable access
             if (!(ignore_uncacheable && entry->isUncacheable()) &&
-                entry->blkAddr == blk_addr && entry->isSecure == is_secure) {
+                entry->matchBlockAddr(blk_addr, is_secure)) {
                 return entry;
             }
         }
@@ -185,7 +185,8 @@ class Queue : public Drainable
     {
         pkt->pushLabel(label);
         for (const auto& entry : allocatedList) {
-            if (entry->blkAddr == blk_addr && entry->trySatisfyFunctional(pkt)) {
+            if (entry->matchBlockAddr(blk_addr, pkt->isSecure()) &&
+                entry->trySatisfyFunctional(pkt)) {
                 pkt->popLabel();
                 return true;
             }
@@ -195,16 +196,17 @@ class Queue : public Drainable
     }
 
     /**
-     * Find any pending requests that overlap the given request.
-     * @param blk_addr Block address.
-     * @param is_secure True if the target memory space is secure.
-     * @return A pointer to the earliest matching WriteQueueEntry.
+     * Find any pending requests that overlap the given request of a
+     * different queue.
+     *
+     * @param entry The entry to be compared against.
+     * @return A pointer to the earliest matching entry.
      */
-    Entry* findPending(Addr blk_addr, bool is_secure) const
+    Entry* findPending(const QueueEntry* entry) const
     {
-        for (const auto& entry : readyList) {
-            if (entry->blkAddr == blk_addr && entry->isSecure == is_secure) {
-                return entry;
+        for (const auto& ready_entry : readyList) {
+            if (ready_entry->conflictAddr(entry)) {
+                return ready_entry;
             }
         }
         return nullptr;
index 39ee0a0b950b272277f5b9f2db6ea005bb458fdf..61c898dd46231af5ba7dc07d66d5522767bee239 100644 (file)
@@ -119,13 +119,40 @@ class QueueEntry : public Packet::SenderState
     /** True if the entry targets the secure memory space. */
     bool isSecure;
 
-    QueueEntry() : readyTime(0), _isUncacheable(false),
-                   inService(false), order(0), blkAddr(0), blkSize(0),
-                   isSecure(false)
+    QueueEntry()
+        : readyTime(0), _isUncacheable(false),
+          inService(false), order(0), blkAddr(0), blkSize(0), isSecure(false)
     {}
 
     bool isUncacheable() const { return _isUncacheable; }
 
+    /**
+     * Check if entry corresponds to the one being looked for.
+     *
+     * @param addr Address to match against.
+     * @param is_secure Whether the target should be in secure space or not.
+     * @return True if entry matches given information.
+     */
+    virtual bool matchBlockAddr(const Addr addr, const bool is_secure)
+                                                            const = 0;
+
+    /**
+     * Check if entry contains a packet that corresponds to the one being
+     * looked for.
+     *
+     * @param pkt The packet to search for.
+     * @return True if any of its targets' packets matches the given one.
+     */
+    virtual bool matchBlockAddr(const PacketPtr pkt) const = 0;
+
+    /**
+     * Check if given entry's packets conflict with this' entries packets.
+     *
+     * @param entry Other entry to compare against.
+     * @return True if entry matches given information.
+     */
+    virtual bool conflictAddr(const QueueEntry* entry) const = 0;
+
     /**
      * Send this queue entry as a downstream packet, with the exact
      * behaviour depending on the specific entry type.
index 6c8387bcbe0eccc80f35a5a62c340c30c2d78bd6..f3106e4bcbeead9e30392e74cce915788c91c4ab 100644 (file)
@@ -112,6 +112,9 @@ WriteQueueEntry::allocate(Addr blk_addr, unsigned blk_size, PacketPtr target,
              "a cacheable eviction or a writeclean");
 
     targets.add(target, when_ready, _order);
+
+    // All targets must refer to the same block
+    assert(target->matchBlockAddr(targets.front().pkt, blkSize));
 }
 
 void
@@ -141,6 +144,27 @@ WriteQueueEntry::sendPacket(BaseCache &cache)
     return cache.sendWriteQueuePacket(this);
 }
 
+bool
+WriteQueueEntry::matchBlockAddr(const Addr addr, const bool is_secure) const
+{
+    assert(hasTargets());
+    return (blkAddr == addr) && (isSecure == is_secure);
+}
+
+bool
+WriteQueueEntry::matchBlockAddr(const PacketPtr pkt) const
+{
+    assert(hasTargets());
+    return pkt->matchBlockAddr(blkAddr, isSecure, blkSize);
+}
+
+bool
+WriteQueueEntry::conflictAddr(const QueueEntry* entry) const
+{
+    assert(hasTargets());
+    return entry->matchBlockAddr(blkAddr, isSecure);
+}
+
 void
 WriteQueueEntry::print(std::ostream &os, int verbosity,
                        const std::string &prefix) const
index 59714d9486aedbb1ace3ce506ec37afd03a56f75..9aaac493c387ebc7e0ec993ce33fbea07ef0089b 100644 (file)
@@ -179,6 +179,10 @@ class WriteQueueEntry : public QueueEntry, public Printable
      * @return string with mshr fields
      */
     std::string print() const;
+
+    bool matchBlockAddr(const Addr addr, const bool is_secure) const override;
+    bool matchBlockAddr(const PacketPtr pkt) const override;
+    bool conflictAddr(const QueueEntry* entry) const override;
 };
 
 #endif // __MEM_CACHE_WRITE_QUEUE_ENTRY_HH__