synthesizer-llvm-0.3: src/Synthesizer/LLVM/ConstantPiece.hs
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE UndecidableInstances #-}
{- |
Data type that allows handling of piecewise constant signals
independently from the source.
-}
module Synthesizer.LLVM.ConstantPiece where
import qualified Synthesizer.LLVM.Parameterized.SignalPrivate as SigP
import qualified Synthesizer.LLVM.Parameter as Param
import qualified Synthesizer.LLVM.Storable.LazySizeIterator as SizeIt
import qualified Data.StorableVector.Lazy.Pattern as SVP
import qualified Synthesizer.LLVM.EventIterator as EventIt
import qualified Data.EventList.Relative.BodyTime as EventList
import qualified Numeric.NonNegative.Wrapper as NonNeg
import qualified LLVM.Extra.MaybeContinuation as Maybe
import qualified LLVM.Extra.Memory as Memory
import qualified LLVM.Extra.Class as Class
import qualified LLVM.Extra.Arithmetic as A
import LLVM.Extra.Control (whileLoop, )
import LLVM.Extra.Class (MakeValueTuple, Undefined, undefTuple, )
import LLVM.Util.Loop (Phi, phis, addPhis, )
import LLVM.Core as LLVM
import Data.TypeLevel.Num (d0, d1, )
import Data.Word (Word32, )
import Foreign.Storable.Tuple ()
import Foreign.Storable (Storable, )
import qualified Synthesizer.LLVM.Alloc as Alloc
import Control.Applicative (liftA2, )
import NumericPrelude.Numeric
import NumericPrelude.Base
data T a = Cons (Value Word32) a
instance (Phi a) => Phi (T a) where
phis bb (Cons len y) =
liftA2 Cons (phis bb len) (phis bb y)
addPhis bb (Cons lenA ya) (Cons lenB yb) =
addPhis bb lenA lenB >> addPhis bb ya yb
instance (Undefined a) =>
Undefined (T a) where
undefTuple =
Cons Class.undefTuple Class.undefTuple
instance (Class.Zero a) =>
Class.Zero (T a) where
zeroTuple =
Cons Class.zeroTuple Class.zeroTuple
parameterMemory ::
(Memory.C a s, IsSized s ss) =>
Memory.Record r (Struct (Word32, (s, ()))) (T a)
parameterMemory =
liftA2 Cons
(Memory.element (\(Cons len _y) -> len) d0)
(Memory.element (\(Cons _len y) -> y) d1)
instance
(Memory.C a s, IsSized s ss) =>
Memory.C (T a) (Struct (Word32, (s, ()))) where
load = Memory.loadRecord parameterMemory
store = Memory.storeRecord parameterMemory
decompose = Memory.decomposeRecord parameterMemory
compose = Memory.composeRecord parameterMemory
flatten ::
(Memory.C value struct, IsSized struct size) =>
SigP.T p (T value) ->
SigP.T p value
flatten (SigP.Cons next start createIOContext deleteIOContext) =
SigP.Cons
(\nextParam state0 -> do
(Cons length1 y1, s1) <-
Maybe.fromBool $
whileLoop (valueOf True, state0)
(\(cont, (Cons len _y, _s)) ->
LLVM.and cont =<< A.cmp CmpEQ len (valueOf 0))
(\(_cont, (Cons _len _y, s)) ->
Maybe.toBool $ next nextParam s)
length2 <- Maybe.lift (A.dec length1)
return (y1, (Cons length2 y1, s1)))
(\startParam ->
fmap ((,) (Cons (valueOf 0) undefTuple)) $
start startParam)
createIOContext deleteIOContext
piecewiseConstant ::
(Storable a, MakeValueTuple a value, Memory.C value struct, IsSized struct size) =>
Param.T p (EventList.T NonNeg.Int a) ->
SigP.T p (T value)
piecewiseConstant evs = SigP.Cons
(\(stable, yPtr) () -> do
len <- Maybe.lift $ do
nextFn <- staticFunction EventIt.nextCallBack
call nextFn stable yPtr
Maybe.guard =<<
Maybe.lift (A.cmp CmpNE len (valueOf 0))
y <- Maybe.lift $ Memory.load yPtr
return (Cons len y, ()))
return
(\p -> do
stable <- EventIt.new (Param.get evs p)
yPtr <- Alloc.malloc
return ((stable, asTypeOfEventListElement yPtr evs),
((stable, Memory.castStorablePtr yPtr), ())))
(\(stable,yPtr) -> do
EventIt.dispose stable
Alloc.free yPtr)
asTypeOfEventListElement ::
Ptr a ->
Param.T p (EventList.T NonNeg.Int a) ->
Ptr a
asTypeOfEventListElement ptr _ = ptr
lazySize ::
Param.T p SVP.LazySize ->
SigP.T p (T ())
lazySize size = SigP.Cons
(\stable () -> do
len <- Maybe.lift $ do
nextFn <- staticFunction SizeIt.nextCallBack
call nextFn stable
Maybe.guard =<<
Maybe.lift (A.cmp CmpNE len (valueOf 0))
return (Cons len (), ()))
return
(\p -> do
stable <- SizeIt.new (Param.get size p)
return (stable, (stable, ())))
SizeIt.dispose