Merge remote-tracking branch 'upstream' into feature/ai_examples

This commit is contained in:
xross
2022-08-08 16:39:19 +01:00
41 changed files with 712 additions and 189 deletions

4
.gitignore vendored
View File

@@ -32,3 +32,7 @@ build/
.build*
*.pyc
xscope.xmt
# Traces
*.gtkw
*.vcd

14
Jenkinsfile vendored
View File

@@ -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') {

View File

@@ -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()

View File

@@ -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')

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -485,20 +485,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

View File

@@ -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);
}

View File

@@ -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__*/

View File

@@ -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)

View File

@@ -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
View 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

View 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

View File

@@ -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__

View File

@@ -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__

View File

@@ -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>

View File

@@ -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)

View File

@@ -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_

View File

@@ -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_

View File

@@ -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>

View File

@@ -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__

View File

@@ -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

View 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

View 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

View 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();
}
}

View 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>

View 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

View 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

View File

@@ -0,0 +1,4 @@
TEST_FLAGS = -DMISSING_SOF_PERIOD=7500
include ../test_sync_clk_basic/Makefile

View 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"

View 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>

View 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

View File

@@ -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)

View File

@@ -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__":