{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE NamedFieldPuns #-}
module Data.SBV.Tools.BMC (
bmc, bmcWith
) where
import Data.SBV
import Data.SBV.Control
import Control.Monad (when)
bmc :: (EqSymbolic st, Queriable IO st res)
=> Maybe Int
-> Bool
-> Symbolic ()
-> (st -> SBool)
-> (st -> [st])
-> (st -> SBool)
-> IO (Either String (Int, [res]))
bmc = bmcWith defaultSMTCfg
bmcWith :: (EqSymbolic st, Queriable IO st res)
=> SMTConfig
-> Maybe Int
-> Bool
-> Symbolic ()
-> (st -> SBool)
-> (st -> [st])
-> (st -> SBool)
-> IO (Either String (Int, [res]))
bmcWith cfg mbLimit chatty setup initial trans goal
= runSMTWith cfg $ do setup
query $ do state <- create
constrain $ initial state
go 0 state []
where go i _ _
| Just l <- mbLimit, i >= l
= return $ Left $ "BMC limit of " ++ show l ++ " reached"
go i curState sofar = do when chatty $ io $ putStrLn $ "BMC: Iteration: " ++ show i
push 1
constrain $ goal curState
cs <- checkSat
case cs of
Sat -> do when chatty $ io $ putStrLn $ "BMC: Solution found at iteration " ++ show i
ms <- mapM project (curState : sofar)
return $ Right (i, reverse ms)
Unk -> do when chatty $ io $ putStrLn $ "BMC: Backend solver said unknown at iteration " ++ show i
return $ Left $ "BMC: Solver said unknown in iteration " ++ show i
Unsat -> do pop 1
nextState <- create
constrain $ sAny (nextState .==) (trans curState)
go (i+1) nextState (curState : sofar)