hardware-edsl-0.1.5: src/Language/Embedded/Hardware/Command/Frontend.hs
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE PolyKinds #-}
module Language.Embedded.Hardware.Command.Frontend where
import Language.Embedded.VHDL (Mode(..))
import Language.Embedded.Hardware.Interface
import Language.Embedded.Hardware.Command.CMD
import Language.Embedded.Hardware.Expression.Represent
import Language.Embedded.Hardware.Expression.Represent.Bit
import Control.Monad.Operational.Higher
import Data.Ix (Ix)
import Data.IORef (readIORef)
import Data.Int
import Data.Word
import Data.Typeable
import System.IO.Unsafe -- used for `veryUnsafeFreezeVariable`.
import GHC.TypeLits (KnownNat)
--------------------------------------------------------------------------------
-- * Hardware frontend.
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- ** Signals.
-- | Declare a named signal.
initNamedSignal :: (SignalCMD :<: instr, pred a) => String -> exp a -> ProgramT instr (Param2 exp pred) m (Signal a)
initNamedSignal name = singleInj . NewSignal (Base name) InOut . Just
-- | Declare a signal.
initSignal :: (SignalCMD :<: instr, pred a) => exp a -> ProgramT instr (Param2 exp pred) m (Signal a)
initSignal = initNamedSignal "s"
-- | Declare an uninitialized named signal.
newNamedSignal :: (SignalCMD :<: instr, pred a) => String -> ProgramT instr (Param2 exp pred) m (Signal a)
newNamedSignal name = singleInj $ NewSignal (Base name) InOut Nothing
-- | Declare an uninitialized signal.
newSignal :: (SignalCMD :<: instr, pred a) => ProgramT instr (Param2 exp pred) m (Signal a)
newSignal = newNamedSignal "s"
-- | Fetches the current value of a signal.
getSignal :: (SignalCMD :<: instr, pred a, FreeExp exp, PredicateExp exp a, Monad m)
=> Signal a -> ProgramT instr (Param2 exp pred) m (exp a)
getSignal = fmap valToExp . singleInj . GetSignal
-- | Update the value of a signal.
setSignal :: (SignalCMD :<: instr, pred a) => Signal a -> exp a -> ProgramT instr (Param2 exp pred) m ()
setSignal s = singleInj . SetSignal s
-- | Unsafe version of fetching the contents of a signal.
unsafeFreezeSignal :: (SignalCMD :<: instr, pred a, FreeExp exp, PredicateExp exp a, Monad m)
=> Signal a -> ProgramT instr (Param2 exp pred) m (exp a)
unsafeFreezeSignal = fmap valToExp . singleInj . UnsafeFreezeSignal
-- | Concurrent update of a signals value.
concurrentSetSignal :: (SignalCMD :<: instr, pred a) => Signal a -> exp a -> ProgramT instr (Param2 exp pred) m ()
concurrentSetSignal s = singleInj . ConcurrentSetSignal s
--------------------------------------------------------------------------------
-- ports.
-- | Declare port signals of the given mode and assign it initial value.
initNamedPort, initExactPort :: (SignalCMD :<: instr, pred a)
=> String -> Mode -> exp a -> ProgramT instr (Param2 exp pred) m (Signal a)
initNamedPort name m = singleInj . NewSignal (Base name) m . Just
initExactPort name m = singleInj . NewSignal (Exact name) m . Just
initPort :: (SignalCMD :<: instr, pred a) => Mode -> exp a -> ProgramT instr (Param2 exp pred) m (Signal a)
initPort = initNamedPort "p"
-- | Declare port signals of the given mode.
newNamedPort, newExactPort :: (SignalCMD :<: instr, pred a)
=> String -> Mode -> ProgramT instr (Param2 exp pred) m (Signal a)
newNamedPort name m = singleInj $ NewSignal (Base name) m Nothing
newExactPort name m = singleInj $ NewSignal (Exact name) m Nothing
newPort :: (SignalCMD :<: instr, pred a) => Mode -> ProgramT instr (Param2 exp pred) m (Signal a)
newPort = newNamedPort "p"
--------------------------------------------------------------------------------
-- short-hands.
signal :: (SignalCMD :<: instr, pred a) => String -> ProgramT instr (Param2 exp pred) m (Signal a)
signal = newNamedSignal
(<--) :: (SignalCMD :<: instr, pred a, PredicateExp exp a, FreeExp exp, Monad m)
=> Signal a
-> a
-> ProgramT instr (Param2 exp pred) m ()
(<--) s e = s <== (litE e)
(<==) :: (SignalCMD :<: instr, pred a)
=> Signal a
-> exp a
-> ProgramT instr (Param2 exp pred) m ()
(<==) s e = setSignal s e
(<=-) :: (SignalCMD :<: instr, pred a, PredicateExp exp a, FreeExp exp, Monad m)
=> Signal a
-> Signal a
-> ProgramT instr (Param2 exp pred) m ()
(<=-) s v = do v' <- unsafeFreezeSignal v; s <== v'
--------------------------------------------------------------------------------
-- ** Variables.
-- | Declare a named variable.
initNamedVariable :: (VariableCMD :<: instr, pred a)
=> String -> exp a -> ProgramT instr (Param2 exp pred) m (Variable a)
initNamedVariable name = singleInj . NewVariable (Base name) . Just
-- | Declare a variable.
initVariable :: (VariableCMD :<: instr, pred a) => exp a -> ProgramT instr (Param2 exp pred) m (Variable a)
initVariable = initNamedVariable "v"
-- | Declare an uninitialized named variable.
newNamedVariable :: (VariableCMD :<: instr, pred a)
=> String -> ProgramT instr (Param2 exp pred) m (Variable a)
newNamedVariable name = singleInj $ NewVariable (Base name) Nothing
-- | Declare an uninitialized variable.
newVariable :: (VariableCMD :<: instr, pred a) => ProgramT instr (Param2 exp pred) m (Variable a)
newVariable = newNamedVariable "v"
-- | Fetches the current value of a variable.
getVariable :: (VariableCMD :<: instr, pred a, PredicateExp exp a, FreeExp exp, Monad m)
=> Variable a -> ProgramT instr (Param2 exp pred) m (exp a)
getVariable = fmap valToExp . singleInj . GetVariable
-- | Updates the value of a variable.
setVariable :: (VariableCMD :<: instr, pred a) => Variable a -> exp a -> ProgramT instr (Param2 exp pred) m ()
setVariable v = singleInj . SetVariable v
-- | Unsafe version of fetching the contents of a variable.
unsafeFreezeVariable :: (VariableCMD :<: instr, pred a, PredicateExp exp a, FreeExp exp, Monad m)
=> Variable a -> ProgramT instr (Param2 exp pred) m (exp a)
unsafeFreezeVariable = fmap valToExp . singleInj . UnsafeFreezeVariable
-- | Read the value of a reference without the monad in a very unsafe fashion.
veryUnsafeFreezeVariable :: (PredicateExp exp a, FreeExp exp) => Variable a -> exp a
veryUnsafeFreezeVariable (VariableE r) = litE $! unsafePerformIO $! readIORef r
veryUnsafeFreezeVariable (VariableC v) = varE v
--------------------------------------------------------------------------------
-- short-hands.
variable :: (VariableCMD :<: instr, pred a) => String -> ProgramT instr (Param2 exp pred) m (Variable a)
variable = newNamedVariable
-- | Short-hand for 'setVariable'.
(==:) :: (VariableCMD :<: instr, pred a) => Variable a -> exp a -> ProgramT instr (Param2 exp pred) m ()
(==:) = setVariable
--------------------------------------------------------------------------------
-- ** Constants.
initNamedConstant :: (ConstantCMD :<: instr, pred a)
=> String -> exp a -> ProgramT instr (Param2 exp pred) m (Constant a)
initNamedConstant name = singleInj . NewConstant (Base name)
initConstant :: (ConstantCMD :<: instr, pred a) => exp a -> ProgramT instr (Param2 exp pred) m (Constant a)
initConstant = initNamedConstant "c"
getConstant :: (ConstantCMD :<: instr, pred a, PredicateExp exp a, FreeExp exp, Monad m)
=> Constant a -> ProgramT instr (Param2 exp pred) m (exp a)
getConstant = fmap valToExp . singleInj . GetConstant
--------------------------------------------------------------------------------
-- short-hands.
constant :: (ConstantCMD :<: instr, pred a) => String -> exp a -> ProgramT instr (Param2 exp pred) m (Constant a)
constant = initNamedConstant
--------------------------------------------------------------------------------
-- ** Arrays.
-- | Create an initialized named virtual array.
initNamedArray :: (ArrayCMD :<: instr, pred a, Integral i, Ix i)
=> String -> [a] -> ProgramT instr (Param2 exp pred) m (Array i a)
initNamedArray name = singleInj . InitArray (Base name)
-- | Create an initialized virtual array.
initArray :: (ArrayCMD :<: instr, pred a, Integral i, Ix i)
=> [a] -> ProgramT instr (Param2 exp pred) m (Array i a)
initArray = initNamedArray "a"
-- | Create an uninitialized named virtual array.
newNamedArray :: (ArrayCMD :<: instr, pred a, Integral i, Ix i)
=> String -> exp i -> ProgramT instr (Param2 exp pred) m (Array i a)
newNamedArray name = singleInj . NewArray (Base name)
-- | Create an uninitialized virtual array.
newArray :: (ArrayCMD :<: instr, pred a, Integral i, Ix i)
=> exp i -> ProgramT instr (Param2 exp pred) m (Array i a)
newArray = newNamedArray "a"
getArray :: (ArrayCMD :<: instr, pred a, Integral i, Ix i, PredicateExp exp a, FreeExp exp, Monad m)
=> Array i a -> exp i -> ProgramT instr (Param2 exp pred) m (exp a)
getArray a = fmap valToExp . singleInj . GetArray a
-- | Set an element of an array.
setArray :: (ArrayCMD :<: instr, pred a, Integral i, Ix i, PredicateExp exp a, FreeExp exp, Monad m)
=> Array i a -> exp i -> exp a -> ProgramT instr (Param2 exp pred) m ()
setArray a i = singleInj . SetArray a i
-- | Copy a slice of one array to another.
copyArray :: (ArrayCMD :<: instr, pred a, Integral i, Ix i)
=> (Array i a, exp i) -- ^ destination and its offset.
-> (Array i a, exp i) -- ^ source and its offset.
-> exp i -- ^ number of elements to copy.
-> ProgramT instr (Param2 exp pred) m ()
copyArray dest src = singleInj . CopyArray dest src
-- | ...
resetArray :: (ArrayCMD :<: instr, pred a, Integral i, Ix i)
=> Array i a -> exp a -> ProgramT instr (Param2 exp pred) m ()
resetArray a rst = singleInj $ ResetArray a rst
--------------------------------------------------------------------------------
-- ** Virtual arrays.
-- | Create an initialized named virtual array.
initNamedVArray :: (VArrayCMD :<: instr, pred a, Integral i, Ix i)
=> String -> [a] -> ProgramT instr (Param2 exp pred) m (VArray i a)
initNamedVArray name = singleInj . InitVArray (Base name)
-- | Create an initialized virtual array.
initVArray :: (VArrayCMD :<: instr, pred a, Integral i, Ix i)
=> [a] -> ProgramT instr (Param2 exp pred) m (VArray i a)
initVArray = initNamedVArray "a"
-- | Create an uninitialized named virtual array.
newNamedVArray :: (VArrayCMD :<: instr, pred a, Integral i, Ix i)
=> String -> exp i -> ProgramT instr (Param2 exp pred) m (VArray i a)
newNamedVArray name = singleInj . NewVArray (Base name)
-- | Create an uninitialized virtual array.
newVArray :: (VArrayCMD :<: instr, pred a, Integral i, Ix i)
=> exp i -> ProgramT instr (Param2 exp pred) m (VArray i a)
newVArray = newNamedVArray "a"
-- | Get an element of an array.
getVArray :: (VArrayCMD :<: instr, pred a, Integral i, Ix i, PredicateExp exp a, FreeExp exp, Monad m)
=> VArray i a -> exp i -> ProgramT instr (Param2 exp pred) m (exp a)
getVArray a = fmap valToExp . singleInj . GetVArray a
-- | Set an element of an array.
setVArray :: (VArrayCMD :<: instr, pred a, Integral i, Ix i)
=> VArray i a -> exp i -> exp a -> ProgramT instr (Param2 exp pred) m ()
setVArray a i = singleInj . SetVArray a i
-- | Copy a slice of one array to another.
copyVArray :: (VArrayCMD :<: instr, pred a, Integral i, Ix i)
=> (VArray i a, exp i) -- ^ destination and its offset.
-> (VArray i a, exp i) -- ^ source and its offset.
-> exp i -- ^ number of elements to copy.
-> ProgramT instr (Param2 exp pred) m ()
copyVArray dest src = singleInj . CopyVArray dest src
-- | Freeze a mutable array into an immutable one by copying.
freezeVArray :: (VArrayCMD :<: instr, pred a, Integral i, Ix i, Num (exp i), Monad m)
=> VArray i a -> exp i -> ProgramT instr (Param2 exp pred) m (IArray i a)
freezeVArray array len =
do copy <- newVArray len
copyVArray (copy,0) (array,0) len
unsafeFreezeVArray copy
-- | Thaw an immutable array into a mutable one by copying.
thawVArray :: (VArrayCMD :<: instr, pred a, Integral i, Ix i, Num (exp i), Monad m)
=> IArray i a -> exp i -> ProgramT instr (Param2 exp pred) m (VArray i a)
thawVArray iarray len =
do array <- unsafeThawVArray iarray
copy <- newVArray len
copyVArray (copy,0) (array,0) len
return copy
-- | Freeze a mutable array to an immuatable one without making a copy.
unsafeFreezeVArray :: (VArrayCMD :<: instr, pred a, Integral i, Ix i)
=> VArray i a -> ProgramT instr (Param2 exp pred) m (IArray i a)
unsafeFreezeVArray = singleInj . UnsafeFreezeVArray
-- | Thaw an immutable array to a mutable one without making a copy.
unsafeThawVArray :: (VArrayCMD :<: instr, pred a, Integral i, Ix i)
=> IArray i a -> ProgramT instr (Param2 exp pred) m (VArray i a)
unsafeThawVArray = singleInj . UnsafeThawVArray
--------------------------------------------------------------------------------
-- ** Looping.
-- | For loop.
for :: (LoopCMD :<: instr, pred i, Integral i, PredicateExp exp i, FreeExp exp, Monad m)
=> exp i -> exp i -> (exp i -> ProgramT instr (Param2 exp pred) m ()) -> ProgramT instr (Param2 exp pred) m ()
for lower upper body = singleInj $ For lower upper (body . valToExp)
-- | While loop.
while :: (LoopCMD :<: instr, pred Bool)
=> ProgramT instr (Param2 exp pred) m (exp Bool)
-> ProgramT instr (Param2 exp pred) m ()
-> ProgramT instr (Param2 exp pred) m ()
while cond = singleInj . While cond
--------------------------------------------------------------------------------
-- ** Conditional statements.
-- | Conditional statements guarded by if and then clauses with an optional else.
conditional :: (ConditionalCMD :<: instr, pred Bool)
=> (exp Bool, ProgramT instr (Param2 exp pred) m ())
-> [(exp Bool, ProgramT instr (Param2 exp pred) m ())]
-> Maybe (ProgramT instr (Param2 exp pred) m ())
-> ProgramT instr (Param2 exp pred) m ()
conditional a bs = singleInj . If a bs
-- | Guarded statement.
when :: (ConditionalCMD :<: instr, pred Bool)
=> exp Bool
-> ProgramT instr (Param2 exp pred) m ()
-> ProgramT instr (Param2 exp pred) m ()
when e p = conditional (e, p) [] Nothing
-- | Standard if-then-else statement.
iff :: (ConditionalCMD :<: instr, pred Bool)
=> exp Bool
-> ProgramT instr (Param2 exp pred) m ()
-> ProgramT instr (Param2 exp pred) m ()
-> ProgramT instr (Param2 exp pred) m ()
iff b t e = conditional (b, t) [] (Just e)
ifE :: (ConditionalCMD :<: instr, pred Bool)
=> (exp Bool, ProgramT instr (Param2 exp pred) m ())
-> (exp Bool, ProgramT instr (Param2 exp pred) m ())
-> ProgramT instr (Param2 exp pred) m ()
ifE a b = conditional a [b] (Nothing)
--------------------------------------------------------------------------------
switch :: (ConditionalCMD :<: instr, pred a, Eq a, Ord a)
=> exp a
-> [When a (ProgramT instr (Param2 exp pred) m)]
-> ProgramT instr (Param2 exp pred) m ()
switch e choices = singleInj (Case e choices Nothing)
switched :: (ConditionalCMD :<: instr, pred a, Eq a, Ord a)
=> exp a
-> [When a (ProgramT instr (Param2 exp pred) m)]
-> ProgramT instr (Param2 exp pred) m ()
-> ProgramT instr (Param2 exp pred) m ()
switched e choices def = singleInj (Case e choices (Just def))
null :: (ConditionalCMD :<: instr) => ProgramT instr (Param2 exp pred) m ()
null = singleInj (Null)
is :: (Eq a, pred a)
=> a
-> ProgramT instr (Param2 exp pred) m ()
-> When a (ProgramT instr (Param2 exp pred) m)
is a = When (Is a)
to :: (Ord a, pred a)
=> a
-> a
-> ProgramT instr (Param2 exp pred) m ()
-> When a (ProgramT instr (Param2 exp pred) m)
to l h = When (To l h)
--------------------------------------------------------------------------------
-- ** Processes.
type Sig instr exp pred m = Signature (Param3 (ProgramT instr (Param2 exp pred) m) exp pred)
type Comp instr exp pred m = Component (Param3 (ProgramT instr (Param2 exp pred) m) exp pred)
-- | Declare a named component.
namedComponent :: (ComponentCMD :<: instr, Monad m)
=> String -> Sig instr exp pred m a
-> ProgramT instr (Param2 exp pred) m (Comp instr exp pred m a)
namedComponent name sig =
do n <- singleInj $ StructComponent (Base name) sig
return $ Component n sig
-- | Declare a component.
component :: (ComponentCMD :<: instr, Monad m)
=> Sig instr exp pred m a
-> ProgramT instr (Param2 exp pred) m (Comp instr exp pred m a)
component = namedComponent "comp"
-- | Call a component.
portmap :: (ComponentCMD :<: instr)
=> Comp instr exp pred m a
-> Argument pred a
-> ProgramT instr (Param2 exp pred) m ()
portmap pro arg = singleInj $ PortMap pro arg
--------------------------------------------------------------------------------
exactInput :: (pred a, Integral a, PrimType a)
=> String
-> (Signal a -> Sig instr exp pred m b)
-> Sig instr exp pred m (Signal a -> b)
exactInput n = SSig (Exact n) In
namedInput :: (pred a, Integral a, PrimType a)
=> String
-> (Signal a -> Sig instr exp pred m b)
-> Sig instr exp pred m (Signal a -> b)
namedInput n = SSig (Base n) In
input :: (pred a, Integral a, PrimType a)
=> (Signal a -> Sig instr exp pred m b)
-> Sig instr exp pred m (Signal a -> b)
input = namedInput "in"
{-
exactInputArr :: (pred a, Inhabited a, Sized a, Integral a, Rep a, Typeable a, pred i, Integral i, Ix i) => String -> i -> (Array i a -> Sig instr exp pred m b) -> Sig instr exp pred m (Array i a -> b)
exactInputArr n l = SArr (Exact n) In l
namedInputArr :: (pred a, Inhabited a, Sized a, Integral a, Rep a, Typeable a, pred i, Integral i, Ix i) => String -> i -> (Array i a -> Sig instr exp pred m b) -> Sig instr exp pred m (Array i a -> b)
namedInputArr n l = SArr (Base n) In l
inputArr :: (pred a, Inhabited a, Sized a, Integral a, Rep a, Typeable a, pred i, Integral i, Ix i) => i -> (Array i a -> Sig instr exp pred m b) -> Sig instr exp pred m (Array i a -> b)
inputArr = namedInputArr "in"
-}
exactOutput :: (pred a, Integral a, PrimType a)
=> String
-> (Signal a -> Sig instr exp pred m b)
-> Sig instr exp pred m (Signal a -> b)
exactOutput n = SSig (Exact n) Out
namedOutput :: (pred a, Integral a, PrimType a)
=> String
-> (Signal a -> Sig instr exp pred m b)
-> Sig instr exp pred m (Signal a -> b)
namedOutput n = SSig (Base n) Out
output :: (pred a, Integral a, PrimType a)
=> (Signal a -> Sig instr exp pred m b)
-> Sig instr exp pred m (Signal a -> b)
output = namedOutput "out"
{-
exactOutputArr :: (pred a, Inhabited a, Sized a, Integral a, Rep a, Typeable a, pred i, Integral i, Ix i) => String -> i -> (Array i a -> Sig instr exp pred m b) -> Sig instr exp pred m (Array i a -> b)
exactOutputArr n l = SArr (Exact n) Out l
namedOutputArr :: (pred a, Inhabited a, Sized a, Integral a, Rep a, Typeable a, pred i, Integral i, Ix i) => String -> i -> (Array i a -> Sig instr exp pred m b) -> Sig instr exp pred m (Array i a -> b)
namedOutputArr n l = SArr (Base n) Out l
outputArr :: (pred a, Inhabited a, Sized a, Integral a, Rep a, Typeable a, pred i, Integral i, Ix i) => i -> (Array i a -> Sig instr exp pred m b) -> Sig instr exp pred m (Array i a -> b)
outputArr = namedOutputArr "out"
-}
ret :: ProgramT instr (Param2 exp pred) m () -> Sig instr exp pred m ()
ret = Ret
--------------------------------------------------------------------------------
-- ** Structural entities.
-- | Declare a new entity by wrapping the program to declare ports & generics.
entity :: (StructuralCMD :<: instr)
=> String
-> ProgramT instr (Param2 exp pred) m a
-> ProgramT instr (Param2 exp pred) m a
entity e = singleInj . StructEntity (Exact e)
-- | Declare a new architecture for some entity by wrapping the given program.
architecture :: (StructuralCMD :<: instr)
=> String -> String
-> ProgramT instr (Param2 exp pred) m a
-> ProgramT instr (Param2 exp pred) m a
architecture e a = singleInj . StructArchitecture (Exact e) (Exact a)
-- | Declare a new process listening to some signals by wrapping the given program.
process :: (StructuralCMD :<: instr)
=> [Ident]
-> ProgramT instr (Param2 exp pred) m ()
-> ProgramT instr (Param2 exp pred) m ()
process is = singleInj . StructProcess is
--------------------------------------------------------------------------------
-- | Construct the untyped signal list for processes.
(.:) :: ToIdent a => a -> [Ident] -> [Ident]
(.:) x xs = toIdent x : xs
infixr .:
--------------------------------------------------------------------------------
-- ** VHDL specific instructions.
--
-- todo: these bit operations really do not have to be over just `Bits`, since
-- VHDL treats all of our types as bit vectors anyway.
-- | Short-hand that catures the common pattern:
-- "when (risingEdge clk) (if (not rst) then tru else fls)"
-- assuming reset is triggered on low.
whenRising :: (VHDLCMD :<: instr, pred Bit)
=> Signal Bit -- ^ Clock.
-> Signal Bit -- ^ Reset.
-> ProgramT instr (Param2 exp pred) m () -- ^ Reset program.
-> ProgramT instr (Param2 exp pred) m () -- ^ Normal program.
-> ProgramT instr (Param2 exp pred) m ()
whenRising clk rst tru fls = singleInj (Rising clk rst tru fls)
-- | ...
copyBits :: (VHDLCMD :<: instr, pred a, pred b, Integral i, Ix i)
=> (Signal a, exp i)
-> (Signal b, exp i)
-> exp i
-> ProgramT instr (Param2 exp pred) m ()
copyBits a b l = singleInj (CopyBits a b l)
-- | ...
copyVBits :: (VHDLCMD :<: instr, pred a, pred b, Integral i, Ix i)
=> (Variable a, exp i)
-> (Signal b, exp i)
-> exp i
-> ProgramT instr (Param2 exp pred) m ()
copyVBits a b l = singleInj (CopyVBits a b l)
-- | ...
getBit :: (VHDLCMD :<: instr, pred a, Integral i, Ix i, pred Bit, PredicateExp exp Bit, FreeExp exp, Monad m)
=> Signal a -> exp i -> ProgramT instr (Param2 exp pred) m (exp Bit)
getBit bits ix = fmap valToExp $ singleInj $ GetBit bits ix
-- | ...
setBit :: (VHDLCMD :<: instr, pred a, Integral i, Ix i, pred Bit)
=> Signal a -> exp i -> exp Bit -> ProgramT instr (Param2 exp pred) m ()
setBit bits ix bit = singleInj $ SetBit bits ix bit
-- | ...
getBits :: (VHDLCMD :<: instr, pred i, Integral i, Ix i, PredicateExp exp i, FreeExp exp, Monad m)
=> Signal (Bits u)
-> exp i
-> exp i
-> ProgramT instr (Param2 exp pred) m (exp i)
getBits a l u = fmap valToExp $ singleInj $ GetBits a l u
--------------------------------------------------------------------------------