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