Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for arrays on ports and state variables #158

Merged
merged 4 commits into from
Dec 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions include/reactor-uc/macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@
_port->set(_port, &__val); \
} while (0)

// Sets an output port, copies data and triggers all downstream reactions.
#define lf_set_array(port, array) \
do { \
Port *_port = (Port *)(port); \
_port->set(_port, array); \
} while (0)

/**
* @brief Retreive the value of a trigger and cast it to the expected type
*/
Expand Down Expand Up @@ -214,6 +221,13 @@
BufferType value; \
} ReactorName##_##PortName;

#define LF_DEFINE_OUTPUT_ARRAY_STRUCT(ReactorName, PortName, SourceSize, BufferType, ArrayLen) \
typedef struct { \
Port super; \
Reaction *sources[(SourceSize)]; \
BufferType value[(ArrayLen)]; \
} ReactorName##_##PortName;

#define LF_DEFINE_OUTPUT_CTOR(ReactorName, PortName, SourceSize) \
void ReactorName##_##PortName##_ctor(ReactorName##_##PortName *self, Reactor *parent, \
OutputExternalCtorArgs external) { \
Expand Down Expand Up @@ -249,6 +263,16 @@
Connection *conns_out[(NumConnsOut)]; \
} ReactorName##_##PortName;

#define LF_DEFINE_INPUT_ARRAY_STRUCT(ReactorName, PortName, EffectSize, ObserversSize, BufferType, ArrayLen, \
NumConnsOut) \
typedef struct { \
Port super; \
Reaction *effects[(EffectSize)]; \
Reaction *observers[(ObserversSize)]; \
BufferType value[(ArrayLen)]; \
Connection *conns_out[(NumConnsOut)]; \
} ReactorName##_##PortName;

#define LF_DEFINE_INPUT_CTOR(ReactorName, PortName, EffectSize, ObserverSize, BufferType, NumConnsOut) \
void ReactorName##_##PortName##_ctor(ReactorName##_##PortName *self, Reactor *parent, \
InputExternalCtorArgs external) { \
Expand Down
4 changes: 2 additions & 2 deletions lfc/core/src/main/java/org/lflang/generator/TargetTypes.java
Original file line number Diff line number Diff line change
Expand Up @@ -184,8 +184,8 @@ default String getTargetExpr(Expression expr, InferredType type) {
return ASTUtils.addZeroToLeadingDot(((Literal) expr).getLiteral()); // here we don't escape
} else if (expr instanceof CodeExpr) {
return ASTUtils.toText(((CodeExpr) expr).getCode());
// } else if (expr instanceof BracedListExpression) {
// return getTargetBracedListExpr((BracedListExpression) expr, type);
} else if (expr instanceof BracedListExpression) {
return getTargetBracedListExpr((BracedListExpression) expr, type);
// } else if (expr instanceof BracketListExpression) {
// return getTargetBracketListExpr((BracketListExpression) expr, type);
// } else if (expr instanceof ParenthesisListExpression) {
Expand Down
2 changes: 1 addition & 1 deletion lfc/core/src/main/java/org/lflang/target/Target.java
Original file line number Diff line number Diff line change
Expand Up @@ -468,7 +468,7 @@ public boolean mandatesEqualsInitializers() {

/** Allow expressions of the form {@code {a, b, c}}. */
public boolean allowsBracedListExpressions() {
return false;
return true;
}

/** Allow expressions of the form {@code [a, b, c]}. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,33 @@ import org.lflang.lf.*
class UcPortGenerator(private val reactor: Reactor, private val connections: UcConnectionGenerator) {
val Port.external_args
get(): String = "_${name}_external"

companion object {
val Port.width
get(): Int = widthSpec?.getWidth()?:1
val Type.isArray
get(): Boolean = cStyleArraySpec != null
val Type.arrayLength
get(): Int = cStyleArraySpec.length

}

private fun generateSelfStruct(input: Input) = "LF_DEFINE_INPUT_STRUCT(${reactor.codeType}, ${input.name}, ${reactor.getEffects(input).size}, ${reactor.getObservers(input).size}, ${input.type.toText()}, ${connections.getNumConnectionsFromPort(null, input as Port)});"
private fun generateSelfStruct(input: Input): String {
if (input.type.isArray) {
return "LF_DEFINE_INPUT_ARRAY_STRUCT(${reactor.codeType}, ${input.name}, ${reactor.getEffects(input).size}, ${reactor.getObservers(input).size}, ${input.type.id}, ${input.type.arrayLength}, ${connections.getNumConnectionsFromPort(null, input as Port)});"
} else {
return "LF_DEFINE_INPUT_STRUCT(${reactor.codeType}, ${input.name}, ${reactor.getEffects(input).size}, ${reactor.getObservers(input).size}, ${input.type.toText()}, ${connections.getNumConnectionsFromPort(null, input as Port)});"
}
}
private fun generateInputCtor(input: Input) = "LF_DEFINE_INPUT_CTOR(${reactor.codeType}, ${input.name}, ${reactor.getEffects(input).size}, ${reactor.getObservers(input).size}, ${input.type.toText()}, ${connections.getNumConnectionsFromPort(null, input as Port)});"
private fun generateSelfStruct(output: Output) = "LF_DEFINE_OUTPUT_STRUCT(${reactor.codeType}, ${output.name}, ${reactor.getSources(output).size}, ${output.type.toText()});"
private fun generateSelfStruct(output: Output): String {
if (output.type.isArray) {
return "LF_DEFINE_OUTPUT_ARRAY_STRUCT(${reactor.codeType}, ${output.name}, ${reactor.getSources(output).size}, ${output.type.id}, ${output.type.arrayLength});"
} else {
return "LF_DEFINE_OUTPUT_STRUCT(${reactor.codeType}, ${output.name}, ${reactor.getSources(output).size}, ${output.type.toText()});"
}
}

private fun generateOutputCtor(output: Output) = "LF_DEFINE_OUTPUT_CTOR(${reactor.codeType}, ${output.name}, ${reactor.getSources(output).size});"

fun generateSelfStructs() = reactor.allInputs.plus(reactor.allOutputs).joinToString(prefix = "// Port structs\n", separator = "\n", postfix = "\n") {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,31 @@
package org.lflang.generator.uc

import org.lflang.allStateVars
import org.lflang.generator.uc.UcPortGenerator.Companion.arrayLength
import org.lflang.generator.uc.UcPortGenerator.Companion.isArray
import org.lflang.isInitialized
import org.lflang.lf.Reactor
import org.lflang.lf.StateVar
import org.lflang.toText

class UcStateGenerator(private val reactor: Reactor) {
fun generateReactorStructFields() =
reactor.allStateVars.joinToString(prefix = "// State variables \n", separator = "\n") { "${it.type.toText()} ${it.name};" }
reactor.allStateVars.joinToString(prefix = "// State variables \n", separator = "\n") {
if (it.type.isArray) {
"${it.type.id} ${it.name}[${it.type.arrayLength}];"
} else {
"${it.type.toText()} ${it.name};"
}
}

fun generateInitializeStateVars() =
reactor.allStateVars.filter{it.isInitialized}.joinToString(prefix = "// Initialize State variables \n", separator = "\n") { "self->${it.name} = ${it.init.expr.toCCode()};" }
reactor.allStateVars.filter{it.isInitialized}.joinToString(prefix = "// Initialize State variables \n", separator = "\n") {
if (it.type.isArray) {
"""|${it.type.id} _${it.name}_init[${it.type.arrayLength}] = ${it.init.expr.toCCode()};
|memcpy(&self->${it.name}, &_${it.name}_init, sizeof(_${it.name}_init));
""".trimMargin()
} else {
"self->${it.name} = ${it.init.expr.toCCode()};"
}
}
}
30 changes: 30 additions & 0 deletions test/lf/src/ArrayPorts.lf
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
target uC {
platform: Native
}


reactor Src {
output out: int[4]

reaction(startup) -> out {=
int arr[] = {1, 2, 3, 4};
lf_set_array(out, arr);
=}
}

reactor Sink {
input in: int[4]

reaction(in) {=
for (int i = 0; i < 4; i++) {
printf("%d\n", in->value[i]);
validate(in->value[i] == i+1);
}
=}
}

main reactor {
src = new Src()
sink = new Sink()
src.out -> sink.in
}
14 changes: 14 additions & 0 deletions test/lf/src/ArrayState.lf
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
target uC {
platform: Native
}

main reactor {
state s: int[4] = {1, 2, 3, 4}

reaction(startup) {=
for (int i = 0; i < 4; i++) {
printf("%d\n", self->s[i]);
validate(self->s[i] == i+1);
}
=}
}
31 changes: 31 additions & 0 deletions test/lf/src/StringPorts.lf
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
target uC {
platform: Native
}


reactor Src {
output out: char[12]

reaction(startup) -> out {=
lf_set_array(out, "Hello World");
=}
}

reactor Sink {
input in: char[12]

reaction(in) {=
const char *expected = "Hello World";
for (int i = 0; i < 12; i++) {
printf("%c", in->value[i]);
validate(in->value[i] == expected[i]);
}
printf("\n");
=}
}

main reactor {
src = new Src()
sink = new Sink()
src.out -> sink.in
}
Loading