A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita
audio
rust
zig
deno
mpris
rockbox
mpd
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2015 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.hpp"
22#include <cstdio>
23#include <cstdlib>
24#include <algorithm>
25#include <map>
26#include <sstream>
27#include <sys/stat.h>
28#include <sys/types.h>
29#include <getopt.h>
30#include <fstream>
31#include <set>
32
33using namespace soc_desc;
34
35#define HEADERGEN_VERSION "3.0.0"
36
37/**
38 * Useful stuff
39 */
40
41std::string tolower(const std::string s)
42{
43 std::string res = s;
44 for(size_t i = 0; i < s.size(); i++)
45 res[i] = ::tolower(res[i]);
46 return res;
47}
48
49std::string toupper(const std::string& s)
50{
51 std::string res = s;
52 for(size_t i = 0; i < s.size(); i++)
53 res[i] = ::toupper(res[i]);
54 return res;
55}
56
57template< typename T >
58std::string to_str(const T& v)
59{
60 std::ostringstream oss;
61 oss << v;
62 return oss.str();
63}
64
65template< typename T >
66std::string to_hex(const T& v)
67{
68 std::ostringstream oss;
69 oss << "0x" << std::hex << v;
70 return oss.str();
71}
72
73std::string strsubst(const std::string& str, const std::string& pattern,
74 const std::string& subst)
75{
76 std::string res = str;
77 size_t pos = 0;
78 while((pos = res.find(pattern, pos)) != std::string::npos)
79 {
80 res.replace(pos, pattern.size(), subst);
81 pos += subst.size();
82 }
83 return res;
84}
85
86void print_context(const error_context_t& ctx)
87{
88 for(size_t j = 0; j < ctx.count(); j++)
89 {
90 err_t e = ctx.get(j);
91 switch(e.level())
92 {
93 case err_t::INFO: printf("[INFO]"); break;
94 case err_t::WARNING: printf("[WARN]"); break;
95 case err_t::FATAL: printf("[FATAL]"); break;
96 default: printf("[UNK]"); break;
97 }
98 if(e.location().size() != 0)
99 printf(" %s:", e.location().c_str());
100 printf(" %s\n", e.message().c_str());
101 }
102}
103
104void print_inst(node_inst_t inst, bool end = true)
105{
106 if(!inst.is_root())
107 {
108 print_inst(inst.parent(), false);
109 printf(".%s", inst.name().c_str());
110 if(inst.is_indexed())
111 printf("[%u]", (unsigned)inst.index());
112 }
113 else
114 {
115 printf("%s", inst.soc().get()->name.c_str());
116 }
117 if(end)
118 printf("\n");
119}
120
121void create_dir(const std::string& path)
122{
123 mkdir(path.c_str(), 0755);
124}
125
126void create_alldir(const std::string& prefix, const std::string& path)
127{
128 size_t p = path.find('/');
129 if(p == std::string::npos)
130 return;
131 create_dir(prefix + "/" + path.substr(0, p));
132 create_alldir(prefix + "/" + path.substr(0, p), path.substr(p + 1));
133}
134
135/**
136 * Printer utils
137 */
138
139struct limited_column_context_t
140{
141 limited_column_context_t(size_t nr_col = 80)
142 :m_nr_col(nr_col), m_prevent_wordcut(true) {}
143 void set_prefix(const std::string& prefix) { m_prefix = prefix; }
144 void add(const std::string& text)
145 {
146 for(size_t i = 0; i < text.size();)
147 {
148 size_t offset = 0;
149 if(m_cur_line.size() == 0)
150 m_cur_line = m_prefix;
151 size_t len = std::min(text.size() - i, m_nr_col - m_cur_line.size());
152 // prevent word cut
153 if(m_prevent_wordcut && !isspace(text[i + len - 1]) &&
154 i + len < text.size() && !isspace(text[i + len]))
155 {
156 size_t pos = text.find_last_of(" \t\n\v\r\f", i + len - 1);
157 if(pos == std::string::npos || pos < i)
158 len = 0;
159 else
160 len = pos - i + 1;
161 }
162 size_t pos = text.find('\n', i);
163 if(pos != std::string::npos && pos <= i + len)
164 {
165 offset = 1;
166 len = pos - i;
167 }
168 m_cur_line += text.substr(i, len);
169 // len == 0 means we need a new line
170 if(m_cur_line.size() == m_nr_col || len == 0)
171 {
172 m_lines.push_back(m_cur_line);
173 m_cur_line = "";
174 }
175 i += len + offset;
176 }
177 }
178
179 std::ostream& print(std::ostream& oss)
180 {
181 for(size_t i = 0; i < m_lines.size(); i++)
182 oss << m_lines[i] << "\n";
183 if(m_cur_line.size() != 0)
184 oss << m_cur_line << "\n";
185 return oss;
186 }
187
188 std::string str()
189 {
190 std::ostringstream oss;
191 print(oss);
192 return oss.str();
193 }
194
195 std::vector< std::string > m_lines;
196 std::string m_cur_line;
197 std::string m_prefix;
198 size_t m_nr_col;
199 bool m_prevent_wordcut;
200};
201
202struct define_align_context_t
203{
204 define_align_context_t():m_max_name(0) {}
205 void add(const std::string& name, const std::string& val)
206 {
207 m_lines.push_back(std::make_pair(name, val));
208 m_max_name = std::max(m_max_name, name.size());
209 }
210
211 void add_raw(const std::string& line)
212 {
213 m_lines.push_back(std::make_pair("", line));
214 }
215
216 std::ostream& print(std::ostream& oss)
217 {
218 std::string define = "#define ";
219 size_t align = define.size() + m_max_name + 1;
220 align = ((align + 3) / 4) * 4;
221
222 for(size_t i = 0; i < m_lines.size(); i++)
223 {
224 std::string name = m_lines[i].first;
225 // raw entry ?
226 if(name.size() != 0)
227 {
228 name.insert(name.end(), align - define.size() - name.size(), ' ');
229 oss << define << name << m_lines[i].second << "\n";
230 }
231 else
232 oss << m_lines[i].second;
233 }
234 return oss;
235 }
236
237 size_t m_max_name;
238 std::vector< std::pair< std::string, std::string > > m_lines;
239};
240
241limited_column_context_t print_description(const std::string& desc, const std::string& prefix)
242{
243 limited_column_context_t ctx;
244 if(desc.size() == 0)
245 return ctx;
246 ctx.set_prefix(prefix);
247 ctx.add(desc);
248 return ctx;
249}
250
251void print_copyright(std::ostream& fout, const std::vector< soc_ref_t >& socs)
252{
253 fout << "\
254/***************************************************************************\n\
255 * __________ __ ___.\n\
256 * Open \\______ \\ ____ ____ | | _\\_ |__ _______ ___\n\
257 * Source | _// _ \\_/ ___\\| |/ /| __ \\ / _ \\ \\/ /\n\
258 * Jukebox | | ( <_> ) \\___| < | \\_\\ ( <_> > < <\n\
259 * Firmware |____|_ /\\____/ \\___ >__|_ \\|___ /\\____/__/\\_ \\\n\
260 * \\/ \\/ \\/ \\/ \\/\n\
261 * This file was automatically generated by headergen, DO NOT EDIT it.\n\
262 * headergen version: " HEADERGEN_VERSION "\n";
263 for(size_t i = 0; i < socs.size(); i++)
264 {
265 soc_t& s = *socs[i].get();
266 if(!s.version.empty())
267 fout << " * " << s.name << " version: " << s.version << "\n";
268 if(!s.author.empty())
269 {
270 fout << " * " << s.name << " authors:";
271 for(size_t j = 0; j < s.author.size(); j++)
272 {
273 if(j != 0)
274 fout << ",";
275 fout << " " << s.author[j];
276 }
277 fout << "\n";
278 }
279 }
280 fout << "\
281 *\n\
282 * Copyright (C) 2015 by the authors\n\
283 *\n\
284 * This program is free software; you can redistribute it and/or\n\
285 * modify it under the terms of the GNU General Public License\n\
286 * as published by the Free Software Foundation; either version 2\n\
287 * of the License, or (at your option) any later version.\n\
288 *\n\
289 * This software is distributed on an \"AS IS\" basis, WITHOUT WARRANTY OF ANY\n\
290 * KIND, either express or implied.\n\
291 *\n\
292 ****************************************************************************/\n";
293}
294
295void print_guard(std::ostream& fout, const std::string& guard, bool begin)
296{
297 if(begin)
298 {
299 fout << "#ifndef " << guard << "\n";
300 fout << "#define " << guard << "\n";
301 }
302 else
303 fout << "\n#endif /* " << guard << "*/\n";
304}
305
306/**
307 * Generator interface
308 */
309
310class abstract_generator
311{
312public:
313 /// set output directory (default is current directory)
314 void set_output_dir(const std::string& dir);
315 /// add a SoC to the list
316 void add_soc(const soc_t& soc);
317 /// generate headers, returns true on success
318 virtual bool generate(error_context_t& ctx) = 0;
319protected:
320 std::vector< soc_t > m_soc; /// list of socs
321 std::string m_outdir; /// output directory path
322};
323
324void abstract_generator::set_output_dir(const std::string& dir)
325{
326 m_outdir = dir;
327}
328
329void abstract_generator::add_soc(const soc_t& soc)
330{
331 m_soc.push_back(soc);
332}
333
334/**
335 * Common Generator
336 *
337 * This generator is an abstract class which can generate register headers while
338 * giving the user a lot of control on how the macros are named and generated.
339 *
340 * The first thing the generator will want to know is whether you want to generate
341 * selector headers or not. Selector headers are used when generating headers from
342 * several SoCs: the selector will include the right header based on some user-defined
343 * logic. For example, imagine you have two socs vsoc1000 and vsoc2000, you could
344 * generate the following files and directories:
345 *
346 * regs/
347 * regs-vsoc.h [selector]
348 * vsoc1000/
349 * regs-vsoc.h [vsoc1000 header]
350 * vsoc2000/
351 * regs-vsoc.h [vsoc2000 header]
352 *
353 * The generator will call has_selectors() to determine if it should generate
354 * selector files or not. If it returns true, it will call selector_soc_dir()
355 * for each of the socs to know in which subdirectory it should include the headers.
356 * The generator will create one macro per soc, which name is given by
357 * selector_soc_macro() and it will finally include the select header YOU will
358 * have to write, which name is given by selector_include_header()
359 * The selector file will typically look like this:
360 *
361 * [regs-vsoc.h]
362 * #define VSOC1000_INCLUDE "vsoc1000/regs-vsoc.h" // returned by selector_soc_macro(vsoc1000)
363 * #define VSOC2000_INCLUDE "vsoc2000/regs-vsoc.h" // returned by selector_soc_macro(vsoc2000)
364 * #include "regs-select.h" // returned by selector_include_header()
365 *
366 * NOTE: it may happen that some header only exists in some soc (for example
367 * in vsoc2000 but not in vsoc1000), in this case the macros will only be
368 * generated for the socs in which it exists.
369 * NOTE: and this is *VERY* important: the register selector file MUST NOT
370 * be protected by include guards since it will included several times, once
371 * for each register file.
372 *
373 * The generator will create one set of files per soc. For each register, it
374 * will call register_header() to determine in which file you want the register
375 * to be put. You can put everything in one file, or one register per file,
376 * that's entirely up to you. Here is an example:
377 *
378 * register_header(vsoc1000.cpu.ctrl) -> "regs-cpu.h"
379 * register_header(vsoc1000.cpu.reset) -> "regs-cpu.h"
380 * register_header(vsoc1000.cop.ctrl) -> "regs-cop.h"
381 * register_header(vsoc1000.cop.magic) -> "regs-magic.h"
382 *
383 * regs-cpu.h:
384 * vsoc1000.cpu.ctrl
385 * vsoc1000.cpu.reset
386 * regs-cop.h:
387 * vsoc1000.cop.ctrl
388 * regs-magic.h
389 * vsoc1000.cop.magic
390 *
391 * Once the list of register files is determine, it will begin generating each
392 * file. A register header is always protected from double inclusion by an
393 * include guard. You can tweak the name by redefining header_include_guard()
394 * or keep the default behaviour which generates something like this:
395 *
396 * #ifndef __HEADERGEN_REGS_CPU_H__
397 * #define __HEADERGEN_REGS_CPU_H__
398 * ...
399 * #endif
400 *
401 * NOTE: the tool will also generate a copyright header which contains the Rockbox
402 * logo, a list of soc names and version, and authors in the description file.
403 * This part cannot be customised at the moment.
404 *
405 * In order to list all registers, the generator will recursively enumerate all
406 * nodes and instances. When a instance is of RANGE type, the generator can generate
407 * two types of macros:
408 * - one for each instance
409 * - one with an index parameter
410 * The generator will ask you if you want to generate one for each instance by
411 * calling register_flag(RF_GENERATE_ALL_INST) and if you want to generate a
412 * parametrized one by calling register_flag(RF_GENERATE_PARAM_INST). You can
413 * generate either one or both (or none).
414 *
415 * register_flag(vsoc.int.enable, RF_GENERATE_ALL_INST) -> true
416 * => will generate vsoc.int.enable[1], vsoc.int.enable[2], ...
417 * register_flag(vsoc.int.enable, RF_GENERATE_PARAM_INST) -> true
418 * => will generate vsoc.int.enable[n]
419 *
420 * This process will give a list of pseudo-instances: these are register instances
421 * where some ranges have a given index and some ranges are parametric. The generator
422 * will create one set of macro per pseudo-instance. The exact list of macros
423 * generated is the following:
424 * - ADDR: this macro will contain the address of the register (possibly parametrized)
425 * - TYPE: this macro will contain the type of the register (width, access)
426 * - NAME: this macro expands to the name of the register (useful for fields and other variants)
427 * - INDEX: this macro expands to the index of the register (or empty is not indexed)
428 * - VAR: this macros expands to a fake variable that can be read/written
429 * - for each field F:
430 * - BP: this macro contains the bit position of F
431 * - BM: this macro contains the bit mask of F
432 * - for each field enum value V:
433 * - BV: this macro contains the value of V (not shifted to the position)
434 * - BF: this macro generate the mask for a value: (((v) << pos) & mask)
435 * - BFV: same as BF but the parameter is the name of an enum value
436 * - BFM: this macro is like BF but ignores value returns mask
437 * - BFMV: like BFV but returns masks like BFM
438 * The generator will also create the following macros for each variant:
439 * - ADDR: same as ADDR but with offset
440 * - TYPE: same as TYPE but depends on variant
441 * - NAME: same as NAME (ie same fields)
442 * - INDEX: same as INDEX
443 *
444 * In order to generate the macro name, the generate relies on you providing detailled
445 * information. Given an pseudo-instance I and a macro type MT, the generator
446 * will always call type_xfix(MT) to know which prefix/suffix you want for the
447 * macro and generate names of the form:
448 * type_xfix(MT, true)basename(I)type_xfix(MT, false)
449 * The basename() functions will call inst_prefix() for each each instance on the
450 * pseudo-instance path, and then instance_name() to know the name. You can
451 * (and must) create a different name for parametrised instances. The basename
452 * looks like this for pseudo-inst i1.i2.i3....in:
453 * instance_name(i1)inst_prefix(i1.i2)instance_name(i1.i2)...inst_name(i1.i2...in)
454 * For field macros, the process is the same with an extra prefix returned by
455 * field_prefix() and you can select the field name with field_name() to obtain
456 * for example for field F in I:
457 * type_xfix(MT,true)basename(I)field_prefix()field_name(I.F)type_xfix(MT,false)
458 * For field enum macros, there is an extra prefix given by enum_prefix()
459 * and the enum name is given by enum_name()
460 * For variants, the basename is surrounded by prefix/suffix given by variant_xfix():
461 * variant_xfix(var, true)basename(I)variant_xfix(var, false)
462 *
463 * Let's illustrate this on example
464 * type_xfix(MT_REG_ADDR, true) -> "RA_x"
465 * type_xfix(MT_REG_ADDR, false) -> "x_AR"
466 * instance_name(vsoc1000.cpu) -> "CPU"
467 * inst_prefix(vsoc1000.cpu.ctrl) -> "_"
468 * instance_name(vsoc1000.cpu.ctrl) -> "CTRL"
469 * => RA_xCPU_CTRLx_AR
470 * type_xfix(MT_FIELD_BF, true) -> "BF_"
471 * type_xfix(MT_FIELD_BF, false) -> ""
472 * field_prefix() -> "__"
473 * field_name(vsoc1000.cpu.ctrl.speed) -> "SPEED"
474 * => BF_CPU_CTRL__SPEED
475 * variant_xfix("set", true) -> "VAR_"
476 * variant_xfix("set", false) -> "_SET"
477 * => HW_VAR_CPU_CTRL_SET
478 *
479 * The generator will also create a macro header file, it will call macro_header()
480 * once to know the name of this file.
481 * The macro header contains useful macro to read, write and manipulate registers
482 * and fields. You must implement the macro_header_macro() method to let the
483 * generator know the name of each macro. Note that the macro header macros
484 * depend on the specific naming of the other macros, which are given by
485 * type_xfix() and field_prefix() most notably. The exact list of generated macros
486 * is the following:
487 * - BF_OR: field ORing (see details below)
488 * - BF_OM: mask ORing (same as BF_OR but except field value is the mask)
489 *
490 * The BF_OR macro is one of the most important and useful macro. It allows for
491 * compact ORing of register field, both for immediate values or value names.
492 * For this macro to work properly, there are constraints that the generator
493 * must satisfy. Notably, type_xfix(MT_FIELD_BF, true) == type_xfix(MT_FIELD_BFV, true)
494 * and similarly for MT_FIELD_BM
495 * The general format is as follows:
496 *
497 * BF_OR(<reg>, <f1>, <f2>, ...) expands to BF(<reg>,<f1>) | BF(<reg>,<f2>) | ...
498 * BM_OR(<reg>, <f1>, <f2>, ...) expands to BM(<reg>,<f1>) | BM(<reg>,<f2>) | ...
499 *
500 * Typical usages of this macro will be of the form:
501 *
502 * BF_OR(<reg>, <f1>(<v1>), <f2>(<v2>), <f3name>(<v3name>), ...)
503 * BM_OR(<reg>, <f1>, <f2>, <f3>, ...)
504 *
505 *
506 * Let's illustrate this on example.
507 * type_xfix(MT_FIELD_BF, true) -> "BF_"
508 * type_xfix(MT_FIELD_BFV, true) -> "BF_"
509 * type_xfix(MT_FIELD_BF, false) -> "BF_"
510 * type_xfix(MT_FIELD_BF, false) -> "_V"
511 * field_prefix() -> "__"
512 * enum_prefix() -> "___"
513 * macro_header_macro(MMM_BF_OR) -> "BF_OR"
514 * => BF_OR(<reg>, <f1>, <f2>, ...) expands to BF_<reg>__<f1> | BF_<reg>__<f2> | ...
515 * => BF_OR(CPU_CTRL, DIVIDER(1), PRIO_V(HIGH), SPEED(100))
516 * expands to
517 * BF_CPU_CTRL__DIVIDER(1) | BF_CPU_CTRL__DIVIDER_V(HIGH) | BF_CPU_CTRL__SPEED(1000)
518 * expands to
519 * BF_CPU_CTRL__DIVIDER(1) | BF_CPU_CTRL__DIVIDER(BV_CPU_CTRL__DIVIDER___HIGH) | BF_CPU_CTRL__SPEED(1000)
520 * and so on...
521 *
522 */
523class common_generator : public abstract_generator
524{
525 struct pseudo_node_inst_t
526 {
527 node_inst_t inst;
528 std::vector< bool > parametric;
529 };
530public:
531 virtual bool generate(error_context_t& ctx);
532protected:
533 /// return true to generate support macros
534 /// if false then all macros are disabled except MT_REG_ADDR, MT_REG_VAR,
535 /// and MT_FIELD_*. Also the macro header is not created
536 virtual bool has_support_macros() const = 0;
537 /// return true to generate selector files
538 virtual bool has_selectors() const = 0;
539 /// return true to generate node address and register offset macros
540 virtual bool has_offsets() const = 0;
541 /// [selector only] return the directory name for the soc
542 virtual std::string selector_soc_dir(const soc_ref_t& ref) const = 0;
543 /// [selector only] return the header to include to select betweens socs
544 virtual std::string selector_include_header() const = 0;
545 /// [selector only] return the name of the macro to emit for each soc
546 virtual std::string selector_soc_macro(const soc_ref_t& ref) const = 0;
547 /// return the relative filename in which to put the register
548 virtual std::string register_header(const node_inst_t& inst) const = 0;
549 /// return the include guard for a file (default does its best)
550 virtual std::string header_include_guard(const std::string& filename);
551 /// return the name of the macros header to generate
552 virtual std::string macro_header() const = 0;
553 /// macro from macro header
554 enum macro_name_t
555 {
556 MN_REG_READ, /// register read
557 MN_FIELD_READ, /// register's field read
558 MN_FIELD_READX, /// register value field read
559 MN_REG_WRITE, /// register write
560 MN_REG_SET, /// register set
561 MN_REG_CLEAR, /// register clear
562 MN_REG_CLEAR_SET, /// register clear then set
563 MN_FIELD_WRITE, /// register's field(s) write
564 MN_FIELD_WRITEX, /// register's field(s) write
565 MN_FIELD_OVERWRITE, /// register full write
566 MN_FIELD_SET, /// register's field(s) set
567 MN_FIELD_CLEAR, /// register's field(s) clear
568 MN_FIELD_TOG, /// register's field(s) toggle
569 MN_FIELD_CLEAR_SET, /// register's field(s) clear then set
570 MN_FIELD_OR, /// field ORing
571 MN_FIELD_OR_MASK, /// field ORing but in fact mask ORing
572 MN_MASK_OR, /// mask ORing
573 MN_GET_VARIANT, /// get register variant
574 MN_VARIABLE, /// return variable-like for register
575 };
576 /// return macro name defined in the macro header
577 virtual std::string macro_name(macro_name_t macro, bool relative = false) const = 0;
578 /// flag to consider
579 enum register_flag_t
580 {
581 RF_GENERATE_ALL_INST, /// for range instance, generate one macro set per instance ?
582 RF_GENERATE_PARAM_INST, /// for range instance, generate a parametrised macro set ?
583 };
584 /** tweak instance generaton and its children
585 * NOTE: for range flags, although the instance will be numbered, the index is
586 * to be ignored */
587 virtual bool register_flag(const node_inst_t& inst, register_flag_t flag) const = 0;
588 /// prefix/suffix type
589 enum macro_type_t
590 {
591 MT_NODE_ADDR, /// node address
592 MT_REG_ADDR, /// register address
593 MT_REG_OFFSET, /// register address relative to parent node
594 MT_REG_TYPE, /// register type
595 MT_REG_NAME, /// register prefix for fields
596 MT_REG_INDEX, /// register index/indices
597 MT_REG_VAR, /// variable-like macro
598 MT_FIELD_BP, /// bit position of a field
599 MT_FIELD_BM, /// bit mask of a field
600 MT_FIELD_BV, /// bit value of a field enum
601 MT_FIELD_BF, /// bit field value: (v << pos) & mask
602 MT_FIELD_BFM, /// ignore value and return mask
603 MT_FIELD_BFV, /// bit field enum value: (enum_v << pos) & mask
604 MT_FIELD_BFMV, /// ignore value and return mask
605 MT_IO_TYPE, /// register io type
606 };
607 /// register access types
608 enum access_type_t
609 {
610 AT_RO, /// read-only: write are disallowed
611 AT_RW, /// read-write: read/writes are allowed, field write by generated a RMW
612 AT_WO, /// write-only: read are disallowed, field write will set other fields to 0
613 };
614 /// register operation
615 enum register_op_t
616 {
617 RO_VAR, /// variable-like
618 RO_READ, /// read
619 RO_WRITE, /// write
620 RO_RMW, /// read-modify-write
621 };
622 /// return type prefix/suffix for register macro
623 virtual std::string type_xfix(macro_type_t type, bool prefix) const = 0;
624 /// return variant prefix/suffix
625 virtual std::string variant_xfix(const std::string& variant, bool prefix) const = 0;
626 /// return instance prefix in macro name
627 virtual std::string inst_prefix(const node_inst_t& inst) const = 0;
628 /// return field prefix in field macro names
629 virtual std::string field_prefix() const = 0;
630 /// return field enum prefix in field macro names
631 virtual std::string enum_prefix() const = 0;
632 /// return the field enum name in field macro names
633 virtual std::string enum_name(const enum_ref_t& enum_) const = 0;
634 /// return instance name in macro, default is instance name then index if any
635 virtual std::string instance_name(const node_inst_t& inst, bool parametric) const;
636 /// return field name in macro, default is field name
637 virtual std::string field_name(const field_ref_t& field) const;
638 /// return the complete macro name with prefix, default uses all the other functions
639 virtual std::string macro_basename(const pseudo_node_inst_t& inst) const;
640 /// return the complete macro name with prefix, default uses macro_basename()
641 virtual std::string macro_basename(const pseudo_node_inst_t& inst, macro_type_t type) const;
642 /// generate address string for a register instance, and fill the parametric
643 /// argument list, default does it the obvious way and parameters are _n1, _n2, ...
644 virtual std::string register_address(const pseudo_node_inst_t& reg,
645 std::vector< std::string >& params, bool offset_only = false) const;
646 /// return access type for a variant and a given register access
647 /// NOTE variant with the unspecified access type will be promoted to register access
648 virtual access_type_t register_access(const std::string& variant, access_t access) const = 0;
649 /// return register type name
650 virtual std::string register_type_name(access_type_t access, int width) const;
651 /// get register operation name
652 virtual std::string register_op_name(register_op_t op, bool relative = false) const;
653 /// register operation prefix
654 virtual std::string register_op_prefix() const;
655 /// generate a macro pasting that is safe even when macro is empty
656 /// ie: safe_macro_paste(false, "A") -> ##A
657 /// ie: safe_macro_paste(false, "A") ->
658 std::string safe_macro_paste(bool left, const std::string& macro) const;
659 /// generate SCT macros using register variant ?
660 virtual bool has_sct() const = 0;
661 /// return the associated SCT variant (only if RF_GENERATE_SCT)
662 /// empty means don't generate
663 virtual std::string sct_variant(macro_name_t name) const = 0;
664
665private:
666 void gather_files(const pseudo_node_inst_t& inst, const std::string& prefix,
667 std::map< std::string, std::vector< pseudo_node_inst_t > >& map);
668 void print_inst(const pseudo_node_inst_t& inst, bool end = true); // debug
669 std::vector< soc_ref_t > list_socs(const std::vector< pseudo_node_inst_t >& list);
670 bool generate_register(std::ostream& os, const pseudo_node_inst_t& reg);
671 bool generate_node(std::ostream& os, const pseudo_node_inst_t& node);
672 std::string generate_param_str(const std::vector<std::string>& params);
673 void generate_macro_type_ops(access_type_t at, int width, bool relative,
674 define_align_context_t& ctx);
675 void generate_macro_reg_ops(const std::string& bf_readx,
676 const std::string& bf_or,
677 bool relative, std::ofstream& fout);
678 bool generate_macro_header(error_context_t& ectx);
679};
680
681std::string common_generator::instance_name(const node_inst_t& inst, bool parametric) const
682{
683 std::ostringstream oss;
684 oss << inst.name();
685 if(inst.is_indexed() && !parametric)
686 oss << inst.index();
687 return oss.str();
688}
689
690std::string common_generator::field_name(const field_ref_t& field) const
691{
692 return field.get()->name;
693}
694
695std::string common_generator::macro_basename(const pseudo_node_inst_t& inst_) const
696{
697 pseudo_node_inst_t inst = inst_;
698 std::string str;
699 while(!inst.inst.is_root())
700 {
701 str = instance_name(inst.inst, inst.parametric.back()) + str;
702 inst.inst = inst.inst.parent();
703 inst.parametric.pop_back();
704 if(!inst.inst.is_root())
705 str = inst_prefix(inst.inst) + str;
706 }
707 return str;
708}
709
710std::string common_generator::macro_basename(const pseudo_node_inst_t& inst, macro_type_t type) const
711{
712 return type_xfix(type, true) + macro_basename(inst);
713}
714
715void common_generator::print_inst(const pseudo_node_inst_t& inst, bool end)
716{
717 if(!inst.inst.is_root())
718 {
719 pseudo_node_inst_t p = inst;
720 p.inst = p.inst.parent();
721 p.parametric.pop_back();
722 print_inst(p, false);
723 printf(".%s", inst.inst.name().c_str());
724 if(inst.inst.is_indexed())
725 {
726 if(inst.parametric.back())
727 printf("[]");
728 else
729 printf("[%u]", (unsigned)inst.inst.index());
730 }
731 }
732 else
733 {
734 printf("%s", inst.inst.soc().get()->name.c_str());
735 }
736 if(end)
737 printf("\n");
738}
739
740std::string common_generator::register_type_name(access_type_t access, int width) const
741{
742 std::ostringstream oss;
743 oss << width << "_";
744 switch(access)
745 {
746 case AT_RO: oss << "RO"; break;
747 case AT_RW: oss << "RW"; break;
748 case AT_WO: oss << "WO"; break;
749 default: oss << "error"; break;
750 }
751 return type_xfix(MT_IO_TYPE, true) + oss.str() + type_xfix(MT_IO_TYPE, false);
752}
753
754std::string common_generator::register_op_name(register_op_t op, bool relative) const
755{
756 switch(op)
757 {
758 case RO_VAR: return relative ? "VARREL" : "VAR";
759 case RO_READ: return relative ? "RDREL" : "RD";
760 case RO_WRITE: return relative ? "WRREL" : "WR";
761 case RO_RMW: return relative ? "RMWREL" : "RMW";
762 default: return "<op>";
763 }
764}
765
766std::string common_generator::register_op_prefix() const
767{
768 return "_";
769}
770
771std::string common_generator::safe_macro_paste(bool left, const std::string& macro) const
772{
773 if(macro.size() == 0)
774 return "";
775 return left ? "##" + macro : macro + "##";
776}
777
778void common_generator::gather_files(const pseudo_node_inst_t& inst, const std::string& prefix,
779 std::map< std::string, std::vector< pseudo_node_inst_t > >& map)
780{
781 if(!inst.inst.is_root())
782 map[prefix + register_header(inst.inst)].push_back(inst);
783
784 // if asked, generate one for each instance
785 std::vector< node_inst_t > list = inst.inst.children();
786 for(size_t i = 0; i < list.size(); i++)
787 {
788 pseudo_node_inst_t c = inst;
789 c.inst = list[i];
790 if(!list[i].is_indexed() || register_flag(inst.inst, RF_GENERATE_ALL_INST))
791 {
792 c.parametric.push_back(false);
793 gather_files(c, prefix, map);
794 c.parametric.pop_back();
795 }
796 if(list[i].is_indexed() && register_flag(list[i], RF_GENERATE_PARAM_INST))
797 {
798 bool first = list[i].index() == list[i].get()->range.first;
799 if(first)
800 {
801 c.parametric.push_back(true);
802 gather_files(c, prefix, map);
803 }
804 }
805 }
806}
807
808std::vector< soc_ref_t > common_generator::list_socs(const std::vector< pseudo_node_inst_t >& list)
809{
810 std::set< soc_ref_t > socs;
811 std::vector< pseudo_node_inst_t >::const_iterator it = list.begin();
812 for(; it != list.end(); ++it)
813 socs.insert(it->inst.soc());
814 std::vector< soc_ref_t > soc_list;
815 for(std::set< soc_ref_t >::iterator jt = socs.begin(); jt != socs.end(); ++jt)
816 soc_list.push_back(*jt);
817 return soc_list;
818}
819
820std::string common_generator::header_include_guard(const std::string& filename)
821{
822 std::string guard = "__HEADERGEN_" + toupper(filename) + "__";
823 for(size_t i = 0; i < guard.size(); i++)
824 if(!isalnum(guard[i]))
825 guard[i] = '_';
826 return guard;
827}
828
829std::string common_generator::register_address(const pseudo_node_inst_t& reg,
830 std::vector< std::string >& params, bool offset_only) const
831{
832 std::ostringstream oss;
833 unsigned counter = 1;
834 size_t start_index = offset_only ? reg.parametric.size() - 1 : 0;
835 oss << "(";
836 for(size_t i = start_index; i < reg.parametric.size(); i++)
837 {
838 if(i != start_index)
839 oss << " + ";
840
841 node_inst_t ninst = reg.inst.parent(reg.parametric.size() - i - 1);
842 instance_t& inst = *ninst.get();
843 if(reg.parametric[i])
844 params.push_back("_n" + to_str(counter++));
845 if(inst.type == instance_t::RANGE)
846 {
847 if(inst.range.type == range_t::STRIDE)
848 {
849 if(reg.parametric[i])
850 {
851 oss << to_hex(inst.range.base) << " + ";
852 oss << "(" << params.back() << ") * " << to_hex(inst.range.stride);
853 }
854 else
855 oss << to_hex(inst.range.base + ninst.index() * inst.range.stride);
856 }
857 else if(inst.range.type == range_t::FORMULA)
858 {
859 if(!reg.parametric[i])
860 {
861 soc_word_t res;
862 std::map< std::string, soc_word_t > vars;
863 vars[inst.range.variable] = ninst.index();
864 error_context_t ctx;
865 if(!evaluate_formula(inst.range.formula, vars, res, "", ctx))
866 oss << "#error cannot evaluate formula";
867 else
868 oss << to_hex(res);
869 }
870 else
871 oss << strsubst(inst.range.formula, inst.range.variable,
872 "(" + params.back() + ")");
873 }
874 else if(inst.range.type == range_t::LIST)
875 {
876 if(reg.parametric[i])
877 {
878 oss << "(";
879 for(size_t j = 0; j + 1 < inst.range.list.size(); j++)
880 {
881 oss << "(" << params.back() << ") == " << (inst.range.first + j)
882 << " ? " << to_hex(inst.range.list[j]) << " : ";
883 }
884 oss << to_hex(inst.range.list.back()) << ")";
885 }
886 else
887 oss << to_hex(inst.range.list[ninst.index() - inst.range.first]);
888 }
889 else
890 {
891 return "#error unknown range type";
892 }
893 }
894 else if(inst.type == instance_t::SINGLE)
895 oss << to_hex(inst.addr);
896 else if (inst.type == instance_t::FLOATING)
897 return "";
898 else
899 return "#error unknown instance type";
900 }
901 oss << ")";
902 return oss.str();
903}
904
905bool common_generator::generate_register(std::ostream& os, const pseudo_node_inst_t& reg)
906{
907 os << "\n";
908 define_align_context_t ctx;
909 std::vector< std::string > addr_params;
910 std::vector< std::string > offset_params;
911 std::string addr = register_address(reg, addr_params);
912 std::string offset = register_address(reg, offset_params, true);
913 std::string basename = macro_basename(reg);
914 std::string addr_param_str = generate_param_str(addr_params);
915 std::string offset_param_str = generate_param_str(offset_params);
916 std::string bp_prefix = macro_basename(reg, MT_FIELD_BP) + field_prefix();
917 std::string bm_prefix = macro_basename(reg, MT_FIELD_BM) + field_prefix();
918 std::string bf_prefix = macro_basename(reg, MT_FIELD_BF) + field_prefix();
919 std::string bfm_prefix = macro_basename(reg, MT_FIELD_BFM) + field_prefix();
920 std::string bfv_prefix = macro_basename(reg, MT_FIELD_BFV) + field_prefix();
921 std::string bfmv_prefix = macro_basename(reg, MT_FIELD_BFMV) + field_prefix();
922 bool has_addr = !addr.empty();
923
924 register_ref_t regr = reg.inst.node().reg();
925 /* handle register the same way as variants */
926 std::vector< std::string > var_prefix;
927 std::vector< std::string > var_suffix;
928 std::vector< std::string > var_addr;
929 std::vector< std::string > var_offset;
930 std::vector< access_type_t > var_access;
931
932 var_prefix.push_back("");
933 var_suffix.push_back("");
934 var_access.push_back(register_access("", regr.get()->access));
935 if(has_addr)
936 var_addr.push_back(addr);
937 var_offset.push_back(offset);
938
939 std::vector< variant_ref_t > variants = regr.variants();
940 for(size_t i = 0; i < variants.size(); i++)
941 {
942 var_prefix.push_back(variant_xfix(variants[i].type(), true));
943 var_suffix.push_back(variant_xfix(variants[i].type(), false));
944 if (has_addr)
945 {
946 var_addr.push_back("(" + type_xfix(MT_REG_ADDR, true) + basename +
947 type_xfix(MT_REG_ADDR, false) + addr_param_str + " + " +
948 to_hex(variants[i].offset()) + ")");
949 }
950 var_offset.push_back("(" + type_xfix(MT_REG_OFFSET, true) + basename +
951 type_xfix(MT_REG_OFFSET, false) + offset_param_str + " + " +
952 to_hex(variants[i].offset()));
953 access_t acc = variants[i].get()->access;
954 if(acc == UNSPECIFIED)
955 acc = regr.get()->access; // fallback to register access
956 var_access.push_back(register_access(variants[i].type(), acc));
957 }
958
959 for(size_t i = 0; i < var_prefix.size(); i++)
960 {
961 std::string var_basename = var_prefix[i] + basename + var_suffix[i];
962 std::string macro_var = type_xfix(MT_REG_VAR, true) + var_basename +
963 type_xfix(MT_REG_VAR, false);
964 std::string macro_addr = type_xfix(MT_REG_ADDR, true) + var_basename +
965 type_xfix(MT_REG_ADDR, false);
966 std::string macro_offset = type_xfix(MT_REG_OFFSET, true) + var_basename +
967 type_xfix(MT_REG_OFFSET, false);
968 std::string macro_type = type_xfix(MT_REG_TYPE, true) + var_basename +
969 type_xfix(MT_REG_TYPE, false);
970 std::string macro_prefix = type_xfix(MT_REG_NAME, true) + var_basename +
971 type_xfix(MT_REG_NAME, false);
972 std::string macro_index = type_xfix(MT_REG_INDEX, true) + var_basename +
973 type_xfix(MT_REG_INDEX, false);
974 /* print VAR macro:
975 * if we have support macros then we generate something like HW(basename)
976 * where HW is some support macros to support complex operations. Otherwise
977 * we just generate something like (*(volatile unsigned uintN_t)basename_addr) */
978 if (has_addr)
979 {
980 if(!has_support_macros())
981 {
982 std::ostringstream oss;
983 oss << "(*(volatile uint" << regr.get()->width << "_t *)" <<
984 macro_addr + addr_param_str << ")";
985 ctx.add(macro_var + addr_param_str, oss.str());
986 }
987 else
988 {
989 ctx.add(macro_var + addr_param_str, macro_name(MN_VARIABLE) +
990 "(" + var_basename + addr_param_str + ")");
991 }
992
993 /* print ADDR macro */
994 ctx.add(macro_addr + addr_param_str, var_addr[i]);
995 }
996 else
997 ctx.add(macro_var + addr_param_str, macro_name(MN_VARIABLE) + "(" + var_basename + addr_param_str + ")");
998
999 if(has_offsets())
1000 {
1001 /* print OFFSET macro */
1002 ctx.add(macro_offset + offset_param_str, var_offset[i]);
1003 }
1004
1005 /* disable macros if needed */
1006 if(has_support_macros())
1007 {
1008 /* print TYPE macro */
1009 ctx.add(macro_type + addr_param_str, register_type_name(var_access[i], regr.get()->width));
1010 /* print PREFIX macro */
1011 ctx.add(macro_prefix + addr_param_str, basename);
1012
1013 if(has_sct())
1014 {
1015 /* print INDEX macro */
1016 ctx.add(macro_index + addr_param_str, addr_param_str);
1017 }
1018 }
1019 }
1020 /* print fields */
1021 std::vector< field_ref_t > fields = regr.fields();
1022 for(size_t i = 0; i < fields.size(); i++)
1023 {
1024 /* print BP macro: pos */
1025 std::string fname = field_name(fields[i]);
1026 ctx.add(bp_prefix + fname + type_xfix(MT_FIELD_BP, false),
1027 to_str(fields[i].get()->pos));
1028 /* print BM macro: mask */
1029 ctx.add(bm_prefix + fname + type_xfix(MT_FIELD_BM, false),
1030 to_hex(fields[i].get()->bitmask()));
1031 std::vector< enum_ref_t > enums = fields[i].enums();
1032 std::string bv_prefix = macro_basename(reg, MT_FIELD_BV) + field_prefix()
1033 + fname + enum_prefix();
1034 /* print BV macros: enum_v */
1035 for(size_t j = 0; j < enums.size(); j++)
1036 ctx.add(bv_prefix + enum_name(enums[j]) + type_xfix(MT_FIELD_BV, false),
1037 to_hex(enums[j].get()->value));
1038 /* print BF macro: (((v) & mask) << pos) */
1039 ctx.add(bf_prefix + fname + type_xfix(MT_FIELD_BF, false) + "(v)",
1040 "(((v) & " + to_hex(fields[i].get()->unshifted_bitmask()) + ") << " +
1041 to_str(fields[i].get()->pos) + ")");
1042 /* print BFM macro: masl */
1043 ctx.add(bfm_prefix + fname + type_xfix(MT_FIELD_BFM, false) + "(v)",
1044 bm_prefix + fname + type_xfix(MT_FIELD_BM, false));
1045 /* print BFV macro: ((enum_v) << pos) & mask) */
1046 ctx.add(bfv_prefix + fname + type_xfix(MT_FIELD_BFV, false) + "(e)",
1047 bf_prefix + fname + type_xfix(MT_FIELD_BF, false) + "(" +
1048 bv_prefix + "##e)");
1049 /* print BFMV macro: masl */
1050 ctx.add(bfmv_prefix + fname + type_xfix(MT_FIELD_BFMV, false) + "(v)",
1051 bm_prefix + fname + type_xfix(MT_FIELD_BM, false));
1052 }
1053
1054 ctx.print(os);
1055 return true;
1056}
1057
1058bool common_generator::generate_node(std::ostream& os, const pseudo_node_inst_t& node)
1059{
1060 define_align_context_t ctx;
1061 std::vector< std::string > params;
1062 std::string addr = register_address(node, params);
1063 std::string basename = macro_basename(node);
1064 std::string param_str = generate_param_str(params);
1065 std::string macro_addr = type_xfix(MT_NODE_ADDR, true) + basename +
1066 type_xfix(MT_NODE_ADDR, false);
1067 bool has_addr = !addr.empty();
1068
1069 if (has_addr)
1070 {
1071 os << "\n";
1072 ctx.add(macro_addr + param_str, addr);
1073 }
1074
1075 ctx.print(os);
1076 return true;
1077}
1078
1079std::string common_generator::generate_param_str(const std::vector<std::string>& params)
1080{
1081 std::string param_str;
1082
1083 if(params.size() > 0)
1084 {
1085 param_str = "(";
1086
1087 for(size_t i = 0; i < params.size(); i++)
1088 param_str += (i == 0 ? "" : ",") + params[i];
1089
1090 param_str += ")";
1091 }
1092
1093 return param_str;
1094}
1095
1096void common_generator::generate_macro_type_ops(access_type_t at, int width, bool relative,
1097 define_align_context_t& ctx)
1098{
1099 std::string io_type = register_type_name(at, width);
1100 macro_type_t mt = relative ? MT_REG_OFFSET : MT_REG_ADDR;
1101 std::string args = relative ? "name, base" : "name";
1102 std::string reg_addr = safe_macro_paste(false, type_xfix(mt, true))
1103 + "name" + safe_macro_paste(true, type_xfix(mt, false));
1104
1105 if(relative)
1106 reg_addr = "(base) + " + reg_addr;
1107
1108 // read
1109 std::ostringstream oss;
1110 if(at == AT_RO)
1111 oss << "(*(const volatile uint" << width << "_t *)(" << reg_addr << "))";
1112 else if(at == AT_RW)
1113 oss << "(*(volatile uint" << width << "_t *)(" << reg_addr << "))";
1114 else
1115 oss << "({_Static_assert(0, #name \" is write-only\"); 0;})";
1116 ctx.add(io_type + register_op_prefix() + register_op_name(RO_READ, relative) + "(" + args + ", ...)",
1117 oss.str());
1118 // write
1119 oss.str("");
1120 if(at != AT_RO)
1121 oss << "(*(volatile uint" << width << "_t *)(" << reg_addr << ")) = (val)";
1122 else
1123 oss << "_Static_assert(0, #name \" is read-only\")";
1124 ctx.add(io_type + register_op_prefix() + register_op_name(RO_WRITE, relative) + "(" + args + ", val)",
1125 oss.str());
1126 // read-modify-write
1127 oss.str("");
1128 if(at == AT_RW)
1129 {
1130 oss << io_type << register_op_prefix() << register_op_name(RO_WRITE, relative) + "(" + args + ", ";
1131 oss << "(" << io_type << register_op_prefix() << register_op_name(RO_READ, relative) + "(" + args + ") & (vand))";
1132 oss << " | (vor))";
1133 }
1134 else if(at == AT_WO)
1135 oss << io_type << register_op_prefix() << register_op_name(RO_WRITE, relative) + "(" + args + ", vor)";
1136 else
1137 oss << "_Static_assert(0, #name \" is read-only\")";
1138 ctx.add(io_type + register_op_prefix() + register_op_name(RO_RMW, relative) + "(" + args + ", vand, vor)",
1139 oss.str());
1140 // variable
1141 oss.str("");
1142 if(at == AT_RO)
1143 oss << "(*(const volatile uint" << width << "_t *)(" << reg_addr << "))";
1144 else
1145 oss << "(*(volatile uint" << width << "_t *)(" << reg_addr << "))";
1146 ctx.add(io_type + register_op_prefix() + register_op_name(RO_VAR, relative) + "(" + args + ", ...)",
1147 oss.str());
1148}
1149
1150void common_generator::generate_macro_reg_ops(const std::string& bf_readx,
1151 const std::string& bf_or,
1152 bool relative, std::ofstream& fout)
1153{
1154 std::string args = relative ? "base, name" : "name";
1155 std::string argswap = relative ? "name, base" : "name";
1156 std::string argbase = relative ? "base, " : "";
1157 std::string docline;
1158
1159 if(relative)
1160 docline = " * register address is calculated by offsetting from the base address\n";
1161
1162 /* print REG_READ macro */
1163 std::string reg_read = macro_name(MN_REG_READ, relative);
1164 fout << "/** " << reg_read << "\n";
1165 fout << " *\n";
1166 fout << " * usage: " << reg_read << "(" << argbase << "register)\n";
1167 fout << " *\n";
1168 fout << " * effect: read the register and return its value\n";
1169 fout << docline;
1170 fout << " * note: register must be fully qualified if indexed\n";
1171 fout << " *\n";
1172 fout << " * example: " << reg_read << "(" << argbase << "ICOLL_STATUS)\n";
1173 fout << " * " << reg_read << "(" << argbase << "ICOLL_ENABLE(42))\n";
1174 fout << " */\n";
1175 fout << "#define " << reg_read << "(" << args << ") "
1176 << safe_macro_paste(false, type_xfix(MT_REG_TYPE, true)) << "name"
1177 << safe_macro_paste(true, type_xfix(MT_REG_TYPE, false))
1178 << "(" << register_op_name(RO_READ, relative) << ", " << argswap << ")\n";
1179 fout << "\n";
1180
1181 /* print FIELD_READ macro */
1182 std::string bf_read = macro_name(MN_FIELD_READ, relative);
1183 fout << "/** " << bf_read << "\n";
1184 fout << " *\n";
1185 fout << " * usage: " << bf_read << "(" << argbase << "register, field)\n";
1186 fout << " *\n";
1187 fout << " * effect: read a register and return the value of a particular field\n";
1188 fout << docline;
1189 fout << " * note: register must be fully qualified if indexed\n";
1190 fout << " *\n";
1191 fout << " * example: " << bf_read << "(" << argbase << "ICOLL_CTRL, SFTRST)\n";
1192 fout << " * " << bf_read << "(" << argbase << "ICOLL_ENABLE(3), CPU0_PRIO)\n";
1193 fout << " */\n";
1194 fout << "#define " << bf_read << "(" << args << ", field) " << bf_read << "_("
1195 << reg_read << "(" << args << "), " << safe_macro_paste(false, type_xfix(MT_REG_NAME, true))
1196 << "name" << safe_macro_paste(true, type_xfix(MT_REG_NAME, false)) << ", field)\n";
1197 fout << "#define " << bf_read << "_(...) " << bf_readx << "(__VA_ARGS__)\n";
1198 fout << "\n";
1199
1200 /* print REG_WRITE macro */
1201 std::string reg_write = macro_name(MN_REG_WRITE, relative);
1202 fout << "/** " << reg_write << "\n";
1203 fout << " *\n";
1204 fout << " * usage: " << reg_write << "(" << argbase << "register, value)\n";
1205 fout << " *\n";
1206 fout << " * effect: write a register\n";
1207 fout << docline;
1208 fout << " * note: register must be fully qualified if indexed\n";
1209 fout << " *\n";
1210 fout << " * example: " << reg_write << "(" << argbase << "ICOLL_CTRL, 0x42)\n";
1211 fout << " * " << reg_write << "(" << argbase << "ICOLL_ENABLE_SET(3), 0x37)\n";
1212 fout << " */\n";
1213 fout << "#define " << reg_write << "(" << args << ", val) "
1214 << safe_macro_paste(false, type_xfix(MT_REG_TYPE, true)) << "name"
1215 << safe_macro_paste(true, type_xfix(MT_REG_TYPE, false))
1216 << "(" << register_op_name(RO_WRITE, relative) << ", " << argswap << ", val)\n";
1217 fout << "\n";
1218
1219 /* print FIELD_WRITE macro */
1220 std::string bf_write = macro_name(MN_FIELD_WRITE, relative);
1221 fout << "/** " << bf_write << "\n";
1222 fout << " *\n";
1223 fout << " * usage: " << bf_write << "(" << argbase << "register, f1(v1), f2(v2), ...)\n";
1224 fout << " *\n";
1225 fout << " * effect: change the register value so that field fi has value vi\n";
1226 fout << docline;
1227 fout << " * note: register must be fully qualified if indexed\n";
1228 fout << " * note: this macro may perform a read-modify-write\n";
1229 fout << " *\n";
1230 fout << " * example: " << bf_write << "(" << argbase << "ICOLL_CTRL, SFTRST(1), CLKGATE(0), TZ_LOCK_V(UNLOCKED))\n";
1231 fout << " * " << bf_write << "(" << argbase << "ICOLL_ENABLE(3), CPU0_PRIO(1), CPU0_TYPE_V(FIQ))\n";
1232 fout << " */\n";
1233 fout << "#define " << bf_write << "(" << args << ", ...) "
1234 << bf_write << "_(" << args << ", " << safe_macro_paste(false, type_xfix(MT_REG_NAME, true))
1235 << "name" << safe_macro_paste(true, type_xfix(MT_REG_NAME, false)) << ", __VA_ARGS__)\n";
1236 fout << "#define " << bf_write << "_(" << args << ", name2, ...) "
1237 << safe_macro_paste(false, type_xfix(MT_REG_TYPE, true)) << "name"
1238 << safe_macro_paste(true, type_xfix(MT_REG_TYPE, false))
1239 << "(" << register_op_name(RO_RMW, relative) << ", " << argswap << ", "
1240 << "~" << macro_name(MN_FIELD_OR_MASK) << "(name2, __VA_ARGS__), "
1241 << macro_name(MN_FIELD_OR) << "(name2, __VA_ARGS__))\n";
1242 fout << "\n";
1243
1244 /* print FIELD_OVERWRITE macro */
1245 std::string bf_overwrite = macro_name(MN_FIELD_OVERWRITE, relative);
1246 fout << "/** " << bf_overwrite << "\n";
1247 fout << " *\n";
1248 fout << " * usage: " << bf_overwrite << "(" << argbase << "register, f1(v1), f2(v2), ...)\n";
1249 fout << " *\n";
1250 fout << " * effect: change the register value so that field fi has value vi and other fields have value zero\n";
1251 fout << docline;
1252 fout << " * thus this macro is equivalent to:\n";
1253 fout << " * " << reg_write << "(" << argbase << "register, " << bf_or << "(register, f1(v1), ...))\n";
1254 fout << " * note: register must be fully qualified if indexed\n";
1255 fout << " * note: this macro will overwrite the register (it is NOT a read-modify-write)\n";
1256 fout << " *\n";
1257 fout << " * example: " << bf_overwrite << "(ICOLL_CTRL, SFTRST(1), CLKGATE(0), TZ_LOCK_V(UNLOCKED))\n";
1258 fout << " * " << bf_overwrite << "(ICOLL_ENABLE(3), CPU0_PRIO(1), CPU0_TYPE_V(FIQ))\n";
1259 fout << " */\n";
1260 fout << "#define " << bf_overwrite << "(" << args << ", ...) "
1261 << bf_overwrite << "_(" << args << ", " << safe_macro_paste(false, type_xfix(MT_REG_NAME, true))
1262 << "name" << safe_macro_paste(true, type_xfix(MT_REG_NAME, false)) << ", __VA_ARGS__)\n";
1263 fout << "#define " << bf_overwrite << "_(" << args << ", name2, ...) "
1264 << safe_macro_paste(false, type_xfix(MT_REG_TYPE, true)) << "name"
1265 << safe_macro_paste(true, type_xfix(MT_REG_TYPE, false))
1266 << "(" << register_op_name(RO_WRITE, relative) << ", " << argswap << ", "
1267 << macro_name(MN_FIELD_OR) << "(name2, __VA_ARGS__))\n";
1268 fout << "\n";
1269
1270 /* print FIELD_SET/FIELD_CLEAR macro */
1271 for(int i = 0; i < 2; i++)
1272 {
1273 macro_name_t n = (i == 0) ? MN_FIELD_SET : MN_FIELD_CLEAR;
1274 std::string bf_set = macro_name(n, relative);
1275 std::string set_var = sct_variant(n);
1276
1277 fout << "/** " << bf_set << "\n";
1278 fout << " *\n";
1279 fout << " * usage: " << bf_set << "(" << argbase << "register, f1, f2, ...)\n";
1280 fout << " *\n";
1281 fout << " * effect: change the register value so that field fi has ";
1282 if(i == 0)
1283 fout << "maximum value\n";
1284 else
1285 fout << "value zero\n";
1286 fout << docline;
1287 if(has_sct())
1288 fout << " * IMPORTANT: this macro performs a write to the " << set_var << " variant of the register\n";
1289 else
1290 fout << " * note: this macro will perform a read-modify-write\n";
1291
1292 fout << " * note: register must be fully qualified if indexed\n";
1293 fout << " *\n";
1294 fout << " * example: " << bf_set << "(" << argbase << "ICOLL_CTRL, SFTRST, CLKGATE)\n";
1295 fout << " * " << bf_set << "(" << argbase << "ICOLL_ENABLE(3), CPU0_PRIO, CPU0_TYPE)\n";
1296 fout << " */\n";
1297
1298 if(has_sct())
1299 {
1300 fout << "#define " << bf_set << "(" << args << ", ...) " << bf_set << "_(" << argbase
1301 << macro_name(MN_GET_VARIANT) << "(name, " << variant_xfix(set_var, true)
1302 << ", " << variant_xfix(set_var, false) << "), "
1303 << safe_macro_paste(false, type_xfix(MT_REG_NAME, true))
1304 << "name" << safe_macro_paste(true, type_xfix(MT_REG_NAME, false))
1305 << ", __VA_ARGS__)\n";
1306 fout << "#define " << bf_set << "_(" << args << ", name2, ...) " << macro_name(MN_REG_WRITE, relative)
1307 << "(" << args << ", " << macro_name(MN_MASK_OR) << "(name2, __VA_ARGS__))\n";
1308 }
1309 else
1310 {
1311 fout << "#define " << bf_set << "(" << args << ", ...) "
1312 << bf_set << "_(" << args << ", " << safe_macro_paste(false, type_xfix(MT_REG_NAME, true))
1313 << "name" << safe_macro_paste(true, type_xfix(MT_REG_NAME, false)) << ", __VA_ARGS__)\n";
1314 fout << "#define " << bf_set << "_(" << args << ", name2, ...) "
1315 << safe_macro_paste(false, type_xfix(MT_REG_TYPE, true)) << "name"
1316 << safe_macro_paste(true, type_xfix(MT_REG_TYPE, false))
1317 << "(" << register_op_name(RO_RMW, relative) << ", " << argswap << ", ~";
1318 if(i == 0)
1319 fout << "0," << macro_name(MN_MASK_OR) << "(name2, __VA_ARGS__))\n";
1320 else
1321 fout << macro_name(MN_MASK_OR) << "(name2, __VA_ARGS__), 0)\n";
1322 }
1323 fout << "\n";
1324 }
1325
1326 if(has_sct())
1327 {
1328 std::string set_var = sct_variant(MN_FIELD_SET);
1329 std::string clr_var = sct_variant(MN_FIELD_CLEAR);
1330
1331 /* print REG_SET */
1332 std::string reg_set = macro_name(MN_REG_SET, relative);
1333 fout << "/** " << reg_set << "\n";
1334 fout << " *\n";
1335 fout << " * usage: " << reg_set << "(" << argbase << "register, set_value)\n";
1336 fout << " *\n";
1337 fout << " * effect: set some bits using " << set_var << " variant\n";
1338 fout << docline;
1339 fout << " * note: register must be fully qualified if indexed\n";
1340 fout << " *\n";
1341 fout << " * example: " << reg_set << "(" << argbase << "ICOLL_CTRL, 0x42)\n";
1342 fout << " * " << reg_set << "(" << argbase << "ICOLL_ENABLE(3), 0x37)\n";
1343 fout << " */\n";
1344 fout << "#define " << reg_set << "(" << args << ", sval) "
1345 << reg_set << "_(" << argbase << macro_name(MN_GET_VARIANT) << "(name, "
1346 << variant_xfix(set_var, true) << ", " << variant_xfix(set_var, false)
1347 << "), sval)\n";
1348 fout << "#define " << reg_set << "_(" << args << ", sval) "
1349 << macro_name(MN_REG_WRITE, relative) << "(" << args << ", sval)\n";
1350 fout << "\n";
1351
1352 /* print REG_CLR */
1353 std::string reg_clr = macro_name(MN_REG_CLEAR, relative);
1354 fout << "/** " << reg_clr << "\n";
1355 fout << " *\n";
1356 fout << " * usage: " << reg_clr << "(" << argbase << "register, clr_value)\n";
1357 fout << " *\n";
1358 fout << " * effect: clear some bits using " << clr_var << " variant\n";
1359 fout << docline;
1360 fout << " * note: register must be fully qualified if indexed\n";
1361 fout << " *\n";
1362 fout << " * example: " << reg_clr << "(" << argbase << "ICOLL_CTRL, 0x42)\n";
1363 fout << " * " << reg_clr << "(" << argbase << "ICOLL_ENABLE(3), 0x37)\n";
1364 fout << " */\n";
1365 fout << "#define " << reg_clr << "(" << args << ", cval) "
1366 << reg_clr << "_(" << argbase << macro_name(MN_GET_VARIANT) << "(name, "
1367 << variant_xfix(clr_var, true) << ", " << variant_xfix(clr_var, false)
1368 << "), cval)\n";
1369 fout << "#define " << reg_clr << "_(" << args << ", cval) "
1370 << macro_name(MN_REG_WRITE, relative) << "(" << args << ", cval)\n";
1371 fout << "\n";
1372
1373 /* print REG_CS */
1374 std::string reg_cs = macro_name(MN_REG_CLEAR_SET, relative);
1375 fout << "/** " << reg_cs << "\n";
1376 fout << " *\n";
1377 fout << " * usage: " << reg_cs << "(" << argbase << "register, clear_value, set_value)\n";
1378 fout << " *\n";
1379 fout << " * effect: clear some bits using " << clr_var << " variant and then set some using " << set_var << " variant\n";
1380 fout << docline;
1381 fout << " * note: register must be fully qualified if indexed\n";
1382 fout << " *\n";
1383 fout << " * example: " << reg_cs << "(" << argbase << "ICOLL_CTRL, 0xff, 0x42)\n";
1384 fout << " * " << reg_cs << "(" << argbase << "ICOLL_ENABLE(3), 0xff, 0x37)\n";
1385 fout << " */\n";
1386 fout << "#define " << reg_cs << "(" << args << ", cval, sval) "
1387 << reg_cs << "_(" << argbase << macro_name(MN_GET_VARIANT) << "(name, "
1388 << variant_xfix(clr_var, true) << ", " << variant_xfix(clr_var, false) << "), "
1389 << macro_name(MN_GET_VARIANT) << "(name, " << variant_xfix(set_var, true)
1390 << ", " << variant_xfix(set_var, false) << "), cval, sval)\n";
1391 fout << "#define " << reg_cs << "_(" << argbase << "cname, sname, cval, sval) "
1392 << "do { " << macro_name(MN_REG_WRITE) << "(" << argbase << "cname, cval); "
1393 << macro_name(MN_REG_WRITE, relative) << "(" << argbase << "sname, sval); } while(0)\n";
1394 fout << "\n";
1395
1396 /* print BF_CS */
1397 std::string bf_cs = macro_name(MN_FIELD_CLEAR_SET, relative);
1398 fout << "/** " << bf_cs << "\n";
1399 fout << " *\n";
1400 fout << " * usage: " << bf_cs << "(" << argbase << "register, f1(v1), f2(v2), ...)\n";
1401 fout << " *\n";
1402 fout << " * effect: change the register value so that field fi has value vi using " << clr_var << " and " << set_var << " variants\n";
1403 fout << docline;
1404 fout << " * note: register must be fully qualified if indexed\n";
1405 fout << " * note: this macro will NOT perform a read-modify-write and is thus safer\n";
1406 fout << " * IMPORTANT: this macro will set some fields to 0 temporarily, make sure this is acceptable\n";
1407 fout << " *\n";
1408 fout << " * example: " << bf_cs << "(" << argbase << "ICOLL_CTRL, SFTRST(1), CLKGATE(0), TZ_LOCK_V(UNLOCKED))\n";
1409 fout << " * " << bf_cs << "(" << argbase << "ICOLL_ENABLE(3), CPU0_PRIO(1), CPU0_TYPE_V(FIQ))\n";
1410 fout << " */\n";
1411 fout << "#define " << bf_cs << "(" << args << ", ...) "
1412 << bf_cs << "_(" << args << ", " << safe_macro_paste(false, type_xfix(MT_REG_NAME, true))
1413 << "name" << safe_macro_paste(true, type_xfix(MT_REG_NAME, false)) << ", __VA_ARGS__)\n";
1414 fout << "#define " << bf_cs << "_(" << args << ", name2, ...) "
1415 << macro_name(MN_REG_CLEAR_SET, relative) << "(" << args << ", " << macro_name(MN_FIELD_OR_MASK)
1416 << "(name2, __VA_ARGS__), " << macro_name(MN_FIELD_OR) << "(name2, __VA_ARGS__))\n";
1417 fout << "\n";
1418 }
1419
1420 /* print REG_VAR macro */
1421 std::string reg_var = macro_name(MN_VARIABLE, relative);
1422 fout << "/** " << reg_var << "\n";
1423 fout << " *\n";
1424 fout << " * usage: " << reg_var << "(" << argbase << "register)\n";
1425 fout << " *\n";
1426 fout << " * effect: return a variable-like expression that can be read/written\n";
1427 fout << docline;
1428 fout << " * note: register must be fully qualified if indexed\n";
1429 fout << " * note: read-only registers will yield a constant expression\n";
1430 fout << " *\n";
1431 fout << " * example: unsigned x = " << reg_var << "(" << argbase << "ICOLL_STATUS)\n";
1432 fout << " * unsigned x = " << reg_var << "(" << argbase << "ICOLL_ENABLE(42))\n";
1433 fout << " * " << reg_var << "(" << argbase << "ICOLL_ENABLE(42)) = 64\n";
1434 fout << " */\n";
1435 fout << "#define " << reg_var << "(" << args << ") "
1436 << safe_macro_paste(false, type_xfix(MT_REG_TYPE, true)) << "name"
1437 << safe_macro_paste(true, type_xfix(MT_REG_TYPE, false))
1438 << "(" << register_op_name(RO_VAR, relative) << ", " << args << ")\n";
1439 fout << "\n";
1440}
1441
1442bool common_generator::generate_macro_header(error_context_t& ectx)
1443{
1444 /* only generate if we need support macros */
1445 if(!has_support_macros())
1446 return true;
1447 std::ofstream fout((m_outdir + "/" + macro_header()).c_str());
1448 if(!fout)
1449 {
1450 printf("Cannot create '%s'\n", (m_outdir + "/" + macro_header()).c_str());
1451 return false;
1452 }
1453 print_copyright(fout, std::vector< soc_ref_t >());
1454 std::string guard = header_include_guard(macro_header());
1455 print_guard(fout, guard, true);
1456 fout << "\n";
1457
1458 /* ensure that types uintXX_t are defined */
1459 fout << "#include <stdint.h>\n\n";
1460
1461 /* print variadic OR macros:
1462 * __VAR_OR1(prefix, suffix) expands to prefix##suffix
1463 * and more n>=2, using multiple layers of macros:
1464 * __VAR_ORn(pre, s01, s02, ..., sn) expands to pre##s01 | .. | pre##sn */
1465 std::string var_or = "__VAR_OR";
1466 const int MAX_N = 20;
1467
1468 fout << "#define " << var_or << "1(prefix, suffix) \\\n";
1469 fout << " (prefix##suffix)\n";
1470 for(int n = 2; n <= MAX_N; n++)
1471 {
1472 fout << "#define " << var_or << n << "(pre";
1473 for(int j = 1; j <= n; j++)
1474 fout << ", s" << j;
1475 fout << ") \\\n";
1476 /* dichotmoty: expands ORn using ORj and ORk where j=n/2 and k=n-j */
1477 int half = n / 2;
1478 fout << " (" << var_or << half << "(pre";
1479 for(int j = 1; j <= half; j++)
1480 fout << ", s" << j;
1481 fout << ") | " << var_or << (n - half) << "(pre";
1482 for(int j = half + 1; j <= n; j++)
1483 fout << ", s" << j;
1484 fout << "))\n";
1485 }
1486 fout << "\n";
1487
1488 /* print macro to compute number of arguments */
1489 std::string var_nargs = "__VAR_NARGS";
1490
1491 fout << "#define " << var_nargs << "(...) " << var_nargs << "_(__VA_ARGS__";
1492 for(int i = MAX_N; i >= 1; i--)
1493 fout << ", " << i;
1494 fout << ")\n";
1495 fout << "#define " << var_nargs << "_(";
1496 for(int i = 1; i <= MAX_N; i++)
1497 fout << "_" << i << ", ";
1498 fout << "N, ...) N\n\n";
1499
1500 /* print macro for variadic register macros */
1501 std::string var_expand = "__VAR_EXPAND";
1502
1503 fout << "#define " << var_expand << "(macro, prefix, ...) "
1504 << var_expand << "_(macro, " << var_nargs << "(__VA_ARGS__), prefix, __VA_ARGS__)\n";
1505 fout << "#define " << var_expand << "_(macro, cnt, prefix, ...) "
1506 << var_expand << "__(macro, cnt, prefix, __VA_ARGS__)\n";
1507 fout << "#define " << var_expand << "__(macro, cnt, prefix, ...) "
1508 << var_expand << "___(macro##cnt, prefix, __VA_ARGS__)\n";
1509 fout << "#define " << var_expand << "___(macro, prefix, ...) "
1510 << "macro(prefix, __VA_ARGS__)\n\n";
1511
1512 /* print type macros */
1513 define_align_context_t ctx;
1514 access_type_t at[3] = { AT_RO, AT_RW, AT_WO };
1515 int width[3] = { 8, 16, 32 };
1516 for(int i = 0; i < 3; i++)
1517 {
1518 for(int j = 0; j < 3; j++)
1519 {
1520 std::string io_type = register_type_name(at[i], width[j]);
1521 ctx.add(io_type + "(op, name, ...)", io_type + register_op_prefix() + "##op(name, __VA_ARGS__)");
1522
1523 generate_macro_type_ops(at[i], width[j], false, ctx);
1524
1525 if(has_offsets())
1526 generate_macro_type_ops(at[i], width[j], true, ctx);
1527
1528 ctx.add_raw("\n");
1529 }
1530 }
1531 ctx.print(fout);
1532 fout << "\n";
1533
1534 if(has_sct())
1535 {
1536 /* print GET_VARIANT macro */
1537 std::string get_var = macro_name(MN_GET_VARIANT);
1538 fout << "/** " << get_var << "\n";
1539 fout << " *\n";
1540 fout << " * usage: " << get_var << "(register, variant_prefix, variant_postfix)\n";
1541 fout << " *\n";
1542 fout << " * effect: expands to register variant given as argument\n";
1543 fout << " * note: internal usage\n";
1544 fout << " * note: register must be fully qualified if indexed\n";
1545 fout << " *\n";
1546 fout << " * example: " << get_var << "(ICOLL_CTRL, , _SET)\n";
1547 fout << " * example: " << get_var << "(ICOLL_ENABLE(3), , _CLR)\n";
1548 fout << " */\n";
1549 fout << "#define " << get_var << "(name, varp, vars) "
1550 << get_var << "_(" << safe_macro_paste(false, type_xfix(MT_REG_NAME, true))
1551 << "name" << safe_macro_paste(true, type_xfix(MT_REG_NAME, false)) << ", "
1552 << safe_macro_paste(false, type_xfix(MT_REG_INDEX, true))
1553 << "name" << safe_macro_paste(true, type_xfix(MT_REG_INDEX, false)) << ", varp, vars)\n";
1554 fout << "#define " << get_var << "_(...) " << get_var << "__(__VA_ARGS__)\n";
1555 fout << "#define " << get_var << "__(name, index, varp, vars) "
1556 << "varp##name##vars index\n";
1557 fout << "\n";
1558 }
1559
1560 /* print BF_OR macro */
1561 std::string bf_or = macro_name(MN_FIELD_OR);
1562 fout << "/** " << bf_or << "\n";
1563 fout << " *\n";
1564 fout << " * usage: " << bf_or << "(register, f1(v1), f2(v2), ...)\n";
1565 fout << " *\n";
1566 fout << " * effect: expands to the register value where each field fi has value vi.\n";
1567 fout << " * Informally: reg_f1(v1) | reg_f2(v2) | ...\n";
1568 fout << " * note: enumerated values for fields can be obtained by using the syntax:\n";
1569 fout << " * f1" << type_xfix(MT_FIELD_BFV, false) << "(name)\n";
1570 fout << " *\n";
1571 fout << " * example: " << bf_or << "(ICOLL_CTRL, SFTRST(1), CLKGATE(0), TZ_LOCK_V(UNLOCKED))\n";
1572 fout << " */\n";
1573 fout << "#define " << bf_or << "(reg, ...) "
1574 << var_expand << "(" << var_or << ", " << type_xfix(MT_FIELD_BF, true)
1575 << "##reg##" << field_prefix() << ", __VA_ARGS__)\n";
1576 fout << "\n";
1577
1578 /* print BF_OR macro */
1579 std::string bfm_or = macro_name(MN_FIELD_OR_MASK);
1580 fout << "/** " << bfm_or << "\n";
1581 fout << " *\n";
1582 fout << " * usage: " << bfm_or << "(register, f1(v1), f2(v2), ...)\n";
1583 fout << " *\n";
1584 fout << " * effect: expands to the register value where each field fi has maximum value (vi is ignored).\n";
1585 fout << " * note: internal usage\n";
1586 fout << " *\n";
1587 fout << " * example: " << bfm_or << "(ICOLL_CTRL, SFTRST(1), CLKGATE(0), TZ_LOCK_V(UNLOCKED))\n";
1588 fout << " */\n";
1589 fout << "#define " << bfm_or << "(reg, ...) "
1590 << var_expand << "(" << var_or << ", " << type_xfix(MT_FIELD_BFM, true)
1591 << "##reg##" << field_prefix() << ", __VA_ARGS__)\n";
1592 fout << "\n";
1593
1594 /* print BM_OR macro */
1595 std::string bm_or = macro_name(MN_MASK_OR);
1596 fout << "/** " << bm_or << "\n";
1597 fout << " *\n";
1598 fout << " * usage: " << bm_or << "(register, f1, f2, ...)\n";
1599 fout << " *\n";
1600 fout << " * effect: expands to the register value where each field fi is set to its maximum value.\n";
1601 fout << " * Informally: reg_f1_mask | reg_f2_mask | ...\n";
1602 fout << " *\n";
1603 fout << " * example: " << bm_or << "(ICOLL_CTRL, SFTRST, CLKGATE)\n";
1604 fout << " */\n";
1605 fout << "#define " << bm_or << "(reg, ...) "
1606 << var_expand << "(" << var_or << ", " << type_xfix(MT_FIELD_BM, true)
1607 << "##reg##" << field_prefix() << ", __VA_ARGS__)\n\n";
1608 fout << "\n";
1609
1610 /* print FIELD_READX macro */
1611 std::string bf_readx = macro_name(MN_FIELD_READX);
1612 fout << "/** " << bf_readx << "\n";
1613 fout << " *\n";
1614 fout << " * usage: " << bf_readx << "(value, register, field)\n";
1615 fout << " *\n";
1616 fout << " * effect: given a register value, return the value of a particular field\n";
1617 fout << " * note: this macro does NOT read any register\n";
1618 fout << " *\n";
1619 fout << " * example: " << bf_readx << "(0xc0000000, ICOLL_CTRL, SFTRST)\n";
1620 fout << " * " << bf_readx << "(0x46ff, ICOLL_ENABLE, CPU0_PRIO)\n";
1621 fout << " */\n";
1622 fout << "#define " << bf_readx << "(val, name, field) "
1623 << "(((val) & " << safe_macro_paste(false, type_xfix(MT_FIELD_BM, true))
1624 << "name" << safe_macro_paste(true, type_xfix(MT_FIELD_BM, false))
1625 << safe_macro_paste(true, field_prefix()) << "##field"
1626 << ") >> " << safe_macro_paste(false, type_xfix(MT_FIELD_BP, true))
1627 << "name" << safe_macro_paste(true, type_xfix(MT_FIELD_BP, false))
1628 << safe_macro_paste(true, field_prefix()) << "##field"
1629 << ")\n";
1630 fout << "\n";
1631
1632 /* print FIELD_WRITEX macro */
1633 std::string bf_writex = macro_name(MN_FIELD_WRITEX);
1634 fout << "/** " << bf_writex << "\n";
1635 fout << " *\n";
1636 fout << " * usage: " << bf_writex << "(var, register, f1(v1), f2(v2), ...)\n";
1637 fout << " *\n";
1638 fout << " * effect: change the variable value so that field fi has value vi\n";
1639 fout << " * note: this macro will perform a read-modify-write\n";
1640 fout << " *\n";
1641 fout << " * example: " << bf_writex << "(var, ICOLL_CTRL, SFTRST(1), CLKGATE(0), TZ_LOCK_V(UNLOCKED))\n";
1642 fout << " * " << bf_writex << "(var, ICOLL_ENABLE, CPU0_PRIO(1), CPU0_TYPE_V(FIQ))\n";
1643 fout << " */\n";
1644 fout << "#define " << bf_writex << "(var, name, ...) "
1645 << "(var) = " << macro_name(MN_FIELD_OR) << "(name, __VA_ARGS__) | (~"
1646 << macro_name(MN_FIELD_OR_MASK) << "(name, __VA_ARGS__) & (var))\n";
1647 fout << "\n";
1648
1649 generate_macro_reg_ops(bf_readx, bf_or, false, fout);
1650
1651 if(has_offsets())
1652 generate_macro_reg_ops(bf_readx, bf_or, true, fout);
1653
1654 print_guard(fout, guard, false);
1655 fout.close();
1656 return true;
1657}
1658
1659bool common_generator::generate(error_context_t& ectx)
1660{
1661 /* first find which inst goes to which file */
1662 std::map< std::string, std::vector< pseudo_node_inst_t > > regmap;
1663 for(size_t i = 0; i < m_soc.size(); i++)
1664 {
1665 soc_ref_t soc(&m_soc[i]);
1666 pseudo_node_inst_t inst;
1667 inst.inst = soc.root_inst();
1668 gather_files(inst, has_selectors() ? selector_soc_dir(soc) + "/" :
1669 "", regmap);
1670 }
1671 /* create output directory */
1672 create_dir(m_outdir);
1673 /* print files */
1674 std::map< std::string, std::vector< pseudo_node_inst_t > >::iterator it = regmap.begin();
1675 for(; it != regmap.end(); ++it)
1676 {
1677 create_alldir(m_outdir, it->first.c_str());
1678 std::ofstream fout((m_outdir + "/" + it->first).c_str());
1679 if(!fout)
1680 {
1681 printf("Cannot create '%s'\n", (m_outdir + "/" + it->first).c_str());
1682 return false;
1683 }
1684 std::vector< soc_ref_t > soc_list = list_socs(it->second);
1685 print_copyright(fout, soc_list);
1686 std::string guard = header_include_guard(it->first);
1687 print_guard(fout, guard, true);
1688
1689 /* if we generate selectors, we include the macro header in them, otherwise
1690 * we include the macro header right here. If we don't need support macros,
1691 * we also don't include it. */
1692 if(!has_selectors() && has_support_macros())
1693 {
1694 fout << "\n";
1695 fout << "#include \"" << macro_header() << "\"\n";
1696 }
1697
1698 for(size_t i = 0; i < it->second.size(); i++)
1699 {
1700 if(it->second[i].inst.node().reg().valid())
1701 {
1702 if(!generate_register(fout, it->second[i]))
1703 {
1704 printf("Cannot generate register ");
1705 print_inst(it->second[i]);
1706 return false;
1707 }
1708 }
1709 else if(has_offsets() && !it->second[i].inst.node().is_root())
1710 {
1711 if(!generate_node(fout, it->second[i]))
1712 {
1713 printf("Cannot generate node ");
1714 print_inst(it->second[i]);
1715 return false;
1716 }
1717 }
1718 }
1719
1720 print_guard(fout, guard, false);
1721 fout.close();
1722 }
1723 /* for selectors only */
1724 if(has_selectors())
1725 {
1726 /* list all possible headers and per soc headers */
1727 std::map< std::string, std::set< soc_ref_t > > headers;
1728 for(it = regmap.begin(); it != regmap.end(); ++it)
1729 {
1730 /* pick the first instance in the file to extract the file name */
1731 node_inst_t inst = it->second[0].inst;
1732 headers[register_header(inst)].insert(inst.node().soc());
1733 }
1734 /* create selector headers */
1735 std::map< std::string, std::set< soc_ref_t > >::iterator jt;
1736 for(jt = headers.begin(); jt != headers.end(); ++jt)
1737 {
1738 std::ofstream fout((m_outdir + "/" + jt->first).c_str());
1739 if(!fout)
1740 {
1741 printf("Cannot create selector '%s'\n", (m_outdir + "/" + jt->first).c_str());
1742 return false;
1743 }
1744 print_copyright(fout, std::vector< soc_ref_t >());
1745 std::string guard = header_include_guard(jt->first);
1746 print_guard(fout, guard, true);
1747
1748 /* if we generate selectors, we include the macro header in them */
1749 fout << "\n";
1750 fout << "#include \"" << macro_header() << "\"\n";
1751
1752 std::set< soc_ref_t >::iterator kt;
1753 define_align_context_t ctx;
1754 for(kt = jt->second.begin(); kt != jt->second.end(); ++kt)
1755 {
1756 std::ostringstream oss;
1757 oss << "\"" << selector_soc_dir(*kt) << "/" << jt->first << "\"";
1758 ctx.add(selector_soc_macro(*kt), oss.str());
1759 }
1760 fout << "\n";
1761 ctx.print(fout);
1762 fout << "\n";
1763 fout << "#include \"" << selector_include_header() << "\"\n";
1764 fout << "\n";
1765 for(kt = jt->second.begin(); kt != jt->second.end(); ++kt)
1766 fout << "#undef " << selector_soc_macro(*kt) << "\n";
1767
1768 print_guard(fout, guard, false);
1769 fout.close();
1770 }
1771 }
1772 /* generate macro header */
1773 if(!generate_macro_header(ectx))
1774 return false;
1775 return true;
1776}
1777
1778/**
1779 * Generator: jz
1780 */
1781
1782class jz_generator : public common_generator
1783{
1784 bool has_support_macros() const
1785 {
1786 return true;
1787 }
1788
1789 bool has_selectors() const
1790 {
1791 return m_soc.size() >= 2;
1792 }
1793
1794 bool has_offsets() const
1795 {
1796 return false;
1797 }
1798
1799 std::string selector_soc_dir(const soc_ref_t& ref) const
1800 {
1801 return ref.get()->name;
1802 }
1803
1804 std::string selector_include_header() const
1805 {
1806 return "select.h";
1807 }
1808
1809 std::string selector_soc_macro(const soc_ref_t& ref) const
1810 {
1811 return toupper(ref.get()->name) + "_INCLUDE";
1812 }
1813
1814 std::string register_header(const node_inst_t& inst) const
1815 {
1816 /* one register header per top-level block */
1817 if(inst.is_root())
1818 return "<error>";
1819 if(inst.parent().is_root())
1820 return tolower(inst.node().name()) + ".h";
1821 else
1822 return register_header(inst.parent());
1823 }
1824
1825 std::string macro_name(macro_name_t macro, bool relative) const
1826 {
1827 switch(macro)
1828 {
1829 case MN_REG_READ: return "jz_read";
1830 case MN_FIELD_READ: return "jz_readf";
1831 case MN_FIELD_READX: return "jz_vreadf";
1832 case MN_REG_WRITE: return "jz_write";
1833 case MN_REG_SET: return "jz_set";
1834 case MN_REG_CLEAR: return "jz_clr";
1835 case MN_FIELD_WRITE: return "jz_writef";
1836 case MN_FIELD_OVERWRITE: return "jz_overwritef";
1837 case MN_FIELD_WRITEX: return "jz_vwritef";
1838 case MN_FIELD_SET: return "jz_setf";
1839 case MN_FIELD_CLEAR: return "jz_clrf";
1840 case MN_FIELD_TOG: return "jz_togf";
1841 case MN_FIELD_CLEAR_SET: return "jz_csf";
1842 case MN_FIELD_OR: return "jz_orf";
1843 case MN_FIELD_OR_MASK: return "__jz_orfm"; // internal macro
1844 case MN_MASK_OR: return "jz_orm";
1845 case MN_REG_CLEAR_SET: return "jz_cs";
1846 case MN_GET_VARIANT: return "__jz_variant"; // internal macro
1847 case MN_VARIABLE: return "jz_reg";
1848 default: return "<macro_name>";
1849 }
1850 }
1851
1852 std::string macro_header() const
1853 {
1854 return "macro.h";
1855 }
1856
1857 bool register_flag(const node_inst_t& inst, register_flag_t flag) const
1858 {
1859 /* make everything parametrized */
1860 switch(flag)
1861 {
1862 case RF_GENERATE_ALL_INST: return false;
1863 case RF_GENERATE_PARAM_INST: return true;
1864 default: return false;
1865 }
1866 }
1867
1868 std::string type_xfix(macro_type_t type, bool prefix) const
1869 {
1870 switch(type)
1871 {
1872 case MT_REG_ADDR: return prefix ? "JA_" : "";
1873 case MT_REG_TYPE: return prefix ? "JT_" : "";
1874 case MT_REG_NAME: return prefix ? "JN_" : "";
1875 case MT_REG_INDEX: return prefix ? "JI_" : "";
1876 case MT_REG_VAR: return prefix ? "REG_" : "";
1877 case MT_FIELD_BP: return prefix ? "BP_" : "";
1878 case MT_FIELD_BM: return prefix ? "BM_" : "";
1879 case MT_FIELD_BV: return prefix ? "BV_" : "";
1880 case MT_FIELD_BF: return prefix ? "BF_" : "";
1881 case MT_FIELD_BFM: return prefix ? "BFM_" : "";
1882 case MT_FIELD_BFV: return prefix ? "BF_" : "_V";
1883 case MT_FIELD_BFMV: return prefix ? "BFM_" : "_V";
1884 case MT_IO_TYPE: return prefix ? "JIO_" : "";
1885 default: return "<xfix>";
1886 }
1887 }
1888
1889 std::string variant_xfix(const std::string& variant, bool prefix) const
1890 {
1891 /* variant X -> reg_X */
1892 if(prefix)
1893 return "";
1894 else
1895 return "_" + toupper(variant);
1896 }
1897
1898 std::string inst_prefix(const node_inst_t& inst) const
1899 {
1900 /* separate blocks with _: block_reg */
1901 return "_";
1902 }
1903
1904 std::string field_prefix() const
1905 {
1906 /* separate fields with _: block_reg_field */
1907 return "_";
1908 }
1909
1910 std::string enum_prefix() const
1911 {
1912 /* separate enums with __: block_reg_field__enum */
1913 return "__";
1914 }
1915
1916 std::string enum_name(const enum_ref_t& enum_) const
1917 {
1918 return enum_.get()->name;
1919 }
1920
1921 access_type_t register_access(const std::string& variant, access_t access) const
1922 {
1923 /* SET and CLR are special and always promoted to WO */
1924 if(variant == "set" || variant == "clr" || access == WRITE_ONLY)
1925 return AT_WO;
1926 else if(access == READ_ONLY)
1927 return AT_RO;
1928 else
1929 return AT_RW;
1930 }
1931
1932 bool has_sct() const
1933 {
1934 return true;
1935 }
1936
1937 std::string sct_variant(macro_name_t name) const
1938 {
1939 switch(name)
1940 {
1941 case MN_FIELD_SET: return "set"; // always use set variant
1942 case MN_FIELD_CLEAR: return "clr"; // always use clr variant
1943 default: return "";
1944 }
1945 }
1946};
1947
1948/**
1949 * Generator: imx
1950 */
1951
1952class imx_generator : public common_generator
1953{
1954 bool has_support_macros() const
1955 {
1956 return true;
1957 }
1958
1959 bool has_selectors() const
1960 {
1961 return m_soc.size() >= 2;
1962 }
1963
1964 bool has_offsets() const
1965 {
1966 return false;
1967 }
1968
1969 std::string selector_soc_dir(const soc_ref_t& ref) const
1970 {
1971 return ref.get()->name;
1972 }
1973
1974 std::string selector_include_header() const
1975 {
1976 return "select.h";
1977 }
1978
1979 std::string selector_soc_macro(const soc_ref_t& ref) const
1980 {
1981 return toupper(ref.get()->name) + "_INCLUDE";
1982 }
1983
1984 std::string register_header(const node_inst_t& inst) const
1985 {
1986 /* one register header per top-level block */
1987 if(inst.is_root())
1988 return "<error>";
1989 if(inst.parent().is_root())
1990 return tolower(inst.node().name()) + ".h";
1991 else
1992 return register_header(inst.parent());
1993 }
1994
1995 std::string macro_name(macro_name_t macro, bool relative) const
1996 {
1997 switch(macro)
1998 {
1999 case MN_REG_READ: return "REG_RD";
2000 case MN_FIELD_READ: return "BF_RD";
2001 case MN_FIELD_READX: return "BF_RDX";
2002 case MN_REG_WRITE: return "REG_WR";
2003 case MN_REG_SET: return ""; // no macro for this
2004 case MN_REG_CLEAR: return ""; // no macro for this
2005 case MN_FIELD_WRITE: return "BF_WR";
2006 case MN_FIELD_OVERWRITE: return "BF_WR_ALL";
2007 case MN_FIELD_WRITEX: return "BF_WRX";
2008 case MN_FIELD_SET: return "BF_SET";
2009 case MN_FIELD_CLEAR: return "BF_CLR";
2010 case MN_FIELD_TOG: return "BF_TOG";
2011 case MN_FIELD_CLEAR_SET: return "BF_CS";
2012 case MN_FIELD_OR: return "BF_OR";
2013 case MN_FIELD_OR_MASK: return "__BFM_OR";
2014 case MN_MASK_OR: return "BM_OR";
2015 case MN_REG_CLEAR_SET: return "REG_CS";
2016 case MN_GET_VARIANT: return "__REG_VARIANT";
2017 case MN_VARIABLE: return "HW";
2018 default: return "<macro_name>";
2019 }
2020 }
2021
2022 std::string macro_header() const
2023 {
2024 return "macro.h";
2025 }
2026
2027 bool register_flag(const node_inst_t& inst, register_flag_t flag) const
2028 {
2029 /* make everything parametrized */
2030 switch(flag)
2031 {
2032 case RF_GENERATE_ALL_INST: return false;
2033 case RF_GENERATE_PARAM_INST: return true;
2034 default: return false;
2035 }
2036 }
2037
2038 std::string type_xfix(macro_type_t type, bool prefix) const
2039 {
2040 switch(type)
2041 {
2042 case MT_REG_ADDR: return prefix ? "HWA_" : "";
2043 case MT_REG_TYPE: return prefix ? "HWT_" : "";
2044 case MT_REG_NAME: return prefix ? "HWN_" : "";
2045 case MT_REG_INDEX: return prefix ? "HWI_" : "";
2046 case MT_REG_VAR: return prefix ? "HW_" : "";
2047 case MT_FIELD_BP: return prefix ? "BP_" : "";
2048 case MT_FIELD_BM: return prefix ? "BM_" : "";
2049 case MT_FIELD_BV: return prefix ? "BV_" : "";
2050 case MT_FIELD_BF: return prefix ? "BF_" : "";
2051 case MT_FIELD_BFM: return prefix ? "BFM_" : "";
2052 case MT_FIELD_BFV: return prefix ? "BF_" : "_V";
2053 case MT_FIELD_BFMV: return prefix ? "BFM_" : "_V";
2054 case MT_IO_TYPE: return prefix ? "HWIO_" : "";
2055 default: return "<xfix>";
2056 }
2057 }
2058
2059 std::string variant_xfix(const std::string& variant, bool prefix) const
2060 {
2061 /* variant X -> reg_X */
2062 if(prefix)
2063 return "";
2064 else
2065 return "_" + toupper(variant);
2066 }
2067
2068 std::string inst_prefix(const node_inst_t& inst) const
2069 {
2070 /* separate blocks with _: block_reg */
2071 return "_";
2072 }
2073
2074 std::string field_prefix() const
2075 {
2076 /* separate fields with _: block_reg_field */
2077 return "_";
2078 }
2079
2080 std::string enum_prefix() const
2081 {
2082 /* separate enums with __: block_reg_field__enum */
2083 return "__";
2084 }
2085
2086 std::string enum_name(const enum_ref_t& enum_) const
2087 {
2088 return enum_.get()->name;
2089 }
2090
2091 access_type_t register_access(const std::string& variant, access_t access) const
2092 {
2093 /* SET, CLR and TOG are special and always promoted to WO */
2094 if(variant == "set" || variant == "clr" || variant == "tog" || access == WRITE_ONLY)
2095 return AT_WO;
2096 else if(access == READ_ONLY)
2097 return AT_RO;
2098 else
2099 return AT_RW;
2100 }
2101
2102 bool has_sct() const
2103 {
2104 return true;
2105 }
2106
2107 std::string sct_variant(macro_name_t name) const
2108 {
2109 switch(name)
2110 {
2111 case MN_FIELD_SET: return "set"; // always use set variant
2112 case MN_FIELD_CLEAR: return "clr"; // always use clr variant
2113 case MN_FIELD_TOG: return "tog"; // always use tog variant
2114 default: return "";
2115 }
2116 }
2117};
2118
2119/**
2120 * Generator: atj
2121 */
2122
2123class atj_generator : public common_generator
2124{
2125 bool has_support_macros() const
2126 {
2127 // no support macros
2128 return false;
2129 }
2130
2131 bool has_selectors() const
2132 {
2133 return false;
2134 }
2135
2136 bool has_offsets() const
2137 {
2138 return false;
2139 }
2140
2141 std::string selector_soc_dir(const soc_ref_t& ref) const
2142 {
2143 return ref.get()->name;
2144 }
2145
2146 std::string selector_include_header() const
2147 {
2148 // unused
2149 return "<error>";
2150 }
2151
2152 std::string selector_soc_macro(const soc_ref_t& ref) const
2153 {
2154 // unused
2155 return "<error>";
2156 }
2157
2158 std::string register_header(const node_inst_t& inst) const
2159 {
2160 /* one register header per top-level block */
2161 if(inst.is_root())
2162 return "<error>";
2163 if(inst.parent().is_root())
2164 return tolower(inst.node().name()) + ".h";
2165 else
2166 return register_header(inst.parent());
2167 }
2168
2169 std::string macro_name(macro_name_t macro, bool relative) const
2170 {
2171 // no macros are generated
2172 return "<macro_name>";
2173 }
2174
2175 std::string macro_header() const
2176 {
2177 // unused
2178 return "<error>";
2179 }
2180
2181 bool register_flag(const node_inst_t& inst, register_flag_t flag) const
2182 {
2183 /* make everything parametrized */
2184 switch(flag)
2185 {
2186 case RF_GENERATE_ALL_INST: return false;
2187 case RF_GENERATE_PARAM_INST: return true;
2188 default: return false;
2189 }
2190 }
2191
2192 std::string type_xfix(macro_type_t type, bool prefix) const
2193 {
2194 switch(type)
2195 {
2196 case MT_REG_ADDR: return prefix ? "" : "_ADDR";
2197 case MT_REG_VAR: return prefix ? "" : "";
2198 case MT_FIELD_BP: return prefix ? "BP_" : "";
2199 case MT_FIELD_BM: return prefix ? "BM_" : "";
2200 case MT_FIELD_BV: return prefix ? "BV_" : "";
2201 case MT_FIELD_BF: return prefix ? "BF_" : "";
2202 case MT_FIELD_BFM: return prefix ? "BFM_" : "";
2203 case MT_FIELD_BFV: return prefix ? "BF_" : "_V";
2204 case MT_FIELD_BFMV: return prefix ? "BFM_" : "_V";
2205 default: return "<xfix>";
2206 }
2207 }
2208
2209 std::string variant_xfix(const std::string& variant, bool prefix) const
2210 {
2211 return "<variant>";
2212 }
2213
2214 std::string inst_prefix(const node_inst_t& inst) const
2215 {
2216 /* separate blocks with _: block_reg */
2217 return "_";
2218 }
2219
2220 std::string field_prefix() const
2221 {
2222 /* separate fields with _: block_reg_field */
2223 return "_";
2224 }
2225
2226 std::string enum_prefix() const
2227 {
2228 /* separate enums with __: block_reg_field__enum */
2229 return "__";
2230 }
2231
2232 std::string enum_name(const enum_ref_t& enum_) const
2233 {
2234 return enum_.get()->name;
2235 }
2236
2237 access_type_t register_access(const std::string& variant, access_t access) const
2238 {
2239 return AT_RW;
2240 }
2241
2242 bool has_sct() const
2243 {
2244 return false;
2245 }
2246
2247 std::string sct_variant(macro_name_t name) const
2248 {
2249 return "<variant>";
2250 }
2251};
2252
2253/**
2254 * Generator: cortex_m
2255 */
2256class cortex_m_generator : public common_generator
2257{
2258 bool has_support_macros() const
2259 {
2260 return true;
2261 }
2262
2263 bool has_selectors() const
2264 {
2265 return m_soc.size() >= 2;
2266 }
2267
2268 bool has_offsets() const
2269 {
2270 return false;
2271 }
2272
2273 std::string selector_soc_dir(const soc_ref_t& ref) const
2274 {
2275 return ref.get()->name;
2276 }
2277
2278 std::string selector_include_header() const
2279 {
2280 return "select.h";
2281 }
2282
2283 std::string selector_soc_macro(const soc_ref_t& ref) const
2284 {
2285 return toupper(ref.get()->name) + "_INCLUDE";
2286 }
2287
2288 std::string register_header(const node_inst_t& inst) const
2289 {
2290 /* one register header per top-level block */
2291 if(inst.is_root())
2292 return "<error>";
2293 if(inst.parent().is_root())
2294 return tolower(inst.node().name()) + ".h";
2295 else
2296 return register_header(inst.parent());
2297 }
2298
2299 std::string header_include_guard(const std::string& filename)
2300 {
2301 // Replace the default include guard to prevent conflicts with
2302 // other SoC-specific headergen-generated files
2303 std::string guard = "__ARM_CORTEX_M_" + toupper(filename) + "__";
2304 for(size_t i = 0; i < guard.size(); i++)
2305 if(!isalnum(guard[i]))
2306 guard[i] = '_';
2307 return guard;
2308 }
2309
2310 std::string macro_name(macro_name_t macro, bool relative) const
2311 {
2312 switch(macro)
2313 {
2314 case MN_REG_READ: return "cm_read";
2315 case MN_FIELD_READ: return "cm_readf";
2316 case MN_FIELD_READX: return "cm_vreadf";
2317 case MN_REG_WRITE: return "cm_write";
2318 case MN_FIELD_WRITE: return "cm_writef";
2319 case MN_FIELD_OVERWRITE: return "cm_overwritef";
2320 case MN_FIELD_WRITEX: return "cm_vwritef";
2321 case MN_FIELD_SET: return "cm_setf";
2322 case MN_FIELD_CLEAR: return "cm_clrf";
2323 case MN_FIELD_OR: return "cm_orf";
2324 case MN_FIELD_OR_MASK: return "__cm_orfm"; // internal macro
2325 case MN_MASK_OR: return "cm_orm";
2326 case MN_GET_VARIANT: return "__cm_variant"; // internal macro
2327 case MN_VARIABLE: return "cm_reg";
2328 default: return "<macro_name>";
2329 }
2330 }
2331
2332 std::string macro_header() const
2333 {
2334 return "macro.h";
2335 }
2336
2337 bool register_flag(const node_inst_t& inst, register_flag_t flag) const
2338 {
2339 /* make everything parametrized */
2340 switch(flag)
2341 {
2342 case RF_GENERATE_ALL_INST: return false;
2343 case RF_GENERATE_PARAM_INST: return true;
2344 default: return false;
2345 }
2346 }
2347
2348 std::string type_xfix(macro_type_t type, bool prefix) const
2349 {
2350 switch(type)
2351 {
2352 case MT_REG_ADDR: return prefix ? "CMA_" : "";
2353 case MT_REG_TYPE: return prefix ? "CMT_" : "";
2354 case MT_REG_NAME: return prefix ? "CMN_" : "";
2355 case MT_REG_VAR: return prefix ? "REG_" : "";
2356 case MT_FIELD_BP: return prefix ? "BP_" : "";
2357 case MT_FIELD_BM: return prefix ? "BM_" : "";
2358 case MT_FIELD_BV: return prefix ? "BV_" : "";
2359 case MT_FIELD_BF: return prefix ? "BF_" : "";
2360 case MT_FIELD_BFM: return prefix ? "BFM_" : "";
2361 case MT_FIELD_BFV: return prefix ? "BF_" : "_V";
2362 case MT_FIELD_BFMV: return prefix ? "BFM_" : "_V";
2363 case MT_IO_TYPE: return prefix ? "CMIO_" : "";
2364 default: return "<xfix>";
2365 }
2366 }
2367
2368 std::string variant_xfix(const std::string& variant, bool prefix) const
2369 {
2370 return "<variant>";
2371 }
2372
2373 std::string inst_prefix(const node_inst_t& inst) const
2374 {
2375 /* separate blocks with _: block_reg */
2376 return "_";
2377 }
2378
2379 std::string field_prefix() const
2380 {
2381 /* separate fields with _: block_reg_field */
2382 return "_";
2383 }
2384
2385 std::string enum_prefix() const
2386 {
2387 /* separate enums with __: block_reg_field__enum */
2388 return "__";
2389 }
2390
2391 std::string enum_name(const enum_ref_t& enum_) const
2392 {
2393 return enum_.get()->name;
2394 }
2395
2396 access_type_t register_access(const std::string& variant, access_t access) const
2397 {
2398 if(access == WRITE_ONLY)
2399 return AT_WO;
2400 else if(access == READ_ONLY)
2401 return AT_RO;
2402 else
2403 return AT_RW;
2404 }
2405
2406 bool has_sct() const
2407 {
2408 return false;
2409 }
2410
2411 std::string sct_variant(macro_name_t name) const
2412 {
2413 return "<variant>";
2414 }
2415};
2416
2417/**
2418 * Generator: st
2419 */
2420
2421class st_generator : public common_generator
2422{
2423 bool has_support_macros() const
2424 {
2425 return true;
2426 }
2427
2428 bool has_selectors() const
2429 {
2430 return m_soc.size() >= 2;
2431 }
2432
2433 bool has_offsets() const
2434 {
2435 return true;
2436 }
2437
2438 std::string selector_soc_dir(const soc_ref_t& ref) const
2439 {
2440 return ref.get()->name;
2441 }
2442
2443 std::string selector_include_header() const
2444 {
2445 return "select.h";
2446 }
2447
2448 std::string selector_soc_macro(const soc_ref_t& ref) const
2449 {
2450 return toupper(ref.get()->name) + "_INCLUDE";
2451 }
2452
2453 std::string register_header(const node_inst_t& inst) const
2454 {
2455 /* one register header per top-level block */
2456 if(inst.is_root())
2457 return "<error>";
2458 if(inst.parent().is_root())
2459 return tolower(inst.node().name()) + ".h";
2460 else
2461 return register_header(inst.parent());
2462 }
2463
2464 std::string macro_name(macro_name_t macro, bool relative) const
2465 {
2466 switch(macro)
2467 {
2468 case MN_REG_READ: return relative ? "st_readl" : "st_read";
2469 case MN_FIELD_READ: return relative ? "st_readlf" : "st_readf";
2470 case MN_FIELD_READX: return "st_vreadf";
2471 case MN_REG_WRITE: return relative ? "st_writel" : "st_write";
2472 case MN_FIELD_WRITE: return relative ? "st_writelf" : "st_writef";
2473 case MN_FIELD_OVERWRITE: return relative ? "st_overwritelf" : "st_overwritef";
2474 case MN_FIELD_WRITEX: return "st_vwritef";
2475 case MN_FIELD_SET: return relative ? "st_setlf" : "st_setf";
2476 case MN_FIELD_CLEAR: return relative ? "st_clrlf" : "st_clrf";
2477 case MN_FIELD_OR: return "st_orf";
2478 case MN_FIELD_OR_MASK: return "__st_orfm"; // internal macro
2479 case MN_MASK_OR: return "st_orm";
2480 case MN_GET_VARIANT: return "__st_variant"; // internal macro
2481 case MN_VARIABLE: return relative ? "st_regl" : "st_reg";
2482 default: return "<macro_name>";
2483 }
2484 }
2485
2486 std::string macro_header() const
2487 {
2488 return "macro.h";
2489 }
2490
2491 bool register_flag(const node_inst_t& inst, register_flag_t flag) const
2492 {
2493 /* make everything parametrized */
2494 switch(flag)
2495 {
2496 case RF_GENERATE_ALL_INST: return false;
2497 case RF_GENERATE_PARAM_INST: return true;
2498 default: return false;
2499 }
2500 }
2501
2502 std::string type_xfix(macro_type_t type, bool prefix) const
2503 {
2504 switch(type)
2505 {
2506 case MT_NODE_ADDR: /* fallthrough */
2507 case MT_REG_ADDR: return prefix ? "STA_" : "";
2508 case MT_REG_OFFSET: return prefix ? "STO_" : "";
2509 case MT_REG_TYPE: return prefix ? "STT_" : "";
2510 case MT_REG_NAME: return prefix ? "STN_" : "";
2511 case MT_REG_VAR: return prefix ? "REG_" : "";
2512 case MT_FIELD_BP: return prefix ? "BP_" : "";
2513 case MT_FIELD_BM: return prefix ? "BM_" : "";
2514 case MT_FIELD_BV: return prefix ? "BV_" : "";
2515 case MT_FIELD_BF: return prefix ? "BF_" : "";
2516 case MT_FIELD_BFM: return prefix ? "BFM_" : "";
2517 case MT_FIELD_BFV: return prefix ? "BF_" : "_V";
2518 case MT_FIELD_BFMV: return prefix ? "BFM_" : "_V";
2519 case MT_IO_TYPE: return prefix ? "STIO_" : "";
2520 default: return "<xfix>";
2521 }
2522 }
2523
2524 std::string variant_xfix(const std::string& variant, bool prefix) const
2525 {
2526 /* variant X -> reg_X */
2527 if(prefix)
2528 return "";
2529 else
2530 return "_" + toupper(variant);
2531 }
2532
2533 std::string inst_prefix(const node_inst_t& inst) const
2534 {
2535 /* separate blocks with _: block_reg */
2536 return "_";
2537 }
2538
2539 std::string field_prefix() const
2540 {
2541 /* separate fields with _: block_reg_field */
2542 return "_";
2543 }
2544
2545 std::string enum_prefix() const
2546 {
2547 /* separate enums with __: block_reg_field__enum */
2548 return "__";
2549 }
2550
2551 std::string enum_name(const enum_ref_t& enum_) const
2552 {
2553 return enum_.get()->name;
2554 }
2555
2556 access_type_t register_access(const std::string& variant, access_t access) const
2557 {
2558 if(access == WRITE_ONLY)
2559 return AT_WO;
2560 else if(access == READ_ONLY)
2561 return AT_RO;
2562 else
2563 return AT_RW;
2564 }
2565
2566 bool has_sct() const
2567 {
2568 return false;
2569 }
2570
2571 std::string sct_variant(macro_name_t name) const
2572 {
2573 return "<variant>";
2574 }
2575};
2576
2577/**
2578 * Driver
2579 */
2580
2581abstract_generator *get_generator(const std::string& name)
2582{
2583 if(name == "jz")
2584 return new jz_generator();
2585 else if(name == "imx")
2586 return new imx_generator();
2587 else if(name == "atj")
2588 return new atj_generator();
2589 else if(name == "cortex_m")
2590 return new cortex_m_generator();
2591 else if(name == "st")
2592 return new st_generator();
2593 else
2594 return 0;
2595}
2596
2597void usage()
2598{
2599 printf("usage: headergen [options] <desc files...>\n");
2600 printf("options:\n");
2601 printf(" -?/--help Dispaly this help\n");
2602 printf(" -g/--generator <gen> Select generator (jz, imx, atj, cortex_m, st)\n");
2603 printf(" -o/--outdir <dir> Output directory\n");
2604 exit(1);
2605}
2606
2607int main(int argc, char **argv)
2608{
2609 char *generator_name = NULL;
2610 char *outdir = NULL;
2611 if(argc <= 1)
2612 usage();
2613
2614 while(1)
2615 {
2616 static struct option long_options[] =
2617 {
2618 {"help", no_argument, 0, '?'},
2619 {"generator", required_argument, 0, 'g'},
2620 {"outdir", required_argument, 0, 'o'},
2621 {0, 0, 0, 0}
2622 };
2623
2624 int c = getopt_long(argc, argv, "?g:o:", long_options, NULL);
2625 if(c == -1)
2626 break;
2627 switch(c)
2628 {
2629 case -1:
2630 break;
2631 case '?':
2632 usage();
2633 break;
2634 case 'g':
2635 generator_name = optarg;
2636 break;
2637 case 'o':
2638 outdir = optarg;
2639 break;
2640 default:
2641 abort();
2642 }
2643 }
2644 if(argc == optind)
2645 {
2646 printf("You need at least one description file\n");
2647 return 3;
2648 }
2649 if(outdir == 0)
2650 {
2651 printf("You need to select an output directory\n");
2652 return 4;
2653 }
2654 if(generator_name == 0)
2655 {
2656 printf("You need to select a generator\n");
2657 return 1;
2658 }
2659 abstract_generator *gen = get_generator(generator_name);
2660 if(gen == 0)
2661 {
2662 printf("Unknown generator name '%s'\n", generator_name);
2663 return 2;
2664 }
2665
2666 gen->set_output_dir(outdir);
2667 for(int i = optind; i < argc; i++)
2668 {
2669 error_context_t ctx;
2670 soc_t s;
2671 bool ret = parse_xml(argv[i], s, ctx);
2672 if(ctx.count() != 0)
2673 printf("In file %s:\n", argv[i]);
2674 print_context(ctx);
2675 if(!ret)
2676 {
2677 printf("Cannot parse file '%s'\n", argv[i]);
2678 return 1;
2679 }
2680 gen->add_soc(s);
2681 }
2682 error_context_t ctx;
2683 bool ret = gen->generate(ctx);
2684 print_context(ctx);
2685 if(!ret)
2686 {
2687 printf("Cannot generate headers\n");
2688 return 5;
2689 }
2690
2691 return 0;
2692}