Skip to content

Commit f4d557d

Browse files
committed
Add AXI4 Lite types
1 parent 289138f commit f4d557d

File tree

6 files changed

+107
-9
lines changed

6 files changed

+107
-9
lines changed

clash-protocols.cabal

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,8 @@ library
135135
-- To be removed; we need 'Test.Tasty.Hedgehog.Extra' to fix upstream issues
136136
, tasty >= 1.2 && < 1.5
137137
, tasty-hedgehog >= 1.2
138+
, tasty-th
139+
, strict-tuple
138140

139141
exposed-modules:
140142
Protocols
@@ -146,6 +148,7 @@ library
146148
Protocols.Axi4.WriteAddress
147149
Protocols.Axi4.WriteData
148150
Protocols.Axi4.WriteResponse
151+
Protocols.Axi4.Lite.Axi4Lite
149152

150153
Protocols.Df
151154
Protocols.DfLike
@@ -154,6 +157,7 @@ library
154157
Protocols.Internal
155158
Protocols.Plugin
156159

160+
157161
-- 'testProperty' is broken upstream, it reports wrong test names
158162
-- TODO: test / upstream ^
159163
Test.Tasty.Hedgehog.Extra

src/Protocols/Axi4/Common.hs

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ import Clash.Prelude (type (^), type (-), type (*))
1818
-- strict-tuple
1919
import Data.Tuple.Strict (T4)
2020

21+
import Control.DeepSeq
22+
2123
-- | Simple wrapper to achieve "named arguments" when instantiating an AXI protocol
2224
data IdWidth = IdWidth Nat
2325

@@ -70,10 +72,10 @@ data SKeepStrobe (strobeType :: KeepStrobe) where
7072
SNoStrobe :: SKeepStrobe 'NoStrobe
7173

