gem5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
lsq_impl.hh
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011-2012, 2014 ARM Limited
3  * Copyright (c) 2013 Advanced Micro Devices, Inc.
4  * All rights reserved
5  *
6  * The license below extends only to copyright in the software and shall
7  * not be construed as granting a license to any other intellectual
8  * property including but not limited to intellectual property relating
9  * to a hardware implementation of the functionality of the software
10  * licensed hereunder. You may use the software subject to the license
11  * terms below provided that you ensure that this notice is replicated
12  * unmodified and in its entirety in all distributions of the software,
13  * modified or unmodified, in source code or in binary form.
14  *
15  * Copyright (c) 2005-2006 The Regents of The University of Michigan
16  * All rights reserved.
17  *
18  * Redistribution and use in source and binary forms, with or without
19  * modification, are permitted provided that the following conditions are
20  * met: redistributions of source code must retain the above copyright
21  * notice, this list of conditions and the following disclaimer;
22  * redistributions in binary form must reproduce the above copyright
23  * notice, this list of conditions and the following disclaimer in the
24  * documentation and/or other materials provided with the distribution;
25  * neither the name of the copyright holders nor the names of its
26  * contributors may be used to endorse or promote products derived from
27  * this software without specific prior written permission.
28  *
29  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40  *
41  * Authors: Korey Sewell
42  */
43 
44 #ifndef __CPU_O3_LSQ_IMPL_HH__
45 #define __CPU_O3_LSQ_IMPL_HH__
46 
47 #include <algorithm>
48 #include <list>
49 #include <string>
50 
51 #include "cpu/o3/lsq.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"
57 
58 using namespace std;
59 
60 template <class Impl>
61 LSQ<Impl>::LSQ(O3CPU *cpu_ptr, IEW *iew_ptr, DerivO3CPUParams *params)
62  : cpu(cpu_ptr), iewStage(iew_ptr),
63  LQEntries(params->LQEntries),
64  SQEntries(params->SQEntries),
65  numThreads(params->numThreads)
66 {
67  assert(numThreads > 0 && numThreads <= Impl::MaxThreads);
68 
69  //**********************************************/
70  //************ Handle SMT Parameters ***********/
71  //**********************************************/
72  std::string policy = params->smtLSQPolicy;
73 
74  //Convert string to lowercase
75  std::transform(policy.begin(), policy.end(), policy.begin(),
76  (int(*)(int)) tolower);
77 
78  //Figure out fetch policy
79  if (policy == "dynamic") {
81 
84 
85  DPRINTF(LSQ, "LSQ sharing policy set to Dynamic\n");
86  } else if (policy == "partitioned") {
88 
89  //@todo:make work if part_amt doesnt divide evenly.
92 
93  DPRINTF(Fetch, "LSQ sharing policy set to Partitioned: "
94  "%i entries per LQ | %i entries per SQ\n",
96  } else if (policy == "threshold") {
98 
99  assert(params->smtLSQThreshold > LQEntries);
100  assert(params->smtLSQThreshold > SQEntries);
101 
102  //Divide up by threshold amount
103  //@todo: Should threads check the max and the total
104  //amount of the LSQ
105  maxLQEntries = params->smtLSQThreshold;
106  maxSQEntries = params->smtLSQThreshold;
107 
108  DPRINTF(LSQ, "LSQ sharing policy set to Threshold: "
109  "%i entries per LQ | %i entries per SQ\n",
111  } else {
112  assert(0 && "Invalid LSQ Sharing Policy.Options Are:{Dynamic,"
113  "Partitioned, Threshold}");
114  }
115 
116  //Initialize LSQs
117  thread = new LSQUnit[numThreads];
118  for (ThreadID tid = 0; tid < numThreads; tid++) {
119  thread[tid].init(cpu, iew_ptr, params, this,
120  maxLQEntries, maxSQEntries, tid);
121  thread[tid].setDcachePort(&cpu_ptr->getDataPort());
122  }
123 }
124 
125 
126 template<class Impl>
127 std::string
129 {
130  return iewStage->name() + ".lsq";
131 }
132 
133 template<class Impl>
134 void
136 {
137  //Initialize LSQs
138  for (ThreadID tid = 0; tid < numThreads; tid++) {
139  thread[tid].regStats();
140  }
141 }
142 
143 template<class Impl>
144 void
146 {
147  activeThreads = at_ptr;
148  assert(activeThreads != 0);
149 }
150 
151 template <class Impl>
152 void
154 {
155  assert(isDrained());
156 
157  for (ThreadID tid = 0; tid < numThreads; tid++)
158  thread[tid].drainSanityCheck();
159 }
160 
161 template <class Impl>
162 bool
164 {
165  bool drained(true);
166 
167  if (!lqEmpty()) {
168  DPRINTF(Drain, "Not drained, LQ not empty.\n");
169  drained = false;
170  }
171 
172  if (!sqEmpty()) {
173  DPRINTF(Drain, "Not drained, SQ not empty.\n");
174  drained = false;
175  }
176 
177  return drained;
178 }
179 
180 template <class Impl>
181 void
183 {
184  for (ThreadID tid = 0; tid < numThreads; tid++) {
185  thread[tid].takeOverFrom();
186  }
187 }
188 
189 template <class Impl>
190 int
192 {
193  if (lsqPolicy == Partitioned) {
194  return LQEntries / num_threads;
195  } else {
196  return 0;
197  }
198 }
199 
200 template <class Impl>
201 void
203 {
204  if (lsqPolicy != Dynamic || numThreads > 1) {
205  int active_threads = activeThreads->size();
206 
207  int maxEntries;
208 
209  if (lsqPolicy == Partitioned) {
210  maxEntries = LQEntries / active_threads;
211  } else if (lsqPolicy == Threshold && active_threads == 1) {
212  maxEntries = LQEntries;
213  } else {
214  maxEntries = LQEntries;
215  }
216 
217  list<ThreadID>::iterator threads = activeThreads->begin();
218  list<ThreadID>::iterator end = activeThreads->end();
219 
220  while (threads != end) {
221  ThreadID tid = *threads++;
222 
223  resizeEntries(maxEntries, tid);
224  }
225  }
226 }
227 
228 template<class Impl>
229 void
231 {
232  thread[tid].clearLQ();
233  thread[tid].clearSQ();
234 }
235 
236 template<class Impl>
237 void
239 {
240  thread[tid].resizeLQ(size);
241  thread[tid].resizeSQ(size);
242 }
243 
244 template<class Impl>
245 void
247 {
248  list<ThreadID>::iterator threads = activeThreads->begin();
249  list<ThreadID>::iterator end = activeThreads->end();
250 
251  while (threads != end) {
252  ThreadID tid = *threads++;
253 
254  thread[tid].tick();
255  }
256 }
257 
258 template<class Impl>
259 void
261 {
262  ThreadID tid = load_inst->threadNumber;
263 
264  thread[tid].insertLoad(load_inst);
265 }
266 
267 template<class Impl>
268 void
270 {
271  ThreadID tid = store_inst->threadNumber;
272 
273  thread[tid].insertStore(store_inst);
274 }
275 
276 template<class Impl>
277 Fault
279 {
280  ThreadID tid = inst->threadNumber;
281 
282  return thread[tid].executeLoad(inst);
283 }
284 
285 template<class Impl>
286 Fault
288 {
289  ThreadID tid = inst->threadNumber;
290 
291  return thread[tid].executeStore(inst);
292 }
293 
294 template<class Impl>
295 void
297 {
298  list<ThreadID>::iterator threads = activeThreads->begin();
299  list<ThreadID>::iterator end = activeThreads->end();
300 
301  while (threads != end) {
302  ThreadID tid = *threads++;
303 
304  if (numStoresToWB(tid) > 0) {
305  DPRINTF(Writeback,"[tid:%i] Writing back stores. %i stores "
306  "available for Writeback.\n", tid, numStoresToWB(tid));
307  }
308 
309  thread[tid].writebackStores();
310  }
311 }
312 
313 template<class Impl>
314 bool
316 {
317  /* Answers: Does Anybody Have a Violation?*/
318  list<ThreadID>::iterator threads = activeThreads->begin();
319  list<ThreadID>::iterator end = activeThreads->end();
320 
321  while (threads != end) {
322  ThreadID tid = *threads++;
323 
324  if (thread[tid].violation())
325  return true;
326  }
327 
328  return false;
329 }
330 
331 template <class Impl>
332 void
334 {
335  iewStage->cacheUnblocked();
336 
337  for (ThreadID tid : *activeThreads) {
338  thread[tid].recvRetry();
339  }
340 }
341 
342 template <class Impl>
343 bool
345 {
346  if (pkt->isError())
347  DPRINTF(LSQ, "Got error packet back for address: %#X\n",
348  pkt->getAddr());
349 
350  thread[cpu->contextToThread(pkt->req->contextId())]
351  .completeDataAccess(pkt);
352 
353  if (pkt->isInvalidate()) {
354  // This response also contains an invalidate; e.g. this can be the case
355  // if cmd is ReadRespWithInvalidate.
356  //
357  // The calling order between completeDataAccess and checkSnoop matters.
358  // By calling checkSnoop after completeDataAccess, we ensure that the
359  // fault set by checkSnoop is not lost. Calling writeback (more
360  // specifically inst->completeAcc) in completeDataAccess overwrites
361  // fault, and in case this instruction requires squashing (as
362  // determined by checkSnoop), the ReExec fault set by checkSnoop would
363  // be lost otherwise.
364 
365  DPRINTF(LSQ, "received invalidation with response for addr:%#x\n",
366  pkt->getAddr());
367 
368  for (ThreadID tid = 0; tid < numThreads; tid++) {
369  thread[tid].checkSnoop(pkt);
370  }
371  }
372 
373  delete pkt->req;
374  delete pkt;
375  return true;
376 }
377 
378 template <class Impl>
379 void
381 {
382  DPRINTF(LSQ, "received pkt for addr:%#x %s\n", pkt->getAddr(),
383  pkt->cmdString());
384 
385  // must be a snoop
386  if (pkt->isInvalidate()) {
387  DPRINTF(LSQ, "received invalidation for addr:%#x\n",
388  pkt->getAddr());
389  for (ThreadID tid = 0; tid < numThreads; tid++) {
390  thread[tid].checkSnoop(pkt);
391  }
392  }
393 }
394 
395 template<class Impl>
396 int
398 {
399  unsigned total = 0;
400 
401  list<ThreadID>::iterator threads = activeThreads->begin();
402  list<ThreadID>::iterator end = activeThreads->end();
403 
404  while (threads != end) {
405  ThreadID tid = *threads++;
406 
407  total += getCount(tid);
408  }
409 
410  return total;
411 }
412 
413 template<class Impl>
414 int
416 {
417  unsigned total = 0;
418 
419  list<ThreadID>::iterator threads = activeThreads->begin();
420  list<ThreadID>::iterator end = activeThreads->end();
421 
422  while (threads != end) {
423  ThreadID tid = *threads++;
424 
425  total += numLoads(tid);
426  }
427 
428  return total;
429 }
430 
431 template<class Impl>
432 int
434 {
435  unsigned total = 0;
436 
437  list<ThreadID>::iterator threads = activeThreads->begin();
438  list<ThreadID>::iterator end = activeThreads->end();
439 
440  while (threads != end) {
441  ThreadID tid = *threads++;
442 
443  total += thread[tid].numStores();
444  }
445 
446  return total;
447 }
448 
449 template<class Impl>
450 unsigned
452 {
453  unsigned total = 0;
454 
455  list<ThreadID>::iterator threads = activeThreads->begin();
456  list<ThreadID>::iterator end = activeThreads->end();
457 
458  while (threads != end) {
459  ThreadID tid = *threads++;
460 
461  total += thread[tid].numFreeLoadEntries();
462  }
463 
464  return total;
465 }
466 
467 template<class Impl>
468 unsigned
470 {
471  unsigned total = 0;
472 
473  list<ThreadID>::iterator threads = activeThreads->begin();
474  list<ThreadID>::iterator end = activeThreads->end();
475 
476  while (threads != end) {
477  ThreadID tid = *threads++;
478 
479  total += thread[tid].numFreeStoreEntries();
480  }
481 
482  return total;
483 }
484 
485 template<class Impl>
486 unsigned
488 {
489  return thread[tid].numFreeLoadEntries();
490 }
491 
492 template<class Impl>
493 unsigned
495 {
496  return thread[tid].numFreeStoreEntries();
497 }
498 
499 template<class Impl>
500 bool
502 {
503  list<ThreadID>::iterator threads = activeThreads->begin();
504  list<ThreadID>::iterator end = activeThreads->end();
505 
506  while (threads != end) {
507  ThreadID tid = *threads++;
508 
509  if (!(thread[tid].lqFull() || thread[tid].sqFull()))
510  return false;
511  }
512 
513  return true;
514 }
515 
516 template<class Impl>
517 bool
519 {
520  //@todo: Change to Calculate All Entries for
521  //Dynamic Policy
522  if (lsqPolicy == Dynamic)
523  return isFull();
524  else
525  return thread[tid].lqFull() || thread[tid].sqFull();
526 }
527 
528 template<class Impl>
529 bool
531 {
532  return lqEmpty() && sqEmpty();
533 }
534 
535 template<class Impl>
536 bool
538 {
539  list<ThreadID>::const_iterator threads = activeThreads->begin();
540  list<ThreadID>::const_iterator end = activeThreads->end();
541 
542  while (threads != end) {
543  ThreadID tid = *threads++;
544 
545  if (!thread[tid].lqEmpty())
546  return false;
547  }
548 
549  return true;
550 }
551 
552 template<class Impl>
553 bool
555 {
556  list<ThreadID>::const_iterator threads = activeThreads->begin();
557  list<ThreadID>::const_iterator end = activeThreads->end();
558 
559  while (threads != end) {
560  ThreadID tid = *threads++;
561 
562  if (!thread[tid].sqEmpty())
563  return false;
564  }
565 
566  return true;
567 }
568 
569 template<class Impl>
570 bool
572 {
573  list<ThreadID>::iterator threads = activeThreads->begin();
574  list<ThreadID>::iterator end = activeThreads->end();
575 
576  while (threads != end) {
577  ThreadID tid = *threads++;
578 
579  if (!thread[tid].lqFull())
580  return false;
581  }
582 
583  return true;
584 }
585 
586 template<class Impl>
587 bool
589 {
590  //@todo: Change to Calculate All Entries for
591  //Dynamic Policy
592  if (lsqPolicy == Dynamic)
593  return lqFull();
594  else
595  return thread[tid].lqFull();
596 }
597 
598 template<class Impl>
599 bool
601 {
602  list<ThreadID>::iterator threads = activeThreads->begin();
603  list<ThreadID>::iterator end = activeThreads->end();
604 
605  while (threads != end) {
606  ThreadID tid = *threads++;
607 
608  if (!sqFull(tid))
609  return false;
610  }
611 
612  return true;
613 }
614 
615 template<class Impl>
616 bool
618 {
619  //@todo: Change to Calculate All Entries for
620  //Dynamic Policy
621  if (lsqPolicy == Dynamic)
622  return sqFull();
623  else
624  return thread[tid].sqFull();
625 }
626 
627 template<class Impl>
628 bool
630 {
631  list<ThreadID>::iterator threads = activeThreads->begin();
632  list<ThreadID>::iterator end = activeThreads->end();
633 
634  while (threads != end) {
635  ThreadID tid = *threads++;
636 
637  if (!thread[tid].isStalled())
638  return false;
639  }
640 
641  return true;
642 }
643 
644 template<class Impl>
645 bool
647 {
648  if (lsqPolicy == Dynamic)
649  return isStalled();
650  else
651  return thread[tid].isStalled();
652 }
653 
654 template<class Impl>
655 bool
657 {
658  list<ThreadID>::iterator threads = activeThreads->begin();
659  list<ThreadID>::iterator end = activeThreads->end();
660 
661  while (threads != end) {
662  ThreadID tid = *threads++;
663 
664  if (hasStoresToWB(tid))
665  return true;
666  }
667 
668  return false;
669 }
670 
671 template<class Impl>
672 bool
674 {
675  list<ThreadID>::iterator threads = activeThreads->begin();
676  list<ThreadID>::iterator end = activeThreads->end();
677 
678  while (threads != end) {
679  ThreadID tid = *threads++;
680 
681  if (willWB(tid))
682  return true;
683  }
684 
685  return false;
686 }
687 
688 template<class Impl>
689 void
691 {
692  list<ThreadID>::const_iterator threads = activeThreads->begin();
693  list<ThreadID>::const_iterator end = activeThreads->end();
694 
695  while (threads != end) {
696  ThreadID tid = *threads++;
697 
698  thread[tid].dumpInsts();
699  }
700 }
701 
702 #endif//__CPU_O3_LSQ_IMPL_HH__
#define DPRINTF(x,...)
Definition: trace.hh:212
unsigned SQEntries
Total Size of SQ Entries.
Definition: lsq.hh:320
void takeOverFrom()
Takes over execution from another CPU's thread.
Definition: lsq_impl.hh:182
void resetEntries()
Reset the max entries for each thread.
Definition: lsq_impl.hh:202
ThreadID numThreads
Number of Threads.
Definition: lsq.hh:329
Impl::DynInstPtr DynInstPtr
Definition: lsq.hh:61
unsigned LQEntries
Total Size of LQ Entries.
Definition: lsq.hh:318
bool willWB()
Returns if the LSQ will write back to memory this cycle.
Definition: lsq_impl.hh:673
ContextID contextId() const
Accessor function for context ID.
Definition: request.hh:694
unsigned maxSQEntries
Max SQ Size - Used to Enforce Sharing Policies.
Definition: lsq.hh:326
void dumpInsts() const
Debugging function to print out all instructions.
Definition: lsq_impl.hh:690
void removeEntries(ThreadID tid)
Definition: lsq_impl.hh:230
void tick()
Ticks the LSQ.
Definition: lsq_impl.hh:246
bool sqFull()
Returns if any of the SQs are full.
Definition: lsq_impl.hh:600
std::string name() const
Returns the name of the LSQ.
Definition: lsq_impl.hh:128
bool violation()
Returns whether or not there was a memory ordering violation.
Definition: lsq_impl.hh:315
bool hasStoresToWB()
Returns whether or not there are any stores to write back to memory.
Definition: lsq_impl.hh:656
Fault executeLoad(DynInstPtr &inst)
Executes a load.
Definition: lsq_impl.hh:278
bool isFull()
Returns if the LSQ is full (either LQ or SQ is full).
Definition: lsq_impl.hh:501
Definition: lsq.hh:58
void writebackStores()
Attempts to write back stores until all cache ports are used or the interface becomes blocked...
Definition: lsq_impl.hh:296
void drainSanityCheck() const
Perform sanity checks after a drain.
Definition: lsq_impl.hh:153
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.
Definition: lsq_impl.hh:469
void insertStore(DynInstPtr &store_inst)
Inserts a store into the LSQ.
Definition: lsq_impl.hh:269
void resizeEntries(unsigned size, ThreadID tid)
Resize the max entries for a thread.
Definition: lsq_impl.hh:238
int numLoads()
Returns the total number of loads in the load queue.
Definition: lsq_impl.hh:415
void insertLoad(DynInstPtr &load_inst)
Inserts a load into the LSQ.
Definition: lsq_impl.hh:260
Fault executeStore(DynInstPtr &inst)
Executes a store.
Definition: lsq_impl.hh:287
unsigned maxLQEntries
Max LQ Size - Used to Enforce Sharing Policies.
Definition: lsq.hh:323
const RequestPtr req
A pointer to the original request.
Definition: packet.hh:304
void setDcachePort(MasterPort *dcache_port)
Sets the pointer to the dcache port.
LSQUnit * thread
The LSQ units for individual threads.
Definition: lsq.hh:312
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
Definition: packet.hh:245
const FlagsType total
Print the total.
Definition: info.hh:49
int getCount()
Returns the number of instructions in all of the queues.
Definition: lsq_impl.hh:397
int16_t ThreadID
Thread index/ID type.
Definition: types.hh:171
Impl::O3CPU O3CPU
Definition: lsq.hh:60
int size()
Definition: pagetable.hh:146
unsigned numFreeLoadEntries()
Returns the number of free load entries.
Definition: lsq_impl.hh:451
int entryAmount(ThreadID num_threads)
Number of entries needed for the given amount of threads.
Definition: lsq_impl.hh:191
bool isError() const
Definition: packet.hh:528
void recvReqRetry()
Retry the previous send that failed.
Definition: lsq_impl.hh:333
LSQPolicy lsqPolicy
The LSQ policy for SMT mode.
Definition: lsq.hh:309
const std::string & cmdString() const
Return the string name of the cmd field (for debugging and tracing).
Definition: packet.hh:497
void setActiveThreads(std::list< ThreadID > *at_ptr)
Sets the pointer to the list of active threads.
Definition: lsq_impl.hh:145
bool isEmpty() const
Returns if the LSQ is empty (both LQ and SQ are empty).
Definition: lsq_impl.hh:530
bool sqEmpty() const
Returns if all of the SQs are empty.
Definition: lsq_impl.hh:554
LSQ(O3CPU *cpu_ptr, IEW *iew_ptr, DerivO3CPUParams *params)
Constructs an LSQ with the given parameters.
Definition: lsq_impl.hh:61
int numStores()
Returns the total number of stores in the store queue.
Definition: lsq_impl.hh:433
bool isDrained() const
Has the LSQ drained?
Definition: lsq_impl.hh:163
void regStats()
Registers statistics of each LSQ unit.
Definition: lsq_impl.hh:135
bool recvTimingResp(PacketPtr pkt)
Handles writing back and completing the load or store that has returned from memory.
Definition: lsq_impl.hh:344
bool isInvalidate() const
Definition: packet.hh:517
Impl::CPUPol::IEW IEW
Definition: lsq.hh:62
Class that implements the actual LQ and SQ for each specific thread.
Definition: lsq_unit.hh:79
O3CPU * cpu
The CPU pointer.
Definition: lsq.hh:302
bool lqEmpty() const
Returns if all of the LQs are empty.
Definition: lsq_impl.hh:537
bool isStalled()
Returns if the LSQ is stalled due to a memory operation that must be replayed.
Definition: lsq_impl.hh:629
void recvTimingSnoopReq(PacketPtr pkt)
Definition: lsq_impl.hh:380
std::shared_ptr< FaultBase > Fault
Definition: types.hh:184
Addr getAddr() const
Definition: packet.hh:639
bool lqFull()
Returns if any of the LQs are full.
Definition: lsq_impl.hh:571

Generated on Fri Jun 9 2017 13:03:43 for gem5 by doxygen 1.8.6