freedreno: slurp in rnn

Signed-off-by: Rob Clark <robdclark@chromium.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6070>
This commit is contained in:
Rob Clark 2020-07-23 16:51:43 -07:00 committed by Marge Bot
parent b721d336da
commit 7c0bd8429f
13 changed files with 3055 additions and 0 deletions

View file

@ -28,6 +28,13 @@ subdir('fdl')
subdir('perfcntrs')
subdir('computerator')
dep_libxml2 = dependency('libxml-2.0', required: false)
# Everything that depends on rnn requires (indirectly) libxml2:
if dep_libxml2.found()
subdir('rnn')
endif
if with_tools.contains('drm-shim')
subdir('drm-shim')
endif

View file

@ -0,0 +1,38 @@
/*
* Copyright (C) 2009-2011 Marcin Kościelnicki <koriakin@0x04.net>
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include "util.h"
#include <stdarg.h>
char *aprintf(const char *format, ...) {
va_list va;
va_start(va, format);
size_t sz = vsnprintf(0, 0, format, va);
va_end(va);
char *res = malloc(sz + 1);
va_start(va, format);
vsnprintf(res, sz + 1, format, va);
va_end(va);
return res;
}

View file

@ -0,0 +1,61 @@
/*
* Copyright (C) 2012 Marcin Kościelnicki <koriakin@0x04.net>
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include "colors.h"
const struct envy_colors envy_null_colors = {
.reset = "",
.iname = "",
.rname = "",
.mod = "",
.sym = "",
.reg = "",
.regsp = "",
.num = "",
.mem = "",
.btarg = "",
.ctarg = "",
.bctarg = "",
.eval = "",
.comm = "",
.err = "",
};
const struct envy_colors envy_def_colors = {
.reset = "\x1b[0m",
.iname = "\x1b[0;32m",
.rname = "\x1b[0;32m",
.mod = "\x1b[0;36m",
.sym = "\x1b[0;36m",
.reg = "\x1b[0;31m",
.regsp = "\x1b[0;35m",
.num = "\x1b[0;33m",
.mem = "\x1b[0;35m",
.btarg = "\x1b[0;35m",
.ctarg = "\x1b[0;1;37m",
.bctarg = "\x1b[0;1;35m",
.eval = "\x1b[0;35m",
.comm = "\x1b[0;34m",
.err = "\x1b[0;1;31m",
};

View file

@ -0,0 +1,49 @@
/*
* Copyright (C) 2012 Marcin Kościelnicki <koriakin@0x04.net>
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef COLORS_H
#define COLORS_H
struct envy_colors {
const char *reset;
const char *iname; /* instruction name */
const char *rname; /* register or bitfield name */
const char *mod; /* instruction modifier */
const char *sym; /* auxiliary char like { , + */
const char *reg; /* ISA register */
const char *regsp; /* special ISA register */
const char *num; /* immediate number */
const char *mem; /* memory reference */
const char *btarg; /* branch target */
const char *ctarg; /* call target */
const char *bctarg; /* branch and call target */
const char *eval; /* enum value */
const char *comm; /* comment */
const char *err; /* error */
};
extern const struct envy_colors envy_null_colors;
extern const struct envy_colors envy_def_colors;
#endif

View file

