Skip to content

Commit

Permalink
Circuitify Bittide Node and components
Browse files Browse the repository at this point in the history
  • Loading branch information
lmbollen committed Sep 24, 2024
1 parent acf5d7b commit c7205ef
Show file tree
Hide file tree
Showing 4 changed files with 209 additions and 36 deletions.
1 change: 0 additions & 1 deletion bittide/src/Bittide/Ethernet/Mac.hs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ macStatusInterfaceWb ::
( CP.HiddenClockResetEnable dom
, KnownNat nBytes
, KnownNat aw
, 2 <= aw
, 1 <= nBytes
, counterWidth <= nBytes * 8
) =>
Expand Down
158 changes: 141 additions & 17 deletions bittide/src/Bittide/Node.hs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,17 @@
{-# LANGUAGE GADTs #-}
{-# OPTIONS_GHC -fconstraint-solver-iterations=6 #-}

{-# OPTIONS -fplugin=Protocols.Plugin #-}

module Bittide.Node where

import Clash.Prelude
import Clash.Sized.Vector.ToTuple (vecToTuple)

import Protocols
import Protocols.Idle
import Protocols.Internal (vecCircuits)
import Protocols.Wishbone

import VexRiscv

import Bittide.Calendar
Expand All @@ -21,8 +24,6 @@ import Bittide.ScatterGather
import Bittide.SharedTypes
import Bittide.Switch

import Control.Arrow ((&&&))

{- | A simple node consisting of one external bidirectional link and two 'gppe's.
This node's 'switch' has a 'CalendarConfig' of for a 'calendar' with up to @1024@ entries,
however, the 'calendar' is initialized with a single entry of repeated zeroes.
Expand Down Expand Up @@ -74,20 +75,19 @@ node ::
forall dom extLinks gppes.
(HiddenClockResetEnable dom, KnownNat extLinks, KnownNat gppes) =>
NodeConfig extLinks gppes ->
Vec extLinks (Signal dom (DataLink 64)) ->
Vec extLinks (Signal dom (DataLink 64))
node (NodeConfig nmuConfig switchConfig gppeConfigs) linksIn = linksOut
where
(switchOut, swS2M) = switch switchConfig swM2S switchIn
switchIn = nmuToSwitch :> pesToSwitch ++ linksIn
(splitAtI -> ((head &&& tail) -> (switchToNmu, switchToPes), linksOut)) = switchOut
(nmuToSwitch, nmuM2Ss) = managementUnit nmuConfig switchToNmu nmuS2Ms
(swM2S, peM2Ss) = (head &&& tail) nmuM2Ss

nmuS2Ms = swS2M :> peS2Ms
Circuit
(Vec extLinks (CSignal dom (DataLink 64)))
(Vec extLinks (CSignal dom (DataLink 64)))
node (NodeConfig nmuConfig switchConfig gppeConfigs) = circuit $ \linksIn -> do
switchOut <- (switchC @_ @_ @_ @_ @64 switchConfig) -< (switchIn, swWb)
switchIn <- appendC3 -< ([nmuLinkOut], pesToSwitch, linksIn)
([nmuLinkIn], switchToPes, linksOut) <- splitC3 -< switchOut
(nmuLinkOut, nmuWbs0) <- managementUnitC nmuConfig -< nmuLinkIn
([swWb], nmuWbs1) <- splitAtC d1 -< nmuWbs0
peWbs <- unconcatC d2 -< nmuWbs1

(pesToSwitch, concat -> peS2Ms) =
unzip $ gppe <$> zip3 gppeConfigs switchToPes (unconcatI peM2Ss)
pesToSwitch <- vecCircuits (map gppeC gppeConfigs) <| zipC -< (switchToPes, peWbs)
idC -< linksOut

type NmuInternalBusses = 6
type NmuRemBusWidth nodeBusses = 30 - CLog 2 (nodeBusses + NmuInternalBusses)
Expand Down Expand Up @@ -158,11 +158,30 @@ gppe (GppeConfig scatterConfig gatherConfig peConfig, linkIn, vecToTuple -> (nmu

{-# NOINLINE managementUnit #-}

gppeC ::
(KnownNat nmuRemBusWidth, HiddenClockResetEnable dom) =>
-- | Configures all local parameters
GppeConfig nmuRemBusWidth ->
-- |
-- ( Incoming 'Bittide.Link'
-- , Incoming @Vector@ of master busses
-- )
Circuit
(CSignal dom (DataLink 64), Vec 2 (Wishbone dom 'Standard nmuRemBusWidth (Bytes 4)))
(CSignal dom (DataLink 64))
gppeC (GppeConfig scatterConfig gatherConfig peConfig) = circuit $ \(linkIn, nmuWbs) -> do
[wbScatCal, wbGathCal] <- idC -< nmuWbs
jtag <- idleSource -< ()
[wbScat, wbGu] <- processingElement peConfig -< jtag
linkOut <- gatherUnitWbC gatherConfig -< (wbGu, wbGathCal)
scatterUnitWbC scatterConfig -< (linkIn, wbScat, wbScatCal)
idC -< linkOut

{- | A special purpose 'processingElement' that manages a Bittide Node. It contains
a 'processingElement', 'linkToPe' and 'peToLink' which create the interface for the
Bittide Link. It takes a 'ManagementConfig', incoming link and a vector of incoming
'WishboneS2M' signals and produces the outgoing link alongside a vector of
'WishhboneM2S' signals.
'WishboneM2S' signals.
-}
managementUnit ::
forall dom nodeBusses.
Expand Down Expand Up @@ -191,3 +210,108 @@ managementUnit (ManagementConfig scatterConfig gatherConfig peConfig) linkIn nod
(vecToTuple -> (nmuM2S0, nmuM2S1), nodeM2Ss) = splitAtI rest
(_, nmuM2Ss) = toSignals (processingElement peConfig) (pure $ JtagIn low low low, nmuS2Ms)
nmuS2Ms = suS2M :> guS2M :> nmuS2M0 :> nmuS2M1 :> nodeS2Ms

managementUnitC ::
forall dom nodeBusses.
( HiddenClockResetEnable dom
, CLog 2 (nodeBusses + NmuInternalBusses) <= 30
) =>
-- |
-- ( Configures all local parameters
-- , Incoming 'Bittide.Link'
-- , Incoming @Vector@ of master busses
-- )
ManagementConfig nodeBusses ->
Circuit
(CSignal dom (DataLink 64))
( CSignal dom (DataLink 64)
, Vec nodeBusses (Wishbone dom 'Standard (NmuRemBusWidth nodeBusses) (Bytes 4))
)
managementUnitC (ManagementConfig scatterConfig gatherConfig peConfig) = circuit $ \linkIn -> do
jtag <- idleSource -< ()
peWbs <- processingElement peConfig -< jtag
([wbScatCal, wbScat, wbGathCal, wbGu], nmuWbs) <- splitAtC d4 -< peWbs
linkOut <- gatherUnitWbC gatherConfig -< (wbGu, wbGathCal)
scatterUnitWbC scatterConfig -< (linkIn, wbScat, wbScatCal)
idC -< (linkOut, nmuWbs)

-- Append two separate vectors of the same circuits into one vector of circuits
appendC ::
(KnownNat n0) =>
Circuit (Vec n0 circuit, Vec n1 circuit) (Vec (n0 + n1) circuit)
appendC = Circuit go
where
go ((fwd0, fwd1), splitAtI -> (bwd0, bwd1)) = ((bwd0, bwd1), (fwd0 ++ fwd1))

-- Append three separate vectors of the same circuits into one vector of circuits
appendC3 ::
(KnownNat n0, KnownNat n1) =>
Circuit (Vec n0 circuit, Vec n1 circuit, Vec n2 circuit) (Vec (n0 + n1 + n2) circuit)
appendC3 = Circuit go
where
go ((fwd0, fwd1, fwd2), splitAtI -> (bwd0, splitAtI -> (bwd1, bwd2))) = ((bwd0, bwd1, bwd2), (fwd0 ++ fwd1 ++ fwd2))

-- Transforms two vectors of circuits into a vector of tuples of circuits.
-- Only works if the two vectors have the same length.
zipC ::
(KnownNat n) =>
Circuit (Vec n a, Vec n b) (Vec n (a, b))
zipC = Circuit go
where
go ((fwd0, fwd1), bwd) = (unzip bwd, zip fwd0 fwd1)

-- Transforms three vectors of circuits into a vector of tuples of circuits.
-- Only works if the three vectors have the same length.
zipC3 ::
(KnownNat n) =>
Circuit (Vec n a, Vec n b, Vec n c) (Vec n (a, b, c))
zipC3 = Circuit go
where
go ((fwd0, fwd1, fwd2), bwd) = (unzip3 bwd, zip3 fwd0 fwd1 fwd2)

-- Split a vector of circuits into two vectors of circuits.
splitC ::
(KnownNat n0) =>
Circuit (Vec (n0 + n1) circuit) (Vec n0 circuit, Vec n1 circuit)
splitC = Circuit go
where
go (splitAtI -> (fwd0, fwd1), (bwd0, bwd1)) = (bwd0 ++ bwd1, (fwd0, fwd1))

-- Split a vector of circuits into three vectors of circuits.
splitC3 ::
(KnownNat n0, KnownNat n1) =>
Circuit (Vec (n0 + n1 + n2) circuit) (Vec n0 circuit, Vec n1 circuit, Vec n2 circuit)
splitC3 = Circuit go
where
go (splitAtI -> (fwd0, splitAtI -> (fwd1, fwd2)), (bwd0, bwd1, bwd2)) = (bwd0 ++ bwd1 ++ bwd2, (fwd0, fwd1, fwd2))

-- Unzip a vector of tuples of circuits into a tuple of vectors of circuits.
unzipC ::
(KnownNat n) =>
Circuit (Vec n (a, b)) (Vec n a, Vec n b)
unzipC = Circuit go
where
go (fwd, (bwd0, bwd1)) = (zip bwd0 bwd1, unzip fwd)

-- Unzip a vector of 3-tuples of circuits into a 3-tuple of vectors of circuits.
unzipC3 ::
(KnownNat n) =>
Circuit (Vec n (a, b, c)) (Vec n a, Vec n b, Vec n c)
unzipC3 = Circuit go
where
go (fwd, (bwd0, bwd1, bwd2)) = (zip3 bwd0 bwd1 bwd2, unzip3 fwd)

concatC ::
(KnownNat n0, KnownNat n1) =>
Circuit (Vec n0 (Vec n1 circuit)) (Vec (n0 * n1) circuit)
concatC = Circuit go
where
go (fwd, bwd) = (unconcat SNat bwd, concat fwd)

unconcatC ::
(KnownNat n, KnownNat m) =>
SNat m ->
Circuit (Vec (n * m) circuit) (Vec n (Vec m circuit))
unconcatC SNat = Circuit go
where
go (fwd, bwd) = (concat bwd, unconcat SNat fwd)
78 changes: 64 additions & 14 deletions bittide/src/Bittide/ScatterGather.hs
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,25 @@

module Bittide.ScatterGather (
scatterUnitWb,
scatterUnitWbC,
ScatterConfig (..),
gatherUnitWb,
gatherUnitWbC,
GatherConfig (..),
) where

import Clash.Prelude

import Protocols.Wishbone

import Bittide.Calendar
import Bittide.DoubleBufferedRam
import Bittide.Extra.Maybe
import Bittide.SharedTypes

import Protocols
import Protocols.Wishbone

import Data.Constraint.Nat.Extra

{- | Existential type to explicitly differentiate between a configuration for
the 'scatterUnitWb' and 'gatherUnitWb' at type level and hide the memory depth from
higher level APIs.
Expand Down Expand Up @@ -185,26 +190,49 @@ addStalling endOfMetacycle (incomingBus@WishboneS2M{..}, wbAddr, writeOp0) =

{-# NOINLINE scatterUnitWb #-}

scatterUnitWbC ::
forall dom awSu nBytesCal awCal.
( HiddenClockResetEnable dom
, KnownNat awSu
, KnownNat nBytesCal
, 1 <= nBytesCal
, KnownNat awCal
) =>
-- | Configuration for the 'calendar'.
ScatterConfig nBytesCal awCal ->
Circuit
( CSignal dom (DataLink 64)
, Wishbone dom 'Standard awSu (Bytes 4)
, Wishbone dom 'Standard awCal (Bytes nBytesCal)
)
()
scatterUnitWbC conf = case cancelMulDiv @nBytesCal @8 of
Dict -> Circuit go
where
go ((linkIn, wbM2SSu, wbM2SCal), _) = ((pure (), wbS2MSu, wbS2MCal), ())
where
(wbS2MSu, wbS2MCal) = scatterUnitWb conf wbM2SCal linkIn wbM2SSu

{- | Wishbone addressable 'scatterUnit', the wishbone port can read the data from this
memory element as if it has a 32 bit port by selecting the upper 32 or lower 32 bits
of the read data.
-}
scatterUnitWb ::
forall dom addrWidthSu nBytesCal addrWidthCal.
forall dom awSu nBytesCal awCal.
( HiddenClockResetEnable dom
, KnownNat addrWidthSu
, KnownNat awSu
, KnownNat nBytesCal
, 1 <= nBytesCal
, KnownNat addrWidthCal
, KnownNat awCal
) =>
-- | Configuration for the 'calendar'.
ScatterConfig nBytesCal addrWidthCal ->
ScatterConfig nBytesCal awCal ->
-- | Wishbone (master -> slave) port 'calendar'.
Signal dom (WishboneM2S addrWidthCal nBytesCal (Bytes nBytesCal)) ->
Signal dom (WishboneM2S awCal nBytesCal (Bytes nBytesCal)) ->
-- | Incoming frame from Bittide link.
Signal dom (DataLink 64) ->
-- | Wishbone (master -> slave) port scatter memory.
Signal dom (WishboneM2S addrWidthSu 4 (Bytes 4)) ->
Signal dom (WishboneM2S awSu 4 (Bytes 4)) ->
-- |
-- 1. Wishbone (slave -> master) port scatter memory
-- 2. Wishbone (slave -> master) port 'calendar'
Expand All @@ -226,24 +254,46 @@ scatterUnitWb (ScatterConfig calConfig) wbInCal linkIn wbInSu =

{-# NOINLINE gatherUnitWb #-}

gatherUnitWbC ::
forall dom awGu nBytesCal awCal.
( HiddenClockResetEnable dom
, KnownNat awGu
, KnownNat nBytesCal
, 1 <= nBytesCal
, KnownNat awCal
) =>
-- | Configuration for the 'calendar'.
GatherConfig nBytesCal awCal ->
Circuit
( Wishbone dom 'Standard awGu (Bytes 4)
, Wishbone dom 'Standard awCal (Bytes nBytesCal)
)
(CSignal dom (DataLink 64))
gatherUnitWbC conf = case (cancelMulDiv @nBytesCal @8) of
Dict -> Circuit go
where
go ((wbInGu, wbInCal), _) = ((wbOutGu, wbOutCal), linkOut)
where
(linkOut, wbOutGu, wbOutCal) = gatherUnitWb conf wbInCal wbInGu

{- | Wishbone addressable 'gatherUnit', the wishbone port can write data to this
memory element as if it has a 32 bit port by controlling the byte enables of the
'gatherUnit' based on the third bit.
-}
gatherUnitWb ::
forall dom addrWidthGu nBytesCal addrWidthCal.
forall dom awGu nBytesCal awCal.
( HiddenClockResetEnable dom
, KnownNat addrWidthGu
, KnownNat awGu
, KnownNat nBytesCal
, 1 <= nBytesCal
, KnownNat addrWidthCal
, KnownNat awCal
) =>
-- | Configuration for the 'calendar'.
GatherConfig nBytesCal addrWidthCal ->
GatherConfig nBytesCal awCal ->
-- | Wishbone (master -> slave) data 'calendar'.
Signal dom (WishboneM2S addrWidthCal nBytesCal (Bytes nBytesCal)) ->
Signal dom (WishboneM2S awCal nBytesCal (Bytes nBytesCal)) ->
-- | Wishbone (master -> slave) port gather memory.
Signal dom (WishboneM2S addrWidthGu 4 (Bytes 4)) ->
Signal dom (WishboneM2S awGu 4 (Bytes 4)) ->
-- |
-- 1. Wishbone (slave -> master) port gather memory
-- 2. Wishbone (slave -> master) port 'calendar'
Expand Down
8 changes: 4 additions & 4 deletions bittide/src/Bittide/Switch.hs
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,14 @@ switchC ::
) =>
CalendarConfig nBytes addrW (CalendarEntry links) ->
Circuit
( CSignal dom (Vec links (DataLink frameWidth))
, Wishbone dom 'Standard addrW (Bytes nBytes)
( Vec links (CSignal dom (DataLink frameWidth))
, Wishbone dom 'Standard addrW (Bytes nBytes) -- calendar interface
)
(CSignal dom (Vec links (DataLink frameWidth)))
(Vec links (CSignal dom (DataLink frameWidth)))
switchC conf = case (cancelMulDiv @nBytes @8) of
Dict -> Circuit go
where
go ((unbundle -> streamsIn, calM2S), _) = ((pure (), calS2M), bundle streamsOut)
go ((streamsIn, calM2S), _) = ((repeat $ pure (), calS2M), streamsOut)
where
(streamsOut, calS2M) = switch conf calM2S streamsIn

Expand Down

0 comments on commit c7205ef

Please sign in to comment.