/*******************************************************************/
/*******************************************************************/
/**                                                               **/
/**  RFG_LAYO                                                     **/
/**                                                               **/
/**  Version 6.03                                                 **/
/**                                                               **/
/*******************************************************************/
/*******************************************************************/

/* "#define rfg_floating_con" must be present if floating      */
/* connector are to be used, if only hard connector are wanted */
/* place it in comment.                                        */

/*
#define rfg_floating_con    
*/

/*
#define rfg_save_blocks
*/

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

#ifdef rfg_floating_con    
  static char *ident_layo="@(#)(RFG) layout view generation (hard and multi-access connectors), version 6.03 (30/09/1993)";
#else
  static char *ident_layo="@(#)(RFG) layout view generation (hard connectors), version 6.03 (30/09/1993)";
#endif

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

#define rfg_width_min_alu1  1L  /* Technological constant. */
#define rfg_width_min_alu2  2L  /* Technological constant. */
#define rfg_width_min_nwell 4L  /* Technological constant. */

#define rfg_width_vss       8L  /* Width of vss track. */
#define rfg_width_vdd       6L  /* Width of vdd track. */

#define rfg_width_nwell    26L  /* Normal width of nwell in a bit-slice */

#define rfg_nbr_tracks      10  /* Number of alu2 track in a bit-slice. */

#define rfg_nbr_slice_buf   2   /* Number of bit-slice used by buffer.          */
#define rfg_nbr_slice_dec   3   /* Number max of bit-slice used by one decoder. */
#define rfg_nbr_read_bus    2   /* Number max of read decoder.                  */

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

/* [sym_x] */
static char rfg_symx[2]=
  {
  NOSYM, SYM_X
  };

/* [sym_y] */
static char rfg_symy[2]=
  {
  NOSYM, SYM_Y
  };

/* [sym_y] [sym_x] */
static char rfg_symyx[2][2]=
  {
    {NOSYM, SYM_X},
    {SYM_Y, SYMXY},
  };

/* [n_bus] [] */
static char rfg_bus_name[2][2]=
  {
  "a","b"
  };

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

/***** width min of nwell for each bit slice *****/

static long rfg_nwell_reg;
static long rfg_nwell_buf[rfg_nbr_slice_buf];
static long rfg_nwell_int;
static long rfg_nwell_dec_r[rfg_nbr_read_bus][rfg_nbr_slice_dec];
static long rfg_nwell_dec_w[rfg_nbr_slice_dec];

/*******************************************************************/
/* Functions and procedure used be the layout generator.           */
/*******************************************************************/

/*******************************************************************/
/*                                                                 */
/*  HARDED_FLOAT ( ins , ref , con , side )                        */
/*                                                                 */
/*******************************************************************/

static void rfg_HARDED_FLOAT(ins, ref, con, side)
  char *ins, *ref, *con;
  char side;

{
/* Convert a floating connector reference in a hard connector. */
PLACE_VIA_REF(ins, ref, CONT_VIA);
PLACE_CON_REF(ins, ref, con, ALU2, rfg_width_min_alu2, side);
}

#ifdef rfg_floating_con
/*******************************************************************/
/*                                                                 */
/*  COPY_FLOAT ( ins , ref , new , side )                          */
/*                                                                 */
/*******************************************************************/

static void rfg_COPY_FLOAT(ins, ref, new, side)
  char *ins, *ref, *new;
  char side;

{
/* Copy up a floating connector reference and place a TALU2 mask */
/* between the reference and the specify side of AB.             */
COPY_UP_REF(ref, ins, new);
PLACE_SEG_REF(ins, ref, TALU2, rfg_width_min_alu2, side);
}
#endif

/*******************************************************************/
/*                                                                 */
/*  MIN_NWELL ( vdd_down , slice_index , tab_y , ref_y )           */
/*                                                                 */
/*******************************************************************/

static long rfg_min_nwell(vdd_down, slice_index, tab_y, ref_y)
  long vdd_down;
  long slice_index; /* index of slice in the block.  */
  long tab_y;       /* previous value of y found.    */
  long ref_y;       /* y position of "fc[i]" in cell. */

{
/* This function is used to calculate the size of nwell masks */
/* who will be placed on each bit-slice.                      */

/*
printf("rfg_min_nwell(%d, %d, %d, %d)\n", vdd_down, slice_index, tab_y, ref_y);
*/

ref_y-=rfg_hslice*slice_index;
if(!vdd_down)
  ref_y=rfg_hslice-ref_y;
if(tab_y>ref_y)
  {
  return(ref_y);
  }
else
  {
  return(tab_y);
  }
}

/*******************************************************************/
/*                                                                 */
/*  PROG_INPUT ( inst_name , vdd_down , number , nand_size )       */
/*                                                                 */
/*******************************************************************/

static void rfg_prog_input(inst_name, vdd_down, number, nand_size)
  char *inst_name;
  long  vdd_down, number, nand_size;

{
/* This procedure place VIAs on REF_REF of inputs nand cells */
/* so the nand will decoded the number specified.            */

/* [number_to_convert] [indice_bit] */
static long code_tab[16][4]=
  {
    {0, 2, 4, 6},
    {1, 2, 4, 6},
    {0, 3, 4, 6},
    {1, 3, 4, 6},
    {0, 2, 5, 6},
    {1, 2, 5, 6},
    {0, 3, 5, 6},
    {1, 3, 5, 6},
    {0, 2, 4, 7},
    {1, 2, 4, 7},
    {0, 3, 4, 7},
    {1, 3, 4, 7},
    {0, 2, 5, 7},
    {1, 2, 5, 7},
    {0, 3, 5, 7},
    {1, 3, 5, 7}
  };
long i;
char *name_ref;

for(i=0L;i<=nand_size;i++)
  {
  if(vdd_down)
    name_ref=NAME("j[%d]", code_tab[number][i]);
  else
    name_ref=NAME("i[%d]", code_tab[number][i]);
  PLACE_VIA_REF(inst_name, name_ref, CONT_VIA);
  }
}

/*******************************************************************/
/* Each of the following procedure create one or more blocks       */
/* needed by the generator.                                        */
/*******************************************************************/

/*********************************************************************/
/*  BLW  * ALW_P *  CLW_P  * CHW_P * ALW_F *  CLW_F  * CHW_F *  BHW  */ /* block name   */
/*   50  *   52  *    54   *   56  *   53  *    55   *   57  *   58  */ /* block indice */
/*********************************************************************/
/* BLR_B * ALR_B * CLR_B_P * CHR_B * ALR_B * CLR_B_F * CHR_B * BHR_B */
/*   40  *   42  *    44   *   46  *   42  *    45   *   46  *   48  */
/*********************************************************************/
/* BLR_A * ALR_A * CLR_A_P * CHR_A * ALR_A * CLR_A_F * CHR_A * BHR_A */
/*   30  *   32  *    34   *   36  *   32  *    35   *   36  *   38  */
/*********************************************************************/
/*  BSI  *       *  BSL_P  *  BDO  *       *  BSL_F  *  BDO  *  BSO  */
/*   20  *       *    24   *   26  *       *    25   *   26  *   28  */
/*********************************************************************/
/*  LIN  *  DIN  *  MLA_P  *  DOU  *  DIN  *  MLA_F  *  DOU  *  LOU  */
/*   10  *   12  * 13 | 14 *   16  *   12  *    15   *   16  *   18  */
/*********************************************************************/

/*******************************************************************/
/*                                                                 */
/*  LIN ( high, inverse_data, type_lin, w_block, w_column )        */
/*                                                                 */
/*******************************************************************/

static void rfg_lin(high, inverse_data, type_lin, w_block, w_column)
  long high, inverse_data, type_lin, w_block, w_column;

{
long i, j, y_place, n_ref;
char *name_cell;

DEF_PHFIG(NAME("%s10", rfg_name_pref));
y_place=0L;

for (i=0L;i<high;i++)
  {
  PLACE(rfg_cell_lin[inverse_data][type_lin],
    NAME("lin[%d]", high-1-i),rfg_symy[i&1], 0L, y_place);
  y_place+=rfg_hslice;
  }
rfg_nwell_reg=rfg_min_nwell(0L, 0L, rfg_nwell_reg, GET_REF_Y(NAME("lin[%d]", high-1), "fc[0]"));

DEF_AB(0L, 0L, w_column-w_block, 2L*rfg_hslice);

n_ref=rfg_n_ref_lin[inverse_data][type_lin];
for(i=0;i<high;i++)
  {
  name_cell=NAME("lin[%d]", i);
  for(j=0L;j<n_ref;j++)
    COPY_UP_REF(rfg_ref_lin[inverse_data][type_lin][j], name_cell,
      NAME("%s[%d]", rfg_ref_lin[inverse_data][type_lin][j], i));
  COPY_UP_CON(0L, "o", name_cell, NAME("o[%d]", i));
  }

#ifdef rfg_save_blocks
if(rfg_save_layout)
  SAVE_PHFIG ();
#endif

}

/*******************************************************************/
/*                                                                 */
/*  DIN ( high, w_block, w_column )                                */
/*                                                                 */
/*******************************************************************/

static void rfg_din(high, w_block, w_column)
  long high, w_block, w_column;

{
long y_place, i;

DEF_PHFIG(NAME("%s12", rfg_name_pref));
y_place=0L;

for (i=0L;i<high;i++)
  {
  PLACE("rfdi_c", NAME("din[%d]", high-1-i), rfg_symy[i&1], 0L, y_place);
  y_place+=rfg_hslice;
  }
rfg_nwell_reg=rfg_min_nwell(0L, 0L, rfg_nwell_reg, GET_REF_Y(NAME("din[%d]", high-1), "fc[0]"));

DEF_AB(w_block-w_column, 0L, 0L, 2L*rfg_hslice);
for(i=0L;i<high;i++)
  COPY_UP_CON(0L, "i", NAME("din[%d]", i), NAME("i[%d]", i));

#ifdef rfg_save_blocks
if(rfg_save_layout)
  SAVE_PHFIG ();
#endif

}

/*******************************************************************/
/*                                                                 */
/*  MLA ( high, l_width, n_bus, cell_alims, stuck )                */
/*                                                                 */
/*******************************************************************/

static void rfg_mla(high, l_width, n_bus, cell_alims, stuck)
  long high, l_width, n_bus, cell_alims, stuck;

{
/* [n_bus] [] */
static char cell_mla[2][rfg_snc]=
  {
  "rfl1b_c", "rfl2b_c"
  };
/* [n_bus] [rfg_low_high_cell] [] */
static char cell_mla_stuck[2][2][rfg_snc]=
  {
    {
    "rfl1bl_c", "rfl1bh_c",
    },
    {
    "rfl2bl_c", "rfl2bh_c",
    },
  };
/* [n_bus] [] */
static char buff_mla[2][rfg_snc]=
  {
  "rfbul1b_c", "rfbul2b_c"
  };
long i, j, w_mla, x_place, y_place;
char *name_cell;

if (stuck)
  DEF_PHFIG(NAME("%s13", rfg_name_pref));
else
  if (l_width>=rfg_wblock)
    DEF_PHFIG(NAME("%s14", rfg_name_pref));
  else
    DEF_PHFIG(NAME("%s15", rfg_name_pref));
w_mla=WIDTH(cell_mla[n_bus]);
x_place=y_place=0L;

i=0L;

if(stuck)
/* 1rst col */
  {
  for (j=0L;j<high;j++)
    {
    PLACE(cell_mla_stuck[n_bus][rfg_low_high_cell], NAME("mla[%d][%d]", i, high-1-j),
      rfg_symyx[j&1][i&1], x_place, y_place);
    y_place+=rfg_hslice;
    }
  PLACE(buff_mla[n_bus], NAME("mla[%d][%d]", i, high), rfg_symx[i&1], x_place, y_place);
  x_place+=w_mla;
  y_place=0L;
  i++;
  }

/* Other col */
for (;i<l_width;i++)
  {
  for (j=0L;j<high;j++)
    {
    PLACE(cell_mla[n_bus], NAME("mla[%d][%d]", i, high-1-j), rfg_symyx[j&1][i&1], x_place, y_place);
    y_place+=rfg_hslice;
    }
  PLACE(buff_mla[n_bus], NAME("mla[%d][%d]", i, high), rfg_symx[i&1], x_place, y_place);
  x_place+=w_mla;
  y_place=0L;
  }
rfg_nwell_reg=rfg_min_nwell(0L, 0L, rfg_nwell_reg, GET_REF_Y(NAME("mla[0][%d]", high-1), "fc[0]"));
rfg_nwell_buf[0]=rfg_min_nwell(0L, high,   rfg_nwell_buf[0], GET_REF_Y(NAME("mla[0][%d]", high), "fc[0]"));
rfg_nwell_buf[1]=rfg_min_nwell(1L, high+1, rfg_nwell_buf[1], GET_REF_Y(NAME("mla[0][%d]", high), "fc[1]"));
if(cell_alims)
  {
  for (j=0L;j<high+2L;j++)
    {
    PLACE("rfal_c", NAME("mla[%d][%d]", l_width, j), rfg_symy[j&1], x_place, y_place);
    y_place+=rfg_hslice;
    }
  /* no nwell contraints in "rfal_c" cell
  rfg_nwell_reg=rfg_min_nwell(0L, 0L, rfg_nwell_reg, GET_REF_Y(NAME("mla[%d][0]", l_width), "fc[0]"));
  rfg_nwell_buf[0]=rfg_min_nwell(0L, high,   rfg_nwell_buf[0], GET_REF_Y(NAME("mla[%d][%d]", l_width, high), "fc[0]"));
  rfg_nwell_buf[1]=rfg_min_nwell(1L, high+1, rfg_nwell_buf[1], GET_REF_Y(NAME("mla[%d][%d]", l_width, high+1), "fc[0]"));
  */
  }
DEF_AB(0L, 0L, 0L, 0L);
for(i=0L;i<l_width;i++)
  {
  name_cell=NAME("mla[%d][%d]", i, high);
  COPY_UP_CON(0L, "w", name_cell, NAME("w[%d]", i));
  COPY_UP_CON(0L, "r_a", name_cell, NAME("r_a[%d]", i));
  if(n_bus)
    COPY_UP_CON(0L, "r_b", name_cell, NAME("r_b[%d]", i));
  }
if(cell_alims)
  {
  for (i=0L;i<high;i++)
    {
    name_cell=NAME("mla[%d][%d]", l_width-1, i);
    COPY_UP_CON(0L, "o_a", name_cell, NAME("o_a[%d]", (high-1)-i));
    if(n_bus)
      COPY_UP_CON(0L, "o_b", name_cell, NAME("o_b[%d]", (high-1)-i));
    }
  COPY_UP_CON(1L, "vss", NAME("mla[%d][0]", l_width), "vss");
  COPY_UP_CON(0L, "vdd", NAME("mla[%d][0]", l_width), "vdd");
  COPY_UP_CON(1L, "vss", NAME("mla[%d][%d]", l_width, high+1L), "vss");
  COPY_UP_CON(0L, "vdd", NAME("mla[%d][%d]", l_width, high+1L), "vdd");
  }

#ifdef rfg_save_blocks
if(rfg_save_layout)
  SAVE_PHFIG ();
#endif

}

/*******************************************************************/
/*                                                                 */
/*  DOU ( high, width, n_bus, w_block, w_column )                  */
/*                                                                 */
/*******************************************************************/

static void rfg_dou(high, width, n_bus, w_block, w_column)
  long high, width, n_bus, w_block, w_column;

{
/* [n_bus] [] */
static char cell_dou[2][rfg_snc]=
  {
  "rfdo1b_c", "rfdo2b_c"
  };
/* [n_bus] [] */
static char buff_dou[2][rfg_snc]=
  {
  "rfbudo1b_c", "rfbudo2b_c"
  };
long y_place, i;
char *name_cell;

DEF_PHFIG(NAME("%s16", rfg_name_pref));
if(width>rfg_wblock)
  {
  y_place=0L;
  for (i=0L;i<high;i++)
    {
    PLACE(cell_dou[n_bus], NAME("dou[%d]", high-1-i), rfg_symy[i&1], 0L, y_place);
    y_place+=rfg_hslice;
    }
  rfg_nwell_reg=rfg_min_nwell(0L, 0L, rfg_nwell_reg, GET_REF_Y(NAME("dou[%d]", high-1), "fc[0]"));
  PLACE(buff_dou[n_bus], NAME("dou[%d]", high), NOSYM, 0L, y_place);
  rfg_nwell_buf[0]=rfg_min_nwell(0L, high,   rfg_nwell_buf[0], GET_REF_Y(NAME("dou[%d]", high), "fc[0]"));
  rfg_nwell_buf[1]=rfg_min_nwell(1L, high+1L, rfg_nwell_buf[1], GET_REF_Y(NAME("dou[%d]", high), "fc[1]"));
  DEF_AB(0L, 0L, w_column-w_block, 0L);
  for(i=0L;i<high;i++)
    {
    name_cell=NAME("dou[%d]", i);
    COPY_UP_CON(0L, "i_a", name_cell, NAME("i_a[%d]", i));
    COPY_UP_CON(0L, "f_a", name_cell, NAME("f_a[%d]", i));
    if(n_bus)
      {
      COPY_UP_CON(0L, "i_b", name_cell, NAME("i_b[%d]", i));
      COPY_UP_CON(0L, "f_b", name_cell, NAME("f_b[%d]", i));
      }
    }
  COPY_UP_CON(0L, "i_0", NAME("dou[%d]", high), "s_a");
  if(n_bus)
    COPY_UP_CON(0L, "i_1", NAME("dou[%d]", high), "s_b");
  }
else /* if block is empty correct AB height */
  DEF_AB(0L, 0L, w_column-w_block, (high+2L)*rfg_hslice);

#ifdef rfg_save_blocks
if(rfg_save_layout)
  SAVE_PHFIG ();
#endif

}

/*******************************************************************/
/*                                                                 */
/*  LOU ( high, n_bus, flip_flop,                                  */
/*        type_lou, w_block, w_column, bld_final)                  */
/*                                                                 */
/*******************************************************************/

static void rfg_lou(high, n_bus, flip_flop,
             type_lou, w_block, w_column, bld_final)
  long high, n_bus, flip_flop;
  long type_lou, w_block, w_column, bld_final;

{
long x_place, y_place, i, j, n_ref;
char *name_cell;

DEF_PHFIG(NAME("%s18", rfg_name_pref));
y_place=0L;
for (i=0L;i<high;i++)
  {
  PLACE(rfg_cell_bleeder[bld_final][type_lou][n_bus], NAME("lou[0][%d]", high-1-i), rfg_symy[i&1], 0L, y_place);
  y_place+=rfg_hslice;
  }
rfg_nwell_reg=rfg_min_nwell(0L, 0L, rfg_nwell_reg, GET_REF_Y(NAME("lou[0][%d]", high-1), "fc[0]"));

x_place=WIDTH(rfg_cell_bleeder[bld_final][type_lou][n_bus]);
y_place=0L;

if (flip_flop)
  {
  for (i=0L;i<high;i++)
    {
    PLACE(rfg_cell_latch[n_bus], NAME("lou[1][%d]", high-1-i), rfg_symy[i&1], x_place, y_place);
    y_place+=rfg_hslice;
    }
  rfg_nwell_reg=rfg_min_nwell(0L, 0L, rfg_nwell_reg, GET_REF_Y(NAME("lou[1][%d]", high-1), "fc[0]"));
  if(n_bus)
    { /* rflo2b_c */
    PLACE("rfbus1b_c", NAME("lou[0][%d]", high),
      SYM_X, WIDTH(rfg_cell_bleeder[bld_final][type_lou][n_bus])-5L, y_place);
    PLACE("rfbus1b_c", NAME("lou[1][%d]", high),
      NOSYM, WIDTH(rfg_cell_bleeder[bld_final][type_lou][n_bus])+40L, y_place);
    }
  else /* rflo1b_c */
    PLACE("rfbus1b_c", NAME("lou[0][%d]", high),
      NOSYM, WIDTH(rfg_cell_bleeder[bld_final][type_lou][n_bus])-3L, y_place);
  }

if(flip_flop)
  {
  rfg_nwell_buf[0]=rfg_min_nwell(0L, high, rfg_nwell_buf[0], GET_REF_Y(NAME("lou[0][%d]", high), "fc[0]"));
  rfg_nwell_buf[1]=rfg_min_nwell(1L, high+1L, rfg_nwell_buf[1], GET_REF_Y(NAME("lou[0][%d]", high), "fc[1]"));
  DEF_AB(0L, 0L, w_column-w_block, 0L);
  }
else
  DEF_AB(0L, 0L, w_column-w_block, 2L*rfg_hslice);

if(flip_flop)
  n_ref=rfg_n_ref_latch[n_bus];
else
  n_ref=rfg_n_ref_bleeder[type_lou][n_bus];
for(i=0L;i<high;i++)
  {
  if(flip_flop)
    name_cell=NAME("lou[1][%d]", i);
  else
    name_cell=NAME("lou[0][%d]", i);
  for(j=0L;j<n_ref;j++)
    if(flip_flop)
      COPY_UP_REF(rfg_ref_latch[n_bus][j], name_cell,
        NAME("%s[%d]", rfg_ref_latch[n_bus][j], i));
    else
      COPY_UP_REF(rfg_ref_bleeder[type_lou][n_bus][j], name_cell,
        NAME("%s[%d]", rfg_ref_bleeder[type_lou][n_bus][j], i));
  }
if(flip_flop)
  {
  COPY_UP_CON(0L, "i_0", NAME("lou[0][%d]", high), "w_r_a");
  if(n_bus)
    COPY_UP_CON(0L, "i_0", NAME("lou[1][%d]", high), "w_r_b");
  }

#ifdef rfg_save_blocks
if(rfg_save_layout)
  SAVE_PHFIG ();
#endif

}

/*******************************************************************/
/*                                                                 */
/*  BSI ( w_block, w_column )                                      */
/*                                                                 */
/*******************************************************************/

static void rfg_bsi(w_block, w_column)
  long w_block, w_column;

{
DEF_PHFIG(NAME("%s20", rfg_name_pref));
DEF_AB(0L, 0L, w_column-w_block, rfg_hslice);

#ifdef rfg_save_blocks
if(rfg_save_layout)
  SAVE_PHFIG ();
#endif

}

/*******************************************************************/
/*                                                                 */
/*  BSL ( l_width, n_bus, cell_alims )                             */
/*                                                                 */
/*******************************************************************/

static void rfg_bsl(l_width, n_bus, cell_alims)
  long l_width, n_bus, cell_alims;

{
long i, j, x_place, w_cell, w_pass;
char *name_cell, *name_pass;

name_pass=NULL;

if (l_width>=rfg_wblock)
  DEF_PHFIG(NAME("%s24", rfg_name_pref));
else
  DEF_PHFIG(NAME("%s25", rfg_name_pref));
x_place=0L;
w_cell=WIDTH("rfbsl_c");
if(n_bus)
  {
  w_pass=WIDTH("rfcna2b_c");
  for (i=0L;i<l_width;i++)
    {
    name_cell=NAME("bsl[%d]", 2*i+((i&1)^1));
    name_pass=NAME("bsl[%d]", 2*i+(i&1));
    for(j=0L;j<2L;j++)
      if((i&1L)^j)
        {
        PLACE("rfbsl_c", name_cell, rfg_symx[i&1], x_place, 0L);
        x_place+=w_cell;
        }
      else
        {
        PLACE("rfcna2b_c", name_pass, rfg_symx[i&1], x_place, 0L);
        x_place+=w_pass;
        }
    WIRE1(ALU1, rfg_width_min_alu1, name_pass, "s0", 0L, name_pass, "s1", 0L);
    WIRE1(ALU1, rfg_width_min_alu1, name_pass, "s1", 0L, name_pass, "s2", 0L);
    }
  rfg_nwell_int=rfg_min_nwell(0L, 0L, rfg_nwell_int, GET_REF_Y("bsl[0]", "fc[0]"));
  rfg_nwell_int=rfg_min_nwell(0L, 0L, rfg_nwell_int, GET_REF_Y("bsl[1]", "fc[0]"));
  }
else
  {
  for (i=0L;i<l_width;i++)
    {
    PLACE("rfbsl_c", NAME("bsl[%d]", i), rfg_symx[i&1], x_place, 0L);
    x_place+=w_cell;
    }
  rfg_nwell_int=rfg_min_nwell(0L, 0L, rfg_nwell_int, GET_REF_Y("bsl[0]", "fc[0]"));
  }
if(cell_alims)
  {
  if(n_bus)
    name_cell=NAME("bsl[%d]", 2*l_width);
  else
    name_cell=NAME("bsl[%d]", l_width);
  PLACE("rfalck_c", name_cell, NOSYM, x_place, 0L);
  PLACE_VIA_REF(name_cell, "ck_m", CONT_VIA);
  }

DEF_AB(0L, 0L, 0L, 0L);
for (i=0L;i<l_width;i++)
  {
  if(n_bus)
    {
    name_cell=NAME("bsl[%d]", 2*i+((i&1)^1));
    name_pass=NAME("bsl[%d]", 2*i+(i&1));
    }
  else
    name_cell=NAME("bsl[%d]", i);
  COPY_UP_CON(0L, "f_w"  , name_cell, NAME("w[%d]",   i));
  COPY_UP_CON(0L, "r_a", name_cell, NAME("r_a[%d]", i));
  if(n_bus)
    PHCON(ALU1, rfg_width_min_alu1, NAME("r_b[%d]", i), SOUTH,
      GET_REF_X(name_pass, "s2"), 0L);
  }

if(n_bus)
  {
  COPY_UP_CON(0L, "ck_m", "bsl[1]", "ck_m");
  COPY_UP_CON(1L, "ck_m", "bsl[1]", "ck_m");
  }
else
  {
  COPY_UP_CON(0L, "ck_m", "bsl[0]", "ck_m");
  COPY_UP_CON(1L, "ck_m", "bsl[0]", "ck_m");
  }

if(cell_alims)
  {
  if(n_bus)
    name_cell=NAME("bsl[%d]", 2*l_width);
  else
    name_cell=NAME("bsl[%d]", l_width);
  COPY_UP_CON(1L, "vss", name_cell, "vss");
  COPY_UP_CON(0L, "vdd", name_cell, "vdd");
  }

#ifdef rfg_save_blocks
if(rfg_save_layout)
  SAVE_PHFIG ();
#endif

}

/*******************************************************************/
/*                                                                 */
/*  BDO ( n_bus, nbr_block, w_block, w_column )                    */
/*                                                                 */
/*******************************************************************/

static void rfg_bdo(n_bus, nbr_block, w_block, w_column)
  long n_bus, nbr_block, w_block, w_column;

{
DEF_PHFIG(NAME("%s26", rfg_name_pref));

if(nbr_block)
  {
  PLACE("rfbdo_c", "bdo[0]", NOSYM, 0L, 0L);
  if(n_bus)
    WIRE3(ALU1, rfg_width_min_alu1, "bdo[0]", "t0", 0L, "bdo[0]", "t1", 0L,
      GET_REF_X("bdo[0]", "t0"), 30, GET_REF_X("bdo[0]", "t1"), 30);
  DEF_AB(0L, 0L, w_column-w_block, 0L);
  COPY_UP_CON(0L, "p_a", "bdo[0]", "s_a");
  if(n_bus)
    PHCON(ALU1, rfg_width_min_alu1, "s_b", SOUTH, GET_REF_X("bdo[0]", "t1"), 0L);
  }
else
  DEF_AB(0L, 0L, w_column-w_block, rfg_hslice);

#ifdef rfg_save_blocks
if(rfg_save_layout)
  SAVE_PHFIG ();
#endif

}

/*******************************************************************/
/*                                                                 */
/*  BSO ( n_bus, flip_flop,                                        */
/*        type_lou, w_block, w_column, bld_final )                 */
/*                                                                 */
/*******************************************************************/

static void rfg_bso( n_bus, flip_flop,
              type_lou, w_block, w_column, bld_final)
  long n_bus, flip_flop;
  long type_lou, w_block, w_column, bld_final;

{
DEF_PHFIG(NAME("%s28", rfg_name_pref));

if (flip_flop)
  {
  if(n_bus)
    { /* rflo2b_c */
    PLACE("rfblo_c", "bso[0]", NOSYM, 0L, 0L);
    PLACE("rfblo_c", "bso[1]", NOSYM, 40L, 0L);
    }
  else /* rflo1b_c */
    PLACE("rfblo_c", "bso[0]", NOSYM, 0L, 0L);
  }

if(flip_flop)
  {
  rfg_nwell_int=rfg_min_nwell(0L, 0L, rfg_nwell_int, GET_REF_Y("bso[0]", "fc[0]"));

  if(n_bus)
    DEF_AB(-WIDTH(rfg_cell_bleeder[bld_final][type_lou][n_bus]), 0L, 0L, 0L);
  else
    DEF_AB(-(WIDTH(rfg_cell_bleeder[bld_final][type_lou][n_bus])-3L), 0L, 0L, 0L);

  if(flip_flop)
    {
    COPY_UP_CON(0L, "f_0", "bso[0]", "w_r_a");
    if(n_bus)
      COPY_UP_CON(0L, "f_0", "bso[1]", "w_r_b");
    }
  }
else
  DEF_AB(0L, 0L, w_column-w_block, rfg_hslice);

#ifdef rfg_save_blocks
if(rfg_save_layout)
  SAVE_PHFIG ();
#endif

}

/*******************************************************************/
/*                                                                 */
/*  BLR ( width, low_power, vdd_down, floor_number,                */
/*        w_block, w_column )                                      */
/*                                                                 */
/*******************************************************************/

static void rfg_blr(width, low_power, vdd_down, floor_number, w_block, w_column)
  long width, low_power, vdd_down, floor_number;
  long w_block, w_column;

