\subsubsection{CommitIfc} {\bf Package} \index{CommitIfc (package)} \begin{verbatim} import CommitIfc :: * ; \end{verbatim} {\bf Description} The \te{CommitIfc} package defines a Commit/Accept protocol and interfaces to implement a combinational connection between two modules without adding an AND gate in the connection. The protocols implemented by FIFO and Get/Put connections add an AND gate between the modules being connected. This combinational loop in the connection of the interfaces can cause complications in FPGA applications and in partitioning for FPGAs. Additionally, some synthesis tools require a connection level without any gates. By using the \te{CommitIfc} protocol the AND gate is moved out of the connection and into the connecting modules. The \te{CommitIfc} package defines two interfaces, \te{SendCommit} and \te{RecvCommit}, which model the opposit ends of a FIFO. The protocol does not apply an execution order between the \te{dataout} and \te{ack} or \te{datain} and \te{accept} methods. That is, one can signal \te{accept} before the data arrives. {\bf Interfaces} The \te{CommitIfc} package defines two interfaces: \te{SendCommit} and \te{RecvCommit}. The \te{SendCommit} interface declares two methods: a value method \te{dataout} and an Action method \te{ack}. No execution order is applied between the \te{dataout} and the \te{ack}; one can signal that the data is accepted before the data rrives. \begin{center} \begin{tabular}{|p{.5in}|p{.5in}|p{4.5 in}|} \hline \multicolumn{3}{|c|}{\te{SendCommit} Interface}\\ \hline Name & Type & Description\\ \hline \hline \te{dataout} &{a\_type}&The data being sent. There is an implicit RDY indicating the data is valid.\\ \hline \te{ack}&Action&Signal that data has been accepted.\\ \hline \end{tabular} \end{center} \begin{verbatim} interface SendCommit#(type a_type); method a_type dataout; (*always_ready*) method Action ack; endinterface \end{verbatim} The \te{RecvCommit} interface declares two methods: an Action method with the data, \te{datain}, and a value method \te{accept}, returning a Bool indicating if the interface can accept data (comparable to a \te{notFull}). \begin{center} \begin{tabular}{|p{.5in}|p{.5in}|p{4.5 in}|} \hline \multicolumn{3}{|c|}{\te{RecvCommit} Interface}\\ \hline Name & Type & Description\\ \hline \hline \te{datain}&Action&Receives, or enqueues, the value \te{din}, of type \te{a\_type}. \\ \hline \te{accept}&Bool& A boolean indicating if the interface can accept data, comparable to a \te{notFull}.\\ \hline \end{tabular} \end{center} \begin{verbatim} interface RecvCommit#(type a_type); (*always_ready*) method Action datain (a_type din); (*always_ready*) method Bool accept ; endinterface \end{verbatim} {\bf Connectble Instances} The \te{CommitIfc} package defines instances of the \te{Connectable} type class for the \te{SendCommit} and \te{RecvCommit} interfaces, defining how the types can be connected. The \te{Connectable} type class defines a \te{mkConnection} module for each set of pairs. \begin{verbatim} instance Connectable#(SendCommit#(a_type), RecvCommit#(a_type)); instance Connectable#(RecvCommit#(a_type), SendCommit#(a_type)); \end{verbatim} \paragraph{FIFOF} The \te{SendCommit} and \te{RecvCommit} interfaces can be connected to \te{FIFOF} interfaces. \begin{verbatim} instance Connectable#(SendCommit#(a_type), FIFOF#(a_type)) provisos (Bits#(a_type, size_a)); instance Connectable#(FIFOF#(a_type), SendCommit#(a_type)) provisos (Bits#(a_type, size_a)); instance Connectable#(RecvCommit#(a_type), FIFOF#(a_type)) provisos (Bits#(a_type, size_a)); instance Connectable#(FIFOF#(a_type), RecvCommit#(a_type)) provisos (Bits#(a_type, size_a)); \end{verbatim} \paragraph{SyncFIFOIfc} The \te{SendCommit} and \te{RecvCommit} interfaces can be connected to \te{SyncFIFOIfc} interfaces. \begin{verbatim} instance Connectable#(SendCommit#(a_type), SyncFIFOIfc#(a_type)) provisos (Bits#(a_type, size_a)); instance Connectable#(SyncFIFOIfc#(a_type), SendCommit#(a_type)) provisos (Bits#(a_type, size_a)); instance Connectable#(RecvCommit#(a_type), SyncFIFOIfc#(a_type)) provisos (Bits#(a_type, size_a)); instance Connectable#(SyncFIFOIfc#(a_type), RecvCommit#(a_type)) provisos (Bits#(a_type, size_a)); \end{verbatim} {\bf Typeclasses} The \te{CommitIfc} package defines typeclasses for converting to these interfaces from other interface types. These must use a module since rules and wires are required. \begin{verbatim} typeclass ToSendCommit#(type a_type , type b_type) dependencies (a_type determines b_type); module mkSendCommit#(a_type x) (SendCommit#(b_type)); endtypeclass \end{verbatim} \begin{verbatim} typeclass ToRecvCommit#(type a_type , type b_type) dependencies (a_type determines b_type); module mkRecvCommit#(a_type x) (RecvCommit#(b_type)); endtypeclass \end{verbatim} {\bf Instances} Instances for the \te{ToSendCommit} and \te{ToRecvCommit} type classes are defined to convert to convert from \te{FIFO}, \te{FIFOF}, \te{SyncFIFOIfc}, \te{Get} and \te{Put} interfaces. \paragraph{FIFO} \begin{verbatim} instance ToSendCommit#(FIFO#(a), a); \end{verbatim} Note: \te{ToRecvCommit\#(FIFO\#(a\_type), a\_type)} is not possible, because it would need to have a \te{notFull} signal. \paragraph{FIFOF} The \te{FIFOF} instances assume that the fifo has proper implicit conditions. \begin{verbatim} instance ToSendCommit#(FIFOF#(a_type), a_type); module mkSendCommit #(FIFOF#(a) f) (SendCommit#(a)); instance ToRecvCommit#(FIFOF#(a_type), a_type) provisos(Bits#(a,sa)); module mkRecvCommit #(FIFOF#(a) f) (RecvCommit#(a)); \end{verbatim} \paragraph{SyncFIFOIfc} The \te{SyncFIFOIfc} instances assume that the fifo has proper implicit conditions. \begin{verbatim} instance ToSendCommit#(SyncFIFOIfc#(a_type), a_type); module mkSendCommit #(SyncFIFOIfc#(a) f) (SendCommit#(a)); instance ToRecvCommit#(SyncFIFOIfc#(a_type), a_type) provisos(Bits#(a,sa)); module mkRecvCommit #(SyncFIFOIfc#(a) f) (RecvCommit#(a)); \end{verbatim} \paragraph{Get and Put} These convert from \te{Get} and \te{Put} interfaces but introduce additional latency: \begin{verbatim} instance ToSendCommit#(Get#(a_type), a_type) provisos ( Bits#(a,sa)); module mkSendCommit #(Get#(a_type) g) (SendCommit#(a_type)); instance ToRecvCommit#(Put#(a_type), a_type) provisos(Bits#(a,sa)); module mkRecvCommit #(Put#(a_type) p) (RecvCommit#(a_type)); \end{verbatim} These add FIFOs, but maintain loopless behavior: \begin{verbatim} instance Connectable#(SendCommit#(a_type), Put#(a_type)) provisos (ToRecvCommit#(Put#(a_type), a_type)); instance Connectable#(Put#(a_type), SendCommit#(a_type)) provisos (ToRecvCommit#(Put#(a_type), a_type)); instance Connectable#(RecvCommit#(a_type), Get#(a_type)) provisos (ToSendCommit#(Get#(a_type), a_type)); instance Connectable#(Get#(a_type), RecvCommit#(a_type)) provisos (ToSendCommit#(Get#(a_type), a_type)); \end{verbatim} {\bf Client/Server Variations} The \te{SendCommit} and \te{RecvCommit} interfaces can be combined into \te{ClientCommit} and \te{ServerCommit} type interfaces, similar to the \te{Client} and \te{Server} interfaces described in Section \ref{lib-clientserver}. A \te{Client} provides two subinterfaces, a \te{Get} and a \te{Put} The \te{ClientCommit} interface combines a \te{SendCommit} request with a \te{RecvCommit} response. \begin{verbatim} interface ClientCommit#(type req, type resp); interface SendCommit#(req) request; interface RecvCommit#(resp) response; endinterface \end{verbatim} The \te{mkClientfromClientCommit} module takes a \te{ClientCommit} interface and provides a \te{Client} interface: \begin{center} \begin{tabular}{|p{1.7 in}|p{4.3 in}|} \hline \te{mkClientFromClientCommit}&Provides a \te{Client} interface from a \te{ClientCommit} interface.\\ \cline{2-2} &\begin{libverbatim} module mkClientFromClientCommit#(ClientCommit#(req, resp) c) (Client#(req,resp)) provisos ( Bits#(resp,_x), Bits#(req,_y)); \end{libverbatim} \\ \hline \end{tabular} \end{center} A \te{Server} interface provides a \te{Put} request with a \te{Get} response. The \te{ServerCommit} interface combines a \te{RecvCommit} request with a \te{SendCommit} response. \begin{verbatim} interface ServerCommit#(type req, type resp); interface RecvCommit#(req) request; interface SendCommit#(resp) response; endinterface \end{verbatim} \te{ClientCommit} and \te{ServerCommit} interfaces are connectable to each other. \begin{verbatim} instance Connectable#(ClientCommit#(req,resp), ServerCommit#(req,resp)); instance Connectable#( ServerCommit#(req,resp), ClientCommit#(req,resp)); \end{verbatim} \te{ClientCommit} and \te{ServerCommit} interfaces are connectable to \te{Clients} and \te{Servers}. \begin{verbatim} instance Connectable #(ClientCommit#(req,resp), Server#(req,resp)) provisos ( Bits#(resp,_x), Bits#(req,_y)); instance Connectable #(Server#(req,resp), ClientCommit#(req,resp)) provisos ( Bits#(resp,_x), Bits#(req,_y)); instance Connectable #(ServerCommit#(req,resp), Client#(req,resp)) provisos ( Bits#(resp,_x), Bits#(req,_y)); instance Connectable #( Client#(req,resp), ServerCommit#(req,resp)) provisos ( Bits#(resp,_x), Bits#(req,_y)); \end{verbatim} The \te{SendCommit} and \te{RecvCommit} can be defined as instances of \te{ToGet} and \te{ToPut}. These functions introduce a combinational loop between the Commit interface methods. \begin{verbatim} instance ToGet#(SendCommit#(a_type, a_type); instance ToPut#(RecvCommit#(a_type, a_type); \end{verbatim}