1 /*
2  * Copyright (C) 2020-2021 Intel Corporation
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  */
7 
8 #include "shared/source/command_container/command_encoder.h"
9 #include "shared/test/common/cmd_parse/gen_cmd_parse.h"
10 #include "shared/test/common/helpers/unit_test_helper.h"
11 #include "shared/test/common/test_macros/test.h"
12 
13 #include "level_zero/core/source/cmdlist/cmdlist_hw_immediate.h"
14 #include "level_zero/core/test/unit_tests/fixtures/cmdlist_fixture.h"
15 #include "level_zero/core/test/unit_tests/fixtures/device_fixture.h"
16 
17 namespace L0 {
18 namespace ult {
19 
20 using CommandListAppendBarrier = Test<CommandListFixture>;
21 
HWTEST_F(CommandListAppendBarrier,WhenAppendingBarrierThenPipeControlIsGenerated)22 HWTEST_F(CommandListAppendBarrier, WhenAppendingBarrierThenPipeControlIsGenerated) {
23     using PIPE_CONTROL = typename FamilyType::PIPE_CONTROL;
24     auto usedSpaceBefore = commandList->commandContainer.getCommandStream()->getUsed();
25 
26     auto result = commandList->appendBarrier(nullptr, 0, nullptr);
27     ASSERT_EQ(ZE_RESULT_SUCCESS, result);
28 
29     auto usedSpaceAfter = commandList->commandContainer.getCommandStream()->getUsed();
30     ASSERT_GT(usedSpaceAfter, usedSpaceBefore);
31 
32     GenCmdList cmdList;
33     ASSERT_TRUE(FamilyType::PARSE::parseCommandBuffer(cmdList,
34                                                       ptrOffset(commandList->commandContainer.getCommandStream()->getCpuBase(), usedSpaceBefore),
35                                                       usedSpaceAfter - usedSpaceBefore));
36 
37     // Find a PC w/ CS stall
38     auto itorPC = find<PIPE_CONTROL *>(cmdList.begin(), cmdList.end());
39     ASSERT_NE(cmdList.end(), itorPC);
40     auto cmd = genCmdCast<PIPE_CONTROL *>(*itorPC);
41     EXPECT_TRUE(cmd->getCommandStreamerStallEnable());
42     EXPECT_FALSE(cmd->getDcFlushEnable());
43 }
44 
HWTEST_F(CommandListAppendBarrier,GivenEventVsNoEventWhenAppendingBarrierThenCorrectPipeControlsIsAddedToCommandStream)45 HWTEST_F(CommandListAppendBarrier, GivenEventVsNoEventWhenAppendingBarrierThenCorrectPipeControlsIsAddedToCommandStream) {
46     using PIPE_CONTROL = typename FamilyType::PIPE_CONTROL;
47     auto usedSpaceBefore = commandList->commandContainer.getCommandStream()->getUsed();
48     commandList->reset();
49     auto result = commandList->appendBarrier(event->toHandle(), 0, nullptr);
50     ASSERT_EQ(ZE_RESULT_SUCCESS, result);
51 
52     auto usedSpaceAfter = commandList->commandContainer.getCommandStream()->getUsed();
53     ASSERT_GT(usedSpaceAfter, usedSpaceBefore);
54 
55     GenCmdList cmdList1, cmdList2;
56     ASSERT_TRUE(FamilyType::PARSE::parseCommandBuffer(cmdList1,
57                                                       ptrOffset(commandList->commandContainer.getCommandStream()->getCpuBase(), 0),
58                                                       usedSpaceAfter));
59 
60     auto itor1 = findAll<PIPE_CONTROL *>(cmdList1.begin(), cmdList1.end());
61     ASSERT_FALSE(itor1.empty());
62 
63     commandList->reset();
64     usedSpaceBefore = commandList->commandContainer.getCommandStream()->getUsed();
65     result = commandList->appendBarrier(nullptr, 0, nullptr);
66     usedSpaceAfter = commandList->commandContainer.getCommandStream()->getUsed();
67 
68     ASSERT_EQ(ZE_RESULT_SUCCESS, result);
69     ASSERT_GT(usedSpaceAfter, usedSpaceBefore);
70 
71     ASSERT_TRUE(FamilyType::PARSE::parseCommandBuffer(cmdList2,
72                                                       ptrOffset(commandList->commandContainer.getCommandStream()->getCpuBase(), 0),
73                                                       usedSpaceAfter));
74     auto itor2 = findAll<PIPE_CONTROL *>(cmdList2.begin(), cmdList2.end());
75     ASSERT_FALSE(itor2.empty());
76 
77     auto sizeWithoutEvent = itor2.size();
78     auto sizeWithEvent = itor1.size();
79 
80     ASSERT_LE(sizeWithoutEvent, sizeWithEvent);
81 }
82 
83 using MultiTileCommandListAppendBarrier = Test<MultiTileCommandListFixture<false, false>>;
84 
HWTEST2_F(MultiTileCommandListAppendBarrier,WhenAppendingBarrierThenPipeControlIsGenerated,IsWithinXeGfxFamily)85 HWTEST2_F(MultiTileCommandListAppendBarrier, WhenAppendingBarrierThenPipeControlIsGenerated, IsWithinXeGfxFamily) {
86     using PIPE_CONTROL = typename FamilyType::PIPE_CONTROL;
87     using MI_BATCH_BUFFER_START = typename FamilyType::MI_BATCH_BUFFER_START;
88     using MI_STORE_DATA_IMM = typename FamilyType::MI_STORE_DATA_IMM;
89     using MI_ATOMIC = typename FamilyType::MI_ATOMIC;
90     using MI_SEMAPHORE_WAIT = typename FamilyType::MI_SEMAPHORE_WAIT;
91 
92     EXPECT_EQ(2u, device->getNEODevice()->getDeviceBitfield().count());
93     EXPECT_EQ(2u, commandList->partitionCount);
94 
95     size_t beforeControlSectionOffset = sizeof(MI_STORE_DATA_IMM) +
96                                         sizeof(PIPE_CONTROL) +
97                                         sizeof(MI_ATOMIC) + sizeof(MI_SEMAPHORE_WAIT) +
98                                         sizeof(MI_BATCH_BUFFER_START);
99 
100     size_t startOffset = beforeControlSectionOffset +
101                          (2 * sizeof(uint32_t));
102 
103     size_t expectedUseBuffer = startOffset +
104                                sizeof(MI_ATOMIC) + sizeof(MI_SEMAPHORE_WAIT) +
105                                sizeof(MI_STORE_DATA_IMM) +
106                                sizeof(MI_ATOMIC) + sizeof(MI_SEMAPHORE_WAIT);
107 
108     auto usedSpaceBefore = commandList->commandContainer.getCommandStream()->getUsed();
109     auto gpuBaseAddress = commandList->commandContainer.getCommandStream()->getGraphicsAllocation()->getGpuAddress() +
110                           usedSpaceBefore;
111 
112     auto gpuCrossTileSyncAddress = gpuBaseAddress +
113                                    beforeControlSectionOffset;
114 
115     auto gpuFinalSyncAddress = gpuCrossTileSyncAddress +
116                                sizeof(uint32_t);
117 
118     auto gpuStartAddress = gpuBaseAddress +
119                            startOffset;
120 
121     auto result = commandList->appendBarrier(nullptr, 0, nullptr);
122     ASSERT_EQ(ZE_RESULT_SUCCESS, result);
123 
124     auto usedSpaceAfter = commandList->commandContainer.getCommandStream()->getUsed();
125     ASSERT_GT(usedSpaceAfter, usedSpaceBefore);
126     size_t usedBuffer = usedSpaceAfter - usedSpaceBefore;
127     EXPECT_EQ(expectedUseBuffer, usedBuffer);
128 
129     void *cmdBuffer = ptrOffset(commandList->commandContainer.getCommandStream()->getCpuBase(), usedSpaceBefore);
130     size_t parsedOffset = 0;
131 
132     {
133         auto storeDataImm = genCmdCast<MI_STORE_DATA_IMM *>(ptrOffset(cmdBuffer, parsedOffset));
134         ASSERT_NE(nullptr, storeDataImm);
135         EXPECT_EQ(gpuFinalSyncAddress, storeDataImm->getAddress());
136         EXPECT_EQ(0u, storeDataImm->getDataDword0());
137         parsedOffset += sizeof(MI_STORE_DATA_IMM);
138     }
139     {
140         auto pipeControl = genCmdCast<PIPE_CONTROL *>(ptrOffset(cmdBuffer, parsedOffset));
141         ASSERT_NE(nullptr, pipeControl);
142         EXPECT_TRUE(pipeControl->getCommandStreamerStallEnable());
143         EXPECT_FALSE(pipeControl->getDcFlushEnable());
144         parsedOffset += sizeof(PIPE_CONTROL);
145     }
146     {
147         auto miAtomic = genCmdCast<MI_ATOMIC *>(ptrOffset(cmdBuffer, parsedOffset));
148         ASSERT_NE(nullptr, miAtomic);
149         auto miAtomicProgrammedAddress = NEO::UnitTestHelper<FamilyType>::getAtomicMemoryAddress(*miAtomic);
150         EXPECT_EQ(gpuCrossTileSyncAddress, miAtomicProgrammedAddress);
151         EXPECT_FALSE(miAtomic->getReturnDataControl());
152         EXPECT_EQ(MI_ATOMIC::ATOMIC_OPCODES::ATOMIC_4B_INCREMENT, miAtomic->getAtomicOpcode());
153         parsedOffset += sizeof(MI_ATOMIC);
154     }
155     {
156         auto miSemaphore = genCmdCast<MI_SEMAPHORE_WAIT *>(ptrOffset(cmdBuffer, parsedOffset));
157         ASSERT_NE(nullptr, miSemaphore);
158         EXPECT_EQ(gpuCrossTileSyncAddress, miSemaphore->getSemaphoreGraphicsAddress());
159         EXPECT_EQ(MI_SEMAPHORE_WAIT::COMPARE_OPERATION::COMPARE_OPERATION_SAD_GREATER_THAN_OR_EQUAL_SDD, miSemaphore->getCompareOperation());
160         EXPECT_EQ(2u, miSemaphore->getSemaphoreDataDword());
161         parsedOffset += sizeof(MI_SEMAPHORE_WAIT);
162     }
163     {
164         auto bbStart = genCmdCast<MI_BATCH_BUFFER_START *>(ptrOffset(cmdBuffer, parsedOffset));
165         ASSERT_NE(nullptr, bbStart);
166         EXPECT_EQ(gpuStartAddress, bbStart->getBatchBufferStartAddress());
167         EXPECT_EQ(MI_BATCH_BUFFER_START::SECOND_LEVEL_BATCH_BUFFER::SECOND_LEVEL_BATCH_BUFFER_SECOND_LEVEL_BATCH, bbStart->getSecondLevelBatchBuffer());
168         parsedOffset += sizeof(MI_BATCH_BUFFER_START);
169     }
170     {
171         auto crossField = reinterpret_cast<uint32_t *>(ptrOffset(cmdBuffer, parsedOffset));
172         EXPECT_EQ(0u, *crossField);
173         parsedOffset += sizeof(uint32_t);
174         auto finalField = reinterpret_cast<uint32_t *>(ptrOffset(cmdBuffer, parsedOffset));
175         EXPECT_EQ(0u, *finalField);
176         parsedOffset += sizeof(uint32_t);
177     }
178     {
179         auto miAtomic = genCmdCast<MI_ATOMIC *>(ptrOffset(cmdBuffer, parsedOffset));
180         ASSERT_NE(nullptr, miAtomic);
181         auto miAtomicProgrammedAddress = NEO::UnitTestHelper<FamilyType>::getAtomicMemoryAddress(*miAtomic);
182         EXPECT_EQ(gpuFinalSyncAddress, miAtomicProgrammedAddress);
183         EXPECT_FALSE(miAtomic->getReturnDataControl());
184         EXPECT_EQ(MI_ATOMIC::ATOMIC_OPCODES::ATOMIC_4B_INCREMENT, miAtomic->getAtomicOpcode());
185         parsedOffset += sizeof(MI_ATOMIC);
186     }
187     {
188         auto miSemaphore = genCmdCast<MI_SEMAPHORE_WAIT *>(ptrOffset(cmdBuffer, parsedOffset));
189         ASSERT_NE(nullptr, miSemaphore);
190         EXPECT_EQ(gpuFinalSyncAddress, miSemaphore->getSemaphoreGraphicsAddress());
191         EXPECT_EQ(MI_SEMAPHORE_WAIT::COMPARE_OPERATION::COMPARE_OPERATION_SAD_GREATER_THAN_OR_EQUAL_SDD, miSemaphore->getCompareOperation());
192         EXPECT_EQ(2u, miSemaphore->getSemaphoreDataDword());
193         parsedOffset += sizeof(MI_SEMAPHORE_WAIT);
194     }
195     {
196         auto storeDataImm = genCmdCast<MI_STORE_DATA_IMM *>(ptrOffset(cmdBuffer, parsedOffset));
197         ASSERT_NE(nullptr, storeDataImm);
198         EXPECT_EQ(gpuCrossTileSyncAddress, storeDataImm->getAddress());
199         EXPECT_EQ(0u, storeDataImm->getDataDword0());
200         parsedOffset += sizeof(MI_STORE_DATA_IMM);
201     }
202     {
203         auto miAtomic = genCmdCast<MI_ATOMIC *>(ptrOffset(cmdBuffer, parsedOffset));
204         ASSERT_NE(nullptr, miAtomic);
205         auto miAtomicProgrammedAddress = NEO::UnitTestHelper<FamilyType>::getAtomicMemoryAddress(*miAtomic);
206         EXPECT_EQ(gpuFinalSyncAddress, miAtomicProgrammedAddress);
207         EXPECT_FALSE(miAtomic->getReturnDataControl());
208         EXPECT_EQ(MI_ATOMIC::ATOMIC_OPCODES::ATOMIC_4B_INCREMENT, miAtomic->getAtomicOpcode());
209         parsedOffset += sizeof(MI_ATOMIC);
210     }
211     {
212         auto miSemaphore = genCmdCast<MI_SEMAPHORE_WAIT *>(ptrOffset(cmdBuffer, parsedOffset));
213         ASSERT_NE(nullptr, miSemaphore);
214         EXPECT_EQ(gpuFinalSyncAddress, miSemaphore->getSemaphoreGraphicsAddress());
215         EXPECT_EQ(MI_SEMAPHORE_WAIT::COMPARE_OPERATION::COMPARE_OPERATION_SAD_GREATER_THAN_OR_EQUAL_SDD, miSemaphore->getCompareOperation());
216         EXPECT_EQ(4u, miSemaphore->getSemaphoreDataDword());
217         parsedOffset += sizeof(MI_SEMAPHORE_WAIT);
218     }
219     EXPECT_EQ(expectedUseBuffer, parsedOffset);
220 }
221 
222 } // namespace ult
223 } // namespace L0
224