The packages in this section provide useful components, primarily interfaces, to connect hardware elements in a design. The basic interfaces, \te{Get} and \te{Put} are defined in the package \te{GetPut}. The typeclass \te{Connectable} indicates that two related types can be connected together. The package \te{ClientServer} provides interfaces using \te{Get} and \te{Put} for modules that have a request-response type of interface. The package \te{CGetPut} defines a type of the \te{Get} and \te{Put} interfaces that is implemented with a credit based FIFO. \subsubsection{GetPut} \index{GetPut@\te{GetPut} (package)} \index{Get@\te{Get} (interface)} \index{Put@\te{Put} (interface)} \label{sec-GetPut} {\bf Package} \begin{verbatim} import GetPut :: *; \end{verbatim} {\bf Description} A common paradigm between two blocks is the get/put mechanism: one side {\em gets} or retrieves an item from an interface and the other side {\em puts} or gives an item to an interface. These types of interfaces are used in {\em Transaction Level Modeling} or TLM for short. This pattern is so common in system design that BSV provides the \te{GetPut} library package for this purpose. The \te{GetPut} package provides basic interfaces to implement the TLM paradigm, along with interface transformer functions and modules to transform to/from FIFO implementations. The \te{ClientServer} package in Section \ref{lib-clientserver} defines more complex interfaces based on the \te{Get} and \te{Put} interfaces to support request-response interfaces. The \te{GetPut} package must be imported when using the \te{ClientServer} package. % \te{Get} and \te{Put} are simple interfaces, consisting of one % method each, \te{get} and \te{put}, respectively. This package % provides the interfaces \te{Get}, \te{Put}, and \te{GetPut}. This % package also provides modules which provide the \te{GetPut} % interface as a \te{FIFO} implementation, but these interfaces can be used % in many additional hardware implementations. {\bf Typeclasses} The \te{GetPut} package defines two typeclasses: \te{ToGet} and \te{ToPut}. \label{toget} The types with instances defined in these typeclasses provide the functions \te{toGet} and \te{toPut}, used to create associated \te{Get} and \te{Put} interfaces from these other types. \te{ToGet} defines the class to which the function \te{toGet} can be applied to create an associated \te{Get} interface. \index{toGet@\te{toGet} (function)} \index[function]{GetPut!toGet} \index[typeclass]{ToGet} \index[typeclass]{ToPut} \begin{verbatim} typeclass ToGet#(a, b); function Get#(b) toGet(a ax); endtypeclass \end{verbatim} \te{ToPut} defines the class to which the function \te{toPut} can be applied to create an associated \te{Put} interface. \index{toPut@\te{toPut} (function)} \index[function]{GetPut!toPut} \begin{verbatim} typeclass ToPut#(a, b); function Put#(b) toPut(a ax); endtypeclass \end{verbatim} Instances of \te{ToGet} and \te{ToPut} are defined for the following interfaces: %\begin{tabular}{|p{1.8 in}|p{.3 in}|p{.3in}|p{3in}|} \begin{tabular}{|p{1.8 in}|c|c|p{3in}|} \hline \multicolumn{4}{|c|}{Defined Instances for \te{ToGet} and \te{ToPut}}\\ \hline Type (Interface)&toGet&toPut&Comments\\ \hline \hline \te{a}&\checkmark&&\te{toGet} returns value \te{a}\\ \te{ActionValue\#(a)}&\checkmark&&\te{toGet} performs the Action and returns the value\\ \te{function Action fn(a)}&&\checkmark& \te{toPut} calls \te{Action} function \te{fn} with argument \te{a}\\ \hline \te{Get\#(a)}&\checkmark&&identity function: returns \te{Get\#(a)}\\ \te{Put\#(a)}&&\checkmark&identity function: returns \te{Put\#(a)}\\ \hline \te{Reg\#(a)}&\checkmark&\checkmark&\te{toGet} returns \te{\_read}, \te{toPut} calls \te{\_write}\\ \te{RWire\#(a)}&\checkmark&\checkmark&\te{toGet} returns \te{wget}, \te{toPut} calls \te{wset}\\ \te{ReadOnly\#(a)}&\checkmark&&\te{toGet} returns \te{\_read}\\ \hline %\end{tabular} % The FIFO instances of \te{ToGet} call \te{deq} and % return \te{first}. The FIFO instances of \te{ToPut} call \te{enq}. %\begin{tabular}{|p{1.8 in}|p{.3 in}|p{.3in}|p{3in}|} %\hline % \multicolumn{4}{|c|}{Defined FIFO Instances for \te{ToGet} and \te{ToPut}}\\ % \hline % FIFO Interface&toGet&toPut&Comments\\ % \hline % \hline \te{FIFO\#(a)}&\checkmark&\checkmark&\te{toGet} calls \te{deq} returns \te{first}, \te{toPut} calls \te{enq}\\ \te{FIFOF\#(a)}&\checkmark&\checkmark&\te{toGet} calls \te{deq} returns \te{first}, \te{toPut} calls \te{enq}\\ \te{SyncFIFOIfc\#(a)}&\checkmark&\checkmark&\te{toGet} calls \te{deq} returns \te{first}, \te{toPut} calls \te{enq}\\ \te{FIFOLevelIfc\#(a)}&\checkmark&\checkmark&\te{toGet} calls \te{deq} returns \te{first}, \te{toPut} calls \te{enq}\\ \te{SyncFIFOLevelIfc\#(a)}&\checkmark&\checkmark&\te{toGet} calls \te{deq} returns \te{first}, \te{toPut} calls \te{enq} \\ \te{FIFOCountIfc\#(a)}&\checkmark&\checkmark&\te{toGet} calls \te{deq} returns \te{first}, \te{toPut} calls \te{enq}\\ \te{SyncFIFOCountIfc\#(a)}&\checkmark&\checkmark&\te{toGet} calls \te{deq} returns \te{first}, \te{toPut} calls \te{enq}\\ \hline \end{tabular} % \begin{verbatim} % Reg % RWire % FIFO % FIFOF % SyncFIFOIfc % FIFOLevelIfc % SyncFIFOLevelIfc % FIFOCountIfc % SyncFIFOCountIfc % ReadOnly % \end{verbatim} % An instance of \te{ToGet} is defined for the \te{ReadOnly} interface. Example - Using \te{toPut} \begin{libverbatim} module mkTop (Put#(UInt#(64))); Reg#(UInt#(64)) inValue <- mkReg(0); Reg#(Bool) startit <- mkReg(True); ... StimIfc stim_gen <- mkStimulusGen; rule startTb (startit && inValue!=0); // Get the value let val = inValue; stim_gen.start(val); startit <= False; endrule ... return (toPut(asReg(inValue))); endmodule: mkTop \end{libverbatim} {\bf Interfaces and methods} The \te{Get} interface defines the \te{get} method, similar to a \te{dequeue}, which retrieves an item from an interface and removes it at the same time. The \te{Put} interface defines the \te{put} method, similar to an \te{enqueue}, which gives an item to an interface. Also provided is the \te{GetS} interface, which defines separate methods for the dequeue (\te{deq}) and retreiving the item (\te{first}) from the interface. You can design your own \te{Get} and \te{Put} interfaces with implicit conditions on the \te{get}/\te{put} to ensure that the \te{get}/\te{put} is not performed when the module is not ready. This would ensure that a rule containing \te{get} method would not fire if the element associated with it is empty and that a rule containing \te{put} method would not fire if the element is full. % \begin{tabular}{|p{1.2in}|p{.8in}|p{2in}|p{1.3in}|} % \hline % \multicolumn{4}{|c|}{Interfaces}\\ % \hline % Interface Name & Parameter name & Parameter Description & Restrictions \\ % \hline % \hline % \te{Get} & \it{element\_type} & type of the element & must be in % \te{Bits} class\\ % & &being retrieved by the \te{Get} &\\ % \hline % \te{Put} & \it{element\_type} & type of the element & must be in % \te{Bits} class\\ % & &being added by the \te{Put} &\\ % \hline % \te{GetS} & \it{element\_type} & type of the element & must be in % \te{Bits} class\\ % & &being retrieved by the \te{Get} &\\ % \hline % \te{PutS} & \it{element\_type} & type of the element & must be in % \te{Bits} class\\ % & &being added by the \te{Put} &\\ % \hline % \te{GetPut}&\it{element\_type}& type of the element & must be in % \te{Bits} class\\ % & & being retrieved and added & \\ % \hline % \end{tabular} The following interfaces are defined in the \te{GetPut} package. They each take a single parameter, \te{element\_type} which must be in the \te{Bits} typeclass. \begin{center} \begin{tabular}{|p{.5 in}|p{3.2 in}|p{.75in}|p{1in}|} \hline \multicolumn{4}{|c|}{Interfaces defined in GetPut}\\ \hline Interface Name & Description&Methods&Type\\ \hline \hline \te{Get} & Retrieves item from an interface&\te{get}&\te{ActionValue}\\ \hline \te{Put} & Adds an item to an interface&\te{put}&\te{Action}\\ \hline \te{GetS} &Retrieves an item from an interface with 2 methods, & \te{first}& \te{Value}\\ &separating the return of the value from the dequeue&\te{deq}&\te{Action}\\ \hline \te{GetPut}&Combination of a \te{Get} and a \te{Put} in a \te{Tuple2} &\te{get}&\te{ActionValue}\\ & &\te{put}&\te{Action}\\ \hline \end{tabular} \end{center} {\bf Get} The \te{Get} interface is where you retrieve (get) data from an object. The \te{Get} interface is provides a single ActionValue method, \te{get}, which retrieves an item of data from an interface and removes it from the object. A \te{get} is similar to a \te{dequeue}, but it can be associated with any interface. A \te{Get} interface is more abstract than a \te{FIFO} interface; it does not describe the underlying hardware. \begin{center} \begin{tabular}{|p{.5in}|p{.7 in}|p{1.5 in}|p{.4in}|p{1.4 in}|} \hline \multicolumn{5}{|c|}{Get}\\ \hline \multicolumn{3}{|c|}{Method}&\multicolumn{2}{|c|}{Argument}\\ \hline Name & Type & Description& Name &\multicolumn{1}{|c|}{Description} \\ \hline \hline \te{get} & ActionValue & returns an item from an interface and removes it from the object & & \\ \hline \end{tabular} \end{center} \begin{libverbatim} interface Get#(type element_type); method ActionValue#(element_type) get(); endinterface: Get \end{libverbatim} Example - adding your own \te{Get} interface: \begin{libverbatim} module mkMyFifoUpstream (Get#(int)); ... method ActionValue#(int) get(); f.deq; return f.first; endmethod \end{libverbatim} {\bf Put} The \te{Put} interface is where you can give (put) data to an object. The \te{Put} interface provides a single Action method, \te{put}, which gives an item to an interface. A \te{put} is similar to an \te{enqueue}, but it can be associated with any interface. A \te{Put} interface is more abstract than a \te{FIFO} interface; it does not describe the underlying hardware. \begin{center} \begin{tabular}{|p{.4 in}|p{.4 in}|p{1.7 in}|p{.4in}|p{2 in}|} \hline \multicolumn{5}{|c|}{Put}\\ \hline \multicolumn{3}{|c|}{Method}&\multicolumn{2}{|c|}{Argument}\\ \hline Name & Type & Description& Name &\multicolumn{1}{|c|}{Description} \\ \hline \hline \te{put} & Action & gives an item to an interface &x1 &data to be added to the object must be of type \te{element\_type}\\ \hline \end{tabular} \end{center} \begin{libverbatim} interface Put#(type element_type); method Action put(element_type x1); endinterface: Put \end{libverbatim} Example - adding your own \te{Put} interface: \begin{libverbatim} module mkMyFifoDownstream (Put#(int)); ... method Action put(int x); F.enq(x); endmethod \end{libverbatim} {\bf GetS} The \te{GetS} interface is like a \te{Get} interface, but separates the \te{get} method into two methods: a \te{first} and a \te{deq}. \begin{center} \begin{tabular}{|p{.5in}|p{.7 in}|p{1.5 in}|p{.4in}|p{1.4 in}|} \hline \multicolumn{5}{|c|}{GetS}\\ \hline \multicolumn{3}{|c|}{Method}&\multicolumn{2}{|c|}{Argument}\\ \hline Name & Type & Description& Name &\multicolumn{1}{|c|}{Description} \\ \hline \hline \te{first} & Value & returns an item from the interface & & \\ \hline \te{deq}&Action& Removes the item from the interface && \\ \hline \end{tabular} \end{center} \begin{libverbatim} interface GetS#(type element_type); method element_type first(); method Action deq(); endinterface: GetS \end{libverbatim} % {\bf PutS} % The \te{PutS} interface is like the \te{Put} interface, but has two % methods: an Action putting the value and a Boolean indicating the value % was accepted. {\bf GetPut} The library also defines an interface \te{GetPut} which associates \te{Get} and \te{Put} interfaces into a \te{Tuple2}. \begin{libverbatim} typedef Tuple2#(Get#(element_type), Put#(element_type)) GetPut#(type element_type); \end{libverbatim} {\bf Type classes} The class \te{Connectable} (Section \ref{lib-connectable}) is meant to indicate that two related types can be connected in some way. It does not specify the nature of the connection. A \te{Get} and \te{Put} is an example of connectable items. One object will \te{put} an element into the interface and the other object will \te{get} the element from the interface. \begin{libverbatim} instance Connectable#(Get#(element_type), Put#(element_type)); \end{libverbatim} {\bf Modules} There are three modules provided by the \te{GetPut} package which provide the \te{GetPut} interface with a type of \te{FIFO}. These FIFOs use \te{Get} and \te{Put} interfaces instead of the usual \te{enq} interfaces. To use any of these modules the \te{FIFO} package must be imported. You can also write your own modules providing a \te{GetPut} interface for other hardware structures. \index{mkGPFIFO@\te{mkGPFIFO} (\te{GetPut} module)} \index[function]{GetPut!mkGPFIFO} \begin{center} \begin{tabular}{|p{1 in}|p{4.5 in}|} \hline &\\ \te{mkGPFIFO} & Creates a FIFO of depth 2 with a \te{GetPut} interface.\\ \cline{2-2} &\begin{libverbatim} module mkGPFIFO (GetPut#(element_type)) provisos (Bits#(element_type, width_elem)); \end{libverbatim} \\ \hline \end{tabular} \end{center} \index{mkGPFIFO1@\te{mkGPFIFO1} (\te{GetPut} module)} \index[function]{GetPut!mkGPFIFO1} \begin{center} \begin{tabular}{|p{1 in}|p{4.5 in}|} \hline &\\ \te{mkGPFIFO1} & Creates a FIFO of depth 1 with a \te{GetPut} interface.\\ \cline{2-2} &\begin{libverbatim} module mkGPFIFO1 (GetPut#(element_type)) provisos (Bits#(element_type, width_elem)); \end{libverbatim} \\ \hline \end{tabular} \end{center} \index{mkGPSizedFIFO@\te{mkGPSizedFIFO} (\te{GetPut} module)} \index[function]{GetPut!mkGPSizedFIFO} \begin{center} \begin{tabular}{|p{1 in}|p{4.5 in}|} \hline &\\ \te{mkGPSizedFIFO} &Creates a FIFO of depth n with a \te{GetPut} interface.\\ \cline{2-2} &\begin{libverbatim} module mkGPSizedFIFO# (Integer n) (GetPut#(element_type)) provisos (Bits#(element_type, width_elem)); \end{libverbatim} \\ \hline \end{tabular} \end{center} {\bf Functions} There are three functions defined in the \te{GetPut} package that change a \te{FIFO} interface to a \te{Get}, \te{GetS} or \te{Put} interface. Given a FIFO we can use the function \te{fifoToGet} to obtain a \te{Get} interface, which is a combination of \te{deq} and \te{first}. Given a FIFO we can use the function \te{fifoToPut} to obtain a \te{Put} interface using \te{enq}. The functions \te{toGet} and \te{toPut} (\ref{toget}) are recommended instead of the \te{fifoToGet} and \te{fifoToPut} functions. The function \te{fifoToGetS} returns the \te{GetS} methods as fifo methods. % The package defines an additional function, \te{peekGet}, which returns the first item without removing it % from the object. There are scheduling concerns when using % \te{peekGet}; because of the implicit condition, it will only fire if there is data available. \index{fifoToGet@\te{fifoToGet} (GetPut function)} \index[function]{GetPut!fifoToGet} \begin{center} \begin{tabular}{|p{1 in}|p{4.5 in}|} \hline &\\ \te{fifoToGet}& Returns a \te{Get} interface. It is recommended that you use the function \te{toGet} (\ref{toget}) instead of this function.\\ \cline{2-2} &\begin{libverbatim} function Get#(element_type) fifoToGet(FIFO#(element_type) f);\end{libverbatim} \\ \hline \end{tabular} \end{center} \index{fifoToGet@\te{fifoToGet} (GetPut function)} \index[function]{GetPut!fifoToGet} \begin{center} \begin{tabular}{|p{1 in}|p{4.5 in}|} \hline &\\ \te{fifoToGetS}& Returns a \te{GetS} interface. \\ \cline{2-2} &\begin{libverbatim} function GetS#(element_type) fifoToGet(FIFO#(element_type) f);\end{libverbatim} \\ \hline \end{tabular} \end{center} \index{fifoToPut@\te{fifoToPut} (GetPut function)} \index[function]{GetPut!fifoToPut} \begin{center} \begin{tabular}{|p{1 in}|p{4.5 in}|} \hline &\\ \te{fifoToPut} & Returns a \te{Put} interface. It is recommended that you use the function \te{toPut} (\ref{toget}) instead of this function.\\ \cline{2-2} &\begin{libverbatim} function Put#(element_type) fifoToPut(FIFO#(element_type) f);\end{libverbatim} \\ \hline \end{tabular} \end{center} % \index{peekGet@\te{peekGet} (GetPut function)} % \index[function]{GetPut!peekGet} % \begin{center} % \begin{tabular}{|p{1 in}|p{4.5 in}|} % \hline % &\\ % \te{peekGet} &Returns first item without removing it from the object. Will not fire if data is not available.\\ % \cline{2-2} % &\begin{libverbatim} % function element_type peekGet(Get#(element_type) g;) \end{libverbatim} % \\ % \hline % \end{tabular} % \end{center} {\bf Example of creating a FIFO with a \te{GetPut} interface} \begin{libverbatim} import GetPut::*; import FIFO::*; ... module mkMyModule (MyInterface); GetPut#(StatusInfo) aFifoOfStatusInfoStructures <- mkGPFIFO; ... endmodule: mkMyModule \end{libverbatim} {\bf Example of a protocol monitor} This is an example of how you might write a protocol monitor that watches bus traffic between a bus and a bus target device \begin{libverbatim} import GetPut::*; import FIFO::*; // Watch bus traffic beteween a bus and a bus target interface ProtocolMonitorIfc; // These subinterfaces are defined inside the module interface Put#(Bus_to_Target_Request) bus_to_targ_req_ifc; interface Put#(Target_to_Bus_Response) targ_to_bus_resp_ifc; endinterface ... module mkProtocolMonitor (ProtocolMonitorIfc); // Input FIFOs that have Put interfaces added a few lines down FIFO#(Bus_to_Target_Request) bus_to_targ_reqs <- mkFIFO; FIFO#(Target_To_Bus_Response) targ_to_bus_resps <- mkFIFO; ... // Define the subinterfaces: attach Put interfaces to the FIFOs, and // then make those the module interfaces interface bus_to_targ_req_ifc = fifoToPut (bus_to_targ_reqs); interface targ_to_bus_resp_ifc = fifoToPut (targ_to_bus_resps); end module: mkProtocolMonitor // Top-level module: connect mkProtocolMonitor to the system: module mkSys (Empty); ProtocolMonitorIfc pmon <- mkProtocolInterface; ... rule pass_bus_req_to_interface; let x <- bus.bus_ifc.get; // definition not shown pmon.but_to_targ_ifc.put (x); endrule ... endmodule: mkSys \end{libverbatim}