@@ -240,7 +240,47 @@ static int parse_input_args(int argc, char **argv, struct testbench_prm *tp)
240240 return ret ;
241241}
242242
243- static void test_pipeline_stats (struct testbench_prm * tp , long long delta_t )
243+ #if CONFIG_IPC_MAJOR_4
244+ static int tb_collect_heap_usage (struct testbench_prm * tp , struct tb_heap_usage_record * records ,
245+ int * count_out )
246+ {
247+ struct list_item * item ;
248+ int count = 0 ;
249+
250+ list_for_item (item , & tp -> widget_list ) {
251+ struct tplg_comp_info * info = container_of (item , struct tplg_comp_info , item );
252+ uint32_t comp_id = IPC4_COMP_ID (info -> module_id , info -> instance_id );
253+ struct comp_dev * dev = ipc4_get_comp_dev (comp_id );
254+
255+ if (!dev || !dev -> mod )
256+ continue ;
257+
258+ /* In testbench environment, skip AIF/DAI because they are not real components. */
259+ if (info -> type == SND_SOC_TPLG_DAPM_AIF_IN ||
260+ info -> type == SND_SOC_TPLG_DAPM_AIF_OUT ||
261+ info -> type == SND_SOC_TPLG_DAPM_DAI_IN ||
262+ info -> type == SND_SOC_TPLG_DAPM_DAI_OUT )
263+ continue ;
264+
265+ if (count >= TB_NUM_WIDGETS_SUPPORTED ) {
266+ fprintf (stderr , "Error: Too many components for heap records, max %d.\n" ,
267+ TB_NUM_WIDGETS_SUPPORTED );
268+ break ;
269+ }
270+
271+ records [count ].module_name = info -> name ;
272+ records [count ].heap_max = dev -> mod -> priv .resources .heap_high_water_mark ;
273+ count ++ ;
274+ }
275+
276+ * count_out = count ;
277+ return 0 ;
278+ }
279+ #endif
280+
281+ static void test_pipeline_stats (struct testbench_prm * tp , long long delta_t ,
282+ struct tb_heap_usage_record * heap_records ,
283+ int heap_records_count )
244284{
245285 long long file_cycles , pipeline_cycles ;
246286 float pipeline_mcps ;
@@ -295,11 +335,15 @@ static void test_pipeline_stats(struct testbench_prm *tp, long long delta_t)
295335 printf ("Warning: Use -d 3 or smaller value to avoid traces to increase MCPS.\n" );
296336 }
297337
298- if (delta_t )
299- printf ("Total execution time: %lld us, %.2f x realtime\n" ,
300- delta_t , (float )frames_out / tp -> fs_out * 1000000 / delta_t );
338+ if (heap_records_count > 0 ) {
339+ for (i = 0 ; i < heap_records_count ; i ++ )
340+ printf ("Heap usage for module %s: %u bytes\n" ,
341+ heap_records [i ].module_name , (uint32_t )heap_records [i ].heap_max );
342+ }
301343
302- printf ("\n" );
344+ if (delta_t )
345+ printf ("Total execution time: %lld us, %.2f x realtime\n\n" , delta_t ,
346+ (float )frames_out / tp -> fs_out * 1000000 / delta_t );
303347}
304348
305349/*
@@ -308,14 +352,16 @@ static void test_pipeline_stats(struct testbench_prm *tp, long long delta_t)
308352 */
309353static int pipline_test (struct testbench_prm * tp )
310354{
311- float samples_to_ns ;
312- int dp_count = 0 ;
313- struct timespec td0 , td1 ;
355+ struct tb_heap_usage_record heap_usage_records [TB_NUM_WIDGETS_SUPPORTED ];
314356 struct file_state * out_stat ;
357+ struct timespec td0 , td1 ;
315358 long long delta_t ;
316359 int64_t next_control_ns ;
317360 int64_t time_ns ;
361+ float samples_to_ns ;
318362 int err ;
363+ int heap_usage_records_count = 0 ;
364+ int dp_count = 0 ;
319365
320366 /* build, run and teardown pipelines */
321367 while (dp_count < tp -> dynamic_pipeline_iterations ) {
@@ -396,6 +442,9 @@ static int pipline_test(struct testbench_prm *tp)
396442 tb_gettime (& td1 );
397443
398444out :
445+ #if CONFIG_IPC_MAJOR_4
446+ tb_collect_heap_usage (tp , heap_usage_records , & heap_usage_records_count );
447+ #endif
399448 err = tb_set_reset_state (tp );
400449 if (err < 0 ) {
401450 fprintf (stderr , "error: pipeline reset %d failed %d\n" ,
@@ -408,7 +457,7 @@ static int pipline_test(struct testbench_prm *tp)
408457 */
409458 delta_t = (td1 .tv_sec - td0 .tv_sec ) * 1000000 ;
410459 delta_t += (td1 .tv_nsec - td0 .tv_nsec ) / 1000 ;
411- test_pipeline_stats (tp , delta_t );
460+ test_pipeline_stats (tp , delta_t , heap_usage_records , heap_usage_records_count );
412461
413462 err = tb_free_all_pipelines (tp );
414463 if (err < 0 ) {
0 commit comments