Port: Stricter port bind/unbind semantics
[gem5.git] / src / cpu / decode_cache.hh
index 1bff315d161160846048ad232c5bbadbd843c2e4..34387419fb0807021b0a9a98955a8b34dc7ceb58 100644 (file)
 #include "arch/types.hh"
 #include "base/hashmap.hh"
 #include "config/the_isa.hh"
-#include "cpu/static_inst.hh"
+#include "cpu/static_inst_fwd.hh"
 
-typedef StaticInstPtr (*DecodeInstFunc)(TheISA::ExtMachInst);
-
-template <DecodeInstFunc decodeInstFunc>
-class DecodeCache
+namespace TheISA
 {
-  private:
-    typedef TheISA::ExtMachInst ExtMachInst;
-
-    /// Hash of decoded instructions.
-    typedef m5::hash_map<ExtMachInst, StaticInstPtr> InstMap;
-    InstMap instMap;
-
-    /// A table of instructions which are already been decoded, indexed by
-    /// page offset.
-    class DecodePage
-    {
-      protected:
-        StaticInstPtr instructions[TheISA::PageBytes];
+    class Decoder;
+}
 
-        // 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;
-            }
+namespace DecodeCache
+{
 
-            InstMap::iterator iter = instMap.find(mach_inst);
-            if (iter != instMap.end()) {
-                si = iter->second;
-            } else {
-                si = decodeInstFunc(mach_inst);
-                instMap[mach_inst] = si;
-            }
+/// Hash for decoded instructions.
+typedef m5::hash_map<TheISA::ExtMachInst, StaticInstPtr> InstMap;
 
-            instructions[offset(addr)] = si;
-            return si;
-        }
+/// A sparse map from an Addr to a Value, stored in page chunks.
+template<class Value>
+class AddrMap
+{
+  protected:
+    // A pages worth of cache entries.
+    struct CachePage {
+        Value items[TheISA::PageBytes];
     };
-
-    /// A store of DecodePages. Basically a slightly smarter hash_map.
-    class DecodePages
+    // A map of cache pages which allows a sparse mapping.
+    typedef typename m5::hash_map<Addr, CachePage *> PageMap;
+    typedef typename PageMap::iterator PageIt;
+    // Mini cache of recent lookups.
+    PageIt recent[2];
+    PageMap pageMap;
+
+    /// Update the mini cache of recent lookups.
+    /// @param recentest The most recent result;
+    void
+    update(PageIt 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 CacheePage 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.
+    CachePage *
+    getPage(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;
             }
-
-            // 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 has_map.
+        PageIt it = pageMap.find(page_addr);
+        if (it != pageMap.end()) {
+            update(it);
+            return it->second;
         }
-    } decodePages;
+
+        // Didn't find an existing page, so add a new one.
+        CachePage *newPage = new CachePage;
+        page_addr = page_addr & ~(TheISA::PageBytes - 1);
+        typename PageMap::value_type to_insert(page_addr, newPage);
+        update(pageMap.insert(to_insert).first);
+        return newPage;
+    }
 
   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] = pageMap.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)
+    {
+        CachePage *page = getPage(addr);
+        return page->items[addr & (TheISA::PageBytes - 1)];
     }
 };
 
+} // namespace DecodeCache
+
 #endif // __CPU_DECODE_CACHE_HH__