Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,5 @@ build.xcore

# Python cache information
lib_mic_array.egg-info
examples/app_mic_array_basic/output.wav
examples/app_mic_array_basic/mic_array_output.bin
84 changes: 64 additions & 20 deletions Jenkinsfile
Original file line number Diff line number Diff line change
@@ -1,25 +1,30 @@
// This file relates to internal XMOS infrastructure and should be ignored by external users

@Library('xmos_jenkins_shared_library@v0.46.0') _
@Library('xmos_jenkins_shared_library@v0.48.0') _

getApproval()
pipeline {
agent none

parameters {
string(
name: 'TOOLS_VERSION',
name: 'TOOLS_XS3_VERSION',
defaultValue: '15.3.1',
description: 'The XTC tools version'
)
string(
name: 'TOOLS_VX4_VERSION',
defaultValue: '-j --repo arch_vx_slipgate -b master -a XTC 116',
description: 'The XTC Slipgate tools version'
)
string(
name: 'XMOSDOC_VERSION',
defaultValue: 'v8.0.1',
description: 'The xmosdoc version')

description: 'The xmosdoc version'
)
string(
name: 'INFR_APPS_VERSION',
defaultValue: 'v3.3.0',
defaultValue: 'develop', //TODO pin after release
description: 'The infr_apps version'
)
choice(
Expand Down Expand Up @@ -60,7 +65,7 @@ pipeline {
stage('Examples build') {
steps {
dir("${REPO_NAME}/examples") {
xcoreBuild()
xcoreBuild(toolsVersion: params.TOOLS_XS3_VERSION)
}
}
}
Expand Down Expand Up @@ -97,6 +102,7 @@ pipeline {
label 'x86_64 && linux'
}
steps {
println "Stage running on ${env.NODE_NAME}"
script {
def (server, user, repo) = extractFromScmUrl()
env.REPO_NAME = repo
Expand All @@ -106,7 +112,7 @@ pipeline {
dir("tests") {
createVenv(reqFile: "requirements.txt")
withVenv {
xcoreBuild()
xcoreBuild(toolsVersion: params.TOOLS_XS3_VERSION, jobs:31)
stash includes: '**/*.xe', name: 'test_bin', useDefaultExcludes: false
}
}
Expand All @@ -124,7 +130,7 @@ pipeline {
sh "git clone git@github.com:xmos/xmos_cmake_toolchain.git --branch v1.0.0"
dir(REPO_NAME) {
checkoutScmShallow()
withTools(params.TOOLS_VERSION) {
withTools(params.TOOLS_XS3_VERSION) {
sh "cmake -B build.xcore -DDEV_LIB_MIC_ARRAY=1 -DCMAKE_TOOLCHAIN_FILE=../xmos_cmake_toolchain/xs3a.cmake"
sh "cd build.xcore && make all -j 16"
}
Expand All @@ -136,13 +142,11 @@ pipeline {
}
}
} // stage('Custom CMake build')

stage('Tests') {
parallel {
stage('XS3 tests') {
agent {
label 'xcore.ai'
}
stage('XS3 Tests') {
agent {label 'xcore.ai'}
stages {
stage("Checkout and Build") {
steps {
Expand All @@ -159,7 +163,7 @@ pipeline {
stage('Run tests') {
steps {
dir("${REPO_NAME}/tests") {
withTools(params.TOOLS_VERSION) {
withTools(params.TOOLS_XS3_VERSION) {
withVenv {

// This ensures a project for XS2 can be built and runs OK
Expand All @@ -183,7 +187,7 @@ pipeline {
if(params.TEST_LEVEL == 'smoke')
{
echo "Running tests with fixed seed 12345"
sh "pytest -v --junitxml=pytest_basic_mic.xml --seed 12345 --level ${params.TEST_LEVEL} "
sh "pytest -v --junitxml=pytest_basic_mic.xml --seed 12345 --level ${params.TEST_LEVEL}"
}
else
{
Expand All @@ -209,11 +213,51 @@ pipeline {
} // stage('Run tests')
} // stages
post {
cleanup {
xcoreCleanSandbox()
}
}
} // stage('HW tests')
cleanup {xcoreCleanSandbox()}
} // post
} // XS3 Tests

stage('VX4 Tests') {
agent {label "vx4"}
stages {
stage("Checkout and Build") {
steps {
dir(REPO_NAME){
checkoutScmShallow()
dir("tests") {
createVenv(reqFile: "requirements.txt")
withVenv {
dir("unit") {
xcoreBuild(toolsVersion: params.TOOLS_VX4_VERSION)
}
dir ("signal/BasicMicArray") {
withTools(params.TOOLS_VX4_VERSION){
xcoreBuild(toolsVersion: params.TOOLS_VX4_VERSION, jobs:8)
}
}
} // withVenv
} // dir("tests")
} // dir(REPO_NAME)
} // steps
} // stage("Checkout and Build")
stage('Run tests') {
steps {
dir("${REPO_NAME}/tests") {
withVenv {
dir("unit") {
withTools(params.TOOLS_VX4_VERSION) {sh "xrun --xscope bin/tests-unit.xe"}
}
dir("signal/BasicMicArray") {
withTools(params.TOOLS_VX4_VERSION) {sh 'python -m pytest --level nightly --seed 12345 -k "0isr or OneStageFilter" -v'}
}
} // withVenv
}}} // stage('Run tests')
} // stages
post {
cleanup {xcoreCleanSandbox()}
} //post
} // VX4 Tests

} // parallel
} // stage('Tests')

Expand Down
1 change: 1 addition & 0 deletions doc/exclude_patterns.inc
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ LICENSE.rst
build.xcore
tests/**/.pytest_cache/*.md
tests/.pytest_cache/*.md
**/app_mic_array_basic*/*.md
1 change: 1 addition & 0 deletions doc/rst/lib_mic_array.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ lib_mic_array: PDM microphone array library
src/getting_started
src/examples
src/resource_usage
src/mic_switching
src/software_structure
src/decimator_stages
src/custom_filters
Expand Down
6 changes: 3 additions & 3 deletions doc/rst/src/advanced_usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ the :cpp:class:`MicArray <mic_array::MicArray>`:
.. code-block:: c++

using TMicArray = mic_array::MicArray<APP_N_MICS,
mic_array::TwoStageDecimator<APP_N_MICS,
mic_array::Decimator<APP_N_MICS,
STAGE2_DEC_FACTOR_48KHZ,
MIC_ARRAY_48K_STAGE_2_TAP_COUNT>,
mic_array::StandardPdmRxService<APP_N_MICS_IN,
Expand All @@ -70,7 +70,7 @@ the :cpp:class:`MicArray <mic_array::MicArray>`:

TMicArray mics;

- ``TwoStageDecimator``, ``StandardPdmRxService``, ``DcoeSampleFilter``,
- ``Decimator``, ``StandardPdmRxService``, ``DcoeSampleFilter``,
and ``FrameOutputHandler`` can all be replaced with custom classes if needed.

- Any custom class must implement the same interface expected by :cpp:class:`MicArray <mic_array::MicArray>`.
Expand All @@ -82,7 +82,7 @@ the :cpp:class:`MicArray <mic_array::MicArray>`:

.. note::

If the application requires custom decimation filters but they're compatible with the :cpp:class:`TwoStageDecimator <mic_array::TwoStageDecimator>` implementation,
If the application requires custom decimation filters but they're compatible with the :cpp:class:`Decimator <mic_array::Decimator>` implementation,
refer to :ref:`custom_filters` to see how to do so.

Define app-callable functions
Expand Down
97 changes: 72 additions & 25 deletions doc/rst/src/custom_filters.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@
Custom decimation filters
*************************

In the :cpp:class:`TwoStageDecimator <mic_array::TwoStageDecimator>`, the tap count and decimation factor
for the first stage decimator are fixed to ``256`` and ``32`` respectively, as described in :ref:`decimator_stage_1`.
The :cpp:class:`Decimator <mic_array::Decimator>` supports 1-, 2-, or 3-stage decimation pipelines configured via custom filters.
This flexibility allows applications to tailor the filter chain to their specific latency and computational requirements.

These parameters cannot be changed without implementing a custom decimator, which is outside the scope of this document.
Custom filters must comply with implementation requirements for each stage. See :ref:`stage_constraints_custom`
for details on stage-specific constraints.

However, both the first-stage and second-stage filter coefficients may be
replaced, and the second-stage decimation factor and tap count may be freely
modified by running the mic array component with custom filters. This is described in the following sections.
This document explains how to design and deploy custom decimation filters for 1-, 2-, or 3-stage configurations.

.. _designing_custom_filters:

Expand All @@ -24,8 +23,8 @@ of ``lib_mic_array`` and save them as ``.pkl`` files. Using these functions as
a guide, the script can be extended to generate custom filters tailored to the
application's needs.

Note that in :cpp:class:`TwoStageDecimator <mic_array::TwoStageDecimator>`,
both the first and second stage filters are implemented
Note that in :cpp:class:`Decimator <mic_array::Decimator>`,
the filters are implemented
using fixed-point arithmetic, which requires the coefficients to be presented
in a specific format.
The helper scripts ``python/stage1.py`` and ``python/stage2.py`` generate
Expand Down Expand Up @@ -68,24 +67,9 @@ From the ``python`` directory, the workflow is typically:
Using custom filters
====================

When using the :cpp:class:`TwoStageDecimator <mic_array::TwoStageDecimator>` provided by the
When using the :cpp:class:`Decimator <mic_array::Decimator>` provided by the
library, the :c:func:`mic_array_init_custom_filter` function is used to
initialize a mic array instance with a custom 2-stage decimation filter.

.. note::

The custom filter provided to :c:func:`mic_array_init_custom_filter` must
be compatible with the :cpp:class:`TwoStageDecimator
<mic_array::TwoStageDecimator>` requirements. Specifically, it must be a
2-stage filter. The tap count and decimation factor for the first-stage
decimator are fixed at ``256`` and ``32``, respectively, and the filter must
be compatible with the :ref:`stage_1_filter_impl`.

The second-stage decimation filter tap count and decimation ratio are flexible,
provided it is a standard FIR filter compatible with :ref:`stage_2_filter_impl`.
Using custom filters that are incompatible with the implementation in
:cpp:class:`TwoStageDecimator <mic_array::TwoStageDecimator>` is outside the
scope of this documentation.
initialize a mic array instance with a custom decimation filter.

The :c:type:`mic_array_conf_t` structure is populated with the decimator and
PDM RX configurations before calling
Expand Down Expand Up @@ -178,3 +162,66 @@ and started by calling :c:func:`mic_array_start`:
as including the mic array in an application, declaring resources, and overriding
build-time default configuration, are exactly the same as in the default usage
model described in :ref:`using_mic_array`.

.. _stage_constraints_custom:

Filter stage constraints
========================

**Stage 1 (mandatory)**

The first stage decimator has fixed constraints that cannot be changed:

- Tap count: ``256`` (fixed)
- Decimation factor: ``32`` (fixed)
- Implementation: Must be compatible with :c:func:`fir_1x16_bit` as described in :ref:`stage_1_filter_impl`

Only the filter coefficients may be customized. The coefficients must be quantized to 16-bit precision
and formatted appropriately for the VPU implementation. Use the Python helper script ``python/stage1.py``
to convert floating-point coefficients to the required format.

**Stage 2 (optional)**

If a second stage is included, it must meet these requirements:

- Implementation: Must be compatible with the 32-bit FIR filter from `lib_xcore_math <https://github.com/xmos/lib_xcore_math>`_,
specifically :c:func:`xs3_filter_fir_s32()` as described in :ref:`stage_2_filter_impl`
- Tap count: Configurable (no fixed constraint)
- Decimation factor: Configurable integer value

Use the Python helper script ``python/stage2.py`` to convert floating-point coefficients to the required format.

**Stage 3 (optional)**

A third stage, if included, must also be compatible with the 32-bit FIR filter from `lib_xcore_math <https://github.com/xmos/lib_xcore_math>`_.
It has the same flexibility as stage 2:

- Tap count: Configurable
- Decimation factor: Configurable integer value

**Single-stage decimator configuration**

Single-stage decimation is a special case in which additional decimation is
expected to be performed in the application. This is useful when downstream
decimation requirements are not directly represented by the integer-factor FIR
stages used by :cpp:class:`Decimator <mic_array::Decimator>` (for example,
rational-factor resampling).

When only stage 1 is used, the decimation factor is fixed at ``32``. If a
different final output sample rate is required, the application must perform
the remaining decimation after receiving the stage-1 output from the mic array.

Because further decimation is expected downstream, single-stage operation has
the following additional constraints:

- The DCOE filter is forcibly disabled, and
:c:macro:`MIC_ARRAY_CONFIG_USE_DC_ELIMINATION` is ignored. If required,
the application must apply DC elimination after all decimation is complete.
- The number of output words per channel from PDM RX
(:c:member:`pdm_rx_conf_t.pdm_out_words_per_channel`) must match
:c:macro:`MIC_ARRAY_CONFIG_SAMPLES_PER_FRAME`.
- :c:member:`pdm_rx_conf_t.pdm_out_words_per_channel` must not exceed
:cpp:member:`mic_array::MicArray::MAX_PDM_OUT_WORDS_PER_CHANNEL`.

These two conditions are checked at runtime. If either condition is violated,
the mic array initialization asserts.
Loading