kfdtest: Add coherency tests for Aqua Vanjaram

Aqua Vanjaram is intended to have fine-grained coherency
from anywhere to anywhere else using read-acquire and
write-release primitives.

Add a test that writes to memory covered by five
different cache lines, then write-releases, while
another thread read-acquires, then reads those
five locations in memory.

There are nine variations of the test to cover
CPU-GPU, same-GPU and across-GPU, vector instructions and
scalar instructions, and data local to the
acquirer or receiver.

Signed-off-by: David Francis <David.Francis@amd.com>
Change-Id: I20d2db5c53bd280e971479aad7e61df6ed5d3623


[ROCm/ROCR-Runtime commit: 30b1f23f7a]
Αυτή η υποβολή περιλαμβάνεται σε:
David Francis
2022-05-13 14:33:44 -04:00
υποβλήθηκε από Graham Sider
γονέας 25a9421f64
υποβολή b7dcb91b58
4 αρχεία άλλαξαν με 548 προσθήκες και 0 διαγραφές
@@ -2394,6 +2394,336 @@ TEST_F(KFDMemoryTest, SramCacheCoherenceWithGPU) {
TEST_END
}
void KFDMemoryTest::AcquireReleaseTestRunCPU(HSAuint32 acquireNode, bool scalar) {
LOG() << "Testing coherency from CPU to node " << std::dec << acquireNode << std::endl;
/* Allocate shared buffer - must be at least 64 * 6 bytes */
HsaMemoryBuffer buffer(PAGE_SIZE, acquireNode, false/*zero*/, false/*local*/, false/*exec*/);
buffer.MapMemToNodes(&acquireNode, 1);
/* Allocate output buffer and insert magic numbers */
HsaMemoryBuffer outputBuffer(PAGE_SIZE, acquireNode, true, false, false);
outputBuffer.As<char *>()[0x40] = 99;
outputBuffer.As<char *>()[0x80] = 99;
outputBuffer.As<char *>()[0xc0] = 99;
outputBuffer.As<char *>()[0x100] = 99;
outputBuffer.As<char *>()[0x140] = 99;
/* Flush results of previous tests from the buffer */
/* This would be done with SDMA, but SDMA doesn't work on some Aqua Vanjaram emulators */
PM4Queue flushQueue;
ASSERT_SUCCESS(flushQueue.Create(acquireNode));
HsaMemoryBuffer flushBuffer(PAGE_SIZE, acquireNode, true/*zero*/, false/*local*/, true/*exec*/);
ASSERT_SUCCESS(m_pAsm->RunAssembleBuf(FlushBufferForAcquireReleaseIsa, flushBuffer.As<char*>()));
Dispatch flushDispatch(flushBuffer);
flushDispatch.SetArgs(buffer.As<char *>(), NULL);
flushDispatch.SetDim(1, 1, 1);
flushDispatch.Submit(flushQueue);
flushDispatch.Sync(g_TestTimeOut);
/* Start acquiring thread */
PM4Queue acquireQueue;
ASSERT_SUCCESS(acquireQueue.Create(acquireNode));
HsaMemoryBuffer acquireBuffer(PAGE_SIZE, acquireNode, true/*zero*/, false/*local*/, true/*exec*/);
if (!scalar)
ASSERT_SUCCESS(m_pAsm->RunAssembleBuf(ReadAcquireVectorIsa, acquireBuffer.As<char*>()));
else
ASSERT_SUCCESS(m_pAsm->RunAssembleBuf(ReadAcquireScalarIsa, acquireBuffer.As<char*>()));
Dispatch acquireDispatch(acquireBuffer);
acquireDispatch.SetArgs(buffer.As<char *>(), outputBuffer.As<char *>());
acquireDispatch.SetDim(1, 1, 1);
acquireDispatch.Submit(acquireQueue);
/* Delay 100ms to ensure acquirer is waiting */
Delay(100);
if (!scalar) {
buffer.As<char *>()[0x40] = 0x1;
buffer.As<char *>()[0x80] = 0x2;
buffer.As<char *>()[0xc0] = 0x3;
buffer.As<char *>()[0x100] = 0x4;
buffer.As<char *>()[0x140] = 0x5;
} else {
buffer.As<char *>()[0x40] = 0x6;
buffer.As<char *>()[0x80] = 0x7;
buffer.As<char *>()[0xc0] = 0x8;
buffer.As<char *>()[0x100] = 0x9;
buffer.As<char *>()[0x140] = 0xa;
}
buffer.As<char *>()[0x0] = 0x1;
acquireDispatch.Sync(g_TestTimeOut);
/* Check test result*/
if (!scalar) {
EXPECT_EQ(0x1, outputBuffer.As<char *>()[0x40]);
EXPECT_EQ(0x2, outputBuffer.As<char *>()[0x80]);
EXPECT_EQ(0x3, outputBuffer.As<char *>()[0xc0]);
EXPECT_EQ(0x4, outputBuffer.As<char *>()[0x100]);
EXPECT_EQ(0x5, outputBuffer.As<char *>()[0x140]);
} else {
EXPECT_EQ(0x6, outputBuffer.As<char *>()[0x40]);
EXPECT_EQ(0x7, outputBuffer.As<char *>()[0x80]);
EXPECT_EQ(0x8, outputBuffer.As<char *>()[0xc0]);
EXPECT_EQ(0x9, outputBuffer.As<char *>()[0x100]);
EXPECT_EQ(0xa, outputBuffer.As<char *>()[0x140]);
}
/*
* Guide to results:
* 0x99: acquiring shader did not write to output buffer at all
* 0x77: coherency error. Either releasing shader did not write or acquiring shader read stale value
* All five EXPECT_EQ fail: error occurs even when releasing shader bypasses cache
* Only first four EXPECT_EQ fail: error occurs only when releasing shader uses cache
*/
/* Clean up */
EXPECT_SUCCESS(acquireQueue.Destroy());
EXPECT_SUCCESS(flushQueue.Destroy());
}
void KFDMemoryTest::AcquireReleaseTestRun(HSAuint32 acquireNode, HSAuint32 releaseNode,
bool localToRemote, bool scalar) {
LOG() << "Testing coherency from node " << std::dec << releaseNode << " to node " << std::dec << acquireNode << std::endl;
/* Allocate shared buffer - must be at least 64 * 6 bytes */
HSAuint32 localNode;
if (!localToRemote)
localNode = acquireNode;
else
localNode = releaseNode;
HsaMemoryBuffer buffer(PAGE_SIZE, localNode, false/*zero*/, true/*local*/, false/*exec*/);
unsigned int nodes[2] = {acquireNode, releaseNode};
buffer.MapMemToNodes(&nodes[0], 2);
/* Allocate output buffer and insert magic numbers */
HsaMemoryBuffer outputBuffer(PAGE_SIZE, acquireNode, true, false, false);
outputBuffer.As<char *>()[0x40] = 99;
outputBuffer.As<char *>()[0x80] = 99;
outputBuffer.As<char *>()[0xc0] = 99;
outputBuffer.As<char *>()[0x100] = 99;
outputBuffer.As<char *>()[0x140] = 99;
/* Flush results of previous tests from the buffer */
/* This would be done with SDMA, but SDMA doesn't work on some Aqua Vanjaram emulators */
PM4Queue flushQueue;
ASSERT_SUCCESS(flushQueue.Create(acquireNode));
HsaMemoryBuffer flushBuffer(PAGE_SIZE, acquireNode, true/*zero*/, false/*local*/, true/*exec*/);
ASSERT_SUCCESS(m_pAsm->RunAssembleBuf(FlushBufferForAcquireReleaseIsa, flushBuffer.As<char*>()));
Dispatch flushDispatch(flushBuffer);
flushDispatch.SetArgs(buffer.As<char *>(), NULL);
flushDispatch.SetDim(1, 1, 1);
flushDispatch.Submit(flushQueue);
flushDispatch.Sync(g_TestTimeOut);
/* Start acquiring thread */
PM4Queue acquireQueue;
ASSERT_SUCCESS(acquireQueue.Create(acquireNode));
HsaMemoryBuffer acquireBuffer(PAGE_SIZE, acquireNode, true/*zero*/, false/*local*/, true/*exec*/);
if (!scalar)
ASSERT_SUCCESS(m_pAsm->RunAssembleBuf(ReadAcquireVectorIsa, acquireBuffer.As<char*>()));
else
ASSERT_SUCCESS(m_pAsm->RunAssembleBuf(ReadAcquireScalarIsa, acquireBuffer.As<char*>()));
Dispatch acquireDispatch(acquireBuffer);
acquireDispatch.SetArgs(buffer.As<char *>(), outputBuffer.As<char *>());
acquireDispatch.SetDim(1, 1, 1);
acquireDispatch.Submit(acquireQueue);
/* Delay 100ms to ensure acquirer is waiting */
Delay(100);
/* Start releasing thread */
PM4Queue releaseQueue;
ASSERT_SUCCESS(releaseQueue.Create(releaseNode));
HsaMemoryBuffer releaseBuffer(PAGE_SIZE, releaseNode, true/*zero*/, false/*local*/, true/*exec*/);
if (!scalar)
ASSERT_SUCCESS(m_pAsm->RunAssembleBuf(WriteReleaseVectorIsa, releaseBuffer.As<char*>()));
else
ASSERT_SUCCESS(m_pAsm->RunAssembleBuf(WriteReleaseScalarIsa, releaseBuffer.As<char*>()));
Dispatch releaseDispatch(releaseBuffer);
releaseDispatch.SetArgs(buffer.As<char *>(), NULL);
releaseDispatch.SetDim(1, 1, 1);
releaseDispatch.Submit(releaseQueue);
/* Wait for threads to finish */
releaseDispatch.Sync(g_TestTimeOut);
acquireDispatch.Sync(g_TestTimeOut);
/* Check test result*/
if (!scalar) {
EXPECT_EQ(0x1, outputBuffer.As<char *>()[0x40]);
EXPECT_EQ(0x2, outputBuffer.As<char *>()[0x80]);
EXPECT_EQ(0x3, outputBuffer.As<char *>()[0xc0]);
EXPECT_EQ(0x4, outputBuffer.As<char *>()[0x100]);
EXPECT_EQ(0x5, outputBuffer.As<char *>()[0x140]);
} else {
EXPECT_EQ(0x6, outputBuffer.As<char *>()[0x40]);
EXPECT_EQ(0x7, outputBuffer.As<char *>()[0x80]);
EXPECT_EQ(0x8, outputBuffer.As<char *>()[0xc0]);
EXPECT_EQ(0x9, outputBuffer.As<char *>()[0x100]);
EXPECT_EQ(0xa, outputBuffer.As<char *>()[0x140]);
}
/*
* Guide to results:
* 0x99: acquiring shader did not write to output buffer at all
* 0x77: coherency error. Either releasing shader did not write or acquiring shader read stale value
* All five EXPECT_EQ fail: error occurs even when releasing shader bypasses cache
* Only first four EXPECT_EQ fail: error occurs only when releasing shader uses cache
*/
/* Clean up */
EXPECT_SUCCESS(acquireQueue.Destroy());
EXPECT_SUCCESS(releaseQueue.Destroy());
EXPECT_SUCCESS(flushQueue.Destroy());
}
/* A test of the memory coherence features on Aqua_Vanjaram.
* One shader stores values at 5 positions in memory, then performs
* a write-release. The other shader performs a read-acquire, then loads
* those 5 values, then stores them in a CPU-visible buffer
*
* withinGPU: When true, the two shaders will be loaded onto two nodes within
* the same GPU. When false, the two shaders will be loaded onto different
* GPUs.
*
* localToRemote: When true, the shared memory will be local to the releasing node.
* When false, the shared memory will be local to the acquiring node.
*
* scalar: When true, the shared data will be stored and loaded with scalar instructions.
* When false, the shared data will be stored and loaded with vector instructions.
*/
void KFDMemoryTest::AcquireReleaseTest(bool withinGPU, bool localToRemote, bool scalar) {
if (m_FamilyId != FAMILY_AV) {
LOG() << "Skipping test: Test requires aqua vanjaram series asics." << std::endl;
return;
}
/* Find second node - nodes with the same DrmRenderMinor are on the same GPU */
const std::vector<int> gpuNodes = m_NodeInfo.GetNodesWithGPU();
HSAuint32 acquireNode;
HSAint32 acquireDRM;
bool foundSecondNode = false;
for (unsigned i = 0; i < gpuNodes.size(); i++) {
acquireNode = gpuNodes.at(i);
acquireDRM = m_NodeInfo.GetNodeProperties(acquireNode)->DrmRenderMinor;
for (unsigned j = 0; j < gpuNodes.size(); j++) {
if (!withinGPU) {
if (m_NodeInfo.GetNodeProperties(gpuNodes.at(j))->DrmRenderMinor != acquireDRM) {
foundSecondNode = true;
AcquireReleaseTestRun(acquireNode, gpuNodes.at(j), localToRemote, scalar);
}
} else {
if (m_NodeInfo.GetNodeProperties(gpuNodes.at(j))->DrmRenderMinor == acquireDRM && gpuNodes.at(j) != acquireNode) {
foundSecondNode = true;
AcquireReleaseTestRun(acquireNode, gpuNodes.at(j), localToRemote, scalar);
}
}
}
}
if (!foundSecondNode) {
if (!withinGPU) {
LOG() << "Skipping test: At least two GPUs are required." << std::endl;
} else {
LOG() << "Skipping test: At least two nodes on the same GPU are required." << std::endl;
}
}
}
TEST_F(KFDMemoryTest, AcquireReleaseCPU) {
if (m_FamilyId != FAMILY_AV) {
LOG() << "Skipping test: Test requires aqua vanjaram series asics." << std::endl;
return;
}
/* Find second node - nodes with the same DrmRenderMinor are on the same GPU */
const std::vector<int> gpuNodes = m_NodeInfo.GetNodesWithGPU();
HSAuint32 acquireNode;
for (unsigned i = 0; i < gpuNodes.size(); i++) {
acquireNode = gpuNodes.at(i);
AcquireReleaseTestRunCPU(acquireNode, true);
AcquireReleaseTestRunCPU(acquireNode, false);
}
}
TEST_F(KFDMemoryTest, AcquireReleaseFarLocalVector) {
TEST_REQUIRE_ENV_CAPABILITIES(ENVCAPS_64BITLINUX);
TEST_START(TESTPROFILE_RUNALL);
AcquireReleaseTest(false /* multi-GPU */, false /* acquirer is local */, false /* vector */);
TEST_END
}
TEST_F(KFDMemoryTest, AcquireReleaseFarLocalScalar) {
TEST_REQUIRE_ENV_CAPABILITIES(ENVCAPS_64BITLINUX);
TEST_START(TESTPROFILE_RUNALL);
AcquireReleaseTest(false /* multi-GPU */, false /* acquirer is local */, true /* scalar */);
TEST_END
}
TEST_F(KFDMemoryTest, AcquireReleaseFarRemoteVector) {
TEST_REQUIRE_ENV_CAPABILITIES(ENVCAPS_64BITLINUX);
TEST_START(TESTPROFILE_RUNALL);
AcquireReleaseTest(false /* multi-GPU */, true /* releaser is local */, false /* vector */);
TEST_END
}
TEST_F(KFDMemoryTest, AcquireReleaseFarRemoteScalar) {
TEST_REQUIRE_ENV_CAPABILITIES(ENVCAPS_64BITLINUX);
TEST_START(TESTPROFILE_RUNALL);
AcquireReleaseTest(false /* multi-GPU */, true /* releaser is local */, true /* scalar */);
TEST_END
}
TEST_F(KFDMemoryTest, AcquireReleaseCloseLocalVector) {
TEST_REQUIRE_ENV_CAPABILITIES(ENVCAPS_64BITLINUX);
TEST_START(TESTPROFILE_RUNALL);
AcquireReleaseTest(true /* within-GPU */, false /* acquirer is local */, false /* vector */);
TEST_END
}
TEST_F(KFDMemoryTest, AcquireReleaseCloseLocalScalar) {
TEST_REQUIRE_ENV_CAPABILITIES(ENVCAPS_64BITLINUX);
TEST_START(TESTPROFILE_RUNALL);
AcquireReleaseTest(true /* within-GPU */, false /* acquirer is local */, true /* scalar */);
TEST_END
}
TEST_F(KFDMemoryTest, AcquireReleaseCloseRemoteVector) {
TEST_REQUIRE_ENV_CAPABILITIES(ENVCAPS_64BITLINUX);
TEST_START(TESTPROFILE_RUNALL);
AcquireReleaseTest(true /* within-GPU */, true /* releaser is local */, false /* vector */);
TEST_END
}
TEST_F(KFDMemoryTest, AcquireReleaseCloseRemoteScalar) {
TEST_REQUIRE_ENV_CAPABILITIES(ENVCAPS_64BITLINUX);
TEST_START(TESTPROFILE_RUNALL);
AcquireReleaseTest(true /* within-GPU */, true /* releaser is local */, true /* scalar */);
TEST_END
}
/* Application register same userptr to multiple GPUs using multiple threads
* Test multiple threads register/deregister same userptr, to verify Thunk race handling
*/
@@ -42,6 +42,10 @@ class KFDMemoryTest : public KFDBaseComponentTest {
void BinarySearchLargestBuffer(int allocNode, const HsaMemFlags &memFlags,
HSAuint64 highMB, int nodeToMap,
HSAuint64 *lastSizeMB);
void AcquireReleaseTestRunCPU(HSAuint32 acquireNode, bool scalar);
void AcquireReleaseTestRun(HSAuint32 acquireNode, HSAuint32 releaseNode,
bool localToRemote, bool scalar);
void AcquireReleaseTest(bool withinGPU, bool localToRemote, bool scalar);
};
#endif // __KFD_MEMORY_TEST__H__
@@ -400,6 +400,215 @@ const char *WriteAndSignalIsa =
s_endpgm
)";
/* Input:
* s[0:1], A buffer of at least 64 * 6 bytes
*
* Store the value 0x77 at the 5 addresses 0x40,
* 0x80, ..., 0x140 in the buffer
*
* Aqua Vanjaram only
*/
const char *FlushBufferForAcquireReleaseIsa =
SHADER_START
R"(
.if (.amdgcn.gfx_generation_number == 9 && .amdgcn.gfx_generation_minor == 4)
s_mov_b32 s11, 0x77
s_mov_b32 s12, 0x0
// Store some data on 5 different cache lines
s_store_dword s12, s[0:1], 0x0 glc
s_store_dword s11, s[0:1], 0x40 glc
s_store_dword s11, s[0:1], 0x80 glc
s_store_dword s11, s[0:1], 0xc0 glc
s_store_dword s11, s[0:1], 0x100 glc
s_store_dword s11, s[0:1], 0x140 glc
s_waitcnt lgkmcnt(0)
.endif
s_endpgm
)";
/* Input:
* s[0:1], A buffer of at least 64 * 6 bytes,
* shared with the acquiring shader
*
* Store the values 1 - 5 at the 5 addresses 0x40,
* 0x80, ..., 0x140 in the buffer, then signal
* the flag at address 0x0 in the buffer.
*
* Uses vector stores
*
* Aqua Vanjaram only
*/
const char *WriteReleaseVectorIsa =
SHADER_START
R"(
.if (.amdgcn.gfx_generation_number == 9 && .amdgcn.gfx_generation_minor == 4)
v_mov_b32 v11, 0x1
v_mov_b32 v12, 0x2
v_mov_b32 v13, 0x3
v_mov_b32 v14, 0x4
v_mov_b32 v15, 0x5
v_mov_b32 v21, 0x40
v_mov_b32 v22, 0x80
v_mov_b32 v23, 0xc0
v_mov_b32 v24, 0x100
v_mov_b32 v25, 0x140
// Store some data on 5 different cache lines
global_store_dword v21, v11, s[0:1]
global_store_dword v22, v12, s[0:1]
global_store_dword v23, v13, s[0:1]
global_store_dword v24, v14, s[0:1]
global_store_dword v25, v15, s[0:1] nt sc1 sc0
s_waitcnt vmcnt(0)
// Write-Release
s_mov_b32 s16, 0x1
buffer_wbl2 sc1 sc0
s_waitcnt vmcnt(0) & lgkmcnt(0)
s_store_dword s16, s[0:1], 0x0 glc
.endif
s_endpgm
)";
/* Input:
* s[0:1], A buffer of at least 64 * 6 bytes,
* shared with the acquiring shader
*
* Store the values 6 - 10 at the 5 addresses 0x40,
* 0x80, ..., 0x140 in the buffer, then signal
* the flag at address 0x0 in the buffer.
*
* Uses scalar stores
*
* Aqua Vanjaram only
*/
const char *WriteReleaseScalarIsa =
SHADER_START
R"(
.if (.amdgcn.gfx_generation_number == 9 && .amdgcn.gfx_generation_minor == 4)
s_mov_b32 s11, 0x6
s_mov_b32 s12, 0x7
s_mov_b32 s13, 0x8
s_mov_b32 s14, 0x9
s_mov_b32 s15, 0xa
// Store some data on 5 different cache lines
s_store_dword s11, s[0:1], 0x40
s_store_dword s12, s[0:1], 0x80
s_store_dword s13, s[0:1], 0xc0
s_store_dword s14, s[0:1], 0x100
s_store_dword s15, s[0:1], 0x140 glc
s_waitcnt lgkmcnt(0)
// Write-Release
s_dcache_wb // WB Scalar L1 cache
s_mov_b32 s16, 0x1
buffer_wbl2 sc1 sc0
s_waitcnt vmcnt(0) & lgkmcnt(0)
s_store_dword s16, s[0:1], 0x0 glc
s_waitcnt lgkmcnt(0)
.endif
s_endpgm
)";
/* Input:
* s[0:1], A buffer of at least 64 * 6 bytes,
* shared with the releasing shader
* s[2:3], A buffer of at least 64 * 6 bytes,
* accessible by the CPU, used for output
*
* Polls the flag at address 0x0 in the shared buffer.
* When the signal is received, read the values
* at the 5 addresses 0x40, 0x80, ... 0x140,
* and store them at the same locations in
* the output buffer
*
* Uses vector loads
*
* Aqua Vanjaram only
*/
const char *ReadAcquireVectorIsa =
SHADER_START
R"(
.if (.amdgcn.gfx_generation_number == 9 && .amdgcn.gfx_generation_minor == 4)
// Read-Acquire
s_mov_b32 s18, 0x1
LOOP:
s_load_dword s17, s[0:1], 0x0 glc
s_waitcnt lgkmcnt(0)
s_cmp_eq_i32 s17, s18
s_cbranch_scc0 LOOP
buffer_inv sc1 sc0
// Load data
v_mov_b32 v21, 0x40
v_mov_b32 v22, 0x80
v_mov_b32 v23, 0xc0
v_mov_b32 v24, 0x100
v_mov_b32 v25, 0x140
global_load_dword v11, v21, s[0:1]
global_load_dword v12, v22, s[0:1]
global_load_dword v13, v23, s[0:1]
global_load_dword v14, v24, s[0:1]
global_load_dword v15, v25, s[0:1]
s_waitcnt vmcnt(0)
// Store data for output
v_mov_b32 v21, 0x40
v_mov_b32 v22, 0x80
v_mov_b32 v23, 0xc0
v_mov_b32 v24, 0x100
v_mov_b32 v25, 0x140
global_store_dword v21, v11, s[2:3] nt sc1 sc0
global_store_dword v22, v12, s[2:3] nt sc1 sc0
global_store_dword v23, v13, s[2:3] nt sc1 sc0
global_store_dword v24, v14, s[2:3] nt sc1 sc0
global_store_dword v25, v15, s[2:3] nt sc1 sc0
s_waitcnt vmcnt(0)
.endif
s_endpgm
)";
/* Input:
* s[0:1], A buffer of at least 64 * 6 bytes,
* shared with the releasing shader
* s[2:3], A buffer of at least 64 * 6 bytes,
* accessible by the CPU, used for output
*
* Polls the flag at address 0x0 in the shared buffer.
* When the signal is received, read the values
* at the 5 addresses 0x40, 0x80, ... 0x140,
* and store them at the same locations in
* the output buffer
*
* Uses scalar loads
*
* Aqua Vanjaram only
*/
const char *ReadAcquireScalarIsa =
SHADER_START
R"(
.if (.amdgcn.gfx_generation_number == 9 && .amdgcn.gfx_generation_minor == 4)
// Read-Acquire
s_mov_b32 s18, 0x1
LOOP:
s_load_dword s17, s[0:1], 0x0 glc
s_waitcnt lgkmcnt(0)
s_cmp_eq_i32 s17, s18
s_cbranch_scc0 LOOP
buffer_inv sc1 sc0
// Load data
s_load_dword s21, s[0:1], 0x40
s_load_dword s22, s[0:1], 0x80
s_load_dword s23, s[0:1], 0xc0
s_load_dword s24, s[0:1], 0x100
s_load_dword s25, s[0:1], 0x140
s_waitcnt lgkmcnt(0)
// Store data for output
s_store_dword s21, s[2:3], 0x40 glc
s_store_dword s22, s[2:3], 0x80 glc
s_store_dword s23, s[2:3], 0xc0 glc
s_store_dword s24, s[2:3], 0x100 glc
s_store_dword s25, s[2:3], 0x140 glc
s_waitcnt lgkmcnt(0)
.endif
s_endpgm
)";
/**
* KFDQMTest
*/
@@ -43,6 +43,11 @@ extern const char *CopyOnSignalIsa;
extern const char *PollAndCopyIsa;
extern const char *WriteFlagAndValueIsa;
extern const char *WriteAndSignalIsa;
extern const char *WriteReleaseVectorIsa;
extern const char *WriteReleaseScalarIsa;
extern const char *ReadAcquireVectorIsa;
extern const char *ReadAcquireScalarIsa;
extern const char *FlushBufferForAcquireReleaseIsa;
/* KFDQMTest */
extern const char *LoopIsa;