Skip to content

Commit dc632df

Browse files
authored
Attributes for action and connection buffers (#198)
* This PR adds attributes for specifying the max num pending events for actions and the max buffer size for connections * Simple formatting
1 parent c84cb92 commit dc632df

File tree

10 files changed

+117
-10
lines changed

10 files changed

+117
-10
lines changed

lfc/core/src/main/java/org/lflang/AttributeUtils.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
package org.lflang;
2727

2828
import static org.lflang.ast.ASTUtils.factory;
29+
import static org.lflang.ast.ASTUtils.toInteger;
2930

3031
import java.util.HashMap;
3132
import java.util.List;
@@ -290,6 +291,24 @@ public static List<Attribute> getInterfaceAttributes(Instantiation node) {
290291
return findAttributesByNameStartingWith(node, "interface");
291292
}
292293

294+
public static int getMaxNumberOfPendingEvents(Action node) {
295+
Attribute attr = findAttributeByName(node, "max_pending_events");
296+
if (attr != null) {
297+
return Integer.valueOf(attr.getAttrParms().get(0).getValue());
298+
} else {
299+
return -1;
300+
}
301+
}
302+
303+
public static int getConnectionBufferSize(Connection node) {
304+
Attribute attr = findAttributeByName(node, "buffer");
305+
if (attr != null) {
306+
return Integer.valueOf(attr.getAttrParms().get(0).getValue());
307+
} else {
308+
return -1;
309+
}
310+
}
311+
293312
public static Attribute getLinkAttribute(Connection node) {
294313
return findAttributeByName(node, "link");
295314
}

lfc/core/src/main/java/org/lflang/validation/AttributeSpec.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,14 @@ enum AttrParamType {
243243
ATTRIBUTE_SPECS_BY_NAME.put(
244244
"_networkReactor",
245245
new AttributeSpec(List.of(new AttrParamSpec(VALUE_ATTR, AttrParamType.STRING, false))));
246+
// @max_pending_event(<value>)
247+
ATTRIBUTE_SPECS_BY_NAME.put(
248+
"max_pending_events",
249+
new AttributeSpec(List.of(new AttrParamSpec(VALUE_ATTR, AttrParamType.INT, false))));
250+
// @buffer(<value>)
251+
ATTRIBUTE_SPECS_BY_NAME.put(
252+
"buffer",
253+
new AttributeSpec(List.of(new AttrParamSpec(VALUE_ATTR, AttrParamType.INT, false))));
246254
// @interface:tcp(name="string", address="string") e.g. @interface:tcp(name="if1", address="127.0.0.1")
247255
ATTRIBUTE_SPECS_BY_NAME.put(
248256
"interface_tcp",

lfc/core/src/main/kotlin/org/lflang/generator/uc/UcActionGenerator.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,17 @@ import org.lflang.generator.uc.UcReactorGenerator.Companion.codeType
99
import org.lflang.generator.uc.UcReactorGenerator.Companion.getEffects
1010
import org.lflang.generator.uc.UcReactorGenerator.Companion.getObservers
1111
import org.lflang.generator.uc.UcReactorGenerator.Companion.getSources
12+
import org.lflang.AttributeUtils.getMaxNumberOfPendingEvents
1213
import org.lflang.lf.*
1314

1415
class UcActionGenerator(private val reactor: Reactor) {
1516

1617
companion object {
1718
public val Action.maxNumPendingEvents
18-
get(): Int = 12 // FIXME: This should be annotated in the LF code
19+
get(): Int {
20+
val num = getMaxNumberOfPendingEvents(this)
21+
return if (num > 0) num else 1
22+
}
1923
}
2024

2125
/** Returns the C Enum representing the type of action.*/

lfc/core/src/main/kotlin/org/lflang/generator/uc/UcConnectionUtils.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package org.lflang.generator.uc
22

3-
import org.lflang.AttributeUtils.getLinkAttribute
3+
import org.lflang.AttributeUtils.*
44
import org.lflang.generator.orNever
55
import org.lflang.generator.uc.UcInstanceGenerator.Companion.codeWidth
66
import org.lflang.generator.uc.UcInstanceGenerator.Companion.width
@@ -58,7 +58,7 @@ open class UcGroupedConnection(
5858
channels.groupingBy { Pair(it.src.getCodePortIdx(), it.src.getCodeBankIdx()) }.eachCount()
5959
frequencyMap.values.maxOrNull() ?: 0
6060
}
61-
val maxNumPendingEvents = 16 // FIXME: Must be derived from the program
61+
val maxNumPendingEvents = if (getConnectionBufferSize(lfConn) > 0) getConnectionBufferSize(lfConn) else 1
6262

6363
fun assignUid(id: Int) {
6464
uid = id

src/action.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ lf_ret_t Action_schedule(Action *self, interval_t offset, const void *value) {
5252
}
5353

5454
if (self->events_scheduled >= self->max_pending_events) {
55-
LF_ERR(TRIG, "Too many pending events. Capacity is %i", self->max_pending_events);
55+
LF_ERR(TRIG, "Action event buffer is full, dropping event. Capacity is %i", self->max_pending_events);
5656
return LF_ERR;
5757
}
5858

src/connection.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,11 @@ void DelayedConnection_trigger_downstreams(Connection *_self, const void *value,
142142
EventPayloadPool *pool = trigger->payload_pool;
143143
if (self->staged_payload_ptr == NULL) {
144144
ret = pool->allocate(pool, &self->staged_payload_ptr);
145-
validate(ret == LF_OK); // FIME: Trigger_downstreams should return lf_ret_t
145+
if (ret != LF_OK) {
146+
LF_ERR(CONN, "No more space in event buffer for delayed connection %p, dropping. Capacity is %d", _self,
147+
self->payload_pool.capacity);
148+
return;
149+
}
146150
}
147151
memcpy(self->staged_payload_ptr, value, value_size);
148152
sched->register_for_cleanup(sched, &_self->super);

test/lf/src/Action.lf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ target uC {
33
}
44

55
main reactor {
6+
@max_pending_events(10)
67
logical action a:int
78
state cnt:int=0
89
state cnt2:int=0

test/lf/src/ActionBuffer.lf

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
target uC {
2+
platform: Native
3+
}
4+
5+
main reactor {
6+
7+
@max_pending_events(10)
8+
logical action a:int
9+
10+
state received:int=0
11+
12+
reaction(startup) -> a {=
13+
for (int i = 0; i<10; i++) {
14+
lf_schedule(a, MSEC(i), i);
15+
}
16+
=}
17+
18+
reaction(a) {=
19+
validate(a->value == self->received++);
20+
printf("Action scheduled wtih %d\n", a->value);
21+
=}
22+
23+
reaction(shutdown) {=
24+
validate(self->received == 10);
25+
=}
26+
}

test/lf/src/Connections.lf

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,25 +19,32 @@ reactor R1 {
1919
}
2020

2121

22-
reactor R2 {
22+
reactor R2(expected: int = 0) {
2323
input in:int
2424

25+
state cnt:int = 0
26+
2527
reaction(startup) {=
2628
printf("Hi from other guy at startup\n");
27-
2829
=}
2930

3031
reaction(in) {=
3132
printf("Got %d\n", in->value);
33+
self->cnt++;
34+
=}
35+
36+
reaction(shutdown) {=
37+
validate(self->cnt == self->expected);
3238
=}
3339
}
3440

3541
main reactor {
3642
r1 = new R1()
37-
r2 = new R2()
43+
r2 = new R2(expected = 11)
3844
r1.out -> r2.in
3945

4046
r3 = new R1()
41-
r4 = new R2()
42-
r3.out -> r4.in after 100 msec
47+
r4 = new R2(expected = 10)
48+
49+
r3.out -> r4.in after 10 msec
4350
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
target uC {
2+
platform: Native,
3+
timeout: 200 msec
4+
}
5+
6+
reactor R1 {
7+
output out: int
8+
timer t(0, 10 msec)
9+
state cnt: int = 0;
10+
11+
reaction(t) -> out {=
12+
if (self->cnt < 10) {
13+
printf("Hello from R1 at %ld\n", env->get_elapsed_physical_time(env));
14+
lf_set(out, self->cnt++);
15+
}
16+
=}
17+
}
18+
19+
reactor R2 {
20+
input in:int
21+
state cnt:int = 0
22+
reaction(in) {=
23+
printf("Got %d\n", in->value);
24+
validate(in->value == self->cnt++);
25+
=}
26+
27+
reaction(shutdown) {=
28+
validate(self->cnt == 10);
29+
=}
30+
}
31+
32+
main reactor {
33+
r1 = new R1()
34+
r2 = new R2()
35+
36+
@buffer(10)
37+
r1.out -> r2.in after 100 msec
38+
}

0 commit comments

Comments
 (0)