Top Up Prev Next Bottom Contents Index Search

2.3 The Ptolemy preprocessor language (ptlang)


The Ptolemy preprocessor, ptlang, was created to make it easier to write and document star class definitions to run under Ptolemy. Instead of writing all the class definitions and initialization code required for a Ptolemy star, the user can concentrate on writing the action code for a star and let the preprocessor generate the standard initialization code for portholes, states, etc. The preprocessor generates standard C++ code, divided into two files (a header file with a .h extension and an implementation file with a .cc extension). It also generates standardized documentation, in a file with a .html extension, to be included in the manual. In releases before Ptolemy 0.7, Ptolemy used .t files, which conained troff source

2.3.1 Invoking the preprocessor

The definition of a star named YYY in domain XXX should appear in file with the name XXXYYY.pl. The class that implements this star will be named XXXYYY. Then, running the command

ptlang XXXYYY.pl will produce the files XXXYYY.cc, XXXYYY.h, and XXXYYY.html. Implementation of the preprocessor

The preprocessor is written in yacc and C. It does not attempt to parse the parts of the language that consist of C++ code (for example, go methods); for these, it simply counts curly braces to find the ends of the items in question. It outputs #line directives so the C++ compiler will print error messages, if any, with respect to the original source file.

2.3.2 An example

To make things clearer, let us start with an example, a rectangular pulse star in the file SDFRect.pl:


defstar {
name { Rect }
domain { SDF }
desc {
Generates a rectangular pulse of height "height" (default 1.0).
with width "width" (default 8).
}
version {%W% %G%}
author { J. T. Buck }
copyright {1993 The Regents of the University of California}
location { SDF main library }
state {
name { height }
type { float }
default { 1.0 }
desc { Height of the rectangular pulse. }
}
state {
name { width }
type { int }
default { 8 }
desc { Width of the rectangular pulse. }
}
state {
name { count }
type { int }
default { 0 }
desc { Internal counting state. }
attributes { A_NONSETTABLE|A_NONCONSTANT }
}
output { // the output port
name { output }
type { float }
desc { The output pulse. }
}
go { // the run-time function
double t = 0.0;
if (count < width) t = height;
count = int(count) + 1;
output%0 << t;
}
}
Running the preprocessor on the above file produces the three files SDFRect.h, SDFRect.cc and SDFRect.html; the names are determined not by the input filename but by concatenating the domain and name fields. These files define a class named SDFRect.

At the time of this writing, only one type of declaration may appear at the top level of a Ptolemy language file, a defstar, used to define a star. Sometime in the future, a defgalaxy section may also be supported. The defstar section is itself composed of subitems that define various attributes of the star. All subitems are of the form

keyword { body } where the body may itself be composed of sub-subitems, or may be C++ code (in which case the Ptolemy language preprocessor checks it only for balanced curly braces). Note that the keywords are not reserved words; they may also be used as identifiers in the body.

2.3.3 Items that appear in a defstar

The following items can appear in a defstar directive. The items are given in the order in which they typically appear in a star definition (although they can appear in any order). An alphabetical listing and summary of directives is given in table
2-1.

name

This is a required item, and has the syntax


name { identifier }
It (together with the domain) provides the name of the class to be defined and the names of the output files. Case is important in the identifier.

domain

This is a required item; it specifies the domain, such as SDF. The syntax is:


domain { identifier }
where identifier specifies the domain (again, case is important).

derivedfrom

This optional item indicates that the star is derived from another class. Syntax:


derivedfrom { identifier }
where identifier specifies the base class. The .h file for the base class is automatically included in the output .h file, assuming it can be located (you may need to create a makefile).

For example, the LMS star in the SDF domain is derived from the FIR star. The full name of the base class is SDFFIR, but the derivedfrom statement allows you to say either

derivedfrom { FIR } or

derivedfrom { SDFFIR } The derivedfrom statement may also be written derivedFrom or derived.

descriptor

This item defines a short description of the class. This description is displayed by the profile pigi command. It has the syntax

descriptor { text } where text is simply a section of text that will become the short descriptor of the star. You may also write desc instead of descriptor. 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 (described below), 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.
}
By convention, in these descriptors, references to the names of states, inputs, 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 seems to get long, augment it with the htmldoc directive, explained below. However, it should be long enough so that it is sufficient to explain the function of the star.

version

This item contains two entries as shown below


version { number MO/DA/YR }
where the number is a version number, and the MO/DA/YR 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 star. The syntax is


