From f5383a573354f8299249116a489fd5aee09af68f Mon Sep 17 00:00:00 2001 From: Kyle Roarty Date: Wed, 17 Feb 2021 16:52:40 -0600 Subject: [PATCH] gpu-compute: Fix accidental execution when stopped at barrier MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Reviewed-by: Alexandru Duțu Maintainer: Matt Sinclair Tested-by: kokoro --- src/arch/gcn3/insts/instructions.cc | 2 -- src/gpu-compute/schedule_stage.cc | 3 +++ 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/arch/gcn3/insts/instructions.cc b/src/arch/gcn3/insts/instructions.cc index 29de1a8a95..bde87efeea 100644 --- a/src/arch/gcn3/insts/instructions.cc +++ b/src/arch/gcn3/insts/instructions.cc @@ -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 " diff --git a/src/gpu-compute/schedule_stage.cc b/src/gpu-compute/schedule_stage.cc index 8a2ea18294..ace6d0c3f5 100644 --- a/src/gpu-compute/schedule_stage.cc +++ b/src/gpu-compute/schedule_stage.cc @@ -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); }