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

Verilog/SystemVerilog generation error: "Can't match template for ...Unsigned.rotateR#" #169

Closed
thoughtpolice opened this Issue Aug 16, 2016 · 3 comments

Comments

Projects
None yet
2 participants
@thoughtpolice
Contributor

thoughtpolice commented Aug 16, 2016

With:

$ clash --version
CAES Language for Synchronous Hardware, version 0.6.22 (using clash-lib, version: 0.6.20)

Consider the following circuit, which is the NORX F permutation, with the recommended 4 rounds (it is almost a transliteration of Figure 2.4, pg 9 in the NORX v2.0 specification):

module NORX where
import Data.Bits
import CLaSH.Prelude

type W = Unsigned 32

norx :: Vec 16 W -> Vec 16 W
norx inp = iterate d5 f inp !! 4

f :: Vec 16 W -> Vec 16 W
f inp = result
  where
    (s0:>s1:>s2:>s3:>s4:>s5:>s6:>s7:>s8:>s9:>s10:>s11:>s12:>s13:>s14:>s15:>_) = inp

    -- Column round
    (t0, t4, t8,  t12) = g (s0, s4, s8,  s12)
    (t1, t5, t9,  t13) = g (s1, s5, s9,  s13)
    (t2, t6, t10, t14) = g (s2, s6, s10, s14)
    (t3, t7, t11, t15) = g (s3, s7, s11, s15)
    -- Diagonal round
    (u0, u5, u10, u15) = g (t0, t5, t10, t15)
    (u1, u6, u11, u12) = g (t1, t6, t11, t12)
    (u2, u7, u8,  u13) = g (t2, t7, t8,  t13)
    (u3, u4, u9,  u14) = g (t3, t4, t9,  t14)

    result = (u0:>u1:>u2:>u3:>u4:>u5:>u6:>u7:>u8:>u9:>u10:>u11:>u12:>u13:>u14:>u15:>Nil)

