#include <algorithm>
#include "arch/faults.hh"
-#include "arch/isa_traits.hh"
+#include "arch/types.hh"
#include "config/full_system.hh"
#include "base/hashmap.hh"
#include "cpu/inst_seq.hh"
#include "sim/debug.hh"
#include "sim/sim_object.hh"
-//class PageTable;
+class MemObject;
/**
* Class that implements the actual LQ and SQ for each specific thread.
class OzoneLWLSQ {
public:
typedef typename Impl::Params Params;
- typedef typename Impl::FullCPU FullCPU;
+ typedef typename Impl::OzoneCPU OzoneCPU;
typedef typename Impl::BackEnd BackEnd;
typedef typename Impl::DynInstPtr DynInstPtr;
typedef typename Impl::IssueStruct IssueStruct;
typedef typename std::map<InstSeqNum, DynInstPtr>::iterator LdMapIt;
- private:
- class StoreCompletionEvent : public Event {
- public:
- /** Constructs a store completion event. */
- StoreCompletionEvent(DynInstPtr &inst, BackEnd *be,
- Event *wb_event, OzoneLWLSQ *lsq_ptr);
-
- /** Processes the store completion event. */
- void process();
-
- /** Returns the description of this event. */
- const char *description();
-
- private:
- /** The store index of the store being written back. */
- DynInstPtr inst;
-
- BackEnd *be;
- /** The writeback event for the store. Needed for store
- * conditionals.
- */
- public:
- Event *wbEvent;
- bool miss;
- private:
- /** The pointer to the LSQ unit that issued the store. */
- OzoneLWLSQ<Impl> *lsqPtr;
- };
-
public:
/** Constructs an LSQ unit. init() must be called prior to use. */
OzoneLWLSQ();
/** Returns the name of the LSQ unit. */
std::string name() const;
+ void regStats();
+
/** Sets the CPU pointer. */
- void setCPU(FullCPU *cpu_ptr)
- { cpu = cpu_ptr; }
+ void setCPU(OzoneCPU *cpu_ptr);
/** Sets the back-end stage pointer. */
void setBE(BackEnd *be_ptr)
{ be = be_ptr; }
- /** Sets the page table pointer. */
-// void setPageTable(PageTable *pt_ptr);
+ Port *getDcachePort() { return &dcachePort; }
/** Ticks the LSQ unit, which in this case only resets the number of
* used cache ports.
/** Writes back stores. */
void writebackStores();
+ /** Completes the data access that has been returned from the
+ * memory system. */
+ void completeDataAccess(PacketPtr pkt);
+
// @todo: Include stats in the LSQ unit.
//void regStats();
int numLoads() { return loads; }
/** Returns the number of stores in the SQ. */
- int numStores() { return stores; }
+ int numStores() { return stores + storesInFlight; }
/** Returns if either the LQ or SQ is full. */
bool isFull() { return lqFull() || sqFull(); }
bool lqFull() { return loads >= (LQEntries - 1); }
/** Returns if the SQ is full. */
- bool sqFull() { return stores >= (SQEntries - 1); }
+ bool sqFull() { return (stores + storesInFlight) >= (SQEntries - 1); }
/** Debugging function to dump instructions in the LSQ. */
void dumpInsts();
/** Returns if the LSQ unit will writeback on this cycle. */
bool willWB() { return storeQueue.back().canWB &&
- !storeQueue.back().completed/* &&
- !dcacheInterface->isBlocked()*/; }
+ !storeQueue.back().completed &&
+ !isStoreBlocked; }
void switchOut();
bool switchedOut;
private:
+ /** Writes back the instruction, sending it to IEW. */
+ void writeback(DynInstPtr &inst, PacketPtr pkt);
+
+ /** Handles completing the send of a store to memory. */
+ void storePostSend(PacketPtr pkt, DynInstPtr &inst);
+
/** Completes the store at the specified index. */
- void completeStore(int store_idx);
+ void completeStore(DynInstPtr &inst);
+
+ void removeStore(int store_idx);
+
+ /** Handles doing the retry. */
+ void recvRetry();
private:
/** Pointer to the CPU. */
- FullCPU *cpu;
+ OzoneCPU *cpu;
/** Pointer to the back-end stage. */
BackEnd *be;
- MemObject *mem;
-
class DcachePort : public Port
{
protected:
- FullCPU *cpu;
+ OzoneLWLSQ *lsq;
public:
- DcachePort(const std::string &_name, FullCPU *_cpu)
- : Port(_name), cpu(_cpu)
+ DcachePort(OzoneLWLSQ *_lsq)
+ : lsq(_lsq)
{ }
protected:
virtual void recvStatusChange(Status status);
virtual void getDeviceAddressRanges(AddrRangeList &resp,
- AddrRangeList &snoop)
- { resp.clear(); snoop.clear(); }
+ bool &snoop)
+ { resp.clear(); snoop = true; }
virtual bool recvTiming(PacketPtr pkt);
virtual void recvRetry();
};
- /** Pointer to the D-cache. */
+ /** D-cache port. */
DcachePort dcachePort;
- /** Pointer to the page table. */
-// PageTable *pTable;
-
public:
struct SQEntry {
/** Constructs an empty store queue entry. */
typename std::list<DynInstPtr>::iterator lqIt;
};
+ /** Derived class to hold any sender state the LSQ needs. */
+ class LSQSenderState : public Packet::SenderState
+ {
+ public:
+ /** Default constructor. */
+ LSQSenderState()
+ : noWB(false)
+ { }
+
+ /** Instruction who initiated the access to memory. */
+ DynInstPtr inst;
+ /** Whether or not it is a load. */
+ bool isLoad;
+ /** The LQ/SQ index of the instruction. */
+ int idx;
+ /** Whether or not the instruction will need to writeback. */
+ bool noWB;
+ };
+
+ /** Writeback event, specifically for when stores forward data to loads. */
+ class WritebackEvent : public Event {
+ public:
+ /** Constructs a writeback event. */
+ WritebackEvent(DynInstPtr &_inst, PacketPtr pkt, OzoneLWLSQ *lsq_ptr);
+
+ /** Processes the writeback event. */
+ void process();
+
+ /** Returns the description of this event. */
+ const char *description();
+
+ private:
+ /** Instruction whose results are being written back. */
+ DynInstPtr inst;
+
+ /** The packet that would have been sent to memory. */
+ PacketPtr pkt;
+
+ /** The pointer to the LSQ unit that issued the store. */
+ OzoneLWLSQ<Impl> *lsqPtr;
+ };
+
enum Status {
Running,
Idle,
int storesToWB;
+ public:
+ int storesInFlight;
+
+ private:
/// @todo Consider moving to a more advanced model with write vs read ports
/** The number of cache ports available each cycle. */
int cachePorts;
//list<InstSeqNum> mshrSeqNums;
+ /** Tota number of memory ordering violations. */
+ Stats::Scalar<> lsqMemOrderViolation;
+
//Stats::Scalar<> dcacheStallCycles;
Counter lastDcacheStall;
/** The index of the above store. */
LQIt stallingLoad;
+ /** The packet that needs to be retried. */
+ PacketPtr retryPkt;
+
+ /** Whehter or not a store is blocked due to the memory system. */
+ bool isStoreBlocked;
+
/** Whether or not a load is blocked due to the memory system. It is
* cleared when this value is checked via loadBlocked().
*/
// at the head of the LSQ and are ready to commit (at the head of the ROB
// too).
// @todo: Fix uncached accesses.
- if (req->getFlags() & UNCACHEABLE &&
- (inst != loadQueue.back() || !inst->reachedCommit)) {
+ if (req->isUncacheable() &&
+ (inst != loadQueue.back() || !inst->isAtCommit())) {
DPRINTF(OzoneLSQ, "[sn:%lli] Uncached load and not head of "
"commit/LSQ!\n",
inst->seqNum);
store_size = (*sq_it).size;
- if (store_size == 0) {
+ if (store_size == 0 || (*sq_it).committed) {
sq_it++;
continue;
}
DPRINTF(OzoneLSQ, "Forwarding from store [sn:%lli] to load to "
"[sn:%lli] addr %#x, data %#x\n",
- (*sq_it).inst->seqNum, inst->seqNum, req->vaddr, *(inst->memData));
-/*
- typename BackEnd::LdWritebackEvent *wb =
- new typename BackEnd::LdWritebackEvent(inst,
- be);
+ (*sq_it).inst->seqNum, inst->seqNum, req->getVaddr(),
+ *(inst->memData));
+
+ PacketPtr data_pkt = new Packet(req, Packet::ReadReq, Packet::Broadcast);
+ data_pkt->dataStatic(inst->memData);
+
+ WritebackEvent *wb = new WritebackEvent(inst, data_pkt, this);
// We'll say this has a 1 cycle load-store forwarding latency
// for now.
- // FIXME - Need to make this a parameter.
+ // @todo: Need to make this a parameter.
wb->schedule(curTick);
-*/
+
// Should keep track of stat for forwarded data
return NoFault;
} else if ((store_has_lower_limit && lower_load_has_store_part) ||
DPRINTF(OzoneLSQ, "Load-store forwarding mis-match. "
"Store [sn:%lli] to load addr %#x\n",
- (*sq_it).inst->seqNum, req->vaddr);
+ (*sq_it).inst->seqNum, req->getVaddr());
return NoFault;
}
DPRINTF(OzoneLSQ, "Doing timing access for inst PC %#x\n",
inst->readPC());
- PacketPtr data_pkt = new Packet(req, Packet::ReadReq, Packet::Broadcast);
+ PacketPtr data_pkt =
+ new Packet(req,
+ (req->isLocked() ?
+ MemCmd::LoadLockedReq : Packet::ReadReq),
+ Packet::Broadcast);
data_pkt->dataStatic(inst->memData);
+ LSQSenderState *state = new LSQSenderState;
+ state->isLoad = true;
+ state->idx = load_idx;
+ state->inst = inst;
+ data_pkt->senderState = state;
+
// if we have a cache, do cache access too
if (!dcachePort.sendTiming(data_pkt)) {
// There's an older load that's already going to squash.
return NoFault;
}
- if (data_pkt->result != Packet::Success) {
- DPRINTF(OzoneLSQ, "OzoneLSQ: D-cache miss!\n");
- DPRINTF(Activity, "Activity: ld accessing mem miss [sn:%lli]\n",
- inst->seqNum);
- } else {
- DPRINTF(OzoneLSQ, "OzoneLSQ: D-cache hit!\n");
- DPRINTF(Activity, "Activity: ld accessing mem hit [sn:%lli]\n",
- inst->seqNum);
+ if (req->isLocked()) {
+ cpu->lockFlag = true;
}
return NoFault;