summaryrefslogtreecommitdiff
path: root/utils/regtools/headergen.cpp
diff options
context:
space:
mode:
authorAmaury Pouly <amaury.pouly@gmail.com>2013-06-13 01:50:14 +0200
committerAmaury Pouly <amaury.pouly@gmail.com>2013-06-13 02:25:08 +0200
commit73db73dbd3c5c6a27e022a5c724136ca6fc2ffe8 (patch)
tree5e73c4b4477b2f47f4581f68d800ef4cb7b8a37a /utils/regtools/headergen.cpp
parent7143ea681c377fe5901bd79801366a26ae0d394a (diff)
downloadrockbox-73db73dbd3c5c6a27e022a5c724136ca6fc2ffe8.tar.gz
rockbox-73db73dbd3c5c6a27e022a5c724136ca6fc2ffe8.zip
regtools: modify description format and refactor tools
Change the XML description to unify multi dev/reg in a clean fashion. Move the description parser to its own library. Fix the tester and headergen tools to work with the new format and library. Move the STMP3700/3780 descriptions to the new format (and fixes many errors as well). Drop the hwemulgen tool in favor on the upcoming hwstub tools revamp. Change-Id: I7119a187aab5c8b083cc5228cb1b248ee29f184d
Diffstat (limited to 'utils/regtools/headergen.cpp')
-rw-r--r--utils/regtools/headergen.cpp311
1 files changed, 218 insertions, 93 deletions
diff --git a/utils/regtools/headergen.cpp b/utils/regtools/headergen.cpp
index b6905363d8..fc1ce6fba6 100644
--- a/utils/regtools/headergen.cpp
+++ b/utils/regtools/headergen.cpp
@@ -7,7 +7,7 @@
7 * \/ \/ \/ \/ \/ 7 * \/ \/ \/ \/ \/
8 * $Id$ 8 * $Id$
9 * 9 *
10 * Copyright (C) 2002 by Amaury Pouly 10 * Copyright (C) 2013 by Amaury Pouly
11 * 11 *
12 * This program is free software; you can redistribute it and/or 12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License 13 * modify it under the terms of the GNU General Public License
@@ -18,22 +18,26 @@
18 * KIND, either express or implied. 18 * KIND, either express or implied.
19 * 19 *
20 ****************************************************************************/ 20 ****************************************************************************/
21#include "desc_parser.hpp" 21#include "soc_desc.hpp"
22#include <stdio.h> 22#include <stdio.h>
23#include <stdlib.h> 23#include <stdlib.h>
24#include <algorithm> 24#include <algorithm>
25#include <map> 25#include <map>
26#include <sstream>
27#include <sys/stat.h>
28#include <sys/types.h>
29
30#define HEADERGEN_VERSION "2.1.7"
26 31
27#define error(...) do{ fprintf(stderr, __VA_ARGS__); exit(1); } while(0) 32#define error(...) do{ fprintf(stderr, __VA_ARGS__); exit(1); } while(0)
28 33
29std::string g_soc_name; 34std::string g_soc_name;
30std::string g_soc_dev; 35std::string g_soc_dev;
31std::string g_soc_reg; 36std::string g_soc_reg;
37std::string g_soc_field;
32std::string g_soc_dev_regs_base; 38std::string g_soc_dev_regs_base;
33std::string g_soc_dev_reg_core_name;
34 39
35namespace { 40namespace {
36
37std::string tolower(const std::string s) 41std::string tolower(const std::string s)
38{ 42{
39 std::string res = s; 43 std::string res = s;
@@ -47,11 +51,32 @@ std::string toupper(const std::string& s)
47 std::transform(res.begin(), res.end(), res.begin(), ::toupper); 51 std::transform(res.begin(), res.end(), res.begin(), ::toupper);
48 return res; 52 return res;
49} 53}
54}
55
56template< typename T >
57std::string to_str(const T& v)
58{
59 std::ostringstream oss;
60 oss << v;
61 return oss.str();
62}
50 63
64template< typename T >
65std::string to_hex(const T& v)
66{
67 std::ostringstream oss;
68 oss << std::hex << v;
69 return oss.str();
51} 70}
52 71
53void fprint_copyright(FILE *f) 72typedef std::pair< std::string, std::string > xml_ver_t;
73
74void fprint_copyright(FILE *f, const std::vector< xml_ver_t >& versions)
54{ 75{
76 std::ostringstream ver;
77 for(size_t i = 0; i < versions.size(); i++)
78 ver << " " << versions[i].first << ":" << versions[i].second;
79
55 fprintf(f,"\ 80 fprintf(f,"\
56/***************************************************************************\n\ 81/***************************************************************************\n\
57 * __________ __ ___.\n\ 82 * __________ __ ___.\n\
@@ -61,8 +86,10 @@ void fprint_copyright(FILE *f)
61 * Firmware |____|_ /\\____/ \\___ >__|_ \\|___ /\\____/__/\\_ \\\n\ 86 * Firmware |____|_ /\\____/ \\___ >__|_ \\|___ /\\____/__/\\_ \\\n\
62 * \\/ \\/ \\/ \\/ \\/\n\ 87 * \\/ \\/ \\/ \\/ \\/\n\
63 * This file was automatically generated by headergen, DO NOT EDIT it.\n\ 88 * This file was automatically generated by headergen, DO NOT EDIT it.\n\
89 * headergen version: " HEADERGEN_VERSION "\n\
90 * XML versions:%s\n\
64 *\n\ 91 *\n\
65 * Copyright (C) 2012 by Amaury Pouly\n\ 92 * Copyright (C) 2013 by Amaury Pouly\n\
66 *\n\ 93 *\n\
67 * This program is free software; you can redistribute it and/or\n\ 94 * This program is free software; you can redistribute it and/or\n\
68 * modify it under the terms of the GNU General Public License\n\ 95 * modify it under the terms of the GNU General Public License\n\
@@ -72,7 +99,13 @@ void fprint_copyright(FILE *f)
72 * This software is distributed on an \"AS IS\" basis, WITHOUT WARRANTY OF ANY\n\ 99 * This software is distributed on an \"AS IS\" basis, WITHOUT WARRANTY OF ANY\n\
73 * KIND, either express or implied.\n\ 100 * KIND, either express or implied.\n\
74 *\n\ 101 *\n\
75 ****************************************************************************/\n"); 102 ****************************************************************************/\n",
103ver.str().c_str());
104}
105
106void fprint_copyright(FILE *f, const xml_ver_t& version)
107{
108 fprint_copyright(f, std::vector< xml_ver_t >(1, version));
76} 109}
77 110
78void fprint_include_guard_ex(FILE *f, bool begin, const std::string& name) 111void fprint_include_guard_ex(FILE *f, bool begin, const std::string& name)
@@ -81,7 +114,6 @@ void fprint_include_guard_ex(FILE *f, bool begin, const std::string& name)
81 { 114 {
82 fprintf(f, "#ifndef %s\n", name.c_str()); 115 fprintf(f, "#ifndef %s\n", name.c_str());
83 fprintf(f, "#define %s\n", name.c_str()); 116 fprintf(f, "#define %s\n", name.c_str());
84 fprintf(f, "\n#include \"imx233.h\"\n");
85 } 117 }
86 else 118 else
87 fprintf(f, "#endif /* %s */\n", name.c_str()); 119 fprintf(f, "#endif /* %s */\n", name.c_str());
@@ -89,108 +121,188 @@ void fprint_include_guard_ex(FILE *f, bool begin, const std::string& name)
89 121
90void fprint_include_guard(FILE *f, bool begin) 122void fprint_include_guard(FILE *f, bool begin)
91{ 123{
92 std::string name = "__" + toupper(g_soc_name) + "__" + toupper(g_soc_dev) 124 std::string name = "__HEADERGEN__" + toupper(g_soc_name) + "__" + toupper(g_soc_dev)
93 + "__H__"; 125 + "__H__";
94 fprint_include_guard_ex(f, begin, name); 126 fprint_include_guard_ex(f, begin, name);
95} 127}
96 128
97void fprint_fields(FILE *f, const std::vector< soc_reg_field_t >& fields) 129struct define_align_context_t
98{ 130{
99 for(size_t i = 0; i < fields.size(); i++) 131 define_align_context_t():m_max_name(0) {}
132 void add(const std::string& name, const std::string& val)
100 { 133 {
101 fprintf(f, "#define BM_%s_%s %#x\n", g_soc_dev_reg_core_name.c_str(), 134 m_lines.push_back(std::make_pair(name, val));
102 fields[i].name.c_str(), fields[i].bitmask()); 135 m_max_name = std::max(m_max_name, name.size());
103 fprintf(f, "#define BP_%s_%s %d\n", g_soc_dev_reg_core_name.c_str(), 136 }
104 fields[i].name.c_str(), fields[i].first_bit); 137
105 fprintf(f, "#define BF_%s_%s(v) (((v) << %d) & %#x)\n", 138 void print(FILE *f)
106 g_soc_dev_reg_core_name.c_str(), fields[i].name.c_str(), 139 {
107 fields[i].first_bit, fields[i].bitmask()); 140 std::string define = "#define ";
108 if(fields[i].values.size() > 0) 141 size_t align = define.size() + m_max_name + 1;
109 { 142 align = ((align + 3) / 4) * 4;
110 fprintf(f, "#define BF_%s_%s_V(sym) ((BV_%s_%s__##sym << %d) & %#x)\n", 143
111 g_soc_dev_reg_core_name.c_str(), fields[i].name.c_str(), 144 for(size_t i = 0; i < m_lines.size(); i++)
112 g_soc_dev_reg_core_name.c_str(), fields[i].name.c_str(),
113 fields[i].first_bit, fields[i].bitmask());
114 }
115 for(size_t j = 0; j < fields[i].values.size(); j++)
116 { 145 {
117 fprintf(f, "#define BV_%s_%s__%s %#x\n", g_soc_dev_reg_core_name.c_str(), 146 std::string name = m_lines[i].first;
118 fields[i].name.c_str(), fields[i].values[j].name.c_str(), 147 name.insert(name.end(), align - define.size() - name.size(), ' ');
119 fields[i].values[j].value); 148 fprintf(f, "%s%s%s\n", define.c_str(), name.c_str(), m_lines[i].second.c_str());
120 } 149 }
121 } 150 }
151
152 size_t m_max_name;
153 std::vector< std::pair< std::string, std::string > > m_lines;
154};
155
156void gen_soc_field(define_align_context_t& ctx, bool multidev, bool multireg, const soc_reg_field_t& field)
157{
158 std::string prefix = g_soc_dev + "_" + g_soc_reg + "_" + g_soc_field;
159 ctx.add("BP_" + prefix, to_str(field.first_bit));
160 ctx.add("BM_" + prefix, "0x" + to_hex(field.bitmask()));
161
162 for(size_t i = 0; i < field.value.size(); i++)
163 ctx.add("BV_" + prefix + "__" + field.value[i].name, "0x" + to_hex(field.value[i].value));
164
165 ctx.add("BF_" + prefix + "(v)", "(((v) << " + to_str(field.first_bit) + ") & 0x" + to_hex(field.bitmask()) + ")");
166
167 if(field.value.size() > 0)
168 ctx.add("BF_" + prefix + "_V(v)", "((BV_" + prefix + "__##v" + " << " + to_str(field.first_bit) + ") & 0x" + to_hex(field.bitmask()) + ")");
122} 169}
123 170
124void fprint_reg(FILE *f, const soc_reg_t& reg) 171void gen_soc_reg(FILE *f, bool multidev, const soc_reg_t& reg)
125{ 172{
126 g_soc_dev_reg_core_name = toupper(g_soc_dev) + "_" + toupper(reg.name); 173 bool multireg = reg.addr.size() > 1;
127 174
128 fprintf(f, "#define RA_%s %#x\n", g_soc_dev_reg_core_name.c_str(), reg.addr); 175 static const char *suffix[] = {"", "_SET", "_CLR", "_TOG"};
129 fprintf(f, "#define HW_%s HW_REG(%s, %s)\n", g_soc_dev_reg_core_name.c_str(), 176 bool sct = !!(reg.flags & REG_HAS_SCT);
130 toupper(g_soc_dev).c_str(), toupper(reg.name).c_str()); 177
131 if(reg.flags & REG_HAS_SCT) 178 fprintf(f, "/**\n");
179 fprintf(f, " * Register: HW_%s_%s\n", g_soc_dev.c_str(), g_soc_reg.c_str());
180 fprintf(f, " * Address:");
181 if(multireg && reg.formula.type == REG_FORMULA_STRING)
132 { 182 {
133 fprintf(f, "#define HW_%s_SET HW_SET(%s, %s)\n", g_soc_dev_reg_core_name.c_str(), 183 fprintf(f, " %s\n", reg.formula.string.c_str());
134 toupper(g_soc_dev).c_str(), toupper(reg.name).c_str());
135 fprintf(f, "#define HW_%s_CLR HW_CLR(%s, %s)\n", g_soc_dev_reg_core_name.c_str(),
136 toupper(g_soc_dev).c_str(), toupper(reg.name).c_str());
137 fprintf(f, "#define HW_%s_TOG HW_TOG(%s, %s)\n", g_soc_dev_reg_core_name.c_str(),
138 toupper(g_soc_dev).c_str(), toupper(reg.name).c_str());
139 } 184 }
140 fprint_fields(f, reg.fields); 185 else
141 fprintf(f, "\n"); 186 {
142} 187 for(size_t i = 0; i < reg.addr.size(); i++)
188 fprintf(f, " %#x", reg.addr[i].addr);
189 fprintf(f, "\n");
190 }
191 fprintf(f, " * SCT: %s\n", sct ? "yes" : "no");
143 192
144void fprint_mreg(FILE *f, const soc_multireg_t& mreg) 193 fprintf(f, "*/\n");
145{ 194
195 define_align_context_t ctx;
196
197 for(int i = 0; i < (sct ? 4 : 1); i++)
198 {
199 std::ostringstream name;
200 name << "HW_" << g_soc_dev << "_" << g_soc_reg << suffix[i];
201 if(multidev || multireg)
202 {
203 name << "(";
204 if(multidev)
205 name << "d";
206 if(multidev && multireg)
207 name << ",";
208 if(multireg)
209 name << "n";
210 name << ")";
211 }
212 std::ostringstream value;
213 value << "(*(volatile unsigned long *)(" << g_soc_dev_regs_base;
214 if(multidev)
215 value << "(d)";
216 value << " + ";
217 if(multireg)
218 {
219 if(reg.formula.type != REG_FORMULA_STRING)
220 printf("Warning: register HW_%s_%s has no formula !\n", g_soc_dev.c_str(), g_soc_reg.c_str());
221 std::string formula = reg.formula.string.c_str();
222 size_t pos = formula.find("n");
223 while(pos != std::string::npos)
224 {
225 formula.replace(pos, 1, "(n)");
226 pos = formula.find("n", pos + 2);
227 }
228 value << formula;
229 }
230 else
231 value << "0x" << std::hex << reg.addr[0].addr;
232
233 if(sct)
234 value << " + 0x" << std::hex << (i * 4);
235 value << "))";
236
237 ctx.add(name.str(), value.str());
238 }
239
240 for(size_t i = 0; i < reg.field.size(); i++)
241 {
242 g_soc_field = reg.field[i].name;
243 gen_soc_field(ctx, multidev, multireg, reg.field[i]);
244 }
245
246 ctx.print(f);
247
248 fprintf(f, "\n");
146} 249}
147 250
148void gen_dev_header(const std::string& filename, const soc_dev_t& dev) 251void gen_soc_dev_header(const std::string& filename, const xml_ver_t& ver, const soc_dev_t& dev)
149{ 252{
150 g_soc_dev = dev.name; 253 /*
151 printf(" Generate header for device %s: write to %s\n", dev.name.c_str(), 254 printf("Generate headers for soc %s, dev %s: use file %s\n", g_soc_name.c_str(),
152 filename.c_str()); 255 g_soc_dev.c_str(), filename.c_str());
256 */
153 FILE *f = fopen(filename.c_str(), "w"); 257 FILE *f = fopen(filename.c_str(), "w");
154 if(f == NULL) 258 if(f == NULL)
155 error("Cannot open file %s\n", filename.c_str()); 259 {
156 fprint_copyright(f); 260 printf("Cannot open %s for writing: %m\n", filename.c_str());
261 return;
262 }
263 fprint_copyright(f, ver);
157 fprint_include_guard(f, true); 264 fprint_include_guard(f, true);
265
266 /* print base */
158 fprintf(f, "\n"); 267 fprintf(f, "\n");
159 g_soc_dev_regs_base = "RB_" + toupper(dev.name); 268 g_soc_dev_regs_base = "REGS_" + g_soc_dev + "_BASE";
160 fprintf(f, "#define %s %#x\n", g_soc_dev_regs_base.c_str(), dev.addr); 269 fprintf(f, "#define %s", g_soc_dev_regs_base.c_str());
161 fprintf(f, "\n");
162 270
163 for(size_t i = 0; i < dev.regs.size(); i++) 271 if(dev.addr.size() > 1)
164 fprint_reg(f, dev.regs[i]); 272 fprintf(f, "(i)");
165 for(size_t i = 0; i < dev.multiregs.size(); i++) 273 fprintf(f, " (");
166 fprint_mreg(f, dev.multiregs[i]);
167 274
275 for(size_t i = 0; i < dev.addr.size() - 1; i++)
276 fprintf(f, "(i) == %d ? %#x : ", (int)i + 1, dev.addr[i].addr);
277
278 fprintf(f, "%#x)\n", dev.addr[dev.addr.size() - 1].addr);
279
280 fprintf(f, "\n");
281
282 /* print version */
283 fprintf(f, "#define REGS_%s_VERSION \"%s\"\n\n", g_soc_dev.c_str(), dev.version.c_str());
284
285 for(size_t i = 0; i < dev.reg.size(); i++)
286 {
287 g_soc_reg = dev.reg[i].name;
288 gen_soc_reg(f, dev.addr.size() > 1, dev.reg[i]);
289 }
290
168 fprint_include_guard(f, false); 291 fprint_include_guard(f, false);
169 fclose(f); 292 fclose(f);
170} 293}
171 294
172void gen_mdev_header(const std::string& filename, const soc_multidev_t& dev)
173{
174 g_soc_dev = dev.name;
175 printf(" Generate header for multi device %s: write to %s\n", dev.name.c_str(),
176 filename.c_str());
177}
178
179void gen_soc_headers(const std::string& prefix, const soc_t& soc) 295void gen_soc_headers(const std::string& prefix, const soc_t& soc)
180{ 296{
181 printf("Generate headers for soc %s: use directory %s (must exists)\n", soc.desc.c_str(), 297 printf("Generate headers for soc %s: use directory %s\n", soc.desc.c_str(),
182 prefix.c_str()); 298 prefix.c_str());
183 for(size_t i = 0; i < soc.devs.size(); i++) 299 mkdir(prefix.c_str(), 0770);
184 { 300
185 std::string name = soc.devs[i].name; 301 for(size_t i = 0; i < soc.dev.size(); i++)
186 name = tolower(name);
187 gen_dev_header(prefix + "/regs-" + name + ".h", soc.devs[i]);
188 }
189 for(size_t i = 0; i < soc.multidevs.size(); i++)
190 { 302 {
191 std::string name = soc.multidevs[i].name; 303 g_soc_dev = soc.dev[i].name;
192 name = tolower(name); 304 xml_ver_t ver(soc.name, soc.dev[i].version);
193 gen_mdev_header(prefix + "/regs-" + name + ".h", soc.multidevs[i]); 305 gen_soc_dev_header(prefix + "/regs-" + tolower(g_soc_dev.c_str()) + ".h", ver, soc.dev[i]);
194 } 306 }
195} 307}
196 308
@@ -203,31 +315,30 @@ void gen_headers(const std::string& prefix, const std::vector< soc_t >& socs)
203 } 315 }
204} 316}
205 317
206typedef std::map< std::string, std::vector< std::string > > general_dev_list_t; 318typedef std::map< std::string, std::vector< std::pair< size_t, size_t > > > general_dev_list_t;
207general_dev_list_t build_general_dev_list(const std::vector< soc_t >& socs) 319general_dev_list_t build_general_dev_list(const std::vector< soc_t >& socs)
208{ 320{
209 general_dev_list_t map; 321 general_dev_list_t map;
210 for(size_t i = 0; i < socs.size(); i++) 322 for(size_t i = 0; i < socs.size(); i++)
211 { 323 {
212 for(size_t j = 0; j < socs[i].devs.size(); j++) 324 for(size_t j = 0; j < socs[i].dev.size(); j++)
213 map[tolower(socs[i].devs[j].name)].push_back(socs[i].name); 325 map[tolower(socs[i].dev[j].name)].push_back(std::make_pair(i,j));
214 for(size_t j = 0; j < socs[i].multidevs.size(); j++)
215 map[tolower(socs[i].multidevs[j].name)].push_back(socs[i].name);
216 } 326 }
217 return map; 327 return map;
218} 328}
219 329
220void gen_select_header(const std::string& filename, const std::string& dev, 330void gen_select_header(const std::string& filename, const std::string& dev,
221 const std::vector< std::string >& socs) 331 const std::vector< std::string >& socs, const std::vector< xml_ver_t >& ver)
222{ 332{
333 /*
223 printf("Generate select header for device %s: write to %s\n", dev.c_str(), 334 printf("Generate select header for device %s: write to %s\n", dev.c_str(),
224 filename.c_str()); 335 filename.c_str());
225 336 */
226 std::string guard = "__SELECT__" + toupper(dev) + "__H__"; 337 std::string guard = "__SELECT__" + toupper(dev) + "__H__";
227 FILE *f = fopen(filename.c_str(), "w"); 338 FILE *f = fopen(filename.c_str(), "w");
228 if(f == NULL) 339 if(f == NULL)
229 error("Cannot open file %s\n", filename.c_str()); 340 error("Cannot open file %s\n", filename.c_str());
230 fprint_copyright(f); 341 fprint_copyright(f, ver);
231 fprint_include_guard_ex(f, true, guard); 342 fprint_include_guard_ex(f, true, guard);
232 fprintf(f, "\n"); 343 fprintf(f, "\n");
233 344
@@ -251,24 +362,38 @@ void gen_selectors(const std::string& prefix, const std::vector< soc_t >& socs)
251{ 362{
252 general_dev_list_t map = build_general_dev_list(socs); 363 general_dev_list_t map = build_general_dev_list(socs);
253 for(general_dev_list_t::iterator it = map.begin(); it != map.end(); ++it) 364 for(general_dev_list_t::iterator it = map.begin(); it != map.end(); ++it)
254 gen_select_header(prefix + "/regs-" + it->first + ".h", it->first, it->second); 365 {
366 std::vector< xml_ver_t > ver;
367 std::vector< std::string > names;
368 for(size_t i = 0; i < it->second.size(); i++)
369 {
370 size_t soc_nr = it->second[i].first;
371 size_t dev_in_soc_nr = it->second[i].second;
372 ver.push_back(std::make_pair(socs[soc_nr].name, socs[soc_nr].dev[dev_in_soc_nr].version));
373 names.push_back(socs[soc_nr].name);
374 }
375 gen_select_header(prefix + "/regs-" + it->first + ".h", it->first, names, ver);
376 }
255} 377}
256 378
257void usage() 379void usage()
258{ 380{
259 printf("usage: headergen <desc file> <output prefix>\n"); 381 printf("usage: headergen <desc files...> <output directory>\n");
260 exit(1); 382 exit(1);
261} 383}
262 384
263int main(int argc, char **argv) 385int main(int argc, char **argv)
264{ 386{
265 if(argc != 3) 387 if(argc < 3)
266 usage(); 388 usage();
267 std::vector< soc_t > socs; 389 std::vector< soc_t > socs;
268 bool ret = parse_soc_desc(argv[1], socs); 390 for(int i = 1; i < argc - 1; i++)
269 printf("parse result: %d\n", ret); 391 if(!soc_desc_parse_xml(argv[i], socs))
270 if(!ret) return 1; 392 {
271 gen_headers(argv[2], socs); 393 printf("Cannot parse %s\n", argv[i]);
272 gen_selectors(argv[2], socs); 394 return 1;
395 }
396 gen_headers(argv[argc - 1], socs);
397 gen_selectors(argv[argc - 1], socs);
273 return 0; 398 return 0;
274} \ No newline at end of file 399} \ No newline at end of file