4.9 Global Declarations

The following sections describe the global declarations in DML. These
can only occur on the top level of a DML program, i.e., not within an
object or method. Unless otherwise noted, their scope is the entire
program.

4.9.1 Import Declarations

import filename;

Imports the contents of the named file. filename must be a string
literal, such as "utility.dml". The -I option to the
dmlc compiler can be used to specify directories to be searched
for import files.

Note that imported files are parsed as separate units, and use their own
language version and bit order declarations.

4.9.2 Template Declarations

template namedesc { ... }

Defines a named template - a piece of code that can be reused
in multiple locations. This is similar to a C preprocessor macro;
however, unlike macros, the body cannot consist of arbitrary text, but
must have the same form as an object declaration body. Also, DML
templates do not take any arguments; instead, the generic DML parameter
system is used for such purposes.

Templates are instantiated using is declarations, written as

is name;

These can be used in any context where an object declaration may be
written, and has the effect of expanding the body of the template at the
point of the is. Note that the expansion is purely textual, so
e.g., two templates which define methods with the same name cannot both
be used in the same context.

As in an object declaration, unless the desc string is
omitted, it is equivalent to defining the parameter desc, as in

template name {
parameter desc = desc;
...
}

Hence, the description does not pertain to the template in itself, but
to any object which uses the template.

4.9.3 Bitorder Declarations

bitorder name;

Selects the default bit order to be used for interpreting bit-slicing
expressions and bit field declarations in the file. name
is one of the identifiers le, be16, be32, and
be64, implying either little-endian order with arbitrary
default width (le), or big-endian order with a fixed default
width in bits (be...). Only the listed widths are allowed.

A bitorder declaration, if present, must follow immediately
after the device declaration, preceding any other global
declarations. The scope of the declaration is the whole of the file it
occurs in. If no bitorder declaration is present in a file, the
default bit order is le (little-endian). The bitorder does not
extend to imported files; for example, if a file containing a
declaration "bitorder be32;" imports a file with no bit order
declaration, the latter file will still use the default le
order.

Note that it is difficult to write general bit-manipulating methods for
arbitrary-width data, if big-endian conventions are used. It is often a
better idea to place such code in a separate file which uses
little-endian order, and then import that file from a big-endian
context.

4.9.4 Constant Declarations

constant name = expr;

Defines a named constant which can be used in C context.
expr must be a constant-valued expression.

4.9.5 Loggroup Declarations

loggroup name;

Defines a log group, for use in log statements. More generally,
the identifier name is bound to an unsigned integer
value that is a power of 2, and can be used anywhere in C context; this
is similar to a constant declaration, but the value is
allocated automatically so that all log groups are represented by
distinct powers of 2 and can be combined with bitwise or (see
Section 4.11.7).

4.9.6 Typedef Declarations

typedef declaration;

Defines a name for a data type, as in C.

4.9.7 Struct Declarations

struct name { declarations }

Declares a structure datatype with the given name; this is similar to a
C struct declaration, but in DML, there is no separate
namespace for structs. The effect is like that of writing "typedef
struct { ... } name;" in C, although in DML,
name can also be used for recursive definitions within
the struct, as in

struct my_struct {
my_struct *next;
...
}

4.9.8 Extern Declarations

extern declaration;

Declares an external identifier, similar to a C extern
declaration; for example,

4.9.9 Header Declarations

header %{
...
%}

Specifies a section of C code which will be included verbatim in the
generated C header file for the device. There must be no whitespace
between the % and the corresponding brace in the %{
and %} markers. The contents of the header section are not
examined in any way by the dmlc compiler; declarations made
in C code must also be specified separately in the DML code proper.

This feature should only be used to solve problems that cannot easily be
handled directly in DML. It is most often used to make the generated
code include particular C header files, as in:

header %{
#include "extra_defs.h"
%}

See also footer declarations, below.

4.9.10 Footer Declarations

footer %{
...
%}

Specifies a piece of C code which will be included verbatim at the end
of the generated code for the device. There must be no whitespace
between the % and the corresponding brace in the %{
and %} markers. The contents of the footer section are not
examined in any way by the dmlc compiler.

This feature should only be used to solve problems that cannot easily be
handled directly in DML. See also header declarations, above.