@ -0,0 +1,501 @@
/*
* Copyright (C) 2013 Rob Clark <robdclark@gmail.com>
* Copyright (C) 2010-2011 Marcin Kościelnicki <koriakin@0x04.net>
* Copyright (C) 2010 Luca Barbieri <luca@luca-barbieri.com>
* Copyright (C) 2010 Marcin Slusarz <marcin.slusarz@gmail.com>
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
/* modified version of headergen which uses enums and inline fxns for
* type safety.. based on original headergen
*/
#define _GNU_SOURCE
#include "rnn.h"
#include "util.h"
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <time.h>
#include <ctype.h>
#include <unistd.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <assert.h>
struct rnndelem **elems = NULL;
int elemsnum = 0;
int elemsmax = 0;
char **offsetfns = NULL;
int offsetfnsnum = 0;
int offsetfnsmax = 0;
int startcol = 64;
struct fout {
char *name;
FILE *file;
char *guard;
};
struct fout *fouts = 0;
int foutsnum = 0;
int foutsmax = 0;
static bool no_asserts = false;
static void seekcol (FILE *f, int src, int dst) {
if (dst <= src)
fprintf (f, "\t");
else {
int n = dst/8 - src/8;
if (n) {
while (n--)
fprintf (f, "\t");
n = dst&7;
} else
n = dst-src;
while (n--)
fprintf (f, " ");
}
}
static FILE *findfout (char *file) {
int i;
for (i = 0; i < foutsnum; i++)
if (!strcmp(fouts[i].name, file))
break;
if (i == foutsnum) {
fprintf (stderr, "AIII, didn't open file %s.\n", file);
exit(1);
}
return fouts[i].file;
}
static void printdef (char *name, char *suf, int type, uint64_t val, char *file) {
FILE *dst = findfout(file);
int len;
if (suf)
fprintf (dst, "#define %s__%s%n", name, suf, &len);
else
fprintf (dst, "#define %s%n", name, &len);
if (type == 0 && val > 0xffffffffull)
seekcol (dst, len, startcol-8);
else
seekcol (dst, len, startcol);
switch (type) {
case 0:
if (val > 0xffffffffull)
fprintf (dst, "0x%016"PRIx64"ULL\n", val);
else
fprintf (dst, "0x%08"PRIx64"\n", val);
break;
case 1:
fprintf (dst, "%"PRIu64"\n", val);
break;
}
}
static void printvalue (struct rnnvalue *val, int shift) {
if (val->varinfo.dead)
return;
if (val->valvalid)
printdef (val->fullname, 0, 0, val->value << shift, val->file);
}
static void printbitfield (struct rnnbitfield *bf, int shift);
static void printtypeinfo (struct rnntypeinfo *ti, struct rnnbitfield *bf,
char *prefix, char *file) {
FILE *dst = findfout(file);
enum rnnttype intype = ti->type;
char *typename = NULL;
uint32_t mask = typeinfo_mask(ti);
uint32_t width = 1 + ti->high - ti->low;
/* for fixed point, input type (arg to fxn) is float: */
if ((ti->type == RNN_TTYPE_FIXED) || (ti->type == RNN_TTYPE_UFIXED))
intype = RNN_TTYPE_FLOAT;
/* for toplevel register (ie. not bitfield), only generate accessor
* fxn for special cases (float, shr, min/max, etc):
*/
if (bf || ti->shr || ti->minvalid || ti->maxvalid || ti->alignvalid ||
ti->radixvalid || (intype == RNN_TTYPE_FLOAT)) {
switch (intype) {
case RNN_TTYPE_HEX:
case RNN_TTYPE_UINT:
case RNN_TTYPE_A3XX_REGID:
typename = "uint32_t";
break;
case RNN_TTYPE_INT:
typename = "int32_t";
break;
case RNN_TTYPE_FLOAT:
typename = "float";
break;
case RNN_TTYPE_ENUM:
asprintf(&typename, "enum %s", ti->name);
break;
}
}
/* for boolean, just generate a #define flag.. rather than inline fxn */
if (bf && (intype == RNN_TTYPE_BOOLEAN)) {
printdef(bf->fullname, 0, 0, mask, file);
return;
}
if (typename) {
printdef(prefix, "MASK", 0, mask, file);
printdef(prefix, "SHIFT", 1, ti->low, file);
fprintf(dst, "static inline uint32_t %s(%s val)\n", prefix, typename);
fprintf(dst, "{\n");
if ((ti->minvalid || ti->maxvalid || ti->alignvalid) && !no_asserts) {
fprintf(dst, "\tassert(1");
if (ti->minvalid)
fprintf(dst, " && (val >= %lu)", ti->min);
if (ti->maxvalid)
fprintf(dst, " && (val <= %lu)", ti->max);
if (ti->alignvalid)
fprintf(dst, " && !(val %% %lu)", ti->align);
fprintf(dst, ");\n");
}
if (ti->shr && !no_asserts) {
fprintf(dst, "\tassert(!(val & 0x%x));\n", (1 << ti->shr) - 1);
}
fprintf(dst, "\treturn ((");
if (ti->type == RNN_TTYPE_FIXED) {
fprintf(dst, "((int32_t)(val * %d.0))", (1 << ti->radix));
} else if (ti->type == RNN_TTYPE_UFIXED) {
fprintf(dst, "((uint32_t)(val * %d.0))", (1 << ti->radix));
} else if (ti->type == RNN_TTYPE_FLOAT) {
if (width == 32)
fprintf(dst, "fui(val)");
else if (width == 16)
fprintf(dst, "util_float_to_half(val)");
else
assert(!"invalid float size");
} else {
fprintf(dst, "val");
}
if (ti->shr)
fprintf(dst, " >> %d", ti->shr);
fprintf(dst, ") << %s__SHIFT) & %s__MASK;\n", prefix, prefix);
fprintf(dst, "}\n");
if (intype == RNN_TTYPE_ENUM)
free(typename);
}
int i;
for (i = 0; i < ti->valsnum; i++)
printvalue(ti->vals[i], ti->low);
for (i = 0; i < ti->bitfieldsnum; i++)
printbitfield(ti->bitfields[i], ti->low);
}
static void printbitfield (struct rnnbitfield *bf, int shift) {
if (bf->varinfo.dead)
return;
printtypeinfo (&bf->typeinfo, bf, bf->fullname, bf->file);
}
static void printdelem (struct rnndelem *elem, uint64_t offset) {
int use_offset_fxn;
char *offsetfn = NULL;
if (elem->varinfo.dead)
return;
use_offset_fxn = elem->offsets || elem->doffset || elem->doffsets;
assert((!!elem->offsets + !!elem->doffset + !!elem->doffsets) <= 1);
if (use_offset_fxn)
asprintf(&offsetfn, "__offset_%s", elem->name);
if (elem->length != 1) {
ADDARRAY(elems, elem);
ADDARRAY(offsetfns, offsetfn);
}
if (elem->name) {
char *regname;
asprintf(&regname, "REG_%s", elem->fullname);
if (elemsnum) {
int len;
FILE *dst = findfout(elem->file);
int i;
if (use_offset_fxn) {
fprintf(dst, "static inline uint32_t %s(", offsetfn);
if (elem->index)
fprintf(dst, "enum %s", elem->index->name);
else
fprintf(dst, "uint32_t");
fprintf(dst, " idx)\n");
fprintf(dst, "{\n");
if (elem->doffset) {
fprintf(dst, "\treturn (%s) + (%#" PRIx64 "*idx);\n", elem->doffset, elem->stride);
} else {
int valuesnum = elem->doffsets ? elem->doffsetsnum : elem->offsetsnum;
fprintf(dst, "\tswitch (idx) {\n");
for (i = 0; i < valuesnum; i++) {
struct rnnvalue *val = NULL;
fprintf(dst, "\t\tcase ");
if (elem->index) {
int j;
for (j = 0; j < elem->index->valsnum; j++) {
if (elem->index->vals[j]->value == i) {
val = elem->index->vals[j];
break;
}
}
}
if (val) {
fprintf(dst, "%s", val->name);
} else {
fprintf(dst, "%d", i);
}
if (elem->offsets) {
fprintf(dst, ": return 0x%08lx;\n", elem->offsets[i]);
} else {
fprintf(dst, ": return (%s);\n", elem->doffsets[i]);
}
}
fprintf(dst, "\t\tdefault: return INVALID_IDX(idx);\n");
fprintf(dst, "\t}\n");
}
fprintf(dst, "}\n");
}
fprintf (dst, "static inline uint32_t %s(", regname);
for (i = 0; i < elemsnum; i++) {
if (i)
fprintf(dst, ", ");
if (elems[i]->index)
fprintf(dst, "enum %s ", elems[i]->index->name);
else
fprintf(dst, "uint32_t ");
fprintf (dst, "i%d%n", i, &len);
}
fprintf (dst, ") { return ");
fprintf (dst, "0x%08"PRIx64"", offset + elem->offset);
for (i = 0; i < elemsnum; i++) {
if (offsetfns[i])
fprintf(dst, " + %s(i%d)", offsetfns[i], i);
else
fprintf (dst, " + %#" PRIx64 "*i%d", elems[i]->stride, i);
}
fprintf (dst, "; }\n");
} else
printdef (regname, 0, 0, offset + elem->offset, elem->file);
free(regname);
/*
if (elem->stride)
printdef (elem->fullname, "ESIZE", 0, elem->stride, elem->file);
if (elem->length != 1)
printdef (elem->fullname, "LEN", 0, elem->length, elem->file);
*/
printtypeinfo (&elem->typeinfo, NULL, elem->fullname, elem->file);
}
fprintf (findfout(elem->file), "\n");
int j;
for (j = 0; j < elem->subelemsnum; j++) {
printdelem(elem->subelems[j], offset + elem->offset);
}
if (elem->length != 1) {
elemsnum--;
offsetfnsnum--;
}
free(offsetfn);
}
static void print_file_info_(FILE *dst, struct stat* sb, struct tm* tm)
{
char timestr[64];
strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S", tm);
fprintf(dst, "(%7Lu bytes, from %s)\n", (unsigned long long)sb->st_size, timestr);
}
static void print_file_info(FILE *dst, const char* file)
{
struct stat sb;
struct tm tm;
stat(file, &sb);
gmtime_r(&sb.st_mtime, &tm);
print_file_info_(dst, &sb, &tm);
}
static void printhead(struct fout f, struct rnndb *db) {
int i, j;
struct stat sb;
struct tm tm;
stat(f.name, &sb);
gmtime_r(&sb.st_mtime, &tm);
fprintf (f.file, "#ifndef %s\n", f.guard);
fprintf (f.file, "#define %s\n", f.guard);
fprintf (f.file, "\n");
fprintf(f.file,
"/* Autogenerated file, DO NOT EDIT manually!\n"
"\n"
"This file was generated by the rules-ng-ng headergen tool in this git repository:\n"
"http://github.com/freedreno/envytools/\n"
"git clone https://github.com/freedreno/envytools.git\n"
"\n"
"The rules-ng-ng source files this header was generated from are:\n");
unsigned maxlen = 0;
for(i = 0; i < db->filesnum; ++i) {
unsigned len = strlen(db->files[i]);
if(len > maxlen)
maxlen = len;
}
for(i = 0; i < db->filesnum; ++i) {
unsigned len = strlen(db->files[i]);
fprintf(f.file, "- %s%*s ", db->files[i], maxlen - len, "");
print_file_info(f.file, db->files[i]);
}
fprintf(f.file,
"\n"
"Copyright (C) ");
if(db->copyright.firstyear && db->copyright.firstyear < (1900 + tm.tm_year))
fprintf(f.file, "%u-", db->copyright.firstyear);
fprintf(f.file, "%u", 1900 + tm.tm_year);
if(db->copyright.authorsnum) {
fprintf(f.file, " by the following authors:");
for(i = 0; i < db->copyright.authorsnum; ++i) {
fprintf(f.file, "\n- ");
if(db->copyright.authors[i]->name)
fprintf(f.file, "%s", db->copyright.authors[i]->name);
if(db->copyright.authors[i]->email)
fprintf(f.file, " <%s>", db->copyright.authors[i]->email);
if(db->copyright.authors[i]->nicknamesnum) {
for(j = 0; j < db->copyright.authors[i]->nicknamesnum; ++j) {
fprintf(f.file, "%s%s", (j ? ", " : " ("), db->copyright.authors[i]->nicknames[j]);
}
fprintf(f.file, ")");
}
}
}
fprintf(f.file, "\n");
if(db->copyright.license)
fprintf(f.file, "\n%s\n", db->copyright.license);
fprintf(f.file, "*/\n\n\n");
}
int main(int argc, char **argv) {
char *file;
struct rnndb *db;
int i, j;
if (argc < 2) {
fprintf(stderr, "Usage:\n\theadergen database-file\n");
exit(1);
}
if ((argc >= 3) && !strcmp(argv[1], "--no-asserts")) {
no_asserts = true;
file = argv[2];
} else {
file = argv[1];
}
rnn_init();
db = rnn_newdb();
rnn_parsefile (db, file);
rnn_prepdb (db);
for(i = 0; i < db->filesnum; ++i) {
char *dstname = malloc(strlen(db->files[i]) + 3);
char *pretty;
strcpy(dstname, db->files[i]);
strcat(dstname, ".h");
struct fout f = { db->files[i], fopen(dstname, "w") };
if (!f.file) {
perror(dstname);
exit(1);
}
free(dstname);
pretty = strrchr(f.name, '/');
if (pretty)
pretty += 1;
else
pretty = f.name;
f.guard = strdup(pretty);
for (j = 0; j < strlen(f.guard); j++)
if (isalnum(f.guard[j]))
f.guard[j] = toupper(f.guard[j]);
else
f.guard[j] = '_';
ADDARRAY(fouts, f);
printhead(f, db);
}
for (i = 0; i < db->enumsnum; i++) {
FILE *dst = NULL;
int j;
for (j = 0; j < db->enums[i]->valsnum; j++) {
if (!dst) {
dst = findfout(db->enums[i]->vals[j]->file);
fprintf(dst, "enum %s {\n", db->enums[i]->name);
}
if (0xffff0000 & db->enums[i]->vals[j]->value)
fprintf(dst, "\t%s = 0x%08lx,\n", db->enums[i]->vals[j]->name,
db->enums[i]->vals[j]->value);
else
fprintf(dst, "\t%s = %lu,\n", db->enums[i]->vals[j]->name,
db->enums[i]->vals[j]->value);
}
if (dst) {
fprintf(dst, "};\n\n");
}
}
for (i = 0; i < db->bitsetsnum; i++) {
if (db->bitsets[i]->isinline)
continue;
int j;
for (j = 0; j < db->bitsets[i]->bitfieldsnum; j++)
printbitfield (db->bitsets[i]->bitfields[j], 0);
}
for (i = 0; i < db->domainsnum; i++) {
if (db->domains[i]->size)
printdef (db->domains[i]->fullname, "SIZE", 0, db->domains[i]->size, db->domains[i]->file);
int j;
for (j = 0; j < db->domains[i]->subelemsnum; j++) {
printdelem(db->domains[i]->subelems[j], 0);
}
}
for(i = 0; i < foutsnum; ++i) {
fprintf (fouts[i].file, "\n#endif /* %s */\n", fouts[i].guard);
}
return db->estatus;
}

