kansas-lava-shake-0.3.0: src/Development/KansasLava/Shake/Xilinx.hs
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
module Development.KansasLava.Shake.Xilinx
( XilinxTarget(..)
, papilioOne, papilioPro
, xilinxRules
) where
import Development.Shake hiding ((~>))
import Development.Shake.FilePath
import Development.Shake.Config
import qualified Data.Text as T
import Text.Mustache
import Text.Mustache.Types
import qualified Data.Map as M
import Data.Maybe (fromMaybe)
import Paths_kansas_lava_shake
data XilinxTarget = XilinxTarget{ targetFamily, targetDevice, targetPackage, targetSpeed :: String }
papilioPro :: XilinxTarget
papilioPro = XilinxTarget "Spartan6" "xc6slx9" "tqg144" "-2"
papilioOne :: XilinxTarget
papilioOne = XilinxTarget "Spartan3E" "xc3s500e" "vq100" "-5"
boards :: M.Map String XilinxTarget
boards = M.fromList
[ ("papilio-pro", papilioPro)
, ("papilio-one", papilioOne)
]
xilinxRules :: Maybe XilinxTarget -> FilePath -> String -> [FilePath] -> [FilePath] -> Rules ()
xilinxRules mtarget outDir projName srcs ipcores = do
usingConfigFile "build.mk"
outDir </> projName <.> "bit" %> \_out -> do
need . concat $ [ [ outDir </> src | src <- srcs ]
, [ outDir </> "ipcore_dir" </> xco | xco <- ipcores ]
, [ outDir </> projName <.> "tcl" ]
]
xilinx "xtclsh" [projName <.> "tcl", "rebuild_project"]
outDir </> "*.tcl" %> \out -> do
target <- case mtarget of
Just target -> return target
Nothing -> do
board <- fromMaybe (error "Please set BOARD in build.mk") <$> getConfig "BOARD"
return $ fromMaybe (error $ unwords ["Unknown board:", board]) $ M.lookup board boards
mustache (projCtxt target) out
where
xilinx tool args = do
root <- getConfig "XILINX_ROOT"
wrap <- getConfig "XILINX_WRAPPER"
let exe = case (wrap, root) of
(Just wrap, _) -> [wrap, tool]
(Nothing, Just root) -> [root </> tool]
(Nothing, Nothing) -> error "XILINX_ROOT or XILINX_WRAPPER must be set"
cmd (Cwd outDir) exe args
projCtxt XilinxTarget{..} = object $ [
"project" ~= projName,
"targetFamily" ~= targetFamily,
"targetDevice" ~= targetDevice,
"targetSpeed" ~= targetSpeed,
"targetPackage" ~= targetPackage,
"ipcores" ~> (map (\n -> object ["name" ~> n]) $ map dropExtension ipcores),
"srcs" ~> (map (\s -> object ["fileName" ~> s]) srcs)
]
mustache :: Value -> FilePath -> Action ()
mustache ctxt target = do
alwaysRerun
rSrc <- liftIO $ getDataFileName ("ise.template" </> templateName)
withTempDir $ \tempDir -> do
copyFileChanged rSrc (tempDir </> templateName)
tE <- liftIO $ automaticCompile [tempDir] templateName
case tE of
Left err ->
liftIO $ error $ "KansasLava.Shake.Xilinx - mustache template problem: " ++ show err
Right template -> do
let st = substitute template ctxt
writeFileChanged target $ T.unpack st
where
ext = drop 1 . takeExtension $ target
templateName = ext <.> "mustache"