NED files have the .ned file name suffix. This is mandatory, and cannot be overridden.
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.
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.
NED file authors have to take care that no reserved words are used as identifiers. The reserved words of the NED language are:
allowunconnected bool channel channelinterface connections const default double extends false for gates if import index inf inout input int like module moduleinterface nan network output package parameters property simple sizeof string submodules this true typename types volatile xml xmldoc
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).
Keywords and identifiers in the NED language are case sensitive. For example, TCP and Tcp are two different names.
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 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.
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 [19.5.9] 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.
Comments can be placed at the end of lines. Comments begin with a double slash //, and continue until the end of the line.
The grammar of the NED language can be found in Appendix [20].
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.
package ned; @namespace(""); channel IdealChannel { @class(cIdealChannel); } channel DelayChannel { @class(cDelayChannel); @signal[messageSent](type=cMessage); @signal[messageDiscarded](type=cMessage); @statistic[messages](...); @statistic[messagesDiscarded](...); bool disabled = default(false); double delay = default(0s) @unit(s); // propagation delay } channel DatarateChannel { @class(cDatarateChannel); @signal[channelBusy](type=long); @signal[messageSent](type=cMessage); @signal[messageDiscarded](type=cMessage); @statistic[busy](...); @statistic[utilization](...); @statistic[packets](...); @statistic[packetBytes](...); @statistic[packetsDiscarded](...); @statistic[throughput](...); bool disabled = default(false); double delay = default(0s) @unit(s); // propagation delay double datarate = default(0bps) @unit(bps); // bits per second; 0=infinite double ber = default(0); // bit error rate (BER) double per = default(0); // packet error rate (PER) } moduleinterface IBidirectionalChannel { gates: inout a; inout b; } moduleinterface IUnidirectionalChannel { gates: input i; output o; }
NED supports hierarchical namespaces called packages. The model is similar to Java packages, with minor changes.
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.
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.
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.
Simple modules, compound modules, networks, channels, module interfaces and channel interfaces are called components.
Simple module types are declared with the simple keyword; see the NED Grammar (Appendix [20]) for the syntax.
Simple modules may have properties ([19.4.8]), parameters ([19.4.9]) and gates ([19.4.11]).
A simple module type may not have inner types ([19.4.15]).
A simple module type may extend another simple module type, and may implement one or more module interfaces ([19.4.5]). Inheritance rules are described in section [19.4.21], and interface implementation rules in section [19.4.20].
Every simple module type has an associated C++ class, which must be subclassed from cSimpleModule. The way of associating the NED type with the C++ class is described in section [19.4.7].
Compound module types are declared with the module keyword; see the NED Grammar (Appendix [20]) for the syntax.
A compound module may have properties ([19.4.8]), parameters ([19.4.9]), and gates ([19.4.11]); its internal structure is defined by its submodules ([19.4.12]) and connections ([19.4.13]); and it may also have inner types ([19.4.15]) 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 ([19.4.5]). Inheritance rules are described in section [19.4.21], and interface implementation rules in section [19.4.20].
A network declared with the network keyword is equivalent to a compound module (module keyword) with the @isNetwork(true) 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.
Channel types are declared with the channel keyword; see the NED Grammar (Appendix [20]) for the syntax.
Channel types may have properties ([19.4.8]) and parameters ([19.4.9]).
A channel type may not have inner types ([19.4.15]).
A channel type may extend another channel type, and may implement one or more channel interfaces ([19.4.6]). Inheritance rules are described in section [19.4.21], and interface implementation rules in section [19.4.20].
Every channel type has an associated C++ class, which must be subclassed from cChannel. The way of associating the NED type with the C++ class is described in section [19.4.7].
The @defaultname property of a channel type determines the default name of the channel object when used in a connection.
Module interface types are declared with the moduleinterface keyword; see the NED Grammar (Appendix [20]) for the syntax.
Module interfaces may have properties ([19.4.8]), parameters ([19.4.9]), and gates ([19.4.11]). However, parameters are not allowed to have a value assigned, not even a default value.
A module interface type may not have inner types ([19.4.15]).
A module interface type may extend one or more other module interface types. Inheritance rules are described in section [19.4.21].
Channel interface types are declared with the channelinterface keyword; see the NED Grammar (Appendix [20]) for the syntax.
Channel interfaces may have properties ([19.4.8]) and parameters ([19.4.9]). However, parameters are not allowed to have a value assigned, not even a default value.
A channel interface type may not have inner types ([19.4.15]).
A channel interface type may extend one or more other channel interface types. Inheritance rules are described in section [19.4.21].
The procedure for determining the C++ implementation class for simple modules and for channels are identical. It goes as follows (we are going to say component instead of “simple module or channel”):
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.
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.
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.
The current namespace is the value of the first @namespace property found while searching the following order:
The @namespace property should contain a single value.
Properties are a means of adding metadata annotations to NED files, component types, parameters, gates, submodules, and connections.
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 index, one with the index index1, and a third with the index index2.
@prop1(); @prop2[index1](); @prop3[index2]();
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 of the properties use the default key with one value. Examples:
@namespace(inet); @class(Foo); @unit(s);
Property values have a liberal syntax (see Appendix [20]). 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 [19.1.6]).
Example:
@prop(marks=the ! mark, "the , mark", "the ; mark", other marks); // 4 items
Properties may be added to NED files, component types, parameters, gates, submodules and connections. For the exact syntax, see Appendix [20].
When a component type extends another component type(s), properties are merged. This is described in section [19.4.21].
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 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 change in the meaning.
The parameters section may also hold pattern assignments ([19.4.10]) and properties ([19.4.8]).
A parameter is identified by a name, and has a data type. A parameter may have value or default value, and may also have properties (see [19.4.8]).
Accepted parameter data types are double, int, string, bool, and xml. 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 [19.5].
For volatile parameters, the value expression is evaluated every time the parameter value is accessed. Non-volatile parameters are evaluated only once.
The following properties are recognized for parameters: @unit, @prompt.
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.
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 }
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 accomodate 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:
See the NED language grammar (Appendix [20]) 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 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 [19.4.8]).
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 [19.5].
See the Connections section ([19.4.13]) for more information on gates.
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 [19.4.13]).
@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.
Example:
gates: input radioIn @directIn;
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
The simple or compound module type ([19.4.1], [19.4.2]) that will be instantiated as the submodule may be specified either statically (with a concrete module type name) or parametrically.
Submodules with a statically defined type are those that contain a concrete NED module type name. Example:
tcp : TCP;
See section [19.4.18] for the type resolution rules.
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 [19.4.5] 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 [20]) for the formal syntax, and section [19.4.19] for the type resolution rules.
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 { ... }
A submodule body may contain parameters ([19.4.9]) and gates ([19.4.5]).
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 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.
Connections may be conditional, and may be created using loops (see [19.4.14]).
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
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 [19.4.4]) 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.
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.go --> b.gi; a.gi <-- b.go;
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.
A channel specification associates a channel object with the connection. A channel object is an instance of a channel type (see [19.4.4]).
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.
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:
Connections with implicit channel types may not use any other parameter.
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 [19.4.18] for the type resolution rules.
Parametric channel types are similar to parametric submodule types, described in section [19.4.12].
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 [19.4.6] 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 [20]) for the formal syntax, and section [19.4.19] for the type resolution rules.
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 ([19.4.9]).
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 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 ([20]) 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 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.
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:
For example, a gate and a submodule cannot have the same name.
A module or channel parameter may be assigned in parameters blocks (see [19.4.9]) 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 [19.4.10]) 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 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:
This yields the following conceptual search order for non-default parameter assignments:
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:
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”.
Names from other NED files can be referred to either by fully qualified name (“inet.networklayer.ip.RoutingTable”), or by short name (“RoutingTable”) if the name is visible.
Visible names are:
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.
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.
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).
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 ([19.4.17]).
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.
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:
This yields the following conceptual search order for typename assignments:
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:
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.
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.
Component inheritance is governed by the following rules:
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:
Other inheritance rules:
The following sections will elaborate on the above rules.
Generally, properties may be modified via inheritance. Inheritance may:
Default values for parameters may be overridden in subclasses.
Gate vector size may not be overridden in subclasses.
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.
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 use built-in and user-defined functions as well.
See section [19.1.6].
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, or, xor |
== | equal |
!= | not equal |
>, >= | greater than, greater than or equal to |
<, <= | less than, less than or equal to |
&&, ||, ## | logical operators and, or, xor |
?: | the C/C++ “inline if” |
Values may have the same types as NED parameters: boolean, integer, double, string, or XML element. An integer or double value may have an associated measurement unit (s, mW, etc.)
Double-to-integer conversions require explicit cast using the int() function, there is no implicit conversion.
Integer-to-double converson is implicit. However, a runtime error will be raised if there is precision loss during the conversion, i.e. the integer is so large that it cannot be precisely represented in a double. That error can be suppressed by using an explicit cast (double().
There is no implicit conversion between boolean and numeric types, so 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, so e.g. "foo"+5 is illegal. There are functions for converting a number to string and vice versa.
Bitwise operators expect integer arguments.
Operations involving numbers with units work in the following way:
Addition, subtraction, and numeric comparisons require their arguments to have the same unit or compatible units; in the latter case 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.
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 unit is not supported.
Operations involving quantities with logarithmic units (dB, dBW, etc.) 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.)
Identifiers in expressions occurring anywhere in component definitions are interpreted as referring to parameters of the given component. For example, identifiers inside submodule bodies refer to the parameters of the compound module.
Expressions may also refer to parameters of submodules defined earlier in the NED file, using the submoduleName.paramName or the submoduleName[index].paramName syntax. To refer to parameters of the local submodule inside a submodule body, use the this qualifier: this.destAddress.
Exception: if an identifier occurs in a connection for loop and names a previously defined loop variable, then it is understood as referring to the loop variable.
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 may 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 if typename!="" condition, one allows the submodule to be omitted by configuring typename="" for it.
typename is not allowed in a submodule vector's if condition. The reason is that the condition applies to the vector as a whole, while type is per-element.
The index operator is only allowed in a vector submodule's body, and yields the index of the submodule instance.
The exists() operator takes one identifier as argument, and it is only accepted in compound module definitions. The identifier must name a previously defined submodule, which will typically be a conditional submodule. The operator returns true if given submodule exists (has been created), and false otherwise.
The sizeof() operator expects one argument, and it is only accepted in compound module definitions.
The sizeof(identifier) syntax occurring anywhere in a compound module yields the size of the named submodule or gate vector of the compound module.
Inside submodule bodies, the size of a gate vector of the same submodule can be referred to with the this qualifier: sizeof(this.out).
To refer to the size of a submodule's gate vector defined earlier in the NED file, use the sizeof(submoduleName.gateVectorName) or sizeof(submoduleName[index].gateVectorName) syntax.
The functions available in NED are listed in Appendix [22].
Selected functions are documented below.
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. (This is unlike XPath, which selects all matching nodes.)
The expression syntax is the following:
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.
The following measurements 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 |
s | second | |
d | day | 86400s |
h | hour | 3600s |
min | minute | 60s |
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 | 1024B |
MiB | mebibyte | 1.04858e6B |
GiB | gibibyte | 1.07374e9B |
TiB | tebibyte | 1.09951e12B |
kB | kilobyte | 1000B |
MB | megabyte | 1e6B |
GB | gigabyte | 1e9B |
TB | terabyte | 1e12B |
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 | |
mm | millimeter | 0.001m |
cm | centimeter | 0.01m |
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 |
K | kelvin | |
J | joule | |
kJ | kilojoule | 1000J |
MJ | megajoule | 1e6J |
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 | |
As | ampere-second | 1C |
mAs | milliampere-second | 0.001C |
Ah | ampere-hour | 3600C |
mAh | milliampere-hour | 3.6C |
ratio | ratio | |
pct | percent | 0.01ratio |
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 | 20*log10(ratio) |