sv2v.hs 4.1 KB
Newer Older
1
{- sv2v
Zachary Snow committed
2 3 4 5
 - Author: Zachary Snow <zach@zachjs.com>
 -
 - conversion entry point
 -}
6

Zachary Snow committed
7 8
import System.IO (hPrint, hPutStrLn, stderr, stdout)
import System.Exit (exitFailure, exitSuccess)
9
import System.FilePath (combine, splitExtension)
Zachary Snow committed
10

11
import Control.Monad (when, zipWithM_)
12
import Control.Monad.Except (runExceptT)
13
import Data.List (nub)
14

15
import Convert (convert)
Zachary Snow committed
16
import Job (readJob, Job(..), Write(..))
17
import Language.SystemVerilog.AST
18
import Language.SystemVerilog.Parser (parseFiles, Config(..))
19

20 21 22 23
isComment :: Description -> Bool
isComment (PackageItem (Decl CommentDecl{})) = True
isComment _ = False

24 25 26 27 28 29 30 31 32 33 34
droppedKind :: Description -> Identifier
droppedKind description =
    case description of
        Part _ _ Interface _ _ _ _ -> "interface"
        Package{} -> "package"
        Class{}   -> "class"
        PackageItem Function{}     -> "function"
        PackageItem Task    {}     -> "task"
        PackageItem (Decl Param{}) -> "localparam"
        _ -> ""

35
emptyWarnings :: AST -> AST -> IO ()
36
emptyWarnings before after =
37
    if all isComment before || not (all isComment after) || null kinds then
38
        return ()
39 40 41 42 43
    else if elem "interface" kinds then
        hPutStrLn stderr $ "Warning: Source includes an interface but the"
            ++ " output is empty because there are no modules without any"
            ++ " interface ports. Please convert interfaces alongside the"
            ++ " modules that instantiate them."
44
    else
45 46 47 48 49 50
        hPutStrLn stderr $ "Warning: Source includes a " ++ kind ++ " but no"
            ++ " modules. Such elements are elaborated into the modules that"
            ++ " use them. Please convert all sources in one invocation."
    where
        kinds = nub $ filter (not . null) $ map droppedKind before
        kind = head kinds
51

Zachary Snow committed
52 53 54 55 56 57 58 59 60
rewritePath :: FilePath -> IO FilePath
rewritePath path = do
    when (end /= ext) $ do
        hPutStrLn stderr $ "Refusing to write adjacent to " ++ show path
            ++ " because that path does not end in " ++ show ext
        exitFailure
    return $ base ++ ".v"
    where
        ext = ".sv"
61 62 63 64 65 66 67 68 69 70 71 72
        (base, end) = splitExtension path

splitModules :: FilePath -> AST -> [(FilePath, String)]
splitModules dir (PackageItem (Decl CommentDecl{}) : ast) =
    splitModules dir ast
splitModules dir (description : ast) =
    (path, output) : splitModules dir ast
    where
        Part _ _ Module _ name _ _ = description
        path = combine dir $ name ++ ".v"
        output = show description ++ "\n"
splitModules _ [] = []
Zachary Snow committed
73 74

writeOutput :: Write -> [FilePath] -> [AST] -> IO ()
75 76
writeOutput _ [] [] =
    hPutStrLn stderr "Warning: No input files specified (try `sv2v --help`)"
Zachary Snow committed
77 78
writeOutput Stdout _ asts =
    hPrint stdout $ concat asts
79
writeOutput (File f) _ asts =
80
    writeFile f $ show $ concat asts
Zachary Snow committed
81 82 83 84
writeOutput Adjacent inPaths asts = do
    outPaths <- mapM rewritePath inPaths
    let results = map (++ "\n") $ map show asts
    zipWithM_ writeFile outPaths results
85 86 87
writeOutput (Directory d) _ asts = do
    let (outPaths, outputs) = unzip $ splitModules d $ concat asts
    zipWithM_ writeFile outPaths outputs
Zachary Snow committed
88

89 90
main :: IO ()
main = do
91
    job <- readJob
92
    -- parse the input files
93
    let config = Config
94
            { cfDefines          = define job
95
            , cfIncludePaths     = incdir job
96
            , cfLibraryPaths     = libdir job
97 98
            , cfSiloed           = siloed job
            , cfSkipPreprocessor = skipPreprocessor job
99
            , cfOversizedNumbers = oversizedNumbers job
100 101
            }
    result <- runExceptT $ parseFiles config (files job)
102 103
    case result of
        Left msg -> do
Zachary Snow committed
104
            hPutStrLn stderr msg
105
            exitFailure
106 107
        Right inputs -> do
            let (inPaths, asts) = unzip inputs
108
            -- convert the files if requested
109 110 111 112 113 114
            let converter = convert (top job) (dumpPrefix job) (exclude job)
            asts' <-
                if passThrough job then
                    return asts
                else
                    converter asts
115
            emptyWarnings (concat asts) (concat asts')
Zachary Snow committed
116
            -- write the converted files out
117
            writeOutput (write job) inPaths asts'
118
            exitSuccess