#ifndef __CPU_OZONE_LW_LSQ_HH__
#define __CPU_OZONE_LW_LSQ_HH__
+#include <algorithm>
#include <list>
#include <map>
#include <queue>
-#include <algorithm>
#include "arch/faults.hh"
-#include "arch/isa_traits.hh"
-#include "config/full_system.hh"
+#include "arch/types.hh"
+#include "base/fast_alloc.hh"
#include "base/hashmap.hh"
+#include "config/full_system.hh"
+#include "config/the_isa.hh"
#include "cpu/inst_seq.hh"
#include "mem/packet.hh"
#include "mem/port.hh"
/** Returns the name of the LSQ unit. */
std::string name() const;
+ void regStats();
+
/** Sets the CPU pointer. */
void setCPU(OzoneCPU *cpu_ptr);
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.
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();
void writeback(DynInstPtr &inst, PacketPtr pkt);
/** Handles completing the send of a store to memory. */
- void storePostSend(Packet *pkt, DynInstPtr &inst);
+ 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();
/** Pointer to the back-end stage. */
BackEnd *be;
- MemObject *mem;
-
class DcachePort : public Port
{
protected:
- OzoneCPU *cpu;
-
OzoneLWLSQ *lsq;
public:
- DcachePort(OzoneCPU *_cpu, OzoneLWLSQ *_lsq)
- : Port(_lsq->name() + "-dport"), cpu(_cpu), lsq(_lsq)
+ 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. */
- DcachePort *dcachePort;
-
- /** Pointer to the page table. */
-// PageTable *pTable;
+ /** D-cache port. */
+ DcachePort dcachePort;
public:
struct SQEntry {
};
/** Derived class to hold any sender state the LSQ needs. */
- class LSQSenderState : public Packet::SenderState
+ class LSQSenderState : public Packet::SenderState, public FastAlloc
{
public:
/** Default constructor. */
void process();
/** Returns the description of this event. */
- const char *description();
+ const char *description() const;
private:
/** Instruction whose results are being written back. */
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;
- //Stats::Scalar<> dcacheStallCycles;
+ /** Tota number of memory ordering violations. */
+ Stats::Scalar lsqMemOrderViolation;
+
+ //Stats::Scalar dcacheStallCycles;
Counter lastDcacheStall;
// Make these per thread?
// 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 &&
+ if (req->isUncacheable() &&
(inst != loadQueue.back() || !inst->isAtCommit())) {
DPRINTF(OzoneLSQ, "[sn:%lli] Uncached load and not head of "
"commit/LSQ!\n",
store_size = (*sq_it).size;
- if (store_size == 0) {
+ if (store_size == 0 || (*sq_it).committed) {
sq_it++;
continue;
}
// We'll say this has a 1 cycle load-store forwarding latency
// for now.
// @todo: Need to make this a parameter.
- wb->schedule(curTick);
+ wb->schedule(curTick());
// Should keep track of stat for forwarded data
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->isLLSC() ?
+ MemCmd::LoadLockedReq : Packet::ReadReq),
+ Packet::Broadcast);
data_pkt->dataStatic(inst->memData);
LSQSenderState *state = new LSQSenderState;
data_pkt->senderState = state;
// if we have a cache, do cache access too
- if (!dcachePort->sendTiming(data_pkt)) {
+ if (!dcachePort.sendTiming(data_pkt)) {
// There's an older load that's already going to squash.
if (isLoadBlocked && blockedLoadSeqNum < inst->seqNum)
return NoFault;
return NoFault;
}
- if (req->getFlags() & LOCKED) {
+ if (req->isLLSC()) {
cpu->lockFlag = true;
}
- 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);
- }
-
return NoFault;
}