Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Df serializer #21

Open
gergoerdi opened this issue Nov 30, 2024 · 6 comments
Open

Df serializer #21

gergoerdi opened this issue Nov 30, 2024 · 6 comments

Comments

@gergoerdi
Copy link

We can wrap clash-cores's UART as a Df-to-CSignal circuit:

-- From [email protected]:bittide/bittide-hardware.git
uart
    :: (HiddenClockResetEnable dom, ValidBaud dom baud)
    => SNat baud
    -> Circuit
        (Df dom (BitVector 8), CSignal dom Bit)
        (CSignal dom (Maybe (BitVector 8)), CSignal dom Bit)
uartDf baud = Circuit \((request, rx_bit), _out_ack) ->
    let (received, tx_bit, in_ack) = uart baud rx_bit (Df.dataToMaybe <$> request)
    in ((Ack <$> in_ack, pure ()), (received, tx_bit))

Since it has no internal concept of holding received bytes until consumed, we need to pair it with a buffer to be useful in the Df world:

buffer :: (HiddenClockResetEnable dom, NFDataX a) => Circuit (CSignal dom (Maybe a)) (Df dom a)
buffer = Circuit \(x, ack) ->
    let r = register Nothing do
            current <- r
            next <- x
            ~(Ack ack) <- ack
            pure $ if ack then next else current <|> next
    in (pure (), Df.maybeToData <$> r)

And now the nifty part: with these two components, we can make a general circuit-to-serial transformer:

uncircuit :: Circuit (CSignal dom a) (CSignal dom b) -> Signal dom a -> Signal dom b
uncircuit c = snd . toSignals c . (, pure ())

serialize
    :: (HiddenClockResetEnable dom, BitPack a, BitSize a ~ 8, BitPack b, BitSize b ~ 8)
    => forall baud -> (KnownNat baud, ValidBaud dom baud)
    => Circuit (Df dom a) (Df dom b)
    -> Signal dom Bit
    -> Signal dom Bit
serialize baud par_circuit = uncircuit $ circuit \rx -> do
    (in_byte, tx) <- uartDf (SNat @baud) -< (out_byte, rx)
    out_byte <- Df.map pack <| par_circuit <| Df.map unpack <| buffer -< in_byte
    idC -< tx

And this is basically the Clash/UART equivalent of Prelude.interact :: (String -> String) -> IO ()!

Would this make sense as an addition to clash-protocols? If yes, I'm happy to prepare a proper PR.

@gergoerdi
Copy link
Author

(I guess for the librarized version you wouldn't want to use RequiredTypeArguments for pre-GHC-9.10 compatibility, but of course it's easily replacable with a SNat baud proxy parameter)

@rowanG077
Copy link
Member

Yes I agree this useful. But rather then living in clash-protocols it should live in clash-cores. Since clash-protocols is more foundational then clash-cores. Perhaps even in the uart module.

@gergoerdi
Copy link
Author

Oh, I didn't realize clash-cores depends on clash-protocols, I assumed it's the other way around, with clash-protocols being considered more "experimental".

Can you move this ticket to clash-cores?

@DigitalBrains1
Copy link
Member

DigitalBrains1 commented Dec 1, 2024

clash-cores doesn't yet depend on clash-protocols, but soon it will, with PR #20 .

I think the wrapper is an excellent idea.

[edit]
Ah, note that actually we can't add clash-protocols as a dependency yet. cores-hdl-tests and clash-protocols have conflicting requirements. This is also blocking #20, so I expect it will be fixed soon. I don't think it'll be difficult.
[/edit]

@DigitalBrains1 DigitalBrains1 transferred this issue from clash-lang/clash-protocols Dec 1, 2024
@lmbollen
Copy link
Member

lmbollen commented Dec 2, 2024

I'd like to draw attention to https://github.com/bittide/bittide-hardware/blob/staging/bittide/src/Bittide/Wishbone.hs#L254-L504 where this already exists

@gergoerdi
Copy link
Author

@lmbollen :

I'd like to draw attention to https://github.com/bittide/bittide-hardware/blob/staging/bittide/src/Bittide/Wishbone.hs#L254-L504 where this already exists

Right, this is where I lifted uartDf from; then I wrote all the other overly simplistic stuff around it. However, to me all of these are just means to an end, and that end is seralize as an equivalent to interactive. So would it work better if we used the full-featured FIFO stuff from your repo to implement `serialize?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants