Performance monitor component. The component contains APIs, example and
documentation.
This commit is contained in:
parent
2f557d1a59
commit
a0730fec2a
25 changed files with 1560 additions and 3 deletions
7
components/perfmon/CMakeLists.txt
Normal file
7
components/perfmon/CMakeLists.txt
Normal 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")
|
0
components/perfmon/component.mk
Normal file
0
components/perfmon/component.mk
Normal file
29
components/perfmon/include/perfmon.h
Normal file
29
components/perfmon/include/perfmon.h
Normal 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_
|
125
components/perfmon/include/xtensa_perfmon_access.h
Normal file
125
components/perfmon/include/xtensa_perfmon_access.h
Normal 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_
|
80
components/perfmon/include/xtensa_perfmon_apis.h
Normal file
80
components/perfmon/include/xtensa_perfmon_apis.h
Normal 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_
|
74
components/perfmon/include/xtensa_perfmon_masks.h
Normal file
74
components/perfmon/include/xtensa_perfmon_masks.h
Normal 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_
|
7
components/perfmon/test/CMakeLists.txt
Normal file
7
components/perfmon/test/CMakeLists.txt
Normal file
|
@ -0,0 +1,7 @@
|
|||
set(COMPONENT_SRCDIRS
|
||||
"."
|
||||
)
|
||||
set(COMPONENT_ADD_INCLUDEDIRS ".")
|
||||
set(COMPONENT_REQUIRES unity xtensa perfmon)
|
||||
|
||||
register_component()
|
5
components/perfmon/test/component.mk
Normal file
5
components/perfmon/test/component.mk
Normal file
|
@ -0,0 +1,5 @@
|
|||
COMPONENT_SRCDIRS := \
|
||||
.
|
||||
|
||||
COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive
|
||||
|
193
components/perfmon/test/test_perfmon_ansi.c
Normal file
193
components/perfmon/test/test_perfmon_ansi.c
Normal 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.");
|
||||
}
|
||||
|
88
components/perfmon/xtensa_perfmon_access.c
Normal file
88
components/perfmon/xtensa_perfmon_access.c
Normal 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;
|
||||
}
|
88
components/perfmon/xtensa_perfmon_apis.c
Normal file
88
components/perfmon/xtensa_perfmon_apis.c
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
299
components/perfmon/xtensa_perfmon_masks.c
Normal file
299
components/perfmon/xtensa_perfmon_masks.c
Normal 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
|
||||
};
|
|
@ -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 counter’s overflow caused PerfMonInt to be asserted.
|
||||
|
||||
|
||||
#define PGM_PMEN (1<<0) // Overall enable for all performance counting
|
||||
|
||||
|
||||
#endif
|
|
@ -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__ */
|
||||
|
|
|
@ -252,7 +252,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
|
||||
|
|
|
@ -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>
|
||||
|
|
26
docs/en/api-reference/system/perfmon.rst
Normal file
26
docs/en/api-reference/system/perfmon.rst
Normal 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
|
||||
|
1
docs/zh_CN/api-reference/system/perfmon.rst
Normal file
1
docs/zh_CN/api-reference/system/perfmon.rst
Normal file
|
@ -0,0 +1 @@
|
|||
.. include:: ../../../en/api-reference/system/perfmon.rst
|
6
examples/system/perfmon/CMakeLists.txt
Normal file
6
examples/system/perfmon/CMakeLists.txt
Normal 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)
|
9
examples/system/perfmon/Makefile
Normal file
9
examples/system/perfmon/Makefile
Normal 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
|
||||
|
365
examples/system/perfmon/README.md
Normal file
365
examples/system/perfmon/README.md
Normal 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
|
||||
|
||||
```
|
4
examples/system/perfmon/main/CMakeLists.txt
Normal file
4
examples/system/perfmon/main/CMakeLists.txt
Normal file
|
@ -0,0 +1,4 @@
|
|||
set(COMPONENT_SRCS "perfmon_example_main.c")
|
||||
set(COMPONENT_ADD_INCLUDEDIRS ".")
|
||||
|
||||
register_component()
|
5
examples/system/perfmon/main/component.mk
Normal file
5
examples/system/perfmon/main/component.mk
Normal file
|
@ -0,0 +1,5 @@
|
|||
#
|
||||
# "main" pseudo-component makefile.
|
||||
#
|
||||
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
|
||||
|
71
examples/system/perfmon/main/perfmon_example_main.c
Normal file
71
examples/system/perfmon/main/perfmon_example_main.c
Normal 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");
|
||||
}
|
0
examples/system/perfmon/sdkconfig.defaults
Normal file
0
examples/system/perfmon/sdkconfig.defaults
Normal file
Loading…
Reference in a new issue