{
if(floor_number)
  DEF_PHFIG(NAME("%s40", rfg_name_pref));
else
  DEF_PHFIG(NAME("%s30", rfg_name_pref));
if (low_power)
  {
  vdd_down^=1L; /* reverse next floor */
  }
if (width>4L)
  DEF_AB(w_block-w_column, -low_power*rfg_hslice, 0L, 2L*rfg_hslice);
else
  DEF_AB(w_block-w_column, -low_power*rfg_hslice, 0L, rfg_hslice);

#ifdef rfg_save_blocks
if(rfg_save_layout)
  SAVE_PHFIG ();
#endif

}

/*******************************************************************/
/*                                                                 */
/*  ALR ( width, low_power, vdd_down, floor_number, addr_size,     */
/*        w_block, w_column )                                      */
/*                                                                 */
/*******************************************************************/

static void rfg_alr(width, low_power, vdd_down, floor_number, addr_size, w_block, w_column)
  long width, low_power, vdd_down, floor_number, addr_size, w_block, w_column;

{
long i, y_place;

if(floor_number)
  DEF_PHFIG(NAME("%s42", rfg_name_pref));
else
  DEF_PHFIG(NAME("%s32", rfg_name_pref));
if (low_power)
  {
  y_place=rfg_hslice;
  vdd_down^=1L; /* reverse next floor */
  }
else
  y_place=0L;
if (width==2L)
  {
  PLACE("rfal2_c", "alr[0]", rfg_symy[vdd_down], 0L, y_place);
  DEF_AB(w_block-w_column, -low_power*rfg_hslice, 0L, 0L);
  COPY_UP_CON(0L, "i0", "alr[0]", NAME("ad_r_%s[%d]", rfg_bus_name[floor_number], addr_size));
  COPY_UP_CON(1L, "i0", "alr[0]", NAME("ad_r_%s[%d]", rfg_bus_name[floor_number], addr_size));
  }
else
  if (width==4L)
    {
    PLACE("rfal4_c", "alr[0]", rfg_symy[vdd_down], 0L, y_place);
    DEF_AB(w_block-w_column, -low_power*rfg_hslice, 0L, 0L);
    COPY_UP_CON(0L, "i0", "alr[0]", NAME("ad_r_%s[%d]", rfg_bus_name[floor_number], addr_size-vdd_down));
    COPY_UP_CON(0L, "i1", "alr[0]", NAME("ad_r_%s[%d]", rfg_bus_name[floor_number], addr_size-(vdd_down^1)));
    COPY_UP_CON(1L, "i0", "alr[0]", NAME("ad_r_%s[%d]", rfg_bus_name[floor_number], addr_size-vdd_down));
    COPY_UP_CON(1L, "i1", "alr[0]", NAME("ad_r_%s[%d]", rfg_bus_name[floor_number], addr_size-(vdd_down^1)));
    }
  else
    if (width<=8L)
      {
      PLACE("rfal4_c", "alr[0]", rfg_symy[vdd_down], 0L, y_place);
      PLACE("rfal2_c", "alr[1]", rfg_symy[vdd_down^1], 0L, y_place+rfg_hslice);
      DEF_AB(w_block-w_column, -low_power*rfg_hslice, 0L, 0L);
      COPY_UP_CON(0L, "i0", "alr[0]", NAME("ad_r_%s[%d]", rfg_bus_name[floor_number], addr_size-(1+vdd_down)));
      COPY_UP_CON(0L, "i1", "alr[0]", NAME("ad_r_%s[%d]", rfg_bus_name[floor_number], addr_size-(1+(vdd_down^1))));
      COPY_UP_CON(0L, "i0", "alr[1]", NAME("ad_r_%s[%d]", rfg_bus_name[floor_number], addr_size));
      COPY_UP_CON(1L, "i0", "alr[0]", NAME("ad_r_%s[%d]", rfg_bus_name[floor_number], addr_size-(1+vdd_down)));
      COPY_UP_CON(1L, "i1", "alr[0]", NAME("ad_r_%s[%d]", rfg_bus_name[floor_number], addr_size-(1+(vdd_down^1))));
      COPY_UP_CON(1L, "i0", "alr[1]", NAME("ad_r_%s[%d]", rfg_bus_name[floor_number], addr_size));
      }
    else
      {
      PLACE("rfal4_c", "alr[0]", rfg_symy[vdd_down], 0L, y_place);
      PLACE("rfal4_c", "alr[1]", rfg_symy[vdd_down^1], 0L, y_place+rfg_hslice);
      DEF_AB(w_block-w_column, -low_power*rfg_hslice, 0L, 0L);
      COPY_UP_CON(0L, "i0", "alr[0]", NAME("ad_r_%s[%d]", rfg_bus_name[floor_number], addr_size-(2+vdd_down)));
      COPY_UP_CON(0L, "i1", "alr[0]", NAME("ad_r_%s[%d]", rfg_bus_name[floor_number], addr_size-(2+(vdd_down^1))));
      COPY_UP_CON(0L, "i0", "alr[1]", NAME("ad_r_%s[%d]", rfg_bus_name[floor_number], addr_size-(vdd_down^1)));
      COPY_UP_CON(0L, "i1", "alr[1]", NAME("ad_r_%s[%d]", rfg_bus_name[floor_number], addr_size-vdd_down));
      COPY_UP_CON(1L, "i0", "alr[0]", NAME("ad_r_%s[%d]", rfg_bus_name[floor_number], addr_size-(2+vdd_down)));
      COPY_UP_CON(1L, "i1", "alr[0]", NAME("ad_r_%s[%d]", rfg_bus_name[floor_number], addr_size-(2+(vdd_down^1))));
      COPY_UP_CON(1L, "i0", "alr[1]", NAME("ad_r_%s[%d]", rfg_bus_name[floor_number], addr_size-(vdd_down^1)));
      COPY_UP_CON(1L, "i1", "alr[1]", NAME("ad_r_%s[%d]", rfg_bus_name[floor_number], addr_size-vdd_down));
      }
i=low_power;
rfg_nwell_dec_r[floor_number][i]=rfg_min_nwell(vdd_down, i,
  rfg_nwell_dec_r[floor_number][i], GET_REF_Y("alr[0]", "fc[0]"));
if (width>4L)
  {
  i++;
  rfg_nwell_dec_r[floor_number][i]=rfg_min_nwell(vdd_down^1L, i,
    rfg_nwell_dec_r[floor_number][i], GET_REF_Y("alr[1]", "fc[0]"));
  }

#ifdef rfg_save_blocks
if(rfg_save_layout)
  SAVE_PHFIG ();
#endif

}

/********************************************************************/
/*                                                                  */
/*  CLR ( l_width, n_bus, low_power, vdd_down,                      */
/*        floor_number, nand_size, cell_alims )                     */
/*                                                                  */
/********************************************************************/

static void rfg_clr(l_width, n_bus, low_power, vdd_down, floor_number, nand_size, cell_alims)
  long l_width, n_bus, low_power, vdd_down, floor_number, nand_size, cell_alims;

{
/* [vdd_down] [] */
static char cell_lp[2][rfg_snc]=
  {
  "rfcnars_c","rfcnard_c"
  };
long i, j, x_place, y_place, w_rfcna2b_c, w_rfcnars_c, vdd_down_back;
char *name_cell, *name_pass, *name_pass2;

name_pass2=NULL;

if (l_width>=rfg_wblock)
  if(floor_number)
    DEF_PHFIG(NAME("%s44", rfg_name_pref));
  else
    DEF_PHFIG(NAME("%s34", rfg_name_pref));
else
  if(floor_number)
    DEF_PHFIG(NAME("%s45", rfg_name_pref));
  else
    DEF_PHFIG(NAME("%s35", rfg_name_pref));
x_place=y_place=0L;
w_rfcnars_c=WIDTH("rfcnars_c");
vdd_down_back=vdd_down;
if (n_bus)
  { /* two read bus part */
  w_rfcna2b_c=WIDTH("rfcna2b_c");
  if (low_power)
    {
    for(i=0L;i<l_width;i++)
      {
      name_pass=NAME("clr[%d][0]", 2*i+(i&1));
      name_cell=NAME("clr[%d][0]", 2*i+((i&1)^1));
      for(j=0L;j<2L;j++)
        if((i&1L)^j)
          {
          PLACE(cell_lp[vdd_down], name_cell, rfg_symx[i&1], x_place, 0L);
          x_place+=w_rfcnars_c;
          }
        else
          {
          PLACE("rfcna2b_c", name_pass, rfg_symyx[vdd_down][i&1], x_place, 0L);
          x_place+=w_rfcna2b_c;
          }
      if(floor_number)
        {
        WIRE1(ALU1, rfg_width_min_alu1, name_cell, "l0", 0L, name_pass, "r1", 0L);
        WIRE1(ALU1, rfg_width_min_alu1, name_pass, NAME("s%d", vdd_down^1) , 0L, name_pass, "r1", 0L);
        }
      else
        {
        WIRE1(ALU1, rfg_width_min_alu1, name_cell, "l1", 0L, name_cell, "s1", 0L);
        WIRE1(ALU1, rfg_width_min_alu1, name_pass, "s0", 0L, name_pass, "s1", 0L);
        }
      }
    rfg_nwell_dec_r[floor_number][0]=rfg_min_nwell(vdd_down, 0L,
      rfg_nwell_dec_r[floor_number][0], GET_REF_Y("clr[1][0]", "fc[0]"));
    vdd_down^=1L; /* reverse next floor */
    x_place=0L;
    y_place=rfg_hslice;
    }
  for(i=0L;i<l_width;i++)
    {
    name_pass=NAME("clr[%d][1]", 2*i+(i&1));
    if(nand_size>1L)
      name_pass2=NAME("clr[%d][2]", 2*i+(i&1));
    name_cell=NAME("clr[%d][1]", 2*i+((i&1)^1));
    for(j=0L;j<2L;j++)
      if((i&1L)^j)
        {
        PLACE(rfg_cell_nand[nand_size][vdd_down], name_cell,
              rfg_sym_nand[nand_size][vdd_down][i&1], x_place, y_place);
        WIRE1(ALU1, rfg_width_min_alu1, name_cell, "t0", 0L, name_cell, "t1", 0L);
        rfg_prog_input(name_cell, vdd_down, i, nand_size);
        x_place+=w_rfcnars_c;
        }
      else
        {
        PLACE("rfcna2b_c", name_pass, rfg_symyx[vdd_down][i&1], x_place, y_place);
        if(!floor_number)
          WIRE1(ALU1, rfg_width_min_alu1, name_pass, "s0", 0L, name_pass, "s1", 0L);
        if(nand_size>1L)
          {
          PLACE("rfcna2b_c", name_pass2, rfg_symyx[vdd_down^1][i&1], x_place, y_place+rfg_hslice);
          if(!floor_number)
            WIRE1(ALU1, rfg_width_min_alu1, name_pass2, "s0", 0L, name_pass2, "s1", 0L);
          }
        x_place+=w_rfcna2b_c;
        }
    /* prog_output */
    if (floor_number && !low_power)
      {
      if(nand_size>1L)
        {
        WIRE1(ALU1, rfg_width_min_alu1, name_cell, "l3", 0L, name_pass, NAME("r%d", 2*vdd_down), 0L);
        WIRE1(ALU1, rfg_width_min_alu1, name_pass, NAME("r%d", 2*vdd_down), 0L,
              name_pass, NAME("s%d", vdd_down^1) , 0L);
        }
      else
        {
        WIRE1(ALU1, rfg_width_min_alu1, name_cell, "l3", 0L, name_pass, "r0", 0L);
        WIRE1(ALU1, rfg_width_min_alu1, name_pass, "r0", 0L,
              name_pass, NAME("s%d", vdd_down^1) , 0L);
        }
      }
    else /* if vdd_down = 0 : connect ref "s1" to "l1" */
         /* if vdd_down = 1 : connect ref "s0" to "l0" */
      WIRE1(ALU1, rfg_width_min_alu1, name_cell, NAME("s%d", vdd_down^1), 0L,
            name_cell, NAME("l%d", vdd_down^1), 0L);
    }
  }
else
  { /* one read bus part */
  if (low_power)
    {
    for (i=0L;i<l_width;i++)
      {
      name_cell=NAME("clr[%d][0]", i);
      PLACE(cell_lp[vdd_down], name_cell, rfg_symx[i&1], x_place, 0L);
      WIRE1(ALU1, rfg_width_min_alu1, name_cell, "l1", 0L, name_cell, "s1", 0L);
      x_place+=w_rfcnars_c;
      }
    rfg_nwell_dec_r[floor_number][0]=rfg_min_nwell(vdd_down, 0L,
      rfg_nwell_dec_r[floor_number][0], GET_REF_Y("clr[0][0]", "fc[0]"));
    x_place=0L;
    y_place=rfg_hslice;
    vdd_down^=1L; /* reverse next floor */
    }
  for (i=0L;i<l_width;i++)
    {
    name_cell=NAME("clr[%d][1]", i);
    PLACE(rfg_cell_nand[nand_size][vdd_down], name_cell,
          rfg_sym_nand[nand_size][vdd_down][i&1], x_place, y_place);
    WIRE1(ALU1, rfg_width_min_alu1, name_cell, "t0", 0L, name_cell, "t1", 0L);
    rfg_prog_input(name_cell, vdd_down, i, nand_size);
    /* prog_output */
    WIRE1(ALU1, rfg_width_min_alu1, name_cell, NAME("s%d", vdd_down^1), 0L,
          name_cell, NAME("l%d", vdd_down^1), 0L);
    x_place+=w_rfcnars_c;
    }
  }
i=low_power;
rfg_nwell_dec_r[floor_number][i]=rfg_min_nwell(vdd_down, i,
  rfg_nwell_dec_r[floor_number][i], GET_REF_Y("clr[1][1]", "fc[0]"));
if(nand_size>1L)
  {
  i++;
  rfg_nwell_dec_r[floor_number][i]=rfg_min_nwell(vdd_down^1L, i,
    rfg_nwell_dec_r[floor_number][i], GET_REF_Y("clr[1][1]", "fc[1]"));
  }

vdd_down=vdd_down_back;

if(cell_alims)
  {
  j=low_power+1L;
  if(nand_size>1L)
    j++;
  for(i=0; i<j; i++)
    {
    if(n_bus)
      PLACE("rfalck_c", NAME("clr[%d][%d]", 2*l_width, i),
        rfg_symy[(i&1)^vdd_down], x_place, i*rfg_hslice);
    else
      PLACE("rfalck_c", NAME("clr[%d][%d]", l_width, i),
        rfg_symy[(i&1)^vdd_down], x_place, i*rfg_hslice);
    }
  }

DEF_AB(0L ,0L ,0L ,0L);
if(n_bus)
  {
  for(i=0; i<2; i++)
    {
    if(low_power)
      {
      COPY_UP_CON(i, "i", "clr[1][0]", "i");
      }
    COPY_UP_CON(i, "i0", "clr[1][1]", "i[0]");
    COPY_UP_CON(i, "i1", "clr[1][1]", "i[1]");
    if(nand_size>0)
      {
      COPY_UP_CON(i, "i2", "clr[1][1]", "i[2]");
      COPY_UP_CON(i, "i3", "clr[1][1]", "i[3]");
      if(nand_size>1)
        {
        COPY_UP_CON(i, "i4", "clr[1][1]", "i[4]");
        COPY_UP_CON(i, "i5", "clr[1][1]", "i[5]");
        if(nand_size>2)
          {
          COPY_UP_CON(i, "i6", "clr[1][1]", "i[6]");
          COPY_UP_CON(i, "i7", "clr[1][1]", "i[7]");
          }
        }
      }
    }
  }
else
  {
  if(low_power && cell_alims)
    COPY_UP_CON(1L, "i", "clr[0][0]", "i");
  }

#ifdef rfg_save_blocks
if(rfg_save_layout)
  SAVE_PHFIG ();
#endif

}