g :: (W, W, W, W) -> (W, W, W, W)
g (a, b, c, d) = (a'', b'', c'', d'')
  where
    a'  = h a b
    d'  = (a' `xor` d)   `rotateR` 8
    c'  = h c d'
    b'  = (b `xor` c')   `rotateR` 11
    a'' = h a' b'
    d'' = (a'' `xor` d') `rotateR` 16
    c'' = h c' d''
    b'' = (b' `xor` c'') `rotateR` 31

h :: W -> W -> W
h x y = (x `xor` y) `xor` ((x .&. y) `shiftL` 1)

--------------------------------------------------------------------------------
-- HDL export interface

topEntity :: Vec 16 W -> Vec 16 W
topEntity = norx

testInput :: Signal (Vec 16 (Unsigned 32))
testInput = stimuliGenerator $(v [ (0 :: Unsigned 32):>1:>2:>3:>4:>5:>6:>7:>8:>9:>10:>11:>12:>13:>14:>15:>Nil ] )

expectedOutput :: Signal (Vec 16 (Unsigned 32)) -> Signal Bool
expectedOutput = outputVerifier $(v [ (0x99a0283a :: Unsigned 32)
                                    :> 0x16c4b42e
                                    :> 0x6e7fa00b
                                    :> 0x7d075c66
                                    :> 0x65c1af81
                                    :> 0xee254c00
                                    :> 0x126631b6
                                    :> 0xf8915260
                                    :> 0x083181d5
                                    :> 0x85dc0152
                                    :> 0x1a44a1f3
                                    :> 0x7ba61b1a
                                    :> 0x37dde5df
                                    :> 0x078203d3
                                    :> 0x9b3c0701
                                    :> 0x9ce6be37
                                    :> Nil ])

This works and passes the test vector:

$ clash --interactive norx.hs
CLaSHi, version 0.6.22 (using clash-lib, version 0.6.20):
http://www.clash-lang.org/  :? for help
[1 of 1] Compiling NORX             ( norx.hs, interpreted ) [GHC.TypeLits.Normalise changed]
Ok, modules loaded: NORX.
*NORX> sampleN 2 $ expectedOutput (fmap topEntity testInput)
[False,True]
*NORX>

I expect that I should be able to compile this (very simple) circuit to Verilog or SystemVerilog, but I can't. VHDL does work:

$ clash --interactive norx.hs
CLaSHi, version 0.6.22 (using clash-lib, version 0.6.20):
http://www.clash-lang.org/  :? for help
[1 of 1] Compiling NORX             ( norx.hs, interpreted )
Ok, modules loaded: NORX.
*NORX> :vhdl
[1 of 1] Compiling NORX             ( norx.hs, norx.o )
Loading dependencies took 1.257921s
Applied 42 transformations
Normalisation took 1.391006s
Netlist generation took 0.348471s
Applied 73 transformations
Applied 132 transformations
Testbench generation took 0.31372s
Total compilation took 3.326497s
*NORX> :verilog
[1 of 1] Compiling NORX             ( norx.hs, norx.o )
Loading dependencies took 1.363019s
Applied 38 transformations
Normalisation took 1.452286s
*** Exception: CLaSH.Netlist.BlackBox(92): Can't match template for "CLaSH.Sized.Internal.Unsigned.rotateR#" :

[C "// rotateR begin\nwire [2*",L 0,C "-1:0] ",GenSym [C "u"] 0,C ";\nassign ",Sym "" 0,C " = {",I 1,C ",",I 1,C "} >> ",I 2,C ";\nassign ",O,C " = ",Sym "" 0,C "[",L 1,C "-1 : 0];\n// rotateR end"]

with context:

Context {bbResult = (Left (Identifier "app_arg_0" Nothing),Unsigned 32), bbInputs = [(Left (Literal (Just (Signed 64,64)) (NumLit 32)),Signed 64,True),(Left (Identifier "app_arg" Nothing),Unsigned 32,False),(Left (BlackBoxE "GHC.Types.I#" [I 0] (Context {bbResult = (Left (Identifier "app_arg_0" Nothing),Signed 64), bbInputs = [(Left (Literal (Just (Signed 64,64)) (NumLit 31)),Signed 64,True)], bbFunctions = fromList []}) True),Signed 64,True)], bbFunctions = fromList []}

*NORX>

SystemVerilog fails in a very similar manner to this, with basically the exact same error message.

@thoughtpolice

This comment has been minimized.

Show comment
Hide comment
@thoughtpolice

thoughtpolice Aug 17, 2016

Contributor

I think I see the problem:

assign ~RESULT = ~SYM[0][~LIT[1]-1 : 0];

~LIT[1] should be ~LIT[0], which refers to the KnownNat constraint. Otherwise, verifyBlackBoxContext will check literals against the inputs context, and return the 3rd Tuple component, which I believe specifies whether it's constant or not - which is (Left (Identifier "app_arg" Nothing),Unsigned 32,False) in this case.

Contributor

thoughtpolice commented Aug 17, 2016

I think I see the problem:

assign ~RESULT = ~SYM[0][~LIT[1]-1 : 0];

~LIT[1] should be ~LIT[0], which refers to the KnownNat constraint. Otherwise, verifyBlackBoxContext will check literals against the inputs context, and return the 3rd Tuple component, which I believe specifies whether it's constant or not - which is (Left (Identifier "app_arg" Nothing),Unsigned 32,False) in this case.

@thoughtpolice

This comment has been minimized.

Show comment
Hide comment
@thoughtpolice

thoughtpolice Aug 17, 2016

Contributor

Yes, I've confirmed this is the problem, fixing my primitives .json file in place makes this example work.

Contributor

thoughtpolice commented Aug 17, 2016

Yes, I've confirmed this is the problem, fixing my primitives .json file in place makes this example work.

@christiaanb

This comment has been minimized.

Show comment
Hide comment
@christiaanb

christiaanb Aug 17, 2016

Contributor

Thanks for the report, and for finding the source of the bug so quickly.

Contributor

christiaanb commented Aug 17, 2016

Thanks for the report, and for finding the source of the bug so quickly.

christiaanb added a commit that referenced this issue Sep 6, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment