diff options
author | Nicolai Hähnle <nicolai.haehnle@amd.com> | 2017-05-08 16:16:34 +0200 |
---|---|---|
committer | Nicolai Hähnle <nicolai.haehnle@amd.com> | 2017-05-14 23:40:34 +0200 |
commit | 293d50a72beda3fe9d3906015b16942875b29095 (patch) | |
tree | 7dac3acc4f95fa4880e257c536a8dd22a518889b | |
parent | 03738fb00715e652937b45a7a3c02983dbe0a88f (diff) |
WIP amd/addrtooladdrtool
-rw-r--r-- | src/amd/Makefile.addrtool.am | 46 | ||||
-rw-r--r-- | src/amd/Makefile.am | 2 | ||||
-rw-r--r-- | src/amd/addrtool/addrtool.cpp | 677 |
3 files changed, 725 insertions, 0 deletions
diff --git a/src/amd/Makefile.addrtool.am b/src/amd/Makefile.addrtool.am new file mode 100644 index 0000000000..dfc76778ca --- /dev/null +++ b/src/amd/Makefile.addrtool.am @@ -0,0 +1,46 @@ +# Copyright 2017 Advanced Micro Devices, 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 (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. + +noinst_PROGRAMS += addrtool/addrtool + +addrtool_addrtool_SOURCES = \ + addrtool/addrtool.cpp + +addrtool_addrtool_LDADD = \ + addrlib/libamdgpu_addrlib.la \ + common/libamd_common.la + +nodist_EXTRA_addrtool_addrtool_SOURCES = dummy.cpp + +addrtool_addrtool_CPPFLAGS = \ + -I$(top_srcdir)/src \ + -I$(top_srcdir)/src/mesa \ + -I$(top_srcdir)/src/amd/common \ + -I$(top_srcdir)/src/gallium/auxiliary \ + -I$(top_srcdir)/src/gallium/include \ + -I$(top_srcdir)/include \ + $(VALGRIND_CFLAGS) \ + $(AMDGPU_CFLAGS) \ + $(DEFINES) + +addrtool_addrtool_LDADD += \ + $(AMDGPU_LIBS) \ + $(LIBDRM_LIBS) diff --git a/src/amd/Makefile.am b/src/amd/Makefile.am index 7d191af443..ad554b657e 100644 --- a/src/amd/Makefile.am +++ b/src/amd/Makefile.am @@ -22,7 +22,9 @@ include Makefile.sources noinst_LTLIBRARIES = +noinst_PROGRAMS = EXTRA_DIST = $(COMMON_HEADER_FILES) common/sid_tables.py include Makefile.addrlib.am +include Makefile.addrtool.am include Makefile.common.am diff --git a/src/amd/addrtool/addrtool.cpp b/src/amd/addrtool/addrtool.cpp new file mode 100644 index 0000000000..3e7971ba73 --- /dev/null +++ b/src/amd/addrtool/addrtool.cpp @@ -0,0 +1,677 @@ +/* + * Copyright 2017 Advanced Micro Devices, 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 + * 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. + */ + +/* Surface description format + * ========================== + * W[xH[xD]][.Samples][*Layers][:Levels][,flag]... + * + * Levels can be empty, indicating a full miptree. + * flags can be: + * * 'cube' + * * '3d' + */ + +//HACK - Must update libdrm to be C++-compatible +#include <stdint.h> +#include <stdbool.h> +extern "C" { +#include <amdgpu.h> +} +//END HACK + +#include <fcntl.h> +#include <inttypes.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "util/bitscan.h" +#include "util/macros.h" +#include "util/u_math.h" + +#include "ac_gpu_info.h" +#include "ac_surface.h" + +#include "addrlib/addrinterface.h" +#include "addrlib/addrtypes.h" + +static struct radeon_info info; +static ADDR_HANDLE addrlib; + +static void usage() +{ + printf( +"usage: addrtool addr <surface> <coord>...\n" +"usage: addrtool coord <surface> <addr>...\n" +"\n" +" <surface> is: W[xH[xD]][.Samples][*Layers][:Levels][,flag]...\n" +" <coord> is: X[xY[xZ]][*Layer][:Level]\n" + ); + exit(1); +} + +static void addrlib_open() +{ + unsigned major_version, minor_version; + int fd = open("/dev/dri/renderD128", O_RDWR); + amdgpu_device_handle dev; + struct amdgpu_gpu_info amdinfo; + int r; + if (fd == -1) + perror("Could not open DRM node"); + + r = amdgpu_device_initialize(fd, &major_version, &minor_version, &dev); + if (r == -1) + perror("Could not initialize amdgpu"); + + if (!ac_query_gpu_info(fd, dev, &info, &amdinfo)) { + fprintf(stderr, "Failed to query GPU info\n"); + exit(1); + } + + addrlib = amdgpu_addr_create(&info, &amdinfo); + if (!addrlib) { + fprintf(stderr, "Failed to create addrlib instance\n"); + exit(1); + } + + amdgpu_device_deinitialize(dev); + close(fd); +} + +static void addrlib_error(ADDR_E_RETURNCODE ret, const char *msg) +{ + fprintf(stderr, "addrlib error %u: %s\n", ret, msg); + exit(1); +} + +static const char *get_tile_mode_string(AddrTileMode tm, char *buf, int len) +{ + static const char *strings[] = { +#define X(e) [e] = #e, + X(ADDR_TM_LINEAR_GENERAL) + X(ADDR_TM_LINEAR_ALIGNED) + X(ADDR_TM_1D_TILED_THIN1) + X(ADDR_TM_1D_TILED_THICK) + X(ADDR_TM_2D_TILED_THIN1) + X(ADDR_TM_2D_TILED_THIN2) + X(ADDR_TM_2D_TILED_THIN4) + X(ADDR_TM_2D_TILED_THICK) + X(ADDR_TM_2B_TILED_THIN1) + X(ADDR_TM_2B_TILED_THIN2) + X(ADDR_TM_2B_TILED_THIN4) + X(ADDR_TM_2B_TILED_THICK) + X(ADDR_TM_3D_TILED_THIN1) + X(ADDR_TM_3D_TILED_THICK) + X(ADDR_TM_3B_TILED_THIN1) + X(ADDR_TM_3B_TILED_THICK) + X(ADDR_TM_2D_TILED_XTHICK) + X(ADDR_TM_3D_TILED_XTHICK) + X(ADDR_TM_POWER_SAVE) + X(ADDR_TM_PRT_TILED_THIN1) + X(ADDR_TM_PRT_2D_TILED_THIN1) + X(ADDR_TM_PRT_3D_TILED_THIN1) + X(ADDR_TM_PRT_TILED_THICK) + X(ADDR_TM_PRT_2D_TILED_THICK) + X(ADDR_TM_PRT_3D_TILED_THICK) + X(ADDR_TM_UNKNOWN) +#undef X + }; + + if (tm < ARRAY_SIZE(strings)) + return strings[tm]; + + snprintf(buf, len, "%u", tm); + return buf; +} + +static const char *get_pipe_config_string(AddrPipeCfg v, char *buf, int len) +{ + switch(v) { +#define X(e) case e: return #e; + X(ADDR_PIPECFG_INVALID) + X(ADDR_PIPECFG_P2) + X(ADDR_PIPECFG_P4_8x16) + X(ADDR_PIPECFG_P4_16x16) + X(ADDR_PIPECFG_P4_16x32) + X(ADDR_PIPECFG_P4_32x32) + X(ADDR_PIPECFG_P8_16x16_8x16) + X(ADDR_PIPECFG_P8_16x32_8x16) + X(ADDR_PIPECFG_P8_32x32_8x16) + X(ADDR_PIPECFG_P8_16x32_16x16) + X(ADDR_PIPECFG_P8_32x32_16x16) + X(ADDR_PIPECFG_P8_32x32_16x32) + X(ADDR_PIPECFG_P8_32x64_32x32) + X(ADDR_PIPECFG_P16_32x32_8x16) + X(ADDR_PIPECFG_P16_32x32_16x16) + X(ADDR_PIPECFG_MAX) +#undef X + default: + snprintf(buf, len, "%u", v); + return buf; + } +} + +static const char *get_tile_type_string(AddrTileType v, char *buf, int len) +{ + static const char *strings[] = { +#define X(e) [e] = #e, + X(ADDR_DISPLAYABLE) + X(ADDR_NON_DISPLAYABLE) + X(ADDR_DEPTH_SAMPLE_ORDER) + X(ADDR_ROTATED) + X(ADDR_THICK) +#undef X + }; + + if (v < ARRAY_SIZE(strings)) + return strings[v]; + + snprintf(buf, len, "%u", v); + return buf; +} + +static void dump_surface_info_output(const ADDR_COMPUTE_SURFACE_INFO_OUTPUT *csio) +{ + char buf1[32]; + + printf("ADDR_COMPUTE_SURFACE_INFO_OUTPUT: {\n"); + printf(" pitch: %u, height: %u, depth: %u, surfSize: %llu, tileMode: %s,\n", + csio->pitch, csio->height, csio->depth, csio->surfSize, + get_tile_mode_string(csio->tileMode, buf1, sizeof(buf1))); + printf(" baseAlign: %u, pitchAlign: %u, heightAlign: %u, depthAlign: %u,\n", + csio->baseAlign, csio->pitchAlign, csio->heightAlign, csio->depthAlign); + printf(" bpp: %u, pixelPitch: %u, pixelHeight: %u, pixelBits: %u, sliceSize: %llu,\n", + csio->bpp, csio->pixelPitch, csio->pixelHeight, csio->pixelBits, csio->sliceSize); + printf(" pitchTileMax: %u, heightTileMax: %u, sliceTileMax: %u, numSamples: %u\n", + csio->pitchTileMax, csio->heightTileMax, csio->sliceTileMax, csio->numSamples); + if (csio->pTileInfo) { + const ADDR_TILEINFO *ti = csio->pTileInfo; + printf(" pTileInfo: { banks: %u, bankWidth: %u, bankHeight: %u, macroAspectRatio: %u,\n", + ti->banks, ti->bankWidth, ti->bankHeight, ti->macroAspectRatio); + printf(" tileSplitBytes: %u, pipeConfig: %s },\n", + ti->tileSplitBytes, get_pipe_config_string(ti->pipeConfig, buf1, sizeof(buf1))); + } + printf(" tileType: %s, tileIndex: %d, macroModeIndex: %d, last2DLevel: %u, tcCompatible: %u\n", + get_tile_type_string(csio->tileType, buf1, sizeof(buf1)), + csio->tileIndex, csio->macroModeIndex, csio->last2DLevel, csio->tcCompatible); + printf(" dccUnsupport: %u, prtTileIndex: %u, equationIndex: %u,\n", + csio->blockWidth, csio->blockHeight, csio->blockSlices); + printf(" pStereoInfo: %p, stencilTileIdx: %d }\n", + csio->pStereoInfo, csio->stencilTileIdx); +} + +static void demo() +{ + ADDR_COMPUTE_SURFACE_INFO_INPUT csii; + ADDR_COMPUTE_SURFACE_INFO_OUTPUT csio; + ADDR_TILEINFO tio = {0}; + ADDR_E_RETURNCODE ret; + + memset(&csii, 0, sizeof(csii)); + csii.size = sizeof(csii); + + csii.tileMode = ADDR_TM_UNKNOWN; + csii.bpp = 32; + csii.numSamples = 1; + csii.width = 64; + csii.height = 64; + csii.numSlices = 18; + csii.numMipLevels = 7; + csii.flags.depth = 1; + csii.flags.stencil = 1; + csii.flags.compressZ = 1; + csii.flags.cube = 1; + csii.flags.pow2Pad = 1; + + csio.size = sizeof(csio); + csio.pTileInfo = &tio; + + ret = AddrComputeSurfaceInfo(addrlib, &csii, &csio); + if (ret != ADDR_OK) + addrlib_error(ret, "AddrComputeSurfaceInfo"); + + dump_surface_info_output(&csio); +} + +static void parse_error(const char *cur, const char *full, const char *msg) +{ + printf("Error: %s\n", msg); + printf("in: %s\n", full); + printf("%*s^\n", 4 + (int)(cur - full), ""); +} + +enum parse_int_flags { + parse_int_optional = (1 << 0), +}; + +static bool parse_uint(const char **pcur, const char *full, unsigned flags, unsigned *result) +{ + const char *cur = *pcur; + + if (!(*cur >= '0' && *cur <= '9')) { + if (flags & parse_int_optional) + return true; + + parse_error(cur, full, "unsigned integer expected"); + return false; + } + + char *endp; + *result = strtol(cur, &endp, 10); + *pcur = endp; + + return true; +} + +static bool parse_keyword(const char **pcur, const char *keyword) +{ + int len = strlen(keyword); + if (strncmp(*pcur, keyword, len) != 0) + return false; + + *pcur += len; + return true; +} + +static bool parse_surf_config(const char *def, struct ac_surf_config *config) +{ + const char *cur = def; + + config->info.width = config->info.height = config->info.depth = config->info.array_size = 1; + config->info.levels = 1; + + if (!parse_uint(&cur, def, 0, &config->info.width)) + return false; + + if (*cur == 'x') { + cur++; + if (!parse_uint(&cur, def, 0, &config->info.height)) + return false; + + if (*cur == 'x') { + cur++; + if (!parse_uint(&cur, def, 0, &config->info.depth)) + return false; + + config->is_3d = 1; + } + } + + if (*cur == '.') { + unsigned samples; + cur++; + if (!parse_uint(&cur, def, 0, &samples)) + return false; + + config->info.samples = samples; + } + + if (*cur == '*') { + unsigned array_size; + cur++; + if (!parse_uint(&cur, def, 0, &array_size)) + return false; + + config->info.array_size = array_size; + } + + if (*cur == ':') { + unsigned levels = MAX3(util_last_bit(config->info.width), + util_last_bit(config->info.height), + util_last_bit(config->info.depth)); + cur++; + if (!parse_uint(&cur, def, parse_int_optional, &levels)) + return false; + + config->info.levels = levels; + } + + while (*cur == ',') { + if (parse_keyword(&cur, "cube")) { + config->is_cube = 1; + } else if (parse_keyword(&cur, "3d")) { + config->is_3d = 1; + } else { + parse_error(cur, def, "unknown flag"); + return false; + } + + if (*cur && *cur != ',') { + parse_error(cur, def, "unexpected noise after flag"); + return false; + } + } + + return true; +} + +struct coordinate { + unsigned x, y, z; + unsigned sample; + unsigned layer; + unsigned level; +}; + +static bool parse_coordinate(const char *def, struct coordinate *coord) +{ + const char *cur = def; + + if (!parse_uint(&cur, def, 0, &coord->x)) + return false; + + if (*cur == 'x') { + cur++; + if (!parse_uint(&cur, def, 0, &coord->y)) + return false; + + if (*cur == 'x') { + cur++; + if (!parse_uint(&cur, def, 0, &coord->z)) + return false; + } + } + + if (*cur == '.') { + cur++; + if (!parse_uint(&cur, def, 0, &coord->sample)) + return false; + } + + if (*cur == '*') { + cur++; + if (!parse_uint(&cur, def, 0, &coord->layer)) + return false; + } + + if (*cur == ':') { + cur++; + if (!parse_uint(&cur, def, parse_int_optional, &coord->level)) + return false; + } + + return true; +} + +static void print_surf_config(const struct ac_surf_config *config, FILE *f) +{ + fprintf(f, "%ux%ux%u.%u*%u:%u", + config->info.width, config->info.height, config->info.depth, + config->info.samples, config->info.array_size, config->info.levels); + if (config->is_3d) + fprintf(f, ",3d"); + if (config->is_cube) + fprintf(f, ",cube"); +} + +static void print_coordinate(const struct coordinate *coord, FILE *f) +{ + fprintf(f, "%ux%ux%u.%u*%u:%u", + coord->x, coord->y, coord->z, coord->sample, coord->layer, + coord->level); +} + +template<typename T> +static void gfx6_setup_compute_addr_coord(const struct ac_surf_config *config, + const struct radeon_surf *surf, + unsigned level, + T *in, + ADDR_TILEINFO *ti) +{ + ADDR_E_RETURNCODE r; + ADDR_EXTRACT_BANKPIPE_SWIZZLE_INPUT ebpsi = {}; + ADDR_EXTRACT_BANKPIPE_SWIZZLE_OUTPUT ebpso = {}; + const struct legacy_surf_level *lvlinfo = &surf->u.legacy.level[level]; + + ebpsi.size = sizeof(ebpsi); + ebpso.size = sizeof(ebpso); + + /* Fill in surface data */ + in->bpp = surf->bpe * 8; + in->pitch = lvlinfo->nblk_x; + in->height = lvlinfo->nblk_y; + in->numSlices = config->is_3d ? u_minify(config->info.depth, level) : config->info.array_size; + in->numSamples = config->info.samples; + + switch (lvlinfo->mode) { + case RADEON_SURF_MODE_LINEAR_ALIGNED: + in->tileMode = ADDR_TM_LINEAR_ALIGNED; + break; + case RADEON_SURF_MODE_1D: + in->tileMode = ADDR_TM_1D_TILED_THIN1; + break; + case RADEON_SURF_MODE_2D: + in->tileMode = ADDR_TM_2D_TILED_THIN1; + break; + default: + assert(0); + } + + in->isDepth = !!(surf->flags & RADEON_SURF_Z_OR_SBUFFER); + in->tileBase = 0; /* ??? */ + in->compBits = 0; /* ??? */ + + /* Set the micro tile type. */ + if (surf->flags & RADEON_SURF_SCANOUT) + in->tileType = ADDR_DISPLAYABLE; + else if (surf->flags & (RADEON_SURF_Z_OR_SBUFFER | RADEON_SURF_FMASK)) + in->tileType = ADDR_DEPTH_SAMPLE_ORDER; + else + in->tileType = ADDR_NON_DISPLAYABLE; + + ti->banks = surf->u.legacy.num_banks; + ti->bankWidth = surf->u.legacy.bankw; + ti->bankHeight = surf->u.legacy.bankh; + ti->macroAspectRatio = surf->u.legacy.mtilea; + ti->tileSplitBytes = surf->u.legacy.tile_split; + ti->pipeConfig = AddrPipeCfg(surf->u.legacy.pipe_config + 1); /* +1 compared to GB_TILE_MODE */ + in->pTileInfo = ti; + in->tileIndex = surf->u.legacy.tiling_index[level]; + + ebpsi.base256b = 0; /* ??? slice swizzle ??? */ + ebpsi.pTileInfo = ti; + ebpsi.tileIndex = surf->u.legacy.tiling_index[level]; + ebpsi.macroModeIndex = surf->u.legacy.macro_tile_index; + + r = AddrExtractBankPipeSwizzle(addrlib, &ebpsi, &ebpso); + if (r != ADDR_OK) { + printf("AddrExtractBankPipeSwizzle failed: %d\n", r); + exit(1); + } + + in->bankSwizzle = ebpso.bankSwizzle; + in->pipeSwizzle = ebpso.pipeSwizzle; +} + +static uint64_t gfx6_compute_addr(const struct ac_surf_config *config, + const struct radeon_surf *surf, + const struct coordinate *coord) +{ + ADDR_TILEINFO ti = {}; + ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT in = {}; + ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT out = {}; + ADDR_E_RETURNCODE r; + int level = coord->level; + + in.size = sizeof(in); + out.size = sizeof(out); + + gfx6_setup_compute_addr_coord(config, surf, level, &in, &ti); + + /* Fill in coordinate */ + in.x = coord->x; + in.y = coord->y; + in.slice = config->is_3d ? coord->z : coord->layer; + in.sample = coord->sample; + + r = AddrComputeSurfaceAddrFromCoord(addrlib, &in, &out); + if (r != ADDR_OK) { + printf("AddrComputeSurfaceAddrFromCoord failed: %d\n", r); + exit(1); + } + + return out.addr + surf->u.legacy.level[level].offset; +} + +static void gfx6_compute_coord(const struct ac_surf_config *config, + const struct radeon_surf *surf, + uint64_t addr, + struct coordinate *coord) +{ + ADDR_TILEINFO ti = {}; + ADDR_COMPUTE_SURFACE_COORDFROMADDR_INPUT in = {}; + ADDR_COMPUTE_SURFACE_COORDFROMADDR_OUTPUT out = {}; + ADDR_E_RETURNCODE r; + int level = 0; + + while (level + 1 < config->info.levels && + addr >= surf->u.legacy.level[level + 1].offset) + level++; + + in.size = sizeof(in); + out.size = sizeof(out); + + gfx6_setup_compute_addr_coord(config, surf, level, &in, &ti); + + /* Fill in address */ + in.addr = addr - surf->u.legacy.level[level].offset; + + r = AddrComputeSurfaceCoordFromAddr(addrlib, &in, &out); + if (r != ADDR_OK) { + printf("AddrComputeSurfaceCoordFromAddr failed: %d\n", r); + exit(1); + } + + coord->x = out.x; + coord->y = out.y; + coord->z = config->is_3d ? out.slice : 0; + coord->layer = config->is_3d ? 0 : out.slice; + coord->sample = out.sample; + coord->level = level; +} + +static void cmd_addr_coord(int argc, char **argv, int argi, bool from_addr) +{ + struct ac_surf_config config = {}; + int r; + + if (argi >= argc) { + printf("Missing arguments: <surface> %s\n", from_addr ? "<addr>" : "<coord>"); + exit(1); + } + if (!parse_surf_config(argv[argi++], &config)) + exit(1); + + printf("Surface: "); + print_surf_config(&config, stdout); + printf("\n"); + + if (argi >= argc) { + printf("Missing argument: %s\n", from_addr ? "<addr>" : "<coord>"); + exit(1); + } + + struct radeon_surf surf = {}; + + surf.blk_w = 1; + surf.blk_h = 1; + surf.bpe = 4; + + r = ac_compute_surface(addrlib, &info, &config, RADEON_SURF_MODE_2D, &surf); + if (r) { + printf("Error computing surface: %d\n", r); + exit(1); + } + + /* TODO: gfx9 support... */ + assert(info.chip_class <= VI); + + while (argi < argc) { + if (from_addr) { + char *endp; + uint64_t addr = strtoull(argv[argi++], &endp, 0); + if (*endp) { + printf("Expected addr: %s\n", argv[argi - 1]); + exit(1); + } + + printf("Addr: %" PRIu64 " -- 0x%" PRIx64 "\n", addr, addr); + + struct coordinate coord; + gfx6_compute_coord(&config, &surf, addr, &coord); + printf("Coordinate: "); + print_coordinate(&coord, stdout); + printf("\n"); + } else { + struct coordinate coord = {}; + if (!parse_coordinate(argv[argi++], &coord)) + exit(1); + + printf("Coordinate: "); + print_coordinate(&coord, stdout); + printf("\n"); + + uint64_t addr = gfx6_compute_addr(&config, &surf, &coord); + printf("Address: %" PRIu64 " -- 0x%" PRIx64 "\n", addr, addr); + } + } +} + +int main(int argc, char **argv) +{ + int i = 1; + + addrlib_open(); + + printf("Demo\n"); + demo(); + + while (i < argc) { + if (argv[i][0] != '-') + break; + + if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { + usage(); + } else { + printf("Unknown argument: %s\n", argv[i]); + exit(1); + } + } + + if (i >= argc) { + printf("Need to provide a command!\n"); + exit(1); + } + + const char *cmd = argv[i++]; + + if (!strcmp(cmd, "addr")) { + cmd_addr_coord(argc, argv, i, false); + } else if (!strcmp(cmd, "coord")) { + cmd_addr_coord(argc, argv, i, true); + } else { + printf("Unknown command: %s\n", argv[i]); + exit(1); + } +} |