Skip to content

Commit

Permalink
code-generation for UART devices and formatting
Browse files Browse the repository at this point in the history
  • Loading branch information
tanneberger committed Jan 27, 2025
1 parent 4330e3d commit 716b08a
Show file tree
Hide file tree
Showing 31 changed files with 2,510 additions and 2,084 deletions.
13 changes: 13 additions & 0 deletions lfc/core/src/main/java/org/lflang/validation/AttributeSpec.java
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,19 @@ enum AttrParamType {
new AttributeSpec(List.of(new AttrParamSpec(VALUE_ATTR, AttrParamType.INT, false))));
// @interface:tcp(name="string", address="string") e.g. @interface:tcp(name="if1",
// address="127.0.0.1")

ATTRIBUTE_SPECS_BY_NAME.put(
"interface_uart",
new AttributeSpec(
List.of(
new AttrParamSpec("name", AttrParamType.STRING, true),
new AttrParamSpec("uart_device", AttrParamType.INT, true),
new AttrParamSpec("baud_rate", AttrParamType.INT, true),
new AttrParamSpec("data_bits", AttrParamType.STRING, true),
new AttrParamSpec("parity", AttrParamType.STRING, true),
new AttrParamSpec("stop_bits", AttrParamType.STRING, true)
)));

ATTRIBUTE_SPECS_BY_NAME.put(
"interface_tcp",
new AttributeSpec(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ package org.lflang.generator.uc
import org.lflang.*
import org.lflang.generator.PrependOperator
import org.lflang.generator.orZero
import org.lflang.generator.uc.UcReactorGenerator.Companion.hasStartup
import org.lflang.generator.uc.UcReactorGenerator.Companion.hasShutdown
import org.lflang.generator.uc.UcReactorGenerator.Companion.codeType
import org.lflang.generator.uc.UcReactorGenerator.Companion.getEffects
import org.lflang.generator.uc.UcReactorGenerator.Companion.getObservers
import org.lflang.generator.uc.UcReactorGenerator.Companion.getSources
import org.lflang.AttributeUtils.getMaxNumberOfPendingEvents
import org.lflang.generator.uc.UcReactorGenerator.Companion.hasShutdown
import org.lflang.generator.uc.UcReactorGenerator.Companion.hasStartup
import org.lflang.lf.*

class UcActionGenerator(private val reactor: Reactor) {
Expand All @@ -22,61 +22,72 @@ class UcActionGenerator(private val reactor: Reactor) {
}
}

/** Returns the C Enum representing the type of action.*/
private val Action.actionType
get(): String = if (isPhysical) "PHYSICAL_ACTION" else "LOGICAL_ACTION"
/** Returns the C Enum representing the type of action. */
private val Action.actionType
get(): String = if (isPhysical) "PHYSICAL_ACTION" else "LOGICAL_ACTION"

private fun generateSelfStruct(action: Action) = with(PrependOperator) {
private fun generateSelfStruct(action: Action) =
with(PrependOperator) {
"""
|LF_DEFINE_ACTION_STRUCT${if (action.type == null) "_VOID" else ""}(${reactor.codeType}, ${action.name}, ${action.actionType}, ${reactor.getEffects(action).size}, ${reactor.getSources(action).size}, ${reactor.getObservers(action).size}, ${action.maxNumPendingEvents} ${if (action.type != null) ", ${action.type.toText()}" else ""});
|
""".trimMargin()
}
"""
.trimMargin()
}

private fun generateCtor(action: Action) = with(PrependOperator) {
private fun generateCtor(action: Action) =
with(PrependOperator) {
"""
|LF_DEFINE_ACTION_CTOR${if (action.type == null) "_VOID" else ""}(${reactor.codeType}, ${action.name}, ${action.actionType}, ${reactor.getEffects(action).size}, ${reactor.getSources(action).size}, ${reactor.getObservers(action).size}, ${action.maxNumPendingEvents} ${if (action.type != null) ", ${action.type.toText()}" else ""});
|
""".trimMargin()
}
"""
.trimMargin()
}

private fun generateCtor(builtin: BuiltinTrigger) =
(if (builtin == BuiltinTrigger.STARTUP) "LF_DEFINE_STARTUP_CTOR" else "LF_DEFINE_SHUTDOWN_CTOR") +
"(${reactor.codeType});\n"
private fun generateCtor(builtin: BuiltinTrigger) =
(if (builtin == BuiltinTrigger.STARTUP) "LF_DEFINE_STARTUP_CTOR"
else "LF_DEFINE_SHUTDOWN_CTOR") + "(${reactor.codeType});\n"

fun generateCtors(): String {
var code = reactor.allActions.joinToString(separator = "\n") { generateCtor(it) }
if (reactor.hasStartup) code += generateCtor(BuiltinTrigger.STARTUP)
if (reactor.hasShutdown) code += generateCtor(BuiltinTrigger.SHUTDOWN)
return code
}

fun generateCtors(): String {
var code = reactor.allActions.joinToString(separator = "\n") { generateCtor(it) }
if (reactor.hasStartup) code += generateCtor(BuiltinTrigger.STARTUP);
if (reactor.hasShutdown) code += generateCtor(BuiltinTrigger.SHUTDOWN);
return code;
private fun generateSelfStruct(builtin: BuiltinTrigger) =
(if (builtin == BuiltinTrigger.STARTUP) "LF_DEFINE_STARTUP_STRUCT"
else "LF_DEFINE_SHUTDOWN_STRUCT") +
"(${reactor.codeType}, ${reactor.getEffects(builtin).size}, ${reactor.getObservers(builtin).size});\n"

fun generateSelfStructs(): String {
var code = reactor.allActions.joinToString(separator = "\n") { generateSelfStruct(it) }
if (reactor.hasStartup) {
code += generateSelfStruct(BuiltinTrigger.STARTUP)
}
if (reactor.hasShutdown) {
code += generateSelfStruct(BuiltinTrigger.SHUTDOWN)
}
return code
}

private fun generateSelfStruct(builtin: BuiltinTrigger) =
(if (builtin == BuiltinTrigger.STARTUP) "LF_DEFINE_STARTUP_STRUCT" else "LF_DEFINE_SHUTDOWN_STRUCT") +
"(${reactor.codeType}, ${reactor.getEffects(builtin).size}, ${reactor.getObservers(builtin).size});\n"
fun generateReactorStructFields(): String {
var code =
reactor.allActions.joinToString(
prefix = "// Actions and builtin triggers\n", separator = "\n", postfix = "\n") {
"LF_ACTION_INSTANCE(${reactor.codeType}, ${it.name});"
}
if (reactor.hasStartup) code += "LF_STARTUP_INSTANCE(${reactor.codeType});"
if (reactor.hasShutdown) code += "LF_SHUTDOWN_INSTANCE(${reactor.codeType});"
return code
}

fun generateSelfStructs(): String {
var code = reactor.allActions.joinToString(separator = "\n") { generateSelfStruct(it) }
if (reactor.hasStartup) {
code += generateSelfStruct(BuiltinTrigger.STARTUP) ;
}
if (reactor.hasShutdown) {
code += generateSelfStruct(BuiltinTrigger.SHUTDOWN) ;
}
return code;
}
private fun generateReactorCtorCode(action: Action) =
"LF_INITIALIZE_ACTION(${reactor.codeType}, ${action.name}, ${action.minDelay.orZero().toCCode()}, ${action.minSpacing.orZero().toCCode()});"

fun generateReactorStructFields(): String {
var code = reactor.allActions.joinToString(prefix = "// Actions and builtin triggers\n", separator = "\n", postfix = "\n") { "LF_ACTION_INSTANCE(${reactor.codeType}, ${it.name});" }
if (reactor.hasStartup) code += "LF_STARTUP_INSTANCE(${reactor.codeType});"
if (reactor.hasShutdown) code += "LF_SHUTDOWN_INSTANCE(${reactor.codeType});"
return code;
}
private fun generateReactorCtorCodeStartup() = "LF_INITIALIZE_STARTUP(${reactor.codeType});"

private fun generateReactorCtorCode(action: Action) = "LF_INITIALIZE_ACTION(${reactor.codeType}, ${action.name}, ${action.minDelay.orZero().toCCode()}, ${action.minSpacing.orZero().toCCode()});"
private fun generateReactorCtorCodeStartup() = "LF_INITIALIZE_STARTUP(${reactor.codeType});"
private fun generateReactorCtorCodeShutdown() = "LF_INITIALIZE_SHUTDOWN(${reactor.codeType});"
private fun generateReactorCtorCodeShutdown() = "LF_INITIALIZE_SHUTDOWN(${reactor.codeType});"

fun generateReactorCtorCodes(): String {
var code = reactor.allActions.joinToString(prefix = "// Initialize actions and builtin triggers\n", separator = "\n", postfix = "\n") { generateReactorCtorCode(it)}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,32 +1,37 @@

package org.lflang.generator.uc

import java.nio.file.Path
import kotlin.io.path.name
import kotlin.math.max
import org.lflang.*
import org.lflang.target.TargetConfig
import org.lflang.generator.PrependOperator
import org.lflang.generator.uc.UcInstanceGenerator.Companion.isAFederate
import org.lflang.lf.Instantiation
import org.lflang.lf.Reactor
import org.lflang.target.TargetConfig
import org.lflang.target.property.BuildTypeProperty
import org.lflang.target.property.CmakeIncludeProperty
import org.lflang.target.property.LoggingProperty
import org.lflang.target.property.PlatformProperty
import org.lflang.target.property.type.PlatformType
import org.lflang.util.FileUtil
import java.nio.file.Path
import java.time.LocalDateTime
import kotlin.io.path.name
import kotlin.math.max

abstract class UcCmakeGenerator(private val targetConfig: TargetConfig, private val fileConfig: UcFileConfig, private val numEvents: Int, private val numReactions: Int) {
protected val S = '$' // a little trick to escape the dollar sign with $S
private val minCmakeVersion = "3.10"
protected val includeFiles = targetConfig.get(CmakeIncludeProperty.INSTANCE)?.map { fileConfig.srcPath.resolve(it).toUnixString() }
protected val platform = targetConfig.get(PlatformProperty.INSTANCE).platform
abstract val mainTarget: String
abstract fun generateCmake(sources: List<Path>): String
abstract class UcCmakeGenerator(
private val targetConfig: TargetConfig,
private val fileConfig: UcFileConfig,
private val numEvents: Int,
private val numReactions: Int
) {
protected val S = '$' // a little trick to escape the dollar sign with $S
private val minCmakeVersion = "3.10"
protected val includeFiles =
targetConfig.get(CmakeIncludeProperty.INSTANCE)?.map {
fileConfig.srcPath.resolve(it).toUnixString()
}
protected val platform = targetConfig.get(PlatformProperty.INSTANCE).platform
abstract val mainTarget: String

protected fun generateCmakeCommon(sources: List<Path>, compileDefs: List<String>) = with(PrependOperator) {
abstract fun generateCmake(sources: List<Path>): String

protected fun generateCmakeCommon(sources: List<Path>, compileDefs: List<String>) =
with(PrependOperator) {
""" |
|set(LFC_GEN_SOURCES
${" | "..sources.filterNot{it.name == "lf_main.c"}.joinWithLn { "$S{CMAKE_CURRENT_LIST_DIR}/${it.toUnixString()}"}}
Expand All @@ -39,10 +44,12 @@ abstract class UcCmakeGenerator(private val targetConfig: TargetConfig, private
|set(LFC_GEN_INCLUDE_DIRS $S{CMAKE_CURRENT_LIST_DIR})
|set(REACTION_QUEUE_SIZE ${max(numReactions, 1)} CACHE STRING "Size of the reaction queue")
|set(EVENT_QUEUE_SIZE ${max(numEvents, 2)} CACHE STRING "Size of the event queue")
""".trimMargin()
}
"""
.trimMargin()
}

protected fun generateCmakePosix(sources: List<Path>, compileDefs: List<String>) = with(PrependOperator) {
protected fun generateCmakePosix(sources: List<Path>, compileDefs: List<String>) =
with(PrependOperator) {
"""
|cmake_minimum_required(VERSION $minCmakeVersion)
|project(${mainTarget} LANGUAGES C)
Expand All @@ -61,28 +68,41 @@ abstract class UcCmakeGenerator(private val targetConfig: TargetConfig, private
|target_link_libraries($S{LF_MAIN_TARGET} PRIVATE reactor-uc)
|target_include_directories($S{LF_MAIN_TARGET} PRIVATE $S{LFC_GEN_INCLUDE_DIRS})
${" |"..(includeFiles?.joinWithLn { "include(\"$it\")" } ?: "")}
""".trimMargin()
}
"""
.trimMargin()
}
}

class UcCmakeGeneratorNonFederated(private val mainDef: Instantiation, targetConfig: TargetConfig, fileConfig: UcFileConfig, numEvents: Int, numReactions: Int): UcCmakeGenerator(targetConfig, fileConfig, numEvents, numReactions) {
override val mainTarget = fileConfig.name
class UcCmakeGeneratorNonFederated(
private val mainDef: Instantiation,
targetConfig: TargetConfig,
fileConfig: UcFileConfig,
numEvents: Int,
numReactions: Int
) : UcCmakeGenerator(targetConfig, fileConfig, numEvents, numReactions) {
override val mainTarget = fileConfig.name

override fun generateCmake(sources: List<Path>) =
if (platform == PlatformType.Platform.NATIVE) {
generateCmakePosix(sources, emptyList())
} else {
generateCmakeCommon(sources, emptyList())
}
override fun generateCmake(sources: List<Path>) =
if (platform == PlatformType.Platform.NATIVE) {
generateCmakePosix(sources, emptyList())
} else {
generateCmakeCommon(sources, emptyList())
}
}

class UcCmakeGeneratorFederated(private val federate: UcFederate, targetConfig: TargetConfig, fileConfig: UcFileConfig, numEvents: Int, numReactions: Int): UcCmakeGenerator(targetConfig, fileConfig, numEvents, numReactions) {
override val mainTarget = federate.codeType
class UcCmakeGeneratorFederated(
private val federate: UcFederate,
targetConfig: TargetConfig,
fileConfig: UcFileConfig,
numEvents: Int,
numReactions: Int
) : UcCmakeGenerator(targetConfig, fileConfig, numEvents, numReactions) {
override val mainTarget = federate.codeType

override fun generateCmake(sources: List<Path>) =
if (platform == PlatformType.Platform.NATIVE) {
generateCmakePosix(sources, federate.getCompileDefs())
} else {
generateCmakeCommon(sources, federate.getCompileDefs())
}
override fun generateCmake(sources: List<Path>) =
if (platform == PlatformType.Platform.NATIVE) {
generateCmakePosix(sources, federate.getCompileDefs())
} else {
generateCmakeCommon(sources, federate.getCompileDefs())
}
}
Loading

0 comments on commit 716b08a

Please sign in to comment.