VPR-6.0
|
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 }