Merge branch 'feature/perfmon' into 'master'

Performance monitor component

See merge request espressif/esp-idf!4705
This commit is contained in:
Angus Gratton 2019-11-04 18:25:14 +08:00
commit c5ef1cae04
25 changed files with 1560 additions and 3 deletions

View file

@ -0,0 +1,7 @@
set(xtensa_perfmon_srcs "xtensa_perfmon_access.c"
"xtensa_perfmon_apis.c"
"xtensa_perfmon_masks.c")
idf_component_register(SRCS "${xtensa_perfmon_srcs}"
INCLUDE_DIRS "include"
REQUIRES "xtensa")

View file

View file

@ -0,0 +1,29 @@
// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef _PERF_MON_H_
#define _PERF_MON_H_
#include <stdint.h>
#include <stdbool.h>
#include "esp_err.h"
#include "esp_log.h"
#include "xtensa_perfmon_access.h"
#include "xtensa_perfmon_masks.h"
#include "xtensa_perfmon_apis.h"
#include "xtensa/xt_perf_consts.h"
#endif // _PERF_MON_H_

View file

@ -0,0 +1,125 @@
// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef _PERF_MON_ACCESS_H_
#define _PERF_MON_ACCESS_H_
#include <stdint.h>
#include <stdbool.h>
#include "esp_err.h"
#include "esp_log.h"
#ifdef __cplusplus
extern "C"
{
#endif
/**@{*/
/**
* @brief Init Performance Monitoor
*
* Initialize performance monitor register with define values
*
* @param[in] id: performance counter number
* @param[in] select: select value from PMCTRLx register
* @param[in] mask: mask value from PMCTRLx register
* @param[in] kernelcnt: kernelcnt value from PMCTRLx register
* @param[in] tracelevel: tracelevel value from PMCTRLx register
*
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_ARG if one of the arguments is not correct
*/
esp_err_t xtensa_perfmon_init(int id, uint16_t select, uint16_t mask, int kernelcnt, int tracelevel);
/**@}*/
/**@{*/
/**
* @brief Reset PM counter
*
* Reset PM counter. Writes 0 to the PMx register.
*
* @param[in] id: performance counter number
*
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_ARG if id out of range
*/
esp_err_t xtensa_perfmon_reset(int id);
/**@}*/
/**@{*/
/**
* @brief Start PM counters
*
* Start all PM counters synchronously. Write 1 to the PGM register
*/
void xtensa_perfmon_start(void);
/**@}*/
/**@{*/
/**
* @brief Stop PM counters
*
* Stop all PM counters synchronously. Write 0 to the PGM register
*/
void xtensa_perfmon_stop(void);
/**@}*/
/**@{*/
/**
* @brief Read PM counter
*
* Read value of defined PM counter.
*
* @param[in] id: performance counter number
*
* @return
* - Performance counter value
*/
uint32_t xtensa_perfmon_value(int id);
/**@}*/
/**@{*/
/**
* @brief Read PM overflow state
*
* Read overflow value of defined PM counter.
*
* @param[in] id: performance counter number
*
* @return
* - ESP_OK if there is no overflow (overflow = 0)
* - ESP_FAIL if overflow occure (overflow = 1)
*/
esp_err_t xtensa_perfmon_overflow(int id);
/**@}*/
/**@{*/
/**
* @brief Dump PM values
*
* Dump all PM register to the console.
*
*/
void xtensa_perfmon_dump(void);
/**@}*/
#ifdef __cplusplus
}
#endif
#endif // _PERF_MON_ACCESS_H_

View file

@ -0,0 +1,80 @@
// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef _xtensa_perfmon_apis_H_
#define _xtensa_perfmon_apis_H_
#include "xtensa_perfmon_access.h"
#include "xtensa_perfmon_masks.h"
#ifdef __cplusplus
extern "C"
{
#endif
/**
* @brief Performance monitor configuration structure
*
* Structure to configure performance counter to measure dedicated function
*/
typedef struct xtensa_perfmon_config {
int repeat_count; /*!< how much times function will be called before the calback will be repeated */
float max_deviation; /*!< Difference between min and max counter number 0..1, 0 - no difference, 1 - not used */
void *call_params; /*!< This pointer will be passed to the call_function as a parameter */
void (*call_function)(void *params); /*!< pointer to the function that have to be called */
void (*callback)(void *params, uint32_t select, uint32_t mask, uint32_t value); /*!< pointer to the function that will be called with result parameters */
void *callback_params; /*!< parameter that will be passed to the callback */
int tracelevel; /*!< trace level for all counters.
In case of negative value, the filter will be ignored.
If it's >=0, then the perfmon will count only when interrupt level > tracelevel. It's useful to monitor interrupts. */
uint32_t counters_size;/*!< amount of counter in the list */
const uint32_t *select_mask; /*!< list of the select/mask parameters */
} xtensa_perfmon_config_t;
/**
* @brief Execute PM
*
* Execute performance counter for dedicated function with defined parameters
*
* @param[in] config: pointer to the configuration structure
*
* @return
* - ESP_OK if no errors
* - ESP_ERR_INVALID_ARG if one of the required parameters not defined
* - ESP_FAIL - counter overflow
*/
esp_err_t xtensa_perfmon_exec(const xtensa_perfmon_config_t *config);
/**
* @brief Dump PM results
*
* Callback to dump perfmon result to a FILE* stream specified in
* perfmon_config_t::callback_params. If callback_params is set to NULL, will print to stdout
*
* @param[in] params: used parameters passed from configuration (callback_params).
* This parameter expected as FILE* hanle, where data will be stored.
* If this parameter NULL, then data will be stored to the stdout.
* @param[in] select: select value for current counter
* @param[in] mask: mask value for current counter
* @param[in] value: counter value for current counter
*
*/
void xtensa_perfmon_view_cb(void *params, uint32_t select, uint32_t mask, uint32_t value);
#ifdef __cplusplus
}
#endif
#endif // _xtensa_perfmon_apis_H_

View file

@ -0,0 +1,74 @@
// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef _xtensa_perfmon_masks_H_
#define _xtensa_perfmon_masks_H_
#include <inttypes.h>
#include "xtensa/xt_perf_consts.h"
#ifdef __cplusplus
extern "C"
{
#endif
/**
* @brief Description for select parameter
*
* Structure defines description for different select values for performance counters
*/
typedef struct xtensa_perfmon_select {
int select; /*!< Selected counter */
const char *description; /*!< Description for selected counter */
} xtensa_perfmon_select_t;
/**
* @brief Description for mask parameter
*
* Structure defines description for different select and mask values for performance counters
*/
typedef struct xtensa_perfmon_masks {
int select; /*!< Selected counter */
int mask; /*!< Selected mask for counter */
const char *description; /*!< Description for selected mask */
} xtensa_perfmon_masks_t;
// Maximum amount of performance counter events
#define MAX_PERFMON_EVENTS 118
/**
* @brief Select value description table
*
* Table contains description for different 'select' values for performance counter
*/
extern const xtensa_perfmon_select_t xtensa_perfmon_select_table[];
/**
* @brief Mask value description table
*
* Table contains description for different 'select' and 'mask' values for performance counter
*/
extern const xtensa_perfmon_masks_t xtensa_perfmon_masks_table[];
/**
* @brief All available counters
*
* Table contains all available counters
*/
extern const uint32_t xtensa_perfmon_select_mask_all[MAX_PERFMON_EVENTS * 2];
#ifdef __cplusplus
}
#endif
#endif // _xtensa_perfmon_masks_H_

View file

@ -0,0 +1,7 @@
set(COMPONENT_SRCDIRS
"."
)
set(COMPONENT_ADD_INCLUDEDIRS ".")
set(COMPONENT_REQUIRES unity xtensa perfmon)
register_component()

View file

@ -0,0 +1,5 @@
COMPONENT_SRCDIRS := \
.
COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive

View file

