This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] TDA4VH-Q1:C7x 编译器对单精度向量复数乘法 (VCMPYSP) 指令的固有支持

Guru**** 2418520 points
Other Parts Discussed in Thread: FFTLIB

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1541337/tda4vh-q1-c7x-compiler-intrinsic-support-for-single-precision-vector-complex-multiply-vcmpysp-instruction

器件型号:TDA4VH-Q1
主题中讨论的其他器件:TDA4VHFFTLIB

工具/软件:

我们需要 在 TDA4VH C7x (C7120) 应用中使用 VCMPYSP 指令、但 V5 编译器没有为此实现内在函数。 请参阅以下 c7x_direct.h 摘录、其中对此说明进行了注释。  

我们试图了解编译器不支持此内在函数的原因、并且此处编译器文档的“已知缺陷“部分没有提到这一点。  

问题:

  1. 为什么__vcmpysp_vvw 指令在 V5 编译器中不可用?
  2. 是否有方法可以启用此内在函数?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、  

    您是否尝试过使用此指令进行构建? 当我尝试相同方法时、我能够在不出现任何构建错误的情况下获得输出。 多个器件 TI v5.0.0 LTS。

    使用的代码:  

    #include<iostream>
    #include<c7x.h>
    
    int main(){
    
        cfloat8 cA, cB;
        float16 cC,cD;
        
        cA.s0.r = 1.0;  // x0
        cA.s0.i = 2.0;  // y0
    
        cA.s1.r = 3.0;  // x1
        cA.s1.i = 4.0;  // y1
    
        cA.s2.r = 5.0;  // x2
        cA.s2.i = 6.0;  // y2
    
        cA.s3.r = 7.0;  // x3
        cA.s3.i = 8.0;  // y3
    
        cA.s4.r = 9.0;  // x4
        cA.s4.i = 10.0; // y4
    
        cA.s5.r = 11.0; // x5
        cA.s5.i = 12.0; // y5
    
        cA.s6.r = 13.0; // x6
        cA.s6.i = 14.0; // y6
    
        cA.s7.r = 15.0; // x7
        cA.s7.i = 16.0; // y7
    
    
        cB.s0.r = 1.1;  // u0
        cB.s0.i = 2.1;  // v0
    
        cB.s1.r = 3.1;  // u1
        cB.s1.i = 4.1;  // v1
    
        cB.s2.r = 5.1;  // u2
        cB.s2.i = 6.1;  // v2
    
        cB.s3.r = 7.1;  // u3
        cB.s3.i = 8.1;  // v3
    
        cB.s4.r = 9.1;  // u4
        cB.s4.i = 10.1; // v4
    
        cB.s5.r = 11.1; // u5
        cB.s5.i = 12.1; // v5
    
        cB.s6.r = 13.1; // u6
        cB.s6.i = 14.1; // v6
    
        cB.s7.r = 15.1; // u7
        cB.s7.i = 16.1; // v7
    
    
        __vcmpysp_vvw(cA, cB, cC, cD);
    
    
        const uint8_t val=16;
        std::cout<<"Complex Out : "<<std::endl;;
        for(uint8_t i=0;i<val;++i){
            std::cout<<cC.s[i]<<" , "<<cD.s[i]<<std::endl;
        }
        return 0;
    }
    
    

    输出:  

    [C71X_0] Complex Out : 
    2.2 , 2.1
    -4.2 , 1.1
    12.4 , 12.3
    -16.4 , 9.3
    30.6 , 30.5
    -36.6 , 25.5
    56.8 , 56.7
    -64.8 , 49.7
    91 , 90.9
    -101 , 81.9
    133.2 , 133.1
    -145.2 , 122.1
    183.4 , 183.3
    -197.4 , 170.3
    241.6 , 241.5
    -257.6 , 226.5

    您能否也从您这边检查一下相同的内容。

    此致、
    Sivadeep

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    你好、Sivadeep。 是的,这是有效的! 非常感谢您提供完整的示例。 我们看到函数定义在 c7x_direct.h 中被注释掉、但我们认为它没有实现。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Sivadeep 在将 __vcmpysp_vvvw 和 _ vaddsp_vvv 与流引擎结合使用时、我们遇到了问题。 我们观察到 、在使用流引擎 (SE/SA) 时、向量乘法的实际分量呈符号翻转、如下面的输出捕获所示。  

    当我们不使用流引擎但尝试优化性能时、我们看到了正确的行为。 请参阅下面的代码片段、了解遇到此问题时所做的工作。 我们使用流引擎调用的方式是否有错误、或者这是否是此选项组合的错误?

       /******************************** */
       /* COMPLEX data type              */ 
       /******************************** */
       // Configure SE and SA for COMPLEX data
       __SE_TEMPLATE_v1 se_cparams = __gen_SE_TEMPLATE_v1();
       se_cparams.VECLEN = __SE_VECLEN_8ELEMS;
       se_cparams.ELETYPE = __SE_ELETYPE_64BIT;
       //se_cparams.ELETYPE = c7x::se_eletype<cfloat8>::value;
       se_cparams.DIMFMT = __SE_DIMFMT_1D;
       se_cparams.ICNT0 = 128;
       __SA_TEMPLATE_v1 sa_cparams = __gen_SA_TEMPLATE_v1();
       sa_cparams.VECLEN = c7x::sa_veclen<c7x::cfloat_vec>::value;
       sa_cparams.DIMFMT = __SA_DIMFMT_1D;
       sa_cparams.ICNT0 = 128;
    
       c7x::cfloat_vec *restrict p_cin70 = (c7x::cfloat_vec *) cin70;
       c7x::cfloat_vec *restrict p_cin71 = (c7x::cfloat_vec *) cin71;
       c7x::cfloat_vec *restrict p_cout2 = (c7x::cfloat_vec *) cout2;
    
       //c7x::float_vec r_temp[128], i_temp[128];
       float16 temp1, temp2; 
    
       __SE0_OPEN(p_cin70, se_cparams);  // complex data
       __SE1_OPEN(p_cin71, se_cparams);  // complex data
       __SA0_OPEN(sa_cparams); // complex
    
       // Pre-processing to get warm cycles when measuring cycle counts
       for (j=0; j<128; j++) {
          cout2[j] = cin70[j] * cin71[j] + (cfloat) (1000.0f, 1000.0f);
       }
    
       // cin70 * cin71   <== VCMPYSP + VADDSP
       start_time = __TSC;
       for (j=0; j<16; j++) {   
          __vcmpysp_vvw(__SE0ADV(cfloat8), __SE1ADV(cfloat8), temp1, temp2);     
          *__SA0ADV(cfloat8, p_cout2) = as_cfloat8(__vaddsp_vvv(temp1, temp2));
       }
       stop_time = __TSC;
       printf("\n[VCMPYSP + VADDSP] Number of clock cycles elapsed is %lu\n", stop_time - start_time);
    
       __SE0_CLOSE();
       __SE1_CLOSE();  
       __SA0_CLOSE();
    
       
       for (size_t c = 0; c < 128; c++) {
          printf("(%10g + %10g j) * (%10g + %10g j) = %10g + %10g j\n", cin70[c].r, cin70[c].i, cin71[c].r, cin71[c].i, cout2[c].r, cout2[c].i);
       }
    

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、

    您能否将元素类型指定为   _SE_ELETYPE_32BIT_CMPLX_SWAP。  这将解决该问题。

    测试代码:

     

    void complex_multiply_ci(float *pIn1,float *pIn2,float *pOut) {
          
        __SE_TEMPLATE_v1 se_cparams = __gen_SE_TEMPLATE_v1();
        se_cparams.VECLEN = __SE_VECLEN_8ELEMS;
        se_cparams.ELETYPE = __SE_ELETYPE_32BIT_CMPLX_SWAP;
        se_cparams.DIMFMT = __SE_DIMFMT_1D;
        se_cparams.ICNT0 = 128;
    
        __SA_TEMPLATE_v1 sa_cparams = __gen_SA_TEMPLATE_v1();
        sa_cparams.VECLEN = c7x::sa_veclen<c7x::cfloat_vec>::value;
        sa_cparams.DIMFMT = __SA_DIMFMT_1D;
        sa_cparams.ICNT0 = 128;
    
    
        cfloat8* pinlocal1 = (cfloat8*)pIn1;
        cfloat8* pinlocal2 = (cfloat8*)pIn2;
        cfloat8* pOutlocal = (cfloat8*)pOut;
    
    
        __SE0_OPEN(pinlocal1, se_cparams); 
        __SE1_OPEN(pinlocal2, se_cparams);
        __SA0_OPEN(sa_cparams);
    
    
    #ifdef DEBUG
        cfloat8 vX0,vX1,cProduct;
        std::cout<<" SE Input : " <<std::endl;
    #endif
    
        for (unsigned short j=0; j<16; j++) {   
    #ifdef DEBUG
            vX0=__SE0ADV(cfloat8);
            vX1=__SE1ADV(cfloat8);
            std::cout<<"Iteration "<< j+1 << " : ";
            vX0.print(); 
            cProduct = __complex_multiply(vX0,vX1);
            cProduct.print();
            *__SA0ADV(cfloat8, pOutlocal)=cProduct;
    #else
            *__SA0ADV(cfloat8, pOutlocal) = __complex_multiply(__SE0ADV(cfloat8),__SE1ADV(cfloat8));
            
    #endif
    
       }
        __SE0_CLOSE();
        __SE1_CLOSE(); 
        __SA0_CLOSE();
    
    }
    
    int main(){
    
        float pIn1[256];
        float pIn2[256];
        float pOut[256];
        
        for (unsigned short i = 0; i < 128; ++i) {
            
            pIn1[2 * i ] = i + 1; //Real       
            pIn1[2 * i +1] = (i + 1);  //Imaginary
    
            pIn2[2 * i ] = i + 1; //Real       
            pIn2[2 * i+1] = (i + 1);  //Imaginary
        }
    
        complex_multiply_ci(pIn1,pIn2,pOut);
    
    #ifdef DEBUGP
        std::cout<<"Product : "<<std::endl;
        for (unsigned short i = 0; i < 128; ++i) {
            std::cout<< pOut[2 * i  ] <<"+i"<< pOut[2 * i +1]<< " "<<std::endl;
        }
    #endif
    }
    

    我也在使用  __复数_乘法 这是用于乘法的伪指令。

    此致、
    Sivadeep

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢您发送编修。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Sivadeep、我构建并运行了此代码。 再次感谢。 我现在 在 C7x.h 中看到了__复数_乘法伪指令、该指令非常有用、但您是否知道是否有记录在案的信息? 我在 编译器用户指南中没有看到这方面的描述。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    但您是否知道这在任何地方都有记录? [/报价]

    不可以、我找不到任何与此相关的文档。 但是、FFTLIB 源中提供了一些参考代码。

    如果所有问题都得到了解答、我们是否可以继续并关闭此主题?

    此致、
    Sivadeep

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    好的、谢谢 Sivadeep。 这是非常有用的。 Ruben