diff --git a/compiler/lib/src/main/scala/codegen/CppWriter/TopologyCppWriter/TopConfigObjects.scala b/compiler/lib/src/main/scala/codegen/CppWriter/TopologyCppWriter/TopConfigObjects.scala index 1dff3f100..3ec15dcae 100644 --- a/compiler/lib/src/main/scala/codegen/CppWriter/TopologyCppWriter/TopConfigObjects.scala +++ b/compiler/lib/src/main/scala/codegen/CppWriter/TopologyCppWriter/TopConfigObjects.scala @@ -10,29 +10,72 @@ case class TopConfigObjects( aNode: Ast.Annotated[AstNode[Ast.DefTopology]] ) extends TopologyCppWriterUtils(s, aNode) { - def getLines: List[Line] = { + private val bannerComment = "Component configuration objects" + + def getCppLines: List[Line] = { addBannerComment( - "Component configuration objects", + bannerComment, addBlankPrefix(getConfigObjectLines) ) } + def getHppLines: List[Line] = { + addBannerComment( + bannerComment, + addBlankPrefix(getConfigObjectHeaderLines) + ) + } + + private def getConfigObjectHeaderLines: List[Line] = { + def specialGen(ci: ComponentInstance, qn: String) = { + qn match { + case "Svc.Health" => getHealthCode(ci, getPingDeclarationBlock) + case _ => None + } + } + + val pairs = instances.map(ci => (ci, getSpecialCode(ci, specialGen))). + filter(_._2.isDefined).map { + case (ci, codeOpt) => (ci, codeOpt.get) + } + wrapInNamespace( + "ConfigObjects", + addBlankPostfix( + flattenWithBlankPrefix( + pairs.map { + case (ci, code) => wrapInNamespace( + getNameAsIdent(ci.qualifiedName), + code + ) + } + ) + ) + ) + } + private def getConfigObjectLines: List[Line] = { - def getCode(ci: ComponentInstance) = getSpecialCode(ci) match { + def specialGen(ci: ComponentInstance, qn: String) = { + qn match { + case "Svc.Health" => getHealthCode(ci, getPingEntryBlock) + case _ => None + } + } + + def getCode(ci: ComponentInstance) = getSpecialCode(ci, specialGen) match { case None => ( getCodeForPhase (CppWriter.Phases.configObjects) (ci) ).map(lines) case code => code } val pairs = instances.map(ci => (ci, getCode(ci))). - filter(_._2.isDefined).map { + filter(_._2.isDefined).map { case (ci, codeOpt) => (ci, codeOpt.get) } wrapInNamespace( "ConfigObjects", addBlankPostfix( flattenWithBlankPrefix( - pairs.map { + pairs.map { case (ci, code) => wrapInNamespace( getNameAsIdent(ci.qualifiedName), code @@ -43,16 +86,51 @@ case class TopConfigObjects( ) } - private def getSpecialCode(ci: ComponentInstance): Option[List[Line]] = { + private def getSpecialCode(ci: ComponentInstance, specialGen: (ComponentInstance, String) => Option[List[Line]]): Option[List[Line]] = { val symbol = Symbol.Component(ci.component.aNode) val qn = s.a.getQualifiedName(symbol) - qn.toString match { - case "Svc.Health" => getHealthCode(ci) - case _ => None + specialGen(ci, qn.toString) + } + + // Get the lines for a ping port entry + private def getPingEntryBlock(map: Map[Int, ComponentInstance], maxNum: Int): List[Line] = { + def getEntryLines(ciOpt: Option[ComponentInstance]) = { + val ss = ciOpt match { + // Entry for connected port + case Some(ci) => + val name = ci.qualifiedName + val ident = getNameAsIdent(name) + List( + s"PingEntries::$ident::WARN,", + s"PingEntries::$ident::FATAL,", + s"$q$ident$q" + ) + // Dummy entry for unconnected port + case None => List("0", "0", "") + } + wrapInScope("{", ss.map(line), "},") } + wrapInScope( + "Svc::Health::PingEntry pingEntries[NUM_PING_ENTRIES] = {", + // Loop over all ports in the range 0..maxNum. + // Entries are positional, so we must generate code + // for any unconnected entries in this range. + List.range(0, maxNum+1).flatMap(n => getEntryLines(map.get(n))), + "};", + ) + } + + private def getPingDeclarationBlock(map: Map[Int, ComponentInstance], maxNum: Int): List[Line] = { + val numEntries = maxNum + 1 + List( + "//!< Number of entries in the pingEntryies array", + s"constexpr FwSizeType NUM_PING_ENTRIES = $numEntries;", + "//!< Ping entry configuration for Svc::Health", + "extern Svc::Health::PingEntry pingEntries[NUM_PING_ENTRIES];", + ).map(line) } - private def getHealthCode(ci: ComponentInstance): Option[List[Line]] = + private def getHealthCode(ci: ComponentInstance, blockGen: (Map[Int, ComponentInstance], Int) => List[Line]): Option[List[Line]] = for { // Get the ping out port pingOutPort <- { @@ -70,7 +148,7 @@ case class TopConfigObjects( val pii = PortInstanceIdentifier(ci, pingOutPort) val m0: Map[Int, ComponentInstance] = Map() val mn = t.getConnectionsFrom(pii).foldLeft ((m0, 0)) { - case ((m, n), c) => + case ((m, n), c) => val n1 = t.getPortNumber(pii.portInstance, c).get ( m + (n1 -> c.to.port.componentInstance), @@ -83,32 +161,8 @@ case class TopConfigObjects( } } yield { - // Get the lines for a ping port entry - def getEntryLines(ciOpt: Option[ComponentInstance]) = { - val ss = ciOpt match { - // Entry for connected port - case Some(ci) => - val name = ci.qualifiedName - val ident = getNameAsIdent(name) - List( - s"PingEntries::$ident::WARN,", - s"PingEntries::$ident::FATAL,", - s"$q$ident$q" - ) - // Dummy entry for unconnected port - case None => List("0", "0", "") - } - wrapInScope("{", ss.map(line), "},") - } val (map, maxNum) = mapAndMaxNum - wrapInScope( - "Svc::Health::PingEntry pingEntries[] = {", - // Loop over all ports in the range 0..maxNum. - // Entries are positional, so we must generate code - // for any unconnected entries in this range. - List.range(0, maxNum+1).flatMap(n => getEntryLines(map.get(n))), - "};" - ) + blockGen(map, maxNum) } } diff --git a/compiler/lib/src/main/scala/codegen/CppWriter/TopologyCppWriter/TopologyCppWriter.scala b/compiler/lib/src/main/scala/codegen/CppWriter/TopologyCppWriter/TopologyCppWriter.scala index 39f16bda1..806fe8975 100644 --- a/compiler/lib/src/main/scala/codegen/CppWriter/TopologyCppWriter/TopologyCppWriter.scala +++ b/compiler/lib/src/main/scala/codegen/CppWriter/TopologyCppWriter/TopologyCppWriter.scala @@ -36,6 +36,7 @@ case class TopologyCppWriter( } val hppLines = linesMember( TopConstants(s, aNode).getLines ++ + TopConfigObjects(s, aNode).getHppLines ++ TopComponentInstances(s, aNode).getHppLines ) val cppIncludes = { @@ -50,14 +51,12 @@ case class TopologyCppWriter( } val cppLines = linesMember( Line.blank :: - List( - wrapInAnonymousNamespace( - addBlankPostfix( - TopConfigObjects(s, aNode).getLines, - ) + List.concat( + addBlankPostfix( + TopConfigObjects(s, aNode).getCppLines, ), TopComponentInstances(s, aNode).getCppLines - ).flatten, + ), CppDoc.Lines.Cpp ) val (helperFnNames, helperFns) = TopHelperFns(s, aNode).getMembers diff --git a/compiler/tools/fpp-to-cpp/test/top/BasicTopologyAc.ref.cpp b/compiler/tools/fpp-to-cpp/test/top/BasicTopologyAc.ref.cpp index 19990ca1a..a42669e8c 100644 --- a/compiler/tools/fpp-to-cpp/test/top/BasicTopologyAc.ref.cpp +++ b/compiler/tools/fpp-to-cpp/test/top/BasicTopologyAc.ref.cpp @@ -8,22 +8,20 @@ namespace M { - namespace { - // ---------------------------------------------------------------------- - // Component configuration objects - // ---------------------------------------------------------------------- - - namespace ConfigObjects { + // ---------------------------------------------------------------------- + // Component configuration objects + // ---------------------------------------------------------------------- - namespace active2 { - U32 x = 0; - } + namespace ConfigObjects { + namespace active2 { + U32 x = 0; } } + // ---------------------------------------------------------------------- // Component instances // ---------------------------------------------------------------------- diff --git a/compiler/tools/fpp-to-cpp/test/top/HealthTopologyAc.ref.cpp b/compiler/tools/fpp-to-cpp/test/top/HealthTopologyAc.ref.cpp index a4c020f70..2ace23686 100644 --- a/compiler/tools/fpp-to-cpp/test/top/HealthTopologyAc.ref.cpp +++ b/compiler/tools/fpp-to-cpp/test/top/HealthTopologyAc.ref.cpp @@ -8,33 +8,31 @@ namespace M { - namespace { - - // ---------------------------------------------------------------------- - // Component configuration objects - // ---------------------------------------------------------------------- - - namespace ConfigObjects { - - namespace health { - Svc::Health::PingEntry pingEntries[] = { - { - PingEntries::c1::WARN, - PingEntries::c1::FATAL, - "c1" - }, - { - PingEntries::c2::WARN, - PingEntries::c2::FATAL, - "c2" - }, - }; - } + // ---------------------------------------------------------------------- + // Component configuration objects + // ---------------------------------------------------------------------- + + namespace ConfigObjects { + + namespace health { + Svc::Health::PingEntry pingEntries[NUM_PING_ENTRIES] = { + { + PingEntries::c1::WARN, + PingEntries::c1::FATAL, + "c1" + }, + { + PingEntries::c2::WARN, + PingEntries::c2::FATAL, + "c2" + }, + }; } } + // ---------------------------------------------------------------------- // Component instances // ---------------------------------------------------------------------- diff --git a/compiler/tools/fpp-to-cpp/test/top/HealthTopologyAc.ref.hpp b/compiler/tools/fpp-to-cpp/test/top/HealthTopologyAc.ref.hpp index e47ba485a..b6df48883 100644 --- a/compiler/tools/fpp-to-cpp/test/top/HealthTopologyAc.ref.hpp +++ b/compiler/tools/fpp-to-cpp/test/top/HealthTopologyAc.ref.hpp @@ -33,6 +33,21 @@ namespace M { }; } + // ---------------------------------------------------------------------- + // Component configuration objects + // ---------------------------------------------------------------------- + + namespace ConfigObjects { + + namespace health { + //!< Number of entries in the pingEntryies array + constexpr FwSizeType NUM_PING_ENTRIES = 2; + //!< Ping entry configuration for Svc::Health + extern Svc::Health::PingEntry pingEntries[NUM_PING_ENTRIES]; + } + + } + // ---------------------------------------------------------------------- // Component instances // ----------------------------------------------------------------------