From e200500f6a43d0ed48b194f9fc397fd32e9ce3e2 Mon Sep 17 00:00:00 2001 From: Yann Herklotz Date: Fri, 26 Jul 2019 11:43:10 +0200 Subject: Add non determinism probability to generation --- default.nix | 2 +- src/VeriFuzz/Config.hs | 46 ++++++++++++++++++++++++++++++++++++--------- src/VeriFuzz/Verilog/Gen.hs | 39 +++++++++++++++++++++++--------------- verifuzz.cabal | 2 ++ 4 files changed, 64 insertions(+), 25 deletions(-) diff --git a/default.nix b/default.nix index e034ece..db81294 100644 --- a/default.nix +++ b/default.nix @@ -9,7 +9,7 @@ }: mkDerivation { pname = "verifuzz"; - version = "0.3.0.0"; + version = "0.3.1.0"; src = ./.; isLibrary = true; isExecutable = true; diff --git a/src/VeriFuzz/Config.hs b/src/VeriFuzz/Config.hs index dab854b..8705f7c 100644 --- a/src/VeriFuzz/Config.hs +++ b/src/VeriFuzz/Config.hs @@ -69,6 +69,8 @@ module VeriFuzz.Config , propModDepth , propMaxModules , propCombine + , propDeterminism + , propNonDeterminism , parseConfigFile , parseConfig , encodeConfig @@ -192,14 +194,36 @@ data Probability = Probability { _probModItem :: {-# UNPACK #-} !ProbModItem } deriving (Eq, Show) -data ConfProperty = ConfProperty { _propSize :: {-# UNPACK #-} !Int - , _propSeed :: !(Maybe Seed) - , _propStmntDepth :: {-# UNPACK #-} !Int - , _propModDepth :: {-# UNPACK #-} !Int - , _propMaxModules :: {-# UNPACK #-} !Int - , _propSampleMethod :: !Text - , _propSampleSize :: {-# UNPACK #-} !Int - , _propCombine :: !Bool +data ConfProperty = ConfProperty { _propSize :: {-# UNPACK #-} !Int + -- ^ The size of the generated Verilog. + , _propSeed :: !(Maybe Seed) + -- ^ A possible seed that could be used to + -- generate the same Verilog. + , _propStmntDepth :: {-# UNPACK #-} !Int + -- ^ The maximum statement depth that should be + -- reached. + , _propModDepth :: {-# UNPACK #-} !Int + -- ^ The maximium module depth that should be + -- reached. + , _propMaxModules :: {-# UNPACK #-} !Int + -- ^ The maximum number of modules that are + -- allowed to be created at each level. + , _propSampleMethod :: !Text + -- ^ The sampling method that should be used to + -- generate specific distributions of random + -- programs. + , _propSampleSize :: {-# UNPACK #-} !Int + -- ^ The number of samples to take for the + -- sampling method. + , _propCombine :: !Bool + -- ^ If the output should be combined into one + -- bit or not. + , _propNonDeterminism :: {-# UNPACK #-} !Int + -- ^ The frequency at which nondeterminism + -- should be generated. + , _propDeterminism :: {-# UNPACK #-} !Int + -- ^ The frequency at which determinism should + -- be generated. } deriving (Eq, Show) @@ -267,7 +291,7 @@ defaultConfig :: Config defaultConfig = Config (Info (pack $(gitHash)) (pack $ showVersion version)) (Probability defModItem defStmnt defExpr) - (ConfProperty 20 Nothing 3 2 5 "random" 10 False) + (ConfProperty 20 Nothing 3 2 5 "random" 10 False 0 1) [] [fromYosys defaultYosys, fromVivado defaultVivado] where @@ -388,6 +412,10 @@ propCodec = <*> defaultValue (defProp propCombine) (Toml.bool (twoKey "output" "combine")) .= _propCombine + <*> defaultValue (defProp propNonDeterminism) (Toml.int "nondeterminism") + .= _propNonDeterminism + <*> defaultValue (defProp propDeterminism) (Toml.int "determinism") + .= _propDeterminism where defProp i = defaultConfig ^. configProperty . i simulator :: TomlCodec SimDescription diff --git a/src/VeriFuzz/Verilog/Gen.hs b/src/VeriFuzz/Verilog/Gen.hs index 6ba79ea..e037b67 100644 --- a/src/VeriFuzz/Verilog/Gen.hs +++ b/src/VeriFuzz/Verilog/Gen.hs @@ -54,6 +54,7 @@ data Context = Context { _variables :: [Port] , _nameCounter :: {-# UNPACK #-} !Int , _stmntDepth :: {-# UNPACK #-} !Int , _modDepth :: {-# UNPACK #-} !Int + , _determinism :: !Bool } makeLenses ''Context @@ -312,16 +313,6 @@ conditional = do nameCounter .= max nc' nc'' return $ CondStmnt expr (Just tstat) (Just fstat) ---constToExpr :: ConstExpr -> Expr ---constToExpr (ConstNum s n ) = Number s n ---constToExpr (ParamId i ) = Id i ---constToExpr (ConstConcat c ) = Concat $ constToExpr <$> c ---constToExpr (ConstUnOp u p ) = UnOp u (constToExpr p) ---constToExpr (ConstBinOp a b c) = BinOp (constToExpr a) b (constToExpr c) ---constToExpr (ConstCond a b c) = --- Cond (constToExpr a) (constToExpr b) (constToExpr c) ---constToExpr (ConstStr s) = Str s - forLoop :: StateGen Statement forLoop = do num <- Hog.int (Hog.linear 0 20) @@ -435,21 +426,27 @@ modInst = do -- | Generate a random module item. modItem :: StateGen ModItem modItem = do - prob <- askProbability + conf <- lift ask + let prob = conf ^. configProbability context <- get let defProb i = prob ^. probModItem . i + det <- Hog.frequency [ (conf ^. configProperty . propDeterminism, return True) + , (conf ^. configProperty . propNonDeterminism, return False) ] + determinism .= det Hog.frequency [ (defProb probModItemAssign , ModCA <$> contAssign) , (defProb probModItemSeqAlways, alwaysSeq) , ( if context ^. modDepth > 0 then defProb probModItemInst else 0 - , modInst - ) + , modInst ) ] +-- | Either return the 'Identifier' that was passed to it, or generate a new +-- 'Identifier' based on the current 'nameCounter'. moduleName :: Maybe Identifier -> StateGen Identifier moduleName (Just t) = return t moduleName Nothing = makeIdentifier "module" +-- | Generate a random 'ConstExpr' by using the current context of 'Parameters'. constExpr :: StateGen ConstExpr constExpr = do prob <- askProbability @@ -457,6 +454,9 @@ constExpr = do gen . Hog.sized $ constExprWithContext (context ^. parameters) (prob ^. probExpr) +-- | Generate a random 'Parameter' and assign it to a constant expression which +-- it will be initialised to. The assumption is that this constant expression +-- should always be able to be evaluated with the current context of parameters. parameter :: StateGen Parameter parameter = do ident <- makeIdentifier "param" @@ -470,11 +470,14 @@ evalRange :: [Parameter] -> Int -> Range -> Range evalRange ps n (Range l r) = Range (eval l) (eval r) where eval = ConstNum . cata (evaluateConst ps) . resize n +-- | Calculate a range to an int by maybe resizing the ranges to a value. calcRange :: [Parameter] -> Maybe Int -> Range -> Int calcRange ps i (Range l r) = eval l - eval r + 1 where eval a = fromIntegral . cata (evaluateConst ps) $ maybe a (`resize` a) i +-- | Filter out a port based on it's name instead of equality of the ports. This +-- is because the ports might not be equal if the sizes are being updated. identElem :: Port -> [Port] -> Bool identElem p = elem (p ^. portName) . toListOf (traverse . portName) @@ -492,7 +495,7 @@ moduleDef top = do config <- lift ask let (newPorts, local) = partition (`identElem` portList) $ _variables context let - size = + size = evalRange (_parameters context) 32 . sum $ local @@ -518,15 +521,21 @@ procedural top config = do return . Verilog $ mainMod : st ^. modules where context = - Context [] [] [] 0 (confProp propStmntDepth) $ confProp propModDepth + Context [] [] [] 0 (confProp propStmntDepth) (confProp propModDepth) True num = fromIntegral $ confProp propSize confProp i = config ^. configProperty . i +-- | Samples the 'Gen' directly to generate random 'Verilog' using the 'T.Text' as +-- the name of the main module and the configuration 'Config' to influence the +-- generation. proceduralIO :: T.Text -> Config -> IO Verilog proceduralIO t = Hog.sample . procedural t +-- | Given a 'T.Text' and a 'Config' will generate a 'SourceInfo' which has the +-- top module set to the right name. proceduralSrc :: T.Text -> Config -> Gen SourceInfo proceduralSrc t c = SourceInfo t <$> procedural t c +-- | Sampled and wrapped into a 'SourceInfo' with the given top module name. proceduralSrcIO :: T.Text -> Config -> IO SourceInfo proceduralSrcIO t c = SourceInfo t <$> proceduralIO t c diff --git a/verifuzz.cabal b/verifuzz.cabal index aa64717..b939034 100644 --- a/verifuzz.cabal +++ b/verifuzz.cabal @@ -62,6 +62,8 @@ library , VeriFuzz.Verilog.Quote , VeriFuzz.Verilog.Token build-depends: base >=4.7 && <5 + -- Cannot upgrade to 1.0 because of missing MonadGen instance for + -- StateT. , hedgehog >= 0.5.3 && <0.7 , fgl >=5.6 && <5.8 , fgl-visualize >=0.1 && <0.2 -- cgit