@ -0,0 +1,193 @@
// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <string.h>
#include "unity.h"
#include "esp_log.h"
#include <stdlib.h>
#include "perfmon.h"
// These includes required only for the tests
#include "xtensa-debug-module.h"
#include "eri.h"
static const char *TAG = "perfmon";
TEST_CASE("Perfomance counter dump", "[perfmon]")
{
xtensa_perfmon_dump();
xtensa_perfmon_stop();
xtensa_perfmon_dump();
xtensa_perfmon_init(0, 0, 0xffff, 0, 6);
xtensa_perfmon_dump();
xtensa_perfmon_reset(0);
xtensa_perfmon_start();
int pm_data[10];
for (int i = 0 ; i < 10 ; i++) {
if (i == 4) {
xtensa_perfmon_reset(0);
xtensa_perfmon_start();
}
if (i == 6) {
xtensa_perfmon_stop();
}
if (i == 8) {
xtensa_perfmon_start();
}
pm_data[i] = eri_read(ERI_PERFMON_PM0);
}
for (int i = 0 ; i < 10 ; i++) {
ESP_LOGI(TAG, "pm_data[%i]= %08x", i, pm_data[i]);
}
if (pm_data[4] > pm_data[3]) {
ESP_LOGE(TAG, "The functions xtensa_perfmon_reset and xtensa_perfmon_start are not working correct.");
ESP_LOGW(TAG, "pm_data[3]= %i, must be > pm_data[4]= %i", pm_data[3], pm_data[4]);
TEST_ESP_OK(ESP_FAIL);
}
if ( pm_data[6] != pm_data[7]) {
ESP_LOGE(TAG, "The xtensa_perfmon_stop functions is not working correct.");
ESP_LOGW(TAG, "pm_data[6]= %i, must be == pm_data[7]= %i", pm_data[6], pm_data[7]);
TEST_ESP_OK(ESP_FAIL);
}
if ( pm_data[7] == pm_data[8]) {
ESP_LOGE(TAG, "The xtensa_perfmon_start functions is not working correct.");
ESP_LOGW(TAG, "pm_data[7]= %i, must be < pm_data[8]= %i", pm_data[7], pm_data[8]);
TEST_ESP_OK(ESP_FAIL);
}
xtensa_perfmon_stop();
}
static void test_call(void* params)
{
for (int i = 0 ; i < 1000 ; i++) {
__asm__ __volatile__(" nop");
}
}
static bool callback_called = false;
static int callback_call_count = 0;
static void test_callback(void *params, uint32_t select, uint32_t mask, uint32_t value)
{
ESP_LOGI("test", "test_callback select = %i, mask = %i, value = %i", select, mask, value);
callback_called = true;
callback_call_count++;
}
TEST_CASE("Performacnce test callback", "[perfmon]")
{
ESP_LOGI(TAG, "Initialize performance structure");
xtensa_perfmon_config_t pm_config = {};
pm_config.counters_size = sizeof(xtensa_perfmon_select_mask_all) / sizeof(uint32_t) / 2;
pm_config.select_mask = xtensa_perfmon_select_mask_all;
pm_config.repeat_count = 200;
pm_config.max_deviation = 1;
pm_config.call_function = test_call;
pm_config.callback = test_callback;
pm_config.callback_params = stdout;
pm_config.tracelevel = -1; // Trace all events
callback_called = false;
callback_call_count = 0;
xtensa_perfmon_exec(&pm_config);
ESP_LOGI(TAG, "Callback count = %i", callback_call_count);
if (callback_call_count != pm_config.counters_size) {
ESP_LOGE(TAG, "The callback count is not correct.");
ESP_LOGW(TAG, "callback_call_count= %i, must be == pm_config.counters_size= %i", callback_call_count, pm_config.counters_size);
TEST_ESP_OK(ESP_FAIL);
}
if (ESP_OK != xtensa_perfmon_overflow(0))
{
ESP_LOGE(TAG, "Perfmon 0 overflow detected!");
TEST_ESP_OK(ESP_FAIL);
}
if (ESP_OK != xtensa_perfmon_overflow(1))
{
ESP_LOGE(TAG, "Perfmon 1 overflow detected!");
TEST_ESP_OK(ESP_FAIL);
}
if (false == callback_called) {
TEST_ESP_OK(ESP_FAIL);
}
}
static void exec_callback(void *params)
{
for (int i = 0 ; i < 100 ; i++) {
__asm__ __volatile__(" nop");
}
}
static const uint32_t test_dsp_table[] = {
XTPERF_CNT_CYCLES, XTPERF_MASK_CYCLES, // total cycles
XTPERF_CNT_INSN, XTPERF_MASK_INSN_ALL, // total instructions
XTPERF_CNT_D_LOAD_U1, XTPERF_MASK_D_LOAD_LOCAL_MEM, // Mem read
XTPERF_CNT_D_STORE_U1, XTPERF_MASK_D_STORE_LOCAL_MEM, // Mem write
XTPERF_CNT_BUBBLES, XTPERF_MASK_BUBBLES_ALL &(~XTPERF_MASK_BUBBLES_R_HOLD_REG_DEP), // wait for other reasons
XTPERF_CNT_BUBBLES, XTPERF_MASK_BUBBLES_R_HOLD_REG_DEP, // Wait for register dependency
XTPERF_CNT_OVERFLOW, XTPERF_MASK_OVERFLOW, // Last test cycle
};
TEST_CASE("Performance test for Empty callback", "[perfmon]")
{
for (int i = 5 ; i < 10 ; i++) {
exec_callback(NULL);
ESP_LOGD(TAG, "Empty call passed.");
}
ESP_LOGI(TAG, "Start first test");
xtensa_perfmon_config_t pm_config = {};
pm_config.counters_size = sizeof(xtensa_perfmon_select_mask_all) / sizeof(uint32_t) / 2;
pm_config.select_mask = xtensa_perfmon_select_mask_all;
pm_config.repeat_count = 200;
pm_config.max_deviation = 1;
pm_config.call_function = exec_callback;
pm_config.callback = xtensa_perfmon_view_cb;
pm_config.callback_params = stdout;
pm_config.tracelevel = -1;
xtensa_perfmon_exec(&pm_config);
callback_call_count = 0;
ESP_LOGI(TAG, "Start second test");
pm_config.counters_size = sizeof(test_dsp_table) / sizeof(uint32_t) / 2;
pm_config.select_mask = test_dsp_table;
pm_config.repeat_count = 200;
pm_config.max_deviation = 1;
pm_config.call_function = exec_callback;
pm_config.callback = xtensa_perfmon_view_cb;
pm_config.callback_params = stdout;
pm_config.tracelevel = -1;
xtensa_perfmon_exec(&pm_config);
callback_call_count = 0;
ESP_LOGI(TAG, "Start third test");
pm_config.counters_size = sizeof(test_dsp_table) / sizeof(uint32_t) / 2;
pm_config.select_mask = test_dsp_table;
pm_config.repeat_count = 200;
pm_config.max_deviation = 1;
pm_config.call_function = exec_callback;
pm_config.callback = test_callback;
pm_config.callback_params = stdout;
pm_config.tracelevel = -1;
xtensa_perfmon_exec(&pm_config);
if (callback_call_count != pm_config.counters_size) {
TEST_ESP_OK(ESP_FAIL);
}
ESP_LOGI(TAG, "All tests passed.");
}

View file

@ -0,0 +1,88 @@
// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "xtensa_perfmon_access.h"
#include "xtensa-debug-module.h"
#include "eri.h"
esp_err_t xtensa_perfmon_init(int id, uint16_t select, uint16_t mask, int kernelcnt, int tracelevel)
{
if (id >= ERI_PERFMON_MAX) {
return ESP_ERR_INVALID_ARG;
}
uint32_t pmc =
((tracelevel & PMCTRL_TRACELEVEL_MASK) << PMCTRL_TRACELEVEL_SHIFT) |
((select & PMCTRL_SELECT_MASK) << PMCTRL_SELECT_SHIFT) |
((mask & PMCTRL_MASK_MASK) << PMCTRL_MASK_SHIFT) |
((kernelcnt & 1) << PMCTRL_KRNLCNT_SHIFT);
eri_write(ERI_PERFMON_PM0 + id * sizeof(int32_t), 0);
eri_write(ERI_PERFMON_PMCTRL0 + id * sizeof(int32_t), pmc);
return ESP_OK;
}
void xtensa_perfmon_dump(void)
{
uint32_t pgm = eri_read(ERI_PERFMON_PGM);
uint32_t intpc = eri_read(ERI_PERFMON_INTPC);
printf("perfmon: PGM=%08x, INTPC=%08x\n", pgm, intpc);
for (int i = 0 ; i < ERI_PERFMON_MAX ; i++) {
uint32_t pm = eri_read(ERI_PERFMON_PM0 + i * sizeof(int32_t));
uint32_t pmctrl = eri_read(ERI_PERFMON_PMCTRL0 + i * sizeof(int32_t));
uint32_t pmstat = eri_read(ERI_PERFMON_PMSTAT0 + i * sizeof(int32_t));
printf("perfmon: pm%i=%08x, pmctrl%i=%08x, pmstat%i=%08x\n", i, pm, i, pmctrl, i, pmstat);
}
}
esp_err_t xtensa_perfmon_reset(int id)
{
if (id >= ERI_PERFMON_MAX) {
return ESP_ERR_INVALID_ARG;
}
eri_write(ERI_PERFMON_PM0 + id * sizeof(int32_t), 0);
return ESP_OK;
}
void xtensa_perfmon_start(void)
{
eri_write(ERI_PERFMON_PGM, PGM_PMEN);
}
void xtensa_perfmon_stop(void)
{
eri_write(ERI_PERFMON_PGM, 0);
}
uint32_t xtensa_perfmon_value(int id)
{
if (id >= ERI_PERFMON_MAX) {
return 0;
}
uint32_t result = eri_read(ERI_PERFMON_PM0 + id * sizeof(int32_t));
return result;
}
esp_err_t xtensa_perfmon_overflow(int id)
{
if (id >= ERI_PERFMON_MAX) {
return ESP_ERR_INVALID_ARG;
}
uint32_t result = eri_read(ERI_PERFMON_PMSTAT0 + id * sizeof(int32_t));
if (result & 1) {
return ESP_FAIL;
}
return ESP_OK;
}

View file

@ -0,0 +1,88 @@
// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <stdlib.h>
#include "xtensa_perfmon_apis.h"
#include "xtensa_perfmon_masks.h"
static const char *TAG = "perfmon";
esp_err_t xtensa_perfmon_exec(const xtensa_perfmon_config_t *config)
{
esp_err_t result = ESP_OK;
if (config->call_function == NULL) {
ESP_LOGE(TAG, "Parameter call_function must be defined.");
return ESP_ERR_INVALID_ARG;
}
if (config->callback == NULL) {
ESP_LOGE(TAG, "Parameter callback must be defined.");
return ESP_ERR_INVALID_ARG;
}
for (size_t n = 0; n < config->counters_size; n++) {
uint32_t call_min = UINT32_MAX;
uint32_t call_max = 0;
float result_value = 0;
for (size_t i = 0; i < config->repeat_count; i++) {
// Set up cycle counter
xtensa_perfmon_stop();
int kernelcnt = 0;
// if tracelevel used, then kernelcnt will be enabled
if (config->tracelevel >=0) kernelcnt = 1;
xtensa_perfmon_init(0, 0, 0xffff, kernelcnt, config->tracelevel);
xtensa_perfmon_init(1, config->select_mask[n * 2 + 0], config->select_mask[n * 2 + 1], kernelcnt, config->tracelevel);
xtensa_perfmon_start();
config->call_function(config->call_params);
xtensa_perfmon_stop();
uint32_t p0 = xtensa_perfmon_value(0);
uint32_t p1 = xtensa_perfmon_value(1);
result_value += (float)p1 / config->repeat_count;
if (p0 < call_min) {
call_min = p0;
}
if (p0 > call_max) {
call_max = p0;
}
ESP_LOGV(TAG, "p0 = %i, p1 = %i", p0, p1);
}
uint32_t call_diff = (call_max - call_min);
if (call_diff > call_max * config->max_deviation) {
return ESP_FAIL;
} else {
config->callback(config->callback_params, config->select_mask[n * 2 + 0], config->select_mask[n * 2 + 1], (uint32_t)result_value);
}
}
return result;
}
void xtensa_perfmon_view_cb(void *params, uint32_t select, uint32_t mask, uint32_t value)
{
FILE *handle;
if (params != NULL) {
handle = (FILE *)params;
} else {
handle = stdout;
}
for (int i = 0 ; xtensa_perfmon_select_table[i].select != -1; i++) {
if (xtensa_perfmon_select_table[i].select == select) {
fprintf(handle, "Value = %9i, select = %2i, mask = %04x. %s.\n", value, select, mask, xtensa_perfmon_select_table[i].description);
}
}
for (int i = 0 ; xtensa_perfmon_masks_table[i].select != -1; i++) {
if ((xtensa_perfmon_masks_table[i].select == select) && (xtensa_perfmon_masks_table[i].mask & mask)) {
fprintf(handle, " %s\n", xtensa_perfmon_masks_table[i].description);
}
}
}

