forked from PAWPAW-Mirror/lib_xua
Merge pull request #274 from xross/feature/sync_tests
Feature/sync tests
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -32,3 +32,7 @@ build/
|
||||
.build*
|
||||
*.pyc
|
||||
xscope.xmt
|
||||
|
||||
# Traces
|
||||
*.gtkw
|
||||
*.vcd
|
||||
|
||||
14
Jenkinsfile
vendored
14
Jenkinsfile
vendored
@@ -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') {
|
||||
|
||||
@@ -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()
|
||||
@@ -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')
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
#include "xua.h"
|
||||
#if XUA_USB_EN
|
||||
#include <xs1.h>
|
||||
#include <print.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 <xs1.h>
|
||||
@@ -6,7 +6,6 @@
|
||||
#include <platform.h>
|
||||
#undef __ASSEMBLER__
|
||||
#include "audioports.h"
|
||||
#include <xccompat.h>
|
||||
#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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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 <xccompat.h>
|
||||
#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__*/
|
||||
|
||||
@@ -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 <xs1.h>
|
||||
#include <platform.h>
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
24
tests/conftest.py
Normal file
24
tests/conftest.py
Normal file
@@ -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
|
||||
81
tests/test_i2s_loopback.py
Normal file
81
tests/test_i2s_loopback.py
Normal file
@@ -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
|
||||
@@ -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__
|
||||
@@ -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__
|
||||
@@ -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 <xs1.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)
|
||||
|
||||
@@ -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_
|
||||
@@ -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_
|
||||
@@ -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 <xs1.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__
|
||||
@@ -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
|
||||
58
tests/test_sync_clk_basic.py
Normal file
58
tests/test_sync_clk_basic.py
Normal file
@@ -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
|
||||
17
tests/test_sync_clk_basic/Makefile
Normal file
17
tests/test_sync_clk_basic/Makefile
Normal file
@@ -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
|
||||
196
tests/test_sync_clk_basic/src/main.xc
Normal file
196
tests/test_sync_clk_basic/src/main.xc
Normal file
@@ -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();
|
||||
}
|
||||
}
|
||||
24
tests/test_sync_clk_basic/src/test_xs3_600.xn
Normal file
24
tests/test_sync_clk_basic/src/test_xs3_600.xn
Normal file
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Network xmlns="http://www.xmos.com"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.xmos.com http://www.xmos.com">
|
||||
<Declarations>
|
||||
<Declaration>tileref tile[2]</Declaration>
|
||||
</Declarations>
|
||||
|
||||
<Packages>
|
||||
<Package id="0" Type="XS3-UnA-1024-FB265">
|
||||
<Nodes>
|
||||
<Node Id="0" InPackageId="0" Type="XS3-L16A-1024" Oscillator="24MHz" SystemFrequency="600MHz" ReferenceFrequency="100MHz">
|
||||
<Tile Number="0" Reference="tile[0]"/>
|
||||
<Tile Number="1" Reference="tile[1]"/>
|
||||
</Node>
|
||||
</Nodes>
|
||||
</Package>
|
||||
</Packages>
|
||||
|
||||
<JTAGChain>
|
||||
<JTAGDevice NodeId="0"/>
|
||||
</JTAGChain>
|
||||
|
||||
</Network>
|
||||
44
tests/test_sync_clk_basic/src/xua_conf.h
Normal file
44
tests/test_sync_clk_basic/src/xua_conf.h
Normal file
@@ -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
|
||||
12
tests/test_sync_clk_plugin.py
Normal file
12
tests/test_sync_clk_plugin.py
Normal file
@@ -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
|
||||
4
tests/test_sync_clk_plugin/Makefile
Normal file
4
tests/test_sync_clk_plugin/Makefile
Normal file
@@ -0,0 +1,4 @@
|
||||
|
||||
TEST_FLAGS = -DMISSING_SOF_PERIOD=7500
|
||||
|
||||
include ../test_sync_clk_basic/Makefile
|
||||
8
tests/test_sync_clk_plugin/src/main.xc
Normal file
8
tests/test_sync_clk_plugin/src/main.xc
Normal file
@@ -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"
|
||||
24
tests/test_sync_clk_plugin/src/test_xs3_600.xn
Normal file
24
tests/test_sync_clk_plugin/src/test_xs3_600.xn
Normal file
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Network xmlns="http://www.xmos.com"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.xmos.com http://www.xmos.com">
|
||||
<Declarations>
|
||||
<Declaration>tileref tile[2]</Declaration>
|
||||
</Declarations>
|
||||
|
||||
<Packages>
|
||||
<Package id="0" Type="XS3-UnA-1024-FB265">
|
||||
<Nodes>
|
||||
<Node Id="0" InPackageId="0" Type="XS3-L16A-1024" Oscillator="24MHz" SystemFrequency="600MHz" ReferenceFrequency="100MHz">
|
||||
<Tile Number="0" Reference="tile[0]"/>
|
||||
<Tile Number="1" Reference="tile[1]"/>
|
||||
</Node>
|
||||
</Nodes>
|
||||
</Package>
|
||||
</Packages>
|
||||
|
||||
<JTAGChain>
|
||||
<JTAGDevice NodeId="0"/>
|
||||
</JTAGChain>
|
||||
|
||||
</Network>
|
||||
44
tests/test_sync_clk_plugin/src/xua_conf.h
Normal file
44
tests/test_sync_clk_plugin/src/xua_conf.h
Normal file
@@ -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
|
||||
@@ -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 os.path
|
||||
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 @@ class UnityTestSource(pytest.File):
|
||||
# |-- 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 @@ class UnityTestExecutable(pytest.Item):
|
||||
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 @@ class UnityTestExecutable(pytest.Item):
|
||||
|
||||
# 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:
|
||||
# <test_source>:<line_number>:<test_case>:PASS
|
||||
# <test_source>:<line_number>:<test_case>:FAIL:<failure_reason>
|
||||
@@ -71,34 +76,43 @@ class UnityTestExecutable(pytest.Item):
|
||||
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)
|
||||
|
||||
|
||||
@@ -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__":
|
||||
|
||||
Reference in New Issue
Block a user