| #include "edge-impulse-sdk/dsp/config.hpp" |
| #if EIDSP_LOAD_CMSIS_DSP_SOURCES |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| #include "edge-impulse-sdk/CMSIS/DSP/Include/dsp/matrix_functions_f16.h" |
|
|
| #if defined(ARM_FLOAT16_SUPPORTED) |
|
|
|
|
| |
| |
| |
|
|
|
|
| |
| |
| |
| |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| #if defined(ARM_MATH_MVE_FLOAT16) && !defined(ARM_MATH_AUTOVECTORIZE) |
|
|
| __STATIC_FORCEINLINE arm_status arm_mat_mult_f16_2x2_mve( |
| const arm_matrix_instance_f16 *pSrcA, |
| const arm_matrix_instance_f16 *pSrcB, |
| arm_matrix_instance_f16 *pDst) |
| { |
| static const uint16_t offsetA[8] = { 0, 0, 2, 2, 0, 0, 2, 2 }; |
| |
| static const uint16_t offsetB[8] = { 0, 1, 0, 1, 0, 1, 0, 1 }; |
| uint16x8_t vecOffsA, vecOffsB; |
| f16x8_t vecInA, vecInB, vecDst; |
| float16_t *pOut = pDst->pData; |
|
|
| |
| |
| |
| vecOffsA = vldrhq_u16((uint16_t const *) offsetA); |
| vecOffsB = vldrhq_u16((uint16_t const *) offsetB); |
| |
| |
| |
| vecInA = vldrhq_gather_shifted_offset((float16_t const *) pSrcA->pData, vecOffsA); |
| |
| |
| |
| vecInB = vldrhq_gather_shifted_offset((float16_t const *) pSrcB->pData, vecOffsB); |
| |
| |
| |
| |
| |
| |
| vecDst = vmulq(vecInA, vecInB); |
| |
| |
| |
| vecOffsA = vaddq_n_u16(vecOffsA, (uint16_t) 1); |
| |
| |
| |
| vecInA = vldrhq_gather_shifted_offset((float16_t const *) pSrcA->pData, vecOffsA); |
| |
| |
| |
| vecOffsB = vaddq_n_u16(vecOffsB, (uint16_t) 2); |
| |
| |
| |
| vecInB = vldrhq_gather_shifted_offset((float16_t const *) pSrcB->pData, vecOffsB); |
| |
| |
| |
| |
| |
| |
| vecDst = vfmaq(vecDst, vecInA, vecInB); |
|
|
| mve_pred16_t p0 = vctp16q(2*2); |
| |
| |
| |
| |
| vstrhq_p(pOut, vecDst, p0); |
|
|
| return (ARM_MATH_SUCCESS); |
| } |
|
|
|
|
|
|
|
|
| __STATIC_FORCEINLINE arm_status arm_mat_mult_f16_3x3_mve( |
| const arm_matrix_instance_f16 *pSrcA, |
| const arm_matrix_instance_f16 *pSrcB, |
| arm_matrix_instance_f16 *pDst) |
| { |
| static const uint16_t offsetA[8] = { 0, 0, 0, 3, 3, 3, 6, 6 }; |
| |
| static const uint16_t offsetB[8] = { 0, 1, 2, 0, 1, 2, 0, 1 }; |
| uint16x8_t vecOffsA, vecOffsB; |
| f16x8_t vecInA, vecInB, vecDst; |
| float16_t *pOut = pDst->pData; |
|
|
| |
| |
| |
| vecOffsA = vldrhq_u16((uint16_t const *) offsetA); |
| vecOffsB = vldrhq_u16((uint16_t const *) offsetB); |
|
|
| |
| |
| |
| vecInA = vldrhq_gather_shifted_offset((float16_t const *) pSrcA->pData, vecOffsA); |
| |
| |
| |
| vecInB = vldrhq_gather_shifted_offset((float16_t const *) pSrcB->pData, vecOffsB); |
| |
| |
| |
| |
| |
| vecDst = vmulq(vecInA, vecInB); |
|
|
| |
| |
| |
| vecOffsA = vaddq_n_u16(vecOffsA, (uint16_t) 1); |
| |
| |
| |
| vecInA = vldrhq_gather_shifted_offset((float16_t const *) pSrcA->pData, vecOffsA); |
| |
| |
| |
| vecOffsB = vaddq_n_u16(vecOffsB, (uint16_t) 3); |
| |
| |
| |
| vecInB = vldrhq_gather_shifted_offset((float16_t const *) pSrcB->pData, vecOffsB); |
| |
| |
| |
| |
| |
| vecDst = vfmaq(vecDst, vecInA, vecInB); |
| |
| |
| |
| vecOffsA = vaddq_n_u16(vecOffsA, (uint16_t) 1); |
| |
| |
| |
| vecInA = vldrhq_gather_shifted_offset((float16_t const *) pSrcA->pData, vecOffsA); |
| |
| |
| |
| vecOffsB = vaddq_n_u16(vecOffsB, (uint16_t) 3); |
| |
| |
| |
| vecInB = vldrhq_gather_shifted_offset((float16_t const *) pSrcB->pData, vecOffsB); |
| |
| |
| |
| |
| |
| vecDst = vfmaq(vecDst, vecInA, vecInB); |
|
|
| |
| |
| |
| vst1q(pOut, vecDst); pOut += 8; |
|
|
| |
| |
| |
| _Float16 * pA = (_Float16 *)pSrcA->pData; |
| _Float16 * pB = (_Float16 *)pSrcB->pData; |
| *pOut = pA[2*3] * pB[2] + pA[2*3+1] * pB[3+2] + pA[2*3+2] * pB[2*3+2]; |
|
|
| return (ARM_MATH_SUCCESS); |
| } |
|
|
|
|
|
|
|
|
|
|
| __STATIC_FORCEINLINE arm_status arm_mat_mult_f16_4x4_mve( |
| const arm_matrix_instance_f16 *pSrcA, |
| const arm_matrix_instance_f16 *pSrcB, |
| arm_matrix_instance_f16 *pDst) |
| { |
| |
| static const uint16_t offsetA[8] = { 0, 0, 0, 0, 4, 4, 4, 4 }; |
| |
| static const uint16_t offsetB[8] = { 0, 1, 2, 3, 0, 1, 2, 3 }; |
| uint16x8_t vecOffsA, vecOffsB; |
| f16x8_t vecInA, vecInB, vecDst0, vecDst1; |
| float16_t *pOut = pDst->pData; |
|
|
| |
| |
| |
| vecOffsA = vldrhq_u16((uint16_t const *) offsetA); |
| vecOffsB = vldrhq_u16((uint16_t const *) offsetB); |
|
|
| |
| |
| |
| vecInA = vldrhq_gather_shifted_offset((float16_t const *) pSrcA->pData, vecOffsA); |
| |
| |
| |
| vecInB = vldrhq_gather_shifted_offset((float16_t const *) pSrcB->pData, vecOffsB); |
| |
| |
| |
| |
| vecDst0 = vmulq(vecInA, vecInB); |
| |
| |
| |
| vecOffsA = vaddq_n_u16(vecOffsA, (uint16_t) 8); |
| |
| |
| |
| vecInA = vldrhq_gather_shifted_offset((float16_t const *) pSrcA->pData, vecOffsA); |
| |
| |
| |
| |
| vecDst1 = vmulq(vecInA, vecInB); |
| |
| |
| |
| vecOffsA = vsubq(vecOffsA, (uint16_t) 7); |
| |
| |
| |
| vecInA = vldrhq_gather_shifted_offset((float16_t const *) pSrcA->pData, vecOffsA); |
| |
| |
| |
| vecOffsB = vaddq_n_u16(vecOffsB, (uint16_t) 4); |
| |
| |
| |
| vecInB = vldrhq_gather_shifted_offset((float16_t const *) pSrcB->pData, vecOffsB); |
| |
| |
| |
| |
| vecDst0 = vfmaq(vecDst0, vecInA, vecInB); |
| |
| |
| |
| vecOffsA = vaddq_n_u16(vecOffsA, (uint16_t) 8); |
| |
| |
| |
| vecInA = vldrhq_gather_shifted_offset((float16_t const *) pSrcA->pData, vecOffsA); |
| |
| |
| |
| |
| vecDst1 = vfmaq(vecDst1, vecInA, vecInB); |
|
|
| |
| |
| |
| vecOffsA = vsubq(vecOffsA, (uint16_t) 7); |
| |
| |
| |
| vecInA = vldrhq_gather_shifted_offset((float16_t const *) pSrcA->pData, vecOffsA); |
| |
| |
| |
| vecOffsB = vaddq_n_u16(vecOffsB, (uint16_t) 4); |
| |
| |
| |
| vecInB = vldrhq_gather_shifted_offset((float16_t const *) pSrcB->pData, vecOffsB); |
| |
| |
| |
| |
| vecDst0 = vfmaq(vecDst0, vecInA, vecInB); |
| |
| |
| |
| vecOffsA = vaddq_n_u16(vecOffsA, (uint16_t) 8); |
|
|
| |
| |
| |
| vecInA = vldrhq_gather_shifted_offset((float16_t const *) pSrcA->pData, vecOffsA); |
| |
| |
| |
| |
| vecDst1 = vfmaq(vecDst1, vecInA, vecInB); |
|
|
| |
| |
| |
| vecOffsA = vsubq(vecOffsA, (uint16_t) 7); |
| |
| |
| |
| vecInA = vldrhq_gather_shifted_offset((float16_t const *) pSrcA->pData, vecOffsA); |
| |
| |
| |
| vecOffsB = vaddq_n_u16(vecOffsB, (uint16_t) 4); |
| |
| |
| |
| vecInB = vldrhq_gather_shifted_offset((float16_t const *) pSrcB->pData, vecOffsB); |
| |
| |
| |
| |
| vecDst0 = vfmaq(vecDst0, vecInA, vecInB); |
| |
| |
| |
| vecOffsA = vaddq_n_u16(vecOffsA, (uint16_t) 8); |
| |
| |
| |
| vecInA = vldrhq_gather_shifted_offset((float16_t const *) pSrcA->pData, vecOffsA); |
| |
| |
| |
| |
| vecDst1 = vfmaq(vecDst1, vecInA, vecInB); |
|
|
| |
| |
| |
| vst1q(pOut, vecDst0); pOut += 8; |
| vst1q(pOut, vecDst1); |
|
|
| return (ARM_MATH_SUCCESS); |
| } |
|
|
|
|
| arm_status arm_mat_mult_f16( |
| const arm_matrix_instance_f16 * pSrcA, |
| const arm_matrix_instance_f16 * pSrcB, |
| arm_matrix_instance_f16 * pDst) |
| { |
| float16_t *pInB = pSrcB->pData; |
| float16_t *pInA = pSrcA->pData; |
| float16_t *pOut = pDst->pData; |
| int numRowsA = pSrcA->numRows; |
| int numColsB = pSrcB->numCols; |
| int numColsA = pSrcA->numCols; |
| uint32_t blkCnt; |
| int i; |
|
|
|
|
| #ifdef ARM_MATH_MATRIX_CHECK |
|
|
| |
| if ((pSrcA->numCols != pSrcB->numRows) || |
| (pSrcA->numRows != pDst->numRows) || |
| (pSrcB->numCols != pDst->numCols) ) |
| { |
| |
| return(ARM_MATH_SIZE_MISMATCH); |
| } |
| else |
|
|
| #endif |
| { |
| |
| if(numRowsA == numColsB && numColsB == numColsA) { |
| if(numRowsA == 2) |
| return arm_mat_mult_f16_2x2_mve(pSrcA, pSrcB, pDst); |
| else if(numRowsA == 3) |
| return arm_mat_mult_f16_3x3_mve(pSrcA, pSrcB, pDst); |
| else if(numRowsA == 4) |
| return arm_mat_mult_f16_4x4_mve(pSrcA, pSrcB, pDst); |
| } |
|
|
| |
| i = numRowsA / 4; |
| while(i > 0) |
| { |
| float16_t *pInA0, *pInA1, *pInA2, *pInA3; |
| float16_t *pInB0; |
| float16_t *pOut0, *pOut1, *pOut2, *pOut3; |
| f16x8_t vecMac0, vecMac1, vecMac2, vecMac3; |
| f16x8_t vecInB; |
|
|
| |
| pOut0 = pOut; |
| pOut1 = pOut0 + numColsB; |
| pOut2 = pOut1 + numColsB; |
| pOut3 = pOut2 + numColsB; |
| pInB0 = pInB; |
|
|
| int k = numColsB >> 3; |
| while(k > 0) |
| { |
| |
| pInA0 = pInA; |
| pInA1 = pInA0 + numColsA; |
| pInA2 = pInA1 + numColsA; |
| pInA3 = pInA2 + numColsA; |
|
|
| vecMac0 = vdupq_n_f16(0.0f16); |
| vecMac1 = vdupq_n_f16(0.0f16); |
| vecMac2 = vdupq_n_f16(0.0f16); |
| vecMac3 = vdupq_n_f16(0.0f16); |
|
|
| blkCnt = numColsA; |
|
|
| while (blkCnt > 0U) |
| { |
| |
| |
| |
| vecInB = *(f16x8_t *)pInB0; |
|
|
| vecMac0 = vfmaq(vecMac0, vecInB, *pInA0++); |
| vecMac1 = vfmaq(vecMac1, vecInB, *pInA1++); |
| vecMac2 = vfmaq(vecMac2, vecInB, *pInA2++); |
| vecMac3 = vfmaq(vecMac3, vecInB, *pInA3++); |
|
|
| pInB0 = pInB0 + numColsB; |
| |
| |
| |
| blkCnt--; |
| } |
|
|
| |
| vst1q(pOut0, vecMac0); pOut0 += 8; |
| vst1q(pOut1, vecMac1); pOut1 += 8; |
| vst1q(pOut2, vecMac2); pOut2 += 8; |
| vst1q(pOut3, vecMac3); pOut3 += 8; |
| |
| |
| |
| pInB0 -= (numColsB * numColsA) - 8; |
| k--; |
| } |
|
|
| int colBLeft = numColsB & 7; |
| if (colBLeft) |
| { |
| pInA0 = pInA; |
| pInA1 = pInA0 + numColsA; |
| pInA2 = pInA1 + numColsA; |
| pInA3 = pInA2 + numColsA; |
| mve_pred16_t p0 = vctp16q(colBLeft); |
|
|
| vecMac0 = vdupq_n_f16(0.0f16); |
| vecMac1 = vdupq_n_f16(0.0f16); |
| vecMac2 = vdupq_n_f16(0.0f16); |
| vecMac3 = vdupq_n_f16(0.0f16); |
|
|
| blkCnt = numColsA; |
|
|
| while (blkCnt > 0U) |
| { |
| |
| |
| |
| vecInB = vldrhq_z_f16(pInB0, p0); |
|
|
| vecMac0 = vfmaq(vecMac0, vecInB, *pInA0++); |
| vecMac1 = vfmaq(vecMac1, vecInB, *pInA1++); |
| vecMac2 = vfmaq(vecMac2, vecInB, *pInA2++); |
| vecMac3 = vfmaq(vecMac3, vecInB, *pInA3++); |
|
|
| pInB0 = pInB0 + numColsB; |
| |
| |
| |
| blkCnt--; |
| } |
|
|
| |
| vstrhq_p_f16(pOut0, vecMac0, p0); |
| vstrhq_p_f16(pOut1, vecMac1, p0); |
| vstrhq_p_f16(pOut2, vecMac2, p0); |
| vstrhq_p_f16(pOut3, vecMac3, p0); |
| } |
|
|
| pInA += 4 * numColsA; |
| pOut += 4 * numColsB; |
| i--; |
| } |
|
|
| |
| |
| |
| |
| if (numRowsA & 3) |
| { |
| i = numRowsA & 3; |
| do |
| { |
| float16_t *pInA0; |
| float16_t *pInB0; |
| float16_t *pOut0; |
| f16x8_t vecInB; |
| f16x8_t vecMac0; |
|
|
| pOut0 = pOut; |
| pInB0 = pInB; |
|
|
| int k = numColsB >> 3; |
| while(k > 0) |
| { |
| pInA0 = pInA; |
|
|
| vecMac0 = vdupq_n_f16(0.0f16); |
| blkCnt = numColsA; |
|
|
| while (blkCnt > 0U) |
| { |
| |
| |
| |
| vecInB = *(f16x8_t *)pInB0; |
|
|
| vecMac0 = vfmaq(vecMac0, vecInB, *pInA0++); |
|
|
| pInB0 = pInB0 + numColsB; |
| |
| |
| |
| blkCnt--; |
| } |
| |
| vst1q(pOut0, vecMac0); pOut0 += 8; |
| |
| |
| |
| pInB0 -= (numColsB * numColsA) - 8; |
| k--; |
| } |
|
|
| int colBLeft = numColsB & 7; |
| if (colBLeft) |
| { |
| pInA0 = pInA; |
| mve_pred16_t p0 = vctp16q(colBLeft); |
|
|
| vecMac0 = vdupq_n_f16(0.0f16); |
| blkCnt = numColsA; |
|
|
| while (blkCnt > 0U) |
| { |
| |
| |
| |
| vecInB = vldrhq_z_f16(pInB0, p0); |
|
|
| vecMac0 = vfmaq(vecMac0, vecInB, *pInA0++); |
|
|
| pInB0 = pInB0 + numColsB; |
| |
| |
| |
| blkCnt--; |
| } |
| |
| vstrhq_p_f16(pOut0, vecMac0, p0); |
| } |
|
|
| pInA += 1 * numColsA; |
| pOut += 1 * numColsB; |
| } |
| while (--i); |
| } |
| |
| |
| |
| return (ARM_MATH_SUCCESS); |
| } |
| } |
| #else |
|
|
|
|
| arm_status arm_mat_mult_f16( |
| const arm_matrix_instance_f16 * pSrcA, |
| const arm_matrix_instance_f16 * pSrcB, |
| arm_matrix_instance_f16 * pDst) |
| { |
| float16_t *pIn1 = pSrcA->pData; |
| float16_t *pIn2 = pSrcB->pData; |
| float16_t *pInA = pSrcA->pData; |
| float16_t *pInB = pSrcB->pData; |
| float16_t *pOut = pDst->pData; |
| float16_t *px; |
| _Float16 sum; |
| uint16_t numRowsA = pSrcA->numRows; |
| uint16_t numColsB = pSrcB->numCols; |
| uint16_t numColsA = pSrcA->numCols; |
| uint32_t col, i = 0U, row = numRowsA, colCnt; |
| arm_status status; |
|
|
| #ifdef ARM_MATH_MATRIX_CHECK |
|
|
| |
| if ((pSrcA->numCols != pSrcB->numRows) || |
| (pSrcA->numRows != pDst->numRows) || |
| (pSrcB->numCols != pDst->numCols) ) |
| { |
| |
| status = ARM_MATH_SIZE_MISMATCH; |
| } |
| else |
|
|
| #endif |
|
|
| { |
| |
| |
| do |
| { |
| |
| px = pOut + i; |
|
|
| |
| col = numColsB; |
|
|
| |
| pIn2 = pSrcB->pData; |
|
|
| |
| do |
| { |
| |
| sum = 0.0f16; |
|
|
| |
| pIn1 = pInA; |
|
|
| #if defined (ARM_MATH_LOOPUNROLL) |
|
|
| |
| colCnt = numColsA >> 2U; |
|
|
| |
| while (colCnt > 0U) |
| { |
| |
|
|
| |
| sum += (_Float16)*pIn1++ * (_Float16)*pIn2; |
| pIn2 += numColsB; |
|
|
| sum += (_Float16)*pIn1++ * (_Float16)*pIn2; |
| pIn2 += numColsB; |
|
|
| sum += (_Float16)*pIn1++ * (_Float16)*pIn2; |
| pIn2 += numColsB; |
|
|
| sum += (_Float16)*pIn1++ * (_Float16)*pIn2; |
| pIn2 += numColsB; |
|
|
| |
| colCnt--; |
| } |
|
|
| |
| colCnt = numColsA % 0x4U; |
|
|
| #else |
|
|
| |
| colCnt = numColsA; |
|
|
| #endif |
|
|
| while (colCnt > 0U) |
| { |
| |
|
|
| |
| sum += (_Float16)*pIn1++ * (_Float16)*pIn2; |
| pIn2 += numColsB; |
|
|
| |
| colCnt--; |
| } |
|
|
| |
| *px++ = sum; |
|
|
| |
| col--; |
|
|
| |
| pIn2 = pInB + (numColsB - col); |
|
|
| } while (col > 0U); |
|
|
| |
| i = i + numColsB; |
| pInA = pInA + numColsA; |
|
|
| |
| row--; |
|
|
| } while (row > 0U); |
|
|
| |
| status = ARM_MATH_SUCCESS; |
| } |
|
|
| |
| return (status); |
| } |
|
|
| #endif |
|
|
| |
| |
| |
|
|
| #endif |
|
|
|
|
| #endif |
|
|