• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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