comp.lang.ada
 help / color / mirror / Atom feed
* copying data between memory locations
@ 2007-09-03  8:59 jef.mangelschots
  2007-09-03 10:38 ` Martin Krischik
                   ` (5 more replies)
  0 siblings, 6 replies; 10+ messages in thread
From: jef.mangelschots @ 2007-09-03  8:59 UTC (permalink / raw)


In our current design, we have a package that maintains a list of
descriptors of various buffers in the application. We don't want to
know their datatypes or how to write data into them. We only want to
maintain a physical address of them and use that address to directly
write data into these buffers (this data comes out incoming packets
over the network).

In C, this is very straightforward and use the address as a pointer
and simply copy the packet into the memory location.
I can't figure out a way to do this in Ada (at least not Ada83).

suppose the following:

type BUFFER_DETAILS_RECORD is
record
    num_bytes : integer;
    start_address : system.address;
end record;
type BUFFER_DETAILS_ARRAY_TYPE is array(1..2) of
BUFFER_DETAILS_RECORD;
BUFFER_DETAILS : constant BUFFER_DETAILS_ARRAY_TYPE :=
BUFFER_DETAILS_ARRAY_TYPE'(1 => (num_bytes => 100, start_address =>
16#123# ),  1 => (num_bytes => 200, start_address => 16#456# ));

procedure insert_block(idx : in integer; num_bytes : in integer;
offset : in integer; data : BYTE_ARRAY_TYPE) is
begin
   ??? how do I copy the content of data into the memory pointed to by
BUFFER_DETAILS(idx).start_address + offset
end;




^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: copying data between memory locations
  2007-09-03  8:59 copying data between memory locations jef.mangelschots
@ 2007-09-03 10:38 ` Martin Krischik
  2007-09-04 15:57   ` Adam Beneschan
  2007-09-03 11:09 ` Niklas Holsti
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 10+ messages in thread
From: Martin Krischik @ 2007-09-03 10:38 UTC (permalink / raw)


jef.mangelschots@gmail.com schrieb:

> In our current design, we have a package that maintains a list of
> descriptors of various buffers in the application. We don't want to
> know their datatypes or how to write data into them. We only want to
> maintain a physical address of them and use that address to directly
> write data into these buffers (this data comes out incoming packets
> over the network).
> 
> In C, this is very straightforward and use the address as a pointer
> and simply copy the packet into the memory location.

straightforward and highly dangerous.

> I can't figure out a way to do this in Ada (at least not Ada83).

You just have not found the right features yet. Suggested reading:

http://en.wikibooks.org/wiki/Ada_Programming/Types/access#Access_vs._System.Address
http://en.wikibooks.org/wiki/Ada_Programming/Type_System#Address_conversion
http://en.wikibooks.org/wiki/Ada_Programming/Type_System#Overlays

and from the reference manual:

http://www.adaic.com/standards/05rm/html/RM-13-7-2.html#I4643
http://www.adaic.com/standards/05rm/html/RM-13-3.html#I4496

As you can see (once you read the articles) you have even got two
options open and now you are left with choosing the right one ;-).

Martin

-- 
mailto://krischik@users.sourceforge.net
Ada programming at: http://ada.krischik.com



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: copying data between memory locations
  2007-09-03  8:59 copying data between memory locations jef.mangelschots
  2007-09-03 10:38 ` Martin Krischik
@ 2007-09-03 11:09 ` Niklas Holsti
  2007-09-03 16:26 ` Steve
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 10+ messages in thread
From: Niklas Holsti @ 2007-09-03 11:09 UTC (permalink / raw)


jef.mangelschots@gmail.com wrote:
> In our current design, we have a package that maintains a list of
> descriptors of various buffers in the application. We don't want to
> know their datatypes or how to write data into them. We only want to
> maintain a physical address of them and use that address to directly
> write data into these buffers (this data comes out incoming packets
> over the network).
> 
> In C, this is very straightforward and use the address as a pointer
> and simply copy the packet into the memory location.

