34a49a01ba3c085101096a38c2f60462d481b605
2 * Copyright (C) 2013 Rob Clark <robdclark@gmail.com>
3 * Copyright (C) 2010-2011 Marcin KoĆcielnicki <koriakin@0x04.net>
4 * Copyright (C) 2010 Luca Barbieri <luca@luca-barbieri.com>
5 * Copyright (C) 2010 Marcin Slusarz <marcin.slusarz@gmail.com>
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:
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
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.
28 /* modified version of headergen which uses enums and inline fxns for
29 * type safety.. based on original headergen
47 struct rnndelem
**elems
= NULL
;
51 char **offsetfns
= NULL
;
63 struct fout
*fouts
= 0;
67 static bool no_asserts
= false;
69 static void seekcol (FILE *f
, int src
, int dst
) {
73 int n
= dst
/8 - src
/8;
85 static FILE *findfout (char *file
) {
87 for (i
= 0; i
< foutsnum
; i
++)
88 if (!strcmp(fouts
[i
].name
, file
))
91 fprintf (stderr
, "AIII, didn't open file %s.\n", file
);
97 static void printdef (char *name
, char *suf
, int type
, uint64_t val
, char *file
) {
98 FILE *dst
= findfout(file
);
101 fprintf (dst
, "#define %s__%s%n", name
, suf
, &len
);
103 fprintf (dst
, "#define %s%n", name
, &len
);
104 if (type
== 0 && val
> 0xffffffffull
)
105 seekcol (dst
, len
, startcol
-8);
107 seekcol (dst
, len
, startcol
);
110 if (val
> 0xffffffffull
)
111 fprintf (dst
, "0x%016"PRIx64
"ULL\n", val
);
113 fprintf (dst
, "0x%08"PRIx64
"\n", val
);
116 fprintf (dst
, "%"PRIu64
"\n", val
);
121 static void printvalue (struct rnnvalue
*val
, int shift
) {
122 if (val
->varinfo
.dead
)
125 printdef (val
->fullname
, 0, 0, val
->value
<< shift
, val
->file
);
128 static void printbitfield (struct rnnbitfield
*bf
, int shift
);
130 static void printtypeinfo (struct rnntypeinfo
*ti
, struct rnnbitfield
*bf
,
131 char *prefix
, char *file
) {
132 FILE *dst
= findfout(file
);
133 enum rnnttype intype
= ti
->type
;
134 char *typename
= NULL
;
135 uint32_t mask
= typeinfo_mask(ti
);
136 uint32_t width
= 1 + ti
->high
- ti
->low
;
138 /* for fixed point, input type (arg to fxn) is float: */
139 if ((ti
->type
== RNN_TTYPE_FIXED
) || (ti
->type
== RNN_TTYPE_UFIXED
))
140 intype
= RNN_TTYPE_FLOAT
;
142 /* for toplevel register (ie. not bitfield), only generate accessor
143 * fxn for special cases (float, shr, min/max, etc):
145 if (bf
|| ti
->shr
|| ti
->minvalid
|| ti
->maxvalid
|| ti
->alignvalid
||
146 ti
->radixvalid
|| (intype
== RNN_TTYPE_FLOAT
)) {
150 case RNN_TTYPE_A3XX_REGID
:
151 typename
= "uint32_t";
154 typename
= "int32_t";
156 case RNN_TTYPE_FLOAT
:
160 asprintf(&typename
, "enum %s", ti
->name
);
165 /* for boolean, just generate a #define flag.. rather than inline fxn */
166 if (bf
&& (intype
== RNN_TTYPE_BOOLEAN
)) {
167 printdef(bf
->fullname
, 0, 0, mask
, file
);
172 printdef(prefix
, "MASK", 0, mask
, file
);
173 printdef(prefix
, "SHIFT", 1, ti
->low
, file
);
175 fprintf(dst
, "static inline uint32_t %s(%s val)\n", prefix
, typename
);
178 if ((ti
->minvalid
|| ti
->maxvalid
|| ti
->alignvalid
) && !no_asserts
) {
179 fprintf(dst
, "\tassert(1");
181 fprintf(dst
, " && (val >= %lu)", ti
->min
);
183 fprintf(dst
, " && (val <= %lu)", ti
->max
);
185 fprintf(dst
, " && !(val %% %lu)", ti
->align
);
186 fprintf(dst
, ");\n");
189 if (ti
->shr
&& !no_asserts
) {
190 fprintf(dst
, "\tassert(!(val & 0x%x));\n", (1 << ti
->shr
) - 1);
193 fprintf(dst
, "\treturn ((");
195 if (ti
->type
== RNN_TTYPE_FIXED
) {
196 fprintf(dst
, "((int32_t)(val * %d.0))", (1 << ti
->radix
));
197 } else if (ti
->type
== RNN_TTYPE_UFIXED
) {
198 fprintf(dst
, "((uint32_t)(val * %d.0))", (1 << ti
->radix
));
199 } else if (ti
->type
== RNN_TTYPE_FLOAT
) {
201 fprintf(dst
, "fui(val)");
202 else if (width
== 16)
203 fprintf(dst
, "util_float_to_half(val)");
205 assert(!"invalid float size");
211 fprintf(dst
, " >> %d", ti
->shr
);
213 fprintf(dst
, ") << %s__SHIFT) & %s__MASK;\n", prefix
, prefix
);
216 if (intype
== RNN_TTYPE_ENUM
)
221 for (i
= 0; i
< ti
->valsnum
; i
++)
222 printvalue(ti
->vals
[i
], ti
->low
);
223 for (i
= 0; i
< ti
->bitfieldsnum
; i
++)
224 printbitfield(ti
->bitfields
[i
], ti
->low
);
227 static void printbitfield (struct rnnbitfield
*bf
, int shift
) {
228 if (bf
->varinfo
.dead
)
230 printtypeinfo (&bf
->typeinfo
, bf
, bf
->fullname
, bf
->file
);
233 static void printdelem (struct rnndelem
*elem
, uint64_t offset
) {
235 char *offsetfn
= NULL
;
237 if (elem
->varinfo
.dead
)
240 use_offset_fxn
= elem
->offsets
|| elem
->doffset
|| elem
->doffsets
;
241 assert((!!elem
->offsets
+ !!elem
->doffset
+ !!elem
->doffsets
) <= 1);
244 asprintf(&offsetfn
, "__offset_%s", elem
->name
);
246 if (elem
->length
!= 1) {
247 ADDARRAY(elems
, elem
);
248 ADDARRAY(offsetfns
, offsetfn
);
253 asprintf(®name
, "REG_%s", elem
->fullname
);
256 FILE *dst
= findfout(elem
->file
);
259 if (use_offset_fxn
) {
260 fprintf(dst
, "static inline uint32_t %s(", offsetfn
);
262 fprintf(dst
, "enum %s", elem
->index
->name
);
264 fprintf(dst
, "uint32_t");
265 fprintf(dst
, " idx)\n");
268 fprintf(dst
, "\treturn (%s) + (%#" PRIx64
"*idx);\n", elem
->doffset
, elem
->stride
);
270 int valuesnum
= elem
->doffsets
? elem
->doffsetsnum
: elem
->offsetsnum
;
272 fprintf(dst
, "\tswitch (idx) {\n");
273 for (i
= 0; i
< valuesnum
; i
++) {
274 struct rnnvalue
*val
= NULL
;
275 fprintf(dst
, "\t\tcase ");
278 for (j
= 0; j
< elem
->index
->valsnum
; j
++) {
279 if (elem
->index
->vals
[j
]->value
== i
) {
280 val
= elem
->index
->vals
[j
];
286 fprintf(dst
, "%s", val
->name
);
288 fprintf(dst
, "%d", i
);
291 fprintf(dst
, ": return 0x%08lx;\n", elem
->offsets
[i
]);
293 fprintf(dst
, ": return (%s);\n", elem
->doffsets
[i
]);
296 fprintf(dst
, "\t\tdefault: return INVALID_IDX(idx);\n");
297 fprintf(dst
, "\t}\n");
301 fprintf (dst
, "static inline uint32_t %s(", regname
);
302 for (i
= 0; i
< elemsnum
; i
++) {
306 fprintf(dst
, "enum %s ", elems
[i
]->index
->name
);
308 fprintf(dst
, "uint32_t ");
309 fprintf (dst
, "i%d%n", i
, &len
);
311 fprintf (dst
, ") { return ");
312 fprintf (dst
, "0x%08"PRIx64
"", offset
+ elem
->offset
);
313 for (i
= 0; i
< elemsnum
; i
++) {
315 fprintf(dst
, " + %s(i%d)", offsetfns
[i
], i
);
317 fprintf (dst
, " + %#" PRIx64
"*i%d", elems
[i
]->stride
, i
);
319 fprintf (dst
, "; }\n");
321 printdef (regname
, 0, 0, offset
+ elem
->offset
, elem
->file
);
326 printdef (elem->fullname, "ESIZE", 0, elem->stride, elem->file);
327 if (elem->length != 1)
328 printdef (elem->fullname, "LEN", 0, elem->length, elem->file);
330 printtypeinfo (&elem
->typeinfo
, NULL
, elem
->fullname
, elem
->file
);
332 fprintf (findfout(elem
->file
), "\n");
334 for (j
= 0; j
< elem
->subelemsnum
; j
++) {
335 printdelem(elem
->subelems
[j
], offset
+ elem
->offset
);
337 if (elem
->length
!= 1) {
344 static void print_file_info_(FILE *dst
, struct stat
* sb
, struct tm
* tm
)
347 strftime(timestr
, sizeof(timestr
), "%Y-%m-%d %H:%M:%S", tm
);
348 fprintf(dst
, "(%7Lu bytes, from %s)\n", (unsigned long long)sb
->st_size
, timestr
);
351 static void print_file_info(FILE *dst
, const char* file
)
356 gmtime_r(&sb
.st_mtime
, &tm
);
357 print_file_info_(dst
, &sb
, &tm
);
360 static void printhead(struct fout f
, struct rnndb
*db
) {
365 gmtime_r(&sb
.st_mtime
, &tm
);
366 fprintf (f
.file
, "#ifndef %s\n", f
.guard
);
367 fprintf (f
.file
, "#define %s\n", f
.guard
);
368 fprintf (f
.file
, "\n");
370 "/* Autogenerated file, DO NOT EDIT manually!\n"
372 "This file was generated by the rules-ng-ng headergen tool in this git repository:\n"
373 "http://github.com/freedreno/envytools/\n"
374 "git clone https://github.com/freedreno/envytools.git\n"
376 "The rules-ng-ng source files this header was generated from are:\n");
378 for(i
= 0; i
< db
->filesnum
; ++i
) {
379 unsigned len
= strlen(db
->files
[i
]);
383 for(i
= 0; i
< db
->filesnum
; ++i
) {
384 unsigned len
= strlen(db
->files
[i
]);
385 fprintf(f
.file
, "- %s%*s ", db
->files
[i
], maxlen
- len
, "");
386 print_file_info(f
.file
, db
->files
[i
]);
391 if(db
->copyright
.firstyear
&& db
->copyright
.firstyear
< (1900 + tm
.tm_year
))
392 fprintf(f
.file
, "%u-", db
->copyright
.firstyear
);
393 fprintf(f
.file
, "%u", 1900 + tm
.tm_year
);
394 if(db
->copyright
.authorsnum
) {
395 fprintf(f
.file
, " by the following authors:");
396 for(i
= 0; i
< db
->copyright
.authorsnum
; ++i
) {
397 fprintf(f
.file
, "\n- ");
398 if(db
->copyright
.authors
[i
]->name
)
399 fprintf(f
.file
, "%s", db
->copyright
.authors
[i
]->name
);
400 if(db
->copyright
.authors
[i
]->email
)
401 fprintf(f
.file
, " <%s>", db
->copyright
.authors
[i
]->email
);
402 if(db
->copyright
.authors
[i
]->nicknamesnum
) {
403 for(j
= 0; j
< db
->copyright
.authors
[i
]->nicknamesnum
; ++j
) {
404 fprintf(f
.file
, "%s%s", (j
? ", " : " ("), db
->copyright
.authors
[i
]->nicknames
[j
]);
406 fprintf(f
.file
, ")");
410 fprintf(f
.file
, "\n");
411 if(db
->copyright
.license
)
412 fprintf(f
.file
, "\n%s\n", db
->copyright
.license
);
413 fprintf(f
.file
, "*/\n\n\n");
416 int main(int argc
, char **argv
) {
422 fprintf(stderr
, "Usage:\n\theadergen database-file\n");
426 if ((argc
>= 3) && !strcmp(argv
[1], "--no-asserts")) {
435 rnn_parsefile (db
, file
);
437 for(i
= 0; i
< db
->filesnum
; ++i
) {
438 char *dstname
= malloc(strlen(db
->files
[i
]) + 3);
440 strcpy(dstname
, db
->files
[i
]);
441 strcat(dstname
, ".h");
442 struct fout f
= { db
->files
[i
], fopen(dstname
, "w") };
448 pretty
= strrchr(f
.name
, '/');
453 f
.guard
= strdup(pretty
);
454 for (j
= 0; j
< strlen(f
.guard
); j
++)
455 if (isalnum(f
.guard
[j
]))
456 f
.guard
[j
] = toupper(f
.guard
[j
]);
463 for (i
= 0; i
< db
->enumsnum
; i
++) {
466 for (j
= 0; j
< db
->enums
[i
]->valsnum
; j
++) {
468 dst
= findfout(db
->enums
[i
]->vals
[j
]->file
);
469 fprintf(dst
, "enum %s {\n", db
->enums
[i
]->name
);
471 if (0xffff0000 & db
->enums
[i
]->vals
[j
]->value
)
472 fprintf(dst
, "\t%s = 0x%08lx,\n", db
->enums
[i
]->vals
[j
]->name
,
473 db
->enums
[i
]->vals
[j
]->value
);
475 fprintf(dst
, "\t%s = %lu,\n", db
->enums
[i
]->vals
[j
]->name
,
476 db
->enums
[i
]->vals
[j
]->value
);
479 fprintf(dst
, "};\n\n");
482 for (i
= 0; i
< db
->bitsetsnum
; i
++) {
483 if (db
->bitsets
[i
]->isinline
)
486 for (j
= 0; j
< db
->bitsets
[i
]->bitfieldsnum
; j
++)
487 printbitfield (db
->bitsets
[i
]->bitfields
[j
], 0);
489 for (i
= 0; i
< db
->domainsnum
; i
++) {
490 if (db
->domains
[i
]->size
)
491 printdef (db
->domains
[i
]->fullname
, "SIZE", 0, db
->domains
[i
]->size
, db
->domains
[i
]->file
);
493 for (j
= 0; j
< db
->domains
[i
]->subelemsnum
; j
++) {
494 printdelem(db
->domains
[i
]->subelems
[j
], 0);
497 for(i
= 0; i
< foutsnum
; ++i
) {
498 fprintf (fouts
[i
].file
, "\n#endif /* %s */\n", fouts
[i
].guard
);