.. _performance-counters:

Performance Counters
====================

Ibex implements performance counters according to the RISC-V Privileged Specification, version 1.11 (see Hardware Performance Monitor, Section 3.1.11).
The performance counters are placed inside the Control and Status Registers (CSRs) and can be accessed with the ``CSRRW(I)`` and ``CSRRS/C(I)`` instructions.

Ibex implements the clock cycle counter ``mcycle(h)``, the retired instruction counter ``minstret(h)``, as well as the 29 event counters ``mhpmcounter3(h)`` - ``mhpmcounter31(h)`` and the corresponding event selector CSRs ``mhpmevent3`` - ``mhpmevent31``, and the ``mcountinhibit`` CSR to individually enable/disable the counters.
``mcycle(h)`` and ``minstret(h)`` are always available and 64 bit wide.
The ``mhpmcounter`` performance counters are optional (unavailable by default) and parametrizable in width.

Event Selector
--------------

The following events can be monitored using the performance counters of Ibex.

+--------------+------------------+---------------------------------------------------------+
| Event ID/Bit | Event Name       | Event Description                                       |
+==============+==================+=========================================================+
|            0 | NumCycles        | Number of cycles                                        |
+--------------+------------------+---------------------------------------------------------+
|            2 | NumInstrRet      | Number of instructions retired                          |
+--------------+------------------+---------------------------------------------------------+
|            3 | NumCyclesLSU     | Number of cycles waiting for data memory                |
+--------------+------------------+---------------------------------------------------------+
|            4 | NumCyclesIF      | Cycles waiting for instruction fetches, i.e., number of |
|              |                  | instructions wasted due to non-ideal caching            |
+--------------+------------------+---------------------------------------------------------+
|            5 | NumLoads         | Number of data memory loads. Misaligned accesses are    |
|              |                  | counted as two accesses                                 |
+--------------+------------------+---------------------------------------------------------+
|            6 | NumStores        | Number of data memory stores. Misaligned accesses are   |
|              |                  | counted as two accesses                                 |
+--------------+------------------+---------------------------------------------------------+
|            7 | NumJumps         | Number of unconditional jumps (j, jal, jr, jalr)        |
+--------------+------------------+---------------------------------------------------------+
|            8 | NumBranches      | Number of branches (conditional)                        |
+--------------+------------------+---------------------------------------------------------+
|            9 | NumBranchesTaken | Number of taken branches (conditional)                  |
+--------------+------------------+---------------------------------------------------------+
|           10 | NumInstrRetC     | Number of compressed instructions retired               |
+--------------+------------------+---------------------------------------------------------+

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.
If an event selector CSR is 0, this means that the corresponding counter is not counting any event.

Controlling the counters from software
--------------------------------------

By default, all available counters are enabled after reset.
They can be individually enabled/disabled by overwriting the corresponding bit in the ``mcountinhibit`` CSR at address ``0x320`` as described in the RISC-V Privileged Specification, version 1.11 (see Machine Counter-Inhibit CSR, Section 3.1.13).
In particular, to enable/disable ``mcycle(h)``, bit 0 must be written. For ``minstret(h)``, it is bit 2. For event counter ``mhpmcounterX(h)``, it is bit X.

The lower 32 bits of all counters can be accessed through the base register, whereas the upper 32 bits are accessed through the ``h``-register.
Reads to all these registers are non-destructive.

Parametrization at synthesis time
---------------------------------

The ``mcycle(h)`` and ``minstret(h)`` counters are always available and 64 bit wide.

The event counters ``mhpmcounter3(h)`` - ``mhpmcounter31(h)`` are parametrizable.
Their width can be parametrized between 1 and 64 bit through the ``WidthMHPMCounters`` parameter, which defaults to 40 bit wide counters.

The number of available event counters ``mhpmcounterX(h)`` can be controlled via the ``NumMHPMCounters`` parameter.
By default (``NumMHPMCounters`` set to 0), no counters are available to software.
Set ``NumMHPMCounters`` to a value between 1 and 8 to make the counters ``mhpmcounter3(h)`` - ``mhpmcounter10(h)`` available as listed below.
Setting ``NumMHPMCounters`` to values larger than 8 does not result in any more performance counters.

Unavailable counters always read 0.

The association of events with the ``mphmcounter`` registers is hardwired as listed in the following table.

+----------------------+----------------+--------------+------------------+
| Event Counter        | CSR Address    | Event ID/Bit | Event Name       |
+======================+================+==============+==================+
| ``mcycle(h)``        | 0xB00 (0xB80)  |            0 | NumCycles        |
+----------------------+----------------+--------------+------------------+
| ``minstret(h)``      | 0xB02 (0xB82)  |            2 | NumInstrRet      |
+----------------------+----------------+--------------+------------------+
| ``mhpmcounter3(h)``  | 0xB03 (0xB83)  |            3 | NumCyclesLSU     |
+----------------------+----------------+--------------+------------------+
| ``mhpmcounter4(h)``  | 0xB04 (0xB84)  |            4 | NumCyclesIF      |
|                      |                |              |                  |
+----------------------+----------------+--------------+------------------+
| ``mhpmcounter5(h)``  | 0xB05 (0xB85)  |            5 | NumLoads         |
|                      |                |              |                  |
+----------------------+----------------+--------------+------------------+
| ``mhpmcounter6(h)``  | 0xB06 (0xB86)  |            6 | NumStores        |
|                      |                |              |                  |
+----------------------+----------------+--------------+------------------+
| ``mhpmcounter7(h)``  | 0xB07 (0xB87)  |            7 | NumJumps         |
+----------------------+----------------+--------------+------------------+
| ``mhpmcounter8(h)``  | 0xB08 (0xB88)  |            8 | NumBranches      |
+----------------------+----------------+--------------+------------------+
| ``mhpmcounter9(h)``  | 0xB09 (0xB89)  |            9 | NumBranchesTaken |
+----------------------+----------------+--------------+------------------+
| ``mhpmcounter10(h)`` | 0xB0A (0xB8A)  |           10 | NumInstrRetC     |
+----------------------+----------------+--------------+------------------+

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.

+----------------------+-------------+-------------+--------------+
| Event Selector       | CSR Address | Reset Value | Event ID/Bit |
+======================+=============+=============+==============+
| ``mhpmevent3(h)``    | 0x323       | 0x0000_0008 |            3 |
+----------------------+-------------+-------------+--------------+
| ``mhpmevent4(h)``    | 0x324       | 0x0000_0010 |            4 |
+----------------------+-------------+-------------+--------------+
| ``mhpmevent5(h)``    | 0x325       | 0x0000_0020 |            5 |
+----------------------+-------------+-------------+--------------+
| ``mhpmevent6(h)``    | 0x326       | 0x0000_0040 |            6 |
+----------------------+-------------+-------------+--------------+
| ``mhpmevent7(h)``    | 0x327       | 0x0000_0080 |            7 |
+----------------------+-------------+-------------+--------------+
| ``mhpmevent8(h)``    | 0x328       | 0x0000_0100 |            8 |
+----------------------+-------------+-------------+--------------+
| ``mhpmevent9(h)``    | 0x329       | 0x0000_0200 |            9 |
+----------------------+-------------+-------------+--------------+
| ``mhpmevent10(h)``   | 0x32A       | 0x0000_0400 |           10 |
+----------------------+-------------+-------------+--------------+
