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

Reply via email to