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
46 struct rnndelem
**elems
= NULL
;
50 char **offsetfns
= NULL
;
62 struct fout
*fouts
= 0;
66 static bool no_asserts
= false;
68 static void seekcol (FILE *f
, int src
, int dst
) {
72 int n
= dst
/8 - src
/8;
84 static FILE *findfout (char *file
) {
86 for (i
= 0; i
< foutsnum
; i
++)
87 if (!strcmp(fouts
[i
].name
, file
))
90 fprintf (stderr
, "AIII, didn't open file %s.\n", file
);
96 static void printdef (char *name
, char *suf
, int type
, uint64_t val
, char *file
) {
97 FILE *dst
= findfout(file
);
100 fprintf (dst
, "#define %s__%s%n", name
, suf
, &len
);
102 fprintf (dst
, "#define %s%n", name
, &len
);
103 if (type
== 0 && val
> 0xffffffffull
)
104 seekcol (dst
, len
, startcol
-8);
106 seekcol (dst
, len
, startcol
);
109 if (val
> 0xffffffffull
)
110 fprintf (dst
, "0x%016"PRIx64
"ULL\n", val
);
112 fprintf (dst
, "0x%08"PRIx64
"\n", val
);
115 fprintf (dst
, "%"PRIu64
"\n", val
);
120 static void printvalue (struct rnnvalue
*val
, int shift
) {
121 if (val
->varinfo
.dead
)
124 printdef (val
->fullname
, 0, 0, val
->value
<< shift
, val
->file
);
127 static void printbitfield (struct rnnbitfield
*bf
, int shift
);
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
;
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
;
141 /* for toplevel register (ie. not bitfield), only generate accessor
142 * fxn for special cases (float, shr, min/max, etc):
144 if (bf
|| ti
->shr
|| ti
->minvalid
|| ti
->maxvalid
|| ti
->alignvalid
||
145 ti
->radixvalid
|| (intype
== RNN_TTYPE_FLOAT
)) {
149 case RNN_TTYPE_A3XX_REGID
:
150 typename
= "uint32_t";
153 typename
= "int32_t";
155 case RNN_TTYPE_FLOAT
:
159 asprintf(&typename
, "enum %s", ti
->name
);
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
);
173 printdef(prefix
, "MASK", 0, mask
, file
);
174 printdef(prefix
, "SHIFT", 1, ti
->low
, file
);
176 fprintf(dst
, "static inline uint32_t %s(%s val)\n", prefix
, typename
);
179 if ((ti
->minvalid
|| ti
->maxvalid
|| ti
->alignvalid
) && !no_asserts
) {
180 fprintf(dst
, "\tassert(1");
182 fprintf(dst
, " && (val >= %"PRIu64
")", ti
->min
);
184 fprintf(dst
, " && (val <= %"PRIu64
")", ti
->max
);
186 fprintf(dst
, " && !(val %% %"PRIu64
")", ti
->align
);
187 fprintf(dst
, ");\n");
190 if (ti
->shr
&& !no_asserts
) {
191 fprintf(dst
, "\tassert(!(val & 0x%x));\n", (1 << ti
->shr
) - 1);
194 fprintf(dst
, "\treturn ((");
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
) {
202 fprintf(dst
, "fui(val)");
203 else if (width
== 16)
204 fprintf(dst
, "util_float_to_half(val)");
206 assert(!"invalid float size");
212 fprintf(dst
, " >> %d", ti
->shr
);
214 fprintf(dst
, ") << %s__SHIFT) & %s__MASK;\n", prefix
, prefix
);
217 if (intype
== RNN_TTYPE_ENUM
)
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
);
228 static void printbitfield (struct rnnbitfield
*bf
, int shift
) {
229 if (bf
->varinfo
.dead
)
231 printtypeinfo (&bf
->typeinfo
, bf
, bf
->fullname
, bf
->file
);
234 static void printdelem (struct rnndelem
*elem
, uint64_t offset
) {
236 char *offsetfn
= NULL
;
238 if (elem
->varinfo
.dead
)
241 use_offset_fxn
= elem
->offsets
|| elem
->doffset
|| elem
->doffsets
;
242 assert((!!elem
->offsets
+ !!elem
->doffset
+ !!elem
->doffsets
) <= 1);
245 asprintf(&offsetfn
, "__offset_%s", elem
->name
);
247 if (elem
->length
!= 1) {
248 ADDARRAY(elems
, elem
);
249 ADDARRAY(offsetfns
, offsetfn
);
254 asprintf(®name
, "REG_%s", elem
->fullname
);
257 FILE *dst
= findfout(elem
->file
);
260 if (use_offset_fxn
) {
261 fprintf(dst
, "static inline uint32_t %s(", offsetfn
);
263 fprintf(dst
, "enum %s", elem
->index
->name
);
265 fprintf(dst
, "uint32_t");
266 fprintf(dst
, " idx)\n");
269 fprintf(dst
, "\treturn (%s) + (%#" PRIx64
"*idx);\n", elem
->doffset
, elem
->stride
);
271 int valuesnum
= elem
->doffsets
? elem
->doffsetsnum
: elem
->offsetsnum
;
273 fprintf(dst
, "\tswitch (idx) {\n");
274 for (i
= 0; i
< valuesnum
; i
++) {
275 struct rnnvalue
*val
= NULL
;
276 fprintf(dst
, "\t\tcase ");
279 for (j
= 0; j
< elem
->index
->valsnum
; j
++) {
280 if (elem
->index
->vals
[j
]->value
== i
) {
281 val
= elem
->index
->vals
[j
];
287 fprintf(dst
, "%s", val
->name
);
289 fprintf(dst
, "%d", i
);
292 fprintf(dst
, ": return 0x%08"PRIx64
";\n", elem
->offsets
[i
]);
294 fprintf(dst
, ": return (%s);\n", elem
->doffsets
[i
]);
297 fprintf(dst
, "\t\tdefault: return INVALID_IDX(idx);\n");
298 fprintf(dst
, "\t}\n");
302 fprintf (dst
, "static inline uint32_t %s(", regname
);
303 for (i
= 0; i
< elemsnum
; i
++) {
307 fprintf(dst
, "enum %s ", elems
[i
]->index
->name
);
309 fprintf(dst
, "uint32_t ");
310 fprintf (dst
, "i%d%n", i
, &len
);
312 fprintf (dst
, ") { return ");
313 fprintf (dst
, "0x%08"PRIx64
"", offset
+ elem
->offset
);
314 for (i
= 0; i
< elemsnum
; i
++) {
316 fprintf(dst
, " + %s(i%d)", offsetfns
[i
], i
);
318 fprintf (dst
, " + %#" PRIx64
"*i%d", elems
[i
]->stride
, i
);
320 fprintf (dst
, "; }\n");
322 printdef (regname
, 0, 0, offset
+ elem
->offset
, elem
->file
);
327 printdef (elem->fullname, "ESIZE", 0, elem->stride, elem->file);
328 if (elem->length != 1)
329 printdef (elem->fullname, "LEN", 0, elem->length, elem->file);
331 printtypeinfo (&elem
->typeinfo
, NULL
, elem
->fullname
, elem
->file
);
333 fprintf (findfout(elem
->file
), "\n");
335 for (j
= 0; j
< elem
->subelemsnum
; j
++) {
336 printdelem(elem
->subelems
[j
], offset
+ elem
->offset
);
338 if (elem
->length
!= 1) {
345 static void print_file_info_(FILE *dst
, struct stat
* sb
, struct tm
* tm
)
348 strftime(timestr
, sizeof(timestr
), "%Y-%m-%d %H:%M:%S", tm
);
349 fprintf(dst
, "(%7Lu bytes, from %s)\n", (unsigned long long)sb
->st_size
, timestr
);
352 static void print_file_info(FILE *dst
, const char* file
)
357 gmtime_r(&sb
.st_mtime
, &tm
);
358 print_file_info_(dst
, &sb
, &tm
);
361 static void printhead(struct fout f
, struct rnndb
*db
) {
366 gmtime_r(&sb
.st_mtime
, &tm
);
367 fprintf (f
.file
, "#ifndef %s\n", f
.guard
);
368 fprintf (f
.file
, "#define %s\n", f
.guard
);
369 fprintf (f
.file
, "\n");
371 "/* Autogenerated file, DO NOT EDIT manually!\n"
373 "This file was generated by the rules-ng-ng headergen tool in this git repository:\n"
374 "http://github.com/freedreno/envytools/\n"
375 "git clone https://github.com/freedreno/envytools.git\n"
377 "The rules-ng-ng source files this header was generated from are:\n");
379 for(i
= 0; i
< db
->filesnum
; ++i
) {
380 unsigned len
= strlen(db
->files
[i
]);
384 for(i
= 0; i
< db
->filesnum
; ++i
) {
385 unsigned len
= strlen(db
->files
[i
]);
386 fprintf(f
.file
, "- %s%*s ", db
->files
[i
], maxlen
- len
, "");
387 print_file_info(f
.file
, db
->files
[i
]);
392 if(db
->copyright
.firstyear
&& db
->copyright
.firstyear
< (1900 + tm
.tm_year
))
393 fprintf(f
.file
, "%u-", db
->copyright
.firstyear
);
394 fprintf(f
.file
, "%u", 1900 + tm
.tm_year
);
395 if(db
->copyright
.authorsnum
) {
396 fprintf(f
.file
, " by the following authors:");
397 for(i
= 0; i
< db
->copyright
.authorsnum
; ++i
) {
398 fprintf(f
.file
, "\n- ");
399 if(db
->copyright
.authors
[i
]->name
)
400 fprintf(f
.file
, "%s", db
->copyright
.authors
[i
]->name
);
401 if(db
->copyright
.authors
[i
]->email
)
402 fprintf(f
.file
, " <%s>", db
->copyright
.authors
[i
]->email
);
403 if(db
->copyright
.authors
[i
]->nicknamesnum
) {
404 for(j
= 0; j
< db
->copyright
.authors
[i
]->nicknamesnum
; ++j
) {
405 fprintf(f
.file
, "%s%s", (j
? ", " : " ("), db
->copyright
.authors
[i
]->nicknames
[j
]);
407 fprintf(f
.file
, ")");
411 fprintf(f
.file
, "\n");
412 if(db
->copyright
.license
)
413 fprintf(f
.file
, "\n%s\n", db
->copyright
.license
);
414 fprintf(f
.file
, "*/\n\n\n");
417 int main(int argc
, char **argv
) {
423 fprintf(stderr
, "Usage:\n\theadergen database-file\n");
427 if ((argc
>= 3) && !strcmp(argv
[1], "--no-asserts")) {
436 rnn_parsefile (db
, file
);
438 for(i
= 0; i
< db
->filesnum
; ++i
) {
439 char *dstname
= malloc(strlen(db
->files
[i
]) + 3);
441 strcpy(dstname
, db
->files
[i
]);
442 strcat(dstname
, ".h");
443 struct fout f
= { db
->files
[i
], fopen(dstname
, "w") };
449 pretty
= strrchr(f
.name
, '/');
454 f
.guard
= strdup(pretty
);
455 for (j
= 0; j
< strlen(f
.guard
); j
++)
456 if (isalnum(f
.guard
[j
]))
457 f
.guard
[j
] = toupper(f
.guard
[j
]);
464 for (i
= 0; i
< db
->enumsnum
; i
++) {
467 for (j
= 0; j
< db
->enums
[i
]->valsnum
; j
++) {
469 dst
= findfout(db
->enums
[i
]->vals
[j
]->file
);
470 fprintf(dst
, "enum %s {\n", db
->enums
[i
]->name
);
472 if (0xffff0000 & db
->enums
[i
]->vals
[j
]->value
)
473 fprintf(dst
, "\t%s = 0x%08"PRIx64
",\n", db
->enums
[i
]->vals
[j
]->name
,
474 db
->enums
[i
]->vals
[j
]->value
);
476 fprintf(dst
, "\t%s = %"PRIu64
",\n", db
->enums
[i
]->vals
[j
]->name
,
477 db
->enums
[i
]->vals
[j
]->value
);
480 fprintf(dst
, "};\n\n");
483 for (i
= 0; i
< db
->bitsetsnum
; i
++) {
484 if (db
->bitsets
[i
]->isinline
)
487 for (j
= 0; j
< db
->bitsets
[i
]->bitfieldsnum
; j
++)
488 printbitfield (db
->bitsets
[i
]->bitfields
[j
], 0);
490 for (i
= 0; i
< db
->domainsnum
; i
++) {
491 if (db
->domains
[i
]->size
)
492 printdef (db
->domains
[i
]->fullname
, "SIZE", 0, db
->domains
[i
]->size
, db
->domains
[i
]->file
);
494 for (j
= 0; j
< db
->domains
[i
]->subelemsnum
; j
++) {
495 printdelem(db
->domains
[i
]->subelems
[j
], 0);
498 for(i
= 0; i
< foutsnum
; ++i
) {
499 fprintf (fouts
[i
].file
, "\n#endif /* %s */\n", fouts
[i
].guard
);