| #include "uhdmastreport.h" | 
 | #include "frontends/ast/ast.h" | 
 | #include <fstream> | 
 | #include <sys/stat.h> | 
 | #include <uhdm/BaseClass.h> | 
 | #include <unordered_set> | 
 |  | 
 | namespace systemverilog_plugin | 
 | { | 
 |  | 
 | using namespace ::Yosys; | 
 |  | 
 | void UhdmAstReport::mark_handled(const UHDM::BaseClass *object) | 
 | { | 
 |     handled_count_per_file.insert(std::make_pair(object->VpiFile(), 0)); | 
 |     auto it = unhandled.find(object); | 
 |     if (it != unhandled.end()) { | 
 |         unhandled.erase(it); | 
 |         handled_count_per_file.at(std::string(object->VpiFile()))++; | 
 |     } | 
 | } | 
 |  | 
 | void UhdmAstReport::mark_handled(const vpiHandle obj_h) | 
 | { | 
 |     auto handle = reinterpret_cast<const uhdm_handle *>(obj_h); | 
 |     mark_handled(reinterpret_cast<const UHDM::BaseClass *>(handle->object)); | 
 | } | 
 |  | 
 | static std::string replace_in_string(std::string str, const std::string &to_find, const std::string &to_replace_with) | 
 | { | 
 |     size_t pos = str.find(to_find); | 
 |     while (pos != std::string::npos) { | 
 |         str.replace(pos, to_find.length(), to_replace_with); | 
 |         pos += to_replace_with.length(); | 
 |         pos = str.find(to_find, pos); | 
 |     } | 
 |     return str; | 
 | } | 
 |  | 
 | void UhdmAstReport::write(const std::string &directory) | 
 | { | 
 |     std::unordered_map<std::string, std::unordered_set<unsigned>> unhandled_per_file; | 
 |     for (auto object : unhandled) { | 
 |         if (!object->VpiFile().empty() && object->VpiFile() != AST::current_filename) { | 
 |             unhandled_per_file.insert(std::make_pair(object->VpiFile(), std::unordered_set<unsigned>())); | 
 |             unhandled_per_file.at(std::string(object->VpiFile())).insert(object->VpiLineNo()); | 
 |             handled_count_per_file.insert(std::make_pair(object->VpiFile(), 0)); | 
 |         } | 
 |     } | 
 |     unsigned total_handled = 0; | 
 |     for (auto &hc : handled_count_per_file) { | 
 |         if (!hc.first.empty() && hc.first != AST::current_filename) { | 
 |             unhandled_per_file.insert(std::make_pair(hc.first, std::unordered_set<unsigned>())); | 
 |             total_handled += hc.second; | 
 |         } | 
 |     } | 
 |     float coverage = total_handled * 100.f / (total_handled + unhandled.size()); | 
 |     mkdir(directory.c_str(), 0777); | 
 |     std::ofstream index_file(directory + "/index.html"); | 
 |     index_file << "<!DOCTYPE html>\n<html>\n<head>\n<style>h3{margin:0;padding:10}</style>\n</head><body>" << std::endl; | 
 |     index_file << "<h2>Overall coverage: " << coverage << "%</h2>" << std::endl; | 
 |     for (auto &unhandled_in_file : unhandled_per_file) { | 
 |         // Calculate coverage in file | 
 |         unsigned handled_count = handled_count_per_file.at(unhandled_in_file.first); | 
 |         unsigned unhandled_count = unhandled_in_file.second.size(); | 
 |         float coverage = handled_count * 100.f / (handled_count + unhandled_count); | 
 |         // Add to the index file | 
 |         std::string report_filename = replace_in_string(unhandled_in_file.first, "/", ".") + ".html"; | 
 |         index_file << "<h3>Cov: " << coverage << "%<a href=\"" << report_filename << "\">" << unhandled_in_file.first << "</a></h3><br>" << std::endl; | 
 |         // Write the report file | 
 |         std::ofstream report_file(directory + '/' + report_filename); | 
 |         report_file << "<!DOCTYPE html>\n<html>\n<head>\n<style>\nbody{font-size:12px;}pre{display:inline}</style>\n</head><body>" << std::endl; | 
 |         report_file << "<h2>" << unhandled_in_file.first << " | Coverage: " << coverage << "%</h2>" << std::endl; | 
 |         std::ifstream source_file(unhandled_in_file.first); // Read the source code | 
 |         unsigned line_number = 1; | 
 |         std::string line; | 
 |         while (std::getline(source_file, line)) { | 
 |             if (unhandled_in_file.second.find(line_number) == unhandled_in_file.second.end()) { | 
 |                 report_file << line_number << "<pre> " << line << "</pre><br>" << std::endl; | 
 |             } else { | 
 |                 report_file << line_number << "<pre style=\"background-color: #FFB6C1;\"> " << line << "</pre><br>" << std::endl; | 
 |             } | 
 |             ++line_number; | 
 |         } | 
 |         report_file << "</body>\n</html>" << std::endl; | 
 |     } | 
 |     index_file << "</body>\n</html>" << std::endl; | 
 | } | 
 |  | 
 | } // namespace systemverilog_plugin |