aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/Verismith/Config.hs53
-rw-r--r--src/Verismith/Generate.hs130
-rw-r--r--src/Verismith/Verilog/Mutate.hs4
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