Welcome to the Devil Homepage
Devil: A DEVice Interface Language
Devil (DEVice Interface
Language) is an IDL
aimed at providing the lower layer of a device driver, i.e., the basic
interaction with the device. A Devil specification rigorously
describes the access mechanisms, the type and the layout of data that
are exchanged to operate the device, as well as some behavioral
properties. It does not assume any particular OS, and can therefore
be used for any target platform.
How to get Devil?
The present distribution contains the Devil compiler (named taz) as a binary
and a set of specifications for testing it.
Please note that this release is an alpha version. There are many known
limitations.
NEW Source code of the Taz compiler released under LGPL.
Related Papers
-
A Language Approach to the Development of Robust Device Driver (in french)
L. Réveillère
In Ph.D. Thesis, University of Rennes (France), December 2001.
-
Dealing with Hardware in Embedded Software: A Retargetable Framework
Based on the Devil Language
F. Mérillon and G. Muller
IRISA Research Report 1391, revised version in
LCTES-2001
-
Cours de DEA sur les langages dédiés (pdf), in french
-
Improving Driver Robustness: an Evaluation of the Devil Approach
L. Réveillère and G. Muller
IRISA Research Report 1385, revised version to appear in DSN-2001
-
Devil: An IDL for Hardware programming
F. Mérillon, L. Réveillère, C. Consel, R. Marlet, and G. Muller
In OSDI
2000, pages 17-30, San Diego, October 2000. [Slides]
-
A DSL
Approach to Improve Productivity and Safety in Device Drivers Development
L. Réveillère, F. Mérillon, C. Consel, R. Marlet,
and G. Muller
In ASE 2000, Grenoble, September 2000.[Slides]
-
Towards
Robust OSes for Appliances: A New Approach Based on Domain-Specific Languages
G. Muller, C. Consel, R. Marlet, L.P. Barreto, F. Mérillon,
and L. Réveillère
In ACM SIGOPS European Workshop 2000 (EW2000), pages 249-249, Rennes,
Juin 1999. [Slides]
Reference manual
How to use the taz compiler?
The taz compiler takes a Devil specification as an input and generates
a C interface that implements this specification.
The following options can be used in the command line :
-o filename Set
the name of the output file (defaults to inputname.h where inputname
is the name of the input file)
-nocode
Do
not generate code, only verifications are performed
-version
Display version information
How to use the generated C interface?
Suppose that we have the following Devil specification :
device foo
(base : bit[8] port @{0..1})
{
register cmd
= write base@0,
mask '1011 0...'
: bit[8];
register stat
= read base@1,
mask '**** **..'
: bit[8];
variable command=
cmd[2..0] : {
ON
=> '100',
OFF
=> '000',
BLINK => '101'
};
structure status
= {
variable ready
= stat[1], volatile : bool;
variable died
= stat[0], volatile : bool;
};
}
|
Once compiled, a C interface is produced from this specification.
The following types, variables, and functions are defined :
-
Device : the type dev_foo is created. The driver must
declare a variable of this type and call the function init_foo(base)
to specify the value of each parameter of the Devil specification;
-
void init_foo(dev_foo *dev, t1 param1, ...)
-
dev_foo *new_foo(int priority, t1 param1, ...) where priority
is the priority to use for the kernel malloc function
-
Boolean : the boolean type bool is declared and have values
true and false;
-
Types : A type bar_t is declared for each type bar
defined
in the specification. For anonymous types, the name used is the concatenation
of the variable name (on which the type was attached) and the string "_t";
-
Variables : For each variable xxx, of type ttt, defined
in the specification, two functions get_xxx and set_xxx are
created with the following prototypes :
-
ttt get_xxx(dev_foo *dev)
-
void set_xxx(dev_foo *dev, ttt val)
Note that a call to get_xxx or set_xxx induces
-
an update of a cache if the variable is a structure field (no physical
read or write)
-
a read or write to the registers that map xxx otherwise.
-
Structures : For each structure S, defined in the specification,
two functions get_S and set_S are created with the following
prototypes :
-
void get_S(dev_foo *dev)
-
void set_S(dev_foo *dev)
Note that a call to get_S or set_S induces a read or write
of all variables grouped inside the structure (physical read or write).
-
Common functions : Some functions are generated in order to manipulate
Devil types and values in C.
-
int dil_eq(t1 x, t1 y) where t1
is a Devil type, returns 1 iff x = y, 0 otherwise.
-
DIL_SWITCH(x) : macro to use instead of "switch x" when x has
a Devil type
-
DIL_CASE(x) : macro to use instead of "case x" when
x has a Devil type
The produced interface can be used in two differents modes, with references
or without.
-
With reference : (default) In this mode, all functions need a pointer
to a device structure as a parameter. This mode is often used when the
driver has to manipulate several devices. Here, is an example for using
the C interface :
-
Without reference : In this mode, the device structure is automatically
allocated once, the new function is not created and each function
is prefixed by the name of the device. This name can be modified with the
dev_name
flag. Functions get and set becomes :
-
ttt get_xxx() and void set_xxx(ttt val) for variables
-
void get_S() and void set_S() for structures
Here is an example for using the C interface in this mode and naming the
targeted device as foo1
#define DEVIL_NO_REF
#define dev_name foo1
#include "foo.dil.h" |
For efficiency purpose, the generated interface can be used with
3 different levels of type safety
-
level 0 : (default) Types are represented with C native types, without
any overhead. No run-time checks are performed
-
level 1 : All Devil types (excepted bool) are fresh C types.
The cost penalty is non nul but really weak. Code is inserted to
enable run-time verifications. The DEVIL_DEBUG flag must be set
in order to select this type safety level.
#define DEVIL_DEBUG
... /* depends on the mode used REF/NO_REF
*/
#include "foo.dil.h" |
-
level 2 : The same level that level 1, plus the fact that the bool
type is also a fresh type. The driver cannot consider a boolean value as
an integer. To select this mode, set the DEVIL_BOOL_TYPED flag.
The DEVIL_DEBUG flag must be set for this mode. Here is an example
of using this mode.
#define DEVIL_DEBUG
#define DEVIL_BOOL_TYPED
... /* depends on the mode used REF/NO_REF
*/
#include "foo.dil.h" |
Real driver performances
In order to evaluate the benefit and impact of Devil in driver development,
we are currently re-engineering various Linux drivers which run on recent bi-processor
PCs installed in our group.1
IDE Driver
Table 1 presents a performance comparison of a Devil-based
IDE driver against the original C driver. Throughput measurements were obtained
using the standard Linux hdparm utility. Two Devil specifications have
been written for this driver: a specification of the IDE controller and a specification
of the Intel PIIX4 PCI busmater IDE.
We have run the IDE driver in both Ultra DMA-2 and several PIO modes,
varying the size of I/O (16 or 32 bits) and the number of sectors transfered
per interrupts. In DMA mode, Devil induces 6 additional I/O operations
to prepare the command. Because of the duration of the DMA transfer, there
is no impact on the available throughput. In PIO modes, there are 3 additional
I/O operations to prepare the command, plus 2 for each interrupt (#s
denotes the total number of sectors of the access). On specific processors
such as those of the Pentium family, replacing a C loop over a variable
read/write by a dedicated looping instruction (e.g., rep)
is often more efficient. This situation can be found for the Programmed
I/O (PIO) transfer mode of the IDE Linux driver; using a C loop induces
a 10% throughput penalty.
| |
Standard driver |
Devil driver |
|
|
|
|
|
|
|
|
|
| Devil/Stand. |
| throughput |
| ratio |
|
| DMA |
- |
- |
14 |
14.25 |
20 |
14.25 |
100 % |
| PIO |
16 |
32 |
7+#s(1+128)/16 |
8.17 |
10+#s(3+128)/16 |
7.36 |
90 % |
| 16 |
7+#s(1+256)/16 |
4.45 |
10+#s(3+256)/16 |
3.94 |
88 % |
| 8 |
32 |
7+#s(1+128)/8 |
8.09 |
10+#s(3+128)/8 |
7.28 |
89 % |
| 16 |
7+#s(1+256)/8 |
4.42 |
10+#s(3+256)/8 |
3.91 |
88 % |
| 1 |
32 |
7+#s(1+128) |
6.93 |
10+#s(3+128) |
6.36 |
91 % |
| 16 |
7+#s(1+256) |
4.06 |
10+#s(3+256) |
3.63 |
89 % |
Table 1: IDE Linux driver comparative performance results
X11 Driver
Tables 2.1 and 2.2
present a performance comparison of a Devil-based X11 driver against the original
C driver. Throughput measurements were obtained using the xbench
utility.
An X11 driver is a module which is built into an X11 server. Unlike most Linux
drivers, an X11 driver is therefore not a kernel module : it runs in user-mode.
In our experiment, we used the 3DLabs-dedicated server from the popular Xfree86
implementation of X11 (version 3.3.6). This server includes a driver for 3DLabs'
Permedia2 graphics controller. Although this chip provides acceleration for
both 2D and 3D, the X11 server does not take advantage of 3D. Moreover, to minimize
hardware-dependant code, the server implements many 2D primitives in software.
Hardware acceleration is only used for the two most time-consuming primitives :
filled rectangle and screen area copy. Tables below present results for both
of these accelerated primitives.
The number of drawn pixels and the depth (number of bits) of each pixel influence
the completion time of a primitive. Indeed, the higher these figures are, the
more video RAM is accessed, and the busier the graphics controller is. Since
the CPU is only used for triggering the controller, driver optimization is more
important when primitive calls are light and quick. We therefore conducted tests
in various contexts, and the slight CPU overhead introduced by Devil showed
only for the lightest calls. For primitive calls involving at least 100 pixels
(which are the most common in pratice), 99% to 100% of the speed were retained
(always 100% at 24 bits, the most common depth). For the tiny 4-pixel calls,
results ranged 94%-100% (97%-100% at 24 bits). We therefore can conclude that
using Devil in this driver did not introduce any significant performance penalty.
Note : Due to the programming model of Permedia2, the driver must wait (busy
loop) for free entries in an on-chip FIFO before accessing the chip. Such loops
take one I/O per iteration. In the tables, the number of I/O operations is given
with a w variable, which is the average number of I/Os per waiting loop.
For example, 3w + 15 means that the driver performs 3 waiting loops,
plus 15 useful I/Os.
| |
Standard Driver
|
Devil Driver
|
|
Display Mode
(bits/pixel)
|
Rectangle Size
(pixels)
|
I/O
Operations
|
Troughput
(rectangles/s)
|
I/O
Operations
|
Troughput
(rectangles/s)
|
Devil/Standard
Troughput Ratio
|
|
8
|
2 x 2
|
3w + 15
|
984838
|
3w + 17
|
949052
|
96 %
|
|
10 x 10
|
589621
|
585350
|
99 %
|
|
100 x 100
|
38472
|
38438
|
100 %
|
|
400 x 400
|
3762
|
3762
|
100 %
|
|
16
|
2 x 2
|
3w + 15
|
982338
|
3w + 17
|
945916
|
96 %
|
|
10 x 10
|
333670
|
332499
|
100 %
|
|
100 x 100
|
21022
|
21033
|
100 %
|
|
400 x 400
|
2221
|
2221
|
100 %
|
|
24
|
2 x 2
|
2w + 10
|
978605
|
2w + 10
|
945884
|
97 %
|
|
10 x 10
|
235119
|
234716
|
100 %
|
|
100 x 100
|
3693
|
3693
|
100 %
|
|
400 x 400
|
244
|
243
|
100 %
|
|
32
|
2 x 2
|
3w + 15
|
957534
|
3w + 17
|
929833
|
97 %
|
|
10 x 10
|
251522
|
251584
|
100 %
|
|
100 x 100
|
10466
|
10466
|
100 %
|
|
400 x 400
|
899
|
899
|
100 %
|
Table 2.1 : Comparative Performance of Permedia2 Xfree86
Driver : Rectangle Test
| |
Standard Driver
|
Devil Driver
|
|
Display Mode
(bits/pixel)
|
Copy Size
(pixels)
|
I/O
Operations
|
Troughput
(copies/s)
|
I/O
Operations
|
Troughput
(copies/s)
|
Devil/Standard
Troughput Ratio
|
|
8
|
2 x 2
|
3w + 15
|
149553
|
3w + 17
|
144494
|
97 %
|
|
10 x 10
|
123584
|
122300
|
99 %
|
|
100 x 100
|
10662
|
10638
|
100 %
|
|
400 x 400
|
764
|
764
|
100 %
|
|
16
|
2 x 2
|
3w + 15
|
145084
|
3w + 17
|
136755
|
94 %
|
|
10 x 10
|
85994
|
85561
|
99 %
|
|
100 x 100
|
3502
|
3512
|
100 %
|
|
400 x 400
|
238
|
238
|
100 %
|
|
24
|
2 x 2
|
2w + 9
|
144385
|
2w + 9
|
144521
|
100 %
|
|
10 x 10
|
77443
|
77605
|
100 %
|
|
100 x 100
|
1716
|
1716
|
100 %
|
|
400 x 400
|
114
|
114
|
100 %
|
|
32
|
2 x 2
|
2w + 9
|
142335
|
2w + 9
|
142598
|
100 %
|
|
10 x 10
|
69762
|
69804
|
100 %
|
|
100 x 100
|
1703
|
1701
|
100 %
|
|
400 x 400
|
111
|
111
|
100 %
|
Table 2.2 : Comparative Performance of Permedia2 Xfree86
Driver : Screen Copy Test
- 1
The PC is a DELL Precision 210 with the following configuration:
two Pentium II 450 MHz, Intel PIIX4 PCI chipset, Maxtor model 91000D8 UDMA2
19.5Gb disk (512Kb cache), 3DLabs Permedia2 Graphics Controller.
Contact the Devil development team
Bug reports and messages can be send to the Devil development team:
devil@labri.fr
The Devil mailing list devil-users@labri.fr: subscribe to devil-users@labri.fr (send the message "subscribe devil-users@labri.fr" to majordomo@labri.fr).
Last modified: jeudi, 25-sep-2003 16:25:24 CEST
- Laurent.Reveillere@labri.fr