From: Gabe Black Date: Fri, 9 Sep 2011 09:30:01 +0000 (-0700) Subject: Decode: Pull instruction decoding out of the StaticInst class into its own. X-Git-Tag: stable_2012_02_02~94 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=b7b545bc38bcd9ee54f1b8e45064cd8b7a3070b0;p=gem5.git Decode: Pull instruction decoding out of the StaticInst class into its own. This change pulls the instruction decoding machinery (including caches) out of the StaticInst class and puts it into its own class. This has a few intrinsic benefits. First, the StaticInst code, which has gotten to be quite large, gets simpler. Second, the code that handles decode caching is now separated out into its own component and can be looked at in isolation, making it easier to understand. I took the opportunity to restructure the code a bit which will hopefully also help. Beyond that, this change also lays some ground work for each ISA to have its own, potentially stateful decode object. We'd be able to include less contextualizing information in the ExtMachInst objects since that context would be applied at the decoder. Also, the decoder could "know" ahead of time that all the instructions it's going to see are going to be, for instance, 64 bit mode, and it will have one less thing to check when it decodes them. Because the decode caching mechanism has been separated out, it's now possible to have multiple caches which correspond to different types of decoding context. Having one cache for each element of the cross product of different configurations may become prohibitive, so it may be desirable to clear out the cache when relatively static state changes and not to have one for each setting. Because the decode function is no longer universally accessible as a static member of the StaticInst class, a new function was added to the ThreadContexts that returns the applicable decode object. --- diff --git a/src/arch/alpha/remote_gdb.cc b/src/arch/alpha/remote_gdb.cc index a060e49a8..88d453754 100644 --- a/src/arch/alpha/remote_gdb.cc +++ b/src/arch/alpha/remote_gdb.cc @@ -134,6 +134,7 @@ #include "base/remote_gdb.hh" #include "base/socket.hh" #include "base/trace.hh" +#include "cpu/decode.hh" #include "cpu/static_inst.hh" #include "cpu/thread_context.hh" #include "debug/GDBAcc.hh" @@ -282,7 +283,7 @@ RemoteGDB::setSingleStep() // User was stopped at pc, e.g. the instruction at pc was not // executed. MachInst inst = read(pc.pc()); - StaticInstPtr si(inst, pc.pc()); + StaticInstPtr si = context->getDecoderPtr()->decode(inst, pc.pc()); if (si->hasBranchTarget(pc, context, bpc)) { // Don't bother setting a breakpoint on the taken branch if it // is the same as the next pc diff --git a/src/arch/arm/remote_gdb.cc b/src/arch/arm/remote_gdb.cc index 4060c999a..223ff4c69 100644 --- a/src/arch/arm/remote_gdb.cc +++ b/src/arch/arm/remote_gdb.cc @@ -148,6 +148,7 @@ #include "base/remote_gdb.hh" #include "base/socket.hh" #include "base/trace.hh" +#include "cpu/decode.hh" #include "cpu/static_inst.hh" #include "cpu/thread_context.hh" #include "cpu/thread_state.hh" @@ -322,7 +323,7 @@ RemoteGDB::setSingleStep() // User was stopped at pc, e.g. the instruction at pc was not // executed. MachInst inst = read(pc.pc()); - StaticInstPtr si(inst, pc.pc()); + StaticInstPtr si = context->getDecoderPtr()->decode(inst, pc.pc()); if (si->hasBranchTarget(pc, context, bpc)) { // Don't bother setting a breakpoint on the taken branch if it // is the same as the next pc diff --git a/src/cpu/SConscript b/src/cpu/SConscript index b24866ddd..a1074cb8b 100644 --- a/src/cpu/SConscript +++ b/src/cpu/SConscript @@ -114,6 +114,7 @@ SimObject('NativeTrace.py') Source('activity.cc') Source('base.cc') Source('cpuevent.cc') +Source('decode.cc') Source('exetrace.cc') Source('func_unit.cc') Source('inteltrace.cc') diff --git a/src/cpu/decode.cc b/src/cpu/decode.cc new file mode 100644 index 000000000..56a484b07 --- /dev/null +++ b/src/cpu/decode.cc @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2011 Google + * 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: Gabe Black + */ + +#include "cpu/decode.hh" + +DecodeCache Decoder::cache; diff --git a/src/cpu/decode.hh b/src/cpu/decode.hh new file mode 100644 index 000000000..653f8eea5 --- /dev/null +++ b/src/cpu/decode.hh @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2011 Google + * 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: Gabe Black + */ + +#ifndef __CPU_DECODE_HH__ +#define __CPU_DECODE_HH__ + +#include "arch/isa_traits.hh" +#include "arch/types.hh" +#include "config/the_isa.hh" +#include "cpu/decode_cache.hh" +#include "cpu/static_inst.hh" + +/// The decoder class. This class doesn't do much of anything now, but in the +/// future it will be redefinable per ISA and allow more interesting behavior. +class Decoder +{ + protected: + /// A cache of decoded instruction objects. + static DecodeCache cache; + + public: + /// Decode a machine instruction. + /// @param mach_inst The binary instruction to decode. + /// @retval A pointer to the corresponding StaticInst object. + StaticInstPtr + decode(TheISA::ExtMachInst mach_inst, Addr addr) + { + return cache.decode(mach_inst, addr); + } +}; + +#endif // __CPU_DECODE_HH__ diff --git a/src/cpu/decode_cache.hh b/src/cpu/decode_cache.hh new file mode 100644 index 000000000..1bff315d1 --- /dev/null +++ b/src/cpu/decode_cache.hh @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2011 Google + * 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: 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" + +typedef StaticInstPtr (*DecodeInstFunc)(TheISA::ExtMachInst); + +template +class DecodeCache +{ + private: + typedef TheISA::ExtMachInst ExtMachInst; + + /// Hash of decoded instructions. + typedef m5::hash_map InstMap; + InstMap instMap; + + /// A table of instructions which are already been decoded, indexed by + /// page offset. + class DecodePage + { + 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; + } + + InstMap::iterator iter = instMap.find(mach_inst); + if (iter != instMap.end()) { + si = iter->second; + } else { + si = decodeInstFunc(mach_inst); + instMap[mach_inst] = si; + } + + instructions[offset(addr)] = si; + return si; + } + }; + + /// A store of DecodePages. Basically a slightly smarter hash_map. + class DecodePages + { + protected: + typedef typename m5::hash_map 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; + } + } + + // Actually look in the has_map. + PageIt it = pageMap.find(page_addr); + if (it != pageMap.end()) { + update(it); + return it->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); + } + } decodePages; + + 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) + { + // 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); + } + + // 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); + } +}; + +#endif // __CPU_DECODE_CACHE_HH__ diff --git a/src/cpu/inorder/cpu.cc b/src/cpu/inorder/cpu.cc index d8552d9d3..07a013afc 100644 --- a/src/cpu/inorder/cpu.cc +++ b/src/cpu/inorder/cpu.cc @@ -1766,6 +1766,14 @@ InOrderCPU::getDTBPtr() return dtb_res->tlb(); } +Decoder * +InOrderCPU::getDecoderPtr() +{ + FetchUnit *fetch_res = + dynamic_cast(resPool->getResource(fetchPortIdx)); + return &fetch_res->decoder; +} + Fault InOrderCPU::read(DynInstPtr inst, Addr addr, uint8_t *data, unsigned size, unsigned flags) diff --git a/src/cpu/inorder/cpu.hh b/src/cpu/inorder/cpu.hh index a5616f8b1..098909cb7 100644 --- a/src/cpu/inorder/cpu.hh +++ b/src/cpu/inorder/cpu.hh @@ -305,6 +305,8 @@ class InOrderCPU : public BaseCPU TheISA::TLB *getITBPtr(); TheISA::TLB *getDTBPtr(); + Decoder *getDecoderPtr(); + /** Accessor Type for the SkedCache */ typedef uint32_t SkedID; diff --git a/src/cpu/inorder/inorder_dyn_inst.cc b/src/cpu/inorder/inorder_dyn_inst.cc index 5343206c1..f65d2ea9f 100644 --- a/src/cpu/inorder/inorder_dyn_inst.cc +++ b/src/cpu/inorder/inorder_dyn_inst.cc @@ -94,9 +94,9 @@ InOrderDynInst::cpuId() } void -InOrderDynInst::setMachInst(ExtMachInst machInst) +InOrderDynInst::setStaticInst(StaticInstPtr si) { - staticInst = StaticInst::decode(machInst, pc.instAddr()); + staticInst = si; for (int i = 0; i < this->staticInst->numDestRegs(); i++) { _destRegIdx[i] = this->staticInst->destRegIdx(i); diff --git a/src/cpu/inorder/inorder_dyn_inst.hh b/src/cpu/inorder/inorder_dyn_inst.hh index ecaf23aab..de9de5eff 100644 --- a/src/cpu/inorder/inorder_dyn_inst.hh +++ b/src/cpu/inorder/inorder_dyn_inst.hh @@ -324,7 +324,7 @@ class InOrderDynInst : public FastAlloc, public RefCounted std::string instName() { return (staticInst) ? staticInst->getName() : "undecoded-inst"; } - void setMachInst(ExtMachInst inst); + void setStaticInst(StaticInstPtr si); ExtMachInst getMachInst() { return staticInst->machInst; } diff --git a/src/cpu/inorder/resources/fetch_unit.cc b/src/cpu/inorder/resources/fetch_unit.cc index 8ba6bdc9a..b32134e00 100644 --- a/src/cpu/inorder/resources/fetch_unit.cc +++ b/src/cpu/inorder/resources/fetch_unit.cc @@ -117,7 +117,7 @@ FetchUnit::createMachInst(std::list::iterator fetch_it, ext_inst = predecoder[tid]->getExtMachInst(instPC); inst->pcState(instPC); - inst->setMachInst(ext_inst); + inst->setStaticInst(decoder.decode(ext_inst, instPC.instAddr())); } void diff --git a/src/cpu/inorder/resources/fetch_unit.hh b/src/cpu/inorder/resources/fetch_unit.hh index 250e53e6c..6d734d7e6 100644 --- a/src/cpu/inorder/resources/fetch_unit.hh +++ b/src/cpu/inorder/resources/fetch_unit.hh @@ -39,6 +39,7 @@ #include "arch/predecoder.hh" #include "arch/tlb.hh" #include "config/the_isa.hh" +#include "cpu/decode.hh" #include "cpu/inorder/resources/cache_unit.hh" #include "cpu/inorder/inorder_dyn_inst.hh" #include "cpu/inorder/pipeline_traits.hh" @@ -88,6 +89,8 @@ class FetchUnit : public CacheUnit void trap(Fault fault, ThreadID tid, DynInstPtr inst); + Decoder decoder; + private: void squashCacheRequest(CacheReqPtr req_ptr); diff --git a/src/cpu/inorder/thread_context.hh b/src/cpu/inorder/thread_context.hh index 3b4e8dd7f..7ec17cb77 100644 --- a/src/cpu/inorder/thread_context.hh +++ b/src/cpu/inorder/thread_context.hh @@ -78,6 +78,8 @@ class InOrderThreadContext : public ThreadContext /** @TODO: PERF: Should we bind this to a pointer in constructor? */ TheISA::TLB *getDTBPtr() { return cpu->getDTBPtr(); } + Decoder *getDecoderPtr() { return cpu->getDecoderPtr(); } + System *getSystemPtr() { return cpu->system; } /** Returns a pointer to this CPU. */ diff --git a/src/cpu/legiontrace.cc b/src/cpu/legiontrace.cc index 49b2f513c..484af1008 100644 --- a/src/cpu/legiontrace.cc +++ b/src/cpu/legiontrace.cc @@ -52,6 +52,7 @@ #include "arch/sparc/utility.hh" #include "base/socket.hh" #include "cpu/base.hh" +#include "cpu/decode.hh" #include "cpu/legiontrace.hh" #include "cpu/static_inst.hh" #include "cpu/thread_context.hh" @@ -438,8 +439,8 @@ Trace::LegionTraceRecord::dump() PCState tempPC = pc; StaticInstPtr legionInst = - StaticInst::decode(predecoder.getExtMachInst(tempPC), - lgnPc); + thread->getDecoderPtr()->decode( + predecoder.getExtMachInst(tempPC), lgnPc); outs << setfill(' ') << setw(15) << " Legion Inst: " << "0x" << setw(8) << setfill('0') << hex diff --git a/src/cpu/o3/fetch.hh b/src/cpu/o3/fetch.hh index 6d93f2cc8..d09d7f680 100644 --- a/src/cpu/o3/fetch.hh +++ b/src/cpu/o3/fetch.hh @@ -48,6 +48,7 @@ #include "arch/utility.hh" #include "base/statistics.hh" #include "config/the_isa.hh" +#include "cpu/decode.hh" #include "cpu/pc_event.hh" #include "cpu/timebuf.hh" #include "cpu/translation.hh" @@ -380,6 +381,9 @@ class DefaultFetch return (addr & ~(cacheBlkMask)); } + /** The decoder. */ + Decoder decoder; + private: DynInstPtr buildInst(ThreadID tid, StaticInstPtr staticInst, StaticInstPtr curMacroop, TheISA::PCState thisPC, diff --git a/src/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh index 86f5df9c7..b0ec349dc 100644 --- a/src/cpu/o3/fetch_impl.hh +++ b/src/cpu/o3/fetch_impl.hh @@ -725,7 +725,7 @@ DefaultFetch::finishTranslation(Fault fault, RequestPtr mem_req) DPRINTF(Fetch, "[tid:%i]: Translation faulted, building noop.\n", tid); // We will use a nop in ordier to carry the fault. DynInstPtr instruction = buildInst(tid, - StaticInstPtr(TheISA::NoopMachInst, fetchPC.instAddr()), + decoder.decode(TheISA::NoopMachInst, fetchPC.instAddr()), NULL, fetchPC, fetchPC, false); instruction->setPredTarg(fetchPC); @@ -1287,11 +1287,10 @@ DefaultFetch::fetch(bool &status_change) do { if (!(curMacroop || inRom)) { if (predecoder.extMachInstReady()) { - ExtMachInst extMachInst; - - extMachInst = predecoder.getExtMachInst(thisPC); - staticInst = StaticInstPtr(extMachInst, - thisPC.instAddr()); + ExtMachInst extMachInst = + predecoder.getExtMachInst(thisPC); + staticInst = + decoder.decode(extMachInst, thisPC.instAddr()); // Increment stat of fetched instructions. ++fetchedInsts; diff --git a/src/cpu/o3/thread_context.hh b/src/cpu/o3/thread_context.hh index ef0fdbb4d..38c94439a 100755 --- a/src/cpu/o3/thread_context.hh +++ b/src/cpu/o3/thread_context.hh @@ -73,6 +73,8 @@ class O3ThreadContext : public ThreadContext /** Returns a pointer to the DTB. */ TheISA::TLB *getDTBPtr() { return cpu->dtb; } + Decoder *getDecoderPtr() { return &cpu->fetch.decoder; } + /** Returns a pointer to this CPU. */ virtual BaseCPU *getCpuPtr() { return cpu; } diff --git a/src/cpu/simple/base.cc b/src/cpu/simple/base.cc index 699e78764..70e2c39e6 100644 --- a/src/cpu/simple/base.cc +++ b/src/cpu/simple/base.cc @@ -383,7 +383,7 @@ BaseSimpleCPU::preExecute() stayAtPC = false; ExtMachInst machInst = predecoder.getExtMachInst(pcState); thread->pcState(pcState); - instPtr = StaticInst::decode(machInst, pcState.instAddr()); + instPtr = thread->decoder.decode(machInst, pcState.instAddr()); } else { stayAtPC = true; fetchOffset += sizeof(MachInst); diff --git a/src/cpu/simple/base.hh b/src/cpu/simple/base.hh index 0cc90645f..b27ebf998 100644 --- a/src/cpu/simple/base.hh +++ b/src/cpu/simple/base.hh @@ -38,6 +38,7 @@ #include "config/full_system.hh" #include "config/the_isa.hh" #include "cpu/base.hh" +#include "cpu/decode.hh" #include "cpu/pc_event.hh" #include "cpu/simple_thread.hh" #include "cpu/static_inst.hh" diff --git a/src/cpu/simple_thread.hh b/src/cpu/simple_thread.hh index a74616a0d..2b7b89030 100644 --- a/src/cpu/simple_thread.hh +++ b/src/cpu/simple_thread.hh @@ -40,6 +40,7 @@ #include "base/types.hh" #include "config/full_system.hh" #include "config/the_isa.hh" +#include "cpu/decode.hh" #include "cpu/thread_context.hh" #include "cpu/thread_state.hh" #include "debug/FloatRegs.hh" @@ -129,6 +130,8 @@ class SimpleThread : public ThreadState TheISA::TLB *itb; TheISA::TLB *dtb; + Decoder decoder; + // constructor: initialize SimpleThread from given process structure #if FULL_SYSTEM SimpleThread(BaseCPU *_cpu, int _thread_num, System *_system, @@ -200,6 +203,8 @@ class SimpleThread : public ThreadState TheISA::TLB *getDTBPtr() { return dtb; } + Decoder *getDecoderPtr() { return &decoder; } + System *getSystemPtr() { return system; } #if FULL_SYSTEM diff --git a/src/cpu/static_inst.cc b/src/cpu/static_inst.cc index df59d1fc3..2a7b584eb 100644 --- a/src/cpu/static_inst.cc +++ b/src/cpu/static_inst.cc @@ -36,11 +36,6 @@ StaticInstPtr StaticInst::nullStaticInstPtr; -// Define the decode cache hash map. -StaticInst::DecodeCache StaticInst::decodeCache; -StaticInst::AddrDecodeCache StaticInst::addrDecodeCache; -StaticInst::cacheElement StaticInst::recentDecodes[2]; - using namespace std; StaticInst::~StaticInst() @@ -49,25 +44,6 @@ StaticInst::~StaticInst() delete cachedDisassembly; } -void -StaticInst::dumpDecodeCacheStats() -{ - cerr << "Decode hash table stats @ " << curTick() << ":" << endl; - cerr << "\tnum entries = " << decodeCache.size() << endl; - cerr << "\tnum buckets = " << decodeCache.bucket_count() << endl; - vector hist(100, 0); - int max_hist = 0; - for (int i = 0; i < decodeCache.bucket_count(); ++i) { - int count = decodeCache.elems_in_bucket(i); - if (count > max_hist) - max_hist = count; - hist[count]++; - } - for (int i = 0; i <= max_hist; ++i) { - cerr << "\tbuckets of size " << i << " = " << hist[i] << endl; - } -} - bool StaticInst::hasBranchTarget(const TheISA::PCState &pc, ThreadContext *tc, TheISA::PCState &tgt) const diff --git a/src/cpu/static_inst.hh b/src/cpu/static_inst.hh index c41ac38a6..b2773052e 100644 --- a/src/cpu/static_inst.hh +++ b/src/cpu/static_inst.hh @@ -34,10 +34,8 @@ #include #include -#include "arch/isa_traits.hh" #include "arch/registers.hh" #include "arch/types.hh" -#include "base/hashmap.hh" #include "base/misc.hh" #include "base/refcnt.hh" #include "base/types.hh" @@ -65,7 +63,6 @@ class AtomicSimpleCPU; class TimingSimpleCPU; class InorderCPU; class SymbolTable; -class AddrDecodePage; namespace Trace { class InstRecord; @@ -285,9 +282,6 @@ class StaticInstPtr; class StaticInst : public StaticInstBase { public: - - /// Binary machine instruction type. - typedef TheISA::MachInst MachInst; /// Binary extended machine instruction type. typedef TheISA::ExtMachInst ExtMachInst; /// Logical register index type. @@ -416,72 +410,8 @@ class StaticInst : public StaticInstBase virtual const std::string &disassemble(Addr pc, const SymbolTable *symtab = 0) const; - /// Decoded instruction cache type. - /// For now we're using a generic hash_map; this seems to work - /// pretty well. - typedef m5::hash_map DecodeCache; - - /// A cache of decoded instruction objects. - static DecodeCache decodeCache; - - /** - * Dump some basic stats on the decode cache hash map. - * Only gets called if DECODE_CACHE_HASH_STATS is defined. - */ - static void dumpDecodeCacheStats(); - - /// Decode a machine instruction. - /// @param mach_inst The binary instruction to decode. - /// @retval A pointer to the corresponding StaticInst object. - //This is defined as inlined below. - static StaticInstPtr decode(ExtMachInst mach_inst, Addr addr); - /// Return name of machine instruction std::string getName() { return mnemonic; } - - /// Decoded instruction cache type, for address decoding. - /// A generic hash_map is used. - typedef m5::hash_map AddrDecodeCache; - - /// A cache of decoded instruction objects from addresses. - static AddrDecodeCache addrDecodeCache; - - struct cacheElement - { - Addr page_addr; - AddrDecodePage *decodePage; - - cacheElement() : decodePage(NULL) { } - }; - - /// An array of recently decoded instructions. - // might not use an array if there is only two elements - static struct cacheElement recentDecodes[2]; - - /// Updates the recently decoded instructions entries - /// @param page_addr The page address recently used. - /// @param decodePage Pointer to decoding page containing the decoded - /// instruction. - static inline void - updateCache(Addr page_addr, AddrDecodePage *decodePage) - { - recentDecodes[1].page_addr = recentDecodes[0].page_addr; - recentDecodes[1].decodePage = recentDecodes[0].decodePage; - recentDecodes[0].page_addr = page_addr; - recentDecodes[0].decodePage = decodePage; - } - - /// Searches the decoded instruction cache for instruction decoding. - /// If it is not found, then we decode the instruction. - /// Otherwise, we get the instruction from the cache and move it into - /// the address-to-instruction decoding page. - /// @param mach_inst The binary instruction to decode. - /// @param addr The address that contained the binary instruction. - /// @param decodePage Pointer to decoding page containing the instruction. - /// @retval A pointer to the corresponding StaticInst object. - //This is defined as inlined below. - static StaticInstPtr searchCache(ExtMachInst mach_inst, Addr addr, - AddrDecodePage *decodePage); }; typedef RefCountingPtr StaticInstBasePtr; @@ -510,13 +440,6 @@ class StaticInstPtr : public RefCountingPtr { } - /// Construct directly from machine instruction. - /// Calls StaticInst::decode(). - explicit StaticInstPtr(TheISA::ExtMachInst mach_inst, Addr addr) - : RefCountingPtr(StaticInst::decode(mach_inst, addr)) - { - } - /// Convert to pointer to StaticInstBase class. operator const StaticInstBasePtr() { @@ -524,123 +447,4 @@ class StaticInstPtr : public RefCountingPtr } }; -/// A page of a list of decoded instructions from an address. -class AddrDecodePage -{ - typedef TheISA::ExtMachInst ExtMachInst; - protected: - StaticInstPtr instructions[TheISA::PageBytes]; - bool valid[TheISA::PageBytes]; - Addr lowerMask; - - public: - /// Constructor - AddrDecodePage() - { - lowerMask = TheISA::PageBytes - 1; - memset(valid, 0, TheISA::PageBytes); - } - - /// Checks if the instruction is already decoded and the machine - /// instruction in the cache matches the current machine instruction - /// related to the address - /// @param mach_inst The binary instruction to check - /// @param addr The address containing the instruction - bool - decoded(ExtMachInst mach_inst, Addr addr) - { - return (valid[addr & lowerMask] && - (instructions[addr & lowerMask]->machInst == mach_inst)); - } - - /// Returns the instruction object. decoded should be called first - /// to check if the instruction is valid. - /// @param addr The address of the instruction. - /// @retval A pointer to the corresponding StaticInst object. - StaticInstPtr - getInst(Addr addr) - { - return instructions[addr & lowerMask]; - } - - /// Inserts a pointer to a StaticInst object into the list of decoded - /// instructions on the page. - /// @param addr The address of the instruction. - /// @param si A pointer to the corresponding StaticInst object. - void - insert(Addr addr, StaticInstPtr &si) - { - instructions[addr & lowerMask] = si; - valid[addr & lowerMask] = true; - } -}; - - -inline StaticInstPtr -StaticInst::decode(StaticInst::ExtMachInst mach_inst, Addr addr) -{ -#ifdef DECODE_CACHE_HASH_STATS - // Simple stats on decode hash_map. Turns out the default - // hash function is as good as anything I could come up with. - const int dump_every_n = 10000000; - static int decodes_til_dump = dump_every_n; - - if (--decodes_til_dump == 0) { - dumpDecodeCacheStats(); - decodes_til_dump = dump_every_n; - } -#endif - - Addr page_addr = addr & ~(TheISA::PageBytes - 1); - - // checks recently decoded addresses - if (recentDecodes[0].decodePage && - page_addr == recentDecodes[0].page_addr) { - if (recentDecodes[0].decodePage->decoded(mach_inst, addr)) - return recentDecodes[0].decodePage->getInst(addr); - - return searchCache(mach_inst, addr, recentDecodes[0].decodePage); - } - - if (recentDecodes[1].decodePage && - page_addr == recentDecodes[1].page_addr) { - if (recentDecodes[1].decodePage->decoded(mach_inst, addr)) - return recentDecodes[1].decodePage->getInst(addr); - - return searchCache(mach_inst, addr, recentDecodes[1].decodePage); - } - - // searches the page containing the address to decode - AddrDecodeCache::iterator iter = addrDecodeCache.find(page_addr); - if (iter != addrDecodeCache.end()) { - updateCache(page_addr, iter->second); - if (iter->second->decoded(mach_inst, addr)) - return iter->second->getInst(addr); - - return searchCache(mach_inst, addr, iter->second); - } - - // creates a new object for a page of decoded instructions - AddrDecodePage *decodePage = new AddrDecodePage; - addrDecodeCache[page_addr] = decodePage; - updateCache(page_addr, decodePage); - return searchCache(mach_inst, addr, decodePage); -} - -inline StaticInstPtr -StaticInst::searchCache(ExtMachInst mach_inst, Addr addr, - AddrDecodePage *decodePage) -{ - DecodeCache::iterator iter = decodeCache.find(mach_inst); - if (iter != decodeCache.end()) { - decodePage->insert(addr, iter->second); - return iter->second; - } - - StaticInstPtr si = TheISA::decodeInst(mach_inst); - decodePage->insert(addr, si); - decodeCache[mach_inst] = si; - return si; -} - #endif // __CPU_STATIC_INST_HH__ diff --git a/src/cpu/thread_context.hh b/src/cpu/thread_context.hh index 0f7228f0c..3b7f8b3c3 100644 --- a/src/cpu/thread_context.hh +++ b/src/cpu/thread_context.hh @@ -48,6 +48,7 @@ namespace TheISA } class BaseCPU; class Checkpoint; +class Decoder; class EndQuiesceEvent; class TranslatingPort; class FunctionalPort; @@ -120,6 +121,8 @@ class ThreadContext virtual TheISA::TLB *getDTBPtr() = 0; + virtual Decoder *getDecoderPtr() = 0; + virtual System *getSystemPtr() = 0; #if FULL_SYSTEM @@ -287,6 +290,8 @@ class ProxyThreadContext : public ThreadContext TheISA::TLB *getDTBPtr() { return actualTC->getDTBPtr(); } + Decoder *getDecoderPtr() { return actualTC->getDecoderPtr(); } + System *getSystemPtr() { return actualTC->getSystemPtr(); } #if FULL_SYSTEM