gpu-compute: Fix accidental execution when stopped at barrier

Due the compute unit pipeline being executed in reverse order, there
exists a scenario where a compute unit will execute an extra
instruction when it's supposed to be stopped at a barrier. It occurs
as follows:

* The ScheduleStage sets a barrier instruction ready to execute.

* The ScoreboardCheckStage adds another instruction to the readyList.
This is where the barrier is checked, but because the barrier isn't
executing yet, the instruction can be passed along to ScheduleStage

* The barrier executes, and stalls

* The ScheduleStage sees that there's a new instruction and schedules
it to be executed.

* Only now will the ScoreboardCheckStage realize a barrier is active
and stall accordingly

* The subsequent instruction executes

This patch sets the wavefront status to be S_BARRIER in ScheduleStage
instead of in the barrier instruction execution in order to have
ScoreboardCheckStage realize that we're going to execute a barrier,
preventing it from marking another instruciton as ready.

Change-Id: Ib683e2c68f361d7ee60a3beaf53b4b6c888c9f8d
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/41573
Reviewed-by: Matt Sinclair <mattdsinclair@gmail.com>
Reviewed-by: Alexandru Duțu <alexandru.dutu@amd.com>
Maintainer: Matt Sinclair <mattdsinclair@gmail.com>
Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
Kyle Roarty
2021-02-17 16:52:40 -06:00
committed by Matt Sinclair
parent c47920d81c
commit f5383a5733
2 changed files with 3 additions and 2 deletions

View File

@@ -4114,8 +4114,6 @@ namespace Gcn3ISA
if (wf->hasBarrier()) {
int bar_id = wf->barrierId();
assert(wf->getStatus() != Wavefront::S_BARRIER);
wf->setStatus(Wavefront::S_BARRIER);
cu->incNumAtBarrier(bar_id);
DPRINTF(GPUSync, "CU[%d] WF[%d][%d] Wave[%d] - Stalling at "
"barrier Id%d. %d waves now at barrier, %d waves "

View File

@@ -314,6 +314,9 @@ ScheduleStage::addToSchList(int exeType, const GPUDynInstPtr &gpu_dyn_inst)
computeUnit.insertInPipeMap(wf);
wavesInSch.emplace(wf->wfDynId);
schList.at(exeType).push_back(std::make_pair(gpu_dyn_inst, RFBUSY));
if (wf->isOldestInstBarrier() && wf->hasBarrier()) {
wf->setStatus(Wavefront::S_BARRIER);
}
if (wf->isOldestInstWaitcnt()) {
wf->setStatus(Wavefront::S_WAITCNT);
}