{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TemplateHaskell #-}
{-# OPTIONS_GHC -Wno-unused-imports #-}

-- |
-- Module      : Verismith.Generate
-- Description : Various useful generators.
-- Copyright   : (c) 2019, Yann Herklotz
-- License     : GPL-3
-- Maintainer  : yann [at] yannherklotz [dot] com
-- Stability   : experimental
-- Portability : POSIX
--
-- Various useful generators.
module Verismith.Generate
  ( -- * Generation methods
    procedural,
    proceduralIO,
    proceduralSrc,
    proceduralSrcIO,
    randomMod,

    -- ** Data types
    EMIContext (..),
    emiNewInputs,
    Context (..),
    wires,
    nonblocking,
    blocking,
    outofscope,
    parameters,
    modules,
    nameCounter,
    stmntDepth,
    modDepth,
    determinism,
    emiContext,
    StateGen (..),

    -- ** Generate Functions
    largeNum,
    wireSize,
    range,
    genBitVec,
    binOp,
    unOp,
    constExprWithContext,
    exprSafeList,
    exprRecList,
    exprWithContext,
    makeIdentifier,
    nextWirePort,
    nextNBPort,
    nextBPort,
    newWirePort,
    newNBPort,
    newBPort,
    scopedExpr,
    contAssign,
    lvalFromPort,
    assignment,
    seqBlock,
    conditional,
    forLoop,
    statement,
    alwaysSeq,
    instantiate,
    modInst,
    modItem,
    constExpr,
    parameter,
    moduleDef,

    -- ** Helpers
    someI,
    probability,
    askProbability,
    resizePort,
    moduleName,
    evalRange,
    calcRange,
  )
where

import Control.Lens hiding (Context)
import Control.Monad (replicateM)
import Control.Monad.Reader
import Control.Monad.State.Strict
import Data.Foldable (fold)
import Data.Functor.Foldable (cata)
import Data.List (foldl', partition)
import Data.Maybe (fromMaybe)
import Data.Text (Text)
import qualified Data.Text as T
import Hedgehog (Gen, GenT, MonadGen)
import qualified Hedgehog as Hog
import qualified Hedgehog.Gen as Hog
import qualified Hedgehog.Range as Hog
import Verismith.Config
import Verismith.Utils
import Verismith.Verilog.AST
import Verismith.Verilog.BitVec
import Verismith.Verilog.Eval
import Verismith.Verilog.Internal
import Verismith.Verilog.Mutate

data EMIContext = EMIContext
  { EMIContext -> [Port]
_emiNewInputs :: [Port]
  }

makeLenses ''EMIContext

data Context a = Context
  { forall a. Context a -> [Port]
_wires :: [Port],
    forall a. Context a -> [Port]
_nonblocking :: [Port],
    forall a. Context a -> [Port]
_blocking :: [Port],
    forall a. Context a -> [Port]
_outofscope :: [Port],
    forall a. Context a -> [Parameter]
_parameters :: [Parameter],
    forall a. Context a -> [ModDecl a]
_modules :: [ModDecl a],
    forall a. Context a -> Int
_nameCounter :: {-# UNPACK #-} !Int,
    forall a. Context a -> Int
_stmntDepth :: {-# UNPACK #-} !Int,
    forall a. Context a -> Int
_modDepth :: {-# UNPACK #-} !Int,
    forall a. Context a -> Bool
_determinism :: !Bool,
    forall a. Context a -> Maybe EMIContext
_emiContext :: !(Maybe EMIContext)
  }

makeLenses ''Context

type StateGen a = ReaderT Config (GenT (State (Context a)))

toId :: Int -> Identifier
toId :: Int -> Identifier
toId = Text -> Identifier
Identifier (Text -> Identifier) -> (Int -> Text) -> Int -> Identifier
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text
"w" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>) (Text -> Text) -> (Int -> Text) -> Int -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
T.pack (String -> Text) -> (Int -> String) -> Int -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> String
forall a. Show a => a -> String
show

toPort :: (MonadGen m) => Identifier -> m Port
toPort :: forall (m :: * -> *). MonadGen m => Identifier -> m Port
toPort Identifier
ident = do
  Range
i <- m Range
forall (m :: * -> *). MonadGen m => m Range
range
  Port -> m Port
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Port -> m Port) -> Port -> m Port
forall a b. (a -> b) -> a -> b
$ Range -> Identifier -> Port
wire Range
i Identifier
ident

sumSize :: [Port] -> Range
sumSize :: [Port] -> Range
sumSize [Port]
ps = [Range] -> Range
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum ([Range] -> Range) -> [Range] -> Range
forall a b. (a -> b) -> a -> b
$ [Port]
ps [Port] -> Getting (Endo [Range]) [Port] Range -> [Range]
forall s a. s -> Getting (Endo [a]) s a -> [a]
^.. (Port -> Const (Endo [Range]) Port)
-> [Port] -> Const (Endo [Range]) [Port]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> [a] -> f [b]
traverse ((Port -> Const (Endo [Range]) Port)
 -> [Port] -> Const (Endo [Range]) [Port])
-> ((Range -> Const (Endo [Range]) Range)
    -> Port -> Const (Endo [Range]) Port)
-> Getting (Endo [Range]) [Port] Range
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Range -> Const (Endo [Range]) Range)
-> Port -> Const (Endo [Range]) Port
Lens' Port Range
portSize

random :: (MonadGen m) => [Port] -> (Expr -> ContAssign) -> m (ModItem ann)
random :: forall (m :: * -> *) ann.
MonadGen m =>
[Port] -> (Expr -> ContAssign) -> m (ModItem ann)
random [Port]
ctx Expr -> ContAssign
fun = do
  Expr
expr <- (Size -> m Expr) -> m Expr
forall (m :: * -> *) a. MonadGen m => (Size -> m a) -> m a
Hog.sized (ProbExpr -> [Parameter] -> [Port] -> Size -> m Expr
forall (m :: * -> *).
MonadGen m =>
ProbExpr -> [Parameter] -> [Port] -> Size -> m Expr
exprWithContext (Int
-> Int
-> Int
-> Int
-> Int
-> Int
-> Int
-> Int
-> Int
-> Int
-> ProbExpr
ProbExpr Int
1 Int
1 Int
0 Int
1 Int
1 Int
1 Int
1 Int
0 Int
1 Int
1) [] [Port]
ctx)
  ModItem ann -> m (ModItem ann)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (ModItem ann -> m (ModItem ann))
-> (ContAssign -> ModItem ann) -> ContAssign -> m (ModItem ann)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ContAssign -> ModItem ann
forall a. ContAssign -> ModItem a
ModCA (ContAssign -> m (ModItem ann)) -> ContAssign -> m (ModItem ann)
forall a b. (a -> b) -> a -> b
$ Expr -> ContAssign
fun Expr
expr

-- randomAssigns :: [Identifier] -> [Gen ModItem]
-- randomAssigns ids = random ids . ContAssign <$> ids

randomOrdAssigns :: (MonadGen m) => [Port] -> [Port] -> [m (ModItem ann)]
randomOrdAssigns :: forall (m :: * -> *) ann.
MonadGen m =>
[Port] -> [Port] -> [m (ModItem ann)]
randomOrdAssigns [Port]
inp [Port]
ids = ([Port], [m (ModItem ann)]) -> [m (ModItem ann)]
forall a b. (a, b) -> b
snd (([Port], [m (ModItem ann)]) -> [m (ModItem ann)])
-> ([Port], [m (ModItem ann)]) -> [m (ModItem ann)]
forall a b. (a -> b) -> a -> b
$ (Port
 -> ([Port], [m (ModItem ann)]) -> ([Port], [m (ModItem ann)]))
-> ([Port], [m (ModItem ann)])
-> [Port]
-> ([Port], [m (ModItem ann)])
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr Port -> ([Port], [m (ModItem ann)]) -> ([Port], [m (ModItem ann)])
forall {m :: * -> *} {ann}.
MonadGen m =>
Port -> ([Port], [m (ModItem ann)]) -> ([Port], [m (ModItem ann)])
generate ([Port]
inp, []) [Port]
ids
  where
    generate :: Port -> ([Port], [m (ModItem ann)]) -> ([Port], [m (ModItem ann)])
generate Port
cid ([Port]
i, [m (ModItem ann)]
o) = (Port
cid Port -> [Port] -> [Port]
forall a. a -> [a] -> [a]
: [Port]
i, [Port] -> (Expr -> ContAssign) -> m (ModItem ann)
forall (m :: * -> *) ann.
MonadGen m =>
[Port] -> (Expr -> ContAssign) -> m (ModItem ann)
random [Port]
i (Identifier -> Expr -> ContAssign
ContAssign (Port -> Identifier
_portName Port
cid)) m (ModItem ann) -> [m (ModItem ann)] -> [m (ModItem ann)]
forall a. a -> [a] -> [a]
: [m (ModItem ann)]
o)

randomMod :: (MonadGen m) => Int -> Int -> m (ModDecl ann)
randomMod :: forall (m :: * -> *) ann.
MonadGen m =>
Int -> Int -> m (ModDecl ann)
randomMod Int
inps Int
total = do
  [Port]
ident <- [m Port] -> m [Port]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
forall (m :: * -> *) a. Monad m => [m a] -> m [a]
sequence ([m Port] -> m [Port]) -> [m Port] -> m [Port]
forall a b. (a -> b) -> a -> b
$ Identifier -> m Port
forall (m :: * -> *). MonadGen m => Identifier -> m Port
toPort (Identifier -> m Port) -> [Identifier] -> [m Port]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Identifier]
ids
  [ModItem ann]
x <- [m (ModItem ann)] -> m [ModItem ann]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
forall (m :: * -> *) a. Monad m => [m a] -> m [a]
sequence ([m (ModItem ann)] -> m [ModItem ann])
-> [m (ModItem ann)] -> m [ModItem ann]
forall a b. (a -> b) -> a -> b
$ [Port] -> [Port] -> [m (ModItem ann)]
forall (m :: * -> *) ann.
MonadGen m =>
[Port] -> [Port] -> [m (ModItem ann)]
randomOrdAssigns ([Port] -> [Port]
forall {a}. [a] -> [a]
start [Port]
ident) ([Port] -> [Port]
forall {a}. [a] -> [a]
end [Port]
ident)
  let inputs_ :: [Port]
inputs_ = Int -> [Port] -> [Port]
forall a. Int -> [a] -> [a]
take Int
inps [Port]
ident
  let other :: [Port]
other = Int -> [Port] -> [Port]
forall a. Int -> [a] -> [a]
drop Int
inps [Port]
ident
  let y :: ModItem a
y = ContAssign -> ModItem a
forall a. ContAssign -> ModItem a
ModCA (ContAssign -> ModItem a)
-> ([Expr] -> ContAssign) -> [Expr] -> ModItem a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Identifier -> Expr -> ContAssign
ContAssign Identifier
"y" (Expr -> ContAssign) -> ([Expr] -> Expr) -> [Expr] -> ContAssign
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Expr] -> Expr
forall m. Monoid m => [m] -> m
forall (t :: * -> *) m. (Foldable t, Monoid m) => t m -> m
fold ([Expr] -> ModItem a) -> [Expr] -> ModItem a
forall a b. (a -> b) -> a -> b
$ Identifier -> Expr
Id (Identifier -> Expr) -> [Identifier] -> [Expr]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> [Identifier] -> [Identifier]
forall a. Int -> [a] -> [a]
drop Int
inps [Identifier]
ids
  let yport :: [Port]
yport = [Range -> Identifier -> Port
wire ([Port] -> Range
sumSize [Port]
other) Identifier
"y"]
  ModDecl ann -> m (ModDecl ann)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (ModDecl ann -> m (ModDecl ann))
-> (ModDecl ann -> ModDecl ann) -> ModDecl ann -> m (ModDecl ann)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Port] -> ModDecl ann -> ModDecl ann
forall ann. [Port] -> ModDecl ann -> ModDecl ann
declareMod [Port]
other (ModDecl ann -> m (ModDecl ann)) -> ModDecl ann -> m (ModDecl ann)
forall a b. (a -> b) -> a -> b
$
    Identifier
-> [Port] -> [Port] -> [ModItem ann] -> [Parameter] -> ModDecl ann
forall a.
Identifier
-> [Port] -> [Port] -> [ModItem a] -> [Parameter] -> ModDecl a
ModDecl
      Identifier
"test_module"
      [Port]
yport
      [Port]
inputs_
      ([ModItem ann]
x [ModItem ann] -> [ModItem ann] -> [ModItem ann]
forall a. [a] -> [a] -> [a]
++ [ModItem ann
forall {a}. ModItem a
y])
      []
  where
    ids :: [Identifier]
ids = Int -> Identifier
toId (Int -> Identifier) -> [Int] -> [Identifier]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Int
1 .. Int
total]
    end :: [a] -> [a]
end = Int -> [a] -> [a]
forall a. Int -> [a] -> [a]
drop Int
inps
    start :: [a] -> [a]
start = Int -> [a] -> [a]
forall a. Int -> [a] -> [a]
take Int
inps

-- | Converts a 'Port' to an 'LVal' by only keeping the 'Identifier' of the
-- 'Port'.
lvalFromPort :: Port -> LVal
lvalFromPort :: Port -> LVal
lvalFromPort (Port PortType
_ Bool
_ Range
_ Identifier
i) = Identifier -> LVal
RegId Identifier
i

-- | Returns the probability from the configuration.
probability :: Config -> Probability
probability :: Config -> Probability
probability Config
c = Config
c Config -> Getting Probability Config Probability -> Probability
forall s a. s -> Getting a s a -> a
^. Getting Probability Config Probability
Lens' Config Probability
configProbability

-- | Gets the current probabilities from the 'State'.
askProbability :: StateGen ann Probability
askProbability :: forall ann. StateGen ann Probability
askProbability = (Config -> Probability)
-> ReaderT Config (GenT (State (Context ann))) Probability
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks Config -> Probability
probability

-- | Generates a random large number, which can also be negative.
largeNum :: (MonadGen m) => m Int
largeNum :: forall (m :: * -> *). MonadGen m => m Int
largeNum = Range Int -> m Int
forall (m :: * -> *). MonadGen m => Range Int -> m Int
Hog.int (Range Int -> m Int) -> Range Int -> m Int
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Range Int
forall a. Integral a => a -> a -> Range a
Hog.linear (-Int
100) Int
100

-- | Generates a random size for a wire so that it is not too small and not too
-- large.
wireSize :: (MonadGen m) => m Int
wireSize :: forall (m :: * -> *). MonadGen m => m Int
wireSize = Range Int -> m Int
forall (m :: * -> *). MonadGen m => Range Int -> m Int
Hog.int (Range Int -> m Int) -> Range Int -> m Int
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Range Int
forall a. Integral a => a -> a -> Range a
Hog.linear Int
2 Int
100

