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 @@

21.4. Translation Tools

diff --git a/docs/fpp-users-guide.html b/docs/fpp-users-guide.html index 21a2df269..adece1686 100644 --- a/docs/fpp-users-guide.html +++ b/docs/fpp-users-guide.html @@ -518,192 +518,200 @@

The F Prime Prime (FPP) User’s Guide, State Machines, Phase 1

  • 8.7. Annotating a Port Definition
  • -
  • 9. Defining Components +
  • 9. Defining State Machines +
  • +
  • 10. Defining Components +
  • -
  • 10. Defining Component Instances +
  • 11. Defining Component Instances
  • -
  • 11. Defining Topologies +
  • 12. Defining Topologies
  • -
  • 12. Specifying Models as Files +
  • 13. Specifying Models as Files
  • -
  • 13. Analyzing and Translating Models +
  • 14. Analyzing and Translating Models
  • -
  • 14. Writing C Plus Plus Implementations +
  • 15. Writing C Plus Plus Implementations @@ -2736,7 +2744,7 @@

    6.3. Abstract Type Definitions

    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 @@

    8.7. Annotating a Port Defi

    -

    9. Defining Components

    +

    9. Defining State Machines

    +
    +
    +

    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:

    +
    +
    +
      +
    1. +

      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.

      +
    2. +
    3. +

      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.

      +
    4. +
    +
    +
    +

    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.

    +
    +
    +

    9.1. External State Machines

    +
    +

    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.

    +
    +
    +
    +

    9.2. Internal State Machines

    +
    +

    Support for internal state machines is in development. +It will be available in a future release of FPP.

    +
    +
    +
    +
    +
    +

    10. Defining Components

    In F Prime, the component is the basic unit of FSW function. @@ -3516,7 +3620,7 @@

    9. Defining Components

    message queue; it is like a non-threaded function library.

    -

    9.1. Component Definitions

    +

    10.1. Component Definitions

    An FPP component definition defines an F Prime component. To write a component definition, you write the following:

    @@ -3561,7 +3665,7 @@

    9.1. Component Definitions

    -

    9.2. Port Instances

    +

    10.2. Port Instances

    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 @@

    9.2. Port Instances

    (input or output).

    -

    9.2.1. Basic Port Instances

    +

    10.2.1. Basic Port Instances

    The simplest port instance specifies a kind, a name, and a type. The kind is one of the following:

    @@ -3686,7 +3790,7 @@

    9.2.1. Basic Po

    -

    9.2.2. Rules for Port Instances

    +

    10.2.2. Rules for Port Instances

    The port instances appearing in a component definition must satisfy certain rules. @@ -3722,8 +3826,11 @@

    9.2.2. Rule

    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.

    @@ -3766,7 +3873,7 @@

    9.2.2. Rule

    -

    9.2.3. Arrays of Port Instances

    +

    10.2.3. Arrays of Port Instances

    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 @@

    9.2.3. Arra

    -

    9.2.4. Priority

    +

    10.2.4. Priority

    For async input ports, you may specify a priority. The priority specification is not allowed for other kinds of ports. @@ -3851,7 +3958,7 @@

    9.2.4. Priority

    -

    9.2.5. Queue Full Behavior

    +

    10.2.5. Queue Full Behavior

    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 @@

    9.2.5. Queue Ful

    -

    9.2.6. Serial Port Instances

    +

    10.2.6. Serial Port Instances

    When writing a port instance, instead of specifying a named port type, you may write the keyword serial. @@ -3960,7 +4067,7 @@

    9.2.6. Serial

    -

    9.3. Special Port Instances

    +

    10.3. Special Port Instances

    A special port instance is a port instance that has a special behavior in F Prime. @@ -3976,7 +4083,7 @@

    9.3. Special Port Instances< and data products.

    -

    9.3.1. Command Ports

    +

    10.3.1. Command Ports

    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 @@

    9.3.1. Command

    -

    9.3.2. Event Ports

    +

    10.3.2. Event Ports

    An event is a report that something happened, for example, that a file was successfully uplinked. @@ -4179,7 +4286,7 @@

    9.3.2. Event Por

    -

    9.3.3. Telemetry Ports

    +

    10.3.3. Telemetry Ports

    Telemetry is data regarding the state of the system. A telemetry port allows a component to emit telemetry. @@ -4228,7 +4335,7 @@

    9.3.3. Telem

    -

    9.3.4. Parameter Ports

    +

    10.3.4. Parameter Ports

    A parameter is a configurable constant that may be updated from the ground. @@ -4313,7 +4420,7 @@

    9.3.4. Param

    -

    9.3.5. Time Get Ports

    +

    10.3.5. Time Get Ports

    A time get port allows a component to get the system time from a time component. @@ -4363,7 +4470,7 @@

    9.3.5. Time G

    -

    9.3.6. Data Product Ports

    +

    10.3.6. Data Product Ports

    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 @@

    9.3.6. Da

    -

    9.4. Internal Ports

    +

    10.4. Internal Ports

    An internal port is a port that a component can use to send a message to itself. @@ -4614,7 +4721,7 @@

    9.4. Internal Ports

    -

    9.5. Commands

    +

    10.5. Commands

    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 @@

    9.5. Commands

    Here we concentrate on how to specify commands in FPP.

    -

    9.5.1. Basic Commands

    +

    10.5.1. Basic Commands

    The simplest command consists of a kind followed by the keyword command and a name. @@ -4729,7 +4836,7 @@

    9.5.1. Basic Commands

    -

    9.5.2. Formal Parameters

    +

    10.5.2. Formal Parameters

    When specifying a command, you may specify one or more formal parameters. @@ -4788,7 +4895,7 @@

    9.5.2. Formal Parameters

    -

    9.5.3. Opcodes

    +

    10.5.3. Opcodes

    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 @@

    9.5.3. Opcodes

    -

    9.5.4. Priority and Queue Full Behavior

    +

    10.5.4. Priority and Queue Full Behavior

    When specifying an async command, you may specify priority and @@ -4952,7 +5059,7 @@

    9.5.4. Pr

    -

    9.6. Events

    +

    10.6. Events

    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 @@

    9.6. Events

    Here we concentrate on how to specify events in FPP.

    -

    9.6.1. Basic Events

    +

    10.6.1. Basic Events

    The simplest event consists of the keyword event, a name, a severity, and a format string. @@ -5055,7 +5162,7 @@

    9.6.1. Basic Events

    -

    9.6.2. Formal Parameters

    +

    10.6.2. Formal Parameters

    When specifying an event, you may specify one or more formal parameters. @@ -5133,7 +5240,7 @@

    9.6.2. Formal Parameters

    -

    9.6.3. Identifiers

    +

    10.6.3. Identifiers

    Every event in an F Prime FSW application has a unique numeric identifier. @@ -5204,7 +5311,7 @@

    9.6.3. Identifiers

    -

    9.6.4. Throttling

    +

    10.6.4. Throttling

    Sometimes it is necessary to throttle events, to ensure that they do not flood the system. @@ -5268,7 +5375,7 @@

    9.6.4. Throttling

    -

    9.7. Telemetry

    +

    10.7. Telemetry

    When defining an F Prime component, you may specify one or more telemetry channels. @@ -5288,7 +5395,7 @@

    9.7. Telemetry

    Here we concentrate on how to specify telemetry channels in FPP.

    -

    9.7.1. Basic Telemetry

    +

    10.7.1. Basic Telemetry

    The simplest telemetry channel consists of the keyword telemetry, a name, and a data type. @@ -5343,7 +5450,7 @@

    9.7.1. Basic Telemetry

    -

    9.7.2. Identifiers

    +

    10.7.2. Identifiers

    Every telemetry channel in an F Prime FSW application has a unique numeric identifier. @@ -5408,7 +5515,7 @@

    9.7.2. Identifiers

    -

    9.7.3. Update Frequency

    +

    10.7.3. Update Frequency

    You can specify how often the telemetry is emitted on a channel C. There are two possibilities:

    @@ -5489,7 +5596,7 @@

    9.7.3. Update Frequency<

    -

    9.7.4. Format Strings

    +

    10.7.4. Format Strings

    You may specify how a telemetry channel is formatted in the ground display. @@ -5541,7 +5648,7 @@

    9.7.4. Format Strings

    -

    9.7.5. Limits

    +

    10.7.5. Limits

    You may specify limits, or bounds, on the expected values carried on a telemetry channel. @@ -5628,7 +5735,7 @@

    9.7.5. Limits

    -

    9.8. Parameters

    +

    10.8. Parameters

    When defining an F Prime component, you may specify one or more parameters. @@ -5646,7 +5753,7 @@

    9.8. Parameters

    Here we concentrate on how to specify parameters in FPP.

    -

    9.8.1. Basic Parameters

    +

    10.8.1. Basic Parameters

    The simplest parameter consists of the keyword param, a name, and a data type. @@ -5721,7 +5828,7 @@

    9.8.1. Basic Parameters

    -

    9.8.2. Default Values

    +

    10.8.2. Default Values

    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 @@

    9.8.2. Default Values

    -

    9.8.3. Identifiers

    +

    10.8.3. Identifiers

    Every parameter in an F Prime FSW application has a unique numeric identifier. @@ -5858,7 +5965,7 @@

    9.8.3. Identifiers

    -

    9.8.4. Set and Save Opcodes

    +

    10.8.4. Set and Save Opcodes

    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 @@

    9.8.4. Set and Save

    -

    9.9. Data Products

    +

    10.9. Data Products

    When defining an F Prime component, you may specify the data products produced by that component. @@ -5975,7 +6082,7 @@

    9.9. Data Products

    data products documentation.

    -

    9.9.1. Basic Data Products

    +

    10.9.1. Basic Data Products

    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 @@

    9.9.1. Basic Data

    -

    9.9.2. Identifiers

    +

    10.9.2. Identifiers

    Every record in an F Prime FSW application has a unique numeric identifier. @@ -6110,7 +6217,7 @@

    9.9.2. Identifiers

    @ 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

    -

    9.9.3. Array Records

    +

    10.9.3. Array Records

    In the basic form of a record described above, each record that does not have @@ -6226,10 +6333,75 @@

    9.9.3. Array Records

    -

    9.10. Constants and Types

    +

    10.10. State Machine Instances

    +
    +

    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
    +
    +}
    +
    +
    +
    +
    +

    10.11. Constants, Types, Enums, and State Machines

    -

    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 @@

    9.10. Constants and Types

    -

    9.11. Include Specifiers

    +

    10.12. Include Specifiers

    Component definitions can become long, especially when there are many commands, events, telemetry channels, and parameters. @@ -6416,7 +6588,7 @@

    9.11. Include Specifiers

    -

    9.12. Matched Ports

    +

    10.13. Matched Ports

    Some F Prime components employ the following pattern:

    @@ -6510,7 +6682,7 @@

    9.12. Matched Ports

    -

    10. Defining Component Instances

    +

    11. Defining Component Instances

    As discussed in the previous section, in F Prime you @@ -6522,14 +6694,14 @@

    10. Defining Component Instances

    construct topologies.

    -

    10.1. Component Instance Definitions

    +

    11.1. Component Instance Definitions

    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.

    -

    10.1.1. Passive Components

    +

    11.1.1. Passive Components

    To instantiate a passive component, you write the following:

    @@ -6685,7 +6857,7 @@

    -

    10.1.2. Queued Components

    +

    11.1.2. Queued Components

    Instantiating a queued component is just like instantiating a passive component, except that you must also specify @@ -6744,7 +6916,7 @@

    -

    10.1.3. Active Components

    +

    11.1.3. Active Components

    Instantiating an active component is like instantiating a queued component, except that you may specify additional parameters @@ -6870,7 +7042,7 @@

    -

    10.2. Specifying the Implementation

    +

    11.2. Specifying the Implementation

    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 @@

    10.2. Specif

    -

    10.3. Init Specifiers

    +

    11.3. Init Specifiers

    In an F Prime FSW application, each component instance I has some associated C++ code @@ -7033,7 +7205,7 @@

    10.3. Init Specifiers

    and so FPP uses "init" as a shorthand name.)

    -

    10.3.1. Execution Phases

    +

    11.3.1. Execution Phases

    The FPP translator uses init specifiers when it generates code for an F Prime topology. @@ -7248,7 +7420,7 @@

    10.3.1. E

    -

    10.3.2. Writing Init Specifiers

    +

    11.3.2. Writing Init Specifiers

    You may write one or more init specifiers as part of a component instance definition. @@ -7379,7 +7551,7 @@

    10

    -

    11. Defining Topologies

    +

    12. Defining Topologies

    In F Prime, a topology or connection graph is the @@ -7400,7 +7572,7 @@

    11. Defining Topologies

    In this section we explain how to define a topology in FPP.

    -

    11.1. A Simple Example

    +

    12.1. A Simple Example

    We begin with a simple example that shows how many of the pieces fit together.

    @@ -7530,7 +7702,7 @@

    11.1. A Simple Example

    -

    11.2. Connection Graphs

    +

    12.2. Connection Graphs

    In general, an FPP topology consists of a list of instances and a set of named connection graphs. @@ -7538,7 +7710,7 @@

    11.2. Connection Graphs

    direct graph specifiers and pattern graph specifiers.

    -

    11.2.1. Direct Graph Specifiers

    +

    12.2.1. Direct Graph Specifiers

    A direct graph specifier provides a name and a list of connections. @@ -7659,7 +7831,7 @@

    11.2.1. D

    -

    11.2.2. Pattern Graph Specifiers

    +

    12.2.2. Pattern Graph Specifiers

    A few connection patterns are so common in F Prime that they get special treatment in FPP. @@ -7981,7 +8153,7 @@

    11.2.2.

    -

    11.3. Port Numbering

    +

    12.3. Port Numbering

    As discussed in the section on defining components, @@ -7994,7 +8166,7 @@

    11.3. Port Numbering

    explicit numbering, matched numbering, and general numbering.

    -

    11.3.1. Explicit Numbering

    +

    12.3.1. Explicit Numbering

    To use explicit numbering, you provide an explicit port number for a connection endpoint. @@ -8141,7 +8313,7 @@

    11.3.1. Explicit

    -

    11.3.2. Matched Numbering

    +

    12.3.2. Matched Numbering

    Automatic matching: After resolving @@ -8236,7 +8408,7 @@

    11.3.2. Matched Nu

    -

    11.3.3. General Numbering

    +

    12.3.3. General Numbering

    After resolving explicit numbering and @@ -8291,7 +8463,7 @@

    11.3.3. General Nu

    -

    11.4. Importing Topologies

    +

    12.4. Importing Topologies

    It is often useful to decompose a flight software project into several topologies. @@ -8327,7 +8499,7 @@

    11.4. Importing Topologies

    -

    11.4.1. Importing Instances and Connections

    +

    12.4.1. Importing Instances and Connections

    To import a topology A into a topology B, you write import A inside topology B, like this:

    @@ -8439,7 +8611,7 @@

    -

    11.4.2. Private Instances

    +

    12.4.2. Private Instances

    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 @@

    11.4.2. Priv

    -

    11.4.3. Multiple Imports

    +

    12.4.3. Multiple Imports

    Multiple imports are allowed. For example:

    @@ -8549,7 +8721,7 @@

    11.4.3. Multi

    -

    11.4.4. Transitive Imports

    +

    12.4.4. Transitive Imports

    In general, transitive imports are allowed. For example, topology A may import topology B, @@ -8566,7 +8738,7 @@

    11.4.4. Tra

    -

    11.5. Include Specifiers

    +

    12.5. Include Specifiers

    You can include code from another file in a topology definition. You do this by writing an include specifier. @@ -8578,7 +8750,7 @@

    11.5. Include Specifiers

    -

    12. Specifying Models as Files

    +

    13. Specifying Models as Files

    The previous sections have explained the syntactic and semantic elements @@ -8597,7 +8769,7 @@

    12. Specifying Models as Files

    the FPP wiki.

    -

    12.1. Dividing Models into Files

    +

    13.1. Dividing Models into Files

    Unlike F Prime XML, FPP does not require any particular division of model elements into files. @@ -8673,7 +8845,7 @@

    12.1. Dividing Mo

    -

    12.2. Include Specifiers

    +

    13.2. Include Specifiers

    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 @@

    12.2. Include Specifiers<

    -

    12.3. Dependencies

    +

    13.3. Dependencies

    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 @@

    12.3. Dependencies

    -

    12.4. Location Specifiers

    +

    13.4. Location Specifiers

    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 @@

    12.4. Location Specifier definitions.

    -

    12.4.1. Syntax

    +

    13.4.1. Syntax

    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 @@

    12.4.1. Syntax

    -

    12.4.2. Path Names

    +

    13.4.2. Path Names

    As with include specifiers, @@ -9010,7 +9182,7 @@

    12.4.2. Path

    -

    12.4.3. Definition Names

    +

    13.4.3. Definition Names

    The definition name appearing after the keyword locate may be a qualified name. @@ -9057,7 +9229,7 @@

    12.4.3.

    -

    12.4.4. Included Files

    +

    13.4.4. Included Files

    When you write a file that contains definitions and you include that file in another file, @@ -9072,7 +9244,7 @@

    12.4.4. I

    -

    12.5. Locating Definitions

    +

    13.5. Locating Definitions

    Given a collection of FPP source files F, you can generate location specifiers for all the definitions in F. @@ -9084,7 +9256,7 @@

    12.5. Locating Definiti specifiers to discover dependencies on individual files within Constants.

    -

    12.5.1. Running fpp-locate-defs

    +

    13.5.1. Running fpp-locate-defs

    To locate definitions, do the following:

    @@ -9121,7 +9293,7 @@

    -

    12.5.2. Location Paths

    +

    13.5.2. Location Paths

    By default, the location path is relative to the current directory. @@ -9143,7 +9315,7 @@

    12.5.2.

    -

    12.5.3. Included Definitions

    +

    13.5.3. Included Definitions

    Consider the case where you write a definition in one file and include that file in another file via an @@ -9199,7 +9371,7 @@

    12

    -

    12.6. Computing Dependencies

    +

    13.6. Computing Dependencies

    Given files F and location specifiers L that locate the definitions used in F, you can @@ -9207,7 +9379,7 @@

    12.6. Computing Depen The tool for doing this is called fpp-depend.

    -

    12.6.1. Running fpp-depend

    +

    13.6.1. Running fpp-depend

    To run fpp-depend, you pass it as input (1) files F that you want to analyze @@ -9279,7 +9451,7 @@

    12

    -

    12.6.2. Transitive Dependencies

    +

    13.6.2. Transitive Dependencies

    fpp-depend computes dependencies transitively. This means that if A depends on B and B @@ -9338,7 +9510,7 @@

    -

    12.6.3. Missing Dependencies

    +

    13.6.3. Missing Dependencies

    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 @@

    -

    12.6.4. Included Files

    +

    13.6.4. Included Files

    Suppose file a.fpp contains the include specifier @@ -9467,7 +9639,7 @@

    12.6.4

    -

    12.6.5. Dependencies Between Build Modules

    +

    13.6.5. Dependencies Between Build Modules

    As discussed above, the standard output of fpp-depend reports transitive dependencies. @@ -9561,7 +9733,7 @@

    -

    12.6.6. Framework Dependencies

    +

    13.6.6. Framework Dependencies

    Certain FPP constructs imply dependencies on parts of the F Prime framework that may not be available on all platforms. @@ -9597,7 +9769,7 @@

    -

    12.7. Locating Uses

    +

    13.7. Locating Uses

    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 @@

    12.7. Locating Uses

    -

    12.8. Path Name Aliases

    +

    13.8. Path Name Aliases

    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 @@

    12.8. Path Name Aliases

    - +

    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 @@

    -

    12.8.2. Unique Locations

    +

    13.8.2. Unique Locations

    The FPP analyzers assume that each symbol s has a unique path defining the location of the source file where @@ -9773,7 +9945,7 @@

    12.8.2. U

    -

    13. Analyzing and Translating Models

    +

    14. Analyzing and Translating Models

    The previous section explained how to specify an FPP model @@ -9785,7 +9957,7 @@

    13. Analyzing and Translating Models

    -

    13.1. Checking Models

    +

    14.1. Checking Models

    It is often useful to check a model for correctness, without doing any translation. @@ -9955,7 +10127,7 @@

    13.1. Checking Models<

    -

    13.2. Generating XML

    +

    14.2. Generating XML

    We are phasing out the use of XML in favor of generating JSON and directly generating C++. @@ -10270,7 +10442,7 @@

    13.2. Generating XML

    -

    13.3. Generating C Plus Plus

    +

    14.3. Generating C Plus Plus

    This section describes how to generate C++ from FPP.

    @@ -10401,7 +10573,7 @@

    13.3. Generatin either through named files or through standard input.

    -

    13.3.1. Constant Definitions

    +

    14.3.1. Constant Definitions

    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 @@

    -

    13.3.2. Topology Definitions

    +

    14.3.2. Topology Definitions

    fpp-to-cpp also extracts topology definitions from the source files. @@ -10614,7 +10786,7 @@

    -

    13.3.3. Types, Ports, and Components

    +

    14.3.3. Types, Ports, and Components

    C++ code generation for types, ports, and components works similarly to the corresponding code generation from XML. @@ -10624,7 +10796,7 @@

    -

    13.3.4. Component Implementation and Unit Test Code

    +

    14.3.4. Component Implementation and Unit Test Code

    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 @@

    -

    13.4. Identifying Generated Files

    +

    14.4. Identifying Generated Files

    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 @@

    13.4. Iden using fpp-filenames and using fpp-depend.

    -

    13.4.1. Using fpp-filenames

    +

    14.4.1. Using fpp-filenames

    Like fpp-check, fpp-filenames reads the files provided as command-line arguments if there are any; @@ -10844,7 +11016,7 @@

    -

    13.4.2. Using fpp-depend

    +

    14.4.2. Using fpp-depend

    Alternatively, you can use fpp-depend @@ -10920,7 +11092,7 @@

    -

    13.5. Translating XML to FPP

    +

    14.5. Translating XML to FPP

    The FPP tool suite provides a capability to translate F Prime XML files to FPP. @@ -11303,7 +11475,7 @@

    13.5. Translati

    -

    13.6. Formatting FPP Source

    +

    14.6. Formatting FPP Source

    The tool fpp-format accepts FPP source files as input and rewrites them as formatted output. @@ -11377,7 +11549,7 @@

    13.6. Formatting

    -

    13.7. Visualizing Topologies

    +

    14.7. Visualizing Topologies

    When FPP translates a topology T to XML, as discussed in the section on generating XML, @@ -11433,7 +11605,7 @@

    13.7. Visualizi

    -

    13.8. Generating Ground Dictionaries

    +

    14.8. Generating Ground Dictionaries

    A ground dictionary specifies all the commands, events, telemetry, parameters, and data products in a FSW @@ -11537,7 +11709,7 @@

    13.8. G

    -

    13.9. Generating JSON Models

    +

    14.9. Generating JSON Models

    FPP provides a tool called fpp-to-json for converting FPP models to JavaScript Object Notation (JSON) format. @@ -11722,7 +11894,7 @@

    13.9. Generatin

    -

    14. Writing C Plus Plus Implementations

    +

    15. Writing C Plus Plus Implementations

    When constructing an F Prime deployment in C++, there are generally @@ -11761,7 +11933,7 @@

    14. Writing C Plus Plus Implementat and implementing deployments.

    -

    14.1. Implementing Abstract Types

    +

    15.1. Implementing Abstract Types

    Except for a few built-in types (see below), when translating to XML and then C++, an abstract type definition @@ -11939,7 +12111,25 @@

    14.1. I

    -

    14.2. Implementing Deployments

    +

    15.2. Implementing External State Machines

    +
    +

    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.

    +
    +
    +
    +

    15.3. Implementing Deployments

    At the highest level of an F Prime implementation, you write two units of C++ code:

    @@ -11960,7 +12150,7 @@

    14.2. Impl

    We describe each of these code units below.

    -

    14.2.1. Application-Specific Definitions

    +

    15.3.1. Application-Specific Definitions

    As discussed in the section on generating C++ topology definitions, when you translate an FPP @@ -12142,7 +12332,7 @@

    -

    14.2.2. The Main Function

    +

    15.3.2. The Main Function

    You must write a main function that performs application-specific and system-specific tasks such as parsing command-line arguments, @@ -12226,7 +12416,7 @@

    -

    14.2.3. Public Symbols

    +

    15.3.3. Public Symbols

    The header file T TopologyAc.hpp declares several public symbols that you can use when writing your main function.

    @@ -12293,7 +12483,7 @@

    diff --git a/docs/index.html b/docs/index.html index 5d3dd6e90..07e30b8d1 100644 --- a/docs/index.html +++ b/docs/index.html @@ -463,7 +463,7 @@

    F Prime Prime (FPP)

    diff --git a/docs/users-guide/Analyzing-and-Translating-Models.adoc b/docs/users-guide/Analyzing-and-Translating-Models.adoc index 67a952073..f03644854 100644 --- a/docs/users-guide/Analyzing-and-Translating-Models.adoc +++ b/docs/users-guide/Analyzing-and-Translating-Models.adoc @@ -490,7 +490,8 @@ Notice how the FPP annotations are translated to comments. *Constants defined inside components:* As noted in the section on -<>, +<>, when you define a constant `c` inside a component `C`, the name of the corresponding constant in the generated {cpp} code is `C_c`. diff --git a/docs/users-guide/Defining-Components.adoc b/docs/users-guide/Defining-Components.adoc index c5fc0916a..738daca19 100644 --- a/docs/users-guide/Defining-Components.adoc +++ b/docs/users-guide/Defining-Components.adoc @@ -189,8 +189,11 @@ Try presenting this code to `fpp-check` and observe what happens. 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. @@ -2295,7 +2298,7 @@ Here is an example: @ 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 { # ---------------------------------------------------------------------- @@ -2404,10 +2407,70 @@ an array of elements of type `Data`. The number of elements is unspecified in the model; it is provided when the record is serialized into a container. -=== Constants and Types +=== State Machine Instances -You can write a <> -or <> +A *state machine instance* is a component member that instantiates +an FPP <>. +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: + +[source,fpp] +---- +@ 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 <>, +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: + +[source,fpp] +---- +@ 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 + +} +---- + +=== Constants, Types, Enums, and State Machines + +You can write a <>, +<>, +<>, +or +<> as a component member. When you do this, the component qualifies the name of the constant or type, similarly to the way that a diff --git a/docs/users-guide/Defining-State-Machines.adoc b/docs/users-guide/Defining-State-Machines.adoc new file mode 100644 index 000000000..1572b9d9e --- /dev/null +++ b/docs/users-guide/Defining-State-Machines.adoc @@ -0,0 +1,70 @@ +== Defining State Machines + +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 <>: +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 +<> +or +<>: +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 +<>. +A state machine definition is an +<>. + +=== External State Machines + +To define an external state machine, you write the keywords +`state` `machine` followed by an identifier, which is the +name of the state machine: + +[source,fpp] +---- +state machine M +---- + +This code defines an external state machine with name `M`. +You can then +<> +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 <>. +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. + +=== Internal State Machines + +Support for internal state machines is in development. +It will be available in a future release of FPP. diff --git a/docs/users-guide/Defining-Types.adoc b/docs/users-guide/Defining-Types.adoc index e7402f7c0..f51ba1f3e 100644 --- a/docs/users-guide/Defining-Types.adoc +++ b/docs/users-guide/Defining-Types.adoc @@ -642,7 +642,7 @@ In particular, when the target language is {cpp}, the default value is the zero-argument constructor `T()`. *Built-in types:* -When translating to XML, there are a few special types that are abstract +When translating FPP to {cpp}, 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 {cpp} classes for these types. We will discuss these types further in the section on diff --git a/docs/users-guide/Writing-C-Plus-Plus-Implementations.adoc b/docs/users-guide/Writing-C-Plus-Plus-Implementations.adoc index 76a02f1da..8ff85c199 100644 --- a/docs/users-guide/Writing-C-Plus-Plus-Implementations.adoc +++ b/docs/users-guide/Writing-C-Plus-Plus-Implementations.adoc @@ -174,6 +174,22 @@ in the FPP model; for a typical F Prime project, these definitions are located at `config/FpConfig.fpp`. You don't have to define header files for these types. +=== Implementing External State Machines + +An <> refers to a state machine implementation +supplied outside the FPP model. +To implement an external state machine, you can use +the https://github.com/JPLOpenSource/STARS/tree/main[State Autocoding for +Real-Time Systems (STARS)] +tool. +STARS provides several ways to specify state machines, and it +provides several {cpp} 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. + === Implementing Deployments At the highest level of an F Prime implementation, you write diff --git a/docs/users-guide/defs.sh b/docs/users-guide/defs.sh index 37d64246c..74c717d7a 100644 --- a/docs/users-guide/defs.sh +++ b/docs/users-guide/defs.sh @@ -18,6 +18,7 @@ Defining-Modules.adoc Defining-Types.adoc Defining-Enums.adoc Defining-Ports.adoc +Defining-State-Machines.adoc Defining-Components.adoc Defining-Component-Instances.adoc Defining-Topologies.adoc