View file

@ -0,0 +1,299 @@
// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD
//
// Descriptions have been adapted from the comments in xt_perf_const.h,
// licensed under MIT license and copyright by Tensilica Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "xtensa_perfmon_masks.h"
const xtensa_perfmon_select_t xtensa_perfmon_select_table[] = {
// select, description
{XTPERF_CNT_CYCLES, "Counts cycles"},
{XTPERF_CNT_OVERFLOW, "Overflow of counter"},
{XTPERF_CNT_INSN, "Successfully Retired Instructions"},
{XTPERF_CNT_D_STALL, "Data-related GlobalStall cycles"},
{XTPERF_CNT_I_STALL, "Instruction-related and Other GlobalStall cycles"},
{XTPERF_CNT_EXR, "Exceptions and Pipeline Replays"},
{XTPERF_CNT_BUBBLES, "Hold and Other Bubble cycles"},
{XTPERF_CNT_I_TLB, "Instruction TLB Accesses (per instruction retiring)"},
{XTPERF_CNT_I_MEM, "Instruction Memory Accesses (per instruction retiring)"},
{XTPERF_CNT_D_TLB, "Data TLB Accesses"},
{XTPERF_CNT_D_LOAD_U1, "Load Instruction (Data Memory)"},
{XTPERF_CNT_D_LOAD_U2, "Load Instruction (Data Memory)"},
{XTPERF_CNT_D_LOAD_U3, "Load Instruction (Data Memory)"},
{XTPERF_CNT_D_STORE_U1, "Store Instruction (Data Memory)"},
{XTPERF_CNT_D_STORE_U2, "Store Instruction (Data Memory)"},
{XTPERF_CNT_D_STORE_U3, "Store Instruction (Data Memory)"},
{XTPERF_CNT_D_ACCESS_U1, "Accesses to Data Memory (Load, Store, S32C1I, ...)"},
{XTPERF_CNT_D_ACCESS_U2, "Accesses to Data Memory (Load, Store, S32C1I, ...)"},
{XTPERF_CNT_D_ACCESS_U3, "Accesses to Data Memory (Load, Store, S32C1I, ...)"},
{XTPERF_CNT_MULTIPLE_LS, "Multiple Load/Store"},
{XTPERF_CNT_OUTBOUND_PIF, "Outbound PIF"},
{XTPERF_CNT_INBOUND_PIF, "Inbound PIF"},
{XTPERF_CNT_PREFETCH, "Prefetch"},
{XTPERF_CNT_IDMA, "iDMA"},
{XTPERF_CNT_INSN_LENGTH, "Length of Instructions"},
{-1, ""},
};
const xtensa_perfmon_masks_t xtensa_perfmon_masks_table[] = {
// select, mask, description
{XTPERF_CNT_CYCLES, 1, "Amount of cycles"},
{XTPERF_CNT_OVERFLOW, 1, "Overflow counter"},
{XTPERF_CNT_INSN, XTPERF_MASK_INSN_JX, "JX instructions"},
{XTPERF_CNT_INSN, XTPERF_MASK_INSN_CALLX, "CALLXn instructions"},
{XTPERF_CNT_INSN, XTPERF_MASK_INSN_RET, "return instructions (RET, RETW, ...)"},
{XTPERF_CNT_INSN, XTPERF_MASK_INSN_RF, "supervisor return instructions (RFDE, RFE, RFI, RFWO, RFWU)"},
{XTPERF_CNT_INSN, XTPERF_MASK_INSN_BRANCH_TAKEN, "Conditional branch instructions where execution"},
{XTPERF_CNT_INSN, XTPERF_MASK_INSN_BRANCH_TAKEN, "transfers to the target (aka. taken branch),"},
{XTPERF_CNT_INSN, XTPERF_MASK_INSN_BRANCH_TAKEN, " or loopgtz/loopnez instr where execution skips"},
{XTPERF_CNT_INSN, XTPERF_MASK_INSN_BRANCH_TAKEN, " the loop (aka. not-taken loop)"},
{XTPERF_CNT_INSN, XTPERF_MASK_INSN_J, "J instr"},
{XTPERF_CNT_INSN, XTPERF_MASK_INSN_CALL, "CALLn instr"},
{XTPERF_CNT_INSN, XTPERF_MASK_INSN_BRANCH_NOT_TAKEN, "Conditional branch instr where execution"},
{XTPERF_CNT_INSN, XTPERF_MASK_INSN_BRANCH_NOT_TAKEN, " falls through (aka. not-taken branch)"},
{XTPERF_CNT_INSN, XTPERF_MASK_INSN_LOOP_TAKEN, "Loop instr where execution falls into loop (aka. taken loop)"},
{XTPERF_CNT_INSN, XTPERF_MASK_INSN_LOOP_BEG, "Last inst of loop and execution transfers"},
{XTPERF_CNT_INSN, XTPERF_MASK_INSN_LOOP_BEG, " to LBEG (aka. loopback taken)"},
{XTPERF_CNT_INSN, XTPERF_MASK_INSN_LOOP_END, "Last inst of loop and execution falls "},
{XTPERF_CNT_INSN, XTPERF_MASK_INSN_LOOP_END, " through to LEND (aka. loopback fallthrough)"},
{XTPERF_CNT_INSN, XTPERF_MASK_INSN_NON_BRANCH, "Non-branch instr (aka. non-CTI)"},
{XTPERF_CNT_D_STALL, XTPERF_MASK_D_STALL_STORE_BUF_FULL, "Store buffer full stall"},
{XTPERF_CNT_D_STALL, XTPERF_MASK_D_STALL_STORE_BUF_CONFLICT, "Store buffer conflict stall"},
{XTPERF_CNT_D_STALL, XTPERF_MASK_D_STALL_CACHE_MISS, "Data Cache-miss stall (unused)"},
{XTPERF_CNT_D_STALL, XTPERF_MASK_D_STALL_BUSY, "Data RAM/ROM/XLMI busy stall"},
{XTPERF_CNT_D_STALL, XTPERF_MASK_D_STALL_IN_PIF, "Data inbound-PIF request stall (includes s32c1i)"},
{XTPERF_CNT_D_STALL, XTPERF_MASK_D_STALL_MHT_LOOKUP, "MHT lookup stall"},
{XTPERF_CNT_D_STALL, XTPERF_MASK_D_STALL_UNCACHED_LOAD, "Uncached load stall (included in MHT lookup stall below)"},
{XTPERF_CNT_D_STALL, XTPERF_MASK_D_STALL_BANK_CONFLICT, "Bank-conflict stall"},
{XTPERF_CNT_I_STALL, XTPERF_MASK_I_STALL_CACHE_MISS, "ICache-miss stall"},
{XTPERF_CNT_I_STALL, XTPERF_MASK_I_STALL_BUSY, "Instruction RAM/ROM busy stall"},
{XTPERF_CNT_I_STALL, XTPERF_MASK_I_STALL_IN_PIF, "Instruction RAM inbound-PIF request stall"},
{XTPERF_CNT_I_STALL, XTPERF_MASK_I_STALL_TIE_PORT, "TIE port stall"},
{XTPERF_CNT_I_STALL, XTPERF_MASK_I_STALL_EXTERNAL_SIGNAL, "External RunStall signal status"},
{XTPERF_CNT_I_STALL, XTPERF_MASK_I_STALL_UNCACHED_FETCH, "Uncached fetch stall"},
{XTPERF_CNT_I_STALL, XTPERF_MASK_I_STALL_FAST_L32R, "FastL32R stall"},
{XTPERF_CNT_I_STALL, XTPERF_MASK_I_STALL_ITERATIVE_MUL, "Iterative multiply stall"},
{XTPERF_CNT_I_STALL, XTPERF_MASK_I_STALL_ITERATIVE_DIV, "Iterative divide stall"},
{XTPERF_CNT_EXR, XTPERF_MASK_EXR_REPLAYS, "Other Pipeline Replay (i.e. excludes cache miss etc.)"},
{XTPERF_CNT_EXR, XTPERF_MASK_EXR_LEVEL1_INT, "Level-1 interrupt"},
{XTPERF_CNT_EXR, XTPERF_MASK_EXR_LEVELH_INT, "Greater-than-level-1 interrupt"},
{XTPERF_CNT_EXR, XTPERF_MASK_EXR_DEBUG, "Debug exception"},
{XTPERF_CNT_EXR, XTPERF_MASK_EXR_NMI, "NMI"},
{XTPERF_CNT_EXR, XTPERF_MASK_EXR_WINDOW, "Window exception"},
{XTPERF_CNT_EXR, XTPERF_MASK_EXR_ALLOCA, "Allocate exception"},
{XTPERF_CNT_EXR, XTPERF_MASK_EXR_OTHER, "Other exceptions"},
{XTPERF_CNT_EXR, XTPERF_MASK_EXR_MEM_ERR, "HW-corrected memory error"},
{XTPERF_CNT_BUBBLES, XTPERF_MASK_BUBBLES_PSO, "Processor domain PSO bubble"},
{XTPERF_CNT_BUBBLES, XTPERF_MASK_BUBBLES_R_HOLD_D_CACHE_MISS, "R hold caused by Data Cache miss(unused)"},
{XTPERF_CNT_BUBBLES, XTPERF_MASK_BUBBLES_R_HOLD_STORE_RELEASE, "R hold caused by Store release"},
{XTPERF_CNT_BUBBLES, XTPERF_MASK_BUBBLES_R_HOLD_REG_DEP, "R hold caused by register dependency"},
{XTPERF_CNT_BUBBLES, XTPERF_MASK_BUBBLES_R_HOLD_WAIT, "R hold caused by MEMW, EXTW or EXCW"},
{XTPERF_CNT_BUBBLES, XTPERF_MASK_BUBBLES_R_HOLD_HALT, "R hold caused by Halt instruction (TX only)"},
{XTPERF_CNT_BUBBLES, XTPERF_MASK_BUBBLES_CTI, "CTI bubble (e.g. branch delay slot)"},
{XTPERF_CNT_BUBBLES, XTPERF_MASK_BUBBLES_WAITI, "WAITI bubble i.e. a cycle spent in WaitI power down mode."},
{XTPERF_CNT_I_TLB, XTPERF_MASK_I_TLB_HITS, "ITLB Hit"},
{XTPERF_CNT_I_TLB, XTPERF_MASK_I_TLB_REPLAYS, "Replay of instruction due to ITLB miss"},
{XTPERF_CNT_I_TLB, XTPERF_MASK_I_TLB_REFILLS, "HW-assisted TLB Refill completes"},
{XTPERF_CNT_I_TLB, XTPERF_MASK_I_TLB_MISSES, "ITLB Miss Exception"},
{XTPERF_CNT_I_MEM, XTPERF_MASK_I_MEM_CACHE_HITS, "Instruction Cache Hit"},
{XTPERF_CNT_I_MEM, XTPERF_MASK_I_MEM_CACHE_MISSES, "Instruction Cache Miss"},
{XTPERF_CNT_I_MEM, XTPERF_MASK_I_MEM_IRAM, "All InstRAM or InstROM accesses"},
{XTPERF_CNT_I_MEM, XTPERF_MASK_I_MEM_BYPASS, "Bypass (i.e. uncached) fetch"},
{XTPERF_CNT_D_TLB, XTPERF_MASK_D_TLB_HITS, "DTLB Hit"},
{XTPERF_CNT_D_TLB, XTPERF_MASK_D_TLB_REPLAYS, "Replay of load/store due to DTLB miss"},
{XTPERF_CNT_D_TLB, XTPERF_MASK_D_TLB_REFILLS, "HW-assisted TLB Refill completes"},
{XTPERF_CNT_D_TLB, XTPERF_MASK_D_TLB_MISSES, "DTLB Miss Exception"},
{XTPERF_CNT_D_LOAD_U1, XTPERF_MASK_D_LOAD_CACHE_HITS, "Data Cache Hit(unused)"},
{XTPERF_CNT_D_LOAD_U1, XTPERF_MASK_D_LOAD_CACHE_MISSES, "Data Cache Miss(unused)"},
{XTPERF_CNT_D_LOAD_U1, XTPERF_MASK_D_LOAD_LOCAL_MEM, "Load from local memory i.e. DataRAM, DataROM, InstRAM, InstROM"},
{XTPERF_CNT_D_LOAD_U1, XTPERF_MASK_D_LOAD_BYPASS, "Bypass (i.e. uncached) load"},
{XTPERF_CNT_D_LOAD_U2, XTPERF_MASK_D_LOAD_CACHE_HITS, "Data Cache Hit(unused)"},
{XTPERF_CNT_D_LOAD_U2, XTPERF_MASK_D_LOAD_CACHE_MISSES, "Data Cache Miss(unused)"},
{XTPERF_CNT_D_LOAD_U2, XTPERF_MASK_D_LOAD_LOCAL_MEM, "Load from local memory i.e. DataRAM, DataROM, InstRAM, InstROM"},
{XTPERF_CNT_D_LOAD_U2, XTPERF_MASK_D_LOAD_BYPASS, "Bypass (i.e. uncached) load"},
{XTPERF_CNT_D_LOAD_U3, XTPERF_MASK_D_LOAD_CACHE_HITS, "Data Cache Hit (unused)"},
{XTPERF_CNT_D_LOAD_U3, XTPERF_MASK_D_LOAD_CACHE_MISSES, "Data Cache Miss (unused)"},
{XTPERF_CNT_D_LOAD_U3, XTPERF_MASK_D_LOAD_LOCAL_MEM, "Load from local memory i.e. DataRAM, DataROM, InstRAM, InstROM"},
{XTPERF_CNT_D_LOAD_U3, XTPERF_MASK_D_LOAD_BYPASS, "Bypass (i.e. uncached) load"},
{XTPERF_CNT_D_STORE_U1, XTPERF_MASK_D_STORE_CACHE_HITS, "Data Cache Hit (unused)"},
{XTPERF_CNT_D_STORE_U1, XTPERF_MASK_D_STORE_CACHE_MISSES, "Data Cache Miss (unused)"},
{XTPERF_CNT_D_STORE_U1, XTPERF_MASK_D_STORE_LOCAL_MEM, "Store to local memory i.e. DataRAM, InstRAM"},
{XTPERF_CNT_D_STORE_U1, XTPERF_MASK_D_STORE_PIF, "PIF Store"},
{XTPERF_CNT_D_STORE_U2, XTPERF_MASK_D_STORE_CACHE_HITS, "Data Cache Hit(unused)"},
{XTPERF_CNT_D_STORE_U2, XTPERF_MASK_D_STORE_CACHE_MISSES, "Data Cache Miss(unused)"},
{XTPERF_CNT_D_STORE_U2, XTPERF_MASK_D_STORE_LOCAL_MEM, "Store to local memory i.e. DataRAM, InstRAM"},
{XTPERF_CNT_D_STORE_U2, XTPERF_MASK_D_STORE_PIF, "PIF Store"},
{XTPERF_CNT_D_STORE_U3, XTPERF_MASK_D_STORE_CACHE_HITS, "Data Cache Hit (unused)"},
{XTPERF_CNT_D_STORE_U3, XTPERF_MASK_D_STORE_CACHE_MISSES, "Data Cache Miss (unused)"},
{XTPERF_CNT_D_STORE_U3, XTPERF_MASK_D_STORE_LOCAL_MEM, "Store to local memory i.e. DataRAM, InstRAM"},
{XTPERF_CNT_D_STORE_U3, XTPERF_MASK_D_STORE_PIF, "PIF Store"},
{XTPERF_CNT_D_ACCESS_U1, XTPERF_MASK_D_ACCESS_CACHE_MISSES, "Cache Miss"},
{XTPERF_CNT_D_ACCESS_U2, XTPERF_MASK_D_ACCESS_CACHE_MISSES, "Cache Miss"},
{XTPERF_CNT_D_ACCESS_U3, XTPERF_MASK_D_ACCESS_CACHE_MISSES, "Cache Miss"},
{XTPERF_CNT_MULTIPLE_LS, XTPERF_MASK_MULTIPLE_LS_0S_0L, "0 stores and 0 loads"},
{XTPERF_CNT_MULTIPLE_LS, XTPERF_MASK_MULTIPLE_LS_0S_1L, "0 stores and 1 loads"},
{XTPERF_CNT_MULTIPLE_LS, XTPERF_MASK_MULTIPLE_LS_1S_0L, "1 stores and 0 loads"},
{XTPERF_CNT_MULTIPLE_LS, XTPERF_MASK_MULTIPLE_LS_1S_1L, "1 stores and 1 loads"},
{XTPERF_CNT_MULTIPLE_LS, XTPERF_MASK_MULTIPLE_LS_0S_2L, "0 stores and 2 loads"},
{XTPERF_CNT_MULTIPLE_LS, XTPERF_MASK_MULTIPLE_LS_2S_0L, "2 stores and 0 loads"},
{XTPERF_CNT_OUTBOUND_PIF, XTPERF_MASK_OUTBOUND_PIF_CASTOUT, "Castout"},
{XTPERF_CNT_OUTBOUND_PIF, XTPERF_MASK_OUTBOUND_PIF_PREFETCH, "Prefetch"},
{XTPERF_CNT_INBOUND_PIF, XTPERF_MASK_INBOUND_PIF_I_DMA, "Data DMA"},
{XTPERF_CNT_INBOUND_PIF, XTPERF_MASK_INBOUND_PIF_D_DMA, "Instruction DMA"},
{XTPERF_CNT_PREFETCH, XTPERF_MASK_PREFETCH_I_HIT, "I prefetch-buffer-lookup hit"},
{XTPERF_CNT_PREFETCH, XTPERF_MASK_PREFETCH_D_HIT, "D prefetch-buffer-lookup hit"},
{XTPERF_CNT_PREFETCH, XTPERF_MASK_PREFETCH_I_MISS, "I prefetch-buffer-lookup miss"},
{XTPERF_CNT_PREFETCH, XTPERF_MASK_PREFETCH_D_MISS, "D prefetch-buffer-lookup miss"},
{XTPERF_CNT_PREFETCH, XTPERF_MASK_PREFETCH_D_L1_FILL, "Direct fill to (L1) Data Cache (unused)"},
{XTPERF_CNT_IDMA, XTPERF_MASK_IDMA_ACTIVE_CYCLES, "active cycles"},
{XTPERF_CNT_INSN_LENGTH, XTPERF_MASK_INSN_LENGTH_16, "16-bit"},
{XTPERF_CNT_INSN_LENGTH, XTPERF_MASK_INSN_LENGTH_24, "24-bit"},
{XTPERF_CNT_INSN_LENGTH, XTPERF_MASK_INSN_LENGTH_32, "32-bit"},
{XTPERF_CNT_INSN_LENGTH, XTPERF_MASK_INSN_LENGTH_40, "40-bit"},
{XTPERF_CNT_INSN_LENGTH, XTPERF_MASK_INSN_LENGTH_48, "48-bit"},
{XTPERF_CNT_INSN_LENGTH, XTPERF_MASK_INSN_LENGTH_56, "56-bit"},
{XTPERF_CNT_INSN_LENGTH, XTPERF_MASK_INSN_LENGTH_64, "64-bit"},
{XTPERF_CNT_INSN_LENGTH, XTPERF_MASK_INSN_LENGTH_72, "72-bit"},
{XTPERF_CNT_INSN_LENGTH, XTPERF_MASK_INSN_LENGTH_80, "80-bit"},
{XTPERF_CNT_INSN_LENGTH, XTPERF_MASK_INSN_LENGTH_88, "88-bit"},
{XTPERF_CNT_INSN_LENGTH, XTPERF_MASK_INSN_LENGTH_96, "96-bit"},
{XTPERF_CNT_INSN_LENGTH, XTPERF_MASK_INSN_LENGTH_104, "104-bit"},
{XTPERF_CNT_INSN_LENGTH, XTPERF_MASK_INSN_LENGTH_112, "112-bit"},
{XTPERF_CNT_INSN_LENGTH, XTPERF_MASK_INSN_LENGTH_120, "120-bit"},
{XTPERF_CNT_INSN_LENGTH, XTPERF_MASK_INSN_LENGTH_128, "128-bit"},
{-1, 0, ""},
};
// All availible combinations
const uint32_t xtensa_perfmon_select_mask_all[MAX_PERFMON_EVENTS * 2] = {
XTPERF_CNT_CYCLES, XTPERF_MASK_CYCLES,
XTPERF_CNT_OVERFLOW, XTPERF_MASK_OVERFLOW,
XTPERF_CNT_INSN, XTPERF_MASK_INSN_JX,
XTPERF_CNT_INSN, XTPERF_MASK_INSN_CALLX,
XTPERF_CNT_INSN, XTPERF_MASK_INSN_RET,
XTPERF_CNT_INSN, XTPERF_MASK_INSN_RF,
XTPERF_CNT_INSN, XTPERF_MASK_INSN_BRANCH_TAKEN,
XTPERF_CNT_INSN, XTPERF_MASK_INSN_J,
XTPERF_CNT_INSN, XTPERF_MASK_INSN_CALL,
XTPERF_CNT_INSN, XTPERF_MASK_INSN_BRANCH_NOT_TAKEN,
XTPERF_CNT_INSN, XTPERF_MASK_INSN_LOOP_TAKEN,
XTPERF_CNT_INSN, XTPERF_MASK_INSN_LOOP_BEG,
XTPERF_CNT_INSN, XTPERF_MASK_INSN_LOOP_END,
XTPERF_CNT_INSN, XTPERF_MASK_INSN_NON_BRANCH,
XTPERF_CNT_D_STALL, XTPERF_MASK_D_STALL_STORE_BUF_FULL,
XTPERF_CNT_D_STALL, XTPERF_MASK_D_STALL_STORE_BUF_CONFLICT,
XTPERF_CNT_D_STALL, XTPERF_MASK_D_STALL_CACHE_MISS,
XTPERF_CNT_D_STALL, XTPERF_MASK_D_STALL_BUSY,
XTPERF_CNT_D_STALL, XTPERF_MASK_D_STALL_IN_PIF,
XTPERF_CNT_D_STALL, XTPERF_MASK_D_STALL_MHT_LOOKUP,
XTPERF_CNT_D_STALL, XTPERF_MASK_D_STALL_UNCACHED_LOAD,
XTPERF_CNT_D_STALL, XTPERF_MASK_D_STALL_BANK_CONFLICT,
XTPERF_CNT_I_STALL, XTPERF_MASK_I_STALL_CACHE_MISS,
XTPERF_CNT_I_STALL, XTPERF_MASK_I_STALL_BUSY,
XTPERF_CNT_I_STALL, XTPERF_MASK_I_STALL_IN_PIF,
XTPERF_CNT_I_STALL, XTPERF_MASK_I_STALL_TIE_PORT,
XTPERF_CNT_I_STALL, XTPERF_MASK_I_STALL_EXTERNAL_SIGNAL,
XTPERF_CNT_I_STALL, XTPERF_MASK_I_STALL_UNCACHED_FETCH,
XTPERF_CNT_I_STALL, XTPERF_MASK_I_STALL_FAST_L32R,
XTPERF_CNT_I_STALL, XTPERF_MASK_I_STALL_ITERATIVE_MUL,
XTPERF_CNT_I_STALL, XTPERF_MASK_I_STALL_ITERATIVE_DIV,
XTPERF_CNT_EXR, XTPERF_MASK_EXR_REPLAYS,
XTPERF_CNT_EXR, XTPERF_MASK_EXR_LEVEL1_INT,
XTPERF_CNT_EXR, XTPERF_MASK_EXR_LEVELH_INT,
XTPERF_CNT_EXR, XTPERF_MASK_EXR_DEBUG,
XTPERF_CNT_EXR, XTPERF_MASK_EXR_NMI,
XTPERF_CNT_EXR, XTPERF_MASK_EXR_WINDOW,
XTPERF_CNT_EXR, XTPERF_MASK_EXR_ALLOCA,
XTPERF_CNT_EXR, XTPERF_MASK_EXR_OTHER,
XTPERF_CNT_EXR, XTPERF_MASK_EXR_MEM_ERR,
XTPERF_CNT_BUBBLES, XTPERF_MASK_BUBBLES_PSO,
XTPERF_CNT_BUBBLES, XTPERF_MASK_BUBBLES_R_HOLD_D_CACHE_MISS,
XTPERF_CNT_BUBBLES, XTPERF_MASK_BUBBLES_R_HOLD_STORE_RELEASE,
XTPERF_CNT_BUBBLES, XTPERF_MASK_BUBBLES_R_HOLD_REG_DEP,
XTPERF_CNT_BUBBLES, XTPERF_MASK_BUBBLES_R_HOLD_WAIT,
XTPERF_CNT_BUBBLES, XTPERF_MASK_BUBBLES_R_HOLD_HALT,
XTPERF_CNT_BUBBLES, XTPERF_MASK_BUBBLES_CTI,
XTPERF_CNT_BUBBLES, XTPERF_MASK_BUBBLES_WAITI,
XTPERF_CNT_I_TLB, XTPERF_MASK_I_TLB_HITS,
XTPERF_CNT_I_TLB, XTPERF_MASK_I_TLB_REPLAYS,
XTPERF_CNT_I_TLB, XTPERF_MASK_I_TLB_REFILLS,
XTPERF_CNT_I_TLB, XTPERF_MASK_I_TLB_MISSES,
XTPERF_CNT_I_MEM, XTPERF_MASK_I_MEM_CACHE_HITS,
XTPERF_CNT_I_MEM, XTPERF_MASK_I_MEM_CACHE_MISSES,
XTPERF_CNT_I_MEM, XTPERF_MASK_I_MEM_IRAM,
XTPERF_CNT_I_MEM, XTPERF_MASK_I_MEM_BYPASS,
XTPERF_CNT_D_TLB, XTPERF_MASK_D_TLB_HITS,
XTPERF_CNT_D_TLB, XTPERF_MASK_D_TLB_REPLAYS,
XTPERF_CNT_D_TLB, XTPERF_MASK_D_TLB_REFILLS,
XTPERF_CNT_D_TLB, XTPERF_MASK_D_TLB_MISSES,
XTPERF_CNT_D_LOAD_U1, XTPERF_MASK_D_LOAD_CACHE_HITS,
XTPERF_CNT_D_LOAD_U1, XTPERF_MASK_D_LOAD_CACHE_MISSES,
XTPERF_CNT_D_LOAD_U1, XTPERF_MASK_D_LOAD_LOCAL_MEM,
XTPERF_CNT_D_LOAD_U1, XTPERF_MASK_D_LOAD_BYPASS,
XTPERF_CNT_D_LOAD_U2, XTPERF_MASK_D_LOAD_CACHE_HITS,
XTPERF_CNT_D_LOAD_U2, XTPERF_MASK_D_LOAD_CACHE_MISSES,
XTPERF_CNT_D_LOAD_U2, XTPERF_MASK_D_LOAD_LOCAL_MEM,
XTPERF_CNT_D_LOAD_U2, XTPERF_MASK_D_LOAD_BYPASS,
XTPERF_CNT_D_LOAD_U3, XTPERF_MASK_D_LOAD_CACHE_HITS,
XTPERF_CNT_D_LOAD_U3, XTPERF_MASK_D_LOAD_CACHE_MISSES,
XTPERF_CNT_D_LOAD_U3, XTPERF_MASK_D_LOAD_LOCAL_MEM,
XTPERF_CNT_D_LOAD_U3, XTPERF_MASK_D_LOAD_BYPASS,
XTPERF_CNT_D_STORE_U1, XTPERF_MASK_D_STORE_CACHE_HITS,
XTPERF_CNT_D_STORE_U1, XTPERF_MASK_D_STORE_CACHE_MISSES,
XTPERF_CNT_D_STORE_U1, XTPERF_MASK_D_STORE_LOCAL_MEM,
XTPERF_CNT_D_STORE_U1, XTPERF_MASK_D_STORE_PIF,
XTPERF_CNT_D_STORE_U2, XTPERF_MASK_D_STORE_CACHE_HITS,
XTPERF_CNT_D_STORE_U2, XTPERF_MASK_D_STORE_CACHE_MISSES,
XTPERF_CNT_D_STORE_U2, XTPERF_MASK_D_STORE_LOCAL_MEM,
XTPERF_CNT_D_STORE_U2, XTPERF_MASK_D_STORE_PIF,
XTPERF_CNT_D_STORE_U3, XTPERF_MASK_D_STORE_CACHE_HITS,
XTPERF_CNT_D_STORE_U3, XTPERF_MASK_D_STORE_CACHE_MISSES,
XTPERF_CNT_D_STORE_U3, XTPERF_MASK_D_STORE_LOCAL_MEM,
XTPERF_CNT_D_STORE_U3, XTPERF_MASK_D_STORE_PIF,
XTPERF_CNT_D_ACCESS_U1, XTPERF_MASK_D_ACCESS_CACHE_MISSES,
XTPERF_CNT_D_ACCESS_U2, XTPERF_MASK_D_ACCESS_CACHE_MISSES,
XTPERF_CNT_D_ACCESS_U3, XTPERF_MASK_D_ACCESS_CACHE_MISSES,
XTPERF_CNT_MULTIPLE_LS, XTPERF_MASK_MULTIPLE_LS_0S_0L,
XTPERF_CNT_MULTIPLE_LS, XTPERF_MASK_MULTIPLE_LS_0S_1L,
XTPERF_CNT_MULTIPLE_LS, XTPERF_MASK_MULTIPLE_LS_1S_0L,
XTPERF_CNT_MULTIPLE_LS, XTPERF_MASK_MULTIPLE_LS_1S_1L,
XTPERF_CNT_MULTIPLE_LS, XTPERF_MASK_MULTIPLE_LS_0S_2L,
XTPERF_CNT_MULTIPLE_LS, XTPERF_MASK_MULTIPLE_LS_2S_0L,
XTPERF_CNT_OUTBOUND_PIF, XTPERF_MASK_OUTBOUND_PIF_CASTOUT,
XTPERF_CNT_OUTBOUND_PIF, XTPERF_MASK_OUTBOUND_PIF_PREFETCH,
XTPERF_CNT_INBOUND_PIF, XTPERF_MASK_INBOUND_PIF_I_DMA,
XTPERF_CNT_INBOUND_PIF, XTPERF_MASK_INBOUND_PIF_D_DMA,
XTPERF_CNT_PREFETCH, XTPERF_MASK_PREFETCH_I_HIT,
XTPERF_CNT_PREFETCH, XTPERF_MASK_PREFETCH_D_HIT,
XTPERF_CNT_PREFETCH, XTPERF_MASK_PREFETCH_I_MISS,
XTPERF_CNT_PREFETCH, XTPERF_MASK_PREFETCH_D_MISS,
XTPERF_CNT_PREFETCH, XTPERF_MASK_PREFETCH_D_L1_FILL,
XTPERF_CNT_IDMA, XTPERF_MASK_IDMA_ALL,
XTPERF_CNT_INSN_LENGTH, XTPERF_MASK_INSN_LENGTH_16,
XTPERF_CNT_INSN_LENGTH, XTPERF_MASK_INSN_LENGTH_24,
XTPERF_CNT_INSN_LENGTH, XTPERF_MASK_INSN_LENGTH_32,
XTPERF_CNT_INSN_LENGTH, XTPERF_MASK_INSN_LENGTH_40,
XTPERF_CNT_INSN_LENGTH, XTPERF_MASK_INSN_LENGTH_48,
XTPERF_CNT_INSN_LENGTH, XTPERF_MASK_INSN_LENGTH_56,
XTPERF_CNT_INSN_LENGTH, XTPERF_MASK_INSN_LENGTH_64,
XTPERF_CNT_INSN_LENGTH, XTPERF_MASK_INSN_LENGTH_72,
XTPERF_CNT_INSN_LENGTH, XTPERF_MASK_INSN_LENGTH_80,
XTPERF_CNT_INSN_LENGTH, XTPERF_MASK_INSN_LENGTH_88,
XTPERF_CNT_INSN_LENGTH, XTPERF_MASK_INSN_LENGTH_96,
XTPERF_CNT_INSN_LENGTH, XTPERF_MASK_INSN_LENGTH_104,
XTPERF_CNT_INSN_LENGTH, XTPERF_MASK_INSN_LENGTH_112,
XTPERF_CNT_INSN_LENGTH, XTPERF_MASK_INSN_LENGTH_120,
XTPERF_CNT_INSN_LENGTH, XTPERF_MASK_INSN_LENGTH_128
};

