From 1f843bd4b040fb3988ba4f18fdc2d0421a82726d Mon Sep 17 00:00:00 2001 From: Shuchita Khare Date: Wed, 21 Feb 2024 14:00:36 +0000 Subject: [PATCH 1/2] Modify backpressure test to something sensible --- test/build_lib_i2s_tests.sh | 24 --- .../backpressure_test/backpressure_test.cmake | 2 +- test/lib_i2s/backpressure_test/src/main.c | 163 +++++++++++++++--- test/lib_i2s/test_backpressure.py | 5 +- 4 files changed, 143 insertions(+), 51 deletions(-) diff --git a/test/build_lib_i2s_tests.sh b/test/build_lib_i2s_tests.sh index ecc5678..de3aa19 100755 --- a/test/build_lib_i2s_tests.sh +++ b/test/build_lib_i2s_tests.sh @@ -9,18 +9,6 @@ source ${FRAMEWORK_IO_ROOT}/tools/ci/helper_functions.sh # row format is: "make_target BOARD toolchain" declare -a applications=( - "test_hil_backpressure_test_32_768000_4_5_5" - "test_hil_backpressure_test_32_768000_4_0_10" - "test_hil_backpressure_test_32_768000_4_10_0" - "test_hil_backpressure_test_32_768000_3_5_5" - "test_hil_backpressure_test_32_768000_3_0_10" - "test_hil_backpressure_test_32_768000_3_10_0" - "test_hil_backpressure_test_32_768000_2_5_5" - "test_hil_backpressure_test_32_768000_2_0_10" - "test_hil_backpressure_test_32_768000_2_10_0" - "test_hil_backpressure_test_32_768000_1_5_5" - "test_hil_backpressure_test_32_768000_1_0_10" - "test_hil_backpressure_test_32_768000_1_10_0" "test_hil_backpressure_test_32_384000_4_5_5" "test_hil_backpressure_test_32_384000_4_0_10" "test_hil_backpressure_test_32_384000_4_10_0" @@ -81,18 +69,6 @@ declare -a applications=( "test_hil_i2s_slave_test_32_1_4_0_inv" "test_hil_i2s_slave_test_32_1_0_4_inv" "test_hil_i2s_slave_test_32_1_2_2_inv" - "test_hil_backpressure_test_16_768000_4_5_5" - "test_hil_backpressure_test_16_768000_4_0_10" - "test_hil_backpressure_test_16_768000_4_10_0" - "test_hil_backpressure_test_16_768000_3_5_5" - "test_hil_backpressure_test_16_768000_3_0_10" - "test_hil_backpressure_test_16_768000_3_10_0" - "test_hil_backpressure_test_16_768000_2_5_5" - "test_hil_backpressure_test_16_768000_2_0_10" - "test_hil_backpressure_test_16_768000_2_10_0" - "test_hil_backpressure_test_16_768000_1_5_5" - "test_hil_backpressure_test_16_768000_1_0_10" - "test_hil_backpressure_test_16_768000_1_10_0" "test_hil_backpressure_test_16_384000_4_5_5" "test_hil_backpressure_test_16_384000_4_0_10" "test_hil_backpressure_test_16_384000_4_10_0" diff --git a/test/lib_i2s/backpressure_test/backpressure_test.cmake b/test/lib_i2s/backpressure_test/backpressure_test.cmake index 554780d..4a14538 100644 --- a/test/lib_i2s/backpressure_test/backpressure_test.cmake +++ b/test/lib_i2s/backpressure_test/backpressure_test.cmake @@ -24,7 +24,7 @@ set(APP_LINK_OPTIONS # Tile Targets #********************** if(NOT DEFINED ENV{SAMPLE_RATES}) - set(SAMPLE_RATES 768000 384000 192000) + set(SAMPLE_RATES 384000 192000) else() set(SAMPLE_RATES $ENV{SAMPLE_RATES}) endif() diff --git a/test/lib_i2s/backpressure_test/src/main.c b/test/lib_i2s/backpressure_test/src/main.c index d28db53..70e350a 100644 --- a/test/lib_i2s/backpressure_test/src/main.c +++ b/test/lib_i2s/backpressure_test/src/main.c @@ -14,7 +14,7 @@ #define BURN_THREADS 6 #endif #ifndef SAMPLE_FREQUENCY -#define SAMPLE_FREQUENCY 768000 +#define SAMPLE_FREQUENCY 192000 #endif #ifndef TEST_LEN #define TEST_LEN 1000 @@ -44,6 +44,115 @@ #define SETSR(c) asm volatile("setsr %0" : : "n"(c)); +enum { + SAMPLE_RATE_192000, + SAMPLE_RATE_384000, + NUM_SAMPLE_RATES +}e_sample_rates; + +enum { + BITDEPTH_16, + BITDEPTH_32, + NUM_BIT_DEPTHS +}e_bit_depth; + +enum { + NUM_I2S_LINES_1, + NUM_I2S_LINES_2, + NUM_I2S_LINES_3, + NUM_I2S_LINES_4, +}e_channel_config; + +static int acceptable_receive_delay = 0, acceptable_send_delay = 0; +static int acceptable_delay_ticks[NUM_SAMPLE_RATES][NUM_I2S_LINES_4+1][NUM_BIT_DEPTHS]; + +static inline void populate_acceptable_delay_ticks() +{ + // These numbers are logged by running the test and logging the delay at the point at which the + // backpressure test starts failing. + + // 192 KHz + acceptable_delay_ticks[SAMPLE_RATE_192000][NUM_I2S_LINES_1][BITDEPTH_16] = 185; + acceptable_delay_ticks[SAMPLE_RATE_192000][NUM_I2S_LINES_1][BITDEPTH_32] = 200; + acceptable_delay_ticks[SAMPLE_RATE_192000][NUM_I2S_LINES_2][BITDEPTH_16] = 155; + acceptable_delay_ticks[SAMPLE_RATE_192000][NUM_I2S_LINES_2][BITDEPTH_32] = 170; + acceptable_delay_ticks[SAMPLE_RATE_192000][NUM_I2S_LINES_3][BITDEPTH_16] = 130; + acceptable_delay_ticks[SAMPLE_RATE_192000][NUM_I2S_LINES_3][BITDEPTH_32] = 150; + acceptable_delay_ticks[SAMPLE_RATE_192000][NUM_I2S_LINES_4][BITDEPTH_16] = 100; + acceptable_delay_ticks[SAMPLE_RATE_192000][NUM_I2S_LINES_4][BITDEPTH_32] = 125; + + // 384 KHz + acceptable_delay_ticks[SAMPLE_RATE_384000][NUM_I2S_LINES_1][BITDEPTH_16] = 60; + acceptable_delay_ticks[SAMPLE_RATE_384000][NUM_I2S_LINES_1][BITDEPTH_32] = 70; + acceptable_delay_ticks[SAMPLE_RATE_384000][NUM_I2S_LINES_2][BITDEPTH_16] = 35; + acceptable_delay_ticks[SAMPLE_RATE_384000][NUM_I2S_LINES_2][BITDEPTH_32] = 45; + acceptable_delay_ticks[SAMPLE_RATE_384000][NUM_I2S_LINES_3][BITDEPTH_16] = 5; + acceptable_delay_ticks[SAMPLE_RATE_384000][NUM_I2S_LINES_3][BITDEPTH_32] = 20; + acceptable_delay_ticks[SAMPLE_RATE_384000][NUM_I2S_LINES_4][BITDEPTH_16] = 0; + acceptable_delay_ticks[SAMPLE_RATE_384000][NUM_I2S_LINES_4][BITDEPTH_32] = 0; +} + +void get_acceptable_delay() +{ + int sample_rate; + if(SAMPLE_FREQUENCY == 192000) + { + sample_rate = SAMPLE_RATE_192000; + } + else if(SAMPLE_FREQUENCY == 384000) + { + sample_rate = SAMPLE_RATE_384000; + } + else + { + printf("ERROR: Invalid sample rate %d\n", SAMPLE_FREQUENCY); + _Exit(1); + } + + int bit_depth; + if(DATA_BITS == 16) + { + bit_depth = BITDEPTH_16; + } + else if(DATA_BITS == 32) + { + bit_depth = BITDEPTH_32; + } + else + { + printf("ERROR: Invalid bit_depth %d\n", DATA_BITS); + _Exit(1); + } + if((NUM_I2S_LINES < 1) || (NUM_I2S_LINES > 4)) + { + printf("ERROR: Invalid NUM_I2S_LINES %d\n", NUM_I2S_LINES); + _Exit(1); + } + int delay = acceptable_delay_ticks[sample_rate][NUM_I2S_LINES-1][bit_depth]; + + // get the send and receive delay based on the + if((RECEIVE_DELAY_INCREMENT == 5) && (SEND_DELAY_INCREMENT == 5)) + { + acceptable_receive_delay = delay; + acceptable_send_delay = delay; + } + else if((RECEIVE_DELAY_INCREMENT == 0) && (SEND_DELAY_INCREMENT == 10)) + { + acceptable_receive_delay = 0; + acceptable_send_delay = 2*delay; + } + else if((RECEIVE_DELAY_INCREMENT == 10) && (SEND_DELAY_INCREMENT == 0)) + { + acceptable_receive_delay = 2*delay; + acceptable_send_delay = 0; + } + else + { + printf("ERROR: Unsupported receive (%d) and send (%d) delay increment combination\n", RECEIVE_DELAY_INCREMENT, SEND_DELAY_INCREMENT); + _Exit(1); + } +} + /* Ports and clocks used by the application */ port_t p_lrclk = XS1_PORT_1G; port_t p_bclk = XS1_PORT_1H; @@ -54,7 +163,7 @@ port_t p_din [4] = {XS1_PORT_1I, XS1_PORT_1J, XS1_PORT_1K, XS1_PORT_1L}; xclock_t mclk = XS1_CLKBLK_1; xclock_t bclk = XS1_CLKBLK_2; -static volatile int receive_delay = 5000; +static volatile int receive_delay = 0; static volatile int send_delay = 0; void i2s_init(void *app_data, i2s_config_t *i2s_config) @@ -85,11 +194,6 @@ i2s_restart_t i2s_restart_check(void *app_data) return I2S_NO_RESTART; } -#if DATA_BITS == 32 -#define OVERHEAD_TICKS 185 // Some of the period needs to be allowed for the callbacks -#else -#define OVERHEAD_TICKS 185 // Non-32b data widths take longer to process -#endif #define JITTER 1 //Allow for rounding so does not break when diff = period + 1 #define N_CYCLES_AT_DELAY 1 //How many LR clock cycles to measure at each backpressure delay value #define DIFF_WRAP_16(new, old) (new > old ? new - old : new + 0x10000 - old) @@ -121,28 +225,40 @@ void test_lr_period() { port_set_trigger_in_equal(p_lr_test, 0); (void) port_in(p_lr_test); counter++; - if (counter == N_CYCLES_AT_DELAY) { - receive_delay += RECEIVE_DELAY_INCREMENT; - send_delay += SEND_DELAY_INCREMENT; - if ((receive_delay + send_delay) > (period - OVERHEAD_TICKS)) { - printf("PASS\n"); - _Exit(0); - } - counter = 0; - } + port_set_trigger_in_equal(p_lr_test, 1); (void) port_in(p_lr_test); time = port_get_trigger_time(p_lr_test); int diff = DIFF_WRAP_16(time, time_old); if (diff > (period + JITTER)) { - printf("Backpressure breaks at receive delay ticks=%d, send delay ticks=%d\n", - receive_delay, send_delay); - printf("actual diff: %d, maximum (period + Jitter): %d\n", - diff, (period + JITTER)); - _Exit(1); + // The delay we're able to add in the i2s_receive() function should be acceptable_receive_delay ticks or more + if(receive_delay < acceptable_receive_delay) + { + printf("Backpressure breaks at receive delay ticks = %d, acceptable receive delay = %d\n", + receive_delay, acceptable_receive_delay); + printf("actual diff: %d, maximum (period + Jitter): %d\n", diff, (period + JITTER)); + _Exit(1); + } + + // The delay we're able to add in the i2s_send() function should be acceptable_send_delay ticks or more + if(send_delay < acceptable_send_delay) + { + printf("Backpressure breaks at send delay ticks = %d, acceptable send delay = %d\n", + send_delay, acceptable_send_delay); + printf("actual diff: %d, maximum (period + Jitter): %d\n", diff, (period + JITTER)); + _Exit(1); + } + printf("PASS\n"); + _Exit(0); } - time_old = time; + + if (counter == N_CYCLES_AT_DELAY) { + receive_delay += RECEIVE_DELAY_INCREMENT; + send_delay += SEND_DELAY_INCREMENT; + counter = 0; + } + time_old = time; } } @@ -153,6 +269,9 @@ void burn(void) { } int main() { + populate_acceptable_delay_ticks(); + get_acceptable_delay(); + i2s_callback_group_t i_i2s = { .init = (i2s_init_t) i2s_init, .restart_check = (i2s_restart_check_t) i2s_restart_check, diff --git a/test/lib_i2s/test_backpressure.py b/test/lib_i2s/test_backpressure.py index 020da02..d54599f 100644 --- a/test/lib_i2s/test_backpressure.py +++ b/test/lib_i2s/test_backpressure.py @@ -5,7 +5,7 @@ import subprocess from pathlib import Path -sample_rate_args = {"768kbps": 768000, "384kbps": 384000, "192kbps": 192000} +sample_rate_args = {"384kbps": 384000, "192kbps": 192000} num_channels_args = {"1ch": 1, "2ch": 2, "3ch": 3, "4ch": 4} @@ -41,9 +41,6 @@ def test_i2s_backpressure( send_increment, bitdepth, ): - if (num_channels != 4) and not nightly: - pytest.skip("Only run 4 channel tests unless it is a nightly") - id_string = ( f"{bitdepth}_{sample_rate}_{num_channels}_{receive_increment}_{send_increment}" ) From 99c48de214a74e9c98b302f8fd655e060b4deb19 Mon Sep 17 00:00:00 2001 From: Shuchita Khare Date: Wed, 21 Feb 2024 16:32:51 +0000 Subject: [PATCH 2/2] Added bare minimum processing in the i2s_receive() callback and adjusted the acceptable backpressure thresholds accordingly --- test/lib_i2s/backpressure_test/src/main.c | 56 +++++++++++++++-------- test/lib_i2s/test_backpressure.py | 5 ++ 2 files changed, 41 insertions(+), 20 deletions(-) diff --git a/test/lib_i2s/backpressure_test/src/main.c b/test/lib_i2s/backpressure_test/src/main.c index 70e350a..d53e8d9 100644 --- a/test/lib_i2s/backpressure_test/src/main.c +++ b/test/lib_i2s/backpressure_test/src/main.c @@ -68,26 +68,29 @@ static int acceptable_delay_ticks[NUM_SAMPLE_RATES][NUM_I2S_LINES_4+1][NUM_BIT_D static inline void populate_acceptable_delay_ticks() { - // These numbers are logged by running the test and logging the delay at the point at which the - // backpressure test starts failing. + // These numbers are logged by running the test and logging the delay at the last passing iteration + // before the backpressure test starts failing. So, on top of the bare minimum code in the i2s_send() + // and i2s_receive() functions in this file plus their calling overheads, we have acceptable_delay_ticks number + // of cycles per send and receive callback function call to add any extra processing. // 192 KHz - acceptable_delay_ticks[SAMPLE_RATE_192000][NUM_I2S_LINES_1][BITDEPTH_16] = 185; - acceptable_delay_ticks[SAMPLE_RATE_192000][NUM_I2S_LINES_1][BITDEPTH_32] = 200; - acceptable_delay_ticks[SAMPLE_RATE_192000][NUM_I2S_LINES_2][BITDEPTH_16] = 155; - acceptable_delay_ticks[SAMPLE_RATE_192000][NUM_I2S_LINES_2][BITDEPTH_32] = 170; - acceptable_delay_ticks[SAMPLE_RATE_192000][NUM_I2S_LINES_3][BITDEPTH_16] = 130; - acceptable_delay_ticks[SAMPLE_RATE_192000][NUM_I2S_LINES_3][BITDEPTH_32] = 150; - acceptable_delay_ticks[SAMPLE_RATE_192000][NUM_I2S_LINES_4][BITDEPTH_16] = 100; - acceptable_delay_ticks[SAMPLE_RATE_192000][NUM_I2S_LINES_4][BITDEPTH_32] = 125; + acceptable_delay_ticks[SAMPLE_RATE_192000][NUM_I2S_LINES_1][BITDEPTH_16] = 170; + acceptable_delay_ticks[SAMPLE_RATE_192000][NUM_I2S_LINES_1][BITDEPTH_32] = 185; + acceptable_delay_ticks[SAMPLE_RATE_192000][NUM_I2S_LINES_2][BITDEPTH_16] = 140; + acceptable_delay_ticks[SAMPLE_RATE_192000][NUM_I2S_LINES_2][BITDEPTH_32] = 155; + acceptable_delay_ticks[SAMPLE_RATE_192000][NUM_I2S_LINES_3][BITDEPTH_16] = 105; + acceptable_delay_ticks[SAMPLE_RATE_192000][NUM_I2S_LINES_3][BITDEPTH_32] = 125; + acceptable_delay_ticks[SAMPLE_RATE_192000][NUM_I2S_LINES_4][BITDEPTH_16] = 70; + acceptable_delay_ticks[SAMPLE_RATE_192000][NUM_I2S_LINES_4][BITDEPTH_32] = 90; // 384 KHz - acceptable_delay_ticks[SAMPLE_RATE_384000][NUM_I2S_LINES_1][BITDEPTH_16] = 60; - acceptable_delay_ticks[SAMPLE_RATE_384000][NUM_I2S_LINES_1][BITDEPTH_32] = 70; - acceptable_delay_ticks[SAMPLE_RATE_384000][NUM_I2S_LINES_2][BITDEPTH_16] = 35; - acceptable_delay_ticks[SAMPLE_RATE_384000][NUM_I2S_LINES_2][BITDEPTH_32] = 45; - acceptable_delay_ticks[SAMPLE_RATE_384000][NUM_I2S_LINES_3][BITDEPTH_16] = 5; - acceptable_delay_ticks[SAMPLE_RATE_384000][NUM_I2S_LINES_3][BITDEPTH_32] = 20; + acceptable_delay_ticks[SAMPLE_RATE_384000][NUM_I2S_LINES_1][BITDEPTH_16] = 50; + acceptable_delay_ticks[SAMPLE_RATE_384000][NUM_I2S_LINES_1][BITDEPTH_32] = 55; + acceptable_delay_ticks[SAMPLE_RATE_384000][NUM_I2S_LINES_2][BITDEPTH_16] = 15; + acceptable_delay_ticks[SAMPLE_RATE_384000][NUM_I2S_LINES_2][BITDEPTH_32] = 25; + // For 384 KHz, we have non-zero backpressure only up to 2 channels + acceptable_delay_ticks[SAMPLE_RATE_384000][NUM_I2S_LINES_3][BITDEPTH_16] = 0; + acceptable_delay_ticks[SAMPLE_RATE_384000][NUM_I2S_LINES_3][BITDEPTH_32] = 0; acceptable_delay_ticks[SAMPLE_RATE_384000][NUM_I2S_LINES_4][BITDEPTH_16] = 0; acceptable_delay_ticks[SAMPLE_RATE_384000][NUM_I2S_LINES_4][BITDEPTH_32] = 0; } @@ -130,20 +133,29 @@ void get_acceptable_delay() } int delay = acceptable_delay_ticks[sample_rate][NUM_I2S_LINES-1][bit_depth]; + if(delay <= 0) + { + printf("ERROR: Invalid delay %d. Check if testing an unsupported configuration\n", delay); + _Exit(1); + } + // get the send and receive delay based on the if((RECEIVE_DELAY_INCREMENT == 5) && (SEND_DELAY_INCREMENT == 5)) { - acceptable_receive_delay = delay; - acceptable_send_delay = delay; + // Backpressure passes at delay, so add another increment number of ticks to get to the first fail instance + acceptable_receive_delay = delay + 5; + acceptable_send_delay = delay + 5; } else if((RECEIVE_DELAY_INCREMENT == 0) && (SEND_DELAY_INCREMENT == 10)) { + // Backpressure passes at 2*delay, so add another increment number of ticks to get to the first fail instance acceptable_receive_delay = 0; - acceptable_send_delay = 2*delay; + acceptable_send_delay = 2*delay + 10; } else if((RECEIVE_DELAY_INCREMENT == 10) && (SEND_DELAY_INCREMENT == 0)) { - acceptable_receive_delay = 2*delay; + // Backpressure passes at 2*delay, so add another increment number of ticks to get to the first fail instance + acceptable_receive_delay = 2*delay + 10; acceptable_send_delay = 0; } else @@ -165,6 +177,7 @@ xclock_t bclk = XS1_CLKBLK_2; static volatile int receive_delay = 0; static volatile int send_delay = 0; +static volatile int32_t receive_data_store[8]; void i2s_init(void *app_data, i2s_config_t *i2s_config) { @@ -184,6 +197,9 @@ void i2s_send(void *app_data, size_t n, int32_t *send_data) void i2s_receive(void *app_data, size_t n, int32_t *receive_data) { + for (size_t c = 0; c < n; c++) { + receive_data_store[c] = receive_data[c]; + } if (receive_delay) { delay_ticks(receive_delay); } diff --git a/test/lib_i2s/test_backpressure.py b/test/lib_i2s/test_backpressure.py index d54599f..e31ceab 100644 --- a/test/lib_i2s/test_backpressure.py +++ b/test/lib_i2s/test_backpressure.py @@ -17,7 +17,12 @@ bitdepth_args = {"16b": 16, "32b": 32} +# 384000 has a non-zero backpressure only upto 2 channels +def uncollect_if(bitdepth, sample_rate, num_channels, receive_increment, send_increment): + if sample_rate == 384000 and num_channels > 2: + return True +@pytest.mark.uncollect_if(func=uncollect_if) @pytest.mark.parametrize("bitdepth", bitdepth_args.values(), ids=bitdepth_args.keys()) @pytest.mark.parametrize( "sample_rate", sample_rate_args.values(), ids=sample_rate_args.keys()