CheckerCPU: Re-factor CheckerCPU to be compatible with current gem5
[gem5.git] / src / cpu / base.hh
index 788f77e3a1ff6b1c9d083de4c241754deec08005..d4de55453dbd7e794294fc63b69c9ea199a9fe01 100644 (file)
@@ -1,5 +1,18 @@
 /*
+ * Copyright (c) 2011 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.
+ *
  * Copyright (c) 2002-2005 The Regents of The University of Michigan
+ * Copyright (c) 2011 Regents of the University of California
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -27,6 +40,7 @@
  *
  * Authors: Steve Reinhardt
  *          Nathan Binkert
+ *          Rick Strong
  */
 
 #ifndef __CPU_BASE_HH__
 
 #include <vector>
 
+#include "arch/isa_traits.hh"
+#include "arch/microcode_rom.hh"
 #include "base/statistics.hh"
 #include "config/full_system.hh"
-#include "sim/eventq.hh"
+#include "config/the_isa.hh"
 #include "mem/mem_object.hh"
-#include "arch/isa_traits.hh"
+#include "sim/eventq.hh"
+#include "sim/insttracer.hh"
 
 #if FULL_SYSTEM
 #include "arch/interrupts.hh"
 #endif
 
+class BaseCPUParams;
 class BranchPred;
 class CheckerCPU;
 class ThreadContext;
 class System;
 class Port;
 
+namespace TheISA
+{
+    class Predecoder;
+}
+
 class CPUProgressEvent : public Event
 {
   protected:
-    Tick interval;
+    Tick _interval;
     Counter lastNumInst;
     BaseCPU *cpu;
+    bool _repeatEvent;
 
   public:
-    CPUProgressEvent(EventQueue *q, Tick ival, BaseCPU *_cpu);
+    CPUProgressEvent(BaseCPU *_cpu, Tick ival = 0);
 
     void process();
 
-    virtual const char *description();
+    void interval(Tick ival) { _interval = ival; }
+    Tick interval() { return _interval; }
+
+    void repeatEvent(bool repeat) { _repeatEvent = repeat; }
+
+    virtual const char *description() const;
 };
 
 class BaseCPU : public MemObject
@@ -70,50 +99,126 @@ 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;
+    // every cpu has an id, put it in the base cpu
+    // Set at initialization, only time a cpuId might change is during a
+    // takeover (which should be done from within the BaseCPU anyway,
+    // therefore no setCpuId() method is provided
+    int _cpuId;
+
+    /**
+     * Define a base class for the CPU ports (instruction and data)
+     * that is refined in the subclasses. This class handles the
+     * common cases, i.e. the functional accesses and the status
+     * changes and address range queries. The default behaviour for
+     * both atomic and timing access is to panic and the corresponding
+     * subclasses have to override these methods.
+     */
+    class CpuPort : public Port
+    {
+      public:
+
+        /**
+         * Create a CPU port with a name and a structural owner.
+         *
+         * @param _name port name including the owner
+         * @param _name structural owner of this port
+         */
+        CpuPort(const std::string& _name, MemObject* _owner) :
+            Port(_name, _owner)
+        { }
+
+      protected:
+
+        virtual bool recvTiming(PacketPtr pkt);
+
+        virtual Tick recvAtomic(PacketPtr pkt);
+
+        virtual void recvRetry();
+
+        void recvFunctional(PacketPtr pkt);
+
+        void recvRangeChange();
+
+    };
 
   public:
+    /** Reads this CPU's ID. */
+    int cpuId() { return _cpuId; }
+
 //    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; }
+    inline Tick frequency() const { return SimClock::Frequency / clock; }
+    inline Tick ticks(int numCycles) const { return clock * numCycles; }
+    inline Tick curCycle() const { return curTick() / clock; }
+    inline Tick tickToCycles(Tick val) const { return val / clock; }
+    inline void workItemBegin() { numWorkItemsStarted++; }
+    inline void workItemEnd() { numWorkItemsCompleted++; }
+    // @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.
+     * 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
+     * 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);
 
+    TheISA::MicrocodeRom microcodeRom;
+
 #if FULL_SYSTEM
   protected:
-//    uint64_t interrupts[TheISA::NumInterruptLevels];
-//    uint64_t intstatus;
-    TheISA::Interrupts interrupts;
+    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;
+    TheISA::Interrupts *
+    getInterruptController()
+    {
+        return interrupts;
+    }
 
-    bool check_interrupts(ThreadContext * tc) const
-    { return interrupts.check_interrupts(tc); }
+    virtual void wakeup() = 0;
+
+    void
+    postInterrupt(int int_num, int index)
+    {
+        interrupts->post(int_num, index);
+        wakeup();
+    }
+
+    void
+    clearInterrupt(int int_num, int index)
+    {
+        interrupts->clear(int_num, index);
+    }
+
+    void
+    clearInterrupts()
+    {
+        interrupts->clearAll();
+    }
+
+    bool
+    checkInterrupts(ThreadContext *tc) const
+    {
+        return interrupts->checkInterrupts(tc);
+    }
 
     class ProfileEvent : public Event
     {
       private:
         BaseCPU *cpu;
-        int interval;
+        Tick interval;
 
       public:
-        ProfileEvent(BaseCPU *cpu, int interval);
+        ProfileEvent(BaseCPU *cpu, Tick interval);
         void process();
     };
     ProfileEvent *profileEvent;
@@ -121,9 +226,18 @@ class BaseCPU : public MemObject
 
   protected:
     std::vector<ThreadContext *> threadContexts;
+    std::vector<TheISA::Predecoder *> predecoders;
+
+    Trace::InstTracer * tracer;
 
   public:
 
+    // Mask to align PCs to MachInst sized boundaries
+    static const Addr PCMask = ~((Addr)sizeof(TheISA::MachInst) - 1);
+
+    /// 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).
@@ -138,36 +252,16 @@ class BaseCPU : public MemObject
     /// Notify the CPU that the indicated context is now halted.
     virtual void haltContext(int thread_num) {}
 
-  public:
-    struct Params
-    {
-        std::string name;
-        int numberOfThreads;
-        bool deferRegistration;
-        Counter max_insts_any_thread;
-        Counter max_insts_all_threads;
-        Counter max_loads_any_thread;
-        Counter max_loads_all_threads;
-        Tick clock;
-        bool functionTrace;
-        Tick functionTraceStart;
-        System *system;
-        int cpu_id;
-#if FULL_SYSTEM
-        Tick profile;
-
-        bool do_statistics_insts;
-        bool do_checkpoint_insts;
-        bool do_quiesce;
-#endif
-        Tick progress_interval;
-        BaseCPU *checker;
-
-        Params();
-    };
+   /// Given a Thread Context pointer return the thread num
+   int findContext(ThreadContext *tc);
 
-    const Params *params;
+   /// Given a thread num get tho thread context for it
+   ThreadContext *getContext(int tn) { return threadContexts[tn]; }
 
+  public:
+    typedef BaseCPUParams Params;
+    const Params *params() const
+    { return reinterpret_cast<const Params *>(_params); }
     BaseCPU(Params *params);
     virtual ~BaseCPU();
 
@@ -175,7 +269,7 @@ class BaseCPU : public MemObject
     virtual void startup();
     virtual void regStats();
 
-    virtual void activateWhenReady(int tid) {};
+    virtual void activateWhenReady(ThreadID tid) {};
 
     void registerThreadContexts();
 
@@ -185,13 +279,13 @@ class BaseCPU : public MemObject
 
     /// 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).
      * This is a constant for the duration of the simulation.
      */
-    int number_of_threads;
+    ThreadID numThreads;
 
     /**
      * Vector of per-thread instruction-based event queues.  Used for
@@ -209,6 +303,8 @@ class BaseCPU : public MemObject
 
     System *system;
 
+    Tick phase;
+
 #if FULL_SYSTEM
     /**
      * Serialize this object to the given output stream.
@@ -231,7 +327,7 @@ class BaseCPU : public MemObject
      */
     virtual BranchPred *getBranchPred() { return NULL; };
 
-    virtual Counter totalInstructions() const { return 0; }
+    virtual Counter totalInstructions() const = 0;
 
     // Function tracing
   private:
@@ -243,17 +339,16 @@ class BaseCPU : public MemObject
     void enableFunctionTrace();
     void traceFunctionsInternal(Addr pc);
 
-  protected:
+  private:
+    static std::vector<BaseCPU *> cpuList;   //!< Static global cpu list
+
+  public:
     void traceFunctions(Addr pc)
     {
         if (functionTracingEnabled)
             traceFunctionsInternal(pc);
     }
 
-  private:
-    static std::vector<BaseCPU *> cpuList;   //!< Static global cpu list
-
-  public:
     static int numSimulatedCPUs() { return cpuList.size(); }
     static Counter numSimulatedInstructions()
     {
@@ -268,7 +363,9 @@ class BaseCPU : public MemObject
 
   public:
     // Number of CPU cycles simulated
-    Stats::Scalar<> numCycles;
+    Stats::Scalar numCycles;
+    Stats::Scalar numWorkItemsStarted;
+    Stats::Scalar numWorkItemsCompleted;
 };
 
 #endif // __CPU_BASE_HH__