Simulation just hangs

I’m trying to include a pipeline inside the Df stream. I’m trying to write:

delayToDf' :: forall dom delay a b.
              (HasCallStack, HiddenClockResetEnable dom, KnownNat delay, NFDataX a, NFDataX b)
           => (HiddenClockResetEnable dom => DSignal dom 0 a -> DSignal dom delay b)
           -> (Signal dom (Maybe a), (Signal dom Ack, Signal dom ()))
           -> (Signal dom Ack, (Signal dom (Maybe b), Signal dom (DelayToDfDbg a b)))
delayToDf' f (input, (outputAck, _)) =
  let delayToDfDbgInput :: HasCallStack => Signal dom (DelayToDfDbgInput a)
      delayToDfDbgInput = DelayToDfDbgInput <$> input <*> fmap A.fromPAck outputAck

      inputAck :: HasCallStack => Signal dom Ack
      inputAck = proceedToAck <$> proceed

      proceed :: HasCallStack => Signal dom Proceed
      mask :: HasCallStack => Signal dom Mask
      (proceed, mask) = mealyB delayToDfSt Unmask (delayToDfDbgInput, pipelineOutput)

      pipelineInput :: HasCallStack => Signal dom a
      pipelineInput = fromMaybe (deepErrorX "Not from input") <$> input

      pipeline :: (HasCallStack, HiddenClockResetEnable dom) => Signal dom (Maybe b)
      pipeline = toSignal (aux <$> valid <*> f (fromSignal pipelineInput))
                 where aux :: Bool -> b -> Maybe b
                       aux True x = Just x
                       aux False _x = Nothing
                       valid :: DSignal dom delay Bool
                       valid = delayedI @delay @_ @_ @0 False (pure True)

      pipelineOutput :: HasCallStack => Signal dom (Maybe b)
      pipelineOutput = andEnable (proceedToBool <$> proceed) pipeline

      output :: HasCallStack => Signal dom (Maybe b)
      output = doMask <$> mask <*> pipelineOutput

      dbg :: HasCallStack => Signal dom (DelayToDfDbg a b)
      dbg =
        DelayToDfDbg <$>
        (DelayToDfDbgInput <$> input <*> fmap A.fromPAck outputAck) <*>
        (DelayToDfDbgOutput <$> fmap A.fromPAck inputAck <*> output) <*>
        (DelayToDfDbgState <$> mask <*> proceed <*> pipelineInput <*> pipelineOutput)
  in (inputAck, (output, dbg))

Now it contains some error that I try to debug but it shouldn’t hang. But when I try to use simulation it just hangs:

          lhsStallMode <- forAll $ P.genStallMode
          rhsStallMode <- forAll $ P.genStallMode
          input :: [C.BitVector 8] <- forAll $ Gen.list (Range.linear 1 100) genBitVector
          (lhsStallAck, lhsStalls) <- forAll $ P.genStalls (Gen.integral $ Range.linear 0 $ C.natToNum @delay) (length input) lhsStallMode
          (rhsStallAck, rhsStalls) <- forAll $ P.genStalls (Gen.integral $ Range.linear 0 $ C.natToNum @delay) (length input) rhsStallMode
          maps :: IORef Maps <- liftIO $ newIORef C.def
          let resetCycles = C.SNat @100
              simCfg = def { resetCycles = C.snatToNum resetCycles }
              lhsStall = Df.stall @C.System simCfg lhsStallAck lhsStalls
              rhsStall = Df.stall @C.System simCfg rhsStallAck rhsStalls
              f :: (C.HiddenClockResetEnable dom) => C.DSignal dom 0 (C.BitVector 8) -> C.DSignal dom delay (C.BitVector 8)
              f = C.delayedI C.undefined
              dut' :: C.HiddenClockResetEnable C.System => Circuit (Df C.System (C.BitVector 8)) (Df C.System (C.BitVector 8))
              dut' = lhsStall |> dut maps f |> rhsStall
              dut'' = C.exposeClockResetEnable dut' C.clockGen (C.resetGenN resetCycles) C.enableGen
              out = simulateC dut'' simCfg (Just <$> input)
              expOpt = P.defExpectOptions { P.eoTimeoutMs = Just 1000, P.eoResetCycles = C.snatToNum resetCycles }
          out' <- P.expectN (Proxy @(Df C.System (C.BitVector 8))) expOpt (take 100 out)

I’m stuck how to debug it. It doesn’t seem to hang when I feed it ‘by hand’ in ghci.

I think it’s because you have a loop in there:

You have a mealy:

(proceed, mask) = mealyB delayToDfSt Unmask (delayToDfDbgInput, pipelineOutput)

And then:

pipelineOutput = andEnable (proceedToBool <$> proceed) pipeline

So The loop is (arrow is depends on)

pipeLineOutput → proceed → delayToDfSt -> pipelineOutput

This looks like classic combinational loop. It’s probably fine via ghci because you didn’t hit the case where the loop is evaluated.

Hmm. Yeah - I guess it is this loop. My question about how to debug it still stands though. I would expect that I get loop exception or I can at least debug it somehow.