aboutsummaryrefslogtreecommitdiffstats
path: root/src/VeriFuzz/Verilog/AST.hs
diff options
context:
space:
mode:
Diffstat (limited to 'src/VeriFuzz/Verilog/AST.hs')
-rw-r--r--src/VeriFuzz/Verilog/AST.hs336
1 files changed, 105 insertions, 231 deletions
diff --git a/src/VeriFuzz/Verilog/AST.hs b/src/VeriFuzz/Verilog/AST.hs
index 405b712..007b3b5 100644
--- a/src/VeriFuzz/Verilog/AST.hs
+++ b/src/VeriFuzz/Verilog/AST.hs
@@ -18,8 +18,6 @@ module VeriFuzz.Verilog.AST
( -- * Top level types
Verilog(..)
, getVerilog
- , Description(..)
- , getDescription
-- * Primitives
-- ** Identifier
, Identifier(..)
@@ -50,6 +48,7 @@ module VeriFuzz.Verilog.AST
, Port(..)
, portType
, portSigned
+ , portSizeLower
, portSize
, portName
-- * Expression
@@ -69,10 +68,20 @@ module VeriFuzz.Verilog.AST
, exprFunc
, exprBody
, exprStr
- , exprWithContext
- , traverseExpr
, ConstExpr(..)
+ , constSize
, constNum
+ , constParamId
+ , constConcat
+ , constUnOp
+ , constPrim
+ , constLhs
+ , constBinOp
+ , constRhs
+ , constCond
+ , constTrue
+ , constFalse
+ , constStr
, Function(..)
-- * Assignment
, Assign(..)
@@ -82,6 +91,13 @@ module VeriFuzz.Verilog.AST
, ContAssign(..)
, contAssignNetLVal
, contAssignExpr
+ -- ** Parameters
+ , Parameter(..)
+ , paramIdent
+ , paramValue
+ , LocalParam(..)
+ , localParamIdent
+ , localParamValue
-- * Statment
, Statement(..)
, statDelay
@@ -91,26 +107,33 @@ module VeriFuzz.Verilog.AST
, statements
, stmntBA
, stmntNBA
- , stmntCA
, stmntTask
, stmntSysTask
, stmntCondExpr
, stmntCondTrue
, stmntCondFalse
+ , forAssign
+ , forExpr
+ , forIncr
+ , forStmnt
-- * Module
, ModDecl(..)
, modId
, modOutPorts
, modInPorts
, modItems
+ , modParams
, ModItem(..)
, modContAssign
, modInstId
, modInstName
, modInstConns
+ , paramDecl
+ , localParamDecl
, traverseModItem
, declDir
, declPort
+ , declVal
, ModConn(..)
, modConn
, modConnName
@@ -118,25 +141,16 @@ module VeriFuzz.Verilog.AST
-- * Useful Lenses and Traversals
, getModule
, getSourceId
- -- * Arbitrary
- , Arb
- , arb
- , genPositive
)
where
import Control.Lens
-import Control.Monad (replicateM)
import Data.Data
import Data.Data.Lens
-import Data.List.NonEmpty (toList)
+import Data.List.NonEmpty (NonEmpty)
import Data.String (IsString, fromString)
import Data.Text (Text)
-import qualified Data.Text as T
import Data.Traversable (sequenceA)
-import Hedgehog (Gen)
-import qualified Hedgehog.Gen as Hog
-import qualified Hedgehog.Range as Hog
-- | Identifier in Verilog. This is just a string of characters that can either
-- be lowercase and uppercase for now. This might change in the future though,
@@ -199,7 +213,7 @@ data UnaryOperator = UnPlus -- ^ @+@
deriving (Eq, Show, Ord, Data)
data Function = SignedFunc
- | UnSignedFunc
+ | UnsignedFunc
deriving (Eq, Show, Ord, Data)
-- | Verilog expression, which can either be a primary expression, unary
@@ -250,17 +264,49 @@ instance IsString Expr where
instance Plated Expr where
plate = uniplate
-traverseExpr :: (Applicative f) => (Expr -> f Expr) -> Expr -> f Expr
-traverseExpr f (Concat e ) = Concat <$> sequenceA (f <$> e)
-traverseExpr f (UnOp u e ) = UnOp u <$> f e
-traverseExpr f (BinOp l o r) = BinOp <$> f l <*> pure o <*> f r
-traverseExpr f (Cond c l r) = Cond <$> f c <*> f l <*> f r
-traverseExpr f (Func fn e ) = Func fn <$> f e
-traverseExpr _ e = pure e
+-- | Constant expression, which are known before simulation at compile time.
+data ConstExpr = ConstNum { _constSize :: Int
+ , _constNum :: Integer
+ }
+ | ParamId { _constParamId :: {-# UNPACK #-} !Identifier }
+ | ConstConcat { _constConcat :: [ConstExpr] }
+ | ConstUnOp { _constUnOp :: !UnaryOperator
+ , _constPrim :: ConstExpr
+ }
+ | ConstBinOp { _constLhs :: ConstExpr
+ , _constBinOp :: !BinaryOperator
+ , _constRhs :: ConstExpr
+ }
+ | ConstCond { _constCond :: ConstExpr
+ , _constTrue :: ConstExpr
+ , _constFalse :: ConstExpr
+ }
+ | ConstStr { _constStr :: {-# UNPACK #-} !Text }
+ deriving (Eq, Show, Ord, Data)
+
+instance Num ConstExpr where
+ a + b = ConstBinOp a BinPlus b
+ a - b = ConstBinOp a BinMinus b
+ a * b = ConstBinOp a BinTimes b
+ negate = ConstUnOp UnMinus
+ abs = undefined
+ signum = undefined
+ fromInteger = ConstNum 32 . fromInteger
+
+instance Semigroup ConstExpr where
+ (ConstConcat a) <> (ConstConcat b) = ConstConcat $ a <> b
+ (ConstConcat a) <> b = ConstConcat $ a <> [b]
+ a <> (ConstConcat b) = ConstConcat $ a : b
+ a <> b = ConstConcat [a, b]
--- | Constant expression, which are known before simulation at compilation time.
-newtype ConstExpr = ConstExpr { _constNum :: Int }
- deriving (Eq, Show, Ord, Data, Num)
+instance Monoid ConstExpr where
+ mempty = ConstConcat []
+
+instance IsString ConstExpr where
+ fromString = ConstStr . fromString
+
+instance Plated ConstExpr where
+ plate = uniplate
data Task = Task { _taskName :: {-# UNPACK #-} !Identifier
, _taskExpr :: [Expr]
@@ -306,10 +352,11 @@ data PortType = Wire
--
-- This is now implemented inside 'ModDecl' itself, which uses a list of output
-- and input ports.
-data Port = Port { _portType :: !PortType
- , _portSigned :: !Bool
- , _portSize :: {-# UNPACK #-} !Int
- , _portName :: {-# UNPACK #-} !Identifier
+data Port = Port { _portType :: !PortType
+ , _portSigned :: !Bool
+ , _portSizeLower :: {-# UNPACK #-} !Int
+ , _portSize :: {-# UNPACK #-} !Int
+ , _portName :: {-# UNPACK #-} !Identifier
} deriving (Eq, Show, Ord, Data)
-- | This is currently a type because direct module declaration should also be
@@ -343,13 +390,17 @@ data Statement = TimeCtrl { _statDelay :: {-# UNPACK #-} !Delay
| SeqBlock { _statements :: [Statement] } -- ^ Sequential block (@begin ... end@)
| BlockAssign { _stmntBA :: !Assign } -- ^ blocking assignment (@=@)
| NonBlockAssign { _stmntNBA :: !Assign } -- ^ Non blocking assignment (@<=@)
- | StatCA { _stmntCA :: !ContAssign } -- ^ Statement continuous assignment. May not be correct.
| TaskEnable { _stmntTask :: !Task }
| SysTaskEnable { _stmntSysTask :: !Task }
| CondStmnt { _stmntCondExpr :: Expr
, _stmntCondTrue :: Maybe Statement
, _stmntCondFalse :: Maybe Statement
}
+ | ForLoop { _forAssign :: !Assign
+ , _forExpr :: Expr
+ , _forIncr :: !Assign
+ , _forStmnt :: Statement
+ } -- ^ Loop bounds shall be statically computable for a for loop.
deriving (Eq, Show, Ord, Data)
instance Semigroup Statement where
@@ -361,6 +412,19 @@ instance Semigroup Statement where
instance Monoid Statement where
mempty = SeqBlock []
+-- | Parameter that can be assigned in blocks or modules using @parameter@.
+data Parameter = Parameter { _paramIdent :: {-# UNPACK #-} !Identifier
+ , _paramValue :: ConstExpr
+ }
+ deriving (Eq, Show, Ord, Data)
+
+-- | Local parameter that can be assigned anywhere using @localparam@. It cannot
+-- be changed by initialising the module.
+data LocalParam = LocalParam { _localParamIdent :: {-# UNPACK #-} !Identifier
+ , _localParamValue :: ConstExpr
+ }
+ deriving (Eq, Show, Ord, Data)
+
-- | Module item which is the body of the module expression.
data ModItem = ModCA { _modContAssign :: !ContAssign }
| ModInst { _modInstId :: {-# UNPACK #-} !Identifier
@@ -371,7 +435,10 @@ data ModItem = ModCA { _modContAssign :: !ContAssign }
| Always !Statement
| Decl { _declDir :: !(Maybe PortDir)
, _declPort :: !Port
+ , _declVal :: Maybe ConstExpr
}
+ | ParamDecl { _paramDecl :: NonEmpty Parameter }
+ | LocalParamDecl { _localParamDecl :: NonEmpty LocalParam }
deriving (Eq, Show, Ord, Data)
-- | 'module' module_identifier [list_of_ports] ';' { module_item } 'end_module'
@@ -379,7 +446,9 @@ data ModDecl = ModDecl { _modId :: {-# UNPACK #-} !Identifier
, _modOutPorts :: [Port]
, _modInPorts :: [Port]
, _modItems :: [ModItem]
- } deriving (Eq, Show, Ord, Data)
+ , _modParams :: [Parameter]
+ }
+ deriving (Eq, Show, Ord, Data)
traverseModConn :: (Applicative f) => (Expr -> f Expr) -> ModConn -> f ModConn
traverseModConn f (ModConn e ) = ModConn <$> f e
@@ -391,12 +460,8 @@ traverseModItem f (ModInst a b e) =
ModInst a b <$> sequenceA (traverseModConn f <$> e)
traverseModItem _ e = pure e
--- | Description of the Verilog module.
-newtype Description = Description { _getDescription :: ModDecl }
- deriving (Eq, Show, Ord, Data)
-
-- | The complete sourcetext for the Verilog module.
-newtype Verilog = Verilog { _getVerilog :: [Description] }
+newtype Verilog = Verilog { _getVerilog :: [ModDecl] }
deriving (Eq, Show, Ord, Data, Semigroup, Monoid)
makeLenses ''Identifier
@@ -412,206 +477,15 @@ makeLenses ''Assign
makeLenses ''ContAssign
makeLenses ''Statement
makeLenses ''ModItem
+makeLenses ''Parameter
+makeLenses ''LocalParam
makeLenses ''ModDecl
-makeLenses ''Description
makeLenses ''Verilog
getModule :: Traversal' Verilog ModDecl
-getModule = getVerilog . traverse . getDescription
+getModule = getVerilog . traverse
{-# INLINE getModule #-}
getSourceId :: Traversal' Verilog Text
getSourceId = getModule . modId . getIdentifier
{-# INLINE getSourceId #-}
-
-listOf1 :: Gen a -> Gen [a]
-listOf1 a = toList <$> Hog.nonEmpty (Hog.linear 0 100) a
-
-listOf :: Gen a -> Gen [a]
-listOf = Hog.list (Hog.linear 0 100)
-
-genPositive :: Gen Int
-genPositive = Hog.filter (>= 0) $ Hog.int (Hog.linear 1 99)
-
-integral :: Gen Integer
-integral = Hog.integral (Hog.linear 0 100)
-
-class Arb a where
- arb :: Gen a
-
-instance Arb Identifier where
- arb = do
- l <- genPositive
- Identifier . T.pack <$> replicateM (l + 1) (Hog.element ['a'..'z'])
-
-instance Arb Delay where
- arb = Delay <$> genPositive
-
-instance Arb Event where
- arb = EId <$> arb
-
-instance Arb BinaryOperator where
- arb = Hog.element
- [ BinPlus
- , BinMinus
- , BinTimes
- -- , BinDiv
- -- , BinMod
- , BinEq
- , BinNEq
- -- , BinCEq
- -- , BinCNEq
- , BinLAnd
- , BinLOr
- , BinLT
- , BinLEq
- , BinGT
- , BinGEq
- , BinAnd
- , BinOr
- , BinXor
- , BinXNor
- , BinXNorInv
- -- , BinPower
- , BinLSL
- , BinLSR
- , BinASL
- , BinASR
- ]
-
-instance Arb UnaryOperator where
- arb = Hog.element
- [ UnPlus
- , UnMinus
- , UnNot
- , UnLNot
- , UnAnd
- , UnNand
- , UnOr
- , UnNor
- , UnXor
- , UnNxor
- , UnNxorInv
- ]
-
-instance Arb Function where
- arb = Hog.element
- [ SignedFunc
- , UnSignedFunc
- ]
-
-instance Arb Expr where
- arb = Hog.sized expr
-
-exprSafeList :: [Gen Expr]
-exprSafeList = [Number <$> genPositive <*> integral]
-
-exprRecList :: (Hog.Size -> Gen Expr) -> [Gen Expr]
-exprRecList subexpr =
- [ Number <$> genPositive <*> integral
- , Concat <$> listOf1 (subexpr 8)
- , UnOp
- <$> arb
- <*> subexpr 2
- -- , Str <$> arb
- , BinOp <$> subexpr 2 <*> arb <*> subexpr 2
- , Cond <$> subexpr 3 <*> subexpr 3 <*> subexpr 3
- , Func <$> arb <*> subexpr 2
- ]
-
-expr :: Hog.Size -> Gen Expr
-expr n | n == 0 = Hog.choice $ (Id <$> arb) : exprSafeList
- | n > 0 = Hog.choice $ (Id <$> arb) : exprRecList subexpr
- | otherwise = expr 0
- where subexpr y = expr (n `div` y)
-
-exprWithContext :: [Identifier] -> Hog.Size -> Gen Expr
-exprWithContext [] n | n == 0 = Hog.choice exprSafeList
- | n > 0 = Hog.choice $ exprRecList subexpr
- | otherwise = exprWithContext [] 0
- where subexpr y = exprWithContext [] (n `div` y)
-exprWithContext l n
- | n == 0 = Hog.choice $ (Id <$> Hog.element l) : exprSafeList
- | n > 0 = Hog.choice $ (Id <$> Hog.element l) : exprRecList subexpr
- | otherwise = exprWithContext l 0
- where subexpr y = exprWithContext l (n `div` y)
-
-instance Arb Int where
- arb = Hog.int (Hog.linear 0 100)
-
-instance Arb ConstExpr where
- arb = ConstExpr <$> Hog.int (Hog.linear 0 100)
-
-instance Arb Task where
- arb = Task <$> arb <*> listOf arb
-
-instance Arb LVal where
- arb = Hog.choice [ RegId <$> arb
- , RegExpr <$> arb <*> arb
- , RegSize <$> arb <*> arb <*> arb
- ]
-
-instance Arb PortDir where
- arb = Hog.element [PortIn, PortOut, PortInOut]
-
-instance Arb PortType where
- arb = Hog.element [Wire, Reg]
-
-instance Arb Port where
- arb = Port <$> arb <*> arb <*> genPositive <*> arb
-
-instance Arb ModConn where
- arb = ModConn <$> arb
-
-instance Arb Assign where
- arb = Assign <$> arb <*> Hog.maybe arb <*> arb
-
-instance Arb ContAssign where
- arb = ContAssign <$> arb <*> arb
-
-instance Arb Statement where
- arb = Hog.sized statement
-
-statement :: Hog.Size -> Gen Statement
-statement n
- | n == 0 = Hog.choice
- [ BlockAssign <$> arb
- , NonBlockAssign <$> arb
- -- , StatCA <$> arb
- , TaskEnable <$> arb
- , SysTaskEnable <$> arb
- ]
- | n > 0 = Hog.choice
- [ TimeCtrl <$> arb <*> (Just <$> substat 2)
- , SeqBlock <$> listOf1 (substat 4)
- , BlockAssign <$> arb
- , NonBlockAssign <$> arb
- -- , StatCA <$> arb
- , TaskEnable <$> arb
- , SysTaskEnable <$> arb
- ]
- | otherwise = statement 0
- where substat y = statement (n `div` y)
-
-instance Arb ModItem where
- arb = Hog.choice [ ModCA <$> arb
- , ModInst <$> arb <*> arb <*> listOf arb
- , Initial <$> arb
- , Always <$> (EventCtrl <$> arb <*> Hog.maybe arb)
- , Decl <$> pure Nothing <*> arb
- ]
-
-modPortGen :: Gen Port
-modPortGen = Port <$> arb <*> arb <*> arb <*> arb
-
-instance Arb ModDecl where
- arb = ModDecl <$> arb <*> listOf arb <*> listOf1 modPortGen <*> listOf arb
-
-instance Arb Description where
- arb = Description <$> arb
-
-instance Arb Verilog where
- arb = Verilog <$> listOf1 arb
-
-instance Arb Bool where
- arb = Hog.element [True, False]