packages feed

clash-shake 0.1.1 → 0.2.0

raw patch · 7 files changed

+345/−26 lines, 7 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Clash.Shake.Xilinx: XilinxTarget :: String -> String -> String -> String -> XilinxTarget
- Clash.Shake.Xilinx: data XilinxTarget
- Clash.Shake.Xilinx: xilinxISE :: XilinxTarget -> ClashKit -> FilePath -> FilePath -> String -> Rules SynthKit
- Clash.Shake.Xilinx: xilinxVivado :: XilinxTarget -> ClashKit -> FilePath -> FilePath -> String -> Rules SynthKit
+ Clash.Shake: (|>) :: String -> Action () -> (String, Action ())
+ Clash.Shake.Intel: Target :: String -> String -> Target
+ Clash.Shake.Intel: [targetDevice] :: Target -> String
+ Clash.Shake.Intel: [targetFamily] :: Target -> String
+ Clash.Shake.Intel: data Target
+ Clash.Shake.Intel: de0Nano :: Target
+ Clash.Shake.Intel: quartus :: Target -> ClashKit -> FilePath -> FilePath -> String -> Rules SynthKit
+ Clash.Shake.SymbiFlow: xilinx7 :: Target -> ClashKit -> FilePath -> FilePath -> String -> Rules SynthKit
+ Clash.Shake.Xilinx: Target :: String -> String -> String -> Word -> Target
+ Clash.Shake.Xilinx: data Target
+ Clash.Shake.Xilinx: ise :: Target -> ClashKit -> FilePath -> FilePath -> String -> Rules SynthKit
+ Clash.Shake.Xilinx: targetPart :: Target -> String
+ Clash.Shake.Xilinx: vivado :: Target -> ClashKit -> FilePath -> FilePath -> String -> Rules SynthKit
- Clash.Shake.Xilinx: [targetDevice] :: XilinxTarget -> String
+ Clash.Shake.Xilinx: [targetDevice] :: Target -> String
- Clash.Shake.Xilinx: [targetFamily] :: XilinxTarget -> String
+ Clash.Shake.Xilinx: [targetFamily] :: Target -> String
- Clash.Shake.Xilinx: [targetPackage] :: XilinxTarget -> String
+ Clash.Shake.Xilinx: [targetPackage] :: Target -> String
- Clash.Shake.Xilinx: [targetSpeed] :: XilinxTarget -> String
+ Clash.Shake.Xilinx: [targetSpeed] :: Target -> Word
- Clash.Shake.Xilinx: nexysA750T :: XilinxTarget
+ Clash.Shake.Xilinx: nexysA750T :: Target
- Clash.Shake.Xilinx: papilioOne :: XilinxTarget
+ Clash.Shake.Xilinx: papilioOne :: Target
- Clash.Shake.Xilinx: papilioPro :: XilinxTarget
+ Clash.Shake.Xilinx: papilioPro :: Target

Files

