Appendix: NED Reference

Syntax

NED File Name Extension

NED files have the .ned file name suffix. This is mandatory, and cannot be overridden.

NED File Encoding

NED files are ASCII, but non-ASCII characters are permitted in comments and string literals. This allows for using encodings that are a superset of ASCII, for example ISO 8859-1 and UTF-8.

Note

There is no standard way to specify or determine the encoding of a NED file. It is up to the user to configure the desired encoding in text editors and other tools that edit or process NED files.

String literals (e.g. in parameter values) will be passed to the C++ code as const char * without any conversion; it is up to the simulation model to interpret them using the desired encoding.

Line ending may be either CR or CRLF, regardless of the platform.

Reserved Words

The following words are reserved and cannot be used for identifiers:

Identifiers

Identifiers must be composed of letters of the English alphabet (a-z, A-Z), numbers (0-9), and underscore “_”. Identifiers may only begin with a letter or underscore.

The recommended way to compose identifiers from multiple words is to capitalize the beginning of each word (camel case).

Case Sensitivity

Keywords and identifiers in the NED language are case sensitive. For example, TCP and Tcp are two different names.

Literals

String Literals

String literals use double quotes. The following C-style backslash escapes are recognized: \b, \f, \n, \r, \t, \\, \", and \xhh where h is a hexadecimal digit.

Numeric Constants

Numeric constants are accepted in the usual decimal, hexadecimal (0x prefix), and scientific notations. Octal numbers are not accepted (numbers that start with the 0 digit are interpreted as decimal).

nan, inf, and -inf mean the floating-point not-a-number, positive infinity, and negative infinity values, respectively.

Quantity Constants

A quantity constant has the form (<numeric-constant> <unit>)+, for example 12.5mW or 3h 15min 37.2s. Whitespace is optional in front of a unit but must be present after a unit if it is followed by a number.

When multiple measurement units are present, they have to be convertible into each other (i.e., refer to the same physical quantity).

Section Units of Measurement lists the units recognized by OMNeT++. Other units can be used as well; the only downside being that OMNeT++ will not be able to perform conversions on them.

Null Object References

The keywords null and nullptr are synonymous and denote an object reference that doesn’t refer to any valid object.

Undefined

The keyword undefined denotes the “missing value” value, similar to (void)0 in C/C++. undefined has its own type and cannot be cast to any other type.

Comments

Comments can be placed at the end of lines. Comments begin with a double slash // and continue until the end of the line.

Grammar

The grammar of the NED language can be found in Appendix Appendix: NED Language Grammar.

Built-in Definitions

The NED language has the following built-in definitions, all in the ned package: channels IdealChannel, DelayChannel, and DatarateChannel; module interfaces IBidirectionalChannel and IUnidirectionalChannel. The latter two are reserved for future use.

The bodies of @statistic properties have been omitted for brevity from the following listing.

Note

One can print the full definitions by running opp_run -h neddecls.

package ned;
@namespace(omnetpp);

channel IdealChannel
{
    @class(cIdealChannel);
}

channel DelayChannel
{
    @class(cDelayChannel);
    @signal[messageSent](type=omnetpp::cMessage);
    @signal[messageDiscarded](type=omnetpp::cMessage);
    @statistic[messages](title="messages sent";source=constant1(messageSent);record=count?;interpolationmode=none);
    @statistic[messagesDiscarded](title="messages discarded";source=constant1(messageDiscarded);record=count?;interpolationmode=none);
    bool disabled @mutable = default(false);
    double delay @mutable = default(0s) @unit(s); // propagation delay
}

channel DatarateChannel
{
    @class(cDatarateChannel);
    @signal[channelBusy](type=long);
    @signal[messageSent](type=omnetpp::cMessage);
    @signal[messageDiscarded](type=omnetpp::cMessage);
    @statistic[busy](title="channel busy state";source=channelBusy;record=vector?;interpolationmode=sample-hold);
    @statistic[averageUtilization](title="average channel utilization";source=timeavg(channelBusy);record=last?);
    @statistic[packets](title="packets sent";source=constant1(messageSent);record=count?;interpolationmode=none);
    @statistic[packetBytes](title="packet bytes sent";source=packetBytes(messageSent);record=sum?;unit=B;interpolationmode=none);
    @statistic[packetsDiscarded](title="packets discarded";source=constant1(messageDiscarded);record=count?;interpolationmode=none);
    @statistic[averageThroughput](title="average throughput";source=sumPerDuration(packetBits(messageSent));record=last?;unit=bps);
    bool disabled @mutable = default(false);
    double delay @mutable = default(0s) @unit(s); // propagation delay
    double datarate @mutable = default(0bps) @unit(bps); // bits per second; 0=infinite
    double ber @mutable = default(0); // bit error rate (BER)
    double per @mutable = default(0); // packet error rate (PER)
}

moduleinterface IBidirectionalChannel
{
    gates:
        inout a;
        inout b;
}

moduleinterface IUnidirectionalChannel
{
    gates:
        input i;
        output o;
}

Packages

NED supports hierarchical namespaces called packages. The model is similar to Java packages, with minor changes.

Package Declaration

A NED file may contain a package declaration. The package declaration uses the package keyword and specifies the package for the definitions in the NED file. If there is no package declaration, the file’s contents are in the default package.

Component type names must be unique within their package.

Directory Structure, package.ned

Like in Java, the directory of a NED file must match the package declaration. However, it is possible to omit directories at the top which do not contain any NED files (like the typical /org/``<projectname>`` directories in Java).

The top of a directory tree containing NED files is named a NED source folder.

Note

The OMNeT++ runtime recognizes a NEDPATH environment variable, which contains a list of NED source folders and is similar to the Java CLASSPATH variable. NEDPATH also has a command-line option equivalent.

The package.ned file at the top level of a NED source folder plays a special role.

If there is no toplevel package.ned or it contains no package declaration, the declared package of a NED file in the folder ``<srcfolder>``/x/y/z must be x.y.z. If there is a toplevel package.ned and it declares the package as a.b, then any NED file in the folder ``<srcfolder>``/x/y/z must have the declared package a.b.x.y.z.

Note

package.ned files are allowed in other folders as well. They may contain properties and/or documentation for their package, but cannot be used to define the package they are in.

Components

Simple modules, compound modules, networks, channels, module interfaces and channel interfaces are called components.

Simple Modules

Simple module types are declared using the simple keyword; see the NED Grammar (Appendix Appendix: NED Language Grammar) for the syntax.

Simple modules may have properties (Properties), parameters (Parameters), and gates (Gates).

A simple module type may not have inner types (Inner Types).

A simple module type may extend another simple module type, and may implement one or more module interfaces (Module Interfaces). Inheritance rules are described in section Inheritance, and interface implementation rules in section Implementing an Interface.

Every simple module type has an associated C++ class, which must be a subclass of cSimpleModule. The way of associating the NED type with the C++ class is described in section Resolving the C++ Implementation Class.

Compound Modules

Compound module types are declared using the module keyword; see the NED Grammar (Appendix Appendix: NED Language Grammar) for the syntax.

A compound module may have properties (Properties), parameters (Parameters), and gates (Gates); its internal structure is defined by its submodules (Submodules) and connections (Connections); and it may also have inner types (Inner Types) that can be used for its submodules and connections.

