riscv-bluespec-classic/bs/BusTypes.bs

96 lines
3.4 KiB
Haskell

package BusTypes(
Bus(..),
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
type Token = UInt 5
type Numeric = 5
a :: UInt 5
a = 3