View file

@ -0,0 +1,59 @@
# Copyright © 2020 Google, Inc
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
libfreedreno_rnn_files = files(
'aprintf.c',
'colors.c',
'colors.h',
'path.c',
'rnn.c',
'rnn.h',
'rnndec.c',
'rnndec.h',
'rnn_path.h',
'util.h',
)
libfreedreno_rnn = static_library(
'freedreno_rnn',
libfreedreno_rnn_files,
include_directories: [],
c_args : [
no_override_init_args,
'-DSOURCE_DIR="' + meson.source_root() + '"',
# TODO how do we get install prefix??
'-DINSTALL_DIR=""',
],
gnu_symbol_visibility: 'hidden',
dependencies: [ dep_libxml2 ],
build_by_default: false,
)
headergen2 = executable(
'headergen2',
'headergen2.c',
include_directories: [],
c_args : [no_override_init_args],
gnu_symbol_visibility: 'hidden',
dependencies: [],
link_with: libfreedreno_rnn,
build_by_default: with_tools.contains('freedreno'),
install: false
)

59
src/freedreno/rnn/path.c Normal file
View file

@ -0,0 +1,59 @@
/*
* Copyright (C) 2011 Marcin Kościelnicki <koriakin@0x04.net>
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include "util.h"
#include <string.h>
FILE *find_in_path(const char *name, const char *path, char **pfullname) {
if (!path)
return 0;
while (path) {
const char *npath = strchr(path, ':');
size_t plen;
if (npath) {
plen = npath - path;
npath++;
} else {
plen = strlen(path);
}
if (plen) {
char *fullname = malloc(strlen(name) + plen + 2);
strncpy(fullname, path, plen);
fullname[plen] = '/';
fullname[plen+1] = 0;
strcat(fullname, name);
FILE *file = fopen(fullname, "r");
if (file) {
if (pfullname)
*pfullname = fullname;
else
free(fullname);
return file;
}
free(fullname);
}
path = npath;
}
return 0;
}

1332
src/freedreno/rnn/rnn.c Normal file

File diff suppressed because it is too large Load diff

243
src/freedreno/rnn/rnn.h Normal file
View file

@ -0,0 +1,243 @@
/*
* Copyright (C) 2010 Marcin Kościelnicki <koriakin@0x04.net>
* Copyright (C) 2010 Luca Barbieri <luca@luca-barbieri.com>
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef RNN_H
#define RNN_H
#include <stdint.h>
#include <stdlib.h>
struct rnnauthor {
char* name;
char* email;
char* contributions;
char* license;
char** nicknames;
int nicknamesnum;
int nicknamesmax;
};
struct rnncopyright {
unsigned firstyear;
char* license;
struct rnnauthor **authors;
int authorsnum;
int authorsmax;
};
struct rnndb {
struct rnncopyright copyright;
struct rnnenum **enums;
int enumsnum;
int enumsmax;
struct rnnbitset **bitsets;
int bitsetsnum;
int bitsetsmax;
struct rnndomain **domains;
int domainsnum;
int domainsmax;
struct rnngroup **groups;
int groupsnum;
int groupsmax;
struct rnnspectype **spectypes;
int spectypesnum;
int spectypesmax;
char **files;
int filesnum;
int filesmax;
int estatus;
};
struct rnnvarset {
struct rnnenum *venum;
int *variants;
};
struct rnnvarinfo {
char *prefixstr;
char *varsetstr;
char *variantsstr;
int dead;
struct rnnenum *prefenum;
char *prefix;
struct rnnvarset **varsets;
int varsetsnum;
int varsetsmax;
};
struct rnnenum {
char *name;
int bare;
int isinline;
struct rnnvarinfo varinfo;
struct rnnvalue **vals;
int valsnum;
int valsmax;
char *fullname;
int prepared;
char *file;
};
struct rnnvalue {
char *name;
int valvalid;
uint64_t value;
struct rnnvarinfo varinfo;
char *fullname;
char *file;
};
struct rnntypeinfo {
char *name;
enum rnnttype {
RNN_TTYPE_INVALID,
RNN_TTYPE_INLINE_ENUM,
RNN_TTYPE_INLINE_BITSET,
RNN_TTYPE_ENUM,
RNN_TTYPE_BITSET,
RNN_TTYPE_SPECTYPE,
RNN_TTYPE_HEX,
RNN_TTYPE_INT,
RNN_TTYPE_UINT,
RNN_TTYPE_FLOAT,
RNN_TTYPE_BOOLEAN,
RNN_TTYPE_FIXED,
RNN_TTYPE_UFIXED,
RNN_TTYPE_A3XX_REGID,
} type;
struct rnnenum *eenum;
struct rnnbitset *ebitset;
struct rnnspectype *spectype;
struct rnnbitfield **bitfields;
int bitfieldsnum;
int bitfieldsmax;
struct rnnvalue **vals;
int valsnum;
int valsmax;
int shr, low, high;
uint64_t min, max, align, radix;
int addvariant;
int minvalid, maxvalid, alignvalid, radixvalid;
};
static inline uint64_t typeinfo_mask(struct rnntypeinfo *ti)
{
if (ti->high == 63)
return -(1ULL << ti->low);
else
return (1ULL << (ti->high + 1)) - (1ULL << ti->low);
}
struct rnnbitset {
char *name;
int bare;
int isinline;
struct rnnvarinfo varinfo;
struct rnnbitfield **bitfields;
int bitfieldsnum;
int bitfieldsmax;
char *fullname;
char *file;
};
struct rnnbitfield {
char *name;
struct rnnvarinfo varinfo;
struct rnntypeinfo typeinfo;
char *fullname;
char *file;
};
struct rnndomain {
char *name;
int bare;
int width;
uint64_t size;
int sizevalid;
struct rnnvarinfo varinfo;
struct rnndelem **subelems;
int subelemsnum;
int subelemsmax;
char *fullname;
char *file;
};
struct rnngroup {
char *name;
struct rnndelem **subelems;
int subelemsnum;
int subelemsmax;
};
struct rnndelem {
enum rnnetype {
RNN_ETYPE_REG,
RNN_ETYPE_ARRAY,
RNN_ETYPE_STRIPE,
RNN_ETYPE_USE_GROUP,
} type;
char *name;
int width;
enum rnnaccess {
RNN_ACCESS_R,
RNN_ACCESS_W,
RNN_ACCESS_RW,
} access;
uint64_t offset;
uint64_t *offsets; /* for "array" with irregular offsets */
int offsetsnum;
int offsetsmax;
char *doffset;
char **doffsets;
int doffsetsnum;
int doffsetsmax;
uint64_t length;
uint64_t stride;
struct rnndelem **subelems;
int subelemsnum;
int subelemsmax;
struct rnnvarinfo varinfo;
struct rnntypeinfo typeinfo;
struct rnnenum *index; /* for arrays, for symbolic idx values */
char *fullname;
char *file;
};
struct rnnspectype {
char *name;
struct rnntypeinfo typeinfo;
char *file;
};
void rnn_init(void);
struct rnndb *rnn_newdb(void);
void rnn_parsefile (struct rnndb *db, char *file);
void rnn_prepdb (struct rnndb *db);
struct rnnenum *rnn_findenum (struct rnndb *db, const char *name);
struct rnnbitset *rnn_findbitset (struct rnndb *db, const char *name);
struct rnndomain *rnn_finddomain (struct rnndb *db, const char *name);
struct rnnspectype *rnn_findspectype (struct rnndb *db, const char *name);
#endif

