summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Makefile.am5
-rw-r--r--src/radeon-bof-json.c374
-rw-r--r--src/radeon.h50
-rw-r--r--src/radeon_family.h71
-rw-r--r--src/radeon_priv.h1
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);