-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathtermite.hs
214 lines (196 loc) · 10.3 KB
/
termite.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
{-# LANGUAGE FlexibleContexts, FlexibleInstances, MultiParamTypeClasses, ScopedTypeVariables, RecordWildCards, UndecidableInstances, TupleSections, ImplicitParams #-}
module Main where
import qualified Data.Map as M
import Data.Tuple.Select
import Data.Maybe
import Data.Char
import Control.Monad
import Control.Monad.ST
import Control.Monad.Trans
import Control.Monad.Trans.Identity
import Control.Error
import System.Environment
import System.Directory
import qualified Text.PrettyPrint as P
import System.Console.GetOpt
import Text.PrettyPrint
import System.FilePath.Posix
import Util
import TSLUtil
import Frontend.SpecInline
import PP
import Frontend.Parse
import Frontend.Spec
import Frontend.SpecOps
import Frontend.Grammar
import Debug.DbgGUI
import Debug.DbgTypes
import Cudd.Cudd
import qualified Cudd.Imperative as CI
import Solver.SMTLib2
import Debug.SourceView
import Debug.SourceViewTypes
import Debug.StrategyView
import Debug.AbstractorIFace
import Synthesis.RefineCommon
import Synthesis.TermiteGame hiding (Config)
import qualified Synthesis.TermiteGame as S
import Synthesis.RefineUtil
import Abstract.TSLAbsGame
import Solver.BVSMT
import Solver.Store
import Solver.SMTSolver
import Abstract.Predicate
import Synthesis.Resource
import qualified Internal.ISpec as I
import qualified Internal.TranSpec as I
-- import Spec2ASL
import TSL2C.TSL2C
import TSL2Boogie.Spec2Boogie
data TOption = InputTSL String
| ImportDir String
| BoundRefines String
| DoSynthesis
| DoCompile
| DoCGen
| DoHGen
| DoBoogie
| NoBuiltins
| ASLConvert
| Verbose
options :: [OptDescr TOption]
options = [ Option ['i'] [] (ReqArg InputTSL "FILE") "input TSL file"
, Option ['I'] [] (ReqArg ImportDir "DIRECTORY") "additional import lookup directory"
, Option ['s'] [] (NoArg DoSynthesis) "compile and synthesise"
, Option ['c'] [] (NoArg DoCompile) "compile only"
, Option ['g'] [] (NoArg DoCGen) "convert TSL file to C"
, Option ['h'] [] (NoArg DoHGen) "generate C header from the TSL file"
, Option ['r'] [] (ReqArg BoundRefines "n") "bound the number of refinements"
, Option ['v'] ["verbose"] (NoArg Verbose) "print verbose debug output"
, Option ['b'] ["boogie"] (NoArg DoBoogie) "convert transducers to Boogie"
, Option [] ["nobuiltins"] (NoArg NoBuiltins) "do not include TSL2 builtins"
--, Option [] ["asl"] (NoArg ASLConvert) "try to convert spec to ASL format"
]
data Config = Config { confTSLFile :: FilePath
, confImportDirs :: [FilePath]
, confBoundRefines :: Maybe Int
, confDoSynthesis :: Bool
, confDoCompile :: Bool
, confDoCGen :: Bool
, confDoHGen :: Bool
, confDoBoogie :: Bool
, confNoBuiltins :: Bool
, confDoASL :: Bool
, confVerbose :: Bool }
defaultConfig = Config { confTSLFile = ""
, confImportDirs = []
, confBoundRefines = Nothing
, confDoSynthesis = False
, confDoCompile = False
, confDoCGen = False
, confDoHGen = False
, confDoBoogie = False
, confNoBuiltins = False
, confDoASL = False
, confVerbose = False}
addOption :: TOption -> Config -> Config
addOption (InputTSL f) config = config{ confTSLFile = f}
addOption (ImportDir dir) config = config{ confImportDirs = (confImportDirs config) ++ [dir]}
addOption (BoundRefines b) config = config{ confBoundRefines = case reads b of
[] -> trace "invalid bound specified" Nothing
((i,_):_) -> Just i}
addOption DoSynthesis config = config{ confDoSynthesis = True}
addOption DoCompile config = config{ confDoCompile = True}
addOption DoCGen config = config{ confDoCGen = True}
addOption DoHGen config = config{ confDoHGen = True}
addOption DoBoogie config = config{ confDoBoogie = True}
addOption NoBuiltins config = config{ confNoBuiltins = True}
addOption ASLConvert config = config{ confDoASL = True}
addOption Verbose config = config{ confVerbose = True}
main = do
args <- getArgs
prog <- getProgName
config@Config{..} <- case getOpt Permute options args of
(flags, [], []) -> return $ foldr addOption defaultConfig flags
_ -> fail $ usageInfo ("Usage: " ++ prog ++ " [OPTION...]") options
let numactions = (if' confDoSynthesis 1 0) + (if' confDoCompile 1 0) + (if' confDoCGen 1 0) + (if' confDoHGen 1 0) + (if' confDoBoogie 1 0)
when (numactions /= 1) $ fail "Exactly one of -c, -s, -g, -h and -b options must be given"
(modules, spec) <- parseTSL confTSLFile confImportDirs (not confDoBoogie && not confNoBuiltins) (confDoCGen == False && confDoHGen == False && confDoBoogie == False)
createDirectoryIfMissing False "tmp"
writeFile "tmp/output.tsl" $ P.render $ pp spec
case validateSpec spec of
Left e -> fail $ "validation error: " ++ e
Right _ -> return ()
case (confDoCGen, confDoHGen) of
(False, False) -> compileAndSynthesise config spec
(True, _) -> genCCode (modules, spec) confTSLFile False
(_, True) -> genCCode (modules, spec) confTSLFile True
compileAndSynthesise :: Config -> Spec -> IO ()
compileAndSynthesise config@Config{..} spec = do
spec' <- case flatten spec of
Left e -> fail $ "flattening error: " ++ e
Right s -> return s
writeFile "tmp/output2.tsl" $ P.render $ pp spec'
case validateSpec spec' of
Left e -> fail $ "flattened spec validation error: " ++ e
Right _ -> return ()
-- when (confDoASL config) $ writeFile "output.asl" $ P.render $ spec2ASL ispec
if' confDoBoogie
(do let ispec = specXducers2Internal spec'
case spec2Boogie ispec of
Left e -> fail e
Right d -> writeFile (dropExtensions confTSLFile ++ ".bpl") (render d))
(CI.withManagerIODefaults $ \m -> do
let ispecFull = spec2Internal spec'
ispecDummy = ispecFull {I.specTran = (I.specTran ispecFull) { I.tsCTran = []
, I.tsUTran = []}}
ispec = if' confDoSynthesis ispecFull ispecDummy
solver = newSMTLib2Solver ispecFull z3Config
writeFile "tmp/output3.tsl" $ P.render $ pp ispec
stToIO $ setupManager m
(ri, model, absvars, sfact, inuse) <- do ((ri, res, avars, model, mstrategy), inuse) <- synthesise m config spec spec' ispec solver confDoSynthesis
putStrLn $ "Synthesis returned " ++ show res
-- putStrLn $ "inuse: " ++ show inuse
return (ri, model, avars, if' (isJust mstrategy) [(strategyViewNew $ fromJust mstrategy, True)] [], inuse)
putStrLn "starting debugger"
let sourceViewFactory = sourceViewNew spec spec' ispec absvars solver m ri inuse
debugGUI ((sourceViewFactory, True):(if' confDoSynthesis sfact [])) model)
genCCode :: (M.Map FilePath [SpecItem], Spec) -> String -> Bool -> IO ()
genCCode (modules, spec) f headeronly =
case M.lookup f modules of
Nothing -> fail $ "File " ++ f ++ " not found in the input specification"
Just items -> let ?spec = spec in
let hname = dropExtensions f ++ ".h"
cname = dropExtensions f ++ ".c"
hdef = map toUpper $ sanitize $ "_" ++ hname
hcode = text ("#ifndef " ++ hdef)
$$ text ("#define " ++ hdef)
$$ text ("#include <termite.h>")
$$ (module2C True items)
$$ text ("#endif /* " ++ hdef ++ " */")
ccode = text ("#include <" ++ hname ++ ">")
$$ (module2C False items) in
do writeFile hname (render hcode)
when (not headeronly) $ writeFile cname (render ccode)
synthesise :: CI.DDManager RealWorld u
-> Config
-> Spec
-> Spec
-> I.Spec
-> SMTSolver
-> Bool
-> IO ((RefineInfo RealWorld u AbsVar AbsVar [[AbsVar]], Maybe Bool, M.Map String AbsVar, Model DDManager DDNode Store SVStore, Maybe (Strategy DDNode)), InUse (CI.DDNode RealWorld u))
synthesise m Config{..} inspec flatspec spec solver dostrat = stToIO $ runResource M.empty $ do
let ts = bvSolver spec solver m
agame = tslAbsGame spec m ts
(win, ri) <- absRefineLoop (if' confVerbose (S.Config True True True True True True True)
(S.Config False False False True False True False))
m agame ts confBoundRefines
sr <- mkSynthesisRes spec m (if' dostrat win Nothing, ri)
let model = mkModel inspec flatspec spec solver sr
strategy = mkStrategy spec sr
(svars, sbits, lvars, lbits) = srStats sr
lift $ traceST $ "Concrete variables used in the final abstraction: " ++
"state variables: " ++ show svars ++ "(" ++ show sbits ++ "bits), " ++
"label variables: "++ show lvars ++ "(" ++ show lbits ++ "bits)"
return (ri, srWin sr, srAbsVars sr, model, strategy)