Keywords in detail

The following items can appear in a defprimitive item. The items are given in the order in which they typically appear in a primitive source file, although they can appear in any order.

name

This is a required item and has the syntax

name { identifier }

Together with the domain, this provides the name of the class to be defined and the names of the output files. The identifier is case sensitive.

domain

This is a required item. It specifies the domain, such as SDF. The syntax is

domain { identifier }

where identifier specifies the domain (again, it is case sensitive).

derivedfrom

This optional item indicates that the primitive is derived from another class. The derived and base primitives must be defined in the same domain. Syntax:

derivedfrom { identifier }

Where identifier specifies the base class. The .h file for the base class is automatically included in the output .h file and the directory where the base class is located is added in the include section of the primitive’s makefile. The derivedfrom statement may also be written derivedFrom or derived. See also the go method for information regarding the usage for derived primitives.

desc

This item defines a short description of the class. It is displayed in a tooltip when you position the mouse cursor over the element in the Tree View window or over an instance. It has the syntax

desc { text }

where text is simply a section of text that will become the short descriptor of the primitive. A principal use of the short descriptor is to get on-screen help, so the descriptor should not include any troff formatting commands. Unlike the htmldoc, it does not pass through troff. The following are legal descriptors:

desc { A one line descriptor. }

or

desc
{
   A multi-line descriptor. The same line breaks and spacing
   will be used when the descriptor is displayed on the screen.
}

In these descriptors, inputs, references to the names of parameters (states), and outputs, should be enclosed in quotation marks. Also, each descriptor should begin with a capital letter, and end with a period. If the descriptor is too long, augment it with the htmldoc item, explained below.

version

This item contains two entries as shown below

version { number mm/dd/yy }

where the number is the version number, and the mm/dd/yy is the version date. If you are using SCCS for version control then the following syntax will work well:

version { %W% %G% }

When the file is checked in by SCCS, the string %W% will be replaced with a string of the form: @(#)filename num, where num is the version number, and %G% will be replaced with a properly formatted date.

author

This optional entry identifies the author or authors of the primitive. The syntax is:

author { author1, author2, author3 }

Any set of characters between the braces will be interpreted as a list of author names.

acknowledge

This optional entry attaches an acknowledgment section to the documentation. The syntax is:

acknowledge { arbitrary single line of text }

copyright

This optional entry attaches a copyright note to the .h, and .cc files. The syntax is:

copyright { copyright information }

The copyright may span multiple lines, just like the descriptor. A typical copyright note is used as follows

copyright {1990-1994 The Regents of the
University of California}

location

This item describes the location of a primitive definition. The following descriptions can be used:

location { SDF dsp library }

or

location { directory }

where directory is the location of the primitive. Please note that this item is for documentation only.

explanation

This item is used to give longer explanations of the function of the primitives. This item is obsolete and has been superceded by the htmldoc item.

htmldoc

This item is used to give longer explanations, including HTML format directives. MLDesigner uses an HTML viewer to display primitive documentation.

defparameter

This item is used to define a parameter.

Here is an example of a parameter definition:

defparameter
{
  name       { gain }
  type       { int }
  default    { 10 }
  desc       { Output gain. }
  attrib     { A_CONSTANT | A_SETTABLE }
}

There are five types of sub items that may appear in a parameter statement, in any order. The name field is the name of the parameter. The type field is its type, which may be one of int, float, string, complex, fix, intarray, floatarray, stringarray, complexarray, fixarray, precision, boolean, enum, file, expression, datastruct and many others. Case is ignored for the type argument. The default item specifies the initial value of the parameter, its argument is either a string (enclosed in quotation marks) or a numeric value. The above entry could equally have been written:

default { "1.0" }

Furthermore, if a particularly long default is required, for example when initializing an array, the string can be broken into a sequence of strings. The following example shows the default for a ComplexArray:

{
  "(-.040609,0.0) (-.001628,0.0) ( .17853 ,0.0)"
  "( .37665 ,0.0) ( .17853 ,0.0) (-.001628,0.0)"
}

For complex parameters, the syntax for the default value is

(real, imag)

where real and imag evaluate to integers or floats. The precision parameter is used to give the precision of fixed-point values. These values can be other parameters or can be internal to the primitive. The default can be specified in either of two ways:

  1. As a string like ”3.2”, or more generally ”m.n”, where m is the number of integer bits (to the left of the binary point) and n is the number of fractional bits (to the right of the binary point). Thus length is m+n.
  2. A string like ”24/32” which means 24 fraction bits from a total length of 32. This format is often more convenient because the word length often remains constant while the number of fraction bits changes with the normalization being used.

In both cases, the sign bit counts as one of the integer bits, so this number must be at least one. The desc (or descriptor) item, which is optional but highly recommended, attaches a descriptor to the parameter. The same formatting options are available as with the primitive descriptor.

Finally, the attrib keyword specifies parameter attributes. Two attributes are defined for all parameters: A_CONSTANT and A_SETTABLE (along with their complements A_NONCONSTANT and A_NONSETTABLE). If a parameter has the A_CONSTANT attribute, then its value is not modified by the run-time code in the primitive (it is up to you as the primitive writer to ensure that this condition is wanted). Parameters with the A_NONCONSTANT attribute may change when the primitive is run. If a parameter has the A_SETTABLE attribute, you can change the value of the parameter when you instantiate the primitive. Values of parameters without this attribute are not editable for primitive instances. Such parameters will always start with their default values as the initial value.

If no attributes are specified, the default is A_CONSTANT | A_SETTABLE. Thus, in the above example, the attributes item is unnecessary. The notation A_CONSTANT | A_SETTABLE indicates a logical ”or” of two flags. This means that they both apply A_CONSTANT and A_SETTABLE. Code generation primitives use a great number of attributes, most of them specific to the language model for which code is being generated. Mechanisms for accessing and updating parameters in C++ methods associated with a primitive are explained in the Parameters and Array Parameter sections.

Sub item Summary Required
name the name of the state variable yes
type data type of the state variable yes
default the default initial value, always a string yes
desc summary of the function of the state no
attrib hints to the simulator or code generator no

defevent

This item is used to define an event. Here is an example of an event definition:

defevent
{
  name    { Event1 }
  scope   { Internal }
  type    { Root }
  default { "{Root}" }
  code
  {
  }
}

There are five types of sub items that appear in an event statement, in any order. The name field is the name of the event. The scope field specifies whether the event is external (visible) or internal (hidden). The type field is its type which can be any data structure type derived from Root or Root itself. The default value specifies the initial value of the event shared element that is used if the event occurs. This item is only used in case of internal events. The syntax has to conform with declarations of data structure value. The event definition can contain a code section that defines the code which is executed if the event occurs.

Sub item Summary Required
name the name of the event yes
scope the visibility of the event yes
type the data type of the event yes
default the default initial value, always a string no
code C++ code to be executed if the event occurs no

defmemory

This item is used to define a memory. Here is an example of a memory definition:

defmemory
{
  name    { Memory1 }
  scope   { Internal }
  type    { Root }
  default { "{Root}" }
}

There are four types of sub items that appear in a memory statement, in any order. The name field is the name of the memory. The scope field specifies whether the memory is external or internal, i.e., visible or hidden respectively. The type field is its type which can be any data structure type derived from Root or Root itself. The default specifies the initial value of the memory shared element. This value is used until a model instance will write data into the memory. The default item is only used in case of internal memories. The syntax has to conform with declarations of data structure value.

Sub item Summary Required
name the name of the memory yes
scope the visibility of the memory yes
type the data type of the memory yes
default the default initial value, always a string no

defresource

This item is used to define a resource. Here is an example of a resource definition:

defresource
{
  name  { Resource1 }
  type  { "Quantity" }
  scope { External }
  code
  {
    // Arguments of the method
    //   int pSuccess
    //   QuantityTransaction* pTrans
    if (pTrans == NULL)
      return;
    if (pSuccess == 0)
    {
    }
    else if (pSuccess == 1)
    {
    }
    else if (pSuccess == 2)
    {
    }
  }
}

There are four types of sub items that appear in a resource statement, in any order. The name field is the name of the resource. The scope field specifies whether the resource is external or internal, i.e., visible or hidden respectively. The type field specifies whether the resource models a quantity or a server. It defines either the string Quantity or the string Server. The resource definition code defines the code which is executed whenever a transaction exits the resource. When you create a resource with MLDesigner, it creates a code sub item template as shown above automatically.

Sub item Summary Required
name the name of the resource yes
scope the visibility of the resource yes
type type of resource, Quantity or Server yes
code C++ code to be executed whenever a transaction exits the resource no

input, output, inout, inmulti, outmulti

These keywords are used to define a port also called porthole, which may be an input, output, inout (bidirectional) port or an input/output multiport. Bidirectional ports are not supported in most domains. Like parameters they contain sub items such as:

input
{  
  name      { signalIn }
  type      { complex }
  numtokens { 2 }
  desc      { A complex input that consumes
              two input particles. }
}

Here, name specifies the port name. This is a required item. Sub item type specifies the particle type. The scalar types are int, float, fix, complex, message, string, file, datastruct, continuous, or anytype. Again, case does not matter for the type value. The matrix types are int_matrix_env, float_matrix_env, complex_matrix_env, and fix_matrix_env. The type item may be omitted; the default type is anytype.

The numtokens keyword, also be written as num or numTokens, specifies the number of tokens consumed or produced on each firing of the primitive. This only makes sense for certain domains like SDF, DDF, and BDF. In such domains, if the item is omitted, a value of one is used. For primitives where this number depends on the value of a parameter, it is preferable to leave out the numtoken specification and to have the setup method set the number of tokens (in the SDF domain and most code generation domains, this is accomplished with the setSDFParams method). This item is primarily used in the SDF and code generation domains, and is discussed further in the documentation of those domains. There is an alternative syntax for the type field of a port. This syntax is used in connection with anytype to specify a link between the types of two ports. The syntax is

type { = name }

where name is the name of another port. This indicates that this port inherits its type from the
specified port. For example, here is a portion of the definition of the SDFFork primitive:

input
{
  name { input }
  type { anytype }
}

outmulti
{
  name { output}
  type { = input}
  desc { Type is inherited from the input. }
}

Sub item Summary Required
name name of the port or group of ports yes
type data type of output particles no
desc summary of the function of the output no
numtokens number of tokens produced by the port (useful only for dataflow domains) no

constructor

This item allows the programmer to specify extra C++ code to be executed in the constructor for the class. This code will be executed after any automatically generated code in the constructor that initializes ports, parameters, etc. The syntax is

constructor { body }

where body is a piece of C++ code. It can be of any length. Note that the constructor is invoked only when the class is first instantiated. Actions that must be performed before every simulation run should appear in the setup or begin methods, not the constructor.

conscalls

You may want to have data members in your primitive that have constructors that require arguments. These members would be added by using the public, private, or protected keywords. If you have such members, the conscalls keyword provides a mechanism for passing arguments to the constructors of those members. Simply list the names of the members followed by the list of constructor arguments for each, separated by commas if there is more than one. The syntax is:

conscalls { member1(arglist), member2(arglist) }

Note that member1 and member2 should have been previously defined in a public, private or protected section.

destructor

This item inserts code into the destructor for the class. The syntax is:

destructor { body }

You generally need a destructor only if you allocate memory in the constructor, begin method, or setup method. Termination functions that happen with every run should appear in the wrapup function. The optional keyword inline may appear before destructor . If it is used, the destructor function definition appears inline, in the header file. Since the destructor for all primitives is virtual, this is only needed if the primitive is used as a base for derivation. See also cleanup.

cleanup

The cleanup method clears memory regardless of whether a simulation ends normally or abnormally. In situations where the user ends the simulation or where an error is displayed before the wrapup method is called, the cleanup code is executed. The syntax is:

cleanup
{
  // delete variable(s)
}

If you free in cleanup dynamically allocated variables, make sure that those variables are initialized to zero in the primitive’s constructor.

The  wrapup method is called before the cleanup method.

setup

This item defines the setup method, which is called every time the simulation is started, before any compile-time schedule is performed. The syntax is:

setup { body }

The optional keyword inline may appear before the setup keyword. It is common for this method to set parameters of input and output ports, and to initialize parameters. The code syntax for this type of method is explained in the  Writing C++ Code for Primitives section. In some domains, with some targets, the setup method may be called more than once during initiation. You must keep this in mind if you use it to allocate or initialize memory.

begin

This item defines the begin method, which is called every time the simulation is started, but after the setup method is called, i.e., after any compile-time schedule is performed. The syntax is:

begin { body }

This method can be used to allocate and initialize memory. It is especially useful when data structures are shared across multiple instances of a primitive. It is always called exactly once when a simulation is started.

go

This item defines the action taken by the primitive when it is fired. The syntax is:

go { body }

For derived primitives the go method is empty. In such cases you can either:

A good example is MLD LibrariesSDF DomainFilterLMSFloat. The LMSFloat primitive is derived from FIRFloat. The go method first updates the taps and then calls FIRFloat’s go method explicitly.

go
{
  // First update the taps
  int index = int(ErrorDelay) * int(DecimationFactor) +
    int(DecimationPhase);
  double factor = double(Error%0) * double(StepSize);
  for (int i = 0; i < Coefficients.size(); i++)
  {
    Coefficients[i] += factor * double(Input%(index));
    index++;
  }

  // Then run FIR filter
  SDFFIRFloat :: go();
}

The optional keyword inline may appear before the go keyword. The go method will typically read input particles and write outputs, and will be invoked many times during the course of a simulation. The code syntax for the body is explained in Writing C++ Code for Primitives.

wrapup

This item defines the wrapup method, which is called at the completion of a simulation. The syntax is:

wrapup { body }

The optional keyword inline may appear before the wrapup keyword. The wrapup method might typically display or store final state values. The code syntax for doing this is explained in the Writing C++ Code for Primitives section. Note that the wrapup method is not invoked if an error occurs during execution. Thus, the wrapup method cannot be used reliably to free allocated memory. Instead, the dynamically allocated memory should be freed in the cleanup method or in the primitive’s destructor.

public, protected, private

These three keywords allow the programmer to declare extra members for the class with the desired protection. The syntax is:

protkey { body }

where protkey is public, protected, or private. Example, from the XMgraph primitive:

protected
{
  XGraph graph;
  double index;
}

This defines an instance of the class XGraph, defined in the MLDesigner kernel, and a double-precision number. If any of the added members require arguments for their constructors, use the conscalls item to specify them.

ccinclude, hinclude

These items cause the .cc file, or the .h file, to #include extra files. A certain number of files are automatically included, when the preprocessor can determine that they are needed, so they do not need to be explicitly specified. If the file to be included is in the kernel it may be necessary to put in the absolute path in future versions of MLDesigner. The syntax is:

ccinclude { inclist }
hinclude  { inclist }
ccinclude { "base/String.h" }

where inclist is a comma-separated list of include files. Each filename must be surrounded either by quotation marks or by < and > for system include files like <math.h>.

code

This keyword allows the programmer to specify a section of arbitrary C++ code. This code is inserted into the .cc file after the include files but before everything else. It can be used to define static non-class functions, declare external variables, or anything else. The outermost pair of curly braces is stripped. The syntax is:

code { body }

header

This keyword allows the programmer to specify an arbitrary set of definitions that will appear in the header file. Everything between the curly braces is inserted into the .h file after the include files but before everything else. This can be used, for example, to define classes used by your primitive. The outermost pair of curly braces is stripped.

method

The method item provides a fully general way to specify an additional method for the class of primitive that is being defined, for example:

virtual method
{
  name    { exec }
  access  { protected }
  arglist { "(const char* extraOpts)" }
  type    { void }
  code
  {
    // code for the exec method goes here
  }
}

An optional function type specification may appear before the method keyword, which must be one of the following:

virtual
pure
inline
static
const

The virtual keyword makes a virtual member function. If the pure virtual keyword is given, a pure virtual member function is declared. There must be no code item in this case. The function type pure is a synonym for pure virtual. The inline function type declares the function to be inline.

If you use multiple type specifiers, the keywords have to be in the following relative order:

[const][inline][pure][virtual]

The static keyword declares a static method of the primitive class. It cannot be used in conjunction with [const] or [pure] virtual as C++ does not support this. You can therefore use either static method or inline static method to declare a static member function.

Sub item Summary Required
name The name of the method. yes
access The level of access for the method, one of public, protected or private. If the item is omitted, protected is assumed. no
arglist The argument list, including the outermost parentheses, for the method as a quoted string. If this is omitted, the method has no arguments. no
type The return type of the method. If the return type is not a single identifier, you have to put quotes around it. If this is omitted, the return type is void (no value is returned). no
code C++ code defining the method. if not pure

exectime

This item defines the optional myExecTime function, which is used in code generation to specify how many time units are required to execute the primitive’s code. The syntax is:

exectime { body }

The optional keyword inline may appear before the exectime keyword. The body defines the body of a function that returns an integer value.

codeblocks

Codeblocks are parameterized blocks of code for use in code generation primitives. The syntax is:

codeblock { code }