Go to the documentation of this file.
42 #include "arch/locked_mem.hh"
48 #include "debug/Activity.hh"
49 #include "debug/Branch.hh"
50 #include "debug/Drain.hh"
51 #include "debug/ExecFaulting.hh"
52 #include "debug/MinorExecute.hh"
53 #include "debug/MinorInterrupt.hh"
54 #include "debug/MinorMem.hh"
55 #include "debug/MinorTrace.hh"
56 #include "debug/PCEvent.hh"
67 const MinorCPUParams ¶ms,
74 zeroReg(cpu.threads[0]->getIsaPtr()->regClasses().
76 issueLimit(params.executeIssueLimit),
77 memoryIssueLimit(params.executeMemoryIssueLimit),
78 commitLimit(params.executeCommitLimit),
79 memoryCommitLimit(params.executeMemoryCommitLimit),
80 processMoreThanOneInput(params.executeCycleInput),
81 fuDescriptions(*params.executeFuncUnits),
82 numFuncUnits(fuDescriptions.funcUnits.size()),
83 setTraceTimeOnCommit(params.executeSetTraceTimeOnCommit),
84 setTraceTimeOnIssue(params.executeSetTraceTimeOnIssue),
85 allowEarlyMemIssue(params.executeAllowEarlyMemoryIssue),
86 noCostFUIndex(fuDescriptions.funcUnits.size() + 1),
87 lsq(name_ +
".lsq", name_ +
".dcache_port",
89 params.executeMaxAccessesInMemory,
90 params.executeMemoryWidth,
91 params.executeLSQRequestsQueueSize,
92 params.executeLSQTransfersQueueSize,
93 params.executeLSQStoreBufferSize,
94 params.executeLSQMaxStoreBufferStoresPerCycle,
96 executeInfo(params.numThreads,
103 fatal(
"%s: executeCommitLimit must be >= 1 (%d)\n", name_,
108 fatal(
"%s: executeCommitLimit must be >= 1 (%d)\n", name_,
113 fatal(
"%s: executeMemoryIssueLimit must be >= 1 (%d)\n", name_,
118 fatal(
"%s: executeMemoryCommitLimit (%d) must be <="
119 " executeCommitLimit (%d)\n",
123 if (params.executeInputBufferSize < 1) {
124 fatal(
"%s: executeInputBufferSize must be >= 1 (%d)\n", name_,
125 params.executeInputBufferSize);
128 if (params.executeInputBufferSize < 1) {
129 fatal(
"%s: executeInputBufferSize must be >= 1 (%d)\n", name_,
130 params.executeInputBufferSize);
136 unsigned int total_slots = 0;
140 std::ostringstream fu_name;
146 total_slots += fu_description->
opLat;
148 fu_name << name_ <<
".fu." <<
i;
156 for (
int op_class = No_OpClass + 1; op_class <
Num_OpClasses; op_class++) {
157 bool found_fu =
false;
158 unsigned int fu_index = 0;
163 static_cast<OpClass
>(op_class)))
171 warn(
"No functional unit for OpClass %s\n",
172 enums::OpClassStrings[op_class]);
177 for (
ThreadID tid = 0; tid < params.numThreads; tid++) {
183 name_ +
".inputBuffer" + tid_str,
"insts",
184 params.executeInputBufferSize));
186 const auto ®Classes =
cpu.
threads[tid]->getIsaPtr()->regClasses();
189 scoreboard.emplace_back(name_ +
".scoreboard" + tid_str, regClasses);
194 name_ +
".inFlightInsts" + tid_str,
"insts", total_slots);
198 name_ +
".inFUMemInsts" + tid_str,
"insts", total_slots);
235 inst->isLastOpInInst() &&
236 (inst->staticInst->isSerializeAfter() ||
237 inst->staticInst->isSquashAfter());
240 pc_before, target, (force_branch ?
" (forcing)" :
""));
243 bool must_branch = pc_before != target ||
251 inst->staticInst->advancePC(target);
258 if (inst->predictedTaken && !force_branch) {
264 " none happened inst: %s\n",
265 inst->pc.instAddr(), inst->predictedTarget.instAddr(), *inst);
268 }
else if (inst->predictedTarget == target) {
273 DPRINTF(
Branch,
"Predicted a branch from 0x%x to 0x%x correctly"
275 inst->pc.instAddr(), inst->predictedTarget.instAddr(), *inst);
281 " but got the wrong target (actual: 0x%x) inst: %s\n",
282 inst->pc.instAddr(), inst->predictedTarget.instAddr(),
283 target.instAddr(), *inst);
287 }
else if (must_branch) {
289 DPRINTF(
Branch,
"Unpredicted branch from 0x%x to 0x%x inst: %s\n",
290 inst->pc.instAddr(), target.instAddr(), *inst);
319 (inst->isBubble() ?
executeInfo[tid].lastPredictionSeqNum
320 : inst->id.predictionSeqNum),
331 ThreadID thread_id = inst->id.threadId;
338 bool is_load = inst->staticInst->isLoad();
339 bool is_store = inst->staticInst->isStore();
340 bool is_atomic = inst->staticInst->isAtomic();
341 bool is_prefetch = inst->staticInst->isDataPrefetch();
345 bool use_context_predicate =
true;
347 if (inst->translationFault !=
NoFault) {
349 DPRINTF(MinorMem,
"Completing fault from DTLB access: %s\n",
350 inst->translationFault->name());
352 if (inst->staticInst->isPrefetch()) {
353 DPRINTF(MinorMem,
"Not taking fault on prefetch: %s\n",
354 inst->translationFault->name());
359 fault = inst->translationFault;
361 fault->invoke(thread, inst->staticInst);
363 }
else if (!packet) {
364 DPRINTF(MinorMem,
"Completing failed request inst: %s\n",
366 use_context_predicate =
false;
368 inst->staticInst->completeAcc(
nullptr, &context, inst->traceData);
369 }
else if (packet->
isError()) {
370 DPRINTF(MinorMem,
"Trying to commit error response: %s\n",
373 fatal(
"Received error response packet for inst: %s\n", *inst);
374 }
else if (is_store || is_load || is_prefetch || is_atomic) {
377 DPRINTF(MinorMem,
"Memory response inst: %s addr: 0x%x size: %d\n",
380 if (is_load && packet->
getSize() > 0) {
381 DPRINTF(MinorMem,
"Memory data[0]: 0x%x\n",
382 static_cast<unsigned int>(packet->
getConstPtr<uint8_t>()[0]));
386 fault = inst->staticInst->completeAcc(packet, &context,
391 DPRINTF(MinorMem,
"Fault in memory completeAcc: %s\n",
393 fault->invoke(thread, inst->staticInst);
401 fatal(
"There should only ever be reads, "
402 "writes or faults at this point\n");
407 if (inst->traceData) {
408 inst->traceData->setPredicate((use_context_predicate ?
427 DPRINTF(MinorInterrupt,
"Considering interrupt status from PC: %s\n",
439 DPRINTF(MinorInterrupt,
"Invoking interrupt: %s to PC: %s\n",
454 bool &passed_predicate,
Fault &fault)
459 passed_predicate =
false;
472 DPRINTF(MinorExecute,
"Initiating memRef inst: %s\n", *inst);
474 Fault init_fault = inst->staticInst->initiateAcc(&context,
479 assert(inst->translationFault !=
NoFault);
485 inst->translationFault =
NoFault;
490 DPRINTF(MinorExecute,
"Fault on memory inst: %s"
491 " initiateAcc: %s\n", *inst, init_fault->name());
497 DPRINTF(MinorMem,
"No memory access for inst: %s\n", *inst);
504 inst->traceData->setPredicate(passed_predicate);
530 unsigned int ret =
index + 1;
532 if (ret == cycle_size)
545 ret = cycle_size - 1;
561 unsigned int fu_index = 0;
570 unsigned num_insts_issued = 0;
573 unsigned num_mem_insts_issued = 0;
577 unsigned num_insts_discarded = 0;
581 Fault fault = inst->fault;
582 bool discarded =
false;
583 bool issued_mem_ref =
false;
585 if (inst->isBubble()) {
591 DPRINTF(MinorExecute,
"Discarding inst: %s from suspended"
596 }
else if (inst->id.streamSeqNum != thread.
streamSeqNum) {
597 DPRINTF(MinorExecute,
"Discarding inst: %s as its stream"
598 " state was unexpected, expected: %d\n",
615 DPRINTF(MinorExecute,
"Trying to issue inst: %s to FU: %d\n",
622 bool fu_is_capable = (!inst->isFault() ?
623 fu->provides(inst->staticInst->opClass()) :
true);
625 if (inst->isNoCostInst()) {
640 inst->extraCommitDelay =
Cycles(0);
641 inst->extraCommitDelayExpr = NULL;
650 }
else if (!fu_is_capable ||
fu->alreadyPushed()) {
652 if (!fu_is_capable) {
653 DPRINTF(MinorExecute,
"Can't issue as FU: %d isn't"
654 " capable\n", fu_index);
656 DPRINTF(MinorExecute,
"Can't issue as FU: %d is"
657 " already busy\n", fu_index);
659 }
else if (
fu->stalled) {
660 DPRINTF(MinorExecute,
"Can't issue inst: %s into FU: %d,"
663 }
else if (!
fu->canInsert()) {
664 DPRINTF(MinorExecute,
"Can't issue inst: %s to busy FU"
665 " for another: %d cycles\n",
666 *inst,
fu->cyclesBeforeInsert());
669 fu->findTiming(inst->staticInst) : NULL);
676 &(
fu->cantForwardFromFUIndices);
679 DPRINTF(MinorExecute,
"Can't issue inst: %s as extra"
680 " decoding is suppressing it\n",
682 }
else if (!
scoreboard[thread_id].canInstIssue(inst,
683 src_latencies, cant_forward_from_fu_indices,
686 DPRINTF(MinorExecute,
"Can't issue inst: %s yet\n",
690 DPRINTF(MinorExecute,
"Issuing inst: %s"
691 " into FU %d\n", *inst,
695 TimingExpr *extra_dest_retire_lat_expr = NULL;
701 extra_dest_retire_lat =
703 extra_dest_retire_lat_expr =
709 issued_mem_ref = inst->isMemRef();
714 inst->fuIndex = fu_index;
715 inst->extraCommitDelay = extra_dest_retire_lat;
716 inst->extraCommitDelayExpr =
717 extra_dest_retire_lat_expr;
719 if (issued_mem_ref) {
724 inst->instToWaitFor =
725 scoreboard[thread_id].execSeqNumToWaitFor(inst,
731 DPRINTF(MinorExecute,
"A barrier will"
732 " cause a delay in mem ref issue of"
733 " inst: %s until after inst"
734 " %d(exec)\n", *inst,
737 inst->instToWaitFor =
740 DPRINTF(MinorExecute,
"Memory ref inst:"
741 " %s must wait for inst %d(exec)"
743 *inst, inst->instToWaitFor);
746 inst->canEarlyIssue =
true;
750 DPRINTF(MinorExecute,
"Pushing mem inst: %s\n",
764 fu->description.opLat +
765 extra_dest_retire_lat +
768 issued_mem_ref && extra_assumed_lat ==
Cycles(0));
782 DPRINTF(MinorExecute,
"Didn't issue inst: %s\n", *inst);
788 if (debug::MinorTrace && !inst->isBubble()) {
789 inst->minorTraceInst(*
this,
794 if (!discarded && inst->isInst() &&
795 inst->staticInst->isFullMemBarrier())
797 DPRINTF(MinorMem,
"Issuing memory barrier inst: %s\n", *inst);
802 inst->traceData->setWhen(
curTick());
806 num_mem_insts_issued++;
809 num_insts_discarded++;
810 }
else if (!inst->isBubble()) {
814 DPRINTF(MinorExecute,
"Reached inst issue limit\n");
818 DPRINTF(MinorExecute,
"Stepping to next inst inputIndex: %d\n",
830 DPRINTF(MinorExecute,
"Wrapping\n");
841 return num_insts_issued;
848 unsigned int num_pc_event_checks = 0;
854 cpu.
threads[thread_id]->pcEventQueue.service(oldPC, thread);
855 num_pc_event_checks++;
856 }
while (oldPC != thread->
instAddr());
858 if (num_pc_event_checks > 1) {
863 return num_pc_event_checks > 1;
869 assert(!inst->isFault());
875 if (!inst->staticInst->isMicroop() || inst->staticInst->isLastMicroop())
888 [inst->staticInst->opClass()]++;
892 inst->traceData->setCPSeq(thread->
numOp);
900 bool &completed_mem_issue)
902 ThreadID thread_id = inst->id.threadId;
905 bool completed_inst =
true;
913 panic(
"We should never hit the case where we try to commit from a "
914 "suspended thread as the streamSeqNum should not match");
915 }
else if (inst->isFault()) {
919 DPRINTF(MinorExecute,
"Fault inst reached Execute: %s\n",
920 inst->fault->name());
923 inst->fault->invoke(thread, NULL);
926 }
else if (inst->staticInst->isMemRef()) {
939 bool predicate_passed =
false;
941 predicate_passed, fault);
943 if (completed_mem_inst && fault !=
NoFault) {
944 if (early_memory_issue) {
945 DPRINTF(MinorExecute,
"Fault in early executing inst: %s\n",
949 inst->canEarlyIssue =
false;
952 completed_inst =
false;
954 DPRINTF(MinorExecute,
"Fault in execute: %s\n",
956 fault->invoke(thread, NULL);
959 completed_inst =
true;
962 completed_inst = completed_mem_inst;
964 completed_mem_issue = completed_inst;
965 }
else if (inst->isInst() && inst->staticInst->isFullMemBarrier() &&
968 DPRINTF(MinorExecute,
"Can't commit data barrier inst: %s yet as"
969 " there isn't space in the store buffer\n", *inst);
971 completed_inst =
false;
972 }
else if (inst->isInst() && inst->staticInst->isQuiesce()
976 completed_inst =
false;
981 DPRINTF(MinorExecute,
"Committing inst: %s\n", *inst);
983 fault = inst->staticInst->execute(&context,
993 if (inst->traceData) {
994 if (debug::ExecFaulting) {
995 inst->traceData->setFaulting(
true);
997 delete inst->traceData;
998 inst->traceData = NULL;
1002 DPRINTF(MinorExecute,
"Fault in execute of inst: %s fault: %s\n",
1003 *inst, fault->name());
1004 fault->invoke(thread, inst->staticInst);
1011 if (completed_inst) {
1015 executeInfo[thread_id].lastPredictionSeqNum = inst->id.predictionSeqNum;
1018 if (!inst->isFault() &&
1026 assert(resume_pc.microPC() == 0);
1028 DPRINTF(MinorInterrupt,
"Suspending thread: %d from Execute"
1029 " inst: %s\n", thread_id, *inst);
1038 return completed_inst;
1076 bool completed_inst =
true;
1079 unsigned int num_insts_committed = 0;
1083 unsigned int num_mem_refs_committed = 0;
1085 if (only_commit_microops && !ex_info.
inFlightInsts->empty()) {
1086 DPRINTF(MinorInterrupt,
"Only commit microops %s %d\n",
1098 if (only_commit_microops) {
1099 DPRINTF(MinorInterrupt,
"Committing tail of insts before"
1107 head_inflight_inst->
inst->id.execSeqNum;
1114 bool committed_inst =
false;
1115 bool discard_inst =
false;
1116 bool completed_mem_ref =
false;
1117 bool issued_mem_ref =
false;
1118 bool early_memory_issue =
false;
1121 completed_inst =
false;
1133 DPRINTF(MinorExecute,
"Trying to commit canCommitInsts: %d\n",
1143 }
else if (mem_response &&
1147 discard_inst = inst->id.streamSeqNum !=
1150 DPRINTF(MinorExecute,
"Trying to commit mem response: %s\n",
1155 DPRINTF(MinorExecute,
"Discarding mem inst: %s as its"
1156 " stream state was unexpected, expected: %d\n",
1162 committed_inst =
true;
1165 completed_mem_ref =
true;
1166 completed_inst =
true;
1167 }
else if (can_commit_insts) {
1172 bool try_to_commit =
false;
1184 DPRINTF(MinorExecute,
"Trying to commit from mem FUs\n");
1193 if (!fu_inst->isBubble() &&
1195 fu_inst->canEarlyIssue &&
1197 head_exec_seq_num > fu_inst->instToWaitFor)
1199 DPRINTF(MinorExecute,
"Issuing mem ref early"
1200 " inst: %s instToWaitFor: %d\n",
1201 *(fu_inst), fu_inst->instToWaitFor);
1204 try_to_commit =
true;
1205 early_memory_issue =
true;
1206 completed_inst =
true;
1211 if (!completed_inst && inst->isNoCostInst()) {
1212 DPRINTF(MinorExecute,
"Committing no cost inst: %s", *inst);
1214 try_to_commit =
true;
1215 completed_inst =
true;
1220 if (!completed_inst && !inst->inLSQ) {
1221 DPRINTF(MinorExecute,
"Trying to commit from FUs\n");
1230 if (fu_inst.
inst->isBubble()) {
1232 completed_inst =
false;
1233 }
else if (fu_inst_seq_num != head_exec_seq_num) {
1239 }
else if (fu_inst.
inst->id == inst->id) {
1243 try_to_commit =
true;
1244 completed_inst =
true;
1248 if (try_to_commit) {
1249 discard_inst = inst->id.streamSeqNum !=
1254 if (!discard_inst) {
1260 if (inst->extraCommitDelayExpr) {
1261 DPRINTF(MinorExecute,
"Evaluating expression for"
1262 " extra commit delay inst: %s\n", *inst);
1269 uint64_t extra_delay = inst->extraCommitDelayExpr->
1272 DPRINTF(MinorExecute,
"Extra commit delay expr"
1273 " result: %d\n", extra_delay);
1275 if (extra_delay < 128) {
1276 inst->extraCommitDelay +=
Cycles(extra_delay);
1278 DPRINTF(MinorExecute,
"Extra commit delay was"
1279 " very long: %d\n", extra_delay);
1281 inst->extraCommitDelayExpr = NULL;
1286 if (inst->extraCommitDelay !=
Cycles(0)) {
1288 inst->extraCommitDelay;
1289 inst->extraCommitDelay =
Cycles(0);
1294 if (!inst->isFault() && inst->isMemRef() &&
1296 inst->id.execSeqNum &&
1299 DPRINTF(MinorExecute,
"Not committing inst: %s yet"
1300 " as there are incomplete barriers in flight\n",
1302 completed_inst =
false;
1303 }
else if (inst->minimumCommitCycle > now) {
1304 DPRINTF(MinorExecute,
"Not committing inst: %s yet"
1305 " as it wants to be stalled for %d more cycles\n",
1306 *inst, inst->minimumCommitCycle - now);
1307 completed_inst =
false;
1310 early_memory_issue, branch, fault,
1311 committed_inst, issued_mem_ref);
1315 completed_inst =
true;
1318 if (completed_inst) {
1324 DPRINTF(MinorExecute,
"Unstalling %d for inst %s\n", inst->fuIndex, inst->id);
1325 funcUnits[inst->fuIndex]->stalled =
false;
1330 DPRINTF(MinorExecute,
"No instructions to commit\n");
1331 completed_inst =
false;
1335 assert(!(discard_inst && !completed_inst));
1340 DPRINTF(MinorExecute,
"Discarding inst: %s as its stream"
1341 " state was unexpected, expected: %d\n",
1349 if (issued_mem_ref) {
1356 if (completed_inst && inst->isMemRef()) {
1366 if (completed_inst && !(issued_mem_ref && fault ==
NoFault)) {
1368 DPRINTF(MinorExecute,
"Completed inst: %s\n", *inst);
1372 inst->isLastOpInInst();
1383 if (inst->isInst() && inst->staticInst->isFullMemBarrier()) {
1384 DPRINTF(MinorMem,
"Completing memory barrier"
1385 " inst: %s committed: %d\n", *inst, committed_inst);
1389 scoreboard[thread_id].clearInstDests(inst, inst->isMemRef());
1393 if (committed_inst) {
1394 bool is_no_cost_inst = inst->isNoCostInst();
1398 if (debug::MinorTrace && !is_no_cost_inst)
1401 if (!is_no_cost_inst)
1402 num_insts_committed++;
1405 DPRINTF(MinorExecute,
"Reached inst commit limit\n");
1409 if (inst->traceData) {
1411 inst->traceData->setWhen(
curTick());
1412 inst->traceData->dump();
1415 if (completed_mem_ref)
1416 num_mem_refs_committed++;
1419 DPRINTF(MinorExecute,
"Reached mem ref commit limit\n");
1427 return executeInfo[thread_id].lastCommitWasEndOfMacroop &&
1434 if (!
inp.outputWire->isBubble())
1439 unsigned int num_issued = 0;
1446 bool interrupted =
false;
1455 DPRINTF(MinorInterrupt,
"Execute skipping a cycle to allow old"
1456 " branch to complete\n");
1463 DPRINTF(MinorExecute,
"Attempting to commit [tid:%d]\n",
1470 commit(commit_tid,
true,
false, branch);
1481 commit(commit_tid,
false,
true, branch);
1486 DPRINTF(MinorExecute,
"Committing micro-ops for interrupt[tid:%d]\n",
1488 bool only_commit_microops = interrupted &&
1490 commit(commit_tid, only_commit_microops,
false, branch);
1507 DPRINTF(MinorExecute,
"Attempting to issue [tid:%d]\n",
1509 num_issued =
issue(issue_tid);
1517 bool can_issue_next =
false;
1523 unsigned int input_index =
executeInfo[tid].inputIndex;
1525 if (inst->isFault()) {
1526 can_issue_next =
true;
1527 }
else if (!inst->isBubble()) {
1528 next_issuable_insts.push_back(inst);
1533 bool becoming_stalled =
true;
1543 if (
fu->occupancy !=0 && !
fu->stalled)
1544 becoming_stalled =
false;
1550 for (
auto inst : next_issuable_insts) {
1551 if (!
fu->stalled &&
fu->provides(inst->staticInst->opClass()) &&
1552 scoreboard[inst->id.threadId].canInstIssue(inst,
1555 can_issue_next =
true;
1561 bool head_inst_might_commit =
false;
1565 if (!info.inFlightInsts->empty()) {
1566 const QueuedInst &head_inst = info.inFlightInsts->front();
1568 if (head_inst.
inst->isNoCostInst()) {
1569 head_inst_might_commit =
true;
1573 fu->front().inst->id == head_inst.
inst->id) ||
1576 head_inst_might_commit =
true;
1583 DPRINTF(Activity,
"Need to tick num issued insts: %s%s%s%s%s%s\n",
1584 (num_issued != 0 ?
" (issued some insts)" :
""),
1585 (becoming_stalled ?
"(becoming stalled)" :
"(not becoming stalled)"),
1586 (can_issue_next ?
" (can issued next inst)" :
""),
1587 (head_inst_might_commit ?
"(head inst might commit)" :
""),
1589 (interrupted ?
" (interrupted)" :
""));
1593 !becoming_stalled ||
1595 head_inst_might_commit ||
1599 if (!need_to_tick) {
1600 DPRINTF(Activity,
"The next cycle might be skippable as there are no"
1601 " advanceable FUs\n");
1613 if (!
inp.outputWire->isBubble())
1625 bool thread_interrupted =
false;
1632 interrupted = interrupted || thread_interrupted;
1634 DPRINTF(MinorInterrupt,
"No interrupt controller\n");
1636 DPRINTF(MinorInterrupt,
"[tid:%d] thread_interrupted?=%d isInbetweenInsts?=%d\n",
1666 std::ostringstream insts;
1667 std::ostringstream stalled;
1669 executeInfo[0].instsBeingCommitted.reportData(insts);
1678 stalled << (
funcUnits[
i]->stalled ?
'1' :
'E');
1685 " stalled=%s drainState=%d isInbetweenInsts=%d\n",
1702 case enums::SingleThreaded:
1704 case enums::RoundRobin:
1711 panic(
"Invalid thread policy");
1714 for (
auto tid : priority_list) {
1717 if (can_commit_insts) {
1721 can_commit_insts = can_commit_insts &&
1725 bool can_transfer_mem_inst =
false;
1731 can_transfer_mem_inst =
1732 !fu_inst->isBubble() &&
1733 fu_inst->id.threadId == tid &&
1735 fu_inst->canEarlyIssue &&
1736 inst->id.execSeqNum > fu_inst->instToWaitFor;
1740 if (can_commit_insts && !can_transfer_mem_inst &&
1744 can_execute_fu_inst = !fu_inst.
inst->isBubble() &&
1745 fu_inst.
inst->id == inst->id;
1748 can_commit_insts = can_commit_insts &&
1749 (can_transfer_mem_inst || can_execute_fu_inst);
1754 if (can_commit_insts) {
1769 case enums::SingleThreaded:
1771 case enums::RoundRobin:
1778 panic(
"Invalid thread scheduling policy.");
1781 for (
auto tid : priority_list) {
1794 DPRINTF(Drain,
"MinorExecute drainResume\n");
1808 os <<
"NotDraining";
1811 os <<
"DrainCurrentInst";
1814 os <<
"DrainHaltFetch";
1817 os <<
"DrainAllInsts";
1820 os <<
"Drain-" <<
static_cast<int>(state);
1830 DPRINTF(Drain,
"setDrainState[%d]: %s\n", thread_id, state);
1837 DPRINTF(Drain,
"MinorExecute drain\n");
1885 return inst->id.streamSeqNum ==
executeInfo[inst->id.threadId].streamSeqNum;
1893 if (!
executeInfo[inst->id.threadId].inFlightInsts->empty())
1894 ret =
executeInfo[inst->id.threadId].inFlightInsts->front().inst->id == inst->id;
Tick curTick()
The universal simulation clock.
#define fatal(...)
This implements a cprintf based fatal() function.
std::vector< ThreadID > randomPriority()
ThreadID getCommittingThread()
Use the current threading policy to determine the next thread to decode from.
constexpr decltype(nullptr) NoFault
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...
bool isBubble() const
BubbleIF interface.
void issuedMemBarrierInst(MinorDynInstPtr inst)
A memory barrier instruction has been issued, remember its execSeqNum that we can avoid issuing memor...
const RegIndex zeroReg
Index of the zero integer register.
Cycles curCycle() const
Determine the current cycle, corresponding to a tick aligned to a clock edge.
MinorDynInstPtr insts[MAX_FORWARD_INSTS]
Array of carried insts, ref counted.
unsigned int inputIndex
Index that we've completed upto in getInput data.
BaseInterrupts * getInterruptController(ThreadID tid)
statistics::Scalar numFetchSuspends
Number of times fetch was asked to suspend by Execute.
unsigned int drain()
Like the drain interface on SimObject.
unsigned int commitLimit
Number of instructions that can be committed per cycle.
bool readPredicate() const override
Provide a non-protected base class for Minor's Ports as derived classes are created by Fetch1 and Exe...
Cycles extraAssumedLat
Extra delay that results should show in the scoreboard after leaving the pipeline.
MinorFUPool & fuDescriptions
Descriptions of the functional units we want to generate.
statistics::Scalar numOps
Stat for number ops (including micro ops) committed.
statistics::Scalar numOps
Number of simulated insts and microops.
bool needsToBeSentToStoreBuffer()
This request, once processed by the requests/transfers queues, will need to go to the store buffer.
const std::string to_string(sc_enc enc)
statistics::Scalar numInsts
Stat for number instructions committed.
Wrapper for a queue type to act as a pipeline stage input queue.
ThreadID checkInterrupts(BranchData &branch, bool &interrupted)
Check all threads for possible interrupts.
MinorCPU is an in-order CPU model with four fixed pipeline stages:
LSQ lsq
Dcache port to pass on to the CPU.
Queue< QueuedInst, ReportTraitsAdaptor< QueuedInst > > * inFUMemInsts
Memory ref instructions still in the FUs.
void evaluate()
Pass on input/buffer data to the output if you can.
static BranchData bubble()
BubbleIF interface.
void step()
Step checks the queues to see if their are issuable transfers which were not otherwise picked up by t...
Container class to box instructions in the FUs to make those queues have correct bubble behaviour whe...
bool needsToTick()
May need to be ticked next cycle as one of the queues contains an actionable transfers or address tra...
virtual Addr instAddr() const =0
bool takeInterrupt(ThreadID thread_id, BranchData &branch)
Act on an interrupt.
Extra timing capability to allow individual ops to have their source register dependency latencies tw...
void pushFailedRequest(MinorDynInstPtr inst)
Push a predicate failed-representing request into the queues just to maintain commit order.
Forward flowing data between Fetch2,Decode,Execute carrying a packet of instructions of a width appro...
bool setTraceTimeOnIssue
Modify instruction trace times on issue.
bool isInterrupted(ThreadID thread_id) const
Has an interrupt been raised.
The SimpleThread object provides a combination of the ThreadState object and the ThreadContext interf...
bool hasInterrupt(ThreadID thread_id)
Checks if a specific thread has an interrupt.
void serviceEvents(Tick when)
process all events up to the given timestamp.
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 wakeupOnEvent(unsigned int stage_id)
Interface for stages to signal that they have become active after a callback or eventq event where th...
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.
InstSeqNum streamSeqNum
Source of sequence number for instuction streams.
unsigned int noCostFUIndex
The FU index of the non-existent costless FU for instructions which pass the MinorDynInst::isNoCostIn...
virtual Status status() const =0
std::vector< minor::MinorThread * > threads
These are thread state-representing objects for this CPU.
minor::MinorStats stats
Processor-specific statistics.
Cycles is a wrapper class for representing cycle counts, i.e.
Derived SenderState to carry data access info.
ThreadID getIssuingThread()
Interface for things with names.
bool isDrained()
Is there nothing left in the LSQ.
gem5::ThreadState::ThreadStateStats threadStats
ThreadID numThreads
Number of threads we're actually simulating (<= SMT_MAX_THREADS).
...ReportTraits are trait classes with the same functionality as ReportIF, but with elements explicit...
std::vector< InputBuffer< ForwardInstData > > inputBuffer
statistics::Scalar numInsts
Number of simulated instructions.
const ForwardInstData * getInput(ThreadID tid)
Get a piece of data to work on from the inputBuffer, or 0 if there is no data.
unsigned int cyclicIndexDec(unsigned int index, unsigned int cycle_size)
Decrement a cyclic buffer index for indices [0, cycle_size-1].
ThreadContext is the external interface to all thread state for anything outside of the CPU.
std::shared_ptr< FaultBase > Fault
MinorCPU::MinorCPUPort & getDcachePort()
Return the raw-bindable port.
bool processMoreThanOneInput
If true, more than one input line can be processed each cycle if there is room to execute more instru...
@ Suspended
Temporarily inactive.
InstSeqNum getLastMemBarrier(ThreadID thread_id) const
Get the execSeqNum of the last issued memory barrier.
@ CorrectlyPredictedBranch
A functional unit that can execute any of opClasses operations with a single op(eration)Lat(ency) and...
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
bool isDrained()
After thread suspension, has Execute been drained of in-flight instructions and memory accesses.
GenericISA::DelaySlotPCState< 4 > PCState
virtual void updateIntrInfo()=0
bool commitInst(MinorDynInstPtr inst, bool early_memory_issue, BranchData &branch, Fault &fault, bool &committed, bool &completed_mem_issue)
Commit a single instruction.
void doInstCommitAccounting(MinorDynInstPtr inst)
Do the stats handling and instruction count and PC event events related to the new instruction/op cou...
bool canRequest()
Is their space in the request queue to be able to push a request by issuing an isMemRef instruction.
@ BadlyPredictedBranchTarget
const T * getConstPtr() const
void minorTrace() const
Report buffer states from 'slot' 'from' to 'to'.
statistics::Scalar numDiscardedOps
Number of ops discarded before committing.
void completeMemBarrierInst(MinorDynInstPtr inst, bool committed)
Complete a barrier instruction.
Object to gather the visible context for evaluation.
static MinorDynInstPtr bubble()
There is a single bubble inst.
unsigned int width() const
Number of instructions carried by this object.
ForwardInstData instsBeingCommitted
Structure for reporting insts currently being processed/retired for MinorTrace.
std::vector< Scoreboard > scoreboard
Scoreboard of instruction dependencies.
const ThreadID InvalidThreadID
void popResponse(LSQRequestPtr response)
Sanity check and pop the head response.
Forward data betwen Execute and Fetch1 carrying change-of-address/stream information.
virtual TheISA::PCState pcState() const =0
bool isInbetweenInsts(ThreadID thread_id) const
Are we between instructions? Can we be interrupted?
MinorCPU::MinorCPUPort & getDcachePort()
Returns the DcachePort owned by this Execute to pass upwards.
statistics::Vector2d committedInstType
Number of instructions by type (OpClass)
virtual ThreadContext * getContext(int tn)
Given a thread num get tho thread context for it.
virtual void probeInstCommit(const StaticInstPtr &inst, Addr pc)
Helper method to trigger PMU probes for a committed instruction.
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
TimingExpr * extraCommitLatExpr
GEM5_DEPRECATED_NAMESPACE(GuestABI, guest_abi)
std::vector< MinorFU * > funcUnits
bool readMemAccPredicate() const override
bool tryPCEvents(ThreadID thread_id)
Try to act on PC-related events.
void minorTrace(const char *fmt, Args ...args)
DPRINTFN for MinorTrace reporting.
void activity()
Records that there is activity this cycle.
A functional unit configured from a MinorFU object.
bool FullSystem
The FullSystem variable can be used to determine the current mode of simulation.
ExecContext bears the exec_context interface for Minor.
Cycles opLat
Delay from issuing the operation, to it reaching the end of the associated pipeline.
bool lastCommitWasEndOfMacroop
The last commit was the end of a full instruction so an interrupt can safely happen.
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 isStreamChange() const
As static isStreamChange but on this branch data.
unsigned int cyclicIndexInc(unsigned int index, unsigned int cycle_size)
Increment a cyclic buffer index for indices [0, cycle_size-1].
Counter numInst
Number of instructions committed.
void popInput(ThreadID tid)
Pop an element off the input buffer, if there are any.
bool setTraceTimeOnCommit
Modify instruction trace times on commit.
Base class for branch operations.
void setDrainState(ThreadID thread_id, DrainState state)
Set the drain state (with useful debugging messages)
std::ostream & operator<<(std::ostream &os, const InstId &id)
Print this id in the usual slash-separated format expected by MinorTrace.
bool accessesInFlight() const
Are there any accesses other than normal cached loads in the memory system or having received respons...
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...
DrainState drainState
State progression for draining NotDraining -> ...
bool checkInterrupts(ThreadID tid) const
std::vector< Cycles > srcRegsRelativeLats
Cycle offsets from the scoreboard delivery times of register values for each of this instruction's so...
Latch< ForwardInstData >::Output inp
Input port carrying instructions from Decode.
Queue< QueuedInst, ReportTraitsAdaptor< QueuedInst > > * inFlightInsts
In-order instructions either in FUs or the LSQ.
bool executeMemRefInst(MinorDynInstPtr inst, BranchData &branch, bool &failed_predicate, Fault &fault)
Execute a memory reference instruction.
Latch< BranchData >::Input out
Input port carrying stream changes to Fetch1.
Counter numOp
Number of ops (including micro ops) committed.
bool allowEarlyMemIssue
Allow mem refs to leave their FUs before reaching the head of the in flight insts queue if their depe...
virtual Fault getInterrupt()=0
static const OpClass Num_OpClasses
DrainState
Stage cycle-by-cycle state.
enums::ThreadPolicy threadPolicy
Thread Scheduling Policy (RoundRobin, Random, etc)
Cycles extraCommitLat
Extra latency that the instruction should spend at the end of the pipeline.
unsigned int numFuncUnits
Number of functional units to produce.
minor::MinorActivityRecorder * activityRecorder
Activity recording for pipeline.
InstSeqNum lastPredictionSeqNum
A prediction number for use where one isn't available from an instruction.
std::vector< FUPipeline * > funcUnits
The execution functional units.
unsigned int issueLimit
Number of instructions that can be issued per cycle.
std::vector< ExecuteThreadInfo > executeInfo
unsigned int issue(ThreadID thread_id)
Try and issue instructions from the inputBuffer.
bool suppress
If true, instructions matching this mask/match should not be issued in this FU.
MinorCPU & cpu
Pointer back to the containing CPU.
ThreadID interruptPriority
@ IntRegClass
Integer register.
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
bool instIsHeadInst(MinorDynInstPtr inst)
Returns true if the given instruction is at the head of the inFlightInsts instruction queue.
unsigned int memoryIssueLimit
Number of memory ops that can be issued per cycle.
void sendStoreToStoreBuffer(LSQRequestPtr request)
A store has been committed, please move it to the store buffer.
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...
bool canPushIntoStoreBuffer() const
Must check this before trying to insert into the store buffer.
EventQueue comInstEventQueue
An instruction-based event queue.
std::vector< ThreadID > roundRobinPriority(ThreadID priority)
Thread scheduling utility functions.
int16_t ThreadID
Thread index/ID type.
bool instIsRightStream(MinorDynInstPtr inst)
Does the given instruction have the right stream sequence number to be committed?
Execute(const std::string &name_, MinorCPU &cpu_, const MinorCPUParams ¶ms, Latch< ForwardInstData >::Output inp_, Latch< BranchData >::Input out_)
#define panic(...)
This implements a cprintf based panic() function.
Generated on Wed Jul 28 2021 12:10:24 for gem5 by doxygen 1.8.17