aboutsummaryrefslogtreecommitdiffstats
path: root/src/Test/VeriFuzz/Verilog
diff options
context:
space:
mode:
authorYann Herklotz <ymherklotz@gmail.com>2018-12-28 19:20:53 +0100
committerYann Herklotz <ymherklotz@gmail.com>2018-12-28 19:20:53 +0100
commit5243210a4c16a7349b59a964072c4effb3aea30a (patch)
treeb92ffc4819d2fd5e4c2742770e5b1e6b3fcd8a9b /src/Test/VeriFuzz/Verilog
parente73362e0650b20281ee43a246d97e1bbe9e34b3b (diff)
downloadverismith-5243210a4c16a7349b59a964072c4effb3aea30a.tar.gz
verismith-5243210a4c16a7349b59a964072c4effb3aea30a.zip
Move verilog files into specific module
Diffstat (limited to 'src/Test/VeriFuzz/Verilog')
-rw-r--r--src/Test/VeriFuzz/Verilog/AST.hs408
-rw-r--r--src/Test/VeriFuzz/Verilog/CodeGen.hs263
-rw-r--r--src/Test/VeriFuzz/Verilog/Mutate.hs80
3 files changed, 751 insertions, 0 deletions
diff --git a/src/Test/VeriFuzz/Verilog/AST.hs b/src/Test/VeriFuzz/Verilog/AST.hs
new file mode 100644
index 0000000..5f6c862
--- /dev/null
+++ b/src/Test/VeriFuzz/Verilog/AST.hs
@@ -0,0 +1,408 @@
+{-|
+Module : Test.VeriFuzz.Verilog.AST
+Description : Definition of the Verilog AST types.
+Copyright : (c) Yann Herklotz Grave 2018
+License : GPL-3
+Maintainer : ymherklotz@gmail.com
+Stability : experimental
+Portability : POSIX
+
+Defines the types to build a Verilog AST.
+-}
+
+{-# LANGUAGE TemplateHaskell #-}
+
+module Test.VeriFuzz.Verilog.AST where
+
+import Control.Lens
+import qualified Data.Graph.Inductive as G
+import Data.String
+import Data.Text (Text)
+import qualified Data.Text as T
+import qualified Test.QuickCheck as QC
+import Test.VeriFuzz.Circuit
+import Test.VeriFuzz.Graph.Random
+
+class Source a where
+ genSource :: a -> Text
+
+-- | Identifier in Verilog. This is just a string of characters that can either
+-- be lowercase and uppercase for now. This might change in the future though,
+-- as Verilog supports many more characters in Identifiers.
+newtype Identifier = Identifier { _getIdentifier :: Text }
+ deriving (Show, Eq, Ord)
+
+-- | A number in Verilog which contains a size and a value.
+data Number = Number { _numSize :: Int
+ , _numVal :: Int
+ } deriving (Show, Eq, Ord)
+
+newtype Delay = Delay { _delay :: Int }
+ deriving (Show, Eq, Ord)
+
+data Event = EId Identifier
+ | EExpr Expression
+ | EAll
+ deriving (Show, Eq, Ord)
+
+data Net = Wire
+ | Tri
+ | Tri1
+ | Supply0
+ | Wand
+ | TriAnd
+ | Tri0
+ | Supply1
+ | Wor
+ | Trior
+ deriving (Show, Eq, Ord)
+
+data RegLVal = RegId Identifier
+ | RegExpr { _regExprId :: Identifier
+ , _regExpr :: Expression
+ }
+ | RegSize { _regSizeId :: Identifier
+ , _regSizeMSB :: ConstExpr
+ , _regSizeLSB :: ConstExpr
+ }
+ deriving (Show, Eq, Ord)
+
+-- | Binary operators that are currently supported in the verilog generation.
+data BinaryOperator = 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 -- ^ @>>>@
+ deriving (Show, Eq, Ord)
+
+-- | Unary operators that are currently supported by the generator.
+data UnaryOperator = UnPlus -- ^ @+@
+ | UnMinus -- ^ @-@
+ | UnNot -- ^ @!@
+ | UnAnd -- ^ @&@
+ | UnNand -- ^ @~&@
+ | UnOr -- ^ @|@
+ | UnNor -- ^ @~|@
+ | UnXor -- ^ @^@
+ | UnNxor -- ^ @~^@
+ | UnNxorInv -- ^ @^~@
+ deriving (Show, Eq, Ord)
+
+-- | A primary expression which can either be a number or an identifier.
+data Primary = PrimNum Number -- ^ Number in primary expression.
+ | PrimId Identifier -- ^ Identifier in primary expression.
+ deriving (Show, Eq, Ord)
+
+-- | Verilog expression, which can either be a primary expression, unary
+-- expression, binary operator expression or a conditional expression.
+data Expression = PrimExpr Primary
+ | UnPrimExpr { _exprUnOp :: UnaryOperator
+ , _exprPrim :: Primary
+ }
+ | OpExpr { _exprLhs :: Expression
+ , _exprBinOp :: BinaryOperator
+ , _exprRhs :: Expression
+ }
+ | CondExpr { _exprCond :: Expression
+ , _exprTrue :: Expression
+ , _exprFalse :: Expression
+ }
+ | ExprStr Text
+ deriving (Show, Eq, Ord)
+
+newtype ConstExpr = ConstExpr { _constNum :: Int }
+ deriving (Show, Eq, Ord)
+
+-- | Different port direction that are supported in Verilog.
+data PortDir = Input -- ^ Input direction for port (@input@).
+ | Output -- ^ Output direction for port (@output@).
+ | InOut -- ^ Inout direction for port (@inout@).
+ deriving (Show, Eq, Ord)
+
+data PortType = PortNet Net
+ | Reg { _regSigned :: Bool }
+ deriving (Show, Eq, Ord)
+
+-- | Port declaration.
+data Port = Port { _portDir :: Maybe PortDir
+ , _portType :: Maybe PortType
+ , _portName :: Identifier
+ } deriving (Show, Eq, Ord)
+
+newtype ModConn = ModConn { _modConn :: Expression }
+ deriving (Show, Eq, Ord)
+
+data Assign = Assign { _assignReg :: RegLVal
+ , _assignDelay :: Maybe Delay
+ , _assignExpr :: Expression
+ } deriving (Show, Eq, Ord)
+
+data ContAssign = ContAssign { _contAssignNetLVal :: Identifier
+ , _contAssignExpr :: Expression
+ } deriving (Show, Eq, Ord)
+
+-- | Statements in Verilog.
+data Statement = TimeCtrl { _statDelay :: Delay
+ , _statDStat :: Maybe Statement
+ } -- ^ Time control (@#NUM@)
+ | EventCtrl { _statEvent :: Event
+ , _statEStat :: Maybe Statement
+ }
+ | SeqBlock { _statements :: [Statement] } -- ^ Sequential block (@begin ... end@)
+ | BlockAssign Assign -- ^ blocking assignment (@=@)
+ | NonBlockAssign Assign -- ^ Non blocking assignment (@<=@)
+ | StatCA ContAssign -- ^ Statement continuous assignment. May not be correct.
+ | TaskEnable Task
+ | SysTaskEnable Task
+ deriving (Show, Eq, Ord)
+
+data Task = Task { _taskName :: Identifier
+ , _taskExpr :: [Expression]
+ } deriving (Show, Eq, Ord)
+
+-- | Module item which is the body of the module expression.
+data ModItem = ModCA ContAssign
+ | ModInst { _modInstId :: Identifier
+ , _modInstName :: Identifier
+ , _modInstConns :: [ModConn]
+ }
+ | Initial Statement
+ | Always Statement
+ | Decl Port
+ deriving (Show, Eq, Ord)
+
+-- | 'module' module_identifier [list_of_ports] ';' { module_item } 'end_module'
+data ModDecl = ModDecl { _moduleId :: Identifier
+ , _modPorts :: [Port]
+ , _moduleItems :: [ModItem]
+ } deriving (Show, Eq, Ord)
+
+-- | Description of the Verilog module.
+newtype Description = Description { _getDescription :: ModDecl }
+ deriving (Show, Eq, Ord)
+
+-- | The complete sourcetext for the Verilog module.
+newtype VerilogSrc = VerilogSrc { _getVerilogSrc :: [Description] }
+ deriving (Show, Eq, Ord)
+
+-- Generate Arbitrary instances for the AST
+
+expr :: Int -> QC.Gen Expression
+expr 0 = QC.oneof
+ [ PrimExpr <$> QC.arbitrary
+ , UnPrimExpr <$> QC.arbitrary <*> QC.arbitrary
+ -- , ExprStr <$> QC.arbitrary
+ ]
+expr n
+ | n > 0 = QC.oneof
+ [ PrimExpr <$> QC.arbitrary
+ , UnPrimExpr <$> QC.arbitrary <*> QC.arbitrary
+ -- , ExprStr <$> QC.arbitrary
+ , OpExpr <$> subexpr 2 <*> QC.arbitrary <*> subexpr 2
+ , CondExpr <$> subexpr 3 <*> subexpr 3 <*> subexpr 3
+ ]
+ | otherwise = expr 0
+ where
+ subexpr y = expr (n `div` y)
+
+statement :: Int -> QC.Gen Statement
+statement 0 = QC.oneof
+ [ BlockAssign <$> QC.arbitrary
+ , NonBlockAssign <$> QC.arbitrary
+ -- , StatCA <$> QC.arbitrary
+ , TaskEnable <$> QC.arbitrary
+ , SysTaskEnable <$> QC.arbitrary
+ ]
+statement n
+ | n > 0 = QC.oneof
+ [ TimeCtrl <$> QC.arbitrary <*> (Just <$> substat 2)
+ , SeqBlock <$> QC.listOf1 (substat 4)
+ , BlockAssign <$> QC.arbitrary
+ , NonBlockAssign <$> QC.arbitrary
+ -- , StatCA <$> QC.arbitrary
+ , TaskEnable <$> QC.arbitrary
+ , SysTaskEnable <$> QC.arbitrary
+ ]
+ | otherwise = statement 0
+ where
+ substat y = statement (n `div` y)
+
+modPortGen :: QC.Gen Port
+modPortGen = QC.oneof
+ [ Port (Just Input) Nothing <$> QC.arbitrary
+ , Port (Just Output) <$> (Just . Reg <$> QC.arbitrary) <*> QC.arbitrary
+ ]
+
+instance QC.Arbitrary Text where
+ arbitrary = T.pack <$> QC.arbitrary
+
+instance QC.Arbitrary Identifier where
+ arbitrary = Identifier . T.pack <$>
+ (QC.shuffle (['a'..'z'] <> ['A'..'Z']) >>= QC.sublistOf)
+
+instance QC.Arbitrary Number where
+ arbitrary = Number <$> QC.suchThat QC.arbitrary (>0) <*> QC.arbitrary
+
+instance QC.Arbitrary Net where
+ arbitrary = pure Wire
+
+instance QC.Arbitrary BinaryOperator where
+ arbitrary = QC.elements
+ [ 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
+ ]
+
+instance QC.Arbitrary UnaryOperator where
+ arbitrary = QC.elements
+ [ UnPlus
+ , UnMinus
+ , UnNot
+ , UnAnd
+ , UnNand
+ , UnOr
+ , UnNor
+ , UnXor
+ , UnNxor
+ , UnNxorInv
+ ]
+
+instance QC.Arbitrary Primary where
+ arbitrary = PrimNum <$> QC.arbitrary
+
+instance QC.Arbitrary PortDir where
+ arbitrary = QC.elements [Input, Output, InOut]
+
+instance QC.Arbitrary PortType where
+ arbitrary = QC.oneof [PortNet <$> QC.arbitrary, Reg <$> QC.arbitrary]
+
+instance QC.Arbitrary Port where
+ arbitrary = Port Nothing <$> QC.arbitrary <*> QC.arbitrary
+
+instance QC.Arbitrary Delay where
+ arbitrary = Delay <$> QC.suchThat QC.arbitrary (\x -> x > 0)
+
+instance QC.Arbitrary Event where
+ arbitrary = EId <$> QC.arbitrary
+
+instance QC.Arbitrary ModConn where
+ arbitrary = ModConn <$> QC.arbitrary
+
+instance QC.Arbitrary ConstExpr where
+ arbitrary = ConstExpr <$> QC.arbitrary
+
+instance QC.Arbitrary RegLVal where
+ arbitrary = QC.oneof [ RegId <$> QC.arbitrary
+ , RegExpr <$> QC.arbitrary <*> QC.arbitrary
+ , RegSize <$> QC.arbitrary <*> QC.arbitrary <*> QC.arbitrary
+ ]
+
+instance QC.Arbitrary Assign where
+ arbitrary = Assign <$> QC.arbitrary <*> QC.arbitrary <*> QC.arbitrary
+
+instance QC.Arbitrary Expression where
+ arbitrary = QC.sized expr
+
+instance QC.Arbitrary Statement where
+ arbitrary = QC.sized statement
+
+instance QC.Arbitrary ContAssign where
+ arbitrary = ContAssign <$> QC.arbitrary <*> QC.arbitrary
+
+instance QC.Arbitrary Task where
+ arbitrary = Task <$> QC.arbitrary <*> QC.arbitrary
+
+instance QC.Arbitrary ModItem where
+ arbitrary = QC.oneof [ ModCA <$> QC.arbitrary
+ , ModInst <$> QC.arbitrary <*> QC.arbitrary <*> QC.arbitrary
+ , Initial <$> QC.arbitrary
+ , Always <$> (EventCtrl <$> QC.arbitrary <*> QC.arbitrary)
+ , Decl <$> QC.arbitrary
+ ]
+
+instance QC.Arbitrary ModDecl where
+ arbitrary = ModDecl <$> QC.arbitrary <*> QC.listOf1 modPortGen <*> QC.arbitrary
+
+instance QC.Arbitrary Description where
+ arbitrary = Description <$> QC.arbitrary
+
+instance QC.Arbitrary VerilogSrc where
+ arbitrary = VerilogSrc <$> QC.arbitrary
+
+-- Traversal Instance
+
+traverseExpr :: Traversal' Expression Expression
+traverseExpr _ (PrimExpr e) = pure (PrimExpr e)
+traverseExpr _ (UnPrimExpr un e) = pure (UnPrimExpr un e)
+traverseExpr f (OpExpr l op r) = OpExpr <$> f l <*> pure op <*> f r
+traverseExpr f (CondExpr c l r) = CondExpr <$> f c <*> f l <*> f r
+
+-- Create all the necessary lenses
+
+makeLenses ''Identifier
+makeLenses ''Number
+makeLenses ''VerilogSrc
+makeLenses ''Description
+makeLenses ''ModDecl
+makeLenses ''ModItem
+makeLenses ''Port
+makeLenses ''PortDir
+makeLenses ''BinaryOperator
+makeLenses ''UnaryOperator
+makeLenses ''Primary
+makeLenses ''Expression
+makeLenses ''ContAssign
+makeLenses ''PortType
+
+-- Make all the necessary prisms
+
+makePrisms ''Expression
+makePrisms ''ModItem
+makePrisms ''ModConn
+
+-- Other Instances
+
+instance IsString Identifier where
+ fromString = Identifier . T.pack
diff --git a/src/Test/VeriFuzz/Verilog/CodeGen.hs b/src/Test/VeriFuzz/Verilog/CodeGen.hs
new file mode 100644
index 0000000..0247648
--- /dev/null
+++ b/src/Test/VeriFuzz/Verilog/CodeGen.hs
@@ -0,0 +1,263 @@
+{-|
+Module : Test.VeriFuzz.Verilog.CodeGen
+Description : Code generation for Verilog AST.
+Copyright : (c) Yann Herklotz Grave 2018
+License : GPL-3
+Maintainer : ymherklotz@gmail.com
+Stability : experimental
+Portability : POSIX
+
+This module generates the code from the Verilog AST defined in
+"Test.VeriFuzz.Verilog.AST".
+-}
+
+module Test.VeriFuzz.Verilog.CodeGen where
+
+import Control.Lens
+import Data.Maybe (fromMaybe)
+import Data.Text (Text)
+import qualified Data.Text as T
+import qualified Data.Text.IO as T
+import Test.VeriFuzz.Internal.Shared
+import Test.VeriFuzz.Verilog.AST
+
+showT :: (Show a) => a -> Text
+showT = T.pack . show
+
+defMap :: Maybe Statement -> Text
+defMap stat = fromMaybe ";\n" $ genStatement <$> stat
+
+-- | Convert the 'VerilogSrc' type to 'Text' so that it can be rendered.
+genVerilogSrc :: VerilogSrc -> Text
+genVerilogSrc source =
+ fromList $ genDescription <$> source ^. getVerilogSrc
+
+-- | Generate the 'Description' to 'Text'.
+genDescription :: Description -> Text
+genDescription desc =
+ genModuleDecl $ desc ^. getDescription
+
+-- | Generate the 'ModDecl' for a module and convert it to 'Text'.
+genModuleDecl :: ModDecl -> Text
+genModuleDecl mod =
+ "module " <> mod ^. moduleId . getIdentifier
+ <> ports <> ";\n"
+ <> modItems
+ <> "endmodule\n"
+ where
+ ports
+ | null $ mod ^. modPorts = ""
+ | otherwise = "(\n" <> (sep ",\n" $ genPort <$> mod ^. modPorts) <> "\n)"
+ modItems = fromList $ genModuleItem <$> mod ^. moduleItems
+
+-- | Generate the 'Port' description.
+genPort :: Port -> Text
+genPort port =
+ dir <> t <> name
+ where
+ dir = fromMaybe "" $ (<>" ") . genPortDir <$> port ^. portDir
+ t = fromMaybe "wire " $ (<>" ") . genPortType <$> port ^. portType
+ name = port ^. portName . getIdentifier
+
+-- | Convert the 'PortDir' type to 'Text'.
+genPortDir :: PortDir -> Text
+genPortDir Input = "input"
+genPortDir Output = "output"
+genPortDir InOut = "inout"
+
+-- | Generate a 'ModItem'.
+genModuleItem :: ModItem -> Text
+genModuleItem (ModCA ca) = genContAssign ca
+genModuleItem (ModInst (Identifier id) (Identifier name) conn) =
+ id <> " " <> name <> "(" <> sep ", " (genExpr . _modConn <$> conn) <> ")" <> ";\n"
+genModuleItem (Initial stat) = "initial " <> genStatement stat
+genModuleItem (Always stat) = "always " <> genStatement stat
+genModuleItem (Decl port) = genPort port <> ";\n"
+
+-- | Generate continuous assignment
+genContAssign :: ContAssign -> Text
+genContAssign (ContAssign val e) =
+ " assign " <> name <> " = " <> expr <> ";\n"
+ where
+ name = val ^. getIdentifier
+ expr = genExpr $ e
+
+-- | Generate 'Expression' to 'Text'.
+genExpr :: Expression -> Text
+genExpr (OpExpr exprRhs bin exprLhs) =
+ "(" <> genExpr exprRhs <> genBinaryOperator bin <> genExpr exprLhs <> ")"
+genExpr (PrimExpr prim) = genPrimary prim
+genExpr (UnPrimExpr u e) =
+ "(" <> genUnaryOperator u <> genPrimary e <> ")"
+genExpr (CondExpr l t f) =
+ "(" <> genExpr l <> " ? " <> genExpr t <> " : " <> genExpr f <> ")"
+genExpr (ExprStr t) = "\"" <> t <> "\""
+
+-- | Generate a 'PrimaryExpression' to 'Text'.
+genPrimary :: Primary -> Text
+genPrimary (PrimNum num) =
+ "(" <> neg <> sh (num ^. numSize) <> "'d" <> (sh . abs) n <> ")"
+ where
+ sh = T.pack . show
+ abs x = if x <= 0 then -x else x
+ n = num ^. numVal
+ neg = if n <= 0 then "-" else ""
+genPrimary (PrimId ident) = ident ^. getIdentifier
+
+-- | Convert 'BinaryOperator' to 'Text'.
+genBinaryOperator :: BinaryOperator -> Text
+genBinaryOperator BinPlus = " + "
+genBinaryOperator BinMinus = " - "
+genBinaryOperator BinTimes = " * "
+genBinaryOperator BinDiv = " / "
+genBinaryOperator BinMod = " % "
+genBinaryOperator BinEq = " == "
+genBinaryOperator BinNEq = " != "
+genBinaryOperator BinCEq = " === "
+genBinaryOperator BinCNEq = " !== "
+genBinaryOperator BinLAnd = " && "
+genBinaryOperator BinLOr = " || "
+genBinaryOperator BinLT = " < "
+genBinaryOperator BinLEq = " <= "
+genBinaryOperator BinGT = " > "
+genBinaryOperator BinGEq = " >= "
+genBinaryOperator BinAnd = " & "
+genBinaryOperator BinOr = " | "
+genBinaryOperator BinXor = " ^ "
+genBinaryOperator BinXNor = " ^~ "
+genBinaryOperator BinXNorInv = " ~^ "
+genBinaryOperator BinPower = " ** "
+genBinaryOperator BinLSL = " << "
+genBinaryOperator BinLSR = " >> "
+genBinaryOperator BinASL = " <<< "
+genBinaryOperator BinASR = " >>> "
+
+genUnaryOperator :: UnaryOperator -> Text
+genUnaryOperator UnPlus = "+"
+genUnaryOperator UnMinus = "-"
+genUnaryOperator UnNot = "!"
+genUnaryOperator UnAnd = "&"
+genUnaryOperator UnNand = "~&"
+genUnaryOperator UnOr = "|"
+genUnaryOperator UnNor = "~|"
+genUnaryOperator UnXor = "^"
+genUnaryOperator UnNxor = "~^"
+genUnaryOperator UnNxorInv = "^~"
+
+genNet :: Net -> Text
+genNet Wire = "wire"
+genNet Tri = "tri"
+genNet Tri1 = "tri1"
+genNet Supply0 = "supply0"
+genNet Wand = "wand"
+genNet TriAnd = "triand"
+genNet Tri0 = "tri0"
+genNet Supply1 = "supply1"
+genNet Wor = "wor"
+genNet Trior = "trior"
+
+genEvent :: Event -> Text
+genEvent (EId id) = "@(" <> id ^. getIdentifier <> ")"
+genEvent (EExpr expr) = "@(" <> genExpr expr <> ")"
+genEvent EAll = "@*"
+
+genDelay :: Delay -> Text
+genDelay (Delay i) = "#" <> showT i
+
+genRegLVal :: RegLVal -> Text
+genRegLVal (RegId id) = id ^. getIdentifier
+genRegLVal (RegExpr id expr) =
+ id ^. getIdentifier <> " [" <> genExpr expr <> "]"
+genRegLVal (RegSize id msb lsb) =
+ id ^. getIdentifier <> " [" <> genConstExpr msb <> ":" <> genConstExpr lsb <> "]"
+
+genConstExpr :: ConstExpr -> Text
+genConstExpr (ConstExpr num) = showT num
+
+genPortType :: PortType -> Text
+genPortType (PortNet net) = genNet net
+genPortType (Reg signed)
+ | signed = " reg signed "
+ | otherwise = " reg "
+
+genAssign :: Text -> Assign -> Text
+genAssign op (Assign r d e) =
+ genRegLVal r <> op <> fromMaybe "" (genDelay <$> d) <> genExpr e
+
+genStatement :: Statement -> Text
+genStatement (TimeCtrl d stat) = genDelay d <> " " <> defMap stat
+genStatement (EventCtrl e stat) = genEvent e <> " " <> defMap stat
+genStatement (SeqBlock s) =
+ "begin\n" <> fromList (genStatement <$> s) <> "end\n"
+genStatement (BlockAssign a) = genAssign " = " a <> ";\n"
+genStatement (NonBlockAssign a) = genAssign " <= " a <> ";\n"
+genStatement (StatCA a) = genContAssign a
+genStatement (TaskEnable task) = genTask task <> ";\n"
+genStatement (SysTaskEnable task) = "$" <> genTask task <> ";\n"
+
+genTask :: Task -> Text
+genTask (Task name expr)
+ | null expr = id
+ | otherwise = id <> "(" <> sep ", " (genExpr <$> expr) <> ")"
+ where
+ id = name ^. getIdentifier
+
+-- | Render the 'Text' to 'IO'. This is equivalent to 'putStrLn'.
+render :: Text -> IO ()
+render = T.putStrLn
+
+-- Instances
+
+instance Source Task where
+ genSource = genTask
+
+instance Source Statement where
+ genSource = genStatement
+
+instance Source PortType where
+ genSource = genPortType
+
+instance Source ConstExpr where
+ genSource = genConstExpr
+
+instance Source RegLVal where
+ genSource = genRegLVal
+
+instance Source Delay where
+ genSource = genDelay
+
+instance Source Event where
+ genSource = genEvent
+
+instance Source Net where
+ genSource = genNet
+
+instance Source UnaryOperator where
+ genSource = genUnaryOperator
+
+instance Source Primary where
+ genSource = genPrimary
+
+instance Source Expression where
+ genSource = genExpr
+
+instance Source ContAssign where
+ genSource = genContAssign
+
+instance Source ModItem where
+ genSource = genModuleItem
+
+instance Source PortDir where
+ genSource = genPortDir
+
+instance Source Port where
+ genSource = genPort
+
+instance Source ModDecl where
+ genSource = genModuleDecl
+
+instance Source Description where
+ genSource = genDescription
+
+instance Source VerilogSrc where
+ genSource = genVerilogSrc
diff --git a/src/Test/VeriFuzz/Verilog/Mutate.hs b/src/Test/VeriFuzz/Verilog/Mutate.hs
new file mode 100644
index 0000000..b903ec9
--- /dev/null
+++ b/src/Test/VeriFuzz/Verilog/Mutate.hs
@@ -0,0 +1,80 @@
+{-|
+Module : Test.VeriFuzz.Verilog.Mutation
+Description : Functions to mutate the Verilog AST.
+Copyright : (c) Yann Herklotz Grave 2018
+License : GPL-3
+Maintainer : ymherklotz@gmail.com
+Stability : experimental
+Portability : POSIX
+
+Functions to mutate the Verilog AST from "Test.VeriFuzz.Verilog.AST" to generate
+more random patterns, such as nesting wires instead of creating new ones.
+-}
+
+module Test.VeriFuzz.Verilog.Mutate where
+
+import Control.Lens
+import Data.Maybe (catMaybes, fromMaybe)
+import Test.VeriFuzz.Internal.Gen
+import Test.VeriFuzz.Internal.Shared
+import Test.VeriFuzz.Verilog.AST
+
+-- | Return if the 'Identifier' is in a 'ModDecl'.
+inPort :: Identifier -> ModDecl -> Bool
+inPort id mod = any (\a -> a ^. portName == id) $ mod ^. modPorts
+
+-- | Find the last assignment of a specific wire/reg to an expression, and
+-- returns that expression.
+findAssign :: Identifier -> [ModItem] -> Maybe Expression
+findAssign id items =
+ safe last . catMaybes $ isAssign <$> items
+ where
+ isAssign (ModCA (ContAssign val expr))
+ | val == id = Just $ expr
+ | otherwise = Nothing
+ isAssign _ = Nothing
+
+-- | Transforms an expression by replacing an Identifier with an
+-- expression. This is used inside 'transformOf' and 'traverseExpr' to replace
+-- the 'Identifier' recursively.
+idTrans :: Identifier -> Expression -> Expression -> Expression
+idTrans i expr (PrimExpr (PrimId id))
+ | id == i = expr
+ | otherwise = (PrimExpr (PrimId id))
+idTrans _ _ e = e
+
+-- | Replaces the identifier recursively in an expression.
+replace :: Identifier -> Expression -> Expression -> Expression
+replace = (transformOf traverseExpr .) . idTrans
+
+-- | Nest expressions for a specific 'Identifier'. If the 'Identifier' is not found,
+-- the AST is not changed.
+--
+-- This could be improved by instead of only using the last assignment to the
+-- wire that one finds, to use the assignment to the wire before the current
+-- expression. This would require a different approach though.
+nestId :: Identifier -> ModDecl -> ModDecl
+nestId id mod
+ | not $ inPort id mod =
+ let expr = fromMaybe def . findAssign id $ mod ^. moduleItems
+ in mod & get %~ replace id expr
+ | otherwise = mod
+ where
+ get = moduleItems . traverse . _ModCA . contAssignExpr
+ def = PrimExpr $ PrimId id
+
+-- | Replaces an identifier by a expression in all the module declaration.
+nestSource :: Identifier -> VerilogSrc -> VerilogSrc
+nestSource id src =
+ src & getVerilogSrc . traverse . getDescription %~ nestId id
+
+-- | Nest variables in the format @w[0-9]*@ up to a certain number.
+nestUpTo :: Int -> VerilogSrc -> VerilogSrc
+nestUpTo i src =
+ foldl (flip nestSource) src $ Identifier . fromNode <$> [1..i]
+
+-- | Add a Module Instantiation using 'ModInst' from the first module passed to
+-- it to the body of the second module.
+instantiateMod :: ModDecl -> ModDecl -> ModDecl
+instantiateMod mod main =
+ main