state machine M
+diff --git a/docs/fpp-spec.html b/docs/fpp-spec.html index e7cceee74..d8a449d3c 100644 --- a/docs/fpp-spec.html +++ b/docs/fpp-spec.html @@ -9740,7 +9740,7 @@
Built-in types: -When translating to XML, there are a few special types that are abstract +When translating FPP to C++, there are a few special types that are abstract in the model, but that are known to the translator. You don’t have to define C++ classes for these types. We will discuss these types further in the section on @@ -3493,7 +3501,103 @@
A hierarchical state machine (state machine for short) +specifies the following:
+A set of states that a system can be in. +The states can be arranged in a hierarchy (i.e., +states may have substates).
+A set of transitions from one state to another that +occur under specified conditions.
+State machines are important in embedded programming. +For example, F Prime components often have a concept of state +that changes as the system runs, and it is useful to model +these state changes as a state machine.
+In FPP there are two ways to define a state machine:
+An external state machine definition is similar to +an abstract type definition: +it tells the analyzer that a state machine exists with a specified +name, but it says nothing about the state machine behavior. +An external tool must provide the state machine implementation.
+An internal state machine definition is similar to an +array type definition +or +struct type definition: +it provides a complete specification in FPP of the state machine behavior. +The FPP back end uses this specification to generate code; +no external tool is required.
+As of the current version of FPP, only external state machines +are implemented. +Support for internal state machines is in development.
+State machine definitions may appear at the top level or inside a +module definition. +A state machine definition is an +annotatable element.
+To define an external state machine, you write the keywords
+state
machine
followed by an identifier, which is the
+name of the state machine:
state machine M
+This code defines an external state machine with name M
.
+You can then
+instantiate
+the state machine M
in a component definition.
When you define an external state machine M
, you must provide
+an implementation for M
, as discussed in the section
+on implementing external state machines.
+The external implementation must have a header file M.hpp
+located in the same directory as the FPP file where
+the state machine M
is defined.
Support for internal state machines is in development. +It will be available in a future release of FPP.
+In F Prime, the component is the basic unit of FSW function. @@ -3516,7 +3620,7 @@
An FPP component definition defines an F Prime component. To write a component definition, you write the following:
@@ -3561,7 +3665,7 @@A port instance is a component member that specifies an instance of an FPP port used by the instances of the component. @@ -3577,7 +3681,7 @@
The simplest port instance specifies a kind, a name, and a type. The kind is one of the following:
@@ -3686,7 +3790,7 @@The port instances appearing in a component definition must satisfy certain rules. @@ -3722,8 +3826,11 @@
Second, an active or queued component must have asynchronous input.
That means it must have at least one async input port;
-or it must have an internal port (described below);
-or it must have at least one async command (also described below).
+or it must have an internal port;
+or it must have at least one async command; or it must have
+at least one state machine instance.
+Internal ports, async commands, and state machine instances
+are described below.
As an example, if we modify the input ports of our ActiveF32Adder
to make them sync
, we get an error, because
there is no async input.
When you specify a port instance as part of an FPP component, you are actually specifying an array of port instances. @@ -3811,7 +3918,7 @@
For async
input
ports, you may specify a priority.
The priority specification is not allowed for other kinds of ports.
@@ -3851,7 +3958,7 @@
By default, if an invocation of an async
input
port causes
a message queue to overflow, then a FSW assertion fails.
@@ -3913,7 +4020,7 @@
When writing a port instance, instead of specifying a named port type,
you may write the keyword serial
.
@@ -3960,7 +4067,7 @@
A special port instance is a port instance that has a special behavior in F Prime. @@ -3976,7 +4083,7 @@
A command is an instruction to the spacecraft to perform an action. Each component instance C that specifies commands has the following @@ -4098,7 +4205,7 @@
An event is a report that something happened, for example, that a file was successfully uplinked. @@ -4179,7 +4286,7 @@
Telemetry is data regarding the state of the system. A telemetry port allows a component to emit telemetry. @@ -4228,7 +4335,7 @@
A parameter is a configurable constant that may be updated from the ground. @@ -4313,7 +4420,7 @@
A time get port allows a component to get the system time from a time component. @@ -4363,7 +4470,7 @@
A data product is a collection of data that can be stored to an onboard file system, given a priority, and downlinked in priority @@ -4488,7 +4595,7 @@
An internal port is a port that a component can use to send a message to itself. @@ -4614,7 +4721,7 @@
When defining an F Prime component, you may specify one or more commands. When you are operating the FSW, you use the F Prime Ground Data System @@ -4631,7 +4738,7 @@
The simplest command consists of a kind followed by the keyword
command
and a name.
@@ -4729,7 +4836,7 @@
When specifying a command, you may specify one or more formal parameters. @@ -4788,7 +4895,7 @@
Every command in an F Prime FSW application has an opcode. The opcode is a number that uniquely identifies the command. @@ -4898,7 +5005,7 @@
When specifying an async command, you may specify priority and @@ -4952,7 +5059,7 @@
When defining an F Prime component, you may specify one or more events. The F Prime framework converts each event into a C++ @@ -4967,7 +5074,7 @@
The simplest event consists of the keyword event
, a name, a severity,
and a format string.
@@ -5055,7 +5162,7 @@
When specifying an event, you may specify one or more formal parameters. @@ -5133,7 +5240,7 @@
Every event in an F Prime FSW application has a unique numeric identifier. @@ -5204,7 +5311,7 @@
Sometimes it is necessary to throttle events, to ensure that they do not flood the system. @@ -5268,7 +5375,7 @@
When defining an F Prime component, you may specify one or more telemetry channels. @@ -5288,7 +5395,7 @@
The simplest telemetry channel consists of the keyword telemetry
,
a name, and a data type.
@@ -5343,7 +5450,7 @@
Every telemetry channel in an F Prime FSW application has a unique numeric identifier. @@ -5408,7 +5515,7 @@
You can specify how often the telemetry is emitted on a channel C. There are two possibilities:
@@ -5489,7 +5596,7 @@You may specify how a telemetry channel is formatted in the ground display. @@ -5541,7 +5648,7 @@
You may specify limits, or bounds, on the expected values carried on a telemetry channel. @@ -5628,7 +5735,7 @@
When defining an F Prime component, you may specify one or more parameters. @@ -5646,7 +5753,7 @@
The simplest parameter consists of the keyword param
,
a name, and a data type.
@@ -5721,7 +5828,7 @@
You can specify a default value for any parameter. This is the value that F Prime will use if no value is @@ -5782,7 +5889,7 @@
Every parameter in an F Prime FSW application has a unique numeric identifier. @@ -5858,7 +5965,7 @@
Each parameter that you specify has two implied commands: one for setting the value bound to the parameter locally in the @@ -5960,7 +6067,7 @@
When defining an F Prime component, you may specify the data products produced by that component. @@ -5975,7 +6082,7 @@
In F Prime, a data product is represented as a container. One container holds one data product, and each data product @@ -6078,7 +6185,7 @@
Every record in an F Prime FSW application has a unique numeric identifier. @@ -6110,7 +6217,7 @@
@ A struct type defining some data
struct Data { a: U32, b: F32 }
-@ A component for illustrating data product
+@ A component for illustrating data product identifiers
passive component DataProductIdentifiers {
# ----------------------------------------------------------------------
@@ -6159,7 +6266,7 @@ 9.9.2. Identifiers
In the basic form of a record described above, each record that does not have @@ -6226,10 +6333,75 @@
A state machine instance is a component member that instantiates +an FPP state machine. +The state machine instance becomes part of the component implementation.
+For example, here is a simple async component that has +one state machine instance and one async input port +for driving the state machine:
+@ An external state machine
+state machine M
+
+@ A component with a state machine
+active component StateMachine {
+
+ @ A port for driving the state machine
+ async input port schedIn: Svc.Sched
+
+ @ An instance of state machine M
+ state machine instance m: M
+
+}
+When a state machine instance m is part of a component C, +each instance c of C sends m signals to process as it runs. +Signals occur in response to commands or port +invocations received by c, and they tell m when to change state. +c puts the signals on its queue, and m dispatches them. +Therefore, if a component C has a state machine instance member m, +then its instances c must have queues, i.e., C must be active or queued.
+As with internal ports, +you may specify priority and queue full behavior associated +with the signals dispatched by a state machine instance. +For example, we can revise the example above as follows:
+@ An external state machine
+state machine M
+
+@ A component with a state machine
+active component StateMachine {
+
+ @ A port for driving the state machine
+ async input port schedIn: Svc.Sched
+
+ @ An instance of state machine M
+ state machine instance m: M priority 10 drop
+
+}
+You can write a constant definition -or type definition +
You can write a constant definition, +type definition, +enum definition, +or +state machine definition as a component member. When you do this, the component qualifies the name of the constant or type, similarly to the way that a @@ -6363,7 +6535,7 @@
Component definitions can become long, especially when there are many commands, events, telemetry channels, and parameters. @@ -6416,7 +6588,7 @@
Some F Prime components employ the following pattern:
As discussed in the previous section, in F Prime you @@ -6522,14 +6694,14 @@
To instantiate a component, you write a component instance definition. The form of a component instance definition depends on the kind of the component you are instantiating: passive, queued, or active.
To instantiate a passive component, you write the following:
Instantiating a queued component is just like instantiating a passive component, except that you must also specify @@ -6744,7 +6916,7 @@
Instantiating an active component is like instantiating a queued component, except that you may specify additional parameters @@ -6870,7 +7042,7 @@
When you define a component instance I, the FPP translator needs to know the following information about the C++ implementation of I:
@@ -7002,7 +7174,7 @@In an F Prime FSW application, each component instance I has some associated C++ code @@ -7033,7 +7205,7 @@
The FPP translator uses init specifiers when it generates code for an F Prime topology. @@ -7248,7 +7420,7 @@
You may write one or more init specifiers as part of a component instance definition. @@ -7379,7 +7551,7 @@
In F Prime, a topology or connection graph is the @@ -7400,7 +7572,7 @@
We begin with a simple example that shows how many of the pieces fit together.
@@ -7530,7 +7702,7 @@In general, an FPP topology consists of a list of instances and a set of named connection graphs. @@ -7538,7 +7710,7 @@
A direct graph specifier provides a name and a list of connections. @@ -7659,7 +7831,7 @@
A few connection patterns are so common in F Prime that they get special treatment in FPP. @@ -7981,7 +8153,7 @@
As discussed in the section on defining components, @@ -7994,7 +8166,7 @@
To use explicit numbering, you provide an explicit port number for a connection endpoint. @@ -8141,7 +8313,7 @@
Automatic matching: After resolving @@ -8236,7 +8408,7 @@
After resolving explicit numbering and @@ -8291,7 +8463,7 @@
It is often useful to decompose a flight software project into several topologies. @@ -8327,7 +8499,7 @@
To import a topology A
into a topology B
, you write
import A
inside topology B
, like this:
Often when importing topology A
into topology B
, you
want to include one or more instances in A
that exist just
@@ -8511,7 +8683,7 @@
Multiple imports are allowed. For example:
@@ -8549,7 +8721,7 @@In general, transitive imports are allowed.
For example, topology A
may import topology B
,
@@ -8566,7 +8738,7 @@
You can include code from another file in a topology definition. You do this by writing an include specifier. @@ -8578,7 +8750,7 @@
The previous sections have explained the syntactic and semantic elements @@ -8597,7 +8769,7 @@
Unlike F Prime XML, FPP does not require any particular division of model elements into files. @@ -8673,7 +8845,7 @@
As part of an FPP model, you can write one or more include specifiers. An include specifier is an instruction to include FPP source elements @@ -8824,7 +8996,7 @@
Whenever a model spans two or more files, one file F may use one or more definitions appearing in other files. @@ -8921,7 +9093,7 @@
A location specifier is a unit of syntax in an FPP model. It specifies the location of a definition used in the model.
@@ -8935,7 +9107,7 @@A location specifier consists of the keyword locate
, a kind of definition,
the name of a definition, and a string representing a file path.
@@ -8981,7 +9153,7 @@
As with include specifiers, @@ -9010,7 +9182,7 @@
The definition name appearing after the keyword locate
may be a qualified name.
@@ -9057,7 +9229,7 @@
When you write a file that contains definitions and you include that file in another file, @@ -9072,7 +9244,7 @@
Given a collection of FPP source files F, you can generate location specifiers for all the definitions in F. @@ -9084,7 +9256,7 @@
Constants
.
To locate definitions, do the following:
By default, the location path is relative to the current directory. @@ -9143,7 +9315,7 @@
Consider the case where you write a definition in one file and include that file in another file via an @@ -9199,7 +9371,7 @@
Given files F and location specifiers L that locate the definitions used in F, you can @@ -9207,7 +9379,7 @@
fpp-depend
.
To run fpp-depend
, you pass it as input (1) files F that you want to
analyze
@@ -9279,7 +9451,7 @@
fpp-depend
computes dependencies transitively.
This means that if A depends on B and B
@@ -9338,7 +9510,7 @@
Suppose we construct the files locations.fpp
and a.fpp
, b.fpp
, and c.fpp
as described in the previous section, but then we temporarily remove b.fpp
.
@@ -9401,7 +9573,7 @@
Suppose file a.fpp
contains the
include specifier
@@ -9467,7 +9639,7 @@
As discussed
above, the standard output of fpp-depend
reports transitive dependencies.
@@ -9561,7 +9733,7 @@
Certain FPP constructs imply dependencies on parts of the F Prime framework that may not be available on all platforms. @@ -9597,7 +9769,7 @@
Given a collection of files F and their dependencies D, you can generate the locations of the definitions appearing in D and used in F. @@ -9674,7 +9846,7 @@
Because FPP associates locations with symbols, and the locations are path names, care is required when using path names that are @@ -9683,7 +9855,7 @@
A relative path is a path that does not start with a slash and is relative to the current directory path, which is @@ -9749,7 +9921,7 @@
The FPP analyzers assume that each symbol s has a unique path defining the location of the source file where @@ -9773,7 +9945,7 @@
The previous section explained how to specify an FPP model @@ -9785,7 +9957,7 @@
It is often useful to check a model for correctness, without doing any translation. @@ -9955,7 +10127,7 @@
We are phasing out the use of XML in favor of generating JSON and directly generating C++. @@ -10270,7 +10442,7 @@
This section describes how to generate C++ from FPP.
fpp-to-cpp
extracts constant definitions
from the source files F.
@@ -10484,7 +10656,7 @@
Constants defined inside components:
As noted in the section on
-defining components,
+defining components,
when you define a constant c
inside a component C
,
the name of the corresponding constant in the generated C++
code is C_c
.
@@ -10558,7 +10730,7 @@
fpp-to-cpp
also extracts topology definitions
from the source files.
@@ -10614,7 +10786,7 @@
C++ code generation for types, ports, and components works similarly to the corresponding code generation from XML. @@ -10624,7 +10796,7 @@
fpp-to-cpp
has options -t
and -u
for generating component "templates" or
partial implementations and for generating unit test code.
@@ -10728,7 +10900,7 @@
As discussed in the previous section, the -n
option
of fpp-to-xml
and fpp-to-cpp
lets you collect the names of
@@ -10742,7 +10914,7 @@
fpp-filenames
and using fpp-depend
.
Like fpp-check
, fpp-filenames
reads the files
provided as command-line arguments if there are any;
@@ -10844,7 +11016,7 @@
Alternatively, you can use
fpp-depend
@@ -10920,7 +11092,7 @@
The FPP tool suite provides a capability to translate F Prime XML files to FPP. @@ -11303,7 +11475,7 @@
The tool fpp-format
accepts FPP source files as input
and rewrites them as formatted output.
@@ -11377,7 +11549,7 @@
When FPP translates a topology T to XML, as discussed in the section on generating XML, @@ -11433,7 +11605,7 @@
A ground dictionary specifies all the commands, events, telemetry, parameters, and data products in a FSW @@ -11537,7 +11709,7 @@
FPP provides a tool called fpp-to-json
for converting FPP models to
JavaScript Object Notation (JSON) format.
@@ -11722,7 +11894,7 @@
When constructing an F Prime deployment in C++, there are generally @@ -11761,7 +11933,7 @@
Except for a few built-in types (see below), when translating to XML and then C++, an abstract type definition @@ -11939,7 +12111,25 @@
An external state machine refers to a state machine implementation +supplied outside the FPP model. +To implement an external state machine, you can use +the State Autocoding for +Real-Time Systems (STARS) +tool. +STARS provides several ways to specify state machines, and it +provides several C++ back ends. +The F Prime back end is designed to work with FPP code generation.
+For an example of an external state machine implemented in STARS,
+see FppTest/state_machine
in the F Prime repository.
At the highest level of an F Prime implementation, you write two units of C++ code:
@@ -11960,7 +12150,7 @@We describe each of these code units below.
As discussed in the section on generating C++ topology definitions, when you translate an FPP @@ -12142,7 +12332,7 @@
You must write a main function that performs application-specific and system-specific tasks such as parsing command-line arguments, @@ -12226,7 +12416,7 @@
The header file T TopologyAc.hpp
declares several public
symbols that you can use when writing your main function.