Easy to code, hard to debug, ... as you probably know :-)

> I can't figure out a way to do this in Ada (at least not Ada83).
> 
> suppose the following:
> 
> type BUFFER_DETAILS_RECORD is
> record
>     num_bytes : integer;
>     start_address : system.address;
> end record;
> type BUFFER_DETAILS_ARRAY_TYPE is array(1..2) of
> BUFFER_DETAILS_RECORD;
> BUFFER_DETAILS : constant BUFFER_DETAILS_ARRAY_TYPE :=
> BUFFER_DETAILS_ARRAY_TYPE'(1 => (num_bytes => 100, start_address =>
> 16#123# ),  1 => (num_bytes => 200, start_address => 16#456# ));
> 
> procedure insert_block(idx : in integer; num_bytes : in integer;
> offset : in integer; data : BYTE_ARRAY_TYPE) is
> begin
>    ??? how do I copy the content of data into the memory pointed to by
> BUFFER_DETAILS(idx).start_address + offset
> end;

You have two problems, in fact: (1) adding an address and an 
(integer) offset to give a new address, and (2) accessing the data 
at that address.

For the addition problem (1) Ada 95/2007 provide the standard 
package System.Storage_Elements. For Ada 83 I don't know of any 
standard method; I would look for a compiler-specific method, 
perhaps compiler-specific functions in package System or in some 
other compiler-supplied package. You could also try to use 
Unchecked_Conversion to convert System.Address to some integer 
type, add the integers, and convert back, but that works only if 
the System.Address is really implemented as an integral type (and 
not, for example, as a segment + offset). But you can also delegate 
the offset to the second problem (2), see below.

For the accessing problem (2) Ada 95/2007 provide the standard 
package System.Address_To_Access_Conversions that can be used to 
convert the physical address into an access to the buffer, of any 
type desired, for example a Byte_Array_Type.

In Ada 83 there are two methods for accessing data at a given 
System.Address:

- Declare an "overlay" for the buffer using an address clause:

      Vec : Byte_Array_Type;
      for Vec use at the_known_address;

   The LRM says that this feature "should not" be used to achieve
   overlays of objects. In practice it is (or was) used in this
   way, at least when the compiler supported it.

- Use Unchecked_Conversion to convert the physical address to
   an access value (access Byte_Array_Type). This works only if
   access values are really implemented as addresses, which is not
   always the case.

If you always access the buffer as a vector of bytes, you could 
delegate problem (1) to problem (2) by setting up the overlay or 
the access value using Buffer.start_address without including the 
offset, then adding the offset part when you index the Byte_Array, 
using Vec(Buffer.offset), Vec(Buffer.offset+1) .. instead of 
Vec(0), Vec(1), ...

HTH

-- 
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
       .      @       .



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: copying data between memory locations
  2007-09-03  8:59 copying data between memory locations jef.mangelschots
  2007-09-03 10:38 ` Martin Krischik
  2007-09-03 11:09 ` Niklas Holsti
@ 2007-09-03 16:26 ` Steve
  2007-09-03 17:22 ` Jeffrey R. Carter
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 10+ messages in thread
From: Steve @ 2007-09-03 16:26 UTC (permalink / raw)


Your statement of the problem and your approach to the problem shows a "C" 
way of thinking.  In C you tend to think of the computer hardware you are 
manipulating.  In Ada you should tend to think more in the problem space.

You start out:
(1)    "In our current design, we have a package that maintains a list of 
descriptors of various buffers in the application."

A nice language independent statement.  Then you go on:
(2)    "We don't want to know their datatypes or how to write data into 
them."

With this statement you are implying "untyped" data.  In the C way of 
thinking a block of memory has no associated type, and you can store 
anything in that memory.

Then you continue:
(3)    "We only want to maintain a physical address of them and use that 
address to directly write data into these buffers (this data comes out 
incoming packets over the network)."

Here you have really locked things down as a C approach, using the term 
physical address.

