\subsubsection{ModuleCollect}

{\bf Package}
\index{ModuleCollect@\te{ModuleCollect} (package)}
\label{package-modulecollect}

\begin{verbatim}
import ModuleCollect :: * ;
\end{verbatim}


{\bf Description}

The \te{ModuleCollect} package provides the capability of adding
additional items, such as configuration bus connections, 
to a design in such a way that it does not change the 
structure of the design.  This section provides a brief overview of
the package.  
For a more detailed description of its usage, see the \te{CBus}
package (\ref{lib-cbus}), which utilizes  \te{ModuleCollect}.
There is also  a detailed  example and  more complete discussion of the \te{CBus}
package in the configbus tutorial in the BSV/tutorials directory.


An ordinary {\BS} module, when instantiated, adds its own state
elements and rules to
the growing accumulation of state elements and rules defined in the
design.  In some designs, for example a configuration bus, additional
items, such as the logic for the
 bus address decoding  must be accumulated as well. While there is a
need to add these items, it is also desirable to keep these
additional design details separate from the main design, keeping the
natural structure of the design intact.  

The \te{ModuleCollect} mechanism allows the designer to \emph{hide} the details of the
additional interfaces.    A module which is going to be synthesized must contain
only rules and state elements, as the compiler does not know how to
handle the additional items.  Therefore, the collection must be
brought into the open, or exposed, before the module can be
synthesized.  The \te{ModuleCollect} package 
provides the mechanisms to allow these additional
items to be collected, processed and exposed.

% An ordinary module, when
% instantiated, adds its own items to the growing accumation of 
% state  elements, and rules, which are processed by later stages of
% the compiler.  The
% \te{ModuleCollect} package allows other items to be accumulated too.  But
% this extra \emph{collection} must be exposed and processed at a higher
% level: in particular, any module which is to be synthesized must not
% be collecting any extra stuff, as the compiler would not know how to
% handle it.  The \te{ModuleCollect} package provides functions to
% create, process and expose collections.

{\bf Types and Type Classes}

The \te{ModuleCollect} type is a variation  on the \te{Module} type
that allows additional items, other than states and rules,  to be collected
while  elaborating the module structure.    A module defining the
accumulation of a special collection will have the type of
\te{ModuleCollect}  which is defined as a type of \te{ModuleContext}
(Section \ref{sec-ModuleContext}):  
\index{ModuleCollect@\te{ModuleCollect} (type)}

\begin{verbatim}
typedef ModuleContext#(HList1#(UAList#(a))) ModuleCollect#(type a_type);
\end{verbatim}


% \BBS
%  struct ModuleCollect#(a\_type, ifc) 
%        {\rm{\emph{$\cdots$ abstract $\cdots$}}}
% \EBS

where \te{a\_type}  defines the type of 
the items being collected.   The collection is kept as an
\te{HList},  therefore each item in the  collection does not  have the
same type.  % The 
% collection is  associated with \te{ifc}, the device module interface.

Your new type of module is a \te{ModuleCollect} defined to collect a
specific type.  It is often convenient to give a name to your new type
of module using the \te{typedef} keyword.

For example:
\begin{libverbatim}
     typedef ModuleCollect#(element_type, ifc_device)
             MyModuleType#(type ifc_device)
\end{libverbatim}

specifies a type named \te{MyModuleType}.

An ordinary module, one defined with the keyword \te{module} without
a type in square brackets immediately after it, can be of any module
type.  It is polymorphic, and when  instantiated  takes the
type of the surrounding module context.   Only modules of type
\te{Module} can be synthesized, so the  \te{*synthesize*}
attribute forces the type to be \te{Module}.  This is equivalent to
writing:
\begin{libverbatim}
    module [Module]...
\end{libverbatim}
Normally, all the modules instantiated inside a synthesized module take
the type \te{Module}.

A module which is accumulating a collection must have the appropriate
type, specified in square brackets immedately after the keyword, as
shown in the following example:
\begin{libverbatim}
    module [AssertModule] mkAssertionReg...
\end{libverbatim}
The complete example is found later in this section.
This implies that any module instantiating \te{mkAssertionReg} is no
longer polymorphic, its type is constrained by the inner module, so it
will have to be explicitly given the \te{AssertModule} type too. Note,
however, that you can continue to instantiate other modules not
concerned with the collection (for example, \te{mkReg}, \te{mkFIFO},
etc.) alongside \te{mkAssertReg} just as before.  But now they will
take the type \te{AssertModule} from the context instead of the type
\te{Module}.  

Since only modules of type \te{Module} can be synthesized, before this
group of \te{AssertModule} instantiations can be 
synthesized, you must use  \te{exposeCollection} to  contain
the collection in a top-level module of type \te{Module}. 


% An ordinary module, one not
% collecting anything other than rules and state
% elements has the type \te{Module}.  When no type is explicitly given,
% the compiler fixes it to \te{Module} when the module is synthesized.
% But for a module accumulating a
% collection, the type must be explicitly given, and it is supplied in
% square brackets immediately after the keyword \te{module}.  Because in
% our example above, 
% the new type alias only takes one argument, the interface, we can use
% it here without arguments:

% \begin{libverbatim}
%     module [MyModuleType] mkSubDesign#(x,y) (IfcType) ;
% \end{libverbatim}

% Since only modules of type \te{Module} can be synthesized 
%  the collection  be  exposed before synthesis, by applying the
%  function \te{exposeCollection}.  The module type of
% the function \te{exposeCollection} is \te{Module}, so once the
% collection has  been exposed 
%  the design is ready for synthesis. 



{\bf Interfaces}

The \texttt{IWithCollection} interface couples the normal module
interface (the \texttt{device} interface) with the collection of
collected items (the \texttt{collection} interface).  This is the
interface provided by the \te{exposeCollection} function.  It separates
the collection list and the device  module interface, to allow the module to be synthesized.

\begin{verbatim}
   interface IWithCollection #(type a, type i);
       method i device();
       method List#(a) collection();
   endinterface: IWithCollection
\end{verbatim}

OLD:
\begin{verbatim}
   interface IWithCollection #(type collection_type, type item_type);
      interface item_type device();
      interface List#(collection_type) collection();
   endinterface: IWithCollection
\end{verbatim}


{\bf Modules and Functions}

% There are three functions defined within the \te{ModuleCollect}
% package; \te{addToCollection}, \te{exposeCollection}, and
% \te{mapCollection}.

In the course of
evaluating a module body during its instantiation, an item
may be added to the current collection by using the function
\texttt{addToCollection}. \index{addToCollection@\te{addToCollection} (\te{ModuleCollect} function)}

\begin{center}
\begin{tabular}{|p{1.1 in}|p{4.5 in}|}
\hline
&  \\
\te{addToCollection}&Adds an item to the collection.\\
&  \\
\cline{2-2}
&\begin{libverbatim}
function ModuleCollect#(a_type, ifc) 
         addToCollection(a_type item); 
\end{libverbatim}
\\
\hline
\end{tabular}
\end{center}

Once a set of items has been collected, those items must be
exposed  before synthesis.  The \texttt{exposeCollection} module
constructor is used to bring the collection out into the open. 
The \texttt{exposeCollection} module  takes as an argument a
\texttt{ModuleCollect} module (\texttt{m}) with interface \texttt{ifc},
and provides an \texttt{IWithCollection} interface.  
\index{exposeCollection@\te{exposeCollection} (\te{ModuleCollect} function)}

\begin{tabular}{|p{1.1 in}|p{4.5 in}|}
\hline
&  \\
\te{exposeCollection}&Expose the collection to allow the module to be synthesized.\\
&\\
\cline{2-2}
&\begin{libverbatim}
module exposeCollection#(ModuleCollect#(a_type, ifc) m)
                        (IWithCollection#(a_type, ifc));
\end{libverbatim}
\\
\hline
\end{tabular}

Finally, the \texttt{ModuleCollect} package provides a function, 
\texttt{mapCollection}, to apply a function to each item in the
current collection.
\index{mapCollection@\te{mapCollection} (\te{ModuleCollect} function)}

\begin{tabular}{|p{1.1 in}|p{4.5 in}|}
\hline
&  \\
\te{mapCollection}&Apply a function to each item added to the collection within
the second argument.\\
&  \\
\cline{2-2}
&\begin{libverbatim}
function ModuleCollect#(a_type, ifc) 
   mapCollection(function a_type x1(a_type x1), 
                 ModuleCollect#(a_type, ifc) x2); 
\end{libverbatim}
\\
\hline
\end{tabular}

{\bf Example - Assertion Wires}
\begin{libverbatim}
// This example shows excerpts of a design which places various
// test conditions (Boolean expressions) at random places in a design,
// and lights an LED (setting an external wire to 1), if the condition
// is ever satisfied.

import ModuleCollect::*;
import List::*;
import Vector::*;
import Assert::*;

// The desired interface at the top level is:
interface AssertionWires#(type n);
   method Bit#(n) wires;
   method Action clear;
endinterface

// The "wires" method tells which conditions have been set, and the
// "clear" method resets them all to 0.  
// The items in our extra collection will be interfaces of the
// following type:

interface AssertionWire;
   method Integer index;   //Indicates which wire is to be set if
   method Bool fail;       // fail method ever returns true.
   method Action clear;
endinterface

// We next define the "AssertModule" type.  This is to behave like an
// ordinary module providing an interface of type "i", except that it
// also can collect items of type "AssertionWire":

typedef ModuleCollect#(AssertionWire, i) AssertModule#(type i);

typedef Tuple2#(AssertionWires#(n), i) AssertIfc#(type i, type n);

...

// The next definition shows how items are added to the collection.
// This is the module which will be instantiated at various places in
// the design, to test various conditions.  It takes one static
// parameter, "ix", to specify which wire is to carry this condition,
// and one dynamic parameter (one varying at run-time) "c", giving the
// value of the condition itself.  

interface AssertionReg;
   method Action set;
   method Action clear;
endinterface

module [AssertModule] mkAssertionReg#(Integer ix)(AssertionReg);

   Reg#(Bool) cond <- mkReg(False);

   // an item is defined and added to the collection
   let item = (interface AssertionWire;
                 method index;
                    return (ix);
                 endmethod
                 method fail;
                    return(cond);
                 endmethod
                 method Action clear;
                     cond <= False;
                 endmethod
               endinterface);
   addToCollection(item);
   ...
endmodule
                     
// the collection must be exposed before synthesis       
module [Module] exposeAssertionWires#(AssertModule#(i) mkI)(AssertIfc#(i, n));
   
   IWithCollection#(AssertionWire, i) ecs <- exposeCollection(mkI);
   
   ...(c_ifc is created from the list ecs.collection)

   // deliver the array of values in the registers
   let dut_ifc = ecs.device;
    
   // return the values in the collection, and the ifc of the device
   return(tuple2(c_ifc, dut_ifc));
endmodule
\end{libverbatim}
