xtensa_perfmon_apis.c 3.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. // Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include <stdlib.h>
  15. #include "xtensa_perfmon_apis.h"
  16. #include "xtensa_perfmon_masks.h"
  17. static const char *TAG = "perfmon";
  18. esp_err_t xtensa_perfmon_exec(const xtensa_perfmon_config_t *config)
  19. {
  20. esp_err_t result = ESP_OK;
  21. if (config->call_function == NULL) {
  22. ESP_LOGE(TAG, "Parameter call_function must be defined.");
  23. return ESP_ERR_INVALID_ARG;
  24. }
  25. if (config->callback == NULL) {
  26. ESP_LOGE(TAG, "Parameter callback must be defined.");
  27. return ESP_ERR_INVALID_ARG;
  28. }
  29. for (size_t n = 0; n < config->counters_size; n++) {
  30. uint32_t call_min = UINT32_MAX;
  31. uint32_t call_max = 0;
  32. float result_value = 0;
  33. for (size_t i = 0; i < config->repeat_count; i++) {
  34. // Set up cycle counter
  35. xtensa_perfmon_stop();
  36. int kernelcnt = 0;
  37. // if tracelevel used, then kernelcnt will be enabled
  38. if (config->tracelevel >=0) kernelcnt = 1;
  39. xtensa_perfmon_init(0, 0, 0xffff, kernelcnt, config->tracelevel);
  40. xtensa_perfmon_init(1, config->select_mask[n * 2 + 0], config->select_mask[n * 2 + 1], kernelcnt, config->tracelevel);
  41. xtensa_perfmon_start();
  42. config->call_function(config->call_params);
  43. xtensa_perfmon_stop();
  44. uint32_t p0 = xtensa_perfmon_value(0);
  45. uint32_t p1 = xtensa_perfmon_value(1);
  46. result_value += (float)p1 / config->repeat_count;
  47. if (p0 < call_min) {
  48. call_min = p0;
  49. }
  50. if (p0 > call_max) {
  51. call_max = p0;
  52. }
  53. ESP_LOGV(TAG, "p0 = %i, p1 = %i", p0, p1);
  54. }
  55. uint32_t call_diff = (call_max - call_min);
  56. if (call_diff > call_max * config->max_deviation) {
  57. return ESP_FAIL;
  58. } else {
  59. config->callback(config->callback_params, config->select_mask[n * 2 + 0], config->select_mask[n * 2 + 1], (uint32_t)result_value);
  60. }
  61. }
  62. return result;
  63. }
  64. void xtensa_perfmon_view_cb(void *params, uint32_t select, uint32_t mask, uint32_t value)
  65. {
  66. FILE *handle;
  67. if (params != NULL) {
  68. handle = (FILE *)params;
  69. } else {
  70. handle = stdout;
  71. }
  72. for (int i = 0 ; xtensa_perfmon_select_table[i].select != -1; i++) {
  73. if (xtensa_perfmon_select_table[i].select == select) {
  74. fprintf(handle, "Value = %9i, select = %2i, mask = %04x. %s.\n", value, select, mask, xtensa_perfmon_select_table[i].description);
  75. }
  76. }
  77. for (int i = 0 ; xtensa_perfmon_masks_table[i].select != -1; i++) {
  78. if ((xtensa_perfmon_masks_table[i].select == select) && (xtensa_perfmon_masks_table[i].mask & mask)) {
  79. fprintf(handle, " %s\n", xtensa_perfmon_masks_table[i].description);
  80. }
  81. }
  82. }