comp.lang.ada
 help / color / mirror / Atom feed
From: Brian Drummond <brian3@shapes.demon.co.uk>
Subject: Re: Exclude parts of a package
Date: Fri, 06 Dec 2013 11:41:50 GMT
Date: 2013-12-06T11:41:50+00:00	[thread overview]
Message-ID: <2Kiou.15508$bz3.2509@fx24.fr7> (raw)
In-Reply-To: 52a0de7e$0$23162$2c885b36@post.eweka.nl

On Thu, 05 Dec 2013 21:13:50 +0100, Felix Krause wrote:

> In C, I have the possibility to switch parts of my code on or off with
> preprocessor defines. What would be the Ada way to do something like
> that?
> 
> I know that I can use scenario variables with gprbuild. This works well
> if I want to include or exclude whole packages (because I can include or
> exclude certain files), but it does not work if I just want to exclude
> certain subroutines from a package.
> 
> Take for example OpenCLAda: The user of the library should be able to
> choose which version of the OpenCL API he wants to use (1.0, 1.1, …).
> This choice should result in subroutines added in newer versions not
> being available.

I would tend to avoid the preprocessor - even the Gnat one - if at all 
possible.

The basic idea is to separate out variant functionality into different 
packages for each revision - maybe OpenCL_1_0, OpenCL_1_1, etc.

Then with/use a base package, OpenCL, in all your application code.

When you come to build the program, you create the package OpenCL 
appropriately : it can be as simple as:

with OpenCL_1_1;
package Open_CL renames OpenCL_1_1;

--------------------------------------------------------------------

In the MSP430 Ada compiler this approach is extended to support 450+ 
different varieties of the MSP430 embedded processor, each with a 
different set of peripherals, and the peripherals themselves vary, not 
just in register addresses but also functionality (e.g. 8 and 16 bit 
timers). If the OpenCL variants are in different categories such as math 
precision, number of cores, etc this sub-package approach may be useful.

A worked example:

Device selection is in package CPU.ads :
with MSP.msp430g2553;
package CPU renames MSP.msp430g2553;

(Everything else - CPUs and peripherals are child packages of package MSP)
package MSP is

   pragma Pure;

   type Byte is Array(0 .. 7) of Boolean;
   Pragma Pack(Byte);
   For Byte'Size use 8;
...
end MSP;

The specific CPU package, MSP.msp430g2553; looks like

with MSP.cpu_5;
with MSP.adc10;
with MSP.port1_r_3;
...
with MSP.ta3_1;
with MSP.vectors_18;
 
package MSP.msp430g2553 is
 
   pragma Preelaborate;
 
   package cpu              renames MSP.cpu_5;
   package adc10            renames MSP.adc10;
   package port1_r          renames MSP.port1_r_3;
...
   package ta3              renames MSP.ta3_1;
   package vectors          renames MSP.vectors_18;
 
end MSP.msp430g2553;
 
as you can see, it selects the 5th variant of the CPU, the 3rd variant of 
Port 1 (a GPIO port) and the 18th variant of the interrupt vector table.

It turns out that there are 19 variants of package MSP.cpu, 5 of port1_r, 
and 84 variants of the interrupt vector table. 

A vector table package looks like:

with Interfaces;  use Interfaces;    --   make unsigned_n visible 
package MSP.vectors_18 is
   pragma Preelaborate;
 
   port1_vector           : constant unsigned_16 :=    16#4#;    
   port2_vector           : constant unsigned_16 :=    16#6#;    
   adc10_vector           : constant unsigned_16 :=    16#A#;     
   timer0_a0_vector       : constant unsigned_16 :=   16#12#;   
   timer1_a1_vector       : constant unsigned_16 :=   16#18#;   
...
   nmi_vector             : constant unsigned_16 :=   16#1C#; 
   reset_vector           : constant unsigned_16 :=   16#1E#;  
 
end MSP.vectors_18;

And finally a fragment of an application : 
-----------------------------
with CPU;

procedure Watch is
   package Timer renames CPU.ta3;
   subtype TickCount is Interfaces.Unsigned_16;
   OneMinute      : constant TickCount := 1024*60;	
begin
   Timer.ccr0    := OneMinute - 1;	
... and so on.
-----------------------------

Now I can change package CPU
with MSP.msp430g2202;
package CPU renames MSP.msp430g2202;
and recompile. 

If I have used any facilities missing in the new CPU, I find out at 
compile time. 

If the timer interrupt vector has been renamed timer_a0_vector (as it has 
in some other CPUs) it is reported as undeclared.
Then the CPU package MSP.msp430g2202 tells me which variant of the 
interrupt vector package I am using, 
   package vectors          renames MSP.vectors_28;
and MSP.vectors_28 gives me the new name. 
Most packages are a page or so, so fairly easy to browse.

There are 450-odd CPU packages, and about 350 peripheral description 
packages (inc. 84 interrupt vector tables) so this gives pretty good 
reuse. 

In contrast, the C toolchain takes the preprocessor approach, and each 
CPU variant has its own #include file ranging from 500 to over 6000 
lines; not so easy!

The Ada packages are auto-generated from the original #includes, and 
simplify 60MB of #includes into 1.2MB of CPUs and under 5MB of peripheral 
packages.

I'm happy without the preprocessor.

If you're interested in the how, the complete example is at 
https://sourceforge.net/projects/msp430ada/

- Brian



  parent reply	other threads:[~2013-12-06 11:41 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-12-05 20:13 Exclude parts of a package Felix Krause
2013-12-06  1:58 ` gautier_niouzes
2013-12-06  7:51 ` Chris Moore
2013-12-06  8:04 ` playerdark
2013-12-06 11:14 ` Brian Drummond
2013-12-06 11:14 ` Brian Drummond
2013-12-06 11:41 ` Brian Drummond [this message]
2013-12-06 20:48   ` Felix Krause
2013-12-06 21:27     ` Shark8
2013-12-07  8:41       ` Felix Krause
2013-12-07 11:55         ` Brian Drummond
2013-12-08 20:00 ` Stephen Leake
2013-12-12 14:30   ` Marius Amado-Alves
2013-12-13 13:16     ` Felix Krause
2013-12-13 16:17     ` Stephen Leake
2014-01-02 15:06       ` Marius Amado-Alves
2014-01-02 15:07       ` Marius Amado-Alves
replies disabled

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