setup
and begin
methods, if any, are called every time a new simulation run is started, the go
method (which always exists except for stars like BlackHole
and Null
that do nothing) is called each time a star is executed, and the wrapup
method is called after the simulation run completes without errors.XXX
use objects of class InXXXPort
and OutXXXPort
(derived from PortHole
) for input and output, respectively. The examples we use here are for the SDF domain. See the appropriate domain chapter for variations that apply to other domains.InSDFPort
and OutSDFPort
after the preprocessor is finished. These are derived from base class PortHole
. For example, given the following directive in the defstar
of an SDF star,in
, of type InSDFPort
, will become part of the star.
We are not usually interested in directly accessing these porthole classes, but rather wish to read or write data through the portholes. All data passing through a porthole is derived from base class Particle
. Each particle contains data of the type specified in the type
subdirective of the input
or output
directive.
The operator "%
" operating on a porthole returns a reference to a particle. Consider the following example:
%
" operator specifies the delay of the access. A zero always means the most recent particle. A one means the particle arriving just before the most recent particle. The same rules apply to outputs. Given an output named out
, the same particles that are read from in
can be written to out
in the same order as follows:out%n
returns a reference to a particle, and hence can accept an assignment. The assignment operator for the class Particle
is overloaded to make a copy of the data field of the particle.
Operating directly on class Particle
, as in the above examples, is useful for writing stars that accept anytype
of input. The operations need not concern themselves with the type of data contained by the particle. But it is far more common to operate numerically on the data carried by a particle. This can be done using a cast to a compatible type. For example, since in
above is of type float
, its data can be accessed as follows:
double(in%0)
can be used anywhere that a double can be used. In many contexts, where there is no ambiguity, the conversion operator can be omitted:
To write data to an output porthole, note that the right-hand side of the assignment operator should be of type Particle
, as shown in the above example. An operator <<
is defined for particle classes to make this more convenient. Consider the following example:
<<
operator and the assignment operator; the latter operator copies Particles, the former operator loads data into particles. The type of the right-side operand of <<
may be int
, float
, double
, Fix
, Complex
or Envelope
; the appropriate type conversion will be performed. For more information on the Envelope
and Message
types, please see the chapter
"Data Types" on page 4-1.in%1
was referenced, some special action is required to tell Ptolemy that past input particles are to be saved. Special action is also required to tell the SDF scheduler how many particles will be consumed at each input and produced at each output when a star fires. This information can be provided through a call to setSDFParams
in the setup
method. This has the syntaxname
is the name of the input or output porthole, multiplicity
is the number of particles consumed or produced, and past
is the maximum value that offset
can take in any expression of the form name%offset
. For example, if the go
method references name
%0
and name
%1
, then past
would have to be at least one. It is zero by default.MultiPortHole
and its derived classes. An object of this class has a sequential list of PortHole
s. For SDF, we have the specialized derived class MultiInSDFPort
(which contains InSDFPorts
) and MultiOutSDFPort
(which contains OutSDFPorts
). Defining a multiple porthole is easy, as illustrated next:
MultiPortHole
, the MPHIter
iterator class should be used. Iterators are explained in more detail in
"Iterators" on page 3-10. Consider the following code segment from the definition of the SDF Fork
star:type
of the output MultiPortHole
is inherited from the type of the input. The first line of the go
method creates an MPHIter
iterator called nextp
, initialized to point to portholes in output
. The "++
" operator on the iterator returns a pointer to the next porthole in the list, until there are no more portholes, at which time it returns NULL
. So the while
construct steps through all output portholes, copying the input particle data to each one.
Consider another example, taken from the SDF Add
star:
MPHIter
iterator named nexti
is created and used to access the inputs.
Upon occasion, the numberPorts
method of class MultiPortHole
, which returns the number of ports, is useful. This is called simply as portname
.numberPorts()
, and it returns an int
.
<<
" operators are defined as virtual methods in the base class Particle
. There are never really objects of class Particle
in the system; instead, there are objects of class IntParticle
, FloatParticle
, ComplexParticle
, and FixParticle
, which hold data of type int
, double
(not float!), Complex
, and Fix
, respectively (there are also MessageParticle
and a variety of matrix particles, described later). The conversion and loading operators are designed to "do the right thing" when an attempt is made to convert between mismatched types.
Clearly we can convert an int
to a double
or Complex
, or a double
to a Complex
, with no loss of information. Attempts to convert in the opposite direction work as follows: conversion of a Complex
to a double
produces the magnitude of the complex number. Conversion of a double
to an int
produces the greatest integer that is less than or equal to the double
value. There are also operators to convert to or from float
and Fix
.
Each particle also has a virtual print
method, so a star that writes particles to a file can accept anytype
.
state
directive. The star can use a state to store data values, remembering them from one invocation to another. They differ from ordinary members of the star, which are defined using the public
, protected
, and private
directives, in that they have a name, and can be accessed from outside the star in systematic ways. For instance, the graphical interface pigi
permits the user to set any state with the A_SETTABLE
attribute to some value prior to a run, using the edit-params command. The interpreter provides similar functionality through the setstate
command. The state attributes are set in the state
directive. A state may be modified by the star code during a run. The attribute A_NONCONSTANT
is used as a
pragma to mark a state as one that gets modified during a run. There is currently no mechanism for checking the correctness of these attributes.
All states are derived from the base class State
, defined in the Ptolemy kernel. The derived state classes currently defined in the kernel are FloatState
, IntState
, ComplexState
, StringState
, FloatArrayState
, IntArrayState
, ComplexArrayState
, and StringArrayState
.
A state can be used in a star method just like the corresponding predefined data types. As an example, suppose the star definition contains the following directive:
FloatState
with default value 1.0. No attributes are defined, so A_CONSTANT
and A_SETTABLE
, the default attributes, are assumed. To use the value of a state, it should be cast to type double
, either explicitly by the programmer or implicitly by the context. For example, the value of this state can be accessed in the go
method as follows:myState
has an explicit cast to double
; this cast is defined in FloatState
class. Similarly, a cast to int
is available for IntState
, to Complex
from ComplexState
, and to const
char*
for Stringstate
). In principle, it is possible to rely on the compiler to automatically invoke this cast. However:
Warning: some compilers (notably some versions of
g++) may not choose the expected cast. In particular, g++ has been known to cast everything to Fix
if the explicit cast is omitted in expressions similar to that above. The arithmetic is then performed using fixed-point point computations. This will be dramatically slower than double or integer arithmetic, and may yield unexpected results. It is best to explicitly cast states to the desired form. An exception is with simple assignment statements, like
SDFChop
star, in which use_past_inputs
is an integer state,
Note that the type Complex
is not a fundamental part of C++. We have implemented a subset of the Complex
class as defined by several library vendors; we use our own version for maximum portability. Using the ComplexState
class will automatically ensure the inclusion of the appropriate header files. A member of the Complex
class can be initialized and operated upon any number of ways. For details, see
"The Complex data type" on page 4-1.
A state may be updated by ordinary assignment in C++, as in the following lines
FloatState
class definition has overloaded the assignment operator ("=
") to set its value from a double
. Similarly, an IntState
can be set from an int
and a StringState
can be set from a char*
or const char*
. ArrayState
classes ( FloatArrayState
, IntArrayState
and ComplexArrayState
) are used to store arrays of data. For example,double
with dimension four, with each element initialized to zero. Quotes must surround the initial values. Alternatively, you can specify a file name with a prefix
<
. If you have a file named foo
that contains the default values for an array state, you can write,ArrayState
objects: the two value strings[]
. The number of elements in an ArrayState
can be determined by calling its size
method. The size is not specified explicitly, but is calculated by scanning the default value.
As an example of how to access the elements of an ArrayState
, suppose fState
is a FloatState
and aState
is a FloatArrayState
. The accesses, like those in the following lines, are routine:
FloatArrayState
, consider the FIR
star defined below. Note that this is a simplified version of the SDF FIR
star that does not permit interpolation or decimation.setup
method; this is necessary to allocate a buffer in the input PortHole
large enough to hold the particles that are accessed in the go
method. Notice the use of the size
method of the FloatArrayState
.
We now illustrate an
ptcl
interpreter session using the above FIR
star. Assume there is a galaxy called singen
that generates a sine wave. you can use it with the FIR
star, as in:
foo
", which contains the data:FloatArrayState
are changed by a setstate
command. Also, notice that file values may be combined with string values; when