This document describes in details the syntax for writting Data Flow Network files. Data Flow Network files are simple text files that the FileParser object will parse to create data structures that will be used by the NetworkBuilder to acctually build the Data Flow network. There can exist more than one Data Flow network in a single text file and some of them can be included into other Data Flow network as what we will call 'subnets.'. This 'subnets' feature allows a Data Flow network to be reused.
The Data Flow network text file format is very flexible. By 'flexible'
is meant that space characters, tabs, newlines can be inserted anywhere
in the Data Flow network text file without affecting the final network
defitions. Lets start by the syntax for defining a Data Flow network.
/* This is a sample Data Flow network text file containing an empty
net block. */
Network: Network1
|
Note that a single Data Flow network text file can contain more than one network block, as long as they each have a unique name.
<keyword: rightside>
These strings enclosed between '<' and '>' are called node blocks and will appear only inside network blocks. Node blocks are used to specify all the information about the nodes such as the node's name, type, input variables and so on... The following sections will describe how to write the node blocks for each possible node attribute.
/* Sample Data Flow network text file. */ Network: SAMPLE_NET
<node: NODE2>
<node: NODE3>
} |
In the above example, 3 nodes (NODE1, NODE2, NODE3) where created inside
the Data Flow network named SAMPLE_NET. Note that the identation
in the above example is purely arbitrary. The following Data Flow
text will have the same effect as the above one, although it might be a
bit more difficult to read by a user. Again note that each node within
a Data Flow network block must each have its own unique name.
<type: the_type_of_the_node_goes_here>
In this case the keyword of the node block is type: and the rightside
is the type of the node. Here is an example:
/* Sample Data Flow network text file. */ Network: SAMPLE_NET
<node: NODE2> <type: PROC1>
|
<param: the_param_name,param_type:the_param_value>
In this case the keyword of the node block is param: and the
rightside contains the name of the parameter variable, its type and its
initial value, seperated by a comma and a ":", respectively. Both
the name and its value must appear in each parameter definition node block.
If a node has more than one parameter, then there will be one parameter
node block for each parameter. Make sure that no two parameter names
are identical. Here is an example of a Data Flow network with 2 nodes,
the first one with a single boolean parameter initialized to true
and the second node having two parameters of numeric type.
/* Sample Data Flow Network text file. */ Network: SAMPLE_NET
<node: NODE2> <type: TYPE2>
|
Parameter values are preceded by its type keyword. If there is no type keyword preceding the parameter's value, then for numerical values, int or float will be used, depending if the value contains a decimal point or not, and for non-numerical values, string will be used for anything that is double quoted and char will be used for single quoted characters. Boolean are written as true or false and the case must be respected. Writting down True, TRUE or TrUe will not work.
Here is a table representing the type keywords to use for each parameter
variable type:
Parameter keyword | Meaning |
int: | Int (int) |
short: | Short (short) |
long: | Long (long) |
char: | Char (char) |
u_char: | U_Char (unsigned char) |
u_int: | U_Int (unsigned int) |
u_long | U_Long (unsigned long) |
bool: | Bool (bool) |
float: | Float (float) |
double: | Double (double) |
string: | String (string) |
ext: | external parameter specified by the program to the builder |
subnet_param: | parameter taken from the network parameters |
env: | string from an environment variable |
... | ... |
Here is an example of a node containing an environment variable:
<node: NODE1> <type: A_NODE_TYPE>
<param: PATH_PARAM, env:PATH> |
In the above example, the line <param: PATH_PARAM, env:PATH> will be replaced (at run-time) by: <param: PATH_PARAM, string:"./:/opt/bin/:/home/username/.....">
Another way of using environment variable is to use the $(VAR) syntax. This feature allows the user to include environment variables anywhere into the description file of the network.
Here is an example of a node containing this type of environment variable:
<node: NODE1> <type: A_NODE_TYPE>
<param: PATH_PARAM, "$(MY_ENV_PATH)/script_to_run.csh"> |
Note: Make sure the environment variable exists, if not, it will cause an exception to be thrown.
<param: variable_name, subnet_param: parameterized_variable_name>
To better understand this feature, here is an example of a simple data
flow network that includes a parameterized subnet:
Network: A_DATA_FLOW_NET { ...
<node: FILENAME_NODE>
<type: CONST>
<node: PROCESSING_NODE>
<type: LOADING_NET>
... } /* Parameterized subnet */
<node: PROC1_NODE>
<type: PROC1>
<netInput: LOADER_NODE>
}
|
At run-time, the above subnet example will be translated the following
way:
Network: A_DATA_FLOW_NET
{
...
<node: FILENAME_NODE> <type: CONST>
<node: PROCESSING_NODE> <type: LOADING_NET__1>
... } /* Parameterized subnet */
<node: PROC1_NODE>
<type: PROC1>
<netInput: LOADER_NODE>
}
|
We can see that a "copy" of the original parameterized subnet is made
with the appropriate changes made to the node parameters. A unique
name is given to this copy, which is this case is "LOADING_NET__1.
This "copy creation" process is completely transparent to the user of the
data flow network library and is illustrated here only to give the user
a general idea of how parameterization of subnets is done.
External parameters are node parameters that are set at run-time
to a value and type both defined in the client application. An example
of where this feature can be very useful is for an application that needs
to pass command-line arguments to the node of its data flow network.
To add an external parameter to a node, the following syntax is used:
<param: param_name, ext: external_param_name>
Here is the previous example but now using an external parameter for
the filename:
Network: A_DATA_FLOW_NET { ...
<node: FILENAME_NODE>
<type: CONST>
<node: PROCESSING_NODE>
<type: LOADING_NET>
... } /* Parameterized subnet */
<node: PROC1_NODE>
<type: PROC1>
<netInput: LOADER_NODE>
}
|
In the above example, the VALUE parameter of the FILENAME_NODE node
will be set at runtime. The way external variables are accessed is
throughout a ParameterSet object, constructed in the client application,
that is passed by pointer to the NetworkBuilder object when calling the
'build' method. Here is an example:
int main() { NeworkBuilder nb; ParameterSet ps; ... ps.add("EXTERNAL_FILENAME",ObjectRef(new String("/home/a_user/a_file.dat"))); ... nb.build(net_info, "A_DATA_FLOW_NET", &ps); ... return 0;
|
In the above example, the value of the filename node's parameter will be set to "/home/a_user/a_file.dat" at run-time when the data flow network is built.
Setting the input variables of a Data Flow network node is very
similar to setting the parameters. To set the inputs of a node, a
node block of the following format is used:
<input: input_var_name, source_node, source_node_output_var>
Here the node block key is input: and the right side contains
3 fields, seperated by commas. The first field, input_var_name,
is the name to give to the input variable. The second field, source_node,
is the name of the node to read the input from... this is why its called
the 'source' node. The third field, source_node_output_var,
is the name of the variable from the source node to accept as input.
For example, suppose that our Data Flow network contains 2 nodes named
NODE1 and NODE2. NODE1 has 2 output variables named OUT1 and OUT2
and NODE1 has 1 input variable named IN1 that will be connected to NODE1's
output variable named OUT1. Here is the RGB text that will accomplish this:
Network: SAMPLE_NET
{ <node: NODE1> <type: TYPE1> <node: NODE2>
} |
Note that the output variable names are not explicitly specified in the Data Flow text file. The name of the output variables are defined in the actuall C/C++ code that implements the functionallity of each node. A node can have more than one input variable, and these may also come from different nodes. It's up to the user to make sure that all the variable names correspond to the actual implementation of each node type.
<netInput: input_node_name>
<netOutput: output_node_name>
The first block with key netInput: is used to set the input node of the Data Flow network. The second one, with key netOutput: is used to set the output node of the network. For the 2 blocks, the right side is the name of the node to be set as input or output for the Data Flow network.
To include a subnet into a Data Flow network simply use the name of the subnet as the type of the node where the subnet should be inserted. A net that can be included as a subnet must have its input and output node explicitly specified in the Data Flow network text file using the <netInput: ...> and <netOutput: ...> network attribute blocks.
Important: A Data Flow network does not support cycles in the
net inclusion (subnets) so make sure that there are no cycles in the inclusion
of subnets. Here is an example of Data Flow network that includes a simple
2 node subnet:
Network: BIGNET
{ <node: AUDIO> <type: AUDIOFILE> <param: FILENAME, string:"/home/aUser/test.au"> <node: FRAME> <type: FRAMING>
/* Subnet node */
<node: FFT> <type: FFT>
<node: PS> <type: POWERSPECTRUM>
<node: FILTER> <type: FILTER1>
<node: COND> <type: CONST>
<node: SWITCH> <type: SWITCH>
<netOutput: SWITCH>
Network: WINDOW
<node: WINDOW> <type: PRODUCT> /* INPUT1 is not specified here
because it will get it from the 'wrapping' node. */
<netOutput: WINDOW>
|
In the data flow network there exists a special network that acts
like a loop (while, for, etc.) and is specified by the Iterator:
keyword. An Iterator Network must have the regular netInput and netOutput
nodes plus the netCondition that enables us to verify if a certain condition
holds. When this condition is false, the iteration stops and the execution
continues at the output of the iterator network. You can specify the network
parameter DOWHILE if you want the condition to be tested after each iteration.
Iterator: MY_ITERATOR_NET
{ <node: NODE1> <type: TYPE1> <node: NODE2> <type: TYPE2>
/* We are checking for the validity of the
output of NODE1 */
<netInput: NODE1>
} |