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
next prev 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