Help - Search - Members - Calendar
Full Version: Read problem with shared memory
Impulse Support Forums > Impulse Forums > Impulse C Support Forum
neo
Hi,

I'm using a Virtex-II Pro with CoDeveloper 3.10.b.9 under Windows XP and a shared Memory at the OPB Bus (0x50000000 - 0x5000ffff).

Using the shared memory from software side is no problem. But when I generate hardware and try to access from there, it doesn't always do, what I want. Writing works fine but reading delivers only the right data, when I read from a address with a multiple of 4. Here is a list with the values for offset and size (in byte) and the addresses for the data, I realy get.

Offset, Size -> Adresses of realy readed data
4, 1 -> 4
5, 1 -> 4
6, 1 -> 4
7, 1 -> 4
8, 1 -> 8

4, 2 -> 4, 5
5, 2 -> 4, 5
6, 2 -> 4, 5
7, 2 -> 4, 9
8, 2 -> 8, 9

4, 3 -> 4, 5, 6
5, 3 -> 4, 5, 6
6, 3 -> 4, 5, 10
7, 3 -> 4, 9. 10
8, 3 -> 8, 9, 10

4, 4 -> 4, 5, 6, 7
5, 4 -> 4, 5, 6, 11
6, 4 -> 4, 5, 10, 11
7, 4 -> 4, 9, 10, 11
8, 4 -> 8, 9, 10, 11

So reading only works for offset 4 and 8. Is this a bug or a feature? If this behaviour is intended, the only way to use the shared memory would be to use always data sizes of 32bit and offset addresses with a multiple of 4. This is a realy waste of memory and necessary memory accesses.

Hope somebody has a solution for my problem.
etrexel
QUOTE (neo @ Aug 13 2008, 09:49 AM) *
Hi,

I'm using a Virtex-II Pro with CoDeveloper 3.10.b.9 under Windows XP and a shared Memory at the OPB Bus (0x50000000 - 0x5000ffff).

Using the shared memory from software side is no problem. But when I generate hardware and try to access from there, it doesn't always do, what I want. Writing works fine but reading delivers only the right data, when I read from a address with a multiple of 4. Here is a list with the values for offset and size (in byte) and the addresses for the data, I realy get.

Offset, Size -> Adresses of realy readed data
4, 1 -> 4
5, 1 -> 4
6, 1 -> 4
7, 1 -> 4
8, 1 -> 8

4, 2 -> 4, 5
5, 2 -> 4, 5
6, 2 -> 4, 5
7, 2 -> 4, 9
8, 2 -> 8, 9

4, 3 -> 4, 5, 6
5, 3 -> 4, 5, 6
6, 3 -> 4, 5, 10
7, 3 -> 4, 9. 10
8, 3 -> 8, 9, 10

4, 4 -> 4, 5, 6, 7
5, 4 -> 4, 5, 6, 11
6, 4 -> 4, 5, 10, 11
7, 4 -> 4, 9, 10, 11
8, 4 -> 8, 9, 10, 11

So reading only works for offset 4 and 8. Is this a bug or a feature? If this behaviour is intended, the only way to use the shared memory would be to use always data sizes of 32bit and offset addresses with a multiple of 4. This is a realy waste of memory and necessary memory accesses.

Hope somebody has a solution for my problem.

Hi,
Memory accesses are a combination of the co_memory interface making a request over the OPB bus, the bridge (if present) transferring the request, and the memory controller being accessed fulfilling the request. Memory controllers tend to be cache line orientated for a CPU and it is the fetching unit of the CPU and/or cache that allows for unaligned memory accesses. The co_memory interface is more "literal" in terms of requests and bus-width orientated so it does not act like a CPU in terms of retrieving cache lines and re-aligning data as necessary.
As for the "jumps" in the "really read addresses", that doesn't look completely correct. Could you please post the test code doing the accesses?

Ed
neo
QUOTE (etrexel @ Aug 13 2008, 07:29 PM) *
Hi,
Memory accesses are a combination of the co_memory interface making a request over the OPB bus, the bridge (if present) transferring the request, and the memory controller being accessed fulfilling the request. Memory controllers tend to be cache line orientated for a CPU and it is the fetching unit of the CPU and/or cache that allows for unaligned memory accesses. The co_memory interface is more "literal" in terms of requests and bus-width orientated so it does not act like a CPU in terms of retrieving cache lines and re-aligning data as necessary.
As for the "jumps" in the "really read addresses", that doesn't look completely correct. Could you please post the test code doing the accesses?

Ed


Thanks for reply. I wrote a little test application that I have attached to this post. The output on the console is the following:

CODE
Write test data to shared memory.
0 1 2 3 4 5 6 7 8 9 a b

Read test data from software side.
Offset, Size -> read data
0, 4 -> 0 1 2 3
1, 4 -> 1 2 3 4
2, 4 -> 2 3 4 5
3, 4 -> 3 4 5 6
4, 4 -> 4 5 6 7
5, 4 -> 5 6 7 8

Read test data from hardware side.
Offset, Size -> read data
0, 4 -> 0 1 2 3
1, 4 -> 0 1 2 7
2, 4 -> 0 1 6 7
3, 4 -> 0 5 6 7
4, 4 -> 4 5 6 7
5, 4 -> 4 5 6 b


So, if it is just an alignment problem when I read, why I don't have the problem at writing?
GreenMountain
QUOTE (neo @ Aug 13 2008, 02:03 PM) *
Thanks for reply. I wrote a little test application that I have attached to this post. The output on the console is the following:

CODE
Write test data to shared memory.
0 1 2 3 4 5 6 7 8 9 a b

Read test data from software side.
Offset, Size -> read data
0, 4 -> 0 1 2 3
1, 4 -> 1 2 3 4
2, 4 -> 2 3 4 5
3, 4 -> 3 4 5 6
4, 4 -> 4 5 6 7
5, 4 -> 5 6 7 8

Read test data from hardware side.
Offset, Size -> read data
0, 4 -> 0 1 2 3
1, 4 -> 0 1 2 7
2, 4 -> 0 1 6 7
3, 4 -> 0 5 6 7
4, 4 -> 4 5 6 7
5, 4 -> 4 5 6 b


So, if it is just an alignment problem when I read, why I don't have the problem at writing?


Hi,

I think it is an alignment mismatch problem.

The shared memory alignment should always match local array alignment, (memory address & 3) == (array offset & 3).

Does the following example code work?


--Scott

CODE

co_uint8 SMData[12];

for(i=0; i<6; i++)
{
co_memory_readblock(SM, i, &SMData[i], 4*sizeof(co_uint8));
StreamData = ((co_uint32)SMData[i]) | (((co_uint32)SMData[i+1])<<8) | (((co_uint32)SMData[i+2])<<16) | (((co_uint32)SMData[i+3])<<24);
co_stream_write(HW2SW, &StreamData, sizeof(co_uint32));
}
neo
That works right but according to the Function Reference of the CoDeveloper User Guide it's totally wrong and should produce an error when building HDL. However surprisingly it doesn't.

CODE

// UNSUPPORTED: The third argument 'buf' must be strictly an array type
// If the following code were in a hardware process, CoBuilder would produce
// this error message when building HDL:
// "Expecting an array in 3rd argument of co_memory_readblock"
for ( i = 0; i < 32; i++ ) {
co_memory_readblock(mem, 0, &data[i], 1);
}


Thanks for that but I will restrict my code to the official allowed variants. Your trick perhaps doesn't work in the next versions of CoDeveloper.

neo
etrexel
QUOTE (neo @ Aug 19 2008, 09:14 AM) *
That works right but according to the Function Reference of the CoDeveloper User Guide it's totally wrong and should produce an error when building HDL. However surprisingly it doesn't.

CODE

// UNSUPPORTED: The third argument 'buf' must be strictly an array type
// If the following code were in a hardware process, CoBuilder would produce
// this error message when building HDL:
// "Expecting an array in 3rd argument of co_memory_readblock"
for ( i = 0; i < 32; i++ ) {
co_memory_readblock(mem, 0, &data[i], 1);
}


Thanks for that but I will restrict my code to the official allowed variants. Your trick perhaps doesn't work in the next versions of CoDeveloper.

neo

Hi,
Actually the use of offsets for array arguments is a new feature, albeit undocumented yet.
And of course, if your application requires something similar to the test code where 32-bit values are reconstructed from 8-bit values read from a co_memory, it'll be far more efficient to access 32-bit values from the co_memory.

Ed
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Invision Power Board © 2001-2010 Invision Power Services, Inc.