Skip to content

Commit

Permalink
Remove create_clock statements on negative clocks in Clash generated SDC
Browse files Browse the repository at this point in the history
  • Loading branch information
martijnbastiaan committed Jul 6, 2023
1 parent d2d2c17 commit ecfd2fa
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 23 deletions.
92 changes: 69 additions & 23 deletions bittide-instances/bin/Shake.hs
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,16 @@ module Main where
import Prelude

import Control.Applicative (liftA2)
import Control.DeepSeq (force)
import Control.Monad.Extra (ifM, unlessM, when)
import Data.Foldable (for_)
import Data.List (isPrefixOf, isInfixOf)
import Development.Shake
import GHC.Stack (HasCallStack)
import Language.Haskell.TH (nameBase)
import System.Console.ANSI (setSGR)
import System.Directory (getCurrentDirectory, setCurrentDirectory)
import System.FilePath (isDrive, (</>), takeDirectory)
import System.FilePath (isDrive, (</>), takeDirectory, replaceFileName)
import System.Process (readProcess)

import Paths_bittide_instances
Expand Down Expand Up @@ -70,6 +72,44 @@ In the future we might be more precise in our source discovery process.
handle this case in Shake either.
-}

-- | "Negative clock pins" used to work around:
--
-- https://github.com/clash-lang/clash-compiler/issues/2518
--
-- List obtained by scanning our board's XDC file:
--
-- @
-- grep -i -E '(clk|clock)' KCU105_Rev1.0_02292016.xdc | grep -o -i -E '".*_n"' | sort | uniq
-- @
--
negativeClocks :: [String]
negativeClocks =
[ "CLK_125MHZ_N"
, "FMC_HPC_CLK0_M2C_N"
, "FMC_HPC_CLK1_M2C_N"
, "FMC_HPC_GBTCLK0_M2C_C_N"
, "FMC_HPC_GBTCLK1_M2C_C_N"
, "FMC_LPC_CLK0_M2C_N"
, "FMC_LPC_CLK1_M2C_N"
, "FMC_LPC_GBTCLK0_M2C_C_N"
, "MGT_SI570_CLOCK_C_N"
, "PCIE_CLK_QO_N"
, "REC_CLOCK_C_N"
, "SGMIICLK_N"
, "SMA_MGT_REFCLK_C_N"
, "SYSCLK_300_N"
, "USER_SI570_CLOCK_N"
, "USER_SMA_CLOCK_N"
]

-- | Does this line (from an XDC file) create a clock from 'negativeClocks'?
isNegativeCreateClock :: String -> Bool
isNegativeCreateClock line =
"create_clock" `isPrefixOf` line && containsNegativeClock
where
containsNegativeClock = or [nm `isInfixOf` line | nm <- tclNegativeClocks]
tclNegativeClocks = ["{" <> nm <> "}" | nm <- negativeClocks]

-- | Get all files whose changes will trigger an HDL rebuild. Because we lack a
-- reliable way to determine which files should trigger a rebuild, this function
-- returns a (very) pessimistic list: all files in the project's directory,
Expand Down Expand Up @@ -201,7 +241,7 @@ shakeOpts :: ShakeOptions
shakeOpts = shakeOptions
{ shakeFiles = buildDir
, shakeChange = ChangeDigest
, shakeVersion = "6"
, shakeVersion = "7"
}

-- | Run Vivado on given TCL script
Expand Down Expand Up @@ -284,6 +324,7 @@ main = do
-- TODO: Dehardcode these paths. They're currently hardcoded in both the
-- TCL and here, which smells.
manifestPath = getManifestLocation clashBuildDir targetName
clashSdcPath = replaceFileName manifestPath (nameBase targetName <> ".sdc")
synthesisDir = vivadoBuildDir </> show targetName
checkpointsDir = synthesisDir </> "checkpoints"
netlistDir = synthesisDir </> "netlist"
Expand All @@ -310,12 +351,6 @@ main = do
bitstreamPath = synthesisDir </> "bitstream.bit"
probesPath = synthesisDir </> "probes.ltx"

postSynthMethodologyPath = reportDir </> "post_synth_methodology.rpt"
postSynthTimingSummaryPath = reportDir </> "post_synth_timing_summary.rpt"

postPlaceMethodologyPath = reportDir </> "post_place_methodology.rpt"
postPlaceTimingSummaryPath = reportDir </> "post_place_timing_summary.rpt"

postRouteMethodologyPath = reportDir </> "post_route_methodology.rpt"
postRouteTimingSummaryPath = reportDir </> "post_route_timing_summary.rpt"
postRouteTimingPath = reportDir </> "post_route_timing.rpt"
Expand Down Expand Up @@ -347,6 +382,11 @@ main = do
-- printed in bold text. Reset manually:
liftIO (setSGR [])

-- XXX: Workaround https://github.com/clash-lang/clash-compiler/issues/2518
sdc0 <- liftIO (force . lines <$> readFile clashSdcPath)
let sdc1 = filter (not . isNegativeCreateClock) sdc0
writeFileChanged clashSdcPath (unlines sdc1)

produces [path]

-- Synthesis
Expand Down Expand Up @@ -381,11 +421,6 @@ main = do
-- also depend on the dependencies' manifest files, etc.
need [runSynthTclPath, manifestPath]
vivadoFromTcl runSynthTclPath
liftIO $
meetsDrcOrError
postSynthMethodologyPath
postSynthTimingSummaryPath
postSynthCheckpointPath

-- Placement
runPlaceTclPath %> \path -> do
Expand All @@ -394,11 +429,6 @@ main = do
(postPlaceCheckpointPath : placeReportPaths) |%> \_ -> do
need [runPlaceTclPath, postSynthCheckpointPath]
vivadoFromTcl runPlaceTclPath
liftIO $
meetsDrcOrError
postPlaceMethodologyPath
postPlaceTimingSummaryPath
postPlaceCheckpointPath

-- Routing
runRouteTclPath %> \path -> do
Expand All @@ -408,11 +438,27 @@ main = do
need [runRouteTclPath, postPlaceCheckpointPath]
vivadoFromTcl runRouteTclPath

liftIO $
meetsDrcOrError
postRouteMethodologyPath
postRouteTimingSummaryPath
postRouteCheckpointPath
-- Design should meet design rule checks (DRC).
liftIO $ unlessM
( liftA2
(&&)
(meetsTiming postRouteMethodologyPath)
(meetsTiming postRouteTimingSummaryPath)
)
(error [I.i|
Design did not meet design rule checks (DRC). Check out the timing summary at:

#{postRouteTimingSummaryPath}

Check out the methodology report at:

#{postRouteMethodologyPath}

You can investigate interactively by opening the latest checkpoint with Vivado:

vivado #{postRouteCheckpointPath}

|])

-- Design should meet timing post routing. Note that this is not a
-- requirement after synthesis as many of the optimizations only follow
Expand Down
1 change: 1 addition & 0 deletions bittide-instances/bittide-instances.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ executable shake
, clash-ghc
, clash-lib
, cryptohash-sha256
, deepseq
, directory
, extra
, Glob
Expand Down

0 comments on commit ecfd2fa

Please sign in to comment.