Skip to content

Commit

Permalink
Parse UGNs, print IGNs, and some cleanup.
Browse files Browse the repository at this point in the history
  • Loading branch information
rslawson committed Feb 27, 2025
1 parent ecf4490 commit 023b087
Showing 1 changed file with 90 additions and 16 deletions.
106 changes: 90 additions & 16 deletions bittide-instances/src/Bittide/Instances/Hitl/Driver/Demo.hs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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
Expand All @@ -50,6 +49,7 @@ data OcdInitData = OcdInitData
data TestStatus = TestRunning | TestDone Bool | TestTimeout deriving (Eq)

driverFunc ::
(HasCallStack) =>
String ->
[(HwTarget, DeviceInfo)] ->
VivadoM ExitCode
Expand Down Expand Up @@ -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]
Expand All @@ -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 <> ")"
Expand All @@ -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
Expand Down Expand Up @@ -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 ()

0 comments on commit 023b087

Please sign in to comment.