lingua-franca icon indicating copy to clipboard operation
lingua-franca copied to clipboard

Initial support for childref multiports

Open jhaye opened this issue 2 years ago • 5 comments

This is an initial attempt to implement child references within a reactor being allowed to be multiports as explained in #806.

Some caveats:
Right now if the child reactors that are being referenced are a bank and then are further referenced to a multiport, this completely flattens this structure. So if the bank is of size 4 and the multiport of size 5, the childref would be unrolled into a PortBank of size 20. This is not ideal but was the easiest to implement right now.
~~Secondly, one of the provided unit tests called ReadOutputOfContainedBank fails right now due to a scheduling error, but it shows that it is able to access the data of the child reactor successfully.~~

jhaye avatar Jun 13 '22 13:06 jhaye

Another caveat, if a reactor is initialised in another, and

  1. The contained reactor is used via childref
  2. The width of the bank used via childref is initialised via an argument to the respective reactor

it does not compile.

I have reduced this to a minimal example, that can be found here: https://gist.github.com/jhaye/ce4d92af09c37379529d3902bec1faab

I'm not sure how I would implement value propagation like this.

jhaye avatar Aug 02 '22 09:08 jhaye

So if the bank is of size 4 and the multiport of size 5, the childref would be unrolled into a PortBank of size 20. This is not ideal but was the easiest to implement right now.

I'm not sure how it's not ideal... IMHO it's a usability feature that there is a uniform API regardless of whether you're accessing a multiport on a child, a port on a bank of children, or a multiport on a bank. Are other targets doing this differently?

I have reduced this to a minimal example, that can be found here: gist.github.com/jhaye/ce4d92af09c37379529d3902bec1faab

This is now supported, thanks for the MWE.

oowekyala avatar Sep 07 '22 13:09 oowekyala

Are other targets doing this differently?

I am not sure if I understand how this works in Rust, but in C++ we do not unroll the multiport. In the case of multiports within a bank, the reaction body can say precisely which port in which reactor instance it wants to access. If it wants to read all values, it needs two nested loops:

target Cpp
reactor Source {
  output[5] out: int;
  reaction (startup) -> out {= /* ... */ =}
}
main reactor {
  source = new[4] Source()
  reaction (source.out) {=
    for (int i{0}; i < source.size(); i++) {
      for (int j{0}; j < source[i].out.size(); j++) {
         int value = *source[i].out[j].get();
         // ....
      }
    }
  =}
}

cmnrd avatar Sep 07 '22 14:09 cmnrd

The C target does this similarly to Cpp.

edwardalee avatar Sep 07 '22 14:09 edwardalee

Thanks for your feedback, so there is one view class generated per reaction to expose only the declared dependencies... We can probably also do that in Rust, I'll create a ticket

oowekyala avatar Sep 07 '22 14:09 oowekyala

@oowekyala What is the status of this PR? Should it be reviewed?

cmnrd avatar Dec 22 '22 09:12 cmnrd

@cmnrd one of the new benchmarks in https://github.com/lf-lang/benchmarks-lingua-franca/pull/38 shows a weird bug which I still have to investigate. I expect the fix will only touch the runtime crate so I think this PR can still be reviewed.

oowekyala avatar Jan 03 '23 10:01 oowekyala

I don't know much about the internals either, which is why I handed this PR off. All I can say from a cursory glance is that it looks good. I also like how the issue of value propagation was solved.

jhaye avatar Jan 04 '23 09:01 jhaye