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
@@ -69,7 +69,8 @@ if(NOT non_os_build)
|
||||
"port/${target}/esp_clk_tree.c"
|
||||
"spi_bus_lock.c"
|
||||
"heap_align_hw.c"
|
||||
"clk_utils.c")
|
||||
"clk_utils.c"
|
||||
"esp_cache_cnt.c")
|
||||
if(CONFIG_SOC_USB_OTG_SUPPORTED)
|
||||
list(APPEND srcs "usb_phy/usb_phy.c")
|
||||
endif()
|
||||
|
||||
164
components/esp_hw_support/esp_cache_cnt.c
Normal file
164
components/esp_hw_support/esp_cache_cnt.c
Normal file
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/*
|
||||
* Chip-agnostic implementation of the cache access counter API, built on
|
||||
* top of the cache profile counter functions of hal/cache_ll.h and the
|
||||
* unit descriptor table in soc/cache_periph.h.
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "esp_cache_cnt.h"
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
float esp_cache_cnt_miss_ratio(const esp_cache_cnt_data_t *data)
|
||||
{
|
||||
const uint32_t needed = ESP_CACHE_CNT_VALID_ACCESSES | ESP_CACHE_CNT_VALID_LINE_FILLS;
|
||||
if ((data->valid_mask & needed) != needed || data->accesses == 0) {
|
||||
return 0.0f;
|
||||
}
|
||||
return (float)data->line_fills / (float)data->accesses;
|
||||
}
|
||||
|
||||
#if SOC_CACHE_CNT_SUPPORTED
|
||||
|
||||
#include "hal/cache_ll.h"
|
||||
|
||||
size_t esp_cache_cnt_num_units(void)
|
||||
{
|
||||
return SOC_CACHE_CNT_UNITS_NUM;
|
||||
}
|
||||
|
||||
esp_err_t esp_cache_cnt_get_unit_info(size_t unit, esp_cache_cnt_unit_info_t *out)
|
||||
{
|
||||
if (unit >= SOC_CACHE_CNT_UNITS_NUM || out == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
const cache_profile_counter_unit_t *desc = &cache_periph_profile_counter_units[unit];
|
||||
out->name = desc->name;
|
||||
out->cache_level = desc->level;
|
||||
out->core_id = desc->core_id;
|
||||
out->traffic_type = desc->traffic;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_cache_cnt_start(void)
|
||||
{
|
||||
cache_ll_clear_profile_counter();
|
||||
cache_ll_enable_profile_counter(true);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_cache_cnt_stop(void)
|
||||
{
|
||||
cache_ll_enable_profile_counter(false);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_cache_cnt_clear(void)
|
||||
{
|
||||
cache_ll_clear_profile_counter();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_cache_cnt_get(size_t unit, esp_cache_cnt_data_t *out)
|
||||
{
|
||||
if (unit >= SOC_CACHE_CNT_UNITS_NUM || out == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
*out = (esp_cache_cnt_data_t) { 0 };
|
||||
if (cache_ll_get_profile_counter(unit, CACHE_PROFILE_COUNTER_HIT, &out->accesses)) {
|
||||
out->valid_mask |= ESP_CACHE_CNT_VALID_ACCESSES;
|
||||
}
|
||||
if (cache_ll_get_profile_counter(unit, CACHE_PROFILE_COUNTER_MISS, &out->stall_events)) {
|
||||
out->valid_mask |= ESP_CACHE_CNT_VALID_STALL_EVENTS;
|
||||
}
|
||||
if (cache_ll_get_profile_counter(unit, CACHE_PROFILE_COUNTER_CONFLICT, &out->conflicts)) {
|
||||
out->valid_mask |= ESP_CACHE_CNT_VALID_CONFLICTS;
|
||||
}
|
||||
if (cache_ll_get_profile_counter(unit, CACHE_PROFILE_COUNTER_NXTLVL_RD, &out->line_fills)) {
|
||||
out->valid_mask |= ESP_CACHE_CNT_VALID_LINE_FILLS;
|
||||
}
|
||||
if (cache_ll_get_profile_counter(unit, CACHE_PROFILE_COUNTER_NXTLVL_WR, &out->writebacks)) {
|
||||
out->valid_mask |= ESP_CACHE_CNT_VALID_WRITEBACKS;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void print_counter(FILE *out, const esp_cache_cnt_data_t *data, uint32_t flag, uint32_t value)
|
||||
{
|
||||
if (data->valid_mask & flag) {
|
||||
fprintf(out, " %12" PRIu32, value);
|
||||
} else {
|
||||
fprintf(out, " %12s", "-");
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t esp_cache_cnt_dump(FILE *out)
|
||||
{
|
||||
if (out == NULL) {
|
||||
out = stdout;
|
||||
}
|
||||
fprintf(out, "%-20s %12s %12s %12s %12s %10s\n",
|
||||
"unit", "accesses", "line fills", "writebacks", "conflicts", "miss rate");
|
||||
for (size_t unit = 0; unit < SOC_CACHE_CNT_UNITS_NUM; unit++) {
|
||||
esp_cache_cnt_unit_info_t info;
|
||||
esp_cache_cnt_data_t data;
|
||||
esp_cache_cnt_get_unit_info(unit, &info);
|
||||
esp_cache_cnt_get(unit, &data);
|
||||
fprintf(out, "%-20s", info.name);
|
||||
print_counter(out, &data, ESP_CACHE_CNT_VALID_ACCESSES, data.accesses);
|
||||
print_counter(out, &data, ESP_CACHE_CNT_VALID_LINE_FILLS, data.line_fills);
|
||||
print_counter(out, &data, ESP_CACHE_CNT_VALID_WRITEBACKS, data.writebacks);
|
||||
print_counter(out, &data, ESP_CACHE_CNT_VALID_CONFLICTS, data.conflicts);
|
||||
fprintf(out, " %9.2f%%\n", 100.0f * esp_cache_cnt_miss_ratio(&data));
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#else // !SOC_CACHE_CNT_SUPPORTED
|
||||
|
||||
size_t esp_cache_cnt_num_units(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
esp_err_t esp_cache_cnt_get_unit_info(size_t unit, esp_cache_cnt_unit_info_t *out)
|
||||
{
|
||||
(void) unit;
|
||||
(void) out;
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
esp_err_t esp_cache_cnt_start(void)
|
||||
{
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
esp_err_t esp_cache_cnt_stop(void)
|
||||
{
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
esp_err_t esp_cache_cnt_clear(void)
|
||||
{
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
esp_err_t esp_cache_cnt_get(size_t unit, esp_cache_cnt_data_t *out)
|
||||
{
|
||||
(void) unit;
|
||||
(void) out;
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
esp_err_t esp_cache_cnt_dump(FILE *out)
|
||||
{
|
||||
(void) out;
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
#endif // !SOC_CACHE_CNT_SUPPORTED
|
||||
168
components/esp_hw_support/include/esp_cache_cnt.h
Normal file
168
components/esp_hw_support/include/esp_cache_cnt.h
Normal file
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include "esp_err.h"
|
||||
#include "soc/cache_periph.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Cache access counter API.
|
||||
*
|
||||
* 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 (e.g. "instruction fetches from core 0 into the L1 cache").
|
||||
* Applications enumerate the units at runtime with esp_cache_cnt_num_units()
|
||||
* and esp_cache_cnt_get_unit_info(), so they keep working when a new chip
|
||||
* adds or removes units.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Description of one counter unit.
|
||||
*/
|
||||
typedef struct {
|
||||
const char *name; /*!< Short human-readable name, e.g. "l1-icache-core0" */
|
||||
uint8_t cache_level; /*!< Cache level the counters belong to, counting from the CPU.
|
||||
On most chips there is a single level (the flash/PSRAM cache);
|
||||
on the ESP32-P4, level 1 is the L1 cache in front of internal
|
||||
memory and level 2 is the flash/PSRAM cache. */
|
||||
cache_profile_traffic_t traffic_type; /*!< Kind of traffic observed */
|
||||
int8_t core_id; /*!< Core the traffic originates from, or -1 if unknown/mixed */
|
||||
} esp_cache_cnt_unit_info_t;
|
||||
|
||||
/**
|
||||
* @name Flags for esp_cache_cnt_data_t::valid_mask
|
||||
*
|
||||
* Not every counter exists for every unit (e.g. instruction buses have no
|
||||
* write-back counter). A field of esp_cache_cnt_data_t is only meaningful if
|
||||
* the corresponding flag is set.
|
||||
* @{
|
||||
*/
|
||||
#define ESP_CACHE_CNT_VALID_ACCESSES (1 << 0)
|
||||
#define ESP_CACHE_CNT_VALID_STALL_EVENTS (1 << 1)
|
||||
#define ESP_CACHE_CNT_VALID_CONFLICTS (1 << 2)
|
||||
#define ESP_CACHE_CNT_VALID_LINE_FILLS (1 << 3)
|
||||
#define ESP_CACHE_CNT_VALID_WRITEBACKS (1 << 4)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief Counter values for one unit.
|
||||
*
|
||||
* Note that the hardware "hit" and "miss" counters do not directly hold the
|
||||
* number of hit and missed accesses:
|
||||
* - accesses: the hit counter increments once for every access that completes,
|
||||
* whether or not it had to wait for a line fill first.
|
||||
* - stall_events: the miss counter increments repeatedly while an access is
|
||||
* stalled on a miss, so it grows roughly with the total miss latency. This is
|
||||
* only useful as a relative measure.
|
||||
* - line_fills: the next-level read counter increments once per line fetched
|
||||
* from the next level, so it is the true miss count.
|
||||
*
|
||||
* The miss ratio of a cache is therefore line_fills / accesses.
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t valid_mask; /*!< Bitwise OR of ESP_CACHE_CNT_VALID_* flags for the fields below */
|
||||
uint32_t accesses; /*!< Completed accesses (hardware hit counter) */
|
||||
uint32_t stall_events; /*!< Miss stall events; grows with total miss latency,
|
||||
NOT the number of missed accesses */
|
||||
uint32_t conflicts; /*!< Conflicts between requesters on this cache */
|
||||
uint32_t line_fills; /*!< Lines fetched from the next level (true miss count) */
|
||||
uint32_t writebacks; /*!< Lines written back to the next level. Only present for data
|
||||
traffic on chips with a write-back cache (PSRAM support,
|
||||
see SOC_CACHE_WRITEBACK_SUPPORTED). */
|
||||
} esp_cache_cnt_data_t;
|
||||
|
||||
/**
|
||||
* @brief Number of counter units on this chip.
|
||||
*
|
||||
* @return Number of units; 0 if the chip has no cache access counters.
|
||||
*/
|
||||
size_t esp_cache_cnt_num_units(void);
|
||||
|
||||
/**
|
||||
* @brief Get the description of a counter unit.
|
||||
*
|
||||
* @param unit Unit index, 0 to esp_cache_cnt_num_units() - 1
|
||||
* @param[out] out Unit description
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - ESP_ERR_INVALID_ARG if unit is out of range or out is NULL
|
||||
*/
|
||||
esp_err_t esp_cache_cnt_get_unit_info(size_t unit, esp_cache_cnt_unit_info_t *out);
|
||||
|
||||
/**
|
||||
* @brief Clear and enable all cache access counters.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - ESP_ERR_NOT_SUPPORTED if the target has no cache access counters
|
||||
*/
|
||||
esp_err_t esp_cache_cnt_start(void);
|
||||
|
||||
/**
|
||||
* @brief Disable all cache access counters. Counter values are retained.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - ESP_ERR_NOT_SUPPORTED if the target has no cache access counters
|
||||
*/
|
||||
esp_err_t esp_cache_cnt_stop(void);
|
||||
|
||||
/**
|
||||
* @brief Reset all cache access counters to zero. Counting state is not changed.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - ESP_ERR_NOT_SUPPORTED if the target has no cache access counters
|
||||
*/
|
||||
esp_err_t esp_cache_cnt_clear(void);
|
||||
|
||||
/**
|
||||
* @brief Read the current counter values for the given unit.
|
||||
*
|
||||
* @param unit Unit index, 0 to esp_cache_cnt_num_units() - 1
|
||||
* @param[out] out Counter values
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - ESP_ERR_INVALID_ARG if unit is out of range or out is NULL
|
||||
* - ESP_ERR_NOT_SUPPORTED if the target has no cache access counters
|
||||
*/
|
||||
esp_err_t esp_cache_cnt_get(size_t unit, esp_cache_cnt_data_t *out);
|
||||
|
||||
/**
|
||||
* @brief Miss ratio (0.0 to 1.0) computed from a set of counter values.
|
||||
*
|
||||
* @param data Counter values obtained from esp_cache_cnt_get()
|
||||
*
|
||||
* @return Miss ratio; 0.0 if the unit does not provide the counters needed
|
||||
* to compute it.
|
||||
*/
|
||||
float esp_cache_cnt_miss_ratio(const esp_cache_cnt_data_t *data);
|
||||
|
||||
/**
|
||||
* @brief Print a table with the current values of all cache access counters.
|
||||
*
|
||||
* @param out Output stream; if NULL, print to stdout
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - ESP_ERR_NOT_SUPPORTED if the target has no cache access counters
|
||||
*/
|
||||
esp_err_t esp_cache_cnt_dump(FILE *out);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "soc/cache_struct.h"
|
||||
#include "soc/ext_mem_defs.h"
|
||||
#include "rom/cache.h"
|
||||
#include "soc/cache_periph.h"
|
||||
#include "hal/cache_types.h"
|
||||
#include "hal/assert.h"
|
||||
#include "esp32c5/rom/cache.h"
|
||||
@@ -414,6 +415,58 @@ static inline uint32_t cache_ll_l1_get_access_error_intr_status(uint32_t cache_i
|
||||
return CACHE.l1_cache_acs_fail_int_st.val & mask;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Cache Profile Counter Related
|
||||
-----------------------------------------------------------------------------*/
|
||||
#define CACHE_LL_PROFILE_CNT_ENA_MASK (CACHE_L1_BUS0_CNT_ENA | CACHE_L1_BUS1_CNT_ENA)
|
||||
#define CACHE_LL_PROFILE_CNT_CLR_MASK (CACHE_L1_BUS0_CNT_CLR | CACHE_L1_BUS1_CNT_CLR)
|
||||
|
||||
/**
|
||||
* @brief Enable or disable the cache profile counters
|
||||
*
|
||||
* @param ena True to enable, false to disable
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void cache_ll_enable_profile_counter(bool ena)
|
||||
{
|
||||
if (ena) {
|
||||
REG_SET_BIT(CACHE_L1_CACHE_ACS_CNT_CTRL_REG, CACHE_LL_PROFILE_CNT_ENA_MASK);
|
||||
} else {
|
||||
REG_CLR_BIT(CACHE_L1_CACHE_ACS_CNT_CTRL_REG, CACHE_LL_PROFILE_CNT_ENA_MASK);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset all cache profile counters to zero
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void cache_ll_clear_profile_counter(void)
|
||||
{
|
||||
/* clear bits are write-to-trigger and self-clearing */
|
||||
REG_SET_BIT(CACHE_L1_CACHE_ACS_CNT_CTRL_REG, CACHE_LL_PROFILE_CNT_CLR_MASK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read one counter of a cache profile counter unit
|
||||
*
|
||||
* @param unit Unit index, 0 to SOC_CACHE_CNT_UNITS_NUM - 1
|
||||
* @param counter Counter to read
|
||||
* @param[out] value Counter value, only written if the counter exists
|
||||
*
|
||||
* @return True if the unit has this counter, false otherwise
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline bool cache_ll_get_profile_counter(int unit, cache_profile_counter_t counter, uint32_t *value)
|
||||
{
|
||||
HAL_ASSERT(unit < SOC_CACHE_CNT_UNITS_NUM);
|
||||
uint32_t reg = cache_periph_profile_counter_units[unit].counter_reg[counter];
|
||||
if (reg == 0) {
|
||||
return false;
|
||||
}
|
||||
*value = REG_READ(reg);
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <stdbool.h>
|
||||
#include "soc/extmem_reg.h"
|
||||
#include "soc/ext_mem_defs.h"
|
||||
#include "soc/cache_periph.h"
|
||||
#include "hal/cache_types.h"
|
||||
#include "hal/assert.h"
|
||||
#include "esp32c6/rom/cache.h"
|
||||
@@ -391,6 +392,58 @@ static inline uint32_t cache_ll_l1_get_access_error_intr_status(uint32_t cache_i
|
||||
return GET_PERI_REG_MASK(EXTMEM_L1_CACHE_ACS_FAIL_INT_ST_REG, mask);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Cache Profile Counter Related
|
||||
-----------------------------------------------------------------------------*/
|
||||
#define CACHE_LL_PROFILE_CNT_ENA_MASK (EXTMEM_L1_IBUS_CNT_ENA | EXTMEM_L1_DBUS_CNT_ENA)
|
||||
#define CACHE_LL_PROFILE_CNT_CLR_MASK (EXTMEM_L1_IBUS_CNT_CLR | EXTMEM_L1_DBUS_CNT_CLR)
|
||||
|
||||
/**
|
||||
* @brief Enable or disable the cache profile counters
|
||||
*
|
||||
* @param ena True to enable, false to disable
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void cache_ll_enable_profile_counter(bool ena)
|
||||
{
|
||||
if (ena) {
|
||||
REG_SET_BIT(EXTMEM_L1_CACHE_ACS_CNT_CTRL_REG, CACHE_LL_PROFILE_CNT_ENA_MASK);
|
||||
} else {
|
||||
REG_CLR_BIT(EXTMEM_L1_CACHE_ACS_CNT_CTRL_REG, CACHE_LL_PROFILE_CNT_ENA_MASK);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset all cache profile counters to zero
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void cache_ll_clear_profile_counter(void)
|
||||
{
|
||||
/* clear bits are write-to-trigger and self-clearing */
|
||||
REG_SET_BIT(EXTMEM_L1_CACHE_ACS_CNT_CTRL_REG, CACHE_LL_PROFILE_CNT_CLR_MASK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read one counter of a cache profile counter unit
|
||||
*
|
||||
* @param unit Unit index, 0 to SOC_CACHE_CNT_UNITS_NUM - 1
|
||||
* @param counter Counter to read
|
||||
* @param[out] value Counter value, only written if the counter exists
|
||||
*
|
||||
* @return True if the unit has this counter, false otherwise
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline bool cache_ll_get_profile_counter(int unit, cache_profile_counter_t counter, uint32_t *value)
|
||||
{
|
||||
HAL_ASSERT(unit < SOC_CACHE_CNT_UNITS_NUM);
|
||||
uint32_t reg = cache_periph_profile_counter_units[unit].counter_reg[counter];
|
||||
if (reg == 0) {
|
||||
return false;
|
||||
}
|
||||
*value = REG_READ(reg);
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "soc/cache_reg.h"
|
||||
#include "soc/cache_struct.h"
|
||||
#include "soc/ext_mem_defs.h"
|
||||
#include "soc/cache_periph.h"
|
||||
#include "hal/cache_types.h"
|
||||
#include "hal/assert.h"
|
||||
#include "esp32c61/rom/cache.h"
|
||||
@@ -413,6 +414,58 @@ static inline uint32_t cache_ll_l1_get_access_error_intr_status(uint32_t cache_i
|
||||
return CACHE.l1_cache_acs_fail_int_st.val & mask;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Cache Profile Counter Related
|
||||
-----------------------------------------------------------------------------*/
|
||||
#define CACHE_LL_PROFILE_CNT_ENA_MASK (CACHE_L1_BUS0_CNT_ENA | CACHE_L1_BUS1_CNT_ENA)
|
||||
#define CACHE_LL_PROFILE_CNT_CLR_MASK (CACHE_L1_BUS0_CNT_CLR | CACHE_L1_BUS1_CNT_CLR)
|
||||
|
||||
/**
|
||||
* @brief Enable or disable the cache profile counters
|
||||
*
|
||||
* @param ena True to enable, false to disable
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void cache_ll_enable_profile_counter(bool ena)
|
||||
{
|
||||
if (ena) {
|
||||
REG_SET_BIT(CACHE_L1_CACHE_ACS_CNT_CTRL_REG, CACHE_LL_PROFILE_CNT_ENA_MASK);
|
||||
} else {
|
||||
REG_CLR_BIT(CACHE_L1_CACHE_ACS_CNT_CTRL_REG, CACHE_LL_PROFILE_CNT_ENA_MASK);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset all cache profile counters to zero
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void cache_ll_clear_profile_counter(void)
|
||||
{
|
||||
/* clear bits are write-to-trigger and self-clearing */
|
||||
REG_SET_BIT(CACHE_L1_CACHE_ACS_CNT_CTRL_REG, CACHE_LL_PROFILE_CNT_CLR_MASK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read one counter of a cache profile counter unit
|
||||
*
|
||||
* @param unit Unit index, 0 to SOC_CACHE_CNT_UNITS_NUM - 1
|
||||
* @param counter Counter to read
|
||||
* @param[out] value Counter value, only written if the counter exists
|
||||
*
|
||||
* @return True if the unit has this counter, false otherwise
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline bool cache_ll_get_profile_counter(int unit, cache_profile_counter_t counter, uint32_t *value)
|
||||
{
|
||||
HAL_ASSERT(unit < SOC_CACHE_CNT_UNITS_NUM);
|
||||
uint32_t reg = cache_periph_profile_counter_units[unit].counter_reg[counter];
|
||||
if (reg == 0) {
|
||||
return false;
|
||||
}
|
||||
*value = REG_READ(reg);
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <stdbool.h>
|
||||
#include "soc/extmem_reg.h"
|
||||
#include "soc/ext_mem_defs.h"
|
||||
#include "soc/cache_periph.h"
|
||||
#include "hal/cache_types.h"
|
||||
#include "hal/assert.h"
|
||||
#include "esp32h2/rom/cache.h"
|
||||
@@ -389,6 +390,58 @@ static inline uint32_t cache_ll_l1_get_access_error_intr_status(uint32_t cache_i
|
||||
return GET_PERI_REG_MASK(CACHE_L1_CACHE_ACS_FAIL_INT_ST_REG, mask);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Cache Profile Counter Related
|
||||
-----------------------------------------------------------------------------*/
|
||||
#define CACHE_LL_PROFILE_CNT_ENA_MASK (CACHE_L1_BUS0_CNT_ENA | CACHE_L1_BUS1_CNT_ENA)
|
||||
#define CACHE_LL_PROFILE_CNT_CLR_MASK (CACHE_L1_BUS0_CNT_CLR | CACHE_L1_BUS1_CNT_CLR)
|
||||
|
||||
/**
|
||||
* @brief Enable or disable the cache profile counters
|
||||
*
|
||||
* @param ena True to enable, false to disable
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void cache_ll_enable_profile_counter(bool ena)
|
||||
{
|
||||
if (ena) {
|
||||
REG_SET_BIT(CACHE_L1_CACHE_ACS_CNT_CTRL_REG, CACHE_LL_PROFILE_CNT_ENA_MASK);
|
||||
} else {
|
||||
REG_CLR_BIT(CACHE_L1_CACHE_ACS_CNT_CTRL_REG, CACHE_LL_PROFILE_CNT_ENA_MASK);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset all cache profile counters to zero
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void cache_ll_clear_profile_counter(void)
|
||||
{
|
||||
/* clear bits are write-to-trigger and self-clearing */
|
||||
REG_SET_BIT(CACHE_L1_CACHE_ACS_CNT_CTRL_REG, CACHE_LL_PROFILE_CNT_CLR_MASK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read one counter of a cache profile counter unit
|
||||
*
|
||||
* @param unit Unit index, 0 to SOC_CACHE_CNT_UNITS_NUM - 1
|
||||
* @param counter Counter to read
|
||||
* @param[out] value Counter value, only written if the counter exists
|
||||
*
|
||||
* @return True if the unit has this counter, false otherwise
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline bool cache_ll_get_profile_counter(int unit, cache_profile_counter_t counter, uint32_t *value)
|
||||
{
|
||||
HAL_ASSERT(unit < SOC_CACHE_CNT_UNITS_NUM);
|
||||
uint32_t reg = cache_periph_profile_counter_units[unit].counter_reg[counter];
|
||||
if (reg == 0) {
|
||||
return false;
|
||||
}
|
||||
*value = REG_READ(reg);
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "soc/cache_reg.h"
|
||||
#include "soc/cache_struct.h"
|
||||
#include "soc/ext_mem_defs.h"
|
||||
#include "soc/cache_periph.h"
|
||||
#include "hal/cache_types.h"
|
||||
#include "hal/assert.h"
|
||||
#include "rom/cache.h"
|
||||
@@ -401,6 +402,58 @@ static inline uint32_t cache_ll_l1_get_access_error_intr_status(uint32_t cache_i
|
||||
return CACHE.l1_cache_acs_fail_int_st.val & mask;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Cache Profile Counter Related
|
||||
-----------------------------------------------------------------------------*/
|
||||
#define CACHE_LL_PROFILE_CNT_ENA_MASK (CACHE_L1_BUS0_CNT_ENA | CACHE_L1_BUS1_CNT_ENA)
|
||||
#define CACHE_LL_PROFILE_CNT_CLR_MASK (CACHE_L1_BUS0_CNT_CLR | CACHE_L1_BUS1_CNT_CLR)
|
||||
|
||||
/**
|
||||
* @brief Enable or disable the cache profile counters
|
||||
*
|
||||
* @param ena True to enable, false to disable
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void cache_ll_enable_profile_counter(bool ena)
|
||||
{
|
||||
if (ena) {
|
||||
REG_SET_BIT(CACHE_L1_CACHE_ACS_CNT_CTRL_REG, CACHE_LL_PROFILE_CNT_ENA_MASK);
|
||||
} else {
|
||||
REG_CLR_BIT(CACHE_L1_CACHE_ACS_CNT_CTRL_REG, CACHE_LL_PROFILE_CNT_ENA_MASK);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset all cache profile counters to zero
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void cache_ll_clear_profile_counter(void)
|
||||
{
|
||||
/* clear bits are write-to-trigger and self-clearing */
|
||||
REG_SET_BIT(CACHE_L1_CACHE_ACS_CNT_CTRL_REG, CACHE_LL_PROFILE_CNT_CLR_MASK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read one counter of a cache profile counter unit
|
||||
*
|
||||
* @param unit Unit index, 0 to SOC_CACHE_CNT_UNITS_NUM - 1
|
||||
* @param counter Counter to read
|
||||
* @param[out] value Counter value, only written if the counter exists
|
||||
*
|
||||
* @return True if the unit has this counter, false otherwise
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline bool cache_ll_get_profile_counter(int unit, cache_profile_counter_t counter, uint32_t *value)
|
||||
{
|
||||
HAL_ASSERT(unit < SOC_CACHE_CNT_UNITS_NUM);
|
||||
uint32_t reg = cache_periph_profile_counter_units[unit].counter_reg[counter];
|
||||
if (reg == 0) {
|
||||
return false;
|
||||
}
|
||||
*value = REG_READ(reg);
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "soc/cache_reg.h"
|
||||
#include "soc/cache_struct.h"
|
||||
#include "soc/ext_mem_defs.h"
|
||||
#include "soc/cache_periph.h"
|
||||
#include "hal/cache_types.h"
|
||||
#include "hal/assert.h"
|
||||
#include "rom/cache.h"
|
||||
@@ -982,6 +983,60 @@ static inline uint32_t cache_ll_l1_get_access_error_intr_status(uint32_t cache_i
|
||||
return CACHE.l1_cache_acs_fail_int_st.val & mask;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Cache Profile Counter Related
|
||||
-----------------------------------------------------------------------------*/
|
||||
#define CACHE_LL_PROFILE_CNT_ENA_MASK (CACHE_L1_IBUS0_CNT_ENA | CACHE_L1_IBUS1_CNT_ENA | \
|
||||
CACHE_L1_DBUS0_CNT_ENA | CACHE_L1_DBUS1_CNT_ENA)
|
||||
#define CACHE_LL_PROFILE_CNT_CLR_MASK (CACHE_L1_IBUS0_CNT_CLR | CACHE_L1_IBUS1_CNT_CLR | \
|
||||
CACHE_L1_DBUS0_CNT_CLR | CACHE_L1_DBUS1_CNT_CLR)
|
||||
|
||||
/**
|
||||
* @brief Enable or disable the cache profile counters
|
||||
*
|
||||
* @param ena True to enable, false to disable
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void cache_ll_enable_profile_counter(bool ena)
|
||||
{
|
||||
if (ena) {
|
||||
REG_SET_BIT(CACHE_L1_CACHE_ACS_CNT_CTRL_REG, CACHE_LL_PROFILE_CNT_ENA_MASK);
|
||||
} else {
|
||||
REG_CLR_BIT(CACHE_L1_CACHE_ACS_CNT_CTRL_REG, CACHE_LL_PROFILE_CNT_ENA_MASK);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset all cache profile counters to zero
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void cache_ll_clear_profile_counter(void)
|
||||
{
|
||||
/* clear bits are write-to-trigger and self-clearing */
|
||||
REG_SET_BIT(CACHE_L1_CACHE_ACS_CNT_CTRL_REG, CACHE_LL_PROFILE_CNT_CLR_MASK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read one counter of a cache profile counter unit
|
||||
*
|
||||
* @param unit Unit index, 0 to SOC_CACHE_CNT_UNITS_NUM - 1
|
||||
* @param counter Counter to read
|
||||
* @param[out] value Counter value, only written if the counter exists
|
||||
*
|
||||
* @return True if the unit has this counter, false otherwise
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline bool cache_ll_get_profile_counter(int unit, cache_profile_counter_t counter, uint32_t *value)
|
||||
{
|
||||
HAL_ASSERT(unit < SOC_CACHE_CNT_UNITS_NUM);
|
||||
uint32_t reg = cache_periph_profile_counter_units[unit].counter_reg[counter];
|
||||
if (reg == 0) {
|
||||
return false;
|
||||
}
|
||||
*value = REG_READ(reg);
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "soc/cache_reg.h"
|
||||
#include "soc/cache_struct.h"
|
||||
#include "soc/ext_mem_defs.h"
|
||||
#include "soc/cache_periph.h"
|
||||
#include "hal/cache_types.h"
|
||||
#include "hal/config.h"
|
||||
#include "hal/assert.h"
|
||||
@@ -1397,6 +1398,67 @@ static inline uint32_t cache_ll_l2_get_access_error_intr_status(uint32_t cache_i
|
||||
return CACHE.l2_cache_acs_fail_int_st.val & mask;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Cache Profile Counter Related
|
||||
-----------------------------------------------------------------------------*/
|
||||
#define CACHE_LL_PROFILE_CNT_L1_ENA_MASK (CACHE_L1_IBUS0_CNT_ENA | CACHE_L1_IBUS1_CNT_ENA | \
|
||||
CACHE_L1_DBUS0_CNT_ENA | CACHE_L1_DBUS1_CNT_ENA)
|
||||
#define CACHE_LL_PROFILE_CNT_L1_CLR_MASK (CACHE_L1_IBUS0_CNT_CLR | CACHE_L1_IBUS1_CNT_CLR | \
|
||||
CACHE_L1_DBUS0_CNT_CLR | CACHE_L1_DBUS1_CNT_CLR)
|
||||
#define CACHE_LL_PROFILE_CNT_L2_ENA_MASK (CACHE_L2_IBUS0_CNT_ENA | CACHE_L2_IBUS1_CNT_ENA | \
|
||||
CACHE_L2_DBUS0_CNT_ENA | CACHE_L2_DBUS1_CNT_ENA)
|
||||
#define CACHE_LL_PROFILE_CNT_L2_CLR_MASK (CACHE_L2_IBUS0_CNT_CLR | CACHE_L2_IBUS1_CNT_CLR | \
|
||||
CACHE_L2_DBUS0_CNT_CLR | CACHE_L2_DBUS1_CNT_CLR)
|
||||
|
||||
/**
|
||||
* @brief Enable or disable the cache profile counters
|
||||
*
|
||||
* @param ena True to enable, false to disable
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void cache_ll_enable_profile_counter(bool ena)
|
||||
{
|
||||
if (ena) {
|
||||
REG_SET_BIT(CACHE_L1_CACHE_ACS_CNT_CTRL_REG, CACHE_LL_PROFILE_CNT_L1_ENA_MASK);
|
||||
REG_SET_BIT(CACHE_L2_CACHE_ACS_CNT_CTRL_REG, CACHE_LL_PROFILE_CNT_L2_ENA_MASK);
|
||||
} else {
|
||||
REG_CLR_BIT(CACHE_L1_CACHE_ACS_CNT_CTRL_REG, CACHE_LL_PROFILE_CNT_L1_ENA_MASK);
|
||||
REG_CLR_BIT(CACHE_L2_CACHE_ACS_CNT_CTRL_REG, CACHE_LL_PROFILE_CNT_L2_ENA_MASK);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset all cache profile counters to zero
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void cache_ll_clear_profile_counter(void)
|
||||
{
|
||||
/* clear bits are write-to-trigger and self-clearing */
|
||||
REG_SET_BIT(CACHE_L1_CACHE_ACS_CNT_CTRL_REG, CACHE_LL_PROFILE_CNT_L1_CLR_MASK);
|
||||
REG_SET_BIT(CACHE_L2_CACHE_ACS_CNT_CTRL_REG, CACHE_LL_PROFILE_CNT_L2_CLR_MASK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read one counter of a cache profile counter unit
|
||||
*
|
||||
* @param unit Unit index, 0 to SOC_CACHE_CNT_UNITS_NUM - 1
|
||||
* @param counter Counter to read
|
||||
* @param[out] value Counter value, only written if the counter exists
|
||||
*
|
||||
* @return True if the unit has this counter, false otherwise
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline bool cache_ll_get_profile_counter(int unit, cache_profile_counter_t counter, uint32_t *value)
|
||||
{
|
||||
HAL_ASSERT(unit < SOC_CACHE_CNT_UNITS_NUM);
|
||||
uint32_t reg = cache_periph_profile_counter_units[unit].counter_reg[counter];
|
||||
if (reg == 0) {
|
||||
return false;
|
||||
}
|
||||
*value = REG_READ(reg);
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "soc/cache_reg.h"
|
||||
#include "soc/cache_struct.h"
|
||||
#include "soc/ext_mem_defs.h"
|
||||
#include "soc/cache_periph.h"
|
||||
#include "hal/cache_types.h"
|
||||
#include "hal/assert.h"
|
||||
#include "esp32s31/rom/cache.h"
|
||||
@@ -1088,6 +1089,60 @@ static inline uint32_t cache_ll_l1_get_access_error_intr_status(uint32_t cache_i
|
||||
return CACHE.l1_cache_acs_fail_int_st.val & mask;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Cache Profile Counter Related
|
||||
-----------------------------------------------------------------------------*/
|
||||
#define CACHE_LL_PROFILE_CNT_L1_ENA_MASK (CACHE_L1_IBUS0_CNT_ENA | CACHE_L1_IBUS1_CNT_ENA | \
|
||||
CACHE_L1_DBUS0_CNT_ENA | CACHE_L1_DBUS1_CNT_ENA)
|
||||
#define CACHE_LL_PROFILE_CNT_L1_CLR_MASK (CACHE_L1_IBUS0_CNT_CLR | CACHE_L1_IBUS1_CNT_CLR | \
|
||||
CACHE_L1_DBUS0_CNT_CLR | CACHE_L1_DBUS1_CNT_CLR)
|
||||
|
||||
/**
|
||||
* @brief Enable or disable the cache profile counters
|
||||
*
|
||||
* @param ena True to enable, false to disable
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void cache_ll_enable_profile_counter(bool ena)
|
||||
{
|
||||
if (ena) {
|
||||
REG_SET_BIT(CACHE_L1_CACHE_ACS_CNT_CTRL_REG, CACHE_LL_PROFILE_CNT_L1_ENA_MASK);
|
||||
} else {
|
||||
REG_CLR_BIT(CACHE_L1_CACHE_ACS_CNT_CTRL_REG, CACHE_LL_PROFILE_CNT_L1_ENA_MASK);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset all cache profile counters to zero
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void cache_ll_clear_profile_counter(void)
|
||||
{
|
||||
/* clear bits are write-to-trigger and self-clearing */
|
||||
REG_SET_BIT(CACHE_L1_CACHE_ACS_CNT_CTRL_REG, CACHE_LL_PROFILE_CNT_L1_CLR_MASK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read one counter of a cache profile counter unit
|
||||
*
|
||||
* @param unit Unit index, 0 to SOC_CACHE_CNT_UNITS_NUM - 1
|
||||
* @param counter Counter to read
|
||||
* @param[out] value Counter value, only written if the counter exists
|
||||
*
|
||||
* @return True if the unit has this counter, false otherwise
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline bool cache_ll_get_profile_counter(int unit, cache_profile_counter_t counter, uint32_t *value)
|
||||
{
|
||||
HAL_ASSERT(unit < SOC_CACHE_CNT_UNITS_NUM);
|
||||
uint32_t reg = cache_periph_profile_counter_units[unit].counter_reg[counter];
|
||||
if (reg == 0) {
|
||||
return false;
|
||||
}
|
||||
*value = REG_READ(reg);
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -66,6 +66,10 @@ if(CONFIG_SOC_DEBUG_PROBE_SUPPORTED)
|
||||
list(APPEND srcs "${target_folder}/debug_probe_periph.c")
|
||||
endif()
|
||||
|
||||
if(CONFIG_SOC_CACHE_CNT_SUPPORTED)
|
||||
list(APPEND srcs "${target_folder}/cache_periph.c")
|
||||
endif()
|
||||
|
||||
if(CONFIG_SOC_MPI_SUPPORTED)
|
||||
list(APPEND srcs "${target_folder}/mpi_periph.c")
|
||||
endif()
|
||||
|
||||
41
components/soc/esp32c5/cache_periph.c
Normal file
41
components/soc/esp32c5/cache_periph.c
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*/
|
||||
|
||||
#include "soc/cache_reg.h"
|
||||
#include "soc/cache_periph.h"
|
||||
|
||||
/*
|
||||
* ESP32-C5 cache profile counter units.
|
||||
*
|
||||
* Single cache level shared by instructions and data (the flash/PSRAM
|
||||
* cache, 32-byte lines), with two request buses: bus0 carries instruction
|
||||
* fetches, bus1 carries data accesses. Counter semantics match the
|
||||
* ESP32-P4. The hit/miss/conflict counters use the BUS0/BUS1 register
|
||||
* names while the corresponding next-level counters use the DBUS0/DBUS1
|
||||
* names. Only the CPU request buses are exposed here.
|
||||
*/
|
||||
|
||||
const cache_profile_counter_unit_t cache_periph_profile_counter_units[SOC_CACHE_CNT_UNITS_NUM] = {
|
||||
{
|
||||
.name = "l1-cache-ibus", .level = 1, .traffic = CACHE_PROFILE_TRAFFIC_INST, .core_id = 0,
|
||||
.counter_reg = {
|
||||
[CACHE_PROFILE_COUNTER_HIT] = CACHE_L1_BUS0_ACS_HIT_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_MISS] = CACHE_L1_BUS0_ACS_MISS_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_CONFLICT] = CACHE_L1_BUS0_ACS_CONFLICT_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_NXTLVL_RD] = CACHE_L1_DBUS0_ACS_NXTLVL_RD_CNT_REG,
|
||||
},
|
||||
},
|
||||
{
|
||||
.name = "l1-cache-dbus", .level = 1, .traffic = CACHE_PROFILE_TRAFFIC_DATA, .core_id = 0,
|
||||
.counter_reg = {
|
||||
[CACHE_PROFILE_COUNTER_HIT] = CACHE_L1_BUS1_ACS_HIT_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_MISS] = CACHE_L1_BUS1_ACS_MISS_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_CONFLICT] = CACHE_L1_BUS1_ACS_CONFLICT_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_NXTLVL_RD] = CACHE_L1_DBUS1_ACS_NXTLVL_RD_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_NXTLVL_WR] = CACHE_L1_DBUS1_ACS_NXTLVL_WR_CNT_REG,
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -423,6 +423,14 @@ config SOC_CACHE_FREEZE_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_CACHE_CNT_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_CACHE_CNT_UNITS_NUM
|
||||
int
|
||||
default 2
|
||||
|
||||
config SOC_CPU_CORES_NUM
|
||||
int
|
||||
default 1
|
||||
|
||||
@@ -155,6 +155,8 @@
|
||||
#define SOC_SHARED_IDCACHE_SUPPORTED 1 //Shared Cache for both instructions and data
|
||||
#define SOC_CACHE_WRITEBACK_SUPPORTED 1
|
||||
#define SOC_CACHE_FREEZE_SUPPORTED 1
|
||||
#define SOC_CACHE_CNT_SUPPORTED 1
|
||||
#define SOC_CACHE_CNT_UNITS_NUM 2 //Number of cache profile counter units
|
||||
|
||||
/*-------------------------- CPU CAPS ----------------------------------------*/
|
||||
#define SOC_CPU_CORES_NUM (1U)
|
||||
|
||||
40
components/soc/esp32c6/cache_periph.c
Normal file
40
components/soc/esp32c6/cache_periph.c
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*/
|
||||
|
||||
#include "soc/extmem_reg.h"
|
||||
#include "soc/cache_periph.h"
|
||||
|
||||
/*
|
||||
* ESP32-C6 cache profile counter units.
|
||||
*
|
||||
* Single cache level shared by instructions and data (the flash cache,
|
||||
* 32-byte lines), with one instruction bus and one data bus. Counter
|
||||
* semantics match the ESP32-P4. There is one next-level counter per bus
|
||||
* (no read/write split), mapped here to line_fills. The cache is
|
||||
* read-only (no PSRAM, no write-back — see SOC_CACHE_WRITEBACK_SUPPORTED),
|
||||
* so there are no write-back counters.
|
||||
*/
|
||||
|
||||
const cache_profile_counter_unit_t cache_periph_profile_counter_units[SOC_CACHE_CNT_UNITS_NUM] = {
|
||||
{
|
||||
.name = "l1-cache-ibus", .level = 1, .traffic = CACHE_PROFILE_TRAFFIC_INST, .core_id = 0,
|
||||
.counter_reg = {
|
||||
[CACHE_PROFILE_COUNTER_HIT] = EXTMEM_L1_IBUS_ACS_HIT_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_MISS] = EXTMEM_L1_IBUS_ACS_MISS_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_CONFLICT] = EXTMEM_L1_IBUS_ACS_CONFLICT_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_NXTLVL_RD] = EXTMEM_L1_IBUS_ACS_NXTLVL_CNT_REG,
|
||||
},
|
||||
},
|
||||
{
|
||||
.name = "l1-cache-dbus", .level = 1, .traffic = CACHE_PROFILE_TRAFFIC_DATA, .core_id = 0,
|
||||
.counter_reg = {
|
||||
[CACHE_PROFILE_COUNTER_HIT] = EXTMEM_L1_DBUS_ACS_HIT_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_MISS] = EXTMEM_L1_DBUS_ACS_MISS_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_CONFLICT] = EXTMEM_L1_DBUS_ACS_CONFLICT_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_NXTLVL_RD] = EXTMEM_L1_DBUS_ACS_NXTLVL_CNT_REG,
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -375,6 +375,14 @@ config SOC_CACHE_FREEZE_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_CACHE_CNT_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_CACHE_CNT_UNITS_NUM
|
||||
int
|
||||
default 2
|
||||
|
||||
config SOC_CPU_CORES_NUM
|
||||
int
|
||||
default 1
|
||||
|
||||
@@ -140,6 +140,8 @@
|
||||
/*-------------------------- CACHE CAPS --------------------------------------*/
|
||||
#define SOC_SHARED_IDCACHE_SUPPORTED 1 //Shared Cache for both instructions and data
|
||||
#define SOC_CACHE_FREEZE_SUPPORTED 1
|
||||
#define SOC_CACHE_CNT_SUPPORTED 1
|
||||
#define SOC_CACHE_CNT_UNITS_NUM 2 //Number of cache profile counter units
|
||||
|
||||
/*-------------------------- CPU CAPS ----------------------------------------*/
|
||||
#define SOC_CPU_CORES_NUM (1U)
|
||||
|
||||
40
components/soc/esp32c61/cache_periph.c
Normal file
40
components/soc/esp32c61/cache_periph.c
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*/
|
||||
|
||||
#include "soc/cache_reg.h"
|
||||
#include "soc/cache_periph.h"
|
||||
|
||||
/*
|
||||
* ESP32-C61 cache profile counter units.
|
||||
*
|
||||
* Single cache level shared by instructions and data (the flash/PSRAM
|
||||
* cache), with two request buses: bus0 carries instruction fetches, bus1
|
||||
* carries data accesses (same bus arrangement as the ESP32-C5). bus0's
|
||||
* next-level counters use the BUS0 register names while bus1's use the
|
||||
* DBUS1 names.
|
||||
*/
|
||||
|
||||
const cache_profile_counter_unit_t cache_periph_profile_counter_units[SOC_CACHE_CNT_UNITS_NUM] = {
|
||||
{
|
||||
.name = "l1-cache-ibus", .level = 1, .traffic = CACHE_PROFILE_TRAFFIC_INST, .core_id = 0,
|
||||
.counter_reg = {
|
||||
[CACHE_PROFILE_COUNTER_HIT] = CACHE_L1_BUS0_ACS_HIT_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_MISS] = CACHE_L1_BUS0_ACS_MISS_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_CONFLICT] = CACHE_L1_BUS0_ACS_CONFLICT_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_NXTLVL_RD] = CACHE_L1_BUS0_ACS_NXTLVL_RD_CNT_REG,
|
||||
},
|
||||
},
|
||||
{
|
||||
.name = "l1-cache-dbus", .level = 1, .traffic = CACHE_PROFILE_TRAFFIC_DATA, .core_id = 0,
|
||||
.counter_reg = {
|
||||
[CACHE_PROFILE_COUNTER_HIT] = CACHE_L1_BUS1_ACS_HIT_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_MISS] = CACHE_L1_BUS1_ACS_MISS_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_CONFLICT] = CACHE_L1_BUS1_ACS_CONFLICT_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_NXTLVL_RD] = CACHE_L1_DBUS1_ACS_NXTLVL_RD_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_NXTLVL_WR] = CACHE_L1_DBUS1_ACS_NXTLVL_WR_CNT_REG,
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -303,6 +303,14 @@ config SOC_CACHE_FREEZE_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_CACHE_CNT_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_CACHE_CNT_UNITS_NUM
|
||||
int
|
||||
default 2
|
||||
|
||||
config SOC_CPU_CORES_NUM
|
||||
int
|
||||
default 1
|
||||
|
||||
@@ -117,6 +117,8 @@
|
||||
#define SOC_SHARED_IDCACHE_SUPPORTED 1 //Shared Cache for both instructions and data
|
||||
#define SOC_CACHE_WRITEBACK_SUPPORTED 1
|
||||
#define SOC_CACHE_FREEZE_SUPPORTED 1
|
||||
#define SOC_CACHE_CNT_SUPPORTED 1
|
||||
#define SOC_CACHE_CNT_UNITS_NUM 2 //Number of cache profile counter units
|
||||
|
||||
/*-------------------------- CPU CAPS ----------------------------------------*/
|
||||
#define SOC_CPU_CORES_NUM (1U)
|
||||
|
||||
40
components/soc/esp32h2/cache_periph.c
Normal file
40
components/soc/esp32h2/cache_periph.c
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*/
|
||||
|
||||
#include "soc/cache_reg.h"
|
||||
#include "soc/cache_periph.h"
|
||||
|
||||
/*
|
||||
* ESP32-H2 cache profile counter units.
|
||||
*
|
||||
* Single cache level shared by instructions and data (the flash cache,
|
||||
* 32-byte lines), with two request buses: bus0 carries instruction
|
||||
* fetches, bus1 carries data accesses. There is one next-level counter
|
||||
* per bus (no read/write split), mapped here to line_fills. The cache is
|
||||
* read-only (no PSRAM, no write-back — see SOC_CACHE_WRITEBACK_SUPPORTED),
|
||||
* so there are no write-back counters.
|
||||
*/
|
||||
|
||||
const cache_profile_counter_unit_t cache_periph_profile_counter_units[SOC_CACHE_CNT_UNITS_NUM] = {
|
||||
{
|
||||
.name = "l1-cache-ibus", .level = 1, .traffic = CACHE_PROFILE_TRAFFIC_INST, .core_id = 0,
|
||||
.counter_reg = {
|
||||
[CACHE_PROFILE_COUNTER_HIT] = CACHE_L1_BUS0_ACS_HIT_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_MISS] = CACHE_L1_BUS0_ACS_MISS_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_CONFLICT] = CACHE_L1_BUS0_ACS_CONFLICT_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_NXTLVL_RD] = CACHE_L1_BUS0_ACS_NXTLVL_CNT_REG,
|
||||
},
|
||||
},
|
||||
{
|
||||
.name = "l1-cache-dbus", .level = 1, .traffic = CACHE_PROFILE_TRAFFIC_DATA, .core_id = 0,
|
||||
.counter_reg = {
|
||||
[CACHE_PROFILE_COUNTER_HIT] = CACHE_L1_BUS1_ACS_HIT_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_MISS] = CACHE_L1_BUS1_ACS_MISS_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_CONFLICT] = CACHE_L1_BUS1_ACS_CONFLICT_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_NXTLVL_RD] = CACHE_L1_BUS1_ACS_NXTLVL_CNT_REG,
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -379,6 +379,14 @@ config SOC_CACHE_FREEZE_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_CACHE_CNT_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_CACHE_CNT_UNITS_NUM
|
||||
int
|
||||
default 2
|
||||
|
||||
config SOC_CPU_CORES_NUM
|
||||
int
|
||||
default 1
|
||||
|
||||
@@ -161,6 +161,8 @@
|
||||
/*-------------------------- CACHE CAPS --------------------------------------*/
|
||||
#define SOC_SHARED_IDCACHE_SUPPORTED 1 //Shared Cache for both instructions and data
|
||||
#define SOC_CACHE_FREEZE_SUPPORTED 1
|
||||
#define SOC_CACHE_CNT_SUPPORTED 1
|
||||
#define SOC_CACHE_CNT_UNITS_NUM 2 //Number of cache profile counter units
|
||||
|
||||
/*-------------------------- CPU CAPS ----------------------------------------*/
|
||||
#define SOC_CPU_CORES_NUM (1U)
|
||||
|
||||
39
components/soc/esp32h21/cache_periph.c
Normal file
39
components/soc/esp32h21/cache_periph.c
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*/
|
||||
|
||||
#include "soc/cache_reg.h"
|
||||
#include "soc/cache_periph.h"
|
||||
|
||||
/*
|
||||
* ESP32-H21 cache profile counter units.
|
||||
*
|
||||
* Single cache level shared by instructions and data (the flash cache),
|
||||
* with two request buses: bus0 carries instruction fetches, bus1 carries
|
||||
* data accesses (same bus arrangement as the ESP32-C5). The cache is
|
||||
* read-only (no PSRAM, no write-back — see SOC_CACHE_WRITEBACK_SUPPORTED),
|
||||
* so no write-back counters are exposed.
|
||||
*/
|
||||
|
||||
const cache_profile_counter_unit_t cache_periph_profile_counter_units[SOC_CACHE_CNT_UNITS_NUM] = {
|
||||
{
|
||||
.name = "l1-cache-ibus", .level = 1, .traffic = CACHE_PROFILE_TRAFFIC_INST, .core_id = 0,
|
||||
.counter_reg = {
|
||||
[CACHE_PROFILE_COUNTER_HIT] = CACHE_L1_BUS0_ACS_HIT_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_MISS] = CACHE_L1_BUS0_ACS_MISS_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_CONFLICT] = CACHE_L1_BUS0_ACS_CONFLICT_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_NXTLVL_RD] = CACHE_L1_BUS0_ACS_NXTLVL_RD_CNT_REG,
|
||||
},
|
||||
},
|
||||
{
|
||||
.name = "l1-cache-dbus", .level = 1, .traffic = CACHE_PROFILE_TRAFFIC_DATA, .core_id = 0,
|
||||
.counter_reg = {
|
||||
[CACHE_PROFILE_COUNTER_HIT] = CACHE_L1_BUS1_ACS_HIT_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_MISS] = CACHE_L1_BUS1_ACS_MISS_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_CONFLICT] = CACHE_L1_BUS1_ACS_CONFLICT_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_NXTLVL_RD] = CACHE_L1_BUS1_ACS_NXTLVL_RD_CNT_REG,
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -351,6 +351,14 @@ config SOC_CACHE_FREEZE_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_CACHE_CNT_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_CACHE_CNT_UNITS_NUM
|
||||
int
|
||||
default 2
|
||||
|
||||
config SOC_CPU_CORES_NUM
|
||||
int
|
||||
default 1
|
||||
|
||||
@@ -145,6 +145,8 @@
|
||||
/*-------------------------- CACHE CAPS --------------------------------------*/
|
||||
#define SOC_SHARED_IDCACHE_SUPPORTED 1 //Shared Cache for both instructions and data
|
||||
#define SOC_CACHE_FREEZE_SUPPORTED 1
|
||||
#define SOC_CACHE_CNT_SUPPORTED 1
|
||||
#define SOC_CACHE_CNT_UNITS_NUM 2 //Number of cache profile counter units
|
||||
|
||||
/*-------------------------- CPU CAPS ----------------------------------------*/
|
||||
#define SOC_CPU_CORES_NUM (1U)
|
||||
|
||||
58
components/soc/esp32h4/cache_periph.c
Normal file
58
components/soc/esp32h4/cache_periph.c
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*/
|
||||
|
||||
#include "soc/cache_reg.h"
|
||||
#include "soc/cache_periph.h"
|
||||
|
||||
/*
|
||||
* ESP32-H4 cache profile counter units.
|
||||
*
|
||||
* Single cache level (the flash/PSRAM cache); each core accesses it
|
||||
* through an instruction bus (ibus0/ibus1) and a data bus (dbus0/dbus1),
|
||||
* each with hit/miss/conflict/next-level counters (next-level write
|
||||
* counters on the data buses only).
|
||||
*/
|
||||
|
||||
const cache_profile_counter_unit_t cache_periph_profile_counter_units[SOC_CACHE_CNT_UNITS_NUM] = {
|
||||
{
|
||||
.name = "l1-cache-inst-core0", .level = 1, .traffic = CACHE_PROFILE_TRAFFIC_INST, .core_id = 0,
|
||||
.counter_reg = {
|
||||
[CACHE_PROFILE_COUNTER_HIT] = CACHE_L1_IBUS0_ACS_HIT_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_MISS] = CACHE_L1_IBUS0_ACS_MISS_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_CONFLICT] = CACHE_L1_IBUS0_ACS_CONFLICT_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_NXTLVL_RD] = CACHE_L1_IBUS0_ACS_NXTLVL_RD_CNT_REG,
|
||||
},
|
||||
},
|
||||
{
|
||||
.name = "l1-cache-inst-core1", .level = 1, .traffic = CACHE_PROFILE_TRAFFIC_INST, .core_id = 1,
|
||||
.counter_reg = {
|
||||
[CACHE_PROFILE_COUNTER_HIT] = CACHE_L1_IBUS1_ACS_HIT_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_MISS] = CACHE_L1_IBUS1_ACS_MISS_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_CONFLICT] = CACHE_L1_IBUS1_ACS_CONFLICT_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_NXTLVL_RD] = CACHE_L1_IBUS1_ACS_NXTLVL_RD_CNT_REG,
|
||||
},
|
||||
},
|
||||
{
|
||||
.name = "l1-cache-data-core0", .level = 1, .traffic = CACHE_PROFILE_TRAFFIC_DATA, .core_id = 0,
|
||||
.counter_reg = {
|
||||
[CACHE_PROFILE_COUNTER_HIT] = CACHE_L1_DBUS0_ACS_HIT_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_MISS] = CACHE_L1_DBUS0_ACS_MISS_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_CONFLICT] = CACHE_L1_DBUS0_ACS_CONFLICT_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_NXTLVL_RD] = CACHE_L1_DBUS0_ACS_NXTLVL_RD_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_NXTLVL_WR] = CACHE_L1_DBUS0_ACS_NXTLVL_WR_CNT_REG,
|
||||
},
|
||||
},
|
||||
{
|
||||
.name = "l1-cache-data-core1", .level = 1, .traffic = CACHE_PROFILE_TRAFFIC_DATA, .core_id = 1,
|
||||
.counter_reg = {
|
||||
[CACHE_PROFILE_COUNTER_HIT] = CACHE_L1_DBUS1_ACS_HIT_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_MISS] = CACHE_L1_DBUS1_ACS_MISS_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_CONFLICT] = CACHE_L1_DBUS1_ACS_CONFLICT_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_NXTLVL_RD] = CACHE_L1_DBUS1_ACS_NXTLVL_RD_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_NXTLVL_WR] = CACHE_L1_DBUS1_ACS_NXTLVL_WR_CNT_REG,
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -355,6 +355,14 @@ config SOC_CACHE_FREEZE_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_CACHE_CNT_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_CACHE_CNT_UNITS_NUM
|
||||
int
|
||||
default 4
|
||||
|
||||
config SOC_CPU_CORES_NUM
|
||||
int
|
||||
default 2
|
||||
|
||||
@@ -152,6 +152,8 @@
|
||||
/*-------------------------- CACHE CAPS --------------------------------------*/
|
||||
#define SOC_CACHE_WRITEBACK_SUPPORTED 1
|
||||
#define SOC_CACHE_FREEZE_SUPPORTED 1
|
||||
#define SOC_CACHE_CNT_SUPPORTED 1
|
||||
#define SOC_CACHE_CNT_UNITS_NUM 4 //Number of cache profile counter units
|
||||
|
||||
/*-------------------------- CPU CAPS ----------------------------------------*/
|
||||
#define SOC_CPU_CORES_NUM (2U)
|
||||
|
||||
77
components/soc/esp32p4/cache_periph.c
Normal file
77
components/soc/esp32p4/cache_periph.c
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*/
|
||||
|
||||
#include "soc/cache_reg.h"
|
||||
#include "soc/cache_periph.h"
|
||||
|
||||
/*
|
||||
* ESP32-P4 cache profile counter units.
|
||||
*
|
||||
* Topology: per-core L1 instruction caches (ibus0/ibus1) and a shared L1
|
||||
* data cache with one port per core (dbus0/dbus1). The L2 (flash/PSRAM)
|
||||
* cache reports all instruction traffic on its ibus0 counters and all data
|
||||
* traffic on its dbus0 counters, regardless of the originating core.
|
||||
*/
|
||||
|
||||
const cache_profile_counter_unit_t cache_periph_profile_counter_units[SOC_CACHE_CNT_UNITS_NUM] = {
|
||||
{
|
||||
.name = "l1-icache-core0", .level = 1, .traffic = CACHE_PROFILE_TRAFFIC_INST, .core_id = 0,
|
||||
.counter_reg = {
|
||||
[CACHE_PROFILE_COUNTER_HIT] = CACHE_L1_IBUS0_ACS_HIT_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_MISS] = CACHE_L1_IBUS0_ACS_MISS_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_CONFLICT] = CACHE_L1_IBUS0_ACS_CONFLICT_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_NXTLVL_RD] = CACHE_L1_IBUS0_ACS_NXTLVL_RD_CNT_REG,
|
||||
},
|
||||
},
|
||||
{
|
||||
.name = "l1-icache-core1", .level = 1, .traffic = CACHE_PROFILE_TRAFFIC_INST, .core_id = 1,
|
||||
.counter_reg = {
|
||||
[CACHE_PROFILE_COUNTER_HIT] = CACHE_L1_IBUS1_ACS_HIT_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_MISS] = CACHE_L1_IBUS1_ACS_MISS_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_CONFLICT] = CACHE_L1_IBUS1_ACS_CONFLICT_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_NXTLVL_RD] = CACHE_L1_IBUS1_ACS_NXTLVL_RD_CNT_REG,
|
||||
},
|
||||
},
|
||||
{
|
||||
.name = "l1-dcache-core0", .level = 1, .traffic = CACHE_PROFILE_TRAFFIC_DATA, .core_id = 0,
|
||||
.counter_reg = {
|
||||
[CACHE_PROFILE_COUNTER_HIT] = CACHE_L1_DBUS0_ACS_HIT_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_MISS] = CACHE_L1_DBUS0_ACS_MISS_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_CONFLICT] = CACHE_L1_DBUS0_ACS_CONFLICT_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_NXTLVL_RD] = CACHE_L1_DBUS0_ACS_NXTLVL_RD_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_NXTLVL_WR] = CACHE_L1_DBUS0_ACS_NXTLVL_WR_CNT_REG,
|
||||
},
|
||||
},
|
||||
{
|
||||
.name = "l1-dcache-core1", .level = 1, .traffic = CACHE_PROFILE_TRAFFIC_DATA, .core_id = 1,
|
||||
.counter_reg = {
|
||||
[CACHE_PROFILE_COUNTER_HIT] = CACHE_L1_DBUS1_ACS_HIT_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_MISS] = CACHE_L1_DBUS1_ACS_MISS_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_CONFLICT] = CACHE_L1_DBUS1_ACS_CONFLICT_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_NXTLVL_RD] = CACHE_L1_DBUS1_ACS_NXTLVL_RD_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_NXTLVL_WR] = CACHE_L1_DBUS1_ACS_NXTLVL_WR_CNT_REG,
|
||||
},
|
||||
},
|
||||
{
|
||||
.name = "l2-cache-inst", .level = 2, .traffic = CACHE_PROFILE_TRAFFIC_INST, .core_id = -1,
|
||||
.counter_reg = {
|
||||
[CACHE_PROFILE_COUNTER_HIT] = CACHE_L2_IBUS0_ACS_HIT_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_MISS] = CACHE_L2_IBUS0_ACS_MISS_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_CONFLICT] = CACHE_L2_IBUS0_ACS_CONFLICT_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_NXTLVL_RD] = CACHE_L2_IBUS0_ACS_NXTLVL_RD_CNT_REG,
|
||||
},
|
||||
},
|
||||
{
|
||||
.name = "l2-cache-data", .level = 2, .traffic = CACHE_PROFILE_TRAFFIC_DATA, .core_id = -1,
|
||||
.counter_reg = {
|
||||
[CACHE_PROFILE_COUNTER_HIT] = CACHE_L2_DBUS0_ACS_HIT_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_MISS] = CACHE_L2_DBUS0_ACS_MISS_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_CONFLICT] = CACHE_L2_DBUS0_ACS_CONFLICT_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_NXTLVL_RD] = CACHE_L2_DBUS0_ACS_NXTLVL_RD_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_NXTLVL_WR] = CACHE_L2_DBUS0_ACS_NXTLVL_WR_CNT_REG,
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -507,6 +507,14 @@ config SOC_CACHE_FREEZE_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_CACHE_CNT_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_CACHE_CNT_UNITS_NUM
|
||||
int
|
||||
default 6
|
||||
|
||||
config SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
|
||||
bool
|
||||
default y
|
||||
|
||||
@@ -174,6 +174,8 @@
|
||||
#define SOC_SHARED_IDCACHE_SUPPORTED 1 //Shared Cache for both instructions and data
|
||||
#define SOC_CACHE_WRITEBACK_SUPPORTED 1
|
||||
#define SOC_CACHE_FREEZE_SUPPORTED 1
|
||||
#define SOC_CACHE_CNT_SUPPORTED 1
|
||||
#define SOC_CACHE_CNT_UNITS_NUM 6 //Number of cache profile counter units
|
||||
#define SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE 1
|
||||
|
||||
/*-------------------------- CPU CAPS ----------------------------------------*/
|
||||
|
||||
59
components/soc/esp32s31/cache_periph.c
Normal file
59
components/soc/esp32s31/cache_periph.c
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*/
|
||||
|
||||
#include "soc/cache_reg.h"
|
||||
#include "soc/cache_periph.h"
|
||||
|
||||
/*
|
||||
* ESP32-S31 cache profile counter units.
|
||||
*
|
||||
* The register layout matches the ESP32-P4: per-bus hit/miss/conflict and
|
||||
* next-level read/write counters, with the same counter semantics. There
|
||||
* is a single cache level (the flash/PSRAM cache, 64-byte lines); each
|
||||
* core accesses it through an instruction bus (ibus0/ibus1) and a data
|
||||
* bus (dbus0/dbus1). Only the CPU request buses are exposed here.
|
||||
*/
|
||||
|
||||
const cache_profile_counter_unit_t cache_periph_profile_counter_units[SOC_CACHE_CNT_UNITS_NUM] = {
|
||||
{
|
||||
.name = "l1-cache-inst-core0", .level = 1, .traffic = CACHE_PROFILE_TRAFFIC_INST, .core_id = 0,
|
||||
.counter_reg = {
|
||||
[CACHE_PROFILE_COUNTER_HIT] = CACHE_L1_IBUS0_ACS_HIT_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_MISS] = CACHE_L1_IBUS0_ACS_MISS_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_CONFLICT] = CACHE_L1_IBUS0_ACS_CONFLICT_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_NXTLVL_RD] = CACHE_L1_IBUS0_ACS_NXTLVL_RD_CNT_REG,
|
||||
},
|
||||
},
|
||||
{
|
||||
.name = "l1-cache-inst-core1", .level = 1, .traffic = CACHE_PROFILE_TRAFFIC_INST, .core_id = 1,
|
||||
.counter_reg = {
|
||||
[CACHE_PROFILE_COUNTER_HIT] = CACHE_L1_IBUS1_ACS_HIT_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_MISS] = CACHE_L1_IBUS1_ACS_MISS_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_CONFLICT] = CACHE_L1_IBUS1_ACS_CONFLICT_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_NXTLVL_RD] = CACHE_L1_IBUS1_ACS_NXTLVL_RD_CNT_REG,
|
||||
},
|
||||
},
|
||||
{
|
||||
.name = "l1-cache-data-core0", .level = 1, .traffic = CACHE_PROFILE_TRAFFIC_DATA, .core_id = 0,
|
||||
.counter_reg = {
|
||||
[CACHE_PROFILE_COUNTER_HIT] = CACHE_L1_DBUS0_ACS_HIT_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_MISS] = CACHE_L1_DBUS0_ACS_MISS_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_CONFLICT] = CACHE_L1_DBUS0_ACS_CONFLICT_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_NXTLVL_RD] = CACHE_L1_DBUS0_ACS_NXTLVL_RD_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_NXTLVL_WR] = CACHE_L1_DBUS0_ACS_NXTLVL_WR_CNT_REG,
|
||||
},
|
||||
},
|
||||
{
|
||||
.name = "l1-cache-data-core1", .level = 1, .traffic = CACHE_PROFILE_TRAFFIC_DATA, .core_id = 1,
|
||||
.counter_reg = {
|
||||
[CACHE_PROFILE_COUNTER_HIT] = CACHE_L1_DBUS1_ACS_HIT_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_MISS] = CACHE_L1_DBUS1_ACS_MISS_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_CONFLICT] = CACHE_L1_DBUS1_ACS_CONFLICT_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_NXTLVL_RD] = CACHE_L1_DBUS1_ACS_NXTLVL_RD_CNT_REG,
|
||||
[CACHE_PROFILE_COUNTER_NXTLVL_WR] = CACHE_L1_DBUS1_ACS_NXTLVL_WR_CNT_REG,
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -491,6 +491,14 @@ config SOC_CACHE_FREEZE_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_CACHE_CNT_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_CACHE_CNT_UNITS_NUM
|
||||
int
|
||||
default 4
|
||||
|
||||
config SOC_CPU_CORES_NUM
|
||||
int
|
||||
default 2
|
||||
|
||||
@@ -164,6 +164,8 @@
|
||||
/*-------------------------- CACHE CAPS --------------------------------------*/
|
||||
#define SOC_CACHE_WRITEBACK_SUPPORTED 1
|
||||
#define SOC_CACHE_FREEZE_SUPPORTED 1
|
||||
#define SOC_CACHE_CNT_SUPPORTED 1
|
||||
#define SOC_CACHE_CNT_UNITS_NUM 4 //Number of cache profile counter units
|
||||
|
||||
/*-------------------------- CPU CAPS ----------------------------------------*/
|
||||
#define SOC_CPU_CORES_NUM (2U)
|
||||
|
||||
58
components/soc/include/soc/cache_periph.h
Normal file
58
components/soc/include/soc/cache_periph.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Kind of traffic observed by a cache profile counter unit
|
||||
*/
|
||||
typedef enum {
|
||||
CACHE_PROFILE_TRAFFIC_INST, /*!< Instruction fetches */
|
||||
CACHE_PROFILE_TRAFFIC_DATA, /*!< Data accesses */
|
||||
CACHE_PROFILE_TRAFFIC_UNIFIED, /*!< Mixed/unknown (unified request bus) */
|
||||
} cache_profile_traffic_t;
|
||||
|
||||
/**
|
||||
* @brief One of the counters of a cache profile counter unit
|
||||
*/
|
||||
typedef enum {
|
||||
CACHE_PROFILE_COUNTER_HIT, /*!< Completed accesses ("hit" counter) */
|
||||
CACHE_PROFILE_COUNTER_MISS, /*!< Miss stall events ("miss" counter) */
|
||||
CACHE_PROFILE_COUNTER_CONFLICT, /*!< Requester conflicts */
|
||||
CACHE_PROFILE_COUNTER_NXTLVL_RD, /*!< Line fills from the next level */
|
||||
CACHE_PROFILE_COUNTER_NXTLVL_WR, /*!< Write-backs to the next level */
|
||||
CACHE_PROFILE_COUNTER_MAX,
|
||||
} cache_profile_counter_t;
|
||||
|
||||
/**
|
||||
* @brief Description of one cache profile counter unit
|
||||
*
|
||||
* A unit is one set of counters observing one traffic stream, e.g. the
|
||||
* instruction fetches of core 0 into the L1 cache.
|
||||
*/
|
||||
typedef struct {
|
||||
const char *name; /*!< Short human-readable name */
|
||||
uint8_t level; /*!< Cache level (1 or 2) */
|
||||
cache_profile_traffic_t traffic; /*!< Kind of traffic observed */
|
||||
int8_t core_id; /*!< Originating core, -1 if unknown/mixed */
|
||||
uint32_t counter_reg[CACHE_PROFILE_COUNTER_MAX]; /*!< Counter registers; 0 if the unit
|
||||
does not have that counter */
|
||||
} cache_profile_counter_unit_t;
|
||||
|
||||
#if SOC_CACHE_CNT_SUPPORTED
|
||||
extern const cache_profile_counter_unit_t cache_periph_profile_counter_units[SOC_CACHE_CNT_UNITS_NUM];
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user