/*******************************************************************/
/*                                                                 */
/*  CHR ( width, n_bus, low_power, vdd_down, nand_size,            */
/*        floor_number, w_block, w_column )                        */
/*                                                                 */
/*******************************************************************/

static void rfg_chr(width, n_bus, low_power, vdd_down, nand_size, floor_number, w_block, w_column)
  long width, n_bus, low_power, vdd_down, nand_size, floor_number, w_block, w_column;

{
long i, x_place, y_place;
char *name_ref;

if(floor_number)
  DEF_PHFIG(NAME("%s46", rfg_name_pref));
else
  DEF_PHFIG(NAME("%s36", rfg_name_pref));

if(nand_size>=0L)
  {

  if(low_power)
    {
    PLACE("rfchr_c", "chr[0][0]", rfg_symy[vdd_down], 0L, 0L);
    rfg_nwell_dec_r[floor_number][0]=rfg_min_nwell(vdd_down, 0L,
      rfg_nwell_dec_r[floor_number][0], GET_REF_Y("chr[0][0]", "fc[0]"));
    y_place=rfg_hslice;
    vdd_down^=1L; /* reverse next floor */
    if(n_bus)
      WIRE1(ALU1, rfg_width_min_alu1, "chr[0][0]", "t0", 0L, "chr[0][0]", "t1", 0L);
    if(floor_number)
      WIRE1(ALU1, rfg_width_min_alu1, "chr[0][0]", "s2", 0L, "chr[0][0]", "t2", 0L);
    else
      WIRE1(ALU1, rfg_width_min_alu1, "chr[0][0]", "s0", 0L, "chr[0][0]", "s1", 0L);
    }
  else
    y_place=0L;

  x_place=WIDTH("rfahb2_c");
  if (nand_size==0L)
    {
    PLACE("rfahb2_c", "chr[0][1]", rfg_symy[vdd_down], 0L, y_place);
    PLACE("rfcna1_c", "chr[1][1]", rfg_symy[vdd_down], x_place, y_place);
    PLACE("rfspe_c", "chr[1][2]", rfg_symy[vdd_down^1], 0L, rfg_hslice+y_place);
    DEF_AB(0L, 0L, w_column-w_block, 0L);
    COPY_UP_CON(0L, "i0", "chr[0][1]", NAME("ad_r_%s[0]", rfg_bus_name[floor_number]));
    COPY_UP_CON(1L, "i0", "chr[0][1]", NAME("ad_r_%s[0]", rfg_bus_name[floor_number]));
    }
  else
    if (nand_size==1L)
      {
      PLACE("rfahb4_c", "chr[0][1]", rfg_symy[vdd_down], 0L, y_place);
      PLACE("rfcna2_c", "chr[1][1]", rfg_symy[vdd_down], x_place, y_place);
      PLACE("rfspe_c", "chr[1][2]", rfg_symy[vdd_down^1], 0L, rfg_hslice+y_place);
      DEF_AB(0L, 0L, w_column-w_block, 0L);
      COPY_UP_CON(0L, "i0", "chr[0][1]", NAME("ad_r_%s[%d]", rfg_bus_name[floor_number], vdd_down^1));
      COPY_UP_CON(0L, "i1", "chr[0][1]", NAME("ad_r_%s[%d]", rfg_bus_name[floor_number], vdd_down));
      COPY_UP_CON(1L, "i0", "chr[0][1]", NAME("ad_r_%s[%d]", rfg_bus_name[floor_number], vdd_down^1));
      COPY_UP_CON(1L, "i1", "chr[0][1]", NAME("ad_r_%s[%d]", rfg_bus_name[floor_number], vdd_down));
      }
    else
      if (nand_size==2L)
        {
        PLACE("rfahb4_c", "chr[0][1]", rfg_symy[vdd_down], 0L, y_place);
        PLACE("rfahb2_c", "chr[0][2]", rfg_symy[vdd_down^1], 0L, y_place+rfg_hslice);
        PLACE(rfg_cell_nand[2][vdd_down], "chr[1][1]", NOSYM, x_place, y_place);
        DEF_AB(0L, 0L, w_column-w_block, 0L);
        COPY_UP_CON(0L, "i0", "chr[0][1]", NAME("ad_r_%s[%d]", rfg_bus_name[floor_number], vdd_down^1));
        COPY_UP_CON(0L, "i1", "chr[0][1]", NAME("ad_r_%s[%d]", rfg_bus_name[floor_number], vdd_down));
        COPY_UP_CON(0L, "i0", "chr[0][2]", NAME("ad_r_%s[2]", rfg_bus_name[floor_number]));
        COPY_UP_CON(1L, "i0", "chr[0][1]", NAME("ad_r_%s[%d]", rfg_bus_name[floor_number], vdd_down^1));
        COPY_UP_CON(1L, "i1", "chr[0][1]", NAME("ad_r_%s[%d]", rfg_bus_name[floor_number], vdd_down));
        COPY_UP_CON(1L, "i0", "chr[0][2]", NAME("ad_r_%s[2]", rfg_bus_name[floor_number]));
        }
      else
        {
        PLACE("rfahb4_c", "chr[0][1]", rfg_symy[vdd_down], 0L, y_place);
        PLACE("rfahb4_c", "chr[0][2]", rfg_symy[vdd_down^1], 0L, y_place+rfg_hslice);
        PLACE(rfg_cell_nand[3][vdd_down], "chr[1][1]", NOSYM, x_place, y_place);
        DEF_AB(0L, 0L, w_column-w_block, 0L);
        COPY_UP_CON(0L, "i0", "chr[0][1]", NAME("ad_r_%s[%d]", rfg_bus_name[floor_number], vdd_down^1));
        COPY_UP_CON(0L, "i1", "chr[0][1]", NAME("ad_r_%s[%d]", rfg_bus_name[floor_number], vdd_down));
        COPY_UP_CON(0L, "i0", "chr[0][2]", NAME("ad_r_%s[%d]", rfg_bus_name[floor_number], 2+vdd_down));
        COPY_UP_CON(0L, "i1", "chr[0][2]", NAME("ad_r_%s[%d]", rfg_bus_name[floor_number], 2+(vdd_down^1)));
        COPY_UP_CON(1L, "i0", "chr[0][1]", NAME("ad_r_%s[%d]", rfg_bus_name[floor_number], vdd_down^1));
        COPY_UP_CON(1L, "i1", "chr[0][1]", NAME("ad_r_%s[%d]", rfg_bus_name[floor_number], vdd_down));
        COPY_UP_CON(1L, "i0", "chr[0][2]", NAME("ad_r_%s[%d]", rfg_bus_name[floor_number], 2+vdd_down));
        COPY_UP_CON(1L, "i1", "chr[0][2]", NAME("ad_r_%s[%d]", rfg_bus_name[floor_number], 2+(vdd_down^1)));
        }
  i=low_power;
  rfg_nwell_dec_r[floor_number][i]=rfg_min_nwell(vdd_down, i,
    rfg_nwell_dec_r[floor_number][i], GET_REF_Y("chr[0][1]", "fc[0]"));
  rfg_nwell_dec_r[floor_number][i]=rfg_min_nwell(vdd_down, i,
    rfg_nwell_dec_r[floor_number][i], GET_REF_Y("chr[1][1]", "fc[0]"));
  if (nand_size>1L)
    {
    i++;
    rfg_nwell_dec_r[floor_number][i]=rfg_min_nwell(vdd_down^1L, i,
      rfg_nwell_dec_r[floor_number][i], GET_REF_Y("chr[0][2]", "fc[0]"));
    rfg_nwell_dec_r[floor_number][i]=rfg_min_nwell(vdd_down^1L, i,
      rfg_nwell_dec_r[floor_number][i], GET_REF_Y("chr[1][1]", "fc[1]"));
    }

  if(!floor_number)
    {
    WIRE1(ALU1, rfg_width_min_alu1, "chr[1][1]", NAME("l%d", vdd_down^1), 0L,
          "chr[1][1]", NAME("s%d", vdd_down^1), 0L);
    }
  else
    {
    WIRE1(ALU1, rfg_width_min_alu1, "chr[1][1]", "l2", 0L, "chr[1][1]", "s2", 0L);
    WIRE1(ALU1, rfg_width_min_alu1, "chr[1][1]", "s2", 0L, "chr[1][1]", NAME("t%d", vdd_down^1), 0L);
    }
  if(n_bus && !floor_number)
    {
    WIRE1(ALU1, rfg_width_min_alu1, "chr[1][1]", "t0", 0L, "chr[1][1]", "t1", 0L);
    if(nand_size<2L)
      WIRE1(ALU1, rfg_width_min_alu1, "chr[1][2]", "t0", 0L, "chr[1][2]", "t1", 0L);
    }

  for(i=0L;i<(nand_size+1L)*2L;i++)
    {
    if(vdd_down)
      name_ref=NAME("j[%d]", i);
    else
      name_ref=NAME("i[%d]", i);
    COPY_UP_REF(name_ref, "chr[1][1]", NAME("i[%d]", i));
    }
  }
else
  if(width>4L)
    DEF_AB(0L, low_power*rfg_hslice, w_column-w_block, 2L*rfg_hslice);
  else
    DEF_AB(0L, low_power*rfg_hslice, w_column-w_block, rfg_hslice);

#ifdef rfg_save_blocks
if(rfg_save_layout)
  SAVE_PHFIG ();
#endif

}

/*******************************************************************/
/*                                                                 */
/*  BHR ( width, low_power, vdd_down, floor_number,                */
/*        w_block, w_column )                                      */
/*                                                                 */
/*******************************************************************/

static void rfg_bhr(width, low_power, vdd_down, floor_number, w_block, w_column)
  long width, low_power, vdd_down, floor_number, w_block, w_column;

{
long y_align_up;

if(floor_number)
  DEF_PHFIG(NAME("%s48", rfg_name_pref));
else
  DEF_PHFIG(NAME("%s38", rfg_name_pref));
if (low_power)
  {
  vdd_down^=1L; /* reverse next floor */
  }

if (width>4L)
  y_align_up=2L+low_power;
else
  y_align_up=1L+low_power;
DEF_AB (0L, 0L, w_column-w_block, y_align_up*rfg_hslice);

#ifdef rfg_save_blocks
if(rfg_save_layout)
  SAVE_PHFIG ();
#endif

}

/*******************************************************************/
/*                                                                 */
/*  BLW ( width, w_block, w_column )                               */
/*                                                                 */
/*******************************************************************/

static void rfg_blw(width, w_block, w_column)
  long width, w_block, w_column;

{
long y_align;

DEF_PHFIG(NAME("%s50", rfg_name_pref));
y_align=1L;
y_align++;
if (width>4L)
  y_align++;
DEF_AB(w_block-w_column, 0L, 0L, y_align*rfg_hslice);

#ifdef rfg_save_blocks
if(rfg_save_layout)
  SAVE_PHFIG ();
#endif

}

/*******************************************************************/
/*                                                                 */
/*  ALW ( l_width, write_enable, inverse_we, vdd_down, addr_size,  */
/*        width, w_block, w_column )                               */
/*                                                                 */
/*******************************************************************/

static void rfg_alw(l_width, write_enable, inverse_we, vdd_down, addr_size,
    width, w_block, w_column)
  long l_width, write_enable, inverse_we, vdd_down, addr_size;
  long width, w_block, w_column;

{
long y_align_down;

if(l_width>=rfg_wblock)
  DEF_PHFIG(NAME("%s52", rfg_name_pref));
else
  DEF_PHFIG(NAME("%s53", rfg_name_pref));
if (write_enable)
  {
  if (l_width<=8L)
    {
    if(inverse_we)
      PLACE("rfaw8n_c", "alw[0]", rfg_symy[vdd_down], 0L, 0L);
    else
      PLACE("rfaw8_c", "alw[0]", rfg_symy[vdd_down], 0L, 0L);
    }
  else
    {
    if(inverse_we)
      PLACE("rfaw16n_c", "alw[0]", rfg_symy[vdd_down], 0L, 0L);
    else
    PLACE("rfaw16_c", "alw[0]", rfg_symy[vdd_down], 0L, 0L);
    }
  rfg_nwell_dec_w[0]=rfg_min_nwell(vdd_down, 0L, rfg_nwell_dec_w[0], GET_REF_Y("alw[0]", "fc[0]"));
  y_align_down=0L;
  }
else
  y_align_down=1L;
vdd_down^=1L;
if (width==2L)
  {
  PLACE("rfal2_c", "alw[1]", rfg_symy[vdd_down], 0L, rfg_hslice);
  DEF_AB(w_block-w_column, -y_align_down*rfg_hslice, 0L, 0L);
  COPY_UP_CON(0L, "i0", "alw[1]", NAME("ad_w[%d]", addr_size));
  COPY_UP_CON(1L, "i0", "alw[1]", NAME("ad_w[%d]", addr_size));
  }
else
  if (width==4L)
    {
    PLACE("rfal4_c", "alw[1]", rfg_symy[vdd_down], 0L, rfg_hslice);
    DEF_AB(w_block-w_column, -y_align_down*rfg_hslice, 0L, 0L);
    COPY_UP_CON(0L, "i0", "alw[1]", NAME("ad_w[%d]", addr_size-vdd_down));
    COPY_UP_CON(0L, "i1", "alw[1]", NAME("ad_w[%d]", addr_size-(vdd_down^1)));
    COPY_UP_CON(1L, "i0", "alw[1]", NAME("ad_w[%d]", addr_size-vdd_down));
    COPY_UP_CON(1L, "i1", "alw[1]", NAME("ad_w[%d]", addr_size-(vdd_down^1)));
    }
  else
    if (width<=8L)
      {
      PLACE("rfal4_c", "alw[1]", rfg_symy[vdd_down], 0L, rfg_hslice);
      PLACE("rfal2_c", "alw[2]", rfg_symy[vdd_down^1], 0L, 2L*rfg_hslice);
      DEF_AB(w_block-w_column, -y_align_down*rfg_hslice, 0L, 0L);
      COPY_UP_CON(0L, "i0", "alw[1]", NAME("ad_w[%d]", addr_size-(1+vdd_down)));
      COPY_UP_CON(0L, "i1", "alw[1]", NAME("ad_w[%d]", addr_size-(1+(vdd_down^1))));
      COPY_UP_CON(0L, "i0", "alw[2]", NAME("ad_w[%d]", addr_size));
      COPY_UP_CON(1L, "i0", "alw[1]", NAME("ad_w[%d]", addr_size-(1+vdd_down)));
      COPY_UP_CON(1L, "i1", "alw[1]", NAME("ad_w[%d]", addr_size-(1+(vdd_down^1))));
      COPY_UP_CON(1L, "i0", "alw[2]", NAME("ad_w[%d]", addr_size));
      }
    else
      {
      PLACE("rfal4_c", "alw[1]", rfg_symy[vdd_down], 0L, rfg_hslice);
      PLACE("rfal4_c", "alw[2]", rfg_symy[vdd_down^1], 0L, 2L*rfg_hslice);
      DEF_AB(w_block-w_column, -y_align_down*rfg_hslice, 0L, 0L);
      COPY_UP_CON(0L, "i0", "alw[1]", NAME("ad_w[%d]", addr_size-(2+vdd_down)));
      COPY_UP_CON(0L, "i1", "alw[1]", NAME("ad_w[%d]", addr_size-(2+(vdd_down^1))));
      COPY_UP_CON(0L, "i0", "alw[2]", NAME("ad_w[%d]", addr_size-(vdd_down^1)));
      COPY_UP_CON(0L, "i1", "alw[2]", NAME("ad_w[%d]", addr_size-vdd_down));
      COPY_UP_CON(1L, "i0", "alw[1]", NAME("ad_w[%d]", addr_size-(2+vdd_down)));
      COPY_UP_CON(1L, "i1", "alw[1]", NAME("ad_w[%d]", addr_size-(2+(vdd_down^1))));
      COPY_UP_CON(1L, "i0", "alw[2]", NAME("ad_w[%d]", addr_size-(vdd_down^1)));
      COPY_UP_CON(1L, "i1", "alw[2]", NAME("ad_w[%d]", addr_size-vdd_down));
      }
rfg_nwell_dec_w[1]=rfg_min_nwell(vdd_down, 1L, rfg_nwell_dec_w[1], GET_REF_Y("alw[1]", "fc[0]"));
if (width>4L)
  rfg_nwell_dec_w[2]=rfg_min_nwell(vdd_down^1L, 2L, rfg_nwell_dec_w[2], GET_REF_Y("alw[2]", "fc[0]"));
if(write_enable)
  {
  COPY_UP_CON(0L, "i", "alw[0]", "we");
  COPY_UP_CON(1L, "i", "alw[0]", "we");
  COPY_UP_CON(0L, "t", "alw[0]", "t");
  }

#ifdef rfg_save_blocks
if(rfg_save_layout)
  SAVE_PHFIG ();
#endif

}

/*********************************************************************/
/*                                                                   */
/*  CLW ( l_width, n_bus, write_enable, vdd_down,                    */
/*        nand_size, width, cell_alims )                             */
/*                                                                   */
/*********************************************************************/

static void rfg_clw(l_width, n_bus, write_enable, vdd_down, nand_size, width, cell_alims)
  long l_width, n_bus, write_enable, vdd_down, nand_size, width, cell_alims;

{
/* [nor_size] [] */
static char cell_nor[3][rfg_snc]=
  {
  "rfcnrw1_c","rfcnrw2_c","rfcnrw3_c",
  };
long i, j, nor_size, x_place, w_rfcna2b_c, w_rfcnrw1_c;
char *name_nand, *name_nor, *name_pass0, *name_pass1, *name_pass2;
char *name_ref1, *name_ref2;
char *name_cell;

j=0L;
name_pass2=NULL;

if (l_width>=rfg_wblock)
  DEF_PHFIG(NAME("%s54", rfg_name_pref));
else
  DEF_PHFIG(NAME("%s55", rfg_name_pref));
x_place=0L;
if (width>rfg_wblock)
  nor_size=1L+write_enable;
else
  nor_size=write_enable;

name_ref1=NAME("s%d", vdd_down);
name_ref2=NAME("l%d", vdd_down);

if (n_bus)
  { /* two read bus part */
  w_rfcna2b_c=WIDTH("rfcna2b_c");
  w_rfcnrw1_c=WIDTH("rfcnrw1_c");
  for(i=0L;i<l_width;i++)
    {
    name_pass0=NAME("clw[%d][0]", 2*i+(i&1));
    name_pass1=NAME("clw[%d][1]", 2*i+(i&1));
    if(nand_size>1L)
      name_pass2=NAME("clw[%d][2]", 2*i+(i&1));
    name_nor=NAME("clw[%d][0]", 2*i+((i&1)^1));
    name_nand=NAME("clw[%d][1]", 2*i+((i&1)^1));
    for(j=0L;j<2L;j++)
      if((i&1L)^j)
        {
        PLACE(cell_nor[nor_size], name_nor, rfg_symyx[vdd_down][i&1], x_place, 0L);
        PLACE(rfg_cell_nand[nand_size][vdd_down^1], name_nand,
              rfg_sym_nand[nand_size][vdd_down^1][i&1], x_place, rfg_hslice);
        rfg_prog_input(name_nand, vdd_down^1L, i, nand_size);
        /* prog_output */
        WIRE1(ALU1, rfg_width_min_alu1, name_nand, name_ref1, 0L,
              name_nand, name_ref2, 0L);
        x_place+=w_rfcnrw1_c;
        }
      else
        {
        PLACE("rfcna2b_c", name_pass0, rfg_symyx[vdd_down][i&1], x_place, 0L);
        PLACE("rfcna2b_c", name_pass1, rfg_symyx[vdd_down^1][i&1], x_place, rfg_hslice);
        if(nand_size>1L)
          PLACE("rfcna2b_c", name_pass2, rfg_symyx[vdd_down][i&1], x_place, 2L*rfg_hslice);
        x_place+=w_rfcna2b_c;
        }
    }
  }
else
  { /* one read bus part */
  w_rfcnrw1_c=WIDTH("rfcnrw1_c");
  for (i=0L;i<l_width;i++)
    {
    PLACE(cell_nor[nor_size], NAME("clw[%d][0]", i), rfg_symyx[vdd_down][i&1], x_place, 0L);
    name_nand=NAME("clw[%d][1]", i);
    PLACE(rfg_cell_nand[nand_size][vdd_down^1], name_nand,
          rfg_sym_nand[nand_size][vdd_down^1][i&1], x_place, rfg_hslice);
    rfg_prog_input(name_nand, vdd_down^1L, i, nand_size);
    /* prog_output */
    WIRE1(ALU1, rfg_width_min_alu1, name_nand, name_ref1, 0L,
          name_nand, name_ref2, 0L);
    x_place+=w_rfcnrw1_c;
    }
  }
rfg_nwell_dec_w[0]=rfg_min_nwell(vdd_down, 0L, rfg_nwell_dec_w[0], GET_REF_Y("clw[1][0]", "fc[0]"));
rfg_nwell_dec_w[1]=rfg_min_nwell(vdd_down^1L, 1L, rfg_nwell_dec_w[1], GET_REF_Y("clw[1][1]", "fc[0]"));
if(nand_size>1L)
  rfg_nwell_dec_w[2]=rfg_min_nwell(vdd_down, 2L, rfg_nwell_dec_w[2], GET_REF_Y("clw[1][1]", "fc[1]"));

if(cell_alims)
  {
  j=2L;
  if(nand_size>1L)
    j++;
  for(i=0; i<j; i++)
    {
    if(n_bus)
      PLACE("rfalck_c", NAME("clw[%d][%d]", 2*l_width, i),
        rfg_symy[(i&1)^vdd_down], x_place, i*rfg_hslice);
    else
      PLACE("rfalck_c", NAME("clw[%d][%d]", l_width, i),
        rfg_symy[(i&1)^vdd_down], x_place, i*rfg_hslice);
    }
  }

DEF_AB(0L, 0L, 0L, 0L);
if(n_bus)
  {
  for(i=0; i<2; i++)
    {
/*
    COPY_UP_CON(i, "i0", "clw[1][0]", "j[0]");
*/	
    if(nor_size>0L)
      {
      COPY_UP_CON(i, "i1", "clw[1][0]", "j[1]");
      if(nor_size>1L)
        COPY_UP_CON(i, "i2", "clw[1][0]", "j[2]");
      }
    COPY_UP_CON(i, "i0", "clw[1][1]", "i[0]");
    COPY_UP_CON(i, "i1", "clw[1][1]", "i[1]");
    if(nand_size>0)
      {
      COPY_UP_CON(i, "i2", "clw[1][1]", "i[2]");
      COPY_UP_CON(i, "i3", "clw[1][1]", "i[3]");
      if(nand_size>1)
        {
        COPY_UP_CON(i, "i4", "clw[1][1]", "i[4]");
        COPY_UP_CON(i, "i5", "clw[1][1]", "i[5]");
        if(nand_size>2)
          {
          COPY_UP_CON(i, "i6", "clw[1][1]", "i[6]");
          COPY_UP_CON(i, "i7", "clw[1][1]", "i[7]");
          }
        }
      }
    }
  }
else
  {
  if(cell_alims)
    if(nor_size>0L)
      {
      COPY_UP_CON(1L, "i1", "clw[0][0]", "j[1]");
      if(nor_size>1L)
        COPY_UP_CON(1L, "i2", "clw[0][0]", "j[2]");
      }
  }

if(cell_alims)
  {
  if(n_bus)
    name_cell=NAME("clw[%d][%d]", 2*l_width, j-1);
  else
    name_cell=NAME("clw[%d][%d]", l_width, j-1);
  if((j^vdd_down)&1)
    {
    COPY_UP_CON(3L, "vss", name_cell, "vss");
    COPY_UP_CON(1L, "ck_m", name_cell, "ck_m");
    COPY_UP_CON(2L, "vdd", name_cell, "vdd");
    }
  else
    {
    COPY_UP_CON(1L, "vss", name_cell, "vss");
    COPY_UP_CON(0L, "ck_m", name_cell, "ck_m");
    COPY_UP_CON(0L, "vdd", name_cell, "vdd");
    }
  }

#ifdef rfg_save_blocks
if(rfg_save_layout)
  SAVE_PHFIG ();
#endif

}

/*******************************************************************/
/*                                                                 */
/*  CHW ( l_width, write_enable, vdd_down, nand_size,              */
/*        w_block, w_column, width )                               */
/*                                                                 */
/*******************************************************************/

static void rfg_chw(l_width, write_enable, vdd_down, nand_size, w_block, w_column, width)
  long l_width, write_enable, vdd_down, nand_size, w_block, w_column, width;

{
long i;
char *name_ref;

if(l_width>=rfg_wblock)
  DEF_PHFIG(NAME("%s56", rfg_name_pref));
else
  DEF_PHFIG(NAME("%s57", rfg_name_pref));

if(nand_size>=0L)
  {

  if(l_width>8L)
    PLACE("rfchw16_c", "chw[0][0]", rfg_symy[vdd_down], 0L, 0L);
  else
    PLACE("rfchw8_c", "chw[0][0]", rfg_symy[vdd_down], 0L, 0L);
  rfg_nwell_dec_w[0]=rfg_min_nwell(vdd_down, 0L, rfg_nwell_dec_w[0], GET_REF_Y("chw[0][0]", "fc[0]"));
  if(!write_enable)
    WIRE1(ALU2, rfg_width_min_alu2, "chw[0][0]", "l0", 0L, "chw[0][0]", "s0", 0L);
  vdd_down^=1L; /* reverse next floor */

  if(nand_size==0L)
    {
    PLACE("rfahb2_c", "chw[0][1]", rfg_symy[vdd_down], 0L, rfg_hslice);
    PLACE("rfcna1_c", "chw[1][1]", rfg_symy[vdd_down], WIDTH("rfahb2_c"), rfg_hslice);
    DEF_AB(0L, 0L, w_column-w_block, rfg_hslice);
    COPY_UP_CON(0L, "i0", "chw[0][1]", "ad_w[0]");
    COPY_UP_CON(1L, "i0", "chw[0][1]", "ad_w[0]");
    }
  else
    if(nand_size==1L)
      {
      PLACE("rfahb4_c", "chw[0][1]", rfg_symy[vdd_down], 0L, rfg_hslice);
      PLACE("rfcna2_c", "chw[1][1]", rfg_symy[vdd_down], WIDTH("rfahb2_c"), rfg_hslice);
      DEF_AB(0L, 0L, w_column-w_block, rfg_hslice);
      COPY_UP_CON(0L, "i0", "chw[0][1]", NAME("ad_w[%d]", vdd_down^1));
      COPY_UP_CON(0L, "i1", "chw[0][1]", NAME("ad_w[%d]", vdd_down));
      COPY_UP_CON(1L, "i0", "chw[0][1]", NAME("ad_w[%d]", vdd_down^1));
      COPY_UP_CON(1L, "i1", "chw[0][1]", NAME("ad_w[%d]", vdd_down));
      }
    else
      if(nand_size==2L)
        {
        PLACE("rfahb4_c", "chw[0][1]", rfg_symy[vdd_down], 0L, rfg_hslice);
        PLACE("rfahb2_c", "chw[0][2]", rfg_symy[vdd_down^1], 0L, 2L*rfg_hslice);
        PLACE(rfg_cell_nand[2][vdd_down], "chw[1][1]", NOSYM, WIDTH("rfahb2_c"), rfg_hslice);
        DEF_AB(0L, 0L, w_column-w_block, 0L);
        COPY_UP_CON(0L, "i0", "chw[0][1]", NAME("ad_w[%d]", vdd_down^1));
        COPY_UP_CON(0L, "i1", "chw[0][1]", NAME("ad_w[%d]", vdd_down));
        COPY_UP_CON(0L, "i0", "chw[0][2]", "ad_w[2]");
        COPY_UP_CON(1L, "i0", "chw[0][1]", NAME("ad_w[%d]", vdd_down^1));
        COPY_UP_CON(1L, "i1", "chw[0][1]", NAME("ad_w[%d]", vdd_down));
        COPY_UP_CON(1L, "i0", "chw[0][2]", "ad_w[2]");
        }
      else
        {
        PLACE("rfahb4_c", "chw[0][1]", rfg_symy[vdd_down], 0L, rfg_hslice);
        PLACE("rfahb4_c", "chw[0][2]", rfg_symy[vdd_down^1], 0L, 2L*rfg_hslice);
        PLACE(rfg_cell_nand[3][vdd_down], "chw[1][1]", NOSYM, WIDTH("rfahb2_c"), rfg_hslice);
        DEF_AB(0L, 0L, w_column-w_block, 0L);
        COPY_UP_CON(0L, "i0", "chw[0][1]", NAME("ad_w[%d]", vdd_down^1));
        COPY_UP_CON(0L, "i1", "chw[0][1]", NAME("ad_w[%d]", vdd_down));
        COPY_UP_CON(0L, "i0", "chw[0][2]", NAME("ad_w[%d]", 2+vdd_down));
        COPY_UP_CON(0L, "i1", "chw[0][2]", NAME("ad_w[%d]", 2+(vdd_down^1)));
        COPY_UP_CON(1L, "i0", "chw[0][1]", NAME("ad_w[%d]", vdd_down^1));
        COPY_UP_CON(1L, "i1", "chw[0][1]", NAME("ad_w[%d]", vdd_down));
        COPY_UP_CON(1L, "i0", "chw[0][2]", NAME("ad_w[%d]", 2+vdd_down));
        COPY_UP_CON(1L, "i1", "chw[0][2]", NAME("ad_w[%d]", 2+(vdd_down^1)));
        }

  rfg_nwell_dec_w[1]=rfg_min_nwell(vdd_down, 1L, rfg_nwell_dec_w[1], GET_REF_Y("chw[0][1]", "fc[0]"));
  rfg_nwell_dec_w[1]=rfg_min_nwell(vdd_down, 1L, rfg_nwell_dec_w[1], GET_REF_Y("chw[1][1]", "fc[0]"));
  if(nand_size>1L)
    {
    rfg_nwell_dec_w[2]=rfg_min_nwell(vdd_down^1L, 2L, rfg_nwell_dec_w[2], GET_REF_Y("chw[0][2]", "fc[0]"));
    rfg_nwell_dec_w[2]=rfg_min_nwell(vdd_down^1L, 2L, rfg_nwell_dec_w[2], GET_REF_Y("chw[1][1]", "fc[1]"));
    }

  WIRE1(ALU1, rfg_width_min_alu1, "chw[1][1]", NAME("s%d", vdd_down^1), 0L,
        "chw[1][1]", NAME("l%d", vdd_down^1), 0L);

  for(i=0L;i<(nand_size+1L)*2L;i++)
    {
    if(vdd_down)
      name_ref=NAME("j[%d]", i);
    else
      name_ref=NAME("i[%d]", i);
    COPY_UP_REF(name_ref, "chw[1][1]", NAME("i[%d]", i));
    }
  }
else
  if(width>4L)
    DEF_AB(0L, 0L, w_column-w_block, 3L*rfg_hslice);
  else
    DEF_AB(0L, 0L, w_column-w_block, 2L*rfg_hslice);

#ifdef rfg_save_blocks
if(rfg_save_layout)
  SAVE_PHFIG ();
#endif

}

/*******************************************************************/
/*                                                                 */
/*  BHW ( width, vdd_down, w_block, w_column )                     */
/*                                                                 */
/*******************************************************************/

static void rfg_bhw(width, vdd_down, w_block, w_column)
  long width, vdd_down, w_block, w_column;

{
long y_align_up;

DEF_PHFIG(NAME("%s58", rfg_name_pref));
vdd_down^=1L; /* reverse next floor (first floor empty) */

if(width>4L)
  y_align_up=3L;
else
  y_align_up=2L;
DEF_AB (0L, 0L, w_column-w_block, y_align_up*rfg_hslice);

#ifdef rfg_save_blocks
if(rfg_save_layout)
  SAVE_PHFIG ();
#endif

}

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

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

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

{
long i, j, k;
long vdd_down, n_slice;
long num_alims, nbr_alims_reg, nbr_alims_dec;
long xmin, xmax, y;
long nwell_index=0;

char *name_block1, *name_block2;

#ifdef rfg_floating_con
long l, n_ref;
char tmp_1[rfg_snc];
#endif

/********** Names and widths of alims **********/

/* [indice_slice&1] [] */
static char alim_name[2][4]=
  {
  "vss","vdd"
  };

/* [indice_slice&1] */
static long alim_width[2]=
  {
  rfg_width_vss,rfg_width_vdd
  };

/********** y position of each ALU2 track of one bit-slice **********/

/* [indice_track] */
static long y_track[rfg_nbr_tracks];

/********** Maps of free ALU2 tracks **********/
/* "1" mean the track if free of any ALU2 segment. */

/***** Map of free track in register slices as function of parameters. *****/
/* [rfg_type_lou] [n_bus] [indice_track] */
static long allow_reg[2][2][rfg_nbr_tracks]=
  {
    {
      {1, 1, 1, 1, 0, 0, 1, 0, 1, 1}, /* one block, one read bus */
      {1, 1, 0, 1, 0, 0, 1, 0, 1, 1}, /* one block, two read bus */
    },
    {
      {1, 1, 1, 1, 0, 0, 0, 0, 1, 1}, /* several blocks, one read bus */
      {1, 1, 0, 1, 0, 0, 0, 0, 0, 1}, /* several blocks, two read bus */
    },
  };

/***** map of free track in buffer slices *****/
/* [num_slice] [indice_track] */
static long allow_buf[2][rfg_nbr_tracks]=
  {
    {1, 1, 1, 1, 1, 1, 0, 0, 0, 0}, /* first bitslice  */
    {0, 0, 0, 0, 1, 1, 1, 1, 1, 1}, /* second bitslice */
  };

/***** map of free track in interception slice *****/
/* [indice_track] */
static long allow_int[rfg_nbr_tracks]=
  {1, 1, 1, 1, 1, 0, 1, 1, 1, 0,};

/***** map of free track in low_power slice *****/
/* [indice_track] */
static long allow_lp[rfg_nbr_tracks]=
  {1, 1, 1, 1, 1, 1, 0, 1, 1, 1,};

/***** map of free track in write_enable slice *****/
/* [indice_track] */
static long allow_we[rfg_nbr_tracks]=
  {1, 1, 1, 1, 0, 0, 0, 1, 1, 1,};

/***** map of free track in nands slices *****/
/* [indice_track] */
static long allow_nand[rfg_nbr_tracks]=
  {0, 0, 1, 0, 0, 0, 0, 0, 1, 0,};

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

nbr_alims_reg=0L;

/***** "read" y of ALU2 tracks *****/
DEF_PHFIG("tmp");
PLACE    ("rfdi_c", "rfdi_c", NOSYM, 0L, 0L);
for(i=0L ; i<rfg_nbr_tracks; i++)
  y_track[i]=GET_REF_Y("rfdi_c", NAME("track[%d]", i));

/***** init rfg_nwell_xxx to max nwell width for a bit slice *****/
rfg_nwell_reg=rfg_hslice;
for(i=0L;i<rfg_nbr_slice_buf;i++)
  rfg_nwell_buf[i]=rfg_hslice;
rfg_nwell_int=rfg_hslice;
for(i=0L;i<rfg_nbr_read_bus;i++)
  for(j=0L;j<rfg_nbr_slice_dec;j++)
    rfg_nwell_dec_r[i][j]=rfg_hslice;
for(i=0L;i<rfg_nbr_slice_dec;i++)
  rfg_nwell_dec_w[i]=rfg_hslice;

/*******************************************************************/
/* Create necessary blocks.                                        */
/*******************************************************************/

/***** Register part blocks. *****/
if (block_type!=rfg_dec_sep)
  {
  rfg_lin (high, rfg_inv_data_cell, rfg_type_lin, rfg_w_lin, rfg_w_col_lin);
  rfg_din (high, rfg_w_din, rfg_w_col_din);
  if(stuck)
    {
    if(rfg_nbr_block_p)
      {
      rfg_mla (high, rfg_wblock, n_bus, rfg_cell_alims, 1L);
      if(rfg_nbr_block_p>1)
        rfg_mla (high, rfg_wblock, n_bus, rfg_cell_alims, 0L);
      if(rfg_width_f)
        rfg_mla (high, rfg_width_f, n_bus, rfg_cell_alims, 0L);
      }
    else
      if(rfg_width_f)
        rfg_mla (high, rfg_width_f, n_bus, rfg_cell_alims, 1L);
    }
  else
    {
    if(rfg_nbr_block_p)
      rfg_mla (high, rfg_wblock, n_bus, rfg_cell_alims, 0L);
    if(rfg_width_f)
      rfg_mla (high, rfg_width_f, n_bus, rfg_cell_alims, 0L);
    }
  rfg_dou (high, width, n_bus, rfg_w_dou, rfg_w_col_dou);
  rfg_lou (high, n_bus, flip_flop, rfg_type_lou, rfg_w_lou, rfg_w_col_lou, rfg_bld_final);
  }

/***** Decoders part blocks. *****/
if((block_type==rfg_dec_sep) || (block_type==rfg_bank))
  {
  /* Interseption of write signals by clocks. */
  rfg_bsi (rfg_w_bsi, rfg_w_col_lin);
  if(rfg_nbr_block_p)
    rfg_bsl (rfg_wblock, n_bus, rfg_cell_alims);
  if(rfg_width_f)
    rfg_bsl (rfg_width_f, n_bus, rfg_cell_alims);
  rfg_bdo (n_bus, rfg_nbr_block, rfg_w_bdo, rfg_w_col_dou);
  rfg_bso (n_bus, flip_flop, rfg_type_lou, rfg_w_bso, rfg_w_col_lou, rfg_bld_final);

  vdd_down=1L; /* Next floor as vdd track bottom. */

  /* Decoder of first read bus. */
  rfg_blr (width, low_power, vdd_down, 0L, rfg_w_blr, rfg_w_col_lin);
  rfg_alr (width, low_power, vdd_down, 0L, rfg_addr_size, rfg_w_alr, rfg_w_col_din);
  if(rfg_nbr_block_p)
    rfg_clr (rfg_wblock, n_bus, low_power, vdd_down, 0L, rfg_nand_l, rfg_cell_alims);
  if(rfg_width_f)
    rfg_clr (rfg_width_f, n_bus, low_power, vdd_down, 0L, rfg_nand_l, rfg_cell_alims);
  rfg_chr (width, n_bus, low_power, vdd_down, rfg_nand_h, 0L, rfg_w_chr, rfg_w_col_dou);
  rfg_bhr (width, low_power, vdd_down, 0L, rfg_w_bhr, rfg_w_col_lou);

  /* Reverse next floor if number of slice is odd. */
  vdd_down^=(HEIGHT(NAME("%s30", rfg_name_pref))/rfg_hslice)&1L;

  /* Decoder of second read bus. */
  if(n_bus)
    {
    rfg_blr (width, low_power, vdd_down, 1L, rfg_w_blr, rfg_w_col_lin);
    rfg_alr (width, low_power, vdd_down, 1L, rfg_addr_size, rfg_w_alr, rfg_w_col_din);
    if(rfg_nbr_block_p)
      rfg_clr (rfg_wblock, n_bus, low_power, vdd_down, 1L, rfg_nand_l, rfg_cell_alims);
    if(rfg_width_f)
      rfg_clr (rfg_width_f, n_bus, low_power, vdd_down, 1L, rfg_nand_l, rfg_cell_alims);
    rfg_chr (width, n_bus, low_power, vdd_down, rfg_nand_h, 1L, rfg_w_chr, rfg_w_col_dou);
    rfg_bhr (width, low_power, vdd_down, 1L, rfg_w_bhr, rfg_w_col_lou);

    /* Reverse next floor if number of slice is odd. */
    vdd_down^=(HEIGHT(NAME("%s40", rfg_name_pref))/rfg_hslice)&1L;
    }

  /* Decoder of write bus. */
  rfg_blw (width, rfg_w_blw, rfg_w_col_lin);
  if(rfg_nbr_block_p)
    {
    rfg_alw (rfg_wblock, write_enable, inverse_we, vdd_down, rfg_addr_size,
      width, rfg_w_alw, rfg_w_col_din);
    rfg_clw (rfg_wblock, n_bus, write_enable, vdd_down, rfg_nand_l, width, rfg_cell_alims);
    rfg_chw (rfg_wblock, write_enable, vdd_down, rfg_nand_h, rfg_w_chw, rfg_w_col_dou, width);
    }
  if(rfg_width_f)
    {
    rfg_alw (rfg_width_f, write_enable, inverse_we, vdd_down, rfg_addr_size,
      width, rfg_w_alw, rfg_w_col_din);
    rfg_clw (rfg_width_f, n_bus, write_enable, vdd_down, rfg_nand_l, width, rfg_cell_alims);
    rfg_chw (rfg_width_f, write_enable, vdd_down, rfg_nand_h, rfg_w_chw, rfg_w_col_dou, width);
    }
  rfg_bhw (width, vdd_down, rfg_w_bhw, rfg_w_col_lou);
  }

/*******************************************************************/
/* Create registers block.                                         */
/*******************************************************************/

if (block_type!=rfg_dec_sep)
  {
  /********** Place blocks. ***********/

  DEF_PHFIG (NAME("%s", rfg_name_pref));
  PLACE (NAME("%s10", rfg_name_pref), "lin", NOSYM, 0L, 0L);
  for(i=0L;i<rfg_nbr_block_p;i++)
    {
    PLACE_RIGHT (NAME("%s12", rfg_name_pref), NAME("din[%d]", i), NOSYM);
    if(stuck && (i==0L))
      PLACE_RIGHT (NAME("%s13", rfg_name_pref), NAME("mla[%d]", i), NOSYM);
    else
      PLACE_RIGHT (NAME("%s14", rfg_name_pref), NAME("mla[%d]", i), NOSYM);
    PLACE_RIGHT (NAME("%s16", rfg_name_pref), NAME("dou[%d]", i), NOSYM);
    }
  if(rfg_width_f)
    {
    PLACE_RIGHT (NAME("%s12", rfg_name_pref), NAME("din[%d]", i), NOSYM);
    if(stuck && (i==0L))
      PLACE_RIGHT (NAME("%s13", rfg_name_pref), NAME("mla[%d]", i), NOSYM);
    else
      PLACE_RIGHT (NAME("%s15", rfg_name_pref), NAME("mla[%d]", i), NOSYM);
    PLACE_RIGHT (NAME("%s16", rfg_name_pref), NAME("dou[%d]", i), NOSYM);
    }
  PLACE_RIGHT (NAME("%s18", rfg_name_pref), "lou", NOSYM);

  /********** Interconnect internal signals. ***********/

  if(width>rfg_wblock)
    {
    name_block1=NAME("din[%d]", rfg_nbr_block);
    name_block2=NAME("dou[%d]", rfg_nbr_block);
    for(j=0L;j<high;j++)
      {
      WIRE1 (ALU2, rfg_width_min_alu2, "din[0]", NAME("i[%d]", j), 0L,
             name_block1, NAME("i[%d]", j), 0L);
      WIRE1 (ALU2, rfg_width_min_alu2, "dou[0]", NAME("f_a[%d]", j), 0L,
             name_block2, NAME("f_a[%d]", j), 0L);
      if(n_bus)
        WIRE1 (ALU2, rfg_width_min_alu2, "dou[0]", NAME("f_b[%d]", j), 0L,
               name_block2, NAME("f_b[%d]", j), 0L);
      }
    }

  DEF_AB (-rfg_half_rules, 0L, rfg_half_rules, 0L);

  nbr_alims_reg=HEIGHT(NAME("%s", rfg_name_pref))/rfg_hslice; /* first alim is VSS */

  if(hard_connectors)
    {
    if(block_type!=rfg_bank)
      DEF_AB (-rfg_half_rules, -(alim_width[0]>>1)-rfg_half_rules,
        rfg_half_rules, (alim_width[0]>>1)+rfg_half_rules);
    else
      DEF_AB (-rfg_half_rules, -(alim_width[0]>>1)-rfg_half_rules,
        rfg_half_rules, 0L);
    }

  xmin= -rfg_half_rules;
  xmax=WIDTH(NAME("%s", rfg_name_pref))-rfg_half_rules;

  /********** Define external interface. ***********/

  /***** WEST side. *****/
  if(hard_connectors)
    {
    for(i=0L;i<high;i++)
      rfg_HARDED_FLOAT("lin", NAME("in_a_4[%d]", i), NAME("in_a[%d]", msb ? i : high-1-i), WEST);
    }

#ifdef rfg_floating_con
  else
    {
    n_ref=rfg_n_ref_lin[rfg_inv_data_cell][rfg_type_lin];
    for(i=0L;i<high;i++)
      {
      for(j=0L; j<n_ref; j++)
        {
        l=0L;
        for(k=0L; rfg_ref_lin[rfg_inv_data_cell][rfg_type_lin][j][k]!='\0'; k++)
          if(rfg_ref_lin[rfg_inv_data_cell][rfg_type_lin][j][k]=='_')
            l=k;
        for(k=0L; k<l; k++)
          tmp_1[k]=rfg_ref_lin[rfg_inv_data_cell][rfg_type_lin][j][k];
        tmp_1[k]=0L;
        rfg_COPY_FLOAT("lin", NAME("%s[%d]", rfg_ref_lin[rfg_inv_data_cell][rfg_type_lin][j], i),
          NAME("%s[%d]%s", tmp_1, msb ? i : high-1-i, &rfg_ref_lin[rfg_inv_data_cell][rfg_type_lin][j][k]),
          WEST);
        }
      }
    }
#endif

  /***** SOUTH side. *****/
  if(rfg_cell_alims)
    for(i=0L;i<=rfg_nbr_block;i++)
      {
      name_block1=NAME("mla[%d]", i);
      COPY_UP_CON(0L, "vss", name_block1, "vss");
      COPY_UP_CON(0L, "vdd", name_block1, "vdd");
      }

  /***** EAST side. *****/
  if(hard_connectors)
    {
    for(i=0L;i<high;i++)
      {
      if(flip_flop)
        {
        rfg_HARDED_FLOAT("lou", NAME("out_a_5[%d]", i), NAME("out_a[%d]", msb ? i : high-1-i), EAST);
        if(n_bus)
          rfg_HARDED_FLOAT("lou", NAME("out_b_6[%d]", i), NAME("out_b[%d]", msb ? i : high-1-i), EAST);
        }
      else
        {
        rfg_HARDED_FLOAT("lou", NAME("out_a_5[%d]", i), NAME("out_a[%d]", msb ? i : high-1-i), EAST);
        if(n_bus)
          rfg_HARDED_FLOAT("lou", NAME("out_b_4[%d]", i), NAME("out_b[%d]", msb ? i : high-1-i), EAST);
        }
      }
    }

#ifdef rfg_floating_con
  else
    {
    if(flip_flop)
      n_ref=rfg_n_ref_latch[n_bus];
    else
      n_ref=rfg_n_ref_bleeder[rfg_type_lou][n_bus];
    for(i=0L;i<high;i++)
      {
      for(j=0L; j<n_ref; j++)
        {
        l=0L;
        if(flip_flop)
          {
          for(k=0L; rfg_ref_latch[n_bus][j][k]!='\0'; k++)
            if(rfg_ref_latch[n_bus][j][k]=='_')
              l=k;
          for(k=0L; k<l; k++)
          tmp_1[k]=rfg_ref_latch[n_bus][j][k];
          tmp_1[k]=0L;
          rfg_COPY_FLOAT("lou", NAME("%s[%d]", rfg_ref_latch[n_bus][j], i),
            NAME("%s[%d]%s", tmp_1, msb ? i : high-1-i, &rfg_ref_latch[n_bus][j][k]), EAST);
          }
        else
          {
          for(k=0L; rfg_ref_bleeder[rfg_type_lou][n_bus][j][k]!='\0'; k++)
            if(rfg_ref_bleeder[rfg_type_lou][n_bus][j][k]=='_')
              l=k;
          for(k=0L; k<l; k++)
          tmp_1[k]=rfg_ref_bleeder[rfg_type_lou][n_bus][j][k];
          tmp_1[k]=0L;
          rfg_COPY_FLOAT("lou", NAME("%s[%d]", rfg_ref_bleeder[rfg_type_lou][n_bus][j], i),
            NAME("%s[%d]%s", tmp_1, msb ? i : high-1-i, &rfg_ref_bleeder[rfg_type_lou][n_bus][j][k]), EAST);
          }
        }
      }
    }
#endif
  
  /***** NORTH side. *****/
  if (block_type!=rfg_bank)
    {
    for(i=0L;i<rfg_nbr_block_p;i++)
      for(j=0L;j<rfg_wblock;j++)
        {
        name_block1=NAME("mla[%d]", i);
        COPY_UP_CON(0L, NAME("w[%d]", j), name_block1, NAME("w[%d]", rfg_wblock*i+j));
        COPY_UP_CON(0L, NAME("r_a[%d]", j), name_block1, NAME("r_a[%d]", rfg_wblock*i+j));
        if(n_bus)
          COPY_UP_CON(0L, NAME("r_b[%d]", j), name_block1, NAME("r_b[%d]", rfg_wblock*i+j));
        }
    for(j=0L;j<rfg_width_f;j++)
      {
      name_block1=NAME("mla[%d]", i);
      COPY_UP_CON(0L, NAME("w[%d]", j), name_block1, NAME("w[%d]", rfg_wblock*i+j));
      COPY_UP_CON(0L, NAME("r_a[%d]", j), name_block1, NAME("r_a[%d]", rfg_wblock*i+j));
      if(n_bus)
        COPY_UP_CON(0L, NAME("r_b[%d]", j), name_block1, NAME("r_b[%d]", rfg_wblock*i+j));
      }

    if(rfg_nbr_block)
      for(i=0L;i<=rfg_nbr_block;i++)
        {
        name_block1=NAME("dou[%d]", i);
        COPY_UP_CON(0L, "s_a", name_block1, NAME("s_a[%d]", i));
        if(n_bus)
          COPY_UP_CON(0L, "s_b", name_block1, NAME("s_b[%d]", i));
        if(rfg_cell_alims)
          {
          name_block1=NAME("mla[%d]", i);
          COPY_UP_CON(1L, "vss", name_block1, "vss");
          COPY_UP_CON(1L, "vdd", name_block1, "vdd");
          }
        }

    if(flip_flop)
      {
      COPY_UP_CON(0L, "w_r_a", "lou", "w_r_a");
      if(n_bus)
        COPY_UP_CON(0L, "w_r_b", "lou", "w_r_b");
      }
    }

  /***** Place alims. *****/
  for(num_alims=0L;num_alims<=nbr_alims_reg;num_alims++) /* first alim is VSS */
    if(rfg_cell_alims)
      THRU_CON_H (ALU2, alim_width[num_alims&1],
             NAME("%s", alim_name[num_alims&1]),
             num_alims*rfg_hslice);
    else
      THRU_CON_H (ALU2, alim_width[num_alims&1],
             NAME("%s%d", alim_name[num_alims&1], num_alims),
             num_alims*rfg_hslice);

  PHSEG (ALU2, 28L, "vss", xmin+rfg_half_rules, ((num_alims-3)*rfg_hslice)+10L, xmax-rfg_half_rules, ((num_alims-3)*rfg_hslice)+10L);
  PHSEG (ALU2, 26L, "vdd", xmin+rfg_half_rules, ((num_alims-2)*rfg_hslice)+10L, xmax-rfg_half_rules, ((num_alims-2)*rfg_hslice)+10L);

  /***** Place NWELL segments. *****/
  for(num_alims=0L;num_alims<high;num_alims++)
    {
    if(rfg_nwell_reg>0L)
      {
      if(num_alims&1L)
        y=num_alims*rfg_hslice+rfg_nwell_reg/2L;
      else
        y=num_alims*rfg_hslice+rfg_hslice-rfg_nwell_reg/2L;
      THRU_H(NWELL, (rfg_nwell_reg+1L)&(~1L), y);
/*
      PHREF("ref_ref", NAME("nwell%d_%d", nwell_index++, (rfg_nwell_reg+1L)&(~1L)), xmin, y);
      PHREF("ref_ref", NAME("nwell%d_%d", nwell_index++, (rfg_nwell_reg+1L)&(~1L)), xmax, y);
*/

      if(num_alims&1L)
        y=num_alims*rfg_hslice+rfg_width_nwell/2L;
      else
        y=num_alims*rfg_hslice+rfg_hslice-rfg_width_nwell/2L;
      PHSEG (NWELL, rfg_width_nwell, "", xmin, y, xmin+2*rfg_half_rules, y);
      PHSEG (NWELL, rfg_width_nwell, "", xmax-2*rfg_half_rules, y, xmax, y);
      PHREF("ref_ref", NAME("nwell%d_%d", nwell_index++, (rfg_width_nwell+1L)&(~1L)), xmin, y);
      PHREF("ref_ref", NAME("nwell%d_%d", nwell_index++, (rfg_width_nwell+1L)&(~1L)), xmax, y);
      }
    }

  for(i=0L;num_alims<nbr_alims_reg;num_alims++, i++)
    {
    if(rfg_nwell_buf[i]>0L)
      {
      if(num_alims&1L)
        y=num_alims*rfg_hslice+rfg_nwell_buf[i]/2L;
      else
        y=num_alims*rfg_hslice+rfg_hslice-rfg_nwell_buf[i]/2L;
      THRU_H(NWELL, (rfg_nwell_buf[i]+1L)&(~1L), y);
      PHREF("ref_ref", NAME("nwell%d_%d", nwell_index++, (rfg_nwell_buf[i]+1L)&(~1L)), xmin, y);
      PHREF("ref_ref", NAME("nwell%d_%d", nwell_index++, (rfg_nwell_buf[i]+1L)&(~1L)), xmax, y);
      }
    }

  /***** Place complete transparency. *****/
  for(i=0L;i<high;i++)
    for(j=0L;j<rfg_nbr_tracks;j++)
      if(allow_reg[rfg_type_lou][n_bus][j]==1L)
        if(i&1L)
          THRU_H(TALU2, rfg_width_min_alu2, i*rfg_hslice+rfg_hslice-y_track[j]);
        else
          THRU_H(TALU2, rfg_width_min_alu2, i*rfg_hslice+y_track[j]);

  for(i=high;i<high+2L;i++)
    for(j=0L;j<rfg_nbr_tracks;j++)
      if(allow_buf[i-high][j]==1L)
        if(i&1L)
          THRU_H(TALU2, rfg_width_min_alu2, i*rfg_hslice+rfg_hslice-y_track[j]);
        else
          THRU_H(TALU2, rfg_width_min_alu2, i*rfg_hslice+y_track[j]);

  if(block_type!=rfg_bank)
    if(rfg_save_layout)
      {
      FLATTEN_ALL_PHINS(YES, NO);
      SAVE_PHFIG ();
      }
  }

/*******************************************************************/
/* Create decoders block.                                          */
/*******************************************************************/

if((block_type==rfg_dec_sep) || (block_type==rfg_bank))
  {
  /********** Place blocks. ***********/

  if(block_type==rfg_dec_sep)
    {
    DEF_PHFIG (NAME("%s", rfg_name_pref));
    PLACE (NAME("%s20", rfg_name_pref), "bsi", NOSYM, 0L, 0L);
    }
  else
    {
    DEF_PHINS ("lin");
    PLACE_TOP (NAME("%s20", rfg_name_pref), "bsi", NOSYM);
    }

  PLACE_TOP (NAME("%s30", rfg_name_pref), "blr_a", NOSYM);
  for(i=0L;i<rfg_nbr_block_p;i++)
    {
    PLACE_RIGHT  (NAME("%s32", rfg_name_pref), NAME("alr_a[%d]", i), NOSYM);
    PLACE_RIGHT  (NAME("%s34", rfg_name_pref), NAME("clr_a[%d]", i), NOSYM);
    PLACE_RIGHT  (NAME("%s36", rfg_name_pref), NAME("chr_a[%d]", i), NOSYM);
    rfg_prog_input   (NAME("chr_a[%d]", i), 0L, i, rfg_nand_h);
    DEF_PHINS    (NAME("clr_a[%d]", i));

    PLACE_BOTTOM (NAME("%s24", rfg_name_pref), NAME("bsl[%d]", i),   NOSYM);
    PLACE_RIGHT  (NAME("%s26", rfg_name_pref), NAME("bdo[%d]", i),   NOSYM);
    DEF_PHINS    (NAME("chr_a[%d]", i));
    }
  if(rfg_width_f)
    {
    PLACE_RIGHT  (NAME("%s32", rfg_name_pref), NAME("alr_a[%d]", i), NOSYM);
    PLACE_RIGHT  (NAME("%s35", rfg_name_pref), NAME("clr_a[%d]", i), NOSYM);
    PLACE_RIGHT  (NAME("%s36", rfg_name_pref), NAME("chr_a[%d]", i), NOSYM);
    rfg_prog_input   (NAME("chr_a[%d]", i), 0L, i, rfg_nand_h);
    DEF_PHINS    (NAME("clr_a[%d]", i));

    PLACE_BOTTOM (NAME("%s25", rfg_name_pref), NAME("bsl[%d]", i),   NOSYM);
    PLACE_RIGHT  (NAME("%s26", rfg_name_pref), NAME("bdo[%d]", i),   NOSYM);
    DEF_PHINS    (NAME("chr_a[%d]", i));
    }
  PLACE_RIGHT  (NAME("%s38", rfg_name_pref), "bhr_a", NOSYM);
  PLACE_BOTTOM (NAME("%s28", rfg_name_pref), "bso",   NOSYM);
  DEF_PHINS   ("blr_a");

  if(n_bus)
    {
    PLACE_TOP (NAME("%s40", rfg_name_pref), "blr_b", NOSYM);
    for(i=0L;i<rfg_nbr_block_p;i++)
      {
      PLACE_RIGHT (NAME("%s42", rfg_name_pref), NAME("alr_b[%d]", i), NOSYM);
      PLACE_RIGHT (NAME("%s44", rfg_name_pref), NAME("clr_b[%d]", i), NOSYM);
      PLACE_RIGHT (NAME("%s46", rfg_name_pref), NAME("chr_b[%d]", i), NOSYM);
      rfg_prog_input  (NAME("chr_b[%d]", i), 0L, i, rfg_nand_h);
      }
    if(rfg_width_f)
      {
      PLACE_RIGHT (NAME("%s42", rfg_name_pref), NAME("alr_b[%d]", i), NOSYM);
      PLACE_RIGHT (NAME("%s45", rfg_name_pref), NAME("clr_b[%d]", i), NOSYM);
      PLACE_RIGHT (NAME("%s46", rfg_name_pref), NAME("chr_b[%d]", i), NOSYM);
      rfg_prog_input  (NAME("chr_b[%d]", i), 0L, i, rfg_nand_h);
      }
    PLACE_RIGHT (NAME("%s48", rfg_name_pref), "bhr_b", NOSYM);
    DEF_PHINS   ("blr_b");
    }

  PLACE_TOP (NAME("%s50", rfg_name_pref), "blw", NOSYM);
  for(i=0L;i<rfg_nbr_block_p;i++)
    {
    PLACE_RIGHT (NAME("%s52", rfg_name_pref), NAME("alw[%d]", i), NOSYM);
    PLACE_RIGHT (NAME("%s54", rfg_name_pref), NAME("clw[%d]", i), NOSYM);
    PLACE_RIGHT (NAME("%s56", rfg_name_pref), NAME("chw[%d]", i), NOSYM);
    rfg_prog_input  (NAME("chw[%d]", i), 0L, i, rfg_nand_h);
    }
  if(rfg_width_f)
    {
    PLACE_RIGHT (NAME("%s53", rfg_name_pref), NAME("alw[%d]", i), NOSYM);
    PLACE_RIGHT (NAME("%s55", rfg_name_pref), NAME("clw[%d]", i), NOSYM);
    PLACE_RIGHT (NAME("%s57", rfg_name_pref), NAME("chw[%d]", i), NOSYM);
    rfg_prog_input  (NAME("chw[%d]", i), 0L, i, rfg_nand_h);
    }
  PLACE_RIGHT (NAME("%s58", rfg_name_pref), "bhw", NOSYM);

  DEF_AB (-rfg_half_rules, 0L, rfg_half_rules, 0L);

  if(block_type==rfg_dec_sep) /* first alim is VSS */
    nbr_alims_dec=HEIGHT(NAME("%s", rfg_name_pref))/rfg_hslice;
  else /* first alim already exist and number start at end of register alims */
    nbr_alims_dec=HEIGHT(NAME("%s", rfg_name_pref))/rfg_hslice-nbr_alims_reg;

  if(hard_connectors)
    DEF_AB (-rfg_half_rules, -(alim_width[0L]>>1)-rfg_half_rules,
      rfg_half_rules, (alim_width[nbr_alims_dec&1]>>1)+rfg_half_rules);

  xmin= -rfg_half_rules;
  xmax=WIDTH(NAME("%s", rfg_name_pref))-rfg_half_rules;

  /********** Define external interface. **********/

  /***** WEST and EAST sides. *****/
  COPY_UP_CON (0L, "ck_m", "bsl[0]", "ck_m");
  COPY_UP_CON (1L, "ck_m", "bsl[0]", "ck_m");

  for(i=rfg_nand_h+1; i<=rfg_addr_size; i++)
    {
    COPY_UP_CON   (0L, NAME("ad_r_a[%d]", i), "alr_a[0]", NAME("ad_r_a[%d]", i));
    COPY_UP_CON   (1L, NAME("ad_r_a[%d]", i), "alr_a[0]", NAME("ad_r_a[%d]", i));
    if(n_bus)
      {
      COPY_UP_CON (0L, NAME("ad_r_b[%d]", i), "alr_b[0]", NAME("ad_r_b[%d]", i));
      COPY_UP_CON (1L, NAME("ad_r_b[%d]", i), "alr_b[0]", NAME("ad_r_b[%d]", i));
      }
    COPY_UP_CON   (0L, NAME("ad_w[%d]", i), "alw[0]", NAME("ad_w[%d]", i));
    COPY_UP_CON   (1L, NAME("ad_w[%d]", i), "alw[0]", NAME("ad_w[%d]", i));
    }

  if(write_enable)
    {
    COPY_UP_CON (0L, "we", "alw[0]", "we");
    COPY_UP_CON (1L, "we", "alw[0]", "we");
    }

  for(i=0; i<=rfg_nand_h; i++)
    {
    COPY_UP_CON   (0L, NAME("ad_r_a[%d]", i), NAME("chr_a[%d]", rfg_nbr_block), NAME("ad_r_a[%d]", i));
    COPY_UP_CON   (1L, NAME("ad_r_a[%d]", i), NAME("chr_a[%d]", rfg_nbr_block), NAME("ad_r_a[%d]", i));
    if(n_bus)
      {
      COPY_UP_CON (0L, NAME("ad_r_b[%d]", i), NAME("chr_b[%d]", rfg_nbr_block), NAME("ad_r_b[%d]", i));
      COPY_UP_CON (1L, NAME("ad_r_b[%d]", i), NAME("chr_b[%d]", rfg_nbr_block), NAME("ad_r_b[%d]", i));
      }
    COPY_UP_CON   (0L, NAME("ad_w[%d]", i), NAME("chw[%d]", rfg_nbr_block), NAME("ad_w[%d]", i));
    COPY_UP_CON   (1L, NAME("ad_w[%d]", i), NAME("chw[%d]", rfg_nbr_block), NAME("ad_w[%d]", i));
    }

  if(!msb)
    {
    REVERSE_PHCON("ad_r_a");
    if(n_bus)
      REVERSE_PHCON("ad_r_b");
    REVERSE_PHCON("ad_w");
    }

  /***** SOUTH side. *****/
  if(block_type==rfg_dec_sep)
    {
    for(i=0L;i<rfg_nbr_block_p;i++)
      for(j=0L;j<rfg_wblock;j++)
        {
        name_block1=NAME("bsl[%d]", i);
        COPY_UP_CON (0L, NAME("w[%d]", j), name_block1, NAME("w[%d]", rfg_wblock*i+j));
        COPY_UP_CON (0L, NAME("r_a[%d]", j), name_block1, NAME("r_a[%d]", rfg_wblock*i+j));
        if(n_bus)
          COPY_UP_CON (0L, NAME("r_b[%d]", j), name_block1, NAME("r_b[%d]", rfg_wblock*i+j));
        }
    for(j=0L;j<rfg_width_f;j++)
      {
      name_block1=NAME("bsl[%d]", i);
      COPY_UP_CON (0L, NAME("w[%d]", j), name_block1, NAME("w[%d]", rfg_wblock*i+j));
      COPY_UP_CON (0L, NAME("r_a[%d]", j), name_block1, NAME("r_a[%d]", rfg_wblock*i+j));
      if(n_bus)
        COPY_UP_CON (0L, NAME("r_b[%d]", j), name_block1, NAME("r_b[%d]", rfg_wblock*i+j));
      }

    if(rfg_nbr_block)
      for(i=0L;i<=rfg_nbr_block;i++)
        {
        name_block1=NAME("bdo[%d]", i);
        COPY_UP_CON (0L, "s_a", name_block1, NAME("s_a[%d]", i));
        if(n_bus)
          COPY_UP_CON (0L, "s_b", name_block1, NAME("s_b[%d]", i));
        if(rfg_cell_alims)
          {
          name_block1=NAME("bsl[%d]", i);
          COPY_UP_CON(0L, "vss", name_block1, "vss");
          COPY_UP_CON(0L, "vdd", name_block1, "vdd");
          }
        }

    if(flip_flop)
      {
      COPY_UP_CON(0L, "w_r_a", "bso", "w_r_a");
      if(n_bus)
        COPY_UP_CON(0L, "w_r_b", "bso", "w_r_b");
      }
    }

  /***** NORTH side. *****/
  if(rfg_cell_alims)
    for(i=0L;i<=rfg_nbr_block;i++)
      {
      name_block1=NAME("clw[%d]", i);
      COPY_UP_CON(0L, "vss",  name_block1, "vss");
      COPY_UP_CON(0L, "ck_m", name_block1, "ck_m");
      COPY_UP_CON(0L, "vdd",  name_block1, "vdd");
      }

  /***** Place alims. *****/
  if(block_type==rfg_dec_sep) /* first alim is VSS */
    {
    for(num_alims=0L;num_alims<=nbr_alims_dec;num_alims++)
      if(rfg_cell_alims)
        THRU_CON_H (ALU2, alim_width[num_alims&1],
          NAME("%s", alim_name[num_alims&1]), num_alims*rfg_hslice);
      else
        THRU_CON_H (ALU2, alim_width[num_alims&1],
          NAME("%s%d", alim_name[num_alims&1], num_alims), num_alims*rfg_hslice);
    }
  else /* first alim already exist and number start at end of register alims */
    {
    for(num_alims=nbr_alims_reg+1L;num_alims<=nbr_alims_reg+nbr_alims_dec;
        num_alims++)
      if(rfg_cell_alims)
        THRU_CON_H (ALU2, alim_width[num_alims&1],
          NAME("%s", alim_name[num_alims&1]), num_alims*rfg_hslice);
      else
        THRU_CON_H (ALU2, alim_width[num_alims&1],
          NAME("%s%d", alim_name[num_alims&1], num_alims), num_alims*rfg_hslice);
    }

  /***** Place NWELL segments. *****/
  if(block_type==rfg_dec_sep)
    i=0L;
  else
    i=nbr_alims_reg;

  /***** for this parts nwell begin at 0 outside of cell *****/
  if(rfg_nwell_int>0L)
    {
    if(i&1L)
      y=i*rfg_hslice+rfg_nwell_int/2L;
    else
      y=i*rfg_hslice+rfg_hslice-rfg_nwell_int/2L;
    THRU_H(NWELL, (rfg_nwell_int+1L)&(~1L), y);
    PHREF("ref_ref", NAME("nwell%d_%d", nwell_index++, (rfg_nwell_int+1L)&(~1L)), xmin, y);
    PHREF("ref_ref", NAME("nwell%d_%d", nwell_index++, (rfg_nwell_int+1L)&(~1L)), xmax, y);
    }
  i++;

  n_slice=1L+low_power;
  if(rfg_addr_size>1L)
    n_slice++;
  for(k=0; k<=n_bus; k++)
    for(j=0L; j<n_slice; i++, j++)
      {
      if(rfg_nwell_dec_r[k][j]>0L)
        {
        if(i&1L)
          y=i*rfg_hslice+rfg_nwell_dec_r[k][j]/2L;
        else
          y=i*rfg_hslice+rfg_hslice-rfg_nwell_dec_r[k][j]/2L;
        THRU_H(NWELL, (rfg_nwell_dec_r[k][j]+1L)&(~1L), y);
        PHREF("ref_ref", NAME("nwell%d_%d", nwell_index++, (rfg_nwell_dec_r[k][j]+1L)&(~1L)), xmin, y);
        PHREF("ref_ref", NAME("nwell%d_%d", nwell_index++, (rfg_nwell_dec_r[k][j]+1L)&(~1L)), xmax, y);
        }
      }

  n_slice=2L;
  if(rfg_addr_size>1L)
    n_slice++;
  /***** for this part nwell begin at 2 outside of cell *****/
  for(j=0L; j<n_slice; i++, j++)
    {
    if(rfg_nwell_dec_w[j]>0L)
      {
      if(i&1L)
        y=i*rfg_hslice+rfg_nwell_dec_w[j]/2L-1L;
      else
        y=i*rfg_hslice+rfg_hslice-rfg_nwell_dec_w[j]/2L+1L;
      THRU_H(NWELL, (rfg_nwell_dec_w[j]+3L)&(~1L), y);
      PHREF("ref_ref", NAME("nwell%d_%d", nwell_index++, (rfg_nwell_dec_w[j]+3L)&(~1L)), xmin, y);
      PHREF("ref_ref", NAME("nwell%d_%d", nwell_index++, (rfg_nwell_dec_w[j]+3L)&(~1L)), xmax, y);
      }
    }

  /***** Place complete transparency. *****/
  if(block_type==rfg_dec_sep)
    i=0L;
  else
    i=nbr_alims_reg;

  for(j=0L; j<rfg_nbr_tracks; j++)
    if(allow_int[j]==1L)
      if(i&1L)
        THRU_H(TALU2, rfg_width_min_alu2, i*rfg_hslice+rfg_hslice-y_track[j]);
      else
        THRU_H(TALU2, rfg_width_min_alu2, i*rfg_hslice+y_track[j]);
  i++;

  if(low_power)
    {
    for(j=0L; j<rfg_nbr_tracks; j++)
      if(allow_lp[j]==1L)
        if(i&1L)
          THRU_H(TALU2, rfg_width_min_alu2, i*rfg_hslice+rfg_hslice-y_track[j]);
        else
          THRU_H(TALU2, rfg_width_min_alu2, i*rfg_hslice+y_track[j]);
    i++;
    }

  if(rfg_addr_size>1L)
    n_slice=2L;
  else
    n_slice=1L;

  for(k=0; k<n_slice; i++, k++)
    {
    for(j=0L; j<rfg_nbr_tracks; j++)
      if(allow_nand[j]==1L)
        if(i&1L)
          THRU_H(TALU2, rfg_width_min_alu2, i*rfg_hslice+rfg_hslice-y_track[j]);
        else
          THRU_H(TALU2, rfg_width_min_alu2, i*rfg_hslice+y_track[j]);
    }

  if(n_bus)
    {
    if(low_power)
      {
      for(j=0L; j<rfg_nbr_tracks; j++)
        if(allow_lp[j]==1L)
          if(i&1L)
            THRU_H(TALU2, rfg_width_min_alu2, i*rfg_hslice+rfg_hslice-y_track[j]);
          else
            THRU_H(TALU2, rfg_width_min_alu2, i*rfg_hslice+y_track[j]);
      i++;
      }

    for(k=0; k<n_slice; i++, k++)
      {
      for(j=0L; j<rfg_nbr_tracks; j++)
        if(allow_nand[j]==1L)
          if(i&1L)
            THRU_H(TALU2, rfg_width_min_alu2, i*rfg_hslice+rfg_hslice-y_track[j]);
          else
            THRU_H(TALU2, rfg_width_min_alu2, i*rfg_hslice+y_track[j]);
      }
    }

  for(j=0L; j<rfg_nbr_tracks; j++)
    if(allow_we[j]==1L)
      if(i&1L)
        THRU_H(TALU2, rfg_width_min_alu2, i*rfg_hslice+rfg_hslice-y_track[j]);
      else
        THRU_H(TALU2, rfg_width_min_alu2, i*rfg_hslice+y_track[j]);
  i++;

  for(k=0; k<n_slice; i++, k++)
    {
    for(j=0L; j<rfg_nbr_tracks; j++)
      if(allow_nand[j]==1L)
        if(i&1L)
          THRU_H(TALU2, rfg_width_min_alu2, i*rfg_hslice+rfg_hslice-y_track[j]);
        else
          THRU_H(TALU2, rfg_width_min_alu2, i*rfg_hslice+y_track[j]);
    }

  if(rfg_save_layout)
    {
    FLATTEN_ALL_PHINS(YES, NO);
    SAVE_PHFIG ();
    }
  }
}

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