From 023b087f60f41889d5077553232f37de89485839 Mon Sep 17 00:00:00 2001 From: Ryan Slawson Date: Thu, 27 Feb 2025 12:08:09 +0100 Subject: [PATCH] Parse UGNs, print IGNs, and some cleanup. --- .../src/Bittide/Instances/Hitl/Driver/Demo.hs | 106 +++++++++++++++--- 1 file changed, 90 insertions(+), 16 deletions(-) diff --git a/bittide-instances/src/Bittide/Instances/Hitl/Driver/Demo.hs b/bittide-instances/src/Bittide/Instances/Hitl/Driver/Demo.hs index 545ed85e7..59d60ee28 100644 --- a/bittide-instances/src/Bittide/Instances/Hitl/Driver/Demo.hs +++ b/bittide-instances/src/Bittide/Instances/Hitl/Driver/Demo.hs @@ -6,20 +6,25 @@ {-# LANGUAGE OverloadedRecordDot #-} {-# LANGUAGE QuasiQuotes #-} -module Bittide.Instances.Hitl.Driver.Demo where +module Bittide.Instances.Hitl.Driver.Demo ( + OcdInitData (..), + driverFunc, +) where import Clash.Prelude import Bittide.Hitl -import Bittide.Instances.Hitl.Setup (demoRigInfo) +import Bittide.Instances.Hitl.Setup (demoRigInfo, fpgaSetup) import Bittide.Instances.Hitl.Utils.Program import Bittide.Instances.Hitl.Utils.Vivado -import Control.Monad (forM_, zipWithM) +import Clash.Functor.Extra ((<<$>>)) +import Control.Monad (forM_, when, zipWithM) import Control.Monad.IO.Class import Data.List.Extra (trim) -import Data.Maybe (fromMaybe) +import Data.Maybe (fromJust, fromMaybe) import Data.String.Interpolate (i) +import GHC.Stack (HasCallStack) import Project.FilePath import Project.Handle import System.Clock (Clock (Monotonic), diffTimeSpec, getTime, toNanoSecs) @@ -34,12 +39,6 @@ import qualified Control.Monad.Trans.Control as CMTC import qualified Data.List as L import qualified System.Timeout.Lifted as STL --- connect EBs over WB --- read/write regs with MU, ensure that correct values show up --- check over GDB too --- no input data --- just one test case - data OcdInitData = OcdInitData { muPort :: Int , ccPort :: Int @@ -50,6 +49,7 @@ data OcdInitData = OcdInitData data TestStatus = TestRunning | TestDone Bool | TestTimeout deriving (Eq) driverFunc :: + (HasCallStack) => String -> [(HwTarget, DeviceInfo)] -> VivadoM ExitCode @@ -301,7 +301,7 @@ driverFunc testName targets = do inner innerInit muGetUgns :: - (HwTarget, DeviceInfo) -> ProcessStdIoHandles -> VivadoM [(Unsigned 64, Unsigned 64)] + (HwTarget, DeviceInfo) -> ProcessStdIoHandles -> VivadoM [(Integer, Integer)] muGetUgns (_, d) gdb = do let mmioAddrs :: [String] @@ -315,7 +315,7 @@ driverFunc testName targets = do , "0x70000000" ] - readUgnMmio :: String -> IO (Unsigned 64, Unsigned 64) + readUgnMmio :: String -> IO (Integer, Integer) readUgnMmio addr = do let startString = "START OF UGN (" <> addr <> ")" @@ -331,9 +331,13 @@ driverFunc testName targets = do $ readUntil gdb.stdoutHandle startString gdbRead <- tryWithTimeout "Reading UGN over GDB" 15_000_000 $ readUntil gdb.stdoutHandle endString - -- Temporary debug print of this so I can get a proper parsing setup going later: + let + outputLine = L.head $ L.lines $ trim gdbRead + outputDataWords = L.words $ trim $ outputLine putStrLn $ "GDB output: {{\n" <> gdbRead <> "}}" - return (0, 0) + case L.drop (L.length outputDataWords - 2) outputDataWords of + [read -> txIJ, read -> rxIJ] -> return (txIJ, rxIJ) + other -> fail [i|Could not read output data. Line: '#{outputLine}', data: #{other}|] liftIO $ putStrLn $ "Getting UGNs for device " <> show d.deviceId liftIO $ mapM readUgnMmio mmioAddrs @@ -384,11 +388,81 @@ driverFunc testName targets = do $ putStrLn [i|Test case #{testName} stabilised on #{sCount} of #{L.length targets} targets|] - liftIO $ putStrLn "Doing GDB checks for each MU" - _ <- zipWithM muGetUgns targets muGdbs + liftIO $ putStrLn "Getting UGNs for all targets" + ugnPairsTable <- zipWithM muGetUgns targets muGdbs + liftIO $ putStrLn "Calculating IGNs for all targets" + liftIO $ printAllIgns ugnPairsTable fpgaSetup let finalExit = fromMaybe ExitSuccess $ L.find (/= ExitSuccess) [stabilityExitCode, gdbExitCode0, gdbExitCode1] return finalExit + +printAllIgns :: + forall n m. + ( HasCallStack + , KnownNat m + , KnownNat n + ) => + [[(Integer, Integer)]] -> + Vec (n + 1) (FpgaId, Vec m (Index (n + 1))) -> + IO () +printAllIgns ugnPairsTable fpgasTable = do + let + ugnPairsTableSquare = L.all (== L.head lengths) lengths + where + lengths = L.length <$> ugnPairsTable + uptRows = L.length ugnPairsTable + uptCols = L.length $ L.head ugnPairsTable + ftRows = length fpgasTable + ftCols = length $ snd $ head fpgasTable + when (not ugnPairsTableSquare) + $ fail "UGNs table is not rectangular." + when ((ftRows /= uptRows) || (ftCols /= uptCols)) + $ fail + $ [i|UGNs table does not match dimensions of FPGAs table. |] + <> [i|Expected (#{ftRows}, #{ftCols}), found (#{uptRows}, #{uptCols})|] + let + ugnsTable :: [[Integer]] + ugnsTable = uncurry (-) <<$>> ugnPairsTable + fpgasMap :: Vec (n + 1) (Vec m (Index (n + 1))) + fpgasMap = snd <$> fpgasTable + indicesM :: Vec m (Index m) + indicesM = indicesI + indicesN :: Vec (n + 1) (Index (n + 1)) + indicesN = indicesI + printIgns :: + (HasCallStack) => Index (n + 1) -> (FpgaId, Vec m (Index (n + 1))) -> IO (Vec m Integer) + printIgns rowI (myId, row) = do + putStrLn [i|Finding IGNs for #{myId} (#{rowI})|] + putStrLn [i| My connections: #{row}|] + let + printIgn :: (HasCallStack) => Index m -> Index (n + 1) -> IO Integer + printIgn colI otherRowI = do + putStrLn [i| Looking at column #{colI} => #{otherRowI}|] + let + otherRow :: Vec m (Index (n + 1)) + otherRow = fpgasMap !! otherRowI + otherRowName :: FpgaId + otherRowName = fst $ fpgasTable !! otherRowI + putStrLn [i| Row name: #{otherRowName}|] + putStrLn [i| Row contents: #{otherRow}|] + let + myIndex :: Index m + myIndex = fromJust $ findIndex (== rowI) otherRow + putStrLn [i| Other row has me at index: #{myIndex}|] + let + myUgn = ugnsTable L.!! (fromIntegral rowI) L.!! (fromIntegral colI) + otherUgn = ugnsTable L.!! (fromIntegral otherRowI) L.!! (fromIntegral myIndex) + ign = myUgn + otherUgn + putStrLn [i| The IGN for this link is: #{myUgn} + #{otherUgn} = #{ign}|] + return ign + igns <- sequence $ zipWith printIgn indicesM row + putStrLn [i|IGNs for FPGA " #{myId} (#{rowI}): #{igns}"|] + return igns + + igns <- sequence $ zipWith printIgns indicesN fpgasTable + putStrLn "Final IGNs table:" + forM_ igns print + return ()