Question

I have an array and a variable declared like this

NextPacketRegister     : array (1 .. Natural (Size)) of Unsigned_32;  
PacketBufferPointer    : Unsigned_32;  

for PacketBufferPointer'Address use To_Address (SPW_PORT_0_OUT_REG_ADDR);

for NextPacketRegister'Address use To_Address (16#A000_0000# + Integer_Address (PacketBufferPointer));

PacketBufferPointer points to an HW registers that you access thru the PCI of our board. NextPacketRegister uses this register's value + 16#A000_0000#

The thing is everytime I access NextPacketRegister, behind the scene I perform a PCI access, these access are very slow and we are trying to remove this limitation.

But I can't seem to find a way to modify NextPacketRegister'Address during runtime (I'd like to read ONCE the PacketBufferPointer register and then add this value + 16#A000_0000# only once so I don't have to perform PCI access everytime.

I looked around but I have no clue how I could achieve this.

Was it helpful?

Solution

That is correct; if you use for ...'address use to overlay an object at a specific address, you cannot change it later.

Generally I try to avoid overlays. What you show is one drawback to them. Another is that if the object has any parts that require initialization, they will be reinitialized every time the object is elaborated.

One thing I do have to ask up front though: This looks like a device driver. If you don't like the hit from going to the PCI bus then, fine. The obvious way around your problem of course is to just read the object into a temporary variable and use that when you don't want to hit the PCI bus. But obviously when you do that you are no longer reading directly from the device, and thus won't see changes it made to its memory-mapped registers (and your changes won't go straight to those memory-mapped registers). That's what you want, right? Ada contains no magic to allow you to get data on and off the PCI bus without hitting the PCI bus.

It almost looks like you are thinking that this line:

for NextPacketRegister'Address use To_Address (16#A000_0000# + Integer_Address (PacketBufferPointer));

Means: "Every time I access NextPacketRegister, go find the value of PacketBufferPointer and overlay it where it happens to be right now". That is not the case. This will only happen once when your declaration is processed. Thereafter, every access to something like NextPacketRegister[12] will go to the same place, without any access to PacketBufferPointer.

Another way would be to use pointers and Unchecked_Conversion. That's generally my preferred solution for overlays. It looks hairer, but what you are doing is hairy, so it should look that way. Also, it doesn't perform initializations on the overlaid memory area. I suppose that could be a bad thing though, if you count on those. Of course overlaying this way could cause an access to PacketBufferPointer, if you want. You'd have control over it depending on how you code it.

Since you asked about pointers, in this case I think you have a very valid case for using the package System.Address_to_Access_Conversions. I don't have the compiler handy, but I think it would go something like this:

type Next_Packet_Array is array (1 .. Natural (Size)) of Unsigned_32;
package Next_Packet_Array_Convert is new System.Address_To_Access_Conversions
   (Next_Packet_Array);
Synced_Next_Packet_Address : System.Address;

Now when you "sync", I guess you'd want to hit that PacketBufferPointer to get the register value (as a SYSTEM.ADDRESS), and save it into a variable for later use:

Synced_Next_Packet_Address = 16#A000_0000# + Integer_Address (PacketBufferPointer);

And when you want to access the Next_Packet_Array, it would be something like this: Next_Packet_Array_Convert.To_Pointer (Synced_Next_Packet_Address).all

OTHER TIPS

Make a structure (array of buffers ? ) that is what your set of packet buffers looks like and sit that at the address of the start of the array.

read the array index from the register.

you can write C in any language, even Ada.

At least it works and you get some sensible bounds checks.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top