comp.lang.ada
 help / color / mirror / Atom feed
* Ada-Comment proposals (version 3)
@ 2014-07-13 16:54 Simon Clubley
  2014-07-13 17:53 ` Niklas Holsti
  2014-07-14  0:24 ` Simon Clubley
  0 siblings, 2 replies; 19+ messages in thread
From: Simon Clubley @ 2014-07-13 16:54 UTC (permalink / raw)


I've restructured issue 1 to turn it into a general partial aggregates
proposal. The atomic updating of device register bitfields discussion
is still pretty much the same but the additional comments and examples
from Niklas make it a more general proposal.

Niklas, since I have included your words and examples directly, can you
make sure you are happy with what I have included please ?

Issue 2 has had the question about 'Size added and some wording clarified.

I've posted this in it's own thread so any comments are clearly associated
with this version.

I think this is now ready for submission, so if there are no further
comments, I will submit it.

Simon.

-----------------------------------------------------------------------------
Issue 1: Partial Aggregate notation

!topic		Adding partial aggregate functionality to Ada
!reference	Ada 2012 RM{clause unsure}
!from		Simon Clubley 2014-07-13
!keywords	partial aggregate device register bitfields atomic updating

[The original motivation for this proposal was the simultaneous
updating of multiple bitfields in a device register. However,
discussions in comp.lang.ada have revealed a wide range of potential
uses for this notation which would allow these other existing uses
to be expressed more cleanly. The examples demonstrating the wider
potential of this proposal were provided by Niklas Holsti.]

Background
----------
Ada can model the bitfields in a device register as a record type
containing those bitfields and can map an instance of that record
type to the address of that device register.

However, sometimes there is a requirement to be able to update a
subset of those bitfields as an atomic operation while preserving
the contents of the other bitfields in the record.

In Ada, the only way to do this (apart from C style bitmasks on an
integer variable) is to read the device register into a temporary
instance of the record type, modify the temporary variable and
write the temporary variable back to the device register.

This, to put it mildly, is ugly.

Normal (non-atomic) records also have similar issues.

For normal records, consider a record type Rec with many components,
one of which is Colour, a variable R of type Rec, and the need to
call procedure Foo twice, once using R with its own Colour, and once
with R but using the Black colour.

There are two ways to do this in current Ada, but both are ugly. The
first uses a temporary variable, a copy, and an assignment to the
component:

   declare
      T : Rec := R;
   begin
      Foo (R);
      T.Colour := Black;
      Foo (T);
   end;

The other way uses an aggregate listing all components of Rec, which is
very cumbersome and a burden for maintenance:

   Foo (R);
   Foo ((X => R.X, Y => R.Y, ...., Colour => Black));

Proposal
--------
An elegant solution for these problems would be a new partial aggregate
syntax in which the list of record components to be modified would be
listed along with their new values.

One suggested syntax would be:

	A := (A changing C => D, E => F);

or

	A := (A updating C => D, E => F);

where A is a record and C and E are record components.

[When this syntax discussion took place in comp.lang.ada, one
suggestion for the keyword was "overriding" but I didn't like that
because that keyword made it seem as if A was the one doing the
overriding, not the later C and E references.]

For an Atomic record, the compiler would generate a Read-Modify-Write
sequence and, as the operation would be on the record as a whole,
C.6(15) would be guaranteed to apply and there would be a single
read of the device register and a single write to the device register.

For the normal record example above, one could simply write instead

   Foo (R);
   Foo ((R changing Colour => Black));

which is much more elegant than the above methods currently provided
by Ada.

In addition, Niklas also provided the following array aggregate example:

   type Month_Days is array (Month) of Positive;

   Normal_Year_Days : constant Month_Days :=
      (Jan => 31, Feb => 28, Mar => 31, ..., Dec => 31);

   Leap_Year_Days : constant Month_Days :=
      (Normal_Year_Days changing Feb => 29);

It was also suggested partial aggregates could be of use in contracts
within Ada 2012 and also had some uses within SPARK. However, this is
one area I currently have no experience with, so I reproduce the
following example as-is:

