clash-shake (empty) → 0.1.0
raw patch · 8 files changed
+829/−0 lines, 8 filesdep +aesondep +basedep +bytestring
Dependencies added: aeson, base, bytestring, clash-ghc, clash-lib, clash-prelude, directory, ghc-typelits-extra, ghc-typelits-knownnat, ghc-typelits-natnormalise, shake, split, stache, text, unordered-containers
Files
- LICENSE +21/−0
- clash-shake.cabal +59/−0
- src/Clash/Shake.hs +152/−0
- src/Clash/Shake/Xilinx.hs +203/−0
- template/xilinx-ise/project.tcl.mustache +258/−0
- template/xilinx-vivado/project-build.tcl.mustache +9/−0
- template/xilinx-vivado/project.tcl.mustache +113/−0
- template/xilinx-vivado/upload.tcl.mustache +14/−0
+ LICENSE view
@@ -0,0 +1,21 @@+MIT License++Copyright (c) 2020 Gergő Érdi (http://gergo.erdi.hu/)++Permission is hereby granted, free of charge, to any person obtaining a copy+of this software and associated documentation files (the "Software"), to deal+in the Software without restriction, including without limitation the rights+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+copies of the Software, and to permit persons to whom the Software is+furnished to do so, subject to the following conditions:++The above copyright notice and this permission notice shall be included in all+copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+SOFTWARE.
+ clash-shake.cabal view
@@ -0,0 +1,59 @@+cabal-version: 1.12++-- This file has been generated from package.yaml by hpack version 0.34.4.+--+-- see: https://github.com/sol/hpack+--+-- hash: 5f6e45bc2e072294d671a13e35cf938c8c9e4cfb32adee44eba24228b48bb9d6++name: clash-shake+version: 0.1.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+ toolchains. See <https://github.com/gergoerdi/clash-pong/> for an+ example project.+category: Hardware, Shake+homepage: https://github.com/gergoerdi/clash-shake#readme+bug-reports: https://github.com/gergoerdi/clash-shake/issues+author: Gergő Érdi+maintainer: gergo@erdi.hu+copyright: 2021 Gergő Érdi+license: MIT+license-file: LICENSE+build-type: Simple+extra-source-files:+ template/xilinx-ise/project.tcl.mustache+ template/xilinx-vivado/project-build.tcl.mustache+ template/xilinx-vivado/project.tcl.mustache+ template/xilinx-vivado/upload.tcl.mustache++source-repository head+ type: git+ location: https://github.com/gergoerdi/clash-shake++library+ exposed-modules:+ Clash.Shake+ Clash.Shake.Xilinx+ other-modules:+ Paths_clash_shake+ hs-source-dirs:+ src+ build-depends:+ aeson+ , base >=4.14 && <5+ , bytestring+ , clash-ghc >=1.4.2 && <1.5+ , clash-lib >=1.4.2 && <1.5+ , clash-prelude >=1.4.2 && <1.5+ , directory+ , ghc-typelits-extra+ , ghc-typelits-knownnat+ , ghc-typelits-natnormalise+ , shake+ , split+ , stache+ , text+ , unordered-containers+ default-language: Haskell2010
+ src/Clash/Shake.hs view
@@ -0,0 +1,152 @@+{-# LANGUAGE RecordWildCards #-}+module Clash.Shake+ ( HDL(..)+ , nestedPhony+ , ClashKit(..)+ , clashRules+ , SynthKit(..)+ , binImage+ , useConfig+ ) where++import Development.Shake+import Development.Shake.FilePath+import Development.Shake.Config+import Development.Shake.Util (parseMakefile)++import qualified Clash.Main as Clash++import Data.List.Split++import qualified Data.Text as T+import qualified Data.HashMap.Strict as HM+import Data.Char (isUpper, toLower)+import Control.Monad (forM_)+import qualified Data.ByteString as BS+import qualified System.Directory as Dir+import Control.Exception (bracket)+import Data.Maybe (fromJust)++import Clash.Driver.Manifest+import Clash.Prelude (pack)++data HDL+ = VHDL+ | Verilog+ | SystemVerilog+ deriving (Eq, Enum, Bounded, Show, Read)++hdlDir :: HDL -> FilePath+hdlDir VHDL = "vhdl"+hdlDir Verilog = "verilog"+hdlDir SystemVerilog = "systemverilog"++hdlExt :: HDL -> FilePath+hdlExt VHDL = "vhdl"+hdlExt Verilog = "v"+hdlExt SystemVerilog = "sv"++data ClashKit = ClashKit+ { clash :: [String] -> Action ()+ , manifestSrcs :: Action [FilePath]+ }++withWorkingDirectory :: FilePath -> IO a -> IO a+withWorkingDirectory dir act =+ bracket Dir.getCurrentDirectory Dir.setCurrentDirectory $ \_ ->+ Dir.setCurrentDirectory dir >> act++clashRules :: FilePath -> HDL -> [FilePath] -> FilePath -> [String] -> Action () -> Rules ClashKit+clashRules outDir hdl srcDirs src clashFlags extraGenerated = do+ let clash args = liftIO $ do+ let srcFlags = ["-i" <> srcDir | srcDir <- srcDirs]+ let args' = ["-outputdir", outDir] <> clashFlags <> srcFlags <> args+ putStrLn $ "Clash.defaultMain " <> unwords args'+ Clash.defaultMain args'++ -- TODO: ideally, Clash should return the manifest, or at least its file location...+ let synModule+ | isModuleName src = src+ | otherwise = "Main"++ clashTopName = "topEntity"+ synOut = outDir </> synModule <.> clashTopName+ manifestFile = synOut </> "clash-manifest.json"+ manifest = do+ need [manifestFile]+ Just manifest <- liftIO $ readManifest manifestFile+ return manifest++ let manifestSrcs = do+ Manifest{..} <- manifest+ let clashSrcs = map T.unpack componentNames <>+ [ map toLower clashTopName <> "_types" | hdl == VHDL ]+ return [ synOut </> c <.> hdlExt hdl | c <- clashSrcs ]++ getSrcs <- do+ outDir </> "ghc-deps.make" %> \out -> do+ alwaysRerun+ -- By writing to a temp file and using `copyFileChanged`,+ -- we avoid spurious reruns+ -- (https://stackoverflow.com/a/64277431/477476)+ withTempFileWithin outDir $ \tmp -> do+ clash ["-M", "-dep-suffix", "", "-dep-makefile", tmp, src]+ liftIO $ removeFiles outDir [takeBaseName tmp <.> "bak"]+ copyFileChanged tmp out++ return $ do+ let depFile = outDir </> "ghc-deps.make"+ need [depFile]+ deps <- parseMakefile <$> liftIO (readFile depFile)+ let isHsSource fn+ | ext `elem` [".hi"] = False+ | ext `elem` [".hs", ".lhs"] = True+ | otherwise = error $ "Unrecognized source file: " <> fn+ where+ ext = takeExtension fn+ hsDeps = [fn | (_, fns) <- deps, fn <- fns, isHsSource fn]+ return hsDeps++ manifestFile %> \_out -> do+ need =<< getSrcs+ extraGenerated+ clash [case hdl of { VHDL -> "--vhdl"; Verilog -> "--verilog"; SystemVerilog -> "--systemverilog" }, src]++ return ClashKit{..}++data SynthKit = SynthKit+ { bitfile :: FilePath+ , phonies :: [(String, Action ())]+ }++nestedPhony :: String -> String -> Action () -> Rules ()+nestedPhony root name = phony (root </> name)++useConfig :: FilePath -> Rules ()+useConfig file = do+ cfg <- do+ haveConfig <- liftIO $ Dir.doesFileExist file+ if haveConfig then do+ usingConfigFile file+ liftIO $ readConfigFile file+ else do+ usingConfig mempty+ return mempty++ forM_ (HM.lookup "TARGET" cfg) $ \target ->+ want [target </> "bitfile"]++binImage :: Maybe Int -> FilePath -> FilePath -> Action ()+binImage size src out = do+ need [src]+ lines <- liftIO $ binLines size <$> BS.readFile src+ writeFileChanged out (unlines lines)++binLines :: Maybe Int -> BS.ByteString -> [String]+binLines size bs = map (filter (/= '_') . show . pack) bytes+ where+ bytes = maybe id ensureSize size $ BS.unpack bs+ ensureSize size bs = take size $ bs <> repeat 0x00++isModuleName :: String -> Bool+isModuleName = all (isUpper . head) . splitOn "."
+ src/Clash/Shake/Xilinx.hs view
@@ -0,0 +1,203 @@+{-# LANGUAGE OverloadedStrings, RecordWildCards, TemplateHaskell #-}+module Clash.Shake.Xilinx+ ( XilinxTarget(..), papilioPro, papilioOne, nexysA750T+ , xilinxISE+ , xilinxVivado+ ) 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 XilinxTarget = XilinxTarget+ { targetFamily :: String+ , targetDevice :: String+ , targetPackage :: String+ , targetSpeed :: String+ }++targetMustache XilinxTarget{..} =+ [ "targetFamily" .= T.pack targetFamily+ , "targetDevice" .= T.pack targetDevice+ , "targetPackage" .= T.pack targetPackage+ , "targetSpeed" .= T.pack targetSpeed+ , "part" .= T.pack (targetDevice <> targetPackage <> targetSpeed)+ ]++papilioPro :: XilinxTarget+papilioPro = XilinxTarget "Spartan6" "xc6slx9" "tqg144" "-2"++papilioOne :: XilinxTarget+papilioOne = XilinxTarget "Spartan3E" "xc3s500e" "vq100" "-5"++nexysA750T :: XilinxTarget+nexysA750T = XilinxTarget "Artrix7" "xc7a50t" "icsg324" "-1L"++xilinxISE :: XilinxTarget -> ClashKit -> FilePath -> FilePath -> String -> Rules SynthKit+xilinxISE fpga kit@ClashKit{..} outDir srcDir topName = do+ let projectName = topName+ rootDir = joinPath . map (const "..") . splitPath $ outDir++ let ise tool args = do+ root <- getConfig "ISE_ROOT"+ wrap <- getConfig "ISE"+ let exe = case (wrap, root) of+ (Just wrap, _) -> [wrap, tool]+ (Nothing, Just root) -> [root </> "ISE/bin/lin64" </> tool]+ (Nothing, Nothing) -> error "ISE_ROOT or ISE must be set in build.mk"+ cmd_ (Cwd outDir) exe 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++ let template = $(TH.compileMustacheFile "template/xilinx-ise/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 ]+ , [ object [ "fileName" .= core ] | core <- cores ]+ ]+ ]+ , [ "ipcores" .= [ object [ "name" .= takeBaseName core ] | core <- cores ] ]+ ]+ writeFileChanged out . TL.unpack $ renderMustache template values++ outDir </> "ipcore_dir" <//> "*" %> \out -> do+ let src = srcDir </> makeRelative outDir out+ copyFileChanged src out++ outDir </> topName <.> "bit" %> \_out -> do+ srcs1 <- manifestSrcs+ srcs2 <- hdlSrcs+ cores <- ipCores+ need $ mconcat+ [ [ outDir </> projectName <.> "tcl" ]+ , [ src | src <- srcs1 ]+ , [ srcDir </> src | src <- srcs2 ]+ , [ outDir </> core | core <- cores ]+ ]+ ise "xtclsh" [projectName <.> "tcl", "rebuild_project"]++ return $ SynthKit+ { bitfile = outDir </> topName <.> "bit"+ , phonies =+ [ "ise" |> do+ need [outDir </> projectName <.> "tcl"]+ ise "ise" [outDir </> projectName <.> "tcl"]+ ]+ }++xilinxVivado :: XilinxTarget -> ClashKit -> FilePath -> FilePath -> String -> Rules SynthKit+xilinxVivado fpga kit@ClashKit{..} outDir srcDir topName = do+ let projectName = topName+ projectDir = outDir </> projectName+ xpr = projectDir </> projectName <.> "xpr"+ rootDir = joinPath . map (const "..") . splitPath $ outDir++ let vivado tool args = do+ root <- getConfig "VIVADO_ROOT"+ wrap <- getConfig "VIVADO"+ let exe = case (wrap, root) of+ (Just wrap, _) -> [wrap, tool]+ (Nothing, Just root) -> [root </> "bin" </> tool]+ (Nothing, Nothing) -> error "VIVADO_ROOT or VIVADO must be set in build.mk"+ cmd_ (Cwd outDir) exe args+ vivadoBatch tcl = do+ need [outDir </> tcl]+ vivado "vivado"+ [ "-mode", "batch"+ , "-nojournal"+ , "-nolog"+ , "-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++ let template = $(TH.compileMustacheFile "template/xilinx-vivado/project.tcl.mustache")+ let values = object . mconcat $+ [ [ "rootDir" .= T.pack rootDir]+ , [ "project" .= T.pack projectName ]+ , [ "top" .= T.pack topName ]+ , targetMustache fpga+ , [ "board" .= T.pack "digilentinc.com:nexys-a7-50t:part0:1.0" ] -- TODO+ , [ "srcs" .= mconcat+ [ [ object [ "fileName" .= src ] | src <- srcs1 ]+ , [ object [ "fileName" .= (srcDir </> src) ] | src <- srcs2 ]+ ]+ ]+ , [ "coreSrcs" .= object+ [ "nonempty" .= not (null cores)+ , "items" .= [ object [ "fileName" .= (srcDir </> core) ] | core <- cores ]+ ]+ ]+ , [ "ipcores" .= [ object [ "name" .= takeBaseName core ] | core <- cores ] ]+ , [ "constraintSrcs" .= [ object [ "fileName" .= (srcDir </> src) ] | src <- constrs ] ]+ ]+ writeFileChanged out . TL.unpack $ renderMustache template values++ outDir </> "build.tcl" %> \out -> do+ let template = $(TH.compileMustacheFile "template/xilinx-vivado/project-build.tcl.mustache")+ let values = object . mconcat $+ [ [ "project" .= T.pack projectName ]+ , [ "top" .= T.pack topName ]+ ]+ writeFileChanged out . TL.unpack $ renderMustache template values++ outDir </> "upload.tcl" %> \out -> do+ let template = $(TH.compileMustacheFile "template/xilinx-vivado/upload.tcl.mustache")+ let values = object . mconcat $+ [ [ "project" .= T.pack projectName ]+ , [ "top" .= T.pack topName ]+ , targetMustache fpga+ ]+ writeFileChanged out . TL.unpack $ renderMustache template values++ projectDir </> projectName <.> "runs" </> "impl_1" </> topName <.> "bit" %> \out -> do+ need [xpr]+ vivadoBatch "build.tcl"++ return SynthKit+ { bitfile = projectDir </> projectName <.> "runs" </> "impl_1" </> topName <.> "bit"+ , phonies =+ [ "vivado" |> do+ need [xpr]+ vivado "vivado" [xpr]+ , "upload" |> do+ need [projectDir </> projectName <.> "runs" </> "impl_1" </> topName <.> "bit"]+ vivadoBatch "upload.tcl"+ ]+ }++(|>) :: String -> Action () -> (String, Action ())+(|>) = (,)
+ template/xilinx-ise/project.tcl.mustache view
@@ -0,0 +1,258 @@+set myProject "{{project}}"+set myScript "{{project}}.tcl"+set myTop "{{top}}"++proc run_process {} {++ global myScript+ global myProject++ ## put out a 'heartbeat' - so we know something's happening.+ puts "\n$myScript: running ($myProject)...\n"++ if { ! [ open_project ] } {+ return false+ }++ set_process_props+ #+ # Remove the comment characters (#'s) to enable the following commands+ # process run "Synthesize"+ # process run "Translate"+ # process run "Map"+ # process run "Place & Route"+ #+ set task "Implement Design"+ if { ! [run_task $task] } {+ puts "$myScript: $task run failed, check run output for details."+ project close+ return+ }++ set task "Generate Programming File"+ if { ! [run_task $task] } {+ puts "$myScript: $task run failed, check run output for details."+ project close+ return+ }++ puts "Run completed (successfully)."+ project close++}++proc rebuild_project {} {++ global myScript+ global myProject++ project close+ ## put out a 'heartbeat' - so we know something's happening.+ puts "\n$myScript: Rebuilding ($myProject)...\n"++ set proj_exts [ list ise xise gise ]+ foreach ext $proj_exts {+ set proj_name "${myProject}.$ext"+ if { [ file exists $proj_name ] } {+ file delete $proj_name+ }+ }++ project new $myProject+ set_project_props+ add_source_files+ create_libraries+ puts "$myScript: project rebuild completed."++ run_process++}++proc run_task { task } {++ # helper proc for run_process++ puts "Running '$task'"+ set result [ process run "$task" ]+ #+ # check process status (and result)+ set status [ process get $task status ]+ if { ( ( $status != "up_to_date" ) && \+ ( $status != "warnings" ) ) || \+ ! $result } {+ return false+ }+ return true+}++proc show_help {} {++ global myScript++ puts ""+ puts "usage: xtclsh $myScript <options>"+ puts " or you can run xtclsh and then enter 'source $myScript'."+ puts ""+ puts "options:"+ puts " run_process - set properties and run processes."+ puts " rebuild_project - rebuild the project from scratch and run processes."+ puts " set_project_props - set project properties (device, speed, etc.)"+ puts " add_source_files - add source files"+ puts " create_libraries - create vhdl libraries"+ puts " set_process_props - set process property values"+ puts " show_help - print this message"+ puts ""+}++proc open_project {} {++ global myScript+ global myProject++ if { ! [ file exists ${myProject}.xise ] } {+ ## project file isn't there, rebuild it.+ puts "Project $myProject not found. Use project_rebuild to recreate it."+ return false+ }++ project open $myProject++ return true++}++proc set_project_props {} {++ global myScript++ if { ! [ open_project ] } {+ return false+ }++ puts "$myScript: Setting project properties..."++ project set family "{{targetFamily}}"+ project set device "{{targetDevice}}"+ project set package "{{targetPackage}}"+ project set speed "{{targetSpeed}}"+ project set top_level_module_type "HDL"+ project set synthesis_tool "XST (VHDL/Verilog)"+ project set simulator "ISim (VHDL/Verilog)"+ project set "Preferred Language" "VHDL"+}+++proc findRtfPath { relativePath } {+ set xilenv ""+ if { [info exists ::env(XILINX) ] } {+ if { [info exists ::env(MYXILINX)] } {+ set xilenv [join [list $::env(MYXILINX) $::env(XILINX)] $::xilinx::path_sep ]+ } else {+ set xilenv $::env(XILINX)+ }+ }+ foreach path [ split $xilenv $::xilinx::path_sep ] {+ set fullPath [ file join $path $relativePath ]+ if { [ file exists $fullPath ] } {+ return $fullPath+ }+ }+ return ""+}++proc add_source_files {} {++ global myProject+ global myScript+ global myTop++ if { ! [ open_project ] } {+ return false+ }++ source [ findRtfPath "data/projnav/scripts/dpm_cgUtils.tcl" ]++ {{#ipcores}}+ if { ! [ file exists "ipcore_dir/{{name}}.vhd" ] } {+ puts "$myScript: Regenerating {{name}}"+ cd ipcore_dir+ run_cg_regen "{{name}}" {{targetDevice}}{{targetSpeed}}{{targetPackage}} VHDL CURRENT+ cd ..+ }+ {{/ipcores}}+++ puts "$myScript: Adding sources to project..."++ {{#srcs}}+ xfile add "{{fileName}}"+ {{/srcs}}++ # Set the Top Module as well...+ project set top "rtl" $myTop++ puts "$myScript: project sources reloaded."++} ; # end add_source_files++proc create_libraries {} {++ global myScript++ if { ! [ open_project ] } {+ return false+ }++ puts "$myScript: Creating libraries..."+++ # must close the project or library definitions aren't saved.+ project save++} ; # end create_libraries++proc set_process_props {} {++ global myScript++ if { ! [ open_project ] } {+ return false+ }++ puts "$myScript: setting process properties..."++ project set "Compiled Library Directory" "\$XILINX/<language>/<simulator>"+ project set "Functional Model Target Language" "VHDL" -process "View HDL Source"++ puts "$myScript: project property values set."++} ; # end set_process_props++proc main {} {++ if { [llength $::argv] == 0 } {+ show_help+ return true+ }++ foreach option $::argv {+ switch $option {+ "show_help" { show_help }+ "run_process" { run_process }+ "rebuild_project" { rebuild_project }+ "set_project_props" { set_project_props }+ "add_source_files" { add_source_files }+ "create_libraries" { create_libraries }+ "set_process_props" { set_process_props }+ default { puts "unrecognized option: $option"; show_help }+ }+ }+}++if { $tcl_interactive } {+ show_help+} else {+ if {[catch {main} result]} {+ puts "$myScript failed: $result."+ }+}
+ template/xilinx-vivado/project-build.tcl.mustache view
@@ -0,0 +1,9 @@+open_project {{project}}/{{project}}.xpr+update_compile_order -fileset sources_1+reset_run synth_1+launch_runs synth_1+wait_on_run synth_1+launch_runs impl_1+wait_on_run impl_1+launch_runs impl_1 -to_step write_bitstream+wait_on_run impl_1
+ template/xilinx-vivado/project.tcl.mustache view
@@ -0,0 +1,113 @@+set origin_dir "{{rootDir}}"+set _xil_proj_name_ "{{project}}"++set orig_proj_dir "[file normalize "$origin_dir/"]"++# Create project+create_project ${_xil_proj_name_} ./${_xil_proj_name_} -force -part {{part}}++# Set the directory path for the new project+set proj_dir [get_property directory [current_project]]++# Set project properties+set obj [current_project]+set_property -name "board_part" -value "{{board}}" -objects $obj+set_property -name "default_lib" -value "xil_defaultlib" -objects $obj+++# Create 'sources_1' fileset (if not found)+if {[string equal [get_filesets -quiet sources_1] ""]} {+ create_fileset -srcset sources_1+}+set obj [get_filesets sources_1]++set files [list \+ {{#srcs}}+ [file normalize "${origin_dir}/{{fileName}}" ]\+ {{/srcs}}+]+add_files -norecurse -fileset $obj $files+set_property -name "top" -value "{{top}}" -objects $obj++{{#coreSrcs.nonempty}}+set files [list \+ {{#coreSrcs.items}}+ [file normalize "${origin_dir}/{{fileName}}" ]\+ {{/coreSrcs.items}}+]+set imported_files [import_files -fileset sources_1 $files]+{{/coreSrcs.nonempty}}++{{#ipcores}}+set file "{{name}}/{{name}}.xci"+set file_obj [get_files -of_objects [get_filesets sources_1] [list "*$file"]]+set_property -name "generate_files_for_reference" -value "0" -objects $file_obj+set_property -name "registered_with_manager" -value "1" -objects $file_obj+if { ![get_property "is_locked" $file_obj] } {+ set_property -name "synth_checkpoint_mode" -value "Singular" -objects $file_obj+}+{{/ipcores}}+++# Create 'constrs_1' fileset (if not found)+if {[string equal [get_filesets -quiet constrs_1] ""]} {+ create_fileset -constrset constrs_1+}+set obj [get_filesets constrs_1]++{{#constraintSrcs}}+set file [file normalize "${origin_dir}/{{fileName}}"]+set file_imported [add_files -norecurse -fileset $obj $file]+set file_obj [get_files -of_objects [get_filesets constrs_1] [list "*$file"]]+set_property -name "file_type" -value "XDC" -objects $file_obj+{{/constraintSrcs}}++# Create 'sim_1' fileset (if not found)+if {[string equal [get_filesets -quiet sim_1] ""]} {+ create_fileset -simset sim_1+}+set obj [get_filesets sim_1]+set_property -name "top" -value "{{top}}" -objects $obj+set_property -name "top_lib" -value "xil_defaultlib" -objects $obj++# Create 'synth_1' run (if not found)+if {[string equal [get_runs -quiet synth_1] ""]} {+ create_run -name synth_1 -part {{part}} -flow {Vivado Synthesis 2019} -strategy "Vivado Synthesis Defaults" -report_strategy {No Reports} -constrset constrs_1+} else {+ set_property strategy "Vivado Synthesis Defaults" [get_runs synth_1]+ set_property flow "Vivado Synthesis 2019" [get_runs synth_1]+}+set obj [get_runs synth_1]+set_property set_report_strategy_name 1 $obj+set_property report_strategy {Vivado Synthesis Default Reports} $obj+set_property set_report_strategy_name 0 $obj+# Create 'synth_1_synth_report_utilization_0' report (if not found)+if { [ string equal [get_report_configs -of_objects [get_runs synth_1] synth_1_synth_report_utilization_0] "" ] } {+ create_report_config -report_name synth_1_synth_report_utilization_0 -report_type report_utilization:1.0 -steps synth_design -runs synth_1+}+set obj [get_report_configs -of_objects [get_runs synth_1] synth_1_synth_report_utilization_0]+if { $obj != "" } {++}+set obj [get_runs synth_1]+set_property -name "strategy" -value "Vivado Synthesis Defaults" -objects $obj++# set the current synth run+current_run -synthesis [get_runs synth_1]++# Create 'impl_1' run (if not found)+if {[string equal [get_runs -quiet impl_1] ""]} {+ create_run -name impl_1 -part {{part}} -flow {Vivado Implementation 2019} -strategy "Vivado Implementation Defaults" -report_strategy {No Reports} -constrset constrs_1 -parent_run synth_1+} else {+ set_property strategy "Vivado Implementation Defaults" [get_runs impl_1]+ set_property flow "Vivado Implementation 2019" [get_runs impl_1]+}+set obj [get_runs impl_1]+set_property set_report_strategy_name 1 $obj+set_property report_strategy {Vivado Implementation Default Reports} $obj+set_property set_report_strategy_name 0 $obj++# set the current impl run+current_run -implementation [get_runs impl_1]++puts "INFO: Project created:${_xil_proj_name_}"
+ template/xilinx-vivado/upload.tcl.mustache view
@@ -0,0 +1,14 @@+open_hw+connect_hw_server+open_hw_target++set devs [get_hw_devices {{targetDevice}}_0]+set dev [lindex $devs 0]++current_hw_device $devs+refresh_hw_device -update_hw_probes false $dev+set_property PROGRAM.FILE {{project}}/{{project}}.runs/impl_1/{{top}}.bit $dev++program_hw_devices $dev+refresh_hw_device $dev+