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