Skip to content

Commit 1fe2ec0

Browse files
committed
cpu-o3: fix squash drain and wakeup recovery
Change-Id: Icc05a7320ee5bf1495ef98694c3e92847613d79e
1 parent 94c3b8a commit 1fe2ec0

File tree

6 files changed

+62
-11
lines changed

6 files changed

+62
-11
lines changed

src/cpu/o3/commit.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1263,7 +1263,7 @@ Commit::commitInsts()
12631263
DPRINTF(Commit, "Retiring squashed instruction from "
12641264
"ROB.\n");
12651265

1266-
rob->retireHead(commit_thread);
1266+
rob->drainSquashedHead(commit_thread);
12671267

12681268
++stats.commitSquashedInsts;
12691269
// Notify potential listeners that this instruction is squashed

src/cpu/o3/issue_queue.cc

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,9 @@ IssueQue::checkScoreboard(const DynInstPtr& inst)
382382
}
383383
// check bypass data ready or not
384384
if (!scheduler->bypassScoreboard[src->flatIndex()]) [[unlikely]] {
385-
auto dst_inst = scheduler->getInstByDstReg(src->flatIndex());
385+
auto dst_inst = scheduler->getInstByDstReg(src->flatIndex(),
386+
inst->threadNumber,
387+
inst->seqNum);
386388
assert(dst_inst);
387389
if (!dst_inst->isLoad()) panic("dst[sn:%llu] is not load, src[sn:%llu]", dst_inst->seqNum, inst->seqNum);
388390
warn_once(
@@ -1241,18 +1243,28 @@ Scheduler::ready(OpClass op, int disp_seq)
12411243
}
12421244

12431245
DynInstPtr
1244-
Scheduler::getInstByDstReg(RegIndex flatIdx)
1246+
Scheduler::getInstByDstReg(RegIndex flatIdx, ThreadID tid,
1247+
InstSeqNum consumerSeqNum)
12451248
{
1249+
DynInstPtr candidate = nullptr;
1250+
12461251
for (auto iq : issueQues) {
1247-
for (auto& inst : iq->instList) {
1248-
for (auto i = 0; i < inst->numDestRegs(); i++) {
1249-
if (inst->renamedDestIdx(i)->flatIndex() == flatIdx) {
1250-
return inst;
1252+
for (auto &inst : iq->instList) {
1253+
if (inst->threadNumber != tid || inst->seqNum >= consumerSeqNum) {
1254+
continue;
1255+
}
1256+
for (int i = 0; i < inst->numDestRegs(); i++) {
1257+
if (inst->renamedDestIdx(i)->flatIndex() != flatIdx) {
1258+
continue;
1259+
}
1260+
if (!candidate || inst->seqNum > candidate->seqNum) {
1261+
candidate = inst;
12511262
}
12521263
}
12531264
}
12541265
}
1255-
return nullptr;
1266+
1267+
return candidate;
12561268
}
12571269

12581270
void

src/cpu/o3/issue_queue.hh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,8 @@ class Scheduler : public SimObject
370370
void issueAndSelect();
371371
void lookahead(std::deque<DynInstPtr>& insts);
372372
bool ready(const DynInstPtr& inst, int disp_seq);
373-
DynInstPtr getInstByDstReg(RegIndex flatIdx);
373+
DynInstPtr getInstByDstReg(RegIndex flatIdx, ThreadID tid,
374+
InstSeqNum consumerSeqNum);
374375

375376
void addProducer(const DynInstPtr& inst);
376377
// return true if insert successful

src/cpu/o3/rename.cc

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -448,9 +448,12 @@ Rename::releasePhysRegs()
448448
}
449449

450450
removeFromHistory(releaseSeq[tid], tid);
451-
// If we committed this cycle then doneSeqNum will be > 0
451+
// doneSeqNum is also reused as a squash-progress marker while the
452+
// ROB is walking younger entries. Only real commit progress should
453+
// release physical registers.
452454
if (fromCommit->commitInfo[tid].doneSeqNum != 0 &&
453-
!fromCommit->commitInfo[tid].squash) {
455+
!fromCommit->commitInfo[tid].squash &&
456+
!fromCommit->commitInfo[tid].robSquashing) {
454457

455458
finalCommitSeq[tid] = fromCommit->commitInfo[tid].doneSeqNum;
456459
releaseSeq[tid] =

src/cpu/o3/rob.cc

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,36 @@ ROB::retireHead(ThreadID tid)
428428
cpu->removeFrontInst(head_inst);
429429
}
430430

431+
void
432+
ROB::drainSquashedHead(ThreadID tid)
433+
{
434+
stats.writes++;
435+
436+
assert(numInstsInROB > 0);
437+
438+
InstIt head_it = instList[tid].begin();
439+
440+
DynInstPtr head_inst = std::move(*head_it);
441+
instList[tid].erase(head_it);
442+
443+
assert(head_inst->readyToCommit());
444+
assert(head_inst->isSquashed());
445+
446+
DPRINTF(ROB, "[tid:%i] Draining squashed head instruction, "
447+
"instruction PC %s, [sn:%llu]\n", tid, head_inst->pcState(),
448+
head_inst->seqNum);
449+
450+
--numInstsInROB;
451+
452+
commitGroup(head_inst, tid);
453+
454+
head_inst->clearInROB();
455+
456+
updateHead();
457+
458+
cpu->removeFrontInst(head_inst);
459+
}
460+
431461
bool
432462
ROB::isHeadGroupReady(ThreadID tid)
433463
{

src/cpu/o3/rob.hh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,11 @@ class ROB
164164
*/
165165
void retireHead(ThreadID tid);
166166

167+
/** Drains a squashed head instruction from a specific thread without
168+
* marking it committed.
169+
*/
170+
void drainSquashedHead(ThreadID tid);
171+
167172
/** Is the oldest instruction across all threads ready. */
168173
// bool isHeadReady();
169174

0 commit comments

Comments
 (0)