Another way to approach the problem is:
  In our current design, whe have a package that maintains a list of 
discriptors of various buffers in the application.  The data contained in 
these buffers consists of a stream of bytes of incoming packets over the 
network.  There must be a systematic way of accessing the data contained in 
these buffers.

  Now for you buffer I suggest:

type byte is range 0..255;
for byte'size use 8;

type byte_array is array( <> ) of byte;

type BUFFER_DETAILS_RECORD( num_bytes : Integer ) is
record
  data : byte_array( 1 .. num_bytes);
end record;

  You can create a series of unchecked conversion functions for retrieving 
data from slices in the data buffers.

Regards,
Steve

<jef.mangelschots@gmail.com> wrote in message 
news:1188809968.217323.145640@r29g2000hsg.googlegroups.com...
> In our current design, we have a package that maintains a list of
> descriptors of various buffers in the application. We don't want to
> know their datatypes or how to write data into them. We only want to
> maintain a physical address of them and use that address to directly
> write data into these buffers (this data comes out incoming packets
> over the network).
>
> In C, this is very straightforward and use the address as a pointer
> and simply copy the packet into the memory location.
> I can't figure out a way to do this in Ada (at least not Ada83).
>
> suppose the following:
>
> type BUFFER_DETAILS_RECORD is
> record
>    num_bytes : integer;
>    start_address : system.address;
> end record;
> type BUFFER_DETAILS_ARRAY_TYPE is array(1..2) of
> BUFFER_DETAILS_RECORD;
> BUFFER_DETAILS : constant BUFFER_DETAILS_ARRAY_TYPE :=
> BUFFER_DETAILS_ARRAY_TYPE'(1 => (num_bytes => 100, start_address =>
> 16#123# ),  1 => (num_bytes => 200, start_address => 16#456# ));
>
> procedure insert_block(idx : in integer; num_bytes : in integer;
> offset : in integer; data : BYTE_ARRAY_TYPE) is
> begin
>   ??? how do I copy the content of data into the memory pointed to by
> BUFFER_DETAILS(idx).start_address + offset
> end;
> 





^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: copying data between memory locations
  2007-09-03  8:59 copying data between memory locations jef.mangelschots
                   ` (2 preceding siblings ...)
  2007-09-03 16:26 ` Steve
@ 2007-09-03 17:22 ` Jeffrey R. Carter
  2007-09-04 11:31 ` Stephen Leake
  2007-09-05  4:39 ` anon
  5 siblings, 0 replies; 10+ messages in thread
From: Jeffrey R. Carter @ 2007-09-03 17:22 UTC (permalink / raw)


jef.mangelschots@gmail.com wrote:
> In our current design, we have a package that maintains a list of
> descriptors of various buffers in the application. We don't want to
> know their datatypes or how to write data into them. We only want to
> maintain a physical address of them and use that address to directly
> write data into these buffers (this data comes out incoming packets
> over the network).
> 
> In C, this is very straightforward and use the address as a pointer
> and simply copy the packet into the memory location.

It's also very easy to accidentally read/write data from/into the wrong 
buffer, ...

> I can't figure out a way to do this in Ada (at least not Ada83).

Probably because you've decided on a very C-like implementation. Maybe 
there's information you're not giving us, but I see no reason from your 
posting why you have to maintain physical addresses and use them to 
write data directly into memory. Maybe there is a reason that you didn't 
think important to give us, or maybe it's just that you're used to 
thinking in low-level, C-like concepts. My experience is, with people 
who say "this is very easy/simple/whatever in C", it's generally the latter.

If you model your problem as a set of package specifications, model 
their behavior using state-transition diagrams or the like, and 
implement the bodies using standard Ada constructs, things are 
straightforward in Ada at least as often as they are in C.

-- 
Jeff Carter
"Many times we're given rhymes that are quite unsingable."
Monty Python and the Holy Grail
57



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: copying data between memory locations
  2007-09-03  8:59 copying data between memory locations jef.mangelschots
                   ` (3 preceding siblings ...)
  2007-09-03 17:22 ` Jeffrey R. Carter
@ 2007-09-04 11:31 ` Stephen Leake
  2007-09-05  4:39 ` anon
  5 siblings, 0 replies; 10+ messages in thread
From: Stephen Leake @ 2007-09-04 11:31 UTC (permalink / raw)


jef.mangelschots@gmail.com writes:

> In our current design, we have a package that maintains a list of
> descriptors of various buffers in the application. We don't want to
> know their datatypes or how to write data into them. 

Ok, you don't need to write to the buffers.

> We only want to maintain a physical address of them and use that
> address to directly write data into these buffers (this data comes
> out incoming packets over the network).

Umm, now you do need to write to the buffers?

As others have pointed out, your requirements are not well-stated;
they assume the implementation. And in fact, they are contradictory.

-- 
-- Stephe



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: copying data between memory locations
  2007-09-03 10:38 ` Martin Krischik
