\subsubsection{LBus} \index{LBus@\te{LBus} (package)} {\bf Package} \begin{verbatim} import LBus :: * ; \end{verbatim} {\bf Description} The \te{LBus} package provides facilities for handling control and status registers in a design, and bringing them out to an interface suitable for connection to a processor bus. The \te{LBus} package uses the \te{ModuleCollect} package (section \ref{package-modulecollect}) to allow the local bus connections to be collected together in a way which does not clutter up the main design. The \te{CBus} package (section \ref{lib-cbus}) provides a simplified configuration bus capability while the \te{LBus} package provides a more powerful, full-featured configuration bus capability. {\bf Types and typeclasses} The type \te{LbAddr} is the address used to get and set registers from the local bus. (This type is exported abstractly.) \index{LbAddr@\te{LbAddr} (type)} \begin{libverbatim} typedef union tagged { Bit#(size_address) LbAddr; } LbAddr #(type size_address) deriving (Literal, Eq, Bits); \end{libverbatim} The \te{LBSReg} type is only needed when creating new kinds of local bus registers. The \te{LBSReg} interface is what the local bus uses to access a register. \index{LBSReg@\te{LBSReg} (interface)} \begin{libverbatim} interface LBSReg #(type size_address, type size_data); method LbAddr#(size_address) lbsAddr(); method Action lbsSet( Bit#(size_data) x1); method ActionValue#(Bit#(size_data)) lbsGet(); endinterface: LBSReg \end{libverbatim} Note that the \te{lbsGet} method allows an action to be performed when the local bus reads the value. This allows implementing, e.g., clear-on-read registers. The type \te{LBSItem} defines the type of item to be collected by \te{ModuleCollect}. \begin{libverbatim} typedef union tagged { LBSReg#(size_address, size_data) Rg; IntFlag#(size_data) Flg; } LBSItem #(type size_address, type size_data); \end{libverbatim} The type \te{LbSModule} defines the type of module which is collecting \te{LBSItem}s. An ordinary type, one not collecting anything other than state elements and rules, has the type \te{Module}. This is the default for all modules where a module type is not specified. Since \te{LbSItem}s are being collected, a module type, \te{LbSModule} is defined. When the module type is not \te{Module} the type must be specified in square brackets, immediately after the \te{module} keyword, in the module definition or instantiation. The local bus registers are collected automatically by \te{ModuleCollect}. An \te{LbSModule\#(size\_address,size\_data,i)} corresponds to a \te{Module\#(i)} except that it also keeps a set of registers. The address is $size\_address$ bits wide and data items are $size\_data$ bits wide. \begin{libverbatim} typedef ModuleCollect#(LBSItem#(size_address, size_data), i) LbSModule#(type size_address, type size_data, type i); \end{libverbatim} The \te{LbSModule} is used to collect individual registers. Once the registers have been collected into an \te{ILbLeaf} interface these interfaces can be collected together. \begin{libverbatim} typedef ModuleCollect#(ILbLeaf#(size_address, size_data), i) LbAModule#(type size_address, type size_data, type i); \end{libverbatim} {\bf Interfaces and Methods} The external interface of a local bus is as follows. It is through this interface that register accesses normally happen. \begin{libverbatim} interface ILBus #(type size_address, type size_data); method Action req(Bool valid, LbRWop op, Bit#(size_address) addr, Bit#(size_data) dat); method Bit#(size_data) rdDat(); method Bit#(1) ack(); method Bit#(1) inrpt(); endinterface: ILBus \end{libverbatim} \begin{libverbatim} interface ILbLeaf#(type size_address, type size_data); \end{libverbatim} \begin{libverbatim} interface ILbNode#(type size_address, type size_data); \end{libverbatim} \begin{libverbatim} instance Connectable#(ILbLeaf#(size_address, size_data), ILbNode#(size_address, size_data)); \end{libverbatim} {\bf Modules} \begin{center} \begin{tabular}{|p{1 in}|p{4.65 in}|} \hline &\\ \te{}& \\ \cline{2-2} &\begin{libverbatim} \end{libverbatim} \\ \hline \end{tabular} \end{center} \index{mkLbRegRW@\te{mkLbRegRW} (module)} The \te{mkLbRegRW} module creates a register that looks like a normal register in the module that creates it, but it is also accessible from the local bus at the given address. \begin{center} \begin{tabular}{|p{1 in}|p{4.65 in}|} \hline &\\ \te{mkLbRegRW}&Creates a register accessible from the local bus at the given address.\\ \cline{2-2} &\begin{libverbatim} module [LbSModule#(size_address, size_data)] mkLbRegRW#( LbAddr#(size_address) aw, Integer an, r_type x) ( Reg#(r_type)) provisos (Bits#(r_type, sr), Add#(k, sr, size_data)); \end{libverbatim} \\ \hline \end{tabular} \end{center} \index{mkLbRegRO@\te{mkLbRegRO} (module)} The \te{mkLbRegRO} module creates a register that looks like a normal register in the module that creates it, but it is also accessible from the local bus at the given address. From the local bus the register is read-only; attempts to write it have no effect. The created register has to have a bit width smaller than or equal to the local bus width. If it is smaller it will padded with zeroes on the left. \begin{center} \begin{tabular}{|p{1 in}|p{4.65 in}|} \hline &\\ \te{mkLbRegRO}&Creates a read-only register that is accessible from the local bus. \\ \cline{2-2} &\begin{libverbatim} module [LbSModule#(size_address, size_data)] mkLbRegRO#(LbAddr#(size_address) aw, Integer an, r x) (Reg#(r)) provisos (Bits#(r, sr), Add#(k, sr, size_data)); \end{libverbatim} \\ \hline \end{tabular} \end{center} {\bf Functions} \begin{libverbatim} interface Accum #(type n); method Action add(Bit#(n) x1); method Bit#(n) value(); endinterface: Accum \end{libverbatim} \index{mkLbAccum@\te{mkLbAccum} (function)} \begin{center} \begin{tabular}{|p{1 in}|p{4.65 in}|} \hline &\\ \te{mkLbAccum}& \\ \cline{2-2} &\begin{libverbatim} module [LbSModule#(size_address, size_data)] mkLbAccum#(LbAddr#(size_address) aw, Integer an, Bit#(k) x)(Accum#(k)) provisos (Add#(k, i, size_data)); \end{libverbatim} \\ \hline \end{tabular} \end{center} \index{mkLbOffset@\te{mkLbOffset} (function)} \begin{center} \begin{tabular}{|p{1 in}|p{4.65 in}|} \hline &\\ \te{mkLbOffset}&Used to adda n offset to all local bus register addresses in an \te{LbSModule}. \\ \cline{2-2} &\begin{libverbatim} module [LbSModule#(size_address,size_data)] mkLbOffset#(LbAddr#(size_address) a, LbSModule#(size_address, size_data, i) m)(i); \end{libverbatim} \\ \hline \end{tabular} \end{center} \index{mkLbLeaf@\te{mkLbLeaf} (function)} \begin{center} \begin{tabular}{|p{1 in}|p{4.65 in}|} \hline &\\ \te{mkLbLeaf}&Extracts the local bus interface and the normal interface from a \te{LbSModule} with a set of registers.\\ \cline{2-2} &\begin{libverbatim} module [Module] mkLbLeaf#(LbSModule#(size_address, size_data, i) lm) (IWithLBus#(ILbLeaf#(size_address, size_data), i)); \end{libverbatim} \\ \hline \end{tabular} \end{center} The \te{mkLbBranch} module makes a \te{LbAModule} out of the result from \te{mkLbLeaf}. \index{mkLbBranch@\te{mkLbBranch} (function)} \begin{center} \begin{tabular}{|p{1 in}|p{4.65 in}|} \hline &\\ \te{mkLbBranch}&Makes a \te{LbAModule} out of the results from \te{mkLbLeaf}.\\ \cline{2-2} &\begin{libverbatim} module [LbAModule#(size_address,size_data)] mkLbBranch#(Module#(IWithLBus#( ILbLeaf#(size_address, size_data), i)) m)(i); \end{libverbatim} \\ \hline \end{tabular} \end{center} %\index{lbaCollect@\te{lbaCollect} (function)} \index{mkLbTop@\te{mkLbTop} (module)} \begin{center} \begin{tabular}{|p{1 in}|p{4.65 in}|} \hline &\\ \te{mkLbTop}& The \te{mkLbTop} module combines local bus register clusters. It introduces a one cycle latency on both request and response.\\ \cline{2-2} &\begin{libverbatim} module [Module] mkLbTop#(Module#(Fan#(ILBus#(size_address, size_data), Vector#(n, ILbNode#(size_address, size_data)))) mkFanout, LbAModule#(size_address, size_data, i) lm) (IWithLBus#(ILBus#(size_address, size_data), i)); \end{libverbatim} \\ \hline \end{tabular} \end{center}