UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Adventurer
Adventurer
4,122 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
Scholar u4223374
Scholar
4,111 Views
Registered: ‎04-26-2015

Re: Why does BASE_ADDR/4?

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
Teacher muzaffer
Teacher
4,085 Views
Registered: ‎03-31-2012

Re: Why does BASE_ADDR/4?

@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
Scholar u4223374
Scholar
4,074 Views
Registered: ‎04-26-2015

Re: Why does BASE_ADDR/4?

@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
Adventurer
Adventurer
4,035 Views
Registered: ‎01-13-2015

Re: Why does BASE_ADDR/4?

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
Teacher muzaffer
Teacher
4,024 Views
Registered: ‎03-31-2012

Re: Why does BASE_ADDR/4?

@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