1a9b44344SZane Shelley #include <analyzer/ras-data/ras-data-parser.hpp> 2a9b44344SZane Shelley #include <util/data_file.hpp> 3a9b44344SZane Shelley #include <util/trace.hpp> 4a9b44344SZane Shelley 5a9b44344SZane Shelley #include <filesystem> 6a9b44344SZane Shelley #include <fstream> 7a9b44344SZane Shelley #include <string> 8a9b44344SZane Shelley 9a9b44344SZane Shelley namespace fs = std::filesystem; 10a9b44344SZane Shelley 11a9b44344SZane Shelley namespace analyzer 12a9b44344SZane Shelley { 13a9b44344SZane Shelley 14a9b44344SZane Shelley //------------------------------------------------------------------------------ 15a9b44344SZane Shelley 16a9b44344SZane Shelley std::shared_ptr<Resolution> 177698b304SZane Shelley RasDataParser::getResolution(const libhei::Signature& i_signature) 18a9b44344SZane Shelley { 197698b304SZane Shelley const auto data = iv_dataFiles.at(i_signature.getChip().getType()); 207698b304SZane Shelley 217698b304SZane Shelley const auto action = parseSignature(data, i_signature); 227698b304SZane Shelley 237698b304SZane Shelley return parseAction(data, action); 24a9b44344SZane Shelley } 25a9b44344SZane Shelley 26a9b44344SZane Shelley //------------------------------------------------------------------------------ 27a9b44344SZane Shelley 28a9b44344SZane Shelley void RasDataParser::initDataFiles() 29a9b44344SZane Shelley { 30a9b44344SZane Shelley iv_dataFiles.clear(); // initially empty 31a9b44344SZane Shelley 32a9b44344SZane Shelley // Get the RAS data schema files from the package `schema` subdirectory. 33a9b44344SZane Shelley fs::path schemaDir{PACKAGE_DIR "schema"}; 34ee54c99fSZane Shelley auto schemaRegex = R"(ras-data-schema-v[0-9]{2}\.json)"; 35ee54c99fSZane Shelley std::vector<fs::path> schemaPaths; 36ee54c99fSZane Shelley util::findFiles(schemaDir, schemaRegex, schemaPaths); 37a9b44344SZane Shelley 38ee54c99fSZane Shelley // Parse each of the schema files. 39ee54c99fSZane Shelley std::map<unsigned int, nlohmann::json> schemaFiles; 40ee54c99fSZane Shelley for (const auto& path : schemaPaths) 41ee54c99fSZane Shelley { 42ee54c99fSZane Shelley // Trace each data file for debug. 43ee54c99fSZane Shelley trace::inf("File found: path=%s", path.string().c_str()); 44a9b44344SZane Shelley 45a9b44344SZane Shelley // Open the file. 46ee54c99fSZane Shelley std::ifstream file{path}; 47ee54c99fSZane Shelley assert(file.good()); // The file must be readable. 48a9b44344SZane Shelley 49a9b44344SZane Shelley // Parse the JSON. 50ee54c99fSZane Shelley auto schema = nlohmann::json::parse(file); 51a9b44344SZane Shelley 52ee54c99fSZane Shelley // Get the schema version. 53ee54c99fSZane Shelley auto version = schema.at("version").get<unsigned int>(); 54ee54c99fSZane Shelley 55ee54c99fSZane Shelley // Keep track of the schemas. 56ee54c99fSZane Shelley auto ret = schemaFiles.emplace(version, schema); 57ee54c99fSZane Shelley assert(ret.second); // Should not have duplicate entries 58ee54c99fSZane Shelley } 59ee54c99fSZane Shelley 60ee54c99fSZane Shelley // Get the RAS data files from the package `data` subdirectory. 61a9b44344SZane Shelley fs::path dataDir{PACKAGE_DIR "ras-data"}; 62a9b44344SZane Shelley std::vector<fs::path> dataPaths; 63a9b44344SZane Shelley util::findFiles(dataDir, R"(.*\.json)", dataPaths); 64a9b44344SZane Shelley 65a9b44344SZane Shelley // Parse each of the data files. 66a9b44344SZane Shelley for (const auto& path : dataPaths) 67a9b44344SZane Shelley { 68a9b44344SZane Shelley // Trace each data file for debug. 69a9b44344SZane Shelley trace::inf("File found: path=%s", path.string().c_str()); 70a9b44344SZane Shelley 71a9b44344SZane Shelley // Open the file. 72a9b44344SZane Shelley std::ifstream file{path}; 73a9b44344SZane Shelley assert(file.good()); // The file must be readable. 74a9b44344SZane Shelley 75a9b44344SZane Shelley // Parse the JSON. 76a9b44344SZane Shelley const auto data = nlohmann::json::parse(file); 77a9b44344SZane Shelley 78ee54c99fSZane Shelley // Get the data version. 79ee54c99fSZane Shelley auto version = data.at("version").get<unsigned int>(); 80ee54c99fSZane Shelley 81ee54c99fSZane Shelley // Get the schema for this file. 82ee54c99fSZane Shelley auto schema = schemaFiles.at(version); 83ee54c99fSZane Shelley 84a9b44344SZane Shelley // Validate the data against the schema. 85a9b44344SZane Shelley assert(util::validateJson(schema, data)); 86a9b44344SZane Shelley 87a9b44344SZane Shelley // Get the chip model/EC level from the data. The value is currently 88a9b44344SZane Shelley // stored as a string representation of the hex value. So it will have 89a9b44344SZane Shelley // to be converted to an integer. 90a9b44344SZane Shelley libhei::ChipType_t chipType = 91a9b44344SZane Shelley std::stoul(data.at("model_ec").get<std::string>(), 0, 16); 92a9b44344SZane Shelley 93a9b44344SZane Shelley // So far, so good. Add the entry. 94a9b44344SZane Shelley auto ret = iv_dataFiles.emplace(chipType, data); 95a9b44344SZane Shelley assert(ret.second); // Should not have duplicate entries 96a9b44344SZane Shelley } 97a9b44344SZane Shelley } 98a9b44344SZane Shelley 99a9b44344SZane Shelley //------------------------------------------------------------------------------ 100a9b44344SZane Shelley 1017698b304SZane Shelley std::string RasDataParser::parseSignature(const nlohmann::json& i_data, 1027698b304SZane Shelley const libhei::Signature& i_signature) 1037698b304SZane Shelley { 1047698b304SZane Shelley // Get the signature keys. All are hex (lower case) with no prefix. 1057698b304SZane Shelley char buf[5]; 1067698b304SZane Shelley sprintf(buf, "%04x", i_signature.getId()); 1077698b304SZane Shelley std::string id{buf}; 1087698b304SZane Shelley 1097698b304SZane Shelley sprintf(buf, "%02x", i_signature.getBit()); 1107698b304SZane Shelley std::string bit{buf}; 1117698b304SZane Shelley 1127698b304SZane Shelley sprintf(buf, "%02x", i_signature.getInstance()); 1137698b304SZane Shelley std::string inst{buf}; 1147698b304SZane Shelley 1157698b304SZane Shelley // Return the action. 1167698b304SZane Shelley return i_data.at("signatures").at(id).at(bit).at(inst).get<std::string>(); 1177698b304SZane Shelley } 1187698b304SZane Shelley 1197698b304SZane Shelley //------------------------------------------------------------------------------ 1207698b304SZane Shelley 1215d63cefcSZane Shelley std::tuple<callout::BusType, std::string> 1225d63cefcSZane Shelley RasDataParser::parseBus(const nlohmann::json& i_data, 1235d63cefcSZane Shelley const std::string& i_name) 1245d63cefcSZane Shelley { 1255d63cefcSZane Shelley auto bus = i_data.at("buses").at(i_name); 1265d63cefcSZane Shelley 1275d63cefcSZane Shelley // clang-format off 1285d63cefcSZane Shelley static const std::map<std::string, callout::BusType> m = 1295d63cefcSZane Shelley { 1305d63cefcSZane Shelley {"SMP_BUS", callout::BusType::SMP_BUS}, 1315d63cefcSZane Shelley {"OMI_BUS", callout::BusType::OMI_BUS}, 1325d63cefcSZane Shelley }; 1335d63cefcSZane Shelley // clang-format on 1345d63cefcSZane Shelley 1355d63cefcSZane Shelley auto busType = m.at(bus.at("type").get<std::string>()); 1365d63cefcSZane Shelley 1375d63cefcSZane Shelley std::string unitPath{}; // default empty if unit does not exist 1385d63cefcSZane Shelley if (bus.contains("unit")) 1395d63cefcSZane Shelley { 1405d63cefcSZane Shelley unitPath = bus.at("unit").get<std::string>(); 1415d63cefcSZane Shelley } 1425d63cefcSZane Shelley 1435d63cefcSZane Shelley return std::make_tuple(busType, unitPath); 1445d63cefcSZane Shelley } 1455d63cefcSZane Shelley 1465d63cefcSZane Shelley //------------------------------------------------------------------------------ 1475d63cefcSZane Shelley 1487698b304SZane Shelley std::shared_ptr<Resolution> 1497698b304SZane Shelley RasDataParser::parseAction(const nlohmann::json& i_data, 1507698b304SZane Shelley const std::string& i_action) 1517698b304SZane Shelley { 1527698b304SZane Shelley auto o_list = std::make_shared<ResolutionList>(); 1537698b304SZane Shelley 1547698b304SZane Shelley // This function will be called recursively and we want to prevent cyclic 1557698b304SZane Shelley // recursion. 1567698b304SZane Shelley static std::vector<std::string> stack; 1577698b304SZane Shelley assert(stack.end() == std::find(stack.begin(), stack.end(), i_action)); 1587698b304SZane Shelley stack.push_back(i_action); 1597698b304SZane Shelley 1607698b304SZane Shelley // Iterate the action list and apply the changes. 1617698b304SZane Shelley for (const auto& a : i_data.at("actions").at(i_action)) 1627698b304SZane Shelley { 1637698b304SZane Shelley auto type = a.at("type").get<std::string>(); 1647698b304SZane Shelley 1657698b304SZane Shelley if ("action" == type) 1667698b304SZane Shelley { 1677698b304SZane Shelley auto name = a.at("name").get<std::string>(); 1687698b304SZane Shelley 1697698b304SZane Shelley o_list->push(parseAction(i_data, name)); 1707698b304SZane Shelley } 1717698b304SZane Shelley else if ("callout_self" == type) 1727698b304SZane Shelley { 1737698b304SZane Shelley auto priority = a.at("priority").get<std::string>(); 1747698b304SZane Shelley auto guard = a.at("guard").get<bool>(); 1757698b304SZane Shelley 176e4bfb47cSZane Shelley std::string path{}; // Must be empty to callout the chip. 177e4bfb47cSZane Shelley 178e4bfb47cSZane Shelley o_list->push(std::make_shared<HardwareCalloutResolution>( 179e4bfb47cSZane Shelley path, getPriority(priority), guard)); 1807698b304SZane Shelley } 1817698b304SZane Shelley else if ("callout_unit" == type) 1827698b304SZane Shelley { 1837698b304SZane Shelley auto name = a.at("name").get<std::string>(); 1847698b304SZane Shelley auto priority = a.at("priority").get<std::string>(); 1857698b304SZane Shelley auto guard = a.at("guard").get<bool>(); 1867698b304SZane Shelley 187e4bfb47cSZane Shelley auto path = i_data.at("units").at(name).get<std::string>(); 188e4bfb47cSZane Shelley 189e4bfb47cSZane Shelley o_list->push(std::make_shared<HardwareCalloutResolution>( 190e4bfb47cSZane Shelley path, getPriority(priority), guard)); 1917698b304SZane Shelley } 1927698b304SZane Shelley else if ("callout_connected" == type) 1937698b304SZane Shelley { 1947698b304SZane Shelley auto name = a.at("name").get<std::string>(); 1957698b304SZane Shelley auto priority = a.at("priority").get<std::string>(); 1967698b304SZane Shelley auto guard = a.at("guard").get<bool>(); 1977698b304SZane Shelley 1985d63cefcSZane Shelley auto busData = parseBus(i_data, name); 1995d63cefcSZane Shelley 2005d63cefcSZane Shelley o_list->push(std::make_shared<ConnectedCalloutResolution>( 2015d63cefcSZane Shelley std::get<0>(busData), std::get<1>(busData), 2025d63cefcSZane Shelley getPriority(priority), guard)); 2037698b304SZane Shelley } 2047698b304SZane Shelley else if ("callout_bus" == type) 2057698b304SZane Shelley { 2067698b304SZane Shelley auto name = a.at("name").get<std::string>(); 207*4757a7bcSZane Shelley auto priority = a.at("priority").get<std::string>(); 2087698b304SZane Shelley auto guard = a.at("guard").get<bool>(); 2097698b304SZane Shelley 210*4757a7bcSZane Shelley auto busData = parseBus(i_data, name); 211*4757a7bcSZane Shelley 212*4757a7bcSZane Shelley o_list->push(std::make_shared<BusCalloutResolution>( 213*4757a7bcSZane Shelley std::get<0>(busData), std::get<1>(busData), 214*4757a7bcSZane Shelley getPriority(priority), guard)); 2157698b304SZane Shelley } 2167698b304SZane Shelley else if ("callout_clock" == type) 2177698b304SZane Shelley { 21884721d90SZane Shelley auto name = a.at("name").get<std::string>(); 2197698b304SZane Shelley auto priority = a.at("priority").get<std::string>(); 2207698b304SZane Shelley auto guard = a.at("guard").get<bool>(); 2217698b304SZane Shelley 22284721d90SZane Shelley // clang-format off 22384721d90SZane Shelley static const std::map<std::string, callout::ClockType> m = 22484721d90SZane Shelley { 22584721d90SZane Shelley {"OSC_REF_CLOCK_0", callout::ClockType::OSC_REF_CLOCK_0}, 22684721d90SZane Shelley {"OSC_REF_CLOCK_1", callout::ClockType::OSC_REF_CLOCK_1}, 22784721d90SZane Shelley }; 22884721d90SZane Shelley // clang-format on 22984721d90SZane Shelley 23084721d90SZane Shelley o_list->push(std::make_shared<ClockCalloutResolution>( 23184721d90SZane Shelley m.at(name), getPriority(priority), guard)); 2327698b304SZane Shelley } 2337698b304SZane Shelley else if ("callout_procedure" == type) 2347698b304SZane Shelley { 2357698b304SZane Shelley auto name = a.at("name").get<std::string>(); 2367698b304SZane Shelley auto priority = a.at("priority").get<std::string>(); 2377698b304SZane Shelley 2387698b304SZane Shelley // clang-format off 239c85716caSZane Shelley static const std::map<std::string, callout::Procedure> m = 2407698b304SZane Shelley { 241c85716caSZane Shelley {"LEVEL2", callout::Procedure::NEXTLVL}, 2427698b304SZane Shelley }; 2437698b304SZane Shelley // clang-format on 2447698b304SZane Shelley 2457698b304SZane Shelley o_list->push(std::make_shared<ProcedureCalloutResolution>( 2467698b304SZane Shelley m.at(name), getPriority(priority))); 2477698b304SZane Shelley } 2487698b304SZane Shelley else if ("callout_part" == type) 2497698b304SZane Shelley { 2507698b304SZane Shelley auto name = a.at("name").get<std::string>(); 2517698b304SZane Shelley auto priority = a.at("priority").get<std::string>(); 2527698b304SZane Shelley 2537698b304SZane Shelley // TODO 2547698b304SZane Shelley trace::inf("callout_part: name=%s priority=%s", name.c_str(), 2557698b304SZane Shelley priority.c_str()); 2567698b304SZane Shelley } 2577698b304SZane Shelley else if ("plugin" == type) 2587698b304SZane Shelley { 2597698b304SZane Shelley auto name = a.at("name").get<std::string>(); 2607698b304SZane Shelley 2617698b304SZane Shelley // TODO 2627698b304SZane Shelley trace::inf("plugin: name=%s", name.c_str()); 2637698b304SZane Shelley } 2647698b304SZane Shelley else 2657698b304SZane Shelley { 2667698b304SZane Shelley throw std::logic_error("Unsupported action type: " + type); 2677698b304SZane Shelley } 2687698b304SZane Shelley } 2697698b304SZane Shelley 2707698b304SZane Shelley // Done with this action pop it off the stack. 2717698b304SZane Shelley stack.pop_back(); 2727698b304SZane Shelley 2737698b304SZane Shelley return o_list; 2747698b304SZane Shelley } 2757698b304SZane Shelley 2767698b304SZane Shelley //------------------------------------------------------------------------------ 2777698b304SZane Shelley 278c85716caSZane Shelley callout::Priority RasDataParser::getPriority(const std::string& i_priority) 2797698b304SZane Shelley { 2807698b304SZane Shelley // clang-format off 281c85716caSZane Shelley static const std::map<std::string, callout::Priority> m = 2827698b304SZane Shelley { 283c85716caSZane Shelley {"HIGH", callout::Priority::HIGH}, 284c85716caSZane Shelley {"MED", callout::Priority::MED}, 285c85716caSZane Shelley {"MED_A", callout::Priority::MED_A}, 286c85716caSZane Shelley {"MED_B", callout::Priority::MED_B}, 287c85716caSZane Shelley {"MED_C", callout::Priority::MED_C}, 288c85716caSZane Shelley {"LOW", callout::Priority::LOW}, 2897698b304SZane Shelley }; 2907698b304SZane Shelley // clang-format on 2917698b304SZane Shelley 2927698b304SZane Shelley return m.at(i_priority); 2937698b304SZane Shelley } 2947698b304SZane Shelley 2957698b304SZane Shelley //------------------------------------------------------------------------------ 2967698b304SZane Shelley 297a9b44344SZane Shelley } // namespace analyzer 298