diff --git a/dv/uvm/core_ibex/scripts/report_lib/util.py b/dv/uvm/core_ibex/scripts/report_lib/util.py index c94698d49f..f6a00756c2 100644 --- a/dv/uvm/core_ibex/scripts/report_lib/util.py +++ b/dv/uvm/core_ibex/scripts/report_lib/util.py @@ -96,7 +96,7 @@ def parse_xcelium_cov_report(cov_report: str) -> Dict[str, Dict[str, Dict[str, i metric_info.append((metric_info_match.group(1), metric_info_match.group(2))) - # Skip header seperator line + # Skip header separator line metrics_start_line = line_no + 2 if metrics_start_line == -1: diff --git a/dv/verilator/pcount/cpp/ibex_pcounts.cc b/dv/verilator/pcount/cpp/ibex_pcounts.cc index 733dcf09bf..6924ee5261 100644 --- a/dv/verilator/pcount/cpp/ibex_pcounts.cc +++ b/dv/verilator/pcount/cpp/ibex_pcounts.cc @@ -10,6 +10,7 @@ #include extern "C" { +extern unsigned int mhpmcounter_num(); extern unsigned long long mhpmcounter_get(int index); } @@ -32,24 +33,48 @@ const std::vector ibex_counter_names = { "Multiply Wait", "Divide Wait"}; +static bool has_hpm_counter(int index) { + // The "cycles" and "instructions retired" counters are special and always + // exist. + if (index == 0 || index == 2) + return true; + + // The "NONE" counter is a placeholder. The space reserves an index that was + // once the "MTIME" CSR, but now is unused. Return false: there's no real HPM + // counter at index 1. + if (index == 1) + return false; + + // Otherwise, a counter exists if the index is strictly less than + // the MHPMCounterNum parameter that got passed to the + // ibex_cs_registers module. + return index < mhpmcounter_num(); +} + std::string ibex_pcount_string(bool csv) { - char seperator = csv ? ',' : ':'; + char separator = csv ? ',' : ':'; std::string::size_type longest_name_length; if (!csv) { longest_name_length = 0; - for (const std::string &counter_name : ibex_counter_names) { - longest_name_length = std::max(longest_name_length, counter_name.length()); + for (int i = 0; i < ibex_counter_names.size(); ++i) { + if (has_hpm_counter(i)) { + longest_name_length = + std::max(longest_name_length, ibex_counter_names[i].length()); + } } - // Add 1 to always get at least once space after the seperator + // Add 1 to always get at least once space after the separator longest_name_length++; } std::stringstream pcount_ss; for (int i = 0; i < ibex_counter_names.size(); ++i) { - pcount_ss << ibex_counter_names[i] << seperator; + if (!has_hpm_counter(i)) + continue; + + pcount_ss << ibex_counter_names[i] << separator; if (!csv) { int padding = longest_name_length - ibex_counter_names[i].length(); diff --git a/examples/simple_system/rtl/ibex_simple_system.sv b/examples/simple_system/rtl/ibex_simple_system.sv index d9647335a1..ac74691d68 100644 --- a/examples/simple_system/rtl/ibex_simple_system.sv +++ b/examples/simple_system/rtl/ibex_simple_system.sv @@ -318,6 +318,12 @@ module ibex_simple_system ( .timer_intr_o (timer_irq) ); + export "DPI-C" function mhpmcounter_num; + + function automatic int unsigned mhpmcounter_num(); + return u_top.u_ibex_top.u_ibex_core.cs_registers_i.MHPMCounterNum; + endfunction + export "DPI-C" function mhpmcounter_get; function automatic longint unsigned mhpmcounter_get(int index);