{-# LANGUAGE TemplateHaskell, DeriveDataTypeable, MultiParamTypeClasses,
FunctionalDependencies, TypeSynonymInstances #-}
module ForSyDe.Deep.Bit (Bit(..),
not,
bitToBool,
boolToBit,
toBitVector8,
fromBitVector8,
toBitVector16,
fromBitVector16,
toBitVector32,
fromBitVector32,
toBitVector64,
fromBitVector64,
fixmul8) where
import Language.Haskell.TH.Lift
import Data.Int
import Data.Bits
import Data.Data (Data, Typeable)
import Prelude hiding (not)
import Data.Param.FSVec (FSVec, reallyUnsafeVector)
import qualified Data.Param.FSVec as V
import Data.TypeLevel.Num (D8,D16,D32,D64,Nat)
data Bit = H
| L
deriving (Eq, Show, Data, Typeable)
$(deriveLift1 ''Bit)
-- | Not operation over bits
not :: Bit -> Bit
not = complement
instance Bits Bit where
H .&. x = x
L .&. _ = L
H .|. _ = H
L .|. x = x
xor H L = H
xor L H = H
xor _ _ = L
complement L = H
complement H = L
shift x 0 = x
shift _ _ = L
rotate x _ = x
bitSize _ = 1
isSigned _ = False
-- Phony instance of Num
instance Num Bit where
H + L = H
H + H = L
L + x = x
-- since they are unsigned and there are only two elements, (-) == (+)
(-) = (+)
-- multiplication is equivalent to (.&.)
(*) = (.&.)
-- since a bit is unsigned, it is equivalent to identity
abs = id
signum _ = L
fromInteger n = if n<=0 then L else H
-- | Convert a bit to a boolean
bitToBool :: Bit -> Bool
bitToBool H = True
bitToBool L = False
-- | Convert a boolean to a bit
boolToBit :: Bool -> Bit
boolToBit True = H
boolToBit False = L
toBitVector8 :: Int8 -> FSVec D8 Bit
toBitVector8 = reallyUnsafeToBitVector
fromBitVector8 :: FSVec D8 Bit -> Int8
fromBitVector8 = fromBitVectorDef 0
toBitVector16 :: Int16 -> FSVec D16 Bit
toBitVector16 = reallyUnsafeToBitVector
fromBitVector16 :: FSVec D16 Bit -> Int16
fromBitVector16 = fromBitVectorDef 0
toBitVector32 :: Int32 -> FSVec D32 Bit
toBitVector32 = reallyUnsafeToBitVector
fromBitVector32 :: FSVec D32 Bit -> Int32
fromBitVector32 = fromBitVectorDef 0
toBitVector64 :: Int64 -> FSVec D64 Bit
toBitVector64 = reallyUnsafeToBitVector
fromBitVector64 :: FSVec D64 Bit -> Int64
fromBitVector64 = fromBitVectorDef 0
fixmul8 :: Int8 -> Int8 -> Int8
fixmul8 a b = fromIntegral $ (fromIntegral a * fromIntegral b::Int16) `div` 128
{- This would have been much more convenient
But it makes things really complicated int he VHDL
backend
-- | Datatypes which can be converted to and from
-- vectors of bits
class BitStream d s | d -> s where
-- | convert a data type to a bit vector
toBitVector :: d -> FSVec s Bit
-- | get a datatype from a bit vector
fromBitVector :: FSVec s Bit -> d
instance BitStream Int8 D8 where
toBitVector = reallyUnsafeToBitVector
fromBitVector = fromBitVectorDef 0
instance BitStream Int16 D16 where
toBitVector = reallyUnsafeToBitVector
fromBitVector = fromBitVectorDef 0
instance BitStream Int32 D32 where
toBitVector = reallyUnsafeToBitVector
fromBitVector = fromBitVectorDef 0
instance BitStream Int64 D64 where
toBitVector = reallyUnsafeToBitVector
fromBitVector = fromBitVectorDef 0
-}
-------------------
-- Helper functions
-------------------
reallyUnsafeToBitVector :: Bits a => a -> FSVec s Bit
reallyUnsafeToBitVector x =
reallyUnsafeVector $ map (boolToBit.(testBit x)) [size-1,size-2..0]
where size = bitSize x
-- | version of fromBitVector supplying a default initial value from which to
-- start working
fromBitVectorDef :: (Bits a, Nat s) => a -> FSVec s Bit -> a
fromBitVectorDef def vec = fst $ V.foldr f (def, 0) vec
where f e (ac, pos) = (copyBit e ac pos, pos+1)
copyBit H = setBit
copyBit L = clearBit