ruby: abstract controller: mark some variables as const
[gem5.git] / src / mem / ruby / slicc_interface / AbstractController.hh
index 28c8a103a0b85553d89de287c71a3b5d1c1220c2..34160c149796ac89da47564d725bd02178118cbf 100644 (file)
+/*
+ * Copyright (c) 2009-2014 Mark D. Hill and David A. Wood
+ * 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.
+ */
 
-#ifndef ABSTRACTCONTROLLER_H
-#define ABSTRACTCONTROLLER_H
+#ifndef __MEM_RUBY_SLICC_INTERFACE_ABSTRACTCONTROLLER_HH__
+#define __MEM_RUBY_SLICC_INTERFACE_ABSTRACTCONTROLLER_HH__
 
-#include "sim/sim_object.hh"
-#include "params/RubyController.hh"
+#include <exception>
+#include <iostream>
+#include <string>
 
-#include "mem/ruby/common/Consumer.hh"
-#include "mem/protocol/MachineType.hh"
+#include "base/callback.hh"
+#include "mem/protocol/AccessPermission.hh"
 #include "mem/ruby/common/Address.hh"
+#include "mem/ruby/common/Consumer.hh"
+#include "mem/ruby/common/DataBlock.hh"
+#include "mem/ruby/common/Histogram.hh"
+#include "mem/ruby/common/MachineID.hh"
+#include "mem/ruby/network/MessageBuffer.hh"
+#include "mem/ruby/network/Network.hh"
+#include "mem/ruby/system/CacheRecorder.hh"
+#include "mem/packet.hh"
+#include "mem/qport.hh"
+#include "params/RubyController.hh"
+#include "mem/mem_object.hh"
 
-class MessageBuffer;
 class Network;
 
