summaryrefslogtreecommitdiff
path: root/utils/regtools/lib
diff options
context:
space:
mode:
Diffstat (limited to 'utils/regtools/lib')
-rw-r--r--utils/regtools/lib/Makefile9
-rw-r--r--utils/regtools/lib/formula.cpp214
-rw-r--r--utils/regtools/lib/soc_desc.cpp1530
-rw-r--r--utils/regtools/lib/soc_desc.hpp228
-rw-r--r--utils/regtools/lib/soc_desc_v1.cpp990
5 files changed, 2073 insertions, 898 deletions
diff --git a/utils/regtools/lib/Makefile b/utils/regtools/lib/Makefile
index 08021ef941..d7d6c1b07a 100644
--- a/utils/regtools/lib/Makefile
+++ b/utils/regtools/lib/Makefile
@@ -1,18 +1,15 @@
1CC?=gcc 1CC?=gcc
2CXX?=g++ 2CXX?=g++
3AR?=ar 3AR?=ar
4CFLAGS=-Wall -O2 `xml2-config --cflags` -std=c99 -g -fPIC 4INCLUDE=../include/
5CXXFLAGS=-Wall -O2 `xml2-config --cflags` -g -fPIC 5CXXFLAGS=-Wall -O2 `xml2-config --cflags` -g -fPIC -I$(INCLUDE)
6LIB=libsocdesc.a 6LIB=libsocdesc.a
7SRC=$(wildcard *.c) 7SRC=$(wildcard *.c)
8SRCXX=$(wildcard *.cpp) 8SRCXX=$(wildcard *.cpp)
9OBJ=$(SRC:.c=.o) $(SRCXX:.cpp=.o) 9OBJ=$(SRCXX:.cpp=.o)
10 10
11all: $(LIB) $(EXEC) 11all: $(LIB) $(EXEC)
12 12
13%.o: %.c
14 $(CC) $(CFLAGS) -c -o $@ $<
15
16%.o: %.cpp 13%.o: %.cpp
17 $(CXX) $(CXXFLAGS) -c -o $@ $< 14 $(CXX) $(CXXFLAGS) -c -o $@ $<
18 15
diff --git a/utils/regtools/lib/formula.cpp b/utils/regtools/lib/formula.cpp
new file mode 100644
index 0000000000..1a6b16c773
--- /dev/null
+++ b/utils/regtools/lib/formula.cpp
@@ -0,0 +1,214 @@
1#include "soc_desc.hpp"
2#include <cstdarg>
3#include <cstdio>
4
5using namespace soc_desc;
6
7namespace soc_desc
8{
9
10namespace
11{
12
13struct formula_evaluator
14{
15 std::string formula;
16 size_t pos;
17 error_context_t& ctx;
18 std::string m_loc;
19
20 bool err(const char *fmt, ...)
21 {
22 char buffer[256];
23 va_list args;
24 va_start(args, fmt);
25 vsnprintf(buffer,sizeof(buffer), fmt, args);
26 va_end(args);
27 ctx.add(error_t(error_t::FATAL, m_loc, buffer));
28 return false;
29 }
30
31 formula_evaluator(const std::string& s, error_context_t& ctx):pos(0),ctx(ctx)
32 {
33 for(size_t i = 0; i < s.size(); i++)
34 if(!isspace(s[i]))
35 formula.push_back(s[i]);
36 }
37
38 void set_location(const std::string& loc)
39 {
40 m_loc = loc;
41 }
42
43 void adv()
44 {
45 pos++;
46 }
47
48 char cur()
49 {
50 return end() ? 0 : formula[pos];
51 }
52
53 bool end()
54 {
55 return pos >= formula.size();
56 }
57
58 bool parse_digit(char c, int basis, soc_word_t& res)
59 {
60 c = tolower(c);
61 if(isdigit(c))
62 {
63 res = c - '0';
64 return true;
65 }
66 if(basis == 16 && isxdigit(c))
67 {
68 res = c + 10 - 'a';
69 return true;
70 }
71 return false;
72 }
73
74 bool parse_signed(soc_word_t& res)
75 {
76 char op = cur();
77 if(op == '+' || op == '-')
78 {
79 adv();
80 if(!parse_signed(res))
81 return false;
82 if(op == '-')
83 res *= -1;
84 return true;
85 }
86 else if(op == '(')
87 {
88 adv();
89 if(!parse_expression(res))
90 return false;
91 if(cur() != ')')
92 return err("expected ')', got '%c'", cur());
93 adv();
94 return true;
95 }
96 else if(isdigit(op))
97 {
98 res = op - '0';
99 adv();
100 int basis = 10;
101 if(op == '0' && cur() == 'x')
102 {
103 basis = 16;
104 adv();
105 }
106 soc_word_t digit = 0;
107 while(parse_digit(cur(), basis, digit))
108 {
109 res = res * basis + digit;
110 adv();
111 }
112 return true;
113 }
114 else if(isalpha(op) || op == '_')
115 {
116 std::string name;
117 while(isalnum(cur()) || cur() == '_')
118 {
119 name.push_back(cur());
120 adv();
121 }
122 return get_variable(name, res);
123 }
124 else
125 return err("express signed expression, got '%c'", op);
126 }
127
128 bool parse_term(soc_word_t& res)
129 {
130 if(!parse_signed(res))
131 return false;
132 while(cur() == '*' || cur() == '/' || cur() == '%')
133 {
134 char op = cur();
135 adv();
136 soc_word_t tmp;
137 if(!parse_signed(tmp))
138 return false;
139 if(op == '*')
140 res *= tmp;
141 else if(tmp != 0)
142 res = op == '/' ? res / tmp : res % tmp;
143 else
144 return err("division by 0");
145 }
146 return true;
147 }
148
149 bool parse_expression(soc_word_t& res)
150 {
151 if(!parse_term(res))
152 return false;
153 while(!end() && (cur() == '+' || cur() == '-'))
154 {
155 char op = cur();
156 adv();
157 soc_word_t tmp;
158 if(!parse_term(tmp))
159 return false;
160 if(op == '+')
161 res += tmp;
162 else
163 res -= tmp;
164 }
165 return true;
166 }
167
168 bool parse(soc_word_t& res)
169 {
170 bool ok = parse_expression(res);
171 if(ok && !end())
172 err("unexpected character '%c'", cur());
173 return ok && end();
174 }
175
176 virtual bool get_variable(std::string name, soc_word_t& res)
177 {
178 return err("unknown variable '%s'", name.c_str());
179 }
180};
181
182struct my_evaluator : public formula_evaluator
183{
184 const std::map< std::string, soc_word_t>& var;
185
186 my_evaluator(const std::string& formula, const std::map< std::string, soc_word_t>& _var,
187 error_context_t& ctx)
188 :formula_evaluator(formula, ctx), var(_var) {}
189
190 virtual bool get_variable(std::string name, soc_word_t& res)
191 {
192 std::map< std::string, soc_word_t>::const_iterator it = var.find(name);
193 if(it == var.end())
194 return formula_evaluator::get_variable(name, res);
195 else
196 {
197 res = it->second;
198 return true;
199 }
200 }
201};
202
203}
204
205bool evaluate_formula(const std::string& formula,
206 const std::map< std::string, soc_word_t>& var, soc_word_t& result,
207 const std::string& loc, error_context_t& error)
208{
209 my_evaluator e(formula, var, error);
210 e.set_location(loc);
211 return e.parse(result);
212}
213
214} // soc_desc
diff --git a/utils/regtools/lib/soc_desc.cpp b/utils/regtools/lib/soc_desc.cpp
index 90e4e0eb81..4e0e46f00e 100644
--- a/utils/regtools/lib/soc_desc.cpp
+++ b/utils/regtools/lib/soc_desc.cpp
@@ -7,7 +7,7 @@
7 * \/ \/ \/ \/ \/ 7 * \/ \/ \/ \/ \/
8 * $Id$ 8 * $Id$
9 * 9 *
10 * Copyright (C) 2012 by Amaury Pouly 10 * Copyright (C) 2014 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
@@ -27,261 +27,429 @@
27#include <string.h> 27#include <string.h>
28#include <algorithm> 28#include <algorithm>
29#include <cctype> 29#include <cctype>
30#include <sstream>
31#include <limits>
32
33namespace soc_desc
34{
35
36/**
37 * Parser
38 */
30 39
31#define XML_CHAR_TO_CHAR(s) ((const char *)(s)) 40#define XML_CHAR_TO_CHAR(s) ((const char *)(s))
32 41
33#define BEGIN_ATTR_MATCH(attr) \ 42#define BEGIN_ATTR_MATCH(attr) \
34 for(xmlAttr *a = attr; a; a = a->next) { 43 for(xmlAttr *a = attr; a; a = a->next) {
35 44
36#define MATCH_X_ATTR(attr_name, hook, ...) \ 45#define MATCH_UNIQUE_ATTR(attr_name, val, has, parse_fn, ctx) \
37 if(strcmp(XML_CHAR_TO_CHAR(a->name), attr_name) == 0) { \ 46 if(strcmp(XML_CHAR_TO_CHAR(a->name), attr_name) == 0) { \
38 std::string s; \ 47 if(has) \
39 if(!parse_text_attr(a, s) || !hook(s, __VA_ARGS__)) \ 48 return parse_not_unique_attr_error(a, ctx); \
40 return false; \ 49 has = true; \
50 xmlChar *str = NULL; \
51 if(!parse_text_attr_internal(a, str, ctx) || !parse_fn(a, val, str, ctx)) \
52 ret = false; \
41 } 53 }
42 54
43#define SOFT_MATCH_X_ATTR(attr_name, hook, ...) \
44 if(strcmp(XML_CHAR_TO_CHAR(a->name), attr_name) == 0) { \
45 std::string s; \
46 if(parse_text_attr(a, s)) \
47 hook(s, __VA_ARGS__); \
48 }
49
50#define SOFT_MATCH_SCT_ATTR(attr_name, var) \
51 SOFT_MATCH_X_ATTR(attr_name, validate_sct_hook, var)
52
53#define MATCH_TEXT_ATTR(attr_name, var) \
54 MATCH_X_ATTR(attr_name, validate_string_hook, var)
55
56#define MATCH_UINT32_ATTR(attr_name, var) \
57 MATCH_X_ATTR(attr_name, validate_uint32_hook, var)
58
59#define MATCH_BITRANGE_ATTR(attr_name, first, last) \
60 MATCH_X_ATTR(attr_name, validate_bitrange_hook, first, last)
61
62#define END_ATTR_MATCH() \ 55#define END_ATTR_MATCH() \
63 } 56 }
64 57
65#define BEGIN_NODE_MATCH(node) \ 58#define BEGIN_NODE_MATCH(node) \
66 for(xmlNode *sub = node; sub; sub = sub->next) { 59 for(xmlNode *sub = node; sub; sub = sub->next) {
67 60
68#define MATCH_ELEM_NODE(node_name, array, parse_fn) \ 61#define MATCH_ELEM_NODE(node_name, array, parse_fn, ctx) \
69 if(sub->type == XML_ELEMENT_NODE && strcmp(XML_CHAR_TO_CHAR(sub->name), node_name) == 0) { \ 62 if(sub->type == XML_ELEMENT_NODE && strcmp(XML_CHAR_TO_CHAR(sub->name), node_name) == 0) { \
70 array.resize(array.size() + 1); \ 63 array.resize(array.size() + 1); \
71 if(!parse_fn(sub, array.back())) \ 64 if(!parse_fn(sub, array.back(), ctx)) \
72 return false; \ 65 ret = false; \
66 array.back().id = array.size(); \
73 } 67 }
74 68
75#define SOFT_MATCH_ELEM_NODE(node_name, array, parse_fn) \ 69#define MATCH_TEXT_NODE(node_name, array, parse_fn, ctx) \
76 if(sub->type == XML_ELEMENT_NODE && strcmp(XML_CHAR_TO_CHAR(sub->name), node_name) == 0) { \ 70 if(sub->type == XML_ELEMENT_NODE && strcmp(XML_CHAR_TO_CHAR(sub->name), node_name) == 0) { \
71 if(!is_real_text_node(sub)) \
72 return parse_not_text_error(sub, ctx); \
73 xmlChar *content = xmlNodeGetContent(sub); \
77 array.resize(array.size() + 1); \ 74 array.resize(array.size() + 1); \
78 if(!parse_fn(sub, array.back())) \ 75 ret = ret && parse_fn(sub, array.back(), content, ctx); \
79 array.pop_back(); \ 76 xmlFree(content); \
77 }
78
79#define MATCH_UNIQUE_ELEM_NODE(node_name, val, has, parse_fn, ctx) \
80 if(sub->type == XML_ELEMENT_NODE && strcmp(XML_CHAR_TO_CHAR(sub->name), node_name) == 0) { \
81 if(has) \
82 return parse_not_unique_error(sub, ctx); \
83 has = true; \
84 if(!parse_fn(sub, val, ctx)) \
85 ret = false; \
86 }
87
88#define MATCH_UNIQUE_TEXT_NODE(node_name, val, has, parse_fn, ctx) \
89 if(sub->type == XML_ELEMENT_NODE && strcmp(XML_CHAR_TO_CHAR(sub->name), node_name) == 0) { \
90 if(has) \
91 return parse_not_unique_error(sub, ctx); \
92 if(!is_real_text_node(sub)) \
93 return parse_not_text_error(sub, ctx); \
94 has = true; \
95 xmlChar *content = xmlNodeGetContent(sub); \
96 ret = ret && parse_fn(sub, val, content, ctx); \
97 xmlFree(content); \
80 } 98 }
81 99
82#define END_NODE_MATCH() \ 100#define END_NODE_MATCH() \
83 } 101 }
84 102
103#define CHECK_HAS(node, node_name, has, ctx) \
104 if(!has) \
105 ret = ret && parse_missing_error(node, node_name, ctx);
106
107#define CHECK_HAS_ATTR(node, attr_name, has, ctx) \
108 if(!has) \
109 ret = ret && parse_missing_attr_error(node, attr_name, ctx);
110
85namespace 111namespace
86{ 112{
87 113
88bool validate_string_hook(const std::string& str, std::string& s) 114bool is_real_text_node(xmlNode *node)
89{ 115{
90 s = str; 116 for(xmlNode *sub = node->children; sub; sub = sub->next)
117 if(sub->type != XML_TEXT_NODE && sub->type != XML_ENTITY_REF_NODE)
118 return false;
91 return true; 119 return true;
92} 120}
93 121
94bool validate_sct_hook(const std::string& str, soc_reg_flags_t& flags) 122std::string xml_loc(xmlNode *node)
95{ 123{
96 if(str == "yes") flags |= REG_HAS_SCT; 124 std::ostringstream oss;
97 else if(str != "no") return false; 125 oss << "line " << node->line;
98 return true; 126 return oss.str();
99} 127}
100 128
101bool validate_unsigned_long_hook(const std::string& str, unsigned long& s) 129std::string xml_loc(xmlAttr *attr)
102{ 130{
103 char *end; 131 return xml_loc(attr->parent);
104 s = strtoul(str.c_str(), &end, 0);
105 return *end == 0;
106} 132}
107 133
108bool validate_uint32_hook(const std::string& str, uint32_t& s) 134template<typename T>
135bool add_error(error_context_t& ctx, error_t::level_t lvl, T *node,
136 const std::string& msg)
109{ 137{
110 unsigned long u; 138 ctx.add(error_t(lvl, xml_loc(node), msg));
111 if(!validate_unsigned_long_hook(str, u)) return false; 139 return false;
112#if ULONG_MAX > 0xffffffff
113 if(u > 0xffffffff) return false;
114#endif
115 s = u;
116 return true;
117} 140}
118 141
119bool validate_bitrange_hook(const std::string& str, unsigned& first, unsigned& last) 142template<typename T>
143bool add_fatal(error_context_t& ctx, T *node, const std::string& msg)
120{ 144{
121 unsigned long a, b; 145 return add_error(ctx, error_t::FATAL, node, msg);
122 size_t sep = str.find(':');
123 if(sep == std::string::npos) return false;
124 if(!validate_unsigned_long_hook(str.substr(0, sep), a)) return false;
125 if(!validate_unsigned_long_hook(str.substr(sep + 1), b)) return false;
126 if(a > 31 || b > 31 || a < b) return false;
127 first = b;
128 last = a;
129 return true;
130} 146}
131 147
132bool parse_text_attr(xmlAttr *attr, std::string& s) 148template<typename T>
149bool add_warning(error_context_t& ctx, T *node, const std::string& msg)
133{ 150{
134 if(attr->children != attr->last) 151 return add_error(ctx, error_t::WARNING, node, msg);
135 return false;
136 if(attr->children->type != XML_TEXT_NODE)
137 return false;
138 s = XML_CHAR_TO_CHAR(attr->children->content);
139 return true;
140} 152}
141 153
142bool parse_value_elem(xmlNode *node, soc_reg_field_value_t& value) 154bool parse_wrong_version_error(xmlNode *node, error_context_t& ctx)
143{ 155{
144 BEGIN_ATTR_MATCH(node->properties) 156 std::ostringstream oss;
145 MATCH_TEXT_ATTR("name", value.name) 157 oss << "unknown version, only version " << MAJOR_VERSION << " is supported";
146 MATCH_UINT32_ATTR("value", value.value) 158 return add_fatal(ctx, node, oss.str());
147 MATCH_TEXT_ATTR("desc", value.desc) 159}
148 END_ATTR_MATCH()
149 160
150 return true; 161bool parse_not_unique_error(xmlNode *node, error_context_t& ctx)
162{
163 std::ostringstream oss;
164 oss << "there must be a unique <" << XML_CHAR_TO_CHAR(node->name) << "> element";
165 if(node->parent->name)
166 oss << " in <" << XML_CHAR_TO_CHAR(node->parent->name) << ">";
167 else
168 oss << " at root level";
169 return add_fatal(ctx, node, oss.str());
151} 170}
152 171
153bool parse_field_elem(xmlNode *node, soc_reg_field_t& field) 172bool parse_not_unique_attr_error(xmlAttr *attr, error_context_t& ctx)
154{ 173{
155 BEGIN_ATTR_MATCH(node->properties) 174 std::ostringstream oss;
156 MATCH_TEXT_ATTR("name", field.name) 175 oss << "there must be a unique " << XML_CHAR_TO_CHAR(attr->name) << " attribute";
157 MATCH_BITRANGE_ATTR("bitrange", field.first_bit, field.last_bit) 176 oss << " in <" << XML_CHAR_TO_CHAR(attr->parent->name) << ">";
158 MATCH_TEXT_ATTR("desc", field.desc) 177 return add_fatal(ctx, attr, oss.str());
159 END_ATTR_MATCH() 178}
160 179
161 BEGIN_NODE_MATCH(node->children) 180bool parse_missing_error(xmlNode *node, const char *name, error_context_t& ctx)
162 SOFT_MATCH_ELEM_NODE("value", field.value, parse_value_elem) 181{
163 END_NODE_MATCH() 182 std::ostringstream oss;
183 oss << "missing <" << name << "> element";
184 if(node->parent->name)
185 oss << " in <" << XML_CHAR_TO_CHAR(node->parent->name) << ">";
186 else
187 oss << " at root level";
188 return add_fatal(ctx, node, oss.str());
189}
164 190
165 return true; 191bool parse_missing_attr_error(xmlNode *node, const char *name, error_context_t& ctx)
192{
193 std::ostringstream oss;
194 oss << "missing " << name << " attribute";
195 oss << " in <" << XML_CHAR_TO_CHAR(node->name) << ">";
196 return add_fatal(ctx, node, oss.str());
166} 197}
167 198
168bool parse_reg_addr_elem(xmlNode *node, soc_reg_addr_t& addr) 199bool parse_conflict_error(xmlNode *node, const char *name1, const char *name2,
200 error_context_t& ctx)
169{ 201{
170 BEGIN_ATTR_MATCH(node->properties) 202 std::ostringstream oss;
171 MATCH_TEXT_ATTR("name", addr.name) 203 oss << "conflicting <" << name1 << "> and <" << name2 << "> elements";
172 MATCH_UINT32_ATTR("addr", addr.addr) 204 if(node->parent->name)
173 END_ATTR_MATCH() 205 oss << " in <" << XML_CHAR_TO_CHAR(node->parent->name) << ">";
206 else
207 oss << " at root level";
208 return add_fatal(ctx, node, oss.str());
209}
174 210
175 return true; 211bool parse_not_text_error(xmlNode *node, error_context_t& ctx)
212{
213 return add_fatal(ctx, node, "this is not a text element");
176} 214}
177 215
178bool parse_reg_formula_elem(xmlNode *node, soc_reg_formula_t& formula) 216bool parse_not_text_attr_error(xmlAttr *attr, error_context_t& ctx)
179{ 217{
180 BEGIN_ATTR_MATCH(node->properties) 218 return add_fatal(ctx, attr, "this is not a text attribute");
181 MATCH_TEXT_ATTR("string", formula.string) 219}
182 END_ATTR_MATCH()
183 220
184 formula.type = REG_FORMULA_STRING; 221bool parse_text_elem(xmlNode *node, std::string& name, xmlChar *content, error_context_t& ctx)
222{
223 name = XML_CHAR_TO_CHAR(content);
224 return true;
225}
185 226
227bool parse_name_elem(xmlNode *node, std::string& name, xmlChar *content, error_context_t& ctx)
228{
229 name = XML_CHAR_TO_CHAR(content);
230 if(name.size() == 0)
231 return add_fatal(ctx, node, "name cannot be empty");
232 for(size_t i = 0; i < name.size(); i++)
233 if(!isalnum(name[i]) && name[i] != '_')
234 return add_fatal(ctx, node, "name must only contain alphanumeric characters or _");
186 return true; 235 return true;
187} 236}
188 237
189bool parse_add_trivial_addr(const std::string& str, soc_reg_t& reg) 238template<typename T, typename U>
239bool parse_unsigned_text(U *node, T& res, xmlChar *content, error_context_t& ctx)
190{ 240{
191 soc_reg_addr_t a; 241 char *end;
192 a.name = reg.name; 242 unsigned long uns = strtoul(XML_CHAR_TO_CHAR(content), &end, 0);
193 if(!validate_uint32_hook(str, a.addr)) 243 if(*end != 0)
194 return false; 244 return add_fatal(ctx, node, "content must be an unsigned integer");
195 reg.addr.push_back(a); 245 res = uns;
246 if(res != uns)
247 return add_fatal(ctx, node, "value does not fit into allowed range");
196 return true; 248 return true;
197} 249}
198 250
199bool parse_reg_elem(xmlNode *node, soc_reg_t& reg) 251template<typename T>
252bool parse_unsigned_elem(xmlNode *node, T& res, xmlChar *content, error_context_t& ctx)
200{ 253{
201 std::list< soc_reg_formula_t > formulas; 254 return parse_unsigned_text(node, res, content, ctx);
202 BEGIN_ATTR_MATCH(node->properties) 255}
203 MATCH_TEXT_ATTR("name", reg.name)
204 SOFT_MATCH_SCT_ATTR("sct", reg.flags)
205 SOFT_MATCH_X_ATTR("addr", parse_add_trivial_addr, reg)
206 MATCH_TEXT_ATTR("desc", reg.desc)
207 END_ATTR_MATCH()
208 256
209 BEGIN_NODE_MATCH(node->children) 257template<typename T>
210 MATCH_ELEM_NODE("addr", reg.addr, parse_reg_addr_elem) 258bool parse_unsigned_attr(xmlAttr *attr, T& res, xmlChar *content, error_context_t& ctx)
211 MATCH_ELEM_NODE("formula", formulas, parse_reg_formula_elem) 259{
212 MATCH_ELEM_NODE("field", reg.field, parse_field_elem) 260 return parse_unsigned_text(attr, res, content, ctx);
213 END_NODE_MATCH() 261}
214 262
215 if(formulas.size() > 1) 263bool parse_text_attr_internal(xmlAttr *attr, xmlChar*& res, error_context_t& ctx)
216 { 264{
217 fprintf(stderr, "Only one formula is allowed per register\n"); 265 if(attr->children != attr->last)
218 return false; 266 return false;
219 } 267 if(attr->children->type != XML_TEXT_NODE)
220 if(formulas.size() == 1) 268 return parse_not_text_attr_error(attr, ctx);
221 reg.formula = formulas.front(); 269 res = attr->children->content;
222
223 return true; 270 return true;
224} 271}
225 272
226bool parse_dev_addr_elem(xmlNode *node, soc_dev_addr_t& addr) 273bool parse_text_attr(xmlAttr *attr, std::string& res, xmlChar *content, error_context_t& ctx)
227{ 274{
228 BEGIN_ATTR_MATCH(node->properties) 275 res = XML_CHAR_TO_CHAR(content);
229 MATCH_TEXT_ATTR("name", addr.name)
230 MATCH_UINT32_ATTR("addr", addr.addr)
231 END_ATTR_MATCH()
232
233 return true; 276 return true;
234} 277}
235 278
236bool parse_dev_elem(xmlNode *node, soc_dev_t& dev) 279bool parse_enum_elem(xmlNode *node, enum_t& reg, error_context_t& ctx)
237{ 280{
238 BEGIN_ATTR_MATCH(node->properties) 281 bool ret = true;
239 MATCH_TEXT_ATTR("name", dev.name) 282 bool has_name = false, has_value = false, has_desc = false;
240 MATCH_TEXT_ATTR("long_name", dev.long_name) 283 BEGIN_NODE_MATCH(node->children)
241 MATCH_TEXT_ATTR("desc", dev.desc) 284 MATCH_UNIQUE_TEXT_NODE("name", reg.name, has_name, parse_name_elem, ctx)
242 MATCH_TEXT_ATTR("version", dev.version) 285 MATCH_UNIQUE_TEXT_NODE("value", reg.value, has_value, parse_unsigned_elem, ctx)
243 END_ATTR_MATCH() 286 MATCH_UNIQUE_TEXT_NODE("desc", reg.desc, has_desc, parse_text_elem, ctx)
287 END_NODE_MATCH()
288 CHECK_HAS(node, "name", has_name, ctx)
289 CHECK_HAS(node, "value", has_value, ctx)
290 return ret;
291}
244 292
293bool parse_field_elem(xmlNode *node, field_t& field, error_context_t& ctx)
294{
295 bool ret = true;
296 bool has_name = false, has_pos = false, has_desc = false, has_width = false;
245 BEGIN_NODE_MATCH(node->children) 297 BEGIN_NODE_MATCH(node->children)
246 MATCH_ELEM_NODE("addr", dev.addr, parse_dev_addr_elem) 298 MATCH_UNIQUE_TEXT_NODE("name", field.name, has_name, parse_name_elem, ctx)
247 MATCH_ELEM_NODE("reg", dev.reg, parse_reg_elem) 299 MATCH_UNIQUE_TEXT_NODE("position", field.pos, has_pos, parse_unsigned_elem, ctx)
300 MATCH_UNIQUE_TEXT_NODE("width", field.width, has_width, parse_unsigned_elem, ctx)
301 MATCH_UNIQUE_TEXT_NODE("desc", field.desc, has_desc, parse_text_elem, ctx)
302 MATCH_ELEM_NODE("enum", field.enum_, parse_enum_elem, ctx)
248 END_NODE_MATCH() 303 END_NODE_MATCH()
304 CHECK_HAS(node, "name", has_name, ctx)
305 CHECK_HAS(node, "position", has_pos, ctx)
306 if(!has_width)
307 field.width = 1;
308 return ret;
309}
249 310
250 return true; 311bool parse_register_elem(xmlNode *node, register_t& reg, error_context_t& ctx)
312{
313 bool ret = true;
314 bool has_width = false;
315 BEGIN_NODE_MATCH(node->children)
316 MATCH_UNIQUE_TEXT_NODE("width", reg.width, has_width, parse_unsigned_elem, ctx)
317 MATCH_ELEM_NODE("field", reg.field, parse_field_elem, ctx)
318 END_NODE_MATCH()
319 if(!has_width)
320 reg.width = 32;
321 return ret;
251} 322}
252 323
253bool parse_soc_elem(xmlNode *node, soc_t& soc) 324bool parse_formula_elem(xmlNode *node, range_t& range, error_context_t& ctx)
254{ 325{
326 bool ret = true;
327 bool has_var = false;
255 BEGIN_ATTR_MATCH(node->properties) 328 BEGIN_ATTR_MATCH(node->properties)
256 MATCH_TEXT_ATTR("name", soc.name) 329 MATCH_UNIQUE_ATTR("variable", range.variable, has_var, parse_text_attr, ctx)
257 MATCH_TEXT_ATTR("desc", soc.desc) 330 END_NODE_MATCH()
258 END_ATTR_MATCH() 331 CHECK_HAS_ATTR(node, "variable", has_var, ctx)
332 return ret;
333}
259 334
335bool parse_range_elem(xmlNode *node, range_t& range, error_context_t& ctx)
336{
337 bool ret = true;
338 bool has_first = false, has_count = false, has_stride = false, has_base = false;
339 bool has_formula = false, has_formula_attr = false;
260 BEGIN_NODE_MATCH(node->children) 340 BEGIN_NODE_MATCH(node->children)
261 MATCH_ELEM_NODE("dev", soc.dev, parse_dev_elem) 341 MATCH_UNIQUE_TEXT_NODE("first", range.first, has_first, parse_unsigned_elem, ctx)
342 MATCH_UNIQUE_TEXT_NODE("count", range.count, has_count, parse_unsigned_elem, ctx)
343 MATCH_UNIQUE_TEXT_NODE("base", range.base, has_base, parse_unsigned_elem, ctx)
344 MATCH_UNIQUE_TEXT_NODE("stride", range.stride, has_stride, parse_unsigned_elem, ctx)
345 MATCH_UNIQUE_ELEM_NODE("formula", range, has_formula_attr, parse_formula_elem, ctx)
346 MATCH_UNIQUE_TEXT_NODE("formula", range.formula, has_formula, parse_text_elem, ctx)
262 END_NODE_MATCH() 347 END_NODE_MATCH()
348 CHECK_HAS(node, "first", has_first, ctx)
349 CHECK_HAS(node, "count", has_count, ctx)
350 if(!has_base && !has_formula)
351 ret = ret && parse_missing_error(node, "base> or <formula", ctx);
352 if(has_base && has_formula)
353 return parse_conflict_error(node, "base", "formula", ctx);
354 if(has_base)
355 CHECK_HAS(node, "stride", has_stride, ctx)
356 if(has_stride && !has_base)
357 ret = ret && parse_conflict_error(node, "stride", "formula", ctx);
358 if(has_stride)
359 range.type = range_t::STRIDE;
360 else
361 range.type = range_t::FORMULA;
362 return ret;
363}
263 364
264 return true; 365bool parse_instance_elem(xmlNode *node, instance_t& inst, error_context_t& ctx)
366{
367 bool ret = true;
368 bool has_name = false, has_title = false, has_desc = false, has_range = false;
369 bool has_address = false;
370 BEGIN_NODE_MATCH(node->children)
371 MATCH_UNIQUE_TEXT_NODE("name", inst.name, has_name, parse_name_elem, ctx)
372 MATCH_UNIQUE_TEXT_NODE("title", inst.title, has_title, parse_text_elem, ctx)
373 MATCH_UNIQUE_TEXT_NODE("desc", inst.desc, has_desc, parse_text_elem, ctx)
374 MATCH_UNIQUE_TEXT_NODE("address", inst.addr, has_address, parse_unsigned_elem, ctx)
375 MATCH_UNIQUE_ELEM_NODE("range", inst.range, has_range, parse_range_elem, ctx)
376 END_NODE_MATCH()
377 CHECK_HAS(node, "name", has_name, ctx)
378 if(!has_address && !has_range)
379 ret = ret && parse_missing_error(node, "address> or <range", ctx);
380 if(has_address && has_range)
381 ret = ret && parse_conflict_error(node, "address", "range", ctx);
382 if(has_address)
383 inst.type = instance_t::SINGLE;
384 else
385 inst.type = instance_t::RANGE;
386 return ret;
265} 387}
266 388
267bool parse_root_elem(xmlNode *node, soc_t& soc) 389bool parse_node_elem(xmlNode *node_, node_t& node, error_context_t& ctx)
268{ 390{
269 std::vector< soc_t > socs; 391 bool ret = true;
270 BEGIN_NODE_MATCH(node) 392 register_t reg;
271 MATCH_ELEM_NODE("soc", socs, parse_soc_elem) 393 bool has_title = false, has_desc = false, has_register = false, has_name = false;
394 BEGIN_NODE_MATCH(node_->children)
395 MATCH_UNIQUE_TEXT_NODE("name", node.name, has_name, parse_name_elem, ctx)
396 MATCH_UNIQUE_TEXT_NODE("title", node.title, has_title, parse_text_elem, ctx)
397 MATCH_UNIQUE_TEXT_NODE("desc", node.desc, has_desc, parse_text_elem, ctx)
398 MATCH_UNIQUE_ELEM_NODE("register", reg, has_register, parse_register_elem, ctx)
399 MATCH_ELEM_NODE("node", node.node, parse_node_elem, ctx)
400 MATCH_ELEM_NODE("instance", node.instance, parse_instance_elem, ctx)
272 END_NODE_MATCH() 401 END_NODE_MATCH()
273 if(socs.size() != 1) 402 CHECK_HAS(node_, "name", has_name, ctx)
403 CHECK_HAS(node_, "instance", !node.instance.empty(), ctx)
404 if(has_register)
405 node.register_.push_back(reg);
406 return ret;
407}
408
409bool parse_soc_elem(xmlNode *node, soc_t& soc, error_context_t& ctx)
410{
411 bool ret = true;
412 bool has_name = false, has_title = false, has_desc = false, has_version = false;
413 bool has_isa = false;
414 BEGIN_NODE_MATCH(node->children)
415 MATCH_UNIQUE_TEXT_NODE("name", soc.name, has_name, parse_name_elem, ctx)
416 MATCH_UNIQUE_TEXT_NODE("title", soc.title, has_title, parse_text_elem, ctx)
417 MATCH_UNIQUE_TEXT_NODE("desc", soc.desc, has_desc, parse_text_elem, ctx)
418 MATCH_UNIQUE_TEXT_NODE("version", soc.version, has_version, parse_text_elem, ctx)
419 MATCH_UNIQUE_TEXT_NODE("isa", soc.isa, has_isa, parse_text_elem, ctx)
420 MATCH_TEXT_NODE("author", soc.author, parse_text_elem, ctx)
421 MATCH_ELEM_NODE("node", soc.node, parse_node_elem, ctx)
422 END_NODE_MATCH()
423 CHECK_HAS(node, "name", has_name, ctx)
424 return ret;
425}
426
427bool parse_root_elem(xmlNode *node, soc_t& soc, error_context_t& ctx)
428{
429 size_t ver = 0;
430 bool ret = true;
431 bool has_soc = false, has_version = false;
432 BEGIN_ATTR_MATCH(node->properties)
433 MATCH_UNIQUE_ATTR("version", ver, has_version, parse_unsigned_attr, ctx)
434 END_ATTR_MATCH()
435 if(!has_version)
274 { 436 {
275 fprintf(stderr, "A description file must contain exactly one soc element\n"); 437 ctx.add(error_t(error_t::FATAL, xml_loc(node), "no version attribute, is this a v1 file ?"));
276 return false; 438 return false;
277 } 439 }
278 soc = socs[0]; 440 if(ver != MAJOR_VERSION)
279 return true; 441 return parse_wrong_version_error(node, ctx);
442 BEGIN_NODE_MATCH(node)
443 MATCH_UNIQUE_ELEM_NODE("soc", soc, has_soc, parse_soc_elem, ctx)
444 END_NODE_MATCH()
445 CHECK_HAS(node, "soc", has_soc, ctx)
446 return ret;
280} 447}
281 448
282} 449}
283 450
284bool soc_desc_parse_xml(const std::string& filename, soc_t& socs) 451bool parse_xml(const std::string& filename, soc_t& soc,
452 error_context_t& error_ctx)
285{ 453{
286 LIBXML_TEST_VERSION 454 LIBXML_TEST_VERSION
287 455
@@ -290,156 +458,207 @@ bool soc_desc_parse_xml(const std::string& filename, soc_t& socs)
290 return false; 458 return false;
291 459
292 xmlNodePtr root_element = xmlDocGetRootElement(doc); 460 xmlNodePtr root_element = xmlDocGetRootElement(doc);
293 bool ret = parse_root_elem(root_element, socs); 461 bool ret = parse_root_elem(root_element, soc, error_ctx);
294 462
295 xmlFreeDoc(doc); 463 xmlFreeDoc(doc);
296 464
297 return ret; 465 return ret;
298} 466}
299 467
468/**
469 * Producer
470 */
471
300namespace 472namespace
301{ 473{
302 474
303int produce_field(xmlTextWriterPtr writer, const soc_reg_field_t& field) 475#define SAFE(x) \
476 do{ \
477 if((x) < 0) { \
478 std::ostringstream oss; \
479 oss << __FILE__ << ":" << __LINE__; \
480 ctx.add(error_t(error_t::FATAL, oss.str(), "write error")); \
481 return -1; \
482 } \
483 }while(0)
484
485int produce_range(xmlTextWriterPtr writer, const range_t& range, error_context_t& ctx)
304{ 486{
305#define SAFE(x) if((x) < 0) return -1; 487 /* <range> */
306 /* <field> */ 488 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "range"));
307 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "field")); 489 /* <first/> */
308 /* name */ 490 SAFE(xmlTextWriterWriteFormatElement(writer, BAD_CAST "first", "%lu", range.first));
309 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "name", BAD_CAST field.name.c_str())); 491 /* <count/> */
310 /* desc */ 492 SAFE(xmlTextWriterWriteFormatElement(writer, BAD_CAST "count", "%lu", range.count));
311 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "desc", BAD_CAST field.desc.c_str())); 493 /* <base/><stride/> */
312 /* bitrange */ 494 if(range.type == range_t::STRIDE)
313 SAFE(xmlTextWriterWriteFormatAttribute(writer, BAD_CAST "bitrange", "%d:%d",
314 field.last_bit, field.first_bit));
315 /* values */
316 for(size_t i = 0; i < field.value.size(); i++)
317 { 495 {
318 /* <value> */ 496 SAFE(xmlTextWriterWriteFormatElement(writer, BAD_CAST "base", "0x%x", range.base));
319 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "value")); 497 SAFE(xmlTextWriterWriteFormatElement(writer, BAD_CAST "stride", "0x%x", range.stride));
320 /* name */
321 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "name", BAD_CAST field.value[i].name.c_str()));
322 /* value */
323 SAFE(xmlTextWriterWriteFormatAttribute(writer, BAD_CAST "value", "0x%x", field.value[i].value));
324 /* name */
325 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "desc", BAD_CAST field.value[i].desc.c_str()));
326 /* </value> */
327 SAFE(xmlTextWriterEndElement(writer));
328 } 498 }
329 /* </field> */ 499 /* <formula> */
330 SAFE(xmlTextWriterEndElement(writer)); 500 else if(range.type == range_t::FORMULA)
331#undef SAFE
332 return 0;
333}
334
335int produce_reg(xmlTextWriterPtr writer, const soc_reg_t& reg)
336{
337#define SAFE(x) if((x) < 0) return -1;
338 /* <reg> */
339 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "reg"));
340 /* name */
341 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "name", BAD_CAST reg.name.c_str()));
342 /* name */
343 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "desc", BAD_CAST reg.desc.c_str()));
344 /* flags */
345 if(reg.flags & REG_HAS_SCT)
346 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "sct", BAD_CAST "yes"));
347 /* formula */
348 if(reg.formula.type != REG_FORMULA_NONE)
349 { 501 {
350 /* <formula> */ 502 /* <formula> */
351 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "formula")); 503 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "formula"));
352 switch(reg.formula.type) 504 /* variable */
353 { 505 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "variable", BAD_CAST range.variable.c_str()));
354 case REG_FORMULA_STRING: 506 /* content */
355 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "string", 507 SAFE(xmlTextWriterWriteString(writer, BAD_CAST range.formula.c_str()));
356 BAD_CAST reg.formula.string.c_str()));
357 break;
358 default:
359 break;
360 }
361 /* </formula> */ 508 /* </formula> */
362 SAFE(xmlTextWriterEndElement(writer)); 509 SAFE(xmlTextWriterEndElement(writer));
363 } 510 }
364 /* addresses */ 511 /* </range> */
365 for(size_t i = 0; i < reg.addr.size(); i++) 512 SAFE(xmlTextWriterEndElement(writer));
366 { 513
367 /* <addr> */ 514 return 0;
368 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "addr")); 515}
369 /* name */ 516
370 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "name", BAD_CAST reg.addr[i].name.c_str())); 517int produce_instance(xmlTextWriterPtr writer, const instance_t& inst, error_context_t& ctx)
371 /* addr */ 518{
372 SAFE(xmlTextWriterWriteFormatAttribute(writer, BAD_CAST "addr", "0x%x", reg.addr[i].addr)); 519 /* <instance> */
373 /* </addr> */ 520 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "instance"));
374 SAFE(xmlTextWriterEndElement(writer)); 521 /* <name/> */
375 } 522 SAFE(xmlTextWriterWriteElement(writer, BAD_CAST "name", BAD_CAST inst.name.c_str()));
523 /* <title/> */
524 if(!inst.title.empty())
525 SAFE(xmlTextWriterWriteElement(writer, BAD_CAST "title", BAD_CAST inst.title.c_str()));
526 /* <desc/> */
527 if(!inst.desc.empty())
528 SAFE(xmlTextWriterWriteElement(writer, BAD_CAST "desc", BAD_CAST inst.desc.c_str()));
529 /* <address/> */
530 if(inst.type == instance_t::SINGLE)
531 SAFE(xmlTextWriterWriteFormatElement(writer, BAD_CAST "address", "0x%x", inst.addr));
532 /* <range/> */
533 else if(inst.type == instance_t::RANGE)
534 SAFE(produce_range(writer, inst.range, ctx));
535 /* </instance> */
536 SAFE(xmlTextWriterEndElement(writer));
537 return 0;
538}
539
540int produce_enum(xmlTextWriterPtr writer, const enum_t& enum_, error_context_t& ctx)
541{
542 /* <enum> */
543 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "enum"));
544 /* <name/> */
545 SAFE(xmlTextWriterWriteElement(writer, BAD_CAST "name", BAD_CAST enum_.name.c_str()));
546 /* <desc/> */
547 if(!enum_.desc.empty())
548 SAFE(xmlTextWriterWriteElement(writer, BAD_CAST "desc", BAD_CAST enum_.desc.c_str()));
549 /* <value/> */
550 SAFE(xmlTextWriterWriteFormatElement(writer, BAD_CAST "value", "0x%x", enum_.value));
551 /* </enum> */
552 SAFE(xmlTextWriterEndElement(writer));
553 return 0;
554}
555
556int produce_field(xmlTextWriterPtr writer, const field_t& field, error_context_t& ctx)
557{
558 /* <field> */
559 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "field"));
560 /* <name/> */
561 SAFE(xmlTextWriterWriteElement(writer, BAD_CAST "name", BAD_CAST field.name.c_str()));
562 /* <desc/> */
563 if(!field.desc.empty())
564 SAFE(xmlTextWriterWriteElement(writer, BAD_CAST "desc", BAD_CAST field.desc.c_str()));
565 /* <position/> */
566 SAFE(xmlTextWriterWriteFormatElement(writer, BAD_CAST "position", "%lu", field.pos));
567 /* <width/> */
568 if(field.width != 1)
569 SAFE(xmlTextWriterWriteFormatElement(writer, BAD_CAST "width", "%lu", field.width));
570 /* enums */
571 for(size_t i = 0; i < field.enum_.size(); i++)
572 SAFE(produce_enum(writer, field.enum_[i], ctx));
573 /* </field> */
574 SAFE(xmlTextWriterEndElement(writer));
575 return 0;
576}
577
578int produce_register(xmlTextWriterPtr writer, const register_t& reg, error_context_t& ctx)
579{
580 /* <register> */
581 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "register"));
582 /* <width/> */
583 if(reg.width != 32)
584 SAFE(xmlTextWriterWriteFormatElement(writer, BAD_CAST "width", "%lu", reg.width));
376 /* fields */ 585 /* fields */
377 for(size_t i = 0; i < reg.field.size(); i++) 586 for(size_t i = 0; i < reg.field.size(); i++)
378 produce_field(writer, reg.field[i]); 587 SAFE(produce_field(writer, reg.field[i], ctx));
379 /* </reg> */ 588 /* </register> */
380 SAFE(xmlTextWriterEndElement(writer)); 589 SAFE(xmlTextWriterEndElement(writer));
381#undef SAFE
382 return 0; 590 return 0;
383} 591}
384 592
385int produce_dev(xmlTextWriterPtr writer, const soc_dev_t& dev) 593int produce_node(xmlTextWriterPtr writer, const node_t& node, error_context_t& ctx)
386{ 594{
387#define SAFE(x) if((x) < 0) return -1; 595 /* <node> */
388 /* <dev> */ 596 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "node"));
389 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "dev")); 597 /* <name/> */
390 /* name */ 598 SAFE(xmlTextWriterWriteElement(writer, BAD_CAST "name", BAD_CAST node.name.c_str()));
391 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "name", BAD_CAST dev.name.c_str())); 599 /* <title/> */
392 /* long_name */ 600 if(!node.title.empty())
393 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "long_name", BAD_CAST dev.long_name.c_str())); 601 SAFE(xmlTextWriterWriteElement(writer, BAD_CAST "title", BAD_CAST node.title.c_str()));
394 /* desc */ 602 /* <desc/> */
395 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "desc", BAD_CAST dev.desc.c_str())); 603 if(!node.desc.empty())
396 /* version */ 604 SAFE(xmlTextWriterWriteElement(writer, BAD_CAST "desc", BAD_CAST node.desc.c_str()));
397 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "version", BAD_CAST dev.version.c_str())); 605 /* instances */
398 /* addresses */ 606 for(size_t i = 0; i < node.instance.size(); i++)
399 for(size_t i = 0; i < dev.addr.size(); i++) 607 SAFE(produce_instance(writer, node.instance[i], ctx));
400 { 608 /* register */
401 /* <addr> */ 609 for(size_t i = 0; i < node.register_.size(); i++)
402 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "addr")); 610 SAFE(produce_register(writer, node.register_[i], ctx));
403 /* name */ 611 /* nodes */
404 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "name", BAD_CAST dev.addr[i].name.c_str())); 612 for(size_t i = 0; i < node.node.size(); i++)
405 /* addr */ 613 SAFE(produce_node(writer, node.node[i], ctx));
406 SAFE(xmlTextWriterWriteFormatAttribute(writer, BAD_CAST "addr", "0x%x", dev.addr[i].addr)); 614 /* </node> */
407 /* </addr> */
408 SAFE(xmlTextWriterEndElement(writer));
409 }
410 /* registers */
411 for(size_t i = 0; i < dev.reg.size(); i++)
412 produce_reg(writer, dev.reg[i]);
413 /* </dev> */
414 SAFE(xmlTextWriterEndElement(writer)); 615 SAFE(xmlTextWriterEndElement(writer));
415#undef SAFE
416 return 0; 616 return 0;
417} 617}
418 618
619#undef SAFE
620
419} 621}
420 622
421bool soc_desc_produce_xml(const std::string& filename, const soc_t& soc) 623bool produce_xml(const std::string& filename, const soc_t& soc, error_context_t& ctx)
422{ 624{
423 LIBXML_TEST_VERSION 625 LIBXML_TEST_VERSION
424 626
627 std::ostringstream oss;
425 xmlTextWriterPtr writer = xmlNewTextWriterFilename(filename.c_str(), 0); 628 xmlTextWriterPtr writer = xmlNewTextWriterFilename(filename.c_str(), 0);
426 if(writer == NULL) 629 if(writer == NULL)
427 return false; 630 return false;
428#define SAFE(x) if((x) < 0) goto Lerr 631#define SAFE(x) do{if((x) < 0) goto Lerr;}while(0)
429 SAFE(xmlTextWriterSetIndent(writer, 1)); 632 SAFE(xmlTextWriterSetIndent(writer, 1));
430 SAFE(xmlTextWriterSetIndentString(writer, BAD_CAST " ")); 633 SAFE(xmlTextWriterSetIndentString(writer, BAD_CAST " "));
431 /* <xml> */ 634 /* <xml> */
432 SAFE(xmlTextWriterStartDocument(writer, NULL, NULL, NULL)); 635 SAFE(xmlTextWriterStartDocument(writer, NULL, NULL, NULL));
433 /* <soc> */ 636 /* <soc> */
434 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "soc")); 637 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "soc"));
435 /* name */ 638 /* version */
436 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "name", BAD_CAST soc.name.c_str())); 639 oss << MAJOR_VERSION;
437 /* desc */ 640 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "version", BAD_CAST oss.str().c_str()));
438 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "desc", BAD_CAST soc.desc.c_str())); 641 /* <name/> */
439 /* devices */ 642 SAFE(xmlTextWriterWriteElement(writer, BAD_CAST "name", BAD_CAST soc.name.c_str()));
440 for(size_t i = 0; i < soc.dev.size(); i++) 643 /* <title/> */
441 SAFE(produce_dev(writer, soc.dev[i])); 644 if(!soc.title.empty())
442 /* end <soc> */ 645 SAFE(xmlTextWriterWriteElement(writer, BAD_CAST "title", BAD_CAST soc.title.c_str()));
646 /* <desc/> */
647 if(!soc.desc.empty())
648 SAFE(xmlTextWriterWriteElement(writer, BAD_CAST "desc", BAD_CAST soc.desc.c_str()));
649 /* <author/> */
650 for(size_t i = 0; i < soc.author.size(); i++)
651 SAFE(xmlTextWriterWriteElement(writer, BAD_CAST "author", BAD_CAST soc.author[i].c_str()));
652 /* <isa/> */
653 if(!soc.isa.empty())
654 SAFE(xmlTextWriterWriteElement(writer, BAD_CAST "isa", BAD_CAST soc.isa.c_str()));
655 /* <version/> */
656 if(!soc.version.empty())
657 SAFE(xmlTextWriterWriteElement(writer, BAD_CAST "version", BAD_CAST soc.version.c_str()));
658 /* nodes */
659 for(size_t i = 0; i < soc.node.size(); i++)
660 SAFE(produce_node(writer, soc.node[i], ctx));
661 /* </soc> */
443 SAFE(xmlTextWriterEndElement(writer)); 662 SAFE(xmlTextWriterEndElement(writer));
444 /* </xml> */ 663 /* </xml> */
445 SAFE(xmlTextWriterEndDocument(writer)); 664 SAFE(xmlTextWriterEndDocument(writer));
@@ -451,520 +670,500 @@ Lerr:
451 return false; 670 return false;
452} 671}
453 672
454namespace 673/**
674 * soc_ref_t
675 */
676
677soc_ref_t::soc_ref_t():m_soc(0)
455{ 678{
679}
456 680
457struct soc_sorter 681soc_ref_t::soc_ref_t(soc_t *soc):m_soc(soc)
458{ 682{
459 bool operator()(const soc_dev_t& a, const soc_dev_t& b) const 683}
460 {
461 return a.name < b.name;
462 }
463 684
464 bool operator()(const soc_dev_addr_t& a, const soc_dev_addr_t& b) const 685bool soc_ref_t::valid() const
465 { 686{
466 return a.name < b.name; 687 return get() != 0;
467 } 688}
468 689
469 bool operator()(const soc_reg_t& a, const soc_reg_t& b) const 690soc_t *soc_ref_t::get() const
470 { 691{
471 soc_addr_t aa = a.addr.size() > 0 ? a.addr[0].addr : 0; 692 return m_soc;
472 soc_addr_t ab = b.addr.size() > 0 ? b.addr[0].addr : 0; 693}
473 return aa < ab;
474 }
475 694
476 bool operator()(const soc_reg_addr_t& a, const soc_reg_addr_t& b) const 695bool soc_ref_t::operator==(const soc_ref_t& ref) const
477 { 696{
478 return a.addr < b.addr; 697 return m_soc == ref.m_soc;
479 } 698}
480 699
481 bool operator()(const soc_reg_field_t& a, const soc_reg_field_t& b) const 700node_ref_t soc_ref_t::root() const
482 { 701{
483 return a.last_bit > b.last_bit; 702 return node_ref_t(*this);
484 } 703}
485 704
486 bool operator()(const soc_reg_field_value_t a, const soc_reg_field_value_t& b) const 705node_inst_t soc_ref_t::root_inst() const
487 { 706{
488 return a.value < b.value; 707 return node_inst_t(*this);
489 } 708}
490};
491 709
492void normalize(soc_reg_field_t& field) 710/**
711 * node_ref_t */
712
713node_ref_t::node_ref_t(soc_ref_t soc):m_soc(soc)
493{ 714{
494 std::sort(field.value.begin(), field.value.end(), soc_sorter());
495} 715}
496 716
497void normalize(soc_reg_t& reg) 717node_ref_t::node_ref_t(soc_ref_t soc, const std::vector< soc_id_t >& path)
718 :m_soc(soc), m_path(path)
498{ 719{
499 std::sort(reg.addr.begin(), reg.addr.end(), soc_sorter());
500 std::sort(reg.field.begin(), reg.field.end(), soc_sorter());
501 for(size_t i = 0; i < reg.field.size(); i++)
502 normalize(reg.field[i]);
503} 720}
504 721
505void normalize(soc_dev_t& dev) 722node_ref_t::node_ref_t()
506{ 723{
507 std::sort(dev.addr.begin(), dev.addr.end(), soc_sorter());
508 std::sort(dev.reg.begin(), dev.reg.end(), soc_sorter());
509 for(size_t i = 0; i < dev.reg.size(); i++)
510 normalize(dev.reg[i]);
511} 724}
512 725
726bool node_ref_t::valid() const
727{
728 return (m_soc.valid() && is_root()) || get() != 0;
513} 729}
514 730
515void soc_desc_normalize(soc_t& soc) 731bool node_ref_t::is_root() const
516{ 732{
517 std::sort(soc.dev.begin(), soc.dev.end(), soc_sorter()); 733 return m_path.empty();
518 for(size_t i = 0; i < soc.dev.size(); i++)
519 normalize(soc.dev[i]);
520} 734}
521 735
522namespace 736namespace
523{ 737{
524 soc_error_t make_error(soc_error_level_t lvl, std::string at, std::string what)
525 {
526 soc_error_t err;
527 err.level = lvl;
528 err.location = at;
529 err.message = what;
530 return err;
531 }
532 738
533 soc_error_t make_warning(std::string at, std::string what) 739std::vector< node_t > *get_children(node_ref_t node)
534 { 740{
535 return make_error(SOC_ERROR_WARNING, at, what); 741 if(node.is_root())
536 } 742 return &node.soc().get()->node;
537 743 node_t *n = node.get();
538 soc_error_t make_fatal(std::string at, std::string what) 744 return n == 0 ? 0 : &n->node;
539 { 745}
540 return make_error(SOC_ERROR_FATAL, at, what);
541 }
542 746
543 soc_error_t prefix(soc_error_t err, const std::string& prefix_at) 747node_t *get_child(std::vector< node_t > *nodes, soc_id_t id)
544 { 748{
545 err.location = prefix_at + "." + err.location; 749 if(nodes == 0)
546 return err; 750 return 0;
547 } 751 for(size_t i = 0; i < nodes->size(); i++)
752 if((*nodes)[i].id == id)
753 return &(*nodes)[i];
754 return 0;
755}
548 756
549 void add_errors(std::vector< soc_error_t >& errors, 757node_t *get_child(std::vector< node_t > *nodes, const std::string& name)
550 const std::vector< soc_error_t >& new_errors, const std::string& prefix_at) 758{
551 { 759 if(nodes == 0)
552 for(size_t i = 0; i < new_errors.size(); i++) 760 return 0;
553 errors.push_back(prefix(new_errors[i], prefix_at)); 761 for(size_t i = 0; i < nodes->size(); i++)
554 } 762 if((*nodes)[i].name == name)
763 return &(*nodes)[i];
764 return 0;
765}
555 766
556 std::vector< soc_error_t > no_error() 767}
557 {
558 std::vector< soc_error_t > s;
559 return s;
560 }
561 768
562 std::vector< soc_error_t > one_error(const soc_error_t& err) 769/* NOTE: valid() is implemented using get() != 0, so don't use it in get() ! */
770node_t *node_ref_t::get() const
771{
772 if(!soc().valid())
773 return 0;
774 /* we could do it recursively but it would make plenty of copies */
775 node_t *n = 0;
776 std::vector< node_t > *nodes = &soc().get()->node;
777 for(size_t i = 0; i < m_path.size(); i++)
563 { 778 {
564 std::vector< soc_error_t > s; 779 n = get_child(nodes, m_path[i]);
565 s.push_back(err); 780 if(n == 0)
566 return s; 781 return 0;
782 nodes = &n->node;
567 } 783 }
784 return n;
785}
568 786
569 bool name_valid(char c) 787soc_ref_t node_ref_t::soc() const
570 { 788{
571 return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || 789 return m_soc;
572 (c >= 'A' && c <= 'Z') || c == '_'; 790}
573 }
574 791
575 bool name_valid(const std::string& s) 792node_ref_t node_ref_t::parent() const
576 { 793{
577 for(size_t i = 0; i < s.size(); i++) 794 std::vector< soc_id_t > path = m_path;
578 if(!name_valid(s[i])) 795 if(!path.empty())
579 return false; 796 path.pop_back();
580 return true; 797 return node_ref_t(m_soc, path);
581 }
582} 798}
583 799
584std::vector< soc_error_t > soc_reg_field_value_t::errors(bool recursive) 800register_ref_t node_ref_t::reg() const
585{ 801{
586 (void) recursive; 802 node_t *n = get();
587 if(name.size() == 0) 803 if(n == 0)
588 return one_error(make_fatal(name, "empty name")); 804 return register_ref_t();
589 else if(!name_valid(name)) 805 if(n->register_.empty())
590 return one_error(make_fatal(name, "invalid name")); 806 return parent().reg();
591 else 807 else
592 return no_error(); 808 return register_ref_t(*this);
593} 809}
594 810
595std::vector< soc_error_t > soc_reg_field_t::errors(bool recursive) 811node_ref_t node_ref_t::child(const std::string& name) const
596{ 812{
597 std::vector< soc_error_t > err; 813 /* check the node exists */
598 std::string at(name); 814 node_t *n = get_child(get_children(*this), name);
599 if(name.size() == 0) 815 if(n == 0)
600 err.push_back(make_fatal(at, "empty name")); 816 return node_ref_t();
601 else if(!name_valid(name)) 817 std::vector< soc_id_t > path = m_path;
602 err.push_back(make_fatal(at, "invalid name")); 818 path.push_back(n->id);
603 if(last_bit > 31) 819 return node_ref_t(m_soc, path);
604 err.push_back(make_fatal(at, "last bit is greater than 31")); 820}
605 if(first_bit > last_bit) 821
606 err.push_back(make_fatal(at, "last bit is greater than first bit")); 822std::vector< node_ref_t > node_ref_t::children() const
607 for(size_t i = 0; i < value.size(); i++) 823{
824 std::vector< node_ref_t > nodes;
825 std::vector< node_t > *children = get_children(*this);
826 if(children == 0)
827 return nodes;
828 for(size_t i = 0; i < children->size(); i++)
608 { 829 {
609 for(size_t j = 0; j < value.size(); j++) 830 std::vector< soc_id_t > path = m_path;
831 path.push_back((*children)[i].id);
832 nodes.push_back(node_ref_t(m_soc, path));
833 }
834 return nodes;
835}
836
837std::vector< std::string > node_ref_t::path() const
838{
839 std::vector< std::string > path;
840 if(!soc().valid())
841 return path;
842 /* we could do it recursively but this is more efficient */
843 node_t *n = 0;
844 std::vector< node_t > *nodes = &soc().get()->node;
845 for(size_t i = 0; i < m_path.size(); i++)
846 {
847 n = get_child(nodes, m_path[i]);
848 if(n == 0)
610 { 849 {
611 if(i == j) 850 path.clear();
612 continue; 851 return path;
613 if(value[i].name == value[j].name)
614 err.push_back(prefix(make_fatal(value[i].name,
615 "there are several values with the same name"), at));
616 if(value[i].value == value[j].value)
617 err.push_back(prefix(make_warning(value[i].name,
618 "there are several values with the same value"), at));
619 } 852 }
620 if(value[i].value > (bitmask() >> first_bit)) 853 path.push_back(n->name);
621 err.push_back(prefix(make_warning(at, "value doesn't fit into the field"), value[i].name)); 854 nodes = &n->node;
622 if(recursive)
623 add_errors(err, value[i].errors(true), at);
624 } 855 }
625 return err; 856 return path;
626} 857}
627 858
628std::vector< soc_error_t > soc_reg_addr_t::errors(bool recursive) 859std::string node_ref_t::name() const
629{ 860{
630 (void) recursive; 861 node_t *n = get();
631 if(name.size() == 0) 862 return n == 0 ? "" : n->name;
632 return one_error(make_fatal("", "empty name"));
633 else if(!name_valid(name))
634 return one_error(make_fatal(name, "invalid name"));
635 else
636 return no_error();
637} 863}
638 864
639std::vector< soc_error_t > soc_reg_formula_t::errors(bool recursive) 865bool node_ref_t::operator==(const node_ref_t& ref) const
640{ 866{
641 (void) recursive; 867 return m_soc == ref.m_soc && m_path == ref.m_path;
642 if(type == REG_FORMULA_STRING && string.size() == 0)
643 return one_error(make_fatal("", "empty string formula"));
644 else
645 return no_error();
646} 868}
647 869
648namespace 870/**
871 * register_ref_t
872 */
873
874register_ref_t::register_ref_t(node_ref_t node)
875 :m_node(node)
649{ 876{
877}
650 878
651bool field_overlap(const soc_reg_field_t& a, const soc_reg_field_t& b) 879register_ref_t::register_ref_t()
652{ 880{
653 return !(a.first_bit > b.last_bit || b.first_bit > a.last_bit);
654} 881}
655 882
883bool register_ref_t::valid() const
884{
885 return get() != 0;
656} 886}
657 887
658std::vector< soc_error_t > soc_reg_t::errors(bool recursive) 888register_t *register_ref_t::get() const
659{ 889{
660 std::vector< soc_error_t > err; 890 node_t *n = m_node.get();
661 std::string at(name); 891 if(n == 0 || n->register_.empty())
662 if(name.size() == 0) 892 return 0;
663 err.push_back(make_fatal(at, "empty name")); 893 return &n->register_[0];
664 else if(!name_valid(name))
665 err.push_back(make_fatal(at, "invalid name"));
666 for(size_t i = 0; i < addr.size(); i++)
667 {
668 for(size_t j = 0; j < addr.size(); j++)
669 {
670 if(i == j)
671 continue;
672 if(addr[i].name == addr[j].name)
673 err.push_back(prefix(make_fatal(addr[i].name,
674 "there are several instances with the same name"), at));
675 if(addr[i].addr == addr[j].addr)
676 err.push_back(prefix(make_fatal(addr[i].name,
677 "there are several instances with the same address"), at));
678 }
679 if(recursive)
680 add_errors(err, addr[i].errors(true), at);
681 }
682 if(recursive)
683 add_errors(err, formula.errors(true), at);
684 for(size_t i = 0; i < field.size(); i++)
685 {
686 for(size_t j = 0; j < field.size(); j++)
687 {
688 if(i == j)
689 continue;
690 if(field[i].name == field[j].name)
691 err.push_back(prefix(make_fatal(field[i].name,
692 "there are several fields with the same name"), at));
693 if(field_overlap(field[i], field[j]))
694 err.push_back(prefix(make_fatal(field[i].name,
695 "there are overlapping fields"), at));
696 }
697 if(recursive)
698 add_errors(err, field[i].errors(true), at);
699 }
700 return err;
701} 894}
702 895
703std::vector< soc_error_t > soc_dev_addr_t::errors(bool recursive) 896node_ref_t register_ref_t::node() const
704{ 897{
705 (void) recursive; 898 return m_node;
706 if(name.size() == 0)
707 return one_error(make_fatal("", "empty name"));
708 else if(!name_valid(name))
709 return one_error(make_fatal(name, "invalid name"));
710 else
711 return no_error();
712} 899}
713 900
714std::vector< soc_error_t > soc_dev_t::errors(bool recursive) 901std::vector< field_ref_t > register_ref_t::fields() const
715{ 902{
716 std::vector< soc_error_t > err; 903 std::vector< field_ref_t > fields;
717 std::string at(name); 904 register_t *r = get();
718 if(name.size() == 0) 905 if(r == 0)
719 err.push_back(make_fatal(at, "empty name")); 906 return fields;
720 else if(!name_valid(name)) 907 for(size_t i = 0; i < r->field.size(); i++)
721 err.push_back(make_fatal(at, "invalid name")); 908 fields.push_back(field_ref_t(*this, r->field[i].id));
722 for(size_t i = 0; i < addr.size(); i++) 909 return fields;
723 {
724 for(size_t j = 0; j < addr.size(); j++)
725 {
726 if(i == j)
727 continue;
728 if(addr[i].name == addr[j].name)
729 err.push_back(prefix(make_fatal(addr[i].name,
730 "there are several instances with the same name"), at));
731 if(addr[i].addr == addr[j].addr)
732 err.push_back(prefix(make_fatal(addr[i].name,
733 "there are several instances with the same address"), at));
734 }
735 if(recursive)
736 add_errors(err, addr[i].errors(true), at);
737 }
738 for(size_t i = 0; i < reg.size(); i++)
739 {
740 for(size_t j = 0; j < reg.size(); j++)
741 {
742 if(i == j)
743 continue;
744 if(reg[i].name == reg[j].name)
745 err.push_back(prefix(make_fatal(reg[i].name,
746 "there are several registers with the same name"), at));
747 }
748 if(recursive)
749 add_errors(err, reg[i].errors(true), at);
750 }
751 return err;
752} 910}
753 911
754std::vector< soc_error_t > soc_t::errors(bool recursive) 912field_ref_t register_ref_t::field(const std::string& name) const
755{ 913{
756 std::vector< soc_error_t > err; 914 register_t *r = get();
757 std::string at(name); 915 if(r == 0)
758 for(size_t i = 0; i < dev.size(); i++) 916 return field_ref_t();
759 { 917 for(size_t i = 0; i < r->field.size(); i++)
760 for(size_t j = 0; j < dev.size(); j++) 918 if(r->field[i].name == name)
761 { 919 return field_ref_t(*this, r->field[i].id);
762 if(i == j) 920 return field_ref_t();
763 continue;
764 if(dev[i].name == dev[j].name)
765 err.push_back(prefix(make_fatal(dev[i].name,
766 "there are several devices with the same name"), at));
767 }
768 if(recursive)
769 add_errors(err, dev[i].errors(true), at);
770 }
771 return err;
772} 921}
773 922
774namespace 923/**
924 * field_ref_t
925 */
926
927field_ref_t::field_ref_t(register_ref_t reg, soc_id_t id)
928 :m_reg(reg), m_id(id)
775{ 929{
930}
776 931
777struct formula_evaluator 932field_ref_t::field_ref_t()
778{ 933{
779 std::string formula; 934}
780 size_t pos;
781 std::string error;
782 935
783 bool err(const char *fmt, ...) 936bool field_ref_t::valid() const
784 { 937{
785 char buffer[256]; 938 return get() != 0;
786 va_list args; 939}
787 va_start(args, fmt);
788 vsnprintf(buffer,sizeof(buffer), fmt, args);
789 va_end(args);
790 error = buffer;
791 return false;
792 }
793 940
794 formula_evaluator(const std::string& s):pos(0) 941field_t *field_ref_t::get() const
795 { 942{
796 for(size_t i = 0; i < s.size(); i++) 943 register_t *reg = m_reg.get();
797 if(!isspace(s[i])) 944 if(reg == 0)
798 formula.push_back(s[i]); 945 return 0;
799 } 946 for(size_t i = 0; i < reg->field.size(); i++)
947 if(reg->field[i].id == m_id)
948 return &reg->field[i];
949 return 0;
950}
800 951
801 void adv() 952register_ref_t field_ref_t::reg() const
802 { 953{
803 pos++; 954 return m_reg;
804 } 955}
805 956
806 char cur() 957/**
807 { 958 * node_inst_t
808 return end() ? 0 : formula[pos]; 959 */
809 }
810 960
811 bool end() 961namespace
812 { 962{
813 return pos >= formula.size(); 963
814 } 964const size_t INST_NO_INDEX = std::numeric_limits<std::size_t>::max();
815 965
816 bool parse_digit(char c, int basis, soc_word_t& res) 966bool get_inst_addr(range_t& range, size_t index, soc_addr_t& addr)
967{
968 if(index < range.first || index >= range.first + range.count)
969 return false;
970 switch(range.type)
817 { 971 {
818 c = tolower(c); 972 case range_t::STRIDE:
819 if(isdigit(c)) 973 addr += range.base + (index - range.first) * range.stride;
820 {
821 res = c - '0';
822 return true; 974 return true;
823 } 975 case range_t::FORMULA:
824 if(basis == 16 && isxdigit(c))
825 { 976 {
826 res = c + 10 - 'a'; 977 soc_word_t res;
978 std::map< std::string, soc_word_t > vars;
979 vars[range.variable] = index;
980 error_context_t ctx;
981 if(!evaluate_formula(range.formula, vars, res, "", ctx))
982 return false;
983 addr += res;
827 return true; 984 return true;
828 } 985 }
829 return err("invalid digit '%c'", c); 986 default:
987 return false;
830 } 988 }
989}
831 990
832 bool parse_signed(soc_word_t& res) 991bool get_inst_addr(instance_t *inst, size_t index, soc_addr_t& addr)
992{
993 if(inst == 0)
994 return false;
995 switch(inst->type)
833 { 996 {
834 char op = cur(); 997 case instance_t::SINGLE:
835 if(op == '+' || op == '-') 998 if(index != INST_NO_INDEX)
836 {
837 adv();
838 if(!parse_signed(res))
839 return false; 999 return false;
840 if(op == '-') 1000 addr += inst->addr;
841 res *= -1;
842 return true; 1001 return true;
843 } 1002 case instance_t::RANGE:
844 else if(op == '(') 1003 if(index == INST_NO_INDEX)
845 {
846 adv();
847 if(!parse_expression(res))
848 return false; 1004 return false;
849 if(cur() != ')') 1005 return get_inst_addr(inst->range, index, addr);
850 return err("expected ')', got '%c'", cur()); 1006 default:
851 adv();
852 return true;
853 }
854 else if(isdigit(op))
855 {
856 res = op - '0';
857 adv();
858 int basis = 10;
859 if(op == '0' && cur() == 'x')
860 {
861 basis = 16;
862 adv();
863 }
864 soc_word_t digit = 0;
865 while(parse_digit(cur(), basis, digit))
866 {
867 res = res * basis + digit;
868 adv();
869 }
870 return true;
871 }
872 else if(isalpha(op) || op == '_')
873 {
874 std::string name;
875 while(isalnum(cur()) || cur() == '_')
876 {
877 name.push_back(cur());
878 adv();
879 }
880 return get_variable(name, res);
881 }
882 else
883 return err("express signed expression, got '%c'", op);
884 }
885
886 bool parse_term(soc_word_t& res)
887 {
888 if(!parse_signed(res))
889 return false; 1007 return false;
890 while(cur() == '*' || cur() == '/' || cur() == '%')
891 {
892 char op = cur();
893 adv();
894 soc_word_t tmp;
895 if(!parse_signed(tmp))
896 return false;
897 if(op == '*')
898 res *= tmp;
899 else if(tmp != 0)
900 res = op == '/' ? res / tmp : res % tmp;
901 else
902 return err("division by 0");
903 }
904 return true;
905 } 1008 }
1009}
906 1010
907 bool parse_expression(soc_word_t& res) 1011}
908 {
909 if(!parse_term(res))
910 return false;
911 while(!end() && (cur() == '+' || cur() == '-'))
912 {
913 char op = cur();
914 adv();
915 soc_word_t tmp;
916 if(!parse_term(tmp))
917 return false;
918 if(op == '+')
919 res += tmp;
920 else
921 res -= tmp;
922 }
923 return true;
924 }
925 1012
926 bool parse(soc_word_t& res, std::string& _error) 1013node_inst_t::node_inst_t(soc_ref_t soc)
927 { 1014 :m_node(soc.root())
928 bool ok = parse_expression(res); 1015{
929 if(ok && !end()) 1016}
930 err("unexpected character '%c'", cur());
931 _error = error;
932 return ok && end();
933 }
934 1017
935 virtual bool get_variable(std::string name, soc_word_t& res) 1018node_inst_t::node_inst_t(node_ref_t node, const std::vector< soc_id_t >& ids,
936 { 1019 const std::vector< size_t >& indexes)
937 return err("unknown variable '%s'", name.c_str()); 1020 :m_node(node), m_id_path(ids), m_index_path(indexes)
938 } 1021{
939}; 1022}
940 1023
941struct my_evaluator : public formula_evaluator 1024node_inst_t::node_inst_t()
942{ 1025{
943 const std::map< std::string, soc_word_t>& var; 1026}
944 1027
945 my_evaluator(const std::string& formula, const std::map< std::string, soc_word_t>& _var) 1028bool node_inst_t::valid() const
946 :formula_evaluator(formula), var(_var) {} 1029{
1030 return is_root() || get() != 0;
1031}
947 1032
948 virtual bool get_variable(std::string name, soc_word_t& res) 1033node_ref_t node_inst_t::node() const
1034{
1035 return m_node;
1036}
1037
1038soc_ref_t node_inst_t::soc() const
1039{
1040 return m_node.soc();
1041}
1042
1043bool node_inst_t::is_root() const
1044{
1045 return m_node.is_root();
1046}
1047
1048node_inst_t node_inst_t::parent() const
1049{
1050 std::vector< soc_id_t > ids = m_id_path;
1051 std::vector< size_t > indexes = m_index_path;
1052 if(!ids.empty())
1053 ids.pop_back();
1054 if(!indexes.empty())
1055 indexes.pop_back();
1056 return node_inst_t(m_node.parent(), ids, indexes);
1057}
1058
1059instance_t *node_inst_t::get() const
1060{
1061 node_t *n = m_node.get();
1062 if(n == 0)
1063 return 0;
1064 for(size_t i = 0; i < n->instance.size(); i++)
1065 if(n->instance[i].id == m_id_path.back())
1066 return &n->instance[i];
1067 return 0;
1068}
1069
1070soc_addr_t node_inst_t::addr() const
1071{
1072 if(is_root())
1073 return 0;
1074 soc_addr_t addr = parent().addr();
1075 if(!get_inst_addr(get(), m_index_path.back(), addr))
1076 return 0;
1077 return addr;
1078}
1079
1080node_inst_t node_inst_t::child(const std::string& name) const
1081{
1082 return child(name, INST_NO_INDEX);
1083}
1084
1085
1086node_inst_t node_inst_t::child(const std::string& name, size_t index) const
1087{
1088 std::vector< node_t > *nodes = get_children(m_node);
1089 if(nodes == 0)
1090 return node_inst_t();
1091 node_ref_t child_node = m_node;
1092 for(size_t i = 0; i < nodes->size(); i++)
949 { 1093 {
950 std::map< std::string, soc_word_t>::const_iterator it = var.find(name); 1094 node_t& node = (*nodes)[i];
951 if(it == var.end()) 1095 child_node.m_path.push_back(node.id);
952 return formula_evaluator::get_variable(name, res); 1096 for(size_t j = 0; j < node.instance.size(); j++)
953 else
954 { 1097 {
955 res = it->second; 1098 if(node.instance[j].name != name)
956 return true; 1099 continue;
1100 std::vector< soc_id_t > ids = m_id_path;
1101 std::vector< size_t > indexes = m_index_path;
1102 ids.push_back(node.instance[j].id);
1103 ids.push_back(index);
1104 return node_inst_t(child_node, ids, indexes);
957 } 1105 }
1106 child_node.m_path.pop_back();
958 } 1107 }
959}; 1108 return node_inst_t();
1109}
1110
1111std::vector< node_inst_t > node_inst_t::children() const
1112{
1113 std::vector< node_inst_t > list;
1114 std::vector< node_t > *nodes = get_children(m_node);
1115 std::vector< soc_id_t > n_path = m_id_path;
1116 std::vector< size_t > i_path = m_index_path;
1117 if(nodes == 0)
1118 return list;
1119 node_ref_t child_node = m_node;
1120 for(size_t i = 0; i < nodes->size(); i++)
1121 {
1122 node_t& node = (*nodes)[i];
1123 child_node.m_path.push_back(node.id);
1124 for(size_t j = 0; j < node.instance.size(); j++)
1125 {
1126 instance_t& inst = node.instance[j];
1127 n_path.push_back(inst.id);
1128 switch(inst.type)
1129 {
1130 case instance_t::SINGLE:
1131 i_path.push_back(INST_NO_INDEX);
1132 list.push_back(node_inst_t(child_node, n_path, i_path));
1133 i_path.pop_back();
1134 break;
1135 case instance_t::RANGE:
1136 for(size_t i = 0; i < inst.range.count; i++)
1137 {
1138 i_path.push_back(inst.range.first + i);
1139 list.push_back(node_inst_t(child_node, n_path, i_path));
1140 i_path.pop_back();
1141 }
1142 break;
1143 default:
1144 break;
1145 }
1146 n_path.pop_back();
1147 }
1148 child_node.m_path.pop_back();
1149 }
1150 return list;
1151}
1152
1153std::string node_inst_t::name() const
1154{
1155 instance_t *inst = get();
1156 return inst == 0 ? "" : inst->name;
1157}
960 1158
1159bool node_inst_t:: is_indexed() const
1160{
1161 return !m_index_path.empty() && m_index_path.back() != INST_NO_INDEX;
961} 1162}
962 1163
963bool soc_desc_evaluate_formula(const std::string& formula, 1164size_t node_inst_t::index() const
964 const std::map< std::string, soc_word_t>& var, soc_word_t& result, std::string& error)
965{ 1165{
966 my_evaluator e(formula, var); 1166 return m_index_path.empty() ? INST_NO_INDEX : m_index_path.back();
967 return e.parse(result, error);
968} 1167}
969 1168
970/** WARNING we need to call xmlInitParser() to init libxml2 but it needs to 1169/** WARNING we need to call xmlInitParser() to init libxml2 but it needs to
@@ -982,4 +1181,7 @@ public:
982}; 1181};
983 1182
984xml_parser_init __xml_parser_init; 1183xml_parser_init __xml_parser_init;
985} \ No newline at end of file 1184}
1185
1186} // soc_desc_v1
1187
diff --git a/utils/regtools/lib/soc_desc.hpp b/utils/regtools/lib/soc_desc.hpp
deleted file mode 100644
index bb8eb4ba8d..0000000000
--- a/utils/regtools/lib/soc_desc.hpp
+++ /dev/null
@@ -1,228 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2012 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#ifndef __SOC_DESC__
22#define __SOC_DESC__
23
24#include <stdint.h>
25#include <vector>
26#include <list>
27#include <string>
28#include <map>
29
30/**
31 * These data structures represent the SoC register in a convenient way.
32 * The basic structure is the following:
33 * - each SoC has several devices
34 * - each device has a generic name, a list of {name,address} and several registers
35 * - each register has a generic name, a list of {name,address}, flags,
36 * several fields
37 * - each field has a name, a first and last bit position, can apply either
38 * to all addresses of a register or be specific to one only and has several values
39 * - each field value has a name and a value
40 *
41 * All addresses, values and names are relative to the parents. For example a field
42 * value BV_LCDIF_CTRL_WORD_LENGTH_18_BIT is represented has:
43 * - device LCDIF, register CTRL, field WORD_LENGTH, value 16_BIT
44 * The address of CTRL is related to the address of LCDIF, the value of 16_BIT
45 * ignores the position of the WORD_LENGTH field in the register.
46 */
47
48#define SOCDESC_VERSION_MAJOR 1
49#define SOCDESC_VERSION_MINOR 4
50#define SOCDESC_VERSION_REV 1
51
52#define SOCDESC_VERSION__(maj,min,rev) #maj"."#min"."#rev
53#define SOCDESC_VERSION_(maj,min,rev) SOCDESC_VERSION__(maj,min,rev)
54#define SOCDESC_VERSION SOCDESC_VERSION_(SOCDESC_VERSION_MAJOR,SOCDESC_VERSION_MINOR,SOCDESC_VERSION_REV)
55
56/**
57 * Typedef for SoC types: word, address and flags */
58typedef uint32_t soc_addr_t;
59typedef uint32_t soc_word_t;
60typedef uint32_t soc_reg_flags_t;
61
62/** SoC error gravity level */
63enum soc_error_level_t
64{
65 SOC_ERROR_WARNING,
66 SOC_ERROR_FATAL,
67};
68
69/** SoC description error */
70struct soc_error_t
71{
72 soc_error_level_t level; /// level (warning, fatal, ...)
73 std::string location; /// human description of the location
74 std::string message; /// message
75};
76
77/** SoC register generic formula */
78enum soc_reg_formula_type_t
79{
80 REG_FORMULA_NONE, /// register has no generic formula
81 REG_FORMULA_STRING, /// register has a generic formula represented by a string
82};
83
84/** <soc_reg_t>.<flags> values */
85const soc_reg_flags_t REG_HAS_SCT = 1 << 0; /// register SCT variants
86
87/** SoC register field named value */
88struct soc_reg_field_value_t
89{
90 std::string name; /// name of the value
91 soc_word_t value; /// numeric value
92 std::string desc; /// human description
93
94 std::vector< soc_error_t > errors(bool recursive);
95};
96
97/** SoC register field */
98struct soc_reg_field_t
99{
100 std::string name; /// name of the field
101 std::string desc; /// human description
102 unsigned first_bit, last_bit; /// bit range of the field
103
104 soc_reg_field_t():first_bit(0), last_bit(31) {}
105
106 /** Return field bitmask in register */
107 soc_word_t bitmask() const
108 {
109 // WARNING beware of the case where first_bit=0 and last_bit=31
110 if(first_bit == 0 && last_bit == 31)
111 return 0xffffffff;
112 else
113 return ((1 << (last_bit - first_bit + 1)) - 1) << first_bit;
114 }
115
116 /** Extract field value from register value */
117 soc_word_t extract(soc_word_t reg_val) const
118 {
119 return (reg_val & bitmask()) >> first_bit;
120 }
121
122 /** Replace the field value in a register value */
123 soc_word_t replace(soc_word_t reg_val, soc_word_t field_val) const
124 {
125 return (reg_val & ~bitmask()) | ((field_val << first_bit) & bitmask());
126 }
127
128 bool is_reserved() const
129 {
130 return name.substr(0, 4) == "RSVD" || name.substr(0, 5) == "RSRVD";
131 }
132
133 /** Return field value index, or -1 if none */
134 int find_value(soc_word_t v) const
135 {
136 for(size_t i = 0; i < value.size(); i++)
137 if(value[i].value == v)
138 return i;
139 return -1;
140 }
141
142 std::vector< soc_reg_field_value_t > value;
143
144 std::vector< soc_error_t > errors(bool recursive);
145};
146
147/** SoC register address */
148struct soc_reg_addr_t
149{
150 std::string name; /// actual register name
151 soc_addr_t addr; /// actual register address (relative to device)
152
153 std::vector< soc_error_t > errors(bool recursive);
154};
155
156/** SoC register formula */
157struct soc_reg_formula_t
158{
159 enum soc_reg_formula_type_t type;
160 std::string string; /// for STRING
161
162 std::vector< soc_error_t > errors(bool recursive);
163};
164
165/** SoC register */
166struct soc_reg_t
167{
168 std::string name; /// generic name (for multi registers) or actual name
169 std::string desc; /// human description
170 std::vector< soc_reg_addr_t > addr; /// instances of the registers
171 soc_reg_formula_t formula; /// formula for the instance addresses
172 soc_reg_flags_t flags; /// ORed value
173
174 std::vector< soc_reg_field_t > field;
175
176 std::vector< soc_error_t > errors(bool recursive);
177};
178
179/** Soc device address */
180struct soc_dev_addr_t
181{
182 std::string name; /// actual device name
183 soc_addr_t addr;
184
185 std::vector< soc_error_t > errors(bool recursive);
186};
187
188/** SoC device */
189struct soc_dev_t
190{
191 std::string name; /// generic name (of multi devices) or actual name
192 std::string long_name; /// human friendly name
193 std::string desc; /// human description
194 std::string version; /// description version
195 std::vector< soc_dev_addr_t > addr;
196
197 std::vector< soc_reg_t > reg;
198
199 std::vector< soc_error_t > errors(bool recursive);
200};
201
202/** SoC */
203struct soc_t
204{
205 std::string name; /// codename (rockbox)
206 std::string desc; /// SoC name
207
208 std::vector< soc_dev_t > dev;
209
210 std::vector< soc_error_t > errors(bool recursive);
211};
212
213/** Parse a SoC description from a XML file, append it to <soc>. */
214bool soc_desc_parse_xml(const std::string& filename, soc_t& soc);
215/** Write a SoC description to a XML file, overwriting it. A file can contain
216 * multiple Soc descriptions */
217bool soc_desc_produce_xml(const std::string& filename, const soc_t& soc);
218/** Normalise a soc description by reordering elemnts so that:
219 * - devices are sorted by first name
220 * - registers are sorted by first address
221 * - fields are sorted by last bit
222 * - values are sorted by value */
223void soc_desc_normalize(soc_t& soc);
224/** Formula parser: try to parse and evaluate a formula to a specific value of 'n' */
225bool soc_desc_evaluate_formula(const std::string& formula,
226 const std::map< std::string, soc_word_t>& var, soc_word_t& result, std::string& error);
227
228#endif /* __SOC_DESC__ */ \ No newline at end of file
diff --git a/utils/regtools/lib/soc_desc_v1.cpp b/utils/regtools/lib/soc_desc_v1.cpp
new file mode 100644
index 0000000000..d585485493
--- /dev/null
+++ b/utils/regtools/lib/soc_desc_v1.cpp
@@ -0,0 +1,990 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2012 by Amaury Pouly
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include "soc_desc_v1.hpp"
22#include <libxml/parser.h>
23#include <libxml/tree.h>
24#include <libxml/xmlsave.h>
25#include <libxml/xmlwriter.h>
26#include <stdio.h>
27#include <string.h>
28#include <algorithm>
29#include <cctype>
30
31namespace soc_desc_v1
32{
33
34#define XML_CHAR_TO_CHAR(s) ((const char *)(s))
35
36#define BEGIN_ATTR_MATCH(attr) \
37 for(xmlAttr *a = attr; a; a = a->next) {
38
39#define MATCH_X_ATTR(attr_name, hook, ...) \
40 if(strcmp(XML_CHAR_TO_CHAR(a->name), attr_name) == 0) { \
41 std::string s; \
42 if(!parse_text_attr(a, s) || !hook(s, __VA_ARGS__)) \
43 return false; \
44 }
45
46#define SOFT_MATCH_X_ATTR(attr_name, hook, ...) \
47 if(strcmp(XML_CHAR_TO_CHAR(a->name), attr_name) == 0) { \
48 std::string s; \
49 if(parse_text_attr(a, s)) \
50 hook(s, __VA_ARGS__); \
51 }
52
53#define SOFT_MATCH_SCT_ATTR(attr_name, var) \
54 SOFT_MATCH_X_ATTR(attr_name, validate_sct_hook, var)
55
56#define MATCH_TEXT_ATTR(attr_name, var) \
57 MATCH_X_ATTR(attr_name, validate_string_hook, var)
58
59#define MATCH_UINT32_ATTR(attr_name, var) \
60 MATCH_X_ATTR(attr_name, validate_uint32_hook, var)
61
62#define MATCH_BITRANGE_ATTR(attr_name, first, last) \
63 MATCH_X_ATTR(attr_name, validate_bitrange_hook, first, last)
64
65#define END_ATTR_MATCH() \
66 }
67
68#define BEGIN_NODE_MATCH(node) \
69 for(xmlNode *sub = node; sub; sub = sub->next) {
70
71#define MATCH_ELEM_NODE(node_name, array, parse_fn) \
72 if(sub->type == XML_ELEMENT_NODE && strcmp(XML_CHAR_TO_CHAR(sub->name), node_name) == 0) { \
73 array.resize(array.size() + 1); \
74 if(!parse_fn(sub, array.back())) \
75 return false; \
76 }
77
78#define SOFT_MATCH_ELEM_NODE(node_name, array, parse_fn) \
79 if(sub->type == XML_ELEMENT_NODE && strcmp(XML_CHAR_TO_CHAR(sub->name), node_name) == 0) { \
80 array.resize(array.size() + 1); \
81 if(!parse_fn(sub, array.back())) \
82 array.pop_back(); \
83 }
84
85#define END_NODE_MATCH() \
86 }
87
88namespace
89{
90
91bool validate_string_hook(const std::string& str, std::string& s)
92{
93 s = str;
94 return true;
95}
96
97bool validate_sct_hook(const std::string& str, soc_reg_flags_t& flags)
98{
99 if(str == "yes") flags |= REG_HAS_SCT;
100 else if(str != "no") return false;
101 return true;
102}
103
104bool validate_unsigned_long_hook(const std::string& str, unsigned long& s)
105{
106 char *end;
107 s = strtoul(str.c_str(), &end, 0);
108 return *end == 0;
109}
110
111bool validate_uint32_hook(const std::string& str, uint32_t& s)
112{
113 unsigned long u;
114 if(!validate_unsigned_long_hook(str, u)) return false;
115#if ULONG_MAX > 0xffffffff
116 if(u > 0xffffffff) return false;
117#endif
118 s = u;
119 return true;
120}
121
122bool validate_bitrange_hook(const std::string& str, unsigned& first, unsigned& last)
123{
124 unsigned long a, b;
125 size_t sep = str.find(':');
126 if(sep == std::string::npos) return false;
127 if(!validate_unsigned_long_hook(str.substr(0, sep), a)) return false;
128 if(!validate_unsigned_long_hook(str.substr(sep + 1), b)) return false;
129 if(a > 31 || b > 31 || a < b) return false;
130 first = b;
131 last = a;
132 return true;
133}
134
135bool parse_text_attr(xmlAttr *attr, std::string& s)
136{
137 if(attr->children != attr->last)
138 return false;
139 if(attr->children->type != XML_TEXT_NODE)
140 return false;
141 s = XML_CHAR_TO_CHAR(attr->children->content);
142 return true;
143}
144
145bool parse_value_elem(xmlNode *node, soc_reg_field_value_t& value)
146{
147 BEGIN_ATTR_MATCH(node->properties)
148 MATCH_TEXT_ATTR("name", value.name)
149 MATCH_UINT32_ATTR("value", value.value)
150 MATCH_TEXT_ATTR("desc", value.desc)
151 END_ATTR_MATCH()
152
153 return true;
154}
155
156bool parse_field_elem(xmlNode *node, soc_reg_field_t& field)
157{
158 BEGIN_ATTR_MATCH(node->properties)
159 MATCH_TEXT_ATTR("name", field.name)
160 MATCH_BITRANGE_ATTR("bitrange", field.first_bit, field.last_bit)
161 MATCH_TEXT_ATTR("desc", field.desc)
162 END_ATTR_MATCH()
163
164 BEGIN_NODE_MATCH(node->children)
165 SOFT_MATCH_ELEM_NODE("value", field.value, parse_value_elem)
166 END_NODE_MATCH()
167
168 return true;
169}
170
171bool parse_reg_addr_elem(xmlNode *node, soc_reg_addr_t& addr)
172{
173 BEGIN_ATTR_MATCH(node->properties)
174 MATCH_TEXT_ATTR("name", addr.name)
175 MATCH_UINT32_ATTR("addr", addr.addr)
176 END_ATTR_MATCH()
177
178 return true;
179}
180
181bool parse_reg_formula_elem(xmlNode *node, soc_reg_formula_t& formula)
182{
183 BEGIN_ATTR_MATCH(node->properties)
184 MATCH_TEXT_ATTR("string", formula.string)
185 END_ATTR_MATCH()
186
187 formula.type = REG_FORMULA_STRING;
188
189 return true;
190}
191
192bool parse_add_trivial_addr(const std::string& str, soc_reg_t& reg)
193{
194 soc_reg_addr_t a;
195 a.name = reg.name;
196 if(!validate_uint32_hook(str, a.addr))
197 return false;
198 reg.addr.push_back(a);
199 return true;
200}
201
202bool parse_reg_elem(xmlNode *node, soc_reg_t& reg)
203{
204 std::list< soc_reg_formula_t > formulas;
205 BEGIN_ATTR_MATCH(node->properties)
206 MATCH_TEXT_ATTR("name", reg.name)
207 SOFT_MATCH_SCT_ATTR("sct", reg.flags)
208 SOFT_MATCH_X_ATTR("addr", parse_add_trivial_addr, reg)
209 MATCH_TEXT_ATTR("desc", reg.desc)
210 END_ATTR_MATCH()
211
212 BEGIN_NODE_MATCH(node->children)
213 MATCH_ELEM_NODE("addr", reg.addr, parse_reg_addr_elem)
214 MATCH_ELEM_NODE("formula", formulas, parse_reg_formula_elem)
215 MATCH_ELEM_NODE("field", reg.field, parse_field_elem)
216 END_NODE_MATCH()
217
218 if(formulas.size() > 1)
219 {
220 fprintf(stderr, "Only one formula is allowed per register\n");
221 return false;
222 }
223 if(formulas.size() == 1)
224 reg.formula = formulas.front();
225
226 return true;
227}
228
229bool parse_dev_addr_elem(xmlNode *node, soc_dev_addr_t& addr)
230{
231 BEGIN_ATTR_MATCH(node->properties)
232 MATCH_TEXT_ATTR("name", addr.name)
233 MATCH_UINT32_ATTR("addr", addr.addr)
234 END_ATTR_MATCH()
235
236 return true;
237}
238
239bool parse_dev_elem(xmlNode *node, soc_dev_t& dev)
240{
241 BEGIN_ATTR_MATCH(node->properties)
242 MATCH_TEXT_ATTR("name", dev.name)
243 MATCH_TEXT_ATTR("long_name", dev.long_name)
244 MATCH_TEXT_ATTR("desc", dev.desc)
245 MATCH_TEXT_ATTR("version", dev.version)
246 END_ATTR_MATCH()
247
248 BEGIN_NODE_MATCH(node->children)
249 MATCH_ELEM_NODE("addr", dev.addr, parse_dev_addr_elem)
250 MATCH_ELEM_NODE("reg", dev.reg, parse_reg_elem)
251 END_NODE_MATCH()
252
253 return true;
254}
255
256bool parse_soc_elem(xmlNode *node, soc_t& soc)
257{
258 BEGIN_ATTR_MATCH(node->properties)
259 MATCH_TEXT_ATTR("name", soc.name)
260 MATCH_TEXT_ATTR("desc", soc.desc)
261 END_ATTR_MATCH()
262
263 BEGIN_NODE_MATCH(node->children)
264 MATCH_ELEM_NODE("dev", soc.dev, parse_dev_elem)
265 END_NODE_MATCH()
266
267 return true;
268}
269
270bool parse_root_elem(xmlNode *node, soc_t& soc)
271{
272 std::vector< soc_t > socs;
273 BEGIN_NODE_MATCH(node)
274 MATCH_ELEM_NODE("soc", socs, parse_soc_elem)
275 END_NODE_MATCH()
276 if(socs.size() != 1)
277 {
278 fprintf(stderr, "A description file must contain exactly one soc element\n");
279 return false;
280 }
281 soc = socs[0];
282 return true;
283}
284
285}
286
287bool parse_xml(const std::string& filename, soc_t& socs)
288{
289 LIBXML_TEST_VERSION
290
291 xmlDocPtr doc = xmlReadFile(filename.c_str(), NULL, 0);
292 if(doc == NULL)
293 return false;
294
295 xmlNodePtr root_element = xmlDocGetRootElement(doc);
296 bool ret = parse_root_elem(root_element, socs);
297
298 xmlFreeDoc(doc);
299
300 return ret;
301}
302
303namespace
304{
305
306int produce_field(xmlTextWriterPtr writer, const soc_reg_field_t& field)
307{
308#define SAFE(x) if((x) < 0) return -1;
309 /* <field> */
310 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "field"));
311 /* name */
312 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "name", BAD_CAST field.name.c_str()));
313 /* desc */
314 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "desc", BAD_CAST field.desc.c_str()));
315 /* bitrange */
316 SAFE(xmlTextWriterWriteFormatAttribute(writer, BAD_CAST "bitrange", "%d:%d",
317 field.last_bit, field.first_bit));
318 /* values */
319 for(size_t i = 0; i < field.value.size(); i++)
320 {
321 /* <value> */
322 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "value"));
323 /* name */
324 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "name", BAD_CAST field.value[i].name.c_str()));
325 /* value */
326 SAFE(xmlTextWriterWriteFormatAttribute(writer, BAD_CAST "value", "0x%x", field.value[i].value));
327 /* name */
328 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "desc", BAD_CAST field.value[i].desc.c_str()));
329 /* </value> */
330 SAFE(xmlTextWriterEndElement(writer));
331 }
332 /* </field> */
333 SAFE(xmlTextWriterEndElement(writer));
334#undef SAFE
335 return 0;
336}
337
338int produce_reg(xmlTextWriterPtr writer, const soc_reg_t& reg)
339{
340#define SAFE(x) if((x) < 0) return -1;
341 /* <reg> */
342 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "reg"));
343 /* name */
344 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "name", BAD_CAST reg.name.c_str()));
345 /* name */
346 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "desc", BAD_CAST reg.desc.c_str()));
347 /* flags */
348 if(reg.flags & REG_HAS_SCT)
349 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "sct", BAD_CAST "yes"));
350 /* formula */
351 if(reg.formula.type != REG_FORMULA_NONE)
352 {
353 /* <formula> */
354 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "formula"));
355 switch(reg.formula.type)
356 {
357 case REG_FORMULA_STRING:
358 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "string",
359 BAD_CAST reg.formula.string.c_str()));
360 break;
361 default:
362 break;
363 }
364 /* </formula> */
365 SAFE(xmlTextWriterEndElement(writer));
366 }
367 /* addresses */
368 for(size_t i = 0; i < reg.addr.size(); i++)
369 {
370 /* <addr> */
371 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "addr"));
372 /* name */
373 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "name", BAD_CAST reg.addr[i].name.c_str()));
374 /* addr */
375 SAFE(xmlTextWriterWriteFormatAttribute(writer, BAD_CAST "addr", "0x%x", reg.addr[i].addr));
376 /* </addr> */
377 SAFE(xmlTextWriterEndElement(writer));
378 }
379 /* fields */
380 for(size_t i = 0; i < reg.field.size(); i++)
381 produce_field(writer, reg.field[i]);
382 /* </reg> */
383 SAFE(xmlTextWriterEndElement(writer));
384#undef SAFE
385 return 0;
386}
387
388int produce_dev(xmlTextWriterPtr writer, const soc_dev_t& dev)
389{
390#define SAFE(x) if((x) < 0) return -1;
391 /* <dev> */
392 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "dev"));
393 /* name */
394 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "name", BAD_CAST dev.name.c_str()));
395 /* long_name */
396 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "long_name", BAD_CAST dev.long_name.c_str()));
397 /* desc */
398 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "desc", BAD_CAST dev.desc.c_str()));
399 /* version */
400 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "version", BAD_CAST dev.version.c_str()));
401 /* addresses */
402 for(size_t i = 0; i < dev.addr.size(); i++)
403 {
404 /* <addr> */
405 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "addr"));
406 /* name */
407 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "name", BAD_CAST dev.addr[i].name.c_str()));
408 /* addr */
409 SAFE(xmlTextWriterWriteFormatAttribute(writer, BAD_CAST "addr", "0x%x", dev.addr[i].addr));
410 /* </addr> */
411 SAFE(xmlTextWriterEndElement(writer));
412 }
413 /* registers */
414 for(size_t i = 0; i < dev.reg.size(); i++)
415 produce_reg(writer, dev.reg[i]);
416 /* </dev> */
417 SAFE(xmlTextWriterEndElement(writer));
418#undef SAFE
419 return 0;
420}
421
422}
423
424bool produce_xml(const std::string& filename, const soc_t& soc)
425{
426 LIBXML_TEST_VERSION
427
428 xmlTextWriterPtr writer = xmlNewTextWriterFilename(filename.c_str(), 0);
429 if(writer == NULL)
430 return false;
431#define SAFE(x) if((x) < 0) goto Lerr
432 SAFE(xmlTextWriterSetIndent(writer, 1));
433 SAFE(xmlTextWriterSetIndentString(writer, BAD_CAST " "));
434 /* <xml> */
435 SAFE(xmlTextWriterStartDocument(writer, NULL, NULL, NULL));
436 /* <soc> */
437 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "soc"));
438 /* name */
439 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "name", BAD_CAST soc.name.c_str()));
440 /* desc */
441 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "desc", BAD_CAST soc.desc.c_str()));
442 /* devices */
443 for(size_t i = 0; i < soc.dev.size(); i++)
444 SAFE(produce_dev(writer, soc.dev[i]));
445 /* end <soc> */
446 SAFE(xmlTextWriterEndElement(writer));
447 /* </xml> */
448 SAFE(xmlTextWriterEndDocument(writer));
449 xmlFreeTextWriter(writer);
450 return true;
451#undef SAFE
452Lerr:
453 xmlFreeTextWriter(writer);
454 return false;
455}
456
457namespace
458{
459
460struct soc_sorter
461{
462 bool operator()(const soc_dev_t& a, const soc_dev_t& b) const
463 {
464 return a.name < b.name;
465 }
466
467 bool operator()(const soc_dev_addr_t& a, const soc_dev_addr_t& b) const
468 {
469 return a.name < b.name;
470 }
471
472 bool operator()(const soc_reg_t& a, const soc_reg_t& b) const
473 {
474 soc_addr_t aa = a.addr.size() > 0 ? a.addr[0].addr : 0;
475 soc_addr_t ab = b.addr.size() > 0 ? b.addr[0].addr : 0;
476 return aa < ab;
477 }
478
479 bool operator()(const soc_reg_addr_t& a, const soc_reg_addr_t& b) const
480 {
481 return a.addr < b.addr;
482 }
483
484 bool operator()(const soc_reg_field_t& a, const soc_reg_field_t& b) const
485 {
486 return a.last_bit > b.last_bit;
487 }
488
489 bool operator()(const soc_reg_field_value_t a, const soc_reg_field_value_t& b) const
490 {
491 return a.value < b.value;
492 }
493};
494
495void normalize(soc_reg_field_t& field)
496{
497 std::sort(field.value.begin(), field.value.end(), soc_sorter());
498}
499
500void normalize(soc_reg_t& reg)
501{
502 std::sort(reg.addr.begin(), reg.addr.end(), soc_sorter());
503 std::sort(reg.field.begin(), reg.field.end(), soc_sorter());
504 for(size_t i = 0; i < reg.field.size(); i++)
505 normalize(reg.field[i]);
506}
507
508void normalize(soc_dev_t& dev)
509{
510 std::sort(dev.addr.begin(), dev.addr.end(), soc_sorter());
511 std::sort(dev.reg.begin(), dev.reg.end(), soc_sorter());
512 for(size_t i = 0; i < dev.reg.size(); i++)
513 normalize(dev.reg[i]);
514}
515
516}
517
518void normalize(soc_t& soc)
519{
520 std::sort(soc.dev.begin(), soc.dev.end(), soc_sorter());
521 for(size_t i = 0; i < soc.dev.size(); i++)
522 normalize(soc.dev[i]);
523}
524
525namespace
526{
527 soc_error_t make_error(soc_error_level_t lvl, std::string at, std::string what)
528 {
529 soc_error_t err;
530 err.level = lvl;
531 err.location = at;
532 err.message = what;
533 return err;
534 }
535
536 soc_error_t make_warning(std::string at, std::string what)
537 {
538 return make_error(SOC_ERROR_WARNING, at, what);
539 }
540
541 soc_error_t make_fatal(std::string at, std::string what)
542 {
543 return make_error(SOC_ERROR_FATAL, at, what);
544 }
545
546 soc_error_t prefix(soc_error_t err, const std::string& prefix_at)
547 {
548 err.location = prefix_at + "." + err.location;
549 return err;
550 }
551
552 void add_errors(std::vector< soc_error_t >& errors,
553 const std::vector< soc_error_t >& new_errors, const std::string& prefix_at)
554 {
555 for(size_t i = 0; i < new_errors.size(); i++)
556 errors.push_back(prefix(new_errors[i], prefix_at));
557 }
558
559 std::vector< soc_error_t > no_error()
560 {
561 std::vector< soc_error_t > s;
562 return s;
563 }
564
565 std::vector< soc_error_t > one_error(const soc_error_t& err)
566 {
567 std::vector< soc_error_t > s;
568 s.push_back(err);
569 return s;
570 }
571
572 bool name_valid(char c)
573 {
574 return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') ||
575 (c >= 'A' && c <= 'Z') || c == '_';
576 }
577
578 bool name_valid(const std::string& s)
579 {
580 for(size_t i = 0; i < s.size(); i++)
581 if(!name_valid(s[i]))
582 return false;
583 return true;
584 }
585}
586
587std::vector< soc_error_t > soc_reg_field_value_t::errors(bool recursive)
588{
589 (void) recursive;
590 if(name.size() == 0)
591 return one_error(make_fatal(name, "empty name"));
592 else if(!name_valid(name))
593 return one_error(make_fatal(name, "invalid name"));
594 else
595 return no_error();
596}
597
598std::vector< soc_error_t > soc_reg_field_t::errors(bool recursive)
599{
600 std::vector< soc_error_t > err;
601 std::string at(name);
602 if(name.size() == 0)
603 err.push_back(make_fatal(at, "empty name"));
604 else if(!name_valid(name))
605 err.push_back(make_fatal(at, "invalid name"));
606 if(last_bit > 31)
607 err.push_back(make_fatal(at, "last bit is greater than 31"));
608 if(first_bit > last_bit)
609 err.push_back(make_fatal(at, "last bit is greater than first bit"));
610 for(size_t i = 0; i < value.size(); i++)
611 {
612 for(size_t j = 0; j < value.size(); j++)
613 {
614 if(i == j)
615 continue;
616 if(value[i].name == value[j].name)
617 err.push_back(prefix(make_fatal(value[i].name,
618 "there are several values with the same name"), at));
619 if(value[i].value == value[j].value)
620 err.push_back(prefix(make_warning(value[i].name,
621 "there are several values with the same value"), at));
622 }
623 if(value[i].value > (bitmask() >> first_bit))
624 err.push_back(prefix(make_warning(at, "value doesn't fit into the field"), value[i].name));
625 if(recursive)
626 add_errors(err, value[i].errors(true), at);
627 }
628 return err;
629}
630
631std::vector< soc_error_t > soc_reg_addr_t::errors(bool recursive)
632{
633 (void) recursive;
634 if(name.size() == 0)
635 return one_error(make_fatal("", "empty name"));
636 else if(!name_valid(name))
637 return one_error(make_fatal(name, "invalid name"));
638 else
639 return no_error();
640}
641
642std::vector< soc_error_t > soc_reg_formula_t::errors(bool recursive)
643{
644 (void) recursive;
645 if(type == REG_FORMULA_STRING && string.size() == 0)
646 return one_error(make_fatal("", "empty string formula"));
647 else
648 return no_error();
649}
650
651namespace
652{
653
654bool field_overlap(const soc_reg_field_t& a, const soc_reg_field_t& b)
655{
656 return !(a.first_bit > b.last_bit || b.first_bit > a.last_bit);
657}
658
659}
660
661std::vector< soc_error_t > soc_reg_t::errors(bool recursive)
662{
663 std::vector< soc_error_t > err;
664 std::string at(name);
665 if(name.size() == 0)
666 err.push_back(make_fatal(at, "empty name"));
667 else if(!name_valid(name))
668 err.push_back(make_fatal(at, "invalid name"));
669 for(size_t i = 0; i < addr.size(); i++)
670 {
671 for(size_t j = 0; j < addr.size(); j++)
672 {
673 if(i == j)
674 continue;
675 if(addr[i].name == addr[j].name)
676 err.push_back(prefix(make_fatal(addr[i].name,
677 "there are several instances with the same name"), at));
678 if(addr[i].addr == addr[j].addr)
679 err.push_back(prefix(make_fatal(addr[i].name,
680 "there are several instances with the same address"), at));
681 }
682 if(recursive)
683 add_errors(err, addr[i].errors(true), at);
684 }
685 if(recursive)
686 add_errors(err, formula.errors(true), at);
687 for(size_t i = 0; i < field.size(); i++)
688 {
689 for(size_t j = 0; j < field.size(); j++)
690 {
691 if(i == j)
692 continue;
693 if(field[i].name == field[j].name)
694 err.push_back(prefix(make_fatal(field[i].name,
695 "there are several fields with the same name"), at));
696 if(field_overlap(field[i], field[j]))
697 err.push_back(prefix(make_fatal(field[i].name,
698 "there are overlapping fields"), at));
699 }
700 if(recursive)
701 add_errors(err, field[i].errors(true), at);
702 }
703 return err;
704}
705
706std::vector< soc_error_t > soc_dev_addr_t::errors(bool recursive)
707{
708 (void) recursive;
709 if(name.size() == 0)
710 return one_error(make_fatal("", "empty name"));
711 else if(!name_valid(name))
712 return one_error(make_fatal(name, "invalid name"));
713 else
714 return no_error();
715}
716
717std::vector< soc_error_t > soc_dev_t::errors(bool recursive)
718{
719 std::vector< soc_error_t > err;
720 std::string at(name);
721 if(name.size() == 0)
722 err.push_back(make_fatal(at, "empty name"));
723 else if(!name_valid(name))
724 err.push_back(make_fatal(at, "invalid name"));
725 for(size_t i = 0; i < addr.size(); i++)
726 {
727 for(size_t j = 0; j < addr.size(); j++)
728 {
729 if(i == j)
730 continue;
731 if(addr[i].name == addr[j].name)
732 err.push_back(prefix(make_fatal(addr[i].name,
733 "there are several instances with the same name"), at));
734 if(addr[i].addr == addr[j].addr)
735 err.push_back(prefix(make_fatal(addr[i].name,
736 "there are several instances with the same address"), at));
737 }
738 if(recursive)
739 add_errors(err, addr[i].errors(true), at);
740 }
741 for(size_t i = 0; i < reg.size(); i++)
742 {
743 for(size_t j = 0; j < reg.size(); j++)
744 {
745 if(i == j)
746 continue;
747 if(reg[i].name == reg[j].name)
748 err.push_back(prefix(make_fatal(reg[i].name,
749 "there are several registers with the same name"), at));
750 }
751 if(recursive)
752 add_errors(err, reg[i].errors(true), at);
753 }
754 return err;
755}
756
757std::vector< soc_error_t > soc_t::errors(bool recursive)
758{
759 std::vector< soc_error_t > err;
760 std::string at(name);
761 for(size_t i = 0; i < dev.size(); i++)
762 {
763 for(size_t j = 0; j < dev.size(); j++)
764 {
765 if(i == j)
766 continue;
767 if(dev[i].name == dev[j].name)
768 err.push_back(prefix(make_fatal(dev[i].name,
769 "there are several devices with the same name"), at));
770 }
771 if(recursive)
772 add_errors(err, dev[i].errors(true), at);
773 }
774 return err;
775}
776
777namespace
778{
779
780struct formula_evaluator
781{
782 std::string formula;
783 size_t pos;
784 std::string error;
785
786 bool err(const char *fmt, ...)
787 {
788 char buffer[256];
789 va_list args;
790 va_start(args, fmt);
791 vsnprintf(buffer,sizeof(buffer), fmt, args);
792 va_end(args);
793 error = buffer;
794 return false;
795 }
796
797 formula_evaluator(const std::string& s):pos(0)
798 {
799 for(size_t i = 0; i < s.size(); i++)
800 if(!isspace(s[i]))
801 formula.push_back(s[i]);
802 }
803
804 void adv()
805 {
806 pos++;
807 }
808
809 char cur()
810 {
811 return end() ? 0 : formula[pos];
812 }
813
814 bool end()
815 {
816 return pos >= formula.size();
817 }
818
819 bool parse_digit(char c, int basis, soc_word_t& res)
820 {
821 c = tolower(c);
822 if(isdigit(c))
823 {
824 res = c - '0';
825 return true;
826 }
827 if(basis == 16 && isxdigit(c))
828 {
829 res = c + 10 - 'a';
830 return true;
831 }
832 return err("invalid digit '%c'", c);
833 }
834
835 bool parse_signed(soc_word_t& res)
836 {
837 char op = cur();
838 if(op == '+' || op == '-')
839 {
840 adv();
841 if(!parse_signed(res))
842 return false;
843 if(op == '-')
844 res *= -1;
845 return true;
846 }
847 else if(op == '(')
848 {
849 adv();
850 if(!parse_expression(res))
851 return false;
852 if(cur() != ')')
853 return err("expected ')', got '%c'", cur());
854 adv();
855 return true;
856 }
857 else if(isdigit(op))
858 {
859 res = op - '0';
860 adv();
861 int basis = 10;
862 if(op == '0' && cur() == 'x')
863 {
864 basis = 16;
865 adv();
866 }
867 soc_word_t digit = 0;
868 while(parse_digit(cur(), basis, digit))
869 {
870 res = res * basis + digit;
871 adv();
872 }
873 return true;
874 }
875 else if(isalpha(op) || op == '_')
876 {
877 std::string name;
878 while(isalnum(cur()) || cur() == '_')
879 {
880 name.push_back(cur());
881 adv();
882 }
883 return get_variable(name, res);
884 }
885 else
886 return err("express signed expression, got '%c'", op);
887 }
888
889 bool parse_term(soc_word_t& res)
890 {
891 if(!parse_signed(res))
892 return false;
893 while(cur() == '*' || cur() == '/' || cur() == '%')
894 {
895 char op = cur();
896 adv();
897 soc_word_t tmp;
898 if(!parse_signed(tmp))
899 return false;
900 if(op == '*')
901 res *= tmp;
902 else if(tmp != 0)
903 res = op == '/' ? res / tmp : res % tmp;
904 else
905 return err("division by 0");
906 }
907 return true;
908 }
909
910 bool parse_expression(soc_word_t& res)
911 {
912 if(!parse_term(res))
913 return false;
914 while(!end() && (cur() == '+' || cur() == '-'))
915 {
916 char op = cur();
917 adv();
918 soc_word_t tmp;
919 if(!parse_term(tmp))
920 return false;
921 if(op == '+')
922 res += tmp;
923 else
924 res -= tmp;
925 }
926 return true;
927 }
928
929 bool parse(soc_word_t& res, std::string& _error)
930 {
931 bool ok = parse_expression(res);
932 if(ok && !end())
933 err("unexpected character '%c'", cur());
934 _error = error;
935 return ok && end();
936 }
937
938 virtual bool get_variable(std::string name, soc_word_t& res)
939 {
940 return err("unknown variable '%s'", name.c_str());
941 }
942};
943
944struct my_evaluator : public formula_evaluator
945{
946 const std::map< std::string, soc_word_t>& var;
947
948 my_evaluator(const std::string& formula, const std::map< std::string, soc_word_t>& _var)
949 :formula_evaluator(formula), var(_var) {}
950
951 virtual bool get_variable(std::string name, soc_word_t& res)
952 {
953 std::map< std::string, soc_word_t>::const_iterator it = var.find(name);
954 if(it == var.end())
955 return formula_evaluator::get_variable(name, res);
956 else
957 {
958 res = it->second;
959 return true;
960 }
961 }
962};
963
964}
965
966bool evaluate_formula(const std::string& formula,
967 const std::map< std::string, soc_word_t>& var, soc_word_t& result, std::string& error)
968{
969 my_evaluator e(formula, var);
970 return e.parse(result, error);
971}
972
973/** WARNING we need to call xmlInitParser() to init libxml2 but it needs to
974 * called from the main thread, which is a super strong requirement, so do it
975 * using a static constructor */
976namespace
977{
978class xml_parser_init
979{
980public:
981 xml_parser_init()
982 {
983 xmlInitParser();
984 }
985};
986
987xml_parser_init __xml_parser_init;
988}
989
990} // soc_desc_v1