Skip to content

Commit

Permalink
performance measurements: extend perf meas state ipc
Browse files Browse the repository at this point in the history
Implement actual functionality for perf meas state ipc handling. This
enables changing the state of global performance measurements.

Signed-off-by: Tobiasz Dryjanski <tobiaszx.dryjanski@intel.com>
  • Loading branch information
tobonex committed Jun 3, 2024
1 parent 0565dad commit 96082f2
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 13 deletions.
12 changes: 10 additions & 2 deletions src/audio/base_fw.c
Original file line number Diff line number Diff line change
Expand Up @@ -413,13 +413,21 @@ int set_perf_meas_state(const char *data)

switch (state) {
case IPC4_PERF_MEASUREMENTS_DISABLED:
disable_performance_counters();
perf_meas_set_state(IPC4_PERF_MEASUREMENTS_DISABLED);
break;
case IPC4_PERF_MEASUREMENTS_STOPPED:
for (int i = 0; i < CONFIG_MAX_CORE_COUNT; i++)
systick_info[i].peak_utilization = 0;
enable_performance_counters();
reset_performance_counters();
perf_meas_set_state(IPC4_PERF_MEASUREMENTS_STOPPED);
break;
case IPC4_PERF_MEASUREMENTS_STARTED:
enable_performance_counters();
perf_meas_set_state(IPC4_PERF_MEASUREMENTS_STARTED);
break;
case IPC4_PERF_MEASUREMENTS_PAUSED:
enable_performance_counters();
perf_meas_set_state(IPC4_PERF_MEASUREMENTS_PAUSED);
break;
default:
return -EINVAL;
Expand Down
16 changes: 10 additions & 6 deletions src/audio/component.c
Original file line number Diff line number Diff line change
Expand Up @@ -542,14 +542,18 @@ bool update_peak_of_measured_cpc(struct comp_dev *dev, size_t measured_cpc)
bool comp_update_performance_data(struct comp_dev *dev, uint32_t cycles_used)
{
struct perf_data_item_comp *item = dev->perf_data.perf_data_item;
/* we divide by ibs so we need to check if its set */
if (item && dev->ibs != 0) {
item->total_iteration_count++;
item->total_cycles_consumed += cycles_used;
item->item.avg_kcps = item->total_cycles_consumed * dev->ll_chunk_size_

if (perf_meas_get_state() == IPC4_PERF_MEASUREMENTS_STARTED) {
/* we divide by ibs so we need to check if its set */
if (item && dev->ibs != 0) {
item->total_iteration_count++;
item->total_cycles_consumed += cycles_used;
item->item.avg_kcps = item->total_cycles_consumed * dev->ll_chunk_size_
/ (dev->ibs * item->total_iteration_count);
item->item.peak_kcps = MAX(item->item.peak_kcps, (cycles_used * dev->ll_chunk_size_)
item->item.peak_kcps =
MAX(item->item.peak_kcps, (cycles_used * dev->ll_chunk_size_)
/ dev->ibs);
}
}
return update_peak_of_measured_cpc(dev, cycles_used);
}
Expand Down
107 changes: 103 additions & 4 deletions src/debug/telemetry/telemetry.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
#include <stddef.h>
#include <stdint.h>

#include <sof/lib_manager.h>
#include <ipc4/base_fw_vendor.h>

LOG_MODULE_DECLARE(ipc, CONFIG_SOF_LOG_LEVEL);

#define PERFORMANCE_DATA_ENTRIES_COUNT (CONFIG_MEMORY_WIN_3_SIZE / sizeof(struct perf_data_item_comp))
Expand All @@ -37,6 +40,12 @@ struct perf_bitmap performance_data_bitmap;

volatile struct perf_data_item_comp *perf_data_;

/* Note that ref. FW used one state per core, all set together to the same state
* by one IPC but only for active cores. It may work slightly different in case
* where we enable a core while perf meas is started.
*/
enum ipc4_perf_measurements_state_set perf_measurements_state = IPC4_PERF_MEASUREMENTS_DISABLED;

int perf_bitmap_init(struct perf_bitmap * const bitmap, sys_bitarray_t *array, size_t size)
{
bitmap->array = array;
Expand Down Expand Up @@ -198,9 +207,15 @@ int free_performance_data(struct perf_data_item_comp *item)

if (item) {
item->item.is_removed = true;
ret = perf_data_free(item);
if (ret < 0)
return -EINVAL;
/* if we don't get the disabled state now, item will be
* deleted on next disable perf meas message
*/
if (perf_measurements_state == IPC4_PERF_MEASUREMENTS_DISABLED) {
int ret = perf_data_free(item);

if (ret < 0)
return -EINVAL;
}
}
return IPC4_SUCCESS;
}
Expand Down Expand Up @@ -266,7 +281,91 @@ int get_extended_performance_data(struct extended_global_perf_data * const ext_g
return IPC4_SUCCESS;
}

//==============================================================================================
enum ipc4_perf_measurements_state_set perf_meas_get_state(void)
{
return perf_measurements_state;
}

void perf_meas_set_state(enum ipc4_perf_measurements_state_set state)
{
perf_measurements_state = state;
}

void disable_performance_counters(void)
{
for (size_t idx = 0; idx < perf_bitmap_get_size(&performance_data_bitmap); ++idx) {
if (perf_bitmap_is_bit_clear(&performance_data_bitmap, idx))
continue;
if (perf_data_[idx].item.is_removed)
perf_data_free(&perf_data_[idx]);
}
}

int enable_performance_counters(void)
{
//struct sof_man_fw_header header;
struct sof_man_module *man_module;
struct comp_dev *dev;
uint32_t comp_id;
const struct sof_man_fw_desc *desc;

if (perf_measurements_state != IPC4_PERF_MEASUREMENTS_DISABLED)
return -EINVAL;

for (int lib_id = 0; lib_id < LIB_MANAGER_MAX_LIBS; ++lib_id) {
if (lib_id == 0) {
desc = basefw_vendor_get_manifest();
} else {
#if CONFIG_LIBRARY_MANAGER
desc = (struct sof_man_fw_desc *)lib_manager_get_library_manifest(lib_id);
#else
desc = NULL;
#endif
}
if (!desc)
continue;

for (int mod_id = 0 ; mod_id < desc->header.num_module_entries; mod_id++) {
man_module =
(struct sof_man_module *)(desc + SOF_MAN_MODULE_OFFSET(mod_id));

for (int inst_id = 0; inst_id < man_module->instance_max_count; inst_id++) {
comp_id = IPC4_COMP_ID(mod_id, inst_id);
dev = ipc4_get_comp_dev(comp_id);

if (dev)
comp_init_performance_data(dev);
}
}
}

/* TODO clear totaldspcycles here once implemented */
return IPC4_SUCCESS;
}

int reset_performance_counters(void)
{
if (perf_measurements_state == IPC4_PERF_MEASUREMENTS_DISABLED)
return -EINVAL;

struct telemetry_wnd_data *wnd_data =
(struct telemetry_wnd_data *)ADSP_DW->slots[SOF_DW_TELEMETRY_SLOT];
struct system_tick_info *systick_info =
(struct system_tick_info *)wnd_data->system_tick_info;

for (size_t core_id = 0; core_id < CONFIG_MAX_CORE_COUNT; ++core_id) {
if (!(cpu_enabled_cores() & BIT(core_id)))
continue;
systick_info[core_id].peak_utilization = 0;
}
for (size_t idx = 0; idx < perf_bitmap_get_size(&performance_data_bitmap); ++idx) {
if (!perf_bitmap_is_bit_clear(&performance_data_bitmap, idx))
perf_data_item_comp_reset(&perf_data_[idx]);
}
/* TODO clear totaldspcycles here once implemented */

return IPC4_SUCCESS;
}

/* Systic variables, one set per core */
static int telemetry_systick_counter[CONFIG_MAX_CORE_COUNT];
Expand Down
7 changes: 7 additions & 0 deletions src/include/sof/debug/telemetry/telemetry.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,4 +106,11 @@ int get_performance_data(struct global_perf_data * const global_perf_data);

int get_extended_performance_data(struct extended_global_perf_data * const ext_global_perf_data);

int reset_performance_counters(void);
int enable_performance_counters(void);
void disable_performance_counters(void);

void perf_meas_set_state(enum ipc4_perf_measurements_state_set state);
enum ipc4_perf_measurements_state_set perf_meas_get_state(void);

#endif /*__SOF_TELEMETRY_H__ */
3 changes: 2 additions & 1 deletion src/ipc/ipc4/helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,8 @@ struct comp_dev *comp_new_ipc4(struct ipc4_module_init_instance *module_init)
/* this can be null, just no performance measurements in this case */
if (dev->perf_data.perf_data_item) {
dev->perf_data.perf_data_item->item.resource_id = comp_id;
comp_init_performance_data(dev);
if (perf_meas_get_state() != IPC4_PERF_MEASUREMENTS_DISABLED)
comp_init_performance_data(dev);
}

ipc4_add_comp_dev(dev);
Expand Down

0 comments on commit 96082f2

Please sign in to comment.