Yet another merge with the main repository.
[gem5.git] / src / cpu / inorder / resources / cache_unit.hh
index 8cd2b89cbf0915da2de6d89a3a3c8405ae7447dd..2155c920c7fe314690e5f9f63b4bec607f610fec 100644 (file)
 #ifndef __CPU_INORDER_CACHE_UNIT_HH__
 #define __CPU_INORDER_CACHE_UNIT_HH__
 
-#include <vector>
 #include <list>
 #include <string>
+#include <vector>
 
-//#include "cpu/inorder/params.hh"
-
-#include "cpu/inorder/resource.hh"
+#include "arch/predecoder.hh"
+#include "arch/tlb.hh"
+#include "base/hashmap.hh"
+#include "config/the_isa.hh"
 #include "cpu/inorder/inorder_dyn_inst.hh"
+#include "cpu/inorder/pipeline_traits.hh"
+#include "cpu/inorder/resource.hh"
 #include "mem/packet.hh"
 #include "mem/packet_access.hh"
 #include "mem/port.hh"
-#include "cpu/inorder/pipeline_traits.hh"
-#include "sim/sim_object.hh"
-
 #include "params/InOrderCPU.hh"
+#include "sim/sim_object.hh"
 
 class CacheRequest;
 typedef CacheRequest* CacheReqPtr;
@@ -62,18 +63,16 @@ class CacheUnit : public Resource
   public:
     CacheUnit(std::string res_name, int res_id, int res_width,
               int res_latency, InOrderCPU *_cpu, ThePipeline::Params *params);
-    virtual ~CacheUnit() {}
 
     enum Command {
-        InitiateFetch,
-        CompleteFetch,
         InitiateReadData,
         CompleteReadData,
         InitiateWriteData,
         CompleteWriteData,
-        Fetch,
-        ReadData,
-        WriteData
+        InitSecondSplitRead,
+        InitSecondSplitWrite,
+        CompleteSecondSplitRead,
+        CompleteSecondSplitWrite
     };
 
   public:
@@ -94,103 +93,98 @@ class CacheUnit : public Resource
             cachePortUnit(_cachePortUnit)
         { }
 
-        bool snoopRangeSent;
-
       protected:
         /** Atomic version of receive.  Panics. */
-        virtual Tick recvAtomic(PacketPtr pkt);
+        Tick recvAtomic(PacketPtr pkt);
 
-        /** Functional version of receive.  Panics. */
-        virtual void recvFunctional(PacketPtr pkt);
+        /** Functional version of receive.*/
+        void recvFunctional(PacketPtr pkt);
 
-        /** Receives status change.  Other than range changing, panics. */
-        virtual void recvStatusChange(Status status);
+        /** Receives range changes. */
+        void recvRangeChange();
 
-        /** Returns the address ranges of this device. */
-        virtual void getDeviceAddressRanges(AddrRangeList &resp,
-                                            AddrRangeList &snoop)
-        { resp.clear(); snoop.clear(); }
-
-        /** Timing version of receive. Handles setting fetch to the
-         * proper status to start fetching. */
-        virtual bool recvTiming(PacketPtr pkt);
+        /** Timing version of receive */
+        bool recvTiming(PacketPtr pkt);
 
         /** Handles doing a retry of a failed fetch. */
-        virtual void recvRetry();
+        void recvRetry();
     };
 
-    enum CachePortStatus {
-        cacheWaitResponse,
-        cacheWaitRetry,
-        cacheAccessComplete
-    };
+    void init();
 
-    ///virtual void init();
+    ResourceRequest* getRequest(DynInstPtr _inst, int stage_num,
+                                int res_idx, int slot_num,
+                                unsigned cmd);
 
-    virtual ResourceRequest* getRequest(DynInstPtr _inst, int stage_num,
-                                        int res_idx, int slot_num,
-                                        unsigned cmd);
+    ResReqPtr findRequest(DynInstPtr inst);
+    ResReqPtr findRequest(DynInstPtr inst, int idx);
 
     void requestAgain(DynInstPtr inst, bool &try_request);
 
-    int getSlot(DynInstPtr inst);
+    virtual int getSlot(DynInstPtr inst);
 
-    void freeSlot(int slot_num);
+    /** Executes one of the commands from the "Command" enum */
+    virtual void execute(int slot_num);
 
-    /** Execute the function of this resource. The Default is action
-     *  is to do nothing. More specific models will derive from this
-     *  class and define their own execute function.
-     */
-    void execute(int slot_num);
+    virtual void squash(DynInstPtr inst, int stage_num,
+                InstSeqNum squash_seq_num, ThreadID tid);
 
