Help! How to use dtfold ? #2400
-
Sorry folks, but I can't work it out from the example+description in the manual at https://hackage.haskell.org/package/clash-prelude-1.6.4/docs/Clash-Sized-Vector.html#v:dtfold . Can anyone help? I am trying to implement a vector mux:
for which the obvious, clean, sane simple implementation unfortunately synthesizes using many tens of thousands of logic units, say 60 thousands. My vector is 256 wide and each wire ("x") is some hundreds of bits wide. Yes, that sane implementation is
This is a candidate to get the complexity down from 2^n to n log2 n in the classical way by recursive halving. The basic idea is ... do v !! i using the top bit of index i to select the first or the second of the two halves v1,v2 of v=v1++v2, and then recursively use the remaining bits of index i to select from inside the half-vector. Perfect for dtfold? Everything I try elicits incomprehensible (to me) type complaints about needing KnownNat l !-(. I must use vector v :: Vec (2^n) x to construct a function f :: Index (2^n) -> x So for dtfold I need to specify how, given two such functions f1,f2 constructed from the two halves v1,v2 with v1++v2=v, I make function f for v:
(give me the lowbits function, say lowbits i = unpack i' where (_::BitVector 1,i') = split i) This is the combinator among the parameters to the dtfold function, though one needs to also say what level "n" it is at. Call it
The other argument to dtfold is the base of the recursion/induction, applied to vectors length 1, i.e. the elements of the original vector v. Like this:
(that index i is in the Index 1 type, which makes it necessarily 0, so we know what it is and ignore it). These components plus some mysterious type formula that I will call foo for now are put together by dtfold :
so I should get
and as far as I can make out from the manual that foo thing is given by
and I want (???) Proxy @(IIndex x) where I have written Proxy @foo. The above definition of (!!!) gives the single error
There is no "l" (letter "ell") anywhere in my definitions. I have declared KnownNat n of every n::Nat that I have introduced in these definitions. What is going on? Is this my mistake or a mistake in dtfold somewhere? The dtfold function wants its argument "combi" to have a universally quantified type that takes a natural as first argument, and combi is defined so that is so. What am I supposed to do here? Thanks for any light in the darkness. PTB |
Beta Was this translation helpful? Give feedback.
Replies: 6 comments 21 replies
-
Thanks for opening this discussion! I opened the documentation for Could you try explicitly applying (!!!) :: forall n . KnownNat n => Vec (2^n) x -> Index (2^n) -> x
v !!! i = dtfold (Proxy @foo) bse (combi @n) v i |
Beta Was this translation helpful? Give feedback.
-
Note that I would expect any and all synthesis tools to already do this by default. I tested with yosys for ECP5 and it does use a tree like structure. Not that it's not possible to do it structurally using For this
it synthesizes to this circuit for target ECP5 (For some reason it renders incorrectly when opening the link directly. Please save the svg and view it that way) : |
Beta Was this translation helpful? Give feedback.
-
Thanks! (nice diagram!) I'm running yosys for xilinx. The vector is 256 wide, the vector elements are 633 bits wide. Used in the muxN of a 256-vector of signals, fmapping the (!!) timewise along the signals, as exhibited in the post at head of thread, that is 66231 LCs. Can you confirm?
(I'd still like to know how to use dtfold! It may be useful! For one thing I could save yosys optimization time even if it does manage to come out with that tree structure -- which is a feat of improbable reverse engineering that i am utterly amazed by) Ironically, I like this message from yosys:
|
Beta Was this translation helpful? Give feedback.
-
Try this:
Pattern matching on the |
Beta Was this translation helpful? Give feedback.
-
@christiaanb Yes, that works! No "KnownNat n" in the definition of the combinator but pattern match on SNat as first argument instead. That seems like a technique! |
Beta Was this translation helpful? Give feedback.
-
With dtfold implementing !!, the results after synthesis with yosys for xilinx are the same as when using the standard !!. So yosys seems to automatically make a tree structure for xilinx too ... (256-way 633-bit wide multiplexer)
Does anyone have any better ideas? This is very costly for such trivial functionality. Is it possible to use three-valued logic somehow? I could power down all but one of the incoming vector of streams very cheaply with a demuxer driven from the stream of incoming indices, and just join all the wires without any gating .... Thanks for all the inputs! |
Beta Was this translation helpful? Give feedback.
Try this:
Pattern matching on the
SNat
(of typeSNat n
) introduces theKnownNat n
constraint for anything in scope of the pattern match. As a result, you no longer need theKnownNat n
constraint in the type signature ofcombi
, since anything inside the definition ofcombi
will now get theKnownNat n
out of theSNat
.