The SR Domain
Introduction
The Synchronous/Reactive domain implements a model of computation
based on a the synchronous model of time like that in the Esterel
language [1]. It is well-suited for
specifying discrete reactive controllers--systems that maintain an
ongoing dialog with their environment and must react to it at a speed
dictated by the environment.
The model of time in the SR domain is based on the concept of an
infinitely-fast machine. When an input arrives from the outside
world, the infinitely fast machine computes and produces its reaction
at the same instant the input arrives. Time is thus a series
of discrete instants when the machine is performing a computation.
Between these instants, nothing happens.
The stars in the SR domain communicate through unbuffered single
driver, multiple receiver arcs. These arcs carry valued events, which
may be present with a value, absent, or unknown in each instant. The
value on an arc does not persist between instants.
The SR domain domain simulates the execution of an infinitely-fast
machine an instant at a time. The behavior of the system in each
instant is simulated in two phases. In the first phase, the stars in
the system are fired repeatedly (their go() methods are
called) to reach a fixed-point on the arcs' values. The stars in the
SR domain satisfy a monotonicity constraint that ensures this fixed
point always exists and is unique, regardless of firing order. In the
second phase, all stars are instructed (their tick() method
is called) to advance their state, if any, based on the values of
their input arcs. This prepares them for the next instant.
Broadly, there are two types of stars in the SR domain: strict and
non-strict. If any input to a strict star is unknown, then all of its
outputs are unknown. A two-input adder, for example, behaves like
this--it cannot say anything about its output until the values of both
inputs are known. A non-strict star, by contrast, can produce some
outputs before all of its inputs are known. A two-input multiplexer
is an example: when the selection input is known, it can ignore the
unselected input.
Non-strict stars are the key to avoiding deadlocked situations when
there are cyclic connections in the system. If all the stars in a
cycle are strict, they each need all of their inputs before producing
an output--all will be left waiting. The deadlock can be broken by
introducing a non-strict star into the cycle that can produce an
output without having all inputs from other stars in the cycle
Writing SR Stars
A porthole on an SR star can have an unknown value, an absent value,
or be present with a particle. These states can be tested with the
following methods, which can be called on both input and output
PortHoles:
- int SRPortHole::known()
- Return TRUE when the value in the port is is known
- int SRPortHole::present()
- Return TRUE when the value in the port is present
- int SRPortHole::absent()
- Return TRUE when the value in the port is absent
Once the presence of a particle on an input port is established, it
can be accessed as follows:
- Particle & InSRPort::get()
- Return the particle in the port. This should only be called
when present() returns TRUE
The value on an output port can be established by calling one of the
following. In an instant, a star may invoke one of these methods
exactly once--more than this is an error. (This ensures the
fixed-point computation in an instant always terminates.)
- Particle & OutSRPort::emit()
- Force the value on the output port to be present and
return a reference to the output particle.
- void OutSRPort::makeAbsent()
- Force the value on the output port to be absent.
A number of methods set attributes of SR stars. These should be
called in the setup method of a star as appropriate. By
default, none of these attributes is assumed to hold.
- SRStar::reactive()
- Indicate the star is reactive--it needs at least one
present input to produce a present output.
- Star::noInternalState()
- Indicate the star has no internal state--its behavior in
an instant is a function only of the inputs in that instant,
and not on history.
By default, a star in the SR domain is strict. Here is (abbreviated)
ptlang source for a two-input adder:
defstar {
name { Add }
domain { SR }
input {
name { input1 }
type { int }
}
input {
name { input2 }
type { int }
}
output {
name { output }
type { int }
}
setup {
reactive();
noInternalState();
}
go {
if ( input1.present() && input2.present() ) {
output.emit() << int(input1.get()) + int(input2.get());
} else {
Error::abortRun(*this, "One input present, the other absent");
}
}
}
Non-strict stars inherit from the SRNonStrictStar class.
Here is abbreviated source for a non-strict two-input multiplexer:
defstar {
name { Mux }
domain { SR }
derivedFrom { SRNonStrictStar }
input {
name { trueInput }
type { int }
}
input {
name { falseInput }
type { int }
}
input {
name { select }
type { int }
}
output {
name { output }
type { int }
}
setup {
noInternalState();
reactive();
}
go {
if ( !output.known() && select.known() ) {
if ( select.present() ) {
if ( int(select.get()) ) {
// Select is true--copy the true input if it's known
if ( trueInput.known() ) {
if ( trueInput.present() ) {
output.emit() << int(trueInput.get());
} else {
// true input is absent: make the output absent
output.makeAbsent();
}
}
} else {
// Select is false--copy the false input if it's known
if ( falseInput.known() ) {
if ( falseInput.present() ) {
output.emit() << int(trueInput.get());
} else {
// false input is absent: make the output absent
output.makeAbsent();
}
}
}
} else {
// Select is absent: make the output absent
output.makeAbsent();
}
}
}
}
- [1]
- Gerard Berry and Georges Gonthier.
- The Esterel synchronous programming language: Design, semantics,
implementation.
- Science of Computer Programming, 19(2):87-152, November 1992.
-
ftp://cma.cma.fr/esterel/BerryGonthierSCP.ps.Z
.