7274
-- | Extracts Nat from 'IdWidth', 'AddrWidth', and 'LengthWidth'
73-
type family Width (a :: k) :: Nat where
74-
Width ('IdWidth n) = n
75-
Width ('AddrWidth n) = n
76-
Width ('LengthWidth n) = n
75+
type family Width (a :: k) :: Nat --where
76+
type instance Width ('IdWidth n) = n
77+
type instance Width ('AddrWidth n) = n
78+
type instance Width ('LengthWidth n) = n
7779

7880
-- | Enables or disables 'BurstMode'
7981
type family BurstType (keepBurst :: KeepBurst) where
@@ -102,7 +104,7 @@ type family LockType (keepLockType :: KeepLock) where
102104

103105
-- | Enables or disables 'Privileged', 'Secure', and 'InstructionOrData'
104106
type family PermissionsType (keepPermissions :: KeepPermissions) where
105-
PermissionsType 'KeepPermissions = T3 Privileged Secure InstructionOrData
107+
PermissionsType 'KeepPermissions = (Privileged, Secure, InstructionOrData)
106108
PermissionsType 'NoPermissions = ()
107109

108110
-- | Enables or disables 'Qos'
@@ -245,6 +247,19 @@ data Resp
245247
| RDecodeError
246248
deriving (Show, C.ShowX, Generic, C.NFDataX)
247249

250+
-- | Status of a read or write transaction on AXI4 Lite.
251+
data RespLite
252+
-- | Normal access success. Indicates that a normal access has been
253+
-- successful.
254+
= RLOkay
255+
-- | Slave error. Used when the access has reached the slave successfully, but
256+
-- the slave wishes to return an error condition to the originating master.
257+
| RLSlaveError
258+
-- | Decode error. Generated, typically by an interconnect component, to
259+
-- indicate that there is no slave at the transaction address.
260+
| RLDecodeError
261+
deriving (Show, C.ShowX, Generic, C.NFDataX)
262+
248263
-- | Whether a resource is accessed with exclusive access or not
249264
data AtomicAccess
250265
= NonExclusiveAccess
@@ -260,12 +275,14 @@ data Modifiable
260275
data Secure
261276
= Secure
262277
| NonSecure
278+
deriving (Show, Generic, C.NFDataX, NFData, C.ShowX, Eq)
263279

264280
-- | An AXI master might support more than one level of operating privilege,
265281
-- and extend this concept of privilege to memory access.
266282
data Privileged
267283
= NotPrivileged
268284
| Privileged
285+
deriving (Show, Generic, C.NFDataX, NFData, C.ShowX, Eq)
269286

270287
-- | Whether the transaction is an instruction access or a data access. The AXI
271288
-- protocol defines this indication as a hint. It is not accurate in all cases,
@@ -276,3 +293,4 @@ data Privileged
276293
data InstructionOrData
277294
= Data
278295
| Instruction
296+
deriving (Show, Generic, C.NFDataX, NFData, C.ShowX, Eq)

src/Protocols/Axi4/Lite/Axi4Lite.hs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
{-# LANGUAGE FlexibleContexts #-}
22
{-# LANGUAGE FlexibleInstances #-}
33
{-# LANGUAGE UndecidableInstances #-}
4+
<<<<<<< HEAD
45
{-# LANGUAGE RecordWildCards #-}
6+
=======
7+
>>>>>>> cc790e6... Add AXI4 Lite types
58
{-|
69
Defines datatypes for all five channels of the AXI4 Lite protocol. For more
710
information on AXI4 Lite, see chapter B of the AMBA AXI specification.
@@ -16,7 +19,11 @@ import Clash.Prelude as C
1619
import Control.DeepSeq
1720

1821
-- | AXI4 Lite busses are always either 32 bit or 64 bit.
22+
<<<<<<< HEAD
1923
data BusWidth = Width32 | Width64 deriving (Show, Eq, Generic, NFDataX)
24+
=======
25+
data BusWidth = Width32 | Width64 deriving (Show, Eq)
26+
>>>>>>> cc790e6... Add AXI4 Lite types
2027

2128
type instance Width 'Width32 = 32
2229
type instance Width 'Width64 = 64
@@ -33,6 +40,10 @@ type family ReadBusWidthType (bw :: BusWidth) where
3340
ReadBusWidthType 'Width32 = C.Vec 4 (C.BitVector 8)
3441
ReadBusWidthType 'Width64 = C.Vec 8 (C.BitVector 8)
3542

43+
<<<<<<< HEAD
44+
=======
45+
46+
>>>>>>> cc790e6... Add AXI4 Lite types
3647
---------------------------
3748
--- Write address types ---
3849
---------------------------

src/Protocols/Df.hs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,17 @@ 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
7879

7980
-- me
8081
import Protocols.Internal
8182
import Protocols.DfLike (DfLike)
8283
import qualified Protocols.DfLike as DfLike
8384

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

8590
-- $setup
8691
-- >>> import Protocols
@@ -137,6 +142,7 @@ dataToMaybe :: Data a -> Maybe a
137142
dataToMaybe NoData = Nothing
138143
dataToMaybe (Data a) = Just a
139144

145+
140146
instance (C.KnownDomain dom, C.NFDataX a, C.ShowX a, Show a) => Simulate (Df dom a) where
141147
type SimulateFwdType (Df dom a) = [Data a]
142148
type SimulateBwdType (Df dom a) = [Ack]
@@ -159,6 +165,52 @@ instance (C.KnownDomain dom, C.NFDataX a, C.ShowX a, Show a) => Drivable (Df dom
159165
sampleC = sample
160166

161167

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+
162214
instance DfLike dom (Df dom) a where
163215
type Data (Df dom) a = Data a
164216
type Payload a = a
@@ -441,6 +493,7 @@ registerBwd = DfLike.registerBwd Proxy
441493

442494
--------------------------------- SIMULATE -------------------------------------
443495

496+
444497
-- | Emit values given in list. Emits no data while reset is asserted. Not
445498
-- synthesizable.
446499
drive ::

src/Protocols/DfLike.hs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -595,7 +595,7 @@ fanin ::
595595
) =>
596596
(a -> a -> a) ->
597597
Circuit (C.Vec n (df x)) (df x)
598-
fanin f = bundleVec Proxy Proxy |> map Proxy Proxy (C.fold @(n-1) f)
598+
fanin f = bundleVec Proxy Proxy |> map Proxy Proxy (C.fold @(n-1) f)
599599
{-# INLINE fanin #-}
600600

601601
-- | Merge data of multiple streams using Monoid's '<>'.
@@ -673,7 +673,7 @@ unbundleVec dfX dfY =
673673

674674
-- Store new acks, send ack if all "clients" have acked
675675
acked1 = C.zipWith (||) acked (C.map (ackToBool dfY) acks)
676-
ack = C.fold @(n-1) (&&) acked1
676+
ack = C.fold @(n-1) (&&) acked1
677677
in
678678
( if ack then initState else acked1
679679
, (boolToAck dfX ack, dats1) )
@@ -776,7 +776,7 @@ roundrobinCollect dfA Parallel =
776776
acks = Maybe.fromMaybe nacks ((\i -> C.replace i ack nacks) <$> iM)
777777
dat1 = Maybe.fromMaybe (noData dfA) dat0
778778
(iM, dat0) = Data.List.NonEmpty.unzip dats1
779-
dats1 = C.fold @(n-1) (<|>) (C.zipWith goDat C.indicesI dats0)
779+
dats1 = C.fold @(n-1) (<|>) (C.zipWith goDat C.indicesI dats0)
780780

781781
goDat i dat
782782
| hasPayload dfA dat = Just (i, dat)
@@ -883,7 +883,9 @@ stall ::
883883
Proxy (df a) ->
884884
SimulationConfig ->
885885
-- | Acknowledgement to send when LHS does not send data. Stall will act
886-
-- transparently when reset is asserted.
886+
-- transparently when reset is asserted. A correct circuit would nack during reset,
887+
-- however since "stall" is used to debug other components it acts transparently as
888+
-- otherwise it may occlude the behavior of the components under test.
887889
StallAck ->
888890
-- Number of cycles to stall for every valid Df packet
889891
[Int] ->

src/Protocols/Internal.hs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ Internal module to prevent hs-boot files (breaks Haddock)
66
{-# LANGUAGE NamedFieldPuns #-}
77
{-# LANGUAGE TypeFamilyDependencies #-}
88
{-# LANGUAGE UndecidableInstances #-}
9+
{-# LANGUAGE MultiParamTypeClasses #-}
910

1011
module Protocols.Internal where
1112

@@ -145,6 +146,7 @@ newtype Circuit a b =
145146
newtype Ack = Ack Bool
146147
deriving (Generic, C.NFDataX, Show)
147148

149+
148150
-- | Acknowledge. Used in circuit-notation plugin to drive ignore components.
149151
instance Default Ack where
150152
def = Ack True
@@ -365,6 +367,7 @@ data StallAck
365367
| StallCycle
366368
deriving (Eq, Bounded, Enum, Show)
367369

370+
368371
-- | Class that defines how to /drive/, /sample/, and /stall/ a "Circuit" of
369372
-- some shape. The "Backpressure" instance requires that the /backward/ type of the
370373
-- circuit can be generated from a list of Booleans.
@@ -490,6 +493,13 @@ instance Drivable () where
490493
sampleC _ _ = ()
491494

492495

496+
simulateRight _ _ _ = ()
497+
simulateLeft _ _ _ = ()
498+
499+
simulateManager _ _ _ = ()
500+
simulateSubordinate _ _ _ = ()
501+
502+
493503
instance (Simulate a, Simulate b) => Simulate (a, b) where
494504
type SimulateFwdType (a, b) = (SimulateFwdType a, SimulateFwdType b)
495505
type SimulateBwdType (a, b) = (SimulateBwdType a, SimulateBwdType b)

0 commit comments

Comments
 (0)