Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion configs/common/xiangshan.py
Original file line number Diff line number Diff line change
Expand Up @@ -583,7 +583,7 @@ def build_xiangshan_system(args):
perfCCT_cmd += PerfRecord.vals[0] + " bigint unsigned NOT NULL"
for i in range(1, len(PerfRecord.vals)):
name = PerfRecord.vals[i]
type_str = "bigint unsigned" if name.lower().startswith(('at', 'pc')) else "char(20)"
type_str = "bigint unsigned" if name.lower().startswith(('at', 'pc', 'result')) else "char(20)"
perfCCT_cmd += "," + name + " " + type_str + " NOT NULL"
perfCCT_cmd += ");"

Expand Down
2 changes: 1 addition & 1 deletion src/cpu/o3/BaseO3CPU.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ class PerfRecord(ScopedEnum):
# position tick
'AtFetch', 'AtDecode', 'AtRename', 'AtDispQue', 'AtIssueQue', 'AtIssueArb', 'AtIssueReadReg',
'AtFU', 'AtBypassVal', 'AtWriteVal', 'AtCommit',
'DisAsm', 'PC'
'Result', 'DisAsm', 'PC'
]

class BaseO3CPU(BaseCPU):
Expand Down
41 changes: 16 additions & 25 deletions src/cpu/o3/comm.hh
Original file line number Diff line number Diff line change
Expand Up @@ -219,29 +219,17 @@ struct TimeStruct
StallReason blockReason;
};

DecodeComm decodeInfo[MaxThreads];
DecodeComm decodeInfo[MaxThreads]; // decode to fetch

struct RenameComm
{
StallReason blockReason;
};

RenameComm renameInfo[MaxThreads];
RenameComm renameInfo[MaxThreads]; // rename to decode

struct IewComm
{
// Also eventually include skid buffer space.
unsigned freeLQEntries;
unsigned freeSQEntries;
unsigned dispatchedToLQ;
unsigned dispatchedToSQ;

unsigned ldstqCount;

unsigned dispatched;
bool usedIQ;
bool usedLSQ;

StallReason robHeadStallReason;
StallReason blockReason;
StallReason lqHeadStallReason;
Expand All @@ -256,7 +244,7 @@ struct TimeStruct
std::vector<ResolvedCFIEntry> resolvedCFIs; // *F
};

IewComm iewInfo[MaxThreads];
IewComm iewInfo[MaxThreads]; // iew to rename, fetch

struct CommitComm
{
Expand Down Expand Up @@ -300,13 +288,12 @@ struct TimeStruct

InstSeqNum doneMemSeqNum;

InstSeqNum robheadSeqNum;

uint64_t doneFtqId; // F
uint64_t squashedTargetId; // F
unsigned squashedLoopIter; // F

/// Tell Rename how many free entries it has in the ROB
unsigned freeROBEntries; // *R

bool isTrapSquash;
bool squash; // *F, D, R, I
bool robSquashing; // *F, D, R, I
Expand Down Expand Up @@ -336,16 +323,20 @@ struct TimeStruct

};

CommitComm commitInfo[MaxThreads];
CommitComm commitInfo[MaxThreads];// commit to iew, rename, fetch
};


bool decodeBlock[MaxThreads];
bool decodeUnblock[MaxThreads];
bool renameBlock[MaxThreads];
bool renameUnblock[MaxThreads];
bool iewBlock[MaxThreads];
bool iewUnblock[MaxThreads];
struct StallSignals
{

bool blockFetch[MaxThreads];// decode to fetch
bool blockDecode[MaxThreads];// rename to decode
bool blockRename[MaxThreads];// iew to rename (if iew is stalling, rename all threads would be stalled)
bool blockIEW[MaxThreads];// commit to iew
};


} // namespace o3
} // namespace gem5

Expand Down
133 changes: 98 additions & 35 deletions src/cpu/o3/commit.cc
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ Commit::Commit(CPU *_cpu, branch_prediction::BPredUnit *_bp, const BaseO3CPUPara
"--debug-start=%llu --debug-end=%llu\n",
lastCommitCycle, cpu->curCycle(),
cpu->cyclesToTicks(Cycles(lastCommitCycle - 200)),
cpu->cyclesToTicks(Cycles(lastCommitCycle + 50)));
cpu->cyclesToTicks(Cycles(lastCommitCycle + 200)));
}
cpu->schedule(this->stuckCheckEvent, cpu->clockEdge(Cycles(40010)));
}, "CommitStuckCheckEvent"),
Expand Down Expand Up @@ -165,7 +165,9 @@ Commit::Commit(CPU *_cpu, branch_prediction::BPredUnit *_bp, const BaseO3CPUPara
}
}

for (ThreadID tid = 0; tid < MaxThreads; tid++) {
assert(renameToROBDelay == 1);

for (ThreadID tid = 0; tid < numThreads; tid++) {
commitStatus[tid] = Idle;
changedROBNumEntries[tid] = false;
trapSquash[tid] = false;
Expand All @@ -181,6 +183,7 @@ Commit::Commit(CPU *_cpu, branch_prediction::BPredUnit *_bp, const BaseO3CPUPara
htmStarts[tid] = 0;
htmStops[tid] = 0;
traceCommitIndex[tid] = 0;
fixedbuffer[tid] = boost::circular_buffer<DynInstPtr>(renameWidth);
}
interrupt = NoFault;

Expand Down Expand Up @@ -461,7 +464,6 @@ Commit::startupStage()
// Broadcast the number of free entries.
for (ThreadID tid = 0; tid < numThreads; tid++) {
toIEW->commitInfo[tid].usedROB = true;
toIEW->commitInfo[tid].freeROBEntries = rob->numFreeEntries(tid);
toIEW->commitInfo[tid].emptyROB = true;
}

Expand Down Expand Up @@ -1104,10 +1106,10 @@ Commit::commit()
_nextStatus = Active;
}

if (num_squashing_threads != numThreads) {
// If we're not currently squashing, then get instructions.
getInsts();
// If we're not currently squashing, then get instructions.
moveInstsToBuffer();

if (num_squashing_threads != numThreads) {
// Try to commit any instructions.
commitInsts();
}
Expand All @@ -1120,7 +1122,6 @@ Commit::commit()

if (changedROBNumEntries[tid]) {
toIEW->commitInfo[tid].usedROB = true;
toIEW->commitInfo[tid].freeROBEntries = rob->numFreeEntries(tid);

wroteToTimeBuffer = true;
changedROBNumEntries[tid] = false;
Expand All @@ -1142,7 +1143,6 @@ Commit::commit()
checkEmptyROB[tid] = false;
toIEW->commitInfo[tid].usedROB = true;
toIEW->commitInfo[tid].emptyROB = true;
toIEW->commitInfo[tid].freeROBEntries = rob->numFreeEntries(tid);
wroteToTimeBuffer = true;
}

Expand Down Expand Up @@ -1204,11 +1204,22 @@ Commit::commitInsts()

// ThreadID commit_thread = getCommittingThread();

if (commit_thread == -1 || !rob->isHeadGroupReady(commit_thread))
if (commit_thread == -1)
break;

head_inst = rob->readHeadInst(commit_thread);

if (!rob->isHeadGroupReady(commit_thread)) {
if (debug::Commit && head_inst->readyToCommit()) {
InstSeqNum seqnum = rob->getHeadGroupLastDoneSeq(commit_thread);
DPRINTF(
Commit,
"[sn:%llu] Head is ready to commit, but the group is not all ready, last done inst [sn:%llu]\n",
head_inst->seqNum, seqnum);
}
break;
}

ThreadID tid = head_inst->threadNumber;

assert(tid == commit_thread);
Expand Down Expand Up @@ -1241,8 +1252,14 @@ Commit::commitInsts()

if (commit_success) {
cpu->perfCCT->updateInstPos(head_inst->seqNum, PerfRecord::AtCommit);
auto res = head_inst->getResult();
if (res.is<RegVal>()) {
cpu->perfCCT->updateInstMeta(head_inst->seqNum, InstDetail::Result, res.as<RegVal>());
}
cpu->perfCCT->commitMeta(head_inst->seqNum);
head_inst->printDisassemblyAndResult(cpu->name());

DPRINTF(CommitTrace, "CT: %s\n", head_inst->genDisassembly());

if (ismispred) {
ismispred = false;
stats.recovery_bubble += (cpu->curCycle() - lastCommitCycle) * renameWidth;
Expand Down Expand Up @@ -1382,7 +1399,11 @@ Commit::commitInsts()
if (head_inst->isLoad()) {
Addr load_pc = head_inst->pcState().instAddr();
Addr load_addr = head_inst->physEffAddr;
Addr load_value = head_inst->memData ? *((uint64_t *)head_inst->memData) : 0;
char buffer[8] = {0};
if (head_inst->memData) {
std::memcpy(buffer, head_inst->memData, head_inst->effSize);
}
Addr load_value = *((uint64_t *)buffer);
bool hit = loadTripleCounter.update(load_pc, load_addr, load_value);
if (hit) {
// same PC && same addr && same value
Expand Down Expand Up @@ -1492,6 +1513,12 @@ Commit::commitInsts()
for (int tid = 0; tid < MaxThreads; tid++) {
toIEW->commitInfo[tid].doneMemSeqNum =
std::max(toIEW->commitInfo[tid].doneSeqNum, rob->getHeadGroupLastDoneSeq(tid));

InstSeqNum robheadSeqNum = 0;
if (auto& it = rob->readHeadInst(tid)) {
robheadSeqNum = it->seqNum;
}
toIEW->commitInfo[tid].robheadSeqNum = robheadSeqNum;
}

DPRINTF(CommitRate, "%i\n", num_committed);
Expand Down Expand Up @@ -1703,9 +1730,9 @@ Commit::commitHead(const DynInstPtr &head_inst, unsigned inst_num)
cause = cpu->readMiscReg(
RiscvISA::MiscRegIndex::MISCREG_MCAUSE, tid);
}
auto exception_no =inst_fault->exception();
auto exception_no = inst_fault->exception();
if (faultNum.find(exception_no) != faultNum.end()) {
DPRINTF(Commit, "Force to raise No.%lu exception at page fault\n", inst_fault);
DPRINTF(Commit, "Force to raise No.%lu exception at page fault\n", exception_no);
cpu->setExceptionGuideExecInfo(
exception_no, cpu->readMiscReg(RiscvISA::MiscRegIndex::MISCREG_MTVAL, tid),
cpu->readMiscReg(RiscvISA::MiscRegIndex::MISCREG_STVAL, tid), false, 0, tid);
Expand Down Expand Up @@ -1806,21 +1833,51 @@ Commit::commitHead(const DynInstPtr &head_inst, unsigned inst_num)
}

void
Commit::getInsts()
Commit::moveInstsToBuffer()
{
DPRINTF(Commit, "Getting instructions from Rename stage.\n");
int insts_from_rename = fromRename->size;
if (insts_from_rename != 0) {
// move to buffer
ThreadID tid = fromRename->insts[0]->threadNumber;
assert(fixedbuffer[tid].empty());
for (int i = 0; i < insts_from_rename; ++i) {
const DynInstPtr &inst = fromRename->insts[i];
assert(inst->threadNumber == tid);
if (!inst->isSquashed())
fixedbuffer[tid].push_back(inst);
}
}

// Read any renamed instructions and place them into the ROB.
int insts_to_process = std::min((int)renameWidth, fromRename->size);

for (int inst_num = 0; inst_num < insts_to_process; ++inst_num) {
const DynInstPtr &inst = fromRename->insts[inst_num];
ThreadID tid = inst->threadNumber;

if (localSquashVer.largerThan(inst->getVersion())) {
inst->setSquashed();
// check threads stall & status
ThreadID tid = InvalidThreadID;
for (int i = 0; i < numThreads; i++) {
bool robblock = commitStatus[i] == ROBSquashing || commitStatus[i] == TrapPending;
bool block = (rob->getMaxEntries(i) - rob->getThreadEntries(i) < fixedbuffer[i].size()) || robblock;
bool active = !block && !fixedbuffer[i].empty();
DPRINTF(Commit, "Thread %i: block %i robblock %i active %i\n", i, block, robblock, active);

stallSig->blockIEW[i] = block;
if (active) {
if (tid == InvalidThreadID) tid = i;
else {
// if there are multiple active threads, must exhaust all threads first
// to avoid starvation of other threads and also avoid resource conflict
stallSig->blockIEW[tid] = true;
stallSig->blockIEW[i] = true;
DPRINTF(IEW, "Multiple active threads detected, blocking all threads\n");
}
}
}
if (tid == InvalidThreadID) {
DPRINTF(Commit, "No instructions from Rename stage.\n");
return;
}

// Read any renamed instructions and place them into the ROB.
int insts_to_process = fixedbuffer[tid].size();
for (int inst_num = 0; inst_num < insts_to_process; ++inst_num) {
const DynInstPtr &inst = fixedbuffer[tid].front();
if (!inst->isSquashed() &&
commitStatus[tid] != ROBSquashing &&
commitStatus[tid] != TrapPending) {
Expand All @@ -1839,6 +1896,13 @@ Commit::getInsts()
"Instruction PC %s was squashed, skipping.\n",
tid, inst->seqNum, inst->pcState());
}

fixedbuffer[tid].pop_front();
}

if (!fixedbuffer[tid].empty()) {
stallSig->blockIEW[tid] = true;
DPRINTF(Commit, "Not all instructions from Rename stage could be processed, blocking thread %i\n", tid);
}
}

Expand All @@ -1847,18 +1911,16 @@ void
Commit::squashInflightAndUpdateVersion(ThreadID tid)
{
DPRINTF(Commit, "Squashing in-flight renamed instructions\n");
int cycle = 0; // Mark instructions renamed this cycle as squashed
auto tb_ptr = renameQueue->getWire(cycle);
DPRINTF(Commit, "%u insts in flight at cycle %d\n", tb_ptr->size,
cycle);
for (unsigned i_idx = 0; i_idx < tb_ptr->size; i_idx++) {
const DynInstPtr &inst = tb_ptr->insts[i_idx];
for (unsigned i_idx = 0; i_idx < fromRename->size; i_idx++) {
const DynInstPtr &inst = fromRename->insts[i_idx];
DPRINTF(Commit, "[tid:%i] [sn:%llu] Squashing in-flight "
"instruction PC %s\n",
inst->threadNumber, inst->seqNum, inst->pcState());
inst->setSquashed();
}

fixedbuffer[tid].clear();

localSquashVer.update(localSquashVer.nextVersion());
toIEW->commitInfo[tid].squashVersion = localSquashVer;
DPRINTF(Commit, "Updating squash version to %u\n",
Expand All @@ -1873,14 +1935,18 @@ Commit::markCompletedInsts()
for (int inst_num = 0; inst_num < fromIEW->size; ++inst_num) {
assert(fromIEW->insts[inst_num]);
if (!fromIEW->insts[inst_num]->isSquashed()) {
DPRINTF(Commit, "[tid:%i] Marking PC %s, [sn:%llu] ready "
DPRINTF(Commit,
"[tid:%i] Marking PC %s, [sn:%llu] ready "
"within ROB.\n",
fromIEW->insts[inst_num]->threadNumber,
fromIEW->insts[inst_num]->pcState(),
fromIEW->insts[inst_num]->threadNumber, fromIEW->insts[inst_num]->pcState(),
fromIEW->insts[inst_num]->seqNum);

// Mark the instruction as ready to commit.
fromIEW->insts[inst_num]->setCanCommit();
auto &inst = fromIEW->insts[inst_num];

panic_if(!rob->findInst(0, inst->seqNum), "[sn:%llu] Committed instruction not found in ROB",
inst->seqNum);
}
}
}
Expand All @@ -1901,10 +1967,7 @@ Commit::updateComInstStats(const DynInstPtr &inst)
cpu->instDone(tid, inst);
}

//
// Control Instructions
//
//
if (inst->isControl()) {
bool mispred = inst->mispredicted();
std::unique_ptr<PCStateBase> tmp_next_pc(inst->pcState().clone());
Expand Down
Loading