├── README.md ├── copilot-c99 ├── Setup.hs ├── src │ └── Copilot │ │ └── Compile │ │ ├── C99.hs │ │ └── C99 │ │ ├── Settings.hs │ │ ├── Representation.hs │ │ ├── Error.hs │ │ ├── Type.hs │ │ ├── Name.hs │ │ └── External.hs ├── tests │ └── Main.hs ├── README.md └── LICENSE ├── copilot ├── Setup.hs ├── runtest ├── examples │ ├── fpga │ │ └── HelloWorld │ │ │ ├── HelloWorld.hs │ │ │ ├── Top.bs │ │ │ ├── constraints.xdc │ │ │ └── mkTop.v │ ├── AddMult.hs │ ├── Cast.hs │ ├── Clock.hs │ ├── Counter.hs │ ├── Heater.hs │ ├── Engine.hs │ ├── what4 │ │ ├── Arrays.hs │ │ └── Arithmetic.hs │ ├── Voting.hs │ ├── Array.hs │ └── Structs.hs ├── src │ └── Language │ │ └── Copilot.hs └── LICENSE ├── copilot-bluespec ├── Setup.hs ├── .dockerignore ├── src │ └── Copilot │ │ └── Compile │ │ ├── Bluespec.hs │ │ └── Bluespec │ │ ├── Settings.hs │ │ ├── Error.hs │ │ ├── Representation.hs │ │ └── External.hs ├── tests │ └── Main.hs ├── Dockerfile ├── LICENSE ├── CHANGELOG └── README.md ├── copilot-core ├── Setup.hs ├── tests │ ├── Main.hs │ └── Test │ │ └── Extra.hs ├── src │ └── Copilot │ │ ├── Core.hs │ │ └── Core │ │ ├── Expr.hs │ │ └── Type │ │ └── Array.hs ├── LICENSE ├── README.md └── copilot-core.cabal ├── copilot-language ├── Setup.hs ├── tests │ ├── Main.hs │ └── Test │ │ └── Extra.hs ├── src │ ├── Copilot │ │ ├── Language │ │ │ ├── Prelude.hs │ │ │ ├── Operators │ │ │ │ ├── Label.hs │ │ │ │ ├── Propositional.hs │ │ │ │ ├── Local.hs │ │ │ │ ├── Eq.hs │ │ │ │ ├── Mux.hs │ │ │ │ ├── Temporal.hs │ │ │ │ ├── Projection.hs │ │ │ │ ├── Boolean.hs │ │ │ │ ├── BitWise.hs │ │ │ │ ├── Integral.hs │ │ │ │ └── Ord.hs │ │ │ ├── Error.hs │ │ │ └── Interpret.hs │ │ └── Language.hs │ └── System │ │ └── Mem │ │ └── StableName │ │ └── Dynamic.hs ├── LICENSE └── README.md ├── copilot-libraries ├── Setup.hs ├── tests │ ├── Main.hs │ └── Test │ │ └── Copilot │ │ └── Library │ │ └── PTLTL.hs ├── src │ └── Copilot │ │ └── Library │ │ ├── Libraries.hs │ │ ├── PTLTL.hs │ │ └── Statistics.hs ├── README.md └── LICENSE ├── copilot-theorem ├── Setup.hs ├── doc │ └── talk.pdf ├── src │ └── Copilot │ │ ├── Theorem │ │ ├── Kind2.hs │ │ ├── TransSys │ │ │ ├── Invariants.hs │ │ │ └── Type.hs │ │ ├── Tactics.hs │ │ ├── IL.hs │ │ ├── TransSys.hs │ │ ├── Misc │ │ │ ├── Error.hs │ │ │ ├── Utils.hs │ │ │ └── SExpr.hs │ │ ├── Prover │ │ │ └── Backend.hs │ │ ├── IL │ │ │ └── Transform.hs │ │ └── Kind2 │ │ │ ├── AST.hs │ │ │ └── PrettyPrint.hs │ │ └── Theorem.hs ├── tests │ └── Main.hs ├── examples │ ├── Incr.hs │ ├── Grey.hs │ └── SerialBoyerMoore.hs └── LICENSE ├── copilot-interpreter ├── Setup.hs ├── src │ └── Copilot │ │ ├── Interpret │ │ └── Error.hs │ │ └── Interpret.hs ├── tests │ ├── Main.hs │ └── Test │ │ └── Extra.hs ├── README.md ├── LICENSE ├── CHANGELOG └── copilot-interpreter.cabal ├── copilot-visualizer ├── Setup.hs ├── CHANGELOG ├── examples │ ├── gui │ │ ├── Main.hs │ │ └── copilot.css │ └── tikz │ │ └── Heater.hs ├── data │ └── tikz │ │ └── tikz.tex ├── src │ └── Copilot │ │ └── Visualize │ │ └── Static.hs ├── README.md └── LICENSE ├── copilot-prettyprinter ├── Setup.hs ├── src │ └── Copilot │ │ └── PrettyPrint │ │ ├── Error.hs │ │ └── Type.hs ├── README.md ├── LICENSE ├── CHANGELOG └── copilot-prettyprinter.cabal ├── .gitignore ├── cabal.project └── copilot-verifier ├── examples └── Copilot │ └── Verifier │ └── Examples │ ├── ShouldPass │ ├── Partial │ │ ├── DivByZero.hs │ │ ├── AbsIntMin.hs │ │ ├── ModByZero.hs │ │ ├── AddSignedWrap.hs │ │ ├── MulSignedWrap.hs │ │ ├── SubSignedWrap.hs │ │ ├── IndexOutOfBounds.hs │ │ ├── ShiftLTooLarge.hs │ │ └── ShiftRTooLarge.hs │ ├── ArrayTriggerArgument.hs │ ├── ArrayGen.hs │ ├── ArrayOfStructs.hs │ ├── UpdateArray.hs │ ├── Clock.hs │ ├── Array.hs │ ├── Arith.hs │ ├── Engine.hs │ ├── Voting.hs │ ├── FPNegation.hs │ ├── Counter.hs │ ├── Heater.hs │ ├── UpdateStruct.hs │ └── IntOps.hs │ └── ShouldFail │ └── Partial │ ├── DivByZero.hs │ ├── ModByZero.hs │ ├── AddSignedWrap.hs │ ├── SubSignedWrap.hs │ ├── AbsIntMin.hs │ ├── IndexOutOfBounds.hs │ ├── MulSignedWrap.hs │ ├── ShiftLTooLarge.hs │ └── ShiftRTooLarge.hs ├── src └── Copilot │ └── Verifier │ ├── Solver.hs │ └── FloatMode.hs ├── test └── Test.hs ├── LICENSE ├── exe └── VerifyExamples.hs └── CHANGELOG /README.md: -------------------------------------------------------------------------------- 1 | copilot/README.md -------------------------------------------------------------------------------- /copilot-c99/Setup.hs: -------------------------------------------------------------------------------- 1 | import Distribution.Simple 2 | main = defaultMain -------------------------------------------------------------------------------- /copilot/Setup.hs: -------------------------------------------------------------------------------- 1 | import Distribution.Simple 2 | main = defaultMain 3 | -------------------------------------------------------------------------------- /copilot-bluespec/Setup.hs: -------------------------------------------------------------------------------- 1 | import Distribution.Simple 2 | main = defaultMain -------------------------------------------------------------------------------- /copilot-core/Setup.hs: -------------------------------------------------------------------------------- 1 | import Distribution.Simple 2 | main = defaultMain 3 | -------------------------------------------------------------------------------- /copilot-language/Setup.hs: -------------------------------------------------------------------------------- 1 | import Distribution.Simple 2 | main = defaultMain -------------------------------------------------------------------------------- /copilot-libraries/Setup.hs: -------------------------------------------------------------------------------- 1 | import Distribution.Simple 2 | main = defaultMain -------------------------------------------------------------------------------- /copilot-theorem/Setup.hs: -------------------------------------------------------------------------------- 1 | import Distribution.Simple 2 | main = defaultMain 3 | -------------------------------------------------------------------------------- /copilot-interpreter/Setup.hs: -------------------------------------------------------------------------------- 1 | import Distribution.Simple 2 | main = defaultMain 3 | -------------------------------------------------------------------------------- /copilot-visualizer/Setup.hs: -------------------------------------------------------------------------------- 1 | import Distribution.Simple 2 | main = defaultMain 3 | -------------------------------------------------------------------------------- /copilot-prettyprinter/Setup.hs: -------------------------------------------------------------------------------- 1 | import Distribution.Simple 2 | main = defaultMain 3 | -------------------------------------------------------------------------------- /copilot-theorem/doc/talk.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Copilot-Language/copilot/HEAD/copilot-theorem/doc/talk.pdf -------------------------------------------------------------------------------- /copilot/runtest: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | infile="$1" 4 | if [ ! -e $infile ]; then 5 | echo "File \"$infile\" does not exist." 6 | exit 1 7 | fi 8 | 9 | shift 10 | 11 | p=$(cabal exec printenv GHC_PACKAGE_PATH) 12 | 13 | GHC_PACKAGE_PATH="$p" runhaskell "$infile" $@ 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | dist-* 3 | cabal-dev 4 | *.o 5 | *.hi 6 | *.chi 7 | *.chs.h 8 | *.dyn_o 9 | *.dyn_hi 10 | .hpc 11 | .hsenv 12 | .cabal-sandbox/ 13 | cabal.sandbox.config 14 | *.prof 15 | *.aux 16 | *.hp 17 | *.eventlog 18 | .stack-work/ 19 | cabal.project.local 20 | cabal.project.local~ 21 | .HTF/ 22 | .ghc.environment.* 23 | copilot-profiling 24 | .DS_Store 25 | .log 26 | -------------------------------------------------------------------------------- /copilot-c99/src/Copilot/Compile/C99.hs: -------------------------------------------------------------------------------- 1 | -- | Compile Copilot specifications to C99 code. 2 | module Copilot.Compile.C99 3 | ( compile 4 | , compileWith 5 | , CSettings(..) 6 | , mkDefaultCSettings 7 | ) where 8 | 9 | -- Internal imports 10 | import Copilot.Compile.C99.Compile ( compile, compileWith ) 11 | import Copilot.Compile.C99.Settings ( CSettings (..), mkDefaultCSettings ) 12 | -------------------------------------------------------------------------------- /cabal.project: -------------------------------------------------------------------------------- 1 | packages: 2 | copilot-bluespec/copilot-bluespec.cabal 3 | copilot-c99/copilot-c99.cabal 4 | copilot-core/copilot-core.cabal 5 | copilot-interpreter/copilot-interpreter.cabal 6 | copilot-language/copilot-language.cabal 7 | copilot-libraries/copilot-libraries.cabal 8 | copilot-prettyprinter/copilot-prettyprinter.cabal 9 | copilot-theorem/copilot-theorem.cabal 10 | copilot/copilot.cabal 11 | -------------------------------------------------------------------------------- /copilot-theorem/src/Copilot/Theorem/Kind2.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE Safe #-} 2 | 3 | -- | Copilot backend for the SMT 4 | -- based model checker. 5 | 6 | module Copilot.Theorem.Kind2 (module X) where 7 | 8 | import Copilot.Theorem.Kind2.AST as X 9 | import Copilot.Theorem.Kind2.Translate as X 10 | import Copilot.Theorem.Kind2.PrettyPrint as X 11 | import Copilot.Theorem.Kind2.Prover as X 12 | -------------------------------------------------------------------------------- /copilot/examples/fpga/HelloWorld/HelloWorld.hs: -------------------------------------------------------------------------------- 1 | module Main where 2 | 3 | import Language.Copilot 4 | import Copilot.Compile.Bluespec 5 | 6 | -- Define switches input 7 | sw :: Stream Word8 8 | sw = extern "sw" Nothing 9 | 10 | -- Define LEDS output 11 | leds :: Stream Word8 12 | leds = sw 13 | 14 | spec = do 15 | trigger "leds" true [arg leds] 16 | 17 | main = do 18 | spec' <- reify spec 19 | compile "HelloWorld" spec' 20 | -------------------------------------------------------------------------------- /copilot-visualizer/CHANGELOG: -------------------------------------------------------------------------------- 1 | 2025-11-07 2 | * Version bump (4.6). (#679) 3 | 4 | 2025-09-07 5 | * Version bump (4.5.1). (#666) 6 | * Relax version constraint on `ogma-extra`. (#645) 7 | 8 | 2025-07-07 9 | * Version bump (4.5). (#642) 10 | * Include in mainline. (#624) 11 | 12 | 2025-06-26 13 | * Release 4.4. (copilot-visualizer#5) 14 | * Initial version. (copilot-visualizer#4) 15 | -------------------------------------------------------------------------------- /copilot-bluespec/.dockerignore: -------------------------------------------------------------------------------- 1 | dist 2 | dist-* 3 | cabal-dev 4 | *.o 5 | *.hi 6 | *.chi 7 | *.chs.h 8 | *.dyn_o 9 | *.dyn_hi 10 | .hpc 11 | .hsenv 12 | .cabal-sandbox/ 13 | cabal.sandbox.config 14 | *.prof 15 | *.aux 16 | *.hp 17 | *.eventlog 18 | .stack-work/ 19 | cabal.project.local 20 | cabal.project.local~ 21 | .HTF/ 22 | .ghc.environment.* 23 | copilot-profiling 24 | .DS_Store 25 | .log 26 | 27 | Dockerfile 28 | .git 29 | .gitignore 30 | -------------------------------------------------------------------------------- /copilot-theorem/tests/Main.hs: -------------------------------------------------------------------------------- 1 | -- | Test copilot-theorem. 2 | module Main where 3 | 4 | -- External imports 5 | import Test.Framework (Test, defaultMain) 6 | 7 | -- Internal imports 8 | import qualified Test.Copilot.Theorem.What4 9 | 10 | -- | Run all unit tests on copilot-theorem. 11 | main :: IO () 12 | main = defaultMain tests 13 | 14 | -- | All unit tests in copilot-theorem. 15 | tests :: [Test.Framework.Test] 16 | tests = 17 | [ Test.Copilot.Theorem.What4.tests 18 | ] 19 | -------------------------------------------------------------------------------- /copilot-c99/tests/Main.hs: -------------------------------------------------------------------------------- 1 | -- | Test copilot-c99. 2 | module Main where 3 | 4 | -- External imports 5 | import Test.Framework (Test, defaultMain) 6 | 7 | -- Internal library modules being tested 8 | import qualified Test.Copilot.Compile.C99 9 | 10 | -- | Run all unit tests on copilot-c99. 11 | main :: IO () 12 | main = defaultMain tests 13 | 14 | -- | All unit tests in copilot-c99. 15 | tests :: [Test.Framework.Test] 16 | tests = 17 | [ Test.Copilot.Compile.C99.tests 18 | ] 19 | -------------------------------------------------------------------------------- /copilot-interpreter/src/Copilot/Interpret/Error.hs: -------------------------------------------------------------------------------- 1 | -- Copyright © 2011 National Institute of Aerospace / Galois, Inc. 2 | 3 | {-# LANGUAGE Safe #-} 4 | 5 | -- | Custom functions to report error messages to users. 6 | module Copilot.Interpret.Error 7 | ( badUsage ) where 8 | 9 | -- | Report an error due to an error detected by Copilot (e.g., user error). 10 | badUsage :: String -- ^ Description of the error. 11 | -> a 12 | badUsage msg = error $ "Copilot error: " ++ msg 13 | -------------------------------------------------------------------------------- /copilot-language/tests/Main.hs: -------------------------------------------------------------------------------- 1 | -- | Test copilot-language. 2 | module Main where 3 | 4 | -- External imports 5 | import Test.Framework (Test, defaultMain) 6 | 7 | -- Internal imports 8 | import qualified Test.Copilot.Language.Reify 9 | 10 | -- | Run all unit tests on copilot-language. 11 | main :: IO () 12 | main = defaultMain tests 13 | 14 | -- | All unit tests in copilot-language. 15 | tests :: [Test.Framework.Test] 16 | tests = 17 | [ Test.Copilot.Language.Reify.tests 18 | ] 19 | -------------------------------------------------------------------------------- /copilot-libraries/tests/Main.hs: -------------------------------------------------------------------------------- 1 | -- | Test copilot-libraries. 2 | module Main where 3 | 4 | -- External imports 5 | import Test.Framework (Test, defaultMain) 6 | 7 | -- Internal imports 8 | import qualified Test.Copilot.Library.PTLTL 9 | 10 | -- | Run all unit tests on copilot-libraries. 11 | main :: IO () 12 | main = defaultMain tests 13 | 14 | -- | All unit tests in copilot-libraries. 15 | tests :: [Test.Framework.Test] 16 | tests = 17 | [ Test.Copilot.Library.PTLTL.tests 18 | ] 19 | -------------------------------------------------------------------------------- /copilot-bluespec/src/Copilot/Compile/Bluespec.hs: -------------------------------------------------------------------------------- 1 | -- | Compile Copilot specifications to Bluespec code. 2 | module Copilot.Compile.Bluespec 3 | ( compile 4 | , compileWith 5 | , BluespecSettings(..) 6 | , mkDefaultBluespecSettings 7 | ) where 8 | 9 | -- Internal imports 10 | import Copilot.Compile.Bluespec.Compile ( compile, compileWith ) 11 | import Copilot.Compile.Bluespec.Settings ( BluespecSettings (..), 12 | mkDefaultBluespecSettings ) 13 | -------------------------------------------------------------------------------- /copilot/examples/AddMult.hs: -------------------------------------------------------------------------------- 1 | -- Copyright © 2019 National Institute of Aerospace / Galois, Inc. 2 | 3 | -- | Another small example that calculates a constant value using a recursive 4 | -- function. 5 | 6 | module Main where 7 | 8 | import Language.Copilot 9 | 10 | spec :: Spec 11 | spec = trigger "f" true [ arg $ mult 5 ] 12 | where 13 | mult :: Word64 -> Stream Word64 14 | mult 0 = 1 15 | mult i = constant i * mult (i-1) 16 | 17 | main :: IO () 18 | main = interpret 100 spec 19 | -------------------------------------------------------------------------------- /copilot-bluespec/tests/Main.hs: -------------------------------------------------------------------------------- 1 | -- | Test copilot-bluespec. 2 | module Main where 3 | 4 | -- External imports 5 | import Test.Framework (Test, defaultMain) 6 | 7 | -- Internal library modules being tested 8 | import qualified Test.Copilot.Compile.Bluespec 9 | 10 | -- | Run all @copilot-bluespec@ tests. 11 | main :: IO () 12 | main = defaultMain tests 13 | 14 | -- | All @copilot-bluespec@ tests. 15 | tests :: [Test.Framework.Test] 16 | tests = 17 | [ Test.Copilot.Compile.Bluespec.tests 18 | ] 19 | -------------------------------------------------------------------------------- /copilot-interpreter/tests/Main.hs: -------------------------------------------------------------------------------- 1 | -- | Test copilot-core. 2 | module Main where 3 | 4 | -- External imports 5 | import Test.Framework (Test, defaultMain) 6 | 7 | -- Internal library modules being tested 8 | import qualified Test.Copilot.Interpret.Eval 9 | 10 | -- | Run all unit tests on copilot-core. 11 | main :: IO () 12 | main = defaultMain tests 13 | 14 | -- | All unit tests in copilot-core. 15 | tests :: [Test.Framework.Test] 16 | tests = 17 | [ Test.Copilot.Interpret.Eval.tests 18 | ] 19 | -------------------------------------------------------------------------------- /copilot-theorem/examples/Incr.hs: -------------------------------------------------------------------------------- 1 | module Incr where 2 | 3 | import Prelude () 4 | import Copilot.Language 5 | 6 | import Copilot.Theorem 7 | import Copilot.Theorem.Prover.Z3 8 | 9 | spec = do 10 | bounds <- prop "bounds" (forAll $ x < 255) 11 | theorem "gt1" (forAll $ x > 1) (assume bounds >> induct) 12 | theorem "neq0" (forAll $ x /= 0) (assume bounds >> induct) 13 | 14 | where 15 | x :: Stream Word8 16 | x = [2] ++ (1 + x) 17 | 18 | induct :: Proof Universal 19 | induct = induction def { nraNLSat = False, debug = True } 20 | -------------------------------------------------------------------------------- /copilot/examples/fpga/HelloWorld/Top.bs: -------------------------------------------------------------------------------- 1 | package Top where 2 | 3 | import HelloWorld 4 | import HelloWorldIfc 5 | import HelloWorldTypes 6 | 7 | helloWorldIfc :: Prelude.Module HelloWorldIfc 8 | helloWorldIfc = 9 | module 10 | -- Register that connects the LEDs to values produced by Copilot 11 | led_reg :: Prelude.Reg (Prelude.UInt 8) <- mkReg 0 12 | interface 13 | led reg = action 14 | led_reg := reg 15 | 16 | mkTop :: Prelude.Module Prelude.Empty 17 | mkTop = mkHelloWorld helloWorldIfc 18 | -------------------------------------------------------------------------------- /copilot/examples/Cast.hs: -------------------------------------------------------------------------------- 1 | -- Copyright © 2019 National Institute of Aerospace / Galois, Inc. 2 | 3 | -- | Examples of casting types. 4 | 5 | {-# LANGUAGE RebindableSyntax #-} 6 | 7 | module Main where 8 | 9 | import Language.Copilot 10 | 11 | b :: Stream Bool 12 | b = [True] ++ not b 13 | 14 | i :: Stream Int8 15 | i = cast b 16 | 17 | x :: Stream Word16 18 | x = [0] ++ x + 1 19 | 20 | y :: Stream Int32 21 | y = 1 + cast x 22 | 23 | spec :: Spec 24 | spec = trigger "trigger" true [arg y, arg i] 25 | 26 | main :: IO () 27 | main = interpret 30 spec 28 | -------------------------------------------------------------------------------- /copilot-c99/src/Copilot/Compile/C99/Settings.hs: -------------------------------------------------------------------------------- 1 | -- | Settings used by the code generator to customize the code. 2 | module Copilot.Compile.C99.Settings 3 | ( CSettings(..) 4 | , mkDefaultCSettings 5 | ) 6 | where 7 | 8 | -- | Settings used to customize the code generated. 9 | data CSettings = CSettings 10 | { cSettingsStepFunctionName :: String 11 | , cSettingsOutputDirectory :: FilePath 12 | } 13 | 14 | -- | Default settings with a step function called @step@. 15 | mkDefaultCSettings :: CSettings 16 | mkDefaultCSettings = CSettings "step" "." 17 | -------------------------------------------------------------------------------- /copilot-core/tests/Main.hs: -------------------------------------------------------------------------------- 1 | -- | Test copilot-core. 2 | module Main where 3 | 4 | -- External imports 5 | import Test.Framework (Test, defaultMain) 6 | 7 | -- Internal library modules being tested 8 | import qualified Test.Copilot.Core.Type 9 | import qualified Test.Copilot.Core.Type.Array 10 | 11 | -- | Run all unit tests on copilot-core. 12 | main :: IO () 13 | main = defaultMain tests 14 | 15 | -- | All unit tests in copilot-core. 16 | tests :: [Test.Framework.Test] 17 | tests = 18 | [ Test.Copilot.Core.Type.tests 19 | , Test.Copilot.Core.Type.Array.tests 20 | ] 21 | -------------------------------------------------------------------------------- /copilot-bluespec/src/Copilot/Compile/Bluespec/Settings.hs: -------------------------------------------------------------------------------- 1 | -- | Settings used by the code generator to customize the code. 2 | module Copilot.Compile.Bluespec.Settings 3 | ( BluespecSettings(..) 4 | , mkDefaultBluespecSettings 5 | ) where 6 | 7 | -- | Settings used to customize the code generated. 8 | newtype BluespecSettings = BluespecSettings 9 | { bluespecSettingsOutputDirectory :: FilePath 10 | } 11 | 12 | -- | Default Bluespec settings. Output to the current directory. 13 | mkDefaultBluespecSettings :: BluespecSettings 14 | mkDefaultBluespecSettings = BluespecSettings "." 15 | -------------------------------------------------------------------------------- /copilot-theorem/src/Copilot/Theorem/TransSys/Invariants.hs: -------------------------------------------------------------------------------- 1 | {-# OPTIONS_GHC -O0 #-} 2 | {-# LANGUAGE Safe #-} 3 | 4 | -- | Augment types with invariants. 5 | 6 | module Copilot.Theorem.TransSys.Invariants 7 | ( HasInvariants (..) 8 | , prop 9 | ) where 10 | 11 | -- | Type class for types with additional invariants or contraints. 12 | class HasInvariants a where 13 | 14 | invariants :: a -> [(String, Bool)] 15 | 16 | checkInvs :: a -> Bool 17 | checkInvs obj = all snd $ invariants obj 18 | 19 | -- | Creates an invariant with a description. 20 | prop :: String -> Bool -> (String, Bool) 21 | prop = (,) 22 | -------------------------------------------------------------------------------- /copilot-language/src/Copilot/Language/Prelude.hs: -------------------------------------------------------------------------------- 1 | -- Copyright © 2011 National Institute of Aerospace / Galois, Inc. 2 | 3 | -- | Reexports 'Prelude' from package "base" hiding identifiers redefined by 4 | -- Copilot. 5 | 6 | {-# LANGUAGE Safe #-} 7 | 8 | module Copilot.Language.Prelude 9 | ( module Prelude 10 | ) where 11 | 12 | import Prelude hiding 13 | ( (++) 14 | , (==), (/=) 15 | , div, mod 16 | , (<=), (>=), (<), (>) 17 | , (&&) 18 | , (^) 19 | , (||) 20 | , const 21 | , drop 22 | , not 23 | , mod 24 | , until 25 | , sum 26 | , max 27 | , min 28 | , (!!) 29 | , cycle 30 | , take 31 | ) 32 | -------------------------------------------------------------------------------- /copilot-theorem/src/Copilot/Theorem/Tactics.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE Safe #-} 2 | 3 | -- | Utility functions to help write proof tactics. 4 | 5 | module Copilot.Theorem.Tactics 6 | ( instantiate, assume, admit 7 | ) where 8 | 9 | import Copilot.Theorem.Prove 10 | 11 | import Control.Monad.Writer 12 | 13 | -- | Instantiate a universal proof into an existential proof. 14 | instantiate :: Proof Universal -> Proof Existential 15 | instantiate (Proof p) = Proof p 16 | 17 | -- | Assume that a property, given by reference, holds. 18 | assume :: PropRef Universal -> Proof a 19 | assume (PropRef p) = Proof $ tell [Assume p] 20 | 21 | -- | Assume that the current goal holds. 22 | admit :: Proof a 23 | admit = Proof $ tell [Admit] 24 | -------------------------------------------------------------------------------- /copilot-theorem/src/Copilot/Theorem/IL.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE Safe #-} 2 | 3 | -- | Each prover first translates the Copilot specification into an 4 | -- intermediate representation best suited for model checking. 5 | -- 6 | -- This module and the ones in the same namespace implement the IL format. A 7 | -- Copilot program is translated into a list of quantifier-free equations over 8 | -- integer sequences, implicitly universally quantified by a free variable n. 9 | -- Each sequence roughly corresponds to a stream. 10 | 11 | module Copilot.Theorem.IL (module X) where 12 | 13 | import Copilot.Theorem.IL.Spec as X 14 | import Copilot.Theorem.IL.Translate as X 15 | import Copilot.Theorem.IL.Transform as X 16 | import Copilot.Theorem.IL.PrettyPrint as X 17 | -------------------------------------------------------------------------------- /copilot/examples/Clock.hs: -------------------------------------------------------------------------------- 1 | -- Copyright © 2019 National Institute of Aerospace / Galois, Inc. 2 | 3 | -- | Example showing usage of clocks to generate periodically recurring truth 4 | -- values. 5 | 6 | module Main where 7 | 8 | import Language.Copilot 9 | import Copilot.Library.Clocks 10 | 11 | -- | We need to force a type for the argument of `period`. 12 | p :: Word8 13 | p = 5 14 | 15 | -- | Both have the same period, but a different phase. 16 | clkStream :: Stream Bool 17 | clkStream = clk (period p) (phase 0) 18 | 19 | clkStream' :: Stream Bool 20 | clkStream' = clk (period p) (phase 2) 21 | 22 | spec :: Spec 23 | spec = do 24 | observer "clk" clkStream 25 | observer "clk'" clkStream' 26 | 27 | main :: IO () 28 | main = interpret 30 spec 29 | -------------------------------------------------------------------------------- /copilot-c99/src/Copilot/Compile/C99/Representation.hs: -------------------------------------------------------------------------------- 1 | -- | C99 backend specific versions of selected `Copilot.Core` datatypes. 2 | module Copilot.Compile.C99.Representation 3 | ( UniqueTrigger (..) 4 | , UniqueTriggerId 5 | , mkUniqueTriggers 6 | ) 7 | where 8 | 9 | import Copilot.Core ( Trigger (..) ) 10 | 11 | -- | Internal unique name for a trigger. 12 | type UniqueTriggerId = String 13 | 14 | -- | A `Copilot.Core.Trigger` with an unique name. 15 | data UniqueTrigger = UniqueTrigger UniqueTriggerId Trigger 16 | 17 | -- | Given a list of triggers, make their names unique. 18 | mkUniqueTriggers :: [Trigger] -> [UniqueTrigger] 19 | mkUniqueTriggers ts = zipWith mkUnique ts [0..] 20 | where 21 | mkUnique t@(Trigger name _ _) n = UniqueTrigger (name ++ "_" ++ show n) t 22 | -------------------------------------------------------------------------------- /copilot-visualizer/examples/gui/Main.hs: -------------------------------------------------------------------------------- 1 | import Copilot.Visualize.Live 2 | 3 | main = visualize spec 4 | 5 | spec :: String 6 | spec = unlines 7 | [ "let temperature :: Stream Word8" 8 | , " temperature = extern \"temperature\" (Just [0, 15, 20, 25, 30])" 9 | , "" 10 | , " ctemp :: Stream Float" 11 | , " ctemp = (unsafeCast temperature) * (150.0 / 255.0) - 50.0" 12 | , "" 13 | , " trueFalse :: Stream Bool" 14 | , " trueFalse = [True] ++ not trueFalse" 15 | , "" 16 | , "in do trigger \"heaton\" (temperature < 18) [arg ctemp, arg (constI16 1), arg trueFalse]" 17 | , " trigger \"heatoff\" (temperature > 21) [arg (constI16 1), arg ctemp]" 18 | , " observer \"temperature\" temperature" 19 | , " observer \"temperature2\" (temperature + 1)" 20 | ] 21 | -------------------------------------------------------------------------------- /copilot-theorem/src/Copilot/Theorem.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE Safe #-} 2 | 3 | -- | Highly automated proof techniques are a necessary step for the widespread 4 | -- adoption of formal methods in the software industry. Moreover, it could 5 | -- provide a partial answer to one of its main issue which is scalability. 6 | -- 7 | -- Copilot-theorem is a Copilot library aimed at checking automatically some 8 | -- safety properties on Copilot programs. It includes: 9 | -- 10 | -- * A prover producing native inputs for the Kind2 model checker. 11 | -- 12 | -- * A What4 backend that uses SMT solvers to prove safety properties. 13 | 14 | module Copilot.Theorem 15 | ( module X 16 | , Proof 17 | , PropId, PropRef 18 | , Universal, Existential 19 | ) where 20 | 21 | import Copilot.Theorem.Tactics as X 22 | import Copilot.Theorem.Prove 23 | -------------------------------------------------------------------------------- /copilot-c99/src/Copilot/Compile/C99/Error.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE Safe #-} 2 | 3 | -- | 4 | -- Copyright: (c) 2011 National Institute of Aerospace / Galois, Inc. 5 | -- 6 | -- Custom functions to report error messages to users. 7 | module Copilot.Compile.C99.Error 8 | ( impossible ) 9 | where 10 | 11 | -- | Report an error due to a bug in Copilot. 12 | impossible :: String -- ^ Name of the function in which the error was detected. 13 | -> String -- ^ Name of the package in which the function is located. 14 | -> a 15 | impossible function package = 16 | error $ "Impossible error in function " 17 | ++ function ++ ", in package " ++ package 18 | ++ ". Please file an issue at " 19 | ++ "https://github.com/Copilot-Language/copilot/issues" 20 | ++ " or email the maintainers at " 21 | -------------------------------------------------------------------------------- /copilot-verifier/examples/Copilot/Verifier/Examples/ShouldPass/Partial/DivByZero.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE NoImplicitPrelude #-} 2 | 3 | -- | This will succeed with 'sideCondVerifierOptions', as Copilot's @Div@ 4 | -- operation is well defined precisely when C division is well defined. 5 | module Copilot.Verifier.Examples.ShouldPass.Partial.DivByZero where 6 | 7 | import Language.Copilot 8 | import Copilot.Compile.C99 9 | import Copilot.Verifier ( Verbosity, VerifierOptions(..) 10 | , sideCondVerifierOptions, verifyWithOptions ) 11 | import Copilot.Verifier.Examples.ShouldFail.Partial.DivByZero (spec) 12 | 13 | verifySpec :: Verbosity -> IO () 14 | verifySpec verb = do 15 | spec' <- reify spec 16 | verifyWithOptions sideCondVerifierOptions{verbosity = verb} 17 | mkDefaultCSettings 18 | [] 19 | "divByZeroPass" spec' 20 | -------------------------------------------------------------------------------- /copilot-bluespec/src/Copilot/Compile/Bluespec/Error.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE Safe #-} 2 | 3 | -- | 4 | -- Copyright: (c) 2011 National Institute of Aerospace / Galois, Inc. 5 | -- 6 | -- Custom functions to report error messages to users. 7 | module Copilot.Compile.Bluespec.Error 8 | ( impossible ) 9 | where 10 | 11 | -- | Report an error due to a bug in Copilot. 12 | impossible :: String -- ^ Name of the function in which the error was detected. 13 | -> String -- ^ Name of the package in which the function is located. 14 | -> a 15 | impossible function package = 16 | error $ "Impossible error in function " 17 | ++ function ++ ", in package " ++ package 18 | ++ ". Please file an issue at " 19 | ++ "https://github.com/Copilot-Language/copilot/issues" 20 | ++ " or email the maintainers at " 21 | -------------------------------------------------------------------------------- /copilot-verifier/examples/Copilot/Verifier/Examples/ShouldPass/Partial/AbsIntMin.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE NoImplicitPrelude #-} 2 | 3 | -- | This will succeed with 'sideCondVerifierOptions', as Copilot's @Abs@ 4 | -- operation is well defined precisely when C's @abs@ function is well defined. 5 | module Copilot.Verifier.Examples.ShouldPass.Partial.AbsIntMin where 6 | 7 | import Language.Copilot 8 | import Copilot.Compile.C99 9 | import Copilot.Verifier ( Verbosity, VerifierOptions(..) 10 | , sideCondVerifierOptions, verifyWithOptions ) 11 | import Copilot.Verifier.Examples.ShouldFail.Partial.AbsIntMin (spec) 12 | 13 | verifySpec :: Verbosity -> IO () 14 | verifySpec verb = do 15 | spec' <- reify spec 16 | verifyWithOptions sideCondVerifierOptions{verbosity = verb} 17 | mkDefaultCSettings 18 | [] 19 | "absIntMinPass" spec' 20 | -------------------------------------------------------------------------------- /copilot-verifier/examples/Copilot/Verifier/Examples/ShouldPass/Partial/ModByZero.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE NoImplicitPrelude #-} 2 | 3 | -- | This will succeed with 'sideCondVerifierOptions', as Copilot's @Mod@ 4 | -- operation is well defined precisely when C's @%@ operator is well defined. 5 | module Copilot.Verifier.Examples.ShouldPass.Partial.ModByZero where 6 | 7 | import Language.Copilot 8 | import Copilot.Compile.C99 9 | import Copilot.Verifier ( Verbosity, VerifierOptions(..) 10 | , sideCondVerifierOptions, verifyWithOptions ) 11 | import Copilot.Verifier.Examples.ShouldFail.Partial.ModByZero (spec) 12 | 13 | verifySpec :: Verbosity -> IO () 14 | verifySpec verb = do 15 | spec' <- reify spec 16 | verifyWithOptions sideCondVerifierOptions{verbosity = verb} 17 | mkDefaultCSettings 18 | [] 19 | "modByZeroPass" spec' 20 | -------------------------------------------------------------------------------- /copilot-bluespec/src/Copilot/Compile/Bluespec/Representation.hs: -------------------------------------------------------------------------------- 1 | -- | Bluespec backend specific versions of selected `Copilot.Core` datatypes. 2 | module Copilot.Compile.Bluespec.Representation 3 | ( UniqueTrigger (..) 4 | , UniqueTriggerId 5 | , mkUniqueTriggers 6 | ) 7 | where 8 | 9 | import Copilot.Core ( Trigger (..) ) 10 | 11 | -- | Internal unique name for a trigger. 12 | type UniqueTriggerId = String 13 | 14 | -- | A `Copilot.Core.Trigger` with an unique name. 15 | data UniqueTrigger = UniqueTrigger UniqueTriggerId Trigger 16 | 17 | -- | Given a list of triggers, make their names unique. 18 | mkUniqueTriggers :: [Trigger] -> [UniqueTrigger] 19 | mkUniqueTriggers ts = zipWith mkUnique ts [0..] 20 | where 21 | mkUnique :: Trigger -> Integer -> UniqueTrigger 22 | mkUnique t@(Trigger name _ _) n = UniqueTrigger (name ++ "_" ++ show n) t 23 | -------------------------------------------------------------------------------- /copilot-verifier/examples/Copilot/Verifier/Examples/ShouldPass/ArrayTriggerArgument.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE DataKinds #-} 2 | 3 | -- | A regression test for 4 | -- . 5 | module Copilot.Verifier.Examples.ShouldPass.ArrayTriggerArgument where 6 | 7 | import Language.Copilot 8 | import Copilot.Compile.C99 9 | import Copilot.Verifier ( Verbosity, VerifierOptions(..) 10 | , defaultVerifierOptions, verifyWithOptions ) 11 | 12 | spec :: Spec 13 | spec = trigger "f" true [arg stream] 14 | where 15 | stream :: Stream (Array 2 Int16) 16 | stream = constant (array [3,4]) 17 | 18 | verifySpec :: Verbosity -> IO () 19 | verifySpec verb = do 20 | spec' <- reify spec 21 | verifyWithOptions 22 | defaultVerifierOptions{verbosity = verb} 23 | mkDefaultCSettings [] "arrayTriggerArgument" spec' 24 | -------------------------------------------------------------------------------- /copilot-verifier/examples/Copilot/Verifier/Examples/ShouldPass/Partial/AddSignedWrap.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE NoImplicitPrelude #-} 2 | 3 | -- | This will succeed with 'sideCondVerifierOptions', as Copilot's @Add@ 4 | -- operation should overflow on signed integers precisely when C addition does. 5 | module Copilot.Verifier.Examples.ShouldPass.Partial.AddSignedWrap where 6 | 7 | import Language.Copilot 8 | import Copilot.Compile.C99 9 | import Copilot.Verifier ( Verbosity, VerifierOptions(..) 10 | , sideCondVerifierOptions, verifyWithOptions ) 11 | import Copilot.Verifier.Examples.ShouldFail.Partial.AddSignedWrap (spec) 12 | 13 | verifySpec :: Verbosity -> IO () 14 | verifySpec verb = do 15 | spec' <- reify spec 16 | verifyWithOptions sideCondVerifierOptions{verbosity = verb} 17 | mkDefaultCSettings 18 | [] 19 | "addSignedWrapPass" spec' 20 | -------------------------------------------------------------------------------- /copilot-verifier/src/Copilot/Verifier/Solver.hs: -------------------------------------------------------------------------------- 1 | module Copilot.Verifier.Solver 2 | ( Solver(..) 3 | , solverAdapter 4 | ) where 5 | 6 | import qualified What4.Solver.Adapter as W4 7 | import qualified What4.Solver.CVC4 as W4.CVC4 8 | import qualified What4.Solver.CVC5 as W4.CVC5 9 | import qualified What4.Solver.Yices as W4.Yices 10 | import qualified What4.Solver.Z3 as W4.Z3 11 | 12 | -- | General-purpose SMT solvers that @copilot-verifier@ supports. 13 | data Solver 14 | = CVC4 15 | | CVC5 16 | | Yices 17 | | Z3 18 | deriving Show 19 | 20 | -- | Return the @what4@ 'W4.SolverAdapter' corresponding to a given 'Solver'. 21 | solverAdapter :: Solver -> W4.SolverAdapter st 22 | solverAdapter CVC4 = W4.CVC4.cvc4Adapter 23 | solverAdapter CVC5 = W4.CVC5.cvc5Adapter 24 | solverAdapter Yices = W4.Yices.yicesAdapter 25 | solverAdapter Z3 = W4.Z3.z3Adapter 26 | -------------------------------------------------------------------------------- /copilot-verifier/examples/Copilot/Verifier/Examples/ShouldPass/Partial/MulSignedWrap.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE NoImplicitPrelude #-} 2 | 3 | -- | This will succeed with 'sideCondVerifierOptions', as Copilot's @Mul@ 4 | -- operation should wrap on signed integers precisely when C multiplication does. 5 | module Copilot.Verifier.Examples.ShouldPass.Partial.MulSignedWrap where 6 | 7 | import Language.Copilot 8 | import Copilot.Compile.C99 9 | import Copilot.Verifier ( Verbosity, VerifierOptions(..) 10 | , sideCondVerifierOptions, verifyWithOptions ) 11 | import Copilot.Verifier.Examples.ShouldFail.Partial.MulSignedWrap (spec) 12 | 13 | verifySpec :: Verbosity -> IO () 14 | verifySpec verb = do 15 | spec' <- reify spec 16 | verifyWithOptions sideCondVerifierOptions{verbosity = verb} 17 | mkDefaultCSettings 18 | [] 19 | "mulSignedWrapPass" spec' 20 | -------------------------------------------------------------------------------- /copilot-verifier/examples/Copilot/Verifier/Examples/ShouldPass/Partial/SubSignedWrap.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE NoImplicitPrelude #-} 2 | 3 | -- | This will succeed with 'sideCondVerifierOptions', as Copilot's @Sub@ 4 | -- operation should underflow on signed integers precisely when C subtraction does. 5 | module Copilot.Verifier.Examples.ShouldPass.Partial.SubSignedWrap where 6 | 7 | import Language.Copilot 8 | import Copilot.Compile.C99 9 | import Copilot.Verifier ( Verbosity, VerifierOptions(..) 10 | , sideCondVerifierOptions, verifyWithOptions ) 11 | import Copilot.Verifier.Examples.ShouldFail.Partial.SubSignedWrap (spec) 12 | 13 | verifySpec :: Verbosity -> IO () 14 | verifySpec verb = do 15 | spec' <- reify spec 16 | verifyWithOptions sideCondVerifierOptions{verbosity = verb} 17 | mkDefaultCSettings 18 | [] 19 | "subSignedWrapPass" spec' 20 | -------------------------------------------------------------------------------- /copilot-verifier/examples/Copilot/Verifier/Examples/ShouldPass/Partial/IndexOutOfBounds.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE NoImplicitPrelude #-} 2 | 3 | -- | This will succeed with 'sideCondVerifierOptions', as Copilot's indexing 4 | -- operation should be out of bounds precisely when C array indexes are out of bounds. 5 | module Copilot.Verifier.Examples.ShouldPass.Partial.IndexOutOfBounds where 6 | 7 | import Language.Copilot 8 | import Copilot.Compile.C99 9 | import Copilot.Verifier ( Verbosity, VerifierOptions(..) 10 | , sideCondVerifierOptions, verifyWithOptions ) 11 | import Copilot.Verifier.Examples.ShouldFail.Partial.IndexOutOfBounds (spec) 12 | 13 | verifySpec :: Verbosity -> IO () 14 | verifySpec verb = do 15 | spec' <- reify spec 16 | verifyWithOptions sideCondVerifierOptions{verbosity = verb} 17 | mkDefaultCSettings 18 | [] 19 | "indexPass" spec' 20 | -------------------------------------------------------------------------------- /copilot-verifier/examples/Copilot/Verifier/Examples/ShouldPass/ArrayGen.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE DataKinds #-} 2 | module Copilot.Verifier.Examples.ShouldPass.ArrayGen where 3 | 4 | import Copilot.Compile.C99 5 | import Copilot.Verifier ( Verbosity, VerifierOptions(..) 6 | , defaultVerifierOptions, verifyWithOptions ) 7 | import Language.Copilot 8 | import qualified Prelude hiding ((++), (>)) 9 | 10 | spec :: Spec 11 | spec = trigger "f" (stream ! 0 > 0) [arg stream] 12 | where 13 | stream :: Stream (Array 2 Int16) 14 | stream = [array [3,4]] ++ rest 15 | 16 | rest :: Stream (Array 2 Int16) 17 | rest = constant $ array [5,6] 18 | 19 | verifySpec :: Verbosity -> IO () 20 | verifySpec verb = reify spec >>= verifyWithOptions defaultVerifierOptions{verbosity = verb} 21 | mkDefaultCSettings [] "arrayGen" 22 | -------------------------------------------------------------------------------- /copilot-verifier/examples/Copilot/Verifier/Examples/ShouldPass/Partial/ShiftLTooLarge.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE NoImplicitPrelude #-} 2 | 3 | -- | This will succeed with 'sideCondVerifierOptions', as Copilot's @BwShiftL@ 4 | -- operation should only accept second arguments as large as C's @<<@ operation does. 5 | module Copilot.Verifier.Examples.ShouldPass.Partial.ShiftLTooLarge where 6 | 7 | import Language.Copilot 8 | import Copilot.Compile.C99 9 | import Copilot.Verifier ( Verbosity, VerifierOptions(..) 10 | , sideCondVerifierOptions, verifyWithOptions ) 11 | import Copilot.Verifier.Examples.ShouldFail.Partial.ShiftLTooLarge (spec) 12 | 13 | verifySpec :: Verbosity -> IO () 14 | verifySpec verb = do 15 | spec' <- reify spec 16 | verifyWithOptions sideCondVerifierOptions{verbosity = verb} 17 | mkDefaultCSettings 18 | [] 19 | "shiftLTooLargePass" spec' 20 | -------------------------------------------------------------------------------- /copilot-verifier/examples/Copilot/Verifier/Examples/ShouldPass/Partial/ShiftRTooLarge.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE NoImplicitPrelude #-} 2 | 3 | -- | This will succeed with 'sideCondVerifierOptions', as Copilot's @BwShiftR@ 4 | -- operation should only accept second arguments as large as C's @>>@ operation does. 5 | module Copilot.Verifier.Examples.ShouldPass.Partial.ShiftRTooLarge where 6 | 7 | import Language.Copilot 8 | import Copilot.Compile.C99 9 | import Copilot.Verifier ( Verbosity, VerifierOptions(..) 10 | , sideCondVerifierOptions, verifyWithOptions ) 11 | import Copilot.Verifier.Examples.ShouldFail.Partial.ShiftRTooLarge (spec) 12 | 13 | verifySpec :: Verbosity -> IO () 14 | verifySpec verb = do 15 | spec' <- reify spec 16 | verifyWithOptions sideCondVerifierOptions{verbosity = verb} 17 | mkDefaultCSettings 18 | [] 19 | "shiftRTooLargePass" spec' 20 | -------------------------------------------------------------------------------- /copilot-interpreter/src/Copilot/Interpret.hs: -------------------------------------------------------------------------------- 1 | -- Copyright © 2011 National Institute of Aerospace / Galois, Inc. 2 | 3 | -- | An interpreter for Copilot specifications. 4 | 5 | {-# LANGUAGE Safe #-} 6 | 7 | module Copilot.Interpret 8 | ( Format (..) 9 | , interpret 10 | ) where 11 | 12 | import Copilot.Core 13 | import Copilot.Interpret.Eval 14 | import Copilot.Interpret.Render 15 | 16 | -- | Output format for the results of a Copilot spec interpretation. 17 | data Format = Table | CSV 18 | 19 | -- | Interpret a Copilot specification. 20 | interpret :: Format -- ^ Format to be used for the output. 21 | -> Int -- ^ Number of steps to interpret. 22 | -> Spec -- ^ Specification to interpret. 23 | -> String 24 | interpret format k spec = 25 | case format of 26 | Table -> renderAsTable e 27 | CSV -> renderAsCSV e 28 | where 29 | e = eval Haskell k spec 30 | -------------------------------------------------------------------------------- /copilot/examples/Counter.hs: -------------------------------------------------------------------------------- 1 | -- Copyright © 2019 National Institute of Aerospace / Galois, Inc. 2 | 3 | -- | Example showing an implementation of a resettable counter. 4 | 5 | {-# LANGUAGE RebindableSyntax #-} 6 | 7 | module Main where 8 | 9 | import Language.Copilot 10 | import Copilot.Compile.C99 11 | 12 | -- A resettable counter 13 | counter :: Stream Bool -> Stream Bool -> Stream Int32 14 | counter inc reset = cnt 15 | where 16 | cnt = if reset then 0 17 | else if inc then z + 1 18 | else z 19 | z = [0] ++ cnt 20 | 21 | -- Counter that resets when it reaches 256 22 | bytecounter :: Stream Int32 23 | bytecounter = counter true reset 24 | where 25 | reset = counter true false `mod` 256 == 0 26 | 27 | spec :: Spec 28 | spec = trigger "counter" true [arg $ bytecounter] 29 | 30 | main :: IO () 31 | -- main = interpret 1280 spec 32 | main = reify spec >>= compile "counter" 33 | -------------------------------------------------------------------------------- /copilot-theorem/src/Copilot/Theorem/TransSys.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE Safe #-} 2 | 3 | -- | Each prover first translates the Copilot specification into an 4 | -- intermediate representation best suited for model checking. 5 | -- 6 | -- This module and the ones in the same namespace implement the TransSys 7 | -- format. A Copilot program is /flattened/ and translated into a /state/ 8 | -- /transition system/. In order to keep some structure in this 9 | -- representation, the variables of this system are grouped by /nodes/, each 10 | -- node exporting and importing variables. The /Kind2 prover/ uses this format, 11 | -- which can be easily translated into the native format. 12 | module Copilot.Theorem.TransSys (module X) where 13 | 14 | import Copilot.Theorem.TransSys.Spec as X 15 | import Copilot.Theorem.TransSys.PrettyPrint as X 16 | import Copilot.Theorem.TransSys.Translate as X 17 | import Copilot.Theorem.TransSys.Transform as X 18 | -------------------------------------------------------------------------------- /copilot-language/src/Copilot/Language/Operators/Label.hs: -------------------------------------------------------------------------------- 1 | -- Copyright © 2011 National Institute of Aerospace / Galois, Inc. 2 | 3 | -- | Label a stream with additional information. 4 | 5 | {-# LANGUAGE Safe #-} 6 | 7 | module Copilot.Language.Operators.Label 8 | ( label 9 | ) where 10 | 11 | import Copilot.Core (Typed) 12 | import Copilot.Language.Stream (Stream (..)) 13 | 14 | -- | This function allows you to label a stream with a tag, which can be used 15 | -- by different backends to provide additional information either in error 16 | -- messages or in the generated code (e.g., for traceability purposes). 17 | -- 18 | -- Semantically, a labelled stream is just the stream inside it. The use of 19 | -- label should not affect the observable behavior of the monitor, and how it 20 | -- is used in the code generated is a decision specific to each backend. 21 | label :: (Typed a) => String -> Stream a -> Stream a 22 | label = Label 23 | -------------------------------------------------------------------------------- /copilot-language/src/System/Mem/StableName/Dynamic.hs: -------------------------------------------------------------------------------- 1 | -- Copyright © 2011 National Institute of Aerospace / Galois, Inc. 2 | 3 | {-# LANGUAGE ExistentialQuantification #-} 4 | {-# LANGUAGE Safe #-} 5 | 6 | module System.Mem.StableName.Dynamic 7 | ( DynStableName(..) 8 | , hashDynStableName 9 | , makeDynStableName 10 | ) where 11 | 12 | import System.Mem.StableName (StableName, eqStableName, makeStableName, 13 | hashStableName) 14 | 15 | data DynStableName = forall a . DynStableName (StableName a) 16 | 17 | makeDynStableName :: a -> IO DynStableName 18 | makeDynStableName x = 19 | do 20 | stn <- makeStableName x 21 | return (DynStableName stn) 22 | 23 | hashDynStableName :: DynStableName -> Int 24 | hashDynStableName (DynStableName sn) = hashStableName sn 25 | 26 | instance Eq DynStableName where 27 | DynStableName sn1 == DynStableName sn2 = eqStableName sn1 sn2 28 | -------------------------------------------------------------------------------- /copilot-verifier/examples/Copilot/Verifier/Examples/ShouldFail/Partial/DivByZero.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE NoImplicitPrelude #-} 2 | 3 | -- | This will fail to verify since the verification does not assume the 4 | -- @nonzero@ property, which is needed to prevent a division-by-zero error. 5 | module Copilot.Verifier.Examples.ShouldFail.Partial.DivByZero where 6 | 7 | import Language.Copilot 8 | import Copilot.Compile.C99 9 | import Copilot.Verifier ( Verbosity, VerifierOptions(..) 10 | , defaultVerifierOptions, verifyWithOptions ) 11 | 12 | spec :: Spec 13 | spec = do 14 | let stream :: Stream Int16 15 | stream = extern "stream" Nothing 16 | 17 | _ <- prop "nonzero" (forAll (stream /= 0)) 18 | trigger "streamDiv" ((stream `div` stream) == 1) [arg stream] 19 | 20 | verifySpec :: Verbosity -> IO () 21 | verifySpec verb = do 22 | spec' <- reify spec 23 | verifyWithOptions defaultVerifierOptions{verbosity = verb} 24 | mkDefaultCSettings 25 | -- ["nonzero"] 26 | [] 27 | "divByZeroFail" spec' 28 | -------------------------------------------------------------------------------- /copilot-verifier/examples/Copilot/Verifier/Examples/ShouldFail/Partial/ModByZero.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE NoImplicitPrelude #-} 2 | 3 | -- | This will fail to verify since the verification does not assume the 4 | -- @nonzero@ property, which is needed to prevent a division-by-zero error. 5 | module Copilot.Verifier.Examples.ShouldFail.Partial.ModByZero where 6 | 7 | import Language.Copilot 8 | import Copilot.Compile.C99 9 | import Copilot.Verifier ( Verbosity, VerifierOptions(..) 10 | , defaultVerifierOptions, verifyWithOptions ) 11 | 12 | spec :: Spec 13 | spec = do 14 | let stream :: Stream Int16 15 | stream = extern "stream" Nothing 16 | 17 | _ <- prop "nonzero" (forAll (stream /= 0)) 18 | trigger "streamMod" ((stream `mod` stream) == 1) [arg stream] 19 | 20 | verifySpec :: Verbosity -> IO () 21 | verifySpec verb = do 22 | spec' <- reify spec 23 | verifyWithOptions defaultVerifierOptions{verbosity = verb} 24 | mkDefaultCSettings 25 | -- ["nonzero"] 26 | [] 27 | "modByZeroFail" spec' 28 | -------------------------------------------------------------------------------- /copilot-language/src/Copilot/Language/Error.hs: -------------------------------------------------------------------------------- 1 | -- Copyright © 2011 National Institute of Aerospace / Galois, Inc. 2 | 3 | {-# LANGUAGE Safe #-} 4 | 5 | -- | Custom functions to report error messages to users. 6 | module Copilot.Language.Error 7 | ( impossible 8 | , badUsage ) where 9 | 10 | -- | Report an error due to a bug in Copilot. 11 | impossible :: String -- ^ Name of the function in which the error was detected. 12 | -> String -- ^ Name of the package in which the function is located. 13 | -> a 14 | impossible function package = 15 | error $ "Impossible error in function " 16 | ++ function ++ ", in package " ++ package 17 | ++ ". Please file an issue at " 18 | ++ "https://github.com/Copilot-Language/copilot/issues" 19 | ++ "or email the maintainers at " 20 | 21 | -- | Report an error due to an error detected by Copilot (e.g., user error). 22 | badUsage :: String -- ^ Description of the error. 23 | -> a 24 | badUsage msg = error $ "Copilot error: " ++ msg 25 | -------------------------------------------------------------------------------- /copilot-prettyprinter/src/Copilot/PrettyPrint/Error.hs: -------------------------------------------------------------------------------- 1 | -- Copyright © 2011 National Institute of Aerospace / Galois, Inc. 2 | 3 | {-# LANGUAGE Safe #-} 4 | 5 | -- | Custom functions to report error messages to users. 6 | module Copilot.PrettyPrint.Error 7 | ( impossible 8 | , badUsage ) where 9 | 10 | -- | Report an error due to a bug in Copilot. 11 | impossible :: String -- ^ Name of the function in which the error was detected. 12 | -> String -- ^ Name of the package in which the function is located. 13 | -> a 14 | impossible function package = 15 | error $ "\"Impossible\" error in function " 16 | ++ function ++ ", in package " ++ package 17 | ++ ". Please file an issue at " 18 | ++ "https://github.com/Copilot-Language/copilot/issues" 19 | ++ "or email the maintainers at " 20 | 21 | -- | Report an error due to an error detected by Copilot (e.g., user error). 22 | badUsage :: String -- ^ Description of the error. 23 | -> a 24 | badUsage msg = error $ "Copilot error: " ++ msg 25 | -------------------------------------------------------------------------------- /copilot-verifier/examples/Copilot/Verifier/Examples/ShouldPass/ArrayOfStructs.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE DataKinds #-} 2 | {-# LANGUAGE NoImplicitPrelude #-} 3 | module Copilot.Verifier.Examples.ShouldPass.ArrayOfStructs where 4 | 5 | import Copilot.Compile.C99 6 | import Copilot.Verifier ( Verbosity, VerifierOptions(..) 7 | , defaultVerifierOptions, verifyWithOptions ) 8 | import Language.Copilot 9 | 10 | data S = S { field :: Field "field" Int16 } 11 | 12 | instance Struct S where 13 | typeName _ = "s" 14 | toValues s = [Value Int16 (field s)] 15 | 16 | instance Typed S where 17 | typeOf = Struct (S (Field 0)) 18 | 19 | spec :: Spec 20 | spec = trigger "f" ((stream ! 0)#field == 27) [arg stream] 21 | where 22 | stream :: Stream (Array 2 S) 23 | stream = [array [S (Field 27), S (Field 42)]] ++ stream 24 | 25 | verifySpec :: Verbosity -> IO () 26 | verifySpec verb = do 27 | spec' <- reify spec 28 | verifyWithOptions defaultVerifierOptions{verbosity = verb} 29 | mkDefaultCSettings [] "arrayOfStructs" spec' 30 | -------------------------------------------------------------------------------- /copilot-libraries/src/Copilot/Library/Libraries.hs: -------------------------------------------------------------------------------- 1 | -- | 2 | -- Module: Libraries 3 | -- Description: Main import module for libraries 4 | -- Copyright: (c) 2011 National Institute of Aerospace / Galois, Inc. 5 | -- 6 | -- This is a convenience module that re-exports a useful subset of modules from 7 | -- @copilot-library@. Not all modules are exported due to name clashes (e.g., 8 | -- in temporal logics implementations). 9 | 10 | module Copilot.Library.Libraries ( 11 | module Copilot.Library.Clocks 12 | , module Copilot.Library.LTL 13 | , module Copilot.Library.PTLTL 14 | , module Copilot.Library.Statistics 15 | , module Copilot.Library.RegExp 16 | , module Copilot.Library.Utils 17 | , module Copilot.Library.Voting 18 | , module Copilot.Library.Stacks 19 | ) where 20 | 21 | import Copilot.Library.Clocks 22 | import Copilot.Library.LTL 23 | import Copilot.Library.PTLTL 24 | import Copilot.Library.Statistics 25 | import Copilot.Library.RegExp 26 | import Copilot.Library.Utils 27 | import Copilot.Library.Voting 28 | import Copilot.Library.Stacks 29 | -------------------------------------------------------------------------------- /copilot-verifier/examples/Copilot/Verifier/Examples/ShouldFail/Partial/AddSignedWrap.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE NoImplicitPrelude #-} 2 | 3 | -- | This will fail to verify since the verification does not assume the 4 | -- @notIntMax@ property, which is needed to prevent signed integer overflow. 5 | module Copilot.Verifier.Examples.ShouldFail.Partial.AddSignedWrap where 6 | 7 | import Language.Copilot 8 | import Copilot.Compile.C99 9 | import Copilot.Verifier ( Verbosity, VerifierOptions(..) 10 | , defaultVerifierOptions, verifyWithOptions ) 11 | 12 | spec :: Spec 13 | spec = do 14 | let stream :: Stream Int32 15 | stream = extern "stream" Nothing 16 | 17 | _ <- prop "notIntMax" (forAll (stream < constI32 maxBound)) 18 | trigger "streamAddSigned" ((stream + 1) == 1) [arg stream] 19 | 20 | verifySpec :: Verbosity -> IO () 21 | verifySpec verb = do 22 | spec' <- reify spec 23 | verifyWithOptions defaultVerifierOptions{verbosity = verb} 24 | mkDefaultCSettings 25 | -- ["notIntMax"] 26 | [] 27 | "addSignedWrapFail" spec' 28 | -------------------------------------------------------------------------------- /copilot-verifier/examples/Copilot/Verifier/Examples/ShouldFail/Partial/SubSignedWrap.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE NoImplicitPrelude #-} 2 | 3 | -- | This will fail to verify since the verification does not assume the 4 | -- @notIntMin@ property, which is needed to prevent signed integer underflow. 5 | module Copilot.Verifier.Examples.ShouldFail.Partial.SubSignedWrap where 6 | 7 | import Language.Copilot 8 | import Copilot.Compile.C99 9 | import Copilot.Verifier ( Verbosity, VerifierOptions(..) 10 | , defaultVerifierOptions, verifyWithOptions ) 11 | 12 | spec :: Spec 13 | spec = do 14 | let stream :: Stream Int32 15 | stream = extern "stream" Nothing 16 | 17 | _ <- prop "notIntMin" (forAll (stream > constI32 minBound)) 18 | trigger "streamSubSigned" ((stream - 1) == 1) [arg stream] 19 | 20 | verifySpec :: Verbosity -> IO () 21 | verifySpec verb = do 22 | spec' <- reify spec 23 | verifyWithOptions defaultVerifierOptions{verbosity = verb} 24 | mkDefaultCSettings 25 | -- ["notIntMin"] 26 | [] 27 | "subSignedWrapFail" spec' 28 | -------------------------------------------------------------------------------- /copilot-verifier/examples/Copilot/Verifier/Examples/ShouldFail/Partial/AbsIntMin.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE NoImplicitPrelude #-} 2 | 3 | -- | This will fail to verify since the verification does not assume the 4 | -- @notIntMin@ property, which is needed to prevent undefined behavior when 5 | -- invoking the 'abs' function. 6 | module Copilot.Verifier.Examples.ShouldFail.Partial.AbsIntMin where 7 | 8 | import Language.Copilot 9 | import Copilot.Compile.C99 10 | import Copilot.Verifier ( Verbosity, VerifierOptions(..) 11 | , defaultVerifierOptions, verifyWithOptions ) 12 | 13 | spec :: Spec 14 | spec = do 15 | let stream :: Stream Int32 16 | stream = extern "stream" Nothing 17 | 18 | _ <- prop "notIntMin" (forAll (stream > constI32 minBound)) 19 | trigger "streamAbs" (abs stream == 1) [arg stream] 20 | 21 | verifySpec :: Verbosity -> IO () 22 | verifySpec verb = do 23 | spec' <- reify spec 24 | verifyWithOptions defaultVerifierOptions{verbosity = verb} 25 | mkDefaultCSettings 26 | -- ["notIntMin"] 27 | [] 28 | "absIntMinFail" spec' 29 | -------------------------------------------------------------------------------- /copilot-visualizer/examples/gui/copilot.css: -------------------------------------------------------------------------------- 1 | /* Timeline */ 2 | /* Timeline decoration: Grid */ 3 | .axis path, 4 | .axis line { 5 | fill: none; 6 | stroke: #000; 7 | shape-rendering: crispEdges; 8 | } 9 | .grid-line { 10 | stroke: #ccc; 11 | stroke-width: 1; 12 | stroke-dasharray: 3,3; 13 | } 14 | 15 | /* Timeline decoration: Labels */ 16 | .label { 17 | font-size: 12px; 18 | } 19 | .time-label { 20 | font-family: sans-serif; 21 | font-size: 12px; 22 | fill: black; 23 | } 24 | .value-text { 25 | font-size: 10px; 26 | text-anchor: middle; 27 | dominant-baseline: middle; 28 | } 29 | 30 | /* Timeline decoration: Values */ 31 | .hexagon { 32 | stroke: black; 33 | stroke-width: 1px; 34 | color: green; 35 | } 36 | .bool-background { 37 | opacity: 0.3; 38 | } 39 | 40 | /* Toolbar buttons */ 41 | button { 42 | width: 100px !important; 43 | height: 48px !important; 44 | border-radius: 24px !important; 45 | background-color: #f1316b !important; 46 | color: #fff !important; 47 | margin-top: 45px !important; 48 | border:none !important; 49 | font-size: 12px !important; 50 | } 51 | -------------------------------------------------------------------------------- /copilot-theorem/examples/Grey.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE RebindableSyntax #-} 2 | 3 | module Grey where 4 | 5 | import Copilot.Language 6 | import Copilot.Theorem 7 | import Copilot.Theorem.Prover.Z3 8 | 9 | import Prelude () 10 | import Data.String (fromString) 11 | 12 | intCounter :: Stream Bool -> Stream Word64 13 | intCounter reset = time 14 | where 15 | time = if reset then 0 16 | else [0] ++ if time == 3 then 0 else time + 1 17 | 18 | greyTick :: Stream Bool -> Stream Bool 19 | greyTick reset = a && b 20 | where 21 | a = (not reset) && ([False] ++ not b) 22 | b = (not reset) && ([False] ++ a) 23 | 24 | spec = do 25 | theorem "iResetOk" (forAll $ r ==> (ic == 0)) induct 26 | theorem "eqCounters" (forAll $ it == gt) $ kinduct 3 27 | 28 | where 29 | ic = intCounter r 30 | it = ic == 2 31 | gt = greyTick r 32 | r = extern "reset" Nothing 33 | 34 | induct :: Proof Universal 35 | induct = induction def { nraNLSat = False, debug = False } 36 | 37 | kinduct :: Word32 -> Proof Universal 38 | kinduct k = kInduction def { nraNLSat = False, startK = k, maxK = k, debug = False } 39 | -------------------------------------------------------------------------------- /copilot-theorem/src/Copilot/Theorem/Misc/Error.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE Safe #-} 2 | 3 | -- | Custom functions to report error messages to users. 4 | module Copilot.Theorem.Misc.Error 5 | ( badUse 6 | , impossible 7 | , impossible_ 8 | , fatal 9 | ) where 10 | 11 | -- | Tag used with error messages to help users locate the component that 12 | -- failed or reports the error. 13 | errorHeader :: String 14 | errorHeader = "[Copilot-kind ERROR] " 15 | 16 | -- | Report an error due to an error detected by Copilot (e.g., user error). 17 | badUse :: String -- ^ Description of the error. 18 | -> a 19 | badUse s = error $ errorHeader ++ s 20 | 21 | -- | Report an error due to a bug in Copilot. 22 | impossible :: String -- ^ Error information to attach to the message. 23 | -> a 24 | impossible s = error $ errorHeader ++ "Unexpected internal error : " ++ s 25 | 26 | -- | Report an error due to a bug in Copilot. 27 | impossible_ :: a 28 | impossible_ = error $ errorHeader ++ "Unexpected internal error" 29 | 30 | -- | Report an unrecoverable error (e.g., incorrect format). 31 | fatal :: String -> a 32 | fatal = error 33 | -------------------------------------------------------------------------------- /copilot-theorem/src/Copilot/Theorem/TransSys/Type.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE ExistentialQuantification #-} 2 | {-# LANGUAGE GADTs #-} 3 | {-# LANGUAGE Safe #-} 4 | 5 | -- | Types suported by the modular transition systems. 6 | module Copilot.Theorem.TransSys.Type 7 | ( Type (..) 8 | , U (..) 9 | ) where 10 | 11 | import Data.Type.Equality 12 | 13 | -- | A type at both value and type level. 14 | -- 15 | -- Real numbers are mapped to 'Double's. 16 | data Type a where 17 | Bool :: Type Bool 18 | Integer :: Type Integer 19 | Real :: Type Double 20 | 21 | -- | Proofs of type equality. 22 | instance TestEquality Type where 23 | testEquality Bool Bool = Just Refl 24 | testEquality Integer Integer = Just Refl 25 | testEquality Real Real = Just Refl 26 | testEquality _ _ = Nothing 27 | 28 | -- | Unknown types. 29 | -- 30 | -- For instance, 'U Expr' is the type of an expression of unknown type 31 | data U f = forall t . U (f t) 32 | 33 | instance Show (Type t) where 34 | show Integer = "Int" 35 | show Bool = "Bool" 36 | show Real = "Real" 37 | -------------------------------------------------------------------------------- /copilot-language/src/Copilot/Language/Operators/Propositional.hs: -------------------------------------------------------------------------------- 1 | -- Copyright © 2011 National Institute of Aerospace / Galois, Inc. 2 | 3 | {-# LANGUAGE FlexibleInstances #-} 4 | {-# LANGUAGE GADTs #-} 5 | {-# LANGUAGE MultiParamTypeClasses #-} 6 | {-# LANGUAGE Safe #-} 7 | 8 | -- | Implement negation over quantified extensions of boolean streams. 9 | -- 10 | -- For details, see 'Prop'. 11 | module Copilot.Language.Operators.Propositional (not) where 12 | 13 | import Prelude (($)) 14 | 15 | import Copilot.Language.Spec (Prop (..)) 16 | import qualified Copilot.Language.Operators.Boolean as B 17 | 18 | import Copilot.Theorem 19 | 20 | -- | A proposition that can be negated. 21 | class Negatable a b where 22 | -- | Negate a proposition. 23 | not :: a -> b 24 | 25 | -- | Negation of an existentially quantified proposition. 26 | instance Negatable (Prop Existential) (Prop Universal) where 27 | not (Exists p) = Forall $ B.not p 28 | 29 | -- | Negation of a universally quantified proposition. 30 | instance Negatable (Prop Universal) (Prop Existential) where 31 | not (Forall p) = Exists $ B.not p 32 | -------------------------------------------------------------------------------- /copilot/src/Language/Copilot.hs: -------------------------------------------------------------------------------- 1 | -- | Copilot is a stream-based runtime verification framework. Programs can be 2 | -- interpreted for testing, or translated into C99 code to be incorporated in a 3 | -- project, or as a standalone application. The C99 backend output is constant 4 | -- in memory and time, making it suitable for systems with hard realtime 5 | -- requirements. 6 | -- 7 | -- This module is the main entry point for the Copilot language. The 8 | -- expectation is that most Copilot users will only need to import this module, 9 | -- together with one of the backend modules (at present, only 10 | -- 'Copilot.Compile.C99' from the 11 | -- library is 12 | -- available). 13 | module Language.Copilot 14 | ( 15 | module Copilot.Language 16 | , module Copilot.Language.Prelude 17 | , module Copilot.Language.Reify 18 | , module Copilot.Library.Libraries 19 | 20 | , copilotMain 21 | , defaultMain 22 | ) where 23 | 24 | import Copilot.Language 25 | import Copilot.Language.Prelude 26 | import Copilot.Language.Reify 27 | import Copilot.Library.Libraries 28 | import Language.Copilot.Main 29 | -------------------------------------------------------------------------------- /copilot-language/src/Copilot/Language/Operators/Local.hs: -------------------------------------------------------------------------------- 1 | -- Copyright © 2011 National Institute of Aerospace / Galois, Inc. 2 | 3 | -- | Let expressions. 4 | -- 5 | -- Although Copilot is a DSL embedded in Haskell and Haskell does support let 6 | -- expressions, we want Copilot to be able to implement sharing, to detect when 7 | -- the same stream is being used in multiple places in a specification and 8 | -- avoid recomputing it unnecessarily. 9 | 10 | {-# LANGUAGE Safe #-} 11 | 12 | module Copilot.Language.Operators.Local 13 | ( local 14 | ) where 15 | 16 | import Copilot.Core (Typed) 17 | import Copilot.Language.Stream (Stream (..)) 18 | 19 | -- | Let expressions. 20 | -- 21 | -- Create a stream that results from applying a stream to a function on 22 | -- streams. Standard usage would be similar to Haskell's let. See the 23 | -- following example, where @stream1@, @stream2@ and @s@ are all streams 24 | -- carrying values of some numeric type: 25 | -- 26 | -- @ 27 | -- expression = local (stream1 + stream2) $ \\s -> 28 | -- (s >= 0 && s <= 10) 29 | -- @ 30 | local :: (Typed a, Typed b) => Stream a -> (Stream a -> Stream b) -> Stream b 31 | local = Local 32 | -------------------------------------------------------------------------------- /copilot/examples/Heater.hs: -------------------------------------------------------------------------------- 1 | -- Copyright 2019 National Institute of Aerospace / Galois, Inc. 2 | 3 | -- This is a simple example with basic usage. It implements a simple home 4 | -- heating system: It heats when temp gets too low, and stops when it is high 5 | -- enough. It read temperature as a byte (range -50C to 100C) and translates 6 | -- this to Celsius. 7 | 8 | module Main where 9 | 10 | import Language.Copilot 11 | import Copilot.Compile.C99 12 | 13 | import Prelude hiding ((>), (<), div) 14 | 15 | -- External temperature as a byte, range of -50C to 100C 16 | temp :: Stream Word8 17 | temp = extern "temperature" Nothing 18 | 19 | -- Calculate temperature in Celsius. 20 | -- We need to cast the Word8 to a Float. Note that it is an unsafeCast, as there 21 | -- is no direct relation between Word8 and Float. 22 | ctemp :: Stream Float 23 | ctemp = (unsafeCast temp) * (150.0 / 255.0) - 50.0 24 | 25 | spec = do 26 | -- Triggers that fire when the ctemp is too low or too high, 27 | -- pass the current ctemp as an argument. 28 | trigger "heaton" (ctemp < 18.0) [arg ctemp] 29 | trigger "heatoff" (ctemp > 21.0) [arg ctemp] 30 | 31 | -- Compile the spec 32 | main = reify spec >>= compile "heater" 33 | -------------------------------------------------------------------------------- /copilot-language/src/Copilot/Language/Operators/Eq.hs: -------------------------------------------------------------------------------- 1 | -- Copyright © 2011 National Institute of Aerospace / Galois, Inc. 2 | 3 | {-# LANGUAGE Safe #-} 4 | 5 | -- | Equality applied point-wise on streams. 6 | module Copilot.Language.Operators.Eq 7 | ( (==) 8 | , (/=) 9 | ) where 10 | 11 | import Copilot.Core (Typed, typeOf) 12 | import qualified Copilot.Core as Core 13 | import Copilot.Language.Prelude 14 | import Copilot.Language.Stream 15 | import qualified Prelude as P 16 | 17 | -- | Compare two streams point-wise for equality. 18 | -- 19 | -- The output stream contains the value True at a point in time if both 20 | -- argument streams contain the same value at that point in time. 21 | (==) :: (P.Eq a, Typed a) => Stream a -> Stream a -> Stream Bool 22 | (Const x) == (Const y) = Const (x P.== y) 23 | x == y = Op2 (Core.Eq typeOf) x y 24 | 25 | -- | Compare two streams point-wise for inequality. 26 | -- 27 | -- The output stream contains the value True at a point in time if both 28 | -- argument streams contain different values at that point in time. 29 | (/=) :: (P.Eq a, Typed a) => Stream a -> Stream a -> Stream Bool 30 | (Const x) /= (Const y) = Const (x P./= y) 31 | x /= y = Op2 (Core.Ne typeOf) x y 32 | -------------------------------------------------------------------------------- /copilot-verifier/examples/Copilot/Verifier/Examples/ShouldFail/Partial/IndexOutOfBounds.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE DataKinds #-} 2 | {-# LANGUAGE NoImplicitPrelude #-} 3 | 4 | -- | This will fail to verify since the verification does not assume the 5 | -- @withinBounds@ property, which is needed to prevent an out-of-bounds array index. 6 | module Copilot.Verifier.Examples.ShouldFail.Partial.IndexOutOfBounds where 7 | 8 | import Language.Copilot 9 | import Copilot.Compile.C99 10 | import Copilot.Verifier ( Verbosity, VerifierOptions(..) 11 | , defaultVerifierOptions, verifyWithOptions ) 12 | 13 | spec :: Spec 14 | spec = do 15 | let stream1 :: Stream (Array 2 Int16) 16 | stream1 = constant (array [27, 42]) 17 | 18 | stream2 :: Stream Word32 19 | stream2 = extern "stream2" Nothing 20 | 21 | _ <- prop "withinBounds" (forAll (stream2 < constW32 2)) 22 | trigger "streamIndex" ((stream1 ! stream2) == 1) [arg stream1, arg stream2] 23 | 24 | verifySpec :: Verbosity -> IO () 25 | verifySpec verb = do 26 | spec' <- reify spec 27 | verifyWithOptions defaultVerifierOptions{verbosity = verb} 28 | mkDefaultCSettings 29 | -- ["withinBounds"] 30 | [] 31 | "indexFail" spec' 32 | -------------------------------------------------------------------------------- /copilot-verifier/examples/Copilot/Verifier/Examples/ShouldFail/Partial/MulSignedWrap.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE NoImplicitPrelude #-} 2 | 3 | -- | This will fail to verify since the verification does not assume the 4 | -- @withinRange@ property, which is needed to prevent signed integer underflow or overflow. 5 | module Copilot.Verifier.Examples.ShouldFail.Partial.MulSignedWrap where 6 | 7 | import qualified Prelude as P 8 | 9 | import Language.Copilot 10 | import Copilot.Compile.C99 11 | import Copilot.Verifier ( Verbosity, VerifierOptions(..) 12 | , defaultVerifierOptions, verifyWithOptions ) 13 | 14 | spec :: Spec 15 | spec = do 16 | let stream :: Stream Int32 17 | stream = extern "stream" Nothing 18 | 19 | _ <- prop "withinRange" (forAll 20 | (constI32 ((minBound P.+ 1) P.* 2) < stream 21 | && stream < constI32 ((maxBound P.- 1) `P.div` 2))) 22 | trigger "streamMulSigned" ((stream * 2) == 2) [arg stream] 23 | 24 | verifySpec :: Verbosity -> IO () 25 | verifySpec verb = do 26 | spec' <- reify spec 27 | verifyWithOptions defaultVerifierOptions{verbosity = verb} 28 | mkDefaultCSettings 29 | -- ["withinRange"] 30 | [] 31 | "mulSignedWrapFail" spec' 32 | -------------------------------------------------------------------------------- /copilot-visualizer/data/tikz/tikz.tex: -------------------------------------------------------------------------------- 1 | {{=<% %>=}} 2 | \documentclass{standalone} 3 | \usepackage{tikz} 4 | \usepackage{tikz-timing} 5 | \usepackage{xcolor} 6 | \definecolor{false}{HTML}{ECD9ED} 7 | \definecolor{true}{HTML}{D9ECED} 8 | \begin{document} 9 | \newcommand{\true}{T} 10 | \newcommand{\false}{F} 11 | \tikzset{ 12 | every picture/.style={ 13 | execute at end picture={ 14 | \path (current bounding box.south west) +(-1,-1) (current bounding box.north east) +(1,1); 15 | } 16 | } 17 | } 18 | 19 | \tikzset{ 20 | timing/.style={x=5ex,y=2ex}, 21 | timing/rowdist=4ex, 22 | timing/dslope=0.1, 23 | x=5ex, 24 | timing/coldist=1ex, 25 | timing/name/.style={font=\sffamily\scriptsize}, 26 | timing/d/text/.style={font=\sffamily\tiny}, 27 | } 28 | \begin{tikztimingtable} 29 | <%#adTraceElems%> 30 | <%teName%> & g<%#teValues%><%#tvIsEmpty%>S<%/tvIsEmpty%><%^tvIsEmpty%><%#teIsBoolean%>[fill=<%tvValue%>]D{\<%tvValue%>}<%/teIsBoolean%><%^teIsBoolean%>D{<%tvValue%>}<%/teIsBoolean%><%/tvIsEmpty%><%/teValues%>\\ 31 | <%/adTraceElems%> 32 | \extracode 33 | \begin{background}[shift={(0.05,0)},help lines] 34 | \vertlines[help lines,opacity=0.3]{-0.3ex,...,<%adLastSample%>} 35 | \end{background} 36 | \end{tikztimingtable} 37 | \end{document} 38 | -------------------------------------------------------------------------------- /copilot-language/src/Copilot/Language/Operators/Mux.hs: -------------------------------------------------------------------------------- 1 | -- Copyright © 2011 National Institute of Aerospace / Galois, Inc. 2 | 3 | {-# LANGUAGE Safe #-} 4 | 5 | -- | Pick values from one of two streams, depending whether a condition is true 6 | -- or false. 7 | module Copilot.Language.Operators.Mux 8 | ( mux 9 | , ifThenElse 10 | ) where 11 | 12 | import Copilot.Core (Typed, typeOf) 13 | import qualified Copilot.Core as Core 14 | import Copilot.Language.Prelude 15 | import Copilot.Language.Stream 16 | import Prelude () 17 | 18 | -- | Convenient synonym for 'ifThenElse'. 19 | mux :: Typed a => Stream Bool -> Stream a -> Stream a -> Stream a 20 | mux (Const True) t _ = t 21 | mux (Const False) _ f = f 22 | mux b t f = Op3 (Core.Mux typeOf) b t f 23 | 24 | -- | If-then-else applied point-wise to three streams (a condition stream, a 25 | -- then-branch stream, and an else-branch stream). 26 | -- 27 | -- Produce a stream that, at any point in time, if the value of the first 28 | -- stream at that point is true, contains the value in the second stream at 29 | -- that time, otherwise it contains the value in the third stream. 30 | ifThenElse :: Typed a => Stream Bool -> Stream a -> Stream a -> Stream a 31 | ifThenElse = mux 32 | -------------------------------------------------------------------------------- /copilot/examples/Engine.hs: -------------------------------------------------------------------------------- 1 | -- Copyright © 2011 National Institute of Aerospace / Galois, Inc. 2 | 3 | -- | Example implementing an engine cooling control system. 4 | 5 | {-# LANGUAGE RebindableSyntax #-} 6 | 7 | module Main where 8 | 9 | import Language.Copilot 10 | import qualified Prelude as P 11 | 12 | -- If the majority of the engine temperature probes exeeds 250 degrees, then 13 | -- the cooler is engaged and remains engaged until the majority of the engine 14 | -- temperature probes drop to 250 or below. Otherwise, trigger an immediate 15 | -- shutdown of the engine. 16 | 17 | engineMonitor :: Spec 18 | engineMonitor = do 19 | trigger "shutoff" (not ok) [arg maj] 20 | 21 | where 22 | vals = [ externW8 "tmp_probe_0" two51 23 | , externW8 "tmp_probe_1" two51 24 | , externW8 "tmp_probe_2" zero] 25 | exceed = map (> 250) vals 26 | maj = majority exceed 27 | checkMaj = aMajority exceed maj 28 | ok = alwaysBeen ((maj && checkMaj) ==> extern "cooler" cooler) 29 | 30 | two51 = Just $ [251, 251] P.++ repeat (250 :: Word8) 31 | zero = Just $ repeat (0 :: Word8) 32 | cooler = Just $ [True, True] P.++ repeat False 33 | 34 | main :: IO () 35 | main = interpret 10 engineMonitor 36 | -------------------------------------------------------------------------------- /copilot-verifier/examples/Copilot/Verifier/Examples/ShouldFail/Partial/ShiftLTooLarge.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE NoImplicitPrelude #-} 2 | 3 | -- | This will fail to verify since the verification does not assume the 4 | -- @lessThanBitWidth@ property, which is needed to prevent shifting by too 5 | -- large of a value. 6 | module Copilot.Verifier.Examples.ShouldFail.Partial.ShiftLTooLarge where 7 | 8 | import Language.Copilot 9 | import Copilot.Compile.C99 10 | import Copilot.Verifier ( Verbosity, VerifierOptions(..) 11 | , defaultVerifierOptions, verifyWithOptions ) 12 | 13 | spec :: Spec 14 | spec = do 15 | let stream1 :: Stream Int32 16 | stream1 = extern "stream1" Nothing 17 | 18 | stream2 :: Stream Int64 19 | stream2 = extern "stream2" Nothing 20 | 21 | _ <- prop "lessThanBitWidth" (forAll 22 | (constI64 0 <= stream2 && stream2 < constI64 32)) 23 | trigger "streamShiftL" ((stream1 .<<. stream2) == 1) [arg stream1, arg stream2] 24 | 25 | verifySpec :: Verbosity -> IO () 26 | verifySpec verb = do 27 | spec' <- reify spec 28 | verifyWithOptions defaultVerifierOptions{verbosity = verb} 29 | mkDefaultCSettings 30 | -- ["lessThanBitWidth"] 31 | [] 32 | "shiftLTooLargeFail" spec' 33 | -------------------------------------------------------------------------------- /copilot-verifier/examples/Copilot/Verifier/Examples/ShouldFail/Partial/ShiftRTooLarge.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE NoImplicitPrelude #-} 2 | 3 | -- | This will fail to verify since the verification does not assume the 4 | -- @lessThanBitWidth@ property, which is needed to prevent shifting by too 5 | -- large of a value. 6 | module Copilot.Verifier.Examples.ShouldFail.Partial.ShiftRTooLarge where 7 | 8 | import Language.Copilot 9 | import Copilot.Compile.C99 10 | import Copilot.Verifier ( Verbosity, VerifierOptions(..) 11 | , defaultVerifierOptions, verifyWithOptions ) 12 | 13 | spec :: Spec 14 | spec = do 15 | let stream1 :: Stream Int32 16 | stream1 = extern "stream1" Nothing 17 | 18 | stream2 :: Stream Int64 19 | stream2 = extern "stream2" Nothing 20 | 21 | _ <- prop "lessThanBitWidth" (forAll 22 | (constI64 0 <= stream2 && stream2 < constI64 32)) 23 | trigger "streamShiftR" ((stream1 .<<. stream2) == 1) [arg stream1, arg stream2] 24 | 25 | verifySpec :: Verbosity -> IO () 26 | verifySpec verb = do 27 | spec' <- reify spec 28 | verifyWithOptions defaultVerifierOptions{verbosity = verb} 29 | mkDefaultCSettings 30 | -- ["lessThanBitWidth"] 31 | [] 32 | "shiftRTooLargeFail" spec' 33 | -------------------------------------------------------------------------------- /copilot/examples/fpga/HelloWorld/constraints.xdc: -------------------------------------------------------------------------------- 1 | set_property -dict { PACKAGE_PIN E3 IOSTANDARD LVCMOS33 } [get_ports CLK] 2 | create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports CLK] 3 | 4 | set_property PACKAGE_PIN C2 [get_ports RST_N] 5 | set_property IOSTANDARD LVCMOS33 [get_ports RST_N] 6 | 7 | # Switches 8 | set_property -dict { PACKAGE_PIN A8 IOSTANDARD LVCMOS33 } [get_ports { sw[0] }]; #IO_L12N_T1_MRCC_16 Sch=sw[0] 9 | set_property -dict { PACKAGE_PIN C11 IOSTANDARD LVCMOS33 } [get_ports { sw[1] }]; #IO_L13P_T2_MRCC_16 Sch=sw[1] 10 | set_property -dict { PACKAGE_PIN C10 IOSTANDARD LVCMOS33 } [get_ports { sw[2] }]; #IO_L13N_T2_MRCC_16 Sch=sw[2] 11 | set_property -dict { PACKAGE_PIN A10 IOSTANDARD LVCMOS33 } [get_ports { sw[3] }]; #IO_L14P_T2_SRCC_16 Sch=sw[3] 12 | 13 | # LEDs 14 | set_property -dict { PACKAGE_PIN H5 IOSTANDARD LVCMOS33 } [get_ports { leds[0] }]; #IO_L24N_T3_35 Sch=led[4] 15 | set_property -dict { PACKAGE_PIN J5 IOSTANDARD LVCMOS33 } [get_ports { leds[1] }]; #IO_25_35 Sch=led[5] 16 | set_property -dict { PACKAGE_PIN T9 IOSTANDARD LVCMOS33 } [get_ports { leds[2] }]; #IO_L24P_T3_A01_D17_14 Sch=led[6] 17 | set_property -dict { PACKAGE_PIN T10 IOSTANDARD LVCMOS33 } [get_ports { leds[3] }]; #IO_L24N_T3_A00_D16_14 Sch=led[7] 18 | -------------------------------------------------------------------------------- /copilot/examples/what4/Arrays.hs: -------------------------------------------------------------------------------- 1 | -- | An example showing the usage of the What4 backend in copilot-theorem for 2 | -- arrays where individual elements are updated. 3 | 4 | {-# LANGUAGE DataKinds #-} 5 | 6 | module Main where 7 | 8 | import qualified Prelude as P 9 | import Control.Monad (void, forM_) 10 | 11 | import Language.Copilot 12 | import Copilot.Theorem.What4 13 | 14 | spec :: Spec 15 | spec = do 16 | let pair :: Stream (Array 2 Int16) 17 | pair = extern "pair" Nothing 18 | 19 | -- Check equality, indexing into array and modifying the value. Note that 20 | -- this is trivial by equality. 21 | void $ prop "Example 1" $ forAll $ 22 | ((pair !! 0 =$ (+1)) ! 0) == ((pair ! 0) + 1) 23 | 24 | -- Same as previous example, but get a different array index (so should be 25 | -- false). 26 | void $ prop "Example 2" $ forAll $ 27 | ((pair !! 0 =$ (+1)) ! 1) == ((pair ! 0) + 1) 28 | 29 | main :: IO () 30 | main = do 31 | spec' <- reify spec 32 | 33 | -- Use Z3 to prove the properties. 34 | results <- prove Z3 spec' 35 | 36 | -- Print the results. 37 | forM_ results $ \(nm, res) -> do 38 | putStr $ nm <> ": " 39 | case res of 40 | Valid -> putStrLn "valid" 41 | Invalid -> putStrLn "invalid" 42 | Unknown -> putStrLn "unknown" 43 | -------------------------------------------------------------------------------- /copilot-verifier/examples/Copilot/Verifier/Examples/ShouldPass/UpdateArray.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE RebindableSyntax #-} 2 | {-# LANGUAGE DataKinds #-} 3 | 4 | -- | An example showing of using @copilot-verifier@ to verify a specification 5 | -- involving arrays where individual elements are updated. 6 | module Copilot.Verifier.Examples.ShouldPass.UpdateArray where 7 | 8 | import Language.Copilot 9 | import Copilot.Compile.C99 10 | import Copilot.Verifier ( Verbosity, VerifierOptions(..) 11 | , defaultVerifierOptions, verifyWithOptions ) 12 | 13 | spec :: Spec 14 | spec = do 15 | let pair :: Stream (Array 2 Word32) 16 | pair = extern "pair" Nothing 17 | 18 | -- Check equality, indexing into array and modifying the value. Note that 19 | -- this is trivial by equality. 20 | trigger "trig_1" 21 | (((pair !! 0 =$ (+1)) ! 0) == ((pair ! 0) + 1)) 22 | [arg pair] 23 | 24 | -- Same as previous example, but get a different array index (so should be 25 | -- false). 26 | trigger "trig_2" 27 | (((pair !! 0 =$ (+1)) ! 1) == ((pair ! 0) + 1)) 28 | [arg pair] 29 | 30 | verifySpec :: Verbosity -> IO () 31 | verifySpec verb = reify spec >>= verifyWithOptions defaultVerifierOptions{verbosity = verb} 32 | mkDefaultCSettings [] "updateArray" 33 | -------------------------------------------------------------------------------- /copilot-bluespec/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:focal 2 | 3 | ENV DEBIAN_FRONTEND=noninteractive 4 | RUN apt-get update && \ 5 | apt-get install --yes curl gcc g++ git libz-dev make libgmp3-dev libtcl8.6 libtinfo-dev wget 6 | 7 | ENV BSC_VER=2023.07 8 | RUN mkdir -p /root/bsc 9 | RUN wget https://github.com/B-Lang-org/bsc/releases/download/$BSC_VER/bsc-$BSC_VER-ubuntu-20.04.tar.gz -O /root/bsc.tar.gz && \ 10 | tar -xvf /root/bsc.tar.gz -C /root/bsc --strip-components=1 && \ 11 | rm /root/bsc.tar.gz 12 | 13 | ENV GHCUP_VER=0.1.22.0 14 | RUN mkdir -p /root/.ghcup/bin 15 | RUN wget https://downloads.haskell.org/~ghcup/$GHCUP_VER/x86_64-linux-ghcup-$GHCUP_VER -O /root/.ghcup/bin/ghcup && \ 16 | chmod a+x /root/.ghcup/bin/ghcup 17 | 18 | ENV PATH=/root/bsc/bin:/root/.cabal/bin:/root/.ghcup/bin:$PATH 19 | 20 | ENV GHC_VER=9.4.8 21 | ENV CABAL_VER=3.8.1.0 22 | RUN ghcup install ghc $GHC_VER && \ 23 | ghcup set ghc $GHC_VER && \ 24 | ghcup install cabal $CABAL_VER && \ 25 | ghcup set cabal $CABAL_VER && \ 26 | cabal update 27 | 28 | COPY . /copilot-bluespec 29 | WORKDIR /copilot-bluespec 30 | 31 | RUN cabal configure --enable-tests && \ 32 | cabal build --write-ghc-environment-files=always && \ 33 | cabal install --lib copilot . --package-env . && \ 34 | cabal test 35 | 36 | ENTRYPOINT ["/usr/bin/bash"] 37 | -------------------------------------------------------------------------------- /copilot-core/tests/Test/Extra.hs: -------------------------------------------------------------------------------- 1 | -- | Auxiliary testing helper functions. 2 | module Test.Extra where 3 | 4 | -- External imports 5 | import Control.Arrow ((***)) 6 | 7 | -- * Function application 8 | 9 | -- | Apply a tuple with two functions to a tuple of arguments. 10 | apply1 :: (a1 -> b1, a2 -> b2) -- ^ Pair with functions 11 | -> (a1, a2) -- ^ Pair with arguments 12 | -> (b1, b2) -- ^ Pair with results 13 | apply1 = uncurry (***) 14 | 15 | -- | Apply a tuple with two functions on two arguments to their tupled 16 | -- arguments. 17 | apply2 :: (a1 -> b1 -> c1, a2 -> b2 -> c2) -- ^ Pair with functions 18 | -> (a1, a2) -- ^ Pair with first arguments 19 | -> (b1, b2) -- ^ Pair with second arguments 20 | -> (c1, c2) -- ^ Pair with results 21 | apply2 fs = apply1 . apply1 fs 22 | 23 | -- | Apply a tuple with two functions on three arguments to their tupled 24 | -- arguments. 25 | apply3 :: (a1 -> b1 -> c1 -> d1, a2 -> b2 -> c2 -> d2) 26 | -- ^ Pair with functions 27 | -> (a1, a2) -- ^ Pair with first arguments 28 | -> (b1, b2) -- ^ Pair with second arguments 29 | -> (c1, c2) -- ^ Pair with third arguments 30 | -> (d1, d2) -- ^ Pair with results 31 | apply3 fs = apply2 . apply1 fs 32 | -------------------------------------------------------------------------------- /copilot-language/tests/Test/Extra.hs: -------------------------------------------------------------------------------- 1 | -- | Auxiliary testing helper functions. 2 | module Test.Extra where 3 | 4 | -- External imports 5 | import Control.Arrow ((***)) 6 | 7 | -- * Function application 8 | 9 | -- | Apply a tuple with two functions to a tuple of arguments. 10 | apply1 :: (a1 -> b1, a2 -> b2) -- ^ Pair with functions 11 | -> (a1, a2) -- ^ Pair with arguments 12 | -> (b1, b2) -- ^ Pair with results 13 | apply1 = uncurry (***) 14 | 15 | -- | Apply a tuple with two functions on two arguments to their tupled 16 | -- arguments. 17 | apply2 :: (a1 -> b1 -> c1, a2 -> b2 -> c2) -- ^ Pair with functions 18 | -> (a1, a2) -- ^ Pair with first arguments 19 | -> (b1, b2) -- ^ Pair with second arguments 20 | -> (c1, c2) -- ^ Pair with results 21 | apply2 fs = apply1 . apply1 fs 22 | 23 | -- | Apply a tuple with two functions on three arguments to their tupled 24 | -- arguments. 25 | apply3 :: (a1 -> b1 -> c1 -> d1, a2 -> b2 -> c2 -> d2) 26 | -- ^ Pair with functions 27 | -> (a1, a2) -- ^ Pair with first arguments 28 | -> (b1, b2) -- ^ Pair with second arguments 29 | -> (c1, c2) -- ^ Pair with third arguments 30 | -> (d1, d2) -- ^ Pair with results 31 | apply3 fs = apply2 . apply1 fs 32 | -------------------------------------------------------------------------------- /copilot-interpreter/tests/Test/Extra.hs: -------------------------------------------------------------------------------- 1 | -- | Auxiliary testing helper functions. 2 | module Test.Extra where 3 | 4 | -- External imports 5 | import Control.Arrow ((***)) 6 | 7 | -- * Function application 8 | 9 | -- | Apply a tuple with two functions to a tuple of arguments. 10 | apply1 :: (a1 -> b1, a2 -> b2) -- ^ Pair with functions 11 | -> (a1, a2) -- ^ Pair with arguments 12 | -> (b1, b2) -- ^ Pair with results 13 | apply1 = uncurry (***) 14 | 15 | -- | Apply a tuple with two functions on two arguments to their tupled 16 | -- arguments. 17 | apply2 :: (a1 -> b1 -> c1, a2 -> b2 -> c2) -- ^ Pair with functions 18 | -> (a1, a2) -- ^ Pair with first arguments 19 | -> (b1, b2) -- ^ Pair with second arguments 20 | -> (c1, c2) -- ^ Pair with results 21 | apply2 fs = apply1 . apply1 fs 22 | 23 | -- | Apply a tuple with two functions on three arguments to their tupled 24 | -- arguments. 25 | apply3 :: (a1 -> b1 -> c1 -> d1, a2 -> b2 -> c2 -> d2) 26 | -- ^ Pair with functions 27 | -> (a1, a2) -- ^ Pair with first arguments 28 | -> (b1, b2) -- ^ Pair with second arguments 29 | -> (c1, c2) -- ^ Pair with third arguments 30 | -> (d1, d2) -- ^ Pair with results 31 | apply3 fs = apply2 . apply1 fs 32 | -------------------------------------------------------------------------------- /copilot-visualizer/src/Copilot/Visualize/Static.hs: -------------------------------------------------------------------------------- 1 | -- | 2 | -- Copyright : (c) NASA, 2024-2025 3 | -- License : BSD-style (see the LICENSE file in the distribution) 4 | -- 5 | -- Produce a visual representation of a Copilot specification. 6 | module Copilot.Visualize.Static 7 | ( visualize 8 | ) 9 | where 10 | 11 | -- External imports 12 | import Data.Aeson (ToJSON (..)) 13 | import System.Directory.Extra (copyTemplate) 14 | import System.FilePath (()) 15 | 16 | -- External imports: Copilot 17 | import Copilot.Core (Spec (..)) 18 | import Copilot.Interpret.Eval (ShowType (Haskell), eval) 19 | 20 | -- Internal imports 21 | import Copilot.Visualize.UntypedTrace (makeTraceEval) 22 | import Paths_copilot_visualizer (getDataDir) 23 | 24 | -- | Produce a visual representation of a Copilot specification, for a given 25 | -- number of steps, using a template. 26 | visualize :: Int -- ^ Number of steps to interpret. 27 | -> Spec -- ^ Specification to interpret. 28 | -> String -- ^ Base used to expand the static file (i.e., @"tikz"@, 29 | -- @"static_html"@). 30 | -> FilePath 31 | -> IO () 32 | visualize k spec base target = do 33 | dir <- getDataDir 34 | let f = dir "data" base 35 | let subs = toJSON $ makeTraceEval k spec $ eval Haskell k spec 36 | copyTemplate f subs target 37 | -------------------------------------------------------------------------------- /copilot-visualizer/examples/tikz/Heater.hs: -------------------------------------------------------------------------------- 1 | -- Copyright 2025 NASA 2 | -- Copyright 2019 National Institute of Aerospace / Galois, Inc. 3 | 4 | -- This is a simple example with basic usage. It implements a simple home 5 | -- heating system: It heats when temp gets too low, and stops when it is high 6 | -- enough. It read temperature as a byte (range -50C to 100C) and translates 7 | -- this to Celsius. 8 | 9 | module Main where 10 | 11 | import Language.Copilot 12 | import Copilot.Visualize.Static 13 | 14 | import Prelude hiding ((>), (<)) 15 | 16 | -- External temperature as a byte, range of -50C to 100C 17 | temp :: Stream Word8 18 | temp = extern "temperature" (Just [ 10, 15, 18, 19, 25, 5, 45 ]) 19 | 20 | -- Calculate temperature in Celsius. 21 | -- We need to cast the Word8 to a Float. Note that it is an unsafeCast, as there 22 | -- is no direct relation between Word8 and Float. 23 | ctemp :: Stream Float 24 | ctemp = (unsafeCast temp) * (150.0 / 255.0) - 50.0 25 | 26 | spec = do 27 | -- Triggers that fire when the ctemp is too low or too high, 28 | -- pass the current ctemp as an argument. 29 | trigger "heaton" (ctemp < 18.0) [arg ctemp] 30 | trigger "heatoff" (ctemp > 21.0) [arg ctemp] 31 | 32 | -- Compile the spec and produce a LaTeX file in the current directory with a 33 | -- Tikz drawing of the spec. 34 | main :: IO () 35 | main = do 36 | spec' <- reify spec 37 | visualize 3 spec' "tikz" "." 38 | -------------------------------------------------------------------------------- /copilot-core/src/Copilot/Core.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE Safe #-} 2 | 3 | -- | 4 | -- Description: Intermediate representation for Copilot specifications. 5 | -- Copyright: (c) 2011 National Institute of Aerospace / Galois, Inc. 6 | -- 7 | -- The following articles might also be useful: 8 | -- 9 | -- * Carette, Jacques and Kiselyov, Oleg and Shan, Chung-chieh, 10 | -- \"/Finally tagless, partially evaluated: Tagless staged/ 11 | -- /interpreters for simpler typed languages/\", 12 | -- Journal of Functional Programming vol. 19, p. 509-543, 2009. 13 | -- 14 | -- * Guillemette, Louis-Julien and Monnier, Stefan, 15 | -- \"/Type-Safe Code Transformations in Haskell/\", 16 | -- Electronic Notes in Theoretical Computer Science vol. 174, p. 23-39, 2007. 17 | -- 18 | -- For examples of how to traverse a Copilot specification see 19 | -- the source code of the interpreter (@copilot-interpreter@) 20 | -- and the pretty-printer (@copilot-prettyprinter@). 21 | module Copilot.Core 22 | ( module Copilot.Core.Expr 23 | , module Copilot.Core.Operators 24 | , module Copilot.Core.Spec 25 | , module Copilot.Core.Type 26 | , module Copilot.Core.Type.Array 27 | , module Data.Int 28 | , module Data.Word 29 | ) 30 | where 31 | 32 | -- External imports 33 | import Data.Int 34 | import Data.Word 35 | 36 | -- Internal imports 37 | import Copilot.Core.Expr 38 | import Copilot.Core.Operators 39 | import Copilot.Core.Spec 40 | import Copilot.Core.Type 41 | import Copilot.Core.Type.Array 42 | -------------------------------------------------------------------------------- /copilot/examples/Voting.hs: -------------------------------------------------------------------------------- 1 | -- Copyright © 2019 National Institute of Aerospace / Galois, Inc. 2 | 3 | -- | Fault-tolerant voting examples. 4 | 5 | {-# LANGUAGE RebindableSyntax #-} 6 | 7 | module Main where 8 | 9 | import Language.Copilot 10 | 11 | vote :: Spec 12 | vote = do 13 | -- majority selects element with the biggest occurance. 14 | trigger "maj" true [arg maj] 15 | 16 | -- aMajority checks if the selected element has a majority. 17 | trigger "aMaj" true [arg $ aMajority inputs maj] 18 | 19 | where 20 | maj = majority inputs 21 | 22 | -- 26 input streams to vote on 23 | inputs :: [Stream Word32] 24 | inputs = [ a, b, c, d, e, f, g, h, i, j, k, l, m 25 | , n, o, p, q, r, s, t, u, v, w, x, y, z 26 | ] 27 | a = [0] ++ a + 1 28 | b = [0] ++ b + 1 29 | c = [0] ++ c + 1 30 | d = [0] ++ d + 1 31 | e = [1] ++ e + 1 32 | f = [1] ++ f + 1 33 | g = [1] ++ g + 1 34 | h = [1] ++ h + 1 35 | i = [1] ++ i + 1 36 | j = [1] ++ j + 1 37 | k = [1] ++ k + 1 38 | l = [1] ++ l + 1 39 | m = [1] ++ m + 1 40 | n = [1] ++ n + 1 41 | o = [1] ++ o + 1 42 | p = [1] ++ p + 1 43 | q = [1] ++ q + 1 44 | r = [1] ++ r + 1 45 | s = [1] ++ s + 1 46 | t = [1] ++ t + 1 47 | u = [1] ++ u + 1 48 | v = [1] ++ v + 1 49 | w = [1] ++ w + 1 50 | x = [1] ++ x + 1 51 | y = [1] ++ y + 1 52 | z = [1] ++ z + 1 53 | 54 | main :: IO () 55 | main = interpret 30 vote 56 | -------------------------------------------------------------------------------- /copilot-language/src/Copilot/Language/Operators/Temporal.hs: -------------------------------------------------------------------------------- 1 | -- Copyright © 2011 National Institute of Aerospace / Galois, Inc. 2 | 3 | {-# LANGUAGE Safe #-} 4 | 5 | -- | Temporal stream transformations. 6 | module Copilot.Language.Operators.Temporal 7 | ( (++) 8 | , drop 9 | ) where 10 | 11 | import Copilot.Core (Typed) 12 | import Copilot.Language.Prelude 13 | import Copilot.Language.Stream 14 | import Prelude () 15 | 16 | infixr 1 ++ 17 | 18 | -- | Prepend a fixed number of samples to a stream. 19 | -- 20 | -- The elements to be appended at the beginning of the stream must be limited, 21 | -- that is, the list must have finite length. 22 | -- 23 | -- Prepending elements to a stream may increase the memory requirements of the 24 | -- generated programs (which now must hold the same number of elements in 25 | -- memory for future processing). 26 | (++) :: Typed a => [a] -> Stream a -> Stream a 27 | (++) = (`Append` Nothing) 28 | 29 | -- | Drop a number of samples from a stream. 30 | -- 31 | -- The elements must be realizable at the present time to be able to drop 32 | -- elements. For most kinds of streams, you cannot drop elements without 33 | -- prepending an equal or greater number of elements to them first, as it 34 | -- could result in undefined samples. 35 | drop :: Typed a => Int -> Stream a -> Stream a 36 | drop 0 s = s 37 | drop _ ( Const j ) = Const j 38 | drop i ( Drop j s ) = Drop (fromIntegral i + j) s 39 | drop i s = Drop (fromIntegral i) s 40 | -------------------------------------------------------------------------------- /copilot-c99/README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.com/Copilot-Language/copilot.svg?branch=master)](https://app.travis-ci.com/github/Copilot-Language/copilot) 2 | 3 | # Copilot: a stream DSL 4 | Copilot-c99 implements a C99 backend for Copilot, producing high quality code 5 | suitable for hard realtime applications. 6 | 7 | Copilot is a runtime verification framework written in Haskell. It allows the 8 | user to write programs in a simple but powerful way using a stream-based 9 | approach. 10 | 11 | Programs can be interpreted for testing, or translated C99 code to be 12 | incorporated in a project, or as a standalone application. The C99 backend 13 | ensures us that the output is constant in memory and time, making it suitable 14 | for systems with hard realtime requirements. 15 | 16 | 17 | ## Installation 18 | Copilot-c99 can be found on 19 | [Hackage](https://hackage.haskell.org/package/copilot-c99). It is typically 20 | only installed as part of the complete Copilot distribution. For installation 21 | instructions, please refer to the [Copilot 22 | website](https://copilot-language.github.io). 23 | 24 | 25 | ## Further information 26 | For further information, install instructions and documentation, please visit 27 | the Copilot website: 28 | [https://copilot-language.github.io](https://copilot-language.github.io) 29 | 30 | 31 | ## License 32 | Copilot is distributed under the BSD-3-Clause license, which can be found 33 | [here](https://raw.githubusercontent.com/Copilot-Language/copilot/master/copilot-c99/LICENSE). 34 | -------------------------------------------------------------------------------- /copilot-libraries/src/Copilot/Library/PTLTL.hs: -------------------------------------------------------------------------------- 1 | -- | 2 | -- Module: PTLTL 3 | -- Description: Past-Time Linear-Temporal Logic 4 | -- Copyright: (c) 2011 National Institute of Aerospace / Galois, Inc. 5 | -- 6 | -- Provides past-time linear-temporal logic (ptLTL operators). 7 | -- 8 | -- /Interface:/ See @Examples/PTLTLExamples.hs@ in the 9 | -- . 10 | -- 11 | -- You can embed a ptLTL specification within a Copilot specification using 12 | -- the form: 13 | -- 14 | -- @ 15 | -- operator stream 16 | -- @ 17 | 18 | {-# LANGUAGE NoImplicitPrelude #-} 19 | 20 | module Copilot.Library.PTLTL 21 | ( since, alwaysBeen, eventuallyPrev, previous ) where 22 | 23 | import Prelude () 24 | import Copilot.Language 25 | 26 | -- | Did @s@ hold in the previous period? 27 | previous :: Stream Bool -> Stream Bool 28 | previous s = [ False ] ++ s 29 | 30 | -- | Has @s@ always held (up to and including the current state)? 31 | alwaysBeen :: Stream Bool -> Stream Bool 32 | alwaysBeen s = s && tmp 33 | where 34 | tmp = [ True ] ++ s && tmp 35 | 36 | -- | Did @s@ hold at some time in the past (including the current state)? 37 | eventuallyPrev :: Stream Bool -> Stream Bool 38 | eventuallyPrev s = s || tmp 39 | where 40 | tmp = [ False ] ++ s || tmp 41 | 42 | -- | Is there a time when @s2@ holds and after which @s1@ continuously holds? 43 | since :: Stream Bool -> Stream Bool -> Stream Bool 44 | since s1 s2 = eventuallyPrev (s2 ==> (alwaysBeen s1)) 45 | -------------------------------------------------------------------------------- /copilot-prettyprinter/README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.com/Copilot-Language/copilot.svg?branch=master)](https://app.travis-ci.com/github/Copilot-Language/copilot) 2 | 3 | # Copilot: a stream DSL 4 | Copilot-prettyprinter implements a pretty-printer of Copilot Core 5 | specifications. 6 | 7 | Copilot is a runtime verification framework written in Haskell. It allows the 8 | user to write programs in a simple but powerful way using a stream-based 9 | approach. 10 | 11 | Programs can be interpreted for testing, or translated C99 code to be 12 | incorporated in a project, or as a standalone application. The C99 backend 13 | ensures us that the output is constant in memory and time, making it suitable 14 | for systems with hard realtime requirements. 15 | 16 | 17 | ## Installation 18 | Copilot-prettyprinter can be found on 19 | [Hackage](https://hackage.haskell.org/package/copilot-prettyprinter). It is 20 | typically only installed as part of the complete Copilot distribution. For 21 | installation instructions, please refer to the [Copilot 22 | website](https://copilot-language.github.io). 23 | 24 | 25 | ## Further information 26 | For further information, install instructions and documentation, please visit 27 | the Copilot website: 28 | [https://copilot-language.github.io](https://copilot-language.github.io) 29 | 30 | 31 | ## License 32 | Copilot is distributed under the BSD-3-Clause license, which can be found 33 | [here](https://raw.githubusercontent.com/Copilot-Language/copilot/master/copilot-prettyprinter/LICENSE). 34 | -------------------------------------------------------------------------------- /copilot-libraries/README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.com/Copilot-Language/copilot.svg?branch=master)](https://app.travis-ci.com/github/Copilot-Language/copilot) 2 | 3 | # Copilot: a stream DSL 4 | User-supplied libraries for Copilot, including linear-temporal logic, 5 | fault-tolerant voting, regular expressions, etc. 6 | 7 | Copilot is a runtime verification framework written in Haskell. It allows the 8 | user to write programs in a simple but powerful way using a stream-based 9 | approach. 10 | 11 | Programs can be interpreted for testing, or translated C99 code to be 12 | incorporated in a project, or as a standalone application. The C99 backend 13 | ensures us that the output is constant in memory and time, making it suitable 14 | for systems with hard realtime requirements. 15 | 16 | 17 | ## Installation 18 | Copilot-libraries can be found on 19 | [Hackage](https://hackage.haskell.org/package/copilot-libraries). It is typically 20 | only installed as part of the complete Copilot distribution. For installation 21 | instructions, please refer to the [Copilot 22 | website](https://copilot-language.github.io). 23 | 24 | 25 | ## Further information 26 | For further information, install instructions and documentation, please visit 27 | the Copilot website: 28 | [https://copilot-language.github.io](https://copilot-language.github.io) 29 | 30 | 31 | ## License 32 | Copilot is distributed under the BSD-3-Clause license, which can be found 33 | [here](https://raw.githubusercontent.com/Copilot-Language/copilot/master/copilot-libraries/LICENSE). 34 | -------------------------------------------------------------------------------- /copilot-c99/LICENSE: -------------------------------------------------------------------------------- 1 | 2009 2 | BSD3 License terms 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions 6 | are met: 7 | 8 | Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in the 13 | documentation and/or other materials provided with the distribution. 14 | 15 | Neither the name of the developers nor the names of its contributors 16 | may be used to endorse or promote products derived from this software 17 | without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 23 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 24 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 26 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 27 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 28 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /copilot-interpreter/README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.com/Copilot-Language/copilot.svg?branch=master)](https://app.travis-ci.com/github/Copilot-Language/copilot) 2 | 3 | # Copilot: a stream DSL 4 | The interpreter, which evaluates Copilot specifications and prints 5 | their results over time. 6 | 7 | Copilot is a runtime verification framework written in Haskell. It allows the 8 | user to write programs in a simple but powerful way using a stream-based 9 | approach. 10 | 11 | Programs can be interpreted for testing (with the library copilot-interpreter), 12 | or translated C99 code to be incorporated in a project, or as a standalone 13 | application. The C99 backend ensures us that the output is constant in memory 14 | and time, making it suitable for systems with hard realtime requirements. 15 | 16 | ## Installation 17 | Copilot-interpreter can be found on 18 | [Hackage](https://hackage.haskell.org/package/copilot-interpreter). It is typically 19 | only installed as part of the complete Copilot distribution. For installation 20 | instructions, please refer to the [Copilot 21 | website](https://copilot-language.github.io). 22 | 23 | ## Further information 24 | For further information, install instructions and documentation, please visit 25 | the Copilot website: 26 | [https://copilot-language.github.io](https://copilot-language.github.io) 27 | 28 | ## License 29 | Copilot is distributed under the BSD-3-Clause license, which can be found 30 | [here](https://raw.githubusercontent.com/Copilot-Language/copilot/master/copilot-interpreter/LICENSE). 31 | -------------------------------------------------------------------------------- /copilot/LICENSE: -------------------------------------------------------------------------------- 1 | 2009 2 | BSD3 License terms 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions 6 | are met: 7 | 8 | Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in the 13 | documentation and/or other materials provided with the distribution. 14 | 15 | Neither the name of the developers nor the names of its contributors 16 | may be used to endorse or promote products derived from this software 17 | without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 23 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 24 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 26 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 27 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 28 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /copilot-bluespec/LICENSE: -------------------------------------------------------------------------------- 1 | 2009 2 | BSD3 License terms 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions 6 | are met: 7 | 8 | Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in the 13 | documentation and/or other materials provided with the distribution. 14 | 15 | Neither the name of the developers nor the names of its contributors 16 | may be used to endorse or promote products derived from this software 17 | without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 23 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 24 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 26 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 27 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 28 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /copilot-core/LICENSE: -------------------------------------------------------------------------------- 1 | 2009 2 | BSD3 License terms 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions 6 | are met: 7 | 8 | Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in the 13 | documentation and/or other materials provided with the distribution. 14 | 15 | Neither the name of the developers nor the names of its contributors 16 | may be used to endorse or promote products derived from this software 17 | without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 23 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 24 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 26 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 27 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 28 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /copilot-language/LICENSE: -------------------------------------------------------------------------------- 1 | 2009 2 | BSD3 License terms 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions 6 | are met: 7 | 8 | Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in the 13 | documentation and/or other materials provided with the distribution. 14 | 15 | Neither the name of the developers nor the names of its contributors 16 | may be used to endorse or promote products derived from this software 17 | without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 23 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 24 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 26 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 27 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 28 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /copilot-theorem/LICENSE: -------------------------------------------------------------------------------- 1 | 2009 2 | BSD3 License terms 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions 6 | are met: 7 | 8 | Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in the 13 | documentation and/or other materials provided with the distribution. 14 | 15 | Neither the name of the developers nor the names of its contributors 16 | may be used to endorse or promote products derived from this software 17 | without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 23 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 24 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 26 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 27 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 28 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /copilot-interpreter/LICENSE: -------------------------------------------------------------------------------- 1 | 2009 2 | BSD3 License terms 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions 6 | are met: 7 | 8 | Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in the 13 | documentation and/or other materials provided with the distribution. 14 | 15 | Neither the name of the developers nor the names of its contributors 16 | may be used to endorse or promote products derived from this software 17 | without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 23 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 24 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 26 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 27 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 28 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /copilot-libraries/LICENSE: -------------------------------------------------------------------------------- 1 | 2009 2 | BSD3 License terms 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions 6 | are met: 7 | 8 | Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in the 13 | documentation and/or other materials provided with the distribution. 14 | 15 | Neither the name of the developers nor the names of its contributors 16 | may be used to endorse or promote products derived from this software 17 | without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 23 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 24 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 26 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 27 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 28 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /copilot-prettyprinter/LICENSE: -------------------------------------------------------------------------------- 1 | 2009 2 | BSD3 License terms 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions 6 | are met: 7 | 8 | Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in the 13 | documentation and/or other materials provided with the distribution. 14 | 15 | Neither the name of the developers nor the names of its contributors 16 | may be used to endorse or promote products derived from this software 17 | without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 23 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 24 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 26 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 27 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 28 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /copilot-core/README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.com/Copilot-Language/copilot.svg?branch=master)](https://app.travis-ci.com/github/Copilot-Language/copilot) 2 | 3 | # Copilot: a stream DSL 4 | The core language, which efficiently represents Copilot expressions. The core 5 | is only of interest to implementers wishing to add a new back-end to Copilot. 6 | 7 | Copilot is a runtime verification framework written in Haskell. It allows the 8 | user to write programs in a simple but powerful way using a stream-based 9 | approach. 10 | 11 | Programs can be interpreted for testing, or translated C99 code to be 12 | incorporated in a project, or as a standalone application. The C99 backend 13 | ensures us that the output is constant in memory and time, making it suitable 14 | for systems with hard realtime requirements. 15 | 16 | 17 | ## Installation 18 | Copilot-core can be found on 19 | [Hackage](https://hackage.haskell.org/package/copilot-core). It is typically 20 | only installed as part of the complete Copilot distribution. For installation 21 | instructions, please refer to the [Copilot 22 | website](https://copilot-language.github.io). 23 | 24 | 25 | ## Further information 26 | For further information, install instructions and documentation, please visit 27 | the Copilot website: 28 | [https://copilot-language.github.io](https://copilot-language.github.io) 29 | 30 | 31 | ## License 32 | Copilot is distributed under the BSD-3-Clause license, which can be found 33 | [here](https://raw.githubusercontent.com/Copilot-Language/copilot/master/copilot-core/LICENSE). 34 | -------------------------------------------------------------------------------- /copilot-verifier/test/Test.hs: -------------------------------------------------------------------------------- 1 | module Main (main) where 2 | 3 | import qualified Data.CaseInsensitive as CI 4 | import qualified Data.Map as Map 5 | import qualified Data.Text as Text 6 | import System.IO (stderr, stdout) 7 | import System.IO.Silently (hSilence) 8 | import Test.Tasty 9 | import Test.Tasty.ExpectedFailure 10 | import Test.Tasty.HUnit 11 | 12 | import Copilot.Verifier (Verbosity(..)) 13 | import Copilot.Verifier.Examples (shouldFailExamples, shouldPassExamples) 14 | 15 | main :: IO () 16 | main = defaultMain $ 17 | testGroup "copilot-verifier-examples tests" 18 | [ testGroup "should-fail tests" $ 19 | -- Why use hSilence for the should-fail tests when we are passing 20 | -- Quiet? It's because crux-llvm errors are logged at the highest 21 | -- severity possible, and even Crux's quietMode isn't enough to 22 | -- suppress those messages. We could try messing with things on the 23 | -- Crux side to avoid this, but it's simpler just to use hSilence here. 24 | -- After all, we don't really care about the output of failing tests 25 | -- anyway, just their exit codes. 26 | map (\(name, action) -> expectFail (testCase (Text.unpack (CI.original name)) 27 | (hSilence [stderr, stdout] action))) 28 | (Map.toAscList (shouldFailExamples Quiet)) 29 | , testGroup "should-pass tests" $ 30 | map (\(name, action) -> testCase (Text.unpack (CI.original name)) action) 31 | (Map.toAscList (shouldPassExamples Quiet)) 32 | ] 33 | -------------------------------------------------------------------------------- /copilot-visualizer/README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.com/Copilot-Language/copilot.svg?branch=master)](https://app.travis-ci.com/github/Copilot-Language/copilot) 2 | 3 | # Copilot: a stream DSL 4 | 5 | The visualizer, which draws Copilot specifications using different graphical 6 | formats. 7 | 8 | Copilot is a runtime verification framework written in Haskell. It allows the 9 | user to write programs in a simple but powerful way using a stream-based 10 | approach. 11 | 12 | Programs can be interpreted for testing (with the library copilot-interpreter), 13 | or translated C99 code to be incorporated in a project, or as a standalone 14 | application. The C99 backend ensures us that the output is constant in memory 15 | and time, making it suitable for systems with hard realtime requirements. 16 | 17 | ## Installation 18 | 19 | Copilot-visualizer can be found on 20 | [Hackage](https://hackage.haskell.org/package/copilot-interpreter). It is 21 | typically only installed as part of the complete Copilot distribution. For 22 | installation instructions, please refer to the [Copilot 23 | website](https://copilot-language.github.io). 24 | 25 | ## Further information 26 | 27 | For further information, install instructions and documentation, please visit 28 | the Copilot website: 29 | [https://copilot-language.github.io](https://copilot-language.github.io) 30 | 31 | ## License 32 | 33 | Copilot is distributed under the BSD-3-Clause license, which can be found 34 | [here](https://raw.githubusercontent.com/Copilot-Language/copilot/master/copilot-interpreter/LICENSE). 35 | -------------------------------------------------------------------------------- /copilot-visualizer/LICENSE: -------------------------------------------------------------------------------- 1 | 2024-2025 (c) NASA 2 | BSD3 License terms 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions 6 | are met: 7 | 8 | Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in the 13 | documentation and/or other materials provided with the distribution. 14 | 15 | Neither the name of the developers nor the names of its contributors 16 | may be used to endorse or promote products derived from this software 17 | without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 23 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 24 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 26 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 27 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 28 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /copilot-verifier/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2021-2024 Galois Inc. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions 6 | are met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | * Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in 13 | the documentation and/or other materials provided with the 14 | distribution. 15 | 16 | * Neither the name of Galois, Inc. nor the names of its contributors 17 | may be used to endorse or promote products derived from this 18 | software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 21 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 23 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 24 | OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | -------------------------------------------------------------------------------- /copilot-libraries/src/Copilot/Library/Statistics.hs: -------------------------------------------------------------------------------- 1 | -- | 2 | -- Module: Statistics 3 | -- Description: Basic bounded statistics 4 | -- Copyright: (c) 2011 National Institute of Aerospace / Galois, Inc. 5 | -- 6 | -- Basic bounded statistics. In the following, a bound @n@ is given stating 7 | -- the number of periods over which to compute the statistic (@n == 1@ computes 8 | -- it only over the current period). 9 | 10 | {-# LANGUAGE NoImplicitPrelude #-} 11 | 12 | module Copilot.Library.Statistics 13 | ( max, min, sum, mean, meanNow ) where 14 | 15 | import Copilot.Language 16 | import Copilot.Library.Utils 17 | 18 | -- | Summation. 19 | sum :: ( Typed a, Num a, Eq a ) => Int -> Stream a -> Stream a 20 | sum n s = nfoldl1 n (+) s 21 | 22 | -- | Maximum value. 23 | max :: ( Typed a, Ord a ) => Int -> Stream a -> Stream a 24 | max n s = nfoldl1 n largest s 25 | where 26 | largest = \ x y -> mux ( x >= y ) x y 27 | 28 | -- | Minimum value. 29 | min :: ( Typed a, Ord a ) => Int -> Stream a -> Stream a 30 | min n s = nfoldl1 n smallest s 31 | where 32 | smallest = \ x y -> mux ( x <= y ) x y 33 | 34 | -- | Mean value. @n@ must not overflow 35 | -- for word size @a@ for streams over which computation is peformed. 36 | mean :: ( Typed a, Eq a, Fractional a ) => Int -> Stream a -> Stream a 37 | mean n s = ( sum n s ) / ( fromIntegral n ) 38 | 39 | -- | Mean value over the current set of streams passed in. 40 | meanNow :: ( Typed a, Integral a ) => [ Stream a ] -> Stream a 41 | meanNow [] = 42 | badUsage "list of arguments to meanNow must be nonempty" 43 | meanNow ls = ( foldl1 (+) ls ) `div` ( fromIntegral $ length ls ) 44 | -------------------------------------------------------------------------------- /copilot-interpreter/CHANGELOG: -------------------------------------------------------------------------------- 1 | 2025-11-07 2 | * Version bump (4.6). (#679) 3 | 4 | 2025-09-07 5 | * Version bump (4.5.1). (#666) 6 | 7 | 2025-07-07 8 | * Version bump (4.5). (#642) 9 | 10 | 2025-05-07 11 | * Version bump (4.4). (#618) 12 | 13 | 2025-03-07 14 | * Version bump (4.3). (#604) 15 | 16 | 2025-01-07 17 | * Version bump (4.2). (#577) 18 | 19 | 2024-11-07 20 | * Version bump (4.1). (#561) 21 | 22 | 2024-09-07 23 | * Version bump (4.0). (#532) 24 | * Add support for array updates. (#36) 25 | 26 | 2024-07-07 27 | * Version bump (3.20). (#522) 28 | * Add support for struct field updates. (#520) 29 | 30 | 2024-05-07 31 | * Version bump (3.19.1). (#512) 32 | 33 | 2024-03-07 34 | * Version bump (3.19). (#504) 35 | 36 | 2024-01-07 37 | * Version bump (3.18.1). (#493) 38 | 39 | 2024-01-07 40 | * Version bump (3.18). (#487) 41 | 42 | 2023-11-07 43 | * Version bump (3.17). (#466) 44 | * Replace uses of deprecated functions. (#457) 45 | 46 | 2023-09-07 47 | * Version bump (3.16.1). (#455) 48 | 49 | 2023-07-07 50 | * Version bump (3.16). (#448) 51 | 52 | 2023-05-07 53 | * Version bump (3.15). (#438) 54 | 55 | 2023-03-07 56 | * Version bump (3.14). (#422) 57 | 58 | 2023-01-07 59 | * Version bump (3.13). (#406) 60 | 61 | 2022-11-07 62 | * Version bump (3.12). (#389) 63 | * Use pretty-printer from copilot-prettyprinter. (#383) 64 | 65 | 2022-09-07 66 | * Version bump (3.11). (#376) 67 | * Split copilot-interpreter into separate library. (#361) 68 | -------------------------------------------------------------------------------- /copilot-theorem/src/Copilot/Theorem/Prover/Backend.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE RankNTypes #-} 2 | {-# LANGUAGE Safe #-} 3 | 4 | -- | Backend to SMT solvers and theorem provers. 5 | -- 6 | -- This module provides three definitions: 7 | -- 8 | -- - A class ('SmtFormat') abstracting over the language used to communicate the 9 | -- desired commands to an SMT solver or theorem prover. 10 | -- 11 | -- - A class ('Backend') abstracting over the backend, which includes the name of 12 | -- the executable, any options and flags necessary, and functions to parse the 13 | -- results and close the communication. 14 | -- 15 | -- - A type ('SatResult') representing a satisfiability result communicated by 16 | -- the SMT solver or theorem prover. 17 | module Copilot.Theorem.Prover.Backend (SmtFormat(..), Backend(..), SatResult(..)) where 18 | 19 | import Copilot.Theorem.IL 20 | 21 | import System.IO 22 | 23 | -- | Format of SMT-Lib commands. 24 | class Show a => SmtFormat a where 25 | push :: a 26 | pop :: a 27 | checkSat :: a 28 | setLogic :: String -> a 29 | declFun :: String -> Type -> [Type] -> a 30 | assert :: Expr -> a 31 | 32 | -- | Backend to an SMT solver or theorem prover. 33 | data Backend a = Backend 34 | { name :: String 35 | , cmd :: String 36 | , cmdOpts :: [String] 37 | , inputTerminator :: Handle -> IO () 38 | , incremental :: Bool 39 | , logic :: String 40 | , interpret :: String -> Maybe SatResult 41 | } 42 | 43 | -- | Satisfiability result communicated by the SMT solver or theorem prover. 44 | data SatResult = Sat | Unsat | Unknown 45 | -------------------------------------------------------------------------------- /copilot-language/src/Copilot/Language/Operators/Projection.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE FlexibleInstances #-} 2 | {-# LANGUAGE FunctionalDependencies #-} 3 | {-# LANGUAGE TypeFamilies #-} 4 | -- | Interface to access portions of a larger data structure. 5 | -- 6 | -- Default operations to access elements from structs and arrays (e.g., a field 7 | -- of a struct, an element of an array) allow obtaining the values of those 8 | -- elements, but not modifying. 9 | -- 10 | -- This module defines a common interface to manipulate portions of a larger 11 | -- data structure. We define the interface in a generic way, using a type 12 | -- class with two operations: one to set the value of the sub-element, and 13 | -- one to update the value of such element applying a stream function. 14 | module Copilot.Language.Operators.Projection 15 | ( Projectable (..) ) 16 | where 17 | 18 | import Copilot.Language.Stream (Stream) 19 | 20 | infixl 8 =: 21 | infixl 8 =$ 22 | 23 | -- | Common interface to manipulate portions of a larger data structure. 24 | -- 25 | -- A projectable d s t means that it is possible to manipulate a sub-element s 26 | -- of type t carried in a stream of type d. 27 | class Projectable d s t | d s -> t where 28 | 29 | -- | Unapplied projection or element access on a type. 30 | data Projection d s t 31 | 32 | -- | Modify the value of a sub-element of a type in a stream of elements 33 | -- of that type. 34 | (=:) :: Projection d s t -> Stream t -> Stream d 35 | 36 | -- | Update the value of a sub-element of a type in a stream of elements of 37 | -- that type, by applying a function on streams. 38 | (=$) :: Projection d s t -> (Stream t -> Stream t) -> Stream d 39 | -------------------------------------------------------------------------------- /copilot-verifier/examples/Copilot/Verifier/Examples/ShouldPass/Clock.hs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- 2 | -- Copyright © 2019 National Institute of Aerospace / Galois, Inc. 3 | -------------------------------------------------------------------------------- 4 | 5 | -- | Example showing usage of clocks to generate periodically recurring truth 6 | -- values. 7 | 8 | module Copilot.Verifier.Examples.ShouldPass.Clock where 9 | 10 | import Control.Monad (when) 11 | import qualified Prelude as P 12 | 13 | import Language.Copilot 14 | import Copilot.Compile.C99 15 | import Copilot.Verifier ( Verbosity(..), VerifierOptions(..) 16 | , defaultVerifierOptions, verifyWithOptions ) 17 | import Copilot.Theorem.What4 (prove, Solver(..)) 18 | 19 | -- | We need to force a type for the argument of `period`. 20 | p :: Word8 21 | p = 5 22 | 23 | -- | Both have the same period, but a different phase. 24 | clkStream :: Stream Bool 25 | clkStream = clk (period p) (phase 0) 26 | 27 | clkStream' :: Stream Bool 28 | clkStream' = clk (period p) (phase 2) 29 | 30 | spec :: Spec 31 | spec = do 32 | observer "clk" clkStream 33 | observer "clk'" clkStream' 34 | _ <- prop "clksPhase" (forAll (clkStream == drop 2 clkStream')) 35 | _ <- prop "clksDistinct" (forAll (not (clkStream && clkStream'))) 36 | trigger "clksHigh" (clkStream && clkStream') [] 37 | 38 | 39 | verifySpec :: Verbosity -> IO () 40 | verifySpec verb = 41 | do s <- reify spec 42 | r <- prove Z3 s 43 | when (verb P.>= Default) $ 44 | print r 45 | verifyWithOptions defaultVerifierOptions{verbosity = verb} 46 | mkDefaultCSettings [] "clock" s 47 | -------------------------------------------------------------------------------- /copilot-prettyprinter/CHANGELOG: -------------------------------------------------------------------------------- 1 | 2025-11-07 2 | * Version bump (4.6). (#679) 3 | 4 | 2025-09-07 5 | * Version bump (4.5.1). (#666) 6 | 7 | 2025-07-07 8 | * Version bump (4.5). (#642) 9 | 10 | 2025-05-07 11 | * Version bump (4.4). (#618) 12 | 13 | 2025-03-07 14 | * Version bump (4.3). (#604) 15 | * Update pretty-printing to handle Props. (#254) 16 | 17 | 2025-01-07 18 | * Version bump (4.2). (#577) 19 | * Remove uses of Copilot.Core.Expr.UExpr.uExprExpr. (#565) 20 | 21 | 2024-11-07 22 | * Version bump (4.1). (#561) 23 | 24 | 2024-09-07 25 | * Version bump (4.0). (#532) 26 | * Add support for pretty-printing struct update expressions. (#526) 27 | * Add support for pretty-printing array update expressions. (#36) 28 | 29 | 2024-07-07 30 | * Version bump (3.20). (#522) 31 | 32 | 2024-05-07 33 | * Version bump (3.19.1). (#512) 34 | 35 | 2024-03-07 36 | * Version bump (3.19). (#504) 37 | 38 | 2024-01-07 39 | * Version bump (3.18.1). (#493) 40 | 41 | 2024-01-07 42 | * Version bump (3.18). (#487) 43 | 44 | 2023-11-07 45 | * Version bump (3.17). (#466) 46 | 47 | 2023-11-05 48 | * Replace uses of deprecated functions. (#457) 49 | 50 | 2023-09-07 51 | * Version bump (3.16.1). (#455) 52 | 53 | 2023-07-07 54 | * Version bump (3.16). (#448) 55 | 56 | 2023-05-07 57 | * Version bump (3.15). (#438) 58 | 59 | 2023-03-07 60 | * Version bump (3.14). (#422) 61 | 62 | 2023-01-07 63 | * Version bump (3.13). (#406) 64 | 65 | 2022-11-07 66 | * Version bump (3.12). (#389) 67 | * Create new library for pretty-printer. (#383) 68 | -------------------------------------------------------------------------------- /copilot-verifier/examples/Copilot/Verifier/Examples/ShouldPass/Array.hs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- 2 | -- Copyright © 2019 National Institute of Aerospace / Galois, Inc. 3 | -------------------------------------------------------------------------------- 4 | 5 | -- | This is a simple example for arrays. As a program, it does not make much 6 | -- sense, however it shows of the features of arrays nicely. 7 | 8 | -- | Enable compiler extension for type-level data, necesary for the array 9 | -- length. 10 | 11 | {-# LANGUAGE RebindableSyntax #-} 12 | {-# LANGUAGE DataKinds #-} 13 | 14 | module Copilot.Verifier.Examples.ShouldPass.Array where 15 | 16 | import Language.Copilot 17 | import Copilot.Compile.C99 18 | import Copilot.Verifier ( Verbosity, VerifierOptions(..) 19 | , defaultVerifierOptions, verifyWithOptions ) 20 | 21 | -- Lets define an array of length 2. 22 | -- Make the buffer of the streams 3 elements long. 23 | arr :: Stream (Array 2 Bool) 24 | arr = [ array [True, False] 25 | , array [True, True] 26 | , array [False, False]] ++ arr 27 | 28 | spec :: Spec 29 | spec = do 30 | -- A trigger that fires 'func' when the first element of 'arr' is True. 31 | -- It passes the current value of arr as an argument. 32 | -- The prototype of 'func' would be: 33 | -- void func (int8_t arg[3]); 34 | trigger "func" (arr ! 0) [arg arr] 35 | 36 | -- Compile the spec 37 | verifySpec :: Verbosity -> IO () 38 | verifySpec verb = reify spec >>= verifyWithOptions defaultVerifierOptions{verbosity = verb} 39 | mkDefaultCSettings [] "array" 40 | -- verifySpec _ = interpret 30 spec 41 | -------------------------------------------------------------------------------- /copilot/examples/Array.hs: -------------------------------------------------------------------------------- 1 | -- Copyright © 2019 National Institute of Aerospace / Galois, Inc. 2 | 3 | -- | This is a simple example for arrays. As a program, it does not make much 4 | -- sense, however it shows of the features of arrays nicely. 5 | 6 | -- | Enable compiler extension for type-level data, necesary for the array 7 | -- length. 8 | 9 | {-# LANGUAGE DataKinds #-} 10 | {-# LANGUAGE RebindableSyntax #-} 11 | 12 | module Main where 13 | 14 | import Language.Copilot 15 | 16 | -- Lets define an array of length 2. 17 | -- Make the buffer of the streams 3 elements long. 18 | arr :: Stream (Array 2 Bool) 19 | arr = [ array [True, False] 20 | , array [True, True] 21 | , array [False, False]] ++ arr 22 | 23 | spec :: Spec 24 | spec = do 25 | -- A trigger that fires 'func' when the first element of 'arr' is True. 26 | -- It passes the current value of arr as an argument. 27 | -- The prototype of 'func' would be: 28 | -- void func (int8_t arg[3]); 29 | trigger "func" (arr ! 0) [arg arr] 30 | 31 | -- A trigger that fires 'func2' every time. 32 | -- It passes the current value of arr as an argument, but updating the first 33 | -- element of the array to always be True. 34 | -- The prototype of 'func2' would be: 35 | -- void func2 (int8_t arg[3]); 36 | trigger "func2" true [arg (arr !! 0 =: true)] 37 | 38 | -- A trigger that fires 'func2' every time. 39 | -- It passes the current value of arr as an argument, but negating the second 40 | -- element of the array. 41 | -- The prototype of 'func3' would be: 42 | -- void func3 (int8_t arg[3]); 43 | trigger "func3" true [arg (arr !! 1 =$ not)] 44 | 45 | -- Compile the spec 46 | main :: IO () 47 | main = interpret 30 spec 48 | -------------------------------------------------------------------------------- /copilot-language/src/Copilot/Language/Interpret.hs: -------------------------------------------------------------------------------- 1 | -- Copyright (c) 2011 National Institute of Aerospace / Galois, Inc. 2 | 3 | -- | This module implements two interpreters, which may be used to simulate or 4 | -- execute Copilot specifications on a computer to understand their behavior to 5 | -- debug possible errors. 6 | -- 7 | -- The interpreters included vary in how the present the results to the user. 8 | -- One of them uses a format (csv) that may be more machine-readable, while the 9 | -- other uses a format that may be easier for humans to read. 10 | 11 | {-# LANGUAGE FlexibleInstances #-} 12 | {-# LANGUAGE GADTs #-} 13 | {-# LANGUAGE Safe #-} 14 | 15 | module Copilot.Language.Interpret 16 | ( csv 17 | , interpret 18 | ) where 19 | 20 | import qualified Copilot.Interpret as I 21 | 22 | import Copilot.Language.Spec (Spec) 23 | import Copilot.Language.Reify 24 | 25 | -- | Simulate a number of steps of a given specification, printing the results 26 | -- in a table in comma-separated value (CSV) format. 27 | csv :: Integer -> Spec -> IO () 28 | csv i spec = do 29 | putStrLn "Note: CSV format does not output observers." 30 | interpret' I.CSV i spec 31 | 32 | -- | Simulate a number of steps of a given specification, printing the results 33 | -- in a table in readable format. 34 | -- 35 | -- Compared to 'csv', this function is slower but the output may be more 36 | -- readable. 37 | interpret :: Integer -> Spec -> IO () 38 | interpret = interpret' I.Table 39 | 40 | -- | Simulate a number of steps of a given specification, printing the results 41 | -- in the format specified. 42 | interpret' :: I.Format -> Integer -> Spec -> IO () 43 | interpret' format i spec = do 44 | coreSpec <- reify spec 45 | putStrLn $ I.interpret format (fromIntegral i) coreSpec 46 | -------------------------------------------------------------------------------- /copilot-language/README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.com/Copilot-Language/copilot.svg?branch=master)](https://app.travis-ci.com/github/Copilot-Language/copilot) 2 | 3 | # Copilot: a stream DSL 4 | Copilot-language contains the actual embedded domain specific language that 5 | Copilot provides to its users. It comes with a series of basic operators and 6 | functionality, typically enough for most applications. Extended functionality 7 | is provided by the 8 | [copilot-libraries](https://github.com/Copilot-Language/copilot/tree/master/copilot-libraries) 9 | module. 10 | 11 | Copilot is a runtime verification framework written in Haskell. It allows the 12 | user to write programs in a simple but powerful way using a stream-based 13 | approach. 14 | 15 | Programs can be interpreted for testing, or translated C99 code to be 16 | incorporated in a project, or as a standalone application. The C99 backend 17 | ensures us that the output is constant in memory and time, making it suitable 18 | for systems with hard realtime requirements. 19 | 20 | 21 | ## Installation 22 | Copilot-language can be found on 23 | [Hackage](https://hackage.haskell.org/package/copilot-language). It is typically 24 | only installed as part of the complete Copilot distribution. For installation 25 | instructions, please refer to the [Copilot 26 | website](https://copilot-language.github.io). 27 | 28 | 29 | ## Further information 30 | For further information, install instructions and documentation, please visit 31 | the Copilot website: 32 | [https://copilot-language.github.io](https://copilot-language.github.io) 33 | 34 | 35 | ## License 36 | Copilot is distributed under the BSD-3-Clause license, which can be found 37 | [here](https://raw.githubusercontent.com/Copilot-Language/copilot/master/copilot-language/LICENSE). 38 | -------------------------------------------------------------------------------- /copilot-verifier/examples/Copilot/Verifier/Examples/ShouldPass/Arith.hs: -------------------------------------------------------------------------------- 1 | 2 | {-# LANGUAGE RebindableSyntax #-} 3 | 4 | module Copilot.Verifier.Examples.ShouldPass.Arith where 5 | 6 | import Control.Monad (when) 7 | import qualified Prelude as P 8 | 9 | import Language.Copilot 10 | import Copilot.Compile.C99 11 | import Copilot.Verifier ( Verbosity(..), VerifierOptions(..) 12 | , defaultVerifierOptions, verifyWithOptions ) 13 | import Copilot.Theorem.What4 (prove, Solver(..)) 14 | 15 | -- The largest unsigned 32-bit prime 16 | lastPrime :: Stream Word32 17 | lastPrime = 31 18 | --lastPrime = 4294967291 -- Whelp, this prime seems too big for the solvers to handle well 19 | 20 | multRingSpec :: Spec 21 | multRingSpec = do 22 | _ <- prop "clamp nonzero" (forAll ((clamp > 0) && (clamp < lastPrime))) 23 | _ <- prop "reduced" (forAll (acc < lastPrime)) 24 | _ <- prop "nonzero" (forAll (acc > 0 && (acc < lastPrime))) 25 | 26 | trigger "outofrange" (not (acc > 0 && acc < lastPrime)) [arg acc] 27 | 28 | return () 29 | 30 | where 31 | -- a stream of external values 32 | vals = externW32 "values" Nothing 33 | 34 | -- Generate a value in [1, lastPrime), which 35 | -- is the multiplictive group of Z_p 36 | clamp :: Stream Word32 37 | clamp = (vals `mod` (lastPrime - 1)) + 1 38 | 39 | -- Successively multiply new values 40 | acc :: Stream Word32 41 | acc = [1] ++ unsafeCast ((cast acc * cast clamp) `mod` (cast lastPrime :: Stream Word64)) 42 | 43 | verifySpec :: Verbosity -> IO () 44 | verifySpec verb = 45 | do s <- reify multRingSpec 46 | r <- prove Z3 s 47 | when (verb P.>= Default) $ 48 | print r 49 | verifyWithOptions defaultVerifierOptions{verbosity = verb} 50 | mkDefaultCSettings ["reduced"] "multRingSpec" s 51 | 52 | --verifySpec _ = interpret 10 engineMonitor 53 | -------------------------------------------------------------------------------- /copilot-prettyprinter/copilot-prettyprinter.cabal: -------------------------------------------------------------------------------- 1 | cabal-version: >=1.10 2 | name: copilot-prettyprinter 3 | version: 4.6 4 | synopsis: A prettyprinter of Copilot Specifications. 5 | description: 6 | A prettyprinter of Copilot specifications. 7 | . 8 | Copilot is a stream (i.e., infinite lists) domain-specific language (DSL) in 9 | Haskell that compiles into embedded C. Copilot contains an interpreter, 10 | multiple back-end compilers, and other verification tools. 11 | . 12 | A tutorial, examples, and other information are available at 13 | . 14 | 15 | author: Frank Dedden, Lee Pike, Robin Morisset, Alwyn Goodloe, 16 | Sebastian Niller, Nis Nordbyop Wegmann, Ivan Perez 17 | license: BSD3 18 | license-file: LICENSE 19 | maintainer: Ivan Perez 20 | homepage: https://copilot-language.github.io 21 | bug-reports: https://github.com/Copilot-Language/copilot/issues 22 | stability: Experimental 23 | category: Language, Embedded 24 | build-type: Simple 25 | extra-source-files: README.md, CHANGELOG 26 | 27 | x-curation: uncurated 28 | 29 | source-repository head 30 | type: git 31 | location: https://github.com/Copilot-Language/copilot.git 32 | subdir: copilot-prettyprinter 33 | 34 | library 35 | 36 | default-language: Haskell2010 37 | 38 | hs-source-dirs: src 39 | 40 | ghc-options: 41 | -Wall 42 | -fno-warn-orphans 43 | 44 | build-depends: 45 | base >= 4.9 && < 5, 46 | pretty >= 1.0 && < 1.2, 47 | 48 | copilot-core >= 4.6 && < 4.7 49 | 50 | exposed-modules: 51 | 52 | Copilot.PrettyPrint 53 | 54 | other-modules: 55 | 56 | Copilot.PrettyPrint.Error 57 | Copilot.PrettyPrint.Type 58 | -------------------------------------------------------------------------------- /copilot-verifier/examples/Copilot/Verifier/Examples/ShouldPass/Engine.hs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- 2 | -- Copyright © 2011 National Institute of Aerospace / Galois, Inc. 3 | -------------------------------------------------------------------------------- 4 | 5 | -- | Example implementing an engine cooling control system. 6 | 7 | {-# LANGUAGE RebindableSyntax #-} 8 | 9 | module Copilot.Verifier.Examples.ShouldPass.Engine where 10 | 11 | import Language.Copilot 12 | import Copilot.Compile.C99 13 | import Copilot.Verifier ( Verbosity, VerifierOptions(..) 14 | , defaultVerifierOptions, verifyWithOptions ) 15 | 16 | import qualified Prelude as P 17 | 18 | {- If the majority of the engine temperature probes exeeds 250 degrees, then 19 | - the cooler is engaged and remains engaged until the majority of the engine 20 | - temperature probes drop to 250 or below. Otherwise, trigger an immediate 21 | - shutdown of the engine. 22 | -} 23 | 24 | engineMonitor :: Spec 25 | engineMonitor = do 26 | trigger "shutoff" (not ok) [arg maj] 27 | 28 | where 29 | vals = [ externW8 "tmp_probe_0" two51 30 | , externW8 "tmp_probe_1" two51 31 | , externW8 "tmp_probe_2" zero] 32 | exceed = map (> 250) vals 33 | maj = majority exceed 34 | checkMaj = aMajority exceed maj 35 | ok = alwaysBeen ((maj && checkMaj) ==> extern "cooler" cooler) 36 | 37 | two51 = Just $ [251, 251] P.++ repeat (250 :: Word8) 38 | zero = Just $ repeat (0 :: Word8) 39 | cooler = Just $ [True, True] P.++ repeat False 40 | 41 | verifySpec :: Verbosity -> IO () 42 | verifySpec verb = reify engineMonitor >>= verifyWithOptions defaultVerifierOptions{verbosity = verb} 43 | mkDefaultCSettings [] "engine" 44 | --verifySpec _ = interpret 10 engineMonitor 45 | -------------------------------------------------------------------------------- /copilot/examples/fpga/HelloWorld/mkTop.v: -------------------------------------------------------------------------------- 1 | // 2 | // Generated by Bluespec Compiler, version 2025.01.1 (build 65e3a87a) 3 | // 4 | // Further modified by Sukhman Kahlon. 5 | // 6 | // On Thu Aug 14 14:52:29 PDT 2025 7 | // 8 | // 9 | // Ports: 10 | // Name I/O size props 11 | // CLK I 1 clock 12 | // RST_N I 1 reset 13 | // 14 | // No combinational paths from inputs to outputs 15 | // 16 | // 17 | 18 | `ifdef BSV_ASSIGNMENT_DELAY 19 | `else 20 | `define BSV_ASSIGNMENT_DELAY 21 | `endif 22 | 23 | `ifdef BSV_POSITIVE_RESET 24 | `define BSV_RESET_VALUE 1'b1 25 | `define BSV_RESET_EDGE posedge 26 | `else 27 | `define BSV_RESET_VALUE 1'b0 28 | `define BSV_RESET_EDGE negedge 29 | `endif 30 | 31 | module mkTop(CLK, 32 | RST_N, 33 | sw, 34 | leds); 35 | input CLK; 36 | input RST_N; 37 | input [3:0] sw; 38 | output [3:0] leds; 39 | 40 | assign leds[3:0] = ifc_led_reg[3:0]; 41 | 42 | // register ifc_led_reg 43 | reg [7 : 0] ifc_led_reg; 44 | wire [7 : 0] ifc_led_reg$D_IN; 45 | wire ifc_led_reg$EN; 46 | 47 | // register ifc_led_reg 48 | assign ifc_led_reg$D_IN = sw[3:0]; 49 | assign ifc_led_reg$EN = 1'd1 ; 50 | 51 | // handling of inlined registers 52 | 53 | always@(posedge CLK) 54 | begin 55 | if (RST_N == `BSV_RESET_VALUE) 56 | begin 57 | ifc_led_reg <= `BSV_ASSIGNMENT_DELAY 8'd0; 58 | end 59 | else 60 | begin 61 | if (ifc_led_reg$EN) 62 | ifc_led_reg <= `BSV_ASSIGNMENT_DELAY ifc_led_reg$D_IN; 63 | end 64 | end 65 | 66 | // synopsys translate_off 67 | `ifdef BSV_NO_INITIAL_BLOCKS 68 | `else // not BSV_NO_INITIAL_BLOCKS 69 | initial 70 | begin 71 | ifc_led_reg = 8'hAA; 72 | end 73 | `endif // BSV_NO_INITIAL_BLOCKS 74 | // synopsys translate_on 75 | endmodule // mkTop 76 | -------------------------------------------------------------------------------- /copilot-bluespec/CHANGELOG: -------------------------------------------------------------------------------- 1 | 2025-11-07 2 | * Version bump (4.6). (#679) 3 | * Flip direction of interface inputs and outputs in Bluespec. (#677) 4 | 5 | 2025-09-07 6 | * Version bump (4.5.1). (#666) 7 | 8 | 2025-07-07 9 | * Version bump (4.5). (#642) 10 | * Include `copilot-bluespec` in mainline `copilot` repo. (#623) 11 | 12 | 2025-05-08 13 | * Version bump (4.4). (copilot-bluespec#43) 14 | 15 | 2025-05-05 16 | * Version bump (4.3.1). (copilot-bluespec#41) 17 | * Move Copilot.Compile.Bluespec.External out of shared directory. 18 | (copilot-bluespec#36) 19 | * Allow building with filepath-1.5.*. (copilot-bluespec#39) 20 | 21 | 2025-03-10 22 | * Version bump (4.3). (copilot-bluespec#34) 23 | 24 | 2025-01-20 25 | * Version bump (4.2). (copilot-bluespec#31) 26 | * Implement missing floating-point operations. (copilot-bluespec#28) 27 | * Allow using same trigger name in multiple declarations. 28 | (copilot-bluespec#30) 29 | 30 | 2024-11-08 31 | * Version bump (4.1). (copilot-bluespec#25) 32 | 33 | 2024-09-09 34 | * Version bump (4.0). (copilot-bluespec#23) 35 | * Support translating Copilot array updates to Bluespec. 36 | (copilot-bluespec#19) 37 | 38 | 2024-08-03 39 | * Test GHC 9.4 through 9.8. (copilot-bluespec#20) 40 | 41 | 2024-07-11 42 | * Version bump (3.20). (copilot-bluespec#11) 43 | * Support translating Copilot struct updates to Bluespec. 44 | (copilot-bluespec#10) 45 | * Fix a bug in the translation of the signum function. 46 | (copilot-bluespec#14) 47 | * Fix a bug in the translation of floating-point comparisons. 48 | (copilot-bluespec#15) 49 | 50 | 2024-03-08 51 | * Version bump (3.19). (copilot-bluespec#5) 52 | * Create new library for Bluespec backend. 53 | -------------------------------------------------------------------------------- /copilot-theorem/examples/SerialBoyerMoore.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE RebindableSyntax #-} 2 | 3 | module SerialBoyerMoore where 4 | 5 | import Copilot.Language 6 | import Copilot.Theorem 7 | import Copilot.Theorem.Prover.Z3 8 | 9 | import Prelude () 10 | import Data.String (fromString) 11 | 12 | conj :: [Stream Bool] -> Stream Bool 13 | conj = foldl (&&) true 14 | 15 | disj :: [Stream Bool] -> Stream Bool 16 | disj = foldl (||) false 17 | 18 | forAllCst :: Typed a => [a] -> (Stream a -> Stream Bool) -> Stream Bool 19 | forAllCst l f = conj $ map (f . constant) l 20 | 21 | existsCst :: Typed a => [a] -> (Stream a -> Stream Bool) -> Stream Bool 22 | existsCst l f = disj $ map (f . constant) l 23 | 24 | allowed :: [Word64] 25 | allowed = [1, 2] 26 | 27 | majority :: Stream Word64 -> (Stream Word64, Stream Word64, Stream Bool) 28 | majority l = (p, s, j) 29 | where 30 | p = [0] ++ if s <= 0 then l else p 31 | s = [0] ++ if (p == l) || (s <= 0) then s + 1 else s - 1 32 | 33 | k = [0] ++ (1 + k) 34 | 35 | count m = cnt 36 | where 37 | cnt = [0] ++ if l == m then cnt + 1 else cnt 38 | 39 | j = forAllCst allowed $ \m -> 40 | local (count m) $ \cnt -> 41 | let j0 = (m /= p) ==> ((s + 2 * cnt) <= k) 42 | j1 = (m == p) ==> ((2 * cnt) <= (s + k)) 43 | in j0 && j1 44 | 45 | spec = do 46 | observer "i" input 47 | observer "p" p 48 | observer "s" s 49 | observer "j" j 50 | 51 | inRange <- prop "inRange" (forAll $ input < 3) 52 | theorem "J" (forAll j) $ assume inRange >> induct 53 | 54 | where 55 | input = externW64 "in" (Just [1, 1, 2, 1, 2, 2, 1, 2, 2, 1, 2, 1]) 56 | (p, s, j) = majority input 57 | 58 | induct :: Proof Universal 59 | induct = induction def { nraNLSat = False, debug = False } 60 | 61 | kinduct :: Word32 -> Proof Universal 62 | kinduct k = kInduction def { nraNLSat = False, startK = k, maxK = k, debug = False } 63 | -------------------------------------------------------------------------------- /copilot/examples/what4/Arithmetic.hs: -------------------------------------------------------------------------------- 1 | -- | An example showing the usage of the What4 backend in copilot-theorem for 2 | -- simple arithmetic. 3 | 4 | module Main where 5 | 6 | import qualified Prelude as P 7 | import Control.Monad (void, forM_) 8 | 9 | import Language.Copilot 10 | import Copilot.Theorem.What4 11 | 12 | spec :: Spec 13 | spec = do 14 | -- Define some external streams. Their values are not important, so external 15 | -- streams suffice. 16 | let eint8 :: Stream Int8 17 | eint8 = extern "eint8" Nothing 18 | eword8 :: Stream Word8 19 | eword8 = extern "eword8" Nothing 20 | efloat :: Stream Float 21 | efloat = extern "efloat" Nothing 22 | 23 | -- The simplest example involving numbers: equality on constant values. 24 | void $ prop "Example 1" (forAll ((constant (1 :: Int8)) == (constant 1))) 25 | 26 | -- Testing "a < a + 1". This should fail, because it isn't true. 27 | void $ prop "Example 2" (forAll (eint8 < (eint8 + 1))) 28 | 29 | -- Adding another condition to the above property to make it true. 30 | void $ prop "Example 3" (forAll ((eint8 < (eint8 + 1)) || (eint8 == 127))) 31 | 32 | -- Just like the previous example, but with words. 33 | void $ prop "Example 4" (forAll ((eword8 < (eword8 + 1)) || (eword8 == 255))) 34 | 35 | -- An example with floats. 36 | void $ prop "Example 5" (forAll ((2 * efloat) == (efloat + efloat))) 37 | 38 | -- Another example with floats. This fails, because it isn't true. 39 | void $ prop "Example 6" (forAll ((efloat + 1) /= efloat)) 40 | 41 | main :: IO () 42 | main = do 43 | spec' <- reify spec 44 | 45 | -- Use Z3 to prove the properties. 46 | results <- prove Z3 spec' 47 | 48 | -- Print the results. 49 | forM_ results $ \(nm, res) -> do 50 | putStr $ nm <> ": " 51 | case res of 52 | Valid -> putStrLn "valid" 53 | Invalid -> putStrLn "invalid" 54 | Unknown -> putStrLn "unknown" 55 | -------------------------------------------------------------------------------- /copilot-language/src/Copilot/Language/Operators/Boolean.hs: -------------------------------------------------------------------------------- 1 | -- Copyright © 2011 National Institute of Aerospace / Galois, Inc. 2 | 3 | {-# LANGUAGE Safe #-} 4 | 5 | -- | Boolean operators applied point-wise to streams. 6 | module Copilot.Language.Operators.Boolean 7 | ( (&&) 8 | , (||) 9 | , not 10 | , true 11 | , false 12 | , xor 13 | , (==>) 14 | ) where 15 | 16 | import qualified Copilot.Core as Core 17 | import Copilot.Language.Prelude 18 | import Copilot.Language.Operators.Constant (constant) 19 | import Copilot.Language.Stream 20 | import qualified Prelude as P 21 | 22 | -- | A stream that contains the constant value 'True'. 23 | true :: Stream Bool 24 | true = constant True 25 | 26 | -- | A stream that contains the constant value 'False'. 27 | false :: Stream Bool 28 | false = constant False 29 | 30 | infixr 4 && 31 | 32 | -- | Apply the and ('&&') operator to two boolean streams, point-wise. 33 | (&&) :: Stream Bool -> Stream Bool -> Stream Bool 34 | (Const False) && _ = false 35 | _ && (Const False) = false 36 | (Const True) && y = y 37 | x && (Const True) = x 38 | x && y = Op2 Core.And x y 39 | 40 | infixr 4 || 41 | 42 | -- | Apply the or ('||') operator to two boolean streams, point-wise. 43 | (||) :: Stream Bool -> Stream Bool -> Stream Bool 44 | (Const True) || _ = true 45 | _ || (Const True) = true 46 | (Const False) || y = y 47 | x || (Const False) = x 48 | x || y = Op2 Core.Or x y 49 | 50 | -- | Negate all the values in a boolean stream. 51 | not :: Stream Bool -> Stream Bool 52 | not (Const c) = (Const $ P.not c) 53 | not x = Op1 Core.Not x 54 | 55 | -- | Apply the exclusive-or ('xor') operator to two boolean streams, 56 | -- point-wise. 57 | xor :: Stream Bool -> Stream Bool -> Stream Bool 58 | xor x y = ( not x && y ) || ( x && not y ) 59 | 60 | -- | Apply the implication ('==>') operator to two boolean streams, point-wise. 61 | (==>) :: Stream Bool -> Stream Bool -> Stream Bool 62 | x ==> y = not x || y 63 | -------------------------------------------------------------------------------- /copilot-c99/src/Copilot/Compile/C99/Type.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE GADTs #-} 2 | 3 | -- | Translate Copilot Core expressions and operators to C99. 4 | module Copilot.Compile.C99.Type 5 | ( transType 6 | , transLocalVarDeclType 7 | , transTypeName 8 | ) 9 | where 10 | 11 | -- External imports 12 | import qualified Language.C99.Simple as C 13 | 14 | -- Internal imports: Copilot 15 | import Copilot.Core ( Type (..), typeLength, typeName ) 16 | 17 | -- | Translate a Copilot type to a C99 type. 18 | transType :: Type a -> C.Type 19 | transType ty = case ty of 20 | Bool -> C.TypeSpec $ C.TypedefName "bool" 21 | Int8 -> C.TypeSpec $ C.TypedefName "int8_t" 22 | Int16 -> C.TypeSpec $ C.TypedefName "int16_t" 23 | Int32 -> C.TypeSpec $ C.TypedefName "int32_t" 24 | Int64 -> C.TypeSpec $ C.TypedefName "int64_t" 25 | Word8 -> C.TypeSpec $ C.TypedefName "uint8_t" 26 | Word16 -> C.TypeSpec $ C.TypedefName "uint16_t" 27 | Word32 -> C.TypeSpec $ C.TypedefName "uint32_t" 28 | Word64 -> C.TypeSpec $ C.TypedefName "uint64_t" 29 | Float -> C.TypeSpec C.Float 30 | Double -> C.TypeSpec C.Double 31 | Array ty' -> C.Array (transType ty') len 32 | where 33 | len = Just $ C.LitInt $ fromIntegral $ typeLength ty 34 | Struct s -> C.TypeSpec $ C.Struct (typeName s) 35 | 36 | -- | Translate a Copilot type to a valid (local) variable declaration C99 type. 37 | -- 38 | -- If the type denotes an array, translate it to a pointer to whatever the 39 | -- array holds. This special case is needed when the type is used for a local 40 | -- variable declaration. We treat global variables differently (we generate 41 | -- list initializers). 42 | transLocalVarDeclType :: Type a -> C.Type 43 | transLocalVarDeclType (Array ty') = C.Ptr $ transType ty' 44 | transLocalVarDeclType ty = transType ty 45 | 46 | -- | Translate a Copilot type intro a C typename 47 | transTypeName :: Type a -> C.TypeName 48 | transTypeName ty = C.TypeName $ transType ty 49 | -------------------------------------------------------------------------------- /copilot-verifier/exe/VerifyExamples.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE NamedFieldPuns #-} 2 | {-# LANGUAGE OverloadedStrings #-} 3 | module Main (main) where 4 | 5 | import qualified Data.CaseInsensitive as CI 6 | import Data.CaseInsensitive (CI) 7 | import Data.Foldable (for_) 8 | import qualified Data.Map as Map 9 | import qualified Data.Text as Text 10 | import qualified Data.Text.IO as Text 11 | import Data.Text (Text) 12 | import Data.Traversable (for) 13 | import Options.Applicative 14 | 15 | import Copilot.Verifier (Verbosity(..)) 16 | import Copilot.Verifier.Examples (shouldFailExamples, shouldPassExamples) 17 | 18 | newtype Options = Options 19 | { examples :: [CI Text] 20 | } deriving Show 21 | 22 | optsParser :: Parser Options 23 | optsParser = Options 24 | <$> (some . strArgument) 25 | ( metavar "EXAMPLE1 [EXAMPLE2 ...]" 26 | <> help "The names of the examples to run" ) 27 | 28 | main :: IO () 29 | main = execParser opts >>= verifyExamples 30 | where 31 | opts = info (optsParser <**> helper) 32 | ( fullDesc 33 | <> header "Run one or more copilot-verifier examples" 34 | <> progDesc (unlines [ "Run one or more examples from the copilot-verifier/examples directory." 35 | , "Each EXAMPLE must correspond to an example name." 36 | ])) 37 | 38 | verifyExamples :: Options -> IO () 39 | verifyExamples Options{examples} = do 40 | -- Check that all requested examples exist 41 | examplesWithMain <- for examples $ \example -> 42 | case Map.lookup example (shouldFailExamples Default `Map.union` shouldPassExamples Default) of 43 | Just m -> pure (example, m) 44 | Nothing -> fail $ "No example named " ++ Text.unpack (CI.original example) 45 | 46 | -- Run the examples 47 | for_ examplesWithMain $ \(example, exampleMain) -> do 48 | Text.putStrLn "=====" 49 | Text.putStrLn $ "== Running the " <> CI.original example <> " example..." 50 | Text.putStrLn "=====" 51 | Text.putStrLn "" 52 | exampleMain 53 | Text.putStrLn "" 54 | -------------------------------------------------------------------------------- /copilot-theorem/src/Copilot/Theorem/IL/Transform.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE LambdaCase #-} 2 | {-# LANGUAGE Safe #-} 3 | 4 | -- | Simplify IL expressions by partly evaluating operations on booleans. 5 | module Copilot.Theorem.IL.Transform ( bsimpl ) where 6 | 7 | import Copilot.Theorem.IL.Spec 8 | 9 | -- | Simplify IL expressions by partly evaluating operations on booleans, 10 | -- eliminating some boolean literals. 11 | -- 12 | -- For example, an if-then-else in which the condition is literally the 13 | -- constant True or the constant False can be reduced to an operation without 14 | -- choice in which the appropriate branch of the if-then-else is used instead. 15 | bsimpl :: Expr -> Expr 16 | bsimpl = until (\x -> bsimpl' x == x) bsimpl' 17 | where 18 | bsimpl' = \case 19 | Ite _ (ConstB True) e _ -> bsimpl' e 20 | Ite _ (ConstB False) _ e -> bsimpl' e 21 | Ite t c e1 e2 -> Ite t (bsimpl' c) (bsimpl' e1) (bsimpl' e2) 22 | 23 | Op1 _ Not (Op1 _ Not e) -> bsimpl' e 24 | Op1 _ Not (ConstB True) -> ConstB False 25 | Op1 _ Not (ConstB False) -> ConstB True 26 | Op1 t o e -> Op1 t o (bsimpl' e) 27 | 28 | Op2 _ Or e (ConstB False) -> bsimpl' e 29 | Op2 _ Or (ConstB False) e -> bsimpl' e 30 | Op2 _ Or _ (ConstB True) -> ConstB True 31 | Op2 _ Or (ConstB True) _ -> ConstB True 32 | 33 | Op2 _ And _ (ConstB False) -> ConstB False 34 | Op2 _ And (ConstB False) _ -> ConstB False 35 | Op2 _ And e (ConstB True) -> bsimpl' e 36 | Op2 _ And (ConstB True) e -> bsimpl' e 37 | 38 | Op2 _ Eq e (ConstB False) -> bsimpl' (Op1 Bool Not e) 39 | Op2 _ Eq (ConstB False) e -> bsimpl' (Op1 Bool Not e) 40 | Op2 _ Eq e (ConstB True) -> bsimpl' e 41 | Op2 _ Eq (ConstB True) e -> bsimpl' e 42 | 43 | Op2 t o e1 e2 -> Op2 t o (bsimpl' e1) (bsimpl' e2) 44 | 45 | FunApp t f args -> FunApp t f (map bsimpl' args) 46 | 47 | e -> e 48 | -------------------------------------------------------------------------------- /copilot-theorem/src/Copilot/Theorem/Kind2/AST.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE Safe #-} 2 | 3 | -- | Abstract syntax tree of Kind2 files. 4 | module Copilot.Theorem.Kind2.AST where 5 | 6 | -- | A file is a sequence of predicates and propositions. 7 | data File = File 8 | { filePreds :: [PredDef] 9 | , fileProps :: [Prop] } 10 | 11 | -- | A proposition is defined by a term. 12 | data Prop = Prop 13 | { propName :: String 14 | , propTerm :: Term } 15 | 16 | -- | A predicate definition. 17 | data PredDef = PredDef 18 | { predId :: String -- ^ Identifier for the predicate. 19 | , predStateVars :: [StateVarDef] -- ^ Variables identifying the states in the 20 | -- underlying state transition system. 21 | , predInit :: Term -- ^ Predicate that holds for initial 22 | -- states. 23 | , predTrans :: Term -- ^ Predicate that holds for two states, if 24 | -- there is state transition between them. 25 | } 26 | 27 | -- | A definition of a state variable. 28 | data StateVarDef = StateVarDef 29 | { varId :: String -- ^ Name of the variable. 30 | , varType :: Type -- ^ Type of the variable. 31 | , varFlags :: [StateVarFlag] } -- ^ Flags for the variable. 32 | 33 | -- | Types used in Kind2 files to represent Copilot types. 34 | -- 35 | -- The Kind2 backend provides functions to, additionally, constrain the range 36 | -- of numeric values depending on their Copilot type ('Int8', 'Int16', etc.). 37 | data Type = Int | Real | Bool 38 | 39 | -- | Possible flags for a state variable. 40 | data StateVarFlag = FConst 41 | 42 | -- | Type of the predicate, either belonging to an initial state or a pair of 43 | -- states with a transition. 44 | data PredType = Init | Trans 45 | 46 | -- | Datatype to describe a term in the Kind language. 47 | data Term = 48 | ValueLiteral String 49 | | PrimedStateVar String 50 | | StateVar String 51 | | FunApp String [Term] 52 | | PredApp String PredType [Term] 53 | -------------------------------------------------------------------------------- /copilot-verifier/examples/Copilot/Verifier/Examples/ShouldPass/Voting.hs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- 2 | -- Copyright © 2019 National Institute of Aerospace / Galois, Inc. 3 | -------------------------------------------------------------------------------- 4 | 5 | -- | Fault-tolerant voting examples. 6 | 7 | {-# LANGUAGE RebindableSyntax #-} 8 | 9 | module Copilot.Verifier.Examples.ShouldPass.Voting where 10 | 11 | import Language.Copilot 12 | import Copilot.Compile.C99 13 | import Copilot.Verifier ( Verbosity, VerifierOptions(..) 14 | , defaultVerifierOptions, verifyWithOptions ) 15 | 16 | vote :: Spec 17 | vote = do 18 | -- majority selects element with the biggest occurance. 19 | trigger "maj" true [arg maj] 20 | 21 | -- aMajority checks if the selected element has a majority. 22 | trigger "aMaj" true [arg $ aMajority inputs maj] 23 | 24 | where 25 | maj = majority inputs 26 | 27 | -- 26 input streams to vote on 28 | inputs :: [Stream Word32] 29 | inputs = [ a, b, c, d, e, f, g, h, i, j, k, l, m 30 | -- , n, o, p, q, r, s, t, u, v, w, x, y, z 31 | ] 32 | a = [0] ++ a + 1 33 | b = [0] ++ b + 1 34 | c = [0] ++ c + 1 35 | d = [0] ++ d + 1 36 | e = [1] ++ e + 1 37 | f = [1] ++ f + 1 38 | g = [1] ++ g + 1 39 | h = [1] ++ h + 1 40 | i = [1] ++ i + 1 41 | j = [1] ++ j + 1 42 | k = [1] ++ k + 1 43 | l = [1] ++ l + 1 44 | m = [1] ++ m + 1 45 | {- 46 | n = [1] ++ n + 1 47 | o = [1] ++ o + 1 48 | p = [1] ++ p + 1 49 | q = [1] ++ q + 1 50 | r = [1] ++ r + 1 51 | s = [1] ++ s + 1 52 | t = [1] ++ t + 1 53 | u = [1] ++ u + 1 54 | v = [1] ++ v + 1 55 | w = [1] ++ w + 1 56 | x = [1] ++ x + 1 57 | y = [1] ++ y + 1 58 | z = [1] ++ z + 1 59 | -} 60 | 61 | verifySpec :: Verbosity -> IO () 62 | --verifySpec _ = interpret 30 vote 63 | verifySpec verb = reify vote >>= verifyWithOptions defaultVerifierOptions{verbosity = verb} 64 | mkDefaultCSettings [] "voting" 65 | -------------------------------------------------------------------------------- /copilot-verifier/CHANGELOG: -------------------------------------------------------------------------------- 1 | 2025-11-07 2 | * Version bump (4.6). (#679) 3 | 4 | 2025-09-07 5 | * Version bump (4.5.1). (#666) 6 | 7 | 2025-07-07 8 | * Version bump (4.5). (#642) 9 | * Include `copilot-verifier` in mainline `copilot` repo. (#622) 10 | 11 | 2025-05-08 12 | * Version bump (4.4). (copilot-verifier#85) 13 | 14 | 2025-03-10 15 | * Version bump (4.3). (copilot-verifier#82) 16 | * Add `smtSolver` option to `VerifierOptions`. (copilot-verifier#78) 17 | * Add `smtFloatMode` option to `VerifierOptions`. (copilot-verifier#79) 18 | 19 | 2025-01-20 20 | * Version bump (4.2). (copilot-verifier#76) 21 | * Reject specs that use multiple triggers with the same name. 22 | (copilot-verifier#74) 23 | 24 | 2024-11-08 25 | * Version bump (4.1). (copilot-verifier#72) 26 | 27 | 2024-09-09 28 | * Version bump (4.0). (copilot-verifier#69) 29 | * Support verifying programs that use array updates. 30 | (copilot-verifier#63) 31 | * Support verifying programs that use struct updates. 32 | (copilot-verifier#57) 33 | 34 | 2024-08-03 35 | * Support building with `crucible-llvm-0.7` and `crux-llvm-0.9`. 36 | (copilot-verifier#64) 37 | * Support GHC 9.4 through 9.8. (copilot-verifier#65) 38 | 39 | 2024-07-30 40 | * When using `Noisy` verbosity, always log proof goals related to the 41 | core correspondence proof, even if the goals are trivial. 42 | (copilot-verifier#51) 43 | * When using `Noisy` verbosity, log more information about which proof 44 | goals arise before or after calling the `step()` function. 45 | (copilot-verifier#52) 46 | 47 | 2024-07-11 48 | * Version bump (3.20). (copilot-verifier#58) 49 | 50 | 2024-03-08 51 | * Version bump (3.19). (copilot-verifier#53) 52 | * Provide more detailed feedback upon a successful run of the verifier. 53 | * Make the examples build with Copilot 3.19. (copilot-verifier#53) 54 | 55 | 2024-02-06 56 | * Initial release of `copilot-verifier`. 57 | -------------------------------------------------------------------------------- /copilot-language/src/Copilot/Language/Operators/BitWise.hs: -------------------------------------------------------------------------------- 1 | -- Copyright © 2011 National Institute of Aerospace / Galois, Inc. 2 | 3 | {-# LANGUAGE CPP #-} 4 | {-# LANGUAGE Safe #-} 5 | 6 | {-# OPTIONS_GHC -fno-warn-orphans #-} 7 | 8 | -- | Bitwise operators applied on streams, pointwise. 9 | module Copilot.Language.Operators.BitWise 10 | ( Bits ((.&.), complement, (.|.)) 11 | , (.^.) 12 | , (.<<.) 13 | , (.>>.) 14 | ) where 15 | 16 | import Copilot.Core (Typed, typeOf) 17 | import qualified Copilot.Core as Core 18 | import Copilot.Language.Stream 19 | import qualified Prelude as P 20 | 21 | #if MIN_VERSION_base(4,17,0) 22 | import Data.Bits hiding ((.>>.), (.<<.)) 23 | #else 24 | import Data.Bits 25 | #endif 26 | 27 | -- | Instance of the 'Bits' class for 'Stream's. 28 | -- 29 | -- Only the methods '.&.', 'complement', '.|.' and 'xor' are defined. 30 | instance (Typed a, Bits a) => Bits (Stream a) where 31 | (.&.) = Op2 (Core.BwAnd typeOf) 32 | complement = Op1 (Core.BwNot typeOf) 33 | (.|.) = Op2 (Core.BwOr typeOf) 34 | xor = Op2 (Core.BwXor typeOf) 35 | shiftL = P.error "shiftL undefined, for left-shifting use .<<." 36 | shiftR = P.error "shiftR undefined, for right-shifting use .>>." 37 | rotate = P.error "tbd: rotate" 38 | bitSize = P.error "tbd: bitSize" 39 | bitSizeMaybe = P.error "tbd: bitSizeMaybe" 40 | isSigned = P.error "tbd: issigned" 41 | testBit = P.error "tbd: testBit" 42 | bit = P.error "tbd: bit" 43 | popCount = P.error "tbd: popCount" 44 | 45 | #if !MIN_VERSION_base(4,17,0) 46 | -- | See 'xor'. 47 | (.^.) :: Bits a => a -> a -> a 48 | (.^.) = xor -- Avoid redefinition of the Operators.Boolean xor 49 | #endif 50 | 51 | -- | Shifting values of a stream to the left. 52 | (.<<.) :: (Bits a, Typed a, Typed b, P.Integral b) 53 | => Stream a -> Stream b -> Stream a 54 | (.<<.) = Op2 (Core.BwShiftL typeOf typeOf) 55 | 56 | -- | Shifting values of a stream to the right. 57 | (.>>.) :: (Bits a, Typed a, Typed b, P.Integral b) 58 | => Stream a -> Stream b -> Stream a 59 | (.>>.) = Op2 (Core.BwShiftR typeOf typeOf) 60 | -------------------------------------------------------------------------------- /copilot-c99/src/Copilot/Compile/C99/Name.hs: -------------------------------------------------------------------------------- 1 | -- | Naming of variables and functions in C. 2 | module Copilot.Compile.C99.Name 3 | ( argNames 4 | , argTempNames 5 | , exCpyName 6 | , generatorName 7 | , generatorOutputArgName 8 | , guardName 9 | , indexName 10 | , streamAccessorName 11 | , streamName 12 | ) 13 | where 14 | 15 | -- External imports: Copilot 16 | import Copilot.Core (Id) 17 | 18 | -- | Turn a stream id into a suitable C variable name. 19 | streamName :: Id -> String 20 | streamName sId = "s" ++ show sId 21 | 22 | -- | Turn a stream id into the global varname for indices. 23 | indexName :: Id -> String 24 | indexName sId = streamName sId ++ "_idx" 25 | 26 | -- | Turn a stream id into the name of its accessor function 27 | streamAccessorName :: Id -> String 28 | streamAccessorName sId = streamName sId ++ "_get" 29 | 30 | -- | Add a postfix for copies of external variables the name. 31 | exCpyName :: String -> String 32 | exCpyName name = name ++ "_cpy" 33 | 34 | -- | Turn stream id into name of its generator function. 35 | generatorName :: Id -> String 36 | generatorName sId = streamName sId ++ "_gen" 37 | 38 | -- | Turn stream id into name of its output argument array. 39 | generatorOutputArgName :: Id -> String 40 | generatorOutputArgName sId = streamName sId ++ "_output" 41 | 42 | -- | Turn the name of a trigger into a guard generator. 43 | guardName :: String -> String 44 | guardName name = name ++ "_guard" 45 | 46 | -- | Turn a trigger name into a trigger argument name. 47 | argName :: String -> Int -> String 48 | argName name n = name ++ "_arg" ++ show n 49 | 50 | -- | Turn a handler function name into a name for a temporary variable for a 51 | -- handler argument. 52 | argTempName :: String -> Int -> String 53 | argTempName name n = name ++ "_arg_temp" ++ show n 54 | 55 | -- | Enumerate all argument names based on trigger name. 56 | argNames :: String -> [String] 57 | argNames base = map (argName base) [0..] 58 | 59 | -- | Enumerate all temporary variable names based on handler function name. 60 | argTempNames :: String -> [String] 61 | argTempNames base = map (argTempName base) [0..] 62 | -------------------------------------------------------------------------------- /copilot-language/src/Copilot/Language/Operators/Integral.hs: -------------------------------------------------------------------------------- 1 | -- Copyright © 2011 National Institute of Aerospace / Galois, Inc. 2 | 3 | -- | Integral class operators applied point-wise on streams. 4 | 5 | {-# LANGUAGE Safe #-} 6 | 7 | module Copilot.Language.Operators.Integral 8 | ( div 9 | , mod 10 | , (^) 11 | ) where 12 | 13 | import Copilot.Core (Typed, typeOf) 14 | import qualified Copilot.Core as Core 15 | import qualified Copilot.Language.Error as Err 16 | import Copilot.Language.Operators.BitWise ((.<<.)) 17 | import Copilot.Language.Stream 18 | 19 | import qualified Data.Bits as B 20 | import qualified Prelude as P 21 | import Data.List (foldl', replicate) 22 | 23 | -- | Apply the 'Prelude.div' operation to two streams, point-wise. 24 | div :: (Typed a, P.Integral a) => Stream a -> Stream a -> Stream a 25 | (Const 0) `div` _ = Const 0 26 | _ `div` (Const 0) = Err.badUsage "in div: division by zero." 27 | x `div` (Const 1) = x 28 | x `div` y = Op2 (Core.Div typeOf) x y 29 | 30 | -- | Apply the 'Prelude.mod' operation to two streams, point-wise. 31 | mod :: (Typed a, P.Integral a) => Stream a -> Stream a -> Stream a 32 | _ `mod` (Const 0) = Err.badUsage "in mod: division by zero." 33 | (Const 0) `mod` _ = (Const 0) 34 | (Const x) `mod` (Const y) = Const (x `P.mod` y) 35 | x `mod` y = Op2 (Core.Mod typeOf) x y 36 | 37 | -- | Apply a limited form of exponentiation (@^@) to two streams, point-wise. 38 | -- 39 | -- Either the first stream must be the constant 2, or the second must be a 40 | -- constant stream. 41 | (^) :: (Typed a, Typed b, P.Num a, B.Bits a, P.Integral b) 42 | => Stream a -> Stream b -> Stream a 43 | (Const 0) ^ (Const 0) = Const 1 44 | (Const 0) ^ x = Op3 (Core.Mux typeOf) (Op2 (Core.Eq typeOf) x 0) (1) (0) 45 | (Const 1) ^ _ = Const 1 46 | (Const x) ^ (Const y) = Const (x P.^ y) 47 | (Const 2) ^ y = (Const 1) .<<. y 48 | x ^ (Const y) = foldl' ((P.*)) (Const 1) (replicate (P.fromIntegral y) x) 49 | _ ^ _ = Err.badUsage "in ^: in x ^ y, either x must be the constant 2, or y must be a constant. (Do not confuse ^ with bitwise XOR (.^.) or with ** for exponentation of floats/doubles.)" 50 | -------------------------------------------------------------------------------- /copilot-verifier/examples/Copilot/Verifier/Examples/ShouldPass/FPNegation.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE NoImplicitPrelude #-} 2 | 3 | -- | This will not succeed when 'smtFloatMode' is 'FloatUninterpreted', as Clang 4 | -- will turn @input /= 30.0@ below into a more complicated expression that also 5 | -- checks if @30.0@ is NaN or not. This is logically equivalent to the original 6 | -- specification, but an SMT solver cannot conclude this when all of the 7 | -- floating-point operations involved are treated as uninterpreted functions. 8 | -- 9 | -- To make this work, we set 'smtFloatMode' to 'FloatIEEE' instead. This works 10 | -- because all of the floating-point operations in the specification below are 11 | -- native to SMT-LIB. 12 | module Copilot.Verifier.Examples.ShouldPass.FPNegation where 13 | 14 | import Copilot.Compile.C99 (mkDefaultCSettings) 15 | import Copilot.Verifier ( Verbosity, VerifierOptions(..) 16 | , defaultVerifierOptions, verifyWithOptions ) 17 | import Copilot.Verifier.FloatMode (FloatMode(..)) 18 | import qualified Copilot.Library.PTLTL as PTLTL 19 | import Language.Copilot 20 | 21 | input :: Stream Float 22 | input = extern "input" Nothing 23 | 24 | -- | MyProperty 25 | -- @ 26 | -- Input is never 30.0 27 | -- @ 28 | propMyProperty :: Stream Bool 29 | propMyProperty = PTLTL.alwaysBeen (input /= 30.0) 30 | 31 | -- | Clock that increases in one-unit steps. 32 | clock :: Stream Int64 33 | clock = [0] ++ (clock + 1) 34 | 35 | -- | First Time Point 36 | ftp :: Stream Bool 37 | ftp = [True] ++ false 38 | 39 | pre :: Stream Bool -> Stream Bool 40 | pre = ([False] ++) 41 | 42 | tpre :: Stream Bool -> Stream Bool 43 | tpre = ([True] ++) 44 | 45 | notPreviousNot :: Stream Bool -> Stream Bool 46 | notPreviousNot = not . PTLTL.previous . not 47 | 48 | -- | Complete specification. Calls C handler functions when properties are 49 | -- violated. 50 | spec :: Spec 51 | spec = do 52 | trigger "handlerMyProperty" (not propMyProperty) [] 53 | 54 | verifySpec :: Verbosity -> IO () 55 | verifySpec verb = do 56 | spec' <- reify spec 57 | verifyWithOptions 58 | (defaultVerifierOptions 59 | { verbosity = verb 60 | , smtFloatMode = FloatIEEE 61 | }) 62 | mkDefaultCSettings [] "fpNegation" spec' 63 | -------------------------------------------------------------------------------- /copilot-verifier/examples/Copilot/Verifier/Examples/ShouldPass/Counter.hs: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------------- 2 | -- Copyright © 2019 National Institute of Aerospace / Galois, Inc. 3 | -------------------------------------------------------------------------------- 4 | 5 | -- | Example showing an implementation of a resettable counter. 6 | 7 | {-# LANGUAGE RebindableSyntax #-} 8 | 9 | module Copilot.Verifier.Examples.ShouldPass.Counter where 10 | 11 | import Control.Monad (when) 12 | import qualified Prelude as P 13 | 14 | import Language.Copilot 15 | import Copilot.Compile.C99 16 | import Copilot.Verifier ( Verbosity(..), VerifierOptions(..) 17 | , defaultVerifierOptions, verifyWithOptions ) 18 | import Copilot.Theorem.What4 (prove, Solver(..)) 19 | 20 | -- A resettable counter 21 | counter :: (Typed a, Integral a) => Stream Bool -> Stream Bool -> Stream a 22 | counter inc reset = cnt 23 | where 24 | cnt = if reset then 0 25 | else if inc then z + 1 26 | else z 27 | z = [0] ++ cnt 28 | 29 | -- Counter that resets when it reaches 256 30 | bytecounter :: Stream Int32 31 | bytecounter = counter true (resetcounter `mod` 256 == 0) 32 | 33 | resetcounter :: Stream Word32 34 | resetcounter = counter true false 35 | 36 | bytecounter2 :: Stream Int32 37 | bytecounter2 = counter true ([False] ++ bytecounter2 == 255) 38 | 39 | spec :: Spec 40 | spec = 41 | do _ <- prop "range" (forAll (bytecounter == unsafeCast (resetcounter `mod` 256))) 42 | _ <- prop "range2" (forAll (0 <= bytecounter2 && bytecounter2 <= 255)) 43 | _ <- prop "same" (forAll ((0 <= bytecounter2 && bytecounter2 <= 255) && 44 | (bytecounter == unsafeCast (resetcounter `mod` 256)) && 45 | (bytecounter == bytecounter2))) 46 | trigger "counter" true [arg $ bytecounter, arg $ bytecounter2] 47 | 48 | verifySpec :: Verbosity -> IO () 49 | -- verifSpec _ = interpret 1280 spec 50 | verifySpec verb = 51 | do s <- reify spec 52 | r <- prove Z3 s 53 | when (verb P.>= Default) $ 54 | print r 55 | verifyWithOptions defaultVerifierOptions{verbosity = verb} 56 | mkDefaultCSettings ["range", "range2"] "counter" s 57 | -------------------------------------------------------------------------------- /copilot-verifier/src/Copilot/Verifier/FloatMode.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE FlexibleContexts #-} 2 | {-# LANGUAGE GADTs #-} 3 | {-# LANGUAGE RankNTypes #-} 4 | 5 | module Copilot.Verifier.FloatMode 6 | ( FloatMode(..) 7 | , withFloatMode 8 | , withInterpretedFloatExprBuilder 9 | ) where 10 | 11 | import qualified What4.Expr.Builder as W4 12 | import qualified What4.InterpretedFloatingPoint as W4 13 | 14 | -- | How the verifier should interpret floating-point operations. 15 | data FloatMode 16 | = -- | Floating-point values are treated as bitvectors of the appropriate 17 | -- width, and all operations on them are translated as uninterpreted 18 | -- functions. This is the verifier's default interpretation, and it is what 19 | -- allows the verifier to perform any reasoning at all over floating-point 20 | -- operations that are not native to SMT-LIB (@sin@, @cos@, @tan@, etc.). 21 | FloatUninterpreted 22 | 23 | | -- | Floating-point values are treated as bit-precise IEEE-754 floats. This 24 | -- interpretation can perform deeper reasoning about floating-point 25 | -- operations that are native to SMT-LIB, but at the expense of causing the 26 | -- verifier to throw an error if it encounters operations that are not 27 | -- native to SMT-LIB (@sin@, @cos@, @tan@, etc.). Use at your own risk. 28 | FloatIEEE 29 | deriving Show 30 | 31 | -- | Convert a 'FloatMode' into a What4 'W4.FloatModeRepr' and pass it to a 32 | -- continuation. 33 | withFloatMode :: 34 | FloatMode -> 35 | (forall fm. W4.FloatModeRepr fm -> r) -> 36 | r 37 | withFloatMode fm k = 38 | case fm of 39 | FloatUninterpreted -> 40 | k W4.FloatUninterpretedRepr 41 | FloatIEEE -> 42 | k W4.FloatIEEERepr 43 | 44 | -- | Match on a 'W4.FloatModeRepr', compute evidence that it gives rise to an 45 | -- instance of 'W4.IsInterpretedFloatExprBuilder', and pass the evidence to a 46 | -- continutation. 47 | withInterpretedFloatExprBuilder :: 48 | W4.ExprBuilder t st (W4.Flags fm) -> 49 | W4.FloatModeRepr fm -> 50 | (W4.IsInterpretedFloatExprBuilder (W4.ExprBuilder t st (W4.Flags fm)) => r) -> 51 | r 52 | withInterpretedFloatExprBuilder _sym fm k = 53 | case fm of 54 | W4.FloatUninterpretedRepr -> k 55 | W4.FloatIEEERepr -> k 56 | W4.FloatRealRepr -> k 57 | -------------------------------------------------------------------------------- /copilot-language/src/Copilot/Language/Operators/Ord.hs: -------------------------------------------------------------------------------- 1 | -- Copyright © 2011 National Institute of Aerospace / Galois, Inc. 2 | 3 | {-# LANGUAGE Safe #-} 4 | 5 | -- | Comparison operators applied point-wise on streams. 6 | module Copilot.Language.Operators.Ord 7 | ( (<=) 8 | , (>=) 9 | , (<) 10 | , (>) 11 | ) where 12 | 13 | import Copilot.Core (Typed, typeOf) 14 | import qualified Copilot.Core as Core 15 | import Copilot.Language.Prelude 16 | import Copilot.Language.Stream 17 | import qualified Prelude as P 18 | 19 | -- | Compare two streams point-wise for order. 20 | -- 21 | -- The output stream contains the value True at a point in time if the 22 | -- element in the first stream is smaller or equal than the element in 23 | -- the second stream at that point in time, and False otherwise. 24 | (<=) :: (P.Ord a, Typed a) => Stream a -> Stream a -> Stream Bool 25 | (Const x) <= (Const y) = Const (x P.<= y) 26 | x <= y = Op2 (Core.Le typeOf) x y 27 | 28 | -- | Compare two streams point-wise for order. 29 | -- 30 | -- The output stream contains the value True at a point in time if the 31 | -- element in the first stream is greater or equal than the element in 32 | -- the second stream at that point in time, and False otherwise. 33 | (>=) :: (P.Ord a, Typed a) => Stream a -> Stream a -> Stream Bool 34 | (Const x) >= (Const y) = Const (x P.>= y) 35 | x >= y = Op2 (Core.Ge typeOf) x y 36 | 37 | -- | Compare two streams point-wise for order. 38 | -- 39 | -- The output stream contains the value True at a point in time if the 40 | -- element in the first stream is smaller than the element in the second stream 41 | -- at that point in time, and False otherwise. 42 | (<) :: (P.Ord a, Typed a) => Stream a -> Stream a -> Stream Bool 43 | (Const x) < (Const y) = Const (x P.< y) 44 | x < y = Op2 (Core.Lt typeOf) x y 45 | 46 | -- | Compare two streams point-wise for order. 47 | -- 48 | -- The output stream contains the value True at a point in time if the element 49 | -- in the first stream is greater than the element in the second stream at that 50 | -- point in time, and False otherwise. 51 | (>) :: (P.Ord a, Typed a) => Stream a -> Stream a -> Stream Bool 52 | (Const x) > (Const y) = Const (x P.> y) 53 | x > y = Op2 (Core.Gt typeOf) x y 54 | -------------------------------------------------------------------------------- /copilot-theorem/src/Copilot/Theorem/Misc/Utils.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE Trustworthy #-} 2 | 3 | -- | Utility / auxiliary functions. 4 | module Copilot.Theorem.Misc.Utils 5 | ( isSublistOf, nub', nubBy', nubEq 6 | , openTempFile 7 | ) where 8 | 9 | import Data.Function (on) 10 | import Data.List (groupBy, sortBy, group, sort) 11 | 12 | import Control.Applicative ((<$>)) 13 | import Control.Monad 14 | 15 | import qualified Data.Set as Set 16 | 17 | import System.IO hiding (openTempFile) 18 | import System.Random 19 | import System.Directory 20 | 21 | -- | True if the given list is a subset of the second list, when both are 22 | -- considered as sets. 23 | isSublistOf :: Ord a => [a] -> [a] -> Bool 24 | isSublistOf = Set.isSubsetOf `on` Set.fromList 25 | 26 | -- | True if both lists contain the same elements, when both are considered as 27 | -- sets. 28 | nubEq :: Ord a => [a] -> [a] -> Bool 29 | nubEq = (==) `on` Set.fromList 30 | 31 | -- | Remove duplicates from a list. 32 | -- 33 | -- This is an efficient version of 'Data.List.nub' that works for lists with a 34 | -- stronger constraint on the type (i.e., 'Ord', as opposed of 35 | -- 'Data.List.nub''s 'Eq' constraint). 36 | nub' :: Ord a => [a] -> [a] 37 | nub' = map head . group . sort 38 | 39 | -- | Variant of 'nub'' parameterized by the comparison function. 40 | nubBy' :: (a -> a -> Ordering) -> [a] -> [a] 41 | nubBy' f = map head . groupBy (\x y -> f x y == EQ) . sortBy f 42 | 43 | -- | Create a temporary file and open it for writing. 44 | openTempFile :: String -- ^ Directory where the file should be created. 45 | -> String -- ^ Base name for the file (prefix). 46 | -> String -- ^ File extension. 47 | -> IO (String, Handle) 48 | openTempFile loc baseName extension = do 49 | 50 | path <- freshPath 51 | handle <- openFile path WriteMode 52 | return (path, handle) 53 | 54 | where 55 | 56 | freshPath :: IO FilePath 57 | freshPath = do 58 | path <- pathFromSuff <$> randSuff 59 | exists <- doesFileExist path 60 | if exists then freshPath else return path 61 | 62 | randSuff :: IO String 63 | randSuff = replicateM 4 $ randomRIO ('0', '9') 64 | 65 | pathFromSuff :: String -> FilePath 66 | pathFromSuff suf = loc ++ "/" ++ baseName ++ suf ++ "." ++ extension 67 | -------------------------------------------------------------------------------- /copilot-core/src/Copilot/Core/Expr.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE ExistentialQuantification #-} 2 | {-# LANGUAGE GADTs #-} 3 | {-# LANGUAGE Safe #-} 4 | 5 | -- | 6 | -- Description: Internal representation of Copilot stream expressions. 7 | -- Copyright: (c) 2011 National Institute of Aerospace / Galois, Inc. 8 | module Copilot.Core.Expr 9 | ( Id 10 | , Name 11 | , Expr (..) 12 | , UExpr (..) 13 | , DropIdx 14 | ) 15 | where 16 | 17 | -- External imports 18 | import Data.Typeable (Typeable) 19 | import Data.Word (Word32) 20 | 21 | -- Internal imports 22 | import Copilot.Core.Operators (Op1, Op2, Op3) 23 | import Copilot.Core.Type (Type) 24 | 25 | -- | A stream identifier. 26 | type Id = Int 27 | 28 | -- | A name of a trigger, an external variable, or an external function. 29 | type Name = String 30 | 31 | -- | An index for the drop operator. 32 | type DropIdx = Word32 33 | 34 | -- | Internal representation of Copilot stream expressions. 35 | -- 36 | -- The Core representation mimics the high-level Copilot stream, but the Core 37 | -- representation contains information about the types of elements in the 38 | -- stream. 39 | data Expr a where 40 | Const :: Typeable a 41 | => Type a -> a -> Expr a 42 | 43 | Drop :: Typeable a 44 | => Type a -> DropIdx -> Id -> Expr a 45 | 46 | Local :: Typeable a 47 | => Type a -> Type b -> Name -> Expr a -> Expr b -> Expr b 48 | 49 | Var :: Typeable a 50 | => Type a -> Name -> Expr a 51 | 52 | ExternVar :: Typeable a 53 | => Type a -> Name -> Maybe [a] -> Expr a 54 | 55 | Op1 :: Typeable a 56 | => Op1 a b -> Expr a -> Expr b 57 | 58 | Op2 :: (Typeable a, Typeable b) 59 | => Op2 a b c -> Expr a -> Expr b -> Expr c 60 | 61 | Op3 :: (Typeable a, Typeable b, Typeable c) 62 | => Op3 a b c d -> Expr a -> Expr b -> Expr c -> Expr d 63 | 64 | Label :: Typeable a 65 | => Type a -> String -> Expr a -> Expr a 66 | 67 | -- | A untyped expression that carries the information about the type of the 68 | -- expression as a value, as opposed to exposing it at type level (using an 69 | -- existential). 70 | data UExpr = forall a . Typeable a => UExpr (Type a) (Expr a) 71 | -------------------------------------------------------------------------------- /copilot-verifier/examples/Copilot/Verifier/Examples/ShouldPass/Heater.hs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- 2 | -- Copyright 2019 National Institute of Aerospace / Galois, Inc. 3 | -------------------------------------------------------------------------------- 4 | 5 | -- This is a simple example with basic usage. It implements a simple home 6 | -- heating system: It heats when temp gets too low, and stops when it is high 7 | -- enough. It read temperature as a byte (range -50C to 100C) and translates 8 | -- this to Celcius. 9 | 10 | module Copilot.Verifier.Examples.ShouldPass.Heater where 11 | 12 | import Language.Copilot 13 | import Copilot.Compile.C99 14 | import Copilot.PrettyPrint as PP 15 | --import Copilot.Language.Prelude 16 | 17 | import Copilot.Verifier ( Verbosity(..), VerifierOptions(..) 18 | , defaultVerifierOptions, verifyWithOptions ) 19 | 20 | import qualified Prelude as P 21 | import Control.Monad (when) 22 | 23 | -- External temperature as a byte, range of -50C to 100C 24 | temp :: Stream Word8 25 | temp = extern "temperature" Nothing 26 | 27 | -- Calculate temperature in Celcius. 28 | -- We need to cast the Word8 to a Float. Note that it is an unsafeCast, as there 29 | -- is no direct relation between Word8 and Float. 30 | ctemp :: Stream Float 31 | ctemp = (unsafeCast temp * constant (150.0/255.0)) - constant 50.0 32 | 33 | -- width of the sliding window 34 | window :: Int 35 | window = 5 36 | 37 | -- Compute the sliding average of the last 5 temps 38 | -- (Here, 19.5 is the average of 18.0 and 21.0, the two temperature extremes 39 | -- that we check for in the spec.) 40 | avgTemp :: Stream Float 41 | avgTemp = (sum window (replicate window 19.5 ++ ctemp)) / fromIntegral window 42 | 43 | spec :: Spec 44 | spec = do 45 | trigger "heaton" (avgTemp < 18.0) [arg avgTemp] 46 | trigger "heatoff" (avgTemp > 21.0) [arg avgTemp] 47 | 48 | -- Compile the spec 49 | verifySpec :: Verbosity -> IO () 50 | verifySpec verb = 51 | do rspec <- reify spec 52 | when (verb P.>= Default) $ putStrLn (PP.prettyPrint rspec) 53 | verifyWithOptions defaultVerifierOptions{verbosity = verb} 54 | mkDefaultCSettings [] "heater" 55 | rspec 56 | 57 | {- 58 | do spec' <- reify spec 59 | putStrLn $ prettyPrintDot spec' 60 | -} 61 | -------------------------------------------------------------------------------- /copilot-core/copilot-core.cabal: -------------------------------------------------------------------------------- 1 | cabal-version: >=1.10 2 | name: copilot-core 3 | version: 4.6 4 | synopsis: An intermediate representation for Copilot. 5 | description: 6 | Intermediate representation for Copilot. 7 | . 8 | Copilot is a stream (i.e., infinite lists) domain-specific language (DSL) in 9 | Haskell that compiles into embedded C. Copilot contains an interpreter, 10 | multiple back-end compilers, and other verification tools. 11 | . 12 | A tutorial, examples, and other information are available at 13 | . 14 | 15 | author: Frank Dedden, Lee Pike, Robin Morisset, Alwyn Goodloe, 16 | Sebastian Niller, Nis Nordbyop Wegmann, Ivan Perez 17 | license: BSD3 18 | license-file: LICENSE 19 | maintainer: Ivan Perez 20 | homepage: https://copilot-language.github.io 21 | bug-reports: https://github.com/Copilot-Language/copilot/issues 22 | stability: Experimental 23 | category: Language, Embedded 24 | build-type: Simple 25 | extra-source-files: README.md, CHANGELOG 26 | 27 | x-curation: uncurated 28 | 29 | source-repository head 30 | type: git 31 | location: https://github.com/Copilot-Language/copilot.git 32 | subdir: copilot-core 33 | 34 | library 35 | 36 | default-language: Haskell2010 37 | 38 | hs-source-dirs: src 39 | 40 | ghc-options: 41 | -Wall 42 | -fno-warn-orphans 43 | 44 | build-depends: 45 | base >= 4.9 && < 5 46 | 47 | exposed-modules: 48 | 49 | Copilot.Core 50 | Copilot.Core.Expr 51 | Copilot.Core.Operators 52 | Copilot.Core.Spec 53 | Copilot.Core.Type 54 | Copilot.Core.Type.Array 55 | 56 | test-suite unit-tests 57 | type: 58 | exitcode-stdio-1.0 59 | 60 | main-is: 61 | Main.hs 62 | 63 | other-modules: 64 | Test.Extra 65 | Test.Copilot.Core.Type 66 | Test.Copilot.Core.Type.Array 67 | 68 | build-depends: 69 | base 70 | , HUnit 71 | , QuickCheck 72 | , test-framework 73 | , test-framework-hunit 74 | , test-framework-quickcheck2 75 | 76 | , copilot-core 77 | 78 | hs-source-dirs: 79 | tests 80 | 81 | default-language: 82 | Haskell2010 83 | 84 | ghc-options: 85 | -Wall 86 | -------------------------------------------------------------------------------- /copilot-core/src/Copilot/Core/Type/Array.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE DataKinds #-} 2 | {-# LANGUAGE GADTs #-} 3 | {-# LANGUAGE Safe #-} 4 | {-# LANGUAGE ScopedTypeVariables #-} 5 | {-# LANGUAGE TypeFamilies #-} 6 | {-# LANGUAGE TypeOperators #-} 7 | 8 | -- | 9 | -- Copyright: (c) 2011 National Institute of Aerospace / Galois, Inc. 10 | -- 11 | -- Implementation of an array that uses type literals to store length. No 12 | -- explicit indexing is used for the input data. Supports arbitrary nesting of 13 | -- arrays. 14 | module Copilot.Core.Type.Array 15 | ( Array 16 | , array 17 | , arrayElems 18 | , arrayUpdate 19 | ) 20 | where 21 | 22 | -- External imports 23 | import Data.Proxy (Proxy (..)) 24 | import GHC.TypeLits (KnownNat, Nat, natVal, type(-)) 25 | 26 | -- | Implementation of an array that uses type literals to store length. 27 | data Array (n :: Nat) t where 28 | Array :: [t] -> Array n t 29 | 30 | instance Show t => Show (Array n t) where 31 | show (Array xs) = show xs 32 | 33 | -- | Smart array constructor that only type checks if the length of the given 34 | -- list matches the length of the array at type level. 35 | array :: forall n t. KnownNat n => [t] -> Array n t 36 | array xs | datalen == typelen = Array xs 37 | | otherwise = error errmsg 38 | where 39 | datalen = length xs 40 | typelen = fromIntegral $ natVal (Proxy :: Proxy n) 41 | errmsg = "Length of data (" ++ show datalen ++ 42 | ") does not match length of type (" ++ show typelen ++ ")." 43 | 44 | -- | Return the elements of an array. 45 | arrayElems :: Array n a -> [a] 46 | arrayElems (Array xs) = xs 47 | 48 | -- | Update element of array to given element. 49 | -- 50 | -- PRE: the second argument denotes a valid index in the array. 51 | arrayUpdate :: Array n a -> Int -> a -> Array n a 52 | arrayUpdate (Array []) _ _ = error errMsg 53 | where 54 | errMsg = "copilot-core: arrayUpdate: Attempt to update empty array" 55 | 56 | arrayUpdate (Array (x:xs)) 0 y = Array (y:xs) 57 | 58 | arrayUpdate (Array (x:xs)) n y = 59 | arrayAppend x (arrayUpdate (Array xs) (n - 1) y) 60 | where 61 | -- | Append to an array while preserving length information at the type 62 | -- level. 63 | arrayAppend :: a -> Array (n - 1) a -> Array n a 64 | arrayAppend x (Array xs) = Array (x:xs) 65 | -------------------------------------------------------------------------------- /copilot-bluespec/src/Copilot/Compile/Bluespec/External.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE ExistentialQuantification #-} 2 | 3 | -- | Represent information about externs needed in the generation of Bluespec 4 | -- code for stream declarations and triggers. 5 | module Copilot.Compile.Bluespec.External 6 | ( External(..) 7 | , gatherExts 8 | ) where 9 | 10 | -- External imports 11 | import Data.List (unionBy) 12 | 13 | -- Internal imports: Copilot 14 | import Copilot.Core ( Expr (..), Stream (..), Trigger (..), Type, UExpr (..) ) 15 | 16 | -- | Representation of external variables. 17 | data External = forall a. External 18 | { extName :: String 19 | , extType :: Type a 20 | } 21 | 22 | -- | Collect all external variables from the streams and triggers. 23 | -- 24 | -- Although Copilot specifications can contain also properties and theorems, 25 | -- the Bluespec backend currently only generates code for streams and triggers. 26 | gatherExts :: [Stream] -> [Trigger] -> [External] 27 | gatherExts streams triggers = streamsExts `extUnion` triggersExts 28 | where 29 | streamsExts = foldr (extUnion . streamExts) mempty streams 30 | triggersExts = foldr (extUnion . triggerExts) mempty triggers 31 | 32 | streamExts :: Stream -> [External] 33 | streamExts (Stream _ _ expr _) = exprExts expr 34 | 35 | triggerExts :: Trigger -> [External] 36 | triggerExts (Trigger _ guard args) = guardExts `extUnion` argExts 37 | where 38 | guardExts = exprExts guard 39 | argExts = concatMap uExprExts args 40 | 41 | uExprExts :: UExpr -> [External] 42 | uExprExts (UExpr _ expr) = exprExts expr 43 | 44 | exprExts :: Expr a -> [External] 45 | exprExts (Local _ _ _ e1 e2) = exprExts e1 `extUnion` exprExts e2 46 | exprExts (ExternVar ty name _) = [External name ty] 47 | exprExts (Op1 _ e) = exprExts e 48 | exprExts (Op2 _ e1 e2) = exprExts e1 `extUnion` exprExts e2 49 | exprExts (Op3 _ e1 e2 e3) = exprExts e1 `extUnion` exprExts e2 50 | `extUnion` exprExts e3 51 | exprExts (Label _ _ e) = exprExts e 52 | exprExts _ = [] 53 | 54 | -- | Union over lists of External, we solely base the equality on the 55 | -- extName's. 56 | extUnion :: [External] -> [External] -> [External] 57 | extUnion = unionBy (\a b -> extName a == extName b) 58 | -------------------------------------------------------------------------------- /copilot-verifier/examples/Copilot/Verifier/Examples/ShouldPass/UpdateStruct.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE RebindableSyntax #-} 2 | {-# LANGUAGE DataKinds #-} 3 | 4 | -- | An example showing of using @copilot-verifier@ to verify a specification 5 | -- involving structs where individual fields are updated. 6 | module Copilot.Verifier.Examples.ShouldPass.UpdateStruct where 7 | 8 | import Language.Copilot 9 | import Copilot.Compile.C99 10 | import Copilot.Verifier ( Verbosity, VerifierOptions(..) 11 | , defaultVerifierOptions, verifyWithOptions ) 12 | 13 | -- | Definition for `Volts`. 14 | data Volts = Volts 15 | { numVolts :: Field "numVolts" Word32 16 | , flag :: Field "flag" Bool 17 | } 18 | 19 | -- | `Struct` instance for `Volts`. 20 | instance Struct Volts where 21 | typeName _ = "volts" 22 | toValues vlts = [ Value Word32 (numVolts vlts) 23 | , Value Bool (flag vlts) 24 | ] 25 | 26 | -- | `Volts` instance for `Typed`. 27 | instance Typed Volts where 28 | typeOf = Struct (Volts (Field 0) (Field False)) 29 | 30 | data Battery = Battery 31 | { temp :: Field "temp" Word32 32 | , volts :: Field "volts" (Array 10 Volts) 33 | , other :: Field "other" (Array 10 (Array 5 Word32)) 34 | } 35 | 36 | -- | `Battery` instance for `Struct`. 37 | instance Struct Battery where 38 | typeName _ = "battery" 39 | toValues battery = [ Value typeOf (temp battery) 40 | , Value typeOf (volts battery) 41 | , Value typeOf (other battery) 42 | ] 43 | 44 | -- | `Battery` instance for `Typed`. Note that `undefined` is used as an 45 | -- argument to `Field`. This argument is never used, so `undefined` will never 46 | -- throw an error. 47 | instance Typed Battery where 48 | typeOf = Struct (Battery (Field 0) (Field undefined) (Field undefined)) 49 | 50 | spec :: Spec 51 | spec = do 52 | let battery :: Stream Battery 53 | battery = extern "battery" Nothing 54 | 55 | -- Update a struct field, then check it for equality. 56 | trigger "updateTrig" 57 | ((battery ## temp =$ (+1))#temp == (battery#temp + 1)) 58 | [arg battery] 59 | 60 | verifySpec :: Verbosity -> IO () 61 | verifySpec verb = reify spec >>= verifyWithOptions defaultVerifierOptions{verbosity = verb} 62 | mkDefaultCSettings [] "updateStruct" 63 | -------------------------------------------------------------------------------- /copilot-prettyprinter/src/Copilot/PrettyPrint/Type.hs: -------------------------------------------------------------------------------- 1 | -- Copyright © 2011 National Institute of Aerospace / Galois, Inc. 2 | 3 | {-# LANGUAGE ExistentialQuantification #-} 4 | {-# LANGUAGE GADTs #-} 5 | {-# LANGUAGE Safe #-} 6 | 7 | -- | Show Copilot Core types and typed values. 8 | module Copilot.PrettyPrint.Type 9 | ( showWithType 10 | , ShowType(..) 11 | , showType 12 | ) where 13 | 14 | import Copilot.Core.Type 15 | 16 | -- Are we proving equivalence with a C backend, in which case we want to show 17 | -- Booleans as '0' and '1'. 18 | 19 | -- | Target language for showing a typed value. Used to adapt the 20 | -- representation of booleans. 21 | data ShowType = C | Haskell 22 | 23 | -- | Show a value. The representation depends on the type and the target 24 | -- language. Booleans are represented differently depending on the backend. 25 | showWithType :: ShowType -> Type a -> a -> String 26 | showWithType showT t x = 27 | case showT of 28 | C -> case t of 29 | Bool -> if x then "1" else "0" 30 | _ -> sw 31 | Haskell -> case t of 32 | Bool -> if x then "true" else "false" 33 | _ -> sw 34 | where 35 | sw = case showWit t of 36 | ShowWit -> show x 37 | 38 | -- | Show Copilot Core type. 39 | showType :: Type a -> String 40 | showType t = 41 | case t of 42 | Bool -> "Bool" 43 | Int8 -> "Int8" 44 | Int16 -> "Int16" 45 | Int32 -> "Int32" 46 | Int64 -> "Int64" 47 | Word8 -> "Word8" 48 | Word16 -> "Word16" 49 | Word32 -> "Word32" 50 | Word64 -> "Word64" 51 | Float -> "Float" 52 | Double -> "Double" 53 | Array t -> "Array " ++ showType t 54 | Struct t -> "Struct" 55 | 56 | -- * Auxiliary show instance 57 | 58 | -- | Witness datatype for showing a value, used by 'showWithType'. 59 | data ShowWit a = Show a => ShowWit 60 | 61 | -- | Turn a type into a show witness. 62 | showWit :: Type a -> ShowWit a 63 | showWit t = 64 | case t of 65 | Bool -> ShowWit 66 | Int8 -> ShowWit 67 | Int16 -> ShowWit 68 | Int32 -> ShowWit 69 | Int64 -> ShowWit 70 | Word8 -> ShowWit 71 | Word16 -> ShowWit 72 | Word32 -> ShowWit 73 | Word64 -> ShowWit 74 | Float -> ShowWit 75 | Double -> ShowWit 76 | Array t -> ShowWit 77 | Struct t -> ShowWit 78 | -------------------------------------------------------------------------------- /copilot-interpreter/copilot-interpreter.cabal: -------------------------------------------------------------------------------- 1 | cabal-version: >=1.10 2 | name: copilot-interpreter 3 | version: 4.6 4 | synopsis: Interpreter for Copilot. 5 | description: 6 | Interpreter for Copilot. 7 | . 8 | Copilot is a stream (i.e., infinite lists) domain-specific language (DSL) in 9 | Haskell that compiles into embedded C. Copilot contains an interpreter, 10 | multiple back-end compilers, and other verification tools. 11 | . 12 | A tutorial, examples, and other information are available at 13 | . 14 | 15 | author: Frank Dedden, Lee Pike, Robin Morisset, Alwyn Goodloe, 16 | Sebastian Niller, Nis Nordbyop Wegmann, Ivan Perez 17 | license: BSD3 18 | license-file: LICENSE 19 | maintainer: Ivan Perez 20 | homepage: https://copilot-language.github.io 21 | bug-reports: https://github.com/Copilot-Language/copilot/issues 22 | stability: Experimental 23 | category: Language, Embedded 24 | build-type: Simple 25 | extra-source-files: README.md, CHANGELOG 26 | 27 | x-curation: uncurated 28 | 29 | source-repository head 30 | type: git 31 | location: https://github.com/Copilot-Language/copilot.git 32 | subdir: copilot-interpreter 33 | 34 | library 35 | 36 | default-language: Haskell2010 37 | 38 | hs-source-dirs: src 39 | 40 | ghc-options: 41 | -Wall 42 | 43 | build-depends: 44 | base >= 4.9 && < 5, 45 | pretty >= 1.0 && < 1.2, 46 | 47 | copilot-core >= 4.6 && < 4.7 48 | 49 | exposed-modules: 50 | 51 | Copilot.Interpret 52 | Copilot.Interpret.Eval 53 | 54 | other-modules: 55 | 56 | Copilot.Interpret.Error 57 | Copilot.Interpret.Render 58 | 59 | test-suite unit-tests 60 | type: 61 | exitcode-stdio-1.0 62 | 63 | main-is: 64 | Main.hs 65 | 66 | other-modules: 67 | Test.Extra 68 | Test.Copilot.Interpret.Eval 69 | 70 | build-depends: 71 | base 72 | , QuickCheck 73 | , pretty 74 | , test-framework 75 | , test-framework-quickcheck2 76 | 77 | , copilot-core 78 | , copilot-interpreter 79 | , copilot-prettyprinter 80 | 81 | hs-source-dirs: 82 | tests 83 | 84 | default-language: 85 | Haskell2010 86 | 87 | ghc-options: 88 | -Wall 89 | -------------------------------------------------------------------------------- /copilot-language/src/Copilot/Language.hs: -------------------------------------------------------------------------------- 1 | -- Copyright © 2011 National Institute of Aerospace / Galois, Inc. 2 | 3 | -- | Main Copilot language export file. 4 | -- 5 | -- This is mainly a meta-module that re-exports most definitions in this 6 | -- library. 7 | 8 | {-# LANGUAGE Safe #-} 9 | 10 | module Copilot.Language 11 | ( module Data.Int 12 | , module Data.Word 13 | , module Copilot.Core 14 | , module Copilot.Core.Type 15 | , module Copilot.Core.Type.Array 16 | , module Copilot.Language.Error 17 | , module Copilot.Language.Interpret 18 | , module Copilot.Language.Operators.Boolean 19 | , module Copilot.Language.Operators.Cast 20 | , module Copilot.Language.Operators.Constant 21 | , module Copilot.Language.Operators.Eq 22 | , module Copilot.Language.Operators.Extern 23 | , module Copilot.Language.Operators.Local 24 | , module Copilot.Language.Operators.Label 25 | , module Copilot.Language.Operators.Integral 26 | , module Copilot.Language.Operators.Mux 27 | , module Copilot.Language.Operators.Ord 28 | , module Copilot.Language.Operators.Temporal 29 | , module Copilot.Language.Operators.BitWise 30 | , module Copilot.Language.Operators.Array 31 | , module Copilot.Language.Operators.Struct 32 | , module Copilot.Language.Prelude 33 | , Spec 34 | , Stream 35 | , observer 36 | , trigger 37 | , arg 38 | , prop 39 | , theorem 40 | , forAll 41 | , exists 42 | ) where 43 | 44 | import Data.Int hiding (Int) 45 | import Data.Word 46 | import Copilot.Core (Name, Typed) 47 | import Copilot.Core.Type 48 | import Copilot.Core.Type.Array 49 | import Copilot.Language.Error 50 | import Copilot.Language.Interpret 51 | import Copilot.Language.Operators.Boolean 52 | import Copilot.Language.Operators.Cast 53 | import Copilot.Language.Operators.Constant 54 | import Copilot.Language.Operators.Eq 55 | import Copilot.Language.Operators.Extern 56 | import Copilot.Language.Operators.Integral 57 | import Copilot.Language.Operators.Local 58 | import Copilot.Language.Operators.Label 59 | import Copilot.Language.Operators.Mux 60 | import Copilot.Language.Operators.Ord 61 | import Copilot.Language.Operators.Temporal 62 | import Copilot.Language.Operators.BitWise 63 | import Copilot.Language.Operators.Array 64 | import Copilot.Language.Operators.Struct 65 | import Copilot.Language.Reify 66 | import Copilot.Language.Prelude 67 | import Copilot.Language.Spec 68 | import Copilot.Language.Stream (Stream) 69 | -------------------------------------------------------------------------------- /copilot-bluespec/README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://github.com/Copilot-Language/copilot-bluespec/workflows/copilot-bluespec/badge.svg)](https://github.com/Copilot-Language/copilot-bluespec/actions?query=workflow%3Acopilot-bluespec) 2 | 3 | # Copilot: a stream DSL 4 | Copilot-Bluespec implements a Bluespec backend for Copilot, producing code that 5 | is suitable for FPGAs. 6 | 7 | Copilot is a runtime verification framework written in Haskell. It allows the 8 | user to write programs in a simple but powerful way using a stream-based 9 | approach. 10 | 11 | Programs can be interpreted for testing, or translated Bluespec code to be 12 | incorporated in a project, or as a standalone application. The Bluespec backend 13 | ensures us that the output is constant in memory and time, making it suitable 14 | for systems with hard realtime requirements. 15 | 16 | ## Installation 17 | Copilot-Bluespec can be found on 18 | [Hackage](https://hackage.haskell.org/package/copilot-bluespec). It is intended 19 | to be installed alongside a Copilot distribution by running the following 20 | commands: 21 | 22 | ``` 23 | $ cabal update 24 | $ cabal install copilot 25 | $ cabal install copilot-bluespec 26 | ``` 27 | 28 | For more detailed instructions on how to install Copilot, please refer to the 29 | [Copilot website](https://copilot-language.github.io). 30 | 31 | The generated Bluespec code requires `bsc` (the Bluespec compiler) in order to 32 | be compiled. `bsc` can be downloaded 33 | [here](https://github.com/B-Lang-org/bsc/releases). 34 | 35 | We also provide a [Dockerfile](Dockerfile) which automates the process of 36 | installing Copilot, Copilot-Bluespec, and `bsc`. The Dockerfile can be built and 37 | run using the following commands: 38 | 39 | ``` 40 | $ docker build -t . 41 | $ docker run -it 42 | ``` 43 | 44 | Where `` is a unique name for the Docker image. 45 | 46 | ## Further information 47 | For further information, install instructions and documentation, please visit 48 | the Copilot website: 49 | [https://copilot-language.github.io](https://copilot-language.github.io) 50 | 51 | There is also an implementation-focused design document 52 | [here](https://raw.githubusercontent.com/Copilot-Language/copilot/master/copilot-bluespec/DESIGN.md). 53 | 54 | 55 | ## License 56 | Copilot is distributed under the BSD-3-Clause license, which can be found 57 | [here](https://raw.githubusercontent.com/Copilot-Language/copilot/master/copilot-bluespec/LICENSE). 58 | -------------------------------------------------------------------------------- /copilot-verifier/examples/Copilot/Verifier/Examples/ShouldPass/IntOps.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE NoImplicitPrelude #-} 2 | module Copilot.Verifier.Examples.ShouldPass.IntOps where 3 | 4 | import Copilot.Compile.C99 (mkDefaultCSettings) 5 | import Copilot.Verifier ( Verbosity, VerifierOptions(..) 6 | , defaultVerifierOptions, verifyWithOptions ) 7 | import Language.Copilot 8 | import qualified Prelude as P 9 | 10 | spec :: Spec 11 | spec = do 12 | let stream :: Stream Int16 13 | stream = extern "stream" Nothing 14 | 15 | shiftBy :: Stream Int16 16 | shiftBy = extern "shiftBy" Nothing 17 | 18 | _ <- prop "nonzero" (forAll (stream /= 0)) 19 | _ <- prop "shiftByBits" (forAll (0 <= shiftBy && shiftBy < 16)) 20 | 21 | triggerOp1 "abs" abs stream 22 | triggerOp1 "signum" signum stream 23 | triggerOp1 "bwNot" complement stream 24 | 25 | triggerOp2 "add" (+) stream stream 26 | triggerOp2 "sub" (-) stream stream 27 | triggerOp2 "mul" (*) stream stream 28 | triggerOp2 "mod" mod stream stream 29 | triggerOp2 "div" div stream stream 30 | triggerOp2 "bwAnd" (.&.) stream stream 31 | triggerOp2 "bwOr" (.|.) stream stream 32 | triggerOp2 "bwXor" (.^.) stream stream 33 | triggerOp2 "bwShiftL" (.<<.) stream shiftBy 34 | triggerOp2 "bwShiftR" (.>>.) stream shiftBy 35 | 36 | triggerOp1 :: String -> 37 | (Stream Int16 -> Stream Int16) -> 38 | Stream Int16 -> 39 | Spec 40 | triggerOp1 name op stream = 41 | trigger (name P.++ "Trigger") (testOp1 op stream) [arg stream] 42 | 43 | triggerOp2 :: String -> 44 | (Stream Int16 -> Stream Int16 -> Stream Int16) -> 45 | Stream Int16 -> Stream Int16 -> 46 | Spec 47 | triggerOp2 name op stream1 stream2 = 48 | trigger (name P.++ "Trigger") (testOp2 op stream1 stream2) [arg stream1, arg stream2] 49 | 50 | testOp1 :: (Stream Int16 -> Stream Int16) -> Stream Int16 -> Stream Bool 51 | testOp1 op stream = 52 | op stream == op stream 53 | 54 | testOp2 :: (Stream Int16 -> Stream Int16 -> Stream Int16) -> 55 | Stream Int16 -> Stream Int16 -> 56 | Stream Bool 57 | testOp2 op stream1 stream2 = 58 | op stream1 stream2 == op stream1 stream2 59 | 60 | verifySpec :: Verbosity -> IO () 61 | verifySpec verb = do 62 | spec' <- reify spec 63 | verifyWithOptions defaultVerifierOptions{verbosity = verb} 64 | mkDefaultCSettings ["nonzero", "shiftByBits"] "intOps" spec' 65 | -------------------------------------------------------------------------------- /copilot-c99/src/Copilot/Compile/C99/External.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE ExistentialQuantification #-} 2 | 3 | -- | Represent information about externs needed in the generation of C99 code 4 | -- for stream declarations and triggers. 5 | module Copilot.Compile.C99.External 6 | ( External(..) 7 | , gatherExts 8 | ) 9 | where 10 | 11 | -- External imports 12 | import Data.List (unionBy) 13 | 14 | -- Internal imports: Copilot 15 | import Copilot.Core ( Expr (..), Stream (..), Trigger (..), Type, UExpr (..) ) 16 | 17 | -- Internal imports 18 | import Copilot.Compile.C99.Name ( exCpyName ) 19 | 20 | -- | Representation of external variables. 21 | data External = forall a. External 22 | { extName :: String 23 | , extCpyName :: String 24 | , extType :: Type a 25 | } 26 | 27 | -- | Collect all external variables from the streams and triggers. 28 | -- 29 | -- Although Copilot specifications can contain also properties and theorems, 30 | -- the C99 backend currently only generates code for streams and triggers. 31 | gatherExts :: [Stream] -> [Trigger] -> [External] 32 | gatherExts streams triggers = streamsExts `extUnion` triggersExts 33 | where 34 | streamsExts = foldr (extUnion . streamExts) mempty streams 35 | triggersExts = foldr (extUnion . triggerExts) mempty triggers 36 | 37 | streamExts :: Stream -> [External] 38 | streamExts (Stream _ _ expr _) = exprExts expr 39 | 40 | triggerExts :: Trigger -> [External] 41 | triggerExts (Trigger _ guard args) = guardExts `extUnion` argExts 42 | where 43 | guardExts = exprExts guard 44 | argExts = concatMap uExprExts args 45 | 46 | uExprExts :: UExpr -> [External] 47 | uExprExts (UExpr _ expr) = exprExts expr 48 | 49 | exprExts :: Expr a -> [External] 50 | exprExts (Local _ _ _ e1 e2) = exprExts e1 `extUnion` exprExts e2 51 | exprExts (ExternVar ty name _) = [External name (exCpyName name) ty] 52 | exprExts (Op1 _ e) = exprExts e 53 | exprExts (Op2 _ e1 e2) = exprExts e1 `extUnion` exprExts e2 54 | exprExts (Op3 _ e1 e2 e3) = exprExts e1 `extUnion` exprExts e2 55 | `extUnion` exprExts e3 56 | exprExts (Label _ _ e) = exprExts e 57 | exprExts _ = [] 58 | 59 | -- | Union over lists of External, we solely base the equality on the 60 | -- extName's. 61 | extUnion :: [External] -> [External] -> [External] 62 | extUnion = unionBy (\a b -> extName a == extName b) 63 | -------------------------------------------------------------------------------- /copilot/examples/Structs.hs: -------------------------------------------------------------------------------- 1 | -- | An example showing how specifications involving structs (in particular, 2 | -- nested structs) are compiled to C using copilot-c99. 3 | 4 | {-# LANGUAGE DataKinds #-} 5 | {-# LANGUAGE DeriveGeneric #-} 6 | 7 | module Main where 8 | 9 | import qualified Prelude as P 10 | import Control.Monad (void, forM_) 11 | import GHC.Generics (Generic) 12 | 13 | import Language.Copilot 14 | import Copilot.Compile.C99 15 | 16 | -- | Definition for `Volts`. 17 | data Volts = Volts 18 | { numVolts :: Field "numVolts" Word16 19 | , flag :: Field "flag" Bool 20 | } 21 | deriving Generic 22 | 23 | -- | `Struct` instance for `Volts`. 24 | instance Struct Volts where 25 | typeName = typeNameDefault 26 | toValues = toValuesDefault 27 | -- Note that we do not implement `updateField` here. `updateField` is only 28 | -- needed to make updates to structs work in the Copilot interpreter, and we 29 | -- do not use the interpreter in this example. (See 30 | -- `examples/StructsUpdateField.hs` for an example that does implement 31 | -- `updateField`.) 32 | 33 | -- | `Volts` instance for `Typed`. 34 | instance Typed Volts where 35 | typeOf = typeOfDefault 36 | 37 | data Battery = Battery 38 | { temp :: Field "temp" Word16 39 | , volts :: Field "volts" (Array 10 Volts) 40 | , other :: Field "other" (Array 10 (Array 5 Word32)) 41 | } 42 | deriving Generic 43 | 44 | -- | `Battery` instance for `Struct`. 45 | instance Struct Battery where 46 | typeName = typeNameDefault 47 | toValues = toValuesDefault 48 | -- Note that we do not implement `updateField` here for the same reasons as in 49 | -- the `Struct Volts` instance above. 50 | 51 | -- | `Battery` instance for `Typed`. 52 | instance Typed Battery where 53 | typeOf = typeOfDefault 54 | 55 | spec :: Spec 56 | spec = do 57 | let battery :: Stream Battery 58 | battery = extern "battery" Nothing 59 | 60 | -- Check equality, indexing into nested structs and arrays. Note that this is 61 | -- trivial by equality. 62 | trigger "equalitySameIndex" 63 | ((((battery#volts) ! 0)#numVolts) == (((battery#volts) ! 0)#numVolts)) 64 | [arg battery] 65 | 66 | -- Same as previous example, but get a different array index (so should be 67 | -- false). 68 | trigger "equalityDifferentIndices" 69 | ((((battery#other) ! 2) ! 3) == (((battery#other) ! 2) ! 4)) 70 | [arg battery] 71 | 72 | main :: IO () 73 | main = do 74 | spec' <- reify spec 75 | 76 | -- Compile the specific to C. 77 | compile "structs" spec' 78 | -------------------------------------------------------------------------------- /copilot-theorem/src/Copilot/Theorem/Kind2/PrettyPrint.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE Safe #-} 2 | 3 | -- | Pretty print a Kind2 file defining predicates and propositions. 4 | module Copilot.Theorem.Kind2.PrettyPrint ( prettyPrint ) where 5 | 6 | import Copilot.Theorem.Misc.SExpr 7 | import qualified Copilot.Theorem.Misc.SExpr as SExpr 8 | import Copilot.Theorem.Kind2.AST 9 | 10 | import Data.List (intercalate) 11 | 12 | -- | A tree of expressions, in which the leafs are strings. 13 | type SSExpr = SExpr String 14 | 15 | -- | Reserved keyword prime. 16 | kwPrime = "prime" 17 | 18 | -- | Pretty print a Kind2 file. 19 | prettyPrint :: File -> String 20 | prettyPrint = 21 | intercalate "\n\n" 22 | . map (SExpr.toString shouldIndent id) 23 | . ppFile 24 | 25 | -- | Define the indentation policy of the S-Expressions 26 | shouldIndent :: SSExpr -> Bool 27 | shouldIndent (Atom _) = False 28 | shouldIndent (List [Atom a, Atom _]) = a `notElem` [kwPrime] 29 | shouldIndent _ = True 30 | 31 | -- | Convert a file into a sequence of expressions. 32 | ppFile :: File -> [SSExpr] 33 | ppFile (File preds props) = map ppPredDef preds ++ ppProps props 34 | 35 | -- | Convert a sequence of propositions into command to check each of them. 36 | ppProps :: [Prop] -> [SSExpr] 37 | ppProps ps = [ node "check-prop" [ list $ map ppProp ps ] ] 38 | 39 | -- | Convert a proposition into an expression. 40 | ppProp :: Prop -> SSExpr 41 | ppProp (Prop n t) = list [atom n, ppTerm t] 42 | 43 | -- | Convert a predicate into an expression. 44 | ppPredDef :: PredDef -> SSExpr 45 | ppPredDef pd = 46 | list [ atom "define-pred" 47 | , atom (predId pd) 48 | , list . map ppStateVarDef . predStateVars $ pd 49 | , node "init" [ppTerm $ predInit pd] 50 | , node "trans" [ppTerm $ predTrans pd] ] 51 | 52 | -- | Convert a state variable definition into an expression. 53 | ppStateVarDef :: StateVarDef -> SSExpr 54 | ppStateVarDef svd = 55 | list [atom (varId svd), ppType (varType svd)] 56 | 57 | -- | Convert a type into an expression. 58 | ppType :: Type -> SSExpr 59 | ppType Int = atom "Int" 60 | ppType Real = atom "Real" 61 | ppType Bool = atom "Bool" 62 | 63 | -- | Convert a term into an expression. 64 | ppTerm :: Term -> SSExpr 65 | ppTerm (ValueLiteral c) = atom c 66 | ppTerm (PrimedStateVar v) = list [atom kwPrime, atom v] 67 | ppTerm (StateVar v) = atom v 68 | ppTerm (FunApp f args) = node f $ map ppTerm args 69 | ppTerm (PredApp p t args) = node (p ++ "." ++ ext) $ map ppTerm args 70 | where 71 | ext = case t of 72 | Init -> "init" 73 | Trans -> "trans" 74 | -------------------------------------------------------------------------------- /copilot-libraries/tests/Test/Copilot/Library/PTLTL.hs: -------------------------------------------------------------------------------- 1 | -- | Test copilot-libraries:Copilot.Library.PTLTL 2 | module Test.Copilot.Library.PTLTL 3 | (tests) 4 | where 5 | 6 | -- External imports 7 | import Test.Framework (Test, testGroup) 8 | import Test.Framework.Providers.QuickCheck2 (testProperty) 9 | import Test.QuickCheck (Gen, Property) 10 | 11 | -- External imports: Copilot 12 | import Copilot.Language (extern) 13 | import qualified Copilot.Language.Operators.Boolean as Copilot 14 | import Copilot.Language.Stream (Stream) 15 | import Copilot.Theorem.What4 (SatResult (..)) 16 | 17 | -- Internal imports: auxiliary functions 18 | import Test.Extra (arbitraryBoolExpr, testWithInterpreter, testWithTheorem) 19 | 20 | -- Internal imports: Modules being tested 21 | import Copilot.Library.PTLTL (eventuallyPrev, previous) 22 | 23 | -- * Constants 24 | 25 | -- | Unit tests for copilot-libraries:Copilot.Library.PTLTL. 26 | tests :: Test.Framework.Test 27 | tests = 28 | testGroup "Copilot.Library.PTLTL" 29 | [ testProperty "previous x ==> eventuallyPrev x (theorem)" 30 | testProvePreviousEventually 31 | , testProperty "previous x ==> eventuallyPrev x (interpreter)" 32 | testCheckPreviousEventually 33 | ] 34 | 35 | -- * Individual tests 36 | 37 | -- | Test that Z3 is able to prove the following expression valid: 38 | -- @ 39 | -- previous x ==> eventuallyPrev x 40 | -- @ 41 | testProvePreviousEventually :: Property 42 | testProvePreviousEventually = testWithTheorem pair 43 | where 44 | pair :: Gen (Stream Bool, SatResult) 45 | pair = pure (stream, expectation) 46 | 47 | stream :: Stream Bool 48 | stream = 49 | previous boolStream Copilot.==> eventuallyPrev boolStream 50 | where 51 | boolStream = extern "x" Nothing 52 | 53 | expectation :: SatResult 54 | expectation = Valid 55 | 56 | -- | Test that the following stream is always true: 57 | -- @ 58 | -- previous x ==> eventuallyPrev x 59 | -- @ 60 | testCheckPreviousEventually :: Property 61 | testCheckPreviousEventually = testWithInterpreter pair 62 | where 63 | pair :: Gen (Stream Bool, [Bool]) 64 | pair = do 65 | -- We discard the expectation from the expression; the temporal formula 66 | -- holds at all times regardless. 67 | boolStream <- fst <$> arbitraryBoolExpr 68 | let prop = previous boolStream Copilot.==> eventuallyPrev boolStream 69 | return (prop, expectation) 70 | 71 | expectation :: [Bool] 72 | expectation = repeat True 73 | -------------------------------------------------------------------------------- /copilot-theorem/src/Copilot/Theorem/Misc/SExpr.hs: -------------------------------------------------------------------------------- 1 | {-# LANGUAGE FlexibleInstances #-} 2 | {-# LANGUAGE Safe #-} 3 | 4 | -- | A representation for structured expression trees, with support for pretty 5 | -- printing. 6 | module Copilot.Theorem.Misc.SExpr where 7 | 8 | import Text.PrettyPrint.HughesPJ as PP hiding (char, Str) 9 | 10 | import Control.Monad 11 | 12 | -- | A structured expression is either an atom, or a sequence of expressions, 13 | -- where the first in the sequence denotes the tag or label of the tree. 14 | data SExpr a = Atom a 15 | | List [SExpr a] 16 | 17 | -- | Empty string expression. 18 | blank = Atom "" 19 | 20 | -- | Atomic expression constructor. 21 | atom = Atom -- s 22 | 23 | -- | Empty expression (empty list). 24 | unit = List [] -- () 25 | 26 | -- | Single expression. 27 | singleton a = List [Atom a] -- (s) 28 | 29 | -- | Sequence of expressions. 30 | list = List -- (ss) 31 | 32 | -- | Sequence of expressions with a root or main note, and a series of 33 | -- additional expressions or arguments. 34 | node a l = List (Atom a : l) -- (s ss) 35 | 36 | -- A straightforward string representation for 'SExpr's of Strings that 37 | -- parenthesizes lists of expressions. 38 | instance Show (SExpr String) where 39 | show = PP.render . show' 40 | where 41 | show' (Atom s) = text s 42 | show' (List ts) = parens . hsep . map show' $ ts 43 | 44 | -- More advanced printing with some basic indentation 45 | 46 | -- | Indent by a given number. 47 | indent = nest 1 48 | 49 | -- | Pretty print a structured expression as a String. 50 | toString :: (SExpr a -> Bool) -- ^ True if an expression should be indented. 51 | -> (a -> String) -- ^ Pretty print the value inside as 'SExpr'. 52 | -> SExpr a -- ^ Root of 'SExpr' tree. 53 | -> String 54 | toString shouldIndent printAtom expr = 55 | PP.render (toDoc shouldIndent printAtom expr) 56 | 57 | -- | Pretty print a structured expression as a 'Doc', or set of layouts. 58 | toDoc :: (SExpr a -> Bool) -- ^ True if an expression should be indented. 59 | -> (a -> String) -- ^ Pretty print the value inside as 'SExpr'. 60 | -> SExpr a -- ^ Root of 'SExpr' tree. 61 | -> Doc 62 | toDoc shouldIndent printAtom expr = case expr of 63 | Atom a -> text (printAtom a) 64 | List l -> parens (foldl renderItem empty l) 65 | 66 | where 67 | renderItem doc s 68 | | shouldIndent s = 69 | doc $$ indent (toDoc shouldIndent printAtom s) 70 | | otherwise = 71 | doc <+> toDoc shouldIndent printAtom s 72 | --------------------------------------------------------------------------------