execute.cc (11419:9c7b55faea5d) execute.cc (11567:560d7fbbddd1)
1/*
2 * Copyright (c) 2013-2014 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software

--- 72 unchanged lines hidden (view full) ---

81 lsq(name_ + ".lsq", name_ + ".dcache_port",
82 cpu_, *this,
83 params.executeMaxAccessesInMemory,
84 params.executeMemoryWidth,
85 params.executeLSQRequestsQueueSize,
86 params.executeLSQTransfersQueueSize,
87 params.executeLSQStoreBufferSize,
88 params.executeLSQMaxStoreBufferStoresPerCycle),
1/*
2 * Copyright (c) 2013-2014 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software

--- 72 unchanged lines hidden (view full) ---

81 lsq(name_ + ".lsq", name_ + ".dcache_port",
82 cpu_, *this,
83 params.executeMaxAccessesInMemory,
84 params.executeMemoryWidth,
85 params.executeLSQRequestsQueueSize,
86 params.executeLSQTransfersQueueSize,
87 params.executeLSQStoreBufferSize,
88 params.executeLSQMaxStoreBufferStoresPerCycle),
89 scoreboard(name_ + ".scoreboard"),
90 inputBuffer(name_ + ".inputBuffer", "insts",
91 params.executeInputBufferSize),
92 inputIndex(0),
93 lastCommitWasEndOfMacroop(true),
94 instsBeingCommitted(params.executeCommitLimit),
95 streamSeqNum(InstId::firstStreamSeqNum),
96 lastPredictionSeqNum(InstId::firstPredictionSeqNum),
97 drainState(NotDraining)
89 executeInfo(params.numThreads, ExecuteThreadInfo(params.executeCommitLimit)),
90 interruptPriority(0),
91 issuePriority(0),
92 commitPriority(0)
98{
99 if (commitLimit < 1) {
100 fatal("%s: executeCommitLimit must be >= 1 (%d)\n", name_,
101 commitLimit);
102 }
103
104 if (issueLimit < 1) {
105 fatal("%s: executeCommitLimit must be >= 1 (%d)\n", name_,

--- 59 unchanged lines hidden (view full) ---

165 }
166
167 if (!found_fu) {
168 warn("No functional unit for OpClass %s\n",
169 Enums::OpClassStrings[op_class]);
170 }
171 }
172
93{
94 if (commitLimit < 1) {
95 fatal("%s: executeCommitLimit must be >= 1 (%d)\n", name_,
96 commitLimit);
97 }
98
99 if (issueLimit < 1) {
100 fatal("%s: executeCommitLimit must be >= 1 (%d)\n", name_,

--- 59 unchanged lines hidden (view full) ---

160 }
161
162 if (!found_fu) {
163 warn("No functional unit for OpClass %s\n",
164 Enums::OpClassStrings[op_class]);
165 }
166 }
167
173 inFlightInsts = new Queue<QueuedInst,
174 ReportTraitsAdaptor<QueuedInst> >(
175 name_ + ".inFlightInsts", "insts", total_slots);
168 /* Per-thread structures */
169 for (ThreadID tid = 0; tid < params.numThreads; tid++) {
170 std::string tid_str = std::to_string(tid);
176
171
177 inFUMemInsts = new Queue<QueuedInst,
178 ReportTraitsAdaptor<QueuedInst> >(
179 name_ + ".inFUMemInsts", "insts", total_slots);
172 /* Input Buffers */
173 inputBuffer.push_back(
174 InputBuffer<ForwardInstData>(
175 name_ + ".inputBuffer" + tid_str, "insts",
176 params.executeInputBufferSize));
177
178 /* Scoreboards */
179 scoreboard.push_back(Scoreboard(name_ + ".scoreboard" + tid_str));
180
181 /* In-flight instruction records */
182 executeInfo[tid].inFlightInsts = new Queue<QueuedInst,
183 ReportTraitsAdaptor<QueuedInst> >(
184 name_ + ".inFlightInsts" + tid_str, "insts", total_slots);
185
186 executeInfo[tid].inFUMemInsts = new Queue<QueuedInst,
187 ReportTraitsAdaptor<QueuedInst> >(
188 name_ + ".inFUMemInsts" + tid_str, "insts", total_slots);
189 }
180}
181
182const ForwardInstData *
190}
191
192const ForwardInstData *
183Execute::getInput()
193Execute::getInput(ThreadID tid)
184{
185 /* Get a line from the inputBuffer to work with */
194{
195 /* Get a line from the inputBuffer to work with */
186 if (!inputBuffer.empty()) {
187 const ForwardInstData &head = inputBuffer.front();
196 if (!inputBuffer[tid].empty()) {
197 const ForwardInstData &head = inputBuffer[tid].front();
188
198
189 return (head.isBubble() ? NULL : &(inputBuffer.front()));
199 return (head.isBubble() ? NULL : &(inputBuffer[tid].front()));
190 } else {
191 return NULL;
192 }
193}
194
195void
200 } else {
201 return NULL;
202 }
203}
204
205void
196Execute::popInput()
206Execute::popInput(ThreadID tid)
197{
207{
198 if (!inputBuffer.empty())
199 inputBuffer.pop();
208 if (!inputBuffer[tid].empty())
209 inputBuffer[tid].pop();
200
210
201 inputIndex = 0;
211 executeInfo[tid].inputIndex = 0;
202}
203
204void
205Execute::tryToBranch(MinorDynInstPtr inst, Fault fault, BranchData &branch)
206{
207 ThreadContext *thread = cpu.getContext(inst->id.threadId);
208 const TheISA::PCState &pc_before = inst->pc;
209 TheISA::PCState target = thread->pcState();

--- 61 unchanged lines hidden (view full) ---

271 inst->pc.instAddr(), target.instAddr(), *inst);
272
273 reason = BranchData::UnpredictedBranch;
274 } else {
275 /* No branch at all */
276 reason = BranchData::NoBranch;
277 }
278
212}
213
214void
215Execute::tryToBranch(MinorDynInstPtr inst, Fault fault, BranchData &branch)
216{
217 ThreadContext *thread = cpu.getContext(inst->id.threadId);
218 const TheISA::PCState &pc_before = inst->pc;
219 TheISA::PCState target = thread->pcState();

--- 61 unchanged lines hidden (view full) ---

281 inst->pc.instAddr(), target.instAddr(), *inst);
282
283 reason = BranchData::UnpredictedBranch;
284 } else {
285 /* No branch at all */
286 reason = BranchData::NoBranch;
287 }
288
279 updateBranchData(reason, inst, target, branch);
289 updateBranchData(inst->id.threadId, reason, inst, target, branch);
280}
281
282void
283Execute::updateBranchData(
290}
291
292void
293Execute::updateBranchData(
294 ThreadID tid,
284 BranchData::Reason reason,
285 MinorDynInstPtr inst, const TheISA::PCState &target,
286 BranchData &branch)
287{
288 if (reason != BranchData::NoBranch) {
289 /* Bump up the stream sequence number on a real branch*/
290 if (BranchData::isStreamChange(reason))
295 BranchData::Reason reason,
296 MinorDynInstPtr inst, const TheISA::PCState &target,
297 BranchData &branch)
298{
299 if (reason != BranchData::NoBranch) {
300 /* Bump up the stream sequence number on a real branch*/
301 if (BranchData::isStreamChange(reason))
291 streamSeqNum++;
302 executeInfo[tid].streamSeqNum++;
292
293 /* Branches (even mis-predictions) don't change the predictionSeqNum,
294 * just the streamSeqNum */
303
304 /* Branches (even mis-predictions) don't change the predictionSeqNum,
305 * just the streamSeqNum */
295 branch = BranchData(reason, streamSeqNum,
306 branch = BranchData(reason, tid,
307 executeInfo[tid].streamSeqNum,
296 /* Maintaining predictionSeqNum if there's no inst is just a
297 * courtesy and looks better on minorview */
308 /* Maintaining predictionSeqNum if there's no inst is just a
309 * courtesy and looks better on minorview */
298 (inst->isBubble() ? lastPredictionSeqNum
310 (inst->isBubble() ? executeInfo[tid].lastPredictionSeqNum
299 : inst->id.predictionSeqNum),
300 target, inst);
301
302 DPRINTF(Branch, "Branch data signalled: %s\n", branch);
303 }
304}
305
306void

--- 107 unchanged lines hidden (view full) ---

414
415 assert(!lsq.accessesInFlight());
416
417 DPRINTF(MinorInterrupt, "Invoking interrupt: %s to PC: %s\n",
418 interrupt->name(), cpu.getContext(thread_id)->pcState());
419
420 /* Assume that an interrupt *must* cause a branch. Assert this? */
421
311 : inst->id.predictionSeqNum),
312 target, inst);
313
314 DPRINTF(Branch, "Branch data signalled: %s\n", branch);
315 }
316}
317
318void

--- 107 unchanged lines hidden (view full) ---

426
427 assert(!lsq.accessesInFlight());
428
429 DPRINTF(MinorInterrupt, "Invoking interrupt: %s to PC: %s\n",
430 interrupt->name(), cpu.getContext(thread_id)->pcState());
431
432 /* Assume that an interrupt *must* cause a branch. Assert this? */
433
422 updateBranchData(BranchData::Interrupt, MinorDynInst::bubble(),
423 cpu.getContext(thread_id)->pcState(), branch);
434 updateBranchData(thread_id, BranchData::Interrupt,
435 MinorDynInst::bubble(), cpu.getContext(thread_id)->pcState(),
436 branch);
424 }
425
426 return interrupt != NoFault;
427}
428
429bool
430Execute::executeMemRefInst(MinorDynInstPtr inst, BranchData &branch,
431 bool &passed_predicate, Fault &fault)

--- 69 unchanged lines hidden (view full) ---

501
502 if (ret < 0)
503 ret = cycle_size - 1;
504
505 return ret;
506}
507
508unsigned int
437 }
438
439 return interrupt != NoFault;
440}
441
442bool
443Execute::executeMemRefInst(MinorDynInstPtr inst, BranchData &branch,
444 bool &passed_predicate, Fault &fault)

--- 69 unchanged lines hidden (view full) ---

