42 #include "arch/locked_mem.hh"
43 #include "arch/registers.hh"
44 #include "arch/utility.hh"
50 #include "debug/Activity.hh"
51 #include "debug/Branch.hh"
52 #include "debug/Drain.hh"
53 #include "debug/MinorExecute.hh"
54 #include "debug/MinorInterrupt.hh"
55 #include "debug/MinorMem.hh"
56 #include "debug/MinorTrace.hh"
57 #include "debug/PCEvent.hh"
64 MinorCPUParams ¶ms,
71 issueLimit(params.executeIssueLimit),
72 memoryIssueLimit(params.executeMemoryIssueLimit),
73 commitLimit(params.executeCommitLimit),
74 memoryCommitLimit(params.executeMemoryCommitLimit),
75 processMoreThanOneInput(params.executeCycleInput),
76 fuDescriptions(*params.executeFuncUnits),
77 numFuncUnits(fuDescriptions.funcUnits.
size()),
78 setTraceTimeOnCommit(params.executeSetTraceTimeOnCommit),
79 setTraceTimeOnIssue(params.executeSetTraceTimeOnIssue),
80 allowEarlyMemIssue(params.executeAllowEarlyMemoryIssue),
81 noCostFUIndex(fuDescriptions.funcUnits.
size() + 1),
82 lsq(name_ +
".lsq", name_ +
".dcache_port",
84 params.executeMaxAccessesInMemory,
85 params.executeMemoryWidth,
86 params.executeLSQRequestsQueueSize,
87 params.executeLSQTransfersQueueSize,
88 params.executeLSQStoreBufferSize,
89 params.executeLSQMaxStoreBufferStoresPerCycle),
96 fatal(
"%s: executeCommitLimit must be >= 1 (%d)\n", name_,
101 fatal(
"%s: executeCommitLimit must be >= 1 (%d)\n", name_,
106 fatal(
"%s: executeMemoryIssueLimit must be >= 1 (%d)\n", name_,
111 fatal(
"%s: executeMemoryCommitLimit (%d) must be <="
112 " executeCommitLimit (%d)\n",
116 if (params.executeInputBufferSize < 1) {
117 fatal(
"%s: executeInputBufferSize must be >= 1 (%d)\n", name_,
118 params.executeInputBufferSize);
121 if (params.executeInputBufferSize < 1) {
122 fatal(
"%s: executeInputBufferSize must be >= 1 (%d)\n", name_,
123 params.executeInputBufferSize);
129 unsigned int total_slots = 0;
133 std::ostringstream fu_name;
139 total_slots += fu_description->
opLat;
141 fu_name << name_ <<
".fu." <<
i;
149 for (
int op_class = No_OpClass + 1; op_class <
Num_OpClasses; op_class++) {
150 bool found_fu =
false;
151 unsigned int fu_index = 0;
153 while (fu_index < numFuncUnits && !found_fu)
156 static_cast<OpClass>(op_class)))
164 warn(
"No functional unit for OpClass %s\n",
165 Enums::OpClassStrings[op_class]);
170 for (
ThreadID tid = 0; tid < params.numThreads; tid++) {
171 std::string tid_str = std::to_string(tid);
176 name_ +
".inputBuffer" + tid_str,
"insts",
177 params.executeInputBufferSize));
185 name_ +
".inFlightInsts" + tid_str,
"insts", total_slots);
189 name_ +
".inFUMemInsts" + tid_str,
"insts", total_slots);
226 inst->isLastOpInInst() &&
227 (inst->staticInst->isSerializeAfter() ||
228 inst->staticInst->isIprAccess());
230 DPRINTF(Branch,
"tryToBranch before: %s after: %s%s\n",
231 pc_before, target, (force_branch ?
" (forcing)" :
""));
234 bool must_branch = pc_before != target ||
246 DPRINTF(Branch,
"Advancing current PC from: %s to: %s\n",
250 if (inst->predictedTaken && !force_branch) {
255 DPRINTF(Branch,
"Predicted a branch from 0x%x to 0x%x but"
256 " none happened inst: %s\n",
257 inst->pc.instAddr(), inst->predictedTarget.instAddr(), *inst);
260 }
else if (inst->predictedTarget == target) {
265 DPRINTF(Branch,
"Predicted a branch from 0x%x to 0x%x correctly"
267 inst->pc.instAddr(), inst->predictedTarget.instAddr(), *inst);
272 DPRINTF(Branch,
"Predicted a branch from 0x%x to 0x%x"
273 " but got the wrong target (actual: 0x%x) inst: %s\n",
274 inst->pc.instAddr(), inst->predictedTarget.instAddr(),
275 target.instAddr(), *inst);
279 }
else if (must_branch) {
281 DPRINTF(Branch,
"Unpredicted branch from 0x%x to 0x%x inst: %s\n",
282 inst->pc.instAddr(), target.instAddr(), *inst);
311 (inst->isBubble() ?
executeInfo[tid].lastPredictionSeqNum
312 : inst->id.predictionSeqNum),
315 DPRINTF(Branch,
"Branch data signalled: %s\n", branch);
323 ThreadID thread_id = inst->id.threadId;
330 bool is_load = inst->staticInst->isLoad();
331 bool is_store = inst->staticInst->isStore();
332 bool is_prefetch = inst->staticInst->isDataPrefetch();
336 bool use_context_predicate =
true;
340 DPRINTF(MinorMem,
"Completing fault from DTLB access: %s\n",
341 response->
fault->name());
343 if (inst->staticInst->isPrefetch()) {
344 DPRINTF(MinorMem,
"Not taking fault on prefetch: %s\n",
345 response->
fault->name());
350 fault = response->
fault;
352 fault->invoke(thread, inst->staticInst);
354 }
else if (!packet) {
355 DPRINTF(MinorMem,
"Completing failed request inst: %s\n",
357 use_context_predicate =
false;
358 }
else if (packet->
isError()) {
359 DPRINTF(MinorMem,
"Trying to commit error response: %s\n",
362 fatal(
"Received error response packet for inst: %s\n", *inst);
363 }
else if (is_store || is_load || is_prefetch) {
366 DPRINTF(MinorMem,
"Memory response inst: %s addr: 0x%x size: %d\n",
369 if (is_load && packet->
getSize() > 0) {
370 DPRINTF(MinorMem,
"Memory data[0]: 0x%x\n",
371 static_cast<unsigned int>(packet->
getConstPtr<uint8_t>()[0]));
375 fault = inst->staticInst->completeAcc(packet, &context,
380 DPRINTF(MinorMem,
"Fault in memory completeAcc: %s\n",
382 fault->invoke(thread, inst->staticInst);
390 fatal(
"There should only ever be reads, "
391 "writes or faults at this point\n");
396 if (inst->traceData) {
397 inst->traceData->setPredicate((use_context_predicate ?
410 return cpu.checkInterrupts(
cpu.getContext(thread_id));
416 DPRINTF(MinorInterrupt,
"Considering interrupt status from PC: %s\n",
417 cpu.getContext(thread_id)->pcState());
420 (
cpu.getContext(thread_id));
424 cpu.getInterruptController(thread_id)->updateIntrInfo
425 (
cpu.getContext(thread_id));
426 interrupt->invoke(
cpu.getContext(thread_id));
430 DPRINTF(MinorInterrupt,
"Invoking interrupt: %s to PC: %s\n",
431 interrupt->name(),
cpu.getContext(thread_id)->pcState());
445 bool &passed_predicate,
Fault &fault)
450 passed_predicate =
false;
463 DPRINTF(MinorExecute,
"Initiating memRef inst: %s\n", *inst);
465 Fault init_fault = inst->staticInst->initiateAcc(&context,
469 DPRINTF(MinorExecute,
"Fault on memory inst: %s"
470 " initiateAcc: %s\n", *inst, init_fault->name());
479 inst->traceData->setPredicate(passed_predicate);
484 if (!passed_predicate) {
502 unsigned int ret = index + 1;
504 if (ret == cycle_size)
517 ret = cycle_size - 1;
533 unsigned int fu_index = 0;
542 unsigned num_insts_issued = 0;
545 unsigned num_mem_insts_issued = 0;
549 unsigned num_insts_discarded = 0;
553 Fault fault = inst->fault;
554 bool discarded =
false;
555 bool issued_mem_ref =
false;
557 if (inst->isBubble()) {
560 }
else if (
cpu.getContext(thread_id)->status() ==
563 DPRINTF(MinorExecute,
"Discarding inst: %s from suspended"
568 }
else if (inst->id.streamSeqNum != thread.
streamSeqNum) {
569 DPRINTF(MinorExecute,
"Discarding inst: %s as its stream"
570 " state was unexpected, expected: %d\n",
587 DPRINTF(MinorExecute,
"Trying to issue inst: %s to FU: %d\n",
594 bool fu_is_capable = (!inst->isFault() ?
595 fu->
provides(inst->staticInst->opClass()) :
true);
597 if (inst->isNoCostInst()) {
608 Cycles(0),
cpu.getContext(thread_id),
false);
612 inst->extraCommitDelay =
Cycles(0);
613 inst->extraCommitDelayExpr = NULL;
624 if (!fu_is_capable) {
625 DPRINTF(MinorExecute,
"Can't issue as FU: %d isn't"
626 " capable\n", fu_index);
628 DPRINTF(MinorExecute,
"Can't issue as FU: %d is"
629 " already busy\n", fu_index);
632 DPRINTF(MinorExecute,
"Can't issue inst: %s into FU: %d,"
636 DPRINTF(MinorExecute,
"Can't issue inst: %s to busy FU"
637 " for another: %d cycles\n",
651 DPRINTF(MinorExecute,
"Can't issue inst: %s as extra"
652 " decoding is suppressing it\n",
654 }
else if (!
scoreboard[thread_id].canInstIssue(inst,
655 src_latencies, cant_forward_from_fu_indices,
656 cpu.curCycle(),
cpu.getContext(thread_id)))
658 DPRINTF(MinorExecute,
"Can't issue inst: %s yet\n",
662 DPRINTF(MinorExecute,
"Issuing inst: %s"
663 " into FU %d\n", *inst,
667 TimingExpr *extra_dest_retire_lat_expr = NULL;
673 extra_dest_retire_lat =
675 extra_dest_retire_lat_expr =
681 issued_mem_ref = inst->isMemRef();
686 inst->fuIndex = fu_index;
687 inst->extraCommitDelay = extra_dest_retire_lat;
688 inst->extraCommitDelayExpr =
689 extra_dest_retire_lat_expr;
691 if (issued_mem_ref) {
696 inst->instToWaitFor =
697 scoreboard[thread_id].execSeqNumToWaitFor(inst,
698 cpu.getContext(thread_id));
703 DPRINTF(MinorExecute,
"A barrier will"
704 " cause a delay in mem ref issue of"
705 " inst: %s until after inst"
706 " %d(exec)\n", *inst,
709 inst->instToWaitFor =
712 DPRINTF(MinorExecute,
"Memory ref inst:"
713 " %s must wait for inst %d(exec)"
715 *inst, inst->instToWaitFor);
718 inst->canEarlyIssue =
true;
722 DPRINTF(MinorExecute,
"Pushing mem inst: %s\n",
737 extra_dest_retire_lat +
739 cpu.getContext(thread_id),
740 issued_mem_ref && extra_assumed_lat ==
Cycles(0));
754 DPRINTF(MinorExecute,
"Didn't issue inst: %s\n", *inst);
760 if (
DTRACE(MinorTrace) && !inst->isBubble())
761 inst->minorTraceInst(*
this);
764 if (!discarded && inst->isInst() &&
765 inst->staticInst->isMemBarrier())
767 DPRINTF(MinorMem,
"Issuing memory barrier inst: %s\n", *inst);
772 inst->traceData->setWhen(
curTick());
776 num_mem_insts_issued++;
779 num_insts_discarded++;
780 }
else if (!inst->isBubble()) {
784 DPRINTF(MinorExecute,
"Reached inst issue limit\n");
788 DPRINTF(MinorExecute,
"Stepping to next inst inputIndex: %d\n",
800 DPRINTF(MinorExecute,
"Wrapping\n");
811 return num_insts_issued;
818 unsigned int num_pc_event_checks = 0;
824 cpu.system->pcEventQueue.service(thread);
825 num_pc_event_checks++;
826 }
while (oldPC != thread->
instAddr());
828 if (num_pc_event_checks > 1) {
833 return num_pc_event_checks > 1;
839 assert(!inst->isFault());
845 if (!inst->staticInst->isMicroop() || inst->staticInst->isLastMicroop())
850 cpu.system->totalNumInsts++;
853 cpu.comInstEventQueue[inst->id.threadId]->serviceEvents(thread->numInst);
854 cpu.system->instEventQueue.serviceEvents(
cpu.system->totalNumInsts);
860 [inst->staticInst->opClass()]++;
864 inst->traceData->setCPSeq(thread->numOp);
866 cpu.probeInstCommit(inst->staticInst);
872 bool &completed_mem_issue)
874 ThreadID thread_id = inst->id.threadId;
877 bool completed_inst =
true;
885 panic(
"We should never hit the case where we try to commit from a "
886 "suspended thread as the streamSeqNum should not match");
887 }
else if (inst->isFault()) {
890 DPRINTF(MinorExecute,
"Fault inst reached Execute: %s\n",
891 inst->fault->name());
894 inst->fault->invoke(thread, NULL);
897 }
else if (inst->staticInst->isMemRef()) {
910 bool predicate_passed =
false;
912 predicate_passed, fault);
914 if (completed_mem_inst && fault !=
NoFault) {
915 if (early_memory_issue) {
916 DPRINTF(MinorExecute,
"Fault in early executing inst: %s\n",
920 inst->canEarlyIssue =
false;
923 completed_inst =
false;
925 DPRINTF(MinorExecute,
"Fault in execute: %s\n",
927 fault->invoke(thread, NULL);
930 completed_inst =
true;
933 completed_inst = completed_mem_inst;
935 completed_mem_issue = completed_inst;
936 }
else if (inst->isInst() && inst->staticInst->isMemBarrier() &&
939 DPRINTF(MinorExecute,
"Can't commit data barrier inst: %s yet as"
940 " there isn't space in the store buffer\n", *inst);
942 completed_inst =
false;
943 }
else if (inst->isInst() && inst->staticInst->isQuiesce()
947 completed_inst =
false;
951 DPRINTF(MinorExecute,
"Committing inst: %s\n", *inst);
953 fault = inst->staticInst->execute(&context,
963 DPRINTF(MinorExecute,
"Fault in execute of inst: %s fault: %s\n",
964 *inst, fault->name());
965 fault->invoke(thread, inst->staticInst);
972 if (completed_inst) {
976 executeInfo[thread_id].lastPredictionSeqNum = inst->id.predictionSeqNum;
979 if (!inst->isFault() &&
987 assert(resume_pc.microPC() == 0);
989 DPRINTF(MinorInterrupt,
"Suspending thread: %d from Execute"
990 " inst: %s\n", thread_id, *inst);
999 return completed_inst;
1037 bool completed_inst =
true;
1040 unsigned int num_insts_committed = 0;
1044 unsigned int num_mem_refs_committed = 0;
1046 if (only_commit_microops && !ex_info.
inFlightInsts->empty()) {
1047 DPRINTF(MinorInterrupt,
"Only commit microops %s %d\n",
1059 if (only_commit_microops) {
1060 DPRINTF(MinorInterrupt,
"Committing tail of insts before"
1068 head_inflight_inst->
inst->id.execSeqNum;
1075 bool committed_inst =
false;
1076 bool discard_inst =
false;
1077 bool completed_mem_ref =
false;
1078 bool issued_mem_ref =
false;
1079 bool early_memory_issue =
false;
1082 completed_inst =
false;
1094 DPRINTF(MinorExecute,
"Trying to commit canCommitInsts: %d\n",
1104 }
else if (mem_response &&
1108 discard_inst = inst->id.streamSeqNum !=
1111 DPRINTF(MinorExecute,
"Trying to commit mem response: %s\n",
1116 DPRINTF(MinorExecute,
"Discarding mem inst: %s as its"
1117 " stream state was unexpected, expected: %d\n",
1123 committed_inst =
true;
1126 completed_mem_ref =
true;
1127 completed_inst =
true;
1128 }
else if (can_commit_insts) {
1133 bool try_to_commit =
false;
1145 DPRINTF(MinorExecute,
"Trying to commit from mem FUs\n");
1154 if (!fu_inst->isBubble() &&
1156 fu_inst->canEarlyIssue &&
1158 head_exec_seq_num > fu_inst->instToWaitFor)
1160 DPRINTF(MinorExecute,
"Issuing mem ref early"
1161 " inst: %s instToWaitFor: %d\n",
1162 *(fu_inst), fu_inst->instToWaitFor);
1165 try_to_commit =
true;
1166 early_memory_issue =
true;
1167 completed_inst =
true;
1172 if (!completed_inst && inst->isNoCostInst()) {
1173 DPRINTF(MinorExecute,
"Committing no cost inst: %s", *inst);
1175 try_to_commit =
true;
1176 completed_inst =
true;
1181 if (!completed_inst && !inst->inLSQ) {
1182 DPRINTF(MinorExecute,
"Trying to commit from FUs\n");
1191 if (fu_inst.
inst->isBubble()) {
1193 completed_inst =
false;
1194 }
else if (fu_inst_seq_num != head_exec_seq_num) {
1200 }
else if (fu_inst.
inst->id == inst->id) {
1204 try_to_commit =
true;
1205 completed_inst =
true;
1209 if (try_to_commit) {
1210 discard_inst = inst->id.streamSeqNum !=
1215 if (!discard_inst) {
1221 if (inst->extraCommitDelayExpr) {
1222 DPRINTF(MinorExecute,
"Evaluating expression for"
1223 " extra commit delay inst: %s\n", *inst);
1230 uint64_t extra_delay = inst->extraCommitDelayExpr->
1233 DPRINTF(MinorExecute,
"Extra commit delay expr"
1234 " result: %d\n", extra_delay);
1236 if (extra_delay < 128) {
1237 inst->extraCommitDelay +=
Cycles(extra_delay);
1239 DPRINTF(MinorExecute,
"Extra commit delay was"
1240 " very long: %d\n", extra_delay);
1242 inst->extraCommitDelayExpr = NULL;
1247 if (inst->extraCommitDelay !=
Cycles(0)) {
1248 inst->minimumCommitCycle =
cpu.curCycle() +
1249 inst->extraCommitDelay;
1250 inst->extraCommitDelay =
Cycles(0);
1255 if (!inst->isFault() && inst->isMemRef() &&
1257 inst->id.execSeqNum &&
1260 DPRINTF(MinorExecute,
"Not committing inst: %s yet"
1261 " as there are incomplete barriers in flight\n",
1263 completed_inst =
false;
1264 }
else if (inst->minimumCommitCycle > now) {
1265 DPRINTF(MinorExecute,
"Not committing inst: %s yet"
1266 " as it wants to be stalled for %d more cycles\n",
1267 *inst, inst->minimumCommitCycle - now);
1268 completed_inst =
false;
1271 early_memory_issue, branch, fault,
1272 committed_inst, issued_mem_ref);
1276 completed_inst =
true;
1279 if (completed_inst) {
1285 DPRINTF(MinorExecute,
"Unstalling %d for inst %s\n", inst->fuIndex, inst->id);
1286 funcUnits[inst->fuIndex]->stalled =
false;
1291 DPRINTF(MinorExecute,
"No instructions to commit\n");
1292 completed_inst =
false;
1296 assert(!(discard_inst && !completed_inst));
1301 DPRINTF(MinorExecute,
"Discarding inst: %s as its stream"
1302 " state was unexpected, expected: %d\n",
1310 if (issued_mem_ref) {
1317 if (completed_inst && inst->isMemRef()) {
1327 if (completed_inst && !(issued_mem_ref && fault ==
NoFault)) {
1329 DPRINTF(MinorExecute,
"Completed inst: %s\n", *inst);
1333 inst->isLastOpInInst();
1344 if (inst->isInst() && inst->staticInst->isMemBarrier()) {
1345 DPRINTF(MinorMem,
"Completing memory barrier"
1346 " inst: %s committed: %d\n", *inst, committed_inst);
1350 scoreboard[thread_id].clearInstDests(inst, inst->isMemRef());
1354 if (committed_inst) {
1355 bool is_no_cost_inst = inst->isNoCostInst();
1359 if (
DTRACE(MinorTrace) && !is_no_cost_inst)
1362 if (!is_no_cost_inst)
1363 num_insts_committed++;
1366 DPRINTF(MinorExecute,
"Reached inst commit limit\n");
1370 if (inst->traceData) {
1372 inst->traceData->setWhen(
curTick());
1373 inst->traceData->dump();
1376 if (completed_mem_ref)
1377 num_mem_refs_committed++;
1380 DPRINTF(MinorExecute,
"Reached mem ref commit limit\n");
1388 return executeInfo[thread_id].lastCommitWasEndOfMacroop &&
1395 if (!
inp.outputWire->isBubble())
1400 unsigned int num_issued = 0;
1407 bool interrupted =
false;
1416 DPRINTF(MinorInterrupt,
"Execute skipping a cycle to allow old"
1417 " branch to complete\n");
1424 DPRINTF(MinorExecute,
"Attempting to commit [tid:%d]\n",
1431 commit(commit_tid,
true,
false, branch);
1442 commit(commit_tid,
false,
true, branch);
1447 DPRINTF(MinorExecute,
"Committing micro-ops for interrupt[tid:%d]\n",
1449 bool only_commit_microops = interrupted &&
1451 commit(commit_tid, only_commit_microops,
false, branch);
1468 DPRINTF(MinorExecute,
"Attempting to issue [tid:%d]\n",
1470 num_issued =
issue(issue_tid);
1478 bool can_issue_next =
false;
1480 for (
ThreadID tid = 0; tid <
cpu.numThreads; tid++) {
1484 unsigned int input_index =
executeInfo[tid].inputIndex;
1486 if (inst->isFault()) {
1487 can_issue_next =
true;
1488 }
else if (!inst->isBubble()) {
1489 next_issuable_insts.push_back(inst);
1494 bool becoming_stalled =
true;
1505 becoming_stalled =
false;
1511 for (
auto inst : next_issuable_insts) {
1513 scoreboard[inst->id.threadId].canInstIssue(inst,
1515 cpu.getContext(inst->id.threadId))) {
1516 can_issue_next =
true;
1522 bool head_inst_might_commit =
false;
1526 if (!info.inFlightInsts->empty()) {
1527 const QueuedInst &head_inst = info.inFlightInsts->front();
1529 if (head_inst.
inst->isNoCostInst()) {
1530 head_inst_might_commit =
true;
1534 fu->
front().inst->id == head_inst.
inst->id) ||
1537 head_inst_might_commit =
true;
1544 DPRINTF(Activity,
"Need to tick num issued insts: %s%s%s%s%s%s\n",
1545 (num_issued != 0 ?
" (issued some insts)" :
""),
1546 (becoming_stalled ?
"(becoming stalled)" :
"(not becoming stalled)"),
1547 (can_issue_next ?
" (can issued next inst)" :
""),
1548 (head_inst_might_commit ?
"(head inst might commit)" :
""),
1550 (interrupted ?
" (interrupted)" :
""));
1554 !becoming_stalled ||
1556 head_inst_might_commit ||
1560 if (!need_to_tick) {
1561 DPRINTF(Activity,
"The next cycle might be skippable as there are no"
1562 " advanceable FUs\n");
1574 if (!
inp.outputWire->isBubble())
1586 bool thread_interrupted =
false;
1593 interrupted = interrupted || thread_interrupted;
1595 DPRINTF(MinorInterrupt,
"No interrupt controller\n");
1597 DPRINTF(MinorInterrupt,
"[tid:%d] thread_interrupted?=%d isInbetweenInsts?=%d\n",
1606 tid = (tid + 1) %
cpu.numThreads;
1627 std::ostringstream insts;
1628 std::ostringstream stalled;
1630 executeInfo[0].instsBeingCommitted.reportData(insts);
1639 stalled << (
funcUnits[
i]->stalled ?
'1' :
'E');
1645 MINORTRACE(
"insts=%s inputIndex=%d streamSeqNum=%d"
1646 " stalled=%s drainState=%d isInbetweenInsts=%d\n",
1663 case Enums::SingleThreaded:
1665 case Enums::RoundRobin:
1672 panic(
"Invalid thread policy");
1675 for (
auto tid : priority_list) {
1678 if (can_commit_insts) {
1682 can_commit_insts = can_commit_insts &&
1686 bool can_transfer_mem_inst =
false;
1692 can_transfer_mem_inst =
1693 !fu_inst->isBubble() &&
1694 fu_inst->id.threadId == tid &&
1696 fu_inst->canEarlyIssue &&
1697 inst->id.execSeqNum > fu_inst->instToWaitFor;
1701 if (can_commit_insts && !can_transfer_mem_inst &&
1705 can_execute_fu_inst = !fu_inst.
inst->isBubble() &&
1706 fu_inst.
inst->id == inst->id;
1709 can_commit_insts = can_commit_insts &&
1710 (can_transfer_mem_inst || can_execute_fu_inst);
1715 if (can_commit_insts) {
1730 case Enums::SingleThreaded:
1732 case Enums::RoundRobin:
1739 panic(
"Invalid thread scheduling policy.");
1742 for (
auto tid : priority_list) {
1755 DPRINTF(Drain,
"MinorExecute drainResume\n");
1757 for (
ThreadID tid = 0; tid <
cpu.numThreads; tid++) {
1769 os <<
"NotDraining";
1772 os <<
"DrainCurrentInst";
1775 os <<
"DrainHaltFetch";
1778 os <<
"DrainAllInsts";
1781 os <<
"Drain-" <<
static_cast<int>(state);
1791 DPRINTF(Drain,
"setDrainState[%d]: %s\n", thread_id, state);
1798 DPRINTF(Drain,
"MinorExecute drain\n");
1800 for (
ThreadID tid = 0; tid <
cpu.numThreads; tid++) {
1823 for (
ThreadID tid = 0; tid <
cpu.numThreads; tid++) {
1839 for (
ThreadID tid = 0; tid <
cpu.numThreads; tid++)
1846 return inst->id.streamSeqNum ==
executeInfo[inst->id.threadId].streamSeqNum;
1854 if (!
executeInfo[inst->id.threadId].inFlightInsts->empty())
1855 ret =
executeInfo[inst->id.threadId].inFlightInsts->front().inst->id == inst->id;
...ReportTraits are trait classes with the same functionality as ReportIF, but with elements explicit...
DrainState
Stage cycle-by-cycle state.
std::ostream & operator<<(std::ostream &os, const InstId &id)
Print this id in the usual slash-separated format expected by MinorTrace.
void handleMemResponse(MinorDynInstPtr inst, LSQ::LSQRequestPtr response, BranchData &branch, Fault &fault)
Handle extracting mem ref responses from the memory queues and completing the associated instructions...
void popInput(ThreadID tid)
Pop an element off the input buffer, if there are any.
Container class to box instructions in the FUs to make those queues have correct bubble behaviour whe...
void commit(ThreadID thread_id, bool only_commit_microops, bool discard, BranchData &branch)
Try and commit instructions from the ends of the functional unit pipelines.
virtual Addr instAddr()=0
decltype(nullptr) constexpr NoFault
Cycles is a wrapper class for representing cycle counts, i.e.
Top level definition of the Minor in-order CPU model.
unsigned int cyclicIndexInc(unsigned int index, unsigned int cycle_size)
Increment a cyclic buffer index for indices [0, cycle_size-1].
bool allowEarlyMemIssue
Allow mem refs to leave their FUs before reaching the head of the in flight insts queue if their depe...
bool isInbetweenInsts(ThreadID thread_id) const
Are we between instructions? Can we be interrupted?
static BranchData bubble()
BubbleIF interface.
unsigned int memoryCommitLimit
Number of memory instructions that can be committed per cycle.
static bool isStreamChange(const BranchData::Reason reason)
Is a request with this reason actually a request to change the PC rather than a bubble or branch pred...
void doInstCommitAccounting(MinorDynInstPtr inst)
Do the stats handling and instruction count and PC event events related to the new instruction/op cou...
void popResponse(LSQRequestPtr response)
Sanity check and pop the head response.
unsigned int cyclicIndexDec(unsigned int index, unsigned int cycle_size)
Decrement a cyclic buffer index for indices [0, cycle_size-1].
void issuedMemBarrierInst(MinorDynInstPtr inst)
A memory barrier instruction has been issued, remember its execSeqNum that we can avoid issuing memor...
bool instIsHeadInst(MinorDynInstPtr inst)
Returns true if the given instruction is at the head of the inFlightInsts instruction queue...
MinorCPU & cpu
Pointer back to the containing CPU.
void pushFailedRequest(MinorDynInstPtr inst)
Push a predicate failed-representing request into the queues just to maintain commit order...
All the fun of executing instructions from Decode and sending branch/new instruction stream info...
void wakeupOnEvent(unsigned int stage_id)
Interface for stages to signal that they have become active after a callback or eventq event where th...
void setDrainState(ThreadID thread_id, DrainState state)
Set the drain state (with useful debugging messages)
Fault fault
Fault generated performing this request.
bool setTraceTimeOnCommit
Modify instruction trace times on commit.
unsigned int memoryIssueLimit
Number of memory ops that can be issued per cycle.
void tryToBranch(MinorDynInstPtr inst, Fault fault, BranchData &branch)
Generate Branch data based (into branch) on an observed (or not) change in PC while executing an inst...
unsigned int issue(ThreadID thread_id)
Try and issue instructions from the inputBuffer.
void activity()
Records that there is activity this cycle.
bool FullSystem
The FullSystem variable can be used to determine the current mode of simulation.
Object to gather the visible context for evaluation.
unsigned int commitLimit
Number of instructions that can be committed per cycle.
ThreadID getCommittingThread()
Use the current threading policy to determine the next thread to decode from.
The SimpleThread object provides a combination of the ThreadState object and the ThreadContext interf...
bool accessesInFlight() const
Are there any accesses other than normal cached loads in the memory system or having received respons...
ElemType & front()
Peek at the end element of the pipe.
virtual TheISA::PCState pcState()=0
Queue< QueuedInst, ReportTraitsAdaptor< QueuedInst > > * inFlightInsts
In-order instructions either in FUs or the LSQ.
A functional unit that can execute any of opClasses operations with a single op(eration)Lat(ency) and...
std::vector< FUPipeline * > funcUnits
The execution functional units.
LSQRequestPtr findResponse(MinorDynInstPtr inst)
Returns a response if it's at the head of the transfers queue and it's either complete or can be sent...
Stats::Scalar numOps
Number of simulated insts and microops.
Cycles opLat
Delay from issuing the operation, to it reaching the end of the associated pipeline.
Wrapper for a queue type to act as a pipeline stage input queue.
unsigned int numFuncUnits
Number of functional units to produce.
Cycles extraAssumedLat
Extra delay that results should show in the scoreboard after leaving the pipeline.
ThreadContext is the external interface to all thread state for anything outside of the CPU...
ExecContext bears the exec_context interface for Minor.
const MinorFU & description
Functional unit description that this pipeline implements.
ExecContext bears the exec_context interface for Minor.
InstSeqNum lastPredictionSeqNum
A prediction number for use where one isn't available from an instruction.
Derived SenderState to carry data access info.
InstSeqNum streamSeqNum
Source of sequence number for instuction streams.
Stats::Scalar numFetchSuspends
Number of times fetch was asked to suspend by Execute.
Provide a non-protected base class for Minor's Ports as derived classes are created by Fetch1 and Exe...
Execute(const std::string &name_, MinorCPU &cpu_, MinorCPUParams ¶ms, Latch< ForwardInstData >::Output inp_, Latch< BranchData >::Input out_)
ForwardInstData instsBeingCommitted
Structure for reporting insts currently being processed/retired for MinorTrace.
bool canRequest()
Is their space in the request queue to be able to push a request by issuing an isMemRef instruction...
std::vector< MinorFU * > funcUnits
void completeMemBarrierInst(MinorDynInstPtr inst, bool committed)
Complete a barrier instruction.
bool provides(OpClass capability)
unsigned int width() const
Number of instructions carried by this object.
ThreadID getIssuingThread()
Tick curTick()
The current simulated tick.
bool takeInterrupt(ThreadID thread_id, BranchData &branch)
Act on an interrupt.
unsigned int noCostFUIndex
The FU index of the non-existent costless FU for instructions which pass the MinorDynInst::isNoCostIn...
bool isBubble() const
BubbleIF interface.
std::vector< InputBuffer< ForwardInstData > > inputBuffer
Stats::Scalar numInsts
Number of simulated instructions.
std::vector< ThreadID > randomPriority()
MinorDynInstPtr insts[MAX_FORWARD_INSTS]
Array of carried insts, ref counted.
bool tryPCEvents(ThreadID thread_id)
Try to act on PC-related events.
MinorCPU::MinorCPUPort & getDcachePort()
Return the raw-bindable port.
Minor::MinorActivityRecorder * activityRecorder
Activity recording for pipeline.
unsigned int inputIndex
Index that we've completed upto in getInput data.
std::vector< Cycles > srcRegsRelativeLats
Cycle offsets from the scoreboard delivery times of register values for each of this instruction's so...
bool needsToBeSentToStoreBuffer()
This request, once processed by the requests/transfers queues, will need to go to the store buffer...
InstSeqNum getLastMemBarrier(ThreadID thread_id) const
Get the execSeqNum of the last issued memory barrier.
Extra timing capability to allow individual ops to have their source register dependency latencies tw...
unsigned int occupancy
The number of slots with non-bubbles in them.
Latch< BranchData >::Input out
Input port carrying stream changes to Fetch1.
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
void advancePC(PCState &pc, const StaticInstPtr &inst)
MinorFUPool & fuDescriptions
Descriptions of the functional units we want to generate.
bool canPushIntoStoreBuffer() const
Must check this before trying to insert into the store buffer.
bool isDrained()
Is there nothing left in the LSQ.
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
MinorFUTiming * findTiming(const StaticInstPtr &inst)
Find the extra timing information for this instruction.
LSQ lsq
Dcache port to pass on to the CPU.
std::vector< ThreadID > roundRobinPriority(ThreadID priority)
Thread scheduling utility functions.
const ThreadID InvalidThreadID
void step()
Step checks the queues to see if their are issuable transfers which were not otherwise picked up by t...
Fetch1 is responsible for fetching "lines" from memory and passing them to Fetch2.
bool hasInterrupt(ThreadID thread_id)
Checks if a specific thread has an interrupt.
A load/store queue that allows outstanding reads and writes.
bool processMoreThanOneInput
If true, more than one input line can be processed each cycle if there is room to execute more instru...
A scoreboard of register dependencies including, for each register: The number of in-flight instructi...
Stats::Scalar numDiscardedOps
Number of ops discarded before committing.
ThreadID checkInterrupts(BranchData &branch, bool &interrupted)
Check all threads for possible interrupts.
bool alreadyPushed()
Have we already pushed onto this pipe without advancing.
int16_t ThreadID
Thread index/ID type.
DrainState drainState
State progression for draining NotDraining -> ...
void sendStoreToStoreBuffer(LSQRequestPtr request)
A store has been committed, please move it to the store buffer.
bool suppress
If true, instructions matching this mask/match should not be issued in this FU.
TimingExpr * extraCommitLatExpr
Forward data betwen Execute and Fetch1 carrying change-of-address/stream information.
ThreadID interruptPriority
Cycles cyclesBeforeInsert()
How many cycles must from curCycle before insertion into the pipeline is allowed. ...
bool lastCommitWasEndOfMacroop
The last commit was the end of a full instruction so an interrupt can safely happen.
Enums::ThreadPolicy threadPolicy
Thread Scheduling Policy (RoundRobin, Random, etc)
bool instIsRightStream(MinorDynInstPtr inst)
Does the given instruction have the right stream sequence number to be committed? ...
bool isStreamChange() const
As static isStreamChange but on this branch data.
bool readPredicate() override
void advance()
Step the pipeline.
static MinorDynInstPtr bubble()
There is a single bubble inst.
static const OpClass Num_OpClasses
GenericISA::SimplePCState< MachInst > PCState
bool executeMemRefInst(MinorDynInstPtr inst, BranchData &branch, bool &failed_predicate, Fault &fault)
Execute a memory reference instruction.
Stats::Vector2d committedInstType
Number of instructions by type (OpClass)
void minorTrace() const
Report buffer states from 'slot' 'from' to 'to'.
std::vector< Minor::MinorThread * > threads
These are thread state-representing objects for this CPU.
bool commitInst(MinorDynInstPtr inst, bool early_memory_issue, BranchData &branch, Fault &fault, bool &committed, bool &completed_mem_issue)
Commit a single instruction.
std::vector< ExecuteThreadInfo > executeInfo
#define MINORTRACE(...)
DPRINTFN for MinorTrace reporting.
std::vector< Scoreboard > scoreboard
Scoreboard of instruction dependencies.
virtual Status status() const =0
void push(ElemType &elem)
Write an element to the back of the pipeline.
const T * getConstPtr() const
MinorCPU is an in-order CPU model with four fixed pipeline stages:
bool isDrained()
After thread suspension, has Execute been drained of in-flight instructions and memory accesses...
Latch< ForwardInstData >::Output inp
Input port carrying instructions from Decode.
Cycles extraCommitLat
Extra latency that the instruction should spend at the end of the pipeline.
Minor::MinorStats stats
Processor-specific statistics.
bool canInsert() const
Can an instruction be inserted now?
void evaluate()
Pass on input/buffer data to the output if you can.
bool stalled
If true, advance will not advance the pipeline.
unsigned int drain()
Like the drain interface on SimObject.
std::shared_ptr< FaultBase > Fault
MinorCPU::MinorCPUPort & getDcachePort()
Returns the DcachePort owned by this Execute to pass upwards.
std::vector< bool > cantForwardFromFUIndices
FUs which this pipeline can't receive a forwarded (i.e.
unsigned int issueLimit
Number of instructions that can be issued per cycle.
bool setTraceTimeOnIssue
Modify instruction trace times on issue.
Forward flowing data between Fetch2,Decode,Execute carrying a packet of instructions of a width appro...
Queue< QueuedInst, ReportTraitsAdaptor< QueuedInst > > * inFUMemInsts
Memory ref instructions still in the FUs.
A functional unit configured from a MinorFU object.
const ForwardInstData * getInput(ThreadID tid)
Get a piece of data to work on from the inputBuffer, or 0 if there is no data.
void updateBranchData(ThreadID tid, BranchData::Reason reason, MinorDynInstPtr inst, const TheISA::PCState &target, BranchData &branch)
Actually create a branch to communicate to Fetch1/Fetch2 and, if that is a stream-changing branch upd...
bool needsToTick()
May need to be ticked next cycle as one of the queues contains an actionable transfers or address tra...
bool isInterrupted(ThreadID thread_id) const
Has an interrupt been raised.