Matt Sinclair has submitted this change. (
https://gem5-review.googlesource.com/c/public/gem5/+/39115 )
Change subject: arch-gcn3: Implementation of s_sleep
......................................................................
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 <[email protected]>
Maintainer: Matt Sinclair <[email protected]>
Reviewed-by: Matt Sinclair <[email protected]>
Tested-by: kokoro <[email protected]>
---
M src/arch/gcn3/insts/instructions.cc
M src/gpu-compute/GPUStaticInstFlags.py
M src/gpu-compute/gpu_dyn_inst.cc
M src/gpu-compute/gpu_dyn_inst.hh
M src/gpu-compute/gpu_static_inst.hh
M src/gpu-compute/schedule_stage.cc
M src/gpu-compute/scoreboard_check_stage.cc
M src/gpu-compute/scoreboard_check_stage.hh
M src/gpu-compute/wavefront.cc
M src/gpu-compute/wavefront.hh
10 files changed, 81 insertions(+), 4 deletions(-)
Approvals:
Matt Sinclair: Looks good to me, approved; Looks good to me, approved
Matthew Poremba: Looks good to me, approved
kokoro: Regressions pass
diff --git a/src/arch/gcn3/insts/instructions.cc
b/src/arch/gcn3/insts/instructions.cc
index 8c02951..03b11ab 100644
--- a/src/arch/gcn3/insts/instructions.cc
+++ b/src/arch/gcn3/insts/instructions.cc
@@ -4187,6 +4187,8 @@
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 @@
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")
diff --git a/src/gpu-compute/GPUStaticInstFlags.py
b/src/gpu-compute/GPUStaticInstFlags.py
index ad4c6c3..1dc143c 100644
--- a/src/gpu-compute/GPUStaticInstFlags.py
+++ b/src/gpu-compute/GPUStaticInstFlags.py
@@ -48,6 +48,7 @@
'UnconditionalJump', #
'SpecialOp', # Special op
'Waitcnt', # Is a waitcnt instruction
+ 'Sleep', # Is a sleep instruction
# Memory ops
'MemBarrier', # Barrier instruction
diff --git a/src/gpu-compute/gpu_dyn_inst.cc
b/src/gpu-compute/gpu_dyn_inst.cc
index a17a93f..b827632 100644
--- a/src/gpu-compute/gpu_dyn_inst.cc
+++ b/src/gpu-compute/gpu_dyn_inst.cc
@@ -399,6 +399,12 @@
}
bool
+GPUDynInst::isSleep() const
+{
+ return _staticInst->isSleep();
+}
+
+bool
GPUDynInst::isBarrier() const
{
return _staticInst->isBarrier();
diff --git a/src/gpu-compute/gpu_dyn_inst.hh
b/src/gpu-compute/gpu_dyn_inst.hh
index 8c7cf87..851a46a 100644
--- a/src/gpu-compute/gpu_dyn_inst.hh
+++ b/src/gpu-compute/gpu_dyn_inst.hh
@@ -180,6 +180,7 @@
bool isUnconditionalJump() const;
bool isSpecialOp() const;
bool isWaitcnt() const;
+ bool isSleep() const;
bool isBarrier() const;
bool isMemSync() const;
diff --git a/src/gpu-compute/gpu_static_inst.hh
b/src/gpu-compute/gpu_static_inst.hh
index 88fd9f9..f973f2f 100644
--- a/src/gpu-compute/gpu_static_inst.hh
+++ b/src/gpu-compute/gpu_static_inst.hh
@@ -119,6 +119,7 @@
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]; }
diff --git a/src/gpu-compute/schedule_stage.cc
b/src/gpu-compute/schedule_stage.cc
index 02580fe..8a2ea18 100644
--- a/src/gpu-compute/schedule_stage.cc
+++ b/src/gpu-compute/schedule_stage.cc
@@ -317,6 +317,9 @@
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);
diff --git a/src/gpu-compute/scoreboard_check_stage.cc
b/src/gpu-compute/scoreboard_check_stage.cc
index c246279..08ce6a1 100644
--- a/src/gpu-compute/scoreboard_check_stage.cc
+++ b/src/gpu-compute/scoreboard_check_stage.cc
@@ -92,6 +92,15 @@
}
}
+ // 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 @@
// 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());
}
diff --git a/src/gpu-compute/scoreboard_check_stage.hh
b/src/gpu-compute/scoreboard_check_stage.hh
index 419dffb..c2c114a 100644
--- a/src/gpu-compute/scoreboard_check_stage.hh
+++ b/src/gpu-compute/scoreboard_check_stage.hh
@@ -65,6 +65,7 @@
NRDY_WF_STOP,
NRDY_IB_EMPTY,
NRDY_WAIT_CNT,
+ NRDY_SLEEP,
NRDY_BARRIER_WAIT,
NRDY_VGPR_NRDY,
NRDY_SGPR_NRDY,
diff --git a/src/gpu-compute/wavefront.cc b/src/gpu-compute/wavefront.cc
index 343b5c9..e442e2a 100644
--- a/src/gpu-compute/wavefront.cc
+++ b/src/gpu-compute/wavefront.cc
@@ -49,7 +49,7 @@
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;
@@ -584,6 +584,20 @@
}
bool
+Wavefront::isOldestInstSleep()
+{
+ if (instructionBuffer.empty())
+ return false;
+
+ GPUDynInstPtr ii = instructionBuffer.front();
+
+ if (ii->isSleep()) {
+ return true;
+ }
+ return false;
+}
+
+bool
Wavefront::isOldestInstWaitcnt()
{
if (instructionBuffer.empty())
@@ -1226,6 +1240,32 @@
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)
{
diff --git a/src/gpu-compute/wavefront.hh b/src/gpu-compute/wavefront.hh
index 7b617c6..1edc6dc 100644
--- a/src/gpu-compute/wavefront.hh
+++ b/src/gpu-compute/wavefront.hh
@@ -68,6 +68,9 @@
S_RUNNING,
// wavefront is stalled
S_STALLED,
+
+ S_STALLED_SLEEP,
+
/**
* wavefront has unsatisfied wait counts
*
@@ -134,6 +137,7 @@
bool isGmInstruction(GPUDynInstPtr ii);
bool isLmInstruction(GPUDynInstPtr ii);
bool isOldestInstWaitcnt();
+ bool isOldestInstSleep();
bool isOldestInstGMem();
bool isOldestInstLMem();
bool isOldestInstPrivMem();
@@ -276,6 +280,9 @@
/** Freeing VRF space */
void freeRegisterFile();
+ bool sleepDone();
+ void setSleepTime(int sleep_time);
+
TheGpuISA::GPUISA&
gpuISA()
{
@@ -315,6 +322,7 @@
int vmemInstsIssued;
int expInstsIssued;
int lgkmInstsIssued;
+ int sleepCnt;
status_e status;
Addr _pc;
VectorMask _execMask;
--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/39115
To unsubscribe, or for help writing mail filters, visit
https://gem5-review.googlesource.com/settings
Gerrit-Project: public/gem5
Gerrit-Branch: develop
Gerrit-Change-Id: I4811c318ac2c76c485e2bfd9d93baa1205ecf183
Gerrit-Change-Number: 39115
Gerrit-PatchSet: 5
Gerrit-Owner: Alexandru Duțu <[email protected]>
Gerrit-Reviewer: Kyle Roarty <[email protected]>
Gerrit-Reviewer: Matt Sinclair <[email protected]>
Gerrit-Reviewer: Matthew Poremba <[email protected]>
Gerrit-Reviewer: kokoro <[email protected]>
Gerrit-MessageType: merged
_______________________________________________
gem5-dev mailing list -- [email protected]
To unsubscribe send an email to [email protected]
%(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s