1 2 #include <assert.h> 3 4 #include <hei_main.hpp> 5 #include <util/pdbg.hpp> 6 #include <util/trace.hpp> 7 8 #include <filesystem> 9 #include <fstream> 10 #include <map> 11 #include <vector> 12 13 namespace fs = std::filesystem; 14 15 namespace analyzer 16 { 17 18 //------------------------------------------------------------------------------ 19 20 void __getChipDataFiles(std::map<libhei::ChipType_t, fs::path>& o_files) 21 { 22 o_files.clear(); 23 24 auto directory = "/usr/share/openpower-libhei/"; 25 26 for (const auto& entry : fs::directory_iterator(directory)) 27 { 28 auto path = entry.path(); 29 30 std::ifstream file{path, std::ios::binary}; 31 if (!file.good()) 32 { 33 trace::err("Unable to open file: %s", path.string().c_str()); 34 continue; 35 } 36 37 // The first 8-bytes is the file keyword and the next 4-bytes is the 38 // chip type. 39 libhei::FileKeyword_t keyword; 40 libhei::ChipType_t chipType; 41 42 const size_t sz_keyword = sizeof(keyword); 43 const size_t sz_chipType = sizeof(chipType); 44 const size_t sz_buffer = sz_keyword + sz_chipType; 45 46 // Read the keyword and chip type from the file. 47 char buffer[sz_buffer]; 48 file.read(buffer, sz_buffer); 49 if (!file.good()) 50 { 51 trace::err("Unable to read file: %s", path.string().c_str()); 52 continue; 53 } 54 55 // Get the keyword. 56 memcpy(&keyword, &buffer[0], sz_keyword); 57 keyword = be64toh(keyword); 58 59 // Ensure the keyword value is correct. 60 if (libhei::KW_CHIPDATA != keyword) 61 { 62 trace::err("Invalid chip data file: %s", path.string().c_str()); 63 continue; 64 } 65 66 // Get the chip type. 67 memcpy(&chipType, &buffer[sz_keyword], sz_chipType); 68 chipType = be32toh(chipType); 69 70 // Trace each legitimate chip data file for debug. 71 trace::inf("File found: type=0x%0" PRIx32 " path=%s", chipType, 72 path.string().c_str()); 73 74 // So far, so good. Add the entry. 75 auto ret = o_files.emplace(chipType, path); 76 assert(ret.second); // Should not have duplicate entries 77 } 78 } 79 80 //------------------------------------------------------------------------------ 81 82 void __initialize(const fs::path& i_path) 83 { 84 // Get file size. 85 const auto sz_buffer = fs::file_size(i_path); 86 87 // Create a buffer large enough to hold the entire file. 88 std::vector<char> buffer(sz_buffer); 89 90 // Open the chip data file. 91 std::ifstream file{i_path, std::ios::binary}; 92 assert(file.good()); // We've opened it once before, so it should open now. 93 94 // Read the entire file into the buffer. 95 file.read(buffer.data(), sz_buffer); 96 assert(file.good()); // Again, this should be readable. 97 98 // This is not necessary, but it frees up memory before calling the memory 99 // intensive initialize() function. 100 file.close(); 101 102 // Initialize the isolator with this chip data file. 103 libhei::initialize(buffer.data(), sz_buffer); 104 } 105 106 //------------------------------------------------------------------------------ 107 108 void initializeIsolator(std::vector<libhei::Chip>& o_chips) 109 { 110 // Get all of the active chips to be analyzed. 111 util::pdbg::getActiveChips(o_chips); 112 113 // Find all of the existing chip data files. 114 std::map<libhei::ChipType_t, fs::path> files; 115 __getChipDataFiles(files); 116 117 // Keep track of models/levels that have already been initialized. 118 std::map<libhei::ChipType_t, unsigned int> initTypes; 119 120 for (const auto& chip : o_chips) 121 { 122 auto chipType = chip.getType(); 123 124 // Mark this chip type as initialized (or will be if it hasn't been). 125 auto ret = initTypes.emplace(chipType, 1); 126 if (!ret.second) 127 { 128 // This type has already been initialized. Nothing more to do. 129 continue; 130 } 131 132 // Get the file for this chip. 133 auto itr = files.find(chipType); 134 135 // Ensure a chip data file exist for this chip. 136 assert(files.end() != itr); 137 138 // Initialize this chip type. 139 __initialize(itr->second); 140 } 141 } 142 143 //------------------------------------------------------------------------------ 144 145 } // namespace analyzer 146