1 /*
2 * Copyright © 2022 Collabora Ltd.
3 * SPDX-License-Identifier: MIT
4 */
5 #include "mme_runner.h"
6 #include "mme_tu104_sim.h"
7
8 #include <vector>
9
10 #include "nvk_clc597.h"
11
12 class mme_builder_test : public ::testing::Test {
13 public:
14 mme_builder_test();
15 ~mme_builder_test();
16
17 std::vector<mme_runner *> sims;
18 uint32_t expected[DATA_DWORDS];
19
20 private:
21 mme_fermi_sim_runner fermi_sim;
22 mme_tu104_sim_runner tu104_sim;
23 };
24
25 #define DATA_ADDR 0xc0ffee00
26
mme_builder_test()27 mme_builder_test::mme_builder_test() :
28 fermi_sim(DATA_ADDR),
29 tu104_sim(DATA_ADDR)
30 {
31 memset(expected, 0, sizeof(expected));
32 sims.push_back(&fermi_sim);
33 sims.push_back(&tu104_sim);
34 }
35
~mme_builder_test()36 mme_builder_test::~mme_builder_test()
37 { }
38
39 #define ASSERT_SIM_DATA(sim) do { \
40 for (uint32_t i = 0; i < DATA_DWORDS; i++) \
41 ASSERT_EQ((sim)->data[i], expected[i]); \
42 } while (0)
43
TEST_F(mme_builder_test,sanity)44 TEST_F(mme_builder_test, sanity)
45 {
46 const uint32_t canary = 0xc0ffee01;
47
48 expected[0] = canary;
49
50 for (auto sim : sims) {
51 mme_builder b;
52 mme_builder_init(&b, sim->devinfo);
53
54 sim->mme_store_data(&b, 0, mme_imm(canary));
55
56 auto macro = mme_builder_finish_vec(&b);
57
58 std::vector<uint32_t> params;
59 sim->run_macro(macro, params);
60 ASSERT_SIM_DATA(sim);
61 }
62 }
63
64 static uint32_t
merge(uint32_t x,uint32_t y,uint16_t dst_pos,uint16_t bits,uint16_t src_pos)65 merge(uint32_t x, uint32_t y,
66 uint16_t dst_pos, uint16_t bits, uint16_t src_pos)
67 {
68 x &= ~(BITFIELD_MASK(bits) << dst_pos);
69 y &= (BITFIELD_MASK(bits) << src_pos);
70 return x | ((y >> src_pos) << dst_pos);
71 }
72
73 static const uint32_t add_cases[] = {
74 0x00000001,
75 0xffffffff,
76 0x0000ffff,
77 0x00008000,
78 0x0001ffff,
79 0xffff8000,
80 0x00010000,
81 0x00020000,
82 0xfffc0000,
83 0xfffe0000,
84 };
85
TEST_F(mme_builder_test,add)86 TEST_F(mme_builder_test, add)
87 {
88 for (auto sim : sims) {
89 mme_builder b;
90 mme_builder_init(&b, sim->devinfo);
91
92 mme_value x = mme_load(&b);
93 mme_value y = mme_load(&b);
94
95 sim->mme_store_data(&b, 0, mme_add(&b, x, y));
96
97 auto macro = mme_builder_finish_vec(&b);
98
99 for (uint32_t i = 0; i < ARRAY_SIZE(add_cases); i++) {
100 for (uint32_t j = 0; j < ARRAY_SIZE(add_cases); j++) {
101 std::vector<uint32_t> params;
102 params.push_back(add_cases[i]);
103 params.push_back(add_cases[j]);
104
105 sim->run_macro(macro, params);
106 ASSERT_EQ(sim->data[0], add_cases[i] + add_cases[j]);
107 }
108 }
109 }
110 }
111
TEST_F(mme_builder_test,add_imm)112 TEST_F(mme_builder_test, add_imm)
113 {
114 for (auto sim : sims) {
115 mme_builder b;
116 mme_builder_init(&b, sim->devinfo);
117
118 mme_value x = mme_load(&b);
119
120 for (uint32_t j = 0; j < ARRAY_SIZE(add_cases); j++) {
121 mme_value y = mme_imm(add_cases[j]);
122 sim->mme_store_data(&b, j, mme_add(&b, x, y), true);
123 }
124
125 auto macro = mme_builder_finish_vec(&b);
126
127 for (uint32_t i = 0; i < ARRAY_SIZE(add_cases); i++) {
128 std::vector<uint32_t> params;
129 params.push_back(add_cases[i]);
130
131 sim->run_macro(macro, params);
132
133 for (uint32_t j = 0; j < ARRAY_SIZE(add_cases); j++)
134 ASSERT_EQ(sim->data[j], add_cases[i] + add_cases[j]);
135 }
136 }
137 }
138
TEST_F(mme_builder_test,sub)139 TEST_F(mme_builder_test, sub)
140 {
141 for (auto sim : sims) {
142 mme_builder b;
143 mme_builder_init(&b, sim->devinfo);
144
145 mme_value x = mme_load(&b);
146 mme_value y = mme_load(&b);
147
148 sim->mme_store_data(&b, 0, mme_sub(&b, x, y));
149
150 auto macro = mme_builder_finish_vec(&b);
151
152 for (uint32_t i = 0; i < ARRAY_SIZE(add_cases); i++) {
153 for (uint32_t j = 0; j < ARRAY_SIZE(add_cases); j++) {
154 std::vector<uint32_t> params;
155 params.push_back(add_cases[i]);
156 params.push_back(add_cases[j]);
157
158 sim->run_macro(macro, params);
159 ASSERT_EQ(sim->data[0], add_cases[i] - add_cases[j]);
160 }
161 }
162 }
163 }
164
TEST_F(mme_builder_test,sub_imm)165 TEST_F(mme_builder_test, sub_imm)
166 {
167 for (auto sim : sims) {
168 mme_builder b;
169 mme_builder_init(&b, sim->devinfo);
170
171 mme_value x = mme_load(&b);
172
173 for (uint32_t j = 0; j < ARRAY_SIZE(add_cases); j++) {
174 mme_value y = mme_imm(add_cases[j]);
175 sim->mme_store_data(&b, j, mme_sub(&b, x, y), true);
176 }
177
178 auto macro = mme_builder_finish_vec(&b);
179
180 for (uint32_t i = 0; i < ARRAY_SIZE(add_cases); i++) {
181 std::vector<uint32_t> params;
182 params.push_back(add_cases[i]);
183
184 sim->run_macro(macro, params);
185
186 for (uint32_t j = 0; j < ARRAY_SIZE(add_cases); j++)
187 ASSERT_EQ(sim->data[j], add_cases[i] - add_cases[j]);
188 }
189 }
190 }
191
TEST_F(mme_builder_test,sll_srl)192 TEST_F(mme_builder_test, sll_srl)
193 {
194 static const uint32_t x = 0xac406fe1;
195
196 for (auto sim : sims) {
197 mme_builder b;
198 mme_builder_init(&b, sim->devinfo);
199
200 mme_value xv = mme_load(&b);
201 mme_value yv = mme_load(&b);
202
203 sim->mme_store_data(&b, 0, mme_sll(&b, xv, yv));
204 sim->mme_store_data(&b, 1, mme_srl(&b, xv, yv));
205
206 auto macro = mme_builder_finish_vec(&b);
207
208 /* Fermi can't shift by 0 */
209 for (uint32_t i = 1; i < 31; i++) {
210 std::vector<uint32_t> params;
211 params.push_back(x);
212 params.push_back(i);
213
214 sim->run_macro(macro, params);
215 ASSERT_EQ(sim->data[0], x << i);
216 ASSERT_EQ(sim->data[1], x >> i);
217 }
218 }
219 }
220
TEST_F(mme_builder_test,merge)221 TEST_F(mme_builder_test, merge)
222 {
223 static const struct {
224 uint16_t dst_pos;
225 uint16_t bits;
226 uint16_t src_pos;
227 } cases[] = {
228 { 12, 12, 20 },
229 { 12, 8, 20 },
230 { 8, 12, 20 },
231 { 12, 16, 8 },
232 { 24, 12, 8 },
233 };
234
235 static const uint32_t x = 0x0c406fe0;
236 static const uint32_t y = 0x76543210;
237
238 for (uint32_t i = 0; i < ARRAY_SIZE(cases); i++) {
239 expected[i] = merge(x, y, cases[i].dst_pos,
240 cases[i].bits, cases[i].src_pos);
241 }
242
243 for (auto sim : sims) {
244 mme_builder b;
245 mme_builder_init(&b, sim->devinfo);
246
247 mme_value xv = mme_load(&b);
248 mme_value yv = mme_load(&b);
249
250 for (uint32_t i = 0; i < ARRAY_SIZE(cases); i++) {
251 mme_value mv = mme_merge(&b, xv, yv, cases[i].dst_pos,
252 cases[i].bits, cases[i].src_pos);
253 sim->mme_store_data(&b, i, mv, true);
254 }
255
256 auto macro = mme_builder_finish_vec(&b);
257
258 std::vector<uint32_t> params;
259 params.push_back(x);
260 params.push_back(y);
261
262 sim->run_macro(macro, params);
263 ASSERT_SIM_DATA(sim);
264 }
265 }
266
TEST_F(mme_builder_test,while_ine)267 TEST_F(mme_builder_test, while_ine)
268 {
269 static const uint32_t cases[] = { 1, 3, 5, 8 };
270
271 for (auto sim : sims) {
272 mme_builder b;
273 mme_builder_init(&b, sim->devinfo);
274
275 mme_value inc = mme_load(&b);
276 mme_value bound = mme_load(&b);
277
278 mme_value x = mme_mov(&b, mme_zero());
279 mme_value y = mme_mov(&b, mme_zero());
280 mme_value z = mme_mov(&b, mme_zero());
281
282 mme_value i = mme_mov(&b, mme_zero());
283 mme_while(&b, ine, i, bound) {
284 mme_add_to(&b, x, x, mme_imm(1));
285 mme_add_to(&b, y, y, mme_imm(2));
286 mme_add_to(&b, z, z, mme_imm(3));
287 mme_add_to(&b, i, i, inc);
288 }
289
290 sim->mme_store_data(&b, 0, x);
291 sim->mme_store_data(&b, 1, y);
292 sim->mme_store_data(&b, 2, z);
293 sim->mme_store_data(&b, 3, i);
294
295 auto macro = mme_builder_finish_vec(&b);
296
297 for (unsigned i = 0; i < ARRAY_SIZE(cases); i++) {
298 const uint32_t inc = cases[i];
299 const uint32_t count = cases[ARRAY_SIZE(cases) - i - 1];
300 const uint32_t bound = inc * count;
301
302 std::vector<uint32_t> params;
303 params.push_back(inc);
304 params.push_back(bound);
305
306 expected[0] = count * 1;
307 expected[1] = count * 2;
308 expected[2] = count * 3;
309 expected[3] = count * inc;
310
311 sim->run_macro(macro, params);
312 ASSERT_SIM_DATA(sim);
313 }
314 }
315 }
316