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