packages feed

retroclash-sim-0.1.0: src/RetroClash/Sim/IO.hs

{-# LANGUAGE RankNTypes #-}
module RetroClash.Sim.IO
    ( simulateIO
    , simulateIO_
    ) where

import Clash.Prelude
import Control.Concurrent
import Control.Monad.IO.Class
import Control.Monad (void)
import Control.Arrow.Transformer.Automaton

simulateIO
    :: (KnownDomain dom, MonadIO m, NFDataX i, NFDataX o)
    => (HiddenClockResetEnable dom => Signal dom i -> Signal dom o)
    -> i
    -> IO ((o -> m (i, a)) -> m a)
simulateIO circuit input0 = do
    let Automaton step = signalAutomaton circuit
    ref <- newMVar $ step input0
    return $ \world -> do
        (out, Automaton step) <- liftIO $ takeMVar ref
        (input, result) <- world out
        liftIO $ putMVar ref $ step input
        return result

simulateIO_
    :: (KnownDomain dom, MonadIO m, NFDataX i, NFDataX o)
    => (HiddenClockResetEnable dom => Signal dom i -> Signal dom o)
    -> i
    -> IO ((o -> m i) -> m ())
simulateIO_ circuit input0 = do
    sim <- simulateIO circuit input0
    return $ \world -> do
        void $ sim $ \output -> do
            input <- world output
            return (input, ())