Skip to content

Commit 5a86ccf

Browse files
authored
Make sure the VHDL BB for Signed.fromInteger can handle any Netlist Expr (#2157)
Previously it could only handle Identifier. (And Literal, which is handled seperately in Clash.Backend.VHDL.expr_) I've also renamed it to make it clear this blackbox is VHDL only. Fixes #2149
1 parent e502f16 commit 5a86ccf

File tree

6 files changed

+46
-12
lines changed

6 files changed

+46
-12
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
FIXED: The VHDL BB for Signed.fromInteger can now handle any Netlist Expr as input [#2149](https://github.com/clash-lang/clash-compiler/issues/2149)

clash-lib/prims/vhdl/Clash_Sized_Internal_Signed.primitives.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@
9797
kind: Expression
9898
type: 'fromInteger# ::
9999
KnownNat n => Integer -> Signed (n :: Nat)'
100-
templateFunction: Clash.Primitives.Sized.Signed.fromIntegerTF
100+
templateFunction: Clash.Primitives.Sized.Signed.fromIntegerTFvhdl
101101
workInfo: Never
102102
- BlackBox:
103103
name: Clash.Sized.Internal.Signed.toEnum#

clash-lib/src/Clash/Driver.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -596,7 +596,7 @@ knownTemplateFunctions =
596596
, ('P.alteraPllQsysTF, P.alteraPllQsysTF)
597597
, ('P.alteraPllTF, P.alteraPllTF)
598598
, ('P.altpllTF, P.altpllTF)
599-
, ('P.fromIntegerTF, P.fromIntegerTF)
599+
, ('P.fromIntegerTFvhdl, P.fromIntegerTFvhdl)
600600
]
601601

602602
-- | Compiles blackbox functions and parses blackbox templates.
Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
{-|
2-
Copyright : (C) 2021 QBayLogic
2+
Copyright : (C) 2021-2022, QBayLogic
33
License : BSD2 (see the file LICENSE)
44
Maintainer : QBayLogic B.V. <[email protected]>
55
66
VHDL Blackbox implementations for "Clash.Sized.Internal.Signed.toInteger#".
77
-}
88

99
{-# LANGUAGE OverloadedStrings #-}
10-
module Clash.Primitives.Sized.Signed (fromIntegerTF) where
10+
module Clash.Primitives.Sized.Signed (fromIntegerTFvhdl) where
1111

1212
import Control.Monad.State (State)
1313
import Data.Monoid (Ap(getAp))
@@ -18,8 +18,8 @@ import Clash.Netlist.Types
1818
(BlackBoxContext (..), Expr (..), HWType (..), Literal (..), Modifier (..),
1919
TemplateFunction (..))
2020

21-
fromIntegerTF :: TemplateFunction
22-
fromIntegerTF = TemplateFunction used valid fromIntegerTFTemplate
21+
fromIntegerTFvhdl :: TemplateFunction
22+
fromIntegerTFvhdl = TemplateFunction used valid fromIntegerTFTemplateVhdl
2323
where
2424
used = [0,1]
2525
valid bbCtx = case bbInputs bbCtx of
@@ -28,16 +28,19 @@ fromIntegerTF = TemplateFunction used valid fromIntegerTFTemplate
2828
_ -> False
2929
_ -> False
3030

31-
fromIntegerTFTemplate
31+
fromIntegerTFTemplateVhdl
3232
:: Backend s
3333
=> BlackBoxContext
3434
-> State s Doc
35-
fromIntegerTFTemplate bbCtx = getAp $ do
36-
let [(Literal _ (NumLit sz),_,_), (i@(Identifier iV m), Signed szI, _)] = bbInputs bbCtx
35+
fromIntegerTFTemplateVhdl bbCtx = getAp $ do
36+
let [(Literal _ (NumLit sz),_,_), (i, Signed szI, _)] = bbInputs bbCtx
3737
case compare sz (toInteger szI) of
38-
LT -> let sl = Sliced (Signed szI,fromInteger sz-1,0)
39-
m1 = Just (maybe sl (`Nested` sl) m)
40-
in expr False (Identifier iV m1)
38+
LT -> case i of
39+
Identifier iV m ->
40+
let sl = Sliced (Signed szI,fromInteger sz-1,0)
41+
m1 = Just (maybe sl (`Nested` sl) m)
42+
in expr False (Identifier iV m1)
43+
_ -> "signed(std_logic_vector(resize(unsigned(std_logic_vector(" <> expr False i <> "))," <> expr False (Literal Nothing (NumLit sz)) <> ")))"
4144
EQ -> expr False i
4245
GT -> "resize" <> tupled (sequenceA [expr False i
4346
,expr False (Literal Nothing (NumLit sz))])

tests/Main.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -637,6 +637,7 @@ runClashTest = defaultMain $ clashTestRoot
637637
, runTest "Strict" def
638638
, runTest "T1019" def{hdlSim=False}
639639
, runTest "T1351" def
640+
, runTest "T2149" def
640641
, outputTest "UndefinedConstantFolding" def{ghcFlags=["-itests/shouldwork/Numbers"]}
641642
, runTest "UnsignedZero" def
642643
]

tests/shouldwork/Numbers/T2149.hs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
module T2149 where
2+
3+
import Clash.Prelude
4+
import Clash.Explicit.Testbench
5+
6+
topEntity :: Word -> Signed 8
7+
topEntity = fromIntegral
8+
{-# NOINLINE topEntity #-}
9+
10+
testBench :: Signal System Bool
11+
testBench = done
12+
where
13+
testInput = stimuliGenerator clk rst (negNr 42 :> posNr 41 :> negNr (-40) :> posNr (-39) :> Nil)
14+
expectedOutput = outputVerifier' clk rst (42 :> 41 :> (-40) :> (-39) :> Nil)
15+
done = expectedOutput (topEntity <$> testInput)
16+
clk = tbSystemClockGen (not <$> done)
17+
rst = systemResetGen
18+
19+
20+
-- | Use input as the lower byte of the output, and set its bits 31 and 63
21+
--
22+
-- By setting both bit 31 and 63, the sign-bit of the intermediate Integer is always set,
23+
-- no matter if we're representing it as a signed 64 or 32 bit number.
24+
negNr :: Signed 8 -> Word
25+
negNr x = unpack (resize (pack x)) .|. bit 31 .|. bit 63
26+
27+
28+
posNr :: Signed 8 -> Word
29+
posNr x = unpack (resize (pack x)) .|. bit 30

0 commit comments

Comments
 (0)