View file

@ -0,0 +1 @@
#define RNN_DEF_PATH SOURCE_DIR "/src/freedreno/registers:" INSTALL_DIR "share/mesa/freedreno/registers"

531
src/freedreno/rnn/rnndec.c Normal file
View file

@ -0,0 +1,531 @@
/*
* Copyright (C) 2010-2011 Marcin Kościelnicki <koriakin@0x04.net>
* Copyright (C) 2010 Francisco Jerez <currojerez@riseup.net>
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#define _GNU_SOURCE // for asprintf
#include "rnndec.h"
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <inttypes.h>
#include "util.h"
struct rnndeccontext *rnndec_newcontext(struct rnndb *db) {
struct rnndeccontext *res = calloc (sizeof *res, 1);
res->db = db;
res->colors = &envy_null_colors;
return res;
}
int rnndec_varadd(struct rnndeccontext *ctx, char *varset, char *variant) {
struct rnnenum *en = rnn_findenum(ctx->db, varset);
if (!en) {
fprintf (stderr, "Enum %s doesn't exist in database!\n", varset);
return 0;
}
int i, j;
for (i = 0; i < en->valsnum; i++)
if (!strcasecmp(en->vals[i]->name, variant)) {
struct rnndecvariant *ci = calloc (sizeof *ci, 1);
ci->en = en;
ci->variant = i;
ADDARRAY(ctx->vars, ci);
return 1;
}
if (i == en->valsnum) {
fprintf (stderr, "Variant %s doesn't exist in enum %s!\n", variant, varset);
return 0;
}
for (j = 0; j < ctx->varsnum; j++) {
if (ctx->vars[j]->en == en) {
ctx->vars[j]->variant = i;
break;
}
}
if (i == ctx->varsnum) {
struct rnndecvariant *ci = calloc (sizeof *ci, 1);
ci->en = en;
ci->variant = i;
ADDARRAY(ctx->vars, ci);
}
return 1;
}
int rnndec_varmatch(struct rnndeccontext *ctx, struct rnnvarinfo *vi) {
if (vi->dead)
return 0;
int i;
for (i = 0; i < vi->varsetsnum; i++) {
int j;
for (j = 0; j < ctx->varsnum; j++)
if (vi->varsets[i]->venum == ctx->vars[j]->en)
break;
if (j == ctx->varsnum) {
fprintf (stderr, "I don't know which %s variant to use!\n", vi->varsets[i]->venum->name);
} else {
if (!vi->varsets[i]->variants[ctx->vars[j]->variant])
return 0;
}
}
return 1;
}
/* see https://en.wikipedia.org/wiki/Half-precision_floating-point_format */
static uint32_t float16i(uint16_t val)
{
uint32_t sign = ((uint32_t)(val & 0x8000)) << 16;
uint32_t frac = val & 0x3ff;
int32_t expn = (val >> 10) & 0x1f;
if (expn == 0) {
if (frac) {
/* denormalized number: */
int shift = __builtin_clz(frac) - 21;
frac <<= shift;
expn = -shift;
} else {
/* +/- zero: */
return sign;
}
} else if (expn == 0x1f) {
/* Inf/NaN: */
return sign | 0x7f800000 | (frac << 13);
}
return sign | ((expn + 127 - 15) << 23) | (frac << 13);
}
static float float16(uint16_t val)
{
union { uint32_t i; float f; } u;
u.i = float16i(val);
return u.f;
}
static const char *rnndec_decode_enum_val(struct rnndeccontext *ctx,
struct rnnvalue **vals, int valsnum, uint64_t value)
{
int i;
for (i = 0; i < valsnum; i++)
if (rnndec_varmatch(ctx, &vals[i]->varinfo) &&
vals[i]->valvalid && vals[i]->value == value)
return vals[i]->name;
return NULL;
}
char *rnndec_decode_enum(struct rnndeccontext *ctx, const char *enumname, uint64_t enumval)
{
struct rnnenum *en = rnn_findenum (ctx->db, enumname);
if (en) {
int i;
for (i = 0; i < en->valsnum; i++)
if (en->vals[i]->valvalid && en->vals[i]->value == enumval)
return en->vals[i]->name;
}
return NULL;
}
/* The name UNK%u is used as a placeholder for bitfields that exist but
* have an unknown function.
*/
static int is_unknown(const char *name)
{
unsigned u;
return sscanf(name, "UNK%u", &u) == 1;
}
char *rnndec_decodeval(struct rnndeccontext *ctx, struct rnntypeinfo *ti, uint64_t value) {
int width = ti->high - ti->low + 1;
char *res = 0;
int i;
struct rnnvalue **vals;
int valsnum;
struct rnnbitfield **bitfields;
int bitfieldsnum;
char *tmp;
uint64_t mask, value_orig;
if (!ti)
goto failhex;
value_orig = value;
value = (value & typeinfo_mask(ti)) >> ti->low;
value <<= ti->shr;
switch (ti->type) {
case RNN_TTYPE_ENUM:
vals = ti->eenum->vals;
valsnum = ti->eenum->valsnum;
goto doenum;
case RNN_TTYPE_INLINE_ENUM:
vals = ti->vals;
valsnum = ti->valsnum;
goto doenum;
doenum:
tmp = rnndec_decode_enum_val(ctx, vals, valsnum, value);
if (tmp) {
asprintf (&res, "%s%s%s", ctx->colors->eval, tmp, ctx->colors->reset);
if (ti->addvariant) {
rnndec_varadd(ctx, ti->eenum->name, tmp);
}
break;
}
goto failhex;
case RNN_TTYPE_BITSET:
bitfields = ti->ebitset->bitfields;
bitfieldsnum = ti->ebitset->bitfieldsnum;
goto dobitset;
case RNN_TTYPE_INLINE_BITSET:
bitfields = ti->bitfields;
bitfieldsnum = ti->bitfieldsnum;
goto dobitset;
dobitset:
mask = 0;
for (i = 0; i < bitfieldsnum; i++) {
if (!rnndec_varmatch(ctx, &bitfields[i]->varinfo))
continue;
uint64_t type_mask = typeinfo_mask(&bitfields[i]->typeinfo);
if (((value & type_mask) == 0) && is_unknown(bitfields[i]->name))
continue;
mask |= type_mask;
if (bitfields[i]->typeinfo.type == RNN_TTYPE_BOOLEAN) {
const char *color = is_unknown(bitfields[i]->name) ?
ctx->colors->err : ctx->colors->mod;
if (value & type_mask) {
if (!res)
asprintf (&res, "%s%s%s", color, bitfields[i]->name, ctx->colors->reset);
else {
asprintf (&tmp, "%s | %s%s%s", res, color, bitfields[i]->name, ctx->colors->reset);
free(res);
res = tmp;
}
}
continue;
}
char *subval;
if (is_unknown(bitfields[i]->name) && (bitfields[i]->typeinfo.type != RNN_TTYPE_A3XX_REGID)) {
uint64_t field_val = value & type_mask;
field_val = (field_val & typeinfo_mask(&bitfields[i]->typeinfo)) >> bitfields[i]->typeinfo.low;
field_val <<= bitfields[i]->typeinfo.shr;
asprintf (&subval, "%s%#"PRIx64"%s", ctx->colors->err, field_val, ctx->colors->reset);
} else {
subval = rnndec_decodeval(ctx, &bitfields[i]->typeinfo, value & type_mask);
}
if (!res)
asprintf (&res, "%s%s%s = %s", ctx->colors->rname, bitfields[i]->name, ctx->colors->reset, subval);
else {
asprintf (&tmp, "%s | %s%s%s = %s", res, ctx->colors->rname, bitfields[i]->name, ctx->colors->reset, subval);
free(res);
res = tmp;
}
free(subval);
}
if (value & ~mask) {
if (!res)
asprintf (&res, "%s%#"PRIx64"%s", ctx->colors->err, value & ~mask, ctx->colors->reset);
else {
asprintf (&tmp, "%s | %s%#"PRIx64"%s", res, ctx->colors->err, value & ~mask, ctx->colors->reset);
free(res);
res = tmp;
}
}
if (!res)
asprintf (&res, "%s0%s", ctx->colors->num, ctx->colors->reset);
asprintf (&tmp, "{ %s }", res);
free(res);
return tmp;
case RNN_TTYPE_SPECTYPE:
return rnndec_decodeval(ctx, &ti->spectype->typeinfo, value);
case RNN_TTYPE_HEX:
asprintf (&res, "%s%#"PRIx64"%s", ctx->colors->num, value, ctx->colors->reset);
break;
case RNN_TTYPE_FIXED:
if (value & UINT64_C(1) << (width-1)) {
asprintf (&res, "%s-%lf%s", ctx->colors->num,
((double)((UINT64_C(1) << width) - value)) / ((double)(1 << ti->radix)),
ctx->colors->reset);
break;
}
/* fallthrough */
case RNN_TTYPE_UFIXED:
asprintf (&res, "%s%lf%s", ctx->colors->num,
((double)value) / ((double)(1LL << ti->radix)),
ctx->colors->reset);
break;
case RNN_TTYPE_A3XX_REGID:
asprintf (&res, "%sr%"PRIu64".%c%s", ctx->colors->num, (value >> 2), "xyzw"[value & 0x3], ctx->colors->reset);
break;
case RNN_TTYPE_UINT:
asprintf (&res, "%s%"PRIu64"%s", ctx->colors->num, value, ctx->colors->reset);
break;
case RNN_TTYPE_INT:
if (value & UINT64_C(1) << (width-1))
asprintf (&res, "%s-%"PRIi64"%s", ctx->colors->num, (UINT64_C(1) << width) - value, ctx->colors->reset);
else
asprintf (&res, "%s%"PRIi64"%s", ctx->colors->num, value, ctx->colors->reset);
break;
case RNN_TTYPE_BOOLEAN:
if (value == 0) {
asprintf (&res, "%sFALSE%s", ctx->colors->eval, ctx->colors->reset);
} else if (value == 1) {
asprintf (&res, "%sTRUE%s", ctx->colors->eval, ctx->colors->reset);
}
break;
case RNN_TTYPE_FLOAT: {
union { uint64_t i; float f; double d; } val;
val.i = value;
if (width == 64)
asprintf(&res, "%s%f%s", ctx->colors->num,
val.d, ctx->colors->reset);
else if (width == 32)
asprintf(&res, "%s%f%s", ctx->colors->num,
val.f, ctx->colors->reset);
else if (width == 16)
asprintf(&res, "%s%f%s", ctx->colors->num,
float16(value), ctx->colors->reset);
else
goto failhex;
break;
}
failhex:
default:
asprintf (&res, "%s%#"PRIx64"%s", ctx->colors->num, value, ctx->colors->reset);
break;
}
if (value_orig & ~typeinfo_mask(ti)) {
asprintf (&tmp, "%s | %s%#"PRIx64"%s", res, ctx->colors->err, value_orig & ~typeinfo_mask(ti), ctx->colors->reset);
free(res);
res = tmp;
}
return res;
}
static char *appendidx (struct rnndeccontext *ctx, char *name, uint64_t idx, struct rnnenum *index) {
char *res, *index_name = NULL;
if (index)
index_name = rnndec_decode_enum_val(ctx, index->vals, index->valsnum, idx);
if (index_name)
asprintf (&res, "%s[%s%s%s]", name, ctx->colors->eval, index_name, ctx->colors->reset);
else
asprintf (&res, "%s[%s%#"PRIx64"%s]", name, ctx->colors->num, idx, ctx->colors->reset);
free (name);
return res;
}
/* This could probably be made to work for stripes too.. */
static int get_array_idx_offset(struct rnndelem *elem, uint64_t addr, uint64_t *idx, uint64_t *offset)
{
if (elem->offsets) {
int i;
for (i = 0; i < elem->offsetsnum; i++) {
uint64_t o = elem->offsets[i];
if ((o <= addr) && (addr < (o + elem->stride))) {
*idx = i;
*offset = addr - o;
return 0;
}
}
return -1;
} else {
if (addr < elem->offset)
return -1;
*idx = (addr - elem->offset) / elem->stride;
*offset = (addr - elem->offset) % elem->stride;
if (elem->length && (*idx >= elem->length))
return -1;
return 0;
}
}
static struct rnndecaddrinfo *trymatch (struct rnndeccontext *ctx, struct rnndelem **elems, int elemsnum, uint64_t addr, int write, int dwidth, uint64_t *indices, int indicesnum) {
struct rnndecaddrinfo *res;
int i, j;
for (i = 0; i < elemsnum; i++) {
if (!rnndec_varmatch(ctx, &elems[i]->varinfo))
continue;
uint64_t offset, idx;
char *tmp, *name;
switch (elems[i]->type) {
case RNN_ETYPE_REG:
if (addr < elems[i]->offset)
break;
if (elems[i]->stride) {
idx = (addr-elems[i]->offset)/elems[i]->stride;
offset = (addr-elems[i]->offset)%elems[i]->stride;
} else {
idx = 0;
offset = addr-elems[i]->offset;
}
if (offset >= elems[i]->width/dwidth)
break;
if (elems[i]->length && idx >= elems[i]->length)
break;
res = calloc (sizeof *res, 1);
res->typeinfo = &elems[i]->typeinfo;
res->width = elems[i]->width;
asprintf (&res->name, "%s%s%s", ctx->colors->rname, elems[i]->name, ctx->colors->reset);
for (j = 0; j < indicesnum; j++)
res->name = appendidx(ctx, res->name, indices[j], NULL);
if (elems[i]->length != 1)
res->name = appendidx(ctx, res->name, idx, elems[i]->index);
if (offset) {
asprintf (&tmp, "%s+%s%#"PRIx64"%s", res->name, ctx->colors->err, offset, ctx->colors->reset);
free(res->name);
res->name = tmp;
}
return res;
case RNN_ETYPE_STRIPE:
for (idx = 0; idx < elems[i]->length || !elems[i]->length; idx++) {
if (addr < elems[i]->offset + elems[i]->stride * idx)
break;
offset = addr - (elems[i]->offset + elems[i]->stride * idx);
int extraidx = (elems[i]->length != 1);
int nindnum = (elems[i]->name ? 0 : indicesnum + extraidx);
uint64_t nind[nindnum];
if (!elems[i]->name) {
for (j = 0; j < indicesnum; j++)
nind[j] = indices[j];
if (extraidx)
nind[indicesnum] = idx;
}
res = trymatch (ctx, elems[i]->subelems, elems[i]->subelemsnum, offset, write, dwidth, nind, nindnum);
if (!res)
continue;
if (!elems[i]->name)
return res;
asprintf (&name, "%s%s%s", ctx->colors->rname, elems[i]->name, ctx->colors->reset);
for (j = 0; j < indicesnum; j++)
name = appendidx(ctx, name, indices[j], NULL);
if (elems[i]->length != 1)
name = appendidx(ctx, name, idx, elems[i]->index);
asprintf (&tmp, "%s.%s", name, res->name);
free(name);
free(res->name);
res->name = tmp;
return res;
}
break;
case RNN_ETYPE_ARRAY:
if (get_array_idx_offset(elems[i], addr, &idx, &offset))
break;
asprintf (&name, "%s%s%s", ctx->colors->rname, elems[i]->name, ctx->colors->reset);
for (j = 0; j < indicesnum; j++)
name = appendidx(ctx, name, indices[j], NULL);
if (elems[i]->length != 1)
name = appendidx(ctx, name, idx, elems[i]->index);
if ((res = trymatch (ctx, elems[i]->subelems, elems[i]->subelemsnum, offset, write, dwidth, 0, 0))) {
asprintf (&tmp, "%s.%s", name, res->name);
free(name);
free(res->name);
res->name = tmp;
return res;
}
res = calloc (sizeof *res, 1);
asprintf (&tmp, "%s+%s%#"PRIx64"%s", name, ctx->colors->err, offset, ctx->colors->reset);
free(name);
res->name = tmp;
return res;
default:
break;
}
}
return 0;
}
int rnndec_checkaddr(struct rnndeccontext *ctx, struct rnndomain *domain, uint64_t addr, int write) {
struct rnndecaddrinfo *res = trymatch(ctx, domain->subelems, domain->subelemsnum, addr, write, domain->width, 0, 0);
if (res) {
free(res->name);
free(res);
}
return res != NULL;
}
struct rnndecaddrinfo *rnndec_decodeaddr(struct rnndeccontext *ctx, struct rnndomain *domain, uint64_t addr, int write) {
struct rnndecaddrinfo *res = trymatch(ctx, domain->subelems, domain->subelemsnum, addr, write, domain->width, 0, 0);
if (res)
return res;
res = calloc (sizeof *res, 1);
asprintf (&res->name, "%s%#"PRIx64"%s", ctx->colors->err, addr, ctx->colors->reset);
return res;
}
static uint64_t tryreg(struct rnndeccontext *ctx, struct rnndelem **elems, int elemsnum,
int dwidth, const char *name)
{
int i;
const char *suffix = strchr(name, '[');
unsigned n = suffix ? (suffix - name) : strlen(name);
const char *child = NULL;
unsigned idx = 0;
if (suffix) {
const char *tmp = strchr(suffix, ']');
idx = strtol(suffix+1, NULL, 0);
child = tmp+2;
}
for (i = 0; i < elemsnum; i++) {
struct rnndelem *elem = elems[i];
if (!rnndec_varmatch(ctx, &elem->varinfo))
continue;
int match = (strlen(elem->name) == n) && !strncmp(elem->name, name, n);
switch (elem->type) {
case RNN_ETYPE_REG:
if (match) {
assert(!suffix);
return elem->offset;
}
break;
case RNN_ETYPE_STRIPE:
assert(0); // TODO
break;
case RNN_ETYPE_ARRAY:
if (match) {
assert(suffix);
return elem->offset + (idx * elem->stride) +
tryreg(ctx, elem->subelems, elem->subelemsnum, dwidth, child);
}
break;
default:
break;
}
}
return 0;
}
uint64_t rnndec_decodereg(struct rnndeccontext *ctx, struct rnndomain *domain, const char *name)
{
return tryreg(ctx, domain->subelems, domain->subelemsnum, domain->width, name);
}

View file

@ -0,0 +1,59 @@
/*
* Copyright (C) 2010 Marcin Kościelnicki <koriakin@0x04.net>
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef RNNDEC_H
#define RNNDEC_H
#include "rnn.h"
#include "colors.h"
struct rnndecvariant {
struct rnnenum *en;
int variant;
};
struct rnndeccontext {
struct rnndb *db;
struct rnndecvariant **vars;
int varsnum;
int varsmax;
const struct envy_colors *colors;
};
struct rnndecaddrinfo {
struct rnntypeinfo *typeinfo;
int width;
char *name;
};
struct rnndeccontext *rnndec_newcontext(struct rnndb *db);
int rnndec_varadd(struct rnndeccontext *ctx, char *varset, char *variant);
int rnndec_varmatch(struct rnndeccontext *ctx, struct rnnvarinfo *vi);
char *rnndec_decode_enum(struct rnndeccontext *ctx, const char *enumname, uint64_t enumval);
char *rnndec_decodeval(struct rnndeccontext *ctx, struct rnntypeinfo *ti, uint64_t value);
int rnndec_checkaddr(struct rnndeccontext *ctx, struct rnndomain *domain, uint64_t addr, int write);
struct rnndecaddrinfo *rnndec_decodeaddr(struct rnndeccontext *ctx, struct rnndomain *domain, uint64_t addr, int write);
uint64_t rnndec_decodereg(struct rnndeccontext *ctx, struct rnndomain *domain, const char *name);
#endif

115
src/freedreno/rnn/util.h Normal file
View file

@ -0,0 +1,115 @@
/*
* Copyright (C) 2010-2011 Marcin Kościelnicki <koriakin@0x04.net>
* Copyright (C) 2010 Francisco Jerez <currojerez@riseup.net>
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef UTIL_H
#define UTIL_H
#include <stdlib.h>
#include <stdio.h>
#include <inttypes.h>
#define ADDARRAY(a, e) \
do { \
if ((a ## num) >= (a ## max)) { \
if (!(a ## max)) \
(a ## max) = 16; \
else \
(a ## max) *= 2; \
(a) = realloc((a), (a ## max)*sizeof(*(a))); \
} \
(a)[(a ## num)++] = (e); \
} while(0)
#define FINDARRAY(a, tmp, pred) \
({ \
int __i; \
\
for (__i = 0; __i < (a ## num); __i++) { \
tmp = (a)[__i]; \
if (pred) \
break; \
} \
\
tmp = ((pred) ? tmp : NULL); \
})
/* ceil(log2(x)) */
static inline int clog2(uint64_t x) {
if (!x)
return x;
int r = 0;
while (x - 1 > (1ull << r) - 1)
r++;
return r;
}
#define ARRAY_SIZE(a) (sizeof (a) / sizeof *(a))
#define min(a,b) \
({ \
typeof (a) _a = (a); \
typeof (b) _b = (b); \
_a < _b ? _a : _b; \
})
#define max(a,b) \
({ \
typeof (a) _a = (a); \
typeof (b) _b = (b); \
_a > _b ? _a : _b; \
})
#define CEILDIV(a, b) (((a) + (b) - 1)/(b))
#define extr(a, b, c) ((uint64_t)(a) << (64 - (b) - (c)) >> (64 - (c)))
#define extrs(a, b, c) ((int64_t)(a) << (64 - (b) - (c)) >> (64 - (c)))
#define sext(a, b) extrs(a, 0, b+1)
#define bflmask(a) ((2ull << ((a)-1)) - 1)
#define insrt(a, b, c, d) ((a) = ((a) & ~(bflmask(c) << (b))) | ((d) & bflmask(c)) << (b))
struct envy_loc {
int lstart;
int cstart;
int lend;
int cend;
const char *file;
};
#define LOC_FORMAT(loc, str) "%s:%d.%d-%d.%d: " str, (loc).file, (loc).lstart, (loc).cstart, (loc).lend, (loc).cend
uint32_t elf_hash(const char *str);
FILE *find_in_path(const char *name, const char *path, char **pfullname);
struct astr {
char *str;
size_t len;
};
void print_escaped_astr(FILE *out, struct astr *astr);
char *aprintf(const char *format, ...);
#endif