aboutsummaryrefslogtreecommitdiffstats
path: root/src/Test/VeriFuzz/Mutate.hs
blob: 3e7acae9fffa9cdbfa3ccab541a536b324bae8ec (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
{-|
Module      : Test.VeriFuzz.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.VerilogAST" to generate
more random patterns, such as nesting wires instead of creating new ones.
-}

{-# LANGUAGE OverloadedStrings #-}

module Test.VeriFuzz.Mutate where

import           Control.Lens
import           Data.Maybe                    (catMaybes)
import           Test.VeriFuzz.Internal.Shared
import           Test.VeriFuzz.VerilogAST

-- | Return if the 'Identifier' is in a 'ModuleDecl'.
inPort :: Identifier -> ModuleDecl -> 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 -> [ModuleItem] -> Maybe Expression
findAssign id items =
  safe last . catMaybes $ isAssign <$> items
  where
    isAssign (Assign ca)
      | ca ^. contAssignNetLVal == id = Just $ ca ^. contAssignExpr
      | otherwise = Nothing

idTrans :: Identifier -> Expression -> Expression -> Expression
idTrans i expr (PrimExpr (PrimId id))
  | id == i = expr
  | otherwise = (PrimExpr (PrimId id))
idTrans _ _ e = e

-- | Nest expressions for a specific 'Identifier'. If the 'Identifier' is not found,
-- the AST is not changed.
nestId :: Identifier -> ModuleDecl -> ModuleDecl
nestId id mod
  | not $ inPort id mod = mod & get %~ trans
  | otherwise = mod
  where
    get = moduleItems . traverse . _Assign . contAssignExpr
    trans = transformOf traverseExpr . idTrans id . PrimExpr . PrimId $ Identifier "RANDOM"

nestSource :: Identifier -> SourceText -> SourceText
nestSource id src =
  src & getSourceText . traverse . getDescription %~ nestId id