cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Highlighted
Adventurer
Adventurer
4,382 Views
Registered: ‎01-13-2015

Why does BASE_ADDR/4?

I'm just testing HLS code to implement AXI master in HLS, and I refer to AR# 59228, https://www.xilinx.com/support/answers/59228.html

in that code, the address is divided by 4 like memcpy(buff, m+(BASE_ADDR/4), N*sizeof(uint32));.

Can anyone tell me why?

 

Thank you

0 Kudos
5 Replies
Highlighted
Advisor
Advisor
4,371 Views
Registered: ‎04-26-2015

m is a pointer to a 32-bit value, so m + 1 is actually four bytes further along in memory than m was.

 

BASE_ADDR is an address measured in bytes. Since adding 1 to m effectively shifts four bytes, you need to divide the number of bytes by four before adding. This way, if BASE_ADDR = 4, BASE_ADDR / 4 = 1, and m + BASE_ADDR/4 will be m + 1 (which, as above, is four bytes further along than m).

0 Kudos
Highlighted
Teacher
Teacher
4,345 Views
Registered: ‎03-31-2012

@u4223374 but this doesn't explain why it's not "m*4 + BASE_ADDR". memcpy addresses are supposed to be byte addresses, not element counts, no?

- Please mark the Answer as "Accept as solution" if information provided is helpful.
Give Kudos to a post which you think is helpful and reply oriented.
0 Kudos
Highlighted
Advisor
Advisor
4,334 Views
Registered: ‎04-26-2015

@muzaffer

 

Good point, there's a bit more complexity to it.

 

When you add a value (N) to a uint32*, the actual result is that the byte address of the uint32* is moved by 4*N bytes (ie so you move N uint32s further along in memory).

 

In this case, they want to move the address by BASE_ADDR bytes. When they add BASE_ADDR/4 to m, the actual resulting address is:

m + (BASE_ADDR/4)*4

An alternative would be to cast to uint8* first, so that adding one to it is exactly the same as shifting by one byte.

((uint8*) m) + BASE_ADDR

This should yield exactly the same result.

0 Kudos
Highlighted
Adventurer
Adventurer
4,295 Views
Registered: ‎01-13-2015

I understand what you guys are saying, but I think that BASE_ADDR should not be divided by 4.

Is there any references of memcpy() function with explanation of why that address has to be unit of 4-byte?

And here below is my quick codes 

Between A code and B code, which one is correct one???

 

//***** Target Board: ZC702 Board *****
#define SRC_BASE_ADDR    0x30000000 //physical memory address for image source
#define DST_BASE_ADDR    0x30096000 //physical memory address for frame buffer
#define BYTE_P_PIXEL    2
#define HSIZE_IMAGE    640
#define VSIZE_IMAGE    480
#define SIZE_IMAGE    HSIZE_IMAGE*VSIZE_IMAGE //307200=0x4B000
#define LEN_IMAGE    SIZE_IMAGE*BYTE_P_PIXEL //614400=0x96000
#define SIZE_BURST    4
#define LEN_BURST    SIZE_BURST*4
#define LOOP_CNT    LEN_IMAGE/(LEN_BURST)

 

 

int i=0;


//================ Code A ================
for(i=0; i<LOOP_CNT; i++){
    memcpy( DST_BASE_ADDR+(i*LEN_BURST) /*Dst*/,
                    SRC_BASE_ADDR+(i*LEN_BURST) /*Src*/,
                    LEN_BURST/*Len in 4-byte*/);
}

 

//================ Code B ================
for(i=0; i<LOOP_CNT; i++){
    memcpy( (DST_BASE_ADDR+(i*LEN_BURST))/4 /*Dst*/,
                    (SRC_BASE_ADDR+(i*LEN_BURST))/4 /*Src*/,
                    LEN_BURST/*Len in 4-byte*/);
}

 

 

Thank you

 

0 Kudos
Highlighted
Teacher
Teacher
4,284 Views
Registered: ‎03-31-2012

@emotaworld 

>> I understand what you guys are saying, but I think that BASE_ADDR should not be divided by 4.

Those two statements are contradictory ;-)

 

>> Is there any references of memcpy() function with explanation of why that address has to be unit of 4-byte?

 

This is not about memcpy but a C language design feature where pointers to different objects are incremented by the size of the object to which they point, how arrays & pointers are the same thing and another feature called casting. To wit, assume uint32 * p = x, then the next object is at p+1 (not p+sizeof(uint32)). You can see this as uint32 pa[100]; pa[1] is one after pa[0] but the &pa[1] = &pa[0] + 4.

So if you have a uint32* you need to add object counts to it to advance it, not byte offsets and when you cast it to a char* the compiler does the proper multiplication for you.

 

PS the address does not have a unit of 4-byte but sizeof(uint32). If your axi master had 64 bit data path, you would need to divide by 8.

- Please mark the Answer as "Accept as solution" if information provided is helpful.
Give Kudos to a post which you think is helpful and reply oriented.
0 Kudos