Reply by David Brown June 10, 20082008-06-10
chrisdekoh@gmail.com wrote:
> Hi all, > thanks for your reply. I have tried some suggestions: > > 1) >>>> int timer_value = * (volatile int *) TIMED_REG_ADDRESS; >>>> volatile int result = doSomething(); >>>> timer_value = (* (volatile int *) TIMED_REG_ADDRESS) - timer_value; > > this doesnt work. > > 2) > > Hi David, you said this: > >> 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. > > how do you make an inline function? can kindly provide give a brief > example? >
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) { }
> 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. >
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.
> > 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 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
Reply by June 10, 20082008-06-10
Hi all,
   thanks for your reply. I have tried some suggestions:

1)
> >> int timer_value =3D * (volatile int *) TIMED_REG_ADDRESS; > >> volatile int result =3D doSomething(); > >> timer_value =3D (* (volatile int *) TIMED_REG_ADDRESS) - timer_value;
this doesnt work. 2) Hi David, you said this:
> 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.
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(); <=3D=3D=3D=3D=3D=3D it dun do it here :( // do some stuff on Microblaze ... //some lines of code .... countvalue =3D readback_timer(); enable_timer(); <=3D=3D=3D=3D=3D=3D 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=A0am, David Brown <da...@westcontrol.removethisbit.com> wrote:
> PFC wrote: > > >> int timer_value =3D * (volatile int *) TIMED_REG_ADDRESS; > >> volatile int result =3D doSomething(); > >> timer_value =3D (* (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. > > > =A0 =A0 Does the compiler know that doSomething() will never access any > > volatile variable ? > > =A0 =A0 (the generated assembly code was correct last time I checked). > > > =A0 =A0 Anyway you can always put your timer code in functions. I don't > > think gcc reorders function calls ?... > > >>> =A0 =A0 =A0 =A0 "volatile int x" is a contradiction so gcc optimized a=
way
> >>> which is the > >>> expected behaviour. > > >> 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. =A0Granted 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. > > > =A0 =A0 Sounds like a big shiny foot-gun. > > =A0 =A0 But you're right... C is so perverse, lol. > > 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. =A0But 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. =A0In 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. =A0Thus even if it *does* use volatile accesses, > non-volatile accesses in doSomething() can be shuffled around about and > below the timer accesses. =A0Just 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.- Hide quoted text - > > - Show quoted text -
Reply by David Brown June 10, 20082008-06-10
PFC wrote:
> >> 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. > > 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 ?... > >>> "volatile int x" is a contradiction so gcc optimized away >>> which is the >>> expected behaviour. >> >> 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. > > Sounds like a big shiny foot-gun. > But you're right... C is so perverse, lol. >
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.
Reply by Jack Klein June 9, 20082008-06-09
On Mon, 9 Jun 2008 12:02:34 -0700 (PDT), cs_posting@hotmail.com wrote
in comp.arch.embedded:

> On Jun 9, 1:43 pm, PFC <li...@peufeu.com> wrote: > > > "volatile int x" is a contradiction so gcc optimized away which is the > > expected behaviour. > > 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.
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
Reply by PFC June 9, 20082008-06-09
> int timer_value =3D * (volatile int *) TIMED_REG_ADDRESS; > volatile int result =3D doSomething(); > timer_value =3D (* (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.
Does the compiler know that doSomething() will never access any volatil= e = 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 g= cc = reorders function calls ?...
>> "volatile int x" is a contradiction so gcc optimized away whi=
ch =
>> is the >> expected behaviour. > > 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.
Sounds like a big shiny foot-gun. But you're right... C is so perverse, lol.
Reply by June 9, 20082008-06-09
On Jun 9, 3:30 pm, David Brown
<david.br...@hesbynett.removethisbit.no> wrote:
> PFC wrote: > > >> In short, I am trying to keep tab of how fast various sections of code > >> takes to run using a timer running on Microblaze. > > > 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 ) > > >> volatile Xuint32 countvalue; > > > 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. > > 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.
Can you declare doSomething() itself to be volatile?
Reply by Rich Webb June 9, 20082008-06-09
On Mon, 09 Jun 2008 21:30:17 +0200, David Brown
<david.brown@hesbynett.removethisbit.no> 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.
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
Reply by David Brown June 9, 20082008-06-09
PFC wrote:
> >> In short, I am trying to keep tab of how fast various sections of code >> takes to run using a timer running on Microblaze. > > 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 ) > >> volatile Xuint32 countvalue; > > 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.
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.
Reply by June 9, 20082008-06-09
On Jun 9, 1:43 pm, PFC <li...@peufeu.com> wrote:

> "volatile int x" is a contradiction so gcc optimized away which is the > expected behaviour.
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.
Reply by PFC June 9, 20082008-06-09
> In short, I am trying to keep tab of how fast various sections of code=
> takes to run using a timer running on Microblaze.
I've done that before, like this : int timer_value =3D * (volatile int *) TIMED_REG_ADDRESS; .. do stuff.. timer_value =3D (* (volatile int *) TIMED_REG_ADDRESS) - timer_value; printf( "Elapsed cycles : %d", timer_value )
> volatile Xuint32 countvalue;
It is the timer register which is incremented unbeknowst to gcc, not yo= ur = int variable. Therefore it is the pointer to the timer register you read which must b= e = 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 =3D -1 (int)0x00000001 =3D 1 Difference : 1 - (-1) =3D 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.