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.

Doubt regarding C5515 MACM instruction

Hi all,

I am a newbie in DSP. We have grabbed the ADS1298-C5515 EVM kit and successfully built the ECG MDK source code. 

Now we are trying to port the ECG algorithm to C64x DSP. For that, I am trying to convert the two assembly functions in 

ECG MDK to C source code. At first, I am trying to test the equivalent C code in C5515 EVM itself. But when I convert the assembly functions

to C code, it is not working properly in C5515 EVM. Below are the functions for your reference:

ECG_FilterProcess:

             AC0 = 0;

   

            repeat (#351)

            AC0 = AC0 + ((*AR0-)* (*AR1+));

        

            (*AR2+) = HI(AC0);

            (*AR2) = AC0;

     

            return

_ECG_AntiAlising_FilterProcess:

 

            AC0 = 0;

           

            repeat (#51)

            AC0 = AC0 + ((*AR0-)* (*AR1+));

 

            (*AR2+) = HI(AC0);

            (*AR2) = AC0;

           

            return

           The Test routine takes three int16 pointers. The first two are inputs and the third one is output.

          One of the operands for multiplication is Q15 format filter coefficients. 

          I understood that there is some problem when I port the multiplication instruction to C source code.

          On viewing the disassembly view, I understood that equivalent instruction for multiplication is MACM. 

         I have also verified the status register settings of SATD, M40, SMUL, FRCT bits in my source code. All these

       are found to be in their default values in the lpva2000.inc file.

         I have debugged the C code and understood that the problem is with the multiplication instruction in my C code.

         I have also referred the following posts in TI forums and made several trials.

        http://e2e.ti.com/support/dsp/c5000/f/109/t/103964.aspx 

        I have tried with the SMULT macro mentioned in the above forum. But still I didn't get the expected results.

        http://e2e.ti.com/support/dsp/tms320c6000_high_performance_dsps/f/115/t/187702.aspx?pi64368=1

       http://e2e.ti.com/support/dsp/c5000/f/109/t/101101.aspx

         Still my multiplication output fails.

       Could you please share your thoughts on this issue?

      Also please tell if it is okay for these asm porting to C while porting to C64x DSP.

Thanks,

Honey S





  • Hi all,

    Below is the equivalent C code I have written for your reference,

    #define SMULT( a, b, n ) ( (int)( ( (long)(int) a * (long)(int) b ) >> n ) )

    void ECG_AntiAlising_FilterProcess (Int16* in, Int16* inp, Int16* out)

    {

    int32 acc = 0;

    int32 index = 0;

    int32 temp = (int32)in;

    temp = temp & 0x0000FFFF;

    in = (int16*) temp;

    for (index =0; index < 51; index ++ )

    {

       acc = acc + SMULT(*in, *inp, 15);

       in --;

       inp ++;

    }

    *out = (acc & 0xFFFF0000) >> 16;

    out++;

    *out = (acc & 0x0000FFFF);

    return;

    }

    I have verified that  the address translation for in pointer is necessary in C after debugging the same with asm code.

    Also verified that problem is with multiplication operation. Verified the multiplication operands. Values of these operands

    are found to be correct. But the multiplication fails.

    Please share your thoughts on this issue.

    Thanks,

    Honey S

     

     

  • I would guess the assembly version is setting SATD and FRACT, most likely at boot time.  Is this the case?

  • At quick glance, it looks like your SMULT( ) macro is not what you would want to use within a Multiply accumulate loop.  The SMULT seems to be set up to return a Q15 in 16 bits.  You want to maintain a 32 bit accumulator, which will be a Q31 in 32 bits, within the for loop and then take the upper 16 bits of your accumulator to store your result.

    Mainly, given

    Int32 q31_product;

    Int16 q15_a,q15_b;

    q31_product = ( (long) q15_a * q15_b)<<1;  // Q15 * Q15 = Q30 in 32 bits, left shift 1 to create Q31 in 32 bits.

    so in your for loop:

    acc = acc + ( (long) (*inp)  * (*in))<<1;

    The C compiler assumes FRCT is 0, so we need the left shift of 1.  The compiler also assumes SATD is 0 and SMUL is 0, so we have to be careful about saturation.

    The best approach is to use the C compiler intrinsics, which mimic assembly language instructions and set FRCT, SATD etc. to get proper operation. See "Using Intrinsics to Access Assembly Language Statements" in the C55x Optimizing C/C++ Compiler Users Guide (SPRU281).    Using these intrinsics, the multiply accumulate operation of the for loop would look like:

    _smac(acc, *inp, *inp);   

    I believe similar intrinsics are available for the C6000.

    -Shawn