diff options
-rw-r--r-- | src/Makefile.am | 5 | ||||
-rw-r--r-- | src/radeon-bof-json.c | 374 | ||||
-rw-r--r-- | src/radeon.h | 50 | ||||
-rw-r--r-- | src/radeon_family.h | 71 | ||||
-rw-r--r-- | src/radeon_priv.h | 1 |
5 files changed, 450 insertions, 51 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 18ee294..da86c1b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -21,7 +21,7 @@ AUTOMAKE_OPTIONS = foreign -bin_PROGRAMS = radeondb +bin_PROGRAMS = radeondb radeon-bof-json AM_CFLAGS = -std=c99 $(LIBJANSSON_CFLAGS) $(LIBDRM_CFLAGS)$(LIBDRM_RADEON_CFLAGS)\ $(PCIACCESS_CFLAGS) @@ -33,6 +33,9 @@ radeondb_SOURCES = radeondb.c bof.c radeon_pciid.c radeon_ctx.c radeon_bof.c\ r600_disassembler.c r100_reg.c r600_reg.c radeondb_LDADD = $(LIBJANSSON_LIBS) $(LIBDRM_LIBS) $(LIBDRM_RADEON_LIBS) $(PCIACCESS_LIBS) +radeon_bof_json_SOURCES = radeon-bof-json.c radeon_pciid.c bof.c +radeon_bof_json_LDADD = $(LIBJANSSON_LIBS) + rs600_reg.c: ../json/rs600.json ../tools/rdb.c ../tools/rdb -j ../json/rs600.json -h rs600 > rs600_reg.c diff --git a/src/radeon-bof-json.c b/src/radeon-bof-json.c new file mode 100644 index 0000000..f6888e3 --- /dev/null +++ b/src/radeon-bof-json.c @@ -0,0 +1,374 @@ +/* + * Copyright 2010 Jerome Glisse <glisse@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 + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS 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: + * Jerome Glisse + */ +#include "config.h" +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <time.h> +#include <sys/timeb.h> +#include <getopt.h> +#include <jansson.h> +#include "bof.h" +#include "radeon_family.h" + +#define RD_ERR(fmt, args...) \ + fprintf(stderr, "EE %s/%s:%d - "fmt, __FILE__, __func__, __LINE__, ##args) + +#define PKT3_NOP 0x10 +#define PKT3_INDIRECT_BUFFER_END 0x17 +#define PKT3_SET_PREDICATION 0x20 +#define PKT3_REG_RMW 0x21 +#define PKT3_COND_EXEC 0x22 +#define PKT3_PRED_EXEC 0x23 +#define PKT3_START_3D_CMDBUF 0x24 +#define PKT3_DRAW_INDEX_2 0x27 +#define PKT3_CONTEXT_CONTROL 0x28 +#define PKT3_DRAW_INDEX_IMMD_BE 0x29 +#define PKT3_INDEX_TYPE 0x2A +#define PKT3_DRAW_INDEX 0x2B +#define PKT3_DRAW_INDEX_AUTO 0x2D +#define PKT3_DRAW_INDEX_IMMD 0x2E +#define PKT3_NUM_INSTANCES 0x2F +#define PKT3_STRMOUT_BUFFER_UPDATE 0x34 +#define PKT3_INDIRECT_BUFFER_MP 0x38 +#define PKT3_MEM_SEMAPHORE 0x39 +#define PKT3_MPEG_INDEX 0x3A +#define PKT3_WAIT_REG_MEM 0x3C +#define PKT3_MEM_WRITE 0x3D +#define PKT3_INDIRECT_BUFFER 0x32 +#define PKT3_CP_INTERRUPT 0x40 +#define PKT3_SURFACE_SYNC 0x43 +#define PKT3_ME_INITIALIZE 0x44 +#define PKT3_COND_WRITE 0x45 +#define PKT3_EVENT_WRITE 0x46 +#define PKT3_EVENT_WRITE_EOP 0x47 +#define PKT3_ONE_REG_WRITE 0x57 +#define PKT3_SET_CONFIG_REG 0x68 +#define PKT3_SET_CONTEXT_REG 0x69 +#define PKT3_SET_ALU_CONST 0x6A +#define PKT3_SET_BOOL_CONST 0x6B +#define PKT3_SET_LOOP_CONST 0x6C +#define PKT3_SET_RESOURCE 0x6D +#define PKT3_SET_SAMPLER 0x6E +#define PKT3_SET_CTL_CONST 0x6F +#define PKT3_SURFACE_BASE_UPDATE 0x73 + +#define PKT_TYPE_S(x) (((x) & 0x3) << 30) +#define PKT_TYPE_G(x) (((x) >> 30) & 0x3) +#define PKT_TYPE_C 0x3FFFFFFF +#define PKT_COUNT_S(x) (((x) & 0x3FFF) << 16) +#define PKT_COUNT_G(x) (((x) >> 16) & 0x3FFF) +#define PKT_COUNT_C 0xC000FFFF +#define PKT0_BASE_INDEX_S(x) (((x) & 0xFFFF) << 0) +#define PKT0_BASE_INDEX_G(x) (((x) >> 0) & 0xFFFF) +#define PKT0_BASE_INDEX_C 0xFFFF0000 +#define PKT3_IT_OPCODE_S(x) (((x) & 0xFF) << 8) +#define PKT3_IT_OPCODE_G(x) (((x) >> 8) & 0xFF) +#define PKT3_IT_OPCODE_C 0xFFFF00FF +#define PKT0(index, count) (PKT_TYPE_S(0) | PKT0_BASE_INDEX_S(index) | PKT_COUNT_S(count)) +#define PKT3(op, count) (PKT_TYPE_S(3) | PKT3_IT_OPCODE_S(op) | PKT_COUNT_S(count)) + +struct radeon_bof_bo { + unsigned *ptr; + unsigned size; +}; + +struct radeon_bof { + unsigned device_id; + unsigned family; + bof_t *bof; + json_t *json; + unsigned id; + unsigned ndwords; + unsigned *pm4; + unsigned nbo; + struct radeon_bof_bo *bo; +}; + +int json_helper_object_add_reg(json_t *json, unsigned offset, unsigned value) +{ + json_t *jvalue; + char tmp[64]; + + sprintf(tmp, "0x%08X", value); + jvalue = json_string(tmp); + sprintf(tmp, "0x%08X", offset); + json_object_set_new(json, tmp, jvalue); + return 0; +} + +int json_helper_object_add_bo(json_t *json, struct radeon_bof *bof, unsigned id) +{ + struct radeon_bof_bo *bo = &bof->bo[id]; + json_t *jbo, *data; + json_t *jvalue; + char tmp[64]; + + jbo = json_object(); + data = json_array(); + jvalue = json_integer(bo->size); + json_object_set_new(jbo, "size", jvalue); + json_object_set_new(jbo, "data", data); + for (int i = 0; i < bo->size / 4; i++) { + sprintf(tmp, "0x%08X", bo->ptr[i]); + jvalue = json_string(tmp); + json_array_append_new(data, jvalue); + } + sprintf(tmp, "bo-0x%04X", id); + json_object_set_new(json, tmp, jbo); + return 0; +} + +int json_helper_object_add_integer(json_t *json, const char *name, unsigned integer) +{ + json_t *tmp; + + tmp = json_integer(integer); + if (tmp == NULL) + return -ENOMEM; + json_object_set_new(json, name, tmp); + return 0; +} + +unsigned find_pkt3_reloc(struct radeon_bof *bof, unsigned id) +{ + unsigned type, count, op; + + type = PKT_TYPE_G(bof->pm4[id]); + count = PKT_COUNT_G(bof->pm4[id]); + op = PKT3_IT_OPCODE_G(bof->pm4[id]); + if (type != 3 || op != PKT3_NOP) { + return 0xFFFFFFFF; + } + return bof->pm4[id + 1]; +} + +json_t *evergreen_parse_cs(struct radeon_bof *bof) +{ + json_t *draw; + unsigned count, type, op, offset, boid; + + draw = json_object(); + do { + type = PKT_TYPE_G(bof->pm4[bof->id]); + count = PKT_COUNT_G(bof->pm4[bof->id]); + switch (type) { + case 3: + op = PKT3_IT_OPCODE_G(bof->pm4[bof->id]); + bof->id++; + offset = bof->pm4[bof->id] << 2; + switch (op) { + case PKT3_SET_CONFIG_REG: + offset += 0X00008000; + break; + case PKT3_SET_CONTEXT_REG: + offset += 0X00028000; + break; + case PKT3_SET_RESOURCE: + offset += 0x00030000; + break; + case PKT3_DRAW_INDEX_AUTO: + bof->id++; + json_helper_object_add_reg(draw, 0x8970, bof->pm4[bof->id++]); + json_helper_object_add_reg(draw, 0x0287F0, bof->pm4[bof->id++]); + return draw; + case PKT3_DRAW_INDEX_IMMD_BE: + case PKT3_DRAW_INDEX: + case PKT3_DRAW_INDEX_IMMD: + bof->id += count; + return draw; + default: + offset = 0; + bof->id += count; + break; + } + if (offset) { + bof->id++; + for (int i = 0; i < count; i++, bof->id++, offset += 4) { + json_helper_object_add_reg(draw, offset, bof->pm4[bof->id]); + switch (offset) { + /* R_02885C_SQ_PGM_START_VS */ + case 0x2885C: + boid = find_pkt3_reloc(bof, bof->id + count - i); +RD_ERR("vs boid %d\n", boid); + json_helper_object_add_bo(draw, bof, boid / 4); + break; + default: + break; + } + } + } + break; + default: + bof->id += count + 1; + break; + } + } while (bof->id < bof->ndwords); + return draw; +} + +typedef json_t *(*radeon_bof_parse_cs_t)(struct radeon_bof *bof); + +void radeon_bof_to_json(struct radeon_bof *bof, const char *bof_name, const char *json_name) +{ + radeon_bof_parse_cs_t parse = NULL; + json_t *jarray, *jdraw; + bof_t *tmp, *bo, *size; + int r; + + bof->bof = bof_load_file(bof_name); + if (bof->bof == NULL) { + RD_ERR("failed to load %s\n", bof_name); + return; + } + bof->device_id = bof_int32_value(bof_object_get(bof->bof, "device_id")); + bof->family = radeon_family_from_device(bof->device_id); + /* pm4 */ + tmp = bof_object_get(bof->bof, "pm4"); + if (tmp == NULL) { + RD_ERR("no pm4 in bof %s\n", bof_name); + return; + } + bof->ndwords = bof_blob_size(tmp) / 4; + bof->pm4 = bof_blob_value(tmp); + bof->id = 0; + /* bo */ + tmp = bof_object_get(bof->bof, "bo"); + if (tmp == NULL) { + RD_ERR("no bo array object\n"); + return; + } + bof->nbo = bof_array_size(tmp); + bof->bo = calloc(bof->nbo, sizeof(struct radeon_bof_bo)); + for (int i = 0; i < bof->nbo; i++) { + bo = bof_array_get(tmp, i); + size = bof_object_get(bo, "size"); + if (size == NULL) { + RD_ERR("can't get %d bo size\n", i); + return; + } + bof->bo[i].size = bof_int32_value(size); + bo = bof_object_get(bo, "data"); + bof->bo[i].ptr = bof_blob_value(bo); + } + + bof->json = json_object(); + if (bof->json == NULL) { + RD_ERR("failed to create json\n"); + return; + } + if (json_helper_object_add_integer(bof->json, "device_id", bof->device_id)) { + RD_ERR("failed to create json\n"); + return; + } + switch (bof->family) { + case CHIP_CEDAR: + case CHIP_REDWOOD: + case CHIP_JUNIPER: + case CHIP_CYPRESS: + case CHIP_HEMLOCK: + parse = &evergreen_parse_cs; + break; + case CHIP_R100: + case CHIP_RV100: + case CHIP_RS100: + case CHIP_RV200: + case CHIP_RS200: + case CHIP_R200: + case CHIP_RV250: + case CHIP_RS300: + case CHIP_RV280: + case CHIP_R300: + case CHIP_R350: + case CHIP_RV350: + case CHIP_RV380: + case CHIP_R420: + case CHIP_R423: + case CHIP_RV410: + case CHIP_RS400: + case CHIP_RS480: + case CHIP_RS600: + case CHIP_RS690: + case CHIP_RS740: + case CHIP_RV515: + case CHIP_R520: + case CHIP_RV530: + case CHIP_RV560: + case CHIP_RV570: + case CHIP_R580: + case CHIP_R600: + case CHIP_RV610: + case CHIP_RV630: + case CHIP_RV670: + case CHIP_RV620: + case CHIP_RV635: + case CHIP_RS780: + case CHIP_RS880: + case CHIP_RV770: + case CHIP_RV730: + case CHIP_RV710: + case CHIP_RV740: + default: + RD_ERR("unsupported chipset 0x%04X family %d\n", bof->device_id, bof->family); + return; + } + /* draw array */ + jarray = json_array(); + if (jarray == NULL) { + RD_ERR("failed to create json\n"); + return; + } + json_object_set_new(bof->json, "draw", jarray); + while (bof->id < bof->ndwords) { + jdraw = parse(bof); + if (jdraw == NULL) { + RD_ERR("failed to parse\n"); + return; + } + if (json_array_append_new(jarray, jdraw)) { + json_decref(jdraw); + RD_ERR("failed to add draw\n"); + return; + } + } + json_dump_file(bof->json, json_name, JSON_INDENT(2) | JSON_SORT_KEYS); +} + +int main(int argc, char *argv[]) +{ + struct radeon_bof bof; + char json_name[256], *tmp; + + strcpy(json_name, argv[1]); + tmp = strstr(json_name, ".bof"); + if (tmp == NULL) { + return -EINVAL; + } + sprintf(tmp, ".json"); + + memset(&bof, 0, sizeof(struct radeon_bof)); + radeon_bof_to_json(&bof, argv[1], json_name); +} diff --git a/src/radeon.h b/src/radeon.h index 200ca03..4e3c083 100644 --- a/src/radeon.h +++ b/src/radeon.h @@ -20,6 +20,7 @@ #define RADEON_CTX_MAX_PM4 (64 * 1024 / 4) #include <stdint.h> +#include "radeon_family.h" typedef uint64_t u64; typedef uint32_t u32; @@ -28,55 +29,6 @@ typedef uint8_t u8; struct radeon; -enum radeon_family { - CHIP_UNKNOWN, - CHIP_R100, - CHIP_RV100, - CHIP_RS100, - CHIP_RV200, - CHIP_RS200, - CHIP_R200, - CHIP_RV250, - CHIP_RS300, - CHIP_RV280, - CHIP_R300, - CHIP_R350, - CHIP_RV350, - CHIP_RV380, - CHIP_R420, - CHIP_R423, - CHIP_RV410, - CHIP_RS400, - CHIP_RS480, - CHIP_RS600, - CHIP_RS690, - CHIP_RS740, - CHIP_RV515, - CHIP_R520, - CHIP_RV530, - CHIP_RV560, - CHIP_RV570, - CHIP_R580, - CHIP_R600, - CHIP_RV610, - CHIP_RV630, - CHIP_RV670, - CHIP_RV620, - CHIP_RV635, - CHIP_RS780, - CHIP_RS880, - CHIP_RV770, - CHIP_RV730, - CHIP_RV710, - CHIP_RV740, - CHIP_CEDAR, - CHIP_REDWOOD, - CHIP_JUNIPER, - CHIP_CYPRESS, - CHIP_HEMLOCK, - CHIP_LAST, -}; - /* * radeon object functions */ diff --git a/src/radeon_family.h b/src/radeon_family.h new file mode 100644 index 0000000..1e30b03 --- /dev/null +++ b/src/radeon_family.h @@ -0,0 +1,71 @@ +/* + * Copyright © 2009 Jerome Glisse <glisse@freedesktop.org> + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#ifndef RADEON_FAMILY_H +#define RADEON_FAMILY_H + +enum radeon_family { + CHIP_UNKNOWN, + CHIP_R100, + CHIP_RV100, + CHIP_RS100, + CHIP_RV200, + CHIP_RS200, + CHIP_R200, + CHIP_RV250, + CHIP_RS300, + CHIP_RV280, + CHIP_R300, + CHIP_R350, + CHIP_RV350, + CHIP_RV380, + CHIP_R420, + CHIP_R423, + CHIP_RV410, + CHIP_RS400, + CHIP_RS480, + CHIP_RS600, + CHIP_RS690, + CHIP_RS740, + CHIP_RV515, + CHIP_R520, + CHIP_RV530, + CHIP_RV560, + CHIP_RV570, + CHIP_R580, + CHIP_R600, + CHIP_RV610, + CHIP_RV630, + CHIP_RV670, + CHIP_RV620, + CHIP_RV635, + CHIP_RS780, + CHIP_RS880, + CHIP_RV770, + CHIP_RV730, + CHIP_RV710, + CHIP_RV740, + CHIP_CEDAR, + CHIP_REDWOOD, + CHIP_JUNIPER, + CHIP_CYPRESS, + CHIP_HEMLOCK, + CHIP_LAST, +}; + +extern unsigned radeon_family_from_device(unsigned device); + +#endif diff --git a/src/radeon_priv.h b/src/radeon_priv.h index dc6b058..6195196 100644 --- a/src/radeon_priv.h +++ b/src/radeon_priv.h @@ -130,7 +130,6 @@ extern int radeon_open_fd(void); extern struct radeon *radeon_new(int fd, unsigned device); extern struct radeon *radeon_incref(struct radeon *radeon); extern struct radeon *radeon_decref(struct radeon *radeon); -extern unsigned radeon_family_from_device(unsigned device); extern int radeon_is_family_compatible(unsigned family1, unsigned family2); extern int radeon_reg_id(struct radeon *radeon, unsigned offset, unsigned *typeid, unsigned *stateid, unsigned *id); extern unsigned radeon_type_from_id(struct radeon *radeon, unsigned id); |