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