VPR-6.0

vpr/SRC/base/check_netlist.c

Go to the documentation of this file.
00001 #include <stdio.h>
00002 #include <string.h>
00003 
00004 #include "util.h"
00005 #include "vpr_types.h"
00006 #include "globals.h"
00007 #include "hash.h"
00008 #include "vpr_utils.h"
00009 #include "check_netlist.h"
00010 #include "assert.h"
00011 #include "read_xml_arch_file.h"
00012 
00013 #define ERROR_THRESHOLD 100
00014 
00015 /**************** Subroutines local to this module **************************/
00016 
00017 static int check_connections_to_global_clb_pins(int inet);
00018 
00019 static int check_for_duplicated_names(void);
00020 
00021 static int check_clb_conn(int iblk,
00022                          int num_conn);
00023 
00024 static int check_clb_internal_nets(int iblk);
00025 
00026 static int check_subblock_internal_nets(int iblk, int isub);
00027 
00028 static void check_for_multiple_sink_connections(void);
00029 
00030 static int get_num_conn(int bnum);
00031 
00032 static int check_subblocks(int iblk);
00033 
00034 static int check_primitives(int iblk, int isub);
00035 
00036 
00037 /*********************** Subroutine definitions *****************************/
00038 
00039 /** This routine checks that the netlist makes sense.         */
00040 void
00041 check_netlist()
00042 {
00043     int i, error, num_conn;
00044         int net_count;
00045         struct s_hash **net_hash_table, *h_net_ptr;
00046     
00047     net_hash_table = alloc_hash_table();
00048 
00049         net_count = 0;
00050 
00051     error = 0;
00052 
00053         /* Check that nets fanout and have a driver. */
00054     for(i = 0; i < num_nets; i++)
00055         {
00056             h_net_ptr = insert_in_hash_table(net_hash_table, clb_net[i].name, i);
00057                 if(h_net_ptr->count != 1) {
00058                         printf(ERRTAG "net %s has multiple drivers.\n", clb_net[i].name);
00059                     error++;
00060                 }
00061             error += check_connections_to_global_clb_pins(i);
00062                 if(error >= ERROR_THRESHOLD) {
00063                         printf("Too many errors in netlist, exiting\n");
00064                         exit(1);
00065                 }
00066         }
00067         free_hash_table(net_hash_table);
00068 
00069 /* Check that each block makes sense. */
00070     for(i = 0; i < num_blocks; i++)
00071         {
00072             num_conn = get_num_conn(i);
00073             error += check_clb_conn(i, num_conn);
00074                 error += check_clb_internal_nets(i);
00075             error += check_subblocks(i);
00076                 if(error >= ERROR_THRESHOLD) {
00077                         printf("Too many errors in netlist, exiting\n");
00078                         exit(1);
00079                 }
00080         }
00081 
00082     error += check_for_duplicated_names();
00083 
00084     if(error != 0)
00085         {
00086             printf("Found %d fatal Errors in the input netlist.\n", error);
00087             exit(1);
00088         }
00089 
00090         /* HACK: Jason Luu January 17, 2011 Do not route common constants gnd and vcc
00091            Todo: Need to make architecture driven.
00092         */
00093         for(i = 0; i < num_nets; i++)
00094         {
00095                 if(strcmp(clb_net[i].name, "vcc") == 0) {
00096                         clb_net[i].is_global = TRUE;
00097                 } else if(strcmp(clb_net[i].name, "gnd") == 0) {
00098                         clb_net[i].is_global = TRUE;
00099                 }
00100         }
00101 }
00102 
00103 
00104 
00105 /** Checks that a global net (inet) connects only to global CLB input pins  
00106  * and that non-global nets never connects to a global CLB pin.  Either    
00107  * global or non-global nets are allowed to connect to pads.               
00108  */
00109 static int
00110 check_connections_to_global_clb_pins(int inet)
00111 {
00112     int ipin, num_pins, iblk, node_block_pin, error;
00113 
00114     num_pins = (clb_net[inet].num_sinks + 1);
00115     error = 0;
00116 
00117 /* For now global signals can be driven by an I/O pad or any CLB output       *
00118  * although a CLB output generates a warning.  I could make a global CLB      *
00119  * output pin type to allow people to make architectures that didn't have     *
00120  * this warning.                                                              */
00121 
00122     for(ipin = 0; ipin < num_pins; ipin++)
00123         {
00124             iblk = clb_net[inet].node_block[ipin];
00125 
00126             node_block_pin = clb_net[inet].node_block_pin[ipin];
00127 
00128             if(block[iblk].type->is_global_pin[node_block_pin] !=
00129                clb_net[inet].is_global && block[iblk].type != IO_TYPE)
00130                 {
00131 
00132                     /* Allow a CLB output pin to drive a global net (warning only). */
00133 
00134                     if(ipin == 0 && clb_net[inet].is_global)
00135                         {
00136                             printf
00137                                 (WARNTAG "in check_connections_to_global_clb_pins:\n"
00138                                  "\tnet #%d (%s) is driven by CLB output pin (#%d)\n"
00139                                  "\ton block #%d (%s).\n", inet,
00140                                  clb_net[inet].name, node_block_pin, iblk,
00141                                  block[iblk].name);
00142                         }
00143                     else
00144                         {       /* Otherwise -> Error */
00145                             printf
00146                                 (ERRTAG "in check_connections_to_global_clb_pins:\n"
00147                                  "\tpin %d on net #%d (%s) connects to CLB input pin (#%d)\n"
00148                                  "\ton block #%d (%s).\n", ipin, inet,
00149                                  clb_net[inet].name, node_block_pin, iblk,
00150                                  block[iblk].name);
00151                             error++;
00152                         }
00153 
00154                     if(clb_net[inet].is_global)
00155                                 printf("\tNet is global, but CLB pin is not.\n\n");
00156                     else
00157                                 printf("\tCLB pin is global, but net is not.\n\n");
00158                 }
00159         }                       /* End for all pins */
00160 
00161     return (error);
00162 }
00163 
00164 
00165 /** Checks that the connections into and out of the clb make sense.  */
00166 static int
00167 check_clb_conn(int iblk,
00168               int num_conn)
00169 {
00170     int iclass, ipin, error;
00171     t_type_ptr type;
00172 
00173     error = 0;
00174     type = block[iblk].type;
00175 
00176     if(type == IO_TYPE)
00177         {
00178             if(num_conn != 1)
00179                 {
00180                     printf(ERRTAG "io blk #%d (%s) has %d pins.\n",
00181                            iblk, block[iblk].name, num_conn);
00182                     error++;
00183                 }
00184         }
00185     else if(num_conn < 2)
00186         {
00187             printf(WARNTAG "logic block #%d (%s) has only %d pin.\n",
00188                    iblk, block[iblk].name, num_conn);
00189 
00190 /* Allow the case where we have only one OUTPUT pin connected to continue. *
00191  * This is used sometimes as a constant generator for a primary output,    *
00192  * but I will still warn the user.  If the only pin connected is an input, *
00193  * abort.                                                                  */
00194 
00195             if(num_conn == 1)
00196                 {
00197                     for(ipin = 0; ipin < type->num_pins; ipin++)
00198                         {
00199                             if(block[iblk].nets[ipin] != OPEN)
00200                                 {
00201                                     iclass = type->pin_class[ipin];
00202 
00203                                     if(type->class_inf[iclass].type != DRIVER)
00204                                         {
00205                                             error++;
00206                                         }
00207                                     else
00208                                         {
00209                                             printf
00210                                                 ("\tPin is an output -- may be a constant generator.\n"
00211                                                  "\tNon-fatal, but check this.\n");
00212                                         }
00213 
00214                                     break;
00215                                 }
00216                         }
00217                 }
00218             else
00219                 {
00220                     error++;
00221                 }
00222         }
00223 
00224 /* This case should already have been flagged as an error -- this is *
00225  * just a redundant double check.                                    */
00226 
00227     if(num_conn > type->num_pins)
00228         {
00229             printf(ERRTAG "logic block #%d with output %s has %d pins.\n",
00230                    iblk, block[iblk].name, num_conn);
00231             error++;
00232         }
00233 
00234     return (error);
00235 }
00236 
00237 static int check_clb_internal_nets(int iblk) {
00238         /* TODO:
00239          * Check if the internal CLB nets makes sense and are connected properly 
00240          *  Consists of 3 main loops
00241          * 1. a) Check name uniqueness
00242               b) Check all net connections are to CLB pins or subblock pins and that they match the net examined
00243          * 2. Check all connected CLB pins are connected to valid internal nets
00244          * 3. Check all connected subblock pins are connected to valid internal nets and that these match the net indexes
00245          */
00246         return 0;
00247 }
00248 
00249 
00250 static int check_subblock_internal_nets(int iblk, int isub) {
00251         /*
00252          * TODO
00253          * Check if the internal CLB nets makes sense and are connected properly 
00254          *  Consists of 3 main checks
00255          * 1. a) Check name uniqueness
00256               b) Check all net connections are to CLB pins or subblock pins and that they match the net examined
00257          * 2. Check all connected CLB pins are connected to valid internal nets
00258          * 3. Check all connected subblock pins are connected to valid internal nets and that these match the net indexes
00259          */
00260         return 0;
00261 }
00262 
00263 static int
00264 check_subblocks(int iblk)
00265 {
00266 /* TODO */
00267 /* This routine checks the subblocks of iblk (which must be a CLB).  It    *
00268  * returns the number of errors found.                                     */
00269         return 0;
00270 }
00271 
00272 
00273 static int
00274 check_primitives(int iblk, int isub)
00275 {
00276 
00277 /* TODO:
00278  This routine checks the subblocks of iblk (which must be a CLB).  It    *
00279  * returns the number of errors found.                                     */
00280 return 0;
00281 
00282 }
00283 
00284 
00285 static int
00286 check_for_duplicated_names(void)
00287 {
00288 #if 0
00289     int iblk, isub, iprim, error;
00290         int clb_count, sub_count, prim_count;
00291     struct s_hash **clb_hash_table, *clb_h_ptr;
00292     struct s_hash **sub_hash_table, *sub_h_ptr;
00293     struct s_hash **prim_hash_table, *prim_h_ptr;
00294     
00295         clb_hash_table = alloc_hash_table();
00296         sub_hash_table = alloc_hash_table();
00297         prim_hash_table = alloc_hash_table();
00298 
00299         error = clb_count = sub_count = prim_count = 0;
00300 
00301         for(iblk = 0; iblk < num_blocks; iblk++)
00302         {
00303                 clb_h_ptr = insert_in_hash_table(clb_hash_table, block[iblk].name, clb_count);
00304                 if(clb_h_ptr->count > 1) {
00305                         printf(ERRTAG "block %s has duplicated name\n", block[iblk].name);
00306                         error++;
00307                 } else {
00308                         clb_count++;
00309                 }
00310                 for(isub = 0; isub < block[iblk].num_subblocks; isub++)
00311                 {
00312                         sub_h_ptr = insert_in_hash_table(sub_hash_table, block[iblk].subblocks[isub].name, sub_count);
00313                         if(sub_h_ptr->count > 1) {
00314                                 printf(ERRTAG "subblock %s has duplicated name\n", block[iblk].subblocks[isub].name);
00315                                 error++;
00316                         } else {
00317                                 sub_count++;
00318                         }
00319                         for(iprim = 0; iprim < block[iblk].subblocks[isub].num_primitives; iprim++)
00320                         {
00321                                 prim_h_ptr = insert_in_hash_table(prim_hash_table, block[iblk].subblocks[isub].primitives[iprim].name, prim_count);
00322                                 if(prim_h_ptr->count > 1) {
00323                                         printf(ERRTAG "primitive %s has duplicated name\n", block[iblk].subblocks[isub].primitives[iprim].name);
00324                                         error++;
00325                                 } else {
00326                                         prim_count++;
00327                                 }
00328                         }
00329                 }
00330         }
00331         return error;
00332 #endif
00333         return 0;
00334 }
00335 
00336 
00337 /** This routine returns the number of connections to a block. */
00338 static int
00339 get_num_conn(int bnum)
00340 {
00341     int i, num_conn;
00342     t_type_ptr type;
00343 
00344     type = block[bnum].type;
00345 
00346     num_conn = 0;
00347 
00348     for(i = 0; i < type->num_pins; i++)
00349         {
00350             if(block[bnum].nets[i] != OPEN)
00351                 num_conn++;
00352         }
00353 
00354     return (num_conn);
00355 }
00356 
00357