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