cpu: use probes infrastructure to do simpoint profiling
authorDam Sunwoo <dam.sunwoo@arm.com>
Sat, 20 Sep 2014 21:17:43 +0000 (17:17 -0400)
committerDam Sunwoo <dam.sunwoo@arm.com>
Sat, 20 Sep 2014 21:17:43 +0000 (17:17 -0400)
Instead of having code embedded in cpu model to do simpoint profiling use
the probes infrastructure to do it.

configs/example/se.py
src/cpu/simple/AtomicSimpleCPU.py
src/cpu/simple/atomic.cc
src/cpu/simple/atomic.hh
src/cpu/simple/probes/SConscript [new file with mode: 0644]
src/cpu/simple/probes/SimPoint.py [new file with mode: 0644]
src/cpu/simple/probes/simpoint.cc [new file with mode: 0644]
src/cpu/simple/probes/simpoint.hh [new file with mode: 0644]

index ad15e14b517a6ef1bcd3f7039b528549472f9470..8ec90599b8b28326323945c7e8b2ac8c6ad47bd8 100644 (file)
@@ -213,8 +213,7 @@ for i in xrange(np):
         system.cpu[i].fastmem = True
 
     if options.simpoint_profile:
-        system.cpu[i].simpoint_profile = True
-        system.cpu[i].simpoint_interval = options.simpoint_interval
+        system.cpu[i].addSimPointProbe(options.simpoint_interval)
 
     if options.checker:
         system.cpu[i].addCheckerCpu()
index 7a066457d1a9ab9c78c3a70f6cf2cdb1b91e9774..04592c68a001a2d9a18bd4f2969f3446a41e05ce 100644 (file)
@@ -40,6 +40,7 @@
 
 from m5.params import *
 from BaseSimpleCPU import BaseSimpleCPU
