Ivan Pizarro has uploaded this change for review. ( https://gem5-review.googlesource.com/c/public/gem5/+/16968

Change subject: mem-cache: Proactive Instruction Fetch Implementation
......................................................................

mem-cache: Proactive Instruction Fetch Implementation

Ferdman, M., Kaynak, C., & Falsafi, B. (2011, December).
Proactive instruction fetch. In Proceedings of the 44th Annual IEEE/ACM
International Symposium on Microarchitecture (pp. 152-162). ACM.

Change-Id: I38c3ab30a94ab279f03e3d5936ce8ed118310c0e
---
M src/cpu/base.cc
M src/cpu/base.hh
M src/cpu/o3/cpu.cc
M src/mem/cache/prefetch/Prefetcher.py
M src/mem/cache/prefetch/SConscript
M src/mem/cache/prefetch/base.cc
M src/mem/cache/prefetch/base.hh
A src/mem/cache/prefetch/pif.cc
A src/mem/cache/prefetch/pif.hh
9 files changed, 415 insertions(+), 4 deletions(-)



diff --git a/src/cpu/base.cc b/src/cpu/base.cc
index 30f6baf..1c3269b 100644
--- a/src/cpu/base.cc
+++ b/src/cpu/base.cc
@@ -391,6 +391,7 @@
     ppActiveCycles = pmuProbePoint("ActiveCycles");

     ppRetiredInsts = pmuProbePoint("RetiredInsts");
+    ppRetiredInstsPC = pmuProbePoint("RetiredInstsPC");
     ppRetiredLoads = pmuProbePoint("RetiredLoads");
     ppRetiredStores = pmuProbePoint("RetiredStores");
     ppRetiredBranches = pmuProbePoint("RetiredBranches");
@@ -417,6 +418,14 @@
 }

 void
+BaseCPU::probeInstCommitPC(const StaticInstPtr &inst, Addr pc)
+{
+    if (!inst->isMicroop() || inst->isLastMicroop()) {
+        ppRetiredInstsPC->notify(pc);
+    }
+}
+
+void
 BaseCPU::regStats()
 {
     MemObject::regStats();
diff --git a/src/cpu/base.hh b/src/cpu/base.hh
index 8673d23..f947181 100644
--- a/src/cpu/base.hh
+++ b/src/cpu/base.hh
@@ -490,6 +490,15 @@
      */
     virtual void probeInstCommit(const StaticInstPtr &inst);

+    /**
+     * Helper method to trigger PMU probes for a committed
+     * instruction.
+     *
+     * @param inst Instruction that just committed
+     * @param pc PC of the instruction that just committed
+     */
+    virtual void probeInstCommitPC(const StaticInstPtr &inst, Addr pc);
+
    protected:
     /**
      * Helper method to instantiate probe points belonging to this
@@ -509,6 +518,7 @@
      * instructions may call notify once for the entire bundle.
      */
     ProbePoints::PMUUPtr ppRetiredInsts;
+    ProbePoints::PMUUPtr ppRetiredInstsPC;

     /** Retired load instructions */
     ProbePoints::PMUUPtr ppRetiredLoads;
diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc
index 965ab04..40dee4a 100644
--- a/src/cpu/o3/cpu.cc
+++ b/src/cpu/o3/cpu.cc
@@ -1624,6 +1624,7 @@
     committedOps[tid]++;

     probeInstCommit(inst->staticInst);
+    probeInstCommitPC(inst->staticInst, inst->instAddr());
 }

 template <class Impl>
diff --git a/src/mem/cache/prefetch/Prefetcher.py b/src/mem/cache/prefetch/Prefetcher.py
index 31d7486..6027335 100644
--- a/src/mem/cache/prefetch/Prefetcher.py
+++ b/src/mem/cache/prefetch/Prefetcher.py
@@ -43,6 +43,7 @@
 from m5.params import *
 from m5.proxy import *

+from m5.objects.BaseCPU import BaseCPU
 from m5.objects.ClockedObject import ClockedObject
 from m5.objects.IndexingPolicies import *
 from m5.objects.ReplacementPolicies import *
@@ -65,6 +66,7 @@
     cxx_header = "mem/cache/prefetch/base.hh"
     cxx_exports = [
         PyBindMethod("addEventProbe"),
+        PyBindMethod("addCPU"),
     ]
     sys = Param.System(Parent.any, "System this prefetcher belongs to")

@@ -90,6 +92,8 @@
     def regProbeListeners(self):
         for event in self._events:
            event.register()
+        for cpu in self._cpus:
+            self.getCCObject().addCPU(cpu.getCCObject())
         self.getCCObject().regProbeListeners()

     def listenFromProbe(self, simObj, *probeNames):
@@ -99,6 +103,12 @@
             raise TypeError("probeNames must have at least one element")
         self.addEvent(HWPProbeEvent(self, simObj, *probeNames))

+    _cpus = []
+    def registerCPU(self, simObj):
+        if not isinstance(simObj, BaseCPU):
+            raise TypeError("argument must be a BaseCPU type")
+        self._cpus.append(simObj)
+
 class QueuedPrefetcher(BasePrefetcher):
     type = "QueuedPrefetcher"
     abstract = True
@@ -363,3 +373,16 @@
     delay_queue_cycles = Param.Cycles(60,
"Cycles to delay a write in the left RR table from the delay \
                 queue")
+
+class PIFPrefetcher(QueuedPrefetcher):
+    type = 'PIFPrefetcher'
+    cxx_class = 'PIFPrefetcher'
+    cxx_header = "mem/cache/prefetch/pif.hh"
+
+    precSpatialRegionBits = Param.Unsigned(1,
+        "Number of preceding addresses in the spatial region")
+    succSpatialRegionBits = Param.Unsigned(2,
+        "Number of subsequent addresses in the spatial region")
+    compactorEntries = Param.Unsigned(2, "Entries in the temp. compactor")
+    streamAddressBufferEntries = Param.Unsigned(7, "Entries in the SAB")
+    historyBufferSize = Param.Unsigned(16, "Entries in the history buffer")
diff --git a/src/mem/cache/prefetch/SConscript b/src/mem/cache/prefetch/SConscript
index d87b694..d28b9e9 100644
--- a/src/mem/cache/prefetch/SConscript
+++ b/src/mem/cache/prefetch/SConscript
@@ -37,6 +37,7 @@
 Source('bop.cc')
 Source('delta_correlating_prediction_tables.cc')
 Source('irregular_stream_buffer.cc')
+Source('pif.cc')
 Source('queued.cc')
 Source('signature_path.cc')
 Source('signature_path_v2.cc')
diff --git a/src/mem/cache/prefetch/base.cc b/src/mem/cache/prefetch/base.cc
index 52f5d1a..8417e9e 100644
--- a/src/mem/cache/prefetch/base.cc
+++ b/src/mem/cache/prefetch/base.cc
@@ -79,11 +79,18 @@
     }
 }

+void
+BasePrefetcher::PrefetchListenerPC::notify(const Addr& pc)
+{
+    parent.notifyRetiredInst(pc);
+}
+
 BasePrefetcher::BasePrefetcher(const BasePrefetcherParams *p)
- : ClockedObject(p), listeners(), cache(nullptr), blkSize(p->block_size),
-      lBlkSize(floorLog2(blkSize)), onMiss(p->on_miss), onRead(p->on_read),
-      onWrite(p->on_write), onData(p->on_data), onInst(p->on_inst),
- masterId(p->sys->getMasterId(this)), pageBytes(p->sys->getPageBytes()),
+    : ClockedObject(p), listeners(), listenersPC(), cache(nullptr),
+ blkSize(p->block_size), lBlkSize(floorLog2(blkSize)), onMiss(p->on_miss),
+      onRead(p->on_read), onWrite(p->on_write), onData(p->on_data),
+      onInst(p->on_inst), masterId(p->sys->getMasterId(this)),
+      pageBytes(p->sys->getPageBytes()),
       prefetchOnAccess(p->prefetch_on_access),
       useVirtualAddresses(p->use_virtual_addresses), issuedPrefetches(0),
       usefulPrefetches(0)
@@ -233,6 +240,14 @@
             listeners.push_back(new PrefetchListener(*this, pm, "Hit"));
         }
     }
+
+    if (!cpus.empty()) {
+        for (auto& cpu : cpus) {
+            ProbeManager *pm(cpu->getProbeManager());
+            listenersPC.push_back(new PrefetchListenerPC(*this, pm,
+                "RetiredInstsPC"));
+        }
+    }
 }

 void
@@ -241,3 +256,9 @@
     ProbeManager *pm(obj->getProbeManager());
     listeners.push_back(new PrefetchListener(*this, pm, name));
 }
+
+void
+BasePrefetcher::addCPU(BaseCPU *cpu)
+{
+    cpus.push_back(cpu);
+}
diff --git a/src/mem/cache/prefetch/base.hh b/src/mem/cache/prefetch/base.hh
index 4df8428..ee42656 100644
--- a/src/mem/cache/prefetch/base.hh
+++ b/src/mem/cache/prefetch/base.hh
@@ -53,6 +53,7 @@

 #include "base/statistics.hh"
 #include "base/types.hh"
+#include "cpu/base.hh"
 #include "mem/packet.hh"
 #include "mem/request.hh"
 #include "sim/clocked_object.hh"
@@ -76,7 +77,20 @@
         bool isFill;
     };

+    class PrefetchListenerPC : public ProbeListenerArgBase<Addr>
+    {
+      public:
+        PrefetchListenerPC(BasePrefetcher &_parent, ProbeManager *pm,
+                         const std::string &name)
+            : ProbeListenerArgBase(pm, name),
+              parent(_parent) {}
+        void notify(const Addr& pc) override;
+      protected:
+        BasePrefetcher &parent;
+    };
+
     std::vector<PrefetchListener *> listeners;
+    std::vector<PrefetchListenerPC *> listenersPC;

   public:

@@ -240,6 +254,9 @@
     /** Total prefetches that has been useful */
     uint64_t usefulPrefetches;

+    /** Registered cpus */
+    std::list<BaseCPU*> cpus;
+
   public:

     BasePrefetcher(const BasePrefetcherParams *p);
@@ -258,6 +275,10 @@
     virtual void notifyFill(const PacketPtr &pkt)
     {}

+    /** Notify prefetcher of instruction retired */
+    virtual void notifyRetiredInst(const Addr pc)
+    {}
+
     virtual PacketPtr getPacket() = 0;

     virtual Tick nextPrefetchReadyTime() const = 0;
@@ -284,5 +305,10 @@
      * @param name The probe name
      */
     void addEventProbe(SimObject *obj, const char *name);
+
+    /**
+     * TODO
+     */
+    void addCPU(BaseCPU *cpu);
 };
 #endif //__MEM_CACHE_PREFETCH_BASE_HH__
diff --git a/src/mem/cache/prefetch/pif.cc b/src/mem/cache/prefetch/pif.cc
new file mode 100644
index 0000000..e18bee8
--- /dev/null
+++ b/src/mem/cache/prefetch/pif.cc
@@ -0,0 +1,189 @@
+/**
+ * Copyright (c) 2019 Metempsy Technology Consulting
+ * 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: Ivan Pizarro
+ */
+
+#include "mem/cache/prefetch/pif.hh"
+
+#include "debug/HWPrefetch.hh"
+#include "params/PIFPrefetcher.hh"
+
+PIFPrefetcher::PIFPrefetcher(const PIFPrefetcherParams *p)
+    : QueuedPrefetcher(p),
+      precSize(p->precSpatialRegionBits),
+      succSize(p->succSpatialRegionBits),
+      maxCompactorEntries(p->compactorEntries),
+      maxStreamAddressBufferEntries(p->streamAddressBufferEntries),
+      historyBuffer(p->historyBufferSize),
+      historyBufferTail(0)
+{
+}
+
+PIFPrefetcher::CompactorEntry::CompactorEntry(Addr addr,
+    unsigned int prec_size, unsigned int succ_size)
+{
+    trigger = addr;
+    prec.resize(prec_size, false);
+    succ.resize(succ_size, false);
+}
+
+bool
+PIFPrefetcher::inSameSpatialRegion(Addr pc, const CompactorEntry& ce,
+    unsigned int& blk_distance)
+{
+    const Addr pc_blk = pc >> lBlkSize;
+    const Addr trigger_blk = ce.trigger >> lBlkSize;
+
+    blk_distance = abs(pc_blk - trigger_blk);
+
+    return (pc_blk > trigger_blk) ?
+                (succSize < blk_distance) : (precSize < blk_distance);
+}
+
+void
+PIFPrefetcher::notifyRetiredInst(const Addr pc)
+{
+    // First access to the prefetcher
+    if (temporalCompactor.size() == 0) {
+        spatialCompactor = CompactorEntry(pc, precSize, succSize);
+    } else {
+ // If the PC of the instruction retired is in the same spatial region + // than the last trigger address, update the bit vectors based on the
+        // distance between them
+        unsigned int blk_distance;
+
+        if (inSameSpatialRegion(pc, spatialCompactor, blk_distance)) {
+            if (pc > spatialCompactor.trigger) {
+                spatialCompactor.succ[blk_distance] = true;
+            } else if (pc < spatialCompactor.trigger) {
+                spatialCompactor.prec[blk_distance] = true;
+            }
+ // If the PC of the instruction retired is outside the latest spatial + // region, check if it matches in any of the regions in the temporal
+        // compactor and update it to the MRU position
+        } else {
+            bool isInTemporalCompactor = false;
+
+            // Check if the PC is in the temporal compactor
+            for (auto it = temporalCompactor.begin();
+                    it != temporalCompactor.end(); it++)
+            {
+                if (inSameSpatialRegion(pc, (*it), blk_distance)) {
+                    spatialCompactor = (*it);
+                    temporalCompactor.erase(it);
+                    isInTemporalCompactor = true;
+                    break;
+                }
+            }
+
+            if (temporalCompactor.size() == maxCompactorEntries) {
+                temporalCompactor.pop_front(); // Discard the LRU entry
+            }
+
+            temporalCompactor.push_back(spatialCompactor);
+
+            if (historyBufferTail == historyBuffer.size()) {
+                historyBufferTail = 0;
+            }
+
+            // If the compactor entry is neither the spatial or can't be
+            // found in the temporal compactor, reset the spatial compactor
+            // updating the trigger address and resetting the vector bits
+            if (!isInTemporalCompactor) {
+ // Insert the spatial entry into the history buffer and update
+                // the 'index' table to point to the new entry
+                historyBuffer[historyBufferTail] = spatialCompactor;
+
+                index.insert(std::pair<Addr, unsigned int>(
+ spatialCompactor.trigger, historyBufferTail));
+
+                historyBufferTail++;
+
+                // Reset the spatial compactor fields with the new address
+                spatialCompactor = CompactorEntry(pc, precSize, succSize);
+            }
+        }
+    }
+}
+
+void
+PIFPrefetcher::calculatePrefetch(const PrefetchInfo &pfi,
+    std::vector<AddrPriority> &addresses)
+{
+    const Addr addr = pfi.getAddr();
+
+ // Check if a valid entry in the 'index' table is found and allocate a new
+    // active prediction stream
+    const auto index_it = index.find(addr);
+
+    if (index_it != index.end()) {
+        // Trigger address from the 'index' table and index to the history
+        // buffer
+        const unsigned int hb_entry = (*index_it).second;
+
+        // Track the block in the Stream Address Buffer
+        if (streamAddressBuffer.size() == maxStreamAddressBufferEntries) {
+            streamAddressBuffer.pop_front();
+        }
+
+        streamAddressBuffer.push_back(&historyBuffer[hb_entry]);
+
+ // Calculate the addresses of the instruction blocks that are encoded + // by the bit vector and issue prefetch requests for these addresses. + // Predictions are made by traversing the bit vector from left to right + // as this typically predicts the accesses in the order they will be
+        // issued in the core.
+        //
+ // Before queueing the prefetch, first probe the cache to confirm that
+        // the block is not present in the cache.
+        const Addr trigger_blk = (*index_it).first >> lBlkSize;
+
+ for (int i = streamAddressBuffer.back()->prec.size()-1; i >= 0; i--) {
+            bool prec = streamAddressBuffer.back()->prec[i];
+            // Address from the preceding blocks to issue a prefetch
+            const Addr prec_addr = (trigger_blk - i) << lBlkSize;
+            if (prec && !inCache(prec_addr, pfi.isSecure())) {
+                addresses.push_back(AddrPriority(prec_addr, 0));
+            }
+        }
+        for (int i = 0; i < streamAddressBuffer.back()->succ.size(); i++) {
+            bool succ = streamAddressBuffer.back()->succ[i];
+            // Address from the succeding blocks to issue a prefetch
+            const Addr succ_addr = (trigger_blk + i) << lBlkSize;
+            if (succ && !inCache(succ_addr, pfi.isSecure())) {
+                addresses.push_back(AddrPriority(succ_addr, 0));
+            }
+        }
+    }
+}
+
+PIFPrefetcher*
+PIFPrefetcherParams::create()
+{
+    return new PIFPrefetcher(this);
+}
diff --git a/src/mem/cache/prefetch/pif.hh b/src/mem/cache/prefetch/pif.hh
new file mode 100644
index 0000000..b5263cf
--- /dev/null
+++ b/src/mem/cache/prefetch/pif.hh
@@ -0,0 +1,131 @@
+/**
+ * Copyright (c) 2019 Metempsy Technology Consulting
+ * 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: Ivan Pizarro
+ */
+
+/** Implementation of the 'Proactive Instruction Fetch' prefetcher
+ *  Reference:
+ *    Ferdman, M., Kaynak, C., & Falsafi, B. (2011, December).
+ *    Proactive instruction fetch.
+ *    In Proceedings of the 44th Annual IEEE/ACM International Symposium
+ *    on Microarchitecture (pp. 152-162). ACM.
+ */
+
+#ifndef __MEM_CACHE_PREFETCH_PIF_HH__
+#define __MEM_CACHE_PREFETCH_PIF_HH__
+
+#include <deque>
+
+#include "mem/cache/prefetch/queued.hh"
+
+struct PIFPrefetcherParams;
+
+class PIFPrefetcher : public QueuedPrefetcher
+{
+    private:
+
+ /** Number of preceding and subsequent spatial addresses to compact */
+        const unsigned int precSize;
+        const unsigned int succSize;
+        /** Number of entries used for the temporal compactor */
+        const unsigned int maxCompactorEntries;
+ /** Max number of entries to be used in the Stream Address Buffer */
+        const unsigned int maxStreamAddressBufferEntries;
+
+        /**
+ * The compactor tracks retired instructions addresses, leveraging the + * spatial and temporal locality among instructions for compaction. It
+         *comprises the spatial and temporal compaction mechanisms.
+         *
+ * Taking advantage of the spatial locality across instruction blocks, + * the spatial compactor combines instruction-block addresses that fall + * within a 'spatial region', a group of adjacent instruction blocks. + * When an instruction outside the current spatial region retires, the
+         * existing spatial region is sent to the temporal compactor.
+         *
+         * The temporal compactor tracks a small number of the
+         * most-recently-observed spatial region records.
+         */
+        struct CompactorEntry {
+            Addr trigger;
+            std::vector<bool> prec;
+            std::vector<bool> succ;
+            CompactorEntry() {}
+            CompactorEntry(Addr, unsigned int, unsigned int);
+        };
+
+        CompactorEntry spatialCompactor;
+        std::deque<CompactorEntry> temporalCompactor;
+
+        /**
+         * History buffer is a circular buffer that stores the sequence of
+         * retired instructions in FIFO order.
+         */
+        std::vector<CompactorEntry> historyBuffer;
+        unsigned int historyBufferTail;
+
+        /**
+         * The index table is a small cache-like structure that facilitates
+         * fast search of the history buffer.
+         */
+        std::map<Addr, unsigned int> index;
+
+        /**
+         * A Stream Address Buffer (SAB) tracks a window of consecutive
+ * spatial regions. The SAB mantains a pointer to the sequence in the + * history buffer, initiallly set to the pointer taken from the index
+         * table
+         */
+        std::deque<CompactorEntry*> streamAddressBuffer;
+
+        /**
+ * Checks if a given address is in the same defined spatial region as
+         * the compactor entry.
+         * @param addr Address to check if it's inside the spatial region
+         * @param ce Compactor entry defining the spatial region
+         * @param blk_distance Distance between the trigger and the addr
+ * @return TRUE if they are in the same spatial region, FALSE otherwise
+         */
+        bool inSameSpatialRegion(Addr addr, const CompactorEntry& ce,
+                                 unsigned int& blk_distance);
+
+        /**
+         * Updates the prefetcher structures upon an instruction retired
+         * @param pc PC of the instruction being retired
+         */
+        void notifyRetiredInst(const Addr pc) override;
+
+    public:
+        PIFPrefetcher(const PIFPrefetcherParams *p);
+        ~PIFPrefetcher() {}
+
+        void calculatePrefetch(const PrefetchInfo &pfi,
+                               std::vector<AddrPriority> &addresses);
+};
+
+#endif // __MEM_CACHE_PREFETCH_PIF_HH__

--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/16968
To unsubscribe, or for help writing mail filters, visit https://gem5-review.googlesource.com/settings

Gerrit-Project: public/gem5
Gerrit-Branch: master
Gerrit-Change-Id: I38c3ab30a94ab279f03e3d5936ce8ed118310c0e
Gerrit-Change-Number: 16968
Gerrit-PatchSet: 1
Gerrit-Owner: Ivan Pizarro <[email protected]>
Gerrit-MessageType: newchange
_______________________________________________
gem5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/gem5-dev

Reply via email to