-- | Generates a random range by using the 'wireSize' and 0 as the lower bound.
range :: (MonadGen m) => m Range
range :: forall (m :: * -> *). MonadGen m => m Range
range = ConstExpr -> ConstExpr -> Range
Range (ConstExpr -> ConstExpr -> Range)
-> m ConstExpr -> m (ConstExpr -> Range)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Int -> ConstExpr) -> m Int -> m ConstExpr
forall a b. (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Int -> ConstExpr
forall a b. (Integral a, Num b) => a -> b
fromIntegral m Int
forall (m :: * -> *). MonadGen m => m Int
wireSize m (ConstExpr -> Range) -> m ConstExpr -> m Range
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ConstExpr -> m ConstExpr
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ConstExpr
0

-- | Generate a random bit vector using 'largeNum'.
genBitVec :: (MonadGen m) => m BitVec
genBitVec :: forall (m :: * -> *). MonadGen m => m BitVec
genBitVec = (Int -> BitVec) -> m Int -> m BitVec
forall a b. (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Int -> BitVec
forall a b. (Integral a, Num b) => a -> b
fromIntegral m Int
forall (m :: * -> *). MonadGen m => m Int
largeNum

-- | Return a random 'BinaryOperator'. This currently excludes 'BinDiv',
-- 'BinMod' because they can take a long time to synthesis, and 'BinCEq',
-- 'BinCNEq', because these are not synthesisable. 'BinPower' is also excluded
-- because it can only be used in conjunction with base powers of 2 which is
-- currently not enforced.
binOp :: (MonadGen m) => m BinaryOperator
binOp :: forall (m :: * -> *). MonadGen m => m BinaryOperator
binOp =
  [BinaryOperator] -> m BinaryOperator
forall (f :: * -> *) (m :: * -> *) a.
(Foldable f, MonadGen m) =>
f a -> m a
Hog.element
    [ BinaryOperator
BinPlus,
      BinaryOperator
BinMinus,
      BinaryOperator
BinTimes,
      -- , BinDiv
      -- , BinMod
      BinaryOperator
BinEq,
      BinaryOperator
BinNEq,
      -- , BinCEq
      -- , BinCNEq
      BinaryOperator
BinLAnd,
      BinaryOperator
BinLOr,
      BinaryOperator
BinLT,
      BinaryOperator
BinLEq,
      BinaryOperator
BinGT,
      BinaryOperator
BinGEq,
      BinaryOperator
BinAnd,
      BinaryOperator
BinOr,
      BinaryOperator
BinXor,
      BinaryOperator
BinXNor,
      BinaryOperator
BinXNorInv,
      -- , BinPower
      BinaryOperator
BinLSL,
      BinaryOperator
BinLSR,
      BinaryOperator
BinASL,
      BinaryOperator
BinASR
    ]

-- | Generate a random 'UnaryOperator'.
unOp :: (MonadGen m) => m UnaryOperator
unOp :: forall (m :: * -> *). MonadGen m => m UnaryOperator
unOp =
  [UnaryOperator] -> m UnaryOperator
forall (f :: * -> *) (m :: * -> *) a.
(Foldable f, MonadGen m) =>
f a -> m a
Hog.element
    [ UnaryOperator
UnPlus,
      UnaryOperator
UnMinus,
      UnaryOperator
UnNot,
      UnaryOperator
UnLNot,
      UnaryOperator
UnAnd,
      UnaryOperator
UnNand,
      UnaryOperator
UnOr,
      UnaryOperator
UnNor,
      UnaryOperator
UnXor,
      UnaryOperator
UnNxor,
      UnaryOperator
UnNxorInv
    ]

-- | Generate a random 'ConstExpr' by using the current context of 'Parameter'.
constExprWithContext :: (MonadGen m) => [Parameter] -> ProbExpr -> Hog.Size -> m ConstExpr
constExprWithContext :: forall (m :: * -> *).
MonadGen m =>
[Parameter] -> ProbExpr -> Size -> m ConstExpr
constExprWithContext [Parameter]
ps ProbExpr
prob Size
size
  | Size
size Size -> Size -> Bool
forall a. Eq a => a -> a -> Bool
== Size
0 =
    [(Int, m ConstExpr)] -> m ConstExpr
forall (m :: * -> *) a. MonadGen m => [(Int, m a)] -> m a
Hog.frequency
      [ (ProbExpr
prob ProbExpr -> Getting Int ProbExpr Int -> Int
forall s a. s -> Getting a s a -> a
^. Getting Int ProbExpr Int
Lens' ProbExpr Int
probExprNum, BitVec -> ConstExpr
ConstNum (BitVec -> ConstExpr) -> m BitVec -> m ConstExpr
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m BitVec
forall (m :: * -> *). MonadGen m => m BitVec
genBitVec),
        ( if [Parameter] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Parameter]
ps then Int
0 else ProbExpr
prob ProbExpr -> Getting Int ProbExpr Int -> Int
forall s a. s -> Getting a s a -> a
^. Getting Int ProbExpr Int
Lens' ProbExpr Int
probExprId,
          Identifier -> ConstExpr
ParamId (Identifier -> ConstExpr)
-> (Parameter -> Identifier) -> Parameter -> ConstExpr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Getting Identifier Parameter Identifier -> Parameter -> Identifier
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting Identifier Parameter Identifier
Lens' Parameter Identifier
paramIdent (Parameter -> ConstExpr) -> m Parameter -> m ConstExpr
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Parameter] -> m Parameter
forall (f :: * -> *) (m :: * -> *) a.
(Foldable f, MonadGen m) =>
f a -> m a
Hog.element [Parameter]
ps
        )
      ]
  | Size
size Size -> Size -> Bool
forall a. Ord a => a -> a -> Bool
> Size
0 =
    [(Int, m ConstExpr)] -> m ConstExpr
forall (m :: * -> *) a. MonadGen m => [(Int, m a)] -> m a
Hog.frequency
      [ (ProbExpr
prob ProbExpr -> Getting Int ProbExpr Int -> Int
forall s a. s -> Getting a s a -> a
^. Getting Int ProbExpr Int
Lens' ProbExpr Int
probExprNum, BitVec -> ConstExpr
ConstNum (BitVec -> ConstExpr) -> m BitVec -> m ConstExpr
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m BitVec
forall (m :: * -> *). MonadGen m => m BitVec
genBitVec),
        ( if [Parameter] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Parameter]
ps then Int
0 else ProbExpr
prob ProbExpr -> Getting Int ProbExpr Int -> Int
forall s a. s -> Getting a s a -> a
^. Getting Int ProbExpr Int
Lens' ProbExpr Int
probExprId,
          Identifier -> ConstExpr
ParamId (Identifier -> ConstExpr)
-> (Parameter -> Identifier) -> Parameter -> ConstExpr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Getting Identifier Parameter Identifier -> Parameter -> Identifier
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting Identifier Parameter Identifier
Lens' Parameter Identifier
paramIdent (Parameter -> ConstExpr) -> m Parameter -> m ConstExpr
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Parameter] -> m Parameter
forall (f :: * -> *) (m :: * -> *) a.
(Foldable f, MonadGen m) =>
f a -> m a
Hog.element [Parameter]
ps
        ),
        (ProbExpr
prob ProbExpr -> Getting Int ProbExpr Int -> Int
forall s a. s -> Getting a s a -> a
^. Getting Int ProbExpr Int
Lens' ProbExpr Int
probExprUnOp, UnaryOperator -> ConstExpr -> ConstExpr
ConstUnOp (UnaryOperator -> ConstExpr -> ConstExpr)
-> m UnaryOperator -> m (ConstExpr -> ConstExpr)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m UnaryOperator
forall (m :: * -> *). MonadGen m => m UnaryOperator
unOp m (ConstExpr -> ConstExpr) -> m ConstExpr -> m ConstExpr
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Size -> m ConstExpr
forall {m :: * -> *}. MonadGen m => Size -> m ConstExpr
subexpr Size
2),
        ( ProbExpr
prob ProbExpr -> Getting Int ProbExpr Int -> Int
forall s a. s -> Getting a s a -> a
^. Getting Int ProbExpr Int
Lens' ProbExpr Int
probExprBinOp,
          ConstExpr -> BinaryOperator -> ConstExpr -> ConstExpr
ConstBinOp (ConstExpr -> BinaryOperator -> ConstExpr -> ConstExpr)
-> m ConstExpr -> m (BinaryOperator -> ConstExpr -> ConstExpr)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Size -> m ConstExpr
forall {m :: * -> *}. MonadGen m => Size -> m ConstExpr
subexpr Size
2 m (BinaryOperator -> ConstExpr -> ConstExpr)
-> m BinaryOperator -> m (ConstExpr -> ConstExpr)
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> m BinaryOperator
forall (m :: * -> *). MonadGen m => m BinaryOperator
binOp m (ConstExpr -> ConstExpr) -> m ConstExpr -> m ConstExpr
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Size -> m ConstExpr
forall {m :: * -> *}. MonadGen m => Size -> m ConstExpr
subexpr Size
2
        ),
        ( ProbExpr
prob ProbExpr -> Getting Int ProbExpr Int -> Int
forall s a. s -> Getting a s a -> a
^. Getting Int ProbExpr Int
Lens' ProbExpr Int
probExprCond,
          ConstExpr -> ConstExpr -> ConstExpr -> ConstExpr
ConstCond (ConstExpr -> ConstExpr -> ConstExpr -> ConstExpr)
-> m ConstExpr -> m (ConstExpr -> ConstExpr -> ConstExpr)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Size -> m ConstExpr
forall {m :: * -> *}. MonadGen m => Size -> m ConstExpr
subexpr Size
2 m (ConstExpr -> ConstExpr -> ConstExpr)
-> m ConstExpr -> m (ConstExpr -> ConstExpr)
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Size -> m ConstExpr
forall {m :: * -> *}. MonadGen m => Size -> m ConstExpr
subexpr Size
2 m (ConstExpr -> ConstExpr) -> m ConstExpr -> m ConstExpr
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Size -> m ConstExpr
forall {m :: * -> *}. MonadGen m => Size -> m ConstExpr
subexpr Size
2
        ),
        ( ProbExpr
prob ProbExpr -> Getting Int ProbExpr Int -> Int
forall s a. s -> Getting a s a -> a
^. Getting Int ProbExpr Int
Lens' ProbExpr Int
probExprConcat,
          NonEmpty ConstExpr -> ConstExpr
ConstConcat (NonEmpty ConstExpr -> ConstExpr)
-> m (NonEmpty ConstExpr) -> m ConstExpr
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Range Int -> m ConstExpr -> m (NonEmpty ConstExpr)
forall (m :: * -> *) a.
MonadGen m =>
Range Int -> m a -> m (NonEmpty a)
Hog.nonEmpty (Int -> Int -> Range Int
forall a. Integral a => a -> a -> Range a
Hog.linear Int
0 Int
10) (Size -> m ConstExpr
forall {m :: * -> *}. MonadGen m => Size -> m ConstExpr
subexpr Size
2)
        )
      ]
  | Bool
otherwise = [Parameter] -> ProbExpr -> Size -> m ConstExpr
forall (m :: * -> *).
MonadGen m =>
[Parameter] -> ProbExpr -> Size -> m ConstExpr
constExprWithContext [Parameter]
ps ProbExpr
prob Size
0
  where
    subexpr :: Size -> m ConstExpr
subexpr Size
y = [Parameter] -> ProbExpr -> Size -> m ConstExpr
forall (m :: * -> *).
MonadGen m =>
[Parameter] -> ProbExpr -> Size -> m ConstExpr
constExprWithContext [Parameter]
ps ProbExpr
prob (Size -> m ConstExpr) -> Size -> m ConstExpr
forall a b. (a -> b) -> a -> b
$ Size
size Size -> Size -> Size
forall a. Integral a => a -> a -> a
`div` Size
y

-- | The list of safe 'Expr', meaning that these will not recurse and will end
-- the 'Expr' generation.
exprSafeList :: (MonadGen m) => ProbExpr -> [(Int, m Expr)]
exprSafeList :: forall (m :: * -> *). MonadGen m => ProbExpr -> [(Int, m Expr)]
exprSafeList ProbExpr
prob = [(ProbExpr
prob ProbExpr -> Getting Int ProbExpr Int -> Int
forall s a. s -> Getting a s a -> a
^. Getting Int ProbExpr Int
Lens' ProbExpr Int
probExprNum, BitVec -> Expr
Number (BitVec -> Expr) -> m BitVec -> m Expr
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m BitVec
forall (m :: * -> *). MonadGen m => m BitVec
genBitVec)]

-- | List of 'Expr' that have the chance to recurse and will therefore not be
-- used when the expression grows too large.
exprRecList :: (MonadGen m) => ProbExpr -> (Hog.Size -> m Expr) -> [(Int, m Expr)]
exprRecList :: forall (m :: * -> *).
MonadGen m =>
ProbExpr -> (Size -> m Expr) -> [(Int, m Expr)]
exprRecList ProbExpr
prob Size -> m Expr
subexpr =
  [ (ProbExpr
prob ProbExpr -> Getting Int ProbExpr Int -> Int
forall s a. s -> Getting a s a -> a
^. Getting Int ProbExpr Int
Lens' ProbExpr Int
probExprNum, BitVec -> Expr
Number (BitVec -> Expr) -> m BitVec -> m Expr
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m BitVec
forall (m :: * -> *). MonadGen m => m BitVec
genBitVec),
    ( ProbExpr
prob ProbExpr -> Getting Int ProbExpr Int -> Int
forall s a. s -> Getting a s a -> a
^. Getting Int ProbExpr Int
Lens' ProbExpr Int
probExprConcat,
      NonEmpty Expr -> Expr
Concat (NonEmpty Expr -> Expr) -> m (NonEmpty Expr) -> m Expr
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Range Int -> m Expr -> m (NonEmpty Expr)
forall (m :: * -> *) a.
MonadGen m =>
Range Int -> m a -> m (NonEmpty a)
Hog.nonEmpty (Int -> Int -> Range Int
forall a. Integral a => a -> a -> Range a
Hog.linear Int
0 Int
10) (Size -> m Expr
subexpr Size
2)
    ),
    (ProbExpr
prob ProbExpr -> Getting Int ProbExpr Int -> Int
forall s a. s -> Getting a s a -> a
^. Getting Int ProbExpr Int
Lens' ProbExpr Int
probExprUnOp, UnaryOperator -> Expr -> Expr
UnOp (UnaryOperator -> Expr -> Expr)
-> m UnaryOperator -> m (Expr -> Expr)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m UnaryOperator
forall (m :: * -> *). MonadGen m => m UnaryOperator
unOp m (Expr -> Expr) -> m Expr -> m Expr
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Size -> m Expr
subexpr Size
2),
    (ProbExpr
prob ProbExpr -> Getting Int ProbExpr Int -> Int
forall s a. s -> Getting a s a -> a
^. Getting Int ProbExpr Int
Lens' ProbExpr Int
probExprStr, Text -> Expr
Str (Text -> Expr) -> m Text -> m Expr
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Range Int -> m Char -> m Text
forall (m :: * -> *). MonadGen m => Range Int -> m Char -> m Text
Hog.text (Int -> Int -> Range Int
forall a. Integral a => a -> a -> Range a
Hog.linear Int
0 Int
100) m Char
forall (m :: * -> *). MonadGen m => m Char
Hog.alphaNum),
    (ProbExpr
prob ProbExpr -> Getting Int ProbExpr Int -> Int
forall s a. s -> Getting a s a -> a
^. Getting Int ProbExpr Int
Lens' ProbExpr Int
probExprBinOp, Expr -> BinaryOperator -> Expr -> Expr
BinOp (Expr -> BinaryOperator -> Expr -> Expr)
-> m Expr -> m (BinaryOperator -> Expr -> Expr)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Size -> m Expr
subexpr Size
2 m (BinaryOperator -> Expr -> Expr)
-> m BinaryOperator -> m (Expr -> Expr)
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> m BinaryOperator
forall (m :: * -> *). MonadGen m => m BinaryOperator
binOp m (Expr -> Expr) -> m Expr -> m Expr
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Size -> m Expr
subexpr Size
2),
    (ProbExpr
prob ProbExpr -> Getting Int ProbExpr Int -> Int
forall s a. s -> Getting a s a -> a
^. Getting Int ProbExpr Int
Lens' ProbExpr Int
probExprCond, Expr -> Expr -> Expr -> Expr
Cond (Expr -> Expr -> Expr -> Expr)
-> m Expr -> m (Expr -> Expr -> Expr)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Size -> m Expr
subexpr Size
2 m (Expr -> Expr -> Expr) -> m Expr -> m (Expr -> Expr)
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Size -> m Expr
subexpr Size
2 m (Expr -> Expr) -> m Expr -> m Expr
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Size -> m Expr
subexpr Size
2),
    (ProbExpr
prob ProbExpr -> Getting Int ProbExpr Int -> Int
forall s a. s -> Getting a s a -> a
^. Getting Int ProbExpr Int
Lens' ProbExpr Int
probExprSigned, Identifier -> Expr -> Expr
Appl (Identifier -> Expr -> Expr) -> m Identifier -> m (Expr -> Expr)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Identifier -> m Identifier
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Identifier
"$signed" m (Expr -> Expr) -> m Expr -> m Expr
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Size -> m Expr
subexpr Size
2),
    (ProbExpr
prob ProbExpr -> Getting Int ProbExpr Int -> Int
forall s a. s -> Getting a s a -> a
^. Getting Int ProbExpr Int
Lens' ProbExpr Int
probExprUnsigned, Identifier -> Expr -> Expr
Appl (Identifier -> Expr -> Expr) -> m Identifier -> m (Expr -> Expr)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Identifier -> m Identifier
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Identifier
"$unsigned" m (Expr -> Expr) -> m Expr -> m Expr
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Size -> m Expr
subexpr Size
2)
  ]

-- | Select a random port from a list of ports and generate a safe bit selection
-- for that port.
rangeSelect :: (MonadGen m) => [Parameter] -> [Port] -> m Expr
rangeSelect :: forall (m :: * -> *). MonadGen m => [Parameter] -> [Port] -> m Expr
rangeSelect [Parameter]
ps [Port]
ports = do
  Port
p <- [Port] -> m Port
forall (f :: * -> *) (m :: * -> *) a.
(Foldable f, MonadGen m) =>
f a -> m a
Hog.element [Port]
ports
  let s :: Int
s = [Parameter] -> Maybe Int -> Range -> Int
calcRange [Parameter]
ps (Int -> Maybe Int
forall a. a -> Maybe a
Just Int
32) (Range -> Int) -> Range -> Int
forall a b. (a -> b) -> a -> b
$ Port -> Range
_portSize Port
p
  Int
msb <- Range Int -> m Int
forall (m :: * -> *). MonadGen m => Range Int -> m Int
Hog.int (Int -> Int -> Int -> Range Int
forall a. a -> a -> a -> Range a
Hog.constantFrom (Int
s Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` Int
2) Int
0 (Int
s Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1))
  Int
lsb <- Range Int -> m Int
forall (m :: * -> *). MonadGen m => Range Int -> m Int
Hog.int (Int -> Int -> Int -> Range Int
forall a. a -> a -> a -> Range a
Hog.constantFrom (Int
msb Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` Int
2) Int
0 Int
msb)
  Expr -> m Expr
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Expr -> m Expr) -> (Range -> Expr) -> Range -> m Expr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Identifier -> Range -> Expr
RangeSelect (Port -> Identifier
_portName Port
p) (Range -> m Expr) -> Range -> m Expr
forall a b. (a -> b) -> a -> b
$
    ConstExpr -> ConstExpr -> Range
Range
      (Int -> ConstExpr
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
msb)
      (Int -> ConstExpr
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
lsb)

-- | Generate a random expression from the 'Context' with a guarantee that it
-- will terminate using the list of safe 'Expr'.
exprWithContext :: (MonadGen m) => ProbExpr -> [Parameter] -> [Port] -> Hog.Size -> m Expr
exprWithContext :: forall (m :: * -> *).
MonadGen m =>
ProbExpr -> [Parameter] -> [Port] -> Size -> m Expr
exprWithContext ProbExpr
prob [Parameter]
ps [] Size
n
  | Size
n Size -> Size -> Bool
forall a. Eq a => a -> a -> Bool
== Size
0 = [(Int, m Expr)] -> m Expr
forall (m :: * -> *) a. MonadGen m => [(Int, m a)] -> m a
Hog.frequency ([(Int, m Expr)] -> m Expr) -> [(Int, m Expr)] -> m Expr
forall a b. (a -> b) -> a -> b
$ ProbExpr -> [(Int, m Expr)]
forall (m :: * -> *). MonadGen m => ProbExpr -> [(Int, m Expr)]
exprSafeList ProbExpr
prob
  | Size
n Size -> Size -> Bool
forall a. Ord a => a -> a -> Bool
> Size
0 = [(Int, m Expr)] -> m Expr
forall (m :: * -> *) a. MonadGen m => [(Int, m a)] -> m a
Hog.frequency ([(Int, m Expr)] -> m Expr) -> [(Int, m Expr)] -> m Expr
forall a b. (a -> b) -> a -> b
$ ProbExpr -> (Size -> m Expr) -> [(Int, m Expr)]
forall (m :: * -> *).
MonadGen m =>
ProbExpr -> (Size -> m Expr) -> [(Int, m Expr)]
exprRecList ProbExpr
prob Size -> m Expr
forall {m :: * -> *}. MonadGen m => Size -> m Expr
subexpr
  | Bool
otherwise = ProbExpr -> [Parameter] -> [Port] -> Size -> m Expr
forall (m :: * -> *).
MonadGen m =>
ProbExpr -> [Parameter] -> [Port] -> Size -> m Expr
exprWithContext ProbExpr
prob [Parameter]
ps [] Size
0
  where
    subexpr :: Size -> m Expr
subexpr Size
y = ProbExpr -> [Parameter] -> [Port] -> Size -> m Expr
forall (m :: * -> *).
MonadGen m =>
ProbExpr -> [Parameter] -> [Port] -> Size -> m Expr
exprWithContext ProbExpr
prob [Parameter]
ps [] (Size -> m Expr) -> Size -> m Expr
forall a b. (a -> b) -> a -> b
$ Size
n Size -> Size -> Size
forall a. Integral a => a -> a -> a
`div` Size
y
exprWithContext ProbExpr
prob [Parameter]
ps [Port]
l Size
n
  | Size
n Size -> Size -> Bool
forall a. Eq a => a -> a -> Bool
== Size
0 =
    [(Int, m Expr)] -> m Expr
forall (m :: * -> *) a. MonadGen m => [(Int, m a)] -> m a
Hog.frequency ([(Int, m Expr)] -> m Expr) -> [(Int, m Expr)] -> m Expr
forall a b. (a -> b) -> a -> b
$
      (ProbExpr
prob ProbExpr -> Getting Int ProbExpr Int -> Int
forall s a. s -> Getting a s a -> a
^. Getting Int ProbExpr Int
Lens' ProbExpr Int
probExprId, Identifier -> Expr
Id (Identifier -> Expr) -> (Port -> Identifier) -> Port -> Expr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Port -> Identifier
fromPort (Port -> Expr) -> m Port -> m Expr
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Port] -> m Port
forall (f :: * -> *) (m :: * -> *) a.
(Foldable f, MonadGen m) =>
f a -> m a
Hog.element [Port]
l) (Int, m Expr) -> [(Int, m Expr)] -> [(Int, m Expr)]
forall a. a -> [a] -> [a]
:
      ProbExpr -> [(Int, m Expr)]
forall (m :: * -> *). MonadGen m => ProbExpr -> [(Int, m Expr)]
exprSafeList ProbExpr
prob
  | Size
n Size -> Size -> Bool
forall a. Ord a => a -> a -> Bool
> Size
0 =
    [(Int, m Expr)] -> m Expr
forall (m :: * -> *) a. MonadGen m => [(Int, m a)] -> m a
Hog.frequency ([(Int, m Expr)] -> m Expr) -> [(Int, m Expr)] -> m Expr
forall a b. (a -> b) -> a -> b
$
      (ProbExpr
prob ProbExpr -> Getting Int ProbExpr Int -> Int
forall s a. s -> Getting a s a -> a
^. Getting Int ProbExpr Int
Lens' ProbExpr Int
probExprId, Identifier -> Expr
Id (Identifier -> Expr) -> (Port -> Identifier) -> Port -> Expr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Port -> Identifier
fromPort (Port -> Expr) -> m Port -> m Expr
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Port] -> m Port
forall (f :: * -> *) (m :: * -> *) a.
(Foldable f, MonadGen m) =>
f a -> m a
Hog.element [Port]
l) (Int, m Expr) -> [(Int, m Expr)] -> [(Int, m Expr)]
forall a. a -> [a] -> [a]
:
      (ProbExpr
prob ProbExpr -> Getting Int ProbExpr Int -> Int
forall s a. s -> Getting a s a -> a
^. Getting Int ProbExpr Int
Lens' ProbExpr Int
probExprRangeSelect, [Parameter] -> [Port] -> m Expr
forall (m :: * -> *). MonadGen m => [Parameter] -> [Port] -> m Expr
rangeSelect [Parameter]
ps [Port]
l) (Int, m Expr) -> [(Int, m Expr)] -> [(Int, m Expr)]
forall a. a -> [a] -> [a]
:
      ProbExpr -> (Size -> m Expr) -> [(Int, m Expr)]
forall (m :: * -> *).
MonadGen m =>
ProbExpr -> (Size -> m Expr) -> [(Int, m Expr)]
exprRecList ProbExpr
prob Size -> m Expr
forall {m :: * -> *}. MonadGen m => Size -> m Expr
subexpr
  | Bool
otherwise =
    ProbExpr -> [Parameter] -> [Port] -> Size -> m Expr
forall (m :: * -> *).
MonadGen m =>
ProbExpr -> [Parameter] -> [Port] -> Size -> m Expr
exprWithContext ProbExpr
prob [Parameter]
ps [Port]
l Size
0
  where
    subexpr :: Size -> m Expr
subexpr Size
y = ProbExpr -> [Parameter] -> [Port] -> Size -> m Expr
forall (m :: * -> *).
MonadGen m =>
ProbExpr -> [Parameter] -> [Port] -> Size -> m Expr
exprWithContext ProbExpr
prob [Parameter]
ps [Port]
l (Size -> m Expr) -> Size -> m Expr
forall a b. (a -> b) -> a -> b
$ Size
n Size -> Size -> Size
forall a. Integral a => a -> a -> a
`div` Size
y

-- | Runs a 'StateGen' for a random number of times, limited by an 'Int' that is
-- passed to it.
someI :: Int -> StateGen ann a -> StateGen ann [a]
someI :: forall ann a. Int -> StateGen ann a -> StateGen ann [a]
someI Int
m StateGen ann a
f = do
  Int
amount <- Range Int -> ReaderT Config (GenT (State (Context ann))) Int
forall (m :: * -> *). MonadGen m => Range Int -> m Int
Hog.int (Int -> Int -> Range Int
forall a. Integral a => a -> a -> Range a
Hog.linear Int
1 Int
m)
  Int -> StateGen ann a -> StateGen ann [a]
forall (m :: * -> *) a. Applicative m => Int -> m a -> m [a]
replicateM Int
amount StateGen ann a
f

-- | Make a new name with a prefix and the current nameCounter. The nameCounter
-- is then increased so that the label is unique.
makeIdentifier :: Text -> StateGen ann Identifier
makeIdentifier :: forall ann. Text -> StateGen ann Identifier
makeIdentifier Text
prefix = do
  Context ann
context <- ReaderT Config (GenT (State (Context ann))) (Context ann)
forall s (m :: * -> *). MonadState s m => m s
get
  let ident :: Identifier
ident = Text -> Identifier
Identifier (Text -> Identifier) -> Text -> Identifier
forall a b. (a -> b) -> a -> b
$ Text
prefix Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Int -> Text
forall a. Show a => a -> Text
showT (Context ann
context Context ann -> Getting Int (Context ann) Int -> Int
forall s a. s -> Getting a s a -> a
^. Getting Int (Context ann) Int
forall a (f :: * -> *).
Functor f =>
(Int -> f Int) -> Context a -> f (Context a)
nameCounter)
  (Int -> Identity Int) -> Context ann -> Identity (Context ann)
forall a (f :: * -> *).
Functor f =>
(Int -> f Int) -> Context a -> f (Context a)
nameCounter ((Int -> Identity Int) -> Context ann -> Identity (Context ann))
-> Int -> ReaderT Config (GenT (State (Context ann))) ()
forall s (m :: * -> *) a.
(MonadState s m, Num a) =>
ASetter' s a -> a -> m ()
+= Int
1
  Identifier -> StateGen ann Identifier
forall a. a -> ReaderT Config (GenT (State (Context ann))) a
forall (m :: * -> *) a. Monad m => a -> m a
return Identifier
ident

newPort_ :: Bool -> PortType -> Identifier -> StateGen ann Port
newPort_ :: forall ann. Bool -> PortType -> Identifier -> StateGen ann Port
newPort_ Bool
blk PortType
pt Identifier
ident = do
  Port
p <- PortType -> Bool -> Range -> Identifier -> Port
Port PortType
pt (Bool -> Range -> Identifier -> Port)
-> ReaderT Config (GenT (State (Context ann))) Bool
-> ReaderT
     Config (GenT (State (Context ann))) (Range -> Identifier -> Port)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ReaderT Config (GenT (State (Context ann))) Bool
forall (m :: * -> *). MonadGen m => m Bool
Hog.bool ReaderT
  Config (GenT (State (Context ann))) (Range -> Identifier -> Port)
-> ReaderT Config (GenT (State (Context ann))) Range
-> ReaderT Config (GenT (State (Context ann))) (Identifier -> Port)
forall a b.
ReaderT Config (GenT (State (Context ann))) (a -> b)
-> ReaderT Config (GenT (State (Context ann))) a
-> ReaderT Config (GenT (State (Context ann))) b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ReaderT Config (GenT (State (Context ann))) Range
forall (m :: * -> *). MonadGen m => m Range
range ReaderT Config (GenT (State (Context ann))) (Identifier -> Port)
-> ReaderT Config (GenT (State (Context ann))) Identifier
-> StateGen ann Port
forall a b.
ReaderT Config (GenT (State (Context ann))) (a -> b)
-> ReaderT Config (GenT (State (Context ann))) a
-> ReaderT Config (GenT (State (Context ann))) b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Identifier
-> ReaderT Config (GenT (State (Context ann))) Identifier
forall a. a -> ReaderT Config (GenT (State (Context ann))) a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Identifier
ident
  case PortType
pt of
    PortType
Reg -> if Bool
blk then ([Port] -> Identity [Port])
-> Context ann -> Identity (Context ann)
forall a (f :: * -> *).
Functor f =>
([Port] -> f [Port]) -> Context a -> f (Context a)
blocking (([Port] -> Identity [Port])
 -> Context ann -> Identity (Context ann))
-> ([Port] -> [Port])
-> ReaderT Config (GenT (State (Context ann))) ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> (a -> b) -> m ()
%= (Port
p Port -> [Port] -> [Port]
forall a. a -> [a] -> [a]
:) else ([Port] -> Identity [Port])
-> Context ann -> Identity (Context ann)
forall a (f :: * -> *).
Functor f =>
([Port] -> f [Port]) -> Context a -> f (Context a)
nonblocking (([Port] -> Identity [Port])
 -> Context ann -> Identity (Context ann))
-> ([Port] -> [Port])
-> ReaderT Config (GenT (State (Context ann))) ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> (a -> b) -> m ()
%= (Port
p Port -> [Port] -> [Port]
forall a. a -> [a] -> [a]
:)
    PortType
Wire -> ([Port] -> Identity [Port])
-> Context ann -> Identity (Context ann)
forall a (f :: * -> *).
Functor f =>
([Port] -> f [Port]) -> Context a -> f (Context a)
wires (([Port] -> Identity [Port])
 -> Context ann -> Identity (Context ann))
-> ([Port] -> [Port])
-> ReaderT Config (GenT (State (Context ann))) ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> (a -> b) -> m ()
%= (Port
p Port -> [Port] -> [Port]
forall a. a -> [a] -> [a]
:)
  Port -> StateGen ann Port
forall a. a -> ReaderT Config (GenT (State (Context ann))) a
forall (m :: * -> *) a. Monad m => a -> m a
return Port
p

-- | Creates a new port based on the current name counter and adds it to the
-- current context.  It will be added to the '_wires' list.
newWirePort :: Identifier -> StateGen ann Port
newWirePort :: forall ann. Identifier -> StateGen ann Port
newWirePort = Bool -> PortType -> Identifier -> StateGen ann Port
forall ann. Bool -> PortType -> Identifier -> StateGen ann Port
newPort_ Bool
False PortType
Wire

-- | Creates a new port based on the current name counter and adds it to the
-- current context.  It will be added to the '_nonblocking' list.
newNBPort :: Identifier -> StateGen ann Port
newNBPort :: forall ann. Identifier -> StateGen ann Port
newNBPort = Bool -> PortType -> Identifier -> StateGen ann Port
forall ann. Bool -> PortType -> Identifier -> StateGen ann Port
newPort_ Bool
False PortType
Reg

-- | Creates a new port based on the current name counter and adds it to the
-- current context.  It will be added to the '_blocking' list.
newBPort :: Identifier -> StateGen ann Port
newBPort :: forall ann. Identifier -> StateGen ann Port
newBPort = Bool -> PortType -> Identifier -> StateGen ann Port
forall ann. Bool -> PortType -> Identifier -> StateGen ann Port
newPort_ Bool
True PortType
Reg

getPort' :: Bool -> PortType -> Identifier -> StateGen ann (Maybe Port)
getPort' :: forall ann.
Bool -> PortType -> Identifier -> StateGen ann (Maybe Port)
getPort' Bool
blk PortType
pt Identifier
i = do
  Context ann
cont <- ReaderT Config (GenT (State (Context ann))) (Context ann)
forall s (m :: * -> *). MonadState s m => m s
get
  let b :: [Port]
b = Context ann -> [Port]
forall a. Context a -> [Port]
_blocking Context ann
cont
  let nb :: [Port]
nb = Context ann -> [Port]
forall a. Context a -> [Port]
_nonblocking Context ann
cont
  let w :: [Port]
w = Context ann -> [Port]
forall a. Context a -> [Port]
_wires Context ann
cont
  let ([Port]
c, [Port]
nc) =
        case PortType
pt of
          PortType
Reg -> if Bool
blk then ([Port]
b, [Port]
nb [Port] -> [Port] -> [Port]
forall a. Semigroup a => a -> a -> a
<> [Port]
w) else ([Port]
nb, [Port]
b [Port] -> [Port] -> [Port]
forall a. Semigroup a => a -> a -> a
<> [Port]
w)
          PortType
Wire -> ([Port]
w, [Port]
b [Port] -> [Port] -> [Port]
forall a. Semigroup a => a -> a -> a
<> [Port]
nb)
  case ((Port -> Bool) -> [Port] -> [Port]
forall a. (a -> Bool) -> [a] -> [a]
filter Port -> Bool
portId [Port]
c, (Port -> Bool) -> [Port] -> [Port]
forall a. (a -> Bool) -> [a] -> [a]
filter Port -> Bool
portId [Port]
nc) of
    ([Port]
_, Port
x : [Port]
_) -> Maybe Port -> StateGen ann (Maybe Port)
forall a. a -> ReaderT Config (GenT (State (Context ann))) a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe Port
forall a. Maybe a
Nothing
    (Port
x : [Port]
_, []) -> Maybe Port -> StateGen ann (Maybe Port)
forall a. a -> ReaderT Config (GenT (State (Context ann))) a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe Port -> StateGen ann (Maybe Port))
-> Maybe Port -> StateGen ann (Maybe Port)
forall a b. (a -> b) -> a -> b
$ Port -> Maybe Port
forall a. a -> Maybe a
Just Port
x
    ([], []) ->
      (Port -> Maybe Port)