@ 2007-09-04 15:57   ` Adam Beneschan
  2007-09-04 18:16     ` jef.mangelschots
  0 siblings, 1 reply; 10+ messages in thread
From: Adam Beneschan @ 2007-09-04 15:57 UTC (permalink / raw)


On Sep 3, 3:38 am, Martin Krischik <krisc...@users.sourceforge.net>
wrote:
> jef.mangelsch...@gmail.com schrieb:
>
> > In our current design, we have a package that maintains a list of
> > descriptors of various buffers in the application. We don't want to
> > know their datatypes or how to write data into them. We only want to
> > maintain a physical address of them and use that address to directly
> > write data into these buffers (this data comes out incoming packets
> > over the network).
>
> > In C, this is very straightforward and use the address as a pointer
> > and simply copy the packet into the memory location.
>
> straightforward and highly dangerous.
>
> > I can't figure out a way to do this in Ada (at least not Ada83).
>
> You just have not found the right features yet. Suggested reading:
>
> http://en.wikibooks.org/wiki/Ada_Programming/Types/access#Access_vs._...http://en.wikibooks.org/wiki/Ada_Programming/Type_System#Address_conv...http://en.wikibooks.org/wiki/Ada_Programming/Type_System#Overlays
>
> and from the reference manual:
>
> http://www.adaic.com/standards/05rm/html/RM-13-7-2.html#I4643http://www.adaic.com/standards/05rm/html/RM-13-3.html#I4496
>
> As you can see (once you read the articles) you have even got two
> options open and now you are left with choosing the right one ;-).

Unfortunately, most of the features you've referred to are not
available in Ada 83, and the original poster hinted that he needed an
Ada 83 way to accomplish this.

In Ada 83, you'll need to do something like:

   type Byte_Array is array (1 .. Num_Bytes) of Byte;
--or--
   subtype Byte_Array is BYTE_ARRAY_TYPE (1 .. Num_Bytes);
   Dest : Byte_Array;
   for Dest use at Buffer_Details(idx) + Offset;

   Dest := Data;

I don't know what "data" is, but if its type is an unconstrained array
whose length is guaranteed to be Num_Bytes, the above assignment will
work; otherwise you'll need a slice, like

   Dest := Data (Data'First .. Data'First + Num_Bytes - 1);

I also don't know that "Buffer_Details(idx) + Offset" will work.
Probably not.  Someone already pointed out that
System.Storage_Elements is available in Ada 95 (and later) to do this
sort of address arithmetic, but in Ada 83 you have to invent your own
method.  If you know that a System.Address type is represented as just
a simple address whose size is the same as an Integer, then using
Unchecked_Conversion to convert System.Address to an Integer, add
Offset to it, and convert it back to System.Address may be necessary.
If a System.Address is more complicated, you'll need a more
complicated method.  Of course, anything you do is likely to be non-
portable but that's probably not your concern.

