clash-lib-1.10.3: src/Clash/Primitives/GHC/Literal.hs
{-|
Copyright : (C) 2019, Myrtle Software Ltd
License : BSD2 (see the file LICENSE)
Maintainer : Christiaan Baaij <christiaan.baaij@gmail.com>
Blackbox generation for literal data constructors. (System)Verilog only!
-}
{-# LANGUAGE OverloadedStrings #-}
module Clash.Primitives.GHC.Literal
( assign
, signed
, signedLiteral
, unsigned
, unsignedLiteral
, literalTF
)
where
import Data.List.NonEmpty (NonEmpty)
import qualified Data.List.NonEmpty as NE
import qualified Data.Text.Lazy as LT
import Data.Text
(Text, stripPrefix, stripSuffix, unpack)
import Data.Text.Extra (showtl)
import Text.Read (readMaybe)
import Clash.Core.Term (Term)
import Clash.Core.Type (Type)
import Clash.Netlist.Types (BlackBox)
import Clash.Netlist.BlackBox.Types
(BlackBoxFunction, Element(Text), BlackBoxMeta)
unsigned :: Element -> [Element]
unsigned el = [Text "$unsigned(", el, Text ")"]
signed :: Element -> [Element]
signed el = [Text "$signed(", el, Text ")"]
assign :: Element -> [Element] -> [Element]
assign lhs rhs = Text "assign " : lhs : Text " = " : rhs ++ [Text ";"]
signedLiteral :: Int -> Integer -> Element
signedLiteral wordSize wordVal =
Text (LT.concat [ if wordVal < 0 then "-" else ""
, showtl wordSize
, "'sd"
, showtl (abs wordVal)
])
unsignedLiteral :: Int -> Integer -> Element
unsignedLiteral wordSize wordVal =
Text (LT.concat [ if wordVal < 0 then "-" else ""
, showtl wordSize
, "'d"
, showtl (abs wordVal)
])
-- | Parse integer in strings of the form "GHC.Word.WordX#" where
-- "GHC.Word.Word" is the prefix given. The first prefix that matches wins.
readSize :: NonEmpty Text -> Text -> Maybe Int
readSize prefixes nm0 = do
let go [] = Nothing
go (p:ps) = case stripPrefix p nm0 of
Just nm1 -> Just nm1
Nothing -> go ps
nm1 <- go (NE.toList prefixes)
nm2 <- stripSuffix "#" nm1
readMaybe (unpack nm2)
-- | Constructs "clean" literals.
literalTF
:: NonEmpty Text
-- ^ Base names of constructors (for example: @"GHC.Word.W" :| ["GHC.Internal.Word.W"]@).
-- The 'GHC.Internal.*' variant is needed for GHC >= 9.14, which moved the
-- constructors into 'ghc-internal'; 'base' re-exports them.
-> (Bool -> [Either Term Type] -> Int -> (BlackBoxMeta, BlackBox))
-- ^ Functions processing
-> BlackBoxFunction
literalTF baseNames tf isDecl primName args _resTy = return $
case readSize baseNames primName of
Nothing ->
Left (concat ["Can only make blackboxes for '", unpack (NE.head baseNames), "X#'"])
Just n ->
Right (tf isDecl args n)