diff options
author | Rob Clark <robdclark@gmail.com> | 2014-10-24 17:40:58 -0400 |
---|---|---|
committer | Rob Clark <robdclark@gmail.com> | 2014-10-25 09:01:44 -0400 |
commit | cf4bea026d46c8fce483cf81f5b1ef56c385fb04 (patch) | |
tree | 70eee4700c41ced88a38582337d2f8900c5d1745 /ir3test.c |
initial commit
Diffstat (limited to 'ir3test.c')
-rw-r--r-- | ir3test.c | 197 |
1 files changed, 197 insertions, 0 deletions
diff --git a/ir3test.c b/ir3test.c new file mode 100644 index 0000000..068383b --- /dev/null +++ b/ir3test.c @@ -0,0 +1,197 @@ +/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */ + +/* + * Copyright (C) 2014 Rob Clark <robclark@freedesktop.org> + * + * 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. + * + * Authors: + * Rob Clark <robclark@freedesktop.org> + */ + +/* A simple emulator for shader program, for testing purposes. */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/mman.h> +#include <fcntl.h> +#include <stdint.h> +#include <stdbool.h> +#include <stdlib.h> +#include <stdio.h> +#include <stdarg.h> +#include <math.h> + +#include "instr-a3xx.h" +#include "asm/ir-a3xx.h" + +static void +read_file(const char *filename, void **ptr, size_t *size) +{ + int fd, ret; + struct stat st; + + *ptr = MAP_FAILED; + + fd = open(filename, O_RDONLY); + if (fd == -1) + errx(1, "couldn't open `%s'", filename); + + ret = fstat(fd, &st); + if (ret) + errx(1, "couldn't stat `%s'", filename); + + *size = st.st_size; + *ptr = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0); + if (*ptr == MAP_FAILED) + errx(1, "couldn't map `%s'", filename); + + close(fd); +} + +static void randomize(float *buf, int num) +{ + unsigned i; + for (i = 0; i < num; i++) + *(buf++) = drand48(); +} + +static float inputs[64], consts[1024]; + +static void shader_run(struct ir3_shader *shader, + struct ir3_shader_info *info, + float *outputs, float *regs) +{ + static uint32_t dwords[64 * 1024]; + unsigned i; + + ir3_shader_assemble(shader, dwords, ARRAY_SIZE(dwords), info); + + assert(((info->max_const + 1) * 4) < ARRAY_SIZE(consts)); + assert(((info->max_reg + 1) * 4) < MAX_REGS); + assert(((info->max_half_reg + 1) * 4) < MAX_REGS); + + /* copy input values into registers: */ + for (i = 0; i < shader->ins_count; i++) { + struct ir3_in *in = shader->ins[i]; + regs[in->rstart->num] = inputs[i]; + } + + ir3_emu_run(dwords, shader->instrs_count, + consts, (info->max_const + 1) * 4, + regs, (info->max_reg + 1) * 4, + (info->max_half_reg + 1) * 4); + + /* copy output values back from registers: */ + for (i = 0; i < shader->outs_count; i++) { + struct ir3_out *out = shader->outs[i]; + outputs[i] = regs[out->rstart->num]; + } +} + +static void dump_registers(struct ir3_shader_info *info, float *regs) +{ + unsigned i; + /* TODO dump half regs too.. */ + for (i = 0; i <= (info->max_reg + 1) * 4; i += 4) { + printf(" %02d: %08x %08x %08x %08x\n", (i / 4), + fui(regs[i+0]), fui(regs[i+1]), + fui(regs[i+2]), fui(regs[i+3])); + } +} + +static int shader_test(struct ir3_shader *ref, struct ir3_shader *test) +{ + float outputs1[64], outputs2[64]; + float regs1[2*MAX_REGS], regs2[2*MAX_REGS]; + struct ir3_shader_info info1, info2; + unsigned i; + int ret = 0; + + randomize(inputs, ARRAY_SIZE(inputs)); + randomize(consts, ARRAY_SIZE(consts)); + + /* give registers random initial values: */ + randomize(regs1, ARRAY_SIZE(regs1)); + randomize(regs2, ARRAY_SIZE(regs2)); + + shader_run(ref, &info1, outputs1, regs1); + shader_run(test, &info2, outputs2, regs2); + + assert(ref->outs_count == test->outs_count); + + for (i = 0; i < ref->outs_count; i++) { + if (fui(outputs1[i]) != fui(outputs2[i])) { + printf("out%d: %f (%08x) vs %f (%08x)\n", i, + outputs1[i], fui(outputs1[i]), + outputs2[i], fui(outputs2[i])); + ret = -1; + } + } + + if (ret) { + /* on failure, dump regs: */ + printf("Fail!\n"); + printf("----------\n"); + printf("reference registers:\n"); + dump_registers(&info1, regs1); + printf("test registers:\n"); + dump_registers(&info2, regs2); + printf("----------\n"); + } else { + printf("Ok!\n"); + } + + return ret; +} + +int main(int argc, char **argv) +{ + char *origfile, *newfile; + char *origasm, *newasm; + struct ir3_shader *origir, *newir; + size_t size; + + if (argc != 3) { + printf("usage: %s orig.asm new.asm\n", argv[0]); + return -1; + } + + origfile = argv[1]; + newfile = argv[2]; + + printf("************ Reading %s\n", origfile); + read_file(origfile, (void **)&origasm, &size); + origir = ir3_asm_parse(origasm); + if (!origir) { + printf("error parsing:\n%s\n", origasm); + return -1; + } + + printf("************ Reading %s\n", newfile); + read_file(newfile, (void **)&newasm, &size); + newir = ir3_asm_parse(newasm); + if (!newir) { + printf("error parsing:\n%s\n", newasm); + return -1; + } + + return shader_test(origir, newir); +} |