From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=unavailable autolearn_force=no version=3.4.4 Path: border1.nntp.dca.giganews.com!nntp.giganews.com!goblin1!goblin.stu.neva.ru!eternal-september.org!feeder.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail From: Simon Clubley Newsgroups: comp.lang.ada Subject: Ada-Comment proposals (version 3) Date: Sun, 13 Jul 2014 16:54:43 +0000 (UTC) Organization: A noiseless patient Spider Message-ID: Injection-Date: Sun, 13 Jul 2014 16:54:43 +0000 (UTC) Injection-Info: mx05.eternal-september.org; posting-host="e458ff8b81bc0c159989eb0e36c6e372"; logging-data="1717"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18Id06Aj8ufOS5e0zROINNN8NlOO6KWcis=" User-Agent: slrn/0.9.8.1 (VMS/Multinet) Cancel-Lock: sha1:451ZiMjlkkhi358BOGe//IAZ6Lo= Xref: number.nntp.dca.giganews.com comp.lang.ada:187567 Date: 2014-07-13T16:54:43+00:00 List-Id: 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