Skip to content

/github/workspace/src/TransformFunctions/kernels/plp_dwt_q32s_xpulpv2.c

Functions

Name
void plp_dwt_q32s_xpulpv2(const int32_t restrict pSrc, uint32_t length, const plp_dwt_wavelet_q32 wavelet, plp_dwt_extension_mode mode, int32_t restrict pDstA, int32_t *restrict pDstD)
Q31 fixed-point DWT on real input data for XPULPV2 extension.

Defines

Name
HAAR_COEF
MAC_SHIFT
MAC(Acc, A, B)
MSU(Acc, A, B)
MAKE_HAAR(NAME, COEF, SHIFT)

Functions Documentation

function plp_dwt_q32s_xpulpv2

void plp_dwt_q32s_xpulpv2(
    const int32_t *__restrict__ pSrc,
    uint32_t length,
    const plp_dwt_wavelet_q32 wavelet,
    plp_dwt_extension_mode mode,
    int32_t *__restrict__ pDstA,
    int32_t *__restrict__ pDstD
)

Q31 fixed-point DWT on real input data for XPULPV2 extension.

Parameters:

  • pSrc points to the input buffer (real data)
  • length length of input buffer
  • wavelet wavelet structure for calculating DWT
  • mode boundary extension mode
  • pDstA points to ouput buffer with Approximate coefficients
  • pDstD points to ouput buffer with Detailed coefficients

Return: none

32bit Fixed-point DWT for XPULPV2 extension.

Macros Documentation

define HAAR_COEF

#define HAAR_COEF ((int64_t) 0x5a82799a)

define MAC_SHIFT

#define MAC_SHIFT 31U

define MAC

#define MAC(
    Acc,
    A,
    B
)
Acc += (int64_t)((int64_t) A * (int64_t) B);

define MSU

#define MSU(
    Acc,
    A,
    B
)
Acc -= (int64_t)((int64_t) A * (int64_t) B);

define MAKE_HAAR

#define MAKE_HAAR(
    NAME,
    COEF,
    SHIFT
)

Source code

/* ----------------------------------------------------------------------
 * Project:      PULP DSP Library
 * Title:        plp_dwt_q32s_xpulpv2.c
 * Description:  32bit Fixed-point Discret Wavelet Transform on real input data for XPULPV2
 *
 * $Date:        10. Juli 2021
 * $Revision:    V1
 *
 * Target Processor: PULP cores
 * -------------------------------------------------------------------- */
/*
 * Copyright (C) 2021 ETH Zurich and University of Bologna. All rights reserved.
 *
 * Author: Jakub Mandula, ETH Zurich
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the License); you may
 * not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "plp_math.h"
#include "plp_const_structs.h"
/* HELPER FUNCTIONS */

#define HAAR_COEF ((int64_t) 0x5a82799a)


#define MAC_SHIFT 31U
#define MAC(Acc, A, B) Acc += (int64_t)((int64_t) A * (int64_t) B);
#define MSU(Acc, A, B) Acc -= (int64_t)((int64_t) A * (int64_t) B);

#include "plp_dwt_signal_ext.h"