View file

@ -1,6 +1,6 @@
#ifndef XTENSA_DEBUG_MODULE_H
#define XTENSA_DEBUG_MODULE_H
#include "soc/cpu.h"
/*
ERI registers / OCD offsets and field definitions
*/
@ -71,5 +71,45 @@ ERI registers / OCD offsets and field definitions
#define PCMATCHCTRL_PCMS (1<<31) //PC Match Sense, 0 - match when procs PC is in-range, 1 - match when
//out-of-range
// Global control/status for all performance counters
#define ERI_PERFMON_PGM (ERI_PERFMON_OFFSET+0x0000)
//PC at the cycle of the event that caused PerfMonInt assertion
#define ERI_PERFMON_INTPC (ERI_PERFMON_OFFSET+0x0010)
// Maximum amount of counter (depends on chip)
#define ERI_PERFMON_MAX XCHAL_NUM_PERF_COUNTERS
// Performance counter value
#define ERI_PERFMON_PM0 (ERI_PERFMON_OFFSET+0x0080)
// Performance counter control register
#define ERI_PERFMON_PMCTRL0 (ERI_PERFMON_OFFSET+0x0100)
// Performance counter status register
#define ERI_PERFMON_PMSTAT0 (ERI_PERFMON_OFFSET+0x0180)
#define PMCTRL_INTEN (1<<0) // Enables assertion of PerfMonInt output when overflow happens
#define PMCTRL_KRNLCNT (1<<3) // Enables counting when CINTLEVEL* >
// TRACELEVEL (i.e. If this bit is set, this counter
// counts only when CINTLEVEL >TRACELEVEL;
// if this bit is cleared, this counter counts only when
// CINTLEVEL ≤ TRACELEVEL)
#define PMCTRL_KRNLCNT_SHIFT 3
#define PMCTRL_TRACELEVEL_SHIFT 4 // Compares this value to CINTLEVEL* when deciding whether to count
#define PMCTRL_TRACELEVEL_MASK 0xf
#define PMCTRL_SELECT_SHIFT 8 // Selects input to be counted by the counter
#define PMCTRL_SELECT_MASK 0x1f
#define PMCTRL_MASK_SHIFT 16 // Selects input subsets to be counted (counter will
// increment only once even if more than one condition
// corresponding to a mask bit occurs)
#define PMCTRL_MASK_MASK 0xffff
#define PMSTAT_OVFL (1<<0) // Counter Overflow. Sticky bit set when a counter rolls over
// from 0xffffffff to 0x0.
#define PMSTAT_INTSTART (1<<4) // This counters overflow caused PerfMonInt to be asserted.
#define PGM_PMEN (1<<0) // Overall enable for all performance counting
#endif

