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++) {
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->isSquashAfter() ||
229 inst->staticInst->isIprAccess());
231 DPRINTF(Branch,
"tryToBranch before: %s after: %s%s\n",
232 pc_before, target, (force_branch ?
" (forcing)" :
""));
235 bool must_branch = pc_before != target ||
247 DPRINTF(Branch,
"Advancing current PC from: %s to: %s\n",
251 if (inst->predictedTaken && !force_branch) {
256 DPRINTF(Branch,
"Predicted a branch from 0x%x to 0x%x but" 257 " none happened inst: %s\n",
258 inst->pc.instAddr(), inst->predictedTarget.instAddr(), *inst);
261 }
else if (inst->predictedTarget == target) {
266 DPRINTF(Branch,
"Predicted a branch from 0x%x to 0x%x correctly" 268 inst->pc.instAddr(), inst->predictedTarget.instAddr(), *inst);
273 DPRINTF(Branch,
"Predicted a branch from 0x%x to 0x%x" 274 " but got the wrong target (actual: 0x%x) inst: %s\n",
275 inst->pc.instAddr(), inst->predictedTarget.instAddr(),
276 target.instAddr(), *inst);
280 }
else if (must_branch) {
282 DPRINTF(Branch,
"Unpredicted branch from 0x%x to 0x%x inst: %s\n",
283 inst->pc.instAddr(), target.instAddr(), *inst);
312 (inst->isBubble() ?
executeInfo[tid].lastPredictionSeqNum
313 : inst->id.predictionSeqNum),
316 DPRINTF(Branch,
"Branch data signalled: %s\n", branch);
324 ThreadID thread_id = inst->id.threadId;
331 bool is_load = inst->staticInst->isLoad();
332 bool is_store = inst->staticInst->isStore();
333 bool is_atomic = inst->staticInst->isAtomic();
334 bool is_prefetch = inst->staticInst->isDataPrefetch();
338 bool use_context_predicate =
true;
340 if (inst->translationFault !=
NoFault) {
342 DPRINTF(MinorMem,
"Completing fault from DTLB access: %s\n",
343 inst->translationFault->name());
345 if (inst->staticInst->isPrefetch()) {
346 DPRINTF(MinorMem,
"Not taking fault on prefetch: %s\n",
347 inst->translationFault->name());
352 fault = inst->translationFault;
354 fault->invoke(thread, inst->staticInst);
356 }
else if (!packet) {
357 DPRINTF(MinorMem,
"Completing failed request inst: %s\n",
359 use_context_predicate =
false;
361 inst->staticInst->completeAcc(
nullptr, &context, inst->traceData);
362 }
else if (packet->
isError()) {
363 DPRINTF(MinorMem,
"Trying to commit error response: %s\n",
366 fatal(
"Received error response packet for inst: %s\n", *inst);
367 }
else if (is_store || is_load || is_prefetch || is_atomic) {
370 DPRINTF(MinorMem,
"Memory response inst: %s addr: 0x%x size: %d\n",
373 if (is_load && packet->
getSize() > 0) {
374 DPRINTF(MinorMem,
"Memory data[0]: 0x%x\n",
375 static_cast<unsigned int>(packet->
getConstPtr<uint8_t>()[0]));
379 fault = inst->staticInst->completeAcc(packet, &context,
384 DPRINTF(MinorMem,
"Fault in memory completeAcc: %s\n",
386 fault->invoke(thread, inst->staticInst);
394 fatal(
"There should only ever be reads, " 395 "writes or faults at this point\n");
400 if (inst->traceData) {
401 inst->traceData->setPredicate((use_context_predicate ?
420 DPRINTF(MinorInterrupt,
"Considering interrupt status from PC: %s\n",
434 DPRINTF(MinorInterrupt,
"Invoking interrupt: %s to PC: %s\n",
449 bool &passed_predicate,
Fault &fault)
454 passed_predicate =
false;
467 DPRINTF(MinorExecute,
"Initiating memRef inst: %s\n", *inst);
469 Fault init_fault = inst->staticInst->initiateAcc(&context,
474 assert(inst->translationFault !=
NoFault);
480 inst->translationFault =
NoFault;
485 DPRINTF(MinorExecute,
"Fault on memory inst: %s" 486 " initiateAcc: %s\n", *inst, init_fault->name());
492 DPRINTF(MinorMem,
"No memory access for inst: %s\n", *inst);
499 inst->traceData->setPredicate(passed_predicate);
525 unsigned int ret = index + 1;
527 if (ret == cycle_size)
540 ret = cycle_size - 1;
556 unsigned int fu_index = 0;
565 unsigned num_insts_issued = 0;
568 unsigned num_mem_insts_issued = 0;
572 unsigned num_insts_discarded = 0;
576 Fault fault = inst->fault;
577 bool discarded =
false;
578 bool issued_mem_ref =
false;
580 if (inst->isBubble()) {
586 DPRINTF(MinorExecute,
"Discarding inst: %s from suspended" 591 }
else if (inst->id.streamSeqNum != thread.
streamSeqNum) {
592 DPRINTF(MinorExecute,
"Discarding inst: %s as its stream" 593 " state was unexpected, expected: %d\n",
610 DPRINTF(MinorExecute,
"Trying to issue inst: %s to FU: %d\n",
617 bool fu_is_capable = (!inst->isFault() ?
618 fu->
provides(inst->staticInst->opClass()) :
true);
620 if (inst->isNoCostInst()) {
635 inst->extraCommitDelay =
Cycles(0);
636 inst->extraCommitDelayExpr = NULL;
647 if (!fu_is_capable) {
648 DPRINTF(MinorExecute,
"Can't issue as FU: %d isn't" 649 " capable\n", fu_index);
651 DPRINTF(MinorExecute,
"Can't issue as FU: %d is" 652 " already busy\n", fu_index);
655 DPRINTF(MinorExecute,
"Can't issue inst: %s into FU: %d," 659 DPRINTF(MinorExecute,
"Can't issue inst: %s to busy FU" 660 " for another: %d cycles\n",
674 DPRINTF(MinorExecute,
"Can't issue inst: %s as extra" 675 " decoding is suppressing it\n",
677 }
else if (!
scoreboard[thread_id].canInstIssue(inst,
678 src_latencies, cant_forward_from_fu_indices,
681 DPRINTF(MinorExecute,
"Can't issue inst: %s yet\n",
685 DPRINTF(MinorExecute,
"Issuing inst: %s" 686 " into FU %d\n", *inst,
690 TimingExpr *extra_dest_retire_lat_expr = NULL;
696 extra_dest_retire_lat =
698 extra_dest_retire_lat_expr =
704 issued_mem_ref = inst->isMemRef();
709 inst->fuIndex = fu_index;
710 inst->extraCommitDelay = extra_dest_retire_lat;
711 inst->extraCommitDelayExpr =
712 extra_dest_retire_lat_expr;
714 if (issued_mem_ref) {
719 inst->instToWaitFor =
720 scoreboard[thread_id].execSeqNumToWaitFor(inst,
726 DPRINTF(MinorExecute,
"A barrier will" 727 " cause a delay in mem ref issue of" 728 " inst: %s until after inst" 729 " %d(exec)\n", *inst,
732 inst->instToWaitFor =
735 DPRINTF(MinorExecute,
"Memory ref inst:" 736 " %s must wait for inst %d(exec)" 738 *inst, inst->instToWaitFor);
741 inst->canEarlyIssue =
true;
745 DPRINTF(MinorExecute,
"Pushing mem inst: %s\n",
760 extra_dest_retire_lat +
763 issued_mem_ref && extra_assumed_lat ==
Cycles(0));
777 DPRINTF(MinorExecute,
"Didn't issue inst: %s\n", *inst);
783 if (
DTRACE(MinorTrace) && !inst->isBubble())
784 inst->minorTraceInst(*
this);
787 if (!discarded && inst->isInst() &&
788 inst->staticInst->isMemBarrier())
790 DPRINTF(MinorMem,
"Issuing memory barrier inst: %s\n", *inst);
795 inst->traceData->setWhen(
curTick());
799 num_mem_insts_issued++;
802 num_insts_discarded++;
803 }
else if (!inst->isBubble()) {
807 DPRINTF(MinorExecute,
"Reached inst issue limit\n");
811 DPRINTF(MinorExecute,
"Stepping to next inst inputIndex: %d\n",
823 DPRINTF(MinorExecute,
"Wrapping\n");
834 return num_insts_issued;
841 unsigned int num_pc_event_checks = 0;
847 cpu.
threads[thread_id]->pcEventQueue.service(oldPC, thread);
848 num_pc_event_checks++;
849 }
while (oldPC != thread->
instAddr());
851 if (num_pc_event_checks > 1) {
856 return num_pc_event_checks > 1;
862 assert(!inst->isFault());
868 if (!inst->staticInst->isMicroop() || inst->staticInst->isLastMicroop())
876 thread->comInstEventQueue.serviceEvents(thread->numInst);
882 [inst->staticInst->opClass()]++;
886 inst->traceData->setCPSeq(thread->numOp);
894 bool &completed_mem_issue)
896 ThreadID thread_id = inst->id.threadId;
899 bool completed_inst =
true;
907 panic(
"We should never hit the case where we try to commit from a " 908 "suspended thread as the streamSeqNum should not match");
909 }
else if (inst->isFault()) {
912 DPRINTF(MinorExecute,
"Fault inst reached Execute: %s\n",
913 inst->fault->name());
916 inst->fault->invoke(thread, NULL);
919 }
else if (inst->staticInst->isMemRef()) {
932 bool predicate_passed =
false;
934 predicate_passed, fault);
936 if (completed_mem_inst && fault !=
NoFault) {
937 if (early_memory_issue) {
938 DPRINTF(MinorExecute,
"Fault in early executing inst: %s\n",
942 inst->canEarlyIssue =
false;
945 completed_inst =
false;
947 DPRINTF(MinorExecute,
"Fault in execute: %s\n",
949 fault->invoke(thread, NULL);
952 completed_inst =
true;
955 completed_inst = completed_mem_inst;
957 completed_mem_issue = completed_inst;
958 }
else if (inst->isInst() && inst->staticInst->isMemBarrier() &&
961 DPRINTF(MinorExecute,
"Can't commit data barrier inst: %s yet as" 962 " there isn't space in the store buffer\n", *inst);
964 completed_inst =
false;
965 }
else if (inst->isInst() && inst->staticInst->isQuiesce()
969 completed_inst =
false;
973 DPRINTF(MinorExecute,
"Committing inst: %s\n", *inst);
975 fault = inst->staticInst->execute(&context,
985 DPRINTF(MinorExecute,
"Fault in execute of inst: %s fault: %s\n",
986 *inst, fault->name());
987 fault->invoke(thread, inst->staticInst);
994 if (completed_inst) {
998 executeInfo[thread_id].lastPredictionSeqNum = inst->id.predictionSeqNum;
1001 if (!inst->isFault() &&
1009 assert(resume_pc.microPC() == 0);
1011 DPRINTF(MinorInterrupt,
"Suspending thread: %d from Execute" 1012 " inst: %s\n", thread_id, *inst);
1021 return completed_inst;
1059 bool completed_inst =
true;
1062 unsigned int num_insts_committed = 0;
1066 unsigned int num_mem_refs_committed = 0;
1068 if (only_commit_microops && !ex_info.
inFlightInsts->empty()) {
1069 DPRINTF(MinorInterrupt,
"Only commit microops %s %d\n",
1081 if (only_commit_microops) {
1082 DPRINTF(MinorInterrupt,
"Committing tail of insts before" 1090 head_inflight_inst->
inst->id.execSeqNum;
1097 bool committed_inst =
false;
1098 bool discard_inst =
false;
1099 bool completed_mem_ref =
false;
1100 bool issued_mem_ref =
false;
1101 bool early_memory_issue =
false;
1104 completed_inst =
false;
1116 DPRINTF(MinorExecute,
"Trying to commit canCommitInsts: %d\n",
1126 }
else if (mem_response &&
1130 discard_inst = inst->id.streamSeqNum !=
1133 DPRINTF(MinorExecute,
"Trying to commit mem response: %s\n",
1138 DPRINTF(MinorExecute,
"Discarding mem inst: %s as its" 1139 " stream state was unexpected, expected: %d\n",
1145 committed_inst =
true;
1148 completed_mem_ref =
true;
1149 completed_inst =
true;
1150 }
else if (can_commit_insts) {
1155 bool try_to_commit =
false;
1167 DPRINTF(MinorExecute,
"Trying to commit from mem FUs\n");
1176 if (!fu_inst->isBubble() &&
1178 fu_inst->canEarlyIssue &&
1180 head_exec_seq_num > fu_inst->instToWaitFor)
1182 DPRINTF(MinorExecute,
"Issuing mem ref early" 1183 " inst: %s instToWaitFor: %d\n",
1184 *(fu_inst), fu_inst->instToWaitFor);
1187 try_to_commit =
true;
1188 early_memory_issue =
true;
1189 completed_inst =
true;
1194 if (!completed_inst && inst->isNoCostInst()) {
1195 DPRINTF(MinorExecute,
"Committing no cost inst: %s", *inst);
1197 try_to_commit =
true;
1198 completed_inst =
true;
1203 if (!completed_inst && !inst->inLSQ) {
1204 DPRINTF(MinorExecute,
"Trying to commit from FUs\n");
1213 if (fu_inst.
inst->isBubble()) {
1215 completed_inst =
false;
1216 }
else if (fu_inst_seq_num != head_exec_seq_num) {
1222 }
else if (fu_inst.
inst->id == inst->id) {
1226 try_to_commit =
true;
1227 completed_inst =
true;
1231 if (try_to_commit) {
1232 discard_inst = inst->id.streamSeqNum !=
1237 if (!discard_inst) {
1243 if (inst->extraCommitDelayExpr) {
1244 DPRINTF(MinorExecute,
"Evaluating expression for" 1245 " extra commit delay inst: %s\n", *inst);
1252 uint64_t extra_delay = inst->extraCommitDelayExpr->
1255 DPRINTF(MinorExecute,
"Extra commit delay expr" 1256 " result: %d\n", extra_delay);
1258 if (extra_delay < 128) {
1259 inst->extraCommitDelay +=
Cycles(extra_delay);
1261 DPRINTF(MinorExecute,
"Extra commit delay was" 1262 " very long: %d\n", extra_delay);
1264 inst->extraCommitDelayExpr = NULL;
1269 if (inst->extraCommitDelay !=
Cycles(0)) {
1271 inst->extraCommitDelay;
1272 inst->extraCommitDelay =
Cycles(0);
1277 if (!inst->isFault() && inst->isMemRef() &&
1279 inst->id.execSeqNum &&
1282 DPRINTF(MinorExecute,
"Not committing inst: %s yet" 1283 " as there are incomplete barriers in flight\n",
1285 completed_inst =
false;
1286 }
else if (inst->minimumCommitCycle > now) {
1287 DPRINTF(MinorExecute,
"Not committing inst: %s yet" 1288 " as it wants to be stalled for %d more cycles\n",
1289 *inst, inst->minimumCommitCycle - now);
1290 completed_inst =
false;
1293 early_memory_issue, branch, fault,
1294 committed_inst, issued_mem_ref);
1298 completed_inst =
true;
1301 if (completed_inst) {
1307 DPRINTF(MinorExecute,
"Unstalling %d for inst %s\n", inst->fuIndex, inst->id);
1308 funcUnits[inst->fuIndex]->stalled =
false;
1313 DPRINTF(MinorExecute,
"No instructions to commit\n");
1314 completed_inst =
false;
1318 assert(!(discard_inst && !completed_inst));
1323 DPRINTF(MinorExecute,
"Discarding inst: %s as its stream" 1324 " state was unexpected, expected: %d\n",
1332 if (issued_mem_ref) {
1339 if (completed_inst && inst->isMemRef()) {
1349 if (completed_inst && !(issued_mem_ref && fault ==
NoFault)) {
1351 DPRINTF(MinorExecute,
"Completed inst: %s\n", *inst);
1355 inst->isLastOpInInst();
1366 if (inst->isInst() && inst->staticInst->isMemBarrier()) {
1367 DPRINTF(MinorMem,
"Completing memory barrier" 1368 " inst: %s committed: %d\n", *inst, committed_inst);
1372 scoreboard[thread_id].clearInstDests(inst, inst->isMemRef());
1376 if (committed_inst) {
1377 bool is_no_cost_inst = inst->isNoCostInst();
1381 if (
DTRACE(MinorTrace) && !is_no_cost_inst)
1384 if (!is_no_cost_inst)
1385 num_insts_committed++;
1388 DPRINTF(MinorExecute,
"Reached inst commit limit\n");
1392 if (inst->traceData) {
1394 inst->traceData->setWhen(
curTick());
1395 inst->traceData->dump();
1398 if (completed_mem_ref)
1399 num_mem_refs_committed++;
1402 DPRINTF(MinorExecute,
"Reached mem ref commit limit\n");
1410 return executeInfo[thread_id].lastCommitWasEndOfMacroop &&
1417 if (!
inp.outputWire->isBubble())
1422 unsigned int num_issued = 0;
1429 bool interrupted =
false;
1438 DPRINTF(MinorInterrupt,
"Execute skipping a cycle to allow old" 1439 " branch to complete\n");
1446 DPRINTF(MinorExecute,
"Attempting to commit [tid:%d]\n",
1453 commit(commit_tid,
true,
false, branch);
1464 commit(commit_tid,
false,
true, branch);
1469 DPRINTF(MinorExecute,
"Committing micro-ops for interrupt[tid:%d]\n",
1471 bool only_commit_microops = interrupted &&
1473 commit(commit_tid, only_commit_microops,
false, branch);
1490 DPRINTF(MinorExecute,
"Attempting to issue [tid:%d]\n",
1492 num_issued =
issue(issue_tid);
1500 bool can_issue_next =
false;
1506 unsigned int input_index =
executeInfo[tid].inputIndex;
1508 if (inst->isFault()) {
1509 can_issue_next =
true;
1510 }
else if (!inst->isBubble()) {
1511 next_issuable_insts.push_back(inst);
1516 bool becoming_stalled =
true;
1527 becoming_stalled =
false;
1533 for (
auto inst : next_issuable_insts) {
1535 scoreboard[inst->id.threadId].canInstIssue(inst,
1538 can_issue_next =
true;
1544 bool head_inst_might_commit =
false;
1548 if (!info.inFlightInsts->empty()) {
1549 const QueuedInst &head_inst = info.inFlightInsts->front();
1551 if (head_inst.
inst->isNoCostInst()) {
1552 head_inst_might_commit =
true;
1556 fu->
front().inst->id == head_inst.
inst->id) ||
1559 head_inst_might_commit =
true;
1566 DPRINTF(Activity,
"Need to tick num issued insts: %s%s%s%s%s%s\n",
1567 (num_issued != 0 ?
" (issued some insts)" :
""),
1568 (becoming_stalled ?
"(becoming stalled)" :
"(not becoming stalled)"),
1569 (can_issue_next ?
" (can issued next inst)" :
""),
1570 (head_inst_might_commit ?
"(head inst might commit)" :
""),
1572 (interrupted ?
" (interrupted)" :
""));
1576 !becoming_stalled ||
1578 head_inst_might_commit ||
1582 if (!need_to_tick) {
1583 DPRINTF(Activity,
"The next cycle might be skippable as there are no" 1584 " advanceable FUs\n");
1596 if (!
inp.outputWire->isBubble())
1608 bool thread_interrupted =
false;
1615 interrupted = interrupted || thread_interrupted;
1617 DPRINTF(MinorInterrupt,
"No interrupt controller\n");
1619 DPRINTF(MinorInterrupt,
"[tid:%d] thread_interrupted?=%d isInbetweenInsts?=%d\n",
1649 std::ostringstream insts;
1650 std::ostringstream stalled;
1652 executeInfo[0].instsBeingCommitted.reportData(insts);
1661 stalled << (
funcUnits[
i]->stalled ?
'1' :
'E');
1667 MINORTRACE(
"insts=%s inputIndex=%d streamSeqNum=%d" 1668 " stalled=%s drainState=%d isInbetweenInsts=%d\n",
1685 case Enums::SingleThreaded:
1687 case Enums::RoundRobin:
1694 panic(
"Invalid thread policy");
1697 for (
auto tid : priority_list) {
1700 if (can_commit_insts) {
1704 can_commit_insts = can_commit_insts &&
1708 bool can_transfer_mem_inst =
false;
1714 can_transfer_mem_inst =
1715 !fu_inst->isBubble() &&
1716 fu_inst->id.threadId == tid &&
1718 fu_inst->canEarlyIssue &&
1719 inst->id.execSeqNum > fu_inst->instToWaitFor;
1723 if (can_commit_insts && !can_transfer_mem_inst &&
1727 can_execute_fu_inst = !fu_inst.
inst->isBubble() &&
1728 fu_inst.
inst->id == inst->id;
1731 can_commit_insts = can_commit_insts &&
1732 (can_transfer_mem_inst || can_execute_fu_inst);
1737 if (can_commit_insts) {
1752 case Enums::SingleThreaded:
1754 case Enums::RoundRobin:
1761 panic(
"Invalid thread scheduling policy.");
1764 for (
auto tid : priority_list) {
1777 DPRINTF(Drain,
"MinorExecute drainResume\n");
1791 os <<
"NotDraining";
1794 os <<
"DrainCurrentInst";
1797 os <<
"DrainHaltFetch";
1800 os <<
"DrainAllInsts";
1803 os <<
"Drain-" <<
static_cast<int>(state);
1813 DPRINTF(Drain,
"setDrainState[%d]: %s\n", thread_id, state);
1820 DPRINTF(Drain,
"MinorExecute drain\n");
1868 return inst->id.streamSeqNum ==
executeInfo[inst->id.threadId].streamSeqNum;
1876 if (!
executeInfo[inst->id.threadId].inFlightInsts->empty())
1877 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...
#define panic(...)
This implements a cprintf based panic() function.
DrainState
Stage cycle-by-cycle state.
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.
bool readMemAccPredicate() const override
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 void probeInstCommit(const StaticInstPtr &inst, Addr pc)
Helper method to trigger PMU probes for a committed instruction.
decltype(nullptr) constexpr NoFault
Cycles is a wrapper class for representing cycle counts, i.e.
unsigned int cyclicIndexInc(unsigned int index, unsigned int cycle_size)
Increment a cyclic buffer index for indices [0, cycle_size-1].
#define fatal(...)
This implements a cprintf based fatal() function.
bool allowEarlyMemIssue
Allow mem refs to leave their FUs before reaching the head of the in flight insts queue if their depe...
static BranchData bubble()
BubbleIF interface.
ThreadID numThreads
Number of threads we're actually simulating (<= SMT_MAX_THREADS).
unsigned int memoryCommitLimit
Number of memory instructions that can be committed per cycle.
virtual TheISA::PCState pcState() const =0
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)
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 width() const
Number of instructions carried by this object.
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.
bool needsToBeSentToStoreBuffer()
This request, once processed by the requests/transfers queues, will need to go to the store buffer...
The SimpleThread object provides a combination of the ThreadState object and the ThreadContext interf...
ElemType & front()
Peek at the end element of the pipe.
Minor contains all the definitions within the MinorCPU apart from the CPU class itself.
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...
virtual Fault getInterrupt(ThreadContext *tc)=0
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.
virtual void updateIntrInfo(ThreadContext *tc)=0
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)
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...
std::vector< InputBuffer< ForwardInstData > > inputBuffer
Stats::Scalar numInsts
Number of simulated instructions.
std::vector< ThreadID > randomPriority()
bool checkInterrupts(ThreadContext *tc) const
bool isBubble() const
BubbleIF interface.
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.
Cycles curCycle() const
Determine the current cycle, corresponding to a tick aligned to a clock edge.
bool canPushIntoStoreBuffer() const
Must check this before trying to insert into the store buffer.
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...
virtual Addr instAddr() const =0
Extra timing capability to allow individual ops to have their source register dependency latencies tw...
bool isInterrupted(ThreadID thread_id) const
Has an interrupt been raised.
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 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.
bool readPredicate() const override
bool isInbetweenInsts(ThreadID thread_id) const
Are we between instructions? Can we be interrupted?
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? ...
void advance()
Step the pipeline.
static MinorDynInstPtr bubble()
There is a single bubble inst.
static const OpClass Num_OpClasses
bool canInsert() const
Can an instruction be inserted now?
GenericISA::SimplePCState< MachInst > PCState
Top level definition of the Minor in-order CPU model.
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)
virtual ThreadContext * getContext(int tn)
Given a thread num get tho thread context for it.
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.
BaseInterrupts * getInterruptController(ThreadID tid)
std::vector< Scoreboard > scoreboard
Scoreboard of instruction dependencies.
const T * getConstPtr() const
virtual Status status() const =0
void minorTrace() const
Report buffer states from 'slot' 'from' to 'to'.
void push(ElemType &elem)
Write an element to the back of the pipeline.
InstSeqNum getLastMemBarrier(ThreadID thread_id) const
Get the execSeqNum of the last issued memory barrier.
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.
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.
friend std::ostream & operator<<(std::ostream &os, DrainState state)
bool accessesInFlight() const
Are there any accesses other than normal cached loads in the memory system or having received respons...
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...
const std::string to_string(sc_enc enc)
Queue< QueuedInst, ReportTraitsAdaptor< QueuedInst > > * inFUMemInsts
Memory ref instructions still in the FUs.
A functional unit configured from a MinorFU object.
bool isStreamChange() const
As static isStreamChange but on this branch data.
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...