xref: /aosp_15_r20/external/mesa3d/src/intel/executor/executor_macros.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © 2024 Intel Corporation
3  * SPDX-License-Identifier: MIT
4  */
5 
6 #include <ctype.h>
7 
8 #include "util/ralloc.h"
9 #include "intel/compiler/brw_asm.h"
10 
11 #include "executor.h"
12 
13 static bool
startswith(const char * prefix,const char * s)14 startswith(const char *prefix, const char *s)
15 {
16    return !strncmp(prefix, s, strlen(prefix));
17 }
18 
19 static char *
skip_prefix(char * prefix,char * start)20 skip_prefix(char *prefix, char *start)
21 {
22    assert(startswith(prefix, start));
23    char *c = start += strlen(prefix);
24    return c;
25 }
26 
27 typedef struct {
28    char **args;
29    int    count;
30 } parse_args_result;
31 
32 static parse_args_result
parse_args(void * mem_ctx,char * c)33 parse_args(void *mem_ctx, char *c)
34 {
35    parse_args_result r = {0};
36 
37    while (*c) {
38       /* Skip spaces. */
39       while (*c && isspace(*c))
40          c++;
41       if (!*c)
42          break;
43 
44       /* Copy non-spaces. */
45       char *start = c;
46       while (*c && !isspace(*c))
47          c++;
48       r.args = reralloc_array_size(mem_ctx, r.args, sizeof(char *), r.count + 1);
49       r.args[r.count++] = ralloc_strndup(mem_ctx, start, c - start);
50    }
51 
52    return r;
53 }
54 
55 static void
executor_macro_mov(executor_context * ec,char ** src,char * line)56 executor_macro_mov(executor_context *ec, char **src, char *line)
57 {
58    char *c = skip_prefix("@mov", line);
59    parse_args_result r = parse_args(ec->mem_ctx, c);
60 
61    if (r.count != 2)
62       failf("@mov needs 2 arguments, found %d\n", r.count);
63 
64    const char *reg = r.args[0];
65    char *value     = r.args[1];
66 
67    if (strchr(value, '.')) {
68       union {
69          float f;
70          uint32_t u;
71       } val;
72 
73       val.f = strtof(value, NULL);
74 
75       switch (ec->devinfo->verx10) {
76       case 90:
77       case 110:
78       case 120:
79       case 125: {
80          ralloc_asprintf_append(src, "mov(8) %s<1>F 0x%08xF /* %f */ { align1 1Q };\n", reg, val.u, val.f);
81          break;
82       }
83       case 200: {
84          ralloc_asprintf_append(src, "mov(16) %s<1>F 0x%08xF /* %f */ { align1 1H };\n", reg, val.u, val.f);
85          break;
86       }
87       default:
88          unreachable("invalid gfx version");
89       }
90 
91    } else {
92       for (char *c = value; *c; c++)
93          *c = tolower(*c);
94       switch (ec->devinfo->verx10) {
95       case 90:
96       case 110:
97       case 120:
98       case 125: {
99          ralloc_asprintf_append(src, "mov(8) %s<1>UD %sUD { align1 1Q };\n", reg, value);
100          break;
101       }
102 
103       case 200: {
104          ralloc_asprintf_append(src, "mov(16) %s<1>UD %sUD { align1 1H };\n", reg, value);
105          break;
106       }
107 
108       default:
109          unreachable("invalid gfx version");
110       }
111    }
112 }
113 
114 static void
executor_macro_syncnop(executor_context * ec,char ** src,char * line)115 executor_macro_syncnop(executor_context *ec, char **src, char *line)
116 {
117    switch (ec->devinfo->verx10) {
118    case 90:
119    case 110: {
120       /* Not needed. */
121       break;
122    }
123 
124    case 120: {
125       ralloc_strcat(src, "sync nop(8)  null<0,1,0>UD  { align1 WE_all 1H @1 $1.dst };\n");
126       break;
127    }
128 
129    case 125:
130    case 200: {
131       ralloc_strcat(src, "sync nop(8)  null<0,1,0>UD  { align1 WE_all 1H A@1 $1.dst };\n");
132       break;
133    }
134 
135    default:
136       unreachable("invalid gfx version");
137    }
138 }
139 
140 static void
executor_macro_eot(executor_context * ec,char ** src,char * line)141 executor_macro_eot(executor_context *ec, char **src, char *line)
142 {
143    switch (ec->devinfo->verx10) {
144    case 90:
145    case 110: {
146       ralloc_strcat(src,
147          "mov(8)          g127<1>UD  g0<8;8,1>UD    { align1 WE_all 1Q };\n"
148          "send(8)         null<1>UW  g127<0,1,0>UD  0x82000010\n"
149          "    thread_spawner MsgDesc: mlen 1 rlen 0 { align1 WE_all 1Q EOT };\n");
150       break;
151    }
152    case 120: {
153       ralloc_strcat(src,
154          "mov(8)          g127<1>UD  g0<8;8,1>UD  { align1 WE_all 1Q };\n"
155          "send(8)         nullUD     g127UD       nullUD  0x02000000  0x00000000\n"
156          "    thread_spawner MsgDesc:  mlen 1 ex_mlen 0 rlen 0 { align1 WE_all 1Q @1 EOT };\n");
157       break;
158    }
159 
160    case 125: {
161       ralloc_strcat(src,
162          "mov(8)         g127<1>UD  g0<8;8,1>UD  { align1 WE_all 1Q };\n"
163          "send(8)        nullUD     g127UD       nullUD  0x02000000  0x00000000\n"
164          "    gateway MsgDesc: (open)  mlen 1 ex_mlen 0 rlen 0 { align1 WE_all 1Q A@1 EOT };\n");
165          break;
166    }
167 
168    case 200: {
169       ralloc_strcat(src,
170          "mov(16)         g127<1>UD  g0<1,1,0>UD  { align1 WE_all 1H };\n"
171          "send(16)        nullUD     g127UD       nullUD  0x02000000  0x00000000\n"
172          "    gateway MsgDesc: (open)  mlen 1 ex_mlen 0 rlen 0 { align1 WE_all 1H I@1 EOT };\n");
173          break;
174    }
175    default:
176       unreachable("invalid gfx version");
177    }
178 }
179 
180 static void
executor_macro_id(executor_context * ec,char ** src,char * line)181 executor_macro_id(executor_context *ec, char **src, char *line)
182 {
183    char *c = skip_prefix("@id", line);
184    parse_args_result r = parse_args(ec->mem_ctx, c);
185 
186    if (r.count != 1)
187       failf("@id needs 1 argument, found %d\n", r.count);
188 
189    const char *reg = r.args[0];
190 
191    switch (ec->devinfo->verx10) {
192    case 90:
193    case 110:
194    case 120:
195    case 125: {
196       ralloc_asprintf_append(src,
197          "mov(8)  g127<1>UW  0x76543210V    { align1 WE_all 1Q };\n"
198          "mov(8)  %s<1>UD    g127<8,8,1>UW  { align1 WE_all 1Q @1 };\n", reg);
199       break;
200    }
201 
202    case 200: {
203       ralloc_asprintf_append(src,
204          "mov(8)  g127<1>UW    0x76543210V         { align1 WE_all 1Q };\n"
205          "add(8)  g127.8<1>UW  g127<1,1,0>UW  8UW  { align1 WE_all 1Q @1 };\n"
206          "mov(16) %s<1>UD      g127<8,8,1>UW       { align1 WE_all 1Q @1 };\n", reg);
207       break;
208    }
209 
210    default:
211       unreachable("invalid gfx version");
212    }
213 }
214 
215 static void
executor_macro_write(executor_context * ec,char ** src,char * line)216 executor_macro_write(executor_context *ec, char **src, char *line)
217 {
218    char *c = skip_prefix("@write", line);
219    parse_args_result r = parse_args(ec->mem_ctx, c);
220 
221    if (r.count != 2)
222       failf("@write needs 2 arguments, found %d\n", r.count);
223 
224    const char *offset_reg = r.args[0];
225    const char *data_reg   = r.args[1];
226 
227    assert(ec->bo.data.addr <= 0xFFFFFFFF);
228    uint32_t base_addr = ec->bo.data.addr;
229 
230    switch (ec->devinfo->verx10) {
231    case 90:
232    case 110:
233    case 120: {
234       const char *send_suffix = ec->devinfo->verx10 < 120 ? "s" : "";
235       ralloc_asprintf_append(src,
236          "mul(8)          g127<1>UD  %s<8;8,1>UD    0x4UW     { align1 @1 1Q };\n"
237          "add(8)          g127<1>UD  g127<8;8,1>UD  0x%08xUD  { align1 @1 1Q };\n"
238          "send%s(8)       nullUD     g127UD         %sUD      0x2026efd   0x00000040\n"
239          "    dp data 1 MsgDesc: (DC untyped surface write, Surface = 253, "
240          "                        SIMD8, Mask = 0xe) mlen 1 ex_mlen 1 rlen 0 "
241          "    { align1 1Q @1 $1 };\n",
242          offset_reg, base_addr, send_suffix, data_reg);
243       executor_macro_syncnop(ec, src, "@syncnop");
244       break;
245    }
246 
247    case 125: {
248       ralloc_asprintf_append(src,
249          "mul(8)          g127<1>UD  %s<1;1,0>UD    0x4UW     { align1 @1 1Q };\n"
250          "add(8)          g127<1>UD  g127<1;1,0>UD  0x%08xUD  { align1 @1 1Q };\n"
251          "send(8)         nullUD     g127UD         %sUD      0x02000504 0x00000040\n"
252          "    ugm MsgDesc: ( store, a32, d32, x, L1STATE_L3MOCS dst_len = 0, "
253          "                   src0_len = 1, src1_len = 1, flat )  base_offset 0 "
254          "    { align1 1Q A@1 $1 };\n",
255          offset_reg, base_addr, data_reg);
256       executor_macro_syncnop(ec, src, "@syncnop");
257       break;
258    }
259 
260    case 200: {
261       ralloc_asprintf_append(src,
262          "mul(16)          g127<1>UD  %s<1;1,0>UD    0x4UW     { align1 @1 1Q };\n"
263          "add(16)          g127<1>UD  g127<1;1,0>UD  0x%08xUD  { align1 @1 1Q };\n"
264          "send(16)         nullUD     g127UD         %sUD      0x02000504 0x00000040\n"
265          "    ugm MsgDesc: ( store, a32, d32, x, L1STATE_L3MOCS dst_len = 0, "
266          "                   src0_len = 1, src1_len = 1, flat ) base_offset 0  "
267          "    { align1 1Q A@1 $1 };\n",
268          offset_reg, base_addr, data_reg);
269       executor_macro_syncnop(ec, src, "@syncnop");
270       break;
271    }
272 
273    default:
274       unreachable("invalid gfx version");
275    }
276 }
277 
278 static void
executor_macro_read(executor_context * ec,char ** src,char * line)279 executor_macro_read(executor_context *ec, char **src, char *line)
280 {
281    char *c = skip_prefix("@read", line);
282    parse_args_result r = parse_args(ec->mem_ctx, c);
283 
284    if (r.count != 2)
285       failf("@read needs 2 arguments, found %d\n", r.count);
286 
287    /* Order follows underlying SEND, destination first. */
288    const char *data_reg   = r.args[0];
289    const char *offset_reg = r.args[1];
290 
291    assert(ec->bo.data.addr <= 0xFFFFFFFF);
292    uint32_t base_addr = ec->bo.data.addr;
293 
294    switch (ec->devinfo->verx10) {
295    case 90:
296    case 110:
297    case 120: {
298       const char *send_suffix = ec->devinfo->verx10 < 120 ? "s" : "";
299       ralloc_asprintf_append(src,
300          "mul(8)          g127<1>UD  %s<8;8,1>UD    0x4UW     { align1 @1 1Q };\n"
301          "add(8)          g127<1>UD  g127<8;8,1>UD  0x%08xUD  { align1 @1 1Q };\n"
302          "send%s(8)       %sUD       g127UD         nullUD    0x2106efd   0x00000000\n"
303          "    dp data 1 MsgDesc: (DC untyped surface read, Surface = 253, "
304          "                        SIMD8, Mask = 0xe) mlen 1 ex_mlen 0 rlen 1 "
305          "    { align1 1Q @1 $1 };\n",
306          offset_reg, base_addr, send_suffix, data_reg);
307       executor_macro_syncnop(ec, src, "@syncnop");
308       break;
309    }
310 
311    case 125: {
312       ralloc_asprintf_append(src,
313          "mul(8)          g127<1>UD  %s<1;1,0>UD    0x4UW     { align1 @1 1Q };\n"
314          "add(8)          g127<1>UD  g127<1;1,0>UD  0x%08xUD  { align1 @1 1Q };\n"
315          "send(8)         %sUD       g127UD         nullUD    0x02100500 0x00000000\n"
316          "    ugm MsgDesc: ( load, a32, d32, x, L1STATE_L3MOCS dst_len = 1, "
317          "                   src0_len = 1, flat ) src1_len = 0  base_offset 0 "
318          "    { align1 1Q A@1 $1 };\n",
319          offset_reg, base_addr, data_reg);
320       executor_macro_syncnop(ec, src, "@syncnop");
321       break;
322    }
323 
324    case 200: {
325       ralloc_asprintf_append(src,
326          "mul(8)          g127<1>UD  %s<1;1,0>UD    0x4UW     { align1 @1 1Q };\n"
327          "add(8)          g127<1>UD  g127<1;1,0>UD  0x%08xUD  { align1 @1 1Q };\n"
328          "send(8)         %sUD       g127UD         nullUD    0x02100500 0x00000000\n"
329          "    ugm MsgDesc: ( load, a32, d32, x, L1STATE_L3MOCS dst_len = 1, "
330          "                   src0_len = 1, flat ) src1_len = 0  base_offset 0 "
331          "    { align1 1Q A@1 $1 };\n",
332          offset_reg, base_addr, data_reg);
333       executor_macro_syncnop(ec, src, "@syncnop");
334       break;
335    }
336 
337    default:
338       unreachable("invalid gfx version");
339    }
340 }
341 
342 static char *
find_macro_symbol(char * line)343 find_macro_symbol(char *line)
344 {
345    char *c = line;
346    while (isspace(*c)) c++;
347    return *c == '@' ? c : NULL;
348 }
349 
350 static bool
match_macro_name(const char * name,const char * line)351 match_macro_name(const char *name, const char *line)
352 {
353    if (!startswith(name, line))
354       return false;
355    line += strlen(name);
356    return !*line || isspace(*line);
357 }
358 
359 const char *
executor_apply_macros(executor_context * ec,const char * original_src)360 executor_apply_macros(executor_context *ec, const char *original_src)
361 {
362    char *scratch = ralloc_strdup(ec->mem_ctx, original_src);
363 
364    /* Create a ralloc'ed empty string so can call append to it later. */
365    char *src = ralloc_strdup(ec->mem_ctx, "");
366 
367    /* TODO: Create a @send macro for common combinations of MsgDesc. */
368    static const struct {
369       const char *name;
370       void (*func)(executor_context *ec, char **output, char *line);
371    } macros[] = {
372       { "@eot",      executor_macro_eot },
373       { "@mov",      executor_macro_mov },
374       { "@write",    executor_macro_write },
375       { "@read",     executor_macro_read },
376       { "@id",       executor_macro_id },
377       { "@syncnop",  executor_macro_syncnop },
378    };
379 
380    char *next = scratch;
381    while (next) {
382       char *line = next;
383       char *end = line;
384 
385       while (*end && *end != '\n') end++;
386       next = *end ? end + 1 : NULL;
387       *end = '\0';
388 
389       char *macro = find_macro_symbol(line);
390       if (!macro) {
391          ralloc_asprintf_append(&src, "%s\n", line);
392       } else {
393          bool found = false;
394          for (int i = 0; i < ARRAY_SIZE(macros); i++) {
395             if (match_macro_name(macros[i].name, macro)) {
396                macros[i].func(ec, &src, macro);
397                found = true;
398                break;
399             }
400          }
401          if (!found)
402             failf("unsupported macro line: %s", macro);
403       }
404    }
405 
406    return src;
407 }
408