comp.lang.ada
 help / color / mirror / Atom feed
From: rgilbert@orl.mmc.com (Bob Gilbert)
Subject: Re: Importing C Structures
Date: 24 Mar 1995 20:20:58 GMT
Date: 1995-03-24T20:20:58+00:00	[thread overview]
Message-ID: <3kv9ja$6h3@theopolis.orl.mmc.com> (raw)
In-Reply-To: 3ksg66$h1c@newssvr.cacd.rockwell.com

In article h1c@newssvr.cacd.rockwell.com, rswhite@cacd.rockwell.com (Robert S. White) writes:
->
->Do you have a clean way to handle hardware registers that have one
->meaning when you read them and another when you write to them with
->nice seperate names for each type of usage?  I know "use at" for 
->Ada 83 can overide this but it seems to be not in the spirit of 
->the 83 LRM;
->  13.5 "Address clauses should not be used to achieve overlays of
->        objects...Any program using address clauses to achieve
->        such effects is erroneous."
->A work around is to have a dual meaning name for the register and
->use one procedure, appropriately named, to write to it and a function,
->again with a suitable name, for reading it.
->
->This is a case where C programmers use the union structure.  I 
->confess that I have not ferreted out in the Ada 95 RM or Rational 
->the right (and very concise) way to do this now.
->
->Recommendations? 

Well, using Ada 83 there are a couple of ways.  You are correct about
avoiding the address clause to "overlay" two or more objects to the 
same memory location.

If the location has different meaning when read from that when written
to, I would use Unchecked_Conversion and do something like the following:

     package Whatever_Interface is

       type READ_WHATEVER is record ..... end record;
       type WRITE_WHATEVER is record .... end record;

       procedure Write(Val : in WRITE_WHATEVER);

       function Read return READ_WHATEVER;

     end Whatever_Interface;

     with System;
     with Unchecked_Conversion;
     package body Whatever_Interface is

       Whatever : WRITE_WHATEVER;
         for Whatever use at {put address here};

       procedure Write(Val : in WRITE_WHATEVER) is
       begin
         Whatever := Val;
       end Write;

       function Read return READ_WHATEVER is
         function To_Read_Type is new
           Unchecked_Conversion(WRITE_WHATEVER, READ_WHATEVER);
       begin
         return To_Read_Type(Whatever);
       end Read;

     end Whatever_Interface;

The advantage of using the packaging and procedure/function to access
the location is that it allows protection of the object. You can only
write a valid type to it as well as returning the proper type when
using the function to read the object. You can use pragma Inline if
there are concerns about the overhead in making these simple calls.
Most reasonable compilers will optimize the code generated such that
it will appear to give direct access to the memory location.

Of course if you really want to "overlay" two seperate objects to the
same location, you can probably make the assumption that access types
are implemented as addresses, and you could then do the following:

     with System;
     with Unchecked_Conversion;
     package Whatever_Interface is

       Location : constant System.ADDRESS := {put address here};

       type READ_WHATEVER is record ..... end record;
       type WRITE_WHATEVER is record .... end record;

       type READ_WHATEVER_PTR is access READ_WHATEVER;
       type WRITE_WHATEVER_PTR is access WRITE_WHATEVER;

       function To_Ptr is new 
         Unchecked_Conversion(System.ADDRESS, READ_WHATEVER_PTR);

       function To_Ptr is new 
         Unchecked_Conversion(System.ADDRESS, WRITE_WHATEVER_PTR);

       Read_Val  : constant READ_WHATEVER_PTR  := To_Ptr(Location);
       Write_Val : constant WRITE_WHATEVER_PTR := To_Ptr(Location);

     end Whatever_Interface;

Of course you have to remember to use the ".all" notation to make sure
you are referencing the value "pointed" to by the access value(s).  This 
is probably considered bastardized Ada code.  It is dangerous since you
can write a read type value (Read_Val := xxx) and the compiler will offer
no protection. It also relies on the knowlege that access types are 
implemented as an address (not required by the LRM, but usually true).
Note that at least I made the access (pointer) values constants so that
they are protected from accidental modification (also stating that something
you intend to be constant with the key word "constant" frequently allows the
compiler to make advantageous assumptions during optimization).

Now with Ada 83 the first example may have a problem using the address
clause.  Many compilers will perform a write to the location during
elaboration (I guess to insure that any initialization that might have
been specified is performed).  This is the reason I used the 
WRITE_WHATEVER type to define the object.  If this should be a problem,
you can use the access type to map the object in the same style as done
in the second example.  

As for Ada 95, I'll quote Tucker Taft from a previous post:
  --------------------------------------------------------------
   In Ada 95, you can specify "pragma Import(Ada, <object-name>);"
   which indicates that *no* default initialization is to be performed
   by the compiler-generated code.  This is generally desirable when
   using an address clause to associate a name with a machine register
   of some sort.

   Also, in Ada 95 there are language-defined functions for converting
   integers to addresses.  Finally, the preferred syntax for
   specifying the address of an object uses "for ...'Address use ...",
   such as:

      for Console_Status_Register'Address use 
        System.Storage_Elements.To_Address(16#FFC0#);

   The "for ... use at ..." syntax is still retained for upward 
   compatibility reasons.
  --------------------------------------------------------------

-Bob





  parent reply	other threads:[~1995-03-24 20:20 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
1995-03-23  6:34 Importing C Structures Chris O'Regan
1995-03-23  7:55 ` Vladimir Vukicevic
1995-03-23 18:55   ` Robert S. White
1995-03-24  8:51     ` Vladimir Vukicevic
1995-03-25  9:57       ` Keith Thompson
1995-03-26 13:16         ` Larry Kilgallen, LJK Software
1995-03-27  0:00           ` Kevin F. Quinn
1995-04-07  0:00             ` Larry Kilgallen
1995-03-27 15:35           ` Theodore Dennison
1995-03-28  0:00             ` Robert Dewar
1995-03-28 11:44             ` Keith Thompson
1995-03-29  0:00               ` misattrubation (was: Re: Importing C Structures) Theodore Dennison
1995-03-31  0:00                 ` Theodore Dennison
1995-03-27 23:39           ` Importing C Structures Keith Thompson
1995-03-27 16:00       ` Norman H. Cohen
1995-03-24 16:08     ` Robert I. Eachus
1995-03-24 20:20     ` Bob Gilbert [this message]
1995-03-25 18:07     ` Robert Dewar
1995-03-24 17:30   ` Robert Dewar
1995-03-24 15:32 ` Robert Dewar
replies disabled

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