Skip to content

Commit 98a612c

Browse files
committed
Add Simulate instance for AXI4Lite
1 parent f4d557d commit 98a612c

File tree

3 files changed

+174
-80
lines changed

3 files changed

+174
-80
lines changed

src/Protocols/Axi4/Lite/Axi4Lite.hs

Lines changed: 168 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
{-# LANGUAGE FlexibleContexts #-}
22
{-# LANGUAGE FlexibleInstances #-}
33
{-# LANGUAGE UndecidableInstances #-}
4-
<<<<<<< HEAD
54
{-# LANGUAGE RecordWildCards #-}
6-
=======
7-
>>>>>>> cc790e6... Add AXI4 Lite types
85
{-|
96
Defines datatypes for all five channels of the AXI4 Lite protocol. For more
107
information on AXI4 Lite, see chapter B of the AMBA AXI specification.
@@ -15,15 +12,17 @@ module Protocols.Axi4.Lite.Axi4Lite where
1512
import Protocols
1613
import Protocols.Axi4.Common
1714
import Clash.Prelude as C
15+
import Clash.Signal.Internal
16+
import Data.List ((\\))
1817

1918
import 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
2325
data BusWidth = Width32 | Width64 deriving (Show, Eq, Generic, NFDataX)
24-
=======
25-
data BusWidth = Width32 | Width64 deriving (Show, Eq)
26-
>>>>>>> cc790e6... Add AXI4 Lite types
2726

2827
type instance Width 'Width32 = 32
2928
type 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'.
164159
data 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.
173166
data 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

src/Protocols/Df.hs

Lines changed: 0 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -75,17 +75,12 @@ import qualified Prelude as P
7575
import Clash.Prelude (type (<=))
7676
import Clash.Signal.Internal (Signal)
7777
import qualified Clash.Prelude as C
78-
import qualified Clash.Explicit.Prelude as CE
7978

8079
-- me
8180
import Protocols.Internal
8281
import Protocols.DfLike (DfLike)
8382
import qualified Protocols.DfLike as DfLike
8483

85-
<<<<<<< HEAD
86-
=======
87-
import Debug.Trace
88-
>>>>>>> cc790e6... Add AXI4 Lite types
8984

9085
-- $setup
9186
-- >>> import Protocols
@@ -165,52 +160,6 @@ instance (C.KnownDomain dom, C.NFDataX a, C.ShowX a, Show a) => Drivable (Df dom
165160
sampleC = sample
166161

167162

168-
simulateRight SimulationConfig{..} acks circ =
169-
P.take timeoutAfter $
170-
CE.sample_lazy $
171-
P.snd $
172-
toSignals circ ((), resetAndAcks)
173-
where
174-
resetAndAcks = C.fromList $ (P.map Ack (replicate resetCycles False) <> acks)
175-
176-
simulateLeft SimulationConfig{..} fwds circ = CE.sample_lazy ackSig
177-
where
178-
(ackSig, ()) = toSignals circ (dataSig, ())
179-
dataSig = C.fromList_lazy (ackedData resetCycles fwds (C.sample ackSig))
180-
181-
ackedData resetN _ (_:acks) | resetN > 0 =
182-
NoData : ackedData (resetN - 1) fwds acks
183-
ackedData _ _ [] = C.errorX "Empty acks list."
184-
ackedData _ [] (_:acks) = NoData : ackedData 0 [] acks
185-
ackedData _ (dat:datas) (ack:acks) = case ack of
186-
Ack True -> dat : ackedData 0 (datas) acks
187-
Ack False -> dat : ackedData 0 (dat:datas) acks
188-
189-
190-
191-
simulateManager SimulationConfig{..} acks circ =
192-
P.take timeoutAfter $
193-
CE.sample_lazy $
194-
P.snd $
195-
toSignals circ ((), resetAndAcks)
196-
where
197-
resetAndAcks = C.fromList $ (P.map Ack (replicate resetCycles False) <> acks)
198-
199-
-- TODO: apply simulation config
200-
simulateSubordinate SimulationConfig{..} fwds circ = CE.sample_lazy ackSig
201-
where
202-
(ackSig, ()) = toSignals circ (dataSig, ())
203-
dataSig = C.fromList_lazy (ackedData resetCycles fwds (C.sample ackSig))
204-
205-
ackedData resetN _ (_:acks) | resetN > 0 =
206-
NoData : ackedData (resetN - 1) fwds acks
207-
ackedData _ [] (_:acks) = NoData : ackedData 0 [] acks
208-
ackedData _ (dat:datas) (ack:acks) = case ack of
209-
Ack True -> dat : ackedData 0 (datas) acks
210-
Ack False -> dat : ackedData 0 (dat:datas) acks
211-
212-
213-
214163
instance DfLike dom (Df dom) a where
215164
type Data (Df dom) a = Data a
216165
type Payload a = a

src/Protocols/Internal.hs

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,7 @@ data StallAck
372372
-- some shape. The "Backpressure" instance requires that the /backward/ type of the
373373
-- circuit can be generated from a list of Booleans.
374374
class (C.KnownNat (SimulateChannels a), Backpressure a, Simulate a) => Drivable a where
375-
-- | Similar to 'SimulateType', but without backpressure information. For
375+
-- | Similar to 'SimulateFwdType', but without backpressure information. For
376376
-- example:
377377
--
378378
-- >>> :kind! (forall dom a. ExpectType (Df dom a))
@@ -385,7 +385,7 @@ class (C.KnownNat (SimulateChannels a), Backpressure a, Simulate a) => Drivable
385385
type ExpectType a :: Type
386386

387387
-- | Convert a /ExpectType a/, a type representing data without backpressure,
388-
-- into a type that does, /SimulateType a/.
388+
-- into a type that does, /SimulateFwdType a/.
389389
toSimulateType ::
390390
-- | Type witness
391391
Proxy a ->
@@ -395,7 +395,7 @@ class (C.KnownNat (SimulateChannels a), Backpressure a, Simulate a) => Drivable
395395
SimulateFwdType a
396396

397397
-- | Convert a /ExpectType a/, a type representing data without backpressure,
398-
-- into a type that does, /SimulateType a/.
398+
-- into a type that does, /SimulateFwdType a/.
399399
fromSimulateType ::
400400
-- | Type witness
401401
Proxy a ->
@@ -493,13 +493,6 @@ instance Drivable () where
493493
sampleC _ _ = ()
494494

495495

496-
simulateRight _ _ _ = ()
497-
simulateLeft _ _ _ = ()
498-
499-
simulateManager _ _ _ = ()
500-
simulateSubordinate _ _ _ = ()
501-
502-
503496
instance (Simulate a, Simulate b) => Simulate (a, b) where
504497
type SimulateFwdType (a, b) = (SimulateFwdType a, SimulateFwdType b)
505498
type SimulateBwdType (a, b) = (SimulateBwdType a, SimulateBwdType b)
@@ -621,9 +614,9 @@ instance (C.NFDataX a, C.ShowX a, Show a, C.KnownDomain dom) => Drivable (CSigna
621614
-- Not synthesizable.
622615
--
623616
-- To figure out what input you need to supply, either solve the type
624-
-- "SimulateType" manually, or let the repl do the work for you! Example:
617+
-- "SimulateFwdType" manually, or let the repl do the work for you! Example:
625618
--
626-
-- >>> :kind! (forall dom a. SimulateType (Df dom a))
619+
-- >>> :kind! (forall dom a. SimulateFwdType (Df dom a))
627620
-- ...
628621
-- = [Protocols.Df.Data a]
629622
--
@@ -687,6 +680,7 @@ simulateCSE c = simulateCS (c clk rst ena)
687680

688681
resetGen n = C.unsafeFromHighPolarity (C.fromList (replicate n True <> repeat False))
689682

683+
-- TODO: implement SimulationConfig
690684
simulateCircuit :: forall a b . (Simulate a, Simulate b) =>
691685
SimulateFwdType a -> SimulateBwdType b ->
692686
Circuit a b ->

0 commit comments

Comments
 (0)