diff --git a/.gitignore b/.gitignore index 979a2930d..0cffca237 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,7 @@ build/ .build* *.pyc xscope.xmt + +# Traces +*.gtkw +*.vcd diff --git a/Jenkinsfile b/Jenkinsfile index 047815029..bb6f57210 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -27,15 +27,21 @@ pipeline { xcoreLibraryChecks("${REPO}") } } - stage('XS2 Tests') { + stage('Testing') { failFast true parallel { - stage('Legacy tests') { + stage('Tests') { steps { - runXmostest("${REPO}", 'legacy_tests') + dir("${REPO}/tests"){ + viewEnv(){ + withVenv{ + runPytest('--numprocesses=4') + } + } + } } } - stage('Unit tests') { + stage('Unity tests') { steps { dir("${REPO}") { dir('tests') { diff --git a/legacy_tests/runtests.py b/legacy_tests/runtests.py deleted file mode 100755 index 0fbc7f5d7..000000000 --- a/legacy_tests/runtests.py +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env python2.7 -# Copyright 2018-2021 XMOS LIMITED. -# This Software is subject to the terms of the XMOS Public Licence: Version 1. -import xmostest -import os.path - -if __name__ == "__main__": - - - xmostest.init() - - xmostest.register_group("lib_xua", - "i2s_loopback_sim_tests", - "I2S loopback simulator tests", - - """ -Tests are performed by running the audiohub code connected to a -loopback plugin -""") - - xmostest.runtests() - - xmostest.finish() diff --git a/legacy_tests/test_i2s_loopback.py b/legacy_tests/test_i2s_loopback.py deleted file mode 100644 index 3e65e2f60..000000000 --- a/legacy_tests/test_i2s_loopback.py +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/env python -# Copyright 2018-2021 XMOS LIMITED. -# This Software is subject to the terms of the XMOS Public Licence: Version 1. -import xmostest - -def runtest_one_config(env, format, i2s_role, num_chans_in, num_chans_out, sample_rate): - testlevel = 'smoke' - resources = xmostest.request_resource('xsim') - - binary = 'app_test_i2s_loopback/bin/{env}_{format}_{i2s_role}_{num_chans_in}in_{num_chans_out}out_{sample_rate}/app_test_i2s_loopback_{env}_{format}_{i2s_role}_{num_chans_in}in_{num_chans_out}out_{sample_rate}.xe'.format(env=env, format=format, i2s_role=i2s_role, num_chans_in=num_chans_in, num_chans_out=num_chans_out, sample_rate=sample_rate) - tester = xmostest.ComparisonTester(open('pass.expect'), - 'lib_xua', - 'i2s_loopback_sim_tests', - 'i2s_loopback', - {'env':env, - 'format':format, - 'i2s_role':i2s_role, - 'num_chans_in':num_chans_in, - 'num_chans_out':num_chans_out, - 'sample_rate':sample_rate}) - tester.set_min_testlevel(testlevel) - loopback_args= '-port tile[0] XS1_PORT_1M 1 0 -port tile[0] XS1_PORT_1I 1 0 ' + \ - '-port tile[0] XS1_PORT_1N 1 0 -port tile[0] XS1_PORT_1J 1 0 ' + \ - '-port tile[0] XS1_PORT_1O 1 0 -port tile[0] XS1_PORT_1K 1 0 ' + \ - '-port tile[0] XS1_PORT_1P 1 0 -port tile[0] XS1_PORT_1L 1 0 ' + \ - '-port tile[0] XS1_PORT_1A 1 0 -port tile[0] XS1_PORT_1F 1 0 ' - if i2s_role == 'slave': - loopback_args += '-port tile[0] XS1_PORT_1B 1 0 -port tile[0] XS1_PORT_1H 1 0 ' #bclk - loopback_args += '-port tile[0] XS1_PORT_1C 1 0 -port tile[0] XS1_PORT_1G 1 0 ' #lrclk - - max_cycles = 1500000 #enough to reach the 10 skip + 100 test in sim at 48kHz - xmostest.run_on_simulator(resources['xsim'], binary, tester=tester, simargs=['--max-cycles', str(max_cycles), '--plugin', 'LoopbackPort.dll', loopback_args]) - -def runtest(): - runtest_one_config('simulation', 'i2s', 'master', 2, 2, '48khz') - runtest_one_config('simulation', 'i2s', 'slave', 2, 2, '48khz') - - runtest_one_config('simulation', 'i2s', 'master', 2, 2, '192khz') - runtest_one_config('simulation', 'i2s', 'slave', 2, 2, '192khz') - - runtest_one_config('simulation', 'i2s', 'master', 8, 8, '48khz') - runtest_one_config('simulation', 'i2s', 'slave', 8, 8, '48khz') - - runtest_one_config('simulation', 'i2s', 'master', 8, 8, '192khz') - runtest_one_config('simulation', 'i2s', 'slave', 8, 8, '192khz') - - runtest_one_config('simulation', 'tdm', 'master', 8, 8, '48khz') - runtest_one_config('simulation', 'tdm', 'slave', 8, 8, '48khz') - - runtest_one_config('simulation', 'tdm', 'master', 16, 16, '48khz') - runtest_one_config('simulation', 'tdm', 'slave', 16, 16, '48khz') diff --git a/lib_xua/src/core/audiohub/xua_audiohub.xc b/lib_xua/src/core/audiohub/xua_audiohub.xc index 5c9ce4e5a..7cec6750b 100755 --- a/lib_xua/src/core/audiohub/xua_audiohub.xc +++ b/lib_xua/src/core/audiohub/xua_audiohub.xc @@ -789,12 +789,11 @@ void XUA_AudioHub(chanend ?c_aud, clock ?clk_audio_mclk, clock ?clk_audio_bclk, null, p_dsd_clk, #endif - divide, curSamFreq, dsdMode); + p_mclk_in, clk_audio_bclk, divide, curSamFreq, dsdMode); } else #endif { - ConfigAudioPortsWrapper( #if (I2S_CHANS_DAC != 0) p_i2s_dac, @@ -813,7 +812,7 @@ void XUA_AudioHub(chanend ?c_aud, clock ?clk_audio_mclk, clock ?clk_audio_bclk, p_bclk, #endif #endif - divide, curSamFreq, dsdMode); + p_mclk_in, clk_audio_bclk, divide, curSamFreq, dsdMode); } diff --git a/lib_xua/src/core/buffer/ep/ep_buffer.xc b/lib_xua/src/core/buffer/ep/ep_buffer.xc index d5d4db320..73ee2768b 100644 --- a/lib_xua/src/core/buffer/ep/ep_buffer.xc +++ b/lib_xua/src/core/buffer/ep/ep_buffer.xc @@ -3,8 +3,7 @@ #include "xua.h" #if XUA_USB_EN #include -#include - +#include #ifdef MIDI #include "usb_midi.h" @@ -357,7 +356,21 @@ void XUA_Buffer_Ep(register chanend c_aud_out, #endif #endif - timer tmr; +#if (XUA_SYNCMODE == XUA_SYNCMODE_SYNC) +#ifndef LOCAL_CLOCK_INCREMENT +#define LOCAL_CLOCK_INCREMENT (100000) /* 500Hz */ +#endif +#ifndef LOCAL_CLOCK_MARGIN +#define LOCAL_CLOCK_MARGIN (1000) +#endif + int sofClockValid = 0; + timer t_sofCheck; + unsigned timeLastEdge; + unsigned timeNextEdge; + t_sofCheck :> timeLastEdge; + timeNextEdge + LOCAL_CLOCK_INCREMENT; + i_pll_ref.toggle(); +#endif while(1) { @@ -502,6 +515,13 @@ void XUA_Buffer_Ep(register chanend c_aud_out, } break; } +#if (XUA_SYNCMODE == XUA_SYNCMODE_SYNC) + case t_sofCheck when timerafter(timeNextEdge) :> void: + i_pll_ref.toggle(); + timeLastEdge = timeNextEdge; + timeNextEdge += LOCAL_CLOCK_INCREMENT; + break; +#endif #define MASK_16_13 (7) /* Bits that should not be transmitted as part of feedback */ #define MASK_16_10 (127) /* For Audio 1.0 we use a mask 1 bit longer than expected to avoid Windows LSB issues */ @@ -517,12 +537,11 @@ void XUA_Buffer_Ep(register chanend c_aud_out, int framesPerSec; GET_SHARED_GLOBAL(usbSpeed, g_curUsbSpeed); static int sofCount = 0; - static unsigned syncPinVal = 0; framesPerSec = (usbSpeed == XUD_SPEED_HS) ? 8000 : 1000; - float float_clocks = (float) sampleFreq/framesPerSec ; - clocks = (unsigned) (float_clocks * (1 << 16)); + clocks = ((int64_t) sampleFreq << 16) / framesPerSec; + asm volatile("stw %0, dp[g_speed]"::"r"(clocks)); sofCount += 1000; @@ -530,7 +549,9 @@ void XUA_Buffer_Ep(register chanend c_aud_out, { /* Port is accessed via interface to allow flexibilty with location */ i_pll_ref.toggle(); + t_sofCheck :> timeLastEdge; sofCount = 0; + timeNextEdge = timeLastEdge + LOCAL_CLOCK_INCREMENT + LOCAL_CLOCK_MARGIN; } #else @@ -889,6 +910,7 @@ void XUA_Buffer_Ep(register chanend c_aud_out, case XUD_SetData_Select(c_hid, ep_hid, result): hid_ready_flag = 0U; unsigned reportTime; + timer tmr; tmr :> reportTime; hidCaptureReportTime(hid_ready_id, reportTime); hidCalcNextReportTime(hid_ready_id); diff --git a/lib_xua/src/core/clocking/clockgen.xc b/lib_xua/src/core/clocking/clockgen.xc index cf3137c78..855ad2301 100644 --- a/lib_xua/src/core/clocking/clockgen.xc +++ b/lib_xua/src/core/clocking/clockgen.xc @@ -490,20 +490,14 @@ void clockGen (streaming chanend ?c_spdif_rx, chanend ?c_adat_rx, client interfa timeNextClockDetection = timeNextEdge + (LOCAL_CLOCK_INCREMENT/2); timeNextEdge += LOCAL_CLOCK_INCREMENT; - /* If we are in an external clock mode and this fire, then clock invalid */ - + /* If we are in an external clock mode and this fire, then clock invalid + * reset counters in case we are moved to digital clock - we want a well timed + * first edge */ #if (XUA_SPDIF_RX_EN) - // if(clkMode == CLOCK_SPDIF) - { - /* We must have lost valid S/PDIF stream, reset counters, so we dont produce a double edge */ - spdifCounters.receivedSamples = 0; - } + spdifCounters.receivedSamples = 0; #endif #if ADAT_RX - //if(clkMode == CLOCK_ADAT) - { - adatCounters.receivedSamples = 0; - } + adatCounters.receivedSamples = 0; #endif #ifdef CLOCK_VALIDITY_CALL diff --git a/lib_xua/src/core/ports/audioports.c b/lib_xua/src/core/ports/audioports.c index 64795ba0b..6c86344bb 100644 --- a/lib_xua/src/core/ports/audioports.c +++ b/lib_xua/src/core/ports/audioports.c @@ -1,4 +1,4 @@ -// Copyright 2013-2021 XMOS LIMITED. +// Copyright 2013-2022 XMOS LIMITED. // This Software is subject to the terms of the XMOS Public Licence: Version 1. #include @@ -6,7 +6,6 @@ #include #undef __ASSEMBLER__ #include "audioports.h" -#include #include "xua.h" /* Note since DSD ports could be reused for I2S ports we do all the setup manually in C */ @@ -46,7 +45,7 @@ void ConfigAudioPortsWrapper( port p_lrclk, port p_bclk, #endif -unsigned int divide, unsigned curSamFreq, unsigned int dsdMode) + port p_mclk_in, clock clk_audio_bclk, unsigned int divide, unsigned curSamFreq, unsigned int dsdMode) { ConfigAudioPorts( #if (I2S_CHANS_DAC != 0) || (DSD_CHANS_DAC != 0) @@ -61,6 +60,6 @@ unsigned int divide, unsigned curSamFreq, unsigned int dsdMode) p_lrclk, p_bclk, #endif - divide, curSamFreq); + p_mclk_in, clk_audio_bclk, divide, curSamFreq); } diff --git a/lib_xua/src/core/ports/audioports.h b/lib_xua/src/core/ports/audioports.h index 5f01fd9c7..d0db02125 100644 --- a/lib_xua/src/core/ports/audioports.h +++ b/lib_xua/src/core/ports/audioports.h @@ -1,9 +1,12 @@ -// Copyright 2011-2021 XMOS LIMITED. +// Copyright 2011-2022 XMOS LIMITED. // This Software is subject to the terms of the XMOS Public Licence: Version 1. #ifndef _AUDIOPORTS_H_ #define _AUDIOPORTS_H_ #include +#ifdef __STDC__ +typedef unsigned clock; +#endif #include "xua.h" #ifdef __XC__ @@ -28,7 +31,7 @@ void ConfigAudioPorts( in port p_bclk, #endif #endif - unsigned int divide, unsigned int curSamFreq); + in port p_mclk_in, clock clk_audio_bclk, unsigned int divide, unsigned int curSamFreq); #else void ConfigAudioPorts( @@ -51,7 +54,7 @@ void ConfigAudioPorts( port p_bclk, #endif #endif - unsigned int divide, unsigned int curSamFreq); + port p_mclk_in, clock clk_audio_bclk, unsigned int divide, unsigned int curSamFreq); #endif /* __XC__*/ @@ -76,7 +79,7 @@ void ConfigAudioPortsWrapper( buffered in port:32 p_bclk, #endif #endif - unsigned int divide, unsigned curSamFreq, unsigned int dsdMode); + in port p_mclk_in, clock clk_audio_bclk, unsigned int divide, unsigned curSamFreq, unsigned int dsdMode); #else void ConfigAudioPortsWrapper( @@ -92,7 +95,7 @@ void ConfigAudioPortsWrapper( port p_lrclk, port p_bclk, #endif - unsigned int divide, unsigned curSamFreq, unsigned int dsdMode); + port p_mclk_in, clock clk_audio_bclk, unsigned int divide, unsigned curSamFreq, unsigned int dsdMode); #endif /* __XC__*/ diff --git a/lib_xua/src/core/ports/audioports.xc b/lib_xua/src/core/ports/audioports.xc index 1f40b89e8..cf282747c 100644 --- a/lib_xua/src/core/ports/audioports.xc +++ b/lib_xua/src/core/ports/audioports.xc @@ -1,4 +1,4 @@ -// Copyright 2011-2021 XMOS LIMITED. +// Copyright 2011-2022 XMOS LIMITED. // This Software is subject to the terms of the XMOS Public Licence: Version 1. #include #include @@ -6,11 +6,9 @@ #include "xua.h" #include "audioports.h" - - -extern in port p_mclk_in; +//extern in port p_mclk_in; extern clock clk_audio_mclk; -extern clock clk_audio_bclk; +//extern clock clk_audio_bclk; void ConfigAudioPorts( #if (I2S_CHANS_DAC != 0) || (DSD_CHANS_DAC != 0) @@ -32,7 +30,7 @@ void ConfigAudioPorts( in port p_bclk, #endif #endif -unsigned int divide, unsigned curSamFreq) + in port p_mclk_in, clock clk_audio_bclk, unsigned int divide, unsigned curSamFreq) { #if (I2S_CHANS_DAC != 0) || (I2S_CHANS_ADC != 0) diff --git a/requirements.txt b/requirements.txt index a9ebc4e93..b7e17c799 100644 --- a/requirements.txt +++ b/requirements.txt @@ -34,3 +34,4 @@ pytest-xdist==1.34.0 # of its own setup.py file, then this list must include an entry for that # setup.py file, e.g., '-e .' or '-e ./python' (without the quotes). -e ./python +-e ./../test_support diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 000000000..f5cca7f75 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,24 @@ +# Copyright 2022 XMOS LIMITED. +# This Software is subject to the terms of the XMOS Public Licence: Version 1. +import pytest + + +def pytest_addoption(parser): + parser.addoption( + "--enabletracing", + action="store_true", + default=False, + help="Run tests with instruction tracing", + ) + + parser.addoption( + "--enablevcdtracing", + action="store_true", + default=False, + help="Run tests with vcd tracing", + ) + + +@pytest.fixture +def options(request): + yield request.config.option diff --git a/legacy_tests/pass.expect b/tests/pass.expect similarity index 100% rename from legacy_tests/pass.expect rename to tests/pass.expect diff --git a/tests/test_i2s_loopback.py b/tests/test_i2s_loopback.py new file mode 100644 index 000000000..48693d610 --- /dev/null +++ b/tests/test_i2s_loopback.py @@ -0,0 +1,81 @@ +# Copyright 2018-2022 XMOS LIMITED. +# This Software is subject to the terms of the XMOS Public Licence: Version 1. +import pytest +import Pyxsim +from Pyxsim import testers +import os +import sys + + +@pytest.fixture() +def test_file(request): + return str(request.node.fspath) + + +def do_test( + pcm_format, i2s_role, channel_count, sample_rate, test_file, options, capfd +): + + build_options = [] + output = [] + testname, _ = os.path.splitext(os.path.basename(test_file)) + + desc = f"simulation_{pcm_format}_{i2s_role}_{channel_count}in_{channel_count}out_{sample_rate}" + binary = f"{testname}/bin/{desc}/{testname}_{desc}.xe" + + tester = testers.ComparisonTester(open("pass.expect")) + + loopback_args = ( + "-port tile[0] XS1_PORT_1M 1 0 -port tile[0] XS1_PORT_1I 1 0 " + + "-port tile[0] XS1_PORT_1N 1 0 -port tile[0] XS1_PORT_1J 1 0 " + + "-port tile[0] XS1_PORT_1O 1 0 -port tile[0] XS1_PORT_1K 1 0 " + + "-port tile[0] XS1_PORT_1P 1 0 -port tile[0] XS1_PORT_1L 1 0 " + + "-port tile[0] XS1_PORT_1A 1 0 -port tile[0] XS1_PORT_1F 1 0 " + ) + if i2s_role == "slave": + loopback_args += ( + "-port tile[0] XS1_PORT_1B 1 0 -port tile[0] XS1_PORT_1H 1 0 " # bclk + ) + loopback_args += ( + "-port tile[0] XS1_PORT_1C 1 0 -port tile[0] XS1_PORT_1G 1 0 " # lrclk + ) + + max_cycles = 1500000 # enough to reach the 10 skip + 100 test in sim at 48kHz + + simargs = [ + "--max-cycles", + str(max_cycles), + "--plugin", + "LoopbackPort.dll", + loopback_args, + ] + + result = Pyxsim.run_on_simulator( + binary, simthreads=[], tester=tester, simargs=simargs, capfd=capfd + ) + + return result + + +@pytest.mark.parametrize("i2s_role", ["master", "slave"]) +@pytest.mark.parametrize("pcm_format", ["i2s", "tdm"]) +@pytest.mark.parametrize("channel_count", [2, 8, 16]) +@pytest.mark.parametrize("sample_rate", ["48khz", "192khz"]) +def test_i2s_loopback( + i2s_role, pcm_format, channel_count, sample_rate, test_file, options, capfd +): + + if pcm_format == "i2s" and channel_count == 16: + pytest.skip("Invalid parameter combination") + + if pcm_format == "tdm" and channel_count == 2: + pytest.skip("Invalid parameter combination") + + if pcm_format == "tdm" and sample_rate == "192khz": + pytest.skip("Invalid parameter combination") + + result = do_test( + pcm_format, i2s_role, channel_count, sample_rate, test_file, options, capfd + ) + + assert result diff --git a/legacy_tests/app_test_i2s_loopback/Makefile b/tests/test_i2s_loopback/Makefile similarity index 100% rename from legacy_tests/app_test_i2s_loopback/Makefile rename to tests/test_i2s_loopback/Makefile diff --git a/legacy_tests/app_test_i2s_loopback/debug_conf.h b/tests/test_i2s_loopback/debug_conf.h similarity index 86% rename from legacy_tests/app_test_i2s_loopback/debug_conf.h rename to tests/test_i2s_loopback/debug_conf.h index aadb00147..11cedc164 100644 --- a/legacy_tests/app_test_i2s_loopback/debug_conf.h +++ b/tests/test_i2s_loopback/debug_conf.h @@ -1,4 +1,4 @@ -// Copyright 2016-2021 XMOS LIMITED. +// Copyright 2016-2022 XMOS LIMITED. // This Software is subject to the terms of the XMOS Public Licence: Version 1. #ifndef __debug_conf_h__ #define __debug_conf_h__ diff --git a/legacy_tests/app_test_i2s_loopback/hid_report_descriptor.h b/tests/test_i2s_loopback/hid_report_descriptor.h similarity index 100% rename from legacy_tests/app_test_i2s_loopback/hid_report_descriptor.h rename to tests/test_i2s_loopback/hid_report_descriptor.h diff --git a/legacy_tests/app_test_i2s_loopback/main.xc b/tests/test_i2s_loopback/main.xc similarity index 100% rename from legacy_tests/app_test_i2s_loopback/main.xc rename to tests/test_i2s_loopback/main.xc diff --git a/legacy_tests/app_test_i2s_loopback/simulation.xc b/tests/test_i2s_loopback/simulation.xc similarity index 100% rename from legacy_tests/app_test_i2s_loopback/simulation.xc rename to tests/test_i2s_loopback/simulation.xc diff --git a/legacy_tests/app_test_i2s_loopback/usb_device.h b/tests/test_i2s_loopback/usb_device.h similarity index 95% rename from legacy_tests/app_test_i2s_loopback/usb_device.h rename to tests/test_i2s_loopback/usb_device.h index 1f5aaa895..9d21df47f 100644 --- a/legacy_tests/app_test_i2s_loopback/usb_device.h +++ b/tests/test_i2s_loopback/usb_device.h @@ -1,4 +1,4 @@ -// Copyright 2016-2021 XMOS LIMITED. +// Copyright 2016-2022 XMOS LIMITED. // This Software is subject to the terms of the XMOS Public Licence: Version 1. #ifndef __usb_device_h__ #define __usb_device_h__ diff --git a/legacy_tests/app_test_i2s_loopback/usb_device.xc b/tests/test_i2s_loopback/usb_device.xc similarity index 96% rename from legacy_tests/app_test_i2s_loopback/usb_device.xc rename to tests/test_i2s_loopback/usb_device.xc index 7a2057350..4f755d1cd 100644 --- a/legacy_tests/app_test_i2s_loopback/usb_device.xc +++ b/tests/test_i2s_loopback/usb_device.xc @@ -1,4 +1,4 @@ -// Copyright 2018-2021 XMOS LIMITED. +// Copyright 2018-2022 XMOS LIMITED. // This Software is subject to the terms of the XMOS Public Licence: Version 1. #if 0 #include diff --git a/legacy_tests/app_test_i2s_loopback/xk_216_mc/audiohw.xc b/tests/test_i2s_loopback/xk_216_mc/audiohw.xc similarity index 100% rename from legacy_tests/app_test_i2s_loopback/xk_216_mc/audiohw.xc rename to tests/test_i2s_loopback/xk_216_mc/audiohw.xc diff --git a/legacy_tests/app_test_i2s_loopback/xk_216_mc/cs2100.h b/tests/test_i2s_loopback/xk_216_mc/cs2100.h similarity index 93% rename from legacy_tests/app_test_i2s_loopback/xk_216_mc/cs2100.h rename to tests/test_i2s_loopback/xk_216_mc/cs2100.h index bc5a0cdda..9e2938a78 100644 --- a/legacy_tests/app_test_i2s_loopback/xk_216_mc/cs2100.h +++ b/tests/test_i2s_loopback/xk_216_mc/cs2100.h @@ -1,4 +1,4 @@ -// Copyright 2018-2021 XMOS LIMITED. +// Copyright 2018-2022 XMOS LIMITED. // This Software is subject to the terms of the XMOS Public Licence: Version 1. #define CS2100_I2C_DEVICE_ADDR (0x9c>>1) diff --git a/legacy_tests/app_test_i2s_loopback/xk_216_mc/cs4384.h b/tests/test_i2s_loopback/xk_216_mc/cs4384.h similarity index 96% rename from legacy_tests/app_test_i2s_loopback/xk_216_mc/cs4384.h rename to tests/test_i2s_loopback/xk_216_mc/cs4384.h index 6de83e811..34ccbc6c9 100644 --- a/legacy_tests/app_test_i2s_loopback/xk_216_mc/cs4384.h +++ b/tests/test_i2s_loopback/xk_216_mc/cs4384.h @@ -1,4 +1,4 @@ -// Copyright 2017-2021 XMOS LIMITED. +// Copyright 2017-2022 XMOS LIMITED. // This Software is subject to the terms of the XMOS Public Licence: Version 1. #ifndef CS4384_H_ #define CS4384_H_ diff --git a/legacy_tests/app_test_i2s_loopback/xk_216_mc/cs5368.h b/tests/test_i2s_loopback/xk_216_mc/cs5368.h similarity index 93% rename from legacy_tests/app_test_i2s_loopback/xk_216_mc/cs5368.h rename to tests/test_i2s_loopback/xk_216_mc/cs5368.h index d2de278da..ce7ed892e 100644 --- a/legacy_tests/app_test_i2s_loopback/xk_216_mc/cs5368.h +++ b/tests/test_i2s_loopback/xk_216_mc/cs5368.h @@ -1,4 +1,4 @@ -// Copyright 2017-2021 XMOS LIMITED. +// Copyright 2017-2022 XMOS LIMITED. // This Software is subject to the terms of the XMOS Public Licence: Version 1. #ifndef _CS5368_H_ #define _CS5368_H_ diff --git a/legacy_tests/app_test_i2s_loopback/xk_216_mc/gpio_access.c b/tests/test_i2s_loopback/xk_216_mc/gpio_access.c similarity index 96% rename from legacy_tests/app_test_i2s_loopback/xk_216_mc/gpio_access.c rename to tests/test_i2s_loopback/xk_216_mc/gpio_access.c index 6d302c550..64f31c44a 100644 --- a/legacy_tests/app_test_i2s_loopback/xk_216_mc/gpio_access.c +++ b/tests/test_i2s_loopback/xk_216_mc/gpio_access.c @@ -1,4 +1,4 @@ -// Copyright 2016-2021 XMOS LIMITED. +// Copyright 2016-2022 XMOS LIMITED. // This Software is subject to the terms of the XMOS Public Licence: Version 1. #ifdef HARDWARE #include diff --git a/legacy_tests/app_test_i2s_loopback/xk_216_mc/gpio_access.h b/tests/test_i2s_loopback/xk_216_mc/gpio_access.h similarity index 98% rename from legacy_tests/app_test_i2s_loopback/xk_216_mc/gpio_access.h rename to tests/test_i2s_loopback/xk_216_mc/gpio_access.h index 93f66fee9..3856619bd 100644 --- a/legacy_tests/app_test_i2s_loopback/xk_216_mc/gpio_access.h +++ b/tests/test_i2s_loopback/xk_216_mc/gpio_access.h @@ -1,4 +1,4 @@ -// Copyright 2016-2021 XMOS LIMITED. +// Copyright 2016-2022 XMOS LIMITED. // This Software is subject to the terms of the XMOS Public Licence: Version 1. #ifndef __gpio_access_h__ #define __gpio_access_h__ diff --git a/legacy_tests/app_test_i2s_loopback/xk_216_mc/xk-audio-216-mc.xn b/tests/test_i2s_loopback/xk_216_mc/xk-audio-216-mc.xn similarity index 100% rename from legacy_tests/app_test_i2s_loopback/xk_216_mc/xk-audio-216-mc.xn rename to tests/test_i2s_loopback/xk_216_mc/xk-audio-216-mc.xn diff --git a/legacy_tests/app_test_i2s_loopback/xua_conf.h b/tests/test_i2s_loopback/xua_conf.h similarity index 77% rename from legacy_tests/app_test_i2s_loopback/xua_conf.h rename to tests/test_i2s_loopback/xua_conf.h index a1120f497..dc381a653 100644 --- a/legacy_tests/app_test_i2s_loopback/xua_conf.h +++ b/tests/test_i2s_loopback/xua_conf.h @@ -1,17 +1,24 @@ -// Copyright 2016-2021 XMOS LIMITED. +// Copyright 2016-2022 XMOS LIMITED. // This Software is subject to the terms of the XMOS Public Licence: Version 1. -#ifndef __custom_defines_h__ -#define __custom_defines_h__ +#ifndef _XUA_CONF_H_ +#define _XUA_CONF_H_ #define EXCLUDE_USB_AUDIO_MAIN #define XUA_NUM_PDM_MICS 0 #define XUD_TILE 1 #define AUDIO_IO_TILE 0 #define MIXER 0 + +#ifndef MCLK_441 #define MCLK_441 (512 * 44100) +#endif + +#ifndef MCLK_48 #define MCLK_48 (512 * 48000) -#define MIN_FREQ 44100 -#define MAX_FREQ 192000 +#endif + +#define MIN_FREQ (44100) +#define MAX_FREQ (192000) #define SPDIF_TX_INDEX 0 #define VENDOR_STR "XMOS" #define VENDOR_ID 0x20B1 @@ -26,4 +33,4 @@ #define MIC_DUAL_ENABLED 1 //Use single thread, dual PDM mic #define XUA_MIC_FRAME_SIZE 240 -#endif // __custom_defines_h__ +#endif diff --git a/tests/test_sync_clk_basic.py b/tests/test_sync_clk_basic.py new file mode 100644 index 000000000..cd2c99c44 --- /dev/null +++ b/tests/test_sync_clk_basic.py @@ -0,0 +1,58 @@ +# Copyright 2022 XMOS LIMITED. +# This Software is subject to the terms of the XMOS Public Licence: Version 1. +import pytest +import Pyxsim +from Pyxsim import testers +import os +import sys + + +@pytest.fixture() +def test_file(request): + return str(request.node.fspath) + + +def do_test(bus_speed, test_file, options, capfd): + + testname, _ = os.path.splitext(os.path.basename(test_file)) + + binary = f"{testname}/bin/{bus_speed}/{testname}_{bus_speed}.xe" + + tester = testers.ComparisonTester(open("pass.expect")) + + loopback_args = ( + "-port tile[0] XS1_PORT_1M 1 0 -port tile[0] XS1_PORT_1I 1 0 " + + "-port tile[0] XS1_PORT_1N 1 0 -port tile[0] XS1_PORT_1J 1 0 " + + "-port tile[0] XS1_PORT_1O 1 0 -port tile[0] XS1_PORT_1K 1 0 " + + "-port tile[0] XS1_PORT_1P 1 0 -port tile[0] XS1_PORT_1L 1 0 " + + "-port tile[0] XS1_PORT_1A 1 0 -port tile[0] XS1_PORT_1B 1 0 " + ) + + max_cycles = 15000000 # enough to reach the 10 skip + 100 test in sim at 48kHz + + simargs = [ + "--max-cycles", + str(max_cycles), + "--plugin", + "LoopbackPort.dll", + loopback_args, + ] + + result = Pyxsim.run_on_simulator( + binary, + tester=tester, + simargs=simargs, + capfd=capfd, + instTracing=options.enabletracing, + vcdTracing=options.enablevcdtracing, + ) + + return result + + +@pytest.mark.parametrize("bus_speed", ["FS", "HS"]) +def test_sync_clk_basic(bus_speed, test_file, options, capfd): + + result = do_test(bus_speed, test_file, options, capfd) + + assert result diff --git a/tests/test_sync_clk_basic/Makefile b/tests/test_sync_clk_basic/Makefile new file mode 100644 index 000000000..513f26140 --- /dev/null +++ b/tests/test_sync_clk_basic/Makefile @@ -0,0 +1,17 @@ + +TEST_FLAGS ?= + +XCC_FLAGS_HS = -O3 -g -DXUD_CORE_CLOCK=600 -save-temps -DUSB_TILE=tile[0] -DLOCAL_CLOCK_INCREMENT=10000 -DLOCAL_CLOCK_MARGIN=100 \ + -DBUS_SPEED=2 \ + $(TEST_FLAGS) + +XCC_FLAGS_FS = -O3 -g -DXUD_CORE_CLOCK=600 -save-temps -DUSB_TILE=tile[0] -DLOCAL_CLOCK_INCREMENT=10000 -DLOCAL_CLOCK_MARGIN=100 \ + -DBUS_SPEED=1 \ + $(TEST_FLAGS) + +TARGET = test_xs3_600.xn + +USED_MODULES = lib_xua + +XMOS_MAKE_PATH ?= ../.. +-include $(XMOS_MAKE_PATH)/xcommon/module_xcommon/build/Makefile.common diff --git a/tests/test_sync_clk_basic/src/main.xc b/tests/test_sync_clk_basic/src/main.xc new file mode 100644 index 000000000..6a7531e82 --- /dev/null +++ b/tests/test_sync_clk_basic/src/main.xc @@ -0,0 +1,196 @@ +// Copyright 2022 XMOS LIMITED. +// This Software is subject to the terms of the XMOS Public Licence: Version 1. + +/* Simple test to ensure reference clock to CS2100 device continues when SOF clock not available + * Note, this test uses "nice" numbers (i.e. MISSIG_SOFS %8 == 0) and therefore doesn't check + * for a graceful change over from internal to SOF clock + */ + +#include "platform.h" +#include "xua.h" +#include "print.h" +#include "xud.h" + +#define EP_COUNT_IN (3) +#define EP_COUNT_OUT (3) + +out port p_pll_ref = XS1_PORT_1A; +in port p_off_mclk = XS1_PORT_1M; +in port p_pll_loop = XS1_PORT_1B; /* Note, this is externally looped back using the loopback plugin */ + +/* Purely for debug/viewing on VCD */ +out port p_test0 = XS1_PORT_1C; +out port p_test1 = XS1_PORT_1D; + +#ifndef BUS_SPEED +#error BUS_SPEED should be defined +#endif + +/* To speed this test up we divide all delays by 10. This is also the case for the delays in the clock generation code */ +#if(BUS_SPEED == 2) // XUD_SPEED_HS + #define SOF_PERIOD_TICKS (12500/10) + #define SOF_DIVIDE (1) +#else + #define SOF_PERIOD_TICKS ((12500*8)/10) + #define SOF_DIVIDE (8) +#endif + +#ifndef MISSING_SOF_PERIOD +/* By default skip a whole number of SOF periods (easy case) + * Note, app_test_sync_plugin/Makefiles sets this to something more nasty */ +#define MISSING_SOF_PERIOD (8 * SOF_PERIOD_TICKS) +#endif + +void exit(int); + +void delay(unsigned d) +{ + timer t; + unsigned time; + t :> time; + t when timerafter(time + d) :> int x; +} + +/* From lib_xud */ +void SetupEndpoints(chanend c_ep_out[], int noEpOut, chanend c_ep_in[], int noEpIn, XUD_EpType epTypeTableOut[], XUD_EpType epTypeTableIn[]); + +void AudioHwInit() +{ + return; +} + +void AudioHwConfig(unsigned samFreq, unsigned mClk, unsigned dsdMode, unsigned sampRes_DAC, unsigned sampRes_ADC) +{ + return; +} + +void driveSofs(chanend c_sof, int count) +{ + static int frame = 0; + + /* For HS frame should only increment every 8 SOFs, but this is a "dont care" */ + for(int i = 0; i < count; i++) + { + outuint(c_sof, frame++); + delay(SOF_PERIOD_TICKS); + } +} + +void fake_xud(chanend c_out[], chanend c_in[], chanend c_sof) +{ + timer t; + unsigned time; + + + /* Makes traces a bit nicer to look at */ + t :> time; + t when timerafter(SOF_PERIOD_TICKS * 2) :> int x; + + p_test0 <: 1; + + /* Endpoint type tables */ + XUD_EpType epTypeTableOut[EP_COUNT_OUT] = {XUD_EPTYPE_CTL, XUD_EPTYPE_ISO, XUD_EPTYPE_DIS}; + XUD_EpType epTypeTableIn[EP_COUNT_IN] = {XUD_EPTYPE_CTL, XUD_EPTYPE_ISO, XUD_EPTYPE_ISO}; + + SetupEndpoints(c_out, EP_COUNT_OUT, c_in, EP_COUNT_IN, epTypeTableOut, epTypeTableIn); + + driveSofs(c_sof, 32/SOF_DIVIDE); + + p_test0 <: 0; + + /* Sim missing SOFs */ + delay(MISSING_SOF_PERIOD); + + p_test0 <: 1; + + driveSofs(c_sof, 16/SOF_DIVIDE); + + p_test0 <: 0; + + delay(MISSING_SOF_PERIOD); + + p_test0 <: 1; + + driveSofs(c_sof, 16/SOF_DIVIDE); + + p_test0 <: 0; + +} + +extern XUD_BusSpeed_t g_curUsbSpeed; + +#define MARGIN (1500/10) +#define EXPECTED_PERIOD (100000/10) + +void checker() +{ + timer t; + unsigned t0, t1; + unsigned x = 0; + int fail = 0; + + p_test1 <: 1; + + p_pll_loop when pinseq(1) :> x; + p_pll_loop when pinseq(0) :> x; + p_pll_loop when pinseq(1) :> x; + + for(int i = 0; i < 12; i++) + { + p_pll_loop when pinsneq(x) :> x; + t :> t0; + p_pll_loop when pinsneq(x) :> x; + t :> t1; + + int period = t1-t0; + + /* Check the period of the reference clock we are generating */ + if(period > (EXPECTED_PERIOD + MARGIN)) + { + printstr("Period too long: "); + printintln(period); + fail = 1; + } + else if(period < (EXPECTED_PERIOD - MARGIN)) + { + printstr("Period too short: "); + printintln(period); + fail = 1; + } + } + if(!fail) + printstrln("PASS"); + + p_test1 <: 0; + + exit(0); +} + + +int main() +{ + chan c_out[EP_COUNT_OUT]; + chan c_in[EP_COUNT_IN]; + chan c_sof; + chan c_aud_ctl; + + interface pll_ref_if i_pll_ref; + + par + { + PllRefPinTask(i_pll_ref, p_pll_ref); + + { + g_curUsbSpeed = BUS_SPEED; + + XUA_Buffer_Ep(c_out[1], /* USB Audio Out*/ + c_in[1], /* USB Audio In */ + c_sof, c_aud_ctl, p_off_mclk, i_pll_ref + ); + } + + fake_xud(c_out, c_in, c_sof); + + checker(); + } +} diff --git a/tests/test_sync_clk_basic/src/test_xs3_600.xn b/tests/test_sync_clk_basic/src/test_xs3_600.xn new file mode 100644 index 000000000..20e8eeb65 --- /dev/null +++ b/tests/test_sync_clk_basic/src/test_xs3_600.xn @@ -0,0 +1,24 @@ + + + + tileref tile[2] + + + + + + + + + + + + + + + + + + diff --git a/tests/test_sync_clk_basic/src/xua_conf.h b/tests/test_sync_clk_basic/src/xua_conf.h new file mode 100644 index 000000000..616262b77 --- /dev/null +++ b/tests/test_sync_clk_basic/src/xua_conf.h @@ -0,0 +1,44 @@ +// Copyright 2016-2022 XMOS LIMITED. +// This Software is subject to the terms of the XMOS Public Licence: Version 1. +#ifndef _XUA_CONF_H_ +#define _XUA_CONF_H_ + +#define NUM_USB_CHAN_OUT (2) +#define NUM_USB_CHAN_IN (2) +#define I2S_CHANS_DAC (2) +#define I2S_CHANS_ADC (2) + +#define XUA_SYNCMODE XUA_SYNCMODE_SYNC +#define UAC_FORCE_FEEDBACK_EP (0) + +#define EXCLUDE_USB_AUDIO_MAIN +#define XUA_NUM_PDM_MICS 0 +#define XUD_TILE 1 +#define AUDIO_IO_TILE 0 +#define MIXER 0 + +#ifndef MCLK_441 +#define MCLK_441 (512 * 44100) +#endif + +#ifndef MCLK_48 +#define MCLK_48 (512 * 48000) +#endif + +#define MIN_FREQ (44100) +#define MAX_FREQ (192000) +#define SPDIF_TX_INDEX 0 +#define VENDOR_STR "XMOS" +#define VENDOR_ID 0x20B1 +#define PRODUCT_STR_A2 "Test device" +#define PRODUCT_STR_A1 "Test device" +#define PID_AUDIO_1 1 +#define PID_AUDIO_2 2 +#define AUDIO_CLASS 2 +#define AUDIO_CLASS_FALLBACK 0 +#define BCD_DEVICE 0x1234 +#define XUA_DFU_EN 0 +#define MIC_DUAL_ENABLED 1 //Use single thread, dual PDM mic +#define XUA_MIC_FRAME_SIZE 240 + +#endif diff --git a/tests/test_sync_clk_plugin.py b/tests/test_sync_clk_plugin.py new file mode 100644 index 000000000..b580ece97 --- /dev/null +++ b/tests/test_sync_clk_plugin.py @@ -0,0 +1,12 @@ +# Copyright 2022 XMOS LIMITED. +# This Software is subject to the terms of the XMOS Public Licence: Version 1. +import pytest +from test_sync_clk_basic import do_test +from test_sync_clk_basic import test_file + + +@pytest.mark.parametrize("bus_speed", ["FS", "HS"]) +def test_sync_clk_plugin(bus_speed, test_file, options, capfd): + pytest.xfail("This is a known failure due to issue #275") + result = do_test(bus_speed, test_file, options, capfd) + assert result diff --git a/tests/test_sync_clk_plugin/Makefile b/tests/test_sync_clk_plugin/Makefile new file mode 100644 index 000000000..08eec76a0 --- /dev/null +++ b/tests/test_sync_clk_plugin/Makefile @@ -0,0 +1,4 @@ + +TEST_FLAGS = -DMISSING_SOF_PERIOD=7500 + +include ../test_sync_clk_basic/Makefile diff --git a/tests/test_sync_clk_plugin/src/main.xc b/tests/test_sync_clk_plugin/src/main.xc new file mode 100644 index 000000000..e66994eaa --- /dev/null +++ b/tests/test_sync_clk_plugin/src/main.xc @@ -0,0 +1,8 @@ +// Copyright 2022 XMOS LIMITED. +// This Software is subject to the terms of the XMOS Public Licence: Version 1. + +/* This tests for a smooth transition from internal to SOF clock. + * Unlike test_sync_clk_basic it does not use a "nice" value for MISSING_SOFS + */ + +#include "../test_sync_clk_basic/src/main.xc" diff --git a/tests/test_sync_clk_plugin/src/test_xs3_600.xn b/tests/test_sync_clk_plugin/src/test_xs3_600.xn new file mode 100644 index 000000000..20e8eeb65 --- /dev/null +++ b/tests/test_sync_clk_plugin/src/test_xs3_600.xn @@ -0,0 +1,24 @@ + + + + tileref tile[2] + + + + + + + + + + + + + + + + + + diff --git a/tests/test_sync_clk_plugin/src/xua_conf.h b/tests/test_sync_clk_plugin/src/xua_conf.h new file mode 100644 index 000000000..616262b77 --- /dev/null +++ b/tests/test_sync_clk_plugin/src/xua_conf.h @@ -0,0 +1,44 @@ +// Copyright 2016-2022 XMOS LIMITED. +// This Software is subject to the terms of the XMOS Public Licence: Version 1. +#ifndef _XUA_CONF_H_ +#define _XUA_CONF_H_ + +#define NUM_USB_CHAN_OUT (2) +#define NUM_USB_CHAN_IN (2) +#define I2S_CHANS_DAC (2) +#define I2S_CHANS_ADC (2) + +#define XUA_SYNCMODE XUA_SYNCMODE_SYNC +#define UAC_FORCE_FEEDBACK_EP (0) + +#define EXCLUDE_USB_AUDIO_MAIN +#define XUA_NUM_PDM_MICS 0 +#define XUD_TILE 1 +#define AUDIO_IO_TILE 0 +#define MIXER 0 + +#ifndef MCLK_441 +#define MCLK_441 (512 * 44100) +#endif + +#ifndef MCLK_48 +#define MCLK_48 (512 * 48000) +#endif + +#define MIN_FREQ (44100) +#define MAX_FREQ (192000) +#define SPDIF_TX_INDEX 0 +#define VENDOR_STR "XMOS" +#define VENDOR_ID 0x20B1 +#define PRODUCT_STR_A2 "Test device" +#define PRODUCT_STR_A1 "Test device" +#define PID_AUDIO_1 1 +#define PID_AUDIO_2 2 +#define AUDIO_CLASS 2 +#define AUDIO_CLASS_FALLBACK 0 +#define BCD_DEVICE 0x1234 +#define XUA_DFU_EN 0 +#define MIC_DUAL_ENABLED 1 //Use single thread, dual PDM mic +#define XUA_MIC_FRAME_SIZE 240 + +#endif diff --git a/tests/xua_unit_tests/conftest.py b/tests/xua_unit_tests/conftest.py index e2e1a54a1..2128a9b7e 100644 --- a/tests/xua_unit_tests/conftest.py +++ b/tests/xua_unit_tests/conftest.py @@ -1,4 +1,4 @@ -# Copyright 2021 XMOS LIMITED. +# Copyright 2021-2022 XMOS LIMITED. # This Software is subject to the terms of the XMOS Public Licence: Version 1. from __future__ import print_function from builtins import str @@ -6,16 +6,17 @@ import pytest import subprocess -target = os.environ.get('TARGET', 'all_possible') +target = os.environ.get("TARGET", "all_possible") print("target = ", target) + def pytest_collect_file(parent, path): - if(path.ext == ".xe"): - if(target == 'all_possible'): + if path.ext == ".xe": + if target == "all_possible": return UnityTestSource.from_parent(parent, fspath=path) - if(target == 'XCOREAI' and ('xcoreai' in path.basename)): + if target == "XCOREAI" and ("xcoreai" in path.basename): return UnityTestSource.from_parent(parent, fspath=path) - if(target == 'XCORE200' and ('xcore200' in path.basename)): + if target == "XCORE200" and ("xcore200" in path.basename): return UnityTestSource.from_parent(parent, fspath=path) @@ -31,7 +32,7 @@ def collect(self): # |-- src/ <- Unity test functions # `-- wscript <- Build system file used to generate/build runners xe_name = ((os.path.basename(self.name)).split("."))[0] + ".xe" - test_bin_path = os.path.join('bin', xe_name) + test_bin_path = os.path.join("bin", xe_name) yield UnityTestExecutable.from_parent(self, name=self.name) @@ -46,12 +47,16 @@ def runtest(self): simulator_fail = False test_output = None try: - if('xcore200' in self.name): + if "xcore200" in self.name: print("run axe for executable ", self.name) - test_output = subprocess.check_output(['axe', self.name], text=True) + test_output = subprocess.check_output(["axe", self.name], text=True) else: print("run xrun for executable ", self.name) - test_output = subprocess.check_output(['xrun', '--io', '--id', '0', self.name], text=True, stderr=subprocess.STDOUT) + test_output = subprocess.check_output( + ["xrun", "--io", "--id", "0", self.name], + text=True, + stderr=subprocess.STDOUT, + ) except subprocess.CalledProcessError as e: # Unity exits non-zero if an assertion fails simulator_fail = True @@ -59,10 +64,10 @@ def runtest(self): # Parse the Unity output unity_pass = False - test_output = test_output.split('\n') + test_output = test_output.split("\n") for line in test_output: - if 'test' in line: - test_report = line.split(':') + if "test" in line: + test_report = line.split(":") # Unity output is as follows: # :::PASS # :::FAIL: @@ -71,34 +76,43 @@ def runtest(self): test_case = test_report[2] result = test_report[3] failure_reason = None - print(('\n {}()'.format(test_case)), end=' ') - if result == 'PASS': + print(("\n {}()".format(test_case)), end=" ") + if result == "PASS": unity_pass = True continue - if result == 'FAIL': + if result == "FAIL": failure_reason = test_report[4] - print('') # Insert line break after test_case print - raise UnityTestException(self, {'test_source': test_source, - 'line_number': line_number, - 'test_case': test_case, - 'failure_reason': - failure_reason}) + print("") # Insert line break after test_case print + raise UnityTestException( + self, + { + "test_source": test_source, + "line_number": line_number, + "test_case": test_case, + "failure_reason": failure_reason, + }, + ) if simulator_fail: raise Exception(self, "Simulation failed.") if not unity_pass: raise Exception(self, "Unity test output not found.") - print('') # Insert line break after final test_case which passed + print("") # Insert line break after final test_case which passed def repr_failure(self, excinfo): if isinstance(excinfo.value, UnityTestException): - return '\n'.join([str(self.parent).strip('<>'), - '{}:{}:{}()'.format( - excinfo.value[1]['test_source'], - excinfo.value[1]['line_number'], - excinfo.value[1]['test_case']), - 'Failure reason:', - excinfo.value[1]['failure_reason']]) + return "\n".join( + [ + str(self.parent).strip("<>"), + "{}:{}:{}()".format( + excinfo.value[1]["test_source"], + excinfo.value[1]["line_number"], + excinfo.value[1]["test_case"], + ), + "Failure reason:", + excinfo.value[1]["failure_reason"], + ] + ) else: return str(excinfo.value) diff --git a/tests/xua_unit_tests/generate_unity_runners.py b/tests/xua_unit_tests/generate_unity_runners.py index f2fe0f047..7276d9695 100644 --- a/tests/xua_unit_tests/generate_unity_runners.py +++ b/tests/xua_unit_tests/generate_unity_runners.py @@ -1,40 +1,43 @@ -# Copyright 2021 XMOS LIMITED. +# Copyright 2021-2022 XMOS LIMITED. # This Software is subject to the terms of the XMOS Public Licence: Version 1. import glob import os.path import subprocess import sys -UNITY_TEST_DIR = 'src' -UNITY_TEST_PREFIX = 'test_' -UNITY_RUNNER_DIR = 'runners' -UNITY_RUNNER_SUFFIX = '_Runner' -project_root = os.path.join('..', '..', '..') +UNITY_TEST_DIR = "src" +UNITY_TEST_PREFIX = "test_" +UNITY_RUNNER_DIR = "runners" +UNITY_RUNNER_SUFFIX = "_Runner" +project_root = os.path.join("..", "..", "..") + def get_ruby(): """ Check ruby is avaliable and return the command to invoke it. """ - interpreter_name = 'ruby' + interpreter_name = "ruby" try: - dev_null = open(os.devnull, 'w') + dev_null = open(os.devnull, "w") # Call the version command to check the interpreter can be run - subprocess.check_call([interpreter_name, '--version'], - stdout=dev_null, - close_fds=True) + subprocess.check_call( + [interpreter_name, "--version"], stdout=dev_null, close_fds=True + ) except OSError as e: print("Failed to run Ruby interpreter: {}".format(e), file=sys.stderr) exit(1) # TODO: Check this is the correct way to kill xwaf on error return interpreter_name + def get_unity_runner_generator(project_root_path): """ Check the Unity generate_test_runner script is avaliable, and return the path to it. """ unity_runner_generator = os.path.join( - project_root_path, 'Unity', 'auto', 'generate_test_runner.rb') + project_root_path, "Unity", "auto", "generate_test_runner.rb" + ) if not os.path.exists(unity_runner_generator): print("Unity repo not found in workspace", file=sys.stderr) exit(1) # TODO: Check this is the correct way to kill xwaf on error @@ -52,32 +55,41 @@ def get_file_type(filename): """ Return the extension from the filename. """ - return filename.rsplit('.')[-1:][0] + return filename.rsplit(".")[-1:][0] -def generate_unity_runner(project_root_path, unity_test_path, unity_runner_dir, - unity_runner_suffix): +def generate_unity_runner( + project_root_path, unity_test_path, unity_runner_dir, unity_runner_suffix +): """ Invoke the Unity runner generation script for the given test file, and return the path to the generated file. The output directory will be created if it does not already exist. """ - runner_path = os.path.join(os.path.join(unity_runner_dir, get_test_name(unity_test_path))) + runner_path = os.path.join( + os.path.join(unity_runner_dir, get_test_name(unity_test_path)) + ) if not os.path.exists(runner_path): os.makedirs(runner_path) unity_runner_path = os.path.join( - runner_path, get_test_name(unity_test_path) + unity_runner_suffix - + '.' + 'c') + runner_path, get_test_name(unity_test_path) + unity_runner_suffix + "." + "c" + ) try: - subprocess.check_call([get_ruby(), - get_unity_runner_generator(project_root_path), - unity_test_path, - unity_runner_path]) + subprocess.check_call( + [ + get_ruby(), + get_unity_runner_generator(project_root_path), + unity_test_path, + unity_runner_path, + ] + ) except OSError as e: - print("Ruby generator failed for {}\n\t{}".format(unity_test_path, e), - file=sys.stderr) + print( + "Ruby generator failed for {}\n\t{}".format(unity_test_path, e), + file=sys.stderr, + ) exit(1) # TODO: Check this is the correct way to kill xwaf on error @@ -86,7 +98,7 @@ def find_unity_test_paths(unity_test_dir, unity_test_prefix): Return a list of all file paths with the unity_test_prefix found in the unity_test_dir. """ - return glob.glob(os.path.join(unity_test_dir, unity_test_prefix+'*')) + return glob.glob(os.path.join(unity_test_dir, unity_test_prefix + "*")) def find_unity_tests(unity_test_dir, unity_test_prefix): @@ -95,25 +107,27 @@ def find_unity_tests(unity_test_dir, unity_test_prefix): unity_test_prefix found in the unity_test_dir. """ unity_test_paths = find_unity_test_paths(unity_test_dir, unity_test_prefix) - print('unity_test_paths = ', unity_test_paths) - return {get_test_name(path): get_file_type(path) - for path in unity_test_paths} + print("unity_test_paths = ", unity_test_paths) + return {get_test_name(path): get_file_type(path) for path in unity_test_paths} + def find_unity_test_paths(unity_test_dir, unity_test_prefix): """ Return a list of all file paths with the unity_test_prefix found in the unity_test_dir. """ - return glob.glob(os.path.join(unity_test_dir, unity_test_prefix+'*')) + return glob.glob(os.path.join(unity_test_dir, unity_test_prefix + "*")) def generate_runners(): UNITY_TESTS = find_unity_tests(UNITY_TEST_DIR, UNITY_TEST_PREFIX) - print('UNITY_TESTS = ',UNITY_TESTS) + print("UNITY_TESTS = ", UNITY_TESTS) unity_test_paths = find_unity_test_paths(UNITY_TEST_DIR, UNITY_TEST_PREFIX) - print('unity_test_paths = ',unity_test_paths) + print("unity_test_paths = ", unity_test_paths) for unity_test_path in unity_test_paths: - generate_unity_runner(project_root, unity_test_path, UNITY_RUNNER_DIR, UNITY_RUNNER_SUFFIX) + generate_unity_runner( + project_root, unity_test_path, UNITY_RUNNER_DIR, UNITY_RUNNER_SUFFIX + ) if __name__ == "__main__":