void plp_dwt_q32s_xpulpv2(const int32_t *__restrict__ pSrc,
                         uint32_t length,
                         const plp_dwt_wavelet_q32 wavelet,
                         plp_dwt_extension_mode mode,
                         int32_t *__restrict__ pDstA,
                         int32_t *__restrict__ pDstD) {
    int32_t *pCurrentA = pDstA;
    int32_t *pCurrentD = pDstD;

    static uint32_t step = 2;

    int32_t offset;

    /***
     * The filter convolution is done in 4 steps handling cases where
     *  1. Filter is hanging over the left side of the signal
     *  2. Filter is same size, or totally enclosed in signal
     *  3. Filter is larger than the enclosed signal and hangs over both edges
     *  4. Filter hangs over the right side of the signal
     * 
     *  Each of the cases, where signal hangs over the boundary of the signal, values are computed 
     *  on demand based on the edge extension mode.
     */


    /*  Step 1.
     *  Handle Left overhanging
     *
     * X() =  x x[A B C D E F]
     * H() = [d c b a]
     *          ^   ^
     *          |   First compute the filter part overlapping with the signal
     *          Then extend the signal (x x) by computing the values based on the extension mode
     */
    for(offset = step-1; offset < wavelet.length - 1 && offset < length; offset += step){
        int64_t sum_lo = 0;
        int64_t sum_hi = 0;

        uint32_t filt_j = 0;

        // Compute Filter overlapping with signal
        for(; filt_j <= offset; filt_j++){
            MAC(sum_lo, wavelet.dec_lo[filt_j], pSrc[offset - filt_j]);
            MAC(sum_hi, wavelet.dec_hi[filt_j], pSrc[offset - filt_j]);
        }

        // Compute Left edge extension
        switch(mode){
            case PLP_DWT_MODE_CONSTANT:
                CONSTANT_EDGE_LEFT(sum_lo, sum_hi, pSrc, length, wavelet, filt_j, offset);
                break;
            case PLP_DWT_MODE_SYMMETRIC:
                SYMMETRIC_EDGE_LEFT(sum_lo, sum_hi, pSrc, length, wavelet, filt_j, offset);
                break;
            case PLP_DWT_MODE_REFLECT:
                REFLECT_EDGE_LEFT(sum_lo, sum_hi, pSrc, length, wavelet, filt_j, offset);
                break;
            case PLP_DWT_MODE_ANTISYMMETRIC:
                ANTISYMMETRIC_EDGE_LEFT(sum_lo, sum_hi, pSrc, length, wavelet, filt_j, offset);
                break;
            case PLP_DWT_MODE_ANTIREFLECT:
                ANTIREFLECT_EDGE_LEFT(sum_lo, sum_hi, pSrc, length, wavelet, filt_j, offset, int64_t);
                break;
            case PLP_DWT_MODE_PERIODIC:
            case PLP_DWT_MODE_ZERO:
            default:
                break;
        }


        *pCurrentA++ = sum_lo >> MAC_SHIFT;
        *pCurrentD++ = sum_hi >> MAC_SHIFT;
    }

    /*  Step 2.
     *  Compute center (length >= wavelet.length)
     *
     *  X() = [A B C D E F]
     *  h() =   [d c b a]
     *                 ^
     *                 Compute a full convolution of the filter with the signal
     */    
    for(;offset < length; offset += step){

        int64_t sum_lo = 0;
        int64_t sum_hi = 0;


        const int32_t *pS = pSrc + offset;
        const int32_t *dec_lo = wavelet.dec_lo;
        const int32_t *dec_hi = wavelet.dec_hi;

        uint32_t blkCnt = wavelet.length >> 1;

        do{
            int32_t S1 = *pS--;
            int32_t S2 = *pS--;
            MAC(sum_lo, *dec_lo++, S1);
            MAC(sum_hi, *dec_hi++, S1);
            MAC(sum_lo, *dec_lo++, S2);
            MAC(sum_hi, *dec_hi++, S2);
        }while(--blkCnt);


        *pCurrentA++ = sum_lo >> MAC_SHIFT;
        *pCurrentD++ = sum_hi >> MAC_SHIFT;
    }

    /*  Step 3.
     *  Compute center (length < wavelet.length)
     *
     *  X() =   y y[A B C]x x x
     *  h() =  [h g f e d c b a]
     *            ^     ^     ^
     *            |     |     Compute Right extension (x x x) based on extension mode
     *            |     Compute a full convolution of the filter overlapping with the signal
     *            Compute Left extension (y y) based on extension mode
     */      

    for(;offset < wavelet.length - 1; offset += step){
        int64_t sum_lo = 0;
        int64_t sum_hi = 0;

        uint32_t filt_j = 0;

        // Filter Right extension
        switch(mode){
            case PLP_DWT_MODE_CONSTANT:
                CONSTANT_EDGE_RIGHT(sum_lo, sum_hi, pSrc, length, wavelet, filt_j, offset);
                break;
            case PLP_DWT_MODE_SYMMETRIC:
                SYMMETRIC_EDGE_RIGHT(sum_lo, sum_hi, pSrc, length, wavelet, filt_j, offset);
                break;
            case PLP_DWT_MODE_REFLECT:
                REFLECT_EDGE_RIGHT(sum_lo, sum_hi, pSrc, length, wavelet, filt_j, offset);
                break;
            case PLP_DWT_MODE_ANTISYMMETRIC:
                ANTISYMMETRIC_EDGE_RIGHT(sum_lo, sum_hi, pSrc, length, wavelet, filt_j, offset);
                break;
            case PLP_DWT_MODE_ANTIREFLECT:
                ANTIREFLECT_EDGE_RIGHT(sum_lo, sum_hi, pSrc, length, wavelet, filt_j, offset, int64_t);
                break;
            case PLP_DWT_MODE_PERIODIC:
            case PLP_DWT_MODE_ZERO:
            default:
                filt_j = offset - length + 1;
                break;
        }

        // Filter Center overlapp
        for(; filt_j <= offset; filt_j++){
            MAC(sum_lo, wavelet.dec_lo[filt_j], pSrc[offset - filt_j]);
            MAC(sum_hi, wavelet.dec_hi[filt_j], pSrc[offset - filt_j]);
        }   

        // Filter Left extension
        switch(mode){
            case PLP_DWT_MODE_CONSTANT:
                CONSTANT_EDGE_LEFT(sum_lo, sum_hi, pSrc, length, wavelet, filt_j, offset);
                break;
            case PLP_DWT_MODE_SYMMETRIC:
                SYMMETRIC_EDGE_LEFT(sum_lo, sum_hi, pSrc, length, wavelet, filt_j, offset);
                break;
            case PLP_DWT_MODE_REFLECT:
                REFLECT_EDGE_LEFT(sum_lo, sum_hi, pSrc, length, wavelet, filt_j, offset);
                break;
            case PLP_DWT_MODE_ANTISYMMETRIC:
                ANTISYMMETRIC_EDGE_LEFT(sum_lo, sum_hi, pSrc, length, wavelet, filt_j, offset);
                break;
            case PLP_DWT_MODE_ANTIREFLECT:
                ANTIREFLECT_EDGE_LEFT(sum_lo, sum_hi, pSrc, length, wavelet, filt_j, offset, int64_t);
                break;
            case PLP_DWT_MODE_PERIODIC:
            case PLP_DWT_MODE_ZERO:
            default:
                break;
        }

        *pCurrentA++ = sum_lo >> MAC_SHIFT;
        *pCurrentD++ = sum_hi >> MAC_SHIFT;
    }


    /*  Step 4.
     *  Handle Right overhanging
     *
     * X() = [A B C D E F]x x
     * H() =         [d c b a]
     *                  ^   ^
     *                  |   First extend the signal (x x) by computing the values based on the extension mode
     *                  Then compute the filter part overlapping with the signal
     */
    for(; offset < length + wavelet.length - 1; offset += step){
        int64_t sum_lo = 0;
        int64_t sum_hi = 0;

        uint32_t filt_j = 0;

        // Compute Left edge extension
        switch(mode){
            case PLP_DWT_MODE_CONSTANT:
                CONSTANT_EDGE_RIGHT(sum_lo, sum_hi, pSrc, length, wavelet, filt_j, offset);
                break;
            case PLP_DWT_MODE_SYMMETRIC:
                SYMMETRIC_EDGE_RIGHT(sum_lo, sum_hi, pSrc, length, wavelet, filt_j, offset);
                break;
            case PLP_DWT_MODE_REFLECT:
                REFLECT_EDGE_RIGHT(sum_lo, sum_hi, pSrc, length, wavelet, filt_j, offset);
                break;
            case PLP_DWT_MODE_ANTISYMMETRIC:
                ANTISYMMETRIC_EDGE_RIGHT(sum_lo, sum_hi, pSrc, length, wavelet, filt_j, offset);
                break;
            case PLP_DWT_MODE_ANTIREFLECT:
                ANTIREFLECT_EDGE_RIGHT(sum_lo, sum_hi, pSrc, length, wavelet, filt_j, offset, int64_t);
                break;
            case PLP_DWT_MODE_PERIODIC:
            case PLP_DWT_MODE_ZERO:
            default:
                filt_j = offset - length + 1;
                break;
        }

        // Filter overlapping with signal
        for(; filt_j < wavelet.length; filt_j++){
            MAC(sum_lo, wavelet.dec_lo[filt_j], pSrc[offset - filt_j]);
            MAC(sum_hi, wavelet.dec_hi[filt_j], pSrc[offset - filt_j]);
        }

        *pCurrentA++ = sum_lo >> MAC_SHIFT;
        *pCurrentD++ = sum_hi >> MAC_SHIFT;
    }
}






