Atmel AVR Toolchain's fixed-points are broken?

Go To Last Post
16 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Compiling the following

void fi (int);
void fc (char);
int sf_to_int (short _Fract a) { return a; }
signed char f_to_schar (_Fract a) { return a; }
_Fract schar_to_f (signed char a) { return a; }
void f_to_fi (_Fract a) { return fi (a); }
void sf_to_fc (short _Fract a) { return fc (a); }

with

    avr-gcc conv.c -S -O -v
then the resulting assembler is:
sf_to_int:
	clr r25
	sbrc r23, 7
	com r25
	mov r24, r25
	ret

f_to_schar:
	clr r24
	sbrc r23, 7
	com r24
	ret

schar_to_f:
	lsl r24
	clr r25
	clr r24
	ret

f_to_fi:
	clr r25
	sbrc r23, 7
	com r25
	mov r24, r25
	rcall fi
	ret

sf_to_fc:
	clr r24
	sbrc r23, 7
	com r24
	rcall fc
	ret

In none of these functions r23 has a defined value. schar_to_f will always return 0, even for a = -1.0. Similar happens to wider types.

The reported version is:

    GNU C (AVR_8_bit_GNU_Toolchain_3.4.0_663) version 4.6.2 (avr)
Regards

avrfreaks does not support Opera. Profile inactive.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Even more trouble.

Compile the following small program with

    avr-gcc -mmcu=atmega8 bug.c -Os -lm
#include 
#include 

volatile unsigned short accum val = 1.0uhk;

int main (void)
{
    if ((float) val > 2.0f)
        abort();
        
    exit (0);
}

You'll observe two problems

  1. If you run it, it will hit abort. Reason is a pasto in __fractuhasf, cf. this patch against 4.5.1 for example. The tool chain is patched against 4.6.2 as you can see in the previous post, but the typo is still there.
  2. Even when linking with -lm the float routines from libgcc are used instead of the hand-optimized routines from AVR-Libc. Reason in that __fract[u]{q|h|s]}{a|q}sf from the patch refer to float routines and the linker resolves them in libgcc, not in AVR-Libc.

avrfreaks does not support Opera. Profile inactive.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Seriously: Atmel should hire you.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Unfortunately there are more problems: __fractsfhq and __fractsfqq are also wrong, they convert from float to fract resp. to short fract.

I am currently attempting to port the fixed-point support to avr-gcc 4.8 and thought that because the code was releases in several distributions, it has experienced some review, testing and increased reliability by means of every-day use by tool chain users.

So it's more work than just adapting the sources because the patches are pretty much outdated as avr-gcc evolves.

It's would be a pity if Sean's work would rot that way, but I also feeling stupid from time to time to do Atmel's home work...

Does anyone use built-in fixed-point arithmetic at all? It appears I am just adding thousands of lines of dead code to the compiler, just rendering it bigger, more complicated and less stable...

avrfreaks does not support Opera. Profile inactive.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

SprinterSB wrote:
Does anyone use built-in fixed-point arithmetic at all?
Yes but not on AVR (yet). It would aid Atmel to support ISO/IEC TR 18037 (Embedded C standard).

"Dare to be naïve." - Buckminster Fuller

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If it hasn't been done already,
perhaps fixed point could be implemented as C++ classes.
That would, of course, remove some opportunities for optimization.

International Theophysical Year seems to have been forgotten..
Anyone remember the song Jukebox Band?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

JohanEkdahl wrote:
Seriously: Atmel should hire you.
+1 to contract him.

"Dare to be naïve." - Buckminster Fuller

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Does anyone use built-in fixed-point arithmetic at all?

Johann! I am a potential user of fixed-point, but have not yet adopted it.

Yes, it would be a shame if Sean's work was to rot away.

I am not in a position, ignorance and lack of time, to do development on this stuff. Testing might be another matter. Is there any infrastructure in GCC to set up and automate tests?

I could go looking for it myself, but a himt/spoiler would help.

I consider myself quite a seasoned C programmer, but one thing that is still both mystical, magical and very scary is the inner workings of GCC, and stuff like the "auto-tools", "configure", patching etc. I have considered trying to build avr-gcc myself, just for the fun of it, but always becomes overwhelmed by the amount of things I do not know/understand. You have my deepest admiration.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

JohanEkdahl wrote:
Is there any infrastructure in GCC to set up and automate tests?
GCC comes with its own testsuite that needs the DejaGNU harness. A convenient way to run execution test is the avrtest hosted with WinAVR, see the README.

The fixed point tests are located in gcc.dg/fixed-point. The only problem there is convert.c which is much tooo big to be executed on ATmega128. Someone will have to split that test case into more manageable parts.

However, the main issue is not running these tests, it's mainly on source level. The sources badly need review and better comments. For example, the second problem mentioned above was triggered by code that originally read

        .global __fractsfhq
        .func __fractsfhq
__fractsfhq:
        subi    r25, -15        ; adjust exponent
        subi    r24, 128
        rjmp    __fixsfsi
.endfunc

It's obvious from the source that something /must/ go wrong and how a test case looks like that triggers the bug, and how a fix looks like:

#define exp_lo(N)  hlo8 ((N) << 23)
#define exp_hi(N)  hhi8 ((N) << 23)
...

DEFUN __fractsfhq
    ;; Multiply with 2^{16+15} to get a HQ result in r25:r24
    ;; resp. with 2^31 to get a SQ result in r25:r22
    subi    r24, exp_lo (-31)
    sbci    r25, exp_hi (-31)
    XJMP    __fixsfsi
ENDF __fractsfhq

It's much easier on that level than to run a 100k program that hits abort somewhere.

In order to test individual routines, I don't use the test suite harness because it is not easy to test a new implementation of, say 32-bit multiplication against an existing one. It's much more lightweight to factor out the routine(s) and test them in a small incubator environment like

#define __zero_reg__ r1
#define __tmp_reg__ r0
#define __SREG__ 0x3f
#if defined (__AVR_HAVE_SPH__)
#define __SP_H__ 0x3e
#endif
#define __SP_L__ 0x3d
#define __RAMPZ__ 0x3B
#define __EIND__  0x3C

	.macro	mov_l  r_dest, r_src
#if defined (__AVR_HAVE_MOVW__)
	movw	\r_dest, \r_src
#else
	mov	\r_dest, \r_src
#endif
	.endm

	.macro	mov_h  r_dest, r_src
#if defined (__AVR_HAVE_MOVW__)
	; empty
#else
	mov	\r_dest, \r_src
#endif
	.endm

.macro	wmov  r_dest, r_src
#if defined (__AVR_HAVE_MOVW__)
    movw \r_dest,   \r_src
#else
    mov \r_dest,    \r_src
    mov \r_dest+1,  \r_src+1
#endif
.endm

#if defined (__AVR_HAVE_JMP_CALL__)
#define XCALL call
#define XJMP  jmp
#else
#define XCALL rcall
#define XJMP  rjmp
#endif

.macro DEFUN name
.global \name
.func \name
\name:
.endm

.macro ENDF name
.size \name, .-\name
.endfunc
.endm

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; Negate a 2-byte value held in consecutive registers
.macro	neg2  reg
    com     \reg+1
    neg     \reg
    sbci    \reg+1, -1
.endm

;; Negate a 4-byte value held in consecutive registers
.macro	neg4  reg
    com     \reg+3
    com     \reg+2
    com     \reg+1
.if \reg >= 16
    neg     \reg
    sbci    \reg+1, -1
    sbci    \reg+2, -1
    sbci    \reg+3, -1
.else
    com     \reg
    adc     \reg,   __zero_reg__
    adc     \reg+1, __zero_reg__
    adc     \reg+2, __zero_reg__
    adc     \reg+3, __zero_reg__
.endif
.endm

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

#define exp_lo(N)  hlo8 ((N) << 23)
#define exp_hi(N)  hhi8 ((N) << 23)

#define L_mulusa3
#include "lib1funcs-fixed.ss"
#undef L_mulusa3

#define L_mulsa3
#include "lib1funcs-fixed.ss"
#undef L_mulsa3

#define L_umulsidi3
#include "lib1funcs-umulsidi3.ss"
#undef L_umulsidi3

...

This is basically the top of lib1funcs.S so that you can build routines and use them by means of inline assembler in small torture programs

static uint32_t __attribute__((unused,used))
A_mulusa3 (uint32_t a, uint32_t b)
{
    uint64_t ab = (uint64_t) a * b;
    return ab >> 16;
}

static uint32_t __attribute__((unused,used))
B_mulusa3 (uint32_t a, uint32_t b)
{
    register uint32_t ra asm ("16") = a;
    register uint32_t rb asm ("20") = b;
    register uint32_t rc asm ("24");
    
    asm ("%~call __mulusa3"
            : "=r" (rc) : "r" (ra), "r" (rb) : "15");
    return rc;
}

That way everything is in a small, ordinary C/asm program. No test suite is needed, no GCC sources, no building GCC. Only after the algorithm performs well (code size, speed, correctness even in corner cases, proper coding style and source comments) it's integrated in GCC and run against the test suite.

Quote:
I consider myself quite a seasoned C programmer, but one thing that is still both mystical, magical and very scary is the inner workings of GCC, and stuff like the "auto-tools", "configure", patching etc. I have considered trying to build avr-gcc myself, just for the fun of it, but always becomes overwhelmed by the amount of things I do not know/understand.
Well; do you understand your computer? I don't understand my computer. I don't even understand a stone. I don't know enough of quantum physics to understand a stone, why it is solid, why it is brown or gray, why it is hard or soft. Yet I have a basic understanding of a stone and how I can handle it, how it feels like, what I can do with it and what not.

I don't even understand my conmputer on the transistor level. Give me a layout scheme of a computer with all it's transistors things, and I don't even know if it's a computer or modern art or tokio's subway. No Idea how all these transistors work together to make Clippy speak to me.

If you try to understand "Was die Welt im Innersten zusammenhält" that's really ambitious...

avrfreaks does not support Opera. Profile inactive.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Johann!

Thank you for the thorough post. I will read it again during weekend to see if I get the finer details of what you write, and ponder if I can contribute.

Me paying back to the avr-gcc community is way overdue, so if it is within my abilities and time I will have a go at it. E.g. the splitting up of tests might be feasible..

I see that the fixed-point tests are not AVR specific (I should have realized that from the start) but GNU-generic. This means that one could "harness" some stuff and test it on a Linux- or Windows-host as well as wellas for an AVR, and expect the same results down to the last bit, right?

Quote:
Well; do you understand your computer?

I understand it more than well enough to use it. (No-one really needs to know the inner workings of a full-adder in order to use a computer, but I still know (or knew) that. One of my all-time favourite books is Tannenbaums "Computer Architecture - a Structured Approach).

Re GCC I do not understand the things involved well enough to even talk about building the tool chain. As I said, every time I try to approach that subject I am overwhelmed.

A rock is solid because else you'd call it "lava".. :wink:

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

JohanEkdahl wrote:
I see that the fixed-point tests are not AVR specific (I should have realized that from the start) but GNU-generic. This means that one could "harness" some stuff and test it on a Linux- or Windows-host as well as for an AVR, and expect the same results down to the last bit, right?
No :-)

The fixed point widths are implementation defined, same for their integral and fractional parts. Same for overflow of the non-saturated operations (undefined, modular warp, saturate, ...). Same for the rounding (to zero, to +oo, to -oo, nearest, undefined). Same for the magnitude of the rounding error (within 2 ±LSBs from the exact result, if I understand TR 18037 correctly).

And of course, only modulo bugs in the implementation. I broke convert.c apart and it can be executed now, but it does not pass so there are more bugs to fix...

Quote:
Re GCC I do not understand the things involved well enough to even talk about building the tool chain. As I said, every time I try to approach that subject I am overwhelmed.
Building is not too complicated; the build scripts around are just frightening scary. You just need a couple of commands, 60% of which are "make" or "make install". You don't need to be root, you don't need to sudo, ...

If you feel to ask questions, a mailing list like avr-gcc-list is a much more convenient place.

  • You can write % in the code without anyone getting a heart attack.
  • You can link to documentation or other helpful pieces of information without proving that you are human.
  • You can attach code without obfuscating it as zip or whatever.
  • You can quote without using BBcode or other weird stuff. Just quote.
  • You can download attachments without their MIME-type being messed up or browser pissed off.
  • You have real tree-like threads.
  • You can see text attachments like patches without downloading them and you can easily quote parts thereof to comment on it.
  • You can use your favourite e-mail program. No annoying advertisements, no blinking graphics, no annoying styles and designs, ...
  • It's focused on the AVR tools, not on developing with these tools, thus it's more appropriate for things below the surface.
  • Many, many more...

avrfreaks does not support Opera. Profile inactive.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OT:

Quote:
No annoying advertisements

Locate the "Maximize" link at the top of every AVRfreaks page. Click.

No more ads. No more meaningless green goo occupying 40 percent of your browser.

Quote:
tree-like threads

Isn't that an oxymoron? :wink:

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

JohanEkdahl wrote:
SprinterSB wrote:
tree-like threads
Isn't that an oxymoron? :wink:
That's that??? Moron-oxide?

avrfreaks does not support Opera. Profile inactive.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

LOL! :D

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

FYI, avr-gcc built-in fixed-point support according to ISO/IEC TR18037 is upstream to the official FSF GCC code base now.

Anybody who wants can test it or contribute more optimizations and tweaks based on it. You need GCC trunk SVN 190644 or newer.

Many thanks to Sean for this work.

avrfreaks does not support Opera. Profile inactive.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you!

"Dare to be naïve." - Buckminster Fuller