/* * Copyright 2010 Jerome Glisse * * 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 #include #include #include #include #include #include "rdb_json.h" struct read { struct rdb_json *rdb; regex_t name; }; void regex_get(int n, regmatch_t *match, const char *line, char *out) { if (match[n].rm_so == -1) { out[0] = 0; return; } for (int i = 0; i < (match[n].rm_eo - match[n].rm_so); i++) { out[i] = line[match[n].rm_so + i]; out[i+1] = 0; } } static void space_align(unsigned n, unsigned lenght) { unsigned i; if (lenght > n) { n = 1; } else { n = n - lenght; } for (i = 0; i < n; i++) printf(" "); } static void define_print_reg(json_t *reg, unsigned offset) { json_t *tmp, *fields, *field; unsigned i, bf, bl, bits, j; tmp = json_object_get(reg, "name"); printf("#define R_%06X_%s", offset, json_string_value(tmp)); space_align(54, strlen(json_string_value(tmp)) + 18); printf("0x%08X\n", offset); fields = json_object_get(reg, "field"); for (i = 0; i < json_array_size(fields); i++) { field = json_array_get(fields, i); tmp = json_object_get(field, "bf"); bf = json_integer_value(tmp); tmp = json_object_get(field, "bl"); bl = json_integer_value(tmp); for (j = 0, bits = 0; j < (bl - bf + 1); j++) { bits |= 1 << j; } tmp = json_object_get(field, "name"); printf("#define S_%06X_%s(x)", offset, json_string_value(tmp)); space_align(56, strlen(json_string_value(tmp)) + 23); printf("(((x) & 0x%X) << %d)\n", bits, bf); printf("#define G_%06X_%s(x)", offset, json_string_value(tmp)); space_align(56, strlen(json_string_value(tmp)) + 23); printf("(((x) >> %d) & 0x%X)\n", bf, bits); printf("#define C_%06X_%s(x)", offset, json_string_value(tmp)); space_align(56, strlen(json_string_value(tmp)) + 23); printf("0x%08X\n", 0xFFFFFFFF & ~(bits << bf)); } } static int process_line(void *user_data, const char *line) { struct read *hr = (struct read *)user_data; json_t *block, *reg, *tmp; regmatch_t match[3]; char name[128]; int r, i; void *iter; r = regexec(&hr->name, line, 2, match, 0); switch (r) { case REG_NOMATCH: break; case 0: regex_get(1, match, line, name); for (i = 0; i < json_array_size(hr->rdb->block); i++) { block = json_array_get(hr->rdb->block, i); iter = json_object_iter(block); while (iter) { unsigned offset; reg = json_object_iter_value(iter); if (json_is_object(reg)) { offset = strtoul(json_object_iter_key(iter), NULL, 16); tmp = json_object_get(reg, "name"); if (!strcmp(json_string_value(tmp), name)) { define_print_reg(reg, offset); } } iter = json_object_iter_next(block, iter); } } break; default: fprintf(stderr, "Error matching regular expression %d\n", r); return r; } return 0; } typedef int (*process_line_t)(void *user_data, const char *line); static int read_file(const char *filename, void *user_data, process_line_t pline) { FILE *file; size_t end; char line[512]; int r; file = fopen(filename, "r"); if (file == NULL) { fprintf(stderr, "Failed to open: %s\n", filename); return 0; } fseek(file, 0, SEEK_END); end = ftell(file); fseek(file, 0, SEEK_SET); while (ftell(file) != end) { if (fgets(line, 512, file) == NULL) return -1; if (strlen(line)) { r = pline(user_data, line); if (r) return r; } } fclose(file); return 0; } static int list_read(const char *filename, struct rdb_json *rdb) { struct read hr; hr.rdb = rdb; if (regcomp(&hr.name, "^([_A-Z0-9]*)", REG_EXTENDED)) { fprintf(stderr, "Failed to compile regular expression\n"); return -1; } return read_file(filename, &hr, &process_line); } void usage(void) { printf("usage: rdb [arguments] [file ..]\n\n"); printf("arguments:\n"); printf(" -j json file\n"); printf(" -l list\n"); printf(" -h header\n"); } static unsigned blockflag(struct rdb_json *rdb, json_t *reg) { unsigned flag = 0, i, j; json_t *tmp, *tmp2, *unit; unit = json_object_get(reg, "unit"); if (unit == NULL) return 0; for (i = 0; i < json_array_size(unit); i++) { tmp = json_array_get(unit, i); for (j = 0; j < json_array_size(rdb->unit); j++) { tmp2 = json_array_get(rdb->unit, j); if (!strcmp(json_string_value(tmp), json_string_value(tmp2))) { flag |= 1 << j; } } } return flag; } struct param { int list; int header; int define; char *file; char *list_str; char *header_name; char *define_name; }; int main(int argc, char *argv[]) { static struct option options[] = { {"json", required_argument, 0, 'j'}, {"list", required_argument, 0, 'l'}, {"header", required_argument, 0, 'h'}, {"define", required_argument, 0, 'd'}, {0, 0, 0, 0} }; struct param param; struct rdb_json *rdb; json_t *block, *reg, *tmp, *name, *tmp2; unsigned i; int option_id; void *iter; int c; memset(¶m, 0, sizeof(struct param)); while (1) { c = getopt_long(argc, argv, "l:j:h:d:", options, &option_id); if (c == -1) break; switch (c) { case 'l': param.list = 1; param.list_str = strdup(optarg); break; case 'j': param.file = strdup(optarg); break; case 'h': param.header = 1; param.header_name = strdup(optarg); break; case 'd': param.define = 1; param.define_name = strdup(optarg); break; case '?': /* getopt_long already printed an error message. */ break; default: abort (); } } if (param.file == NULL) { usage(); return -1; } rdb = rdb_json_load(param.file); if (rdb == NULL) { return -1; } if (param.list) { if (strstr(param.list_str, "r")) { for (i = 0; i < json_array_size(rdb->block); i++) { block = json_array_get(rdb->block, i); iter = json_object_iter(block); while (iter) { reg = json_object_iter_value(iter); if (json_is_object(reg)) { tmp = json_object_get(reg, "name"); printf("%s\n", json_string_value(tmp)); } iter = json_object_iter_next(block, iter); } } } return 0; } if (param.define) { list_read(param.define_name, rdb); } if (param.header_name) { printf("/* this file is autogenerated don't edit */\n"); printf("#include \"radeon_reg.h\"\n\n"); printf("struct reg_block %s_block[] = {\n", param.header_name); for (i = 0; i < json_array_size(rdb->unit); i++) { tmp = json_array_get(rdb->unit, i); printf("\t{0x%08X, \"%s\"},\n", 1 << i, json_string_value(tmp)); } printf("};\n\n"); printf("unsigned %s_nblock = %d;\n\n", param.header_name, json_array_size(rdb->unit)); printf("struct reg %s_reg[] = {\n", param.header_name); for (i = 0, c = 0; i < json_array_size(rdb->block); i++) { block = json_array_get(rdb->block, i); name = json_object_get(block, "name"); iter = json_object_iter(block); while (iter) { unsigned offset; reg = json_object_iter_value(iter); if (json_is_object(reg)) { offset = strtoul(json_object_iter_key(iter), NULL, 16); tmp = json_object_get(reg, "name"); printf("\t{0x%08X, 0x%08X, \"%s\", %s_%s_rreg, %s_%s_wreg},\n", offset, blockflag(rdb, reg), json_string_value(tmp), param.header_name, json_string_value(name), param.header_name, json_string_value(name)); c++; } iter = json_object_iter_next(block, iter); } } printf("};\n\n"); printf("unsigned %s_nreg = %d;\n\n", param.header_name, c); } return 0; }