I agree with others that trying to deal with addresses directly like
this *may* be evidence of a poor design decision; it's better to try
to see if Ada has nicer features for accomplishing something than to
assume you have to do things the same way you do it in C.  (I've seen
a lot of needlessly horrendous Ada code written by programmers who
still tried to do things the C way.)  I say *may* because we can't say
for sure, without knowing more about your particular problem.  Also,

rant: begin

I'd like to gripe about those who respond to a question like this by
telling them how they should have designed their program in the first
place, rather than by answering their question.  We do want Ada to be
used in the Real World, after all (we do, right?), and the Real World
can be messy sometimes---sometimes you have to come up with a quick
solution to cope with a previous poor design decision, because your
customer has a problem and can't wait for you to rewrite a billion
lines of code or whatever to make the design nice and clean and
perfect.  I've had to do ugly things like that.  Ada generally
provides ways to get around problems like this, and this is a strength
of the language rather than a weakness, despite the fact that these
features are things you're better off not using if you don't have to.
Anyway, maybe a better design is feasible in this particular poster's
case and maybe it isn't.  But I'm afraid that being unhelpful could
help scare programmers back to using C.

end rant;

                        -- Adam








^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: copying data between memory locations
  2007-09-04 15:57   ` Adam Beneschan
@ 2007-09-04 18:16     ` jef.mangelschots
  2007-09-04 20:12       ` Jeffrey R. Carter
  0 siblings, 1 reply; 10+ messages in thread
From: jef.mangelschots @ 2007-09-04 18:16 UTC (permalink / raw)


Just a few words of clarification:

I do work on and off on both Ada and C projects, so yes, I sometimes
do tend to think in terms like "I would do that like this in C, how do
I do it in Ada".
It is an Ada83 project with a very short deadline. This section of
code is non-vital. Hopefully our last new Ada83 project (Ada83 is
dictated by the compiler we use. not because we want it). Next
projects will be Ada95/2005 on a new platform with new compilers.
The reason why I ask the question is because we typically never do
this kind of stuff and do it in ways suggested in your replies, hence
my question. Thanks for the answers though.
We feel comfortable doing this because we know the size of that buffer
exactly and typically build in at least 2 ways of guaranteeing no
buffer overflow can occur.
The reason we want to do this is because it will bloat the code
significantly if we want to go through the regular channels to get the
data in those buffers. It is easy for use to know their memory address
and size because they are mapped to specific hardware locations.
Some of your suggestions like "type byte_array is array( <> ) of
byte;",we do use already.
The fact that Ada95 has a feature that could help us out means that it
isn't an unreasonable request. Unfortunately, Ada83 doesn't have it.
The difficulty is in maintaining a reference to these buffers, which
are located and maintained elsewhere, in an array of structures, and
access them via these references in a generic way rather than directly
via their implementation-specific interfaces.

Thank you for the answers.
regards
Jef




^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: copying data between memory locations
  2007-09-04 18:16     ` jef.mangelschots
@ 2007-09-04 20:12       ` Jeffrey R. Carter
  0 siblings, 0 replies; 10+ messages in thread
From: Jeffrey R. Carter @ 2007-09-04 20:12 UTC (permalink / raw)


jef.mangelschots@gmail.com wrote:
> 
> It is an Ada83 project with a very short deadline. This section of
> code is non-vital. Hopefully our last new Ada83 project (Ada83 is
> dictated by the compiler we use. not because we want it). Next
> projects will be Ada95/2005 on a new platform with new compilers.
> The reason why I ask the question is because we typically never do
> this kind of stuff and do it in ways suggested in your replies, hence
> my question. Thanks for the answers though.

If you were using Ada 95, the low-level approach might be the best way 
to meet your deadline. But in Ada 83 this sort of thing is so compiler 
dependent and often unclear and difficult that I would be surprised if I 
weren't done sooner taking the Ada approach than the one you're trying 
to use.

> The fact that Ada95 has a feature that could help us out means that it
> isn't an unreasonable request.

This doesn't follow. Unreasonable things were added in Ada 95. Which 
they are depends on the individual. Ada 07 added some more.

> The difficulty is in maintaining a reference to these buffers, which
> are located and maintained elsewhere, in an array of structures, and
> access them via these references in a generic way rather than directly
> via their implementation-specific interfaces.

References in Ada are best done through access values. The language 
provides a mechanism for accessing things via access values. Your 
compiler probably provides a (non-portable) way to convert your existing 
addresses to access values.

"An array of structures" implies array indices and a common 
implementation. Could you use the index into the array as the reference 
and a common operation that takes the index as a parameter to access 
them? That would seem to be simple and clear.

-- 
Jeff Carter
"What I wouldn't give for a large sock with horse manure in it."
Annie Hall
42



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: copying data between memory locations
  2007-09-03  8:59 copying data between memory locations jef.mangelschots
                   ` (4 preceding siblings ...)
  2007-09-04 11:31 ` Stephen Leake
@ 2007-09-05  4:39 ` anon
  5 siblings, 0 replies; 10+ messages in thread
