/*******************************************************************/
/*******************************************************************/
/**                                                               **/
/**  RFG_DISP                                                     **/
/**                                                               **/
/**  Version 6.03                                                 **/
/**                                                               **/
/*******************************************************************/
/*******************************************************************/

static char *ident_disp="@(#)(RFG) dispatch, version 6.03 (03/12/1993)";

/*******************************************************************/

#include "rfg_head.h"

#include <genlib.h>

#include <malloc.h>

/*******************************************************************/
/*  Global constants.                                              */
/*******************************************************************/

#define rfg_snc         16  /* Max size of cell's string name. */

/*******************************************************************/

#define rfg_wblock      16L /* Max number of word in one block. */

#define rfg_half_rules  3L

/*******************************************************************/

/* The following values are used to create the prefix crunch name.   */
/* The crunch name is constitued of 5 characters.                    */
/* Each charater represent a 5 bits value, so 25 bits are available. */

/* |       0      |       1      |       2      |       3      |       4      | */ /* characteres */
/* |24 23 22 21 20|19 18 17 16 15|14 13 12 11 10| 9  8  7  6  5| 4  3  2  1  0| */ /* bits        */
/* |              |              |              |              |              | */
/* | x  x  x|     (width-2)/2    |  (high-2)/2  | n  x ff id lp|hc we  i  s  m| */ /* parameters  */
/* |        |                    |              | _            |       w  t  s| */
/* |        |                    |              | b            |       e  u  b| */
/* |        |                    |              | u            |          c   | */
/* |        |                    |              | s            |          k   | */

#define rfg_deca_width (15-1)
#define rfg_mask_width 0xfe
#define rfg_deca_high  (10-1)
#define rfg_mask_high  0x3e
#define rfg_deca_bus   9
#define rfg_mask_bus   0x1
#define rfg_deca_ff    7
#define rfg_mask_ff    0x1
#define rfg_deca_id    6
#define rfg_mask_id    0x1
#define rfg_deca_lp    5
#define rfg_mask_lp    0x1
#define rfg_deca_hc    4
#define rfg_mask_hc    0x1
#define rfg_deca_we    3
#define rfg_mask_we    0x1
#define rfg_deca_iwe   2
#define rfg_mask_iwe   0x1
#define rfg_deca_st    1
#define rfg_mask_st    0x1
#define rfg_deca_msb   0
#define rfg_mask_msb   0x1

/*******************************************************************/

#define rfg_sba           (8+1)   /* Size max of a binary address. */
#define rfg_sbw           (64+1)  /* Size max of a binary word. */
#define rfg_sbd           (256+1) /* Size max of a binary decoded address. */

#define rfg_err_pattern   0L      /* Value of output when selection is missing. */

#define rfg_long_bits     32L     /* Number of bits in a long integer var. */

/*******************************************************************/

#ifdef rfg_crunch_name
/* [5 bits value to convert] [] */
static char rfg_crunch_tab[32][2]=
  {
  "0", "1", "2", "3", "4", "5", "6", "7",
  "8", "9", "a", "b", "c", "d", "e", "f",
  "g", "h", "i", "j", "k", "l", "m", "n",
  "o", "p", "q", "r", "s", "t", "u", "v"
  };
#endif

/***** Input cells. *****/

/* [rfg_inv_data_cell] [rfg_type_lin] [] */
static char rfg_cell_lin[2][2][rfg_snc]=
  {
    {"rfdi8_c", "rfdi16_c"},
    {"rfdi8n_c","rfdi16n_c"},
  };
/* [rfg_inv_data_cell] [rfg_type_lin] */
static long rfg_n_ref_lin[2][2]=
  {
    { 5,  8},
    { 4,  10},
  };
#define rfg_nbr_ref_lin 10
/* [rfg_inv_data_cell] [rfg_type_lin] [indice_ref] [] */
static char rfg_ref_lin[2][2][rfg_nbr_ref_lin][rfg_snc]=
  {
    {
      {"in_a_0", "in_a_1", "in_a_4", "in_a_8", "in_a_9", },
      {"in_a_0", "in_a_1", "in_a_2", "in_a_3", "in_a_4",
       "in_a_5", "in_a_6", "in_a_7", },
    },
    {
      {"in_a_3", "in_a_4", "in_a_6", "in_a_7", },
      {"in_a_0", "in_a_1", "in_a_2", "in_a_3", "in_a_4",
       "in_a_5", "in_a_6", "in_a_7", "in_a_8", "in_a_9", },
    },
  };

/***** Output cells. *****/

/* [rfg_bld_final] [rfg_type_lou] [n_bus] [] */
static char rfg_cell_bleeder[2][2][2][rfg_snc]=
  {
    {
      {"rfde1bs_c", "rfde2bs_c"},
      {"rfde1b_c" , "rfde2b_c" },
    },
    {
      {"rfde1bsf_c", "rfde2bsf_c"},
      {"rfde1bf_c" , "rfde2bf_c" },
    },
  };
/* [rfg_type_lou] [n_bus] */
static long rfg_n_ref_bleeder[2][2]=
  {
    {5, 10},
    {5, 10},
  };
#define rfg_nbr_ref_bleeder 10
/* [rfg_type_lou] [n_bus] [indice_ref] [] */
static char rfg_ref_bleeder[2][2][rfg_nbr_ref_bleeder][rfg_snc]=
  {
    {
      { /* rfde1bsf_c */
      "out_a_1", "out_a_4", "out_a_5", "out_a_6", "out_a_9",
      },
      { /* rfde2bsf_c */
      "out_a_1", "out_a_4", "out_a_5", "out_a_6", "out_a_9",
      "out_b_1", "out_b_4", "out_b_6", "out_b_8", "out_b_9",
      },
    },
    {
      { /* rfde1bf_c */
      "out_a_1", "out_a_4", "out_a_5", "out_a_6", "out_a_9",
      },
      { /* rfde2bf_c */
      "out_a_1", "out_a_4", "out_a_5", "out_a_6", "out_a_9",
      "out_b_1", "out_b_4", "out_b_5", "out_b_8", "out_b_9",
      },
    },
  };
/* [n_bus] [] */
static char rfg_cell_latch[2][rfg_snc]=
  {
  "rflo1b_c", "rflo2b_c"
  };
/* [n_bus] */
static long rfg_n_ref_latch[2]=
  {
  4, 8,
  };
#define rfg_nbr_ref_latch 8 
/* [n_bus] [indice_ref] [indice_ref] [] */
static char rfg_ref_latch[2][rfg_nbr_ref_latch][rfg_snc]=
  {
    { /* rflo1b_c */
    "out_a_1", "out_a_4", "out_a_5", "out_a_6",
    },
    { /* rflo2b_c */
    "out_a_1", "out_a_5", "out_a_6", "out_a_9",
    "out_b_1", "out_b_5", "out_b_6", "out_b_9",
    },
  };

/***** Decoder cells. *****/

/* [nand_size] [sym_y] [sym_x] */
static char rfg_sym_nand[4][2][2]=
  {
    {{NOSYM, SYM_X}, {SYM_Y, SYMXY}},
    {{NOSYM, SYM_X}, {SYM_Y, SYMXY}},
    {{NOSYM, SYM_X}, {NOSYM, SYM_X}},
    {{NOSYM, SYM_X}, {NOSYM, SYM_X}}
  };
/* [nand_size] [sym_y] [] */
static char rfg_cell_nand[4][2][rfg_snc]=
  {
    {"rfcna1_c",  "rfcna1_c"},
    {"rfcna2_c",  "rfcna2_c"},
    {"rfcna3s_c", "rfcna3d_c"},
    {"rfcna4s_c", "rfcna4d_c"}
  };

/*******************************************************************/
/* Global constantes and type for string.                          */
/*******************************************************************/

#define rfg_size_line_max 256     /* Maximun number of char in one line. */
#define rfg_max_value     16      /* Number of string for convert functions. */

typedef struct
  {
  char line[rfg_size_line_max];
  } rfg_string;

/*******************************************************************/
/* Global constantes, type and macros for connector list.          */
/*******************************************************************/

#define rfg_con_in     0x01L
#define rfg_con_out    0x02L
#define rfg_con_supply 0x04L
#define rfg_con_invert 0x08L
#define rfg_con_clock  0x10L

#define rfg_con_north 0L
#define rfg_con_south 1L
#define rfg_con_west  2L
#define rfg_con_east  3L

typedef struct rfg_connector
  {
  struct rfg_connector *next;
  char                *name;
  long                vector;      /* 0 : one bit connector */
                                   /* 1 : vectorized connector */
  long                start_index;
  long                end_index;
  long                type;
  long                side;
  char                format;      /* B : binary */
                                   /* X : hexadecimal */
  } rfg_connector_list;

#define RFG_FIRST_CON() (rfg_connector_ptr=rfg_connector_start)
#define RFG_TEST_CON()  (rfg_connector_ptr!=NULL)
#define RFG_NEXT_CON()  (rfg_connector_ptr=rfg_connector_ptr->next)

#define RFG_CON_NAME()        (rfg_connector_ptr->name)
#define RFG_CON_VECTOR()      (rfg_connector_ptr->vector)
#define RFG_CON_START_INDEX() (rfg_connector_ptr->start_index)
#define RFG_CON_END_INDEX()   (rfg_connector_ptr->end_index)
#define RFG_CON_TEST_INDEX()  (RFG_CON_END_INDEX()>=RFG_CON_START_INDEX())
#define RFG_CON_TYPE()        (rfg_connector_ptr->type)
#define RFG_CON_SIDE()        (rfg_connector_ptr->side)
#define RFG_CON_FORMAT()      (rfg_connector_ptr->format)