author { author1, author2 and 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 notice to the .h, .cc, and .t files. The syntax is


copyright { copyright information }
For example, we used to use the following (our lawyers have recently caused us to increase the verbosity):


copyright {1994 The Regents of the University of California}
The copyright may span multiple lines, just like a descriptor. In house, we use the SCCS %Q% keyword to update the date when a file is changed. A typical copyright line might look like:

copyright {1990-%Q% The Regents of the University of
California}

location

This item describes the location of a star definition. The following descriptions are used, for example:


location { SDF dsp library }
or

location { directory } where directory is the location of the star. This item is for documentation only.

explanation

This item is used to give longer explanations of the function of the stars. In releases previous to Ptolemy 0.7, this item included troff formatting directives. In Ptolemy 0.7 and later, this item has been superceded by the htmldoc item.

htmldoc

This item is used to give longer explanations that include HTML format directives. The Tycho system includes an HTML viewer that can be used to display star documentation. The HTML output of ptlang can be viewed by any HTML viewer, but certain features, such as the <tcl></tcl> directive are only operational when viewed with Tycho. For complete documentation for the Tycho HTML viewer, see the HTML viewer Help menu.

state

This item is used to define a state or parameter. Recall that by definition, a parameter is the initial value of a state. Here is an example of a state definition:

state {
name { gain }
type { int }
default { 10 }
desc { Output gain. }
attributes { A_CONSTANT|A_SETTABLE }
}
There are five types of subitems that may appear in a state statement, in any order. The name field is the name of the state; the type field is its type, which may be one of int, float, string, complex, fix, intarray, floatarray, complexarray, precision, or stringarray. Case is ignored for the type argument.

The default item specifies the default initial value of the state; its argument is either a string (enclosed in quotation marks) or a numeric value. The above entry could equivalently have been written:


default { "1.0" }
Furthermore, if a particularly long default is required, as 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:


default {
"(-.040609,0.0) (-.001628,0.0) (.17853,0.0) (.37665,0.0)"
"(.37665,0.0) (.17853,0.0) (-.001628,0.0) (-.040609,0.0)"
}
For complex states, the syntax for the default value is

(real, imag) where real and imag evaluate to integers or floats.

The precision state is used to give the precision of fixed-point values. These values may be other states or may be internal to the star. The default can be specified in either of two ways:

input, output, inout, inmulti, outmulti, inoutmulti

These keywords are used to define a porthole, which may be an input, output, inout (bidirectional) porthole or an input, output, or inout multiporthole. Bidirectional ports are not supported in most domains (The Thor domain is an exception). Like state, it contains subitems. Here is an example:


input {
name { signalIn }
type { complex }
numtokens { 2 }
desc {A complex input that consumes 2 input particles.}
}
Here, name specifies the porthole name. This is a required item. type specifies the particle type. The scalar types are int, float, fix, complex, message, 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. For more information on all of these, please see chapter 4, "Data Types".

The numtokens keyword (it may also be written num or numTokens) specifies the number of tokens consumed or produced on each firing of the star. This only makes sense for certain domains (SDF, DDF, and BDF); in such domains, if the item is omitted, a value of one is used. For stars where this number depends on the value of a state, it is preferable to leave out the numtokens 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 used primarily 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 porthole; this syntax is used in connection with ANYTYPE to specify a link between the types of two portholes. The syntax is


type { = name }
where name is the name of another porthole. This indicates that this porthole inherits its type from the specified porthole. For example, here is a portion of the definition of the SDF Fork star:




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

constructor

This item allows the user 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 portholes, states, 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 star 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 (see page 2-14).

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 function1. The optional keyword inline may appear before destructor; if so, the destructor function definition appears inline, in the header file. Since the destructor for all stars is virtual, this is only a win when the star is used as a base for derivation.

setup

This item defines the setup method, which is called every time the simulation is started, before any compile-time scheduling 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 portholes, and to initialize states. The code syntax for doing this is explained starting on page 2-16. 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 scheduler setup method is called (i.e., after any compile-time scheduling 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 star. It is always called exactly once when a simulation is started.

go

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


go { body }
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 starting on page 2-16.

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 starting on page 2-16. 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, you should free memory from the previous run in the setup or begin method, prior to allocating new memory, and in the destructor.

public, protected, private

These three keywords allow the user 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 star:


protected {
XGraph graph;
double index;
}
This defines an instance of the class XGraph, defined in the Ptolemy 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 directives 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. The syntax is:


ccinclude { inclist }
hinclude { inclist }
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 user 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 user 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 star. 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 star that is being defined. Here is an 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
inline
pure
pure virtual
inline virtual
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.

Here are the method subitems:


name:
The name of the method. This is a required item.

access:
The level of access for the method, one of public, protected, or private. If the item is omitted, protected is assumed.

arglist:
The argument list, including the outermost parentheses, for the method as a quoted string. If this is omitted, the method has no arguments.

type:
The return type of the method. If the return type is not a single identifier, you must put quotes around it. If this is omitted, the return type is void (no value is returned).

code:
The code that implements the method. This is a required item, unless the pure keyword appears, in which case this item cannot appear.

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 star'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.

codeblock

Codeblocks are parametrized blocks of code for use in code generation stars. Their use and format is discussed in detail in the code generation chapters. The syntax is:


codeblock {
code
...
}


Top Up Prev Next Bottom Contents Index Search

1 Note, however, that wrapup is not called if an error occurs. See page 2-14.

Copyright © 1990-1997, University of California. All rights reserved.