#ifndef __CPU_DECODE_CACHE_HH__
#define __CPU_DECODE_CACHE_HH__
+#include <unordered_map>
+
#include "arch/isa_traits.hh"
#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);
+namespace TheISA
+{
+ class Decoder;
+}
-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;
- struct DecodePage {
- StaticInstPtr insts[TheISA::PageBytes];
- };
- /// A store of DecodePages. Basically a slightly smarter hash_map.
- class DecodePages
+/// 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>
+class AddrMap
+{
+ protected:
+ // A pages worth of cache entries.
+ struct CachePage {
+ Value items[TheISA::PageBytes];
+ };
+ // A map of cache pages which allows a sparse mapping.
+ typedef typename std::unordered_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;
- }
+ recent[1] = recent[0];
+ recent[0] = recentest;
+ }
- 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);
+ /// 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;
+ }
}
- public:
- /// Constructor
- DecodePages()
- {
- recent[0] = recent[1] = pageMap.end();
+ // 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 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 *
- 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;
- }
- }
-
- // Actually look in the has_map.
- PageIt it = pageMap.find(page_addr);
- if (it != pageMap.end()) {
- update(it);
- return it->second;
- }
-
- // Didn't find an existing page, so add a new one.
- DecodePage *newPage = new DecodePage;
- addPage(page_addr, newPage);
- return newPage;
- }
- } 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.getPage(addr);
-
- // Use the table to decode the instruction. It will fall back to other
- // mechanisms if it needs to.
- Addr offset = addr & (TheISA::PageBytes - 1);
- StaticInstPtr si = page->insts[offset];
- if (si && (si->machInst == mach_inst))
- return si;
-
- InstMap::iterator iter = instMap.find(mach_inst);
- if (iter != instMap.end()) {
- si = iter->second;
- page->insts[offset] = si;
- return si;
- }
+ recent[0] = recent[1] = pageMap.end();
+ }
- si = decodeInstFunc(mach_inst);
- instMap[mach_inst] = si;
- page->insts[offset] = si;
- return si;
+ Value &
+ lookup(Addr addr)
+ {
+ CachePage *page = getPage(addr);
+ return page->items[addr & (TheISA::PageBytes - 1)];
}
};
+} // namespace DecodeCache
+
#endif // __CPU_DECODE_CACHE_HH__