diff --git a/examples/deps.cmake b/examples/deps.cmake index 1eb6236f..55ebaaa8 100644 --- a/examples/deps.cmake +++ b/examples/deps.cmake @@ -6,7 +6,7 @@ if(NOT EXISTS ${XMOS_SANDBOX_DIR}/fwk_io) FetchContent_Declare( fwk_io GIT_REPOSITORY git@github.com:xmos/fwk_io - GIT_TAG feature/xcommon_cmake + GIT_TAG b88f0d700a8f8eda8e686c4a088ff7d648ef69f6 SOURCE_DIR ${XMOS_SANDBOX_DIR}/fwk_io ) FetchContent_Populate(fwk_io) diff --git a/lib_mic_array/api/mic_array/cpp/PdmRx.hpp b/lib_mic_array/api/mic_array/cpp/PdmRx.hpp index 8c77ab3e..a95ffdce 100644 --- a/lib_mic_array/api/mic_array/cpp/PdmRx.hpp +++ b/lib_mic_array/api/mic_array/cpp/PdmRx.hpp @@ -613,8 +613,10 @@ void mic_array::StandardPdmRxService } // Now that we're sure that PdmRx thread has exited, drain any pending blocks chanend_t c_pdm_blocks_end_b = this->c_pdm_blocks.end_b; - SELECT_RES(CASE_THEN(c_pdm_blocks_end_b, rx_pending_block), - DEFAULT_THEN(empty)) + SELECT_RES( + CASE_THEN(c_pdm_blocks_end_b, rx_pending_block), + DEFAULT_THEN(empty) + ) { rx_pending_block: pdm_samples = GetPdmBlock(); @@ -623,6 +625,7 @@ void mic_array::StandardPdmRxService empty: break; } + (void)pdm_samples; // Avoid unused variable warning. } // Now that shutdown is complete, free the pdmrx channel s_chan_free(this->c_pdm_blocks); diff --git a/lib_mic_array/api/mic_array/etc/fir_1x16_bit.h b/lib_mic_array/api/mic_array/etc/fir_1x16_bit.h index 79f14129..4b2e87cb 100644 --- a/lib_mic_array/api/mic_array/etc/fir_1x16_bit.h +++ b/lib_mic_array/api/mic_array/etc/fir_1x16_bit.h @@ -11,18 +11,16 @@ C_API_START /** Function that computes an FIR over a 1-bit signal with 16-bit coefficients. * The one-bit signal is stored as a sequence of bits, each of them representing - * -1 or +1. The coefficients are notionally a vector of 16-bti values, but with + * -1 or +1. The coefficients are notionally a vector of 16-bit values, but with * a few provisos: * - * * The number of coefficients must be a multiple of 256, and N_256 (the third - * parameter) represents how many multiples there are. N must be at least 1 * * * The coefficients shall be in the range [-32767 .. 32767] * * * Coefficients are stored in slices of bits. A slice of the coefficient vector - * comprises 256 coefficients, so there are N_256 slices. + * comprises 256 coefficients. * Each slice occupies 256 * 16 / 32 = 128 words: 16 bits for each of the 256 - * elements, and there are 23 bits per word. The coefficients are decomposed + * elements, and there are 32 bits per word. The coefficients are decomposed * over the words, and each group of eight words (256 bits) store subsequent * bits of the coefficients values as follows. The bits in * - words 0..7 have magnitude +/-1 @@ -48,4 +46,4 @@ C_API_START MA_C_API int fir_1x16_bit(uint32_t signal[], const uint32_t coeff_1[]); -C_API_END \ No newline at end of file +C_API_END diff --git a/tests/signal/BasicMicArray/src/app.c b/tests/signal/BasicMicArray/src/app.c index 093cc6d4..d55c251c 100644 --- a/tests/signal/BasicMicArray/src/app.c +++ b/tests/signal/BasicMicArray/src/app.c @@ -57,12 +57,14 @@ #define DATA_OUT (1) #endif +#define FIFO_ENTRIES (8) + typedef chanend_t streaming_chanend_t; -DECLARE_JOB(app_output_task, (chanend_t, chanend_t)); -DECLARE_JOB(app_fifo_to_xscope_task, (chanend_t)); DECLARE_JOB(app_mic, (chanend_t, chanend_t)); -DECLARE_JOB(host_words_to_app, (chanend_t, streaming_chanend_t)); +DECLARE_JOB(app_output_task, (chanend_t, chanend_t, chanend_t)); +DECLARE_JOB(app_fifo_to_xscope_task, (chanend_t, chanend_t)); +DECLARE_JOB(host_words_to_app, (chanend_t, streaming_chanend_t, chanend_t, chanend_t)); typedef struct { @@ -203,17 +205,18 @@ void cmd_print_msg(unsigned i){ } static inline -void cmd_perform_action(unsigned cmd){ +unsigned cmd_perform_action(unsigned cmd){ switch(cmd){ case 0: break; - case 1: exit(0); break; + case 1: return 1; case 2: app_print_filters(); break; default: assert(0); break; } + return 0; } static inline -void cmd_loop(chanend_t c_from_host) +void cmd_loop(chanend_t c_from_host, chanend_t c_end_htf, chanend_t c_end_hta) { char cmd_buff[BUFF_SIZE]; int pp; @@ -225,7 +228,12 @@ void cmd_loop(chanend_t c_from_host) assert((pp-1) == 4); uint32_t cmd = ((uint32_t*)(void*) &cmd_buff[0])[0]; cmd_print_msg(cmd); - cmd_perform_action(cmd); + unsigned ret = cmd_perform_action(cmd); + if(ret){ + chanend_out_byte(c_end_htf, 1); // signal host fifo task to end + chanend_out_byte(c_end_hta, 1); // signal host to app task to end + return; + } break; } } @@ -378,12 +386,11 @@ void app_mic( // Sometimes xscope doesn't keep up causing backpressure so add a FIFO to decouple this, at least up to 8 frames. // We can buffer up to 8 chars in a same tile chanend. -const unsigned fifo_entries = 8; typedef int32_t ma_frame_t[APP_MIC_COUNT][MIC_ARRAY_CONFIG_SAMPLES_PER_FRAME]; -ma_frame_t frame_fifo[fifo_entries]; +ma_frame_t frame_fifo[FIFO_ENTRIES]; -void app_output_task(chanend_t c_frames_in, chanend_t c_fifo) +void app_output_task(chanend_t c_frames_in, chanend_t c_fifo, chanend_t c_end_hta) { // Before listening for any frames, use the META_OUT xscope probe to report // our configuration to the host. This will help make sure the right version @@ -405,25 +412,40 @@ void app_output_task(chanend_t c_frames_in, chanend_t c_fifo) // receive the output of the mic array and send it to the host via a fifo to decouple the backpressure from xscope int32_t frame[APP_MIC_COUNT][MIC_ARRAY_CONFIG_SAMPLES_PER_FRAME]; uint8_t fifo_idx = 0; - while(1){ - ma_frame_rx(&frame[0][0], c_frames_in, APP_MIC_COUNT, MIC_ARRAY_CONFIG_SAMPLES_PER_FRAME); - memcpy(frame_fifo[fifo_idx], &frame[0][0], sizeof(ma_frame_t)); - int t0 = get_reference_time(); - chanend_out_byte(c_fifo, fifo_idx++); - int t1 = get_reference_time(); - if(t1 - t0 > 10){ - printstrln("ERROR - Timing fail"); + SELECT_RES( + CASE_THEN(c_end_hta, c_end_hta_handler), + DEFAULT_THEN(default_handler)) + { + default_handler: { + ma_frame_rx(&frame[0][0], c_frames_in, APP_MIC_COUNT, MIC_ARRAY_CONFIG_SAMPLES_PER_FRAME); + memcpy(frame_fifo[fifo_idx], &frame[0][0], sizeof(ma_frame_t)); + int t0 = get_reference_time(); + chanend_out_byte(c_fifo, fifo_idx++); + int t1 = get_reference_time(); + if(t1 - t0 > 10){ + printstrln("ERROR - Timing fail"); + } + if(fifo_idx == FIFO_ENTRIES){ + fifo_idx = 0; + } + continue; } - if(fifo_idx == fifo_entries){ - fifo_idx = 0; + c_end_hta_handler:{ + (void)chanend_in_byte(c_end_hta); + ma_shutdown(c_frames_in); + return; // end signal received from host, end the task } } } -void app_fifo_to_xscope_task(chanend_t c_fifo) +void app_fifo_to_xscope_task(chanend_t c_fifo, chanend_t c_end_htf) { - while(1){ + SELECT_RES( + CASE_THEN(c_fifo, c_fifo_handler), + CASE_THEN(c_end_htf, c_end_htf_handler)) + { + c_fifo_handler:{ uint8_t idx = chanend_in_byte(c_fifo); ma_frame_t *ptr = &frame_fifo[idx]; @@ -433,11 +455,16 @@ void app_fifo_to_xscope_task(chanend_t c_fifo) xscope_int(DATA_OUT, (*ptr)[ch][smp]); } } + continue; + } + c_end_htf_handler:{ + (void)chanend_in_byte(c_end_htf); + return; // end signal received from host, end the task + } } } - -void host_words_to_app(chanend_t c_from_host, streaming_chanend_t c_to_app) +void host_words_to_app(chanend_t c_from_host, streaming_chanend_t c_to_app, chanend_t c_end_htf, chanend_t c_end_hta) { xscope_connect_data_from_host(c_from_host); @@ -453,7 +480,7 @@ void host_words_to_app(chanend_t c_from_host, streaming_chanend_t c_to_app) dd--; buff_lvl += dd; if(dd == 0) { - cmd_loop(c_from_host); + cmd_loop(c_from_host, c_end_htf, c_end_hta); } else { buff_lvl = send_words_to_app(c_to_app, buff, buff_lvl); @@ -474,11 +501,15 @@ int main(){ chanend_t xscope_chan = chanend_alloc(); xscope_mode_lossless(); + // end of program channels + channel_t c_end_hta = chan_alloc(); // host to app (hta) + channel_t c_end_htf = chan_alloc(); // host to fifo (htf) + PAR_JOBS( PJOB(app_mic, (c_to_app.end_a, c_frames.end_a)), - PJOB(app_output_task, (c_frames.end_b, c_fifo.end_a)), - PJOB(app_fifo_to_xscope_task, (c_fifo.end_b)), - PJOB(host_words_to_app, (xscope_chan, c_to_app.end_b)) + PJOB(app_output_task, (c_frames.end_b, c_fifo.end_a, c_end_hta.end_b)), + PJOB(app_fifo_to_xscope_task, (c_fifo.end_b, c_end_htf.end_b)), + PJOB(host_words_to_app, (xscope_chan, c_to_app.end_b, c_end_htf.end_a, c_end_hta.end_a)) ); s_chan_free(c_to_app); chan_free(c_frames); diff --git a/tests/signal/BasicMicArray/test_mic_array.py b/tests/signal/BasicMicArray/test_mic_array.py index bfc1678d..ec5f880c 100644 --- a/tests/signal/BasicMicArray/test_mic_array.py +++ b/tests/signal/BasicMicArray/test_mic_array.py @@ -37,6 +37,8 @@ from pathlib import Path from mic_array_shared import MicArraySharedBase +MAX_DIFF_TH = 12 + with open(Path(__file__).parent / "test_params.json") as f: params = json.load(f) @@ -151,8 +153,13 @@ def test_BasicMicArray(self, request, chans, frame_size, use_isr, one_mic_overri # applied to them prior to being summed. result_diff = np.max(np.abs(expected - device_output)) print(f"result_diff = {result_diff}") - threshold = 12 - assert result_diff <= threshold, f"max diff between python and xcore mic array output ({result_diff}) exceeds threshold ({threshold})" + + exp_size = expected.size + dev_size = device_output.size + print(f"expected size: {exp_size}, device output size: {dev_size}") + + assert result_diff <= MAX_DIFF_TH, f"max diff between python and xcore mic array output ({result_diff}) exceeds MAX_DIFF_TH ({MAX_DIFF_TH})" + assert exp_size == dev_size, f"Expected and device output sizes differ" @pytest.mark.parametrize("chans", [1, 2], ids=["1mic_override", "2mic"]) @@ -227,12 +234,17 @@ def test_BasicMicArrayOneStageFilter(self, request, chans): end = -device_output_delay_samps or None start = device_output_delay_samps + exp_size = expected[:, :end].size + dev_size = device_output[:, start:].size result_diff = np.max(np.abs(expected[:, :end] - device_output[:, start:])) print(f"result_diff = {result_diff}") + print(f"expected size: {exp_size}, device output size: {dev_size}") - threshold = 12 - assert result_diff <= threshold, ( + assert exp_size == dev_size, ( + f"Expected and device output sizes differ" + ) + assert result_diff <= MAX_DIFF_TH, ( f"max diff between python and xcore mic array output ({result_diff}) " - f"exceeds threshold ({threshold})" - ) \ No newline at end of file + f"exceeds MAX_DIFF_TH ({MAX_DIFF_TH})" + ) diff --git a/tests/signal/profile/test_measure_mips.py b/tests/signal/profile/test_measure_mips.py index bedfeffa..cdb5fd07 100644 --- a/tests/signal/profile/test_measure_mips.py +++ b/tests/signal/profile/test_measure_mips.py @@ -9,6 +9,9 @@ cwd = Path(__file__).parent +MIC_LIST = [1, 2] +FS_LIST = [16000, 32000, 48000] + def get_xcc_version() -> str: output = subprocess.check_output(["xcc", "--version"], text=True) for line in output.splitlines(): @@ -102,9 +105,9 @@ def test_measure_mips(pytestconfig): mic_array_mips_table.rst - autogenerated RST table of results """ update = pytestconfig.getoption("--update") - mics = [1, 2] pdmrx = get_isr_list() - fs = [16000, 32000, 48000] + mics = MIC_LIST + fs = FS_LIST results = {} print("\n\n") for chans, pdmrx_type, samp_freq in itertools.product(mics, pdmrx, fs):