import byucc.jhdl.base.*;
import byucc.jhdl.Logic.*;
import byucc.jhdl.Xilinx.Virtex.VirtexTechMapper;

public class tb_NBitAdder extends Logic implements ProgrammaticTestBench {
 
  public Cell design; 

  public static void main(String argv[]) {
    tb_NBitAdder tb = new tb_NBitAdder(new HWSystem());

    boolean netlist = false, cvt = false;

    for ( int argi = 0; argi < argv.length; ++argi ) {
      String arg = argv[argi];
      if ( arg.equals("--netlist") && !cvt ) {
	netlist = true;
      } else if ( arg.equals("--cvt") && !netlist ) {
	cvt = true;
      } else {
	System.err.println("USAGE: java tb_NBitAdder [--netlist|--cvt]");
	return;
      }
    }

    if ( netlist ) {
      tb.getDefaultTechMapper().netlist(tb.design);
      System.out.println("Netlisted NBitAdder, now exiting.");
      return;
    } else if ( cvt ) {
      new cvt( tb );
      return;
    } else {
      tb.execute();
    }
  }

  private Wire a, b, sum;
  
  public tb_NBitAdder(Node parent) {
    super(parent);

    setDefaultTechMapper(new VirtexTechMapper(true));

    final int adder_width = 63;

    a = wire(adder_width, "a");
    b = wire(adder_width, "b");
    sum = wire(adder_width, "sum");

    design = new NBitAdder(this, a, b, sum);

  }

  private long a_val, b_val, sum_val;

  public void execute() {

    final long a_iterations = 10;
    final long b_iterations = 500;

    for (long i=0;i<a_iterations;i++) {
      for (long j=0;j<b_iterations;j++) {
	a_val = i;
	b_val = j;
	getSystem().cycle(1);
	getValues();
	long correct = a_val + b_val;
	if (sum_val != correct) {
	  System.out.println("NBitAdder failed miserably!");
	  System.out.println("a = " + a_val);
	  System.out.println("b = " + b_val);
	  System.out.println("sum = " + sum_val);
	  System.out.println("correct = " + correct);
	  return;
	}
      }
    }
    System.out.println("NBitAdder passed with flying colors.");
  }
  
  public void reset() {
    a.putL(this, 0);
    b.putL(this, 0);
  }
 
  public void clock() {
    a.putL(this, a_val);
    b.putL(this, b_val);
  }

  public void getValues() {
    sum_val = sum.getL(this);
  }

}
