4

I'd like to know how many lines of C code in average corresponds to 1Ko programmable memory for PIC18F microcontrollers

Or how many lines of assembly instructions ?

aqww
  • 69
  • 2
  • 3
  • 4
    None. I filled it with data instead. – Ignacio Vazquez-Abrams Apr 25 '15 at 14:28
  • 4
    There is nothing opinion based about the answer to this question. It is an easy factual statement. – Passerby Apr 25 '15 at 16:52
  • 3
    I'm with @Passerby, there is no opinion involved! It may be argued that the questioner is clueless about the translation process from an high level language like C to machine language, but the potential answers are not a matter of opinion at all! If I could, I would vote to reopen. – LorenzoDonati4Ukraine-OnStrike Apr 25 '15 at 17:32
  • 1
    @LorenzoDonati This depends a lot on the qualities of the C code. On a PIC, a function call takes more instructions than `++i;` It's anyone's guess as to what code to use as a benchmark for this question. – Nick Alexeev May 01 '15 at 03:44
  • 2
    @NickAlexeev Yes, I agree, but it could have been made in a good answer, nonetheless (IMO). This is one of those cases where one could have spent a couple dozen of lines to explain the fact: a non-definitive answer (in this case) *could be* an answer, since it could point out *why* you cannot in general estimate the memory footprint of machine code generated by a C compiler without further information on the compiler, compiler options, actual C code, etc. I think it could be a useful reference and it doesn't fall in the "too broad" category. – LorenzoDonati4Ukraine-OnStrike May 01 '15 at 10:54
  • 1
    It depends *entirely* on what that code is. It is perfectly possible to imagine ***one*** long line of C code that would occupy 1k of memory, or alternatively 1000 lines that take up no space at all. – user207421 May 02 '15 at 08:49
  • Tenuously related: http://electronics.stackexchange.com/questions/91562/should-i-refactor-my-c-code-to-optimise-it-for-an-embedded-microcontroller/91563#91563 – David May 02 '15 at 09:52

2 Answers2

11

Let's take some real world examples. I wrote a simple C program, which I think represents typical C code. Some could argue one way or another that it doesn't, but I think it will make my point.

Here is the C code:

unsigned short m [20];

int main()
{
    unsigned char a, x, i;
    unsigned short b, y;
    unsigned long c, z;

    a = b = c = 0;

    for (i=0; i < 20; i++)
    {
        a++;
        b++;
        c++;

        x = a * 3;
        y = b * 3;
        z = c * 3;

        if (a > 50)
        {
            a = 0;
        }

        m[i] = a / (b / (c - z) * x) + i;
    }
}

In addition to the 8-bit PIC18F asked about by the OP, I also compiled it for three other processors: an 8-bit 8051, an 8-bit PIC16F, and a 32-bit PIC32, and for each I took a look at the disassembly code to get the number of instructions and the number of bytes for each line of C code. Due to the length, I decided not to post the disassembly code here.

For the C code above, the PIC18F used 168 instructions and 336 bytes of code (all machine instructions were two bytes long). That however doesn't include some helper routines since the PIC18F for example doesn't have a hardware divide instruction, so a subroutine call is made for that. Of course these helper routines are shared for all the code in a program. So I'll ignore them since they probably affect the code size in a real program by a few percent.

The PIC16F used 272 instructions and 476 bytes of code (all machine instructions on the PIC16F are 14-bits long, so I converted this to bytes). Like the PIC18F, the PIC16F doesn't have a hardware divide instruction, so it also uses helper routines which were not included in the count.

The 8051 used 99 instructions and 175 bytes of code, or an average of 1.77 bytes per machine instruction. Like the PIC18F, the 8051 doesn't have a hardware divide instruction, so it also uses helper routines which were not included in the count.

The PIC32 used 68 instructions and 272 bytes of code. All machine instructions on the PIC32 take 4 bytes, unlike for example the 8051 where instructions can be variable length: 1, 2 or 3 bytes.

There are 11 lines of executable code in my C program. So that works out to be 15.2 instructions per line of C for the for the PIC18F; 24.7 instructions for the PIC16F; 9 instructions for the 8051; and 6.2 instructions For the PIC32.

As far as program bytes per line of code, the numbers are 30.5 bytes for the PIC18F; 43.3 bytes for the PIC16F; 15.9 bytes for the 8051; and 24.7 bytes for the PIC32. So the 8051 wins in terms of least number of bytes per line of C code.

However, for the three PIC compilers, I was not using the optimized versions (they have three versions of each compiler: free, standard, and pro). I was using the free one. Microchip claims the pro compilers can reduce code space by 60%. In my own work experience with the PIC32 pro compiler, I was getting 40-50% reduction. So I'm going to use 50% here as a compromise.

So the numbers become:

          Instructions/line of code    Bytes/line of code

PIC18F          7.6 (est)                  15.2 (est)                
PIC16F          12.4 (est)                 21.6 (est)
8051            9                          15.9
PIC32           3.1 (est)                  12.3 (est)

Interesting that the number of bytes per line of code is so similar between three of the processors, and not that much higher for the PIC16F.

So to answer the original question, for the PIC18F you get 1024/168 * 11 = 67.0 lines of C per 1K of code; for the PIC16F you can get 1024/272 * 11 = 41.4 lines of C, for the 8051 you can get 1024/175 * 11 = 64.4 lines of C, and for the PIC32, 1024/136 * 11 = 82.8 lines of C. So you get the most number of lines of C using the PIC32. I think the average number of lines of C (which is what the OP asked for) for most programs is probably somewhere between 25 and 120 lines of code depending on the processor and the program.

As far as lines of assembly instructions, for the PIC18F you can get 7.6 * 67.0 = 509 instructions; for the PIC16F you can get 12.3 * 40.4 * 16/14 = 567.9 instructions, for the 8051 you can get 9 * 62.8 = 565.2 instructions, and for the PIC32, 3.1 * 82.8 = 256.7

          Lines of C in 1K bytes    Instructions in 1K bytes

PIC18F          65.5 (est)               497.8 (est)                
PIC18F          40.4 (est)               567.9 (est)
8051            62.8                     565.2
PIC32           80.9 (est)               256.7 (est)

Note the "Instructions in 1K bytes" actually is just over 500 for the PIC18F, and 250 for the PIC32, since they use 2 and 4 bytes instruction respectively. The number for the PIC16F is higher due to the allowance for its 14-bit words.

tcrosley
  • 47,708
  • 5
  • 97
  • 161
  • What about optimization? Did you compile both with out it? – Passerby May 02 '15 at 07:26
  • @Passerby I don't have the optimizing versions of these compilers at home, only at work (if I remember correctly, the optimized PIC32 compiler is around $800). From my experience there, the optimized code was about 40% smaller than the unoptimized. I'll include that in my answer. Thanks. – tcrosley May 02 '15 at 08:01
  • "exactly 500". Not quite, since 1KB of memory on a uC is 1024B (they use the 2^10 system, not the 10^3 one). – Tom Carpenter May 02 '15 at 15:04
  • @TomCarpenter I'll redo my calculations using 1024 instead of 1000. Thanks. – tcrosley May 02 '15 at 16:46
8

As for C - it can be one line, or it can be a thousand. Depending on the constructs and optimization. For assembly it is clear - PIC18 has an instruction set composed of 16 and 32bit long instructions. So 1Kb can contain at 1024/2=512 instructions at most.

Eugene Sh.
  • 9,986
  • 2
  • 26
  • 41
  • The OP didn't ask how many machine instructions in 1K of code, he asked for how many lines of C code. – tcrosley May 02 '15 at 02:12
  • @tcrosley If you look carefully at the question you will notice the line about assembly that *mostly* translating one line to one instruction. So the answer is addressing both parts of the question. – Eugene Sh. May 02 '15 at 02:16
  • 1
    Well, I disagree that on most processors, on average one line of C translates to one machine instruction. – tcrosley May 02 '15 at 02:19
  • 4
    @tcrosley Do you mind re-reading the question and the answer? The answer is stating that you can't tell for C. But you can for assembly. – Eugene Sh. May 02 '15 at 02:21
  • one line of c code can have several constants and several variable assiggments, there'n no way that's going to reduce to one istruction. – Jasen Слава Україні May 03 '15 at 11:06
  • @Jasen Some lines or even blocks can reduce to *zero* instructions if optimized away, which happens a lot. – Eugene Sh. May 03 '15 at 13:42