Runtime for RISC-V softcore

I’d like to create a custom runtime for the Microchip MI-V softcores. They are not 100% supported by the GNAT runtimes, since they have no support for the “c” (compressed instructions) extension. So rv32-im is missing the “a” and rv32-imac has the additional “c”. Of course the code runs with rv32-im anyway and “a” is typically not required without SMP (as far as I know).

Nevertheless I like to use the CoreUARTapb peripheral for standard Put, so a custom runtime makes sense.

Now my main issue: The core can be configured with or without FPU. Since the only difference between rv32-imac and rv32-imafc is the runtime.xml with the the -march and -mabi compiler flags, I’d like to make those flags configurable using alire. Can I just remove the runtime.xml and put the switches into the runtime_build.gpr?

Switches in runtime.xml are used for all compilation units, while from runtime_build.gpr for runtime units only.

PS. I’m trying to evaluate another way to manage runtimes, see

Announce: bare board runtime generator version 0.0.1

I haven’t tried, but you could maybe potentially modify the runtime.xml to have the choice there, based on the alire’s config gpr file. The XML is runtime.xml is really just a template for a .gpr file, so I would think it would allow you to put in case statements and such? Again, I haven’t tested, but something to look at.

AFAIK, when the RISC-V toolchain is built, several Ada runtimes are automatically built. They have several combinations. It seems that your specific combination is not taking place (ima), as imac tends to be the more common one.

Nevertheless, the compiler can compile any and all combinations that you may want, so if you pass the ima combination to march with the corresponding mabi if necessary, GNAT/GCC will use the ima instruction set. So you could try and do what is documented here https://stackoverflow.com/questions/26337516/how-to-make-gnatmake-tool-compile-rts-with-project to create your own ima RTS without having to modify and build GNAT from scratch.

I hope this helps,
Fer

P.S.: I have learnt all of this as I have been also playing a bit with RISC-V softcores :slight_smile:

I’m fully aware of that. The source for all those variants is the same, just the runtime.xml differs. Therefore my question was, 1) if I actually need that XML and 2) if yes, how I can modify it using alire. Because I don’t want a full copy of the runtime for each variant of the softcore.

The only way I can see to make -march configurable is to follow the same pattern as Loaders in the runtime.xml, i.e. declare an external variable to specify whether the target has an FPU, then use that to set -march. So your runtime.xml might look something like:

<?xml version="1.0" ?>

<gprconfig>
  <configuration>
    <config><![CDATA[
   type Loaders is ("USER");
   Loader : Loaders := external("LOADER", "USER");

   type Has_FPU_Type is ("True", "False");
   Has_FPU : Has_FPU_Type := external("HAS_FPU", "False");

   package Compiler is
      case Has_FPU is
         when "True" =>
            Common_Required_Switches := ("-march=rv32imaf", "-mabi=ilp32f", "-fno-tree-loop-distribute-patterns");
         when "False" =>
            Common_Required_Switches := ("-march=rv32ima", "-mabi=ilp32", "-fno-tree-loop-distribute-patterns");
      end case;

      for Leading_Required_Switches ("Ada") use
         Compiler'Leading_Required_Switches ("Ada") &
         Common_Required_Switches;
      for Leading_Required_Switches ("C") use
         Compiler'Leading_Required_Switches ("C") &
         Common_Required_Switches;
      for Leading_Required_Switches ("C++") use
         Compiler'Leading_Required_Switches ("C++") &
         Common_Required_Switches;
      for Leading_Required_Switches ("Asm") use
         Compiler'Leading_Required_Switches ("Asm") &
         Common_Required_Switches;
      for Leading_Required_Switches ("Asm2") use
         Compiler'Leading_Required_Switches ("Asm2") &
         Common_Required_Switches;
      for Leading_Required_Switches ("Asm_Cpp") use
         Compiler'Leading_Required_Switches ("Asm_Cpp") &
         Common_Required_Switches;
   end Compiler;

   package Linker is
      for Required_Switches use Linker'Required_Switches &
        ("-Wl,-L${RUNTIME_DIR(Ada)}/adalib",
         "-nostartfiles", "-nolibc",
         "-L${RUNTIME_DIR(ada)}/ld_user") &
         Compiler.Common_Required_Switches;

      case Loader is
         when "USER" =>
      end case;
   end Linker;
]]>
   </config>
  </configuration>
</gprconfig>

Then when building your project, you can set HAS_FPU either on the command line:

alr build -- -XHAS_FPU=True

or in your project’s alire.toml:

[gpr-set-externals]
HAS_FPU = "True"