Commit 383754fa by Zachary Snow

final major round of splitting and cleanup in the SystemVerilog module

parent 6d0f7dd0
-- | A parser for SystemVerilog.
{- sv2v
- Author: Tom Hawkins <tomahawkins@gmail.com>
-
- A parser for SystemVerilog.
-}
module Language.SystemVerilog
( module Language.SystemVerilog.AST
, module Language.SystemVerilog.Parser
) where
( module Language.SystemVerilog.AST
, module Language.SystemVerilog.Parser
) where
import Language.SystemVerilog.AST
import Language.SystemVerilog.Parser
......@@ -14,257 +14,28 @@
-}
module Language.SystemVerilog.AST
( Description(..)
, PackageItem(..)
, ModuleItem (..)
, Direction (..)
, GenItem (..)
, AlwaysKW (..)
, CaseKW (..)
, PartKW (..)
, Lifetime (..)
, NInputGateKW (..)
, NOutputGateKW (..)
, AST
, PortBinding
, ModportDecl
, GenCase
, simplify
, rangeSize
( AST
, module Attr
, module Decl
, module Description
, module Expr
, module GenItem
, module LHS
, module ModuleItem
, module Op
, module Stmt
, module Type
) where
import Data.List (intercalate)
import Data.Maybe (maybe, fromJust, isJust)
import Text.Printf (printf)
import Text.Read (readMaybe)
import Language.SystemVerilog.AST.Attr as Attr
import Language.SystemVerilog.AST.Decl as Decl
import Language.SystemVerilog.AST.Description as Description
import Language.SystemVerilog.AST.Expr as Expr
import Language.SystemVerilog.AST.GenItem as GenItem
import Language.SystemVerilog.AST.LHS as LHS
import Language.SystemVerilog.AST.ModuleItem as ModuleItem
import Language.SystemVerilog.AST.Op as Op
import Language.SystemVerilog.AST.Stmt as Stmt
import Language.SystemVerilog.AST.Type as Type
import Language.SystemVerilog.AST.ShowHelp
-- Note: Verilog allows modules to be declared with either a simple list of
-- ports _identifiers_, or a list of port _declarations_. If only the
-- identifiers are used, they must be declared with a type and direction
-- (potentially separately!) within the module itself.
type AST = [Description]
data PackageItem
= Typedef Type Identifier
| Function (Maybe Lifetime) Type Identifier [Decl] [Stmt]
| Task (Maybe Lifetime) Identifier [Decl] [Stmt]
| Comment String
deriving Eq
instance Show PackageItem where
show (Typedef t x) = printf "typedef %s %s;" (show t) x
show (Function ml t x i b) =
printf "function %s%s%s;\n%s\n%s\nendfunction"
(showLifetime ml) (showPad t) x (indent $ show i)
(indent $ unlines' $ map show b)
show (Task ml x i b) =
printf "task %s%s;\n%s\n%s\nendtask"
(showLifetime ml) x (indent $ show i)
(indent $ unlines' $ map show b)
show (Comment c) = "// " ++ c
data Description
= Part Bool PartKW (Maybe Lifetime) Identifier [Identifier] [ModuleItem]
| PackageItem PackageItem
| Directive String
deriving Eq
instance Show Description where
showList descriptions _ = intercalate "\n" $ map show descriptions
show (Part True kw lifetime name _ items) =
printf "extern %s %s%s %s;"
(show kw) (showLifetime lifetime) name (indentedParenList itemStrs)
where itemStrs = map (\(MIDecl a) -> init $ show a) items
show (Part False kw lifetime name ports items) =
printf "%s %s%s%s;\n%s\nend%s"
(show kw) (showLifetime lifetime) name portsStr bodyStr (show kw)
where
portsStr =
if null ports
then ""
else " " ++ indentedParenList ports
bodyStr = indent $ unlines' $ map show items
show (PackageItem i) = show i
show (Directive str) = str
data PartKW
= Module
| Interface
deriving Eq
instance Show PartKW where
show Module = "module"
show Interface = "interface"
data ModuleItem
= MIAttr Attr ModuleItem
| MIDecl Decl
| AlwaysC AlwaysKW Stmt
| Assign (Maybe Expr) LHS Expr
| Defparam LHS Expr
| Instance Identifier [PortBinding] Identifier (Maybe Range) [PortBinding]
| Genvar Identifier
| Generate [GenItem]
| Modport Identifier [ModportDecl]
| Initial Stmt
| MIPackageItem PackageItem
| NInputGate NInputGateKW (Maybe Identifier) LHS [Expr]
| NOutputGate NOutputGateKW (Maybe Identifier) [LHS] Expr
| AssertionItem AssertionItem
deriving Eq
data AlwaysKW
= Always
| AlwaysComb
| AlwaysFF
| AlwaysLatch
deriving Eq
instance Show AlwaysKW where
show Always = "always"
show AlwaysComb = "always_comb"
show AlwaysFF = "always_ff"
show AlwaysLatch = "always_latch"
type PortBinding = (Identifier, Maybe Expr)
type ModportDecl = (Direction, Identifier, Maybe Expr)
instance Show ModuleItem where
show thing = case thing of
MIAttr attr mi -> printf "%s %s" (show attr) (show mi)
MIDecl nest -> show nest
AlwaysC k b -> printf "%s %s" (show k) (show b)
Assign d a b -> printf "assign %s%s = %s;" delayStr (show a) (show b)
where delayStr = maybe "" (\e -> "#(" ++ show e ++ ") ") d
Defparam a b -> printf "defparam %s = %s;" (show a) (show b)
Instance m params i r ports
| null params -> printf "%s %s%s%s;" m i rStr (showPorts ports)
| otherwise -> printf "%s #%s %s%s%s;" m (showPorts params) i rStr (showPorts ports)
where rStr = maybe "" (\a -> showRanges [a] ++ " ") r
Genvar x -> printf "genvar %s;" x
Generate b -> printf "generate\n%s\nendgenerate" (indent $ unlines' $ map show b)
Modport x l -> printf "modport %s(\n%s\n);" x (indent $ intercalate ",\n" $ map showModportDecl l)
Initial s -> printf "initial %s" (show s)
MIPackageItem i -> show i
NInputGate kw x lhs exprs -> printf "%s%s (%s, %s);" (show kw) (maybe "" (" " ++) x) (show lhs) (commas $ map show exprs)
NOutputGate kw x lhss expr -> printf "%s%s (%s, %s);" (show kw) (maybe "" (" " ++) x) (commas $ map show lhss) (show expr)
AssertionItem (Nothing, a) -> show a
AssertionItem (Just x, a) -> printf "%s : %s" x (show a)
where
showPorts :: [PortBinding] -> String
showPorts ports = indentedParenList $ map showPort ports
showPort :: PortBinding -> String
showPort ("*", Nothing) = ".*"
showPort (i, arg) =
if i == ""
then show (fromJust arg)
else printf ".%s(%s)" i (if isJust arg then show $ fromJust arg else "")
showModportDecl :: ModportDecl -> String
showModportDecl (dir, ident, me) =
if me == Just (Ident ident)
then printf "%s %s" (show dir) ident
else printf "%s .%s(%s)" (show dir) ident (maybe "" show me)
data NInputGateKW
= GateAnd
| GateNand
| GateOr
| GateNor
| GateXor
| GateXnor
deriving Eq
data NOutputGateKW
= GateBuf
| GateNot
deriving Eq
instance Show NInputGateKW where
show GateAnd = "and"
show GateNand = "nand"
show GateOr = "or"
show GateNor = "nor"
show GateXor = "xor"
show GateXnor = "xnor"
instance Show NOutputGateKW where
show GateBuf = "buf"
show GateNot = "not"
type GenCase = ([Expr], GenItem)
data GenItem
= GenBlock (Maybe Identifier) [GenItem]
| GenCase Expr [GenCase] (Maybe GenItem)
| GenFor (Identifier, Expr) Expr (Identifier, AsgnOp, Expr) (Maybe Identifier) [GenItem]
| GenIf Expr GenItem GenItem
| GenNull
| GenModuleItem ModuleItem
deriving Eq
instance Show GenItem where
showList i _ = unlines' $ map show i
show (GenBlock Nothing i) = printf "begin\n%s\nend" (indent $ unlines' $ map show i)
show (GenBlock (Just x) i) = printf "begin : %s\n%s\nend" x (indent $ unlines' $ map show i)
show (GenCase e c Nothing ) = printf "case (%s)\n%s\nendcase" (show e) (indent $ unlines' $ map showCase c)
show (GenCase e c (Just d)) = printf "case (%s)\n%s\n\tdefault:\n%s\nendcase" (show e) (indent $ unlines' $ map showCase c) (indent $ indent $ show d)
show (GenIf e a GenNull) = printf "if (%s) %s" (show e) (show a)
show (GenIf e a b ) = printf "if (%s) %s\nelse %s" (show e) (show a) (show b)
show (GenFor (x1, e1) c (x2, o2, e2) mx is) = printf "for (%s = %s; %s; %s %s %s) %s" x1 (show e1) (show c) x2 (show o2) (show e2) (show $ GenBlock mx is)
show GenNull = ";"
show (GenModuleItem item) = show item
data Lifetime
= Static
| Automatic
deriving (Eq, Ord)
instance Show Lifetime where
show Static = "static"
show Automatic = "automatic"
showLifetime :: Maybe Lifetime -> String
showLifetime Nothing = ""
showLifetime (Just l) = show l ++ " "
-- basic expression simplfication utility to help us generate nicer code in the
-- common case of ranges like `[FOO-1:0]`
simplify :: Expr -> Expr
simplify (BinOp op e1 e2) =
case (op, e1', e2') of
(Add, Number "0", e) -> e
(Add, e, Number "0") -> e
(Sub, e, Number "0") -> e
(Add, BinOp Sub e (Number "1"), Number "1") -> e
(Add, e, BinOp Sub (Number "0") (Number "1")) -> BinOp Sub e (Number "1")
(_ , Number a, Number b) ->
case (op, readMaybe a :: Maybe Int, readMaybe b :: Maybe Int) of
(Add, Just x, Just y) -> Number $ show (x + y)
(Sub, Just x, Just y) -> Number $ show (x - y)
(Mul, Just x, Just y) -> Number $ show (x * y)
_ -> BinOp op e1' e2'
_ -> BinOp op e1' e2'
where
e1' = simplify e1
e2' = simplify e2
simplify other = other
rangeSize :: Range -> Expr
rangeSize (s, e) =
simplify $ BinOp Add (BinOp Sub s e) (Number "1")
{- sv2v
- Author: Zachary Snow <zach@zachjs.com>
- Initial Verilog AST Author: Tom Hawkins <tomahawkins@gmail.com>
-
- SystemVerilog top-level items (descriptions, package items)
-}
module Language.SystemVerilog.AST.Description
( Description (..)
, PackageItem (..)
, PartKW (..)
, Lifetime (..)
) where
import Data.List (intercalate)
import Text.Printf (printf)
import Language.SystemVerilog.AST.ShowHelp
import Language.SystemVerilog.AST.Decl (Decl)
import Language.SystemVerilog.AST.Stmt (Stmt)
import Language.SystemVerilog.AST.Type (Type, Identifier)
import {-# SOURCE #-} Language.SystemVerilog.AST.ModuleItem (ModuleItem)
data Description
= Part Bool PartKW (Maybe Lifetime) Identifier [Identifier] [ModuleItem]
| PackageItem PackageItem
| Directive String -- currently unused
deriving Eq
instance Show Description where
showList descriptions _ = intercalate "\n" $ map show descriptions
show (Part True kw lifetime name _ items) =
printf "extern %s %s%s %s;"
(show kw) (showLifetime lifetime) name (indentedParenList itemStrs)
where itemStrs = map (init . show) items
show (Part False kw lifetime name ports items) =
printf "%s %s%s%s;\n%s\nend%s"
(show kw) (showLifetime lifetime) name portsStr bodyStr (show kw)
where
portsStr = if null ports
then ""
else " " ++ indentedParenList ports
bodyStr = indent $ unlines' $ map show items
show (PackageItem i) = show i
show (Directive str) = str
data PackageItem
= Typedef Type Identifier
| Function (Maybe Lifetime) Type Identifier [Decl] [Stmt]
| Task (Maybe Lifetime) Identifier [Decl] [Stmt]
| Comment String
deriving Eq
instance Show PackageItem where
show (Typedef t x) = printf "typedef %s %s;" (show t) x
show (Function ml t x i b) =
printf "function %s%s%s;\n%s\n%s\nendfunction"
(showLifetime ml) (showPad t) x (indent $ show i)
(indent $ unlines' $ map show b)
show (Task ml x i b) =
printf "task %s%s;\n%s\n%s\nendtask"
(showLifetime ml) x (indent $ show i)
(indent $ unlines' $ map show b)
show (Comment c) =
if elem '\n' c
then "// " ++ show c
else "// " ++ c
data PartKW
= Module
| Interface
deriving Eq
instance Show PartKW where
show Module = "module"
show Interface = "interface"
data Lifetime
= Static
| Automatic
deriving (Eq, Ord)
instance Show Lifetime where
show Static = "static"
show Automatic = "automatic"
showLifetime :: Maybe Lifetime -> String
showLifetime Nothing = ""
showLifetime (Just l) = show l ++ " "
......@@ -8,13 +8,16 @@
module Language.SystemVerilog.AST.Expr
( Expr (..)
, Range
, Args (..)
, showAssignment
, showRanges
, Args (..)
, simplify
, rangeSize
) where
import Data.List (intercalate)
import Text.Printf (printf)
import Text.Read (readMaybe)
import Language.SystemVerilog.AST.Op
import Language.SystemVerilog.AST.ShowHelp
......@@ -83,3 +86,29 @@ showRanges l = " " ++ (concatMap showRange l)
showRange :: Range -> String
showRange (h, l) = printf "[%s:%s]" (show h) (show l)
-- basic expression simplfication utility to help us generate nicer code in the
-- common case of ranges like `[FOO-1:0]`
simplify :: Expr -> Expr
simplify (BinOp op e1 e2) =
case (op, e1', e2') of
(Add, Number "0", e) -> e
(Add, e, Number "0") -> e
(Sub, e, Number "0") -> e
(Add, BinOp Sub e (Number "1"), Number "1") -> e
(Add, e, BinOp Sub (Number "0") (Number "1")) -> BinOp Sub e (Number "1")
(_ , Number a, Number b) ->
case (op, readMaybe a :: Maybe Int, readMaybe b :: Maybe Int) of
(Add, Just x, Just y) -> Number $ show (x + y)
(Sub, Just x, Just y) -> Number $ show (x - y)
(Mul, Just x, Just y) -> Number $ show (x * y)
_ -> BinOp op e1' e2'
_ -> BinOp op e1' e2'
where
e1' = simplify e1
e2' = simplify e2
simplify other = other
rangeSize :: Range -> Expr
rangeSize (s, e) =
simplify $ BinOp Add (BinOp Sub s e) (Number "1")
{- sv2v
- Author: Zachary Snow <zach@zachjs.com>
- Initial Verilog AST Author: Tom Hawkins <tomahawkins@gmail.com>
-
- SystemVerilog `generate` items
-}
module Language.SystemVerilog.AST.GenItem
( GenItem (..)
, GenCase
) where
import Text.Printf (printf)
import Language.SystemVerilog.AST.ShowHelp
import Language.SystemVerilog.AST.Expr (Expr)
import Language.SystemVerilog.AST.Op (AsgnOp)
import Language.SystemVerilog.AST.Type (Identifier)
import {-# SOURCE #-} Language.SystemVerilog.AST.ModuleItem (ModuleItem)
data GenItem
= GenBlock (Maybe Identifier) [GenItem]
| GenCase Expr [GenCase] (Maybe GenItem)
| GenFor (Identifier, Expr) Expr (Identifier, AsgnOp, Expr) (Maybe Identifier) [GenItem]
| GenIf Expr GenItem GenItem
| GenNull
| GenModuleItem ModuleItem
deriving Eq
instance Show GenItem where
showList i _ = unlines' $ map show i
show (GenBlock mx i) =
printf "begin%s\n%s\nend"
(maybe "" (" : " ++) mx)
(indent $ unlines' $ map show i)
show (GenCase e c md) =
printf "case (%s)\n%s%s\nendcase" (show e)
(indent $ unlines' $ map showCase c)
(maybe "" (indent . indent . show) md)
show (GenIf e a GenNull) = printf "if (%s) %s" (show e) (show a)
show (GenIf e a b ) = printf "if (%s) %s\nelse %s" (show e) (show a) (show b)
show (GenFor (x1, e1) c (x2, o2, e2) mx is) =
printf "for (%s = %s; %s; %s %s %s) %s"
x1 (show e1)
(show c)
x2 (show o2) (show e2)
(show $ GenBlock mx is)
show (GenNull) = ";"
show (GenModuleItem item) = show item
type GenCase = ([Expr], GenItem)
{- sv2v
- Author: Zachary Snow <zach@zachjs.com>
- Initial Verilog AST Author: Tom Hawkins <tomahawkins@gmail.com>
-
- SystemVerilog `module` items
-}
module Language.SystemVerilog.AST.ModuleItem
( ModuleItem (..)
, PortBinding
, ModportDecl
, AlwaysKW (..)
, NInputGateKW (..)
, NOutputGateKW (..)
) where
import Data.List (intercalate)
import Data.Maybe (maybe, fromJust, isJust)
import Text.Printf (printf)
import Language.SystemVerilog.AST.ShowHelp
import Language.SystemVerilog.AST.Attr (Attr)
import Language.SystemVerilog.AST.Decl (Decl, Direction)
import Language.SystemVerilog.AST.Description (PackageItem)
import Language.SystemVerilog.AST.Expr (Expr(Ident), Range, showRanges)
import Language.SystemVerilog.AST.GenItem (GenItem)
import Language.SystemVerilog.AST.LHS (LHS)
import Language.SystemVerilog.AST.Stmt (Stmt, AssertionItem)
import Language.SystemVerilog.AST.Type (Identifier)
data ModuleItem
= MIAttr Attr ModuleItem
| MIDecl Decl
| AlwaysC AlwaysKW Stmt
| Assign (Maybe Expr) LHS Expr
| Defparam LHS Expr
| Instance Identifier [PortBinding] Identifier (Maybe Range) [PortBinding]
| Genvar Identifier
| Generate [GenItem]
| Modport Identifier [ModportDecl]
| Initial Stmt
| MIPackageItem PackageItem
| NInputGate NInputGateKW (Maybe Identifier) LHS [Expr]
| NOutputGate NOutputGateKW (Maybe Identifier) [LHS] Expr
| AssertionItem AssertionItem
deriving Eq
instance Show ModuleItem where
show (MIDecl nest) = show nest
show (MIPackageItem i) = show i
show (MIAttr attr mi ) = printf "%s %s" (show attr) (show mi)
show (AlwaysC k b) = printf "%s %s" (show k) (show b)
show (Defparam a b) = printf "defparam %s = %s;" (show a) (show b)
show (Genvar x ) = printf "genvar %s;" x
show (Generate b ) = printf "generate\n%s\nendgenerate" (indent $ unlines' $ map show b)
show (Modport x l) = printf "modport %s(\n%s\n);" x (indent $ intercalate ",\n" $ map showModportDecl l)
show (Initial s ) = printf "initial %s" (show s)
show (NInputGate kw x lhs exprs) = printf "%s%s (%s, %s);" (show kw) (maybe "" (" " ++) x) (show lhs) (commas $ map show exprs)
show (NOutputGate kw x lhss expr) = printf "%s%s (%s, %s);" (show kw) (maybe "" (" " ++) x) (commas $ map show lhss) (show expr)
show (Assign d a b) =
printf "assign %s%s = %s;" delayStr (show a) (show b)
where delayStr = maybe "" (\e -> "#(" ++ show e ++ ") ") d
show (AssertionItem (mx, a)) =
if mx == Nothing
then show a
else printf "%s : %s" (fromJust mx) (show a)
show (Instance m params i r ports) =
if null params
then printf "%s %s%s%s;" m i rStr (showPorts ports)
else printf "%s #%s %s%s%s;" m (showPorts params) i rStr (showPorts ports)
where rStr = maybe "" (\a -> showRanges [a] ++ " ") r
showPorts :: [PortBinding] -> String
showPorts ports = indentedParenList $ map showPort ports
showPort :: PortBinding -> String
showPort ("*", Nothing) = ".*"
showPort (i, arg) =
if i == ""
then show (fromJust arg)
else printf ".%s(%s)" i (if isJust arg then show $ fromJust arg else "")
showModportDecl :: ModportDecl -> String
showModportDecl (dir, ident, me) =
if me == Just (Ident ident)
then printf "%s %s" (show dir) ident
else printf "%s .%s(%s)" (show dir) ident (maybe "" show me)
type PortBinding = (Identifier, Maybe Expr)
type ModportDecl = (Direction, Identifier, Maybe Expr)
data AlwaysKW
= Always
| AlwaysComb
| AlwaysFF
| AlwaysLatch
deriving Eq
instance Show AlwaysKW where
show Always = "always"
show AlwaysComb = "always_comb"
show AlwaysFF = "always_ff"
show AlwaysLatch = "always_latch"
data NInputGateKW
= GateAnd
| GateNand
| GateOr
| GateNor
| GateXor
| GateXnor
deriving Eq
instance Show NInputGateKW where
show GateAnd = "and"
show GateNand = "nand"
show GateOr = "or"
show GateNor = "nor"
show GateXor = "xor"
show GateXnor = "xnor"
data NOutputGateKW
= GateBuf
| GateNot
deriving Eq
instance Show NOutputGateKW where
show GateBuf = "buf"
show GateNot = "not"
module Language.SystemVerilog.AST.ModuleItem
( ModuleItem
) where
data ModuleItem
instance Eq ModuleItem
instance Show ModuleItem
......@@ -2,15 +2,15 @@
- Author: Zachary Snow <zach@zachjs.com>
-}
module Language.SystemVerilog.Parser
( parseFile
) where
( parseFile
) where
import Language.SystemVerilog.AST
import Language.SystemVerilog.Parser.Lex
import Language.SystemVerilog.Parser.Parse
import Language.SystemVerilog.AST (AST)
import Language.SystemVerilog.Parser.Lex (lexFile)
import Language.SystemVerilog.Parser.Parse (parse)
-- parses a file given a table of predefined macros and the file name
-- parses a file given include search paths, a table of predefined macros, and
-- the file path
parseFile :: [String] -> [(String, String)] -> FilePath -> IO AST
parseFile includePaths env file =
lexFile includePaths env file >>=
return . descriptions
parseFile includePaths defines path =
lexFile includePaths defines path >>= return . parse
......@@ -5,19 +5,20 @@
- This file has been *heavily* modified and extended from the original version
- in tomahawkins/verilog. I have added support for numerous SystemVerilog
- constructs, which has necessitated rewriting nearly all of this.
-
- This file is the only remaining one that still uses 2-space indentation. I've
- decided to leave it this way because I think it is too important to preserve
- the ability to easily blame/diff this file.
-}
{
module Language.SystemVerilog.Parser.Parse (descriptions) where
import Data.List
import Data.Maybe
module Language.SystemVerilog.Parser.Parse (parse) where
import Language.SystemVerilog.AST
import Language.SystemVerilog.Parser.ParseDecl
import Language.SystemVerilog.Parser.Tokens
}
%name descriptions
%name parse
%tokentype { Token }
%error { parseError }
......
......@@ -36,8 +36,11 @@ executable sv2v
Language.SystemVerilog.AST
Language.SystemVerilog.AST.Attr
Language.SystemVerilog.AST.Decl
Language.SystemVerilog.AST.Description
Language.SystemVerilog.AST.Expr
Language.SystemVerilog.AST.GenItem
Language.SystemVerilog.AST.LHS
Language.SystemVerilog.AST.ModuleItem
Language.SystemVerilog.AST.Op
Language.SystemVerilog.AST.ShowHelp
Language.SystemVerilog.AST.Stmt
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment