Commit 7ddb1c64 authored by Ben Gamari's avatar Ben Gamari
Browse files

Some spring cleaning

parent 32e8cd86
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE ApplicativeDo #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE NoImplicitPrelude #-}
-- | An AXI3 slave
module Axi
( axiSlave
, ReadRequest(..)
, ReadResponse(..)
, module Axi.Types
) where
import Clash.Signal
import Clash.Prelude
import Axi.Types
import Axi.Read
import Axi.Write
axiSlave :: (HasClockReset clk k f, KnownNat idWidth, KnownNat dataWidth, KnownNat (8*dataWidth))
=> Signal clk (AxiIn idWidth dataWidth)
-> Signal clk (Maybe (ReadResponse dataWidth))
-> Signal clk (Maybe WriteConfirmation)
-> Signal clk ( AxiOut idWidth dataWidth
, Maybe (ReadRequest dataWidth)
, Maybe (WriteRequest dataWidth)
)
axiSlave axiIn readResp writeConfirm =
let readRes = mealy readT ReadIdle
((,) <$> fmap _axiReadIn axiIn <*> register Nothing readResp)
writeRes = mealy writeT WriteIdle
((,) <$> fmap _axiWriteIn axiIn <*> register Nothing writeConfirm)
f (readReq, readOut) (writeReq, writeOut) =
( AxiOut writeOut readOut
, readReq
, writeReq
)
in f <$> readRes <*> writeRes
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE ApplicativeDo #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE NoImplicitPrelude #-}
module Axi.Read where
import GHC.Generics
import Control.Lens
import Clash.Signal
import Clash.Prelude
import Control.DeepSeq
import Axi.Types
import Utils
defAxiReadOut :: (KnownNat idWidth, KnownNat (8*dataWidth))
=> AxiReadOut idWidth dataWidth
defAxiReadOut = AxiReadOut
{ _arready = False
, _rid = errorX "not valid"
, _rdata = errorX "not valid"
, _rresp = errorX "not valid"
, _rlast = False
, _rvalid = False
}
data ReadState idWidth dataWidth
= -- | Waiting for @arvalid@
ReadIdle
-- | Have read request, waiting for data from backing store
| ReadDataWait (TransactionParams idWidth) BurstLength (Address dataWidth)
-- | Have data, waiting for @rready@
| ReadConfirmWait (TransactionParams idWidth) BurstLength (Address dataWidth) (Data dataWidth)
deriving (Generic)
instance (KnownNat x, KnownNat y) => ShowX (ReadState x y)
data ReadRequest dataWidth
= ReadRequest { readReqAddr :: Address dataWidth
}
deriving (Generic)
instance (KnownNat dataWidth) => ShowX (ReadRequest dataWidth)
newtype ReadResponse dataWidth
= ReadResponse (Data dataWidth)
deriving (Generic)
instance (KnownNat dataWidth) => ShowX (ReadResponse dataWidth)
readT :: forall idWidth dataWidth.
(KnownNat idWidth, KnownNat (8*dataWidth), KnownNat dataWidth)
=> ReadState idWidth dataWidth
-> (AxiReadIn idWidth dataWidth, Maybe (ReadResponse dataWidth))
-> ( ReadState idWidth dataWidth
, (Maybe (ReadRequest dataWidth), AxiReadOut idWidth dataWidth)
)
-- Waiting for read request
readT ReadIdle (AxiReadIn{..}, Nothing)
| _arvalid
= let params = TransParams { burstType = _arburst
, burstSize = _arsize
, transId = _arid
}
in ( ReadDataWait params _arlen _araddr
, (Just (ReadRequest _araddr), defAxiReadOut { _arready = True })
)
| otherwise
= ( ReadIdle
, (Nothing, defAxiReadOut { _arready = True })
)
-- Catch read requests when not idle
readT _ (axiIn, _)
| axiIn ^. arvalid
= error "uh oh"
-- Waiting for data from data source
readT s@(ReadDataWait _ _ addr) (_, Nothing)
= ( s
, (Nothing, defAxiReadOut)
)
readT (ReadDataWait params xfersRem addr) (_, Just (ReadResponse dat))
= ( ReadConfirmWait params xfersRem addr dat
, (Nothing, defAxiReadOut)
)
-- Waiting for confirmation from master
readT s@(ReadConfirmWait params xfersRem addr dat) (axiIn, Nothing)
| not $ axiIn ^. rready
= ( s
, (Nothing, out)
)
| xfersRem == 0
= ( ReadIdle
, (Nothing, out)
)
| otherwise
= ( ReadDataWait params (xfersRem-1) addr'
, (Just (ReadRequest addr'), out)
)
where
addr' = nextTransferAddress params addr
out = AxiReadOut { _arready = False
, _rvalid = True
, _rid = transId params
, _rdata = dat
, _rlast = xfersRem == 0
, _rresp = AxiOkay
}
-- Catch read responses when not waiting for data
readT _ (axiIn, Just _)
= error "unexpected read response"
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE ApplicativeDo #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE NoImplicitPrelude #-}
module Axi.Write where
import Data.Maybe
import GHC.Generics
import Control.Lens
import Clash.Prelude
import Control.DeepSeq
import Axi.Types
defAxiWriteOut :: KnownNat idWidth => AxiWriteOut idWidth dataWidth
defAxiWriteOut = AxiWriteOut
{ _awready = False
, _wready = False
, _bid = TransId 0
, _bresp = AxiDecodeError
, _bvalid = False
}
data WriteState idWidth dataWidth
= -- | Waiting for @awvalid@
WriteIdle
-- | Waiting for @wvalid@
| WriteDataWait (TransactionParams idWidth) BurstLength (Address dataWidth)
-- | Waiting for confirmation from write target
| WriteConfirmWait (TransactionParams idWidth) BurstLength (Address dataWidth) (Data dataWidth)
data WriteRequest dataWidth
= WriteRequest (Address dataWidth) (Data dataWidth)
deriving (Show, Generic, NFData)
data WriteConfirmation
= WriteConfirmation
deriving (Show, Generic, NFData)
writeT :: forall idWidth dataWidth.
(KnownNat idWidth, KnownNat (8*dataWidth), KnownNat dataWidth)
=> WriteState idWidth dataWidth
-> (AxiWriteIn idWidth dataWidth, Maybe WriteConfirmation)
-> ( WriteState idWidth dataWidth
, (Maybe (WriteRequest dataWidth), AxiWriteOut idWidth dataWidth)
)
-- Waiting for write request
writeT WriteIdle (AxiWriteIn{..}, Nothing)
| _awvalid
= let params = TransParams { burstType = _awburst
, burstSize = _awsize
, transId = _awid
}
in ( WriteDataWait params _awlen _awaddr
, (Nothing, defAxiWriteOut { _awready = True })
)
| otherwise
= ( WriteIdle
, (Nothing, defAxiWriteOut)
)
-- Catch write requests when not idle
writeT _ (axiIn, Nothing)
| axiIn ^. awvalid
= error "uh oh"
-- Waiting for data from master
writeT s@(WriteDataWait params xfersRem addr) (axiIn, Nothing)
| axiIn ^. wvalid
= ( WriteConfirmWait params xfersRem addr (axiIn ^. wdata)
, (Nothing, defAxiWriteOut { _wready = True })
)
| otherwise
= (s, (Nothing, defAxiWriteOut { _wready = True }))
writeT s@(WriteConfirmWait params xfersRem addr dat) (_, confirmation)
= ( nextState
, (Just (WriteRequest addr dat), out)
)
where
nextState
| Nothing <- confirmation
= s
| 0 == xfersRem = WriteIdle
| otherwise = WriteDataWait params (xfersRem-1) addr'
addr' = nextTransferAddress params addr
out = AxiWriteOut { _awready = False
, _wready = isJust confirmation
, _bid = transId params
, _bresp = AxiOkay
, _bvalid = True
}
-- Catch unexpected write confirmations
writeT _ (_, Just _)
= error "unexpected write confirmation"
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment