diff options
author | Yann Herklotz <ymherklotz@gmail.com> | 2019-02-01 19:39:52 +0000 |
---|---|---|
committer | Yann Herklotz <ymherklotz@gmail.com> | 2019-02-01 19:39:52 +0000 |
commit | 1067284cc1f6ca8ba646545c5b8d0a79cc2e41ad (patch) | |
tree | 2c9a8d54bf6f9870f0ae62c150803ccec90d46e7 /src/VeriFuzz/Verilog/CodeGen.hs | |
parent | a38289ca9d96e97bc4e65b67c50f5805d56a3d86 (diff) | |
download | verismith-1067284cc1f6ca8ba646545c5b8d0a79cc2e41ad.tar.gz verismith-1067284cc1f6ca8ba646545c5b8d0a79cc2e41ad.zip |
More restructuring
Diffstat (limited to 'src/VeriFuzz/Verilog/CodeGen.hs')
-rw-r--r-- | src/VeriFuzz/Verilog/CodeGen.hs | 276 |
1 files changed, 0 insertions, 276 deletions
diff --git a/src/VeriFuzz/Verilog/CodeGen.hs b/src/VeriFuzz/Verilog/CodeGen.hs deleted file mode 100644 index 3253f86..0000000 --- a/src/VeriFuzz/Verilog/CodeGen.hs +++ /dev/null @@ -1,276 +0,0 @@ -{-| -Module : VeriFuzz.Verilog.CodeGen -Description : Code generation for Verilog AST. -Copyright : (c) 2018-2019, Yann Herklotz Grave -License : BSD-3 -Maintainer : ymherklotz [at] gmail [dot] com -Stability : experimental -Portability : POSIX - -This module generates the code from the Verilog AST defined in -"VeriFuzz.Verilog.AST". --} - -{-# LANGUAGE FlexibleInstances #-} - -module VeriFuzz.Verilog.CodeGen where - -import Control.Lens (view, (^.)) -import Data.Foldable (fold) -import Data.Text (Text) -import qualified Data.Text as T -import qualified Data.Text.IO as T -import Numeric (showHex) -import Test.QuickCheck (Arbitrary, arbitrary) -import VeriFuzz.Verilog.AST - --- | 'Source' class which determines that source code is able to be generated --- from the data structure using 'genSource'. This will be stored in 'Text' and --- can then be processed further. -class Source a where - genSource :: a -> Text - --- | Inserts commas between '[Text]' and except the last one. -comma :: [Text] -> Text -comma = T.intercalate ", " - --- | Show function for 'Text' -showT :: (Show a) => a -> Text -showT = T.pack . show - --- | Map a 'Maybe Stmnt' to 'Text'. If it is 'Just stmnt', the generated --- statements are returned. If it is 'Nothing', then @;\n@ is returned. -defMap :: Maybe Stmnt -> Text -defMap = maybe ";\n" genStmnt - --- | Convert the 'VerilogSrc' type to 'Text' so that it can be rendered. -genVerilogSrc :: VerilogSrc -> Text -genVerilogSrc source = fold $ genDescription <$> source ^. getVerilogSrc - --- | Generate the 'Description' to 'Text'. -genDescription :: Description -> Text -genDescription desc = genModuleDecl $ desc ^. getDescription - --- | Generate the 'ModDecl' for a module and convert it to 'Text'. -genModuleDecl :: ModDecl -> Text -genModuleDecl m = - "module " <> m ^. modId . getIdentifier <> ports <> ";\n" <> modI <> "endmodule\n" - where - ports | noIn && noOut = "" - | otherwise = "(" <> comma (genModPort <$> outIn) <> ")" - modI = fold $ genModuleItem <$> m ^. modItems - noOut = null $ m ^. modOutPorts - noIn = null $ m ^. modInPorts - outIn = (m ^. modOutPorts) ++ (m ^. modInPorts) - --- | Conversts 'Port' to 'Text' for the module list, which means it only --- generates a list of identifiers. -genModPort :: Port -> Text -genModPort port = port ^. portName . getIdentifier - --- | Generate the 'Port' description. -genPort :: Port -> Text -genPort port = t <> size <> name - where - t = (<> " ") . genPortType $ port ^. portType - size | port ^. portSize > 1 = "[" <> showT (port ^. portSize - 1) <> ":0] " - | otherwise = "" - name = port ^. portName . getIdentifier - --- | Convert the 'PortDir' type to 'Text'. -genPortDir :: PortDir -> Text -genPortDir PortIn = "input" -genPortDir PortOut = "output" -genPortDir PortInOut = "inout" - --- | Generate a 'ModItem'. -genModuleItem :: ModItem -> Text -genModuleItem (ModCA ca) = genContAssign ca -genModuleItem (ModInst (Identifier i) (Identifier name) conn) = - i <> " " <> name <> "(" <> comma (genModConn <$> conn) <> ")" <> ";\n" -genModuleItem (Initial stat ) = "initial " <> genStmnt stat -genModuleItem (Always stat ) = "always " <> genStmnt stat -genModuleItem (Decl dir port) = maybe "" makePort dir <> genPort port <> ";\n" - where makePort = (<> " ") . genPortDir - -genModConn :: ModConn -> Text -genModConn (ModConn c) = - genExpr c -genModConn (ModConnNamed n c) = - "." <> n ^. getIdentifier <> "(" <> genExpr c <> ")" - --- | Generate continuous assignment -genContAssign :: ContAssign -> Text -genContAssign (ContAssign val e) = "assign " <> name <> " = " <> expr <> ";\n" - where - name = val ^. getIdentifier - expr = genExpr e - --- | Generate 'Function' to 'Text' -genFunc :: Function -> Text -genFunc SignedFunc = "$signed" -genFunc UnSignedFunc = "$unsigned" - --- | Generate 'Expr' to 'Text'. -genExpr :: Expr -> Text -genExpr (BinOp eRhs bin eLhs) = "(" <> genExpr eRhs <> genBinaryOperator bin <> genExpr eLhs <> ")" -genExpr (Number s n ) = minus <> showT s <> "'h" <> T.pack (showHex (abs n) "") - where minus | signum n > 0 = "" | otherwise = "-" -genExpr (Id i ) = i ^. getIdentifier -genExpr (Concat c ) = "{" <> comma (genExpr <$> c) <> "}" -genExpr (UnOp u e ) = "(" <> genUnaryOperator u <> genExpr e <> ")" -genExpr (Cond l t f ) = "(" <> genExpr l <> " ? " <> genExpr t <> " : " <> genExpr f <> ")" -genExpr (Func f e ) = genFunc f <> "(" <> genExpr e <> ")" -genExpr (Str t ) = "\"" <> t <> "\"" - --- | Convert 'BinaryOperator' to 'Text'. -genBinaryOperator :: BinaryOperator -> Text -genBinaryOperator BinPlus = " + " -genBinaryOperator BinMinus = " - " -genBinaryOperator BinTimes = " * " -genBinaryOperator BinDiv = " / " -genBinaryOperator BinMod = " % " -genBinaryOperator BinEq = " == " -genBinaryOperator BinNEq = " != " -genBinaryOperator BinCEq = " === " -genBinaryOperator BinCNEq = " !== " -genBinaryOperator BinLAnd = " && " -genBinaryOperator BinLOr = " || " -genBinaryOperator BinLT = " < " -genBinaryOperator BinLEq = " <= " -genBinaryOperator BinGT = " > " -genBinaryOperator BinGEq = " >= " -genBinaryOperator BinAnd = " & " -genBinaryOperator BinOr = " | " -genBinaryOperator BinXor = " ^ " -genBinaryOperator BinXNor = " ^~ " -genBinaryOperator BinXNorInv = " ~^ " -genBinaryOperator BinPower = " ** " -genBinaryOperator BinLSL = " << " -genBinaryOperator BinLSR = " >> " -genBinaryOperator BinASL = " <<< " -genBinaryOperator BinASR = " >>> " - --- | Convert 'UnaryOperator' to 'Text'. -genUnaryOperator :: UnaryOperator -> Text -genUnaryOperator UnPlus = "+" -genUnaryOperator UnMinus = "-" -genUnaryOperator UnNot = "!" -genUnaryOperator UnAnd = "&" -genUnaryOperator UnNand = "~&" -genUnaryOperator UnOr = "|" -genUnaryOperator UnNor = "~|" -genUnaryOperator UnXor = "^" -genUnaryOperator UnNxor = "~^" -genUnaryOperator UnNxorInv = "^~" - --- | Generate verilog code for an 'Event'. -genEvent :: Event -> Text -genEvent (EId i ) = "@(" <> i ^. getIdentifier <> ")" -genEvent (EExpr expr) = "@(" <> genExpr expr <> ")" -genEvent EAll = "@*" -genEvent (EPosEdge i) = "@(posedge " <> i ^. getIdentifier <> ")" -genEvent (ENegEdge i) = "@(negedge " <> i ^. getIdentifier <> ")" - --- | Generates verilog code for a 'Delay'. -genDelay :: Delay -> Text -genDelay (Delay i) = "#" <> showT i - --- | Generate the verilog code for an 'LVal'. -genLVal :: LVal -> Text -genLVal (RegId i ) = i ^. getIdentifier -genLVal (RegExpr i expr) = i ^. getIdentifier <> " [" <> genExpr expr <> "]" -genLVal (RegSize i msb lsb) = - i ^. getIdentifier <> " [" <> genConstExpr msb <> ":" <> genConstExpr lsb <> "]" -genLVal (RegConcat e) = "{" <> comma (genExpr <$> e) <> "}" - -genConstExpr :: ConstExpr -> Text -genConstExpr (ConstExpr num) = showT num - -genPortType :: PortType -> Text -genPortType Wire = "wire" -genPortType (Reg signed) | signed = "reg signed" - | otherwise = "reg" - -genAssign :: Text -> Assign -> Text -genAssign op (Assign r d e) = genLVal r <> op <> maybe "" genDelay d <> genExpr e - -genStmnt :: Stmnt -> Text -genStmnt (TimeCtrl d stat ) = genDelay d <> " " <> defMap stat -genStmnt (EventCtrl e stat ) = genEvent e <> " " <> defMap stat -genStmnt (SeqBlock s ) = "begin\n" <> fold (genStmnt <$> s) <> "end\n" -genStmnt (BlockAssign a ) = genAssign " = " a <> ";\n" -genStmnt (NonBlockAssign a ) = genAssign " <= " a <> ";\n" -genStmnt (StatCA a ) = genContAssign a -genStmnt (TaskEnable task) = genTask task <> ";\n" -genStmnt (SysTaskEnable task) = "$" <> genTask task <> ";\n" - -genTask :: Task -> Text -genTask (Task name expr) | null expr = i - | otherwise = i <> "(" <> comma (genExpr <$> expr) <> ")" - where i = name ^. getIdentifier - --- | Render the 'Text' to 'IO'. This is equivalent to 'putStrLn'. -render :: (Source a) => a -> IO () -render = T.putStrLn . genSource - --- Instances - -instance Source Identifier where - genSource = view getIdentifier - -instance Source Task where - genSource = genTask - -instance Source Stmnt where - genSource = genStmnt - -instance Source PortType where - genSource = genPortType - -instance Source ConstExpr where - genSource = genConstExpr - -instance Source LVal where - genSource = genLVal - -instance Source Delay where - genSource = genDelay - -instance Source Event where - genSource = genEvent - -instance Source UnaryOperator where - genSource = genUnaryOperator - -instance Source Expr where - genSource = genExpr - -instance Source ContAssign where - genSource = genContAssign - -instance Source ModItem where - genSource = genModuleItem - -instance Source PortDir where - genSource = genPortDir - -instance Source Port where - genSource = genPort - -instance Source ModDecl where - genSource = genModuleDecl - -instance Source Description where - genSource = genDescription - -instance Source VerilogSrc where - genSource = genVerilogSrc - -newtype GenVerilog a = GenVerilog { unGenVerilog :: a } - -instance (Source a) => Show (GenVerilog a) where - show = T.unpack . genSource . unGenVerilog - -instance (Arbitrary a) => Arbitrary (GenVerilog a) where - arbitrary = GenVerilog <$> arbitrary |