Forum Discussion

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

A big bug?

Hi,

Here is a simple program:# include <stdio.h># include <io.h># include "sys/alt_stdio.h"# include "alt_types.h"# include "system.h"

alt_u8 SND[1100];

int main()

{

int i;

int prt1;

alt_u8 *p8;

alt_u32 *p32;

for(i=0;i<100;i++)SND=0;

snd[47]=9;

snd[46]=8;

p8=snd+48;

p32=(alt_u32 *)p8;

*p32=0x11223344;

prt1=(int)p32;

i=prt1 & 0x3;

uartprintf("\n\n\n\nsnd48 | 4=(%d:%d),%x,%x,%x,%x,%x,%x,\n",prt1,i,snd[46],snd[47],snd[48],snd[49],snd[50],snd[51]);

for(i=0;i<100;i++)snd=0;

SND[47]=9;

SND[46]=8;

p8=SND+50;

p32=(alt_u32 *)p8;

*p32=0x11223344;

prt1=(int)p32;

i=prt1 & 0x3;

UartPrintf("\n\n\n\nSND50 | 4=(%d:%d),%x,%x,%x,%x,%x,%x,\n",prt1,i,SND[46],SND[47],SND[48],SND[49],SND[50],SND[51]);

return 0;

}

and the printed results are as following:

___________________________________________

SND48 | 4=(67146460:0),8,9,44,33,22,11,

SND50 | 4=(67146462:2),8,9,44,33,22,11,

___________________________________________

while it should be as following:

___________________________________________

SND48 | 4=(67146460:0),8,9,44,33,22,11,

SND50 | 4=(67146462:2),8,9,00,00,44,33,

___________________________________________

Is there any person encountered this case? It seems that *P32 only can be used in the case of ((int)p32) % 4 =0, otherwise it will get an error result.

8 Replies

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

    No, there is no reason why misaligned memory cycles should do anything sensible.

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

    The problem is about understanding the requirements of the processor architecture. NIOS II reference handbook tells:

    --- Quote Start ---

    A data address is considered misaligned if the byte address is not a multiple of the width of the load or store instruction data width (four bytes for word, two bytes for half-word). Byte load and store instructions are always aligned so never take a misaligned address exception.

    --- Quote End ---

    The same is valid for most modern processors. x86 is an exception somehow.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Supporting misaligned transfers isn't as easy as it might seem.

    At first sight it might be thought adequate to perform 2 bus cycles with appropriate byte enabled and shifted data. This in itself is a moderate amount of logic - especially if you don't want to slow down the processor.

    The real issues arise when you get a memory error on the second cycle (eg a mmu 'page not present', or a TLB miss). This really requires a mid-instruction fault! For atomic 'compare and swap' type instructions it is all horrid and really not worth thinking about.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Hi,

    Thank you all of the persons replaied..

    As you mentioned that Nios does not support mismatch.Now I try to align SND[1100] to word in my actual project:# pragma align 4

    alt_u8 SND[1100];

    There was no warning during building and the address was 67389634 ( % 4=2) not my expected. Is there any way to solve this problem.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I don't understand what you are trying to achieve. SND has been already word aligned in your original code. A# pragma align can be used to enforce word align of structs (I think it's the default), but it can't change the placement of individual array elements. In an array of byte, the distance between succeeding elements will be always 1.

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

    Since SND[] is a byte array, it might have any alignment. You can force a larger alignment (with gcc) by writing:

    unsigned char SND __attribute__((aligned(32)));

    You can similarly reduce the alignment of structure members - gcc will generate code to read/write the separate bytes of the field.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Hi,

    My project is very complex ,it is migrated from DOS in which there are many such case.When building the project some of the arrays were aligned to word and some of them were aligned to short,so I have to force all of them align to word since Nios not support mismatch.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    You'll also find that the bytes get written in the opposite order (to i386).

    If you are trying to make protocol packets that will matter.

    You'll also need to ensure that the 32bit items within the packets are actually aligned - if not you'll need to do byte assignments.

    If your code had used structures (not magic constants) for the layouts you can do things like;

    #define aligned(n) __attribute__(aligned(n)))# define verify_size(type, size) typedef char verify_##type
    typedef unsigned it u32_align16 aligned(2);
    struct foo {
        unsigned short   a;
        u32_align_16     b;
    };
    /* verify size */
    verify_size(foo, 6);
    
    The compiler will then do two 16bit accesses for 'b'.

    If you need to byteswap data, add a combinatorial custom instruction to do it.