comp.lang.ada
 help / color / mirror / Atom feed
* Packing Record Structures in Ada
@ 1998-01-12  0:00 Randall_Rathbun
  1998-01-12  0:00 ` Matthew Heaney
                   ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: Randall_Rathbun @ 1998-01-12  0:00 UTC (permalink / raw)



Has anyone struggled and fixed the following problem with ordering inside
the Ada83 record structure? We are working with two compilers, call them
A & B, and they pack the record structure inversely. A typical example:
type sample_message_type is
   record
      first_field  : unsigned_20_bits_type;
      second_field : unsigned_22_bits_type;
      third_field  : unsigned_22_bits_type;
   end record
sample_message : sample_message_type;

When compiler A sends a message out across a bus, it will send
  |1.........20|21......32|   1st quad-word
   first field   second
  |1...10|11............32|   2nd quad-word
    2nd      third field

However when the message is received, using compiler B it gets
  |1.....12|13..........32|   1st quad-word
    2nd        1st field
  |1...........22|23....32|   2nd quad-word
    3rd field      2nd
(this is due to the way data is sent across the bus, 32 bits at a
time)
When the 2nd compiler B tries to understand what compiler A sent,
it will force its interpretation, but since the relative order has
been horizontally flipped, garbage results. One compiler stacks 8 bit
bytes left-to-right inside the quadword, the other in the opposite
order.

If you've encountered this problem in Ada83, and developed work-arounds,
I'd like to hear from you Currently we're using a rotate function that
uses the "with System" module to remedy this ugly mess. Thanks!
please email: Randall_Rathbun@rc.trw.com

-------------------==== Posted via Deja News ====-----------------------
      http://www.dejanews.com/     Search, Read, Post to Usenet




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

* Re: Packing Record Structures in Ada
  1998-01-12  0:00 Packing Record Structures in Ada Randall_Rathbun
@ 1998-01-12  0:00 ` Matthew Heaney
  1998-01-13  0:00 ` Robert Dewar
  1998-01-19  0:00 ` Anonymous
  2 siblings, 0 replies; 8+ messages in thread
From: Matthew Heaney @ 1998-01-12  0:00 UTC (permalink / raw)



In article <884639188.24707084@dejanews.com>, Randall_Rathbun@rc.trw.com wrote:

>Has anyone struggled and fixed the following problem with ordering inside
>the Ada83 record structure? We are working with two compilers, call them
>A & B, and they pack the record structure inversely. A typical example:
>type sample_message_type is
>   record
>      first_field  : unsigned_20_bits_type;
>      second_field : unsigned_22_bits_type;
>      third_field  : unsigned_22_bits_type;
>   end record
>sample_message : sample_message_type;

You haven't specified what the representation is.  You MUST specify the
representation of all data that leaves an Ada application, and transmitted
to an external device.

The solution is simple: include a representation clause for your type, as in

for Sample_Message_Type use
   record
      First_Field at 0 range 0 .. 19;
      Second_Field at 0 range 20 .. 41;
      Third_Field    at 0 range 42 .. 63;
   end record;

for Sample_Message_type'Size use 64;

Since you didn't specify the representation of the type, the compiler is
free to place the record components where ever it feels like.

Watch out for endian issues.  Are computers the same endianess?  You may
have to do byte-swapping too.

Make sure you get the positions correct.  Ada is consistent in the sense
that a bigger value means a bigger address, but this is contrary to what
you'd expect on a big-endian machine.  For example,

type RT is
   record
      B : Boolean;
   end record;

for RT use
   record
      B at 0 range 0 .. 0;
   end record;

for RT'Size use 8;

On a little endian machine, B is where you expect it: at the least
significant bit, at the position corresponding to the value 2 ** 0.

However, on a big endian machine, the same declaration puts B at the most
significant bit, at the position corresponding to the value 2 ** 7.

This "feature" of Ada can be mitigated by using the Bit_Order attribute
(available only in Ada 95 though), but I don't think any compiler actually
supports it.  I hope I'm wrong.  Even with it, you still have an ...um...
"issue" indexing packed bit arrays.

--------------------------------------------------------------------
Matthew Heaney
Software Development Consultant
<mailto:matthew_heaney@acm.org>
(818) 985-1271




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

* Re: Packing Record Structures in Ada
  1998-01-13  0:00 ` Robert Dewar
@ 1998-01-13  0:00   ` Corey Minyard
  1998-01-13  0:00     ` Robert Dewar
  1998-01-15  0:00     ` Michael F Brenner
  0 siblings, 2 replies; 8+ messages in thread
From: Corey Minyard @ 1998-01-13  0:00 UTC (permalink / raw)



dewar@merv.cs.nyu.edu (Robert Dewar) writes:
> 
> THe stream facility in Ada 95 is one of its very powerful features. I have
> the impression that a lot of Ada 95 programmers are not sufficiently aware
> of this very important capability, and its wide applicability to solving
> problems of this nature, either through explicit use, or implicit use via
> the distribution annex.
> 

From my reading of the ARM, it is not extremely clear to me that
streaming between different compilers is 100% compatible.  It may be
(I haven't read the AARM and I'm no language expert) and I would
expect it would be in general (assuming endian-ness conversion is
done, of course).

I have done tests of streaming vs direct layout and copying using
GNAT.  Streaming is rather slow, on the order of 20 times slower than
direct copying.  I would expect this is due to a polymorphic call on
every data item (every array element, etc.), so I wouldn't expect any
other compilers to be any better.  With a representation clause,
layouts are guaranteed except for endianness, and you can directly
copy the data structure.

If you were able to do a "for T'Bit_Order use ..." would that solve
the endianness problem?  I realize that compilers do not have to allow
this, but if they did...

-- 
Corey Minyard               Internet:  minyard@acm.org
  Work: minyard@nortel.ca       UUCP:  minyard@wf-rch.cirr.com




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

* Re: Packing Record Structures in Ada
  1998-01-13  0:00   ` Corey Minyard
@ 1998-01-13  0:00     ` Robert Dewar
  1998-01-15  0:00     ` Michael F Brenner
  1 sibling, 0 replies; 8+ messages in thread
From: Robert Dewar @ 1998-01-13  0:00 UTC (permalink / raw)



Corey asks

<<From my reading of the ARM, it is not extremely clear to me that
streaming between different compilers is 100% compatible.  It may be
(I haven't read the AARM and I'm no language expert) and I would
expect it would be in general (assuming endian-ness conversion is
done, of course).

I have done tests of streaming vs direct layout and copying using
GNAT.  Streaming is rather slow, on the order of 20 times slower than
direct copying.  I would expect this is due to a polymorphic call on
every data item (every array element, etc.), so I wouldn't expect any
other compilers to be any better.  With a representation clause,
layouts are guaranteed except for endianness, and you can directly
copy the data structure.

If you were able to do a "for T'Bit_Order use ..." would that solve
the endianness problem?  I realize that compilers do not have to allow
this, but if they did...
>>

No, of course there is no requirement that different compilers represent
data in the same way. For example two compilers on the same machine with
32-bit type Integer, are free to represent it in different manners (it's
unlikely that they will, but there is nothing in the RM to suggest that
this kind of interoperability is guaranteed, and streams have nothing
to say about that.

The factor of 20 will differ a lot, you can get cases with much higher
costs (e.g. when exceptions are involved), or much lower costs, it very
much depends on the case.





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

* Re: Packing Record Structures in Ada
  1998-01-12  0:00 Packing Record Structures in Ada Randall_Rathbun
  1998-01-12  0:00 ` Matthew Heaney
