diff options
-rw-r--r-- | src/Verismith/Config.hs | 53 | ||||
-rw-r--r-- | src/Verismith/Generate.hs | 130 | ||||
-rw-r--r-- | src/Verismith/Verilog/Mutate.hs | 4 |
3 files changed, 112 insertions, 75 deletions
diff --git a/src/Verismith/Config.hs b/src/Verismith/Config.hs index decf1fb..bf79683 100644 --- a/src/Verismith/Config.hs +++ b/src/Verismith/Config.hs @@ -291,31 +291,46 @@ defaultConfig :: Config defaultConfig = Config (Info (pack $(gitHash)) (pack $ showVersion version)) (Probability defModItem defStmnt defExpr) - (ConfProperty 20 Nothing 3 2 5 "random" 10 False 0 1) + defProperty [] [fromYosys defaultYosys, fromVivado defaultVivado] where defModItem = - ProbModItem 5 -- Assign - 1 -- Sequential Always - 1 -- Combinational Always - 1 -- Instantiation + ProbModItem { _probModItemAssign = 5 + , _probModItemSeqAlways = 1 + , _probModItemCombAlways = 0 + , _probModItemInst = 1 + } defStmnt = - ProbStatement 0 -- Blocking assignment - 3 -- Non-blocking assignment - 1 -- Conditional - 0 -- For loop + ProbStatement { _probStmntBlock = 0 + , _probStmntNonBlock = 3 + , _probStmntCond = 1 + , _probStmntFor = 0 + } defExpr = - ProbExpr 1 -- Number - 5 -- Identifier - 5 -- Range selection - 5 -- Unary operator - 5 -- Binary operator - 5 -- Ternary conditional - 3 -- Concatenation - 0 -- String - 5 -- Signed function - 5 -- Unsigned funtion + ProbExpr { _probExprNum = 1 + , _probExprId = 5 + , _probExprRangeSelect = 5 + , _probExprUnOp = 5 + , _probExprBinOp = 5 + , _probExprCond = 5 + , _probExprConcat = 3 + , _probExprStr = 0 + , _probExprSigned = 5 + , _probExprUnsigned = 5 + } + defProperty = + ConfProperty { _propSize = 20 + , _propSeed = Nothing + , _propStmntDepth = 3 + , _propModDepth = 2 + , _propMaxModules = 5 + , _propSampleMethod = "random" + , _propSampleSize = 10 + , _propCombine = False + , _propNonDeterminism = 0 + , _propDeterminism = 1 + } twoKey :: Toml.Piece -> Toml.Piece -> Toml.Key twoKey a b = Toml.Key (a :| [b]) diff --git a/src/Verismith/Generate.hs b/src/Verismith/Generate.hs index ff20f05..8dba3fa 100644 --- a/src/Verismith/Generate.hs +++ b/src/Verismith/Generate.hs @@ -81,19 +81,34 @@ import Verismith.Verilog.Eval import Verismith.Verilog.Internal import Verismith.Verilog.Mutate -data Context = Context { _variables :: [Port] - , _parameters :: [Parameter] - , _modules :: [ModDecl] - , _nameCounter :: {-# UNPACK #-} !Int - , _stmntDepth :: {-# UNPACK #-} !Int - , _modDepth :: {-# UNPACK #-} !Int - , _determinism :: !Bool +data PortInfo = PortInfo { _portInfoPort :: {-# UNPACK #-} !Port + , _portInfoDet :: !Bool + } + +$(makeLenses ''PortInfo) + +data Context = Context { _contextVariables :: ![PortInfo] + , _contextParameters :: ![Parameter] + , _contextModules :: ![ModDecl] + , _contextNameCounter :: {-# UNPACK #-} !Int + , _contextStmntDepth :: {-# UNPACK #-} !Int + , _contextModDepth :: {-# UNPACK #-} !Int + , _contextDeterminism :: !Bool } -makeLenses ''Context +$(makeLenses ''Context) type StateGen = ReaderT Config (GenT (State Context)) +fromPort :: Port -> PortInfo +fromPort p = PortInfo p True + +portsFromContext :: Traversal' Context Port +portsFromContext = contextVariables . traverse . portInfoPort + +_portsFromContext :: Context -> [Port] +_portsFromContext c = c ^.. contextVariables . traverse . portInfoPort + toId :: Int -> Identifier toId = Identifier . ("w" <>) . T.pack . show @@ -105,9 +120,21 @@ toPort ident = do sumSize :: [Port] -> Range sumSize ps = sum $ ps ^.. traverse . portSize +legacySafeProb = ProbExpr { _probExprNum = 1 + , _probExprId = 1 + , _probExprRangeSelect = 0 + , _probExprUnOp = 1 + , _probExprBinOp = 1 + , _probExprCond = 1 + , _probExprConcat = 0 + , _probExprStr = 0 + , _probExprSigned = 1 + , _probExprUnsigned = 1 + } + random :: (MonadGen m) => [Port] -> (Expr -> ContAssign) -> m ModItem random ctx fun = do - expr <- Hog.sized (exprWithContext (ProbExpr 1 1 0 1 1 1 1 0 1 1) [] ctx) + expr <- Hog.sized (exprWithContext legacySafeProb [] ctx) return . ModCA $ fun expr --randomAssigns :: [Identifier] -> [Gen ModItem] @@ -222,13 +249,13 @@ constExprWithContext ps prob size | size == 0 = Hog.frequency [ (prob ^. probExprNum, ConstNum <$> genBitVec) , ( if null ps then 0 else prob ^. probExprId - , ParamId . view paramIdent <$> Hog.element ps + , ParamId . _paramIdent <$> Hog.element ps ) ] | size > 0 = Hog.frequency [ (prob ^. probExprNum, ConstNum <$> genBitVec) , ( if null ps then 0 else prob ^. probExprId - , ParamId . view paramIdent <$> Hog.element ps + , ParamId . _paramIdent <$> Hog.element ps ) , (prob ^. probExprUnOp, ConstUnOp <$> unOp <*> subexpr 2) , ( prob ^. probExprBinOp @@ -286,11 +313,11 @@ exprWithContext prob ps [] n | n == 0 = Hog.frequency $ exprSafeList prob exprWithContext prob ps l n | n == 0 = Hog.frequency - $ (prob ^. probExprId, Id . fromPort <$> Hog.element l) + $ (prob ^. probExprId, Id . _portName <$> Hog.element l) : exprSafeList prob | n > 0 = Hog.frequency - $ (prob ^. probExprId , Id . fromPort <$> Hog.element l) + $ (prob ^. probExprId , Id . _portName <$> Hog.element l) : (prob ^. probExprRangeSelect, rangeSelect ps l) : exprRecList prob subexpr | otherwise @@ -309,8 +336,8 @@ someI m f = do makeIdentifier :: T.Text -> StateGen Identifier makeIdentifier prefix = do context <- get - let ident = Identifier $ prefix <> showT (context ^. nameCounter) - nameCounter += 1 + let ident = Identifier $ prefix <> showT (context ^. contextNameCounter) + contextNameCounter += 1 return ident getPort' :: PortType -> Identifier -> [Port] -> StateGen Port @@ -328,7 +355,7 @@ nextPort :: PortType -> StateGen Port nextPort pt = do context <- get ident <- makeIdentifier . T.toLower $ showT pt - getPort' pt ident (_variables context) + getPort' pt ident (_portsFromContext context) -- | Creates a new port based on the current name counter and adds it to the -- current context. @@ -365,9 +392,9 @@ assignment = do -- | Generate a random 'Statement' safely, by also increasing the depth counter. seqBlock :: StateGen Statement seqBlock = do - stmntDepth -= 1 + contextStmntDepth -= 1 tstat <- SeqBlock <$> someI 20 statement - stmntDepth += 1 + contextStmntDepth += 1 return tstat -- | Generate a random conditional 'Statement'. The nameCounter is reset between @@ -377,13 +404,13 @@ seqBlock = do conditional :: StateGen Statement conditional = do expr <- scopedExpr - nc <- _nameCounter <$> get + nc <- _contextNameCounter <$> get tstat <- seqBlock - nc' <- _nameCounter <$> get - nameCounter .= nc + nc' <- _contextNameCounter <$> get + contextNameCounter .= nc fstat <- seqBlock - nc'' <- _nameCounter <$> get - nameCounter .= max nc' nc'' + nc'' <- _contextNameCounter <$> get + contextNameCounter .= max nc' nc'' return $ CondStmnt expr (Just tstat) (Just fstat) -- | Generate a random for loop by creating a new variable name for the counter @@ -410,7 +437,7 @@ statement = do , (onDepth cont (defProb probStmntCond), conditional) , (onDepth cont (defProb probStmntFor) , forLoop) ] - where onDepth c n = if c ^. stmntDepth > 0 then n else 0 + where onDepth c n = if c ^. contextStmntDepth > 0 then n else 0 -- | Generate a sequential always block which is dependent on the clock. alwaysSeq :: StateGen ModItem @@ -419,12 +446,11 @@ alwaysSeq = Always . EventCtrl (EPosEdge "clk") . Just <$> seqBlock -- | Should resize a port that connects to a module port if the latter is -- larger. This should not cause any problems if the same net is used as input -- multiple times, and is resized multiple times, as it should only get larger. -resizePort :: [Parameter] -> Identifier -> Range -> [Port] -> [Port] -resizePort ps i ra = foldl' func [] +resizePort :: [Parameter] -> Identifier -> Range -> Port -> Port +resizePort ps i ra p@(Port t _ ri i') + | i' == i && calc ri < calc ra = (p & portSize .~ ra) + | otherwise = p where - func l p@(Port t _ ri i') - | i' == i && calc ri < calc ra = (p & portSize .~ ra) : l - | otherwise = p : l calc = calcRange ps $ Just 64 -- | Instantiate a module, where the outputs are new nets that are created, and @@ -442,7 +468,7 @@ instantiate (ModDecl i outP inP _ _) = do insLit <- replicateM (length inpFixed - length ins) (Number <$> genBitVec) mapM_ (uncurry process) . zip (ins ^.. traverse . portName) $ inpFixed ^.. traverse . portSize ident <- makeIdentifier "modinst" - vs <- view variables <$> get + vs <- _portsFromContext <$> get Hog.choice [ return . ModInst i ident $ ModConn <$> (toE (outs <> clkPort <> ins) <> insLit) , ModInst i ident <$> Hog.shuffle @@ -450,14 +476,14 @@ instantiate (ModDecl i outP inP _ _) = do (toE (outs <> clkPort <> ins) <> insLit)) ] where - toE ins = Id . view portName <$> ins + toE ins = Id . _portName <$> ins (inpFixed, clkPort) = partition filterFunc inP filterFunc (Port _ _ _ n) | n == "clk" = False | otherwise = True process p r = do - params <- view parameters <$> get - variables %= resizePort params p r + params <- _contextParameters <$> get + portsFromContext %= resizePort params p r -- | Generates a module instance by also generating a new module if there are -- not enough modules currently in the context. It keeps generating new modules @@ -483,24 +509,24 @@ modInst = do prob <- ask context <- get let maxMods = prob ^. configProperty . propMaxModules - if length (context ^. modules) < maxMods + if length (_contextModules context) < maxMods then do - let currMods = context ^. modules - let params = context ^. parameters - let vars = context ^. variables - modules .= [] - variables .= [] - parameters .= [] - modDepth -= 1 + let currMods = _contextModules context + let params = _contextParameters context + let vars = _contextVariables context + contextModules .= [] + contextVariables .= [] + contextParameters .= [] + contextModDepth -= 1 chosenMod <- moduleDef Nothing ncont <- get - let genMods = ncont ^. modules - modDepth += 1 - parameters .= params - variables .= vars - modules .= chosenMod : currMods <> genMods + let genMods = _contextModules ncont + contextModDepth += 1 + contextParameters .= params + contextVariables .= vars + contextModules .= chosenMod : currMods <> genMods instantiate chosenMod - else Hog.element (context ^. modules) >>= instantiate + else Hog.element (_contextModules context) >>= instantiate -- | Generate a random module item. modItem :: StateGen ModItem @@ -511,16 +537,16 @@ modItem = do let defProb i = prob ^. probModItem . i det <- Hog.frequency [ (conf ^. configProperty . propDeterminism, return True) , (conf ^. configProperty . propNonDeterminism, return False) ] - determinism .= det + contextDeterminism .= det Hog.frequency [ (defProb probModItemAssign , ModCA <$> contAssign) , (defProb probModItemSeqAlways, alwaysSeq) - , ( if context ^. modDepth > 0 then defProb probModItemInst else 0 + , ( if context ^. contextModDepth > 0 then defProb probModItemInst else 0 , modInst ) ] -- | Either return the 'Identifier' that was passed to it, or generate a new --- 'Identifier' based on the current 'nameCounter'. +-- 'Identifier' based on the current 'contextNameCounter'. moduleName :: Maybe Identifier -> StateGen Identifier moduleName (Just t) = return t moduleName Nothing = makeIdentifier "module" @@ -541,7 +567,7 @@ parameter = do ident <- makeIdentifier "param" cexpr <- constExpr let param = Parameter ident cexpr - parameters %= (param :) + contextParameters %= (param :) return param -- | Evaluate a range to an integer, and cast it back to a range. @@ -575,7 +601,7 @@ moduleDef top = do let (newPorts, local) = partition (`identElem` portList) $ _variables context let size = - evalRange (_parameters context) 32 + evalRange (_contextParameters context) 32 . sum $ local ^.. traverse diff --git a/src/Verismith/Verilog/Mutate.hs b/src/Verismith/Verilog/Mutate.hs index 2f17de5..44a502a 100644 --- a/src/Verismith/Verilog/Mutate.hs +++ b/src/Verismith/Verilog/Mutate.hs @@ -36,7 +36,6 @@ module Verismith.Verilog.Mutate , combineAssigns , combineAssigns_ , declareMod - , fromPort ) where @@ -396,6 +395,3 @@ combineAssigns_ comb p ps = <$> ps ^.. traverse . portName - -fromPort :: Port -> Identifier -fromPort (Port _ _ _ i) = i |