-    void squash(DynInstPtr inst, int stage_num,
-                InstSeqNum squash_seq_num, unsigned tid);
+    void squashDueToMemStall(DynInstPtr inst, int stage_num,
+                             InstSeqNum squash_seq_num, ThreadID tid);
 
-    /** Processes cache completion event. */
-    void processCacheCompletion(PacketPtr pkt);
+    virtual void squashCacheRequest(CacheReqPtr req_ptr);
 
-    void recvRetry();
+    /** After memory request is completedd in the cache, then do final
+        processing to complete the request in the CPU.
+    */
+    virtual void processCacheCompletion(PacketPtr pkt);
 
-    /** Align a PC to the start of an I-cache block. */
-    Addr cacheBlockAlignPC(Addr addr)
-    {
-        //addr = TheISA::realPCToFetchPC(addr);
-        return (addr & ~(cacheBlkMask));
-    }
+    /** Create request that will interface w/TLB and Memory objects */
+    virtual void setupMemRequest(DynInstPtr inst, CacheReqPtr cache_req,
+                                 int acc_size, int flags);
+
+    void finishCacheUnitReq(DynInstPtr inst, CacheRequest *cache_req);
+
+    void buildDataPacket(CacheRequest *cache_req);
+
+    bool processSquash(CacheReqPacket *cache_pkt);
+
+    void trap(Fault fault, ThreadID tid, DynInstPtr inst);
+
+    void recvRetry();
 
     /** Returns a specific port. */
     Port *getPort(const std::string &if_name, int idx);
+    
+    Fault read(DynInstPtr inst, Addr addr,
+               uint8_t *data, unsigned size, unsigned flags);
 
-    /** Fetch on behalf of an instruction. Will check to see
-     *  if instruction is actually in resource before
-     *  trying to fetch.
-     */
-    //Fault doFetchAccess(DynInstPtr inst);
+    Fault write(DynInstPtr inst, uint8_t *data, unsigned size,
+                Addr addr, unsigned flags, uint64_t *res);
+
+    void doTLBAccess(DynInstPtr inst, CacheReqPtr cache_req, int acc_size,
+                      int flags,  TheISA::TLB::Mode tlb_mode);
 
     /** Read/Write on behalf of an instruction.
      *  curResSlot needs to be a valid value in instruction.
      */
-    Fault doDataAccess(DynInstPtr inst);
+    void doCacheAccess(DynInstPtr inst, uint64_t *write_result=NULL,
+                        CacheReqPtr split_req=NULL);
 
     uint64_t getMemData(Packet *packet);
 
+    void setAddrDependency(DynInstPtr inst);
+    virtual void removeAddrDependency(DynInstPtr inst);
+    
   protected:
     /** Cache interface. */
     CachePort *cachePort;
 
-    CachePortStatus cacheStatus;
-
-    CacheReqPtr retryReq;
+    bool cachePortBlocked;
 
-    PacketPtr retryPkt;
+    std::list<Addr> addrList[ThePipeline::MaxThreads];
 
-    int retrySlot;
-
-    bool cacheBlocked;
-
-    std::vector<Addr> addrList;
-
-    std::map<Addr, InstSeqNum> addrMap;
+    m5::hash_map<Addr, InstSeqNum> addrMap[ThePipeline::MaxThreads];
 
   public:
     int cacheBlkSize;
@@ -203,79 +197,60 @@ class CacheUnit : public Resource
         return (addr & ~(cacheBlkMask));
     }
 
-    /** THINGS USED FOR FETCH */
-    // NO LONGER USED BY COMMENT OUT UNTIL FULL VERIFICATION
-    /** The mem line being fetched. */
-    //uint8_t *cacheData[ThePipeline::MaxThreads];
-
-    /** The Addr of the cacheline that has been loaded. */
-    //Addr cacheBlockAddr[ThePipeline::MaxThreads];
+    bool tlbBlocked[ThePipeline::MaxThreads];
+    InstSeqNum tlbBlockSeqNum[ThePipeline::MaxThreads];
 
-    //unsigned fetchOffset[ThePipeline::MaxThreads];
-
-    /** @todo: Add Resource Stats Here */
+    TheISA::TLB* tlb();
+    TheISA::TLB *_tlb;
 };
 
