aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYann Herklotz <git@yannherklotz.com>2019-10-27 20:05:08 +0000
committerYann Herklotz <git@yannherklotz.com>2019-10-27 20:05:08 +0000
commitcbb08507aea00fd95eaf065a26a8902eb8e412c3 (patch)
tree3e94fbe6b1f2eb591234981905dbb753c39d95db
parent779833f8e1253c150a31541799195a57958adfef (diff)
downloadverismith-cbb08507aea00fd95eaf065a26a8902eb8e412c3.tar.gz
verismith-cbb08507aea00fd95eaf065a26a8902eb8e412c3.zip
Add OptParser to separate option parsing
-rw-r--r--src/Verismith.hs249
-rw-r--r--src/Verismith/OptParser.hs266
2 files changed, 270 insertions, 245 deletions
diff --git a/src/Verismith.hs b/src/Verismith.hs
index a3d3d03..bde3e2a 100644
--- a/src/Verismith.hs
+++ b/src/Verismith.hs
@@ -62,6 +62,7 @@ import Verismith.Circuit
import Verismith.Config
import Verismith.Fuzz
import Verismith.Generate
+import Verismith.OptParser
import Verismith.Reduce
import Verismith.Report
import Verismith.Result
@@ -70,254 +71,12 @@ import Verismith.Tool.Internal
import Verismith.Verilog
import Verismith.Verilog.Parser (parseSourceInfoFile)
-data OptTool = TYosys
- | TXST
- | TIcarus
-
-instance Show OptTool where
- show TYosys = "yosys"
- show TXST = "xst"
- show TIcarus = "icarus"
-
-data Opts = Fuzz { fuzzOutput :: {-# UNPACK #-} !Text
- , configFile :: !(Maybe FilePath)
- , forced :: !Bool
- , keepAll :: !Bool
- , num :: {-# UNPACK #-} !Int
- }
- | Generate { mFileName :: !(Maybe FilePath)
- , configFile :: !(Maybe FilePath)
- }
- | Parse { fileName :: {-# UNPACK #-} !FilePath
- }
- | Reduce { fileName :: {-# UNPACK #-} !FilePath
- , top :: {-# UNPACK #-} !Text
- , reduceScript :: !(Maybe FilePath)
- , synthesiserDesc :: ![SynthDescription]
- , rerun :: Bool
- }
- | ConfigOpt { writeConfig :: !(Maybe FilePath)
- , configFile :: !(Maybe FilePath)
- , doRandomise :: !Bool
- }
-
myForkIO :: IO () -> IO (MVar ())
myForkIO io = do
mvar <- newEmptyMVar
_ <- forkFinally io (\_ -> putMVar mvar ())
return mvar
-textOption :: Mod OptionFields String -> Parser Text
-textOption = fmap T.pack . strOption
-
-optReader :: (String -> Maybe a) -> ReadM a
-optReader f = eitherReader $ \arg -> case f arg of
- Just a -> Right a
- Nothing -> Left $ "Cannot parse option: " <> arg
-
-parseSynth :: String -> Maybe OptTool
-parseSynth val | val == "yosys" = Just TYosys
- | val == "xst" = Just TXST
- | otherwise = Nothing
-
-parseSynthDesc :: String -> Maybe SynthDescription
-parseSynthDesc val
- | val == "yosys" = Just $ SynthDescription "yosys" Nothing Nothing Nothing
- | val == "vivado" = Just $ SynthDescription "vivado" Nothing Nothing Nothing
- | val == "xst" = Just $ SynthDescription "xst" Nothing Nothing Nothing
- | val == "quartus" = Just
- $ SynthDescription "quartus" Nothing Nothing Nothing
- | val == "identity" = Just
- $ SynthDescription "identity" Nothing Nothing Nothing
- | otherwise = Nothing
-
-parseSim :: String -> Maybe OptTool
-parseSim val | val == "icarus" = Just TIcarus
- | otherwise = Nothing
-
-fuzzOpts :: Parser Opts
-fuzzOpts =
- Fuzz
- <$> textOption
- ( long "output"
- <> short 'o'
- <> metavar "DIR"
- <> help "Output directory that the fuzz run takes place in."
- <> showDefault
- <> value "output"
- )
- <*> ( optional
- . strOption
- $ long "config"
- <> short 'c'
- <> metavar "FILE"
- <> help "Config file for the current fuzz run."
- )
- <*> (switch $ long "force" <> short 'f' <> help
- "Overwrite the specified directory."
- )
- <*> (switch $ long "keep" <> short 'k' <> help
- "Keep all the directories."
- )
- <*> ( option auto
- $ long "num"
- <> short 'n'
- <> help "The number of fuzz runs that should be performed."
- <> showDefault
- <> value 1
- <> metavar "INT"
- )
-
-genOpts :: Parser Opts
-genOpts =
- Generate
- <$> ( optional
- . strOption
- $ long "output"
- <> short 'o'
- <> metavar "FILE"
- <> help "Output to a verilog file instead."
- )
- <*> ( optional
- . strOption
- $ long "config"
- <> short 'c'
- <> metavar "FILE"
- <> help "Config file for the generation run."
- )
-
-parseOpts :: Parser Opts
-parseOpts = Parse . fromText . T.pack <$> strArgument
- (metavar "FILE" <> help "Verilog input file.")
-
-reduceOpts :: Parser Opts
-reduceOpts =
- Reduce
- . fromText
- . T.pack
- <$> strArgument (metavar "FILE" <> help "Verilog input file.")
- <*> textOption
- ( short 't'
- <> long "top"
- <> metavar "TOP"
- <> help "Name of top level module."
- <> showDefault
- <> value "top"
- )
- <*> ( optional
- . strOption
- $ long "script"
- <> metavar "SCRIPT"
- <> help
- "Script that determines if the current file is interesting, which is determined by the script returning 0."
- )
- <*> ( many
- . option (optReader parseSynthDesc)
- $ short 's'
- <> long "synth"
- <> metavar "SYNTH"
- <> help "Specify synthesiser to use."
- )
- <*> ( switch
- $ short 'r'
- <> long "rerun"
- <> help
- "Only rerun the current synthesis file with all the synthesisers."
- )
-
-configOpts :: Parser Opts
-configOpts =
- ConfigOpt
- <$> ( optional
- . strOption
- $ long "output"
- <> short 'o'
- <> metavar "FILE"
- <> help "Output to a TOML Config file."
- )
- <*> ( optional
- . strOption
- $ long "config"
- <> short 'c'
- <> metavar "FILE"
- <> help "Config file for the current fuzz run."
- )
- <*> ( switch
- $ long "randomise"
- <> short 'r'
- <> help
- "Randomise the given default config, or the default config by randomly switchin on and off options."
- )
-
-argparse :: Parser Opts
-argparse =
- hsubparser
- ( command
- "fuzz"
- (info
- fuzzOpts
- (progDesc
- "Run fuzzing on the specified simulators and synthesisers."
- )
- )
- <> metavar "fuzz"
- )
- <|> hsubparser
- ( command
- "generate"
- (info
- genOpts
- (progDesc "Generate a random Verilog program.")
- )
- <> metavar "generate"
- )
- <|> hsubparser
- ( command
- "parse"
- (info
- parseOpts
- (progDesc
- "Parse a verilog file and output a pretty printed version."
- )
- )
- <> metavar "parse"
- )
- <|> hsubparser
- ( command
- "reduce"
- (info
- reduceOpts
- (progDesc
- "Reduce a Verilog file by rerunning the fuzzer on the file."
- )
- )
- <> metavar "reduce"
- )
- <|> hsubparser
- ( command
- "config"
- (info
- configOpts
- (progDesc
- "Print the current configuration of the fuzzer."
- )
- )
- <> metavar "config"
- )
-
-version :: Parser (a -> a)
-version = infoOption versionInfo $ mconcat
- [long "version", short 'v', help "Show version information.", hidden]
-
-opts :: ParserInfo Opts
-opts = info
- (argparse <**> helper <**> version)
- ( fullDesc
- <> progDesc "Fuzz different simulators and synthesisers."
- <> header
- "Verismith - A hardware simulator and synthesiser Verilog fuzzer."
- )
-
getConfig :: Maybe FilePath -> IO Config
getConfig s =
maybe (return defaultConfig) parseConfigFile $ T.unpack . toTextIgnore <$> s
@@ -363,12 +122,12 @@ randomise config@(Config a _ c d e) = do
ce = config ^. configProbability . probExpr
handleOpts :: Opts -> IO ()
-handleOpts (Fuzz o configF _ k n) = do
+handleOpts (Fuzz o configF f k n nosim noequiv) = do
config <- getConfig configF
_ <- runFuzz
- config
+ (FuzzOpts (Just $ fromText o) f k n nosim noequiv config)
defaultYosys
- (fuzzMultiple n k (Just $ fromText o) (proceduralSrc "top" config))
+ (fuzzMultiple (proceduralSrc "top" config))
return ()
handleOpts (Generate f c) = do
config <- getConfig c
diff --git a/src/Verismith/OptParser.hs b/src/Verismith/OptParser.hs
new file mode 100644
index 0000000..1db0d52
--- /dev/null
+++ b/src/Verismith/OptParser.hs
@@ -0,0 +1,266 @@
+module Verismith.OptParser
+ ( OptTool (..)
+ , Opts (..)
+ , opts
+ )
+where
+
+import Control.Applicative ((<|>))
+import Data.Text (Text)
+import qualified Data.Text as T
+import Options.Applicative (Mod (..), OptionFields (..), Parser (..),
+ ParserInfo (..), ReadM (..), (<**>))
+import qualified Options.Applicative as Opt
+import Prelude hiding (FilePath (..))
+import Shelly (FilePath (..), fromText)
+import Verismith.Config (SynthDescription (..), versionInfo)
+
+data OptTool = TYosys
+ | TXST
+ | TIcarus
+
+instance Show OptTool where
+ show TYosys = "yosys"
+ show TXST = "xst"
+ show TIcarus = "icarus"
+
+data Opts = Fuzz { fuzzOutput :: {-# UNPACK #-} !Text
+ , fuzzConfigFile :: !(Maybe FilePath)
+ , fuzzForced :: !Bool
+ , fuzzKeepAll :: !Bool
+ , fuzzNum :: {-# UNPACK #-} !Int
+ , fuzzNoSim :: !Bool
+ , fuzzNoEquiv :: !Bool
+ }
+ | Generate { generateFilename :: !(Maybe FilePath)
+ , generateConfigFile :: !(Maybe FilePath)
+ }
+ | Parse { parseFilename :: {-# UNPACK #-} !FilePath
+ }
+ | Reduce { reduceFilename :: {-# UNPACK #-} !FilePath
+ , reduceTop :: {-# UNPACK #-} !Text
+ , reduceScript :: !(Maybe FilePath)
+ , reduceSynthesiserDesc :: ![SynthDescription]
+ , reduceRerun :: !Bool
+ }
+ | ConfigOpt { configOptWriteConfig :: !(Maybe FilePath)
+ , configOptConfigFile :: !(Maybe FilePath)
+ , configOptDoRandomise :: !Bool
+ }
+
+textOption :: Mod OptionFields String -> Parser Text
+textOption = fmap T.pack . Opt.strOption
+
+optReader :: (String -> Maybe a) -> ReadM a
+optReader f = Opt.eitherReader $ \arg -> case f arg of
+ Just a -> Right a
+ Nothing -> Left $ "Cannot parse option: " <> arg
+
+parseSynth :: String -> Maybe OptTool
+parseSynth val | val == "yosys" = Just TYosys
+ | val == "xst" = Just TXST
+ | otherwise = Nothing
+
+parseSynthDesc :: String -> Maybe SynthDescription
+parseSynthDesc val
+ | val == "yosys" = Just $ SynthDescription "yosys" Nothing Nothing Nothing
+ | val == "vivado" = Just $ SynthDescription "vivado" Nothing Nothing Nothing
+ | val == "xst" = Just $ SynthDescription "xst" Nothing Nothing Nothing
+ | val == "quartus" = Just
+ $ SynthDescription "quartus" Nothing Nothing Nothing
+ | val == "identity" = Just
+ $ SynthDescription "identity" Nothing Nothing Nothing
+ | otherwise = Nothing
+
+parseSim :: String -> Maybe OptTool
+parseSim val | val == "icarus" = Just TIcarus
+ | otherwise = Nothing
+
+fuzzOpts :: Parser Opts
+fuzzOpts =
+ Fuzz
+ <$> textOption
+ ( Opt.long "output"
+ <> Opt.short 'o'
+ <> Opt.metavar "DIR"
+ <> Opt.help "Output directory that the fuzz run takes place in."
+ <> Opt.showDefault
+ <> Opt.value "output"
+ )
+ <*> ( Opt.optional
+ . Opt.strOption
+ $ Opt.long "config"
+ <> Opt.short 'c'
+ <> Opt.metavar "FILE"
+ <> Opt.help "Config file for the current fuzz run."
+ )
+ <*> (Opt.switch $ Opt.long "force" <> Opt.short 'f' <> Opt.help
+ "Overwrite the specified directory."
+ )
+ <*> (Opt.switch $ Opt.long "keep" <> Opt.short 'k' <> Opt.help
+ "Keep all the directories."
+ )
+ <*> ( Opt.option Opt.auto
+ $ Opt.long "num"
+ <> Opt.short 'n'
+ <> Opt.help "The number of fuzz runs that should be performed."
+ <> Opt.showDefault
+ <> Opt.value 1
+ <> Opt.metavar "INT"
+ )
+ <*> (Opt.switch $ Opt.long "no-sim" <> Opt.help
+ "Do not run simulation on the output netlist."
+ )
+ <*> (Opt.switch $ Opt.long "no-equiv" <> Opt.help
+ "Do not run an equivalence check on the output netlist."
+ )
+
+genOpts :: Parser Opts
+genOpts =
+ Generate
+ <$> ( Opt.optional
+ . Opt.strOption
+ $ Opt.long "output"
+ <> Opt.short 'o'
+ <> Opt.metavar "FILE"
+ <> Opt.help "Output to a verilog file instead."
+ )
+ <*> ( Opt.optional
+ . Opt.strOption
+ $ Opt.long "config"
+ <> Opt.short 'c'
+ <> Opt.metavar "FILE"
+ <> Opt.help "Config file for the generation run."
+ )
+
+parseOpts :: Parser Opts
+parseOpts = Parse . fromText . T.pack <$> Opt.strArgument
+ (Opt.metavar "FILE" <> Opt.help "Verilog input file.")
+
+reduceOpts :: Parser Opts
+reduceOpts =
+ Reduce
+ . fromText
+ . T.pack
+ <$> Opt.strArgument (Opt.metavar "FILE" <> Opt.help "Verilog input file.")
+ <*> textOption
+ ( Opt.short 't'
+ <> Opt.long "top"
+ <> Opt.metavar "TOP"
+ <> Opt.help "Name of top level module."
+ <> Opt.showDefault
+ <> Opt.value "top"
+ )
+ <*> ( Opt.optional
+ . Opt.strOption
+ $ Opt.long "script"
+ <> Opt.metavar "SCRIPT"
+ <> Opt.help
+ "Script that determines if the current file is interesting, which is determined by the script returning 0."
+ )
+ <*> ( Opt.many
+ . Opt.option (optReader parseSynthDesc)
+ $ Opt.short 's'
+ <> Opt.long "synth"
+ <> Opt.metavar "SYNTH"
+ <> Opt.help "Specify synthesiser to use."
+ )
+ <*> ( Opt.switch
+ $ Opt.short 'r'
+ <> Opt.long "rerun"
+ <> Opt.help
+ "Only rerun the current synthesis file with all the synthesisers."
+ )
+
+configOpts :: Parser Opts
+configOpts =
+ ConfigOpt
+ <$> ( Opt.optional
+ . Opt.strOption
+ $ Opt.long "output"
+ <> Opt.short 'o'
+ <> Opt.metavar "FILE"
+ <> Opt.help "Output to a TOML Config file."
+ )
+ <*> ( Opt.optional
+ . Opt.strOption
+ $ Opt.long "config"
+ <> Opt.short 'c'
+ <> Opt.metavar "FILE"
+ <> Opt.help "Config file for the current fuzz run."
+ )
+ <*> ( Opt.switch
+ $ Opt.long "randomise"
+ <> Opt.short 'r'
+ <> Opt.help
+ "Randomise the given default config, or the default config by randomly switchin on and off options."
+ )
+
+argparse :: Parser Opts
+argparse =
+ Opt.hsubparser
+ ( Opt.command
+ "fuzz"
+ (Opt.info
+ fuzzOpts
+ (Opt.progDesc
+ "Run fuzzing on the specified simulators and synthesisers."
+ )
+ )
+ <> Opt.metavar "fuzz"
+ )
+ <|> Opt.hsubparser
+ ( Opt.command
+ "generate"
+ (Opt.info
+ genOpts
+ (Opt.progDesc "Generate a random Verilog program.")
+ )
+ <> Opt.metavar "generate"
+ )
+ <|> Opt.hsubparser
+ ( Opt.command
+ "parse"
+ (Opt.info
+ parseOpts
+ (Opt.progDesc
+ "Parse a verilog file and output a pretty printed version."
+ )
+ )
+ <> Opt.metavar "parse"
+ )
+ <|> Opt.hsubparser
+ ( Opt.command
+ "reduce"
+ (Opt.info
+ reduceOpts
+ (Opt.progDesc
+ "Reduce a Verilog file by rerunning the fuzzer on the file."
+ )
+ )
+ <> Opt.metavar "reduce"
+ )
+ <|> Opt.hsubparser
+ ( Opt.command
+ "config"
+ (Opt.info
+ configOpts
+ (Opt.progDesc
+ "Print the current configuration of the fuzzer."
+ )
+ )
+ <> Opt.metavar "config"
+ )
+
+version :: Parser (a -> a)
+version = Opt.infoOption versionInfo $ mconcat
+ [Opt.long "version", Opt.short 'v', Opt.help "Show version information.", Opt.hidden]
+
+opts :: ParserInfo Opts
+opts = Opt.info
+ (argparse <**> Opt.helper <**> version)
+ ( Opt.fullDesc
+ <> Opt.progDesc "Fuzz different simulators and synthesisers."
+ <> Opt.header
+ "Verismith - A hardware simulator and synthesiser Verilog fuzzer."
+ )