Skip to content

Commit 60cc60e

Browse files
authored
Merge pull request #707 from nasa/feature/external-params
Add support for externally stored parameters
2 parents 0c16a74 + dbf54bf commit 60cc60e

File tree

164 files changed

+51822
-1521
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

164 files changed

+51822
-1521
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,6 @@ __SHADOW__
88
__pycache__
99
dist/
1010
fprime_fpp/fpp_version_info.py
11+
# Scala metals project files
12+
compiler/project/metals.sbt
13+
compiler/project/project/

compiler/lib/src/main/scala/analysis/Analysis.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -309,12 +309,12 @@ case class Analysis(
309309
def getIntValueOpt[T](nodeOpt: Option[AstNode[T]]): Result.Result[Option[Int]] =
310310
Result.mapOpt(nodeOpt, (node: AstNode[T]) => getIntValue(node.id))
311311

312-
/** Gets an optional nonnegative BigInt value from an AST ndoe */
312+
/** Gets an optional nonnegative BigInt value from an AST node */
313313
def getNonnegativeBigIntValueOpt[T](nodeOpt: Option[AstNode[T]]):
314314
Result.Result[Option[BigInt]] =
315315
Result.mapOpt(nodeOpt, (node: AstNode[T]) => getNonnegativeBigIntValue(node.id))
316316

317-
/** Gets an optional nonnegative int value from an AST ndoe */
317+
/** Gets an optional nonnegative int value from an AST node */
318318
def getNonnegativeIntValueOpt[T](nodeOpt: Option[AstNode[T]]): Result.Result[Option[Int]] =
319319
Result.mapOpt(nodeOpt, (node: AstNode[T]) => getNonnegativeIntValue(node.id))
320320

compiler/lib/src/main/scala/analysis/Semantics/Component.scala

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ case class Component(
4949
/** Query whether the component has parameters */
5050
def hasParameters = this.paramMap.size > 0
5151

52+
/** Query whether the component has external parameters */
53+
def hasExternalParameters = paramMap.values.exists(_.isExternal)
54+
5255
/** Query whether the component has commands */
5356
def hasCommands = this.commandMap.size > 0
5457

@@ -148,7 +151,7 @@ case class Component(
148151
val loc = instance.getLoc
149152
val prevLoc = prevInstance.getLoc
150153
Left(SemanticError.DuplicateStateMachineInstance(name, loc, prevLoc))
151-
case None =>
154+
case None =>
152155
val stateMachineInstanceMap = this.stateMachineInstanceMap + (name -> instance)
153156
val component = this.copy(stateMachineInstanceMap = stateMachineInstanceMap)
154157
Right(component)
@@ -164,7 +167,7 @@ case class Component(
164167
val loc = instance.getLoc
165168
val prevLoc = prevInstance.getLoc
166169
Left(SemanticError.DuplicatePortInstance(name, loc, prevLoc))
167-
case None =>
170+
case None =>
168171
val portMap = this.portMap + (name -> instance)
169172
val component = this.copy(portMap = portMap)
170173
Right(component)
@@ -180,7 +183,7 @@ case class Component(
180183
val loc = instance.getLoc
181184
val prevLoc = prevInstance.getLoc
182185
Left(SemanticError.DuplicatePortInstance(kind.toString, loc, prevLoc))
183-
case None =>
186+
case None =>
184187
val specialPortMap = this.specialPortMap + (kind -> instance)
185188
val component = this.copy(specialPortMap = specialPortMap)
186189
Right(component)
@@ -224,7 +227,7 @@ case class Component(
224227
defaultEventId = result._2
225228
)
226229
}
227-
230+
228231
/** Add a parameter */
229232
def addParam(
230233
idOpt: Option[Param.Id],
@@ -305,7 +308,7 @@ case class Component(
305308
portKinds: List[Ast.SpecPortInstance.SpecialKind]
306309
) = if (condition) Result.map(
307310
portKinds,
308-
(portKind: Ast.SpecPortInstance.SpecialKind) =>
311+
(portKind: Ast.SpecPortInstance.SpecialKind) =>
309312
this.specialPortMap.get(portKind) match {
310313
case Some(_) => Right(())
311314
case None =>
@@ -436,7 +439,7 @@ case class Component(
436439
val error = SemanticError.PassiveStateMachine(loc)
437440
Left(error)
438441
}
439-
)
442+
)
440443
for {
441444
_ <- checkPortInstances()
442445
_ <- checkCommands()

compiler/lib/src/main/scala/analysis/Semantics/Param.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ final case class Param(
99
paramType: Type,
1010
default: Option[Value],
1111
setOpcode: BigInt,
12-
saveOpcode: BigInt
12+
saveOpcode: BigInt,
13+
isExternal: Boolean
1314
) {
1415

1516
/** Gets the name of the parameter */
@@ -52,7 +53,7 @@ object Param {
5253
yield {
5354
val (setOpcode, defaultOpcode1) = computeOpcode(setOpcodeOpt, defaultOpcode)
5455
val (saveOpcode, defaultOpcode2) = computeOpcode(saveOpcodeOpt, defaultOpcode1)
55-
(Param(aNode, paramType, default, setOpcode, saveOpcode), defaultOpcode2)
56+
(Param(aNode, paramType, default, setOpcode, saveOpcode, data.isExternal), defaultOpcode2)
5657
}
5758
}
5859

compiler/lib/src/main/scala/ast/Ast.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -590,8 +590,9 @@ object Ast {
590590
typeName: AstNode[TypeName],
591591
default: Option[AstNode[Expr]],
592592
id: Option[AstNode[Expr]],
593-
setOpcode: Option[AstNode[Expr]],
594-
saveOpcode: Option[AstNode[Expr]]
593+
setOpcode: Option[AstNode[Expr]],
594+
saveOpcode: Option[AstNode[Expr]],
595+
isExternal: Boolean
595596
)
596597

597598
/** Port instance specifier */

compiler/lib/src/main/scala/codegen/AstWriter.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,7 @@ object AstWriter extends AstVisitor with LineUtils {
473473
) = {
474474
val (_, node, _) = aNode
475475
val data = node.data
476-
lines("spec param") ++
476+
lines(if data.isExternal then "external spec param" else "spec param") ++
477477
List.concat(
478478
ident(data.name),
479479
typeNameNode(data.typeName),

compiler/lib/src/main/scala/codegen/CppWriter/ComponentCppWriter/ComponentCppWriter.scala

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -93,11 +93,13 @@ case class ComponentCppWriter (
9393
guardedList (hasChannels) (List("Fw/Tlm/TlmString.hpp"))
9494
val prmStrHeaders =
9595
guardedList (hasParameters) (List("Fw/Prm/PrmString.hpp"))
96+
val prmExtHeaders =
97+
guardedList (hasExternalParameters) (List("Fw/Prm/PrmExternalTypes.hpp"))
9698
val logStrHeaders =
9799
guardedList (hasEvents) (List("Fw/Log/LogString.hpp"))
98100
val internalStrHeaders =
99101
guardedList (hasInternalPorts) (List("Fw/Types/InternalInterfaceString.hpp"))
100-
val systemHeaders =
102+
val systemHeaders =
101103
(guardedList (hasEvents) (
102104
List("atomic")
103105
)).map(CppWriter.systemHeaderString).sortBy(_.toLowerCase()).map(line)
@@ -114,6 +116,7 @@ case class ComponentCppWriter (
114116
cmdStrHeaders,
115117
tlmStrHeaders,
116118
prmStrHeaders,
119+
prmExtHeaders,
117120
logStrHeaders,
118121
internalStrHeaders
119122
).map(CppWriter.headerString)
@@ -263,10 +266,10 @@ case class ComponentCppWriter (
263266
),
264267
lines(
265268
s"""|
266-
|//! Friend class for white-box testing
267-
|friend class ${componentClassName}Friend;
268269
|//! Friend class tester to support autocoded test harness
269270
|friend class ${componentName}TesterBase;
271+
|//! Friend class tester implementation to support white-box testing
272+
|friend class ${componentName}Tester;
270273
|"""
271274
)
272275
).flatten
@@ -524,8 +527,8 @@ case class ComponentCppWriter (
524527
}
525528

526529
addAccessTagAndComment(
527-
"PROTECTED",
528-
"Component construction and destruction",
530+
"PROTECTED",
531+
"Component construction and destruction",
529532
List(
530533
constructorClassMember(
531534
Some(s"Construct $componentClassName object"),
@@ -537,17 +540,18 @@ case class ComponentCppWriter (
537540
Some("\"\"")
538541
)
539542
),
540-
s"Fw::${kindStr}ComponentBase(compName)" ::
541-
smInstancesByName.map((name, smi) => {
543+
List(s"Fw::${kindStr}ComponentBase(compName)") :::
544+
(if (hasExternalParameters) List("paramDelegatePtr(NULL)") else Nil) :::
545+
smInstancesByName.map { (name, smi) =>
542546
val sm = s.a.stateMachineMap(smi.symbol)
543547
val hasActionsOrGuards = sm.hasActions || sm.hasGuards
544548
val args = (smi.getSmKind, hasActionsOrGuards) match {
545-
case (StateMachine.Kind.External, _) => "this"
546-
case (StateMachine.Kind.Internal, true) => "*this"
547-
case (StateMachine.Kind.Internal, false) => ""
549+
case (StateMachine.Kind.External, _) => "this"
550+
case (StateMachine.Kind.Internal, true) => "*this"
551+
case (StateMachine.Kind.Internal, false) => ""
548552
}
549553
s"m_stateMachine_$name($args)"
550-
}),
554+
},
551555
intersperseBlankLines(
552556
List(
553557
intersperseBlankLines(
@@ -558,8 +562,8 @@ case class ComponentCppWriter (
558562
throttledEvents.map((_, event) => line(
559563
s"this->${eventThrottleCounterName(event.getName)} = 0;"
560564
)),
561-
sortedParams.map((_, param) => line(
562-
s"this->${paramValidityFlagName(param.getName)} = Fw::ParamValid::UNINIT;"
565+
sortedParams.flatMap((_, param) => guardedList(!param.isExternal) (
566+
lines(s"this->${paramValidityFlagName(param.getName)} = Fw::ParamValid::UNINIT;")
563567
))
564568
)
565569
)

compiler/lib/src/main/scala/codegen/CppWriter/ComponentCppWriter/ComponentCppWriterUtils.scala

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,8 @@ abstract class ComponentCppWriterUtils(
313313

314314
val hasParameters: Boolean = component.paramMap.nonEmpty
315315

316+
val hasExternalParameters: Boolean = component.paramMap.values.exists(_.isExternal)
317+
316318
val hasDataProducts: Boolean = component.hasDataProducts
317319

318320
val hasContainers: Boolean = containersByName != Nil
@@ -333,30 +335,32 @@ abstract class ComponentCppWriterUtils(
333335

334336
/** Parameters for the init function */
335337
val initParams: List[CppDoc.Function.Param] = List.concat(
336-
if componentData.kind != Ast.ComponentKind.Passive then List(
337-
CppDoc.Function.Param(
338-
CppDoc.Type("FwSizeType"),
339-
"queueDepth",
340-
Some("The queue depth")
338+
guardedList (componentData.kind != Ast.ComponentKind.Passive) (
339+
List(
340+
CppDoc.Function.Param(
341+
CppDoc.Type("FwSizeType"),
342+
"queueDepth",
343+
Some("The queue depth")
344+
)
341345
)
342-
)
343-
else Nil,
344-
if hasSerialAsyncInputPorts then List(
345-
CppDoc.Function.Param(
346-
CppDoc.Type("FwSizeType"),
347-
"msgSize",
348-
Some("The message size")
346+
),
347+
guardedList (hasSerialAsyncInputPorts) (
348+
List(
349+
CppDoc.Function.Param(
350+
CppDoc.Type("FwSizeType"),
351+
"msgSize",
352+
Some("The message size")
353+
)
349354
)
350-
)
351-
else Nil,
355+
),
352356
List(
353357
CppDoc.Function.Param(
354358
CppDoc.Type("FwEnumStoreType"),
355359
"instance",
356360
Some("The instance number"),
357361
Some("0")
358362
)
359-
),
363+
)
360364
)
361365

362366
val portParamTypeMap: ComponentCppWriterUtils.PortParamTypeMap =

compiler/lib/src/main/scala/codegen/CppWriter/ComponentCppWriter/ComponentImplWriter.scala

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,25 @@ case class ComponentImplWriter(
122122
hookCmds.map(getCommandOverflowHook)
123123
)
124124

125-
private def getConstructor: CppDoc.Class.Member =
125+
private def getConstructor: CppDoc.Class.Member = {
126+
val initializers = if (hasExternalParameters) {
127+
Nil
128+
} else {
129+
List(s"$className(compName)")
130+
}
131+
val bodyLines = if (hasExternalParameters) {
132+
lines(
133+
s"""|// TODO Initialize the ParamExternalDelegate
134+
|// The register function can be called directly here:
135+
|// E.G. this->registerExternalParameters(SomeParamExternalDelegateChild());
136+
|// Or you can call the register function in a public setup method
137+
|// that is called when setting up the component instance.
138+
|"""
139+
)
140+
} else {
141+
Nil
142+
}
143+
126144
constructorClassMember(
127145
Some(s"Construct $componentImplClassName object"),
128146
List(
@@ -132,9 +150,10 @@ case class ComponentImplWriter(
132150
Some("The component name")
133151
)
134152
),
135-
List(s"$className(compName)"),
136-
Nil
153+
initializers,
154+
bodyLines
137155
)
156+
}
138157

139158
private def getConstructorsAndDestructors: List[CppDoc.Class.Member] =
140159
addAccessTagAndComment(

0 commit comments

Comments
 (0)