clash-shake.cabal view
@@ -5,7 +5,7 @@ -- see: https://github.com/sol/hpack  name:           clash-shake-version:        0.1.1+version:        0.2.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 and Xilinx Vivado@@ -25,6 +25,7 @@     template/xilinx-vivado/project-build.tcl.mustache     template/xilinx-vivado/project.tcl.mustache     template/xilinx-vivado/upload.tcl.mustache+    template/intel-quartus/project.tcl.mustache  source-repository head   type: git@@ -34,6 +35,8 @@   exposed-modules:       Clash.Shake       Clash.Shake.Xilinx+      Clash.Shake.Intel+      Clash.Shake.SymbiFlow   other-modules:       Paths_clash_shake   hs-source-dirs:
src/Clash/Shake.hs view
@@ -2,11 +2,15 @@ module Clash.Shake     ( HDL(..)     , nestedPhony+    , (|>)++    , useConfig     , ClashKit(..)     , clashRules     , SynthKit(..)+     , binImage-    , useConfig+     , toolchain     ) where @@ -161,5 +165,8 @@     let exe = case (wrap, root) of             (Just wrap, _) -> [wrap, tool]             (Nothing, Just root) -> [root </> tool]-            (Nothing, Nothing) -> error $ printf "%s or %s must be set in build.mk" (name <> "_ROOT") name+            (Nothing, Nothing) -> [tool]     return $ exe ++ args++(|>) :: String -> Action () -> (String, Action ())+(|>) = (,)
+ src/Clash/Shake/Intel.hs view
@@ -0,0 +1,94 @@+{-# LANGUAGE OverloadedStrings, RecordWildCards, TemplateHaskell #-}+module Clash.Shake.Intel+    ( Target(..), de0Nano+    , quartus+    ) where++import Clash.Shake++import Development.Shake+import Development.Shake.Command+import Development.Shake.FilePath+import Development.Shake.Config++import Text.Mustache+import qualified Text.Mustache.Compile.TH as TH+import Data.Aeson++import qualified Data.Text as T+import qualified Data.Text.Lazy as TL+import qualified Data.Text.IO as T++data Target = Target+    { targetFamily :: String+    , targetDevice :: String+    }++targetMustache Target{..} =+    [ "targetFamily"  .= T.pack targetFamily+    , "targetDevice"  .= T.pack targetDevice+    ]++de0Nano :: Target+de0Nano = Target "Cyclone IV E" "EP4CE22F17C6"++quartus :: Target -> ClashKit -> FilePath -> FilePath -> String -> Rules SynthKit+quartus fpga kit@ClashKit{..} outDir srcDir topName = 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++        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 ]+                             ]+                    ]+                  , [ "tclSrcs" .= [ object [ "fileName" .= (rootDir </> srcDir </> src) ] | src <- tcls ] ]+                  , [ "ipcores" .= [ object [ "fileName" .= (rootDir </> srcDir </> core) ] | core <- cores ] ]+                  , [ "constraintSrcs" .= [ object [ "fileName" .= (rootDir </> srcDir </> src) ] | src <- constrs ] ]+                ]+        writeFileChanged out . TL.unpack $ renderMustache template values++    outDir </> "ip" <//> "*" %> \out -> do+            let src = srcDir </> makeRelative outDir out+            copyFileChanged src out++    outDir </> topName <.> "sof" %> \_out -> do+        srcs1 <- manifestSrcs+        srcs2 <- hdlSrcs+        cores <- ipCores+        need $ mconcat+            [ [ outDir </> projectName <.> "tcl" ]+              , [ src | src <- srcs1 ]+              , [ srcDir </> src | src <- srcs2 ]+              , [ outDir </> core | core <- cores ]+            ]+        quartus "quartus_sh" ["-t", projectName <.> "tcl"]++    return $ SynthKit+        { bitfile = outDir </> topName <.> "sof"+          , phonies =+              [ "quartus" |> do+                  need [outDir </> projectName <.> "tcl"]+                  quartus "quartus_sh" ["-t", outDir </> projectName <.> "tcl"]+              ]+        }
+ src/Clash/Shake/SymbiFlow.hs view
@@ -0,0 +1,100 @@+{-# LANGUAGE OverloadedStrings, RecordWildCards, TemplateHaskell #-}+module Clash.Shake.SymbiFlow+    ( xilinx7+    ) where++import Clash.Shake+import qualified Clash.Shake.Xilinx as Xilinx++import Development.Shake+import Development.Shake.Command+import Development.Shake.FilePath+import Development.Shake.Config++xilinx7 :: Xilinx.Target -> ClashKit -> FilePath -> FilePath -> String -> Rules SynthKit+xilinx7 target@Xilinx.Target{..} kit@ClashKit{..} outDir srcDir topName = 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 :: 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" ]++    outDir </> topName <.> "eblif" %> \out -> do+        srcs <- manifestSrcs+        verilogs <- verilogSrcs+        xdcs <- xdcSrcs+        need $ verilogs <> xdcs++        symbiflow' "symbiflow_synth" $+          [ "-d", targetFamily+          , "-p", Xilinx.targetPart target+          , "-t", topName+          ] +++          [ "-v " <> rootDir </> src | src <- srcs <> verilogs ] +++          [ "-x " <> rootDir </> xdc | xdc <- xdcs ]++    outDir <//> "*.net" %> \out -> do+        let eblif = out -<.> "eblif"+        need [eblif]+        symbiflow' "symbiflow_pack" $+          [ "-d", targetDevice <> "_test"+          , "-e", takeFileName eblif+          ]++    outDir <//> "*.place" %> \out -> do+        let eblif = out -<.> "eblif"+            net = out -<.> "net"+        need [eblif, net]+        symbiflow' "symbiflow_place" $+          [ "-d", targetDevice <> "_test"+          , "-P", Xilinx.targetPart target+          , "-e", takeFileName eblif+          , "-n", takeFileName net+          ]++    outDir <//> "*.route" %> \out -> do+        let eblif = out -<.> "eblif"+            place = out -<.> "place"+        need [eblif, place]+        symbiflow' "symbiflow_route" $+          [ "-d", targetDevice <> "_test"+          , "-e", takeFileName eblif+          ]++    outDir <//> "*.fasm" %> \out -> do+        let eblif = out -<.> "eblif"+            route = out -<.> "route"+        need [eblif, route]+        symbiflow' "symbiflow_write_fasm" $+          [ "-d", targetDevice <> "_test"+          , "-e", takeFileName eblif+          ]++    outDir <//> "*.bit" %> \out -> do+        let fasm = out -<.> "fasm"+        need [fasm]+        symbiflow "symbiflow_write_bitstream" $+          [ "-d", targetFamily+          , "-p", Xilinx.targetPart target+          , "-f", fasm+          , "-b", out+          ]++    let bitfile = outDir </> topName <.> "bit"++    return SynthKit+        { bitfile = bitfile+        , phonies =+            [ "upload" |> openFPGALoader ["-c", "digilent"] bitfile+            ]+        }++openFPGALoader :: [String] -> FilePath -> Action ()+openFPGALoader args bitfile = do+    need [bitfile]+    cmd_ =<< toolchain "OPENFPGALOADER" "openFPGALoader" (args ++ [bitfile])
src/Clash/Shake/Xilinx.hs view
@@ -1,8 +1,10 @@ {-# LANGUAGE OverloadedStrings, RecordWildCards, TemplateHaskell #-} module Clash.Shake.Xilinx-    ( XilinxTarget(..), papilioPro, papilioOne, nexysA750T-    , xilinxISE-    , xilinxVivado+    ( Target(..), targetPart+    , ise+    , vivado++    , papilioPro, papilioOne, nexysA750T     ) where  import Clash.Shake@@ -15,37 +17,42 @@ import Text.Mustache import qualified Text.Mustache.Compile.TH as TH import Data.Aeson+import qualified Data.Aeson.Types as Aeson  import qualified Data.Text as T import qualified Data.Text.Lazy as TL import qualified Data.Text.IO as T -data XilinxTarget = XilinxTarget+data Target = Target     { targetFamily :: String     , targetDevice :: String     , targetPackage :: String-    , targetSpeed :: String+    , targetSpeed :: Word     } -targetMustache XilinxTarget{..} =+targetPart :: Target -> String+targetPart Target{..} = targetDevice <> targetPackage <> "-" <> show targetSpeed++targetMustache :: Target -> [Aeson.Pair]+targetMustache target@Target{..} =     [ "targetFamily"  .= T.pack targetFamily     , "targetDevice"  .= T.pack targetDevice     , "targetPackage" .= T.pack targetPackage-    , "targetSpeed"   .= T.pack targetSpeed-    , "part"          .= T.pack (targetDevice <> targetPackage <> targetSpeed)+    , "targetSpeed"   .= targetSpeed+    , "part"          .= T.pack (targetPart target)     ] -papilioPro :: XilinxTarget-papilioPro = XilinxTarget "Spartan6" "xc6slx9" "tqg144" "-2"+papilioPro :: Target+papilioPro = Target "Spartan6" "xc6slx9" "tqg144" 2 -papilioOne :: XilinxTarget-papilioOne = XilinxTarget "Spartan3E" "xc3s500e" "vq100" "-5"+papilioOne :: Target+papilioOne = Target "Spartan3E" "xc3s500e" "vq100" 5 -nexysA750T :: XilinxTarget-nexysA750T = XilinxTarget "Artrix7" "xc7a50t" "icsg324" "-1L"+nexysA750T :: Target+nexysA750T = Target "artix7" "xc7a50t" "csg324" 1 -xilinxISE :: XilinxTarget -> ClashKit -> FilePath -> FilePath -> String -> Rules SynthKit-xilinxISE fpga kit@ClashKit{..} outDir srcDir topName = do+ise :: Target -> ClashKit -> FilePath -> FilePath -> String -> Rules SynthKit+ise fpga kit@ClashKit{..} outDir srcDir topName = do     let projectName = topName         rootDir = joinPath . map (const "..") . splitPath $ outDir @@ -100,8 +107,8 @@             ]         } -xilinxVivado :: XilinxTarget -> ClashKit -> FilePath -> FilePath -> String -> Rules SynthKit-xilinxVivado fpga kit@ClashKit{..} outDir srcDir topName = do+vivado :: Target -> ClashKit -> FilePath -> FilePath -> String -> Rules SynthKit+vivado fpga kit@ClashKit{..} outDir srcDir topName = do     let projectName = topName         projectDir = outDir </> projectName         xpr = projectDir </> projectName <.> "xpr"@@ -184,6 +191,3 @@                    vivadoBatch "upload.tcl"             ]         }--(|>) :: String -> Action () -> (String, Action ())-(|>) = (,)
+ template/intel-quartus/project.tcl.mustache view
@@ -0,0 +1,111 @@+# Mustache template for Intel Quartus projects+# for more details see: Quartus II Handbook Version 11.0 Volume 2+# and Quartus II Scripting Reference Manual++set myScript "{{project}}.tcl"++# Load Quartus Prime Tcl Project packages+package require ::quartus::project++# Add the next line to get the execute_flow command+package require ::quartus::flow++set need_to_close_project 0+set make_assignments 1++# This procedure will open a quartus project+proc Open {prj_name} {+    global need_to_close_project+    # Check that the right project is open+    if {[is_project_open]} {+        if {[string compare $quartus(project) $prj_name]} {+            puts "Project is not open"+            set make_assignments 0+        }+    } else {+        # Only open if not already open+        if {[project_exists $prj_name]} {+            set current_revision [get_current_revision $prj_name]+                project_open -revision $current_revision $prj_name+        } else {+            project_new -revision $prj_name $prj_name+        }+        set need_to_close_project 1+    }+}++# This procedure adds files to quartus .qsf file+proc Addfile {src_file {library "lib"} } {+    if [regexp {.vhdl?$} $src_file] {+        set_global_assignment -name VHDL_FILE "$src_file" -library "$library"+    } elseif [regexp {.sv?$} $src_file] {+        set_global_assignment -name SYSTEMVERILOG_FILE "$src_file" -library "$library"+    } elseif [regexp {.v?$} $src_file] {+        set_global_assignment -name VERILOG_FILE "$src_file" -library "$library"+    } else {+        puts "Unknown file type: $src_file"+    }+    # Commit assignments+    export_assignments+}++# Open project+Open "{{project}}"++# Make assignments+if {$make_assignments} {+    set_global_assignment -name FAMILY "{{targetFamily}}"+    set_global_assignment -name DEVICE "{{targetDevice}}"+    set_global_assignment -name PROJECT_OUTPUT_DIRECTORY "./"+    set_global_assignment -name NUM_PARALLEL_PROCESSORS 2+    set_global_assignment -name EDA_SIMULATION_TOOL "ModelSim-Altera (Verilog)"+    set_global_assignment -name EDA_NETLIST_WRITER_OUTPUT_DIR ./netlist -section_id eda_simulation+    set_global_assignment -name EDA_OUTPUT_DATA_FORMAT Verilog -section_id eda_simulation+    set_global_assignment -name TIMEQUEST_MULTICORNER_ANALYSIS ON+    set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top+    set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT -section_id Top+    set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top+    set_global_assignment -name VERILOG_INPUT_VERSION SYSTEMVERILOG_2005+    set_global_assignment -name CYCLONEII_RESERVE_NCEO_AFTER_CONFIGURATION "USE AS REGULAR IO"+    set_global_assignment -name RESERVE_FLASH_NCE_AFTER_CONFIGURATION "USE AS REGULAR IO"+    set_global_assignment -name RESERVE_DATA0_AFTER_CONFIGURATION "USE AS REGULAR IO"+    set_global_assignment -name RESERVE_DATA1_AFTER_CONFIGURATION "USE AS REGULAR IO"+    set_global_assignment -name RESERVE_DCLK_AFTER_CONFIGURATION "USE AS REGULAR IO"+    set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top++    # Setup top entity+    set_global_assignment -name TOP_LEVEL_ENTITY "{{top}}"++    # Source settings+    {{#tclSrcs}}+    source "{{fileName}}"+    {{/tclSrcs}}++    # Source constrains+    {{#constraintSrcs}}+    set_global_assignment -name SDC_FILE "{{fileName}}"+    {{/constraintSrcs}}++    puts "$myScript: Adding sources to project..."++    # Add QIP files (from ip dir)+    {{#ipcores}}+    set_global_assignment -name QIP_FILE "{{fileName}}"+    {{/ipcores}}++    # Add sources to the project+    {{#srcs}}+    Addfile "{{fileName}}"+    {{/srcs}}++    # Commit assignments+    export_assignments+}++execute_flow -compile++# Close project+if {$need_to_close_project} {+    puts "Closing project"+    project_close+}
template/xilinx-ise/project.tcl.mustache view
@@ -134,7 +134,7 @@    project set family "{{targetFamily}}"    project set device "{{targetDevice}}"    project set package "{{targetPackage}}"-   project set speed "{{targetSpeed}}"+   project set speed "-{{targetSpeed}}"    project set top_level_module_type "HDL"    project set synthesis_tool "XST (VHDL/Verilog)"    project set simulator "ISim (VHDL/Verilog)"@@ -176,7 +176,7 @@    if { ! [ file exists "ipcore_dir/{{name}}.vhd" ] } {        puts "$myScript: Regenerating {{name}}"        cd ipcore_dir-       run_cg_regen "{{name}}" {{targetDevice}}{{targetSpeed}}{{targetPackage}} VHDL CURRENT+       run_cg_regen "{{name}}" "{{part}}" VHDL CURRENT        cd ..    }    {{/ipcores}}