1. This forum section is a read-only archive which contains old newsgroup posts. If you wish to post a query, please do so in one of our main forum sections (here). This way you will get a faster, better response from the members on Motherboard Point.

how to prevent timer code firmware running on Microblaze from beingoptimised

Discussion in 'Embedded' started by chrisdekoh, Jun 9, 2008.

  1. chrisdekoh

    chrisdekoh Guest

    I am trying to do the following on Microblaze. Here is the program

    void main() {
    Xuint32 countvalue;

    // do some stuff on Microblaze

    ... //some lines of code ....

    countvalue = readback_timer();

    //send count value back to serial port


    In short, I am trying to keep tab of how fast various sections of code
    takes to run using a timer running on Microblaze.

    when i do compile with some compiler optimization level set to -O1 or -
    O2 or -O3, the compiler cleverly enables the timer at the WRONG place.
    it enables the timer and then disables the timer again, giving me a
    very short compute time. this is not what i want. :( since i want to
    be able to accurately measure how long it takes for the code to
    execute. I tried declaring countvalue as

    volatile Xuint32 countvalue;

    It doesn't quite work. Does anybody have an idea on how i could go
    about solving this?

    thanks for your patience; I have not much experience developing
    embedded firmware.

    chrisdekoh, Jun 9, 2008
    1. Advertisements

  2. chrisdekoh

    ghelbig Guest

    Something you could try

    Recode enable_timer to return a value (say zero) - use the return
    value to initialize a variable (starting sum, whatever) in your "do
    stuff" section, real close to the start.

    Similar, re-code disable_timer to accept (and probably ignore) a
    parameter. Pass the result of "do stuff" to disable_timer.

    That should prevent the optimizer from moving the calls. At least, it
    had better not move them very far.

    Oh, and if it were me, I would disable (stop) the timer before reading
    it, not the other way around.

    Take a look at the assembler output to verify that you're getting what
    you want.

    ghelbig, Jun 9, 2008
    1. Advertisements

  3. chrisdekoh

    PFC Guest

    I've done that before, like this :

    int timer_value = * (volatile int *) TIMED_REG_ADDRESS;

    .. do stuff..

    timer_value = (* (volatile int *) TIMED_REG_ADDRESS) - timer_value;

    printf( "Elapsed cycles : %d", timer_value )
    It is the timer register which is incremented unbeknowst to gcc, not your
    int variable.
    Therefore it is the pointer to the timer register you read which must be
    declared (volatile int *), not the int variable (this is useless).

    I put the explicit code in the example above. You can use defines or
    functions to make it prettier.

    Note also that this handles wraparound :

    instant 1 : you get 0xFFFFFFFF from timer
    instant 2 : you get 0x00000001 from timer (it wrapped)

    (int)0xFFFFFFFF = -1
    (int)0x00000001 = 1

    Difference : 1 - (-1) = 2 cycles.
    int arithmetic handles the wraparound nicely for you.

    Note that if you set the timer to wraparound at some random value it
    won't work.

    "volatile int x" is a contradiction so gcc optimized away which is the
    expected behaviour.
    However *(volatile *)address has a very specific meaning which is what
    you want. Accesses to volatiles create barriers that gcc instruction
    reordering cannot skip so it will do what you want.
    PFC, Jun 9, 2008
  4. chrisdekoh

    cs_posting Guest

    How is it a contradiction?

    You can still get it's address and modify or examine it that way
    behind the compiler's back, so the compiler must assume that when you
    say it's volatile, you might mean it. Granted you want to be careful
    that you only do this during a time when the compiler is obligated to
    ensure that the variable exists, but that's not unreasonable within
    the scope, or when playing with a hardware-based debugger.
    cs_posting, Jun 9, 2008
  5. chrisdekoh

    Rich Webb Guest

    Pardon me for jumping in, but doesn't the above violate the
    constraints on all side-effects of previous expressions, and none of
    subsequent expressions, being evaluated at each sequence point?
    Rich Webb, Jun 9, 2008
  6. chrisdekoh

    cs_posting Guest

    Can you declare doSomething() itself to be volatile?
    cs_posting, Jun 9, 2008
  7. chrisdekoh

    PFC Guest

    Does the compiler know that doSomething() will never access any volatile
    variable ?
    (the generated assembly code was correct last time I checked).

    Anyway you can always put your timer code in functions. I don't think gcc
    reorders function calls ?...
    Sounds like a big shiny foot-gun.
    But you're right... C is so perverse, lol.
    PFC, Jun 10, 2008
  8. chrisdekoh

    David Brown Guest

    In answer to this and the other replies to my post:

    You are right that the compiler can only re-order "doSomething()" around
    volatile accesses if it knows that doSomething() does not make volatile
    accesses itself. But the compiler can be surprisingly knowledgeable
    about such things - if the doSomething() function is in the same source
    file, and you have at least some optimisations enabled, then it probably
    has this knowledge. In fact, in many common cases when you are writing
    test code like this, the doSomething() function is not only in the same
    file, but it is only used the one time, and the compiler may well inline
    the function. Thus even if it *does* use volatile accesses,
    non-volatile accesses in doSomething() can be shuffled around about and
    below the timer accesses. Just to add to the fun, the compiler might
    also figure out that parts of the code in doSomething() can be
    calculated at compile time, and eliminated from the object code.

    You can't make a function itself "volatile", but you can use the
    "noinline" function attribute to ensure it is not inlined - that's
    probably enough to make sure it is called properly.

    As has been said, check the assembly listing to make sure you are
    measuring the code you want to measure.
    David Brown, Jun 10, 2008
  9. chrisdekoh

    chrisdekoh Guest

    Hi all,
    thanks for your reply. I have tried some suggestions:

    this doesnt work.


    Hi David, you said this:
    how do you make an inline function? can kindly provide give a brief

    kindly help. I have already tried to dump out the assembly
    instructions from the compiled binary file beforehand using mb-
    objdump. I already know that the smart compiler reorders the timer
    enable and puts it some where at the bottom just before the read back
    of timer value and timer disabled.

    so i get something like this ( in C terms for easy reading):

    void main() {
    Xuint32 countvalue;

    // enable_timer(); <====== it dun do it here :(
    // do some stuff on Microblaze

    ... //some lines of code ....

    countvalue = readback_timer();
    enable_timer(); <====== the stupid compiler reshuffles the code
    //send count value back to serial port


    this is really disaster. :(
    kindly help

    chrisdekoh, Jun 10, 2008
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.