Bluepsec Examples
Server Farm
Introduction
This is generic package replicates any Server as many times as you like. For example, we could take the FibServer example (or a DividerServer, left as an exercise to the reader) and replicate it twice as illustrated below. This will route the requests to in an alternating (round-robin) manner the two internal FibServer. If the FibServer is iterative, it will take several cycles, so the ServerFarm version with two FibServers will have twice the bandwidth.
![ServerFarm Illustration](FibFarm.png)
Example of ServerFarm instantiating two FibServers
So if the original FibServer was instantiated vis:
FibServerT#(`width) divServ <- mkFibServer;
then the new version with two FibServers is simply:
FibServerT#(`width) fasterDivServ <- mkServerFarm(2,mkFibServer);
This, for me, is an excellent example of how Bluespec allows you to do rapid design exploration.
Notes
- The Server to be replicated is passed in as a higher-order type called mkServer. A vector of mkServers is created using replicateM (monadic replicate).
- The incoming request is enqueued into a BypassFIFO. Exactly one of put_requests rules (generated using a for-loop) will be enabled and can forward the request to corresponding server.
The code
/***************************************************************************** ServerFarm ========== Simon Moore, Oct 2009 Substantial improvements by Matthew Naylor in 2013 Generic module which multiplexes N servers to one server interface. Useful if the base server is quite slow and you want several copies of it. *****************************************************************************/ package ServerFarm; import FIFO::*; import FIFOF::*; import SpecialFIFOs::*; import GetPut::*; import ClientServer::*; import Connectable::*; import List::*; import Assert::*; module mkServerFarm#(Integer numServers, module#(Server#(requestT,responseT)) mkServer) (Server#(requestT,responseT)) provisos(Bits#(requestT,requestTwidth), Bits#(responseT,responseTwidth)); staticAssert(numServers > 1, "ServerFarm: number of servers must be > 1."); staticAssert(numServers < 65, "ServerFarm: number of servers must be < 65."); List#(Server#(requestT,responseT)) servers <- replicateM(numServers, mkServer); Reg#(UInt#(6)) write_server <- mkReg(0); Reg#(UInt#(6)) read_server <- mkReg(0); FIFOF#(requestT) request_fifo <- mkBypassFIFOF; FIFOF#(responseT) response_fifo <- mkBypassFIFOF; function Integer nextServer(Integer n); let next = n+1; return (next>=numServers) ? 0 : next; endfunction for(Integer j=0; j<numServers; j=j+1) begin rule put_requests (write_server == fromInteger(j)); let r = request_fifo.first; request_fifo.deq; servers[j].request.put(r); write_server <= fromInteger(nextServer(j)); endrule rule gather_results (read_server == fromInteger(j)); let result <- servers[j].response.get; response_fifo.enq(result); read_server <= fromInteger(nextServer(j)); endrule end interface Put request = toPut(request_fifo); interface Get response = toGet(response_fifo); endmodule endpackage
Link to the ServerFarm.bsv source