dev-arm: Add a VExpress_GEM5_V2 platform with GICv3 support
[gem5.git] / src / dev / intel_8254_timer.hh
index 23596a687c80b917d94a2361cc7584c93ff6fce2..86b91620db674eb129409dc90ccd0decaf599b98 100644 (file)
 #ifndef __DEV_8254_HH__
 #define __DEV_8254_HH__
 
+#include <iostream>
+#include <string>
+
 #include "base/bitunion.hh"
-#include "sim/eventq.hh"
-#include "sim/host.hh"
+#include "base/types.hh"
+#include "base/trace.hh"
+#include "debug/Intel8254Timer.hh"
+#include "sim/eventq_impl.hh"
 #include "sim/serialize.hh"
 
-#include <string>
-#include <iostream>
-
 /** Programmable Interval Timer (Intel 8254) */
-class Intel8254Timer
+class Intel8254Timer : public EventManager
 {
+  protected:
     BitUnion8(CtrlReg)
         Bitfield<7, 6> sel;
         Bitfield<5, 4> rw;
@@ -89,7 +92,7 @@ class Intel8254Timer
             CounterEvent(Counter*);
 
             /** Event process */
-            virtual void process();
+            void process();
 
             /** Event description */
             virtual const char *description() const;
@@ -97,16 +100,25 @@ class Intel8254Timer
             friend class Counter;
 
             void setTo(int clocks);
+
+            int clocksLeft();
+
+            Tick getInterval();
         };
 
       private:
         std::string _name;
         const std::string &name() const { return _name; }
 
+        unsigned int num;
+
         CounterEvent event;
 
-        /** Current count value */
-        uint16_t count;
+        /** True after startup is called. */
+        bool running;
+
+        /** Initial count value */
+        uint16_t initial_count;
 
         /** Latched count */
         uint16_t latched_count;
@@ -114,6 +126,9 @@ class Intel8254Timer
         /** Interrupt period */
         uint16_t period;
 
+        /** When to start ticking */
+        Tick offset;
+
         /** Current mode of operation */
         uint8_t mode;
 
@@ -129,12 +144,18 @@ class Intel8254Timer
         /** Determine which byte of a 16-bit count value to read/write */
         uint8_t read_byte, write_byte;
 
+        /** Pointer to container */
+        Intel8254Timer *parent;
+
       public:
-        Counter(const std::string &name);
+        Counter(Intel8254Timer *p, const std::string &name, unsigned int num);
 
         /** Latch the current count (if one is not already latched) */
         void latchCount();
 
+        /** Get the current count for this counter */
+        int currentCount();
+
         /** Set the read/write mode */
         void setRW(int rw_val);
 
@@ -158,7 +179,7 @@ class Intel8254Timer
          * @param base The base name of the counter object.
          * @param os   The stream to serialize to.
          */
-        void serialize(const std::string &base, std::ostream &os);
+        void serialize(const std::string &base, CheckpointOut &cp) const;
 
         /**
          * Reconstruct the state of this object from a checkpoint.
@@ -166,34 +187,66 @@ class Intel8254Timer
          * @param cp The checkpoint use.
          * @param section The section name of this object
          */
-        void unserialize(const std::string &base, Checkpoint *cp,
-                         const std::string &section);
+        void unserialize(const std::string &base, CheckpointIn &cp);
+
+        /** Start ticking */
+        void startup();
     };
 
-  private:
+  protected:
     std::string _name;
     const std::string &name() const { return _name; }
 
     /** PIT has three seperate counters */
     Counter *counter[3];
 
+    virtual void
+    counterInterrupt(unsigned int num)
+    {
+        DPRINTF(Intel8254Timer, "Timer interrupt from counter %d.\n", num);
+    }
+
   public:
-    /** Public way to access individual counters (avoid array accesses) */
-    Counter counter0;
-    Counter counter1;
-    Counter counter2;
 
-    Intel8254Timer(const std::string &name);
+    virtual
+    ~Intel8254Timer()
+    {}
+
+    Intel8254Timer(EventManager *em, const std::string &name,
+            Counter *counter0, Counter *counter1, Counter *counter2);
+
+    Intel8254Timer(EventManager *em, const std::string &name);
 
     /** Write control word */
     void writeControl(const CtrlReg data);
 
+    uint8_t
+    readCounter(unsigned int num)
+    {
+        assert(num < 3);
+        return counter[num]->read();
+    }
+
+    void
+    writeCounter(unsigned int num, const uint8_t data)
+    {
+        assert(num < 3);
+        counter[num]->write(data);
+    }
+
+    bool
+    outputHigh(unsigned int num)
+    {
+        assert(num < 3);
+        return counter[num]->outputHigh();
+    }
+
     /**
      * Serialize this object to the given output stream.
      * @param base The base name of the counter object.
      * @param os The stream to serialize to.
      */
-    void serialize(const std::string &base, std::ostream &os);
+    void serialize(const std::string &base, CheckpointOut &cp) const;
 
     /**
      * Reconstruct the state of this object from a checkpoint.
@@ -201,8 +254,10 @@ class Intel8254Timer
      * @param cp The checkpoint use.
      * @param section The section name of this object
      */
-    void unserialize(const std::string &base, Checkpoint *cp,
-                     const std::string &section);
+    void unserialize(const std::string &base, CheckpointIn &cp);
+
+    /** Start ticking */
+    void startup();
 };
 
 #endif // __DEV_8254_HH__