xref: /aosp_15_r20/external/mesa3d/src/nouveau/mme/tests/mme_builder_test.cpp (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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 "nv_push_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 
192 static const uint32_t mul_cases[] = {
193    0x00000000,
194    0x00000001,
195    0x0000005c,
196    0x00c0ffee,
197    0xffffffff,
198    0x0000ffff,
199    0x00008000,
200    0x0001ffff,
201    0xffff8000,
202    0x00010000,
203    0x00020000,
204    0xfffc0000,
205    0xfffe0000,
206 };
207 
TEST_F(mme_builder_test,mul_32x32_32)208 TEST_F(mme_builder_test, mul_32x32_32)
209 {
210    for (auto sim : sims) {
211       mme_builder b;
212       mme_builder_init(&b, sim->devinfo);
213 
214       mme_value x = mme_load(&b);
215       mme_value y = mme_load(&b);
216 
217       sim->mme_store_data(&b, 0, mme_mul_32x32_32_free_srcs(&b, x, y));
218 
219       auto macro = mme_builder_finish_vec(&b);
220 
221       for (uint32_t i = 0; i < ARRAY_SIZE(mul_cases); i++) {
222          for (uint32_t j = 0; j < ARRAY_SIZE(mul_cases); j++) {
223             std::vector<uint32_t> params;
224             params.push_back(mul_cases[i]);
225             params.push_back(mul_cases[j]);
226 
227             sim->run_macro(macro, params);
228             ASSERT_EQ(sim->data[0], mul_cases[i] * mul_cases[j]);
229          }
230       }
231    }
232 }
233 
TEST_F(mme_builder_test,umul_32x32_64)234 TEST_F(mme_builder_test, umul_32x32_64)
235 {
236    for (auto sim : sims) {
237       mme_builder b;
238       mme_builder_init(&b, sim->devinfo);
239 
240       mme_value x = mme_load(&b);
241       mme_value y = mme_load(&b);
242 
243       struct mme_value64 d = mme_umul_32x32_64_free_srcs(&b, x, y);
244 
245       sim->mme_store_data(&b, 0, d.lo);
246       sim->mme_store_data(&b, 1, d.hi);
247 
248       auto macro = mme_builder_finish_vec(&b);
249 
250       for (uint32_t i = 0; i < ARRAY_SIZE(mul_cases); i++) {
251          for (uint32_t j = 0; j < ARRAY_SIZE(mul_cases); j++) {
252             std::vector<uint32_t> params;
253             params.push_back(mul_cases[i]);
254             params.push_back(mul_cases[j]);
255 
256             sim->run_macro(macro, params);
257 
258             uint64_t d = (uint64_t)mul_cases[i] * (uint64_t)mul_cases[j];
259             ASSERT_EQ(sim->data[0], (uint32_t)d);
260             ASSERT_EQ(sim->data[1], (uint32_t)(d >> 32));
261          }
262       }
263    }
264 }
265 
TEST_F(mme_builder_test,umul_32x64_64)266 TEST_F(mme_builder_test, umul_32x64_64)
267 {
268    for (auto sim : sims) {
269       mme_builder b;
270       mme_builder_init(&b, sim->devinfo);
271 
272       mme_value x = mme_load(&b);
273       struct mme_value64 y;
274       y.lo = mme_load(&b);
275       y.hi = mme_load(&b);
276 
277       struct mme_value64 d = mme_umul_32x64_64_free_srcs(&b, x, y);
278 
279       sim->mme_store_data(&b, 0, d.lo);
280       sim->mme_store_data(&b, 1, d.hi);
281 
282       auto macro = mme_builder_finish_vec(&b);
283 
284       for (uint32_t i = 0; i < ARRAY_SIZE(mul_cases); i++) {
285          for (uint32_t j = 0; j < ARRAY_SIZE(mul_cases); j++) {
286             for (uint32_t k = 0; k < ARRAY_SIZE(mul_cases); k++) {
287                std::vector<uint32_t> params;
288                params.push_back(mul_cases[i]);
289                params.push_back(mul_cases[j]);
290                params.push_back(mul_cases[k]);
291 
292                sim->run_macro(macro, params);
293 
294                uint32_t x = mul_cases[i];
295                uint32_t y_lo = mul_cases[j];
296                uint32_t y_hi = mul_cases[k];
297                uint64_t y = ((uint64_t)y_hi << 32) | (uint64_t)y_lo;
298 
299                uint64_t d = x * y;
300 
301                ASSERT_EQ(sim->data[0], (uint32_t)d);
302                ASSERT_EQ(sim->data[1], (uint32_t)(d >> 32));
303             }
304          }
305       }
306    }
307 }
308 
TEST_F(mme_builder_test,sll_srl)309 TEST_F(mme_builder_test, sll_srl)
310 {
311    static const uint32_t x = 0xac406fe1;
312 
313    for (auto sim : sims) {
314       mme_builder b;
315       mme_builder_init(&b, sim->devinfo);
316 
317       mme_value xv = mme_load(&b);
318       mme_value yv = mme_load(&b);
319 
320       sim->mme_store_data(&b, 0, mme_sll(&b, xv, yv));
321       sim->mme_store_data(&b, 1, mme_srl(&b, xv, yv));
322       sim->mme_store_data(&b, 2, mme_sll(&b, mme_imm(x), yv));
323       sim->mme_store_data(&b, 3, mme_srl(&b, mme_imm(x), yv));
324 
325       auto macro = mme_builder_finish_vec(&b);
326 
327       /* Fermi can't shift by 0 */
328       for (uint32_t i = 1; i < 31; i++) {
329          std::vector<uint32_t> params;
330          params.push_back(x);
331          params.push_back(i);
332 
333          sim->run_macro(macro, params);
334          ASSERT_EQ(sim->data[0], x << i);
335          ASSERT_EQ(sim->data[1], x >> i);
336          ASSERT_EQ(sim->data[2], x << i);
337          ASSERT_EQ(sim->data[3], x >> i);
338       }
339    }
340 }
341 
TEST_F(mme_builder_test,not)342 TEST_F(mme_builder_test, not)
343 {
344    static const uint32_t x = 0xac406fe1;
345 
346    for (auto sim : sims) {
347       mme_builder b;
348       mme_builder_init(&b, sim->devinfo);
349 
350       mme_value xv = mme_load(&b);
351 
352       sim->mme_store_data(&b, 0, mme_not(&b, xv));
353 
354       auto macro = mme_builder_finish_vec(&b);
355 
356       /* Fermi can't shift by 0 */
357       for (uint32_t i = 1; i < 31; i++) {
358          std::vector<uint32_t> params;
359          params.push_back(x);
360 
361          sim->run_macro(macro, params);
362          ASSERT_EQ(sim->data[0], ~x);
363       }
364    }
365 }
366 
TEST_F(mme_builder_test,and_not)367 TEST_F(mme_builder_test, and_not)
368 {
369    static const uint32_t x = 0xac406fe1;
370    static const uint32_t y = 0x00fff0c0;
371 
372    for (auto sim : sims) {
373       mme_builder b;
374       mme_builder_init(&b, sim->devinfo);
375 
376       mme_value xv = mme_load(&b);
377       mme_value yv = mme_load(&b);
378 
379       sim->mme_store_data(&b, 0, mme_and(&b, xv, yv));
380       sim->mme_store_data(&b, 1, mme_and_not(&b, xv, yv));
381 
382       auto macro = mme_builder_finish_vec(&b);
383 
384       /* Fermi can't shift by 0 */
385       for (uint32_t i = 1; i < 31; i++) {
386          std::vector<uint32_t> params;
387          params.push_back(x);
388          params.push_back(y);
389 
390          sim->run_macro(macro, params);
391          ASSERT_EQ(sim->data[0], x & y);
392          ASSERT_EQ(sim->data[1], x & ~y);
393       }
394    }
395 }
396 
TEST_F(mme_builder_test,merge)397 TEST_F(mme_builder_test, merge)
398 {
399    static const struct {
400       uint16_t dst_pos;
401       uint16_t bits;
402       uint16_t src_pos;
403    } cases[] = {
404       { 12, 12, 20 },
405       { 12, 8,  20 },
406       { 8,  12, 20 },
407       { 12, 16, 8 },
408       { 24, 12, 8 },
409    };
410 
411    static const uint32_t x = 0x0c406fe0;
412    static const uint32_t y = 0x76543210;
413 
414    for (uint32_t i = 0; i < ARRAY_SIZE(cases); i++) {
415       expected[i] = merge(x, y, cases[i].dst_pos,
416                           cases[i].bits, cases[i].src_pos);
417    }
418 
419    for (auto sim : sims) {
420       mme_builder b;
421       mme_builder_init(&b, sim->devinfo);
422 
423       mme_value xv = mme_load(&b);
424       mme_value yv = mme_load(&b);
425 
426       for (uint32_t i = 0; i < ARRAY_SIZE(cases); i++) {
427          mme_value mv = mme_merge(&b, xv, yv, cases[i].dst_pos,
428                                   cases[i].bits, cases[i].src_pos);
429          sim->mme_store_data(&b, i, mv, true);
430       }
431 
432       auto macro = mme_builder_finish_vec(&b);
433 
434       std::vector<uint32_t> params;
435       params.push_back(x);
436       params.push_back(y);
437 
438       sim->run_macro(macro, params);
439       ASSERT_SIM_DATA(sim);
440    }
441 }
442 
TEST_F(mme_builder_test,while_ine)443 TEST_F(mme_builder_test, while_ine)
444 {
445    static const uint32_t cases[] = { 1, 3, 5, 8 };
446 
447    for (auto sim : sims) {
448       mme_builder b;
449       mme_builder_init(&b, sim->devinfo);
450 
451       mme_value inc = mme_load(&b);
452       mme_value bound = mme_load(&b);
453 
454       mme_value x = mme_mov(&b, mme_zero());
455       mme_value y = mme_mov(&b, mme_zero());
456       mme_value z = mme_mov(&b, mme_zero());
457 
458       mme_value i = mme_mov(&b, mme_zero());
459       mme_while(&b, ine, i, bound) {
460          mme_add_to(&b, x, x, mme_imm(1));
461          mme_add_to(&b, y, y, mme_imm(2));
462          mme_add_to(&b, z, z, mme_imm(3));
463          mme_add_to(&b, i, i, inc);
464       }
465 
466       sim->mme_store_data(&b, 0, x);
467       sim->mme_store_data(&b, 1, y);
468       sim->mme_store_data(&b, 2, z);
469       sim->mme_store_data(&b, 3, i);
470 
471       auto macro = mme_builder_finish_vec(&b);
472 
473       for (unsigned i = 0; i < ARRAY_SIZE(cases); i++) {
474          const uint32_t inc = cases[i];
475          const uint32_t count = cases[ARRAY_SIZE(cases) - i - 1];
476          const uint32_t bound = inc * count;
477 
478          std::vector<uint32_t> params;
479          params.push_back(inc);
480          params.push_back(bound);
481 
482          expected[0] = count * 1;
483          expected[1] = count * 2;
484          expected[2] = count * 3;
485          expected[3] = count * inc;
486 
487          sim->run_macro(macro, params);
488          ASSERT_SIM_DATA(sim);
489       }
490    }
491 }
492