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()
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")
'UnconditionalJump', #
'SpecialOp', # Special op
'Waitcnt', # Is a waitcnt instruction
+ 'Sleep', # Is a sleep instruction
# Memory ops
'MemBarrier', # Barrier instruction
return _staticInst->isWaitcnt();
}
+bool
+GPUDynInst::isSleep() const
+{
+ return _staticInst->isSleep();
+}
+
bool
GPUDynInst::isBarrier() const
{
bool isUnconditionalJump() const;
bool isSpecialOp() const;
bool isWaitcnt() const;
+ bool isSleep() const;
bool isBarrier() const;
bool isMemSync() const;
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]; }
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);
}
}
+ // 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.
// 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());
}
NRDY_WF_STOP,
NRDY_IB_EMPTY,
NRDY_WAIT_CNT,
+ NRDY_SLEEP,
NRDY_BARRIER_WAIT,
NRDY_VGPR_NRDY,
NRDY_SGPR_NRDY,
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;
return false;
}
+bool
+Wavefront::isOldestInstSleep()
+{
+ if (instructionBuffer.empty())
+ return false;
+
+ GPUDynInstPtr ii = instructionBuffer.front();
+
+ if (ii->isSleep()) {
+ return true;
+ }
+ return false;
+}
+
bool
Wavefront::isOldestInstWaitcnt()
{
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)
{
S_RUNNING,
// wavefront is stalled
S_STALLED,
+
+ S_STALLED_SLEEP,
+
/**
* wavefront has unsatisfied wait counts
*
bool isGmInstruction(GPUDynInstPtr ii);
bool isLmInstruction(GPUDynInstPtr ii);
bool isOldestInstWaitcnt();
+ bool isOldestInstSleep();
bool isOldestInstGMem();
bool isOldestInstLMem();
bool isOldestInstPrivMem();
/** Freeing VRF space */
void freeRegisterFile();
+ bool sleepDone();
+ void setSleepTime(int sleep_time);
+
TheGpuISA::GPUISA&
gpuISA()
{
int vmemInstsIssued;
int expInstsIssued;
int lgkmInstsIssued;
+ int sleepCnt;
status_e status;
Addr _pc;
VectorMask _execMask;