A modern, network-enabled music player platform built on Rockbox technology. rockboxd.tsiry-sandratraina.com
rust deno navidrome airplay libadwaita zig mpris snapcast mpd rockbox audio subsonic
2

Configure Feed

Select the types of activity you want to include in your feed.

rockboxd / utils / regtools / tester_v1.cpp
12 kB 364 lines
1/*************************************************************************** 2 * __________ __ ___. 3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 * \/ \/ \/ \/ \/ 8 * 9 * Copyright (C) 2012 by Amaury Pouly 10 * 11 * This program is free software; you can redistribute it and/or 12 * modify it under the terms of the GNU General Public License 13 * as published by the Free Software Foundation; either version 2 14 * of the License, or (at your option) any later version. 15 * 16 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 17 * KIND, either express or implied. 18 * 19 ****************************************************************************/ 20#include "soc_desc_v1.hpp" 21#include <stdio.h> 22#include <stdlib.h> 23#include <map> 24#include <cstring> 25 26using namespace soc_desc_v1; 27 28template< typename T > 29bool build_map(const char *type, const std::vector< T >& vec, 30 std::map< std::string, size_t >& map) 31{ 32 for(size_t i = 0; i < vec.size(); i++) 33 { 34 if(map.find(vec[i].name) != map.end()) 35 { 36 printf("soc has duplicate %s '%s'\n", type, vec[i].name.c_str()); 37 return false; 38 } 39 map[vec[i].name] = i; 40 } 41 return true; 42} 43 44template< typename T > 45bool build_map(const char *type, const std::vector< T >& a, const std::vector< T >& b, 46 std::vector< std::pair< size_t, size_t > >& m) 47{ 48 std::map< std::string, size_t > ma, mb; 49 if(!build_map(type, a, ma) || !build_map(type, b, mb)) 50 return false; 51 std::map< std::string, size_t >::iterator it; 52 for(it = ma.begin(); it != ma.end(); ++it) 53 { 54 if(mb.find(it->first) == mb.end()) 55 { 56 printf("%s '%s' exists in only one file\n", type, it->first.c_str()); 57 return false; 58 } 59 m.push_back(std::make_pair(it->second, mb[it->first])); 60 } 61 for(it = mb.begin(); it != mb.end(); ++it) 62 { 63 if(ma.find(it->first) == ma.end()) 64 { 65 printf("%s '%s' exists in only one file\n", type, it->first.c_str()); 66 return false; 67 } 68 } 69 return true; 70} 71 72bool compare_value(const soc_t& soc, const soc_dev_t& dev, const soc_reg_t& reg, 73 const soc_reg_field_t& field, const soc_reg_field_value_t& a, const soc_reg_field_value_t& b) 74{ 75 if(a.value != b.value) 76 { 77 printf("register field value '%s.%s.%s.%s.%s' have different values\n", soc.name.c_str(), 78 dev.name.c_str(), reg.name.c_str(), field.name.c_str(), a.name.c_str()); 79 return false; 80 } 81 if(a.desc != b.desc) 82 { 83 printf("register field value '%s.%s.%s.%s.%s' have different descriptions\n", soc.name.c_str(), 84 dev.name.c_str(), reg.name.c_str(), field.name.c_str(), a.name.c_str()); 85 return false; 86 } 87 return true; 88} 89 90bool compare_field(const soc_t& soc, const soc_dev_t& dev, const soc_reg_t& reg, 91 const soc_reg_field_t& a, const soc_reg_field_t& b) 92{ 93 if(a.first_bit != b.first_bit || a.last_bit != b.last_bit) 94 { 95 printf("register address '%s.%s.%s.%s' have different bit ranges\n", soc.name.c_str(), 96 dev.name.c_str(), reg.name.c_str(), a.name.c_str()); 97 return false; 98 } 99 if(a.desc != b.desc) 100 { 101 printf("register address '%s.%s.%s.%s' have different descriptions\n", soc.name.c_str(), 102 dev.name.c_str(), reg.name.c_str(), a.name.c_str()); 103 return false; 104 } 105 /* values */ 106 std::vector< std::pair< size_t, size_t > > map; 107 if(!build_map("field value", a.value, b.value, map)) 108 return false; 109 for(size_t i = 0; i < map.size(); i++) 110 if(!compare_value(soc, dev, reg, a, a.value[map[i].first], b.value[map[i].second])) 111 return false; 112 return true; 113} 114 115bool compare_reg_addr(const soc_t& soc, const soc_dev_t& dev, const soc_reg_t& reg, 116 const soc_reg_addr_t& a, const soc_reg_addr_t& b) 117{ 118 if(a.addr != b.addr) 119 { 120 printf("register address '%s.%s.%s.%s' have different values\n", soc.name.c_str(), 121 dev.name.c_str(), reg.name.c_str(), a.name.c_str()); 122 return false; 123 } 124 else 125 return true; 126} 127 128bool compare_reg(const soc_t& soc, const soc_dev_t& dev, const soc_reg_t& a, 129 const soc_reg_t& b) 130{ 131 if(a.desc != b.desc) 132 { 133 printf("register '%s.%s.%s' have different descriptions\n", soc.name.c_str(), 134 dev.name.c_str(), a.name.c_str()); 135 return false; 136 } 137 if(a.flags != b.flags) 138 { 139 printf("device '%s.%s.%s' have different flags\n", soc.name.c_str(), 140 dev.name.c_str(), a.name.c_str()); 141 return false; 142 } 143 if(a.formula.type != b.formula.type) 144 { 145 printf("device '%s.%s.%s' have different formula types\n", soc.name.c_str(), 146 dev.name.c_str(), a.name.c_str()); 147 return false; 148 } 149 if(a.formula.string != b.formula.string) 150 { 151 printf("device '%s.%s.%s' have different formula string\n", soc.name.c_str(), 152 dev.name.c_str(), a.name.c_str()); 153 return false; 154 } 155 /* addresses */ 156 std::vector< std::pair< size_t, size_t > > map; 157 if(!build_map("register address", a.addr, b.addr, map)) 158 return false; 159 for(size_t i = 0; i < map.size(); i++) 160 if(!compare_reg_addr(soc, dev, a, a.addr[map[i].first], b.addr[map[i].second])) 161 return false; 162 /* field */ 163 map.clear(); 164 if(!build_map("field", a.field, b.field, map)) 165 return false; 166 for(size_t i = 0; i < map.size(); i++) 167 if(!compare_field(soc, dev, a, a.field[map[i].first], b.field[map[i].second])) 168 return false; 169 return true; 170} 171 172bool compare_dev_addr(const soc_t& soc, const soc_dev_t& dev, const soc_dev_addr_t& a, 173 const soc_dev_addr_t& b) 174{ 175 if(a.addr != b.addr) 176 { 177 printf("device address '%s.%s.%s' have different values\n", soc.name.c_str(), 178 dev.name.c_str(), a.name.c_str()); 179 return false; 180 } 181 else 182 return true; 183} 184 185bool compare_dev(const soc_t& soc, const soc_dev_t& a, const soc_dev_t& b) 186{ 187 if(a.long_name != b.long_name) 188 { 189 printf("device '%s.%s' have different long names\n", soc.name.c_str(), 190 a.name.c_str()); 191 return false; 192 } 193 if(a.desc != b.desc) 194 { 195 printf("device '%s.%s' have different descriptions\n", soc.name.c_str(), 196 a.name.c_str()); 197 return false; 198 } 199 if(a.version != b.version) 200 { 201 printf("device '%s.%s' have different versions\n", soc.name.c_str(), 202 a.name.c_str()); 203 return false; 204 } 205 /* addresses */ 206 std::vector< std::pair< size_t, size_t > > map; 207 if(!build_map("device address", a.addr, b.addr, map)) 208 return false; 209 for(size_t i = 0; i < map.size(); i++) 210 if(!compare_dev_addr(soc, a, a.addr[map[i].first], b.addr[map[i].second])) 211 return false; 212 /* reg */ 213 map.clear(); 214 if(!build_map("register", a.reg, b.reg, map)) 215 return false; 216 for(size_t i = 0; i < map.size(); i++) 217 if(!compare_reg(soc, a, a.reg[map[i].first], b.reg[map[i].second])) 218 return false; 219 return true; 220} 221 222bool compare_soc(const soc_t& a, const soc_t& b) 223{ 224 if(a.name != b.name) 225 { 226 return printf("soc have different names\n"); 227 return false; 228 } 229 if(a.desc != b.desc) 230 { 231 printf("soc '%s' have different descriptions\n", a.name.c_str()); 232 return false; 233 } 234 std::vector< std::pair< size_t, size_t > > map; 235 if(!build_map("device", a.dev, b.dev, map)) 236 return false; 237 for(size_t i = 0; i< map.size(); i++) 238 if(!compare_dev(a, a.dev[map[i].first], b.dev[map[i].second])) 239 return false; 240 return true; 241} 242 243int do_compare(int argc, char **argv) 244{ 245 if(argc != 2) 246 return printf("compare mode expects two arguments\n"); 247 soc_t soc[2]; 248 if(!parse_xml(argv[0], soc[0])) 249 return printf("cannot read file '%s'\n", argv[0]); 250 if(!parse_xml(argv[1], soc[1])) 251 return printf("cannot read file '%s'\n", argv[1]); 252 if(compare_soc(soc[0], soc[1])) 253 printf("Files are identical.\n"); 254 return 0; 255} 256 257int do_write(int argc, char **argv) 258{ 259 if(argc != 2) 260 return printf("write mode expects two arguments\n"); 261 soc_t soc; 262 if(!parse_xml(argv[0], soc)) 263 return printf("cannot read file '%s'\n", argv[0]); 264 if(!produce_xml(argv[1], soc)) 265 return printf("cannot write file '%s'\n", argv[1]); 266 return 0; 267} 268 269int do_check(int argc, char **argv) 270{ 271 for(int i = 0; i < argc; i++) 272 { 273 soc_t soc; 274 if(!parse_xml(argv[i], soc)) 275 { 276 printf("cannot read file '%s'\n", argv[i]); 277 continue; 278 } 279 printf("[%s]\n", argv[i]); 280 std::vector< soc_error_t > errs = soc.errors(true); 281 for(size_t i = 0; i < errs.size(); i++) 282 { 283 const soc_error_t& e = errs[i]; 284 switch(e.level) 285 { 286 case SOC_ERROR_WARNING: printf("[WARN ] "); break; 287 case SOC_ERROR_FATAL: printf("[FATAL] "); break; 288 default: printf("[ UNK ] "); break; 289 } 290 printf("%s: %s\n", e.location.c_str(), e.message.c_str()); 291 } 292 } 293 return 0; 294} 295 296int do_eval(int argc, char **argv) 297{ 298 std::map< std::string, soc_word_t > map; 299 for(int i = 0; i < argc; i++) 300 { 301 std::string error; 302 std::string formula(argv[i]); 303 soc_word_t result; 304 if(strcmp(argv[i], "--var") == 0) 305 { 306 if(i + 1 >= argc) 307 break; 308 i++; 309 std::string str(argv[i]); 310 size_t pos = str.find('='); 311 if(pos == std::string::npos) 312 { 313 printf("invalid variable string '%s'\n", str.c_str()); 314 continue; 315 } 316 std::string name = str.substr(0, pos); 317 std::string val = str.substr(pos + 1); 318 char *end; 319 soc_word_t v = strtoul(val.c_str(), &end, 0); 320 if(*end) 321 { 322 printf("invalid variable string '%s'\n", str.c_str()); 323 continue; 324 } 325 printf("%s = %#lx\n", name.c_str(), (unsigned long)v); 326 map[name] = v; 327 continue; 328 } 329 if(!evaluate_formula(formula, map, result, error)) 330 printf("error: %s\n", error.c_str()); 331 else 332 printf("result: %lu (%#lx)\n", (unsigned long)result, (unsigned long)result); 333 } 334 return 0; 335} 336 337void usage() 338{ 339 printf("usage: tester <mode> [options]\n"); 340 printf("modes:\n"); 341 printf(" compare <desc file> <desc file>\n"); 342 printf(" write <read file> <write file>\n"); 343 printf(" check <files...>\n"); 344 printf(" eval [<formula>|--var <name>=<val>]...\n"); 345 exit(1); 346} 347 348int main(int argc, char **argv) 349{ 350 if(argc < 2) 351 usage(); 352 std::string mode = argv[1]; 353 if(mode == "compare") 354 return do_compare(argc - 2, argv + 2); 355 else if(mode == "write") 356 return do_write(argc - 2, argv + 2); 357 else if(mode == "check") 358 return do_check(argc - 2, argv + 2); 359 else if(mode == "eval") 360 return do_eval(argc - 2, argv + 2); 361 else 362 usage(); 363 return 0; 364}