44 #ifndef __CPU_O3_LSQ_IMPL_HH__
45 #define __CPU_O3_LSQ_IMPL_HH__
52 #include "debug/Drain.hh"
53 #include "debug/Fetch.hh"
54 #include "debug/LSQ.hh"
55 #include "debug/Writeback.hh"
56 #include "params/DerivO3CPU.hh"
62 : cpu(cpu_ptr), iewStage(iew_ptr),
63 LQEntries(params->LQEntries),
64 SQEntries(params->SQEntries),
65 numThreads(params->numThreads)
72 std::string policy = params->smtLSQPolicy;
75 std::transform(policy.begin(), policy.end(), policy.begin(),
76 (int(*)(int)) tolower);
79 if (policy ==
"dynamic") {
85 DPRINTF(
LSQ,
"LSQ sharing policy set to Dynamic\n");
86 }
else if (policy ==
"partitioned") {
93 DPRINTF(Fetch,
"LSQ sharing policy set to Partitioned: "
94 "%i entries per LQ | %i entries per SQ\n",
96 }
else if (policy ==
"threshold") {
99 assert(params->smtLSQThreshold >
LQEntries);
100 assert(params->smtLSQThreshold >
SQEntries);
108 DPRINTF(
LSQ,
"LSQ sharing policy set to Threshold: "
109 "%i entries per LQ | %i entries per SQ\n",
112 assert(0 &&
"Invalid LSQ Sharing Policy.Options Are:{Dynamic,"
113 "Partitioned, Threshold}");
130 return iewStage->name() +
".lsq";
138 for (
ThreadID tid = 0; tid < numThreads; tid++) {
139 thread[tid].regStats();
147 activeThreads = at_ptr;
148 assert(activeThreads != 0);
151 template <
class Impl>
157 for (
ThreadID tid = 0; tid < numThreads; tid++)
158 thread[tid].drainSanityCheck();
161 template <
class Impl>
168 DPRINTF(Drain,
"Not drained, LQ not empty.\n");
173 DPRINTF(Drain,
"Not drained, SQ not empty.\n");
180 template <
class Impl>
184 for (
ThreadID tid = 0; tid < numThreads; tid++) {
185 thread[tid].takeOverFrom();
189 template <
class Impl>
193 if (lsqPolicy == Partitioned) {
194 return LQEntries / num_threads;
200 template <
class Impl>
204 if (lsqPolicy != Dynamic || numThreads > 1) {
205 int active_threads = activeThreads->size();
209 if (lsqPolicy == Partitioned) {
210 maxEntries = LQEntries / active_threads;
211 }
else if (lsqPolicy == Threshold && active_threads == 1) {
212 maxEntries = LQEntries;
214 maxEntries = LQEntries;
220 while (threads != end) {
223 resizeEntries(maxEntries, tid);
232 thread[tid].clearLQ();
233 thread[tid].clearSQ();
240 thread[tid].resizeLQ(size);
241 thread[tid].resizeSQ(size);
251 while (threads != end) {
262 ThreadID tid = load_inst->threadNumber;
264 thread[tid].insertLoad(load_inst);
271 ThreadID tid = store_inst->threadNumber;
273 thread[tid].insertStore(store_inst);
282 return thread[tid].executeLoad(inst);
291 return thread[tid].executeStore(inst);
301 while (threads != end) {
304 if (numStoresToWB(tid) > 0) {
305 DPRINTF(Writeback,
"[tid:%i] Writing back stores. %i stores "
306 "available for Writeback.\n", tid, numStoresToWB(tid));
309 thread[tid].writebackStores();
321 while (threads != end) {
324 if (thread[tid].violation())
331 template <
class Impl>
335 iewStage->cacheUnblocked();
337 for (
ThreadID tid : *activeThreads) {
338 thread[tid].recvRetry();
342 template <
class Impl>
347 DPRINTF(
LSQ,
"Got error packet back for address: %#X\n",
351 .completeDataAccess(pkt);
365 DPRINTF(
LSQ,
"received invalidation with response for addr:%#x\n",
368 for (
ThreadID tid = 0; tid < numThreads; tid++) {
369 thread[tid].checkSnoop(pkt);
378 template <
class Impl>
387 DPRINTF(
LSQ,
"received invalidation for addr:%#x\n",
389 for (
ThreadID tid = 0; tid < numThreads; tid++) {
390 thread[tid].checkSnoop(pkt);
404 while (threads != end) {
407 total += getCount(tid);
422 while (threads != end) {
425 total += numLoads(tid);
440 while (threads != end) {
443 total += thread[tid].numStores();
458 while (threads != end) {
461 total += thread[tid].numFreeLoadEntries();
476 while (threads != end) {
479 total += thread[tid].numFreeStoreEntries();
489 return thread[tid].numFreeLoadEntries();
496 return thread[tid].numFreeStoreEntries();
506 while (threads != end) {
509 if (!(thread[tid].lqFull() || thread[tid].sqFull()))
522 if (lsqPolicy == Dynamic)
525 return thread[tid].lqFull() || thread[tid].sqFull();
532 return lqEmpty() && sqEmpty();
542 while (threads != end) {
545 if (!thread[tid].lqEmpty())
559 while (threads != end) {
562 if (!thread[tid].sqEmpty())
576 while (threads != end) {
579 if (!thread[tid].lqFull())
592 if (lsqPolicy == Dynamic)
595 return thread[tid].lqFull();
605 while (threads != end) {
621 if (lsqPolicy == Dynamic)
624 return thread[tid].sqFull();
634 while (threads != end) {
637 if (!thread[tid].isStalled())
648 if (lsqPolicy == Dynamic)
651 return thread[tid].isStalled();
661 while (threads != end) {
664 if (hasStoresToWB(tid))
678 while (threads != end) {
695 while (threads != end) {
698 thread[tid].dumpInsts();
702 #endif//__CPU_O3_LSQ_IMPL_HH__
unsigned SQEntries
Total Size of SQ Entries.
void takeOverFrom()
Takes over execution from another CPU's thread.
void resetEntries()
Reset the max entries for each thread.
ThreadID numThreads
Number of Threads.
Impl::DynInstPtr DynInstPtr
unsigned LQEntries
Total Size of LQ Entries.
bool willWB()
Returns if the LSQ will write back to memory this cycle.
ContextID contextId() const
Accessor function for context ID.
unsigned maxSQEntries
Max SQ Size - Used to Enforce Sharing Policies.
void dumpInsts() const
Debugging function to print out all instructions.
void removeEntries(ThreadID tid)
void tick()
Ticks the LSQ.
bool sqFull()
Returns if any of the SQs are full.
std::string name() const
Returns the name of the LSQ.
bool violation()
Returns whether or not there was a memory ordering violation.
bool hasStoresToWB()
Returns whether or not there are any stores to write back to memory.
Fault executeLoad(DynInstPtr &inst)
Executes a load.
bool isFull()
Returns if the LSQ is full (either LQ or SQ is full).
void writebackStores()
Attempts to write back stores until all cache ports are used or the interface becomes blocked...
void drainSanityCheck() const
Perform sanity checks after a drain.
void init(O3CPU *cpu_ptr, IEW *iew_ptr, DerivO3CPUParams *params, LSQ *lsq_ptr, unsigned maxLQEntries, unsigned maxSQEntries, unsigned id)
Initializes the LSQ unit with the specified number of entries.
unsigned numFreeStoreEntries()
Returns the number of free store entries.
void insertStore(DynInstPtr &store_inst)
Inserts a store into the LSQ.
void resizeEntries(unsigned size, ThreadID tid)
Resize the max entries for a thread.
int numLoads()
Returns the total number of loads in the load queue.
void insertLoad(DynInstPtr &load_inst)
Inserts a load into the LSQ.
Fault executeStore(DynInstPtr &inst)
Executes a store.
unsigned maxLQEntries
Max LQ Size - Used to Enforce Sharing Policies.
const RequestPtr req
A pointer to the original request.
void setDcachePort(MasterPort *dcache_port)
Sets the pointer to the dcache port.
LSQUnit * thread
The LSQ units for individual threads.
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
const FlagsType total
Print the total.
int getCount()
Returns the number of instructions in all of the queues.
int16_t ThreadID
Thread index/ID type.
unsigned numFreeLoadEntries()
Returns the number of free load entries.
int entryAmount(ThreadID num_threads)
Number of entries needed for the given amount of threads.
void recvReqRetry()
Retry the previous send that failed.
LSQPolicy lsqPolicy
The LSQ policy for SMT mode.
const std::string & cmdString() const
Return the string name of the cmd field (for debugging and tracing).
void setActiveThreads(std::list< ThreadID > *at_ptr)
Sets the pointer to the list of active threads.
bool isEmpty() const
Returns if the LSQ is empty (both LQ and SQ are empty).
bool sqEmpty() const
Returns if all of the SQs are empty.
LSQ(O3CPU *cpu_ptr, IEW *iew_ptr, DerivO3CPUParams *params)
Constructs an LSQ with the given parameters.
int numStores()
Returns the total number of stores in the store queue.
bool isDrained() const
Has the LSQ drained?
void regStats()
Registers statistics of each LSQ unit.
bool recvTimingResp(PacketPtr pkt)
Handles writing back and completing the load or store that has returned from memory.
bool isInvalidate() const
Class that implements the actual LQ and SQ for each specific thread.
O3CPU * cpu
The CPU pointer.
bool lqEmpty() const
Returns if all of the LQs are empty.
bool isStalled()
Returns if the LSQ is stalled due to a memory operation that must be replayed.
void recvTimingSnoopReq(PacketPtr pkt)
std::shared_ptr< FaultBase > Fault
bool lqFull()
Returns if any of the LQs are full.