* 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__