Tech Support > Computer Hardware > Microprocessors > how to prevent timer code firmware running on Microblaze from beingoptimised
how to prevent timer code firmware running on Microblaze from beingoptimised
Posted by chrisdekoh@gmail.com on June 9th, 2008


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


void main() {
Xuint32 countvalue;

enable_timer();
// do some stuff on Microblaze

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

countvalue = readback_timer();
disable_timer();

//send count value back to serial port
...

return1;
}

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.

Chris

Posted by ghelbig@lycos.com on June 9th, 2008


On Jun 9, 9:08 am, chrisde...@gmail.com wrote:
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.

G.

Posted by PFC on June 9th, 2008



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.

Posted by cs_posting@hotmail.com on June 9th, 2008


On Jun 9, 1:43 pm, PFC <li...@peufeu.com> wrote:

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.


Posted by David Brown on June 9th, 2008


PFC wrote:
This is a common misconception about volatile in C. The compiler cannot
change volatile accesses with respect to other volatile accesses - but
it can happily re-order non-volatile accesses around the volatile
access. Thus it is perfectly allowed to do "...do stuff..." either
before or after the two volatile reads of the timer. Even if you write
something like :

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

The compiler can call doSomething(), storing the result in a temporary
register, then read TIMED_REG_ADDRESS, store the result in "result",
then re-read TIMED_REG_ADDRESS - all without violating the volatile
requirements.

What's important is that you read the timer with a volatile access, then
call doSomthing() in a way that requires a volatile access at the start
and the end of the process, then re-read the timer with a volatile
access at the end.

Posted by Rich Webb on June 9th, 2008


On Mon, 09 Jun 2008 21:30:17 +0200, David Brown
<david.brown@hesbynett.removethisbit.no> wrote:

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 Norfolk, VA

Posted by cs_posting@hotmail.com on June 9th, 2008


On Jun 9, 3:30 pm, David Brown
<david.br...@hesbynett.removethisbit.no> wrote:
Can you declare doSomething() itself to be volatile?

Posted by PFC on June 10th, 2008



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.


Posted by Jack Klein on June 10th, 2008


On Mon, 9 Jun 2008 12:02:34 -0700 (PDT), cs_posting@hotmail.com wrote
in comp.arch.embedded:

Actually, the compiler can still optimize this away. To simplify:

void some_function(void)
{
volatile int x = func1();
/* do stuff */
x = func2();
return;
}

Since the variable, even though it is declared volatile, has automatic
storage duration and its address is never taken, it cannot possibly be
modified without the compiler's knowledge.

On the other hand, if it was defined at file scope, and therefore had
external linkage, that would be a different story.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.club.cc.cmu.edu/~ajo/docs/FAQ-acllc.html

Posted by David Brown on June 10th, 2008


PFC wrote:
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.

Posted by chrisdekoh@gmail.com on June 10th, 2008


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

1)
this doesnt work.

2)

Hi David, you said this:

how do you make an inline function? can kindly provide give a brief
example?

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
here
disable_timer();
//send count value back to serial port
...


return1;
}


this is really disaster.
kindly help

Chris



On Jun 10, 12:47*am, David Brown <da...@westcontrol.removethisbit.com>
wrote:

Posted by David Brown on June 10th, 2008


chrisdekoh@gmail.com wrote:
Making an inline function is easy (assuming you have the compiler flags
set to accept the C99 "inline" keyword, or are compiling C++ - I have no
idea which version of gcc the Microblaze uses):

static inline int doSomething(void) { }

If you are compiling with a reasonably recent version of gcc, and have
optimisations enabled, then any single-use static function will be
inlined automatically.

But what you really want here is a non-inlined function:

static int attribute((__noinline__)) doSomething(void) { }


Set your compiler flags to generate a listing file from the C code -
it's much easier to follow than using objdump. Alternatively, load the
code in the debugger and switch to mixed C and disassembly mode.

This looks like your enable_timer() and readback_timer() (and probably
disable_timer()) definitions are wrong - they should be using volatile
accesses to read and write the hardware timer registers. If they were
doing that correctly, the compiler would not reorder them.

mvh.,

David


Similar Posts