* 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: Steve Reinhardt
+ * Nathan Binkert
*/
#ifndef __CPU_BASE_HH__
#include <vector>
+#include "arch/isa_traits.hh"
#include "base/statistics.hh"
#include "config/full_system.hh"
-#include "cpu/sampler/sampler.hh"
#include "sim/eventq.hh"
-#include "sim/sim_object.hh"
-#include "arch/isa_traits.hh"
+#include "sim/insttracer.hh"
+#include "mem/mem_object.hh"
+
+#if FULL_SYSTEM
+#include "arch/interrupts.hh"
+#endif
-class System;
-namespace Kernel { class Statistics; }
class BranchPred;
-class ExecContext;
+class CheckerCPU;
+class ThreadContext;
+class System;
+class Port;
+
+namespace TheISA
+{
+ class Predecoder;
+}
-class BaseCPU : public SimObject
+class CPUProgressEvent : public Event
+{
+ protected:
+ Tick interval;
+ Counter lastNumInst;
+ BaseCPU *cpu;
+
+ public:
+ CPUProgressEvent(EventQueue *q, Tick ival, BaseCPU *_cpu);
+
+ void process();
+
+ virtual const char *description();
+};
+
+class BaseCPU : public MemObject
{
protected:
// CPU's clock period in terms of the number of ticks of curTime.
Tick clock;
+ // @todo remove me after debugging with legion done
+ Tick instCnt;
public:
+// Tick currentTick;
inline Tick frequency() const { return Clock::Frequency / clock; }
inline Tick cycles(int numCycles) const { return clock * numCycles; }
inline Tick curCycle() const { return curTick / clock; }
+ // @todo remove me after debugging with legion done
+ Tick instCount() { return instCnt; }
+
+ /** The next cycle the CPU should be scheduled, given a cache
+ * access or quiesce event returning on this cycle. This function
+ * may return curTick if the CPU should run on the current cycle.
+ */
+ Tick nextCycle();
+
+ /** The next cycle the CPU should be scheduled, given a cache
+ * access or quiesce event returning on the given Tick. This
+ * function may return curTick if the CPU should run on the
+ * current cycle.
+ * @param begin_tick The tick that the event is completing on.
+ */
+ Tick nextCycle(Tick begin_tick);
#if FULL_SYSTEM
protected:
- uint64_t interrupts[TheISA::NumInterruptLevels];
- uint64_t intstatus;
+// uint64_t interrupts[TheISA::NumInterruptLevels];
+// uint64_t intstatus;
+ TheISA::Interrupts interrupts;
public:
virtual void post_interrupt(int int_num, int index);
virtual void clear_interrupt(int int_num, int index);
virtual void clear_interrupts();
- bool checkInterrupts;
+ virtual uint64_t get_interrupts(int int_num);
- bool check_interrupt(int int_num) const {
- if (int_num > TheISA::NumInterruptLevels)
- panic("int_num out of bounds\n");
-
- return interrupts[int_num] != 0;
- }
-
- bool check_interrupts() const { return intstatus != 0; }
- uint64_t intr_status() const { return intstatus; }
+ bool check_interrupts(ThreadContext * tc) const
+ { return interrupts.check_interrupts(tc); }
class ProfileEvent : public Event
{
#endif
protected:
- std::vector<ExecContext *> execContexts;
+ std::vector<ThreadContext *> threadContexts;
+ std::vector<TheISA::Predecoder *> predecoders;
+
+ Trace::InstTracer * tracer;
public:
+ /// Provide access to the tracer pointer
+ Trace::InstTracer * getTracer() { return tracer; }
+
/// Notify the CPU that the indicated context is now active. The
/// delay parameter indicates the number of ticks to wait before
/// executing (typically 0 or 1).
/// Notify the CPU that the indicated context is now halted.
virtual void haltContext(int thread_num) {}
+ /// Given a Thread Context pointer return the thread num
+ int findContext(ThreadContext *tc);
+
+ /// Given a thread num get tho thread context for it
+ ThreadContext *getContext(int tn) { return threadContexts[tn]; }
+
public:
struct Params
{
bool functionTrace;
Tick functionTraceStart;
System *system;
-#if FULL_SYSTEM
int cpu_id;
+ Trace::InstTracer * tracer;
+
+ Tick phase;
+#if FULL_SYSTEM
Tick profile;
+
+ bool do_statistics_insts;
+ bool do_checkpoint_insts;
+ bool do_quiesce;
#endif
+ Tick progress_interval;
+ BaseCPU *checker;
Params();
};
virtual void activateWhenReady(int tid) {};
- void registerExecContexts();
+ void registerThreadContexts();
/// Prepare for another CPU to take over execution. When it is
/// is ready (drained pipe) it signals the sampler.
- virtual void switchOut(Sampler *);
+ virtual void switchOut();
/// Take over execution from the given CPU. Used for warm-up and
/// sampling.
- virtual void takeOverFrom(BaseCPU *);
+ virtual void takeOverFrom(BaseCPU *, Port *ic, Port *dc);
/**
* Number of threads we're actually simulating (<= SMT_MAX_THREADS).
System *system;
+ Tick phase;
+
#if FULL_SYSTEM
/**
* Serialize this object to the given output stream.
public:
// Number of CPU cycles simulated
Stats::Scalar<> numCycles;
-
-#if FULL_SYSTEM
- Kernel::Statistics *kernelStats;
-#endif
};
#endif // __CPU_BASE_HH__