+++ /dev/null
-module CLasH.Translator
- (
- makeVHDLAnnotations
- ) where
-
--- Standard Modules
-import qualified System.Directory as Directory
-import qualified Maybe
-import qualified Monad
-import qualified System.FilePath as FilePath
-import qualified Control.Monad.Trans.State as State
-import Text.PrettyPrint.HughesPJ (render)
-import Data.Accessor.Monad.Trans.State
-import qualified Data.Map as Map
-import qualified Data.Time.Clock as Clock
-import Debug.Trace
-
--- GHC API
-import qualified CoreSyn
-import qualified HscTypes
-import qualified UniqSupply
-
--- VHDL Imports
-import qualified Language.VHDL.AST as AST
-import qualified Language.VHDL.FileIO as FileIO
-import qualified Language.VHDL.Ppr as Ppr
-
--- Local Imports
-import CLasH.Translator.TranslatorTypes
-import CLasH.Translator.Annotations
-import CLasH.Utils
-import CLasH.Utils.GhcTools
-import CLasH.VHDL
-import CLasH.VHDL.VHDLTools
-import CLasH.VHDL.Testbench
-
--- | Turn Haskell to VHDL, Using the Annotations for Top Entity, Initial State
--- and Test Inputs found in the Files.
-makeVHDLAnnotations ::
- FilePath -- ^ The GHC Library Dir
- -> [FilePath] -- ^ The FileNames
- -> IO ()
-makeVHDLAnnotations libdir filenames =
- makeVHDL libdir filenames finder
- where
- finder = findSpec (hasCLasHAnnotation isTopEntity)
- (hasCLasHAnnotation isInitState)
- (isCLasHAnnotation isInitState)
- (hasCLasHAnnotation isTestInput)
-
--- | Turn Haskell to VHDL, using the given finder functions to find the Top
--- Entity, Initial State and Test Inputs in the Haskell Files.
-makeVHDL ::
- FilePath -- ^ The GHC Library Dir
- -> [FilePath] -- ^ The Filenames
- -> Finder
- -> IO ()
-makeVHDL libdir filenames finder = do
- start <- Clock.getCurrentTime
- -- Load the modules
- (cores, env, specs) <- loadModules libdir filenames (Just finder)
- -- Translate to VHDL
- vhdl <- moduleToVHDL env cores specs
- -- Write VHDL to file. Just use the first entity for the name
- let top_entity = head $ Maybe.catMaybes $ map (\(t, _, _) -> t) specs
- let dir = "./vhdl/" ++ (show top_entity) ++ "/"
- prepareDir dir
- mapM_ (writeVHDL dir) vhdl
- end <- Clock.getCurrentTime
- trace ("\nTotal compilation took " ++ show (Clock.diffUTCTime end start)) $
- return ()
-
--- | Translate the specified entities in the given modules to VHDL.
-moduleToVHDL ::
- HscTypes.HscEnv -- ^ The GHC Environment
- -> [HscTypes.CoreModule] -- ^ The Core Modules
- -> [EntitySpec] -- ^ The entities to generate
- -> IO [(AST.VHDLId, AST.DesignFile)]
-moduleToVHDL env cores specs = do
- (vhdl, count) <- runTranslatorSession env $ do
- let all_bindings = concatMap (\x -> CoreSyn.flattenBinds (HscTypes.cm_binds x)) cores
- -- Store the bindings we loaded
- tsBindings %= Map.fromList all_bindings
- let all_initstates = concatMap (\x -> case x of (_, Nothing, _) -> []; (_, Just inits, _) -> inits) specs
- tsInitStates %= Map.fromList all_initstates
- test_binds <- catMaybesM $ Monad.mapM mkTest specs
- let topbinds = Maybe.catMaybes $ map (\(top, _, _) -> top) specs
- vhdl <- case topbinds of
- [] -> error "Could not find top entity requested"
- tops -> createDesignFiles (tops ++ test_binds)
- count <- get tsTransformCounter
- return (vhdl, count)
- mapM_ (putStr . render . Ppr.ppr . snd) vhdl
- putStr $ "Total number of transformations applied: " ++ (show count) ++ "\n"
- return vhdl
- where
- mkTest :: EntitySpec -> TranslatorSession (Maybe CoreSyn.CoreBndr)
- -- Create a testbench for any entry that has test input
- mkTest (_, _, Nothing) = return Nothing
- mkTest (Nothing, _, _) = return Nothing
- mkTest (Just top, _, Just input) = do
- bndr <- createTestbench Nothing cores input top
- return $ Just bndr
-
--- Run the given translator session. Generates a new UniqSupply for that
--- session.
-runTranslatorSession :: HscTypes.HscEnv -> TranslatorSession a -> IO a
-runTranslatorSession env session = do
- -- Generate a UniqSupply
- -- Running
- -- egrep -r "(initTcRnIf|mkSplitUniqSupply)" .
- -- on the compiler dir of ghc suggests that 'z' is not used to generate
- -- a unique supply anywhere.
- uniqSupply <- UniqSupply.mkSplitUniqSupply 'z'
- let init_typestate = TypeState builtin_types [] Map.empty Map.empty env
- let init_state = TranslatorState uniqSupply init_typestate Map.empty Map.empty 0 Map.empty Map.empty Map.empty 0
- return $ State.evalState session init_state
-
--- | Prepares the directory for writing VHDL files. This means creating the
--- dir if it does not exist and removing all existing .vhdl files from it.
-prepareDir :: String -> IO()
-prepareDir dir = do
- -- Create the dir if needed
- Directory.createDirectoryIfMissing True dir
- -- Find all .vhdl files in the directory
- files <- Directory.getDirectoryContents dir
- let to_remove = filter ((==".vhdl") . FilePath.takeExtension) files
- -- Prepend the dirname to the filenames
- let abs_to_remove = map (FilePath.combine dir) to_remove
- -- Remove the files
- mapM_ Directory.removeFile abs_to_remove
-
--- | Write the given design file to a file with the given name inside the
--- given dir
-writeVHDL :: String -> (AST.VHDLId, AST.DesignFile) -> IO ()
-writeVHDL dir (name, vhdl) = do
- -- Find the filename
- let fname = dir ++ (AST.fromVHDLId name) ++ ".vhdl"
- -- Write the file
- FileIO.writeDesignFile vhdl fname
-
--- vim: set ts=8 sw=2 sts=2 expandtab: