#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "util.h"
#include "vpack.h"
#include "globals.h"
#include "output_clustering.h"

#define LINELENGTH 160

/*------------------------------------------------------------
 *  Copyright 2002 By Kara K.W. Poon and Steve Wilton
 *
 * Permission to use, copy, and modify this software and its documentation is
 * hereby granted only under the following terms and conditions.  Both the
 * above copyright notice and this permission notice must appear in all copies
 * of the software, derivative works or modified versions, and any portions
 * thereof, and both notices must appear in supporting documentation.
 * Permission is granted ONLY for non-commercial use.  For
 * commercial use, please contact the authors.
 *
 * This software may be distributed (but not offered for sale or transferred
 * for compensation) to third parties, provided such third parties agree to
 * abide by the terms and conditions of this notice.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS, AS
 * WELL AS THE UNIVERSITY OF BRITISH COLUMBIA AND THE
 * UNIVERSITY OF TORONTO DISCLAIM ALL WARRANTIES WITH
 * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL THE
 * AUTHORS OR THE UNIVERSITY OF BRITISH COLUMBIA OR THE
 * UNIVERSITY OF TORONTO BE LIABLE FOR ANY SPECIAL, DIRECT,
 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *------------------------------------------------------------*/

/*
  T-Vpack was written by Vaughn Betz at the University of Toronto.
  
  May 2001   Modified by Dr. Steve Wilton at the University 
             of British Columbia to propagate signal 
             activities
  July 2001  Further modified by Kara Poon at the University 
             of British Columbia to propagate both
             static probability and transition density

 */
/*
  November 2006		Modified by Yu Chi Wai at the Imperial
					College of London to support adding 
					virtual embedded block (VEB) to the circuit
 */

/****************** Subroutines local to this module ************************/

static void print_subblock_ipin (int inet, int *io_net_mapping, int 
         inputs_per_cluster, int cluster_size, int *column_ptr, FILE *fpout); 

static void print_subblock_opin (int inet, int *io_net_mapping, int 
     inputs_per_cluster, int *net_of_clb_pin, int *column_ptr, FILE *fpout,
     boolean muxes_to_cluster_output_pins); 

static void print_cluster_pins (FILE *fpout, int icluster, int lut_size, int **cluster_contents, int *cluster_occupancy, int cluster_size) ;
static void print_subblock_pins (FILE *fpout, int icluster, int lut_size, int **cluster_contents, int *cluster_occupancy, int cluster_size) ;
static void print_pins_transparent (FILE *fpout, int bnum) ;
void print_statistic();

/**************** Subroutine definitions ************************************/

int dspnum = 0;
int memnum = 0;
int vebnum = 0;

static void print_string (char *str_ptr, int *column, FILE *fpout) {

/* Prints string without making any lines longer than LINELENGTH.  Column  *
 * points to the column in which the next character will go (both used and *
 * updated), and fpout points to the output file.                          */

 int len;

 len = strlen(str_ptr);
 if (len + 3 > LINELENGTH) {
     printf("Error in print_string: String %s is too long for desired\n"
            "maximum line length.\n", str_ptr);
     exit(1);
 }
 
 if (*column + len + 2 > LINELENGTH) {
    fprintf(fpout,"\\\n");
    *column = 1;
 }
 
 fprintf(fpout,"%s ",str_ptr);
 *column += len + 1;
}


static void print_net_name (int inet, int *column, FILE *fpout) {

/* This routine prints out the net name (or open) and limits the    *
 * length of a line to LINELENGTH characters by using \ to continue *
 * lines.  net_num is the index of the net to be printed, while     *
 * column points to the current printing column (column is both     *
 * used and updated by this routine).  fpout is the output file     *
 * pointer.                                                         */
 
 char *str_ptr;
 
 if (inet == OPEN)
    str_ptr = "open";
 else
    str_ptr = net[inet].name;
 
 print_string (str_ptr, column, fpout);
}


static void print_net_number (int inet, int *column, FILE *fpout) {

/* Prints out either a number or "open".                     */

 char str[BUFSIZE];

 if (inet == OPEN) 
    sprintf (str, "open");
 else
    sprintf (str, "%d", inet);

 print_string (str, column, fpout);
}


static void print_pins (FILE *fpout, int bnum, int lut_size) {

/* This routine is used only for netlists that have NOT been clustered.   *
 * It prints out the pinlist for a clb that contains either a LUT, a      *
 * LATCH or both, assuming that each LUT input needs its own pin, and     *
 * the output cannot be fed back to inputs via local routing.  It prints  *
 * the LUT inputs and output in the order below so that the net ordering  *
 * when parsed will be the same as that of the old combinational blif     *
 * parsing in vpr.  This allows the routing serial numbers to be compared.*/
 
 int ipin, column, netnum;
 
 fprintf(fpout,"pinlist: ");
 
 column = 10;   //Next column I will write to. 
 
/* LUT inputs first. */
 
 for (ipin=1;ipin<=lut_size;ipin++) {
    netnum = block[bnum].nets[ipin];
    print_net_name (netnum, &column, fpout);
 }
 
/* Output next.  */
 
 netnum = block[bnum].nets[0];
 print_net_name (netnum, &column, fpout);
 
/* Clock last. */
 
 netnum = block[bnum].nets[lut_size+1];
 print_net_name (netnum, &column, fpout);
 
 fprintf(fpout,"\n");
}



static void print_cluster_pins (FILE *fpout, int icluster, int lut_size, int **cluster_contents, int *cluster_occupancy, int cluster_size) {


	int ipin, column, netnum;
	int inet;
	char*  temp_name;

	int num_block;	
	int i;
	int iblk;

	//block 0 is the bottom BLE (x), 1 is upper BLE (y)
	temp_name = strtok( block[cluster_contents[icluster][0]].name , "\\");
	//fprintf (fpout,".clb %s\n", block[cluster_contents[icluster][0]].name);
	fprintf (fpout,".clb %s \n", temp_name);
	fprintf(fpout,"pinlist: ");

	num_block = cluster_occupancy[icluster] ;	//number of block in this cluster 

//	printf (".clb %s %d\n", temp_name);
//	printf("pinlist: ");

	column = 10;   //Next column I will write to. 
	
	//--share pin
	//SOPIN: 0
//	printf("icluster %d, blocknum = %d \n", icluster, cluster_contents[icluster][1]);
//	printf("icluster %d, blocknum = %d \n", icluster, cluster_contents[icluster][0]);
/*
	if (cluster_occupancy[icluster]>1)
		inet = block[cluster_contents[icluster][1]].nets[B_SOPIN];
	else
		inet = OPEN;


	if ( inet != OPEN)	
		fprintf(fpout,"\t%s", net[inet].name);
	else
		fprintf(fpout,"\topen");
*/	
	fprintf(fpout,"\topen");

	//ALTDIG: 1
	/*
	if (cluster_occupancy[icluster]>1)
		inet = block[cluster_contents[icluster][num_block]].nets[B_ALTDIG];
	else
		inet = OPEN;

	if ( inet != OPEN)	
		fprintf(fpout,"\t%s", net[inet].name);
	else
		fprintf(fpout,"\topen");
*/
	fprintf(fpout,"\topen");

	//CE : 2
	for (i= 0 ; i < num_block; i++)
	{
		//print the net name
		inet = block[cluster_contents[icluster][i]].nets[B_CE];
		if (inet != OPEN)
		{
			fprintf(fpout,"\t%s ", net[inet].name);
			break;
		}		
	}

	if (i == num_block)
	{
		//no net connected
		fprintf(fpout,"\topen");
	}

	
	//CLK : 3

	for (i= 0 ; i < num_block; i++)
	{
		//print the net name
		inet = block[cluster_contents[icluster][i]].nets[B_CLK];
		if (inet != OPEN)
		{
			fprintf(fpout,"\t%s ", net[inet].name);
			break;
		}		
	}

	if (i == num_block)
	{
		//no net connected
		fprintf(fpout,"\topen");
	}

	//SR : 4

	for (i= 0 ; i < num_block; i++)
	{
		//print the net name
		inet = block[cluster_contents[icluster][i]].nets[B_SR];
		if (inet != OPEN)
		{
			fprintf(fpout,"\t%s ", net[inet].name);
			break;
		}		
	}

	if (i == num_block)
	{
		//no net connected
		fprintf(fpout,"\topen");
	}


	//DIG : 5
	/*
	if (cluster_occupancy[icluster]>1)
		inet = block[cluster_contents[icluster][1]].nets[B_DIG];
	else
		inet = OPEN;

	if ( inet != OPEN)	
		fprintf(fpout,"\t%s", net[inet].name);
	else
		fprintf(fpout,"\topen");
		*/

	fprintf(fpout,"\topen");

	//SOPOUT : 6
	/*
	if (cluster_occupancy[icluster]>1)
		inet = block[cluster_contents[icluster][1]].nets[B_SOPOUT];
	else
		inet = OPEN;

	if ( inet != OPEN)	
		fprintf(fpout,"\t%s", net[inet].name);
	else
		fprintf(fpout,"\topen");
		*/

	fprintf(fpout,"\topen");

	//CIN:7
	inet = block[cluster_contents[icluster][0]].nets[B_CIN];
	if ( inet != OPEN)	
		fprintf(fpout,"\t%s ", net[inet].name);
	else
		fprintf(fpout,"\topen");


	//COUT :8
	if (cluster_occupancy[icluster] == cluster_size)
		inet = block[cluster_contents[icluster][cluster_size - 1]].nets[B_COUT];
	else
		inet = OPEN;

	if ( inet != OPEN)	
		fprintf(fpout,"\t%s ", net[inet].name);
	else
		fprintf(fpout,"\topen");

	//for each block 

	for (iblk=0;iblk<cluster_occupancy[icluster];iblk++) 
	{		
		//B_SHIFTIN = 0,
		inet = block[cluster_contents[icluster][iblk]].nets[B_SHIFTIN];
		if ( inet != OPEN)	
			fprintf(fpout,"\t%s ", net[inet].name);
		else
			fprintf(fpout,"\topen");

		//B_SHIFTOUT =1,
		inet = block[cluster_contents[icluster][iblk]].nets[B_SHIFTOUT];
		if ( inet != OPEN)	
			fprintf(fpout,"\t%s ", net[inet].name);
		else
			fprintf(fpout,"\topen");

		//B_BY= 2, 
		inet = block[cluster_contents[icluster][iblk]].nets[B_BY];
		if ( inet != OPEN)	
			fprintf(fpout,"\t%s ", net[inet].name);
		else
			fprintf(fpout,"\topen");

		//B_BYOUT= 3,
		fprintf(fpout,"\topen");

		//B_YB=4,
		inet = block[cluster_contents[icluster][iblk]].nets[B_YB];
		if ( inet != OPEN)	
			fprintf(fpout,"\t%s ", net[inet].name);
		else
			fprintf(fpout,"\topen");

		//B_Y=5,
		inet = block[cluster_contents[icluster][iblk]].nets[B_Y];
		if ( inet != OPEN)	
			fprintf(fpout,"\t%s ", net[inet].name);
		else
			fprintf(fpout,"\topen");

		//B_DY=6,
		inet = block[cluster_contents[icluster][iblk]].nets[B_DY];
		if ( inet != OPEN)	
			fprintf(fpout,"\t%s ", net[inet].name);
		else
			fprintf(fpout,"\topen");

		//B_YQ=7,
		inet = block[cluster_contents[icluster][iblk]].nets[B_Q];
		if ( inet != OPEN)	
			fprintf(fpout,"\t%s ", net[inet].name);
		else
			fprintf(fpout,"\topen");

		//B_FXINA=8,
		inet = block[cluster_contents[icluster][iblk]].nets[B_FXINA];
		if ( inet != OPEN)	
			fprintf(fpout,"\t%s ", net[inet].name);
		else
			fprintf(fpout,"\topen");

		//B_FXINB=9,
		inet = block[cluster_contents[icluster][iblk]].nets[B_FXINB];
		if ( inet != OPEN)	
			fprintf(fpout,"\t%s ", net[inet].name);
		else
			fprintf(fpout,"\topen");

		//B_FX=10,
		inet = block[cluster_contents[icluster][iblk]].nets[B_FX];
		if ( inet != OPEN)	
			fprintf(fpout,"\t%s ", net[inet].name);
		else
			fprintf(fpout,"\topen");

		//B_LUT_IN =11
		for (ipin = 0; ipin <lut_size; ipin ++)
		{			
			inet = block[cluster_contents[icluster][iblk]].nets[B_LUT_IN + ipin];
			
			if ( inet != OPEN)	
				fprintf(fpout,"\t%s ", net[inet].name);
			else
				fprintf(fpout,"\topen");
		}

	}

	for (iblk=cluster_occupancy[icluster];iblk<cluster_size;iblk++) 
	{
		//B_SHIFTIN = 0,		
		fprintf(fpout,"\topen");
		//B_SHIFTOUT =1,		
		fprintf(fpout,"\topen");		
		//B_BY= 2, 		
		fprintf(fpout,"\topen");
		//B_BYOUT= 3,		
		fprintf(fpout,"\topen");
		//B_YB=4,		
		fprintf(fpout,"\topen");
		//B_Y=5,		
		fprintf(fpout,"\topen");
		//B_DY=6,		
		fprintf(fpout,"\topen");
		//B_YQ=7,		
		fprintf(fpout,"\topen");
		//B_FXINA=8,		
		fprintf(fpout,"\topen");
		//B_FXINB=9,		
		fprintf(fpout,"\topen");
		//B_FX=10,		
		fprintf(fpout,"\topen");

		//B_LUT_IN =11
		for (ipin = 0; ipin <lut_size; ipin ++)
		{						
			fprintf(fpout,"\topen");
		}
	}


	fprintf(fpout,"\n");
}


static void print_subblock_pins (FILE *fpout, int icluster, int lut_size, int **cluster_contents, int *cluster_occupancy, int cluster_size) 
{
	int iblk, sub_blk, inet, ipin ;
	int base;
	char*  temp_name;
	for (iblk=0;iblk<cluster_occupancy[icluster];iblk++) 
	{
		fprintf(fpout,"subblock: ");
		sub_blk = cluster_contents[icluster][iblk];
		temp_name = strtok( block[sub_blk].name , "\\");
		fprintf(fpout,"%s ", temp_name);

		base = SLICE_SUBBLOCK + iblk *(SUB_LUT_IN + lut_size );
		
		//SUB_SHIFTIN = 0,
		inet = block[cluster_contents[icluster][iblk]].nets[B_SHIFTIN];
		if ( inet != OPEN)	
			fprintf(fpout,"\t%d", SUB_SHIFTIN + base);
		else
			fprintf(fpout,"\topen");

		//SUB_SHIFTOUT =1,
		inet = block[cluster_contents[icluster][iblk]].nets[B_SHIFTOUT];
		if ( inet != OPEN)	
			fprintf(fpout,"\t%d", SUB_SHIFTOUT + base);
		else
			fprintf(fpout,"\topen");

		//SUB_CIN =2,
		if (iblk == 0)
		{
			//start of carry chain
			inet = block[cluster_contents[icluster][iblk]].nets[B_CIN];
			if ( inet != OPEN)	
				fprintf(fpout,"\t%d", SLICE_CIN);
			else
				fprintf(fpout,"\topen");
		}
		else
		{
			inet = block[cluster_contents[icluster][iblk]].nets[B_CIN];
			if (inet != OPEN)
			{
				fprintf(fpout,"\tble_%d_%d", iblk - 1,  SUB_COUT);
			}
			else
			{
				fprintf(fpout,"\topen");
			}
		}

		//SUB_COUT =3,		
		if (iblk == (cluster_size - 1))
		{
			//end of carry chain
			inet = block[cluster_contents[icluster][iblk]].nets[B_COUT];
			if ( inet != OPEN)	
				fprintf(fpout,"\t%d", SLICE_COUT);
			else
				fprintf(fpout,"\topen");
		}
		else
		{
			inet = block[cluster_contents[icluster][iblk]].nets[B_COUT];
			if (inet != OPEN)
			{
				fprintf(fpout,"\tble_%d_%d", iblk + 1,  SUB_CIN);
			}
			else
			{
				fprintf(fpout,"\topen");
			}
		}

		//SUB_BY= 4, 
		inet = block[cluster_contents[icluster][iblk]].nets[B_BY];
		if ( inet != OPEN)	
			fprintf(fpout,"\t%d", SUB_BY + base);
		else
			fprintf(fpout,"\topen");

		//SUB_BYOUT= 5,		
		fprintf(fpout,"\topen");

		//SUB_YB=6,
		inet = block[cluster_contents[icluster][iblk]].nets[B_YB];
		if ( inet != OPEN)	
			fprintf(fpout,"\t%d", SUB_YB + base);
		else
			fprintf(fpout,"\topen");

		//SUB_Y=7,
		inet = block[cluster_contents[icluster][iblk]].nets[B_Y];
		if ( inet != OPEN)	
			fprintf(fpout,"\t%d", SUB_Y + base);
		else
			fprintf(fpout,"\topen");

		//SUB_DY=8,
		inet = block[cluster_contents[icluster][iblk]].nets[B_DY];
		if ( inet != OPEN)	
			fprintf(fpout,"\t%d", SUB_DY + base);
		else
			fprintf(fpout,"\topen");

		//SUB_YQ=9,
		inet = block[cluster_contents[icluster][iblk]].nets[B_Q];
		if ( inet != OPEN)	
			fprintf(fpout,"\t%d", SUB_YQ + base);
		else
			fprintf(fpout,"\topen");

		//SUB_FXINA = 10,
		inet = block[cluster_contents[icluster][iblk]].nets[B_FXINA];
		if ( inet != OPEN)	
			fprintf(fpout,"\t%d", SUB_FXINA + base);
		else
			fprintf(fpout,"\topen");

		//SUB_FXINB = 11,
		inet = block[cluster_contents[icluster][iblk]].nets[B_FXINB];
		if ( inet != OPEN)	
			fprintf(fpout,"\t%d", SUB_FXINB + base);
		else
			fprintf(fpout,"\topen");

		//SUB_FX = 12,
		inet = block[cluster_contents[icluster][iblk]].nets[B_FX];
		if ( inet != OPEN)	
			fprintf(fpout,"\t%d", SUB_FX + base);
		else
			fprintf(fpout,"\topen");


		//SUB_CE=13,
		inet = block[cluster_contents[icluster][iblk]].nets[B_CE];
		if ( inet != OPEN)	
			fprintf(fpout,"\t%d", SLICE_CE);
		else
			fprintf(fpout,"\topen");

		//SUB_SR=14,
		inet = block[cluster_contents[icluster][iblk]].nets[B_SR];
		if ( inet != OPEN)	
			fprintf(fpout,"\t%d", SLICE_SR);
		else
			fprintf(fpout,"\topen");

		//SUB_CLK=15,
		inet = block[cluster_contents[icluster][iblk]].nets[B_CLK];
		if ( inet != OPEN)	
			fprintf(fpout,"\t%d", SLICE_CLK);
		else
			fprintf(fpout,"\topen");

		//SUB_LUT_IN =16
		for (ipin = 0; ipin < lut_size; ipin ++)
		{
			inet = block[cluster_contents[icluster][iblk]].nets[B_LUT_IN + ipin];
			if ( inet != OPEN)	
				fprintf(fpout,"\t%d", base + SUB_LUT_IN + ipin);
			else
				fprintf(fpout,"\topen");
		}
		fprintf(fpout,"\n");
	}
	fprintf(fpout,"\n\n");

}

static void print_clbs (FILE *fpout, int *cluster_occupancy, 
          int **cluster_contents, int *cluster_carryouts, int *cluster_carryout_blocks,
          int lut_size, int cluster_size, 
          int inputs_per_cluster, int clocks_per_cluster, 
          int num_clusters, boolean muxes_to_cluster_output_pins) 
{

/* Prints out one cluster (clb).  Both the external pins and the *
 * internal connections are printed out.                         */

 int ipin, icluster, sub_blk, num_clb_pins, inet, free_pin_index, i,j, found_cluster;
 int column, iblk;
 int redundant_outputs, used_outputs, total_used_ble_inputs;
 int total_locally_generated_ble_inputs, total_bles;
 char str[BUFSIZE];
 int total_nets = 0;
 int total_pins = 0;
 int total_intercluster_nets = 0;
 int total_intracluster_nets = 0;
 int total_intercluster_pins = 0;
 int total_intracluster_pins = 0;
 float total_power = 0.0;
 float total_intercluster_act = 0.0;
 float total_intracluster_act = 0.0;
 float average_intercluster_act = 0.0;
 float average_intracluster_act = 0.0;
 float total_act = 0.0;
 float average_act = 0.0;
 float diff = 0.0;
 float intercluster_diff = 0.0;
 float intracluster_diff = 0.0;
 float variance = 0.0;
 float intercluster_variance = 0.0;
 float intracluster_variance = 0.0;
 float std_dev = 0.0;
 float intercluster_std_dev = 0.0;
 float intracluster_std_dev = 0.0;


/* [0..num_nets-1].  Which clb pin connects to this net?   Need  *
 * separate data structures for input or output pins and clocks, *
 * because a clock net could connect to both a clb output and a  *
 * clock input.                                                  */

 int *io_net_mapping, *clock_net_mapping, *num_pins_in_cluster;

// [0..num_cluster_pins].  Net connected to this clb pin. 
 int *net_of_clb_pin;

printf("num_clusters %d \n", num_clusters);

 for (icluster=0;icluster<num_clusters;icluster++) 
 {
	//printf("icluster %d \n", icluster);
	print_cluster_pins(fpout, icluster, lut_size, cluster_contents, cluster_occupancy,cluster_size);
	print_subblock_pins(fpout,icluster, lut_size, cluster_contents, cluster_occupancy, cluster_size);
 } 
		 
}


static void print_subblock_ipin (int inet, int *io_net_mapping, int 
         inputs_per_cluster, int cluster_size, int *column_ptr, FILE *fpout) {

/* Prints out where a subblock gets its input pin from. */

 char str[BUFSIZE];
 int ble_num;

 if (inet == OPEN) {
    print_net_number (OPEN, column_ptr, fpout);
 }
 else if (io_net_mapping[inet] >= inputs_per_cluster && io_net_mapping[inet] 
                      < inputs_per_cluster + cluster_size) {

   /* Subblock input comes from a BLE output within this cluster. */

    ble_num = io_net_mapping[inet] - inputs_per_cluster;
    sprintf (str, "ble_%d", ble_num);
    print_string (str, column_ptr, fpout);
 }
 else {    /* Regular input or clock pin */
    print_net_number (io_net_mapping[inet], column_ptr, fpout);
 }
}


static void print_subblock_opin (int inet, int *io_net_mapping, int 
     inputs_per_cluster, int *net_of_clb_pin, int *column_ptr, FILE *fpout, 
     boolean muxes_to_cluster_output_pins) {

/* Prints out a subblock output pin.  If the net driven by this BLE is used *
 * only internally to the clb, then the subblock output is marked as OPEN.  */

 int clb_pin;

 if (inet == OPEN) {
    printf ("Error in print_subblock_opin:  inet = %d.\n", inet);
    exit (1);
/*    print_net_number (OPEN, column_ptr, fpout);  */
 }
 else {
    clb_pin = io_net_mapping[inet];
    if (net_of_clb_pin[clb_pin] == OPEN && muxes_to_cluster_output_pins) { 
      /* Output not used outside clb and subblock output not directly    *
       * connected to the CLB output pin.                                */
       print_net_number (OPEN, column_ptr, fpout);
    }
    else {
       print_net_number (clb_pin, column_ptr, fpout);
    }
 }
}


void output_clustering (int **cluster_contents, int *cluster_occupancy,
     int *cluster_carryouts, int *cluster_carryout_blocks,
     int cluster_size, int inputs_per_cluster, int clocks_per_cluster,
     int num_clusters, int lut_size, boolean global_clocks, boolean
     muxes_to_cluster_output_pins, boolean *is_clock, char *out_fname) {

/* This routine dumps out the output netlist in a format suitable for  *
 * input to vpr.  The clb pins are in the following order:             *
 * inputs_per_cluster inputs, cluster_size outputs, and                *
 * clocks_per_cluster clocks.  For a single LUT cluster, this reduces  *
 * to N LUT inputs, 1 output, followed by the clock input.  Pins that  *
 * are unconnected are marked as open.  If global_clocks is TRUE, all  *
 * the clock nets (nets marked with TRUE in is_clock) will be set to   *
 * be global.  This routine also dumps out the internal structure of   *
 * the cluster, in essentially a graph based format.  For each LUT +   * 
 * FF subblock, I write out which cluster pin connects to each of the  *
 * LUT pins.  The LUT + FF pins are ordered as N LUT inputs, LUT       *
 * output, then clock.  If a pin is not connected, it is marked as     *
 * OPEN.  Otherwise, it is given the number of the cluster pin to      *
 * which it connects -- the cluster pins begin with inputs (starting   *
 * from 0), then list outputs, then clocks.  Hence all cluster pins    *
 * have an index from 0 to inputs_per_cluster + cluster_size +         *
 * clocks_per_cluster - 1.                                             *
 * If cluster_contents is NULL, this routine prints out an unclustered *
 * netlist -- i.e. it just prints out the LUT+FF logic blocks with all *
 * pins distint.                                                       */

 FILE *fpout;
 int bnum, netnum, column;
 boolean skip_clustering;
 int inet;
 
 FILE *iofile;
 char iofilename[BUFSIZE];

 if (cluster_contents == NULL)    /* No clustering was performed. */
 {
    skip_clustering = TRUE;
	printf("cluster contents is null \n");
 }
 else
 {
    skip_clustering = FALSE;
 }

 fpout = my_fopen (out_fname, "wb", 0);
 
 strncpy(iofilename, out_fname, strlen(out_fname)-4);
 strcat(iofilename, ".io");
 iofile = my_fopen (iofilename, "wb", 0);

 if (global_clocks) {
    for (netnum=0;netnum<num_nets;netnum++) {
       if (is_clock[netnum])
          fprintf(fpout,".global %s\n\n", net[netnum].name);
    }
 }

 //print to IO file for name conversion in topmodule
 
 //print the clock first
 for(bnum = 0; bnum< num_blocks; bnum++)
 {
 	netnum = block[bnum].nets[0];
 	if (block[bnum].type == INPAD && is_clock[netnum]) 
	{
		if (netnum != OPEN)
			fprintf(iofile, "%s\t1\n",net[netnum].name);
		else
			fprintf(iofile, "open\t1\n");
	}
 }
 
 //print the input
 for(bnum = num_blocks - 1; bnum>=0; bnum--)
 {
 	netnum = block[bnum].nets[0];
 	if (block[bnum].type == INPAD && !is_clock[netnum]) 
	{
		if (netnum != OPEN)
			fprintf(iofile, "%s\t1\n",net[netnum].name);
		else
			fprintf(iofile, "open\t1\n");
	}
 }
 
 //print the output
 for(bnum = num_blocks - 1; bnum>=0; bnum--)
 {
 	netnum = block[bnum].nets[0];
 	if (block[bnum].type == OUTPAD && !is_clock[netnum]) 
	{
		if (netnum != OPEN)
			fprintf(iofile, "%s\t0\n",net[netnum].name);
		else
			fprintf(iofile, "open\t0\n");
	}
 }
 
    
// Print out all input and output pads. 
 
 //for(bnum=num_blocks-1;bnum>=0; bnum--) {
 for(bnum= 0; bnum <num_blocks; bnum++) {

    switch (block[bnum].type) {
 
    case INPAD:
	case VCC:
	case GND:

       netnum = block[bnum].nets[0];

		if (netnum != OPEN)
		{
	       fprintf(fpout,".input %s \n", block[bnum].name);
    	   fprintf(fpout,"pinlist: ");
	       column = 10;
   	    	print_net_name (netnum, &column, fpout);
    	   fprintf (fpout, "\n\n");
		   if (block[bnum].type == VCC || block[bnum].type == GND)
		   {
			fprintf(fpout,".global %s\n\n", net[netnum].name);
		   }
		}
       	
       break;			
 
    case OUTPAD:
       fprintf(fpout,".output %s \n", block[bnum].name);
       netnum = block[bnum].nets[0];
       fprintf(fpout,"pinlist: ");
       column = 10;
       print_net_name (netnum, &column, fpout);
       fprintf (fpout, "\topen\topen\topen\topen\topen\topen\n\n");
              	
       break;
 
    case LUT:
	case LATCH:
	case LUT_AND_LATCH:
       if (skip_clustering) {
		   
          //fprintf(fpout,".clb %s  # Only LUT used.\n", block[bnum].name);
		   fprintf(fpout,".clb %s  \n", block[bnum].name);
          //print_pins (fpout, bnum, lut_size);
          //print_basic_subblock (fpout, bnum, lut_size);
		  
       }
       break;
/*
	case LATCH:
		if (skip_clustering) {
			fprintf(fpout,".clb %s  # Only LATCH used.\n", block[bnum].name);
			//print_pins (fpout, bnum, lut_size);
			//print_basic_subblock (fpout, bnum, lut_size);
		}
		break;

	case LUT_AND_LATCH:
		if (skip_clustering) {
			fprintf(fpout,".clb %s  # Both LUT and LATCH used.\n",
				block[bnum].name);
			//print_pins (fpout, bnum, lut_size);
			//print_basic_subblock (fpout, bnum, lut_size);
		}
		break;
		*/

    case DSP:
	case DSPS:
        fprintf(fpout,".dsp %s \n",block[bnum].name);
		fprintf(fpout,"pinlist: ");
		for (inet = 0; inet <block[bnum].num_nets; inet++)
		{
	  		if (block[bnum].nets[inet] != OPEN)
			{
	  			fprintf(fpout, "%s \t", net[block[bnum].nets[inet]].name);
			}
			else
			{
				fprintf(fpout, "OPEN\t");
			}
			//fprintf(fpout, "%d\t", block[bnum].nets[inet]);
		}
		if (block[bnum].type == DSP)
		{
			fprintf(fpout, "OPEN\t"); //C
			fprintf(fpout, "OPEN\t"); //CE
			fprintf(fpout, "OPEN\t"); //R
		}
	  
		fprintf(fpout,"\n");
        dspnum++;
        //  print_pins_transparent (fpout, bnum);
          break;

    case MEMORY:
          fprintf(fpout,".memory %s \n",block[bnum].name);
          memnum++;
          print_pins_transparent (fpout, bnum);

 	case VEB:
      fprintf(fpout,".emb %s \n",block[bnum].name);
	  printf("emb: %s, num_input %d, num_output %d, num_net %d \n", block[bnum].name, block[bnum].num_input, block[bnum].num_output, block[bnum].num_nets);
	  
	  fprintf(fpout,"pinlist \t");
	  
	  for (inet = 0; inet <block[bnum].num_nets; inet++)
	  {
	  	if (block[bnum].nets[inet] != OPEN)
		{
	  		fprintf(fpout, "%s \t", net[block[bnum].nets[inet]].name);
		}
		else
		{
			fprintf(fpout, "OPEN\t");
		}
		//fprintf(fpout, "%d\t", block[bnum].nets[inet]);
	  }
	  
	  fprintf(fpout,"\n");
	  
	  
          vebnum++;
         // print_pins_transparent (fpout, bnum);
          break;
      
       break;



    case EMPTY:
       printf("Error in output_netlist -- block %d is EMPTY.\n",bnum);
       exit (1);
       break;

    default:
       printf("Error in output_netlist.  Unexpected type %d for block"
            "%d.\n", block[bnum].type, bnum);
    }

 }

 if (skip_clustering == FALSE) 
    print_clbs (fpout, cluster_occupancy, cluster_contents, cluster_carryouts, cluster_carryout_blocks,lut_size,
         cluster_size, inputs_per_cluster, clocks_per_cluster, 
         num_clusters, muxes_to_cluster_output_pins); 

 fclose (fpout);
 fclose (iofile);
}



void output_activities (int **cluster_contents, int *cluster_occupancy,
     int cluster_size, int inputs_per_cluster, int clocks_per_cluster,
     int num_clusters, int lut_size, boolean global_clocks, boolean
     muxes_to_cluster_output_pins, boolean *is_clock, char *out_fname) 
{
  /* output the activity to an output file */
 FILE *fpout;
 int bnum, netnum, column;
 boolean skip_clustering;
 int i;

 if (out_fname[0] == '\0') {
    return;   /* do not output activities */
 }
 if (cluster_contents == NULL)    /* No clustering was performed. */
    skip_clustering = TRUE;
 else
    skip_clustering = FALSE;

    
 fpout = my_fopen (out_fname, "w", 0);

 if (global_clocks) {
    for (netnum=0;netnum<num_nets;netnum++) {
       
          if (is_clock[netnum])
				{       
				 fprintf(fpout,"global_net_probability %s %f\n", net[netnum].name,net[netnum].probability);
				 fprintf(fpout,"global_net_density %s %f\n", net[netnum].name,net[netnum].density);
				}
       }
    
 }

 for (netnum=0;netnum<num_nets;netnum++) {
    if (net[netnum].mark) {
       if (!is_clock[netnum])
			{
			  fprintf(fpout,"intercluster_net_probability %s %f\n", net[netnum].name,net[netnum].probability);
			  fprintf(fpout,"intercluster_net_density %s %f\n", net[netnum].name,net[netnum].density);
			}
    }
 }


 for (bnum=0;bnum<num_blocks;bnum++) {
    if ((block[bnum].type == LUT) || (block[bnum].type == LATCH) ||
        (block[bnum].type == LUT_AND_LATCH)) {
		
       fprintf(fpout,"subblock_probability %s ",block[bnum].name);
       // order: inputs clkinput dactivity output 
       for(i=1;i<lut_size+1;i++) {
          if (block[bnum].nets[i] != OPEN)
           fprintf(fpout,"%f ",net[block[bnum].nets[i]].probability);
	  else
           fprintf(fpout,"OPEN ");

       }
       if (block[bnum].nets[lut_size+1] != OPEN)
         fprintf(fpout,"%f ", net[block[bnum].nets[lut_size+1]].probability);
       else
	 fprintf(fpout,"OPEN ");

       fprintf(fpout,"%f ", block[bnum].probability);

       if (block[bnum].nets[lut_size+1] != OPEN)
         fprintf(fpout,"%f ", net[block[bnum].nets[lut_size+1]].probability);
       else
	 fprintf(fpout,"OPEN ");

       if (block[bnum].nets[0] != OPEN)
         fprintf(fpout,"%f\n", net[block[bnum].nets[0]].probability);
       else
	 fprintf(fpout,"OPEN\n");


       fprintf(fpout,"subblock_density %s ", block[bnum].name);
        //order: inputs clkinput dactivity output 

       for(i=1;i<lut_size+1;i++) {
         if (block[bnum].nets[i] == OPEN) {
              fprintf(fpout,"%f ",0.0);
         } else {
              fprintf(fpout,"%f ",net[block[bnum].nets[i]].density);
         }
       }
       if (block[bnum].nets[lut_size+1] == OPEN) {
          fprintf(fpout,"%f ",0.0);
       } else {
          fprintf(fpout,"%f ",net[block[bnum].nets[lut_size+1]].density);
       }   
       fprintf(fpout,"%f ",block[bnum].density);
       if (block[bnum].nets[0] == OPEN) {
         fprintf(fpout,"%f ",0.0);
       } else {
         fprintf(fpout,"%f ",net[block[bnum].nets[0]].density);
       }
       fprintf(fpout,"\n");
    } else if ((block[bnum].type == DSP) || (block[bnum].type == MEMORY) || (block[bnum].type == VEB)) {
		
       fprintf(fpout,"embeddedblock_probability %s ",block[bnum].name);
       for(i=0;i<block[bnum].num_nets;i++) {
          if (block[bnum].nets[i] != OPEN)
           fprintf(fpout,"%f ",net[block[bnum].nets[i]].probability);
	  else
           fprintf(fpout,"OPEN ");
       }
       fprintf(fpout,"\n");

       fprintf(fpout,"embeddedblock_density %s ", block[bnum].name);

       for(i=0;i<block[bnum].num_nets;i++) {
          if (block[bnum].nets[i] != OPEN)
           fprintf(fpout,"%f ",net[block[bnum].nets[i]].density);
	  else
           fprintf(fpout,"OPEN ");
       }
       fprintf(fpout,"\n");

    }
 }

 fclose (fpout);
}


void output_functions(char *out_fname)
{
   int bnum;
   FILE *fpout;

   if (out_fname[0] == '\0') {
       return;   /* do not output functions */
   }
   
   fpout = my_fopen (out_fname, "w", 0);

   for (bnum=0;bnum<num_blocks;bnum++) {
		/*     if ((block[bnum].type == LUT) 
			 || (block[bnum].type == LATCH) 
			 || (block[bnum].type == LUT_AND_LATCH)) */
		if ((block[bnum].type == LUT)
			 || (block[bnum].type == LUT_AND_LATCH))
		  {
			 fprintf(fpout,"subblock_function %s %s\n",block[bnum].name,block[bnum].function);
		  }
   }
  
   fclose(fpout);
}

void output_all_block()
{
	int iblk;

	for (iblk = 0;iblk < num_blocks; iblk ++)
	{
	/*
		printf("-----------------------------------------\n");
		printf("Block number: %d  \n", iblk);
		if (block[iblk].type == LUT)
			printf("Block type :	LUT \n");
		if (block[iblk].type == LATCH)
			printf("Block type :	LATCH \n");		
		if (block[iblk].type == OUTPAD )
			printf("Block type :	OUTPAD  \n");
		if (block[iblk].type == INPAD )
			printf("Block type :	INPAD  \n");
		if (block[iblk].type == GND )
			printf("Block type :	GND  \n");
		if (block[iblk].type == VCC )
			printf("Block type :	VCC  \n");
		if (block[iblk].type == LUT_AND_LATCH )
			printf("Block type :	LUT_AND_LATCH  \n");
		if (block[iblk].type == LUT_L )
			printf("Block type :	LUT_L  \n");
		if (block[iblk].type == FD )
			printf("Block type :	FD  \n");
		if (block[iblk].type == FDP )
			printf("Block type :	FDP  \n");
		if (block[iblk].type == FDC )
			printf("Block type :	FDC  \n");
		if (block[iblk].type == FDCE )
			printf("Block type :	FDCE  \n");
		if (block[iblk].type == FDE )
			printf("Block type :	FDE  \n");
		if (block[iblk].type == FDR )
			printf("Block type :	FDR  \n");
		if (block[iblk].type == XORCY )
			printf("Block type :	XORCY  \n");
		if (block[iblk].type == MUXCY )
			printf("Block type :	MUXCY  \n");
		if (block[iblk].type == MUXCY_L )
			printf("Block type :	MUXCY_L  \n");
		if (block[iblk].type == INV )
			printf("Block type :	INV  \n");
		if (block[iblk].type == MULT_AND )
			printf("Block type :	MULT_AND  \n");

		printf("use of FF = %d \n", block[iblk].use_ff);
		printf("use of inv ce = %d \n", block[iblk].use_inv_ce);
		printf("use of inv clk = %d \n", block[iblk].use_inv_clk);
		printf("use of inv sr = %d \n", block[iblk].use_inv_sr);		


		if (block[iblk].nets[FF_CE] == OPEN)
			printf("FF_CE = OPEN \n");
		else
			printf("FF_CE = %s \n", net[block[iblk].nets[FF_CE]].name);

		if (block[iblk].nets[B_CE] == OPEN)
			printf("B_CE = OPEN \n");
		else
			printf("B_CE = %s \n", net[block[iblk].nets[B_CE]].name);

		if (block[iblk].nets[B_Y] == OPEN)
			printf("B_Y = OPEN \n");
		else
			printf("B_Y = %s \n", net[block[iblk].nets[B_Y]].name);
			*/
		output_block(iblk, 4);
	}

}

