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

Precise go/done interface #405

Closed
rachitnigam opened this issue Feb 24, 2021 · 2 comments · Fixed by #635
Closed

Precise go/done interface #405

rachitnigam opened this issue Feb 24, 2021 · 2 comments · Fixed by #635
Labels
C: Calyx Extension or change to the Calyx IL S: Available Can be worked upon

Comments

@rachitnigam
Copy link
Contributor

rachitnigam commented Feb 24, 2021

At many points, we have informally stated the go/done interface as "go must be kept high for the duration of the execution of the component and done is set to high in the cycle after the component is finished executing."

Stated formally, we can ask: Given a component with latency L, does the go signal stay active for L cycles or L+1 cycles?

The implementation of this interface in the compiler provides two potentially* contradicting answers to this:

Structurally Invoking Components

The canonical "correct" way of structurally invoking a component is:

// Assuming has_run = 0 initially 
has_run.in = comp.done;
has_run.write_en = comp.done;
comp.go = !has_run.out;

In this program, the go signal is set to 1 for L + 1 cycles. The following sequence of events happen:

  1. Cycle 0: comp.go is set to high since has_run.out = 0.
  2. Cycle L: comp.done becomes high and has_run.out and has_run.write_en are set to 1.
  3. Cycle L + 1: has_run.out becomes 1 and comp.go is set to 0.

Latency-Sensitive Compilation

A static annotation of a group provides the latency L of the group or the component. We use this information to transition the controller FSM without waiting for the done signal in the group.

fsm.in = fsm.out + 1; // every cycle
comp.go = fsm.out >= 0 && fsm.out < 2; // assume comp takes 2 cycles

In this program, comp.go is kept high for exactly L cycles.

Potentially Conflicting

These implementation are only potentially conflicting: it might be reasonable to say that the go signal can be 0 or 1 in the cycle when the done signal is high. After all, this extra cycle represents the coordination required for latency-insensitive compilation.

However, we need to be precise about one thing: when does setting the go signal start a "new" invocation

@rachitnigam rachitnigam added S: Discussion needed Issues blocked on discussion Priority: High Blocking issues C: Calyx Extension or change to the Calyx IL labels Feb 24, 2021
@sampsyo
Copy link
Contributor

sampsyo commented Feb 26, 2021

Thanks for writing this up, @rachitnigam; it certainly is odd! I don't exactly know how to proceed, but I thought I'd just add a tad more color to the problem as it stands (if I understand correctly):

As a base assumption, this would be a nice property to have: The go/done interface looks the same to from the perspective of a given group, regardless of its invoking context. In other words, a group knows what its "job" is when interacting with the outside world—and this job doesn't change for different settings the group might appear in.

In practice, Calyx currently only has two ways that it creates "invoking contexts" for groups: latency-insensitive FSMs (from CompileControl) and latency-sensitive FSMs (from Sensitive). @rachitnigam's argument above tries to show that a go/done interface actually behaves differently in these two settings. The consequence is that we either need a flexible definition of the go/done interface that will capture both settings, or we need to rectify the two so they behave exactly the same (and hence a simpler, less flexible go/done definition will suffice).

Concretely, the latency-sensitive case is pretty straightforward; go is high for exactly the latency of the component. The latency-insensitive case looks "off-by-one" from this perspective. We need to decide whether we like it that way, and hence we will nail down a definition that encompasses both behaviors, or we think it's feasible to rectify the two—probably by shaving off one cycle from the latency-insensitive case somehow.

@rachitnigam
Copy link
Contributor Author

rachitnigam commented Mar 4, 2021

The current resolution for this is generating latency-insensitive FSM transitions like this when compiling seq:

one[go] = f.out == 0;
two[go] = f.out == 1 || one[done];

@rachitnigam rachitnigam added S: Available Can be worked upon and removed Priority: High Blocking issues S: Discussion needed Issues blocked on discussion labels Mar 4, 2021
@rachitnigam rachitnigam linked a pull request Sep 4, 2021 that will close this issue
20 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C: Calyx Extension or change to the Calyx IL S: Available Can be worked upon
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants