arch-gcn3: Implementation of s_sleep
This changeset implements the s_sleep instruction in a similar way to s_waitcnt. Change-Id: I4811c318ac2c76c485e2bfd9d93baa1205ecf183 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/39115 Maintainer: Matthew Poremba <matthew.poremba@amd.com> Maintainer: Matt Sinclair <mattdsinclair@gmail.com> Reviewed-by: Matt Sinclair <mattdsinclair@gmail.com> Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
committed by
Matt Sinclair
parent
4060208a04
commit
14d6e8fac4
@@ -4187,6 +4187,8 @@ namespace Gcn3ISA
|
||||
Inst_SOPP__S_SLEEP::Inst_SOPP__S_SLEEP(InFmt_SOPP *iFmt)
|
||||
: Inst_SOPP(iFmt, "s_sleep")
|
||||
{
|
||||
setFlag(ALU);
|
||||
setFlag(Sleep);
|
||||
} // Inst_SOPP__S_SLEEP
|
||||
|
||||
Inst_SOPP__S_SLEEP::~Inst_SOPP__S_SLEEP()
|
||||
@@ -4197,8 +4199,12 @@ namespace Gcn3ISA
|
||||
void
|
||||
Inst_SOPP__S_SLEEP::execute(GPUDynInstPtr gpuDynInst)
|
||||
{
|
||||
panicUnimplemented();
|
||||
}
|
||||
ScalarRegI32 simm16 = (ScalarRegI32)instData.SIMM16;
|
||||
gpuDynInst->wavefront()->setStatus(Wavefront::S_STALLED_SLEEP);
|
||||
// sleep duration is specified in multiples of 64 cycles
|
||||
gpuDynInst->wavefront()->setSleepTime(64 * simm16);
|
||||
} // execute
|
||||
// --- Inst_SOPP__S_SETPRIO class methods ---
|
||||
|
||||
Inst_SOPP__S_SETPRIO::Inst_SOPP__S_SETPRIO(InFmt_SOPP *iFmt)
|
||||
: Inst_SOPP(iFmt, "s_setprio")
|
||||
|
||||
@@ -48,6 +48,7 @@ class GPUStaticInstFlags(Enum):
|
||||
'UnconditionalJump', #
|
||||
'SpecialOp', # Special op
|
||||
'Waitcnt', # Is a waitcnt instruction
|
||||
'Sleep', # Is a sleep instruction
|
||||
|
||||
# Memory ops
|
||||
'MemBarrier', # Barrier instruction
|
||||
|
||||
@@ -398,6 +398,12 @@ GPUDynInst::isWaitcnt() const
|
||||
return _staticInst->isWaitcnt();
|
||||
}
|
||||
|
||||
bool
|
||||
GPUDynInst::isSleep() const
|
||||
{
|
||||
return _staticInst->isSleep();
|
||||
}
|
||||
|
||||
bool
|
||||
GPUDynInst::isBarrier() const
|
||||
{
|
||||
|
||||
@@ -180,6 +180,7 @@ class GPUDynInst : public GPUExecContext
|
||||
bool isUnconditionalJump() const;
|
||||
bool isSpecialOp() const;
|
||||
bool isWaitcnt() const;
|
||||
bool isSleep() const;
|
||||
|
||||
bool isBarrier() const;
|
||||
bool isMemSync() const;
|
||||
|
||||
@@ -119,6 +119,7 @@ class GPUStaticInst : public GPUStaticInstFlags
|
||||
|
||||
bool isSpecialOp() const { return _flags[SpecialOp]; }
|
||||
bool isWaitcnt() const { return _flags[Waitcnt]; }
|
||||
bool isSleep() const { return _flags[Sleep]; }
|
||||
|
||||
bool isBarrier() const { return _flags[MemBarrier]; }
|
||||
bool isMemSync() const { return _flags[MemSync]; }
|
||||
|
||||
@@ -317,6 +317,9 @@ ScheduleStage::addToSchList(int exeType, const GPUDynInstPtr &gpu_dyn_inst)
|
||||
if (wf->isOldestInstWaitcnt()) {
|
||||
wf->setStatus(Wavefront::S_WAITCNT);
|
||||
}
|
||||
if (wf->isOldestInstSleep()) {
|
||||
wf->setStatus(Wavefront::S_STALLED_SLEEP);
|
||||
}
|
||||
if (!gpu_dyn_inst->isScalar()) {
|
||||
computeUnit.vrf[wf->simdId]
|
||||
->scheduleReadOperands(wf, gpu_dyn_inst);
|
||||
|
||||
@@ -92,6 +92,15 @@ ScoreboardCheckStage::ready(Wavefront *w, nonrdytype_e *rdyStatus,
|
||||
}
|
||||
}
|
||||
|
||||
// sleep instruction has been dispatched or executed: next
|
||||
// instruction should be blocked until the sleep period expires.
|
||||
if (w->getStatus() == Wavefront::S_STALLED_SLEEP) {
|
||||
if (!w->sleepDone()) {
|
||||
*rdyStatus = NRDY_SLEEP;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Is the wave waiting at a barrier. Check this condition BEFORE checking
|
||||
// for instruction buffer occupancy to avoid a deadlock when the barrier is
|
||||
// the last instruction in the instruction buffer.
|
||||
@@ -143,7 +152,8 @@ ScoreboardCheckStage::ready(Wavefront *w, nonrdytype_e *rdyStatus,
|
||||
// through this logic and always return not ready.
|
||||
if (!(ii->isBarrier() || ii->isNop() || ii->isReturn() || ii->isBranch() ||
|
||||
ii->isALU() || ii->isLoad() || ii->isStore() || ii->isAtomic() ||
|
||||
ii->isEndOfKernel() || ii->isMemSync() || ii->isFlat())) {
|
||||
ii->isEndOfKernel() || ii->isMemSync() || ii->isFlat() ||
|
||||
ii->isSleep())) {
|
||||
panic("next instruction: %s is of unknown type\n", ii->disassemble());
|
||||
}
|
||||
|
||||
|
||||
@@ -65,6 +65,7 @@ class ScoreboardCheckStage
|
||||
NRDY_WF_STOP,
|
||||
NRDY_IB_EMPTY,
|
||||
NRDY_WAIT_CNT,
|
||||
NRDY_SLEEP,
|
||||
NRDY_BARRIER_WAIT,
|
||||
NRDY_VGPR_NRDY,
|
||||
NRDY_SGPR_NRDY,
|
||||
|
||||
@@ -49,7 +49,7 @@ Wavefront::Wavefront(const Params &p)
|
||||
maxIbSize(p.max_ib_size), _gpuISA(*this),
|
||||
vmWaitCnt(-1), expWaitCnt(-1), lgkmWaitCnt(-1),
|
||||
vmemInstsIssued(0), expInstsIssued(0), lgkmInstsIssued(0),
|
||||
barId(WFBarrier::InvalidID), stats(this)
|
||||
sleepCnt(0), barId(WFBarrier::InvalidID), stats(this)
|
||||
{
|
||||
lastTrace = 0;
|
||||
execUnitId = -1;
|
||||
@@ -583,6 +583,20 @@ Wavefront::isLmInstruction(GPUDynInstPtr ii)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
Wavefront::isOldestInstSleep()
|
||||
{
|
||||
if (instructionBuffer.empty())
|
||||
return false;
|
||||
|
||||
GPUDynInstPtr ii = instructionBuffer.front();
|
||||
|
||||
if (ii->isSleep()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
Wavefront::isOldestInstWaitcnt()
|
||||
{
|
||||
@@ -1226,6 +1240,32 @@ Wavefront::waitCntsSatisfied()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
Wavefront::sleepDone()
|
||||
{
|
||||
assert(status == S_STALLED_SLEEP);
|
||||
|
||||
// if the sleep count has not been set, then the sleep instruction has not
|
||||
// been executed yet, so we will return true without setting the wavefront
|
||||
// status
|
||||
if (sleepCnt == 0)
|
||||
return false;
|
||||
|
||||
sleepCnt--;
|
||||
if (sleepCnt != 0)
|
||||
return false;
|
||||
|
||||
status = S_RUNNING;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
Wavefront::setSleepTime(int sleep_time)
|
||||
{
|
||||
assert(sleepCnt == 0);
|
||||
sleepCnt = sleep_time;
|
||||
}
|
||||
|
||||
void
|
||||
Wavefront::setWaitCnts(int vm_wait_cnt, int exp_wait_cnt, int lgkm_wait_cnt)
|
||||
{
|
||||
|
||||
@@ -68,6 +68,9 @@ class Wavefront : public SimObject
|
||||
S_RUNNING,
|
||||
// wavefront is stalled
|
||||
S_STALLED,
|
||||
|
||||
S_STALLED_SLEEP,
|
||||
|
||||
/**
|
||||
* wavefront has unsatisfied wait counts
|
||||
*
|
||||
@@ -134,6 +137,7 @@ class Wavefront : public SimObject
|
||||
bool isGmInstruction(GPUDynInstPtr ii);
|
||||
bool isLmInstruction(GPUDynInstPtr ii);
|
||||
bool isOldestInstWaitcnt();
|
||||
bool isOldestInstSleep();
|
||||
bool isOldestInstGMem();
|
||||
bool isOldestInstLMem();
|
||||
bool isOldestInstPrivMem();
|
||||
@@ -276,6 +280,9 @@ class Wavefront : public SimObject
|
||||
/** Freeing VRF space */
|
||||
void freeRegisterFile();
|
||||
|
||||
bool sleepDone();
|
||||
void setSleepTime(int sleep_time);
|
||||
|
||||
TheGpuISA::GPUISA&
|
||||
gpuISA()
|
||||
{
|
||||
@@ -315,6 +322,7 @@ class Wavefront : public SimObject
|
||||
int vmemInstsIssued;
|
||||
int expInstsIssued;
|
||||
int lgkmInstsIssued;
|
||||
int sleepCnt;
|
||||
status_e status;
|
||||
Addr _pc;
|
||||
VectorMask _execMask;
|
||||
|
||||
Reference in New Issue
Block a user