+from SimPoint import SimPoint
 
 class AtomicSimpleCPU(BaseSimpleCPU):
     """Simple CPU model executing a configurable number of
@@ -61,6 +62,8 @@ class AtomicSimpleCPU(BaseSimpleCPU):
     simulate_data_stalls = Param.Bool(False, "Simulate dcache stall cycles")
     simulate_inst_stalls = Param.Bool(False, "Simulate icache stall cycles")
     fastmem = Param.Bool(False, "Access memory directly")
-    simpoint_profile = Param.Bool(False, "Generate SimPoint BBVs")
-    simpoint_interval = Param.UInt64(100000000, "SimPoint Interval Size (insts)")
-    simpoint_profile_file = Param.String("simpoint.bb.gz", "SimPoint BBV file")
+
+    def addSimPointProbe(self, interval):
+        simpoint = SimPoint()
+        simpoint.interval = interval
+        self.probeListener = simpoint
index 219e940431e4e0dcd25e860fc71bccffaf5cd254..0ac4a54953facbbcdb30f5f72ceb9d3e63345ece 100644 (file)
@@ -110,20 +110,9 @@ AtomicSimpleCPU::AtomicSimpleCPU(AtomicSimpleCPUParams *p)
       drain_manager(NULL),
       icachePort(name() + ".icache_port", this),
       dcachePort(name() + ".dcache_port", this),
-      fastmem(p->fastmem),
-      simpoint(p->simpoint_profile),
-      intervalSize(p->simpoint_interval),
-      intervalCount(0),
-      intervalDrift(0),
-      simpointStream(NULL),
-      currentBBV(0, 0),
-      currentBBVInstCount(0)
+      fastmem(p->fastmem)
 {
     _status = Idle;
-
-    if (simpoint) {
-        simpointStream = simout.create(p->simpoint_profile_file, false);
-    }
 }
 
 
@@ -132,9 +121,6 @@ AtomicSimpleCPU::~AtomicSimpleCPU()
     if (tickEvent.scheduled()) {
         deschedule(tickEvent);
     }
-    if (simpointStream) {
-        simout.close(simpointStream);
-    }
 }
 
 unsigned int
@@ -574,8 +560,13 @@ AtomicSimpleCPU::tick()
                 fault = curStaticInst->execute(this, traceData);
 
                 // keep an instruction count
-                if (fault == NoFault)
+                if (fault == NoFault) {
                     countInst();
+                    if (!curStaticInst->isMicroop() ||
+                         curStaticInst->isLastMicroop()) {
+                        ppCommit->notify(std::make_pair(thread, curStaticInst));
+                    }
+                }
                 else if (traceData && !DTRACE(ExecFaulting)) {
                     delete traceData;
                     traceData = NULL;
@@ -589,13 +580,6 @@ AtomicSimpleCPU::tick()
                         curStaticInst->isFirstMicroop()))
                 instCnt++;
 
-            // profile for SimPoints if enabled and macro inst is finished
-            if (simpoint && curStaticInst && (fault == NoFault) &&
-                    (!curStaticInst->isMicroop() ||
-                     curStaticInst->isLastMicroop())) {
-                profileSimPoint();
-            }
-
             Tick stall_ticks = 0;
             if (simulate_inst_stalls && icache_access)
                 stall_ticks += icache_latency;
@@ -627,72 +611,17 @@ AtomicSimpleCPU::tick()
         schedule(tickEvent, curTick() + latency);
 }
 
-
 void
-AtomicSimpleCPU::printAddr(Addr a)
+AtomicSimpleCPU::regProbePoints()
 {
-    dcachePort.printAddr(a);
+    ppCommit = new ProbePointArg<pair<SimpleThread*, const StaticInstPtr>>
+                                (getProbeManager(), "Commit");
 }
 
 void
-AtomicSimpleCPU::profileSimPoint()
+AtomicSimpleCPU::printAddr(Addr a)
 {
-    if (!currentBBVInstCount)
-        currentBBV.first = thread->pcState().instAddr();
-
-    ++intervalCount;
-    ++currentBBVInstCount;
-
-    // If inst is control inst, assume end of basic block.
-    if (curStaticInst->isControl()) {
-        currentBBV.second = thread->pcState().instAddr();
-
-        auto map_itr = bbMap.find(currentBBV);
-        if (map_itr == bbMap.end()){
-            // If a new (previously unseen) basic block is found,
-            // add a new unique id, record num of insts and insert into bbMap.
-            BBInfo info;
-            info.id = bbMap.size() + 1;
-            info.insts = currentBBVInstCount;
-            info.count = currentBBVInstCount;
-            bbMap.insert(std::make_pair(currentBBV, info));
-        } else {
-            // If basic block is seen before, just increment the count by the
-            // number of insts in basic block.
-            BBInfo& info = map_itr->second;
-            info.count += currentBBVInstCount;
-        }
-        currentBBVInstCount = 0;
-
-        // Reached end of interval if the sum of the current inst count
-        // (intervalCount) and the excessive inst count from the previous
-        // interval (intervalDrift) is greater than/equal to the interval size.
-        if (intervalCount + intervalDrift >= intervalSize) {
-            // summarize interval and display BBV info
-            std::vector<pair<uint64_t, uint64_t> > counts;
-            for (auto map_itr = bbMap.begin(); map_itr != bbMap.end();
-                    ++map_itr) {
-                BBInfo& info = map_itr->second;
-                if (info.count != 0) {
-                    counts.push_back(std::make_pair(info.id, info.count));
-                    info.count = 0;
-                }
-            }
-            std::sort(counts.begin(), counts.end());
-
-            // Print output BBV info
-            *simpointStream << "T";
-            for (auto cnt_itr = counts.begin(); cnt_itr != counts.end();
-                    ++cnt_itr) {
-                *simpointStream << ":" << cnt_itr->first
-                                << ":" << cnt_itr->second << " ";
-            }
-            *simpointStream << "\n";
-
-            intervalDrift = (intervalCount + intervalDrift) - intervalSize;
-            intervalCount = 0;
-        }
-    }
+    dcachePort.printAddr(a);
 }
 
 ////////////////////////////////////////////////////////////////////////
index 7426139e7e8d63e640d0ae8ab76f56f6baed0aa4..91f558e060f6676062d5767b245ad0f8f42b4b85 100644 (file)
 #ifndef __CPU_SIMPLE_ATOMIC_HH__
 #define __CPU_SIMPLE_ATOMIC_HH__
 
-#include "base/hashmap.hh"
 #include "cpu/simple/base.hh"
 #include "params/AtomicSimpleCPU.hh"
-
-/**
- *  Start and end address of basic block for SimPoint profiling.
- *  This structure is used to look up the hash table of BBVs.
- *  - first: PC of first inst in basic block
- *  - second: PC of last inst in basic block
- */
-typedef std::pair<Addr, Addr> BasicBlockRange;
-
-/** Overload hash function for BasicBlockRange type */
-__hash_namespace_begin
-template <>
-struct hash<BasicBlockRange>
-{
-  public:
-    size_t operator()(const BasicBlockRange &bb) const {
-        return hash<Addr>()(bb.first + bb.second);
-    }
-};
-__hash_namespace_end
-
+#include "sim/probe/probe.hh"
 
 class AtomicSimpleCPU : public BaseSimpleCPU
 {
@@ -200,49 +179,8 @@ class AtomicSimpleCPU : public BaseSimpleCPU
     bool dcache_access;
     Tick dcache_latency;
 
-    /**
-     * Profile basic blocks for SimPoints.
-     * Called at every macro inst to increment basic block inst counts and
-     * to profile block if end of block.
-     */
-    void profileSimPoint();
-
-    /** Data structures for SimPoints BBV generation
-     *  @{
-     */
-
-    /** Whether SimPoint BBV profiling is enabled */
-    const bool simpoint;
-    /** SimPoint profiling interval size in instructions */
-    const uint64_t intervalSize;
-
-    /** Inst count in current basic block */
-    uint64_t intervalCount;
-    /** Excess inst count from previous interval*/
-    uint64_t intervalDrift;
-    /** Pointer to SimPoint BBV output stream */
-    std::ostream *simpointStream;
-
-    /** Basic Block information */
-    struct BBInfo {
-        /** Unique ID */
-        uint64_t id;
-        /** Num of static insts in BB */
-        uint64_t insts;
-        /** Accumulated dynamic inst count executed by BB */
-        uint64_t count;
-    };
-
-    /** Hash table containing all previously seen basic blocks */
-    m5::hash_map<BasicBlockRange, BBInfo> bbMap;
-    /** Currently executing basic block */
-    BasicBlockRange currentBBV;
-    /** inst count in current basic block */
-    uint64_t currentBBVInstCount;
-
-    /** @}
-     *  End of data structures for SimPoints BBV generation
-     */
+    /** Probe Points. */
+    ProbePointArg<std::pair<SimpleThread*, const StaticInstPtr>> *ppCommit;
 
   protected:
 
@@ -270,6 +208,8 @@ class AtomicSimpleCPU : public BaseSimpleCPU
     Fault writeMem(uint8_t *data, unsigned size,
                    Addr addr, unsigned flags, uint64_t *res);
 
+    virtual void regProbePoints();
+
     /**
      * Print state of address in memory system via PrintReq (for
      * debugging).
diff --git a/src/cpu/simple/probes/SConscript b/src/cpu/simple/probes/SConscript
new file mode 100644 (file)
index 0000000..648d205
--- /dev/null
@@ -0,0 +1,35 @@
+# -*- mode:python -*-
+
+# Copyright (c) 2014 ARM Limited
+# 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: Curtis Dunham
+
+Import('*')
+
+if 'AtomicSimpleCPU' in env['CPU_MODELS']:
+    SimObject('SimPoint.py')
+    Source('simpoint.cc')
diff --git a/src/cpu/simple/probes/SimPoint.py b/src/cpu/simple/probes/SimPoint.py
new file mode 100644 (file)
index 0000000..ac6ec07
--- /dev/null
@@ -0,0 +1,48 @@
+# Copyright (c) 2012-2014 ARM Limited
+# All rights reserved.
+#
+# The license below extends only to copyright in the software and shall
+# not be construed as granting a license to any other intellectual
+# property including but not limited to intellectual property relating
+# to a hardware implementation of the functionality of the software
+# licensed hereunder.  You may use the software subject to the license
+# terms below provided that you ensure that this notice is replicated
+# unmodified and in its entirety in all distributions of the software,
+# modified or unmodified, in source code or in binary form.
+#
+# 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: Curtis Dunham
+
+from m5.params import *
+from Probe import ProbeListenerObject
+
+class SimPoint(ProbeListenerObject):
+    """Probe for collecting SimPoint Basic Block Vectors (BBVs)."""
+
+    type = 'SimPoint'
+    cxx_header = "cpu/simple/probes/simpoint.hh"
+
+    interval = Param.UInt64(100000000, "Interval Size (insts)")
+    profile_file = Param.String("simpoint.bb.gz", "BBV (output) file")
diff --git a/src/cpu/simple/probes/simpoint.cc b/src/cpu/simple/probes/simpoint.cc
new file mode 100644 (file)
index 0000000..22eaad0
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2012-2014 ARM Limited
+ * All rights reserved.
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder.  You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
+ * 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: Dam Sunwoo
+ *          Curtis Dunham
+ */
+
+#include "base/output.hh"
+#include "cpu/simple/probes/simpoint.hh"
+
+SimPoint::SimPoint(const SimPointParams *p)
+    : ProbeListenerObject(p),
+      intervalSize(p->interval),
+      intervalCount(0),
+      intervalDrift(0),
+      simpointStream(NULL),
+      currentBBV(0, 0),
+      currentBBVInstCount(0)
+{
+    simpointStream = simout.create(p->profile_file, false);
+    if (!simpointStream)
+        fatal("unable to open SimPoint profile_file");
+}
+
+SimPoint::~SimPoint()
+{
+    simout.close(simpointStream);
+}
+
+void
+SimPoint::init()
+{}
+
+void
+SimPoint::regProbeListeners()
+{
+    typedef ProbeListenerArg<SimPoint, std::pair<SimpleThread*,StaticInstPtr>>
+        SimPointListener;
+    listeners.push_back(new SimPointListener(this, "Commit",
+                                             &SimPoint::profile));
+}
+
+void
+SimPoint::profile(const std::pair<SimpleThread*, StaticInstPtr>& p)
+{
+    SimpleThread* thread = p.first;
+    StaticInstPtr inst = p.second;
+
+    if (!currentBBVInstCount)
+        currentBBV.first = thread->pcState().instAddr();
+
+    ++intervalCount;
+    ++currentBBVInstCount;
+
+    // If inst is control inst, assume end of basic block.
+    if (inst->isControl()) {
+        currentBBV.second = thread->pcState().instAddr();
+
+        auto map_itr = bbMap.find(currentBBV);
+        if (map_itr == bbMap.end()){
+            // If a new (previously unseen) basic block is found,
+            // add a new unique id, record num of insts and insert into bbMap.
+            BBInfo info;
+            info.id = bbMap.size() + 1;
+            info.insts = currentBBVInstCount;
+            info.count = currentBBVInstCount;
+            bbMap.insert(std::make_pair(currentBBV, info));
+        } else {
+            // If basic block is seen before, just increment the count by the
+            // number of insts in basic block.
+            BBInfo& info = map_itr->second;
+            info.count += currentBBVInstCount;
+        }
+        currentBBVInstCount = 0;
+
+        // Reached end of interval if the sum of the current inst count
+        // (intervalCount) and the excessive inst count from the previous
+        // interval (intervalDrift) is greater than/equal to the interval size.
+        if (intervalCount + intervalDrift >= intervalSize) {
+            // summarize interval and display BBV info
+            std::vector<std::pair<uint64_t, uint64_t> > counts;
+            for (auto map_itr = bbMap.begin(); map_itr != bbMap.end();
+                    ++map_itr) {
+                BBInfo& info = map_itr->second;
+                if (info.count != 0) {
+                    counts.push_back(std::make_pair(info.id, info.count));
+                    info.count = 0;
+                }
+            }
+            std::sort(counts.begin(), counts.end());
+
+            // Print output BBV info
+            *simpointStream << "T";
+            for (auto cnt_itr = counts.begin(); cnt_itr != counts.end();
+                    ++cnt_itr) {
+                *simpointStream << ":" << cnt_itr->first
+                                << ":" << cnt_itr->second << " ";
+            }
+            *simpointStream << "\n";
+
+            intervalDrift = (intervalCount + intervalDrift) - intervalSize;
+            intervalCount = 0;
+        }
+    }
+}
+
+/** SimPoint SimObject */
+SimPoint*
+SimPointParams::create()
+{
+    return new SimPoint(this);
+}
diff --git a/src/cpu/simple/probes/simpoint.hh b/src/cpu/simple/probes/simpoint.hh
new file mode 100644 (file)
index 0000000..e2c3437
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2012-2014 ARM Limited
+ * All rights reserved.
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder.  You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
+ * 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: Dam Sunwoo
+ *          Curtis Dunham
+ */
+
+#ifndef __CPU_SIMPLE_PROBES_SIMPOINT_HH__
+#define __CPU_SIMPLE_PROBES_SIMPOINT_HH__
+
+#include "base/hashmap.hh"
+#include "cpu/simple_thread.hh"
+#include "params/SimPoint.hh"
+#include "sim/probe/probe.hh"
+
+/**
+ * Probe for SimPoints BBV generation
+ */
+
+/**
+ *  Start and end address of basic block for SimPoint profiling.
+ *  This structure is used to look up the hash table of BBVs.
+ *  - first: PC of first inst in basic block
+ *  - second: PC of last inst in basic block
+ */
+typedef std::pair<Addr, Addr> BasicBlockRange;
+
+/** Overload hash function for BasicBlockRange type */
+__hash_namespace_begin
+template <>
+struct hash<BasicBlockRange>
+{
+  public:
+    size_t operator()(const BasicBlockRange &bb) const {
+        return hash<Addr>()(bb.first + bb.second);
+    }
+};
+__hash_namespace_end
+
+class SimPoint : public ProbeListenerObject
+{
+  public:
+    SimPoint(const SimPointParams *params);
+    virtual ~SimPoint();
+
+    virtual void init();
+
+    virtual void regProbeListeners();
+
+    /**
+     * Profile basic blocks for SimPoints.
+     * Called at every macro inst to increment basic block inst counts and
+     * to profile block if end of block.
+     */
+    void profile(const std::pair<SimpleThread*, StaticInstPtr>&);
+
+  private:
+    /** SimPoint profiling interval size in instructions */
+    const uint64_t intervalSize;
+
+    /** Inst count in current basic block */
+    uint64_t intervalCount;
+    /** Excess inst count from previous interval*/
+    uint64_t intervalDrift;
+    /** Pointer to SimPoint BBV output stream */
+    std::ostream *simpointStream;
+
+    /** Basic Block information */
+    struct BBInfo {
+        /** Unique ID */
+        uint64_t id;
+        /** Num of static insts in BB */
+        uint64_t insts;
+        /** Accumulated dynamic inst count executed by BB */
+        uint64_t count;
+    };
+
+    /** Hash table containing all previously seen basic blocks */
+    m5::hash_map<BasicBlockRange, BBInfo> bbMap;
+    /** Currently executing basic block */
+    BasicBlockRange currentBBV;
+    /** inst count in current basic block */
+    uint64_t currentBBVInstCount;
+};
+
+#endif // __CPU_SIMPLE_PROBES_SIMPOINT_HH__