-> ReaderT Config (GenT (State (Context ann))) Port
-> StateGen ann (Maybe Port)
forall a b.
(a -> b)
-> ReaderT Config (GenT (State (Context ann))) a
-> ReaderT Config (GenT (State (Context ann))) b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap
        Port -> Maybe Port
forall a. a -> Maybe a
Just
        ( case PortType
pt of
            PortType
Reg -> if Bool
blk then Identifier -> ReaderT Config (GenT (State (Context ann))) Port
forall ann. Identifier -> StateGen ann Port
newBPort Identifier
i else Identifier -> ReaderT Config (GenT (State (Context ann))) Port
forall ann. Identifier -> StateGen ann Port
newNBPort Identifier
i
            PortType
Wire -> Identifier -> ReaderT Config (GenT (State (Context ann))) Port
forall ann. Identifier -> StateGen ann Port
newWirePort Identifier
i
        )
  where
    portId :: Port -> Bool
portId (Port PortType
pt' Bool
_ Range
_ Identifier
i') = Identifier
i Identifier -> Identifier -> Bool
forall a. Eq a => a -> a -> Bool
== Identifier
i' Bool -> Bool -> Bool
&& PortType
pt PortType -> PortType -> Bool
forall a. Eq a => a -> a -> Bool
== PortType
pt'

try :: StateGen ann (Maybe a) -> StateGen ann a
try :: forall ann a. StateGen ann (Maybe a) -> StateGen ann a
try StateGen ann (Maybe a)
a = do
  Maybe a
r <- StateGen ann (Maybe a)
a
  case Maybe a
r of
    Maybe a
Nothing -> StateGen ann (Maybe a) -> StateGen ann a
forall ann a. StateGen ann (Maybe a) -> StateGen ann a
try StateGen ann (Maybe a)
a
    Just a
res -> a -> StateGen ann a
forall a. a -> ReaderT Config (GenT (State (Context ann))) a
forall (m :: * -> *) a. Monad m => a -> m a
return a
res

-- | Makes a new 'Identifier' and then checks if the 'Port' already exists, if
-- it does the existant 'Port' is returned, otherwise a new port is created with
-- 'newPort'. This is used subsequently in all the functions to create a port,
-- in case a port with the same name was already created. This could be because
-- the generation is currently in the other branch of an if-statement.
nextWirePort :: Maybe Text -> StateGen ann Port
nextWirePort :: forall ann. Maybe Text -> StateGen ann Port
nextWirePort Maybe Text
i = StateGen ann (Maybe Port) -> StateGen ann Port
forall ann a. StateGen ann (Maybe a) -> StateGen ann a
try (StateGen ann (Maybe Port) -> StateGen ann Port)
-> StateGen ann (Maybe Port) -> StateGen ann Port
forall a b. (a -> b) -> a -> b
$ do
  Identifier
ident <- Text -> StateGen ann Identifier
forall ann. Text -> StateGen ann Identifier
makeIdentifier (Text -> StateGen ann Identifier)
-> Text -> StateGen ann Identifier
forall a b. (a -> b) -> a -> b
$ Text -> Maybe Text -> Text
forall a. a -> Maybe a -> a
fromMaybe (Text -> Text
T.toLower (Text -> Text) -> Text -> Text
forall a b. (a -> b) -> a -> b
$ PortType -> Text
forall a. Show a => a -> Text
showT PortType
Wire) Maybe Text
i
  Bool -> PortType -> Identifier -> StateGen ann (Maybe Port)
forall ann.
Bool -> PortType -> Identifier -> StateGen ann (Maybe Port)
getPort' Bool
False PortType
Wire Identifier
ident

nextNBPort :: Maybe Text -> StateGen ann Port
nextNBPort :: forall ann. Maybe Text -> StateGen ann Port
nextNBPort Maybe Text
i = StateGen ann (Maybe Port) -> StateGen ann Port
forall ann a. StateGen ann (Maybe a) -> StateGen ann a
try (StateGen ann (Maybe Port) -> StateGen ann Port)
-> StateGen ann (Maybe Port) -> StateGen ann Port
forall a b. (a -> b) -> a -> b
$ do
  Identifier
ident <- Text -> StateGen ann Identifier
forall ann. Text -> StateGen ann Identifier
makeIdentifier (Text -> StateGen ann Identifier)
-> Text -> StateGen ann Identifier
forall a b. (a -> b) -> a -> b
$ Text -> Maybe Text -> Text
forall a. a -> Maybe a -> a
fromMaybe (Text -> Text
T.toLower (Text -> Text) -> Text -> Text
forall a b. (a -> b) -> a -> b
$ PortType -> Text
forall a. Show a => a -> Text
showT PortType
Reg) Maybe Text
i
  Bool -> PortType -> Identifier -> StateGen ann (Maybe Port)
forall ann.
Bool -> PortType -> Identifier -> StateGen ann (Maybe Port)
getPort' Bool
False PortType
Reg Identifier
ident

nextBPort :: Maybe Text -> StateGen ann Port
nextBPort :: forall ann. Maybe Text -> StateGen ann Port
nextBPort Maybe Text
i = StateGen ann (Maybe Port) -> StateGen ann Port
forall ann a. StateGen ann (Maybe a) -> StateGen ann a
try (StateGen ann (Maybe Port) -> StateGen ann Port)
-> StateGen ann (Maybe Port) -> StateGen ann Port
forall a b. (a -> b) -> a -> b
$ do
  Identifier
ident <- Text -> StateGen ann Identifier
forall ann. Text -> StateGen ann Identifier
makeIdentifier (Text -> StateGen ann Identifier)
-> Text -> StateGen ann Identifier
forall a b. (a -> b) -> a -> b
$ Text -> Maybe Text -> Text
forall a. a -> Maybe a -> a
fromMaybe (Text -> Text
T.toLower (Text -> Text) -> Text -> Text
forall a b. (a -> b) -> a -> b
$ PortType -> Text
forall a. Show a => a -> Text
showT PortType
Reg) Maybe Text
i
  Bool -> PortType -> Identifier -> StateGen ann (Maybe Port)
forall ann.
Bool -> PortType -> Identifier -> StateGen ann (Maybe Port)
getPort' Bool
True PortType
Reg Identifier
ident

allVariables :: StateGen ann [Port]
allVariables :: forall ann. StateGen ann [Port]
allVariables =
  (Context ann -> [Port])
-> ReaderT Config (GenT (State (Context ann))) (Context ann)
-> ReaderT Config (GenT (State (Context ann))) [Port]
forall a b.
(a -> b)
-> ReaderT Config (GenT (State (Context ann))) a
-> ReaderT Config (GenT (State (Context ann))) b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\Context ann
context -> Context ann -> [Port]
forall a. Context a -> [Port]
_wires Context ann
context [Port] -> [Port] -> [Port]
forall a. Semigroup a => a -> a -> a
<> Context ann -> [Port]
forall a. Context a -> [Port]
_nonblocking Context ann
context [Port] -> [Port] -> [Port]
forall a. Semigroup a => a -> a -> a
<> Context ann -> [Port]
forall a. Context a -> [Port]
_blocking Context ann
context) ReaderT Config (GenT (State (Context ann))) (Context ann)
forall s (m :: * -> *). MonadState s m => m s
get

shareableVariables :: StateGen ann [Port]
shareableVariables :: forall ann. StateGen ann [Port]
shareableVariables =
  (Context ann -> [Port])
-> ReaderT Config (GenT (State (Context ann))) (Context ann)
-> ReaderT Config (GenT (State (Context ann))) [Port]
forall a b.
(a -> b)
-> ReaderT Config (GenT (State (Context ann))) a
-> ReaderT Config (GenT (State (Context ann))) b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\Context ann
context -> Context ann -> [Port]
forall a. Context a -> [Port]
_wires Context ann
context [Port] -> [Port] -> [Port]
forall a. Semigroup a => a -> a -> a
<> Context ann -> [Port]
forall a. Context a -> [Port]
_nonblocking Context ann
context) ReaderT Config (GenT (State (Context ann))) (Context ann)
forall s (m :: * -> *). MonadState s m => m s
get

-- | Generates an expression from variables that are currently in scope.
scopedExpr_ :: [Port] -> StateGen ann Expr
scopedExpr_ :: forall ann. [Port] -> StateGen ann Expr
scopedExpr_ [Port]
vars = do
  Context ann
context <- ReaderT Config (GenT (State (Context ann))) (Context ann)
forall s (m :: * -> *). MonadState s m => m s
get
  Probability
prob <- StateGen ann Probability
forall ann. StateGen ann Probability
askProbability
  (Size -> StateGen ann Expr) -> StateGen ann Expr
forall (m :: * -> *) a. MonadGen m => (Size -> m a) -> m a
Hog.sized
    ((Size -> StateGen ann Expr) -> StateGen ann Expr)
-> ([Port] -> Size -> StateGen ann Expr)
-> [Port]
-> StateGen ann Expr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ProbExpr -> [Parameter] -> [Port] -> Size -> StateGen ann Expr
forall (m :: * -> *).
MonadGen m =>
ProbExpr -> [Parameter] -> [Port] -> Size -> m Expr
exprWithContext (Probability -> ProbExpr
_probExpr Probability
prob) (Context ann -> [Parameter]
forall a. Context a -> [Parameter]
_parameters Context ann
context)
    ([Port] -> StateGen ann Expr) -> [Port] -> StateGen ann Expr
forall a b. (a -> b) -> a -> b
$ [Port]
vars

scopedExprAll :: StateGen ann Expr
scopedExprAll :: forall ann. StateGen ann Expr
scopedExprAll = StateGen ann [Port]
forall ann. StateGen ann [Port]
allVariables StateGen ann [Port]
-> ([Port] -> ReaderT Config (GenT (State (Context ann))) Expr)
-> ReaderT Config (GenT (State (Context ann))) Expr
forall a b.
ReaderT Config (GenT (State (Context ann))) a
-> (a -> ReaderT Config (GenT (State (Context ann))) b)
-> ReaderT Config (GenT (State (Context ann))) b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= [Port] -> ReaderT Config (GenT (State (Context ann))) Expr
forall ann. [Port] -> StateGen ann Expr
scopedExpr_

scopedExpr :: StateGen ann Expr
scopedExpr :: forall ann. StateGen ann Expr
scopedExpr = StateGen ann [Port]
forall ann. StateGen ann [Port]
shareableVariables StateGen ann [Port]
-> ([Port] -> ReaderT Config (GenT (State (Context ann))) Expr)
-> ReaderT Config (GenT (State (Context ann))) Expr
forall a b.
ReaderT Config (GenT (State (Context ann))) a
-> (a -> ReaderT Config (GenT (State (Context ann))) b)
-> ReaderT Config (GenT (State (Context ann))) b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= [Port] -> ReaderT Config (GenT (State (Context ann))) Expr
forall ann. [Port] -> StateGen ann Expr
scopedExpr_

-- | Generates a random continuous assignment and assigns it to a random wire
-- that is created.
contAssign :: StateGen ann ContAssign
contAssign :: forall ann. StateGen ann ContAssign
contAssign = do
  Expr
expr <- StateGen ann Expr
forall ann. StateGen ann Expr
scopedExpr
  Port
p <- Maybe Text -> StateGen ann Port
forall ann. Maybe Text -> StateGen ann Port
nextWirePort Maybe Text
forall a. Maybe a
Nothing
  ContAssign -> StateGen ann ContAssign
forall a. a -> ReaderT Config (GenT (State (Context ann))) a
forall (m :: * -> *) a. Monad m => a -> m a
return (ContAssign -> StateGen ann ContAssign)
-> ContAssign -> StateGen ann ContAssign
forall a b. (a -> b) -> a -> b
$ Identifier -> Expr -> ContAssign
ContAssign (Port
p Port -> Getting Identifier Port Identifier -> Identifier
forall s a. s -> Getting a s a -> a
^. Getting Identifier Port Identifier
Lens' Port Identifier
portName) Expr
expr

-- | Generate a random assignment and assign it to a random 'Reg'.
assignment :: Bool -> StateGen ann Assign
assignment :: forall ann. Bool -> StateGen ann Assign
assignment Bool
blk = do
  Expr
expr <- StateGen ann Expr
forall ann. StateGen ann Expr
scopedExprAll
  LVal
lval <- Port -> LVal
lvalFromPort (Port -> LVal)
-> ReaderT Config (GenT (State (Context ann))) Port
-> ReaderT Config (GenT (State (Context ann))) LVal
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (if Bool
blk then Maybe Text -> ReaderT Config (GenT (State (Context ann))) Port
forall ann. Maybe Text -> StateGen ann Port
nextBPort else Maybe Text -> ReaderT Config (GenT (State (Context ann))) Port
forall ann. Maybe Text -> StateGen ann Port
nextNBPort) Maybe Text
forall a. Maybe a
Nothing
  Assign -> StateGen ann Assign
forall a. a -> ReaderT Config (GenT (State (Context ann))) a
forall (m :: * -> *) a. Monad m => a -> m a
return (Assign -> StateGen ann Assign) -> Assign -> StateGen ann Assign
forall a b. (a -> b) -> a -> b
$ LVal -> Maybe Delay -> Expr -> Assign
Assign LVal
lval Maybe Delay
forall a. Maybe a
Nothing Expr
expr

-- | Generate a random 'Statement' safely, by also increasing the depth counter.
seqBlock :: StateGen ann (Statement ann)
seqBlock :: forall ann. StateGen ann (Statement ann)
seqBlock = do
  (Int -> Identity Int) -> Context ann -> Identity (Context ann)
forall a (f :: * -> *).
Functor f =>
(Int -> f Int) -> Context a -> f (Context a)
stmntDepth ((Int -> Identity Int) -> Context ann -> Identity (Context ann))
-> Int -> ReaderT Config (GenT (State (Context ann))) ()
forall s (m :: * -> *) a.
(MonadState s m, Num a) =>
ASetter' s a -> a -> m ()
-= Int
1
  Statement ann
tstat <- [Statement ann] -> Statement ann
forall a. [Statement a] -> Statement a
SeqBlock ([Statement ann] -> Statement ann)
-> ReaderT Config (GenT (State (Context ann))) [Statement ann]
-> StateGen ann (Statement ann)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int
-> StateGen ann (Statement ann)
-> ReaderT Config (GenT (State (Context ann))) [Statement ann]
forall ann a. Int -> StateGen ann a -> StateGen ann [a]
someI Int
20 StateGen ann (Statement ann)
forall ann. StateGen ann (Statement ann)
statement
  (Int -> Identity Int) -> Context ann -> Identity (Context ann)
forall a (f :: * -> *).
Functor f =>
(Int -> f Int) -> Context a -> f (Context a)
stmntDepth ((Int -> Identity Int) -> Context ann -> Identity (Context ann))
-> Int -> ReaderT Config (GenT (State (Context ann))) ()
forall s (m :: * -> *) a.
(MonadState s m, Num a) =>
ASetter' s a -> a -> m ()
+= Int
1
  Statement ann -> StateGen ann (Statement ann)
forall a. a -> ReaderT Config (GenT (State (Context ann))) a
forall (m :: * -> *) a. Monad m => a -> m a
return Statement ann
tstat

-- | Generate a random conditional 'Statement'. The nameCounter is reset between
-- branches so that port names can be reused. This is safe because if a 'Port'
-- is not reused, it is left at 0, as all the 'Reg' are initialised to 0 at the
-- start.
conditional :: StateGen ann (Statement ann)
conditional :: forall ann. StateGen ann (Statement ann)
conditional = do
  Expr
expr <- StateGen ann Expr
forall ann. StateGen ann Expr
scopedExprAll
  Int
nc <- Context ann -> Int
forall a. Context a -> Int
_nameCounter (Context ann -> Int)
-> ReaderT Config (GenT (State (Context ann))) (Context ann)
-> ReaderT Config (GenT (State (Context ann))) Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ReaderT Config (GenT (State (Context ann))) (Context ann)
forall s (m :: * -> *). MonadState s m => m s
get
  Statement ann
tstat <- StateGen ann (Statement ann)
forall ann. StateGen ann (Statement ann)
seqBlock
  Int
nc' <- Context ann -> Int
forall a. Context a -> Int
_nameCounter (Context ann -> Int)
-> ReaderT Config (GenT (State (Context ann))) (Context ann)
-> ReaderT Config (GenT (State (Context ann))) Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ReaderT Config (GenT (State (Context ann))) (Context ann)
forall s (m :: * -> *). MonadState s m => m s
get
  (Int -> Identity Int) -> Context ann -> Identity (Context ann)
forall a (f :: * -> *).
Functor f =>
(Int -> f Int) -> Context a -> f (Context a)
nameCounter ((Int -> Identity Int) -> Context ann -> Identity (Context ann))
-> Int -> ReaderT Config (GenT (State (Context ann))) ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= Int
nc
  Statement ann
fstat <- StateGen ann (Statement ann)
forall ann. StateGen ann (Statement ann)
seqBlock
  Int
nc'' <- Context ann -> Int
forall a. Context a -> Int
_nameCounter (Context ann -> Int)
-> ReaderT Config (GenT (State (Context ann))) (Context ann)
-> ReaderT Config (GenT (State (Context ann))) Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ReaderT Config (GenT (State (Context ann))) (Context ann)
forall s (m :: * -> *). MonadState s m => m s
get
  (Int -> Identity Int) -> Context ann -> Identity (Context ann)
forall a (f :: * -> *).
Functor f =>
(Int -> f Int) -> Context a -> f (Context a)
nameCounter ((Int -> Identity Int) -> Context ann -> Identity (Context ann))
-> Int -> ReaderT Config (GenT (State (Context ann))) ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
nc' Int
nc''
  Statement ann -> StateGen ann (Statement ann)
forall a. a -> ReaderT Config (GenT (State (Context ann))) a
forall (m :: * -> *) a. Monad m => a -> m a
return (Statement ann -> StateGen ann (Statement ann))
-> Statement ann -> StateGen ann (Statement ann)
forall a b. (a -> b) -> a -> b
$ Expr
-> Maybe (Statement ann) -> Maybe (Statement ann) -> Statement ann
forall a.
Expr -> Maybe (Statement a) -> Maybe (Statement a) -> Statement a
CondStmnt Expr
expr (Statement ann -> Maybe (Statement ann)
forall a. a -> Maybe a
Just Statement ann
tstat) (Statement ann -> Maybe (Statement ann)
forall a. a -> Maybe a
Just Statement ann
fstat)

-- | Generate a random for loop by creating a new variable name for the counter
-- and then generating random statements in the body.
forLoop :: StateGen ann (Statement ann)
forLoop :: forall ann. StateGen ann (Statement ann)
forLoop = do
  Int
num <- Range Int -> ReaderT Config (GenT (State (Context ann))) Int
forall (m :: * -> *). MonadGen m => Range Int -> m Int
Hog.int (Int -> Int -> Range Int
forall a. Integral a => a -> a -> Range a
Hog.linear Int
0 Int
20)
  LVal
var <- Port -> LVal
lvalFromPort (Port -> LVal)
-> ReaderT Config (GenT (State (Context ann))) Port
-> ReaderT Config (GenT (State (Context ann))) LVal
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe Text -> ReaderT Config (GenT (State (Context ann))) Port
forall ann. Maybe Text -> StateGen ann Port
nextBPort (Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"forvar")
  Assign -> Expr -> Assign -> Statement ann -> Statement ann
forall a. Assign -> Expr -> Assign -> Statement a -> Statement a
ForLoop
    (LVal -> Maybe Delay -> Expr -> Assign
Assign LVal
var Maybe Delay
forall a. Maybe a
Nothing Expr
0)
    (Expr -> BinaryOperator -> Expr -> Expr
BinOp (LVal -> Expr
varId LVal
var) BinaryOperator
BinLT (Expr -> Expr) -> Expr -> Expr
forall a b. (a -> b) -> a -> b
$ Int -> Expr
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
num)
    (LVal -> Maybe Delay -> Expr -> Assign
Assign LVal
var Maybe Delay
forall a. Maybe a
Nothing (Expr -> Assign) -> Expr -> Assign
forall a b. (a -> b) -> a -> b
$ Expr -> BinaryOperator -> Expr -> Expr
BinOp (LVal -> Expr
varId LVal
var) BinaryOperator
BinPlus Expr
1)
    (Statement ann -> Statement ann)
-> StateGen ann (Statement ann) -> StateGen ann (Statement ann)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> StateGen ann (Statement ann)
forall ann. StateGen ann (Statement ann)
seqBlock
  where
    varId :: LVal -> Expr
varId LVal
v = Identifier -> Expr
Id (LVal
v LVal -> Getting Identifier LVal Identifier -> Identifier
forall s a. s -> Getting a s a -> a
^. Getting Identifier LVal Identifier
Traversal' LVal Identifier
regId)

-- | Choose a 'Statement' to generate.
statement :: StateGen ann (Statement ann)
statement :: forall ann. StateGen ann (Statement ann)
statement = do
  Probability
prob <- StateGen ann Probability
forall ann. StateGen ann Probability
askProbability
  Context ann
cont <- ReaderT Config (GenT (State (Context ann))) (Context ann)
forall s (m :: * -> *). MonadState s m => m s
get
  let defProb :: ((a -> Const a a) -> ProbStatement -> Const a ProbStatement) -> a
defProb (a -> Const a a) -> ProbStatement -> Const a ProbStatement
i = Probability
prob Probability -> Getting a Probability a -> a
forall s a. s -> Getting a s a -> a
^. (ProbStatement -> Const a ProbStatement)
-> Probability -> Const a Probability
Lens' Probability ProbStatement
probStmnt ((ProbStatement -> Const a ProbStatement)
 -> Probability -> Const a Probability)
-> ((a -> Const a a) -> ProbStatement -> Const a ProbStatement)
-> Getting a Probability a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> Const a a) -> ProbStatement -> Const a ProbStatement
i
  [(Int, StateGen ann (Statement ann))]
-> StateGen ann (Statement ann)
forall (m :: * -> *) a. MonadGen m => [(Int, m a)] -> m a
Hog.frequency
    [ (((Int -> Const Int Int)
 -> ProbStatement -> Const Int ProbStatement)
-> Int
forall {a}.
((a -> Const a a) -> ProbStatement -> Const a ProbStatement) -> a
defProb (Int -> Const Int Int) -> ProbStatement -> Const Int ProbStatement
Lens' ProbStatement Int
probStmntBlock, Assign -> Statement ann
forall a. Assign -> Statement a
BlockAssign (Assign -> Statement ann)
-> ReaderT Config (GenT (State (Context ann))) Assign
-> StateGen ann (Statement ann)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Bool -> ReaderT Config (GenT (State (Context ann))) Assign
forall ann. Bool -> StateGen ann Assign
assignment Bool
True),
      (((Int -> Const Int Int)
 -> ProbStatement -> Const Int ProbStatement)
-> Int
forall {a}.
((a -> Const a a) -> ProbStatement -> Const a ProbStatement) -> a
defProb (Int -> Const Int Int) -> ProbStatement -> Const Int ProbStatement
Lens' ProbStatement Int
probStmntNonBlock, Assign -> Statement ann
forall a. Assign -> Statement a
NonBlockAssign (Assign -> Statement ann)
-> ReaderT Config (GenT (State (Context ann))) Assign
-> StateGen ann (Statement ann)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Bool -> ReaderT Config (GenT (State (Context ann))) Assign
forall ann. Bool -> StateGen ann Assign
assignment Bool
False),
      (Context ann -> Int -> Int
forall {p} {a}. Num p => Context a -> p -> p
onDepth Context ann
cont (((Int -> Const Int Int)
 -> ProbStatement -> Const Int ProbStatement)
-> Int
forall {a}.
((a -> Const a a) -> ProbStatement -> Const a ProbStatement) -> a
defProb (Int -> Const Int Int) -> ProbStatement -> Const Int ProbStatement
Lens' ProbStatement Int
probStmntCond), StateGen ann (Statement ann)
forall ann. StateGen ann (Statement ann)
conditional),
      (Context ann -> Int -> Int
forall {p} {a}. Num p => Context a -> p -> p
onDepth Context ann
cont (((Int -> Const Int Int)
 -> ProbStatement -> Const Int ProbStatement)
-> Int
forall {a}.
((a -> Const a a) -> ProbStatement -> Const a ProbStatement) -> a
defProb (Int -> Const Int Int) -> ProbStatement -> Const Int ProbStatement
Lens' ProbStatement Int
probStmntFor), StateGen ann (Statement ann)
forall ann. StateGen ann (Statement ann)
forLoop)
    ]
  where
    onDepth :: Context a -> p -> p
onDepth Context a
c p
n = if Context a
c Context a -> Getting Int (Context a) Int -> Int
forall s a. s -> Getting a s a -> a
^. Getting Int (Context a) Int
forall a (f :: * -> *).
Functor f =>
(Int -> f Int) -> Context a -> f (Context a)
stmntDepth Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0 then p
n else p
0

-- | Generate a sequential always block which is dependent on the clock.
alwaysSeq :: StateGen ann (ModItem ann)
alwaysSeq :: forall ann. StateGen ann (ModItem ann)
alwaysSeq = do
  ModItem ann
always <- Statement ann -> ModItem ann
forall a. Statement a -> ModItem a
Always (Statement ann -> ModItem ann)
-> (Statement ann -> Statement ann) -> Statement ann -> ModItem ann
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Event -> Maybe (Statement ann) -> Statement ann
forall a. Event -> Maybe (Statement a) -> Statement a
EventCtrl (Identifier -> Event
EPosEdge Identifier
"clk") (Maybe (Statement ann) -> Statement ann)
-> (Statement ann -> Maybe (Statement ann))
-> Statement ann
-> Statement ann
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Statement ann -> Maybe (Statement ann)
forall a. a -> Maybe a
Just (Statement ann -> ModItem ann)
-> ReaderT Config (GenT (State (Context ann))) (Statement ann)
-> StateGen ann (ModItem ann)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ReaderT Config (GenT (State (Context ann))) (Statement ann)
forall ann. StateGen ann (Statement ann)
seqBlock
  [Port]
blk <- (Context ann -> [Port])
-> ReaderT Config (GenT (State (Context ann))) (Context ann)
-> ReaderT Config (GenT (State (Context ann))) [Port]
forall a b.
(a -> b)
-> ReaderT Config (GenT (State (Context ann))) a
-> ReaderT Config (GenT (State (Context ann))) b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Context ann -> [Port]
forall a. Context a -> [Port]
_blocking ReaderT Config (GenT (State (Context ann))) (Context ann)
forall s (m :: * -> *). MonadState s m => m s
get
  ([Port] -> Identity [Port])
-> Context ann -> Identity (Context ann)
forall a (f :: * -> *).
Functor f =>
([Port] -> f [Port]) -> Context a -> f (Context a)
outofscope (([Port] -> Identity [Port])
 -> Context ann -> Identity (Context ann))
-> ([Port] -> [Port])
-> ReaderT Config (GenT (State (Context ann))) ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> (a -> b) -> m ()
%= [Port] -> [Port] -> [Port]
forall a. Monoid a => a -> a -> a
mappend [Port]
blk
  ([Port] -> Identity [Port])
-> Context ann -> Identity (Context ann)
forall a (f :: * -> *).
Functor f =>
([Port] -> f [Port]) -> Context a -> f (Context a)
blocking (([Port] -> Identity [Port])
 -> Context ann -> Identity (Context ann))
-> [Port] -> ReaderT Config (GenT (State (Context ann))) ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= []
  ModItem ann -> StateGen ann (ModItem ann)
forall a. a -> ReaderT Config (GenT (State (Context ann))) a
forall (m :: * -> *) a. Monad m => a -> m a
return ModItem ann
always

-- | 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 :: [Parameter] -> Identifier -> Range -> [Port] -> [Port]
resizePort [Parameter]
ps Identifier
i Range
ra = ([Port] -> Port -> [Port]) -> [Port] -> [Port] -> [Port]
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' [Port] -> Port -> [Port]
func []
  where
    func :: [Port] -> Port -> [Port]
func [Port]
l p :: Port
p@(Port PortType
t Bool
_ Range
ri Identifier
i')
      | Identifier
i' Identifier -> Identifier -> Bool
forall a. Eq a => a -> a -> Bool
== Identifier
i Bool -> Bool -> Bool
&& Range -> Int
calc Range
ri Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Range -> Int
calc Range
ra = (Port
p Port -> (Port -> Port) -> Port
forall a b. a -> (a -> b) -> b
& (Range -> Identity Range) -> Port -> Identity Port
Lens' Port Range
portSize ((Range -> Identity Range) -> Port -> Identity Port)
-> Range -> Port -> Port
forall s t a b. ASetter s t a b -> b -> s -> t
.~ Range
ra) Port -> [Port] -> [Port]
forall a. a -> [a] -> [a]
: [Port]
l
      | Bool
otherwise = Port
p Port -> [Port] -> [Port]
forall a. a -> [a] -> [a]
: [Port]
l
    calc :: Range -> Int
calc = [Parameter] -> Maybe Int -> Range -> Int
calcRange [Parameter]
ps (Maybe Int -> Range -> Int) -> Maybe Int -> Range -> Int
forall a b. (a -> b) -> a -> b
$ Int -> Maybe Int
forall a. a -> Maybe a
Just Int
64

-- | Instantiate a module, where the outputs are new nets that are created, and
-- the inputs are taken from existing ports in the context.
--
-- 1 is subtracted from the inputs for the length because the clock is not
-- counted and is assumed to be there, this should be made nicer by filtering
-- out the clock instead. I think that in general there should be a special
-- representation for the clock.
instantiate :: (ModDecl ann) -> StateGen ann (ModItem ann)
instantiate :: forall ann. ModDecl ann -> StateGen ann (ModItem ann)
instantiate (ModDecl Identifier
i [Port]
outP [Port]
inP [ModItem ann]
_ [Parameter]
_) = do
  [Port]
vars <- StateGen ann [Port]
forall ann. StateGen ann [Port]
shareableVariables
  [Port]
outs <- Int
-> ReaderT Config (GenT (State (Context ann))) Port
-> StateGen ann [Port]
forall (m :: * -> *) a. Applicative m => Int -> m a -> m [a]
replicateM ([Port] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Port]
outP) (ReaderT Config (GenT (State (Context ann))) Port
 -> StateGen ann [Port])
-> ReaderT Config (GenT (State (Context ann))) Port
-> StateGen ann [Port]
forall a b. (a -> b) -> a -> b
$ Maybe Text -> ReaderT Config (GenT (State (Context ann))) Port
forall ann. Maybe Text -> StateGen ann Port
nextWirePort Maybe Text
forall a. Maybe a
Nothing
  [Port]
ins <- Int -> [Port] -> [Port]
forall a. Int -> [a] -> [a]
take ([Port] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Port]
inpFixed) ([Port] -> [Port]) -> StateGen ann [Port] -> StateGen ann [Port]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Port] -> StateGen ann [Port]
forall (m :: * -> *) a. MonadGen m => [a] -> m [a]
Hog.shuffle [Port]
vars
  [Expr]
insLit <- Int
-> ReaderT Config (GenT (State (Context ann))) Expr
-> ReaderT Config (GenT (State (Context ann))) [Expr]
forall (m :: * -> *) a. Applicative m => Int -> m a -> m [a]
replicateM ([Port] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Port]
inpFixed Int -> Int -> Int
forall a. Num a => a -> a -> a
- [Port] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Port]
ins) (BitVec -> Expr
Number (BitVec -> Expr)
-> ReaderT Config (GenT (State (Context ann))) BitVec
-> ReaderT Config (GenT (State (Context ann))) Expr
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ReaderT Config (GenT (State (Context ann))) BitVec
forall (m :: * -> *). MonadGen m => m BitVec
genBitVec)
  (((Identifier, PortType), Range)
 -> ReaderT Config (GenT (State (Context ann))) ())
-> [((Identifier, PortType), Range)]
-> ReaderT Config (GenT (State (Context ann))) ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (((Identifier, PortType)
 -> Range -> ReaderT Config (GenT (State (Context ann))) ())
-> ((Identifier, PortType), Range)
-> ReaderT Config (GenT (State (Context ann))) ()
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry (Identifier, PortType)
-> Range -> ReaderT Config (GenT (State (Context ann))) ()
forall {m :: * -> *} {a}.
MonadState (Context a) m =>
(Identifier, PortType) -> Range -> m ()
process)
    ([((Identifier, PortType), Range)]
 -> ReaderT Config (GenT (State (Context ann))) ())
-> ([Range] -> [((Identifier, PortType), Range)])
-> [Range]
-> ReaderT Config (GenT (State (Context ann))) ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [(Identifier, PortType)]
-> [Range] -> [((Identifier, PortType), Range)]
forall a b. [a] -> [b] -> [(a, b)]
zip
      ( [Identifier] -> [PortType] -> [(Identifier, PortType)]
forall a b. [a] -> [b] -> [(a, b)]
zip
          ([Port]
ins [Port]
-> Getting (Endo [Identifier]) [Port] Identifier -> [Identifier]
forall s a. s -> Getting (Endo [a]) s a -> [a]
^.. (Port -> Const (Endo [Identifier]) Port)
-> [Port] -> Const (Endo [Identifier]) [Port]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> [a] -> f [b]
traverse ((Port -> Const (Endo [Identifier]) Port)
 -> [Port] -> Const (Endo [Identifier]) [Port])
-> ((Identifier -> Const (Endo [Identifier]) Identifier)
    -> Port -> Const (Endo [Identifier]) Port)
-> Getting (Endo [Identifier]) [Port] Identifier
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Identifier -> Const (Endo [Identifier]) Identifier)
-> Port -> Const (Endo [Identifier]) Port
Lens' Port Identifier
portName)
          ([Port]
ins [Port] -> Getting (Endo [PortType]) [Port] PortType -> [PortType]
forall s a. s -> Getting (Endo [a]) s a -> [a]
^.. (Port -> Const (Endo [PortType]) Port)
-> [Port] -> Const (Endo [PortType]) [Port]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> [a] -> f [b]
traverse ((Port -> Const (Endo [PortType]) Port)
 -> [Port] -> Const (Endo [PortType]) [Port])
-> ((PortType -> Const (Endo [PortType]) PortType)
    -> Port -> Const (Endo [PortType]) Port)
-> Getting (Endo [PortType]) [Port] PortType
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (PortType -> Const (Endo [PortType]) PortType)
-> Port -> Const (Endo [PortType]) Port
Lens' Port PortType
portType)
      )
    ([Range] -> ReaderT Config (GenT (State (Context ann))) ())
-> [Range] -> ReaderT Config (GenT (State (Context ann))) ()
forall a b. (a -> b) -> a -> b
$ [Port]
inpFixed [Port] -> Getting (Endo [Range]) [Port] Range -> [Range]
forall s a. s -> Getting (Endo [a]) s a -> [a]
^.. (Port -> Const (Endo [Range]) Port)
-> [Port] -> Const (Endo [Range]) [Port]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> [a] -> f [b]
traverse ((Port -> Const (Endo [Range]) Port)
 -> [Port] -> Const (Endo [Range]) [Port])
-> ((Range -> Const (Endo [Range]) Range)
    -> Port -> Const (Endo [Range]) Port)
-> Getting (Endo [Range]) [Port] Range
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Range -> Const (Endo [Range]) Range)
-> Port -> Const (Endo [Range]) Port
Lens' Port Range
portSize
  Identifier
ident <- Text -> StateGen ann Identifier
forall ann. Text -> StateGen ann Identifier
makeIdentifier Text
"modinst"
  [StateGen ann (ModItem ann)] -> StateGen ann (ModItem ann)
forall (m :: * -> *) a. MonadGen m => [m a] -> m a
Hog.choice
    [ ModItem ann -> StateGen ann (ModItem ann)
forall a. a -> ReaderT Config (GenT (State (Context ann))) a
forall (m :: * -> *) a. Monad m => a -> m a
return (ModItem ann -> StateGen ann (ModItem ann))
-> ([ModConn] -> ModItem ann)
-> [ModConn]
-> StateGen ann (ModItem ann)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Identifier -> [ModConn] -> Identifier -> [ModConn] -> ModItem ann
forall a.
Identifier -> [ModConn] -> Identifier -> [ModConn] -> ModItem a
ModInst Identifier
i [] Identifier
ident ([ModConn] -> StateGen ann (ModItem ann))
-> [ModConn] -> StateGen ann (ModItem ann)
forall a b. (a -> b) -> a -> b
$ Expr -> ModConn
ModConn (Expr -> ModConn) -> [Expr] -> [ModConn]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ([Port] -> [Expr]
forall {f :: * -> *}. Functor f => f Port -> f Expr
toE ([Port]
outs [Port] -> [Port] -> [Port]
forall a. Semigroup a => a -> a -> a
<> [Port]
clkPort [Port] -> [Port] -> [Port]
forall a. Semigroup a => a -> a -> a
<> [Port]
ins) [Expr] -> [Expr] -> [Expr]
forall a. Semigroup a => a -> a -> a
<> [Expr]
insLit),
      Identifier -> [ModConn] -> Identifier -> [ModConn] -> ModItem ann
forall a.
Identifier -> [ModConn] -> Identifier -> [ModConn] -> ModItem a
ModInst Identifier
i [] Identifier
ident
        ([ModConn] -> ModItem ann)
-> ReaderT Config (GenT (State (Context ann))) [ModConn]
-> StateGen ann (ModItem ann)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [ModConn] -> ReaderT Config (GenT (State (Context ann))) [ModConn]
forall (m :: * -> *) a. MonadGen m => [a] -> m [a]
Hog.shuffle
          ( (Identifier -> Expr -> ModConn)
-> [Identifier] -> [Expr] -> [ModConn]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith
              Identifier -> Expr -> ModConn
ModConnNamed
              (Getting Identifier Port Identifier -> Port -> Identifier
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting Identifier Port Identifier
Lens' Port Identifier
portName (Port -> Identifier) -> [Port] -> [Identifier]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Port]
outP [Port] -> [Port] -> [Port]
forall a. Semigroup a => a -> a -> a
<> [Port]
clkPort [Port] -> [Port] -> [Port]
forall a. Semigroup a => a -> a -> a
<> [Port]
inpFixed)
              ([Port] -> [Expr]
forall {f :: * -> *}. Functor f => f Port -> f Expr
toE ([Port]
outs [Port] -> [Port] -> [Port]
forall a. Semigroup a => a -> a -> a
<> [Port]
clkPort [Port] -> [Port] -> [Port]
forall a. Semigroup a => a -> a -> a
<> [Port]
ins) [Expr] -> [Expr] -> [Expr]
forall a. Semigroup a => a -> a -> a
<> [Expr]
insLit)
          )
    ]
  where
    toE :: f Port -> f Expr
toE f Port
ins = Identifier -> Expr
Id (Identifier -> Expr) -> (Port -> Identifier) -> Port -> Expr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Getting Identifier Port Identifier -> Port -> Identifier
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting Identifier Port Identifier
Lens' Port Identifier
portName (Port -> Expr) -> f Port -> f Expr
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> f Port
ins
    ([Port]
inpFixed, [Port]
clkPort) = (Port -> Bool) -> [Port] -> ([Port], [Port])
forall a. (a -> Bool) -> [a] -> ([a], [a])
partition Port -> Bool
filterFunc [Port]
inP
    filterFunc :: Port -> Bool
filterFunc (Port PortType
_ Bool
_ Range
_ Identifier
n)
      | Identifier
n Identifier -> Identifier -> Bool
forall a. Eq a => a -> a -> Bool
== Identifier
"clk" = Bool
False
      | Bool
otherwise = Bool
True
    process :: (Identifier, PortType) -> Range -> m ()
process (Identifier
p, PortType
t) Range
r = do
      [Parameter]
params <- Getting [Parameter] (Context a) [Parameter]
-> Context a -> [Parameter]
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting [Parameter] (Context a) [Parameter]
forall a (f :: * -> *).
Functor f =>
([Parameter] -> f [Parameter]) -> Context a -> f (Context a)
parameters (Context a -> [Parameter]) -> m (Context a) -> m [Parameter]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m (Context a)
forall s (m :: * -> *). MonadState s m => m s
get
      case PortType
t of
        PortType
Reg -> ([Port] -> Identity [Port]) -> Context a -> Identity (Context a)
forall a (f :: * -> *).
Functor f =>
([Port] -> f [Port]) -> Context a -> f (Context a)
nonblocking (([Port] -> Identity [Port]) -> Context a -> Identity (Context a))
-> ([Port] -> [Port]) -> m ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> (a -> b) -> m ()
%= [Parameter] -> Identifier -> Range -> [Port] -> [Port]
resizePort [Parameter]
params Identifier
p Range
r
        PortType
Wire -> ([Port] -> Identity [Port]) -> Context a -> Identity (Context a)
forall a (f :: * -> *).
Functor f =>
([Port] -> f [Port]) -> Context a -> f (Context a)
wires (([Port] -> Identity [Port]) -> Context a -> Identity (Context a))
-> ([Port] -> [Port]) -> m ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> (a -> b) -> m ()
%= [Parameter] -> Identifier -> Range -> [Port] -> [Port]
resizePort [Parameter]
params Identifier
p Range
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
-- for every instance and for every level until either the deepest level is
-- achieved, or the maximum number of modules are reached.
--
-- If the maximum number of levels are reached, it will always pick an instance
-- from the current context. The problem with this approach is that at the end
-- there may be many more than the max amount of modules, as the modules are
-- always set to empty when entering a new level. This is to fix recursive
-- definitions of modules, which are not defined.
--
-- One way to fix that is to also decrement the max modules for every level,
-- depending on how many modules have already been generated. This would mean
-- there would be moments when the module cannot generate a new instance but
-- also not take a module from the current context. A fix for that may be to
-- have a default definition of a simple module that is used instead.
--
-- Another different way to handle this would be to have a probability of taking
-- a module from a context or generating a new one.
modInst :: StateGen ann (ModItem ann)
modInst :: forall ann. StateGen ann (ModItem ann)
modInst = do
  Config
prob <- ReaderT Config (GenT (State (Context ann))) Config
forall r (m :: * -> *). MonadReader r m => m r
ask
  Context ann
context <- ReaderT Config (GenT (State (Context ann))) (Context ann)
forall s (m :: * -> *). MonadState s m => m s
get
  let maxMods :: Int
maxMods = Config
prob Config -> Getting Int Config Int -> Int
forall s a. s -> Getting a s a -> a
^. (ConfProperty -> Const Int ConfProperty)
-> Config -> Const Int Config
Lens' Config ConfProperty
configProperty ((ConfProperty -> Const Int ConfProperty)
 -> Config -> Const Int Config)
-> ((Int -> Const Int Int)
    -> ConfProperty -> Const Int ConfProperty)
-> Getting Int Config Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> Const Int Int) -> ConfProperty -> Const Int ConfProperty
Lens' ConfProperty Int
propMaxModules
  if [ModDecl ann] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length (Context ann
context Context ann
-> Getting [ModDecl ann] (Context ann) [ModDecl ann]
-> [ModDecl ann]
forall s a. s -> Getting a s a -> a
^. Getting [ModDecl ann] (Context ann) [ModDecl ann]
forall a a (f :: * -> *).
Functor f =>
([ModDecl a] -> f [ModDecl a]) -> Context a -> f (Context a)
modules) Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
maxMods
    then do
      let currMods :: [ModDecl ann]
currMods = Context ann
context Context ann
-> Getting [ModDecl ann] (Context ann) [ModDecl ann]
-> [ModDecl ann]
forall s a. s -> Getting a s a -> a
^. Getting [ModDecl ann] (Context ann) [ModDecl ann]
forall a a (f :: * -> *).
Functor f =>
([ModDecl a] -> f [ModDecl a]) -> Context a -> f (Context a)
modules
      let params :: [Parameter]
params = Context ann
context Context ann
-> Getting [Parameter] (Context ann) [Parameter] -> [Parameter]
forall s a. s -> Getting a s a -> a
^. Getting [Parameter] (Context ann) [Parameter]
forall a (f :: * -> *).
Functor f =>
([Parameter] -> f [Parameter]) -> Context a -> f (Context a)
parameters
      let w :: [Port]
w = Context ann -> [Port]
forall a. Context a -> [Port]
_wires Context ann
context
      let nb :: [Port]
nb = Context ann -> [Port]
forall a. Context a -> [Port]
_nonblocking Context ann
context
      let b :: [Port]
b = Context ann -> [Port]
forall a. Context a -> [Port]
_blocking Context ann
context
      let oos :: [Port]
oos = Context ann -> [Port]
forall a. Context a -> [Port]
_outofscope Context ann
context
      ([ModDecl ann] -> Identity [ModDecl ann])
-> Context ann -> Identity (Context ann)
forall a a (f :: * -> *).
Functor f =>
([ModDecl a] -> f [ModDecl a]) -> Context a -> f (Context a)
modules (([ModDecl ann] -> Identity [ModDecl ann])
 -> Context ann -> Identity (Context ann))
-> [ModDecl ann] -> ReaderT Config (GenT (State (Context ann))) ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= []
      ([Port] -> Identity [Port])
-> Context ann -> Identity (Context ann)
forall a (f :: * -> *).
Functor f =>
([Port] -> f [Port]) -> Context a -> f (Context a)
wires (([Port] -> Identity [Port])
 -> Context ann -> Identity (Context ann))
-> [Port] -> ReaderT Config (GenT (State (Context ann))) ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= []
      ([Port] -> Identity [Port])
-> Context ann -> Identity (Context ann)
forall a (f :: * -> *).
Functor f =>
([Port] -> f [Port]) -> Context a -> f (Context a)
nonblocking (([Port] -> Identity [Port])
 -> Context ann -> Identity (Context ann))
-> [Port] -> ReaderT Config (GenT (State (Context ann))) ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= []
      ([Port] -> Identity [Port])
-> Context ann -> Identity (Context ann)
forall a (f :: * -> *).
Functor f =>
([Port] -> f [Port]) -> Context a -> f (Context a)
blocking (([Port] -> Identity [Port])
 -> Context ann -> Identity (Context ann))
-> [Port] -> ReaderT Config (GenT (State (Context ann))) ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= []
      ([Port] -> Identity [Port])
-> Context ann -> Identity (Context ann)
forall a (f :: * -> *).
Functor f =>
([Port] -> f [Port]) -> Context a -> f (Context a)
outofscope (([Port] -> Identity [Port])
 -> Context ann -> Identity (Context ann))
-> [Port] -> ReaderT Config (GenT (State (Context ann))) ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= []
      ([Parameter] -> Identity [Parameter])
-> Context ann -> Identity (Context ann)
forall a (f :: * -> *).
Functor f =>
([Parameter] -> f [Parameter]) -> Context a -> f (Context a)
parameters (([Parameter] -> Identity [Parameter])
 -> Context ann -> Identity (Context ann))
-> [Parameter] -> ReaderT Config (GenT (State (Context ann))) ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= []
      (Int -> Identity Int) -> Context ann -> Identity (Context ann)
forall a (f :: * -> *).
Functor f =>
(Int -> f Int) -> Context a -> f (Context a)
modDepth ((Int -> Identity Int) -> Context ann -> Identity (Context ann))
-> Int -> ReaderT Config (GenT (State (Context ann))) ()
forall s (m :: * -> *) a.
(MonadState s m, Num a) =>
ASetter' s a -> a -> m ()
-= Int
1
      ModDecl ann
chosenMod <- Maybe Identifier -> StateGen ann (ModDecl ann)
forall ann. Maybe Identifier -> StateGen ann (ModDecl ann)
moduleDef Maybe Identifier
forall a. Maybe a
Nothing
      Context ann
ncont <- ReaderT Config (GenT (State (Context ann))) (Context ann)
forall s (m :: * -> *). MonadState s m => m s
get
      let genMods :: [ModDecl ann]
genMods = Context ann
ncont Context ann
-> Getting [ModDecl ann] (Context ann) [ModDecl ann]
-> [ModDecl ann]
forall s a. s -> Getting a s a -> a
^. Getting [ModDecl ann] (Context ann) [ModDecl ann]
forall a a (f :: * -> *).
Functor f =>
([ModDecl a] -> f [ModDecl a]) -> Context a -> f (Context a)
modules
      (Int -> Identity Int) -> Context ann -> Identity (Context ann)
forall a (f :: * -> *).
Functor f =>
(Int -> f Int) -> Context a -> f (Context a)
modDepth ((Int -> Identity Int) -> Context ann -> Identity (Context ann))
-> Int -> ReaderT Config (GenT (State (Context ann))) ()
forall s (m :: * -> *) a.
(MonadState s m, Num a) =>
ASetter' s a -> a -> m ()
+= Int
1
      ([Parameter] -> Identity [Parameter])
-> Context ann -> Identity (Context ann)
forall a (f :: * -> *).
Functor f =>
([Parameter] -> f [Parameter]) -> Context a -> f (Context a)
parameters (([Parameter] -> Identity [Parameter])
 -> Context ann -> Identity (Context ann))
-> [Parameter] -> ReaderT Config (GenT (State (Context ann))) ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= [Parameter]
params
      ([Port] -> Identity [Port])
-> Context ann -> Identity (Context ann)
forall a (f :: * -> *).
Functor f =>
([Port] -> f [Port]) -> Context a -> f (Context a)
wires (([Port] -> Identity [Port])
 -> Context ann -> Identity (Context ann))
-> [Port] -> ReaderT Config (GenT (State (Context ann))) ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= [Port]
w
      ([Port] -> Identity [Port])
-> Context ann -> Identity (Context ann)
forall a (f :: * -> *).
Functor f =>
([Port] -> f [Port]) -> Context a -> f (Context a)
nonblocking (([Port] -> Identity [Port])
 -> Context ann -> Identity (Context ann))
-> [Port] -> ReaderT Config (GenT (State (Context ann))) ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= [Port]
nb
      ([Port] -> Identity [Port])
-> Context ann -> Identity (Context ann)
forall a (f :: * -> *).
Functor f =>
([Port] -> f [Port]) -> Context a -> f (Context a)
blocking (([Port] -> Identity [Port])
 -> Context ann -> Identity (Context ann))
