hardware-edsl-0.1.2: src/Language/Embedded/Hardware/Expression/Frontend.hs
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
module Language.Embedded.Hardware.Expression.Frontend where
import qualified Language.VHDL as V
import Language.Embedded.Hardware.Interface
import Language.Embedded.Hardware.Expression.Syntax hiding (Term, Factor, Primary)
import Language.Embedded.Hardware.Expression.Hoist
import Language.Embedded.Hardware.Expression.Represent
import Language.Embedded.Hardware.Expression.Represent.Bit
import qualified Language.Embedded.VHDL.Monad.Expression as V
import Data.Typeable (Typeable)
import qualified Data.Bits as B (Bits)
import Prelude hiding (not, and, or, abs, rem, div, mod, exp)
import qualified Prelude as P
import GHC.TypeLits
--------------------------------------------------------------------------------
-- * ...
--------------------------------------------------------------------------------
type Hardware exp =
( Expr exp
, Rel exp
, Shift exp
, Simple exp
, Term exp
, Factor exp
, Primary exp)
--------------------------------------------------------------------------------
-- | Logical operators.
class Expr exp where
true :: exp Bool
false :: exp Bool
and :: exp Bool -> exp Bool -> exp Bool
or :: exp Bool -> exp Bool -> exp Bool
xor :: exp Bool -> exp Bool -> exp Bool
xnor :: exp Bool -> exp Bool -> exp Bool
nand :: exp Bool -> exp Bool -> exp Bool
nor :: exp Bool -> exp Bool -> exp Bool
instance Expr HExp where
true = value True
false = value False
and = sugarT And
or = sugarT Or
xor = sugarT Xor
xnor = sugarT Xnor
nand = sugarT Nand
nor = sugarT Nor
--------------------------------------------------------------------------------
-- | Relational operators.
class Rel exp where
eq :: (HType a, Eq a) => exp a -> exp a -> exp Bool
neq :: (HType a, Eq a) => exp a -> exp a -> exp Bool
lt :: (HType a, Ord a) => exp a -> exp a -> exp Bool
lte :: (HType a, Ord a) => exp a -> exp a -> exp Bool
gt :: (HType a, Ord a) => exp a -> exp a -> exp Bool
gte :: (HType a, Ord a) => exp a -> exp a -> exp Bool
instance Rel HExp where
eq = sugarT Eq
neq = sugarT Neq
lt = sugarT Lt
lte = sugarT Lte
gt = sugarT Gt
gte = sugarT Gte
--------------------------------------------------------------------------------
-- | Shift operators.
class Shift exp where
sll :: (HType a, B.Bits a) => exp a -> exp Integer -> exp a
srl :: (HType a, B.Bits a) => exp a -> exp Integer -> exp a
sla :: (HType a, B.Bits a) => exp a -> exp Integer -> exp a
sra :: (HType a, B.Bits a) => exp a -> exp Integer -> exp a
rol :: (HType a, B.Bits a) => exp a -> exp Integer -> exp a
ror :: (HType a, B.Bits a) => exp a -> exp Integer -> exp a
instance Shift HExp where
sll = sugarT Sll
srl = sugarT Srl
sla = sugarT Sla
sra = sugarT Sra
rol = sugarT Rol
ror = sugarT Ror
--------------------------------------------------------------------------------
-- | Adding operators.
class Simple exp where
neg :: (HType a, Num a) => exp a -> exp a
add :: (HType a, Num a) => exp a -> exp a -> exp a
sub :: (HType a, Num a) => exp a -> exp a -> exp a
cat :: ( KnownNat n, KnownNat m, KnownNat (n + m), Typeable (n + m))
=> exp (Bits n) -> exp (Bits m) -> exp (Bits (n + m))
instance Simple HExp where
neg = sugarT Neg
add = sugarT Add
sub = sugarT Sub
cat = sugarT Cat
--------------------------------------------------------------------------------
-- | Multiplying operators.
class Term exp where
mul :: (HType a, Num a) => exp a -> exp a -> exp a
div :: (HType a, Integral a) => exp a -> exp a -> exp a
mod :: (HType a, Integral a) => exp a -> exp a -> exp a
rem :: (HType a, Integral a) => exp a -> exp a -> exp a
instance Term HExp where
mul = sugarT Mul
div = sugarT Div
mod = sugarT Mod
rem = sugarT Rem
--------------------------------------------------------------------------------
-- | Miscellaneous operators.
class Factor exp where
exp :: (HType a, Num a, HType b, Integral b) => exp a -> exp b -> exp a
abs :: (HType a, Num a) => exp a -> exp a
not :: exp Bool -> exp Bool
instance Factor HExp where
exp = sugarT Exp
abs = sugarT Abs
not = sugarT Not
--------------------------------------------------------------------------------
-- | Primary operations.
class Primary exp where
value :: HType a => a -> exp a
name :: HType a => String -> exp a
cast :: (HType a, HType b) => (a -> b) -> exp a -> exp b
instance Primary HExp where
value = sugarT . Literal
name n = sugarT (Name (V.NSimple (V.Ident n)))
cast f = sugarT (Conversion f)
-- | Creates a variable from a string.
var :: (Primary exp, HType a) => String -> exp a
var = name
-- | Converts an integral (signed/unsigned/integer) to an integer.
toInteger :: (Primary exp, HType a, Integral a) => exp a -> exp Integer
toInteger = cast (fromIntegral)
-- | Converts an integral to a signed value.
toSigned :: (Primary exp, HType a, HType b, Integral a, Num b) => exp a -> exp b
toSigned = cast (fromIntegral)
-- | Converts an integral to a unsigned value.
toUnsigned :: (Primary exp, HType a, HType b, Integral a, Num b) => exp a -> exp b
toUnsigned = cast (fromIntegral)
-- | Converts an integral to its bit representation.
toBits :: (Primary exp, HType a, HType (Bits b), Integral a, KnownNat b) => exp a -> exp (Bits b)
toBits = cast (bitFromInteger . fromIntegral)
--------------------------------------------------------------------------------
fromBits :: (Primary exp, HType (Bits a), HType b, Num b, KnownNat a) => exp (Bits a) -> exp b
fromBits = cast (fromIntegral . bitToInteger)
--------------------------------------------------------------------------------
-- I should probably not support most of these, as they can't implement the
-- interfaces fully. Would perhaps be better to implement my own versions
-- of the type classes.
instance (HType a, Eq a) => Eq (HExp a)
where
(==) = error "VHDL: equality checking is not supported"
instance (HType a, Ord a) => Ord (HExp a)
where
compare = error "VHDL: compare is not supported"
max = error "VHDL: max is not supported"
min = error "VHDL: min is not supported"
instance (HType a, Bounded a) => Bounded (HExp a)
where
minBound = value minBound
maxBound = value maxBound
instance (HType a, Enum a) => Enum (HExp a)
where
toEnum = error "VHDL: toEnum is not supported"
fromEnum = error "VHDL: fromEnum is not supported"
instance (HType a, Real a) => Real (HExp a)
where
toRational = error "VHDL: toRational is not supported"
instance (HType a, Num a) => Num (HExp a)
where
fromInteger = value . fromInteger
(+) = add
(-) = sub
(*) = mul
abs = abs
signum = error "VHDL: signum is not supported"
instance (HType a, Integral a) => Integral (HExp a)
where
quot = error "VHDL: quotient is not supported"
rem = rem
div = div
mod = mod
quotRem a b = (quot a b, rem a b)
divMod a b = (div a b, mod a b)
toInteger = error "VHDL: toInteger is not supported"
instance (HType a, Fractional a) => Fractional (HExp a)
where
(/) = error "VHDL: floating point division is not _yet_ supported"
recip = (/) (value 1)
fromRational = error "VHDL: fromRational is not supported"
--------------------------------------------------------------------------------