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.

MSP430FR5992: IQmath saturation problem in rsmpy (not rmpy) for small values when one is negative and result should be rounded to zero

Part Number: MSP430FR5992

Dear all,

i have a problem using the fixed point math. Maybe its a problem in understanding but i think its more a problem in the implementation - hopefully no hardware problem.

I want to multiply two numbers in the _iq15 format and have stumbled over the following obvious error:

 _IQ15(-0.0015) = a = -49
_IQ15(0.0015) = b = 49

so far so good... but multiplying both values result in:
_IQ15rsmpy(a,b) = c = -2,147484E+09
_IQ15toF(c) = -65536.0 ... but it should be 0.00000225 which should be rounded to 0

 If I use _IQ15rmpy(a,b), than it returns the right value “0”.

*edit* As the edited title says i narrowed it down: it seems to only happen if only one values is negative and if the result should be rounded to 0 all other cases I tried it works as expected.

 

What am I overlooking or understanding wrong? I would really appreciate if someone could point me in the right direction.

 

Best wishes

Tobias

  • Hi Tobias,

    I assume you are using 32bit data format for the data processing, so I think it is relevant to this.

    430device is 16-bit data MCU, so when you call "_IQ15rsmpy" and it will work with saturation which might make some error (if it doesn't process the high 16 bits and low 16 bits for the saturation ).

    I find it work with the correct result if Iclarify the variable as the "int".

    So, I reccommend you use the Q format, or use the function that without saturation.

    B.R.

    Sal

  • Dear Sal,

    thank you very much for your answer - sadly i do not understand it correctly or it is not directly applicable (or at least should not).

    The MSP450FR599x i am using has a 32bit hardware multiplier (i think with a 64bit result register) included. The IQmath should use it.... sadly i have not found the c / asm code for IQmath so i can fix it myself.

    The dynamic of the Qmath is not enough for my case, so sadly that is no option.

    What i do not understand is why the saturation is a problem /does not work when the result is rounded to 0. If it would not work correctly for large values i might understand but around 0 it should not do anything. As i need the saturation done i dont know how to implement it otherwise...

    What do you mean by “I find it work with the correct result if Iclarify the variable as the "int".“? The _iq are defines as int32_t ….

    I fear there is a bug in the IQmath or the multiplier... hopefully someone from TI will take a look.

     

    Thanks again and best wishes

    Tobias

  • Hi Tobias,

    What do you mean by “I find it work with the correct result if Iclarify the variable as the "int".“? The _iq are defines as int32_t ….

    My apologize. The int means 16-bit in msp430 device, I don't make it clear to you.

    Actually, due to the IQmath library of msp430 is static, so I cannot give much explanation what makes it happen. However, I have another suggestion for this: you can downlaod the mspm0 SDK for checking the IQmath library, and the source .c file is listed in it, so I think you can do some verfication.

    Below is the link for mspm0 sdk:

    https://www.ti.com/tool/MSPM0-SDK?keyMatch=MSPM0%20SDK 

    B.R.

    Sal

  • Dear Sal,

    thanks again for your reply.

    Might i enquire where you found this c file? I browsed all iqmath directory here: https://dev.ti.com/tirex/explore/node?node=A__AMztb67RYAJCCVC9dL423Q__MSPM0-SDK__a3PaaoK__LATEST
    but could only find the header and examples.... nothing new to learn from that.

    *edit* Ah after installing the .exe i found the code you meant.... ill look into it....

    But i think it might not be applicable since the MSPM0 is based on Arm (i think) and therefore the implementation might be different -> this error might not occur (cant check this obviously)?

    Best wishes

    Tobias

  • Sooo i tried the c-code in the M0 SDK and its works fine.

    --> Therefore the error must be in the IQmath implementation for the MSP430FR599x (and maybe others) ... probably how the MPY module registers (maybe MACS32 or RES3) are used (but thats just a guess as i cant look into the implementation for the not M0 lib).

    Hopefully some TI employer can look into this fault and escalate this, so it can be fixed.

    Best wishes and looking forward to an employer/admin reply.

    Tobias

  • It isn't too difficult to look at the library code. I never use that library (I tend to use mixed formats which the library doesn't support) but it was pretty easy to dump something. For example:

    Disassembly of section .text:_IQ15rmpy:
    
    00000000 <_IQ15rmpy>:
       0:   02 12           push    r2              ;
       2:   32 c2           dint                    
       4:   03 43           nop                     
       6:   12 12 5c 01     push    &0x015c         ;
       a:   82 43 5c 01     mov     #0,     &0x015c ;r3 As==00
       e:   82 4c 44 01     mov     r12,    &0x0144 ;
      12:   82 4d 46 01     mov     r13,    &0x0146 ;
      16:   82 4e 50 01     mov     r14,    &0x0150 ;
      1a:   82 4f 52 01     mov     r15,    &0x0152 ;
      1e:   1e 42 54 01     mov     &0x0154,r14     ;0x0154
      22:   1c 42 56 01     mov     &0x0156,r12     ;0x0156
      26:   1d 42 58 01     mov     &0x0158,r13     ;0x0158
      2a:   3e 50 00 40     add     #16384, r14     ;#0x4000
      2e:   0c 63           adc     r12             ;
      30:   0d 63           adc     r13             ;
      32:   0e 5e           rla     r14             ;
      34:   0c 6c           rlc     r12             ;
      36:   0d 6d           rlc     r13             ;
      38:   b2 41 5c 01     pop     &0x015c         ;
      3c:   32 41           pop     r2              ;
      3e:   30 41           ret  

    This moves the arguments into the hardware multiplier registers, reads the results and rounds.  Rounding is done by adding 1/2lsb (before the 15 bit right shift to align the binary point), aka 0x4000.

    The other version:

    Disassembly of section .text:_IQ15rsmpy:
    
    00000000 <_IQ15rsmpy>:
       0:   02 12           push    r2              ;
       2:   32 c2           dint                    
       4:   03 43           nop                     
       6:   12 12 5c 01     push    &0x015c         ;
       a:   82 43 5c 01     mov     #0,     &0x015c ;r3 As==00
       e:   82 4c 44 01     mov     r12,    &0x0144 ;
      12:   82 4d 46 01     mov     r13,    &0x0146 ;
      16:   82 4e 50 01     mov     r14,    &0x0150 ;
      1a:   82 4f 52 01     mov     r15,    &0x0152 ;
      1e:   1e 42 54 01     mov     &0x0154,r14     ;0x0154
      22:   1c 42 56 01     mov     &0x0156,r12     ;0x0156
      26:   1d 42 58 01     mov     &0x0158,r13     ;0x0158
      2a:   3e 50 00 40     add     #16384, r14     ;#0x4000
      2e:   0c 63           adc     r12             ;
      30:   0d 63           adc     r13             ;
      32:   1f 42 5a 01     mov     &0x015a,r15     ;0x015a
      36:   3f 93           cmp     #-1,    r15     ;r3 As==11
      38:   18 38           jl      $+50            ;abs 0x6a
      3a:   03 20           jnz     $+8             ;abs 0x42
      3c:   3d 90 00 c0     cmp     #-16384,r13     ;#0xc000
      40:   14 28           jnc     $+42            ;abs 0x6a
    
    00000042 <IQNrsmpy_5$55$>:
      42:   0f 93           cmp     #0,     r15     ;r3 As==00
      44:   04 38           jl      $+10            ;abs 0x4e
      46:   0a 20           jnz     $+22            ;abs 0x5c
      48:   3d 90 00 40     cmp     #16384, r13     ;#0x4000
      4c:   07 2c           jc      $+16            ;abs 0x5c
    
    0000004e <IQNrsmpy_6$55$>:
      4e:   0e 5e           rla     r14             ;
      50:   0c 6c           rlc     r12             ;
      52:   0d 6d           rlc     r13             ;
      54:   b2 41 5c 01     pop     &0x015c         ;
      58:   32 41           pop     r2              ;
      5a:   30 41           ret    

    This starts out the same way including the rounding step. I will leave the remainder of the code for someone else to analyse. I assume it does saturation.

    The problem you have occurs when the full 64 bit product isn't all 1s and the 32 bit IQ15 format  result is. Rounding can't fix that.

    Rounding is done by adding 0x4000. If that particular bit in the result isn't a 1, then no carry will occur. For a small negative number, this will leave all of the bits selected for the IQ15 format result as 1s. Not quite what you were looking for.

  • Hi Tibias,

    --> Therefore the error must be in the IQmath implementation for the MSP430FR599x (and maybe others) ... probably how the MPY module registers (maybe MACS32 or RES3) are used (but thats just a guess as i cant look into the implementation for the not M0 lib).

    As for 430 library code, I think we have no update plans recently. But I will  forward this thread to our software team, and they might put effort into fixing the problem when available.

    Due to 430 IQmath library is not editable. From my side, you can migrate the _IQ15rsmpy function from M0 to 430, and do some modification based on the results.

    B.R.

    Sal

**Attention** This is a public forum