From 7a974b64edeac68cb079cfe338ae37e4e7df6857 Mon Sep 17 00:00:00 2001 From: Ryan Slawson Date: Tue, 17 Dec 2024 10:10:11 +0100 Subject: [PATCH] Add driver for SwCc after rebase. --- .github/synthesis/debug.json | 3 + bittide-experiments/src/Bittide/Plot.hs | 2 +- bittide-instances/bittide-instances.cabal | 3 +- .../data/constraints/fullMeshHwCcTest.xdc | 44 ---- .../constraints/fullMeshHwCcWithRiscvTest.xdc | 1 - .../data/constraints/fullMeshSwCcTest.xdc | 1 - .../data/constraints/hwCcTopologyTest.xdc | 1 - .../data/constraints/jtag_pmod1-alt.xdc | 16 ++ .../data/constraints/swCcTopologyTest.xdc | 45 +++- bittide-instances/data/openocd/start.sh | 18 +- .../Instances/Hitl/Driver/SwCcTopologies.hs | 238 +++++++++++++++++ .../Bittide/Instances/Hitl/Driver/VexRiscv.hs | 2 +- .../src/Bittide/Instances/Hitl/IlaPlot.hs | 2 +- .../Bittide/Instances/Hitl/SwCcTopologies.hs | 75 ++++-- .../Bittide/Instances/Hitl/Utils/Program.hs | 28 ++ .../src/Bittide/Instances/Pnr/ClockControl.hs | 28 -- bittide/bittide.cabal | 1 - bittide/src/Bittide/ClockControl/Callisto.hs | 246 ------------------ .../Bittide/ClockControl/Callisto/Types.hs | 3 + .../src/Bittide/ClockControl/CallistoSw.hs | 63 +++-- 20 files changed, 444 insertions(+), 376 deletions(-) create mode 100644 .github/synthesis/debug.json delete mode 100644 bittide-instances/data/constraints/fullMeshHwCcTest.xdc delete mode 120000 bittide-instances/data/constraints/fullMeshHwCcWithRiscvTest.xdc delete mode 120000 bittide-instances/data/constraints/fullMeshSwCcTest.xdc delete mode 120000 bittide-instances/data/constraints/hwCcTopologyTest.xdc create mode 100644 bittide-instances/data/constraints/jtag_pmod1-alt.xdc mode change 120000 => 100644 bittide-instances/data/constraints/swCcTopologyTest.xdc create mode 100644 bittide-instances/src/Bittide/Instances/Hitl/Driver/SwCcTopologies.hs delete mode 100644 bittide-instances/src/Bittide/Instances/Pnr/ClockControl.hs delete mode 100644 bittide/src/Bittide/ClockControl/Callisto.hs diff --git a/.github/synthesis/debug.json b/.github/synthesis/debug.json new file mode 100644 index 000000000..bde75c045 --- /dev/null +++ b/.github/synthesis/debug.json @@ -0,0 +1,3 @@ +[ + {"top": "swCcTopologyTest", "stage": "test"} +] diff --git a/bittide-experiments/src/Bittide/Plot.hs b/bittide-experiments/src/Bittide/Plot.hs index ea527f8a7..91aae3219 100644 --- a/bittide-experiments/src/Bittide/Plot.hs +++ b/bittide-experiments/src/Bittide/Plot.hs @@ -41,7 +41,7 @@ import Graphics.Matplotlib ( import Graphics.Matplotlib qualified as MP (plot) import Bittide.ClockControl (RelDataCount) -import Bittide.ClockControl.Callisto (ReframingState (..)) +import Bittide.ClockControl.Callisto.Types (ReframingState (..)) import Bittide.ClockControl.StabilityChecker qualified as SC (StabilityIndication (..)) import Bittide.Topology diff --git a/bittide-instances/bittide-instances.cabal b/bittide-instances/bittide-instances.cabal index a9790f8ff..843a5a299 100644 --- a/bittide-instances/bittide-instances.cabal +++ b/bittide-instances/bittide-instances.cabal @@ -92,6 +92,7 @@ common common-options clash-prelude, clash-protocols, clash-vexriscv, + clock, constraints >=0.13.3 && <0.15, containers, cryptohash-sha256, @@ -132,6 +133,7 @@ library Bittide.Instances.Hitl.BoardTest Bittide.Instances.Hitl.DnaOverSerial Bittide.Instances.Hitl.Driver.DnaOverSerial + Bittide.Instances.Hitl.Driver.SwCcTopologies Bittide.Instances.Hitl.Driver.VexRiscv Bittide.Instances.Hitl.Driver.VexRiscvTcp Bittide.Instances.Hitl.Ethernet @@ -151,7 +153,6 @@ library Bittide.Instances.Hitl.Utils.Vivado Bittide.Instances.Hitl.VexRiscv Bittide.Instances.Pnr.Calendar - Bittide.Instances.Pnr.ClockControl Bittide.Instances.Pnr.Counter Bittide.Instances.Pnr.ElasticBuffer Bittide.Instances.Pnr.Ethernet diff --git a/bittide-instances/data/constraints/fullMeshHwCcTest.xdc b/bittide-instances/data/constraints/fullMeshHwCcTest.xdc deleted file mode 100644 index b1776818f..000000000 --- a/bittide-instances/data/constraints/fullMeshHwCcTest.xdc +++ /dev/null @@ -1,44 +0,0 @@ -# SPDX-FileCopyrightText: 2024 Google LLC -# -# SPDX-License-Identifier: Apache-2.0 - -set_property BOARD_PART_PIN sysclk_125_n [get_ports SYSCLK_125_n] -set_property BOARD_PART_PIN sysclk_125_p [get_ports SYSCLK_125_p] -set_property BOARD_PART_PIN sma_mgt_refclk_n [get_ports SMA_MGT_REFCLK_C_n] -set_property BOARD_PART_PIN sma_mgt_refclk_p [get_ports SMA_MGT_REFCLK_C_p] - -set_property BOARD_PART_PIN GPIO_LED_0_LS [get_ports spiDone] - -set_clock_groups \ - -asynchronous \ - -group [get_clocks -include_generated_clocks {SYSCLK_125_p}] \ - -group [get_clocks -include_generated_clocks {SMA_MGT_REFCLK_C_p}] - -# Color | FPGA pin | LVLSHFT | Connection -# --------|---------------|---------------|------------------ -# Grey | PMOD0_0 | IO1 | SYNC_OUT (legacy) -# Blue | PMOD0_1 | IO2 | FINC -# Yellow | PMOD0_2 | IO3 | MOSI/SDIO -# Red | PMOD0_3 | IO4 | SCLK -# White | PMOD0_4 | IO5 | SYNC_IN (legacy) -# Purple | PMOD0_5 | IO6 | FDEC -# Green | PMOD0_6 | IO7 | CSB -# Orange | PMOD0_7 | IO8 | MISO/SDO -# Black | Not connected | Not connected | -# Brown | PMOD_GND | GND | GND (SPI) - -# PMOD1_[0..7] -set_property -dict {IOSTANDARD LVCMOS12 PACKAGE_PIN AN21} [get_ports {FINC}] -set_property -dict {IOSTANDARD LVCMOS12 PACKAGE_PIN AH18} [get_ports {MOSI}] -set_property -dict {IOSTANDARD LVCMOS12 PACKAGE_PIN AM19} [get_ports {SCLK}] -set_property -dict {IOSTANDARD LVCMOS12 PACKAGE_PIN AF25} [get_ports {FDEC}] -set_property -dict {IOSTANDARD LVCMOS12 PACKAGE_PIN AE21} [get_ports {CSB}] -set_property -dict {IOSTANDARD LVCMOS12 PACKAGE_PIN AM17} [get_ports {MISO}] - -# PMOD0_3 -# set_property -dict {IOSTANDARD LVCMOS12 PACKAGE_PIN AM19} [get_ports {shared_reset_btn}] - -# USER SMA GPIO_P -set_property -dict {IOSTANDARD LVCMOS18 PACKAGE_PIN H27} [get_ports {SYNC_IN}] -# USER_SMA_GPIO_N (connected on node 0 to SYNC_IN of all nodes) -set_property -dict {IOSTANDARD LVCMOS18 PACKAGE_PIN G27} [get_ports {SYNC_OUT}] diff --git a/bittide-instances/data/constraints/fullMeshHwCcWithRiscvTest.xdc b/bittide-instances/data/constraints/fullMeshHwCcWithRiscvTest.xdc deleted file mode 120000 index 54029713e..000000000 --- a/bittide-instances/data/constraints/fullMeshHwCcWithRiscvTest.xdc +++ /dev/null @@ -1 +0,0 @@ -fullMeshHwCcTest.xdc \ No newline at end of file diff --git a/bittide-instances/data/constraints/fullMeshSwCcTest.xdc b/bittide-instances/data/constraints/fullMeshSwCcTest.xdc deleted file mode 120000 index 54029713e..000000000 --- a/bittide-instances/data/constraints/fullMeshSwCcTest.xdc +++ /dev/null @@ -1 +0,0 @@ -fullMeshHwCcTest.xdc \ No newline at end of file diff --git a/bittide-instances/data/constraints/hwCcTopologyTest.xdc b/bittide-instances/data/constraints/hwCcTopologyTest.xdc deleted file mode 120000 index 54029713e..000000000 --- a/bittide-instances/data/constraints/hwCcTopologyTest.xdc +++ /dev/null @@ -1 +0,0 @@ -fullMeshHwCcTest.xdc \ No newline at end of file diff --git a/bittide-instances/data/constraints/jtag_pmod1-alt.xdc b/bittide-instances/data/constraints/jtag_pmod1-alt.xdc new file mode 100644 index 000000000..a74cfa067 --- /dev/null +++ b/bittide-instances/data/constraints/jtag_pmod1-alt.xdc @@ -0,0 +1,16 @@ +# SPDX-FileCopyrightText: 2024 Google LLC +# +# SPDX-License-Identifier: Apache-2.0 + +# PMOD1_[0..7] +# Note that there are no clock capable pins in this list +set_property -dict {IOSTANDARD LVCMOS12 PACKAGE_PIN AP16} [get_ports {JTAG_TCK}] +set_property -dict {IOSTANDARD LVCMOS12 PACKAGE_PIN AP15} [get_ports {JTAG_TDI}] +set_property -dict {IOSTANDARD LVCMOS12 PACKAGE_PIN AM16} [get_ports {JTAG_RST}] +set_property -dict {IOSTANDARD LVCMOS12 PACKAGE_PIN AM15} [get_ports {JTAG_TMS}] +set_property -dict {IOSTANDARD LVCMOS12 PACKAGE_PIN AN18} [get_ports {JTAG_TDO}] + +# PMOD1 does not have a clock capable pin. To Vivado's credit, it refuses to +# produce a bitstream if we try to use a non-clock capable pin as a clock. With +# the following line, we tell Vivado to ignore this warning. +set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets JTAG_TCK] diff --git a/bittide-instances/data/constraints/swCcTopologyTest.xdc b/bittide-instances/data/constraints/swCcTopologyTest.xdc deleted file mode 120000 index 54029713e..000000000 --- a/bittide-instances/data/constraints/swCcTopologyTest.xdc +++ /dev/null @@ -1 +0,0 @@ -fullMeshHwCcTest.xdc \ No newline at end of file diff --git a/bittide-instances/data/constraints/swCcTopologyTest.xdc b/bittide-instances/data/constraints/swCcTopologyTest.xdc new file mode 100644 index 000000000..b1776818f --- /dev/null +++ b/bittide-instances/data/constraints/swCcTopologyTest.xdc @@ -0,0 +1,44 @@ +# SPDX-FileCopyrightText: 2024 Google LLC +# +# SPDX-License-Identifier: Apache-2.0 + +set_property BOARD_PART_PIN sysclk_125_n [get_ports SYSCLK_125_n] +set_property BOARD_PART_PIN sysclk_125_p [get_ports SYSCLK_125_p] +set_property BOARD_PART_PIN sma_mgt_refclk_n [get_ports SMA_MGT_REFCLK_C_n] +set_property BOARD_PART_PIN sma_mgt_refclk_p [get_ports SMA_MGT_REFCLK_C_p] + +set_property BOARD_PART_PIN GPIO_LED_0_LS [get_ports spiDone] + +set_clock_groups \ + -asynchronous \ + -group [get_clocks -include_generated_clocks {SYSCLK_125_p}] \ + -group [get_clocks -include_generated_clocks {SMA_MGT_REFCLK_C_p}] + +# Color | FPGA pin | LVLSHFT | Connection +# --------|---------------|---------------|------------------ +# Grey | PMOD0_0 | IO1 | SYNC_OUT (legacy) +# Blue | PMOD0_1 | IO2 | FINC +# Yellow | PMOD0_2 | IO3 | MOSI/SDIO +# Red | PMOD0_3 | IO4 | SCLK +# White | PMOD0_4 | IO5 | SYNC_IN (legacy) +# Purple | PMOD0_5 | IO6 | FDEC +# Green | PMOD0_6 | IO7 | CSB +# Orange | PMOD0_7 | IO8 | MISO/SDO +# Black | Not connected | Not connected | +# Brown | PMOD_GND | GND | GND (SPI) + +# PMOD1_[0..7] +set_property -dict {IOSTANDARD LVCMOS12 PACKAGE_PIN AN21} [get_ports {FINC}] +set_property -dict {IOSTANDARD LVCMOS12 PACKAGE_PIN AH18} [get_ports {MOSI}] +set_property -dict {IOSTANDARD LVCMOS12 PACKAGE_PIN AM19} [get_ports {SCLK}] +set_property -dict {IOSTANDARD LVCMOS12 PACKAGE_PIN AF25} [get_ports {FDEC}] +set_property -dict {IOSTANDARD LVCMOS12 PACKAGE_PIN AE21} [get_ports {CSB}] +set_property -dict {IOSTANDARD LVCMOS12 PACKAGE_PIN AM17} [get_ports {MISO}] + +# PMOD0_3 +# set_property -dict {IOSTANDARD LVCMOS12 PACKAGE_PIN AM19} [get_ports {shared_reset_btn}] + +# USER SMA GPIO_P +set_property -dict {IOSTANDARD LVCMOS18 PACKAGE_PIN H27} [get_ports {SYNC_IN}] +# USER_SMA_GPIO_N (connected on node 0 to SYNC_IN of all nodes) +set_property -dict {IOSTANDARD LVCMOS18 PACKAGE_PIN G27} [get_ports {SYNC_OUT}] diff --git a/bittide-instances/data/openocd/start.sh b/bittide-instances/data/openocd/start.sh index 84880eaa0..2040d934c 100755 --- a/bittide-instances/data/openocd/start.sh +++ b/bittide-instances/data/openocd/start.sh @@ -2,5 +2,21 @@ # SPDX-FileCopyrightText: 2024 Google LLC # # SPDX-License-Identifier: Apache-2.0 +set -e + +# Default stdout to /dev/null +OPENOCD_STDOUT_LOG="${OPENOCD_STDOUT_LOG:-/dev/null}" +stdout_dir=$(dirname "$(realpath ${OPENOCD_STDOUT_LOG})") +mkdir -p "${stdout_dir}" +OPENOCD_STDERR_LOG="$(realpath ${OPENOCD_STDOUT_LOG})" + +# Default stderr to /dev/null +OPENOCD_STDERR_LOG="${OPENOCD_STDERR_LOG:-/dev/null}" +stderr_dir=$(dirname "${OPENOCD_STDERR_LOG}") +mkdir -p "${stderr_dir}" +OPENOCD_STDERR_LOG="$(realpath ${OPENOCD_STDERR_LOG})" + cd $(dirname $0) -exec openocd-vexriscv -f ports.tcl -f sipeed.tcl -f vexriscv_init.tcl $@ +openocd-vexriscv -f ports.tcl -f sipeed.tcl -f vexriscv_init.tcl $@ \ + > >(tee "${OPENOCD_STDOUT_LOG}") \ + 2> >(tee "${OPENOCD_STDERR_LOG}" >&2) diff --git a/bittide-instances/src/Bittide/Instances/Hitl/Driver/SwCcTopologies.hs b/bittide-instances/src/Bittide/Instances/Hitl/Driver/SwCcTopologies.hs new file mode 100644 index 000000000..fa5a6cfaf --- /dev/null +++ b/bittide-instances/src/Bittide/Instances/Hitl/Driver/SwCcTopologies.hs @@ -0,0 +1,238 @@ +-- SPDX-FileCopyrightText: 2024 Google LLC +-- +-- SPDX-License-Identifier: Apache-2.0 +{-# LANGUAGE NumericUnderscores #-} +{-# LANGUAGE OverloadedRecordDot #-} + +module Bittide.Instances.Hitl.Driver.SwCcTopologies where + +import Clash.Prelude + +import Project.FilePath +import Project.Handle + +import Vivado +import Vivado.Tcl + +import Bittide.Hitl +import Bittide.Instances.Hitl.Setup (demoRigInfo) +import Bittide.Instances.Hitl.Utils.Gdb +import Bittide.Instances.Hitl.Utils.Program +import Bittide.Instances.Hitl.Utils.Vivado + +import Control.Exception (SomeException, displayException, handle, throw) +import Control.Monad (zipWithM_) +import Data.Foldable (sequenceA_) +import Data.Maybe (fromMaybe) +import System.Clock (Clock (Monotonic), diffTimeSpec, getTime, toNanoSecs) +import System.Exit +import System.FilePath +import System.IO +import System.Timeout (timeout) + +import qualified Data.List as L + +getProbeProgEnTcl :: String +getProbeProgEnTcl = getTestProbeTcl "*vioHitlt/probe_prog_en" + +data TestStatus = TestRunning | TestDone Bool deriving (Eq) + +driverFunc :: + VivadoHandle -> + String -> + FilePath -> + [(HwTarget, DeviceInfo)] -> + IO ExitCode +driverFunc v _name ilaPath targets = do + putStrLn + $ "Running Driver function for targets " + <> show ((\(_, info) -> info.deviceId) <$> targets) + + startTime <- getTime Monotonic + + let + calcTimeSpentMs = (`div` 1000000) . toNanoSecs . diffTimeSpec startTime <$> getTime Monotonic + + catchError :: DeviceInfo -> SomeException -> IO ExitCode + catchError d ex = do + putStrLn $ "Test failed on device " <> d.deviceId <> " with: " <> displayException ex + pure $ ExitFailure 2 + + tryWithTimeout :: String -> Int -> IO a -> IO a + tryWithTimeout actionName dur action = do + result <- timeout dur action + case result of + Nothing -> do + error $ "Timeout while performing action: " <> actionName + Just r -> pure r + + startPrograms :: + (HwTarget, DeviceInfo) -> + IO (ProcessStdIoHandles, ProcessStdIoHandles, IO ()) + startPrograms (hwT, d) = do + putStrLn $ "Starting OpenOCD, and GDB for target " <> show d.deviceId + + openHwT v hwT + execCmd_ v "set_property" ["PROBES.FILE", embrace ilaPath, "[current_hw_device]"] + refresh_hw_device v [] + execCmd_ v "set_property" ["OUTPUT_VALUE", "1", getProbeProgEnTcl] + commit_hw_vio v ["[get_hw_vios]"] + + let targetId = idFromHwT hwT + let targetIndex = fromMaybe 9 $ L.findIndex (\di -> di.deviceId == targetId) demoRigInfo + let gdbPort = 3333 + targetIndex + + projectDir <- findParentContaining "cabal.project" + let + ocdStdout = projectDir "_build" "hitl" "openocd-" <> show targetIndex <> "-stdout.log" + ocdStderr = projectDir "_build" "hitl" "openocd-" <> show targetIndex <> "-stderr.log" + putStrLn $ "logging OpenOCD stdout to `" <> ocdStdout <> "`" + putStrLn $ "logging OpenOCD stderr to `" <> ocdStderr <> "`" + + putStrLn "Starting OpenOCD..." + (ocd, ocdClean) <- + startOpenOcdWithEnv + [("OPENOCD_STDOUT_LOG", ocdStdout), ("OPENOCD_STDERR_LOG", ocdStderr)] + d.usbAdapterLocation + gdbPort + hSetBuffering ocd.stderrHandle LineBuffering + tryWithTimeout "Waiting for OpenOCD to start" 15_000_000 + $ expectLine ocd.stderrHandle openOcdWaitForHalt + + (gdb, gdbClean) <- startGdb + hSetBuffering gdb.stdinHandle LineBuffering + + runGdbCommands + gdb.stdinHandle + [ "set logging file ./_build/hitl/gdb-out-" <> show targetIndex <> ".log" + , "set logging overwrite on" + , "set logging enabled on" + , "file \"./_build/cargo/firmware-binaries/riscv32imc-unknown-none-elf/release/clock-control\"" + , "target extended-remote :" <> show gdbPort + ] + + return (ocd, gdb, gdbClean >> ocdClean) + + loadBinary :: + (HwTarget, DeviceInfo) -> + (ProcessStdIoHandles, ProcessStdIoHandles, IO ()) -> + IO () + loadBinary (hwT, d) (_, gdb, cleanup) = + handle (\e -> catchError d e >> cleanup >> throw e) $ do + putStrLn $ "Loading binary onto target " <> show d.deviceId + runGdbCommands gdb.stdinHandle ["load"] + tryWithTimeout "Waiting for program load to finish" 120_000_000 + $ expectLine gdb.stdoutHandle gdbWaitForLoad + openHwT v hwT + execCmd_ v "set_property" ["PROBES.FILE", embrace ilaPath, "[current_hw_device]"] + refresh_hw_device v [] + execCmd_ v "set_property" ["OUTPUT_VALUE", "0", getProbeProgEnTcl] + commit_hw_vio v ["[get_hw_vios]"] + + startBinary :: + (HwTarget, DeviceInfo) -> + (ProcessStdIoHandles, ProcessStdIoHandles, IO ()) -> + IO () + startBinary (hwT, d) (_, gdb, cleanup) = + handle (\e -> catchError d e >> cleanup >> throw e) $ do + putStrLn $ "Starting binary on target " <> show d.deviceId + openHwT v hwT + execCmd_ v "set_property" ["PROBES.FILE", embrace ilaPath, "[current_hw_device]"] + refresh_hw_device v [] + execCmd_ v "set_property" ["OUTPUT_VALUE", "0", getProbeProgEnTcl] + execCmd_ v "set_property" ["OUTPUT_VALUE", "1", getProbeTestStartTcl] + commit_hw_vio v ["[get_hw_vios]"] + runGdbCommands gdb.stdinHandle ["continue"] + + getTestsStatus :: + [(HwTarget, DeviceInfo)] -> + [(ProcessStdIoHandles, ProcessStdIoHandles, IO ())] -> + [TestStatus] -> + IO [Maybe TestStatus] + getTestsStatus [] _ _ = return [] + getTestsStatus _ [] _ = return [] + getTestsStatus _ _ [] = return [] + getTestsStatus ((hwT, _) : hwtdRest) (_ : hdlsRest) (status : statusRest) = do + case status of + TestRunning -> do + timeSpent <- calcTimeSpentMs + rest <- getTestsStatus hwtdRest hdlsRest statusRest + if timeSpent < testTimeoutMs + then do + openHwT v hwT + execCmd_ v "set_property" ["PROBES.FILE", embrace ilaPath, "[current_hw_device]"] + refresh_hw_device v [] + testDone <- execCmd v "get_property" ["INPUT_VALUE", getProbeTestDoneTcl] + testSuccess <- execCmd v "get_property" ["INPUT_VALUE", getProbeTestSuccessTcl] + let newStatus = if testDone == "1" then TestDone (testSuccess == "1") else TestRunning + pure $ (Just newStatus) : rest + else pure $ Nothing : rest + other -> do + rest <- getTestsStatus hwtdRest hdlsRest statusRest + pure $ (Just other) : rest + + getTestResults :: + [(HwTarget, DeviceInfo)] -> + [(ProcessStdIoHandles, ProcessStdIoHandles, IO ())] -> + Maybe [TestStatus] -> + IO [ExitCode] + getTestResults tgts hdls prevStatus0 = do + let prevStatus1 = fromMaybe (L.replicate (L.length tgts) TestRunning) prevStatus0 + testsStatus <- getTestsStatus tgts hdls prevStatus1 + case sequence testsStatus of + Just statuses -> + if not (TestRunning `L.elem` statuses) + then do + let + go (TestDone True) = ExitSuccess + go _ = ExitFailure 2 + exitCodes = go <$> statuses + return exitCodes + else getTestResults tgts hdls (Just statuses) + Nothing -> do + let + go :: + (HwTarget, DeviceInfo) -> + (ProcessStdIoHandles, ProcessStdIoHandles, IO ()) -> + Maybe TestStatus -> + IO () + go _ (_, _, cleanup) (Just _) = cleanup + go (_, d) (_, _, cleanup) Nothing = do + cleanup + putStrLn $ "Test timed out on target " <> show d.deviceId + sequenceA_ (L.zipWith3 go tgts hdls testsStatus) + error "Test failed on previously listed timeouts." + + deassertStartTest :: + (HwTarget, DeviceInfo) -> + (ProcessStdIoHandles, ProcessStdIoHandles, IO ()) -> + IO () + deassertStartTest (hwT, d) (_, _, cleanup) = + handle (\e -> catchError d e >> cleanup >> throw e) $ do + openHwT v hwT + execCmd_ v "set_property" ["PROBES.FILE", embrace ilaPath, "[current_hw_device]"] + refresh_hw_device v [] + execCmd_ v "set_property" ["OUTPUT_VALUE", "1", getProbeTestStartTcl] + commit_hw_vio v ["[get_hw_vios]"] + cleanup + + targetProgs <- mapM startPrograms targets + + zipWithM_ loadBinary targets targetProgs + + zipWithM_ startBinary targets targetProgs + + testResults <- getTestResults targets targetProgs Nothing + + let + exitCode = + L.foldl + (\acc code -> if code == ExitSuccess then acc else code) + ExitSuccess + testResults + + zipWithM_ deassertStartTest targets targetProgs + + return exitCode + where + testTimeoutMs = 60_000 :: Integer diff --git a/bittide-instances/src/Bittide/Instances/Hitl/Driver/VexRiscv.hs b/bittide-instances/src/Bittide/Instances/Hitl/Driver/VexRiscv.hs index 199439194..a89d12252 100644 --- a/bittide-instances/src/Bittide/Instances/Hitl/Driver/VexRiscv.hs +++ b/bittide-instances/src/Bittide/Instances/Hitl/Driver/VexRiscv.hs @@ -130,7 +130,7 @@ driverFunc v _name ilaPath targets = do , "load" ] - tryWithTimeout "Waiting for \"load dome\"" 120_000_000 + tryWithTimeout "Waiting for \"load done\"" 120_000_000 $ expectLine gdb.stdoutHandle gdbWaitForLoad -- break test diff --git a/bittide-instances/src/Bittide/Instances/Hitl/IlaPlot.hs b/bittide-instances/src/Bittide/Instances/Hitl/IlaPlot.hs index 262d182c1..ff13ef38c 100644 --- a/bittide-instances/src/Bittide/Instances/Hitl/IlaPlot.hs +++ b/bittide-instances/src/Bittide/Instances/Hitl/IlaPlot.hs @@ -57,7 +57,7 @@ import Clash.Sized.Extra (concatUnsigneds) import Bittide.Arithmetic.Time (PeriodToCycles, trueFor) import Bittide.ClockControl (RelDataCount, SpeedChange (..)) -import Bittide.ClockControl.Callisto ( +import Bittide.ClockControl.Callisto.Types ( CallistoResult (..), ReframingState (..), ) diff --git a/bittide-instances/src/Bittide/Instances/Hitl/SwCcTopologies.hs b/bittide-instances/src/Bittide/Instances/Hitl/SwCcTopologies.hs index 02bf51db5..bcf994119 100644 --- a/bittide-instances/src/Bittide/Instances/Hitl/SwCcTopologies.hs +++ b/bittide-instances/src/Bittide/Instances/Hitl/SwCcTopologies.hs @@ -33,13 +33,14 @@ module Bittide.Instances.Hitl.SwCcTopologies ( import Clash.Explicit.Prelude hiding (PeriodToCycles) import qualified Clash.Explicit.Prelude as E import Clash.Explicit.Signal.Extra (changepoints) -import Clash.Prelude (withClockResetEnable) +import Clash.Prelude (HiddenClockResetEnable, exposeReset, hasReset, withClockResetEnable) import Data.Functor ((<&>)) import Data.Maybe (fromMaybe, isJust, isNothing) import Data.Proxy import GHC.Float.RealFracMethods (roundFloatInteger) import LiftType (liftTypeQ) +import VexRiscv (JtagIn, JtagOut) import Bittide.Arithmetic.PartsPer (PartsPer, ppm) import Bittide.Arithmetic.Time @@ -69,6 +70,7 @@ import Clash.Annotations.TH (makeTopEntity) import Clash.Class.Counter import Clash.Cores.Xilinx.GTH import Clash.Cores.Xilinx.Ila (Depth (..), IlaConfig (..), ila, ilaConfig) +import Clash.Cores.Xilinx.VIO import Clash.Cores.Xilinx.Xpm (xpmCdcArraySingle) import Clash.Cores.Xilinx.Xpm.Cdc (xpmCdcSingle) import Clash.Functor.Extra @@ -78,6 +80,7 @@ import Clash.Xilinx.ClockGen import qualified Bittide.Arithmetic.PartsPer as PartsPer import qualified Bittide.ClockControl.StabilityChecker as SI +import qualified Bittide.Instances.Hitl.Driver.SwCcTopologies as D import qualified Bittide.Transceiver as Transceiver import qualified Bittide.Transceiver.ResetManager as ResetManager import qualified Data.Map.Strict as Map (fromList) @@ -214,7 +217,9 @@ topologyTest :: "GTH_RX_PS" ::: TransceiverWires GthRxS LinkCount -> "MISO" ::: Signal Basic125 Bit -> "TEST_CFG" ::: Signal Basic125 TestConfig -> + "PROG_EN" ::: Reset Basic125 -> "CALIBRATED_SHIFT" ::: Signal Basic125 FincFdecCount -> + "JTAG" ::: Signal Basic125 JtagIn -> ( "GTH_TX_NS" ::: TransceiverWires GthTxS LinkCount , "GTH_TX_PS" ::: TransceiverWires GthTxS LinkCount , "FINC_FDEC" ::: Signal Basic125 (FINC, FDEC) @@ -235,8 +240,9 @@ topologyTest :: , "allUgnsStable" ::: Signal Basic125 Bool , "noFifoOverflows" ::: Signal Basic125 Bool , "noFifoUnderflows" ::: Signal Basic125 Bool + , "JTAG" ::: Signal Basic125 JtagOut ) -topologyTest refClk sysClk IlaControl{syncRst = rst, ..} rxNs rxPs miso cfg ccs = +topologyTest refClk sysClk IlaControl{syncRst = rst, ..} rxNs rxPs miso cfg progEn ccs jtagIn = hwSeqX fincFdecIla ( transceivers.txNs @@ -255,6 +261,7 @@ topologyTest refClk sysClk IlaControl{syncRst = rst, ..} rxNs rxPs miso cfg ccs , allUgnsStable , noFifoOverflows , noFifoUnderflows + , callistoResult.jtagOut ) where syncRst = rst `orReset` unsafeFromActiveHigh spiErr @@ -332,11 +339,35 @@ topologyTest refClk sysClk IlaControl{syncRst = rst, ..} rxNs rxPs miso cfg ccs allStable0 = callistoResult.allStable allStable1 = sticky sysClk syncRst allStable0 - ccConfig = + ccConfig :: SwControlConfig - (reframingEnabled <$> cfg) - (SNat @CccStabilityCheckerMargin) - (SNat @(CccStabilityCheckerFramesize Basic125)) + Basic125 + CccStabilityCheckerMargin + (CccStabilityCheckerFramesize Basic125) + ccConfig = SwControlConfig jtagIn (reframingEnabled <$> cfg) SNat SNat + + callistoSwClockControlInner :: + forall nLinks eBufBits dom margin framesize. + ( HiddenClockResetEnable dom + , KnownNat nLinks + , KnownNat eBufBits + , 1 <= nLinks + , 1 <= eBufBits + , nLinks + eBufBits <= 32 + , 1 <= framesize + , 1 <= DomainPeriod dom + ) => + Reset dom -> + SwControlConfig dom margin framesize -> + Signal dom (BitVector nLinks) -> + Vec nLinks (Signal dom (RelDataCount eBufBits)) -> + Signal dom (CallistoResult nLinks) + callistoSwClockControlInner extraRst a b c = + exposeReset (callistoSwClockControl a b c) newReset + where + oldReset = unsafeToActiveHigh hasReset + extraRst1 = unsafeToActiveHigh extraRst + newReset = unsafeFromActiveHigh $ oldReset .&&. extraRst1 callistoResult = callistoClockControlWithIla @LinkCount @CccBufferSize @@ -344,7 +375,7 @@ topologyTest refClk sysClk IlaControl{syncRst = rst, ..} rxNs rxPs miso cfg ccs sysClk clockControlReset ccConfig - callistoSwClockControl + (callistoSwClockControlInner progEn) IlaControl{..} (mask <$> cfg) (resize <<$>> domainDiffs) @@ -714,6 +745,7 @@ swCcTopologyTest :: "GTH_RX_NS" ::: TransceiverWires GthRxS LinkCount -> "GTH_RX_PS" ::: TransceiverWires GthRxS LinkCount -> "MISO" ::: Signal Basic125 Bit -> + "JTAG" ::: Signal Basic125 JtagIn -> ( "GTH_TX_NS" ::: TransceiverWires GthTxS LinkCount , "GTH_TX_PS" ::: TransceiverWires GthTxS LinkCount , "" @@ -727,9 +759,10 @@ swCcTopologyTest :: , "MOSI" ::: Signal Basic125 Bit , "CSB" ::: Signal Basic125 Bool ) + , "JTAG" ::: Signal Basic125 JtagOut ) -swCcTopologyTest refClkDiff sysClkDiff syncIn1 rxns rxps miso = - hwSeqX tleDebugIla (txns, txps, unbundle swFincFdecs, syncOut, spiDone, spiOut) +swCcTopologyTest refClkDiff sysClkDiff syncIn1 rxns rxps miso jtagIn = + hwSeqX tleDebugIla (txns, txps, unbundle swFincFdecs, syncOut, spiDone, spiOut, jtagOut) where refClk = ibufds_gte3 refClkDiff :: Clock Ext200 (sysClk, sysRst) = clockWizardDifferential sysClkDiff noReset @@ -788,6 +821,7 @@ swCcTopologyTest refClkDiff sysClkDiff syncIn1 rxns rxps miso = , allUgnsStable , noFifoOverflows , noFifoUnderflows + , jtagOut ) = topologyTest refClk @@ -797,7 +831,9 @@ swCcTopologyTest refClkDiff sysClkDiff syncIn1 rxns rxps miso = rxps miso cfg + progEnRst calibratedClockShift + jtagIn captureFlag = riseEvery @@ -908,8 +944,18 @@ swCcTopologyTest refClkDiff sysClkDiff syncIn1 rxns rxps miso = .&&. (not <$> (transceiversFailedAfterUp .||. startBeforeAllReady)) ) - testConfig :: Signal Basic125 (Maybe TestConfig) - testConfig = hitlVio disabled sysClk testDone testSuccess + (unbundle -> (testStart, testConfig0, progEn)) = + setName @"vioHitlt" + $ vioProbe + ("probe_test_done" :> "probe_test_success" :> Nil) + ("probe_test_start" :> "probe_test_data" :> "probe_prog_en" :> Nil) + (False, disabled, False) + sysClk + testDone + testSuccess + + testConfig = mux testStart (Just <$> testConfig0) (pure Nothing) + progEnRst = unsafeFromActiveLow progEn makeTopEntity 'swCcTopologyTest @@ -981,7 +1027,6 @@ tests = testGroup , clockOffsets = Nothing , startupDelays = toList $ repeat @FpgaCount 0 } - -- , preProc = InheritPreProcess } -- tests the given topology @@ -992,7 +1037,6 @@ tests = testGroup Vec n StartupDelay -> Topology n -> Bool -> - -- HitlTestCase HwTargetRef TestConfig CcConf () HitlTestCase HwTargetRef TestConfig CcConf tt clockShifts startDelays t r = HitlTestCase @@ -1019,7 +1063,6 @@ tests = testGroup , startupDelays = fromIntegral <$> toList startDelays , reframe = r } - -- , preProc = InheritPreProcess } maybeVecToVecMaybe :: forall n a. (KnownNat n) => Maybe (Vec n a) -> Vec n (Maybe a) @@ -1049,7 +1092,7 @@ tests = testGroup testGroup = HitlTestGroup { topEntity = 'swCcTopologyTest - , extraXdcFiles = [] + , extraXdcFiles = ["jtag_config.xdc", "jtag_pmod1-alt.xdc"] , externalHdl = [] , testCases = [ -- detect the natual clock offsets to be elided from the later tests @@ -1067,7 +1110,7 @@ tests = testGroup -- make sure the clock offsets detected during calibration is still the same , validateClockOffsetCalibration ] - , mDriverProc = Nothing + , mDriverProc = Just D.driverFunc , mPostProc = Nothing } {- FOURMOLU_ENABLE -} diff --git a/bittide-instances/src/Bittide/Instances/Hitl/Utils/Program.hs b/bittide-instances/src/Bittide/Instances/Hitl/Utils/Program.hs index 025522e06..0857ec301 100644 --- a/bittide-instances/src/Bittide/Instances/Hitl/Utils/Program.hs +++ b/bittide-instances/src/Bittide/Instances/Hitl/Utils/Program.hs @@ -64,6 +64,34 @@ startOpenOcd usbLoc gdbPort = do pure (ocdHandles', cleanupProcess ocdHandles) +startOpenOcdWithEnv :: + [(String, String)] -> String -> Int -> IO (ProcessStdIoHandles, IO ()) +startOpenOcdWithEnv extraEnv usbLoc gdbPort = do + startOpenOcdPath <- getOpenOcdStartPath + currentEnv <- getEnvironment + let + openOcdProc = + (proc startOpenOcdPath []) + { std_in = CreatePipe + , std_out = CreatePipe + , std_err = CreatePipe + , env = + Just (currentEnv <> extraEnv <> [("USB_DEVICE", usbLoc), ("GDB_PORT", show gdbPort)]) + } + + ocdHandles@(openOcdStdin, openOcdStdout, openOcdStderr, _openOcdPh) <- + createProcess openOcdProc + + let + ocdHandles' = + ProcessStdIoHandles + { stdinHandle = fromJust openOcdStdin + , stdoutHandle = fromJust openOcdStdout + , stderrHandle = fromJust openOcdStderr + } + + pure (ocdHandles', cleanupProcess ocdHandles) + withGdb :: (ProcessStdIoHandles -> IO a) -> IO a withGdb action = do (gdb, clean) <- startGdb diff --git a/bittide-instances/src/Bittide/Instances/Pnr/ClockControl.hs b/bittide-instances/src/Bittide/Instances/Pnr/ClockControl.hs deleted file mode 100644 index b6dc87ef9..000000000 --- a/bittide-instances/src/Bittide/Instances/Pnr/ClockControl.hs +++ /dev/null @@ -1,28 +0,0 @@ --- SPDX-FileCopyrightText: 2022 Google LLC --- --- SPDX-License-Identifier: Apache-2.0 - -module Bittide.Instances.Pnr.ClockControl where - -import Clash.Prelude - -import Bittide.ClockControl -import Bittide.ClockControl.Callisto -import Bittide.Instances.Domains - -config :: ClockControlConfig Basic200 12 8 1500000 -config = $(lift (defClockConfig @Basic200)) - -callisto3 :: - Clock Basic200 -> - Reset Basic200 -> - Enable Basic200 -> - -- | Data counts from elastic buffers - Vec 3 (Signal Basic200 (RelDataCount 12)) -> - -- | Speed change requested from clock multiplier - Signal Basic200 (CallistoResult 3) -callisto3 clk rst ena dataCounts = - callistoClockControl clk rst ena config availableLinkMask dataCounts - where - -- all links available - availableLinkMask = pure $ complement 0 diff --git a/bittide/bittide.cabal b/bittide/bittide.cabal index 11778e4ca..707989e22 100644 --- a/bittide/bittide.cabal +++ b/bittide/bittide.cabal @@ -127,7 +127,6 @@ library Bittide.CaptureUgn Bittide.CircuitUtils Bittide.ClockControl - Bittide.ClockControl.Callisto Bittide.ClockControl.Callisto.Types Bittide.ClockControl.Callisto.Util Bittide.ClockControl.CallistoSw diff --git a/bittide/src/Bittide/ClockControl/Callisto.hs b/bittide/src/Bittide/ClockControl/Callisto.hs deleted file mode 100644 index 00eef7275..000000000 --- a/bittide/src/Bittide/ClockControl/Callisto.hs +++ /dev/null @@ -1,246 +0,0 @@ --- SPDX-FileCopyrightText: 2022 Google LLC --- --- SPDX-License-Identifier: Apache-2.0 -{-# LANGUAGE RecordWildCards #-} - -module Bittide.ClockControl.Callisto ( - CallistoResult (..), - ReframingState (..), - callistoClockControl, -) where - -import Clash.Prelude - -import Data.Constraint -import Data.Constraint.Nat (leTrans) -import Data.Constraint.Nat.Extra (euclid3, useLowerLimit) - -import Bittide.ClockControl -import Bittide.ClockControl.Callisto.Types -import Bittide.ClockControl.Callisto.Util -import Bittide.ClockControl.StabilityChecker -import Bittide.Extra.Maybe - -import qualified Clash.Cores.Xilinx.Floating as F -import qualified Clash.Signal.Delayed as D - -{-# NOINLINE callistoClockControl #-} - -{- | Determines how to influence clock frequency given statistics provided by -all elastic buffers. See 'callisto' for more information. --} -callistoClockControl :: - forall n m dom margin framesize. - ( KnownDomain dom - , KnownNat n - , KnownNat m - , KnownNat margin - , KnownNat framesize - , 1 <= n - , 1 <= m - , n + m <= 32 - , 1 <= framesize - ) => - Clock dom -> - Reset dom -> - Enable dom -> - -- | Configuration for this component, see individual fields for more info. - ClockControlConfig dom m margin framesize -> - -- | Link availability mask - Signal dom (BitVector n) -> - -- | Statistics provided by elastic buffers. - Vec n (Signal dom (RelDataCount m)) -> - Signal dom (CallistoResult n) -callistoClockControl clk rst ena ClockControlConfig{..} mask allDataCounts = - withClockResetEnable clk rst ena - $ let - dataCounts = filterCounts <$> fmap bv2v mask <*> bundle allDataCounts - updateCounter = wrappingCounter cccSettleCycles - shouldUpdate = updateCounter .==. 0 - scs = bundle $ map stabilityCheck $ unbundle dataCounts - allStable = allAvailable stable <$> mask <*> scs - allSettled = allAvailable settled <$> mask <*> scs - state = register initState state' - - state' = - mux - shouldUpdate - (callisto controlConfig mask scs dataCounts state) - state - - stabilityCheck = - stabilityChecker - cccStabilityCheckerMargin - cccStabilityCheckerFramesize - in - CallistoResult - <$> (orNothing <$> shouldUpdate <*> fmap _b_k state') - <*> scs - <*> allStable - <*> allSettled - <*> (rfState <$> state') - where - controlConfig = - ControlConfig - { reframingEnabled = cccEnableReframing - , waitTime = cccReframingWaitTime - , targetCount = targetDataCount - } - - initState = - ControlSt - { _z_k = 0 - , _b_k = NoChange - , _steadyStateTarget = 0.0 - , rfState = Detect - } - - filterCounts vMask vCounts = flip map (zip vMask vCounts) - $ \(isActive, count) -> if isActive == high then count else 0 - - allAvailable f x y = - and $ zipWith ((||) . not) (bitToBool <$> bv2v x) (f <$> y) - -{- | Clock correction strategy based on: - - https://github.com/bittide/Callisto.jl - -Note that this is an incredibly wasteful implementation: it instantiates -numerous floating point multipliers and adders, even though they're not doing -any useful work 99% of the time. Furthermore, 'RelDataCount' isn't properly -scaled to match elastic buffer sizes, resulting in unnecessarily big integer -adders. Optimization work has been postponed because: - - * It isn't clear yet whether this will be the final clock control algorithm. - * These algorithms will probably run on a Risc core in the future. --} -callisto :: - forall m n dom. - ( HiddenClockResetEnable dom - , KnownNat n - , KnownNat m - , 1 <= n - , 1 <= m - , -- 'callisto' sums incoming 'RelDataCount's and feeds them to a Xilinx signed to - -- float IP. We can currently only interpret 32 bit signeds to unsigned, so to - -- make sure we don't overflow any addition we force @n + m <= 32@. - n + m <= 32 - ) => - -- | Configuration parameters. - ControlConfig m -> - -- | Link availability mask. - Signal dom (BitVector n) -> - -- | Stability indicators for each of the elastic buffers. - Signal dom (Vec n StabilityIndication) -> - -- | Data counts from elastic buffers. - Signal dom (Vec n (RelDataCount m)) -> - -- | Current state. - Signal dom ControlSt -> - -- | Updated state. - Signal dom ControlSt -callisto ControlConfig{..} mask scs dataCounts state = - rfStateUpdate - <$> (all stable <$> scs) - <*> D.toSignal c_des - <*> updatedState - where - updatedState = - D.toSignal - $ ControlSt - <$> delayIU "[1]" z_kNext - <*> b_kNext - <*> delayIU "[2]" steadyStateTarget - <*> delayIU "[3]" (D.fromSignal (rfState <$> state)) - - -- See fields in 'ControlSt' for documentation of 'z_k', 'b_k', and css. - z_k :: DSignal dom 0 (Signed 32) - z_k = D.fromSignal (_z_k <$> state) - - b_k :: DSignal dom 0 SpeedChange - b_k = D.fromSignal (_b_k <$> state) - - steadyStateTarget :: DSignal dom 0 Float - steadyStateTarget = D.fromSignal (_steadyStateTarget <$> state) - - -- see clock control algorithm simulation here: - -- - -- https://github.com/bittide/Callisto.jl/blob/e47139fca128995e2e64b2be935ad588f6d4f9fb/demo/pulsecontrol.jl#L24 - -- - -- `k_p` (proportional gain) is copied from the Julia implementation. `fStep` should - -- match the step size of the clock boards. For all our HITL tests this is set by - -- `HwCcTopologies.commonStepSizeSelect`. - -- - k_p, fStep :: forall d. DSignal dom d Float - k_p = pure 2e-8 - fStep = pure 100e-9 - - r_k :: DSignal dom F.FromS32DefDelay Float - r_k = - F.fromS32 - $ D.fromSignal - $ let - nBuffers = case useLowerLimit @n @m @32 of - Dict -> safePopCountTo32 <$> mask - measuredSum = sumTo32 <$> dataCounts - targetCountSigned = case euclid3 @n @m @32 of - Dict -> case leTrans @1 @n @(32 - m) of - Sub Dict -> extend @_ @_ @(32 - m - 1) $ dataCountToSigned targetCount - in - measuredSum - (pure targetCountSigned * nBuffers) - - c_des :: DSignal dom (F.FromS32DefDelay + F.MulDefDelay + F.AddDefDelay) Float - c_des = delayIU "[4]" $ (k_p `F.mul` r_k) `F.add` delayIU "[5]" steadyStateTarget - - z_kNext :: DSignal dom 0 (Signed 32) - z_kNext = z_k + fmap sign b_k - - c_est :: DSignal dom (F.FromS32DefDelay + F.MulDefDelay + F.AddDefDelay) Float - c_est = delayIU "[6]" $ fStep `F.mul` F.fromS32 z_kNext - - b_kNext = - flip fmap (F.compare c_des c_est) $ \case - F.LT -> SlowDown - F.GT -> SpeedUp - F.EQ -> NoChange - -- TODO: Propagate errors upwards? - F.NaN -> NoChange - - rfStateUpdate stable target st@ControlSt{..} - | not reframingEnabled = st - | otherwise = case rfState of - Detect - | not stable -> - st - | otherwise -> - st - { rfState = - Wait - { curWaitTime = waitTime - , targetCorrection = target - } - } - Wait{..} - | curWaitTime > 0 -> - st - { rfState = - Wait - { curWaitTime = curWaitTime - 1 - , .. - } - } - | otherwise -> - st - { rfState = Done - , _steadyStateTarget = targetCorrection - } - Done -> st - - -- Uninitialized version of 'Clash.Signal.Delayed.delayI' - delayIU :: - forall d k a. - (HiddenClock dom, HiddenEnable dom, NFDataX a, KnownNat d) => - String -> - DSignal dom k a -> - DSignal dom (k + d) a - delayIU = - D.delayI . errorX . ("callisto: No start value " <>) diff --git a/bittide/src/Bittide/ClockControl/Callisto/Types.hs b/bittide/src/Bittide/ClockControl/Callisto/Types.hs index 5357a1a26..33a1441b0 100644 --- a/bittide/src/Bittide/ClockControl/Callisto/Types.hs +++ b/bittide/src/Bittide/ClockControl/Callisto/Types.hs @@ -18,6 +18,7 @@ import Clash.Prelude import Bittide.ClockControl import Bittide.ClockControl.StabilityChecker (StabilityIndication) import Clash.Signal.TH.Extra (deriveSignalHasFields) +import VexRiscv (JtagOut) -- | Result of the clock control algorithm. data CallistoResult (n :: Nat) = CallistoResult @@ -34,6 +35,8 @@ data CallistoResult (n :: Nat) = CallistoResult -- buffers have been settled. , reframingState :: ReframingState -- ^ State of the Reframing detector + , jtagOut :: JtagOut + -- ^ JTAG output from the CPU } deriving (Generic, NFDataX) diff --git a/bittide/src/Bittide/ClockControl/CallistoSw.hs b/bittide/src/Bittide/ClockControl/CallistoSw.hs index 57e610072..5c6af8b85 100644 --- a/bittide/src/Bittide/ClockControl/CallistoSw.hs +++ b/bittide/src/Bittide/ClockControl/CallistoSw.hs @@ -16,12 +16,9 @@ import Clash.Prelude hiding (PeriodToCycles) import Clash.Cores.Xilinx.Ila (Depth (..), IlaConfig (..), ila, ilaConfig) import Data.Maybe (fromMaybe, isJust) -import Language.Haskell.TH (runIO) -import Project.FilePath import Protocols import Protocols.Idle -import System.FilePath -import VexRiscv (DumpVcd (NoDumpVcd)) +import VexRiscv (DumpVcd (NoDumpVcd), JtagIn) import Bittide.CircuitUtils import Bittide.ClockControl (RelDataCount) @@ -31,10 +28,8 @@ import Bittide.ClockControl.DebugRegister ( debugRegisterWb, ) import Bittide.ClockControl.Registers (ClockControlData (..), clockControlWb) -import Bittide.DoubleBufferedRam (ContentType (Blob), InitialContent (Reloadable)) +import Bittide.DoubleBufferedRam (InitialContent (Undefined)) import Bittide.ProcessingElement (PeConfig (..), processingElement) -import Bittide.ProcessingElement.Util (memBlobsFromElf) -import Bittide.SharedTypes (ByteOrder (BigEndian)) -- | Configuration type for software clock control. data SwControlConfig dom mgn fsz where @@ -44,6 +39,8 @@ data SwControlConfig dom mgn fsz where , 1 <= fsz , KnownDomain dom ) => + -- | JTAG input to the CPU + Signal dom JtagIn -> -- | Enable reframing? -- -- N.B.: FOR TESTING USE ONLY. Reframing should eventually be handled solely within @@ -79,7 +76,7 @@ callistoSwClockControl :: -- | Diff counters Vec nLinks (Signal dom (RelDataCount eBufBits)) -> Signal dom (CallistoResult nLinks) -callistoSwClockControl (SwControlConfig (reframe :: Signal dom Bool) mgn fsz) mask ebs = +callistoSwClockControl (SwControlConfig jtagIn reframe mgn fsz) mask ebs = hwSeqX callistoSwIla callistoResult where callistoResult = @@ -89,6 +86,7 @@ callistoSwClockControl (SwControlConfig (reframe :: Signal dom Bool) mgn fsz) ma <*> ccData.allStable <*> ccData.allSettled <*> resultRfs + <*> jtag resultRfs = fromMaybe Done <$> debugData.reframingState @@ -117,30 +115,31 @@ callistoSwClockControl (SwControlConfig (reframe :: Signal dom Bool) mgn fsz) ma capture = isRising False (isJust <$> ccData.clockMod) - (_, (ccData, debugData)) = - toSignals @() - ( circuit $ \_unit -> do - jtag <- idleSource -< () - [wbClockControl, wbDebug, wbDummy] <- processingElement NoDumpVcd peConfig -< jtag - idleSink -< wbDummy - [ccd0, ccd1] <- cSignalDupe <| clockControlWb mgn fsz mask ebs -< wbClockControl - cm <- cSignalMap clockMod -< ccd0 - dbg <- debugRegisterWb debugRegisterCfg -< (wbDebug, cm) - idC -< (ccd1, dbg) - ) - ((), (pure (), pure ())) - (iMem, dMem) = - $( do - root <- runIO $ findParentContaining "cabal.project" - let - elfDir = root firmwareBinariesDir "riscv32imc-unknown-none-elf" Release - elfPath = elfDir "clock-control" - iSize = 64 * 1024 -- 64 KB - dSize = 64 * 1024 -- 64 KB - memBlobsFromElf BigEndian (Just iSize, Just dSize) elfPath Nothing - ) + (jtag, (ccData, debugData)) = + circuitFn (jtagIn, (pure (), pure ())) + + Circuit circuitFn = circuit $ \jtag -> do + [wbClockControl, wbDebug, wbDummy] <- processingElement NoDumpVcd peConfig -< jtag + idleSink -< wbDummy + [ccd0, ccd1] <- cSignalDupe <| clockControlWb mgn fsz mask ebs -< wbClockControl + cm <- cSignalMap clockMod -< ccd0 + dbg <- debugRegisterWb debugRegisterCfg -< (wbDebug, cm) + idC -< (ccd1, dbg) + + -- (_, (ccData, debugData)) = + -- toSignals @() + -- ( circuit $ \_unit -> do + -- jtag <- idleSource -< () + -- [wbClockControl, wbDebug, wbDummy] <- processingElement NoDumpVcd peConfig -< jtag + -- idleSink -< wbDummy + -- [ccd0, ccd1] <- cSignalDupe <| clockControlWb mgn fsz mask ebs -< wbClockControl + -- cm <- cSignalMap clockMod -< ccd0 + -- dbg <- debugRegisterWb debugRegisterCfg -< (wbDebug, cm) + -- idC -< (ccd1, dbg) + -- ) + -- ((), (pure (), pure ())) peConfig = PeConfig (0b100 :> 0b010 :> 0b110 :> 0b111 :> 0b001 :> Nil) - (Reloadable $ Blob iMem) - (Reloadable $ Blob dMem) + (Undefined @(Div (64 * 1024) 4)) + (Undefined @(Div (64 * 1024) 4))