packages feed

verismith 0.4.0.1 → 0.5.0.0

raw patch · 24 files changed

+1757/−704 lines, 24 filesdep +mtlPVP ok

version bump matches the API change (PVP)

Dependencies added: mtl

API changes (from Hackage documentation)

- Verismith: [configFile] :: Opts -> !Maybe FilePath
- Verismith: [doRandomise] :: Opts -> !Bool
- Verismith: [fileName] :: Opts -> {-# UNPACK #-} !FilePath
- Verismith: [forced] :: Opts -> !Bool
- Verismith: [keepAll] :: Opts -> !Bool
- Verismith: [mFileName] :: Opts -> !Maybe FilePath
- Verismith: [num] :: Opts -> {-# UNPACK #-} !Int
- Verismith: [rerun] :: Opts -> Bool
- Verismith: [synthesiserDesc] :: Opts -> ![SynthDescription]
- Verismith: [top] :: Opts -> {-# UNPACK #-} !Text
- Verismith: [writeConfig] :: Opts -> !Maybe FilePath
- Verismith: instance GHC.Show.Show Verismith.OptTool
+ Verismith: [configOptConfigFile] :: Opts -> !Maybe FilePath
+ Verismith: [configOptDoRandomise] :: Opts -> !Bool
+ Verismith: [configOptWriteConfig] :: Opts -> !Maybe FilePath
+ Verismith: [fuzzConfigFile] :: Opts -> !Maybe FilePath
+ Verismith: [fuzzCrossCheck] :: Opts -> !Bool
+ Verismith: [fuzzExistingFileTop] :: Opts -> !Text
+ Verismith: [fuzzExistingFile] :: Opts -> !Maybe FilePath
+ Verismith: [fuzzForced] :: Opts -> !Bool
+ Verismith: [fuzzKeepAll] :: Opts -> !Bool
+ Verismith: [fuzzNoEquiv] :: Opts -> !Bool
+ Verismith: [fuzzNoReduction] :: Opts -> !Bool
+ Verismith: [fuzzNoSim] :: Opts -> !Bool
+ Verismith: [fuzzNum] :: Opts -> {-# UNPACK #-} !Int
+ Verismith: [generateConfigFile] :: Opts -> !Maybe FilePath
+ Verismith: [generateFilename] :: Opts -> !Maybe FilePath
+ Verismith: [parseFilename] :: Opts -> {-# UNPACK #-} !FilePath
+ Verismith: [parseOutput] :: Opts -> !Maybe FilePath
+ Verismith: [parseRemoveConstInConcat] :: Opts -> !Bool
+ Verismith: [parseTop] :: Opts -> {-# UNPACK #-} !Text
+ Verismith: [reduceFilename] :: Opts -> {-# UNPACK #-} !FilePath
+ Verismith: [reduceRerun] :: Opts -> !Bool
+ Verismith: [reduceSynthesiserDesc] :: Opts -> ![SynthDescription]
+ Verismith: [reduceTop] :: Opts -> {-# UNPACK #-} !Text
+ Verismith.Config: fromQuartusLight :: QuartusLight -> SynthDescription
+ Verismith.CounterEg: CounterEg :: ![(Text, Text)] -> ![[(Text, Text)]] -> CounterEg
+ Verismith.CounterEg: [_counterEgInitial] :: CounterEg -> ![(Text, Text)]
+ Verismith.CounterEg: [_counterEgStates] :: CounterEg -> ![[(Text, Text)]]
+ Verismith.CounterEg: data CounterEg
+ Verismith.CounterEg: instance GHC.Base.Monoid Verismith.CounterEg.CounterEg
+ Verismith.CounterEg: instance GHC.Base.Semigroup Verismith.CounterEg.CounterEg
+ Verismith.CounterEg: instance GHC.Classes.Eq Verismith.CounterEg.CounterEg
+ Verismith.CounterEg: instance GHC.Show.Show Verismith.CounterEg.CounterEg
+ Verismith.CounterEg: parseCounterEg :: Text -> Either String CounterEg
+ Verismith.Fuzz: FuzzOpts :: !Maybe FilePath -> !Bool -> !Bool -> {-# UNPACK #-} !Int -> !Bool -> !Bool -> !Bool -> {-# UNPACK #-} !Config -> {-# UNPACK #-} !FilePath -> !Bool -> FuzzOpts
+ Verismith.Fuzz: [_fuzzDataDir] :: FuzzOpts -> {-# UNPACK #-} !FilePath
+ Verismith.Fuzz: [_fuzzOptsConfig] :: FuzzOpts -> {-# UNPACK #-} !Config
+ Verismith.Fuzz: [_fuzzOptsCrossCheck] :: FuzzOpts -> !Bool
+ Verismith.Fuzz: [_fuzzOptsForced] :: FuzzOpts -> !Bool
+ Verismith.Fuzz: [_fuzzOptsIterations] :: FuzzOpts -> {-# UNPACK #-} !Int
+ Verismith.Fuzz: [_fuzzOptsKeepAll] :: FuzzOpts -> !Bool
+ Verismith.Fuzz: [_fuzzOptsNoEquiv] :: FuzzOpts -> !Bool
+ Verismith.Fuzz: [_fuzzOptsNoReduction] :: FuzzOpts -> !Bool
+ Verismith.Fuzz: [_fuzzOptsNoSim] :: FuzzOpts -> !Bool
+ Verismith.Fuzz: [_fuzzOptsOutput] :: FuzzOpts -> !Maybe FilePath
+ Verismith.Fuzz: data FuzzOpts
+ Verismith.Fuzz: instance GHC.Classes.Eq Verismith.Fuzz.FuzzOpts
+ Verismith.Fuzz: instance GHC.Show.Show Verismith.Fuzz.FuzzOpts
+ Verismith.OptParser: ConfigOpt :: !Maybe FilePath -> !Maybe FilePath -> !Bool -> Opts
+ Verismith.OptParser: Fuzz :: {-# UNPACK #-} !Text -> !Maybe FilePath -> !Bool -> !Bool -> {-# UNPACK #-} !Int -> !Bool -> !Bool -> !Bool -> !Maybe FilePath -> !Text -> !Bool -> Opts
+ Verismith.OptParser: Generate :: !Maybe FilePath -> !Maybe FilePath -> Opts
+ Verismith.OptParser: Parse :: {-# UNPACK #-} !FilePath -> {-# UNPACK #-} !Text -> !Maybe FilePath -> !Bool -> Opts
+ Verismith.OptParser: Reduce :: {-# UNPACK #-} !FilePath -> {-# UNPACK #-} !Text -> !Maybe FilePath -> ![SynthDescription] -> !Bool -> Opts
+ Verismith.OptParser: TIcarus :: OptTool
+ Verismith.OptParser: TXST :: OptTool
+ Verismith.OptParser: TYosys :: OptTool
+ Verismith.OptParser: [configOptConfigFile] :: Opts -> !Maybe FilePath
+ Verismith.OptParser: [configOptDoRandomise] :: Opts -> !Bool
+ Verismith.OptParser: [configOptWriteConfig] :: Opts -> !Maybe FilePath
+ Verismith.OptParser: [fuzzConfigFile] :: Opts -> !Maybe FilePath
+ Verismith.OptParser: [fuzzCrossCheck] :: Opts -> !Bool
+ Verismith.OptParser: [fuzzExistingFileTop] :: Opts -> !Text
+ Verismith.OptParser: [fuzzExistingFile] :: Opts -> !Maybe FilePath
+ Verismith.OptParser: [fuzzForced] :: Opts -> !Bool
+ Verismith.OptParser: [fuzzKeepAll] :: Opts -> !Bool
+ Verismith.OptParser: [fuzzNoEquiv] :: Opts -> !Bool
+ Verismith.OptParser: [fuzzNoReduction] :: Opts -> !Bool
+ Verismith.OptParser: [fuzzNoSim] :: Opts -> !Bool
+ Verismith.OptParser: [fuzzNum] :: Opts -> {-# UNPACK #-} !Int
+ Verismith.OptParser: [fuzzOutput] :: Opts -> {-# UNPACK #-} !Text
+ Verismith.OptParser: [generateConfigFile] :: Opts -> !Maybe FilePath
+ Verismith.OptParser: [generateFilename] :: Opts -> !Maybe FilePath
+ Verismith.OptParser: [parseFilename] :: Opts -> {-# UNPACK #-} !FilePath
+ Verismith.OptParser: [parseOutput] :: Opts -> !Maybe FilePath
+ Verismith.OptParser: [parseRemoveConstInConcat] :: Opts -> !Bool
+ Verismith.OptParser: [parseTop] :: Opts -> {-# UNPACK #-} !Text
+ Verismith.OptParser: [reduceFilename] :: Opts -> {-# UNPACK #-} !FilePath
+ Verismith.OptParser: [reduceRerun] :: Opts -> !Bool
+ Verismith.OptParser: [reduceScript] :: Opts -> !Maybe FilePath
+ Verismith.OptParser: [reduceSynthesiserDesc] :: Opts -> ![SynthDescription]
+ Verismith.OptParser: [reduceTop] :: Opts -> {-# UNPACK #-} !Text
+ Verismith.OptParser: data OptTool
+ Verismith.OptParser: data Opts
+ Verismith.OptParser: instance GHC.Show.Show Verismith.OptParser.OptTool
+ Verismith.OptParser: opts :: ParserInfo Opts
+ Verismith.Reduce: reduceSimIc :: (Synthesiser a, MonadSh m) => FilePath -> [ByteString] -> a -> SourceInfo -> m SourceInfo
+ Verismith.Reduce: removeConstInConcat :: Replace SourceInfo
+ Verismith.Reduce: takeReplace :: Monoid a => Replacement a -> a
+ Verismith.Report: QuartusLightSynth :: {-# UNPACK #-} !QuartusLight -> SynthTool
+ Verismith.Report: defaultQuartusLightSynth :: SynthTool
+ Verismith.Result: justFail :: Result a b -> Maybe a
+ Verismith.Result: justPass :: Result a b -> Maybe b
+ Verismith.Tool: QuartusLight :: !Maybe FilePath -> {-# UNPACK #-} !Text -> {-# UNPACK #-} !FilePath -> QuartusLight
+ Verismith.Tool: [quartusLightBin] :: QuartusLight -> !Maybe FilePath
+ Verismith.Tool: [quartusLightDesc] :: QuartusLight -> {-# UNPACK #-} !Text
+ Verismith.Tool: [quartusLightOutput] :: QuartusLight -> {-# UNPACK #-} !FilePath
+ Verismith.Tool: data QuartusLight
+ Verismith.Tool: defaultQuartusLight :: QuartusLight
+ Verismith.Tool.Icarus: runSimIcEC :: Synthesiser b => FilePath -> Icarus -> b -> SourceInfo -> CounterEg -> Maybe ByteString -> ResultSh ByteString
+ Verismith.Tool.QuartusLight: QuartusLight :: !Maybe FilePath -> {-# UNPACK #-} !Text -> {-# UNPACK #-} !FilePath -> QuartusLight
+ Verismith.Tool.QuartusLight: [quartusLightBin] :: QuartusLight -> !Maybe FilePath
+ Verismith.Tool.QuartusLight: [quartusLightDesc] :: QuartusLight -> {-# UNPACK #-} !Text
+ Verismith.Tool.QuartusLight: [quartusLightOutput] :: QuartusLight -> {-# UNPACK #-} !FilePath
+ Verismith.Tool.QuartusLight: data QuartusLight
+ Verismith.Tool.QuartusLight: defaultQuartusLight :: QuartusLight
+ Verismith.Tool.QuartusLight: instance Control.DeepSeq.NFData Verismith.Tool.QuartusLight.QuartusLight
+ Verismith.Tool.QuartusLight: instance GHC.Classes.Eq Verismith.Tool.QuartusLight.QuartusLight
+ Verismith.Tool.QuartusLight: instance GHC.Show.Show Verismith.Tool.QuartusLight.QuartusLight
+ Verismith.Tool.QuartusLight: instance Verismith.Tool.Internal.Synthesiser Verismith.Tool.QuartusLight.QuartusLight
+ Verismith.Tool.QuartusLight: instance Verismith.Tool.Internal.Tool Verismith.Tool.QuartusLight.QuartusLight
+ Verismith.Tool.Template: quartusLightSynthConfig :: Synthesiser a => a -> FilePath -> Text -> FilePath -> Text
+ Verismith.Tool.Template: quartusSynthConfig :: Synthesiser a => a -> FilePath -> Text -> FilePath -> Text
+ Verismith.Tool.Template: yosysSynthConfigStd :: Synthesiser a => a -> FilePath -> Text
+ Verismith.Verilog.AST: instance GHC.Base.Monoid Verismith.Verilog.AST.SourceInfo
+ Verismith.Verilog.AST: instance GHC.Base.Semigroup Verismith.Verilog.AST.SourceInfo
- Verismith: Fuzz :: {-# UNPACK #-} !Text -> !Maybe FilePath -> !Bool -> !Bool -> {-# UNPACK #-} !Int -> Opts
+ Verismith: Fuzz :: {-# UNPACK #-} !Text -> !Maybe FilePath -> !Bool -> !Bool -> {-# UNPACK #-} !Int -> !Bool -> !Bool -> !Bool -> !Maybe FilePath -> !Text -> !Bool -> Opts
- Verismith: Parse :: {-# UNPACK #-} !FilePath -> Opts
+ Verismith: Parse :: {-# UNPACK #-} !FilePath -> {-# UNPACK #-} !Text -> !Maybe FilePath -> !Bool -> Opts
- Verismith: Reduce :: {-# UNPACK #-} !FilePath -> {-# UNPACK #-} !Text -> !Maybe FilePath -> ![SynthDescription] -> Bool -> Opts
+ Verismith: Reduce :: {-# UNPACK #-} !FilePath -> {-# UNPACK #-} !Text -> !Maybe FilePath -> ![SynthDescription] -> !Bool -> Opts
- Verismith.Fuzz: fuzz :: MonadFuzz m => Gen SourceInfo -> Config -> Fuzz m FuzzReport
+ Verismith.Fuzz: fuzz :: MonadFuzz m => Gen SourceInfo -> Fuzz m FuzzReport
- Verismith.Fuzz: fuzzInDir :: MonadFuzz m => Bool -> FilePath -> Gen SourceInfo -> Config -> Fuzz m FuzzReport
+ Verismith.Fuzz: fuzzInDir :: MonadFuzz m => Gen SourceInfo -> Fuzz m FuzzReport
- Verismith.Fuzz: fuzzMultiple :: MonadFuzz m => Int -> Bool -> Maybe FilePath -> Gen SourceInfo -> Config -> Fuzz m [FuzzReport]
+ Verismith.Fuzz: fuzzMultiple :: MonadFuzz m => Gen SourceInfo -> Fuzz m [FuzzReport]
- Verismith.Fuzz: runFuzz :: MonadIO m => Config -> Yosys -> (Config -> Fuzz Sh a) -> m a
+ Verismith.Fuzz: runFuzz :: MonadIO m => FuzzOpts -> Yosys -> Fuzz Sh a -> m a
- Verismith.Reduce: reduce :: MonadSh m => (SourceInfo -> m Bool) -> SourceInfo -> m SourceInfo
+ Verismith.Reduce: reduce :: MonadSh m => FilePath -> (SourceInfo -> m Bool) -> SourceInfo -> m SourceInfo
- Verismith.Reduce: reduceSynth :: (Synthesiser a, Synthesiser b, MonadSh m) => a -> b -> SourceInfo -> m SourceInfo
+ Verismith.Reduce: reduceSynth :: (Synthesiser a, Synthesiser b, MonadSh m) => FilePath -> a -> b -> SourceInfo -> m SourceInfo
- Verismith.Reduce: reduce_ :: MonadSh m => Text -> Replace SourceInfo -> (SourceInfo -> Bool) -> (SourceInfo -> m Bool) -> SourceInfo -> m SourceInfo
+ Verismith.Reduce: reduce_ :: MonadSh m => FilePath -> Text -> Replace SourceInfo -> (SourceInfo -> Bool) -> (SourceInfo -> m Bool) -> SourceInfo -> m SourceInfo
- Verismith.Report: SimResult :: !SynthTool -> !SimTool -> !BResult -> !NominalDiffTime -> SimResult
+ Verismith.Report: SimResult :: !SynthTool -> !SimTool -> ![ByteString] -> !BResult -> !NominalDiffTime -> SimResult
- Verismith.Tool: runEquiv :: (Synthesiser a, Synthesiser b) => a -> b -> SourceInfo -> ResultSh ()
+ Verismith.Tool: runEquiv :: (Synthesiser a, Synthesiser b) => FilePath -> a -> b -> SourceInfo -> ResultSh ()
- Verismith.Tool.Icarus: runSimIc :: Synthesiser b => Icarus -> b -> SourceInfo -> [ByteString] -> ResultSh ByteString
+ Verismith.Tool.Icarus: runSimIc :: Synthesiser b => FilePath -> Icarus -> b -> SourceInfo -> [ByteString] -> Maybe ByteString -> ResultSh ByteString
- Verismith.Tool.Internal: EquivFail :: Failed
+ Verismith.Tool.Internal: EquivFail :: CounterEg -> Failed
- Verismith.Tool.Internal: SimFail :: Failed
+ Verismith.Tool.Internal: SimFail :: ByteString -> Failed
- Verismith.Tool.Template: icarusTestbench :: Synthesiser a => Verilog -> a -> Text
+ Verismith.Tool.Template: icarusTestbench :: Synthesiser a => FilePath -> Verilog -> a -> Text
- Verismith.Tool.Template: sbyConfig :: (Synthesiser a, Synthesiser b) => a -> b -> SourceInfo -> Text
+ Verismith.Tool.Template: sbyConfig :: (Synthesiser a, Synthesiser b) => FilePath -> a -> b -> SourceInfo -> Text
- Verismith.Tool.Yosys: runEquiv :: (Synthesiser a, Synthesiser b) => a -> b -> SourceInfo -> ResultSh ()
+ Verismith.Tool.Yosys: runEquiv :: (Synthesiser a, Synthesiser b) => FilePath -> a -> b -> SourceInfo -> ResultSh ()
- Verismith.Verilog.AST: ConstBinOpF :: !r_aO5G -> !BinaryOperator -> !r_aO5G -> ConstExprF r_aO5G
+ Verismith.Verilog.AST: ConstBinOpF :: !r_aPQP -> !BinaryOperator -> !r_aPQP -> ConstExprF r_aPQP
- Verismith.Verilog.AST: ConstConcatF :: !NonEmpty r_aO5G -> ConstExprF r_aO5G
+ Verismith.Verilog.AST: ConstConcatF :: !NonEmpty r_aPQP -> ConstExprF r_aPQP
- Verismith.Verilog.AST: ConstCondF :: !r_aO5G -> !r_aO5G -> !r_aO5G -> ConstExprF r_aO5G
+ Verismith.Verilog.AST: ConstCondF :: !r_aPQP -> !r_aPQP -> !r_aPQP -> ConstExprF r_aPQP
- Verismith.Verilog.AST: ConstNumF :: {-# UNPACK #-} !BitVecF Integer -> ConstExprF r_aO5G
+ Verismith.Verilog.AST: ConstNumF :: {-# UNPACK #-} !BitVecF Integer -> ConstExprF r_aPQP
- Verismith.Verilog.AST: ConstStrF :: {-# UNPACK #-} !Text -> ConstExprF r_aO5G
+ Verismith.Verilog.AST: ConstStrF :: {-# UNPACK #-} !Text -> ConstExprF r_aPQP
- Verismith.Verilog.AST: ConstUnOpF :: !UnaryOperator -> !r_aO5G -> ConstExprF r_aO5G
+ Verismith.Verilog.AST: ConstUnOpF :: !UnaryOperator -> !r_aPQP -> ConstExprF r_aPQP
- Verismith.Verilog.AST: ParamIdF :: {-# UNPACK #-} !Identifier -> ConstExprF r_aO5G
+ Verismith.Verilog.AST: ParamIdF :: {-# UNPACK #-} !Identifier -> ConstExprF r_aPQP
- Verismith.Verilog.AST: [_constBinOpF] :: ConstExprF r_aO5G -> !BinaryOperator
+ Verismith.Verilog.AST: [_constBinOpF] :: ConstExprF r_aPQP -> !BinaryOperator
- Verismith.Verilog.AST: [_constConcatF] :: ConstExprF r_aO5G -> !NonEmpty r_aO5G
+ Verismith.Verilog.AST: [_constConcatF] :: ConstExprF r_aPQP -> !NonEmpty r_aPQP
- Verismith.Verilog.AST: [_constCondF] :: ConstExprF r_aO5G -> !r_aO5G
+ Verismith.Verilog.AST: [_constCondF] :: ConstExprF r_aPQP -> !r_aPQP
- Verismith.Verilog.AST: [_constFalseF] :: ConstExprF r_aO5G -> !r_aO5G
+ Verismith.Verilog.AST: [_constFalseF] :: ConstExprF r_aPQP -> !r_aPQP
- Verismith.Verilog.AST: [_constLhsF] :: ConstExprF r_aO5G -> !r_aO5G
+ Verismith.Verilog.AST: [_constLhsF] :: ConstExprF r_aPQP -> !r_aPQP
- Verismith.Verilog.AST: [_constNumF] :: ConstExprF r_aO5G -> {-# UNPACK #-} !BitVecF Integer
+ Verismith.Verilog.AST: [_constNumF] :: ConstExprF r_aPQP -> {-# UNPACK #-} !BitVecF Integer
- Verismith.Verilog.AST: [_constParamIdF] :: ConstExprF r_aO5G -> {-# UNPACK #-} !Identifier
+ Verismith.Verilog.AST: [_constParamIdF] :: ConstExprF r_aPQP -> {-# UNPACK #-} !Identifier
- Verismith.Verilog.AST: [_constPrimF] :: ConstExprF r_aO5G -> !r_aO5G
+ Verismith.Verilog.AST: [_constPrimF] :: ConstExprF r_aPQP -> !r_aPQP
- Verismith.Verilog.AST: [_constRhsF] :: ConstExprF r_aO5G -> !r_aO5G
+ Verismith.Verilog.AST: [_constRhsF] :: ConstExprF r_aPQP -> !r_aPQP
- Verismith.Verilog.AST: [_constStrF] :: ConstExprF r_aO5G -> {-# UNPACK #-} !Text
+ Verismith.Verilog.AST: [_constStrF] :: ConstExprF r_aPQP -> {-# UNPACK #-} !Text
- Verismith.Verilog.AST: [_constTrueF] :: ConstExprF r_aO5G -> !r_aO5G
+ Verismith.Verilog.AST: [_constTrueF] :: ConstExprF r_aPQP -> !r_aPQP
- Verismith.Verilog.AST: [_constUnOpF] :: ConstExprF r_aO5G -> !UnaryOperator
+ Verismith.Verilog.AST: [_constUnOpF] :: ConstExprF r_aPQP -> !UnaryOperator
- Verismith.Verilog.AST: data ConstExprF r_aO5G
+ Verismith.Verilog.AST: data ConstExprF r_aPQP

Files

README.md view
@@ -29,7 +29,7 @@  ## Reported bugs -9 bugs have been reported and confirmed to be bugs by the vendors, out of which 4 have been fixed.+9 bugs have been reported and confirmed to be bugs by the vendors, out of which 4 have been fixed. 1 bug has also been found in the Icarus Verilog simulator as a side effect of using it to verify equivalence check results.  ### Yosys @@ -44,11 +44,17 @@  | Type          | Issue                                                                                                                               | Confirmed | Fixed | |---------------|-------------------------------------------------------------------------------------------------------------------------------------|-----------|-------|-| Crash         | [Forum 981787](https://forums.xilinx.com/t5/Synthesis/Vivado-2019-1-Verilog-If-statement-nesting-crash/td-p/981787)                 | ✓         | 𐄂     |-| Crash         | [Forum 981136](https://forums.xilinx.com/t5/Synthesis/Vivado-2018-3-synthesis-crash/td-p/981136)                                    | ✓         | 𐄂     |-| Mis-synthesis | [Forum 981789](https://forums.xilinx.com/t5/Synthesis/Vivado-2019-1-Unsigned-bit-extension-in-if-statement/td-p/981789)             | ✓         | 𐄂     |-| Mis-synthesis | [Forum 982518](https://forums.xilinx.com/t5/Synthesis/Vivado-2019-1-Signed-with-shift-in-condition-synthesis-mistmatch/td-p/982518) | ✓         | 𐄂     |-| Mis-synthesis | [Forum 982419](https://forums.xilinx.com/t5/Synthesis/Vivado-2019-1-Bit-selection-synthesis-mismatch/td-p/982419)                   | ✓         | 𐄂     |+| Crash         | [Forum 981787](https://forums.xilinx.com/t5/Synthesis/Vivado-2019-1-Verilog-If-statement-nesting-crash/td-p/981787)                 | ✓         | ✗     |+| Crash         | [Forum 981136](https://forums.xilinx.com/t5/Synthesis/Vivado-2018-3-synthesis-crash/td-p/981136)                                    | ✓         | ✗     |+| Mis-synthesis | [Forum 981789](https://forums.xilinx.com/t5/Synthesis/Vivado-2019-1-Unsigned-bit-extension-in-if-statement/td-p/981789)             | ✓         | ✗     |+| Mis-synthesis | [Forum 982518](https://forums.xilinx.com/t5/Synthesis/Vivado-2019-1-Signed-with-shift-in-condition-synthesis-mistmatch/td-p/982518) | ✓         | ✗     |+| Mis-synthesis | [Forum 982419](https://forums.xilinx.com/t5/Synthesis/Vivado-2019-1-Bit-selection-synthesis-mismatch/td-p/982419)                   | ✓         | ✗     |++### Icarus Verilog++| Type           | Issue                                                           | Confirmed | Fixed |+|----------------|-----------------------------------------------------------------|-----------|-------|+| Mis-simulation | [Issue 283](https://github.com/steveicarus/iverilog/issues/283) | ✓         | ✓     |  ## Install the Fuzzer 
data/cells_cyclone_v.v view
@@ -2,6 +2,46 @@  // ========================================================================================== +module dffeas (d, clk, ena, clrn, prn, aload, asdata, sclr, sload, devclrn, devpor, q );+   // GLOBAL PARAMETER DECLARATION+   parameter power_up = "DONT_CARE";+   parameter is_wysiwyg = "false";+   parameter dont_touch = "false";+++   parameter x_on_violation = "on";+   parameter lpm_type = "dffeas";++   input d;+   input clk;+   input ena;+   input clrn;+   input prn;+   input aload; +   input asdata;  +   input sclr; +   input sload; +   input devclrn; +   input devpor; ++   output reg q = 0;++   always @(posedge clk) begin+      if (ena == 1'b1) begin+         if (sclr == 1'b1)+           q <= 0;+         else if (aload == 1'b1)+           q <= asdata;+         else if (sload == 1'b1)+           q <= asdata;+         else+           q <= d;+      end+   end++endmodule++ module cyclonev_lcell_comb ( 	                        dataa, datab, datac, datad, datae, dataf, datag, cin, sharein, 	                        combout, sumout, cout, shareout@@ -155,6 +195,32 @@  endmodule +module cyclonev_clkena    (+                           inclk,+                           ena,+                           enaout,+                           outclk);++   // leda G_521_3_B off+   parameter    clock_type    =    "auto";+   parameter    ena_register_mode    =    "always enabled";+   parameter    lpm_type    =    "cyclonev_clkena";+   parameter    ena_register_power_up    =    "high";+   parameter    disable_mode    =    "low";+   parameter    test_syn    =    "high";+   // leda G_521_3_B on++   input    inclk;+   input    ena;+   output   enaout;+   output   outclk;++   assign outclk = ena ? inclk : 1'b0;+   assign enaout = ena;++endmodule //cyclonev_clkena++ // ==========================================================================================  module cyclonev_io_ibuf (i, ibar, dynamicterminationcontrol, o);@@ -196,42 +262,201 @@  endmodule -module dffeas (d, clk, ena, clrn, prn, aload, asdata, sclr, sload, devclrn, devpor, q );-   // GLOBAL PARAMETER DECLARATION-   parameter power_up = "DONT_CARE";-   parameter is_wysiwyg = "false";-   parameter dont_touch = "false";+module cyclone10lp_lcell_comb (+	                        dataa, datab, datac, datad, datae, dataf, datag, cin, sharein,+	                        combout, sumout, cout, shareout+                            ); +   input dataa, datab, datac, datad, datae, dataf, datag, cin, sharein;+   output reg combout = 0, sumout = 0, cout = 0, shareout = 0; -   parameter x_on_violation = "on";-   parameter lpm_type = "dffeas";+   parameter lut_mask = 64'hFFFFFFFFFFFFFFFF;+   parameter shared_arith = "off";+   parameter extended_lut = "off";+   parameter dont_touch = "off";+   parameter lpm_type = "cyclone10lp_lcell_comb"; -   input d;-   input clk;-   input ena;-   input clrn;-   input prn;-   input aload; -   input asdata;  -   input sclr; -   input sload; -   input devclrn; -   input devpor; +   localparam ishared_arith = shared_arith == "on";+   localparam iextended_lut = extended_lut == "on"; -   output reg q = 0;+   localparam [15:0] f0_mask = lut_mask[15:0];+   localparam [15:0] f1_mask = lut_mask[31:16];+   localparam [15:0] f2_mask = lut_mask[47:32];+   localparam [15:0] f3_mask = lut_mask[63:48]; -   always @(posedge clk or posedge aload) begin-      if (aload == 1'b1)-        q <= asdata;-      else if (sload == 1'b1)-        q <= asdata;-      else-        q <= d;-   end+   reg        f0_out, f1_out, f2_out, f3_out;+   reg        g0_out, g1_out;+   reg        f2_input3, f2_f;+   reg        adder_input2; +   // 4-input LUT function+   function lut4;+      input [15:0] mask;+      input        dataa;+      input        datab;+      input        datac;+      input        datad;+      begin+         lut4 = datad ? ( datac ? ( datab ? ( dataa ? mask[15] : mask[14])+                                    : ( dataa ? mask[13] : mask[12]))+                          : ( datab ? ( dataa ? mask[11] : mask[10])+                              : ( dataa ? mask[ 9] : mask[ 8])))+           : ( datac ? ( datab ? ( dataa ? mask[ 7] : mask[ 6])+                         : ( dataa ? mask[ 5] : mask[ 4]))+               : ( datab ? ( dataa ? mask[ 3] : mask[ 2])+                   : ( dataa ? mask[ 1] : mask[ 0])));+      end+   endfunction++   // 5-input LUT function+   function lut5;+      input [31:0] mask;+      input        dataa;+      input        datab;+      input        datac;+      input        datad;+      input        datae;+      reg          e0_lut;+      reg          e1_lut;+      reg [15:0]   e0_mask;+      reg [31:16]  e1_mask;+      begin+         e0_mask = mask[15:0];+         e1_mask = mask[31:16];+         e0_lut = lut4(e0_mask, dataa, datab, datac, datad);+         e1_lut = lut4(e1_mask, dataa, datab, datac, datad);+      end+   endfunction++   // 6-input LUT function+   function lut6;+      input [63:0] mask;+      input        dataa;+      input        datab;+      input        datac;+      input        datad;+      input        datae;+      input        dataf;+      reg          f0_lut;+      reg          f1_lut;+      reg [31:0]   f0_mask;+      reg [63:32]  f1_mask ;+      begin+         f0_mask = mask[31:0];+         f1_mask = mask[63:32];+         lut6 = mask[{dataf, datae, datad, datac, datab, dataa}];+      end+   endfunction++   always @(datag or dataf or datae or datad or datac or+            datab or dataa or cin or sharein)+     begin+        // check for extended LUT mode+        if (iextended_lut == 1)+          f2_input3 = datag;+        else+          f2_input3 = datac;++        f0_out = lut4(f0_mask, dataa, datab, datac, datad);+        f1_out = lut4(f1_mask, dataa, datab, f2_input3, datad);+        f2_out = lut4(f2_mask, dataa, datab, datac, datad);+        f3_out = lut4(f3_mask, dataa, datab, f2_input3, datad);++        // combout is the 6-input LUT+        if (iextended_lut == 1)+          begin+             if (datae == 1'b0)+               begin+                  g0_out = f0_out;+                  g1_out = f2_out;+               end+             else if (datae == 1'b1)+               begin+                  g0_out = f1_out;+                  g1_out = f3_out;+               end+             else+               begin+                  if (f0_out == f1_out)+                    g0_out = f0_out;+                  else+                    g0_out = 1'bX;++                  if (f2_out == f3_out)+                    g1_out = f2_out;+                  else+                    g1_out = 1'bX;+               end++             if (dataf == 1'b0)+               combout = g0_out;+             else if ((dataf == 1'b1) || (g0_out == g1_out))+               combout = g1_out;+             else+               combout = 1'bX;+          end+        else+          combout = lut6(lut_mask, dataa, datab, datac, datad, datae, dataf);++        // check for shareed arithmetic mode+        if (ishared_arith == 1)+          adder_input2 = sharein;+        else+          begin+             f2_f = lut4(f2_mask, dataa, datab, datac, dataf);+             adder_input2 = !f2_f;+          end++        // sumout & cout+        sumout = cin ^ f0_out ^ adder_input2;+        cout = (cin & f0_out) | (cin & adder_input2) | (f0_out & adder_input2);+        shareout = f2_out;+     end+ endmodule -module cyclonev_clkena    (+// ==========================================================================================++module cyclone10lp_io_ibuf (i, ibar, dynamicterminationcontrol, o);++   parameter differential_mode = 0;+   parameter bus_hold = 0;+   parameter simulate_z_as = 0;+   parameter lpm_type = 0;++   input i;+   input ibar;+   input dynamicterminationcontrol;+   output o;++   assign o = i;++endmodule++// ==========================================================================================++module cyclone10lp_io_obuf (i, oe, dynamicterminationcontrol, seriesterminationcontrol, parallelterminationcontrol, devoe, o, obar);++   parameter open_drain_output = 0;+   parameter bus_hold = 0;+   parameter shift_series_termination_control = 0;+   parameter sim_dynamic_termination_control_is_connected = 0;+   parameter lpm_type = 0;++   input i;+   input oe;+   input devoe;+   input dynamicterminationcontrol;+   input [15:0] seriesterminationcontrol;+   input [15:0] parallelterminationcontrol;+   output       o;+   output       obar;++   assign o = i, obar = ~i;++endmodule++module cyclone10lp_clkena    (                            inclk,                            ena,                            enaout,@@ -240,7 +465,7 @@    // leda G_521_3_B off    parameter    clock_type    =    "auto";    parameter    ena_register_mode    =    "always enabled";-   parameter    lpm_type    =    "cyclonev_clkena";+   parameter    lpm_type    =    "cyclone10lp_clkena";    parameter    ena_register_power_up    =    "high";    parameter    disable_mode    =    "low";    parameter    test_syn    =    "high";@@ -254,4 +479,223 @@    assign outclk = ena ? inclk : 1'b0;    assign enaout = ena; -endmodule //cyclonev_clkena+endmodule //cyclone10lp_clkena++module cyclone10gx_lcell_comb (+	                        dataa, datab, datac, datad, datae, dataf, datag, cin, sharein,+	                        combout, sumout, cout, shareout+                            );++   input dataa, datab, datac, datad, datae, dataf, datag, cin, sharein;+   output reg combout = 0, sumout = 0, cout = 0, shareout = 0;++   parameter lut_mask = 64'hFFFFFFFFFFFFFFFF;+   parameter shared_arith = "off";+   parameter extended_lut = "off";+   parameter dont_touch = "off";+   parameter lpm_type = "cyclone10gx_lcell_comb";++   localparam ishared_arith = shared_arith == "on";+   localparam iextended_lut = extended_lut == "on";++   localparam [15:0] f0_mask = lut_mask[15:0];+   localparam [15:0] f1_mask = lut_mask[31:16];+   localparam [15:0] f2_mask = lut_mask[47:32];+   localparam [15:0] f3_mask = lut_mask[63:48];++   reg        f0_out, f1_out, f2_out, f3_out;+   reg        g0_out, g1_out;+   reg        f2_input3, f2_f;+   reg        adder_input2;++   // 4-input LUT function+   function lut4;+      input [15:0] mask;+      input        dataa;+      input        datab;+      input        datac;+      input        datad;+      begin+         lut4 = datad ? ( datac ? ( datab ? ( dataa ? mask[15] : mask[14])+                                    : ( dataa ? mask[13] : mask[12]))+                          : ( datab ? ( dataa ? mask[11] : mask[10])+                              : ( dataa ? mask[ 9] : mask[ 8])))+           : ( datac ? ( datab ? ( dataa ? mask[ 7] : mask[ 6])+                         : ( dataa ? mask[ 5] : mask[ 4]))+               : ( datab ? ( dataa ? mask[ 3] : mask[ 2])+                   : ( dataa ? mask[ 1] : mask[ 0])));+      end+   endfunction++   // 5-input LUT function+   function lut5;+      input [31:0] mask;+      input        dataa;+      input        datab;+      input        datac;+      input        datad;+      input        datae;+      reg          e0_lut;+      reg          e1_lut;+      reg [15:0]   e0_mask;+      reg [31:16]  e1_mask;+      begin+         e0_mask = mask[15:0];+         e1_mask = mask[31:16];+         e0_lut = lut4(e0_mask, dataa, datab, datac, datad);+         e1_lut = lut4(e1_mask, dataa, datab, datac, datad);+      end+   endfunction++   // 6-input LUT function+   function lut6;+      input [63:0] mask;+      input        dataa;+      input        datab;+      input        datac;+      input        datad;+      input        datae;+      input        dataf;+      reg          f0_lut;+      reg          f1_lut;+      reg [31:0]   f0_mask;+      reg [63:32]  f1_mask ;+      begin+         f0_mask = mask[31:0];+         f1_mask = mask[63:32];+         lut6 = mask[{dataf, datae, datad, datac, datab, dataa}];+      end+   endfunction++   always @(datag or dataf or datae or datad or datac or+            datab or dataa or cin or sharein)+     begin+        // check for extended LUT mode+        if (iextended_lut == 1)+          f2_input3 = datag;+        else+          f2_input3 = datac;++        f0_out = lut4(f0_mask, dataa, datab, datac, datad);+        f1_out = lut4(f1_mask, dataa, datab, f2_input3, datad);+        f2_out = lut4(f2_mask, dataa, datab, datac, datad);+        f3_out = lut4(f3_mask, dataa, datab, f2_input3, datad);++        // combout is the 6-input LUT+        if (iextended_lut == 1)+          begin+             if (datae == 1'b0)+               begin+                  g0_out = f0_out;+                  g1_out = f2_out;+               end+             else if (datae == 1'b1)+               begin+                  g0_out = f1_out;+                  g1_out = f3_out;+               end+             else+               begin+                  if (f0_out == f1_out)+                    g0_out = f0_out;+                  else+                    g0_out = 1'bX;++                  if (f2_out == f3_out)+                    g1_out = f2_out;+                  else+                    g1_out = 1'bX;+               end++             if (dataf == 1'b0)+               combout = g0_out;+             else if ((dataf == 1'b1) || (g0_out == g1_out))+               combout = g1_out;+             else+               combout = 1'bX;+          end+        else+          combout = lut6(lut_mask, dataa, datab, datac, datad, datae, dataf);++        // check for shareed arithmetic mode+        if (ishared_arith == 1)+          adder_input2 = sharein;+        else+          begin+             f2_f = lut4(f2_mask, dataa, datab, datac, dataf);+             adder_input2 = !f2_f;+          end++        // sumout & cout+        sumout = cin ^ f0_out ^ adder_input2;+        cout = (cin & f0_out) | (cin & adder_input2) | (f0_out & adder_input2);+        shareout = f2_out;+     end++endmodule++// ==========================================================================================++module cyclone10gx_io_ibuf (i, ibar, dynamicterminationcontrol, o);++   parameter differential_mode = 0;+   parameter bus_hold = 0;+   parameter simulate_z_as = 0;+   parameter lpm_type = 0;++   input i;+   input ibar;+   input dynamicterminationcontrol;+   output o;++   assign o = i;++endmodule++// ==========================================================================================++module cyclone10gx_io_obuf (i, oe, dynamicterminationcontrol, seriesterminationcontrol, parallelterminationcontrol, devoe, o, obar);++   parameter open_drain_output = 0;+   parameter bus_hold = 0;+   parameter shift_series_termination_control = 0;+   parameter sim_dynamic_termination_control_is_connected = 0;+   parameter lpm_type = 0;++   input i;+   input oe;+   input devoe;+   input dynamicterminationcontrol;+   input [15:0] seriesterminationcontrol;+   input [15:0] parallelterminationcontrol;+   output       o;+   output       obar;++   assign o = i, obar = ~i;++endmodule++module cyclone10gx_clkena    (+                           inclk,+                           ena,+                           enaout,+                           outclk);++   // leda G_521_3_B off+   parameter    clock_type    =    "auto";+   parameter    ena_register_mode    =    "always enabled";+   parameter    lpm_type    =    "cyclone10gx_clkena";+   parameter    ena_register_power_up    =    "high";+   parameter    disable_mode    =    "low";+   parameter    test_syn    =    "high";+   // leda G_521_3_B on++   input    inclk;+   input    ena;+   output   enaout;+   output   outclk;++   assign outclk = ena ? inclk : 1'b0;+   assign enaout = ena;++endmodule //cyclone10gx_clkena
+ scripts/reducer.sh view
@@ -0,0 +1,65 @@+#!/usr/bin/env bash++for i in $(seq 0 100); do+  echo "INFO: Run ${i}"+  dir="$(dirname "$(find /mnt/data/projects/verismith/runs/yosys_0.8/run_5 -name 'reduce*' -type f | shuf | head -1)")"+  dest="$(pwd)/run_${i}"+  interesting="${dest}/creduce/interesting.sh"+  vfile="${dest}/creduce/rtl.v"+  orig="$(pwd)"++  echo "INFO: Picked ${dir}"++  cp -r $dir $dest+  mkdir -p "${dest}/creduce"++  if [[ -f "${dest}/reduce_yosys.v" ]]; then+    echo "INFO: Detected crash"+    cat >$interesting <<EOF+/mnt/data/tools/yosys/constant/bin/yosys -q -p "read_verilog rtl.v; synth; write_verilog -noattr syn_yosys.v" >yosys.log 2>&1+grep "vector::_M_range_check:" yosys.log++exit \$?+EOF+  elif [[ -f "${dest}/reduce_identity_yosys.v" ]]; then+    echo "INFO: Detected mis-synthesis"+    cat >$interesting <<EOF+#!/usr/bin/env bash++grep -v -E '^[[:space:]]*reg[[:space:]].*=.*0.*;' rtl.v | grep '^[[:space:]]*reg[[:space:]].*[^,+-]*;'+if [[ \$? -eq 0 ]]; then exit 1; fi++cp "${dest}/equiv_identity_yosys/top.v" .+cp "${dest}/equiv_identity_yosys/proof.sby" .++sed -i 's:/home/vagrant/.cabal/store/ghc-8.6.5/verismith-0.4.0.1-[a-f0-9]*/share:/home/ymherklotz/projects/verismith:' proof.sby++/mnt/data/tools/yosys/constant/bin/yosys -q -p "read_verilog rtl.v; synth; write_verilog -noattr syn_yosys.v" >yosys1.log 2>&1 || exit 1++grep -v "Warning: Resizing cell port" yosys1.log >yosys.log++grep "Warning" yosys.log+greturn=\$?+if [[ \$greturn -eq 0 ]]; then exit 1; fi++sed -i -E 's/((module[0-9]+)|top)/\1_2/' syn_yosys.v+sed -E 's/((module[0-9]+)|top)/\1_1/' rtl.v >syn_identity.v++sby -f proof.sby >symbiyosys.log 2>&1++grep "FAIL" symbiyosys.log >/dev/null 2>&1 || exit 1++exit 0+EOF+  else+    echo "WARNING: No original reduction found"+    continue+  fi++  cp "${dest}/identity/syn_identity.v" "$vfile"+  chmod +x "$interesting"+  cd "${dest}/creduce"+  time creduce --abs-timing --no-c ./interesting.sh rtl.v >creduce.log+  cd "${orig}"+  echo "INFO: Done"+done
src/Verismith.hs view
@@ -54,6 +54,7 @@ import qualified Hedgehog.Gen             as Hog import           Hedgehog.Internal.Seed   (Seed) import           Options.Applicative+import           Paths_verismith          (getDataDir) import           Prelude                  hiding (FilePath) import           Shelly                   hiding (command) import           Shelly.Lifted            (liftSh)@@ -62,6 +63,7 @@ import           Verismith.Config import           Verismith.Fuzz import           Verismith.Generate+import           Verismith.OptParser import           Verismith.Reduce import           Verismith.Report import           Verismith.Result@@ -70,36 +72,21 @@ import           Verismith.Verilog import           Verismith.Verilog.Parser (parseSourceInfoFile) -data OptTool = TYosys-          | TXST-          | TIcarus+-- | Generate a specific number of random bytestrings of size 256.+randomByteString :: C.CtrDRBG -> Int -> [ByteString] -> [ByteString]+randomByteString gen n bytes+    | n == 0    = ranBytes : bytes+    | otherwise = randomByteString newGen (n - 1) $ ranBytes : bytes+    where Right (ranBytes, newGen) = C.genBytes 32 gen -instance Show OptTool where-  show TYosys  = "yosys"-  show TXST    = "xst"-  show TIcarus = "icarus"+-- | generates the specific number of bytestring with a random seed.+generateByteString :: Int -> IO [ByteString]+generateByteString n = do+    gen <- C.newGenIO :: IO C.CtrDRBG+    return $ randomByteString gen n [] -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-                      }+toFP :: String -> FilePath+toFP = fromText . T.pack  myForkIO :: IO () -> IO (MVar ()) myForkIO io = do@@ -107,221 +94,15 @@     _    <- 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 +getGenerator :: Config -> Text -> Maybe FilePath -> IO (Gen SourceInfo)+getGenerator config top s =+    maybe (return $ proceduralSrc top config) (fmap return . parseSourceInfoFile top)+    $ toTextIgnore <$> s+ -- | Randomly remove an option by setting it to 0. randDelete :: Int -> IO Int randDelete i = do@@ -363,12 +144,15 @@     ce = config ^. configProbability . probExpr  handleOpts :: Opts -> IO ()-handleOpts (Fuzz o configF _ k n) = do+handleOpts (Fuzz o configF f k n nosim noequiv noreduction file top cc) = do     config <- getConfig configF+    gen <- getGenerator config top file+    datadir <- getDataDir     _      <- runFuzz-        config+        (FuzzOpts (Just $ fromText o)+         f k n nosim noequiv noreduction config (toFP datadir) cc)         defaultYosys-        (fuzzMultiple n k (Just $ fromText o) (proceduralSrc "top" config))+        (fuzzMultiple gen)     return () handleOpts (Generate f c) = do     config <- getConfig c@@ -377,21 +161,29 @@         $   T.unpack         .   toTextIgnore         <$> f-handleOpts (Parse f) = do+handleOpts (Parse f t o rc) = do     verilogSrc <- T.readFile file     case parseVerilog (T.pack file) verilogSrc of         Left  l -> print l-        Right v -> print $ GenVerilog v-    where file = T.unpack . toTextIgnore $ f+        Right v ->+            case (o, GenVerilog+                     . mapply rc (takeReplace . removeConstInConcat)+                     $ SourceInfo t v) of+            (Nothing, a) -> print a+            (Just o', a) -> writeFile (T.unpack $ toTextIgnore o') $ show a+  where+    file = T.unpack . toTextIgnore $ f+    mapply i f = if i then f else id handleOpts (Reduce f t _ ls' False) = do     src <- parseSourceInfoFile t (toTextIgnore f)+    datadir <- getDataDir     case descriptionToSynth <$> ls' of         a : b : _ -> do             putStrLn "Reduce with equivalence check"             shelly $ do                 make dir                 pop dir $ do-                    src' <- reduceSynth a b src+                    src' <- reduceSynth (toFP datadir) a b src                     writefile (fromText ".." </> dir <.> "v") $ genSource src'         a : _ -> do             putStrLn "Reduce with synthesis failure"@@ -406,6 +198,7 @@     where dir = fromText "reduce" handleOpts (Reduce f t _ ls' True) = do     src <- parseSourceInfoFile t (toTextIgnore f)+    datadir <- getDataDir     case descriptionToSynth <$> ls' of         a : b : _ -> do             putStrLn "Starting equivalence check"@@ -414,12 +207,12 @@                 pop dir $ do                     runSynth a src                     runSynth b src-                    runEquiv a b src+                    runEquiv (toFP datadir) a b src             case res of-                Pass _            -> putStrLn "Equivalence check passed"-                Fail EquivFail    -> putStrLn "Equivalence check failed"-                Fail TimeoutError -> putStrLn "Equivalence check timed out"-                Fail _            -> putStrLn "Equivalence check error"+                Pass _             -> putStrLn "Equivalence check passed"+                Fail (EquivFail _) -> putStrLn "Equivalence check failed"+                Fail TimeoutError  -> putStrLn "Equivalence check timed out"+                Fail _             -> putStrLn "Equivalence check error"             return ()         as -> do             putStrLn "Synthesis check"@@ -438,19 +231,6 @@     optsparsed <- execParser opts     handleOpts optsparsed --- | Generate a specific number of random bytestrings of size 256.-randomByteString :: C.CtrDRBG -> Int -> [ByteString] -> [ByteString]-randomByteString gen n bytes-    | n == 0    = ranBytes : bytes-    | otherwise = randomByteString newGen (n - 1) $ ranBytes : bytes-    where Right (ranBytes, newGen) = C.genBytes 32 gen---- | generates the specific number of bytestring with a random seed.-generateByteString :: Int -> IO [ByteString]-generateByteString n = do-    gen <- C.newGenIO :: IO C.CtrDRBG-    return $ randomByteString gen n []- makeSrcInfo :: ModDecl -> SourceInfo makeSrcInfo m = SourceInfo (getIdentifier $ m ^. modId) (Verilog [m]) @@ -504,10 +284,11 @@ checkEquivalence src dir = shellyFailDir $ do     mkdir_p (fromText dir)     curr <- toTextIgnore <$> pwd+    datadir <- liftIO getDataDir     setenv "VERISMITH_ROOT" curr     cd (fromText dir)     catch_sh-        ((runResultT $ runEquiv defaultYosys defaultVivado src) >> return True)+        ((runResultT $ runEquiv (toFP datadir) defaultYosys defaultVivado src) >> return True)         ((\_ -> return False) :: RunFailed -> Sh Bool)  -- | Run a fuzz run and check if all of the simulators passed by checking if the@@ -524,6 +305,7 @@     (_, m) <- shelly $ sampleSeed seed gm     let srcInfo = SourceInfo "top" m     rand <- generateByteString 20+    datadir <- getDataDir     shellyFailDir $ do         mkdir_p (fromText d </> fromText n)         curr <- toTextIgnore <$> pwd@@ -532,7 +314,7 @@         _ <-             catch_sh                     (  runResultT-                    $  runEquiv defaultYosys defaultVivado srcInfo+                    $  runEquiv (toFP datadir) defaultYosys defaultVivado srcInfo                     >> liftSh (logger "Test OK")                     )                 $ onFailure n@@ -550,4 +332,4 @@  runReduce :: SourceInfo -> IO SourceInfo runReduce s =-    shelly $ reduce (\s' -> not <$> liftIO (checkEquivalence s' "reduce")) s+    shelly $ reduce "reduce.v" (\s' -> not <$> liftIO (checkEquivalence s' "reduce")) s
src/Verismith/Config.hs view
@@ -36,6 +36,7 @@     , fromYosys     , fromVivado     , fromQuartus+    , fromQuartusLight     , configProbability     , configProperty     , configSimulators@@ -79,20 +80,21 @@     ) where -import           Control.Applicative    (Alternative)-import           Control.Lens           hiding ((.=))-import           Data.List.NonEmpty     (NonEmpty (..))-import           Data.Maybe             (fromMaybe)-import           Data.Text              (Text, pack)-import qualified Data.Text.IO           as T-import           Data.Version           (showVersion)+import           Control.Applicative         (Alternative)+import           Control.Lens                hiding ((.=))+import           Data.List.NonEmpty          (NonEmpty (..))+import           Data.Maybe                  (fromMaybe)+import           Data.Text                   (Text, pack)+import qualified Data.Text.IO                as T+import           Data.Version                (showVersion) import           Development.GitRev-import           Hedgehog.Internal.Seed (Seed)-import           Paths_verismith        (version)-import           Shelly                 (toTextIgnore)-import           Toml                   (TomlCodec, (.=))+import           Hedgehog.Internal.Seed      (Seed)+import           Paths_verismith             (version)+import           Shelly                      (toTextIgnore)+import           Toml                        (TomlCodec, (.=)) import qualified Toml import           Verismith.Tool.Quartus+import           Verismith.Tool.QuartusLight import           Verismith.Tool.Vivado import           Verismith.Tool.XST import           Verismith.Tool.Yosys@@ -283,6 +285,12 @@  fromQuartus :: Quartus -> SynthDescription fromQuartus (Quartus a b c) = SynthDescription "quartus"+                                               (toTextIgnore <$> a)+                                               (Just b)+                                               (Just $ toTextIgnore c)++fromQuartusLight :: QuartusLight -> SynthDescription+fromQuartusLight (QuartusLight a b c) = SynthDescription "quartuslight"                                                (toTextIgnore <$> a)                                                (Just b)                                                (Just $ toTextIgnore c)
+ src/Verismith/CounterEg.hs view
@@ -0,0 +1,112 @@+{-|+Module      : Verismith.CounterEg+Description : Counter example parser to load the counter example+Copyright   : (c) 2019, Yann Herklotz+License     : BSD-3+Maintainer  : yann [at] yannherklotz [dot] com+Stability   : experimental+Portability : POSIX+-}++module Verismith.CounterEg+    ( CounterEg(..)+    , parseCounterEg+    )+where++import           Control.Applicative  ((<|>))+import           Data.Bifunctor       (bimap)+import           Data.Binary          (encode)+import           Data.Bits            (shiftL, (.|.))+import           Data.ByteString      (ByteString)+import qualified Data.ByteString      as B+import qualified Data.ByteString.Lazy as L+import           Data.Char            (digitToInt)+import           Data.Functor         (($>))+import           Data.Maybe           (listToMaybe)+import           Data.Text            (Text)+import qualified Data.Text            as T+import           Numeric              (readInt)+import qualified Text.Parsec          as P++data CounterEg = CounterEg { _counterEgInitial :: ![(Text, Text)]+                           , _counterEgStates  :: ![[(Text, Text)]]+                           }+               deriving (Eq, Show)++instance Semigroup CounterEg where+    CounterEg a b <> CounterEg c d = CounterEg (a <> c) (b <> d)++instance Monoid CounterEg where+    mempty = CounterEg mempty mempty++type Parser = P.Parsec String ()++-- fromBytes :: ByteString -> Int+-- fromBytes = B.foldl' f 0 where f a b = a `shiftL` 8 .|. fromIntegral b++-- convert :: String -> ByteString+-- convert =+--     L.toStrict+--         . (encode :: Integer -> L.ByteString)+--         . maybe 0 fst+--         . listToMaybe+--         . readInt 2 (`elem` ("01" :: String)) digitToInt++-- convertBinary :: String -> Int+-- convertBinary = fromBytes . convert++lexme :: Parser a -> Parser a+lexme f = do { a <- f; _ <- P.spaces; return a }++nameChar :: Parser Char+nameChar = P.alphaNum+           <|> P.oneOf "$.:_"++parens :: Parser a -> Parser a+parens = lexme . P.between (P.char '(') (P.char ')')++brackets :: Parser a -> Parser a+brackets = lexme . P.between (P.char '[') (P.char ']')++trueOrFalse :: Parser String+trueOrFalse = lexme $ (P.string "true" $> "1") <|> (P.string "false" $> "0")++assumeBody :: Parser (String, String)+assumeBody = lexme $ do+    name <- P.char '=' *> P.spaces *> brackets (P.many1 nameChar)+    num <- P.spaces *> ((P.string "#b" *> P.many1 P.digit) <|> trueOrFalse)+    return (name, num)++parseAssume :: Parser (String, String)+parseAssume = lexme $ P.string "assume" *> P.spaces *> parens assumeBody++parseInitial :: Parser [(String, String)]+parseInitial = lexme $ do+    _ <- lexme $ P.string "initial"+    P.many parseAssume++parseState :: Parser (String, [(String, String)])+parseState = lexme $ do+    n <- lexme $ P.string "state" *> P.spaces *> P.many1 P.digit+    assumes <- P.many parseAssume+    return (n, assumes)++parseCE :: Parser [[(String, String)]]+parseCE = lexme $ do+    i <- parseInitial+    other <- fmap snd <$> P.many parseState+    return (i : other)++cEtoCounterEg :: [[(String, String)]] -> CounterEg+cEtoCounterEg [] = mempty+cEtoCounterEg (i : is) = CounterEg (bimap T.pack T.pack <$> i)+                         (fmap (bimap T.pack T.pack) <$> is)++parseCounterEg' :: Parser CounterEg+parseCounterEg' = lexme $ do+    _ <- P.spaces+    cEtoCounterEg <$> parseCE++parseCounterEg :: Text -> Either String CounterEg+parseCounterEg = bimap show id . P.parse parseCounterEg' "" . T.unpack
src/Verismith/Fuzz.hs view
@@ -15,7 +15,8 @@ {-# LANGUAGE TemplateHaskell  #-}  module Verismith.Fuzz-    ( Fuzz+    ( Fuzz (..)+    , FuzzOpts (..)     , fuzz     , fuzzInDir     , fuzzMultiple@@ -27,34 +28,33 @@     ) where -import           Control.DeepSeq                  (force)-import           Control.Exception.Lifted         (finally)-import           Control.Lens                     hiding ((<.>))-import           Control.Monad                    (forM, replicateM)+import           Control.DeepSeq             (force)+import           Control.Exception.Lifted    (finally)+import           Control.Lens                hiding ((<.>))+import           Control.Monad               (forM, replicateM) import           Control.Monad.IO.Class-import           Control.Monad.Trans.Class        (lift)-import           Control.Monad.Trans.Control      (MonadBaseControl)-import           Control.Monad.Trans.Maybe        (runMaybeT)-import           Control.Monad.Trans.Reader       hiding (local)-import           Control.Monad.Trans.State.Strict-import qualified Crypto.Random.DRBG               as C-import           Data.ByteString                  (ByteString)-import           Data.List                        (nubBy, sort)-import           Data.Maybe                       (isNothing)-import           Data.Text                        (Text)-import qualified Data.Text                        as T+import           Control.Monad.Reader+import           Control.Monad.State.Strict+import           Control.Monad.Trans.Control (MonadBaseControl)+import qualified Crypto.Random.DRBG          as C+import           Data.ByteString             (ByteString)+import           Data.List                   (nubBy, sort)+import           Data.Maybe                  (catMaybes, fromMaybe, isNothing)+import           Data.Text                   (Text)+import qualified Data.Text                   as T import           Data.Time-import           Data.Tuple                       (swap)-import           Hedgehog                         (Gen)-import qualified Hedgehog.Internal.Gen            as Hog-import           Hedgehog.Internal.Seed           (Seed)-import qualified Hedgehog.Internal.Seed           as Hog-import qualified Hedgehog.Internal.Tree           as Hog-import           Prelude                          hiding (FilePath)-import           Shelly                           hiding (get)-import           Shelly.Lifted                    (MonadSh, liftSh)-import           System.FilePath.Posix            (takeBaseName)+import           Data.Tuple                  (swap)+import           Hedgehog                    (Gen)+import qualified Hedgehog.Internal.Gen       as Hog+import           Hedgehog.Internal.Seed      (Seed)+import qualified Hedgehog.Internal.Seed      as Hog+import qualified Hedgehog.Internal.Tree      as Hog+import           Prelude                     hiding (FilePath)+import           Shelly                      hiding (get)+import           Shelly.Lifted               (MonadSh, liftSh)+import           System.FilePath.Posix       (takeBaseName) import           Verismith.Config+import           Verismith.CounterEg         (CounterEg (..)) import           Verismith.Internal import           Verismith.Reduce import           Verismith.Report@@ -65,12 +65,43 @@ import           Verismith.Verilog.AST import           Verismith.Verilog.CodeGen -data FuzzEnv = FuzzEnv { getSynthesisers :: ![SynthTool]-                       , getSimulators   :: ![SimTool]-                       , yosysInstance   :: {-# UNPACK #-} !Yosys+data FuzzOpts = FuzzOpts { _fuzzOptsOutput      :: !(Maybe FilePath)+                         , _fuzzOptsForced      :: !Bool+                         , _fuzzOptsKeepAll     :: !Bool+                         , _fuzzOptsIterations  :: {-# UNPACK #-} !Int+                         , _fuzzOptsNoSim       :: !Bool+                         , _fuzzOptsNoEquiv     :: !Bool+                         , _fuzzOptsNoReduction :: !Bool+                         , _fuzzOptsConfig      :: {-# UNPACK #-} !Config+                         , _fuzzDataDir         :: {-# UNPACK #-} !FilePath+                         , _fuzzOptsCrossCheck  :: !Bool+                         }+              deriving (Show, Eq)++$(makeLenses ''FuzzOpts)++defaultFuzzOpts :: FuzzOpts+defaultFuzzOpts = FuzzOpts { _fuzzOptsOutput      = Nothing+                           , _fuzzOptsForced      = False+                           , _fuzzOptsKeepAll     = False+                           , _fuzzOptsIterations  = 1+                           , _fuzzOptsNoSim       = False+                           , _fuzzOptsNoEquiv     = False+                           , _fuzzOptsNoReduction = False+                           , _fuzzOptsConfig      = defaultConfig+                           , _fuzzDataDir = fromText "."+                           , _fuzzOptsCrossCheck = False+                           }++data FuzzEnv = FuzzEnv { _getSynthesisers :: ![SynthTool]+                       , _getSimulators   :: ![SimTool]+                       , _yosysInstance   :: {-# UNPACK #-} !Yosys+                       , _fuzzEnvOpts     :: {-# UNPACK #-} !FuzzOpts                        }                deriving (Eq, Show) +$(makeLenses ''FuzzEnv)+ data FuzzState = FuzzState { _fuzzSynthResults :: ![SynthResult]                            , _fuzzSimResults   :: ![SimResult]                            , _fuzzSynthStatus  :: ![SynthStatus]@@ -87,29 +118,80 @@  type MonadFuzz m = (MonadBaseControl IO m, MonadIO m, MonadSh m) -runFuzz :: MonadIO m => Config -> Yosys -> (Config -> Fuzz Sh a) -> m a-runFuzz conf yos m = shelly $ runFuzz' conf yos m+runFuzz :: MonadIO m => FuzzOpts -> Yosys -> Fuzz Sh a -> m a+runFuzz fo yos m = shelly $ runFuzz' fo yos m -runFuzz' :: Monad m => Config -> Yosys -> (Config -> Fuzz m b) -> m b-runFuzz' conf yos m = runReaderT-    (evalStateT (m conf) (FuzzState [] [] []))-    (FuzzEnv-        ( force-        $ defaultIdentitySynth-        : (descriptionToSynth <$> conf ^. configSynthesisers)-        )-        (force $ descriptionToSim <$> conf ^. configSimulators)-        yos+runFuzz' :: Monad m => FuzzOpts -> Yosys -> Fuzz m b -> m b+runFuzz' fo yos m = runReaderT+    (evalStateT m (FuzzState [] [] []))+    (FuzzEnv { _getSynthesisers = ( force+                                   $ defaultIdentitySynth+                                   : (descriptionToSynth <$> conf ^. configSynthesisers)+                                 )+             , _getSimulators = (force $ descriptionToSim <$> conf ^. configSimulators)+             , _yosysInstance = yos+             , _fuzzEnvOpts   = fo+             }     )+  where+    conf = _fuzzOptsConfig fo +askConfig :: Monad m => Fuzz m Config+askConfig = asks (_fuzzOptsConfig . _fuzzEnvOpts)++askOpts :: Monad m => Fuzz m FuzzOpts+askOpts = asks _fuzzEnvOpts++genMethod conf seed gen =+    case T.toLower $ conf ^. configProperty . propSampleMethod of+        "hat" -> do+            logT "Using the hat function"+            sv hatFreqs+        "mean" -> do+            logT "Using the mean function"+            sv meanFreqs+        "median" -> do+            logT "Using the median function"+            sv medianFreqs+        _ -> do+            logT "Using first seed"+            sampleSeed seed gen+  where+    sv a = sampleVerilog a (conf ^. configProperty . propSampleSize) seed gen++relativeFuzzReport :: (MonadSh m) => FuzzReport -> m FuzzReport+relativeFuzzReport fr@(FuzzReport dir _ _ _ _ _ _ _) = liftSh $ do+    newPath <- relPath dir+    return $ (fuzzDir .~ newPath) fr++filterSynth :: SynthResult -> Bool+filterSynth (SynthResult _ _ (Pass _) _) = True+filterSynth _                            = False++filterSim :: SimResult -> Bool+filterSim (SimResult _ _ _ (Pass _) _) = True+filterSim _                            = False++filterSynthStat :: SynthStatus -> Bool+filterSynthStat (SynthStatus _ (Pass _) _) = True+filterSynthStat _                          = False++passedFuzz :: FuzzReport -> Bool+passedFuzz (FuzzReport _ synth sim synthstat _ _ _ _) =+    (passedSynth + passedSim + passedSynthStat) == 0+  where+    passedSynth = length $ filter (not . filterSynth) synth+    passedSim = length $ filter (not . filterSim) sim+    passedSynthStat = length $ filter (not . filterSynthStat) synthstat+ synthesisers :: Monad m => Fuzz m [SynthTool]-synthesisers = lift $ asks getSynthesisers+synthesisers = lift $ asks _getSynthesisers  --simulators :: (Monad m) => Fuzz () m [SimTool] --simulators = lift $ asks getSimulators ---combinations :: [a] -> [b] -> [(a, b)]---combinations l1 l2 = [ (x, y) | x <- l1, y <- l2 ]+combinations :: [a] -> [b] -> [(a, b)]+combinations l1 l2 = [ (x, y) | x <- l1, y <- l2 ]  logT :: MonadSh m => Text -> m () logT = liftSh . logger@@ -148,9 +230,7 @@     toSynth (SynthStatus s _ _) = s  make :: MonadSh m => FilePath -> m ()-make f = liftSh $ do-    mkdir_p f-    cp_r "data" $ f </> fromText "data"+make f = liftSh $ mkdir_p f  pop :: (MonadBaseControl IO m, MonadSh m) => FilePath -> m a -> m a pop f a = do@@ -163,35 +243,43 @@ applyLots :: (a -> b -> c -> d -> e) -> [(a, b)] -> [(c, d)] -> [e] applyLots func a b = applyList (uncurry . uncurry func <$> a) b -toSynthResult-    :: [(SynthTool, SynthTool)]-    -> [(NominalDiffTime, Result Failed ())]-    -> [SynthResult]+toSynthResult :: [(SynthTool, SynthTool)]+              -> [(NominalDiffTime, Result Failed ())]+              -> [SynthResult] toSynthResult a b = applyLots SynthResult a $ fmap swap b -toolRun :: (MonadIO m, MonadSh m) => Text -> m a -> m (NominalDiffTime, a)+toSimResult :: SimTool+            -> [ByteString]+            -> [SynthTool]+            -> [(NominalDiffTime, Result Failed ByteString)]+            -> [SimResult]+toSimResult sima bs as b =+    applyList (applyList (repeat uncurry)+               (applyList (applyList (SimResult <$> as) (repeat sima)) (repeat bs)))+    $ fmap swap b++toolRun :: (MonadIO m, MonadSh m, Show a) => Text -> m a -> m (NominalDiffTime, a) toolRun t m = do     logT $ "Running " <> t-    (diff, res) <- timeit m-    logT $ "Finished " <> t <> " (" <> showT diff <> ")"-    return (diff, res)+    s <- timeit m+    logT $ "Finished " <> t <> " " <> showT s+    return s  equivalence :: (MonadBaseControl IO m, MonadSh m) => SourceInfo -> Fuzz m () equivalence src = do+    doCrossCheck <- fmap _fuzzOptsCrossCheck askOpts+    datadir <- fmap _fuzzDataDir askOpts     synth <- passedSynthesis---    let synthComb =---            nubBy tupEq . filter (uncurry (/=)) $ combinations synth synth     let synthComb =-            nubBy tupEq-                .   filter (uncurry (/=))-                $   (,) defaultIdentitySynth-                <$> synth-    resTimes <- liftSh $ mapM (uncurry equiv) synthComb+            if doCrossCheck+            then nubBy tupEq . filter (uncurry (/=)) $ combinations synth synth+            else nubBy tupEq . filter (uncurry (/=)) $ (,) defaultIdentitySynth <$> synth+    resTimes <- liftSh $ mapM (uncurry (equiv datadir)) synthComb     fuzzSynthResults .= toSynthResult synthComb resTimes     liftSh $ inspect resTimes   where     tupEq (a, b) (a', b') = (a == a' && b == b') || (a == b' && b == a')-    equiv a b =+    equiv datadir a b =         toolRun ("equivalence check for " <> toText a <> " and " <> toText b)             . runResultT             $ do make dir@@ -206,30 +294,42 @@                               </> synthOutput b                             ) $ synthOutput b                          writefile "rtl.v" $ genSource src-                     runEquiv a b src+                     runEquiv datadir a b src         where dir = fromText $ "equiv_" <> toText a <> "_" <> toText b  simulation :: (MonadIO m, MonadSh m) => SourceInfo -> Fuzz m () simulation src = do-    synth    <- passEquiv+    datadir <- fmap _fuzzDataDir askOpts+    synth    <- passedSynthesis+    counterEgs <- failEquivWithIdentityCE     vals     <- liftIO $ generateByteString 20-    ident    <- liftSh $ equiv vals defaultIdentitySynth-    resTimes <- liftSh $ mapM (equiv vals) $ conv <$> synth+    ident    <- liftSh $ sim datadir vals Nothing defaultIdentitySynth+    resTimes <- liftSh $ mapM (sim datadir vals (justPass $ snd ident)) synth+    resTimes2 <- liftSh $ mapM (simCounterEg datadir) counterEgs+    fuzzSimResults .= toSimResult defaultIcarusSim vals synth resTimes     liftSh         .   inspect         $   (\(_, r) -> bimap show (T.unpack . T.take 10 . showBS) r)         <$> (ident : resTimes)   where-    conv (SynthResult _ a _ _) = a-    equiv b a = toolRun ("simulation for " <> toText a) . runResultT $ do+    sim datadir b i a = toolRun ("simulation for " <> toText a) . runResultT $ do         make dir         pop dir $ do             liftSh $ do                 cp (fromText ".." </> fromText (toText a) </> synthOutput a)                     $ synthOutput a                 writefile "rtl.v" $ genSource src-            runSimIc defaultIcarus a src b+            runSimIc datadir defaultIcarus a src b i         where dir = fromText $ "simulation_" <> toText a+    simCounterEg datadir (a, b) = toolRun ("counter-example simulation for " <> toText a) . runResultT $ do+        make dir+        pop dir $ do+            liftSh $ do+                cp (fromText ".." </> fromText (toText a) </> synthOutput a) $ synthOutput a+                writefile "syn_identity.v" $ genSource src+            ident <- runSimIcEC datadir defaultIcarus defaultIdentitySynth src b Nothing+            runSimIcEC datadir defaultIcarus a src b (Just ident)+      where dir = fromText $ "countereg_sim_" <> toText a  -- | Generate a specific number of random bytestrings of size 256. randomByteString :: C.CtrDRBG -> Int -> [ByteString] -> [ByteString]@@ -247,10 +347,23 @@ failEquivWithIdentity :: (MonadSh m) => Fuzz m [SynthResult] failEquivWithIdentity = filter withIdentity . _fuzzSynthResults <$> get   where-    withIdentity (SynthResult (IdentitySynth _) _ (Fail EquivFail) _) = True-    withIdentity (SynthResult _ (IdentitySynth _) (Fail EquivFail) _) = True+    withIdentity (SynthResult (IdentitySynth _) _ (Fail (EquivFail _)) _) = True+    withIdentity (SynthResult _ (IdentitySynth _) (Fail (EquivFail _)) _) = True     withIdentity _                                                    = False +failEquivWithIdentityCE :: (MonadSh m) => Fuzz m [(SynthTool, CounterEg)]+failEquivWithIdentityCE = catMaybes . fmap withIdentity . _fuzzSynthResults <$> get+  where+    withIdentity (SynthResult (IdentitySynth _) s (Fail (EquivFail c)) _) = Just (s, c)+    withIdentity (SynthResult s (IdentitySynth _) (Fail (EquivFail c)) _) = Just (s, c)+    withIdentity _                                                        = Nothing++failedSimulations :: (MonadSh m) => Fuzz m [SimResult]+failedSimulations = filter failedSim . _fuzzSimResults <$> get+  where+    failedSim (SimResult _ _ _ (Fail (SimFail _)) _) = True+    failedSim _                                      = False+ passEquiv :: (MonadSh m) => Fuzz m [SynthResult] passEquiv = filter withIdentity . _fuzzSynthResults <$> get   where@@ -260,26 +373,18 @@ -- | Always reduces with respect to 'Identity'. reduction :: (MonadSh m) => SourceInfo -> Fuzz m () reduction src = do+    datadir <- fmap _fuzzDataDir askOpts     fails      <- failEquivWithIdentity     synthFails <- failedSynthesis-    _          <- liftSh $ mapM red fails+    simFails <- failedSimulations+    _          <- liftSh $ mapM (red datadir) fails     _          <- liftSh $ mapM redSynth synthFails+    _ <- liftSh $ mapM (redSim datadir) simFails     return ()   where-    red (SynthResult a b _ _) = do-        make dir-        pop dir $ do-            s <- reduceSynth a b src-            writefile (fromText ".." </> dir <.> "v") $ genSource s-            return s-        where dir = fromText $ "reduce_" <> toText a <> "_" <> toText b-    redSynth a = do-        make dir-        pop dir $ do-            s <- reduceSynthesis a src-            writefile (fromText ".." </> dir <.> "v") $ genSource s-            return s-        where dir = fromText $ "reduce_" <> toText a+    red datadir (SynthResult a b _ _) = reduceSynth datadir a b src+    redSynth a = reduceSynthesis a src+    redSim datadir (SimResult t _ bs _ _) = reduceSimIc datadir bs t src  titleRun     :: (MonadIO m, MonadSh m) => Text -> Fuzz m a -> Fuzz m (NominalDiffTime, a)@@ -346,9 +451,12 @@     hat = set_ <$> [1 .. length l]     set_ n = if n == h then 1 else 0 -fuzz :: MonadFuzz m => Gen SourceInfo -> Config -> Fuzz m FuzzReport-fuzz gen conf = do-    (seed', src) <- generateSample genMethod+fuzz :: MonadFuzz m => Gen SourceInfo -> Fuzz m FuzzReport+fuzz gen = do+    conf <- askConfig+    opts <- askOpts+    let seed = conf ^. configProperty . propSeed+    (seed', src) <- generateSample $ genMethod conf seed gen     let size = length . lines . T.unpack $ genSource src     liftSh         .  writefile "config.toml"@@ -358,12 +466,18 @@         .  propSeed         ?~ seed'     (tsynth, _) <- titleRun "Synthesis" $ synthesis src-    (tequiv, _) <- titleRun "Equivalence Check" $ equivalence src-    (_     , _) <- titleRun "Simulation" $ simulation src+    (tequiv, _) <- if (_fuzzOptsNoEquiv opts)+        then return (0, mempty)+        else titleRun "Equivalence Check" $ equivalence src+    (_     , _) <- if (_fuzzOptsNoSim opts)+        then return (0, mempty)+        else titleRun "Simulation" $ simulation src     fails       <- failEquivWithIdentity+    failedSim <- failedSimulations     synthFails  <- failedSynthesis     redResult   <--        whenMaybe (not $ null fails && null synthFails)+        whenMaybe (not (null failedSim && null fails && null synthFails)+                   && not (_fuzzOptsNoReduction opts))         . titleRun "Reduction"         $ reduction src     state_  <- get@@ -378,70 +492,28 @@                             tequiv                             (getTime redResult)     return report-  where-    seed      = conf ^. configProperty . propSeed-    genMethod = case T.toLower $ conf ^. configProperty . propSampleMethod of-        "hat" -> do-            logT "Using the hat function"-            sv hatFreqs-        "mean" -> do-            logT "Using the mean function"-            sv meanFreqs-        "median" -> do-            logT "Using the median function"-            sv medianFreqs-        _ -> do-            logT "Using first seed"-            sampleSeed seed gen-    sv a = sampleVerilog a (conf ^. configProperty . propSampleSize) seed gen -relativeFuzzReport :: (MonadSh m) => FuzzReport -> m FuzzReport-relativeFuzzReport fr@(FuzzReport dir _ _ _ _ _ _ _) = liftSh $ do-    newPath <- relPath dir-    return $ (fuzzDir .~ newPath) fr--filterSynth :: SynthResult -> Bool-filterSynth (SynthResult _ _ (Pass _) _) = True-filterSynth _                            = False--filterSim :: SimResult -> Bool-filterSim (SimResult _ _ (Pass _) _) = True-filterSim _                          = False--filterSynthStat :: SynthStatus -> Bool-filterSynthStat (SynthStatus _ (Pass _) _) = True-filterSynthStat _                          = False--passedFuzz :: FuzzReport -> Bool-passedFuzz (FuzzReport _ synth sim synthstat _ _ _ _) =-    (passedSynth + passedSim + passedSynthStat) == 0-  where-    passedSynth = length $ filter (not . filterSynth) synth-    passedSim = length $ filter (not . filterSim) sim-    passedSynthStat = length $ filter (not . filterSynthStat) synthstat--fuzzInDir-    :: MonadFuzz m => Bool -> FilePath -> Gen SourceInfo -> Config -> Fuzz m FuzzReport-fuzzInDir k fp src conf = do+fuzzInDir :: MonadFuzz m => Gen SourceInfo -> Fuzz m FuzzReport+fuzzInDir src = do+    fuzzOpts <- askOpts+    let fp = fromMaybe "fuzz" $ _fuzzOptsOutput fuzzOpts     make fp-    res <- pop fp $ fuzz src conf+    res <- pop fp $ fuzz src     liftSh $ do         writefile (fp <.> "html") $ printResultReport (bname fp) res-        when (passedFuzz res && not k) $ rm_rf fp+        when (passedFuzz res && not (_fuzzOptsKeepAll fuzzOpts)) $ rm_rf fp     relativeFuzzReport res   where     bname = T.pack . takeBaseName . T.unpack . toTextIgnore  fuzzMultiple     :: MonadFuzz m-    => Int-    -> Bool-    -> Maybe FilePath-    -> Gen SourceInfo-    -> Config+    => Gen SourceInfo     -> Fuzz m [FuzzReport]-fuzzMultiple n k fp src conf = do-    x <- case fp of+fuzzMultiple src = do+    fuzzOpts <- askOpts+    let seed = (_fuzzOptsConfig fuzzOpts) ^. configProperty . propSeed+    x <- case _fuzzOptsOutput fuzzOpts of         Nothing -> do             ct <- liftIO getZonedTime             return@@ -453,21 +525,22 @@     make x     pop x $ do         results <- if isNothing seed-            then forM [1 .. n] fuzzDir'+            then forM [1 .. (_fuzzOptsIterations fuzzOpts)] fuzzDir'             else (: []) <$> fuzzDir' (1 :: Int)         liftSh . writefile (fromText "index" <.> "html") $ printSummary             "Fuzz Summary"             results         return results   where-    fuzzDir' n' = fuzzInDir k (fromText $ "fuzz_" <> showT n') src conf-    seed = conf ^. configProperty . propSeed+    fuzzDir' :: (Show a, MonadFuzz m) => a -> Fuzz m FuzzReport+    fuzzDir' n' = local (fuzzEnvOpts . fuzzOptsOutput .~+                         (Just . fromText $ "fuzz_" <> showT n'))+                  $ fuzzInDir src  sampleSeed :: MonadSh m => Maybe Seed -> Gen a -> m (Seed, a) sampleSeed s gen =     liftSh-        $ let-              loop n = if n <= 0+        $ let loop n = if n <= 0                   then                       error                           "Hedgehog.Gen.sample: too many discards, could not generate a sample"
src/Verismith/Generate.hs view
@@ -10,7 +10,8 @@ Various useful generators. -} -{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TemplateHaskell  #-} {-# OPTIONS_GHC -Wno-unused-imports #-}  module Verismith.Generate@@ -60,19 +61,18 @@     ) where -import           Control.Lens                     hiding (Context)-import           Control.Monad                    (replicateM)-import           Control.Monad.Trans.Class        (lift)-import           Control.Monad.Trans.Reader       hiding (local)-import           Control.Monad.Trans.State.Strict-import           Data.Foldable                    (fold)-import           Data.Functor.Foldable            (cata)-import           Data.List                        (foldl', partition)-import qualified Data.Text                        as T-import           Hedgehog                         (Gen, GenT, MonadGen)-import qualified Hedgehog                         as Hog-import qualified Hedgehog.Gen                     as Hog-import qualified Hedgehog.Range                   as Hog+import           Control.Lens               hiding (Context)+import           Control.Monad              (replicateM)+import           Control.Monad.Reader+import           Control.Monad.State.Strict+import           Data.Foldable              (fold)+import           Data.Functor.Foldable      (cata)+import           Data.List                  (foldl', partition)+import qualified Data.Text                  as T+import           Hedgehog                   (Gen, GenT, MonadGen)+import qualified Hedgehog                   as Hog+import qualified Hedgehog.Gen               as Hog+import qualified Hedgehog.Range             as Hog import           Verismith.Config import           Verismith.Internal import           Verismith.Verilog.AST@@ -149,12 +149,6 @@ askProbability :: StateGen Probability askProbability = asks probability -rask :: StateGen Config-rask = ask--lget :: StateGen Context-lget = lift . lift $ get- -- | Generates a random large number, which can also be negative. largeNum :: (MonadGen m) => m Int largeNum = Hog.int $ Hog.linear (-100) 100@@ -314,7 +308,7 @@ -- is then increased so that the label is unique. makeIdentifier :: T.Text -> StateGen Identifier makeIdentifier prefix = do-    context <- lget+    context <- get     let ident = Identifier $ prefix <> showT (context ^. nameCounter)     nameCounter += 1     return ident@@ -332,7 +326,7 @@ -- the generation is currently in the other branch of an if-statement. nextPort :: PortType -> StateGen Port nextPort pt = do-    context <- lget+    context <- get     ident   <- makeIdentifier . T.toLower $ showT pt     getPort' pt ident (_variables context) @@ -347,7 +341,7 @@ -- | Generates an expression from variables that are currently in scope. scopedExpr :: StateGen Expr scopedExpr = do-    context <- lget+    context <- get     prob    <- askProbability     Hog.sized         . exprWithContext (_probExpr prob) (_parameters context)@@ -383,12 +377,12 @@ conditional :: StateGen Statement conditional = do     expr  <- scopedExpr-    nc    <- _nameCounter <$> lget+    nc    <- _nameCounter <$> get     tstat <- seqBlock-    nc'   <- _nameCounter <$> lget+    nc'   <- _nameCounter <$> get     nameCounter .= nc     fstat <- seqBlock-    nc''  <- _nameCounter <$> lget+    nc''  <- _nameCounter <$> get     nameCounter .= max nc' nc''     return $ CondStmnt expr (Just tstat) (Just fstat) @@ -408,7 +402,7 @@ statement :: StateGen Statement statement = do     prob <- askProbability-    cont <- lget+    cont <- get     let defProb i = prob ^. probStmnt . i     Hog.frequency         [ (defProb probStmntBlock              , BlockAssign <$> assignment)@@ -442,13 +436,13 @@ -- representation for the clock. instantiate :: ModDecl -> StateGen ModItem instantiate (ModDecl i outP inP _ _) = do-    context <- lget+    context <- get     outs    <- replicateM (length outP) (nextPort Wire)     ins <- take (length inpFixed) <$> Hog.shuffle (context ^. variables)     insLit <- replicateM (length inpFixed - length ins) (Number <$> genBitVec)     mapM_ (uncurry process) . zip (ins ^.. traverse . portName) $ inpFixed ^.. traverse . portSize     ident <- makeIdentifier "modinst"-    vs <- view variables <$> lget+    vs <- view variables <$> get     Hog.choice         [ return . ModInst i ident $ ModConn <$> (toE (outs <> clkPort <> ins) <> insLit)         , ModInst i ident <$> Hog.shuffle@@ -462,7 +456,7 @@             | n == "clk" = False             | otherwise = True         process p r = do-            params <- view parameters <$> lget+            params <- view parameters <$> get             variables %= resizePort params p r  -- | Generates a module instance by also generating a new module if there are@@ -486,8 +480,8 @@ -- a module from a context or generating a new one. modInst :: StateGen ModItem modInst = do-    prob    <- rask-    context <- lget+    prob    <- ask+    context <- get     let maxMods = prob ^. configProperty . propMaxModules     if length (context ^. modules) < maxMods         then do@@ -499,7 +493,7 @@             parameters .= []             modDepth -= 1             chosenMod <- moduleDef Nothing-            ncont     <- lget+            ncont     <- get             let genMods = ncont ^. modules             modDepth += 1             parameters .= params@@ -511,9 +505,9 @@ -- | Generate a random module item. modItem :: StateGen ModItem modItem = do-    conf    <- rask+    conf    <- ask     let prob = conf ^. configProbability-    context <- lget+    context <- get     let defProb i = prob ^. probModItem . i     det <- Hog.frequency [ (conf ^. configProperty . propDeterminism, return True)                          , (conf ^. configProperty . propNonDeterminism, return False) ]@@ -535,7 +529,7 @@ constExpr :: StateGen ConstExpr constExpr = do     prob    <- askProbability-    context <- lget+    context <- get     Hog.sized $ constExprWithContext (context ^. parameters)                                            (prob ^. probExpr) @@ -576,8 +570,8 @@     portList <- Hog.list (Hog.linear 4 10) $ nextPort Wire     mi       <- Hog.list (Hog.linear 4 100) modItem     ps       <- Hog.list (Hog.linear 0 10) parameter-    context  <- lget-    config   <- rask+    context  <- get+    config   <- ask     let (newPorts, local) = partition (`identElem` portList) $ _variables context     let          size =
+ src/Verismith/OptParser.hs view
@@ -0,0 +1,299 @@+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+                 , fuzzNoReduction     :: !Bool+                 , fuzzExistingFile    :: !(Maybe FilePath)+                 , fuzzExistingFileTop :: !Text+                 , fuzzCrossCheck      :: !Bool+                 }+          | Generate { generateFilename   :: !(Maybe FilePath)+                     , generateConfigFile :: !(Maybe FilePath)+                     }+          | Parse { parseFilename            :: {-# UNPACK #-} !FilePath+                  , parseTop                 :: {-# UNPACK #-} !Text+                  , parseOutput              :: !(Maybe FilePath)+                  , parseRemoveConstInConcat :: !Bool+                  }+          | 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.")+        <*> (Opt.switch $ Opt.long "no-reduction" <> Opt.help+                "Do not run reduction on a failed testcase.")+        <*> (  Opt.optional+            .  Opt.strOption+            $  Opt.long "source"+            <> Opt.short 's'+            <> Opt.metavar "FILE"+            <> Opt.help "Name of the top module.")+        <*> textOption+                (  Opt.long "source-top"+                <> Opt.short 't'+                <> Opt.metavar "TOP"+                <> Opt.help "Define the top module for the source file."+                <> Opt.showDefault+                <> Opt.value "top")+        <*> (Opt.switch $ Opt.long "crosscheck" <> Opt.help+                "Do not only compare against the original design, but also against other netlists.")++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."))+    <*> 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 "output"+          <> Opt.short 'o'+          <> Opt.metavar "FILE"+          <> Opt.help "Output file to write the parsed file to.")+    <*> (Opt.switch $ Opt.long "remove-const-in-concat" <> Opt.help+            "Remove constants in concatenation to simplify the Verilog.")++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."+    )
src/Verismith/Reduce.hs view
@@ -18,6 +18,7 @@       reduceWithScript     , reduceSynth     , reduceSynthesis+    , reduceSimIc     , reduce     , reduce_     , Replacement(..)@@ -31,6 +32,8 @@     , cleanSourceInfo     , cleanSourceInfoAll     , removeDecl+    , removeConstInConcat+    , takeReplace     , filterExpr     ) where@@ -38,18 +41,21 @@ import           Control.Lens             hiding ((<.>)) import           Control.Monad            (void) import           Control.Monad.IO.Class   (MonadIO, liftIO)+import           Data.ByteString          (ByteString) import           Data.Foldable            (foldrM) import           Data.List                (nub) import           Data.List.NonEmpty       (NonEmpty (..)) import qualified Data.List.NonEmpty       as NonEmpty import           Data.Maybe               (mapMaybe) import           Data.Text                (Text)-import           Shelly                   ((<.>))+import           Shelly                   (fromText, (<.>)) import qualified Shelly-import           Shelly.Lifted            (MonadSh, liftSh)+import           Shelly.Lifted            (MonadSh, liftSh, rm_rf, writefile) import           Verismith.Internal import           Verismith.Result import           Verismith.Tool+import           Verismith.Tool.Icarus+import           Verismith.Tool.Identity import           Verismith.Tool.Internal import           Verismith.Verilog import           Verismith.Verilog.AST@@ -156,6 +162,21 @@ clean :: (Mutate a) => [Identifier] -> a -> a clean ids = mutExpr (transform $ filterExpr ids) +takeReplace :: (Monoid a) => Replacement a -> a+takeReplace (Single a) = a+takeReplace (Dual a _) = a+takeReplace None       = mempty++removeConstInConcat :: Replace SourceInfo+removeConstInConcat = Single . mutExpr replace+  where+    replace :: Expr -> Expr+    replace (Concat expr) = maybe (Number 0) Concat . NonEmpty.nonEmpty+                            $ NonEmpty.filter notConstant expr+    replace e             = e+    notConstant (Number _) = False+    notConstant _          = True+ cleanUndefined :: [Identifier] -> [ModItem] -> [ModItem] cleanUndefined ids mis = clean usedWires mis   where@@ -496,13 +517,15 @@ -- | Reduction using custom reduction strategies. reduce_     :: MonadSh m-    => Text+    => Shelly.FilePath+    -> Text     -> Replace SourceInfo     -> (SourceInfo -> Bool)     -> (SourceInfo -> m Bool)     -> SourceInfo     -> m SourceInfo-reduce_ title repl bot eval src = do+reduce_ out title repl bot eval src = do+    writefile out $ genSource src     liftSh         .  Shelly.echo         $  "Reducing "@@ -535,24 +558,26 @@             None -> return src   where     cond s = s /= src-    recReduction = reduce_ title repl bot eval+    recReduction = reduce_ out title repl bot eval  -- | Reduce an input to a minimal representation. It follows the reduction -- strategy mentioned above. reduce     :: MonadSh m-    => (SourceInfo -> m Bool) -- ^ Failed or not.+    => Shelly.FilePath -- ^ Filepath for temporary file.+    -> (SourceInfo -> m Bool) -- ^ Failed or not.     -> SourceInfo              -- ^ Input verilog source to be reduced.     -> m SourceInfo           -- ^ Reduced output.-reduce eval src =+reduce fp eval src =     fmap removeDecl         $   red "Modules" moduleBot halveModules src-        >>= redAll "Module Items" modItemBot         halveModItems+        >>= redAll "Module items" modItemBot         halveModItems         >>= redAll "Statements"   (const defaultBot) halveStatements         -- >>= redAll "Expressions"  (const defaultBot) halveExpr+        >>= red "Remove constants in concat" defaultBot removeConstInConcat   where-    red s bot a = reduce_ s a bot eval-    red' s bot a t = reduce_ s (a t) (bot t) eval+    red s bot a = reduce_ fp s a bot eval+    red' s bot a t = reduce_ fp s (a t) (bot t) eval     redAll s bot halve' src' = foldrM         (\t -> red' (s <> " (" <> getIdentifier t <> ")") bot halve' t)         src'@@ -577,33 +602,53 @@ reduceWithScript top script file = do     liftSh . Shelly.cp file $ file <.> "original"     srcInfo <- liftIO . parseSourceInfoFile top $ Shelly.toTextIgnore file-    void $ reduce (runScript script file) srcInfo+    void $ reduce (fromText "reduce_script.v") (runScript script file) srcInfo  -- | Reduce a 'SourceInfo' using two 'Synthesiser' that are passed to it. reduceSynth     :: (Synthesiser a, Synthesiser b, MonadSh m)-    => a+    => Shelly.FilePath+    -> a     -> b     -> SourceInfo     -> m SourceInfo-reduceSynth a b = reduce synth+reduceSynth datadir a b = reduce (fromText $ "reduce_" <> toText a <> "_" <> toText b <> ".v") synth   where     synth src' = liftSh $ do         r <- runResultT $ do             runSynth a src'             runSynth b src'-            runEquiv a b src'+            runEquiv datadir a b src'         return $ case r of-            Fail EquivFail -> True-            Fail _         -> False-            Pass _         -> False+            Fail (EquivFail _) -> True+            _                  -> False  reduceSynthesis :: (Synthesiser a, MonadSh m) => a -> SourceInfo -> m SourceInfo-reduceSynthesis a = reduce synth+reduceSynthesis a = reduce (fromText $ "reduce_" <> toText a <> ".v") synth   where     synth src = liftSh $ do         r <- runResultT $ runSynth a src         return $ case r of             Fail SynthFail -> True-            Fail _         -> False-            Pass _         -> False+            _              -> False++runInTmp :: Shelly.Sh a -> Shelly.Sh a+runInTmp a = Shelly.withTmpDir $ (\f -> do+    dir <- Shelly.pwd+    Shelly.cd f+    r <- a+    Shelly.cd dir+    return r)++reduceSimIc :: (Synthesiser a, MonadSh m) => Shelly.FilePath -> [ByteString] -> a -> SourceInfo -> m SourceInfo+reduceSimIc fp bs a = reduce (fromText $ "reduce_sim_" <> toText a <> ".v") synth+  where+    synth src = liftSh . runInTmp $ do+        r <- runResultT $ do+            runSynth a src+            runSynth defaultIdentity src+            i <- runSimIc fp defaultIcarus defaultIdentity src bs Nothing+            runSimIc fp defaultIcarus a src bs $ Just i+        return $ case r of+            Fail (SimFail _) -> True+            _                -> False
src/Verismith/Report.hs view
@@ -35,6 +35,7 @@     , defaultYosysSynth     , defaultXSTSynth     , defaultQuartusSynth+    , defaultQuartusLightSynth     , defaultIdentitySynth     , descriptionToSim     , descriptionToSynth@@ -76,47 +77,54 @@                | VivadoSynth {-# UNPACK #-} !Vivado                | YosysSynth {-# UNPACK #-} !Yosys                | QuartusSynth {-# UNPACK #-} !Quartus+               | QuartusLightSynth {-# UNPACK #-} !QuartusLight                | IdentitySynth {-# UNPACK #-} !Identity                deriving (Eq)  instance NFData SynthTool where-    rnf (XSTSynth a)      = rnf a-    rnf (VivadoSynth a)   = rnf a-    rnf (YosysSynth a)    = rnf a-    rnf (QuartusSynth a)  = rnf a-    rnf (IdentitySynth a) = rnf a+    rnf (XSTSynth a)          = rnf a+    rnf (VivadoSynth a)       = rnf a+    rnf (YosysSynth a)        = rnf a+    rnf (QuartusSynth a)      = rnf a+    rnf (QuartusLightSynth a) = rnf a+    rnf (IdentitySynth a)     = rnf a  instance Show SynthTool where-    show (XSTSynth xst)           = show xst-    show (VivadoSynth vivado)     = show vivado-    show (YosysSynth yosys)       = show yosys-    show (QuartusSynth quartus)   = show quartus-    show (IdentitySynth identity) = show identity+    show (XSTSynth xst)              = show xst+    show (VivadoSynth vivado)        = show vivado+    show (YosysSynth yosys)          = show yosys+    show (QuartusSynth quartus)      = show quartus+    show (QuartusLightSynth quartus) = show quartus+    show (IdentitySynth identity)    = show identity  instance Tool SynthTool where-    toText (XSTSynth xst)           = toText xst-    toText (VivadoSynth vivado)     = toText vivado-    toText (YosysSynth yosys)       = toText yosys-    toText (QuartusSynth quartus)   = toText quartus-    toText (IdentitySynth identity) = toText identity+    toText (XSTSynth xst)              = toText xst+    toText (VivadoSynth vivado)        = toText vivado+    toText (YosysSynth yosys)          = toText yosys+    toText (QuartusSynth quartus)      = toText quartus+    toText (QuartusLightSynth quartus) = toText quartus+    toText (IdentitySynth identity)    = toText identity  instance Synthesiser SynthTool where-    runSynth (XSTSynth xst)           = runSynth xst-    runSynth (VivadoSynth vivado)     = runSynth vivado-    runSynth (YosysSynth yosys)       = runSynth yosys-    runSynth (QuartusSynth quartus)   = runSynth quartus-    runSynth (IdentitySynth identity) = runSynth identity+    runSynth (XSTSynth xst)              = runSynth xst+    runSynth (VivadoSynth vivado)        = runSynth vivado+    runSynth (YosysSynth yosys)          = runSynth yosys+    runSynth (QuartusSynth quartus)      = runSynth quartus+    runSynth (QuartusLightSynth quartus) = runSynth quartus+    runSynth (IdentitySynth identity)    = runSynth identity -    synthOutput (XSTSynth xst)           = synthOutput xst-    synthOutput (VivadoSynth vivado)     = synthOutput vivado-    synthOutput (YosysSynth yosys)       = synthOutput yosys-    synthOutput (QuartusSynth quartus)   = synthOutput quartus-    synthOutput (IdentitySynth identity) = synthOutput identity+    synthOutput (XSTSynth xst)              = synthOutput xst+    synthOutput (VivadoSynth vivado)        = synthOutput vivado+    synthOutput (YosysSynth yosys)          = synthOutput yosys+    synthOutput (QuartusSynth quartus)      = synthOutput quartus+    synthOutput (QuartusLightSynth quartus) = synthOutput quartus+    synthOutput (IdentitySynth identity)    = synthOutput identity      setSynthOutput (YosysSynth yosys)     = YosysSynth . setSynthOutput yosys     setSynthOutput (XSTSynth xst)         = XSTSynth . setSynthOutput xst     setSynthOutput (VivadoSynth vivado)   = VivadoSynth . setSynthOutput vivado     setSynthOutput (QuartusSynth quartus) = QuartusSynth . setSynthOutput quartus+    setSynthOutput (QuartusLightSynth quartus) = QuartusLightSynth . setSynthOutput quartus     setSynthOutput (IdentitySynth identity) = IdentitySynth . setSynthOutput identity  defaultYosysSynth :: SynthTool@@ -125,6 +133,9 @@ defaultQuartusSynth :: SynthTool defaultQuartusSynth = QuartusSynth defaultQuartus +defaultQuartusLightSynth :: SynthTool+defaultQuartusLightSynth = QuartusLightSynth defaultQuartusLight+ defaultVivadoSynth :: SynthTool defaultVivadoSynth = VivadoSynth defaultVivado @@ -155,15 +166,15 @@  -- | The results from running a tool through a simulator. It can either fail or -- return a result, which is most likely a 'ByteString'.-data SimResult = SimResult !SynthTool !SimTool !BResult !NominalDiffTime+data SimResult = SimResult !SynthTool !SimTool ![ByteString] !BResult !NominalDiffTime                  deriving (Eq)  instance Show SimResult where-    show (SimResult synth sim r d) = show synth <> ", " <> show sim <> ": " <> show (bimap show (T.unpack . showBS) r) <> " (" <> show d <> ")"+    show (SimResult synth sim _ r d) = show synth <> ", " <> show sim <> ": " <> show (bimap show (T.unpack . showBS) r) <> " (" <> show d <> ")"  getSimResult :: SimResult -> UResult-getSimResult (SimResult _ _ (Pass _) _) = Pass ()-getSimResult (SimResult _ _ (Fail b) _) = Fail b+getSimResult (SimResult _ _ _ (Pass _) _) = Pass ()+getSimResult (SimResult _ _ _ (Fail b) _) = Fail b  -- | The results of comparing the synthesised outputs of two files using a -- formal equivalence checker. This will either return a failure or an output@@ -228,6 +239,11 @@         . Quartus (fromText <$> bin)                   (fromMaybe (quartusDesc defaultQuartus) desc)         $ maybe (quartusOutput defaultQuartus) fromText out+descriptionToSynth (SynthDescription "quartuslight" bin desc out) =+    QuartusLightSynth+        . QuartusLight (fromText <$> bin)+                  (fromMaybe (quartusDesc defaultQuartus) desc)+        $ maybe (quartusOutput defaultQuartus) fromText out descriptionToSynth (SynthDescription "identity" _ desc out) =     IdentitySynth         . Identity (fromMaybe (identityDesc defaultIdentity) desc)@@ -236,13 +252,13 @@     error $ "Could not find implementation for synthesiser '" <> show s <> "'"  status :: Result Failed () -> Html-status (Pass _           ) = H.td ! A.class_ "is-success" $ "Passed"-status (Fail EmptyFail   ) = H.td ! A.class_ "is-danger" $ "Failed"-status (Fail EquivFail   ) = H.td ! A.class_ "is-danger" $ "Equivalence failed"-status (Fail SimFail     ) = H.td ! A.class_ "is-danger" $ "Simulation failed"-status (Fail SynthFail   ) = H.td ! A.class_ "is-danger" $ "Synthesis failed"-status (Fail EquivError  ) = H.td ! A.class_ "is-danger" $ "Equivalence error"-status (Fail TimeoutError) = H.td ! A.class_ "is-warning" $ "Time out"+status (Pass _           )  = H.td ! A.class_ "is-success" $ "Passed"+status (Fail EmptyFail   )  = H.td ! A.class_ "is-danger" $ "Failed"+status (Fail (EquivFail _)) = H.td ! A.class_ "is-danger" $ "Equivalence failed"+status (Fail (SimFail  _))  = H.td ! A.class_ "is-danger" $ "Simulation failed"+status (Fail SynthFail   )  = H.td ! A.class_ "is-danger" $ "Synthesis failed"+status (Fail EquivError  )  = H.td ! A.class_ "is-danger" $ "Equivalence error"+status (Fail TimeoutError)  = H.td ! A.class_ "is-warning" $ "Time out"  synthStatusHtml :: SynthStatus -> Html synthStatusHtml (SynthStatus synth res diff) = H.tr $ do
src/Verismith/Result.hs view
@@ -22,6 +22,8 @@ module Verismith.Result     ( Result(..)     , ResultT(..)+    , justPass+    , justFail     , (<?>)     , annotate     )@@ -41,6 +43,14 @@ data Result a b = Fail a                 | Pass b                 deriving (Eq, Show)++justPass :: Result a b -> Maybe b+justPass (Fail _) = Nothing+justPass (Pass a) = Just a++justFail :: Result a b -> Maybe a+justFail (Pass _) = Nothing+justFail (Fail a) = Just a  instance Semigroup (Result a b) where     Pass _ <> a = a
src/Verismith/Tool.hs view
@@ -29,6 +29,9 @@     -- ** Quartus     , Quartus(..)     , defaultQuartus+    -- ** Quartus Light+    , QuartusLight(..)+    , defaultQuartusLight     -- ** Identity     , Identity(..)     , defaultIdentity@@ -46,6 +49,7 @@ import           Verismith.Tool.Identity import           Verismith.Tool.Internal import           Verismith.Tool.Quartus+import           Verismith.Tool.QuartusLight import           Verismith.Tool.Vivado import           Verismith.Tool.XST import           Verismith.Tool.Yosys
src/Verismith/Tool/Icarus.hs view
@@ -14,6 +14,7 @@     ( Icarus(..)     , defaultIcarus     , runSimIc+    , runSimIcEC     ) where @@ -39,6 +40,8 @@ import           Prelude                    hiding (FilePath) import           Shelly import           Shelly.Lifted              (liftSh)+import           Verismith.CounterEg        (CounterEg (..))+import           Verismith.Result import           Verismith.Tool.Internal import           Verismith.Tool.Template import           Verismith.Verilog.AST@@ -114,12 +117,12 @@     let newtb     = instantiateMod m tb     let modWithTb = Verilog [newtb, m]     liftSh . writefile "main.v" $ genSource modWithTb-    annotate SimFail $ runSimWithFile sim "main.v" bss+    annotate (SimFail mempty) $ runSimWithFile sim "main.v" bss     where m = rinfo ^. mainModule  runSimIcarusWithFile     :: Icarus -> FilePath -> [ByteString] -> ResultSh ByteString-runSimIcarusWithFile sim f _ = annotate SimFail . liftSh $ do+runSimIcarusWithFile sim f _ = annotate (SimFail mempty) . liftSh $ do     dir <- pwd     logCommand_ dir "icarus"         $ run (icarusPath sim) ["-o", "main", toTextIgnore f]@@ -131,48 +134,46 @@ fromBytes :: ByteString -> Integer fromBytes = B.foldl' f 0 where f a b = a `shiftL` 8 .|. fromIntegral b -runSimIc-    :: (Synthesiser b)-    => Icarus-    -> b-    -> SourceInfo-    -> [ByteString]-    -> ResultSh ByteString-runSimIc sim1 synth1 srcInfo bss = do-    dir <- liftSh pwd-    let top      = srcInfo ^. mainModule-    let inConcat = (RegConcat (Id . fromPort <$> (top ^. modInPorts)))-    let-        tb = instantiateMod top $ ModDecl-            "testbench"-            []-            []-            [ Initial-            $  fold-                   [ BlockAssign (Assign "clk" Nothing 0)-                   , BlockAssign (Assign inConcat Nothing 0)-                   ]-            <> fold-                   (   (\r -> TimeCtrl-                           10-                           (Just $ BlockAssign (Assign inConcat Nothing r))-                       )-                   .   fromInteger-                   .   fromBytes-                   <$> bss-                   )-            <> (SysTaskEnable $ Task "finish" [])-            , Always . TimeCtrl 5 . Just $ BlockAssign+tbModule :: [ByteString] -> ModDecl -> Verilog+tbModule bss top =+    Verilog [ instantiateMod top $ ModDecl "testbench" [] []+              [ Initial+                $  fold [ BlockAssign (Assign "clk" Nothing 0)+                        , BlockAssign (Assign inConcat Nothing 0)+                        ]+                <> fold ((\r -> TimeCtrl 10+                             (Just $ BlockAssign (Assign inConcat Nothing r)))+                         . fromInteger . fromBytes <$> bss)+                <> (TimeCtrl 10 . Just . SysTaskEnable $ Task "finish" [])+              , Always . TimeCtrl 5 . Just $ BlockAssign                 (Assign "clk" Nothing (UnOp UnNot (Id "clk")))-            , Always . EventCtrl (EPosEdge "clk") . Just . SysTaskEnable $ Task-                "strobe"-                ["%b", Id "y"]+              , Always . EventCtrl (EPosEdge "clk") . Just . SysTaskEnable+                $ Task "strobe" ["%b", Id "y"]+              ] []             ]-            []+  where+    inConcat = (RegConcat . filter (/= (Id "clk")) $ (Id . fromPort <$> (top ^. modInPorts))) -    liftSh . writefile "testbench.v" $ icarusTestbench (Verilog [tb]) synth1-    liftSh $ exe dir "icarus" "iverilog" ["-o", "main", "testbench.v"]-    liftSh+counterTestBench :: CounterEg -> ModDecl -> Verilog+counterTestBench (CounterEg _ states) m = tbModule filtered m+  where+    filtered = convert . fold . fmap snd . filter ((/= "clk") . fst) <$> states++runSimIc' :: (Synthesiser b) => ([ByteString] -> ModDecl -> Verilog)+          -> FilePath+          -> Icarus+          -> b+          -> SourceInfo+          -> [ByteString]+          -> Maybe ByteString+          -> ResultSh ByteString+runSimIc' fun datadir sim1 synth1 srcInfo bss bs = do+    dir <- liftSh pwd+    let top      = srcInfo ^. mainModule+    let tb = fun bss top+    liftSh . writefile tbname $ icarusTestbench datadir tb synth1+    liftSh $ exe dir "icarus" "iverilog" ["-o", exename, toTextIgnore tbname]+    s <- liftSh         $   B.take 8         .   BA.convert         .   (hash :: ByteString -> Digest SHA256)@@ -182,7 +183,29 @@                 (runFoldLines (mempty :: ByteString)                               callback                               (vvpPath sim1)-                              ["main"]-                )+                              [exename])+    case (bs, s) of+        (Nothing, s') -> ResultT . return $ Pass s'+        (Just bs', s') -> if bs' == s'+                    then ResultT . return $ Pass s'+                    else ResultT . return $ Fail (SimFail s')   where     exe dir name e = void . errExit False . logCommand dir name . timeout e+    tbname = fromText $ toText synth1 <> "_testbench.v"+    exename = toText synth1 <> "_main"++runSimIc :: (Synthesiser b)+         => FilePath         -- ^ Data directory.+         -> Icarus           -- ^ Icarus simulator.+         -> b                -- ^ Synthesis tool to be tested.+         -> SourceInfo       -- ^ Original generated program to test.+         -> [ByteString]     -- ^ Test vectors to be passed as inputs to the generated Verilog.+         -> Maybe ByteString -- ^ What the correct output should be. If+                             -- 'Nothing' is passed, then just return 'Pass+                             -- ByteString' with the answer.+         -> ResultSh ByteString+runSimIc = runSimIc' tbModule++runSimIcEC :: (Synthesiser b) => FilePath -> Icarus -> b+           -> SourceInfo -> CounterEg -> Maybe ByteString -> ResultSh ByteString+runSimIcEC a b c d e = runSimIc' (const $ counterTestBench e) a b c d []
src/Verismith/Tool/Internal.hs view
@@ -54,6 +54,7 @@ import           Shelly import           Shelly.Lifted         (MonadSh, liftSh) import           System.FilePath.Posix (takeBaseName)+import           Verismith.CounterEg   (CounterEg) import           Verismith.Internal import           Verismith.Result import           Verismith.Verilog.AST@@ -74,12 +75,20 @@                  -> ResultSh ByteString  data Failed = EmptyFail-            | EquivFail+            | EquivFail CounterEg             | EquivError-            | SimFail+            | SimFail ByteString             | SynthFail             | TimeoutError-            deriving (Eq, Show)+            deriving (Eq)++instance Show Failed where+    show EmptyFail     = "EmptyFail"+    show (EquivFail _) = "EquivFail"+    show EquivError    = "EquivError"+    show (SimFail bs)  = "SimFail " <> T.unpack (T.take 10 $ showBS bs)+    show SynthFail     = "SynthFail"+    show TimeoutError  = "TimeoutError"  instance Semigroup Failed where     EmptyFail <> a = a
src/Verismith/Tool/Quartus.hs view
@@ -22,6 +22,7 @@ import           Shelly import           Shelly.Lifted             (liftSh) import           Verismith.Tool.Internal+import           Verismith.Tool.Template import           Verismith.Verilog.AST import           Verismith.Verilog.CodeGen @@ -52,18 +53,16 @@ runSynthQuartus sim (SourceInfo top src) = do     dir <- liftSh pwd     let ex = execute_ SynthFail dir "quartus"-    liftSh . writefile inpf $ genSource src-    liftSh . noPrint $ run_-        "sed"-        [ "-i"-        , "s/^module/(* multstyle = \"logic\" *) module/;"-        , toTextIgnore inpf-        ]-    ex (exec "quartus_map")-       [top, "--source=" <> toTextIgnore inpf, "--family=Cyclone V"]-    ex (exec "quartus_fit") [top, "--part=5CGXFC7D6F31C6"]-    ex (exec "quartus_eda") [top, "--simulation", "--tool=vcs"]     liftSh $ do+        writefile inpf $ genSource src+        noPrint $ run_ "sed" [ "-i"+                             , "s/^module/(* multstyle = \"logic\" *) module/;"+                             , toTextIgnore inpf+                             ]+        writefile quartusSdc $ "create_clock -period 5 -name clk [get_ports clock]"+        writefile quartusTcl $ quartusSynthConfig sim quartusSdc top inpf+    ex (exec "quartus_sh") ["-t", toTextIgnore quartusTcl]+    liftSh $ do         cp (fromText "simulation/vcs" </> fromText top <.> "vo")             $ synthOutput sim         run_@@ -75,3 +74,5 @@   where     inpf = "rtl.v"     exec s = maybe (fromText s) (</> fromText s) $ quartusBin sim+    quartusTcl = fromText top <.> "tcl"+    quartusSdc = fromText top <.> "sdc"
+ src/Verismith/Tool/QuartusLight.hs view
@@ -0,0 +1,78 @@+{-|+Module      : Verismith.Tool.QuartusLight+Description : QuartusLight synthesiser implementation.+Copyright   : (c) 2019, Yann Herklotz Grave+License     : GPL-3+Maintainer  : yann [at] yannherklotz [dot] com+Stability   : experimental+Portability : POSIX++QuartusLight synthesiser implementation.+-}++module Verismith.Tool.QuartusLight+    ( QuartusLight(..)+    , defaultQuartusLight+    )+where++import           Control.DeepSeq           (NFData, rnf, rwhnf)+import           Data.Text                 (Text, unpack)+import           Prelude                   hiding (FilePath)+import           Shelly+import           Shelly.Lifted             (liftSh)+import           Verismith.Tool.Internal+import           Verismith.Tool.Template+import           Verismith.Verilog.AST+import           Verismith.Verilog.CodeGen++data QuartusLight = QuartusLight { quartusLightBin    :: !(Maybe FilePath)+                                 , quartusLightDesc   :: {-# UNPACK #-} !Text+                                 , quartusLightOutput :: {-# UNPACK #-} !FilePath+                                 }+                  deriving (Eq)++instance Tool QuartusLight where+    toText (QuartusLight _ t _) = t++instance Show QuartusLight where+    show t = unpack $ toText t++instance Synthesiser QuartusLight where+    runSynth = runSynthQuartusLight+    synthOutput = quartusLightOutput+    setSynthOutput (QuartusLight a b _) = QuartusLight a b++instance NFData QuartusLight where+    rnf = rwhnf++defaultQuartusLight :: QuartusLight+defaultQuartusLight = QuartusLight Nothing "quartus" "syn_quartus.v"++runSynthQuartusLight :: QuartusLight -> SourceInfo -> ResultSh ()+runSynthQuartusLight sim (SourceInfo top src) = do+    dir <- liftSh pwd+    let ex = execute_ SynthFail dir "quartus"+    liftSh $ do+        writefile inpf $ genSource src+        noPrint $ run_ "sed" [ "-i"+                             , "s/^module/(* multstyle = \"logic\" *) module/;"+                             , toTextIgnore inpf+                             ]+        writefile quartusSdc $ "create_clock -period 5 -name clk [get_ports clock]"+        writefile quartusTcl $ quartusSynthConfig sim quartusSdc top inpf+    ex (exec "quartus_sh") ["-t", toTextIgnore quartusTcl]+    liftSh $ do+        cp (fromText "simulation/vcs" </> fromText top <.> "vo")+            $ synthOutput sim+        run_+            "sed"+            [ "-ri"+            , "s,^// DATE.*,,; s,^tri1 (.*);,wire \\1 = 1;,; /^\\/\\/ +synopsys/ d;"+            , toTextIgnore $ synthOutput sim+            ]+  where+    inpf = "rtl.v"+    exec s = maybe (fromText s) (</> fromText s) $ quartusLightBin sim+    quartusTcl = fromText top <.> "tcl"+    quartusSdc = fromText top <.> "sdc"
src/Verismith/Tool/Template.hs view
@@ -13,8 +13,11 @@ {-# LANGUAGE QuasiQuotes #-}  module Verismith.Tool.Template-    ( yosysSatConfig+    ( yosysSynthConfigStd+    , yosysSatConfig     , yosysSimConfig+    , quartusLightSynthConfig+    , quartusSynthConfig     , xstSynthConfig     , vivadoSynthConfig     , sbyConfig@@ -48,7 +51,15 @@ outputText :: Synthesiser a => a -> Text outputText = toTextIgnore . synthOutput --- brittany-disable-next-binding+yosysSynthConfig :: Synthesiser a => Text -> a -> FilePath -> Text+yosysSynthConfig t a fp = [st|read_verilog #{toTextIgnore fp}+#{t}+write_verilog #{outputText a}+|]++yosysSynthConfigStd :: Synthesiser a => a -> FilePath -> Text+yosysSynthConfigStd = yosysSynthConfig "synth"+ yosysSatConfig :: (Synthesiser a, Synthesiser b) => a -> b -> SourceInfo -> Text yosysSatConfig sim1 sim2 (SourceInfo top src) = [st|read_verilog #{outputText sim1} #{rename "_1" mis}@@ -62,13 +73,51 @@   where     mis = src ^.. getSourceId --- brittany-disable-next-binding yosysSimConfig :: Text yosysSimConfig = [st|read_verilog rtl.v; proc;; rename mod mod_rtl |] --- brittany-disable-next-binding+quartusLightSynthConfig :: Synthesiser a => a -> FilePath -> Text -> FilePath -> Text+quartusLightSynthConfig q sdc top fp = [st|load_package flow++project_new -overwrite #{top}++set_global_assignment -name FAMILY "Cyclone V"+set_global_assignment -name SYSTEMVERILOG_FILE #{toTextIgnore fp}+set_global_assignment -name TOP_LEVEL_ENTITY #{top}+set_global_assignment -name SDC_FILE #{toTextIgnore sdc}+set_global_assignment -name INI_VARS "qatm_force_vqm=on;"+set_global_assignment -name NUM_PARALLEL_PROCESSORS 2+set_instance_assignment -name VIRTUAL_PIN ON -to *++execute_module -tool map+execute_module -tool fit+execute_module -tool sta -args "--mode=implement"+execute_module -tool eda -args "--simulation --tool=vcs"++project_close+|]++quartusSynthConfig :: Synthesiser a => a -> FilePath -> Text -> FilePath -> Text+quartusSynthConfig q sdc top fp = [st|load_package flow++project_new -overwrite #{top}++set_global_assignment -name FAMILY "Cyclone 10 GX"+set_global_assignment -name SYSTEMVERILOG_FILE #{toTextIgnore fp}+set_global_assignment -name TOP_LEVEL_ENTITY #{top}+set_global_assignment -name SDC_FILE #{toTextIgnore sdc}+set_global_assignment -name INI_VARS "qatm_force_vqm=on;"+set_global_assignment -name NUM_PARALLEL_PROCESSORS 2+set_instance_assignment -name VIRTUAL_PIN ON -to *++execute_module -tool syn+execute_module -tool eda -args "--simulation --tool=vcs"++project_close+|]+ xstSynthConfig :: Text -> Text xstSynthConfig top = [st|run -ifn #{top}.prj -ofn #{top} -p artix7 -top #{top}@@ -77,7 +126,6 @@ -change_error_to_warning "HDLCompiler:226 HDLCompiler:1832" |] --- brittany-disable-next-binding vivadoSynthConfig :: Text -> Text -> Text vivadoSynthConfig top outf = [st| # CRITICAL WARNING: [Synth 8-5821] Potential divide by zero@@ -88,11 +136,11 @@ write_verilog -force #{outf} |] --- brittany-disable-next-binding-sbyConfig :: (Synthesiser a, Synthesiser b) => a -> b -> SourceInfo -> Text-sbyConfig sim1 sim2 (SourceInfo top _) = [st|[options]+sbyConfig :: (Synthesiser a, Synthesiser b) => FilePath -> a -> b -> SourceInfo -> Text+sbyConfig datadir sim1 sim2 (SourceInfo top _) = [st|[options] multiclock on mode prove+aigsmt z3  [engines] abc pdr@@ -115,19 +163,21 @@     depList =       T.intercalate "\n"         $   toTextIgnore-        .   (fromText "data" </>)+        .   (datadir </> fromText "data" </>)         .   fromText         <$> deps     readL = T.intercalate "\n" $ mappend "read -formal " <$> deps -icarusTestbench :: (Synthesiser a) => Verilog -> a -> Text-icarusTestbench t synth1 = [st|-`include "data/cells_cmos.v"-`include "data/cells_cyclone_v.v"-`include "data/cells_verific.v"-`include "data/cells_xilinx_7.v"-`include "data/cells_yosys.v"+icarusTestbench :: (Synthesiser a) => FilePath -> Verilog -> a -> Text+icarusTestbench datadir t synth1 = [st|+`include "#{ddir}/data/cells_cmos.v"+`include "#{ddir}/data/cells_cyclone_v.v"+`include "#{ddir}/data/cells_verific.v"+`include "#{ddir}/data/cells_xilinx_7.v"+`include "#{ddir}/data/cells_yosys.v" `include "#{toTextIgnore $ synthOutput synth1}"  #{genSource t} |]+  where+    ddir = toTextIgnore datadir
src/Verismith/Tool/Yosys.hs view
@@ -23,11 +23,14 @@ import           Control.DeepSeq           (NFData, rnf, rwhnf) import           Control.Lens import           Control.Monad             (void)+import           Data.Either               (fromRight) import           Data.Text                 (Text, unpack) import           Prelude                   hiding (FilePath)-import           Shelly-import           Shelly.Lifted             (liftSh)+import           Shelly                    (FilePath, (</>))+import qualified Shelly                    as S+import           Shelly.Lifted             (liftSh, readfile) import           Text.Shakespeare.Text     (st)+import           Verismith.CounterEg       (parseCounterEg) import           Verismith.Result import           Verismith.Tool.Internal import           Verismith.Tool.Template@@ -59,13 +62,13 @@ defaultYosys = Yosys Nothing "yosys" "syn_yosys.v"  yosysPath :: Yosys -> FilePath-yosysPath sim = maybe (fromText "yosys") (</> fromText "yosys") $ yosysBin sim+yosysPath sim = maybe (S.fromText "yosys") (</> S.fromText "yosys") $ yosysBin sim  runSynthYosys :: Yosys -> SourceInfo -> ResultSh () runSynthYosys sim (SourceInfo _ src) = do     dir <- liftSh $ do-        dir' <- pwd-        writefile inpf $ genSource src+        dir' <- S.pwd+        S.writefile inpf $ genSource src         return dir'     execute_         SynthFail@@ -77,8 +80,8 @@         ]   where     inpf = "rtl.v"-    inp  = toTextIgnore inpf-    out  = toTextIgnore $ synthOutput sim+    inp  = S.toTextIgnore inpf+    out  = S.toTextIgnore $ synthOutput sim  runEquivYosys     :: (Synthesiser a, Synthesiser b)@@ -89,24 +92,24 @@     -> ResultSh () runEquivYosys yosys sim1 sim2 srcInfo = do     liftSh $ do-        writefile "top.v"+        S.writefile "top.v"             .  genSource             .  initMod             .  makeTop 2             $  srcInfo             ^. mainModule-        writefile checkFile $ yosysSatConfig sim1 sim2 srcInfo+        S.writefile checkFile $ yosysSatConfig sim1 sim2 srcInfo     runSynth sim1 srcInfo     runSynth sim2 srcInfo-    liftSh $ run_ (yosysPath yosys) [toTextIgnore checkFile]-    where checkFile = fromText [st|test.#{toText sim1}.#{toText sim2}.ys|]+    liftSh $ S.run_ (yosysPath yosys) [S.toTextIgnore checkFile]+    where checkFile = S.fromText [st|test.#{toText sim1}.#{toText sim2}.ys|]  runEquiv-    :: (Synthesiser a, Synthesiser b) => a -> b -> SourceInfo -> ResultSh ()-runEquiv sim1 sim2 srcInfo = do-    dir <- liftSh pwd+    :: (Synthesiser a, Synthesiser b) => FilePath -> a -> b -> SourceInfo -> ResultSh ()+runEquiv datadir sim1 sim2 srcInfo = do+    dir <- liftSh S.pwd     liftSh $ do-        writefile "top.v"+        S.writefile "top.v"             .  genSource             .  initMod             .  makeTopAssert@@ -114,14 +117,15 @@             ^. mainModule         replaceMods (synthOutput sim1) "_1" srcInfo         replaceMods (synthOutput sim2) "_2" srcInfo-        writefile "proof.sby" $ sbyConfig sim1 sim2 srcInfo+        S.writefile "proof.sby" $ sbyConfig datadir sim1 sim2 srcInfo     e <- liftSh $ do         exe dir "symbiyosys" "sby" ["-f", "proof.sby"]-        lastExitCode+        S.lastExitCode     case e of         0   -> ResultT . return $ Pass ()-        2   -> ResultT . return $ Fail EquivFail+        2   -> ResultT $ Fail . EquivFail . fromRight mempty+                       . parseCounterEg <$> readfile "proof/engine_0/trace.smtc"         124 -> ResultT . return $ Fail TimeoutError         _   -> ResultT . return $ Fail EquivError   where-    exe dir name e = void . errExit False . logCommand dir name . timeout e+    exe dir name e = void . S.errExit False . logCommand dir name . timeout e
src/Verismith/Verilog/AST.hs view
@@ -524,6 +524,12 @@                              }                   deriving (Eq, Show, Ord, Data, Generic, NFData) +instance Semigroup SourceInfo where+    (SourceInfo t v) <> (SourceInfo _ v2) = SourceInfo t $ v <> v2++instance Monoid SourceInfo where+    mempty = SourceInfo mempty mempty+ $(makeLenses ''Expr) $(makeLenses ''ConstExpr) $(makeLenses ''Task)
src/Verismith/Verilog/Mutate.hs view
@@ -115,7 +115,7 @@     mutExpr f (TaskEnable a)     = TaskEnable $ mutExpr f a     mutExpr f (SysTaskEnable a)  = SysTaskEnable $ mutExpr f a     mutExpr f (CondStmnt a b c) = CondStmnt (f a) (mutExpr f <$> b) $ mutExpr f <$> c-    mutExpr f (ForLoop a1 e a2 s) = ForLoop (mutExpr f a1) (f e) (mutExpr f a2) $ mutExpr f s+    mutExpr f (ForLoop a1 e a2 s) = ForLoop a1 e a2 $ mutExpr f s  instance Mutate Parameter where     mutExpr _ = id@@ -244,7 +244,7 @@             ^.. modItems             .   traverse             .   modInstId-    conns = ModConn . Id <$> allVars m+    conns = uncurry ModConnNamed . fmap Id <$> zip (allVars m) (allVars m)  -- | Instantiate without adding wire declarations. It also does not count the -- current instantiations of the same module.
test/Parser.hs view
@@ -17,10 +17,10 @@ where  import           Control.Lens-import           Data.Either              (either, isRight)-import           Hedgehog                 (Gen, Property, (===))-import qualified Hedgehog                 as Hog-import qualified Hedgehog.Gen             as Hog+import           Data.Either                  (either, isRight)+import           Hedgehog                     (Gen, Property, (===))+import qualified Hedgehog                     as Hog+import qualified Hedgehog.Gen                 as Hog import           Test.Tasty import           Test.Tasty.Hedgehog import           Test.Tasty.HUnit@@ -29,6 +29,7 @@ import           Verismith.Internal import           Verismith.Verilog.Lex import           Verismith.Verilog.Parser+import           Verismith.Verilog.Preprocess (uncomment)  smallConfig :: Config smallConfig = defaultConfig & configProperty . propSize .~ 5@@ -38,11 +39,10 @@  parserInputMod :: Property parserInputMod = Hog.property $ do-    v <- Hog.forAll randomMod'+    v <- GenVerilog <$> Hog.forAll randomMod'     Hog.assert . isRight $ parse parseModDecl                                  "input_test_mod"-                                 (alexScanTokens $ str v)-    where str = show . GenVerilog+                                 (alexScanTokens . uncomment "test" $ show v)  parserIdempotentMod :: Property parserIdempotentMod = Hog.property $ do@@ -58,11 +58,10 @@  parserInput :: Property parserInput = Hog.property $ do-    v <- Hog.forAll (procedural "top" smallConfig)+    v <- Hog.forAll (GenVerilog <$> procedural "top" smallConfig)     Hog.assert . isRight $ parse parseModDecl                                  "input_test"-                                 (alexScanTokens $ str v)-    where str = show . GenVerilog+                                 (alexScanTokens . uncomment "test" $ show v)  parserIdempotent :: Property parserIdempotent = Hog.property $ do
test/Reduce.hs view
@@ -36,7 +36,37 @@     , removeDeclTest     ] --- brittany-disable-next-binding+removeConstInConcatTest :: TestTree+removeConstInConcatTest = testCase "Remove const in concat" $ do+    GenVerilog (removeDecl srcInfo1) @?= golden1+  where+    srcInfo1 = SourceInfo "top" [verilog|+module top;+  wire a;+  reg b;++  assign a = {1'b0, 1'b0, 1'b0, (1'b0), b, (1'b0), (1'b0)};++  always @(posedge clk) begin+    if (a)+      b <= 1 + 5 + {1'b0, 1'b1, 5'h20, b, 2'b0};+  end+endmodule+|]+    golden1 = GenVerilog $ SourceInfo "top" [verilog|+module top;+  wire a;+  reg b;++  assign a = {b};++  always @(posedge clk) begin+    if (a)+      b <= 1 + 5 + {b};+  end+endmodule+|]+ removeDeclTest :: TestTree removeDeclTest = testCase "Remove declarations" $ do     GenVerilog (removeDecl srcInfo1) @?= golden1@@ -95,7 +125,6 @@ endmodule |] --- brittany-disable-next-binding cleanAllTest :: TestTree cleanAllTest = testCase "Clean all" $ do     GenVerilog (cleanSourceInfoAll srcInfo1) @?= golden1@@ -157,7 +186,6 @@ endmodule |] --- brittany-disable-next-binding cleanTest :: TestTree cleanTest = testCase "Clean expression" $ do     clean ["wire1", "wire2"] srcInfo1 @?= golden1@@ -197,7 +225,6 @@ |]  --- brittany-disable-next-binding activeWireTest :: TestTree activeWireTest = testCase "Active wires" $ do     findActiveWires "top" verilog1 \\ ["x", "y", "z", "w"]          @?= []@@ -271,7 +298,6 @@ endmodule |] --- brittany-disable-next-binding halveStatementsTest :: TestTree halveStatementsTest = testCase "Statements" $ do     GenVerilog <$> halveStatements "top" srcInfo1 @?= golden1@@ -336,7 +362,6 @@ endmodule |]) --- brittany-disable-next-binding modItemReduceTest :: TestTree modItemReduceTest = testCase "Module items" $ do     GenVerilog <$> halveModItems "top" srcInfo1 @?= golden1@@ -372,7 +397,6 @@ endmodule |]) --- brittany-disable-next-binding statementReducerTest :: TestTree statementReducerTest = testCase "Statement reducer" $ do     GenVerilog <$> halveStatements "top" srcInfo1 @?= fmap GenVerilog golden1@@ -460,7 +484,6 @@ endmodule |] --- brittany-disable-next-binding moduleReducerTest :: TestTree moduleReducerTest = testCase "Module reducer" $ do     halveModules srcInfo1 @?= golden1
verismith.cabal view
@@ -1,5 +1,5 @@ name: verismith-version: 0.4.0.1+version: 0.5.0.0 synopsis: Random verilog generation and simulator testing. description:   Verismith provides random verilog generation modules@@ -14,11 +14,11 @@ build-type: Custom cabal-version: >=1.10 extra-source-files: README.md-                  , data/*.v                   , examples/*.v                   , examples/config.toml                   , scripts/*.py                   , scripts/*.sh+data-files: data/*.v  source-repository head   type:     git@@ -27,7 +27,7 @@ source-repository this   type:     git   location: https://github.com/ymherklotz/verismith-  tag:      v0.4.0.0+  tag:      v0.5.0.0  custom-setup   setup-depends:@@ -47,9 +47,11 @@                  , Verismith.Circuit.Internal                  , Verismith.Circuit.Random                  , Verismith.Config+                 , Verismith.CounterEg                  , Verismith.Fuzz                  , Verismith.Generate                  , Verismith.Internal+                 , Verismith.OptParser                  , Verismith.Reduce                  , Verismith.Report                  , Verismith.Result@@ -58,6 +60,7 @@                  , Verismith.Tool.Identity                  , Verismith.Tool.Internal                  , Verismith.Tool.Quartus+                 , Verismith.Tool.QuartusLight                  , Verismith.Tool.Template                  , Verismith.Tool.Vivado                  , Verismith.Tool.XST@@ -74,42 +77,41 @@                  , Verismith.Verilog.Preprocess                  , Verismith.Verilog.Quote                  , Verismith.Verilog.Token-  build-depends: base >=4.7 && <5-               -- Cannot upgrade to 1.0 because of missing MonadGen instance for-               -- StateT.-               , hedgehog >=1.0 && <1.2+  build-depends: DRBG >=0.5 && <0.6+               , array >=0.5 && <0.6+               , base >=4.7 && <5+               , binary >= 0.8.5.1 && <0.9+               , blaze-html >=0.9.0.1 && <0.10+               , bytestring >=0.10 && <0.11+               , cryptonite >=0.25 && <0.26+               , deepseq >= 1.4.3.0 && <1.5+               , exceptions >=0.10.0 && <0.11                , fgl >=5.6 && <5.8                , fgl-visualize >=0.1 && <0.2+               , filepath >=1.4.2 && <1.5+               , gitrev >= 1.3.1 && <1.4+               , hedgehog >=1.0 && <1.2                , lens >=4.16.1 && <4.18+               , lifted-base >=0.2.3 && <0.3+               , memory >=0.14 && <0.15+               , monad-control >=1.0.2 && <1.1+               , mtl >=2.2.2 && <2.3+               , optparse-applicative >=0.14 && <0.15+               , parsec >=3.1 && <3.2+               , prettyprinter >=1.2.0.1 && <1.3                , random >=1.1 && <1.2+               , recursion-schemes >=5.0.2 && <5.2                , shakespeare >=2 && <2.1                , shelly >=1.8.0 && <1.9+               , statistics >=0.14.0.2 && <0.16+               , template-haskell >=2.13.0 && <2.15                , text >=1.2 && <1.3-               , bytestring >=0.10 && <0.11-               , filepath >=1.4.2 && <1.5-               , binary >= 0.8.5.1 && <0.9-               , cryptonite >=0.25 && <0.26-               , memory >=0.14 && <0.15-               , DRBG >=0.5 && <0.6-               , parsec >=3.1 && <3.2+               , time >= 1.8.0.2 && <1.9+               , tomland >=1.0 && <1.2                , transformers >=0.5 && <0.6                , transformers-base >=0.4.5 && <0.5-               , tomland >=1.0 && <1.2-               , prettyprinter >=1.2.0.1 && <1.3-               , array >=0.5 && <0.6-               , recursion-schemes >=5.0.2 && <5.2-               , time >= 1.8.0.2 && <1.9-               , lifted-base >=0.2.3 && <0.3-               , monad-control >=1.0.2 && <1.1-               , gitrev >= 1.3.1 && <1.4-               , deepseq >= 1.4.3.0 && <1.5-               , template-haskell >=2.13.0 && <2.15-               , optparse-applicative >=0.14 && <0.15-               , exceptions >=0.10.0 && <0.11-               , blaze-html >=0.9.0.1 && <0.10-               , statistics >=0.14.0.2 && <0.16-               , vector >=0.12.0.1 && <0.13                , unordered-containers >=0.2.10 && <0.3+               , vector >=0.12.0.1 && <0.13   default-extensions: OverloadedStrings  executable verismith@@ -144,14 +146,14 @@   build-depends: base >=4 && <5                , verismith                , fgl >=5.6 && <5.8-               , tasty >=1.0.1.1 && <1.3-               , tasty-hunit >=0.10 && <0.11-               , tasty-hedgehog >=1.0 && <1.1                , hedgehog >=1.0 && <1.2                , lens >=4.16.1 && <4.18+               , parsec >= 3.1 && < 3.2                , shakespeare >=2 && <2.1+               , tasty >=1.0.1.1 && <1.3+               , tasty-hedgehog >=1.0 && <1.1+               , tasty-hunit >=0.10 && <0.11                , text >=1.2 && <1.3-               , parsec >= 3.1 && < 3.2   default-extensions: OverloadedStrings  --test-suite doctest