A modern, network-enabled music player platform built on Rockbox technology. rockboxd.tsiry-sandratraina.com
rust deno navidrome airplay libadwaita zig mpris snapcast mpd rockbox audio subsonic
2

Configure Feed

Select the types of activity you want to include in your feed.

rockboxd / utils / regtools / headergen_v1.cpp
26 kB 750 lines
1/*************************************************************************** 2 * __________ __ ___. 3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 * \/ \/ \/ \/ \/ 8 * 9 * Copyright (C) 2013 by Amaury Pouly 10 * 11 * This program is free software; you can redistribute it and/or 12 * modify it under the terms of the GNU General Public License 13 * as published by the Free Software Foundation; either version 2 14 * of the License, or (at your option) any later version. 15 * 16 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 17 * KIND, either express or implied. 18 * 19 ****************************************************************************/ 20#include "soc_desc_v1.hpp" 21#include <stdio.h> 22#include <stdlib.h> 23#include <algorithm> 24#include <map> 25#include <sstream> 26#include <sys/stat.h> 27#include <sys/types.h> 28#include <getopt.h> 29 30using namespace soc_desc_v1; 31 32#define HEADERGEN_VERSION "2.1.8" 33 34#define error(...) do{ fprintf(stderr, __VA_ARGS__); exit(1); } while(0) 35 36bool g_gen_selector = false; 37 38std::string g_macro_filename; 39 40std::string g_soc_name; 41std::string g_soc_dev; 42std::string g_soc_reg; 43std::string g_soc_field; 44std::string g_soc_dev_regs_base; 45 46namespace { 47std::string tolower(const std::string s) 48{ 49 std::string res = s; 50 std::transform(res.begin(), res.end(), res.begin(), ::tolower); 51 return res; 52} 53 54std::string toupper(const std::string& s) 55{ 56 std::string res = s; 57 std::transform(res.begin(), res.end(), res.begin(), ::toupper); 58 return res; 59} 60} 61 62template< typename T > 63std::string to_str(const T& v) 64{ 65 std::ostringstream oss; 66 oss << v; 67 return oss.str(); 68} 69 70template< typename T > 71std::string to_hex(const T& v) 72{ 73 std::ostringstream oss; 74 oss << std::hex << v; 75 return oss.str(); 76} 77 78typedef std::pair< std::string, std::string > xml_ver_t; 79 80void fprint_copyright(FILE *f, const std::vector< xml_ver_t >& versions, char const *author) 81{ 82 std::ostringstream ver; 83 time_t t = time(NULL); 84 struct tm tm = *localtime(&t); 85 86 for(size_t i = 0; i < versions.size(); i++) 87 ver << " " << versions[i].first << ":" << versions[i].second; 88 89 fprintf(f,"\ 90/***************************************************************************\n\ 91 * __________ __ ___.\n\ 92 * Open \\______ \\ ____ ____ | | _\\_ |__ _______ ___\n\ 93 * Source | _// _ \\_/ ___\\| |/ /| __ \\ / _ \\ \\/ /\n\ 94 * Jukebox | | ( <_> ) \\___| < | \\_\\ ( <_> > < <\n\ 95 * Firmware |____|_ /\\____/ \\___ >__|_ \\|___ /\\____/__/\\_ \\\n\ 96 * \\/ \\/ \\/ \\/ \\/\n\ 97 * This file was automatically generated by headergen, DO NOT EDIT it.\n\ 98 * headergen version: " HEADERGEN_VERSION "\n"); 99 if(versions.size() > 0) 100 fprintf(f, " * XML versions:%s\n", ver.str().c_str()); 101 fprintf(f,"\ 102 *\n\ 103 * Copyright (C) "); 104 fprintf(f, "%d by %s\n", 1900+tm.tm_year, author); 105 fprintf(f,"\ 106 *\n\ 107 * This program is free software; you can redistribute it and/or\n\ 108 * modify it under the terms of the GNU General Public License\n\ 109 * as published by the Free Software Foundation; either version 2\n\ 110 * of the License, or (at your option) any later version.\n\ 111 *\n\ 112 * This software is distributed on an \"AS IS\" basis, WITHOUT WARRANTY OF ANY\n\ 113 * KIND, either express or implied.\n\ 114 *\n\ 115 ****************************************************************************/\n"); 116} 117 118void fprint_copyright(FILE *f, const xml_ver_t& version, char const *author) 119{ 120 fprint_copyright(f, std::vector< xml_ver_t >(1, version), author); 121} 122 123void fprint_copyright(FILE *f, char const *author) 124{ 125 fprint_copyright(f, std::vector< xml_ver_t >(), author); 126} 127 128void fprint_include_guard_ex(FILE *f, bool begin, const std::string& name) 129{ 130 if(begin) 131 { 132 fprintf(f, "#ifndef %s\n", name.c_str()); 133 fprintf(f, "#define %s\n", name.c_str()); 134 } 135 else 136 fprintf(f, "#endif /* %s */\n", name.c_str()); 137} 138 139void fprint_include_guard(FILE *f, bool begin) 140{ 141 std::string name = "__HEADERGEN__" + toupper(g_soc_name) + "__" + toupper(g_soc_dev) 142 + "__H__"; 143 fprint_include_guard_ex(f, begin, name); 144} 145 146struct limited_column_context_t 147{ 148 limited_column_context_t(size_t nr_col = 80) 149 :m_nr_col(nr_col), m_prevent_wordcut(true) {} 150 void set_prefix(const std::string& prefix) { m_prefix = prefix; } 151 void add(const std::string& text) 152 { 153 for(size_t i = 0; i < text.size();) 154 { 155 size_t offset = 0; 156 if(m_cur_line.size() == 0) 157 m_cur_line = m_prefix; 158 size_t len = std::min(text.size() - i, m_nr_col - m_cur_line.size()); 159 // prevent word cut 160 if(m_prevent_wordcut && !isspace(text[i + len - 1]) && 161 i + len < text.size() && !isspace(text[i + len])) 162 { 163 size_t pos = text.find_last_of(" \t\n\v\r\f", i + len - 1); 164 if(pos == std::string::npos || pos < i) 165 len = 0; 166 else 167 len = pos - i + 1; 168 } 169 size_t pos = text.find('\n', i); 170 if(pos != std::string::npos && pos <= i + len) 171 { 172 offset = 1; 173 len = pos - i; 174 } 175 m_cur_line += text.substr(i, len); 176 // len == 0 means we need a new line 177 if(m_cur_line.size() == m_nr_col || len == 0) 178 { 179 m_lines.push_back(m_cur_line); 180 m_cur_line = ""; 181 } 182 i += len + offset; 183 } 184 } 185 186 std::string to_string() 187 { 188 std::string str; 189 for(size_t i = 0; i < m_lines.size(); i++) 190 str += m_lines[i] + "\n"; 191 if(m_cur_line.size() != 0) 192 str += m_cur_line + "\n"; 193 return str; 194 } 195 196 void print(FILE *f) 197 { 198 fprintf(f, "%s", to_string().c_str()); 199 } 200 201 std::vector< std::string > m_lines; 202 std::string m_cur_line; 203 std::string m_prefix; 204 size_t m_nr_col; 205 bool m_prevent_wordcut; 206}; 207 208struct define_align_context_t 209{ 210 define_align_context_t():m_max_name(0) {} 211 void add(const std::string& name, const std::string& val) 212 { 213 m_lines.push_back(std::make_pair(name, val)); 214 m_max_name = std::max(m_max_name, name.size()); 215 } 216 217 void add_raw(const std::string& line) 218 { 219 m_lines.push_back(std::make_pair("", line)); 220 } 221 222 void print(FILE *f) 223 { 224 std::string define = "#define "; 225 size_t align = define.size() + m_max_name + 1; 226 align = ((align + 3) / 4) * 4; 227 228 for(size_t i = 0; i < m_lines.size(); i++) 229 { 230 std::string name = m_lines[i].first; 231 // raw entry ? 232 if(name.size() == 0) 233 { 234 fprintf(f, "%s", m_lines[i].second.c_str()); 235 continue; 236 } 237 name.insert(name.end(), align - define.size() - name.size(), ' '); 238 fprintf(f, "%s%s%s\n", define.c_str(), name.c_str(), m_lines[i].second.c_str()); 239 } 240 } 241 242 size_t m_max_name; 243 std::vector< std::pair< std::string, std::string > > m_lines; 244}; 245 246limited_column_context_t print_description(const std::string& desc, const std::string& prefix) 247{ 248 limited_column_context_t ctx; 249 if(desc.size() == 0) 250 return ctx; 251 ctx.set_prefix(prefix); 252 ctx.add(desc); 253 return ctx; 254} 255 256void fprint_description(FILE *f, const std::string& desc, const std::string& prefix) 257{ 258 limited_column_context_t ctx = print_description(desc, prefix); 259 ctx.print(f); 260} 261 262void fprint_description(define_align_context_t& ctx, const std::string& desc, const std::string& prefix) 263{ 264 limited_column_context_t ctx2 = print_description(desc, prefix); 265 ctx.add_raw(ctx2.to_string()); 266} 267 268void gen_soc_field(define_align_context_t& ctx, bool multidev, bool multireg, const soc_reg_field_t& field) 269{ 270 if(field.desc.size() != 0) 271 { 272 ctx.add_raw("/* Field: " + field.name + "\n"); 273 fprint_description(ctx, "Description: " + field.desc + " */\n", " * "); 274 } 275 276 std::string prefix = g_soc_dev + "_" + g_soc_reg + "_" + g_soc_field; 277 ctx.add("BP_" + prefix, to_str(field.first_bit)); 278 ctx.add("BM_" + prefix, "0x" + to_hex(field.bitmask())); 279 280 for(size_t i = 0; i < field.value.size(); i++) 281 ctx.add("BV_" + prefix + "__" + field.value[i].name, "0x" + to_hex(field.value[i].value)); 282 283 ctx.add("BF_" + prefix + "(v)", "(((v) << " + to_str(field.first_bit) + ") & 0x" + to_hex(field.bitmask()) + ")"); 284 285 if(field.value.size() > 0) 286 ctx.add("BF_" + prefix + "_V(v)", "((BV_" + prefix + "__##v" + " << " + to_str(field.first_bit) + ") & 0x" + to_hex(field.bitmask()) + ")"); 287} 288 289void gen_soc_reg(FILE *f, bool multidev, const soc_reg_t& reg, char const *author, char const *hwprefix) 290{ 291 bool multireg = reg.addr.size() > 1; 292 293 static const char *suffix[] = {"", "_SET", "_CLR", "_TOG"}; 294 bool sct = !!(reg.flags & REG_HAS_SCT); 295 296 // comment generator 297 fprintf(f, "/**\n"); 298 fprintf(f, " * Register: %s%s_%s\n", hwprefix, g_soc_dev.c_str(), g_soc_reg.c_str()); 299 fprintf(f, " * Address:"); 300 if(multireg && reg.formula.type == REG_FORMULA_STRING) 301 { 302 fprintf(f, " %s\n", reg.formula.string.c_str()); 303 } 304 else 305 { 306 for(size_t i = 0; i < reg.addr.size(); i++) 307 fprintf(f, " %#x", reg.addr[i].addr); 308 fprintf(f, "\n"); 309 } 310 fprintf(f, " * SCT: %s\n", sct ? "yes" : "no"); 311 if(reg.desc.size() != 0) 312 fprint_description(f, "Description: " + reg.desc, " * "); 313 fprintf(f, " */\n"); 314 315 define_align_context_t ctx; 316 317 if (multireg && reg.formula.type != REG_FORMULA_STRING) 318 { 319 for(int i=0; i < (int)reg.addr.size(); i++) 320 { 321 std::ostringstream name, value; 322 name << hwprefix << g_soc_dev << "_" << reg.addr[i].name; 323 if (multidev) 324 { 325 name << "(d)"; 326 } 327 value << "(*(volatile unsigned long *)(" << g_soc_dev_regs_base; 328 if (multidev) 329 { 330 value << "(d)"; 331 } 332 value << " + 0x" << std::hex << reg.addr[i].addr << "))"; 333 334 ctx.add(name.str(), value.str()); 335 } 336 } 337 else 338 { 339 for(int i = 0; i < (sct ? 4 : 1); i++) 340 { 341 std::ostringstream name; 342 name << hwprefix << g_soc_dev << "_" << g_soc_reg << suffix[i]; 343 if(multidev || multireg) 344 { 345 name << "("; 346 if(multidev) 347 name << "d"; 348 if(multidev && multireg) 349 name << ","; 350 if(multireg) 351 name << "n"; 352 name << ")"; 353 } 354 std::ostringstream value; 355 value << "(*(volatile unsigned long *)(" << g_soc_dev_regs_base; 356 if(multidev) 357 value << "(d)"; 358 value << " + "; 359 if(multireg) 360 { 361 std::string formula = reg.formula.string.c_str(); 362 size_t pos = formula.find("n"); 363 while(pos != std::string::npos) 364 { 365 formula.replace(pos, 1, "(n)"); 366 pos = formula.find("n", pos + 2); 367 } 368 value << formula; 369 } 370 else 371 value << "0x" << std::hex << reg.addr[0].addr; 372 373 if(sct) 374 value << " + 0x" << std::hex << (i * 4); 375 value << "))"; 376 377 ctx.add(name.str(), value.str()); 378 } 379 } 380 381 for(size_t i = 0; i < reg.field.size(); i++) 382 { 383 g_soc_field = reg.field[i].name; 384 gen_soc_field(ctx, multidev, multireg, reg.field[i]); 385 } 386 387 ctx.print(f); 388 389 fprintf(f, "\n"); 390} 391 392void gen_soc_dev_header(const std::string& filename, const xml_ver_t& ver, const soc_dev_t& dev, 393 char const *author, char const *hwprefix) 394{ 395 /* 396 printf("Generate headers for soc %s, dev %s: use file %s\n", g_soc_name.c_str(), 397 g_soc_dev.c_str(), filename.c_str()); 398 */ 399 FILE *f = fopen(filename.c_str(), "w"); 400 if(f == NULL) 401 { 402 printf("Cannot open %s for writing: %m\n", filename.c_str()); 403 return; 404 } 405 fprint_copyright(f, ver, author); 406 fprint_include_guard(f, true); 407 if(g_macro_filename.size() > 0) 408 fprintf(f, "#include \"%s\"\n", g_macro_filename.c_str()); 409 410 /* print base */ 411 fprintf(f, "\n"); 412 g_soc_dev_regs_base = "REGS_" + g_soc_dev + "_BASE"; 413 fprintf(f, "#define %s", g_soc_dev_regs_base.c_str()); 414 415 if(dev.addr.size() > 1) 416 fprintf(f, "(i)"); 417 fprintf(f, " ("); 418 419 for(size_t i = 0; i < dev.addr.size() - 1; i++) 420 fprintf(f, "(i) == %d ? %#x : ", (int)i + 1, dev.addr[i].addr); 421 422 fprintf(f, "%#x)\n", dev.addr[dev.addr.size() - 1].addr); 423 424 fprintf(f, "\n"); 425 426 /* print version */ 427 fprintf(f, "#define REGS_%s_VERSION \"%s\"\n\n", g_soc_dev.c_str(), dev.version.c_str()); 428 429 for(size_t i = 0; i < dev.reg.size(); i++) 430 { 431 g_soc_reg = dev.reg[i].name; 432 gen_soc_reg(f, dev.addr.size() > 1, dev.reg[i], author, hwprefix); 433 } 434 435 fprint_include_guard(f, false); 436 fclose(f); 437} 438 439void gen_soc_headers(const std::string& prefix, const soc_t& soc, char const *author, char const *hwprefix) 440{ 441 printf("Generate headers for soc %s: use directory %s\n", soc.name.c_str(), 442 prefix.c_str()); 443 mkdir(prefix.c_str(), 0770); 444 445 for(size_t i = 0; i < soc.dev.size(); i++) 446 { 447 g_soc_dev = soc.dev[i].name; 448 xml_ver_t ver(soc.name, soc.dev[i].version); 449 gen_soc_dev_header(prefix + "/regs-" + tolower(g_soc_dev.c_str()) + ".h", ver, soc.dev[i], author, hwprefix); 450 } 451} 452 453void gen_headers(const std::string& prefix, const std::vector< soc_t >& socs, char const *author, char const *hwprefix) 454{ 455 for(size_t i = 0; i < socs.size(); i++) 456 { 457 g_soc_name = socs[i].name; 458 std::string dir = prefix; 459 if(g_gen_selector) 460 dir += "/" + socs[i].name; 461 gen_soc_headers(dir, socs[i], author, hwprefix); 462 } 463} 464 465typedef std::map< std::string, std::vector< std::pair< size_t, size_t > > > general_dev_list_t; 466general_dev_list_t build_general_dev_list(const std::vector< soc_t >& socs) 467{ 468 general_dev_list_t map; 469 for(size_t i = 0; i < socs.size(); i++) 470 { 471 for(size_t j = 0; j < socs[i].dev.size(); j++) 472 map[tolower(socs[i].dev[j].name)].push_back(std::make_pair(i,j)); 473 } 474 return map; 475} 476 477void gen_select_header(const std::string& filename, const std::string& dev, 478 const std::vector< std::string >& socs, const std::vector< xml_ver_t >& ver, char const *author) 479{ 480 std::string guard = "__SELECT__" + toupper(dev) + "__H__"; 481 FILE *f = fopen(filename.c_str(), "w"); 482 if(f == NULL) 483 error("Cannot open file %s\n", filename.c_str()); 484 fprint_copyright(f, ver, author); 485 fprint_include_guard_ex(f, true, guard); 486 if(g_macro_filename.size() > 0) 487 fprintf(f, "#include \"%s\"\n", g_macro_filename.c_str()); 488 fprintf(f, "\n"); 489 490 for(size_t i = 0; i < socs.size(); i++) 491 { 492 fprintf(f, "#define %s_INCLUDE \"%s/regs-%s.h\"\n", 493 toupper(socs[i]).c_str(), tolower(socs[i]).c_str(), 494 tolower(dev).c_str()); 495 } 496 fprintf(f, "\n#include \"regs-select.h\"\n\n"); 497 for(size_t i = 0; i < socs.size(); i++) 498 { 499 fprintf(f, "#undef %s_INCLUDE\n", toupper(socs[i]).c_str()); 500 } 501 fprintf(f, "\n"); 502 fprint_include_guard_ex(f, false, guard); 503 fclose(f); 504} 505 506void gen_selectors(const std::string& prefix, const std::vector< soc_t >& socs, char const *author) 507{ 508 printf("Generate select headers: use directory %s\n", prefix.c_str()); 509 general_dev_list_t map = build_general_dev_list(socs); 510 for(general_dev_list_t::iterator it = map.begin(); it != map.end(); ++it) 511 { 512 std::vector< xml_ver_t > ver; 513 std::vector< std::string > names; 514 for(size_t i = 0; i < it->second.size(); i++) 515 { 516 size_t soc_nr = it->second[i].first; 517 size_t dev_in_soc_nr = it->second[i].second; 518 ver.push_back(std::make_pair(socs[soc_nr].name, socs[soc_nr].dev[dev_in_soc_nr].version)); 519 names.push_back(socs[soc_nr].name); 520 } 521 gen_select_header(prefix + "/regs-" + it->first + ".h", it->first, names, ver, author); 522 } 523} 524 525void gen_macro_list(FILE *f, const std::string& prefix, int count, int nr_digits, 526 const std::string& sep, int max_per_line = 1000, const std::string& align = "") 527{ 528 for(int i = 1; i <= count;) 529 { 530 for(int j = i; j <= std::min(count, i + max_per_line - 1); j++) 531 { 532 fprintf(f, "%s%0*d", prefix.c_str(), nr_digits, j); 533 if(j < count) 534 fprintf(f, "%s", sep.c_str()); 535 } 536 i += max_per_line; 537 if(i <= count) 538 fprintf(f, "\\\n%s", align.c_str()); 539 } 540} 541 542void gen_macro(const std::string& filename, bool variadic, char const *author, char const *hwprefix) 543{ 544 printf("Generate %smacro header: use %s\n", variadic ? "": "non-variadic ", 545 filename.c_str()); 546 std::string guard = "__REGS__MACRO__H__"; 547 FILE *f = fopen(filename.c_str(), "w"); 548 if(f == NULL) 549 error("Cannot open file %s\n", filename.c_str()); 550 fprint_copyright(f, author); 551 fprint_include_guard_ex(f, true, guard); 552 fprintf(f, "\n"); 553 554#define REG_WRITE "REG_WRITE" 555 fprintf(f, "#ifndef %s\n", REG_WRITE); 556 fprintf(f, "#define %s(var,value) ((var) = (value))\n", REG_WRITE); 557 fprintf(f, "#endif /* %s */\n", REG_WRITE); 558 fprintf(f, "\n"); 559 560#define REG_READ "REG_READ" 561 fprintf(f, "#ifndef %s\n", REG_READ); 562 fprintf(f, "#define %s(var) (var)\n", REG_READ); 563 fprintf(f, "#endif /* %s */\n", REG_READ); 564 fprintf(f, "\n"); 565 566 const int MAX_NARGS = 32; 567 568 fprintf(f, "\ 569#define BF_SET(reg, field) " REG_WRITE "(%1$s##reg##_SET, BM_##reg##_##field)\n\ 570#define BF_CLR(reg, field) " REG_WRITE "(%1$s##reg##_CLR, BM_##reg##_##field)\n\ 571#define BF_TOG(reg, field) " REG_WRITE "(%1$s##reg##_TOG, BM_##reg##_##field)\n\ 572\n\ 573#define BF_SETV(reg, field, v) " REG_WRITE "(%1$s##reg##_SET, BF_##reg##_##field(v))\n\ 574#define BF_CLRV(reg, field, v) " REG_WRITE "(%1$s##reg##_CLR, BF_##reg##_##field(v))\n\ 575#define BF_TOGV(reg, field, v) " REG_WRITE "(%1$s##reg##_TOG, BF_##reg##_##field(v))\n\ 576\n\ 577#define BF_RDX(val, reg, field) ((" REG_READ "(val) & BM_##reg##_##field) >> BP_##reg##_##field)\n\ 578#define BF_RD(reg, field) BF_RDX(" REG_READ "(%1$s##reg), reg, field)\n\ 579#define BF_WRX(val, reg, field, v) " REG_WRITE "(val, (" REG_READ "(val) & ~BM_##reg##_##field) | (((v) << BP_##reg##_##field) & BM_##reg##_##field))\n\ 580#define BF_WR(reg, field, v) BF_WRX(%1$s##reg, reg, field, v)\n\ 581#define BF_WR_V(reg, field, sy) BF_WR(reg, field, BV_##reg##_##field##__##sy)\n\ 582#define BF_WR_VX(val, reg, field, sy) BF_WRX(val, reg, field, BV_##reg##_##field##__##sy)\n\ 583\n\ 584#define BF_SETn(reg, n, field) " REG_WRITE "(%1$s##reg##_SET(n), BM_##reg##_##field)\n\ 585#define BF_CLRn(reg, n, field) " REG_WRITE "(%1$s##reg##_CLR(n), BM_##reg##_##field)\n\ 586#define BF_TOGn(reg, n, field) " REG_WRITE "(%1$s##reg##_TOG(n), BM_##reg##_##field)\n\ 587\n\ 588#define BF_SETVn(reg, n, field, v) " REG_WRITE "(%1$s##reg##_SET(n), BF_##reg##_##field(v))\n\ 589#define BF_CLRVn(reg, n, field, v) " REG_WRITE "(%1$s##reg##_CLR(n), BF_##reg##_##field(v))\n\ 590#define BF_TOGVn(reg, n, field, v) " REG_WRITE "(%1$s##reg##_TOG(n), BF_##reg##_##field(v))\n\ 591\n\ 592#define BF_RDn(reg, n, field) BF_RDX(%1$s##reg(n), reg, field)\n\ 593#define BF_WRn(reg, n, field, v) BF_WRX(%1$s##reg(n), reg, field, v)\n\ 594#define BF_WRn_V(reg, n, field, sy) BF_WRn(reg, n, field, BV_##reg##_##field##__##sy)\n\ 595\n", hwprefix); 596 597 for(int nargs = 1; nargs <= MAX_NARGS; nargs++) 598 { 599 fprintf(f, "#define BM_OR%d(reg, ", nargs); 600 gen_macro_list(f, "f", nargs, 2, ", ", 10, " "); 601 fprintf(f, ") \\\n ("); 602 gen_macro_list(f, "BM_##reg##_##f", nargs, 2, " | ", 4, " "); 603 fprintf(f, ")\n"); 604 } 605 fprintf(f, "\n"); 606 607 for(int nargs = 1; nargs <= MAX_NARGS; nargs++) 608 { 609 fprintf(f, "#define BF_OR%d(reg, ", nargs); 610 gen_macro_list(f, "f", nargs, 2, ", ", 10, " "); 611 fprintf(f, ") \\\n ("); 612 gen_macro_list(f, "BF_##reg##_##f", nargs, 2, " | ", 4, " "); 613 fprintf(f, ")\n"); 614 } 615 fprintf(f, "\n"); 616 617 if(variadic) 618 { 619 fprintf(f, "#define REG_NARG(...) REG_NARGS_(__VA_ARGS__"); 620 for(int i = MAX_NARGS; i >= 1; i--) 621 fprintf(f, ", %d", i); 622 fprintf(f, ")\n"); 623 fprintf(f, "#define REG_NARGS_("); 624 gen_macro_list(f, "_", MAX_NARGS, 1, ", "); 625 fprintf(f, ", N, ...) N\n\n"); 626 627 fprintf(f, "#define REG_VARIADIC(macro, reg, ...) REG_VARIADIC_(macro, REG_NARG(__VA_ARGS__), reg, __VA_ARGS__)\n"); 628 fprintf(f, "#define REG_VARIADIC_(macro, cnt, reg, ...) REG_VARIADIC__(macro, cnt, reg, __VA_ARGS__)\n"); 629 fprintf(f, "#define REG_VARIADIC__(macro, cnt, reg, ...) REG_VARIADIC___(macro##cnt, reg, __VA_ARGS__)\n"); 630 fprintf(f, "#define REG_VARIADIC___(macro, reg, ...) macro(reg, __VA_ARGS__)\n\n"); 631 632 fprintf(f, "#define BM_OR(reg, ...) REG_VARIADIC(BM_OR, reg, __VA_ARGS__)\n"); 633 fprintf(f, "#define BF_OR(reg, ...) REG_VARIADIC(BF_OR, reg, __VA_ARGS__)\n"); 634 } 635 636 fprint_include_guard_ex(f, false, guard); 637 fclose(f); 638} 639 640void usage() 641{ 642 printf("usage: headergen [options] <desc files...> <output directory>\n"); 643 printf("options:\n"); 644 printf(" -?/--help Dispaly this help\n"); 645 printf(" -s/--selector Always produce selector files\n"); 646 printf(" -m/--no-macro Do not generate a macro file with helpers\n"); 647 printf(" -i/--no-include Do not include the macro file in the headers\n"); 648 printf(" -v/--no-variadic Do not generate variadic macros\n"); 649 printf(" -p/--reg-prefix \"prefix\" Prefix register names\n"); 650 printf(" -a/--author \"Author\" Set author name in preamble\n"); 651 printf("\n"); 652 printf("Default option is to generate a macro file with variadic macros.\n"); 653 printf("Default option is to include the macro file in the headers.\n"); 654 printf("Default option is to generate selector files only for two or more socs.\n"); 655 printf("Default option is to create one subdirectory per soc, except if no\n"); 656 printf("selector files are needed. The subdirectories will be created if necessary.\n"); 657 printf("Default option is to not prefix register names\n"); 658 printf("Default option is \"Unknown Author\" for author in preamble\n"); 659 exit(1); 660} 661 662int main(int argc, char **argv) 663{ 664 bool force_selector = false; 665 bool no_variadic = false; 666 bool no_macro = false; 667 bool no_include = false; 668 char const *author = "Unknown Author"; 669 char const *hwprefix = ""; 670 671 if(argc <= 1) 672 usage(); 673 674 while(1) 675 { 676 static struct option long_options[] = 677 { 678 {"help", no_argument, 0, '?'}, 679 {"selector", no_argument, 0, 's'}, 680 {"no-macro", no_argument, 0, 'm'}, 681 {"no-include", no_argument, 0, 'i'}, 682 {"no-variadic", no_argument, 0, 'v'}, 683 {"reg-prefix", required_argument, 0, 'p'}, 684 {"author", required_argument, 0, 'a'}, 685 {0, 0, 0, 0} 686 }; 687 688 int c = getopt_long(argc, argv, "?smivp:a:", long_options, NULL); 689 if(c == -1) 690 break; 691 switch(c) 692 { 693 case -1: 694 break; 695 case '?': 696 usage(); 697 break; 698 case 's': 699 force_selector = true; 700 break; 701 case 'm': 702 no_macro = true; 703 break; 704 case 'i': 705 no_include = true; 706 break; 707 case 'v': 708 no_variadic = true; 709 break; 710 case 'a' : 711 author = optarg; 712 break; 713 case 'p' : 714 hwprefix = optarg; 715 break; 716 default: 717 abort(); 718 } 719 } 720 721 std::vector< soc_t > socs; 722 for(int i = optind; i < argc - 1; i++) 723 { 724 soc_t s; 725 if(!parse_xml(argv[i], s)) 726 { 727 printf("Cannot parse %s\n", argv[i]); 728 return 1; 729 } 730 socs.push_back(s); 731 } 732 733 g_gen_selector = force_selector || socs.size() > 1; 734 735 if(!no_macro) 736 { 737 g_macro_filename = std::string(argv[argc - 1]) + "/regs-macro.h"; 738 gen_macro(g_macro_filename, !no_variadic, author, hwprefix); 739 g_macro_filename = "regs-macro.h"; 740 if(no_include) 741 g_macro_filename.clear(); 742 } 743 if(g_gen_selector) 744 { 745 gen_selectors(argv[argc - 1], socs, author); 746 g_macro_filename.clear(); 747 } 748 gen_headers(argv[argc - 1], socs, author, hwprefix); 749 return 0; 750}