Decode: Pull instruction decoding out of the StaticInst class into its own.
authorGabe Black <gblack@eecs.umich.edu>
Fri, 9 Sep 2011 09:30:01 +0000 (02:30 -0700)
committerGabe Black <gblack@eecs.umich.edu>
Fri, 9 Sep 2011 09:30:01 +0000 (02:30 -0700)
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.

23 files changed:
src/arch/alpha/remote_gdb.cc
src/arch/arm/remote_gdb.cc
src/cpu/SConscript
src/cpu/decode.cc [new file with mode: 0644]
src/cpu/decode.hh [new file with mode: 0644]
src/cpu/decode_cache.hh [new file with mode: 0644]
src/cpu/inorder/cpu.cc
src/cpu/inorder/cpu.hh
src/cpu/inorder/inorder_dyn_inst.cc
src/cpu/inorder/inorder_dyn_inst.hh
src/cpu/inorder/resources/fetch_unit.cc
src/cpu/inorder/resources/fetch_unit.hh
src/cpu/inorder/thread_context.hh
src/cpu/legiontrace.cc
src/cpu/o3/fetch.hh
src/cpu/o3/fetch_impl.hh
src/cpu/o3/thread_context.hh
src/cpu/simple/base.cc
src/cpu/simple/base.hh
src/cpu/simple_thread.hh
src/cpu/static_inst.cc
src/cpu/static_inst.hh
src/cpu/thread_context.hh

index a060e49a89a8781fc23e41e68b7feab6fc22362f..88d4537545f0a7ad0a6ab3ca03bb7cc1c7e5d9e3 100644 (file)
 #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<MachInst>(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
index 4060c999abfd09355971c246e05b693ba591102d..223ff4c69d87d786aa6b66da9a29ee5b04097eca 100644 (file)
 #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<MachInst>(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
index b24866ddd6ff22685437967f4504ec5edce9654a..a1074cb8b6bb73c51b405d2895a482158949fff7 100644 (file)
@@ -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 (file)
index 0000000..56a484b
--- /dev/null
@@ -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<TheISA::decodeInst> Decoder::cache;
diff --git a/src/cpu/decode.hh b/src/cpu/decode.hh
new file mode 100644 (file)
index 0000000..653f8ee
--- /dev/null
@@ -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<TheISA::decodeInst> 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 (file)
index 0000000..1bff315
--- /dev/null
@@ -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 <DecodeInstFunc decodeInstFunc>
+class DecodeCache
+{
+  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];
+
+        // 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<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;
+                }
+            }
+
+            // 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__
index d8552d9d30d5bd887724a34b04f39badca3d1955..07a013afc71ac2483c94605c3311c70827052d63 100644 (file)
@@ -1766,6 +1766,14 @@ InOrderCPU::getDTBPtr()
     return dtb_res->tlb();
 }
 
+Decoder *
+InOrderCPU::getDecoderPtr()
+{
+    FetchUnit *fetch_res =
+        dynamic_cast<FetchUnit*>(resPool->getResource(fetchPortIdx));
+    return &fetch_res->decoder;
+}
+
 Fault
 InOrderCPU::read(DynInstPtr inst, Addr addr,
                  uint8_t *data, unsigned size, unsigned flags)
index a5616f8b18862064da524335011277d483844cb4..098909cb7e2b6476256d44c216c20a3e503c5b04 100644 (file)
@@ -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;
 
index 5343206c1fe105e1ab46e59fe18ba5e0f80f4f1b..f65d2ea9fd249ba03117efbcc08b18d56c8900f9 100644 (file)
@@ -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);
index ecaf23aab34f15792bb09bcfb7860acdf675d2a4..de9de5effe3970072e571bd13b2302fd941d45ac 100644 (file)
@@ -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; }
 
index 8ba6bdc9aab7502b12907c429f5af623742848b9..b32134e0044cab7921ed57476d4ff6138f8a2e23 100644 (file)
@@ -117,7 +117,7 @@ FetchUnit::createMachInst(std::list<FetchBlock*>::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
index 250e53e6c73bd6d09f2ae44ce727b105c49b7685..6d734d7e6a6ebb0d8d6f2a4182ebf6585742802b 100644 (file)
@@ -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);
 
index 3b4e8dd7f223002ba2e10771fd16c8b992e0e53b..7ec17cb770f6883348322d28fbd3dc53e51b8a39 100644 (file)
@@ -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. */
index 49b2f513cf7530d54f4e111682c5f41e84294f47..484af1008b279be9fe65fd6784b7a76706f55635 100644 (file)
@@ -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
index 6d93f2cc8748d80b9efbe5e535003eca99b704a4..d09d7f6804adb1fa0694f20838f4f117383ddd7d 100644 (file)
@@ -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,
index 86f5df9c764efdffaebbf8e26a7e09bb6374026a..b0ec349dc8d4c207051e9537189a3280b4f558f2 100644 (file)
@@ -725,7 +725,7 @@ DefaultFetch<Impl>::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<Impl>::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;
index ef0fdbb4d8b2772fd5f3f63368eecebd6b74ebda..38c94439a7e5ae0b12e3e0ee6318353799102637 100755 (executable)
@@ -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; }
 
index 699e7876434c4a566555a4a758423171e1f19357..70e2c39e65d213a607d6aa8853daaae6da59768a 100644 (file)
@@ -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);
index 0cc90645f060efcb8ab5bbba3c20c102457e8c23..b27ebf9984e39664bd3f49de5a93c6e93e8cbdd1 100644 (file)
@@ -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"
index a74616a0d783a25faf856b242ea0c216a2b90271..2b7b89030b41b2f14dd02fe3c038c915cd804c08 100644 (file)
@@ -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
index df59d1fc317024ba8f652a31e9284b94d3f39164..2a7b584eb4b4fe41c7877e9b389c476004477d89 100644 (file)
 
 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<int> 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
index c41ac38a6920c15c1b8acdcb856e2f27946e7abf..b2773052eda36ef05b199027c907bcb2d5945267 100644 (file)
 #include <bitset>
 #include <string>
 
-#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<ExtMachInst, StaticInstPtr> 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<Addr, AddrDecodePage *> 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<StaticInstBase> StaticInstBasePtr;
@@ -510,13 +440,6 @@ class StaticInstPtr : public RefCountingPtr<StaticInst>
     {
     }
 
-    /// Construct directly from machine instruction.
-    /// Calls StaticInst::decode().
-    explicit StaticInstPtr(TheISA::ExtMachInst mach_inst, Addr addr)
-        : RefCountingPtr<StaticInst>(StaticInst::decode(mach_inst, addr))
-    {
-    }
-
     /// Convert to pointer to StaticInstBase class.
     operator const StaticInstBasePtr()
     {
@@ -524,123 +447,4 @@ class StaticInstPtr : public RefCountingPtr<StaticInst>
     }
 };
 
-/// 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__
index 0f7228f0c3b2fe87442911aa5ff04c9cbe3a1094..3b7f8b3c320f855781aeaead42c38c2b14d95d16 100644 (file)
@@ -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