From 90bc30d4bed9bc0e164fc7ea9ac1a4a89dd89014 Mon Sep 17 00:00:00 2001 From: Zachary Snow Date: Mon, 5 Aug 2019 22:00:04 -0400 Subject: [PATCH] add --oneunit, which treats all input files as being part of one compilation unit --- src/Job.hs | 2 ++ src/Language/SystemVerilog/Parser.hs | 27 ++++++++++++++++++++----- src/Language/SystemVerilog/Parser/Lex.x | 17 ++++++++++------ src/sv2v.hs | 17 ++++++++++------ test/resolve/module.sv | 1 + test/resolve/package.svh | 1 + test/resolve/reference.v | 2 ++ test/resolve/run.sh | 2 +- 8 files changed, 51 insertions(+), 18 deletions(-) diff --git a/src/Job.hs b/src/Job.hs index f64bedd..46ecff8 100644 --- a/src/Job.hs +++ b/src/Job.hs @@ -20,6 +20,7 @@ data Job = Job , files :: [FilePath] , incdir :: [FilePath] , define :: [String] + , oneunit :: Bool } deriving (Show, Typeable, Data) defaultJob :: Job @@ -29,6 +30,7 @@ defaultJob = Job , files = def &= args &= typ "FILES" , incdir = def &= typDir &= help "add directory to include search path" , define = def &= typ "NAME[=VALUE]" &= help "define a macro for preprocessing" + , oneunit = False &= help "compile all files in one compilation unit" } &= program "sv2v" &= summary "sv2v v0.0.1, (C) 2019 Zachary Snow, 2011-2015 Tom Hawkins" diff --git a/src/Language/SystemVerilog/Parser.hs b/src/Language/SystemVerilog/Parser.hs index 8dafabc..6f0e49e 100644 --- a/src/Language/SystemVerilog/Parser.hs +++ b/src/Language/SystemVerilog/Parser.hs @@ -2,15 +2,32 @@ - Author: Zachary Snow -} module Language.SystemVerilog.Parser - ( parseFile + ( parseFiles ) where +import qualified Data.Map.Strict as Map import Language.SystemVerilog.AST (AST) -import Language.SystemVerilog.Parser.Lex (lexFile) +import Language.SystemVerilog.Parser.Lex (lexFile, Env) 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 -- the file path -parseFile :: [String] -> [(String, String)] -> FilePath -> IO AST -parseFile includePaths defines path = - lexFile includePaths defines path >>= return . parse +parseFile' :: [String] -> Env -> FilePath -> IO (AST, Env) +parseFile' includePaths env path = do + (tokens, env') <- lexFile includePaths env path + let ast = parse tokens + return (ast, env') diff --git a/src/Language/SystemVerilog/Parser/Lex.x b/src/Language/SystemVerilog/Parser/Lex.x index c09272c..ef0c03a 100644 --- a/src/Language/SystemVerilog/Parser/Lex.x +++ b/src/Language/SystemVerilog/Parser/Lex.x @@ -20,7 +20,10 @@ -- 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) -module Language.SystemVerilog.Parser.Lex (lexFile) where +module Language.SystemVerilog.Parser.Lex + ( lexFile + , Env + ) where import System.FilePath (dropFileName) import System.Directory (findFile) @@ -322,11 +325,14 @@ data Cond | NeverTrue deriving (Eq, Show) +-- map from macro to definition, plus arguments +type Env = Map.Map String (String, [(String, Maybe String)]) + -- our custom lexer state data AlexUserState = LS { lsToks :: [Token] -- tokens read so far, *in reverse order* for efficiency , 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 , lsIncludePaths :: [FilePath] -- folders to search for includes } deriving (Eq, Show) @@ -338,7 +344,7 @@ alexInitUserState :: AlexUserState alexInitUserState = LS [] "" Map.empty [] [] -- public-facing lexer entrypoint -lexFile :: [String] -> [(String, String)] -> FilePath -> IO [Token] +lexFile :: [String] -> Env -> FilePath -> IO ([Token], Env) lexFile includePaths env path = do str <- readFile path let result = runAlex str $ setEnv >> alexMonadScan >> get @@ -346,16 +352,15 @@ lexFile includePaths env path = do Left msg -> error $ "Lexical Error: " ++ msg Right finalState -> if null $ lsCondStack finalState - then reverse $ lsToks finalState + then (reverse $ lsToks finalState, lsEnv finalState) else error $ "unfinished conditional directives: " ++ (show $ length $ lsCondStack finalState) where - initialEnv = Map.map (\a -> (a, [])) $ Map.fromList env setEnv = do -- standardize the file path format path' <- includeSearch path modify $ \s -> s - { lsEnv = initialEnv + { lsEnv = env , lsIncludePaths = includePaths , lsCurrFile = path' } diff --git a/src/sv2v.hs b/src/sv2v.hs index 97e2995..7d0a51b 100644 --- a/src/sv2v.hs +++ b/src/sv2v.hs @@ -8,9 +8,9 @@ import System.IO import System.Exit import Data.List (elemIndex) -import Job (readJob, files, exclude, incdir, define) +import Job (readJob, files, exclude, incdir, define, oneunit) import Convert (convert) -import Language.SystemVerilog.Parser +import Language.SystemVerilog.Parser (parseFiles) splitDefine :: String -> (String, String) splitDefine str = @@ -21,12 +21,17 @@ splitDefine str = main :: IO () main = do job <- readJob - -- parse the input file + -- parse the input files let includePaths = incdir job let defines = map splitDefine $ define job - asts <- mapM (parseFile includePaths defines) (files job) - -- convert the file + let singleton = \x -> [x] + 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 - -- print the converted file out + -- print the converted files out hPrint stdout $ concat asts' exitSuccess diff --git a/test/resolve/module.sv b/test/resolve/module.sv index b644026..2f3cb44 100644 --- a/test/resolve/module.sv +++ b/test/resolve/module.sv @@ -5,5 +5,6 @@ module top assign o = i + 1'b1; initial begin $display(width); + $display(`FANCY_SEEING_YOU); end endmodule diff --git a/test/resolve/package.svh b/test/resolve/package.svh index 8c4e7ed..478b77c 100644 --- a/test/resolve/package.svh +++ b/test/resolve/package.svh @@ -1,3 +1,4 @@ +`define FANCY_SEEING_YOU 1337 package pkg; function automatic integer width_calc; input integer a; diff --git a/test/resolve/reference.v b/test/resolve/reference.v index 70dca57..b8490a0 100644 --- a/test/resolve/reference.v +++ b/test/resolve/reference.v @@ -1,3 +1,4 @@ +`define FANCY_SEEING_YOU 1337 module top; parameter width = 5; input [width-1:0] i; @@ -5,5 +6,6 @@ module top; assign o = i + 1'b1; initial begin $display(width); + $display(`FANCY_SEEING_YOU); end endmodule diff --git a/test/resolve/run.sh b/test/resolve/run.sh index 87606b8..e5ba118 100755 --- a/test/resolve/run.sh +++ b/test/resolve/run.sh @@ -2,7 +2,7 @@ test_main() { 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" }