clash-shake 0.3.2 → 0.4.0
raw patch · 6 files changed
+145/−92 lines, 6 filesdep ~aesondep ~bytestringdep ~directoryPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: aeson, bytestring, directory, shake, split, stache, text, unordered-containers
API changes (from Hackage documentation)
+ Clash.Shake: findFiles :: [FilePath] -> [FilePattern] -> [FilePath]
+ Clash.Shake: staticFiles :: FilePath -> Action [FilePath]
+ Clash.Shake: type SynthRules = ClashKit -> FilePath -> String -> Action [FilePath] -> Rules SynthKit
+ Clash.Shake.ECP5: ecp5 :: String -> SynthRules
+ Clash.Shake.ECP5: fujprog :: [String] -> FilePath -> Action ()
- Clash.Shake.F4PGA: xilinx7 :: Board -> ClashKit -> FilePath -> FilePath -> String -> Rules SynthKit
+ Clash.Shake.F4PGA: xilinx7 :: Board -> SynthRules
- Clash.Shake.Intel: quartus :: Target -> ClashKit -> FilePath -> FilePath -> String -> Rules SynthKit
+ Clash.Shake.Intel: quartus :: Target -> SynthRules
- Clash.Shake.Xilinx: ise :: Target -> ClashKit -> FilePath -> FilePath -> String -> Rules SynthKit
+ Clash.Shake.Xilinx: ise :: Target -> SynthRules
- Clash.Shake.Xilinx: vivado :: Board -> ClashKit -> FilePath -> FilePath -> String -> Rules SynthKit
+ Clash.Shake.Xilinx: vivado :: Board -> SynthRules
Files
- clash-shake.cabal +15/−14
- src/Clash/Shake.hs +14/−0
- src/Clash/Shake/ECP5.hs +69/−0
- src/Clash/Shake/F4PGA.hs +7/−10
- src/Clash/Shake/Intel.hs +12/−32
- src/Clash/Shake/Xilinx.hs +28/−36
clash-shake.cabal view
@@ -1,15 +1,15 @@ cabal-version: 1.12 --- This file has been generated from package.yaml by hpack version 0.35.0.+-- This file has been generated from package.yaml by hpack version 0.37.0. -- -- see: https://github.com/sol/hpack name: clash-shake-version: 0.3.2+version: 0.4.0 synopsis: Shake rules for building Clash programs description: Shake rules for building Clash programs and synthesizing FPGA configuration. Contains build rules for Xilinx ISE, Xilinx Vivado,- Intel Quartus and the open-source SymbiFlow toolchains. See+ Intel Quartus, F4PGA for Xilinx, and Yosys for ECP-5 and toolchains. See <https://github.com/gergoerdi/clash-pong/> for an example project. category: Hardware, Shake homepage: https://github.com/gergoerdi/clash-shake#readme@@ -38,21 +38,22 @@ Clash.Shake.Intel Clash.Shake.F4PGA Clash.Shake.SymbiFlow+ Clash.Shake.ECP5 other-modules: Paths_clash_shake hs-source-dirs: src build-depends:- aeson+ aeson <3 , base >=4.14 && <5- , bytestring- , clash-ghc >=1.4.2 && <1.5 || >=1.6.1 && <1.7- , clash-lib >=1.4.2 && <1.5 || >=1.6.1 && <1.7- , clash-prelude >=1.4.2 && <1.5 || >=1.6.1 && <1.7- , directory- , shake- , split- , stache- , text- , unordered-containers+ , bytestring <0.13+ , clash-ghc >=1.4.2 && <2.0+ , clash-lib >=1.4.2 && <2.0+ , clash-prelude >=1.4.2 && <2.0+ , directory <2+ , shake <0.20+ , split <0.3+ , stache <=3+ , text <3+ , unordered-containers <=1 default-language: Haskell2010
src/Clash/Shake.hs view
@@ -8,6 +8,9 @@ , RunClash(..), ClashKit(..) , clashRules , SynthKit(..)+ , findFiles+ , staticFiles+ , SynthRules , binImage @@ -140,6 +143,11 @@ , phonies :: [(String, Action ())] } +type SynthRules = ClashKit -> FilePath -> String -> Action [FilePath] -> Rules SynthKit++findFiles :: [FilePath] -> [FilePattern] -> [FilePath]+findFiles universe pats = filter (\fn -> (?== fn) `any` pats) universe+ nestedPhony :: String -> String -> Action () -> Rules () nestedPhony target name = phony (target <> ":" <> name) @@ -195,3 +203,9 @@ withTargets targets rules | null targets = rules | otherwise = want targets >> withoutActions rules++staticFiles :: FilePath -> Action [FilePath]+staticFiles dir = do+ files <- map (dir </>) <$> getDirectoryFiles dir ["//*"]+ need files+ return files
+ src/Clash/Shake/ECP5.hs view
@@ -0,0 +1,69 @@+{-# LANGUAGE OverloadedStrings, RecordWildCards, TemplateHaskell #-}+module Clash.Shake.ECP5+ ( ecp5+ , fujprog+ ) where++import Clash.Shake++import Development.Shake+import Development.Shake.Command+import Development.Shake.FilePath+import Development.Shake.Config+import Text.Printf++ecp5 :: String -> SynthRules+ecp5 device kit@ClashKit{..} outDir topName extraGenerated = do+ let yosys :: String -> [String] -> Action ()+ yosys tool args = cmd_ (EchoStdout False) =<< toolchain "YOSYS" tool args++ let json = outDir </> topName <.> "json"++ outDir </> topName <.> "ys" %> \out -> do+ extraFiles <- findFiles <$> extraGenerated+ srcs <- manifestSrcs+ let verilogs = extraFiles ["//*.v"]+ need $ srcs <> verilogs+ writeFileChanged out $ unlines+ [ printf "read_verilog %s" $ unwords (srcs <> verilogs)+ , printf "hierarchy -top %s" topName+ , printf "synth_ecp5 -json %s" json+ ]++ outDir <//> "*.json" %> \out -> do+ extraFiles <- findFiles <$> extraGenerated+ srcs <- manifestSrcs+ let verilogs = extraFiles ["//*.v"]+ need $ srcs <> verilogs++ let ys = out -<.> "ys"+ need [ys]+ yosys "yosys" ["-q", ys]++ outDir <//> "*.config" %> \out -> do+ extraFiles <- findFiles <$> extraGenerated+ let [lpf] = extraFiles ["//*.lpf"]+ let json = out -<.> "json"++ need [lpf, json]+ yosys "nextpnr-ecp5" ["--json", json, "--textcfg", out, "--" <> device, "--lpf", lpf]++ outDir <//> "*.bit" %> \out -> do+ let config = out -<.> "config"+ need [config]++ yosys "ecppack" ["--input", config, "--bit", out]++ let bitfile = outDir </> topName <.> "bit"++ pure SynthKit+ { bitfile = bitfile+ , phonies =+ [ "upload" |> fujprog [] bitfile+ ]+ }++fujprog :: [String] -> FilePath -> Action ()+fujprog args bitfile = do+ need [bitfile]+ cmd_ =<< toolchain "FUJPROG" "fujprog" (args ++ [bitfile])
src/Clash/Shake/F4PGA.hs view
@@ -12,23 +12,20 @@ import Development.Shake.FilePath import Development.Shake.Config -xilinx7 :: Xilinx.Board -> ClashKit -> FilePath -> FilePath -> String -> Rules SynthKit-xilinx7 Xilinx.Board{ boardTarget = target@Xilinx.Target{..} } kit@ClashKit{..} outDir srcDir topName = do+xilinx7 :: Xilinx.Board -> SynthRules+xilinx7 Xilinx.Board{ boardTarget = target@Xilinx.Target{..} } kit@ClashKit{..} outDir topName extraGenerated = do let rootDir = joinPath . map (const "..") . splitPath $ outDir let symbiflow' :: String -> [String] -> Action ()- symbiflow' tool args = cmd_ (EchoStdout False) (Cwd outDir) =<< toolchain "SYMBIFLOW" tool args+ symbiflow' tool args = cmd_ (EchoStdout False) (Cwd outDir) =<< toolchain "F4PGA" tool args symbiflow :: String -> [String] -> Action ()- symbiflow tool args = cmd_ (EchoStdout False) =<< toolchain "SYMBIFLOW" tool args-- let getFiles dir pats = map (srcDir </>) <$> getDirectoryFiles srcDir [ dir </> pat | pat <- pats ]- verilogSrcs = getFiles "src-hdl" ["*.v"]- xdcSrcs = getFiles "src-hdl" ["*.xdc" ]+ symbiflow tool args = cmd_ (EchoStdout False) =<< toolchain "F4PGA" tool args outDir </> topName <.> "eblif" %> \out -> do+ extraFiles <- findFiles <$> extraGenerated srcs <- manifestSrcs- verilogs <- verilogSrcs- xdcs <- xdcSrcs+ let verilogs = extraFiles ["//*.v"]+ xdcs = extraFiles ["//*.xdc"] need $ srcs <> verilogs <> xdcs symbiflow' "symbiflow_synth" $
src/Clash/Shake/Intel.hs view
@@ -39,58 +39,38 @@ arrowDeca :: Target arrowDeca = Target "MAX 10" "10M50DAF484C6GES" -quartus :: Target -> ClashKit -> FilePath -> FilePath -> String -> Rules SynthKit-quartus fpga kit@ClashKit{..} outDir srcDir topName = do+quartus :: Target -> SynthRules+quartus fpga kit@ClashKit{..} outDir topName extraGenerated = do let projectName = topName rootDir = joinPath . map (const "..") . splitPath $ outDir let quartus tool args = cmd_ (Cwd outDir) =<< toolchain "QUARTUS" tool args - let getFiles dir pats = getDirectoryFiles srcDir [ dir </> pat | pat <- pats ]- hdlSrcs = getFiles "src-hdl" ["*.vhdl", "*.v", "*.sv"]- tclSrcs = getFiles "src-hdl" ["*.tcl"]- constrSrcs = getFiles "src-hdl" ["*.sdc"]- ipCores = getFiles "ip" ["//*.qip"]- outDir <//> "*.tcl" %> \out -> do srcs1 <- manifestSrcs- srcs2 <- hdlSrcs- tcls <- tclSrcs- constrs <- constrSrcs- cores <- ipCores+ extraFiles <- findFiles <$> extraGenerated+ let srcs2 = extraFiles ["//*.vhdl", "//*.v", "//*.sv"]+ tcls = extraFiles ["//*.tcl"]+ constrs = extraFiles ["//*.sdc"]+ cores = extraFiles ["//*.qip"] let template = $(TH.compileMustacheFile "template/intel-quartus/project.tcl.mustache") let values = object . mconcat $ [ [ "project" .= T.pack projectName ] , [ "top" .= T.pack topName ] , targetMustache fpga- , [ "srcs" .= mconcat- [ [ object [ "fileName" .= (rootDir </> src) ] | src <- srcs1 ]- , [ object [ "fileName" .= (rootDir </> srcDir </> src) ] | src <- srcs2 ]- ]+ , [ "srcs" .= [ object [ "fileName" .= (rootDir </> src) ] | src <- srcs1 <> srcs2 ] ]- , [ "tclSrcs" .= [ object [ "fileName" .= (rootDir </> srcDir </> src) ] | src <- tcls ] ]- , [ "ipcores" .= [ object [ "fileName" .= (rootDir </> srcDir </> core) ] | core <- cores ] ]- , [ "constraintSrcs" .= [ object [ "fileName" .= (rootDir </> srcDir </> src) ] | src <- constrs ] ]+ , [ "tclSrcs" .= [ object [ "fileName" .= (rootDir </> src) ] | src <- tcls ] ]+ , [ "ipcores" .= [ object [ "fileName" .= (rootDir </> core) ] | core <- cores ] ]+ , [ "constraintSrcs" .= [ object [ "fileName" .= (rootDir </> src) ] | src <- constrs ] ] ] writeFileChanged out . TL.unpack $ renderMustache template values - outDir </> "ip" <//> "*" %> \out -> do- let src = srcDir </> makeRelative outDir out- copyFileChanged src out- let bitfile = outDir </> topName <.> "sof" bitfile %> \_out -> do- srcs1 <- manifestSrcs- srcs2 <- hdlSrcs- cores <- ipCores- need $ mconcat- [ [ outDir </> projectName <.> "tcl" ]- , [ src | src <- srcs1 ]- , [ srcDir </> src | src <- srcs2 ]- , [ outDir </> core | core <- cores ]- ]+ need $ [ outDir </> projectName <.> "tcl" ] quartus "quartus_sh" ["-t", projectName <.> "tcl"] outDir </> topName <.> "rbf" %> \out -> do
src/Clash/Shake/Xilinx.hs view
@@ -82,21 +82,18 @@ pynqZ2 = Board "tul.com.tw:pynq-z2:part0:1.0" 1 $ Target "zynq7000" "xc7z020" "clg400" 1 -ise :: Target -> ClashKit -> FilePath -> FilePath -> String -> Rules SynthKit-ise fpga kit@ClashKit{..} outDir srcDir topName = do+ise :: Target -> SynthRules+ise fpga kit@ClashKit{..} outDir topName extraGenerated = do let projectName = topName rootDir = joinPath . map (const "..") . splitPath $ outDir let ise tool args = cmd_ (Cwd outDir) =<< toolchain "ISE" tool args - let getFiles dir pats = getDirectoryFiles srcDir [ dir </> pat | pat <- pats ]- hdlSrcs = getFiles "src-hdl" ["*.vhdl", "*.v", "*.ucf" ]- ipCores = getFiles "ipcore_dir" ["*.xco", "*.xaw"]- outDir <//> "*.tcl" %> \out -> do srcs1 <- manifestSrcs- srcs2 <- hdlSrcs- cores <- ipCores+ extraFiles <- findFiles <$> extraGenerated+ let srcs2 = extraFiles ["//*.vhdl", "//*.v", "//*.ucf"]+ cores = extraFiles ["//*.xco", "//*.xaw"] let template = $(TH.compileMustacheFile "template/xilinx-ise/project.tcl.mustache") let values = object . mconcat $@@ -104,9 +101,8 @@ , [ "top" .= T.pack topName ] , targetMustache fpga , [ "srcs" .= mconcat- [ [ object [ "fileName" .= (rootDir </> src) ] | src <- srcs1 ]- , [ object [ "fileName" .= (rootDir </> srcDir </> src) ] | src <- srcs2 ]- , [ object [ "fileName" .= core ] | core <- cores ]+ [ [ object [ "fileName" .= (rootDir </> src) ] | src <- srcs1 <> srcs2 ]+ , [ object [ "fileName" .= ("ipcore_dir" </> takeFileName core) ] | core <- cores ] ] ] , [ "ipcores" .= [ object [ "name" .= takeBaseName core ] | core <- cores ] ]@@ -114,19 +110,20 @@ writeFileChanged out . TL.unpack $ renderMustache template values outDir </> "ipcore_dir" <//> "*" %> \out -> do- let src = srcDir </> makeRelative outDir out- copyFileChanged src out+ let src = makeRelative (outDir </> "ipcore_dir") out+ extraFiles <- findFiles <$> extraGenerated+ case extraFiles ["//" <> src] of+ [oneFile] -> copyFileChanged oneFile out+ [] -> error $ unwords ["Cannot find IP core file", src]+ multiple -> error $ unwords ["Multiple candidates for IP core file", src, show multiple] outDir </> topName <.> "bit" %> \_out -> do- srcs1 <- manifestSrcs- srcs2 <- hdlSrcs- cores <- ipCores+ extraFiles <- findFiles <$> extraGenerated+ let cores = extraFiles ["//*.xco", "//*.xaw"] need $ mconcat- [ [ outDir </> projectName <.> "tcl" ]- , [ src | src <- srcs1 ]- , [ srcDir </> src | src <- srcs2 ]- , [ outDir </> core | core <- cores ]- ]+ [ [ outDir </> projectName <.> "tcl" ]+ , [ outDir </> "ipcore_dir" </> takeFileName core | core <- cores ]+ ] ise "xtclsh" [projectName <.> "tcl", "rebuild_project"] return $ SynthKit@@ -138,8 +135,8 @@ ] } -vivado :: Board -> ClashKit -> FilePath -> FilePath -> String -> Rules SynthKit-vivado board kit@ClashKit{..} outDir srcDir topName = do+vivado :: Board -> SynthRules+vivado board kit@ClashKit{..} outDir topName extraGenerated = do let projectName = topName projectDir = outDir </> projectName xpr = projectDir </> projectName <.> "xpr"@@ -155,18 +152,14 @@ , "-source", tcl ] - let getFiles dir pats = getDirectoryFiles srcDir [ dir </> pat | pat <- pats ]- hdlSrcs = getFiles "src-hdl" ["*.vhdl", "*.v" ]- constrSrcs = getFiles "src-hdl" ["*.xdc" ]- ipCores = getFiles "ip" ["*.xci"]- xpr %> \out -> vivadoBatch "project.tcl" outDir </> "project.tcl" %> \out -> do srcs1 <- manifestSrcs- srcs2 <- hdlSrcs- cores <- ipCores- constrs <- constrSrcs+ extraFiles <- findFiles <$> extraGenerated+ let srcs2 = extraFiles ["//*.vhdl", "//*.v" ]+ cores = extraFiles ["//*.xci"]+ constrs = extraFiles ["//*.xdc"] let template = $(TH.compileMustacheFile "template/xilinx-vivado/project.tcl.mustache") let values = object . mconcat $@@ -175,17 +168,16 @@ , [ "top" .= T.pack topName ] , boardMustache board , [ "srcs" .= mconcat- [ [ object [ "fileName" .= src ] | src <- srcs1 ]- , [ object [ "fileName" .= (srcDir </> src) ] | src <- srcs2 ]+ [ [ object [ "fileName" .= src ] | src <- srcs1 <> srcs2 ] ] ] , [ "coreSrcs" .= object [ "nonempty" .= not (null cores)- , "items" .= [ object [ "fileName" .= (srcDir </> core) ] | core <- cores ]+ , "items" .= [ object [ "fileName" .= core ] | core <- cores ] ] ] , [ "ipcores" .= [ object [ "name" .= takeBaseName core ] | core <- cores ] ]- , [ "constraintSrcs" .= [ object [ "fileName" .= (srcDir </> src) ] | src <- constrs ] ]+ , [ "constraintSrcs" .= [ object [ "fileName" .= src ] | src <- constrs ] ] ] writeFileChanged out . TL.unpack $ renderMustache template values @@ -215,7 +207,7 @@ , phonies = [ "vivado" |> do need [xpr]- vivado "vivado" [xpr]+ vivado "vivado" [makeRelative outDir xpr] , "upload" |> do need [projectDir </> projectName <.> "runs" </> "impl_1" </> topName <.> "bit"] vivadoBatch "upload.tcl"