Skip to content

[Handshake] Using LazyFork can produce combinatorial cycles. #3936

Open
@Dinistro

Description

It seems that handshake's LazyFork violates a required property for composable dataflow circuits:

Consider the following example:

handshake.func @test(%arg0: none) -> (none) {
  %0:2 = lazy_fork [2] %arg0 : none
  %outCtrl = join %0#0, %0#1 : none, none
  return %outCtrl: none
}

when lowering this to FIRRTL and feeding it into firtool it will complain that there is a cycle involving the valid and ready signals of %0. LazyFork will only set the output's valid signal once all of them are ready to receive something. Join on the other hand, waits until all inputs are valid, before it sets their ready signals.

The paper which introduces compositional dataflow circuits states the following:

We avoid combinational cycles by insisting each cycle in the dataflow network have at least one
data and one control buffer (see Section 4) and by insisting no block has a combinational path from
a ready to a valid signal.

While we ensure the first property with buffer insertions, the latter is violated by LazyFork.

It seems that a correct LazyFork implementation requires changes to ensure it can be used correctly. Not sure if it will then still be "cheaper" than a normal/eager fork, though.

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions