A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 1741 lines 50 kB view raw
1/*************************************************************************** 2 * __________ __ ___. 3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 * \/ \/ \/ \/ \/ 8 * $Id$ 9 * 10 * Copyright (C) 2014 by Amaury Pouly 11 * 12 * This program is free software; you can redistribute it and/or 13 * modify it under the terms of the GNU General Public License 14 * as published by the Free Software Foundation; either version 2 15 * of the License, or (at your option) any later version. 16 * 17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 18 * KIND, either express or implied. 19 * 20 ****************************************************************************/ 21#include "soc_desc.hpp" 22#include <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#include <sstream> 31#include <limits> 32 33namespace soc_desc 34{ 35 36/** 37 * Parser 38 */ 39 40#define XML_CHAR_TO_CHAR(s) ((const char *)(s)) 41 42#define BEGIN_ATTR_MATCH(attr) \ 43 for(xmlAttr *a = attr; a; a = a->next) { \ 44 bool used = false; 45 46#define MATCH_UNIQUE_ATTR(attr_name, val, has, parse_fn, ctx) \ 47 if(strcmp(XML_CHAR_TO_CHAR(a->name), attr_name) == 0) { \ 48 if(has) \ 49 return parse_not_unique_attr_error(a, ctx); \ 50 has = true; \ 51 xmlChar *str = NULL; \ 52 if(!parse_text_attr_internal(a, str, ctx) || !parse_fn(a, val, str, ctx)) \ 53 ret = false; \ 54 used = true; \ 55 } 56 57#define MATCH_UNUSED_ATTR(parse_fn, ctx) \ 58 if(!used) { \ 59 ret = ret && parse_fn(a, ctx); \ 60 } 61 62#define END_ATTR_MATCH() \ 63 } 64 65#define BEGIN_NODE_MATCH(node) \ 66 for(xmlNode *sub = node; sub; sub = sub->next) { \ 67 bool used = false; \ 68 69#define MATCH_ELEM_NODE(node_name, array, parse_fn, ctx) \ 70 if(sub->type == XML_ELEMENT_NODE && strcmp(XML_CHAR_TO_CHAR(sub->name), node_name) == 0) { \ 71 array.resize(array.size() + 1); \ 72 if(!parse_fn(sub, array.back(), ctx)) \ 73 ret = false; \ 74 array.back().id = array.size(); \ 75 used = true; \ 76 } 77 78#define MATCH_TEXT_NODE(node_name, array, parse_fn, ctx) \ 79 if(sub->type == XML_ELEMENT_NODE && strcmp(XML_CHAR_TO_CHAR(sub->name), node_name) == 0) { \ 80 if(!is_real_text_node(sub)) \ 81 return parse_not_text_error(sub, ctx); \ 82 xmlChar *content = xmlNodeGetContent(sub); \ 83 array.resize(array.size() + 1); \ 84 ret = ret && parse_fn(sub, array.back(), content, ctx); \ 85 xmlFree(content); \ 86 used = true; \ 87 } 88 89#define MATCH_UNIQUE_ELEM_NODE(node_name, val, has, parse_fn, ctx) \ 90 if(sub->type == XML_ELEMENT_NODE && strcmp(XML_CHAR_TO_CHAR(sub->name), node_name) == 0) { \ 91 if(has) \ 92 return parse_not_unique_error(sub, ctx); \ 93 has = true; \ 94 if(!parse_fn(sub, val, ctx)) \ 95 ret = false; \ 96 used = true; \ 97 } 98 99#define MATCH_UNIQUE_TEXT_NODE(node_name, val, has, parse_fn, ctx) \ 100 if(sub->type == XML_ELEMENT_NODE && strcmp(XML_CHAR_TO_CHAR(sub->name), node_name) == 0) { \ 101 if(has) \ 102 return parse_not_unique_error(sub, ctx); \ 103 if(!is_real_text_node(sub)) \ 104 return parse_not_text_error(sub, ctx); \ 105 has = true; \ 106 xmlChar *content = xmlNodeGetContent(sub); \ 107 ret = ret && parse_fn(sub, val, content, ctx); \ 108 xmlFree(content); \ 109 used = true; \ 110 } 111 112#define MATCH_UNUSED_NODE(parse_fn, ctx) \ 113 if(!used) { \ 114 ret = ret && parse_fn(sub, ctx); \ 115 } 116 117#define END_NODE_MATCH() \ 118 } 119 120#define CHECK_HAS(node, node_name, has, ctx) \ 121 if(!has) \ 122 ret = ret && parse_missing_error(node, node_name, ctx); 123 124#define CHECK_HAS_ATTR(node, attr_name, has, ctx) \ 125 if(!has) \ 126 ret = ret && parse_missing_attr_error(node, attr_name, ctx); 127 128namespace 129{ 130 131bool is_real_text_node(xmlNode *node) 132{ 133 for(xmlNode *sub = node->children; sub; sub = sub->next) 134 if(sub->type != XML_TEXT_NODE && sub->type != XML_ENTITY_REF_NODE) 135 return false; 136 return true; 137} 138 139std::string xml_loc(xmlNode *node) 140{ 141 std::ostringstream oss; 142 oss << "line " << node->line; 143 return oss.str(); 144} 145 146std::string xml_loc(xmlAttr *attr) 147{ 148 return xml_loc(attr->parent); 149} 150 151template<typename T> 152bool add_error(error_context_t& ctx, err_t::level_t lvl, T *node, 153 const std::string& msg) 154{ 155 ctx.add(err_t(lvl, xml_loc(node), msg)); 156 return false; 157} 158 159template<typename T> 160bool add_fatal(error_context_t& ctx, T *node, const std::string& msg) 161{ 162 return add_error(ctx, err_t::FATAL, node, msg); 163} 164 165template<typename T> 166bool add_warning(error_context_t& ctx, T *node, const std::string& msg) 167{ 168 return add_error(ctx, err_t::WARNING, node, msg); 169} 170 171bool parse_wrong_version_error(xmlNode *node, error_context_t& ctx) 172{ 173 std::ostringstream oss; 174 oss << "unknown version, only version " << MAJOR_VERSION << " is supported"; 175 return add_fatal(ctx, node, oss.str()); 176} 177 178bool parse_not_unique_error(xmlNode *node, error_context_t& ctx) 179{ 180 std::ostringstream oss; 181 oss << "there must be a unique <" << XML_CHAR_TO_CHAR(node->name) << "> element"; 182 if(node->parent->name) 183 oss << " in <" << XML_CHAR_TO_CHAR(node->parent->name) << ">"; 184 else 185 oss << " at root level"; 186 return add_fatal(ctx, node, oss.str()); 187} 188 189bool parse_not_unique_attr_error(xmlAttr *attr, error_context_t& ctx) 190{ 191 std::ostringstream oss; 192 oss << "there must be a unique " << XML_CHAR_TO_CHAR(attr->name) << " attribute"; 193 oss << " in <" << XML_CHAR_TO_CHAR(attr->parent->name) << ">"; 194 return add_fatal(ctx, attr, oss.str()); 195} 196 197bool parse_missing_error(xmlNode *node, const char *name, error_context_t& ctx) 198{ 199 std::ostringstream oss; 200 oss << "missing <" << name << "> element"; 201 if(node->parent->name) 202 oss << " in <" << XML_CHAR_TO_CHAR(node->parent->name) << ">"; 203 else 204 oss << " at root level"; 205 return add_fatal(ctx, node, oss.str()); 206} 207 208bool parse_missing_attr_error(xmlNode *node, const char *name, error_context_t& ctx) 209{ 210 std::ostringstream oss; 211 oss << "missing " << name << " attribute"; 212 oss << " in <" << XML_CHAR_TO_CHAR(node->name) << ">"; 213 return add_fatal(ctx, node, oss.str()); 214} 215 216bool parse_conflict_error(xmlNode *node, const char *name1, const char *name2, 217 error_context_t& ctx) 218{ 219 std::ostringstream oss; 220 oss << "conflicting <" << name1 << "> and <" << name2 << "> elements"; 221 if(node->parent->name) 222 oss << " in <" << XML_CHAR_TO_CHAR(node->parent->name) << ">"; 223 else 224 oss << " at root level"; 225 return add_fatal(ctx, node, oss.str()); 226} 227 228bool parse_not_text_error(xmlNode *node, error_context_t& ctx) 229{ 230 return add_fatal(ctx, node, "this is not a text element"); 231} 232 233bool parse_not_text_attr_error(xmlAttr *attr, error_context_t& ctx) 234{ 235 return add_fatal(ctx, attr, "this is not a text attribute"); 236} 237 238bool parse_text_elem(xmlNode *node, std::string& name, xmlChar *content, error_context_t& ctx) 239{ 240 name = XML_CHAR_TO_CHAR(content); 241 return true; 242} 243 244bool parse_name_elem(xmlNode *node, std::string& name, xmlChar *content, error_context_t& ctx) 245{ 246 name = XML_CHAR_TO_CHAR(content); 247 if(name.size() == 0) 248 return add_fatal(ctx, node, "name cannot be empty"); 249 for(size_t i = 0; i < name.size(); i++) 250 if(!isalnum(name[i]) && name[i] != '_') 251 return add_fatal(ctx, node, "name must only contain alphanumeric characters or _"); 252 return true; 253} 254 255bool parse_unknown_elem(xmlNode *node, error_context_t& ctx) 256{ 257 /* ignore blank nodes */ 258 if(xmlIsBlankNode(node)) 259 return true; 260 std::ostringstream oss; 261 oss << "unknown <" << XML_CHAR_TO_CHAR(node->name) << "> element"; 262 return add_fatal(ctx, node, oss.str()); 263} 264 265bool parse_access_elem(xmlNode *node, access_t& acc, xmlChar *content, error_context_t& ctx) 266{ 267 const char *text = XML_CHAR_TO_CHAR(content); 268 if(strcmp(text, "read-only") == 0) 269 acc = READ_ONLY; 270 else if(strcmp(text, "read-write") == 0) 271 acc = READ_WRITE; 272 else if(strcmp(text, "write-only") == 0) 273 acc = WRITE_ONLY; 274 else 275 return add_fatal(ctx, node, "unknown access type " + std::string(text)); 276 return true; 277} 278 279template<typename T, typename U> 280bool parse_unsigned_text(U *node, T& res, xmlChar *content, error_context_t& ctx) 281{ 282 char *end; 283 unsigned long uns = strtoul(XML_CHAR_TO_CHAR(content), &end, 0); 284 if(*end != 0) 285 return add_fatal(ctx, node, "content must be an unsigned integer"); 286 res = uns; 287 if(res != uns) 288 return add_fatal(ctx, node, "value does not fit into allowed range"); 289 return true; 290} 291 292template<typename T> 293bool parse_unsigned_elem(xmlNode *node, T& res, xmlChar *content, error_context_t& ctx) 294{ 295 return parse_unsigned_text(node, res, content, ctx); 296} 297 298template<typename T> 299bool parse_unsigned_attr(xmlAttr *attr, T& res, xmlChar *content, error_context_t& ctx) 300{ 301 return parse_unsigned_text(attr, res, content, ctx); 302} 303 304bool parse_text_attr_internal(xmlAttr *attr, xmlChar*& res, error_context_t& ctx) 305{ 306 if(attr->children != attr->last) 307 return false; 308 if(attr->children->type != XML_TEXT_NODE) 309 return parse_not_text_attr_error(attr, ctx); 310 res = attr->children->content; 311 return true; 312} 313 314bool parse_text_attr(xmlAttr *attr, std::string& res, xmlChar *content, error_context_t& ctx) 315{ 316 res = XML_CHAR_TO_CHAR(content); 317 return true; 318} 319 320bool parse_unknown_attr(xmlAttr *attr, error_context_t& ctx) 321{ 322 std::ostringstream oss; 323 oss << "unknown '" << XML_CHAR_TO_CHAR(attr->name) << "' attribute"; 324 return add_fatal(ctx, attr, oss.str()); 325} 326 327 328bool parse_enum_elem(xmlNode *node, enum_t& reg, error_context_t& ctx) 329{ 330 bool ret = true; 331 bool has_name = false, has_value = false, has_desc = false; 332 BEGIN_NODE_MATCH(node->children) 333 MATCH_UNIQUE_TEXT_NODE("name", reg.name, has_name, parse_name_elem, ctx) 334 MATCH_UNIQUE_TEXT_NODE("value", reg.value, has_value, parse_unsigned_elem, ctx) 335 MATCH_UNIQUE_TEXT_NODE("desc", reg.desc, has_desc, parse_text_elem, ctx) 336 MATCH_UNUSED_NODE(parse_unknown_elem, ctx) 337 END_NODE_MATCH() 338 CHECK_HAS(node, "name", has_name, ctx) 339 CHECK_HAS(node, "value", has_value, ctx) 340 return ret; 341} 342 343bool parse_field_elem(xmlNode *node, field_t& field, error_context_t& ctx) 344{ 345 bool ret = true; 346 bool has_name = false, has_pos = false, has_desc = false, has_width = false; 347 BEGIN_NODE_MATCH(node->children) 348 MATCH_UNIQUE_TEXT_NODE("name", field.name, has_name, parse_name_elem, ctx) 349 MATCH_UNIQUE_TEXT_NODE("position", field.pos, has_pos, parse_unsigned_elem, ctx) 350 MATCH_UNIQUE_TEXT_NODE("width", field.width, has_width, parse_unsigned_elem, ctx) 351 MATCH_UNIQUE_TEXT_NODE("desc", field.desc, has_desc, parse_text_elem, ctx) 352 MATCH_ELEM_NODE("enum", field.enum_, parse_enum_elem, ctx) 353 MATCH_UNUSED_NODE(parse_unknown_elem, ctx) 354 END_NODE_MATCH() 355 CHECK_HAS(node, "name", has_name, ctx) 356 CHECK_HAS(node, "position", has_pos, ctx) 357 if(!has_width) 358 field.width = 1; 359 return ret; 360} 361 362bool parse_variant_elem(xmlNode *node, variant_t& variant, error_context_t& ctx) 363{ 364 bool ret = true; 365 bool has_type = false, has_offset = false, has_access = false; 366 BEGIN_NODE_MATCH(node->children) 367 MATCH_UNIQUE_TEXT_NODE("type", variant.type, has_type, parse_name_elem, ctx) 368 MATCH_UNIQUE_TEXT_NODE("offset", variant.offset, has_offset, parse_unsigned_elem, ctx) 369 MATCH_UNIQUE_TEXT_NODE("access", variant.access, has_access, parse_access_elem, ctx) 370 MATCH_UNUSED_NODE(parse_unknown_elem, ctx) 371 END_NODE_MATCH() 372 CHECK_HAS(node, "type", has_type, ctx) 373 CHECK_HAS(node, "offset", has_offset, ctx) 374 if(!has_access) 375 variant.access = UNSPECIFIED; 376 return ret; 377} 378 379bool parse_register_elem(xmlNode *node, register_t& reg, error_context_t& ctx) 380{ 381 bool ret = true; 382 bool has_width = false, has_desc = false, has_access = false; 383 BEGIN_NODE_MATCH(node->children) 384 MATCH_UNIQUE_TEXT_NODE("desc", reg.desc, has_desc, parse_text_elem, ctx) 385 MATCH_UNIQUE_TEXT_NODE("width", reg.width, has_width, parse_unsigned_elem, ctx) 386 MATCH_UNIQUE_TEXT_NODE("access", reg.access, has_access, parse_access_elem, ctx) 387 MATCH_ELEM_NODE("field", reg.field, parse_field_elem, ctx) 388 MATCH_ELEM_NODE("variant", reg.variant, parse_variant_elem, ctx) 389 MATCH_UNUSED_NODE(parse_unknown_elem, ctx) 390 END_NODE_MATCH() 391 if(!has_width) 392 reg.width = 32; 393 if(!has_access) 394 reg.access = UNSPECIFIED; 395 return ret; 396} 397 398bool parse_formula_elem(xmlNode *node, range_t& range, error_context_t& ctx) 399{ 400 bool ret = true; 401 bool has_var = false; 402 BEGIN_ATTR_MATCH(node->properties) 403 MATCH_UNIQUE_ATTR("variable", range.variable, has_var, parse_text_attr, ctx) 404 MATCH_UNUSED_ATTR(parse_unknown_attr, ctx) 405 END_NODE_MATCH() 406 CHECK_HAS_ATTR(node, "variable", has_var, ctx) 407 return ret; 408} 409 410bool parse_range_elem(xmlNode *node, range_t& range, error_context_t& ctx) 411{ 412 bool ret = true; 413 bool has_first = false, has_count = false, has_stride = false, has_base = false; 414 bool has_formula = false, has_formula_attr = false; 415 BEGIN_NODE_MATCH(node->children) 416 MATCH_UNIQUE_TEXT_NODE("first", range.first, has_first, parse_unsigned_elem, ctx) 417 MATCH_UNIQUE_TEXT_NODE("count", range.count, has_count, parse_unsigned_elem, ctx) 418 MATCH_UNIQUE_TEXT_NODE("base", range.base, has_base, parse_unsigned_elem, ctx) 419 MATCH_UNIQUE_TEXT_NODE("stride", range.stride, has_stride, parse_unsigned_elem, ctx) 420 MATCH_UNIQUE_ELEM_NODE("formula", range, has_formula_attr, parse_formula_elem, ctx) 421 MATCH_UNIQUE_TEXT_NODE("formula", range.formula, has_formula, parse_text_elem, ctx) 422 MATCH_TEXT_NODE("address", range.list, parse_unsigned_elem, ctx) 423 MATCH_UNUSED_NODE(parse_unknown_elem, ctx) 424 END_NODE_MATCH() 425 CHECK_HAS(node, "first", has_first, ctx) 426 if(range.list.size() == 0) 427 { 428 CHECK_HAS(node, "count", has_count, ctx) 429 if(!has_base && !has_formula) 430 ret = ret && parse_missing_error(node, "base> or <formula", ctx); 431 if(has_base && has_formula) 432 return parse_conflict_error(node, "base", "formula", ctx); 433 if(has_base) 434 CHECK_HAS(node, "stride", has_stride, ctx) 435 if(has_stride && !has_base) 436 ret = ret && parse_conflict_error(node, "stride", "formula", ctx); 437 if(has_stride) 438 range.type = range_t::STRIDE; 439 else 440 range.type = range_t::FORMULA; 441 } 442 else 443 { 444 if(has_base) 445 ret = ret && parse_conflict_error(node, "base", "addr", ctx); 446 if(has_count) 447 ret = ret && parse_conflict_error(node, "count", "addr", ctx); 448 if(has_formula) 449 ret = ret && parse_conflict_error(node, "formula", "addr", ctx); 450 if(has_stride) 451 ret = ret && parse_conflict_error(node, "stride", "addr", ctx); 452 range.type = range_t::LIST; 453 } 454 return ret; 455} 456 457bool parse_instance_elem(xmlNode *node, instance_t& inst, error_context_t& ctx) 458{ 459 bool ret = true; 460 bool has_name = false, has_title = false, has_desc = false, has_range = false; 461 bool has_address = false, has_floating = false, has_nochild = false; 462 unsigned floating = 0, nochild = 0; 463 BEGIN_NODE_MATCH(node->children) 464 MATCH_UNIQUE_TEXT_NODE("name", inst.name, has_name, parse_name_elem, ctx) 465 MATCH_UNIQUE_TEXT_NODE("title", inst.title, has_title, parse_text_elem, ctx) 466 MATCH_UNIQUE_TEXT_NODE("desc", inst.desc, has_desc, parse_text_elem, ctx) 467 MATCH_UNIQUE_TEXT_NODE("nochild", nochild, has_nochild, parse_unsigned_elem, ctx) 468 MATCH_UNIQUE_TEXT_NODE("floating", floating, has_floating, parse_unsigned_elem, ctx) 469 MATCH_UNIQUE_TEXT_NODE("address", inst.addr, has_address, parse_unsigned_elem, ctx) 470 MATCH_UNIQUE_ELEM_NODE("range", inst.range, has_range, parse_range_elem, ctx) 471 MATCH_UNUSED_NODE(parse_unknown_elem, ctx) 472 END_NODE_MATCH() 473 CHECK_HAS(node, "name", has_name, ctx) 474 if(!has_address && !has_range && !floating) 475 ret = ret && parse_missing_error(node, "address> or <range", ctx); 476 if(has_address && has_range) 477 ret = ret && parse_conflict_error(node, "address", "range", ctx); 478 if(floating && has_address) 479 ret = ret && parse_conflict_error(node, "floating", "address", ctx); 480 if(floating && has_range) 481 ret = ret && parse_conflict_error(node, "floating", "range", ctx); 482 if(floating && nochild) 483 ret = ret && parse_conflict_error(node, "floating", "nochild", ctx); 484 if(floating) 485 inst.type = instance_t::FLOATING; 486 else if(has_address) 487 inst.type = instance_t::SINGLE; 488 else 489 inst.type = instance_t::RANGE; 490 if (nochild) 491 inst.nochild = true; 492 return ret; 493} 494 495bool parse_node_elem(xmlNode *node_, node_t& node, error_context_t& ctx) 496{ 497 bool ret = true; 498 register_t reg; 499 bool has_title = false, has_desc = false, has_register = false, has_name = false; 500 BEGIN_NODE_MATCH(node_->children) 501 MATCH_UNIQUE_TEXT_NODE("name", node.name, has_name, parse_name_elem, ctx) 502 MATCH_UNIQUE_TEXT_NODE("title", node.title, has_title, parse_text_elem, ctx) 503 MATCH_UNIQUE_TEXT_NODE("desc", node.desc, has_desc, parse_text_elem, ctx) 504 MATCH_UNIQUE_ELEM_NODE("register", reg, has_register, parse_register_elem, ctx) 505 MATCH_ELEM_NODE("node", node.node, parse_node_elem, ctx) 506 MATCH_ELEM_NODE("instance", node.instance, parse_instance_elem, ctx) 507 MATCH_UNUSED_NODE(parse_unknown_elem, ctx) 508 END_NODE_MATCH() 509 CHECK_HAS(node_, "name", has_name, ctx) 510 if(has_register) 511 node.register_.push_back(reg); 512 return ret; 513} 514 515bool parse_soc_elem(xmlNode *node, soc_t& soc, error_context_t& ctx) 516{ 517 bool ret = true; 518 bool has_name = false, has_title = false, has_desc = false, has_version = false; 519 bool has_isa = false; 520 BEGIN_NODE_MATCH(node->children) 521 MATCH_UNIQUE_TEXT_NODE("name", soc.name, has_name, parse_name_elem, ctx) 522 MATCH_UNIQUE_TEXT_NODE("title", soc.title, has_title, parse_text_elem, ctx) 523 MATCH_UNIQUE_TEXT_NODE("desc", soc.desc, has_desc, parse_text_elem, ctx) 524 MATCH_UNIQUE_TEXT_NODE("version", soc.version, has_version, parse_text_elem, ctx) 525 MATCH_UNIQUE_TEXT_NODE("isa", soc.isa, has_isa, parse_text_elem, ctx) 526 MATCH_TEXT_NODE("author", soc.author, parse_text_elem, ctx) 527 MATCH_ELEM_NODE("node", soc.node, parse_node_elem, ctx) 528 MATCH_UNUSED_NODE(parse_unknown_elem, ctx) 529 END_NODE_MATCH() 530 CHECK_HAS(node, "name", has_name, ctx) 531 return ret; 532} 533 534bool parse_root_elem(xmlNode *node, soc_t& soc, error_context_t& ctx) 535{ 536 size_t ver = 0; 537 bool ret = true; 538 bool has_soc = false, has_version = false; 539 BEGIN_ATTR_MATCH(node->properties) 540 MATCH_UNIQUE_ATTR("version", ver, has_version, parse_unsigned_attr, ctx) 541 MATCH_UNUSED_ATTR(parse_unknown_attr, ctx) 542 END_ATTR_MATCH() 543 if(!has_version) 544 { 545 ctx.add(err_t(err_t::FATAL, xml_loc(node), "no version attribute, is this a v1 file ?")); 546 return false; 547 } 548 if(ver != MAJOR_VERSION) 549 return parse_wrong_version_error(node, ctx); 550 BEGIN_NODE_MATCH(node) 551 MATCH_UNIQUE_ELEM_NODE("soc", soc, has_soc, parse_soc_elem, ctx) 552 MATCH_UNUSED_NODE(parse_unknown_elem, ctx) 553 END_NODE_MATCH() 554 CHECK_HAS(node, "soc", has_soc, ctx) 555 return ret; 556} 557 558} 559 560bool parse_xml(const std::string& filename, soc_t& soc, 561 error_context_t& error_ctx) 562{ 563 LIBXML_TEST_VERSION 564 565 xmlDocPtr doc = xmlReadFile(filename.c_str(), NULL, 0); 566 if(doc == NULL) 567 return false; 568 569 xmlNodePtr root_element = xmlDocGetRootElement(doc); 570 bool ret = parse_root_elem(root_element, soc, error_ctx); 571 572 xmlFreeDoc(doc); 573 574 return ret; 575} 576 577/** 578 * Normalizer 579 */ 580 581namespace 582{ 583 584struct soc_sorter 585{ 586 /* returns the lowest address of an instance, or 0 if none 587 * and 0xffffffff if cannot evaluate */ 588 soc_addr_t first_addr(const instance_t& inst) const 589 { 590 if(inst.type == instance_t::SINGLE) 591 return inst.addr; 592 /* sanity check */ 593 if(inst.type != instance_t::RANGE) 594 { 595 printf("Warning: unknown instance type %d\n", inst.type); 596 return 0; 597 } 598 if(inst.range.type == range_t::STRIDE) 599 return inst.range.base; /* assume positive stride */ 600 if(inst.range.type == range_t::LIST) 601 { 602 soc_addr_t min = 0xffffffff; 603 for(size_t i = 0; i < inst.range.list.size(); i++) 604 if(inst.range.list[i] < min) 605 min = inst.range.list[i]; 606 return min; 607 } 608 /* sanity check */ 609 if(inst.range.type != range_t::FORMULA) 610 { 611 printf("Warning: unknown range type %d\n", inst.range.type); 612 return 0; 613 } 614 soc_addr_t min = 0xffffffff; 615 std::map< std::string, soc_word_t > vars; 616 for(size_t i = 0; i < inst.range.count; i++) 617 { 618 soc_word_t res; 619 vars[inst.range.variable] = inst.range.first; 620 error_context_t ctx; 621 if(evaluate_formula(inst.range.formula, vars, res, "", ctx) && res < min) 622 min = res; 623 } 624 return min; 625 } 626 627 /* return smallest address among all instances */ 628 soc_addr_t first_addr(const node_t& node) const 629 { 630 soc_addr_t min = 0xffffffff; 631 for(size_t i = 0; i < node.instance.size(); i++) 632 min = std::min(min, first_addr(node.instance[i])); 633 return min; 634 } 635 636 /* sort instances by first address */ 637 bool operator()(const instance_t& a, const instance_t& b) const 638 { 639 return first_addr(a) < first_addr(b); 640 } 641 642 /* sort nodes by first address of first instance (which is the lowest of 643 * any instance if instances are sorted) */ 644 bool operator()(const node_t& a, const node_t& b) const 645 { 646 soc_addr_t addr_a = first_addr(a); 647 soc_addr_t addr_b = first_addr(b); 648 /* It may happen that two nodes have the same first instance address, 649 * for example if one logically splits a block into two blocks with 650 * the same base. In this case, sort by name */ 651 if(addr_a == addr_b) 652 return a.name < b.name; 653 return addr_a < addr_b; 654 } 655 656 /* sort fields by decreasing position */ 657 bool operator()(const field_t& a, const field_t& b) const 658 { 659 /* in the unlikely case where two fields have the same position, use name */ 660 if(a.pos == b.pos) 661 return a.name < b.name; 662 return a.pos > b.pos; 663 } 664 665 /* sort enum values by value, then by name */ 666 bool operator()(const enum_t& a, const enum_t& b) const 667 { 668 if(a.value == b.value) 669 return a.name < b.name; 670 return a.value < b.value; 671 } 672}; 673 674void normalize(field_t& field) 675{ 676 std::sort(field.enum_.begin(), field.enum_.end(), soc_sorter()); 677} 678 679void normalize(register_t& reg) 680{ 681 for(size_t i = 0; i < reg.field.size(); i++) 682 normalize(reg.field[i]); 683 std::sort(reg.field.begin(), reg.field.end(), soc_sorter()); 684} 685 686void normalize(node_t& node) 687{ 688 for(size_t i = 0; i < node.register_.size(); i++) 689 normalize(node.register_[i]); 690 for(size_t i = 0; i < node.node.size(); i++) 691 normalize(node.node[i]); 692 std::sort(node.node.begin(), node.node.end(), soc_sorter()); 693 std::sort(node.instance.begin(), node.instance.end(), soc_sorter()); 694} 695 696} /* namespace */ 697 698void normalize(soc_t& soc) 699{ 700 for(size_t i = 0; i < soc.node.size(); i++) 701 normalize(soc.node[i]); 702 std::sort(soc.node.begin(), soc.node.end(), soc_sorter()); 703} 704 705/** 706 * Producer 707 */ 708 709namespace 710{ 711 712#define SAFE(x) \ 713 do{ \ 714 if((x) < 0) { \ 715 std::ostringstream oss; \ 716 oss << __FILE__ << ":" << __LINE__; \ 717 ctx.add(err_t(err_t::FATAL, oss.str(), "write error")); \ 718 return -1; \ 719 } \ 720 }while(0) 721 722int produce_range(xmlTextWriterPtr writer, const range_t& range, error_context_t& ctx) 723{ 724 /* <range> */ 725 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "range")); 726 /* <first/> */ 727 SAFE(xmlTextWriterWriteFormatElement(writer, BAD_CAST "first", "%lu", range.first)); 728 if(range.type == range_t::STRIDE) 729 { 730 /* <count/> */ 731 SAFE(xmlTextWriterWriteFormatElement(writer, BAD_CAST "count", "%lu", range.count)); 732 /* <base/> */ 733 SAFE(xmlTextWriterWriteFormatElement(writer, BAD_CAST "base", "0x%x", range.base)); 734 /* <stride/> */ 735 SAFE(xmlTextWriterWriteFormatElement(writer, BAD_CAST "stride", "0x%x", range.stride)); 736 } 737 /* <formula> */ 738 else if(range.type == range_t::FORMULA) 739 { 740 /* <count/> */ 741 SAFE(xmlTextWriterWriteFormatElement(writer, BAD_CAST "count", "%lu", range.count)); 742 /* <formula> */ 743 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "formula")); 744 /* variable */ 745 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "variable", BAD_CAST range.variable.c_str())); 746 /* content */ 747 SAFE(xmlTextWriterWriteString(writer, BAD_CAST range.formula.c_str())); 748 /* </formula> */ 749 SAFE(xmlTextWriterEndElement(writer)); 750 } 751 else if(range.type == range_t::LIST) 752 { 753 for(size_t i = 0; i < range.list.size(); i++) 754 SAFE(xmlTextWriterWriteFormatElement(writer, BAD_CAST "address", "0x%x", range.list[i])); 755 } 756 /* </range> */ 757 SAFE(xmlTextWriterEndElement(writer)); 758 759 return 0; 760} 761 762int produce_instance(xmlTextWriterPtr writer, const instance_t& inst, error_context_t& ctx) 763{ 764 /* <instance> */ 765 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "instance")); 766 /* <name/> */ 767 SAFE(xmlTextWriterWriteElement(writer, BAD_CAST "name", BAD_CAST inst.name.c_str())); 768 /* <title/> */ 769 if(!inst.title.empty()) 770 SAFE(xmlTextWriterWriteElement(writer, BAD_CAST "title", BAD_CAST inst.title.c_str())); 771 /* <desc/> */ 772 if(!inst.desc.empty()) 773 SAFE(xmlTextWriterWriteElement(writer, BAD_CAST "desc", BAD_CAST inst.desc.c_str())); 774 /* <address/> */ 775 if(inst.type == instance_t::SINGLE) 776 SAFE(xmlTextWriterWriteFormatElement(writer, BAD_CAST "address", "0x%x", inst.addr)); 777 /* <range/> */ 778 else if(inst.type == instance_t::RANGE) 779 SAFE(produce_range(writer, inst.range, ctx)); 780 /* </instance> */ 781 SAFE(xmlTextWriterEndElement(writer)); 782 return 0; 783} 784 785int produce_enum(xmlTextWriterPtr writer, const enum_t& enum_, error_context_t& ctx) 786{ 787 /* <enum> */ 788 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "enum")); 789 /* <name/> */ 790 SAFE(xmlTextWriterWriteElement(writer, BAD_CAST "name", BAD_CAST enum_.name.c_str())); 791 /* <desc/> */ 792 if(!enum_.desc.empty()) 793 SAFE(xmlTextWriterWriteElement(writer, BAD_CAST "desc", BAD_CAST enum_.desc.c_str())); 794 /* <value/> */ 795 SAFE(xmlTextWriterWriteFormatElement(writer, BAD_CAST "value", "0x%x", enum_.value)); 796 /* </enum> */ 797 SAFE(xmlTextWriterEndElement(writer)); 798 return 0; 799} 800 801int produce_field(xmlTextWriterPtr writer, const field_t& field, error_context_t& ctx) 802{ 803 /* <field> */ 804 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "field")); 805 /* <name/> */ 806 SAFE(xmlTextWriterWriteElement(writer, BAD_CAST "name", BAD_CAST field.name.c_str())); 807 /* <desc/> */ 808 if(!field.desc.empty()) 809 SAFE(xmlTextWriterWriteElement(writer, BAD_CAST "desc", BAD_CAST field.desc.c_str())); 810 /* <position/> */ 811 SAFE(xmlTextWriterWriteFormatElement(writer, BAD_CAST "position", "%lu", field.pos)); 812 /* <width/> */ 813 if(field.width != 1) 814 SAFE(xmlTextWriterWriteFormatElement(writer, BAD_CAST "width", "%lu", field.width)); 815 /* enums */ 816 for(size_t i = 0; i < field.enum_.size(); i++) 817 SAFE(produce_enum(writer, field.enum_[i], ctx)); 818 /* </field> */ 819 SAFE(xmlTextWriterEndElement(writer)); 820 return 0; 821} 822 823const char *access_string(access_t acc) 824{ 825 switch(acc) 826 { 827 case READ_ONLY: return "read-only"; 828 case READ_WRITE: return "read-write"; 829 case WRITE_ONLY: return "write-only"; 830 default: return "bug-invalid-access"; 831 } 832} 833 834int produce_variant(xmlTextWriterPtr writer, const variant_t& variant, error_context_t& ctx) 835{ 836 /* <variant> */ 837 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "variant")); 838 /* <name/> */ 839 SAFE(xmlTextWriterWriteElement(writer, BAD_CAST "type", BAD_CAST variant.type.c_str())); 840 /* <position/> */ 841 SAFE(xmlTextWriterWriteFormatElement(writer, BAD_CAST "offset", "%lu", (unsigned long)variant.offset)); 842 /* <access/> */ 843 if(variant.access != UNSPECIFIED) 844 SAFE(xmlTextWriterWriteElement(writer, BAD_CAST "access", BAD_CAST access_string(variant.access))); 845 /* </variant> */ 846 SAFE(xmlTextWriterEndElement(writer)); 847 return 0; 848} 849 850int produce_register(xmlTextWriterPtr writer, const register_t& reg, error_context_t& ctx) 851{ 852 /* <register> */ 853 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "register")); 854 /* <width/> */ 855 if(reg.width != 32) 856 SAFE(xmlTextWriterWriteFormatElement(writer, BAD_CAST "width", "%lu", reg.width)); 857 /* <desc/> */ 858 if(!reg.desc.empty()) 859 SAFE(xmlTextWriterWriteElement(writer, BAD_CAST "desc", BAD_CAST reg.desc.c_str())); 860 /* <access/> */ 861 if(reg.access != UNSPECIFIED) 862 SAFE(xmlTextWriterWriteElement(writer, BAD_CAST "access", BAD_CAST access_string(reg.access))); 863 /* fields */ 864 for(size_t i = 0; i < reg.field.size(); i++) 865 SAFE(produce_field(writer, reg.field[i], ctx)); 866 /* variants */ 867 for(size_t i = 0; i < reg.variant.size(); i++) 868 SAFE(produce_variant(writer, reg.variant[i], ctx)); 869 /* </register> */ 870 SAFE(xmlTextWriterEndElement(writer)); 871 return 0; 872} 873 874int produce_node(xmlTextWriterPtr writer, const node_t& node, error_context_t& ctx) 875{ 876 /* <node> */ 877 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "node")); 878 /* <name/> */ 879 SAFE(xmlTextWriterWriteElement(writer, BAD_CAST "name", BAD_CAST node.name.c_str())); 880 /* <title/> */ 881 if(!node.title.empty()) 882 SAFE(xmlTextWriterWriteElement(writer, BAD_CAST "title", BAD_CAST node.title.c_str())); 883 /* <desc/> */ 884 if(!node.desc.empty()) 885 SAFE(xmlTextWriterWriteElement(writer, BAD_CAST "desc", BAD_CAST node.desc.c_str())); 886 /* instances */ 887 for(size_t i = 0; i < node.instance.size(); i++) 888 SAFE(produce_instance(writer, node.instance[i], ctx)); 889 /* register */ 890 for(size_t i = 0; i < node.register_.size(); i++) 891 SAFE(produce_register(writer, node.register_[i], ctx)); 892 /* nodes */ 893 for(size_t i = 0; i < node.node.size(); i++) 894 SAFE(produce_node(writer, node.node[i], ctx)); 895 /* </node> */ 896 SAFE(xmlTextWriterEndElement(writer)); 897 return 0; 898} 899 900#undef SAFE 901 902} 903 904bool produce_xml(const std::string& filename, const soc_t& soc, error_context_t& ctx) 905{ 906 LIBXML_TEST_VERSION 907 908 std::ostringstream oss; 909 xmlTextWriterPtr writer = xmlNewTextWriterFilename(filename.c_str(), 0); 910 if(writer == NULL) 911 return false; 912#define SAFE(x) do{if((x) < 0) goto Lerr;}while(0) 913 SAFE(xmlTextWriterSetIndent(writer, 1)); 914 SAFE(xmlTextWriterSetIndentString(writer, BAD_CAST " ")); 915 /* <xml> */ 916 SAFE(xmlTextWriterStartDocument(writer, NULL, NULL, NULL)); 917 /* <soc> */ 918 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "soc")); 919 /* version */ 920 oss << MAJOR_VERSION; 921 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "version", BAD_CAST oss.str().c_str())); 922 /* <name/> */ 923 SAFE(xmlTextWriterWriteElement(writer, BAD_CAST "name", BAD_CAST soc.name.c_str())); 924 /* <title/> */ 925 if(!soc.title.empty()) 926 SAFE(xmlTextWriterWriteElement(writer, BAD_CAST "title", BAD_CAST soc.title.c_str())); 927 /* <desc/> */ 928 if(!soc.desc.empty()) 929 SAFE(xmlTextWriterWriteElement(writer, BAD_CAST "desc", BAD_CAST soc.desc.c_str())); 930 /* <author/> */ 931 for(size_t i = 0; i < soc.author.size(); i++) 932 SAFE(xmlTextWriterWriteElement(writer, BAD_CAST "author", BAD_CAST soc.author[i].c_str())); 933 /* <isa/> */ 934 if(!soc.isa.empty()) 935 SAFE(xmlTextWriterWriteElement(writer, BAD_CAST "isa", BAD_CAST soc.isa.c_str())); 936 /* <version/> */ 937 if(!soc.version.empty()) 938 SAFE(xmlTextWriterWriteElement(writer, BAD_CAST "version", BAD_CAST soc.version.c_str())); 939 /* nodes */ 940 for(size_t i = 0; i < soc.node.size(); i++) 941 SAFE(produce_node(writer, soc.node[i], ctx)); 942 /* </soc> */ 943 SAFE(xmlTextWriterEndElement(writer)); 944 /* </xml> */ 945 SAFE(xmlTextWriterEndDocument(writer)); 946 xmlFreeTextWriter(writer); 947 return true; 948#undef SAFE 949Lerr: 950 xmlFreeTextWriter(writer); 951 return false; 952} 953 954/** 955 * utils 956 */ 957 958namespace 959{ 960 961template< typename T > 962soc_id_t gen_fresh_id(const std::vector< T >& list) 963{ 964 soc_id_t id = 0; 965 for(size_t i = 0; i < list.size(); i++) 966 id = std::max(id, list[i].id); 967 return id + 1; 968} 969 970} 971 972/** 973 * soc_ref_t 974 */ 975 976soc_ref_t::soc_ref_t():m_soc(0) 977{ 978} 979 980soc_ref_t::soc_ref_t(soc_t *soc):m_soc(soc) 981{ 982} 983 984bool soc_ref_t::valid() const 985{ 986 return get() != 0; 987} 988 989soc_t *soc_ref_t::get() const 990{ 991 return m_soc; 992} 993 994bool soc_ref_t::operator==(const soc_ref_t& ref) const 995{ 996 return m_soc == ref.m_soc; 997} 998 999node_ref_t soc_ref_t::root() const 1000{ 1001 return node_ref_t(*this); 1002} 1003 1004node_inst_t soc_ref_t::root_inst() const 1005{ 1006 return node_inst_t(*this); 1007} 1008 1009void soc_ref_t::reset() 1010{ 1011 m_soc = 0; 1012} 1013 1014/** 1015 * node_ref_t */ 1016 1017node_ref_t::node_ref_t(soc_ref_t soc):m_soc(soc) 1018{ 1019} 1020 1021node_ref_t::node_ref_t(soc_ref_t soc, const std::vector< soc_id_t >& path) 1022 :m_soc(soc), m_path(path) 1023{ 1024} 1025 1026node_ref_t::node_ref_t() 1027{ 1028} 1029 1030bool node_ref_t::valid() const 1031{ 1032 return (m_soc.valid() && is_root()) || get() != 0; 1033} 1034 1035bool node_ref_t::is_root() const 1036{ 1037 return m_path.empty(); 1038} 1039 1040void node_ref_t::reset() 1041{ 1042 m_soc.reset(); 1043} 1044 1045namespace 1046{ 1047 1048std::vector< node_t > *get_children(node_ref_t node) 1049{ 1050 if(node.is_root()) 1051 return node.soc().valid() ? &node.soc().get()->node : 0; 1052 node_t *n = node.get(); 1053 return n == 0 ? 0 : &n->node; 1054} 1055 1056node_t *get_child(std::vector< node_t > *nodes, soc_id_t id) 1057{ 1058 if(nodes == 0) 1059 return 0; 1060 for(size_t i = 0; i < nodes->size(); i++) 1061 if((*nodes)[i].id == id) 1062 return &(*nodes)[i]; 1063 return 0; 1064} 1065 1066node_t *get_child(std::vector< node_t > *nodes, const std::string& name) 1067{ 1068 if(nodes == 0) 1069 return 0; 1070 for(size_t i = 0; i < nodes->size(); i++) 1071 if((*nodes)[i].name == name) 1072 return &(*nodes)[i]; 1073 return 0; 1074} 1075 1076} 1077 1078/* NOTE: valid() is implemented using get() != 0, so don't use it in get() ! */ 1079node_t *node_ref_t::get() const 1080{ 1081 if(!soc().valid()) 1082 return 0; 1083 /* we could do it recursively but it would make plenty of copies */ 1084 node_t *n = 0; 1085 std::vector< node_t > *nodes = &soc().get()->node; 1086 for(size_t i = 0; i < m_path.size(); i++) 1087 { 1088 n = get_child(nodes, m_path[i]); 1089 if(n == 0) 1090 return 0; 1091 nodes = &n->node; 1092 } 1093 return n; 1094} 1095 1096soc_ref_t node_ref_t::soc() const 1097{ 1098 return m_soc; 1099} 1100 1101node_ref_t node_ref_t::parent(unsigned level) const 1102{ 1103 if(level > depth()) 1104 return node_ref_t(); 1105 std::vector< soc_id_t > path = m_path; 1106 path.resize(depth() - level); 1107 return node_ref_t(m_soc, path); 1108} 1109 1110unsigned node_ref_t::depth() const 1111{ 1112 return m_path.size(); 1113} 1114 1115register_ref_t node_ref_t::reg() const 1116{ 1117 node_t *n = get(); 1118 if(n == 0) 1119 return register_ref_t(); 1120 if(n->register_.empty()) 1121 return parent().reg(); 1122 else 1123 return register_ref_t(*this); 1124} 1125 1126register_ref_t node_ref_t::create_reg(size_t width) const 1127{ 1128 node_t *n = get(); 1129 if(n == 0) 1130 return register_ref_t(); 1131 if(!n->register_.empty()) 1132 return register_ref_t(); 1133 n->register_.resize(1); 1134 n->register_[0].width = width; 1135 return register_ref_t(*this); 1136} 1137 1138node_ref_t node_ref_t::child(const std::string& name) const 1139{ 1140 /* check the node exists */ 1141 node_t *n = get_child(get_children(*this), name); 1142 if(n == 0) 1143 return node_ref_t(); 1144 std::vector< soc_id_t > path = m_path; 1145 path.push_back(n->id); 1146 return node_ref_t(m_soc, path); 1147} 1148 1149std::vector< node_ref_t > node_ref_t::children() const 1150{ 1151 std::vector< node_ref_t > nodes; 1152 std::vector< node_t > *children = get_children(*this); 1153 if(children == 0) 1154 return nodes; 1155 for(size_t i = 0; i < children->size(); i++) 1156 { 1157 std::vector< soc_id_t > path = m_path; 1158 path.push_back((*children)[i].id); 1159 nodes.push_back(node_ref_t(m_soc, path)); 1160 } 1161 return nodes; 1162} 1163 1164std::vector< std::string > node_ref_t::path() const 1165{ 1166 std::vector< std::string > path; 1167 if(!soc().valid()) 1168 return path; 1169 /* we could do it recursively but this is more efficient */ 1170 node_t *n = 0; 1171 std::vector< node_t > *nodes = &soc().get()->node; 1172 for(size_t i = 0; i < m_path.size(); i++) 1173 { 1174 n = get_child(nodes, m_path[i]); 1175 if(n == 0) 1176 { 1177 path.clear(); 1178 return path; 1179 } 1180 path.push_back(n->name); 1181 nodes = &n->node; 1182 } 1183 return path; 1184} 1185 1186std::string node_ref_t::name() const 1187{ 1188 node_t *n = get(); 1189 return n == 0 ? "" : n->name; 1190} 1191 1192bool node_ref_t::operator==(const node_ref_t& ref) const 1193{ 1194 return m_soc == ref.m_soc && m_path == ref.m_path; 1195} 1196 1197void node_ref_t::remove() 1198{ 1199 if(is_root()) 1200 { 1201 soc_t *s = soc().get(); 1202 if(s) 1203 s->node.clear(); 1204 } 1205 else 1206 { 1207 std::vector< node_t > *list = get_children(parent()); 1208 if(list == 0) 1209 return; 1210 for(size_t i = 0; i < list->size(); i++) 1211 if((*list)[i].id == m_path.back()) 1212 { 1213 list->erase(list->begin() + i); 1214 return; 1215 } 1216 } 1217} 1218 1219node_ref_t node_ref_t::create() const 1220{ 1221 std::vector< node_t > *list = get_children(*this); 1222 if(list == 0) 1223 return node_ref_t(); 1224 node_t n; 1225 n.id = gen_fresh_id(*list); 1226 list->push_back(n); 1227 std::vector< soc_id_t > path = m_path; 1228 path.push_back(n.id); 1229 return node_ref_t(soc(), path); 1230} 1231 1232/** 1233 * register_ref_t 1234 */ 1235 1236register_ref_t::register_ref_t(node_ref_t node) 1237 :m_node(node) 1238{ 1239} 1240 1241register_ref_t::register_ref_t() 1242{ 1243} 1244 1245bool register_ref_t::valid() const 1246{ 1247 return get() != 0; 1248} 1249 1250void register_ref_t::reset() 1251{ 1252 m_node.reset(); 1253} 1254 1255register_t *register_ref_t::get() const 1256{ 1257 node_t *n = m_node.get(); 1258 if(n == 0 || n->register_.empty()) 1259 return 0; 1260 return &n->register_[0]; 1261} 1262 1263node_ref_t register_ref_t::node() const 1264{ 1265 return m_node; 1266} 1267 1268std::vector< field_ref_t > register_ref_t::fields() const 1269{ 1270 std::vector< field_ref_t > fields; 1271 register_t *r = get(); 1272 if(r == 0) 1273 return fields; 1274 for(size_t i = 0; i < r->field.size(); i++) 1275 fields.push_back(field_ref_t(*this, r->field[i].id)); 1276 return fields; 1277} 1278 1279std::vector< variant_ref_t > register_ref_t::variants() const 1280{ 1281 std::vector< variant_ref_t > variants; 1282 register_t *r = get(); 1283 if(r == 0) 1284 return variants; 1285 for(size_t i = 0; i < r->variant.size(); i++) 1286 variants.push_back(variant_ref_t(*this, r->variant[i].id)); 1287 return variants; 1288} 1289 1290field_ref_t register_ref_t::field(const std::string& name) const 1291{ 1292 register_t *r = get(); 1293 if(r == 0) 1294 return field_ref_t(); 1295 for(size_t i = 0; i < r->field.size(); i++) 1296 if(r->field[i].name == name) 1297 return field_ref_t(*this, r->field[i].id); 1298 return field_ref_t(); 1299} 1300 1301variant_ref_t register_ref_t::variant(const std::string& type) const 1302{ 1303 register_t *r = get(); 1304 if(r == 0) 1305 return variant_ref_t(); 1306 for(size_t i = 0; i < r->variant.size(); i++) 1307 if(r->variant[i].type == type) 1308 return variant_ref_t(*this, r->variant[i].id); 1309 return variant_ref_t(); 1310} 1311 1312void register_ref_t::remove() 1313{ 1314 node_t *n = node().get(); 1315 if(n) 1316 n->register_.clear(); 1317} 1318 1319field_ref_t register_ref_t::create_field() const 1320{ 1321 register_t *r = get(); 1322 if(r == 0) 1323 return field_ref_t(); 1324 field_t f; 1325 f.id = gen_fresh_id(r->field); 1326 r->field.push_back(f); 1327 return field_ref_t(*this, f.id); 1328} 1329 1330variant_ref_t register_ref_t::create_variant() const 1331{ 1332 register_t *r = get(); 1333 if(r == 0) 1334 return variant_ref_t(); 1335 variant_t v; 1336 v.id = gen_fresh_id(r->variant); 1337 r->variant.push_back(v); 1338 return variant_ref_t(*this, v.id); 1339} 1340 1341/** 1342 * field_ref_t 1343 */ 1344 1345field_ref_t::field_ref_t(register_ref_t reg, soc_id_t id) 1346 :m_reg(reg), m_id(id) 1347{ 1348} 1349 1350field_ref_t::field_ref_t() 1351{ 1352} 1353 1354bool field_ref_t::valid() const 1355{ 1356 return get() != 0; 1357} 1358 1359void field_ref_t::reset() 1360{ 1361 m_reg.reset(); 1362} 1363 1364field_t *field_ref_t::get() const 1365{ 1366 register_t *reg = m_reg.get(); 1367 if(reg == 0) 1368 return 0; 1369 for(size_t i = 0; i < reg->field.size(); i++) 1370 if(reg->field[i].id == m_id) 1371 return &reg->field[i]; 1372 return 0; 1373} 1374 1375std::vector< enum_ref_t > field_ref_t::enums() const 1376{ 1377 std::vector< enum_ref_t > enums; 1378 field_t *f = get(); 1379 if(f == 0) 1380 return enums; 1381 for(size_t i = 0; i < f->enum_.size(); i++) 1382 enums.push_back(enum_ref_t(*this, f->enum_[i].id)); 1383 return enums; 1384} 1385 1386register_ref_t field_ref_t::reg() const 1387{ 1388 return m_reg; 1389} 1390 1391enum_ref_t field_ref_t::create_enum() const 1392{ 1393 field_t *f = get(); 1394 if(f == 0) 1395 return enum_ref_t(); 1396 enum_t e; 1397 e.id = gen_fresh_id(f->enum_); 1398 f->enum_.push_back(e); 1399 return enum_ref_t(*this, e.id); 1400} 1401 1402/** 1403 * enum_ref_t 1404 */ 1405 1406enum_ref_t::enum_ref_t(field_ref_t field, soc_id_t id) 1407 :m_field(field), m_id(id) 1408{ 1409} 1410 1411enum_ref_t::enum_ref_t() 1412{ 1413} 1414 1415bool enum_ref_t::valid() const 1416{ 1417 return get() != 0; 1418} 1419 1420void enum_ref_t::reset() 1421{ 1422 m_field.reset(); 1423} 1424 1425enum_t *enum_ref_t::get() const 1426{ 1427 field_t *field = m_field.get(); 1428 if(field == 0) 1429 return 0; 1430 for(size_t i = 0; i < field->enum_.size(); i++) 1431 if(field->enum_[i].id == m_id) 1432 return &field->enum_[i]; 1433 return 0; 1434} 1435 1436field_ref_t enum_ref_t::field() const 1437{ 1438 return m_field; 1439} 1440 1441/** 1442 * variant_ref_t 1443 */ 1444 1445variant_ref_t::variant_ref_t(register_ref_t reg, soc_id_t id) 1446 :m_reg(reg), m_id(id) 1447{ 1448} 1449 1450variant_ref_t::variant_ref_t() 1451{ 1452} 1453 1454bool variant_ref_t::valid() const 1455{ 1456 return get() != 0; 1457} 1458 1459void variant_ref_t::reset() 1460{ 1461 m_reg.reset(); 1462} 1463 1464variant_t *variant_ref_t::get() const 1465{ 1466 register_t *reg = m_reg.get(); 1467 if(reg == 0) 1468 return 0; 1469 for(size_t i = 0; i < reg->variant.size(); i++) 1470 if(reg->variant[i].id == m_id) 1471 return &reg->variant[i]; 1472 return 0; 1473} 1474 1475register_ref_t variant_ref_t::reg() const 1476{ 1477 return m_reg; 1478} 1479 1480std::string variant_ref_t::type() const 1481{ 1482 variant_t *v = get(); 1483 return v ? v->type : std::string(); 1484} 1485 1486soc_word_t variant_ref_t::offset() const 1487{ 1488 variant_t *v = get(); 1489 return v ? v->offset : 0; 1490} 1491 1492/** 1493 * node_inst_t 1494 */ 1495 1496namespace 1497{ 1498 1499const size_t INST_NO_INDEX = std::numeric_limits<std::size_t>::max(); 1500 1501bool get_inst_addr(range_t& range, size_t index, soc_addr_t& addr) 1502{ 1503 if(index < range.first || index >= range.first + range.size()) 1504 return false; 1505 switch(range.type) 1506 { 1507 case range_t::STRIDE: 1508 addr += range.base + (index - range.first) * range.stride; 1509 return true; 1510 case range_t::FORMULA: 1511 { 1512 soc_word_t res; 1513 std::map< std::string, soc_word_t > vars; 1514 vars[range.variable] = index; 1515 error_context_t ctx; 1516 if(!evaluate_formula(range.formula, vars, res, "", ctx)) 1517 return false; 1518 addr += res; 1519 return true; 1520 } 1521 case range_t::LIST: 1522 addr += range.list[index - range.first]; 1523 return true; 1524 default: 1525 return false; 1526 } 1527} 1528 1529bool get_inst_addr(instance_t *inst, size_t index, soc_addr_t& addr) 1530{ 1531 if(inst == 0) 1532 return false; 1533 switch(inst->type) 1534 { 1535 case instance_t::SINGLE: 1536 if(index != INST_NO_INDEX) 1537 return false; 1538 addr += inst->addr; 1539 return true; 1540 case instance_t::RANGE: 1541 if(index == INST_NO_INDEX) 1542 return false; 1543 return get_inst_addr(inst->range, index, addr); 1544 default: 1545 return false; 1546 } 1547} 1548 1549} 1550 1551node_inst_t::node_inst_t(soc_ref_t soc) 1552 :m_node(soc.root()) 1553{ 1554} 1555 1556node_inst_t::node_inst_t(node_ref_t node, const std::vector< soc_id_t >& ids, 1557 const std::vector< size_t >& indexes) 1558 :m_node(node), m_id_path(ids), m_index_path(indexes) 1559{ 1560} 1561 1562node_inst_t::node_inst_t() 1563{ 1564} 1565 1566bool node_inst_t::valid() const 1567{ 1568 return (is_root() && node().valid()) || get() != 0; 1569} 1570 1571void node_inst_t::reset() 1572{ 1573 m_node.reset(); 1574} 1575 1576node_ref_t node_inst_t::node() const 1577{ 1578 return m_node; 1579} 1580 1581soc_ref_t node_inst_t::soc() const 1582{ 1583 return m_node.soc(); 1584} 1585 1586bool node_inst_t::is_root() const 1587{ 1588 return m_node.is_root(); 1589} 1590 1591node_inst_t node_inst_t::parent(unsigned level) const 1592{ 1593 if(level > depth()) 1594 return node_inst_t(); 1595 std::vector< soc_id_t > ids = m_id_path; 1596 std::vector< size_t > indexes = m_index_path; 1597 ids.resize(depth() - level); 1598 indexes.resize(depth() - level); 1599 return node_inst_t(m_node.parent(level), ids, indexes); 1600} 1601 1602unsigned node_inst_t::depth() const 1603{ 1604 return m_id_path.size(); 1605} 1606 1607instance_t *node_inst_t::get() const 1608{ 1609 node_t *n = m_node.get(); 1610 if(n == 0) 1611 return 0; 1612 for(size_t i = 0; i < n->instance.size(); i++) 1613 if(n->instance[i].id == m_id_path.back()) 1614 return &n->instance[i]; 1615 return 0; 1616} 1617 1618soc_addr_t node_inst_t::addr() const 1619{ 1620 if(!valid() || is_root()) 1621 return 0; 1622 soc_addr_t addr = parent().addr(); 1623 if(!get_inst_addr(get(), m_index_path.back(), addr)) 1624 return 0; 1625 return addr; 1626} 1627 1628node_inst_t node_inst_t::child(const std::string& name) const 1629{ 1630 return child(name, INST_NO_INDEX); 1631} 1632 1633node_inst_t node_inst_t::child(const std::string& name, size_t index) const 1634{ 1635 std::vector< node_t > *nodes = get_children(m_node); 1636 if(nodes == 0 || is_nochild()) 1637 return node_inst_t(); 1638 node_ref_t child_node = m_node; 1639 for(size_t i = 0; i < nodes->size(); i++) 1640 { 1641 node_t& node = (*nodes)[i]; 1642 child_node.m_path.push_back(node.id); 1643 for(size_t j = 0; j < node.instance.size(); j++) 1644 { 1645 if(node.instance[j].name != name) 1646 continue; 1647 std::vector< soc_id_t > ids = m_id_path; 1648 std::vector< size_t > indexes = m_index_path; 1649 ids.push_back(node.instance[j].id); 1650 indexes.push_back(index); 1651 return node_inst_t(child_node, ids, indexes); 1652 } 1653 child_node.m_path.pop_back(); 1654 } 1655 return node_inst_t(); 1656} 1657 1658std::vector< node_inst_t > node_inst_t::children() const 1659{ 1660 std::vector< node_inst_t > list; 1661 std::vector< node_t > *nodes = get_children(m_node); 1662 std::vector< soc_id_t > n_path = m_id_path; 1663 std::vector< size_t > i_path = m_index_path; 1664 if(nodes == 0 || is_nochild()) 1665 return list; 1666 node_ref_t child_node = m_node; 1667 for(size_t i = 0; i < nodes->size(); i++) 1668 { 1669 node_t& node = (*nodes)[i]; 1670 child_node.m_path.push_back(node.id); 1671 for(size_t j = 0; j < node.instance.size(); j++) 1672 { 1673 instance_t& inst = node.instance[j]; 1674 n_path.push_back(inst.id); 1675 switch(inst.type) 1676 { 1677 case instance_t::FLOATING: 1678 case instance_t::SINGLE: 1679 i_path.push_back(INST_NO_INDEX); 1680 list.push_back(node_inst_t(child_node, n_path, i_path)); 1681 i_path.pop_back(); 1682 break; 1683 case instance_t::RANGE: 1684 for(size_t i = 0; i < inst.range.size(); i++) 1685 { 1686 i_path.push_back(inst.range.first + i); 1687 list.push_back(node_inst_t(child_node, n_path, i_path)); 1688 i_path.pop_back(); 1689 } 1690 break; 1691 default: 1692 break; 1693 } 1694 n_path.pop_back(); 1695 } 1696 child_node.m_path.pop_back(); 1697 } 1698 return list; 1699} 1700 1701bool node_inst_t::is_nochild() const 1702{ 1703 instance_t *inst = get(); 1704 return inst == 0 ? false : inst->nochild; 1705} 1706 1707std::string node_inst_t::name() const 1708{ 1709 instance_t *inst = get(); 1710 return inst == 0 ? "" : inst->name; 1711} 1712 1713bool node_inst_t:: is_indexed() const 1714{ 1715 return !m_index_path.empty() && m_index_path.back() != INST_NO_INDEX; 1716} 1717 1718size_t node_inst_t::index() const 1719{ 1720 return m_index_path.empty() ? INST_NO_INDEX : m_index_path.back(); 1721} 1722 1723/** WARNING we need to call xmlInitParser() to init libxml2 but it needs to 1724 * called from the main thread, which is a super strong requirement, so do it 1725 * using a static constructor */ 1726namespace 1727{ 1728class xml_parser_init 1729{ 1730public: 1731 xml_parser_init() 1732 { 1733 xmlInitParser(); 1734 } 1735}; 1736 1737xml_parser_init __xml_parser_init; 1738} 1739 1740} // soc_desc_v1 1741