diff --git a/dv/verilator/pcount/cpp/ibex_pcounts.cc b/dv/verilator/pcount/cpp/ibex_pcounts.cc new file mode 100644 index 00000000..8f2cf699 --- /dev/null +++ b/dv/verilator/pcount/cpp/ibex_pcounts.cc @@ -0,0 +1,57 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +#include +#include +#include +#include + +#include "ibex_pcounts.h" + +// see mhpmcounter_incr signals in rtl/ibex_cs_registers.sv for details + +const std::vector ibex_counter_names = { + "Cycles", + "NONE", + "Instructions Retired", + "LSU Busy", + "Fetch Wait", + "Loads", + "Stores", + "Jumps", + "Conditional Branches", + "Taken Conditional Branches", + "Compressed Instructions"}; + +std::string ibex_pcount_string(uint64_t pcounts[], bool csv) { + char seperator = 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()); + } + + // Add 1 to always get at least once space after the seperator + 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 (!csv) { + int padding = longest_name_length - ibex_counter_names[i].length(); + + for (int j = 0; j < padding; ++j) + pcount_ss << ' '; + } + + pcount_ss << pcounts[i] << std::endl; + } + + return pcount_ss.str(); +} diff --git a/dv/verilator/pcount/cpp/ibex_pcounts.h b/dv/verilator/pcount/cpp/ibex_pcounts.h new file mode 100644 index 00000000..0d90678e --- /dev/null +++ b/dv/verilator/pcount/cpp/ibex_pcounts.h @@ -0,0 +1,44 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +#ifndef IBEX_PCOUNTS_H_ +#define IBEX_PCOUNTS_H_ + +#include +#include +#include + +extern const std::vector ibex_counter_names; + +/** + * Returns a formatted string of performance counter values + * + * In Ibex the performance counters are held in the mhpmcounter flops in + * ibex_cs_registers. In a verilator simulation the signal type of the + * mhpmcounter array should be compatible with the type of pcounts here and so + * can be passed in directly to this function. + * + * There are two options for string formatting, csv or pretty-print. Both + * produce one counter name and value per line. csv just seperates them with a + * comma and no further formatting. pretty-print uses a colon and aligns the + * values. + * + * csv (csv == true): + * countername1, 1234 + * longercountername1, 43980 + * ... + * + * pretty-print (csv == false): + * countername1: 1234 + * longercountername1: 43980 + * ... + * + * @param pcounts Array of performance counter values, must be of length + * ibex_pcount_num + * @param csv Choose csv or pretty-print formatting + * @return String of formatted performance counter values, newline at end + */ +std::string ibex_pcount_string(uint64_t pcounts[], bool csv); + +#endif // IBEX_PCOUNTS_H_ diff --git a/dv/verilator/pcount/ibex_pcounts.core b/dv/verilator/pcount/ibex_pcounts.core new file mode 100644 index 00000000..1a8f0447 --- /dev/null +++ b/dv/verilator/pcount/ibex_pcounts.core @@ -0,0 +1,19 @@ +CAPI=2: +# Copyright lowRISC contributors. +# Licensed under the Apache License, Version 2.0, see LICENSE for details. +# SPDX-License-Identifier: Apache-2.0 + +name: "lowrisc:dv_verilator:ibex_pcounts" +description: "Ibex performance counter utils" +filesets: + files_cpp: + files: + - cpp/ibex_pcounts.cc + - cpp/ibex_pcounts.h: { is_include_file: true } + file_type: cppSource + +targets: + default: + filesets: + - files_cpp + diff --git a/rtl/ibex_cs_registers.sv b/rtl/ibex_cs_registers.sv index 7ca67537..111c1f8c 100644 --- a/rtl/ibex_cs_registers.sv +++ b/rtl/ibex_cs_registers.sv @@ -780,6 +780,10 @@ module ibex_cs_registers #( // event selection (hardwired) & control always_comb begin : gen_mhpmcounter_incr + // When adding or altering performance counter meanings and default + // mappings please update dv/verilator/pcount/cpp/ibex_pcounts.cc + // appropriately. + // // active counters mhpmcounter_incr[0] = 1'b1; // mcycle mhpmcounter_incr[1] = 1'b0; // reserved