-struct CacheSchedEntry : public ThePipeline::ScheduleEntry
-{
-    enum EntryType {
-        FetchAccess,
-        DataAccess
-    };
+class CacheUnitEvent : public ResourceEvent {
+  public:
+    const std::string name() const
+    {
+        return "CacheUnitEvent";
+    }
 
-    CacheSchedEntry(int stage_num, int _priority, int res_num,
-                    MemCmd::Command pkt_cmd, EntryType _type = FetchAccess)
-        : ScheduleEntry(stage_num, _priority, res_num), pktCmd(pkt_cmd),
-          type(_type)
-    { }
 
-    MemCmd::Command pktCmd;
-    EntryType type;
+    /** Constructs a resource event. */
+    CacheUnitEvent();
+    virtual ~CacheUnitEvent() {}
+
+    /** Processes a resource event. */
+    void process();
 };
 
+//@todo: Move into CacheUnit Class for private access to "valid" field
 class CacheRequest : public ResourceRequest
 {
   public:
-    CacheRequest(CacheUnit *cres, DynInstPtr inst, int stage_num, int res_idx,
-                 int slot_num, unsigned cmd, int req_size,
-                 MemCmd::Command pkt_cmd, unsigned flags, int cpu_id)
-        : ResourceRequest(cres, inst, stage_num, res_idx, slot_num, cmd),
-          pktCmd(pkt_cmd), memAccComplete(false), memAccPending(false)
-    {
-        memReq = inst->memReq;
+    CacheRequest(CacheUnit *cres)
+        :  ResourceRequest(cres), memReq(NULL), reqData(NULL),
+           dataPkt(NULL), memAccComplete(false),
+           memAccPending(false), tlbStall(false), splitAccess(false),
+           splitAccessNum(-1), split2ndAccess(false),
+           fetchBufferFill(false)
+    { }
 
-        reqData = new uint8_t[req_size];
-        retryPkt = NULL;
+    virtual ~CacheRequest()
+    {
+        if (reqData && !splitAccess)
+            delete [] reqData;
     }
 
-    virtual ~CacheRequest()
+    void setRequest(DynInstPtr _inst, int stage_num, int res_idx, int slot_num,
+                    unsigned _cmd, MemCmd::Command pkt_cmd, int idx)
     {
-#if 0
-        delete reqData;
-
-        // Can get rid of packet and packet request now
-        if (*dataPkt) {
-            if (*dataPkt->req) {
-                delete dataPkt->req;
-            }
-            delete dataPkt;
-        }
-
-        // Can get rid of packet and packet request now
-        if (retryPkt) {
-            if (retryPkt->req) {
-                delete retryPkt->req;
-            }
-            delete retryPkt;
-        }
-#endif
-
-        if (memReq)
-            delete memReq;
+        pktCmd = pkt_cmd;
+        instIdx = idx;
+
+        ResourceRequest::setRequest(_inst, stage_num, res_idx, slot_num, _cmd);
     }
 
+    void clearRequest();
+
     virtual PacketDataPtr getData()
-    {  return reqData; }
+    { return reqData; }
 
     void
     setMemAccCompleted(bool completed = true)
@@ -283,6 +258,11 @@ class CacheRequest : public ResourceRequest
         memAccComplete = completed;
     }
 
+    bool is2ndSplit() 
+    {
+        return split2ndAccess;
+    }
+    
     bool isMemAccComplete() { return memAccComplete; }
 
     void setMemAccPending(bool pending = true) { memAccPending = pending; }
@@ -292,24 +272,37 @@ class CacheRequest : public ResourceRequest
     MemCmd::Command pktCmd;
     RequestPtr memReq;
     PacketDataPtr reqData;
-    PacketPtr dataPkt;
-    PacketPtr retryPkt;
+    CacheReqPacket *dataPkt;
 
     bool memAccComplete;
     bool memAccPending;
+    bool tlbStall;
+
+    bool splitAccess;
+    int splitAccessNum;
+    bool split2ndAccess;
+    int instIdx;    
+
+    /** Should we expect block from cache access or fetch buffer? */
+    bool fetchBufferFill;
 };
 
 class CacheReqPacket : public Packet
 {
   public:
     CacheReqPacket(CacheRequest *_req,
-                   Command _cmd, short _dest)
-        : Packet(_req->memReq, _cmd, _dest), cacheReq(_req)
+                   Command _cmd, short _dest, int _idx = 0)
+        : Packet(&(*_req->memReq), _cmd, _dest), cacheReq(_req),
+          instIdx(_idx), hasSlot(false), reqData(NULL), memReq(NULL)
     {
 
     }
 
     CacheRequest *cacheReq;
+    int instIdx;
+    bool hasSlot;
+    PacketDataPtr reqData;
+    RequestPtr memReq;
 };
 
 #endif //__CPU_CACHE_UNIT_HH__