#define RFG_CON_RANGE()       (RFG_CON_START_INDEX()!=RFG_CON_END_INDEX())

/*******************************************************************/
/* Global variables.                                               */
/*******************************************************************/

static rfg_connector_list *rfg_connector_start=NULL;
static rfg_connector_list **rfg_connector_end;
static rfg_connector_list *rfg_connector_ptr;

static char *rfg_name_pref; /* prefix for all files names */

static long rfg_hslice;     /* var for height of 1 bit-slice */

static long rfg_nbr_block_p; /* Number of 16 registers blocks.       */
static long rfg_width_f;     /* Number of registers in last block.   */
static long rfg_nbr_block;   /* Total number -1 of registers blocks. */

static long rfg_nand_h; /* Number of entries for nand of high address decoder : */
                       /* -1 = no high address; */
                       /*  0 = nand 1;          */
                       /*  1 = nand 2;          */
                       /*  2 = nand 3;          */
                       /*  3 = nand 4.          */
static long rfg_nand_l; /* Number of entries for nand of low address decoder : */
                       /*  0 = nand 1; */
                       /*  1 = nand 2; */
                       /*  2 = nand 3; */
                       /*  3 = nand 4. */
static long rfg_addr_size; /* Size -1 of each address bus. */

static long rfg_type_lin, rfg_type_lou, rfg_bld_final, rfg_type_buf;

static long rfg_cell_alims; /* 0 no vertical alims added.               */
                           /* 1 vertical alims and ck_m must be added. */

static long rfg_num_slices_reg;
static long rfg_num_slices_dec;
static long rfg_num_slices;

static long rfg_inv_data_cell;
static long rfg_low_high_cell;
static long rfg_inv_we_cell;

/* vars for widths of blocks and columns */
static long rfg_w_lin,rfg_w_bsi,rfg_w_blr,rfg_w_blw,rfg_w_col_lin;
static long rfg_w_din,rfg_w_alr,rfg_w_alw,rfg_w_col_din;
static long rfg_w_col_mla;
static long rfg_w_dou,rfg_w_bdo,rfg_w_chr,rfg_w_chw,rfg_w_col_dou;
static long rfg_w_lou,rfg_w_bso,rfg_w_bhr,rfg_w_bhw,rfg_w_col_lou;

static long rfg_save_layout;

/*******************************************************************/
/* General purpose functions                                       */
/*******************************************************************/

/*******************************************************************/
/*                                                                 */
/*  MAX_2 ( val1 , val2 )                                          */
/*                                                                 */
/*******************************************************************/

static long rfg_max_2(val1, val2)
  long val1, val2;

{
if (val1>val2)
  return(val1);
else
  return(val2);
}

/*******************************************************************/
/*                                                                 */
/*  MAX_4 ( val1 , val2 , val3, val4 )                             */
/*                                                                 */
/*******************************************************************/

static long rfg_max_4(val1, val2, val3, val4)
  long val1, val2, val3, val4 ;

{
if (val1>val2)
  val2=val1;
if (val3>val4)
  val4=val3;
if (val2>val4)
  return(val2);
else
  return(val4);
}

/*******************************************************************/
/*                                                                 */
/*  INIT_VAR ( width, high, n_bus, flip_flop, inverse_data,        */
/*             low_power, write_enable, inverse_we, stuck, msb,    */
/*             block_type )                                        */
/*                                                                 */
/*******************************************************************/

static void rfg_init_var (width, high, n_bus, flip_flop, inverse_data, 
                   low_power, write_enable, inverse_we /*, stuck, msb*/ ,
                   block_type)

  long width, high, n_bus, flip_flop, inverse_data;
  long low_power, write_enable, inverse_we /*, stuck, msb*/ ;
  long block_type;

{
long i, w_tmp;

rfg_hslice=HEIGHT("rfdi_c");

rfg_nbr_block_p=width / rfg_wblock;

rfg_width_f=width % rfg_wblock;

rfg_nbr_block=rfg_nbr_block_p;
if(!rfg_width_f)
  rfg_nbr_block--;

if(width>128)
  rfg_nand_h=3L;
else
  if(width>64)
    rfg_nand_h=2L;
  else
    if(width>32)
      rfg_nand_h=1L;
    else
      if(width>16)
        rfg_nand_h=0L;
      else
        rfg_nand_h= -1L;

if(width>8L)
  rfg_nand_l=3L;
else
  if(width>4L)
    rfg_nand_l=2L;
  else
    if(width>2L)
      rfg_nand_l=1L;
    else
      rfg_nand_l=0L;

rfg_addr_size=rfg_nand_l+rfg_nand_h+1L;

if(width>8L*rfg_wblock)
  rfg_type_lin=1;
else
  rfg_type_lin=0;

if(width>rfg_wblock)
  rfg_type_lou=1;
else
  rfg_type_lou=0;

rfg_bld_final=(~flip_flop) & 1L;

rfg_type_buf=rfg_addr_size-5;

/*
if(width>4L*rfg_wblock)
  rfg_cell_alims=1L;
else
  rfg_cell_alims=0L;
*/
rfg_cell_alims=1L;

if(rfg_addr_size>1)
  i=1; /* Decoder take two slices. */
else
  i=0; /* Decoder take one slice. */

if(block_type==rfg_dec_sep)
  rfg_num_slices_reg=0L;
else
  rfg_num_slices_reg=high+2L;

if((block_type==rfg_reg_only) || (block_type==rfg_reg_sep))
  rfg_num_slices_dec=0L;
else
  rfg_num_slices_dec=1L+(1L+n_bus)*(1L+low_power+i)+2L+i;

rfg_num_slices=rfg_num_slices_reg+rfg_num_slices_dec;

/******************************************/
/* Calculate if reverse cells are needed. */
/******************************************/

if(width>rfg_wblock)
  rfg_inv_data_cell=inverse_data;
else
  rfg_inv_data_cell=inverse_data^1L;
if(flip_flop)
  rfg_inv_data_cell^=1L;

rfg_low_high_cell=inverse_data^rfg_inv_data_cell^1L;

if(write_enable)
  rfg_inv_we_cell=inverse_we;
else
  rfg_inv_we_cell=0L;

/************************************************/
/* For each block we calculate his width,       */
/* then for each column we calculate her width. */
/************************************************/

/***** Width of LIN block. *****/
rfg_w_lin=WIDTH(rfg_cell_lin[rfg_inv_data_cell][rfg_type_lin]);

/***** Width of BSI block. *****/
rfg_w_bsi=0L;

/***** Width of BLR block. *****/
rfg_w_blr=0L;

/***** Width of BLW block. *****/
rfg_w_blw=0L;

/********** Width of LIN column. **********/

if (block_type==rfg_reg_only)
  rfg_w_col_lin=rfg_w_lin;
else
  rfg_w_col_lin=rfg_max_4(rfg_w_lin, rfg_w_bsi, rfg_w_blr, rfg_w_blw);

/***** Width of DIN block. *****/
rfg_w_din=WIDTH("rfdi_c");

/***** Width of ALR block. *****/
rfg_w_alr=WIDTH("rfal4_c");

/***** Width of ALW block. *****/
rfg_w_alw=WIDTH("rfal4_c");
if (width<=8L)
  w_tmp=WIDTH("rfaw8_c");
else
  w_tmp=WIDTH("rfaw16_c");
rfg_w_alw=rfg_max_2(rfg_w_alw, w_tmp);

/********** Width of DIN column. **********/

if (block_type==rfg_reg_only)
  rfg_w_col_din=rfg_w_din;
else
  rfg_w_col_din=rfg_max_4(rfg_w_din, 0L, rfg_w_alr, rfg_w_alw);

/********** Width of MLA column. **********/
if (n_bus)
  rfg_w_col_mla=WIDTH("rfl2b_c");
else
  rfg_w_col_mla=WIDTH("rfl1b_c");

/***** Width of DOU block. *****/
if(width>rfg_wblock)
  {
  if(n_bus)
    rfg_w_dou=WIDTH("rfdo2b_c");
  else
    rfg_w_dou=WIDTH("rfdo1b_c");
  }
else
  rfg_w_dou=0L;

/***** Width of BDO block. *****/
if(rfg_nbr_block)
  rfg_w_bdo=WIDTH("rfbdo_c");
else
  rfg_w_bdo=0L;

/***** Width of CHR block. *****/
if(width>rfg_wblock)
  rfg_w_chr=rfg_max_2(WIDTH("rfahb4_c")+WIDTH("rfcna4d_c"),WIDTH("rfchr_c"));
else
  rfg_w_chr=0L;

/***** Width of CHW block. *****/
if(width>rfg_wblock)
  rfg_w_chw=rfg_max_2(WIDTH("rfahb4_c")+WIDTH("rfcna4d_c"),WIDTH("rfchw16_c"));
else
  rfg_w_chw=0L;

/********** Width of DOU column. **********/

if (block_type==rfg_reg_only)
  rfg_w_col_dou=rfg_w_dou;
else
  rfg_w_col_dou=rfg_max_4(rfg_w_dou, rfg_w_bdo, rfg_w_chr, rfg_w_chw);

/***** Width of LOU block. *****/
rfg_w_lou=WIDTH(rfg_cell_bleeder[rfg_bld_final][rfg_type_lou][n_bus]);
if(flip_flop)
  rfg_w_lou+=WIDTH(rfg_cell_latch[n_bus]);

/***** Width of BSO block. *****/
rfg_w_bso=0L;

/***** Width of BHR block. *****/
rfg_w_bhr=0L;

/***** Width of BHW block. *****/
rfg_w_bhw=0L;

/********** Width of LOU column. **********/

if (block_type==rfg_reg_only)
  rfg_w_col_lou=rfg_w_lou;
else
  rfg_w_col_lou=rfg_max_4(rfg_w_lou, rfg_w_bso, rfg_w_bhr, rfg_w_bhw);
}

/*******************************************************************/
/*                                                                 */
/*  ADD_CON ( name, vector, start_index, end_index, type, side,    */
/*            format )                                             */
/*                                                                 */
/*******************************************************************/

static void rfg_add_con (name, vector, start_index, end_index, type, side, format)

  char *name;
  long  vector, start_index, end_index, type, side;
  char  format;

{
rfg_connector_list *new_con;

/***** Allocate a connector. *****/
if((new_con=(rfg_connector_list *) malloc(sizeof(rfg_connector_list)))==NULL)
  { (void) fprintf(stderr, "Error : out of memory during connector allocation !!!\n");
    EXIT(1); }

/***** Insert connector at the end of list. *****/
if(rfg_connector_start==NULL)
  rfg_connector_start=new_con;
*rfg_connector_end=new_con;
rfg_connector_end=&(new_con->next);

/***** Inititialize connector values. *****/
new_con->next=NULL;
new_con->name=name;
new_con->vector=vector;
new_con->start_index=start_index;
new_con->end_index=end_index;
new_con->type=type;
new_con->side=side;
new_con->format=format;
}

/*******************************************************************/
/*                                                                 */
/*  INIT_CON_LIST ( width, high, n_bus, flip_flop, inverse_data,   */
/*                  low_power, write_enable, inverse_we, stuck,    */
/*                  msb, block_type )                              */
/*                                                                 */
/*******************************************************************/

static void rfg_init_con_list (width, high, n_bus, flip_flop, inverse_data,
                        /*low_power,*/ write_enable, inverse_we /*, stuck*/ ,
                        msb, block_type)

  long width, high, n_bus, flip_flop, inverse_data;
  long /*low_power,*/ write_enable, inverse_we /*, stuck*/ ;
  long msb, block_type;