|I have not yet used Ada 2012 contracts in my programming, but I believe
|that partial aggregates would be quite useful in post-conditions, to
|express that some "out" value is the same as some "in" value except for
|changes to certain components:
|
|   with Post => X = (X'old changing Colour => Black)

Regarding the use of a new keyword, I do think we need a new keyword
because we are talking about adding a subset update capability to Ada
and that new usage should stand out in any code.

Thanks,

Simon.

-----------------------------------------------------------------------------
Issue 2: Does Atomic apply to record components ?

!topic		Does Atomic on a record apply to it's components ?
!reference	Ada 2012 RMC.6(15)
!from		Simon Clubley 2014-07-13
!keywords	Atomic update record components

This submission was prompted by an issue identified recently in
comp.lang.ada. On an ARM target, a 32-bit record, with multiple bitfields,
was defined as Atomic. However, the generated code showed that when a
bitfield, instead of the record as a whole, was referenced, GNAT
sometimes used ldrb/strb (byte level access instructions) instead of
ldr/str (32 bit access instructions).

This broke the hardware requirement that the register this record was
been used to access must be accessed in units of 32 bits.

Scenario:

Consider a 32 bit record marked as Atomic. This record consists of
multiple bitfields and is used to model the bitfields in a 32 bit
memory mapped device register. The hardware requires the device
register to be read from and written to in units of 32 bits.

Now consider the following statement:

	Device_Register.bitfield := 1;

When this specific bitfield in the record, say 4 bits wide, is written
to, does the Atomic attribute on the record require the record to
be accessed in units of 32 bits or is the compiler permitted to
generate code to access, say, 8 bits of the record only ?

C.6(15) states:

	For an atomic object (including an atomic component) all reads and
	updates of the object as a whole are indivisible.

There are conflicting opinions about the above rule in comp.lang.ada.
The words "as a whole" in C.6(15) were used to justify the position that
access to this single bitfield is not required to be in units of the
record size which on the surface seemed reasonable.

However, other opinions are that C.6(15) does apply when accessing this
single bitfield.

Which opinion is correct ?

I would like C.6(15) to apply, but I am more interested in obtaining a
firm decision so other options can be considered if it doesn't.

As a related question, when C.6(15) does apply, does it also apply to
all the bits included by 'Size when 'Size has been used to increase
the size of the atomic object (say from 5 bits to 32 bits) ?

Possible solutions:

If C.6(15) applies when accessing a single bitfield in an Atomic record,
then this is clearly a GNAT bug and needs handling as such.

If C.6(15) is deemed not to apply to a single bitfield, then we need a
mechanism to indicate, in the program source code, that the compiler is
not allowed to reference a bitfield in an Atomic record by just
accessing one segment of that record's memory.

If the partial aggregate proposal is approved, then this could be the
mechanism. If it is not approved, then a pragma/aspect along the lines
of "No_Segmented_Access" could be the mechanism to enforce this.

I do believe a mechanism is required in Ada itself however. The special
requirements of the register should be declared in the source code, for
the compiler (and maintainers) to see, so that it can be guaranteed to
be honoured when the code is compiled.

Thank you,

Simon.

-- 
Simon Clubley, clubley@remove_me.eisner.decus.org-Earth.UFP
Microsoft: Bringing you 1980s technology to a 21st century world


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

end of thread, other threads:[~2014-07-22  0:26 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-07-13 16:54 Ada-Comment proposals (version 3) Simon Clubley
2014-07-13 17:53 ` Niklas Holsti
2014-07-13 18:16   ` Simon Clubley
2014-07-13 21:05     ` Niklas Holsti
2014-07-13 23:45       ` Simon Clubley
2014-07-14  0:24 ` Simon Clubley
2014-07-15 17:20   ` Simon Clubley
2014-07-15 22:11     ` Randy Brukardt
2014-07-15 23:15       ` Simon Clubley
2014-07-15 23:39         ` Adam Beneschan
2014-07-15 23:50           ` Adam Beneschan
2014-07-16  0:05             ` Simon Clubley
2014-07-21 22:02             ` Randy Brukardt
2014-07-21 22:09               ` Simon Wright
2014-07-22  0:26                 ` Randy Brukardt
2014-07-15 23:53           ` Simon Clubley
2014-07-21 22:20             ` Randy Brukardt
2014-07-21 23:06               ` Simon Clubley
2014-07-22  0:24                 ` Randy Brukardt

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