View file

@ -56,7 +56,8 @@
#define XTPERF_CNT_OUTBOUND_PIF 23 /* Outbound PIF transactions */
#define XTPERF_CNT_INBOUND_PIF 24 /* Inbound PIF transactions */
#define XTPERF_CNT_PREFETCH 26 /* Prefetch events */
#define XTPERF_CNT_IDMA 27 /* iDMA counters */
#define XTPERF_CNT_INSN_LENGTH 28 /* Instruction length counters */
/*
* Masks for each of the selector listed above
@ -280,4 +281,33 @@
#define XTPERF_MASK_PREFETCH_D_MISS 0x0008 /* D prefetch-buffer-lookup miss */
#define XTPERF_MASK_PREFETCH_D_L1_FILL 0x0020 /* Fill directly to DCache L1 */
/*
* XTPERF_CNT_IDMA selector mask
*/
#define XTPERF_MASK_IDMA_ALL 0x0001
#define XTPERF_MASK_IDMA_ACTIVE_CYCLES 0x0001 /* Active Cycles */
/*
* XTPERF_CNT_INSN_LENGTH selector mask
*/
#define XTPERF_MASK_INSN_LENGTH_ALL 0x7FFF
#define XTPERF_MASK_INSN_LENGTH_16 0x0001 /* 16-bit instruction length */
#define XTPERF_MASK_INSN_LENGTH_24 0x0002 /* 24-bit instruction length */
#define XTPERF_MASK_INSN_LENGTH_32 0x0004 /* 32-bit instruction length */
#define XTPERF_MASK_INSN_LENGTH_40 0x0008 /* 40-bit instruction length */
#define XTPERF_MASK_INSN_LENGTH_48 0x0010 /* 48-bit instruction length */
#define XTPERF_MASK_INSN_LENGTH_56 0x0020 /* 56-bit instruction length */
#define XTPERF_MASK_INSN_LENGTH_64 0x0040 /* 64-bit instruction length */
#define XTPERF_MASK_INSN_LENGTH_72 0x0080 /* 72-bit instruction length */
#define XTPERF_MASK_INSN_LENGTH_80 0x0100 /* 80-bit instruction length */
#define XTPERF_MASK_INSN_LENGTH_88 0x0200 /* 88-bit instruction length */
#define XTPERF_MASK_INSN_LENGTH_96 0x0400 /* 96-bit instruction length */
#define XTPERF_MASK_INSN_LENGTH_104 0x0800 /* 104-bit instruction length */
#define XTPERF_MASK_INSN_LENGTH_112 0x1000 /* 112-bit instruction length */
#define XTPERF_MASK_INSN_LENGTH_120 0x2000 /* 120-bit instruction length */
#define XTPERF_MASK_INSN_LENGTH_128 0x4000 /* 128-bit instruction length */
#endif /* __XT_PERF_CONSTS_H__ */

