99 lines
3.6 KiB
Haskell
99 lines
3.6 KiB
Haskell
package BusTypes(
|
|
BusClient(..), BusServer(..),
|
|
BusRequest(..), BusResponse(..),
|
|
ReadRequest(..), ReadResponse(..), WriteRequest(..), WriteResponse(..),
|
|
BusVal(..), BusError(..), TransactionSize(..)
|
|
) where
|
|
|
|
import Types
|
|
import Vector
|
|
|
|
data BusError
|
|
= UnMapped
|
|
| UnAligned
|
|
deriving (Bits, Eq, FShow)
|
|
|
|
data TransactionSize
|
|
= SizeByte
|
|
| SizeHalfWord
|
|
| SizeFullWord
|
|
| SizeDoubleWord
|
|
| SizeQuadWord
|
|
deriving (Bits, Eq, FShow)
|
|
|
|
data BusVal
|
|
= BusByte Byte
|
|
| BusHalfWord HalfWord
|
|
| BusFullWord FullWord
|
|
| BusDoubleWord DoubleWord
|
|
| BusQuadWord QuadWord
|
|
deriving (Bits, Eq, FShow)
|
|
|
|
data ReadRequest = ReadRequest Addr TransactionSize
|
|
deriving (Bits, Eq, FShow)
|
|
|
|
data WriteRequest = WriteRequest Addr BusVal
|
|
deriving (Bits, Eq, FShow)
|
|
|
|
type ReadResponse = Either BusError BusVal
|
|
type WriteResponse = Either BusError ()
|
|
|
|
data BusRequest
|
|
= BusReadRequest ReadRequest
|
|
| WriteReadRequest WriteRequest
|
|
deriving (Bits, Eq, FShow)
|
|
|
|
data BusResponse
|
|
= BusReadResponse ReadResponse
|
|
| BusWriteResponse WriteResponse
|
|
deriving (Bits, Eq, FShow)
|
|
|
|
-- # BusClient.dequeueRequest
|
|
-- * The Bus arbiter will call the Bus Client's request method if it is
|
|
-- the Bus Client's turn to make a request, or if another client forfits
|
|
-- its turn.
|
|
-- * The BusClient must guard its request method such that calling its
|
|
-- request method is only valid when the BusClient has a request to make.
|
|
-- * This has implications about for the implementor of BusClient,
|
|
-- namely, that it should hold its request until it's request method
|
|
-- gets called. The arbiter tags the request so that the client can
|
|
-- later correctly correlate the response.
|
|
-- * Although the tag is technically passed in as an argument from the
|
|
-- arbiter to the client's request method, given that methods are
|
|
-- atomic in Bluespec, this is effectively equivalent to tagging the
|
|
-- transaction from the client's perspective. Thus, the client must
|
|
-- take care to appropiately store the tag.
|
|
-- # BusClient.enqueueResponse
|
|
-- * From the client's perspective, the response should not be called
|
|
-- by the arbiter until the client is ready to accept the response.
|
|
-- In other words, the response method should be guarded by the client.
|
|
interface (BusClient :: * -> *) transactionTagType =
|
|
dequeueRequest :: transactionTagType -> ActionValue BusRequest
|
|
enqueueResponse :: (BusResponse, transactionTagType) -> Action
|
|
|
|
-- # BusServer.dequeueResponse
|
|
-- * If the arbiter is able to successfully call `dequeueResponse`, then
|
|
-- the BusServer's internal logici must update such that it understand
|
|
-- the response has been handed off.
|
|
-- # BusServer.peekClientTagDestination
|
|
-- * The arbiter looks at (peekClientTagDestination :: clientTagTye) to
|
|
-- determine whether or not it is currently safe whether to dequeue the
|
|
-- response as well as where to route the response should it dequeue the
|
|
-- response.
|
|
-- * `peekClientTagDestination` should be guarded on whether or not there is
|
|
-- a valid response available.
|
|
interface (BusServer :: * -> * -> *) transactionTagType clientTagType =
|
|
enqueueRequest :: (transactionTagType, BusRequest) -> Action
|
|
dequeueResponse :: ActionValue (clientTagType, BusResponse, transactionTagType)
|
|
peekClientTagDestination :: clientTagTye
|
|
|
|
interface (Bus :: # -> # -> * -> * -> *) numClients numServers transactionTagType clientTagType =
|
|
clients :: Vector numClients (BusClient transactionTagType)
|
|
servers :: Vector numServers (BusServer transactionTagType clientTagType)
|
|
|
|
type Token = UInt 5
|
|
type Numeric = 5
|
|
|
|
a :: UInt 5
|
|
a = 3
|