-> [Port] -> ReaderT Config (GenT (State (Context ann))) ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= [Port]
b
      ([Port] -> Identity [Port])
-> Context ann -> Identity (Context ann)
forall a (f :: * -> *).
Functor f =>
([Port] -> f [Port]) -> Context a -> f (Context a)
outofscope (([Port] -> Identity [Port])
 -> Context ann -> Identity (Context ann))
-> [Port] -> ReaderT Config (GenT (State (Context ann))) ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= [Port]
oos
      ([ModDecl ann] -> Identity [ModDecl ann])
-> Context ann -> Identity (Context ann)
forall a a (f :: * -> *).
Functor f =>
([ModDecl a] -> f [ModDecl a]) -> Context a -> f (Context a)
modules (([ModDecl ann] -> Identity [ModDecl ann])
 -> Context ann -> Identity (Context ann))
-> [ModDecl ann] -> ReaderT Config (GenT (State (Context ann))) ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= ModDecl ann
chosenMod ModDecl ann -> [ModDecl ann] -> [ModDecl ann]
forall a. a -> [a] -> [a]
: [ModDecl ann]
currMods [ModDecl ann] -> [ModDecl ann] -> [ModDecl ann]
forall a. Semigroup a => a -> a -> a
<> [ModDecl ann]
genMods
      ModDecl ann -> StateGen ann (ModItem ann)
forall ann. ModDecl ann -> StateGen ann (ModItem ann)
instantiate ModDecl ann
chosenMod
    else [ModDecl ann] -> StateGen ann (ModDecl ann)
forall (f :: * -> *) (m :: * -> *) a.
(Foldable f, MonadGen m) =>
f a -> m a
Hog.element (Context ann
context Context ann
-> Getting [ModDecl ann] (Context ann) [ModDecl ann]
-> [ModDecl ann]
forall s a. s -> Getting a s a -> a
^. Getting [ModDecl ann] (Context ann) [ModDecl ann]
forall a a (f :: * -> *).
Functor f =>
([ModDecl a] -> f [ModDecl a]) -> Context a -> f (Context a)
modules) StateGen ann (ModDecl ann)
-> (ModDecl ann -> StateGen ann (ModItem ann))
-> StateGen ann (ModItem ann)
forall a b.
ReaderT Config (GenT (State (Context ann))) a
-> (a -> ReaderT Config (GenT (State (Context ann))) b)
-> ReaderT Config (GenT (State (Context ann))) b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= ModDecl ann -> StateGen ann (ModItem ann)
forall ann. ModDecl ann -> StateGen ann (ModItem ann)
instantiate

-- | Generate a random module item.
modItem :: StateGen ann (ModItem ann)
modItem :: forall ann. StateGen ann (ModItem ann)
modItem = do
  Config
conf <- ReaderT Config (GenT (State (Context ann))) Config
forall r (m :: * -> *). MonadReader r m => m r
ask
  let prob :: Probability
prob = Config
conf Config -> Getting Probability Config Probability -> Probability
forall s a. s -> Getting a s a -> a
^. Getting Probability Config Probability
Lens' Config Probability
configProbability
  Context ann
context <- ReaderT Config (GenT (State (Context ann))) (Context ann)
forall s (m :: * -> *). MonadState s m => m s
get
  let defProb :: ((a -> Const a a) -> ProbModItem -> Const a ProbModItem) -> a
defProb (a -> Const a a) -> ProbModItem -> Const a ProbModItem
i = Probability
prob Probability -> Getting a Probability a -> a
forall s a. s -> Getting a s a -> a
^. (ProbModItem -> Const a ProbModItem)
-> Probability -> Const a Probability
Lens' Probability ProbModItem
probModItem ((ProbModItem -> Const a ProbModItem)
 -> Probability -> Const a Probability)
-> ((a -> Const a a) -> ProbModItem -> Const a ProbModItem)
-> Getting a Probability a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> Const a a) -> ProbModItem -> Const a ProbModItem
i
  Bool
det <-
    [(Int, ReaderT Config (GenT (State (Context ann))) Bool)]
-> ReaderT Config (GenT (State (Context ann))) Bool
forall (m :: * -> *) a. MonadGen m => [(Int, m a)] -> m a
Hog.frequency
      [ (Config
conf Config -> Getting Int Config Int -> Int
forall s a. s -> Getting a s a -> a
^. (ConfProperty -> Const Int ConfProperty)
-> Config -> Const Int Config
Lens' Config ConfProperty
configProperty ((ConfProperty -> Const Int ConfProperty)
 -> Config -> Const Int Config)
-> ((Int -> Const Int Int)
    -> ConfProperty -> Const Int ConfProperty)
-> Getting Int Config Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> Const Int Int) -> ConfProperty -> Const Int ConfProperty
Lens' ConfProperty Int
propDeterminism, Bool -> ReaderT Config (GenT (State (Context ann))) Bool
forall a. a -> ReaderT Config (GenT (State (Context ann))) a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True),
        (Config
conf Config -> Getting Int Config Int -> Int
forall s a. s -> Getting a s a -> a
^. (ConfProperty -> Const Int ConfProperty)
-> Config -> Const Int Config
Lens' Config ConfProperty
configProperty ((ConfProperty -> Const Int ConfProperty)
 -> Config -> Const Int Config)
-> ((Int -> Const Int Int)
    -> ConfProperty -> Const Int ConfProperty)
-> Getting Int Config Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> Const Int Int) -> ConfProperty -> Const Int ConfProperty
Lens' ConfProperty Int
propNonDeterminism, Bool -> ReaderT Config (GenT (State (Context ann))) Bool
forall a. a -> ReaderT Config (GenT (State (Context ann))) a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False)
      ]
  (Bool -> Identity Bool) -> Context ann -> Identity (Context ann)
forall a (f :: * -> *).
Functor f =>
(Bool -> f Bool) -> Context a -> f (Context a)
determinism ((Bool -> Identity Bool) -> Context ann -> Identity (Context ann))
-> Bool -> ReaderT Config (GenT (State (Context ann))) ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= Bool
det
  [(Int, StateGen ann (ModItem ann))] -> StateGen ann (ModItem ann)
forall (m :: * -> *) a. MonadGen m => [(Int, m a)] -> m a
Hog.frequency
    [ (((Int -> Const Int Int) -> ProbModItem -> Const Int ProbModItem)
-> Int
forall {a}.
((a -> Const a a) -> ProbModItem -> Const a ProbModItem) -> a
defProb (Int -> Const Int Int) -> ProbModItem -> Const Int ProbModItem
Lens' ProbModItem Int
probModItemAssign, ContAssign -> ModItem ann
forall a. ContAssign -> ModItem a
ModCA (ContAssign -> ModItem ann)
-> ReaderT Config (GenT (State (Context ann))) ContAssign
-> StateGen ann (ModItem ann)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ReaderT Config (GenT (State (Context ann))) ContAssign
forall ann. StateGen ann ContAssign
contAssign),
      (((Int -> Const Int Int) -> ProbModItem -> Const Int ProbModItem)
-> Int
forall {a}.
((a -> Const a a) -> ProbModItem -> Const a ProbModItem) -> a
defProb (Int -> Const Int Int) -> ProbModItem -> Const Int ProbModItem
Lens' ProbModItem Int
probModItemSeqAlways, StateGen ann (ModItem ann)
forall ann. StateGen ann (ModItem ann)
alwaysSeq),
      ( if Context ann
context Context ann -> Getting Int (Context ann) Int -> Int
forall s a. s -> Getting a s a -> a
^. Getting Int (Context ann) Int
forall a (f :: * -> *).
Functor f =>
(Int -> f Int) -> Context a -> f (Context a)
modDepth Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0 then ((Int -> Const Int Int) -> ProbModItem -> Const Int ProbModItem)
-> Int
forall {a}.
((a -> Const a a) -> ProbModItem -> Const a ProbModItem) -> a
defProb (Int -> Const Int Int) -> ProbModItem -> Const Int ProbModItem
Lens' ProbModItem Int
probModItemInst else Int
0,
        StateGen ann (ModItem ann)
forall ann. StateGen ann (ModItem ann)
modInst
      )
    ]

-- | Either return the 'Identifier' that was passed to it, or generate a new
-- 'Identifier' based on the current 'nameCounter'.
moduleName :: Maybe Identifier -> StateGen ann Identifier
moduleName :: forall ann. Maybe Identifier -> StateGen ann Identifier
moduleName (Just Identifier
t) = Identifier
-> ReaderT Config (GenT (State (Context ann))) Identifier
forall a. a -> ReaderT Config (GenT (State (Context ann))) a
forall (m :: * -> *) a. Monad m => a -> m a
return Identifier
t
moduleName Maybe Identifier
Nothing = Text -> ReaderT Config (GenT (State (Context ann))) Identifier
forall ann. Text -> StateGen ann Identifier
makeIdentifier Text
"module"

-- | Generate a random 'ConstExpr' by using the current context of 'Parameters'.
constExpr :: StateGen ann ConstExpr
constExpr :: forall ann. StateGen ann ConstExpr
constExpr = do
  Probability
prob <- StateGen ann Probability
forall ann. StateGen ann Probability
askProbability
  Context ann
context <- ReaderT Config (GenT (State (Context ann))) (Context ann)
forall s (m :: * -> *). MonadState s m => m s
get
  (Size -> StateGen ann ConstExpr) -> StateGen ann ConstExpr
forall (m :: * -> *) a. MonadGen m => (Size -> m a) -> m a
Hog.sized ((Size -> StateGen ann ConstExpr) -> StateGen ann ConstExpr)
-> (Size -> StateGen ann ConstExpr) -> StateGen ann ConstExpr
forall a b. (a -> b) -> a -> b
$
    [Parameter] -> ProbExpr -> Size -> StateGen ann ConstExpr
forall (m :: * -> *).
MonadGen m =>
[Parameter] -> ProbExpr -> Size -> m ConstExpr
constExprWithContext
      (Context ann
context Context ann
-> Getting [Parameter] (Context ann) [Parameter] -> [Parameter]
forall s a. s -> Getting a s a -> a
^. Getting [Parameter] (Context ann) [Parameter]
forall a (f :: * -> *).
Functor f =>
([Parameter] -> f [Parameter]) -> Context a -> f (Context a)
parameters)
      (Probability
prob Probability -> Getting ProbExpr Probability ProbExpr -> ProbExpr
forall s a. s -> Getting a s a -> a
^. Getting ProbExpr Probability ProbExpr
Lens' Probability ProbExpr
probExpr)

-- | Generate a random 'Parameter' and assign it to a constant expression which
-- it will be initialised to. The assumption is that this constant expression
-- should always be able to be evaluated with the current context of parameters.
parameter :: StateGen ann Parameter
parameter :: forall ann. StateGen ann Parameter
parameter = do
  Identifier
ident <- Text -> StateGen ann Identifier
forall ann. Text -> StateGen ann Identifier
makeIdentifier Text
"param"
  ConstExpr
cexpr <- StateGen ann ConstExpr
forall ann. StateGen ann ConstExpr
constExpr
  let param :: Parameter
param = Identifier -> ConstExpr -> Parameter
Parameter Identifier
ident ConstExpr
cexpr
  ([Parameter] -> Identity [Parameter])
-> Context ann -> Identity (Context ann)
forall a (f :: * -> *).
Functor f =>
([Parameter] -> f [Parameter]) -> Context a -> f (Context a)
parameters (([Parameter] -> Identity [Parameter])
 -> Context ann -> Identity (Context ann))
-> ([Parameter] -> [Parameter])
-> ReaderT Config (GenT (State (Context ann))) ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> (a -> b) -> m ()
%= (Parameter
param Parameter -> [Parameter] -> [Parameter]
forall a. a -> [a] -> [a]
:)
  Parameter -> StateGen ann Parameter
forall a. a -> ReaderT Config (GenT (State (Context ann))) a
forall (m :: * -> *) a. Monad m => a -> m a
return Parameter
param

-- | Evaluate a range to an integer, and cast it back to a range.
evalRange :: [Parameter] -> Int -> Range -> Range
evalRange :: [Parameter] -> Int -> Range -> Range
evalRange [Parameter]
ps Int
n (Range ConstExpr
l ConstExpr
r) = ConstExpr -> ConstExpr -> Range
Range (ConstExpr -> ConstExpr
eval ConstExpr
l) (ConstExpr -> ConstExpr
eval ConstExpr
r)
  where
    eval :: ConstExpr -> ConstExpr
eval = BitVec -> ConstExpr
ConstNum (BitVec -> ConstExpr)
-> (ConstExpr -> BitVec) -> ConstExpr -> ConstExpr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Base ConstExpr BitVec -> BitVec) -> ConstExpr -> BitVec
forall t a. Recursive t => (Base t a -> a) -> t -> a
forall a. (Base ConstExpr a -> a) -> ConstExpr -> a
cata ([Parameter] -> ConstExprF BitVec -> BitVec
evaluateConst [Parameter]
ps) (ConstExpr -> BitVec)
-> (ConstExpr -> ConstExpr) -> ConstExpr -> BitVec
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> ConstExpr -> ConstExpr
resize Int
n

-- | Calculate a range to an int by maybe resizing the ranges to a value.
calcRange :: [Parameter] -> Maybe Int -> Range -> Int
calcRange :: [Parameter] -> Maybe Int -> Range -> Int
calcRange [Parameter]
ps Maybe Int
i (Range ConstExpr
l ConstExpr
r) = ConstExpr -> Int
forall {c}. Num c => ConstExpr -> c
eval ConstExpr
l Int -> Int -> Int
forall a. Num a => a -> a -> a
- ConstExpr -> Int
forall {c}. Num c => ConstExpr -> c
eval ConstExpr
r Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1
  where
    eval :: ConstExpr -> c
eval ConstExpr
a = BitVec -> c
forall a b. (Integral a, Num b) => a -> b
fromIntegral (BitVec -> c) -> (ConstExpr -> BitVec) -> ConstExpr -> c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Base ConstExpr BitVec -> BitVec) -> ConstExpr -> BitVec
forall t a. Recursive t => (Base t a -> a) -> t -> a
forall a. (Base ConstExpr a -> a) -> ConstExpr -> a
cata ([Parameter] -> ConstExprF BitVec -> BitVec
evaluateConst [Parameter]
ps) (ConstExpr -> c) -> ConstExpr -> c
forall a b. (a -> b) -> a -> b
$ ConstExpr -> (Int -> ConstExpr) -> Maybe Int -> ConstExpr
forall b a. b -> (a -> b) -> Maybe a -> b
maybe ConstExpr
a (Int -> ConstExpr -> ConstExpr
`resize` ConstExpr
a) Maybe Int
i

-- | Filter out a port based on it's name instead of equality of the ports. This
-- is because the ports might not be equal if the sizes are being updated.
identElem :: Port -> [Port] -> Bool
identElem :: Port -> [Port] -> Bool
identElem Port
p = Identifier -> [Identifier] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
elem (Port
p Port -> Getting Identifier Port Identifier -> Identifier
forall s a. s -> Getting a s a -> a
^. Getting Identifier Port Identifier
Lens' Port Identifier
portName) ([Identifier] -> Bool)
-> ([Port] -> [Identifier]) -> [Port] -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Getting (Endo [Identifier]) [Port] Identifier
-> [Port] -> [Identifier]
forall a s. Getting (Endo [a]) s a -> s -> [a]
toListOf ((Port -> Const (Endo [Identifier]) Port)
-> [Port] -> Const (Endo [Identifier]) [Port]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> [a] -> f [b]
traverse ((Port -> Const (Endo [Identifier]) Port)
 -> [Port] -> Const (Endo [Identifier]) [Port])
-> ((Identifier -> Const (Endo [Identifier]) Identifier)
    -> Port -> Const (Endo [Identifier]) Port)
-> Getting (Endo [Identifier]) [Port] Identifier
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Identifier -> Const (Endo [Identifier]) Identifier)
-> Port -> Const (Endo [Identifier]) Port
Lens' Port Identifier
portName)

-- | Select items from a list with a specific frequency, returning the new list
-- that contains the selected items. If 0 is passed to both the select and
-- not-select parameter, the function will act like the idententy, returning the
-- original list inside the 'Gen' monad.
--
-- The reason for doing this at the output of a module reduces the number of
-- wires that are exposed at the output and therefore allows the synthesis tool
-- to perform more optimisations that it could otherwise not perform. The
-- synthesis tool is quite strict with optimisations if all the wires and
-- registers are exposed.
selectwfreq :: (MonadGen m) => Int -> Int -> [a] -> m [a]
selectwfreq :: forall (m :: * -> *) a. MonadGen m => Int -> Int -> [a] -> m [a]
selectwfreq Int
_ Int
_ [] = [a] -> m [a]
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return []
selectwfreq Int
s Int
n a :: [a]
a@(a
l : [a]
ls)
  | Int
s Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0 Bool -> Bool -> Bool
&& Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0 =
    [(Int, m [a])] -> m [a]