View file

@ -256,7 +256,11 @@ INPUT = \
### Modbus controller component header file
../../components/freemodbus/common/include/esp_modbus_common.h \
../../components/freemodbus/common/include/esp_modbus_slave.h \
../../components/freemodbus/common/include/esp_modbus_master.h
../../components/freemodbus/common/include/esp_modbus_master.h \
### Performance Monitor component header file
../../components/perfmon/include/xtensa_perfmon_access.h \
../../components/perfmon/include/xtensa_perfmon_apis.h \
../../components/perfmon/include/xtensa_perfmon_masks.h
## Get warnings for functions that have no documentation for their parameters or return value

View file

@ -22,6 +22,7 @@ System API
Logging <log>
Miscellaneous System APIs <system>
Over The Air Updates (OTA) <ota>
Performance Monitor <perfmon>
Power Management <power_management>
Sleep Modes <sleep_modes>
Watchdogs <wdts>

View file

@ -0,0 +1,26 @@
Performance Monitor
===================
The Performance Monitor component provides APIs to use ESP32 internal performance counters to profile functions and
applications.
Application Example
-------------------
An example which combines performance monitor is provided in ``examples/system/perfmon`` directory.
This example initializes the performance monitor structure and execute them with printing the statistics.
High level API Reference
------------------------
Header Files
^^^^^^^^^^^^
* :component_file:`perfmon/include/perfmon.h`
API Reference
-------------
.. include:: /_build/inc/xtensa_perfmon_access.inc
.. include:: /_build/inc/xtensa_perfmon_apis.inc

