[rtl/sw] Add multiply and divide wait counters

This commit is contained in:
Greg Chadwick 2020-03-05 14:37:42 +00:00
parent efbfecbb38
commit 3927fd8d2a
7 changed files with 36 additions and 5 deletions

View file

@ -41,6 +41,10 @@ The following events can be monitored using the performance counters of Ibex.
+--------------+------------------+---------------------------------------------------------+
| 10 | NumInstrRetC | Number of compressed instructions retired |
+--------------+------------------+---------------------------------------------------------+
| 11 | NumCyclesMulWait | Cycles waiting for multiply to complete |
+--------------+------------------+---------------------------------------------------------+
| 12 | NumCyclesDivWait | Cycles waiting for divide to complete |
+--------------+------------------+---------------------------------------------------------+
The event selector CSRs ``mhpmevent3`` - ``mhpmevent31`` define which of these events are counted by the event counters ``mhpmcounter3(h)`` - ``mhpmcounter31(h)``.
If a specific bit in an event selector CSR is set to 1, this means that events with this ID are being counted by the counter associated with that selector CSR.
@ -99,6 +103,10 @@ The association of events with the ``mphmcounter`` registers is hardwired as lis
+----------------------+----------------+--------------+------------------+
| ``mhpmcounter10(h)`` | 0xB0A (0xB8A) | 10 | NumInstrRetC |
+----------------------+----------------+--------------+------------------+
| ``mhpmcounter11(h)`` | 0xB0B (0xB8B) | 11 | NumCyclesMulWait |
+----------------------+----------------+--------------+------------------+
| ``mhpmcounter12(h)`` | 0xB0C (0xB8C) | 12 | NumCyclesDivWait |
+----------------------+----------------+--------------+------------------+
Similarly, the event selector CSRs are hardwired as follows.
The remaining event selector CSRs are tied to 0, i.e., no events are counted by the corresponding counters.

View file

@ -94,6 +94,8 @@ module tb_cs_registers #(
logic mem_load_i; // load from memory in this cycle
logic mem_store_i; // store to memory in this cycle
logic dside_wait_i; // core waiting for the dside
logic mul_wait_i;
logic div_wait_i;
//-----------------
// Reset generation

View file

@ -22,7 +22,9 @@ const std::vector<std::string> ibex_counter_names = {
"Jumps",
"Conditional Branches",
"Taken Conditional Branches",
"Compressed Instructions"};
"Compressed Instructions",
"Multiply Wait",
"Divide Wait"};
std::string ibex_pcount_string(uint64_t pcounts[], bool csv) {
char seperator = csv ? ',' : ':';

View file

@ -66,6 +66,8 @@ void pcount_read(uint32_t pcount_out[]) {
PCOUNT_READ(mhpmcounter8, pcount_out[6]);
PCOUNT_READ(mhpmcounter9, pcount_out[7]);
PCOUNT_READ(mhpmcounter10, pcount_out[8]);
PCOUNT_READ(mhpmcounter11, pcount_out[9]);
PCOUNT_READ(mhpmcounter12, pcount_out[10]);
}
const char *pcount_names[] = {"Instructions Retired",
@ -76,7 +78,9 @@ const char *pcount_names[] = {"Instructions Retired",
"Jumps",
"Branches",
"Taken Branches",
"Compressed Instructions"};
"Compressed Instructions",
"Multiply Wait",
"Divide Wait"};
const uint32_t pcount_num = sizeof(pcount_names) / sizeof(char *);

View file

@ -257,6 +257,8 @@ module ibex_core #(
logic perf_iside_wait;
logic perf_dside_wait;
logic perf_mul_wait;
logic perf_div_wait;
logic perf_jump;
logic perf_branch;
logic perf_tbranch;
@ -533,6 +535,8 @@ module ibex_core #(
.perf_branch_o ( perf_branch ),
.perf_tbranch_o ( perf_tbranch ),
.perf_dside_wait_o ( perf_dside_wait ),
.perf_mul_wait_o ( perf_mul_wait ),
.perf_div_wait_o ( perf_div_wait ),
.instr_id_done_o ( instr_id_done ),
.instr_id_done_compressed_o ( instr_id_done_compressed )
);
@ -828,7 +832,9 @@ module ibex_core #(
.branch_taken_i ( perf_tbranch ),
.mem_load_i ( perf_load ),
.mem_store_i ( perf_store ),
.dside_wait_i ( perf_dside_wait )
.dside_wait_i ( perf_dside_wait ),
.mul_wait_i ( perf_mul_wait ),
.div_wait_i ( perf_div_wait )
);
if (PMPEnable) begin : g_pmp

View file

@ -14,7 +14,7 @@
module ibex_cs_registers #(
parameter bit DbgTriggerEn = 0,
parameter int unsigned MHPMCounterNum = 8,
parameter int unsigned MHPMCounterNum = 10,
parameter int unsigned MHPMCounterWidth = 40,
parameter bit PMPEnable = 0,
parameter int unsigned PMPGranularity = 0,
@ -97,7 +97,9 @@ module ibex_cs_registers #(
input logic branch_taken_i, // branch was taken
input logic mem_load_i, // load from memory in this cycle
input logic mem_store_i, // store to memory in this cycle
input logic dside_wait_i // core waiting for the dside
input logic dside_wait_i, // core waiting for the dside
input logic mul_wait_i, // core waiting for multiply
input logic div_wait_i // core waiting for divide
);
import ibex_pkg::*;
@ -855,6 +857,8 @@ module ibex_cs_registers #(
mhpmcounter_incr[8] = branch_i; // num of branches (conditional)
mhpmcounter_incr[9] = branch_taken_i; // num of taken branches (conditional)
mhpmcounter_incr[10] = instr_ret_compressed_i; // num of compressed instr
mhpmcounter_incr[11] = mul_wait_i; // cycles waiting for multiply
mhpmcounter_incr[12] = div_wait_i; // cycles waiting for divide
// inactive counters
for (int unsigned i=3+MHPMCounterNum; i<32; i++) begin : gen_mhpmcounter_incr_inactive

View file

@ -160,6 +160,8 @@ module ibex_id_stage #(
output logic perf_tbranch_o, // executing a taken branch instr
output logic perf_dside_wait_o, // instruction in ID/EX is awaiting memory
// access to finish before proceeding
output logic perf_mul_wait_o,
output logic perf_div_wait_o,
output logic instr_id_done_o,
output logic instr_id_done_compressed_o
);
@ -836,6 +838,9 @@ module ibex_id_stage #(
assign instr_id_done_o = instr_done;
end
assign perf_mul_wait_o = stall_multdiv & mult_en_dec;
assign perf_div_wait_o = stall_multdiv & div_en_dec;
assign instr_id_done_compressed_o = instr_id_done_o & instr_is_compressed_i;
////////////////