From 1a6c8e1750ef3caba30b0247524cae106a4416d3 Mon Sep 17 00:00:00 2001 From: Yan Xu <934348725@qq.com> Date: Thu, 19 Dec 2024 11:25:33 +0800 Subject: [PATCH] cpu-o3: add regfile write conflict (#210) Change-Id: I77fa15b0a1bf25dc7a5f9729d99c230ee6b3a88c --- src/cpu/o3/commit.cc | 1 + src/cpu/o3/dyn_inst.hh | 10 +++--- src/cpu/o3/issue_queue.cc | 76 +++++++++++++++++++++++---------------- src/cpu/o3/issue_queue.hh | 3 +- 4 files changed, 52 insertions(+), 38 deletions(-) diff --git a/src/cpu/o3/commit.cc b/src/cpu/o3/commit.cc index 17ce63685b..f1e70e5969 100644 --- a/src/cpu/o3/commit.cc +++ b/src/cpu/o3/commit.cc @@ -722,6 +722,7 @@ Commit::tick() if (cpu->curCycle() - lastCommitCycle > 20000) { if (maybeStucked) { + warn("[sn:%s] %s", rob->head->get()->seqNum, rob->head->get()->staticInst->disassemble(0)); panic("cpu stucked!!\n"); } warn("cpu may be stucked\n"); diff --git a/src/cpu/o3/dyn_inst.hh b/src/cpu/o3/dyn_inst.hh index 5bee40588d..f519b0c504 100644 --- a/src/cpu/o3/dyn_inst.hh +++ b/src/cpu/o3/dyn_inst.hh @@ -157,7 +157,6 @@ class DynInst : public ExecContext, public RefCounted protected: enum Status { - IqEntry, /// Instruction is in the IQ RobEntry, /// Instruction is in the ROB LsqEntry, /// Instruction is in the LSQ Completed, /// Instruction has completed @@ -166,6 +165,7 @@ class DynInst : public ExecContext, public RefCounted MemDepSolved, /// Memory dependencies are solved InReadyQue, /// Instruction is in the ready queue Canceled, /// Instruction is canceled + Scheduled, /// Instruction is scheduled ArbFailed, Issued, /// Instruction has issued Executed, /// Instruction has executed @@ -849,8 +849,6 @@ class DynInst : public ExecContext, public RefCounted /** Returns whether or not this instruction has issued. */ bool isIssued() const { return status[Issued]; } - /** Clears this instruction as being issued. */ - void clearIssued() { status.reset(Issued); } /** Sets this instruction as executed. */ void setExecuted() { status.set(Executed); } @@ -886,13 +884,13 @@ class DynInst : public ExecContext, public RefCounted //Instruction Queue Entry //----------------------- /** Sets this instruction as a entry the IQ. */ - void setInIQ() { status.set(IqEntry); } + void setScheduled() { status.set(Scheduled); } /** Sets this instruction as a entry the IQ. */ - void clearInIQ() { status.reset(IqEntry); } + void clearScheduled() { status.reset(Scheduled); } /** Returns whether or not this instruction has issued. */ - bool isInIQ() const { return status[IqEntry]; } + bool isScheduled() const { return status[Scheduled]; } /** Sets this instruction as squashed in the IQ. */ void setSquashedInIQ() { status.set(SquashedInIQ); status.set(Squashed);} diff --git a/src/cpu/o3/issue_queue.cc b/src/cpu/o3/issue_queue.cc index a53182b095..ec6361fe81 100644 --- a/src/cpu/o3/issue_queue.cc +++ b/src/cpu/o3/issue_queue.cc @@ -234,8 +234,8 @@ IssueQue::addToFu(const DynInstPtr& inst) panic("%s [sn:%llu] has alreayd been issued\n", enums::OpClassStrings[inst->opClass()], inst->seqNum); } inst->setIssued(); - scheduler->addToFU(inst); POPINST(inst); + scheduler->addToFU(inst); } void @@ -248,24 +248,12 @@ IssueQue::issueToFu() if (!inst) { continue; } - if (portBusy[inst->issueportid]) { - DPRINTF(Schedule, "port%d busy, retry\n", inst->issueportid); - iqstats->portBusy[inst->issueportid]++; - // replay it - inst->setInReadyQ(); - readyQclassify[inst->opClass()]->push(inst); // retry - continue; - } if (!checkScoreboard(inst)) { continue; } addToFu(inst); cpu->perfCCT->updateInstPos(inst->seqNum, PerfRecord::AtIssueReadReg); issued++; - if (!opPipelined[inst->opClass()]) [[unlikely]] { - // set fu busy - portBusy[inst->issueportid] = scheduler->getOpLatency(inst) - 1; - } } for (int i = size; !replayQ.empty() && i < outports; i++) { auto inst = replayQ.front(); @@ -373,6 +361,21 @@ IssueQue::addIfReady(const DynInstPtr& inst) } } +void +IssueQue::cancel(const DynInstPtr& inst) +{ + // before issued + assert(!inst->isIssued()); + + inst->setCancel(); + if (inst->isScheduled() && !opPipelined[inst->opClass()]) { + inst->clearScheduled(); + portBusy[inst->issueportid] = 0; + } + + iqstats->canceledInst++; +} + void IssueQue::selectInst() { @@ -389,6 +392,10 @@ IssueQue::selectInst() } if (!readyQ->empty()) { auto inst = readyQ->top(); + if (portBusy[pi] & (1llu << scheduler->getCorrectedOpLat(inst))) { + continue; + } + DPRINTF(Schedule, "[sn %ld] was selected\n", inst->seqNum); // get regfile read port @@ -431,9 +438,16 @@ IssueQue::scheduleInst() } else [[likely]] { DPRINTF(Schedule, "[sn:%llu] no conflict, scheduled\n", inst->seqNum); iqstats->portissued[pi]++; - inst->clearInIQ(); + inst->setScheduled(); toIssue->push(inst); inst->issueportid = pi; + + if (!opPipelined[inst->opClass()]) { + portBusy[pi] = -1ll; + } else if (scheduler->getCorrectedOpLat(inst) > 1) { + portBusy[pi] |= 1ll << scheduler->getCorrectedOpLat(inst); + } + scheduler->specWakeUpDependents(inst, this); cpu->perfCCT->updateInstPos(inst->seqNum, PerfRecord::AtIssueArb); } @@ -451,12 +465,12 @@ IssueQue::tick() } instNumInsert = 0; - for (auto& t : portBusy) { - t = t > 0 ? t - 1 : t; - } - scheduleInst(); inflightIssues.advance(); + + for (auto& t : portBusy) { + t = t >> 1; + } } bool @@ -472,8 +486,8 @@ IssueQue::ready() bool IssueQue::full() { - bool full = instNumInsert + instNum >= iqsize; - full |= replayQ.size() > replayQsize; // TODO: parameterize it + bool full = instNum >= iqsize; + full |= replayQ.size() > replayQsize; if (full) { DPRINTF(Schedule, "has full!\n"); } @@ -493,7 +507,6 @@ IssueQue::insert(const DynInstPtr& inst) cpu->perfCCT->updateInstPos(inst->seqNum, PerfRecord::AtIssueQue); DPRINTF(Schedule, "[sn:%llu] %s insert into %s\n", inst->seqNum, enums::OpClassStrings[inst->opClass()], iqname); - DPRINTF(Schedule, "[sn:%llu] instNum++\n", inst->seqNum); inst->issueQue = this; instList.emplace_back(inst); bool addToDepGraph = false; @@ -551,17 +564,20 @@ IssueQue::doSquash(const InstSeqNum seqNum) { for (auto it = instList.begin(); it != instList.end();) { if ((*it)->seqNum > seqNum) { - (*it)->setSquashedInIQ(); - (*it)->setCanCommit(); - (*it)->clearInIQ(); - (*it)->setCancel(); if (!(*it)->isIssued()) { POPINST((*it)); (*it)->setIssued(); - } else if ((*it)->issueportid >= 0) { + } + if ((*it)->isScheduled() && !opPipelined[(*it)->opClass()]) { portBusy[(*it)->issueportid] = 0; } + + (*it)->setSquashedInIQ(); + (*it)->setCanCommit(); + (*it)->clearScheduled(); + (*it)->setCancel(); it = instList.erase(it); + assert(instList.size() >= instNum); } else { it++; } @@ -734,6 +750,8 @@ Scheduler::addToFU(const DynInstPtr& inst) void Scheduler::tick() { + // we need to update portBusy counter each cycle + cpu->activateStage(CPU::IEWIdx); for (auto it : issueQues) { it->tick(); } @@ -821,7 +839,6 @@ Scheduler::addProducer(const DynInstPtr& inst) void Scheduler::insert(const DynInstPtr& inst) { - inst->setInIQ(); auto& iqs = dispTable[inst->opClass()]; bool inserted = false; @@ -853,7 +870,6 @@ Scheduler::insert(const DynInstPtr& inst) void Scheduler::insertNonSpec(const DynInstPtr& inst) { - inst->setInIQ(); auto& iqs = dispTable[inst->opClass()]; for (auto iq : iqs) { @@ -976,11 +992,9 @@ Scheduler::loadCancel(const DynInstPtr& inst) int srcIdx = it.first; auto& depInst = it.second; if (depInst->readySrcIdx(srcIdx) && depInst->renamedSrcIdx(srcIdx) != cpu->vecOnesPhysRegId) { - assert(!depInst->isIssued()); DPRINTF(Schedule, "cancel [sn:%llu], clear src p%d ready\n", depInst->seqNum, depInst->renamedSrcIdx(srcIdx)->flatIndex()); - depInst->setCancel(); - iq->iqstats->canceledInst++; + depInst->issueQue->cancel(depInst); depInst->clearSrcRegReady(srcIdx); dfs.push(depInst); } diff --git a/src/cpu/o3/issue_queue.hh b/src/cpu/o3/issue_queue.hh index 2c34163c8a..6170abf7e6 100644 --- a/src/cpu/o3/issue_queue.hh +++ b/src/cpu/o3/issue_queue.hh @@ -107,7 +107,7 @@ class IssueQue : public SimObject // issueport : regfileport : priority std::vector>> intRfTypePortId; std::vector>> fpRfTypePortId; - std::vector portBusy; + std::vector portBusy; // opclass mapping to pipeid std::vector readyQclassify; // s0: wakeup inst, add ready inst to readyInstsQue @@ -145,6 +145,7 @@ class IssueQue : public SimObject void selectInst(); void scheduleInst(); void addIfReady(const DynInstPtr& inst); + void cancel(const DynInstPtr& inst); public: inline void clearBusy(uint32_t pi) { portBusy.at(pi) = 0; }