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