@ 1998-01-13  0:00 ` Robert Dewar
  1998-01-13  0:00   ` Corey Minyard
  1998-01-19  0:00 ` Anonymous
  2 siblings, 1 reply; 8+ messages in thread
From: Robert Dewar @ 1998-01-13  0:00 UTC (permalink / raw)



Randall says

<<When compiler A sends a message out across a bus, it will send
  |1.........20|21......32|   1st quad-word
   first field   second
  |1...10|11............32|   2nd quad-word
    2nd      third field

However when the message is received, using compiler B it gets
  |1.....12|13..........32|   1st quad-word
    2nd        1st field
  |1...........22|23....32|   2nd quad-word
    3rd field      2nd
(this is due to the way data is sent across the bus, 32 bits at a
time)
>>


If this is an endianness difference then the differences are just what
one would expect. If not, then one of the compilers is behaving in a very
peculiar manner. You might want to say what machines and compilers are
involved here to understand things better. I assume you have rep clauses
for the two records? If not, then of course all bets are off, and the
problem is yours (to expect any default layout to be applicable between
two separate compilers is plain wrong).

Note that if you use the distribution support in GNAT, all such issues
are handled automatically, and indeed you can deal with the situation
in a completely general manner, compiler independently, by using the
stream facility in Ada 95.

THe stream facility in Ada 95 is one of its very powerful features. I have
the impression that a lot of Ada 95 programmers are not sufficiently aware
of this very important capability, and its wide applicability to solving
problems of this nature, either through explicit use, or implicit use via
the distribution annex.





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

* Re: Packing Record Structures in Ada
  1998-01-13  0:00   ` Corey Minyard
  1998-01-13  0:00     ` Robert Dewar
@ 1998-01-15  0:00     ` Michael F Brenner
  1998-01-15  0:00       ` Robert Dewar
  1 sibling, 1 reply; 8+ messages in thread
From: Michael F Brenner @ 1998-01-15  0:00 UTC (permalink / raw)



  > I have done tests of streaming vs direct layout and copying using
  > GNAT.  Streaming is rather slow, on the order of 20 times slower than
  > direct copying. 

Because of the bugs in the current version of gnat for DOS streaming,
I recommend putting off implementing stream-io until after the next
version of gnat for DOS is released by some volunteer someday.

Timing on DOS shows that copying files with stream-io is the fastest
way Ada can do it (faster than calling the C-library getc and putc,
faster than text_io, faster than sequential_IO, faster than
direct_IO, and faster than doing a djgpp DOS call for buffering
the reads 32K at a time). 

When you say it is 20 times lower than direct copying, you mean
it is 20 times slower than a REAL mode copy command. Since
you probably restricted your Ada code to run in PROTECTED mode,
that is not a fair test. When you compare the Ada code to 
assembly code running in PROTECTED mode and using the DOS calls
in REAL mode to do the copying, you will find the Ada code runs
just as fast as the assembly code. 

Going back and forth between REAL and PROTECTED mode takes time.
That is the one weakness of DOS under the djgpp extender, it does
not have PROTECTED mode I/O and so goes down to REAL mode to get
all of its I/O handled.




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

* Re: Packing Record Structures in Ada
  1998-01-15  0:00     ` Michael F Brenner
@ 1998-01-15  0:00       ` Robert Dewar
  0 siblings, 0 replies; 8+ messages in thread
From: Robert Dewar @ 1998-01-15  0:00 UTC (permalink / raw)



Michael said

<<Because of the bugs in the current version of gnat for DOS streaming,
I recommend putting off implementing stream-io until after the next
version of gnat for DOS is released by some volunteer someday.
>>

Note that there is no current version of GNAT for DOS. It is certainly true
that the 3.07 DOS version is quite out of date at this stage, and the best
advice is to switch to a more recent version (if you are using the PC, choices
are NT/Win95, OS/2, Solaris x86, or Linux, and there are also volunteer ports
for NetBSD and FreeBSD).

Michael is one of the hardy minority who is still interested in DOS per se,
and he puts a lot of energy into loudly complaining about there being no
more recent version for the DOS GNAT port. A (rather small number) of
others have voiced the same complaint, but since we see zero market for
this product, we have dropped support. Unfortunately none of the energy
that has gone into complkaining about this has been diverted into actually
doing something about it.

Note once again that it is perfectly practical for someone to create a DOS
port of the lastest GNAT technology. After all the original port for DOS
was done *from scratch* from a volunteer, and starting with what is here
already for 3.07 is a much easier task.

I don't particularly remember the original message in this thread having
anything to do with DOS, so this may just be a case of Michael using the
opportunity to jump on his DOS hobby horse :-) But in any case if you
are using DOS, you should definitely consider switching to a more recent
version of the technology (both OS wise and GNAT wise)!

Robert Dewar
Ada Core Technologies





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

* Re: Packing Record Structures in Ada
  1998-01-12  0:00 Packing Record Structures in Ada Randall_Rathbun
  1998-01-12  0:00 ` Matthew Heaney
  1998-01-13  0:00 ` Robert Dewar
@ 1998-01-19  0:00 ` Anonymous
  2 siblings, 0 replies; 8+ messages in thread
