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.

TMS320F28035: F28035 CLA floating point math accelerator enabled or not

Part Number: TMS320F28035

Tool/software:

Dear TI Experts,

I am currently working with the F28035 CLA for some floating-point calculations, which, according to the manual, are supported by the CLA hardware.

However, I have observed that a single precision floating-point multiplication takes approximately 800ns. I have a few questions regarding this:

  1. Floating Point Multiplication Implementation: Is the floating-point multiplication actually utilizing the hardware floating point accelerator, or is it still using the software library? How can I verify which one is being used?

  2. Enabling Hardware Floating Point Accelerator: What steps do I need to follow to ensure that the hardware floating point accelerator is enabled and properly utilized?

Additionally, I have attached the disassembly of a floating-point multiply operation in the CLA for your reference.

223 p->integralAccumulation += p->error * p->integralGain;


009402: 0004 PUSH RPC
009403: 7FF0 MOV *+XAR0[6], AR7
009404: 0000 ITRAP0
009405: 7FA0 MOV @AR0, AR7
009406: 0000 ITRAP0
009407: 7FA0 MOV @AR0, AR7
009408: 0000 ITRAP0
009409: 7FA0 MOV @AR0, AR7
00940a: 0000 ITRAP0
00940b: 73D2 ADD *+XAR2[2], AH
00940c: 00087FF0 BANZ 32752,AR0--
00940e: 000A7FD0 BANZ 32720,AR2--
009410: 0000 ITRAP0
009411: 7FA0 MOV @AR0, AR7
009412: 0000 ITRAP0
009413: 7FA0 MOV @AR0, AR7
009414: 0000 ITRAP0
009415: 73E2 ADD *+XAR2[4], AH
009416: 0000 ITRAP0
009417: 0691 MOVL ACC, *+XAR1[AR0]
009418: 0019 INTR INT10
009419: 7C20 MOV @0x20, AR4
00941a: 0000 ITRAP0
00941b: 74D1 SUB *+XAR1[2], AL
00941c: 0000 ITRAP0
00941d: 7FA0 MOV @AR0, AR7

  • Hi Ivan,

    The c28x can be extended to enable FPU support (which enables the use of the c28x instruction set plus the FPU instruction set.) The CLA however is a completely separate processor that has its own instruction set. The CLA instruction set is a subset of the c28x+FPU instruction set, so it should contain equivalent math instructions for most floating-point instructions (including multiplcation). These floating-point capabilities are inherent to the CLA instruction set, so nothing needs to be done to enable them.

    The main issue I see from the disassembly is that there are a lot of ITRAP0 instructions. ITRAP indicates that an illegal opcode has been fetched, which means the program is continuously triggering the ITRAP interrupt and branching to the ITRAP ISR in the boot ROM. This likely points to an issue with how the CLA program memory is being mapped. A couple things to check:

    1. Verify that the MMEMCFG.PROGE bit is being set to 1, meaning that the CLA is being given access to the CLA program memory.
    2. Make sure you are copying the CLA program memory into a CLA accessible LSRAM. If using the provided CLA linker cmd file for the F2803x, you should have the following line in your main C code to copy the CLA program over:

    memcpy(&Cla1funcsRunStart, &Cla1funcsLoadStart,(Uint32)&Cla1funcsLoadSize);

    Please upvote this response if it is helpful and let me know if you have any further questions/issues.

    Best Regards,

    Delaney

  • Hi Delaney, thanks for your help.

    I have checked based on your suggestion. It looks fine. But ITRAP still there.

    For your information, the code in CLA is definitely working, and controlling PWMs properly, albeit slow calculation. Anything else to check?

    (1) MMEMCFG.PROGE bit. It is set.

    void cla_init(void)
    {
        EALLOW;
        Cla1Regs.MVECT1 = (Uint16)((Uint32)&Cla1Task1 - (Uint32)&Cla1Prog_Start);
        Cla1Regs.MVECT2 = (Uint16)((Uint32)&Cla1Task2 - (Uint32)&Cla1Prog_Start);
        Cla1Regs.MVECT3 = (Uint16)((Uint32)&Cla1Task3 - (Uint32)&Cla1Prog_Start);
    
        Cla1Regs.MPISRCSEL1.bit.PERINT1SEL = CLA_INT1_NONE;
        Cla1Regs.MPISRCSEL1.bit.PERINT2SEL = CLA_INT2_NONE;
        Cla1Regs.MPISRCSEL1.bit.PERINT3SEL = CLA_INT3_NONE;
        Cla1Regs.MIER.bit.INT1 = 1;
        Cla1Regs.MIER.bit.INT2 = 1;
        Cla1Regs.MIER.bit.INT3 = 1;
    
        Cla1Regs.MMEMCFG.bit.PROGE = 1;
        Cla1Regs.MCTL.bit.IACKE = 1;
        Cla1Regs.MMEMCFG.bit.RAM0E = 0;
        Cla1Regs.MMEMCFG.bit.RAM1E = 1;
        EDIS;
    }

    (2) Memory copy is done. Please note cla_init() after memory copy. Is it an issue?

        memcpy(&Cla1funcsRunStart, &Cla1funcsLoadStart, (Uint32)&Cla1funcsLoadSize);
        cla_init();

    (3) .cmd file

    _Cla1Prog_Start = _Cla1funcsRunStart;
    -heap 0x200
    -stack 0x200
    
    CLA_SCRATCHPAD_SIZE = 0x100;
    --undef_sym=__cla_scratchpad_end
    --undef_sym=__cla_scratchpad_start
    
    MEMORY
    {
    PAGE 0:    /* Program Memory */
               /* Memory (RAM/FLASH/OTP) blocks can be moved to PAGE1 for data allocation */\
       RAMM1       : origin = 0x000750, length = 0x0000B0
       RAML3       : origin = 0x009000, length = 0x001000
    
       OTP         : origin = 0x3D7800, length = 0x000400     /* on-chip OTP */
       FLASHH      : origin = 0x3E8000, length = 0x002000     /* on-chip FLASH H*/
       FLASHCDEFG  : origin = 0x3EA000, length = 0x009FF0     /* on-chip FLASH CDEFG*/
    
       BEGIN	   : origin = 0x3F3FF0, length = 0x000004	   //App������ڵ�ַ
    
       ROM         : origin = 0x3FF27C, length = 0x000D44     /* Boot ROM */
       RESET       : origin = 0x3FFFC0, length = 0x000002     /* part of boot ROM  */
       VECTORS     : origin = 0x3FFFC2, length = 0x00003E     /* part of boot ROM  */
    
    PAGE 1 :   /* Data Memory */
               /* Memory (RAM/FLASH/OTP) blocks can be moved to PAGE0 for program allocation */
               /* Registers remain on PAGE1                                                  */
       BOOT_RSVD   : origin = 0x000000, length = 0x000050     /* Part of M0, BOOT rom will use this for stack */
       RAMM0       : origin = 0x000050, length = 0x000700     /* on-chip RAM block M0M1 */
    
       CLA1_MSGRAMLOW   : origin = 0x001480, length = 0x000080
       CLA1_MSGRAMHIGH  : origin = 0x001500, length = 0x000080
    
       RAML0L1     : origin = 0x008000, length = 0x000C00     /* on-chip RAM block L0L1L2 */
       CLARAM1     : origin = 0x008C00, length = 0x000400
    }
    
    /* Allocate sections to memory blocks.
       Note:
             codestart user defined section in DSP28_CodeStartBranch.asm used to redirect code
                       execution when booting to flash
             ramfuncs  user defined section to store functions that will be copied from Flash into RAM
    */
    
    SECTIONS
    {
       /* Allocate program areas: */
       .cinit              : > FLASHCDEFG      PAGE = 0, ALIGN(4)
       .pinit              : > FLASHCDEFG      PAGE = 0, ALIGN(4)
       .text               : > FLASHCDEFG      PAGE = 0, ALIGN(4)
       codestart           : > BEGIN       PAGE = 0, ALIGN(4)
    
       ramfuncs            : LOAD = FLASHCDEFG, ALIGN(4)
                             RUN = RAMM1,
                             LOAD_START(_RamfuncsLoadStart),
                             LOAD_SIZE(_RamfuncsLoadSize),
                             RUN_START(_RamfuncsRunStart),
                             PAGE = 0
    
       /* Allocate uninitalized data sections: */
       .stack              : > RAMM0       PAGE = 1, ALIGN(4)
       .ebss               : > RAML0L1      PAGE = 1, ALIGN(4)
       .esysmem            : > RAMM0       PAGE = 1, ALIGN(4)
    
       largeRAMData        : > RAMM0,   PAGE = 1
       .bss_cla		       : > CLARAM1,   PAGE = 1
       .scratchpad         : > CLARAM1,   PAGE = 1
    
       Cla1Prog            : LOAD = FLASHH,
                             RUN = RAML3,
                             LOAD_START(_Cla1funcsLoadStart),
                             LOAD_END(_Cla1funcsLoadEnd),
                             RUN_START(_Cla1funcsRunStart),
                             LOAD_SIZE(_Cla1funcsLoadSize),
                             PAGE = 0
    
       Cla1ToCpuMsgRAM     : > CLA1_MSGRAMLOW,   PAGE = 1
       CpuToCla1MsgRAM     : > CLA1_MSGRAMHIGH,  PAGE = 1
       Cla1DataRam1		   : > CLARAM1,		  PAGE = 1
    
       CLAscratch          :
                             { *.obj(CLAscratch)
                             . += CLA_SCRATCHPAD_SIZE;
                             *.obj(CLAscratch_end) } > CLARAM1,
    					     PAGE = 1
    
       /* Initalized sections go in Flash */
       /* For SDFlash to program these, they must be allocated to page 0 */
       .econst             : > FLASHCDEFG      PAGE = 0, ALIGN(4)
       .switch             : > FLASHCDEFG      PAGE = 0, ALIGN(4)
    
       /* .reset is a standard section used by the compiler.  It contains the */
       /* the address of the start of _c_int00 for C Code.   /*
       /* When using the boot ROM this section and the CPU vector */
       /* table is not needed.  Thus the default type is set here to  */
       /* DSECT  */
       .reset              : > RESET,      PAGE = 0, ALIGN(4), TYPE = DSECT
       vectors             : > VECTORS     PAGE = 0, ALIGN(4), TYPE = DSECT
    }
    

    (4) More information, based on this post (larger memory size needed of CLA compiler than C28x - C2000 microcontrollers forum - C2000Tm︎ microcontrollers - TI E2E support forums), 

    "The assembly shown here is c28x assembly not CLA. I suspect you copied this from the disassembly window while the c28x debug tap was selected. the debugger window will try to interpret the CLA opcodes in terms of c28x assembly mnemonics; that is why there are so many ITRAPs in the code."

    So the following should be correct CLA disassembly for the same line of code. I can see a lot of MNOP, which I believe is CLA's NOP. Any suggestion on improvement?

    223 p->integralAccumulation += p->error * p->integralGain;
    
    000093e0:   7FF00004    MMOV16     MAR1, MR0, #0x4
    000093e2:   7FA00000    MNOP       
    000093e4:   7FA00000    MNOP       
    000093e6:   7FA00000    MNOP       
    000093e8:   73D20000    MMOV32     MR1, *MAR1, UNCF
    000093ea:   7FF00008    MMOV16     MAR1, MR0, #0x8
    000093ec:   7FD0000A    MMOV16     MAR0, MR0, #0xa
    000093ee:   7FA00000    MNOP       
    000093f0:   7FA00000    MNOP       
    000093f2:   73E20000    MMOV32     MR2, *MAR1, UNCF
    000093f4:   06910000    MMPYF32    MR2, MR2, MR1 || MMOV32    MR1, *MAR0
    000093f6:   7C200019    MADDF32    MR1, MR2, MR1
    000093f8:   74D10000    MMOV32     *MAR0, MR1

  • Hi Ivan,

    Thank you for sharing your code. I will take a look at it and get back to you with a response tomorrow.

    Best Regards,

    Delaney

  • Hi Ivan,

    Memory copy is done. Please note cla_init() after memory copy. Is it an issue?

    No that shouldn't be an issue. That is the recommended order of operations.

    So the following should be correct CLA disassembly for the same line of code. I can see a lot of MNOP, which I believe is CLA's NOP. Any suggestion on improvement?

    I see, yes this should be an optimization issue then. Can you try changing the optimization to level 2 or higher? It will allow more opportunities for parallel instructions and should improve performance. You can do this in the project's Properties >> Build >> C2000 Compiler >> Optimization.

    The following excerpt is from the compiler guide (linked here) and discusses how the CLA can be optimized.

    Best Regards,

    Delaney