hardware-edsl-0.1.6: src/Language/Embedded/Hardware/Expression/Represent.hs
{-# LANGUAGE GADTs #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE FlexibleContexts #-}
module Language.Embedded.Hardware.Expression.Represent where
import Language.Embedded.Hardware.Expression.Represent.Bit
import Language.Embedded.VHDL (VHDL, MonadV)
import Language.Embedded.VHDL.Monad (newSym, addLibrary, addImport)
import Language.Embedded.VHDL.Monad.Type
import Language.Embedded.VHDL.Monad.Util (printBits)
import Data.Char (isDigit)
import Data.Int
import Data.Word
import Data.Proxy (Proxy(..))
import Data.Typeable (Typeable)
import GHC.TypeLits
--------------------------------------------------------------------------------
-- * Inhabited types.
--------------------------------------------------------------------------------
-- | Inhabited types, that is, types with a base element.
class Inhabited a
where
-- | Ground value.
reset :: a
instance Inhabited Bool where reset = False
instance Inhabited Int8 where reset = 0
instance Inhabited Int16 where reset = 0
instance Inhabited Int32 where reset = 0
instance Inhabited Int64 where reset = 0
instance Inhabited Word8 where reset = 0
instance Inhabited Word16 where reset = 0
instance Inhabited Word32 where reset = 0
instance Inhabited Word64 where reset = 0
instance Inhabited Int where reset = 0
instance Inhabited Integer where reset = 0
instance Inhabited Float where reset = 0
instance Inhabited Double where reset = 0
instance forall n . KnownNat n => Inhabited (Bits n)
where
reset = bitFromInteger 0
--------------------------------------------------------------------------------
-- * Sized types.
--------------------------------------------------------------------------------
-- | Types with a known size.
class Sized a
where
-- | Bits required to represent values of type 'a'.
bits :: proxy a -> Integer
instance Sized Bool where bits _ = 1
instance Sized Int8 where bits _ = 8
instance Sized Int16 where bits _ = 16
instance Sized Int32 where bits _ = 32
instance Sized Int64 where bits _ = 64
instance Sized Word8 where bits _ = 8
instance Sized Word16 where bits _ = 16
instance Sized Word32 where bits _ = 32
instance Sized Word64 where bits _ = 64
instance Sized Int where bits _ = 32
instance Sized Integer where bits _ = 64
instance Sized Float where bits _ = 32
instance Sized Double where bits _ = 64
instance forall n . KnownNat n => Sized (Bits n)
where
bits _ = ni (Proxy :: Proxy n)
--------------------------------------------------------------------------------
-- * Representable types.
--------------------------------------------------------------------------------
-- | Representation of primitive hardware types.
data TypeRep a
where
-- booleans.
BoolT :: TypeRep Bool
-- signed numbers.
Int8T :: TypeRep Int8
Int16T :: TypeRep Int16
Int32T :: TypeRep Int32
Int64T :: TypeRep Int64
-- unsigned numbers.
Word8T :: TypeRep Word8
Word16T :: TypeRep Word16
Word32T :: TypeRep Word32
Word64T :: TypeRep Word64
-- integers.
IntT :: TypeRep Int
IntegerT :: TypeRep Integer
-- floating point numbers.
FloatT :: TypeRep Float
DoubleT :: TypeRep Double
-- variable sized bit values (todo).
BitsT :: KnownNat n => TypeRep (Bits n)
deriving instance Eq (TypeRep a)
deriving instance Show (TypeRep a)
deriving instance Typeable (TypeRep a)
isBool :: TypeRep a -> Bool
isBool BoolT = True
isBool _ = False
isSigned :: TypeRep a -> Bool
isSigned Int8T = True
isSigned Int16T = True
isSigned Int32T = True
isSigned Int64T = True
isSigned _ = False
isUnsigned :: TypeRep a -> Bool
isUnsigned Word8T = True
isUnsigned Word16T = True
isUnsigned Word32T = True
isUnsigned Word64T = True
isInteger :: TypeRep a -> Bool
isInteger IntT = True
isInteger IntegerT = True
isInteger _ = False
isFloat :: TypeRep a -> Bool
isFloat FloatT = True
isFloat DoubleT = True
isFloat _ = False
--------------------------------------------------------------------------------
-- | Primitive hardware types.
class (Eq a, Show a, Typeable a, Inhabited a, Sized a) => PrimType a
where
typeRep :: TypeRep a
instance PrimType Bool where typeRep = BoolT
instance PrimType Int8 where typeRep = Int8T
instance PrimType Int16 where typeRep = Int16T
instance PrimType Int32 where typeRep = Int32T
instance PrimType Int64 where typeRep = Int64T
instance PrimType Word8 where typeRep = Word8T
instance PrimType Word16 where typeRep = Word16T
instance PrimType Word32 where typeRep = Word32T
instance PrimType Word64 where typeRep = Word64T
instance PrimType Int where typeRep = IntT
instance PrimType Integer where typeRep = IntegerT
instance PrimType Float where typeRep = FloatT
instance PrimType Double where typeRep = DoubleT
instance forall n . KnownNat n => PrimType (Bits n)
where
typeRep = BitsT
--------------------------------------------------------------------------------
-- | Print a value.
primTypeVal :: forall a . PrimType a => a -> String
primTypeVal a = case typeRep :: TypeRep a of
BoolT -> if a then "\'1\'" else "\'0\'"
t -> show a
-- | Print a value as its bit representation.
primTypeBits :: forall a . PrimType a => a -> String
primTypeBits a = case typeRep :: TypeRep a of
BoolT -> primTypeVal a
Int8T -> printBits 8 a
Int16T -> printBits 16 a
Int32T -> printBits 32 a
Int64T -> printBits 64 a
Word8T -> printBits 8 a
Word16T -> printBits 16 a
Word32T -> printBits 32 a
Word64T -> printBits 64 a
IntT -> error "todo: print ints as bits."
IntegerT -> error "todo: print integers as bits."
FloatT -> error "todo: print floats as bits."
DoubleT -> error "todo: print doubles as bits."
-- | Hardware type representation of a primitive type.
primTypeRep :: forall a . PrimType a => Proxy a -> Type
primTypeRep _ = case typeRep :: TypeRep a of
BoolT -> std_logic
Int8T -> signed8
Int16T -> signed16
Int32T -> signed32
Int64T -> signed64
Word8T -> usigned8
Word16T -> usigned16
Word32T -> usigned32
Word64T -> usigned64
IntT -> integer Nothing -- todo: might be wrong.
IntegerT -> integer Nothing -- todo: migth be wrong.
FloatT -> float
DoubleT -> double
BitsT -> primTypeRepBits (Proxy :: Proxy a)
primTypeRepBits :: forall n. KnownNat n => Proxy (Bits n) -> Type
primTypeRepBits _ = std_logic_vector size
where size = fromInteger (ni (undefined :: Bits n))
-- | Declare the necessary imports/packages to support a primitive type.
primTypeDeclare :: forall m a. (MonadV m, PrimType a) => Proxy a -> m ()
primTypeDeclare p = case typeRep :: TypeRep a of
BoolT -> declareBoolean
Int8T -> declareNumeric
Int16T -> declareNumeric
Int32T -> declareNumeric
Int64T -> declareNumeric
Word8T -> declareNumeric
Word16T -> declareNumeric
Word32T -> declareNumeric
Word64T -> declareNumeric
IntT -> declareNumeric
IntegerT -> declareNumeric
FloatT -> declareFloating
DoubleT -> declareFloating
BitsT -> declareBoolean
-- | Declare a primitive hardware type and get back its representation.
declareType :: (MonadV m, PrimType a) => Proxy a -> m Type
declareType proxy = primTypeDeclare proxy >> return (primTypeRep proxy)
-- | Declare the necessary libraries to support boolean operations.
declareBoolean :: MonadV m => m ()
declareBoolean =
do addLibrary "IEEE"
addImport "IEEE.std_logic_1164"
-- | Declare the necessary libraries to support numerical operations.
declareNumeric :: MonadV m => m ()
declareNumeric =
do addLibrary "IEEE"
addImport "IEEE.std_logic_1164"
addImport "IEEE.numeric_std"
-- | Declare the necessary libraries to support floating point operations.
declareFloating :: MonadV m => m ()
declareFloating =
do addLibrary "IEEE"
addImport "IEEE.float_pkg"
--------------------------------------------------------------------------------