Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
11 years ago

NIOS II Structure Casting w/ Opt. (-O3)

I recently enabled optimization on my NIOS II software (custom telnet server + webserver) and I'm experiencing unexpected behavior. I suspect memory corruption and alignment issues, but I can't seem to get this resolved. The software does work reliably when optimization is disabled.

One of my issues is when type casting a data word (unsigned int) to a bit-wise data structure (word aligned) as shown below. This is performed on the stack, so I'm not sure what the problem is. The register value is valid (val), and so is the bitfield when manually masking & shifting. I also verified the structure is packed (no padding, sizeof(version_reg_t)=4), and adding the following "__attribute__((packed, aligned(4)))" did not fix this issue.

typedef struct{

uint32_t ver_build_rev :8;

uint32_t ver_fpga_id :8;

uint32_t ver_major_rev :8;

uint32_t ver_minor_rev :8;

}version_reg_t;

uint32_t val = IOWR_32DIRECT(0, VERSION_ADDR_OFFSET);

version_reg_t* p_reg = (version_reg_t*)&val;

In my makefile, I'm only using the following APP_MAKEFILE_FLAGS:

--set APP_CFLAGS_OPTIMIZATION -O3

Any help would be appreciated.

2 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Look at the assembler code generated for your code.

    I had a case on an x86 where bit-field access resulted in byte-based assembly instructions, even though the bit-field is described using integers.

    In your case, since each bit-field is actually a byte, it might be less ambiguous (in the sense of undefined compiler operation) to use an array of bytes. You can use a union to make the array accessible as either a single integer or four single byte fields.

    Cheers,

    Dave
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Write valid C! - see 'strict aliasing'.

    The compiler is allowed to (and will) reorder memory accesses if the types differ (and aren't 'char') even if it is obvious from the source code that they refer to the same physical memory.

    If you use a 'union' then you'll get the code you expect. The compiler will also sometimes use shifts and optimise away the memory access itself.

    I'd not thought that int:8 might give a byte-sized item that the compiler doesn't have to assume might alias all other C types.