From: anon @ 2007-09-05  4:39 UTC (permalink / raw)


-------------------------------------------
pragma Ada_83 ; -- limit GNAT to Ada 83. --
-------------------------------------------
with Interfaces ;
with System ;

procedure ytest is

   function Read_Memory ( Addr : System.Address ) 
                return Interfaces.Unsigned_8 is

     begin -- Read_Memory
       declare
         Mem : Interfaces.Unsigned_8 ;
         for Mem'Address use Addr ;
       begin
        return Mem ;
       end ;
     end Read_Memory ;

   procedure Write_Memory ( Addr : System.Address ; 
                            Data : Interfaces.Unsigned_8 ) is
     begin -- Write_Memory
       declare
         Mem : Interfaces.Unsigned_8 ;
         for Mem'Address use Addr ;
       begin
        Mem := Data ;
       end ;
     end Write_Memory ;


begin -- ytest
  null ;
end ytest ;

--
-- I think you can modify the code to fit your needs for records
--

In <1188809968.217323.145640@r29g2000hsg.googlegroups.com>,  jef.mangelschots@gmail.com writes:
>In our current design, we have a package that maintains a list of
>descriptors of various buffers in the application. We don't want to
>know their datatypes or how to write data into them. We only want to
>maintain a physical address of them and use that address to directly
>write data into these buffers (this data comes out incoming packets
>over the network).
>
>In C, this is very straightforward and use the address as a pointer
>and simply copy the packet into the memory location.
>I can't figure out a way to do this in Ada (at least not Ada83).
>
>suppose the following:
>
>type BUFFER_DETAILS_RECORD is
>record
>    num_bytes : integer;
>    start_address : system.address;
>end record;
>type BUFFER_DETAILS_ARRAY_TYPE is array(1..2) of
>BUFFER_DETAILS_RECORD;
>BUFFER_DETAILS : constant BUFFER_DETAILS_ARRAY_TYPE :=
>BUFFER_DETAILS_ARRAY_TYPE'(1 => (num_bytes => 100, start_address =>
>16#123# ),  1 => (num_bytes => 200, start_address => 16#456# ));
>
>procedure insert_block(idx : in integer; num_bytes : in integer;
>offset : in integer; data : BYTE_ARRAY_TYPE) is
>begin
>   ??? how do I copy the content of data into the memory pointed to by
>BUFFER_DETAILS(idx).start_address + offset
>end;
>




^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2007-09-05  4:39 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-09-03  8:59 copying data between memory locations jef.mangelschots
2007-09-03 10:38 ` Martin Krischik
2007-09-04 15:57   ` Adam Beneschan
2007-09-04 18:16     ` jef.mangelschots
2007-09-04 20:12       ` Jeffrey R. Carter
2007-09-03 11:09 ` Niklas Holsti
2007-09-03 16:26 ` Steve
2007-09-03 17:22 ` Jeffrey R. Carter
2007-09-04 11:31 ` Stephen Leake
2007-09-05  4:39 ` anon

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox