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

Fix cycle checking when calculating min delay from nearest physical action #2459

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

lsk567
Copy link
Collaborator

@lsk567 lsk567 commented Jan 21, 2025

As the title suggests, currently, when actions for a deep loop, the recursion never terminates and leads to stack overflow. This PR addresses the issue by introducing a visited set.

@lsk567 lsk567 added the bugfix label Jan 21, 2025
Copy link
Collaborator

@edwardalee edwardalee left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for catching and fixing this! It would be nice to add a test case.

Comment on lines +750 to +768
if (trigger.getDefinition() instanceof Input) {
var upstreamPorts = port.eventualSources();
for (RuntimeRange<PortInstance> range : upstreamPorts) {
PortInstance upstreamPort = range.instance;

// Get a connection delay value between upstream port and
// the current port.
TimeValue connectionDelay =
upstreamPort.getDependentPorts().stream()
.filter(
sRange ->
sRange.destinations.stream()
.map(it -> it.instance)
.anyMatch(port::equals))
.map(sRange -> ASTUtils.getDelay(sRange.connection.getDelay()))
.filter(Objects::nonNull)
.map(TimeValue::fromNanoSeconds)
.findFirst()
.orElse(TimeValue.ZERO);
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a cleaner way to look at an input port (PortInstance) and get a connection delay from an upstream connection into the input port? @edwardalee @erlingrj

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow that code is ugly. It's also not quite correct. E.g., suppose you have hierarchy:

   p1 ----> p2 ---/D/---> p3

this will return TimeValue.ZERO, I think, ignoring D.
Are you trying to get the minimum tag offset along the path from the eventual source to the port?
This is pretty tricky. Something like this was done by @byeonggiljun in CExtensionUtils.java, but there is a telling comment there:

        // The minimum delay calculation needs to be made in the C code because it
        // may depend on parameter values.

Also, if the port is a multiport, there could be multiple delays to it.

Copy link
Collaborator Author

@lsk567 lsk567 Jan 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you trying to get the minimum tag offset along the path from the eventual source to the port?

Yes, that is precisely what findNearestPhysicalActionTrigger was designed to do, but it wasn't doing it thoroughly.

Here is the test case I designed. The current master branch would falsely report 10 sec when tracing back from out2.

TriggerLoop

The fix in this PR now correctly identifies that the minimum path delay from out2 to the physical action is 2 sec, not 10 sec:

 --> test/C/src/federated/TriggerLoop.lf:23:3
   |
22 | reactor Hard {
23 |   output out2: int
   |   ^^^^^^^^^^^^^^^^ Found a path from a physical action to output for reactor "Hard".
The amount of delay is 2 sec.
With centralized coordination, this can result in a large number of messages to the RTI.
Consider refactoring the code so that the output does not depend on the physical action,
or consider using decentralized coordination. To silence this warning, set the target
parameter coordination-options with a value like {advance-message-interval: 10 msec}

But it has to do some gymnastics since it seems hard to get the connection delay value from an input port (the in port of the left Delay, of type RuntimeRange.Port). So far I have only found a way to access the delay from SendRange, which requires tracing from the input port to the upstream output port, hence the ugliness.

Perhaps a long-term solution is to refactor RuntimeRange to make accessing connection delays easier.

Something like this was done by @byeonggiljun in CExtensionUtils.java, but there is a telling comment there

If the parameters are not passed in on the command line, which should not be possible now, I think it should be okay?

Also, if the port is a multiport, there could be multiple delays to it.

That's true. I will augment the test case to check for this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants