
import byucc.jhdl.base.CellInterface;
import byucc.jhdl.base.Node;
import byucc.jhdl.base.Wire;
import byucc.jhdl.Logic.Logic;
import byucc.jhdl.Xilinx.Virtex.Modules.Equals;
import byucc.jhdl.Xilinx.Virtex.Modules.upcnt;

/** This parameterizable module implements a concept of a network
 * monitor/filter.  A large input bus represents packets streamed into
 * the system.  The monitor counts the number of packets whose
 * destination address matches one of a set of addresses of interest.
 * A subset of those address is designated for blocking.  That is, if
 * such an address is detected, the packet is not allowed to pass
 * through the system.
 * @author Anthony L. Slade */
public class NetworkMonitor extends Logic {

  public static CellInterface[] cell_interface = {
    in( "packetInput", "PACKETWIDTH" ),
    in( "resetCounts", 1 ),
    out( "packetOutput", "PACKETWIDTH" ),
    param("PACKETWIDTH",INTEGER),
  };

  /**
   * @param parent the parent node of this cell
   * @param hitValues the values to watch for
   * @param blockValues the values to watch for _and_ block
   * @param packetInput the packets being streamed in
   * @param addressLo the low-order bit of the address field in the
   * packets
   * @param addressHi the high-order bit of the address field in the
   * packets
   * @param packetOutput the packet output
   * @param countersWidth the width of the counters for the hits to watch
   */
  public NetworkMonitor( Node parent, int[] hitValues,
			 int[] blockValues, Wire packetInput,
			 int addressLo, int addressHi,
			 Wire resetCounts,
			 Wire packetOutput, int countersWidth ) {
    super( parent );
    bind( "PACKETWIDTH", packetInput.getWidth() );
    Wire netIn = connect( "packetInput", packetInput );
    Wire reset = connect( "resetCounts", resetCounts );
    Wire netOut = connect( "packetOutput", packetOutput );

    Wire toCompare = netIn.range( this, addressHi, addressLo );

    // Create the comparators and counters
    if ( 0 < hitValues.length )
      new HitCounterArray( this, hitValues, toCompare,
			   reset, countersWidth, nc(), "ToCount" );
    Wire matchToBlock;
    if ( 0 < blockValues.length ) {
      matchToBlock = wire( 1, "blockingHit" );
      new HitCounterArray( this, blockValues, toCompare,
			   reset, countersWidth, matchToBlock, "ToBlock" );
    } else
      matchToBlock = constant( 1, 0, "alwaysOn" );

    // set up a register that does simply passes the packets through
    // unless an address to block is detected
    regr_o( packetInput, matchToBlock, packetOutput );

  }
  
} // end class NetworkMonitor
