diff options
Diffstat (limited to 'src/VeriFuzz/Verilog/AST.hs')
-rw-r--r-- | src/VeriFuzz/Verilog/AST.hs | 336 |
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] |