void output_block(int bnum, int lut_size)
{
	int ipin;

	printf("******************************************************************** \n");
	printf("Block number : %d, block name : %s, number of net: %d \n", bnum, block[bnum].name, block[bnum].num_nets);

	if (block[bnum].type == LUT)
		printf("Block type :	LUT \n");
	if (block[bnum].type == LATCH)
		printf("Block type :	LATCH \n");	
	if (block[bnum].type == OUTPAD )
		printf("Block type :	OUTPAD  \n");
	if (block[bnum].type == INPAD )
		printf("Block type :	INPAD  \n");
	if (block[bnum].type == GND )
		printf("Block type :	GND  \n");
	if (block[bnum].type == VCC )
		printf("Block type :	VCC  \n");
	if (block[bnum].type == LUT_AND_LATCH )
		printf("Block type :	LUT_AND_LATCH  \n");
	if (block[bnum].type == LUT_L )
		printf("Block type :	LUT_L  \n");
	if (block[bnum].type == FD )
		printf("Block type :	FD  \n");
	if (block[bnum].type == FDP )
		printf("Block type :	FDP  \n");
	if (block[bnum].type == FDC )
		printf("Block type :	FDC  \n");
	if (block[bnum].type == FDCE )
		printf("Block type :	FDCE  \n");
	if (block[bnum].type == FDE )
		printf("Block type :	FDE  \n");
	if (block[bnum].type == FDR )
		printf("Block type :	FDR  \n");
	if (block[bnum].type == XORCY )
		printf("Block type :	XORCY  \n");
	if (block[bnum].type == MUXCY )
		printf("Block type :	MUXCY  \n");
	if (block[bnum].type == MUXCY_L )
		printf("Block type :	MUXCY_L  \n");
	if (block[bnum].type == INV )
		printf("Block type :	INV  \n");
	if (block[bnum].type == MULT_AND )
		printf("Block type :	MULT_AND  \n");
	if (block[bnum].type == MUXF )
		printf("Block type :	MUXF  \n");
	if (block[bnum].type == DSP)
		printf("Block type :	DSP  \n");
	if (block[bnum].type == DSPS)
		printf("Block type :	DSPS  \n");

	printf("use of FF = %d \n", block[bnum].use_ff);
	printf("use of mult_and = %d \n", block[bnum].use_mult_and);
	printf("use of muxcy = %d \n", block[bnum].use_muxcy);
	printf("use of xorcy = %d \n", block[bnum].use_xorcy);
	printf("use of muxf = %d \n", block[bnum].use_muxf);
	

	if (block[bnum].nets[LUT_D] == OPEN)
		printf("LUT_D = OPEN \n");
	else
		printf("LUT_D = %s \n", net[block[bnum].nets[LUT_D]].name);

	
	if (block[bnum].nets[LUT_DI] == OPEN)
		printf("LUT_DI = OPEN \n");
	else
		printf("LUT_DI = %s \n", net[block[bnum].nets[LUT_DI]].name);
		 
	if (block[bnum].nets[LUT_MC15] == OPEN)
		printf("LUT_MC15 = OPEN \n");
	else
		printf("LUT_MC15 = %s \n", net[block[bnum].nets[LUT_MC15]].name);
				
	if (block[bnum].nets[FF_D] == OPEN)
		printf("FF_D = OPEN \n");
	else
		printf("FF_D = %s \n", net[block[bnum].nets[FF_D]].name);
	
	if (block[bnum].nets[FF_Q] == OPEN)
		printf("FF_Q = OPEN \n");
	else
		printf("FF_Q = %s \n", net[block[bnum].nets[FF_Q]].name);
		
	if (block[bnum].nets[FF_CLK] == OPEN)
		printf("FF_CLK = OPEN \n");
	else
		printf("FF_CLK = %s \n", net[block[bnum].nets[FF_CLK]].name);

	if (block[bnum].nets[FF_CE] == OPEN)
		printf("FF_CE = OPEN \n");
	else
		printf("FF_CE = %s \n", net[block[bnum].nets[FF_CE]].name);

	if (block[bnum].nets[FF_SR] == OPEN)
		printf("FF_SR = OPEN \n");
	else
		printf("FF_SR = %s \n", net[block[bnum].nets[FF_SR]].name);
	
	if (block[bnum].nets[INV_IN] == OPEN)
		printf("INV_IN = OPEN \n");
	else
		printf("INV_IN = %s \n", net[block[bnum].nets[INV_IN]].name);

	if (block[bnum].nets[INV_O] == OPEN)
		printf("INV_O = OPEN \n");
	else
		printf("INV_O = %s \n", net[block[bnum].nets[INV_O]].name);

	if (block[bnum].nets[MUXCY_S] == OPEN)
		printf("MUXCY_S = OPEN \n");
	else
		printf("MUXCY_S = %s \n", net[block[bnum].nets[MUXCY_S]].name);
		
	if (block[bnum].nets[MUXCY_DI] == OPEN)
		printf("MUXCY_DI = OPEN \n");
	else
		printf("MUXCY_DI = %s \n", net[block[bnum].nets[MUXCY_DI]].name);

	if (block[bnum].nets[MUXCY_CI] == OPEN)
		printf("MUXCY_CI = OPEN \n");
	else
		printf("MUXCY_CI = %s \n", net[block[bnum].nets[MUXCY_CI]].name);

	if (block[bnum].nets[MUXCY_O] == OPEN)
		printf("MUXCY_O = OPEN \n");
	else
		printf("MUXCY_O = %s \n", net[block[bnum].nets[MUXCY_O]].name);

	if (block[bnum].nets[MUXF_S] == OPEN)
		printf("MUXF_S = OPEN \n");
	else
		printf("MUXF_S = %s \n", net[block[bnum].nets[MUXF_S]].name);
		
	if (block[bnum].nets[MUXF_I0] == OPEN)
		printf("MUXF_I0 = OPEN \n");
	else
		printf("MUXF_I0 = %s \n", net[block[bnum].nets[MUXF_I0]].name);

	if (block[bnum].nets[MUXF_I1] == OPEN)
		printf("MUXF_I1 = OPEN \n");
	else
		printf("MUXF_I1 = %s \n", net[block[bnum].nets[MUXF_I1]].name);

	if (block[bnum].nets[MUXF_O] == OPEN)
		printf("MUXF_O = OPEN \n");
	else
		printf("MUXF_O = %s \n", net[block[bnum].nets[MUXF_O]].name);
				
	if (block[bnum].nets[XORCY_LI] == OPEN)
		printf("XORCY_LI = OPEN \n");
	else
		printf("XORCY_LI = %s \n", net[block[bnum].nets[XORCY_LI]].name);

	if (block[bnum].nets[XORCY_CI] == OPEN)
		printf("XORCY_CI = OPEN \n");
	else
		printf("XORCY_CI = %s \n", net[block[bnum].nets[XORCY_CI]].name);

	if (block[bnum].nets[XORCY_O] == OPEN)
		printf("XORCY_O = OPEN \n");
	else
		printf("XORCY_O = %s \n", net[block[bnum].nets[XORCY_O]].name);

	if (block[bnum].nets[MULTAND_I0] == OPEN)
		printf("MULTAND_I0 = OPEN \n");
	else
		printf("MULTAND_I0 = %s \n", net[block[bnum].nets[MULTAND_I0]].name);

	if (block[bnum].nets[MULTAND_I1] == OPEN)
		printf("MULTAND_I1 = OPEN \n");
	else
		printf("MULTAND_I1 = %s \n", net[block[bnum].nets[MULTAND_I1]].name);

	if (block[bnum].nets[MULTAND_O] == OPEN)
		printf("MULTAND_O = OPEN \n");
	else
		printf("MULTAND_O = %s \n", net[block[bnum].nets[MULTAND_O]].name);

	if (block[bnum].nets[B_COUT] == OPEN)
		printf("B_COUT = OPEN \n");
	else
		printf("B_COUT = %s \n", net[block[bnum].nets[B_COUT]].name);

	if (block[bnum].nets[B_SHIFTOUT] == OPEN)
		printf("B_SHIFTOUT = OPEN \n");
	else
		printf("B_SHIFTOUT = %s \n", net[block[bnum].nets[B_SHIFTOUT]].name);

	if (block[bnum].nets[B_Y] == OPEN)
		printf("B_Y = OPEN \n");
	else
		printf("B_Y = %s \n", net[block[bnum].nets[B_Y]].name);

	if (block[bnum].nets[B_Q] == OPEN)
		printf("B_Q = OPEN \n");
	else
		printf("B_Q = %s \n", net[block[bnum].nets[B_Q]].name);

	if (block[bnum].nets[B_YB] == OPEN)
		printf("B_YB = OPEN \n");
	else
		printf("B_YB = %s \n", net[block[bnum].nets[B_YB]].name);

	if (block[bnum].nets[B_SOPOUT] == OPEN)
		printf("B_SOPOUT = OPEN \n");
	else
		printf("B_SOPOUT = %s \n", net[block[bnum].nets[B_SOPOUT]].name);

	if (block[bnum].nets[B_DIG] == OPEN)
		printf("B_DIG = OPEN \n");
	else
		printf("B_DIG = %s \n", net[block[bnum].nets[B_DIG]].name);

	if (block[bnum].nets[B_FX] == OPEN)
		printf("B_FX = OPEN \n");
	else
		printf("B_FX = %s \n", net[block[bnum].nets[B_FX]].name);

	if (block[bnum].nets[B_CLK] == OPEN)
		printf("B_CLK = OPEN \n");
	else
		printf("B_CLK = %s \n", net[block[bnum].nets[B_CLK]].name);

	if (block[bnum].nets[B_CIN] == OPEN)
		printf("B_CIN = OPEN \n");
	else
		printf("B_CIN = %s \n", net[block[bnum].nets[B_CIN]].name);

	if (block[bnum].nets[B_SHIFTIN] == OPEN)
		printf("B_SHIFTIN = OPEN \n");
	else
		printf("B_SHIFTIN = %s \n", net[block[bnum].nets[B_SHIFTIN]].name);

	if (block[bnum].nets[B_CE] == OPEN)
		printf("B_CE = OPEN \n");
	else
		printf("B_CE = %s \n", net[block[bnum].nets[B_CE]].name);

	if (block[bnum].nets[B_SR] == OPEN)
		printf("B_SR = OPEN \n");
	else
		printf("B_SR = %s \n", net[block[bnum].nets[B_SR]].name);

	if (block[bnum].nets[B_BY] == OPEN)
		printf("B_BY = OPEN \n");
	else
		printf("B_BY = %s \n", net[block[bnum].nets[B_BY]].name);

	if (block[bnum].nets[B_SOPIN] == OPEN)
		printf("B_SOPIN = OPEN \n");
	else
		printf("B_SOPIN = %s \n", net[block[bnum].nets[B_SOPIN]].name);

	if (block[bnum].nets[B_DY] == OPEN)
		printf("B_DY = OPEN \n");
	else
		printf("B_DY = %s \n", net[block[bnum].nets[B_DY]].name);

	if (block[bnum].nets[B_ALTDIG] == OPEN)
		printf("B_ALTDIG = OPEN \n");
	else
		printf("B_ALTDIG = %s \n", net[block[bnum].nets[B_ALTDIG]].name);

	if (block[bnum].nets[B_GND] == OPEN)
		printf("B_GND = OPEN \n");
	else
		printf("B_GND = %s \n", net[block[bnum].nets[B_GND]].name);

	if (block[bnum].nets[B_VCC] == OPEN)
		printf("B_VCC = OPEN \n");
	else
		printf("B_VCC = %s \n", net[block[bnum].nets[B_VCC]].name);

	if (block[bnum].nets[B_FXINA] == OPEN)
		printf("B_FXINA = OPEN \n");
	else
		printf("B_FXINA = %s \n", net[block[bnum].nets[B_FXINA]].name);

	if (block[bnum].nets[B_FXINB] == OPEN)
		printf("B_FXINB = OPEN \n");
	else
		printf("B_FXINB = %s \n", net[block[bnum].nets[B_FXINB]].name);	

	for (ipin = 0; ipin < lut_size; ipin ++)
	{
		if (block[bnum].nets[B_LUT_IN + ipin] == OPEN)
			printf("B_LUT_IN %d = OPEN \n", ipin);
		else
			printf("B_LUT_IN %d = %s \n", ipin, net[block[bnum].nets[B_LUT_IN + ipin]].name);
	}
	
}

static void print_pins_transparent (FILE *fpout, int bnum) {

	int ipin, column, netnum;

	fprintf(fpout,"pinlist: ");

	column = 10;  /* Next column I will write to. */

	for(ipin=0;ipin<block[bnum].num_nets;ipin++) {
		netnum = block[bnum].nets[ipin];
		print_net_name (netnum, &column, fpout);
	}

	fprintf(fpout,"\n");
}


static void print_basic_subblock (FILE *fpout, int bnum, int lut_size) {

	/* Prints out the subblock connectivity.  Used only when *
	* the -no_clustering option is selected -- prints out   *
	* basically redundant connection info for a LUT + FF    *
	* logic block.                                          */

	int inet, ipin, column;

	fprintf(fpout, "subblock: ");
	column = 11;
	print_string (block[bnum].name, &column, fpout);

	for (ipin=1;ipin<=lut_size;ipin++) {   /* Inputs first. */
		inet = block[bnum].nets[ipin];
		if (inet == OPEN)
			print_net_number (OPEN, &column, fpout);
		else
			print_net_number (ipin-1, &column, fpout);
	}

	print_net_number (lut_size, &column, fpout);   /* Output next */

	inet = block[bnum].nets[lut_size+1];
	if (inet == OPEN)
		print_net_number (OPEN, &column, fpout);
	else
		print_net_number (lut_size+1, &column, fpout);

	fprintf (fpout, "\n\n");
}

void print_statistic()
{
	int iblk;
	int numLUT, numMUXCY, numXORCY, numINV, numDSP,numMULT_AND, numLUT_LATCH, numFF, numMUXF;

	numLUT = 0;
	numFF = 0;
	numMUXCY = 0;
	numXORCY = 0; 
	numINV = 0;  
	numDSP = 0;
	numMULT_AND = 0;
	numLUT_LATCH = 0;
	numMUXF = 0;

	for (iblk = 0;iblk < num_blocks; iblk ++)
	{
		if (block[iblk].type == LUT 
			|| block[iblk].type == LUT_L)
			numLUT ++ ;

		if (block[iblk].type == FD 
			|| block[iblk].type == FDP
			|| block[iblk].type == FDS
			|| block[iblk].type == FDC
			|| block[iblk].type == FDCE
			|| block[iblk].type == FDE
			|| block[iblk].type == FDR
			|| block[iblk].type == FDCP
			|| block[iblk].type == LDC
			|| block[iblk].type == LATCH
			)
			numFF ++ ;

		if (block[iblk].type == LUT_AND_LATCH)		
			numLUT_LATCH ++  ;

		if (block[iblk].type == MUXCY
			|| block[iblk].type == MUXCY_L
			)
			numMUXCY ++  ;

		if (block[iblk].type == XORCY			
			)
			numXORCY ++  ;

		if (block[iblk].type == INV			
			)
			numINV ++  ;

		if (block[iblk].type == DSP
			|| block[iblk].type == DSPS
			)
			numDSP ++  ;

		if (block[iblk].type ==MULT_AND			
			)
			numMULT_AND ++  ;


		if (block[iblk].type == MUXF
			)
		numMUXF ++;
	}

	printf("numLUT = %d , numFF = %d, 	numMUXCY = %d, numXORCY = %d, numINV = %d, numDSP = %d, numMULT_AND = %d, numLUT_LATCH = %d, numMUXF = %d \n", 
		numLUT, numFF, 	numMUXCY, numXORCY, numINV, numDSP,  numMULT_AND , numLUT_LATCH, numMUXF );
					
	
	
}

