cpu: Remove the "SingleThreaded" fetch policy from the O3 CPU.
[gem5.git] / src / cpu / decode_cache.hh
index 1bff315d161160846048ad232c5bbadbd843c2e4..20b6783d2d79d2f4fb4995e589426cbe72622f61 100644 (file)
  * 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: Gabe Black
  */
 
 #ifndef __CPU_DECODE_CACHE_HH__
 #define __CPU_DECODE_CACHE_HH__
 
-#include "arch/isa_traits.hh"
-#include "arch/types.hh"
-#include "base/hashmap.hh"
-#include "config/the_isa.hh"
-#include "cpu/static_inst.hh"
+#include <unordered_map>
 
-typedef StaticInstPtr (*DecodeInstFunc)(TheISA::ExtMachInst);
+#include "base/bitfield.hh"
+#include "cpu/static_inst_fwd.hh"
 
-template <DecodeInstFunc decodeInstFunc>
-class DecodeCache
+namespace DecodeCache
 {
-  private:
-    typedef TheISA::ExtMachInst ExtMachInst;
 
-    /// Hash of decoded instructions.
-    typedef m5::hash_map<ExtMachInst, StaticInstPtr> InstMap;
-    InstMap instMap;
+/// Hash for decoded instructions.
+template <typename EMI>
+using InstMap = std::unordered_map<EMI, StaticInstPtr>;
+
+/// A sparse map from an Addr to a Value, stored in page chunks.
+template<class Value, Addr CacheChunkShift = 12>
+class AddrMap
+{
+  protected:
+    static constexpr Addr CacheChunkBytes = 1ULL << CacheChunkShift;
 
-    /// A table of instructions which are already been decoded, indexed by
-    /// page offset.
-    class DecodePage
+    static constexpr Addr
+    chunkOffset(Addr addr)
     {
-      protected:
-        StaticInstPtr instructions[TheISA::PageBytes];
-
-        // A helper function to compute the index of an address in the table.
-        Addr offset(Addr addr) { return addr & (TheISA::PageBytes - 1); }
-
-      public:
-        /// Decode the given instruction. First attempt to find it in the
-        /// table, then in the generic decode cache, and finally call the
-        /// actual decode function.
-        ///
-        /// @param mach_inst The predecoded instruction to decode.
-        /// @param addr The address the instruction came from.
-        /// @param cache A cache of already decoded instructions.
-        /// @retval The decoded instruction object.
-        StaticInstPtr
-        decode(const ExtMachInst &mach_inst, Addr addr, InstMap &instMap)
-        {
-            StaticInstPtr si = instructions[offset(addr)];
-            if (si && (si->machInst == mach_inst)) {
-                return si;
-            }
+        return addr & (CacheChunkBytes - 1);
+    }
 
-            InstMap::iterator iter = instMap.find(mach_inst);
-            if (iter != instMap.end()) {
-                si = iter->second;
-            } else {
-                si = decodeInstFunc(mach_inst);
-                instMap[mach_inst] = si;
-            }
+    static constexpr Addr
+    chunkStart(Addr addr)
+    {
+        return addr & ~(CacheChunkBytes - 1);
+    }
 
-            instructions[offset(addr)] = si;
-            return si;
-        }
+    // A chunk of cache entries.
+    struct CacheChunk
+    {
+        Value items[CacheChunkBytes];
     };
-
-    /// A store of DecodePages. Basically a slightly smarter hash_map.
-    class DecodePages
+    // A map of cache chunks which allows a sparse mapping.
+    typedef typename std::unordered_map<Addr, CacheChunk *> ChunkMap;
+    typedef typename ChunkMap::iterator ChunkIt;
+    // Mini cache of recent lookups.
+    ChunkIt recent[2];
+    ChunkMap chunkMap;
+
+    /// Update the mini cache of recent lookups.
+    /// @param recentest The most recent result;
+    void
+    update(ChunkIt recentest)
     {
-      protected:
-        typedef typename m5::hash_map<Addr, DecodePage *> PageMap;
-        typedef typename PageMap::iterator PageIt;
-        PageIt recent[2];
-        PageMap pageMap;
-
-        /// Update the small cache of recent lookups.
-        /// @param recentest The most recent result;
-        void
-        update(PageIt recentest)
-        {
-            recent[1] = recent[0];
-            recent[0] = recentest;
-        }
-
-      public:
-        /// Constructor
-        DecodePages()
-        {
-            recent[0] = recent[1] = pageMap.end();
-        }
-
-        /// Attempt to find the DecodePage which goes with a particular
-        /// address. First check the small cache of recent results, then
-        /// actually look in the hash_map.
-        /// @param addr The address to look up.
-        DecodePage *
-        findPage(Addr addr)
-        {
-            Addr page_addr = addr & ~(TheISA::PageBytes - 1);
-
-            // Check against recent lookups.
-            if (recent[0] != pageMap.end()) {
-                if (recent[0]->first == page_addr)
-                    return recent[0]->second;
-                if (recent[1] != pageMap.end() &&
-                        recent[1]->first == page_addr) {
-                    update(recent[1]);
-                    // recent[1] has just become recent[0].
-                    return recent[0]->second;
-                }
-            }
+        recent[1] = recent[0];
+        recent[0] = recentest;
+    }
 
-            // Actually look in the has_map.
-            PageIt it = pageMap.find(page_addr);
-            if (it != pageMap.end()) {
-                update(it);
-                return it->second;
+    /// Attempt to find the CacheChunk which goes with a particular
+    /// address. First check the small cache of recent results, then
+    /// actually look in the hash map.
+    /// @param addr The address to look up.
+    CacheChunk *
+    getChunk(Addr addr)
+    {
+        Addr chunk_addr = chunkStart(addr);
+
+        // Check against recent lookups.
+        if (recent[0] != chunkMap.end()) {
+            if (recent[0]->first == chunk_addr)
+                return recent[0]->second;
+            if (recent[1] != chunkMap.end() &&
+                    recent[1]->first == chunk_addr) {
+                update(recent[1]);
+                // recent[1] has just become recent[0].
+                return recent[0]->second;
             }
-
-            // Didn't find it so return NULL.
-            return NULL;
         }
 
-        void
-        addPage(Addr addr, DecodePage *page)
-        {
-            Addr page_addr = addr & ~(TheISA::PageBytes - 1);
-            typename PageMap::value_type to_insert(page_addr, page);
-            update(pageMap.insert(to_insert).first);
+        // Actually look in the hash_map.
+        ChunkIt it = chunkMap.find(chunk_addr);
+        if (it != chunkMap.end()) {
+            update(it);
+            return it->second;
         }
-    } decodePages;
+
+        // Didn't find an existing chunk, so add a new one.
+        CacheChunk *newChunk = new CacheChunk;
+        typename ChunkMap::value_type to_insert(chunk_addr, newChunk);
+        update(chunkMap.insert(to_insert).first);
+        return newChunk;
+    }
 
   public:
-    /// Decode a machine instruction.
-    /// @param mach_inst The binary instruction to decode.
-    /// @retval A pointer to the corresponding StaticInst object.
-    StaticInstPtr
-    decode(ExtMachInst mach_inst, Addr addr)
+    /// Constructor
+    AddrMap()
     {
-        // Try to find a matching address based table of instructions.
-        DecodePage *page = decodePages.findPage(addr);
-        if (!page) {
-            // Nothing was found, so create a new one.
-            page = new DecodePage;
-            decodePages.addPage(addr, page);
-        }
+        recent[0] = recent[1] = chunkMap.end();
+    }
 
-        // Use the table to decode the instruction. It will fall back to other
-        // mechanisms if it needs to.
-        return page->decode(mach_inst, addr, instMap);
+    Value &
+    lookup(Addr addr)
+    {
+        CacheChunk *chunk = getChunk(addr);
+        return chunk->items[chunkOffset(addr)];
     }
 };
 
+} // namespace DecodeCache
+
 #endif // __CPU_DECODE_CACHE_HH__