Changes to get OzoneCPU to compile once more.
[gem5.git] / src / cpu / ozone / lw_back_end_impl.hh
1 /*
2 * Copyright (c) 2006 The Regents of The University of Michigan
3 * All rights reserved.
4 *
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.
15 *
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.
27 *
28 * Authors: Kevin Lim
29 */
30
31 #include "config/use_checker.hh"
32
33 #include "cpu/ozone/lw_back_end.hh"
34 #include "cpu/op_class.hh"
35
36 #if USE_CHECKER
37 #include "cpu/checker/cpu.hh"
38 #endif
39
40 template <class Impl>
41 void
42 LWBackEnd<Impl>::generateTrapEvent(Tick latency)
43 {
44 DPRINTF(BE, "Generating trap event\n");
45
46 TrapEvent *trap = new TrapEvent(this);
47
48 trap->schedule(curTick + cpu->cycles(latency));
49
50 thread->trapPending = true;
51 }
52
53 template <class Impl>
54 int
55 LWBackEnd<Impl>::wakeDependents(DynInstPtr &inst, bool memory_deps)
56 {
57 assert(!inst->isSquashed());
58 std::vector<DynInstPtr> &dependents = memory_deps ? inst->getMemDeps() :
59 inst->getDependents();
60 int num_outputs = dependents.size();
61
62 DPRINTF(BE, "Waking instruction [sn:%lli] dependents in IQ\n", inst->seqNum);
63
64 for (int i = 0; i < num_outputs; i++) {
65 DynInstPtr dep_inst = dependents[i];
66 if (!memory_deps) {
67 dep_inst->markSrcRegReady();
68 } else {
69 if (!dep_inst->isSquashed())
70 dep_inst->markMemInstReady(inst.get());
71 }
72
73 DPRINTF(BE, "Marking source reg ready [sn:%lli] in IQ\n", dep_inst->seqNum);
74
75 if (dep_inst->readyToIssue() && dep_inst->isInROB() &&
76 !dep_inst->isNonSpeculative() && !dep_inst->isStoreConditional() &&
77 dep_inst->memDepReady() && !dep_inst->isMemBarrier() &&
78 !dep_inst->isWriteBarrier()) {
79 DPRINTF(BE, "Adding instruction to exeList [sn:%lli]\n",
80 dep_inst->seqNum);
81 exeList.push(dep_inst);
82 if (dep_inst->iqItValid) {
83 DPRINTF(BE, "Removing instruction from waiting list\n");
84 waitingList.erase(dep_inst->iqIt);
85 waitingInsts--;
86 dep_inst->iqItValid = false;
87 assert(waitingInsts >= 0);
88 }
89 if (dep_inst->isMemRef()) {
90 removeWaitingMemOp(dep_inst);
91 DPRINTF(BE, "Issued a waiting mem op [sn:%lli]\n",
92 dep_inst->seqNum);
93 }
94 }
95 }
96 return num_outputs;
97 }
98
99 template <class Impl>
100 void
101 LWBackEnd<Impl>::rescheduleMemInst(DynInstPtr &inst)
102 {
103 replayList.push_front(inst);
104 }
105
106 template <class Impl>
107 LWBackEnd<Impl>::TrapEvent::TrapEvent(LWBackEnd<Impl> *_be)
108 : Event(&mainEventQueue, CPU_Tick_Pri), be(_be)
109 {
110 this->setFlags(Event::AutoDelete);
111 }
112
113 template <class Impl>
114 void
115 LWBackEnd<Impl>::TrapEvent::process()
116 {
117 be->trapSquash = true;
118 }
119
120 template <class Impl>
121 const char *
122 LWBackEnd<Impl>::TrapEvent::description()
123 {
124 return "Trap event";
125 }
126
127 template <class Impl>
128 void
129 LWBackEnd<Impl>::replayMemInst(DynInstPtr &inst)
130 {
131 bool found_inst = false;
132 while (!replayList.empty()) {
133 exeList.push(replayList.front());
134 if (replayList.front() == inst) {
135 found_inst = true;
136 }
137 replayList.pop_front();
138 }
139 assert(found_inst);
140 }
141
142 template <class Impl>
143 LWBackEnd<Impl>::LWBackEnd(Params *params)
144 : d2i(5, 5), i2e(5, 5), e2c(5, 5), numInstsToWB(5, 5),
145 trapSquash(false), tcSquash(false),
146 width(params->backEndWidth), exactFullStall(true)
147 {
148 numROBEntries = params->numROBEntries;
149 numInsts = 0;
150 numDispatchEntries = 32;
151 maxOutstandingMemOps = params->maxOutstandingMemOps;
152 numWaitingMemOps = 0;
153 waitingInsts = 0;
154 switchedOut = false;
155 switchPending = false;
156
157 LSQ.setBE(this);
158
159 // Setup IQ and LSQ with their parameters here.
160 instsToDispatch = d2i.getWire(-1);
161
162 instsToExecute = i2e.getWire(-1);
163
164 dispatchWidth = params->dispatchWidth ? params->dispatchWidth : width;
165 issueWidth = params->issueWidth ? params->issueWidth : width;
166 wbWidth = params->wbWidth ? params->wbWidth : width;
167 commitWidth = params->commitWidth ? params->commitWidth : width;
168
169 LSQ.init(params, params->LQEntries, params->SQEntries, 0);
170
171 dispatchStatus = Running;
172 }
173
174 template <class Impl>
175 std::string
176 LWBackEnd<Impl>::name() const
177 {
178 return cpu->name() + ".backend";
179 }
180
181 template <class Impl>
182 void
183 LWBackEnd<Impl>::regStats()
184 {
185 using namespace Stats;
186 rob_cap_events
187 .init(cpu->number_of_threads)
188 .name(name() + ".ROB:cap_events")
189 .desc("number of cycles where ROB cap was active")
190 .flags(total)
191 ;
192
193 rob_cap_inst_count
194 .init(cpu->number_of_threads)
195 .name(name() + ".ROB:cap_inst")
196 .desc("number of instructions held up by ROB cap")
197 .flags(total)
198 ;
199
200 iq_cap_events
201 .init(cpu->number_of_threads)
202 .name(name() +".IQ:cap_events" )
203 .desc("number of cycles where IQ cap was active")
204 .flags(total)
205 ;
206
207 iq_cap_inst_count
208 .init(cpu->number_of_threads)
209 .name(name() + ".IQ:cap_inst")
210 .desc("number of instructions held up by IQ cap")
211 .flags(total)
212 ;
213
214
215 exe_inst
216 .init(cpu->number_of_threads)
217 .name(name() + ".ISSUE:count")
218 .desc("number of insts issued")
219 .flags(total)
220 ;
221
222 exe_swp
223 .init(cpu->number_of_threads)
224 .name(name() + ".ISSUE:swp")
225 .desc("number of swp insts issued")
226 .flags(total)
227 ;
228
229 exe_nop
230 .init(cpu->number_of_threads)
231 .name(name() + ".ISSUE:nop")
232 .desc("number of nop insts issued")
233 .flags(total)
234 ;
235
236 exe_refs
237 .init(cpu->number_of_threads)
238 .name(name() + ".ISSUE:refs")
239 .desc("number of memory reference insts issued")
240 .flags(total)
241 ;
242
243 exe_loads
244 .init(cpu->number_of_threads)
245 .name(name() + ".ISSUE:loads")
246 .desc("number of load insts issued")
247 .flags(total)
248 ;
249
250 exe_branches
251 .init(cpu->number_of_threads)
252 .name(name() + ".ISSUE:branches")
253 .desc("Number of branches issued")
254 .flags(total)
255 ;
256
257 issued_ops
258 .init(cpu->number_of_threads)
259 .name(name() + ".ISSUE:op_count")
260 .desc("number of insts issued")
261 .flags(total)
262 ;
263
264 /*
265 for (int i=0; i<Num_OpClasses; ++i) {
266 stringstream subname;
267 subname << opClassStrings[i] << "_delay";
268 issue_delay_dist.subname(i, subname.str());
269 }
270 */
271 //
272 // Other stats
273 //
274 lsq_forw_loads
275 .init(cpu->number_of_threads)
276 .name(name() + ".LSQ:forw_loads")
277 .desc("number of loads forwarded via LSQ")
278 .flags(total)
279 ;
280
281 inv_addr_loads
282 .init(cpu->number_of_threads)
283 .name(name() + ".ISSUE:addr_loads")
284 .desc("number of invalid-address loads")
285 .flags(total)
286 ;
287
288 inv_addr_swpfs
289 .init(cpu->number_of_threads)
290 .name(name() + ".ISSUE:addr_swpfs")
291 .desc("number of invalid-address SW prefetches")
292 .flags(total)
293 ;
294
295 lsq_blocked_loads
296 .init(cpu->number_of_threads)
297 .name(name() + ".LSQ:blocked_loads")
298 .desc("number of ready loads not issued due to memory disambiguation")
299 .flags(total)
300 ;
301
302 lsqInversion
303 .name(name() + ".ISSUE:lsq_invert")
304 .desc("Number of times LSQ instruction issued early")
305 ;
306
307 n_issued_dist
308 .init(issueWidth + 1)
309 .name(name() + ".ISSUE:issued_per_cycle")
310 .desc("Number of insts issued each cycle")
311 .flags(total | pdf | dist)
312 ;
313 issue_delay_dist
314 .init(Num_OpClasses,0,99,2)
315 .name(name() + ".ISSUE:")
316 .desc("cycles from operands ready to issue")
317 .flags(pdf | cdf)
318 ;
319
320 queue_res_dist
321 .init(Num_OpClasses, 0, 99, 2)
322 .name(name() + ".IQ:residence:")
323 .desc("cycles from dispatch to issue")
324 .flags(total | pdf | cdf )
325 ;
326 for (int i = 0; i < Num_OpClasses; ++i) {
327 queue_res_dist.subname(i, opClassStrings[i]);
328 }
329
330 writeback_count
331 .init(cpu->number_of_threads)
332 .name(name() + ".WB:count")
333 .desc("cumulative count of insts written-back")
334 .flags(total)
335 ;
336
337 producer_inst
338 .init(cpu->number_of_threads)
339 .name(name() + ".WB:producers")
340 .desc("num instructions producing a value")
341 .flags(total)
342 ;
343
344 consumer_inst
345 .init(cpu->number_of_threads)
346 .name(name() + ".WB:consumers")
347 .desc("num instructions consuming a value")
348 .flags(total)
349 ;
350
351 wb_penalized
352 .init(cpu->number_of_threads)
353 .name(name() + ".WB:penalized")
354 .desc("number of instrctions required to write to 'other' IQ")
355 .flags(total)
356 ;
357
358
359 wb_penalized_rate
360 .name(name() + ".WB:penalized_rate")
361 .desc ("fraction of instructions written-back that wrote to 'other' IQ")
362 .flags(total)
363 ;
364
365 wb_penalized_rate = wb_penalized / writeback_count;
366
367 wb_fanout
368 .name(name() + ".WB:fanout")
369 .desc("average fanout of values written-back")
370 .flags(total)
371 ;
372
373 wb_fanout = producer_inst / consumer_inst;
374
375 wb_rate
376 .name(name() + ".WB:rate")
377 .desc("insts written-back per cycle")
378 .flags(total)
379 ;
380 wb_rate = writeback_count / cpu->numCycles;
381
382 stat_com_inst
383 .init(cpu->number_of_threads)
384 .name(name() + ".COM:count")
385 .desc("Number of instructions committed")
386 .flags(total)
387 ;
388
389 stat_com_swp
390 .init(cpu->number_of_threads)
391 .name(name() + ".COM:swp_count")
392 .desc("Number of s/w prefetches committed")
393 .flags(total)
394 ;
395
396 stat_com_refs
397 .init(cpu->number_of_threads)
398 .name(name() + ".COM:refs")
399 .desc("Number of memory references committed")
400 .flags(total)
401 ;
402
403 stat_com_loads
404 .init(cpu->number_of_threads)
405 .name(name() + ".COM:loads")
406 .desc("Number of loads committed")
407 .flags(total)
408 ;
409
410 stat_com_membars
411 .init(cpu->number_of_threads)
412 .name(name() + ".COM:membars")
413 .desc("Number of memory barriers committed")
414 .flags(total)
415 ;
416
417 stat_com_branches
418 .init(cpu->number_of_threads)
419 .name(name() + ".COM:branches")
420 .desc("Number of branches committed")
421 .flags(total)
422 ;
423 n_committed_dist
424 .init(0,commitWidth,1)
425 .name(name() + ".COM:committed_per_cycle")
426 .desc("Number of insts commited each cycle")
427 .flags(pdf)
428 ;
429
430 //
431 // Commit-Eligible instructions...
432 //
433 // -> The number of instructions eligible to commit in those
434 // cycles where we reached our commit BW limit (less the number
435 // actually committed)
436 //
437 // -> The average value is computed over ALL CYCLES... not just
438 // the BW limited cycles
439 //
440 // -> The standard deviation is computed only over cycles where
441 // we reached the BW limit
442 //
443 commit_eligible
444 .init(cpu->number_of_threads)
445 .name(name() + ".COM:bw_limited")
446 .desc("number of insts not committed due to BW limits")
447 .flags(total)
448 ;
449
450 commit_eligible_samples
451 .name(name() + ".COM:bw_lim_events")
452 .desc("number cycles where commit BW limit reached")
453 ;
454
455 squashedInsts
456 .init(cpu->number_of_threads)
457 .name(name() + ".COM:squashed_insts")
458 .desc("Number of instructions removed from inst list")
459 ;
460
461 ROBSquashedInsts
462 .init(cpu->number_of_threads)
463 .name(name() + ".COM:rob_squashed_insts")
464 .desc("Number of instructions removed from inst list when they reached the head of the ROB")
465 ;
466
467 ROB_fcount
468 .name(name() + ".ROB:full_count")
469 .desc("number of cycles where ROB was full")
470 ;
471
472 ROB_count
473 .init(cpu->number_of_threads)
474 .name(name() + ".ROB:occupancy")
475 .desc(name() + ".ROB occupancy (cumulative)")
476 .flags(total)
477 ;
478
479 ROB_full_rate
480 .name(name() + ".ROB:full_rate")
481 .desc("ROB full per cycle")
482 ;
483 ROB_full_rate = ROB_fcount / cpu->numCycles;
484
485 ROB_occ_rate
486 .name(name() + ".ROB:occ_rate")
487 .desc("ROB occupancy rate")
488 .flags(total)
489 ;
490 ROB_occ_rate = ROB_count / cpu->numCycles;
491
492 ROB_occ_dist
493 .init(cpu->number_of_threads,0,numROBEntries,2)
494 .name(name() + ".ROB:occ_dist")
495 .desc("ROB Occupancy per cycle")
496 .flags(total | cdf)
497 ;
498 }
499
500 template <class Impl>
501 void
502 LWBackEnd<Impl>::setCPU(OzoneCPU *cpu_ptr)
503 {
504 cpu = cpu_ptr;
505 LSQ.setCPU(cpu_ptr);
506 checker = cpu->checker;
507 }
508
509 template <class Impl>
510 void
511 LWBackEnd<Impl>::setCommBuffer(TimeBuffer<CommStruct> *_comm)
512 {
513 comm = _comm;
514 toIEW = comm->getWire(0);
515 fromCommit = comm->getWire(-1);
516 }
517
518 #if FULL_SYSTEM
519 template <class Impl>
520 void
521 LWBackEnd<Impl>::checkInterrupts()
522 {
523 if (cpu->checkInterrupts &&
524 cpu->check_interrupts() &&
525 !cpu->inPalMode(thread->readPC()) &&
526 !trapSquash &&
527 !tcSquash) {
528 frontEnd->interruptPending = true;
529 if (robEmpty() && !LSQ.hasStoresToWB()) {
530 // Will need to squash all instructions currently in flight and have
531 // the interrupt handler restart at the last non-committed inst.
532 // Most of that can be handled through the trap() function. The
533 // processInterrupts() function really just checks for interrupts
534 // and then calls trap() if there is an interrupt present.
535
536 // Not sure which thread should be the one to interrupt. For now
537 // always do thread 0.
538 assert(!thread->inSyscall);
539 thread->inSyscall = true;
540
541 // CPU will handle implementation of the interrupt.
542 cpu->processInterrupts();
543
544 // Now squash or record that I need to squash this cycle.
545 commitStatus = TrapPending;
546
547 // Exit state update mode to avoid accidental updating.
548 thread->inSyscall = false;
549
550 // Generate trap squash event.
551 generateTrapEvent();
552
553 DPRINTF(BE, "Interrupt detected.\n");
554 } else {
555 DPRINTF(BE, "Interrupt must wait for ROB to drain.\n");
556 }
557 }
558 }
559
560 template <class Impl>
561 void
562 LWBackEnd<Impl>::handleFault(Fault &fault, Tick latency)
563 {
564 DPRINTF(BE, "Handling fault!\n");
565
566 assert(!thread->inSyscall);
567
568 thread->inSyscall = true;
569
570 // Consider holding onto the trap and waiting until the trap event
571 // happens for this to be executed.
572 fault->invoke(thread->getTC());
573
574 // Exit state update mode to avoid accidental updating.
575 thread->inSyscall = false;
576
577 commitStatus = TrapPending;
578
579 // Generate trap squash event.
580 generateTrapEvent(latency);
581 }
582 #endif
583
584 template <class Impl>
585 void
586 LWBackEnd<Impl>::tick()
587 {
588 DPRINTF(BE, "Ticking back end\n");
589
590 if (switchPending && robEmpty() && !LSQ.hasStoresToWB()) {
591 cpu->signalSwitched();
592 return;
593 }
594
595 ROB_count[0]+= numInsts;
596
597 wbCycle = 0;
598
599 // Read in any done instruction information and update the IQ or LSQ.
600 updateStructures();
601
602 #if FULL_SYSTEM
603 checkInterrupts();
604
605 if (trapSquash) {
606 assert(!tcSquash);
607 squashFromTrap();
608 } else if (tcSquash) {
609 squashFromTC();
610 }
611 #endif
612
613 if (dispatchStatus != Blocked) {
614 dispatchInsts();
615 } else {
616 checkDispatchStatus();
617 }
618
619 if (commitStatus != TrapPending) {
620 executeInsts();
621
622 commitInsts();
623 }
624
625 LSQ.writebackStores();
626
627 DPRINTF(BE, "Waiting insts: %i, mem ops: %i, ROB entries in use: %i, "
628 "LSQ loads: %i, LSQ stores: %i\n",
629 waitingInsts, numWaitingMemOps, numInsts,
630 LSQ.numLoads(), LSQ.numStores());
631
632 #ifdef DEBUG
633 assert(numInsts == instList.size());
634 assert(waitingInsts == waitingList.size());
635 assert(numWaitingMemOps == waitingMemOps.size());
636 assert(!switchedOut);
637 #endif
638 }
639
640 template <class Impl>
641 void
642 LWBackEnd<Impl>::updateStructures()
643 {
644 if (fromCommit->doneSeqNum) {
645 LSQ.commitLoads(fromCommit->doneSeqNum);
646 LSQ.commitStores(fromCommit->doneSeqNum);
647 }
648
649 if (fromCommit->nonSpecSeqNum) {
650 if (fromCommit->uncached) {
651 // LSQ.executeLoad(fromCommit->lqIdx);
652 } else {
653 // IQ.scheduleNonSpec(
654 // fromCommit->nonSpecSeqNum);
655 }
656 }
657 }
658
659 template <class Impl>
660 void
661 LWBackEnd<Impl>::addToLSQ(DynInstPtr &inst)
662 {
663 // Do anything LSQ specific here?
664 LSQ.insert(inst);
665 }
666
667 template <class Impl>
668 void
669 LWBackEnd<Impl>::dispatchInsts()
670 {
671 DPRINTF(BE, "Trying to dispatch instructions.\n");
672
673 while (numInsts < numROBEntries &&
674 numWaitingMemOps < maxOutstandingMemOps) {
675 // Get instruction from front of time buffer
676 DynInstPtr inst = frontEnd->getInst();
677 if (!inst) {
678 break;
679 } else if (inst->isSquashed()) {
680 continue;
681 }
682
683 ++numInsts;
684 instList.push_front(inst);
685
686 inst->setInROB();
687
688 DPRINTF(BE, "Dispatching instruction [sn:%lli] PC:%#x\n",
689 inst->seqNum, inst->readPC());
690
691 for (int i = 0; i < inst->numDestRegs(); ++i)
692 renameTable[inst->destRegIdx(i)] = inst;
693
694 if (inst->isMemBarrier() || inst->isWriteBarrier()) {
695 if (memBarrier) {
696 DPRINTF(BE, "Instruction [sn:%lli] is waiting on "
697 "barrier [sn:%lli].\n",
698 inst->seqNum, memBarrier->seqNum);
699 memBarrier->addMemDependent(inst);
700 inst->addSrcMemInst(memBarrier);
701 }
702 memBarrier = inst;
703 inst->setCanCommit();
704 } else if (inst->readyToIssue() &&
705 !inst->isNonSpeculative() &&
706 !inst->isStoreConditional()) {
707 if (inst->isMemRef()) {
708
709 LSQ.insert(inst);
710 if (memBarrier) {
711 DPRINTF(BE, "Instruction [sn:%lli] is waiting on "
712 "barrier [sn:%lli].\n",
713 inst->seqNum, memBarrier->seqNum);
714 memBarrier->addMemDependent(inst);
715 inst->addSrcMemInst(memBarrier);
716 addWaitingMemOp(inst);
717
718 waitingList.push_front(inst);
719 inst->iqIt = waitingList.begin();
720 inst->iqItValid = true;
721 waitingInsts++;
722 } else {
723 DPRINTF(BE, "Instruction [sn:%lli] ready, addding to "
724 "exeList.\n",
725 inst->seqNum);
726 exeList.push(inst);
727 }
728 } else if (inst->isNop()) {
729 DPRINTF(BE, "Nop encountered [sn:%lli], skipping exeList.\n",
730 inst->seqNum);
731 inst->setIssued();
732 inst->setExecuted();
733 inst->setCanCommit();
734 } else {
735 DPRINTF(BE, "Instruction [sn:%lli] ready, addding to "
736 "exeList.\n",
737 inst->seqNum);
738 exeList.push(inst);
739 }
740 } else {
741 if (inst->isNonSpeculative() || inst->isStoreConditional()) {
742 inst->setCanCommit();
743 DPRINTF(BE, "Adding non speculative instruction\n");
744 }
745
746 if (inst->isMemRef()) {
747 addWaitingMemOp(inst);
748 LSQ.insert(inst);
749 if (memBarrier) {
750 memBarrier->addMemDependent(inst);
751 inst->addSrcMemInst(memBarrier);
752
753 DPRINTF(BE, "Instruction [sn:%lli] is waiting on "
754 "barrier [sn:%lli].\n",
755 inst->seqNum, memBarrier->seqNum);
756 }
757 }
758
759 DPRINTF(BE, "Instruction [sn:%lli] not ready, addding to "
760 "waitingList.\n",
761 inst->seqNum);
762 waitingList.push_front(inst);
763 inst->iqIt = waitingList.begin();
764 inst->iqItValid = true;
765 waitingInsts++;
766 }
767 }
768
769 // Check if IQ or LSQ is full. If so we'll need to break and stop
770 // removing instructions. Also update the number of insts to remove
771 // from the queue. Check here if we don't care about exact stall
772 // conditions.
773 /*
774 bool stall = false;
775 if (IQ.isFull()) {
776 DPRINTF(BE, "IQ is full!\n");
777 stall = true;
778 } else if (LSQ.isFull()) {
779 DPRINTF(BE, "LSQ is full!\n");
780 stall = true;
781 } else if (isFull()) {
782 DPRINTF(BE, "ROB is full!\n");
783 stall = true;
784 ROB_fcount++;
785 }
786 if (stall) {
787 d2i.advance();
788 dispatchStall();
789 return;
790 }
791 */
792 }
793
794 template <class Impl>
795 void
796 LWBackEnd<Impl>::dispatchStall()
797 {
798 dispatchStatus = Blocked;
799 if (!cpu->decoupledFrontEnd) {
800 // Tell front end to stall here through a timebuffer, or just tell
801 // it directly.
802 }
803 }
804
805 template <class Impl>
806 void
807 LWBackEnd<Impl>::checkDispatchStatus()
808 {
809 DPRINTF(BE, "Checking dispatch status\n");
810 assert(dispatchStatus == Blocked);
811 if (!LSQ.isFull() && !isFull()) {
812 DPRINTF(BE, "Dispatch no longer blocked\n");
813 dispatchStatus = Running;
814 dispatchInsts();
815 }
816 }
817
818 template <class Impl>
819 void
820 LWBackEnd<Impl>::executeInsts()
821 {
822 DPRINTF(BE, "Trying to execute instructions\n");
823
824 int num_executed = 0;
825 while (!exeList.empty() && num_executed < issueWidth) {
826 DynInstPtr inst = exeList.top();
827
828 DPRINTF(BE, "Executing inst [sn:%lli] PC: %#x\n",
829 inst->seqNum, inst->readPC());
830
831 // Check if the instruction is squashed; if so then skip it
832 // and don't count it towards the FU usage.
833 if (inst->isSquashed()) {
834 DPRINTF(BE, "Execute: Instruction was squashed.\n");
835
836 // Not sure how to handle this plus the method of sending # of
837 // instructions to use. Probably will just have to count it
838 // towards the bandwidth usage, but not the FU usage.
839 ++num_executed;
840
841 // Consider this instruction executed so that commit can go
842 // ahead and retire the instruction.
843 inst->setExecuted();
844
845 // Not sure if I should set this here or just let commit try to
846 // commit any squashed instructions. I like the latter a bit more.
847 inst->setCanCommit();
848
849 // ++iewExecSquashedInsts;
850 exeList.pop();
851
852 continue;
853 }
854
855 Fault fault = NoFault;
856
857 // Execute instruction.
858 // Note that if the instruction faults, it will be handled
859 // at the commit stage.
860 if (inst->isMemRef() &&
861 (!inst->isDataPrefetch() && !inst->isInstPrefetch())) {
862 DPRINTF(BE, "Execute: Initiating access for memory "
863 "reference.\n");
864
865 if (inst->isLoad()) {
866 LSQ.executeLoad(inst);
867 } else if (inst->isStore()) {
868 LSQ.executeStore(inst);
869 if (inst->req && !(inst->req->getFlags() & LOCKED)) {
870 inst->setExecuted();
871
872 instToCommit(inst);
873 }
874 } else {
875 panic("Unknown mem type!");
876 }
877 } else {
878 inst->execute();
879
880 inst->setExecuted();
881
882 instToCommit(inst);
883 }
884
885 updateExeInstStats(inst);
886
887 ++funcExeInst;
888 ++num_executed;
889
890 exeList.pop();
891
892 if (inst->mispredicted()) {
893 squashDueToBranch(inst);
894 break;
895 } else if (LSQ.violation()) {
896 // Get the DynInst that caused the violation. Note that this
897 // clears the violation signal.
898 DynInstPtr violator;
899 violator = LSQ.getMemDepViolator();
900
901 DPRINTF(BE, "LDSTQ detected a violation. Violator PC: "
902 "%#x, inst PC: %#x. Addr is: %#x.\n",
903 violator->readPC(), inst->readPC(), inst->physEffAddr);
904
905 // Squash.
906 squashDueToMemViolation(inst);
907 }
908 }
909
910 issued_ops[0]+= num_executed;
911 n_issued_dist[num_executed]++;
912 }
913
914 template<class Impl>
915 void
916 LWBackEnd<Impl>::instToCommit(DynInstPtr &inst)
917 {
918
919 DPRINTF(BE, "Sending instructions to commit [sn:%lli] PC %#x.\n",
920 inst->seqNum, inst->readPC());
921
922 if (!inst->isSquashed()) {
923 DPRINTF(BE, "Writing back instruction [sn:%lli] PC %#x.\n",
924 inst->seqNum, inst->readPC());
925
926 inst->setCanCommit();
927
928 if (inst->isExecuted()) {
929 inst->setResultReady();
930 int dependents = wakeDependents(inst);
931 if (dependents) {
932 producer_inst[0]++;
933 consumer_inst[0]+= dependents;
934 }
935 }
936 }
937
938 writeback_count[0]++;
939 }
940 #if 0
941 template <class Impl>
942 void
943 LWBackEnd<Impl>::writebackInsts()
944 {
945 int wb_width = wbWidth;
946 // Using this method I'm not quite sure how to prevent an
947 // instruction from waking its own dependents multiple times,
948 // without the guarantee that commit always has enough bandwidth
949 // to accept all instructions being written back. This guarantee
950 // might not be too unrealistic.
951 InstListIt wb_inst_it = writeback.begin();
952 InstListIt wb_end_it = writeback.end();
953 int inst_num = 0;
954 int consumer_insts = 0;
955
956 for (; inst_num < wb_width &&
957 wb_inst_it != wb_end_it; inst_num++) {
958 DynInstPtr inst = (*wb_inst_it);
959
960 // Some instructions will be sent to commit without having
961 // executed because they need commit to handle them.
962 // E.g. Uncached loads have not actually executed when they
963 // are first sent to commit. Instead commit must tell the LSQ
964 // when it's ready to execute the uncached load.
965 if (!inst->isSquashed()) {
966 DPRINTF(BE, "Writing back instruction [sn:%lli] PC %#x.\n",
967 inst->seqNum, inst->readPC());
968
969 inst->setCanCommit();
970 inst->setResultReady();
971
972 if (inst->isExecuted()) {
973 int dependents = wakeDependents(inst);
974 if (dependents) {
975 producer_inst[0]++;
976 consumer_insts+= dependents;
977 }
978 }
979 }
980
981 writeback.erase(wb_inst_it++);
982 }
983 LSQ.writebackStores();
984 consumer_inst[0]+= consumer_insts;
985 writeback_count[0]+= inst_num;
986 }
987 #endif
988 template <class Impl>
989 bool
990 LWBackEnd<Impl>::commitInst(int inst_num)
991 {
992 // Read instruction from the head of the ROB
993 DynInstPtr inst = instList.back();
994
995 // Make sure instruction is valid
996 assert(inst);
997
998 if (!inst->readyToCommit())
999 return false;
1000
1001 DPRINTF(BE, "Trying to commit instruction [sn:%lli] PC:%#x\n",
1002 inst->seqNum, inst->readPC());
1003
1004 thread->setPC(inst->readPC());
1005 thread->setNextPC(inst->readNextPC());
1006 inst->setAtCommit();
1007
1008 // If the instruction is not executed yet, then it is a non-speculative
1009 // or store inst. Signal backwards that it should be executed.
1010 if (!inst->isExecuted()) {
1011 if (inst->isNonSpeculative() ||
1012 inst->isStoreConditional() ||
1013 inst->isMemBarrier() ||
1014 inst->isWriteBarrier()) {
1015 #if !FULL_SYSTEM
1016 // Hack to make sure syscalls aren't executed until all stores
1017 // write back their data. This direct communication shouldn't
1018 // be used for anything other than this.
1019 if (inst_num > 0 || LSQ.hasStoresToWB())
1020 #else
1021 if ((inst->isMemBarrier() || inst->isWriteBarrier() ||
1022 inst->isQuiesce()) &&
1023 LSQ.hasStoresToWB())
1024 #endif
1025 {
1026 DPRINTF(BE, "Waiting for all stores to writeback.\n");
1027 return false;
1028 }
1029
1030 DPRINTF(BE, "Encountered a store or non-speculative "
1031 "instruction at the head of the ROB, PC %#x.\n",
1032 inst->readPC());
1033
1034 if (inst->isMemBarrier() || inst->isWriteBarrier()) {
1035 DPRINTF(BE, "Waking dependents on barrier [sn:%lli]\n",
1036 inst->seqNum);
1037 assert(memBarrier);
1038 wakeDependents(inst, true);
1039 if (memBarrier == inst)
1040 memBarrier = NULL;
1041 inst->clearMemDependents();
1042 }
1043
1044 // Send back the non-speculative instruction's sequence number.
1045 if (inst->iqItValid) {
1046 DPRINTF(BE, "Removing instruction from waiting list\n");
1047 waitingList.erase(inst->iqIt);
1048 inst->iqItValid = false;
1049 waitingInsts--;
1050 assert(waitingInsts >= 0);
1051 if (inst->isStore())
1052 removeWaitingMemOp(inst);
1053 }
1054
1055 exeList.push(inst);
1056
1057 // Change the instruction so it won't try to commit again until
1058 // it is executed.
1059 inst->clearCanCommit();
1060
1061 // ++commitNonSpecStalls;
1062
1063 return false;
1064 } else if (inst->isLoad()) {
1065 DPRINTF(BE, "[sn:%lli]: Uncached load, PC %#x.\n",
1066 inst->seqNum, inst->readPC());
1067
1068 // Send back the non-speculative instruction's sequence
1069 // number. Maybe just tell the lsq to re-execute the load.
1070
1071 // Send back the non-speculative instruction's sequence number.
1072 if (inst->iqItValid) {
1073 DPRINTF(BE, "Removing instruction from waiting list\n");
1074 waitingList.erase(inst->iqIt);
1075 inst->iqItValid = false;
1076 waitingInsts--;
1077 assert(waitingInsts >= 0);
1078 removeWaitingMemOp(inst);
1079 }
1080 replayMemInst(inst);
1081
1082 inst->clearCanCommit();
1083
1084 return false;
1085 } else {
1086 panic("Trying to commit un-executed instruction "
1087 "of unknown type!\n");
1088 }
1089 }
1090
1091 // Not handled for now.
1092 assert(!inst->isThreadSync());
1093 assert(inst->memDepReady());
1094 // Stores will mark themselves as totally completed as they need
1095 // to wait to writeback to memory. @todo: Hack...attempt to fix
1096 // having the checker be forced to wait until a store completes in
1097 // order to check all of the instructions. If the store at the
1098 // head of the check list misses, but a later store hits, then
1099 // loads in the checker may see the younger store values instead
1100 // of the store they should see. Either the checker needs its own
1101 // memory (annoying to update), its own store buffer (how to tell
1102 // which value is correct?), or something else...
1103 if (!inst->isStore()) {
1104 inst->setCompleted();
1105 }
1106 // Check if the instruction caused a fault. If so, trap.
1107 Fault inst_fault = inst->getFault();
1108
1109 // Use checker prior to updating anything due to traps or PC
1110 // based events.
1111 #if USE_CHECKER
1112 if (checker) {
1113 checker->verify(inst);
1114 }
1115 #endif
1116
1117 if (inst_fault != NoFault) {
1118 DPRINTF(BE, "Inst [sn:%lli] PC %#x has a fault\n",
1119 inst->seqNum, inst->readPC());
1120
1121 // Instruction is completed as it has a fault.
1122 inst->setCompleted();
1123
1124 if (LSQ.hasStoresToWB()) {
1125 DPRINTF(BE, "Stores still in flight, will wait until drained.\n");
1126 return false;
1127 } else if (inst_num != 0) {
1128 DPRINTF(BE, "Will wait until instruction is head of commit group.\n");
1129 return false;
1130 }
1131 #if USE_CHECKER
1132 else if (checker && inst->isStore()) {
1133 checker->verify(inst);
1134 }
1135 #endif
1136
1137 thread->setInst(
1138 static_cast<TheISA::MachInst>(inst->staticInst->machInst));
1139 #if FULL_SYSTEM
1140 handleFault(inst_fault);
1141 return false;
1142 #else // !FULL_SYSTEM
1143 panic("fault (%d) detected @ PC %08p", inst_fault,
1144 inst->PC);
1145 #endif // FULL_SYSTEM
1146 }
1147
1148 int freed_regs = 0;
1149
1150 for (int i = 0; i < inst->numDestRegs(); ++i) {
1151 DPRINTF(BE, "Commit rename map setting reg %i to [sn:%lli]\n",
1152 (int)inst->destRegIdx(i), inst->seqNum);
1153 thread->renameTable[inst->destRegIdx(i)] = inst;
1154 ++freed_regs;
1155 }
1156
1157 if (inst->traceData) {
1158 inst->traceData->setFetchSeq(inst->seqNum);
1159 inst->traceData->setCPSeq(thread->numInst);
1160 inst->traceData->finalize();
1161 inst->traceData = NULL;
1162 }
1163
1164 inst->clearDependents();
1165
1166 frontEnd->addFreeRegs(freed_regs);
1167
1168 instList.pop_back();
1169
1170 --numInsts;
1171 ++thread->funcExeInst;
1172 // Maybe move this to where the fault is handled; if the fault is
1173 // handled, don't try to set this myself as the fault will set it.
1174 // If not, then I set thread->PC = thread->nextPC and
1175 // thread->nextPC = thread->nextPC + 4.
1176 thread->setPC(thread->readNextPC());
1177 thread->setNextPC(thread->readNextPC() + sizeof(TheISA::MachInst));
1178 updateComInstStats(inst);
1179
1180 // Write the done sequence number here.
1181 toIEW->doneSeqNum = inst->seqNum;
1182 lastCommitCycle = curTick;
1183
1184 #if FULL_SYSTEM
1185 int count = 0;
1186 Addr oldpc;
1187 do {
1188 if (count == 0)
1189 assert(!thread->inSyscall && !thread->trapPending);
1190 oldpc = thread->readPC();
1191 cpu->system->pcEventQueue.service(
1192 thread->getTC());
1193 count++;
1194 } while (oldpc != thread->readPC());
1195 if (count > 1) {
1196 DPRINTF(BE, "PC skip function event, stopping commit\n");
1197 tcSquash = true;
1198 return false;
1199 }
1200 #endif
1201 return true;
1202 }
1203
1204 template <class Impl>
1205 void
1206 LWBackEnd<Impl>::commitInsts()
1207 {
1208 // Not sure this should be a loop or not.
1209 int inst_num = 0;
1210 while (!instList.empty() && inst_num < commitWidth) {
1211 if (instList.back()->isSquashed()) {
1212 instList.back()->clearDependents();
1213 instList.pop_back();
1214 --numInsts;
1215 ROBSquashedInsts[instList.back()->threadNumber]++;
1216 continue;
1217 }
1218
1219 if (!commitInst(inst_num++)) {
1220 DPRINTF(BE, "Can't commit, Instruction [sn:%lli] PC "
1221 "%#x is head of ROB and not ready\n",
1222 instList.back()->seqNum, instList.back()->readPC());
1223 --inst_num;
1224 break;
1225 }
1226 }
1227 n_committed_dist.sample(inst_num);
1228 }
1229
1230 template <class Impl>
1231 void
1232 LWBackEnd<Impl>::squash(const InstSeqNum &sn)
1233 {
1234 LSQ.squash(sn);
1235
1236 int freed_regs = 0;
1237 InstListIt waiting_list_end = waitingList.end();
1238 InstListIt insts_it = waitingList.begin();
1239
1240 while (insts_it != waiting_list_end && (*insts_it)->seqNum > sn)
1241 {
1242 if ((*insts_it)->isSquashed()) {
1243 ++insts_it;
1244 continue;
1245 }
1246 DPRINTF(BE, "Squashing instruction on waitingList PC %#x, [sn:%lli].\n",
1247 (*insts_it)->readPC(),
1248 (*insts_it)->seqNum);
1249
1250 if ((*insts_it)->isMemRef()) {
1251 DPRINTF(BE, "Squashing a waiting mem op [sn:%lli]\n",
1252 (*insts_it)->seqNum);
1253 removeWaitingMemOp((*insts_it));
1254 }
1255
1256 waitingList.erase(insts_it++);
1257 waitingInsts--;
1258 }
1259 assert(waitingInsts >= 0);
1260
1261 insts_it = instList.begin();
1262
1263 while (!instList.empty() && (*insts_it)->seqNum > sn)
1264 {
1265 if ((*insts_it)->isSquashed()) {
1266 ++insts_it;
1267 continue;
1268 }
1269 DPRINTF(BE, "Squashing instruction on inst list PC %#x, [sn:%lli].\n",
1270 (*insts_it)->readPC(),
1271 (*insts_it)->seqNum);
1272
1273 // Mark the instruction as squashed, and ready to commit so that
1274 // it can drain out of the pipeline.
1275 (*insts_it)->setSquashed();
1276
1277 (*insts_it)->setCanCommit();
1278
1279 (*insts_it)->clearInROB();
1280
1281 for (int i = 0; i < (*insts_it)->numDestRegs(); ++i) {
1282 DynInstPtr prev_dest = (*insts_it)->getPrevDestInst(i);
1283 DPRINTF(BE, "Commit rename map setting reg %i to [sn:%lli]\n",
1284 (int)(*insts_it)->destRegIdx(i), prev_dest->seqNum);
1285 renameTable[(*insts_it)->destRegIdx(i)] = prev_dest;
1286 ++freed_regs;
1287 }
1288
1289 (*insts_it)->clearDependents();
1290
1291 squashedInsts[(*insts_it)->threadNumber]++;
1292
1293 instList.erase(insts_it++);
1294 --numInsts;
1295 }
1296
1297 insts_it = waitingList.begin();
1298 while (!waitingList.empty() && insts_it != waitingList.end()) {
1299 if ((*insts_it)->seqNum < sn) {
1300 ++insts_it;
1301 continue;
1302 }
1303 assert((*insts_it)->isSquashed());
1304
1305 waitingList.erase(insts_it++);
1306 waitingInsts--;
1307 }
1308
1309 while (memBarrier && memBarrier->seqNum > sn) {
1310 DPRINTF(BE, "[sn:%lli] Memory barrier squashed (or previously "
1311 "squashed)\n", memBarrier->seqNum);
1312 memBarrier->clearMemDependents();
1313 if (memBarrier->memDepReady()) {
1314 DPRINTF(BE, "No previous barrier\n");
1315 memBarrier = NULL;
1316 } else {
1317 std::list<DynInstPtr> &srcs = memBarrier->getMemSrcs();
1318 memBarrier = srcs.front();
1319 srcs.pop_front();
1320 assert(srcs.empty());
1321 DPRINTF(BE, "Previous barrier: [sn:%lli]\n",
1322 memBarrier->seqNum);
1323 }
1324 }
1325
1326 frontEnd->addFreeRegs(freed_regs);
1327 }
1328
1329 template <class Impl>
1330 void
1331 LWBackEnd<Impl>::squashFromTC()
1332 {
1333 InstSeqNum squashed_inst = robEmpty() ? 0 : instList.back()->seqNum - 1;
1334 squash(squashed_inst);
1335 frontEnd->squash(squashed_inst, thread->readPC(),
1336 false, false);
1337 frontEnd->interruptPending = false;
1338
1339 thread->trapPending = false;
1340 thread->inSyscall = false;
1341 tcSquash = false;
1342 commitStatus = Running;
1343 }
1344
1345 template <class Impl>
1346 void
1347 LWBackEnd<Impl>::squashFromTrap()
1348 {
1349 InstSeqNum squashed_inst = robEmpty() ? 0 : instList.back()->seqNum - 1;
1350 squash(squashed_inst);
1351 frontEnd->squash(squashed_inst, thread->readPC(),
1352 false, false);
1353 frontEnd->interruptPending = false;
1354
1355 thread->trapPending = false;
1356 thread->inSyscall = false;
1357 trapSquash = false;
1358 commitStatus = Running;
1359 }
1360
1361 template <class Impl>
1362 void
1363 LWBackEnd<Impl>::squashDueToBranch(DynInstPtr &inst)
1364 {
1365 // Update the branch predictor state I guess
1366 DPRINTF(BE, "Squashing due to branch [sn:%lli], will restart at PC %#x\n",
1367 inst->seqNum, inst->readNextPC());
1368 squash(inst->seqNum);
1369 frontEnd->squash(inst->seqNum, inst->readNextPC(),
1370 true, inst->mispredicted());
1371 }
1372
1373 template <class Impl>
1374 void
1375 LWBackEnd<Impl>::squashDueToMemViolation(DynInstPtr &inst)
1376 {
1377 // Update the branch predictor state I guess
1378 DPRINTF(BE, "Squashing due to violation [sn:%lli], will restart at PC %#x\n",
1379 inst->seqNum, inst->readNextPC());
1380 squash(inst->seqNum);
1381 frontEnd->squash(inst->seqNum, inst->readNextPC(),
1382 false, inst->mispredicted());
1383 }
1384
1385 template <class Impl>
1386 void
1387 LWBackEnd<Impl>::squashDueToMemBlocked(DynInstPtr &inst)
1388 {
1389 DPRINTF(IEW, "Memory blocked, squashing load and younger insts, "
1390 "PC: %#x [sn:%i].\n", inst->readPC(), inst->seqNum);
1391
1392 squash(inst->seqNum - 1);
1393 frontEnd->squash(inst->seqNum - 1, inst->readPC());
1394 }
1395
1396 template <class Impl>
1397 void
1398 LWBackEnd<Impl>::fetchFault(Fault &fault)
1399 {
1400 faultFromFetch = fault;
1401 fetchHasFault = true;
1402 }
1403
1404 template <class Impl>
1405 void
1406 LWBackEnd<Impl>::switchOut()
1407 {
1408 switchPending = true;
1409 }
1410
1411 template <class Impl>
1412 void
1413 LWBackEnd<Impl>::doSwitchOut()
1414 {
1415 switchedOut = true;
1416 switchPending = false;
1417 // Need to get rid of all committed, non-speculative state and write it
1418 // to memory/TC. In this case this is stores that have committed and not
1419 // yet written back.
1420 assert(robEmpty());
1421 assert(!LSQ.hasStoresToWB());
1422
1423 LSQ.switchOut();
1424
1425 squash(0);
1426 }
1427
1428 template <class Impl>
1429 void
1430 LWBackEnd<Impl>::takeOverFrom(ThreadContext *old_tc)
1431 {
1432 switchedOut = false;
1433 tcSquash = false;
1434 trapSquash = false;
1435
1436 numInsts = 0;
1437 numWaitingMemOps = 0;
1438 waitingMemOps.clear();
1439 waitingInsts = 0;
1440 switchedOut = false;
1441 dispatchStatus = Running;
1442 commitStatus = Running;
1443 LSQ.takeOverFrom(old_tc);
1444 }
1445
1446 template <class Impl>
1447 void
1448 LWBackEnd<Impl>::updateExeInstStats(DynInstPtr &inst)
1449 {
1450 int thread_number = inst->threadNumber;
1451
1452 //
1453 // Pick off the software prefetches
1454 //
1455 #ifdef TARGET_ALPHA
1456 if (inst->isDataPrefetch())
1457 exe_swp[thread_number]++;
1458 else
1459 exe_inst[thread_number]++;
1460 #else
1461 exe_inst[thread_number]++;
1462 #endif
1463
1464 //
1465 // Control operations
1466 //
1467 if (inst->isControl())
1468 exe_branches[thread_number]++;
1469
1470 //
1471 // Memory operations
1472 //
1473 if (inst->isMemRef()) {
1474 exe_refs[thread_number]++;
1475
1476 if (inst->isLoad())
1477 exe_loads[thread_number]++;
1478 }
1479 }
1480
1481 template <class Impl>
1482 void
1483 LWBackEnd<Impl>::updateComInstStats(DynInstPtr &inst)
1484 {
1485 unsigned tid = inst->threadNumber;
1486
1487 // keep an instruction count
1488 thread->numInst++;
1489 thread->numInsts++;
1490
1491 cpu->numInst++;
1492 //
1493 // Pick off the software prefetches
1494 //
1495 #ifdef TARGET_ALPHA
1496 if (inst->isDataPrefetch()) {
1497 stat_com_swp[tid]++;
1498 } else {
1499 stat_com_inst[tid]++;
1500 }
1501 #else
1502 stat_com_inst[tid]++;
1503 #endif
1504
1505 //
1506 // Control Instructions
1507 //
1508 if (inst->isControl())
1509 stat_com_branches[tid]++;
1510
1511 //
1512 // Memory references
1513 //
1514 if (inst->isMemRef()) {
1515 stat_com_refs[tid]++;
1516
1517 if (inst->isLoad()) {
1518 stat_com_loads[tid]++;
1519 }
1520 }
1521
1522 if (inst->isMemBarrier()) {
1523 stat_com_membars[tid]++;
1524 }
1525 }
1526
1527 template <class Impl>
1528 void
1529 LWBackEnd<Impl>::dumpInsts()
1530 {
1531 int num = 0;
1532 int valid_num = 0;
1533
1534 InstListIt inst_list_it = --(instList.end());
1535
1536 cprintf("ExeList size: %i\n", exeList.size());
1537
1538 cprintf("Inst list size: %i\n", instList.size());
1539
1540 while (inst_list_it != instList.end())
1541 {
1542 cprintf("Instruction:%i\n",
1543 num);
1544 if (!(*inst_list_it)->isSquashed()) {
1545 if (!(*inst_list_it)->isIssued()) {
1546 ++valid_num;
1547 cprintf("Count:%i\n", valid_num);
1548 } else if ((*inst_list_it)->isMemRef() &&
1549 !(*inst_list_it)->memOpDone) {
1550 // Loads that have not been marked as executed still count
1551 // towards the total instructions.
1552 ++valid_num;
1553 cprintf("Count:%i\n", valid_num);
1554 }
1555 }
1556
1557 cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n"
1558 "Issued:%i\nSquashed:%i\n",
1559 (*inst_list_it)->readPC(),
1560 (*inst_list_it)->seqNum,
1561 (*inst_list_it)->threadNumber,
1562 (*inst_list_it)->isIssued(),
1563 (*inst_list_it)->isSquashed());
1564
1565 if ((*inst_list_it)->isMemRef()) {
1566 cprintf("MemOpDone:%i\n", (*inst_list_it)->memOpDone);
1567 }
1568
1569 cprintf("\n");
1570
1571 inst_list_it--;
1572 ++num;
1573 }
1574
1575 cprintf("Waiting list size: %i\n", waitingList.size());
1576
1577 inst_list_it = --(waitingList.end());
1578
1579 while (inst_list_it != waitingList.end())
1580 {
1581 cprintf("Instruction:%i\n",
1582 num);
1583 if (!(*inst_list_it)->isSquashed()) {
1584 if (!(*inst_list_it)->isIssued()) {
1585 ++valid_num;
1586 cprintf("Count:%i\n", valid_num);
1587 } else if ((*inst_list_it)->isMemRef() &&
1588 !(*inst_list_it)->memOpDone) {
1589 // Loads that have not been marked as executed still count
1590 // towards the total instructions.
1591 ++valid_num;
1592 cprintf("Count:%i\n", valid_num);
1593 }
1594 }
1595
1596 cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n"
1597 "Issued:%i\nSquashed:%i\n",
1598 (*inst_list_it)->readPC(),
1599 (*inst_list_it)->seqNum,
1600 (*inst_list_it)->threadNumber,
1601 (*inst_list_it)->isIssued(),
1602 (*inst_list_it)->isSquashed());
1603
1604 if ((*inst_list_it)->isMemRef()) {
1605 cprintf("MemOpDone:%i\n", (*inst_list_it)->memOpDone);
1606 }
1607
1608 cprintf("\n");
1609
1610 inst_list_it--;
1611 ++num;
1612 }
1613
1614 cprintf("waitingMemOps list size: %i\n", waitingMemOps.size());
1615
1616 MemIt waiting_it = waitingMemOps.begin();
1617
1618 while (waiting_it != waitingMemOps.end())
1619 {
1620 cprintf("[sn:%lli] ", (*waiting_it));
1621 waiting_it++;
1622 ++num;
1623 }
1624 cprintf("\n");
1625 }