IPB

Welcome Guest ( Log In | Register )

> More Bank Switching Fun...
Orin
post Dec 21 2007, 07:08 AM
Post #1


Regular
*

Group: EstablishedMember
Posts: 55
Joined: 17-November 07
Member No.: 3,897



I had some code that suddenly got bigger and slower and all I'd done was change the size of an array, though no variables ended up placed anywhere but bank 0.

I tracked it down to some uses of porta which were getting both RP0 and RP1 cleared each time before it was used. Even though in some cases, the flow of control made it obviously unnecessary, the initial clear was necessary due to accessing trisa a while back in the call tree. What was particularly bad was the bank switching instructions were inside a loop.

The simplest solution was to force a local variable that is set before the loop into bank 0 only RAM so the bank switching is done to set this variable. The extra unwanted bank switching then went away. All other access in the loop turned out to be in locations which are shared between banks.

Another solution was to force the array I'd changed out into bank 1 and yet another was to use a global variable for the bit count which just happened to be in bank 0 only RAM.

Here is the offending function. It makes no difference whether the C or assembly version is used:

CODE
#pragma OPTIMIZE "a"
void WriteByte(unsigned char byte)
{
    unsigned char bitCount = 8;

#if 1
    do {
        DATA1 = byte.7;
                        // Ts(500nS) might be marginal if the clock is a bit fast
        CLK1 = 1;
        byte <<= 1;        // Th/Thmin are both 500nS
        CLK1 = 0;
    } while ( --bitCount != 0 );
#else
    _asm {
    loop:
        btfsc    _byte,7
        bsf        _porta,2; DATA1
        btfss    _byte,7
        bcf        _porta,2
        bcf     _status,C; Not actually needed, but it ensures Ts
        bsf        _porta,1; CLK1
        rlf        _byte, F
        bcf        _porta,1
        decfsz    _bitCount, F
        goto    loop
    }
#endif
}


And the code it produces:

CODE
    ORG 0x00000044
0044        WriteByte_00000
0044       ; { WriteByte; function begin
0044  3008      MOVLW 0x08
0045  00F6      MOVWF WriteByte_00000_1_bitCount
0046        label7
0046  1FF5      BTFSS WriteByte_00000_arg_byte,7
0047  284B      GOTO    label8
0048  1283      BCF STATUS, RP0
0049  1303      BCF STATUS, RP1
004A  1505      BSF gbl_porta,2
004B        label8
004B  1BF5      BTFSC WriteByte_00000_arg_byte,7
004C  2850      GOTO    label9
004D  1283      BCF STATUS, RP0
004E  1303      BCF STATUS, RP1
004F  1105      BCF gbl_porta,2
0050        label9
0050  1283      BCF STATUS, RP0
0051  1303      BCF STATUS, RP1
0052  1485      BSF gbl_porta,1
0053  1003      BCF STATUS,C
0054  0DF5      RLF WriteByte_00000_arg_byte, F
0055  1085      BCF gbl_porta,1
0056  03F6      DECF WriteByte_00000_1_bitCount, F
0057  1D03      BTFSS STATUS,Z
0058  2846      GOTO    label7
0059  0008      RETURN
005A       ; } WriteByte function end


Simply changing unsigned char bitCount to unsigned char bitCount@0x20 produces:

CODE
    ORG 0x00000046
0046        WriteByte_00000
0046       ; { WriteByte; function begin
0046  3008      MOVLW 0x08
0047  1283      BCF STATUS, RP0
0048  1303      BCF STATUS, RP1
0049  00A0      MOVWF WriteByte_00000_1_bitCount
004A        label7
004A  1BF6      BTFSC WriteByte_00000_arg_byte,7
004B  1505      BSF gbl_porta,2
004C  1FF6      BTFSS WriteByte_00000_arg_byte,7
004D  1105      BCF gbl_porta,2
004E  1485      BSF gbl_porta,1
004F  1003      BCF STATUS,C
0050  0DF6      RLF WriteByte_00000_arg_byte, F
0051  1085      BCF gbl_porta,1
0052  03A0      DECF WriteByte_00000_1_bitCount, F
0053  1D03      BTFSS STATUS,Z
0054  284A      GOTO    label7
0055  0008      RETURN
0056       ; } WriteByte function end


I realise that this is a difficult case to analyse, but nowhere in the loop is anything but bank 0 used. In such a case, the bank select could be moved outside the loop.

Orin.
update SourceBoost release 6.97 is available.
Download Now
Go to the top of the page
 
+Quote Post
 
Start new topic
Replies
soft2
post Dec 24 2007, 10:49 PM
Post #2


Regular
*

Group: EstablishedMember
Posts: 62
Joined: 29-September 07
From: Vermont
Member No.: 3,810



Orin,
Have you tried different optimizations? How about compiling on the MPLab asm compiler? Does either make a difference? It seems like a lot of work to have to keep track of which bank was accessed prior to entering every loop.
Go to the top of the page
 
+Quote Post
Orin
post Dec 26 2007, 04:13 AM
Post #3


Regular
*

Group: EstablishedMember
Posts: 55
Joined: 17-November 07
Member No.: 3,897



QUOTE (soft2 @ Dec 24 2007, 02:49 PM) *
Orin,
Have you tried different optimizations? How about compiling on the MPLab asm compiler? Does either make a difference? It seems like a lot of work to have to keep track of which bank was accessed prior to entering every loop.


The example I posted was with aggressive optimization. It was no different with optimization set to "1". The bank switching appears in the ASM file so assembling with MPLAB wouldn't help.

Yes, it is a lot of work to keep track of bank usage - and the compiler does a really good job of it. But there are some cases like this one that are extremely difficult for the compiler to analyse that can result in excess bank switching instructions.

In this case, if I look at the loop carefully, I see it uses three registers/variables - byte, bitcount and porta. Clearly, to get maximum performance out of it, byte and bitcount should be in bank 0 (or to be more accurate bitCount must be in bank only 0 memory, byte merely needs to be acessible from bank 0). If I leave the variable memory allocation to the compiler, then who knows where they'll end up...

For time/performance critical code, you have to look at the code that the compiler is producing, then understand why so you can rearrange the code or force a variable into a particular bank or rewrite a block in assembly.

Orin.
Go to the top of the page
 
+Quote Post

Posts in this topic


Reply to this topicStart new topic
1 User(s) are reading this topic (1 Guests and 0 Anonymous Users)
0 Members:

 



Lo-Fi Version Time is now: 3rd September 2010 - 02:49 PM