Go to the documentation of this file.
40 #include "arch/locked_mem.hh"
41 #include "arch/registers.hh"
42 #include "arch/utility.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"
63 MinorCPUParams ¶ms,
70 issueLimit(params.executeIssueLimit),
71 memoryIssueLimit(params.executeMemoryIssueLimit),
72 commitLimit(params.executeCommitLimit),
73 memoryCommitLimit(params.executeMemoryCommitLimit),
74 processMoreThanOneInput(params.executeCycleInput),
75 fuDescriptions(*params.executeFuncUnits),
76 numFuncUnits(fuDescriptions.funcUnits.size()),
77 setTraceTimeOnCommit(params.executeSetTraceTimeOnCommit),
78 setTraceTimeOnIssue(params.executeSetTraceTimeOnIssue),
79 allowEarlyMemIssue(params.executeAllowEarlyMemoryIssue),
80 noCostFUIndex(fuDescriptions.funcUnits.size() + 1),
81 lsq(name_ +
".lsq", name_ +
".dcache_port",
83 params.executeMaxAccessesInMemory,
84 params.executeMemoryWidth,
85 params.executeLSQRequestsQueueSize,
86 params.executeLSQTransfersQueueSize,
87 params.executeLSQStoreBufferSize,
88 params.executeLSQMaxStoreBufferStoresPerCycle),
95 fatal(
"%s: executeCommitLimit must be >= 1 (%d)\n", name_,
100 fatal(
"%s: executeCommitLimit must be >= 1 (%d)\n", name_,
105 fatal(
"%s: executeMemoryIssueLimit must be >= 1 (%d)\n", name_,
110 fatal(
"%s: executeMemoryCommitLimit (%d) must be <="
111 " executeCommitLimit (%d)\n",
115 if (params.executeInputBufferSize < 1) {
116 fatal(
"%s: executeInputBufferSize must be >= 1 (%d)\n", name_,
117 params.executeInputBufferSize);
120 if (params.executeInputBufferSize < 1) {
121 fatal(
"%s: executeInputBufferSize must be >= 1 (%d)\n", name_,
122 params.executeInputBufferSize);
128 unsigned int total_slots = 0;
132 std::ostringstream fu_name;
138 total_slots += fu_description->
opLat;
140 fu_name << name_ <<
".fu." <<
i;
148 for (
int op_class = No_OpClass + 1; op_class <
Num_OpClasses; op_class++) {
149 bool found_fu =
false;
150 unsigned int fu_index = 0;
155 static_cast<OpClass
>(op_class)))
163 warn(
"No functional unit for OpClass %s\n",
164 Enums::OpClassStrings[op_class]);
169 for (
ThreadID tid = 0; tid < params.numThreads; tid++) {
175 name_ +
".inputBuffer" + tid_str,
"insts",
176 params.executeInputBufferSize));
184 name_ +
".inFlightInsts" + tid_str,
"insts", total_slots);
188 name_ +
".inFUMemInsts" + tid_str,
"insts", total_slots);
225 inst->isLastOpInInst() &&
226 (inst->staticInst->isSerializeAfter() ||
227 inst->staticInst->isSquashAfter() ||
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_atomic = inst->staticInst->isAtomic();
333 bool is_prefetch = inst->staticInst->isDataPrefetch();
337 bool use_context_predicate =
true;
339 if (inst->translationFault !=
NoFault) {
341 DPRINTF(MinorMem,
"Completing fault from DTLB access: %s\n",
342 inst->translationFault->name());
344 if (inst->staticInst->isPrefetch()) {
345 DPRINTF(MinorMem,
"Not taking fault on prefetch: %s\n",
346 inst->translationFault->name());
351 fault = inst->translationFault;
353 fault->invoke(thread, inst->staticInst);
355 }
else if (!packet) {
356 DPRINTF(MinorMem,
"Completing failed request inst: %s\n",
358 use_context_predicate =
false;
360 inst->staticInst->completeAcc(
nullptr, &context, inst->traceData);
361 }
else if (packet->
isError()) {
362 DPRINTF(MinorMem,
"Trying to commit error response: %s\n",
365 fatal(
"Received error response packet for inst: %s\n", *inst);
366 }
else if (is_store || is_load || is_prefetch || is_atomic) {
369 DPRINTF(MinorMem,
"Memory response inst: %s addr: 0x%x size: %d\n",
372 if (is_load && packet->
getSize() > 0) {
373 DPRINTF(MinorMem,
"Memory data[0]: 0x%x\n",
374 static_cast<unsigned int>(packet->
getConstPtr<uint8_t>()[0]));
378 fault = inst->staticInst->completeAcc(packet, &context,
383 DPRINTF(MinorMem,
"Fault in memory completeAcc: %s\n",
385 fault->invoke(thread, inst->staticInst);
393 fatal(
"There should only ever be reads, "
394 "writes or faults at this point\n");
399 if (inst->traceData) {
400 inst->traceData->setPredicate((use_context_predicate ?
419 DPRINTF(MinorInterrupt,
"Considering interrupt status from PC: %s\n",
431 DPRINTF(MinorInterrupt,
"Invoking interrupt: %s to PC: %s\n",
446 bool &passed_predicate,
Fault &fault)
451 passed_predicate =
false;
464 DPRINTF(MinorExecute,
"Initiating memRef inst: %s\n", *inst);
466 Fault init_fault = inst->staticInst->initiateAcc(&context,
471 assert(inst->translationFault !=
NoFault);
477 inst->translationFault =
NoFault;
482 DPRINTF(MinorExecute,
"Fault on memory inst: %s"
483 " initiateAcc: %s\n", *inst, init_fault->name());
489 DPRINTF(MinorMem,
"No memory access for inst: %s\n", *inst);
496 inst->traceData->setPredicate(passed_predicate);
522 unsigned int ret =
index + 1;
524 if (ret == cycle_size)
537 ret = cycle_size - 1;
553 unsigned int fu_index = 0;
562 unsigned num_insts_issued = 0;
565 unsigned num_mem_insts_issued = 0;
569 unsigned num_insts_discarded = 0;
573 Fault fault = inst->fault;
574 bool discarded =
false;
575 bool issued_mem_ref =
false;
577 if (inst->isBubble()) {
583 DPRINTF(MinorExecute,
"Discarding inst: %s from suspended"
588 }
else if (inst->id.streamSeqNum != thread.
streamSeqNum) {
589 DPRINTF(MinorExecute,
"Discarding inst: %s as its stream"
590 " state was unexpected, expected: %d\n",
607 DPRINTF(MinorExecute,
"Trying to issue inst: %s to FU: %d\n",
614 bool fu_is_capable = (!inst->isFault() ?
615 fu->provides(inst->staticInst->opClass()) :
true);
617 if (inst->isNoCostInst()) {
632 inst->extraCommitDelay =
Cycles(0);
633 inst->extraCommitDelayExpr = NULL;
642 }
else if (!fu_is_capable ||
fu->alreadyPushed()) {
644 if (!fu_is_capable) {
645 DPRINTF(MinorExecute,
"Can't issue as FU: %d isn't"
646 " capable\n", fu_index);
648 DPRINTF(MinorExecute,
"Can't issue as FU: %d is"
649 " already busy\n", fu_index);
651 }
else if (
fu->stalled) {
652 DPRINTF(MinorExecute,
"Can't issue inst: %s into FU: %d,"
655 }
else if (!
fu->canInsert()) {
656 DPRINTF(MinorExecute,
"Can't issue inst: %s to busy FU"
657 " for another: %d cycles\n",
658 *inst,
fu->cyclesBeforeInsert());
661 fu->findTiming(inst->staticInst) : NULL);
668 &(
fu->cantForwardFromFUIndices);
671 DPRINTF(MinorExecute,
"Can't issue inst: %s as extra"
672 " decoding is suppressing it\n",
674 }
else if (!
scoreboard[thread_id].canInstIssue(inst,
675 src_latencies, cant_forward_from_fu_indices,
678 DPRINTF(MinorExecute,
"Can't issue inst: %s yet\n",
682 DPRINTF(MinorExecute,
"Issuing inst: %s"
683 " into FU %d\n", *inst,
687 TimingExpr *extra_dest_retire_lat_expr = NULL;
693 extra_dest_retire_lat =
695 extra_dest_retire_lat_expr =
701 issued_mem_ref = inst->isMemRef();
706 inst->fuIndex = fu_index;
707 inst->extraCommitDelay = extra_dest_retire_lat;
708 inst->extraCommitDelayExpr =
709 extra_dest_retire_lat_expr;
711 if (issued_mem_ref) {
716 inst->instToWaitFor =
717 scoreboard[thread_id].execSeqNumToWaitFor(inst,
723 DPRINTF(MinorExecute,
"A barrier will"
724 " cause a delay in mem ref issue of"
725 " inst: %s until after inst"
726 " %d(exec)\n", *inst,
729 inst->instToWaitFor =
732 DPRINTF(MinorExecute,
"Memory ref inst:"
733 " %s must wait for inst %d(exec)"
735 *inst, inst->instToWaitFor);
738 inst->canEarlyIssue =
true;
742 DPRINTF(MinorExecute,
"Pushing mem inst: %s\n",
756 fu->description.opLat +
757 extra_dest_retire_lat +
760 issued_mem_ref && extra_assumed_lat ==
Cycles(0));
774 DPRINTF(MinorExecute,
"Didn't issue inst: %s\n", *inst);
780 if (
DTRACE(MinorTrace) && !inst->isBubble())
781 inst->minorTraceInst(*
this);
784 if (!discarded && inst->isInst() &&
785 inst->staticInst->isMemBarrier())
787 DPRINTF(MinorMem,
"Issuing memory barrier inst: %s\n", *inst);
792 inst->traceData->setWhen(
curTick());
796 num_mem_insts_issued++;
799 num_insts_discarded++;
800 }
else if (!inst->isBubble()) {
804 DPRINTF(MinorExecute,
"Reached inst issue limit\n");
808 DPRINTF(MinorExecute,
"Stepping to next inst inputIndex: %d\n",
820 DPRINTF(MinorExecute,
"Wrapping\n");
831 return num_insts_issued;
838 unsigned int num_pc_event_checks = 0;
844 cpu.
threads[thread_id]->pcEventQueue.service(oldPC, thread);
845 num_pc_event_checks++;
846 }
while (oldPC != thread->
instAddr());
848 if (num_pc_event_checks > 1) {
853 return num_pc_event_checks > 1;
859 assert(!inst->isFault());
865 if (!inst->staticInst->isMicroop() || inst->staticInst->isLastMicroop())
879 [inst->staticInst->opClass()]++;
883 inst->traceData->setCPSeq(thread->
numOp);
891 bool &completed_mem_issue)
893 ThreadID thread_id = inst->id.threadId;
896 bool completed_inst =
true;
904 panic(
"We should never hit the case where we try to commit from a "
905 "suspended thread as the streamSeqNum should not match");
906 }
else if (inst->isFault()) {
909 DPRINTF(MinorExecute,
"Fault inst reached Execute: %s\n",
910 inst->fault->name());
913 inst->fault->invoke(thread, NULL);
916 }
else if (inst->staticInst->isMemRef()) {
929 bool predicate_passed =
false;
931 predicate_passed, fault);
933 if (completed_mem_inst && fault !=
NoFault) {
934 if (early_memory_issue) {
935 DPRINTF(MinorExecute,
"Fault in early executing inst: %s\n",
939 inst->canEarlyIssue =
false;
942 completed_inst =
false;
944 DPRINTF(MinorExecute,
"Fault in execute: %s\n",
946 fault->invoke(thread, NULL);
949 completed_inst =
true;
952 completed_inst = completed_mem_inst;
954 completed_mem_issue = completed_inst;
955 }
else if (inst->isInst() && inst->staticInst->isMemBarrier() &&
958 DPRINTF(MinorExecute,
"Can't commit data barrier inst: %s yet as"
959 " there isn't space in the store buffer\n", *inst);
961 completed_inst =
false;
962 }
else if (inst->isInst() && inst->staticInst->isQuiesce()
966 completed_inst =
false;
970 DPRINTF(MinorExecute,
"Committing inst: %s\n", *inst);
972 fault = inst->staticInst->execute(&context,
982 if (inst->traceData) {
983 if (
DTRACE(ExecFaulting)) {
984 inst->traceData->setFaulting(
true);
986 delete inst->traceData;
987 inst->traceData = NULL;
991 DPRINTF(MinorExecute,
"Fault in execute of inst: %s fault: %s\n",
992 *inst, fault->name());
993 fault->invoke(thread, inst->staticInst);
1000 if (completed_inst) {
1004 executeInfo[thread_id].lastPredictionSeqNum = inst->id.predictionSeqNum;
1007 if (!inst->isFault() &&
1015 assert(resume_pc.microPC() == 0);
1017 DPRINTF(MinorInterrupt,
"Suspending thread: %d from Execute"
1018 " inst: %s\n", thread_id, *inst);
1027 return completed_inst;
1065 bool completed_inst =
true;
1068 unsigned int num_insts_committed = 0;
1072 unsigned int num_mem_refs_committed = 0;
1074 if (only_commit_microops && !ex_info.
inFlightInsts->empty()) {
1075 DPRINTF(MinorInterrupt,
"Only commit microops %s %d\n",
1087 if (only_commit_microops) {
1088 DPRINTF(MinorInterrupt,
"Committing tail of insts before"
1096 head_inflight_inst->
inst->id.execSeqNum;
1103 bool committed_inst =
false;
1104 bool discard_inst =
false;
1105 bool completed_mem_ref =
false;
1106 bool issued_mem_ref =
false;
1107 bool early_memory_issue =
false;
1110 completed_inst =
false;
1122 DPRINTF(MinorExecute,
"Trying to commit canCommitInsts: %d\n",
1132 }
else if (mem_response &&
1136 discard_inst = inst->id.streamSeqNum !=
1139 DPRINTF(MinorExecute,
"Trying to commit mem response: %s\n",
1144 DPRINTF(MinorExecute,
"Discarding mem inst: %s as its"
1145 " stream state was unexpected, expected: %d\n",
1151 committed_inst =
true;
1154 completed_mem_ref =
true;
1155 completed_inst =
true;
1156 }
else if (can_commit_insts) {
1161 bool try_to_commit =
false;
1173 DPRINTF(MinorExecute,
"Trying to commit from mem FUs\n");
1182 if (!fu_inst->isBubble() &&
1184 fu_inst->canEarlyIssue &&
1186 head_exec_seq_num > fu_inst->instToWaitFor)
1188 DPRINTF(MinorExecute,
"Issuing mem ref early"
1189 " inst: %s instToWaitFor: %d\n",
1190 *(fu_inst), fu_inst->instToWaitFor);
1193 try_to_commit =
true;
1194 early_memory_issue =
true;
1195 completed_inst =
true;
1200 if (!completed_inst && inst->isNoCostInst()) {
1201 DPRINTF(MinorExecute,
"Committing no cost inst: %s", *inst);
1203 try_to_commit =
true;
1204 completed_inst =
true;
1209 if (!completed_inst && !inst->inLSQ) {
1210 DPRINTF(MinorExecute,
"Trying to commit from FUs\n");
1219 if (fu_inst.
inst->isBubble()) {
1221 completed_inst =
false;
1222 }
else if (fu_inst_seq_num != head_exec_seq_num) {
1228 }
else if (fu_inst.
inst->id == inst->id) {
1232 try_to_commit =
true;
1233 completed_inst =
true;
1237 if (try_to_commit) {
1238 discard_inst = inst->id.streamSeqNum !=
1243 if (!discard_inst) {
1249 if (inst->extraCommitDelayExpr) {
1250 DPRINTF(MinorExecute,
"Evaluating expression for"
1251 " extra commit delay inst: %s\n", *inst);
1258 uint64_t extra_delay = inst->extraCommitDelayExpr->
1261 DPRINTF(MinorExecute,
"Extra commit delay expr"
1262 " result: %d\n", extra_delay);
1264 if (extra_delay < 128) {
1265 inst->extraCommitDelay +=
Cycles(extra_delay);
1267 DPRINTF(MinorExecute,
"Extra commit delay was"
1268 " very long: %d\n", extra_delay);
1270 inst->extraCommitDelayExpr = NULL;
1275 if (inst->extraCommitDelay !=
Cycles(0)) {
1276 inst->minimumCommitCycle =
cpu.curCycle() +
1277 inst->extraCommitDelay;
1278 inst->extraCommitDelay =
Cycles(0);
1283 if (!inst->isFault() && inst->isMemRef() &&
1285 inst->id.execSeqNum &&
1288 DPRINTF(MinorExecute,
"Not committing inst: %s yet"
1289 " as there are incomplete barriers in flight\n",
1291 completed_inst =
false;
1292 }
else if (inst->minimumCommitCycle > now) {
1293 DPRINTF(MinorExecute,
"Not committing inst: %s yet"
1294 " as it wants to be stalled for %d more cycles\n",
1295 *inst, inst->minimumCommitCycle - now);
1296 completed_inst =
false;
1299 early_memory_issue, branch, fault,
1300 committed_inst, issued_mem_ref);
1304 completed_inst =
true;
1307 if (completed_inst) {
1313 DPRINTF(MinorExecute,
"Unstalling %d for inst %s\n", inst->fuIndex, inst->id);
1314 funcUnits[inst->fuIndex]->stalled =
false;
1319 DPRINTF(MinorExecute,
"No instructions to commit\n");
1320 completed_inst =
false;
1324 assert(!(discard_inst && !completed_inst));
1329 DPRINTF(MinorExecute,
"Discarding inst: %s as its stream"
1330 " state was unexpected, expected: %d\n",
1338 if (issued_mem_ref) {
1345 if (completed_inst && inst->isMemRef()) {
1355 if (completed_inst && !(issued_mem_ref && fault ==
NoFault)) {
1357 DPRINTF(MinorExecute,
"Completed inst: %s\n", *inst);
1361 inst->isLastOpInInst();
1372 if (inst->isInst() && inst->staticInst->isMemBarrier()) {
1373 DPRINTF(MinorMem,
"Completing memory barrier"
1374 " inst: %s committed: %d\n", *inst, committed_inst);
1378 scoreboard[thread_id].clearInstDests(inst, inst->isMemRef());
1382 if (committed_inst) {
1383 bool is_no_cost_inst = inst->isNoCostInst();
1387 if (
DTRACE(MinorTrace) && !is_no_cost_inst)
1390 if (!is_no_cost_inst)
1391 num_insts_committed++;
1394 DPRINTF(MinorExecute,
"Reached inst commit limit\n");
1398 if (inst->traceData) {
1400 inst->traceData->setWhen(
curTick());
1401 inst->traceData->dump();
1404 if (completed_mem_ref)
1405 num_mem_refs_committed++;
1408 DPRINTF(MinorExecute,
"Reached mem ref commit limit\n");
1416 return executeInfo[thread_id].lastCommitWasEndOfMacroop &&
1423 if (!
inp.outputWire->isBubble())
1428 unsigned int num_issued = 0;
1435 bool interrupted =
false;
1444 DPRINTF(MinorInterrupt,
"Execute skipping a cycle to allow old"
1445 " branch to complete\n");
1452 DPRINTF(MinorExecute,
"Attempting to commit [tid:%d]\n",
1459 commit(commit_tid,
true,
false, branch);
1470 commit(commit_tid,
false,
true, branch);
1475 DPRINTF(MinorExecute,
"Committing micro-ops for interrupt[tid:%d]\n",
1477 bool only_commit_microops = interrupted &&
1479 commit(commit_tid, only_commit_microops,
false, branch);
1496 DPRINTF(MinorExecute,
"Attempting to issue [tid:%d]\n",
1498 num_issued =
issue(issue_tid);
1506 bool can_issue_next =
false;
1512 unsigned int input_index =
executeInfo[tid].inputIndex;
1514 if (inst->isFault()) {
1515 can_issue_next =
true;
1516 }
else if (!inst->isBubble()) {
1517 next_issuable_insts.push_back(inst);
1522 bool becoming_stalled =
true;
1532 if (
fu->occupancy !=0 && !
fu->stalled)
1533 becoming_stalled =
false;
1539 for (
auto inst : next_issuable_insts) {
1540 if (!
fu->stalled &&
fu->provides(inst->staticInst->opClass()) &&
1541 scoreboard[inst->id.threadId].canInstIssue(inst,
1544 can_issue_next =
true;
1550 bool head_inst_might_commit =
false;
1554 if (!info.inFlightInsts->empty()) {
1555 const QueuedInst &head_inst = info.inFlightInsts->front();
1557 if (head_inst.
inst->isNoCostInst()) {
1558 head_inst_might_commit =
true;
1562 fu->front().inst->id == head_inst.
inst->id) ||
1565 head_inst_might_commit =
true;
1572 DPRINTF(Activity,
"Need to tick num issued insts: %s%s%s%s%s%s\n",
1573 (num_issued != 0 ?
" (issued some insts)" :
""),
1574 (becoming_stalled ?
"(becoming stalled)" :
"(not becoming stalled)"),
1575 (can_issue_next ?
" (can issued next inst)" :
""),
1576 (head_inst_might_commit ?
"(head inst might commit)" :
""),
1578 (interrupted ?
" (interrupted)" :
""));
1582 !becoming_stalled ||
1584 head_inst_might_commit ||
1588 if (!need_to_tick) {
1589 DPRINTF(Activity,
"The next cycle might be skippable as there are no"
1590 " advanceable FUs\n");
1602 if (!
inp.outputWire->isBubble())
1614 bool thread_interrupted =
false;
1621 interrupted = interrupted || thread_interrupted;
1623 DPRINTF(MinorInterrupt,
"No interrupt controller\n");
1625 DPRINTF(MinorInterrupt,
"[tid:%d] thread_interrupted?=%d isInbetweenInsts?=%d\n",
1655 std::ostringstream insts;
1656 std::ostringstream stalled;
1658 executeInfo[0].instsBeingCommitted.reportData(insts);
1667 stalled << (
funcUnits[
i]->stalled ?
'1' :
'E');
1673 MINORTRACE(
"insts=%s inputIndex=%d streamSeqNum=%d"
1674 " stalled=%s drainState=%d isInbetweenInsts=%d\n",
1691 case Enums::SingleThreaded:
1693 case Enums::RoundRobin:
1700 panic(
"Invalid thread policy");
1703 for (
auto tid : priority_list) {
1706 if (can_commit_insts) {
1710 can_commit_insts = can_commit_insts &&
1714 bool can_transfer_mem_inst =
false;
1720 can_transfer_mem_inst =
1721 !fu_inst->isBubble() &&
1722 fu_inst->id.threadId == tid &&
1724 fu_inst->canEarlyIssue &&
1725 inst->id.execSeqNum > fu_inst->instToWaitFor;
1729 if (can_commit_insts && !can_transfer_mem_inst &&
1733 can_execute_fu_inst = !fu_inst.
inst->isBubble() &&
1734 fu_inst.
inst->id == inst->id;
1737 can_commit_insts = can_commit_insts &&
1738 (can_transfer_mem_inst || can_execute_fu_inst);
1743 if (can_commit_insts) {
1758 case Enums::SingleThreaded:
1760 case Enums::RoundRobin:
1767 panic(
"Invalid thread scheduling policy.");
1770 for (
auto tid : priority_list) {
1783 DPRINTF(Drain,
"MinorExecute drainResume\n");
1797 os <<
"NotDraining";
1800 os <<
"DrainCurrentInst";
1803 os <<
"DrainHaltFetch";
1806 os <<
"DrainAllInsts";
1809 os <<
"Drain-" <<
static_cast<int>(state);
1819 DPRINTF(Drain,
"setDrainState[%d]: %s\n", thread_id, state);
1826 DPRINTF(Drain,
"MinorExecute drain\n");
1874 return inst->id.streamSeqNum ==
executeInfo[inst->id.threadId].streamSeqNum;
1882 if (!
executeInfo[inst->id.threadId].inFlightInsts->empty())
1883 ret =
executeInfo[inst->id.threadId].inFlightInsts->front().inst->id == inst->id;
Queue< QueuedInst, ReportTraitsAdaptor< QueuedInst > > * inFUMemInsts
Memory ref instructions still in the FUs.
const ThreadID InvalidThreadID
static const OpClass Num_OpClasses
Stats::Scalar numInsts
Stat for number instructions committed.
MinorCPU::MinorCPUPort & getDcachePort()
Return the raw-bindable port.
#define fatal(...)
This implements a cprintf based fatal() function.
std::vector< InputBuffer< ForwardInstData > > inputBuffer
std::vector< Cycles > srcRegsRelativeLats
Cycle offsets from the scoreboard delivery times of register values for each of this instruction's so...
bool isInterrupted(ThreadID thread_id) const
Has an interrupt been raised.
void popResponse(LSQRequestPtr response)
Sanity check and pop the head response.
Latch< BranchData >::Input out
Input port carrying stream changes to Fetch1.
void wakeupOnEvent(unsigned int stage_id)
Interface for stages to signal that they have become active after a callback or eventq event where th...
Forward flowing data between Fetch2,Decode,Execute carrying a packet of instructions of a width appro...
bool tryPCEvents(ThreadID thread_id)
Try to act on PC-related events.
void minorTrace() const
Report buffer states from 'slot' 'from' to 'to'.
Object to gather the visible context for evaluation.
Extra timing capability to allow individual ops to have their source register dependency latencies tw...
bool lastCommitWasEndOfMacroop
The last commit was the end of a full instruction so an interrupt can safely happen.
bool isStreamChange() const
As static isStreamChange but on this branch data.
void pushFailedRequest(MinorDynInstPtr inst)
Push a predicate failed-representing request into the queues just to maintain commit order.
bool processMoreThanOneInput
If true, more than one input line can be processed each cycle if there is room to execute more instru...
int16_t ThreadID
Thread index/ID type.
Stats::Vector2d committedInstType
Number of instructions by type (OpClass)
ThreadID checkInterrupts(BranchData &branch, bool &interrupted)
Check all threads for possible interrupts.
Minor::MinorActivityRecorder * activityRecorder
Activity recording for pipeline.
MinorFUPool & fuDescriptions
Descriptions of the functional units we want to generate.
const std::string to_string(sc_enc enc)
LSQ lsq
Dcache port to pass on to the CPU.
bool hasInterrupt(ThreadID thread_id)
Checks if a specific thread has an interrupt.
bool instIsRightStream(MinorDynInstPtr inst)
Does the given instruction have the right stream sequence number to be committed?
Stats::Scalar numDiscardedOps
Number of ops discarded before committing.
bool accessesInFlight() const
Are there any accesses other than normal cached loads in the memory system or having received respons...
bool isInbetweenInsts(ThreadID thread_id) const
Are we between instructions? Can we be interrupted?
Enums::ThreadPolicy threadPolicy
Thread Scheduling Policy (RoundRobin, Random, etc)
void step()
Step checks the queues to see if their are issuable transfers which were not otherwise picked up by t...
#define MINORTRACE(...)
DPRINTFN for MinorTrace reporting.
Minor::MinorStats stats
Processor-specific statistics.
std::vector< MinorFU * > funcUnits
bool FullSystem
The FullSystem variable can be used to determine the current mode of simulation.
bool suppress
If true, instructions matching this mask/match should not be issued in this FU.
virtual ThreadContext * getContext(int tn)
Given a thread num get tho thread context for it.
ThreadID interruptPriority
InstSeqNum streamSeqNum
Source of sequence number for instuction streams.
std::vector< Scoreboard > scoreboard
Scoreboard of instruction dependencies.
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...
bool executeMemRefInst(MinorDynInstPtr inst, BranchData &branch, bool &failed_predicate, Fault &fault)
Execute a memory reference instruction.
@ BadlyPredictedBranchTarget
unsigned int cyclicIndexDec(unsigned int index, unsigned int cycle_size)
Decrement a cyclic buffer index for indices [0, cycle_size-1].
void advancePC(PCState &pc, const StaticInstPtr &inst)
bool isDrained()
After thread suspension, has Execute been drained of in-flight instructions and memory accesses.
bool commitInst(MinorDynInstPtr inst, bool early_memory_issue, BranchData &branch, Fault &fault, bool &committed, bool &completed_mem_issue)
Commit a single instruction.
@ CorrectlyPredictedBranch
Latch< ForwardInstData >::Output inp
Input port carrying instructions from Decode.
Cycles opLat
Delay from issuing the operation, to it reaching the end of the associated pipeline.
unsigned int inputIndex
Index that we've completed upto in getInput data.
The SimpleThread object provides a combination of the ThreadState object and the ThreadContext interf...
std::vector< Minor::MinorThread * > threads
These are thread state-representing objects for this CPU.
std::vector< ExecuteThreadInfo > executeInfo
bool canRequest()
Is their space in the request queue to be able to push a request by issuing an isMemRef instruction.
...ReportTraits are trait classes with the same functionality as ReportIF, but with elements explicit...
InstSeqNum lastPredictionSeqNum
A prediction number for use where one isn't available from an instruction.
Cycles extraAssumedLat
Extra delay that results should show in the scoreboard after leaving the pipeline.
MinorCPU::MinorCPUPort & getDcachePort()
Returns the DcachePort owned by this Execute to pass upwards.
void completeMemBarrierInst(MinorDynInstPtr inst, bool committed)
Complete a barrier instruction.
ThreadContext is the external interface to all thread state for anything outside of the CPU.
Counter numOp
Number of ops (including micro ops) committed.
static MinorDynInstPtr bubble()
There is a single bubble inst.
MinorCPU is an in-order CPU model with four fixed pipeline stages:
DrainState
Stage cycle-by-cycle state.
Wrapper for a queue type to act as a pipeline stage input queue.
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...
bool needsToBeSentToStoreBuffer()
This request, once processed by the requests/transfers queues, will need to go to the store buffer.
std::shared_ptr< FaultBase > Fault
unsigned int width() const
Number of instructions carried by this object.
void evaluate()
Pass on input/buffer data to the output if you can.
unsigned int drain()
Like the drain interface on SimObject.
bool isBubble() const
BubbleIF interface.
void serviceEvents(Tick when)
process all events up to the given timestamp.
bool setTraceTimeOnIssue
Modify instruction trace times on issue.
Counter numInst
Number of instructions committed.
bool canPushIntoStoreBuffer() const
Must check this before trying to insert into the store buffer.
unsigned int issueLimit
Number of instructions that can be issued per cycle.
bool needsToTick()
May need to be ticked next cycle as one of the queues contains an actionable transfers or address tra...
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...
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 cyclicIndexInc(unsigned int index, unsigned int cycle_size)
Increment a cyclic buffer index for indices [0, cycle_size-1].
Provide a non-protected base class for Minor's Ports as derived classes are created by Fetch1 and Exe...
MinorDynInstPtr insts[MAX_FORWARD_INSTS]
Array of carried insts, ref counted.
void popInput(ThreadID tid)
Pop an element off the input buffer, if there are any.
unsigned int memoryCommitLimit
Number of memory instructions that can be committed per cycle.
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.
bool readMemAccPredicate() const override
MinorCPU & cpu
Pointer back to the containing CPU.
Queue< QueuedInst, ReportTraitsAdaptor< QueuedInst > > * inFlightInsts
In-order instructions either in FUs or the LSQ.
constexpr decltype(nullptr) NoFault
virtual Status status() const =0
void setDrainState(ThreadID thread_id, DrainState state)
Set the drain state (with useful debugging messages)
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Stats::Scalar numInsts
Number of simulated instructions.
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 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
bool setTraceTimeOnCommit
Modify instruction trace times on commit.
Stats::Scalar numOps
Stat for number ops (including micro ops) committed.
virtual TheISA::PCState pcState() const =0
unsigned int issue(ThreadID thread_id)
Try and issue instructions from the inputBuffer.
EventQueue comInstEventQueue
An instruction-based event queue.
Forward data betwen Execute and Fetch1 carrying change-of-address/stream information.
virtual void updateIntrInfo()=0
ForwardInstData instsBeingCommitted
Structure for reporting insts currently being processed/retired for MinorTrace.
std::ostream & operator<<(std::ostream &os, const InstId &id)
Print this id in the usual slash-separated format expected by MinorTrace.
void doInstCommitAccounting(MinorDynInstPtr inst)
Do the stats handling and instruction count and PC event events related to the new instruction/op cou...
bool instIsHeadInst(MinorDynInstPtr inst)
Returns true if the given instruction is at the head of the inFlightInsts instruction queue.
@ Suspended
Temporarily inactive.
void issuedMemBarrierInst(MinorDynInstPtr inst)
A memory barrier instruction has been issued, remember its execSeqNum that we can avoid issuing memor...
bool readPredicate() const override
ExecContext bears the exec_context interface for Minor.
GenericISA::DelaySlotPCState< MachInst > PCState
void activity()
Records that there is activity this cycle.
std::vector< ThreadID > roundRobinPriority(ThreadID priority)
Thread scheduling utility functions.
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.
unsigned int memoryIssueLimit
Number of memory ops that can be issued per cycle.
A functional unit configured from a MinorFU object.
void sendStoreToStoreBuffer(LSQRequestPtr request)
A store has been committed, please move it to the store buffer.
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....
Cycles extraCommitLat
Extra latency that the instruction should spend at the end of the pipeline.
static BranchData bubble()
BubbleIF interface.
A scoreboard of register dependencies including, for each register: The number of in-flight instructi...
ThreadID numThreads
Number of threads we're actually simulating (<= SMT_MAX_THREADS).
InstSeqNum getLastMemBarrier(ThreadID thread_id) const
Get the execSeqNum of the last issued memory barrier.
Cycles is a wrapper class for representing cycle counts, i.e.
std::vector< FUPipeline * > funcUnits
The execution functional units.
Container class to box instructions in the FUs to make those queues have correct bubble behaviour whe...
std::vector< ThreadID > randomPriority()
unsigned int numFuncUnits
Number of functional units to produce.
TimingExpr * extraCommitLatExpr
bool takeInterrupt(ThreadID thread_id, BranchData &branch)
Act on an interrupt.
bool isDrained()
Is there nothing left in the LSQ.
DrainState drainState
State progression for draining NotDraining -> ...
Stats::Scalar numFetchSuspends
Number of times fetch was asked to suspend by Execute.
Execute(const std::string &name_, MinorCPU &cpu_, MinorCPUParams ¶ms, Latch< ForwardInstData >::Output inp_, Latch< BranchData >::Input out_)
virtual void probeInstCommit(const StaticInstPtr &inst, Addr pc)
Helper method to trigger PMU probes for a committed instruction.
bool checkInterrupts(ThreadID tid) const
virtual Addr instAddr() const =0
const T * getConstPtr() const
BaseInterrupts * getInterruptController(ThreadID tid)
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...
ThreadState::ThreadStateStats threadStats
Derived SenderState to carry data access info.
ThreadID getIssuingThread()
unsigned int noCostFUIndex
The FU index of the non-existent costless FU for instructions which pass the MinorDynInst::isNoCostIn...
#define panic(...)
This implements a cprintf based panic() function.
Tick curTick()
The current simulated tick.
Stats::Scalar numOps
Number of simulated insts and microops.
Generated on Wed Sep 30 2020 14:02:08 for gem5 by doxygen 1.8.17