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---------------------------
@@ -158,16 +153,12 @@ data S2M_ReadAddress
158153--- Read data types ---
159154-----------------------
160155
161- -- | Acknowledges data from the slave component. This data type needs the 'bw' type
162- -- to fullfil the injectivity requirement of 'Fwd' in 'Protocol', even though it only
163- -- contains a ready signal of type 'Bool'.
156+ -- | Acknowledges data from the slave component.
164157data M2S_ReadData
165- (bw :: BusWidth )
166158 = M2S_ReadData {
167159 _rready :: Bool
168- } deriving (Generic , NFDataX )
160+ } deriving (Generic , NFDataX , Show )
169161
170- deriving instance (Show (ReadBusWidthType bw )) => Show (M2S_ReadData bw )
171162
172163-- | Data type for the data sent over the read data channel from the slave to the master.
173164data S2M_ReadData
@@ -191,7 +182,7 @@ data M2S_Axi4Lite
191182 m2s_wd :: M2S_WriteData bw ,
192183 m2s_wr :: M2S_WriteResponse ,
193184 m2s_ra :: M2S_ReadAddress aw ,
194- m2s_rd :: M2S_ReadData bw
185+ m2s_rd :: M2S_ReadData
195186 }
196187 deriving (Generic )
197188
@@ -252,6 +243,164 @@ instance (C.KnownDomain dom, NFDataX (S2M_Axi4Lite aw bw)) => Simulate (Axi4Lite
252243 sigToSimFwd _ = C. sample_lazy
253244 sigToSimBwd _ = C. sample_lazy
254245
255- stallC SimulationConfig { .. } (waStalls :> wdStalls :> wrStalls :> raStalls :> rdStalls :> Nil ) = Circuit go
246+ stallC conf stallAckVector = Circuit go
256247 where
257- go (fwd, bwd) = (bwd, fwd)
248+ (waStalls:> wdStalls:> wrStalls:> raStalls:> rdStalls:> Nil ) = stallAckVector
249+ SimulationConfig {.. } = conf
250+ go :: (Signal dom (M2S_Axi4Lite aw bw ),
251+ Signal dom (S2M_Axi4Lite aw bw )) ->
252+ (Signal dom (S2M_Axi4Lite aw bw ),
253+ Signal dom (M2S_Axi4Lite aw bw ))
254+ go (fwd, bwd) = (bwd', fwd')
255+ where
256+ bwd' = S2M_Axi4Lite <$> waBwdOut <*> wdBwdOut <*> wrBwdOut <*> raBwdOut <*> rdBwdOut
257+ fwd' = M2S_Axi4Lite <$> waFwdOut <*> wdFwdOut <*> wrFwdOut <*> raFwdOut <*> rdFwdOut
258+
259+ (waFwd, wdFwd, wrFwd, raFwd, rdFwd) = dissectM2S fwd
260+ (waBwd, wdBwd, wrBwd, raBwd, rdBwd) = dissectS2M bwd
261+
262+ (waStallAck, waStallNs) = waStalls
263+ (waBwdOut, waFwdOut) = stallM2S (stallAcks waStallAck) waStallNs resetCycles waFwd waBwd
264+
265+ (wdStallAck, wdStallNs) = wdStalls
266+ (wdBwdOut, wdFwdOut) = stallM2S (stallAcks wdStallAck) wdStallNs resetCycles wdFwd wdBwd
267+
268+ (wrStallAck, wrStallNs) = wrStalls
269+ (wrBwdOut, wrFwdOut) = stallS2M (stallAcks wrStallAck) wrStallNs resetCycles wrFwd wrBwd
270+
271+ (raStallAck, raStallNs) = raStalls
272+ (raBwdOut, raFwdOut) = stallM2S (stallAcks raStallAck) raStallNs resetCycles raFwd raBwd
273+
274+ (rdStallAck, rdStallNs) = rdStalls
275+ (rdBwdOut, rdFwdOut) = stallS2M (stallAcks rdStallAck) rdStallNs resetCycles rdFwd rdBwd
276+
277+ dissectM2S (m :- m2s) =
278+ ( m2s_wa m :- waSig
279+ , m2s_wd m :- wdSig
280+ , m2s_wr m :- wrSig
281+ , m2s_ra m :- raSig
282+ , m2s_rd m :- rdSig )
283+ where
284+ (waSig, wdSig, wrSig, raSig, rdSig) = dissectM2S m2s
285+
286+ dissectS2M (s :- s2m) =
287+ ( s2m_wa s :- waSig
288+ , s2m_wd s :- wdSig
289+ , s2m_wr s :- wrSig
290+ , s2m_ra s :- raSig
291+ , s2m_rd s :- rdSig )
292+ where
293+ (waSig, wdSig, wrSig, raSig, rdSig) = dissectS2M s2m
294+
295+
296+ stallAcks stallAck = cycle saList
297+ where
298+ saList | stallAck == StallCycle = [minBound .. maxBound ] \\ [StallCycle ]
299+ | otherwise = [stallAck]
300+
301+
302+ stallM2S :: (Source src , Destination dst ) =>
303+ [StallAck ] -> [Int ] -> Int ->
304+ Signal dom src -> Signal dom dst ->
305+ (Signal dom dst , Signal dom src )
306+ stallM2S [] _ _ _ _ = error " finite stallAck list"
307+ stallM2S sas stalls resetN (f :- fwd) (b :- bwd) | resetN > 0 =
308+ B. bimap (b :- ) (f :- ) (stallM2S sas stalls (resetN - 1 ) fwd bwd)
309+ stallM2S (sa: sas) [] _ (f :- fwd) ~ (b :- bwd) =
310+ B. bimap (toStallAck (maybePayload f) (isReady b) sa :- ) (f :- ) (stallM2S sas [] 0 fwd bwd)
311+ stallM2S (sa: sas) stalls _ ((maybePayload -> Nothing ) :- fwd) ~ (b :- bwd) =
312+ B. bimap (b' :- ) (noData :- ) (stallM2S sas stalls 0 fwd bwd)
313+ where b' = toStallAck (Nothing :: Maybe (M2S_WriteAddress aw )) (isReady b) sa
314+ stallM2S (_: sas) (stall: stalls) _ (f0 :- fwd) ~ (b0 :- bwd) =
315+ let
316+ (f1, b1, stalls') = case compare 0 stall of
317+ LT -> (noData, ready False , (stall - 1 ): stalls)
318+ EQ -> (f0, b0, if isReady b0 then stalls else stall: stalls)
319+ GT -> error (" Unexpected negative stall: " <> show stall)
320+ in
321+ B. bimap (b1 :- ) (f1 :- ) (stallM2S sas stalls' 0 fwd bwd)
322+
323+ stallS2M :: (Destination dst , Source src ) =>
324+ [StallAck ] -> [Int ] -> Int ->
325+ Signal dom dst -> Signal dom src ->
326+ (Signal dom src , Signal dom dst )
327+ stallS2M sas stalls resetN fwd bwd = (src, dst)
328+ where (dst, src) = stallM2S sas stalls resetN bwd fwd
329+
330+ toStallAck :: (Source src , Destination dst ) => Maybe src -> Bool -> StallAck -> dst
331+ toStallAck (Just _) ack = const (ready ack)
332+ toStallAck Nothing ack = \ case
333+ StallWithNack -> ready False
334+ StallWithAck -> ready True
335+ StallWithErrorX -> C. errorX " No defined ack"
336+ StallTransparently -> ready ack
337+ StallCycle -> ready False -- shouldn't happen..
338+
339+ -- | Every data-carrying direction in a channel in AXI4 has a @<Channel>@ and @No<Channel>@
340+ -- constructor. In some functions (like "stallC") it is useful to write functions that
341+ -- use this fact such that these can be applied to every channel of AXI4. This typeclass
342+ -- provides functions to convert a value in a channel to @Maybe@, where the @No<Channel>@ is
343+ -- converted to @Nothing@, and any other value to @Just value@.
344+ --
345+ -- This class is called @Source@ because a source of useful data is the sender of the type
346+ -- for which this class is relevant.
347+ class Source src where
348+ -- | Converts a channel type to a @Maybe@
349+ maybePayload :: src -> Maybe src
350+ -- | The value of type "src" that is mapped to @Nothing@ by "maybePayload"
351+ noData :: src
352+
353+ -- | Typeclass to convert Booleans to channel-specific acknowledgement types.
354+ class Destination dst where
355+ ready :: Bool -> dst
356+ isReady :: dst -> Bool
357+
358+ instance Source (M2S_WriteAddress aw ) where
359+ maybePayload M2S_NoWriteAddress = Nothing
360+ maybePayload m2s_wa = Just m2s_wa
361+
362+ noData = M2S_NoWriteAddress
363+
364+ instance Destination S2M_WriteAddress where
365+ ready b = S2M_WriteAddress b
366+ isReady (S2M_WriteAddress b) = b
367+
368+ instance Source (M2S_WriteData bw ) where
369+ maybePayload M2S_NoWriteData = Nothing
370+ maybePayload m2s_wd = Just m2s_wd
371+
372+ noData = M2S_NoWriteData
373+
374+ instance Destination S2M_WriteData where
375+ ready b = S2M_WriteData b
376+ isReady (S2M_WriteData b) = b
377+
378+ instance Source (S2M_WriteResponse ) where
379+ maybePayload S2M_NoWriteResponse = Nothing
380+ maybePayload s2m_wr = Just s2m_wr
381+
382+ noData = S2M_NoWriteResponse
383+
384+ instance Destination (M2S_WriteResponse ) where
385+ ready b = M2S_WriteResponse b
386+ isReady (M2S_WriteResponse b) = b
387+
388+ instance Source (M2S_ReadAddress aw ) where
389+ maybePayload M2S_NoReadAddress = Nothing
390+ maybePayload m2s_ra = Just m2s_ra
391+
392+ noData = M2S_NoReadAddress
393+
394+ instance Destination S2M_ReadAddress where
395+ ready b = S2M_ReadAddress b
396+ isReady (S2M_ReadAddress b) = b
397+
398+ instance Source (S2M_ReadData bw ) where
399+ maybePayload S2M_NoReadData = Nothing
400+ maybePayload s2m_rd = Just s2m_rd
401+
402+ noData = S2M_NoReadData
403+
404+ instance Destination M2S_ReadData where
405+ ready b = M2S_ReadData b
406+ isReady (M2S_ReadData b) = b
0 commit comments