calyxir / calyx

Intermediate Language (IL) for Hardware Accelerator Generators
https://calyxir.org
MIT License
500 stars 52 forks source link

How to convert `while` to `enable`? #80

Closed tissue3 closed 4 years ago

tissue3 commented 4 years ago

This is a child issue of #52 .

Any idea on how to represent while in structure, so we can replace it with enable? We cannot simply substitute while with a signature in structure, because there can be sequence inside while body, and we do want the while body be executed step by step, following seq control.

One way I can think about is ban while and only allow for control. So we convert for n step s to seq (enable ...) (enable ...) ..., repeating enable n/s times. This will not result in increase overheap in RTL backend since we don't duplicate structure.

However, abandoning while loop means we we cannot represent a lot of interesting functions. If we want to keep while, we need to come up with some way of representing sequential execution in structure.

sampsyo commented 4 years ago

It's a good point. A while is inherently variable-latency—that's the reason we'd want it to exist independently of for. So in that sense, it will need to somehow interact with #50 and the alternatives therein for dealing with asynchronous invocation, etc., as well as #53, where we're figuring out how to describe the latency of submodules.

One way to think about it is that, for any while loop, we'd want to instantiate a special while_structure subcomponent that includes the loop state and invokes the body repeatedly. This subcomponent will need to be invoked asynchronously from the supercomponent in a variable-latency way—however we decide to do that—so it gets to run continuously and just signal to the outside world when the iteration is finished.

tissue3 commented 4 years ago

How about applying a new semantics/signature that allows one structure to take in another component (that has control semantics)? For example

(define/component main()()
..
   ( (new-std while0 (std_while 32 substruct_A))
     (-> (@ i0 out) (@ while0 left))
     (-> (@ const3 out) (@ lt0 right)) 
   .. )
  (seq 
      (enable X Y)
      (enable while0)
 ..))
(define/component substruct_A()()     //while body
.. //structure
( seq 
   (enable M N) 
   (enable K)))
.. )

Then 1) For each component, the control can be made of sequence of enables only. 2) It can be easily translate to dynamic&static scheduling hybrids, since structure naturally fall into static scheduling as far as the structure does not take in another component, and the only thing once appear changes upper components to dynamic scheduling is while structure.

tissue3 commented 4 years ago

It's a good point. A while is inherently variable-latency—that's the reason we'd want it to exist independently of for. So in that sense, it will need to somehow interact with #50 and the alternatives therein for dealing with asynchronous invocation, etc., as well as #53, where we're figuring out how to describe the latency of submodules.

One way to think about it is that, for any while loop, we'd want to instantiate a special while_structure subcomponent that includes the loop state and invokes the body repeatedly. This subcomponent will need to be invoked asynchronously from the supercomponent in a variable-latency way—however we decide to do that—so it gets to run continuously and just signal to the outside world when the iteration is finished.

I was just typing when you reply and it seems we have a similar thought.

sampsyo commented 4 years ago

Indeed! A while back, @sgpthomas and I were chatting about a similar feature idea where components could take other components as “arguments” and gain access to them. At that point, the idea was about letting two different components read & write the same memory, for example. But this would be another use case.

Maybe we should make a separate issue about that idea specifically?

sgpthomas commented 4 years ago

Linking issue #48. This is where I describe this loan idea.

rachitnigam commented 4 years ago

Futil has been redesigned to use go/done holes and groups in #139.