#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;
class CacheReqPacket;
typedef CacheReqPacket* CacheReqPktPtr;
-class CacheUnit : public Resource {
+class CacheUnit : public Resource
+{
public:
typedef ThePipeline::DynInstPtr DynInstPtr;
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:
public:
/** Default constructor. */
CachePort(CacheUnit *_cachePortUnit)
- : Port(_cachePortUnit->name() + "-cache-port", (MemObject*)_cachePortUnit->cpu),
- cachePortUnit(_cachePortUnit)
+ : Port(_cachePortUnit->name() + "-cache-port",
+ (MemObject*)_cachePortUnit->cpu),
+ 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;
-
- PacketPtr retryPkt;
+ bool cachePortBlocked;
- int retrySlot;
+ std::list<Addr> addrList[ThePipeline::MaxThreads];
- bool cacheBlocked;
-
- std::vector<Addr> addrList;
-
- std::map<Addr, InstSeqNum> addrMap;
+ m5::hash_map<Addr, InstSeqNum> addrMap[ThePipeline::MaxThreads];
public:
int cacheBlkSize;
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];
-
- //unsigned fetchOffset[ThePipeline::MaxThreads];
+ bool tlbBlocked[ThePipeline::MaxThreads];
+ InstSeqNum tlbBlockSeqNum[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();
};
-class CacheRequest : public ResourceRequest {
+//@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)
{
- /*
- 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;
- }*/
-
- 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)
+ {
+ memAccComplete = completed;
+ }
- void setMemAccCompleted(bool completed = true) { memAccComplete = completed; }
+ bool is2ndSplit()
+ {
+ return split2ndAccess;
+ }
+
bool isMemAccComplete() { return memAccComplete; }
void setMemAccPending(bool pending = true) { memAccPending = pending; }
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 {
+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__