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.

what causes variation in f28m35 instruction cycles

I am using an ISR that does nothing but store/restore the XARn registers,  set/clear a GPIO bit upon entering and exiting, and in between execute the senseless code appended below. The GPIO bit enables measuring the execution time of each instruction, indicated as a comment in each line of the code.

My expectation is that each of these is a one-cycle instruction, but that is obviously wrong. The M3 is doing nothing but an infinite  while(1) ; loop. The DMACH1 and DMACH2 channels are setup, but they are not started, so there would seem to be no bus contention conflicts. Yet the instructions take multiple cycles to execute, and identical instructions execute in different numbers of cycles.

Can someone tell me what is going on and point me to the right document?

MOVW  DP,      #variable1_pointer           // 1 cycle
MOVL   XAR0, @variable1_pointer          //  1 cycle
MOV     AL,       *XAR0                                 //  4 cycles
MOV    *XAR0, AL                                        //  1 cycle
MOVL   XAR0, @variable2_pointer         //  2 cycle
MOV     AL,       *XAR0                                 //  3 cycles
MOV    *XAR0, AL                                        //  1 cycle
MOVL   XAR0, @variable3_pointer         //  1 cycle
MOV     AL,       *XAR0                                 //  4 cycles
MOV    *XAR0, AL                                        //  1 cycle
MOVL   XAR0, @variable4_pointer         //  2 cycle
MOV     AL,       *XAR0                                 //  3 cycles
MOV    *XAR0, AL                                        //  1 cycle

 

  • Dick,

    Can you elaborate on your setup?  It sounds like you are trying to measure the ASM execution time by observing a GPIO toggle between each MOV instruction.  Is this true?

    -Tommy

  • Dick Hester said:
    My expectation is that each of these is a one-cycle instruction

    On what do you base that expectation?

  • Not exactly. I add each instruction, one at a time. I rebuild the project after each addition and I measure the GPIO set time. By subtracting the previous GPIO set time, I deduce the time required for the most recently added instruction.

  • Andy Neil said:

    My expectation is that each of these is a one-cycle instruction

    On what do you base that expectation?

    [/quote]

    Those assembly instructions are single-cycle operations on the C28x core.

  • Dick, Daniel

    where does the XAR0 point to? internal FLASH, internal RAM, external RAM?

    Regards, Mitja

  • Dick,

    I think variations are expected when using GPIOs to profile instructions because the signal path between the CPU and actual pin crosses various bus and clock domains along the way.  The crossover points can introduce clock-cycle jitter.  A more accurate measure would be to use a CPU performance timer.

    I also find that results are more stable if you repeat  the same instruction inline multiple times (say 50 times) and then capture the overall time for the 50 executions & divide by 50.

    -Tommy

  • Mitja,

    The contents of XAR0 points to addresses 0xB933-6, corresponding to each of the four variable's pointers. In my command file this corresponds to RAML3.

  • Tommy, my issues were both variability and the fact that 13 single cycle instructions are invariably taking 25 C28 clocks to complete. 

    Regarding measurability, I have no trouble measuring and correlating the execution time of the 23 instructions I use to store/restore the XARn registers with the number of instructions. However,  I will accept that the issue bring up is the source of variability I mentioned, and I will stop worrying about it. That leaves the long execution time that is a much more seerious issue.

    Per your suggestion, I replicated my 13-instruction snippet four times for a total of 52 instructions. I find that the total execution time increases to 123 clock cycles, 23 for the XARn context overhead and 100 = 4*25 for the 52 instructions. I conclucde that the thirteen siingle cycle instructions execute in 25 C28 clock cycles. This is s terrific waste of my ISR budget.

    - Dick

  • Dick,

    If this is still profiled with the GPIO, can you output PLLSYSCLKOUT onto the XCLKOUT pin to make sure that the system is running at the expected frequency?  

    -Tommy

  • Tommy,

    I have not figured out how to use the CCS4 profiler. It complains when I try to set it up. So I have done something else to verify the master clock frequency: When I add 30 consecutive NOPs to the ISR the GPIO bit on time is increased by 200ns. That is a 150MHz clock. The clock setup code from main_m3.c is

    // Sets up PLL, M3 running at 75MHz and C28 running at 150MHz
    SysCtlClockConfigSet(SYSCTL_USE_PLL | (SYSCTL_SPLLIMULT_M & 0xF) |
                                             SYSCTL_SYSDIV_1 | SYSCTL_M3SSDIV_2 |
                                             SYSCTL_XCLKDIV_4);

    - Dick

  • Dick,

    I think your measurements are correct. The reason for the delayed execution of some of the instructions is with the CPU pipeline. By definition, all of the instructions from you code snipped are 1 cycle instructions. However, when you use these instructions in a sequence like in your code example from above, you will get delay cycles because of the protected pipeline (avoid reads before writes for the same memory location).

    Example:   

    The pipeline has 8 stages: F1,F2,D1,D2,R1,R2,X,W

    The instruction MOVL XAR0,@v1   will update register XAR0 when the instruction is in phase 'W' (or 'X' - am not quite sure here).

    The next instruction MOV AL,*XAR0  will try to read from memory pointed by XAR0. But this instruction is only 1 clock cycle behind in the pipeline. Therrfore the pipeline protection mechanism will delay the R1,R2 and X phase by 3 more cycles so that 'W' from instruction 1 is earlier than 'R1' from instruction2. 

    That's how I would explain your measurement results.

     

  • Frank, thank you. I think you broke the code.

     I have rewritten my code snippet to 15 instructions and reordered executions (below). It appears to execute in 18 or 19 cycles, I think it suffers from the same issue where reading the low half of the accumulator occurs before it is written by the prior instruction. That would seem to add four cycles. Do you agree?

    To remove the four extra cycles, I could use anouther register, like P or T, but the C28 instruction set does not seem to offer offer a way to do this with a convenient multiply by 8. Can you confirm?

    MOVW DP,       #_input_Pointer:n:
    MOVL  XAR0,   @_input_Pointer:n:
    MOVL  XAR1,   @_output_Pointer:n:
    MOVL  XAR2,   @_Iin_Pointer:n:
    MOVL  XAR3,   @_Vin_Pointer:n:
    MOVL  XAR4,   @_Iout_Pointer:n:
    MOVL  XAR5,   @_Vout_Pointer:n:
    MOV    ACC,    *XAR0++<<#3
    MOV    *XAR2,  AL                               ; Iin=8*input[0]
    MOV    ACC,    *XAR1++<<#3
    MOV    *XAR4,  AL                               ; Iout=8*output[0]
    MOV    ACC,    *XAR0<<#3
    MOV    *XAR3,  AL                               ; Vin=8*input[1]
    MOV    ACC,    *XAR1<<#3
    MOV    *XAR5,  AL                               ; Iout=8*output[1]

  • Dick,

    I am not that clear on the details of how the pipeline works, but you could further re-arrange by inserting the "MOVL XARn, @_address" between the ACC register read/write

    MOV ACC, *XAR
    MOVL XARn, @_address
    MOV *XAR, AL

    Regards,
    Daniel

     

  • Dick,

    now your code looks much better in terms of pipeline optimization. And, yes the MOV combined with a shift left in 1 cycle is only available for ACC, not for P or T.

    Your new combination MOV ACC, *XAR0++ and MOV *XAR2,AL is a read from memory to ACC(instrucrion 1) followed by a write from ACC to memory (instruction 2) - which would add 1 clcok cycle delay for each pair and so the overall result is 4 additional clocks in your code snippet.