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.

MSP430FR5994: Using LEA for matrix multiplications

Part Number: MSP430FR5994

I am looking to implement matrix multiplication on the LEA. My matrix dimensions in succession for every stage of operation are as follows:

[1,256] * [256,20] ---> [1,20] * [1,10] ----> [1,10] * [10,2] ----> [1,2]

After checking the available documentation provided by the DSPLib - I see that I cannot work with the [256,20] matrix on the LEA as the multiplication terminates due to address range being insufficient. Additionally, I would prefer not to use the 'msp_matrix_mpy15()' function as it works with the fixed point representation and I cannot afford to lose the lower half of the final result of matrix multiplication. An alternative I found was the use of LEA commands to perform matrix multiplication and addition as mentioned in the reference guide [slau850] - https://www.ti.com/lit/ug/slau850/slau850.pdf?ts=1642755710288&ref_url=https%253A%252F%252Fwww.ti.com%252Fproduct%252FMSP430FR5043%253FkeyMatch%253DMSP430FR5043 - according to this guide the LEACMD_MAC, LEACMD_MPYMATRIX, LEACMD_MPYLONGMATRIX functions can also be used to execute the operations I have mentioned above. However, I have the following questions here -

Is there any way in which the LEA can access the large matrix from the stored location in the normal memory of the MSP430 instead of the shared memory?

Considering the dimensions of the matrices, would it make sense to use the LEA in the first place, as I read across the forum that it takes an addition of upto 60-70 cycles to set up the LEA ?

Additionally, I see that the 'msp_matrix_mpy15()' function contains an option for using the hardware multiplier - how could I enable the hardware multiplier to perform the matrix multiplication instead as I have a smooth running function that can perform the required operation on the MPY32? 

Please let me know if any more info is required. Thank you. 

  • Hi Siddhant,

    Sorry for reply you later.

    You would like to calcul a [256,20] matrix?  

    This size should less than 8K, I think this should can work normally.

    And attach LEA code example(register level), maybe useful for you.

    LEACMD__MPYMATRIX.zip

    Thanks!

    Best Regards

    Johnson

  • Thank you. I will have a look at the code and then update the thread at the earliest!

  • In the example attached, I am trying to run a very basic example as follows - 

    #include "msp430fr5994.h"
    
    #include "lea_params.h"
    #include "reference/reference_c.h"
    
    #include <math.h>
    #include <stdio.h>
    #include <stdint.h>
    #include <stdlib.h>
    #include <string.h>
    #include <stdbool.h>
    
    // Convert MSP430 address to internal LEA address mapping.
    #define LEA_CONVERT_ADDRESS(x)    ((uint16_t)(((uintptr_t)(x) >> 2) & 0xffff))
    
    // Convert LEA address to MSP430 address mapping.
    #define LEA_REVERT_ADDRESS(x)     ((uintptr_t)(((uint32_t)(x) << 2)))
    
    // Test Size
    #define VECTOR_SIZE       2
    
    // Q15 format -> 0.5 -> 0.5*2^15 = 32768
    const int16_t initInputA[VECTOR_SIZE][VECTOR_SIZE] = {{559, 393},
                                                          {444, 980}};
    const int16_t initInputB[VECTOR_SIZE][VECTOR_SIZE] = {{1,0},
                                                          {1,0}};
    
    #pragma DATA_SECTION(inputA, ".leaRAM");
    #pragma DATA_ALIGN(inputA, 4);
    int16_t inputA[VECTOR_SIZE][VECTOR_SIZE];
    
    #pragma DATA_SECTION(inputB, ".leaRAM");
    #pragma DATA_ALIGN(inputB, 4);
    int16_t inputB[VECTOR_SIZE][VECTOR_SIZE];
    
    #pragma DATA_SECTION(output, ".leaRAM");
    #pragma DATA_ALIGN(output, 4);
    int16_t output[VECTOR_SIZE][VECTOR_SIZE];
    
    #pragma DATA_SECTION(params, ".leaRAM");
    #pragma DATA_ALIGN(params, 4);
    LEA_raddmlParams params;
    
    int16_t outputGolden[VECTOR_SIZE][VECTOR_SIZE];
    
    volatile bool success = false;
    volatile uint16_t benchmark;
    
    void main(void)
    {
    
        WDTCTL = WDTPW | WDTHOLD;       // Stop watchdog timer
        PM5CTL0 &= ~LOCKLPM5;           // Clear lock bit
    
        CSCTL0_H = CSKEY_H;
        CSCTL3 = 0;
        CSCTL0_H = 0;
    
        /* Initialize LEASC. */
        LEACNF0 = LEALPR | LEAILPM;
        LEASCCNF1 = 0;
        LEASCCNF2 = 0;
        LEASCCNF2 |= LEASCMT >> 2;
        LEASCPMS1 = 0;
        LEASCPMS0 = 0;
        LEASCPMDST = 0;
        LEASCPMCTL |= LEASCCMDEN;  // Enable LEA by setting command enable
        LEASCIFG = LEASCPMCMDIFG | LEASCSDIIFG | LEASCOORIFG | LEASCCOVLIFG; // Clear all interrupt flags
        LEASCIE |= LEASCPMCMDIE; // Enable the command complete interrupt
    
        /* Load input data */
        memcpy(inputA,initInputA,sizeof(initInputA));
        memcpy(inputB,initInputB,sizeof(initInputB));
    
        /* Set parameters */
        params.vectorSize = VECTOR_SIZE;
        params.input2 = LEA_CONVERT_ADDRESS(inputB);
        params.output = LEA_CONVERT_ADDRESS(output);
        params.input1Offset = 1;
        params.input2Offset = 1;
        params.outputOffset = 1;
    
        /* Load source arguments to LEA. */
        LEASCPMS0 = LEA_CONVERT_ADDRESS(inputA);
        LEASCPMS1 = LEA_CONVERT_ADDRESS(&params);
    
        /* Invoke RAM command with interrupts. */
        LEAPMCB = LEACMD__MPYMATRIX | LEAITFLG1;
    
        /* Enable Interrupt & enter LPM0 mode. */
        __bis_SR_register(GIE + LPM0_bits);
    
        /* BREAK HERE, RAM version */
        __no_operation();
    
        while(1);
    }
    

    Now, here instead of obtaining {{559,0}, {444,0}} as the output - I received only [[0,0],[0,0]]. This is also the same in case I treat the 2x2 matrix as an array of 4 elements or a 1x4 matrix like the one given in the sample. As far as  I can understand, this must be due to right shifting of the result 15 times. And, this is exactly where I had a problem, where I need the original values for my calculations and not the shifted result. Is it possible to obtain the answer in the original form - in this case it would be  - {{559,0}, {444,0}} ? Let me know if any more information is necessary. Thank you

  • You could get what you want, more or less, if you used the Q31 routines. You would have to store your data as 32 bit integers which would take more of the space you don't have enough of already. And the hardware mangles the data from the natural Q62 result into Q63. So you would have to undo that 64 bit left shift.

    You are far better off using the hardware multiply-accumulate function directly. You could maybe move your data into LEARAM one 256 element row at a time to do a LEA dot product but any savings in power from the multiply is probably lost in moving the data around.

    If you just sit around waiting for the LEA hardware to complete its operation, I can't see how it saves much energy.

  • Thank you for the detailed response David. That was indeed very helpful. I will have a look at the options once again and proceed accordingly. I will mark the issue as resolved.

**Attention** This is a public forum