forall (m :: * -> *) a. MonadGen m => [(Int, m a)] -> m a
Hog.frequency
      [ (Int
s, (a
l a -> [a] -> [a]
forall a. a -> [a] -> [a]
:) ([a] -> [a]) -> m [a] -> m [a]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> Int -> [a] -> m [a]
forall (m :: * -> *) a. MonadGen m => Int -> Int -> [a] -> m [a]
selectwfreq Int
s Int
n [a]
ls),
        (Int
n, Int -> Int -> [a] -> m [a]
forall (m :: * -> *) a. MonadGen m => Int -> Int -> [a] -> m [a]
selectwfreq Int
s Int
n [a]
ls)
      ]
  | Bool
otherwise = [a] -> m [a]
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return [a]
a

-- | Generates a module definition randomly. It always has one output port which
-- is set to @y@. The size of @y@ is the total combination of all the locally
-- defined wires, so that it correctly reflects the internal state of the
-- module.
moduleDef :: Maybe Identifier -> StateGen ann (ModDecl ann)
moduleDef :: forall ann. Maybe Identifier -> StateGen ann (ModDecl ann)
moduleDef Maybe Identifier
top = do
  Identifier
name <- Maybe Identifier -> StateGen ann Identifier
forall ann. Maybe Identifier -> StateGen ann Identifier
moduleName Maybe Identifier
top
  [Port]
portList <- Range Int
-> ReaderT Config (GenT (State (Context ann))) Port
-> ReaderT Config (GenT (State (Context ann))) [Port]
forall (m :: * -> *) a. MonadGen m => Range Int -> m a -> m [a]
Hog.list (Int -> Int -> Range Int
forall a. Integral a => a -> a -> Range a
Hog.linear Int
4 Int
10) (ReaderT Config (GenT (State (Context ann))) Port
 -> ReaderT Config (GenT (State (Context ann))) [Port])
-> ReaderT Config (GenT (State (Context ann))) Port
-> ReaderT Config (GenT (State (Context ann))) [Port]
forall a b. (a -> b) -> a -> b
$ Maybe Text -> ReaderT Config (GenT (State (Context ann))) Port
forall ann. Maybe Text -> StateGen ann Port
nextWirePort Maybe Text
forall a. Maybe a
Nothing
  [ModItem ann]
mi <- Range Int
-> ReaderT Config (GenT (State (Context ann))) (ModItem ann)
-> ReaderT Config (GenT (State (Context ann))) [ModItem ann]
forall (m :: * -> *) a. MonadGen m => Range Int -> m a -> m [a]
Hog.list (Int -> Int -> Range Int
forall a. Integral a => a -> a -> Range a
Hog.linear Int
4 Int
100) ReaderT Config (GenT (State (Context ann))) (ModItem ann)
forall ann. StateGen ann (ModItem ann)
modItem
  [Parameter]
ps <- Range Int
-> ReaderT Config (GenT (State (Context ann))) Parameter
-> ReaderT Config (GenT (State (Context ann))) [Parameter]
forall (m :: * -> *) a. MonadGen m => Range Int -> m a -> m [a]
Hog.list (Int -> Int -> Range Int
forall a. Integral a => a -> a -> Range a
Hog.linear Int
0 Int
10) ReaderT Config (GenT (State (Context ann))) Parameter
forall ann. StateGen ann Parameter
parameter
  Context ann
context <- ReaderT Config (GenT (State (Context ann))) (Context ann)
forall s (m :: * -> *). MonadState s m => m s
get
  [Port]
vars <- ReaderT Config (GenT (State (Context ann))) [Port]
forall ann. StateGen ann [Port]
shareableVariables
  Config
config <- ReaderT Config (GenT (State (Context ann))) Config
forall r (m :: * -> *). MonadReader r m => m r
ask
  let ([Port]
newPorts, [Port]
local) = (Port -> Bool) -> [Port] -> ([Port], [Port])
forall a. (a -> Bool) -> [a] -> ([a], [a])
partition (Port -> [Port] -> Bool
`identElem` [Port]
portList) ([Port] -> ([Port], [Port])) -> [Port] -> ([Port], [Port])
forall a b. (a -> b) -> a -> b
$ [Port]
vars [Port] -> [Port] -> [Port]
forall a. Semigroup a => a -> a -> a
<> Context ann -> [Port]
forall a. Context a -> [Port]
_outofscope Context ann
context
  let size :: Range
size =
        [Parameter] -> Int -> Range -> Range
evalRange (Context ann -> [Parameter]
forall a. Context a -> [Parameter]
_parameters Context ann
context) Int
32
          (Range -> Range) -> ([Range] -> Range) -> [Range] -> Range
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Range] -> Range
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum
          ([Range] -> Range) -> [Range] -> Range
forall a b. (a -> b) -> a -> b
$ [Port]
local
            [Port] -> Getting (Endo [Range]) [Port] Range -> [Range]
forall s a. s -> Getting (Endo [a]) s a -> [a]
^.. (Port -> Const (Endo [Range]) Port)
-> [Port] -> Const (Endo [Range]) [Port]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> [a] -> f [b]
traverse
              ((Port -> Const (Endo [Range]) Port)
 -> [Port] -> Const (Endo [Range]) [Port])
-> ((Range -> Const (Endo [Range]) Range)
    -> Port -> Const (Endo [Range]) Port)
-> Getting (Endo [Range]) [Port] Range
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Range -> Const (Endo [Range]) Range)
-> Port -> Const (Endo [Range]) Port
Lens' Port Range
portSize
  let (ProbMod Int
n Int
s) = Config
config Config -> Getting ProbMod Config ProbMod -> ProbMod
forall s a. s -> Getting a s a -> a
^. (Probability -> Const ProbMod Probability)
-> Config -> Const ProbMod Config
Lens' Config Probability
configProbability ((Probability -> Const ProbMod Probability)
 -> Config -> Const ProbMod Config)
-> ((ProbMod -> Const ProbMod ProbMod)
    -> Probability -> Const ProbMod Probability)
-> Getting ProbMod Config ProbMod
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ProbMod -> Const ProbMod ProbMod)
-> Probability -> Const ProbMod Probability
Lens' Probability ProbMod
probMod
  [Port]
newlocal <- Int
-> Int
-> [Port]
-> ReaderT Config (GenT (State (Context ann))) [Port]
forall (m :: * -> *) a. MonadGen m => Int -> Int -> [a] -> m [a]
selectwfreq Int
s Int
n [Port]
local
  let clock :: Port
clock = PortType -> Bool -> Range -> Identifier -> Port
Port PortType
Wire Bool
False Range
1 Identifier
"clk"
  let combine :: Bool
combine = Config
config Config -> Getting Bool Config Bool -> Bool
forall s a. s -> Getting a s a -> a
^. (ConfProperty -> Const Bool ConfProperty)
-> Config -> Const Bool Config
Lens' Config ConfProperty
configProperty ((ConfProperty -> Const Bool ConfProperty)
 -> Config -> Const Bool Config)
-> ((Bool -> Const Bool Bool)
    -> ConfProperty -> Const Bool ConfProperty)
-> Getting Bool Config Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Bool -> Const Bool Bool)
-> ConfProperty -> Const Bool ConfProperty
Lens' ConfProperty Bool
propCombine
  let yport :: Port
yport =
        if Bool
combine then PortType -> Bool -> Range -> Identifier -> Port
Port PortType
Wire Bool
False Range
1 Identifier
"y" else PortType -> Bool -> Range -> Identifier -> Port
Port PortType
Wire Bool
False Range
size Identifier
"y"
  let comb :: ModItem ann
comb = Bool -> Port -> [Port] -> ModItem ann
forall ann. Bool -> Port -> [Port] -> ModItem ann
combineAssigns_ Bool
combine Port
yport [Port]
newlocal
  ModDecl ann -> StateGen ann (ModDecl ann)
forall a. a -> ReaderT Config (GenT (State (Context ann))) a
forall (m :: * -> *) a. Monad m => a -> m a
return
    (ModDecl ann -> StateGen ann (ModDecl ann))
-> ([Parameter] -> ModDecl ann)
-> [Parameter]
-> StateGen ann (ModDecl ann)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Port] -> ModDecl ann -> ModDecl ann
forall ann. [Port] -> ModDecl ann -> ModDecl ann
declareMod [Port]
local
    (ModDecl ann -> ModDecl ann)
-> ([Parameter] -> ModDecl ann) -> [Parameter] -> ModDecl ann
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Identifier
-> [Port] -> [Port] -> [ModItem ann] -> [Parameter] -> ModDecl ann
forall a.
Identifier
-> [Port] -> [Port] -> [ModItem a] -> [Parameter] -> ModDecl a
ModDecl Identifier
name [Port
yport] (Port
clock Port -> [Port] -> [Port]
forall a. a -> [a] -> [a]
: [Port]
newPorts) (ModItem ann
forall {a}. ModItem a
comb ModItem ann -> [ModItem ann] -> [ModItem ann]
forall a. a -> [a] -> [a]
: [ModItem ann]
mi)
    ([Parameter] -> StateGen ann (ModDecl ann))
-> [Parameter] -> StateGen ann (ModDecl ann)
forall a b. (a -> b) -> a -> b
$ [Parameter]
ps

-- | Procedural generation method for random Verilog. Uses internal 'Reader' and
-- 'State' to keep track of the current Verilog code structure.
procedural :: Text -> Config -> Gen (Verilog ann)
procedural :: forall ann. Text -> Config -> Gen (Verilog ann)
procedural Text
top Config
config = do
  (ModDecl ann
mainMod, Context ann
st) <-
    Size
-> GenT Identity (ModDecl ann, Context ann)
-> GenT Identity (ModDecl ann, Context ann)
forall (m :: * -> *) a. MonadGen m => Size -> m a -> m a
Hog.resize Size
num (GenT Identity (ModDecl ann, Context ann)
 -> GenT Identity (ModDecl ann, Context ann))
-> GenT Identity (ModDecl ann, Context ann)
-> GenT Identity (ModDecl ann, Context ann)
forall a b. (a -> b) -> a -> b
$
      StateT (Context ann) (GenT Identity) (ModDecl ann)
-> Context ann -> GenT Identity (ModDecl ann, Context ann)
forall s (m :: * -> *) a. StateT s m a -> s -> m (a, s)
runStateT
        (GenT (StateT (Context ann) Identity) (ModDecl ann)
-> StateT (Context ann) (GenT Identity) (ModDecl ann)
forall (g :: (* -> *) -> * -> *) (f :: (* -> *) -> * -> *)
       (m :: * -> *) a.
(MonadTransDistributive g, Transformer f g m) =>
g (f m) a -> f (g m) a
forall (f :: (* -> *) -> * -> *) (m :: * -> *) a.
Transformer f GenT m =>
GenT (f m) a -> f (GenT m) a
Hog.distributeT (ReaderT Config (GenT (StateT (Context ann) Identity)) (ModDecl ann)
-> Config -> GenT (StateT (Context ann) Identity) (ModDecl ann)
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT (Maybe Identifier
-> ReaderT
     Config (GenT (StateT (Context ann) Identity)) (ModDecl ann)
forall ann. Maybe Identifier -> StateGen ann (ModDecl ann)
moduleDef (Identifier -> Maybe Identifier
forall a. a -> Maybe a
Just (Identifier -> Maybe Identifier) -> Identifier -> Maybe Identifier
forall a b. (a -> b) -> a -> b
$ Text -> Identifier
Identifier Text
top)) Config
config))
        Context ann
forall {a}. Context a
context
  Verilog ann -> Gen (Verilog ann)
forall a. a -> GenT Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return (Verilog ann -> Gen (Verilog ann))
-> ([ModDecl ann] -> Verilog ann)
-> [ModDecl ann]
-> Gen (Verilog ann)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [ModDecl ann] -> Verilog ann
forall a. [ModDecl a] -> Verilog a
Verilog ([ModDecl ann] -> Gen (Verilog ann))
-> [ModDecl ann] -> Gen (Verilog ann)
forall a b. (a -> b) -> a -> b
$ ModDecl ann
mainMod ModDecl ann -> [ModDecl ann] -> [ModDecl ann]
forall a. a -> [a] -> [a]
: Context ann
st Context ann
-> Getting [ModDecl ann] (Context ann) [ModDecl ann]
-> [ModDecl ann]
forall s a. s -> Getting a s a -> a
^. Getting [ModDecl ann] (Context ann) [ModDecl ann]
forall a a (f :: * -> *).
Functor f =>
([ModDecl a] -> f [ModDecl a]) -> Context a -> f (Context a)
modules
  where
    context :: Context a
context =
      [Port]
-> [Port]
-> [Port]
-> [Port]
-> [Parameter]
-> [ModDecl a]
-> Int
-> Int
-> Int
-> Bool
-> Maybe EMIContext
-> Context a
forall a.
[Port]
-> [Port]
-> [Port]
-> [Port]
-> [Parameter]
-> [ModDecl a]
-> Int
-> Int
-> Int
-> Bool
-> Maybe EMIContext
-> Context a
Context [] [] [] [] [] [] Int
0 (((Int -> Const Int Int) -> ConfProperty -> Const Int ConfProperty)
-> Int
forall {a}.
((a -> Const a a) -> ConfProperty -> Const a ConfProperty) -> a
confProp (Int -> Const Int Int) -> ConfProperty -> Const Int ConfProperty
Lens' ConfProperty Int
propStmntDepth) (((Int -> Const Int Int) -> ConfProperty -> Const Int ConfProperty)
-> Int
forall {a}.
((a -> Const a a) -> ConfProperty -> Const a ConfProperty) -> a
confProp (Int -> Const Int Int) -> ConfProperty -> Const Int ConfProperty
Lens' ConfProperty Int
propModDepth) Bool
True Maybe EMIContext
forall a. Maybe a
Nothing
    num :: Size
num = Int -> Size
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Size) -> Int -> Size
forall a b. (a -> b) -> a -> b
$ ((Int -> Const Int Int) -> ConfProperty -> Const Int ConfProperty)
-> Int
forall {a}.
((a -> Const a a) -> ConfProperty -> Const a ConfProperty) -> a
confProp (Int -> Const Int Int) -> ConfProperty -> Const Int ConfProperty
Lens' ConfProperty Int
propSize
    confProp :: ((a -> Const a a) -> ConfProperty -> Const a ConfProperty) -> a
confProp (a -> Const a a) -> ConfProperty -> Const a ConfProperty
i = Config
config Config -> Getting a Config a -> a
forall s a. s -> Getting a s a -> a
^. (ConfProperty -> Const a ConfProperty) -> Config -> Const a Config
Lens' Config ConfProperty
configProperty ((ConfProperty -> Const a ConfProperty)
 -> Config -> Const a Config)
-> ((a -> Const a a) -> ConfProperty -> Const a ConfProperty)
-> Getting a Config a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> Const a a) -> ConfProperty -> Const a ConfProperty
i

-- | Samples the 'Gen' directly to generate random 'Verilog' using the 'Text' as
-- the name of the main module and the configuration 'Config' to influence the
-- generation.
proceduralIO :: Text -> Config -> IO (Verilog a)
proceduralIO :: forall a. Text -> Config -> IO (Verilog a)
proceduralIO Text
t = Gen (Verilog a) -> IO (Verilog a)
forall (m :: * -> *) a. MonadIO m => Gen a -> m a
Hog.sample (Gen (Verilog a) -> IO (Verilog a))
-> (Config -> Gen (Verilog a)) -> Config -> IO (Verilog a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Config -> Gen (Verilog a)
forall ann. Text -> Config -> Gen (Verilog ann)
procedural Text
t

-- | Given a 'Text' and a 'Config' will generate a '(SourceInfo ann)' which has the
-- top module set to the right name.
proceduralSrc :: Text -> Config -> Gen (SourceInfo ann)
proceduralSrc :: forall ann. Text -> Config -> Gen (SourceInfo ann)
proceduralSrc Text
t Config
c = Text -> Verilog ann -> SourceInfo ann
forall a. Text -> Verilog a -> SourceInfo a
SourceInfo Text
t (Verilog ann -> SourceInfo ann)
-> GenT Identity (Verilog ann) -> GenT Identity (SourceInfo ann)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text -> Config -> GenT Identity (Verilog ann)
forall ann. Text -> Config -> Gen (Verilog ann)
procedural Text
t Config
c

-- | Sampled and wrapped into a '(SourceInfo ann)' with the given top module name.
proceduralSrcIO :: Text -> Config -> IO (SourceInfo ann)
proceduralSrcIO :: forall ann. Text -> Config -> IO (SourceInfo ann)
proceduralSrcIO Text
t Config
c = Text -> Verilog ann -> SourceInfo ann
forall a. Text -> Verilog a -> SourceInfo a
SourceInfo Text
t (Verilog ann -> SourceInfo ann)
-> IO (Verilog ann) -> IO (SourceInfo ann)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text -> Config -> IO (Verilog ann)
forall a. Text -> Config -> IO (Verilog a)
proceduralIO Text
t Config
c