#define MAKE_HAAR(NAME, COEF, SHIFT)                                                                           \
void NAME(const int32_t *__restrict__ pSrc,                                                                    \
                         uint32_t length,                                                                      \
                         plp_dwt_extension_mode mode,                                                          \
                         int32_t *__restrict__ pDstA,                                                          \
                         int32_t *__restrict__ pDstD) {                                                        \
    int32_t *pCurrentA = pDstA;                                                                                \
    int32_t *pCurrentD = pDstD;                                                                                \
                                                                                                               \
                                                                                                               \
    /***                                                                                                       \
     * The filter convolution is done in 2 steps handling cases where                                          \
     *  1. Filter is same size, or totally enclosed in signal center                                           \
     *  2. Filter hangs over the right side of the signal                                                      \
     *                                                                                                         \
     *  In of the cases, where signal hangs over the boundary of the signal, values are computed               \
     *  on demand based on the edge extension mode.                                                            \
     */                                                                                                        \
                                                                                                               \
                                                                                                               \
    /*  Step 1.                                                                                                \
     *  Compute center (length >= wavelet.length)                                                              \
     *                                                                                                         \
     *  X() = [A B C D E F]                                                                                    \
     *  h() =       [b a]                                                                                      \
     *                 ^                                                                                       \
     *                 Compute a full convolution of the filter with the signal                                \
     */                                                                                                        \
    uint32_t blkCnt = length >> 2;                                                                             \
                                                                                                               \
    const int32_t *pS = pSrc;                                                                                  \
    while(blkCnt--){                                                                                           \
        int32_t s0 = *pS++;                                                                                    \
        int32_t s1 = *pS++;                                                                                    \
        int32_t s2 = *pS++;                                                                                    \
        int32_t s3 = *pS++;                                                                                    \
                                                                                                               \
        *pCurrentA++ = (COEF * (s0 + s1)) >> SHIFT;                                                            \
        *pCurrentD++ = (COEF * (s0 - s1)) >> SHIFT;                                                            \
        *pCurrentA++ = (COEF * (s2 + s3)) >> SHIFT;                                                            \
        *pCurrentD++ = (COEF * (s2 - s3)) >> SHIFT;                                                            \
                                                                                                               \
    }                                                                                                          \
                                                                                                               \
    if(length % 4 > 1){                                                                                        \
        int32_t s0 = *pS++;                                                                                    \
        int32_t s1 = *pS++;                                                                                    \
                                                                                                               \
        *pCurrentA++ = (COEF * (s0 + s1)) >> SHIFT;                                                            \
        *pCurrentD++ = (COEF * (s0 - s1)) >> SHIFT;                                                            \
    }                                                                                                          \
                                                                                                               \
                                                                                                               \
                                                                                                               \
                                                                                                               \
                                                                                                               \
    /*  Step 2.                                                                                                \
     *  Handle Right overhanging (only for odd signal lengths)                                                 \
     *                                                                                                         \
     * X() = [A B C D E F]x                                                                                    \
     * H() =           [b a]                                                                                   \
     *                  ^ ^                                                                                    \
     *                  | Extend the signal (x) by computing the values based on the extension mode            \
     *                  Then compute the filter part overlapping with the signal                               \
     */                                                                                                        \
    if(length % 2U){                                                                                           \
        int64_t sum_lo = 0;                                                                                    \
        int64_t sum_hi = 0;                                                                                    \
                                                                                                               \
        uint32_t filt_j = 0;                                                                                   \
                                                                                                               \
        /* Compute Left edge extension  */                                                                     \
        switch(mode){                                                                                          \
            case PLP_DWT_MODE_CONSTANT:                                                                        \
            case PLP_DWT_MODE_SYMMETRIC:                                                                       \
                /* dec_lo[0] * src[N-1] + dec_lo[1] * src[N-1] */                                              \
                sum_lo = 2 * COEF * pSrc[length - 1];                                                          \
                /* dec_hi[0] * src[N-1] + dec_hi[1] * src[N-1] == -dec_hi[1] * src[N-1] + dec_hi[1] * src[N-1]*/\
                sum_hi = 0;                                                                                    \
                break;                                                                                         \
            case PLP_DWT_MODE_REFLECT:                                                                         \
                sum_lo = COEF * (pSrc[length - 1] + pSrc[length - 2]);                                         \
                sum_hi = COEF * (pSrc[length - 1] - pSrc[length - 2]);                                         \
                break;                                                                                         \
            case PLP_DWT_MODE_ANTISYMMETRIC:                                                                   \
                sum_lo = COEF * (pSrc[length - 1] - pSrc[length - 1]);                                         \
                sum_hi = COEF * (pSrc[length - 1] + pSrc[length - 1]);                                         \
                break;                                                                                         \
            case PLP_DWT_MODE_ANTIREFLECT:                                                                     \
                sum_lo = COEF * (3*pSrc[length - 1] - pSrc[length - 2]);                                       \
                sum_hi = COEF * ( -pSrc[length - 1] + pSrc[length - 2]);                                       \
                break;                                                                                         \
            case PLP_DWT_MODE_PERIODIC:                                                                        \
            case PLP_DWT_MODE_ZERO:                                                                            \
            default:                                                                                           \
                sum_lo = COEF * pSrc[length - 1];                                                              \
                sum_hi = COEF * pSrc[length - 1];                                                              \
                break;                                                                                         \
        }                                                                                                      \
                                                                                                               \
        *pCurrentA = sum_lo >> SHIFT;                                                                          \
        *pCurrentD = sum_hi >> SHIFT;                                                                          \
    }                                                                                                          \
}                                                                                                              \






MAKE_HAAR(plp_dwt_haar_q32s_xpulpv2, HAAR_COEF, MAC_SHIFT)



MAKE_HAAR(plp_dwt_haar_u_q32s_xpulpv2, 1U, 0U)

Updated on 2023-03-01 at 16:16:33 +0000