summaryrefslogtreecommitdiff
path: root/utils/regtools/headergen_v2.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'utils/regtools/headergen_v2.cpp')
-rw-r--r--utils/regtools/headergen_v2.cpp1991
1 files changed, 1991 insertions, 0 deletions
diff --git a/utils/regtools/headergen_v2.cpp b/utils/regtools/headergen_v2.cpp
new file mode 100644
index 0000000000..bc056aaeb5
--- /dev/null
+++ b/utils/regtools/headergen_v2.cpp
@@ -0,0 +1,1991 @@
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 error_t e = ctx.get(j);
91 switch(e.level())
92 {
93 case error_t::INFO: printf("[INFO]"); break;
94 case error_t::WARNING: printf("[WARN]"); break;
95 case error_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);
532private:
533 void gather_files(const pseudo_node_inst_t& inst, const std::string& prefix,
534 std::map< std::string, std::vector< pseudo_node_inst_t > >& map);
535 void print_inst(const pseudo_node_inst_t& inst, bool end = true); // debug
536 std::vector< soc_ref_t > list_socs(const std::vector< pseudo_node_inst_t >& list);
537 bool generate_register(std::ostream& os, const pseudo_node_inst_t& reg);
538 bool generate_macro_header(error_context_t& ectx);
539protected:
540 /// return true to generate selector files
541 virtual bool has_selectors() const = 0;
542 /// [selector only] return the directory name for the soc
543 virtual std::string selector_soc_dir(const soc_ref_t& ref) const = 0;
544 /// [selector only] return the header to include to select betweens socs
545 virtual std::string selector_include_header() const = 0;
546 /// [selector only] return the name of the macro to emit for each soc
547 virtual std::string selector_soc_macro(const soc_ref_t& ref) const = 0;
548 /// return the relative filename in which to put the register
549 virtual std::string register_header(const node_inst_t& inst) const = 0;
550 /// return the include guard for a file (default does its best)
551 virtual std::string header_include_guard(const std::string& filename);
552 /// return the name of the macros header to generate
553 virtual std::string macro_header() const = 0;
554 /// macro from macro header
555 enum macro_name_t
556 {
557 MN_REG_READ, /// register read
558 MN_FIELD_READ, /// register's field read
559 MN_FIELD_READX, /// register value field read
560 MN_REG_WRITE, /// register write
561 MN_REG_CLEAR_SET, /// register clear then set
562 MN_FIELD_WRITE, /// register's field(s) write
563 MN_FIELD_WRITEX, /// register's field(s) write
564 MN_FIELD_OVERWRITE, /// register full write
565 MN_FIELD_SET, /// register's field(s) set
566 MN_FIELD_CLEAR, /// register's field(s) clear
567 MN_FIELD_TOG, /// register's field(s) toggle
568 MN_FIELD_CLEAR_SET, /// register's field(s) clear then set
569 MN_FIELD_OR, /// field ORing
570 MN_FIELD_OR_MASK, /// field ORing but in fact mask ORing
571 MN_MASK_OR, /// mask ORing
572 MN_GET_VARIANT, /// get register variant
573 MN_VARIABLE, /// return variable-like for register
574 };
575 /// return macro name defined in the macro header
576 virtual std::string macro_name(macro_name_t macro) const = 0;
577 /// flag to consider
578 enum register_flag_t
579 {
580 RF_GENERATE_ALL_INST, /// for range instance, generate one macro set per instance ?
581 RF_GENERATE_PARAM_INST, /// for range instance, generate a parametrised macro set ?
582 };
583 /** tweak instance generaton and its children
584 * NOTE: for range flags, although the instance will be numbered, the index is
585 * to be ignored */
586 virtual bool register_flag(const node_inst_t& inst, register_flag_t flag) const = 0;
587 /// prefix/suffix type
588 enum macro_type_t
589 {
590 MT_REG_ADDR, /// register address
591 MT_REG_TYPE, /// register type
592 MT_REG_NAME, /// register prefix for fields
593 MT_REG_INDEX, /// register index/indices
594 MT_REG_VAR, /// variable-like macro
595 MT_FIELD_BP, /// bit position of a field
596 MT_FIELD_BM, /// bit mask of a field
597 MT_FIELD_BV, /// bit value of a field enum
598 MT_FIELD_BF, /// bit field value: (v << pos) & mask
599 MT_FIELD_BFM, /// ignore value and return mask
600 MT_FIELD_BFV, /// bit field enum value: (enum_v << pos) & mask
601 MT_FIELD_BFMV, /// ignore value and return mask
602 MT_IO_TYPE, /// register io type
603 };
604 /// register access types
605 enum access_type_t
606 {
607 AT_RO, /// read-only: write are disallowed
608 AT_RW, /// read-write: read/writes are allowed, field write by generated a RMW
609 AT_WO, /// write-only: read are disallowed, field write will set other fields to 0
610 };
611 /// register operation
612 enum register_op_t
613 {
614 RO_VAR, /// variable-like
615 RO_READ, /// read
616 RO_WRITE, /// write
617 RO_RMW, /// read-modify-write
618 };
619 /// return type prefix/suffix for register macro
620 virtual std::string type_xfix(macro_type_t type, bool prefix) const = 0;
621 /// return variant prefix/suffix
622 virtual std::string variant_xfix(const std::string& variant, bool prefix) const = 0;
623 /// return instance prefix in macro name
624 virtual std::string inst_prefix(const node_inst_t& inst) const = 0;
625 /// return field prefix in field macro names
626 virtual std::string field_prefix() const = 0;
627 /// return field enum prefix in field macro names
628 virtual std::string enum_prefix() const = 0;
629 /// return the field enum name in field macro names
630 virtual std::string enum_name(const enum_ref_t& enum_) const = 0;
631 /// return instance name in macro, default is instance name then index if any
632 virtual std::string instance_name(const node_inst_t& inst, bool parametric) const;
633 /// return field name in macro, default is field name
634 virtual std::string field_name(const field_ref_t& field) const;
635 /// return the complete macro name with prefix, default uses all the other functions
636 virtual std::string macro_basename(const pseudo_node_inst_t& inst) const;
637 /// return the complete macro name with prefix, default uses macro_basename()
638 virtual std::string macro_basename(const pseudo_node_inst_t& inst, macro_type_t type) const;
639 /// generate address string for a register instance, and fill the parametric
640 /// argument list, default does it the obvious way and parameters are _n1, _n2, ...
641 virtual std::string register_address(const pseudo_node_inst_t& reg,
642 std::vector< std::string >& params) const;
643 /// return access type for a variant and a given register access
644 /// NOTE variant with the unspecified access type will be promoted to register access
645 virtual access_type_t register_access(const std::string& variant, access_t access) const = 0;
646 /// return register type name
647 virtual std::string register_type_name(access_type_t access, int width) const;
648 /// get register operation name
649 virtual std::string register_op_name(register_op_t op) const;
650 /// register operation prefix
651 virtual std::string register_op_prefix() const;
652 /// generate a macro pasting that is safe even when macro is empty
653 /// ie: safe_macro_paste(false, "A") -> ##A
654 /// ie: safe_macro_paste(false, "A") ->
655 std::string safe_macro_paste(bool left, const std::string& macro) const;
656 /// generate SCT macros using register variant ?
657 virtual bool has_sct() const = 0;
658 /// return the associated SCT variant (only if RF_GENERATE_SCT)
659 /// empty means don't generate
660 virtual std::string sct_variant(macro_name_t name) const = 0;
661};
662
663std::string common_generator::instance_name(const node_inst_t& inst, bool parametric) const
664{
665 std::ostringstream oss;
666 oss << inst.name();
667 if(inst.is_indexed() && !parametric)
668 oss << inst.index();
669 return oss.str();
670}
671
672std::string common_generator::field_name(const field_ref_t& field) const
673{
674 return field.get()->name;
675}
676
677std::string common_generator::macro_basename(const pseudo_node_inst_t& inst_) const
678{
679 pseudo_node_inst_t inst = inst_;
680 std::string str;
681 while(!inst.inst.is_root())
682 {
683 str = instance_name(inst.inst, inst.parametric.back()) + str;
684 inst.inst = inst.inst.parent();
685 inst.parametric.pop_back();
686 if(!inst.inst.is_root())
687 str = inst_prefix(inst.inst) + str;
688 }
689 return str;
690}
691
692std::string common_generator::macro_basename(const pseudo_node_inst_t& inst, macro_type_t type) const
693{
694 return type_xfix(type, true) + macro_basename(inst);
695}
696
697void common_generator::print_inst(const pseudo_node_inst_t& inst, bool end)
698{
699 if(!inst.inst.is_root())
700 {
701 pseudo_node_inst_t p = inst;
702 p.inst = p.inst.parent();
703 p.parametric.pop_back();
704 print_inst(p, false);
705 printf(".%s", inst.inst.name().c_str());
706 if(inst.inst.is_indexed())
707 {
708 if(inst.parametric.back())
709 printf("[]");
710 else
711 printf("[%u]", (unsigned)inst.inst.index());
712 }
713 }
714 else
715 {
716 printf("%s", inst.inst.soc().get()->name.c_str());
717 }
718 if(end)
719 printf("\n");
720}
721
722std::string common_generator::register_type_name(access_type_t access, int width) const
723{
724 std::ostringstream oss;
725 oss << width << "_";
726 switch(access)
727 {
728 case AT_RO: oss << "RO"; break;
729 case AT_RW: oss << "RW"; break;
730 case AT_WO: oss << "WO"; break;
731 default: oss << "error"; break;
732 }
733 return type_xfix(MT_IO_TYPE, true) + oss.str() + type_xfix(MT_IO_TYPE, false);
734}
735
736std::string common_generator::register_op_name(register_op_t op) const
737{
738 switch(op)
739 {
740 case RO_VAR: return "VAR";
741 case RO_READ: return "RD";
742 case RO_WRITE: return "WR";
743 case RO_RMW: return "RMW";
744 default: return "<op>";
745 }
746}
747
748std::string common_generator::register_op_prefix() const
749{
750 return "_";
751}
752
753std::string common_generator::safe_macro_paste(bool left, const std::string& macro) const
754{
755 if(macro.size() == 0)
756 return "";
757 return left ? "##" + macro : macro + "##";
758}
759
760void common_generator::gather_files(const pseudo_node_inst_t& inst, const std::string& prefix,
761 std::map< std::string, std::vector< pseudo_node_inst_t > >& map)
762{
763 if(inst.inst.node().reg().valid())
764 map[prefix + register_header(inst.inst)].push_back(inst);
765 // if asked, generate one for each instance
766 std::vector< node_inst_t > list = inst.inst.children();
767 for(size_t i = 0; i < list.size(); i++)
768 {
769 pseudo_node_inst_t c = inst;
770 c.inst = list[i];
771 if(!list[i].is_indexed() || register_flag(inst.inst, RF_GENERATE_ALL_INST))
772 {
773 c.parametric.push_back(false);
774 gather_files(c, prefix, map);
775 c.parametric.pop_back();
776 }
777 if(list[i].is_indexed() && register_flag(list[i], RF_GENERATE_PARAM_INST))
778 {
779 bool first = list[i].index() == list[i].get()->range.first;
780 if(first)
781 {
782 c.parametric.push_back(true);
783 gather_files(c, prefix, map);
784 }
785 }
786 }
787}
788
789std::vector< soc_ref_t > common_generator::list_socs(const std::vector< pseudo_node_inst_t >& list)
790{
791 std::set< soc_ref_t > socs;
792 std::vector< pseudo_node_inst_t >::const_iterator it = list.begin();
793 for(; it != list.end(); ++it)
794 socs.insert(it->inst.soc());
795 std::vector< soc_ref_t > soc_list;
796 for(std::set< soc_ref_t >::iterator jt = socs.begin(); jt != socs.end(); ++jt)
797 soc_list.push_back(*jt);
798 return soc_list;
799}
800
801std::string common_generator::header_include_guard(const std::string& filename)
802{
803 std::string guard = "__HEADERGEN_" + toupper(filename) + "__";
804 for(size_t i = 0; i < guard.size(); i++)
805 if(!isalnum(guard[i]))
806 guard[i] = '_';
807 return guard;
808}
809
810std::string common_generator::register_address(const pseudo_node_inst_t& reg,
811 std::vector< std::string >& params) const
812{
813 std::ostringstream oss;
814 unsigned counter = 1;
815 oss << "(";
816 for(size_t i = 0; i < reg.parametric.size(); i++)
817 {
818 if(i != 0)
819 oss << " + ";
820 node_inst_t ninst = reg.inst.parent(reg.parametric.size() - i - 1);
821 instance_t& inst = *ninst.get();
822 if(reg.parametric[i])
823 params.push_back("_n" + to_str(counter++));
824 if(inst.type == instance_t::RANGE)
825 {
826 if(inst.range.type == range_t::STRIDE)
827 {
828 if(reg.parametric[i])
829 {
830 oss << to_hex(inst.range.base) << " + ";
831 oss << "(" << params.back() << ") * " << to_hex(inst.range.stride);
832 }
833 else
834 oss << to_hex(inst.range.base + ninst.index() * inst.range.stride);
835 }
836 else if(inst.range.type == range_t::FORMULA)
837 {
838 if(!reg.parametric[i])
839 {
840 soc_word_t res;
841 std::map< std::string, soc_word_t > vars;
842 vars[inst.range.variable] = ninst.index();
843 error_context_t ctx;
844 if(!evaluate_formula(inst.range.formula, vars, res, "", ctx))
845 oss << "#error cannot evaluate formula";
846 else
847 oss << to_hex(res);
848 }
849 else
850 oss << strsubst(inst.range.formula, inst.range.variable,
851 "(" + params.back() + ")");
852 }
853 else if(inst.range.type == range_t::LIST)
854 {
855 if(reg.parametric[i])
856 {
857 oss << "(";
858 for(size_t j = 0; j + 1 < inst.range.list.size(); j++)
859 {
860 oss << "(" << params.back() << ") == " << (inst.range.first + j)
861 << " ? " << to_hex(inst.range.list[j]) << " : ";
862 }
863 oss << to_hex(inst.range.list.back()) << ")";
864 }
865 else
866 oss << to_hex(inst.range.list[ninst.index() - inst.range.first]);
867 }
868 else
869 {
870 return "#error unknown range type";
871 }
872 }
873 else if(inst.type == instance_t::SINGLE)
874 oss << to_hex(inst.addr);
875 else
876 return "#error unknown instance type";
877 }
878 oss << ")";
879 return oss.str();
880}
881
882bool common_generator::generate_register(std::ostream& os, const pseudo_node_inst_t& reg)
883{
884 os << "\n";
885 define_align_context_t ctx;
886 std::vector< std::string > params;
887 std::string addr = register_address(reg, params);
888 std::string basename = macro_basename(reg);
889 std::string param_str;
890 std::string param_str_no_paren;
891 std::string param_str_no_paren_comma;
892 if(params.size() > 0)
893 {
894 for(size_t i = 0; i < params.size(); i++)
895 param_str_no_paren += (i == 0 ? "" : ",") + params[i];
896 param_str = "(" + param_str_no_paren + ")";
897 param_str_no_paren_comma = param_str_no_paren + ",";
898 }
899 std::string bp_prefix = macro_basename(reg, MT_FIELD_BP) + field_prefix();
900 std::string bm_prefix = macro_basename(reg, MT_FIELD_BM) + field_prefix();
901 std::string bf_prefix = macro_basename(reg, MT_FIELD_BF) + field_prefix();
902 std::string bfm_prefix = macro_basename(reg, MT_FIELD_BFM) + field_prefix();
903 std::string bfv_prefix = macro_basename(reg, MT_FIELD_BFV) + field_prefix();
904 std::string bfmv_prefix = macro_basename(reg, MT_FIELD_BFMV) + field_prefix();
905
906 register_ref_t regr = reg.inst.node().reg();
907 /* handle register the same way as variants */
908 std::vector< std::string > var_prefix;
909 std::vector< std::string > var_suffix;
910 std::vector< std::string > var_addr;
911 std::vector< access_type_t > var_access;
912 var_prefix.push_back("");
913 var_suffix.push_back("");
914 var_access.push_back(register_access("", regr.get()->access));
915 var_addr.push_back(addr);
916 std::vector< variant_ref_t > variants = regr.variants();
917 for(size_t i = 0; i < variants.size(); i++)
918 {
919 var_prefix.push_back(variant_xfix(variants[i].type(), true));
920 var_suffix.push_back(variant_xfix(variants[i].type(), false));
921 var_addr.push_back("(" + type_xfix(MT_REG_ADDR, true) + basename +
922 type_xfix(MT_REG_ADDR, false) + param_str + " + " +
923 to_hex(variants[i].offset()) + ")");
924 access_t acc = variants[i].get()->access;
925 if(acc == UNSPECIFIED)
926 acc = regr.get()->access; // fallback to register access
927 var_access.push_back(register_access(variants[i].type(), acc));
928 }
929
930 for(size_t i = 0; i < var_prefix.size(); i++)
931 {
932 std::string var_basename = var_prefix[i] + basename + var_suffix[i];
933 std::string macro_var = type_xfix(MT_REG_VAR, true) + var_basename +
934 type_xfix(MT_REG_VAR, false);
935 std::string macro_addr = type_xfix(MT_REG_ADDR, true) + var_basename +
936 type_xfix(MT_REG_ADDR, false);
937 std::string macro_type = type_xfix(MT_REG_TYPE, true) + var_basename +
938 type_xfix(MT_REG_TYPE, false);
939 std::string macro_prefix = type_xfix(MT_REG_NAME, true) + var_basename +
940 type_xfix(MT_REG_NAME, false);
941 std::string macro_index = type_xfix(MT_REG_INDEX, true) + var_basename +
942 type_xfix(MT_REG_INDEX, false);
943 /* print VAR macro */
944 ctx.add(macro_var + param_str, macro_name(MN_VARIABLE) + "(" + var_basename + param_str + ")");
945 /* print ADDR macro */
946 ctx.add(macro_addr + param_str, var_addr[i]);
947 /* print TYPE macro */
948 ctx.add(macro_type + param_str, register_type_name(var_access[i], regr.get()->width));
949 /* print PREFIX macro */
950 ctx.add(macro_prefix + param_str, basename);
951 /* print INDEX macro */
952 ctx.add(macro_index + param_str, param_str);
953 }
954 /* print fields */
955 std::vector< field_ref_t > fields = regr.fields();
956 for(size_t i = 0; i < fields.size(); i++)
957 {
958 /* print BP macro: pos */
959 std::string fname = field_name(fields[i]);
960 ctx.add(bp_prefix + fname + type_xfix(MT_FIELD_BP, false),
961 to_str(fields[i].get()->pos));
962 /* print BM macro: mask */
963 ctx.add(bm_prefix + fname + type_xfix(MT_FIELD_BM, false),
964 to_hex(fields[i].get()->bitmask()));
965 std::vector< enum_ref_t > enums = fields[i].enums();
966 std::string bv_prefix = macro_basename(reg, MT_FIELD_BV) + field_prefix()
967 + fname + enum_prefix();
968 /* print BV macros: enum_v */
969 for(size_t j = 0; j < enums.size(); j++)
970 ctx.add(bv_prefix + enum_name(enums[j]) + type_xfix(MT_FIELD_BV, false),
971 to_hex(enums[j].get()->value));
972 /* print BF macro: (((v) & mask) << pos) */
973 ctx.add(bf_prefix + fname + type_xfix(MT_FIELD_BF, false) + "(v)",
974 "(((v) & " + to_hex(fields[i].get()->unshifted_bitmask()) + ") << " +
975 to_str(fields[i].get()->pos) + ")");
976 /* print BFM macro: masl */
977 ctx.add(bfm_prefix + fname + type_xfix(MT_FIELD_BFM, false) + "(v)",
978 bm_prefix + fname + type_xfix(MT_FIELD_BM, false));
979 /* print BFV macro: ((enum_v) << pos) & mask) */
980 ctx.add(bfv_prefix + fname + type_xfix(MT_FIELD_BFV, false) + "(e)",
981 bf_prefix + fname + type_xfix(MT_FIELD_BF, false) + "(" +
982 bv_prefix + "##e)");
983 /* print BFMV macro: masl */
984 ctx.add(bfmv_prefix + fname + type_xfix(MT_FIELD_BFMV, false) + "(v)",
985 bm_prefix + fname + type_xfix(MT_FIELD_BM, false));
986 }
987
988 ctx.print(os);
989 return true;
990}
991
992bool common_generator::generate_macro_header(error_context_t& ectx)
993{
994 std::ofstream fout((m_outdir + "/" + macro_header()).c_str());
995 if(!fout)
996 {
997 printf("Cannot create '%s'\n", (m_outdir + "/" + macro_header()).c_str());
998 return false;
999 }
1000 print_copyright(fout, std::vector< soc_ref_t >());
1001 std::string guard = header_include_guard(macro_header());
1002 print_guard(fout, guard, true);
1003 fout << "\n";
1004
1005 /* print variadic OR macros:
1006 * __VAR_OR1(prefix, suffix) expands to prefix##suffix
1007 * and more n>=2, using multiple layers of macros:
1008 * __VAR_ORn(pre, s01, s02, ..., sn) expands to pre##s01 | .. | pre##sn */
1009 std::string var_or = "__VAR_OR";
1010 const int MAX_N = 13;
1011
1012 fout << "#define " << var_or << "1(prefix, suffix) \\\n";
1013 fout << " (prefix##suffix)\n";
1014 for(int n = 2; n <= MAX_N; n++)
1015 {
1016 fout << "#define " << var_or << n << "(pre";
1017 for(int j = 1; j <= n; j++)
1018 fout << ", s" << j;
1019 fout << ") \\\n";
1020 /* dichotmoty: expands ORn using ORj and ORk where j=n/2 and k=n-j */
1021 int half = n / 2;
1022 fout << " (" << var_or << half << "(pre";
1023 for(int j = 1; j <= half; j++)
1024 fout << ", s" << j;
1025 fout << ") | " << var_or << (n - half) << "(pre";
1026 for(int j = half + 1; j <= n; j++)
1027 fout << ", s" << j;
1028 fout << "))\n";
1029 }
1030 fout << "\n";
1031
1032 /* print macro to compute number of arguments */
1033 std::string var_nargs = "__VAR_NARGS";
1034
1035 fout << "#define " << var_nargs << "(...) " << var_nargs << "_(__VA_ARGS__";
1036 for(int i = MAX_N; i >= 1; i--)
1037 fout << ", " << i;
1038 fout << ")\n";
1039 fout << "#define " << var_nargs << "_(";
1040 for(int i = 1; i <= MAX_N; i++)
1041 fout << "_" << i << ", ";
1042 fout << "N, ...) N\n\n";
1043
1044 /* print macro for variadic register macros */
1045 std::string var_expand = "__VAR_EXPAND";
1046
1047 fout << "#define " << var_expand << "(macro, prefix, ...) "
1048 << var_expand << "_(macro, " << var_nargs << "(__VA_ARGS__), prefix, __VA_ARGS__)\n";
1049 fout << "#define " << var_expand << "_(macro, cnt, prefix, ...) "
1050 << var_expand << "__(macro, cnt, prefix, __VA_ARGS__)\n";
1051 fout << "#define " << var_expand << "__(macro, cnt, prefix, ...) "
1052 << var_expand << "___(macro##cnt, prefix, __VA_ARGS__)\n";
1053 fout << "#define " << var_expand << "___(macro, prefix, ...) "
1054 << "macro(prefix, __VA_ARGS__)\n\n";
1055
1056 /* print type macros */
1057 define_align_context_t ctx;
1058 access_type_t at[3] = { AT_RO, AT_RW, AT_WO };
1059 int width[3] = { 8, 16, 32 };
1060 for(int i = 0; i < 3; i++)
1061 {
1062 for(int j = 0; j < 3; j++)
1063 {
1064 std::string io_type = register_type_name(at[i], width[j]);
1065 ctx.add(io_type + "(op, name, ...)", io_type + register_op_prefix() + "##op(name, __VA_ARGS__)");
1066 // read
1067 std::ostringstream oss;
1068 std::string reg_addr = safe_macro_paste(false, type_xfix(MT_REG_ADDR, true))
1069 + "name" + safe_macro_paste(true, type_xfix(MT_REG_ADDR, false));
1070 if(at[i] == AT_RO)
1071 oss << "(*(const volatile uint" << width[j] << "_t *)(" << reg_addr << "))";
1072 else if(at[i] == AT_RW)
1073 oss << "(*(volatile uint" << width[j] << "_t *)(" << reg_addr << "))";
1074 else
1075 oss << "({_Static_assert(0, #name \" is write-only\"); 0;})";
1076 ctx.add(io_type + register_op_prefix() + register_op_name(RO_READ) + "(name, ...)",
1077 oss.str());
1078 // write
1079 oss.str("");
1080 if(at[i] != AT_RO)
1081 oss << "(*(volatile uint" << width[j] << "_t *)(" << reg_addr << ")) = (val)";
1082 else
1083 oss << "_Static_assert(0, #name \" is read-only\")";
1084 ctx.add(io_type + register_op_prefix() + register_op_name(RO_WRITE) + "(name, val)",
1085 oss.str());
1086 // read-modify-write
1087 oss.str("");
1088 if(at[i] == AT_RW)
1089 {
1090 oss << io_type << register_op_prefix() << register_op_name(RO_WRITE) + "(name, ";
1091 oss << "(" << io_type << register_op_prefix() << register_op_name(RO_READ) + "(name) & (vand))";
1092 oss << " | (vor))";
1093 }
1094 else if(at[i] == AT_WO)
1095 oss << io_type << register_op_prefix() << register_op_name(RO_WRITE) + "(name, vor)";
1096 else
1097 oss << "_Static_assert(0, #name \" is read-only\")";
1098 ctx.add(io_type + register_op_prefix() + register_op_name(RO_RMW) + "(name, vand, vor)",
1099 oss.str());
1100 // variable
1101 oss.str("");
1102 if(at[i] == AT_RO)
1103 oss << "(*(const volatile uint" << width[j] << "_t *)(" << reg_addr << "))";
1104 else
1105 oss << "(*(volatile uint" << width[j] << "_t *)(" << reg_addr << "))";
1106 ctx.add(io_type + register_op_prefix() + register_op_name(RO_VAR) + "(name, ...)",
1107 oss.str());
1108
1109 ctx.add_raw("\n");
1110 }
1111 }
1112 ctx.print(fout);
1113 fout << "\n";
1114
1115 /* print GET_VARIANT macro */
1116 std::string get_var = macro_name(MN_GET_VARIANT);
1117 fout << "/** " << get_var << "\n";
1118 fout << " *\n";
1119 fout << " * usage: " << get_var << "(register, variant_prefix, variant_postfix)\n";
1120 fout << " *\n";
1121 fout << " * effect: expands to register variant given as argument\n";
1122 fout << " * note: internal usage\n";
1123 fout << " * note: register must be fully qualified if indexed\n";
1124 fout << " *\n";
1125 fout << " * example: " << get_var << "(ICOLL_CTRL, , _SET)\n";
1126 fout << " * example: " << get_var << "(ICOLL_ENABLE(3), , _CLR)\n";
1127 fout << " */\n";
1128 fout << "#define " << get_var << "(name, varp, vars) "
1129 << get_var << "_(" << safe_macro_paste(false, type_xfix(MT_REG_NAME, true))
1130 << "name" << safe_macro_paste(true, type_xfix(MT_REG_NAME, false)) << ", "
1131 << safe_macro_paste(false, type_xfix(MT_REG_INDEX, true))
1132 << "name" << safe_macro_paste(true, type_xfix(MT_REG_INDEX, false)) << ", varp, vars)\n";
1133 fout << "#define " << get_var << "_(...) " << get_var << "__(__VA_ARGS__)\n";
1134 fout << "#define " << get_var << "__(name, index, varp, vars) "
1135 << "varp##name##vars index\n";
1136 fout << "\n";
1137
1138 /* print BF_OR macro */
1139 std::string bf_or = macro_name(MN_FIELD_OR);
1140 fout << "/** " << bf_or << "\n";
1141 fout << " *\n";
1142 fout << " * usage: " << bf_or << "(register, f1(v1), f2(v2), ...)\n";
1143 fout << " *\n";
1144 fout << " * effect: expands to the register value where each field fi has value vi.\n";
1145 fout << " * Informally: reg_f1(v1) | reg_f2(v2) | ...\n";
1146 fout << " * note: enumerated values for fields can be obtained by using the syntax:\n";
1147 fout << " * f1" << type_xfix(MT_FIELD_BFV, false) << "(name)\n";
1148 fout << " *\n";
1149 fout << " * example: " << bf_or << "(ICOLL_CTRL, SFTRST(1), CLKGATE(0), TZ_LOCK_V(UNLOCKED))\n";
1150 fout << " */\n";
1151 fout << "#define " << bf_or << "(reg, ...) "
1152 << var_expand << "(" << var_or << ", " << type_xfix(MT_FIELD_BF, true)
1153 << "##reg##" << field_prefix() << ", __VA_ARGS__)\n";
1154 fout << "\n";
1155
1156 /* print BF_OR macro */
1157 std::string bfm_or = macro_name(MN_FIELD_OR_MASK);
1158 fout << "/** " << bfm_or << "\n";
1159 fout << " *\n";
1160 fout << " * usage: " << bfm_or << "(register, f1(v1), f2(v2), ...)\n";
1161 fout << " *\n";
1162 fout << " * effect: expands to the register value where each field fi has maximum value (vi is ignored).\n";
1163 fout << " * note: internal usage\n";
1164 fout << " *\n";
1165 fout << " * example: " << bfm_or << "(ICOLL_CTRL, SFTRST(1), CLKGATE(0), TZ_LOCK_V(UNLOCKED))\n";
1166 fout << " */\n";
1167 fout << "#define " << bfm_or << "(reg, ...) "
1168 << var_expand << "(" << var_or << ", " << type_xfix(MT_FIELD_BFM, true)
1169 << "##reg##" << field_prefix() << ", __VA_ARGS__)\n";
1170 fout << "\n";
1171
1172 /* print BM_OR macro */
1173 std::string bm_or = macro_name(MN_MASK_OR);
1174 fout << "/** " << bm_or << "\n";
1175 fout << " *\n";
1176 fout << " * usage: " << bm_or << "(register, f1, f2, ...)\n";
1177 fout << " *\n";
1178 fout << " * effect: expands to the register value where each field fi is set to its maximum value.\n";
1179 fout << " * Informally: reg_f1_mask | reg_f2_mask | ...\n";
1180 fout << " *\n";
1181 fout << " * example: " << bm_or << "(ICOLL_CTRL, SFTRST, CLKGATE)\n";
1182 fout << " */\n";
1183 fout << "#define " << bm_or << "(reg, ...) "
1184 << var_expand << "(" << var_or << ", " << type_xfix(MT_FIELD_BM, true)
1185 << "##reg##" << field_prefix() << ", __VA_ARGS__)\n\n";
1186 fout << "\n";
1187
1188 /* print REG_READ macro */
1189 std::string reg_read = macro_name(MN_REG_READ);
1190 fout << "/** " << reg_read << "\n";
1191 fout << " *\n";
1192 fout << " * usage: " << reg_read << "(register)\n";
1193 fout << " *\n";
1194 fout << " * effect: read a register and return its value\n";
1195 fout << " * note: register must be fully qualified if indexed\n";
1196 fout << " *\n";
1197 fout << " * example: " << reg_read << "(ICOLL_STATUS)\n";
1198 fout << " * " << reg_read << "(ICOLL_ENABLE(42))\n";
1199 fout << " */\n";
1200 fout << "#define " << reg_read << "(name) "
1201 << safe_macro_paste(false, type_xfix(MT_REG_TYPE, true)) << "name"
1202 << safe_macro_paste(true, type_xfix(MT_REG_TYPE, false))
1203 << "(" << register_op_name(RO_READ) << ", name)\n";
1204 fout << "\n";
1205
1206 /* print FIELD_READX macro */
1207 std::string bf_readx = macro_name(MN_FIELD_READX);
1208 fout << "/** " << bf_readx << "\n";
1209 fout << " *\n";
1210 fout << " * usage: " << bf_readx << "(value, register, field)\n";
1211 fout << " *\n";
1212 fout << " * effect: given a register value, return the value of a particular field\n";
1213 fout << " * note: this macro does NOT read any register\n";
1214 fout << " *\n";
1215 fout << " * example: " << bf_readx << "(0xc0000000, ICOLL_CTRL, SFTRST)\n";
1216 fout << " * " << bf_readx << "(0x46ff, ICOLL_ENABLE, CPU0_PRIO)\n";
1217 fout << " */\n";
1218 fout << "#define " << bf_readx << "(val, name, field) "
1219 << "(((val) & " << safe_macro_paste(false, type_xfix(MT_FIELD_BM, true))
1220 << "name" << safe_macro_paste(true, type_xfix(MT_FIELD_BM, false))
1221 << safe_macro_paste(true, field_prefix()) << "##field"
1222 << ") >> " << safe_macro_paste(false, type_xfix(MT_FIELD_BP, true))
1223 << "name" << safe_macro_paste(true, type_xfix(MT_FIELD_BP, false))
1224 << safe_macro_paste(true, field_prefix()) << "##field"
1225 << ")\n";
1226 fout << "\n";
1227
1228 /* print FIELD_READ macro */
1229 std::string bf_read = macro_name(MN_FIELD_READ);
1230 fout << "/** " << bf_read << "\n";
1231 fout << " *\n";
1232 fout << " * usage: " << bf_read << "(register, field)\n";
1233 fout << " *\n";
1234 fout << " * effect: read a register and return the value of a particular field\n";
1235 fout << " * note: register must be fully qualified if indexed\n";
1236 fout << " *\n";
1237 fout << " * example: " << bf_read << "(ICOLL_CTRL, SFTRST)\n";
1238 fout << " * " << bf_read << "(ICOLL_ENABLE(3), CPU0_PRIO)\n";
1239 fout << " */\n";
1240 fout << "#define " << bf_read << "(name, field) " << bf_read << "_("
1241 << reg_read << "(name), " << safe_macro_paste(false, type_xfix(MT_REG_NAME, true))
1242 << "name" << safe_macro_paste(true, type_xfix(MT_REG_NAME, false)) << ", field)\n";
1243 fout << "#define " << bf_read << "_(...) " << bf_readx << "(__VA_ARGS__)\n";
1244 fout << "\n";
1245
1246 /* print REG_WRITE macro */
1247 std::string reg_write = macro_name(MN_REG_WRITE);
1248 fout << "/** " << reg_write << "\n";
1249 fout << " *\n";
1250 fout << " * usage: " << reg_write << "(register, value)\n";
1251 fout << " *\n";
1252 fout << " * effect: write a register\n";
1253 fout << " * note: register must be fully qualified if indexed\n";
1254 fout << " *\n";
1255 fout << " * example: " << reg_write << "(ICOLL_CTRL, 0x42)\n";
1256 fout << " * " << reg_write << "(ICOLL_ENABLE_SET(3), 0x37)\n";
1257 fout << " */\n";
1258 fout << "#define " << reg_write << "(name, val) "
1259 << safe_macro_paste(false, type_xfix(MT_REG_TYPE, true)) << "name"
1260 << safe_macro_paste(true, type_xfix(MT_REG_TYPE, false))
1261 << "(" << register_op_name(RO_WRITE) << ", name, val)\n";
1262 fout << "\n";
1263
1264 /* print FIELD_WRITE macro */
1265 std::string bf_write = macro_name(MN_FIELD_WRITE);
1266 fout << "/** " << bf_write << "\n";
1267 fout << " *\n";
1268 fout << " * usage: " << bf_write << "(register, f1(v1), f2(v2), ...)\n";
1269 fout << " *\n";
1270 fout << " * effect: change the register value so that field fi has value vi\n";
1271 fout << " * note: register must be fully qualified if indexed\n";
1272 fout << " * note: this macro may perform a read-modify-write\n";
1273 fout << " *\n";
1274 fout << " * example: " << bf_write << "(ICOLL_CTRL, SFTRST(1), CLKGATE(0), TZ_LOCK_V(UNLOCKED))\n";
1275 fout << " * " << bf_write << "(ICOLL_ENABLE(3), CPU0_PRIO(1), CPU0_TYPE_V(FIQ))\n";
1276 fout << " */\n";
1277 fout << "#define " << bf_write << "(name, ...) "
1278 << bf_write << "_(name, " << safe_macro_paste(false, type_xfix(MT_REG_NAME, true))
1279 << "name" << safe_macro_paste(true, type_xfix(MT_REG_NAME, false)) << ", __VA_ARGS__)\n";
1280 fout << "#define " << bf_write << "_(name, name2, ...) "
1281 << safe_macro_paste(false, type_xfix(MT_REG_TYPE, true)) << "name"
1282 << safe_macro_paste(true, type_xfix(MT_REG_TYPE, false))
1283 << "(" << register_op_name(RO_RMW) << ", name, "
1284 << "~" << macro_name(MN_FIELD_OR_MASK) << "(name2, __VA_ARGS__), "
1285 << macro_name(MN_FIELD_OR) << "(name2, __VA_ARGS__))\n";
1286 fout << "\n";
1287
1288 /* print FIELD_OVERWRITE macro */
1289 std::string bf_overwrite = macro_name(MN_FIELD_OVERWRITE);
1290 fout << "/** " << bf_overwrite << "\n";
1291 fout << " *\n";
1292 fout << " * usage: " << bf_overwrite << "(register, f1(v1), f2(v2), ...)\n";
1293 fout << " *\n";
1294 fout << " * effect: change the register value so that field fi has value vi and other fields have value zero\n";
1295 fout << " * thus this macro is equivalent to:\n";
1296 fout << " * " << reg_write << "(register, " << bf_or << "(register, f1(v1), ...))\n";
1297 fout << " * note: register must be fully qualified if indexed\n";
1298 fout << " * note: this macro will overwrite the register (it is NOT a read-modify-write)\n";
1299 fout << " *\n";
1300 fout << " * example: " << bf_overwrite << "(ICOLL_CTRL, SFTRST(1), CLKGATE(0), TZ_LOCK_V(UNLOCKED))\n";
1301 fout << " * " << bf_overwrite << "(ICOLL_ENABLE(3), CPU0_PRIO(1), CPU0_TYPE_V(FIQ))\n";
1302 fout << " */\n";
1303 fout << "#define " << bf_overwrite << "(name, ...) "
1304 << bf_overwrite << "_(name, " << safe_macro_paste(false, type_xfix(MT_REG_NAME, true))
1305 << "name" << safe_macro_paste(true, type_xfix(MT_REG_NAME, false)) << ", __VA_ARGS__)\n";
1306 fout << "#define " << bf_overwrite << "_(name, name2, ...) "
1307 << safe_macro_paste(false, type_xfix(MT_REG_TYPE, true)) << "name"
1308 << safe_macro_paste(true, type_xfix(MT_REG_TYPE, false))
1309 << "(" << register_op_name(RO_WRITE) << ", name, "
1310 << macro_name(MN_FIELD_OR) << "(name2, __VA_ARGS__))\n";
1311 fout << "\n";
1312
1313 /* print FIELD_WRITEX macro */
1314 std::string bf_writex = macro_name(MN_FIELD_WRITEX);
1315 fout << "/** " << bf_writex << "\n";
1316 fout << " *\n";
1317 fout << " * usage: " << bf_writex << "(var, register, f1(v1), f2(v2), ...)\n";
1318 fout << " *\n";
1319 fout << " * effect: change the variable value so that field fi has value vi\n";
1320 fout << " * note: this macro will perform a read-modify-write\n";
1321 fout << " *\n";
1322 fout << " * example: " << bf_writex << "(var, ICOLL_CTRL, SFTRST(1), CLKGATE(0), TZ_LOCK_V(UNLOCKED))\n";
1323 fout << " * " << bf_writex << "(var, ICOLL_ENABLE, CPU0_PRIO(1), CPU0_TYPE_V(FIQ))\n";
1324 fout << " */\n";
1325 fout << "#define " << bf_writex << "(var, name, ...) "
1326 << "(var) = " << macro_name(MN_FIELD_OR) << "(name, __VA_ARGS__) | (~"
1327 << macro_name(MN_FIELD_OR_MASK) << "(name, __VA_ARGS__) & (var))\n";
1328 fout << "\n";
1329
1330 /* print FIELD_SET/FIELD_CLEAR macro */
1331 for(int i = 0; i < 2; i++)
1332 {
1333 macro_name_t n = (i == 0) ? MN_FIELD_SET : MN_FIELD_CLEAR;
1334 std::string bf_set = macro_name(n);
1335 std::string set_var = sct_variant(n);
1336
1337 fout << "/** " << bf_set << "\n";
1338 fout << " *\n";
1339 fout << " * usage: " << bf_set << "(register, f1, f2, ...)\n";
1340 fout << " *\n";
1341 fout << " * effect: change the register value so that field fi has ";
1342 if(i == 0)
1343 fout << "maximum value\n";
1344 else
1345 fout << "value zero\n";
1346 if(has_sct())
1347 fout << " * IMPORTANT: this macro performs a write to the " << set_var << " variant of the register\n";
1348 else
1349 fout << " * note: this macro will perform a read-modify-write\n";
1350
1351 fout << " * note: register must be fully qualified if indexed\n";
1352 fout << " *\n";
1353 fout << " * example: " << bf_set << "(ICOLL_CTRL, SFTRST, CLKGATE)\n";
1354 fout << " * " << bf_set << "(ICOLL_ENABLE(3), CPU0_PRIO, CPU0_TYPE)\n";
1355 fout << " */\n";
1356
1357 if(has_sct())
1358 {
1359 fout << "#define " << bf_set << "(name, ...) " << bf_set << "_("
1360 << macro_name(MN_GET_VARIANT) << "(name, " << variant_xfix(set_var, true)
1361 << ", " << variant_xfix(set_var, false) << "), "
1362 << safe_macro_paste(false, type_xfix(MT_REG_NAME, true))
1363 << "name" << safe_macro_paste(true, type_xfix(MT_REG_NAME, false))
1364 << ", __VA_ARGS__)\n";
1365 fout << "#define " << bf_set << "_(name, name2, ...) " << macro_name(MN_REG_WRITE)
1366 << "(name, " << macro_name(MN_MASK_OR) << "(name2, __VA_ARGS__))\n";
1367 }
1368 else
1369 {
1370 fout << "#define " << bf_set << "(name, ...) "
1371 << bf_set << "_(name, " << safe_macro_paste(false, type_xfix(MT_REG_NAME, true))
1372 << "name" << safe_macro_paste(true, type_xfix(MT_REG_NAME, false)) << ", __VA_ARGS__)\n";
1373 fout << "#define " << bf_set << "_(name, name2, ...) "
1374 << safe_macro_paste(false, type_xfix(MT_REG_TYPE, true)) << "name"
1375 << safe_macro_paste(true, type_xfix(MT_REG_TYPE, false))
1376 << "(" << register_op_name(RO_RMW) << ", name, ~";
1377 if(i == 0)
1378 fout << "0," << macro_name(MN_MASK_OR) << "(name2, __VA_ARGS__))\n";
1379 else
1380 fout << macro_name(MN_MASK_OR) << "(name2, __VA_ARGS__), 0)\n";
1381 }
1382 fout << "\n";
1383 }
1384
1385 if(has_sct())
1386 {
1387 std::string set_var = sct_variant(MN_FIELD_SET);
1388 std::string clr_var = sct_variant(MN_FIELD_CLEAR);
1389 /* print REG_CS */
1390 std::string reg_cs = macro_name(MN_REG_CLEAR_SET);
1391 fout << "/** " << reg_cs << "\n";
1392 fout << " *\n";
1393 fout << " * usage: " << reg_cs << "(register, clear_value, set_value)\n";
1394 fout << " *\n";
1395 fout << " * effect: clear some bits using " << set_var << " variant and then set some using " << set_var << " variant\n";
1396 fout << " * note: register must be fully qualified if indexed\n";
1397 fout << " *\n";
1398 fout << " * example: " << reg_cs << "(ICOLL_CTRL, 0xff, 0x42)\n";
1399 fout << " * " << reg_cs << "(ICOLL_ENABLE(3), 0xff, 0x37)\n";
1400 fout << " */\n";
1401 fout << "#define " << reg_cs << "(name, cval, sval) "
1402 << reg_cs << "_(" << macro_name(MN_GET_VARIANT) << "(name, "
1403 << variant_xfix(clr_var, true) << ", " << variant_xfix(clr_var, false) << "), "
1404 << macro_name(MN_GET_VARIANT) << "(name, " << variant_xfix(set_var, true)
1405 << ", " << variant_xfix(set_var, false) << "), cval, sval)\n";
1406 fout << "#define " << reg_cs << "_(cname, sname, cval, sval) "
1407 << "do { " << macro_name(MN_REG_WRITE) << "(cname, cval); "
1408 << macro_name(MN_REG_WRITE) << "(sname, sval); } while(0)\n";
1409 fout << "\n";
1410
1411 /* print BF_CS */
1412 std::string bf_cs = macro_name(MN_FIELD_CLEAR_SET);
1413 fout << "/** " << bf_cs << "\n";
1414 fout << " *\n";
1415 fout << " * usage: " << bf_cs << "(register, f1(v1), f2(v2), ...)\n";
1416 fout << " *\n";
1417 fout << " * effect: change the register value so that field fi has value vi using " << clr_var << " and " << set_var << " variants\n";
1418 fout << " * note: register must be fully qualified if indexed\n";
1419 fout << " * note: this macro will NOT perform a read-modify-write and is thus safer\n";
1420 fout << " * IMPORTANT: this macro will set some fields to 0 temporarily, make sure this is acceptable\n";
1421 fout << " *\n";
1422 fout << " * example: " << bf_cs << "(ICOLL_CTRL, SFTRST(1), CLKGATE(0), TZ_LOCK_V(UNLOCKED))\n";
1423 fout << " * " << bf_cs << "(ICOLL_ENABLE(3), CPU0_PRIO(1), CPU0_TYPE_V(FIQ))\n";
1424 fout << " */\n";
1425 fout << "#define " << bf_cs << "(name, ...) "
1426 << bf_cs << "_(name, " << safe_macro_paste(false, type_xfix(MT_REG_NAME, true))
1427 << "name" << safe_macro_paste(true, type_xfix(MT_REG_NAME, false)) << ", __VA_ARGS__)\n";
1428 fout << "#define " << bf_cs << "_(name, name2, ...) "
1429 << macro_name(MN_REG_CLEAR_SET) << "(name, " << macro_name(MN_FIELD_OR_MASK)
1430 << "(name2, __VA_ARGS__), " << macro_name(MN_FIELD_OR) << "(name2, __VA_ARGS__))\n";
1431 fout << "\n";
1432 }
1433
1434 /* print REG_VAR macro */
1435 std::string reg_var = macro_name(MN_VARIABLE);
1436 fout << "/** " << reg_var << "\n";
1437 fout << " *\n";
1438 fout << " * usage: " << reg_var << "(register)\n";
1439 fout << " *\n";
1440 fout << " * effect: return a variable-like expression that can be read/written\n";
1441 fout << " * note: register must be fully qualified if indexed\n";
1442 fout << " * note: read-only registers will yield a constant expression\n";
1443 fout << " *\n";
1444 fout << " * example: unsigned x = " << reg_var << "(ICOLL_STATUS)\n";
1445 fout << " * unsigned x = " << reg_var << "(ICOLL_ENABLE(42))\n";
1446 fout << " * " << reg_var << "(ICOLL_ENABLE(42)) = 64\n";
1447 fout << " */\n";
1448 fout << "#define " << reg_var << "(name) "
1449 << safe_macro_paste(false, type_xfix(MT_REG_TYPE, true)) << "name"
1450 << safe_macro_paste(true, type_xfix(MT_REG_TYPE, false))
1451 << "(" << register_op_name(RO_VAR) << ", name)\n";
1452 fout << "\n";
1453
1454 print_guard(fout, guard, false);
1455 fout.close();
1456 return true;
1457}
1458
1459bool common_generator::generate(error_context_t& ectx)
1460{
1461 /* first find which inst goes to which file */
1462 std::map< std::string, std::vector< pseudo_node_inst_t > > regmap;
1463 for(size_t i = 0; i < m_soc.size(); i++)
1464 {
1465 soc_ref_t soc(&m_soc[i]);
1466 pseudo_node_inst_t inst;
1467 inst.inst = soc.root_inst();
1468 gather_files(inst, has_selectors() ? selector_soc_dir(soc) + "/" :
1469 "", regmap);
1470 }
1471 /* create output directory */
1472 create_dir(m_outdir);
1473 /* print files */
1474 std::map< std::string, std::vector< pseudo_node_inst_t > >::iterator it = regmap.begin();
1475 for(; it != regmap.end(); ++it)
1476 {
1477 create_alldir(m_outdir, it->first.c_str());
1478 std::ofstream fout((m_outdir + "/" + it->first).c_str());
1479 if(!fout)
1480 {
1481 printf("Cannot create '%s'\n", (m_outdir + "/" + it->first).c_str());
1482 return false;
1483 }
1484 std::vector< soc_ref_t > soc_list = list_socs(it->second);
1485 print_copyright(fout, soc_list);
1486 std::string guard = header_include_guard(it->first);
1487 print_guard(fout, guard, true);
1488
1489 /* if we generate selectors, we include the macro header in them, otherwise
1490 * we include the macro header right here */
1491 if(!has_selectors())
1492 {
1493 fout << "\n";
1494 fout << "#include \"" << macro_header() << "\"\n";
1495 }
1496
1497 for(size_t i = 0; i < it->second.size(); i++)
1498 {
1499 if(!generate_register(fout, it->second[i]))
1500 {
1501 printf("Cannot generate register");
1502 print_inst(it->second[i]);
1503 return false;
1504 }
1505 }
1506
1507 print_guard(fout, guard, false);
1508 fout.close();
1509 }
1510 /* for selectors only */
1511 if(has_selectors())
1512 {
1513 /* list all possible headers and per soc headers */
1514 std::map< std::string, std::set< soc_ref_t > > headers;
1515 for(it = regmap.begin(); it != regmap.end(); ++it)
1516 {
1517 /* pick the first instance in the file to extract the file name */
1518 node_inst_t inst = it->second[0].inst;
1519 headers[register_header(inst)].insert(inst.node().soc());
1520 }
1521 /* create selector headers */
1522 std::map< std::string, std::set< soc_ref_t > >::iterator jt;
1523 for(jt = headers.begin(); jt != headers.end(); ++jt)
1524 {
1525 std::ofstream fout((m_outdir + "/" + jt->first).c_str());
1526 if(!fout)
1527 {
1528 printf("Cannot create selector '%s'\n", (m_outdir + "/" + jt->first).c_str());
1529 return false;
1530 }
1531 print_copyright(fout, std::vector< soc_ref_t >());
1532 std::string guard = header_include_guard(jt->first);
1533 print_guard(fout, guard, true);
1534
1535 /* if we generate selectors, we include the macro header in them */
1536 fout << "\n";
1537 fout << "#include \"" << macro_header() << "\"\n";
1538
1539 std::set< soc_ref_t >::iterator kt;
1540 define_align_context_t ctx;
1541 for(kt = jt->second.begin(); kt != jt->second.end(); ++kt)
1542 {
1543 std::ostringstream oss;
1544 oss << "\"" << selector_soc_dir(*kt) << "/" << jt->first << "\"";
1545 ctx.add(selector_soc_macro(*kt), oss.str());
1546 }
1547 fout << "\n";
1548 ctx.print(fout);
1549 fout << "\n";
1550 fout << "#include \"" << selector_include_header() << "\"\n";
1551 fout << "\n";
1552 for(kt = jt->second.begin(); kt != jt->second.end(); ++kt)
1553 fout << "#undef " << selector_soc_macro(*kt) << "\n";
1554
1555 print_guard(fout, guard, false);
1556 fout.close();
1557 }
1558 }
1559 /* generate macro header */
1560 if(!generate_macro_header(ectx))
1561 return false;
1562 return true;
1563}
1564
1565/**
1566 * Generator: jz
1567 */
1568
1569class jz_generator : public common_generator
1570{
1571 bool has_selectors() const
1572 {
1573 return m_soc.size() >= 2;
1574 }
1575
1576 std::string selector_soc_dir(const soc_ref_t& ref) const
1577 {
1578 return ref.get()->name;
1579 }
1580
1581 std::string selector_include_header() const
1582 {
1583 return "select.h";
1584 }
1585
1586 std::string selector_soc_macro(const soc_ref_t& ref) const
1587 {
1588 return toupper(ref.get()->name) + "_INCLUDE";
1589 }
1590
1591 std::string register_header(const node_inst_t& inst) const
1592 {
1593 /* one register header per top-level block */
1594 if(inst.is_root())
1595 return "<error>";
1596 if(inst.parent().is_root())
1597 return tolower(inst.node().name()) + ".h";
1598 else
1599 return register_header(inst.parent());
1600 }
1601
1602 std::string macro_name(macro_name_t macro) const
1603 {
1604 switch(macro)
1605 {
1606 case MN_REG_READ: return "jz_read";
1607 case MN_FIELD_READ: return "jz_readf";
1608 case MN_FIELD_READX: return "jz_vreadf";
1609 case MN_REG_WRITE: return "jz_write";
1610 case MN_FIELD_WRITE: return "jz_writef";
1611 case MN_FIELD_OVERWRITE: return "jz_overwritef";
1612 case MN_FIELD_WRITEX: return "jz_vwritef";
1613 case MN_FIELD_SET: return "jz_setf";
1614 case MN_FIELD_CLEAR: return "jz_clrf";
1615 case MN_FIELD_TOG: return "jz_togf";
1616 case MN_FIELD_CLEAR_SET: return "jz_csf";
1617 case MN_FIELD_OR: return "jz_orf";
1618 case MN_FIELD_OR_MASK: return "__jz_orfm"; // internal macro
1619 case MN_MASK_OR: return "jz_orm";
1620 case MN_REG_CLEAR_SET: return "jz_cs";
1621 case MN_GET_VARIANT: return "__jz_variant"; // internal macro
1622 case MN_VARIABLE: return "jz_reg";
1623 default: return "<macro_name>";
1624 }
1625 }
1626
1627 std::string macro_header() const
1628 {
1629 return "macro.h";
1630 }
1631
1632 bool register_flag(const node_inst_t& inst, register_flag_t flag) const
1633 {
1634 /* make everything parametrized */
1635 switch(flag)
1636 {
1637 case RF_GENERATE_ALL_INST: return false;
1638 case RF_GENERATE_PARAM_INST: return true;
1639 default: return false;
1640 }
1641 }
1642
1643 std::string type_xfix(macro_type_t type, bool prefix) const
1644 {
1645 switch(type)
1646 {
1647 case MT_REG_ADDR: return prefix ? "JA_" : "";
1648 case MT_REG_TYPE: return prefix ? "JT_" : "";
1649 case MT_REG_NAME: return prefix ? "JN_" : "";
1650 case MT_REG_INDEX: return prefix ? "JI_" : "";
1651 case MT_REG_VAR: return prefix ? "REG_" : "";
1652 case MT_FIELD_BP: return prefix ? "BP_" : "";
1653 case MT_FIELD_BM: return prefix ? "BM_" : "";
1654 case MT_FIELD_BV: return prefix ? "BV_" : "";
1655 case MT_FIELD_BF: return prefix ? "BF_" : "";
1656 case MT_FIELD_BFM: return prefix ? "BFM_" : "";
1657 case MT_FIELD_BFV: return prefix ? "BF_" : "_V";
1658 case MT_FIELD_BFMV: return prefix ? "BFM_" : "_V";
1659 case MT_IO_TYPE: return prefix ? "JIO_" : "";
1660 default: return "<xfix>";
1661 }
1662 }
1663
1664 std::string variant_xfix(const std::string& variant, bool prefix) const
1665 {
1666 /* variant X -> reg_X */
1667 if(prefix)
1668 return "";
1669 else
1670 return "_" + toupper(variant);
1671 }
1672
1673 std::string inst_prefix(const node_inst_t& inst) const
1674 {
1675 /* separate blocks with _: block_reg */
1676 return "_";
1677 }
1678
1679 std::string field_prefix() const
1680 {
1681 /* separate fields with _: block_reg_field */
1682 return "_";
1683 }
1684
1685 std::string enum_prefix() const
1686 {
1687 /* separate enums with __: block_reg_field__enum */
1688 return "__";
1689 }
1690
1691 std::string enum_name(const enum_ref_t& enum_) const
1692 {
1693 return enum_.get()->name;
1694 }
1695
1696 access_type_t register_access(const std::string& variant, access_t access) const
1697 {
1698 /* SET and CLR are special and always promoted to WO */
1699 if(variant == "set" || variant == "clr" || access == WRITE_ONLY)
1700 return AT_WO;
1701 else if(access == READ_ONLY)
1702 return AT_RO;
1703 else
1704 return AT_RW;
1705 }
1706
1707 bool has_sct() const
1708 {
1709 return true;
1710 }
1711
1712 std::string sct_variant(macro_name_t name) const
1713 {
1714 switch(name)
1715 {
1716 case MN_FIELD_SET: return "set"; // always use set variant
1717 case MN_FIELD_CLEAR: return "clr"; // always use clr variant
1718 default: return "";
1719 }
1720 }
1721};
1722
1723/**
1724 * Generator: imx
1725 */
1726
1727class imx_generator : public common_generator
1728{
1729 bool has_selectors() const
1730 {
1731 return m_soc.size() >= 2;
1732 }
1733
1734 std::string selector_soc_dir(const soc_ref_t& ref) const
1735 {
1736 return ref.get()->name;
1737 }
1738
1739 std::string selector_include_header() const
1740 {
1741 return "select.h";
1742 }
1743
1744 std::string selector_soc_macro(const soc_ref_t& ref) const
1745 {
1746 return toupper(ref.get()->name) + "_INCLUDE";
1747 }
1748
1749 std::string register_header(const node_inst_t& inst) const
1750 {
1751 /* one register header per top-level block */
1752 if(inst.is_root())
1753 return "<error>";
1754 if(inst.parent().is_root())
1755 return tolower(inst.node().name()) + ".h";
1756 else
1757 return register_header(inst.parent());
1758 }
1759
1760 std::string macro_name(macro_name_t macro) const
1761 {
1762 switch(macro)
1763 {
1764 case MN_REG_READ: return "REG_RD";
1765 case MN_FIELD_READ: return "BF_RD";
1766 case MN_FIELD_READX: return "BF_RDX";
1767 case MN_REG_WRITE: return "REG_WR";
1768 case MN_FIELD_WRITE: return "BF_WR";
1769 case MN_FIELD_OVERWRITE: return "BF_WR_ALL";
1770 case MN_FIELD_WRITEX: return "BF_WRX";
1771 case MN_FIELD_SET: return "BF_SET";
1772 case MN_FIELD_CLEAR: return "BF_CLR";
1773 case MN_FIELD_TOG: return "BF_TOG";
1774 case MN_FIELD_CLEAR_SET: return "BF_CS";
1775 case MN_FIELD_OR: return "BF_OR";
1776 case MN_FIELD_OR_MASK: return "__BFM_OR";
1777 case MN_MASK_OR: return "BM_OR";
1778 case MN_REG_CLEAR_SET: return "REG_CS";
1779 case MN_GET_VARIANT: return "__REG_VARIANT";
1780 case MN_VARIABLE: return "HW";
1781 default: return "<macro_name>";
1782 }
1783 }
1784
1785 std::string macro_header() const
1786 {
1787 return "macro.h";
1788 }
1789
1790 bool register_flag(const node_inst_t& inst, register_flag_t flag) const
1791 {
1792 /* make everything parametrized */
1793 switch(flag)
1794 {
1795 case RF_GENERATE_ALL_INST: return false;
1796 case RF_GENERATE_PARAM_INST: return true;
1797 default: return false;
1798 }
1799 }
1800
1801 std::string type_xfix(macro_type_t type, bool prefix) const
1802 {
1803 switch(type)
1804 {
1805 case MT_REG_ADDR: return prefix ? "HWA_" : "";
1806 case MT_REG_TYPE: return prefix ? "HWT_" : "";
1807 case MT_REG_NAME: return prefix ? "HWN_" : "";
1808 case MT_REG_INDEX: return prefix ? "HWI_" : "";
1809 case MT_REG_VAR: return prefix ? "HW_" : "";
1810 case MT_FIELD_BP: return prefix ? "BP_" : "";
1811 case MT_FIELD_BM: return prefix ? "BM_" : "";
1812 case MT_FIELD_BV: return prefix ? "BV_" : "";
1813 case MT_FIELD_BF: return prefix ? "BF_" : "";
1814 case MT_FIELD_BFM: return prefix ? "BFM_" : "";
1815 case MT_FIELD_BFV: return prefix ? "BF_" : "_V";
1816 case MT_FIELD_BFMV: return prefix ? "BFM_" : "_V";
1817 case MT_IO_TYPE: return prefix ? "HWIO_" : "";
1818 default: return "<xfix>";
1819 }
1820 }
1821
1822 std::string variant_xfix(const std::string& variant, bool prefix) const
1823 {
1824 /* variant X -> reg_X */
1825 if(prefix)
1826 return "";
1827 else
1828 return "_" + toupper(variant);
1829 }
1830
1831 std::string inst_prefix(const node_inst_t& inst) const
1832 {
1833 /* separate blocks with _: block_reg */
1834 return "_";
1835 }
1836
1837 std::string field_prefix() const
1838 {
1839 /* separate fields with _: block_reg_field */
1840 return "_";
1841 }
1842
1843 std::string enum_prefix() const
1844 {
1845 /* separate enums with __: block_reg_field__enum */
1846 return "__";
1847 }
1848
1849 std::string enum_name(const enum_ref_t& enum_) const
1850 {
1851 return enum_.get()->name;
1852 }
1853
1854 access_type_t register_access(const std::string& variant, access_t access) const
1855 {
1856 /* SET, CLR and TOG are special and always promoted to WO */
1857 if(variant == "set" || variant == "clr" || variant == "tog" || access == WRITE_ONLY)
1858 return AT_WO;
1859 else if(access == READ_ONLY)
1860 return AT_RO;
1861 else
1862 return AT_RW;
1863 }
1864
1865 bool has_sct() const
1866 {
1867 return true;
1868 }
1869
1870 std::string sct_variant(macro_name_t name) const
1871 {
1872 switch(name)
1873 {
1874 case MN_FIELD_SET: return "set"; // always use set variant
1875 case MN_FIELD_CLEAR: return "clr"; // always use clr variant
1876 case MN_FIELD_TOG: return "tog"; // always use tog variant
1877 default: return "";
1878 }
1879 }
1880};
1881
1882/**
1883 * Driver
1884 */
1885
1886abstract_generator *get_generator(const std::string& name)
1887{
1888 if(name == "jz")
1889 return new jz_generator();
1890 else if(name == "imx")
1891 return new imx_generator();
1892 else
1893 return 0;
1894}
1895
1896void usage()
1897{
1898 printf("usage: headergen [options] <desc files...>\n");
1899 printf("options:\n");
1900 printf(" -?/--help Dispaly this help\n");
1901 printf(" -g/--generator <gen> Select generator (jz, imx)\n");
1902 printf(" -o/--outdir <dir> Output directory\n");
1903 exit(1);
1904}
1905
1906int main(int argc, char **argv)
1907{
1908 char *generator_name = NULL;
1909 char *outdir = NULL;
1910 if(argc <= 1)
1911 usage();
1912
1913 while(1)
1914 {
1915 static struct option long_options[] =
1916 {
1917 {"help", no_argument, 0, '?'},
1918 {"generator", required_argument, 0, 'g'},
1919 {"outdir", required_argument, 0, 'o'},
1920 {0, 0, 0, 0}
1921 };
1922
1923 int c = getopt_long(argc, argv, "?g:o:", long_options, NULL);
1924 if(c == -1)
1925 break;
1926 switch(c)
1927 {
1928 case -1:
1929 break;
1930 case '?':
1931 usage();
1932 break;
1933 case 'g':
1934 generator_name = optarg;
1935 break;
1936 case 'o':
1937 outdir = optarg;
1938 break;
1939 default:
1940 abort();
1941 }
1942 }
1943 if(argc == optind)
1944 {
1945 printf("You need at least one description file\n");
1946 return 3;
1947 }
1948 if(outdir == 0)
1949 {
1950 printf("You need to select an output directory\n");
1951 return 4;
1952 }
1953 if(generator_name == 0)
1954 {
1955 printf("You need to select a generator\n");
1956 return 1;
1957 }
1958 abstract_generator *gen = get_generator(generator_name);
1959 if(gen == 0)
1960 {
1961 printf("Unknown generator name '%s'\n", generator_name);
1962 return 2;
1963 }
1964
1965 gen->set_output_dir(outdir);
1966 for(int i = optind; i < argc; i++)
1967 {
1968 error_context_t ctx;
1969 soc_t s;
1970 bool ret = parse_xml(argv[i], s, ctx);
1971 if(ctx.count() != 0)
1972 printf("In file %s:\n", argv[i]);
1973 print_context(ctx);
1974 if(!ret)
1975 {
1976 printf("Cannot parse file '%s'\n", argv[i]);
1977 return 1;
1978 }
1979 gen->add_soc(s);
1980 }
1981 error_context_t ctx;
1982 bool ret = gen->generate(ctx);
1983 print_context(ctx);
1984 if(!ret)
1985 {
1986 printf("Cannot generate headers\n");
1987 return 5;
1988 }
1989
1990 return 0;
1991}