Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/freedreno/rnn/headergen2.c
4565 views
1
/*
2
* Copyright (C) 2013 Rob Clark <[email protected]>
3
* Copyright (C) 2010-2011 Marcin Koƛcielnicki <[email protected]>
4
* Copyright (C) 2010 Luca Barbieri <[email protected]>
5
* Copyright (C) 2010 Marcin Slusarz <[email protected]>
6
* All Rights Reserved.
7
*
8
* Permission is hereby granted, free of charge, to any person obtaining a
9
* copy of this software and associated documentation files (the "Software"),
10
* to deal in the Software without restriction, including without limitation
11
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
12
* and/or sell copies of the Software, and to permit persons to whom the
13
* Software is furnished to do so, subject to the following conditions:
14
*
15
* The above copyright notice and this permission notice (including the next
16
* paragraph) shall be included in all copies or substantial portions of the
17
* Software.
18
*
19
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25
* OTHER DEALINGS IN THE SOFTWARE.
26
*/
27
28
/* modified version of headergen which uses enums and inline fxns for
29
* type safety.. based on original headergen
30
*/
31
32
#include "rnn.h"
33
#include "util.h"
34
#include <stdbool.h>
35
#include <stdio.h>
36
#include <stdlib.h>
37
#include <inttypes.h>
38
#include <time.h>
39
#include <ctype.h>
40
#include <unistd.h>
41
#include <string.h>
42
#include <sys/stat.h>
43
#include <sys/wait.h>
44
#include <assert.h>
45
46
struct rnndelem **elems = NULL;
47
int elemsnum = 0;
48
int elemsmax = 0;
49
50
char **offsetfns = NULL;
51
int offsetfnsnum = 0;
52
int offsetfnsmax = 0;
53
54
int startcol = 64;
55
56
struct fout {
57
char *name;
58
FILE *file;
59
char *guard;
60
};
61
62
struct fout *fouts = 0;
63
int foutsnum = 0;
64
int foutsmax = 0;
65
66
static bool no_asserts = false;
67
68
static void seekcol (FILE *f, int src, int dst) {
69
if (dst <= src)
70
fprintf (f, "\t");
71
else {
72
int n = dst/8 - src/8;
73
if (n) {
74
while (n--)
75
fprintf (f, "\t");
76
n = dst&7;
77
} else
78
n = dst-src;
79
while (n--)
80
fprintf (f, " ");
81
}
82
}
83
84
static FILE *findfout (char *file) {
85
int i;
86
for (i = 0; i < foutsnum; i++)
87
if (!strcmp(fouts[i].name, file))
88
break;
89
if (i == foutsnum) {
90
fprintf (stderr, "AIII, didn't open file %s.\n", file);
91
exit(1);
92
}
93
return fouts[i].file;
94
}
95
96
static void printdef (char *name, char *suf, int type, uint64_t val, char *file) {
97
FILE *dst = findfout(file);
98
int len;
99
if (suf)
100
fprintf (dst, "#define %s__%s%n", name, suf, &len);
101
else
102
fprintf (dst, "#define %s%n", name, &len);
103
if (type == 0 && val > 0xffffffffull)
104
seekcol (dst, len, startcol-8);
105
else
106
seekcol (dst, len, startcol);
107
switch (type) {
108
case 0:
109
if (val > 0xffffffffull)
110
fprintf (dst, "0x%016"PRIx64"ULL\n", val);
111
else
112
fprintf (dst, "0x%08"PRIx64"\n", val);
113
break;
114
case 1:
115
fprintf (dst, "%"PRIu64"\n", val);
116
break;
117
}
118
}
119
120
static void printvalue (struct rnnvalue *val, int shift) {
121
if (val->varinfo.dead)
122
return;
123
if (val->valvalid)
124
printdef (val->fullname, 0, 0, val->value << shift, val->file);
125
}
126
127
static void printbitfield (struct rnnbitfield *bf, int shift);
128
129
static void printtypeinfo (struct rnntypeinfo *ti, struct rnnbitfield *bf,
130
char *prefix, char *file) {
131
FILE *dst = findfout(file);
132
enum rnnttype intype = ti->type;
133
char *typename = NULL;
134
uint32_t mask = typeinfo_mask(ti);
135
uint32_t width = 1 + ti->high - ti->low;
136
137
/* for fixed point, input type (arg to fxn) is float: */
138
if ((ti->type == RNN_TTYPE_FIXED) || (ti->type == RNN_TTYPE_UFIXED))
139
intype = RNN_TTYPE_FLOAT;
140
141
/* for toplevel register (ie. not bitfield), only generate accessor
142
* fxn for special cases (float, shr, min/max, etc):
143
*/
144
if (bf || ti->shr || ti->minvalid || ti->maxvalid || ti->alignvalid ||
145
ti->radixvalid || (intype == RNN_TTYPE_FLOAT)) {
146
switch (intype) {
147
case RNN_TTYPE_HEX:
148
case RNN_TTYPE_UINT:
149
case RNN_TTYPE_A3XX_REGID:
150
typename = "uint32_t";
151
break;
152
case RNN_TTYPE_INT:
153
typename = "int32_t";
154
break;
155
case RNN_TTYPE_FLOAT:
156
typename = "float";
157
break;
158
case RNN_TTYPE_ENUM:
159
asprintf(&typename, "enum %s", ti->name);
160
break;
161
default:
162
break;
163
}
164
}
165
166
/* for boolean, just generate a #define flag.. rather than inline fxn */
167
if (bf && (intype == RNN_TTYPE_BOOLEAN)) {
168
printdef(bf->fullname, 0, 0, mask, file);
169
return;
170
}
171
172
if (typename) {
173
printdef(prefix, "MASK", 0, mask, file);
174
printdef(prefix, "SHIFT", 1, ti->low, file);
175
176
fprintf(dst, "static inline uint32_t %s(%s val)\n", prefix, typename);
177
fprintf(dst, "{\n");
178
179
if ((ti->minvalid || ti->maxvalid || ti->alignvalid) && !no_asserts) {
180
fprintf(dst, "\tassert(1");
181
if (ti->minvalid)
182
fprintf(dst, " && (val >= %"PRIu64")", ti->min);
183
if (ti->maxvalid)
184
fprintf(dst, " && (val <= %"PRIu64")", ti->max);
185
if (ti->alignvalid)
186
fprintf(dst, " && !(val %% %"PRIu64")", ti->align);
187
fprintf(dst, ");\n");
188
}
189
190
if (ti->shr && !no_asserts) {
191
fprintf(dst, "\tassert(!(val & 0x%x));\n", (1 << ti->shr) - 1);
192
}
193
194
fprintf(dst, "\treturn ((");
195
196
if (ti->type == RNN_TTYPE_FIXED) {
197
fprintf(dst, "((int32_t)(val * %d.0))", (1 << ti->radix));
198
} else if (ti->type == RNN_TTYPE_UFIXED) {
199
fprintf(dst, "((uint32_t)(val * %d.0))", (1 << ti->radix));
200
} else if (ti->type == RNN_TTYPE_FLOAT) {
201
if (width == 32)
202
fprintf(dst, "fui(val)");
203
else if (width == 16)
204
fprintf(dst, "_mesa_float_to_half(val)");
205
else
206
assert(!"invalid float size");
207
} else {
208
fprintf(dst, "val");
209
}
210
211
if (ti->shr)
212
fprintf(dst, " >> %d", ti->shr);
213
214
fprintf(dst, ") << %s__SHIFT) & %s__MASK;\n", prefix, prefix);
215
fprintf(dst, "}\n");
216
217
if (intype == RNN_TTYPE_ENUM)
218
free(typename);
219
}
220
221
int i;
222
for (i = 0; i < ti->valsnum; i++)
223
printvalue(ti->vals[i], ti->low);
224
for (i = 0; i < ti->bitfieldsnum; i++)
225
printbitfield(ti->bitfields[i], ti->low);
226
}
227
228
static void printbitfield (struct rnnbitfield *bf, int shift) {
229
if (bf->varinfo.dead)
230
return;
231
printtypeinfo (&bf->typeinfo, bf, bf->fullname, bf->file);
232
}
233
234
static void printdelem (struct rnndelem *elem, uint64_t offset, const char *str) {
235
int use_offset_fxn;
236
char *offsetfn = NULL;
237
238
if (elem->varinfo.dead)
239
return;
240
241
use_offset_fxn = elem->offsets || elem->doffset || elem->doffsets;
242
assert((!!elem->offsets + !!elem->doffset + !!elem->doffsets) <= 1);
243
244
if (use_offset_fxn)
245
asprintf(&offsetfn, "__offset_%s", elem->name);
246
247
if (elem->length != 1) {
248
ADDARRAY(elems, elem);
249
ADDARRAY(offsetfns, offsetfn);
250
}
251
252
if (elem->name) {
253
char *regname;
254
if (str) {
255
asprintf(&regname, "REG_%s_%s", elem->fullname, str);
256
} else {
257
asprintf(&regname, "REG_%s", elem->fullname);
258
}
259
if (elemsnum) {
260
int len;
261
FILE *dst = findfout(elem->file);
262
int i;
263
264
if (use_offset_fxn) {
265
fprintf(dst, "static inline uint32_t %s(", offsetfn);
266
if (elem->index)
267
fprintf(dst, "enum %s", elem->index->name);
268
else
269
fprintf(dst, "uint32_t");
270
fprintf(dst, " idx)\n");
271
fprintf(dst, "{\n");
272
if (elem->doffset) {
273
fprintf(dst, "\treturn (%s) + (%#" PRIx64 "*idx);\n", elem->doffset, elem->stride);
274
} else {
275
int valuesnum = elem->doffsets ? elem->doffsetsnum : elem->offsetsnum;
276
277
fprintf(dst, "\tswitch (idx) {\n");
278
for (i = 0; i < valuesnum; i++) {
279
struct rnnvalue *val = NULL;
280
fprintf(dst, "\t\tcase ");
281
if (elem->index) {
282
int j;
283
for (j = 0; j < elem->index->valsnum; j++) {
284
if (elem->index->vals[j]->value == i) {
285
val = elem->index->vals[j];
286
break;
287
}
288
}
289
}
290
if (val) {
291
fprintf(dst, "%s", val->name);
292
} else {
293
fprintf(dst, "%d", i);
294
}
295
if (elem->offsets) {
296
fprintf(dst, ": return 0x%08"PRIx64";\n", elem->offsets[i]);
297
} else {
298
fprintf(dst, ": return (%s);\n", elem->doffsets[i]);
299
}
300
}
301
fprintf(dst, "\t\tdefault: return INVALID_IDX(idx);\n");
302
fprintf(dst, "\t}\n");
303
}
304
fprintf(dst, "}\n");
305
}
306
fprintf (dst, "static inline uint32_t %s(", regname);
307
for (i = 0; i < elemsnum; i++) {
308
if (i)
309
fprintf(dst, ", ");
310
if (elems[i]->index)
311
fprintf(dst, "enum %s ", elems[i]->index->name);
312
else
313
fprintf(dst, "uint32_t ");
314
fprintf (dst, "i%d%n", i, &len);
315
}
316
fprintf (dst, ") { return ");
317
fprintf (dst, "0x%08"PRIx64"", offset + elem->offset);
318
for (i = 0; i < elemsnum; i++) {
319
if (offsetfns[i])
320
fprintf(dst, " + %s(i%d)", offsetfns[i], i);
321
else
322
fprintf (dst, " + %#" PRIx64 "*i%d", elems[i]->stride, i);
323
}
324
fprintf (dst, "; }\n");
325
} else
326
printdef (regname, 0, 0, offset + elem->offset, elem->file);
327
328
free(regname);
329
/*
330
if (elem->stride)
331
printdef (elem->fullname, "ESIZE", 0, elem->stride, elem->file);
332
if (elem->length != 1)
333
printdef (elem->fullname, "LEN", 0, elem->length, elem->file);
334
*/
335
printtypeinfo (&elem->typeinfo, NULL, elem->fullname, elem->file);
336
}
337
fprintf (findfout(elem->file), "\n");
338
int j;
339
for (j = 0; j < elem->subelemsnum; j++) {
340
printdelem(elem->subelems[j], offset + elem->offset, elem->varinfo.prefixstr);
341
}
342
if (elem->length != 1) {
343
elemsnum--;
344
offsetfnsnum--;
345
}
346
free(offsetfn);
347
}
348
349
static void print_file_info_(FILE *dst, struct stat* sb, struct tm* tm)
350
{
351
char timestr[64];
352
strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S", tm);
353
fprintf(dst, "(%7Lu bytes, from %s)\n", (unsigned long long)sb->st_size, timestr);
354
}
355
356
static void print_file_info(FILE *dst, const char* file)
357
{
358
struct stat sb;
359
struct tm tm;
360
stat(file, &sb);
361
gmtime_r(&sb.st_mtime, &tm);
362
print_file_info_(dst, &sb, &tm);
363
}
364
365
static void printhead(struct fout f, struct rnndb *db) {
366
int i, j;
367
struct stat sb;
368
struct tm tm;
369
stat(f.name, &sb);
370
gmtime_r(&sb.st_mtime, &tm);
371
fprintf (f.file, "#ifndef %s\n", f.guard);
372
fprintf (f.file, "#define %s\n", f.guard);
373
fprintf (f.file, "\n");
374
fprintf(f.file,
375
"/* Autogenerated file, DO NOT EDIT manually!\n"
376
"\n"
377
"This file was generated by the rules-ng-ng headergen tool in this git repository:\n"
378
"http://github.com/freedreno/envytools/\n"
379
"git clone https://github.com/freedreno/envytools.git\n"
380
"\n"
381
"The rules-ng-ng source files this header was generated from are:\n");
382
unsigned maxlen = 0;
383
for(i = 0; i < db->filesnum; ++i) {
384
unsigned len = strlen(db->files[i]);
385
if(len > maxlen)
386
maxlen = len;
387
}
388
for(i = 0; i < db->filesnum; ++i) {
389
unsigned len = strlen(db->files[i]);
390
fprintf(f.file, "- %s%*s ", db->files[i], maxlen - len, "");
391
print_file_info(f.file, db->files[i]);
392
}
393
fprintf(f.file,
394
"\n"
395
"Copyright (C) ");
396
if(db->copyright.firstyear && db->copyright.firstyear < (1900 + tm.tm_year))
397
fprintf(f.file, "%u-", db->copyright.firstyear);
398
fprintf(f.file, "%u", 1900 + tm.tm_year);
399
if(db->copyright.authorsnum) {
400
fprintf(f.file, " by the following authors:");
401
for(i = 0; i < db->copyright.authorsnum; ++i) {
402
fprintf(f.file, "\n- ");
403
if(db->copyright.authors[i]->name)
404
fprintf(f.file, "%s", db->copyright.authors[i]->name);
405
if(db->copyright.authors[i]->email)
406
fprintf(f.file, " <%s>", db->copyright.authors[i]->email);
407
if(db->copyright.authors[i]->nicknamesnum) {
408
for(j = 0; j < db->copyright.authors[i]->nicknamesnum; ++j) {
409
fprintf(f.file, "%s%s", (j ? ", " : " ("), db->copyright.authors[i]->nicknames[j]);
410
}
411
fprintf(f.file, ")");
412
}
413
}
414
}
415
fprintf(f.file, "\n");
416
if(db->copyright.license)
417
fprintf(f.file, "\n%s\n", db->copyright.license);
418
fprintf(f.file, "*/\n\n\n");
419
}
420
421
int main(int argc, char **argv) {
422
char *file;
423
struct rnndb *db;
424
int i, j;
425
426
if (argc < 2) {
427
fprintf(stderr, "Usage:\n\theadergen database-file\n");
428
exit(1);
429
}
430
431
if ((argc >= 3) && !strcmp(argv[1], "--no-asserts")) {
432
no_asserts = true;
433
file = argv[2];
434
} else {
435
file = argv[1];
436
}
437
438
rnn_init();
439
db = rnn_newdb();
440
rnn_parsefile (db, file);
441
rnn_prepdb (db);
442
for(i = 0; i < db->filesnum; ++i) {
443
char *dstname = malloc(strlen(db->files[i]) + 3);
444
char *pretty;
445
strcpy(dstname, db->files[i]);
446
strcat(dstname, ".h");
447
struct fout f = { db->files[i], fopen(dstname, "w") };
448
if (!f.file) {
449
perror(dstname);
450
exit(1);
451
}
452
free(dstname);
453
pretty = strrchr(f.name, '/');
454
if (pretty)
455
pretty += 1;
456
else
457
pretty = f.name;
458
f.guard = strdup(pretty);
459
for (j = 0; j < strlen(f.guard); j++)
460
if (isalnum(f.guard[j]))
461
f.guard[j] = toupper(f.guard[j]);
462
else
463
f.guard[j] = '_';
464
ADDARRAY(fouts, f);
465
printhead(f, db);
466
}
467
468
for (i = 0; i < db->enumsnum; i++) {
469
FILE *dst = NULL;
470
int j;
471
for (j = 0; j < db->enums[i]->valsnum; j++) {
472
if (!dst) {
473
dst = findfout(db->enums[i]->vals[j]->file);
474
fprintf(dst, "enum %s {\n", db->enums[i]->name);
475
}
476
if (0xffff0000 & db->enums[i]->vals[j]->value)
477
fprintf(dst, "\t%s = 0x%08"PRIx64",\n", db->enums[i]->vals[j]->name,
478
db->enums[i]->vals[j]->value);
479
else
480
fprintf(dst, "\t%s = %"PRIu64",\n", db->enums[i]->vals[j]->name,
481
db->enums[i]->vals[j]->value);
482
}
483
if (dst) {
484
fprintf(dst, "};\n\n");
485
}
486
}
487
for (i = 0; i < db->bitsetsnum; i++) {
488
if (db->bitsets[i]->isinline)
489
continue;
490
int j;
491
for (j = 0; j < db->bitsets[i]->bitfieldsnum; j++)
492
printbitfield (db->bitsets[i]->bitfields[j], 0);
493
}
494
for (i = 0; i < db->domainsnum; i++) {
495
if (db->domains[i]->size)
496
printdef (db->domains[i]->fullname, "SIZE", 0, db->domains[i]->size, db->domains[i]->file);
497
int j;
498
for (j = 0; j < db->domains[i]->subelemsnum; j++) {
499
printdelem(db->domains[i]->subelems[j], 0, NULL);
500
}
501
}
502
for(i = 0; i < foutsnum; ++i) {
503
fprintf (fouts[i].file, "\n#endif /* %s */\n", fouts[i].guard);
504
}
505
return db->estatus;
506
}
507
508