View file

@ -0,0 +1 @@
.. include:: ../../../en/api-reference/system/perfmon.rst

View file

@ -0,0 +1,6 @@
# The following lines of boilerplate have to be in your project's CMakeLists
# in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(perfmon_example)

View file

@ -0,0 +1,9 @@
#
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
# project subdirectory.
#
PROJECT_NAME := perfmon_example
include $(IDF_PATH)/make/project.mk

View file

@ -0,0 +1,365 @@
# Performance Monitor (`perfmon`) example
(See the README.md file in the upper level 'examples' directory for more information about examples.)
## Overview
This example illustrates usage of `perfmon` APIs to monitor and profile functions.
The example will calculate performance statistic for simple test function.
The simple test function could be exchanged to one from the user.
The example contain test function that will be executed with perfmon component and collect CPU statistic. The test function will be executed 200 times in each test case. The first test case collect statistic from all available performance counters, and second test just from defined in the list.
## How to use example
### Hardware Required
Example should be able to run on any commonly available ESP32 development board.
### Configure the project
```
make menuconfig
```
* Set serial port under Serial Flasher Options.
### Build and Flash
Enter `make -j4 flash monitor` if you are using GNU Make based build system or enter `idf.py build flash monitor` if you' are using CMake based build system.
(To exit the serial monitor, type ``Ctrl-]``.)
See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html) for full steps to configure and use ESP-IDF to build projects.
## Example Output
1. Example starts and call first test. The first test call test function 'exec_test_function'
```bash
I (288) example: Start
I (288) example: Start test with printing all available statistic
Value = 750, select = 0, mask = 0001. Counts cycles.
Amount of cycles
Value = 0, select = 1, mask = 0001. Overflow of counter.
Overflow counter
Value = 0, select = 2, mask = 0001. Successfully Retired Instructions.
JX instructions
Value = 0, select = 2, mask = 0002. Successfully Retired Instructions.
CALLXn instructions
Value = 3, select = 2, mask = 0004. Successfully Retired Instructions.
return instructions (RET, RETW, ...)
Value = 0, select = 2, mask = 0008. Successfully Retired Instructions.
supervisor return instructions (RFDE, RFE, RFI, RFWO, RFWU)
Value = 100, select = 2, mask = 0010. Successfully Retired Instructions.
Conditional branch instructions where execution
transfers to the target (aka. taken branch),
or loopgtz/loopnez instr where execution skips
the loop (aka. not-taken loop)
Value = 0, select = 2, mask = 0020. Successfully Retired Instructions.
J instr
Value = 1, select = 2, mask = 0040. Successfully Retired Instructions.
CALLn instr
Value = 0, select = 2, mask = 0080. Successfully Retired Instructions.
Conditional branch instr where execution
falls through (aka. not-taken branch)
Value = 0, select = 2, mask = 0100. Successfully Retired Instructions.
Loop instr where execution falls into loop (aka. taken loop)
Value = 0, select = 2, mask = 0400. Successfully Retired Instructions.
Last inst of loop and execution transfers
to LBEG (aka. loopback taken)
Value = 0, select = 2, mask = 0800. Successfully Retired Instructions.
Last inst of loop and execution falls
through to LEND (aka. loopback fallthrough)
Value = 309, select = 2, mask = 8000. Successfully Retired Instructions.
Non-branch instr (aka. non-CTI)
Value = 0, select = 3, mask = 0002. Data-related GlobalStall cycles.
Store buffer full stall
Value = 0, select = 3, mask = 0004. Data-related GlobalStall cycles.
Store buffer conflict stall
Value = 0, select = 3, mask = 0008. Data-related GlobalStall cycles.
Data Cache-miss stall (unused)
Value = 0, select = 3, mask = 0010. Data-related GlobalStall cycles.
Data RAM/ROM/XLMI busy stall
Value = 0, select = 3, mask = 0020. Data-related GlobalStall cycles.
Data inbound-PIF request stall (includes s32c1i)
Value = 0, select = 3, mask = 0040. Data-related GlobalStall cycles.
MHT lookup stall
Value = 0, select = 3, mask = 0080. Data-related GlobalStall cycles.
Uncached load stall (included in MHT lookup stall below)
Value = 0, select = 3, mask = 0100. Data-related GlobalStall cycles.
Bank-conflict stall
Value = 0, select = 4, mask = 0001. Instruction-related and Other Glob
alStall cycles.
ICache-miss stall
Value = 0, select = 4, mask = 0002. Instruction-related and Other Glob
alStall cycles.
Instruction RAM/ROM busy stall
Value = 0, select = 4, mask = 0004. Instruction-related and Other Glob
alStall cycles.
Instruction RAM inbound-PIF request stall
Value = 0, select = 4, mask = 0008. Instruction-related and Other Glob
alStall cycles.
TIE port stall
Value = 0, select = 4, mask = 0010. Instruction-related and Other Glob
alStall cycles.
External RunStall signal status
Value = 0, select = 4, mask = 0020. Instruction-related and Other Glob
alStall cycles.
Uncached fetch stall
Value = 1, select = 4, mask = 0040. Instruction-related and Other Glob
alStall cycles.
FastL32R stall
Value = 0, select = 4, mask = 0080. Instruction-related and Other Glob
alStall cycles.
Iterative multiply stall
Value = 0, select = 4, mask = 0100. Instruction-related and Other Glob
alStall cycles.
Iterative divide stall
Value = 0, select = 5, mask = 0001. Exceptions and Pipeline Replays.
Other Pipeline Replay (i.e. excludes cache miss etc.)
Value = 0, select = 5, mask = 0002. Exceptions and Pipeline Replays.
Level-1 interrupt
Value = 0, select = 5, mask = 0004. Exceptions and Pipeline Replays.
Greater-than-level-1 interrupt
Value = 0, select = 5, mask = 0008. Exceptions and Pipeline Replays.
Debug exception
Value = 0, select = 5, mask = 0010. Exceptions and Pipeline Replays.
NMI
Value = 0, select = 5, mask = 0020. Exceptions and Pipeline Replays.
Window exception
Value = 0, select = 5, mask = 0040. Exceptions and Pipeline Replays.
Allocate exception
Value = 0, select = 5, mask = 0080. Exceptions and Pipeline Replays.
Other exceptions
Value = 0, select = 5, mask = 0100. Exceptions and Pipeline Replays.
HW-corrected memory error
Value = 0, select = 6, mask = 0001. Hold and Other Bubble cycles.
Processor domain PSO bubble
Value = 0, select = 6, mask = 0004. Hold and Other Bubble cycles.
R hold caused by Data Cache miss(unused)
Value = 0, select = 6, mask = 0008. Hold and Other Bubble cycles.
R hold caused by Store release
Value = 0, select = 6, mask = 0010. Hold and Other Bubble cycles.
R hold caused by register dependency
Value = 0, select = 6, mask = 0020. Hold and Other Bubble cycles.
R hold caused by MEMW, EXTW or EXCW
Value = 0, select = 6, mask = 0040. Hold and Other Bubble cycles.
R hold caused by Halt instruction (TX only)
Value = 322, select = 6, mask = 0080. Hold and Other Bubble cycles.
CTI bubble (e.g. branch delay slot)
Value = 0, select = 6, mask = 0100. Hold and Other Bubble cycles.
WAITI bubble i.e. a cycle spent in WaitI power down mode.
Value = 417, select = 7, mask = 0001. Instruction TLB Accesses (per inst
ruction retiring).
ITLB Hit
Value = 0, select = 7, mask = 0002. Instruction TLB Accesses (per inst
ruction retiring).
Replay of instruction due to ITLB miss
Value = 0, select = 7, mask = 0004. Instruction TLB Accesses (per inst
ruction retiring).
HW-assisted TLB Refill completes
Value = 0, select = 7, mask = 0008. Instruction TLB Accesses (per inst
ruction retiring).
ITLB Miss Exception
Value = 0, select = 8, mask = 0001. Instruction Memory Accesses (per i
nstruction retiring).
Instruction Cache Hit
Value = 0, select = 8, mask = 0002. Instruction Memory Accesses (per i
nstruction retiring).
Instruction Cache Miss
Value = 420, select = 8, mask = 0004. Instruction Memory Accesses (per i
nstruction retiring).
All InstRAM or InstROM accesses
Value = 0, select = 8, mask = 0008. Instruction Memory Accesses (per i
nstruction retiring).
Bypass (i.e. uncached) fetch
Value = 3, select = 9, mask = 0001. Data TLB Accesses.
DTLB Hit
Value = 0, select = 9, mask = 0002. Data TLB Accesses.
Replay of load/store due to DTLB miss
Value = 0, select = 9, mask = 0004. Data TLB Accesses.
HW-assisted TLB Refill completes
Value = 0, select = 9, mask = 0008. Data TLB Accesses.
DTLB Miss Exception
Value = 0, select = 10, mask = 0001. Load Instruction (Data Memory).
Data Cache Hit(unused)
Value = 0, select = 10, mask = 0002. Load Instruction (Data Memory).
Data Cache Miss(unused)
Value = 3, select = 10, mask = 0004. Load Instruction (Data Memory).
Load from local memory i.e. DataRAM, DataROM, InstRAM, InstROM
Value = 0, select = 10, mask = 0008. Load Instruction (Data Memory).
Bypass (i.e. uncached) load
Value = 0, select = 13, mask = 0001. Load Instruction (Data Memory).
Data Cache Hit(unused)
Value = 0, select = 13, mask = 0002. Load Instruction (Data Memory).
Data Cache Miss(unused)
Value = 0, select = 13, mask = 0004. Load Instruction (Data Memory).
Load from local memory i.e. DataRAM, DataROM, InstRAM, InstROM
Value = 0, select = 13, mask = 0008. Load Instruction (Data Memory).
Bypass (i.e. uncached) load
Value = 0, select = 16, mask = 0001. Load Instruction (Data Memory).
Data Cache Hit (unused)
Value = 0, select = 16, mask = 0002. Load Instruction (Data Memory).
Data Cache Miss (unused)
Value = 0, select = 16, mask = 0004. Load Instruction (Data Memory).
Load from local memory i.e. DataRAM, DataROM, InstRAM, InstROM
Value = 0, select = 16, mask = 0008. Load Instruction (Data Memory).
Bypass (i.e. uncached) load
Value = 0, select = 11, mask = 0001. Store Instruction (Data Memory).
Data Cache Hit (unused)
Value = 0, select = 11, mask = 0002. Store Instruction (Data Memory).
Data Cache Miss (unused)
Value = 0, select = 11, mask = 0004. Store Instruction (Data Memory).
Store to local memory i.e. DataRAM, InstRAM
Value = 0, select = 11, mask = 0008. Store Instruction (Data Memory).
PIF Store
Value = 0, select = 14, mask = 0001. Store Instruction (Data Memory).
Data Cache Hit(unused)
Value = 0, select = 14, mask = 0002. Store Instruction (Data Memory).
Data Cache Miss(unused)
Value = 0, select = 14, mask = 0004. Store Instruction (Data Memory).
Store to local memory i.e. DataRAM, InstRAM
Value = 0, select = 14, mask = 0008. Store Instruction (Data Memory).
PIF Store
Value = 0, select = 17, mask = 0001. Store Instruction (Data Memory).
Data Cache Hit (unused)
Value = 0, select = 17, mask = 0002. Store Instruction (Data Memory).
Data Cache Miss (unused)
Value = 0, select = 17, mask = 0004. Store Instruction (Data Memory).
Store to local memory i.e. DataRAM, InstRAM
Value = 0, select = 17, mask = 0008. Store Instruction (Data Memory).
PIF Store
Value = 0, select = 12, mask = 0001. Accesses to Data Memory (Load, Sto
re, S32C1I, ...).
Cache Miss
Value = 0, select = 15, mask = 0001. Accesses to Data Memory (Load, Sto
re, S32C1I, ...).
Cache Miss
Value = 0, select = 18, mask = 0001. Accesses to Data Memory (Load, Sto
re, S32C1I, ...).
Cache Miss
Value = 415, select = 22, mask = 0001. Multiple Load/Store.
0 stores and 0 loads
Value = 3, select = 22, mask = 0002. Multiple Load/Store.
0 stores and 1 loads
Value = 0, select = 22, mask = 0004. Multiple Load/Store.
1 stores and 0 loads
Value = 0, select = 22, mask = 0008. Multiple Load/Store.
1 stores and 1 loads
Value = 0, select = 22, mask = 0010. Multiple Load/Store.
0 stores and 2 loads
Value = 0, select = 22, mask = 0020. Multiple Load/Store.
2 stores and 0 loads
Value = 0, select = 23, mask = 0001. Outbound PIF.
Castout
Value = 0, select = 23, mask = 0002. Outbound PIF.
Prefetch
Value = 0, select = 24, mask = 0001. Inbound PIF.
Data DMA
Value = 0, select = 24, mask = 0002. Inbound PIF.
Instruction DMA
Value = 0, select = 26, mask = 0001. Prefetch.
I prefetch-buffer-lookup hit
Value = 0, select = 26, mask = 0002. Prefetch.
D prefetch-buffer-lookup hit
Value = 0, select = 26, mask = 0004. Prefetch.
I prefetch-buffer-lookup miss
Value = 0, select = 26, mask = 0008. Prefetch.
D prefetch-buffer-lookup miss
Value = 0, select = 26, mask = 0020. Prefetch.
Direct fill to (L1) Data Cache (unused)
Value = 0, select = 27, mask = 0001. iDMA.
active cycles
Value = 0, select = 28, mask = 0001. Length of Instructions.
16-bit
Value = 0, select = 28, mask = 0002. Length of Instructions.
24-bit
Value = 0, select = 28, mask = 0004. Length of Instructions.
32-bit
Value = 0, select = 28, mask = 0008. Length of Instructions.
40-bit
Value = 0, select = 28, mask = 0010. Length of Instructions.
48-bit
Value = 0, select = 28, mask = 0020. Length of Instructions.
56-bit
Value = 0, select = 28, mask = 0040. Length of Instructions.
64-bit
Value = 0, select = 28, mask = 0080. Length of Instructions.
72-bit
Value = 0, select = 28, mask = 0100. Length of Instructions.
80-bit
Value = 0, select = 28, mask = 0200. Length of Instructions.
88-bit
Value = 0, select = 28, mask = 0400. Length of Instructions.
96-bit
Value = 0, select = 28, mask = 0800. Length of Instructions.
104-bit
Value = 0, select = 28, mask = 1000. Length of Instructions.
112-bit
Value = 0, select = 28, mask = 2000. Length of Instructions.
120-bit
Value = 0, select = 28, mask = 4000. Length of Instructions.
128-bit
```
2. Example calls second test.
```
I (1588) example: Start test with user defined statistic
Value = 743, select = 0, mask = 0001. Counts cycles.
Amount of cycles
Value = 417, select = 2, mask = 8dff. Successfully Retired Instructions.
JX instructions
CALLXn instructions
return instructions (RET, RETW, ...)
supervisor return instructions (RFDE, RFE, RFI, RFWO, RFWU)
Conditional branch instructions where execution
transfers to the target (aka. taken branch),
or loopgtz/loopnez instr where execution skips
the loop (aka. not-taken loop)
J instr
CALLn instr
Conditional branch instr where execution
falls through (aka. not-taken branch)
Loop instr where execution falls into loop (aka. taken loop)
Last inst of loop and execution transfers
to LBEG (aka. loopback taken)
Last inst of loop and execution falls
through to LEND (aka. loopback fallthrough)
Non-branch instr (aka. non-CTI)
Value = 3, select = 10, mask = 0004. Load Instruction (Data Memory).
Load from local memory i.e. DataRAM, DataROM, InstRAM, InstROM
Value = 0, select = 11, mask = 0004. Store Instruction (Data Memory).
Store to local memory i.e. DataRAM, InstRAM
Value = 321, select = 6, mask = 01ed. Hold and Other Bubble cycles.
Processor domain PSO bubble
R hold caused by Data Cache miss(unused)
R hold caused by Store release
R hold caused by MEMW, EXTW or EXCW
R hold caused by Halt instruction (TX only)
CTI bubble (e.g. branch delay slot)
WAITI bubble i.e. a cycle spent in WaitI power down mode.
Value = 0, select = 6, mask = 0010. Hold and Other Bubble cycles.
R hold caused by register dependency
Value = 0, select = 1, mask = 0001. Overflow of counter.
Overflow counter
I (1788) example: The End
```

