diff options
Diffstat (limited to 'utils/regtools')
-rw-r--r-- | utils/regtools/headergen.cpp | 227 |
1 files changed, 214 insertions, 13 deletions
diff --git a/utils/regtools/headergen.cpp b/utils/regtools/headergen.cpp index fc1ce6fba6..0a65388686 100644 --- a/utils/regtools/headergen.cpp +++ b/utils/regtools/headergen.cpp | |||
@@ -26,11 +26,16 @@ | |||
26 | #include <sstream> | 26 | #include <sstream> |
27 | #include <sys/stat.h> | 27 | #include <sys/stat.h> |
28 | #include <sys/types.h> | 28 | #include <sys/types.h> |
29 | #include <getopt.h> | ||
29 | 30 | ||
30 | #define HEADERGEN_VERSION "2.1.7" | 31 | #define HEADERGEN_VERSION "2.1.7" |
31 | 32 | ||
32 | #define error(...) do{ fprintf(stderr, __VA_ARGS__); exit(1); } while(0) | 33 | #define error(...) do{ fprintf(stderr, __VA_ARGS__); exit(1); } while(0) |
33 | 34 | ||
35 | bool g_gen_selector = false; | ||
36 | |||
37 | std::string g_macro_filename; | ||
38 | |||
34 | std::string g_soc_name; | 39 | std::string g_soc_name; |
35 | std::string g_soc_dev; | 40 | std::string g_soc_dev; |
36 | std::string g_soc_reg; | 41 | std::string g_soc_reg; |
@@ -86,8 +91,10 @@ void fprint_copyright(FILE *f, const std::vector< xml_ver_t >& versions) | |||
86 | * Firmware |____|_ /\\____/ \\___ >__|_ \\|___ /\\____/__/\\_ \\\n\ | 91 | * Firmware |____|_ /\\____/ \\___ >__|_ \\|___ /\\____/__/\\_ \\\n\ |
87 | * \\/ \\/ \\/ \\/ \\/\n\ | 92 | * \\/ \\/ \\/ \\/ \\/\n\ |
88 | * This file was automatically generated by headergen, DO NOT EDIT it.\n\ | 93 | * This file was automatically generated by headergen, DO NOT EDIT it.\n\ |
89 | * headergen version: " HEADERGEN_VERSION "\n\ | 94 | * headergen version: " HEADERGEN_VERSION "\n"); |
90 | * XML versions:%s\n\ | 95 | if(versions.size() > 0) |
96 | fprintf(f, " * XML versions:%s\n", ver.str().c_str()); | ||
97 | fprintf(f,"\ | ||
91 | *\n\ | 98 | *\n\ |
92 | * Copyright (C) 2013 by Amaury Pouly\n\ | 99 | * Copyright (C) 2013 by Amaury Pouly\n\ |
93 | *\n\ | 100 | *\n\ |
@@ -99,8 +106,7 @@ void fprint_copyright(FILE *f, const std::vector< xml_ver_t >& versions) | |||
99 | * This software is distributed on an \"AS IS\" basis, WITHOUT WARRANTY OF ANY\n\ | 106 | * This software is distributed on an \"AS IS\" basis, WITHOUT WARRANTY OF ANY\n\ |
100 | * KIND, either express or implied.\n\ | 107 | * KIND, either express or implied.\n\ |
101 | *\n\ | 108 | *\n\ |
102 | ****************************************************************************/\n", | 109 | ****************************************************************************/\n"); |
103 | ver.str().c_str()); | ||
104 | } | 110 | } |
105 | 111 | ||
106 | void fprint_copyright(FILE *f, const xml_ver_t& version) | 112 | void fprint_copyright(FILE *f, const xml_ver_t& version) |
@@ -108,6 +114,11 @@ void fprint_copyright(FILE *f, const xml_ver_t& version) | |||
108 | fprint_copyright(f, std::vector< xml_ver_t >(1, version)); | 114 | fprint_copyright(f, std::vector< xml_ver_t >(1, version)); |
109 | } | 115 | } |
110 | 116 | ||
117 | void fprint_copyright(FILE *f) | ||
118 | { | ||
119 | fprint_copyright(f, std::vector< xml_ver_t >()); | ||
120 | } | ||
121 | |||
111 | void fprint_include_guard_ex(FILE *f, bool begin, const std::string& name) | 122 | void fprint_include_guard_ex(FILE *f, bool begin, const std::string& name) |
112 | { | 123 | { |
113 | if(begin) | 124 | if(begin) |
@@ -262,6 +273,8 @@ void gen_soc_dev_header(const std::string& filename, const xml_ver_t& ver, const | |||
262 | } | 273 | } |
263 | fprint_copyright(f, ver); | 274 | fprint_copyright(f, ver); |
264 | fprint_include_guard(f, true); | 275 | fprint_include_guard(f, true); |
276 | if(g_macro_filename.size() > 0) | ||
277 | fprintf(f, "#include \"%s\"\n", g_macro_filename.c_str()); | ||
265 | 278 | ||
266 | /* print base */ | 279 | /* print base */ |
267 | fprintf(f, "\n"); | 280 | fprintf(f, "\n"); |
@@ -311,7 +324,10 @@ void gen_headers(const std::string& prefix, const std::vector< soc_t >& socs) | |||
311 | for(size_t i = 0; i < socs.size(); i++) | 324 | for(size_t i = 0; i < socs.size(); i++) |
312 | { | 325 | { |
313 | g_soc_name = socs[i].name; | 326 | g_soc_name = socs[i].name; |
314 | gen_soc_headers(prefix + "/" + socs[i].name, socs[i]); | 327 | std::string dir = prefix; |
328 | if(g_gen_selector) | ||
329 | dir += "/" + socs[i].name; | ||
330 | gen_soc_headers(dir, socs[i]); | ||
315 | } | 331 | } |
316 | } | 332 | } |
317 | 333 | ||
@@ -330,16 +346,14 @@ general_dev_list_t build_general_dev_list(const std::vector< soc_t >& socs) | |||
330 | void gen_select_header(const std::string& filename, const std::string& dev, | 346 | void gen_select_header(const std::string& filename, const std::string& dev, |
331 | const std::vector< std::string >& socs, const std::vector< xml_ver_t >& ver) | 347 | const std::vector< std::string >& socs, const std::vector< xml_ver_t >& ver) |
332 | { | 348 | { |
333 | /* | ||
334 | printf("Generate select header for device %s: write to %s\n", dev.c_str(), | ||
335 | filename.c_str()); | ||
336 | */ | ||
337 | std::string guard = "__SELECT__" + toupper(dev) + "__H__"; | 349 | std::string guard = "__SELECT__" + toupper(dev) + "__H__"; |
338 | FILE *f = fopen(filename.c_str(), "w"); | 350 | FILE *f = fopen(filename.c_str(), "w"); |
339 | if(f == NULL) | 351 | if(f == NULL) |
340 | error("Cannot open file %s\n", filename.c_str()); | 352 | error("Cannot open file %s\n", filename.c_str()); |
341 | fprint_copyright(f, ver); | 353 | fprint_copyright(f, ver); |
342 | fprint_include_guard_ex(f, true, guard); | 354 | fprint_include_guard_ex(f, true, guard); |
355 | if(g_macro_filename.size() > 0) | ||
356 | fprintf(f, "#include \"%s\"\n", g_macro_filename.c_str()); | ||
343 | fprintf(f, "\n"); | 357 | fprintf(f, "\n"); |
344 | 358 | ||
345 | for(size_t i = 0; i < socs.size(); i++) | 359 | for(size_t i = 0; i < socs.size(); i++) |
@@ -360,6 +374,7 @@ void gen_select_header(const std::string& filename, const std::string& dev, | |||
360 | 374 | ||
361 | void gen_selectors(const std::string& prefix, const std::vector< soc_t >& socs) | 375 | void gen_selectors(const std::string& prefix, const std::vector< soc_t >& socs) |
362 | { | 376 | { |
377 | printf("Generate select headers: use directory %s\n", prefix.c_str()); | ||
363 | general_dev_list_t map = build_general_dev_list(socs); | 378 | general_dev_list_t map = build_general_dev_list(socs); |
364 | for(general_dev_list_t::iterator it = map.begin(); it != map.end(); ++it) | 379 | for(general_dev_list_t::iterator it = map.begin(); it != map.end(); ++it) |
365 | { | 380 | { |
@@ -376,24 +391,210 @@ void gen_selectors(const std::string& prefix, const std::vector< soc_t >& socs) | |||
376 | } | 391 | } |
377 | } | 392 | } |
378 | 393 | ||
394 | void gen_macro_list(FILE *f, const std::string& prefix, int count, int nr_digits, | ||
395 | const std::string& sep, int max_per_line = 1000, const std::string& align = "") | ||
396 | { | ||
397 | for(int i = 1; i <= count;) | ||
398 | { | ||
399 | for(int j = i; j <= std::min(count, i + max_per_line - 1); j++) | ||
400 | { | ||
401 | fprintf(f, "%s%0*d", prefix.c_str(), nr_digits, j); | ||
402 | if(j < count) | ||
403 | fprintf(f, "%s", sep.c_str()); | ||
404 | } | ||
405 | i += max_per_line; | ||
406 | if(i <= count) | ||
407 | fprintf(f, "\\\n%s", align.c_str()); | ||
408 | } | ||
409 | } | ||
410 | |||
411 | void gen_macro(const std::string& filename, bool variadic) | ||
412 | { | ||
413 | printf("Generate %smacro header: use %s\n", variadic ? "": "non-variadic ", | ||
414 | filename.c_str()); | ||
415 | std::string guard = "__REGS__MACRO__H__"; | ||
416 | FILE *f = fopen(filename.c_str(), "w"); | ||
417 | if(f == NULL) | ||
418 | error("Cannot open file %s\n", filename.c_str()); | ||
419 | fprint_copyright(f); | ||
420 | fprint_include_guard_ex(f, true, guard); | ||
421 | fprintf(f, "\n"); | ||
422 | |||
423 | #define REG_WRITE "REG_WRITE" | ||
424 | fprintf(f, "#ifndef %s\n", REG_WRITE); | ||
425 | fprintf(f, "#define %s(var,value) ((var) = (value))\n", REG_WRITE); | ||
426 | fprintf(f, "#endif /* %s */\n", REG_WRITE); | ||
427 | fprintf(f, "\n"); | ||
428 | |||
429 | #define REG_READ "REG_READ" | ||
430 | fprintf(f, "#ifndef %s\n", REG_READ); | ||
431 | fprintf(f, "#define %s(var) (var)\n", REG_READ); | ||
432 | fprintf(f, "#endif /* %s */\n", REG_READ); | ||
433 | fprintf(f, "\n"); | ||
434 | |||
435 | const int MAX_NARGS = 32; | ||
436 | |||
437 | fprintf(f, "\ | ||
438 | #define BF_SET(reg, field) "REG_WRITE"(HW_##reg##_SET, BM_##reg##_##field)\n\ | ||
439 | #define BF_CLR(reg, field) "REG_WRITE"(HW_##reg##_CLR, BM_##reg##_##field)\n\ | ||
440 | #define BF_TOG(reg, field) "REG_WRITE"(HW_##reg##_TOG, BM_##reg##_##field)\n\ | ||
441 | \n\ | ||
442 | #define BF_SETV(reg, field, v) "REG_WRITE"(HW_##reg##_SET, BF_##reg##_##field(v))\n\ | ||
443 | #define BF_CLRV(reg, field, v) "REG_WRITE"(HW_##reg##_CLR, BF_##reg##_##field(v))\n\ | ||
444 | #define BF_TOGV(reg, field, v) "REG_WRITE"(HW_##reg##_TOG, BF_##reg##_##field(v))\n\ | ||
445 | \n\ | ||
446 | #define BF_RDX(val, reg, field) (("REG_READ"(val) & BM_##reg##_##field) >> BP_##reg##_##field)\n\ | ||
447 | #define BF_RD(reg, field) BF_RDX("REG_READ"(HW_##reg), reg, field)\n\ | ||
448 | #define BF_WRX(val, reg, field, v) "REG_WRITE"(val, ("REG_READ"(val) & ~BM_##reg##_##field) | (((v) << BP_##reg##_##field) & BM_##reg##_##field))\n\ | ||
449 | #define BF_WR(reg, field, v) BF_WRX(HW_##reg, reg, field, v)\n\ | ||
450 | #define BF_WR_V(reg, field, sy) BF_WR(reg, field, BV_##reg##_##field##__##sy)\n\ | ||
451 | #define BF_WR_VX(val, reg, field, sy) BF_WRX(val, reg, field, BV_##reg##_##field##__##sy)\n\ | ||
452 | \n\ | ||
453 | #define BF_SETn(reg, n, field) "REG_WRITE"(HW_##reg##_SET(n), BM_##reg##_##field)\n\ | ||
454 | #define BF_CLRn(reg, n, field) "REG_WRITE"(HW_##reg##_CLR(n), BM_##reg##_##field)\n\ | ||
455 | #define BF_TOGn(reg, n, field) "REG_WRITE"(HW_##reg##_TOG(n), BM_##reg##_##field)\n\ | ||
456 | \n\ | ||
457 | #define BF_SETVn(reg, n, field, v) "REG_WRITE"(HW_##reg##_SET(n), BF_##reg##_##field(v))\n\ | ||
458 | #define BF_CLRVn(reg, n, field, v) "REG_WRITE"(HW_##reg##_CLR(n), BF_##reg##_##field(v))\n\ | ||
459 | #define BF_TOGVn(reg, n, field, v) "REG_WRITE"(HW_##reg##_TOG(n), BF_##reg##_##field(v))\n\ | ||
460 | \n\ | ||
461 | #define BF_RDn(reg, n, field) BF_RDX(HW_##reg(n), reg, field)\n\ | ||
462 | #define BF_WRn(reg, n, field, v) BF_WRX(HW_##reg(n), reg, field, v)\n\ | ||
463 | #define BF_WRn_V(reg, n, field, sy) BF_WRn(reg, n, field, BV_##reg##_##field##__##sy)\n\ | ||
464 | \n"); | ||
465 | |||
466 | for(int nargs = 1; nargs <= MAX_NARGS; nargs++) | ||
467 | { | ||
468 | fprintf(f, "#define BM_OR%d(reg, ", nargs); | ||
469 | gen_macro_list(f, "f", nargs, 2, ", ", 10, " "); | ||
470 | fprintf(f, ") \\\n ("); | ||
471 | gen_macro_list(f, "BM_##reg##_##f", nargs, 2, " | ", 4, " "); | ||
472 | fprintf(f, ")\n"); | ||
473 | } | ||
474 | fprintf(f, "\n"); | ||
475 | |||
476 | for(int nargs = 1; nargs <= MAX_NARGS; nargs++) | ||
477 | { | ||
478 | fprintf(f, "#define BF_OR%d(reg, ", nargs); | ||
479 | gen_macro_list(f, "f", nargs, 2, ", ", 10, " "); | ||
480 | fprintf(f, ") \\\n ("); | ||
481 | gen_macro_list(f, "BF_##reg##_##f", nargs, 2, " | ", 4, " "); | ||
482 | fprintf(f, ")\n"); | ||
483 | } | ||
484 | fprintf(f, "\n"); | ||
485 | |||
486 | if(variadic) | ||
487 | { | ||
488 | fprintf(f, "#define REG_NARG(...) REG_NARGS_(__VA_ARGS__"); | ||
489 | for(int i = MAX_NARGS; i >= 1; i--) | ||
490 | fprintf(f, ", %d", i); | ||
491 | fprintf(f, ")\n"); | ||
492 | fprintf(f, "#define REG_NARGS_("); | ||
493 | gen_macro_list(f, "_", MAX_NARGS, 1, ", "); | ||
494 | fprintf(f, ", N, ...) N\n\n"); | ||
495 | |||
496 | fprintf(f, "#define REG_VARIADIC(macro, reg, ...) REG_VARIADIC_(macro, NARG(__VA_ARGS__), reg, __VA_ARGS__)\n"); | ||
497 | fprintf(f, "#define REG_VARIADIC_(macro, cnt, reg, ...) REG_VARIADIC__(macro, cnt, reg, __VA_ARGS__)\n"); | ||
498 | fprintf(f, "#define REG_VARIADIC__(macro, cnt, reg, ...) REG_VARIADIC___(macro##cnt, reg, ...)\n"); | ||
499 | fprintf(f, "#define REG_VARIADIC___(macro, reg, ...) macro(reg, __VA_ARGS__)\n\n"); | ||
500 | |||
501 | fprintf(f, "#define BM_OR(reg, ...) REG_VARIADIC(BM_OR, reg, __VA_ARGS__)\n"); | ||
502 | fprintf(f, "#define BF_OR(reg, ...) REG_VARIADIC(BF_OR, reg, __VA_ARGS__)\n"); | ||
503 | } | ||
504 | |||
505 | fprint_include_guard_ex(f, false, guard); | ||
506 | fclose(f); | ||
507 | } | ||
508 | |||
379 | void usage() | 509 | void usage() |
380 | { | 510 | { |
381 | printf("usage: headergen <desc files...> <output directory>\n"); | 511 | printf("usage: headergen [options] <desc files...> <output directory>\n"); |
512 | printf("options:\n"); | ||
513 | printf(" -?/--help Dispaly this help\n"); | ||
514 | printf(" -s/--selector Always produce selector files\n"); | ||
515 | printf(" -m/--no-macro Do not generate a macro file with helpers\n"); | ||
516 | printf(" -i/--no-include Do not include the macro file in the headers\n"); | ||
517 | printf(" -v/--no-variadic Do not generate variadic macros\n"); | ||
518 | printf("Default option is to generate a macro file with variadic macros.\n"); | ||
519 | printf("Default option is to include the macro file in the headers.\n"); | ||
520 | printf("Default option is to generate selector files only for two or more socs.\n"); | ||
521 | printf("Default option is to create one subdirectory per soc, except if no\n"); | ||
522 | printf("selector files are needed. The subdirectories will be created if\n"); | ||
523 | printf("necessary.\n"); | ||
382 | exit(1); | 524 | exit(1); |
383 | } | 525 | } |
384 | 526 | ||
385 | int main(int argc, char **argv) | 527 | int main(int argc, char **argv) |
386 | { | 528 | { |
387 | if(argc < 3) | 529 | bool force_selector = false; |
530 | bool no_variadic = false; | ||
531 | bool no_macro = false; | ||
532 | bool no_include = false; | ||
533 | if(argc <= 1) | ||
388 | usage(); | 534 | usage(); |
535 | |||
536 | while(1) | ||
537 | { | ||
538 | static struct option long_options[] = | ||
539 | { | ||
540 | {"help", no_argument, 0, '?'}, | ||
541 | {"selector", no_argument, 0, 's'}, | ||
542 | {"no-macro", no_argument, 0, 'm'}, | ||
543 | {"no-include", no_argument, 0, 'i'}, | ||
544 | {"no-variadic", no_argument, 0, 'v'}, | ||
545 | {0, 0, 0, 0} | ||
546 | }; | ||
547 | |||
548 | int c = getopt_long(argc, argv, "?smiv", long_options, NULL); | ||
549 | if(c == -1) | ||
550 | break; | ||
551 | switch(c) | ||
552 | { | ||
553 | case -1: | ||
554 | break; | ||
555 | case '?': | ||
556 | usage(); | ||
557 | break; | ||
558 | case 's': | ||
559 | force_selector = true; | ||
560 | break; | ||
561 | case 'm': | ||
562 | no_macro = true; | ||
563 | break; | ||
564 | case 'i': | ||
565 | no_include = true; | ||
566 | break; | ||
567 | case 'v': | ||
568 | no_variadic = true; | ||
569 | break; | ||
570 | default: | ||
571 | abort(); | ||
572 | } | ||
573 | } | ||
574 | |||
389 | std::vector< soc_t > socs; | 575 | std::vector< soc_t > socs; |
390 | for(int i = 1; i < argc - 1; i++) | 576 | for(int i = optind; i < argc - 1; i++) |
391 | if(!soc_desc_parse_xml(argv[i], socs)) | 577 | if(!soc_desc_parse_xml(argv[i], socs)) |
392 | { | 578 | { |
393 | printf("Cannot parse %s\n", argv[i]); | 579 | printf("Cannot parse %s\n", argv[i]); |
394 | return 1; | 580 | return 1; |
395 | } | 581 | } |
582 | |||
583 | g_gen_selector = force_selector || socs.size() > 1; | ||
584 | |||
585 | if(!no_macro) | ||
586 | { | ||
587 | g_macro_filename = std::string(argv[argc - 1]) + "/regs-macro.h"; | ||
588 | gen_macro(g_macro_filename, !no_variadic); | ||
589 | g_macro_filename = "regs-macro.h"; | ||
590 | if(no_include) | ||
591 | g_macro_filename.clear(); | ||
592 | } | ||
593 | if(g_gen_selector) | ||
594 | { | ||
595 | gen_selectors(argv[argc - 1], socs); | ||
596 | g_macro_filename.clear(); | ||
597 | } | ||
396 | gen_headers(argv[argc - 1], socs); | 598 | gen_headers(argv[argc - 1], socs); |
397 | gen_selectors(argv[argc - 1], socs); | ||
398 | return 0; | 599 | return 0; |
399 | } \ No newline at end of file | 600 | } \ No newline at end of file |