package BusTypes( ClientTagType, BusClient(..), BusServer(..), BusRequest(..), BusResponse(..), ReadRequest(..), ReadResponse(..), WriteRequest(..), WriteResponse(..), BusVal(..), BusError(..), TransactionSize(..) ) where import Types import Vector import TagEngine type ClientTagType a = (UInt (TLog a)) 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 :: # -> *) inFlightTransactions = dequeueRequest :: TagType inFlightTransactions -> ActionValue BusRequest enqueueResponse :: (BusResponse, TagType inFlightTransactions) -> 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 :: clientTagType) 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 :: # -> # -> *) inFlightTransactions numClients = enqueueRequest :: (TagType inFlightTransactions, BusRequest) -> Action dequeueResponse :: ActionValue ( ClientTagType numClients, BusResponse, transactionTagType ) peekClientTagDestination :: clientTagType type Token = UInt 5 type Numeric = 5 a :: UInt 5 a = 3