**Contributors:**

Ruqiu, Cao

Yuwen, Liu

## Introduction

Intel® Integrated Performance Primitives (Intel® IPP) provides many APIs for signal processing, and all of them are optimized with several levels for different algorithms or different platforms. FlexRAN 5G BBU (with IPP APIs integrated) runs on Intel® CPU is broadly adopted by a bunch of wireless equipment manufacturers. In this article, the benefits of using Intel® IPP APIs in 5G will be explained. And two illustrations have also been given to understand how to use Intel® IPP library in signal processing for 5G Base Station.

Intel® IPP library is available as part of the Intel® oneAPI Base Toolkit.

A simplified list of Intel® IPP functions for 5G with their description is given in the table below. There are many IPP APIs can be used for 5G system. Refer to the developer reference guide for more details and examples.

Intel® IPP Functions for 5G | Description |
---|---|

Copy |
Copies the contents of one vector to another. It also works for bit copy. For example, ippsCopyLE_1u: can be used for 5G PDSCH/PUSCH rate match block ippsCopyLE_8u: can be used for 5G PDSCH/PUSCH rate de-match block |

CRCs | Computes the CRC checksum for the source data buffer. IPP supports all the CRCs defined in 5G specification, for example calculating CRC of TB, CB in data channel as well as control channels |

Fourier Transform Functions | The functions perform the fast Fourier transform (FFT) and the discrete Fourier transform (DFT) of signal samples. They can speedup 5G PUSCH/PUCCH receiver for transform precoding, and can be used for FFT/DFT based channel estimation. |

MaxIndx | Returns the maximum value of a vector and the index of the maximum element. It can be used for 5G PRACH peak detection. |

SortIndexDescend | Rearranges elements of the vector and their indexes, which can be used for 5G beamforming weight matrix generation. |

## Benefits of using Intel® IPP APIs for 5G

There are three major advantages of using Intel® IPP APIs for 5G:

- Intel® IPP provide developers with ready-to-use, processor- optimized functions in signal processing for 5G system.
- Maintenance, maintain the code implementation.
- Performance, function should run as fast as possible on different platform without spending extra effort by calling same IPP APIs.

## Examples

**Example 1: Intel® IPP APIs for 5G CRCs**

**ippsCRC16_8u**and**ippsCRC16_1u**. This function computes the checksum with the following polynomial:

X16 + X12 + X5 + X + 1

If the user wants to specify the offsets from the source and destination data buffers, then the srcBitOffset and dstBitOffset parameters work for API ippsCRC16_1u.**ippsCRC24a_8u**,**ippsCRC24b_8u**,**ippsCRC24c_8u**,**ippsCRC24a_1u**,**ippsCRC24b_1u**and**ippsCRC24c_1u**.These functions compute the checksum with the following polynomials:- ippsCRC24a: X24 + X23 + X18 + X17 + X14 + X11 + X10 + X7 + X6 + X5 + X4 + X3 + X + 1
- ippsCRC24b: X24 + X23 + X6 + X5 + X + 1
- ippsCRC24c: X24 + X23 + X21 + X20 + X17 + X15 + X13 + X12 + X8 + X4 + X2 + X + 1

**ippsCRC_8u**(pSrc, len, poly, optPoly[128], init, pCRC). This function computes the CRC value with the polynomial poly and the initial value for the input vector with the length. The default optPoly value is NULL. It only supports 8, 16, 24 or 32 bits-length polynomials. For 5G CRC6 and CRC11, user can update 6-bit or 11-bit polynomials to 8bits or 16bit by left shift 2bits or 5bits respectively.

The following sample code demonstrates how to call ippsCRC_8u to compute CRC6 with the polynomial poly is 0x61.

```
int main()
{
Ipp8u* src = "123456789";
IppStatus status;
Ipp32u CRC;
/* CRC6 polynomial poly */
Ipp64u poly = 0x61;
Ipp32u init = 0x0;
Ipp8u optPoly[128];
/* for having better performance, the 6-bit polynomial need to update to 8x bits, Shift 2 bits
left here, CRC6 -> CRC8 */
poly <<= 2;
/* Generates optimization table for ippsCRC_8u */
status = ippsGenCRCOptPoly_8u(poly, optPoly);
/* Computes CRC8 for a given data vector */
status = ippsCRC_8u(src, 9, poly, optPoly, init, &CRC);
printf("status = %d, '%s'\n", status, ippGetStatusString(status));
/* Shift 2 bits right, to make CRC8 to CRC6 as expect*/
printf("crc6=%x\n", CRC >> 2);
return 0;
}
```

**Example 2: Intel® IPP APIs for FFT/DFT for 5G**

To use the IPP FFT or DFT functions, initialize the specification structure which contains such data as tables of twiddle factors. The initialization functions create the specifications for both forward and inverse transforms. The number of prior calculations is thus reduced, and the overall performance is increased.

There are 3 IppHintAlgorithm (ippAlgHintNone, ippAlgHintFast and ippAlgHintAccurate) enumeration defines the type of code to be used in the FFT or DFT operations: faster but less accurate, or vice-versa, more accurate but slower. The hint argument needs to be passed into the initialization functions, which suggests the use of algorithm to be faster or more accurate. And there is a flag argument, which specifies the result normalization method.

To initialize the FFT or DFT specification structure, use the ippsFFTInit_R or ippsDFTInit_R and ippsFFTInit_C or ippsDFTInit_C functions. Before using these functions, you need to compute the size of the specification structure using ippsFFTGetSize_R or ippsDFTGetSize_R for real data and ippsFFTGetSize_C or ippsDFTGetSize_C for complex data respectively.

The following sample demonstrates how to perform length 8 complex FFT with order equals 3. In general, there are 3 steps.

Step 1: Compute the sizes of the specification structure

Step 2: Initialize the specification structure

Step 3: Perform the FFT function with specific length and data type

```
int main(void)
{
int i;
IppStatus status = ippStsNoErr;
/* Pointers to source/destination */
Ipp32f pSrc[8], pDst[10];
/* Pointer to FFT pSpec structure */
IppsFFTSpec_C_32f* pSpec = NULL;
/* Pointer to the work buffers */
Ipp8u *pMemInit = NULL, *pBuffer = NULL, *pSpecMem = NULL;
/* size of FFT pSpec structure, Init and work buffers */
int sizeSpec = 0, sizeInit = 0, sizeBuf = 0;
/* Initialize input */
for (i = 0; i< 8 ; ++i)
{
pSrc[i] = (float)cos(IPP_2PI * i * 16.0/64);
}
/* step 1: Compute the sizes of the specification structure for length 8 complex FFT */
status = ippsFFTGetSize_C_32f(3, IPP_FFT_DIV_INV_BY_N, ippAlgHintNone, &sizeSpec, &sizeInit, &sizeBuf);
/* memory allocation with the sizes of the specification structure */
pSpecMem = (Ipp8u*) ippMalloc( sizeSpec );
pBuffer = (Ipp8u*) ippMalloc( sizeBuf );
pMemInit = (Ipp8u*) ippMalloc( sizeInit );
/* step 2: Initialize the specification structure which contains such data as tables of twiddle
factors */
status = ippsFFTInit_C_32f(&pSpec, 3, IPP_FFT_DIV_INV_BY_N, ippAlgHintNone, pSpecMem, pMemInit);
/* step 3: Performs the length 8 complex FFT */
status = ippsFFTFwd_CToCCS_32f(pSrc, pDst, pSpec, NULL);
/* Free memory */
ippFree( pMemInit );
ippFree( pSpec );
ippFree( pBuffer );
printf("Exit status %d (%s)\n", (int)status, ippGetStatusString(status));
return (int)status;
}
```