11{-# LANGUAGE FlexibleContexts #-}
22{-# LANGUAGE FlexibleInstances #-}
33{-# LANGUAGE UndecidableInstances #-}
4- <<<<<<< HEAD
54{-# LANGUAGE RecordWildCards #-}
6- =======
7- >>>>>>> cc790e6... Add AXI4 Lite types
85{-|
96Defines datatypes for all five channels of the AXI4 Lite protocol. For more
107information on AXI4 Lite, see chapter B of the AMBA AXI specification.
@@ -15,15 +12,17 @@ module Protocols.Axi4.Lite.Axi4Lite where
1512import Protocols
1613import Protocols.Axi4.Common
1714import Clash.Prelude as C
15+ import Clash.Signal.Internal
16+ import Data.List ((\\) )
1817
1918import Control.DeepSeq
2019
20+ import qualified Data.Bifunctor as B
21+
22+
23+
2124-- | AXI4 Lite busses are always either 32 bit or 64 bit.
22- <<<<<<< HEAD
2325data BusWidth = Width32 | Width64 deriving (Show , Eq , Generic , NFDataX )
24- =======
25- data BusWidth = Width32 | Width64 deriving (Show , Eq )
26- >>>>>>> cc790e6... Add AXI4 Lite types
2726
2827type instance Width 'Width32 = 32
2928type instance Width 'Width64 = 64
@@ -40,10 +39,6 @@ type family ReadBusWidthType (bw :: BusWidth) where
4039 ReadBusWidthType 'Width32 = C. Vec 4 (C. BitVector 8 )
4140 ReadBusWidthType 'Width64 = C. Vec 8 (C. BitVector 8 )
4241
43- <<<<<<< HEAD
44- =======
45-
46- >>>>>>> cc790e6... Add AXI4 Lite types
4742---------------------------
4843--- Write address types ---
4944---------------------------
@@ -162,12 +157,10 @@ data S2M_ReadAddress
162157-- to fullfil the injectivity requirement of 'Fwd' in 'Protocol', even though it only
163158-- contains a ready signal of type 'Bool'.
164159data M2S_ReadData
165- (bw :: BusWidth )
166160 = M2S_ReadData {
167161 _rready :: Bool
168- } deriving (Generic , NFDataX )
162+ } deriving (Generic , NFDataX , Show )
169163
170- deriving instance (Show (ReadBusWidthType bw )) => Show (M2S_ReadData bw )
171164
172165-- | Data type for the data sent over the read data channel from the slave to the master.
173166data S2M_ReadData
@@ -191,7 +184,7 @@ data M2S_Axi4Lite
191184 m2s_wd :: M2S_WriteData bw ,
192185 m2s_wr :: M2S_WriteResponse ,
193186 m2s_ra :: M2S_ReadAddress aw ,
194- m2s_rd :: M2S_ReadData bw
187+ m2s_rd :: M2S_ReadData
195188 }
196189 deriving (Generic )
197190
@@ -252,6 +245,164 @@ instance (C.KnownDomain dom, NFDataX (S2M_Axi4Lite aw bw)) => Simulate (Axi4Lite
252245 sigToSimFwd _ = C. sample_lazy
253246 sigToSimBwd _ = C. sample_lazy
254247
255- stallC SimulationConfig { .. } (waStalls :> wdStalls :> wrStalls :> raStalls :> rdStalls :> Nil ) = Circuit go
248+ stallC conf stallAckVector = Circuit go
256249 where
257- go (fwd, bwd) = (bwd, fwd)
250+ (waStalls:> wdStalls:> wrStalls:> raStalls:> rdStalls:> Nil ) = stallAckVector
251+ SimulationConfig {.. } = conf
252+ go :: (Signal dom (M2S_Axi4Lite aw bw ),
253+ Signal dom (S2M_Axi4Lite aw bw )) ->
254+ (Signal dom (S2M_Axi4Lite aw bw ),
255+ Signal dom (M2S_Axi4Lite aw bw ))
256+ go (fwd, bwd) = (bwd', fwd')
257+ where
258+ bwd' = S2M_Axi4Lite <$> waBwdOut <*> wdBwdOut <*> wrBwdOut <*> raBwdOut <*> rdBwdOut
259+ fwd' = M2S_Axi4Lite <$> waFwdOut <*> wdFwdOut <*> wrFwdOut <*> raFwdOut <*> rdFwdOut
260+
261+ (waFwd, wdFwd, wrFwd, raFwd, rdFwd) = dissectM2S fwd
262+ (waBwd, wdBwd, wrBwd, raBwd, rdBwd) = dissectS2M bwd
263+
264+ (waStallAck, waStallNs) = waStalls
265+ (waBwdOut, waFwdOut) = stallM2S (stallAcks waStallAck) waStallNs resetCycles waFwd waBwd
266+
267+ (wdStallAck, wdStallNs) = wdStalls
268+ (wdBwdOut, wdFwdOut) = stallM2S (stallAcks wdStallAck) wdStallNs resetCycles wdFwd wdBwd
269+
270+ (wrStallAck, wrStallNs) = wrStalls
271+ (wrBwdOut, wrFwdOut) = stallS2M (stallAcks wrStallAck) wrStallNs resetCycles wrFwd wrBwd
272+
273+ (raStallAck, raStallNs) = raStalls
274+ (raBwdOut, raFwdOut) = stallM2S (stallAcks raStallAck) raStallNs resetCycles raFwd raBwd
275+
276+ (rdStallAck, rdStallNs) = rdStalls
277+ (rdBwdOut, rdFwdOut) = stallS2M (stallAcks rdStallAck) rdStallNs resetCycles rdFwd rdBwd
278+
279+ dissectM2S (m :- m2s) =
280+ ( m2s_wa m :- waSig
281+ , m2s_wd m :- wdSig
282+ , m2s_wr m :- wrSig
283+ , m2s_ra m :- raSig
284+ , m2s_rd m :- rdSig )
285+ where
286+ (waSig, wdSig, wrSig, raSig, rdSig) = dissectM2S m2s
287+
288+ dissectS2M (s :- s2m) =
289+ ( s2m_wa s :- waSig
290+ , s2m_wd s :- wdSig
291+ , s2m_wr s :- wrSig
292+ , s2m_ra s :- raSig
293+ , s2m_rd s :- rdSig )
294+ where
295+ (waSig, wdSig, wrSig, raSig, rdSig) = dissectS2M s2m
296+
297+
298+ stallAcks stallAck = cycle saList
299+ where
300+ saList | stallAck == StallCycle = [minBound .. maxBound ] \\ [StallCycle ]
301+ | otherwise = [stallAck]
302+
303+
304+ stallM2S :: (Source src , Destination dst ) =>
305+ [StallAck ] -> [Int ] -> Int ->
306+ Signal dom src -> Signal dom dst ->
307+ (Signal dom dst , Signal dom src )
308+ stallM2S [] _ _ _ _ = error " finite stallAck list"
309+ stallM2S sas stalls resetN (f :- fwd) (b :- bwd) | resetN > 0 =
310+ B. bimap (b :- ) (f :- ) (stallM2S sas stalls (resetN - 1 ) fwd bwd)
311+ stallM2S (sa: sas) [] _ (f :- fwd) ~ (b :- bwd) =
312+ B. bimap (toStallAck (maybePayload f) (isReady b) sa :- ) (f :- ) (stallM2S sas [] 0 fwd bwd)
313+ stallM2S (sa: sas) stalls _ ((maybePayload -> Nothing ) :- fwd) ~ (b :- bwd) =
314+ B. bimap (b' :- ) (noData :- ) (stallM2S sas stalls 0 fwd bwd)
315+ where b' = toStallAck (Nothing :: Maybe (M2S_WriteAddress aw )) (isReady b) sa
316+ stallM2S (_: sas) (stall: stalls) _ (f0 :- fwd) ~ (b0 :- bwd) =
317+ let
318+ (f1, b1, stalls') = case compare 0 stall of
319+ LT -> (noData, ready False , (stall - 1 ): stalls)
320+ EQ -> (f0, b0, if isReady b0 then stalls else stall: stalls)
321+ GT -> error (" Unexpected negative stall: " <> show stall)
322+ in
323+ B. bimap (b1 :- ) (f1 :- ) (stallM2S sas stalls' 0 fwd bwd)
324+
325+ stallS2M :: (Destination dst , Source src ) =>
326+ [StallAck ] -> [Int ] -> Int ->
327+ Signal dom dst -> Signal dom src ->
328+ (Signal dom src , Signal dom dst )
329+ stallS2M sas stalls resetN fwd bwd = (src, dst)
330+ where (dst, src) = stallM2S sas stalls resetN bwd fwd
331+
332+ toStallAck :: (Source src , Destination dst ) => Maybe src -> Bool -> StallAck -> dst
333+ toStallAck (Just _) ack = const (ready ack)
334+ toStallAck Nothing ack = \ case
335+ StallWithNack -> ready False
336+ StallWithAck -> ready True
337+ StallWithErrorX -> C. errorX " No defined ack"
338+ StallTransparently -> ready ack
339+ StallCycle -> ready False -- shouldn't happen..
340+
341+ -- | Every data-carrying direction in a channel in AXI4 has a @<Channel>@ and @No<Channel>@
342+ -- constructor. In some functions (like "stallC") it is useful to write functions that
343+ -- use this fact such that these can be applied to every channel of AXI4. This typeclass
344+ -- provides functions to convert a value in a channel to @Maybe@, where the @No<Channel>@ is
345+ -- converted to @Nothing@, and any other value to @Just value@.
346+ --
347+ -- This class is called @Source@ because a source of useful data is the sender of the type
348+ -- for which this class is relevant.
349+ class Source src where
350+ -- | Converts a channel type to a @Maybe@
351+ maybePayload :: src -> Maybe src
352+ -- | The value of type "src" that is mapped to @Nothing@ by "maybePayload"
353+ noData :: src
354+
355+ -- | Typeclass to convert Booleans to channel-specific acknowledgement types.
356+ class Destination dst where
357+ ready :: Bool -> dst
358+ isReady :: dst -> Bool
359+
360+ instance Source (M2S_WriteAddress aw ) where
361+ maybePayload M2S_NoWriteAddress = Nothing
362+ maybePayload m2s_wa = Just m2s_wa
363+
364+ noData = M2S_NoWriteAddress
365+
366+ instance Destination S2M_WriteAddress where
367+ ready b = S2M_WriteAddress b
368+ isReady (S2M_WriteAddress b) = b
369+
370+ instance Source (M2S_WriteData bw ) where
371+ maybePayload M2S_NoWriteData = Nothing
372+ maybePayload m2s_wd = Just m2s_wd
373+
374+ noData = M2S_NoWriteData
375+
376+ instance Destination S2M_WriteData where
377+ ready b = S2M_WriteData b
378+ isReady (S2M_WriteData b) = b
379+
380+ instance Source (S2M_WriteResponse ) where
381+ maybePayload S2M_NoWriteResponse = Nothing
382+ maybePayload s2m_wr = Just s2m_wr
383+
384+ noData = S2M_NoWriteResponse
385+
386+ instance Destination (M2S_WriteResponse ) where
387+ ready b = M2S_WriteResponse b
388+ isReady (M2S_WriteResponse b) = b
389+
390+ instance Source (M2S_ReadAddress aw ) where
391+ maybePayload M2S_NoReadAddress = Nothing
392+ maybePayload m2s_ra = Just m2s_ra
393+
394+ noData = M2S_NoReadAddress
395+
396+ instance Destination S2M_ReadAddress where
397+ ready b = S2M_ReadAddress b
398+ isReady (S2M_ReadAddress b) = b
399+
400+ instance Source (S2M_ReadData bw ) where
401+ maybePayload S2M_NoReadData = Nothing
402+ maybePayload s2m_rd = Just s2m_rd
403+
404+ noData = S2M_NoReadData
405+
406+ instance Destination M2S_ReadData where
407+ ready b = M2S_ReadData b
408+ isReady (M2S_ReadData b) = b
0 commit comments