\subsubsection{CompletionBuffer} \index{CompletionBuffer@\te{CompletionBuffer} (package)} \label{lib-completionbuffer} {\bf Package} \begin{verbatim} import CompletionBuffer :: * ; \end{verbatim} {\bf Description} A \te{CompletionBuffer} is like a FIFO except that the order of the elements in the buffer is independent of the order in which the elements are entered. Each element obtains a token, which reserves a slot in the buffer. Once the element is ready to be entered into the buffer, the token is used to place the element in the correct position. When removing elements from the buffer, the elements are delivered in the order specified by the tokens, not in the order that the elements were written. Completion Buffers are useful when multiple tasks are running, which may complete at different times, in any order. By using a completion buffer, the order in which the elements are placed in the buffer can be controlled, independent of the order in which the data becomes available. {\bf Interface and Methods} \index{CompletionBuffer@\te{CompletionBuffer} (interface)} The CompletionBuffer interface provides three subinterfaces. The \te{reserve} interface, a \te{Get}, allows the caller to reserve a slot in the buffer by returning a token holding the identity of the slot. When data is ready to be placed in the buffer, it is added to the buffer using the \te{complete} interface of type \te{Put}. This interface takes a pair of values as its argument - the token identifying its slot, and the data itself. Finally, using the \te{drain} interface, of type \te{Get}, data may be retrieved from the buffer in the order in which the tokens were originally allocated. Thus the results of quick tasks might have to wait in the buffer while a lengthy task ahead of them completes. The type of the elements to be stored is \te{element\_type}. The type of the required size of the buffer is a numeric type \te{n}, which is also the type argument for the type for the tokens issued, \te{CBToken}. This allows the type-checking phase of the synthesis to ensure that the tokens are the appropriate size for the buffer, and that all the buffer's internal registers are of the correct sizes as well. \begin{center} \begin{tabular}{|p{.6 in}|p{.5in}|p{4.4 in}|} \hline \multicolumn{3}{|c|}{\te{CompletionBuffer} Interface}\\ \hline Name & Type & Description\\ \hline \hline &&\\ \te{reserve}&\te{Get}&Used to reserve a slot in the buffer. Returns a token, \te{CBToken \#(n)}, identifying the slot in the buffer.\\ \hline &&\\ \te{complete}&\te{Put}&Enters the element into the buffer. Takes as arguments the slot in the buffer, \te{CBToken\#(n)}, and the element to be stored in the buffer.\\ \hline &&\\ \te{drain}&\te{Get}&Removes an element from the buffer. The elements are returned in the order the tokens were allocated.\\ \hline \end{tabular} \end{center} \begin{libverbatim} interface CompletionBuffer #(numeric type n, type element_type); interface Get#(CBToken#(n)) reserve; interface Put#(Tuple2 #(CBToken#(n), element_type)) complete; interface Get#(element_type) drain; endinterface: CompletionBuffer \end{libverbatim} {\bf Datatypes} The \te{CBToken} type is abstract to avoid misuse. \begin{libverbatim} typedef union tagged { ... } CBToken #(numeric type n) ...; \end{libverbatim} {\bf Modules} \index{mkCompletionBuffer@\te{mkCompletionBuffer} (module)} The \te{mkCompletionBuffer} module is used to instantiate a completion buffer. It takes no size arguments, as all that information is already contained in the type of the interface it produces. \begin{center} \begin{tabular}{|p{1.25 in}|p{4.4 in}|} \hline &\\ \te{mkCompletionBuffer}& Creates a completion buffer.\\ \cline{2-2} &\begin{libverbatim} module mkCompletionBuffer(CompletionBuffer#(n, element_type)) provisos (Bits#(element_type, sizea)) \end{libverbatim} \\ \hline \end{tabular} \end{center} {\bf Example- Using a Completion Buffer in a server farm of multipliers} A server farm is a set of identical servers, which can each perform the same task, together with a controller. The controller allocates incoming tasks to any server which happens to be available (free), and sends results back to its caller. The time needed to complete each task depends on the value of the multiplier argument; there is therefore no guarantee that results will become available in the order the tasks were started. It is required, however, that the controller return results to its caller in the order the tasks were received. The controller accordingly must instantiate a special mechanism for this purpose. The appropriate mechanism is a Completion Buffer. \begin{verbatim} import List::*; import FIFO::*; import GetPut::*; import CompletionBuffer::*; typedef Bit#(16) Tin; typedef Bit#(32) Tout; // Multiplier interface interface Mult_IFC; method Action start (Tin m1, Tin m2); method ActionValue#(Tout) result(); endinterface typedef Tuple2#(Tin,Tin) Args; typedef 8 BuffSize; typedef CBToken#(BuffSize) Token; // This is a farm of multipliers, mkM. The module // definition for the multipliers mkM is not provided here. // The interface definition, Mult_IFC, is provided. module mkFarm#( module#(Mult_IFC) mkM ) ( Mult_IFC ); // make the buffer twice the size of the farm Integer n = div(valueof(BuffSize),2); // Declare the array of servers and instantiate them: Mult_IFC mults[n]; for (Integer i=0; i