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

Is it plausible for Clash to (optionally) automatically insert registers to meet timing requirements? #165

Open
tomjaguarpaw opened this issue Aug 3, 2016 · 2 comments
Milestone

Comments

@tomjaguarpaw
Copy link

Sometimes when we write Clash we write large signal computations that are essentially pure expressions. Here's a silly but illustrative example:

mySignal :: Signal Int
mySignal = mySignal1 +. mySignal2 +. mySignal3 +. ... +. mySignal1024
    where (+.) = liftA2 (+)

Even if we reparenthesise this expression so that it is of log depth then it will still be eight additions deep and it is easily possibly that a signal cannot propagate through it properly within one cycle. We could rewrite it thus:

mySignal :: Signal Int
mySignal = r( ... (r (r mySignal1 +. r mySignal2) +. r (r mySignal3 +. r mySignal4)) + ...
    where r = register undefined
          (+.) = liftA2 (+)

That is, we can register every subexpression. If every subexpression meets timing requirements then the rewritten version of mySignal will too. We can be even cleverer and only add registers in the few places where it is necessary (as long as we also add registers in parallel pipelines so that inputs to subsequent combinators are synchronised). (NB it is not possible to add registers into any recursive parts of the design.)

My question is: would it be possible to add an optional register insertion phase to Clash? It is not semantics preserving, because the transformed output may be delayed by more than the original output, but it is semantics preserving up to time shift. Clash could report this time shift to the user.

@ggreif
Copy link
Contributor

ggreif commented Aug 3, 2016

IIRC Signals have a Num instance, so you can use (+) directly without lifting.

Just my 2 cents!

@christiaanb
Copy link
Member

While it is plausible that clash could one day do this, there are several caveats (some of which you already mentioned):

  • registers cannot be inserted into feedback loops.
  • we need to develop a heuristic for propagation delay, so that we know when/if to add registers, and also how to space them apart.

I always hoped that we could just place a couple of registers at the output of our circuits, and that the FPGA synthesis tools would just re-time them. However, I've been told they don't (always) do this, so I guess we would need to add such a pass to clash. Certainly plausible, but we would need people to implement it.

Somewhat related, we already have delay-annotated signals in clash: http://hackage.haskell.org/package/clash-prelude-0.10.11/docs/CLaSH-Signal-Delayed.html
Using those we can already statically verify that parallel pipelines are properly synchronized, although the user still needs to manually add the registers.

christiaanb added a commit that referenced this issue Sep 6, 2018
@christiaanb christiaanb added this to the 2.0 milestone Dec 18, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants