mirror of
https://github.com/nasa/fpp.git
synced 2025-12-11 03:05:32 -06:00
15821 lines
582 KiB
HTML
15821 lines
582 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<meta name="generator" content="Asciidoctor 2.0.23">
|
|
<title>The F Prime Prime (FPP) User’s Guide, Unreleased, after v3.0.0</title>
|
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700">
|
|
<style>
|
|
/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */
|
|
/* Uncomment the following line when using as a custom stylesheet */
|
|
/* @import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700"; */
|
|
html{font-family:sans-serif;-webkit-text-size-adjust:100%}
|
|
a{background:none}
|
|
a:focus{outline:thin dotted}
|
|
a:active,a:hover{outline:0}
|
|
h1{font-size:2em;margin:.67em 0}
|
|
b,strong{font-weight:bold}
|
|
abbr{font-size:.9em}
|
|
abbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}
|
|
dfn{font-style:italic}
|
|
hr{height:0}
|
|
mark{background:#ff0;color:#000}
|
|
code,kbd,pre,samp{font-family:monospace;font-size:1em}
|
|
pre{white-space:pre-wrap}
|
|
q{quotes:"\201C" "\201D" "\2018" "\2019"}
|
|
small{font-size:80%}
|
|
sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
|
|
sup{top:-.5em}
|
|
sub{bottom:-.25em}
|
|
img{border:0}
|
|
svg:not(:root){overflow:hidden}
|
|
figure{margin:0}
|
|
audio,video{display:inline-block}
|
|
audio:not([controls]){display:none;height:0}
|
|
fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
|
|
legend{border:0;padding:0}
|
|
button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
|
|
button,input{line-height:normal}
|
|
button,select{text-transform:none}
|
|
button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}
|
|
button[disabled],html input[disabled]{cursor:default}
|
|
input[type=checkbox],input[type=radio]{padding:0}
|
|
button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
|
|
textarea{overflow:auto;vertical-align:top}
|
|
table{border-collapse:collapse;border-spacing:0}
|
|
*,::before,::after{box-sizing:border-box}
|
|
html,body{font-size:100%}
|
|
body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}
|
|
a:hover{cursor:pointer}
|
|
img,object,embed{max-width:100%;height:auto}
|
|
object,embed{height:100%}
|
|
img{-ms-interpolation-mode:bicubic}
|
|
.left{float:left!important}
|
|
.right{float:right!important}
|
|
.text-left{text-align:left!important}
|
|
.text-right{text-align:right!important}
|
|
.text-center{text-align:center!important}
|
|
.text-justify{text-align:justify!important}
|
|
.hide{display:none}
|
|
img,object,svg{display:inline-block;vertical-align:middle}
|
|
textarea{height:auto;min-height:50px}
|
|
select{width:100%}
|
|
.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
|
|
div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}
|
|
a{color:#2156a5;text-decoration:underline;line-height:inherit}
|
|
a:hover,a:focus{color:#1d4b8f}
|
|
a img{border:0}
|
|
p{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
|
|
p aside{font-size:.875em;line-height:1.35;font-style:italic}
|
|
h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
|
|
h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
|
|
h1{font-size:2.125em}
|
|
h2{font-size:1.6875em}
|
|
h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}
|
|
h4,h5{font-size:1.125em}
|
|
h6{font-size:1em}
|
|
hr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}
|
|
em,i{font-style:italic;line-height:inherit}
|
|
strong,b{font-weight:bold;line-height:inherit}
|
|
small{font-size:60%;line-height:inherit}
|
|
code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)}
|
|
ul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
|
|
ul,ol{margin-left:1.5em}
|
|
ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}
|
|
ul.circle{list-style-type:circle}
|
|
ul.disc{list-style-type:disc}
|
|
ul.square{list-style-type:square}
|
|
ul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}
|
|
ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
|
|
dl dt{margin-bottom:.3125em;font-weight:bold}
|
|
dl dd{margin-bottom:1.25em}
|
|
blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
|
|
blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
|
|
@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}
|
|
h1{font-size:2.75em}
|
|
h2{font-size:2.3125em}
|
|
h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}
|
|
h4{font-size:1.4375em}}
|
|
table{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}
|
|
table thead,table tfoot{background:#f7f8f7}
|
|
table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
|
|
table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
|
|
table tr.even,table tr.alt{background:#f8f8f7}
|
|
table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}
|
|
h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
|
|
h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
|
|
.center{margin-left:auto;margin-right:auto}
|
|
.stretch{width:100%}
|
|
.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:" ";display:table}
|
|
.clearfix::after,.float-group::after{clear:both}
|
|
:not(pre).nobreak{word-wrap:normal}
|
|
:not(pre).nowrap{white-space:nowrap}
|
|
:not(pre).pre-wrap{white-space:pre-wrap}
|
|
:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}
|
|
pre{color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;line-height:1.45;text-rendering:optimizeSpeed}
|
|
pre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}
|
|
pre>code{display:block}
|
|
pre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}
|
|
em em{font-style:normal}
|
|
strong strong{font-weight:400}
|
|
.keyseq{color:rgba(51,51,51,.8)}
|
|
kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
|
|
.keyseq kbd:first-child{margin-left:0}
|
|
.keyseq kbd:last-child{margin-right:0}
|
|
.menuseq,.menuref{color:#000}
|
|
.menuseq b:not(.caret),.menuref{font-weight:inherit}
|
|
.menuseq{word-spacing:-.02em}
|
|
.menuseq b.caret{font-size:1.25em;line-height:.8}
|
|
.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}
|
|
b.button::before,b.button::after{position:relative;top:-1px;font-weight:400}
|
|
b.button::before{content:"[";padding:0 3px 0 2px}
|
|
b.button::after{content:"]";padding:0 2px 0 3px}
|
|
p a>code:hover{color:rgba(0,0,0,.9)}
|
|
#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
|
|
#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:" ";display:table}
|
|
#header::after,#content::after,#footnotes::after,#footer::after{clear:both}
|
|
#content{margin-top:1.25em}
|
|
#content::before{content:none}
|
|
#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
|
|
#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}
|
|
#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}
|
|
#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}
|
|
#header .details span:first-child{margin-left:-.125em}
|
|
#header .details span.email a{color:rgba(0,0,0,.85)}
|
|
#header .details br{display:none}
|
|
#header .details br+span::before{content:"\00a0\2013\00a0"}
|
|
#header .details br+span.author::before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)}
|
|
#header .details br+span#revremark::before{content:"\00a0|\00a0"}
|
|
#header #revnumber{text-transform:capitalize}
|
|
#header #revnumber::after{content:"\00a0"}
|
|
#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
|
|
#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}
|
|
#toc>ul{margin-left:.125em}
|
|
#toc ul.sectlevel0>li>a{font-style:italic}
|
|
#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
|
|
#toc ul{font-family:"Open Sans","DejaVu Sans",sans-serif;list-style-type:none}
|
|
#toc li{line-height:1.3334;margin-top:.3334em}
|
|
#toc a{text-decoration:none}
|
|
#toc a:active{text-decoration:underline}
|
|
#toctitle{color:#7a2518;font-size:1.2em}
|
|
@media screen and (min-width:768px){#toctitle{font-size:1.375em}
|
|
body.toc2{padding-left:15em;padding-right:0}
|
|
body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}
|
|
#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
|
|
#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
|
|
#toc.toc2>ul{font-size:.9em;margin-bottom:0}
|
|
#toc.toc2 ul ul{margin-left:0;padding-left:1em}
|
|
#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
|
|
body.toc2.toc-right{padding-left:0;padding-right:15em}
|
|
body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}
|
|
@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
|
|
#toc.toc2{width:20em}
|
|
#toc.toc2 #toctitle{font-size:1.375em}
|
|
#toc.toc2>ul{font-size:.95em}
|
|
#toc.toc2 ul ul{padding-left:1.25em}
|
|
body.toc2.toc-right{padding-left:0;padding-right:20em}}
|
|
#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}
|
|
#content #toc>:first-child{margin-top:0}
|
|
#content #toc>:last-child{margin-bottom:0}
|
|
#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}
|
|
#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}
|
|
#content{margin-bottom:.625em}
|
|
.sect1{padding-bottom:.625em}
|
|
@media screen and (min-width:768px){#content{margin-bottom:1.25em}
|
|
.sect1{padding-bottom:1.25em}}
|
|
.sect1:last-child{padding-bottom:0}
|
|
.sect1+.sect1{border-top:1px solid #e7e7e9}
|
|
#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
|
|
#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em}
|
|
#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}
|
|
#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}
|
|
#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}
|
|
details,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
|
|
details{margin-left:1.25rem}
|
|
details>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}
|
|
details>summary::-webkit-details-marker{display:none}
|
|
details>summary::before{content:"";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}
|
|
details[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}
|
|
details>summary::after{content:"";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}
|
|
.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:"Noto Serif","DejaVu Serif",serif;font-size:1rem;font-style:italic}
|
|
table.tableblock.fit-content>caption.title{white-space:nowrap;width:0}
|
|
.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}
|
|
.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}
|
|
.admonitionblock>table td.icon{text-align:center;width:80px}
|
|
.admonitionblock>table td.icon img{max-width:none}
|
|
.admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase}
|
|
.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}
|
|
.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}
|
|
.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}
|
|
.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}
|
|
.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}
|
|
.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}
|
|
.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}
|
|
.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}
|
|
@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}
|
|
@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}
|
|
.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^="highlight "]{background:#f7f7f8}
|
|
.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}
|
|
.listingblock>.content{position:relative}
|
|
.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}
|
|
.listingblock:hover code[data-lang]::before{display:block}
|
|
.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}
|
|
.listingblock.terminal pre .command:not([data-prompt])::before{content:"$"}
|
|
.listingblock pre.highlightjs{padding:0}
|
|
.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}
|
|
.listingblock pre.prettyprint{border-width:0}
|
|
.prettyprint{background:#f7f7f8}
|
|
pre.prettyprint .linenums{line-height:1.45;margin-left:2em}
|
|
pre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}
|
|
pre.prettyprint li code[data-lang]::before{opacity:1}
|
|
pre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}
|
|
table.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}
|
|
table.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}
|
|
table.linenotable td.code{padding-left:.75em}
|
|
table.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
|
|
pre.pygments span.linenos{display:inline-block;margin-right:.75em}
|
|
.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
|
|
.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}
|
|
.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
|
|
.quoteblock blockquote{margin:0;padding:0;border:0}
|
|
.quoteblock blockquote::before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
|
|
.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}
|
|
.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}
|
|
.verseblock{margin:0 1em 1.25em}
|
|
.verseblock pre{font-family:"Open Sans","DejaVu Sans",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
|
|
.verseblock pre strong{font-weight:400}
|
|
.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
|
|
.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
|
|
.quoteblock .attribution br,.verseblock .attribution br{display:none}
|
|
.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
|
|
.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}
|
|
.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}
|
|
.quoteblock.abstract{margin:0 1em 1.25em;display:block}
|
|
.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}
|
|
.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}
|
|
.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}
|
|
.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}
|
|
.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}
|
|
p.tableblock:last-child{margin-bottom:0}
|
|
td.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}
|
|
td.tableblock>.content>:last-child{margin-bottom:-1.25em}
|
|
table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
|
|
table.grid-all>*>tr>*{border-width:1px}
|
|
table.grid-cols>*>tr>*{border-width:0 1px}
|
|
table.grid-rows>*>tr>*{border-width:1px 0}
|
|
table.frame-all{border-width:1px}
|
|
table.frame-ends{border-width:1px 0}
|
|
table.frame-sides{border-width:0 1px}
|
|
table.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}
|
|
table.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}
|
|
table.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}
|
|
table.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}
|
|
table.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}
|
|
th.halign-left,td.halign-left{text-align:left}
|
|
th.halign-right,td.halign-right{text-align:right}
|
|
th.halign-center,td.halign-center{text-align:center}
|
|
th.valign-top,td.valign-top{vertical-align:top}
|
|
th.valign-bottom,td.valign-bottom{vertical-align:bottom}
|
|
th.valign-middle,td.valign-middle{vertical-align:middle}
|
|
table thead th,table tfoot th{font-weight:bold}
|
|
tbody tr th{background:#f7f8f7}
|
|
tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
|
|
p.tableblock>code:only-child{background:none;padding:0}
|
|
p.tableblock{font-size:1em}
|
|
ol{margin-left:1.75em}
|
|
ul li ol{margin-left:1.5em}
|
|
dl dd{margin-left:1.125em}
|
|
dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}
|
|
li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
|
|
ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}
|
|
ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}
|
|
ul.unstyled,ol.unstyled{margin-left:0}
|
|
li>p:empty:only-child::before{content:"";display:inline-block}
|
|
ul.checklist>li>p:first-child{margin-left:-1em}
|
|
ul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}
|
|
ul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}
|
|
ul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}
|
|
ul.inline>li{margin-left:1.25em}
|
|
.unstyled dl dt{font-weight:400;font-style:normal}
|
|
ol.arabic{list-style-type:decimal}
|
|
ol.decimal{list-style-type:decimal-leading-zero}
|
|
ol.loweralpha{list-style-type:lower-alpha}
|
|
ol.upperalpha{list-style-type:upper-alpha}
|
|
ol.lowerroman{list-style-type:lower-roman}
|
|
ol.upperroman{list-style-type:upper-roman}
|
|
ol.lowergreek{list-style-type:lower-greek}
|
|
.hdlist>table,.colist>table{border:0;background:none}
|
|
.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}
|
|
td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
|
|
td.hdlist1{font-weight:bold;padding-bottom:1.25em}
|
|
td.hdlist2{word-wrap:anywhere}
|
|
.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
|
|
.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}
|
|
.colist td:not([class]):first-child img{max-width:none}
|
|
.colist td:not([class]):last-child{padding:.25em 0}
|
|
.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}
|
|
.imageblock.left{margin:.25em .625em 1.25em 0}
|
|
.imageblock.right{margin:.25em 0 1.25em .625em}
|
|
.imageblock>.title{margin-bottom:0}
|
|
.imageblock.thumb,.imageblock.th{border-width:6px}
|
|
.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}
|
|
.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
|
|
.image.left{margin-right:.625em}
|
|
.image.right{margin-left:.625em}
|
|
a.image{text-decoration:none;display:inline-block}
|
|
a.image object{pointer-events:none}
|
|
sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
|
|
sup.footnote a,sup.footnoteref a{text-decoration:none}
|
|
sup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}
|
|
#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
|
|
#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}
|
|
#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}
|
|
#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}
|
|
#footnotes .footnote:last-of-type{margin-bottom:0}
|
|
#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
|
|
div.unbreakable{page-break-inside:avoid}
|
|
.big{font-size:larger}
|
|
.small{font-size:smaller}
|
|
.underline{text-decoration:underline}
|
|
.overline{text-decoration:overline}
|
|
.line-through{text-decoration:line-through}
|
|
.aqua{color:#00bfbf}
|
|
.aqua-background{background:#00fafa}
|
|
.black{color:#000}
|
|
.black-background{background:#000}
|
|
.blue{color:#0000bf}
|
|
.blue-background{background:#0000fa}
|
|
.fuchsia{color:#bf00bf}
|
|
.fuchsia-background{background:#fa00fa}
|
|
.gray{color:#606060}
|
|
.gray-background{background:#7d7d7d}
|
|
.green{color:#006000}
|
|
.green-background{background:#007d00}
|
|
.lime{color:#00bf00}
|
|
.lime-background{background:#00fa00}
|
|
.maroon{color:#600000}
|
|
.maroon-background{background:#7d0000}
|
|
.navy{color:#000060}
|
|
.navy-background{background:#00007d}
|
|
.olive{color:#606000}
|
|
.olive-background{background:#7d7d00}
|
|
.purple{color:#600060}
|
|
.purple-background{background:#7d007d}
|
|
.red{color:#bf0000}
|
|
.red-background{background:#fa0000}
|
|
.silver{color:#909090}
|
|
.silver-background{background:#bcbcbc}
|
|
.teal{color:#006060}
|
|
.teal-background{background:#007d7d}
|
|
.white{color:#bfbfbf}
|
|
.white-background{background:#fafafa}
|
|
.yellow{color:#bfbf00}
|
|
.yellow-background{background:#fafa00}
|
|
span.icon>.fa{cursor:default}
|
|
a span.icon>.fa{cursor:inherit}
|
|
.admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
|
|
.admonitionblock td.icon .icon-note::before{content:"\f05a";color:#19407c}
|
|
.admonitionblock td.icon .icon-tip::before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
|
|
.admonitionblock td.icon .icon-warning::before{content:"\f071";color:#bf6900}
|
|
.admonitionblock td.icon .icon-caution::before{content:"\f06d";color:#bf3400}
|
|
.admonitionblock td.icon .icon-important::before{content:"\f06a";color:#bf0000}
|
|
.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold}
|
|
.conum[data-value] *{color:#fff!important}
|
|
.conum[data-value]+b{display:none}
|
|
.conum[data-value]::after{content:attr(data-value)}
|
|
pre .conum[data-value]{position:relative;top:-.125em}
|
|
b.conum *{color:inherit!important}
|
|
.conum:not([data-value]):empty{display:none}
|
|
dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
|
|
h1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}
|
|
p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
|
|
p,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}
|
|
p{margin-bottom:1.25rem}
|
|
.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
|
|
.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}
|
|
.print-only{display:none!important}
|
|
@page{margin:1.25cm .75cm}
|
|
@media print{*{box-shadow:none!important;text-shadow:none!important}
|
|
html{font-size:80%}
|
|
a{color:inherit!important;text-decoration:underline!important}
|
|
a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important}
|
|
a[href^="http:"]:not(.bare)::after,a[href^="https:"]:not(.bare)::after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em}
|
|
abbr[title]{border-bottom:1px dotted}
|
|
abbr[title]::after{content:" (" attr(title) ")"}
|
|
pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
|
|
thead{display:table-header-group}
|
|
svg{max-width:100%}
|
|
p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
|
|
h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}
|
|
#header,#content,#footnotes,#footer{max-width:none}
|
|
#toc,.sidebarblock,.exampleblock>.content{background:none!important}
|
|
#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}
|
|
body.book #header{text-align:center}
|
|
body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}
|
|
body.book #header .details{border:0!important;display:block;padding:0!important}
|
|
body.book #header .details span:first-child{margin-left:0!important}
|
|
body.book #header .details br{display:block}
|
|
body.book #header .details br+span::before{content:none!important}
|
|
body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
|
|
body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}
|
|
.listingblock code[data-lang]::before{display:block}
|
|
#footer{padding:0 .9375em}
|
|
.hide-on-print{display:none!important}
|
|
.print-only{display:block!important}
|
|
.hide-for-print{display:none!important}
|
|
.show-for-print{display:inherit!important}}
|
|
@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}
|
|
.sect1{padding:0!important}
|
|
.sect1+.sect1{border:0}
|
|
#footer{background:none}
|
|
#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}
|
|
@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}
|
|
</style>
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prettify/r298/prettify.min.css">
|
|
</head>
|
|
<body class="article toc2 toc-left">
|
|
<div id="header">
|
|
<h1>The F Prime Prime (FPP) User’s Guide, Unreleased, after v3.0.0</h1>
|
|
<div id="toc" class="toc2">
|
|
<div id="toctitle">Table of Contents</div>
|
|
<ul class="sectlevel1">
|
|
<li><a href="#Introduction">1. Introduction</a></li>
|
|
<li><a href="#Installing-FPP">2. Installing FPP</a></li>
|
|
<li><a href="#Defining-Constants">3. Defining Constants</a>
|
|
<ul class="sectlevel2">
|
|
<li><a href="#Defining-Constants_Writing-a-Constant-Definition">3.1. Writing a Constant Definition</a></li>
|
|
<li><a href="#Defining-Constants_Names">3.2. Names</a>
|
|
<ul class="sectlevel3">
|
|
<li><a href="#Defining-Constants_Names_Reserved-Words">3.2.1. Reserved Words</a></li>
|
|
<li><a href="#Defining-Constants_Names_Name-Clashes">3.2.2. Name Clashes</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#Defining-Constants_Expressions">3.3. Expressions</a>
|
|
<ul class="sectlevel3">
|
|
<li><a href="#Defining-Constants_Expressions_Primitive-Values">3.3.1. Primitive Values</a></li>
|
|
<li><a href="#Defining-Constants_Expressions_String-Values">3.3.2. String Values</a></li>
|
|
<li><a href="#Defining-Constants_Expressions_Array-Values">3.3.3. Array Values</a></li>
|
|
<li><a href="#Defining-Constants_Expressions_Array-Elements">3.3.4. Array Elements</a></li>
|
|
<li><a href="#Defining-Constants_Expressions_Struct-Values">3.3.5. Struct Values</a></li>
|
|
<li><a href="#Defining-Constants_Expressions_Struct-Members">3.3.6. Struct Members</a></li>
|
|
<li><a href="#Defining-Constants_Expressions_Name-Expressions">3.3.7. Name Expressions</a></li>
|
|
<li><a href="#Defining-Constants_Expressions_Value-Arithmetic-Expressions">3.3.8. Value Arithmetic Expressions</a></li>
|
|
<li><a href="#Defining-Constants_Expressions_Compound-Expressions">3.3.9. Compound Expressions</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#Defining-Constants_Multiple-Definitions-and-Element-Sequences">3.4. Multiple Definitions and Element Sequences</a></li>
|
|
<li><a href="#Defining-Constants_Multiline-Definitions">3.5. Multiline Definitions</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#Writing-Comments-and-Annotations">4. Writing Comments and Annotations</a>
|
|
<ul class="sectlevel2">
|
|
<li><a href="#Writing-Comments-and-Annotations_Comments">4.1. Comments</a></li>
|
|
<li><a href="#Writing-Comments-and-Annotations_Annotations">4.2. Annotations</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#Defining-Modules">5. Defining Modules</a></li>
|
|
<li><a href="#Defining-Types">6. Defining Types</a>
|
|
<ul class="sectlevel2">
|
|
<li><a href="#Defining-Types_Array-Type-Definitions">6.1. Array Type Definitions</a>
|
|
<ul class="sectlevel3">
|
|
<li><a href="#Defining-Types_Array-Type-Definitions_Writing-an-Array-Type-Definition">6.1.1. Writing an Array Type Definition</a></li>
|
|
<li><a href="#Defining-Types_Array-Type-Definitions_Type-Names">6.1.2. Type Names</a></li>
|
|
<li><a href="#Defining-Types_Array-Type-Definitions_Default-Values">6.1.3. Default Values</a></li>
|
|
<li><a href="#Defining-Types_Array-Type-Definitions_Format-Strings">6.1.4. Format Strings</a></li>
|
|
<li><a href="#Defining-Types_Array-Type-Definitions_Arrays-of-Arrays">6.1.5. Arrays of Arrays</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#Defining-Types_Struct-Type-Definitions">6.2. Struct Type Definitions</a>
|
|
<ul class="sectlevel3">
|
|
<li><a href="#Defining-Types_Struct-Type-Definitions_Writing-a-Struct-Type-Definition">6.2.1. Writing a Struct Type Definition</a></li>
|
|
<li><a href="#Defining-Types_Struct-Type-Definitions_Annotating-a-Struct-Type-Definition">6.2.2. Annotating a Struct Type Definition</a></li>
|
|
<li><a href="#Defining-Types_Struct-Type-Definitions_Default-Values">6.2.3. Default Values</a></li>
|
|
<li><a href="#Defining-Types_Struct-Type-Definitions_Member-Arrays">6.2.4. Member Arrays</a></li>
|
|
<li><a href="#Defining-Types_Struct-Type-Definitions_Member-Format-Strings">6.2.5. Member Format Strings</a></li>
|
|
<li><a href="#Defining-Types_Struct-Type-Definitions_Struct-Types-Containing-Named-Types">6.2.6. Struct Types Containing Named Types</a></li>
|
|
<li><a href="#Defining-Types_Struct-Type-Definitions_The-Order-of-Members">6.2.7. The Order of Members</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#Defining-Types_Abstract-Type-Definitions">6.3. Abstract Type Definitions</a></li>
|
|
<li><a href="#Defining-Types_Alias-Type-Definitions">6.4. Alias Type Definitions</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#Defining-Enums">7. Defining Enums</a>
|
|
<ul class="sectlevel2">
|
|
<li><a href="#Defining-Enums_Writing-an-Enum-Definition">7.1. Writing an Enum Definition</a></li>
|
|
<li><a href="#Defining-Enums_Using-an-Enum-Definition">7.2. Using an Enum Definition</a></li>
|
|
<li><a href="#Defining-Enums_Numeric-Values">7.3. Numeric Values</a></li>
|
|
<li><a href="#Defining-Enums_The-Representation-Type">7.4. The Representation Type</a></li>
|
|
<li><a href="#Defining-Enums_The-Default-Value">7.5. The Default Value</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#Defining-Ports">8. Defining Ports</a>
|
|
<ul class="sectlevel2">
|
|
<li><a href="#Defining-Ports_Port-Names">8.1. Port Names</a></li>
|
|
<li><a href="#Defining-Ports_Formal-Parameters">8.2. Formal Parameters</a></li>
|
|
<li><a href="#Defining-Ports_Handler-Functions">8.3. Handler Functions</a></li>
|
|
<li><a href="#Defining-Ports_Reference-Parameters">8.4. Reference Parameters</a></li>
|
|
<li><a href="#Defining-Ports_Returning-Values">8.5. Returning Values</a></li>
|
|
<li><a href="#Defining-Ports_Pass-by-Reference-Semantics">8.6. Pass-by-Reference Semantics</a></li>
|
|
<li><a href="#Defining-Ports_Annotating-a-Port-Definition">8.7. Annotating a Port Definition</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#Defining-State-Machines">9. Defining State Machines</a>
|
|
<ul class="sectlevel2">
|
|
<li><a href="#Defining-State-Machines_Writing-a-State-Machine-Definition">9.1. Writing a State Machine Definition</a></li>
|
|
<li><a href="#Defining-State-Machines_States-Signals-and-Transitions">9.2. States, Signals, and Transitions</a></li>
|
|
<li><a href="#Defining-State-Machines_Actions">9.3. Actions</a>
|
|
<ul class="sectlevel3">
|
|
<li><a href="#Defining-State-Machines_Actions_Actions-in-Transitions">9.3.1. Actions in Transitions</a></li>
|
|
<li><a href="#Defining-State-Machines_Actions_Entry-and-Exit-Actions">9.3.2. Entry and Exit Actions</a></li>
|
|
<li><a href="#Defining-State-Machines_Actions_Typed-Signals-and-Actions">9.3.3. Typed Signals and Actions</a></li>
|
|
<li><a href="#Defining-State-Machines_Actions_Atomicity-of-Signal-Handling">9.3.4. Atomicity of Signal Handling</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#Defining-State-Machines_More-on-State-Transitions">9.4. More on State Transitions</a>
|
|
<ul class="sectlevel3">
|
|
<li><a href="#Defining-State-Machines_More-on-State-Transitions_Guarded-Transitions">9.4.1. Guarded Transitions</a></li>
|
|
<li><a href="#Defining-State-Machines_More-on-State-Transitions_Self-Transitions">9.4.2. Self Transitions</a></li>
|
|
<li><a href="#Defining-State-Machines_More-on-State-Transitions_Internal-Transitions">9.4.3. Internal Transitions</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#Defining-State-Machines_Choices">9.5. Choices</a></li>
|
|
<li><a href="#Defining-State-Machines_Hierarchy">9.6. Hierarchy</a>
|
|
<ul class="sectlevel3">
|
|
<li><a href="#Defining-State-Machines_Hierarchy_Substates">9.6.1. Substates</a></li>
|
|
<li><a href="#Defining-State-Machines_Hierarchy_Inherited-Transitions">9.6.2. Inherited Transitions</a></li>
|
|
<li><a href="#Defining-State-Machines_Hierarchy_Entry-and-Exit-Actions">9.6.3. Entry and Exit Actions</a></li>
|
|
<li><a href="#Defining-State-Machines_Hierarchy_Directly-Related-States">9.6.4. Directly Related States</a></li>
|
|
<li><a href="#Defining-State-Machines_Hierarchy_Choices">9.6.5. Choices</a></li>
|
|
</ul>
|
|
</li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#Defining-Components">10. Defining Components</a>
|
|
<ul class="sectlevel2">
|
|
<li><a href="#Defining-Components_Component-Definitions">10.1. Component Definitions</a></li>
|
|
<li><a href="#Defining-Components_Port-Instances">10.2. Port Instances</a>
|
|
<ul class="sectlevel3">
|
|
<li><a href="#Defining-Components_Port-Instances_Basic-Port-Instances">10.2.1. Basic Port Instances</a></li>
|
|
<li><a href="#Defining-Components_Port-Instances_Rules-for-Port-Instances">10.2.2. Rules for Port Instances</a></li>
|
|
<li><a href="#Defining-Components_Port-Instances_Arrays-of-Port-Instances">10.2.3. Arrays of Port Instances</a></li>
|
|
<li><a href="#Defining-Components_Port-Instances_Priority">10.2.4. Priority</a></li>
|
|
<li><a href="#Defining-Components_Port-Instances_Queue-Full-Behavior">10.2.5. Queue Full Behavior</a></li>
|
|
<li><a href="#Defining-Components_Port-Instances_Serial-Port-Instances">10.2.6. Serial Port Instances</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#Defining-Components_Special-Port-Instances">10.3. Special Port Instances</a>
|
|
<ul class="sectlevel3">
|
|
<li><a href="#Defining-Components_Special-Port-Instances_Command-Ports">10.3.1. Command Ports</a></li>
|
|
<li><a href="#Defining-Components_Special-Port-Instances_Event-Ports">10.3.2. Event Ports</a></li>
|
|
<li><a href="#Defining-Components_Special-Port-Instances_Telemetry-Ports">10.3.3. Telemetry Ports</a></li>
|
|
<li><a href="#Defining-Components_Special-Port-Instances_Parameter-Ports">10.3.4. Parameter Ports</a></li>
|
|
<li><a href="#Defining-Components_Special-Port-Instances_Time-Get-Ports">10.3.5. Time Get Ports</a></li>
|
|
<li><a href="#Defining-Components_Special-Port-Instances_Data-Product-Ports">10.3.6. Data Product Ports</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#Defining-Components_Internal-Ports">10.4. Internal Ports</a></li>
|
|
<li><a href="#Defining-Components_Commands">10.5. Commands</a>
|
|
<ul class="sectlevel3">
|
|
<li><a href="#Defining-Components_Commands_Basic-Commands">10.5.1. Basic Commands</a></li>
|
|
<li><a href="#Defining-Components_Commands_Formal-Parameters">10.5.2. Formal Parameters</a></li>
|
|
<li><a href="#Defining-Components_Commands_Opcodes">10.5.3. Opcodes</a></li>
|
|
<li><a href="#Defining-Components_Commands_Priority-and-Queue-Full-Behavior">10.5.4. Priority and Queue Full Behavior</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#Defining-Components_Events">10.6. Events</a>
|
|
<ul class="sectlevel3">
|
|
<li><a href="#Defining-Components_Events_Basic-Events">10.6.1. Basic Events</a></li>
|
|
<li><a href="#Defining-Components_Events_Formal-Parameters">10.6.2. Formal Parameters</a></li>
|
|
<li><a href="#Defining-Components_Events_Identifiers">10.6.3. Identifiers</a></li>
|
|
<li><a href="#Defining-Components_Events_Throttling">10.6.4. Throttling</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#Defining-Components_Telemetry">10.7. Telemetry</a>
|
|
<ul class="sectlevel3">
|
|
<li><a href="#Defining-Components_Telemetry_Basic-Telemetry">10.7.1. Basic Telemetry</a></li>
|
|
<li><a href="#Defining-Components_Telemetry_Identifiers">10.7.2. Identifiers</a></li>
|
|
<li><a href="#Defining-Components_Telemetry_Update-Frequency">10.7.3. Update Frequency</a></li>
|
|
<li><a href="#Defining-Components_Telemetry_Format-Strings">10.7.4. Format Strings</a></li>
|
|
<li><a href="#Defining-Components_Telemetry_Limits">10.7.5. Limits</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#Defining-Components_Parameters">10.8. Parameters</a>
|
|
<ul class="sectlevel3">
|
|
<li><a href="#Defining-Components_Parameters_Basic-Parameters">10.8.1. Basic Parameters</a></li>
|
|
<li><a href="#Defining-Components_Parameters_Default-Values">10.8.2. Default Values</a></li>
|
|
<li><a href="#Defining-Components_Parameters_Identifiers">10.8.3. Identifiers</a></li>
|
|
<li><a href="#Defining-Components_Parameters_Set-and-Save-Opcodes">10.8.4. Set and Save Opcodes</a></li>
|
|
<li><a href="#Defining-Components_Parameters_External-Parameters">10.8.5. External Parameters</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#Defining-Components_Data-Products">10.9. Data Products</a>
|
|
<ul class="sectlevel3">
|
|
<li><a href="#Defining-Components_Data-Products_Basic-Data-Products">10.9.1. Basic Data Products</a></li>
|
|
<li><a href="#Defining-Components_Data-Products_Identifiers">10.9.2. Identifiers</a></li>
|
|
<li><a href="#Defining-Components_Data-Products_Array-Records">10.9.3. Array Records</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#Defining-Components_State-Machine-Instances">10.10. State Machine Instances</a></li>
|
|
<li><a href="#Defining-Components_Constants-Types-Enums-and-State-Machines">10.11. Constants, Types, Enums, and State Machines</a></li>
|
|
<li><a href="#Defining-Components_Include-Specifiers">10.12. Include Specifiers</a></li>
|
|
<li><a href="#Defining-Components_Matched-Ports">10.13. Matched Ports</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#Defining-and-Using-Port-Interfaces">11. Defining and Using Port Interfaces</a>
|
|
<ul class="sectlevel2">
|
|
<li><a href="#Defining-and-Using-Port-Interfaces_Defining-Port-Interfaces">11.1. Defining Port Interfaces</a></li>
|
|
<li><a href="#Defining-and-Using-Port-Interfaces_Using-Port-Interfaces-in-Component-Definitions">11.2. Using Port Interfaces in Component Definitions</a></li>
|
|
<li><a href="#Defining-and-Using-Port-Interfaces_Using-Port-Interfaces-in-Interface-Definitions">11.3. Using Port Interfaces in Interface Definitions</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#Defining-Component-Instances">12. Defining Component Instances</a>
|
|
<ul class="sectlevel2">
|
|
<li><a href="#Defining-Component-Instances_Component-Instance-Definitions">12.1. Component Instance Definitions</a>
|
|
<ul class="sectlevel3">
|
|
<li><a href="#Defining-Component-Instances_Component-Instance-Definitions_Passive-Components">12.1.1. Passive Components</a></li>
|
|
<li><a href="#Defining-Component-Instances_Component-Instance-Definitions_Queued-Components">12.1.2. Queued Components</a></li>
|
|
<li><a href="#Defining-Component-Instances_Component-Instance-Definitions_Active-Components">12.1.3. Active Components</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#Defining-Component-Instances_Specifying-the-Implementation">12.2. Specifying the Implementation</a></li>
|
|
<li><a href="#Defining-Component-Instances_Init-Specifiers">12.3. Init Specifiers</a>
|
|
<ul class="sectlevel3">
|
|
<li><a href="#Defining-Component-Instances_Init-Specifiers_Execution-Phases">12.3.1. Execution Phases</a></li>
|
|
<li><a href="#Defining-Component-Instances_Init-Specifiers_Writing-Init-Specifiers">12.3.2. Writing Init Specifiers</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#Defining-Component-Instances_Generation-of-Names">12.4. Generation of Names</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#Defining-Topologies">13. Defining Topologies</a>
|
|
<ul class="sectlevel2">
|
|
<li><a href="#Defining-Topologies_A-Simple-Example">13.1. A Simple Example</a></li>
|
|
<li><a href="#Defining-Topologies_Connection-Graphs">13.2. Connection Graphs</a>
|
|
<ul class="sectlevel3">
|
|
<li><a href="#Defining-Topologies_Connection-Graphs_Direct-Graph-Specifiers">13.2.1. Direct Graph Specifiers</a></li>
|
|
<li><a href="#Defining-Topologies_Connection-Graphs_Pattern-Graph-Specifiers">13.2.2. Pattern Graph Specifiers</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#Defining-Topologies_Port-Numbering">13.3. Port Numbering</a>
|
|
<ul class="sectlevel3">
|
|
<li><a href="#Defining-Topologies_Port-Numbering_Explicit-Numbering">13.3.1. Explicit Numbering</a></li>
|
|
<li><a href="#Defining-Topologies_Port-Numbering_Matched-Numbering">13.3.2. Matched Numbering</a></li>
|
|
<li><a href="#Defining-Topologies_Port-Numbering_General-Numbering">13.3.3. General Numbering</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#Defining-Topologies_Importing-Topologies">13.4. Importing Topologies</a>
|
|
<ul class="sectlevel3">
|
|
<li><a href="#Defining-Topologies_Importing-Topologies_Importing-Instances-and-Connections">13.4.1. Importing Instances and Connections</a></li>
|
|
<li><a href="#Defining-Topologies_Importing-Topologies_Private-Instances">13.4.2. Private Instances</a></li>
|
|
<li><a href="#Defining-Topologies_Importing-Topologies_Multiple-Imports">13.4.3. Multiple Imports</a></li>
|
|
<li><a href="#Defining-Topologies_Importing-Topologies_Transitive-Imports">13.4.4. Transitive Imports</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#Defining-Topologies_Include-Specifiers">13.5. Include Specifiers</a></li>
|
|
<li><a href="#Defining-Topologies_Telemetry-Packets">13.6. Telemetry Packets</a>
|
|
<ul class="sectlevel3">
|
|
<li><a href="#Defining-Topologies_Telemetry-Packets_Telemetry-Packet-Sets">13.6.1. Telemetry Packet Sets</a></li>
|
|
<li><a href="#Defining-Topologies_Telemetry-Packets_Telemetry-Packet-Identifiers">13.6.2. Telemetry Packet Identifiers</a></li>
|
|
<li><a href="#Defining-Topologies_Telemetry-Packets_Omitting-Channels">13.6.3. Omitting Channels</a></li>
|
|
<li><a href="#Defining-Topologies_Telemetry-Packets_Specifying-Multiple-Telemetry-Packet-Sets">13.6.4. Specifying Multiple Telemetry Packet Sets</a></li>
|
|
<li><a href="#Defining-Topologies_Telemetry-Packets_Include-Specifiers">13.6.5. Include Specifiers</a></li>
|
|
</ul>
|
|
</li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#Specifying-Models-as-Files">14. Specifying Models as Files</a>
|
|
<ul class="sectlevel2">
|
|
<li><a href="#Specifying-Models-as-Files_Dividing-Models-into-Files">14.1. Dividing Models into Files</a></li>
|
|
<li><a href="#Specifying-Models-as-Files_Include-Specifiers">14.2. Include Specifiers</a></li>
|
|
<li><a href="#Specifying-Models-as-Files_Dependencies">14.3. Dependencies</a></li>
|
|
<li><a href="#Specifying-Models-as-Files_Location-Specifiers">14.4. Location Specifiers</a>
|
|
<ul class="sectlevel3">
|
|
<li><a href="#Specifying-Models-as-Files_Location-Specifiers_Syntax">14.4.1. Syntax</a></li>
|
|
<li><a href="#Specifying-Models-as-Files_Location-Specifiers_Path-Names">14.4.2. Path Names</a></li>
|
|
<li><a href="#Specifying-Models-as-Files_Location-Specifiers_Definition-Names">14.4.3. Definition Names</a></li>
|
|
<li><a href="#Specifying-Models-as-Files_Location-Specifiers_Included-Files">14.4.4. Included Files</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#Specifying-Models-as-Files_Locating-Definitions">14.5. Locating Definitions</a>
|
|
<ul class="sectlevel3">
|
|
<li><a href="#Specifying-Models-as-Files_Locating-Definitions_Running-fpp-locate-defs">14.5.1. Running fpp-locate-defs</a></li>
|
|
<li><a href="#Specifying-Models-as-Files_Locating-Definitions_Location-Paths">14.5.2. Location Paths</a></li>
|
|
<li><a href="#Specifying-Models-as-Files_Locating-Definitions_Included-Definitions">14.5.3. Included Definitions</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#Specifying-Models-as-Files_Computing-Dependencies">14.6. Computing Dependencies</a>
|
|
<ul class="sectlevel3">
|
|
<li><a href="#Specifying-Models-as-Files_Computing-Dependencies_Running-fpp-depend">14.6.1. Running fpp-depend</a></li>
|
|
<li><a href="#Specifying-Models-as-Files_Computing-Dependencies_Transitive-Dependencies">14.6.2. Transitive Dependencies</a></li>
|
|
<li><a href="#Specifying-Models-as-Files_Computing-Dependencies_Missing-Dependencies">14.6.3. Missing Dependencies</a></li>
|
|
<li><a href="#Specifying-Models-as-Files_Computing-Dependencies_Included-Files">14.6.4. Included Files</a></li>
|
|
<li><a href="#Specifying-Models-as-Files_Computing-Dependencies_Dependencies-Between-Build-Modules">14.6.5. Dependencies Between Build Modules</a></li>
|
|
<li><a href="#Specifying-Models-as-Files_Computing-Dependencies_Framework-Dependencies">14.6.6. Framework Dependencies</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#Specifying-Models-as-Files_Locating-Uses">14.7. Locating Uses</a></li>
|
|
<li><a href="#Specifying-Models-as-Files_Path-Name-Aliases">14.8. Path Name Aliases</a>
|
|
<ul class="sectlevel3">
|
|
<li><a href="#Specifying-Models-as-Files_Path-Name-Aliases_Relative-Paths-and-Symbolic-Links">14.8.1. Relative Paths and Symbolic Links</a></li>
|
|
<li><a href="#Specifying-Models-as-Files_Path-Name-Aliases_Unique-Locations">14.8.2. Unique Locations</a></li>
|
|
</ul>
|
|
</li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#Analyzing-and-Translating-Models">15. Analyzing and Translating Models</a>
|
|
<ul class="sectlevel2">
|
|
<li><a href="#Analyzing-and-Translating-Models_Checking-Models">15.1. Checking Models</a></li>
|
|
<li><a href="#Analyzing-and-Translating-Models_Generating-C-Plus-Plus">15.2. Generating C Plus Plus</a>
|
|
<ul class="sectlevel3">
|
|
<li><a href="#Analyzing-and-Translating-Models_Generating-C-Plus-Plus_Constant-Definitions">15.2.1. Constant Definitions</a></li>
|
|
<li><a href="#Analyzing-and-Translating-Models_Generating-C-Plus-Plus_Types-Ports-State-Machines-and-Components">15.2.2. Types, Ports, State Machines, and Components</a></li>
|
|
<li><a href="#Analyzing-and-Translating-Models_Generating-C-Plus-Plus_Component-Implementation-and-Unit-Test-Code">15.2.3. Component Implementation and Unit Test Code</a></li>
|
|
<li><a href="#Analyzing-and-Translating-Models_Generating-C-Plus-Plus_Topology-Definitions">15.2.4. Topology Definitions</a></li>
|
|
<li><a href="#Analyzing-and-Translating-Models_Generating-C-Plus-Plus_Compiling-the-Generated-Code">15.2.5. Compiling the Generated Code</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#Analyzing-and-Translating-Models_Formatting-FPP-Source">15.3. Formatting FPP Source</a></li>
|
|
<li><a href="#Analyzing-and-Translating-Models_Visualizing-Topologies">15.4. Visualizing Topologies</a></li>
|
|
<li><a href="#Analyzing-and-Translating-Models_Generating-Ground-Dictionaries">15.5. Generating Ground Dictionaries</a></li>
|
|
<li><a href="#Analyzing-and-Translating-Models_Identifying-Generated-Files">15.6. Identifying Generated Files</a>
|
|
<ul class="sectlevel3">
|
|
<li><a href="#Analyzing-and-Translating-Models_Identifying-Generated-Files_Using-fpp-filenames">15.6.1. Using fpp-filenames</a></li>
|
|
<li><a href="#Analyzing-and-Translating-Models_Identifying-Generated-Files_Using-fpp-depend">15.6.2. Using fpp-depend</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#Analyzing-and-Translating-Models_Generating-JSON-Models">15.7. Generating JSON Models</a></li>
|
|
<li><a href="#Analyzing-and-Translating-Models_Translating-Older-XML-to-FPP">15.8. Translating Older XML to FPP</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#Writing-C-Plus-Plus-Implementations">16. Writing C Plus Plus Implementations</a>
|
|
<ul class="sectlevel2">
|
|
<li><a href="#Writing-C-Plus-Plus-Implementations_Implementing-Abstract-Types">16.1. Implementing Abstract Types</a></li>
|
|
<li><a href="#Writing-C-Plus-Plus-Implementations_Implementing-External-State-Machines">16.2. Implementing External State Machines</a></li>
|
|
<li><a href="#Writing-C-Plus-Plus-Implementations_Implementing-Deployments">16.3. Implementing Deployments</a>
|
|
<ul class="sectlevel3">
|
|
<li><a href="#Writing-C-Plus-Plus-Implementations_Implementing-Deployments_Application-Specific-Definitions">16.3.1. Application-Specific Definitions</a></li>
|
|
<li><a href="#Writing-C-Plus-Plus-Implementations_Implementing-Deployments_The-Main-Function">16.3.2. The Main Function</a></li>
|
|
<li><a href="#Writing-C-Plus-Plus-Implementations_Implementing-Deployments_Public-Symbols">16.3.3. Public Symbols</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#Writing-C-Plus-Plus-Implementations_Serialization-of-FPP-Values">16.4. Serialization of FPP Values</a></li>
|
|
</ul>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div id="content">
|
|
<div class="sect1">
|
|
<h2 id="Introduction">1. Introduction</h2>
|
|
<div class="sectionbody">
|
|
<div class="paragraph">
|
|
<p>This document describes <strong>F Prime Prime</strong>, also known as FPP or F Double Prime.
|
|
FPP is a modeling language for the
|
|
<a href="https://fprime.jpl.nasa.gov">F Prime flight software framework</a>.
|
|
For more detailed information about F Prime, see the
|
|
<a href="https://fprime.jpl.nasa.gov/devel/docs/user-manual/">F Prime User Manual</a>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The goals of FPP are as follows:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>To provide a modeling language for F Prime that is simple, easy to use, and
|
|
well-tailored to its purpose.</p>
|
|
</li>
|
|
<li>
|
|
<p>To provide semantic checking and error reporting for F Prime models.</p>
|
|
</li>
|
|
<li>
|
|
<p>To generate code in the various languages that F Prime uses, e.g.,
|
|
C++ and JSON.
|
|
In this document, we will call these languages the <strong>target languages</strong>.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Developers may combine code generated from FPP with code written by hand to
|
|
create, e.g., deployable flight software (FSW) programs and ground data environments.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The name “F Double Prime” (or F″) deliberately suggests the idea of a
|
|
“derivative”
|
|
of F Prime (or F′).
|
|
By “integrating” an FPP model (i.e., running the tools) you get a partial
|
|
FSW implementation in the F Prime framework; and then by “integrating” again
|
|
(i.e., providing
|
|
the project-specific C++ implementation) you get a FSW application.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Purpose:</strong> The purpose of this document is to describe FPP in a way that is accessible
|
|
to users, including beginning users.
|
|
A more detailed and precise description is available in
|
|
<a href="https://nasa.github.io/fpp/fpp-spec.html"><em>The FPP Language Specification</em></a>.
|
|
We recommend that you read this document before consulting that one.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Overview:</strong> The rest of this document proceeds as follows.
|
|
Section 2 explains how to get up and running with FPP.
|
|
Sections 3 through 12 describe the elements of an FPP
|
|
model, starting with the simplest elements (constants
|
|
and types) and working towards the most complex (components
|
|
and topologies).
|
|
Section 13 explains how to specify a model as a collection
|
|
of files: for example, it covers the management of dependencies
|
|
between files.
|
|
Section 14 explains how to analyze FPP models and how
|
|
to translate FPP models to C++ and JSON.
|
|
It also explains how to translate an XML format previously used
|
|
by F Prime into FPP.
|
|
Section 15 explains how to write a C++ implementation
|
|
against the code generated from an FPP model.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="Installing-FPP">2. Installing FPP</h2>
|
|
<div class="sectionbody">
|
|
<div class="paragraph">
|
|
<p>Before reading the rest of this document, you should install
|
|
the latest version of FPP.
|
|
The installation instructions are available here:</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><a href="https://github.com/nasa/fpp/tree/main/compiler#compiler" class="bare">https://github.com/nasa/fpp/tree/main/compiler#compiler</a></p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Make sure that the FPP command-line tools are in your shell path.
|
|
For example, running <code>fpp-check</code> on the command line should succeed and should
|
|
prompt for standard input. You can type control-C to end
|
|
the program:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>% fpp-check
|
|
^C
|
|
%</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><code>fpp-check</code> is the tool for checking that an FPP model is valid.
|
|
Like most FPP tools,
|
|
<code>fpp-check</code> reads either from named files or from standard input.
|
|
If one or more files are named on the command line, <code>fpp-check</code> reads those;
|
|
otherwise it reads from standard input.
|
|
As an example, the following two operations are equivalent:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>% fpp-check < file.fpp
|
|
% fpp-check file.fpp</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The first operation redirects <code>file.fpp</code> into the standard input of
|
|
<code>fpp-check</code>.
|
|
The second operation names <code>file.fpp</code> as an input file of <code>fpp-check</code>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Most of the examples in the following sections are complete FPP models.
|
|
You can run the models through
|
|
<code>fpp-check</code> by typing or pasting them into a file or into standard input.
|
|
We recommend that you to this for at least a few of the examples,
|
|
to get a feel for how FPP works.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="Defining-Constants">3. Defining Constants</h2>
|
|
<div class="sectionbody">
|
|
<div class="paragraph">
|
|
<p>The simplest FPP model consists of one or more <strong>constant definitions</strong>.
|
|
A constant definition associates a name with a value,
|
|
so that elsewhere you can use the name instead of re-computing or restating the
|
|
value.
|
|
Using named constants makes the model easier to understand (the name
|
|
says what the value means) and to maintain (changing a constant definition is
|
|
easy;
|
|
changing all and only the relevant uses of a repeated value is not).</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>This section covers the following topics:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>Writing an FPP constant definition.</p>
|
|
</li>
|
|
<li>
|
|
<p>Writing an <strong>expression</strong>, which is the source text
|
|
that defines the value associated with the constant definition.</p>
|
|
</li>
|
|
<li>
|
|
<p>Writing multiple constant definitions.</p>
|
|
</li>
|
|
<li>
|
|
<p>Writing a constant definition that spans two or more lines of source text.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Defining-Constants_Writing-a-Constant-Definition">3.1. Writing a Constant Definition</h3>
|
|
<div class="paragraph">
|
|
<p>To write a constant definition, you write the keyword <code>constant</code>,
|
|
an equals sign, and an expression.
|
|
A <a href="#Defining-Constants_Expressions">later section</a>
|
|
describes all the expressions you can write.
|
|
Here is an example that uses an integer literal expression representing
|
|
the value 42:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant ultimateAnswer = 42</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>This definition associates the name <code>ultimateAnswer</code> with the value 42.
|
|
Elsewhere in the FPP model you can use the name <code>ultimateAnswer</code> to represent
|
|
the value.
|
|
You can also generate a C++ header file that defines the C++ constant
|
|
<code>ultimateAnswer</code> and gives it the value 42.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>As an example, do the following:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>On the command line, run <code>fpp-check</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>When the prompt appears, type the text shown above, type return, type control-D, and type return.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>You should see something like the following on your console:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>% fpp-check
|
|
constant ultimateAnswer = 42
|
|
^D
|
|
%</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>As an example of an incorrect model that produces an error message, repeat the
|
|
exercise, but omit the value 42.
|
|
You should see something like this:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>% fpp-check
|
|
constant ultimateAnswer =
|
|
^D
|
|
fpp-check
|
|
stdin: end of input
|
|
error: expression expected</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Here the <code>fpp-check</code> tool is telling you that it could not parse the input:
|
|
the input ended where it expected an expression.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Defining-Constants_Names">3.2. Names</h3>
|
|
<div class="paragraph">
|
|
<p>Names in FPP follow the usual rules for identifiers in a programming language:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>A name must contain at least one character.</p>
|
|
</li>
|
|
<li>
|
|
<p>A name must start with a letter or underscore character.</p>
|
|
</li>
|
|
<li>
|
|
<p>The characters after the first may be letters, numbers, or underscores.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For example:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p><code>name</code>, <code>Name</code>, <code>_name</code>, and <code>name1</code> are valid names.</p>
|
|
</li>
|
|
<li>
|
|
<p><code>1invalid</code> is not a valid name, because names may not start with digits.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Constants_Names_Reserved-Words">3.2.1. Reserved Words</h4>
|
|
<div class="paragraph">
|
|
<p>Certain sequences of letters such as <code>constant</code> are called out as <strong>reserved
|
|
words</strong> (also called keywords) in FPP.
|
|
Each reserved word has a special meaning, such as introducing a constant
|
|
declaration.
|
|
<em>The FPP Language Specification</em> has a complete list of reserved words.
|
|
In this document, we will introduce reserved words as needed to explain
|
|
the language features.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Using a reserved word as a name in the ordinary way causes a parsing error.
|
|
For example, this code is incorrect:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant constant = 0</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>To use a reserved word as a name, you must put the character <code>$</code> in
|
|
front of it with no space.
|
|
For example, this code is legal:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant $constant = 0</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The character sequence <code>$constant</code> represents the name <code>constant</code>,
|
|
as opposed to the keyword <code>constant</code>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>You can put the character <code>$</code> in front of any identifier,
|
|
not just a keyword.
|
|
If the identifier is not a keyword, then the <code>$</code> has no effect.
|
|
For example, <code>$name</code> has the same meaning as <code>name</code>.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Constants_Names_Name-Clashes">3.2.2. Name Clashes</h4>
|
|
<div class="paragraph">
|
|
<p>FPP will not let you define two different symbols of the same
|
|
kind with the same name.
|
|
For example, this code will produce an error:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant c = 0
|
|
constant c = 1</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Two symbols can have the same unqualified name if they
|
|
reside in different
|
|
<a href="#Defining-Modules">modules</a> or
|
|
<a href="#Defining-Enums">enums</a>; these concepts
|
|
are explained below.
|
|
Two symbols can also have the same name if the analyzer
|
|
can distinguish them based on their kinds.
|
|
For example, an
|
|
<a href="#Defining-Types_Array-Type-Definitions">array type</a> (described below) and a
|
|
constant
|
|
can have the same name, but an array type and a
|
|
<a href="#Defining-Types_Struct-Type-Definitions">struct type</a> may not.
|
|
<em>The FPP Language Specification</em> has all the details.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Defining-Constants_Expressions">3.3. Expressions</h3>
|
|
<div class="paragraph">
|
|
<p>This section describes the expressions that you can write as part of a constant
|
|
definition.
|
|
Expressions appear in other FPP elements as well, so we will refer back
|
|
to this section in later sections of the manual.</p>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Constants_Expressions_Primitive-Values">3.3.1. Primitive Values</h4>
|
|
<div class="paragraph">
|
|
<p>A <strong>primitive value expression</strong> represents a primitive machine value, such as an
|
|
integer.
|
|
It is one of the following:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>A decimal integer literal value such as <code>1234</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>A hexadecimal integer literal value such as <code>0xABCD</code> or <code>0xabcd</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>A floating-point literal value such as <code>12.34</code> or <code>1234e-2</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>A Boolean literal expression <code>true</code> or <code>false</code>.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>As an exercise, construct some constant definitions with primitive values as their
|
|
expressions, and
|
|
feed the results to <code>fpp-check</code>.
|
|
For example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant a = 1234
|
|
constant b = 0xABCD</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>If you get an error, make sure you understand why.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Constants_Expressions_String-Values">3.3.2. String Values</h4>
|
|
<div class="paragraph">
|
|
<p>A <strong>string value</strong> represents a string of characters.
|
|
There are two kinds of string values:
|
|
single-line strings and multiline strings.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Single-line strings:</strong>
|
|
A single-line string represents a string of characters
|
|
that does not contain a newline character.
|
|
It is written as a string of characters enclosed in double quotation
|
|
marks <code>"</code>.
|
|
For example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant s = "This is a string."</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>To put the double-quote character in a string, write the double quote
|
|
character as <code>\"</code>, like this:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant s = "\"This is a quotation within a string,\" he said."</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>To encode the character <code>\</code> followed by the character <code>"</code>, write
|
|
the backslash character as <code>\\</code>, like this:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant s = "\\\""</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>This string represents the literal character sequence <code>\</code>, <code>"</code>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In general, the sequence <code>\</code> followed by a character <em>c</em>
|
|
is translated to <em>c</em>.
|
|
This sequence is called an <strong>escape sequence</strong>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Multiline strings:</strong>
|
|
A multiline string represents a string of characters
|
|
that may contain a newline character.
|
|
It is enclosed in a pair of sequences of three double quotation
|
|
marks <code>"""</code>.
|
|
For example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant s = """
|
|
This is a multiline string.
|
|
|
|
It has three lines.
|
|
"""</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>When interpreting a multiline string, FPP ignores any newline
|
|
characters at the start and end of the string.
|
|
FPP also ignores any blanks to the left of the column where
|
|
the first <code>"""</code> appears.
|
|
For example, the string shown above consists of three lines and starts
|
|
with <code>This</code>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Literal quotation marks are allowed inside a multiline string:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant s = """
|
|
"This is a quotation within a string," he said.
|
|
"""</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Escape sequences work as for single-line strings.
|
|
For example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant s = """
|
|
Here are three double-quote characters in a row: \"\"\"
|
|
"""</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Constants_Expressions_Array-Values">3.3.3. Array Values</h4>
|
|
<div class="paragraph">
|
|
<p>An <strong>array value expression</strong> represents a fixed-size array
|
|
of values.
|
|
To write an array value expression, you write a comma-separated list of one or more values
|
|
(the array elements)
|
|
enclosed in square brackets.
|
|
Here is an example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant a = [ 1, 2, 3 ]</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>This code associates the name <code>a</code> with the array of
|
|
integers
|
|
<code>[ 1, 2, 3 ]</code>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>As mentioned in the introduction, an FPP model describes the structure of a FSW
|
|
application; the computations are specified in a target
|
|
language such as C++.
|
|
As a result, FPP does not provide an array indexing operation.
|
|
In particular, it does not specify the index of the leftmost array element;
|
|
that is up to the target language.
|
|
For example, if the target language is C++, then array indices start
|
|
at zero.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Here are some rules for writing array values:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>An array value must have at least one element.
|
|
That is, <code>[]</code> is not a valid array value.</p>
|
|
</li>
|
|
<li>
|
|
<p>The types of the elements must match.
|
|
For example, the following code is illegal, because the value <code>1</code> (which has type <code>Integer</code>)
|
|
and the value <code>"abcd"</code> (which has type <code>string</code>) are incompatible:</p>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant mismatch = [ 1, "abcd" ]</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Try entering this example into <code>fpp-check</code> and see what happens.</p>
|
|
</div>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>What does it mean for types to match?
|
|
<em>The FPP Specification</em> has all the details, and we won’t attempt
|
|
to repeat them here.
|
|
In general, things work as you would expect: for example, we can convert
|
|
an integer value to a floating-point value, so the following code is allowed:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant a = [ 1, 2.0 ]</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>It evaluates to an array of two floating-point values.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>If you are not sure whether a type conversion is allowed, you can
|
|
ask <code>fpp-check</code>.
|
|
For example: can we convert a Boolean value to an integer value?
|
|
In older languages like C and C++ we can, but in many newer languages
|
|
we can’t. Here is the answer in FPP:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>% fpp-check
|
|
constant a = [ 1, true ]
|
|
^D
|
|
fpp-check
|
|
stdin: 1.16
|
|
constant a = [ 1, true ]
|
|
^
|
|
error: cannot compute common type of Integer and bool</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>So no, we can’t.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Here are two more points about array values:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>Any legal value can be an element of an array value, so in particular arrays
|
|
of arrays
|
|
are allowed. For example, this code is allowed:</p>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant a = [ [ 1, 2 ], [ 3, 4 ] ]</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>It represents an array with two elements: the array <code>[ 1, 2 ]</code> and the array <code>[
|
|
3, 4 ]</code>.</p>
|
|
</div>
|
|
</li>
|
|
<li>
|
|
<p>To avoid repeating values, a numeric, string, or Boolean value is automatically promoted to an array
|
|
of appropriate size whenever necessary to make the types work.
|
|
For example, this code is allowed:</p>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant a = [ [ 1, 2, 3 ], 0 ]</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>It is equivalent to this:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant a = [ [ 1, 2, 3 ], [ 0, 0, 0 ] ]</code></pre>
|
|
</div>
|
|
</div>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Constants_Expressions_Array-Elements">3.3.4. Array Elements</h4>
|
|
<div class="paragraph">
|
|
<p>An <strong>array element expression</strong> represents an element of an array value.
|
|
To write an array element expression, you write an array value
|
|
followed by an index expression enclosed in square brackets.
|
|
The index expression must resolve to a number.
|
|
The number specifies the index of the array element, where the
|
|
array indices start at zero.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Here is an example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant a = [ 1, 2, 3 ]
|
|
constant b = a[1]</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In this example, the constant <code>b</code> has the value 2.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The index expression must resolve to a number that is in range
|
|
for the array.
|
|
For example, this code is incorrect, because <code>"hello"</code> is not a number:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant a = [ 1, 2, 3 ]
|
|
constant b = a["hello"]</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>This code is incorrect because 3 is not in the range [0, 2]:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant a = [ 1, 2, 3 ]
|
|
constant b = a[3]</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Constants_Expressions_Struct-Values">3.3.5. Struct Values</h4>
|
|
<div class="paragraph">
|
|
<p>A <strong>struct value expression</strong> represents a C- or C++-style structure, i.e., a
|
|
mapping
|
|
of names to values.
|
|
To write a struct value expression, you write a comma-separated list of zero or
|
|
more <strong>struct members</strong>
|
|
enclosed in curly braces.
|
|
A struct member consists of a name, an equals sign, and a value.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Here is an example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant s = { x = 1, y = "abc" }</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>This code associates the name <code>s</code> with a struct value.
|
|
The struct value has two members <code>x</code> and <code>y</code>.
|
|
Member <code>x</code> has the integer value 1, and member <code>y</code> has the string value <code>"abc"</code>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>The order of members:</strong> When writing a struct value, the order in which the
|
|
members appear does not matter.
|
|
For example, in the following code, constants <code>s1</code> and <code>s2</code> denote the same
|
|
value:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant s1 = { x = 1, y = "abc" }
|
|
constant s2 = { y = "abc", x = 1 }</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>The empty struct:</strong> The empty struct is allowed:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant s = {}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Arrays in structs:</strong> You can write an array value as a member of a struct value.
|
|
For example, this code is allowed:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant s = { x = 1, y = [ 2, 3 ] }</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Structs in arrays:</strong> You can write a struct value as a member of an array value.
|
|
For example, this code is allowed:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant a = [ { x = 1, y = 2 }, { x = 3, y = 4 } ]</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>This code is not allowed, because the element types don’t match — an array is not
|
|
compatible with a struct.</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant a = [ { x = 1, y = 2 }, [ 3, 4 ] ]</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>However, this code is allowed:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant a = [ { x = 1, y = 2 }, { x = 3 } ]</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Notice that the first member of <code>a</code> is a struct with two members <code>x</code> and <code>y</code>.
|
|
The second member of <code>a</code> is also a struct, but it has only one member <code>x</code>.
|
|
When the FPP analyzer detects that a struct type is missing a member,
|
|
it automatically adds the member, giving it a default value.
|
|
The default values are the ones you would expect: zero for numeric members, the empty
|
|
string for string members, and <code>false</code> for Boolean members.
|
|
So the code above is equivalent to the following:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant a = [ { x = 1, y = 2 }, { x = 3, y = 0 } ]</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Constants_Expressions_Struct-Members">3.3.6. Struct Members</h4>
|
|
<div class="paragraph">
|
|
<p>A <strong>struct member expression</strong> represents a member of a struct value.
|
|
To write a struct member expression, you write a struct value followed
|
|
by a dot and the member name.
|
|
For example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant a = { x = 1, y = [ 2, 3 ] }
|
|
constant b = a.y</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Here <code>a</code> is a struct value with members <code>x</code> and <code>y</code>
|
|
The constant <code>b</code> has the array value <code>[ 2, 3 ]</code>, which is the
|
|
value stored in member <code>y</code> of <code>a</code>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>This code is incorrect because <code>a</code> is not a struct value:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant a = 0
|
|
constant b = a.y</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>This code is incorrect because <code>z</code> is not a member of <code>a</code>:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant a = { x = 1, y = [ 2, 3 ] }
|
|
constant b = a.z</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Constants_Expressions_Name-Expressions">3.3.7. Name Expressions</h4>
|
|
<div class="paragraph">
|
|
<p>A <strong>name expression</strong> is a use of a name appearing in a constant definition.
|
|
It stands for the associated constant value.
|
|
For example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant a = 1
|
|
constant b = a</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In this code, constant <code>b</code> has the value 1.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The order of definitions does not matter, so this code is equivalent:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant b = a
|
|
constant a = 1</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The only requirement is that there may not be any cycles in the graph
|
|
consisting of constant definitions and their uses.
|
|
For example, this code is illegal, because there is a cycle from <code>a</code> to <code>b</code> to
|
|
<code>c</code> and back to <code>a</code>:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant a = c
|
|
constant b = a
|
|
constant c = b</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Try submitting this code to <code>fpp-check</code>, to see what happens.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Names like <code>a</code>, <code>b</code>, and <code>c</code> are simple or unqualified names.
|
|
Names can also be qualified: for example <code>A.a</code> is allowed.
|
|
We will discuss qualified names further when we introduce
|
|
module definitions and enum definitions below.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Constants_Expressions_Value-Arithmetic-Expressions">3.3.8. Value Arithmetic Expressions</h4>
|
|
<div class="paragraph">
|
|
<p>A <strong>value arithmetic expression</strong> performs arithmetic on values.
|
|
It is one of the following:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>A negation expression, for example:</p>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant a = -1</code></pre>
|
|
</div>
|
|
</div>
|
|
</li>
|
|
<li>
|
|
<p>A binary operation expression, where the binary operation is one of <code>+</code> (addition), <code>-</code> (subtraction),
|
|
<code>*</code> (multiplication), and <code>/</code> (division). For example:</p>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant a = 1 + 2</code></pre>
|
|
</div>
|
|
</div>
|
|
</li>
|
|
<li>
|
|
<p>A parenthesis expression, for example:</p>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant a = (1)</code></pre>
|
|
</div>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The following rules apply to arithmetic expressions:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>The subexpressions must be integer or floating-point values.</p>
|
|
</li>
|
|
<li>
|
|
<p>If there are any floating-point subexpressions, then the entire expression is
|
|
evaluated using 64-bit floating-point arithmetic.</p>
|
|
</li>
|
|
<li>
|
|
<p>Otherwise the expression is evaluated using arbitrary-precision integer
|
|
arithmetic.</p>
|
|
</li>
|
|
<li>
|
|
<p>In a division operation, the second operand may not be zero or (for
|
|
floating-point values) very close to zero.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Constants_Expressions_Compound-Expressions">3.3.9. Compound Expressions</h4>
|
|
<div class="paragraph">
|
|
<p>Wherever you can write a value inside an expression, you can write
|
|
a more complex expression there, so long as the types work out.
|
|
For example, these expressions are valid:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant a = (1 + 2) * 3
|
|
constant b = [ 1 + 2, 3 ]</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The first example is a binary expression whose first operand is a parentheses
|
|
expression;
|
|
that parentheses expression in turn has a binary expression as its
|
|
subexpression.
|
|
The second example is an array expression whose first element is a binary
|
|
expression.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>This expression is invalid, because <code>1 + 2.0</code> evaluates to a floating-point
|
|
value, which is incompatible with type <code>string</code>:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant a = [ 1 + 2.0, "abc" ]</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Compound expressions are evaluated in the obvious way.
|
|
For example, the constant definitions above are equivalent to the following:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant a = 9
|
|
constant b = [ 3, 3 ]</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For compound arithmetic expressions, the
|
|
precedence and associativity rules are the usual ones (evaluate parentheses
|
|
first, then multiplication, and so forth).</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Defining-Constants_Multiple-Definitions-and-Element-Sequences">3.4. Multiple Definitions and Element Sequences</h3>
|
|
<div class="paragraph">
|
|
<p>Typically you want to specify several definitions in a model source file, not
|
|
just one.
|
|
There are two ways to do this:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>You can separate the definitions by one or more newlines, as shown
|
|
in the examples above.</p>
|
|
</li>
|
|
<li>
|
|
<p>You can put the definitions on the same line, separated by a semicolon.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For example, the following two code excerpts are equivalent:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant a = 1
|
|
constant b = 2</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant a = 1; constant b = 2</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>More generally, a collection of several constant definitions is an example
|
|
of an <strong>element sequence</strong>, i.e., a sequence of similar syntactic elements.
|
|
Here are the rules for writing an element sequence:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>Every kind of element sequence has optional <strong>terminating punctuation</strong>.
|
|
The terminating punctuation is either a semicolon or a comma, depending
|
|
on the kind of element sequence.
|
|
For constant definitions, it is a semicolon.</p>
|
|
</li>
|
|
<li>
|
|
<p>When writing elements on separate lines, the terminating punctuation is
|
|
optional.</p>
|
|
</li>
|
|
<li>
|
|
<p>When writing two or more elements on the same line, the terminating
|
|
punctuation is
|
|
required between the elements and optional after the last element.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Defining-Constants_Multiline-Definitions">3.5. Multiline Definitions</h3>
|
|
<div class="paragraph">
|
|
<p>Sometimes, especially for long definitions, it is useful to split a
|
|
definition across two or more lines.
|
|
In FPP there are several ways to do this.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>First, FPP ignores newlines that follow opening symbols like <code>[</code> and precede
|
|
closing symbols like <code>]</code>.
|
|
For example, this code is allowed:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant a = [
|
|
1, 2, 3
|
|
]</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Second, the elements of an array or struct form an element sequence (see
|
|
the previous section), so you can write each element on its own line,
|
|
omitting the commas if you wish:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant s = {
|
|
x = 1
|
|
y = 2
|
|
z = 3
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>This is a clean way to write arrays and structs.
|
|
The assignment of each element to its own line and the lack of
|
|
terminating punctuation
|
|
make it easy to rearrange the elements.
|
|
In particular, one can do a line-by-line sort on the elements (for example, to
|
|
sort struct members alphabetically by name) without concern for messing up the
|
|
arrangement of commas.
|
|
If we assume that the example represents the first five lines of a source file,
|
|
then in vi this is easily done as <code>:2-4!sort</code>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Third, FPP ignores newlines that follow connecting symbols such as <code>=</code> and <code>+</code>
|
|
For example, this code is allowed;</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant a =
|
|
1
|
|
constant b = 1 +
|
|
2</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Finally, you can always create an explicit line continuation by escaping
|
|
one or more newline characters with <code>\</code>:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant \
|
|
a = 1</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Note that in this example you need the explicit continuation, i.e., this code
|
|
is not legal:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant
|
|
a = 1</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="Writing-Comments-and-Annotations">4. Writing Comments and Annotations</h2>
|
|
<div class="sectionbody">
|
|
<div class="paragraph">
|
|
<p>In FPP, you can write <strong>comments</strong> that are ignored by the parser.
|
|
These are just like comments in most programming languages.
|
|
You can also write <strong>annotations</strong> that have no meaning in the FPP model
|
|
but are attached to model elements and may be carried through
|
|
to translation — for example, they may become comments in generated C++ code.</p>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Writing-Comments-and-Annotations_Comments">4.1. Comments</h3>
|
|
<div class="paragraph">
|
|
<p>A comment starts with the character <code>#</code> and goes to the end of the line.
|
|
For example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp"># This is a comment</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>To write a comment that spans multiple lines, start each line with <code>#</code>:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp"># This is a comment.
|
|
# It spans two lines.</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Writing-Comments-and-Annotations_Annotations">4.2. Annotations</h3>
|
|
<div class="paragraph">
|
|
<p>Annotations are attached to elements of a model, such as
|
|
<a href="#Defining-Constants">constant definitions</a>.
|
|
A model element that may have an annotation attached to it
|
|
is called an <strong>annotatable element</strong>.
|
|
Any constant definition is an annotatable element.
|
|
Other annotatable elements will be called out in future sections
|
|
of this document.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>There are two kinds of annotations: <strong>pre annotations</strong> and <strong>post annotations</strong>:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>A pre annotation starts with the character <code>@</code> and is attached to the
|
|
annotatable element that follows it.</p>
|
|
</li>
|
|
<li>
|
|
<p>A post annotation starts with the characters <code>@<</code> and is attached to
|
|
the annotatable element that precedes it.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In either case</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>Any white space immediately following the <code>@</code> or <code>@<</code> characters is ignored.</p>
|
|
</li>
|
|
<li>
|
|
<p>The annotation goes to the end of the line.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ This is a pre annotation
|
|
constant c = 0 @< This is a post annotation</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Multiline annotations are allowed. For example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ This is a pre annotation.
|
|
@ It has two lines.
|
|
constant c = 0 @< This is a post annotation.
|
|
@< It also has two lines.</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The meaning of the annotations is tool-specific. A typical use is to
|
|
concatenate the pre and post annotations into a list of lines and emit them as
|
|
a comment. For example, if you send the code immediately above through the
|
|
tool <a href="#Analyzing-and-Translating-Models_Generating-C-Plus-Plus"><code>fpp-to-cpp</code></a>,
|
|
it should generate a file <code>FppConstantsAc.hpp</code>. If you examine that file,
|
|
you should see, in relevant part, the following code:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="cpp">//! This is a pre annotation.
|
|
//! It has two lines.
|
|
//! This is a post annotation.
|
|
//! It also has two lines.
|
|
enum FppConstant_c {
|
|
c = 0
|
|
};</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The two lines of the pre annotation and the two lines of the post
|
|
annotation have been concatenated and written out as a Doxygen
|
|
comment attached to the constant definition, represented as a C++ enum.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In the future, annotations may be used to provide additional capabilities, for
|
|
example timing analysis, that are not part of the FPP language specification.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="Defining-Modules">5. Defining Modules</h2>
|
|
<div class="sectionbody">
|
|
<div class="paragraph">
|
|
<p>In an FPP model, a <strong>module</strong> is a group of model elements that are all qualified
|
|
with a name, called the <strong>module name</strong>.
|
|
An FPP module corresponds to a namespace in C++ and a module in Python.
|
|
Modules are useful for (1) organizing a large model into a hierarchy of smaller
|
|
units and (2) avoiding
|
|
<a href="#Defining-Constants_Names_Name-Clashes">name clashes</a>
|
|
between different units.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>To define a module, you write the keyword <code>module</code> followed by one
|
|
or more definitions enclosed in curly braces.
|
|
For example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">module M {
|
|
constant a = 1
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The name of a module qualifies the names of all the definitions that the module
|
|
encloses.
|
|
To write the qualified name, you write the qualifier, a dot, and the base name:
|
|
for example <code>M.a</code>. (This is also the way that
|
|
name qualification works in Python, Java, and Scala.)
|
|
Inside the module, you can use the qualified name or the unqualified
|
|
name.
|
|
Outside the module, you must use the qualified name.
|
|
For example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">module M {
|
|
constant a = 1
|
|
constant b = a # OK: refers to M.a
|
|
constant c = M.b
|
|
}
|
|
|
|
constant a = M.a
|
|
constant c = b # Error: b is not in scope here</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>As with namespaces in C++, you can close a module definition and
|
|
reopen it later.
|
|
All the definitions enclosed by the same name go in the module
|
|
with that name.
|
|
For example, the following code is allowed:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">module M {
|
|
constant a = 0
|
|
}
|
|
module M {
|
|
constant b = 1
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>It is equivalent to this code:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">module M {
|
|
constant a = 0
|
|
constant b = 1
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>You can define modules inside other modules.
|
|
When you do that, the name qualification works in the obvious way.
|
|
For example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">module A {
|
|
module B {
|
|
constant c = 0
|
|
}
|
|
}
|
|
constant c = A.B.c</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The inside of a module definition is an
|
|
<a href="#Defining-Constants_Multiple-Definitions-and-Element-Sequences">element sequence</a>
|
|
with a semicolon as the optional terminating punctuation.
|
|
For example, you can write this:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">module M { constant a = 0; constant b = 1 }; constant c = M.a</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>A module definition is an
|
|
<a href="#Writing-Comments-and-Annotations_Annotations">annotatable element</a>,
|
|
so you can attach annotations to it, like this:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ This is module M
|
|
module M {
|
|
constant a = 0
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="Defining-Types">6. Defining Types</h2>
|
|
<div class="sectionbody">
|
|
<div class="paragraph">
|
|
<p>An FPP model may include one or more <strong>type definitions</strong>.
|
|
These definitions describe named types that may be used elsewhere in the
|
|
model and that may generate code in the target language.
|
|
For example,
|
|
an FPP type definition may become a class definition in C++.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>There are four kinds of type definitions:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>Array type definitions</p>
|
|
</li>
|
|
<li>
|
|
<p>Struct type definitions</p>
|
|
</li>
|
|
<li>
|
|
<p>Abstract type definitions</p>
|
|
</li>
|
|
<li>
|
|
<p>Alias type definitions</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Type definitions may appear at the top level or inside a
|
|
<a href="#Defining-Modules">module definition</a>.
|
|
A type definition is an
|
|
<a href="#Writing-Comments-and-Annotations_Annotations">annotatable element</a>.</p>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Defining-Types_Array-Type-Definitions">6.1. Array Type Definitions</h3>
|
|
<div class="paragraph">
|
|
<p>An <strong>array type definition</strong> associates a name with an <strong>array type</strong>.
|
|
An array type describes the shape of an
|
|
<a href="#Defining-Constants_Expressions_Array-Values">array value</a>.
|
|
It specifies an element type and a size.</p>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Types_Array-Type-Definitions_Writing-an-Array-Type-Definition">6.1.1. Writing an Array Type Definition</h4>
|
|
<div class="paragraph">
|
|
<p>As an example, here is an array type definition that associates
|
|
the name <code>A</code> with an array of three values, each of which is a 32-bit unsigned
|
|
integer:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">array A = [3] U32</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In general, to write an array type definition, you write the following:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>The keyword <code>array</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>The <a href="#Defining-Constants_Names">name</a> of the array type.</p>
|
|
</li>
|
|
<li>
|
|
<p>An equals sign <code>=</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>An <a href="#Defining-Constants_Expressions">expression</a>
|
|
enclosed in square brackets <code>[</code> …​ <code>]</code> denoting the size (number of elements) of the array.</p>
|
|
</li>
|
|
<li>
|
|
<p>A type name denoting the element type.
|
|
The available type names are discussed below.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Notice that the size expression precedes the element type, and the whole
|
|
type reads left to right.
|
|
For example, you may read the type <code>[3] U32</code> as "array of 3 <code>U32</code>."</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The size may be any legal expression.
|
|
It doesn’t have to be a literal integer.
|
|
For example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant numElements = 10
|
|
array A = [numElements] U32</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Types_Array-Type-Definitions_Type-Names">6.1.2. Type Names</h4>
|
|
<div class="paragraph">
|
|
<p>The following type names are available for the element types:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>The type names <code>U8</code>, <code>U16</code>, <code>U32</code>, and <code>U64</code>, denoting the type of unsigned
|
|
integers of width 8, 16, 32, and 64 bits.</p>
|
|
</li>
|
|
<li>
|
|
<p>The type names <code>I8</code>, <code>I16</code>, <code>I32</code>, and <code>I64</code>, denoting the type of signed integers
|
|
of width 8, 16, 32, and 64 bits.</p>
|
|
</li>
|
|
<li>
|
|
<p>The type names <code>F32</code> and <code>F64</code>, denoting the type of floating-point values
|
|
of width 32 and 64 bits.</p>
|
|
</li>
|
|
<li>
|
|
<p>The type name <code>bool</code>, denoting the type of Boolean values (<code>true</code> and <code>false</code>).</p>
|
|
</li>
|
|
<li>
|
|
<p>The type name <code>string</code>, denoting the type of
|
|
<a href="#Defining-Constants_Expressions_String-Values">string values</a>.
|
|
This type has a default maximum size.
|
|
For example:</p>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp"># A is an array of 3 strings with default maximum size
|
|
array A = [3] string</code></pre>
|
|
</div>
|
|
</div>
|
|
</li>
|
|
<li>
|
|
<p>The type name <code>string size</code> <em>e</em>, where <em>e</em> is a numeric expression
|
|
specifying a maximum string size.</p>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp"># A is an array of 3 strings with maximum size 40
|
|
array A = [3] string size 40</code></pre>
|
|
</div>
|
|
</div>
|
|
</li>
|
|
<li>
|
|
<p>A name associated with another type definition.
|
|
In particular, an array definition may have another array definition as
|
|
its element type; this situation is discussed further below.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>An array type definition may not refer to itself (array type definitions are not
|
|
recursive). For example, this definition is illegal:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">array A = [3] A # Illegal: the definition of A may not refer to itself</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Types_Array-Type-Definitions_Default-Values">6.1.3. Default Values</h4>
|
|
<div class="paragraph">
|
|
<p>Optionally, you can specify a default value for an array type.
|
|
To do this, you write the keyword <code>default</code> and an expression
|
|
that evaluates to an <a href="#Defining-Constants_Expressions_Array-Values">array value</a>.
|
|
For example, here is an array type <code>A</code> with default value <code>[ 1, 2, 3 ]</code>:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">array A = [3] U32 default [ 1, 2, 3 ]</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>A default value expression need not be a literal array value; it
|
|
can be any expression with the correct type.
|
|
For example, you can create a named constant with an array
|
|
value and use it multiple times, like this:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant a = [ 1, 2, 3 ]
|
|
array A = [3] U8 default a # default value is [ 1, 2, 3 ]
|
|
array B = [3] U16 default a # default value is [ 1, 2, 3 ]</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>If you don’t specify a default value, then the type gets an automatic default value,
|
|
consisting of the default value for each element.
|
|
The default numeric value is zero, the default Boolean value is <code>false</code>,
|
|
the default string value is <code>""</code>, and the default value of an array type
|
|
is specified in the type definition.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The type of the default expression must match the size and element type of the
|
|
array, with type conversions allowed as discussed for
|
|
<a href="#Defining-Constants_Expressions_Array-Values">array values</a>.
|
|
For example, this default expression is allowed, because we can convert integer
|
|
values to floating-point values, and we can promote a single value to an array
|
|
of three values:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">array A = [3] F32 default 1 # default value is [ 1.0, 1.0, 1.0 ]</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>However, these default expressions are not allowed:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">array A = [3] U32 default [ 1, 2 ] # Error: size does not match</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">array B = [3] U32 default [ "a", "b", "c" ] # Error: element type does not match</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Types_Array-Type-Definitions_Format-Strings">6.1.4. Format Strings</h4>
|
|
<div class="paragraph">
|
|
<p>You can specify an optional <strong>format string</strong> which says how to display
|
|
each element value and optionally provides some surrounding text.
|
|
For example, here is an array definition that interprets three integer
|
|
values as wheel speeds measured in RPMs:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">array WheelSpeeds = [3] U32 format "{} RPM"</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Then an element with value 100 would have the format <code>100 RPM</code>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Note that the format string specifies the format for an <em>element</em>, not the
|
|
entire array.
|
|
The way an entire array is displayed is implementation-specific.
|
|
A standard way is a comma-separated list enclosed in square brackets.
|
|
For example, a value <code>[ 100, 200, 300 ]</code> of type <code>WheelSpeeds</code> might
|
|
be displayed as <code>[ 100 RPM, 200 RPM, 300 RPM ]</code>.
|
|
Or, since the format is the same for all elements, the implementation could
|
|
display the array as <code>[ 100, 200, 300 ] RPM</code>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The special character sequence <code>{}</code> is called a <strong>replacement field</strong>; it says
|
|
where to put the value in the format text.
|
|
Each format string must have exactly one replacement field.
|
|
The following replacement fields are allowed:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>The field <code>{}</code> for displaying element values in their default format.</p>
|
|
</li>
|
|
<li>
|
|
<p>The field <code>{c}</code> for displaying a character value</p>
|
|
</li>
|
|
<li>
|
|
<p>The field <code>{d}</code> for displaying a decimal value</p>
|
|
</li>
|
|
<li>
|
|
<p>The field <code>{x}</code> for displaying a hexadecimal value</p>
|
|
</li>
|
|
<li>
|
|
<p>The field <code>{o}</code> for displaying an octal value</p>
|
|
</li>
|
|
<li>
|
|
<p>The field <code>{e}</code> for displaying a rational value in exponent notation, e.g.,
|
|
<code>1.234e2</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>The field <code>{f}</code> for displaying a rational value in fixed-point notation,
|
|
e.g., <code>123.4</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>The field <code>{g}</code> for displaying a rational value in general format
|
|
(fixed-point notation up to an implementation-dependent size and exponent
|
|
notation for larger sizes).</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For field types <code>c</code>, <code>d</code>, <code>x</code>, and <code>o</code>, the element type must be an integer
|
|
type.
|
|
For field types <code>e</code>, <code>f</code>, and <code>g</code>, the element type must be a floating-point
|
|
type.
|
|
For example, the following format string is illegal, because
|
|
type <code>string</code> is not an integer type:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">array A = [3] string format "{d}" # Illegal: string is not an integer type</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For field types <code>e</code>, <code>f</code>, and <code>g</code>, you can optionally specify a precision
|
|
by writing a decimal point and an integer before the field type. For example,
|
|
the replacement field <code>{.3f}</code>, specifies fixed-point notation with a precision
|
|
of 3.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>To include the literal character <code>{</code> in the formatted output, you can write
|
|
<code>{{</code>, and similarly for <code>}</code> and <code>}}</code>. For example, the following definition</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">array A = [3] U32 format "{{element {}}}"</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>specifies a format string <code>element {0}</code> for element value 0.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>No other use of <code>{</code> or <code>}</code> in a format string is allowed. For example, this is illegal:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">array A = [3] U32 format "{" # Illegal use of { character</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>You can include both a default value and a format; in this case, the default
|
|
value must come first. For example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">array WheelSpeeds = [3] U32 default 100 format "{} RPM"</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>If you don’t specify an element format, then each element is displayed
|
|
using the default format for its type.
|
|
Therefore, omitting the format string is equivalent to writing the format
|
|
string <code>"{}"</code>.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Types_Array-Type-Definitions_Arrays-of-Arrays">6.1.5. Arrays of Arrays</h4>
|
|
<div class="paragraph">
|
|
<p>An array type may have another array type as its element type.
|
|
In this way you can construct an array of arrays.
|
|
For example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">array A = [3] U32
|
|
array B = [3] A # An array of 3 A, which is an array of 3 U32</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>When constructing an array of arrays, you may provide any legal
|
|
default expression, so long as the types are compatible.
|
|
For example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">array A = [2] U32 default 10 # default value is [ 10, 10 ]
|
|
array B1 = [2] A # default value is [ [ 10, 10 ], [ 10, 10 ] ]
|
|
array B2 = [2] A default 1 # default value is [ [ 1, 1 ], [ 1, 1 ] ]
|
|
array B3 = [2] A default [ 1, 2 ] # default value is [ [ 1, 1 ], [ 2, 2 ] ]
|
|
array B4 = [2] A default [ [ 1, 2 ], [ 3, 4 ] ]</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Defining-Types_Struct-Type-Definitions">6.2. Struct Type Definitions</h3>
|
|
<div class="paragraph">
|
|
<p>A <strong>struct type definition</strong> associates a name with a <strong>struct type</strong>.
|
|
A struct type describes the shape of a
|
|
<a href="#Defining-Constants_Expressions_Struct-Values">struct value</a>.
|
|
It specifies a mapping from element names to their types.
|
|
As discussed below, it also specifies a serialization order
|
|
for the struct elements.</p>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Types_Struct-Type-Definitions_Writing-a-Struct-Type-Definition">6.2.1. Writing a Struct Type Definition</h4>
|
|
<div class="paragraph">
|
|
<p>As an example, here is a struct type definition that associates the name <code>S</code> with
|
|
a struct type containing two members: <code>x</code> of type <code>U32</code>, and <code>y</code> of type <code>string</code>:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">struct S { x: U32, y: string }</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In general, to write a struct type definition, you write the following:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>The keyword <code>struct</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>The <a href="#Defining-Constants_Names">name</a> of the struct type.</p>
|
|
</li>
|
|
<li>
|
|
<p>A sequence of <strong>struct type members</strong> enclosed in curly braces <code>{</code> …​ <code>}</code>.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>A struct type member consists of a name, a colon, and a
|
|
<a href="#Defining-Types_Array-Type-Definitions_Type-Names">type name</a>,
|
|
for example <code>x: U32</code>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The struct type members form an
|
|
<a href="#Defining-Constants_Multiple-Definitions-and-Element-Sequences">element
|
|
sequence</a>
|
|
in which the optional terminating punctuation is a comma.
|
|
As usual for element sequences, you can omit the comma and use
|
|
a newline instead.
|
|
So, for example, we can write the definition shown above in this alternate way:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">struct S {
|
|
x: U32
|
|
y: string
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Types_Struct-Type-Definitions_Annotating-a-Struct-Type-Definition">6.2.2. Annotating a Struct Type Definition</h4>
|
|
<div class="paragraph">
|
|
<p>As noted in the beginning of this section, a type definition is
|
|
an annotatable element, so you can attach pre and post annotations
|
|
to it.
|
|
A struct type member is also an annotatable element, so any
|
|
struct type member can have pre and post annotations as well.
|
|
Here is an example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ This is a pre annotation for struct S
|
|
struct S {
|
|
@ This is a pre annotation for member x
|
|
x: U32 @< This is a post annotation for member x
|
|
@ This is a pre annotation for member y
|
|
y: string @< This is a post annotation for member y
|
|
} @< This is a post annotation for struct S</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Types_Struct-Type-Definitions_Default-Values">6.2.3. Default Values</h4>
|
|
<div class="paragraph">
|
|
<p>You can specify an optional default value for a struct definition.
|
|
To do this, you write the keyword <code>default</code> and an expression
|
|
that evaluates to a <a href="#Defining-Constants_Expressions_Struct-Values">struct
|
|
value</a>.
|
|
For example, here is a struct type <code>S</code> with default value <code>{ x = 1, y = "abc"
|
|
}</code>:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">struct S { x: U32, y: string } default { x = 1, y = "abc" }</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>A default value expression need not be a literal struct value; it
|
|
can be any expression with the correct type.
|
|
For example, you can create a named constant with a struct
|
|
value and use it multiple times, like this:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant s = { x = 1, y = "abc" }
|
|
struct S1 { x: U8, y: string } default s
|
|
struct S2 { x: U32, y: string } default s</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>If you don’t specify a default value, then the struct type gets an automatic default
|
|
value,
|
|
consisting of the default value for each member.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The type of the default expression must match the type of the struct, with type
|
|
conversions allowed as discussed for
|
|
<a href="#Defining-Constants_Expressions_Struct-Values">struct values</a>.
|
|
For example, this default expression is allowed, because we can convert integer
|
|
values to floating-point values, and we can promote a single value to a
|
|
struct with numeric members:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">struct S { x: F32, y: F32 } default 1 # default value is { x = 1.0, y = 1.0 }</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>And this default expression is allowed, because if we omit a member of a struct,
|
|
then FPP will fill in the member and give it the default value:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">struct S { x: F32, y: F32 } default { x = 1 } # default value is { x = 1.0, y = 0.0 }</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>However, these default expressions are not allowed:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">struct S1 { x: U32, y: string } default { z = 1 } # Error: member z does not match</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">struct S2 { x: U32, y: string } default { x = "abc" } # Error: type of member x does not match</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Types_Struct-Type-Definitions_Member-Arrays">6.2.4. Member Arrays</h4>
|
|
<div class="paragraph">
|
|
<p>For any struct member, you can specify that the member
|
|
is an array of elements.
|
|
To do this you, write an array the size enclosed in square brackets
|
|
before the member type.
|
|
For example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">struct S {
|
|
x: [3] U32
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>This definition says that struct <code>S</code> has one element <code>x</code>,
|
|
which is an array consisting of three <code>U32</code> values.
|
|
We call this array a <strong>member array</strong>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Member arrays vs. array types:</strong>
|
|
Member arrays let you include an array
|
|
of elements as a member of a struct type,
|
|
without defining a separate
|
|
<a href="#Defining-Types_Array-Type-Definitions">named array type</a>.
|
|
Also, member arrays generate less code than named arrays.
|
|
Whereas a member size array is a native C++ array,
|
|
each named array is a C++ class.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>On the other hand, defining a named array is usually
|
|
a good choice when</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>You want to use the array outside of any structure.</p>
|
|
</li>
|
|
<li>
|
|
<p>You want the convenience of a generated array class,
|
|
which has a richer interface than the bare
|
|
C++ array.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In particular, the generated array class provides
|
|
<strong>bounds-checked</strong> access operations:
|
|
it causes a runtime failure if an out-of-bounds access
|
|
occurs.
|
|
The bounds checking provides an additional degree of memory
|
|
safety when accessing array elements.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Member arrays and default values:</strong>
|
|
FPP ignores member array sizes when checking the types of
|
|
default values.
|
|
For example, this code is accepted:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">struct S {
|
|
x: [3] U32
|
|
} default { x = 10 }</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The member <code>x</code> of the struct <code>S</code> gets three copies of the value
|
|
10 specified for <code>x</code> in the default value expression.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Types_Struct-Type-Definitions_Member-Format-Strings">6.2.5. Member Format Strings</h4>
|
|
<div class="paragraph">
|
|
<p>For any struct member, you can include an optional format.
|
|
To do this, write the keyword <code>format</code> and a format string.
|
|
The format string for a struct member has the same form as for an
|
|
<a href="#Defining-Types_Array-Type-Definitions_Format-Strings">array member</a>.
|
|
For example, the following struct definition specifies
|
|
that member <code>x</code> should be displayed as a hexadecimal value:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">struct Channel {
|
|
name: string
|
|
offset: U32 format "offset 0x{x}"
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>How the entire struct is displayed depends on the implementation.
|
|
As an example, the value of <code>S</code> with <code>name = "momentum"</code> and <code>offset = 1024</code>
|
|
might look like this when displayed:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>Channel { name = "momentum", offset = 0x400 }</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>If you don’t specify a format for a struct member, then the system uses the default
|
|
format for the type of that member.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>If the member has a size greater than one, then the format
|
|
is applied to each element.
|
|
For example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">struct Telemetry {
|
|
velocity: [3] F32 format "{} m/s"
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The format string is applied to each of the three
|
|
elements of the member <code>velocity</code>.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Types_Struct-Type-Definitions_Struct-Types-Containing-Named-Types">6.2.6. Struct Types Containing Named Types</h4>
|
|
<div class="paragraph">
|
|
<p>A struct type may have an array or struct type as a member type.
|
|
In this way you can define a struct that has arrays or structs as members.
|
|
For example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">array Speeds = [3] U32
|
|
# Member speeds has type Speeds, which is an array of 3 U32 values
|
|
struct Wheel { name: string, speeds: Speeds }</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>When initializing a struct, you may provide any legal
|
|
default expression, so long as the types are compatible.
|
|
For example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">array A = [2] U32
|
|
struct S1 { x: U32, y: string }
|
|
|
|
# default value is { s1 = { x = 0, y = "" }, a = [ 0, 0 ] }
|
|
struct S2 { s1: S1, a: A }
|
|
|
|
# default value is { s1 = { x = 0, y = "abc" }, a = [ 5, 5 ] }
|
|
struct S3 { s1: S1, a: A } default { s1 = { y = "abc" }, a = 5 }</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Types_Struct-Type-Definitions_The-Order-of-Members">6.2.7. The Order of Members</h4>
|
|
<div class="paragraph">
|
|
<p>For <a href="#Defining-Constants_Expressions_Struct-Values">struct values</a>,
|
|
we said that the order in which the members appear in the value is not
|
|
significant.
|
|
For example, the expressions <code>{ x = 1, y = 2 }</code> and <code>{ y = 2, x = 1 }</code> denote
|
|
the same value.
|
|
For struct types, the rule is different.
|
|
The order in which the members appear is significant, because
|
|
it governs the order in which the members appear in the generated
|
|
code.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For example, the type <code>struct S1 { x: U32, y : string }</code> might generate a C++
|
|
class <code>S1</code> with members <code>x</code> and <code>y</code> laid out with <code>x</code> first; while <code>struct S2
|
|
{ y : string, x : U32 }</code>
|
|
might generate a C++ class <code>S2</code> with members <code>x</code> and <code>y</code> laid out with <code>y</code>
|
|
first.
|
|
Since class members are generally serialized in the order in which they appear in
|
|
the class,
|
|
the members of <code>S1</code> would be serialized with <code>x</code> first, and the members of
|
|
<code>S2</code>
|
|
would be serialized with <code>y</code> first.
|
|
Serializing <code>S1</code> to data and then trying to deserialize it to <code>S2</code> would
|
|
produce garbage.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The order matters only for purposes of defining the type, not for
|
|
assigning default values to it.
|
|
For example, this code is legal:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">struct S { x: U32, y: string } default { y = "abc", x = 5 }</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>FPP struct <em>values</em> have no inherent order associated with their members.
|
|
However, once those values are assigned to a named struct <em>type</em>,
|
|
the order becomes fixed.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Defining-Types_Abstract-Type-Definitions">6.3. Abstract Type Definitions</h3>
|
|
<div class="paragraph">
|
|
<p>An array or struct type definition specifies a complete type:
|
|
in addition to the name of the type, it provides the names and types
|
|
of all the members.
|
|
An <strong>abstract type</strong>, by contrast, has an incomplete or opaque definition.
|
|
It provides only a name <em>N</em>.
|
|
Its purpose is to tell the analyzer that a type with name <em>N</em> exists and will
|
|
be defined elsewhere.
|
|
For example, if the target language is C++, then the type is a C++
|
|
class.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>To define an abstract type, you write the keyword <code>type</code> followed
|
|
by the name of the type.
|
|
For example, you can define an abstract type <code>T</code>; then you can construct
|
|
an array <code>A</code> with member type <code>T</code>:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">type T # T is an abstract type
|
|
array A = [3] T # A is an array of 3 values of type T</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>This code says the following:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>A type <code>T</code> exists. It is defined in the implementation,
|
|
but not in the model.</p>
|
|
</li>
|
|
<li>
|
|
<p><code>A</code> is an array of three values, each of type <code>T</code>.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Now suppose that the target language is C++.
|
|
Then the following happens when generating code:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>The definition <code>type T</code> does not cause any code to be generated.</p>
|
|
</li>
|
|
<li>
|
|
<p>The definition <code>array A =</code> …​ causes a C++ class <code>A</code>
|
|
to be generated.
|
|
By F Prime convention, the generated files are <code>AArrayAc.hpp</code> and <code>AArrayAc.cpp</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>File <code>AArrayAc.hpp</code> includes a header file <code>T.hpp</code>.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>It is up to the user to implement a C++ class <code>T</code> with
|
|
a header file <code>T.hpp</code>.
|
|
This header file must define <code>T</code> in a way that is compatible
|
|
with the way that <code>T</code> is used in <code>A</code>.
|
|
We will have more to say about this topic in the section on
|
|
<a href="#Writing-C-Plus-Plus-Implementations_Implementing-Abstract-Types">implementing abstract types</a>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In general, an abstract type <code>T</code> is opaque in the FPP model
|
|
and has no values that are expressible in the model.
|
|
Thus, every use of an abstract type <code>T</code> represents the default value
|
|
for <code>T</code>.
|
|
The implementation of <code>T</code> in the target language
|
|
provides the default value.
|
|
In particular, when the target language is C++, the default
|
|
value is the zero-argument constructor <code>T()</code>.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Defining-Types_Alias-Type-Definitions">6.4. Alias Type Definitions</h3>
|
|
<div class="paragraph">
|
|
<p>An <strong>alias type definition</strong> provides an alternate name for
|
|
a type that is defined elsewhere.
|
|
The alternate name is called an <strong>alias</strong> of the original type.
|
|
For example, here is an alias type definition specifying that the type
|
|
<code>T</code> is an alias of the type <code>U32</code>:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">type T = U32</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Wherever this definition is available, the type <code>T</code> may be used
|
|
interchangeably with the type <code>U32</code>.
|
|
For example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">type T = U32
|
|
array A = [3] T</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>An alias type definition may refer to any type, including another
|
|
alias type, except that it may not refer to itself, either directly or through
|
|
another alias.
|
|
For example, here is an alias type definition specifying that the type
|
|
<code>T</code> is an alias of the struct type <code>S</code>:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">struct S { x: U32, y: I32 }
|
|
type T = S</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Here is a pair of definitions specifying that <code>S</code> is an alias of <code>T</code>,
|
|
and <code>T</code> is an alias of <code>F32</code>:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">type S = T
|
|
type T = F32</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Here is a pair of alias type definitions that is illegal, because each of
|
|
the definitions indirectly refers to itself:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">type S = T
|
|
type T = S</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Alias type definitions are useful for specifying configurations.
|
|
Part of a model can use a type <code>T</code>, without
|
|
defining <code>T</code>; elsewhere, configuration code can define
|
|
<code>T</code> to be the alias of another type.
|
|
F Prime uses this method to provide basic type whose definitions
|
|
configure the framework.
|
|
These types are defined in the file <code>config/FpConfig.fpp</code>.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="Defining-Enums">7. Defining Enums</h2>
|
|
<div class="sectionbody">
|
|
<div class="paragraph">
|
|
<p>An FPP model may contain one or more <strong>enum definitions</strong>.
|
|
Enum is short for enumeration.
|
|
An FPP enum is similar to an enum in C or C++.
|
|
It defines a named type called an <strong>enum type</strong> and a set of named constants
|
|
called <strong>enumerated constants</strong>.
|
|
The enumerated constants are the values associated with the type.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>An enum definition may appear at the top level or inside a
|
|
<a href="#Defining-Modules">module definition</a>.
|
|
An enum definition is an
|
|
<a href="#Writing-Comments-and-Annotations_Annotations">annotatable element</a>.</p>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Defining-Enums_Writing-an-Enum-Definition">7.1. Writing an Enum Definition</h3>
|
|
<div class="paragraph">
|
|
<p>Here is an example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">enum Decision {
|
|
YES
|
|
NO
|
|
MAYBE
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>This code defines an enum type <code>Decision</code> with three
|
|
enumerated constants: <code>YES</code>, <code>NO</code>, and <code>MAYBE</code>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In general, to write an enum definition, you write the following:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>The keyword <code>enum</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>The name of the enum.</p>
|
|
</li>
|
|
<li>
|
|
<p>A sequence of enumerated constants enclosed in curly braces <code>{</code> …​ <code>}</code>.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The enumerated constants form an
|
|
<a href="#Defining-Constants_Multiple-Definitions-and-Element-Sequences">element
|
|
sequence</a>
|
|
in which the optional terminating punctuation is a comma.
|
|
For example, this definition is equivalent to the one above:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">enum Decision { YES, NO, MAYBE }</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>There must be at least one enumerated constant.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Defining-Enums_Using-an-Enum-Definition">7.2. Using an Enum Definition</h3>
|
|
<div class="paragraph">
|
|
<p>Once you have defined an enum, you can use the enum as a type and the
|
|
enumerated constants as constants of that type.
|
|
The name of each enumerated constant is qualified by the enum name.
|
|
Here is an example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">enum State { ON, OFF }
|
|
constant initialState = State.OFF</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The constant <code>s</code> has type <code>State</code> and value <code>State.ON</code>.
|
|
Here is another example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">enum Decision { YES, NO, MAYBE }
|
|
array Decisions = [3] Decision default Decision.MAYBE</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Here we have used the enum type as the type of the array member,
|
|
and we have used the value <code>Decision.MAYBE</code> as the default
|
|
value of an array member.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Defining-Enums_Numeric-Values">7.3. Numeric Values</h3>
|
|
<div class="paragraph">
|
|
<p>As in C and C++, each enumerated constant has an associated
|
|
numeric value.
|
|
By default, the values start at zero and go up by one.
|
|
For example, in the enum <code>Decision</code> defined above,
|
|
<code>YES</code> has value 0, <code>NO</code> has value 1, and <code>MAYBE</code> has value 2.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>You can optionally assign explicit values to the enumerated
|
|
constants.
|
|
To do this, you write an equals sign and an expression after
|
|
each of the constant definitions.
|
|
Here is an example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">enum E { A = 1, B = 2, C = 3 }</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>This definition creates an enum type <code>E</code> with three enumerated constants <code>E.A</code>,
|
|
<code>E.B</code>, and <code>E.C</code>. The constants have 1, 2, and 3 as their associated numeric
|
|
values.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>If you provide an explicit numeric value for any of the enumerated constants,
|
|
then you must do so for all of them.
|
|
For example, this code is not allowed:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp"># Error: cannot provide a value for just one enumerated constant
|
|
enum E { A = 1, B, C }</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Further, the values must be distinct.
|
|
For example, this code is not allowed, because
|
|
the enumerated constants <code>A</code> and <code>B</code> both have the value 2:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp"># Error: enumerated constant values must be distinct
|
|
enum E { A = 2, B = 1 + 1 }</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>You may convert an enumerated constant to its associated numeric value.
|
|
For example, this code is allowed:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">enum E { A = 5 }
|
|
constant c = E.A + 1</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The constant <code>c</code> has the value 6.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>However, you may not convert a numeric value to an enumerated constant.
|
|
This is for type safety reasons: a value of enumeration type should have
|
|
one of the numeric values specified in the type.
|
|
Assigning an arbitrary number to an enum type would violate this rule.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For example, this code is not allowed:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">enum E { A, B, C }
|
|
# Error: cannot assign integer 10 to type E
|
|
array A = [3] E default 10</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Defining-Enums_The-Representation-Type">7.4. The Representation Type</h3>
|
|
<div class="paragraph">
|
|
<p>Each enum definition has an associated <strong>representation type</strong>.
|
|
This is the primitive integer type used to represent the numeric
|
|
values associated with the enumerated constants when generating code.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>If you don’t specify a representation type, then the default
|
|
type is <code>I32</code>.
|
|
For example, in the enumerations defined in the previous sections,
|
|
the representation type is <code>I32</code>.
|
|
To specify an explicit representation type, you write it after
|
|
the enum name, separated from the name by a colon, like this:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">enum Small : U8 { A, B, C }</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>This code defines an enum <code>Small</code> with three enumerated constants
|
|
<code>Small.A</code>, <code>Small.B</code>, and <code>Small.C</code>.
|
|
Each of the enumerated constants is represented as a <code>U8</code> value
|
|
in C++.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Defining-Enums_The-Default-Value">7.5. The Default Value</h3>
|
|
<div class="paragraph">
|
|
<p>Every type in FPP has an associated default value.
|
|
For enum types, if you don’t specify a default value explicitly,
|
|
then the default value is the first enumerated constant
|
|
in the definition.
|
|
For example, given this definition</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">enum Decision { YES, NO, MAYBE }</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>the default value for the type <code>Decision</code> is <code>Decision.YES</code>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>That may be too permissive, say if <code>Decision</code> represents
|
|
a decision on a bank loan.
|
|
Perhaps the default value should be <code>Decision.MAYBE</code>.
|
|
To specify an explicit default value, write the keyword <code>default</code>
|
|
and the enumerated constant after the enumerated constant
|
|
definitions, like this:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">enum Decision { YES, NO, MAYBE } default MAYBE</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Notice that when using the constant <code>MAYBE</code> as a default value, we
|
|
don’t need to qualify it with the enum name, because the
|
|
use appears inside the enum where it is defined.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="Defining-Ports">8. Defining Ports</h2>
|
|
<div class="sectionbody">
|
|
<div class="paragraph">
|
|
<p>A <strong>port definition</strong> defines an F Prime port.
|
|
In F Prime, a port specifies the endpoint of a connection
|
|
between two component instances.
|
|
Components are the basic units of FSW function in F Prime
|
|
and are described in the
|
|
<a href="#Defining-Components">next section</a>.
|
|
A port definition specifies (1) the name of the port, (2) the type of the data
|
|
carried
|
|
on the port, and (3) an optional return type.</p>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Defining-Ports_Port-Names">8.1. Port Names</h3>
|
|
<div class="paragraph">
|
|
<p>The simplest port definition consists of the keyword <code>port</code> followed
|
|
by a name.
|
|
For example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">port P</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>This code defines a port named <code>P</code> that carries no data and returns
|
|
no data.
|
|
This kind of port can be useful for sending or receiving a triggering event.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Defining-Ports_Formal-Parameters">8.2. Formal Parameters</h3>
|
|
<div class="paragraph">
|
|
<p>More often, a port will carry data.
|
|
To specify the data, you write <strong>formal parameters</strong>
|
|
enclosed in parentheses.
|
|
The formal parameters of a port definition are similar to the formal parameters
|
|
of a function in a programming
|
|
language: each one has a name and a type, and you may write
|
|
zero or more of them.
|
|
For example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">port P1() # Zero parameters; equivalent to port P1
|
|
port P2(a: U32) # One parameter
|
|
port P3(a: I32, b: F32, c: string) # Three parameters</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The type of a formal parameter may be any valid type, including an
|
|
array type, a struct type, an enum type, or an abstract type.
|
|
For example, here is some code that defines an enum type <code>E</code> and
|
|
and abstract type <code>T</code>, and then uses those types in the
|
|
formal parameters of a port:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">enum E { A, B }
|
|
type T
|
|
port P(e: E, t: T)</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The formal parameters form an
|
|
<a href="#Defining-Constants_Multiple-Definitions-and-Element-Sequences">element
|
|
sequence</a> in which the optional terminating punctuation is a comma. As usual
|
|
for element sequences, you can omit the comma and use a newline instead. So,
|
|
for example, we can write the definition shown above in this alternate way:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">enum E { A, B }
|
|
type T
|
|
port P(
|
|
e: E
|
|
t: T
|
|
)</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Defining-Ports_Handler-Functions">8.3. Handler Functions</h3>
|
|
<div class="paragraph">
|
|
<p>As discussed further in the sections on
|
|
<a href="#Defining-Components">defining components</a>
|
|
and
|
|
<a href="#Defining-Component-Instances">instantiating components</a>,
|
|
when constructing an F Prime application, you
|
|
instantiate port definitions as <strong>output ports</strong> and
|
|
<strong>input ports</strong> of component instances.
|
|
Output ports are connected to input ports.
|
|
For each output port <code>pOut</code> of a component instance <code>c1</code>,
|
|
there is a corresponding auto-generated function that the
|
|
implementation of <code>c1</code> can call in order to <strong>invoke</strong> <code>pOut</code>.
|
|
If <code>pOut</code> is connected to an input
|
|
port <code>pIn</code> of component instance <code>c2</code>, then invoking <code>pOut</code> runs a
|
|
<strong>handler function</strong> <code>pIn_handler</code> associated with <code>pIn</code>.
|
|
The handler function is part of the implementation of the component
|
|
<code>C2</code> that <code>c2</code> instantiates.
|
|
In this way <code>c1</code> can send data to <code>c2</code> or request
|
|
that <code>c2</code> take some action.
|
|
Each input port may be <strong>synchronous</strong> or <strong>asynchronous</strong>.
|
|
A synchronous invocation directly calls a handler function.
|
|
An asynchronous invocation calls a short function that puts
|
|
a message on a queue for later dispatch.
|
|
Dispatching the message calls the handler function.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Translating handler functions:</strong>
|
|
In FPP, each output port <code>pOut</code> or input port <code>pIn</code> has a <strong>port type</strong>.
|
|
This port type refers to an FPP port definition <code>P</code>.
|
|
In the C++ translation, the signature of a handler function
|
|
<code>pIn_handler</code> for <code>pIn</code>
|
|
is derived from <code>P</code>.
|
|
In particular, the C++ formal parameters of <code>pIn_handler</code>
|
|
correspond to the
|
|
<a href="#Defining-Ports_Formal-Parameters">FPP formal parameters</a> of <code>P</code>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>When generating the handler function <code>pIn_handler</code>, F
|
|
Prime translates each formal parameter <em>p</em> of <code>P</code> in the following way:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>If <em>p</em> carries a
|
|
<a href="#Defining-Constants_Expressions_Primitive-Values">primitive value</a>,
|
|
then <em>p</em> is translated to a C++ value parameter.</p>
|
|
</li>
|
|
<li>
|
|
<p>Otherwise <em>p</em> is translated to a C++ <code>const</code> reference
|
|
parameter.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>As an example, suppose that <code>P</code> looks like this:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">type T
|
|
port P(a: U32, b: T)</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Then the signature of <code>pIn_handler</code> might look like this:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="cpp">virtual void pIn_handler(U32 a, const T& b);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Calling handler functions:</strong>
|
|
Suppose again that output port <code>pOut</code> of component instance <code>c1</code>
|
|
is connected to input port <code>pIn</code> of component instance <code>c2</code>.
|
|
Suppose that the implementation of <code>c1</code> invokes <code>pOut</code>.
|
|
What happens next depends on whether <code>pIn</code> is synchronous
|
|
or asynchronous.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>If <code>pIn</code> is synchronous, then the invocation is a direct
|
|
call of the <code>pIn</code> handler function.
|
|
Any value parameter is passed by copying the value on
|
|
the stack.
|
|
Any <code>const</code> reference parameter provides a reference to
|
|
the data passed in by <code>c1</code> at the point of invocation.
|
|
For example, if <code>pIn</code> has the port type <code>P</code> shown above,
|
|
then the implementation of <code>pIn_handler</code> might look like this:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="cpp">// Assume pIn is a synchronous input port
|
|
void C2::pIn_handler(U32 a, const T& b) {
|
|
// a is a local copy of a U32 value
|
|
// b is a const reference to T data passed in by c1
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Usually the <code>const</code> reference is what you want, for efficiency reasons.
|
|
If you want a local copy of the data, you can make one.
|
|
For example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="cpp">// Copy b into b1
|
|
auto b1 = b</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Now <code>b1</code> has the same data that the parameter <code>b</code> would have
|
|
if it were passed by value.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>If <code>pIn</code> is asynchronous, then the invocation does not
|
|
call the handler directly. Instead, it calls
|
|
a function that puts a message on a queue.
|
|
The handler is called when the message is dispatched.
|
|
At this point, any value parameter is passed by
|
|
copying the value out of the queue and onto the stack.
|
|
Any <code>const</code> reference parameter is passed by
|
|
(1) copying data out of the queue and onto the stack and
|
|
(2) then providing a <code>const</code> reference to the data on the stack.
|
|
For example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="cpp">// Assume pIn is an asynchronous input port
|
|
void C2::pIn_handler(U32 a, const T& b) {
|
|
// a is a local copy of a U32 value
|
|
// b is a const reference to T data copied across the queue
|
|
// and owned by this component
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Note that unlike in the synchronous case, const references
|
|
in parameters refer to data owned by the handler
|
|
(residing on the handler stack),
|
|
not data owned by the invoking component.
|
|
Note also that the values must be small enough to permit
|
|
placement on the queue and on the stack.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>If you want the handler and the invoking component to share data
|
|
passed in as a parameter, or if the data values are too large
|
|
for the queue and the stack, then you can use a data structure
|
|
that contains a pointer or a reference as a member.
|
|
For example, <code>T</code> could have a member that stores a reference
|
|
or a pointer to shared data.
|
|
F Prime provides a type <code>Fw::Buffer</code> that stores a
|
|
pointer to a shared data buffer.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Passing string arguments:</strong>
|
|
Suppose that an input port <code>pIn</code> of a component instance <code>c</code>
|
|
has port type <code>P</code>.
|
|
If <code>P</code> has a formal parameter of type <code>string</code>,
|
|
the corresponding formal parameter in the handler for <code>pIn</code> is
|
|
a constant reference to <code>Fw::StringBase</code>, which is an abstract
|
|
supertype of all F Prime string types.
|
|
The string object referred to depends on whether <code>pIn</code> is synchronous
|
|
or asynchronous:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>If <code>pIn</code> is synchronous, then the reference is
|
|
to the string object used in the invocation.
|
|
In this case the size specified in the <code>string</code> type is ignored.
|
|
For example, if a string of length 80 is bound to a port parameter
|
|
whose type is <code>string size 40</code>, the reference is to the original
|
|
string of length 80.</p>
|
|
</li>
|
|
<li>
|
|
<p>If <code>pIn</code> is asynchronous, then the reference is to
|
|
a string object on the stack whose size is bounded by
|
|
the size named in the port parameter.
|
|
For example, if a string of length 80 is bound to a port parameter
|
|
whose type is <code>string size 40</code>, then the reference is to a string
|
|
consisting of the first 40 characters of the original string.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Defining-Ports_Reference-Parameters">8.4. Reference Parameters</h3>
|
|
<div class="paragraph">
|
|
<p>You may write the keyword <code>ref</code> in front of any formal parameter <em>p</em>
|
|
of a port definition.
|
|
Doing this specifies that <em>p</em> is a <strong>reference parameter</strong>.
|
|
Each reference parameter in an FPP port becomes a mutable
|
|
C++ reference at the corresponding place in the
|
|
handler function signature.
|
|
For example, suppose this port definition</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">type T
|
|
port P(a: U32, b: T, ref c: T)</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>appears as the type of an input port <code>pIn</code> of component <code>C</code>.
|
|
The generated code for <code>C</code> might contain a handler function with a
|
|
signature like this:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="cpp">virtual void pIn_handler(U32 a, const T& b, T& c);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Notice that parameter <code>b</code> is not marked <code>ref</code>, so it is
|
|
translated to <code>const T& b</code>, as discussed in the previous section.
|
|
On the other hand, parameter <code>c</code> is marked ref, so it
|
|
is translated to <code>T& c</code>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Apart from the mutability, a reference parameter has the same
|
|
behavior as a <code>const</code> reference parameter, as described in
|
|
the previous section.
|
|
In particular:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>When <code>pIn</code> is synchronous, a reference parameter <em>p</em> of <code>pIn_handler</code>
|
|
refers to the data passed in by the invoking component.</p>
|
|
</li>
|
|
<li>
|
|
<p>When <code>pIn</code> is asynchronous, a reference parameter <em>p</em> of <code>pIn_handler</code>
|
|
refers to data copied out of the queue and placed on the local stack.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The main reason to use a reference parameter is to
|
|
return a value to the sender by storing it through
|
|
the reference.
|
|
We discuss this pattern in the section on
|
|
<a href="#Defining-Ports_Returning-Values">returning values</a>.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Defining-Ports_Returning-Values">8.5. Returning Values</h3>
|
|
<div class="paragraph">
|
|
<p>Optionally, you can give a port definition a return type.
|
|
To do this you write an arrow <code>-></code> and a type
|
|
after the name and the formal parameters, if any.
|
|
For example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">type T
|
|
port P1 -> U32 # No parameters, returns U32
|
|
port P2(a: U32, b: F32) -> T # Two parameters, returns T</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Invoking a port with a return type is like calling a function with
|
|
a return value.
|
|
Such a port may be used only in a synchronous context (i.e.,
|
|
as a direct function call, not as a message placed
|
|
on a concurrent queue).</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In a synchronous context only, <code>ref</code> parameters provide another way to return
|
|
values on the port,
|
|
by assigning to the reference, instead of executing a C++ <code>return</code> statement.
|
|
As an example, consider the following two port definitions:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">type T
|
|
port P1 -> T
|
|
port P2(ref t: T)</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The similarities and differences are as follows:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>Both <code>P1</code> and <code>P2</code> must be used in a synchronous context,
|
|
because each returns a <code>T</code> value.</p>
|
|
</li>
|
|
<li>
|
|
<p>In the generated C++ code,</p>
|
|
<div class="olist loweralpha">
|
|
<ol class="loweralpha" type="a">
|
|
<li>
|
|
<p>The function for invoking <code>P1</code>
|
|
has no arguments and returns a <code>T</code> value.
|
|
A handler associated with <code>P1</code> returns a value of type <code>T</code>
|
|
via the C++ <code>return</code> statement.
|
|
For example:</p>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>T C::p1In_handler() {
|
|
...
|
|
return T(1, 2, 3);
|
|
}</pre>
|
|
</div>
|
|
</div>
|
|
</li>
|
|
<li>
|
|
<p>The function for invoking <code>P1</code> has one argument <code>t</code>
|
|
of type <code>T&</code>.
|
|
A handler associated with <code>P2</code> returns a value of type <code>T</code>
|
|
by updating the reference <code>t</code> (assigning to it, or updating
|
|
its fields).
|
|
For example:</p>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>void C::p2In_handler(T& t) {
|
|
...
|
|
t = T(1, 2, 3);
|
|
}</pre>
|
|
</div>
|
|
</div>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The second way may involve less copying of data.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Finally, there can be any number of reference parameters,
|
|
but at most one return value.
|
|
So if you need to return multiple values on a port, then reference
|
|
parameters can be useful.
|
|
As an example, the following port attempts to update a result
|
|
value of type <code>U32</code>.
|
|
It does this via reference parameter.
|
|
It also returns a status value indicating whether the update
|
|
was successful.</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">enum Status { SUCCEED, FAIL }
|
|
port P(ref result: U32) -> Status</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>A handler for <code>P</code> might look like this:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>Status C::pIn_handler(U32& result) {
|
|
Status status = Status::FAIL;
|
|
if (...) {
|
|
...
|
|
result = ...
|
|
status = Status::SUCCEED;
|
|
}
|
|
return status;
|
|
}</pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Defining-Ports_Pass-by-Reference-Semantics">8.6. Pass-by-Reference Semantics</h3>
|
|
<div class="paragraph">
|
|
<p>Whenever a C++ formal parameter <em>p</em> enables sharing of data between
|
|
an invoking component and a handler function <code>pIn_handler</code>,
|
|
we say that <em>p</em> has <strong>pass-by-reference semantics</strong>.
|
|
Pass-by-reference semantics occurs in the following cases:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p><em>p</em> has reference or <code>const</code> reference type,
|
|
and the port <code>pIn</code> is synchronous.</p>
|
|
</li>
|
|
<li>
|
|
<p><em>p</em> has a type <em>T</em> that contains a pointer or
|
|
a reference as a member.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>When using pass-by-reference semantics,
|
|
you must carefully manage the
|
|
use of the data to avoid concurrency bugs
|
|
such as data races.
|
|
This is especially true for references that can modify
|
|
shared data.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Except in special cases that require special expertise (e.g.,
|
|
the implementation of highly concurrent data structures),
|
|
you should enforce the rule that at most
|
|
one component may use any piece of data at any time.
|
|
In particular, if component <code>A</code> passes a reference to component <code>B</code>,
|
|
then component <code>A</code> should not use the reference while
|
|
component <code>B</code> is using it, and vice versa.
|
|
For example:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>Suppose component <code>A</code> owns some data <code>D</code> and passes a reference
|
|
to <code>D</code> via a synchronous port call to component <code>B</code>.
|
|
Suppose the port handler in component <code>B</code> uses the data but
|
|
does not store the reference, so that when the handler exits,
|
|
the reference is lost.
|
|
This is a good pattern.
|
|
In this case, we may say that ownership of <code>D</code> resides in <code>A</code>, temporarily
|
|
goes to <code>B</code> for the life of the handler, and goes back to <code>A</code>
|
|
when the handler exits.
|
|
Because the port call is synchronous, the handler in <code>B</code>
|
|
never runs concurrently with any code in <code>A</code> that uses <code>D</code>.
|
|
So at most one of <code>A</code> or <code>B</code> uses <code>D</code> at any time.</p>
|
|
</li>
|
|
<li>
|
|
<p>Suppose instead that the handler in <code>B</code> stores the reference
|
|
into a member variable, so that the reference
|
|
persists after the handler exits.
|
|
If this happens, then you should make sure that <code>A</code> cannot use
|
|
<code>D</code> unless and until <code>B</code> passes ownership of <code>D</code> to <code>A</code> and vice versa.
|
|
For example, you could use state variables of enum type in <code>A</code> and in <code>B</code> to
|
|
track ownership, and you could have a port invocation from <code>A</code> to <code>B</code> pass the
|
|
reference and transfer ownership from <code>A</code> to <code>B</code> and vice versa.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Defining-Ports_Annotating-a-Port-Definition">8.7. Annotating a Port Definition</h3>
|
|
<div class="paragraph">
|
|
<p>A port definition is an
|
|
<a href="#Writing-Comments-and-Annotations_Annotations">annotatable element</a>.
|
|
Each formal parameter is also an annotatable element.
|
|
Here is an example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ Pre annotation for port P
|
|
port P(
|
|
@ Pre annotation for parameter a
|
|
a: U32
|
|
@ Pre annotation for parameter b
|
|
b: F32
|
|
)</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="Defining-State-Machines">9. Defining State Machines</h2>
|
|
<div class="sectionbody">
|
|
<div class="paragraph">
|
|
<p>A <strong>hierarchical state machine</strong> (state machine for short)
|
|
is a software subsystem that specifies the following:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>A set of <strong>states</strong> that the system can be in.
|
|
The states can be arranged in a hierarchy (i.e.,
|
|
states may have substates).</p>
|
|
</li>
|
|
<li>
|
|
<p>A set of <strong>transitions</strong> from one state to another that
|
|
occur under specified conditions.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>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.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In FPP there are two ways to define a state machine:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>An <strong>external</strong> state machine definition is like
|
|
an <a href="#Defining-Types_Abstract-Type-Definitions">abstract type definition</a>:
|
|
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.</p>
|
|
</li>
|
|
<li>
|
|
<p>An <strong>internal</strong> state machine definition is like an
|
|
<a href="#Defining-Types_Array-Type-Definitions">array type definition</a>
|
|
or
|
|
<a href="#Defining-Types_Struct-Type-Definitions">struct type definition</a>:
|
|
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.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The following subsections describe both kinds of state machine
|
|
definitions.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>State machine definitions may appear at the top level or inside a
|
|
<a href="#Defining-Modules">module definition</a>.
|
|
A state machine definition is an
|
|
<a href="#Writing-Comments-and-Annotations_Annotations">annotatable element</a>.
|
|
Once you define a state machine, you can
|
|
<a href="#Defining-Components_State-Machine-Instances">instantiate it as part of a component</a>.
|
|
The component can then send the signals that cause the state
|
|
transitions.
|
|
The component also provides the functions that are called when
|
|
the state machine does actions and evaluates guards.</p>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Defining-State-Machines_Writing-a-State-Machine-Definition">9.1. Writing a State Machine Definition</h3>
|
|
<div class="paragraph">
|
|
<p><strong>External state machines:</strong>
|
|
To define an external state machine, you write the keywords
|
|
<code>state</code> <code>machine</code> followed by an identifier, which is the
|
|
name of the state machine:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">state machine M</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>This code defines an external state machine with name <code>M</code>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>When you define an external state machine <code>M</code>, you must provide
|
|
an implementation for <code>M</code>, as discussed in the section
|
|
on <a href="#Writing-C-Plus-Plus-Implementations_Implementing-External-State-Machines">implementing external state machines</a>.
|
|
The external implementation must have a header file <code>M.hpp</code>
|
|
located in the same directory as the FPP file where
|
|
the state machine <code>M</code> is defined.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Internal state machines:</strong>
|
|
In the following subsections, we explain how to define internal
|
|
state machines in FPP.
|
|
The behavior of these state machines closely follows the behavior
|
|
described for state machines in the
|
|
<a href="https://www.omg.org/spec/UML/2.5.1/PDF">Universal Modeling Language (UML)</a>.
|
|
UML is a graphical language and FPP is a textual language,
|
|
but each of the concepts in the FPP language is motivated
|
|
by a corresponding UML concept.
|
|
FPP does not represent every aspect of UML state machines:
|
|
because our goal is to support embedded and flight software,
|
|
we focus on a subset of UML state machine behavior that is
|
|
(1) simple and unambiguous and (2) sufficient for embedded
|
|
applications that use F Prime.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In this manual, we focus on the syntax and high-level behavior
|
|
of FPP state machines.
|
|
For more details about the C++ code generation
|
|
for state machines, see the
|
|
<a href="https://fprime.jpl.nasa.gov/devel/docs/user-manual/framework/state-machines/">F
|
|
Prime design documentation</a>.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Defining-State-Machines_States-Signals-and-Transitions">9.2. States, Signals, and Transitions</h3>
|
|
<div class="paragraph">
|
|
<p>In this and the following sections, we explain how to define
|
|
internal state machines, i.e., state machines that are fully
|
|
specified in FPP.
|
|
In these sections, when we say “state machine,”
|
|
we mean an internal state machine.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>First we explain the concepts of states,
|
|
signals, and transitions.
|
|
These are the basic building blocks of FPP state machines.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Basic state machines:</strong>
|
|
The simplest state machine <em>M</em> that has any useful
|
|
behavior consists of the following:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>Several <strong>state definitions</strong>.
|
|
These define the states of <em>M</em>.</p>
|
|
</li>
|
|
<li>
|
|
<p>An <strong>initial transition specifier</strong>.
|
|
This specifies the state that an instance of <em>M</em> is in when it starts up.</p>
|
|
</li>
|
|
<li>
|
|
<p>One or more <strong>signal definitions</strong>.
|
|
The external environment (typically an F Prime component)
|
|
sends signals to instances of <em>M</em>.</p>
|
|
</li>
|
|
<li>
|
|
<p>One or more <strong>state transition specifiers</strong>.
|
|
These tell each instance of <em>M</em> what to do when it receives a signal.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Here is an example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ A state machine representing a device with on-off behavior
|
|
state machine Device {
|
|
|
|
@ A signal for turning the device on
|
|
signal cmdOn
|
|
|
|
@ A signal for turning the device off
|
|
signal cmdOff
|
|
|
|
@ The initial state is OFF
|
|
initial enter OFF
|
|
|
|
@ The ON state
|
|
state ON {
|
|
|
|
@ In the ON state, a cmdOff signal causes a transition to the OFF state
|
|
on cmdOff enter OFF
|
|
|
|
}
|
|
|
|
@ The OFF state
|
|
state OFF {
|
|
|
|
@ In the OFF state, a cmdOff signal causes a transition to the ON state
|
|
on cmdOn enter ON
|
|
|
|
}
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Here is the example represented graphically, as a UML state
|
|
machine:</p>
|
|
</div>
|
|
<div class="imageblock text-center">
|
|
<div class="content">
|
|
<img src="users-guide/diagrams/state-machine/Basic.png" alt="Device state machine" width="200">
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>This example defines a state machine <code>Device</code> that represents
|
|
a device with on-off behavior.
|
|
There are two states, <code>ON</code> and <code>OFF</code>.
|
|
The initial transition specifier <code>initial enter OFF</code>
|
|
says that the state machine is in state <code>OFF</code> when it starts up.
|
|
There are two signals: <code>cmdOn</code> for turning the device
|
|
on and <code>cmdOff</code> for turning the device off.
|
|
There are two state transition specifiers:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>A specifier that says to enter state <code>OFF</code>
|
|
on receiving the <code>cmdOff</code> signal in state <code>ON</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>A specifier that says to enter state <code>ON</code>
|
|
on receiving the <code>cmdOn</code> signal in state <code>OFF</code>.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In general, a state transition specifier causes a transition
|
|
from the state <em>S</em> in which it appears to the state <em>S'</em> that
|
|
appears after the keyword <code>enter</code>.
|
|
We say that <em>S</em> is the <strong>source</strong> of the transition,
|
|
and <em>S'</em> is the <strong>target</strong> of the transition.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>If a state machine instance receives a signal <em>s</em>, and it is
|
|
in a state <em>S</em> that specifies no behavior for signal <em>s</em>
|
|
(i.e., there is no transition with source <em>S</em> and signal <em>s</em>),
|
|
then nothing happens.
|
|
In the example above, if the state machine receives signal
|
|
<code>cmdOn</code> in state <code>ON</code>
|
|
or signal <code>cmdOff</code> in state <code>OFF</code>, then it takes no action.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Rules for defining state machines:</strong>
|
|
Each state machine definition must conform to the following rules:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>A state machine definition and each of its members is an
|
|
<a href="#Writing-Comments-and-Annotations_Annotations">annotatable element</a>.
|
|
For example, you can annotate the <code>Device</code> state machine as shown above.
|
|
The members of a state machine definition form an
|
|
<a href="#Defining-Constants_Multiple-Definitions-and-Element-Sequences">element sequence</a> with a semicolon as the optional
|
|
terminating punctuation.
|
|
The same rules apply to the members of a state definition.</p>
|
|
</li>
|
|
<li>
|
|
<p>Each state machine definition must have exactly one
|
|
initial transition specifier that names a state of
|
|
the state machine.
|
|
For example, if we deleted the initial transition specifier
|
|
from the example above and passed the result through
|
|
<code>fpp-check</code>, an error would occur.</p>
|
|
</li>
|
|
<li>
|
|
<p>Every state definition must be reachable from the initial
|
|
transition specifier or from a state transition specifier.
|
|
For example, if we deleted the state transition specifier
|
|
in the state <code>ON</code> from the example above and passed
|
|
the result through <code>fpp-check</code>, an error would occur.
|
|
In this case, there would be no way to reach the <code>ON</code> state.</p>
|
|
</li>
|
|
<li>
|
|
<p>Every state name must be unique, and every signal name
|
|
must be unique.</p>
|
|
</li>
|
|
<li>
|
|
<p>Each state may have at most one state transition specifier
|
|
for each signal <em>s</em>.
|
|
For example, if we added another transition to state <code>ON</code>
|
|
on signal <code>cmdOff</code>, the FPP analyzer would report an error.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Simple state definitions:</strong>
|
|
If a state definition has no transitions, then you can omit
|
|
the braces.
|
|
For example, here is a revised version of the <code>Device</code> state
|
|
machine that has an off-on transition but no on-off transition:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ A state machine representing a device with on-only behavior
|
|
state machine Device {
|
|
|
|
@ A signal for turning the device on
|
|
signal cmdOn
|
|
|
|
@ The initial state is OFF
|
|
initial enter OFF
|
|
|
|
@ The ON state
|
|
state ON
|
|
|
|
@ The OFF state
|
|
state OFF {
|
|
|
|
@ In the OFF state, a cmdOff signal causes a transition to the ON state
|
|
on cmdOn enter ON
|
|
|
|
}
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Notice that state <code>ON</code> has a simple definition with no curly braces.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Defining-State-Machines_Actions">9.3. Actions</h3>
|
|
<div class="paragraph">
|
|
<p>An <strong>action</strong> is a function that a state machine calls at a
|
|
specified point in its behavior.
|
|
In the FPP model, actions are abstract;
|
|
in the C++ back end they become pure virtual functions that
|
|
you implement.
|
|
When a state machine instance calls the function associated with
|
|
an action <em>A</em>, we say that it <strong>does</strong> <em>A</em>.</p>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-State-Machines_Actions_Actions-in-Transitions">9.3.1. Actions in Transitions</h4>
|
|
<div class="paragraph">
|
|
<p>To define an action, you write the keyword <code>action</code> followed
|
|
by the name of the action.
|
|
As with <a href="#Defining-State-Machines_States-Signals-and-Transitions">signals</a>,
|
|
every action name must be unique.
|
|
To do an action, you write the keyword <code>do</code>
|
|
followed by a list of action names enclosed in curly braces.
|
|
You can do this in an initial transition specifier or in a
|
|
state transition specifier.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>As an example, here is the <code>Device</code> state machine from the
|
|
previous section, with actions added:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ A state machine representing a device with on-off behavior,
|
|
@ with actions on transitions
|
|
state machine Device {
|
|
|
|
@ Initial action 1
|
|
action initialAction1
|
|
|
|
@ Initial action 2
|
|
action initialAction2
|
|
|
|
@ An action on the transition from OFF to ON
|
|
action offOnAction
|
|
|
|
@ An action on the transition from ON to OFF
|
|
action onOffAction
|
|
|
|
@ A signal for turning the device on
|
|
signal cmdOn
|
|
|
|
@ A signal for turning the device off
|
|
signal cmdOff
|
|
|
|
@ The initial state is OFF
|
|
@ Before entering the initial state, do initialAction1 and then initialAction2
|
|
initial do { initialAction1, initialAction2 } enter OFF
|
|
|
|
@ The ON state
|
|
state ON {
|
|
|
|
@ In the ON state, a cmdOff signal causes a transition to the OFF state
|
|
@ Before entering the OFF state, do onOffAction
|
|
on cmdOff do { onOffAction } enter OFF
|
|
|
|
}
|
|
|
|
@ The OFF state
|
|
state OFF {
|
|
|
|
@ In the OFF state, a cmdOff signal causes a transition to the ON state
|
|
@ Before entering the ON state, do offOnAction
|
|
on cmdOn do { offOnAction } enter ON
|
|
|
|
}
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Here is the graphical representation:</p>
|
|
</div>
|
|
<div class="imageblock text-center">
|
|
<div class="content">
|
|
<img src="users-guide/diagrams/state-machine/ActionsInTransitions.png" alt="Device state machine with actions on transitions" width="500">
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In this example there are four actions:
|
|
<code>initialAction1</code>, <code>initialAction2</code>, <code>offOnAction</code>, and <code>onOffAction</code>.
|
|
The behavior of each of these actions is specified in the C++
|
|
implementation; for example, each could emit an
|
|
<a href="#Defining-Components_Events">F Prime event</a>.
|
|
The state machine has the following behavior:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>On startup, do <code>initialAction1</code>, do <code>initialAction2</code>, and
|
|
enter the <code>OFF</code> state.</p>
|
|
</li>
|
|
<li>
|
|
<p>In state <code>OFF</code>, on receiving the <code>cmdOn</code> signal, do
|
|
<code>offOnAction</code> and enter the <code>ON</code> state.</p>
|
|
</li>
|
|
<li>
|
|
<p>In state <code>ON</code>, on receiving the <code>cmdOff</code> signal, do
|
|
<code>onOffAction</code> and enter the <code>OFF</code> state.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>When multiple actions appear in an action list, as in the initial
|
|
transition specifier shown above, the actions occur in the order
|
|
listed.
|
|
Each action list is an
|
|
<a href="#Defining-Constants_Multiple-Definitions-and-Element-Sequences">element sequence</a> with a comma as the optional
|
|
terminating punctuation.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-State-Machines_Actions_Entry-and-Exit-Actions">9.3.2. Entry and Exit Actions</h4>
|
|
<div class="paragraph">
|
|
<p>In addition to doing actions on transitions, a state machine
|
|
can do actions on entry to or exit from a state.
|
|
To do actions like this, you write <strong>state entry specifiers</strong>
|
|
and <strong>state exit specifiers</strong>.
|
|
For example, here is the <code>Device</code> state machine from
|
|
the previous section, with state entry and exit specifiers
|
|
added to the <code>ON</code> and <code>OFF</code> states:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ A state machine representing a device with on-off behavior,
|
|
@ with actions on transitions and on state entry and exit
|
|
state machine Device {
|
|
|
|
@ Initial action 1
|
|
action initialAction1
|
|
|
|
@ Initial action 2
|
|
action initialAction2
|
|
|
|
@ An action on the transition from OFF to ON
|
|
action offOnAction
|
|
|
|
@ An action on the transition from ON to OFF
|
|
action onOffAction
|
|
|
|
@ An action on entering the ON state
|
|
action enterOn
|
|
|
|
@ An action on exiting the ON state
|
|
action exitOn
|
|
|
|
@ An action on entering the OFF state
|
|
action enterOff
|
|
|
|
@ An action on exiting the OFF state
|
|
action exitOff
|
|
|
|
@ A signal for turning the device on
|
|
signal cmdOn
|
|
|
|
@ A signal for turning the device off
|
|
signal cmdOff
|
|
|
|
@ The initial state is OFF
|
|
@ Before entering the initial state, do initialAction1 and then initialAction2
|
|
initial do { initialAction1, initialAction2 } enter OFF
|
|
|
|
@ The ON state
|
|
state ON {
|
|
|
|
@ On entering the ON state, do enterOn
|
|
entry do { enterOn }
|
|
|
|
@ In the ON state, a cmdOff signal causes a transition to the OFF state
|
|
@ Before entering the OFF state, do offAction
|
|
on cmdOff do { onOffAction } enter OFF
|
|
|
|
@ On exiting the ON state, do exitOn
|
|
exit do { exitOn }
|
|
|
|
}
|
|
|
|
@ The OFF state
|
|
state OFF {
|
|
|
|
@ On entering the OFF state, do enterOff
|
|
entry do { enterOff }
|
|
|
|
@ In the OFF state, a cmdOff signal causes a transition to the ON state
|
|
@ Before entering the ON state, do onAction
|
|
on cmdOn do { offOnAction } enter ON
|
|
|
|
@ On exiting the OFF state, do exitOff
|
|
exit do { exitOff }
|
|
|
|
}
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Here is the graphical representation:</p>
|
|
</div>
|
|
<div class="imageblock text-center">
|
|
<div class="content">
|
|
<img src="users-guide/diagrams/state-machine/EntryAndExitActions.png" alt="Device state machine with entry and exit actions" width="500">
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>As with actions on transitions, each entry or exit specifier names
|
|
a list of actions, and the actions are done in the order named.
|
|
The entry actions are done just before entering the state,
|
|
and the exit actions are done just before exiting the state.
|
|
For example, if the state machine is in state <code>OFF</code> and it
|
|
receives a <code>cmdOn</code> signal, then it runs the following behavior,
|
|
in the following order:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>Exit state <code>OFF</code>. On exit, do <code>exitOff</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>Transition from <code>OFF</code> to <code>ON</code>. On the transition, do <code>offOnAction</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>Enter state <code>ON</code>. On entry, do <code>enterOn</code>.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Each state may have at most one entry specifier and at most one
|
|
exit specifier.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-State-Machines_Actions_Typed-Signals-and-Actions">9.3.3. Typed Signals and Actions</h4>
|
|
<div class="paragraph">
|
|
<p>Optionally, signals and actions may carry data values.
|
|
To specify that a signal or action carries a data value,
|
|
you write a colon and a data type at the end of the
|
|
signal or action specifier.
|
|
For example, here is a <code>Device</code> state machine in which
|
|
the <code>cmdOn</code> signal and the <code>offOnAction</code> each carries
|
|
a <code>U32</code> counter value:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ A state machine representing a device with on-off behavior,
|
|
@ with actions on transitions
|
|
state machine Device {
|
|
|
|
@ An action on the transition from OFF to ON
|
|
@ The value counts the number of times this action has occurred
|
|
action offOnAction: U32
|
|
|
|
@ A signal for turning the device on
|
|
@ The value counts the number of times this signal has been received
|
|
signal cmdOn: U32
|
|
|
|
@ A signal for turning the device off
|
|
signal cmdOff
|
|
|
|
@ The initial state is OFF
|
|
initial enter OFF
|
|
|
|
@ The ON state
|
|
state ON {
|
|
|
|
@ In the ON state, a cmdOff signal causes a transition to the OFF state
|
|
on cmdOff enter OFF
|
|
|
|
}
|
|
|
|
@ The OFF state
|
|
state OFF {
|
|
|
|
@ In the OFF state, a cmdOff signal causes a transition to the ON state
|
|
@ Before entering the ON state, do offOnAction, passing the data from
|
|
@ the signal into the action
|
|
on cmdOn do { offOnAction } enter ON
|
|
|
|
}
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>When you send the <code>cmdOn</code> signal to an instance of
|
|
this state machine, you must provide a <code>U32</code> value.
|
|
When the state machine is in the <code>OFF</code> state and it receives
|
|
this signal, it does action <code>offOnAction</code> as shown.
|
|
The function that defines the behavior of <code>offOnAction</code> has
|
|
a single argument of type <code>U32</code>.
|
|
The value provided when the signal is sent is passed as the
|
|
argument to this function.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Here are the rules for writing typed signals and actions:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>When you do an action that has a type, a value
|
|
compatible with that type must be available.
|
|
For example, we can’t do the <code>offOnAction</code> in the <code>cmdOff</code> transition shown
|
|
above, because no <code>U32</code>
|
|
value is available there.
|
|
Similarly, no action done in a
|
|
<a href="#Defining-State-Machines_Actions_Entry-and-Exit-Actions">state entry or exit specifier</a> may carry a value,
|
|
because no values are available on entry to or exit
|
|
from a state.</p>
|
|
</li>
|
|
<li>
|
|
<p>The type that appears in a signal or an action can
|
|
be any FPP type.
|
|
In the example above we used a simple <code>U32</code> type;
|
|
we could have used, for example, a struct or array type.
|
|
In particular, you can use a struct type to send several
|
|
data values, with each value represented as a member
|
|
of the struct.</p>
|
|
</li>
|
|
<li>
|
|
<p>When doing an action with a value, you don’t have to
|
|
make the types exactly match.
|
|
For example, you are permitted to pass a <code>U16</code> value
|
|
to an action that requires a <code>U32</code> value.
|
|
However, the type of the value must be convertible to the type
|
|
specified in the action.
|
|
The type conversion rules are spelled out in full in
|
|
<em>The FPP Language Specification</em>.
|
|
In general, the analyzer will allow a conversion if it
|
|
can be safely done for all values of the original type.</p>
|
|
</li>
|
|
<li>
|
|
<p>If an action <em>A</em> does not carry any value, then you
|
|
can do <em>A</em> in any context, even if a value is available there.
|
|
For example, in the code shown above, the <code>cmdOn</code>
|
|
transition could do some other action that carries no value.
|
|
In this case the value is ignored when doing the action.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-State-Machines_Actions_Atomicity-of-Signal-Handling">9.3.4. Atomicity of Signal Handling</h4>
|
|
<div class="paragraph">
|
|
<p>When an FPP state machine receives a signal, the handling of
|
|
that signal is <strong>atomic</strong>.
|
|
That means that signals may be received concurrently,
|
|
but they are handled one by one.
|
|
For example, this sequence of events cannot occur:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>In state <em>S</em><sub>1</sub>, signal <em>s</em><sub>1</sub> is handled, causing an action <em>A</em> and a
|
|
transition to state <em>S</em><sub>2</sub>.</p>
|
|
</li>
|
|
<li>
|
|
<p>After doing action <em>A</em>, but before entering state <em>S</em><sub>2</sub>,
|
|
a signal <em>s</em><sub>2</sub> is handled.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Instead, <em>s</em><sub>2</sub> will be handled either before the handling of <em>s</em><sub>1</sub>
|
|
starts or after the handling of <em>s</em><sub>1</sub> is complete.
|
|
This atomicity guarantee is achieved by putting the signals on
|
|
an input queue and using the queue to serialize the signal handler
|
|
functions.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Because of the atomicity guarantee, the C++ implementation of an FPP state machine
|
|
can safely send a signal <em>s</em> as part of its implementation for an action <em>A</em>.
|
|
The action <em>A</em> will be run during the handling of a signal <em>s'</em>.
|
|
When <em>s'</em> is handled and <em>A</em> is run, <em>s</em> is placed on the queue.
|
|
After <em>s'</em> is complete, <em>s</em> is dispatched from the queue and handled.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For more details on sending signals to an FPP state machine, see the
|
|
<a href="https://fprime.jpl.nasa.gov/devel/docs/user-manual/framework/state-machines/">F
|
|
Prime design documentation</a>.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Defining-State-Machines_More-on-State-Transitions">9.4. More on State Transitions</h3>
|
|
<div class="paragraph">
|
|
<p>In this section, we provide more details on how to write
|
|
<a href="#Defining-State-Machines_States-Signals-and-Transitions">state transitions</a>
|
|
in FPP state machines.</p>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-State-Machines_More-on-State-Transitions_Guarded-Transitions">9.4.1. Guarded Transitions</h4>
|
|
<div class="paragraph">
|
|
<p>Sometimes it is useful to specify that a transition should occur
|
|
only if a certain condition is true.
|
|
For example, you may want to turn on a device, but only if
|
|
it is safe to do so.
|
|
We call this kind of transition a <strong>guarded transition</strong>.
|
|
To specify this transition, you define a <strong>guard</strong>, which
|
|
is an abstract function that returns a Boolean value.
|
|
Then you use the guard in a transition.
|
|
Here is an example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ A device state machine with a guarded transition
|
|
state machine Device {
|
|
|
|
@ A guard for checking whether the device is in a safe state for power-on
|
|
guard powerOnIsSafe
|
|
|
|
@ A signal for turning the device on
|
|
signal cmdOn
|
|
|
|
@ A signal for turning the device off
|
|
signal cmdOff
|
|
|
|
@ The initial state is OFF
|
|
initial enter OFF
|
|
|
|
@ The ON state
|
|
state ON {
|
|
|
|
@ In the ON state, a cmdOff signal causes a transition to the OFF state
|
|
on cmdOff enter OFF
|
|
|
|
}
|
|
|
|
@ The OFF state
|
|
state OFF {
|
|
|
|
@ In the OFF state, a cmdOff signal causes a transition to the ON state
|
|
@ if powerOnIsSafe evaluates to true. Otherwise no transition occurs.
|
|
on cmdOn if powerOnIsSafe enter ON
|
|
|
|
}
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Here is the graphical representation:</p>
|
|
</div>
|
|
<div class="imageblock text-center">
|
|
<div class="content">
|
|
<img src="users-guide/diagrams/state-machine/GuardedTransitions.png" alt="Device state machine with a guarded transition" width="400">
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In this example, there is one guard, <code>powerOnIsSafe</code>.
|
|
The implementation of this function will return true
|
|
if it is safe to power on the device; otherwise it will
|
|
return false.
|
|
In state <code>OFF</code>, the transition on signal <code>cmdOn</code> is
|
|
now guarded: when the signal is received in this state,
|
|
the transition occurs if and only if <code>powerOnIsSafe</code>
|
|
evaluates to <code>true</code>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>As with actions, each guard must have a unique name.
|
|
Also as with actions, a guard can have a type; if it does,
|
|
the type must match the type of the signal at the point
|
|
where the guard is evaluated.
|
|
For example, here is a revised version of the previous
|
|
state machine that adds a value of type <code>DeviceStatus</code>
|
|
to the guard <code>powerOnIsSafe</code>:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ A type representing the status of a device
|
|
type DeviceStatus
|
|
|
|
@ A device state machine with a guarded transition
|
|
state machine Device {
|
|
|
|
@ A guard for checking whether the device is in a safe state for power-on
|
|
@ The DeviceStatus value provides the current device status
|
|
guard powerOnIsSafe: DeviceStatus
|
|
|
|
@ A signal for turning the device on
|
|
@ The DeviceStatus value provides the current device status
|
|
signal cmdOn: DeviceStatus
|
|
|
|
@ A signal for turning the device off
|
|
signal cmdOff
|
|
|
|
@ The initial state is OFF
|
|
initial enter OFF
|
|
|
|
@ The ON state
|
|
state ON {
|
|
|
|
@ In the ON state, a cmdOff signal causes a transition to the OFF state
|
|
on cmdOff enter OFF
|
|
|
|
}
|
|
|
|
@ The OFF state
|
|
state OFF {
|
|
|
|
@ In the OFF state, a cmdOff signal causes a transition to the ON state
|
|
@ if powerOnIsSafe evaluates to true. Otherwise no transition occurs.
|
|
on cmdOn if powerOnIsSafe enter ON
|
|
|
|
}
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>When you send the signal <code>cmdOn</code> to an instance of this state
|
|
machine, you must provide a value of type <code>DeviceStatus</code>.
|
|
When the state machine instance evaluates the guard <code>powerOnIsSafe</code>,
|
|
it passes in the value as an argument to the function.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-State-Machines_More-on-State-Transitions_Self-Transitions">9.4.2. Self Transitions</h4>
|
|
<div class="paragraph">
|
|
<p>When a state transition has the same state <em>S</em> as its source
|
|
and its target, and <em>S</em> has no substates, we call the transition
|
|
a <strong>self transition</strong>.
|
|
In this case the following behavior occurs:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>The state machine does the exit actions for <em>S</em>, if any.</p>
|
|
</li>
|
|
<li>
|
|
<p>The state machine does the actions specified in the transition, if any.</p>
|
|
</li>
|
|
<li>
|
|
<p>The state machine does the entry actions for <em>S</em>, if any.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Note that on a self transition, the state machine exits and
|
|
reenters <em>S</em>.
|
|
This behavior is a special case of a more general behavior that we will
|
|
discuss
|
|
<a href="#Defining-State-Machines_Hierarchy_Entry-and-Exit-Actions">below</a>
|
|
in connection with state hierarchy.
|
|
<a href="#Defining-State-Machines_Hierarchy_Directly-Related-States">Below</a>
|
|
we will also generalize the concept of a self transition to
|
|
the case of a state with substates.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>As an example, consider the following state machine:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ A state machine representing a device with on-off behavior,
|
|
@ with a self transition
|
|
state machine Device {
|
|
|
|
@ An action on entering the ON state
|
|
action enterOn
|
|
|
|
@ An action to perform on reset
|
|
action reset
|
|
|
|
@ An action on exiting the ON state
|
|
action exitOn
|
|
|
|
@ A signal for turning the device on
|
|
signal cmdOn
|
|
|
|
@ A signal for turning the device off
|
|
signal cmdOff
|
|
|
|
@ A signal for resetting the device
|
|
signal cmdReset
|
|
|
|
@ The initial state is OFF
|
|
@ Before entering the initial state, do initialAction1 and then initialAction2
|
|
initial enter OFF
|
|
|
|
@ The ON state
|
|
state ON {
|
|
|
|
@ On entering the ON state, do enterOn
|
|
entry do { enterOn }
|
|
|
|
@ In the ON state, a cmdOff signal causes a transition to the OFF state
|
|
on cmdOff enter OFF
|
|
|
|
@ In the ON state, a cmdReset signal causes a self transition
|
|
on cmdReset do { reset } enter ON
|
|
|
|
@ On exiting the ON state, do exitOn
|
|
exit do { exitOn }
|
|
|
|
}
|
|
|
|
@ The OFF state
|
|
state OFF {
|
|
|
|
@ In the OFF state, a cmdOff signal causes a transition to the ON state
|
|
on cmdOn enter ON
|
|
|
|
}
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Here is the graphical representation:</p>
|
|
</div>
|
|
<div class="imageblock text-center">
|
|
<div class="content">
|
|
<img src="users-guide/diagrams/state-machine/SelfTransitions.png" alt="Device state machine with a self transition" width="400">
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In this example, when the state machine is in the <code>ON</code> state and
|
|
it receives a <code>cmdReset</code> signal, the following behavior occurs:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>Do action <code>exitOn</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>Do action <code>reset</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>Do action <code>enterOn</code>.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-State-Machines_More-on-State-Transitions_Internal-Transitions">9.4.3. Internal Transitions</h4>
|
|
<div class="paragraph">
|
|
<p>An <strong>internal transition</strong> is like a
|
|
<a href="#Defining-State-Machines_More-on-State-Transitions_Self-Transitions">self transition</a>,
|
|
except that there is no exit and reentry.
|
|
To write an internal transition, you write the <code>on</code> and <code>do</code>
|
|
parts of a transition and omit the <code>enter</code> part.
|
|
For example, here is a device state machine with a <code>reset</code>
|
|
action that causes an internal transition:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ A state machine representing a device with on-off behavior,
|
|
@ with an internal transition
|
|
state machine Device {
|
|
|
|
@ An action on entering the ON state
|
|
action enterOn
|
|
|
|
@ An action to perform on reset
|
|
action reset
|
|
|
|
@ An action on exiting the ON state
|
|
action exitOn
|
|
|
|
@ A signal for turning the device on
|
|
signal cmdOn
|
|
|
|
@ A signal for turning the device off
|
|
signal cmdOff
|
|
|
|
@ A signal for resetting the device
|
|
signal cmdReset
|
|
|
|
@ The initial state is OFF
|
|
@ Before entering the initial state, do initialAction1 and then initialAction2
|
|
initial enter OFF
|
|
|
|
@ The ON state
|
|
state ON {
|
|
|
|
@ On entering the ON state, do enterOn
|
|
entry do { enterOn }
|
|
|
|
@ In the ON state, a cmdOff signal causes a transition to the OFF state
|
|
on cmdOff enter OFF
|
|
|
|
@ In the ON state, a cmdReset signal causes an internal transition
|
|
on cmdReset do { reset }
|
|
|
|
@ On exiting the ON state, do exitOn
|
|
exit do { exitOn }
|
|
|
|
}
|
|
|
|
@ The OFF state
|
|
state OFF {
|
|
|
|
@ In the OFF state, a cmdOff signal causes a transition to the ON state
|
|
on cmdOn enter ON
|
|
|
|
}
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Here is the graphical representation:</p>
|
|
</div>
|
|
<div class="imageblock text-center">
|
|
<div class="content">
|
|
<img src="users-guide/diagrams/state-machine/InternalTransitions.png" alt="Device state machine with an internal transition" width="200">
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In this example, when the state machine is in state <code>ON</code> and it
|
|
receives a <code>cmdReset</code> signal, it does the <code>reset</code> action and
|
|
performs no other behavior.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>An internal transition may have a guard.
|
|
For example, we could define a guard <code>resetIsSafe</code> and
|
|
write the internal transition as follows:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">on cmdReset if resetIsSafe do { reset }</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>As with other transitions, if the signal carries data, then
|
|
any actions and guards named in an internal transition may
|
|
carry data of a compatible type.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Defining-State-Machines_Choices">9.5. Choices</h3>
|
|
<div class="paragraph">
|
|
<p>A <strong>choice definition</strong> is a state machine member that
|
|
defines a branch point for one or more transitions.
|
|
In this section we explain how to write and use
|
|
choice definitions.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Basic choice definitions:</strong>
|
|
The most basic choice definition consists of the following:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>A name. Like a state name, this name can be the target
|
|
of a transition.</p>
|
|
</li>
|
|
<li>
|
|
<p>The name of a
|
|
<a href="#Defining-State-Machines_More-on-State-Transitions_Guarded-Transitions">guard</a>
|
|
<em>G</em>.
|
|
The evaluation of <em>G</em> selects which branch of the choice to
|
|
follow.</p>
|
|
</li>
|
|
<li>
|
|
<p>An <strong>if transition</strong> that specifies what to do if <em>G</em>
|
|
evaluates to <code>true</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>An <strong>else transition</strong> that specifies what to do if <em>G</em>
|
|
evaluates to <code>false</code>.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Each of the if and else transitions has a target,
|
|
which can be a state or a choice.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Here is an example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ A device state machine with a choice
|
|
state machine Device {
|
|
|
|
@ A guard for checking whether the device is in a safe state for power-on
|
|
guard powerOnIsSafe
|
|
|
|
@ A signal for turning the device on
|
|
signal cmdOn
|
|
|
|
@ A signal for turning the device off
|
|
signal cmdOff
|
|
|
|
@ A signal for resetting the device
|
|
signal cmdReset
|
|
|
|
@ The initial state is OFF
|
|
initial enter OFF
|
|
|
|
@ The ON state
|
|
state ON {
|
|
|
|
@ In the ON state, a cmdOff signal causes a transition to the OFF state
|
|
on cmdOff enter OFF
|
|
|
|
}
|
|
|
|
@ The OFF state
|
|
state OFF {
|
|
|
|
@ In the OFF state, a cmdOff signal causes a transition to the choice ON_OR_ERROR
|
|
on cmdOn enter ON_OR_ERROR
|
|
|
|
}
|
|
|
|
@ The ON_OR_ERROR choice
|
|
choice ON_OR_ERROR {
|
|
if powerOnIsSafe enter ON else enter ERROR
|
|
}
|
|
|
|
@ The ERROR state
|
|
state ERROR {
|
|
|
|
@ In the ERROR state, a cmdReset signal causes a transition to the OFF state
|
|
on cmdReset enter OFF
|
|
|
|
}
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Here is the graphical representation:</p>
|
|
</div>
|
|
<div class="imageblock text-center">
|
|
<div class="content">
|
|
<img src="users-guide/diagrams/state-machine/Choices.png" alt="Device state machine with a choice" width="450">
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>This version of the <code>Device</code> state machine has three states:
|
|
<code>ON</code>, <code>OFF</code>, and <code>ERROR</code>.
|
|
It also has a choice <code>ON_OR_ERROR</code>.
|
|
Each instance of the state machine has the following behavior:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>The initial state is <code>OFF</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>On receiving the signal <code>cmdOn</code> in the <code>OFF</code> state, it
|
|
enters the choice <code>ON_OR_ERROR</code>.
|
|
At that point, if <code>powerOnIsSafe</code> evaluates to <code>true</code>, then
|
|
it enters then <code>ON</code> state.
|
|
Otherwise it enters the <code>ERROR</code> state.</p>
|
|
</li>
|
|
<li>
|
|
<p>On receiving the signal <code>cmdReset</code> in the <code>ERROR</code> state,
|
|
it enters the <code>OFF</code> state.</p>
|
|
</li>
|
|
<li>
|
|
<p>On receiving the signal <code>cmdOff</code> in the <code>ON</code> state,
|
|
it enters the <code>OFF</code> state.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The text inside the curly braces of a choice consists
|
|
of a single line.
|
|
To write the text on multiple lines, you can use an
|
|
<a href="#Defining-Constants_Multiline-Definitions">explicit line
|
|
continuation</a>. For example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">choice ON_OR_ERROR {
|
|
if powerOnIsSafe \
|
|
enter ON \
|
|
else enter ERROR
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Initial transitions to choices:</strong>
|
|
An initial transition can go to a choice.
|
|
This pattern can express conditional behavior on state
|
|
machine startup.
|
|
For example, in the <code>Device</code> state machine shown above,
|
|
we could have the initial transition go to a choice
|
|
that checks a safety condition and then enters either
|
|
the <code>OFF</code> state or an error state.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Choice transitions to choices:</strong>
|
|
An if transition or an else transition of a choice
|
|
(or both) can enter another choice.
|
|
For example, it is permissible to write a chain of
|
|
choices like this:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">choice C {
|
|
if g1 enter C1 else enter C2
|
|
}
|
|
|
|
choice C1 {
|
|
if g2 enter S1 else enter S2
|
|
}
|
|
|
|
choice C2 {
|
|
if g3 enter S3 else enter S4
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Effectively this is a four-way choice; it is a two-way
|
|
choice, each branch of which leads to a two way choice.
|
|
By having the if or else branch of <code>C1</code> go directly
|
|
to a state, you could get a three-way choice.
|
|
And by adding more levels, you can create an <em>n</em> -way
|
|
choice for any <em>n</em>.
|
|
In this way you can use choices to create arbitrarily
|
|
complex branching patterns.
|
|
Note though, that it is usually a good idea not to have
|
|
more than a few levels of choices; otherwise the state
|
|
machine can be complex and hard to understand.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>The type associated with a choice:</strong>
|
|
Like initial transitions and state transitions, the
|
|
transitions out of a choice may
|
|
<a href="#Defining-State-Machines_Actions_Typed-Signals-and-Actions">carry a value</a>.
|
|
To determine whether the transitions of a choice <em>C</em> carry a value,
|
|
and if so what type that value has, we use the following rules:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>If any transition into <em>C</em> carries no value,
|
|
then transitions out of <em>C</em> carry no value.</p>
|
|
</li>
|
|
<li>
|
|
<p>Otherwise if all of the transitions into <em>C</em> carry
|
|
a value of the same type <em>T</em>, then each of the
|
|
transitions out of <em>C</em> carries a value of type <em>T</em>.</p>
|
|
</li>
|
|
<li>
|
|
<p>Otherwise if the incoming types can be resolved to
|
|
a common type <em>T</em>, then each of the transitions out of <em>C</em>
|
|
carries a value of type <em>T</em>.
|
|
The rules for resolving common types are given in
|
|
<em>The FPP Language Specification</em>.
|
|
The basic idea is to find a type to which it is always
|
|
safe to cast all the incoming types.</p>
|
|
</li>
|
|
<li>
|
|
<p>Otherwise the analyzer reports an error.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Actions in choice transitions:</strong>
|
|
You can do actions in choice transitions just as for
|
|
<a href="#Defining-State-Machines_Actions">initial transitions and
|
|
state transitions</a>.
|
|
For example, suppose we add the definitions of actions <code>onAction</code> and
|
|
<code>errorAction</code> to the <code>Device</code> state machine shown above.
|
|
Then we could revise the <code>ON_OR_ERROR</code> choice to read as follows:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">choice ON_OR_ERROR {
|
|
if powerOnIsSafe do onAction enter ON else do errorAction enter ERROR
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>As for other kinds of transitions, the actions done in choice
|
|
transitions may carry values.
|
|
If an action <em>A</em> done in a transition of a choice <em>C</em> carries a value,
|
|
the type named in the definition of <em>A</em> must be
|
|
compatible with the type associated with <em>C</em>, as discussed above.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Entry and exit actions:</strong>
|
|
When a transition <em>T</em> of a state machine <em>M</em>
|
|
goes to or from a choice, entry and
|
|
exit actions are done as if each choice were a state with
|
|
no entry and or exit actions.
|
|
For example, let <em>I</em> be an instance of <em>M</em>, and
|
|
suppose <em>I</em> is carrying out a transition <em>T</em>.</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>If <em>T</em> goes from a choice <em>C</em> to a state <em>S</em>,
|
|
then <em>I</em>
|
|
does the actions of <em>T</em> followed by the entry actions of <em>S</em>.</p>
|
|
</li>
|
|
<li>
|
|
<p>If <em>T</em> goes from a state <em>S</em> to a choice <em>C</em>,
|
|
then <em>I</em>
|
|
does the exit actions of <em>S</em> followed by the actions of <em>T</em>.</p>
|
|
</li>
|
|
<li>
|
|
<p>If <em>T</em> goes from a choice <em>C</em><sub>1</sub> to a choice <em>C</em><sub>2</sub>,
|
|
then <em>I</em> does the actions of <em>T</em>.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Rules for choice definitions:</strong>
|
|
Choice definitions must conform to the following rules:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>No state or choice may have the same name as any other
|
|
state or choice.</p>
|
|
</li>
|
|
<li>
|
|
<p>Every choice must be reachable from the initial transition
|
|
or from a state transition.</p>
|
|
</li>
|
|
<li>
|
|
<p>There may be no cycles of choice transitions.
|
|
For example, it is not permitted for a choice <code>C1</code> to
|
|
have a transition to a choice <code>C2</code> that has a transition
|
|
back to <code>C1</code>.
|
|
Nor is it permissible for <code>C1</code> to go to <code>C2</code>, <code>C2</code> to
|
|
go to <code>C3</code>, and <code>C3</code> to go to <code>C1</code>.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Defining-State-Machines_Hierarchy">9.6. Hierarchy</h3>
|
|
<div class="paragraph">
|
|
<p>As with UML state machines, FPP state machines can have <strong>hierarchy</strong>.
|
|
That is, we can do the following:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>Define states within other states.
|
|
When a state <em>T</em> is defined within a state <em>S</em>, <em>S</em> is called the
|
|
<strong>parent</strong> of <em>T</em>, and <em>T</em> is called a <strong>substate</strong> or <strong>child</strong> of <em>S</em>.</p>
|
|
</li>
|
|
<li>
|
|
<p>Define choices within states.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Using hierarchy, we can do the following:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>Group related substates under a single parent.
|
|
This grouping lets us express the state machine structure in a
|
|
disciplined and modular way.</p>
|
|
</li>
|
|
<li>
|
|
<p>Define behaviors of a parent state that are inherited
|
|
by its substates.
|
|
The parent behavior saves having to redefine the behavior for each
|
|
substate.</p>
|
|
</li>
|
|
<li>
|
|
<p>Control the way that entry and exit actions occur
|
|
when transitions cross state boundaries.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>A state machine with hierarchy is called a
|
|
<strong>hierarchical state machine</strong>.
|
|
In the following subsections, we explain how to define
|
|
hierarchical state machines in FPP.</p>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-State-Machines_Hierarchy_Substates">9.6.1. Substates</h4>
|
|
<div class="paragraph">
|
|
<p>In this section we explain how to define and use substates.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>An example:</strong>
|
|
Here is an example of a state machine with substates:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ A device state machine with substates
|
|
state machine Device {
|
|
|
|
@ A signal for turning the device on
|
|
signal cmdOn
|
|
|
|
@ A signal for turning the device off
|
|
signal cmdOff
|
|
|
|
@ A signal for indicating that the device is in an unsafe state
|
|
signal cmdUnsafe
|
|
|
|
@ A signal for indicating that the device is in a safe state
|
|
signal cmdSafe
|
|
|
|
@ The initial state is OFF
|
|
initial enter OFF
|
|
|
|
@ The ON state
|
|
state ON {
|
|
|
|
@ In the ON state, a cmdOff signal causes a transition to the OFF state
|
|
on cmdOff enter OFF
|
|
|
|
@ In the ON state, a cmdUnsafe signal causes a transition to OFF.UNSAFE
|
|
on cmdUnsafe enter OFF.UNSAFE
|
|
|
|
}
|
|
|
|
@ The OFF state
|
|
state OFF {
|
|
|
|
@ The initial state is SAFE
|
|
initial enter SAFE
|
|
|
|
@ The state OFF.SAFE
|
|
@ In this state, it is safe to turn on the device
|
|
state SAFE {
|
|
|
|
@ In the SAFE state, a cmdOff signal causes a transition to the ON state
|
|
on cmdOn enter ON
|
|
|
|
@ In the SAFE state, a cmdUnsafe signal causes a transition to the UNSAFE state
|
|
on cmdUnsafe enter UNSAFE
|
|
|
|
}
|
|
|
|
@ The state OFF.UNSAFE
|
|
@ In this state, it is not safe to turn on the device
|
|
state UNSAFE {
|
|
|
|
@ In the UNSAFE state, a cmdSafe signal causes a transition to the SAFE state
|
|
on cmdSafe enter SAFE
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Here is the graphical representation:</p>
|
|
</div>
|
|
<div class="imageblock text-center">
|
|
<div class="content">
|
|
<img src="users-guide/diagrams/state-machine/Substates.png" alt="Device state machine with substates" width="500">
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>This state machine has four states: <code>ON</code>, <code>OFF</code>, <code>OFF.SAFE</code>, and <code>OFF.UNSAFE</code>.
|
|
The last two states are substates of <code>OFF</code>.
|
|
Notice the following:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>The substates are defined syntactically within the parent state.</p>
|
|
</li>
|
|
<li>
|
|
<p>The full names of the substates are qualified by the name of the parent state.</p>
|
|
</li>
|
|
<li>
|
|
<p>Inside the scope of the parent state, you can refer
|
|
to the substates by the shorter name that omits the implied qualifier.
|
|
The way the qualification works for state names is identical to the
|
|
way it works for <a href="#Defining-Modules">module names</a>.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>An instance <em>m</em> of this state machine has the following behavior:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>When <em>m</em> starts up, it runs its initial transition specifier, just as for
|
|
<a href="#Defining-State-Machines_States-Signals-and-Transitions">a state machine
|
|
without hierarchy</a>.
|
|
The state machine enters state <code>OFF</code>.
|
|
<code>OFF</code> is a parent state, so it in turn has an initial transition
|
|
specifier which is run.
|
|
The state machine enters <code>OFF.SAFE</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>In state <code>ON</code>, the following behavior occurs:</p>
|
|
<div class="olist loweralpha">
|
|
<ol class="loweralpha" type="a">
|
|
<li>
|
|
<p>When <em>m</em> receives signal <code>cmdOff</code>, it enters state
|
|
<code>OFF</code>. This entry causes it to enter state <code>OFF.SAFE</code> as discussed above.</p>
|
|
</li>
|
|
<li>
|
|
<p>When <em>m</em> receives signal <code>cmdUnsafe</code>, it goes
|
|
directly to <code>OFF.UNSAFE</code>, bypassing the <code>OFF</code> state and its initial
|
|
transition.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
</li>
|
|
<li>
|
|
<p>In state <code>OFF.SAFE</code>, the following behavior occurs:</p>
|
|
<div class="olist loweralpha">
|
|
<ol class="loweralpha" type="a">
|
|
<li>
|
|
<p>When <em>m</em> receives signal <code>cmdOn</code>, it enters
|
|
the <code>ON</code> state.</p>
|
|
</li>
|
|
<li>
|
|
<p>When <em>m</em> receives signal <code>cmdUnsafe</code>, it
|
|
enters the <code>OFF.UNSAFE</code> state.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
</li>
|
|
<li>
|
|
<p>In state <code>OFF.UNSAFE</code>, when <em>m</em> receives signal
|
|
<code>cmdSafe</code>, it enters the <code>OFF.SAFE</code> state.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Rules for substates:</strong>
|
|
Here are the rules for defining substates:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>Each parent state <em>S</em> must have exactly one initial transition
|
|
specifier that enters a substate of <em>S</em>.</p>
|
|
</li>
|
|
<li>
|
|
<p>Each state, including parents and substates, must be reachable
|
|
from the initial transition of the state machine or from
|
|
a state transition.</p>
|
|
</li>
|
|
<li>
|
|
<p>Substates may themselves be parents (i.e., may have substates),
|
|
to any depth.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Rule 1 ensures that the final target of every transition,
|
|
after following all initial transition specifiers, is a
|
|
<strong>leaf state</strong>, i.e., a state that has no substates.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>The hierarchy tree:</strong>
|
|
When a state <em>S</em> is a parent of a state <em>S'</em>, we say that <em>S</em> is an
|
|
<strong>ancestor</strong> of <em>S'</em> in the state hierarchy.
|
|
We also say that <em>S</em> is an ancestor of <em>S'</em> if it is a parent of
|
|
an ancestor of <em>S'</em>.
|
|
For example, if <em>S</em> is a parent of a parent of <em>S'</em>, then
|
|
<em>S</em> is an ancestor of <em>S'</em>.
|
|
Note that a state is never an ancestor of itself.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>When a state <em>S</em> is a an ancestor of a state <em>S'</em>, we
|
|
say that <em>S'</em> is a <strong>descendant</strong> of <em>S</em>.
|
|
For example, <em>S'</em> is a descendant of <em>S</em> if <em>S'</em>
|
|
is a child of <em>S</em>, or if <em>S'</em> is a child of a child of
|
|
<em>S</em>.
|
|
Note that a state is never a descendant of itself.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In order to make the state hierarchy into a tree, we also
|
|
say that the entire state machine <em>M</em> is a parent of every top-level
|
|
state in the state machine.
|
|
This means that (1) <em>M</em> is an ancestor of every
|
|
state in <em>M</em> and (2) every state in <em>M</em> is a descendant of <em>M</em>.
|
|
We will say that the tree constructed in this way is the
|
|
<strong>hierarchy tree</strong> for <em>M</em>, and that each of <em>M</em> and every state
|
|
in <em>M</em> is a <strong>node</strong> in the hierarchy tree.
|
|
In particular, <em>M</em> is the root node of the hierarchy tree.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-State-Machines_Hierarchy_Inherited-Transitions">9.6.2. Inherited Transitions</h4>
|
|
<div class="paragraph">
|
|
<p>In general, when a transition <em>T</em> is defined in a parent state <em>S</em>,
|
|
<em>T</em> behaves as if it were defined in each of the
|
|
<a href="#Defining-State-Machines_Hierarchy_Substates">leaf states</a> that is a
|
|
<a href="#Defining-State-Machines_Hierarchy_Substates">descendant of <em>T</em></a>.
|
|
In this case we say that <em>T</em> is <strong>inherited</strong> by each of the leaf states.
|
|
There is an important exception to this rule:
|
|
When a state <em>S</em> defines a transition <em>T</em> on a signal <em>s</em>,
|
|
and a descendant <em>S'</em> of <em>S</em> defines another transition <em>T'</em>
|
|
on the same signal <em>s</em>, the behavior of <em>T'</em> takes precedence
|
|
over the inherited transition <em>T</em> in the behavior of <em>S'</em>.
|
|
This rule is called <strong>behavioral polymorphism</strong> for transitions.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Example:</strong>
|
|
Here is an example that illustrates inherited transitions
|
|
and behavioral polymorphism:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ A device state machine with inherited transitions and behavioral polymorphism
|
|
state machine Device {
|
|
|
|
@ A signal for turning the device on
|
|
signal cmdOn
|
|
|
|
@ A signal for turning the device off
|
|
signal cmdOff
|
|
|
|
@ A signal for indicating that the device is in an unsafe state
|
|
signal cmdUnsafe
|
|
|
|
@ A signal for indicating that the device is in a safe state
|
|
signal cmdSafe
|
|
|
|
@ The initial state is DEVICE
|
|
initial enter DEVICE
|
|
|
|
@ The DEVICE state
|
|
state DEVICE {
|
|
|
|
@ The initial state is OFF
|
|
initial enter OFF
|
|
|
|
@ In the DEVICE state, a cmdUnsafe signal causes a transition to OFF.UNSAFE
|
|
on cmdUnsafe enter OFF.UNSAFE
|
|
|
|
@ The ON state
|
|
state ON {
|
|
|
|
@ In the ON state, a cmdOff signal causes a transition to the OFF state
|
|
on cmdOff enter OFF
|
|
|
|
}
|
|
|
|
@ The OFF state
|
|
state OFF {
|
|
|
|
@ The initial state is SAFE
|
|
initial enter SAFE
|
|
|
|
@ The state OFF.SAFE
|
|
@ In this state, it is safe to turn on the device
|
|
state SAFE {
|
|
|
|
@ In the SAFE state, a cmdOff signal causes a transition to the ON state
|
|
on cmdOn enter ON
|
|
|
|
}
|
|
|
|
@ The state OFF.UNSAFE
|
|
@ In this state, it is not safe to turn on the device
|
|
state UNSAFE {
|
|
|
|
@ In the UNSAFE state, a cmdSafe signal causes a transition to the SAFE state
|
|
on cmdSafe enter SAFE
|
|
|
|
@ In the UNSAFE state, a cmdUnsafe signal causes no action
|
|
on cmdUnsafe do { }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Here is the graphical representation:</p>
|
|
</div>
|
|
<div class="imageblock text-center">
|
|
<div class="content">
|
|
<img src="users-guide/diagrams/state-machine/InheritedTransitions.png" alt="Device state machine with inherited transitions" width="600">
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Here we have rewritten the
|
|
<a href="#Defining-State-Machines_Hierarchy_Substates"><code>Device</code> state machine from the previous section</a>
|
|
so that all the states in that example are descendants of a single state
|
|
<code>DEVICE</code>.
|
|
By doing this, we can have a single transition out of <code>DEVICE</code> on signal
|
|
<code>cmdUnsafe</code>.
|
|
Before we had to write out the same transition twice,
|
|
once in the state <code>ON</code> and once in the state <code>OFF.SAFE</code>.
|
|
Here we can write the transition once in the ancestor state, and
|
|
it is inherited by all the descendants.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>There is one catch, though: in the previous example, we did not define
|
|
the transition on <code>cmdUnsafe</code> in the state <code>OFF.UNSAFE</code>.
|
|
Here, if we use inheritance in the obvious way, the transition will
|
|
be inherited by all the descendants of <code>DEVICE</code>, including <code>OFF.UNSAFE</code>,
|
|
so the behavior will not be exactly the same as for the previous
|
|
state machine.
|
|
This may not matter much in this example, but it would matter if the
|
|
the state <code>DEVICE.OFF.UNSAFE</code> had entry or exit actions; in this case
|
|
transition from <code>UNSAFE</code> to itself (which is a
|
|
<a href="#Defining-State-Machines_More-on-State-Transitions_Self-Transitions">self transition</a>)
|
|
would cause an exit from and reentry to the state, which we may not want.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>To remedy this situation, we use behavioral polymorphism.
|
|
In the state <code>DEVICE.OFF.UNSAFE</code>, we define an
|
|
<a href="#Defining-State-Machines_More-on-State-Transitions_Internal-Transitions">internal
|
|
transition</a>
|
|
that has an empty list of actions and so does nothing.
|
|
This transition overrides the transition provided in the ancestor state,
|
|
so it restores the behavior that, on receipt of the signal
|
|
<code>cmdUnsafe</code> in the state <code>DEVICE.OFF.UNSAFE</code>, nothing happens.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Syntactic and flattened state transitions:</strong>
|
|
Once we introduce substates and inheritance, it is useful to
|
|
distinguish <strong>syntactic state transitions</strong> from <strong>flattened state transitions</strong>.
|
|
A syntactic state transition is a state transition in the FPP source
|
|
for a state machine <em>M</em>.
|
|
A flattened state transition is a transition that results from
|
|
applying the rules for transition inheritance to a syntactic
|
|
state transition.
|
|
We say the transition is “flattened” because we create
|
|
it by moving the left side of the transition down to a leaf state.
|
|
This move flattens the hierarchy on the left
|
|
side of the transition.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>When there is no hierarchy, a syntactic transition from state
|
|
<em>S</em><sub>1</sub> to <em>S</em><sub>2</sub> generates exactly one flattened transition,
|
|
also from <em>S</em><sub>1</sub> to <em>S</em><sub>2</sub>.
|
|
Once we have hierarchy, however, syntactic and flattened
|
|
state transitions may be different.
|
|
For example, suppose that <em>S</em><sub>1</sub> is a parent state,
|
|
and let <em>T</em> be a syntactic transition from <em>S</em><sub>1</sub> to <em>S</em><sub>2</sub>.
|
|
Then for each descendant <em>L</em> of <em>S</em><sub>1</sub> that is a leaf state, there is a flattened
|
|
state transition from <em>L</em> to <em>S</em><sub>2</sub>.
|
|
Note in particular that whereas a syntactic state transition may
|
|
have a parent state as its source, a flattened state transition always
|
|
has a leaf state as its source.
|
|
This distinction between syntactic and flattened state transitions
|
|
will be useful when we discuss entry and exit actions
|
|
in the following sections.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Internal transitions:</strong>
|
|
<a href="#Defining-State-Machines_More-on-State-Transitions_Internal-Transitions">Internal transitions</a> are flattened and inherited like other transitions,
|
|
except that there is no target state.
|
|
When a parent state <em>S</em> defines an internal transition, the following occurs:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>There is one flattened transition for each leaf state that
|
|
that is a descendant of <em>S</em>.</p>
|
|
</li>
|
|
<li>
|
|
<p>The behavior of each flattened transition is to stay in <em>S</em>
|
|
and do the actions listed in the transition.
|
|
There is no state change, and no entry or exit actions are done.</p>
|
|
</li>
|
|
<li>
|
|
<p>As usual, any of these flattened transitions may be overridden
|
|
by behavioral polymorphism.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-State-Machines_Hierarchy_Entry-and-Exit-Actions">9.6.3. Entry and Exit Actions</h4>
|
|
<div class="paragraph">
|
|
<p>In previous sections on
|
|
<a href="#Defining-State-Machines_Actions_Entry-and-Exit-Actions">entry and exit actions</a> and on
|
|
<a href="#Defining-State-Machines_More-on-State-Transitions_Self-Transitions">self transitions</a>,
|
|
we explained the order in which actions occur during a transition between
|
|
states without hierarchy.
|
|
Each of the behaviors described there is a special case of a more general
|
|
behavior for state machines with hierarchy, which we now describe.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>General behavior:</strong>
|
|
Suppose, in the course of running an instance of a state machine <em>M</em>,
|
|
a <a href="#Defining-State-Machines_Hierarchy_Inherited-Transitions">flattened state transition</a> <em>T</em>
|
|
occurs from state <em>L</em> to state <em>S</em>.
|
|
By the definition of a flattened state transition, we know
|
|
that <em>L</em> is a leaf state.
|
|
When carrying out the transition <em>T</em>, the state machine instance will do
|
|
actions as follows:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>Compute the <strong>least common ancestor</strong> of <em>L</em> and <em>S</em>.
|
|
This is the unique node <em>N</em> of the <a href="#Defining-State-Machines_Hierarchy_Substates">hierarchy tree</a> of <em>M</em> such that (a) <em>N</em> is an ancestor of <em>L</em>,
|
|
(b) <em>N</em> is an ancestor of <em>S</em>, and (c) there is no node <em>N'</em>
|
|
that is a descendant of <em>N</em> and that satisfies properties (a) and (b).</p>
|
|
</li>
|
|
<li>
|
|
<p>Traverse the hierarchy tree upwards from <em>L</em> to <em>N</em>.
|
|
At each point where the traversal passes out of a state <em>S'</em>, in the
|
|
order of the traversal, do the exit actions of <em>S'</em>, if any.</p>
|
|
</li>
|
|
<li>
|
|
<p>Do the actions specified in <em>T</em>, if any.</p>
|
|
</li>
|
|
<li>
|
|
<p>Traverse the hierarchy tree downwards from <em>N</em> to <em>S</em>.
|
|
At each point where the traversal enters a state <em>S'</em>, in the
|
|
order of the traversal, do the entry actions of <em>S'</em>, if any.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For example, suppose that <em>M</em> has a state <em>A</em> with substates
|
|
<em>B</em> and <em>C</em>, <em>B</em> has substate <em>D</em>, and <em>C</em> has substate <em>E</em>.
|
|
Suppose that <em>T</em> goes from <em>D</em> to <em>E</em>.
|
|
Then least common ancestor is <em>A</em>, and the following actions
|
|
would be done, in the following order:
|
|
the exit actions of <em>D</em>, the exit actions of <em>B</em>,
|
|
the actions of <em>T</em>, the entry actions of <em>C</em>, and the
|
|
entry actions of <em>E</em>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Remember also that if <em>E</em> is not a leaf state, then <em>T</em> will
|
|
<a href="#Defining-State-Machines_Hierarchy_Substates">follow
|
|
one or more transitions to go to a leaf state</a>.
|
|
In this case, any actions specified in those transitions are
|
|
done as well,
|
|
after the transitions described above, and in the order that
|
|
the initial transitions are run.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Finally, the algorithm above is described in a way
|
|
that emphasizes ease of understanding.
|
|
As stated, it is inefficient because it
|
|
recomputes the least common ancestor every time a flattened state
|
|
transition occurs.
|
|
In fact all the sequences of exit and entry actions for flattened
|
|
state transitions can be computed before generating code, and
|
|
it is more efficient to do this.
|
|
This is how the FPP code generator works.
|
|
For more details, see the algorithm descriptions on the
|
|
<a href="https://github.com/nasa/fpp/wiki/Compute-Flattened-State-Transition-Map">FPP wiki</a>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>The special case of no hierarchy:</strong>
|
|
The general behavior described above agrees with the special-case
|
|
behavior that we described in the section on
|
|
<a href="#Defining-State-Machines_Actions_Entry-and-Exit-Actions">entry and exit actions for state machines without hierarchy</a>.
|
|
When a state machine <em>M</em> has no hierarchy, a every state transition <em>T</em>
|
|
is a flattened transition that goes from a leaf state <em>L</em> to a leaf
|
|
state <em>S</em>, both of which are children of <em>M</em> in the hierarchy tree.
|
|
So we always exit <em>L</em>, do the actions of <em>T</em>, and enter <em>S</em>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In particular,
|
|
the general behavior agrees with the behavior that we previously
|
|
described for
|
|
<a href="#Defining-State-Machines_More-on-State-Transitions_Self-Transitions">self transitions</a>.
|
|
When <em>L</em> and <em>S</em> are the same leaf state, the least common
|
|
ancestor of <em>L</em> and <em>S</em> is the parent <em>P</em> of <em>S</em>.
|
|
So we exit <em>S</em> to go up to <em>P</em>, do the actions of <em>T</em>, and
|
|
reenter <em>S</em>.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-State-Machines_Hierarchy_Directly-Related-States">9.6.4. Directly Related States</h4>
|
|
<div class="paragraph">
|
|
<p>Let <em>S</em><sub>1</sub> and <em>S</em><sub>2</sub> be states.
|
|
If <em>S</em><sub>1</sub> is equal to S<sub>2</sub>, or <em>S</em><sub>1</sub> is an ancestor of S<sub>2</sub>, or S<sub>2</sub>
|
|
is an ancestor of <em>S</em><sub>1</sub>, then we say that <em>S</em><sub>1</sub> and S<sub>2</sub> are
|
|
<strong>directly related</strong> in the hierarchy tree.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In this section we describe the behavior of transitions between
|
|
directly related states.
|
|
Each of the behaviors described below follows from the general behavior
|
|
presented in the previous section.
|
|
However, in some cases the behavior may be subtle or surprising.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Flattened transitions to ancestors:</strong>
|
|
When a transition <em>T</em> goes from a leaf state <em>L</em> to a state <em>A</em>
|
|
that is an ancestor of <em>L</em>, we call <em>T</em> a
|
|
<strong>flattened transition to an ancestor</strong>.
|
|
The least common ancestor
|
|
of <em>L</em> and <em>A</em> is the parent <em>P</em> of <em>A</em>.
|
|
Therefore the following behavior occurs:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>Do exit actions to get from <em>L</em> to <em>P</em>. The last actions will
|
|
be the exit actions of <em>A</em>, if any.</p>
|
|
</li>
|
|
<li>
|
|
<p>Do the actions of <em>T</em>, if any.</p>
|
|
</li>
|
|
<li>
|
|
<p>Do the entry actions of <em>A</em>, if any.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Syntactic transitions to ancestors:</strong>
|
|
Consider a state transition <em>T</em> of the form
|
|
<code>on</code> <em>s</em> <code>enter</code> <em>A</em> that is defined in the state <em>S</em>,
|
|
where <em>A</em> is an ancestor of <em>S</em>.
|
|
We call this kind of state transition a
|
|
<strong>syntactic transition to an ancestor</strong>.
|
|
If <em>S</em> is a leaf state, then it represents
|
|
a flattened transition to the ancestor <em>A</em>.
|
|
Otherwise it represents one flattened transition
|
|
to the ancestor <em>A</em> for each descendant of <em>S</em> that
|
|
is a leaf state.
|
|
Because of
|
|
<a href="#Defining-State-Machines_Hierarchy_Inherited-Transitions">behavioral polymorphism</a>, any of the flattened transitions may
|
|
be overridden.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Flattened transitions to self:</strong>
|
|
A <strong>flattened transition to self</strong> is a transition
|
|
from a leaf state <em>L</em> to itself.
|
|
This is what we previously called a
|
|
<a href="#Defining-State-Machines_More-on-State-Transitions_Self-Transitions">self
|
|
transition</a>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Syntactic transitions to self:</strong>
|
|
Consider a state transition <em>T</em> of the form
|
|
<code>on</code> <em>s</em> <code>enter</code> <em>S</em> that is defined in the state <em>S</em>.
|
|
In general we call this kind of state transition a
|
|
<strong>syntactic transition to self</strong>.
|
|
If <em>S</em> is a leaf state, then <em>T</em> a flattened
|
|
transition to self.
|
|
In particular, when there is no hierarchy, every syntactic
|
|
transition to self is a self transition.
|
|
If <em>S</em> is not a leaf state, then <em>T</em> is flattened
|
|
to one or more transitions from leaf states <em>L</em> that are
|
|
descendants of <em>S</em>.
|
|
Each of these transitions is a flattened transition
|
|
to the ancestor <em>S</em>.
|
|
Because of
|
|
<a href="#Defining-State-Machines_Hierarchy_Inherited-Transitions">behavioral polymorphism</a>, any of the flattened transitions may
|
|
be overridden.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Flattened transitions to descendants:</strong>
|
|
In theory, a <strong>flattened transition to a descendant</strong> would
|
|
be a transition from a leaf node <em>L</em> to a descendant <em>D</em> of <em>L</em>.
|
|
However, leaf nodes have no descendants, so no such transition
|
|
is possible.
|
|
We include the category for completeness.
|
|
It has no members.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Syntactic transitions to descendants:</strong>
|
|
Consider a state transition <em>T</em> of the form
|
|
<code>on</code> <em>s</em> <code>enter</code> <em>D</em> that is defined in the state <em>S</em>,
|
|
where <em>D</em> is a descendant of <em>S</em>.
|
|
We call this kind of state transition a
|
|
<strong>syntactic transition to a descendant</strong>.
|
|
By symmetry with syntactic transitions to ancestors,
|
|
you might expect that the first behavior when
|
|
making such a transition is to exit and reenter <em>S</em>.
|
|
However, this is not what happens.
|
|
Instead, <em>T</em> represents one flattened transition
|
|
from each leaf state that is a descendant of <em>S</em>.
|
|
The flattened transitions have the following properties:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>If <em>D</em> is a leaf state, then the flattened
|
|
transition out of <em>D</em> (and only that transition)
|
|
is a flattened transition to self.</p>
|
|
</li>
|
|
<li>
|
|
<p>Otherwise (a) none of the flattened transitions
|
|
is a flattened transition to self, and (b) the
|
|
flattened transitions out of the descendants of <em>D</em>
|
|
are flattened transitions to the ancestor <em>D</em>.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In either case, because of
|
|
<a href="#Defining-State-Machines_Hierarchy_Inherited-Transitions">behavioral polymorphism</a>, any of the flattened transitions may
|
|
be overridden.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-State-Machines_Hierarchy_Choices">9.6.5. Choices</h4>
|
|
<div class="paragraph">
|
|
<p>Like state definitions, choice definitions are hierarchical.
|
|
That is, you may define a choice inside a state.
|
|
The names of choices are qualified by the enclosing
|
|
state names
|
|
<a href="#Defining-State-Machines_Hierarchy_Substates">as for the
|
|
names of substates</a>.
|
|
For example, you can write this:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">state machine M {
|
|
...
|
|
state S {
|
|
...
|
|
choice C { ... }
|
|
...
|
|
}
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The dots represent omitted text needed to make the state machine valid.
|
|
In this example, the qualified name of the choice is <code>S.C</code>.
|
|
Inside state <code>S</code>, you can refer to the choice as <code>S.C</code> or <code>C</code>.
|
|
Outside state <code>S</code>, you must refer to it as <code>S.C</code>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Initial transitions to choices:</strong>
|
|
When an initial transition <em>I</em> goes to a choice <em>C</em>,
|
|
<em>C</em> and <em>I</em> must have the same parent <em>P</em> in the
|
|
<a href="#Defining-State-Machines_Hierarchy_Substates">hierarchy tree</a>.
|
|
In addition, each transition out of <em>C</em> must go to a state
|
|
or choice with parent <em>P</em>; and if it goes
|
|
to a choice, then each transition out of that choice must
|
|
go to a state or choice with parent <em>P</em>, and so forth.
|
|
Another way to say this is that (since no cycles of transitions
|
|
through choices are allowed) each transition
|
|
path out of <em>I</em> must go through zero or more choices with parent <em>P</em>
|
|
to a state with parent <em>P</em>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For example, this state machine is allowed:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">state machine ValidInitialChoice {
|
|
|
|
guard g
|
|
|
|
initial enter S1
|
|
|
|
state S1 {
|
|
|
|
@ This initial transition is valid: C, S2, and S3 all have parent S1
|
|
initial enter C
|
|
|
|
choice C { if g enter S2 else enter S3 }
|
|
|
|
state S2
|
|
|
|
state S3
|
|
|
|
}
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>But this one is not:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">state machine InvalidInitialChoice {
|
|
|
|
guard g
|
|
|
|
initial enter S1
|
|
|
|
state S1 {
|
|
|
|
@ This initial transition is invalid: C has parent S1,
|
|
@ but S2 and S3 have parent InvalidInitialChoice
|
|
initial enter C
|
|
|
|
choice C { if g enter S2 else enter S3 }
|
|
|
|
}
|
|
|
|
state S2
|
|
|
|
state S3
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Entry and exit actions:</strong>
|
|
As in the <a href="#Defining-State-Machines_Choices">non-hierarchical case</a>,
|
|
when a transition <em>T</em> of a state machine <em>M</em>
|
|
goes to or from a choice, entry and
|
|
exit actions occur as if each choice were a leaf state with
|
|
no entry or exit actions.
|
|
For example, suppose that <em>M</em> has a state <em>S</em> with substates
|
|
<em>A</em> and <em>B</em>, <em>A</em> has a choice <em>C</em>, and <em>B</em> has substate <em>B'</em>.
|
|
Suppose that <em>T</em> goes from <em>C</em> to <em>B'</em>.
|
|
Then least common ancestor is <em>S</em>, and the following actions
|
|
would be done, in the following order:
|
|
the exit actions of <em>A</em>, the actions of <em>T</em>, the entry actions of <em>B</em>, and the
|
|
entry actions of <em>B'</em>.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="Defining-Components">10. Defining Components</h2>
|
|
<div class="sectionbody">
|
|
<div class="paragraph">
|
|
<p>In F Prime, the <strong>component</strong> is the basic unit of FSW function.
|
|
An F Prime component is similar to a class in an object-oriented language.
|
|
An F Prime FSW application is divided into several
|
|
<strong>component instances</strong>, each of which instantiates a component.
|
|
The component instances communicate by sending and receiving
|
|
invocations on their
|
|
<a href="#Defining-Ports">ports</a>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In F Prime, there are three kinds of components:
|
|
active, queued, and passive.
|
|
An active component has a thread of control
|
|
and a message queue.
|
|
A queued component has a message queue, but no thread
|
|
of control; control runs on another thread, such as
|
|
a rate group thread.
|
|
A passive component has no thread of control and no
|
|
message queue; it is like a non-threaded function library.</p>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Defining-Components_Component-Definitions">10.1. Component Definitions</h3>
|
|
<div class="paragraph">
|
|
<p>An FPP <strong>component definition</strong> defines an F Prime component.
|
|
To write a component definition, you write the following:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>The component kind: one of <code>active</code>, <code>passive</code>,
|
|
or <code>queued</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>The keyword <code>component</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>The <a href="#Defining-Constants_Names">name</a> of the component.</p>
|
|
</li>
|
|
<li>
|
|
<p>A sequence of <strong>component members</strong> enclosed in curly braces
|
|
<code>{</code> …​ <code>}</code>.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>As an example, here is a passive component <code>C</code> with no members:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ An empty passive component
|
|
passive component C {
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>A component definition and each of its members is an
|
|
<a href="#Writing-Comments-and-Annotations_Annotations">annotatable element</a>.
|
|
For example, you can annotate the component as shown above.
|
|
The members of a component form an
|
|
<a href="#Defining-Constants_Multiple-Definitions-and-Element-Sequences">element sequence</a> with a semicolon as the optional
|
|
terminating punctuation.
|
|
The following sections describe the available component members
|
|
except for importing port interfaces, which we describe in
|
|
<a href="#Defining-and-Using-Port-Interfaces_Using-Port-Interfaces-in-Interface-Definitions">a separate section</a>.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Defining-Components_Port-Instances">10.2. Port Instances</h3>
|
|
<div class="paragraph">
|
|
<p>A <strong>port instance</strong> is a component member that specifies an instance of an FPP
|
|
<a href="#Defining-Ports">port</a> used by the instances of the component.
|
|
Component instances use their port instances to communicate
|
|
with other component instances.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>A port instance instantiates a port.
|
|
The port definition provides information common to all uses of the port, such as
|
|
the kind of data carried on the port.
|
|
The port instance provides use-specific information, such
|
|
as the name of the instance and the direction of invocation
|
|
(input or output).</p>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Components_Port-Instances_Basic-Port-Instances">10.2.1. Basic Port Instances</h4>
|
|
<div class="paragraph">
|
|
<p>The simplest port instance specifies a kind, a name, and a type.
|
|
The kind is one of the following:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p><code>async</code> <code>input</code>: Input to this component that arrives on a message queue, to
|
|
be dispatched on this component’s thread (if this component is active)
|
|
or on the thread of another port invocation (if this component is queued).</p>
|
|
</li>
|
|
<li>
|
|
<p><code>sync</code> <code>input</code>: Input that invokes a handler defined in this component,
|
|
and run on the thread of the caller.</p>
|
|
</li>
|
|
<li>
|
|
<p><code>guarded</code> <code>input</code>: Similar to sync input, but the handler is
|
|
guarded by a mutual exclusion lock.</p>
|
|
</li>
|
|
<li>
|
|
<p><code>output</code>: Output transmitted by this component.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The name is the name of the port instance.
|
|
The type refers to a <a href="#Defining-Ports">port definition</a>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>As an example, here is a passive component <code>F32Adder</code> that
|
|
adds two <code>F32</code> values and produces an <code>F32</code> value.</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ A port for carrying an F32 value
|
|
port F32Value(value: F32)
|
|
|
|
@ A passive component for adding two F32 values
|
|
passive component F32Adder {
|
|
|
|
@ Input 1
|
|
sync input port f32ValueIn1: F32Value
|
|
|
|
@ Input 2
|
|
sync input port f32ValueIn2: F32Value
|
|
|
|
@ Output
|
|
output port f32ValueOut: F32Value
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>There are two sync input port instances and one output port
|
|
instance.
|
|
The kind appears first, followed by the keyword <code>port</code>, the port instance
|
|
name, a colon, and the type.
|
|
Each port instance is an
|
|
<a href="#Writing-Comments-and-Annotations_Annotations">annotatable element</a>,
|
|
so you can annotate the instances as shown.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>As another example, here is an active version of <code>F32Adder</code>
|
|
with <code>async</code> input ports:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ A port for carrying an F32 value
|
|
port F32Value(value: F32)
|
|
|
|
@ An active component for adding two F32 values
|
|
active component ActiveF32Adder {
|
|
|
|
@ Input 1
|
|
async input port f32ValueIn1: F32Value
|
|
|
|
@ Input 2
|
|
async input port f32ValueIn2: F32Value
|
|
|
|
@ Output
|
|
output port f32ValueOut: F32Value
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In each case, the adding is done in the target language.
|
|
For example, in the C++ implementation, you would generate a
|
|
base class with a virtual handler function, and then override that virtual
|
|
function in a derived class that you write.
|
|
For further details about implementing F Prime components, see the
|
|
<a href="https://fprime.jpl.nasa.gov/devel/docs/user-manual/">F Prime User Manual</a>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Note on terminology:</strong> As explained above, there is a technical
|
|
distinction between a <em>port type</em> (defined outside any component, and providing
|
|
the type of a port instance)
|
|
and a <em>port instance</em> (specified inside a component and instantiating
|
|
a port type).
|
|
However, it is sometimes useful to refer to a port instance with
|
|
the shorter term “port” when there is no danger of confusion.
|
|
We will do that in this manual.
|
|
For example, we will say that the <code>F32Adder</code> component has three
|
|
ports: two async input ports of type <code>F32Value</code> and one output port
|
|
of type <code>F32Value</code>.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Components_Port-Instances_Rules-for-Port-Instances">10.2.2. Rules for Port Instances</h4>
|
|
<div class="paragraph">
|
|
<p>The port instances appearing in a component definition must
|
|
satisfy certain rules.
|
|
These rules ensure that the FPP model makes sense.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>First, no passive component may have an <code>async</code> <code>input</code>
|
|
port.
|
|
This is because a passive component has no message queue,
|
|
so asynchronous input is not possible.
|
|
As an example, if we modify the input ports of our <code>F32Adder</code>
|
|
to make them <code>async</code>, we get an error.</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">port F32Value(value: F32)
|
|
|
|
# Error: Passive component may not have async input
|
|
passive component ErroneousF32Adder {
|
|
|
|
async input port f32ValueIn1: F32Value
|
|
|
|
async input port f32ValueIn2: F32Value
|
|
|
|
output port f32ValueOut: F32Value
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Try presenting this code to <code>fpp-check</code> and observe what happens.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Second, an active or queued component <em>must</em> have asynchronous input.
|
|
That means it must have at least one async input port;
|
|
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 <code>ActiveF32Adder</code>
|
|
to make them <code>sync</code>, we get an error, because
|
|
there is no async input.</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">port F32Value(value: F32)
|
|
|
|
# Error: Active component must have async input
|
|
active component ErroneousActiveF32Adder {
|
|
|
|
sync input port f32ValueIn1: F32Value
|
|
|
|
sync input port f32ValueIn2: F32Value
|
|
|
|
output port f32ValueOut: F32Value
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Third, a port type appearing in an <code>async</code> <code>input</code> port
|
|
may not have a return type.
|
|
This is because returning a value
|
|
makes sense only for synchronous input.
|
|
As an example, this component definition is illegal:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">port P -> U32
|
|
|
|
active component Error {
|
|
|
|
# Error: port instance p: P is async input and
|
|
# port P has a return type
|
|
async input port p: P
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Components_Port-Instances_Arrays-of-Port-Instances">10.2.3. Arrays of Port Instances</h4>
|
|
<div class="paragraph">
|
|
<p>When you specify a port instance as part of an FPP component, you
|
|
are actually specifying an <em>array</em> of port instances.
|
|
Each instance has a <strong>port number</strong>, where the port numbers start at zero
|
|
and go up by one at each successive element.
|
|
(Another way to say this is that the port numbers are the array indices,
|
|
and the indices start at zero.)</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>If you don’t specify a size for the array, as shown in
|
|
the previous sections, then the array has size one, and there is a single port
|
|
instance with port number zero.
|
|
Thus a port instance specifier with no array size acts like a singleton
|
|
element.
|
|
Alternatively, you can specify an explicit array size.
|
|
You do that by writing an <a href="#Defining-Constants_Expressions">expression</a>
|
|
enclosed in square brackets <code>[</code> …​ <code>]</code> denoting the size (number of elements)
|
|
of the array.
|
|
The size expression must evaluate to a numeric value.
|
|
As with
|
|
<a href="#Defining-Types_Array-Type-Definitions_Writing-an-Array-Type-Definition">array type definitions</a>,
|
|
the size goes before the element type.
|
|
As an example, here is another version of the <code>F32Adder</code> component, this time
|
|
using a single array of two input ports instead of two named ports.</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ A port for carrying an F32 value
|
|
port F32Value(value: F32)
|
|
|
|
@ A passive component for adding two F32 values
|
|
passive component F32Adder {
|
|
|
|
@ Inputs 0 and 1
|
|
sync input port f32ValueIn: [2] F32Value
|
|
|
|
@ Output
|
|
output port f32ValueOut: F32Value
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Components_Port-Instances_Priority">10.2.4. Priority</h4>
|
|
<div class="paragraph">
|
|
<p>For <code>async</code> <code>input</code> ports, you may specify a priority.
|
|
The priority specification is not allowed for other kinds of ports.
|
|
To specify a priority, you write the keyword <code>priority</code> and an
|
|
expression that evaluates to a numeric value after the port type.
|
|
As an example, here is a modified version of the <code>ActiveF32Adder</code>
|
|
with specified priorities:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ A port for carrying an F32 value
|
|
port F32Value(value: F32)
|
|
|
|
@ An active component for adding two F32 values
|
|
@ Uses specified priorities
|
|
active component ActiveF32Adder {
|
|
|
|
@ Input 1 at priority 10
|
|
async input port f32ValueIn1: F32Value priority 10
|
|
|
|
@ Input 2 at priority 20
|
|
async input port f32ValueIn2: F32Value priority 20
|
|
|
|
@ Output
|
|
output port f32ValueOut: F32Value
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>If an <code>async</code> <code>input</code> port has no specified priority, then the
|
|
translator uses a default priority.
|
|
The precise meaning of the default priority and of the numeric priorities is
|
|
implementation-specific.
|
|
In general the priorities regulate the order in which elements are dispatched
|
|
from the message queue.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Components_Port-Instances_Queue-Full-Behavior">10.2.5. Queue Full Behavior</h4>
|
|
<div class="paragraph">
|
|
<p>By default, if an invocation of an <code>async</code> <code>input</code> port causes
|
|
a message queue to overflow, then a <strong>FSW assertion</strong> fails.
|
|
A FSW assertion is a condition that must be true in order
|
|
for FSW execution to proceed safely.
|
|
The behavior of a FSW assertion failure is configurable in the C++
|
|
implementation of the F Prime framework; typically it causes a FSW
|
|
abort and system reset.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Optionally, you can specify the behavior when a message
|
|
received on an <code>async</code> <code>input</code> port causes a queue overflow.
|
|
There are three possible behaviors:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p><code>assert</code>: Fail a FSW assertion (the default behavior).</p>
|
|
</li>
|
|
<li>
|
|
<p><code>block</code>: Block the sender until the queue is available.</p>
|
|
</li>
|
|
<li>
|
|
<p><code>drop</code>: Drop the incoming message and proceed.</p>
|
|
</li>
|
|
<li>
|
|
<p><code>hook</code>: Call a user-specified function and proceed.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>To specify queue full behavior, you write one of the keywords <code>assert</code>,
|
|
<code>block</code>, <code>drop</code>, or <code>hook</code> after the port type and after the priority
|
|
(if any).
|
|
As an example, here is the <code>ActiveF32Adder</code> updated with explicit
|
|
queue full behavior.</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ A port for carrying an F32 value
|
|
port F32Value(value: F32)
|
|
|
|
@ An active component for adding two F32 values
|
|
@ Uses specified priorities
|
|
active component ActiveF32Adder {
|
|
|
|
@ Input 1 at priority 10: Block on queue full
|
|
async input port f32ValueIn1: F32Value priority 10 block
|
|
|
|
@ Input 2: Drop on queue full
|
|
async input port f32ValueIn2: F32Value drop
|
|
|
|
@ Input 3: Call hook function on queue full
|
|
async input port f32ValueIn3: F32Value hook
|
|
|
|
@ Output
|
|
output port f32ValueOut: F32Value
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>As for priority specifiers, queue full specifiers are allowed only
|
|
for <code>async</code> <code>input</code> ports.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Components_Port-Instances_Serial-Port-Instances">10.2.6. Serial Port Instances</h4>
|
|
<div class="paragraph">
|
|
<p>When writing a port instance, instead of specifying a named port type,
|
|
you may write the keyword <code>serial</code>.
|
|
Doing this specifies a <strong>serial port instance</strong>.
|
|
A serial port instance does not specify the type of data that it carries.
|
|
It may be connected to a port of any type.
|
|
Serial data passes through the port; the data may be converted to or from a
|
|
specific type at the other end of the connection.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>As an example, here is a passive component for taking a stream
|
|
of serial data and splitting it (i.e., repeating it by copy)
|
|
onto several streams:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ Split factor
|
|
constant splitFactor = 10
|
|
|
|
@ Component for splitting a serial data stream
|
|
passive component SerialSplitter {
|
|
|
|
@ Input
|
|
sync input port serialIn: serial
|
|
|
|
@ Output
|
|
output port serialOut: [splitFactor] serial
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>By using serial ports, you can send several unrelated types
|
|
of data over the same port connection.
|
|
This technique is useful when communicating across
|
|
a network: on each side of the network connection, a single component
|
|
can act as a hub that routs all data to and from components
|
|
on that side.
|
|
This flexibility comes at the cost that you lose the type
|
|
compile-time type checking provided by port connections with named types.
|
|
For more information about serial ports and their use, see
|
|
the <a href="https://fprime.jpl.nasa.gov/devel/docs/user-manual/">F Prime User Manual</a>.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Defining-Components_Special-Port-Instances">10.3. Special Port Instances</h3>
|
|
<div class="paragraph">
|
|
<p>A <strong>special port instance</strong> is a port instance that has a special
|
|
behavior in F Prime.
|
|
As discussed <a href="#Defining-Components_Port-Instances">above</a>,
|
|
when writing a general port instance,
|
|
you specify a port kind, a port type, and possibly other
|
|
information such as array size and priority.
|
|
Writing a special port instance is a bit different.
|
|
In this case you specify a predefined behavior
|
|
provided by the F Prime framework.
|
|
The special port behaviors fall into six groups:
|
|
commands, events, telemetry, parameters, time,
|
|
and data products.</p>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Components_Special-Port-Instances_Command-Ports">10.3.1. Command Ports</h4>
|
|
<div class="paragraph">
|
|
<p>A <strong>command</strong> is an instruction to the spacecraft to perform an action.
|
|
Each component instance <em>C</em> that specifies commands has the following
|
|
high-level behaviors:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>At FSW startup time, <em>C</em> registers its commands with a component
|
|
instance called the <strong>command dispatcher</strong>.</p>
|
|
</li>
|
|
<li>
|
|
<p>During FSW execution, <em>C</em> receives commands from the command
|
|
dispatcher.
|
|
For each command received, <em>C</em> executes the command and
|
|
sends a response back to the command dispatcher.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In FPP, the keywords for the special command behaviors are as follows:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p><code>command</code> <code>reg</code>: A port for sending command registration requests.</p>
|
|
</li>
|
|
<li>
|
|
<p><code>command</code> <code>recv</code>: A port for receiving commands.</p>
|
|
</li>
|
|
<li>
|
|
<p><code>command</code> <code>resp</code>: A port for sending command responses.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Collectively, these ports are known as <strong>command ports</strong>.
|
|
To specify a command port, you write one of the keyword pairs
|
|
shown above followed by the keyword <code>port</code> and the port name.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>As an example, here is a passive component <code>CommandPorts</code> with each
|
|
of the command ports:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ A component for illustrating command ports
|
|
passive component CommandPorts {
|
|
|
|
@ A port for receiving commands
|
|
command recv port cmdIn
|
|
|
|
@ A port for sending command registration requests
|
|
command reg port cmdRegOut
|
|
|
|
@ A port for sending command responses
|
|
command resp port cmdResponseOut
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Any component may have at most one of each kind of command
|
|
port.
|
|
If a component receives commands (more on this below),
|
|
then all three ports are required.
|
|
The port names shown in the example above are standard but not
|
|
required; you can use any names you wish.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>During translation, each command port is converted into
|
|
a typed port instance with a predefined port type, as follows:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p><code>command</code> <code>recv</code> uses the port <code>Fw.Cmd</code></p>
|
|
</li>
|
|
<li>
|
|
<p><code>command</code> <code>reg</code> uses the port <code>Fw.CmdReg</code></p>
|
|
</li>
|
|
<li>
|
|
<p><code>command</code> <code>resp</code> uses the port <code>Fw.CmdResponse</code></p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The F Prime framework provides definitions for these ports
|
|
in the directory <code>Fw/Cmd</code>.
|
|
For checking simple examples, you can use the following
|
|
simplified definitions of these ports:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">module Fw {
|
|
port Cmd
|
|
port CmdReg
|
|
port CmdResponse
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For example, to check the <code>CommandPorts</code> component, you can
|
|
add these lines before the component definition.
|
|
If you don’t do this, or something similar, then the component
|
|
definition won’t pass through <code>fpp-check</code> because of the missing ports.
|
|
(Try it and see.)</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Note that the port definitions shown above are for conveniently checking
|
|
simple examples only.
|
|
They are not correct for the F Prime framework and will not work
|
|
properly with F Prime C++ code generation.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For further information about command registration, receipt, and
|
|
response, and implementing command handlers, see the
|
|
<a href="https://fprime.jpl.nasa.gov/devel/docs/user-manual/">F Prime User Manual</a>.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Components_Special-Port-Instances_Event-Ports">10.3.2. Event Ports</h4>
|
|
<div class="paragraph">
|
|
<p>An <strong>event</strong> is a report that something happened, for example,
|
|
that a file was successfully uplinked.
|
|
The special event behaviors, and their keywords, are as follows:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p><code>event</code>: A port for emitting events as serialized bytes.</p>
|
|
</li>
|
|
<li>
|
|
<p><code>text</code> <code>event</code>: A port for emitting events as human-readable
|
|
text (usually used for testing and debugging on the ground).</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Collectively, these ports are known as <strong>event ports</strong>.
|
|
To specify an event port, you write one of the keyword groups
|
|
shown above followed by the keyword <code>port</code> and the port name.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>As an example, here is a passive component <code>EventPorts</code> with each
|
|
of the event ports:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ A component for illustrating event ports
|
|
passive component EventPorts {
|
|
|
|
@ A port for emitting events
|
|
event port eventOut
|
|
|
|
@ A port for emitting text events
|
|
text event port textEventOut
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Any component may have at most one of each kind of event
|
|
port.
|
|
If a component emits events (more on this below),
|
|
then both event ports are required.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>During translation, each event port is converted into
|
|
a typed port instance with a predefined port type, as follows:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p><code>event</code> uses the port <code>Fw.Log</code></p>
|
|
</li>
|
|
<li>
|
|
<p><code>text</code> <code>event</code> uses the port <code>Fw.LogText</code></p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The name <code>Log</code> refers to an event log.
|
|
The F Prime framework provides definitions for these ports
|
|
in the directory <code>Fw/Log</code>.
|
|
For checking simple examples, you can use the following
|
|
simplified definitions of these ports:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">module Fw {
|
|
port Log
|
|
port LogText
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For further information about events in F Prime, see the
|
|
<a href="https://fprime.jpl.nasa.gov/devel/docs/user-manual/">F Prime User Manual</a>.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Components_Special-Port-Instances_Telemetry-Ports">10.3.3. Telemetry Ports</h4>
|
|
<div class="paragraph">
|
|
<p><strong>Telemetry</strong> is data regarding the state of the system.
|
|
A <strong>telemetry port</strong> allows a component to emit telemetry.
|
|
To specify a telemetry port, you write the keyword <code>telemetry</code>,
|
|
the keyword <code>port</code>, and the port name.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>As an example, here is a passive component <code>TelemetryPorts</code> with
|
|
a telemetry port:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ A component for illustrating telemetry ports
|
|
passive component TelemetryPorts {
|
|
|
|
@ A port for emitting telemetry
|
|
telemetry port tlmOut
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Any component may have at most one telemetry port.
|
|
If a component emits telemetry (more on this below),
|
|
then a telemetry port is required.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>During translation, each telemetry port is converted into
|
|
a typed port instance with the predefined port type
|
|
<code>Fw.Tlm</code>.
|
|
The F Prime framework provides a definition for this port
|
|
in the directory <code>Fw/Tlm</code>.
|
|
For checking simple examples, you can use the following
|
|
simplified definition of this port:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">module Fw {
|
|
port Tlm
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For further information about telemetry in F Prime, see the
|
|
<a href="https://fprime.jpl.nasa.gov/devel/docs/user-manual/">F Prime User Manual</a>.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Components_Special-Port-Instances_Parameter-Ports">10.3.4. Parameter Ports</h4>
|
|
<div class="paragraph">
|
|
<p>A <strong>parameter</strong> is a configurable constant that may be updated
|
|
from the ground.
|
|
The current parameter values are stored in an F Prime component
|
|
called the <strong>parameter database</strong>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The special parameter behaviors, and their keywords, are as follows:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p><code>param</code> <code>get</code>: A port for getting the current value of a parameter
|
|
from the parameter database.</p>
|
|
</li>
|
|
<li>
|
|
<p><code>param</code> <code>set</code>: A port for setting the current value of a parameter
|
|
in the parameter database.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Collectively, these ports are known as <strong>parameter ports</strong>.
|
|
To specify a parameter port, you write one of the keyword groups
|
|
shown above followed by the keyword <code>port</code> and the port name.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>As an example, here is a passive component <code>ParamPorts</code> with each
|
|
of the parameter ports:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ A component for illustrating parameter ports
|
|
passive component ParamPorts {
|
|
|
|
@ A port for getting parameter values
|
|
param get port prmGetOut
|
|
|
|
@ A port for setting parameter values
|
|
param set port prmSetOut
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Any component may have at most one of each kind of parameter
|
|
port.
|
|
If a component has parameters (more on this below),
|
|
then both parameter ports are required.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>During translation, each parameter port is converted into
|
|
a typed port instance with a predefined port type, as follows:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p><code>param</code> <code>get</code> uses the port <code>Fw.PrmGet</code></p>
|
|
</li>
|
|
<li>
|
|
<p><code>param</code> <code>set</code> uses the port <code>Fw.PrmSet</code></p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The F Prime framework provides definitions for these ports
|
|
in the directory <code>Fw/Prm</code>.
|
|
For checking simple examples, you can use the following
|
|
simplified definitions of these ports:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">module Fw {
|
|
port PrmGet
|
|
port PrmSet
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For further information about parameters in F Prime, see the
|
|
<a href="https://fprime.jpl.nasa.gov/devel/docs/user-manual/">F Prime User Manual</a>.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Components_Special-Port-Instances_Time-Get-Ports">10.3.5. Time Get Ports</h4>
|
|
<div class="paragraph">
|
|
<p>A <strong>time get port</strong> allows a component to get the system time from a
|
|
time component.
|
|
To specify a time get port, you write the keywords <code>time</code> <code>get</code>,
|
|
the keyword <code>port</code>, and the port name.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>As an example, here is a passive component <code>TimeGetPorts</code> with
|
|
a time get port:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ A component for illustrating time get ports
|
|
passive component TimeGetPorts {
|
|
|
|
@ A port for getting the time
|
|
time get port timeGetOut
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Any component may have at most one time get port.
|
|
If a component emits events or telemetry (more on this below),
|
|
then a time get port is required, so that the events
|
|
and telemetry points can be time stamped.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>During translation, each time get port is converted into
|
|
a typed port instance with the predefined port type
|
|
<code>Fw.Time</code>.
|
|
The F Prime framework provides a definition for this port
|
|
in the directory <code>Fw/Time</code>.
|
|
For checking simple examples, you can use the following
|
|
simplified definition of this port:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">module Fw {
|
|
port Time
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For further information about time in F Prime, see the
|
|
<a href="https://fprime.jpl.nasa.gov/devel/docs/user-manual/">F Prime User Manual</a>.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Components_Special-Port-Instances_Data-Product-Ports">10.3.6. Data Product Ports</h4>
|
|
<div class="paragraph">
|
|
<p>A <strong>data product</strong> is a collection of data that can be stored to an
|
|
onboard file system, given a priority, and downlinked in priority
|
|
order.
|
|
For example, a data product may be an image or a unit of
|
|
science data.
|
|
Data products are stored in <strong>containers</strong> that contain
|
|
<strong>records</strong>.
|
|
A record is a unit of data.
|
|
A container stores (1) a header that describes the container
|
|
and (2) a list of records.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The special data product behaviors, and their keywords, are as follows:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p><code>product</code> <code>get</code>: A port for synchronously requesting a
|
|
memory buffer to store a container.</p>
|
|
</li>
|
|
<li>
|
|
<p><code>product</code> <code>request</code>: A port for asynchronously requesting
|
|
a buffer to store a container.</p>
|
|
</li>
|
|
<li>
|
|
<p><code>product</code> <code>recv</code>: A port for receiving a response to an
|
|
asynchronous buffer request.</p>
|
|
</li>
|
|
<li>
|
|
<p><code>product</code> <code>send</code>: A port for sending a buffer that stores
|
|
a container, after the container has been filled with data.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Collectively, these ports are known as <strong>data product ports</strong>.
|
|
To specify a data product port, you write one of the keyword groups
|
|
shown above followed by the keyword <code>port</code> and the port name.
|
|
To specify a product receive port, you must first write
|
|
<code>async</code>, <code>sync</code> or <code>guarded</code> to specify whether the input port
|
|
is asynchronous, synchronous, or guarded, as described in
|
|
the section on <a href="#Defining-Components_Port-Instances_Basic-Port-Instances">basic port instances</a>.
|
|
When specifying an <code>async</code> product receive port, you may
|
|
specify a <a href="#Defining-Components_Port-Instances_Priority">priority behavior</a>
|
|
or <a href="#Defining-Components_Port-Instances_Queue-Full-Behavior">queue full behavior</a>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>As an example, here is a passive component <code>DataProductPorts</code> with each
|
|
of the data product ports:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ A component for illustrating data product ports
|
|
active component DataProductPorts {
|
|
|
|
@ A port for getting a data product container
|
|
product get port productGetOut
|
|
|
|
@ A port for requesting a data product container
|
|
product request port productRequestOut
|
|
|
|
@ An async port for receiving a requested data product container
|
|
async product recv port productRecvIn priority 10 assert
|
|
|
|
@ A port for sending a filled data product container
|
|
product send port productSendOut
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Any component may have at most one of each kind of data product
|
|
port.
|
|
If a component defines data products (more on this below),
|
|
then there must be (1) a product get port or a product request port
|
|
and (2) a product send port.
|
|
If there is a product request port, then there must be a product
|
|
receive port.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>During translation, each data product port is converted into
|
|
a typed port instance with a predefined port type, as follows:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p><code>product</code> <code>get</code> uses the port <code>Fw.DpGet</code></p>
|
|
</li>
|
|
<li>
|
|
<p><code>product</code> <code>request</code> uses the port <code>Fw.DpRequest</code></p>
|
|
</li>
|
|
<li>
|
|
<p><code>product</code> <code>recv</code> uses the port <code>Fw.DpResponse</code></p>
|
|
</li>
|
|
<li>
|
|
<p><code>product</code> <code>send</code> uses the port <code>Fw.DpSend</code></p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The F Prime framework provides definitions for these ports
|
|
in the directory <code>Fw/Dp</code>.
|
|
For checking simple examples, you can use the following
|
|
simplified definitions of these ports:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">module Fw {
|
|
port DpGet
|
|
port DpRequest
|
|
port DpResponse
|
|
port DpSend
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For further information about data products in F Prime, see the
|
|
<a href="https://fprime.jpl.nasa.gov/devel/docs/user-manual/framework/data-products/">F
|
|
Prime design documentation</a>.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Defining-Components_Internal-Ports">10.4. Internal Ports</h3>
|
|
<div class="paragraph">
|
|
<p>An <strong>internal port</strong> is a port that a component can use to send a
|
|
message to itself.
|
|
In the ordinary case, when a component sends a message, it invokes an
|
|
output port that is connected to an async input port.
|
|
When the output port and input port reside in the same component,
|
|
it is simpler to use an internal port.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>As an example, suppose we have a component
|
|
that needs to send a message to itself.
|
|
We could construct such a component in the following way:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ A data type T
|
|
type T
|
|
|
|
@ A port for sending data of type T
|
|
port P(t: T)
|
|
|
|
@ A component that sends data to itself on an async input port
|
|
active component ExternalSelfMessage {
|
|
|
|
@ A port for sending data of type T
|
|
async input port pIn: P
|
|
|
|
@ A port for receiving data of type T
|
|
output port pOut: P
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>This works, but if the only user of <code>pIn</code> is
|
|
<code>ExternalSelfMessage</code>, it is cumbersome.
|
|
We need to declare two ports and connect them.
|
|
Instead, we can use an internal port, like this:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ A data type T
|
|
type T
|
|
|
|
@ A component that sends data to itself on an internal port
|
|
active component InternalSelfMessage {
|
|
|
|
@ An internal port for sending data of type T
|
|
internal port pInternal(t: T)
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>When the implementation of <code>InternalSelfMessage</code> invokes
|
|
the port <code>pInternal</code>, a message goes on its queue.
|
|
This corresponds to the behavior of <code>pOut</code> in
|
|
<code>ExternalSelfMessage</code>.
|
|
Later, when the framework dispatches the message, it
|
|
calls a handler function associated with the port.
|
|
This corresponds to the behavior of <code>pIn</code> in
|
|
<code>ExternalSelfMessage</code>.
|
|
So an internal port is like two ports (an output port
|
|
and an async input port) fused into one.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>When writing an internal port, you do not use a named
|
|
port definition.
|
|
Instead, you provide the formal parameters directly.
|
|
Notice that when defining <code>ExternalSelfMessage</code> we
|
|
defined and used the port <code>P</code>, but when defining
|
|
<code>InternalSelfMessage</code> we did not.
|
|
The formal parameters of an internal port work in the same way
|
|
as for a <a href="#Defining-Ports_Formal-Parameters">port definition</a>,
|
|
except that none of the parameters may be a
|
|
<a href="#Defining-Ports_Reference-Parameters">reference parameter</a>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>When specifying an internal port, you may specify
|
|
<a href="#Defining-Components_Port-Instances_Priority">priority</a> and
|
|
<a href="#Defining-Components_Port-Instances_Queue-Full-Behavior">queue full behavior</a>
|
|
as for an async input port.
|
|
For example, we can add priority and queue full behavior
|
|
to <code>pInternal</code> as follows:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ A data type T
|
|
type T
|
|
|
|
@ A component that sends data to itself on an internal port,
|
|
@ with priority and queue full behavior
|
|
active component InternalSelfMessage {
|
|
|
|
@ An internal port for sending data of type T
|
|
internal port pInternal(t: T) priority 10 drop
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Internal ports generate async input, so they make sense
|
|
only for <code>active</code> and <code>queued</code> components.
|
|
As an example, consider the following component
|
|
definition:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">type T
|
|
|
|
passive component PassiveInternalPort {
|
|
|
|
# Internal ports don't make sense for passive components
|
|
internal port pInternal(t: T)
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>What do you think will happen if you run <code>fpp-check</code>
|
|
on this code?
|
|
Try it and see.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Defining-Components_Commands">10.5. Commands</h3>
|
|
<div class="paragraph">
|
|
<p>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
|
|
or another ground data system to send commands to the FSW.
|
|
On receipt of a command <em>C</em>, a Command Dispatcher component instance
|
|
dispatches <em>C</em> to the component instance where that command is implemented.
|
|
The command is handled in a C++ command handler that you write
|
|
as part of the component implementation.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For complete information about F Prime command dispatch and
|
|
handling, see the
|
|
<a href="https://fprime.jpl.nasa.gov/devel/docs/user-manual/">F Prime User Manual</a>.
|
|
Here we concentrate on how to specify commands in FPP.</p>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Components_Commands_Basic-Commands">10.5.1. Basic Commands</h4>
|
|
<div class="paragraph">
|
|
<p>The simplest command consists of a kind followed by the keyword
|
|
<code>command</code> and a name.
|
|
The kind is one of the following:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p><code>async</code>: The command arrives on a message queue, to
|
|
be dispatched on this component’s thread (if this component is active)
|
|
or on the thread of a port invocation (if this component is queued).</p>
|
|
</li>
|
|
<li>
|
|
<p><code>sync</code>: The command invokes a handler defined in this component,
|
|
and run on the thread of the caller.</p>
|
|
</li>
|
|
<li>
|
|
<p><code>guarded</code>: Similar to sync input, but the handler is
|
|
guarded by a mutual exclusion lock.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Notice that the kinds of commands are similar to the kinds of
|
|
<a href="#Defining-Components_Port-Instances_Basic-Port-Instances">input ports</a>.
|
|
The name is the name of the command.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>As an example, here is an active component called <code>Action</code>
|
|
with two commands: an async command <code>START</code> and a sync
|
|
command <code>STOP</code>.</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ An active component for performing an action
|
|
active component Action {
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Ports
|
|
# ----------------------------------------------------------------------
|
|
|
|
@ Command input
|
|
command recv port cmdIn
|
|
|
|
@ Command registration
|
|
command reg port cmdRegOut
|
|
|
|
@ Command response
|
|
command resp port cmdResponseOut
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Commands
|
|
# ----------------------------------------------------------------------
|
|
|
|
@ Start the action
|
|
async command START
|
|
|
|
@ Stop the action
|
|
sync command STOP
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Command <code>START</code> is declared <code>async</code>.
|
|
That means that when a <code>START</code> command is dispatched
|
|
to an instance of this component, it arrives on a queue.
|
|
Later, the F Prime framework takes the message off the queue
|
|
and calls the corresponding handler on the thread
|
|
of the component.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Command <code>STOP</code> is declared <code>sync</code>.
|
|
That means that the command runs immediately on the
|
|
thread of the invoking component (for example,
|
|
a command dispatcher component).
|
|
Because the command runs immediately, its handler
|
|
should be very short.
|
|
For example, it could set a stop flag and then exit.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Notice that we defined the three
|
|
<a href="#Defining-Components_Special-Port-Instances_Command-Ports">command ports</a>
|
|
for this component.
|
|
All three ports are required for any component that has commands.
|
|
As an example, try deleting one or more of the command ports from the
|
|
code above and running the result through <code>fpp-check</code>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><code>async</code> commands require a message queue, so
|
|
they are allowed only for active and queued
|
|
components.
|
|
As an example, try making the <code>Action</code> component passive and
|
|
running the result through <code>fpp-check</code>.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Components_Commands_Formal-Parameters">10.5.2. Formal Parameters</h4>
|
|
<div class="paragraph">
|
|
<p>When specifying a command, you may specify one or more
|
|
formal parameters.
|
|
The parameters are bound to arguments when the command
|
|
is sent to the spacecraft.
|
|
Different uses of the same command can have different
|
|
argument values.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The formal parameters of a command are the same
|
|
as for a <a href="#Defining-Ports_Formal-Parameters">port definition</a>, except
|
|
for the following:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>None of the parameters may be a
|
|
<a href="#Defining-Ports_Reference-Parameters">reference parameter</a>.</p>
|
|
</li>
|
|
<li>
|
|
<p>Each parameter must have a <strong>displayable type</strong>, i.e., a
|
|
type that the F Prime ground data system knows how to display.
|
|
For example, the type may not be an
|
|
<a href="#Defining-Types_Abstract-Type-Definitions">abstract type</a>.
|
|
Nor may it be an array or struct type that has an abstract type
|
|
as a member type.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>As an example, here is a <code>Switch</code> component that has
|
|
two states, <code>ON</code> and <code>OFF</code>.
|
|
The component has a <code>SET_STATE</code> command for
|
|
setting the state.
|
|
The command has a single argument <code>state</code>
|
|
that specifies the new state.</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ The state enumeration
|
|
enum State {
|
|
OFF @< The off state
|
|
ON @< The on state
|
|
}
|
|
|
|
@ A switch with on and off state
|
|
active component Switch {
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Ports
|
|
# ----------------------------------------------------------------------
|
|
|
|
@ Command input
|
|
command recv port cmdIn
|
|
|
|
@ Command registration
|
|
command reg port cmdRegOut
|
|
|
|
@ Command response
|
|
command resp port cmdResponseOut
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Commands
|
|
# ----------------------------------------------------------------------
|
|
|
|
@ Set the state
|
|
async command SET_STATE(
|
|
$state: State @< The new state
|
|
)
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In this example, the enum type <code>State</code> is a displayable type because
|
|
its definition is known to FPP.
|
|
Try replacing the enum definition with the
|
|
abstract type definition <code>type S</code> and see what happens when
|
|
you run the model through <code>fpp-check</code>.
|
|
Remember to <a href="#Defining-Components_Special-Port-Instances_Command-Ports">provide
|
|
stubs for the special command ports</a> that are required by
|
|
<code>fpp-check</code>.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Components_Commands_Opcodes">10.5.3. Opcodes</h4>
|
|
<div class="paragraph">
|
|
<p>Every command in an F Prime FSW application has an <strong>opcode</strong>.
|
|
The opcode is a number that uniquely identifies the command.
|
|
The F Prime framework uses the opcode when dispatching commands
|
|
because it is a more compact identifier than the name.
|
|
The name is mainly for human interaction on the ground.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The opcodes associated with each component <em>C</em>
|
|
are relative to the component.
|
|
Typically the opcodes start at zero: that is, the
|
|
opcodes are 0, 1, 2, etc.
|
|
When constructing an instance <em>I</em> of component <em>C</em>,
|
|
the framework adds a base opcode for <em>I</em> to each relative opcode
|
|
associated with <em>C</em> to form
|
|
the global opcodes associated with <em>I</em>.
|
|
That way different instances of <em>C</em> can have different opcodes
|
|
for the same commands defined in <em>C</em>.
|
|
We will have more to say about base and relative opcodes
|
|
when we describe component instances and topologies.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>If you specify a command <em>c</em> with no explicit opcode, as in the examples
|
|
shown in the previous sections, then FPP assigns a default opcode
|
|
to <em>c</em>.
|
|
The default opcode for the first command in a component is zero.
|
|
Otherwise the default opcode for any command is one more than
|
|
the opcode of the previous command.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>It is usually convenient to rely on the default opcodes.
|
|
However, you may wish to specify one or more opcodes explicitly.
|
|
To do this, you write the keyword <code>opcode</code> followed
|
|
by a numeric expression after the command name and after the
|
|
formal parameters, if any.
|
|
Here is an example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ Component for illustrating command opcodes
|
|
active component CommandOpcodes {
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Ports
|
|
# ----------------------------------------------------------------------
|
|
|
|
@ Command input
|
|
command recv port cmdIn
|
|
|
|
@ Command registration
|
|
command reg port cmdRegOut
|
|
|
|
@ Command response
|
|
command resp port cmdResponseOut
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Commands
|
|
# ----------------------------------------------------------------------
|
|
|
|
@ This command has default opcode 0x0
|
|
async command COMMAND_1
|
|
|
|
@ This command has explicit opcode 0x10
|
|
async command COMMAND_2(a: F32, b: U32) opcode 0x10
|
|
|
|
@ This command has default opcode 0x11
|
|
sync command COMMAND_3
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Within a component, the command opcodes must be unique.
|
|
For example, this component is incorrect because
|
|
the opcode zero appears twice:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ Component for illustrating a duplicate opcode
|
|
active component DuplicateOpcode {
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Ports
|
|
# ----------------------------------------------------------------------
|
|
|
|
@ Command input
|
|
command recv port cmdIn
|
|
|
|
@ Command registration
|
|
command reg port cmdRegOut
|
|
|
|
@ Command response
|
|
command resp port cmdResponseOut
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Commands
|
|
# ----------------------------------------------------------------------
|
|
|
|
@ This command has opcode 0x0
|
|
async command COMMAND_1
|
|
|
|
@ Oops! This command also has opcode 0x0
|
|
async command COMMAND_2 opcode 0x0
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Components_Commands_Priority-and-Queue-Full-Behavior">10.5.4. Priority and Queue Full Behavior</h4>
|
|
<div class="paragraph">
|
|
<p>When specifying an async command, you may specify
|
|
<a href="#Defining-Components_Port-Instances_Priority">priority</a> and
|
|
<a href="#Defining-Components_Port-Instances_Queue-Full-Behavior">queue full behavior</a>
|
|
as for an async input port.
|
|
You put the priority and queue full information after the command name
|
|
and after the formal parameters and opcode, if any.
|
|
Here is an example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ A component for illustrating priority and queue full behavior for async
|
|
@ commands
|
|
active component PriorityQueueFull {
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Ports
|
|
# ----------------------------------------------------------------------
|
|
|
|
@ Command input
|
|
command recv port cmdIn
|
|
|
|
@ Command registration
|
|
command reg port cmdRegOut
|
|
|
|
@ Command response
|
|
command resp port cmdResponseOut
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Commands
|
|
# ----------------------------------------------------------------------
|
|
|
|
@ Command with priority
|
|
async command COMMAND_1 priority 10
|
|
|
|
@ Command with formal parameters and priority
|
|
async command COMMAND_2(a: U32, b: F32) priority 20
|
|
|
|
@ Command with formal parameters, opcode, priority, and queue full behavior
|
|
async command COMMAND_3(a: string) opcode 0x10 priority 30 drop
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Priority and queue full behavior are allowed only for
|
|
<code>async</code> commands.
|
|
Try changing one of the commands in the previous example
|
|
to <code>sync</code> and see what <code>fpp-check</code> has to say about it.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Defining-Components_Events">10.6. Events</h3>
|
|
<div class="paragraph">
|
|
<p>When defining an F Prime component, you may specify one or more events.
|
|
The F Prime framework converts each event into a C++
|
|
function that you can call from the component implementation.
|
|
Calling the function emits a serialized event report that
|
|
you can store in an on-board file system or send to the ground.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For complete information about F Prime event
|
|
handling, see the
|
|
<a href="https://fprime.jpl.nasa.gov/devel/docs/user-manual/">F Prime User Manual</a>.
|
|
Here we concentrate on how to specify events in FPP.</p>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Components_Events_Basic-Events">10.6.1. Basic Events</h4>
|
|
<div class="paragraph">
|
|
<p>The simplest event consists of the keyword <code>event</code>, a name, a severity,
|
|
and a format string.
|
|
The name is the name of the event.
|
|
A severity is the keyword <code>severity</code> and one of the following:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p><code>activity</code> <code>high</code>: Spacecraft activity of greater importance.</p>
|
|
</li>
|
|
<li>
|
|
<p><code>activity</code> <code>low</code>: Spacecraft activity of lesser importance.</p>
|
|
</li>
|
|
<li>
|
|
<p><code>command</code>: An event related to commanding.
|
|
Primarily used by the command dispatcher.</p>
|
|
</li>
|
|
<li>
|
|
<p><code>diagnostic</code>: An event relating to system diagnosis
|
|
and debugging.</p>
|
|
</li>
|
|
<li>
|
|
<p><code>fatal</code>: An event that causes the system to abort.</p>
|
|
</li>
|
|
<li>
|
|
<p><code>warning</code> <code>high</code>: A warning of greater importance.</p>
|
|
</li>
|
|
<li>
|
|
<p><code>warning</code> <code>low</code>: A warning of lesser importance.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>A format is the keyword <code>format</code> and a literal string for
|
|
use in a formatted real-time display or event log.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>As an example, here is an active component called <code>BasicEvents</code>
|
|
with a few basic events.</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ A component for illustrating basic events
|
|
passive component BasicEvents {
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Ports
|
|
# ----------------------------------------------------------------------
|
|
|
|
@ Event port
|
|
event port eventOut
|
|
|
|
@ Text event port
|
|
text event port textEventOut
|
|
|
|
@ Time get port
|
|
time get port timeGetOut
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Events
|
|
# ----------------------------------------------------------------------
|
|
|
|
@ Activity low event
|
|
event Event1 severity activity low format "Event 1 occurred"
|
|
|
|
@ Warning low event
|
|
event Event2 severity warning low format "Event 2 occurred"
|
|
|
|
@ Warning high event
|
|
event Event3 severity warning high format "Event 3 occurred"
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Notice that we defined the two
|
|
<a href="#Defining-Components_Special-Port-Instances_Event-Ports">event ports</a>
|
|
and a
|
|
<a href="#Defining-Components_Special-Port-Instances_Time-Get-Ports">time get port</a>
|
|
for this component.
|
|
All three ports are required for any component that has events.
|
|
As an example, try deleting one or more of these ports from the
|
|
code above and running the result through <code>fpp-check</code>.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Components_Events_Formal-Parameters">10.6.2. Formal Parameters</h4>
|
|
<div class="paragraph">
|
|
<p>When specifying an event, you may specify one or more
|
|
formal parameters.
|
|
The parameters are bound to arguments when the component
|
|
instance emits the event.
|
|
The argument values appear in the formatted text
|
|
that describes the event.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>You specify the formal parameters of an event in the same
|
|
way as for a <a href="#Defining-Components_Commands_Formal-Parameters">command
|
|
specifier</a>.
|
|
For each formal parameter, there must be a corresponding
|
|
replacement field in the format string.
|
|
The replacement fields for event format strings are the same as for
|
|
format strings in
|
|
<a href="#Defining-Types_Array-Type-Definitions_Format-Strings">type definitions</a>.
|
|
The replacement fields in the format string match the event
|
|
parameters, one for one and in the same order.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>As an example, here is a component with two events,
|
|
each of which has formal parameters.
|
|
Notice how the replacement fields in the event format
|
|
strings correspond to the formal parameters.</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ An enumeration of cases
|
|
enum Case { A, B, C }
|
|
|
|
@ An array of 3 F64 values
|
|
array F64x3 = [3] F64
|
|
|
|
@ A component for illustrating event formal parameters
|
|
passive component EventParameters {
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Ports
|
|
# ----------------------------------------------------------------------
|
|
|
|
@ Event port
|
|
event port eventOut
|
|
|
|
@ Text event port
|
|
text event port textEventOut
|
|
|
|
@ Time get port
|
|
time get port timeGetOut
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Events
|
|
# ----------------------------------------------------------------------
|
|
|
|
@ Event 1
|
|
@ Sample output: "Event 1 occurred with argument 42"
|
|
event Event1(
|
|
arg1: U32 @< Argument 1
|
|
) \
|
|
severity activity high \
|
|
format "Event 1 occurred with argument {}"
|
|
|
|
@ Event 2
|
|
@ Sample output: "Saw value [ 0.001, 0.002, 0.003 ] for case A"
|
|
event Event2(
|
|
case: Case @< The case
|
|
value: F64x3 @< The value
|
|
) \
|
|
severity warning low \
|
|
format "Saw value {} for case {}"
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Components_Events_Identifiers">10.6.3. Identifiers</h4>
|
|
<div class="paragraph">
|
|
<p>Every event in an F Prime FSW application has a unique
|
|
numeric identifier.
|
|
As for
|
|
<a href="#Defining-Components_Commands_Opcodes">command opcodes</a>,
|
|
the event identifiers for a component are specified
|
|
relative to the component, usually starting from
|
|
zero and counting up by one.
|
|
If you omit the identifier, then
|
|
FPP assigns a default identifier: zero for the first
|
|
event in the component; otherwise one more than the
|
|
identifier of the previous event.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>If you wish, you may explicitly specify one or more event
|
|
identifiers.
|
|
To do this, you write the keyword <code>id</code> followed
|
|
by a numeric expression immediately before the keyword <code>format</code>.
|
|
Here is an example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ Component for illustrating event identifiers
|
|
passive component EventIdentifiers {
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Ports
|
|
# ----------------------------------------------------------------------
|
|
|
|
@ Event port
|
|
event port eventOut
|
|
|
|
@ Text event port
|
|
text event port textEventOut
|
|
|
|
@ Time get port
|
|
time get port timeGetOut
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Events
|
|
# ----------------------------------------------------------------------
|
|
|
|
@ Event 1
|
|
@ Its identifier is 0x00
|
|
event Event1 severity activity low \
|
|
id 0x10 \
|
|
format "Event 1 occurred"
|
|
|
|
@ Event 2
|
|
@ Its identifier is 0x10
|
|
event Event2(
|
|
count: U32 @< The count
|
|
) \
|
|
severity activity high \
|
|
id 0x11 \
|
|
format "The count is {}"
|
|
|
|
@ Event 3
|
|
@ Its identifier is 0x11
|
|
event Event3 severity activity high \
|
|
format "Event 3 occurred"
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Within a component, the event identifiers must be unique.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Components_Events_Throttling">10.6.4. Throttling</h4>
|
|
<div class="paragraph">
|
|
<p>Sometimes it is necessary to throttle events, to ensure that
|
|
they do not flood the system.
|
|
For example, suppose that the FSW requests some resource <em>R</em>
|
|
at a rate <em>r</em> of several times per second.
|
|
Suppose further that if <em>R</em> is unavailable, then the FSW
|
|
emits a warning event.
|
|
In this case, we typically do not want the FSW to emit an unbounded number
|
|
of warnings at rate <em>r</em>; instead, we want it to emit a single warning
|
|
or a few warnings.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>To achieve this behavior, you can write the keyword <code>throttle</code> and a
|
|
numeric expression after the format string.
|
|
The expression must evaluate to a constant value <em>n</em>.
|
|
After an instance of the component has emitted the event <em>n</em> times, it will
|
|
stop emitting the event.
|
|
Here is an example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ Component for illustrating event throttling
|
|
passive component EventThrottling {
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Ports
|
|
# ----------------------------------------------------------------------
|
|
|
|
@ Event port
|
|
event port eventOut
|
|
|
|
@ Text event port
|
|
text event port textEventOut
|
|
|
|
@ Time get port
|
|
time get port timeGetOut
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Events
|
|
# ----------------------------------------------------------------------
|
|
|
|
@ Event 1
|
|
event Event1 severity warning high \
|
|
format "Event 1 occurred" \
|
|
throttle 10
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In this example, event <code>E</code> will be throttled after the component
|
|
instance has emitted it ten times.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Once an event is throttled, the component instance will no longer
|
|
emit the event until the throttling is canceled.
|
|
Typically, the canceling happens via a FSW command.
|
|
For details, see the
|
|
<a href="https://fprime.jpl.nasa.gov/devel/docs/user-manual/">F Prime User Manual</a>.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Defining-Components_Telemetry">10.7. Telemetry</h3>
|
|
<div class="paragraph">
|
|
<p>When defining an F Prime component, you may specify one or more
|
|
<strong>telemetry channels</strong>.
|
|
A telemetry channel consists of a data type and an identifier.
|
|
The F Prime framework converts each telemetry into a C++
|
|
function that you can call from the component implementation.
|
|
Calling the function emits a value on the channel.
|
|
Each emitted value is called a
|
|
<strong>telemetry point</strong>.
|
|
You can store the telemetry points in an on-board file system
|
|
or send them the ground.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For complete information about F Prime telemetry
|
|
handling, see the
|
|
<a href="https://fprime.jpl.nasa.gov/devel/docs/user-manual/">F Prime User Manual</a>.
|
|
Here we concentrate on how to specify telemetry channels in FPP.</p>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Components_Telemetry_Basic-Telemetry">10.7.1. Basic Telemetry</h4>
|
|
<div class="paragraph">
|
|
<p>The simplest telemetry channel consists of the keyword <code>telemetry</code>,
|
|
a name, and a data type.
|
|
The name is the name of the channel.
|
|
The data type is the type of data carried on the channel.
|
|
The data type must be a
|
|
<a href="#Defining-Components_Commands_Formal-Parameters">displayable type</a>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>As an example, here is an active component called <code>BasicTelemetry</code>
|
|
with a few basic events.</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ An array of 3 F64 values
|
|
array F64x3 = [3] F64
|
|
|
|
@ A component for illustrating basic telemetry channels
|
|
passive component BasicTelemetry {
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Ports
|
|
# ----------------------------------------------------------------------
|
|
|
|
@ Telemetry port
|
|
telemetry port tlmOut
|
|
|
|
@ Time get port
|
|
time get port timeGetOut
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Telemetry
|
|
# ----------------------------------------------------------------------
|
|
|
|
@ Telemetry channel 1
|
|
telemetry Channel1: U32
|
|
|
|
@ Telemetry channel 2
|
|
telemetry Channel2: F64
|
|
|
|
@ Telemetry channel 3
|
|
telemetry Channel3: F64x3
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Notice that we defined a
|
|
<a href="#Defining-Components_Special-Port-Instances_Telemetry-Ports">telemetry port</a>
|
|
and a
|
|
<a href="#Defining-Components_Special-Port-Instances_Time-Get-Ports">time get port</a>
|
|
for this component.
|
|
Both ports are required for any component that has telemetry.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Components_Telemetry_Identifiers">10.7.2. Identifiers</h4>
|
|
<div class="paragraph">
|
|
<p>Every telemetry channel in an F Prime FSW application has a unique
|
|
numeric identifier.
|
|
As for
|
|
<a href="#Defining-Components_Commands_Opcodes">command opcodes</a>
|
|
and
|
|
<a href="#Defining-Components_Events_Identifiers">event identifiers</a>,
|
|
the telemetry channel identifiers for a component are specified
|
|
relative to the component, usually starting from
|
|
zero and counting up by one.
|
|
If you omit the identifier, then
|
|
FPP assigns a default identifier: zero for the first
|
|
event in the component; otherwise one more than the
|
|
identifier of the previous channel.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>If you wish, you may explicitly specify one or more
|
|
telemetry channel identifiers.
|
|
To do this, you write the keyword <code>id</code> followed
|
|
by a numeric expression immediately after the data type.
|
|
Here is an example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ An array of 3 F64 values
|
|
array F64x3 = [3] F64
|
|
|
|
@ Component for illustrating telemetry channel identifiers
|
|
passive component TlmIdentifiers {
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Ports
|
|
# ----------------------------------------------------------------------
|
|
|
|
@ Telemetry port
|
|
telemetry port tlmOut
|
|
|
|
@ Time get port
|
|
time get port timeGetOut
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Telemetry
|
|
# ----------------------------------------------------------------------
|
|
|
|
@ Telemetry channel 1
|
|
@ Its implied identifier is 0x00
|
|
telemetry Channel1: U32
|
|
|
|
@ Telemetry channel 2
|
|
@ Its identifier is 0x10
|
|
telemetry Channel2: F64 id 0x10
|
|
|
|
@ Telemetry channel 3
|
|
@ Its implied identifier is 0x11
|
|
telemetry Channel3: F64x3
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Within a component, the telemetry channel identifiers must be unique.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Components_Telemetry_Update-Frequency">10.7.3. Update Frequency</h4>
|
|
<div class="paragraph">
|
|
<p>You can specify how often the telemetry is emitted on a channel <em>C</em>.
|
|
There are two possibilities:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p><code>always</code>: Emit a telemetry point on <em>C</em>
|
|
whenever the component implementation calls the
|
|
auto-generated function <em>F</em> that emits telemetry on <em>C</em>.</p>
|
|
</li>
|
|
<li>
|
|
<p><code>on</code> <code>change</code>: Emit a telemetry point whenever
|
|
(1) the implementation calls <em>F</em> and (2) either (a)
|
|
<em>F</em> has not been called before or
|
|
(b) the last time that <em>F</em> was called, the argument
|
|
to <em>F</em> had a different value.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Emitting telemetry on change can reduce unnecessary
|
|
activity in the system.
|
|
For example, suppose a telemetry channel <em>C</em> counts
|
|
the number of times that some event <em>E</em> occurs
|
|
in a periodic task,
|
|
and suppose that <em>E</em> does not occur on every cycle.
|
|
If you declare channel <em>C</em> <code>on</code> <code>change</code>, then your implementation
|
|
can call the telemetry emit function for <em>C</em> on every
|
|
cycle, and telemetry will be emitted only when
|
|
<em>E</em> occurs.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>To specify an update frequency, you write the keyword <code>update</code>
|
|
and one of the frequency selectors shown above.
|
|
The update specifier goes after
|
|
the type name and after the channel identifier, if any.
|
|
If you don’t specify an update frequency, then the default
|
|
value is <code>always</code>.
|
|
Here is an example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ An array of 3 F64 values
|
|
array F64x3 = [3] F64
|
|
|
|
@ Component for illustrating telemetry channel update specifiers
|
|
passive component TlmUpdate {
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Ports
|
|
# ----------------------------------------------------------------------
|
|
|
|
@ Telemetry port
|
|
telemetry port tlmOut
|
|
|
|
@ Time get port
|
|
time get port timeGetOut
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Telemetry
|
|
# ----------------------------------------------------------------------
|
|
|
|
@ Telemetry channel 1
|
|
@ Always emitted
|
|
telemetry Channel1: U32
|
|
|
|
@ Telemetry channel 2
|
|
@ Emitted on change
|
|
telemetry Channel2: F64 id 0x10 update on change
|
|
|
|
@ Telemetry channel 3
|
|
@ Always emitted
|
|
telemetry Channel3: F64x3 update always
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Components_Telemetry_Format-Strings">10.7.4. Format Strings</h4>
|
|
<div class="paragraph">
|
|
<p>You may specify how a telemetry channel is formatted in the
|
|
ground display.
|
|
To do this, you write the keyword <code>format</code> and a format string
|
|
with one
|
|
<a href="#Defining-Types_Array-Type-Definitions_Format-Strings">replacement field</a>.
|
|
The replacement field must match the type of the telemetry
|
|
channel.
|
|
The format specifier comes after the type name, after the
|
|
channel identifier, and after the update specifier.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Here is an example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ Component for illustrating telemetry channel format specifiers
|
|
passive component TlmFormat {
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Ports
|
|
# ----------------------------------------------------------------------
|
|
|
|
@ Telemetry port
|
|
telemetry port tlmOut
|
|
|
|
@ Time get port
|
|
time get port timeGetOut
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Telemetry
|
|
# ----------------------------------------------------------------------
|
|
|
|
@ Telemetry channel 1
|
|
telemetry Channel1: U32 format "{x}"
|
|
|
|
@ Telemetry channel 2
|
|
telemetry Channel2: F64 id 0x10 \
|
|
update on change \
|
|
format "{.3f}"
|
|
|
|
@ Telemetry channel 3
|
|
telemetry Channel3: F64\
|
|
update always \
|
|
format "{e}"
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Components_Telemetry_Limits">10.7.5. Limits</h4>
|
|
<div class="paragraph">
|
|
<p>You may specify <strong>limits</strong>, or bounds, on the expected values
|
|
carried on a telemetry channel.
|
|
There are two kinds of limits: <code>low</code> (meaning that the
|
|
values on the channel should stay above the limit) and <code>high</code>
|
|
(meaning that the values should stay below the limit).
|
|
Within each kind, there are three levels of severity:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p><code>yellow</code>: Crossing the limit is of low concern.</p>
|
|
</li>
|
|
<li>
|
|
<p><code>orange</code>: Crossing the limit is of medium concern.</p>
|
|
</li>
|
|
<li>
|
|
<p><code>red</code>: Crossing the limit is of high concern.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The F Prime ground data system displays an appropriate warning
|
|
when a telemetry point crosses a limit.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The limit specifiers come after the type name, identifier,
|
|
update specifier, and format string.
|
|
You specify the low limits (if any) first, and then the high limits.
|
|
For the low limits, you write the keyword <code>low</code> followed by a
|
|
list of limits in curly braces <code>{ …​ }</code>.
|
|
For the high limits, you do the same thing but use the keyword
|
|
<code>high</code>.
|
|
Each limit is a severity keyword followed by a numeric expression.
|
|
Here are some examples:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ Component for illustrating telemetry channel limits
|
|
passive component TlmLimits {
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Ports
|
|
# ----------------------------------------------------------------------
|
|
|
|
@ Telemetry port
|
|
telemetry port tlmOut
|
|
|
|
@ Time get port
|
|
time get port timeGetOut
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Telemetry
|
|
# ----------------------------------------------------------------------
|
|
|
|
@ Telemetry channel 1
|
|
telemetry Channel1: U32 \
|
|
low { red 0, orange 1, yellow 2 }
|
|
|
|
@ Telemetry channel 2
|
|
telemetry Channel2: F64 id 0x10 \
|
|
update on change \
|
|
format "{.3f}" \
|
|
low { red -3, orange -2, yellow -1 } \
|
|
high { red 3, orange 2, yellow 1 }
|
|
|
|
@ Telemetry channel 3
|
|
telemetry Channel3: F64 \
|
|
update always \
|
|
format "{e}" \
|
|
high { red 3, orange 2, yellow 1 }
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Each limit must be a numeric value.
|
|
The type of the telemetry channel must be (1) a numeric
|
|
type; or (2) an array or struct type each of whose members
|
|
has a numeric type; or (3) an array or struct type
|
|
each of whose members satisfies condition (1) or
|
|
condition (2).</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Defining-Components_Parameters">10.8. Parameters</h3>
|
|
<div class="paragraph">
|
|
<p>When defining an F Prime component, you may specify one or more
|
|
<strong>parameters</strong>.
|
|
A parameter is a typed constant value that you can update
|
|
by command.
|
|
For example, it could be a configuration constant
|
|
for a hardware device or a software algorithm.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>F Prime has special support for parameters, including a parameter
|
|
database component for storing parameters in a non-volatile
|
|
manner (e.g., on a file system).
|
|
For complete information about F Prime parameters, see the
|
|
<a href="https://fprime.jpl.nasa.gov/devel/docs/user-manual/">F Prime User Manual</a>.
|
|
Here we concentrate on how to specify parameters in FPP.</p>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Components_Parameters_Basic-Parameters">10.8.1. Basic Parameters</h4>
|
|
<div class="paragraph">
|
|
<p>The simplest parameter consists of the keyword <code>param</code>,
|
|
a name, and a data type.
|
|
The name is the name of the parameter.
|
|
The data type is the type of data stored in the parameter.
|
|
The data type must be a
|
|
<a href="#Defining-Components_Commands_Formal-Parameters">displayable type</a>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>As an example, here is an active component called <code>BasicParams</code>
|
|
with a few basic parameters.</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ An array of 3 F64 values
|
|
array F64x3 = [3] F64
|
|
|
|
@ A component for illustrating basic parameters
|
|
passive component BasicParams {
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Ports
|
|
# ----------------------------------------------------------------------
|
|
|
|
@ Command receive port
|
|
command recv port cmdIn
|
|
|
|
@ Command registration port
|
|
command reg port cmdRegOut
|
|
|
|
@ Command response port
|
|
command resp port cmdResponseOut
|
|
|
|
@ Parameter get port
|
|
param get port prmGetOut
|
|
|
|
@ Parameter set port
|
|
param set port prmSetOut
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Parameters
|
|
# ----------------------------------------------------------------------
|
|
|
|
@ Parameter 1
|
|
param Param1: U32
|
|
|
|
@ Parameter 2
|
|
param Param2: F64
|
|
|
|
@ Parameter 3
|
|
param Param3: F64x3
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Notice that we defined the two
|
|
<a href="#Defining-Components_Special-Port-Instances_Parameter-Ports">parameter ports</a>
|
|
for this component.
|
|
Both ports are required for any component that has parameters.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Notice also that we defined the
|
|
<a href="#Defining-Components_Special-Port-Instances_Command-Ports">command ports</a>
|
|
for this component.
|
|
When you add one or more parameters to a component,
|
|
F Prime automatically generates commands for (1)
|
|
setting the local parameter in the component and (2) saving
|
|
the local parameter to a system-wide parameter database.
|
|
Therefore, any component that has parameters must have
|
|
the command ports.
|
|
Try deleting one or more of the command ports from the example
|
|
above and see what <code>fpp-check</code> does.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Components_Parameters_Default-Values">10.8.2. Default Values</h4>
|
|
<div class="paragraph">
|
|
<p>You can specify a default value for any parameter.
|
|
This is the value that F Prime will use if no value is
|
|
available in the parameter database.
|
|
If you don’t specify a default value, and no value is
|
|
available in the database, then attempting to get
|
|
the parameter produces an invalid value.
|
|
What happens then is up to the FSW implementation.
|
|
By providing default values for your parameters,
|
|
you can avoid handling this case.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Here is the example from the previous section, updated
|
|
to include default values for the parameters:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ An array of 3 F64 values
|
|
array F64x3 = [3] F64
|
|
|
|
@ A component for illustrating default parameter values
|
|
passive component ParamDefaults {
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Ports
|
|
# ----------------------------------------------------------------------
|
|
|
|
@ Command receive port
|
|
command recv port cmdIn
|
|
|
|
@ Command registration port
|
|
command reg port cmdRegOut
|
|
|
|
@ Command response port
|
|
command resp port cmdResponseOut
|
|
|
|
@ Parameter get port
|
|
param get port prmGetOut
|
|
|
|
@ Parameter set port
|
|
param set port prmSetOut
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Parameters
|
|
# ----------------------------------------------------------------------
|
|
|
|
@ Parameter 1
|
|
param Param1: U32 default 1
|
|
|
|
@ Parameter 2
|
|
param Param2: F64 default 2.0
|
|
|
|
@ Parameter 3
|
|
param Param3: F64x3 default [ 1.0, 2.0, 3.0 ]
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Components_Parameters_Identifiers">10.8.3. Identifiers</h4>
|
|
<div class="paragraph">
|
|
<p>Every parameter in an F Prime FSW application has a unique
|
|
numeric identifier.
|
|
As for
|
|
<a href="#Defining-Components_Commands_Opcodes">command opcodes</a>,
|
|
<a href="#Defining-Components_Events_Identifiers">event identifiers</a>,
|
|
and
|
|
<a href="#Defining-Components_Telemetry_Identifiers">telemetry channel identifiers</a>,
|
|
the parameter identifiers for a component are specified
|
|
relative to the component, usually starting from
|
|
zero and counting up by one.
|
|
If you omit the identifier, then
|
|
FPP assigns a default identifier: zero for the first
|
|
parameter in the component; otherwise one more than the
|
|
identifier of the previous parameter.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>If you wish, you may explicitly specify one or more
|
|
parameter identifiers.
|
|
To do this, you write the keyword <code>id</code> followed
|
|
by a numeric expression after the data type
|
|
and after the default value, if any.
|
|
Here is an example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ An array of 3 F64 values
|
|
array F64x3 = [3] F64
|
|
|
|
@ A component for illustrating default parameter identifiers
|
|
passive component ParamIdentifiers {
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Ports
|
|
# ----------------------------------------------------------------------
|
|
|
|
@ Command receive port
|
|
command recv port cmdIn
|
|
|
|
@ Command registration port
|
|
command reg port cmdRegOut
|
|
|
|
@ Command response port
|
|
command resp port cmdResponseOut
|
|
|
|
@ Parameter get port
|
|
param get port prmGetOut
|
|
|
|
@ Parameter set port
|
|
param set port prmSetOut
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Parameters
|
|
# ----------------------------------------------------------------------
|
|
|
|
@ Parameter 1
|
|
@ Its implied identifier is 0x00
|
|
param Param1: U32 default 1
|
|
|
|
@ Parameter 2
|
|
@ Its identifier is 0x10
|
|
param Param2: F64 default 2.0 id 0x10
|
|
|
|
@ Parameter 3
|
|
@ Its implied identifier is 0x11
|
|
param Param3: F64x3 default [ 1.0, 2.0, 3.0 ]
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Within a component, the parameter identifiers must be unique.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Components_Parameters_Set-and-Save-Opcodes">10.8.4. Set and Save Opcodes</h4>
|
|
<div class="paragraph">
|
|
<p>Each parameter that you specify has two implied commands: one
|
|
for setting the value bound to the parameter locally in the
|
|
component, and one for saving the current local value
|
|
to the system-wide parameter database.
|
|
The opcodes for these implied commands are called the <strong>set and
|
|
save opcodes</strong> for the parameter.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>By default, FPP generates set and save opcodes for a
|
|
parameter <em>P</em> according to the following rules:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>If no command or parameter appears before <em>P</em> in the
|
|
component, then the set opcode is 0, and the save opcode is 1.</p>
|
|
</li>
|
|
<li>
|
|
<p>Otherwise, let <em>o</em> be the previous opcode defined
|
|
in the component
|
|
(either a command opcode or a parameter save opcode).
|
|
Then the set opcode is <em>o</em> + 1, and the save opcode is
|
|
<em>o</em> + 2.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>If you wish, you may specify either or both of the set and
|
|
save opcodes explicitly.
|
|
To specify the set opcode, you write the keywords <code>set</code> <code>opcode</code>
|
|
and a numeric expression.
|
|
To specify the save opcode, you write the keywords <code>save</code> <code>opcode</code>
|
|
and a numeric expression.
|
|
The set and save opcodes come after the type name, default
|
|
parameter value, and parameter identifier.
|
|
If both are present, the set opcode comes first.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>When you specify an explicit set or save opcode <em>o</em>, the
|
|
default value for the next opcode is <em>o</em> + 1.
|
|
Here is an example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ An array of 3 F64 values
|
|
array F64x3 = [3] F64
|
|
|
|
@ A component for illustrating parameter set and save opcodes
|
|
passive component ParamOpcodes {
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Ports
|
|
# ----------------------------------------------------------------------
|
|
|
|
@ Command receive port
|
|
command recv port cmdIn
|
|
|
|
@ Command registration port
|
|
command reg port cmdRegOut
|
|
|
|
@ Command response port
|
|
command resp port cmdResponseOut
|
|
|
|
@ Parameter get port
|
|
param get port prmGetOut
|
|
|
|
@ Parameter set port
|
|
param set port prmSetOut
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Parameters
|
|
# ----------------------------------------------------------------------
|
|
|
|
@ Parameter 1
|
|
@ Its implied set opcode is 0x00
|
|
@ Its implied save opcode is 0x01
|
|
param Param1: U32 default 1
|
|
|
|
@ Parameter 2
|
|
@ Its set opcode is 0x10
|
|
@ Its save opcode is 0x11
|
|
param Param2: F64 \
|
|
default 2.0 \
|
|
id 0x10 \
|
|
set opcode 0x10 \
|
|
save opcode 0x11
|
|
|
|
@ Parameter 3
|
|
@ Its set opcode is 0x12
|
|
@ Its save opcode is 0x20
|
|
param Param3: F64x3 \
|
|
default [ 1.0, 2.0, 3.0 ] \
|
|
save opcode 0x20
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Components_Parameters_External-Parameters">10.8.5. External Parameters</h4>
|
|
<div class="paragraph">
|
|
<p>In the default case, when you specify a parameter <em>P</em> in a component
|
|
<em>C</em>, the FPP code generator produces code for storing
|
|
and managing <em>P</em> as part of the auto-generated
|
|
code for <em>C</em>.
|
|
Sometimes it is more convenient to store and manage parameters separately.
|
|
For example, you may wish to integrate an F Prime component with a library
|
|
that stores and manages its own parameters.
|
|
In this case you can specify an <strong>external</strong> parameter.
|
|
An external parameter is like an ordinary parameter (also called
|
|
an internal parameter), except that its specifier begins
|
|
with the keyword <code>external</code>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Here is an example component definition that specifies two parameters,
|
|
an internal parameter <code>Param1</code> and an external parameter <code>Param2</code>.</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ A component for illustrating internal and external parameters
|
|
passive component ParamExternal {
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Ports
|
|
# ----------------------------------------------------------------------
|
|
|
|
@ Command receive port
|
|
command recv port cmdIn
|
|
|
|
@ Command registration port
|
|
command reg port cmdRegOut
|
|
|
|
@ Command response port
|
|
command resp port cmdResponseOut
|
|
|
|
@ Parameter get port
|
|
param get port prmGetOut
|
|
|
|
@ Parameter set port
|
|
param set port prmSetOut
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Parameters
|
|
# ----------------------------------------------------------------------
|
|
|
|
@ Param1 is an internal parameter
|
|
param Param1: U32
|
|
|
|
@ Param2 is an external parameter
|
|
external param Param2: F64 \
|
|
default 2.0 \
|
|
id 0x10 \
|
|
set opcode 0x10 \
|
|
save opcode 0x11
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>When you specify an external parameter, you are responsible for
|
|
providing the C++ code that stores and maintains the parameter.
|
|
The
|
|
<a href="https://fprime.jpl.nasa.gov/devel/docs/user-manual/framework/autocoded-functions/#parameters">F
|
|
Prime User Manual</a> explains how to do this.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Defining-Components_Data-Products">10.9. Data Products</h3>
|
|
<div class="paragraph">
|
|
<p>When defining an F Prime component, you may specify the <strong>data products</strong>
|
|
produced by that component.
|
|
A data product is a collection of related data that is stored onboard
|
|
and transmitted to the ground.
|
|
F Prime has special support for data products, including components
|
|
for (1) managing buffers that can store data products in memory;
|
|
(2) writing data products to the file system; and (3)
|
|
cataloging stored data products for downlink in priority order.
|
|
For more information about these F Prime features, see the
|
|
<a href="https://fprime.jpl.nasa.gov/devel/docs/user-manual/framework/data-products/">F
|
|
Prime User Manual</a>.</p>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Components_Data-Products_Basic-Data-Products">10.9.1. Basic Data Products</h4>
|
|
<div class="paragraph">
|
|
<p>In F Prime, a data product is represented as a <strong>container</strong>.
|
|
One container holds one data product, and each data product
|
|
is typically stored in its own file.
|
|
A container consists of a header, which provides information about
|
|
the container (e.g., the size of the data payload), and binary data
|
|
representing a list of serialized <strong>records</strong>.
|
|
A record is a unit of data.
|
|
For a complete specification of the container format, see the
|
|
<a href="https://fprime.jpl.nasa.gov/devel/Fw/Dp/docs/sdd/">F Prime design
|
|
documentation</a>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In an F Prime component, you can specify one or more containers
|
|
and one or more records.
|
|
The simplest container specification consists of the keywords <code>product</code> <code>container</code>
|
|
and a name.
|
|
The name is the name of the container.
|
|
The simplest record specification consists of the keywords <code>product</code> <code>record</code>,
|
|
a name, and a data type.
|
|
The name is the name of the record.
|
|
The data type is the type of the data that the record holds.
|
|
The data type must be a
|
|
<a href="#Defining-Components_Commands_Formal-Parameters">displayable type</a>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>As an example, here is a component called <code>BasicDataProducts</code> that specifies
|
|
two records and two containers.</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ A struct type defining some data
|
|
struct Data { a: U32, b: F32 }
|
|
|
|
@ A component for illustrating basic data products
|
|
passive component BasicDataProducts {
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Ports
|
|
# ----------------------------------------------------------------------
|
|
|
|
@ Product get port
|
|
product get port productGetOut
|
|
|
|
@ Product send port
|
|
product send port productSendOut
|
|
|
|
@ Time get port
|
|
time get port timeGetOut
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Records
|
|
# ----------------------------------------------------------------------
|
|
|
|
@ Record 1
|
|
product record Record1: I32
|
|
|
|
@ Record 2
|
|
product record Record2: Data
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Containers
|
|
# ----------------------------------------------------------------------
|
|
|
|
@ Container 1
|
|
product container Container1
|
|
|
|
@ Container 2
|
|
product container Container2
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The FPP back end uses this specification to generate code for requesting
|
|
buffers to hold containers and for serializing records into containers.
|
|
See the
|
|
<a href="https://fprime.jpl.nasa.gov/devel/docs/user-manual/framework/data-products/">F
|
|
Prime design documentation</a> for the details.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Note the following:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>Records are not specific to containers.
|
|
For example, with the specification shown above, you can serialize instances of
|
|
<code>Record1</code> and <code>Record2</code> into either or both of <code>Container1</code> and <code>Container2</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>Like telemetry channels, F Prime containers are component-centric.
|
|
A component can request containers that it defines, and it can fill those
|
|
containers with records that it defines.
|
|
It cannot use records or containers defined by another component.</p>
|
|
</li>
|
|
<li>
|
|
<p>If a component has container specifier, then it must have at least one record
|
|
specifier, and vice versa.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Components_Data-Products_Identifiers">10.9.2. Identifiers</h4>
|
|
<div class="paragraph">
|
|
<p>Every record in an F Prime FSW application has a unique
|
|
numeric identifier.
|
|
As for
|
|
<a href="#Defining-Components_Commands_Opcodes">command opcodes</a>,
|
|
<a href="#Defining-Components_Events_Identifiers">event identifiers</a>,
|
|
<a href="#Defining-Components_Telemetry_Identifiers">telemetry channel identifiers</a>, and
|
|
<a href="#Defining-Components_Parameters">parameters</a>,
|
|
the record identifiers for a component are specified
|
|
relative to the component, usually starting from
|
|
zero and counting up by one.
|
|
If you omit the identifier, then
|
|
FPP assigns a default identifier: zero for the first
|
|
event in the component; otherwise one more than the
|
|
identifier of the previous parameter.
|
|
The same observations apply to containers and container
|
|
identifiers.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>If you wish, you may explicitly specify one or more
|
|
container or record identifiers.
|
|
To do this, you write the keyword <code>id</code> followed
|
|
by a numeric expression at the end of the container
|
|
or record specifier.
|
|
Here is an example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ A struct type defining some data
|
|
struct Data { a: U32, b: F32 }
|
|
|
|
@ A component for illustrating data product identifiers
|
|
passive component DataProductIdentifiers {
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Ports
|
|
# ----------------------------------------------------------------------
|
|
|
|
@ Product get port
|
|
product get port productGetOut
|
|
|
|
@ Product send port
|
|
product send port productSendOut
|
|
|
|
@ Time get port
|
|
time get port timeGetOut
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Records
|
|
# ----------------------------------------------------------------------
|
|
|
|
@ Record 1
|
|
@ Its implied identifier is 0x00
|
|
product record Record1: I32
|
|
|
|
@ Record 2
|
|
@ Its identifier is 0x10
|
|
product record Record2: Data id 0x10
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Containers
|
|
# ----------------------------------------------------------------------
|
|
|
|
@ Container 1
|
|
@ Its identifier is 0x10
|
|
product container Container1 id 0x10
|
|
|
|
@ Container 2
|
|
@ Its implied identifier is 0x11
|
|
product container Container2
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Within a component, the record identifiers must be unique,
|
|
and the container identifiers must be unique.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Components_Data-Products_Array-Records">10.9.3. Array Records</h4>
|
|
<div class="paragraph">
|
|
<p>In the basic form of a record described above, each record that
|
|
does not have
|
|
<a href="#Defining-Types_Array-Type-Definitions_Type-Names">string type</a>
|
|
has a fixed, statically-specified size.
|
|
The record may contain an array (e.g., an
|
|
<a href="#Defining-Types_Array-Type-Definitions">array type</a>
|
|
or a struct type with a
|
|
<a href="#Defining-Types_Struct-Type-Definitions_Member-Arrays">member array</a>),
|
|
but the size of the array must be specified in the model.
|
|
To specify a record that is a dynamically-sized array, you put
|
|
the keyword <code>array</code> after the type specifier for the record.
|
|
For example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ A struct type defining some data
|
|
struct Data { a: U32, b: F32 }
|
|
|
|
@ A component for illustrating array records
|
|
passive component ArrayRecords {
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Ports
|
|
# ----------------------------------------------------------------------
|
|
|
|
@ Product get port
|
|
product get port productGetOut
|
|
|
|
@ Product send port
|
|
product send port productSendOut
|
|
|
|
@ Time get port
|
|
time get port timeGetOut
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Records
|
|
# ----------------------------------------------------------------------
|
|
|
|
@ A data record
|
|
@ It holds one element of type Data
|
|
product record DataRecord: Data
|
|
|
|
@ A data array record
|
|
@ It holds an array of elements of type Data
|
|
product record DataArrayRecord: Data array
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Containers
|
|
# ----------------------------------------------------------------------
|
|
|
|
@ A container
|
|
product container Container
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In this example, a record with name <code>DataArrayRecord</code> holds
|
|
an array of elements of type <code>Data</code>.
|
|
The number of elements is unspecified in the model;
|
|
it is provided when the record is serialized into a container.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Defining-Components_State-Machine-Instances">10.10. State Machine Instances</h3>
|
|
<div class="paragraph">
|
|
<p>A <strong>state machine instance</strong> is a component member that instantiates
|
|
an FPP <a href="#Defining-State-Machines">state machine</a>.
|
|
The state machine instance becomes part of the component implementation.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For example, here is a simple async component that has
|
|
one state machine instance and one async input port
|
|
for driving the state machine:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="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
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>When a state machine instance <em>m</em> is part of a component <em>C</em>,
|
|
each instance <em>c</em> of <em>C</em> sends <em>m</em> <strong>signals</strong> to process as it runs.
|
|
Signals occur in response to commands or port
|
|
invocations received by <em>c</em>, and they tell <em>m</em> when to change state.
|
|
<em>c</em> puts the signals on its queue, and <em>m</em> dispatches them.
|
|
Therefore, if a component <em>C</em> has a state machine instance member <em>m</em>,
|
|
then its instances <em>c</em> must have queues, i.e., <em>C</em> must be active or queued.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>As with <a href="#Defining-Components_Internal-Ports">internal ports</a>,
|
|
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:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="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
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>As discussed
|
|
<a href="#Defining-State-Machines_Writing-a-State-Machine-Definition">above</a>, state
|
|
machine definitions may be internal (specified in FPP) or external (specified
|
|
by an external tool). For more details about the C++ code generation for
|
|
instances of internal state machines, see the
|
|
<a href="https://fprime.jpl.nasa.gov/devel/docs/user-manual/framework/state-machines/">F
|
|
Prime design documentation</a>.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Defining-Components_Constants-Types-Enums-and-State-Machines">10.11. Constants, Types, Enums, and State Machines</h3>
|
|
<div class="paragraph">
|
|
<p>You can write a <a href="#Defining-Constants">constant definition</a>,
|
|
<a href="#Defining-Types">type definition</a>,
|
|
<a href="#Defining-Enums">enum definition</a>,
|
|
or
|
|
<a href="#Defining-State-Machines">state machine definition</a>
|
|
as a component member.
|
|
When you do this, the component qualifies
|
|
the name of the constant or type, similarly to the way that a
|
|
<a href="#Defining-Modules">module</a> qualifies the names of the
|
|
definitions it contains.
|
|
For example, if you define a type <code>T</code> inside a component
|
|
<code>C</code>, then</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>Inside the definition of <code>C</code>, you can refer to the
|
|
type as <code>T</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>Outside the definition of <code>C</code>, you must refer to the
|
|
type as <code>C.T</code>.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>As an example, here is the <code>SerialSplitter</code> component
|
|
from the section on
|
|
<a href="#Defining-Components_Port-Instances_Serial-Port-Instances">serial port instances</a>, where we have moved the
|
|
definition of the constant <code>splitFactor</code>
|
|
into the definition of the component.</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ Component for splitting a serial data stream
|
|
passive component SerialSplitter {
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Constants
|
|
# ----------------------------------------------------------------------
|
|
|
|
@ Split factor
|
|
constant splitFactor = 10
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Ports
|
|
# ----------------------------------------------------------------------
|
|
|
|
@ Input
|
|
sync input port serialIn: serial
|
|
|
|
@ Output
|
|
output port serialOut: [splitFactor] serial
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>As another example, here is the <code>Switch</code> component from the section on
|
|
<a href="#Defining-Components_Commands_Formal-Parameters">command formal parameters</a>, where we have moved the definition of
|
|
the enum <code>State</code> into the component:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ A switch with on and off state
|
|
active component Switch {
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Types
|
|
# ----------------------------------------------------------------------
|
|
|
|
@ The state enumeration
|
|
enum State {
|
|
OFF @< The off state
|
|
ON @< The on state
|
|
}
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Ports
|
|
# ----------------------------------------------------------------------
|
|
|
|
@ Command input
|
|
command recv port cmdIn
|
|
|
|
@ Command registration
|
|
command reg port cmdRegOut
|
|
|
|
@ Command response
|
|
command resp port cmdResponseOut
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Commands
|
|
# ----------------------------------------------------------------------
|
|
|
|
@ Set the state
|
|
async command SET_STATE(
|
|
$state: State @< The new state
|
|
)
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In general, it is a good idea to state a definition inside a component
|
|
when the definition logically belongs to the component.
|
|
The name scoping mechanism emphasizes the hierarchical relationship
|
|
and prevents name clashes.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In most cases, a qualified name such as <code>Switch.State</code>
|
|
in FPP becomes a qualified name such as <code>Switch::State</code> when translating
|
|
to C++.
|
|
However, the current C++ code generation strategy does not
|
|
support the definition
|
|
of constants and types as members of C++ components.
|
|
Therefore, when translating the previous example to C++,
|
|
the following occurs:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>The component <code>Switch</code> becomes an auto-generated C++ class
|
|
<code>SwitchComponentBase</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>The type <code>State</code> becomes a C++ class <code>Switch_State</code>.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Similarly, the FPP constant <code>SerialSplitter.splitFactor</code>
|
|
becomes a C++ constant <code>SerialSplitter_SplitFactor</code>.
|
|
We will have more to say about this issue in the section on
|
|
<a href="#Analyzing-and-Translating-Models_Generating-C-Plus-Plus">generating C++</a>.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Defining-Components_Include-Specifiers">10.12. Include Specifiers</h3>
|
|
<div class="paragraph">
|
|
<p>Component definitions can become long, especially when there
|
|
are many commands, events, telemetry channels, and parameters.
|
|
In this case it is useful to break up the component
|
|
definition into several files.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For example, suppose you are defining a component with
|
|
many commands, and you wish to place the commands in a
|
|
separate file <code>Commands.fppi</code>.
|
|
The suffix <code>.fppi</code> is conventional for included FPP files.
|
|
Inside the component definition, you can write the
|
|
following component member:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">include "Commands.fppi"</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>This construct is called an <strong>include specifier</strong>.
|
|
During analysis and translation, the include specifier
|
|
is replaced with the commands specified
|
|
in <code>Commands.fppi</code>, just as if you had written them
|
|
at the point where you wrote the include specifier.
|
|
This replacement is called expanding or resolving the
|
|
include specifier.
|
|
You can use the same technique for events, telemetry,
|
|
parameters, or any other component members.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The text enclosed in quotation marks after the keyword
|
|
<code>include</code> is a path name relative to the directory of the
|
|
file in which the include specifier appears.
|
|
The file must exist and must contain component members
|
|
that can validly appear at the point where the include
|
|
specifier appears.
|
|
For example, if <code>Commands.fppi</code> contains invalid syntax
|
|
or syntax that may not appear inside a component,
|
|
or if the file <code>Commands.fppi</code> does not exist, then
|
|
the specifier <code>include "Commands.fppi"</code> is not valid.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Include specifiers are perhaps most useful when defining
|
|
components, but they can also appear at the top level of a
|
|
model, inside a module definition, or inside a
|
|
topology definition.
|
|
We discuss include specifiers further in the section on
|
|
<a href="#Specifying-Models-as-Files_Include-Specifiers">specifying models as files</a>.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Defining-Components_Matched-Ports">10.13. Matched Ports</h3>
|
|
<div class="paragraph">
|
|
<p>Some F Prime components employ the following pattern:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>The component has a pair of port arrays, say <code>p1</code> and <code>p2</code>.
|
|
The two arrays have the same number of ports.</p>
|
|
</li>
|
|
<li>
|
|
<p>For every connection between <code>p1</code> and another component
|
|
instance, there must be a matching connection between that
|
|
component instance and <code>p2</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>The matched pairs in item 2 must be connected to the
|
|
same port numbers at <code>p1</code> and <code>p2</code>.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In this case we call <code>p1</code> and <code>p2</code> a pair of
|
|
<strong>matched ports</strong>.
|
|
For example:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>The standard Command Dispatcher component has matched ports
|
|
<code>compCmdReg</code> for receiving command registration and
|
|
<code>compCmdSend</code> for sending commands.</p>
|
|
</li>
|
|
<li>
|
|
<p>The standard Health component has matched ports
|
|
<code>PingSend</code> for sending health ping messages and
|
|
<code>PingReturn</code> for receiving responses to the ping messages.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>FPP provides special support for matched ports.
|
|
Inside a component definition, you can write
|
|
<code>match p1 with p2</code>, where <code>p1</code> and <code>p2</code> are the names of
|
|
<a href="#Defining-Components_Port-Instances">port instances</a>
|
|
defined in the component.
|
|
When you do this, the following occurs:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>The FPP translator checks that <code>p1</code> and <code>p2</code> have
|
|
the same number of ports.
|
|
If not, an error occurs.</p>
|
|
</li>
|
|
<li>
|
|
<p>When
|
|
<a href="#Defining-Topologies_Port-Numbering_Matched-Numbering">automatically numbering a topology</a>, the
|
|
translator ensures that the port numbers match in the manner
|
|
described above.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For example, here is a simplified version of the Health
|
|
component:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ Number of health ping ports
|
|
constant numPingPorts = 10
|
|
|
|
queued component Health {
|
|
|
|
@ Ping output port
|
|
output port pingOut: [numPingPorts] Svc.Ping
|
|
|
|
@ Ping input port
|
|
async input port pingIn: [numPingPorts] Svc.Ping
|
|
|
|
@ Corresponding port numbers of pingOut and pingIn must match
|
|
match pingOut with pingIn
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>This component defines a pair of matched ports
|
|
<code>pingOut</code> and <code>pingIn</code>.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="Defining-and-Using-Port-Interfaces">11. Defining and Using Port Interfaces</h2>
|
|
<div class="sectionbody">
|
|
<div class="paragraph">
|
|
<p>A common pattern in F Prime is to use an identical set of
|
|
<a href="#Defining-Components_Port-Instances">port instances</a>
|
|
in the definitions of each of several components.
|
|
For example, each of several driver components may specify
|
|
an identical set of ports for sending and receiving data.
|
|
Such a set of port instances is called a <strong>port interface</strong>
|
|
(interface for short).
|
|
FPP has special support for defining and using port interfaces,
|
|
which we describe in this section.</p>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Defining-and-Using-Port-Interfaces_Defining-Port-Interfaces">11.1. Defining Port Interfaces</h3>
|
|
<div class="paragraph">
|
|
<p>A <strong>port interface definition</strong> defines a port interface.
|
|
To write a port interface definition, you write the following:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>The keyword <code>interface</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>The <a href="#Defining-Constants_Names">name</a> of the interface.</p>
|
|
</li>
|
|
<li>
|
|
<p>A sequence of <strong>port interface members</strong> enclosed in curly braces
|
|
<code>{</code> …​ <code>}</code>.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>A port interface member may directly specify a
|
|
<a href="#Defining-Components_Port-Instances">general port instance</a> or a
|
|
<a href="#Defining-Components_Special-Port-Instances">special port instance</a>.
|
|
For example, here is a port interface representing a binary operation
|
|
that takes two <code>F32</code> inputs and produces an <code>F32</code> output:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ A port for carrying an F32 value
|
|
port F32Value(value: F32)
|
|
|
|
@ A priority constant for async F32 binary operation input
|
|
constant AsyncF32BinopInputPriority = 10
|
|
|
|
@ An active component for adding two F32 values with specified priorities
|
|
interface AsyncF32Binop {
|
|
|
|
@ Input 1 at priority 10
|
|
async input port f32ValueIn1: F32Value priority AsyncF32BinopInputPriority
|
|
|
|
@ Input 2 at priority 20
|
|
async input port f32ValueIn2: F32Value priority AsyncF32BinopInputPriority
|
|
|
|
@ Output
|
|
output port f32ValueOut: F32Value
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>This interface represents the input and output ports for any
|
|
binary operation: addition, multiplication, etc.
|
|
An interface member may also import the definition of another interface;
|
|
we describe this option
|
|
<a href="#Defining-and-Using-Port-Interfaces_Using-Port-Interfaces-in-Interface-Definitions">below</a>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>An interface definition and each of its members is an
|
|
<a href="#Writing-Comments-and-Annotations_Annotations">annotatable element</a>.
|
|
For example, you can annotate the interface as shown above.
|
|
The members of a interface form an
|
|
<a href="#Defining-Constants_Multiple-Definitions-and-Element-Sequences">element sequence</a> with a semicolon as the optional
|
|
terminating punctuation.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In general, port instances that appear in port interfaces must follow the same rules
|
|
as
|
|
<a href="#Defining-Components_Port-Instances">port instances that appear in
|
|
components</a>.
|
|
For example, each port name appearing in the interface must
|
|
be distinct.
|
|
The rules specific to active, passive, and queued components
|
|
do not apply to interfaces; those are checked when the interface
|
|
is used in a component, as described in the next section.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Defining-and-Using-Port-Interfaces_Using-Port-Interfaces-in-Component-Definitions">11.2. Using Port Interfaces in Component Definitions</h3>
|
|
<div class="paragraph">
|
|
<p>Once you have defined a port interface, you can use it in a component definition.
|
|
To do this you write a <a href="#Defining-Components_Component-Definitions">component
|
|
member</a> consisting of the keyword <code>import</code> followed by the interface name.
|
|
For example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ An active component for adding two F32 values
|
|
active component ActiveF32Adder {
|
|
|
|
@ Import the AsyncF32Binop interface
|
|
import AsyncF32Binop
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>This component is identical to the <code>ActiveF32Adder</code> component
|
|
that we defined in the section on
|
|
<a href="#Defining-Components_Port-Instances_Basic-Port-Instances">basic port instances</a>, except that we have factored the input
|
|
and output ports into an interface.
|
|
We can then use the same interface to define an <code>ActiveF32Multiplier</code>
|
|
component:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ An active component for multiplying two F32 values
|
|
active component ActiveF32Multiplier {
|
|
|
|
@ Import the AsyncF32Binop interface
|
|
import AsyncF32Binop
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>This component is identical to <code>ActiveF32Adder</code>, except
|
|
that it performs multiplication instead of addition.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In general, a component member <code>import</code> <em>I</em> member is analyzed by (1)
|
|
resolving the interface <em>I</em> to a set of port instances
|
|
and (2) adding each of the port instances to the component.
|
|
After this resolution, all the rules for component definition
|
|
must be obeyed.
|
|
For example, this component definition is illegal,
|
|
because it has a duplicate port name:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">port P
|
|
|
|
interface I {
|
|
sync input port p: P
|
|
}
|
|
|
|
passive component C {
|
|
|
|
@ Port instance p is imported here
|
|
import I
|
|
|
|
@ Port instance name p is a duplicate here
|
|
sync input port p: P
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Defining-and-Using-Port-Interfaces_Using-Port-Interfaces-in-Interface-Definitions">11.3. Using Port Interfaces in Interface Definitions</h3>
|
|
<div class="paragraph">
|
|
<p>You can import a port interface into another interface.
|
|
For example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">port P
|
|
|
|
interface I1 {
|
|
sync input port p1: P
|
|
}
|
|
|
|
interface I2 {
|
|
import I1
|
|
sync input port p2: P
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Either <code>I1</code> or <code>I2</code> may be imported into a component
|
|
or into another interface.
|
|
Interface <code>I2</code> is functionally equivalent to the
|
|
following:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">port P
|
|
|
|
interface I2 {
|
|
sync input port p1: P
|
|
sync input port p2: P
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="Defining-Component-Instances">12. Defining Component Instances</h2>
|
|
<div class="sectionbody">
|
|
<div class="paragraph">
|
|
<p>As discussed in the section on <a href="#Defining-Components">defining-components</a>,
|
|
in F Prime you define components and instantiate them.
|
|
Then you construct a <strong>topology</strong>, which is a graph
|
|
that specifies the connections between the components.
|
|
This section explains how to define component instances.
|
|
In the next section, we will explain how to
|
|
construct topologies.</p>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Defining-Component-Instances_Component-Instance-Definitions">12.1. Component Instance Definitions</h3>
|
|
<div class="paragraph">
|
|
<p>To instantiate a component, you write a <strong>component instance definition</strong>.
|
|
The form of a component instance definition depends on the kind
|
|
of the component you are instantiating: passive, queued, or active.</p>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Component-Instances_Component-Instance-Definitions_Passive-Components">12.1.1. Passive Components</h4>
|
|
<div class="paragraph">
|
|
<p>To instantiate a passive component, you write the following:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>The keyword <code>instance</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>The <a href="#Defining-Constants_Names">name</a> of the instance.</p>
|
|
</li>
|
|
<li>
|
|
<p>A colon <code>:</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>The name of a <a href="#Defining-Components_Component-Definitions">component definition</a>.</p>
|
|
</li>
|
|
<li>
|
|
<p>The keywords <code>base</code> <code>id</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>An <a href="#Defining-Constants_Expressions">expression</a> denoting
|
|
the <strong>base identifier</strong> associated with the component instance.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The base identifier must resolve to a number.
|
|
The FPP translator adds this number to each of the component-relative
|
|
<a href="#Defining-Components_Commands_Opcodes">command opcodes</a>,
|
|
<a href="#Defining-Components_Events_Identifiers">event identifiers</a>,
|
|
<a href="#Defining-Components_Telemetry_Identifiers">telemetry channel identifiers</a>,
|
|
and
|
|
<a href="#Defining-Components_Parameters_Identifiers">parameter identifiers</a>
|
|
specified in the component, as discussed in the previous section.
|
|
The base identifier for the instance plus the component-relative
|
|
opcode or identifier for the component gives the corresponding
|
|
opcode or identifier for the instance.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Here is an example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">module Sensors {
|
|
|
|
@ A component for sensing engine temperature
|
|
passive component EngineTemp {
|
|
|
|
@ Schedule input port
|
|
sync input port schedIn: Svc.Sched
|
|
|
|
@ Telemetry port
|
|
telemetry port tlmOut
|
|
|
|
@ Time get port
|
|
time get port timeGetOut
|
|
|
|
@ Impulse engine temperature
|
|
telemetry ImpulseTemp: F32
|
|
|
|
@ Warp core temperature
|
|
telemetry WarpTemp: F32
|
|
|
|
}
|
|
|
|
}
|
|
|
|
module FSW {
|
|
|
|
@ Engine temperature instance
|
|
instance engineTemp: Sensors.EngineTemp base id 0x100
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>We have defined a passive component <code>Sensors.EngineTemp</code> with three ports:
|
|
a schedule input port for driving the component periodically on a rate group,
|
|
a time get port for getting the time, and a telemetry port
|
|
for reporting telemetry.
|
|
(For more information on rate groups and the use of <code>Svc.Sched</code>
|
|
ports, see the
|
|
<a href="https://fprime.jpl.nasa.gov/devel/docs/user-manual/design-patterns/rate-group/">F
|
|
Prime documentation</a>.)
|
|
We have given the component two telemetry channels:
|
|
<code>ImpulseTemp</code> for reporting the temperature of the impulse engine,
|
|
and <code>WarpTemp</code> for reporting the temperature of the warp core.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Next we have defined an instance <code>FSW.engineTemp</code> of component <code>Sensors.EngineTemp</code>.
|
|
Because the instance definition is in a different module from the
|
|
component definition, we must refer to the component by its
|
|
qualified name <code>Sensors.EngineTemp</code>.
|
|
If we wrote</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">instance engineTemp: EngineTemp base id 0x100</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>the FPP compiler would complain that the symbol <code>EngineTemp</code> is undefined
|
|
(try it and see).</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>We have specified that the base identifier of instance <code>FSW.engineTemp</code>
|
|
is the hexadecimal number 0x100 (256 decimal).
|
|
In the component definition, the telemetry channel <code>ImpulseTemp</code>
|
|
has relative identifier 0, and the telemetry channel <code>WarpTemp</code>
|
|
has relative identifier 1.
|
|
Therefore the corresponding telemetry channels for the instance
|
|
<code>FSW.engineTemp</code> have identifiers 0x100 and 0x101 (256 and 257)
|
|
respectively.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For consistency, the base identifier is required for all component instances,
|
|
even instances that define no dictionary elements (commands, events, telemetry,
|
|
or parameters).
|
|
For each component instance <em>I</em>, the range of numbers between the base
|
|
identifier and the base identifier plus the largest relative identifier
|
|
is called the <strong>identifier range</strong> of <em>I</em>.
|
|
If a component instance defines no dictionary elements, then the
|
|
identifier range is empty.
|
|
All the numbers in the identifier range of <em>I</em> are reserved for
|
|
instance <em>I</em> (even if they are not all used).
|
|
No other component instance may have a base identifier that lies within the
|
|
identifier range of <em>I</em>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For example, this code is illegal:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">module FSW {
|
|
|
|
@ Temperature sensor for the left engine
|
|
instance leftEngineTemp: Sensors.EngineTemp base id 0x100
|
|
|
|
@ Temperature sensor for the right engine
|
|
instance rightEngineTemp: Sensors.EngineTemp base id 0x101
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The base identifier 0x101 for <code>rightEngineTemp</code> is inside the
|
|
identifier range for <code>leftEngineTemp</code>, which goes from
|
|
0x100 to 0x101, inclusive.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Component-Instances_Component-Instance-Definitions_Queued-Components">12.1.2. Queued Components</h4>
|
|
<div class="paragraph">
|
|
<p>Instantiating a queued component is just like instantiating
|
|
a passive component, except that you must also specify
|
|
a queue size for the instance.
|
|
You do this by writing the keywords <code>queue</code> <code>size</code> and
|
|
the queue size after the base identifier.
|
|
Here is an example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">module Sensors {
|
|
|
|
@ A port for calibration input
|
|
port Calibration(cal: F32)
|
|
|
|
@ A component for sensing engine temperature
|
|
queued component EngineTemp {
|
|
|
|
@ Schedule input port
|
|
sync input port schedIn: Svc.Sched
|
|
|
|
@ Calibration input
|
|
async input port calibrationIn: Calibration
|
|
|
|
@ Telemetry port
|
|
telemetry port tlmOut
|
|
|
|
@ Time get port
|
|
time get port timeGetOut
|
|
|
|
@ Impulse engine temperature
|
|
telemetry ImpulseTemp: F32
|
|
|
|
@ Warp core temperature
|
|
telemetry WarpTemp: F32
|
|
|
|
}
|
|
|
|
}
|
|
|
|
module FSW {
|
|
|
|
@ Engine temperature sensor
|
|
instance engineTemp: Sensors.EngineTemp base id 0x100 \
|
|
queue size 10
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In the component definition, we have revised the example from the previous
|
|
section so that
|
|
the <code>EngineTemp</code> component is queued instead of passive,
|
|
and we have added an async input port for calibration input.
|
|
In the component instance definition, we have specified a queue size of 10.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Component-Instances_Component-Instance-Definitions_Active-Components">12.1.3. Active Components</h4>
|
|
<div class="paragraph">
|
|
<p>Instantiating an active component is like instantiating a queued
|
|
component, except that you may specify additional parameters
|
|
that configure the OS thread associated with each component instance.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Queue size, stack size, and priority:</strong>
|
|
When instantiating an active component, you <em>must</em>
|
|
specify a queue size, and you <em>may</em> specify either or both of
|
|
a stack size and priority.
|
|
You specify the queue size in the same way as for a queued component.
|
|
You specify the stack size by writing the keywords <code>stack</code> <code>size</code>
|
|
and the desired stack size in bytes.
|
|
You specify the priority by writing the keyword <code>priority</code>
|
|
and a numeric priority.
|
|
The priority number is passed to the OS operation for creating
|
|
the thread, and its meaning is OS-specific.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Here is an example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">module Utils {
|
|
|
|
@ A component for compressing data
|
|
active component DataCompressor {
|
|
|
|
@ Uncompressed input data
|
|
async input port bufferSendIn: Fw.BufferSend
|
|
|
|
@ Compressed output data
|
|
output port bufferSendOut: Fw.BufferSend
|
|
|
|
}
|
|
|
|
}
|
|
|
|
module FSW {
|
|
|
|
module Default {
|
|
@ Default queue size
|
|
constant queueSize = 10
|
|
@ Default stack size
|
|
constant stackSize = 10 * 1024
|
|
}
|
|
|
|
@ Data compressor instance
|
|
instance dataCompressor: Utils.DataCompressor base id 0x100 \
|
|
queue size Default.queueSize \
|
|
stack size Default.stackSize \
|
|
priority 30
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>We have defined an active component <code>Utils.DataCompressor</code>
|
|
for compressing data.
|
|
We have defined an instance of this component called
|
|
<code>FSW.dataCompressor</code>.
|
|
Our instance has base identifier 0x100, the default
|
|
queue size, the default stack size, and priority 30.
|
|
We have used
|
|
<a href="#Defining-Constants">constant definitions</a> for
|
|
the default queue and stack sizes.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>We could also have omitted either or both of the stack size and priority
|
|
specifiers.
|
|
When you omit the stack size or priority from a component instance
|
|
definition, F Prime supplies a default value appropriate to the
|
|
target platform.
|
|
With implicit stack size and priority, the <code>dataCompressor</code>
|
|
instance looks like this:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">instance dataCompressor: Utils.DataCompressor base id 0x100 \
|
|
queue size Default.queueSize</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>CPU affinity:</strong>
|
|
When defining an active component, you may specify
|
|
a <strong>CPU affinity</strong>.
|
|
The CPU affinity is a number whose meaning depends on
|
|
the platform.
|
|
Usually it is an instruction to the operating system
|
|
to run the thread of the active component on a particular
|
|
CPU, identified by number.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>To specify CPU affinity, you write the keyword <code>cpu</code>
|
|
and the CPU number after the queue size, the stack size (if any),
|
|
and the priority specifier (if any).
|
|
For example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">instance dataCompressor: Utils.DataCompressor base id 0x100 \
|
|
queue size Default.queueSize \
|
|
stack size Default.stackSize \
|
|
priority 30 \
|
|
cpu 0</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>This example is the same as the previous <code>dataCompressor</code>
|
|
instance, except that we have specified that the thread
|
|
associated with the instance should run on CPU 0.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>With implicit stack size and priority, the example looks like this:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">instance dataCompressor: Utils.DataCompressor base id 0x100 \
|
|
queue size Default.queueSize \
|
|
cpu 0</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Defining-Component-Instances_Specifying-the-Implementation">12.2. Specifying the Implementation</h3>
|
|
<div class="paragraph">
|
|
<p>When you define a component instance <em>I</em>, the FPP translator needs
|
|
to know the following information about the C++ implementation of <em>I</em>:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>The type (i.e., the name of the C++ class) that defines the
|
|
implementation.</p>
|
|
</li>
|
|
<li>
|
|
<p>The location of the C++ header file that declares the implementation
|
|
class.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In most cases, the translator can infer this information.
|
|
However, in some cases you must specify it manually.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>The implementation type:</strong>
|
|
The FPP translator can automatically infer the implementation
|
|
type if its qualified C++ class name matches the qualified
|
|
name of the FPP component.
|
|
For example, the C++ class name <code>A::B</code> matches the FPP component
|
|
name <code>A.B</code>.
|
|
More generally, modules in FPP become namespaces in C++, so
|
|
dot qualifiers in FPP become double-colon qualifiers in C++.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>If the names do not match, then you must provide the type
|
|
associated with the implementation.
|
|
You do this by writing the keyword <code>type</code> after the base identifier,
|
|
followed by a <a href="#Defining-Constants_Expressions_String-Values">string</a>
|
|
specifying the implementation type.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For example, suppose we have a C++ class <code>Utils::SpecialDataCompressor</code>,
|
|
which is a specialized implementation of the FPP component
|
|
<code>Utils.DataCompressor</code>.
|
|
By default, when we specify <code>Utils.DataCompressor</code> as the component name, the
|
|
translator infers <code>Utils::DataCompressor</code> as the implementation type.
|
|
Here is how we specify the implementation type <code>Utils::SpecialDataCompressor</code>:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">instance dataCompressor: Utils.DataCompressor base id 0x100 \
|
|
type "Utils::SpecialDataCompressor" \
|
|
queue size Default.queueSize \
|
|
cpu 0</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>The header file:</strong>
|
|
The FPP translator can automatically locate the header file for <em>I</em>
|
|
if it conforms to the following rules:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>The name of the header file is <code>Name.hpp</code>, where <code>Name</code>
|
|
is the name of the component in the FPP model, without
|
|
any module qualifiers.</p>
|
|
</li>
|
|
<li>
|
|
<p>The header file is located in the same directory as the FPP
|
|
source file that defines the component.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For example, the F Prime repository contains a reference FSW implementation
|
|
with instances defined in the file <code>Ref/Top/instances.fpp</code>.
|
|
One of the instances is <code>SG1</code>.
|
|
Its definition reads as follows:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">instance SG1: Ref.SignalGen base id 0x2100 \
|
|
queue size Default.queueSize</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The FPP component <code>Ref.SignalGen</code> is
|
|
defined in the directory <code>Ref/SignalGen/SignalGen.fpp</code>,
|
|
and the implementation class <code>Ref::SignalGen</code> is declared in
|
|
the header file <code>Ref/SignalGen/SignalGen.hpp</code>.
|
|
In this case, the header file follows rules (1) and (2)
|
|
stated above, so the FPP translator can automatically locate
|
|
the file.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>If the implementation header file does not follow
|
|
rules (1) and (2) stated above, then you must specify
|
|
the name and location of the header file by hand.
|
|
You do that by writing the keyword <code>at</code> followed by
|
|
a <a href="#Defining-Constants_Expressions_String-Values">string</a>
|
|
specifying the header file path.
|
|
The header file path is relative to the directory
|
|
containing the source file that defines the component
|
|
instance.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For example, the F Prime repository has a directory
|
|
<code>Svc/Time</code> that contains an FPP model for a component <code>Svc.Time</code>.
|
|
Because the C++ implementation for this component
|
|
is platform-specific, the directory <code>Svc/Time</code> doesn’t
|
|
contain any implementation.
|
|
Instead, when instantiating the component, you have to
|
|
provide the header file to an implementation located
|
|
in a different directory.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The F Prime repository also provides a Linux-specific implementation
|
|
of the <code>Time</code> component in the directory <code>Svc/LinuxTime</code>.
|
|
The file <code>Ref/Top/instances.fpp</code> contains an instance definition
|
|
<code>linuxTime</code> that reads as follows:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">instance linuxTime: Svc.Time base id 0x4500 \
|
|
type "Svc::LinuxTime" \
|
|
at "../../Svc/LinuxTime/LinuxTime.hpp"</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>This definition says to use the implementation of the component
|
|
<code>Svc.Time</code> with C++ type name <code>Svc::LinuxTime</code> defined in the header
|
|
file <code>../../Svc/LinuxTime/LinuxTime.hpp</code>.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Defining-Component-Instances_Init-Specifiers">12.3. Init Specifiers</h3>
|
|
<div class="paragraph">
|
|
<p>In an F Prime FSW application, each component instance <em>I</em>
|
|
has some associated C++ code
|
|
for setting up <em>I</em> when FSW starts up
|
|
and tearing down <em>I</em> when FSW exits.
|
|
Much of this code can be inferred from the FPP model,
|
|
but some of it is implementation-specific.
|
|
For example, each instance of the standard F Prime command sequencer
|
|
component has a method <code>allocateBuffer</code> that the FSW must
|
|
call during setup to allocate the sequence buffer
|
|
for that instance.
|
|
The FPP model does not represent this function;
|
|
instead, you have to provide
|
|
the function call directly in C++.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>To do this, you write one or more <strong>init specifiers</strong>
|
|
as part of a component instance definition.
|
|
An init specifier names a phase
|
|
of the setup or teardown process and
|
|
provides a snippet of literal C++ code.
|
|
The FPP translator pastes the snippet into the setup
|
|
or teardown code according to the phase named in
|
|
the specifier.
|
|
(Strictly speaking, the init specifier should be called
|
|
a "setup or teardown specifier."
|
|
However, most of the code is in fact initialization code,
|
|
and so FPP uses "init" as a shorthand name.)</p>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Component-Instances_Init-Specifiers_Execution-Phases">12.3.1. Execution Phases</h4>
|
|
<div class="paragraph">
|
|
<p>The FPP translator uses init specifiers when it generates
|
|
code for an F Prime topology.
|
|
We will have more to say about topology generation in the
|
|
next section.
|
|
For now, you just need to know the following:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>A topology is a unit of an FPP model that specifies the top-level
|
|
structure of an F Prime application (the component instances
|
|
and their connections).</p>
|
|
</li>
|
|
<li>
|
|
<p>Each topology has a name, which we will refer to here generically as <em>T</em>.</p>
|
|
</li>
|
|
<li>
|
|
<p>When generating C++ code for topology <em>T</em>, the code generator produces
|
|
files <em>T</em> <code>TopologyAc.hpp</code> and <em>T</em> <code>TopologyAc.cpp</code>.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The generated code in <em>T</em> <code>TopologyAc.hpp</code> and <em>T</em> <code>TopologyAc.cpp</code>
|
|
is divided into several phases of execution.
|
|
Table <a href="#execution-phases">Execution Phases</a> shows the execution phases
|
|
recognized by the FPP code generator.
|
|
In this table, <em>T</em> is the name of a topology and <em>I</em> is the
|
|
name of a component instance.
|
|
The columns of the table have the following meanings:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p><strong>Phase:</strong> The symbol denoting the execution phase.
|
|
These symbols are the enumerated constants of the
|
|
<a href="#Defining-Enums">enum</a> <code>Fpp.ToCpp.Phases</code> defined in
|
|
<code>Fpp/ToCpp.fpp</code> in the F Prime repository.</p>
|
|
</li>
|
|
<li>
|
|
<p><strong>Generated File:</strong> The generated file for topology <em>T</em>
|
|
that contains the definition:
|
|
either <em>T</em> <code>TopologyAc.hpp</code> (for compile-time symbols)
|
|
or <em>T</em> <code>TopologyAc.cpp</code> (for link-time symbols).</p>
|
|
</li>
|
|
<li>
|
|
<p><strong>Intended Use:</strong> The intended use of the C++ code snippet
|
|
associated with the instance <em>I</em> and the phase.</p>
|
|
</li>
|
|
<li>
|
|
<p><strong>Where Placed:</strong> Where FPP places the code snippet
|
|
in the generated file.</p>
|
|
</li>
|
|
<li>
|
|
<p><strong>Default Code:</strong> Whether FPP generates default code if
|
|
there is no init specifier for instance <em>I</em>
|
|
and for this phase.
|
|
If there is an init specifier, then it replaces any
|
|
default code.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<table id="execution-phases" class="tableblock frame-all grid-all stretch">
|
|
<caption class="title">Table 1. Execution Phases</caption>
|
|
<colgroup>
|
|
<col style="width: 20%;">
|
|
<col style="width: 20%;">
|
|
<col style="width: 20%;">
|
|
<col style="width: 20%;">
|
|
<col style="width: 20%;">
|
|
</colgroup>
|
|
<thead>
|
|
<tr>
|
|
<th class="tableblock halign-left valign-top">Phase</th>
|
|
<th class="tableblock halign-left valign-top">Generated File</th>
|
|
<th class="tableblock halign-left valign-top">Intended Use</th>
|
|
<th class="tableblock halign-left valign-top">Where Placed</th>
|
|
<th class="tableblock halign-left valign-top">Default Code</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>configConstants</code></p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>T</em> <code>TopologyAc.hpp</code></p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">C++ constants for use in constructing and
|
|
initializing an instance <em>I</em>.</p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">In the namespace <code>ConfigConstants::</code> <em>I</em>.</p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">None.</p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>configObjects</code></p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>T</em> <code>TopologyAc.cpp</code></p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">Statically declared C++ objects for use in
|
|
constructing and initializing instance <em>I</em>.</p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">In the namespace <code>ConfigObjects::</code> <em>I</em>.</p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">None.</p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>instances</code></p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>T</em> <code>TopologyAc.cpp</code></p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">A constructor for an instance <em>I</em> that has a non-standard
|
|
constructor format.</p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">In an anonymous (file-private) namespace.</p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">The standard constructor call for <em>I</em>.</p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>initComponents</code></p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>T</em> <code>TopologyAc.cpp</code></p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">Initialization code for an instance <em>I</em> that has a non-standard
|
|
initialization format.</p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">In the file-private function <code>initComponents</code>.</p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">The standard call to <code>init</code> for <em>I</em>.</p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>configComponents</code></p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>T</em> <code>TopologyAc.cpp</code></p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">Implementation-specific configuration code for an instance <em>I</em>.</p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">In the file-private function <code>configComponents</code>.</p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">None.</p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>regCommands</code></p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>T</em> <code>TopologyAc.cpp</code></p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">Code for registering the commands of <em>I</em> (if any)
|
|
with the command dispatcher.
|
|
Required only if <em>I</em> has a
|
|
non-standard command registration format.</p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">In the file-private function <code>regCommands</code>.</p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">The standard call to <code>regCommands</code> if <em>I</em> has commands;
|
|
otherwise none.</p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>readParameters</code></p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>T</em> <code>TopologyAc.cpp</code></p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">Code for reading parameters from a file.
|
|
Ordinarily used only when <em>I</em> is the parameter database.</p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">In the file-private function <code>readParameters</code>.</p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">None.</p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>loadParameters</code></p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>T</em> <code>TopologyAc.cpp</code></p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">Code for loading parameter values from the parameter database.
|
|
Required only if <em>I</em> has a non-standard parameter-loading
|
|
format.</p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">In the file-private function <code>loadParameters</code>.</p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">The standard call to <code>loadParameters</code> if <em>I</em>
|
|
has parameters; otherwise none.</p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>startTasks</code></p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>T</em> <code>TopologyAc.cpp</code></p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">Code for starting the task (if any) of <em>I</em>.</p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">In the file-private function <code>startTasks</code>.</p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">The standard call to <code>startTasks</code> if <em>I</em>
|
|
is an active component; otherwise none.</p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>stopTasks</code></p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>T</em> <code>TopologyAc.cpp</code></p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">Code for stopping the task (if any) of <em>I</em>.</p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">In the file-private function <code>stopTasks</code>.</p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">The standard call to <code>exit</code> if <em>I</em>
|
|
is an active component; otherwise none.</p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>freeThreads</code></p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>T</em> <code>TopologyAc.cpp</code></p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">Code for freeing the thread associated with <em>I</em>.</p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">In the file-private function <code>freeThreads</code>.</p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">The standard call to <code>join</code> if <em>I</em> is an
|
|
active component; otherwise none.</p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>tearDownComponents</code></p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>T</em> <code>TopologyAc.cpp</code></p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">Code for deallocating the allocated memory
|
|
(if any) associated with <em>I</em>.</p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">In the file-private function <code>tearDownComponents</code>.</p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">None.</p></td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
<div class="paragraph">
|
|
<p>You will most often need to write code for <code>configConstants</code>,
|
|
<code>configObjects</code>, and <code>configComponents</code>.
|
|
These phases often require implementation-specific input that
|
|
cannot be provided in any other way, except to write an init specifier.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In theory you should never have to write code for <code>instances</code>
|
|
or <code>initComponents</code> — this code can be be standardized — but in practice not all F Prime components conform to the standard,
|
|
so you may have to override the default.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>You will typically not have to write code for <code>regCommands</code>,
|
|
<code>readParameters</code>, and <code>loadParameters</code> — the framework can generate
|
|
this code automatically — except that the parameter database
|
|
instance needs one line of special code for reading its parameters.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Code for <code>startTasks</code>, <code>stopTasks</code>,
|
|
and <code>freeThreads</code> is required only if the user-written implementation of
|
|
a component instance manages its own F Prime task.
|
|
If you use a standard F Prime active component, then the framework
|
|
manages the task, and this code is generated automatically.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Code for <code>tearDownComponents</code> is required only if a component
|
|
instance needs to deallocate memory or release resources on program exit.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Component-Instances_Init-Specifiers_Writing-Init-Specifiers">12.3.2. Writing Init Specifiers</h4>
|
|
<div class="paragraph">
|
|
<p>You may write one or more init specifiers as part of a component
|
|
instance definition.
|
|
The init specifiers, if any, come at the end of the
|
|
definition and must be enclosed in curly braces.
|
|
The init specifiers form an
|
|
<a href="#Defining-Constants_Multiple-Definitions-and-Element-Sequences">element sequence</a>
|
|
with a semicolon as the optional terminating punctuation.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>To write an init specifier, you write the following:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>The keyword <code>phase</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>The
|
|
<a href="#Defining-Component-Instances_Init-Specifiers_Execution-Phases">execution phase</a>
|
|
of the init specifier.</p>
|
|
</li>
|
|
<li>
|
|
<p>A
|
|
<a href="#Defining-Constants_Expressions_String-Values">string</a>
|
|
that provides the code snippet.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>It is usually convenient, but not required, to use a multiline string
|
|
for the code snippet.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>As an example, here is the component instance definition for the
|
|
command sequencer instance <code>cmdSeq</code> from the
|
|
<a href="https://github.com/fprime-community/fprime-system-reference/blob/main/SystemReference/Top/instances.fpp">F Prime system reference deployment</a>:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">instance cmdSeq: Svc.CmdSequencer base id 0x0700 \
|
|
queue size Default.queueSize \
|
|
stack size Default.stackSize \
|
|
priority 100 \
|
|
{
|
|
|
|
phase Fpp.ToCpp.Phases.configConstants """
|
|
enum {
|
|
BUFFER_SIZE = 5*1024
|
|
};
|
|
"""
|
|
|
|
phase Fpp.ToCpp.Phases.configComponents """
|
|
cmdSeq.allocateBuffer(
|
|
0,
|
|
Allocation::mallocator,
|
|
ConfigConstants::SystemReference_cmdSeq::BUFFER_SIZE
|
|
);
|
|
"""
|
|
|
|
phase Fpp.ToCpp.Phases.tearDownComponents """
|
|
cmdSeq.deallocateBuffer(Allocation::mallocator);
|
|
"""
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The code for <code>configConstants</code> provides a constant <code>BUFFER_SIZE</code>
|
|
that is used in the <code>configComponents</code> phase.
|
|
The code generator places this code snippet in the
|
|
namespace <code>ConfigConstants::SystemReference_cmdSeq</code>.
|
|
Notice that the second part of the namespace uses the
|
|
fully qualified name <code>SystemReference::cmdSeq</code>, and it replaces
|
|
the double colon <code>::</code> with an underscore <code>_</code> to generate
|
|
the name.
|
|
We will explain this behavior further in the section on
|
|
<a href="#Defining-Component-Instances_Generation-of-Names">generation of names</a>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The code for <code>configComponents</code> calls <code>allocateBuffer</code>, passing
|
|
in an allocator object that is declared elsewhere.
|
|
(In the section on
|
|
<a href="#Writing-C-Plus-Plus-Implementations_Implementing-Deployments">implementing deployments</a>, we will explain where this allocator
|
|
object is declared.)
|
|
The code for <code>tearDownComponents</code> calls <code>deallocateBuffer</code> to
|
|
deallocate the sequence buffer, passing in the allocator
|
|
object again.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>As another example, here is the instance definition for the parameter
|
|
database instance <code>prmDb</code> from the system reference deployment:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">instance prmDb: Svc.PrmDb base id 0x0D00 \
|
|
queue size Default.queueSize \
|
|
stack size Default.stackSize \
|
|
priority 96 \
|
|
{
|
|
|
|
phase Fpp.ToCpp.Phases.instances """
|
|
Svc::PrmDb prmDb(FW_OPTIONAL_NAME("prmDb"), "PrmDb.dat");
|
|
"""
|
|
|
|
phase Fpp.ToCpp.Phases.readParameters """
|
|
prmDb.readParamFile();
|
|
"""
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Here we provide code for the <code>instances</code> phase because the constructor
|
|
call for this component is nonstandard — it takes the parameter
|
|
file name as an argument.
|
|
In the <code>readParameters</code> phase, we provide the code for reading the parameters
|
|
from the file.
|
|
As discussed above, this code is needed only for the parameter database
|
|
instance.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>When writing init specifiers, you may read (but not modify) a special value
|
|
<code>state</code> that you define in a handwritten main function.
|
|
This value lets you pass application-specific information from the
|
|
handwritten code to the auto-generated code.
|
|
We will explain the special <code>state</code> value further in the
|
|
section on <a href="#Writing-C-Plus-Plus-Implementations_Implementing-Deployments">implementing deployments</a>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For more examples of init specifiers in action, see the rest of
|
|
the file <code>SystemReference/Top/instances.fpp</code> in the F Prime repository.
|
|
In particular, the init specifiers for the <code>comDriver</code> instance
|
|
use the <code>state</code> value that we just mentioned.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Defining-Component-Instances_Generation-of-Names">12.4. Generation of Names</h3>
|
|
<div class="paragraph">
|
|
<p>FPP uses the following rules to generate the names associated with
|
|
component instances.
|
|
First, as explained in the section on
|
|
<a href="#Defining-Component-Instances_Specifying-the-Implementation">specifying the implementation</a>,
|
|
a component type <code>M.C</code> in FPP becomes the type <code>M::C</code> in C++.
|
|
Here <code>C</code> is a C++ class defined in namespace <code>M</code> that
|
|
implements the behavior of component <code>C</code>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Second, a component instance <em>I</em> defined in module <em>N</em> becomes
|
|
a C++ variable <em>I</em> defined in namespace <em>N</em>.
|
|
For example, this FPP code</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">module N {
|
|
|
|
instance i: M.C base id 0x100
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>becomes this code in the generated C++:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="c++">namespace N {
|
|
|
|
M::C i;
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>So the fully qualified name of the instance is <code>N.i</code> in FPP and <code>N::i</code>
|
|
in C++.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Third, all other code related to instances is generated in the namespace of the
|
|
top-level implementation.
|
|
For example, in the System Reference example from the previous section,
|
|
the top-level implementation is in the namespace <code>SystemReference</code>, so
|
|
the code for configuring constants is generated in that namespace.
|
|
We will have more to say about the top-level implementation in
|
|
the section on <a href="#Writing-C-Plus-Plus-Implementations_Implementing-Deployments">implementing deployments</a>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Fourth, when generating the name of a constant associated with an instance,
|
|
FPP uses the fully-qualified name of the instance, and it replaces
|
|
the dots (in FPP) or the colons (in C++) with underscores.
|
|
For example, as discussed in the previous section, the configuration
|
|
constants for the instance <code>SystemReference::cmdSeq</code> are placed in
|
|
the namespace <code>ConfigConstants::SystemReference_cmdSeq</code>.
|
|
This namespace, in turn, is placed in the namespace <code>SystemReference</code>
|
|
according to the previous paragraph.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="Defining-Topologies">13. Defining Topologies</h2>
|
|
<div class="sectionbody">
|
|
<div class="paragraph">
|
|
<p>In F Prime, a <strong>topology</strong> or connection graph is the
|
|
highest level of software architecture in a FSW application.
|
|
A topology specifies what
|
|
<a href="#Defining-Component-Instances">component instances</a>
|
|
are used in the application and how their
|
|
<a href="#Defining-Components_Port-Instances">port instances</a>
|
|
are connected.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>An F Prime FSW application consists of a topology <em>T</em>;
|
|
all the types, ports, and components used by <em>T</em>;
|
|
and a small amount of top-level C++ code that you write by hand.
|
|
In the section on
|
|
<a href="#Writing-C-Plus-Plus-Implementations_Implementing-Deployments">implementing deployments</a>, we will explain more about the top-level
|
|
C++ code.
|
|
In this section we explain how to define a topology in FPP.</p>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Defining-Topologies_A-Simple-Example">13.1. A Simple Example</h3>
|
|
<div class="paragraph">
|
|
<p>We begin with a simple example that shows how many of the pieces
|
|
fit together.</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">port P
|
|
|
|
passive component C {
|
|
sync input port pIn: P
|
|
output port pOut: P
|
|
}
|
|
|
|
instance c1: C base id 0x100
|
|
instance c2: C base id 0x200
|
|
|
|
@ A simple topology
|
|
topology Simple {
|
|
|
|
@ This specifier says that instance c1 is part of the topology
|
|
instance c1
|
|
@ This specifier says that instance c2 is part of the topology
|
|
instance c2
|
|
|
|
@ This code specifies a connection graph C1
|
|
connections C1 {
|
|
c1.pOut -> c2.pIn
|
|
}
|
|
|
|
@ This code specifies a connection graph C2
|
|
connections C2 {
|
|
c2.pOut -> c1.pIn
|
|
}
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In this example, we define a <a href="#Defining-Ports">port</a> <code>P</code>.
|
|
Then we define a <a href="#Defining-Components">passive component</a> <code>C</code>
|
|
with an input port and an output port, both of type <code>P</code>.
|
|
We define two <a href="#Defining-Component-Instances">instances</a> of
|
|
<code>C</code>, <code>c1</code> and <code>c2</code>.
|
|
We put these instances into a topology called <code>Simple</code>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>As shown, to define a topology, you write the keyword <code>topology</code>,
|
|
the name of the topology, and the members of the topology
|
|
definition enclosed in curly braces.
|
|
In this case, the topology has two kinds of members:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>Two <strong>instance specifiers</strong> specifying that instances
|
|
<code>c1</code> and <code>c2</code> are part of the topology.</p>
|
|
</li>
|
|
<li>
|
|
<p>Two <strong>graph specifiers</strong> that specify connection graphs
|
|
named <code>C1</code> and <code>C2</code>.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>As shown, to write an instance specifier, you write the
|
|
keyword <code>instance</code> and the name of a component instance
|
|
definition.
|
|
In general the name may be a qualified name such as <code>A.B</code>.
|
|
if the instance is defined inside a
|
|
<a href="#Defining-Modules">module</a>; in this simple
|
|
example it is not.
|
|
Each instance specifier states that the instance it names
|
|
is part of the topology.
|
|
The instances appearing in the list must be distinct.
|
|
For example, this is not correct:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">topology T {
|
|
instance c1
|
|
instance c1 # Error: duplicate instance c1
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>A graph specifier specifies one or more connections
|
|
between component instances.
|
|
Each graph specifier has a name.
|
|
By dividing the connections of a topology into named
|
|
graphs, you can organize the connections in a meaningful way.
|
|
For example you can have one graph group
|
|
for connections that send commands, another one
|
|
for connections that send telemetry, and so forth.
|
|
We will have more to say about this in a later section.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>As shown, to write a graph specifier, you may write the keyword <code>connections</code>
|
|
followed by the name of the graph; then you may list
|
|
the connections inside curly braces.
|
|
(In the next section, we will explain another way to write a graph specifier.)
|
|
Each connection consists of an endpoint, an arrow <code>-></code>,
|
|
and another endpoint.
|
|
An endpoint is the name of a component instance
|
|
(which in general may be a qualified name), a dot,
|
|
and the name of a port of that component instance.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In this example there are two connection graphs, each containing
|
|
one connection:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>A connection graph <code>C1</code> containing a connection from <code>c1.pOut</code> to <code>c2.pIn</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>A connection graph <code>C2</code> containing a connection from <code>c2.pOut</code> to <code>c1.pIn</code>.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>As shown, topologies and their members are
|
|
<a href="#Writing-Comments-and-Annotations_Annotations">annotatable elements</a>.
|
|
The topology members form an
|
|
<a href="#Defining-Constants_Multiple-Definitions-and-Element-Sequences">element sequence</a> in which the optional
|
|
terminating punctuation is a semicolon.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Defining-Topologies_Connection-Graphs">13.2. Connection Graphs</h3>
|
|
<div class="paragraph">
|
|
<p>In general, an FPP topology consists of a list of instances
|
|
and a set of named connection graphs.
|
|
There are two ways to specify connection graphs:
|
|
<strong>direct graph specifiers</strong> and <strong>pattern graph specifiers</strong>.</p>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Topologies_Connection-Graphs_Direct-Graph-Specifiers">13.2.1. Direct Graph Specifiers</h4>
|
|
<div class="paragraph">
|
|
<p>A direct graph specifier provides a name and a list
|
|
of connections.
|
|
We illustrated direct graph specifiers in the
|
|
previous section, where the simple topology example
|
|
included direct graph specifiers for graphs named
|
|
<code>C1</code> and <code>C2</code>.
|
|
Here are some more details about direct graph specifiers.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>As shown in the previous section, each connection consists
|
|
of an output port specifier, followed by an arrow, followed
|
|
by an input port specifier.
|
|
For example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">connections C {
|
|
a.p -> b.p
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Each of the two port specifiers consists of a component
|
|
instance name, followed by a dot, followed the name of a port instance.
|
|
The component instance name must refer to a
|
|
<a href="#Defining-Component-Instances">component instance definition</a>
|
|
and may be qualified by a module name.
|
|
For example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">connections C {
|
|
M.a.p -> N.b.p
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Here component instance <code>a</code> is defined in module <code>M</code> and component
|
|
instance <code>b</code> is defined in module <code>N</code>.
|
|
In a port specifier <code>a.p</code>, the port instance name <code>p</code> must refer to a
|
|
<a href="#Defining-Components_Port-Instances">port instance</a> of the
|
|
component definition associated with the component instance <code>a</code>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Each component instance named in a connection must be part of the
|
|
instance list in the topology.
|
|
For example, if you write a connection <code>a.b -> c.d</code> inside
|
|
a topology <code>T</code>, and the specifier <code>instance a</code> does not
|
|
appear inside topology <code>T</code>, then you will get an error — even if <code>a</code> is a valid instance name for the FPP model.
|
|
The reason for this rule is that in flight code we need
|
|
to be very careful about which instances are included
|
|
in the application.
|
|
Naming all the instances also lets us check for
|
|
<a href="#Analyzing-and-Translating-Models_Checking-Models">unconnected ports</a>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>You may use the same name in more than one direct
|
|
graph specifier in the same topology.
|
|
If you do this, then all specifiers with the same
|
|
name are combined into a single graph with that name.
|
|
For example, this code</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">connections C {
|
|
a.p -> b.p
|
|
}
|
|
connections C {
|
|
c.p -> d.p
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>is equivalent to this code:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">connections C {
|
|
a.p -> b.p
|
|
c.p -> d.p
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The members of a direct graph specifier form an
|
|
<a href="#Defining-Constants_Multiple-Definitions-and-Element-Sequences">element sequence</a> in which the optional
|
|
terminating punctuation is a comma.
|
|
For example, you can write this:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">connections C { a.p -> b.p, c.p -> d.p }</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The connections appearing in direct graph specifiers must obey the
|
|
following rules:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>Each connection must go from an output port instance to
|
|
an input port instance.</p>
|
|
</li>
|
|
<li>
|
|
<p>The types of the ports must match, except that a
|
|
<a href="#Defining-Components_Port-Instances_Serial-Port-Instances">serial port instance</a> may be connected to a port of any
|
|
type.
|
|
In particular, serial to serial connections are allowed.</p>
|
|
</li>
|
|
<li>
|
|
<p>If a typed port <em>P</em> is connected to a serial port in either direction,
|
|
then the port type of <em>P</em> may not specify a
|
|
<a href="#Defining-Ports_Returning-Values">return type</a>.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Topologies_Connection-Graphs_Pattern-Graph-Specifiers">13.2.2. Pattern Graph Specifiers</h4>
|
|
<div class="paragraph">
|
|
<p>A few connection patterns are so common in F Prime that they
|
|
get special treatment in FPP.
|
|
For example, an F Prime topology typically includes an
|
|
instance of the component <code>Svc.Time</code>.
|
|
This component has a port <code>timeGetPort</code>
|
|
of type <code>Fw.Time</code> that other components can use to get the system
|
|
time.
|
|
Any component that gets the system time
|
|
(and there are usually several) has a connection to
|
|
the <code>timeGetPort</code> port of the <code>Svc.Time</code> instance.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Suppose you are constructing a topology in which
|
|
(1) <code>sysTime</code> is an instance of <code>Svc.Time</code>; and (2)
|
|
each of the instances
|
|
<code>a</code>, <code>b</code>, <code>c</code>, etc., has a
|
|
<a href="#Defining-Components_Special-Port-Instances_Time-Get-Ports">time get port</a>
|
|
<code>timeGetOut</code> port connected to <code>sysTime.timeGetPort</code>,
|
|
If you used a direct graph specifier to write all these connections,
|
|
the result might look like this:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">connections Time {
|
|
a.timeGetOut -> sysTime.timeGetPort
|
|
b.timeGetOut -> sysTime.timeGetPort
|
|
c.timeGetOut -> sysTime.timeGetPort
|
|
...
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>This works, but it is tedious and repetitive. So FPP provides
|
|
a better way: you can use a <strong>pattern graph specifier</strong>
|
|
to specify this common pattern.
|
|
You can write</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">time connections instance sysTime</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>This code says the following:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>Use the instance <code>sysTime</code> as the instance of <code>Fw.Time</code>
|
|
for the time connection pattern.</p>
|
|
</li>
|
|
<li>
|
|
<p>Automatically construct a direct graph specifier named <code>Time</code>.
|
|
In this direct graph specifier, include one connection
|
|
from each component instance that has a time get port
|
|
to the input port of <code>sysTime</code> of type <code>Fw.Time</code>.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The result is as if you had written the direct graph specifier
|
|
yourself.
|
|
All the other rules for direct graph specifiers apply: for example,
|
|
if you write another direct graph specifier with name <code>Time</code>, then
|
|
the connections in that specifier are merged with the connections
|
|
generated by the pattern specifier.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In the example above, we call <code>time</code> the <strong>kind</strong> of the pattern
|
|
graph specifier.
|
|
We call <code>sysTime</code> the <strong>source instance</strong> of the pattern.
|
|
It is the source of all the time pattern connections
|
|
in the topology.
|
|
We call the instances that have time get ports (and so contribute
|
|
connections to the pattern) the <strong>target instances</strong>.
|
|
They are the instances targeted by the pattern once the source
|
|
instance is named.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Table <a href="#pattern-graph-specifiers">Pattern Graph Specifiers</a> shows the pattern graph
|
|
specifiers allowed in FPP.
|
|
The columns of the table have the following meanings:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p><strong>Kind:</strong> The keyword or keywords denoting the kind.
|
|
When writing the specifier, these appear just before
|
|
the keyword <code>connections</code>, as shown above for the time example.</p>
|
|
</li>
|
|
<li>
|
|
<p><strong>Source Instance:</strong> The source instance for the pattern.</p>
|
|
</li>
|
|
<li>
|
|
<p><strong>Target Instances:</strong> The target instances for the pattern.</p>
|
|
</li>
|
|
<li>
|
|
<p><strong>Graph Name:</strong> The name of the connection graph
|
|
generated by the pattern.</p>
|
|
</li>
|
|
<li>
|
|
<p><strong>Connections:</strong> The connections generated by the pattern.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The command pattern specifier generates three connection graphs:
|
|
<code>Command</code>, <code>CommandRegistration</code>, and <code>CommandResponse</code>.</p>
|
|
</div>
|
|
<table id="pattern-graph-specifiers" class="tableblock frame-all grid-all stretch">
|
|
<caption class="title">Table 2. Pattern Graph Specifiers</caption>
|
|
<colgroup>
|
|
<col style="width: 20%;">
|
|
<col style="width: 20%;">
|
|
<col style="width: 20%;">
|
|
<col style="width: 20%;">
|
|
<col style="width: 20%;">
|
|
</colgroup>
|
|
<thead>
|
|
<tr>
|
|
<th class="tableblock halign-left valign-top">Kind</th>
|
|
<th class="tableblock halign-left valign-top">Source Instance</th>
|
|
<th class="tableblock halign-left valign-top">Target Instances</th>
|
|
<th class="tableblock halign-left valign-top">Graph Name</th>
|
|
<th class="tableblock halign-left valign-top">Connections</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top"></td>
|
|
<td class="tableblock halign-left valign-top"></td>
|
|
<td class="tableblock halign-left valign-top"></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>Command</code></p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">All connections from the unique output port of type <code>Fw::Cmd</code>
|
|
of the source instance to the
|
|
<a href="#Defining-Components_Special-Port-Instances_Command-Ports"><code>command</code> <code>recv</code> port</a>
|
|
of each target instance.</p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>command</code></p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">An instance of <code>Svc.CommandDispatcher</code> or a similar component for
|
|
dispatching commands.
|
|
The instance must have a unique output port of type <code>Fw.Cmd</code>,
|
|
a unique input port of type <code>Fw.CmdReg</code>, and a unique
|
|
input port of type <code>Fw.CmdResponse</code>.</p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">Each instance that has
|
|
<a href="#Defining-Components_Special-Port-Instances_Command-Ports">command ports</a>.</p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CommandRegistration</code></p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">All connections from the
|
|
<a href="#Defining-Components_Special-Port-Instances_Command-Ports"><code>command</code> <code>reg</code> port</a> of each target instance to the
|
|
unique input port of type <code>Fw.CmdReg</code> of the source instance.</p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top"></td>
|
|
<td class="tableblock halign-left valign-top"></td>
|
|
<td class="tableblock halign-left valign-top"></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CommandResponse</code></p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">All connections from the
|
|
<a href="#Defining-Components_Special-Port-Instances_Command-Ports"><code>command</code> <code>resp</code> port</a> of each target instance to the
|
|
unique input port of type <code>Fw.CmdResponse</code> of the source instance.</p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>event</code></p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">An instance of <code>Svc.ActiveLogger</code> or a similar component for
|
|
logging event reports.
|
|
The instance must have a unique input port of type
|
|
<code>Fw.Log</code>.</p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">Each instance that has an
|
|
<a href="#Defining-Components_Special-Port-Instances_Event-Ports"><code>event</code> port</a>.</p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>Events</code></p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">All connections from the
|
|
<a href="#Defining-Components_Special-Port-Instances_Event-Ports"><code>event</code> port</a> of each target instance to the unique
|
|
input port of type <code>Fw.Log</code> of the source instance.</p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>health</code></p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">An instance of <code>Svc.Health</code> or a similar component for
|
|
health monitoring.
|
|
The instance must have a unique output port of type
|
|
<code>Svc.Ping</code> and a unique input port of type <code>Svc.Ping</code>.</p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">Each instance other than the source instance
|
|
that has a unique output port of type
|
|
<code>Svc.Ping</code> and a unique input port of type <code>Svc.Ping</code>.</p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>Health</code></p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">(1) All connections from the unique output port of type
|
|
<code>Svc.Ping</code> of each target instance to the unique input
|
|
port of type <code>Svc.Ping</code> of the source instance.
|
|
(2) All connections from the unique output port of type
|
|
<code>Svc.Ping</code> of the source instance to the unique
|
|
input port of type <code>Svc.Ping</code> of each target instance.</p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>param</code></p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">An instance of <code>Svc.PrmDb</code> or a similar component representing
|
|
a database of parameters.
|
|
The instance must have a unique input port of type <code>Fw.PrmGet</code>
|
|
and a unique input port of type <code>Fw.PrmSet</code>.</p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">Each instance that has
|
|
<a href="#Defining-Components_Special-Port-Instances_Parameter-Ports">parameter ports</a>.</p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>Parameters</code></p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">(1) All connections from the
|
|
<a href="#Defining-Components_Special-Port-Instances_Parameter-Ports"><code>param</code> <code>get</code> port</a> of each target instance
|
|
to the unique input port of type <code>Fw.PrmGet</code> of the source instance.
|
|
(2) All connections from the
|
|
<a href="#Defining-Components_Special-Port-Instances_Parameter-Ports"><code>param</code> <code>set</code> port</a> of each target instance
|
|
to the unique input port of type <code>Fw.PrmSet</code> of the source instance.</p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>telemetry</code></p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">An instance of <code>Svc.TlmChan</code> or a similar component for
|
|
storing channelized telemetry.
|
|
The instance must have a unique input port of type <code>Fw.Tlm</code>.</p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">Each instance that has a <a href="#Defining-Components_Special-Port-Instances_Telemetry-Ports">telemetry port</a>.</p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>Telemetry</code></p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">All connections from the
|
|
<a href="#Defining-Components_Special-Port-Instances_Telemetry-Ports"><code>telemetry</code> port</a> of each target instance to the unique input
|
|
port of type <code>Fw.Tlm</code> of the source instance.</p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>text</code> <code>event</code></p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">An instance of <code>Svc.PassiveTextLogger</code> or a similar component
|
|
for logging event reports in textual form.
|
|
The instance must have a unique input port of type <code>Fw.LogText</code>.</p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">Each instance that has a <a href="#Defining-Components_Special-Port-Instances_Event-Ports"><code>text</code> <code>event</code> port</a>.</p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>TextEvents</code></p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">All connections from the
|
|
<a href="#Defining-Components_Special-Port-Instances_Event-Ports"><code>text</code> <code>event</code> port</a> of each target instance to the unique
|
|
input port of type <code>Fw.LogText</code> of the source instance.</p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>time</code></p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">An instance of <code>Svc.Time</code> or a similar component for providing
|
|
the system time.
|
|
The instance must have a unique input port of type <code>Fw.Time</code>.</p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">Each instance that has a
|
|
<a href="#Defining-Components_Special-Port-Instances_Time-Get-Ports"><code>time</code> <code>get</code> port</a>.</p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>Time</code></p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">All connections from the
|
|
<a href="#Defining-Components_Special-Port-Instances_Time-Get-Ports"><code>time</code> <code>get</code> port</a> of each target instance to the unique
|
|
input port of type <code>Fw.Time</code> of the source instance.</p></td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
<div class="paragraph">
|
|
<p>Here are some rules for writing graph pattern specifiers:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>At most one occurrence of each pattern kind is allowed in
|
|
each topology.</p>
|
|
</li>
|
|
<li>
|
|
<p>For each pattern, the required ports shown in the table
|
|
must exist and must be unambiguous.
|
|
For example, if you write a time pattern</p>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">time connections instance sysTime</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>then you will get an error if <code>sysTime</code> has no
|
|
input ports of type <code>Fw.Time</code>,
|
|
You will also get an error if <code>sysTime</code> has two or more
|
|
such ports.</p>
|
|
</div>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The default behavior for a pattern is
|
|
to generate the connections for all target instances
|
|
as shown in the table.
|
|
If you wish, you may generate connections for a selected
|
|
set of target instances.
|
|
To do this, you write a list of target instances enclosed in
|
|
curly braces after the source instance.
|
|
For example, suppose a topology contains instances
|
|
<code>a</code>, <code>b</code>, and <code>c</code> each of which has an output port
|
|
that satisfies the time pattern.
|
|
And suppose that <code>sysTime</code> is an instance of <code>Svc.Time</code>.
|
|
Then if you write this pattern</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">time connections instance sysTime</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>you will get a connection graph <code>Time</code> containing
|
|
time connections from each of <code>a</code>, <code>b</code>, and <code>c</code> to <code>sysTime</code>.
|
|
But if you write this pattern</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">time connections instance sysTime {
|
|
a
|
|
b
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>then you will just get the connections from <code>a</code> and <code>b</code>
|
|
to <code>sysTime</code>.
|
|
The instances <code>a</code> and <code>b</code> must be valid target instances
|
|
for the pattern.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>As with connections, you can write the instances <code>a</code> and <code>b</code>
|
|
each on its own line, or you can separate them with commas:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">time connections instance sysTime { a, b }</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Defining-Topologies_Port-Numbering">13.3. Port Numbering</h3>
|
|
<div class="paragraph">
|
|
<p>As discussed in the
|
|
<a href="#Defining-Components_Port-Instances_Arrays-of-Port-Instances">section on defining components</a>,
|
|
each named port instance is actually an array of
|
|
one or more port instances.
|
|
When the size of the array exceeds one, you
|
|
must specify the port number (i.e., the array index)
|
|
of each connection going into or out of the port instance.
|
|
In FPP, there are three ways to specify port numbers:
|
|
explicit numbering, matched numbering, and general numbering.</p>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Topologies_Port-Numbering_Explicit-Numbering">13.3.1. Explicit Numbering</h4>
|
|
<div class="paragraph">
|
|
<p>To use explicit numbering, you provide an explicit port number
|
|
for a connection endpoint.
|
|
You write the port number as a
|
|
<a href="#Defining-Constants_Expressions">numeric expression</a>
|
|
in square brackets, immediately following the port name.
|
|
The port numbers start at zero.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For example, the <code>RateGroups</code> graph of the Ref (reference) topology in the F Prime
|
|
repository defines the rate group connections.
|
|
It contains the following connection:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">rateGroupDriverComp.CycleOut[Ports.RateGroups.rateGroup1] -> rateGroup1Comp.CycleIn
|
|
rateGroup1Comp.RateGroupMemberOut[0] -> SG1.schedIn
|
|
rateGroup1Comp.RateGroupMemberOut[1] -> SG2.schedIn
|
|
rateGroup1Comp.RateGroupMemberOut[2] -> chanTlm.Run
|
|
rateGroup1Comp.RateGroupMemberOut[3] -> fileDownlink.Run</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The first line says to connect the port at index
|
|
<code>Ports.RateGroups.rateGroup1</code> of <code>rateGroupDriverComp.CycleOut</code>
|
|
to <code>rateGroup1Comp.CycleIn</code>.
|
|
The symbol <code>Ports.RateGroups.rateGroup1</code> is an enumerated constant, defined
|
|
like this:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">module Ports {
|
|
|
|
enum RateGroups {
|
|
rateGroup1
|
|
rateGroup2
|
|
rateGroup3
|
|
}
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The second and following lines say to connect the ports of
|
|
<code>rateGroup1Comp.RateGroupMemberOut</code> at the indices 0, 1, 2, and 3
|
|
in the manner shown.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>As another example, the <code>Downlink</code> graph of the reference topology
|
|
contains the following connection:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">downlink.framedAllocate -> staticMemory.bufferAllocate[Ports.StaticMemory.downlink]</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>This line says to connect <code>downlink.framedAllocate</code> to
|
|
<code>staticMemory.bufferAllocate</code> at index
|
|
<code>Port.StaticMemory.downlink</code>.
|
|
Again the port index is a symbolic constant.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>If you wish, you may write two explicit port numbers,
|
|
one at each endpoint.
|
|
For example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">a.b[0] -> c.d[1]</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Here are some rules to keep in mind when using explicit numbering:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>You can write any numeric expression as a port number.
|
|
Each port number must be in bounds for the port (greater than
|
|
or equal to zero and less than the size of the port array).
|
|
If you write a port number that is out of bounds, you will get an error.</p>
|
|
</li>
|
|
<li>
|
|
<p>Use symbolic constants judiciously.
|
|
Avoid scattering "magic" literal
|
|
constants throughout the topology definition.
|
|
For example:</p>
|
|
<div class="olist loweralpha">
|
|
<ol class="loweralpha" type="a">
|
|
<li>
|
|
<p>The Ref topology uses the symbolic constants
|
|
<code>Ports.RateGroups.rateGroup1</code> and <code>Ports.StaticMemory.downlink</code>, as shown
|
|
above.
|
|
Because these constants appear in several different places, it is
|
|
better to use symbolic constants here.
|
|
Using literal constants would decrease readability and increase
|
|
the chance of using incorrect or inconsistent numbers.</p>
|
|
</li>
|
|
<li>
|
|
<p>The Ref topology uses the literal constants 0, 1, 2, and 3
|
|
to connect the ports of <code>rateGroup1Comp.RateGroupMemberOut</code>.
|
|
Here there are no obvious names to associate with the numbers,
|
|
the numbers go in sequence, and all the numbers appear together in one place.
|
|
So there is no clear benefit to giving them names.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
</li>
|
|
<li>
|
|
<p>Remember that in F Prime, multiple connections can go to the same
|
|
input port, but only one connection can go from each output port.
|
|
For example, this code is allowed:</p>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">c1.p1 -> c2.p[0]
|
|
c1.p2 -> c2.p[0] # OK: Two connections into c2.p[0]</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>But this code is incorrect:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">c1.p[0] -> c2.p1
|
|
c1.p[0] -> c2.p2 # Error: Two connections out of c1.p[0]</code></pre>
|
|
</div>
|
|
</div>
|
|
</li>
|
|
<li>
|
|
<p>Use explicit numbering as little as possible.
|
|
Instead, use matched numbering or general numbering
|
|
(described in the next sections) and let FPP
|
|
do the numbering for you.
|
|
In particular, avoid writing zero indices such as
|
|
<code>c.p[0]</code> except in cases where you need to control the assignment
|
|
of numbers, such as in the rate group example shown above.
|
|
In other cases, write <code>c.p</code> and let FPP infer
|
|
the zero index.
|
|
For example, this is what we did in the section on
|
|
<a href="#Defining-Topologies_Connection-Graphs_Direct-Graph-Specifiers">direct graph specifiers</a>.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Topologies_Port-Numbering_Matched-Numbering">13.3.2. Matched Numbering</h4>
|
|
<div class="paragraph">
|
|
<p><strong>Automatic matching:</strong>
|
|
After resolving
|
|
<a href="#Defining-Topologies_Port-Numbering_Explicit-Numbering">explicit numbering</a>, the FPP translator applies
|
|
<strong>matched numbering</strong>.
|
|
In this step, the translator numbers all pairs of
|
|
<a href="#Defining-Components_Matched-Ports">matched ports</a>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Matched numbering is essential for resolving the command and health
|
|
<a href="#Defining-Topologies_Connection-Graphs_Pattern-Graph-Specifiers">patterns</a>, each of which has matched ports.
|
|
You can also use matched numbering in conjunction with direct
|
|
graph specifiers.
|
|
For example, the Ref topology contains the following connections:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">connections Sequencer {
|
|
cmdSeq.comCmdOut -> cmdDisp.seqCmdBuff
|
|
cmdDisp.seqCmdStatus -> cmdSeq.cmdResponseIn
|
|
}
|
|
|
|
connections Uplink {
|
|
...
|
|
uplink.comOut -> cmdDisp.seqCmdBuff
|
|
cmdDisp.seqCmdStatus -> uplink.cmdResponseIn
|
|
...
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The port <code>cmdDisp.seqCmdBuff</code> port of the command dispatcher receives
|
|
command input from the command sequencer or from the ground.
|
|
The corresponding command response goes out on
|
|
port <code>cmdDisp.seqCmdStatus</code>.
|
|
These two ports are matched in the definition of the Command
|
|
Sequencer component.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>When you use matched numbering with direct graph specifiers, you
|
|
must obey the following rules:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>When a component has the matching specifier
|
|
<code>match p1 with p2</code>, for every connection between <code>p1</code>
|
|
and another component, there must be a corresponding
|
|
connection between that other component and <code>p2</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>You can use explicit numbering, and the automatic matching
|
|
will work around the numbers you supply if it can.
|
|
However, you may not do this in a way that makes the matching impossible.
|
|
For example, you may not connect <code>p1[0]</code> to another component
|
|
and <code>p2[1]</code> to the same component, because this connection
|
|
forces a mismatch.</p>
|
|
</li>
|
|
<li>
|
|
<p>Duplicate connections at the same port number of <code>p1</code> or
|
|
<code>p2</code> are not allowed, even if <code>p1</code> or <code>p2</code> are input ports.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>If you violate these rules, you will get an error during
|
|
analysis.
|
|
You can relax these rules by writing unmatched connections,
|
|
as described below.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Unmatched connections:</strong>
|
|
Occasionally you may need to relax the rules for using matched ports.
|
|
For example, you may need to match pairs of connections that use
|
|
the F Prime hub pattern to cross a network boundary.
|
|
In this case, although the connections are logically matched
|
|
at the endpoints, they all go through a single hub instance
|
|
on the side of the boundary that has the matched ports, and so they do not obey the
|
|
simple rules for matching given here.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>When a connection goes to or from a matched port,
|
|
we say that it is <strong>match constrained</strong>.
|
|
Ordinarily a match constrained connection must obey the
|
|
rules for matching stated above.
|
|
To relax the rules, you can write an <strong>unmatched</strong> connection.
|
|
To do this, write the keyword <code>unmatched</code> at the start of the connection
|
|
specifier.
|
|
Here is an example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">Port P
|
|
|
|
passive component Source {
|
|
sync input port pIn: [2] P
|
|
output port pOut: [2] P
|
|
|
|
match pOut with pIn
|
|
}
|
|
|
|
passive component Target {
|
|
sync input port pIn: [2] P
|
|
output port pOut: [2] P
|
|
}
|
|
|
|
instance source: Source base id 0x100
|
|
instance target: Target base id 0x200
|
|
|
|
topology T {
|
|
|
|
instance source
|
|
instance target
|
|
|
|
connections C {
|
|
unmatched source.pOut[0] -> target.pIn[0]
|
|
unmatched target.pOut[0] -> source.pIn[0]
|
|
unmatched source.pOut[1] -> target.pIn[1]
|
|
unmatched target.pOut[1] -> source.pIn[1]
|
|
}
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In this example, there are two pairs of connections between the
|
|
<code>pIn</code> and <code>pOut</code> connections of the instances <code>source</code> and <code>target</code>.
|
|
The ports of <code>source</code> are match constrained, so ordinarily
|
|
the connections would need to obey the matching rules.
|
|
The connections do partially obey the rules: for example,
|
|
there are no duplicate numbers, and the numbers match.
|
|
However, both pairs of connections go to and from the same
|
|
instance <code>target</code>; ordinarily this is not allowed for
|
|
match constrained connections.
|
|
To allow it, we need to use unmatched ports as shown.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Note the following about using unmatched ports:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>When connections are marked <code>unmatched</code>, the analyzer cannot check that the
|
|
port numbers assigned to the connections conform to any particular pattern.
|
|
If you need the port numbers to follow a pattern, as in the example shown
|
|
above, then you must use explicit numbering.
|
|
For a suggestion on how to do this, see the discussion of manual matching
|
|
below.</p>
|
|
</li>
|
|
<li>
|
|
<p>Unmatched ports must still obey the rule that distinct
|
|
connections at a matched port must have distinct port numbers.</p>
|
|
</li>
|
|
<li>
|
|
<p>The <code>unmatched</code> keyword is allowed only for connections that
|
|
are match constrained, i.e., that go to or from a matched port.
|
|
If you try to write an unmatched connection and the connection
|
|
is not match constrained, then you will get an error.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Manual matching:</strong>
|
|
Port matching specifiers work well when each matched pair of connections
|
|
goes between the same two components, one of which
|
|
has a matched pair of ports.
|
|
If the matching does not follow this pattern, then automatic matched
|
|
numbering will not work, and it is usually better not to
|
|
use a port matching specifier at all.
|
|
Instead, you can use explicit port numbers to express the matching.
|
|
For example, the Ref topology contains these connections:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">comm.allocate -> staticMemory.bufferAllocate[Ports.StaticMemory.uplink]
|
|
comm.$recv -> uplink.framedIn
|
|
uplink.framedDeallocate -> staticMemory.bufferDeallocate[Ports.StaticMemory.uplink]</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In this case the <code>staticMemory</code> instance requires that pairs of
|
|
allocation and deallocation requests for the same memory
|
|
go to the same port.
|
|
But the allocation request comes from <code>comm</code>,
|
|
and the deallocation request comes from <code>uplink</code>.
|
|
Since the allocation and deallocation connections go to different
|
|
component instances, we can’t used automatic matched numbering.
|
|
Instead we define a symbolic constant <code>Ports.StaticMemory.uplink</code>
|
|
and use that twice to do the matching by hand.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Topologies_Port-Numbering_General-Numbering">13.3.3. General Numbering</h4>
|
|
<div class="paragraph">
|
|
<p>After resolving
|
|
<a href="#Defining-Topologies_Port-Numbering_Explicit-Numbering">explicit numbering</a> and
|
|
<a href="#Defining-Topologies_Port-Numbering_Matched-Numbering">matched numbering</a>,
|
|
the FPP translator applies
|
|
<strong>general numbering</strong>.
|
|
In this step, the translator uses the following algorithm to
|
|
fill in any remaining unassigned
|
|
port numbers:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>Traverse the connections in a deterministic order.
|
|
The order is fully described in <em>The FPP Language Specification</em>.</p>
|
|
</li>
|
|
<li>
|
|
<p>For each connection</p>
|
|
<div class="olist loweralpha">
|
|
<ol class="loweralpha" type="a">
|
|
<li>
|
|
<p>If the output port number is unassigned, then set it to the
|
|
lowest available port number.</p>
|
|
</li>
|
|
<li>
|
|
<p>If the input port number is unassigned, then set it to zero.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For example, consider the following connections:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">a.p -> b.p
|
|
a.p -> c.p</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>After general numbering, the connections could be numbered
|
|
as follows:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">a.p[0] -> b.p[0]
|
|
a.p[1] -> c.p[0]</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Defining-Topologies_Importing-Topologies">13.4. Importing Topologies</h3>
|
|
<div class="paragraph">
|
|
<p>It is often useful to decompose a flight software project
|
|
into several topologies.
|
|
For example, a project might have the following topologies:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>A topology for command and data handling (CDH) with
|
|
components such as a command dispatcher, an event logger, a telemetry data
|
|
base,
|
|
a parameter database, and components for managing files.</p>
|
|
</li>
|
|
<li>
|
|
<p>Various subsystem topologies, for example power, thermal,
|
|
attitude control, etc.</p>
|
|
</li>
|
|
<li>
|
|
<p>A release topology.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Each of the subsystem topologies might include the CDH topology.
|
|
The release topology might include the CDH topology
|
|
and each of the subsystem topologies.
|
|
Further, to enable modular testing, it is useful for
|
|
each topology to be able to run on its own.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In FPP, the way we accomplish these goals is to <strong>import</strong>
|
|
one topology into another one.
|
|
In this section of the User Guide, we explain how to do that.</p>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Topologies_Importing-Topologies_Importing-Instances-and-Connections">13.4.1. Importing Instances and Connections</h4>
|
|
<div class="paragraph">
|
|
<p>To import a topology <code>A</code> into a topology <code>B</code>, you write
|
|
<code>import A</code> inside topology <code>B</code>, like this:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">topology B {
|
|
|
|
import A
|
|
|
|
...
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>You may add instances and connections as usual to <code>B</code>, as shown
|
|
by the dots.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>When you do this, the FPP translator does the following:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p><strong>Resolve <code>A</code>:</strong> Resolve all pattern graph
|
|
specifiers in <code>A</code>, and resolve all explicit port numbers in <code>A</code>.
|
|
Call the resulting topology <code>T</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p><strong>Form the instances of <code>B</code>:</strong>
|
|
Take the union of the instances specified in <code>T</code> and
|
|
the instances specified in <code>B</code>, counting any duplicates once.
|
|
These are the instances of <code>B</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p><strong>Form the connections of <code>B</code>:</strong>
|
|
Take the union of the connection graphs specified in <code>T</code> and
|
|
the connection graphs specified in <code>B</code>.
|
|
If each of <code>T</code> and <code>B</code> has a connection between the same
|
|
ports, then each becomes a separate connection in <code>B</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p><strong>Resolve <code>B</code>:</strong> Resolve the pattern graph specifies of <code>B</code>.
|
|
Apply matched numbering and general numbering to <code>B</code>.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For example, suppose topologies <code>A</code> and <code>B</code> are defined
|
|
as follows:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">topology A {
|
|
|
|
instance a
|
|
instance b
|
|
|
|
connections C1 {
|
|
a.p1 -> b.p
|
|
}
|
|
|
|
}
|
|
|
|
topology B {
|
|
|
|
import A
|
|
|
|
instance c
|
|
|
|
connections C1 {
|
|
a.p1 -> c.p
|
|
}
|
|
|
|
connections C2 {
|
|
a.p2 -> c.p
|
|
}
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>After import resolution, <code>B</code> is equivalent to this topology:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">topology B {
|
|
|
|
instance a
|
|
instance b
|
|
instance c
|
|
|
|
connections C1 {
|
|
a.p1 -> b.p
|
|
a.p1 -> c.p
|
|
}
|
|
|
|
connections C2 {
|
|
a.p2 -> c.p
|
|
}
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Notice that the <code>C1</code> connections of <code>A</code> are merged with the <code>C1</code>
|
|
connections of <code>B</code>.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Topologies_Importing-Topologies_Private-Instances">13.4.2. Private Instances</h4>
|
|
<div class="paragraph">
|
|
<p>Often when importing topology <code>A</code> into topology <code>B</code>, you
|
|
want to include one or more instances in <code>A</code> that exist just
|
|
for running <code>A</code>, but that you don’t want imported into <code>B</code>.
|
|
For example, <code>A</code> could have an instance <code>cStub</code> which is a stub version of
|
|
a component <code>c</code> that is fully implemented in <code>B</code>.
|
|
In this case</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>When running <code>A</code> you may need <code>cStub</code>; the topology
|
|
may not run or may not even compile without it.</p>
|
|
</li>
|
|
<li>
|
|
<p>When importing <code>A</code> into <code>B</code> you don’t want to import
|
|
<code>cStub</code>, because it is superseded by the real implementation <code>c</code> in <code>B</code>.
|
|
Also, any connections to <code>cStub</code> in <code>A</code> should be replaced
|
|
by connections to <code>c</code> in <code>B</code>.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>To handle this case, you can make <code>cStub</code> a <strong>private</strong> instance
|
|
of <code>A</code> and <code>c</code> an instance of <code>B</code>.
|
|
When you import <code>B</code> into <code>A</code>, <code>cStub</code> will not become an instance
|
|
of <code>B</code>.
|
|
Further, no connections in <code>A</code> involving <code>cStub</code> will be imported
|
|
into <code>B</code>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>As an example, suppose we revise topology <code>A</code> from the previous
|
|
section as follows:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">topology A {
|
|
|
|
instance a
|
|
instance b
|
|
private instance d
|
|
|
|
connections C1 {
|
|
a.p1 -> b.p
|
|
}
|
|
|
|
connections C2 {
|
|
a.p1 -> d.p
|
|
}
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Notice that we have added an instance <code>d</code> to topology
|
|
<code>A</code>, and we have declared <code>d</code> private to <code>A</code>.
|
|
We have also added a new connection to <code>d</code> in the
|
|
connection graph <code>C2</code>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Now suppose that we use the same definition of <code>B</code> given
|
|
in the previous section.
|
|
After import resolution, <code>B</code> will still be equivalent
|
|
to the topology shown at the end of the last section:
|
|
we have added an instance and a connection to <code>A</code>,
|
|
but the instance is private and the connection goes
|
|
from a private instance, so neither the instance nor
|
|
the connection is imported into <code>B</code>.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Topologies_Importing-Topologies_Multiple-Imports">13.4.3. Multiple Imports</h4>
|
|
<div class="paragraph">
|
|
<p>Multiple imports are allowed.
|
|
For example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">topology A {
|
|
|
|
import B
|
|
import C
|
|
|
|
...
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>This has the obvious meaning: both topology <code>B</code> and
|
|
topology <code>C</code> are imported into topology <code>A</code>, according
|
|
to the rules described above.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Each topology may appear at most once in the import list.
|
|
For example, this is incorrect:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">topology A {
|
|
|
|
import B
|
|
import B # Error: B imported twice
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Topologies_Importing-Topologies_Transitive-Imports">13.4.4. Transitive Imports</h4>
|
|
<div class="paragraph">
|
|
<p>In general, transitive imports are allowed.
|
|
For example, topology <code>A</code> may import topology <code>B</code>,
|
|
and topology <code>B</code> may import topology <code>C</code>.
|
|
Resolution works bottom-up on the import graph:
|
|
for example, first we resolve <code>C</code>, and then we resolve <code>B</code>,
|
|
and then we resolve <code>A</code>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Cycles in the import graph are not allowed.
|
|
For example, if <code>A</code> imports <code>B</code> and <code>B</code> imports <code>C</code>
|
|
and <code>C</code> imports <code>A</code>, you will get an error.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Defining-Topologies_Include-Specifiers">13.5. Include Specifiers</h3>
|
|
<div class="paragraph">
|
|
<p>You can include code from another file in a topology definition.
|
|
You do this by writing an <strong>include specifier</strong>.
|
|
Here is a simple example, in which the body of a topology
|
|
definition is specified in a file <code>T.fppi</code> and then included
|
|
in a topology definition:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">topology T {
|
|
|
|
include "T.fppi"
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>We will explain more about this feature in the section on
|
|
<a href="#Specifying-Models-as-Files_Include-Specifiers">include specifiers</a>
|
|
below.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Defining-Topologies_Telemetry-Packets">13.6. Telemetry Packets</h3>
|
|
<div class="paragraph">
|
|
<p>When defining a topology, you may (but are not required to)
|
|
specify how the <a href="#Defining-Components_Telemetry">telemetry channels</a>
|
|
defined in the topology are grouped into <strong>telemetry packets</strong>.
|
|
If you do this, then you can use an F Prime component called
|
|
the Telemetry Packetizer to construct telemetry packets and transmit
|
|
them to the ground.
|
|
This approach is usually more space efficient than transmitting
|
|
individual channels.
|
|
In this section we explain how to specify telemetry packets in FPP.</p>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Topologies_Telemetry-Packets_Telemetry-Packet-Sets">13.6.1. Telemetry Packet Sets</h4>
|
|
<div class="paragraph">
|
|
<p>To group the channels of a topology <em>T</em> into packets, you write a
|
|
<strong>telemetry packet set</strong> as part of the definition of <em>T</em>.
|
|
Here is a simple example showing a complete topology with a
|
|
telemetry packet set:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">passive component C {
|
|
|
|
telemetry port tlmOut
|
|
|
|
time get port timeGetOut
|
|
|
|
telemetry T1: U32
|
|
|
|
telemetry T2: F32
|
|
|
|
}
|
|
|
|
instance c1: C base id 0x100
|
|
instance c2: C base id 0x200
|
|
|
|
topology T {
|
|
|
|
instance c1
|
|
instance c2
|
|
|
|
@ Telemetry packet set PacketSet
|
|
telemetry packets PacketSet {
|
|
|
|
@ Packet P1
|
|
packet P1 group 0 {
|
|
c1.T1
|
|
c2.T1
|
|
c1.T1
|
|
}
|
|
|
|
@ Packet P2
|
|
packet P2 group 1 {
|
|
c1.T2
|
|
c2.T2
|
|
}
|
|
|
|
}
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In this example, we have defined a passive component <code>C</code> with two telemetry
|
|
channels, <code>T1</code> and <code>T2</code>.
|
|
We have defined two instances of <code>C</code>, <code>c1</code> and <code>c2</code>, so that there
|
|
are four telemetry channels overall: <code>c1.T1</code>, <code>c1.T2</code>, <code>c2.T1</code>, and <code>c2.T2</code>.
|
|
We have defined a topology <code>T</code> that uses the instances <code>c1</code> and <code>c2</code>
|
|
and defines a telemetry packet set <code>PacketSet</code>.
|
|
(In a realistic topology, there would be other instances and connections,
|
|
for example the telemetry packetizer instance and the ground interface
|
|
component. Here we have omitted these instances
|
|
and connections to focus on illustrating the FPP features.)</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Notice the following about this example:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>To write a telemetry packet set, you write the keywords <code>telemetry</code> <code>packets</code>
|
|
followed by the name of the packet set, here <code>PacketSet</code>.
|
|
Then you write the body of the telemetry packet set inside curly braces
|
|
<code>{ …​ }</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>In the body of the packet set, you specify packets.
|
|
The packet specifiers are
|
|
<a href="#Writing-Comments-and-Annotations_Annotations">annotatable elements</a>.
|
|
The body of the packet set is an
|
|
<a href="#Defining-Constants_Multiple-Definitions-and-Element-Sequences">element sequence</a> in which the optional
|
|
terminating punctuation is a comma.</p>
|
|
</li>
|
|
<li>
|
|
<p>Each packet specifier consists of the keyword <code>packet</code>, the packet
|
|
name, the keyword <code>group</code>, a group identifier, and the body of the packet.
|
|
Within a telemetry packet set, the packet names must be distinct.
|
|
The group identifiers must be numeric values.
|
|
In particular they can be
|
|
<a href="#Defining-Constants_Writing-a-Constant-Definition">defined constants</a>,
|
|
<a href="#Defining-Enums">enumerated constants</a>, or
|
|
<a href="#Defining-Constants_Expressions_Value-Arithmetic-Expressions">arithmetic expressions</a>.
|
|
The Telemetry Packetizer uses the group identifiers to select
|
|
which packets get transmitted.
|
|
For example, it is possible to transmit packets from group 0 but not group 1.
|
|
More than one packet may have the same group identifier.</p>
|
|
</li>
|
|
<li>
|
|
<p>Inside each packet, you specify telemetry channels
|
|
enclosed in curly braces <code>{ …​ }</code>.
|
|
The channel specifiers are
|
|
<a href="#Writing-Comments-and-Annotations_Annotations">annotatable elements</a>.
|
|
The body of the packet is an
|
|
<a href="#Defining-Constants_Multiple-Definitions-and-Element-Sequences">element sequence</a> in which the optional
|
|
terminating punctuation is a comma.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>When the packets are serialized and transmitted, each packet with name
|
|
<em>P</em> contains data from
|
|
the channels listed in the specification for <em>P</em>, in the order that
|
|
the channels are specified.
|
|
As shown for packet <code>P1</code>, a single channel may appear more than
|
|
once in a packet; that means that data from that channel appears at
|
|
two or more offsets in that packet.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The form of a telemetry channel specifier
|
|
is an instance name followed by a dot and a channel name.
|
|
The instance name must refer to an instance of the topology.
|
|
The channel name must refer to a channel of that instance.
|
|
For example, in the model above, <code>c1.T</code> is a valid channel
|
|
for topology <code>T</code> because <code>c1</code> is an instance of <code>T</code>,
|
|
<code>c1</code> has type <code>C</code>, and <code>T</code> is a channel of <code>C</code>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The instance name may be a qualified name containing a dot,
|
|
as discussed in
|
|
the section on <a href="#Defining-Modules">defining modules</a>.
|
|
For example, if we had written</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">module M {
|
|
|
|
instance c1: C base id 0x100
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>instead of</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">instance c1: C base id 0x100</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>to define instance <code>c1</code> in the model shown above,
|
|
then in the topology <code>T</code> we would write
|
|
<code>instance M.c1</code> instead of <code>instance c</code>, and we would write
|
|
channel <code>M.c1.T</code> instead of channel <code>c1.T</code>.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Topologies_Telemetry-Packets_Telemetry-Packet-Identifiers">13.6.2. Telemetry Packet Identifiers</h4>
|
|
<div class="paragraph">
|
|
<p>Within a telemetry packet set, every packet has a unique numeric identifier.
|
|
Typically the identifiers start at zero and count up by one.
|
|
If you don’t specify an identifier, as in the example shown in the previous
|
|
section, then FPP assigns a default identifier: zero for the first packet in the set;
|
|
otherwise one more than the identifier of the previous packet.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>If you wish, you may explicitly specify one or more packet identifiers. To do
|
|
this, you write the keyword <code>id</code> followed by a numeric expression immediately
|
|
after the packet name.
|
|
For example, in the model shown in the previous section, we
|
|
could have written</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">@ Packet P1
|
|
packet P1 id 0 group 0 {
|
|
c1.T1
|
|
c2.T1
|
|
c1.T1
|
|
}
|
|
|
|
@ Packet P2
|
|
packet P2 id 1 group 1 {
|
|
c1.T2
|
|
c2.T2
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>for the packet specifiers, and this would have equivalent behavior.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Topologies_Telemetry-Packets_Omitting-Channels">13.6.3. Omitting Channels</h4>
|
|
<div class="paragraph">
|
|
<p>By default, every telemetry channel in the topology must appear
|
|
in at least one telemetry packet.
|
|
For example, in the model shown above, if we comment out the definition
|
|
of packet <code>P2</code> and run the result through <code>fpp-check</code>, then an error will result,
|
|
because neither channel
|
|
<code>c1.T2</code> nor channel <code>c2.T2</code> appears in any packet.
|
|
The purpose of this behavior is to ensure that you don’t omit
|
|
any channels from the telemetry by mistake.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>If you do want to omit channels from the telemetry packets,
|
|
then you can do so explicitly by writing the keyword <code>omit</code> and listing
|
|
those channels after the main specification of the packet set.
|
|
Here is an example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">passive component C {
|
|
|
|
telemetry port tlmOut
|
|
|
|
time get port timeGetOut
|
|
|
|
telemetry T1: U32
|
|
|
|
telemetry T2: F32
|
|
|
|
}
|
|
|
|
instance c1: C base id 0x100
|
|
instance c2: C base id 0x200
|
|
|
|
topology T {
|
|
|
|
instance c1
|
|
instance c2
|
|
|
|
@ Telemetry packet set PacketSet
|
|
telemetry packets PacketSet {
|
|
|
|
@ Packet P1
|
|
packet P1 group 0 {
|
|
c1.T1
|
|
c2.T1
|
|
c1.T1
|
|
}
|
|
|
|
} omit {
|
|
c1.T2
|
|
c2.T2
|
|
}
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The form of the list of omitted channels is the same as the
|
|
form of the list of channels in a telemetry packet.
|
|
It is an error for any channel to appear in a telemetry
|
|
packet and also to appear in the omitted list.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Topologies_Telemetry-Packets_Specifying-Multiple-Telemetry-Packet-Sets">13.6.4. Specifying Multiple Telemetry Packet Sets</h4>
|
|
<div class="paragraph">
|
|
<p>You may specify more than one telemetry packet set in a topology.
|
|
Each telemetry packet set must have a distinct name.
|
|
For example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">passive component C {
|
|
|
|
telemetry port tlmOut
|
|
|
|
time get port timeGetOut
|
|
|
|
telemetry T: U32
|
|
|
|
}
|
|
|
|
instance c1: C base id 0x100
|
|
instance c2: C base id 0x200
|
|
|
|
topology T {
|
|
|
|
instance c1
|
|
instance c2
|
|
|
|
@ Telemetry packet set PacketSet1
|
|
telemetry packets PacketSet1 {
|
|
|
|
@ Packet P
|
|
packet P1 group 0 {
|
|
c1.T
|
|
}
|
|
|
|
} omit {
|
|
c2.T
|
|
}
|
|
|
|
@ Telemetry packet set PacketSet2
|
|
telemetry packets PacketSet2 {
|
|
|
|
@ Packet P
|
|
packet P1 group 0 {
|
|
c2.T
|
|
}
|
|
|
|
} omit {
|
|
c1.T
|
|
}
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>When you run the F Prime ground data system, you can tell it which
|
|
telemetry packet set to use to decode the packets.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Defining-Topologies_Telemetry-Packets_Include-Specifiers">13.6.5. Include Specifiers</h4>
|
|
<div class="paragraph">
|
|
<p>When writing a telemetry packet set, you can
|
|
<a href="#Defining-Topologies_Include-Specifiers">include code
|
|
from another file</a> in the following places:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>You can include code inside a packet set specifier.
|
|
The code must contain packet specifiers.</p>
|
|
</li>
|
|
<li>
|
|
<p>You can include code inside a packet specifier.
|
|
The code must list telemetry channels.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">telemetry packets PacketSet {
|
|
|
|
@ Include some packets
|
|
include "packets.fppi"
|
|
|
|
packet P group 0 {
|
|
c1.T1
|
|
# Include some channels
|
|
include "channels.fppi"
|
|
}
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The files that you include can themselves include code
|
|
from other files, if you wish.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="Specifying-Models-as-Files">14. Specifying Models as Files</h2>
|
|
<div class="sectionbody">
|
|
<div class="paragraph">
|
|
<p>The previous sections have explained the syntactic and semantic elements
|
|
of FPP models.
|
|
This section takes a more file-centric view:
|
|
it explains how to assemble a collection of elements specified in
|
|
several files into a model.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>We discuss several tools for specifying and analyzing dependencies between
|
|
model files.
|
|
We focus on how to use the tools, and we summarize their most important
|
|
features.
|
|
We do not attempt to cover every feature of every tool.
|
|
For more comprehensive coverage, see
|
|
<a href="https://github.com/nasa/fpp/wiki/Tools">the FPP wiki</a>.</p>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Specifying-Models-as-Files_Dividing-Models-into-Files">14.1. Dividing Models into Files</h3>
|
|
<div class="paragraph">
|
|
<p>FPP does not require any particular division of model
|
|
elements into files.
|
|
For example, there is no requirement that each
|
|
type definition reside in its own file.
|
|
Nor is there any requirement that the names of files correspond
|
|
to the names of the definitions they contain.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Of course you should try to adhere to good style when decomposing a large model
|
|
into many files.
|
|
For example:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>Group related model elements into files, and name the files
|
|
according to the purpose of the grouping.</p>
|
|
</li>
|
|
<li>
|
|
<p>Choose meaningful module names, and group all files in a single module
|
|
in single directory (including its subdirectories).
|
|
In the F Prime distribution, the <code>Fw</code> and <code>Svc</code> directories
|
|
follow this pattern, where the C++ namespaces <code>Fw</code> and <code>Svc</code>
|
|
correspond to FPP modules.</p>
|
|
</li>
|
|
<li>
|
|
<p>Group files into modules and directories logically according to their function.</p>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>You can group files according to their role in the FPP model.
|
|
For example, group types separately from ports.</p>
|
|
</li>
|
|
<li>
|
|
<p>You can group files according to their role in the FSW.
|
|
For example, group framework files separately from application files.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</li>
|
|
<li>
|
|
<p>If the definition of a constant or type is logically part of a component,
|
|
then make the definition a member of the component.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>There is still the usual requirement that a syntactic unit must begin and end
|
|
in the same file.
|
|
For example:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>Each type definition is a syntactic unit, so each type definition must begin
|
|
and end in the same file.</p>
|
|
</li>
|
|
<li>
|
|
<p>A module definition may span several syntactic units of the form
|
|
<code>module { …​ }</code>,
|
|
so a module definition may span multiple files (with each unit of the form
|
|
<code>module { …​ }</code> residing in a single file).</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>These rules are similar to the way that C++ requires a class definition
|
|
<code>class C { …​ }</code> or a namespace block <code>namespace N { …​ }</code> to reside in a
|
|
single file, but it allows the definition of a single namespace <code>N</code> to span
|
|
multiple blocks
|
|
<code>namespace N { …​ }</code> that can be in different files.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Specifying-Models-as-Files_Include-Specifiers">14.2. Include Specifiers</h3>
|
|
<div class="paragraph">
|
|
<p>As part of an FPP model, you can write one or more <strong>include specifiers</strong>.
|
|
An include specifier is an instruction to include FPP source elements
|
|
from one file into another file.
|
|
Include specifiers may occur at the top level of a model,
|
|
inside a <a href="#Defining-Modules">module definition</a>,
|
|
inside a <a href="#Defining-Components">component definition</a>,
|
|
or inside a <a href="#Defining-Topologies">topology definition</a>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The main purpose of include specifiers is to split up large syntactic units
|
|
into several files.
|
|
For example, a component definition may include a telemetry dictionary
|
|
from a separate file.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>To write an include specifier, you write the keyword <code>include</code>
|
|
followed by string denoting a file path.
|
|
The path is relative to the file in which the include specifier appears.
|
|
By convention, included FPP files end in <code>.fppi</code> to distinguish
|
|
them from <code>.fpp</code> files that are directly analyzed and translated.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For example, suppose that the file <code>a.fppi</code> contains the definition</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant a = 0</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In a file <code>b.fppi</code> in the same directory, you could write this:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">include "a.fppi"
|
|
constant b = a</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>After resolving the include specifier, the model is equivalent
|
|
to the following:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant a = 0
|
|
constant b = a</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>To see this, do the following:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>Create files <code>a.fppi</code> and <code>b.fpp</code> as described
|
|
above.</p>
|
|
</li>
|
|
<li>
|
|
<p>Run <code>fpp-format -i b.fpp</code>.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><code>fpp-format</code> is a tool for formatting FPP source files.
|
|
It also can expand include specifiers.
|
|
<code>fpp-format</code> is discussed further in the section on
|
|
<a href="#Analyzing-and-Translating-Models_Formatting-FPP-Source">formatting FPP source</a>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>As mentioned above, the path is relative to the directory
|
|
of the file containing the include specifier.
|
|
So if <code>a.fppi</code> is located in a subdirectory <code>A</code>, you could write this:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">include "A/a.fppi"
|
|
constant b = a</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>And if <code>a.fppi</code> is located in the parent directory, you could write this:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">include "../a.fppi"
|
|
constant b = a</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>You can write an include specifier inside a module.
|
|
In this case, any definitions in the included file are treated as occurring
|
|
inside the module.
|
|
For example, if <code>a.fppi</code> contains the definition <code>constant a = 0</code>,
|
|
then this source text</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">module M { include "a.fppi" }</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>defines the constant <code>M.a</code>.
|
|
As an exercise, try this:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>% echo "module M { constant a = 0 }" > a.fppi
|
|
% fpp-check
|
|
include "a.fppi"
|
|
constant b = M.a
|
|
^D
|
|
%</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The check should pass.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In any case, an included file must contain complete syntactic
|
|
units that may legally appear at the point where the include specifier appears.
|
|
For example, an included file may contain one or more constant
|
|
definitions or type definitions.
|
|
It may not contain a bare identifier <code>a</code>, as this is not a valid top-level
|
|
or module-level syntactic unit.
|
|
Nor is it valid to write an include specifier in a place where an identifier
|
|
like <code>a</code>
|
|
is expected.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For example, here is the result of a failed attempt to include
|
|
an identifier into a constant definition:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>% echo a > a.fppi
|
|
% fpp-check
|
|
module M { constant include "a.fppi" = 0 }
|
|
constant b = M.a
|
|
^D
|
|
fpp-check
|
|
stdin: 1.21
|
|
module M { constant include "a.fppi" = 0 }
|
|
^
|
|
error: identifier expected
|
|
%</pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Specifying-Models-as-Files_Dependencies">14.3. Dependencies</h3>
|
|
<div class="paragraph">
|
|
<p>Whenever a model spans two or more files, one file <em>F</em> may use
|
|
one or more definitions appearing in other files.
|
|
In order to analyze <em>F</em>, the tools must extract
|
|
the definitions from these other files, called the <strong>dependencies</strong> of <em>F</em>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For example, suppose the file <code>a.fpp</code> contains the following definition:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant a = 0</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>And suppose the file <code>b.fpp</code> contains the following definition:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant b = a</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>If you present both files to <code>fpp-check</code>, like this:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>% fpp-check a.fpp b.fpp</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>the check will pass.
|
|
However, if you present just <code>b.fpp</code>, like this:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>% fpp-check b.fpp</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>you will get an error stating that the symbol <code>a</code> is undefined. (Try it and
|
|
see.)
|
|
The error occurs because the definition of <code>a</code> is located in <code>a.fpp</code>,
|
|
which was not included in the input to the analysis.
|
|
In this case we say that <code>a.fpp</code> is a <strong>dependency</strong> of <code>b.fpp</code>.
|
|
In order to analyze a file <em>F</em> (for example, <code>b.fpp</code>), the analyzer
|
|
needs to be told where to find all the dependencies of <em>F</em> (for example,
|
|
<code>a.fpp</code>).</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For simple models, we can manage the dependencies by hand, as we
|
|
did for the example above.
|
|
However, for even moderately complex models, this kind of hand management
|
|
becomes difficult.
|
|
Therefore FPP has a set of tools and features for automatic dependency
|
|
management.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In summary, dependency management in FPP works as follows:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>You run a tool called <code>fpp-locate-defs</code> to generate <strong>location specifiers</strong>
|
|
for all the definitions <em>that could be used</em> in a set of files <em>F</em>.</p>
|
|
</li>
|
|
<li>
|
|
<p>You run a tool called <code>fpp-depend</code>, passing it the files <em>F</em>
|
|
and the location specifiers generated in step 1.
|
|
It emits a list of files containing definitions <em>that are actually used</em> in <em>F</em>
|
|
(i.e., the dependencies of <em>F</em>).</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>These steps may occur in separate phases of development.
|
|
For example:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>You may run step 1 to locate all the type definitions
|
|
available for use in the model.</p>
|
|
</li>
|
|
<li>
|
|
<p>You may run step 2 to develop ports that depend on the types.
|
|
Typically you would run this step as part of a build process, e.g.,
|
|
the CMake build process included in the F Prime distribution.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Below we explain these steps in more detail.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Specifying-Models-as-Files_Location-Specifiers">14.4. Location Specifiers</h3>
|
|
<div class="paragraph">
|
|
<p>A location specifier is a unit of syntax in an FPP model.
|
|
It specifies the location of a definition used in the model.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Although it is possible to write location specifiers by hand,
|
|
you should usually not do so.
|
|
Instead, you should write definitions and let the tools discover their
|
|
locations, as described
|
|
in the section on <a href="#Specifying-Models-as-Files_Locating-Definitions">locating
|
|
definitions</a>.</p>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Specifying-Models-as-Files_Location-Specifiers_Syntax">14.4.1. Syntax</h4>
|
|
<div class="paragraph">
|
|
<p>A location specifier consists of the keyword <code>locate</code>, a kind of definition,
|
|
the name of a definition, and a string representing a file path.
|
|
For example, to locate the definition of constant <code>a</code> at <code>a.fpp</code>,
|
|
we would write</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp"># Locating a constant definition
|
|
locate constant a at "a.fpp"</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For the current version of FPP, the kind of definition can be <code>constant</code>,
|
|
<code>type</code>, or <code>port</code>.
|
|
To locate a type <code>T</code> in a file <code>T.fpp</code>, we would write the following:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp"># Locating a type definition
|
|
locate type T at "T.fpp"</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>To locate a port <code>P</code> in a file <code>P.fpp</code>, we write the following:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp"># Locating a port definition
|
|
locate port P at "P.fpp"</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>To locate an enum, we locate the type; the location of the enumerated
|
|
constants are then implied:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp"># Locating an enum definition,
|
|
# including the enumerated constant definitions
|
|
locate type E at "E.fpp"</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Specifying-Models-as-Files_Location-Specifiers_Path-Names">14.4.2. Path Names</h4>
|
|
<div class="paragraph">
|
|
<p>As with
|
|
<a href="#Specifying-Models-as-Files_Include-Specifiers">include specifiers</a>,
|
|
the path name in a location specifier <em>L</em> is relative to the
|
|
location of the file where <em>L</em> appears.
|
|
For example, suppose the file <code>b.fpp</code> appears in the file system in some
|
|
directory <em>D</em>.
|
|
Suppose also that <em>D</em> has a subdirectory <code>Constants</code>, <code>Constants</code> contains a
|
|
file <code>a.fpp</code>,
|
|
and <code>a.fpp</code> defines the constant <code>a</code>.
|
|
Then in <code>b.fpp</code> we could write this:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">locate constant a at "Constants/a.fpp"</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>If, instead of residing in a subdirectory, <code>a.fpp</code> were located one directory above
|
|
<code>b.fpp</code> in the file system, we could write this:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">locate constant a at "../a.fpp"</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Specifying-Models-as-Files_Location-Specifiers_Definition-Names">14.4.3. Definition Names</h4>
|
|
<div class="paragraph">
|
|
<p>The definition name appearing after the keyword <code>locate</code>
|
|
may be a qualified name.
|
|
For example, suppose the file <code>M.fpp</code> contains the following:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">module M { constant a = 0 }</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Then in file <code>b.fpp</code> we could write this:</p>
|
|
</div>
|
|
<div class="listingblock fpp">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code>locate constant M.a at "M.fpp"</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Optionally, we may enclose the location specifier in the module <code>M</code>, like
|
|
this:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">module M { locate constant a at "M.fpp" }</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>A location specifier written inside a module this way has its definition name
|
|
implicitly qualified with the module name.
|
|
For example, the name <code>a</code> appearing in the example above is automatically
|
|
resolved to <code>M.a</code>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Note that this rule is different than for other uses of definitions.
|
|
For example, when using the constant <code>M.a</code> in an expression inside module <code>M</code>,
|
|
you may spell the constant either <code>a</code> or <code>M.a</code>;
|
|
but when referring to the same constant <code>M.a</code> in a location specifier inside
|
|
module <code>M</code>, you must write <code>a</code> and not <code>M.a</code>.
|
|
(If you wrote <code>M.a</code>, it would be incorrectly resolved to <code>M.M.a</code>.)
|
|
The purpose of this rule is to facilitate dependency analysis,
|
|
which occurs before the analyzer has complete information about
|
|
definitions and their uses.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Specifying-Models-as-Files_Location-Specifiers_Included-Files">14.4.4. Included Files</h4>
|
|
<div class="paragraph">
|
|
<p>When you write a file that contains definitions and you
|
|
<a href="#Specifying-Models-as-Files_Include-Specifiers">include that file in another file</a>,
|
|
the location of each definition is the file where the definition is
|
|
included, not the file where the definition appears.
|
|
For example, suppose that file <code>a.fppi</code> contains the
|
|
definition <code>constant a = 0</code>,
|
|
and suppose that file <code>b.fpp</code> contains the include specifier <code>include "a.fppi"</code>.
|
|
When analyzing <code>b.fpp</code>, the location of the definition of the constant <code>a</code>
|
|
is <code>b.fpp</code>, not <code>a.fppi</code>.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Specifying-Models-as-Files_Locating-Definitions">14.5. Locating Definitions</h3>
|
|
<div class="paragraph">
|
|
<p>Given a collection of FPP source files <em>F</em>, you can generate location specifiers
|
|
for all the definitions in <em>F</em>.
|
|
The tool for doing this analysis is called <code>fpp-locate-defs</code>.
|
|
As example, you can run <code>fpp-locate-defs</code> to report the locations of all
|
|
the definitions in a subdirectory called <code>Constants</code> that contains constant
|
|
definitions for your model.
|
|
When analyzing other files that use the constants, you can use the location
|
|
specifiers to discover dependencies on individual files within <code>Constants</code>.</p>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Specifying-Models-as-Files_Locating-Definitions_Running-fpp-locate-defs">14.5.1. Running fpp-locate-defs</h4>
|
|
<div class="paragraph">
|
|
<p>To locate definitions, do the following:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>Collect all the FPP source files containing the definitions you want to
|
|
locate.
|
|
For example, run <code>find Constants -name '*.fpp'</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>Run <code>fpp-locate-defs</code> with the result of step 1 as the command-line
|
|
arguments.
|
|
The result will be a list of location specifiers.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For example, suppose the file <code>Constants/a.fpp</code> defines the constant <code>a</code>.
|
|
Running</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>% fpp-locate-defs `find Constants -name '*.fpp'`</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>generates the location specifier</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">locate constant a at "Constants/a.fpp"</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Specifying-Models-as-Files_Locating-Definitions_Location-Paths">14.5.2. Location Paths</h4>
|
|
<div class="paragraph">
|
|
<p>By default, the location path is relative to the current
|
|
directory.
|
|
To specify a different base directory, use the option <code>-d</code>.
|
|
For example, running</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>% fpp-locate-defs -d Constants `find Constants -name '*.fpp'`</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>generates the location specifier</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">locate constant a at "a.fpp"</code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Specifying-Models-as-Files_Locating-Definitions_Included-Definitions">14.5.3. Included Definitions</h4>
|
|
<div class="paragraph">
|
|
<p>Consider the case where you write a definition in one file and
|
|
include that file in another file via an
|
|
<a href="#Specifying-Models-as-Files_Include-Specifiers">include specifier</a>.
|
|
For example, suppose file <code>Constants.fpp</code> looks like this:</p>
|
|
</div>
|
|
<div class="listingblock fpp">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code>module Constants {
|
|
|
|
constant a = 0
|
|
include "b.fppi"
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Suppose <code>b.fppi</code> contains the definition <code>constant b = 1</code>.
|
|
If you run <code>find</code> on this directory as described above and provide
|
|
the output to <code>fpp-locate-defs</code>, then you will get the following output:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>The definition of constant <code>a</code> is located at <code>Constants.fpp</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>The definition of constant <code>b</code> is also located at <code>Constants.fpp</code>.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For purposes of dependency analysis, this is what you want.
|
|
You want uses of <code>b</code> to depend on <code>Constants.fpp</code> (where the
|
|
definition
|
|
of <code>b</code> is included) rather than <code>b.fpp</code> (where the definition of <code>b</code> is
|
|
stated).</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>When running a <code>find</code> command to find files containing definitions,
|
|
you should exclude any files that are included in other files.
|
|
If your main FPP files end with <code>.fpp</code> and your included FPP files end with
|
|
<code>.fppi</code>, then running</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>find . -name '*.fpp'</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>will pick up just the main files.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Specifying-Models-as-Files_Computing-Dependencies">14.6. Computing Dependencies</h3>
|
|
<div class="paragraph">
|
|
<p>Given files <em>F</em> and location specifiers <em>L</em> that locate the definitions used in
|
|
<em>F</em>, you can
|
|
generate the dependencies of <em>F</em>.
|
|
The tool for doing this is called <code>fpp-depend</code>.</p>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Specifying-Models-as-Files_Computing-Dependencies_Running-fpp-depend">14.6.1. Running fpp-depend</h4>
|
|
<div class="paragraph">
|
|
<p>To run <code>fpp-depend</code>, you pass it as input (1) files <em>F</em> that you want to
|
|
analyze
|
|
and (2) a superset of the location specifiers for the definitions used in that
|
|
code.
|
|
The tool extracts the location specifiers for the definitions used in <em>F</em>, resolves
|
|
them to absolute path names (the dependencies of <em>F</em>), and writes the
|
|
dependencies to standard output.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For example, suppose the file <code>a.fpp</code> contains the following
|
|
definition:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant a = 0</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Suppose the file <code>b.fpp</code> contains the following definition:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant b = 1</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Suppose the file <code>locations.fpp</code> contains the following location
|
|
specifiers:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">locate constant a at "a.fpp"
|
|
locate constant b at "b.fpp"</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>And suppose the file <code>c.fpp</code> contains the following definition of <code>c</code>,
|
|
which uses the definition of <code>b</code> but not the definition of <code>a</code>:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant c = b + 1</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Then running <code>fpp-depend locations.fpp c.fpp</code> produces the output
|
|
<code>[path-prefix]/b.fpp</code>.
|
|
The dependency output contains absolute path names, which will vary from system
|
|
to system.
|
|
Here we represent the system-dependent part of the path as <code>[path-prefix]</code>.</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>% fpp-depend locations.fpp c.fpp
|
|
[path-prefix]/b.fpp</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>As usual with FPP tools, you can provide input as a set of files
|
|
or on standard input.
|
|
So the following is equivalent:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>% cat locations.fpp c.fpp | fpp-depend
|
|
[path-prefix]/b.fpp</pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Specifying-Models-as-Files_Computing-Dependencies_Transitive-Dependencies">14.6.2. Transitive Dependencies</h4>
|
|
<div class="paragraph">
|
|
<p><code>fpp-depend</code> computes dependencies transitively.
|
|
This means that if <em>A</em> depends on <em>B</em> and <em>B</em>
|
|
depends on <em>C</em>, then <em>A</em> depends on <em>C</em>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For example, suppose again that <code>locations.fpp</code>
|
|
contains the following location specifiers:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">locate constant a at "a.fpp"
|
|
locate constant b at "b.fpp"</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Suppose the file <code>a.fpp</code> contains the following definition:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant a = 0</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Suppose the file <code>b.fpp</code> contains the following definition:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant b = a</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>And suppose that file <code>c.fpp</code> contains the following definition:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant c = b</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Notice that there is a direct dependency of <code>c.fpp</code> on <code>b.fpp</code>
|
|
and a transitive dependency of <code>c.fpp</code> on <code>a.fpp</code>.
|
|
The transitive dependency occurs because there is a direct dependency
|
|
of <code>c.fpp</code> on <code>b.fpp</code> and a direct dependency of <code>b.fpp</code> on <code>a.fpp</code>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Running <code>fpp-depend</code> on <code>locations.fpp</code> and <code>c.fpp</code>
|
|
produces both dependencies:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>% fpp-depend locations.fpp c.fpp
|
|
[path-prefix]/a.fpp
|
|
[path-prefix]/b.fpp</pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Specifying-Models-as-Files_Computing-Dependencies_Missing-Dependencies">14.6.3. Missing Dependencies</h4>
|
|
<div class="paragraph">
|
|
<p>Suppose we construct the files <code>locations.fpp</code> and <code>a.fpp</code>, <code>b.fpp</code>, and <code>c.fpp</code>
|
|
as described in the previous section, but then we temporarily remove <code>b.fpp</code>.
|
|
Then the following facts are true:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p><code>fpp-depend</code> can see the direct dependency of <code>c.fpp</code> on <code>b.fpp</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p><code>fpp-depend</code> can see that <code>b.fpp</code> does not exist.
|
|
In this case we say that <code>b.fpp</code> is a <strong>missing dependency</strong>.</p>
|
|
</li>
|
|
<li>
|
|
<p><code>fpp-depend</code> cannot see that <code>b.fpp</code> depends on <code>a.fpp</code> (that dependency
|
|
occurred in the missing file) and therefore it cannot see that
|
|
<code>c.fpp</code> depends on <code>a.fpp</code>.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In this case, by default, <code>fpp-depend</code> does the best that it can:
|
|
it reports the dependency of <code>c.fpp</code> on <code>b.fpp</code>.</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>% fpp-depend locations.fpp c.fpp
|
|
[path-prefix]/b.fpp</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The philosophy behind <code>fpp-depend</code> is to be as permissive and enabling as
|
|
possible.
|
|
It doesn’t assume that something is wrong because a dependency is missing:
|
|
for example, that dependency could be created later, as part of a code-generation
|
|
step.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>However, you may want to know about missing dependencies, either to issue
|
|
a warning or error because something really is wrong, or to identify files to
|
|
generate.
|
|
To record missing dependencies, use the <code>-m</code> option.
|
|
It takes as an argument the name of a file, and it writes missing dependencies
|
|
(if any)
|
|
to that file.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For example, the command</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>fpp-depend -m missing.txt locations.fpp c.fpp</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>writes the missing dependency <code>[path-prefix]/b.fpp</code> to <code>missing.txt</code> in
|
|
addition to writing
|
|
the dependency <code>[path-prefix]/b.fpp</code> to standard output.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Specifying-Models-as-Files_Computing-Dependencies_Included-Files">14.6.4. Included Files</h4>
|
|
<div class="paragraph">
|
|
<p>Suppose file <code>a.fpp</code> contains the
|
|
<a href="#Specifying-Models-as-Files_Include-Specifiers">include specifier</a>
|
|
<code>include "b.fppi"</code>.
|
|
Then there are two options for computing the dependencies of <code>a.fpp</code>:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p><code>a.fpp</code> does not depend on <code>b.fppi</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p><code>a.fpp</code> does depend on <code>b.fppi</code>.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Option 1 is what you want for assembling the input
|
|
to FPP analysis and translation tools such as <code>fpp-check</code>.
|
|
In this case, when analyzing <code>a.fpp</code>, the tool will resolve the include
|
|
specifier and include the contents of <code>b.fppi</code>. So <code>b.fppi</code> should
|
|
not be included as a separate input to the analysis.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>On the other hand, suppose you are constructing a list of dependencies
|
|
for a build system such as the F Prime CMake system.
|
|
In this case, the build system doesn’t know anything about FPP include specifiers.
|
|
However, it needs to know that <code>a.fpp</code> does depend on <code>b.fppi</code> in the sense that
|
|
if <code>b.fppi</code> is modified, then <code>a.fpp</code> should be analyzed or translated again.
|
|
So in this case we want option 2.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>By default, <code>fpp-depend</code> provides option 1:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>% echo 'include "b.fppi"' > a.fpp
|
|
% rm -f b.fppi
|
|
% touch b.fppi
|
|
% fpp-depend a.fpp</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>To get option 2, use the <code>-i</code> option to <code>fpp-depend</code>.
|
|
It takes as an argument the name of a file, and it writes the included dependencies
|
|
(if any) to that file.</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>% echo 'include "b.fppi"' > a.fpp
|
|
% rm -f b.fppi
|
|
% touch b.fppi
|
|
% fpp-depend -i included.txt a.fpp
|
|
% cat included.txt
|
|
[path-prefix]/b.fppi</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In practice, you usually run <code>fpp-depend</code> with the <code>-i</code> <em>file</em> option
|
|
enabled.
|
|
Then option 1 corresponds to the output of the tool, and option 2 corresponds
|
|
to the output plus the contents of <em>file</em>.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Specifying-Models-as-Files_Computing-Dependencies_Dependencies-Between-Build-Modules">14.6.5. Dependencies Between Build Modules</h4>
|
|
<div class="paragraph">
|
|
<p>As discussed
|
|
<a href="#Specifying-Models-as-Files_Computing-Dependencies_Transitive-Dependencies">above</a>, the standard output of <code>fpp-depend</code> reports transitive dependencies.
|
|
This is ordinarily what you want (a) for computing the input to an FPP
|
|
analysis tool and (b) for managing dependencies between files in a build.
|
|
For example, suppose that <code>a.fpp</code> depends on <code>b.fpp</code> and <code>b.fpp</code> depends on <code>c.fpp</code>.
|
|
When running analysis or code generation on <code>a.fpp</code>, you will need to import
|
|
<code>b.fpp</code> and <code>c.fpp</code> (see the
|
|
<a href="#Specifying-Models-as-Files_Locating-Uses">next section</a>
|
|
for an example).
|
|
Further, if you have a build rule for translating <code>a.fpp</code> to C++, then you probably want to
|
|
re-run that rule if <code>c.fpp</code> changes.
|
|
Therefore you need to report a dependency of <code>a.fpp</code> on <code>c.fpp</code>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>However, suppose that your build system divides the FPP files into groups
|
|
of files called <strong>build modules</strong>, and it manages dependencies between
|
|
the modules.
|
|
This is how the F Prime CMake system works.
|
|
In this case, assuming there is no direct dependency from <code>a.fpp</code> to <code>c.fpp</code>,
|
|
you may <em>not</em> want to report a dependency from <code>a.fpp</code> to <code>c.fpp</code>
|
|
to the build system:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>If <code>a.fpp</code> and <code>c.fpp</code> are in the same build module, then they
|
|
are in the same node of the dependency graph.
|
|
So there is no dependency to manage.</p>
|
|
</li>
|
|
<li>
|
|
<p>Otherwise, it suffices to report the file dependencies (a) from <code>a.fpp</code>
|
|
to <code>b.fpp</code> and (b) from <code>b.fpp</code> to <code>c.fpp</code>.
|
|
We can let the build system infer (a) the direct dependency from the module
|
|
containing <code>a.fpp</code> to the module containing <code>b.fpp</code>; (b) the direct
|
|
dependency from the module
|
|
containing <code>b.fpp</code> to the module containing <code>c.fpp</code>; and (c)
|
|
the transitive dependency from the module containing <code>a.fpp</code>
|
|
to the module containing <code>c.fpp</code>.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>To compute direct dependencies, run <code>fpp-depend</code> with the option
|
|
<code>-d</code> <em>file</em>.
|
|
The tool will write a list of direct dependencies to <em>file</em>.
|
|
Because direct dependencies are build dependencies,
|
|
any
|
|
<a href="#Specifying-Models-as-Files_Computing-Dependencies_Included-Files">included files</a>
|
|
will appear in the list.
|
|
For this purpose, an included file is (a) any file included by an
|
|
input file to <code>fpp-depend</code>; or (b) any file included
|
|
by such a file, and so forth.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>When setting up a build based on build modules, you will typically
|
|
use <code>fpp-depend</code> as follows, for each module <em>M</em> in the build:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>Let <em>S</em> be the list of source files in <em>M</em>.</p>
|
|
</li>
|
|
<li>
|
|
<p>Run <code>fpp-depend -m missing.txt -d direct.txt</code> <em>S</em> and use the
|
|
output as follows:</p>
|
|
<div class="olist loweralpha">
|
|
<ol class="loweralpha" type="a">
|
|
<li>
|
|
<p>The standard output reports the FPP source files to import
|
|
when running FPP analysis tools on the module.</p>
|
|
</li>
|
|
<li>
|
|
<p><code>missing.txt</code> reports missing dependencies.</p>
|
|
</li>
|
|
<li>
|
|
<p><code>direct.txt</code> reports direct dependencies.
|
|
Use those to construct module dependencies for the build system.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>You can also use the <code>-g</code> option to identify generated files;
|
|
we discuss this option
|
|
<a href="#Analyzing-and-Translating-Models_Identifying-Generated-Files">below</a>.
|
|
Note that we do not use the <code>-i</code> option to <code>fpp-depend</code>, because the relevant
|
|
included files are already present in <code>direct.txt</code>.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Specifying-Models-as-Files_Computing-Dependencies_Framework-Dependencies">14.6.6. Framework Dependencies</h4>
|
|
<div class="paragraph">
|
|
<p>Certain FPP constructs imply dependencies on parts of the F Prime framework
|
|
that may not be available on all platforms.
|
|
For example, use of a
|
|
<a href="#Defining-Components_Port-Instances_Basic-Port-Instances">guarded input port</a>
|
|
requires that an operating system provides a mutex lock.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>To report framework dependencies, run <code>fpp-depend</code> with the option
|
|
<code>-f</code> <em>file</em>, where <em>file</em> is the name of an output file.
|
|
The currently recognized framework dependencies are as follows:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p><code>Fw_Comp</code> if the FPP model defines a passive component.</p>
|
|
</li>
|
|
<li>
|
|
<p><code>Fw_CompQueued</code> if the model defines a queued or active component.</p>
|
|
</li>
|
|
<li>
|
|
<p><code>Os</code> if the model defines a queued or active component or
|
|
uses a guarded input port specifier.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Each dependency corresponds to a build module (i.e., a
|
|
statically compiled library) of the F Prime framework.
|
|
<code>fpp-depend</code> writes the dependencies in the order that they must
|
|
be provided to the linker.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Specifying-Models-as-Files_Locating-Uses">14.7. Locating Uses</h3>
|
|
<div class="paragraph">
|
|
<p>Given a collection of files <em>F</em> and their dependencies <em>D</em>, you can generate
|
|
the locations of the definitions appearing in <em>D</em> and used in <em>F</em>.
|
|
This information is not necessary for doing analysis and translation — for
|
|
that it is sufficient to know the file dependencies <em>D</em>.
|
|
However, by reporting dependencies on individual definitions,
|
|
this analysis provides an additional level of detail that may be helpful.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The tool for doing this analysis is called <code>fpp-locate-uses</code>.
|
|
As an example, you can run <code>fpp-locate-uses</code> to report the locations of all the
|
|
type definitions used in a port definition.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>To locate uses, run <code>fpp-locate-uses -i</code> <em>D</em> <em>F</em>, where <em>D</em> is a comma-separated
|
|
list and <em>F</em> is a space-separated list.
|
|
The <code>-i</code> option stands for <em>import</em>: it says that the files <em>D</em> are to be read
|
|
for their
|
|
definitions, but not to be included in the results of the analysis.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For example, suppose <code>a.fpp</code> defines constant <code>a</code>, <code>b.fpp</code> defines constant
|
|
<code>b</code>,
|
|
and <code>c.fpp</code> uses <code>a</code> but not <code>b</code>.
|
|
Then <code>fpp-locate-uses -i a.fpp,b.fpp c.fpp</code> generates the output <code>locate a at
|
|
"a.fpp"</code></p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Note that unlike in the case of
|
|
<a href="#Specifying-Models-as-Files_Computing-Dependencies">dependency analysis</a>,
|
|
the inputs <em>D</em> and <em>F</em> to <code>fpp-locate-uses</code> must form a complete model.
|
|
There must be no name used in <em>D</em> or in <em>F</em> that is not defined somewhere in
|
|
<em>D</em> or in <em>F</em>.
|
|
If <em>D</em> is the output of running <code>fpp-depend</code> on <em>F</em>, and there are no
|
|
<a href="#Specifying-Models-as-Files_Computing-Dependencies_Missing-Dependencies">missing dependencies</a>,
|
|
then this property should hold.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>With <code>fpp-locate-uses</code>, you can automatically derive the equivalent of the
|
|
<code>include</code>
|
|
declarations that you would normally write by hand when programming in C++.
|
|
For example, suppose you have specified a port <em>P</em> that uses a type <em>T</em>.
|
|
To bring <em>P</em> into a C++ translation context, you would write an <code>include</code>
|
|
directive that
|
|
includes <em>T</em> into <em>P</em>. In FPP you don’t do this.
|
|
Instead, you can do the following:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>Run <code>fpp-locate-defs</code> to generate location specifiers <em>L</em> for all the type
|
|
definitions.
|
|
You can do this as needed, or you can do it once and check it in as part of
|
|
the module that defines the types.</p>
|
|
</li>
|
|
<li>
|
|
<p>Run <code>fpp-depend</code> on <em>L</em> and <em>P</em> to generate the dependencies <em>D</em> of <em>P</em>.</p>
|
|
</li>
|
|
<li>
|
|
<p>Run <code>fpp-locate-uses -i</code> <em>D</em> <em>P</em>.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The result is a location specifier that gives the location of <em>T</em>.
|
|
If you wish, you can check the result in as part of the source code that
|
|
defines <em>P</em>.
|
|
Doing this provide as a kind of “import statement,” if that is desired
|
|
to make the dependencies explicit in the code.
|
|
Or you can just use the procedure given above to generate the "import
|
|
statement"
|
|
whenever desired, and see the dependencies that way.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>As with <code>fpp-locate-defs</code>, you can use <code>-d</code> to specify a base directory
|
|
for the location specifiers.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Specifying-Models-as-Files_Path-Name-Aliases">14.8. Path Name Aliases</h3>
|
|
<div class="paragraph">
|
|
<p>Because FPP associates locations with symbols, and the locations
|
|
are path names, care is required when using path names that are
|
|
aliases of other path names, via symbolic links or hard links.
|
|
There are two issues to consider:
|
|
relative paths and unique locations.</p>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Specifying-Models-as-Files_Path-Name-Aliases_Relative-Paths-and-Symbolic-Links">14.8.1. Relative Paths and Symbolic Links</h4>
|
|
<div class="paragraph">
|
|
<p>A <strong>relative path</strong> is a path that does not start with a slash and is
|
|
relative to the current directory path, which is
|
|
set by the environment in which an FPP tool is run.
|
|
For example, the command sequence</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="bash">% cd /home/user/dir
|
|
% fpp-check file.fpp</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>sets the current directory path to <code>/home/user/dir</code> and then runs
|
|
<code>fpp-check file.fpp</code>.
|
|
In this case, the relative path <code>file.fpp</code> is resolved to
|
|
<code>/home/user/dir/file.fpp</code>.
|
|
An <strong>absolute path</strong> is a path that starts with a slash and specifies
|
|
a complete path from the root of the file system, e.g.,
|
|
<code>/home/user/dir/file.fpp</code>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Because FPP is implemented in Scala, relative paths are resolved by
|
|
the Java Virtual Machine (JVM).
|
|
When the current directory path contains a symbolic link,
|
|
this resolution may not work in the way that you expect.
|
|
For example, suppose the following:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p><em>D</em> is an absolute path to a directory.
|
|
<em>D</em> is a “real” path, i.e., none of the path elements in <em>D</em> is a symbolic
|
|
link to a directory.</p>
|
|
</li>
|
|
<li>
|
|
<p><em>S</em> is an absolute path in which one or more of the path elements is a symbolic
|
|
link to a directory.
|
|
After resolving all symbolic links, <em>S</em> points to <em>D</em>.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Suppose that <em>D</em> contains a file <code>file.fpp</code>, and that the
|
|
current directory path is <em>D</em>.
|
|
In this case, when you run an FPP tool with <code>file.fpp</code> as input,
|
|
any symbols defined in <code>file.fpp</code> will have location
|
|
<em>D</em> <code>/file.fpp</code>, as expected.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Now suppose that the current directory path is <em>S</em>.
|
|
In this case, when you run an FPP tool with <code>file.fpp</code> as input,
|
|
the symbols defined in <code>file.fpp</code> again have location <em>D</em> <code>/file.fpp</code>,
|
|
when you might expect them to have location <em>S</em> <code>/file.fpp</code>.
|
|
This is because the JVM resolves all symbolic links before computing
|
|
relative path names.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>This behavior can cause problems when using the <code>-p</code> (path prefix)
|
|
option with FPP code generation tools, as described in the section on
|
|
<a href="#Analyzing-and-Translating-Models">analyzing and translating models</a>.
|
|
See that section for details, and for suggested workarounds.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Specifying-Models-as-Files_Path-Name-Aliases_Unique-Locations">14.8.2. Unique Locations</h4>
|
|
<div class="paragraph">
|
|
<p>The FPP analyzers assume that each symbol <em>s</em> has
|
|
a unique path defining the location of the source file where
|
|
<em>s</em> is defined.
|
|
If paths contain names that are aliased via symbolic links or hard links, then
|
|
this may not be true:
|
|
for example, <em>P<sub>1</sub></em> and <em>P<sub>2</sub></em> may be syntactically different
|
|
absolute paths that represent the same physical location in the file system.
|
|
In this case it may be possible for the tools to associate two different locations
|
|
with the same FPP symbol definition.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>You must ensure that this doesn’t happen.
|
|
If you present the same file <em>F</em> to the FPP tools several times,
|
|
for example to locate definitions and to compute dependencies,
|
|
you must ensure that the path describing <em>F</em> is the same each
|
|
time, after resolving relative paths as described above.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="Analyzing-and-Translating-Models">15. Analyzing and Translating Models</h2>
|
|
<div class="sectionbody">
|
|
<div class="paragraph">
|
|
<p>The previous section explained how to specify an FPP model
|
|
as a collection of files:
|
|
how to divide a model into source files and how to compute the
|
|
dependencies of one or more files on other files.
|
|
This section explains the next step: how to perform analysis and
|
|
translation on part or all of an FPP model, after specifying
|
|
the model and computing its dependencies.</p>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Analyzing-and-Translating-Models_Checking-Models">15.1. Checking Models</h3>
|
|
<div class="paragraph">
|
|
<p>It is often useful to check a model for correctness, without
|
|
doing any translation.
|
|
The tool for checking models is called <code>fpp-check</code>.
|
|
If you provide one or more files as arguments, <code>fpp-check</code>
|
|
will attempt to read those files.
|
|
For example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>% fpp-check file1.fpp file2.fpp</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>If there are no arguments, then <code>fpp-check</code> reads from standard input.
|
|
For example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>% cat file1.fpp file2.fpp | fpp-check</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>If you run <code>fpp-check</code> with no arguments on the command line,
|
|
it will block and wait for standard input.
|
|
This is useful for interactive sessions, where you want
|
|
to type simple model text into the console and immediately check it.
|
|
<code>fpp-check</code> will keep reading input until (1) it encounters a parse error (more
|
|
on this below); or (2) you terminate the input with control-D (which must be
|
|
the first character in a line); or (3)
|
|
you terminate the program with control-C.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For larger models, the usual procedure for running <code>fpp-check</code> is as follows:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>Identify one or more files <em>F</em> that you want to check.</p>
|
|
</li>
|
|
<li>
|
|
<p><a href="#Specifying-Models-as-Files_Computing-Dependencies">Compute the dependencies</a> <em>D</em> of <em>F</em>.</p>
|
|
</li>
|
|
<li>
|
|
<p>Run <code>fpp-check</code> <em>D</em> <em>F</em>.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>All the files <em>D</em> and all the files <em>F</em> are specified as file arguments,
|
|
separated by spaces.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>When you run <code>fpp-check</code>, the following occurs:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>The tool parses all the input files, recursively resolving
|
|
<a href="#Specifying-Models-as-Files_Include-Specifiers">include specifiers</a> as it goes.
|
|
If there are any parse errors or any problems resolving include files (for
|
|
example, a missing file), it prints an error message to standard error and
|
|
halts with nonzero status.</p>
|
|
</li>
|
|
<li>
|
|
<p>If parsing succeeds, then the tool runs semantic analysis.
|
|
If everything checks out, the tool silently returns zero status.
|
|
Otherwise it prints an error message to standard error and
|
|
halts with nonzero status.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Checking for unconnected port instances:</strong>
|
|
It is often useful to check for port instances that appear
|
|
in a topology but that have no connections.
|
|
For example, the following is a useful procedure for adding component instances
|
|
and connections to a topology:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>Add the component instances.
|
|
In general this will introduce new port instances,
|
|
which will initially be unconnected.</p>
|
|
</li>
|
|
<li>
|
|
<p>Check for unconnected port instances.</p>
|
|
</li>
|
|
<li>
|
|
<p>Add some or all of the connections identified
|
|
in step 2.</p>
|
|
</li>
|
|
<li>
|
|
<p>Rerun steps 2 and 3 until there are no more
|
|
missing connections, or you are certain that the
|
|
missing connections are valid for your design.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>To check for unconnected port instances (step 2 in the procedure above),
|
|
run <code>fpp-check</code> with the option <code>-u</code> <em>file</em>, where <em>file</em> is
|
|
the name of an output file.
|
|
<code>fpp-check</code> will write the names of all unconnected port instances
|
|
to the file.
|
|
For this purpose, a port instance array is considered unconnected
|
|
if none of its port numbers are connected.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code>% fpp-check -u unconnected.txt
|
|
port P
|
|
|
|
passive component C {
|
|
sync input port pIn: P
|
|
output port pOut: [2] P
|
|
}
|
|
|
|
instance c: C base id 0x100
|
|
|
|
topology T1 {
|
|
|
|
instance c
|
|
|
|
}
|
|
|
|
topology T2 {
|
|
|
|
instance c
|
|
|
|
connections C {
|
|
c.pOut -> c.pIn
|
|
}
|
|
|
|
}
|
|
^D
|
|
% cat unconnected.txt
|
|
Topology T1:
|
|
c.pIn
|
|
c.pOut</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In this example, component instance <code>c</code> has the following port instances:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>Two output port instances <code>c.pOut[0]</code> and <code>c.pOut[1]</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>One input port instance <code>c.pIn</code>.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Topology <code>T1</code> uses instance <code>c</code> and does not connect any port number of
|
|
<code>c.pOut</code> or <code>c.pIn</code>.
|
|
So the output written to <code>unconnected.txt</code> reports that fact.
|
|
On the other hand, in topology <code>T2</code>, both <code>c.pOut</code> and <code>c.pIn</code>
|
|
are considered connected (so not reported as unconnected)
|
|
even though <code>c.Out</code> has two ports and only one of them is connected.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Analyzing-and-Translating-Models_Generating-C-Plus-Plus">15.2. Generating C Plus Plus</h3>
|
|
<div class="paragraph">
|
|
<p>This section describes how to generate C++ from FPP.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Tool name:</strong> The tool for translating FPP to C++ is called
|
|
<code>fpp-to-cpp</code>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Procedure:</strong>
|
|
The usual procedure for running <code>fpp-to-cpp</code> is as follows:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>Identify one or more files <em>F</em> that you want to translate.</p>
|
|
</li>
|
|
<li>
|
|
<p><a href="#Specifying-Models-as-Files_Computing-Dependencies">Compute the dependencies</a> <em>D</em> of <em>F</em>.</p>
|
|
</li>
|
|
<li>
|
|
<p>If <em>D</em> is empty, then run <code>fpp-to-cpp</code> <em>F</em>.</p>
|
|
</li>
|
|
<li>
|
|
<p>Otherwise run <code>fpp-to-cpp -i</code> <em>D<sub>1</sub></em> <code>,</code> …​ <code>,</code> <em>D<sub>n</sub></em> <em>F</em>, where <em>D<sub>i</sub></em> are the
|
|
names of the dependencies.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For example, suppose you want to generate C++ for the definitions in <code>c.fpp</code>,
|
|
If <code>c.fpp</code> has no dependencies, then run</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>% fpp-to-cpp c.fpp</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>On the other hand, if <code>c.fpp</code> depends on <code>a.fpp</code> and <code>b.fpp</code>, then run</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>% fpp-to-cpp -i a.fpp,b.fpp c.fpp</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Notice that you provide the dependencies as a comma-separated list of
|
|
arguments to the option <code>-i</code>.
|
|
<code>-i</code> stands for <em>import</em>.
|
|
This option tells the tool that you want to read the files in <em>D</em> for their symbols,
|
|
but you don’t want to translate them.
|
|
Only the files <em>F</em> provided as arguments are translated.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Tool behavior:</strong> When you run <code>fpp-to-cpp</code>, the following occurs:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>The tool runs the same analysis
|
|
<a href="#Analyzing-and-Translating-Models_Checking-Models">as for <code>fpp-check</code></a>.
|
|
If there is any problem, the tool prints an error message to
|
|
standard error and halts with nonzero status.</p>
|
|
</li>
|
|
<li>
|
|
<p>If the analysis succeeds, then the tool generates C++files, one
|
|
for each definition appearing in <em>F</em>, with names as shown in the table above.
|
|
The files are written to the current directory.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Standard input:</strong> Instead of providing named files as arguments,
|
|
you can provide FPP source on standard input, as described
|
|
for <a href="#Analyzing-and-Translating-Models_Checking-Models"><code>fpp-check</code></a>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>C++ file names:</strong> The table <a href="#cpp-file-names">C++ File Names</a> shows how FPP definitions are
|
|
translated to C++ files.</p>
|
|
</div>
|
|
<table id="cpp-file-names" class="tableblock frame-all grid-all stretch">
|
|
<caption class="title">Table 3. C++ File Names</caption>
|
|
<colgroup>
|
|
<col style="width: 50%;">
|
|
<col style="width: 50%;">
|
|
</colgroup>
|
|
<thead>
|
|
<tr>
|
|
<th class="tableblock halign-left valign-top">FPP Definition</th>
|
|
<th class="tableblock halign-left valign-top">C++ Files</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">Constants</p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>FppConstantsAc.{hpp,cpp}</code></p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">Array <em>A</em> outside any component</p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>A</em> <code>ArrayAc.{hpp,cpp}</code></p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">Array <em>A</em> in component <em>C</em></p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>C</em> <code><em></code> _A</em> <code>ArrayAc.{hpp,cpp}</code></p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">Enum <em>E</em> outside any component</p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>E</em> <code>EnumAc.{hpp,cpp}</code></p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">Enum <em>E</em> in component <em>C</em></p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>C</em> <code><em></code> _E</em> <code>EnumAc.{hpp,cpp}</code></p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">State machine <em>M</em> outside any component</p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>M</em> <code>StateMachineAc.{hpp,cpp}</code></p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">State machine <em>M</em> in component <em>C</em></p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>C</em> <code><em></code> _M</em> <code>StateMachineAc.{hpp,cpp}</code></p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">Struct <em>S</em> outside any component</p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>S</em> <code>SerializableAc.{hpp,cpp}</code></p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">Struct <em>S</em> in component <em>C</em></p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>C</em> <code><em></code> _S</em> <code>SerializableAc.{hpp,cpp}</code></p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">Alias type <em>A</em> outside any component</p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>A</em> <code>AliasAc.{hpp,h,cpp}</code></p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">Alias type <em>A</em> in component <em>C</em></p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>C</em> <code><em></code> _A</em> <code>AliasAc.{hpp,h,cpp}</code></p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">Port <em>P</em></p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>P</em> <code>PortAc.{hpp,cpp}</code></p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">Component <em>C</em></p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>C</em> <code>ComponentAc.{hpp,cpp}</code></p></td>
|
|
</tr>
|
|
<tr>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock">Topology <em>T</em></p></td>
|
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>T</em> <code>TopologyAc.{hpp,cpp}</code></p></td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
<div class="paragraph">
|
|
<p>For example, consider the FPP array definition</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">array A = [3] U32</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Outside of any component definition, this definition is translated to
|
|
a C++ class with name <code>A</code> defined in a files <code>AArrayAc.hpp</code>
|
|
and <code>AArray.cpp</code>.
|
|
Inside the definition of component <code>C</code>, it is translated to
|
|
a class with name <code>C_A</code> defined in the files <code>C_AArrayAc.hpp</code>
|
|
and <code>C_AArray.cpp</code>.
|
|
In either case the C++ namespace is given by the enclosing
|
|
FPP modules, if any.
|
|
For example, the following code</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">module M {
|
|
|
|
array A = [3] U32
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>generates an array class <code>M::A</code> in files <code>AArrayAc.hpp</code>
|
|
and <code>AArrayAc.cpp</code>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Headers for alias types:</strong>
|
|
For alias types, a C++ header with suffix <code>.hpp</code> is always generated.
|
|
A C header with suffix <code>.h</code> is also generated if the alias type
|
|
is C-compatible.
|
|
This means (1) the underlying
|
|
type is a signed or unsigned integer type or a floating-point type,
|
|
and (2) the alias type definition does not appear in an FPP module
|
|
or component, and (3) if the alias type refers to another alias
|
|
type <em>T</em>, then <em>T</em> is C-compatible.
|
|
For example, the following alias types are C-compatible
|
|
and cause <code>.h</code> headers to be generated:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">type T1 = U32
|
|
type T2 = T1</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The following alias types are not C-compatible, so
|
|
they do not cause <code>.h</code> headers to be generated:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">module M {
|
|
type T1 = U32 # Definition is in a module
|
|
}
|
|
type T2 = M.T1 # M.T1 is not C-compatible
|
|
array A = [3] U32
|
|
type T3 = A # A is not C-compatible</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>When both headers are generated, you should include the <code>.h</code> header in your
|
|
C programs and the <code>.hpp</code> header in your C++ programs.</p>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Analyzing-and-Translating-Models_Generating-C-Plus-Plus_Constant-Definitions">15.2.1. Constant Definitions</h4>
|
|
<div class="paragraph">
|
|
<p><code>fpp-to-cpp</code> extracts <a href="#Defining-Constants">constant definitions</a>
|
|
from the source files <em>F</em>.
|
|
It generates files <code>FppConstantsAc.hpp</code> and <code>FppConstantsAc.cpp</code>
|
|
containing C++ translations of the constants.
|
|
By including and/or linking against these files,
|
|
you can use constants defined in the FPP model
|
|
in your FSW implementation code.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>To keep things simple, only numeric, string, and Boolean constants are
|
|
translated;
|
|
struct and array constants are ignored.
|
|
For example, the following constant is not translated, because
|
|
it is an array:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant a = [ 1, 2, 3 ]</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>To translate array constants, you must expand them to values
|
|
that are translated, like this:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">constant a0 = 1
|
|
constant a1 = 2
|
|
constant a2 = 3
|
|
constant a = [ a0, a1, a2 ]</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Constants are translated as follows:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>Integer constants become enumeration constants.</p>
|
|
</li>
|
|
<li>
|
|
<p>Floating-point constants become <code>const</code> floating-point variables.</p>
|
|
</li>
|
|
<li>
|
|
<p><code>bool</code> point constants become <code>const bool</code> variables.</p>
|
|
</li>
|
|
<li>
|
|
<p><code>string</code> constants become <code>const char* const</code> variables initialized
|
|
with string literals.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>As an example, try this:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>% fpp-to-cpp
|
|
@ Constant a
|
|
constant a = 1
|
|
@ Constant b
|
|
constant b = 2.0
|
|
@ Constant c
|
|
constant c = true
|
|
@ Constant d
|
|
constant d = "abcd"
|
|
^D</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>You should see files <code>FppConstantsAc.hpp</code> and <code>FppConstantsAc.cpp</code>
|
|
in the current directory.
|
|
Examine them to confirm your understanding of how the translation
|
|
works.
|
|
Notice how the FPP annotations are translated to comments.
|
|
(We also remarked on this in the section on
|
|
<a href="#Writing-Comments-and-Annotations_Annotations">writing annotations</a>.)</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Constants defined inside components:</strong>
|
|
As noted in the section on
|
|
<a href="#Defining-Components_Constants-Types-Enums-and-State-Machines">defining components</a>,
|
|
when you define a constant <code>c</code> inside a component <code>C</code>,
|
|
the name of the corresponding constant in the generated C++
|
|
code is <code>C_c</code>.
|
|
As an example, run the following code through <code>fpp-to-cpp</code>
|
|
and examine the results:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">passive component C {
|
|
|
|
constant c = 0
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Generated header paths:</strong>
|
|
When one FPP definition <code>A</code> refers to another definition <code>B</code>,
|
|
the generated C++ file for <code>A</code> contains a directive to
|
|
include the generated header file for <code>B</code>.
|
|
The tool constructs the import path from the
|
|
<a href="#Specifying-Models-as-Files_Locating-Definitions">location</a> of the
|
|
definition of <code>B</code>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For example, suppose the file <code>[path prefix]/A/A.fpp</code> contains the following
|
|
definition, where <code>[path prefix]</code> represents the path prefix of directory
|
|
<code>A</code> starting from the root of the file system:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">array A = [3] B</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>And suppose the file <code>[path prefix]/B/B.fpp</code> contains the following definition:</p>
|
|
</div>
|
|
<div class="listingblock fpp">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code>array B = [3] U32</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>If you run this command in directory <code>[path prefix]/A</code></p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>% fpp-to-cpp -i ../B/B.fpp A.fpp</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>then in that directory the tool will generate a file <code>AArrayAc.hpp</code> containing
|
|
the following line:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="cpp">#include "[path prefix]/B/BArrayAc.hpp"</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Removing path prefixes:</strong>
|
|
Usually when generating C++ we don’t want to include the system-specific path
|
|
prefix.
|
|
Instead, we want the path to be specified relative to some known place, for
|
|
example
|
|
the root of the F Prime repository or a project repository.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>To remove the prefix <em>prefix</em> from generated paths, use the option
|
|
<code>-p</code> <em>prefix</em> .
|
|
To continue the previous example, running</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>fpp-to-cpp -i ../B/B.fpp -p [path prefix] A.fpp</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>generates a file <code>AArrayAc.hpp</code> containing the line</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="cpp">#include "B/BArrayAc.hpp"</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Notice that the path prefix <code>[path prefix]/</code> has been removed.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>To specify multiple prefixes, separate them with commas:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>fpp-to-cpp -p prefix1,prefix2, ...</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For each generated path, the tool will delete the longest prefix
|
|
that matches a prefix in the list.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>As discussed in the section on
|
|
<a href="#Specifying-Models-as-Files_Path-Name-Aliases_Relative-Paths-and-Symbolic-Links">relative paths and symbolic links</a>,
|
|
when a file name is relative to a path <em>S</em> that includes symbolic links,
|
|
the associated location is relative to the directory <em>D</em> pointed to by <em>S</em>.
|
|
In this case, providing <em>S</em> as an argument to <code>-p</code> will not work as expected.
|
|
To work around this issue, you can do one of the following:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>Provide both <em>D</em> and <em>S</em> as arguments to <code>-p</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>Use absolute paths when presenting files to FPP code generation tools
|
|
with the <code>-p</code> option.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>The include guard prefix:</strong> By default, the include guard
|
|
for <code>FppConstantsAc.hpp</code> is <em>guard-prefix</em> <code>_FppConstantsAc_HPP</code>,
|
|
where <em>guard-prefix</em> is the absolute path of the current
|
|
directory, after replacing non-identifier characters with underscores.
|
|
For example, if the current directory is <code>/home/user</code>, then
|
|
the guard prefix is <code>_home_user</code>, and the include guard is
|
|
<code>_home_user_FppConstantsAc_HPP</code>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The <code>-p</code> option, if present, is applied to the guard
|
|
prefix.
|
|
For example, if you run <code>fpp-to-cpp -p $PWD …​</code> then
|
|
the guard prefix will be empty.
|
|
In this case, the guard is <code>FppConstantsAc_HPP</code>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>If you wish to use a different prefix entirely, use the option
|
|
<code>-g</code> <em>guard-prefix</em>.
|
|
For example, if you run <code>fpp-to-cpp -g Commands …​</code>,
|
|
then the include guard will be <code>Commands_FppConstantsAc_HPP</code>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>More options:</strong> The following additional options are available
|
|
when running <code>fpp-to-cpp</code>:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p><code>-d</code> <em>dir</em> : Use <em>dir</em> instead of the current directory as
|
|
the output directory for writing files.
|
|
For example,</p>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>fpp-to-cpp -d cpp ...</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>writes output files
|
|
to the directory <code>cpp</code> (which must already exist).</p>
|
|
</div>
|
|
</li>
|
|
<li>
|
|
<p><code>-n</code> <em>file</em> : Write the names of the generated C++ files
|
|
to <em>file</em>.
|
|
This is useful for collecting autocoder build dependencies.</p>
|
|
</li>
|
|
<li>
|
|
<p><code>-s</code> <em>size</em> : Specify a default string size.
|
|
For example,</p>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>fpp-to-cpp -s 40 ...</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>FPP allows string types with no specified size.
|
|
When generating code we need to provide a default size
|
|
to use when FPP doesn’t specify the size.
|
|
If you don’t specify the <code>-s</code> option, then the tool uses
|
|
an automatic default of 80.</p>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Analyzing-and-Translating-Models_Generating-C-Plus-Plus_Types-Ports-State-Machines-and-Components">15.2.2. Types, Ports, State Machines, and Components</h4>
|
|
<div class="paragraph">
|
|
<p><strong>Generating code:</strong>
|
|
To generate code for type, port, state machine, and component definitions, you
|
|
run <code>fpp-to-cpp</code> in the same way as for
|
|
<a href="#Analyzing-and-Translating-Models_Generating-C-Plus-Plus_Constant-Definitions">constant definitions</a>, with one exception:
|
|
the translator ignores the <code>-g</code> option, because the include guard comes from
|
|
the qualified name of the definition.
|
|
For example, a component whose qualified name in FPP is <code>A.B.C</code>
|
|
uses the name <code>A_B_CComponentAc_HPP</code> in its include guard.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Alias types:</strong>
|
|
The generated code for an <a href="#Defining-Types_Alias-Type-Definitions">alias type
|
|
definition</a> is either a C-style <code>typedef</code> (in a <code>.h</code> file) or a C++11-style
|
|
<code>using</code> alias (in a <code>.hpp</code> file). The generated code for an alias to an FPP
|
|
<code>string</code> type is always an alias to the F Prime type <code>Fw::String</code>; the size in
|
|
the <code>string</code> type is ignored when generating the alias.
|
|
For example, the following alias type definitions
|
|
all generate aliases to <code>Fw::String</code>, either directly or indirectly:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">type T1 = string size 40 # Generates an alias to Fw::String
|
|
type T2 = string size 80 # Generates an alias to Fw::String
|
|
type T3 = T2 # Generates an alias to T2, which is an alias to Fw::String</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>When reporting generated files for alias types via the <code>-n</code> option,
|
|
<code>fpp-to-cpp</code> reports only <code>.hpp</code> files, not <code>.h</code> files.
|
|
This is to keep the analysis simple, so that it can be run when
|
|
<a href="#Analyzing-and-Translating-Models_Identifying-Generated-Files_Using-fpp-depend">computing dependencies</a>.
|
|
In a future version of FPP, we may revise the analysis strategy
|
|
and report the generation of <code>.h</code> files as well.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Using the generated code:</strong>
|
|
Once you generate C++ code for these definitions, you can use it to
|
|
write a flight software implementation.
|
|
The <a href="https://fprime.jpl.nasa.gov/devel/docs/user-manual/">F
|
|
User Manual</a> explains how to do this.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For more information about the generated code for data products,
|
|
for state machines, and for state machine instances, see the
|
|
<a href="https://fprime.jpl.nasa.gov/devel/docs/user-manual/">F
|
|
Prime design documentation</a>.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Analyzing-and-Translating-Models_Generating-C-Plus-Plus_Component-Implementation-and-Unit-Test-Code">15.2.3. Component Implementation and Unit Test Code</h4>
|
|
<div class="paragraph">
|
|
<p><code>fpp-to-cpp</code> has options <code>-t</code> and <code>-u</code> for generating component “templates”
|
|
or
|
|
partial implementations and for generating unit test code.
|
|
Here we cover the mechanics of using these options.
|
|
For more information on implementing and testing components in F Prime, see
|
|
the <a href="https://fprime.jpl.nasa.gov/devel/docs/user-manual/">F Prime User Manual</a>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Generating implementation templates:</strong>
|
|
When you run <code>fpp-to-cpp</code> with option <code>-t</code> and without option <code>-u</code>,
|
|
it generates a partial implementation for
|
|
each component definition <em>C</em> in the input.
|
|
The generated files are called <em>C</em> <code>.template.hpp</code> and <em>C</em> <code>.template.cpp</code>.
|
|
You can fill in the blanks in these files to provide the concrete
|
|
implementation of <em>C</em>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Generating unit test harness code:</strong>
|
|
When you run <code>fpp-to-cpp</code> with option <code>-u</code> and without option <code>-t</code>,
|
|
it generates support code for testing each component definition <em>C</em>
|
|
in the input.
|
|
The unit test support code resides in the following files:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p><em>C</em> <code>TesterBase.hpp</code> and <em>C</em> <code>TesterBase.cpp</code>.
|
|
These files define a class <em>C</em> <code>TesterBase</code>.
|
|
This class contains helper code for unit testing <em>C</em>,
|
|
for example an input port and history corresponding to each output port of <em>C</em>.</p>
|
|
</li>
|
|
<li>
|
|
<p><em>C</em> <code>GTestBase.hpp</code> and <em>C</em> <code>GTestBase.cpp</code>.
|
|
These files define a class <em>C</em> <code>GTestBase</code> derived
|
|
from <em>C</em>.
|
|
This class uses the Google Test framework to provide additional helper
|
|
code.
|
|
It is factored into a separate class so that you can use <em>C</em> <code>TesterBase</code>
|
|
without <em>C</em> <code>GTestBase</code> if you wish.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Generating unit test templates:</strong>
|
|
When you run <code>fpp-to-cpp</code> with both the <code>-u</code> and the <code>-t</code> options,
|
|
it generates a template or partial implementation of the unit tests
|
|
for each component <em>C</em> in the input.
|
|
The generated code consists of the following files:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p><em>C</em> <code>Tester.hpp</code> and <em>C</em> <code>Tester.cpp</code>.
|
|
These files partially define a class <em>C</em> <code>Tester</code> that is derived from <em>C</em> <code>GTestBase</code>.
|
|
You can fill in the partial definition to provide unit tests for <em>C</em>.
|
|
If you are not using Google Test, then you can modify
|
|
<em>C</em> <code>Tester</code> so that it is derived from <em>C</em> <code>TesterBase</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p><em>C</em> <code>TesterHelpers.cpp</code>. This file provides helper functions called by
|
|
the functions defined in <code>Tester.cpp</code>.
|
|
These functions are factored into a separate file so that you
|
|
can redefine them if you wish.
|
|
To redefine them, omit <em>C</em> <code>TesterHelpers.cpp</code> from your F Prime
|
|
unit test build.</p>
|
|
</li>
|
|
<li>
|
|
<p><em>C</em> <code>TestMain.cpp</code>. This file provides a minimal main function for unit
|
|
testing, including a sample test.
|
|
You can add your top-level test code to this file.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Unit test auto helpers:</strong>
|
|
When running <code>fpp-to-cpp</code> with the <code>-u</code> option, you can also specify the <code>-a</code>
|
|
or <strong>unit test auto helpers</strong> option.
|
|
This option moves the generation of the file <em>C</em> <code>TesterHelpers.cpp</code>
|
|
from the unit test template code to the unit test harness code.
|
|
Specifically:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>When you run <code>fpp-to-cpp -a -u</code>, the file <em>C</em> <code>TesterHelpers.cpp</code>
|
|
is generated.</p>
|
|
</li>
|
|
<li>
|
|
<p>When you run <code>fpp-to-cpp -a -t -u</code>, the file <em>C</em> <code>TesterHelpers.cpp</code>
|
|
is not generated.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The <code>-a</code> option supports a feature of the F Prime CMake build system called
|
|
<code>UT_AUTO_HELPERS</code>. With this feature enabled, you don’t have to manage the
|
|
file <em>C</em> <code>TesterHelpers.cpp</code> as part of your unit test source files; the
|
|
build system does it for you.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Analyzing-and-Translating-Models_Generating-C-Plus-Plus_Topology-Definitions">15.2.4. Topology Definitions</h4>
|
|
<div class="paragraph">
|
|
<p><code>fpp-to-cpp</code> also extracts <a href="#Defining-Topologies">topology definitions</a>
|
|
from the source files.
|
|
For each topology <em>T</em> defined in the source files, <code>fpp-to-cpp</code>
|
|
writes files <em>T</em> <code>TopologyAc.hpp</code> and <em>T</em> <code>TopologyAc.cpp</code>.
|
|
These files define two public functions:
|
|
<code>setup</code> for setting up the topology, and
|
|
<code>teardown</code>, for tearing down the topology.
|
|
The function definitions come from the definition of <em>T</em> and
|
|
from the
|
|
<a href="#Defining-Component-Instances_Init-Specifiers">init specifiers</a>
|
|
for the component instances used in <em>T</em>.
|
|
You can call these functions from a handwritten <code>main</code>
|
|
function.
|
|
We will explain how to write this <code>main</code> function in the
|
|
section on
|
|
<a href="#Writing-C-Plus-Plus-Implementations_Implementing-Deployments">implementing deployments</a>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>As an example, you can do the following:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>On the command line, run <code>fpp-to-cpp -p $PWD</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>Copy the text of the <a href="#Defining-Topologies_A-Simple-Example">simple topology example</a> and paste it into the terminal.</p>
|
|
</li>
|
|
<li>
|
|
<p>Press return, control-D, and return.</p>
|
|
</li>
|
|
<li>
|
|
<p>Examine the generated files <code>SimpleTopologyAc.hpp</code>
|
|
and <code>SimpleTopologyAc.cpp</code>.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>You can examine the files <code>RefTopologyAc.hpp</code> and <code>RefTopologyAc.cpp</code>
|
|
in the F Prime repository.
|
|
Currently these files are checked in at <code>Ref/Top</code>.
|
|
Once we have integrated FPP with CMake, these files will be auto-generated
|
|
by CMake and will be located at <code>Ref/build-fprime-automatic-native/F-Prime/Ref/Top</code>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Options:</strong>
|
|
When translating topologies,
|
|
the <code>-d</code>, <code>-n</code>, and <code>-p</code> options work in the same way as for
|
|
<a href="#Analyzing-and-Translating-Models_Generating-C-Plus-Plus_Constant-Definitions">translating constant definitions</a>.
|
|
The <code>-g</code> option is ignored, because
|
|
the include guard prefix comes from the name of the topology.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Analyzing-and-Translating-Models_Generating-C-Plus-Plus_Compiling-the-Generated-Code">15.2.5. Compiling the Generated Code</h4>
|
|
<div class="paragraph">
|
|
<p>The generated C++ is intended to compile with the following gcc
|
|
and clang compiler flags:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>--std=c++11
|
|
-Wall
|
|
-Wconversion
|
|
-Wdouble-promotion
|
|
-Werror
|
|
-Wextra
|
|
-Wno-unused-parameter
|
|
-Wold-style-cast
|
|
-Wshadow
|
|
-pedantic</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>When using clang, the following flags must also be set:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>-Wno-vla-extension</pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Analyzing-and-Translating-Models_Formatting-FPP-Source">15.3. Formatting FPP Source</h3>
|
|
<div class="paragraph">
|
|
<p>The tool <code>fpp-format</code> accepts FPP source files as input
|
|
and rewrites them as formatted output.
|
|
You can use this tool to put your source files into
|
|
a standard form.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For example, try this:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>% fpp-format
|
|
array A = [3] U32 default [ 1, 2, 3 ]
|
|
^D
|
|
array A = [3] U32 default [
|
|
1
|
|
2
|
|
3
|
|
]</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><code>fpp-format</code> has reformatted the default value so that each array
|
|
element is on its own line.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>By default, <code>fpp-format</code> does not resolve include specifiers.
|
|
For example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>% echo 'constant a = 0' > a.fppi
|
|
% fpp-format
|
|
include "a.fppi"
|
|
^D
|
|
include "a.fppi"</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The <code>-i</code> option causes <code>fpp-format</code> to resolve include specifiers.
|
|
For example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>% echo 'constant a = 0' > a.fpp
|
|
% fpp-format -i
|
|
include "a.fppi"
|
|
^D
|
|
constant a = 0</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><code>fpp-format</code> has one big limitation: it goes through
|
|
the FPP parser, so it deletes all
|
|
<a href="#Writing-Comments-and-Annotations_Comments">comments</a>
|
|
from the program
|
|
(<a href="#Writing-Comments-and-Annotations_Annotations">annotations</a>
|
|
are preserved).
|
|
To preserve comments on their own lines that precede
|
|
annotatable elements, you can run this script:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="bash">#!/bin/sh
|
|
sed 's/^\( *\)#/\1@ #/' | fpp-format $@ | sed 's/^\( *\)@ #/\1#/'</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>It converts comments to annotations, runs <code>fpp-format</code>, and converts the
|
|
annotations back to comments.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Analyzing-and-Translating-Models_Visualizing-Topologies">15.4. Visualizing Topologies</h3>
|
|
<div class="paragraph">
|
|
<p>FPP provides a tool called <code>fpp-to-layout</code> for generating files
|
|
that you can use to visualize topologies.
|
|
Given a topology <em>T</em>, this tool generates a directory containing
|
|
the <strong>layout input files</strong> for <em>T</em>.
|
|
There is one file for each <a href="#Defining-Topologies_Connection-Graphs">connection
|
|
graph</a> in <em>T</em>.
|
|
The files are designed to work with a tool called <code>fprime-layout</code>, which
|
|
we describe below.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Procedure:</strong>
|
|
The usual procedure for running <code>fpp-to-layout</code> is as follows:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>Identify one or more files <em>F</em> containing topology definitions
|
|
for which you wish to generate layout input files.</p>
|
|
</li>
|
|
<li>
|
|
<p><a href="#Specifying-Models-as-Files_Computing-Dependencies">Compute the dependencies</a> <em>D</em> of <em>F</em>.</p>
|
|
</li>
|
|
<li>
|
|
<p>If <em>D</em> is empty, then run <code>fpp-to-layout</code> <em>F</em>.</p>
|
|
</li>
|
|
<li>
|
|
<p>Otherwise run <code>fpp-to-layout -i</code> <em>D<sub>1</sub></em> <code>,</code> …​ <code>,</code> <em>D<sub>n</sub></em> <em>F</em>, where <em>D<sub>i</sub></em> are the
|
|
names of the dependencies.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Except for the tool name, this procedure is identical to the one given for
|
|
<a href="#Analyzing-and-Translating-Models_Generating-C-Plus-Plus">generating C++</a>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Input:</strong> You can provide input to <code>fpp-to-layout</code>
|
|
either through named files or through standard input.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Tool behavior:</strong>
|
|
For each topology <em>T</em> defined in the input files <em>F</em>, <code>fpp-to-layout</code> does
|
|
the following:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>If a directory named <em>T</em> <code>Layout</code> exists in the current directory, then
|
|
remove it.</p>
|
|
</li>
|
|
<li>
|
|
<p>Create a directory named <em>T</em> <code>Layout</code> in the current directory.</p>
|
|
</li>
|
|
<li>
|
|
<p>In the directory created in step 2, write one layout input file
|
|
for each of the connection graphs in <em>T</em>.
|
|
The
|
|
<a href="https://github.com/fprime-community/fprime-layout/wiki/Topology-Input"><code>fprime-layout</code> wiki</a>
|
|
describes the file format.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Options:</strong>
|
|
<code>fpp-to-layout</code> provides an option <code>-d</code> for selecting the current directory
|
|
to use when writing layout input files.
|
|
This option works in the same way as for
|
|
<a href="#Analyzing-and-Translating-Models_Generating-C-Plus-Plus_Constant-Definitions"><code>fpp-to-cpp</code></a>.
|
|
See the <a href="https://github.com/nasa/fpp/wiki/fpp-to-layout">FPP wiki</a> for details.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Producing visualizations:</strong>
|
|
Once you have generated layout input files, you can use a
|
|
companion tool called <code>fprime-layout</code> to read the files and produce a
|
|
<strong>topology visualization</strong>, i.e., a graphical rendering of the topology in which
|
|
the component instances are shapes, the ports are smaller shapes, and the
|
|
connections are arrows between the ports.
|
|
Topology visualization is an important part of the FPP work flow:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>It provides a graphical representation of the instances and
|
|
connections in each connection graph.
|
|
This graphical representation is a useful complement to the
|
|
textual representation provided by the FPP source.</p>
|
|
</li>
|
|
<li>
|
|
<p>It makes explicit information that is only implicit in the
|
|
FPP source, e.g., the auto-generated port numbers of the connections and
|
|
the auto-generated connections of the pattern graph specifiers.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Using <code>fprime-layout</code>, you can do the following:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>Render the connection graphs as EPS (Encapsulated PostScript),
|
|
generating one EPS file for each connection graph.</p>
|
|
</li>
|
|
<li>
|
|
<p>Generate a set of layouts, one for each layout input file,
|
|
and view the layouts in a browser.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>See the <a href="https://github.com/fprime-community/fprime-layout"><code>fprime-layout</code>
|
|
repository</a> for more details.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Analyzing-and-Translating-Models_Generating-Ground-Dictionaries">15.5. Generating Ground Dictionaries</h3>
|
|
<div class="paragraph">
|
|
<p>A <strong>ground dictionary</strong> specifies all the commands,
|
|
events, telemetry, parameters, and data products in a FSW
|
|
application.
|
|
Typically a ground data system (GDS), such as the F Prime GDS,
|
|
uses the ground dictionary to provide the operational
|
|
interface to the application.
|
|
The interface typically includes real-time commanding;
|
|
real-time display of events and telemetry; logging of
|
|
commands, events, and telemetry; uplink and downlink of files, including data
|
|
products; and decoding of data products.
|
|
This section explains how to generate ground dictionaries from
|
|
FPP models.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Tool name:</strong> The tool for generating ground dictionaries is called
|
|
<code>fpp-to-dict</code>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Procedure:</strong>
|
|
The usual procedure for running <code>fpp-to-dict</code> is as follows:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>Identify one or more files <em>F</em> that you want to translate.</p>
|
|
</li>
|
|
<li>
|
|
<p><a href="#Specifying-Models-as-Files_Computing-Dependencies">Compute the dependencies</a> <em>D</em> of <em>F</em>.</p>
|
|
</li>
|
|
<li>
|
|
<p>If <em>D</em> is empty, then run <code>fpp-to-dict</code> <em>F</em>.</p>
|
|
</li>
|
|
<li>
|
|
<p>Otherwise run <code>fpp-to-dict -i</code> <em>D<sub>1</sub></em> <code>,</code> …​ <code>,</code> <em>D<sub>n</sub></em> <em>F</em>, where <em>D<sub>i</sub></em> are the
|
|
names of the dependencies.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Except for the tool name, this procedure is identical to the one given for
|
|
<a href="#Analyzing-and-Translating-Models_Generating-C-Plus-Plus">generating C++</a>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Input:</strong> As with the tools described above, you can provide input to
|
|
<code>fpp-to-dict</code>
|
|
either through named files or through standard input.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Tool behavior:</strong>
|
|
For each topology <em>T</em> defined in the input files <em>F</em>, <code>fpp-to-dict</code> writes a
|
|
file
|
|
<em>T</em> <code>TopologyDictionary.json</code>.
|
|
The dictionary is specified in JavaScript Object Notation (JSON) format.
|
|
The JSON format is specified in the
|
|
<a href="https://fprime.jpl.nasa.gov/devel/docs/reference/fpp-json-dict/">F Prime design
|
|
documentation</a>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Here is a common use case:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>The input files <em>F</em> define a single topology <em>T</em>.
|
|
<em>T</em> describes all the component instances and connections in a FSW
|
|
application, and the generated dictionary <em>T</em> <code>TopologyDictionary.json</code>
|
|
is the dictionary for the application.</p>
|
|
</li>
|
|
<li>
|
|
<p>If <em>T</em> imports subtopologies, then those subtopologies are defined
|
|
in the dependency files <em>D</em>.
|
|
That way the subtopologies are part of the model, but no dictionaries
|
|
are generated for them.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>F Prime configuration:</strong>
|
|
When you run <code>fpp-to-dict</code> on an FPP model, the model must define the following
|
|
types:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p><code>FwChanIdType</code></p>
|
|
</li>
|
|
<li>
|
|
<p><code>FwEventIdType</code></p>
|
|
</li>
|
|
<li>
|
|
<p><code>FwOpcodeType</code></p>
|
|
</li>
|
|
<li>
|
|
<p><code>FwPacketDescriptorType</code></p>
|
|
</li>
|
|
<li>
|
|
<p><code>FwTlmPacketizeIdType</code></p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>These types are required by the F Prime GDS, so they are included in the
|
|
dictionary.
|
|
Each of these types must be an alias of an integer type.
|
|
Typically you specify these types as part of F Prime configuration,
|
|
in the file <code>config/FpConfig.fpp</code>.
|
|
See the
|
|
<a href="https://fprime.jpl.nasa.gov/devel/docs/user-manual/framework/configuring-fprime/">F
|
|
Prime documentation</a> for details.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Options:</strong>
|
|
<code>fpp-to-dict</code> provides the following options:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>The <code>-d</code> and <code>-s</code> options work in the same way as for
|
|
<a href="#Analyzing-and-Translating-Models_Generating-C-Plus-Plus_Constant-Definitions"><code>fpp-to-cpp</code></a>.</p>
|
|
</li>
|
|
<li>
|
|
<p>You can use the <code>-f</code> and <code>-p</code> options to specify a framework version
|
|
and project version for the dictionary.
|
|
That way the dictionary is stamped with information that connects
|
|
it to the FSW version for which it is intended to be used.</p>
|
|
</li>
|
|
<li>
|
|
<p>You can use the <code>-l</code> option to specify library versions used
|
|
in the project.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>See the <a href="https://github.com/nasa/fpp/wiki/fpp-to-dict">FPP wiki</a> for details.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Analyzing-and-Translating-Models_Identifying-Generated-Files">15.6. Identifying Generated Files</h3>
|
|
<div class="paragraph">
|
|
<p>As discussed in the
|
|
<a href="#Analyzing-and-Translating-Models_Generating-C-Plus-Plus">section on generating
|
|
C++</a>,
|
|
the <code>-n</code> option
|
|
of <code>fpp-to-cpp</code> lets you collect the names of
|
|
files generated from an FPP model as those files are generated.
|
|
However, sometimes you need to know the names of the generated
|
|
files up front.
|
|
For example, the CMake build tool writes out a Makefile rule
|
|
for every generated file, and it does this as an initial step
|
|
before generating any files.
|
|
There are two ways to collect the names of generated files:
|
|
using <code>fpp-filenames</code> and using <code>fpp-depend</code>.</p>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Analyzing-and-Translating-Models_Identifying-Generated-Files_Using-fpp-filenames">15.6.1. Using fpp-filenames</h4>
|
|
<div class="paragraph">
|
|
<p>Like <code>fpp-check</code>, <code>fpp-filenames</code> reads the files
|
|
provided as command-line arguments if there are any;
|
|
otherwise it reads from standard input.
|
|
The FPP source presented to <code>fpp-filenames</code> need not be a complete
|
|
model (i.e., it may contain undefined symbols).
|
|
When run with no options, tool parses the FPP source that you give it.
|
|
It identifies all definitions in the source that would cause
|
|
C++ files to be generated when running
|
|
<code>fpp-to-cpp</code> or <code>fpp-to-dict</code>.
|
|
Then it writes the names of those files to standard output.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>% fpp-filenames
|
|
array A = [3] U32
|
|
^D
|
|
AArrayAc.cpp
|
|
AArrayAc.hpp</pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>% fpp-filenames
|
|
constant a = 0
|
|
^D
|
|
FppConstantsAc.cpp
|
|
FppConstantsAc.hpp</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>You can run <code>fpp-filenames</code> with the <code>-u</code> option, with the <code>-t</code> option,
|
|
or with both options.
|
|
In these cases <code>fpp-filenames</code> writes out the names of
|
|
the files that would be generated by running <code>fpp-to-cpp</code> with the
|
|
corresponding options.
|
|
For example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>% fpp-filenames -t
|
|
array A = [3] U32
|
|
passive component C {}
|
|
^D
|
|
C.template.cpp
|
|
C.template.hpp</pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>% fpp-filenames -u
|
|
array A = [3] U32
|
|
passive component C {}
|
|
^D
|
|
array A = [3] U32
|
|
passive component C {}
|
|
AArrayAc.cpp
|
|
AArrayAc.hpp
|
|
CComponentAc.cpp
|
|
CComponentAc.hpp
|
|
CGTestBase.cpp
|
|
CGTestBase.hpp
|
|
CTesterBase.cpp
|
|
CTesterBase.hpp</pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>% fpp-filenames -u -t
|
|
array A = [3] U32
|
|
passive component C {}
|
|
^D
|
|
CTestMain.cpp
|
|
CTester.cpp
|
|
CTester.hpp
|
|
CTesterHelpers.cpp</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>You can also also run <code>fpp-filenames</code> with the <code>-a</code> option.
|
|
Again the results correspond to running <code>fpp-to-cpp</code> with this option.
|
|
For example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>% fpp-filenames -a -u -t
|
|
array A = [3] U32
|
|
passive component C {}
|
|
^D
|
|
CTestMain.cpp
|
|
CTester.cpp
|
|
CTester.hpp</pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Analyzing-and-Translating-Models_Identifying-Generated-Files_Using-fpp-depend">15.6.2. Using fpp-depend</h4>
|
|
<div class="paragraph">
|
|
<p>Alternatively, you can use
|
|
<a href="#Specifying-Models-as-Files_Computing-Dependencies"><code>fpp-depend</code></a>
|
|
to write out the names of generated files during dependency analysis.
|
|
The output is the same as for <code>fpp-filenames</code>, but this way you can
|
|
run one tool (<code>fpp-depend</code>) instead of two (<code>fpp-depend</code> and
|
|
<code>fpp-filenames</code>).
|
|
Running one tool may help your build go faster.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>To write out the names of generated files, you can use the following
|
|
options provided by <code>fpp-depend</code>:</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><code>-a</code>: Report the generation of files with
|
|
<a href="#Analyzing-and-Translating-Models_Generating-C-Plus-Plus_Component-Implementation-and-Unit-Test-Code">unit
|
|
test auto helpers enabled</a>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><code>-g</code> <em>file</em>: Write the names of the generated autocode files
|
|
to the file <em>file</em>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><code>-u</code> <em>file</em>: Write the names of the unit test support code
|
|
files to <em>file</em>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>% fpp-depend -g generated.txt -u ut-generated.txt
|
|
array A = [3] U32
|
|
passive component C {}
|
|
^D
|
|
% cat generated.txt
|
|
AArrayAc.cpp
|
|
AArrayAc.hpp
|
|
CComponentAc.cpp
|
|
CComponentAc.hpp
|
|
% cat ut-generated.txt
|
|
CGTestBase.cpp
|
|
CGTestBase.hpp
|
|
CTesterBase.cpp
|
|
CTesterBase.hpp</pre>
|
|
</div>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>% fpp-depend -a -g generated.txt -u ut-generated.txt
|
|
array A = [3] U32
|
|
passive component C {}
|
|
^D
|
|
% cat generated.txt
|
|
AArrayAc.cpp
|
|
AArrayAc.hpp
|
|
CComponentAc.cpp
|
|
CComponentAc.hpp
|
|
% cat ut-generated.txt
|
|
CGTestBase.cpp
|
|
CGTestBase.hpp
|
|
CTesterBase.cpp
|
|
CTesterBase.hpp
|
|
CTesterHelpers.cpp</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><code>fpp-depend</code> does not have an option for writing out the names of
|
|
implementation template files, since those file names are not
|
|
needed during dependency analysis.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Analyzing-and-Translating-Models_Generating-JSON-Models">15.7. Generating JSON Models</h3>
|
|
<div class="paragraph">
|
|
<p>FPP provides a tool called <code>fpp-to-json</code> for converting FPP models to
|
|
JavaScript Object Notation (JSON) format.
|
|
Using this tool, you can import FPP models into programs written
|
|
in any language that has a library for reading JSON, e.g., JavaScript,
|
|
TypeScript, or Python.
|
|
Generating and importing JSON may be convenient if you need to develop
|
|
a simple analysis or translation tool for FPP models, and you don’t
|
|
want to develop the tool in Scala.
|
|
For more complex tools, we recommend that you develop in Scala
|
|
against the FPP compiler data structures.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Procedure:</strong>
|
|
The usual procedure for running <code>fpp-to-json</code> is as follows:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>Identify one or more files <em>F</em> that you want to analyze.</p>
|
|
</li>
|
|
<li>
|
|
<p><a href="#Specifying-Models-as-Files_Computing-Dependencies">Compute the dependencies</a> <em>D</em> of <em>F</em>.</p>
|
|
</li>
|
|
<li>
|
|
<p>Run <code>fpp-to-json</code> <em>D</em> <em>F</em>. Note that <em>D</em> may be empty.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>If you are using <code>fpp-to-json</code> with the <code>-s</code> option (see below),
|
|
then you can run <code>fpp-to-json</code> <em>F</em>, without computing dependencies.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Tool behavior:</strong> When you run <code>fpp-to-json</code>, the tool checks the
|
|
syntax and semantics of the source model, reporting any errors that occur.
|
|
If everything checks out, it generates three files:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p><code>fpp-ast.json</code>: The abstract syntax tree (AST).
|
|
This is a tree data structure that represents the source syntax.
|
|
It contains AST nodes, each of which has a unique identifier.</p>
|
|
</li>
|
|
<li>
|
|
<p><code>fpp-loc-map.json</code>: The location map.
|
|
This object is a map from AST node IDs to the source
|
|
locations (file, line number, and column number)
|
|
of the corresponding AST nodes.</p>
|
|
</li>
|
|
<li>
|
|
<p><code>fpp-analysis.json</code>: The Analysis data structure.
|
|
This object contains semantic information
|
|
inferred from the source model, e.g., the types of all the
|
|
expressions and the constant values of all the numeric
|
|
expressions.
|
|
Only output data is included in the JSON; temporary
|
|
data structures used during the analysis algorithm are
|
|
omitted.
|
|
For more information on the Analysis data structure,
|
|
see the
|
|
<a href="https://github.com/nasa/fpp/wiki/Analysis-Data-Structure">FPP wiki</a>.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>JSON format:</strong>
|
|
To understand this subsection, you need to know a little
|
|
bit about case classes in Scala.
|
|
For a primer, see
|
|
<a href="https://github.com/nasa/fpp/wiki/Pure-Functional-Programming-in-Scala#use-case-classes-for-pattern-matching">this wiki page</a>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The JSON translation uses a Scala library called
|
|
<a href="https://circe.github.io/circe/">Circe</a>.
|
|
In general the translation follows a set of standard rules, so the
|
|
output format can be easily inferred from the types of the data structures
|
|
in the FPP source code:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>A Scala case class <code>C</code> is translated as follows, unless
|
|
it extends a sealed trait (see below).
|
|
A value <code>v</code> of type <code>C</code> becomes
|
|
a JSON dictionary with the field names as keys and the field
|
|
values as their values.
|
|
For example a value <code>C(1,"hello")</code> of type <code>case class C(n: Int, s: String)</code>
|
|
becomes a JSON value <code>{ "n": 1, "s": "String" }</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>A Scala case class <code>C</code> that extends a sealed trait <code>T</code> represents a
|
|
named variant of type <code>T</code>.
|
|
In this case a value <code>v</code> of type <code>C</code> is wrapped in a dictionary with one
|
|
key (the variant name <code>C</code>) and one value (the value <code>v</code>).
|
|
For example, a value <code>C(1)</code> of type <code>case class C(n: Int) extends T</code>
|
|
becomes a JSON value <code>{ "C" : { "n" : 1 } }</code>, while a value
|
|
<code>D("hello")</code> of type <code>case class D(s: String) extends T</code>
|
|
becomes a JSON value <code>{ "D" : { "s" : "hello" } }</code>.
|
|
In this way each variant is labeled with the variant name.</p>
|
|
</li>
|
|
<li>
|
|
<p>A Scala list becomes a JSON array, and a Scala map becomes
|
|
a JSON dictionary.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>There are a few exceptions, either because the standard translation
|
|
does not work, or because we need special behavior for important
|
|
cases:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>We streamline the translation of the Scala Option type, translating
|
|
<code>Some(v)</code> as <code>{ "Some" : v }</code> and <code>None</code> as <code>"None"</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>In the AST, we translate
|
|
the type AstNode as if it were a variant type, i.e., we translate
|
|
<code>AstNode([data], [id])</code> to <code>"AstNode" : { "data" : [data], "id" : [id] } }</code>.
|
|
The <code>AstNode</code> keys identify the AstNode objects.</p>
|
|
</li>
|
|
<li>
|
|
<p>In the AST, to reduce clutter we skip over the <code>node</code>
|
|
field of module, component, and topology member lists.
|
|
This field is an artifact of the way the Scala code is written;
|
|
deleting it does not lose information.</p>
|
|
</li>
|
|
<li>
|
|
<p>In the Analysis data structure, to avoid repetition,
|
|
we translate AstNode values as <code>{ "astNodeId" : [node id] }</code>,
|
|
eliminating the data field of the node.
|
|
We also omit annotations from annotated AST nodes.
|
|
The data fields and the annotations can be looked up in the AST,
|
|
by searching for the node ID.</p>
|
|
</li>
|
|
<li>
|
|
<p>When translating an FPP symbol (i.e., a reference to a definition),
|
|
we provide the information in the
|
|
Symbol trait (the node ID and the unqualified name).
|
|
All symbols extend this trait.
|
|
We omit the AST node information stored in the concrete symbol.
|
|
This information can be looked up with the AST node ID.</p>
|
|
</li>
|
|
<li>
|
|
<p>When translating a component instance value, we replace
|
|
the component stored in the value with the corresponding
|
|
AST node ID.</p>
|
|
</li>
|
|
<li>
|
|
<p>When the keys of a Scala map cannot easily be
|
|
converted to strings, we convert the map to a list
|
|
of pairs, represented as an array of JSON arrays.
|
|
For example, this is how we translate the PortNumberMap
|
|
in the Analysis data structure, which maps Connection objects to integers.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Options:</strong> The following options are available
|
|
when running <code>fpp-to-json</code>:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p><code>-d</code> <em>dir</em> : Similar to the corresponding option of
|
|
<a href="#Analyzing-and-Translating-Models_Generating-C-Plus-Plus"><code>fpp-to-cpp</code></a>.</p>
|
|
</li>
|
|
<li>
|
|
<p><code>-s</code>: Analyze syntax only:
|
|
With this option, <code>fpp-to-json</code> generates the AST and the
|
|
location map only; it doesn’t generate the Analysis data structure.
|
|
Because semantic analysis is not run, you don’t have to present
|
|
a complete or semantically correct FPP model to the tool.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Analyzing-and-Translating-Models_Translating-Older-XML-to-FPP">15.8. Translating Older XML to FPP</h3>
|
|
<div class="paragraph">
|
|
<p>Previous versions of F Prime used XML to represent model
|
|
elements such as components and ports.
|
|
The FPP tool suite provides a capability to translate this
|
|
older format to FPP.
|
|
Its purpose is to address the following case:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>You have an older F Prime model that was developed in XML.</p>
|
|
</li>
|
|
<li>
|
|
<p>You wish to translate the model to FPP in order to use FPP as the source
|
|
language going forward.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The XML-to-FPP translation is designed to do most of the work in translating an
|
|
XML model into FPP.
|
|
As discussed below, some manual effort will still be required,
|
|
because the FPP and XML representations are not identical.
|
|
The good news is that this is a one-time effort: you can do it once
|
|
and use the FPP version thereafter.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Tool name:</strong> The tool for translating XML to FPP is called
|
|
<code>fpp-from-xml</code>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Tool behavior:</strong>
|
|
Unlike the tools described above, <code>fpp-from-xml</code> does not read
|
|
from standard input.
|
|
To use it, you must name one or more XML files on the command line.
|
|
The reason is that the XML parsing library used by the tool requires
|
|
named files.
|
|
The tool reads the XML files you name, translates them, and
|
|
writes the result to standard output.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>As an example, try this:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>% cat > SSerializable.xml
|
|
<serializable name="S">
|
|
<members>
|
|
<member name="x" type="U32">
|
|
</member>
|
|
<member name="y" type="F32">
|
|
</member>
|
|
</members>
|
|
</serializable>
|
|
^D
|
|
% fpp-from-xml SSerializableAi.xml
|
|
struct S {
|
|
x: U32
|
|
y: F32
|
|
}</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>(The formula <code>cat ></code> <em>file</em> lets us enter input to
|
|
the console and have it written to <em>file</em>.)</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Default values:</strong>
|
|
There are two issues to note in connection with translating default
|
|
values.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>First, in FPP, every definition has a default value, but
|
|
the default value need not be given explicitly:
|
|
if you provide no explicit default value, then an implicit default is used.
|
|
By contrast, in F Prime XML, (1) you <em>must</em> supply default values for array
|
|
elements, and (2) you <em>may</em> supply default values for struct members
|
|
or enumerations.
|
|
To keep the translation simple, if default values are present in the XML
|
|
representation, then <code>fpp-from-xml</code> translates them to explicit values,
|
|
even if they could be made implicit.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Here is an example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>% cat > AArrayAi.xml
|
|
<array name="A">
|
|
<type>U32</type>
|
|
<size>3</size>
|
|
<format>%u</format>
|
|
<default>
|
|
<value>0</value>
|
|
<value>0</value>
|
|
<value>0</value>
|
|
</default>
|
|
</array>
|
|
^D
|
|
% fpp-from-xml AArrayAi.xml
|
|
array A = [3] U32 default [
|
|
0
|
|
0
|
|
0
|
|
]</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Notice that the implicit default value <code>[ 0, 0, 0 ]</code> becomes
|
|
explicit when translating to XML and back to FPP.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Second, to keep the translation simple, only literal numeric values,
|
|
literal string values, literal Boolean values, and C++ qualified identifiers
|
|
(e.g., <code>a</code> or <code>A::B</code>) are translated.
|
|
Other values (e.g., values specified with C++ constructor calls), are not translated.
|
|
The reason is that the types of these values cannot be easily inferred from the
|
|
XML representation.
|
|
When a default value is not translated, the translator inserts an annotation
|
|
identifying what was not translated, so that you can do the translation
|
|
yourself.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For example, try this:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>% cat > AArrayAi.xml
|
|
<array name="A">
|
|
<include_header>T.hpp</include_header>
|
|
<type>T</type>
|
|
<size>3</size>
|
|
<format>%s</format>
|
|
<default>
|
|
<value>T()</value>
|
|
<value>T()</value>
|
|
<value>T()</value>
|
|
</default>
|
|
</array>
|
|
^D
|
|
% fpp-from-xml AArrayAi.xml
|
|
@ FPP from XML: could not translate array value [ T(), T(), T() ]
|
|
array A = [3] T</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The tool cannot translate the value <code>T()</code>.
|
|
So it adds an annotation stating that.
|
|
In this case, <code>T()</code> is the default value associated with the
|
|
abstract type <code>T</code>, so using the implicit default is correct.
|
|
So in this case, just delete the annotation.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Here is another example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>% cat > BArrayAi.xml
|
|
<array name="B">
|
|
<import_array_type>AArrayAi.xml</import_array_type>
|
|
<type>A</type>
|
|
<size>2</size>
|
|
<format>%s</format>
|
|
<default>
|
|
<value>A(1, 2)</value>
|
|
<value>A(3, 4)</value>
|
|
</default>
|
|
</array>
|
|
^D
|
|
% fpp-from-xml BArrayAi.xml
|
|
@ FPP from XML: could not translate array value [ A(1, 2), A(3, 4) ]
|
|
array B = [2] A</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Here the XML representation of the array values <code>[ 1, 2 ]</code> and <code>[ 3, 4 ]</code>
|
|
uses the C++ constructor calls <code>A(1, 2)</code> and <code>A(3, 4)</code>.
|
|
When translating <code>BArrayAi.xml</code>, <code>fpp-from-xml</code> doesn’t know how to translate
|
|
those values, because it doesn’t have any information about the type <code>A</code>.
|
|
So it omits the FPP default array value and reports the XML default element
|
|
values in the annotation.
|
|
That way, you can manually construct a default value in FPP.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Inline enum definitions:</strong>
|
|
The following F Prime XML formats may include inline
|
|
enum definitions:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>In the Serializable XML format,
|
|
enumerations may appear as member types.</p>
|
|
</li>
|
|
<li>
|
|
<p>In the Port XML format, enumerations may appear
|
|
as the types of arguments or as the return type.</p>
|
|
</li>
|
|
<li>
|
|
<p>In the XML formats for commands and for events,
|
|
enumerations may appear as the types of arguments.</p>
|
|
</li>
|
|
<li>
|
|
<p>In the XML formats for telemetry channels and for
|
|
parameters, enumerations may appear as the types of
|
|
data elements.</p>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In each case, the enumerated constants are specified
|
|
as part of the definition of the member, argument, return type, etc.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>FPP does not represent these inline enum definitions directly.
|
|
In FPP, enum definitions are always named, so they can be reused.
|
|
Therefore, when translating an F Prime XML file that contains inline enum
|
|
definitions, <code>fpp-from-xml</code> does the following: (1) translate
|
|
each inline definition to a named FPP enum; and (2) use the corresponding named
|
|
types in the translated FPP struct or port.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For example, here is an F Prime Serializable XML type
|
|
<code>N::S1</code> containing a member <code>m</code> whose type is an enum
|
|
<code>E</code> with three enumerated constants <code>A</code>, <code>B</code>, and <code>C</code>:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>cat > S1SerializableAi.xml
|
|
<serializable namespace="N" name="S1">
|
|
<members>
|
|
<member name="m" type="ENUM">
|
|
<enum name="E">
|
|
<item name="A"/>
|
|
<item name="B"/>
|
|
<item name="C"/>
|
|
</enum>
|
|
</member>
|
|
</members>
|
|
</serializable>
|
|
^D</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Running <code>fpp-from-xml</code> on this file yields the following:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>% fpp-from-xml S1SerializableAi.xml
|
|
module N {
|
|
|
|
enum E {
|
|
A = 0
|
|
B = 1
|
|
C = 2
|
|
}
|
|
|
|
struct S1 {
|
|
m: E
|
|
}
|
|
|
|
}</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Notice the following:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>The tool translates namespace <code>N</code> in XML to module <code>N</code> in FPP.</p>
|
|
</li>
|
|
<li>
|
|
<p>The tool translates Serializable type <code>S1</code> in namespace <code>N</code>
|
|
to struct type <code>S1</code> in module <code>N</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>The tool generates an enum type <code>N.E</code> to represent the
|
|
type of member <code>m</code> of struct <code>N.S1</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>The tool assigns member <code>m</code> of struct <code>N.S1</code> the type <code>N.E</code>.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Format strings:</strong>
|
|
<code>fpp-from-xml</code> translates XML format strings to FPP
|
|
format strings, if it can.
|
|
Here is an example:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>% cat > AArrayAi.xml
|
|
<array name="A">
|
|
<type>F32</type>
|
|
<size>3</size>
|
|
<format>%f</format>
|
|
<default>
|
|
<value>0.0f</value>
|
|
<value>0.0f</value>
|
|
<value>0.0f</value>
|
|
</default>
|
|
</array>
|
|
^D</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Notice that this code contains the line</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre><format>%f</format></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>which is the XML representation of the format.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Now try this:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>% fpp-from-xml AArrayAi.xml
|
|
array A = [3] F32 default [
|
|
0.0
|
|
0.0
|
|
0.0
|
|
] format "{f}"</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The XML format <code>%f</code> is translated back to the FPP format <code>{f}</code>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>If the tool cannot translate the format, it will insert an annotation
|
|
stating that. For example, <code>%q</code> is not a format recognized by
|
|
FPP, so a format containing this string won’t be translated:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>% cat > AArrayAi.xml
|
|
<array name="A">
|
|
<type>F32</type>
|
|
<size>1</size>
|
|
<format>%q</format>
|
|
<default>
|
|
<value>0.0</value>
|
|
</default>
|
|
</array>
|
|
^D
|
|
% fpp-from-xml AArrayAi.xml
|
|
@ FPP from XML: could not translate format string "%q"
|
|
array A = [1] F32 default [
|
|
0.0
|
|
]</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Import directives:</strong>
|
|
XML directives that import symbols (such as <code>import_port_type</code>)
|
|
are ignored in the translation.
|
|
These directives represent dependencies between XML files, which
|
|
become dependencies between FPP source files in the FPP translation.
|
|
Once the XML-to-FPP translation is done, you can handle these
|
|
dependencies in the ordinary way for FPP, as discussed in the
|
|
section on <a href="#Specifying-Models-as-Files">specifying models as files</a>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>XML directives that import XML dictionaries are translated
|
|
to
|
|
<a href="#Specifying-Models-as-Files_Include-Specifiers">include specifiers</a>.
|
|
For example, suppose that <code>CComponentAi.xml</code> defines component <code>C</code>
|
|
and contains the directive</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="xml"><import_dictionary>Commands.xml</import_dictionary></code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Running <code>fpp-from-xml</code> on <code>CComponentAi.xml</code> produces an
|
|
FPP definition of a component <code>C</code>; the component definition
|
|
contains the include specifier</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">include "Commands.fppi"</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Separately, you can use <code>fpp-from-xml</code> to translate <code>Commands.xml</code>
|
|
to <code>Commands.fppi</code>.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect1">
|
|
<h2 id="Writing-C-Plus-Plus-Implementations">16. Writing C Plus Plus Implementations</h2>
|
|
<div class="sectionbody">
|
|
<div class="paragraph">
|
|
<p>When constructing an F Prime deployment in C++, there are generally
|
|
five kinds of implementations you have to write:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>Implementations of
|
|
<a href="#Defining-Types_Abstract-Type-Definitions">abstract types</a>.
|
|
These are types that are named in the FPP model but are defined
|
|
directly in C++.</p>
|
|
</li>
|
|
<li>
|
|
<p>Implementations of <a href="#Defining-State-Machines_Writing-a-State-Machine-Definition">external state machines</a>.</p>
|
|
</li>
|
|
<li>
|
|
<p>Implementations of
|
|
<a href="#Defining-Components">components</a>.</p>
|
|
</li>
|
|
<li>
|
|
<p>Implementations of any libraries used by the component implementations,
|
|
e.g., algorithm libraries or hardware device driver libraries.</p>
|
|
</li>
|
|
<li>
|
|
<p>A top-level implementation including a <code>main</code> function for running
|
|
the FSW application.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Implementing a component (item 3) involves filling out the API provided by
|
|
the C++ component base class.
|
|
This process is covered in detail in the F Prime user’s guide;
|
|
we won’t cover it further here.
|
|
Similarly, implementing libraries (item 4) is unrelated to FPP, so we
|
|
won’t cover it in this manual.
|
|
Here we focus on items 1, 2, and 5: implementing abstract types,
|
|
implementing external state machines, and implementing deployments.
|
|
We also discuss <strong>serialization</strong> of data values, i.e., representing
|
|
FPP data values as binary data for storage and transmission.</p>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Writing-C-Plus-Plus-Implementations_Implementing-Abstract-Types">16.1. Implementing Abstract Types</h3>
|
|
<div class="paragraph">
|
|
<p>When translating to C++, an
|
|
<a href="#Defining-Types_Abstract-Type-Definitions">abstract type definition</a>
|
|
represents a C++ class that you write directly in C++.
|
|
When you use an abstract type <em>T</em> in an FPP definition <em>D</em> (for example, as the
|
|
member type of an array definition)
|
|
and you translate <em>D</em> to C++, then the generated C++ for <em>D</em> contains an
|
|
<code>include</code> directive that includes a header file for <em>T</em>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>As an example, try this:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>% fpp-to-cpp -p $PWD
|
|
type T
|
|
array A = [3] T
|
|
^D</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Notice that we used the option <code>-p $PWD</code>.
|
|
This is to make the generated include path relative to the current directory.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Now run</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>% cat AArrayAc.hpp</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>You should see the following line in the generated C++:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="cpp">#include "T.hpp"</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>This line says that in order to compile <code>AArrayAc.cpp</code>,
|
|
a header file <code>T.hpp</code> must exist in the current directory.
|
|
It is up to you to provide that header file.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>General implementations:</strong>
|
|
In most cases, when implementing an abstract type <code>T</code> in C++, you
|
|
will define
|
|
a class that extends <code>Fw::Serializable</code> from the F Prime framework.
|
|
Your class definition should include the following:</p>
|
|
</div>
|
|
<div class="ulist">
|
|
<ul>
|
|
<li>
|
|
<p>An implementation of the virtual function</p>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>Fw::SerializeStatus T::serializeTo(
|
|
Fw::LinearBufferBase&,
|
|
Fw::Endianness = Fw::Endianness::BIG
|
|
) const</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>that specifies how to <strong>serialize</strong> a class instance to a buffer
|
|
(i.e., convert a class instance to a byte string stored in a buffer).</p>
|
|
</div>
|
|
</li>
|
|
<li>
|
|
<p>An implementation of the function</p>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>Fw::SerializeStatus T::deserializeFrom(
|
|
Fw::LinearBufferBase&,
|
|
Fw::Endianness = Fw::Endianness::BIG
|
|
)</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>that specifies how to <strong>deserialize</strong> a class instance from a
|
|
buffer (i.e., reconstruct a class instance from a byte string stored in a
|
|
buffer).</p>
|
|
</div>
|
|
</li>
|
|
<li>
|
|
<p>A constant <code>T::SERIALIZED_SIZE</code> that specifies the size in bytes
|
|
of a byte string serialized from the class.</p>
|
|
</li>
|
|
<li>
|
|
<p>A zero-argument constructor <code>T()</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>An overloaded equality operator</p>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>bool operator==(const T& that) const;</pre>
|
|
</div>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For more on serialization, see the section on
|
|
<a href="#Writing-C-Plus-Plus-Implementations_Serialization-of-FPP-Values">serialization of FPP values</a>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>Here is a minimal complete implementation of an abstract type <code>T</code>.
|
|
It has one member variable <code>x</code> of type <code>U32</code> and no methods other than
|
|
those required by F Prime.
|
|
We have made <code>T</code> a C++ struct (rather than a class) so that
|
|
all members are public by default.
|
|
To implement <code>serializeTo</code>, we use the <code>serializeFrom</code> function
|
|
provided by <code>Fw::LinearBufferBase</code>.</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre>// A minimal implementation of abstract type T
|
|
|
|
#ifndef T_HPP
|
|
#define T_HPP
|
|
|
|
// Include Fw/Types/Serializable.hpp from the F Prime framework
|
|
#include "Fw/Types/Serializable.hpp"
|
|
|
|
struct T final : public Fw::Serializable { // Extend Fw::Serializable
|
|
|
|
// Define some shorthand for F Prime types
|
|
using SS = Fw::SerializeStatus SS;
|
|
using B = Fw::LinearBufferBase B;
|
|
using E = Fw::Endianness E;
|
|
|
|
// Define the constant SERIALIZED_SIZE
|
|
enum Constants { SERIALIZED_SIZE = sizeof(U32) };
|
|
|
|
// Provide a zero-argument constructor
|
|
T() : x(0) { }
|
|
|
|
// Define a comparison operator
|
|
bool operator==(const T& that) const { return this->x == that.x; }
|
|
|
|
// Define the virtual serializeTo method
|
|
SS serializeTo(B& b, E e) const final { return b.serializeFrom(x, e); }
|
|
|
|
// Define the virtual deserializeFrom method
|
|
SS deserializeFrom(B& b, E e) final { return b.deserializeTo(x, e); }
|
|
|
|
// Provide some data
|
|
U32 x;
|
|
|
|
};
|
|
|
|
#endif</pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Serializable buffers used in ports:</strong>
|
|
In some cases, you may want to define an abstract type <code>T</code> that represents
|
|
a data buffer and that is used only in <a href="#Defining-Ports">port definitions</a>.
|
|
In this case you can implement
|
|
<code>T</code> as a class that extends <code>Fw::LinearBufferBase</code>.
|
|
Instead of implementing the <code>serializeTo</code> and <code>deserializeFrom</code> functions
|
|
directly, you override functions that get the address and the capacity
|
|
(allocated size) of the buffer; the base class <code>Fw::LinearBufferBase</code>
|
|
uses these functions to implement <code>serializeTo</code> and <code>deserializeFrom</code>.
|
|
For an example of how to do this, see the files <code>Fw/Cmd/CmdArgBuffer.hpp</code>
|
|
and <code>Fw/Cmd/CmdArgBuffer.cpp</code> in the F Prime repository.
|
|
Be careful, though: if you implement an abstract type <code>T</code> this way
|
|
and you try to use the type <code>T</code> outside of a port definition,
|
|
the generated C++ may not compile.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Writing-C-Plus-Plus-Implementations_Implementing-External-State-Machines">16.2. Implementing External State Machines</h3>
|
|
<div class="paragraph">
|
|
<p>An <a href="#Defining-State-Machines_Writing-a-State-Machine-Definition">external state machine</a> refers to a state machine implementation
|
|
supplied outside the FPP model.
|
|
To implement an external state machine, you can use
|
|
the <a href="https://github.com/JPLOpenSource/STARS/tree/main">State Autocoding for
|
|
Real-Time Systems (STARS)</a>
|
|
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.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For an example of an external state machine implemented in STARS,
|
|
see <code>FppTest/state_machine</code> in the F Prime repository.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Writing-C-Plus-Plus-Implementations_Implementing-Deployments">16.3. Implementing Deployments</h3>
|
|
<div class="paragraph">
|
|
<p>At the highest level of an F Prime implementation, you write
|
|
two units of C++ code:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>Application-specific definitions visible
|
|
both to the <code>main</code> function and to the auto-generated
|
|
topology code.</p>
|
|
</li>
|
|
<li>
|
|
<p>The <code>main</code> function.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>We describe each of these code units below.</p>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Writing-C-Plus-Plus-Implementations_Implementing-Deployments_Application-Specific-Definitions">16.3.1. Application-Specific Definitions</h4>
|
|
<div class="paragraph">
|
|
<p>As discussed in the section on
|
|
<a href="#Analyzing-and-Translating-Models_Generating-C-Plus-Plus_Topology-Definitions">generating C++ topology definitions</a>, when you translate an FPP
|
|
topology <em>T</em> to C++, the result goes into files
|
|
<em>T</em> <code>TopologyAc.hpp</code> and <em>T</em> <code>TopologyAc.cpp</code>.
|
|
The generated file <em>T</em> <code>TopologyAc.hpp</code> includes a file
|
|
<em>T</em> <code>TopologyDefs.hpp</code>.
|
|
The purpose of this file inclusion is as follows:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p><em>T</em> <code>TopologyDefs.hpp</code> is not auto-generated.
|
|
You must write it by hand as part of your C++ implementation.</p>
|
|
</li>
|
|
<li>
|
|
<p>Because <em>T</em> <code>TopologyAc.cpp</code> includes <em>T</em> <code>TopologyAc.hpp</code>
|
|
and <em>T</em> <code>TopologyAc.hpp</code> includes <em>T</em> <code>TopologyDefs.hpp</code>,
|
|
the handwritten definitions in <em>T</em> <code>TopologyDefs.hpp</code> are visible
|
|
to the auto-generated code in <em>T</em> <code>TopologyAc.hpp</code> and
|
|
<code>TopologyAc.cpp</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>You can also include <em>T</em> <code>TopologyDefs.hpp</code> in your main
|
|
function (described in the next section) to make its
|
|
definitions visible there.
|
|
That way <code>main</code> and the auto-generated topology
|
|
code can share these custom definitions.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><em>T</em> <code>TopologyDefs.hpp</code>
|
|
must be located in the same directory where the topology <em>T</em> is defined.
|
|
When writing the file <em>T</em> <code>TopologyDefs.hpp</code>, you should
|
|
follow the description given below.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Topology state:</strong>
|
|
<em>T</em> <code>TopologyDefs.hpp</code> must define a type
|
|
<code>TopologyState</code> in the C++ namespace
|
|
corresponding to the FPP module where the topology <em>T</em> is defined.
|
|
For example, in <code>SystemReference/Top/topology.fpp</code> in the
|
|
<a href="https://github.com/fprime-community/fprime-system-reference/blob/main/SystemReference/Top/topology.fpp">F Prime system reference deployment</a>, the FPP topology <code>SystemReference</code> is defined in the FPP
|
|
module <code>SystemReference</code>, and so in
|
|
<a href="https://github.com/fprime-community/fprime-system-reference/blob/main/SystemReference/Top/SystemReferenceTopologyDefs.hpp"><code>SystemReference/Top/SystemReferenceTopologyDefs.hpp</code></a>, the type <code>TopologyState</code>
|
|
is defined in the namespace <code>SystemReference</code>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><code>TopologyState</code> may be any type.
|
|
Usually it is a struct or class.
|
|
The C++ code generated by FPP passes a value <code>state</code> of type <code>TopologyState</code> into
|
|
each of the functions for setting up and tearing down topologies.
|
|
You can read this value in the code associated with your
|
|
<a href="#Defining-Component-Instances_Init-Specifiers">init specifiers</a>.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In the F Prime system reference example, <code>TopologyState</code>
|
|
is a struct with two member variables: a C-style string
|
|
<code>hostName</code> that stores a host name and a <code>U32</code> value <code>portNumber</code>
|
|
that stores a port number.
|
|
The main function defined in <code>Main.cpp</code> parses the command-line
|
|
arguments to the application, uses the result to create an object
|
|
<code>state</code> of type <code>TopologyState</code>, and passes the <code>state</code> object
|
|
into the functions for setting up and tearing down the topology.
|
|
The <code>startTasks</code> phase for the <code>comDriver</code> instance uses the <code>state</code>
|
|
object in the following way:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="fpp">phase Fpp.ToCpp.Phases.startTasks """
|
|
// Initialize socket server if and only if there is a valid specification
|
|
if (state.hostName != nullptr && state.portNumber != 0) {
|
|
Os::TaskString name("ReceiveTask");
|
|
// Uplink is configured for receive so a socket task is started
|
|
comDriver.configure(state.hostName, state.portNumber);
|
|
comDriver.startSocketTask(
|
|
name,
|
|
true,
|
|
ConfigConstants::SystemReference_comDriver::PRIORITY,
|
|
ConfigConstants::SystemReference_comDriver::STACK_SIZE
|
|
);
|
|
}
|
|
"""</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>In this code snippet, the expressions <code>state.hostName</code> and <code>state.portNumber</code>
|
|
refer to the <code>hostName</code> and <code>portNumber</code> member variables of the
|
|
state object passed in from the main function.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The <code>state</code> object is passed in to the setup and teardown functions
|
|
via <code>const</code> reference.
|
|
Therefore, you may read, but not write, the <code>state</code> object in the
|
|
code associated with the init specifiers.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Health ping entries:</strong>
|
|
If your topology uses an instance of the standard component <code>Svc::Health</code> for
|
|
monitoring
|
|
the health of components with threads, then <em>T</em> <code>TopologyDefs.hpp</code>
|
|
must define the <strong>health ping entries</strong> used by the health component instance.
|
|
The health ping entries specify the time in seconds to wait for the
|
|
receipt of a health ping before declaring a timeout.
|
|
For each component being monitored, there are two timeout intervals:
|
|
a warning interval and a fatal interval.
|
|
If the warning interval passes without a health ping, then a warning event occurs.
|
|
If the fatal interval passes without a health ping, then a fatal event occurs.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>You must specify the health ping entries in the namespace corresponding
|
|
to the FPP module where <em>T</em> is defined.
|
|
To specify the health ping entries, you do the following:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>Open a namespace <code>PingEntries</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>In that namespace, open a namespace corresponding to the name
|
|
of each component instance with health ping ports.</p>
|
|
</li>
|
|
<li>
|
|
<p>Inside namespace in item 2, define a C++ enumeration with
|
|
the following constants <code>WARN</code> and <code>FATAL</code>.
|
|
Set <code>WARN</code> equal to the warning interval for the enclosing
|
|
component instance.
|
|
Set <code>FATAL</code> equal to the fatal interval.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For example, here are the health ping entries from
|
|
<code>SystemReference/Top/SystemReferenceTopologyDefs.hpp</code>
|
|
in the F Prime system reference repository:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="cpp">namespace SystemReference {
|
|
|
|
...
|
|
|
|
// Health ping entries
|
|
namespace PingEntries {
|
|
namespace SystemReference_blockDrv { enum { WARN = 3, FATAL = 5 }; }
|
|
namespace SystemReference_chanTlm { enum { WARN = 3, FATAL = 5 }; }
|
|
namespace SystemReference_cmdDisp { enum { WARN = 3, FATAL = 5 }; }
|
|
namespace SystemReference_cmdSeq { enum { WARN = 3, FATAL = 5 }; }
|
|
namespace SystemReference_eventLogger { enum { WARN = 3, FATAL = 5 }; }
|
|
namespace SystemReference_fileDownlink { enum { WARN = 3, FATAL = 5 }; }
|
|
namespace SystemReference_fileManager { enum { WARN = 3, FATAL = 5 }; }
|
|
namespace SystemReference_fileUplink { enum { WARN = 3, FATAL = 5 }; }
|
|
namespace SystemReference_imageProcessor { enum {WARN = 3, FATAL = 5}; }
|
|
namespace SystemReference_prmDb { enum { WARN = 3, FATAL = 5 }; }
|
|
namespace SystemReference_processedImageBufferLogger { enum {WARN = 3, FATAL = 5}; }
|
|
namespace SystemReference_rateGroup1Comp { enum { WARN = 3, FATAL = 5 }; }
|
|
namespace SystemReference_rateGroup2Comp { enum { WARN = 3, FATAL = 5 }; }
|
|
namespace SystemReference_rateGroup3Comp { enum { WARN = 3, FATAL = 5 }; }
|
|
namespace SystemReference_saveImageBufferLogger { enum { WARN = 3, FATAL = 5 }; }
|
|
}
|
|
|
|
}</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Other definitions:</strong>
|
|
You can put any compile-time definitions you wish into <em>T</em> <code>TopologyAc.hpp</code>
|
|
If you need link-time definitions (e.g., to declare variables with storage),
|
|
you can put them in <em>T</em> <code>TopologyAc.cpp</code>, but this is not required.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For example, <code>SystemReference/Top/SystemReferenceTopologyAc.hpp</code> declares
|
|
a variable <code>SystemReference::Allocation::mallocator</code> of type <code>Fw::MallocAllocator</code>.
|
|
It provides an allocator used in the setup and teardown
|
|
of several component instances.
|
|
The corresponding link-time symbol is defined in <code>SystemReferenceTopologyDefs.cpp</code>.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Writing-C-Plus-Plus-Implementations_Implementing-Deployments_The-Main-Function">16.3.2. The Main Function</h4>
|
|
<div class="paragraph">
|
|
<p>You must write a main function that performs application-specific
|
|
and system-specific tasks such as parsing command-line arguments,
|
|
handling signals, and returning a numeric code to the system on exit.
|
|
Your main code can use the following public interface provided
|
|
by <em>T</em> <code>TopologyAc.hpp</code>:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="cpp">// ----------------------------------------------------------------------
|
|
// Public interface functions
|
|
// ----------------------------------------------------------------------
|
|
|
|
//! Set up the topology
|
|
void setup(
|
|
const TopologyState& state //!< The topology state
|
|
);
|
|
|
|
//! Tear down the topology
|
|
void teardown(
|
|
const TopologyState& state //!< The topology state
|
|
);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>These functions reside in the C++ namespace corresponding to
|
|
the FPP module where the topology <em>T</em> is defined.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>On Linux, a typical main function might work this way:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>Parse command-line arguments. Use the result to construct
|
|
a <code>TopologyState</code> object <code>state</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>Set up a signal handler to catch signals.</p>
|
|
</li>
|
|
<li>
|
|
<p>Call <em>T</em> <code>::setup</code>, passing in the <code>state</code> object, to
|
|
construct and initialize the topology.</p>
|
|
</li>
|
|
<li>
|
|
<p>Start the topology running, e.g., by looping in the main thread
|
|
until a signal is handled, or by calling a start function on a
|
|
timer component (see, e.g., <code>Svc::LinuxTimer</code>).
|
|
The loop or timer typically runs until a signal is caught, e.g.,
|
|
when the user presses control-C at the console.</p>
|
|
</li>
|
|
<li>
|
|
<p>On catching a signal</p>
|
|
<div class="olist loweralpha">
|
|
<ol class="loweralpha" type="a">
|
|
<li>
|
|
<p>Set a flag that causes the main loop to exit or the timer
|
|
to stop.
|
|
This flag must be a volatile and atomic variable (e.g.,
|
|
<code>std::atomic_bool</code>) because it is accessed
|
|
concurrently by signal handlers and threads.</p>
|
|
</li>
|
|
<li>
|
|
<p>Call <em>T</em> <code>::teardown</code>, passing in the <code>state</code> object, to
|
|
tear down the topology.</p>
|
|
</li>
|
|
<li>
|
|
<p>Wait some time for all the threads to exit.</p>
|
|
</li>
|
|
<li>
|
|
<p>Exit the main thread.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>For an example like this, see <code>SystemReference/Top/Main.cpp</code> in the
|
|
F Prime system reference repository.</p>
|
|
</div>
|
|
</div>
|
|
<div class="sect3">
|
|
<h4 id="Writing-C-Plus-Plus-Implementations_Implementing-Deployments_Public-Symbols">16.3.3. Public Symbols</h4>
|
|
<div class="paragraph">
|
|
<p>The header file <em>T</em> <code>TopologyAc.hpp</code> declares several public
|
|
symbols that you can use when writing your main function.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Instance variables:</strong>
|
|
Each component instance used in the topology is declared as
|
|
an <code>extern</code> variable, so you can refer to any component instance
|
|
in the main function.
|
|
For example, the main function in the <code>SystemReference</code> topology
|
|
calls the method <code>callIsr</code> of the <code>blockDrv</code> (block driver)
|
|
component instance, in order to simulate an interrupt service
|
|
routine (ISR) call triggered by a hardware interrupt.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p><strong>Helper functions:</strong>
|
|
The auto-generated <code>setup</code> function calls the following auto-generated
|
|
helper functions:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="cpp">void initComponents(const TopologyState& state);
|
|
void configComponents(const TopologyState& state);
|
|
void setBaseIds();
|
|
void connectComponents();
|
|
void regCommands();
|
|
void readParameters();
|
|
void loadParameters();
|
|
void startTasks(const TopologyState& state);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The auto-generated <code>teardown</code> function calls the following
|
|
auto-generated helper functions:</p>
|
|
</div>
|
|
<div class="listingblock">
|
|
<div class="content">
|
|
<pre class="prettyprint highlight"><code data-lang="cpp">void stopTasks(const TopologyState& state);
|
|
void freeThreads(const TopologyState& state);
|
|
void tearDownComponents(const TopologyState& state);</code></pre>
|
|
</div>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>The helper functions are declared as public symbols in <em>T</em>
|
|
<code>TopologyAc.hpp</code>, so if you wish, you may write your own versions
|
|
of <code>setup</code> and <code>teardown</code> that call these functions directly.
|
|
The FPP modeling is designed so that you don’t have to do this;
|
|
you can put any custom C++ code for setup or teardown into
|
|
<a href="#Defining-Component-Instances_Init-Specifiers">init specifiers</a>
|
|
and let the FPP translator generate complete <code>setup</code> and <code>teardown</code>
|
|
functions that you simply call, as described above.
|
|
Using init specifiers generally produces cleaner integration between
|
|
the model and the C++ code: you write the custom
|
|
C++ code once, any topology <em>T</em> that uses an instance <em>I</em> will pick
|
|
up the custom C++ code for <em>I</em>, and the FPP translator will automatically
|
|
put the code for <em>I</em> into the correct place in <em>T</em> <code>TopologyAc.cpp</code>.
|
|
However, if you wish to write the custom code directly into your main
|
|
function, you may.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sect2">
|
|
<h3 id="Writing-C-Plus-Plus-Implementations_Serialization-of-FPP-Values">16.4. Serialization of FPP Values</h3>
|
|
<div class="paragraph">
|
|
<p>Every value represented in FPP can be <strong>serialized</strong>, i.e., converted into a
|
|
machine-independent sequence of bytes.
|
|
Serialization provides a consistent way to store data (e.g.,
|
|
to onboard storage) and to transmit data (e.g., to or from the ground).
|
|
The F Prime framework also uses serialization to pass data through asynchronous
|
|
port invocations.
|
|
The data is serialized when it is put on a message queue
|
|
and then <strong>deserialized</strong> (i.e., converted from a byte sequence to
|
|
a C++ representation)
|
|
when it is taken off the queue for processing.</p>
|
|
</div>
|
|
<div class="paragraph">
|
|
<p>F Prime uses the following rules for serializing data:</p>
|
|
</div>
|
|
<div class="olist arabic">
|
|
<ol class="arabic">
|
|
<li>
|
|
<p>Values of primitive integer type are serialized as follows:</p>
|
|
<div class="olist loweralpha">
|
|
<ol class="loweralpha" type="a">
|
|
<li>
|
|
<p>A value of unsigned integer type (<code>U8</code>, <code>U16</code>, <code>U32</code>, or <code>U64</code>)
|
|
is serialized into big-endian order (most significant byte first) by default,
|
|
using the number of bytes implied by the bit width.
|
|
For example, the <code>U16</code> value 10 (decimal) is serialized as the
|
|
two bytes <code>00</code> <code>0A</code> (hex). If little-endian order is desired, the optional mode parameter can be specified as <code>Fw::Serialization::LITTLE</code>. This stores the data least significant byte order. The <code>U16</code> value 10 (decimal) is serialized in little-endian as the two bytes <code>0A</code> <code>00</code> (hex).</p>
|
|
</li>
|
|
<li>
|
|
<p>A value of signed integer type (<code>I8</code>, <code>I16</code>, <code>I32</code>, or <code>I64</code>)
|
|
is serialized by first converting the value to an unsigned value of the same bit
|
|
width and then serializing the unsigned value as stated in rule 1.a.
|
|
If the value is nonnegative, then the unsigned value is
|
|
the same as the signed value.
|
|
Otherwise the unsigned value is the two’s complement of the signed value.
|
|
For example:</p>
|
|
<div class="olist lowerroman">
|
|
<ol class="lowerroman" type="i">
|
|
<li>
|
|
<p>The <code>I16</code> value 10 (decimal) is serialized as two bytes, yielding the bytes <code>00</code> <code>0A</code> (hex) in big-endian and <code>0A</code> <code>00</code> (hex) in little-endian.</p>
|
|
</li>
|
|
<li>
|
|
<p>The <code>I16</code> value -10 (decimal) is serialized by
|
|
(1) computing the <code>U16</code> value 2<sup>16</sup> - 10 = 65526
|
|
and (2) serializing that value as two bytes in the selected byte order,
|
|
yielding the bytes <code>FF</code> <code>F6</code> (hex) big-endian and <code>F6</code> <code>FF</code> (hex) little-endian.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
</li>
|
|
<li>
|
|
<p>A value of floating-point type (<code>F32</code> or <code>F64</code>)
|
|
is serialized in the selected byte order according to the IEEE
|
|
standard for representing these values.</p>
|
|
</li>
|
|
<li>
|
|
<p>A value of Boolean type is serialized as a single byte.
|
|
The byte values used to represent <code>true</code> and <code>false</code>
|
|
are <code>FW_SERIALIZE_TRUE_VALUE</code> and <code>FW_SERIALIZE_FALSE_VALUE</code>,
|
|
which are defined in the F Prime configuration header <code>FpConfig.h</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>A value of string type is serialized as a size followed
|
|
by the string characters in string order.</p>
|
|
<div class="olist loweralpha">
|
|
<ol class="loweralpha" type="a">
|
|
<li>
|
|
<p>The size is serialized according to rule 1 for primitive
|
|
integer types.
|
|
The F Prime type definition <code>FwSizeStoreType</code> specifies the type to use
|
|
for the size.
|
|
This type definition is user-configurable; it is found in the
|
|
F Prime configuration file <code>FpConfig.fpp</code>.</p>
|
|
</li>
|
|
<li>
|
|
<p>There is one byte for each character of the string, and there is
|
|
no null terminator.
|
|
Each string character is serialized as an <code>I8</code> value according to rule 1.b.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
</li>
|
|
<li>
|
|
<p>A value of <a href="#Defining-Types_Array-Type-Definitions">array type</a>
|
|
is serialized as a sequence of serialized values, one for each array
|
|
element, in array order.
|
|
Each value is serialized using these rules.</p>
|
|
</li>
|
|
<li>
|
|
<p>A value of <a href="#Defining-Types_Struct-Type-Definitions">struct type</a>
|
|
is serialized member-by-member, in the order
|
|
that the members appear in the FPP struct definition,
|
|
with no padding.</p>
|
|
<div class="olist loweralpha">
|
|
<ol class="loweralpha" type="a">
|
|
<li>
|
|
<p>Except for
|
|
<a href="#Defining-Types_Struct-Type-Definitions_Member-Arrays">member arrays</a>,
|
|
each member is serialized using these rules.</p>
|
|
</li>
|
|
<li>
|
|
<p>Each member array is serialized as stated in rule 5.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
</li>
|
|
<li>
|
|
<p>A value of <a href="#Defining-Enums">enum type</a> is converted to a primitive
|
|
integer value of the <a href="#Defining-Enums_The-Representation-Type">representation
|
|
type</a> specified in the enum definition.
|
|
This value is serialized as stated in rule 1.</p>
|
|
</li>
|
|
<li>
|
|
<p>A value of <a href="#Defining-Types_Abstract-Type-Definitions">abstract type</a> is
|
|
serialized according to its
|
|
<a href="#Writing-C-Plus-Plus-Implementations_Implementing-Abstract-Types">C++ implementation</a>.</p>
|
|
</li>
|
|
</ol>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div id="footer">
|
|
<div id="footer-text">
|
|
Last updated 2025-10-30 13:48:01 -0700
|
|
</div>
|
|
</div>
|
|
<script src="code-prettify/run_prettify.js"></script>
|
|
<script type="text/x-mathjax-config">
|
|
MathJax.Hub.Config({
|
|
messageStyle: "none",
|
|
tex2jax: {
|
|
inlineMath: [["\\(", "\\)"]],
|
|
displayMath: [["\\[", "\\]"]],
|
|
ignoreClass: "nostem|nolatexmath"
|
|
},
|
|
asciimath2jax: {
|
|
delimiters: [["\\$", "\\$"]],
|
|
ignoreClass: "nostem|noasciimath"
|
|
},
|
|
TeX: { equationNumbers: { autoNumber: "none" } }
|
|
})
|
|
MathJax.Hub.Register.StartupHook("AsciiMath Jax Ready", function () {
|
|
MathJax.InputJax.AsciiMath.postfilterHooks.Add(function (data, node) {
|
|
if ((node = data.script.parentNode) && (node = node.parentNode) && node.classList.contains("stemblock")) {
|
|
data.math.root.display = "block"
|
|
}
|
|
return data
|
|
})
|
|
})
|
|
</script>
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.9/MathJax.js?config=TeX-MML-AM_HTMLorMML"></script>
|
|
</body>
|
|
</html> |