aboutsummaryrefslogtreecommitdiffstats
path: root/src/VeriFuzz/Verilog/Arbitrary.hs
blob: 1bcb727dc62b60077c879b57819f9c1564fbc646 (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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
{-|
Module      : Test.VeriFuzz.Verilog.Arbitrary
Description : Arbitrary instances for the AST.
Copyright   : (c) 2018-2019, Yann Herklotz Grave
License     : GPL-3
Maintainer  : ymherklotz [at] gmail [dot] com
Stability   : experimental
Portability : POSIX

Arbitrary instances for the AST.
-}

module Test.VeriFuzz.Verilog.Arbitrary where

import           Control.Monad             (replicateM)
import           Data.Text                 (Text)
import qualified Data.Text                 as T
import qualified Test.QuickCheck           as QC
import           Test.VeriFuzz.Verilog.AST

-- Generate Arbitrary instances for the AST

positiveArb :: (QC.Arbitrary a, Ord a, Num a) => QC.Gen a
positiveArb = QC.suchThat QC.arbitrary (>0)

expr :: Int -> QC.Gen Expr
expr 0 = QC.oneof
  [ Id <$> QC.arbitrary
  , Number <$> positiveArb <*> QC.arbitrary
  , UnOp <$> QC.arbitrary <*> QC.arbitrary
  -- , Str <$> QC.arbitrary
  ]
expr n
  | n > 0 = QC.oneof
    [ Id <$> QC.arbitrary
    , Number <$> positiveArb <*> QC.arbitrary
    , Concat <$> QC.listOf1 (subexpr 4)
    , UnOp <$> QC.arbitrary <*> QC.arbitrary
    -- , Str <$> QC.arbitrary
    , BinOp <$> subexpr 2 <*> QC.arbitrary <*> subexpr 2
    , Cond <$> subexpr 3 <*> subexpr 3 <*> subexpr 3
    ]
  | otherwise = expr 0
  where
    subexpr y = expr (n `div` y)

statement :: Int -> QC.Gen Stmnt
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 Wire <$> positiveArb <*> QC.arbitrary
  , Port <$> (Reg <$> QC.arbitrary) <*> positiveArb <*> QC.arbitrary
  ]

instance QC.Arbitrary Text where
  arbitrary = T.pack <$> QC.arbitrary

instance QC.Arbitrary Identifier where
  arbitrary = do
    l <- QC.choose (2, 10)
    Identifier . T.pack <$> replicateM l (QC.elements ['a'..'z'])

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 PortDir where
  arbitrary = QC.elements [PortIn, PortOut, PortInOut]

instance QC.Arbitrary PortType where
  arbitrary = QC.oneof [pure Wire, Reg <$> QC.arbitrary]

instance QC.Arbitrary Port where
  arbitrary = Port <$> QC.arbitrary <*> positiveArb <*> QC.arbitrary

instance QC.Arbitrary Delay where
  arbitrary = Delay <$> positiveArb

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 <$> positiveArb

instance QC.Arbitrary LVal 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 Expr where
  arbitrary = QC.sized expr

instance QC.Arbitrary Stmnt 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 <$> pure Nothing <*> QC.arbitrary
                       ]

instance QC.Arbitrary ModDecl where
  arbitrary = ModDecl <$> QC.arbitrary <*> 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