mirror of
https://github.com/espressif/esp-idf.git
synced 2026-09-22 13:01:16 +03:00
feat(esp_hw_support): add cache access counter API
This commit is contained in:
committed by
Ivan Grokhotkov
parent
7e5235a7a7
commit
16078650c8
@@ -133,6 +133,8 @@ COEXISTENCE_DOCS = ['api-guides/coexist.rst']
|
||||
|
||||
MM_SYNC_DOCS = ['api-reference/system/mm_sync.rst']
|
||||
|
||||
CACHE_CNT_DOCS = ['api-reference/system/cache_cnt.rst']
|
||||
|
||||
CAMERA_DOCS = ['api-reference/peripherals/camera_driver.rst']
|
||||
|
||||
BITSCRAMBLER_DOCS = ['api-reference/peripherals/bitscrambler.rst']
|
||||
@@ -378,6 +380,7 @@ conditional_include_dict = {
|
||||
'SOC_SUPPORT_COEXISTENCE': COEXISTENCE_DOCS,
|
||||
'SOC_PSRAM_DMA_CAPABLE': MM_SYNC_DOCS,
|
||||
'SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE': MM_SYNC_DOCS,
|
||||
'SOC_CACHE_CNT_SUPPORTED': CACHE_CNT_DOCS,
|
||||
'SOC_CLK_TREE_SUPPORTED': CLK_TREE_DOCS,
|
||||
'SOC_UART_SUPPORTED': UART_DOCS,
|
||||
'SOC_UHCI_SUPPORTED': UHCI_DOCS,
|
||||
|
||||
@@ -236,6 +236,7 @@ INPUT = \
|
||||
$(PROJECT_PATH)/components/esp_https_ota/include/esp_https_ota.h \
|
||||
$(PROJECT_PATH)/components/esp_https_server/include/esp_https_server.h \
|
||||
$(PROJECT_PATH)/components/esp_hw_support/etm/include/esp_etm.h \
|
||||
$(PROJECT_PATH)/components/esp_hw_support/include/esp_cache_cnt.h \
|
||||
$(PROJECT_PATH)/components/esp_hw_support/include/esp_clk_tree.h \
|
||||
$(PROJECT_PATH)/components/esp_hw_support/include/esp_chip_info.h \
|
||||
$(PROJECT_PATH)/components/esp_hw_support/include/esp_cpu.h \
|
||||
|
||||
47
docs/en/api-reference/system/cache_cnt.rst
Normal file
47
docs/en/api-reference/system/cache_cnt.rst
Normal file
@@ -0,0 +1,47 @@
|
||||
Cache Access Counters
|
||||
=====================
|
||||
|
||||
:link_to_translation:`zh_CN:[中文]`
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
{IDF_TARGET_NAME} has hardware counters attached to the cache request buses. They record the number of completed cache accesses, miss stall events, requester conflicts, and cache lines transferred to and from the next level of the memory hierarchy. These counters can be used to measure the cache hit/miss behavior of a piece of code, for example to choose the placement of data in memory, or to find out why some code runs slower than expected.
|
||||
|
||||
Counter Units
|
||||
-------------
|
||||
|
||||
The set of counters differs between chips: the number of cache levels, the number of request buses per cache, and which counters exist per bus all vary. Instead of a fixed list of caches, the API exposes a chip-defined list of counter *units*. Each unit is one set of counters observing one traffic stream, for example instruction fetches from core 0 into the L1 cache. Applications enumerate the units at runtime using :cpp:func:`esp_cache_cnt_num_units` and :cpp:func:`esp_cache_cnt_get_unit_info`, so they keep working when a new chip adds or removes units.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
1. Call :cpp:func:`esp_cache_cnt_start` to clear and enable all counters.
|
||||
2. Run the code to be measured.
|
||||
3. Call :cpp:func:`esp_cache_cnt_stop` to disable the counters, so that reading out and reporting the results is not counted as well.
|
||||
4. Call :cpp:func:`esp_cache_cnt_dump` to print a table of all counter values, or read the values of individual units with :cpp:func:`esp_cache_cnt_get`.
|
||||
|
||||
:cpp:func:`esp_cache_cnt_clear` resets the counters without changing whether they are running, which is useful when the counters have to stay enabled across measurement phases.
|
||||
|
||||
Counter Semantics
|
||||
-----------------
|
||||
|
||||
For each unit, :cpp:func:`esp_cache_cnt_get` returns:
|
||||
|
||||
- ``accesses``: the number of completed accesses. The hardware "hit" counter increments once for every access that completes, whether or not the access had to wait for a line fill first, so it is reported as the total access count.
|
||||
- ``stall_events``: incremented repeatedly while an access is stalled on a miss. This value grows with the total miss latency, not with the number of missed accesses, so it is only useful as a relative measure.
|
||||
- ``conflicts``: the number of conflicts between requesters on the cache.
|
||||
- ``line_fills``: the number of lines fetched from the next level of the memory hierarchy. This is the true miss count.
|
||||
- ``writebacks``: the number of lines written back to the next level. Only present for data traffic on chips with a write-back cache.
|
||||
|
||||
The miss ratio of a unit is therefore ``line_fills / accesses``, available as :cpp:func:`esp_cache_cnt_miss_ratio`. Not every counter exists for every unit; a field of :cpp:struct:`esp_cache_cnt_data_t` is only meaningful if the corresponding bit of the ``valid_mask`` member is set.
|
||||
|
||||
Application Examples
|
||||
--------------------
|
||||
|
||||
- :example:`system/cache_counters` runs a read workload over working sets of different sizes and placements, and prints the counter values after each run, showing how the working set size determines which level of the memory hierarchy serves the accesses.
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
|
||||
.. include-build-file:: inc/esp_cache_cnt.inc
|
||||
@@ -11,6 +11,7 @@ System API
|
||||
app_trace
|
||||
esp_trace
|
||||
esp_function_with_shared_stack
|
||||
:SOC_CACHE_CNT_SUPPORTED: cache_cnt
|
||||
chip_revision
|
||||
console
|
||||
efuse
|
||||
|
||||
47
docs/zh_CN/api-reference/system/cache_cnt.rst
Normal file
47
docs/zh_CN/api-reference/system/cache_cnt.rst
Normal file
@@ -0,0 +1,47 @@
|
||||
缓存访问计数器
|
||||
==============
|
||||
|
||||
:link_to_translation:`en:[English]`
|
||||
|
||||
简介
|
||||
----
|
||||
|
||||
{IDF_TARGET_NAME} 的缓存请求总线上带有硬件计数器,用于记录已完成的缓存访问次数、未命中停顿事件、请求方冲突次数,以及与下一级存储之间传输的缓存行数量。借助这些计数器,可以测量某段代码的缓存命中/未命中情况,例如用于选择数据在内存中的放置位置,或分析某段代码运行速度不及预期的原因。
|
||||
|
||||
计数器单元
|
||||
----------
|
||||
|
||||
不同芯片提供的计数器有所不同:缓存层级数、每个缓存的请求总线数量,以及每条总线上存在哪些计数器都可能不同。因此,API 没有定义固定的缓存列表,而是提供由芯片定义的计数器 **单元** 列表。每个单元是观察同一数据流的一组计数器,例如 CPU0 向 L1 缓存发出的取指请求。应用程序可在运行时通过 :cpp:func:`esp_cache_cnt_num_units` 和 :cpp:func:`esp_cache_cnt_get_unit_info` 枚举这些单元,因此当新芯片增加或减少单元时,应用程序无需修改。
|
||||
|
||||
使用方法
|
||||
--------
|
||||
|
||||
1. 调用 :cpp:func:`esp_cache_cnt_start`,清零并使能所有计数器。
|
||||
2. 运行需要测量的代码。
|
||||
3. 调用 :cpp:func:`esp_cache_cnt_stop` 停止计数,这样读取和打印结果本身不会被计入。
|
||||
4. 调用 :cpp:func:`esp_cache_cnt_dump` 打印所有计数器数值的表格,或通过 :cpp:func:`esp_cache_cnt_get` 读取单个单元的计数值。
|
||||
|
||||
:cpp:func:`esp_cache_cnt_clear` 在不改变计数使能状态的情况下将计数器清零,适用于需要在多个测量阶段之间保持计数器使能的场景。
|
||||
|
||||
计数器含义
|
||||
----------
|
||||
|
||||
对于每个单元,:cpp:func:`esp_cache_cnt_get` 返回以下计数值:
|
||||
|
||||
- ``accesses``:已完成的访问次数。硬件的“命中”计数器在每次访问完成时加一,无论该访问是否先等待了缓存行填充,因此这里将其报告为总访问次数。
|
||||
- ``stall_events``:访问因未命中而停顿期间会反复递增。该数值随未命中总延迟增长,而不是未命中的访问次数,因此只能用作相对指标。
|
||||
- ``conflicts``:该缓存上请求方之间的冲突次数。
|
||||
- ``line_fills``:从下一级存储取回的缓存行数量。这是真正的未命中次数。
|
||||
- ``writebacks``:写回到下一级存储的缓存行数量。仅在具有写回型缓存的芯片上对数据流量提供。
|
||||
|
||||
因此,一个单元的未命中率为 ``line_fills / accesses``,可通过 :cpp:func:`esp_cache_cnt_miss_ratio` 计算。并非每个单元都具有全部计数器;只有当 :cpp:struct:`esp_cache_cnt_data_t` 的 ``valid_mask`` 成员中相应位被置位时,对应字段才有意义。
|
||||
|
||||
应用示例
|
||||
--------
|
||||
|
||||
- :example:`system/cache_counters` 对不同大小和位置的工作集运行读取负载,并在每次运行后打印计数器数值,展示工作集大小如何决定由存储层级中的哪一级来响应访问。
|
||||
|
||||
API 参考
|
||||
--------
|
||||
|
||||
.. include-build-file:: inc/esp_cache_cnt.inc
|
||||
@@ -11,6 +11,7 @@
|
||||
app_trace
|
||||
esp_trace
|
||||
esp_function_with_shared_stack
|
||||
:SOC_CACHE_CNT_SUPPORTED: cache_cnt
|
||||
chip_revision
|
||||
console
|
||||
efuse
|
||||
|
||||
Reference in New Issue
Block a user