Ada-Rapporteur-Group / User-Community-Input

Ada User Community Input Working Group - Github Mirror Prototype
26 stars 1 forks source link

Have light (ZFP) runtimes received enough consideration? #67

Open kevlar700 opened 10 months ago

kevlar700 commented 10 months ago

I am fairly sure that implementing a full runtime on thousands of microchips will never happen. I personally chose not to focus time on a full or Ravenscar runtime for one microchip. Perhaps for all development but Ada/Spark is certainly the best language for microchip development bar none.

I wonder which features of Ada which are incompatible with a light runtime could have alternatives made available that are compatible. Likely with a better design than are suggested here. Please add design suggestions.

Perhaps a single globally defined exception variable that the user must define in main could be set. Contracts on a light runtime might set it and return rather than causing last chance handler execution. Or an alternative error handling package provided to replace exception propagation. Hopefully it would consider error and code flow or perhaps more suitably leave status to the user. I am not 100% sure but the Rust option error type may conflate the two? A well considered practice or package in Adas usual grace may save light runtime users significant time/refactoring even if contracts cannot be made compatible.

Some kinds of containers might be provided that perhaps do not permit deletion but only popping off a stack etc.. Perhaps Spark ownership might help with deletion on a light runtime or simply indexing into an array?

Is a subset of protected objects possible for light runtimes?

kevlar700 commented 9 months ago

The Ada 2022 'Image attribute on a record requires unbounded strings. The light runtime has bounded strings. Could it use bounded or String in order to be made compatible?

swbaird commented 9 months ago

What led you to conclude that "the Ada2022 'Image attribute on a record requires unbounded strings" ? I don't think that is correct, but perhaps I am mistaken. FWIW, some thought was given to restricted runtimes when the Ada2022 'Image stuff was designed - that's why the interface type Root_Buffer_Type is implemented by Ada.Strings.Text_Buffers.Bounded.Buffer_Type. -- Steve

sttaft commented 9 months ago

All good questions, and Ada 2022 has some reasonable answers I would say ...

In Ada 2022, 'Image is implemented in terms of 'Put_Image, which you can call directly if you prefer (see http://www.ada-auth.org/standards/22aarm/html/AA-4-10.html). For 'Put_Image, you can provide your own Buffer_Type object, which can be a bounded buffer (see http://www.ada-auth.org/standards/22aarm/html/AA-A-4-12.html) where you specify Max_Character.

In Annex H, a language-defined Restriction Max_Image_Length is described, which if specified, gives a value for Max_Character which will be used by the implementation for the bounded Buffer used to implement 'Image functions (see http://www.ada-auth.org/standards/22aarm/html/AA-H-4.html, paragraph H.4(23.11/5)).

As far as "light" runtimes, Ada defines two subsets, identified as the Ravenscar and Jorvik profiles (see http://www.ada-auth.org/standards/22aarm/html/AA-D-13.html), which both support protected types, albeit with some restrictions.

kevlar700 commented 9 months ago

What led you to conclude that "the Ada2022 'Image attribute on a record requires unbounded strings" ? I don't think that is correct, but perhaps I am mistaken. FWIW, some thought was given to restricted runtimes when the Ada2022 'Image stuff was designed - that's why the interface type Root_Buffer_Type is implemented by Ada.Strings.Text_Buffers.Bounded.Buffer_Type. -- Steve

When compiling with gnat_arm_elf 12.2.1 with flag -gnat2022. I got the compilation error:

error: construct not allowed in configurable run-time mode
   error: file a-stbuun.ads not found
   error: entity "Ada.Strings.Text_Buffers.Unbounded.Buffer_Type" not available

However I have since discovered that I also get it when using 'Image on an array created from an unconstrained array type.

sttaft commented 9 months ago

You might try specifying the Max_Image_Length restriction (see RM H.4), or alternatively, use 'Put_Image instead of 'Image, and provide your own bounded buffer (see RM 4.10 and A.4.12).

kevlar700 commented 9 months ago

All good questions, and Ada 2022 has some reasonable answers I would say ...

In Ada 2022, 'Image is implemented in terms of 'Put_Image, which you can call directly if you prefer (see http://www.ada-auth.org/standards/22aarm/html/AA-4-10.html). For 'Put_Image, you can provide your own Buffer_Type object, which can be a bounded buffer (see http://www.ada-auth.org/standards/22aarm/html/AA-A-4-12.html) where you specify Max_Character.

In Annex H, a language-defined Restriction Max_Image_Length is described, which if specified, gives a value for Max_Character which will be used by the implementation for the bounded Buffer used to implement 'Image functions (see http://www.ada-auth.org/standards/22aarm/html/AA-H-4.html, paragraph H.4(23.11/5)).

Very nice.

As far as "light" runtimes, Ada defines two subsets, identified as the Ravenscar and Jorvik profiles (see http://www.ada-auth.org/standards/22aarm/html/AA-D-13.html), which both support protected types, albeit with some restrictions.

Gnat provides light runtimes that run on e.g. any Cortex-M4. Found in directory arm-eabi/lib/gnat and specified in a gpr file with:

for Runtime ("ada") use "light-cortex-m4";

I believe they may be more restricted than Jorvik or Ravenscar. Perhaps they are not Ada standard then? I doubt that I would be using Ada without them though as creating a runtime for a new chip appears to be fairly time consuming, especially for a low power chip, where system clock speeds may change frequently.

This is the page that got me sailing with Ada.

"https://blog.adacore.com/ada-on-any-arm-cortex-m-device-in-just-a-couple-minutes"

The runtime that I am using does not support protected objects and I am uncertain how much work would be required to enable protected objects.

Ada does more than enough for me to be very happy with it. I am not complaining. Simply wondering what is best for further adoption of Ada. I am glad to hear that the light runtimes are getting significant consideration and was happy when the bounded package appeared after the switch from zfp (zero footprint) to light that I believe happened in Gnat 11 or 12.

sttaft commented 9 months ago

Here is a description of the three "levels" of GNAT run times (standard, embedded, and light):

https://docs.adacore.com/gnat_ugx-docs/html/gnat_ugx/gnat_ugx/gnat_runtimes.html#predefined-gnat-pro-run-times

As you might have discovered, the "light" run times do not support tasking, while the "embedded" run times do. You could download the source for the embedded run time to see how much code might be needed to support a bare bones protected type feature.

kevlar700 commented 9 months ago

I have considered that but maintaining that porting ability for new chips may be more work and represent more uncertainty than adapting any code that requires protected objects to no longer use protected objects. Additionally a percentage of potential Ada users certainly would not match that effort. Though perhaps it would apply across all cortex-m4. Unfortunately, I cannot afford the time to find out.

kevlar700 commented 9 months ago

Today I noticed that if you want to output in a different base such as hex then you have to write a function yourself.

"https://stackoverflow.com/questions/13872022/convert-integer-value-to-hexadecimal-in-ada"

I assume because that function chose to utilise a put at it's root using File_Type perhaps for maintainability. It is quite straight forward to just use a Characters position and something that I could contribute to if I had time. The harder part would be working out how to integrate it into Gnat Ada.Text_IO.Integer_IO or switch upon a light (cortex/zfp) runtimes use.

This procedure could quite easily be written in such a way as to be perfectly compatible with ZFP, yet it is not.

procedure Put(To   : out String;
              Item : in Num;
              Base : in Number_Base := Default_Base);

"http://www.ada-auth.org/standards/12rm/html/RM-A-10-8.html#p18"

Does this demonstrate a lack of consideration not in Ada but in the implementation, in this case? Perhaps embedded being a priority for Ada has not carried through so well into the implementations.

sttaft commented 9 months ago

I am not sure I understand your comment. The standard Ada.Text_IO.Integer_IO includes an operation for putting a hex value to a string. Are you asking to include this in the ZFP subset?

Unfortunately, it is not trivial to find the perfect subset which includes all of what folks might want in a light runtime, and nothing more. It is straightforward to write a function that produces a hexadecimal string from an integer, but it is also something that not everyone using a light runtime needs, so it ends up in the "roll your own" bucket. You will almost certainly have a collection of extra "utility" functions like this. Given that the full GNAT runtime is available in source form, you should not be afraid to copy the bits and pieces of it that you would find useful into such a set of utility packages.

kevlar700 commented 9 months ago

I have created my own array hex dump routines from scratch but would rather not have spent the time. Still far nicer than pulling in Cs precarious printf though.

If some functionality benefits from tasks or protected types or other runtime features then I can understand why so much code does not run on a bare runtime. The functionality in question is perfectly compatible with a bare runtime. I therefore expect that the code simply needs refactoring and so surely that is just poor design or lack of consideration? I shall have to delve deeper but I assume the file type routine was simply implemented first.

My point is that all procedures that could without negative consequences run on a bare runtime, should, at least in the standard libraries?