• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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       case 300: {
85          ralloc_asprintf_append(src, "mov(16) %s<1>F 0x%08xF /* %f */ { align1 1H };\n", reg, val.u, val.f);
86          break;
87       }
88       default:
89          unreachable("invalid gfx version");
90       }
91 
92    } else {
93       for (char *c = value; *c; c++)
94          *c = tolower(*c);
95       switch (ec->devinfo->verx10) {
96       case 90:
97       case 110:
98       case 120:
99       case 125: {
100          ralloc_asprintf_append(src, "mov(8) %s<1>UD %sUD { align1 1Q };\n", reg, value);
101          break;
102       }
103 
104       case 200:
105       case 300: {
106          ralloc_asprintf_append(src, "mov(16) %s<1>UD %sUD { align1 1H };\n", reg, value);
107          break;
108       }
109 
110       default:
111          unreachable("invalid gfx version");
112       }
113    }
114 }
115 
116 static void
executor_macro_syncnop(executor_context * ec,char ** src,char * line)117 executor_macro_syncnop(executor_context *ec, char **src, char *line)
118 {
119    switch (ec->devinfo->verx10) {
120    case 90:
121    case 110: {
122       /* Not needed. */
123       break;
124    }
125 
126    case 120: {
127       ralloc_strcat(src, "sync nop(8)  null<0,1,0>UD  { align1 WE_all 1H @1 $1.dst };\n");
128       break;
129    }
130 
131    case 125:
132    case 200:
133    case 300: {
134       ralloc_strcat(src, "sync nop(8)  null<0,1,0>UD  { align1 WE_all 1H A@1 $1.dst };\n");
135       break;
136    }
137 
138    default:
139       unreachable("invalid gfx version");
140    }
141 }
142 
143 static void
executor_macro_eot(executor_context * ec,char ** src,char * line)144 executor_macro_eot(executor_context *ec, char **src, char *line)
145 {
146    switch (ec->devinfo->verx10) {
147    case 90:
148    case 110: {
149       ralloc_strcat(src,
150          "mov(8)          g127<1>UD  g0<8;8,1>UD    { align1 WE_all 1Q };\n"
151          "send(8)         null<1>UW  g127<0,1,0>UD  0x82000010\n"
152          "    thread_spawner MsgDesc: mlen 1 rlen 0 { align1 WE_all 1Q EOT };\n");
153       break;
154    }
155    case 120: {
156       ralloc_strcat(src,
157          "mov(8)          g127<1>UD  g0<8;8,1>UD  { align1 WE_all 1Q };\n"
158          "send(8)         nullUD     g127UD       nullUD  0x02000000  0x00000000\n"
159          "    thread_spawner MsgDesc:  mlen 1 ex_mlen 0 rlen 0 { align1 WE_all 1Q @1 EOT };\n");
160       break;
161    }
162 
163    case 125: {
164       ralloc_strcat(src,
165          "mov(8)         g127<1>UD  g0<8;8,1>UD  { align1 WE_all 1Q };\n"
166          "send(8)        nullUD     g127UD       nullUD  0x02000000  0x00000000\n"
167          "    gateway MsgDesc: (open)  mlen 1 ex_mlen 0 rlen 0 { align1 WE_all 1Q A@1 EOT };\n");
168          break;
169    }
170 
171    case 200:
172    case 300: {
173       ralloc_strcat(src,
174          "mov(16)         g127<1>UD  g0<1,1,0>UD  { align1 WE_all 1H };\n"
175          "send(16)        nullUD     g127UD       nullUD  0x02000000  0x00000000\n"
176          "    gateway MsgDesc: (open)  mlen 1 ex_mlen 0 rlen 0 { align1 WE_all 1H I@1 EOT };\n");
177          break;
178    }
179    default:
180       unreachable("invalid gfx version");
181    }
182 }
183 
184 static void
executor_macro_id(executor_context * ec,char ** src,char * line)185 executor_macro_id(executor_context *ec, char **src, char *line)
186 {
187    char *c = skip_prefix("@id", line);
188    parse_args_result r = parse_args(ec->mem_ctx, c);
189 
190    if (r.count != 1)
191       failf("@id needs 1 argument, found %d\n", r.count);
192 
193    const char *reg = r.args[0];
194 
195    switch (ec->devinfo->verx10) {
196    case 90:
197    case 110:
198    case 120:
199    case 125: {
200       ralloc_asprintf_append(src,
201          "mov(8)  g127<1>UW  0x76543210V    { align1 WE_all 1Q };\n"
202          "mov(8)  %s<1>UD    g127<8,8,1>UW  { align1 WE_all 1Q @1 };\n", reg);
203       break;
204    }
205 
206    case 200:
207    case 300: {
208       ralloc_asprintf_append(src,
209          "mov(8)  g127<1>UW    0x76543210V         { align1 WE_all 1Q };\n"
210          "add(8)  g127.8<1>UW  g127<1,1,0>UW  8UW  { align1 WE_all 1Q @1 };\n"
211          "mov(16) %s<1>UD      g127<8,8,1>UW       { align1 WE_all 1Q @1 };\n", reg);
212       break;
213    }
214 
215    default:
216       unreachable("invalid gfx version");
217    }
218 }
219 
220 static void
executor_macro_write(executor_context * ec,char ** src,char * line)221 executor_macro_write(executor_context *ec, char **src, char *line)
222 {
223    char *c = skip_prefix("@write", line);
224    parse_args_result r = parse_args(ec->mem_ctx, c);
225 
226    if (r.count != 2)
227       failf("@write needs 2 arguments, found %d\n", r.count);
228 
229    const char *offset_reg = r.args[0];
230    const char *data_reg   = r.args[1];
231 
232    assert(ec->bo.data.addr <= 0xFFFFFFFF);
233    uint32_t base_addr = ec->bo.data.addr;
234 
235    switch (ec->devinfo->verx10) {
236    case 90:
237    case 110:
238    case 120: {
239       const char *send_suffix = ec->devinfo->verx10 < 120 ? "s" : "";
240       ralloc_asprintf_append(src,
241          "mul(8)          g127<1>UD  %s<8;8,1>UD    0x4UW     { align1 @1 1Q };\n"
242          "add(8)          g127<1>UD  g127<8;8,1>UD  0x%08xUD  { align1 @1 1Q };\n"
243          "send%s(8)       nullUD     g127UD         %sUD      0x2026efd   0x00000040\n"
244          "    dp data 1 MsgDesc: (DC untyped surface write, Surface = 253, "
245          "                        SIMD8, Mask = 0xe) mlen 1 ex_mlen 1 rlen 0 "
246          "    { align1 1Q @1 $1 };\n",
247          offset_reg, base_addr, send_suffix, data_reg);
248       executor_macro_syncnop(ec, src, "@syncnop");
249       break;
250    }
251 
252    case 125: {
253       ralloc_asprintf_append(src,
254          "mul(8)          g127<1>UD  %s<1;1,0>UD    0x4UW     { align1 @1 1Q };\n"
255          "add(8)          g127<1>UD  g127<1;1,0>UD  0x%08xUD  { align1 @1 1Q };\n"
256          "send(8)         nullUD     g127UD         %sUD      0x02000504 0x00000040\n"
257          "    ugm MsgDesc: ( store, a32, d32, x, L1STATE_L3MOCS dst_len = 0, "
258          "                   src0_len = 1, src1_len = 1, flat )  base_offset 0 "
259          "    { align1 1Q A@1 $1 };\n",
260          offset_reg, base_addr, data_reg);
261       executor_macro_syncnop(ec, src, "@syncnop");
262       break;
263    }
264 
265    case 200:
266    case 300: {
267       ralloc_asprintf_append(src,
268          "mul(16)          g127<1>UD  %s<1;1,0>UD    0x4UW     { align1 @1 1Q };\n"
269          "add(16)          g127<1>UD  g127<1;1,0>UD  0x%08xUD  { align1 @1 1Q };\n"
270          "send(16)         nullUD     g127UD         %sUD      0x02000504 0x00000040\n"
271          "    ugm MsgDesc: ( store, a32, d32, x, L1STATE_L3MOCS dst_len = 0, "
272          "                   src0_len = 1, src1_len = 1, flat ) base_offset 0  "
273          "    { align1 1Q A@1 $1 };\n",
274          offset_reg, base_addr, data_reg);
275       executor_macro_syncnop(ec, src, "@syncnop");
276       break;
277    }
278 
279    default:
280       unreachable("invalid gfx version");
281    }
282 }
283 
284 static void
executor_macro_read(executor_context * ec,char ** src,char * line)285 executor_macro_read(executor_context *ec, char **src, char *line)
286 {
287    char *c = skip_prefix("@read", line);
288    parse_args_result r = parse_args(ec->mem_ctx, c);
289 
290    if (r.count != 2)
291       failf("@read needs 2 arguments, found %d\n", r.count);
292 
293    /* Order follows underlying SEND, destination first. */
294    const char *data_reg   = r.args[0];
295    const char *offset_reg = r.args[1];
296 
297    assert(ec->bo.data.addr <= 0xFFFFFFFF);
298    uint32_t base_addr = ec->bo.data.addr;
299 
300    switch (ec->devinfo->verx10) {
301    case 90:
302    case 110:
303    case 120: {
304       const char *send_suffix = ec->devinfo->verx10 < 120 ? "s" : "";
305       ralloc_asprintf_append(src,
306          "mul(8)          g127<1>UD  %s<8;8,1>UD    0x4UW     { align1 @1 1Q };\n"
307          "add(8)          g127<1>UD  g127<8;8,1>UD  0x%08xUD  { align1 @1 1Q };\n"
308          "send%s(8)       %sUD       g127UD         nullUD    0x2106efd   0x00000000\n"
309          "    dp data 1 MsgDesc: (DC untyped surface read, Surface = 253, "
310          "                        SIMD8, Mask = 0xe) mlen 1 ex_mlen 0 rlen 1 "
311          "    { align1 1Q @1 $1 };\n",
312          offset_reg, base_addr, send_suffix, data_reg);
313       executor_macro_syncnop(ec, src, "@syncnop");
314       break;
315    }
316 
317    case 125: {
318       ralloc_asprintf_append(src,
319          "mul(8)          g127<1>UD  %s<1;1,0>UD    0x4UW     { align1 @1 1Q };\n"
320          "add(8)          g127<1>UD  g127<1;1,0>UD  0x%08xUD  { align1 @1 1Q };\n"
321          "send(8)         %sUD       g127UD         nullUD    0x02100500 0x00000000\n"
322          "    ugm MsgDesc: ( load, a32, d32, x, L1STATE_L3MOCS dst_len = 1, "
323          "                   src0_len = 1, flat ) src1_len = 0  base_offset 0 "
324          "    { align1 1Q A@1 $1 };\n",
325          offset_reg, base_addr, data_reg);
326       executor_macro_syncnop(ec, src, "@syncnop");
327       break;
328    }
329 
330    case 200:
331    case 300: {
332       ralloc_asprintf_append(src,
333          "mul(16)         g127<1>UD  %s<1;1,0>UD    0x4UW     { align1 @1 1Q };\n"
334          "add(16)         g127<1>UD  g127<1;1,0>UD  0x%08xUD  { align1 @1 1Q };\n"
335          "send(16)        %sUD       g127UD         nullUD    0x02100500 0x00000000\n"
336          "    ugm MsgDesc: ( load, a32, d32, x, L1STATE_L3MOCS dst_len = 1, "
337          "                   src0_len = 1, flat ) src1_len = 0  base_offset 0 "
338          "    { align1 1Q A@1 $1 };\n",
339          offset_reg, base_addr, data_reg);
340       executor_macro_syncnop(ec, src, "@syncnop");
341       break;
342    }
343 
344    default:
345       unreachable("invalid gfx version");
346    }
347 }
348 
349 static char *
find_macro_symbol(char * line)350 find_macro_symbol(char *line)
351 {
352    char *c = line;
353    while (isspace(*c)) c++;
354    return *c == '@' ? c : NULL;
355 }
356 
357 static bool
match_macro_name(const char * name,const char * line)358 match_macro_name(const char *name, const char *line)
359 {
360    if (!startswith(name, line))
361       return false;
362    line += strlen(name);
363    return !*line || isspace(*line);
364 }
365 
366 const char *
executor_apply_macros(executor_context * ec,const char * original_src)367 executor_apply_macros(executor_context *ec, const char *original_src)
368 {
369    char *scratch = ralloc_strdup(ec->mem_ctx, original_src);
370 
371    /* Create a ralloc'ed empty string so can call append to it later. */
372    char *src = ralloc_strdup(ec->mem_ctx, "");
373 
374    /* TODO: Create a @send macro for common combinations of MsgDesc. */
375    static const struct {
376       const char *name;
377       void (*func)(executor_context *ec, char **output, char *line);
378    } macros[] = {
379       { "@eot",      executor_macro_eot },
380       { "@mov",      executor_macro_mov },
381       { "@write",    executor_macro_write },
382       { "@read",     executor_macro_read },
383       { "@id",       executor_macro_id },
384       { "@syncnop",  executor_macro_syncnop },
385    };
386 
387    char *next = scratch;
388    while (next) {
389       char *line = next;
390       char *end = line;
391 
392       while (*end && *end != '\n') end++;
393       next = *end ? end + 1 : NULL;
394       *end = '\0';
395 
396       char *macro = find_macro_symbol(line);
397       if (!macro) {
398          ralloc_asprintf_append(&src, "%s\n", line);
399       } else {
400          bool found = false;
401          for (int i = 0; i < ARRAY_SIZE(macros); i++) {
402             if (match_macro_name(macros[i].name, macro)) {
403                macros[i].func(ec, &src, macro);
404                found = true;
405                break;
406             }
407          }
408          if (!found)
409             failf("unsupported macro line: %s", macro);
410       }
411    }
412 
413    return src;
414 }
415