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

Remove CSignal constructor #67

Merged
merged 3 commits into from
Mar 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 20 additions & 19 deletions src/Protocols/Internal.hs
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
{-|
Internal module to prevent hs-boot files (breaks Haddock)
-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE RoleAnnotations #-}
{-# LANGUAGE TypeFamilyDependencies #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE CPP #-}

#if !MIN_VERSION_clash_prelude(1, 8, 2)
{-# OPTIONS_GHC -fno-warn-orphans #-} -- NFDataX and ShowX for Identity and Proxy
#endif

-- TODO: Hide internal documentation
-- {-# OPTIONS_HADDOCK hide #-}
Expand All @@ -25,7 +29,6 @@
import qualified Clash.Prelude as C
import qualified Clash.Explicit.Prelude as CE

import Control.Applicative (Const(..))
import Control.Arrow ((***))
import Data.Coerce (coerce)
import Data.Default (Default(def))
Expand Down Expand Up @@ -153,19 +156,20 @@

-- | Protocol-agnostic acknowledgement
newtype Ack = Ack Bool
deriving (Generic, C.NFDataX, Show, C.Bundle)

Check warning on line 159 in src/Protocols/Internal.hs

View workflow job for this annotation

GitHub Actions / Cabal tests - ghc 9.2.8 / clash 1.8.1

• Both DeriveAnyClass and GeneralizedNewtypeDeriving are enabled

Check warning on line 159 in src/Protocols/Internal.hs

View workflow job for this annotation

GitHub Actions / Cabal tests - ghc 9.2.8 / clash 1.8.1

• Both DeriveAnyClass and GeneralizedNewtypeDeriving are enabled

Check warning on line 159 in src/Protocols/Internal.hs

View workflow job for this annotation

GitHub Actions / Cabal tests - ghc 9.4.8 / clash 1.8.1

• Both DeriveAnyClass and GeneralizedNewtypeDeriving are enabled

Check warning on line 159 in src/Protocols/Internal.hs

View workflow job for this annotation

GitHub Actions / Cabal tests - ghc 9.4.8 / clash 1.8.1

• Both DeriveAnyClass and GeneralizedNewtypeDeriving are enabled

Check warning on line 159 in src/Protocols/Internal.hs

View workflow job for this annotation

GitHub Actions / Cabal tests - ghc 9.6.4 / clash 1.8.1

• Both DeriveAnyClass and GeneralizedNewtypeDeriving are enabled

Check warning on line 159 in src/Protocols/Internal.hs

View workflow job for this annotation

GitHub Actions / Cabal tests - ghc 9.6.4 / clash 1.8.1

• Both DeriveAnyClass and GeneralizedNewtypeDeriving are enabled

-- | Acknowledge. Used in circuit-notation plugin to drive ignore components.
instance Default Ack where
def = Ack True

-- | Circuit protocol with /CSignal dom a/ in its forward direction, and
-- /CSignal dom ()/ in its backward direction. Convenient for exposing
-- protocol internals.
data CSignal dom a = CSignal (Signal dom a)

instance Default a => Default (CSignal dom a) where
def = CSignal def
-- | Circuit protocol with /Signal dom a/ in its forward direction, and
-- /()/ in its backward direction. Convenient for exposing protocol
-- internals, or simply for undirectional streams.
--
-- Note: 'CSignal' exists to work around [issue 760](https://github.com/clash-lang/clash-compiler/issues/760)
-- in Clash, where type families with 'Signal' on the LHS are broken.
data CSignal (dom :: CE.Domain) (a :: Type)
type role CSignal nominal representational

-- | A protocol describes the in- and outputs of one side of a 'Circuit'.
class Protocol a where
Expand Down Expand Up @@ -199,8 +203,8 @@

-- XXX: Type families with Signals on LHS are currently broken on Clash:
instance Protocol (CSignal dom a) where
type Fwd (CSignal dom a) = CSignal dom a
type Bwd (CSignal dom a) = CSignal dom ()
type Fwd (CSignal dom a) = Signal dom a
type Bwd (CSignal dom a) = ()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this change? why not:

type Bwd (CSignal dom a) = Signal dom ()

Now Bwd () and Bwd (CSignal dom a) are the same, and there's even less hope to make Bwd injective again.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've given up the hope.. If we make an instance for DSignal (CDSignal? 🥴) it will have the same Bwd.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To me a Protocol instance of DSignal does not make sense. I'd figure you either use DSignal to build latency matched pipelines or Protocols to build backpressure based pipelines, but you don't mix these.

Copy link
Member Author

@martijnbastiaan martijnbastiaan Mar 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO its existence would be motivated similar to CSignal: sometimes you just want to deal with a non-backpressure thing in Circuit context.

In any case, I just remembered the original motivation for dropping injectivity: all the protocols having a simple "acknowledge" on their Bwd would have to make newtypes, which turned out to be really annoying.

Copy link
Member

@DigitalBrains1 DigitalBrains1 Mar 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd figure you either use DSignal to build latency matched pipelines or Protocols to build backpressure based pipelines, but you don't mix these.

In general, you can mix backpressure and latency just fine; it's often a requirement for efficient pipelining without buffers. You'd have the contract that when ready deasserts, you can still transfer n more samples for a certain fixed n, after which the transfer stalls. For instance the Avalon Streaming interface supports this notion.

I'm not acquainted enough with clash-protocols to really say how this relates here; I just noticed a dichotomy being constructed between latencies and backpressure that I think isn't there.


-- | Left-to-right circuit composition.
--
Expand Down Expand Up @@ -253,7 +257,7 @@
boolsToBwd _ bs = C.repeat (boolsToBwd (Proxy @a) bs)

instance Backpressure (CSignal dom a) where
boolsToBwd _ _ = CSignal (pure ())
boolsToBwd _ _ = ()

-- | Right-to-left circuit composition.
--
Expand Down Expand Up @@ -600,16 +604,13 @@
type SimulateBwdType (CSignal dom a) = ()
type SimulateChannels (CSignal dom a) = 1

simToSigFwd Proxy list = CSignal (C.fromList_lazy list)
simToSigFwd Proxy list = C.fromList_lazy list
simToSigBwd Proxy () = def
sigToSimFwd Proxy (CSignal sig) = C.sample_lazy sig
sigToSimFwd Proxy sig = C.sample_lazy sig
sigToSimBwd Proxy _ = ()

stallC _ _ = idC

instance Default (CSignal dom (Const () a)) where
def = CSignal (pure (Const ()))

instance (C.NFDataX a, C.ShowX a, Show a, C.KnownDomain dom) => Drivable (CSignal dom a) where
type ExpectType (CSignal dom a) = [a]

Expand All @@ -619,10 +620,10 @@
driveC _conf [] = error "CSignal.driveC: Can't drive with empty list"
driveC SimulationConfig{resetCycles} fwd0@(f:_) =
let fwd1 = C.fromList_lazy (replicate resetCycles f <> fwd0 <> repeat f) in
Circuit ( \_ -> ((), CSignal fwd1) )
Circuit ( \_ -> ((), fwd1) )

sampleC SimulationConfig{resetCycles, ignoreReset} (Circuit f) =
let sampled = CE.sample_lazy ((\(CSignal s) -> s) (snd (f ((), def)))) in
let sampled = CE.sample_lazy (snd (f ((), def))) in
if ignoreReset then drop resetCycles sampled else sampled


Expand Down
5 changes: 2 additions & 3 deletions src/Protocols/Wishbone/Standard.hs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ module Protocols.Wishbone.Standard where
import Clash.Prelude
import qualified Data.Bifunctor as B
import Protocols
import Protocols.Internal
import Protocols.Wishbone
import Prelude hiding (head, not, repeat, (!!), (&&), (||))

Expand Down Expand Up @@ -89,8 +88,8 @@ crossbarSwitch ::
(Vec m (Wishbone dom 'Standard addressWidth a)) -- slaves
crossbarSwitch = Circuit go
where
go ((CSignal route, bundle -> m2ss0), bundle -> s2ms0) =
((CSignal (pure ()), unbundle s2ms1), unbundle m2ss1)
go ((route, bundle -> m2ss0), bundle -> s2ms0) =
(((), unbundle s2ms1), unbundle m2ss1)
where
m2ss1 = scatter @_ @_ @_ @_ @0 (repeat emptyWishboneM2S) <$> route <*> m2ss0
s2ms1 = gather <$> s2ms0 <*> route
Expand Down
Loading