514
515 if (ret < 0)
516 ret = cycle_size - 1;
517
518 return ret;
519}
520
521unsigned int
509Execute::issue(bool only_issue_microops)
522Execute::issue(ThreadID thread_id)
510{
523{
511 const ForwardInstData *insts_in = getInput();
524 const ForwardInstData *insts_in = getInput(thread_id);
525 ExecuteThreadInfo &thread = executeInfo[thread_id];
512
513 /* Early termination if we have no instructions */
514 if (!insts_in)
515 return 0;
516
517 /* Start from the first FU */
518 unsigned int fu_index = 0;
519

--- 9 unchanged lines hidden (view full) ---

529 /* Number of memory ops issues this cycle to check for memoryIssueLimit */
530 unsigned num_mem_insts_issued = 0;
531
532 /* Number of instructions discarded this cycle in order to enforce a
533 * discardLimit. @todo, add that parameter? */
534 unsigned num_insts_discarded = 0;
535
536 do {
526
527 /* Early termination if we have no instructions */
528 if (!insts_in)
529 return 0;
530
531 /* Start from the first FU */
532 unsigned int fu_index = 0;
533

--- 9 unchanged lines hidden (view full) ---

543 /* Number of memory ops issues this cycle to check for memoryIssueLimit */
544 unsigned num_mem_insts_issued = 0;
545
546 /* Number of instructions discarded this cycle in order to enforce a
547 * discardLimit. @todo, add that parameter? */
548 unsigned num_insts_discarded = 0;
549
550 do {
537 MinorDynInstPtr inst = insts_in->insts[inputIndex];
538 ThreadID thread_id = inst->id.threadId;
551 MinorDynInstPtr inst = insts_in->insts[thread.inputIndex];
539 Fault fault = inst->fault;
540 bool discarded = false;
541 bool issued_mem_ref = false;
542
543 if (inst->isBubble()) {
544 /* Skip */
545 issued = true;
546 } else if (cpu.getContext(thread_id)->status() ==
547 ThreadContext::Suspended)
548 {
549 DPRINTF(MinorExecute, "Not issuing inst: %s from suspended"
550 " thread\n", *inst);
551
552 issued = false;
552 Fault fault = inst->fault;
553 bool discarded = false;
554 bool issued_mem_ref = false;
555
556 if (inst->isBubble()) {
557 /* Skip */
558 issued = true;
559 } else if (cpu.getContext(thread_id)->status() ==
560 ThreadContext::Suspended)
561 {
562 DPRINTF(MinorExecute, "Not issuing inst: %s from suspended"
563 " thread\n", *inst);
564
565 issued = false;
553 } else if (inst->id.streamSeqNum != streamSeqNum) {
566 } else if (inst->id.streamSeqNum != thread.streamSeqNum) {
554 DPRINTF(MinorExecute, "Discarding inst: %s as its stream"
555 " state was unexpected, expected: %d\n",
567 DPRINTF(MinorExecute, "Discarding inst: %s as its stream"
568 " state was unexpected, expected: %d\n",
556 *inst, streamSeqNum);
569 *inst, thread.streamSeqNum);
557 issued = true;
558 discarded = true;
570 issued = true;
571 discarded = true;
559 } else if (fault == NoFault && only_issue_microops &&
560 /* Is this anything other than a non-first microop */
561 (!inst->staticInst->isMicroop() ||
562 !inst->staticInst->isFirstMicroop()))
563 {
564 DPRINTF(MinorExecute, "Not issuing new non-microop inst: %s\n",
565 *inst);
566
567 issued = false;
568 } else {
569 /* Try and issue an instruction into an FU, assume we didn't and
570 * fix that in the loop */
571 issued = false;
572
573 /* Try FU from 0 each instruction */
574 fu_index = 0;
575

--- 17 unchanged lines hidden (view full) ---

593 fu_index = noCostFUIndex;
594
595 /* And start the countdown on activity to allow
596 * this instruction to get to the end of its FU */
597 cpu.activityRecorder->activity();
598
599 /* Mark the destinations for this instruction as
600 * busy */
572 } else {
573 /* Try and issue an instruction into an FU, assume we didn't and
574 * fix that in the loop */
575 issued = false;
576
577 /* Try FU from 0 each instruction */
578 fu_index = 0;
579

--- 17 unchanged lines hidden (view full) ---

597 fu_index = noCostFUIndex;
598
599 /* And start the countdown on activity to allow
600 * this instruction to get to the end of its FU */
601 cpu.activityRecorder->activity();
602
603 /* Mark the destinations for this instruction as
604 * busy */
601 scoreboard.markupInstDests(inst, cpu.curCycle() +
605 scoreboard[thread_id].markupInstDests(inst, cpu.curCycle() +
602 Cycles(0), cpu.getContext(thread_id), false);
603
606 Cycles(0), cpu.getContext(thread_id), false);
607
608 DPRINTF(MinorExecute, "Issuing %s to %d\n", inst->id, noCostFUIndex);
604 inst->fuIndex = noCostFUIndex;
605 inst->extraCommitDelay = Cycles(0);
606 inst->extraCommitDelayExpr = NULL;
607
608 /* Push the instruction onto the inFlight queue so
609 * it can be committed in order */
610 QueuedInst fu_inst(inst);
609 inst->fuIndex = noCostFUIndex;
610 inst->extraCommitDelay = Cycles(0);
611 inst->extraCommitDelayExpr = NULL;
612
613 /* Push the instruction onto the inFlight queue so
614 * it can be committed in order */
615 QueuedInst fu_inst(inst);
611 inFlightInsts->push(fu_inst);
616 thread.inFlightInsts->push(fu_inst);
612
613 issued = true;
614
615 } else if (!fu_is_capable || fu->alreadyPushed()) {
616 /* Skip */
617 if (!fu_is_capable) {
618 DPRINTF(MinorExecute, "Can't issue as FU: %d isn't"
619 " capable\n", fu_index);

--- 19 unchanged lines hidden (view full) ---

639
640 const std::vector<bool> *cant_forward_from_fu_indices =
641 &(fu->cantForwardFromFUIndices);
642
643 if (timing && timing->suppress) {
644 DPRINTF(MinorExecute, "Can't issue inst: %s as extra"
645 " decoding is suppressing it\n",
646 *inst);
617
618 issued = true;
619
620 } else if (!fu_is_capable || fu->alreadyPushed()) {
621 /* Skip */
622 if (!fu_is_capable) {
623 DPRINTF(MinorExecute, "Can't issue as FU: %d isn't"
624 " capable\n", fu_index);

--- 19 unchanged lines hidden (view full) ---

644
645 const std::vector<bool> *cant_forward_from_fu_indices =
646 &(fu->cantForwardFromFUIndices);
647
648 if (timing && timing->suppress) {
649 DPRINTF(MinorExecute, "Can't issue inst: %s as extra"
650 " decoding is suppressing it\n",
651 *inst);
647 } else if (!scoreboard.canInstIssue(inst, src_latencies,
648 cant_forward_from_fu_indices,
652 } else if (!scoreboard[thread_id].canInstIssue(inst,
653 src_latencies, cant_forward_from_fu_indices,
649 cpu.curCycle(), cpu.getContext(thread_id)))
650 {
651 DPRINTF(MinorExecute, "Can't issue inst: %s yet\n",
652 *inst);
653 } else {
654 /* Can insert the instruction into this FU */
655 DPRINTF(MinorExecute, "Issuing inst: %s"
656 " into FU %d\n", *inst,

--- 25 unchanged lines hidden (view full) ---

682 extra_dest_retire_lat_expr;
683
684 if (issued_mem_ref) {
685 /* Remember which instruction this memory op
686 * depends on so that initiateAcc can be called
687 * early */
688 if (allowEarlyMemIssue) {
689 inst->instToWaitFor =
654 cpu.curCycle(), cpu.getContext(thread_id)))
655 {
656 DPRINTF(MinorExecute, "Can't issue inst: %s yet\n",
657 *inst);
658 } else {
659 /* Can insert the instruction into this FU */
660 DPRINTF(MinorExecute, "Issuing inst: %s"
661 " into FU %d\n", *inst,

--- 25 unchanged lines hidden (view full) ---

687 extra_dest_retire_lat_expr;
688
689 if (issued_mem_ref) {
690 /* Remember which instruction this memory op
691 * depends on so that initiateAcc can be called
692 * early */
693 if (allowEarlyMemIssue) {
694 inst->instToWaitFor =
690 scoreboard.execSeqNumToWaitFor(inst,
695 scoreboard[thread_id].execSeqNumToWaitFor(inst,
691 cpu.getContext(thread_id));
692
696 cpu.getContext(thread_id));
697
693 if (lsq.getLastMemBarrier() >
698 if (lsq.getLastMemBarrier(thread_id) >
694 inst->instToWaitFor)
695 {
696 DPRINTF(MinorExecute, "A barrier will"
697 " cause a delay in mem ref issue of"
698 " inst: %s until after inst"
699 " %d(exec)\n", *inst,
699 inst->instToWaitFor)
700 {
701 DPRINTF(MinorExecute, "A barrier will"
702 " cause a delay in mem ref issue of"
703 " inst: %s until after inst"
704 " %d(exec)\n", *inst,
700 lsq.getLastMemBarrier());
705 lsq.getLastMemBarrier(thread_id));
701
702 inst->instToWaitFor =
706
707 inst->instToWaitFor =
703 lsq.getLastMemBarrier();
708 lsq.getLastMemBarrier(thread_id);
704 } else {
705 DPRINTF(MinorExecute, "Memory ref inst:"
706 " %s must wait for inst %d(exec)"
707 " before issuing\n",
708 *inst, inst->instToWaitFor);
709 }
710
711 inst->canEarlyIssue = true;
712 }
713 /* Also queue this instruction in the memory ref
714 * queue to ensure in-order issue to the LSQ */
715 DPRINTF(MinorExecute, "Pushing mem inst: %s\n",
716 *inst);
709 } else {
710 DPRINTF(MinorExecute, "Memory ref inst:"
711 " %s must wait for inst %d(exec)"
712 " before issuing\n",
713 *inst, inst->instToWaitFor);
714 }
715
716 inst->canEarlyIssue = true;
717 }
718 /* Also queue this instruction in the memory ref
719 * queue to ensure in-order issue to the LSQ */
720 DPRINTF(MinorExecute, "Pushing mem inst: %s\n",
721 *inst);
717 inFUMemInsts->push(fu_inst);
722 thread.inFUMemInsts->push(fu_inst);
718 }
719
720 /* Issue to FU */
721 fu->push(fu_inst);
722 /* And start the countdown on activity to allow
723 * this instruction to get to the end of its FU */
724 cpu.activityRecorder->activity();
725
726 /* Mark the destinations for this instruction as
727 * busy */
723 }
724
725 /* Issue to FU */
726 fu->push(fu_inst);
727 /* And start the countdown on activity to allow
728 * this instruction to get to the end of its FU */
729 cpu.activityRecorder->activity();
730
731 /* Mark the destinations for this instruction as
732 * busy */
728 scoreboard.markupInstDests(inst, cpu.curCycle() +
733 scoreboard[thread_id].markupInstDests(inst, cpu.curCycle() +
729 fu->description.opLat +
730 extra_dest_retire_lat +
731 extra_assumed_lat,
732 cpu.getContext(thread_id),
733 issued_mem_ref && extra_assumed_lat == Cycles(0));
734
735 /* Push the instruction onto the inFlight queue so
736 * it can be committed in order */
734 fu->description.opLat +
735 extra_dest_retire_lat +
736 extra_assumed_lat,
737 cpu.getContext(thread_id),
738 issued_mem_ref && extra_assumed_lat == Cycles(0));
739
740 /* Push the instruction onto the inFlight queue so
741 * it can be committed in order */
737 inFlightInsts->push(fu_inst);
742 thread.inFlightInsts->push(fu_inst);
738
739 issued = true;
740 }
741 }
742
743 fu_index++;
744 } while (fu_index != numFuncUnits && !issued);
745

--- 26 unchanged lines hidden (view full) ---

772 num_insts_discarded++;
773 } else if (!inst->isBubble()) {
774 num_insts_issued++;
775
776 if (num_insts_issued == issueLimit)
777 DPRINTF(MinorExecute, "Reached inst issue limit\n");
778 }
779
743
744 issued = true;
745 }
746 }
747
748 fu_index++;
749 } while (fu_index != numFuncUnits && !issued);
750

--- 26 unchanged lines hidden (view full) ---

777 num_insts_discarded++;
778 } else if (!inst->isBubble()) {
779 num_insts_issued++;
780
781 if (num_insts_issued == issueLimit)
782 DPRINTF(MinorExecute, "Reached inst issue limit\n");
783 }
784
780 inputIndex++;
785 thread.inputIndex++;
781 DPRINTF(MinorExecute, "Stepping to next inst inputIndex: %d\n",
786 DPRINTF(MinorExecute, "Stepping to next inst inputIndex: %d\n",
782 inputIndex);
787 thread.inputIndex);
783 }
784
785 /* Got to the end of a line */
788 }
789
790 /* Got to the end of a line */
786 if (inputIndex == insts_in->width()) {
787 popInput();
791 if (thread.inputIndex == insts_in->width()) {
792 popInput(thread_id);
788 /* Set insts_in to null to force us to leave the surrounding
789 * loop */
790 insts_in = NULL;
791
792 if (processMoreThanOneInput) {
793 DPRINTF(MinorExecute, "Wrapping\n");
793 /* Set insts_in to null to force us to leave the surrounding
794 * loop */
795 insts_in = NULL;
796
797 if (processMoreThanOneInput) {
798 DPRINTF(MinorExecute, "Wrapping\n");
794 insts_in = getInput();
799 insts_in = getInput(thread_id);
795 }
796 }
800 }
801 }
797 } while (insts_in && inputIndex < insts_in->width() &&
802 } while (insts_in && thread.inputIndex < insts_in->width() &&
798 /* We still have instructions */
799 fu_index != numFuncUnits && /* Not visited all FUs */
800 issued && /* We've not yet failed to issue an instruction */
801 num_insts_issued != issueLimit && /* Still allowed to issue */
802 num_mem_insts_issued != memoryIssueLimit);
803
804 return num_insts_issued;
805}
806
807bool
803 /* We still have instructions */
804 fu_index != numFuncUnits && /* Not visited all FUs */
805 issued && /* We've not yet failed to issue an instruction */
806 num_insts_issued != issueLimit && /* Still allowed to issue */
807 num_mem_insts_issued != memoryIssueLimit);
808
809 return num_insts_issued;
810}
811
812bool
808Execute::tryPCEvents()
813Execute::tryPCEvents(ThreadID thread_id)
809{
814{
810 ThreadContext *thread = cpu.getContext(0);
815 ThreadContext *thread = cpu.getContext(thread_id);
811 unsigned int num_pc_event_checks = 0;
812
813 /* Handle PC events on instructions */
814 Addr oldPC;
815 do {
816 oldPC = thread->instAddr();
817 cpu.system->pcEventQueue.service(thread);
818 num_pc_event_checks++;

--- 110 unchanged lines hidden (view full) ---

929 completed_mem_issue = completed_inst;
930 } else if (inst->isInst() && inst->staticInst->isMemBarrier() &&
931 !lsq.canPushIntoStoreBuffer())
932 {
933 DPRINTF(MinorExecute, "Can't commit data barrier inst: %s yet as"
934 " there isn't space in the store buffer\n", *inst);
935
936 completed_inst = false;
816 unsigned int num_pc_event_checks = 0;
817
818 /* Handle PC events on instructions */
819 Addr oldPC;
820 do {
821 oldPC = thread->instAddr();
822 cpu.system->pcEventQueue.service(thread);
823 num_pc_event_checks++;

--- 110 unchanged lines hidden (view full) ---

934 completed_mem_issue = completed_inst;
935 } else if (inst->isInst() && inst->staticInst->isMemBarrier() &&
936 !lsq.canPushIntoStoreBuffer())
937 {
938 DPRINTF(MinorExecute, "Can't commit data barrier inst: %s yet as"
939 " there isn't space in the store buffer\n", *inst);
940
941 completed_inst = false;
942 } else if (inst->isInst() && inst->staticInst->isQuiesce()
943 && !branch.isBubble()){
944 /* This instruction can suspend, need to be able to communicate
945 * backwards, so no other branches may evaluate this cycle*/
946 completed_inst = false;
937 } else {
938 ExecContext context(cpu, *cpu.threads[thread_id], *this, inst);
939
940 DPRINTF(MinorExecute, "Committing inst: %s\n", *inst);
941
942 fault = inst->staticInst->execute(&context,
943 inst->traceData);
944

--- 12 unchanged lines hidden (view full) ---

957 doInstCommitAccounting(inst);
958 tryToBranch(inst, fault, branch);
959 }
960
961 if (completed_inst) {
962 /* Keep a copy of this instruction's predictionSeqNum just in case
963 * we need to issue a branch without an instruction (such as an
964 * interrupt) */
947 } else {
948 ExecContext context(cpu, *cpu.threads[thread_id], *this, inst);
949
950 DPRINTF(MinorExecute, "Committing inst: %s\n", *inst);
951
952 fault = inst->staticInst->execute(&context,
953 inst->traceData);
954

--- 12 unchanged lines hidden (view full) ---

967 doInstCommitAccounting(inst);
968 tryToBranch(inst, fault, branch);
969 }
970
971 if (completed_inst) {
972 /* Keep a copy of this instruction's predictionSeqNum just in case
973 * we need to issue a branch without an instruction (such as an
974 * interrupt) */
965 lastPredictionSeqNum = inst->id.predictionSeqNum;
975 executeInfo[thread_id].lastPredictionSeqNum = inst->id.predictionSeqNum;
966
967 /* Check to see if this instruction suspended the current thread. */
968 if (!inst->isFault() &&
969 thread->status() == ThreadContext::Suspended &&
970 branch.isBubble() && /* It didn't branch too */
971 !isInterrupted(thread_id)) /* Don't suspend if we have
972 interrupts */
973 {
976
977 /* Check to see if this instruction suspended the current thread. */
978 if (!inst->isFault() &&
979 thread->status() == ThreadContext::Suspended &&
980 branch.isBubble() && /* It didn't branch too */
981 !isInterrupted(thread_id)) /* Don't suspend if we have
982 interrupts */
983 {
974 TheISA::PCState resume_pc = cpu.getContext(0)->pcState();
984 TheISA::PCState resume_pc = cpu.getContext(thread_id)->pcState();
975
976 assert(resume_pc.microPC() == 0);
977
978 DPRINTF(MinorInterrupt, "Suspending thread: %d from Execute"
985
986 assert(resume_pc.microPC() == 0);
987
988 DPRINTF(MinorInterrupt, "Suspending thread: %d from Execute"
979 " inst: %s\n", inst->id.threadId, *inst);
989 " inst: %s\n", thread_id, *inst);
980
981 cpu.stats.numFetchSuspends++;
982
990
991 cpu.stats.numFetchSuspends++;
992
983 updateBranchData(BranchData::SuspendThread, inst, resume_pc,
984 branch);
993 updateBranchData(thread_id, BranchData::SuspendThread, inst,
994 resume_pc, branch);
985 }
986 }
987
988 return completed_inst;
989}
990
991void
995 }
996 }
997
998 return completed_inst;
999}
1000
1001void
992Execute::commit(bool only_commit_microops, bool discard, BranchData &branch)
1002Execute::commit(ThreadID thread_id, bool only_commit_microops, bool discard,
1003 BranchData &branch)
993{
994 Fault fault = NoFault;
995 Cycles now = cpu.curCycle();
1004{
1005 Fault fault = NoFault;
1006 Cycles now = cpu.curCycle();
1007 ExecuteThreadInfo &ex_info = executeInfo[thread_id];
996
997 /**
998 * Try and execute as many instructions from the end of FU pipelines as
999 * possible. This *doesn't* include actually advancing the pipelines.
1000 *
1001 * We do this by looping on the front of the inFlightInsts queue for as
1002 * long as we can find the desired instruction at the end of the
1003 * functional unit it was issued to without seeing a branch or a fault.

--- 21 unchanged lines hidden (view full) ---

1025
1026 /* Number of insts committed this cycle to check against commitLimit */
1027 unsigned int num_insts_committed = 0;
1028
1029 /* Number of memory access instructions committed to check against
1030 * memCommitLimit */
1031 unsigned int num_mem_refs_committed = 0;
1032
1008
1009 /**
1010 * Try and execute as many instructions from the end of FU pipelines as
1011 * possible. This *doesn't* include actually advancing the pipelines.
1012 *
1013 * We do this by looping on the front of the inFlightInsts queue for as
1014 * long as we can find the desired instruction at the end of the
1015 * functional unit it was issued to without seeing a branch or a fault.

--- 21 unchanged lines hidden (view full) ---

1037
1038 /* Number of insts committed this cycle to check against commitLimit */
1039 unsigned int num_insts_committed = 0;
1040
1041 /* Number of memory access instructions committed to check against
1042 * memCommitLimit */
1043 unsigned int num_mem_refs_committed = 0;
1044
1033 if (only_commit_microops && !inFlightInsts->empty()) {
1045 if (only_commit_microops && !ex_info.inFlightInsts->empty()) {
1034 DPRINTF(MinorInterrupt, "Only commit microops %s %d\n",
1046 DPRINTF(MinorInterrupt, "Only commit microops %s %d\n",
1035 *(inFlightInsts->front().inst),
1036 lastCommitWasEndOfMacroop);
1047 *(ex_info.inFlightInsts->front().inst),
1048 ex_info.lastCommitWasEndOfMacroop);
1037 }
1038
1049 }
1050
1039 while (!inFlightInsts->empty() && /* Some more instructions to process */
1051 while (!ex_info.inFlightInsts->empty() && /* Some more instructions to process */
1040 !branch.isStreamChange() && /* No real branch */
1041 fault == NoFault && /* No faults */
1042 completed_inst && /* Still finding instructions to execute */
1043 num_insts_committed != commitLimit /* Not reached commit limit */
1044 )
1045 {
1046 if (only_commit_microops) {
1047 DPRINTF(MinorInterrupt, "Committing tail of insts before"
1048 " interrupt: %s\n",
1052 !branch.isStreamChange() && /* No real branch */
1053 fault == NoFault && /* No faults */
1054 completed_inst && /* Still finding instructions to execute */
1055 num_insts_committed != commitLimit /* Not reached commit limit */
1056 )
1057 {
1058 if (only_commit_microops) {
1059 DPRINTF(MinorInterrupt, "Committing tail of insts before"
1060 " interrupt: %s\n",
1049 *(inFlightInsts->front().inst));
1061 *(ex_info.inFlightInsts->front().inst));
1050 }
1051
1062 }
1063
1052 QueuedInst *head_inflight_inst = &(inFlightInsts->front());
1064 QueuedInst *head_inflight_inst = &(ex_info.inFlightInsts->front());
1053
1054 InstSeqNum head_exec_seq_num =
1055 head_inflight_inst->inst->id.execSeqNum;
1056
1057 /* The instruction we actually process if completed_inst
1058 * remains true to the end of the loop body.
1059 * Start by considering the the head of the in flight insts queue */
1060 MinorDynInstPtr inst = head_inflight_inst->inst;

--- 5 unchanged lines hidden (view full) ---

1066 bool early_memory_issue = false;
1067
1068 /* Must set this again to go around the loop */
1069 completed_inst = false;
1070
1071 /* If we're just completing a macroop before an interrupt or drain,
1072 * can we stil commit another microop (rather than a memory response)
1073 * without crosing into the next full instruction? */
1065
1066 InstSeqNum head_exec_seq_num =
1067 head_inflight_inst->inst->id.execSeqNum;
1068
1069 /* The instruction we actually process if completed_inst
1070 * remains true to the end of the loop body.
1071 * Start by considering the the head of the in flight insts queue */
1072 MinorDynInstPtr inst = head_inflight_inst->inst;

--- 5 unchanged lines hidden (view full) ---

1078 bool early_memory_issue = false;
1079
1080 /* Must set this again to go around the loop */
1081 completed_inst = false;
1082
1083 /* If we're just completing a macroop before an interrupt or drain,
1084 * can we stil commit another microop (rather than a memory response)
1085 * without crosing into the next full instruction? */
1074 bool can_commit_insts = !inFlightInsts->empty() &&
1075 !(only_commit_microops && lastCommitWasEndOfMacroop);
1086 bool can_commit_insts = !ex_info.inFlightInsts->empty() &&
1087 !(only_commit_microops && ex_info.lastCommitWasEndOfMacroop);
1076
1077 /* Can we find a mem response for this inst */
1078 LSQ::LSQRequestPtr mem_response =
1079 (inst->inLSQ ? lsq.findResponse(inst) : NULL);
1080
1081 DPRINTF(MinorExecute, "Trying to commit canCommitInsts: %d\n",
1082 can_commit_insts);
1083
1084 /* Test for PC events after every instruction */
1088
1089 /* Can we find a mem response for this inst */
1090 LSQ::LSQRequestPtr mem_response =
1091 (inst->inLSQ ? lsq.findResponse(inst) : NULL);
1092
1093 DPRINTF(MinorExecute, "Trying to commit canCommitInsts: %d\n",
1094 can_commit_insts);
1095
1096 /* Test for PC events after every instruction */
1085 if (isInbetweenInsts() && tryPCEvents()) {
1086 ThreadContext *thread = cpu.getContext(0);
1097 if (isInbetweenInsts(thread_id) && tryPCEvents(thread_id)) {
1098 ThreadContext *thread = cpu.getContext(thread_id);
1087
1088 /* Branch as there was a change in PC */
1099
1100 /* Branch as there was a change in PC */
1089 updateBranchData(BranchData::UnpredictedBranch,
1101 updateBranchData(thread_id, BranchData::UnpredictedBranch,
1090 MinorDynInst::bubble(), thread->pcState(), branch);
1091 } else if (mem_response &&
1092 num_mem_refs_committed < memoryCommitLimit)
1093 {
1094 /* Try to commit from the memory responses next */
1102 MinorDynInst::bubble(), thread->pcState(), branch);
1103 } else if (mem_response &&
1104 num_mem_refs_committed < memoryCommitLimit)
1105 {
1106 /* Try to commit from the memory responses next */
1095 discard_inst = inst->id.streamSeqNum != streamSeqNum ||
1096 discard;
1107 discard_inst = inst->id.streamSeqNum !=
1108 ex_info.streamSeqNum || discard;
1097
1098 DPRINTF(MinorExecute, "Trying to commit mem response: %s\n",
1099 *inst);
1100
1101 /* Complete or discard the response */
1102 if (discard_inst) {
1103 DPRINTF(MinorExecute, "Discarding mem inst: %s as its"
1104 " stream state was unexpected, expected: %d\n",
1109
1110 DPRINTF(MinorExecute, "Trying to commit mem response: %s\n",
1111 *inst);
1112
1113 /* Complete or discard the response */
1114 if (discard_inst) {
1115 DPRINTF(MinorExecute, "Discarding mem inst: %s as its"
1116 " stream state was unexpected, expected: %d\n",
1105 *inst, streamSeqNum);
1117 *inst, ex_info.streamSeqNum);
1106
1107 lsq.popResponse(mem_response);
1108 } else {
1109 handleMemResponse(inst, mem_response, branch, fault);
1110 committed_inst = true;
1111 }
1112
1113 completed_mem_ref = true;

--- 9 unchanged lines hidden (view full) ---

1123 * - Can push a request into the LSQ
1124 * - Have reached the end of their FUs
1125 * - Have had all their dependencies satisfied
1126 * - Are from the right stream
1127 *
1128 * For any other case, leave it to the normal instruction
1129 * issue below to handle them.
1130 */
1118
1119 lsq.popResponse(mem_response);
1120 } else {
1121 handleMemResponse(inst, mem_response, branch, fault);
1122 committed_inst = true;
1123 }
1124
1125 completed_mem_ref = true;

--- 9 unchanged lines hidden (view full) ---

1135 * - Can push a request into the LSQ
1136 * - Have reached the end of their FUs
1137 * - Have had all their dependencies satisfied
1138 * - Are from the right stream
1139 *
1140 * For any other case, leave it to the normal instruction
1141 * issue below to handle them.
1142 */
1131 if (!inFUMemInsts->empty() && lsq.canRequest()) {
1143 if (!ex_info.inFUMemInsts->empty() && lsq.canRequest()) {
1132 DPRINTF(MinorExecute, "Trying to commit from mem FUs\n");
1133
1134 const MinorDynInstPtr head_mem_ref_inst =
1144 DPRINTF(MinorExecute, "Trying to commit from mem FUs\n");
1145
1146 const MinorDynInstPtr head_mem_ref_inst =
1135 inFUMemInsts->front().inst;
1147 ex_info.inFUMemInsts->front().inst;
1136 FUPipeline *fu = funcUnits[head_mem_ref_inst->fuIndex];
1137 const MinorDynInstPtr &fu_inst = fu->front().inst;
1138
1139 /* Use this, possibly out of order, inst as the one
1140 * to 'commit'/send to the LSQ */
1141 if (!fu_inst->isBubble() &&
1142 !fu_inst->inLSQ &&
1143 fu_inst->canEarlyIssue &&
1148 FUPipeline *fu = funcUnits[head_mem_ref_inst->fuIndex];
1149 const MinorDynInstPtr &fu_inst = fu->front().inst;
1150
1151 /* Use this, possibly out of order, inst as the one
1152 * to 'commit'/send to the LSQ */
1153 if (!fu_inst->isBubble() &&
1154 !fu_inst->inLSQ &&
1155 fu_inst->canEarlyIssue &&
1144 streamSeqNum == fu_inst->id.streamSeqNum &&
1156 ex_info.streamSeqNum == fu_inst->id.streamSeqNum &&
1145 head_exec_seq_num > fu_inst->instToWaitFor)
1146 {
1147 DPRINTF(MinorExecute, "Issuing mem ref early"
1148 " inst: %s instToWaitFor: %d\n",
1149 *(fu_inst), fu_inst->instToWaitFor);
1150
1151 inst = fu_inst;
1152 try_to_commit = true;

--- 26 unchanged lines hidden (view full) ---

1179 /* No instruction ready */
1180 completed_inst = false;
1181 } else if (fu_inst_seq_num != head_exec_seq_num) {
1182 /* Past instruction: we must have already executed it
1183 * in the same cycle and so the head inst isn't
1184 * actually at the end of its pipeline
1185 * Future instruction: handled above and only for
1186 * mem refs on their way to the LSQ */
1157 head_exec_seq_num > fu_inst->instToWaitFor)
1158 {
1159 DPRINTF(MinorExecute, "Issuing mem ref early"
1160 " inst: %s instToWaitFor: %d\n",
1161 *(fu_inst), fu_inst->instToWaitFor);
1162
1163 inst = fu_inst;
1164 try_to_commit = true;

--- 26 unchanged lines hidden (view full) ---

1191 /* No instruction ready */
1192 completed_inst = false;
1193 } else if (fu_inst_seq_num != head_exec_seq_num) {
1194 /* Past instruction: we must have already executed it
1195 * in the same cycle and so the head inst isn't
1196 * actually at the end of its pipeline
1197 * Future instruction: handled above and only for
1198 * mem refs on their way to the LSQ */
1187 } else /* if (fu_inst_seq_num == head_exec_seq_num) */ {
1199 } else if (fu_inst.inst->id == inst->id) {
1188 /* All instructions can be committed if they have the
1189 * right execSeqNum and there are no in-flight
1190 * mem insts before us */
1191 try_to_commit = true;
1192 completed_inst = true;
1193 }
1194 }
1195
1196 if (try_to_commit) {
1200 /* All instructions can be committed if they have the
1201 * right execSeqNum and there are no in-flight
1202 * mem insts before us */
1203 try_to_commit = true;
1204 completed_inst = true;
1205 }
1206 }
1207
1208 if (try_to_commit) {
1197 discard_inst = inst->id.streamSeqNum != streamSeqNum ||
1198 discard;
1209 discard_inst = inst->id.streamSeqNum !=
1210 ex_info.streamSeqNum || discard;
1199
1200 /* Is this instruction discardable as its streamSeqNum
1201 * doesn't match? */
1202 if (!discard_inst) {
1203 /* Try to commit or discard a non-memory instruction.
1204 * Memory ops are actually 'committed' from this FUs
1205 * and 'issued' into the memory system so we need to
1206 * account for them later (commit_was_mem_issue gets
1207 * set) */
1208 if (inst->extraCommitDelayExpr) {
1209 DPRINTF(MinorExecute, "Evaluating expression for"
1210 " extra commit delay inst: %s\n", *inst);
1211
1211
1212 /* Is this instruction discardable as its streamSeqNum
1213 * doesn't match? */
1214 if (!discard_inst) {
1215 /* Try to commit or discard a non-memory instruction.
1216 * Memory ops are actually 'committed' from this FUs
1217 * and 'issued' into the memory system so we need to
1218 * account for them later (commit_was_mem_issue gets
1219 * set) */
1220 if (inst->extraCommitDelayExpr) {
1221 DPRINTF(MinorExecute, "Evaluating expression for"
1222 " extra commit delay inst: %s\n", *inst);
1223
1212 ThreadContext *thread =
1213 cpu.getContext(inst->id.threadId);
1224 ThreadContext *thread = cpu.getContext(thread_id);
1214
1215 TimingExprEvalContext context(inst->staticInst,
1216 thread, NULL);
1217
1218 uint64_t extra_delay = inst->extraCommitDelayExpr->
1219 eval(context);
1220
1221 DPRINTF(MinorExecute, "Extra commit delay expr"

--- 14 unchanged lines hidden (view full) ---

1236 inst->minimumCommitCycle = cpu.curCycle() +
1237 inst->extraCommitDelay;
1238 inst->extraCommitDelay = Cycles(0);
1239 }
1240
1241 /* @todo Think about making lastMemBarrier be
1242 * MAX_UINT_64 to avoid using 0 as a marker value */
1243 if (!inst->isFault() && inst->isMemRef() &&
1225
1226 TimingExprEvalContext context(inst->staticInst,
1227 thread, NULL);
1228
1229 uint64_t extra_delay = inst->extraCommitDelayExpr->
1230 eval(context);
1231
1232 DPRINTF(MinorExecute, "Extra commit delay expr"

--- 14 unchanged lines hidden (view full) ---

1247 inst->minimumCommitCycle = cpu.curCycle() +
1248 inst->extraCommitDelay;
1249 inst->extraCommitDelay = Cycles(0);
1250 }
1251
1252 /* @todo Think about making lastMemBarrier be
1253 * MAX_UINT_64 to avoid using 0 as a marker value */
1254 if (!inst->isFault() && inst->isMemRef() &&
1244 lsq.getLastMemBarrier() <
1255 lsq.getLastMemBarrier(thread_id) <
1245 inst->id.execSeqNum &&
1256 inst->id.execSeqNum &&
1246 lsq.getLastMemBarrier() != 0)
1257 lsq.getLastMemBarrier(thread_id) != 0)
1247 {
1248 DPRINTF(MinorExecute, "Not committing inst: %s yet"
1249 " as there are incomplete barriers in flight\n",
1250 *inst);
1251 completed_inst = false;
1252 } else if (inst->minimumCommitCycle > now) {
1253 DPRINTF(MinorExecute, "Not committing inst: %s yet"
1254 " as it wants to be stalled for %d more cycles\n",

--- 9 unchanged lines hidden (view full) ---

1264 completed_inst = true;
1265 }
1266
1267 if (completed_inst) {
1268 /* Allow the pipeline to advance. If the FU head
1269 * instruction wasn't the inFlightInsts head
1270 * but had already been committed, it would have
1271 * unstalled the pipeline before here */
1258 {
1259 DPRINTF(MinorExecute, "Not committing inst: %s yet"
1260 " as there are incomplete barriers in flight\n",
1261 *inst);
1262 completed_inst = false;
1263 } else if (inst->minimumCommitCycle > now) {
1264 DPRINTF(MinorExecute, "Not committing inst: %s yet"
1265 " as it wants to be stalled for %d more cycles\n",

--- 9 unchanged lines hidden (view full) ---

1275 completed_inst = true;
1276 }
1277
1278 if (completed_inst) {
1279 /* Allow the pipeline to advance. If the FU head
1280 * instruction wasn't the inFlightInsts head
1281 * but had already been committed, it would have
1282 * unstalled the pipeline before here */
1272 if (inst->fuIndex != noCostFUIndex)
1283 if (inst->fuIndex != noCostFUIndex) {
1284 DPRINTF(MinorExecute, "Unstalling %d for inst %s\n", inst->fuIndex, inst->id);
1273 funcUnits[inst->fuIndex]->stalled = false;
1285 funcUnits[inst->fuIndex]->stalled = false;
1286 }
1274 }
1275 }
1276 } else {
1277 DPRINTF(MinorExecute, "No instructions to commit\n");
1278 completed_inst = false;
1279 }
1280
1281 /* All discardable instructions must also be 'completed' by now */
1282 assert(!(discard_inst && !completed_inst));
1283
1284 /* Instruction committed but was discarded due to streamSeqNum
1285 * mismatch */
1286 if (discard_inst) {
1287 DPRINTF(MinorExecute, "Discarding inst: %s as its stream"
1288 " state was unexpected, expected: %d\n",
1287 }
1288 }
1289 } else {
1290 DPRINTF(MinorExecute, "No instructions to commit\n");
1291 completed_inst = false;
1292 }
1293
1294 /* All discardable instructions must also be 'completed' by now */
1295 assert(!(discard_inst && !completed_inst));
1296
1297 /* Instruction committed but was discarded due to streamSeqNum
1298 * mismatch */
1299 if (discard_inst) {
1300 DPRINTF(MinorExecute, "Discarding inst: %s as its stream"
1301 " state was unexpected, expected: %d\n",
1289 *inst, streamSeqNum);
1302 *inst, ex_info.streamSeqNum);
1290
1291 if (fault == NoFault)
1292 cpu.stats.numDiscardedOps++;
1293 }
1294
1295 /* Mark the mem inst as being in the LSQ */
1296 if (issued_mem_ref) {
1297 inst->fuIndex = 0;
1298 inst->inLSQ = true;
1299 }
1300
1301 /* Pop issued (to LSQ) and discarded mem refs from the inFUMemInsts
1302 * as they've *definitely* exited the FUs */
1303 if (completed_inst && inst->isMemRef()) {
1304 /* The MemRef could have been discarded from the FU or the memory
1305 * queue, so just check an FU instruction */
1303
1304 if (fault == NoFault)
1305 cpu.stats.numDiscardedOps++;
1306 }
1307
1308 /* Mark the mem inst as being in the LSQ */
1309 if (issued_mem_ref) {
1310 inst->fuIndex = 0;
1311 inst->inLSQ = true;
1312 }
1313
1314 /* Pop issued (to LSQ) and discarded mem refs from the inFUMemInsts
1315 * as they've *definitely* exited the FUs */
1316 if (completed_inst && inst->isMemRef()) {
1317 /* The MemRef could have been discarded from the FU or the memory
1318 * queue, so just check an FU instruction */
1306 if (!inFUMemInsts->empty() &&
1307 inFUMemInsts->front().inst == inst)
1319 if (!ex_info.inFUMemInsts->empty() &&
1320 ex_info.inFUMemInsts->front().inst == inst)
1308 {
1321 {
1309 inFUMemInsts->pop();
1322 ex_info.inFUMemInsts->pop();
1310 }
1311 }
1312
1313 if (completed_inst && !(issued_mem_ref && fault == NoFault)) {
1314 /* Note that this includes discarded insts */
1315 DPRINTF(MinorExecute, "Completed inst: %s\n", *inst);
1316
1317 /* Got to the end of a full instruction? */
1323 }
1324 }
1325
1326 if (completed_inst && !(issued_mem_ref && fault == NoFault)) {
1327 /* Note that this includes discarded insts */
1328 DPRINTF(MinorExecute, "Completed inst: %s\n", *inst);
1329
1330 /* Got to the end of a full instruction? */
1318 lastCommitWasEndOfMacroop = inst->isFault() ||
1331 ex_info.lastCommitWasEndOfMacroop = inst->isFault() ||
1319 inst->isLastOpInInst();
1320
1321 /* lastPredictionSeqNum is kept as a convenience to prevent its
1322 * value from changing too much on the minorview display */
1332 inst->isLastOpInInst();
1333
1334 /* lastPredictionSeqNum is kept as a convenience to prevent its
1335 * value from changing too much on the minorview display */
1323 lastPredictionSeqNum = inst->id.predictionSeqNum;
1336 ex_info.lastPredictionSeqNum = inst->id.predictionSeqNum;
1324
1325 /* Finished with the inst, remove it from the inst queue and
1326 * clear its dependencies */
1337
1338 /* Finished with the inst, remove it from the inst queue and
1339 * clear its dependencies */
1327 inFlightInsts->pop();
1340 ex_info.inFlightInsts->pop();
1328
1329 /* Complete barriers in the LSQ/move to store buffer */
1330 if (inst->isInst() && inst->staticInst->isMemBarrier()) {
1331 DPRINTF(MinorMem, "Completing memory barrier"
1332 " inst: %s committed: %d\n", *inst, committed_inst);
1333 lsq.completeMemBarrierInst(inst, committed_inst);
1334 }
1335
1341
1342 /* Complete barriers in the LSQ/move to store buffer */
1343 if (inst->isInst() && inst->staticInst->isMemBarrier()) {
1344 DPRINTF(MinorMem, "Completing memory barrier"
1345 " inst: %s committed: %d\n", *inst, committed_inst);
1346 lsq.completeMemBarrierInst(inst, committed_inst);
1347 }
1348
1336 scoreboard.clearInstDests(inst, inst->isMemRef());
1349 scoreboard[thread_id].clearInstDests(inst, inst->isMemRef());
1337 }
1338
1339 /* Handle per-cycle instruction counting */
1340 if (committed_inst) {
1341 bool is_no_cost_inst = inst->isNoCostInst();
1342
1343 /* Don't show no cost instructions as having taken a commit
1344 * slot */
1345 if (DTRACE(MinorTrace) && !is_no_cost_inst)
1350 }
1351
1352 /* Handle per-cycle instruction counting */
1353 if (committed_inst) {
1354 bool is_no_cost_inst = inst->isNoCostInst();
1355
1356 /* Don't show no cost instructions as having taken a commit
1357 * slot */
1358 if (DTRACE(MinorTrace) && !is_no_cost_inst)
1346 instsBeingCommitted.insts[num_insts_committed] = inst;
1359 ex_info.instsBeingCommitted.insts[num_insts_committed] = inst;
1347
1348 if (!is_no_cost_inst)
1349 num_insts_committed++;
1350
1351 if (num_insts_committed == commitLimit)
1352 DPRINTF(MinorExecute, "Reached inst commit limit\n");
1353
1354 /* Re-set the time of the instruction if that's required for

--- 9 unchanged lines hidden (view full) ---

1364
1365 if (num_mem_refs_committed == memoryCommitLimit)
1366 DPRINTF(MinorExecute, "Reached mem ref commit limit\n");
1367 }
1368 }
1369}
1370
1371bool
1360
1361 if (!is_no_cost_inst)
1362 num_insts_committed++;
1363
1364 if (num_insts_committed == commitLimit)
1365 DPRINTF(MinorExecute, "Reached inst commit limit\n");
1366
1367 /* Re-set the time of the instruction if that's required for

--- 9 unchanged lines hidden (view full) ---

1377
1378 if (num_mem_refs_committed == memoryCommitLimit)
1379 DPRINTF(MinorExecute, "Reached mem ref commit limit\n");
1380 }
1381 }
1382}
1383
1384bool
1372Execute::isInbetweenInsts() const
1385Execute::isInbetweenInsts(ThreadID thread_id) const
1373{
1386{
1374 return lastCommitWasEndOfMacroop &&
1387 return executeInfo[thread_id].lastCommitWasEndOfMacroop &&
1375 !lsq.accessesInFlight();
1376}
1377
1378void
1379Execute::evaluate()
1380{
1388 !lsq.accessesInFlight();
1389}
1390
1391void
1392Execute::evaluate()
1393{
1381 inputBuffer.setTail(*inp.outputWire);
1394 if (!inp.outputWire->isBubble())
1395 inputBuffer[inp.outputWire->threadId].setTail(*inp.outputWire);
1396
1382 BranchData &branch = *out.inputWire;
1383
1397 BranchData &branch = *out.inputWire;
1398
1384 const ForwardInstData *insts_in = getInput();
1399 unsigned int num_issued = 0;
1385
1386 /* Do all the cycle-wise activities for dcachePort here to potentially
1387 * free up input spaces in the LSQ's requests queue */
1388 lsq.step();
1389
1400
1401 /* Do all the cycle-wise activities for dcachePort here to potentially
1402 * free up input spaces in the LSQ's requests queue */
1403 lsq.step();
1404
1390 /* Has an interrupt been signalled? This may not be acted on
1391 * straighaway so this is different from took_interrupt below */
1405 /* Check interrupts first. Will halt commit if interrupt found */
1392 bool interrupted = false;
1406 bool interrupted = false;
1393 /* If there was an interrupt signalled, was it acted on now? */
1394 bool took_interrupt = false;
1407 ThreadID interrupt_tid = checkInterrupts(branch, interrupted);
1395
1408
1396 if (cpu.getInterruptController(0)) {
1397 /* This is here because it seems that after drainResume the
1398 * interrupt controller isn't always set */
1399 interrupted = drainState == NotDraining && isInterrupted(0);
1400 } else {
1401 DPRINTF(MinorInterrupt, "No interrupt controller\n");
1402 }
1403
1404 unsigned int num_issued = 0;
1405
1406 if (DTRACE(MinorTrace)) {
1407 /* Empty the instsBeingCommitted for MinorTrace */
1408 instsBeingCommitted.bubbleFill();
1409 }
1410
1411 /* THREAD threadId on isInterrupted */
1412 /* Act on interrupts */
1413 if (interrupted && isInbetweenInsts()) {
1414 took_interrupt = takeInterrupt(0, branch);
1415 /* Clear interrupted if no interrupt was actually waiting */
1416 interrupted = took_interrupt;
1417 }
1418
1419 if (took_interrupt) {
1420 /* Do no commit/issue this cycle */
1409 if (interrupt_tid != InvalidThreadID) {
1410 /* Signalling an interrupt this cycle, not issuing/committing from
1411 * any other threads */
1421 } else if (!branch.isBubble()) {
1422 /* It's important that this is here to carry Fetch1 wakeups to Fetch1
1423 * without overwriting them */
1424 DPRINTF(MinorInterrupt, "Execute skipping a cycle to allow old"
1425 " branch to complete\n");
1426 } else {
1412 } else if (!branch.isBubble()) {
1413 /* It's important that this is here to carry Fetch1 wakeups to Fetch1
1414 * without overwriting them */
1415 DPRINTF(MinorInterrupt, "Execute skipping a cycle to allow old"
1416 " branch to complete\n");
1417 } else {
1427 if (interrupted) {
1428 if (inFlightInsts->empty()) {
1429 DPRINTF(MinorInterrupt, "Waiting but no insts\n");
1418 ThreadID commit_tid = getCommittingThread();
1419
1420 if (commit_tid != InvalidThreadID) {
1421 ExecuteThreadInfo& commit_info = executeInfo[commit_tid];
1422
1423 DPRINTF(MinorExecute, "Attempting to commit [tid:%d]\n",
1424 commit_tid);
1425 /* commit can set stalled flags observable to issue and so *must* be
1426 * called first */
1427 if (commit_info.drainState != NotDraining) {
1428 if (commit_info.drainState == DrainCurrentInst) {
1429 /* Commit only micro-ops, don't kill anything else */
1430 commit(commit_tid, true, false, branch);
1431
1432 if (isInbetweenInsts(commit_tid))
1433 setDrainState(commit_tid, DrainHaltFetch);
1434
1435 /* Discard any generated branch */
1436 branch = BranchData::bubble();
1437 } else if (commit_info.drainState == DrainAllInsts) {
1438 /* Kill all instructions */
1439 while (getInput(commit_tid))
1440 popInput(commit_tid);
1441 commit(commit_tid, false, true, branch);
1442 }
1430 } else {
1443 } else {
1431 DPRINTF(MinorInterrupt, "Waiting for end of inst before"
1432 " signalling interrupt\n");
1444 /* Commit micro-ops only if interrupted. Otherwise, commit
1445 * anything you like */
1446 DPRINTF(MinorExecute, "Committing micro-ops for interrupt[tid:%d]\n",
1447 commit_tid);
1448 bool only_commit_microops = interrupted &&
1449 hasInterrupt(commit_tid);
1450 commit(commit_tid, only_commit_microops, false, branch);
1433 }
1451 }
1434 }
1435
1452
1436 /* commit can set stalled flags observable to issue and so *must* be
1437 * called first */
1438 if (drainState != NotDraining) {
1439 if (drainState == DrainCurrentInst) {
1440 /* Commit only micro-ops, don't kill anything else */
1441 commit(true, false, branch);
1453 /* Halt fetch, but don't do it until we have the current instruction in
1454 * the bag */
1455 if (commit_info.drainState == DrainHaltFetch) {
1456 updateBranchData(commit_tid, BranchData::HaltFetch,
1457 MinorDynInst::bubble(), TheISA::PCState(0), branch);
1442
1458
1443 if (isInbetweenInsts())
1444 setDrainState(DrainHaltFetch);
1445
1446 /* Discard any generated branch */
1447 branch = BranchData::bubble();
1448 } else if (drainState == DrainAllInsts) {
1449 /* Kill all instructions */
1450 while (getInput())
1451 popInput();
1452 commit(false, true, branch);
1459 cpu.wakeupOnEvent(Pipeline::ExecuteStageId);
1460 setDrainState(commit_tid, DrainAllInsts);
1453 }
1461 }
1454 } else {
1455 /* Commit micro-ops only if interrupted. Otherwise, commit
1456 * anything you like */
1457 commit(interrupted, false, branch);
1458 }
1462 }
1459
1463 ThreadID issue_tid = getIssuingThread();
1460 /* This will issue merrily even when interrupted in the sure and
1461 * certain knowledge that the interrupt with change the stream */
1464 /* This will issue merrily even when interrupted in the sure and
1465 * certain knowledge that the interrupt with change the stream */
1462 if (insts_in)
1463 num_issued = issue(false);
1464 }
1466 if (issue_tid != InvalidThreadID) {
1467 DPRINTF(MinorExecute, "Attempting to issue [tid:%d]\n",
1468 issue_tid);
1469 num_issued = issue(issue_tid);
1470 }
1465
1471
1466 /* Halt fetch, but don't do it until we have the current instruction in
1467 * the bag */
1468 if (drainState == DrainHaltFetch) {
1469 updateBranchData(BranchData::HaltFetch, MinorDynInst::bubble(),
1470 TheISA::PCState(0), branch);
1471
1472 cpu.wakeupOnEvent(Pipeline::ExecuteStageId);
1473 setDrainState(DrainAllInsts);
1474 }
1475
1472 }
1473
1476 MinorDynInstPtr next_issuable_inst = NULL;
1474 /* Run logic to step functional units + decide if we are active on the next
1475 * clock cycle */
1476 std::vector<MinorDynInstPtr> next_issuable_insts;
1477 bool can_issue_next = false;
1478
1477 bool can_issue_next = false;
1478
1479 /* Find the next issuable instruction and see if it can be issued */
1480 if (getInput()) {
1481 MinorDynInstPtr inst = getInput()->insts[inputIndex];
1482
1483 if (inst->isFault()) {
1484 can_issue_next = true;
1485 } else if (!inst->isBubble()) {
1486 if (cpu.getContext(inst->id.threadId)->status() !=
1487 ThreadContext::Suspended)
1488 {
1489 next_issuable_inst = inst;
1479 for (ThreadID tid = 0; tid < cpu.numThreads; tid++) {
1480 /* Find the next issuable instruction for each thread and see if it can
1481 be issued */
1482 if (getInput(tid)) {
1483 unsigned int input_index = executeInfo[tid].inputIndex;
1484 MinorDynInstPtr inst = getInput(tid)->insts[input_index];
1485 if (inst->isFault()) {
1486 can_issue_next = true;
1487 } else if (!inst->isBubble()) {
1488 if (cpu.getContext(tid)->status() != ThreadContext::Suspended) {
1489 next_issuable_insts.push_back(inst);
1490 }
1490 }
1491 }
1492 }
1493
1494 bool becoming_stalled = true;
1495
1496 /* Advance the pipelines and note whether they still need to be
1491 }
1492 }
1493 }
1494
1495 bool becoming_stalled = true;
1496
1497 /* Advance the pipelines and note whether they still need to be
1497 * advanced */
1498 * advanced */
1498 for (unsigned int i = 0; i < numFuncUnits; i++) {
1499 FUPipeline *fu = funcUnits[i];
1499 for (unsigned int i = 0; i < numFuncUnits; i++) {
1500 FUPipeline *fu = funcUnits[i];
1500
1501 fu->advance();
1502
1501 fu->advance();
1502
1503 /* If we need to go again, the pipeline will have been left or set
1504 * to be unstalled */
1505 if (fu->occupancy != 0 && !fu->stalled)
1503 /* If we need to tick again, the pipeline will have been left or set
1504 * to be unstalled */
1505 if (fu->occupancy !=0 && !fu->stalled)
1506 becoming_stalled = false;
1507
1506 becoming_stalled = false;
1507
1508 /* Could we possibly issue the next instruction? This is quite
1509 * an expensive test */
1510 if (next_issuable_inst && !fu->stalled &&
1511 scoreboard.canInstIssue(next_issuable_inst,
1512 NULL, NULL, cpu.curCycle() + Cycles(1),
1513 cpu.getContext(next_issuable_inst->id.threadId)) &&
1514 fu->provides(next_issuable_inst->staticInst->opClass()))
1515 {
1516 can_issue_next = true;
1508 /* Could we possibly issue the next instruction from any thread?
1509 * This is quite an expensive test and is only used to determine
1510 * if the CPU should remain active, only run it if we aren't sure
1511 * we are active next cycle yet */
1512 for (auto inst : next_issuable_insts) {
1513 if (!fu->stalled && fu->provides(inst->staticInst->opClass()) &&
1514 scoreboard[inst->id.threadId].canInstIssue(inst,
1515 NULL, NULL, cpu.curCycle() + Cycles(1),
1516 cpu.getContext(inst->id.threadId))) {
1517 can_issue_next = true;
1518 break;
1519 }
1517 }
1518 }
1519
1520 bool head_inst_might_commit = false;
1521
1522 /* Could the head in flight insts be committed */
1520 }
1521 }
1522
1523 bool head_inst_might_commit = false;
1524
1525 /* Could the head in flight insts be committed */
1523 if (!inFlightInsts->empty()) {
1524 const QueuedInst &head_inst = inFlightInsts->front();
1526 for (auto const &info : executeInfo) {
1527 if (!info.inFlightInsts->empty()) {
1528 const QueuedInst &head_inst = info.inFlightInsts->front();
1525
1529
1526 if (head_inst.inst->isNoCostInst()) {
1527 head_inst_might_commit = true;
1528 } else {
1529 FUPipeline *fu = funcUnits[head_inst.inst->fuIndex];
1530
1531 /* Head inst is commitable */
1532 if ((fu->stalled &&
1533 fu->front().inst->id == head_inst.inst->id) ||
1534 lsq.findResponse(head_inst.inst))
1535 {
1530 if (head_inst.inst->isNoCostInst()) {
1536 head_inst_might_commit = true;
1531 head_inst_might_commit = true;
1532 } else {
1533 FUPipeline *fu = funcUnits[head_inst.inst->fuIndex];
1534 if ((fu->stalled &&
1535 fu->front().inst->id == head_inst.inst->id) ||
1536 lsq.findResponse(head_inst.inst))
1537 {
1538 head_inst_might_commit = true;
1539 break;
1540 }
1537 }
1538 }
1539 }
1540
1541 DPRINTF(Activity, "Need to tick num issued insts: %s%s%s%s%s%s\n",
1542 (num_issued != 0 ? " (issued some insts)" : ""),
1541 }
1542 }
1543 }
1544
1545 DPRINTF(Activity, "Need to tick num issued insts: %s%s%s%s%s%s\n",
1546 (num_issued != 0 ? " (issued some insts)" : ""),
1543 (becoming_stalled ? " (becoming stalled)" : "(not becoming stalled)"),
1547 (becoming_stalled ? "(becoming stalled)" : "(not becoming stalled)"),
1544 (can_issue_next ? " (can issued next inst)" : ""),
1545 (head_inst_might_commit ? "(head inst might commit)" : ""),
1546 (lsq.needsToTick() ? " (LSQ needs to tick)" : ""),
1547 (interrupted ? " (interrupted)" : ""));
1548
1549 bool need_to_tick =
1550 num_issued != 0 || /* Issued some insts this cycle */
1551 !becoming_stalled || /* Some FU pipelines can still move */

--- 11 unchanged lines hidden (view full) ---

1563 if (need_to_tick)
1564 cpu.wakeupOnEvent(Pipeline::ExecuteStageId);
1565
1566 /* Note activity of following buffer */
1567 if (!branch.isBubble())
1568 cpu.activityRecorder->activity();
1569
1570 /* Make sure the input (if any left) is pushed */
1548 (can_issue_next ? " (can issued next inst)" : ""),
1549 (head_inst_might_commit ? "(head inst might commit)" : ""),
1550 (lsq.needsToTick() ? " (LSQ needs to tick)" : ""),
1551 (interrupted ? " (interrupted)" : ""));
1552
1553 bool need_to_tick =
1554 num_issued != 0 || /* Issued some insts this cycle */
1555 !becoming_stalled || /* Some FU pipelines can still move */

--- 11 unchanged lines hidden (view full) ---

1567 if (need_to_tick)
1568 cpu.wakeupOnEvent(Pipeline::ExecuteStageId);
1569
1570 /* Note activity of following buffer */
1571 if (!branch.isBubble())
1572 cpu.activityRecorder->activity();
1573
1574 /* Make sure the input (if any left) is pushed */
1571 inputBuffer.pushTail();
1575 if (!inp.outputWire->isBubble())
1576 inputBuffer[inp.outputWire->threadId].pushTail();
1572}
1573
1577}
1578
1574void
1575Execute::wakeupFetch(BranchData::Reason reason)
1579ThreadID
1580Execute::checkInterrupts(BranchData& branch, bool& interrupted)
1576{
1581{
1577 BranchData branch;
1578 assert(branch.isBubble());
1582 ThreadID tid = interruptPriority;
1583 /* Evaluate interrupts in round-robin based upon service */
1584 do {
1585 /* Has an interrupt been signalled? This may not be acted on
1586 * straighaway so this is different from took_interrupt */
1587 bool thread_interrupted = false;
1579
1588
1580 /* THREAD thread id */
1581 ThreadContext *thread = cpu.getContext(0);
1589 if (FullSystem && cpu.getInterruptController(tid)) {
1590 /* This is here because it seems that after drainResume the
1591 * interrupt controller isn't always set */
1592 thread_interrupted = executeInfo[tid].drainState == NotDraining &&
1593 isInterrupted(tid);
1594 interrupted = interrupted || thread_interrupted;
1595 } else {
1596 DPRINTF(MinorInterrupt, "No interrupt controller\n");
1597 }
1598 DPRINTF(MinorInterrupt, "[tid:%d] thread_interrupted?=%d isInbetweenInsts?=%d\n",
1599 tid, thread_interrupted, isInbetweenInsts(tid));
1600 /* Act on interrupts */
1601 if (thread_interrupted && isInbetweenInsts(tid)) {
1602 if (takeInterrupt(tid, branch)) {
1603 interruptPriority = tid;
1604 return tid;
1605 }
1606 } else {
1607 tid = (tid + 1) % cpu.numThreads;
1608 }
1609 } while (tid != interruptPriority);
1582
1610
1583 /* Force a branch to the current PC (which should be the next inst.) to
1584 * wake up Fetch1 */
1585 if (!branch.isStreamChange() /* No real branch already happened */) {
1586 DPRINTF(MinorInterrupt, "Waking up Fetch (via Execute) by issuing"
1587 " a branch: %s\n", thread->pcState());
1611 return InvalidThreadID;
1612}
1588
1613
1589 assert(thread->pcState().microPC() == 0);
1590
1591 updateBranchData(reason,
1592 MinorDynInst::bubble(), thread->pcState(), branch);
1593 } else {
1594 DPRINTF(MinorInterrupt, "Already branching, no need for wakeup\n");
1614bool
1615Execute::hasInterrupt(ThreadID thread_id)
1616{
1617 if (FullSystem && cpu.getInterruptController(thread_id)) {
1618 return executeInfo[thread_id].drainState == NotDraining &&
1619 isInterrupted(thread_id);
1595 }
1596
1620 }
1621
1597 *out.inputWire = branch;
1598
1599 /* Make sure we get ticked */
1600 cpu.wakeupOnEvent(Pipeline::ExecuteStageId);
1622 return false;
1601}
1602
1603void
1604Execute::minorTrace() const
1605{
1606 std::ostringstream insts;
1607 std::ostringstream stalled;
1608
1623}
1624
1625void
1626Execute::minorTrace() const
1627{
1628 std::ostringstream insts;
1629 std::ostringstream stalled;
1630
1609 instsBeingCommitted.reportData(insts);
1631 executeInfo[0].instsBeingCommitted.reportData(insts);
1610 lsq.minorTrace();
1632 lsq.minorTrace();
1611 inputBuffer.minorTrace();
1612 scoreboard.minorTrace();
1633 inputBuffer[0].minorTrace();
1634 scoreboard[0].minorTrace();
1613
1614 /* Report functional unit stalling in one string */
1615 unsigned int i = 0;
1616 while (i < numFuncUnits)
1617 {
1618 stalled << (funcUnits[i]->stalled ? '1' : 'E');
1619 i++;
1620 if (i != numFuncUnits)
1621 stalled << ',';
1622 }
1623
1624 MINORTRACE("insts=%s inputIndex=%d streamSeqNum=%d"
1625 " stalled=%s drainState=%d isInbetweenInsts=%d\n",
1635
1636 /* Report functional unit stalling in one string */
1637 unsigned int i = 0;
1638 while (i < numFuncUnits)
1639 {
1640 stalled << (funcUnits[i]->stalled ? '1' : 'E');
1641 i++;
1642 if (i != numFuncUnits)
1643 stalled << ',';
1644 }
1645
1646 MINORTRACE("insts=%s inputIndex=%d streamSeqNum=%d"
1647 " stalled=%s drainState=%d isInbetweenInsts=%d\n",
1626 insts.str(), inputIndex, streamSeqNum, stalled.str(), drainState,
1627 isInbetweenInsts());
1648 insts.str(), executeInfo[0].inputIndex, executeInfo[0].streamSeqNum,
1649 stalled.str(), executeInfo[0].drainState, isInbetweenInsts(0));
1628
1629 std::for_each(funcUnits.begin(), funcUnits.end(),
1630 std::mem_fun(&FUPipeline::minorTrace));
1631
1650
1651 std::for_each(funcUnits.begin(), funcUnits.end(),
1652 std::mem_fun(&FUPipeline::minorTrace));
1653
1632 inFlightInsts->minorTrace();
1633 inFUMemInsts->minorTrace();
1654 executeInfo[0].inFlightInsts->minorTrace();
1655 executeInfo[0].inFUMemInsts->minorTrace();
1634}
1635
1656}
1657
1658inline ThreadID
1659Execute::getCommittingThread()
1660{
1661 std::vector<ThreadID> priority_list;
1662
1663 switch (cpu.threadPolicy) {
1664 case Enums::SingleThreaded:
1665 return 0;
1666 case Enums::RoundRobin:
1667 priority_list = cpu.roundRobinPriority(commitPriority);
1668 break;
1669 case Enums::Random:
1670 priority_list = cpu.randomPriority();
1671 break;
1672 default:
1673 panic("Invalid thread policy");
1674 }
1675
1676 for (auto tid : priority_list) {
1677 ExecuteThreadInfo &ex_info = executeInfo[tid];
1678 bool can_commit_insts = !ex_info.inFlightInsts->empty();
1679 if (can_commit_insts) {
1680 QueuedInst *head_inflight_inst = &(ex_info.inFlightInsts->front());
1681 MinorDynInstPtr inst = head_inflight_inst->inst;
1682
1683 can_commit_insts = can_commit_insts &&
1684 (!inst->inLSQ || (lsq.findResponse(inst) != NULL));
1685
1686 if (!inst->inLSQ) {
1687 bool can_transfer_mem_inst = false;
1688 if (!ex_info.inFUMemInsts->empty() && lsq.canRequest()) {
1689 const MinorDynInstPtr head_mem_ref_inst =
1690 ex_info.inFUMemInsts->front().inst;
1691 FUPipeline *fu = funcUnits[head_mem_ref_inst->fuIndex];
1692 const MinorDynInstPtr &fu_inst = fu->front().inst;
1693 can_transfer_mem_inst =
1694 !fu_inst->isBubble() &&
1695 fu_inst->id.threadId == tid &&
1696 !fu_inst->inLSQ &&
1697 fu_inst->canEarlyIssue &&
1698 inst->id.execSeqNum > fu_inst->instToWaitFor;
1699 }
1700
1701 bool can_execute_fu_inst = inst->fuIndex == noCostFUIndex;
1702 if (can_commit_insts && !can_transfer_mem_inst &&
1703 inst->fuIndex != noCostFUIndex)
1704 {
1705 QueuedInst& fu_inst = funcUnits[inst->fuIndex]->front();
1706 can_execute_fu_inst = !fu_inst.inst->isBubble() &&
1707 fu_inst.inst->id == inst->id;
1708 }
1709
1710 can_commit_insts = can_commit_insts &&
1711 (can_transfer_mem_inst || can_execute_fu_inst);
1712 }
1713 }
1714
1715
1716 if (can_commit_insts) {
1717 commitPriority = tid;
1718 return tid;
1719 }
1720 }
1721
1722 return InvalidThreadID;
1723}
1724
1725inline ThreadID
1726Execute::getIssuingThread()
1727{
1728 std::vector<ThreadID> priority_list;
1729
1730 switch (cpu.threadPolicy) {
1731 case Enums::SingleThreaded:
1732 return 0;
1733 case Enums::RoundRobin:
1734 priority_list = cpu.roundRobinPriority(issuePriority);
1735 break;
1736 case Enums::Random:
1737 priority_list = cpu.randomPriority();
1738 break;
1739 default:
1740 panic("Invalid thread scheduling policy.");
1741 }
1742
1743 for (auto tid : priority_list) {
1744 if (cpu.getContext(tid)->status() == ThreadContext::Active &&
1745 getInput(tid)) {
1746 issuePriority = tid;
1747 return tid;
1748 }
1749 }
1750
1751 return InvalidThreadID;
1752}
1753
1636void
1637Execute::drainResume()
1638{
1639 DPRINTF(Drain, "MinorExecute drainResume\n");
1640
1754void
1755Execute::drainResume()
1756{
1757 DPRINTF(Drain, "MinorExecute drainResume\n");
1758
1641 setDrainState(NotDraining);
1759 for (ThreadID tid = 0; tid < cpu.numThreads; tid++) {
1760 setDrainState(tid, NotDraining);
1761 }
1642
1762
1643 /* Wakeup fetch and keep the pipeline running until that branch takes
1644 * effect */
1645 wakeupFetch(BranchData::WakeupFetch);
1646 cpu.wakeupOnEvent(Pipeline::ExecuteStageId);
1647}
1648
1649std::ostream &operator <<(std::ostream &os, Execute::DrainState state)
1650{
1651 switch (state)
1652 {
1653 case Execute::NotDraining:

--- 12 unchanged lines hidden (view full) ---

1666 os << "Drain-" << static_cast<int>(state);
1667 break;
1668 }
1669
1670 return os;
1671}
1672
1673void
1763 cpu.wakeupOnEvent(Pipeline::ExecuteStageId);
1764}
1765
1766std::ostream &operator <<(std::ostream &os, Execute::DrainState state)
1767{
1768 switch (state)
1769 {
1770 case Execute::NotDraining:

--- 12 unchanged lines hidden (view full) ---

1783 os << "Drain-" << static_cast<int>(state);
1784 break;
1785 }
1786
1787 return os;
1788}
1789
1790void
1674Execute::setDrainState(DrainState state)
1791Execute::setDrainState(ThreadID thread_id, DrainState state)
1675{
1792{
1676 DPRINTF(Drain, "setDrainState: %s\n", state);
1677 drainState = state;
1793 DPRINTF(Drain, "setDrainState[%d]: %s\n", thread_id, state);
1794 executeInfo[thread_id].drainState = state;
1678}
1679
1680unsigned int
1681Execute::drain()
1682{
1683 DPRINTF(Drain, "MinorExecute drain\n");
1684
1795}
1796
1797unsigned int
1798Execute::drain()
1799{
1800 DPRINTF(Drain, "MinorExecute drain\n");
1801
1685 if (drainState == NotDraining) {
1686 cpu.wakeupOnEvent(Pipeline::ExecuteStageId);
1802 for (ThreadID tid = 0; tid < cpu.numThreads; tid++) {
1803 if (executeInfo[tid].drainState == NotDraining) {
1804 cpu.wakeupOnEvent(Pipeline::ExecuteStageId);
1687
1805
1688 /* Go to DrainCurrentInst if we're between microops
1689 * or waiting on an unbufferable memory operation.
1690 * Otherwise we can go straight to DrainHaltFetch
1691 */
1692 if (isInbetweenInsts())
1693 setDrainState(DrainHaltFetch);
1694 else
1695 setDrainState(DrainCurrentInst);
1806 /* Go to DrainCurrentInst if we're between microops
1807 * or waiting on an unbufferable memory operation.
1808 * Otherwise we can go straight to DrainHaltFetch
1809 */
1810 if (isInbetweenInsts(tid))
1811 setDrainState(tid, DrainHaltFetch);
1812 else
1813 setDrainState(tid, DrainCurrentInst);
1814 }
1696 }
1815 }
1697
1698 return (isDrained() ? 0 : 1);
1699}
1700
1701bool
1702Execute::isDrained()
1703{
1816 return (isDrained() ? 0 : 1);
1817}
1818
1819bool
1820Execute::isDrained()
1821{
1704 return drainState == DrainAllInsts &&
1705 inputBuffer.empty() &&
1706 inFlightInsts->empty() &&
1707 lsq.isDrained();
1822 if (!lsq.isDrained())
1823 return false;
1824
1825 for (ThreadID tid = 0; tid < cpu.numThreads; tid++) {
1826 if (executeInfo[tid].drainState != DrainAllInsts ||
1827 !inputBuffer[tid].empty() ||
1828 !executeInfo[tid].inFlightInsts->empty()) {
1829
1830 return false;
1831 }
1832 }
1833
1834 return true;
1708}
1709
1710Execute::~Execute()
1711{
1712 for (unsigned int i = 0; i < numFuncUnits; i++)
1713 delete funcUnits[i];
1714
1835}
1836
1837Execute::~Execute()
1838{
1839 for (unsigned int i = 0; i < numFuncUnits; i++)
1840 delete funcUnits[i];
1841
1715 delete inFlightInsts;
1842 for (ThreadID tid = 0; tid < cpu.numThreads; tid++)
1843 delete executeInfo[tid].inFlightInsts;
1716}
1717
1718bool
1719Execute::instIsRightStream(MinorDynInstPtr inst)
1720{
1844}
1845
1846bool
1847Execute::instIsRightStream(MinorDynInstPtr inst)
1848{
1721 return inst->id.streamSeqNum == streamSeqNum;
1849 return inst->id.streamSeqNum == executeInfo[inst->id.threadId].streamSeqNum;
1722}
1723
1724bool
1725Execute::instIsHeadInst(MinorDynInstPtr inst)
1726{
1727 bool ret = false;
1728
1850}
1851
1852bool
1853Execute::instIsHeadInst(MinorDynInstPtr inst)
1854{
1855 bool ret = false;
1856
1729 if (!inFlightInsts->empty())
1730 ret = inFlightInsts->front().inst->id == inst->id;
1857 if (!executeInfo[inst->id.threadId].inFlightInsts->empty())
1858 ret = executeInfo[inst->id.threadId].inFlightInsts->front().inst->id == inst->id;
1731
1732 return ret;
1733}
1734
1735MinorCPU::MinorCPUPort &
1736Execute::getDcachePort()
1737{
1738 return lsq.getDcachePort();
1739}
1740
1741}
1859
1860 return ret;
1861}
1862
1863MinorCPU::MinorCPUPort &
1864Execute::getDcachePort()
1865{
1866 return lsq.getDcachePort();
1867}
1868
1869}