View file

@ -0,0 +1,4 @@
set(COMPONENT_SRCS "perfmon_example_main.c")
set(COMPONENT_ADD_INCLUDEDIRS ".")
register_component()

View file

@ -0,0 +1,5 @@
#
# "main" pseudo-component makefile.
#
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)

View file

@ -0,0 +1,71 @@
/* perfmon (performance monitor) example
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "esp_timer.h"
#include "esp_log.h"
#include "esp_sleep.h"
#include "sdkconfig.h"
#include "perfmon.h"
static const char* TAG = "example";
static void exec_test_function(void *params)
{
for (int i = 0 ; i < 100 ; i++) {
__asm__ __volatile__(" nop");
}
}
// Table with dedicated performance counters
static uint32_t pm_check_table[] = {
XTPERF_CNT_CYCLES, XTPERF_MASK_CYCLES, // total cycles
XTPERF_CNT_INSN, XTPERF_MASK_INSN_ALL, // total instructions
XTPERF_CNT_D_LOAD_U1, XTPERF_MASK_D_LOAD_LOCAL_MEM, // Mem read
XTPERF_CNT_D_STORE_U1, XTPERF_MASK_D_STORE_LOCAL_MEM, // Mem write
XTPERF_CNT_BUBBLES, XTPERF_MASK_BUBBLES_ALL &(~XTPERF_MASK_BUBBLES_R_HOLD_REG_DEP), // wait for other reasons
XTPERF_CNT_BUBBLES, XTPERF_MASK_BUBBLES_R_HOLD_REG_DEP, // Wait for register dependency
XTPERF_CNT_OVERFLOW, XTPERF_MASK_OVERFLOW, // Last test cycle
};
#define TOTAL_CALL_AMOUNT 200
#define PERFMON_TRACELEVEL -1 // -1 - will ignore trace level
void app_main(void)
{
ESP_LOGI(TAG, "Start");
ESP_LOGI(TAG, "Start test with printing all available statistic");
xtensa_perfmon_config_t pm_config = {};
pm_config.counters_size = sizeof(xtensa_perfmon_select_mask_all) / sizeof(uint32_t) / 2;
pm_config.select_mask = xtensa_perfmon_select_mask_all;
pm_config.repeat_count = TOTAL_CALL_AMOUNT;
pm_config.max_deviation = 1;
pm_config.call_function = exec_test_function;
pm_config.callback = xtensa_perfmon_view_cb;
pm_config.callback_params = stdout;
pm_config.tracelevel = PERFMON_TRACELEVEL;
xtensa_perfmon_exec(&pm_config);
ESP_LOGI(TAG, "Start test with user defined statistic");
pm_config.counters_size = sizeof(pm_check_table) / sizeof(uint32_t) / 2;
pm_config.select_mask = pm_check_table;
pm_config.repeat_count = TOTAL_CALL_AMOUNT;
pm_config.max_deviation = 1;
pm_config.call_function = exec_test_function;
pm_config.callback = xtensa_perfmon_view_cb;
pm_config.callback_params = stdout;
pm_config.tracelevel = PERFMON_TRACELEVEL;
xtensa_perfmon_exec(&pm_config);
ESP_LOGI(TAG, "The End");
}