{
long i;

rfg_connector_end=&rfg_connector_start;

if((block_type==rfg_dec_sep) || (block_type==rfg_bank))
  {
  if(msb)
    rfg_add_con("ad_r_a", 1L, 0L, rfg_addr_size, rfg_con_in, rfg_con_north, 'X');
  else
    rfg_add_con("ad_r_a", 1L, rfg_addr_size, 0L, rfg_con_in, rfg_con_north, 'X');
  if(n_bus)
    if(msb)
      rfg_add_con("ad_r_b", 1L, 0L, rfg_addr_size, rfg_con_in, rfg_con_north, 'X');
    else
      rfg_add_con("ad_r_b", 1L, rfg_addr_size, 0L, rfg_con_in, rfg_con_north, 'X');
  if(write_enable)
    rfg_add_con("we", 0L, 0L, 0L,
      rfg_con_in|(inverse_we ? rfg_con_invert : 0L), rfg_con_north, 'B');
  if(msb)
    rfg_add_con("ad_w", 1L, 0L, rfg_addr_size, rfg_con_in, rfg_con_north, 'X');
  else
    rfg_add_con("ad_w", 1L, rfg_addr_size, 0L, rfg_con_in, rfg_con_north, 'X');
  }

if(block_type==rfg_dec_sep)
  {
  rfg_add_con("r_a", 1L, 0L, width-1L, rfg_con_out|rfg_con_invert, rfg_con_south, 'B');
  if(n_bus)
    rfg_add_con("r_b", 1L, 0L, width-1L, rfg_con_out|rfg_con_invert, rfg_con_south, 'B');
  if(rfg_nbr_block)
    {
    rfg_add_con("s_a", 1L, 0L, rfg_nbr_block, rfg_con_out|rfg_con_invert, rfg_con_south, 'B');
    if(n_bus)
      rfg_add_con("s_b", 1L, 0L, rfg_nbr_block, rfg_con_out|rfg_con_invert, rfg_con_south, 'B');
    }
  rfg_add_con("w", 1L, 0L, width-1L, rfg_con_out|rfg_con_invert, rfg_con_south, 'B');
  if(flip_flop)
    {
    rfg_add_con("w_r_a", 0L, 0L, 0L, rfg_con_out|rfg_con_invert, rfg_con_south, 'B');
    if(n_bus)
      rfg_add_con("w_r_b", 0L, 0L, 0L, rfg_con_out|rfg_con_invert, rfg_con_south, 'B');
    }
  }

if((block_type==rfg_reg_only) || (block_type==rfg_reg_sep) || (block_type==rfg_bank))
  {
  if(msb)
    rfg_add_con("in_a", 1L, 0L, high-1L,
      rfg_con_in|(inverse_data ? rfg_con_invert : 0L), rfg_con_west, 'X');
  else
    rfg_add_con("in_a", 1L, high-1L, 0L,
      rfg_con_in|(inverse_data ? rfg_con_invert : 0L), rfg_con_west, 'X');
  if(msb)
    rfg_add_con("out_a", 1L, 0L, high-1L, rfg_con_out, rfg_con_east, 'X');
  else
    rfg_add_con("out_a", 1L, high-1L, 0L, rfg_con_out, rfg_con_east, 'X');
  if(n_bus)
    if(msb)
      rfg_add_con("out_b", 1L, 0L, high-1L, rfg_con_out, rfg_con_east, 'X');
    else
      rfg_add_con("out_b", 1L, high-1L, 0L, rfg_con_out, rfg_con_east, 'X');
  }

if((block_type==rfg_dec_sep) || (block_type==rfg_bank))
  {
  rfg_add_con("ck_m", 0L, 0L, 0L, rfg_con_in|rfg_con_clock, rfg_con_north, 'B');
  }

if((block_type==rfg_reg_only) || (block_type==rfg_reg_sep))
  {
  rfg_add_con("r_a", 1L, 0L, width-1L, rfg_con_in|rfg_con_invert, rfg_con_north, 'B');
  if(n_bus)
    rfg_add_con("r_b", 1L, 0L, width-1L, rfg_con_in|rfg_con_invert, rfg_con_north, 'B');
  if(rfg_nbr_block)
    {
    rfg_add_con("s_a", 1L, 0L, rfg_nbr_block, rfg_con_in|rfg_con_invert, rfg_con_north, 'B');
    if(n_bus)
      rfg_add_con("s_b", 1L, 0L, rfg_nbr_block, rfg_con_in|rfg_con_invert, rfg_con_north, 'B');
    }
  rfg_add_con("w", 1L, 0L, width-1L, rfg_con_in|rfg_con_invert, rfg_con_north, 'B');
  if(flip_flop)
    {
    rfg_add_con("w_r_a", 0L, 0L, 0L, rfg_con_in|rfg_con_invert, rfg_con_north, 'B');
    if(n_bus)
      rfg_add_con("w_r_b", 0L, 0L, 0L, rfg_con_in|rfg_con_invert, rfg_con_north, 'B');
    }
  }

if(rfg_cell_alims)
  {
  rfg_add_con("vdd", 0L, 0L, 0L, rfg_con_in | rfg_con_supply, rfg_con_north, 'B');
  rfg_add_con("vss", 0L, 0L, 0L, rfg_con_in | rfg_con_supply, rfg_con_south, 'B');
  }
else
  {
  for(i=0; i<=rfg_num_slices ; i++)
    {
    if(i&1)
      rfg_add_con(NAME("vdd%ld", i), 0L, 0L, 0L, rfg_con_in | rfg_con_supply,
        rfg_con_north, 'B');
    else
      rfg_add_con(NAME("vss%ld", i), 0L, 0L, 0L, rfg_con_in | rfg_con_supply,
        rfg_con_south, 'B');
    }
  }
}

/*******************************************************************/
/* Include view generators.                                        */
/*******************************************************************/

#include "rfg_layo.c"
#include "rfg_icon.c"
#include "rfg_vhdl.c"
#include "rfg_patt.c"
#include "rfg_data.c"
#include "rfg_netl.c"

/*******************************************************************/
/*******************************************************************/
/**                                                               **/
/**  RFG ( width, high, n_bus, flip_flop, inverse_data,           **/
/**        low_power, write_enable, inverse_we, stuck,            **/
/**        hard_connectors, msb, block_type, name_blocks,         **/
/**        layout, outline, vhdl, pat, data, netlist,             **/
/**        icon )                                                 **/
/**                                                               **/
/*******************************************************************/
/*******************************************************************/

char *rfg (width, high, n_bus, flip_flop, inverse_data,
           low_power, write_enable, inverse_we, stuck,
           hard_connectors, msb, block_type, name_blocks,
           layout, outline, vhdl, pat, data, netlist, 
           icon)

                       /* Function and possible values for following vars : */

  long width;          /* Number of registers (2<=width<=256). */
                       /* Value must be even.                  */
  long high;           /* Number of bits in register words (2<=high<=64). */
                       /* Value must be even.                             */
  long n_bus;          /* Number of read bus : 0 = 1 read bus; */
                       /*                      1 = 2 read bus. */
  long flip_flop;      /* 0 = level sensitive latch;    */
                       /* 1 = edge-triggered flip-flop. */
  long inverse_data;   /* 0 = data out has same polarity than data in;   */
                       /* 1 = data out polarity is reverse than data in. */
  long low_power;      /* 0 = high consumption option; */
                       /* 1 = low consumption option.  */
  long write_enable;   /* 0 = no write enable signal; */
                       /* 1 = write enable signal.    */
  long inverse_we;     /* 0 = write enable active high; */
                       /* 1 = write enable active low.  */
  long stuck;          /* 0 = register at address 0 is normal;                */
                       /* 1 = register at address 0 is stuck to a null value. */
  long hard_connectors;/* 0 = datapath connectors are multi-access; */
                       /* 1 = all conectors are hard (one-access).  */
  long msb;            /* 0 = index 0 is gived to the less significant bit of each bus; */
                       /* 1 = index 0 is gived to the most significant bit of each bus. */

  long block_type;     /* 0 = generate an optimised registers block        */
                       /*     (uncompatible with generated decoder block), */
                       /* 1 = generate a registers block                   */
                       /*     (compatible with generated decoder block),   */
                       /* 2 = generate a decoder block,                    */
                       /* 3 = generate a complet registers bank.           */

  char *name_blocks;   /* If = NULL : a name must be generate be the function to prefix blocks, */
                       /* else take the indicate name to prefix blocks.                         */
  
  long layout;         /* !0 = generate a layout view block files. */
  long outline;        /* !0 = generate a outline view block file. */
  long vhdl;           /* !0 = generate a vhdl view block file. */
  long pat;            /* !0 = generate a pat view block file. */
  long data;           /* !0 = generate a data sheet file. */
  long netlist;        /* !0 = generate a connectors netlist. */
  long icon;           /* !0 = generate a icon view block file. */

{
/* [block_type] [] */
static char b_type_tab[4][3]=
  {
  "ro", "rs", "ds", "ba"
  };

DEF_PHFIG("tmp"); /* this is only to avoid an mkb error */

/*******************************************************************/
/* Verify all parameters.                                          */
/*******************************************************************/

if(width<rfg_WIDTH_MIN)
  { (void) fprintf(stderr, "Error : number of registers must be greater or equal to 2 !!!\n");
    EXIT(1); }
if(width>rfg_WIDTH_MAX)
  { (void) fprintf(stderr, "Error : number of registers must be lower or equal to 256 !!!\n");
    EXIT(1); }
if(width&1L)
  { (void) fprintf(stderr, "Error : number of registers must be even !!!\n");
    EXIT(1); }

if(high<rfg_HIGH_MIN)
  { (void) fprintf(stderr, "Error : number of bits in register must be greater or equal to 2 !!!\n");
    EXIT(1); }
if(high>rfg_HIGH_MAX)
  { (void) fprintf(stderr, "Error : number of bits in register must be lower or equal to 64 !!!\n");
    EXIT(1); }
if(high&1L)
  { (void) fprintf(stderr, "Error : number of bits in register must be even !!!\n");
    EXIT(1); }

if((n_bus|1L)!=1L)
  { (void) fprintf(stderr, "Error : number of read bus must be 1 or 2 (0 or 1 for \"n_bus\") !!!\n");
    EXIT(1); }

if((flip_flop|1L)!=1L)
  { (void) fprintf(stderr, "Error : illegal value for \"flip_flop\", must be 0 or 1 !!!\n");
    EXIT(1); }

if((inverse_data|1L)!=1L)
  { (void) fprintf(stderr, "Error : illegal value for \"inverse_data\", must be 0 or 1 !!!\n");
    EXIT(1); }

if((low_power|1L)!=1L)
  { (void) fprintf(stderr, "Error : illegal value for \"low_power\", must be 0 or 1 !!!\n");
    EXIT(1); }
if(width<=rfg_wblock)
  low_power=0L;

if((write_enable|1L)!=1L)
  { (void) fprintf(stderr, "Error : illegal value for \"write_enable\", must be 0 or 1 !!!\n");
    EXIT(1); }
if((inverse_we|1L)!=1L)
  { (void) fprintf(stderr, "Error : illegal value for \"inverse_we\", must be 0 or 1 !!!\n");
    EXIT(1); }
inverse_we&=write_enable; /* if no write_enable : inverse_we = 0. */

if((stuck|1L)!=1L)
  { (void) fprintf(stderr, "Error : illegal value for \"stuck\", must be 0 or 1 !!!\n");
    EXIT(1); }

#ifdef rfg_floating_con
if((hard_connectors|1L)!=1L)
  { (void) fprintf(stderr, "Error : illegal value for \"hard_connectors\", must be 0 or 1 !!!\n");
    EXIT(1); }
#else
/* only hard connectors could be used */
if(hard_connectors==0L)
  { (void) fprintf(stderr, "Error : illegal value for \"hard_connectors\",\n  must be 1 in this reduce version of generator !!!\n");
    EXIT(1); }
#endif

if((msb|1L)!=1L)
  { (void) fprintf(stderr, "Error : illegal value for \"msb\", must be 0 or 1 !!!\n");
    EXIT(1); }

if((block_type|3L)!=3L)
  { (void) fprintf(stderr, "Error : illegal value for \"block_type\", must be 0, 1, 2 or 3 !!!\n");
    EXIT(1); }

#ifdef rfg_crunch_name
if(STRLEN(name_blocks)>rfg_pref_length)
  { (void) fprintf(stderr, "Error : length of \"name_prefix\" must be lower or equal to %ld !!!\n", rfg_pref_length);
    EXIT(1); }
#endif

if(!layout && !outline && !vhdl && !pat && !data && !netlist && !icon)
  { (void) fprintf(stderr, "Error : no view selected !!!\n");
    EXIT(1); }

if(layout && outline)
  { (void) fprintf(stderr, "Error : you cannot generate a layout and a physical_box view at same time !!!\n");
    EXIT(1); }

/*******************************************************************/
/* Calculate a prefix for resulting blocks.                        */
/*******************************************************************/

if((name_blocks==NULL) || (STRLEN(name_blocks)==0))
  {

#ifdef rfg_crunch_name
  long i;

  /* The prefix name is composed by a 2 characters block type identificator, */
  /* following by the crunch name. */
  i=((width-2L)     <<rfg_deca_width)+
    ((high-2L)      <<rfg_deca_high)+
    (n_bus          <<rfg_deca_bus)+
    (flip_flop      <<rfg_deca_ff)+
    (inverse_data   <<rfg_deca_id)+
    (low_power      <<rfg_deca_lp)+
    (write_enable   <<rfg_deca_we)+
    (inverse_we     <<rfg_deca_iwe)+
    (stuck          <<rfg_deca_st)+
    (hard_connectors<<rfg_deca_hc)+
    (msb            <<rfg_deca_msb);
  rfg_name_pref=NAME("%s%s%s%s%s%s",
    b_type_tab[block_type],
    rfg_crunch_tab[(i>>20)&0x1f],
    rfg_crunch_tab[(i>>15)&0x1f],
    rfg_crunch_tab[(i>>10)&0x1f],
    rfg_crunch_tab[(i>> 5)&0x1f],
    rfg_crunch_tab[(i    )&0x1f]);
#else
  rfg_name_pref=NAME("%s%ldx%ldx%ld%s%s%s%s%s%s%s",
    b_type_tab[block_type], high, width, n_bus+1,
    flip_flop ?                  "f"  : ""  ,
    inverse_data ?               "i"  : ""  ,
    low_power ?                  "l"  : ""  ,
    write_enable ? (inverse_we ? "wl" : "wh") : "",
    stuck  ?                     "s"  : ""  ,
    hard_connectors ?            ""   : "v" ,
    msb ?                        "m"  : ""  );
#endif

  }
else
  rfg_name_pref=name_blocks;

/*******************************************************************/
/* Call view generators.                                           */
/*******************************************************************/

/***** Initialise global vars *****/
rfg_init_var (width, high, n_bus, flip_flop, inverse_data,
  low_power, write_enable, inverse_we /*, stuck, msb*/ ,
  block_type);

/***** Create list of connectors *****/
if (vhdl || pat || data || netlist || icon)
  rfg_init_con_list(width, high, n_bus, flip_flop, inverse_data,
    /*low_power,*/ write_enable, inverse_we /*, stuck*/ , msb,
    block_type);

rfg_save_layout=layout;

if (layout || outline)
  rfg_layout (width, high, n_bus, flip_flop /*, inverse_data*/ ,
    low_power, write_enable, inverse_we, stuck,
    hard_connectors, msb, block_type);

if (icon)
  rfg_icon ( /*width, high, n_bus,*/ flip_flop /*, inverse_data,
    low_power, write_enable, inverse_we, stuck, msb, block_type*/ );

if (vhdl)
  rfg_vhdl (width, high, n_bus, flip_flop /*, inverse_data*/ ,
    low_power, write_enable, inverse_we, stuck, msb, block_type);

if (pat)
  rfg_pat (width, high, n_bus, flip_flop, inverse_data,
    low_power, write_enable, inverse_we, stuck /*, msb*/ , block_type);

if (data)
  rfg_data (width, high, n_bus, flip_flop, inverse_data,
    low_power, write_enable, inverse_we, stuck, 
    hard_connectors, msb, block_type);

if (outline)
  {
  OUTLINE ();
  SAVE_PHFIG ();
  }

if (netlist)
  rfg_netlist ();

return(rfg_name_pref);
}

/*******************************************************************/