From: Anonymous @ 1998-01-19  0:00 UTC (permalink / raw)



On Mon, 12 Jan 1998 22:52:55 -0600, Randall_Rathbun@rc.trw.com wrote:

> Has anyone struggled and fixed the following problem with ordering inside
> the Ada83 record structure? We are working with two compilers, call them
> A & B, and they pack the record structure inversely. A typical example:
> type sample_message_type is
>    record
>       first_field  : unsigned_20_bits_type;
>       second_field : unsigned_22_bits_type;
>       third_field  : unsigned_22_bits_type;
>    end record
> sample_message : sample_message_type;
> 
> When compiler A sends a message out across a bus, it will send
>   |1.........20|21......32|   1st quad-word
>    first field   second
>   |1...10|11............32|   2nd quad-word
>     2nd      third field
> 
> However when the message is received, using compiler B it gets
>   |1.....12|13..........32|   1st quad-word
>     2nd        1st field
>   |1...........22|23....32|   2nd quad-word
>     3rd field      2nd
> (this is due to the way data is sent across the bus, 32 bits at a
> time)
> When the 2nd compiler B tries to understand what compiler A sent,
> it will force its interpretation, but since the relative order has
> been horizontally flipped, garbage results. One compiler stacks 8 bit
> bytes left-to-right inside the quadword, the other in the opposite
> order.
> 
> If you've encountered this problem in Ada83, and developed work-arounds,
> I'd like to hear from you Currently we're using a rotate function that
> uses the "with System" module to remedy this ugly mess. Thanks!
> please email: Randall_Rathbun@rc.trw.com
> 
> -------------------==== Posted via Deja News ====-----------------------
>       http://www.dejanews.com/     Search, Read, Post to Usenet
> 
> 

What do you get if you use

type Byte is range 0 .. 255; -- This is Ada 83
for Byte'Size use 8;

type Byte_9 is array (1 .. 9) of Byte;
for Byte_9'Size use 9 * 8;
pragma Pack (Byte_9);

M : Sample_Message_Type;
C : Byte_9;

C (1) := M.First_Field rem 256; -- LSB
C (2) := (M.First_Field / 256) rem 256; -- Middle byte
C (3) := M.First_Field / (256 ** 2); -- MSB
C (4) := M.Second_Field rem 256; -- LSB

.. 

-- C (1 .. 3) contains First_Field, little endian byte order
-- C (4 .. 6)    "     Second_ "  ,          "
-- C (7 .. 9)    "     Third_  "  ,          "

Send C from A to B. On B, reverse:

M.First_Field := (256 ** 2) * C (3) + 256 * C (2) + C (1);

..

This generally works. With Ada, you can use modular types, and shifts
and logical operations instead of arithmetic operations. It should also
work to send from B to A.

Jeff Carter  PGP:1024/440FBE21
My real e-mail address: ( carter @ innocon . com )
"English bed-wetting types."
Monty Python & the Holy Grail

Posted with Spam Hater - see
http://www.compulink.co.uk/~net-services/spam/




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

end of thread, other threads:[~1998-01-19  0:00 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1998-01-12  0:00 Packing Record Structures in Ada Randall_Rathbun
1998-01-12  0:00 ` Matthew Heaney
1998-01-13  0:00 ` Robert Dewar
1998-01-13  0:00   ` Corey Minyard
1998-01-13  0:00     ` Robert Dewar
1998-01-15  0:00     ` Michael F Brenner
1998-01-15  0:00       ` Robert Dewar
1998-01-19  0:00 ` Anonymous

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