VPR-6.0

vpr/SRC/pack/ff_pack.c

Go to the documentation of this file.
00001 #include <assert.h>
00002 #include <stdio.h>
00003 #include <string.h>
00004 #include "util.h"
00005 #include "vpr_types.h"
00006 #include "globals.h"
00007 #include "ff_pack.h"
00008 
00009 /** This routine uses a simple pattern matching algorithm to remove buffer LUTs where possible (single-input LUTs that are programmed to be a wire) */
00010 void absorb_buffer_luts() {
00011 
00012         int bnum, in_blk, out_blk, ipin, out_net, in_net;
00013         int removed = 0;
00014 
00015         /* Pin ordering for the clb blocks (1 VPACK_LUT + 1 FF in each logical_block) is      *
00016         * output, n VPACK_LUT inputs, clock input.                                   */
00017 
00018         for (bnum=0;bnum<num_logical_blocks;bnum++) {
00019                 if (strcmp(logical_block[bnum].model->name, "names") == 0) {
00020                         if(logical_block[bnum].truth_table != NULL && logical_block[bnum].truth_table->data_vptr) {
00021                                 if(strcmp("0 0", (char*)logical_block[bnum].truth_table->data_vptr) == 0 ||
00022                                         strcmp("1 1", (char*)logical_block[bnum].truth_table->data_vptr) == 0)
00023                                 {
00024                                         for(ipin = 0; ipin < logical_block[bnum].model->inputs->size; ipin++) {
00025                                                 if(logical_block[bnum].input_nets[0][ipin] == OPEN)
00026                                                         break;
00027                                         }
00028                                         assert(ipin == 1);
00029 
00030                                         assert(logical_block[bnum].clock_net == OPEN);
00031                                         assert(logical_block[bnum].model->inputs->next == NULL);
00032                                         assert(logical_block[bnum].model->outputs->size == 1);
00033                                         assert(logical_block[bnum].model->outputs->next == NULL);
00034                                         
00035                                         in_net = logical_block[bnum].input_nets[0][0];   /* Net driving the buffer */
00036                                         out_net = logical_block[bnum].output_nets[0][0];   /* Net the buffer us driving */
00037                                         out_blk = vpack_net[out_net].node_block[1];
00038                                         in_blk = vpack_net[in_net].node_block[0];
00039 
00040                                         assert(in_net != OPEN);
00041                                         assert(out_net != OPEN);
00042                                         assert(out_blk != OPEN);
00043                                         assert(in_blk != OPEN);
00044                                         
00045                                         /* TODO: Make this handle general cases, due to time reasons I can only handle buffers with single outputs */
00046                                         if (vpack_net[out_net].num_sinks == 1) {
00047                                                 for(ipin = 1; ipin <= vpack_net[in_net].num_sinks; ipin++) {
00048                                                         if(vpack_net[in_net].node_block[ipin] == bnum) {
00049                                                                 break;
00050                                                         }
00051                                                 }
00052                                                 assert(ipin <= vpack_net[in_net].num_sinks);
00053                                                  
00054                                                 vpack_net[in_net].node_block[ipin] = vpack_net[out_net].node_block[1];  /* New output */
00055                                                 vpack_net[in_net].node_block_port[ipin] = vpack_net[out_net].node_block_port[1];
00056                                                 vpack_net[in_net].node_block_pin[ipin] = vpack_net[out_net].node_block_pin[1];
00057 
00058                                                 assert(logical_block[out_blk].input_nets[vpack_net[out_net].node_block_port[1]][vpack_net[out_net].node_block_pin[1]] == out_net);
00059                                                 logical_block[out_blk].input_nets[vpack_net[out_net].node_block_port[1]][vpack_net[out_net].node_block_pin[1]] = in_net;
00060                                                 
00061                                                 vpack_net[out_net].node_block[0] = OPEN; /* This vpack_net disappears; mark. */
00062                                                 vpack_net[out_net].node_block_pin[0] = OPEN; /* This vpack_net disappears; mark. */
00063                                                 vpack_net[out_net].node_block_port[0] = OPEN; /* This vpack_net disappears; mark. */
00064                                                 vpack_net[out_net].num_sinks = 0; /* This vpack_net disappears; mark. */
00065                                                 
00066                                                 logical_block[bnum].type = VPACK_EMPTY;   /* Mark logical_block that had LUT */
00067                                                 
00068                                                 /* error checking */
00069                                                 for (ipin=0;ipin<=vpack_net[out_net].num_sinks;ipin++) {
00070                                                         assert(vpack_net[out_net].node_block[ipin] != bnum);
00071                                                 }
00072                                                 removed++;
00073                                         }
00074                                 }
00075                         }
00076                 }
00077         }
00078         printf("Removed %d LUT buffers \n", removed);
00079 }
00080 
00081 /** This routine removes all the VPACK_EMPTY blocks and OPEN nets that 
00082  * may have been created by the ff_pack routine.  After this    
00083  * routine, all the VPACK_LUT+FF blocks that exist in the netlist     
00084  * are in a contiguous list with no unused spots.  The same     
00085  * goes for the list of nets.  This means that blocks and nets  
00086  * have to be renumbered somewhat.                              
00087  */
00088 void compress_netlist () {
00089  int inet, iblk, index, ipin, new_num_nets, new_num_blocks, i;
00090  int *net_remap, *block_remap;
00091  int num_nets;
00092  t_model_ports *port;
00093  struct s_linked_vptr *tvptr, *next;
00094 
00095  new_num_nets = 0;
00096  new_num_blocks = 0;
00097  net_remap = my_malloc (num_logical_nets * sizeof(int));
00098  block_remap = my_malloc (num_logical_blocks * sizeof(int));
00099 
00100  for (inet=0;inet<num_logical_nets;inet++) {
00101          if (vpack_net[inet].node_block[0] != OPEN) {
00102        net_remap[inet] = new_num_nets;
00103        new_num_nets++;
00104     }
00105     else {
00106        net_remap[inet] = OPEN;
00107     }
00108  }
00109 
00110  for (iblk=0;iblk<num_logical_blocks;iblk++) {
00111     if (logical_block[iblk].type != VPACK_EMPTY) {
00112        block_remap[iblk] = new_num_blocks;
00113        new_num_blocks++;
00114     }
00115     else {
00116        block_remap[iblk] = OPEN;
00117     }
00118  }
00119 
00120  
00121  if (new_num_nets != num_logical_nets || new_num_blocks != num_logical_blocks) {
00122 
00123     for (inet=0;inet<num_logical_nets;inet++) {
00124                 if (vpack_net[inet].node_block[0] != OPEN) {
00125           index = net_remap[inet];
00126           vpack_net[index] = vpack_net[inet];
00127                   for (ipin = 0; ipin <= vpack_net[index].num_sinks; ipin++) 
00128                   {
00129                           vpack_net[index].node_block[ipin] = block_remap[vpack_net[index].node_block[ipin]];
00130                   }
00131        }
00132        else {
00133           free (vpack_net[inet].name);
00134                   free (vpack_net[inet].node_block);
00135                   free (vpack_net[inet].node_block_port);
00136                   free (vpack_net[inet].node_block_pin);
00137        }
00138     }
00139   
00140     num_logical_nets = new_num_nets;
00141     vpack_net = (struct s_net *) my_realloc (vpack_net, 
00142              num_logical_nets * sizeof (struct s_net));
00143 
00144     for (iblk=0;iblk<num_logical_blocks;iblk++) {
00145        if (logical_block[iblk].type != VPACK_EMPTY) {
00146           index = block_remap[iblk];
00147                   if(index != iblk) {
00148                         logical_block[index] = logical_block[iblk];
00149                   }
00150 
00151                   num_nets = 0;
00152                   port = logical_block[index].model->inputs;
00153                   while(port) {
00154                           for(ipin = 0; ipin < port->size; ipin++) {
00155                                   if(port->is_clock) {
00156                                           assert(port->size == 1 && port->index == 0 && ipin == 0);
00157                                           if(logical_block[index].clock_net == OPEN)
00158                                                 continue;
00159                                           logical_block[index].clock_net =
00160                                                 net_remap[logical_block[index].clock_net];
00161                                   } else {
00162                                         if(logical_block[index].input_nets[port->index][ipin] == OPEN)
00163                                           continue;
00164                                         logical_block[index].input_nets[port->index][ipin] =
00165                                                 net_remap[logical_block[index].input_nets[port->index][ipin]];
00166                                   }
00167                                 num_nets++;
00168                   }
00169                           port = port->next;
00170                   }
00171 
00172                   port = logical_block[index].model->outputs;
00173                   while(port) {
00174                           for(ipin = 0; ipin < port->size; ipin++) {
00175                                   if(logical_block[index].output_nets[port->index][ipin] == OPEN)
00176                                           continue;
00177                                 logical_block[index].output_nets[port->index][ipin] =
00178                                         net_remap[logical_block[index].output_nets[port->index][ipin]];
00179                                 num_nets++;
00180                   }
00181                           port = port->next;
00182                   }
00183        }
00184 
00185        else {
00186                         free (logical_block[iblk].name);
00187                         port = logical_block[iblk].model->inputs;
00188                         i = 0;
00189                         while(port) {
00190                                 if(!port->is_clock) {
00191                                         if(logical_block[iblk].input_nets) {
00192                                                 if(logical_block[iblk].input_nets[i]) {
00193                                                         free(logical_block[iblk].input_nets[i]);
00194                                                         logical_block[iblk].input_nets[i] = NULL;
00195                                                 }
00196                                         }
00197                                         i++;
00198                                 }
00199                                 port = port->next;
00200                         }
00201                         if(logical_block[iblk].input_nets)
00202                                 free(logical_block[iblk].input_nets);
00203                         port = logical_block[iblk].model->outputs;
00204                         i = 0;
00205                         while(port) {
00206                                 if(logical_block[iblk].output_nets) {
00207                                         if(logical_block[iblk].output_nets[i]) {
00208                                                 free(logical_block[iblk].output_nets[i]);
00209                                                 logical_block[iblk].output_nets[i] = NULL;
00210                                         }
00211                                 }
00212                                 i++;
00213                                 port = port->next;
00214                         }
00215                         if(logical_block[iblk].output_nets)
00216                                 free(logical_block[iblk].output_nets);
00217                         tvptr = logical_block[iblk].truth_table;
00218                         while(tvptr != NULL) {
00219                                 if(tvptr->data_vptr)
00220                                         free(tvptr->data_vptr);
00221                                 next = tvptr->next;
00222                                 free(tvptr);
00223                                 tvptr = next;
00224                         }
00225        }
00226     }
00227 
00228         printf("Sweeped away %d nodes\n", num_logical_blocks - new_num_blocks);
00229 
00230     num_logical_blocks = new_num_blocks;
00231     logical_block = (struct s_logical_block *) my_realloc (logical_block, 
00232               num_logical_blocks * sizeof (struct s_logical_block));
00233  }
00234 
00235 /* Now I have to recompute the number of primary inputs and outputs, since *
00236  * some inputs may have been unused and been removed.  No real need to     *
00237  * recount primary outputs -- it's just done as defensive coding.          */
00238 
00239  num_p_inputs = 0;
00240  num_p_outputs = 0;
00241  
00242  for (iblk=0;iblk<num_logical_blocks;iblk++) {
00243     if (logical_block[iblk].type == VPACK_INPAD) 
00244        num_p_inputs++;
00245     else if (logical_block[iblk].type == VPACK_OUTPAD) 
00246        num_p_outputs++;
00247  }
00248  
00249  
00250  free (net_remap);
00251  free (block_remap);
00252 }
00253 
00254 /** Looks through all the logical_block to find and mark all the clocks, by setting 
00255  * the corresponding entry in is_clock to true.  global_clocks is used     
00256  * only for an error check.                                                
00257  */
00258 boolean *alloc_and_load_is_clock (boolean global_clocks) {
00259 
00260         int num_clocks, bnum, clock_net;
00261         boolean *is_clock;
00262 
00263         num_clocks = 0;
00264 
00265         is_clock = (boolean *) my_calloc (num_logical_nets, sizeof(boolean));
00266 
00267         /* Want to identify all the clock nets.  */
00268 
00269         for (bnum=0;bnum<num_logical_blocks;bnum++) {
00270                 if(logical_block[bnum].type == VPACK_LATCH) {
00271                         clock_net = logical_block[bnum].clock_net;
00272                         assert(clock_net != OPEN);
00273                         if (is_clock[clock_net] == FALSE) {
00274                                 is_clock[clock_net] = TRUE;
00275                                 num_clocks++;
00276                         }
00277                 } else {
00278                         if(logical_block[bnum].clock_net != OPEN) {
00279                                 clock_net = logical_block[bnum].clock_net;
00280                                 if (is_clock[clock_net] == FALSE) {
00281                                         is_clock[clock_net] = TRUE;
00282                                         num_clocks++;
00283                                 }
00284                         }
00285                 }
00286         }
00287 
00288         /* If we have multiple clocks and we're supposed to declare them global, *
00289         * print a warning message, since it looks like this circuit may have    *
00290         * locally generated clocks.                                             */
00291 
00292         if (num_clocks > 1 && global_clocks) {
00293                 printf("Warning:  circuit contains %d clocks.\n", num_clocks);
00294                 printf("          All will be marked global.\n");
00295         }
00296 
00297         return (is_clock);
00298 }