mirror of https://github.com/zachjs/sv2v.git
add --oneunit, which treats all input files as being part of one compilation unit
This commit is contained in:
parent
376f0d3f2a
commit
90bc30d4be
|
|
@ -20,6 +20,7 @@ data Job = Job
|
||||||
, files :: [FilePath]
|
, files :: [FilePath]
|
||||||
, incdir :: [FilePath]
|
, incdir :: [FilePath]
|
||||||
, define :: [String]
|
, define :: [String]
|
||||||
|
, oneunit :: Bool
|
||||||
} deriving (Show, Typeable, Data)
|
} deriving (Show, Typeable, Data)
|
||||||
|
|
||||||
defaultJob :: Job
|
defaultJob :: Job
|
||||||
|
|
@ -29,6 +30,7 @@ defaultJob = Job
|
||||||
, files = def &= args &= typ "FILES"
|
, files = def &= args &= typ "FILES"
|
||||||
, incdir = def &= typDir &= help "add directory to include search path"
|
, incdir = def &= typDir &= help "add directory to include search path"
|
||||||
, define = def &= typ "NAME[=VALUE]" &= help "define a macro for preprocessing"
|
, define = def &= typ "NAME[=VALUE]" &= help "define a macro for preprocessing"
|
||||||
|
, oneunit = False &= help "compile all files in one compilation unit"
|
||||||
}
|
}
|
||||||
&= program "sv2v"
|
&= program "sv2v"
|
||||||
&= summary "sv2v v0.0.1, (C) 2019 Zachary Snow, 2011-2015 Tom Hawkins"
|
&= summary "sv2v v0.0.1, (C) 2019 Zachary Snow, 2011-2015 Tom Hawkins"
|
||||||
|
|
|
||||||
|
|
@ -2,15 +2,32 @@
|
||||||
- Author: Zachary Snow <zach@zachjs.com>
|
- Author: Zachary Snow <zach@zachjs.com>
|
||||||
-}
|
-}
|
||||||
module Language.SystemVerilog.Parser
|
module Language.SystemVerilog.Parser
|
||||||
( parseFile
|
( parseFiles
|
||||||
) where
|
) where
|
||||||
|
|
||||||
|
import qualified Data.Map.Strict as Map
|
||||||
import Language.SystemVerilog.AST (AST)
|
import Language.SystemVerilog.AST (AST)
|
||||||
import Language.SystemVerilog.Parser.Lex (lexFile)
|
import Language.SystemVerilog.Parser.Lex (lexFile, Env)
|
||||||
import Language.SystemVerilog.Parser.Parse (parse)
|
import Language.SystemVerilog.Parser.Parse (parse)
|
||||||
|
|
||||||
|
-- parses a compilation unit given include search paths and predefined macros
|
||||||
|
parseFiles :: [FilePath] -> [(String, String)] -> [FilePath] -> IO [AST]
|
||||||
|
parseFiles includePaths defines paths = do
|
||||||
|
let env = Map.map (\a -> (a, [])) $ Map.fromList defines
|
||||||
|
parseFiles' includePaths env paths
|
||||||
|
|
||||||
|
-- parses a compilation unit given include search paths and predefined macros
|
||||||
|
parseFiles' :: [FilePath] -> Env -> [FilePath] -> IO [AST]
|
||||||
|
parseFiles' _ _ [] = return []
|
||||||
|
parseFiles' includePaths env (path : paths) = do
|
||||||
|
(ast, env') <- parseFile' includePaths env path
|
||||||
|
asts <- parseFiles' includePaths env' paths
|
||||||
|
return $ ast : asts
|
||||||
|
|
||||||
-- parses a file given include search paths, a table of predefined macros, and
|
-- parses a file given include search paths, a table of predefined macros, and
|
||||||
-- the file path
|
-- the file path
|
||||||
parseFile :: [String] -> [(String, String)] -> FilePath -> IO AST
|
parseFile' :: [String] -> Env -> FilePath -> IO (AST, Env)
|
||||||
parseFile includePaths defines path =
|
parseFile' includePaths env path = do
|
||||||
lexFile includePaths defines path >>= return . parse
|
(tokens, env') <- lexFile includePaths env path
|
||||||
|
let ast = parse tokens
|
||||||
|
return (ast, env')
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,10 @@
|
||||||
-- been fixed on their development branch, so this can be removed once they roll
|
-- been fixed on their development branch, so this can be removed once they roll
|
||||||
-- a new release. (no new release as of 3/29/2018)
|
-- a new release. (no new release as of 3/29/2018)
|
||||||
|
|
||||||
module Language.SystemVerilog.Parser.Lex (lexFile) where
|
module Language.SystemVerilog.Parser.Lex
|
||||||
|
( lexFile
|
||||||
|
, Env
|
||||||
|
) where
|
||||||
|
|
||||||
import System.FilePath (dropFileName)
|
import System.FilePath (dropFileName)
|
||||||
import System.Directory (findFile)
|
import System.Directory (findFile)
|
||||||
|
|
@ -322,11 +325,14 @@ data Cond
|
||||||
| NeverTrue
|
| NeverTrue
|
||||||
deriving (Eq, Show)
|
deriving (Eq, Show)
|
||||||
|
|
||||||
|
-- map from macro to definition, plus arguments
|
||||||
|
type Env = Map.Map String (String, [(String, Maybe String)])
|
||||||
|
|
||||||
-- our custom lexer state
|
-- our custom lexer state
|
||||||
data AlexUserState = LS
|
data AlexUserState = LS
|
||||||
{ lsToks :: [Token] -- tokens read so far, *in reverse order* for efficiency
|
{ lsToks :: [Token] -- tokens read so far, *in reverse order* for efficiency
|
||||||
, lsCurrFile :: FilePath -- currently active filename
|
, lsCurrFile :: FilePath -- currently active filename
|
||||||
, lsEnv :: Map.Map String (String, [(String, Maybe String)]) -- active macro definitions
|
, lsEnv :: Env -- active macro definitions
|
||||||
, lsCondStack :: [Cond] -- if-else cascade state
|
, lsCondStack :: [Cond] -- if-else cascade state
|
||||||
, lsIncludePaths :: [FilePath] -- folders to search for includes
|
, lsIncludePaths :: [FilePath] -- folders to search for includes
|
||||||
} deriving (Eq, Show)
|
} deriving (Eq, Show)
|
||||||
|
|
@ -338,7 +344,7 @@ alexInitUserState :: AlexUserState
|
||||||
alexInitUserState = LS [] "" Map.empty [] []
|
alexInitUserState = LS [] "" Map.empty [] []
|
||||||
|
|
||||||
-- public-facing lexer entrypoint
|
-- public-facing lexer entrypoint
|
||||||
lexFile :: [String] -> [(String, String)] -> FilePath -> IO [Token]
|
lexFile :: [String] -> Env -> FilePath -> IO ([Token], Env)
|
||||||
lexFile includePaths env path = do
|
lexFile includePaths env path = do
|
||||||
str <- readFile path
|
str <- readFile path
|
||||||
let result = runAlex str $ setEnv >> alexMonadScan >> get
|
let result = runAlex str $ setEnv >> alexMonadScan >> get
|
||||||
|
|
@ -346,16 +352,15 @@ lexFile includePaths env path = do
|
||||||
Left msg -> error $ "Lexical Error: " ++ msg
|
Left msg -> error $ "Lexical Error: " ++ msg
|
||||||
Right finalState ->
|
Right finalState ->
|
||||||
if null $ lsCondStack finalState
|
if null $ lsCondStack finalState
|
||||||
then reverse $ lsToks finalState
|
then (reverse $ lsToks finalState, lsEnv finalState)
|
||||||
else error $ "unfinished conditional directives: " ++
|
else error $ "unfinished conditional directives: " ++
|
||||||
(show $ length $ lsCondStack finalState)
|
(show $ length $ lsCondStack finalState)
|
||||||
where
|
where
|
||||||
initialEnv = Map.map (\a -> (a, [])) $ Map.fromList env
|
|
||||||
setEnv = do
|
setEnv = do
|
||||||
-- standardize the file path format
|
-- standardize the file path format
|
||||||
path' <- includeSearch path
|
path' <- includeSearch path
|
||||||
modify $ \s -> s
|
modify $ \s -> s
|
||||||
{ lsEnv = initialEnv
|
{ lsEnv = env
|
||||||
, lsIncludePaths = includePaths
|
, lsIncludePaths = includePaths
|
||||||
, lsCurrFile = path'
|
, lsCurrFile = path'
|
||||||
}
|
}
|
||||||
|
|
|
||||||
17
src/sv2v.hs
17
src/sv2v.hs
|
|
@ -8,9 +8,9 @@ import System.IO
|
||||||
import System.Exit
|
import System.Exit
|
||||||
|
|
||||||
import Data.List (elemIndex)
|
import Data.List (elemIndex)
|
||||||
import Job (readJob, files, exclude, incdir, define)
|
import Job (readJob, files, exclude, incdir, define, oneunit)
|
||||||
import Convert (convert)
|
import Convert (convert)
|
||||||
import Language.SystemVerilog.Parser
|
import Language.SystemVerilog.Parser (parseFiles)
|
||||||
|
|
||||||
splitDefine :: String -> (String, String)
|
splitDefine :: String -> (String, String)
|
||||||
splitDefine str =
|
splitDefine str =
|
||||||
|
|
@ -21,12 +21,17 @@ splitDefine str =
|
||||||
main :: IO ()
|
main :: IO ()
|
||||||
main = do
|
main = do
|
||||||
job <- readJob
|
job <- readJob
|
||||||
-- parse the input file
|
-- parse the input files
|
||||||
let includePaths = incdir job
|
let includePaths = incdir job
|
||||||
let defines = map splitDefine $ define job
|
let defines = map splitDefine $ define job
|
||||||
asts <- mapM (parseFile includePaths defines) (files job)
|
let singleton = \x -> [x]
|
||||||
-- convert the file
|
let toFileLists = if oneunit job then singleton else map singleton
|
||||||
|
astLists <- mapM
|
||||||
|
(parseFiles includePaths defines)
|
||||||
|
(toFileLists $ files job)
|
||||||
|
let asts = concat astLists
|
||||||
|
-- convert the files
|
||||||
let asts' = convert (exclude job) asts
|
let asts' = convert (exclude job) asts
|
||||||
-- print the converted file out
|
-- print the converted files out
|
||||||
hPrint stdout $ concat asts'
|
hPrint stdout $ concat asts'
|
||||||
exitSuccess
|
exitSuccess
|
||||||
|
|
|
||||||
|
|
@ -5,5 +5,6 @@ module top
|
||||||
assign o = i + 1'b1;
|
assign o = i + 1'b1;
|
||||||
initial begin
|
initial begin
|
||||||
$display(width);
|
$display(width);
|
||||||
|
$display(`FANCY_SEEING_YOU);
|
||||||
end
|
end
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
`define FANCY_SEEING_YOU 1337
|
||||||
package pkg;
|
package pkg;
|
||||||
function automatic integer width_calc;
|
function automatic integer width_calc;
|
||||||
input integer a;
|
input integer a;
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
`define FANCY_SEEING_YOU 1337
|
||||||
module top;
|
module top;
|
||||||
parameter width = 5;
|
parameter width = 5;
|
||||||
input [width-1:0] i;
|
input [width-1:0] i;
|
||||||
|
|
@ -5,5 +6,6 @@ module top;
|
||||||
assign o = i + 1'b1;
|
assign o = i + 1'b1;
|
||||||
initial begin
|
initial begin
|
||||||
$display(width);
|
$display(width);
|
||||||
|
$display(`FANCY_SEEING_YOU);
|
||||||
end
|
end
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
test_main() {
|
test_main() {
|
||||||
cv="$SHUNIT_TMPDIR/conv.v"
|
cv="$SHUNIT_TMPDIR/conv.v"
|
||||||
convert "$cv" package.svh module.sv
|
convert "$cv" --oneunit package.svh module.sv
|
||||||
simulateAndCompare "reference.v" "$cv" "$SCRIPT_DIR/empty.v"
|
simulateAndCompare "reference.v" "$cv" "$SCRIPT_DIR/empty.v"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue