clash-vexriscv-0.1: src/VexRiscv/JtagTcpBridge.hs
-- SPDX-FileCopyrightText: 2023 Google LLC
--
-- SPDX-License-Identifier: Apache-2.0
{-# LANGUAGE RecordWildCards #-}
module VexRiscv.JtagTcpBridge (vexrJtagBridge, defaultIn) where
import Clash.Prelude
import Clash.Signal.Internal
import Foreign
import Network.Socket (PortNumber)
import System.IO.Unsafe (unsafePerformIO)
import VexRiscv.FFI
import VexRiscv.Internal
defaultIn :: JtagIn
defaultIn = JtagIn{testClock = low, testModeSelect = low, testDataIn = low}
{-# NOINLINE inner #-}
inner :: (t -> IO JtagIn) -> Signal dom t -> Signal dom JtagIn
inner jtagBridgeStep (o :- outs) = unsafePerformIO $ do
in' <- jtagBridgeStep o
let ins' = inner jtagBridgeStep outs
pure $ in' :- (in' `deepseqX` ins')
vexrJtagBridge :: PortNumber -> IO (Signal dom JtagOut -> Signal dom JtagIn)
vexrJtagBridge port = do
(_, jtagBridgeStep) <- vexrJtagBridge' port
pure (inner jtagBridgeStep)
vexrJtagBridge' ::
PortNumber ->
IO
( IO ()
, -- \^ delete function
JtagOut -> IO JtagIn
)
-- \^ step function
vexrJtagBridge' port = do
bridge <- vexrJtagBridgeInit (fromIntegral port)
let
shutDown = vexrJtagBridgeShutdown bridge
step JtagOut{..} = alloca $ \outFFI -> alloca $ \inFFI -> do
poke outFFI (JTAG_OUTPUT testDataOut)
vexrJtagBridgeStep bridge outFFI inFFI
JTAG_INPUT{..} <- peek inFFI
let input = JtagIn{testClock = tck, testModeSelect = tms, testDataIn = tdi}
pure input
pure (shutDown, step)