From 6bcdac596fab6e989c999d63ba3f0ad09532989c Mon Sep 17 00:00:00 2001 From: Yann Herklotz Date: Fri, 12 Apr 2019 17:16:42 +0100 Subject: Add for loop to design --- src/VeriFuzz/Config.hs | 6 +- src/VeriFuzz/Verilog/AST.hs | 10 +-- src/VeriFuzz/Verilog/CodeGen.hs | 18 ++--- src/VeriFuzz/Verilog/Gen.hs | 147 +++++++++++++++++++++++++++++++--------- 4 files changed, 135 insertions(+), 46 deletions(-) (limited to 'src') diff --git a/src/VeriFuzz/Config.hs b/src/VeriFuzz/Config.hs index 8b48995..66c5aa2 100644 --- a/src/VeriFuzz/Config.hs +++ b/src/VeriFuzz/Config.hs @@ -39,6 +39,7 @@ module VeriFuzz.Config , probStmntBlock , probStmntNonBlock , probStmntCond + , probStmntFor , propSize , propSeed , propStmntDepth @@ -81,6 +82,7 @@ data ProbModItem = ProbModItem { _probModItemAssign :: {-# UNPACK #-} !Int data ProbStatement = ProbStatement { _probStmntBlock :: {-# UNPACK #-} !Int , _probStmntNonBlock :: {-# UNPACK #-} !Int , _probStmntCond :: {-# UNPACK #-} !Int + , _probStmntFor :: {-# UNPACK #-} !Int } deriving (Eq, Show) @@ -122,7 +124,7 @@ defaultConfig = Config (Probability defModItem defStmnt defExpr) (Property 20 Nothing 3 2 5) where defModItem = ProbModItem 5 1 1 - defStmnt = ProbStatement 5 5 1 + defStmnt = ProbStatement 5 5 1 1 defExpr = ProbExpr 1 1 1 1 1 1 0 1 1 twoKey :: Toml.Piece -> Toml.Piece -> Toml.Key @@ -165,6 +167,8 @@ stmntCodec = .= _probStmntNonBlock <*> defaultValue (defProb probStmntCond) (intS "conditional") .= _probStmntCond + <*> defaultValue (defProb probStmntFor) (intS "forloop") + .= _probStmntFor where defProb i = defaultConfig ^. configProbability . probStmnt . i intS = int "statement" diff --git a/src/VeriFuzz/Verilog/AST.hs b/src/VeriFuzz/Verilog/AST.hs index 8ed0254..007b3b5 100644 --- a/src/VeriFuzz/Verilog/AST.hs +++ b/src/VeriFuzz/Verilog/AST.hs @@ -48,6 +48,7 @@ module VeriFuzz.Verilog.AST , Port(..) , portType , portSigned + , portSizeLower , portSize , portName -- * Expression @@ -351,10 +352,11 @@ data PortType = Wire -- -- This is now implemented inside 'ModDecl' itself, which uses a list of output -- and input ports. -data Port = Port { _portType :: !PortType - , _portSigned :: !Bool - , _portSize :: {-# UNPACK #-} !Int - , _portName :: {-# UNPACK #-} !Identifier +data Port = Port { _portType :: !PortType + , _portSigned :: !Bool + , _portSizeLower :: {-# UNPACK #-} !Int + , _portSize :: {-# UNPACK #-} !Int + , _portName :: {-# UNPACK #-} !Identifier } deriving (Eq, Show, Ord, Data) -- | This is currently a type because direct module declaration should also be diff --git a/src/VeriFuzz/Verilog/CodeGen.hs b/src/VeriFuzz/Verilog/CodeGen.hs index 53af0d1..3a8d14a 100644 --- a/src/VeriFuzz/Verilog/CodeGen.hs +++ b/src/VeriFuzz/Verilog/CodeGen.hs @@ -91,13 +91,11 @@ modPort p = p ^. portName . getIdentifier -- | Generate the 'Port' description. port :: Port -> Text -port p = t <> sign <> size <> name +port (Port tp sgn low sz (Identifier name)) = t <> sign <> size <> name where - t = flip mappend " " . pType $ p ^. portType - size | p ^. portSize > 1 = "[" <> showT (p ^. portSize - 1) <> ":0] " - | otherwise = "" - name = p ^. portName . getIdentifier - sign = signed $ p ^. portSigned + t = flip mappend " " $ pType tp + size = "[" <> showT (low+sz-1) <> ":" <> showT low <> "] " + sign = signed sgn signed :: Bool -> Text signed True = "signed " @@ -116,9 +114,11 @@ moduleItem (ModInst (Identifier i) (Identifier name) conn) = i <> " " <> name <> "(" <> comma (mConn <$> conn) <> ")" <> ";\n" moduleItem (Initial stat) = "initial " <> statement stat moduleItem (Always stat) = "always " <> statement stat -moduleItem (Decl dir p ini ) = maybe "" makePort dir <> port p <> maybe "" makeIni ini <> ";\n" - where makePort = (<> " ") . portDir - makeIni = (" = " <>) . constExpr +moduleItem (Decl dir p ini) = + maybe "" makePort dir <> port p <> maybe "" makeIni ini <> ";\n" + where + makePort = (<> " ") . portDir + makeIni = (" = " <>) . constExpr moduleItem (ParamDecl p) = paramList p <> ";\n" moduleItem (LocalParamDecl p) = localParamList p <> ";\n" diff --git a/src/VeriFuzz/Verilog/Gen.hs b/src/VeriFuzz/Verilog/Gen.hs index 4f3ceca..8da4d1a 100644 --- a/src/VeriFuzz/Verilog/Gen.hs +++ b/src/VeriFuzz/Verilog/Gen.hs @@ -26,13 +26,13 @@ import Control.Monad.Trans.Class (lift) import Control.Monad.Trans.Reader hiding (local) import Control.Monad.Trans.State.Lazy import Data.Foldable (fold) +import Data.List.NonEmpty (toList) import qualified Data.Text as T import Hedgehog (Gen) import qualified Hedgehog.Gen as Hog import qualified Hedgehog.Range as Hog import VeriFuzz.Config import VeriFuzz.Internal -import VeriFuzz.Verilog.Arbitrary import VeriFuzz.Verilog.AST import VeriFuzz.Verilog.Internal import VeriFuzz.Verilog.Mutate @@ -54,7 +54,7 @@ toId = Identifier . ("w" <>) . T.pack . show toPort :: Identifier -> Gen Port toPort ident = do - i <- genPositive + i <- Hog.int $ Hog.linear 0 100 return $ wire i ident sumSize :: [Port] -> Int @@ -93,22 +93,80 @@ randomMod inps total = do gen :: Gen a -> StateGen a gen = lift . lift +listOf1 :: Gen a -> Gen [a] +listOf1 a = toList <$> Hog.nonEmpty (Hog.linear 0 100) a + +--listOf :: Gen a -> Gen [a] +--listOf = Hog.list (Hog.linear 0 100) + +largeNum :: Gen Int +largeNum = Hog.int Hog.linearBounded + +wireSize :: Gen Int +wireSize = Hog.int $ Hog.linear 2 200 + +binOp :: Gen BinaryOperator +binOp = + Hog.element + [ BinPlus + , BinMinus + , BinTimes + -- , BinDiv + -- , BinMod + , BinEq + , BinNEq + -- , BinCEq + -- , BinCNEq + , BinLAnd + , BinLOr + , BinLT + , BinLEq + , BinGT + , BinGEq + , BinAnd + , BinOr + , BinXor + , BinXNor + , BinXNorInv + -- , BinPower + , BinLSL + , BinLSR + , BinASL + , BinASR + ] + +unOp :: Gen UnaryOperator +unOp = + Hog.element + [ UnPlus + , UnMinus + , UnNot + , UnLNot + , UnAnd + , UnNand + , UnOr + , UnNor + , UnXor + , UnNxor + , UnNxorInv + ] + constExprWithContext :: [Parameter] -> ProbExpr -> Hog.Size -> Gen ConstExpr constExprWithContext ps prob size | size == 0 = Hog.frequency - [ (prob ^. probExprNum, ConstNum <$> genPositive <*> arb) + [ (prob ^. probExprNum, ConstNum <$> wireSize <*> fmap fromIntegral largeNum) , ( if null ps then 0 else prob ^. probExprId , ParamId . view paramIdent <$> Hog.element ps ) ] | size > 0 = Hog.frequency - [ (prob ^. probExprNum, ConstNum <$> genPositive <*> arb) + [ (prob ^. probExprNum, ConstNum <$> wireSize <*> fmap fromIntegral largeNum) , ( if null ps then 0 else prob ^. probExprId , ParamId . view paramIdent <$> Hog.element ps ) - , (prob ^. probExprUnOp, ConstUnOp <$> arb <*> subexpr 2) + , (prob ^. probExprUnOp, ConstUnOp <$> unOp <*> subexpr 2) , ( prob ^. probExprBinOp - , ConstBinOp <$> subexpr 2 <*> arb <*> subexpr 2 + , ConstBinOp <$> subexpr 2 <*> binOp <*> subexpr 2 ) , ( prob ^. probExprCond , ConstCond <$> subexpr 3 <*> subexpr 3 <*> subexpr 3 @@ -121,19 +179,19 @@ constExprWithContext ps prob size exprSafeList :: ProbExpr -> [(Int, Gen Expr)] exprSafeList prob = [ ( prob ^. probExprNum - , Number <$> genPositive <*> Hog.integral (Hog.linearFrom 0 (-100) 100) + , Number <$> wireSize <*> fmap fromIntegral largeNum ) ] exprRecList :: ProbExpr -> (Hog.Size -> Gen Expr) -> [(Int, Gen Expr)] exprRecList prob subexpr = [ ( prob ^. probExprNum - , Number <$> genPositive <*> Hog.integral (Hog.linearFrom 0 (-100) 100) + , Number <$> wireSize <*> fmap fromIntegral largeNum ) , (prob ^. probExprConcat , Concat <$> listOf1 (subexpr 8)) - , (prob ^. probExprUnOp , UnOp <$> arb <*> subexpr 2) + , (prob ^. probExprUnOp , UnOp <$> unOp <*> subexpr 2) , (prob ^. probExprStr, Str <$> Hog.text (Hog.linear 0 100) Hog.alphaNum) - , (prob ^. probExprBinOp , BinOp <$> subexpr 2 <*> arb <*> subexpr 2) + , (prob ^. probExprBinOp , BinOp <$> subexpr 2 <*> binOp <*> subexpr 2) , (prob ^. probExprCond , Cond <$> subexpr 3 <*> subexpr 3 <*> subexpr 3) , (prob ^. probExprSigned , Func <$> pure SignedFunc <*> subexpr 2) , (prob ^. probExprUnsigned, Func <$> pure UnsignedFunc <*> subexpr 2) @@ -159,12 +217,12 @@ exprWithContext prob l n some :: StateGen a -> StateGen [a] some f = do - amount <- gen genPositive + amount <- gen $ Hog.int (Hog.linear 1 100) replicateM amount f many :: StateGen a -> StateGen [a] many f = do - amount <- gen $ Hog.int (Hog.linear 0 30) + amount <- gen $ Hog.int (Hog.linear 0 100) replicateM amount f makeIdentifier :: T.Text -> StateGen Identifier @@ -177,7 +235,7 @@ makeIdentifier prefix = do newPort :: PortType -> StateGen Port newPort pt = do ident <- makeIdentifier . T.toLower $ showT pt - p <- gen $ Port pt <$> arb <*> genPositive <*> pure ident + p <- gen $ Port pt <$> Hog.bool <*> pure 0 <*> wireSize <*> pure ident variables %= (p :) return p @@ -185,13 +243,11 @@ scopedExpr :: StateGen Expr scopedExpr = do context <- get prob <- askProbability - gen - . Hog.sized - . exprWithContext (prob ^. probExpr) - $ context - ^.. variables - . traverse - . portName + gen . Hog.sized . exprWithContext (prob ^. probExpr) $ vars context + where + vars cont = + (cont ^.. variables . traverse . portName) + <> (cont ^.. parameters . traverse . paramIdent) contAssign :: StateGen ContAssign contAssign = do @@ -200,7 +256,7 @@ contAssign = do return $ ContAssign (p ^. portName) expr lvalFromPort :: Port -> LVal -lvalFromPort (Port _ _ _ i) = RegId i +lvalFromPort (Port _ _ _ _ i) = RegId i probability :: Config -> Probability probability c = c ^. configProbability @@ -214,14 +270,40 @@ assignment = do lval <- lvalFromPort <$> newPort Reg return $ Assign lval Nothing expr -conditional :: StateGen Statement -conditional = do - expr <- scopedExpr +seqBlock :: StateGen Statement +seqBlock = do stmntDepth -= 1 tstat <- SeqBlock <$> some statement - fstat <- Hog.maybe $ SeqBlock <$> some statement stmntDepth += 1 - return $ CondStmnt (BinOp expr BinEq 0) (Just tstat) fstat + return tstat + +conditional :: StateGen Statement +conditional = do + expr <- scopedExpr + tstat <- seqBlock + fstat <- Hog.maybe seqBlock + return $ CondStmnt expr (Just tstat) 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) + var <- lvalFromPort <$> newPort Reg + stats <- seqBlock + return $ ForLoop (Assign var Nothing 0) + (BinOp (varId var) BinLT $ fromIntegral num) + (Assign var Nothing $ BinOp (varId var) BinPlus 1) + stats + where varId v = Id (v ^. regId) statement :: StateGen Statement statement = do @@ -232,6 +314,7 @@ statement = do [ (defProb probStmntBlock , BlockAssign <$> assignment) , (defProb probStmntNonBlock , NonBlockAssign <$> assignment) , (onDepth cont (defProb probStmntCond), conditional) + , (onDepth cont (defProb probStmntFor) , forLoop) ] where onDepth c n = if c ^. stmntDepth > 0 then n else 0 @@ -253,8 +336,8 @@ instantiate (ModDecl i outP inP _ _) = do ident <- makeIdentifier "modinst" Hog.choice [ return . ModInst i ident $ ModConn <$> outs <> ins - , ModInst i ident - <$> Hog.shuffle (zipWith ModConnNamed (view portName <$> outP <> inP) (outs <> ins)) + , ModInst i ident <$> Hog.shuffle + (zipWith ModConnNamed (view portName <$> outP <> inP) (outs <> ins)) ] -- | Generates a module instance by also generating a new module if there are @@ -291,7 +374,7 @@ modInst = do parameters .= [] modDepth -= 1 chosenMod <- moduleDef Nothing - ncont <- get + ncont <- get let genMods = ncont ^. modules modDepth += 1 parameters .= params @@ -341,12 +424,12 @@ moduleDef :: Maybe Identifier -> StateGen ModDecl moduleDef top = do name <- moduleName top portList <- some $ newPort Wire - mi <- some modItem + mi <- Hog.list (Hog.linear 4 100) modItem context <- get let local = filter (`notElem` portList) $ context ^. variables let size = sum $ local ^.. traverse . portSize - let clock = Port Wire False 1 "clk" - let yport = Port Wire False size "y" + let clock = Port Wire False 0 1 "clk" + let yport = Port Wire False 0 size "y" let comb = combineAssigns_ yport local declareMod local . ModDecl name [yport] (clock : portList) (mi <> [comb]) -- cgit