A compound module type may extend another compound module type, and may implement one or more module interfaces (Module Interfaces). Inheritance rules are described in section Inheritance, and interface implementation rules in section Implementing an Interface.

Networks

The network Keyword

A network declared with the network keyword is equivalent to a compound module (module keyword) with the @isNetwork(true) property.

Note

A simple module can only be designated as a network by specifying the @isNetwork property; the network keyword may not be used for that purpose.

The @isNetwork Property

The @isNetwork property is only recognized for simple modules and compound modules. The value may be empty, true, or false:

@isNetwork;
@isNetwork();
@isNetwork(true);
@isNetwork(false);

The empty value corresponds to @isNetwork(true).

The @isNetwork property is not inherited; that is, a subclass of a module with @isNetwork set does not automatically become a network. The @isNetwork property needs to be explicitly added to the subclass to make it a network.

Subclassing may introduce changes to a module that make it unfit to be used as a network.

Channels

Channel types are declared using the channel keyword; see the NED Grammar (Appendix Appendix: NED Language Grammar) for the syntax.

Channel types may have properties (Properties) and parameters (Parameters).

A channel type may not have inner types (Inner Types).

A channel type may extend another channel type, and may implement one or more channel interfaces (Channel Interfaces). Inheritance rules are described in section Inheritance, and interface implementation rules in section Implementing an Interface.

Every channel type has an associated C++ class, which must be a subclass of cChannel. The way of associating the NED type with the C++ class is described in section Resolving the C++ Implementation Class.

The @defaultname property of a channel type determines the default name of the channel object when used in a connection.

Module Interfaces

Module interface types are declared using the moduleinterface keyword; see the NED Grammar (Appendix Appendix: NED Language Grammar) for the syntax.

Module interfaces may have properties (Properties), parameters (Parameters), and gates (Gates). However, parameters are not allowed to have a value assigned, not even a default value.

A module interface type may not have inner types (Inner Types).

A module interface type may extend one or more other module interface types. Inheritance rules are described in section Inheritance.

Channel Interfaces

Channel interface types are declared using the channelinterface keyword; see the NED Grammar (Appendix Appendix: NED Language Grammar) for the syntax.

Channel interfaces may have properties (Properties) and parameters (Parameters). However, parameters are not allowed to have a value assigned, not even a default value.

A channel interface type may not have inner types (Inner Types).

A channel interface type may extend one or more other channel interface types. Inheritance rules are described in section Inheritance.

Resolving the C++ Implementation Class

The procedure for determining the C++ implementation class for simple modules and channels, collectively referred to as components), is identical. It is as follows:

If the component extends another component and has no @class property, the C++ implementation class is inherited from the base type.

If the component contains a @class property, the C++ class name will be composed of the current namespace (see below) and the value of the @class property. The @class property should contain a single value.

Note

The @class property itself may contain a namespace declaration (i.e. may contain “::”).

If the component contains no @class property and has no base class, the C++ class name will be composed of the current namespace and the unqualified name of the component.

Important

Subclassing in NED does not imply subclassing the C++ implementation. If one intends to subclass a simple module or channel in NED as well as in C++, the @class property needs to be explicitly specified in the derived type, otherwise it will continue to use the C++ class from its super type.

Compound modules will be instantiated with the built-in cModule class, unless the module contains the @class property. When @class is present, the resolution rules are the same as with simple modules.

Current Namespace

The current namespace is the value of the first @namespace property found while searching in the following order:

  1. the current NED file

  2. the package.ned file in the current package or the first ancestor package searching upwards

Note

Note that namespaces coming from multiple @namespace properties in different scopes do not nest; rather, the nearest one wins.

The @namespace property should contain a single value.

Properties

Properties are a means of adding metadata annotations to NED files, component types, parameters, gates, submodules, and connections.

Identifying a Property

Properties are identified by name. It is possible to have several properties on the same object with the same name, as long as they have unique indices. An index is an identifier in square brackets after the property name.

The following example shows a property without an index, one with the index index1, and a third with the index index2.

@prop();
@prop[index1]();
@prop[index2]();

Property Value

The value of the property is specified inside parentheses. The property value consists of key=valuelist pairs, separated by semicolons; valuelist elements are separated with commas. Example:

@prop(key1=value11,value12,value13;key2=value21,value22)

Keys must be unique.

If the key+equal sign part (key=) is missing, the valuelist belongs to the default key. Examples:

@prop1(value1,value2)
@prop2(value1,value2;key1=value11,value12,value13)

Most properties use the default key with one value. Examples:

@namespace(inet);
@class(Foo);
@unit(s);

Property values have a liberal syntax (see Appendix Appendix: NED Language Grammar). Values that do not fit the grammar (notably, those containing a comma or a semicolon) need to be surrounded with double quotes.

When interpreting a property value, one layer of quotes is removed automatically, that is, foo and "foo" are the same. Within quotes, escaping works in the same way as within string literals (see Literals).

Example:

@prop(marks=the ! mark, "the , mark", "the ; mark", other marks); // 4 items

Placement

Properties may be added to NED files, component types, parameters, gates, submodules, and connections. For the exact syntax, see Appendix Appendix: NED Language Grammar.

When a component type extends another component type(s), properties are merged. This is described in section Inheritance.

Property Declarations

The property keyword is reserved for future use. It is envisioned that accepted property names and property keys would need to be pre-declared, so that the NED infrastructure can warn the user about mistyped or unrecognized names.

Parameters

Parameters can be defined and assigned in the parameters section of component types. In addition, parameters can also be assigned in the parameters sections of submodule bodies and connection bodies, but those places do not allow adding new parameters.

The parameters keyword is optional and can be omitted without changing the meaning.

The parameters section may also hold pattern assignments (Pattern Assignments) and properties (Properties).

A parameter is identified by a name and has a data type. A parameter may have a value or default value and may also have properties (see Properties).

Accepted parameter data types are double, int, string, bool, xml, and object. Any of the above types can be declared volatile as well (volatile int, volatile string, etc.)

The presence of a data type keyword determines whether the given line defines a new parameter or refers to an existing parameter. One can assign a value or default value to an existing parameter, and/or modify its properties or add new properties.

Examples:

int a;           // defines new parameter
int b @foo;      // new parameter with property
int c = default(5); // new parameter with default value
int d = 5;       // new parameter with value assigned
int e @foo = 5;  // new parameter with property and value
f = 10;          // assignment to existing (e.g.inherited) parameter
g = default(10); // overrides default value of existing parameter
h;               // legal, but does nothing
i @foo(1);       // adds a property to existing parameter
j @foo(1) = 10;  // adds a property and value to existing parameter

Parameter values are NED expressions. Expressions are described in section Expressions.

For volatile parameters, the value expression is evaluated every time the parameter value is accessed. Non-volatile parameters are evaluated only once.

Note

The const keyword is reserved for future use within expressions to define constant subexpressions, i.e. to denote a part within an expression that should only be evaluated once. Constant subexpressions are not currently supported.

The following properties are recognized for parameters: @unit, @prompt, @mutable, @enum, @class.

The @prompt Property

The @prompt property defines a prompt string for the parameter. The prompt string is used when/if a simulation runtime user interface interactively prompts the user for the parameter’s value.

