2 * Copyright (c) 2005-2006 The Regents of The University of Michigan
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 * Authors: Korey Sewell
35 #include "cpu/o3/lsq.hh"
39 LSQ<Impl>::DcachePort::recvAtomic(PacketPtr pkt)
41 panic("O3CPU model does not work with atomic mode!");
47 LSQ<Impl>::DcachePort::recvFunctional(PacketPtr pkt)
49 DPRINTF(LSQ, "LSQ doesn't update things on a recvFunctional.");
54 LSQ<Impl>::DcachePort::recvStatusChange(Status status)
56 if (status == RangeChange) {
57 if (!snoopRangeSent) {
58 snoopRangeSent = true;
59 sendStatusChange(Port::RangeChange);
63 panic("O3CPU doesn't expect recvStatusChange callback!");
68 LSQ<Impl>::DcachePort::recvTiming(PacketPtr pkt)
70 if (pkt->isResponse()) {
71 lsq->thread[pkt->req->getThreadNum()].completeDataAccess(pkt);
74 //else it is a coherence request, maybe you need to do something
75 warn("Recieved a coherence request (Invalidate?), 03CPU doesn't"
76 "update LSQ for these\n");
83 LSQ<Impl>::DcachePort::recvRetry()
85 if (lsq->retryTid == -1)
87 //Squashed, so drop it
90 lsq->thread[lsq->retryTid].recvRetry();
91 // Speculatively clear the retry Tid. This will get set again if
92 // the LSQUnit was unable to complete its access.
97 LSQ<Impl>::LSQ(Params *params)
98 : dcachePort(this), LQEntries(params->LQEntries),
99 SQEntries(params->SQEntries), numThreads(params->numberOfThreads),
102 DPRINTF(LSQ, "Creating LSQ object.\n");
104 dcachePort.snoopRangeSent = false;
106 //**********************************************/
107 //************ Handle SMT Parameters ***********/
108 //**********************************************/
109 std::string policy = params->smtLSQPolicy;
111 //Convert string to lowercase
112 std::transform(policy.begin(), policy.end(), policy.begin(),
113 (int(*)(int)) tolower);
115 //Figure out fetch policy
116 if (policy == "dynamic") {
119 maxLQEntries = LQEntries;
120 maxSQEntries = SQEntries;
122 DPRINTF(LSQ, "LSQ sharing policy set to Dynamic\n");
124 } else if (policy == "partitioned") {
125 lsqPolicy = Partitioned;
127 //@todo:make work if part_amt doesnt divide evenly.
128 maxLQEntries = LQEntries / numThreads;
129 maxSQEntries = SQEntries / numThreads;
131 DPRINTF(Fetch, "LSQ sharing policy set to Partitioned: "
132 "%i entries per LQ | %i entries per SQ",
133 maxLQEntries,maxSQEntries);
135 } else if (policy == "threshold") {
136 lsqPolicy = Threshold;
138 assert(params->smtLSQThreshold > LQEntries);
139 assert(params->smtLSQThreshold > SQEntries);
141 //Divide up by threshold amount
142 //@todo: Should threads check the max and the total
144 maxLQEntries = params->smtLSQThreshold;
145 maxSQEntries = params->smtLSQThreshold;
147 DPRINTF(LSQ, "LSQ sharing policy set to Threshold: "
148 "%i entries per LQ | %i entries per SQ",
149 maxLQEntries,maxSQEntries);
152 assert(0 && "Invalid LSQ Sharing Policy.Options Are:{Dynamic,"
153 "Partitioned, Threshold}");
157 for (int tid=0; tid < numThreads; tid++) {
158 thread[tid].init(params, this, maxLQEntries, maxSQEntries, tid);
159 thread[tid].setDcachePort(&dcachePort);
166 LSQ<Impl>::name() const
168 return iewStage->name() + ".lsq";
173 LSQ<Impl>::regStats()
176 for (int tid=0; tid < numThreads; tid++) {
177 thread[tid].regStats();
183 LSQ<Impl>::setActiveThreads(std::list<unsigned> *at_ptr)
185 activeThreads = at_ptr;
186 assert(activeThreads != 0);
191 LSQ<Impl>::setCPU(O3CPU *cpu_ptr)
195 dcachePort.setName(name());
197 for (int tid=0; tid < numThreads; tid++) {
198 thread[tid].setCPU(cpu_ptr);
204 LSQ<Impl>::setIEW(IEW *iew_ptr)
208 for (int tid=0; tid < numThreads; tid++) {
209 thread[tid].setIEW(iew_ptr);
213 template <class Impl>
215 LSQ<Impl>::switchOut()
217 for (int tid = 0; tid < numThreads; tid++) {
218 thread[tid].switchOut();
222 template <class Impl>
224 LSQ<Impl>::takeOverFrom()
226 for (int tid = 0; tid < numThreads; tid++) {
227 thread[tid].takeOverFrom();
231 template <class Impl>
233 LSQ<Impl>::entryAmount(int num_threads)
235 if (lsqPolicy == Partitioned) {
236 return LQEntries / num_threads;
242 template <class Impl>
244 LSQ<Impl>::resetEntries()
246 if (lsqPolicy != Dynamic || numThreads > 1) {
247 int active_threads = activeThreads->size();
251 if (lsqPolicy == Partitioned) {
252 maxEntries = LQEntries / active_threads;
253 } else if (lsqPolicy == Threshold && active_threads == 1) {
254 maxEntries = LQEntries;
256 maxEntries = LQEntries;
259 std::list<unsigned>::iterator threads = activeThreads->begin();
260 std::list<unsigned>::iterator end = activeThreads->end();
262 while (threads != end) {
263 unsigned tid = *threads++;
265 resizeEntries(maxEntries, tid);
272 LSQ<Impl>::removeEntries(unsigned tid)
274 thread[tid].clearLQ();
275 thread[tid].clearSQ();
280 LSQ<Impl>::resizeEntries(unsigned size,unsigned tid)
282 thread[tid].resizeLQ(size);
283 thread[tid].resizeSQ(size);
290 std::list<unsigned>::iterator threads = activeThreads->begin();
291 std::list<unsigned>::iterator end = activeThreads->end();
293 while (threads != end) {
294 unsigned tid = *threads++;
302 LSQ<Impl>::insertLoad(DynInstPtr &load_inst)
304 unsigned tid = load_inst->threadNumber;
306 thread[tid].insertLoad(load_inst);
311 LSQ<Impl>::insertStore(DynInstPtr &store_inst)
313 unsigned tid = store_inst->threadNumber;
315 thread[tid].insertStore(store_inst);
320 LSQ<Impl>::executeLoad(DynInstPtr &inst)
322 unsigned tid = inst->threadNumber;
324 return thread[tid].executeLoad(inst);
329 LSQ<Impl>::executeStore(DynInstPtr &inst)
331 unsigned tid = inst->threadNumber;
333 return thread[tid].executeStore(inst);
338 LSQ<Impl>::writebackStores()
340 std::list<unsigned>::iterator threads = activeThreads->begin();
341 std::list<unsigned>::iterator end = activeThreads->end();
343 while (threads != end) {
344 unsigned tid = *threads++;
346 if (numStoresToWB(tid) > 0) {
347 DPRINTF(Writeback,"[tid:%i] Writing back stores. %i stores "
348 "available for Writeback.\n", tid, numStoresToWB(tid));
351 thread[tid].writebackStores();
357 LSQ<Impl>::violation()
359 /* Answers: Does Anybody Have a Violation?*/
360 std::list<unsigned>::iterator threads = activeThreads->begin();
361 std::list<unsigned>::iterator end = activeThreads->end();
363 while (threads != end) {
364 unsigned tid = *threads++;
366 if (thread[tid].violation())
375 LSQ<Impl>::getCount()
379 std::list<unsigned>::iterator threads = activeThreads->begin();
380 std::list<unsigned>::iterator end = activeThreads->end();
382 while (threads != end) {
383 unsigned tid = *threads++;
385 total += getCount(tid);
393 LSQ<Impl>::numLoads()
397 std::list<unsigned>::iterator threads = activeThreads->begin();
398 std::list<unsigned>::iterator end = activeThreads->end();
400 while (threads != end) {
401 unsigned tid = *threads++;
403 total += numLoads(tid);
411 LSQ<Impl>::numStores()
415 std::list<unsigned>::iterator threads = activeThreads->begin();
416 std::list<unsigned>::iterator end = activeThreads->end();
418 while (threads != end) {
419 unsigned tid = *threads++;
421 total += thread[tid].numStores();
429 LSQ<Impl>::numLoadsReady()
433 std::list<unsigned>::iterator threads = activeThreads->begin();
434 std::list<unsigned>::iterator end = activeThreads->end();
436 while (threads != end) {
437 unsigned tid = *threads++;
439 total += thread[tid].numLoadsReady();
447 LSQ<Impl>::numFreeEntries()
451 std::list<unsigned>::iterator threads = activeThreads->begin();
452 std::list<unsigned>::iterator end = activeThreads->end();
454 while (threads != end) {
455 unsigned tid = *threads++;
457 total += thread[tid].numFreeEntries();
465 LSQ<Impl>::numFreeEntries(unsigned tid)
467 //if( lsqPolicy == Dynamic )
468 //return numFreeEntries();
470 return thread[tid].numFreeEntries();
477 std::list<unsigned>::iterator threads = activeThreads->begin();
478 std::list<unsigned>::iterator end = activeThreads->end();
480 while (threads != end) {
481 unsigned tid = *threads++;
483 if (!(thread[tid].lqFull() || thread[tid].sqFull()))
492 LSQ<Impl>::isFull(unsigned tid)
494 //@todo: Change to Calculate All Entries for
496 if (lsqPolicy == Dynamic)
499 return thread[tid].lqFull() || thread[tid].sqFull();
506 std::list<unsigned>::iterator threads = activeThreads->begin();
507 std::list<unsigned>::iterator end = activeThreads->end();
509 while (threads != end) {
510 unsigned tid = *threads++;
512 if (!thread[tid].lqFull())
521 LSQ<Impl>::lqFull(unsigned tid)
523 //@todo: Change to Calculate All Entries for
525 if( lsqPolicy == Dynamic )
528 return thread[tid].lqFull();
535 std::list<unsigned>::iterator threads = activeThreads->begin();
536 std::list<unsigned>::iterator end = activeThreads->end();
538 while (threads != end) {
539 unsigned tid = *threads++;
550 LSQ<Impl>::sqFull(unsigned tid)
552 //@todo: Change to Calculate All Entries for
554 if( lsqPolicy == Dynamic )
557 return thread[tid].sqFull();
562 LSQ<Impl>::isStalled()
564 std::list<unsigned>::iterator threads = activeThreads->begin();
565 std::list<unsigned>::iterator end = activeThreads->end();
567 while (threads != end) {
568 unsigned tid = *threads++;
570 if (!thread[tid].isStalled())
579 LSQ<Impl>::isStalled(unsigned tid)
581 if( lsqPolicy == Dynamic )
584 return thread[tid].isStalled();
589 LSQ<Impl>::hasStoresToWB()
591 std::list<unsigned>::iterator threads = activeThreads->begin();
592 std::list<unsigned>::iterator end = activeThreads->end();
597 while (threads != end) {
598 unsigned tid = *threads++;
600 if (!hasStoresToWB(tid))
611 std::list<unsigned>::iterator threads = activeThreads->begin();
612 std::list<unsigned>::iterator end = activeThreads->end();
614 while (threads != end) {
615 unsigned tid = *threads++;
626 LSQ<Impl>::dumpInsts()
628 std::list<unsigned>::iterator threads = activeThreads->begin();
629 std::list<unsigned>::iterator end = activeThreads->end();
631 while (threads != end) {
632 unsigned tid = *threads++;
634 thread[tid].dumpInsts();