diff --git a/bs/Bus.bs b/bs/Bus.bs index 7df4955..73f9e76 100644 --- a/bs/Bus.bs +++ b/bs/Bus.bs @@ -6,60 +6,66 @@ import TagEngine import Vector import Util import Arbiter +import FIFO +import FIFOF +import SpecialFIFOs clientRequest :: Arbiter.ArbiterClient_IFC -> Action clientRequest ifc = ifc.request -busRequestToAddr :: BusRequest -> Addr +busRequestToAddr :: BusRequest -> Maybe Addr busRequestToAddr req = case req of BusReadRequest (ReadRequest addr _) -> addr - WriteReadRequest (WriteRequest addr _) -> addr + BusWriteRequest (WriteRequest addr _) -> addr -mkBus :: (Addr -> Integer) - -> Vector numClients (BusClient inFlightTransactions) - -> Vector numServers (BusServer inFlightTransactions numClients) - -> Module Empty -mkBus addrToServerTranslation clientVec serverVec = do +mkBus :: (Addr -> Maybe Integer) + -> Module (Bus inFlightTransactions numClients numServers) +mkBus addrToServerTranslation = do + -- Tag engines for each client to manage transaction tags tagEngineByClientVec :: Vector numClients (TagEngine inFlightTransactions) tagEngineByClientVec <- replicateM mkTagEngine - arbiterByServerVec :: Vector numServers (Arbiter_IFC numClients) - arbiterByServerVec <- replicateM (mkArbiter False) + -- Arbitration for clients to send requests to servers + clientArbiter :: Arbiter.Arbiter_IFC numClients + clientArbiter <- mkArbiter False - -- statically determinate criteria - let - clientIdx :: Integer = 0 - selectedClient ::(BusClient inFlightTransactions) - selectedClient = (select clientVec clientIdx) - selectedTagEngine = (select tagEngineByClientVec clientIdx) + dummyVar :: Reg(Bool) + dummyVar <- mkReg False - addRules |> - rules - "placeholder rule": when True ==> do - let selectedServerArbiter = (select arbiterByServerVec 0) - mapM_ clientRequest selectedServerArbiter.clients + -- Queues to hold requests from clients to servers + requestQueues :: Vector numServers (FIFOF BusRequest) + requestQueues <- replicateM (mkSizedBypassFIFOF (valueOf inFlightTransactions)) - "connect request client 0": - when True - ==> do - tag <- selectedTagEngine.requestTag + -- Queues to hold responses from servers to clients + responseQueues :: Vector numClients (FIFOF (BusResponse, MkTagType inFlightTransactions)) + responseQueues <- replicateM (mkSizedBypassFIFOF (valueOf inFlightTransactions)) - busRequest :: BusRequest - busRequest <- selectedClient.dequeueRequest tag + -- Client interface vector + let clients :: Vector numClients (BusClient inFlightTransactions) + clients = genWith $ \clientIdx -> + interface BusClient + submitRequest req = do + dummyVar := (not dummyVar) + return 0 - -- let - -- addr = busRequestToAddr busRequest - -- targetServerIdx = addrToServerTranslation addr - -- targetServer = (select serverVec targetServerIdx) - -- targetServerArbiter = (select arbiterByServerVec targetServerIdx) - - -- targetServerArbiter.request + consumeResponse = do + dummyVar := (not dummyVar) + let dummyResponse = BusReadResponse (Left UnMapped) + return (dummyResponse, 0) - -- if targetServerArbiter.grant - -- then targetServer.enqueueRequest (tag, busRequest) - -- else action {} - - -- targetServer - action {} + -- Server interface vector + let servers :: Vector numServers (BusServer inFlightTransactions numClients) + servers = genWith $ \serverIdx -> + interface BusServer + consumeRequest = do + dummyVar := (not dummyVar) + let dummyBusRequest = BusReadRequest (ReadRequest 0 SizeByte) + return (0, dummyBusRequest) - return $ interface Empty { } + submitResponse (clientTag, busResponse, transactionTag) = do + dummyVar := (not dummyVar) + + return $ + interface Bus + clients = clients + servers = servers diff --git a/bs/BusTypes.bs b/bs/BusTypes.bs index 818fd3d..f0ae7fa 100644 --- a/bs/BusTypes.bs +++ b/bs/BusTypes.bs @@ -1,4 +1,5 @@ package BusTypes( + Bus(..), MkClientTagType, BusClient(..), BusServer(..), BusRequest(..), BusResponse(..), @@ -44,7 +45,7 @@ type WriteResponse = Either BusError () data BusRequest = BusReadRequest ReadRequest - | WriteReadRequest WriteRequest + | BusWriteRequest WriteRequest deriving (Bits, Eq, FShow) data BusResponse @@ -52,47 +53,44 @@ data BusResponse | 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. +-- # BusClient.submitRequest +-- * The bus client calls the `submitRequest` method of the `BusClient` interface +-- with the `BusRequest` it wishes to submit and immediately recieves back +-- a transaction-duration-unqiue tag that it can later correlate with the +-- returned response should responses arrive out of order(OOO). OOO can +-- happen if a bus server is is able to process bus requests faster than +-- other bus servers for example. +-- # BusClient.consumeResponse +-- * The bus client is able to consume a response when a response is available. +-- Responses are tagged with the tag given to bus client when it called +-- `submitRequest` interface (BusClient :: # -> *) inFlightTransactions = - dequeueRequest :: MkTagType inFlightTransactions - -> ActionValue BusRequest - enqueueResponse :: (BusResponse, MkTagType inFlightTransactions) + submitRequest :: BusRequest + -> ActionValue (MkTagType inFlightTransactions) + consumeResponse :: ActionValue (BusResponse, MkTagType inFlightTransactions) + +-- # BusServer.consumeRequest +-- * The bus server calls the `consumeRequest` method of the `BusServer` interface +-- to retrieve a pending bus request initiated by a client. It immediately +-- receives a tuple containing a transaction-duration-unique tag +-- (associated with the original request) and the `BusRequest` itself. This +-- tag is used to track the transaction and correlate it with the eventual +-- response. +-- # BusServer.submitResponse +-- * The bus server calls the `submitResponse` method to send a `BusResponse` +-- back to the originating client. The method takes a tuple containing: +-- - A client tag (of type `MkClientTagType numClients`) identifying the +-- client that submitted the request. +-- - The `BusResponse` containing the result of the request (either a read +-- or write response). +-- - The transaction tag (of type `transactionTagType`) that matches the tag +-- received from `consumeRequest`, ensuring the response is correctly +-- associated with the original request. +interface (BusServer :: # -> # -> *) inFlightTransactions numClients = + consumeRequest :: ActionValue (MkTagType inFlightTransactions, BusRequest) + submitResponse :: (MkClientTagType numClients, BusResponse, transactionTagType) -> Action --- # BusServer.dequeueResponse --- * If the arbiter is able to successfully call `dequeueResponse`, then --- the BusServer's internal logic must update such that it understands --- the response has been handed off. --- # BusServer.peekClientTagDestination --- * The arbiter looks at (peekClientTagDestination :: MkClientTagType) 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 :: (MkTagType inFlightTransactions, BusRequest) - -> Action - dequeueResponse :: ActionValue ( - MkClientTagType numClients, - BusResponse, transactionTagType - ) - peekClientTagDestination :: MkClientTagType numClients +interface (Bus :: # -> # -> # -> *) inFlightTransactions numClients numServers = + clients :: Vector numClients (BusClient inFlightTransactions) + servers :: Vector numServers (BusServer inFlightTransactions numClients)