The @prompt property is expected to contain one string value for the default key.

The @unit Property

A parameter may have a @unit property to associate it with a measurement unit. The @unit property should contain one string value for the default key. Examples:

@unit(s)
@unit(second)

When present, values assigned to the parameter must be in the same or in a compatible (that is, convertible) unit. Examples:

double a @unit(s) = 5s;   // OK
double a @unit(s) = 10ms; // OK; will be converted to seconds
double a @unit(s) = 5;    // error: should be 5s
double a @unit(s) = 5kg;  // error: incompatible unit

@unit behavior for non-numeric parameters (boolean, string, XML) is unspecified (may be ignored or may be an error).

The @unit property of a parameter may not be modified via inheritance.

Example:

simple A {
    double p @unit(s);
}
simple B extends A {
    p @unit(mW);  // illegal: cannot override @unit
}

The @mutable Property

When a parameter is annotated with @mutable, the parameter’s value is allowed to be changed at runtime, i.e. after its module has been set up. Parameters without the @mutable property cannot be changed at runtime.

The @enum Property

The @enum property is only recognized for string parameters. It defines a list of accepted values for the parameter. The values are specified as a comma-separated list.

string protocol @enum("udp","tcp");

At runtime, the simulation kernel will raise an error if the parameter is assigned a value not in the list.

The @class Property on Parameters

The @class property on an object parameter specifies the expected C++ class of the parameter’s value. When set, the simulation kernel verifies that objects assigned to the parameter are instances of the given class (or a subclass thereof).

object route @class(inet::L3Address);

Note

This use of @class is unrelated to the component-level @class property that specifies the C++ implementation class of a module or channel (see Resolving the C++ Implementation Class).

Pattern Assignments

Pattern assignments allow one to set more than one parameter using wildcards, and to assign parameters deeper down in a submodule tree. Pattern assignments may occur in the parameters section of component types, submodules and connections.

The syntax of a pattern assignment is <pattern> = <value>.

A pattern consists of two or more pattern elements, separated by dots. The pattern element syntax is defined so that it can accommodate names of parameters, submodules (optionally with index), gates (optionally with the $i/$o suffix and/or index) and connections, and their wildcard forms. (The default name of connection channel objects is channel.)

Wildcard forms may use:

  1. Asterisks: They match zero or more characters except dots.

  2. Numeric ranges, {<start>..<end>} e.g. {5..120} or {..10}. They match numbers embedded in identifiers, that is, a sequence of decimal digit characters interpreted as a nonnegative integer that is within the specified start..end range (both limits are inclusive). Both start and end are optional.

  3. Numeric index ranges,[<start>..<end>]. e.g. [5..120] or [..10]. They are intended for selecting submodule and gate index ranges. They match a nonnegative integer enclosed in square brackets that is within the specified start..end range (both limits are inclusive). Both start and end are optional.

  4. Double asterisks: They match zero or more characters (including dots), and can be used to match more than one parameter path elements.

See the NED language grammar (Appendix Appendix: NED Language Grammar) for a more formal definition of the pattern syntax.

Examples:

host1.tcp.mss = 512B;
host*.tcp.mss = 512B; // matches host, host1, host2, hostileHost, ...
host{9..11}.tcp.mss = 512B; // matches host9/host10/host11, but nothing else
host[9..11].tcp.mss = 512B; // matches host[9]/host[10]/host[11], but nothing else
**.mss = 512B; // matches foo.mss, host[1].transport.tcp[0].mss, ...

Gates

Gates can be defined in the gates section of component types. The size of a gate vector (see below) may be specified at the place of defining the gate, via inheritance in a derived type, and also in the gates block of a submodule body. A submodule body does not allow defining new gates.

A gate is identified by a name, and is characterized by a type (input, output, inout) and optionally a vector size. Gates may also have properties (see Properties).

Gates may be scalar or vector. The vector size is specified with a numeric expression inside square brackets. The vector size may also be left unspecified by writing an empty pair of square brackets.

An already specified gate vector size may not be overridden in subclasses or in a submodule.

The presence of a gate type keyword determines whether the given line defines a new gate or refers to an existing gate. One can specify the gate vector size for an existing gate vector, and/or modify its properties, or add new properties.

Examples:

gates:
  input a;         // defines new gate
  input b @foo;    // new gate with property
  input c[];       // new gate vector with unspecified size
  input d[8];      // new gate vector with size=8
  e[10];           // set gate size for existing (e.g.inherited) gate vector
  f @foo(bar);     // add property to existing gate
  g[10] @foo(bar); // set gate size and add property to existing gate

Gate vector sizes are NED expressions. Expressions are described in section Expressions.

See the Connections section (Connections) for more information on gates.

Recognized Gate Properties

The following properties are recognized for gates: @directIn and @loose. They have the same effect: When either of them is present on a gate, the gate is not required to be connected in the connections section of a compound module (see Connections).

@directIn should be used when the gate is an input gate that is intended for being used as a target for the sendDirect() method; @loose should be used in any other case when the gate is not required to be connected for some reason.

Note

The reason @directIn gates are not required to remain unconnected is that it is often useful to wrap such modules in a compound module, where the compound module also has a @directIn input gate that is internally connected to the submodule’s corresponding gate.

Example:

gates:
    input radioIn @directIn;

Submodules

Submodules are defined in the submodules section of the compound module.

The type of the submodule may be specified statically or parametrically.

Submodules may be scalar or vector. The size of submodule vectors must be specified as a numeric expression inside square brackets.

Submodules may also be conditional.

A submodule definition may or may not have a body (a curly brace delimited block). An empty submodule body is equivalent to a missing one.

Syntax examples:

submodules:
    ip : IP;         // scalar submodule without body
    tcp : TCP {}     // scalar submodule with empty body
    app[10] : App;   // submodule vector

Submodule Type

The simple or compound module type (Simple Modules, Compound Modules) that will be instantiated as the submodule may be specified either statically (with a concrete module type name) or parametrically.

Static Submodule Type

Submodules with a statically defined type are those that contain a concrete NED module type name. Example:

tcp : TCP;

See section Type Name Resolution for the type resolution rules.

Parametric Submodule Type

Parametric submodule type means that the NED type name is given in a string expression. The string expression may be specified locally in the submodule declaration, or elsewhere using typename patterns (see later).

Parametric submodule types are syntactically denoted by the presence of an expression in a pair of angle brackets and the like keyword followed by a module interface type Module Interfaces that a module type must implement in order to be eligible to be chosen. The angle brackets may be empty, contain a string expression, or contain a default string expression (default(...) syntax).

Examples:

tcp : <tcpType> like ITCP;        // type comes from parent module parameter
tcp : <"TCP_"+suffix> like ITCP;  // expression using parent module parameter

tcp : <> like ITCP;               // type must be specified elsewhere

tcp : <default("TCP")> like ITCP; // type may be specified elsewhere;
                                  // if not, the default is "TCP"
tcp : <default("TCP_"+suffix)> like ITCP;
                                  // type may be specified elsewhere;
                                  // if not, the default is an expression

See the NED Grammar (Appendix Appendix: NED Language Grammar) for the formal syntax, and section Resolution of Parametric Types for the type resolution rules.

The @dynamic Property

The @dynamic property is only recognized for submodules. The value may be empty, true or false; @dynamic is equivalent to @dynamic(true).

When a submodule is marked as dynamic inside a compound module, the submodule will not be instantiated when the compound module is created; rather, it is expected that it will be instantiated at runtime, using dynamic module creation. A module created this way will pick up parameter values from the submodule declaration in the NED file as well as from the ini file. Dynamic submodules may be displayed in the graphical NED editor as semi-transparent, allowing them to be edited and configured like other submodules.

The @omittedTypename Property

The @omittedTypename property is recognized on module interfaces, channel interfaces, parametric submodules (like), and parametric connections. It simplifies the construction of highly configurable compound modules where many submodules are optional, by reducing the need for complex conditional connections.

When a parametric submodule’s type name is configured as an empty string (""), the network builder would normally raise an error. If the submodule has an @omittedTypename property (which typically comes from the interface), the specified type is instantiated instead. By convention, this type is a lightweight self-destructing module (e.g. OmittedTcp) that shortcuts its input and output gates during initialization and then removes itself from the compound module. This way, the surrounding connections remain valid even though the submodule is effectively absent, without the compound module needing complicated conditional connection logic.

@omittedTypename is typically specified on the module interface, so that all submodules using that interface inherit the behavior:

moduleinterface ITCP {
    @omittedTypename(OmittedTcp);
}

It may also be specified directly on a submodule or connection, which takes precedence over the interface. If @omittedTypename is present but its value is empty, the submodule will simply not be created (equivalent to being conditionally omitted). For connections with parametric channel types, an empty value means no channel object will be created for the connection.

Conditional Submodules

Submodules may be made conditional using the if keyword. The condition expression must evaluate to a boolean; if the result is false, the submodule is not created, and trying to connect its gates or reference its parameters will be an error.

An example:

submodules:
  tcp : TCP if withTCP { ... }

Parameters, Gates

A submodule body may contain parameters (Parameters) and gates (Module Interfaces).

A submodule body cannot define new parameters or gates. It is only allowed to assign existing parameters, and to set the vector size of existing gate vectors.

It is also allowed to add or modify submodule properties and parameter/gate properties.

Connections

Connections are defined in the connections section of the compound module.

Connections may not span multiple hierarchy levels, that is, a connection may be created between two submodules, a submodule and the compound module, or between two gates of the compound module.

Normally, all gates must be connected, including submodule gates and the gates of the compound module. When the allowunconnected modifier is present after connections, gates will be allowed to be left unconnected.

Note

The @directIn and @loose gate properties are alternatives to the connections allow­unconnected syntax; see Gates.

Connections may be conditional, and may be created using loops (see Conditional and Loop Connections, Connection Groups).

Connection Syntax

The connection syntax uses arrows (-->, <--) to connect input and output gates, and double arrows (<-->) to connect inout gates. The latter is also said to be a bidirectional connection.

Arrows point from the source gate (a submodule output gate or a compound module input gate) to the destination gate (a submodule input gate or a compound module output gate). Connections may be written either left to right or right to left, that is, a-->b is equivalent to b<--a.

Gates are specified as <modulespec>.<gatespec> (to connect a submodule), or as <gatespec> (to connect the compound module). <modulespec> is either a submodule name (for scalar submodules), or a submodule name plus an index in square brackets (for submodule vectors). For scalar gates, <gatespec> is the gate name; for gate vectors it is either the gate name plus a numeric index expression in square brackets, or <gatename>++.

The <gatename>++ notation causes the first unconnected gate index to be used. If all gates of the given gate vector are connected, the behavior is different for submodules and for the enclosing compound module. For submodules, the gate vector expands by one. For the compound module, it is an error to use ++ on a gate vector with no unconnected gates.

Syntax examples:

connections:
   a.out --> b.in;   // unidirectional between two submodules
   c.in[2] <-- in;   // parent-to-child; gate vector with index
   d.g++ <--> e.g++; // bidirectional, auto-expanding gate vectors

The reason it is not supported to expand the gate vector of the compound module is that the module structure is built in top-down order: new gates would be left unconnected on the outside, as there is no way in NED to “go back” and connect them afterwards.

When the ++ operator is used with $i or $o (e.g. g$i++ or g$o++, see later), it will actually add a gate pair (input+output) to maintain equal gate size for the two directions.

The syntax to associate a channel (see Channels) with the connection is to use two arrows with a channel specification in between (see later). The same syntax is used to add properties such as @display to the connection.

Inout Gates

An inout gate is represented as a gate pair: an input gate and an output gate. The two sub-gates may also be referenced and connected individually, by adding the $i and $o suffix to the name of the inout gate.

A bidirectional connection (which uses a double arrow to connect two inout gates), is also a shorthand for two uni-directional connections; that is,

a.g <--> b.g;

is equivalent to

a.g$o --> b.g$i;
a.g$i <-- b.g$o;

In inout gate vectors, gates are always in pairs, that is, sizeof(g$i)==sizeof(g$o) always holds. It is maintained even when g$i++ or g$o++ is used: the ++ operator will add a gate pair, not just an input or an output gate.

Specifying Channels

A channel specification associates a channel object with the connection. A channel object is an instance of a channel type (see Channels).

Note

As bidirectional connections are a shorthand for a pair of uni-directional connections, they will actually create two channel objects, one for each direction.

The channel type to be instantiated may be implicit, or may be specified statically or parametrically.

A connection may have a body (a curly brace delimited block) for setting properties and/or parameters of the channel.

A connection syntax allows one to specify a name for the channel object. When not specified, the channel name will be taken from the @defaultname property of the channel type; when there is no such property, it will be "channel". Custom connection names can be useful for easier addressing of channel objects when assigning parameters using patterns.

See subsequent sections for details.

Implicit Channel Type

If the connection syntax does not say anything about the channel type, it is implicitly determined from the set of connection parameters used.

Syntax examples for connections with implicit channel types:

a.g <--> b.g; // no parameters
a.g <--> {delay = 1ms;} <--> b.g;  // assigns delay
a.g <--> {datarate = 100Mbps; delay = 50ns;} <--> b.g; // assigns delay and datarate

For such connections, the actual NED type to be used will depend on the parameters set in the connection:

  1. When no parameters are set, ned.IdealChannel is chosen.

  2. When only ned.DelayChannel parameters are used (delay and disabled), ned.DelayChannel is chosen.

  3. When only ned.DatarateChannel parameters are used (datarate, delay, ber, per, disabled), the chosen channel type will be ned.DatarateChannel.

Connections with implicit channel types may not use any other parameter.

Static Channel Type

Connections with a statically defined channel type are those that contain a concrete NED channel type name.

Examples:

a.g <--> FastEthernet <--> b.g;
a.g <--> FastEthernet {per = 1e-6;} <--> b.g;

See section Type Name Resolution for the type resolution rules.

Parametric Channel Type

Parametric channel types are similar to parametric submodule types, described in section Submodules.

Parametric channel type means that the NED type name is given in a string expression. The string expression may be specified locally in the connection declaration, or elsewhere using typename patterns (see later).

Parametric channel types are syntactically denoted by the presence of an expression in a pair of angle brackets and the like keyword followed by a channel interface type Channel Interfaces that a channel type must implement in order to be eligible to be chosen. The angle brackets may be empty, contain a string expression, or contain a default string expression (default(...) syntax).

Examples:

a.g++ <--> <channelType> like IMyChannel <--> b.g++;
                                  // type comes from parent module parameter
a.g++ <--> <"Ch_"+suffix> like IMyChannel <--> b.g++;
                                  // expression using parent module parameter
a.g++ <--> <> like IMyChannel <--> b.g++;
                                  // type must be specified elsewhere
a.g++ <--> <default("MyChannel")> like IMyChannel <--> b.g++;
                                  // type may be specified elsewhere;
                                  // if not, the default is "MyChannel"
a.g++ <--> <default("Ch_"+suffix)> like IMyChannel <--> b.g++;
                                  // type may be specified elsewhere;
                                  // if not, the default is an expression

See the NED Grammar (Appendix Appendix: NED Language Grammar) for the formal syntax, and section Resolution of Parametric Types for the type resolution rules.

Channel Parameters and Properties

A channel definition may or may not have a body (a curly brace delimited block). An empty channel body ({ }) is equivalent to a missing one.

A channel body may contain parameters (Parameters).

A channel body cannot define new parameters. It is only allowed to assign existing parameters.

It is also allowed to add or modify properties and parameter properties.

The @reconnect Property

The @reconnect property is recognized for connections. Normally, it is an error for a NED connection to refer to a gate that is already connected. When @reconnect is present on a connection, the network builder first disconnects any existing connections on the involved gates before creating the new connection.

a.out --> {@reconnect;} --> b.in;

The primary use of @reconnect is in combination with inheritance, where it allows a derived compound module to modify the connections established by the base type, e.g., to insert a new submodule in the path between two already connected submodules.

See also Reconnecting Gates.

Conditional and Loop Connections, Connection Groups

The connections section may contain any number of connections and connection groups. A connection group is one or more connections grouped with curly braces.

Both connections and connection groups may be conditional (if keyword) or may be multiple (for keyword).

Any number of for and if clauses may be added to a connection or connection loop; they are interpreted as if they were nested in the given order. Loop variables of a for may be referenced from subsequent conditions and loops as well as in module and gate index expressions in the connections.

See the NED Grammar (Appendix: NED Language Grammar) for the exact syntax.

Example connections:

a.out --> b.in;
c.out --> d.in if p>0;
e.out[i] --> f[i].in for i=0..sizeof(f)-1, if i%2==0;

Example connection groups:

if p>0 {
    a.out --> b.in;
    a.in <-- b.out;
}
for i=0..sizeof(c)-1, if i%2==0 {
    c[i].out --> out[i];
    c[i].in <-- in[i];
}
for i=0..sizeof(d)-1, for j=0..sizeof(d)-1, if i!=j {
    d[i].out[j] --> d[j].in[i];
}
for i=0..sizeof(e)-1, for j=0..sizeof(e)-1 {
    e[i].out[j] --> e[j].in[i] if i!=j;
}

Inner Types

Inner types can be defined in the types section of compound modules, with the same syntax as toplevel (i.e. non-inner) types.

Inner types may not contain further inner types, that is, type nesting is limited to two levels.

Inner types are only visible inside the enclosing component type and its subclasses.

Name Uniqueness

Identifier names within a component must be unique. That is, the following items in a component are considered to be in the same name space and must not have colliding names:

  • parameters

  • gates

  • submodules

  • inner types

  • the above items of super type(s)

For example, a gate and a submodule cannot have the same name.

Parameter Assignment Order

A module or channel parameter may be assigned in parameters blocks (see Parameters) at various places in NED: in the module or channel type that defines it; in the type’s subclasses; in the submodule or connection that instantiates the type. The parameter may also be assigned using pattern assignments (see Pattern Assignments) in any compound module that uses the given module or channel type directly or indirectly.

Patterns are matched against the relative path of the parameter, which is the relative path of its submodule or connection, with a dot and the parameter name appended. The relative path is composed of a list of submodule names (name plus index) separated by dots; a connection is identified by the full name of its source gate plus the name of the channel object (which is currently always channel) separated by a dot.

Note

As bidirectional connections are a shorthand for two unidirectional connections, the source gate name is qualified with $i or $o in the relative path.

Note that the parameters keyword itself is optional, and is usually not written out in submodules and connections.

This section describes the module and channel parameter assignments procedure.

The general rules are the following:

  1. A (non-default) parameter assignment may not be overridden later; that is, if there are assignments in multiple places, the assignment “closest” to the parameter declaration will be effective; others will be flagged as errors.

  2. A default value is only used if a non-default value is not present for the given parameter. A non-default value may also come from a source external to NED, namely the simulation configuration (omnetpp.ini).

  3. Unlike non-default values, a default value may be overridden; that is, if there are default value assignments in multiple places, the assignment “farthest” from the parameter declaration will win.

  4. Among pattern assignments within the same parameters block, the first match will win. Pattern assignments with default and non-default values are considered to be two disjoint sets, only one of which are searched at a time.

This yields the following conceptual search order for non-default parameter assignments:

  1. First, the NED type that contains the parameter declaration is checked;

  2. Then its subclasses are checked;

  3. Then the submodule or connection that instantiates the type is checked;

  4. Then the compound module that contains the submodule or connection is checked for matching pattern assignments;

  5. Then, assuming the compound module is part of a network, the search for matching pattern assignments continues up on the module tree until the root (the module that represents the network). At each level (compound module), first the specific submodule definition is checked, then the (parent) compound module. If a compound module is subclassed before instantiated, the base type is checked first.

When no (non-default) assignment is found, the same places are searched in the reverse order for default value assignments. If no default value is found, an error may be raised or the user may be interactively prompted.

To illustrate the above rules, consider the following example where we want to assign parameter p:

simple A { double p; }
simple A2 extends A {...}
module B { submodules: a2: A2 {...} }
module B2 extends B {...}
network C { submodules: b2: B2 {...} }

Here, the search order is: A, A2, a2, B, B2, b2, C. NED conceptually searches the parameters blocks in that order for a (non-default) value, and then in reverse order for a default value.

The full search order and the form of assignment expected on each level:

  1. A { p = ...; }

  2. A2 { p = ...; }

  3. a2 { p = ...; }

  4. B { a2.p = ...; }

  5. B2 { a2.p = ...; }

  6. b2 { a2.p = ...; }

  7. C { b2.a2.p = ...; }

  8. C { b2.a2.p = default(...); }

  9. b2 { a2.p = default(...); }

  10. B2 { a2.p = default(...); }

  11. B { a2.p = default(...); }

  12. a2 { p = default(...); }

  13. A2 { p = default(...); }

  14. A { p = default(...); }

If only a default value is found or not even that, external configuration has a say. The configuration may contain an assignment for C.b2.a2.p; it may apply the default if there is one; it may ask the user interactively to enter a value; or if there is no default, it may raise an error “no value for parameter”.

Type Name Resolution

Names from other NED files can be referred to either by fully qualified name (“inet.network­layer.ip.RoutingTable”), or by short name (“RoutingTable”) if the name is visible.

Visible names are:

  • inner types of the same type or its super types;

  • anything from the same package;

  • imported names.

Imports

Imports have a similar syntax to Java, but they are more flexible with wildcards. All of the following are legal:

import inet.networklayer.ipv4.RoutingTable;
import inet.networklayer.ipv4.*;
import inet.networklayer.ipv4.Ro*Ta*;
import inet.*.ipv4.*;
import inet.**.RoutingTable;

One asterisk stands for any character sequence not containing dots; and a double asterisk stands for any character sequence (which may contain dots). No other wildcards are recognized.

An import not containing a wildcard must match an existing NED type. However, it is legal for an import that does contain wildcards not to match any NED type (although that might generate a warning.)

Inner types may not be referenced outside their enclosing types and their subclasses.

Base Types and Submodules

Fully qualified names and simple names are accepted. Simple names are looked up among the inner types of the enclosing type (compound module), then using imports, then in the same package.

Network Name in the Ini File

The network name in the ini file may be given as a fully qualified name or as a simple (unqualified) name.

Simple (unqualified) names are tried with the same package as the ini file is in (provided it is in a NED directory).

Resolution of Parametric Types

This section describes the type resolution for submodules and connections that are defined using the like keyword.

Type resolution is done in two steps. In the first step, the type name string expression is found and evaluated. Then in the second step, the resulting type name string is resolved to an actual NED type.

Step 1. The lookup of the type name string expression is similar to that of a parameter value lookup (Parameter Assignment Order).

The expression may be specified locally (between the angle brackets), or using typename pattern assignments in any compound module that contains the submodule or connection directly or indirectly. A typename pattern is a pattern that ends in .typename.

Patterns are matched against the relative path of the submodule or connection, with .typename appended. The relative path is composed of a list of submodule names (name plus index) separated by dots; a connection is identified by the full name of its source gate plus the name of the channel object (which is currently always channel) separated by a dot.

Note

As bidirectional connections are a shorthand for two unidirectional connections, the source gate name is qualified with $i or $o in the relative path.

An example that uses typename pattern assignment:

module Host {
    submodules:
        tcp: <> like ITCP;;
        ...
    connections:
        tcp.ipOut --> <> like IMyChannel --> ip.tcpIn;
}

network Network {
    parameters:
        host[*].tcp.typename = "TCP_lwIP";
        host[*].tcp.ipOut.channel.typename = "DebugChannel";
    submodules:
        host[10] : Host;
        ...
}

The general rules are the following:

  1. A (non-default) parameter assignment may not be overridden later; that is, if there are assignments in multiple places, the assignment “closest” to the submodule or connection definition will be effective; others will be flagged as errors.

  2. A default value is only used if a non-default value is not present. A non-default value may also come from a source external to NED, namely the simulation configuration (omnetpp.ini).

  3. Unlike non-default values, a default value may be overridden; that is, if there are default value assignments in multiple places, the assignment “farthest” from the submodule or connection definition will win.

  4. Among pattern assignments within the same parameters block, the first match will win. Patterns assignments with default and non-default values are considered to be two disjoint sets, only one of which are searched at a time.

This yields the following conceptual search order for typename assignments:

  1. First, the submodule or connection definition is checked (angle brackets);

  2. Then the compound module that contains the submodule or connection is checked for matching pattern assignments;

  3. Then, assuming the compound module is part of a network, the search for matching pattern assignments continues up on the module tree until the root (the module that represents the network). At each level (compound module), first the specific submodule definition is checked, then the (parent) compound module. If a compound module is subclassed before instantiated, the base type is checked first.

When no (non-default) assignment is found, the same places are searched in the reverse order for default value assignments. If no default value is found, an error may be raised or the user may be interactively prompted.

To illustrate the above rules, consider the following example:

module A { submodules: h: <> like IFoo; }
module A2 extends A {...}
module B { submodules: a2: A2 {...} }
module B2 extends B {...}
network C { submodules: b2: B2 {...} }

Here, the search order is: h, A, A2, a2, B, B2, b2, C. NED conceptually searches the parameters blocks in that order for a (non-default) value, and then in reverse order for a default value.

The full search order and the form of assignment expected on each level:

  1. h: <...> like IFoo;

  2. A { h.typename = ...; }

  3. A2 { h.typename = ...; }

  4. a2 { h.typename = ...; }

  5. B { a2.h.typename = ...; }

  6. B2 { a2.h.typename = ...; }

  7. b2 { a2.h.typename = ...; }

  8. C { b2.a2.h.typename = ...; }

  9. C { b2.a2.h.typename = default(...); }

  10. b2 { a2.h.typename = default(...); }

  11. B2 { a2.h.typename = default(...); }

  12. B { a2.h.typename = default(...); }

  13. a2 { h.typename = default(...); }

  14. A2 { h.typename = default(...); }

  15. A { h.typename = default(...); }

  16. h: <default(...)> like IFoo;

If only a default value is found or not even that, external configuration has a say. The configuration may contain an assignment for C.b2.a2.h.typename; it may apply the default value if there is one; it may ask the user interactively to enter a value; or if there is no default value, it may raise an error “cannot determine submodule type”.

Step 2. The type name string is expected to hold the simple name or fully qualified name of the desired NED type. Resolving the type name string to an actual NED type differs from normal type name lookups in that it ignores the imports in the file altogether. Instead, a list of NED types that have the given simple name or fully qualified name and implement the given interface is collected. The result must be exactly one module or channel type.

Implementing an Interface

A module type may implement one or more module interfaces, and a channel type may implement one or more channel interfaces, using the like keyword.

The module or channel type is required to have at least those parameters and gates that the interface has.

Regarding component properties, parameter properties and gate properties defined in the interface: the module or channel type is required to have at least the properties of the interface, with at least the same values. The component may have additional properties, and properties may add more keys and values.

Note

Implementing an interface does not cause the properties, parameters and gates to be interited by the module or channel type; they have to be added explicitly.

Note

A module or channel type may have extra properties, parameters and gates in addition to those in the interface.

Inheritance

Component inheritance is governed by the following rules:

  • A simple module may only extend a simple module.

  • A compound module may only extend a compound module or a simple module.

  • A channel may only extend a channel.

  • A module interface may only extend a module interface (or several module interfaces).

  • A channel interface may only extend a channel interface (or several channel interfaces).

A network is a shorthand for a compound module with the @isNetwork property set, so the same rules apply to it as to compound modules.

Inheritance may:

  • add new properties, parameters, gates, inner types, submodules, connections, as long as names do not conflict with inherited names

  • modify inherited properties, and properties of inherited parameters and gates

  • it may not modify inherited submodules, connections and inner types

Other inheritance rules:

  • for inner types: new inner types can be added, but inherited ones cannot be changed

  • for properties: contents will be merged (rules like for display strings: values on same key and same position will overwrite old ones)

  • for parameters: type cannot be redefined; value may be redefined in subclasses or at place of usage

  • for gates: type cannot be redefined; vector size may be specified in subclasses or at place of usage if it was unspecified

  • for gate/parameter properties: extra properties can be added; existing properties can be overridden/extended as for standalone properties

  • for submodules: new submodules may be added, but inherited ones cannot be modified

  • for connections: new connections may be added, but inherited ones cannot be modified

The following sections will elaborate on the above rules.

Property Inheritance

Generally, properties may be modified via inheritance. Inheritance may:

  • add new keys

  • add/overwrite values for existing keys

  • remove a value from an existing key by using hyphen as a special value

Parameter Inheritance

Default values for parameters may be overridden in subclasses.

Gate Inheritance

Gate vector size may not be overridden in subclasses.

Network Build Order

When a network is instantiated for simulation, the module tree is built in a top-down preorder fashion. This means that starting from an empty system module, all submodules are created, their parameters and vector sizes are assigned, and they get fully connected before proceeding to go into the submodules to build their internals.

This implies that inside a compound module definition (including in submodules and connections), one can refer to the compound module’s parameters and gate sizes, because they are already built at the time of usage.

The same rules apply to compound or simple modules created dynamically during runtime.

Expressions

NED language expressions have a C-like syntax, with some variations on operator names (see ^, #, ##). Expressions may refer to module parameters, loop variables (inside connection for loops), gate vector and module vector sizes, and other attributes of the model. Expressions can also use built-in and user-defined functions. There is a JSON-like notation for defining arrays and objects (dictionary-like).

Note

New NED functions can be defined in C++; refer to section Defining New NED Functions.

Constants

Refer to section Literals.

Array and Object Values

A bracketed list of zero or more comma-separated expressions denotes an array value. For example: [9.81, false, "Hello"].

A list of zero or more comma-separated key-value pairs enclosed in a pair of curly braces denotes an object value. A key and a value are separated by a colon. A key may be a name or a string literal. A value may be an arbitrary expression, including a list or an object. The open brace may be preceded by an (optionally namespace-qualified) class name. Example 1: {name:"John", age: 31}. Example 2 (includes class name): Filter {dest:"10.0.0.1", port:1200}.

Array and object values may be assigned to parameters of type object. Note that null / nullptr are also of type object.

Array values are represented with the C++ class cValueArray, and by default, object values with the C++ class cValueMap. If the object notation includes a class name, then the named C++ class will be used instead of cValueMap, and filled in using the key-value list with the help of the class descriptor (cClassDescriptor) of the class, interpreting keys as field names.

Operators

The following operators are supported (in order of decreasing precedence):

Operator

Meaning

-, !, ~

unary minus, negation, bitwise complement

^

power-of

*, /, %

multiply, divide, integer modulo

+, -

add, subtract, string concatenation

<<, >>

bitwise shift

&

bitwise and

#

bitwise xor

|

bitwise or

=~

string match

<=>

three-way comparison, a.k.a. “spaceship operator”

>, >=

greater than, greater than or equal to

<, <=

less than, less than or equal to

==

equal

!=

not equal

&&

logical operator and

##

logical operator xor

||

logical operator or

?:

the C/C++ “inline if”

The spaceship operator is defined as follows. The result of a <=> b is negative if a<b, zero if a==b, and positive if a>b. If either a or b is nan (not-a-number), the result is nan as well.

The string match operator works as follows. x =~pattern returns true if the string x matches the string pattern, and false otherwise. The operator performs case-sensitive full-string match. The pattern has the following syntax:

  • Asterisk * matches zero or more of any character except dot

  • Double asterisk ** matches zero or more characters (including dot)

  • Curly braces containing a numeric range match an embedded whole number in that range

  • Square brackets containing a numeric range match a number in that range enclosed in square brackets

  • A numeric range has the syntax of <start>..<end>, where both <start> and <end> are integers (optional)

The interpretation of other operators is similar to that in C/C++.

Conversions

Values may have the same types as NED parameters: boolean, integer, double, string, XML element, and object. An integer or double value may have an associated measurement unit (e.g., s, mW).

Double-to-integer conversions require explicit casting using the int() function. There is no implicit conversion.

Integer-to-double conversion is implicit. However, a runtime error will be raised if there is precision loss during the conversion, i.e., the integer is too large to be precisely represented in a double. To suppress this error, an explicit cast (double()) can be used.

There is no implicit conversion between boolean and numeric types. Thus, 0 is not a synonym for false, and nonzero numbers are not a synonym for true.

There is also no conversion between string and numeric types. For example, "foo"+5 is illegal. However, there are functions for converting a number to a string and vice versa.

Bitwise operators expect integer arguments.

Note

Integers are represented with 64-bit signed integers (int64_t in C++).

Unit Handling

Operations involving numbers with units work as follows:

Addition, subtraction, and numeric comparisons require their arguments to have the same unit or compatible units. If the units are compatible, a unit conversion is performed before the operation. Incompatible units cause an error.

Modulo, power-of, and the bitwise operations require their arguments to be dimensionless. Otherwise, the result would depend on the choice of the unit.

Note

If a floating-point modulo operator that handles units is needed, the fmod() function can be used.

Multiplying two numbers with units is not supported.

For division, dividing two numbers with units is only supported if the two units are convertible (i.e., the result will be dimensionless). Dividing a dimensionless number with a number with a unit is not supported.

Operations involving quantities with logarithmic units (e.g., dB, dBW) are not supported, except for comparisons. The reason is that such operations would be easy to misinterpret. For example, it is not obvious whether 10dB+10dB (3.16+3.16) should evaluate to 20dB (=10.0) or to 16.02dB (=2*3.16=6.32), considering that such quantities would often be hidden behind parameter names where the unit is not obvious.

Referencing Parameters, Gates and Loop Variables

Expressions may refer to parameters, gates, and other submodules using the this or the parent qualifier, or without a qualifier. Unqualified identifiers refer to the parameters, gates or submodules of the (nearest) block in which they are defined: the submodule or the module/channel. In connection for loops, if an identifier matches a previously defined loop variable, it refers to that loop variable. Namely: [1]

Outside submodule and connection blocks:

Unqualified identifiers refer to parameters, gates, and submodules of the compound module being defined.

Inside submodule and connection blocks:

Unqualified identifiers refer to items of (or within) the local submodule or channel object, not to items of the enclosing compound module. To refer to the compound module’s items from within a submodule or connection block, use the parent qualifier. To make references to the local submodule or channel explicit, use the this qualifier.

Example demonstrating the semantics:

network Network {
  parameters:
      int foo;
  submodules:
    node1: { ... }
    node2: Node {
      foo = foo; // ERROR: self-reference! Change to 'foo = parent.foo'.
      bar = this.foo;  // OK: refers to node2.foo
      baz = node1.foo;  // ERROR: refers to yet-uncreated submodule this.node1!
      bax = parent.node1.foo;  // OK: refers to Network.node1.foo
    }
}

Expressions may also refer to parameters of submodules defined earlier in the NED file using the parent.submoduleName.paramName or parent.submoduleName[index].paramName syntax from within a submodule block.

Note

Referencing a submodule’s submodule from NED (i.e., the a.b or this.a.b syntax within a submodule block) is generally wrong, because the network is built top-down and submodules are only created after parameters have already been set up. An exception is using such references in the values of volatile parameters, because they are evaluated later, at access time.

The typename Operator

The typename operator returns the NED type name as a string. If it occurs inside a component definition but outside a submodule or channel block, it returns the type name of the component being defined. If it occurs inside a submodule or channel block, it returns the type name of that submodule or channel.

The typename operator can also occur in the if condition of a scalar submodule or connection. In such cases, it evaluates to the would-be type name of the submodule or condition. This allows for conditional instantiation of parametric-type submodules, controlled from a typename assignment. (For example, by using the condition, one allows the submodule to be omitted by configuring typename="" for it.)

The typename operator is not allowed in a submodule vector’s if condition. The reason is that the condition applies to the vector as a whole while the type is per-element.

The index Operator

The index operator is only allowed in a vector submodule’s body and yields the index of the submodule instance.

The exists() Operator

The exists() operator is only accepted in compound module definitions. It returns true if the specified item exists, and false otherwise.

The operator accepts various forms of arguments:

  • exists(submoduleName) – checks if a (typically conditional) submodule exists

  • exists(submoduleName[index]) – checks if an element in a submodule vector exists (useful with submodule vectors that may contain holes due to @omittedTypename)

  • exists(parent.submoduleName) – explicitly refers to the parent module’s submodule

  • exists(this.submoduleName) – checks for a submodule within the current submodule (generally only useful in volatile parameter expressions)

The sizeof() Operator

The sizeof() operator expects one argument and is only accepted in compound module definitions. It returns the size of a submodule vector or gate vector. The usual scoping rules apply to the argument (see Referencing Parameters, Gates and Loop Variables): use the this and parent qualifiers to disambiguate.

In particular, to refer to the size of a sibling submodule’s gate vector, use the sizeof(parent.submoduleName.gateVectorName) or sizeof(parent.submoduleName[index].gateVectorName) syntax from within a submodule block.

The expr() Operator

The expr() operator allows a mathematical formula or other expression to be passed to a component as an object. expr() expects an expression as an argument and returns an object that encapsulates the expression in a parsed form. In the intended use case, the returned expression object is assigned to a module parameter and is later utilized by user code (a component implementation) by binding its free variables and evaluating it. Identifiers in the expression are not interpreted as parameter references as in NED but as free variables.

Functions

The functions available in NED are listed in Appendix Appendix: NED Functions.

Selected functions are documented below.

The xmldoc() Function

The xmldoc() NED function can be used to assign xml parameters, that is, point them to XML files or to specific elements inside XML files.

xmldoc() accepts a file name as well as an optional second string argument that contains an XPath-like expression.

The XPath expression is used to select an element within the document. If the expression matches several elements, the first element (in preorder depth-first traversal) will be selected (unlike XPath, which selects all matching nodes).

The expression syntax is as follows:

  • An expression consists of path components (or “steps”) separated by “/” or “//”.

  • A path component can be an element tag name, “*”, “.”, or “..”.

  • “/” means child element (just like in /usr/bin/gcc), while “//” means an element at any level under the current element.

  • “.”, “..”, and “*” mean the current element, the parent element, and an element with any tag name, respectively.

  • Element tag names and “*” can have an optional predicate in the form “[position]” or “[@attribute=’value’]”. Positions start from zero.

  • Predicates of the form “[@attribute=``$param``]” are also accepted, where ``$param`` can be one of the following items: $MODULE_­FULLPATH, $MODULE_­FULLNAME, $MODULE_­NAME, $MODULE_­INDEX, $MODULE_­ID, $PARENT­MODULE_­FULLPATH, $PARENT­MODULE_­FULLNAME, $PARENT­MODULE_­NAME, $PARENT­MODULE_­INDEX, $PARENT­MODULE_­ID, $GRAND­PARENT­MODULE_­FULLPATH, $GRAND­PARENT­MODULE_­FULLNAME, $GRAND­PARENT­MODULE_­NAME, $GRAND­PARENT­MODULE_­INDEX, $GRAND­PARENT­MODULE_­ID.

The xml() Function

The xml() NED function can be used to parse a string as an XML document and assign the result to an xml parameter.

xml() accepts the string to be parsed as well as an optional second string argument that contains an XPath-like expression.

The XPath expression is used in the same manner as with the xmldoc() function.

Units of Measurement

The following measurement units are recognized in constants. Other units can be used as well, but there are no conversions available for them (i.e., parsec and kiloparsec will be treated as two completely unrelated units).

Unit

Name

Value

d

day

86400s

h

hour

3600s

min

minute

60s

s

second

ms

millisecond

0.001s

us

microsecond

1e-6s

ns

nanosecond

1e-9s

ps

picosecond

1e-12s

fs

femtosecond

1e-15s

as

attosecond

1e-18s

bps

bit/sec

kbps

kilobit/sec

1000bps

Mbps

megabit/sec

1e6bps

Gbps

gigabit/sec

1e9bps

Tbps

terabit/sec

1e12bps

B

byte

8b

KiB

kibibyte

8192b

MiB

mebibyte

8.38861e6b

GiB

gibibyte

8.58993e9b

TiB

tebibyte

8.79609e12b

kB

kilobyte

8000b

MB

megabyte

8e6b

GB

gigabyte

8e9b

TB

terabyte

8e12b

b

bit

Kib

kibibit

1024b

Mib

mebibit

1.04858e6b

Gib

gibibit

1.07374e9b

Tib

tebibit

1.09951e12b

kb

kilobit

1000b

Mb

megabit

1e6b

Gb

gigabit

1e9b

Tb

terabit

1e12b

rad

radian

deg

degree

0.0174533rad

m

meter

dm

decimeter

0.1m

cm

centimeter

0.01m

mm

millimeter

0.001m

um

micrometer

1e-6m

nm

nanometer

1e-9m

km

kilometer

1000m

W

watt

mW

milliwatt

0.001W

uW

microwatt

1e-6W

nW

nanowatt

1e-9W

pW

picowatt

1e-12W

fW

femtowatt

1e-15W

kW

kilowatt

1000W

MW

megawatt

1e6W

GW

gigawatt

1e9W

Hz

hertz

kHz

kilohertz

1000Hz

MHz

megahertz

1e6Hz

GHz

gigahertz

1e9Hz

THz

terahertz

1e12Hz

kg

kilogram

g

gram

0.001kg

t

tonne

1000kg

K

kelvin

J

joule

kJ

kilojoule

1000J

MJ

megajoule

1e6J

Ws

watt-second

1J

Wh

watt-hour

3600J

kWh

kilowatt-hour

3.6e6J

MWh

megawatt-hour

3.6e9J

V

volt

kV

kilovolt

1000V

mV

millivolt

0.001V

A

ampere

mA

milliampere

0.001A

uA

microampere

1e-6A

Ohm

ohm

mOhm

milliohm

0.001Ohm

kOhm

kiloohm

1000Ohm

MOhm

megaohm

1e6Ohm

mps

meter/sec

kmps

kilometer/sec

1000mps

kmph

kilometer/hour

(1/3.6)mps

C

coulomb

1As

As

ampere-second

mAs

milliampere-second

0.001As

Ah

ampere-hour

3600As

mAh

milliampere-hour

3.6As

x

times

dBW

decibel-watt

10*log10(W)

dBm

decibel-milliwatt

10*log10(mW)

dBmW

decibel-milliwatt

10*log10(mW)

dBV

decibel-volt

20*log10(V)

dBmV

decibel-millivolt

20*log10(mV)

dBA

decibel-ampere

20*log10(A)

dBmA

decibel-milliampere

20*log10(mA)

dB

decibel