-class AbstractController : public SimObject, public Consumer {
-public:
+// used to communicate that an in_port peeked the wrong message type
+class RejectException: public std::exception
+{
+    virtual const char* what() const throw()
+    { return "Port rejected message based on type"; }
+};
+
+class AbstractController : public MemObject, public Consumer
+{
+  public:
     typedef RubyControllerParams Params;
-    AbstractController(const Params *p) : SimObject(p) {}
-  virtual void init(Network* net_ptr, const vector<string> & argv) = 0;
-
-  // returns the number of controllers created of the specific subtype
-  //  virtual int getNumberOfControllers() const = 0;
-  virtual MessageBuffer* getMandatoryQueue() const = 0;
-  virtual const int & getVersion() const = 0;
-  virtual const string toString() const = 0;  // returns text version of controller type
-  virtual const string getName() const = 0;   // return instance name
-  virtual const MachineType getMachineType() const = 0;
-  virtual void blockOnQueue(Address, MessageBuffer*) = 0;
-  virtual void unblock(Address) = 0;
-
-  virtual void print(ostream & out) const = 0;
-  virtual void printStats(ostream & out) const = 0;
-  virtual void printConfig(ostream & out) const = 0;
-  virtual void wakeup() = 0;
-  //  virtual void dumpStats(ostream & out) = 0;
-  virtual void clearStats() = 0;
+    AbstractController(const Params *p);
+    void init();
+    const Params *params() const { return (const Params *)_params; }
+
+    const NodeID getVersion() const { return m_machineID.getNum(); }
+    const MachineType getType() const { return m_machineID.getType(); }
+
+    void initNetworkPtr(Network* net_ptr) { m_net_ptr = net_ptr; }
+
+    // return instance name
+    void blockOnQueue(Addr, MessageBuffer*);
+    void unblock(Addr);
+
+    virtual MessageBuffer* getMandatoryQueue() const = 0;
+    virtual MessageBuffer* getMemoryQueue() const = 0;
+    virtual AccessPermission getAccessPermission(const Addr &addr) = 0;
+
+    virtual void print(std::ostream & out) const = 0;
+    virtual void wakeup() = 0;
+    virtual void resetStats() = 0;
+    virtual void regStats();
+
+    virtual void recordCacheTrace(int cntrl, CacheRecorder* tr) = 0;
+    virtual Sequencer* getSequencer() const = 0;
+
+    //! These functions are used by ruby system to read/write the data blocks
+    //! that exist with in the controller.
+    virtual void functionalRead(const Addr &addr, PacketPtr) = 0;
+    void functionalMemoryRead(PacketPtr);
+    //! The return value indicates the number of messages written with the
+    //! data from the packet.
+    virtual int functionalWriteBuffers(PacketPtr&) = 0;
+    virtual int functionalWrite(const Addr &addr, PacketPtr) = 0;
+    int functionalMemoryWrite(PacketPtr);
+
+    //! Function for enqueuing a prefetch request
+    virtual void enqueuePrefetch(const Addr &, const RubyRequestType&)
+    { fatal("Prefetches not implemented!");}
+
+    //! Function for collating statistics from all the controllers of this
+    //! particular type. This function should only be called from the
+    //! version 0 of this controller type.
+    virtual void collateStats()
+    {fatal("collateStats() should be overridden!");}
+
+    //! Initialize the message buffers.
+    virtual void initNetQueues() = 0;
+
+    /** A function used to return the port associated with this bus object. */
+    BaseMasterPort& getMasterPort(const std::string& if_name,
+                                  PortID idx = InvalidPortID);
+
+    void queueMemoryRead(const MachineID &id, Addr addr, Cycles latency);
+    void queueMemoryWrite(const MachineID &id, Addr addr, Cycles latency,
+                          const DataBlock &block);
+    void queueMemoryWritePartial(const MachineID &id, Addr addr, Cycles latency,
+                                 const DataBlock &block, int size);
+    void recvTimingResp(PacketPtr pkt);
+
+  public:
+    MachineID getMachineID() const { return m_machineID; }
+
+    Stats::Histogram& getDelayHist() { return m_delayHistogram; }
+    Stats::Histogram& getDelayVCHist(uint32_t index)
+    { return *(m_delayVCHistogram[index]); }
+
+  protected:
+    //! Profiles original cache requests including PUTs
+    void profileRequest(const std::string &request);
+    //! Profiles the delay associated with messages.
+    void profileMsgDelay(uint32_t virtualNetwork, Cycles delay);
+
+    void stallBuffer(MessageBuffer* buf, Addr addr);
+    void wakeUpBuffers(Addr addr);
+    void wakeUpAllBuffers(Addr addr);
+    void wakeUpAllBuffers();
+
+  protected:
+    const NodeID m_version;
+    MachineID m_machineID;
+    const NodeID m_clusterID;
+
+    // MasterID used by some components of gem5.
+    const MasterID m_masterId;
+
+    Network *m_net_ptr;
+    bool m_is_blocking;
+    std::map<Addr, MessageBuffer*> m_block_map;
+
+    typedef std::vector<MessageBuffer*> MsgVecType;
+    typedef std::set<MessageBuffer*> MsgBufType;
+    typedef std::map<Addr, MsgVecType* > WaitingBufType;
+    WaitingBufType m_waiting_buffers;
+
+    unsigned int m_in_ports;
+    unsigned int m_cur_in_port;
+    const int m_number_of_TBEs;
+    const int m_transitions_per_cycle;
+    const unsigned int m_buffer_size;
+    Cycles m_recycle_latency;
+
+    //! Counter for the number of cycles when the transitions carried out
+    //! were equal to the maximum allowed
+    Stats::Scalar m_fully_busy_cycles;
+
+    //! Histogram for profiling delay for the messages this controller
+    //! cares for
+    Stats::Histogram m_delayHistogram;
+    std::vector<Stats::Histogram *> m_delayVCHistogram;
+
+    //! Callback class used for collating statistics from all the
+    //! controller of this type.
+    class StatsCallback : public Callback
+    {
+      private:
+        AbstractController *ctr;
+
+      public:
+        virtual ~StatsCallback() {}
+        StatsCallback(AbstractController *_ctr) : ctr(_ctr) {}
+        void process() {ctr->collateStats();}
+    };
+
+    /**
+     * Port that forwards requests and receives responses from the
+     * memory controller.  It has a queue of packets not yet sent.
+     */
+    class MemoryPort : public QueuedMasterPort
+    {
+      private:
+        // Packet queues used to store outgoing requests and snoop responses.
+        ReqPacketQueue reqQueue;
+        SnoopRespPacketQueue snoopRespQueue;
+
+        // Controller that operates this port.
+        AbstractController *controller;
+
+      public:
+        MemoryPort(const std::string &_name, AbstractController *_controller,
+                   const std::string &_label);
+
+        // Function for receiving a timing response from the peer port.
+        // Currently the pkt is handed to the coherence controller
+        // associated with this port.
+        bool recvTimingResp(PacketPtr pkt);
+    };
+
+    /* Master port to the memory controller. */
+    MemoryPort memoryPort;
+
+    // State that is stored in packets sent to the memory controller.
+    struct SenderState : public Packet::SenderState
+    {
+        // Id of the machine from which the request originated.
+        MachineID id;
 
+        SenderState(MachineID _id) : id(_id)
+        {}
+    };
 };
 
-#endif
+#endif // __MEM_RUBY_SLICC_INTERFACE_ABSTRACTCONTROLLER_HH__