📄 check_netlist.c
字号:
/* Subblock output pin. */ clb_pin = subblock_inf[isub].output; error += check_subblock_pin (clb_pin, 0, pins_per_clb - 1, DRIVER, iblk, isub, subblock_inf); /* Subblock clock pin. */ clb_pin = subblock_inf[isub].clock; error += check_subblock_pin (clb_pin, 0, pins_per_clb + num_subblocks - 1, RECEIVER, iblk, isub, subblock_inf); } /* End subblock for loop. */ /* If pins out of range, return. Could get seg faults otherwise. */ if (error != 0) return (error);/* Reset fanout counts. */ for (i=0;i<pins_per_clb;i++) num_uses_of_clb_pin[i] = 0; for (i=0;i<num_subblocks;i++) num_uses_of_sblk_opin[i] = 0; load_one_clb_fanout_count (subblock_lut_size, subblock_inf, num_subblocks, num_uses_of_clb_pin, num_uses_of_sblk_opin, iblk); error += check_clb_to_subblock_connections (iblk, subblock_inf, num_subblocks, num_uses_of_clb_pin); error += check_internal_subblock_connections (subblock_data_ptr, iblk, num_uses_of_sblk_opin); return (error);}static int check_subblock_pin (int clb_pin, int min_val, int max_val, enum e_pin_type pin_type, int iblk, int isubblk, t_subblock *subblock_inf) { /* Checks that this subblock pin connects to a valid clb pin or BLE output * * within the clb. Returns the number of errors found. */ int iclass; if (clb_pin != OPEN) { if (clb_pin < min_val || clb_pin > max_val) { printf("Error: Block #%d (%s) subblock #%d (%s)" "connects to nonexistent clb pin #%d.\n", iblk, block[iblk].name, isubblk, subblock_inf[isubblk].name, clb_pin); return (1); } if (clb_pin < pins_per_clb) { /* clb pin */ iclass = clb_pin_class[clb_pin]; if (class_inf[iclass].type != pin_type) { printf ("Error: Block #%d (%s) subblock #%d (%s) pin connects\n" "\tto clb pin (#%d) of wrong input/output type.\n", iblk, block[iblk].name, isubblk, subblock_inf[isubblk].name, clb_pin); return (1); } } } return (0);}static void check_for_multiple_sink_connections (void) { /* The check is for nets that connect more than once to the same class of * * pins on the same block. For LUTs and cluster-based logic blocks that * * doesn't make sense, although for some logic blocks it does. The router * * can now handle this case, so maybe I should get rid of this check. */ int iblk, ipin, inet, iclass, class_pin; int *num_pins_connected; num_pins_connected = my_calloc (num_nets, sizeof (int)); /* Have to do the check block by block, rather than net by net, for speed. * * This makes the code a bit messy. */ for (iblk=0;iblk<num_blocks;iblk++) { for (iclass=0;iclass<num_class;iclass++) { /* Two DRIVER pins can never connect to the same net (already checked by * * the multiple driver check) so skip that check. */ if (class_inf[iclass].type == DRIVER) continue; for (class_pin=0;class_pin<class_inf[iclass].num_pins;class_pin++) { ipin = class_inf[iclass].pinlist[class_pin]; inet = block[iblk].nets[ipin]; if (inet != OPEN) num_pins_connected[inet]++; } for (class_pin=0;class_pin<class_inf[iclass].num_pins;class_pin++) { ipin = class_inf[iclass].pinlist[class_pin]; inet = block[iblk].nets[ipin]; if (inet != OPEN) { if (num_pins_connected[inet] > 1) { printf("Warning: block %d (%s) connects %d pins of class " "%d to net %d (%s).\n", iblk, block[iblk].name, num_pins_connected[inet], iclass, inet, net[inet].name); printf("\tThis does not make sense for many logic blocks " "(e.g. LUTs).\n" "\tBe sure you really want this.\n"); } num_pins_connected[inet] = 0; } } } } free (num_pins_connected);}static int get_num_conn (int bnum) {/* This routine returns the number of connections to a block. */ int i, num_conn; num_conn = 0; for (i=0;i<pins_per_clb;i++) { if (block[bnum].nets[i] != OPEN) num_conn++; } return (num_conn);}static int check_internal_subblock_connections (t_subblock_data *subblock_data_ptr, int iblk, int *num_uses_of_sblk_opin) {/* This routine checks that all subblocks in this block are either * * completely empty (no pins hooked to anything) or have their output used * * somewhere. It also counts the number of constant generators (no input * * sblks) and the number of FFs used in the circuit. */ int num_const_gen, num_ff, isub, ipin, error; boolean has_inputs; int subblock_lut_size; int num_subblocks; t_subblock *subblock_inf; subblock_lut_size = subblock_data_ptr->subblock_lut_size; num_subblocks = subblock_data_ptr->num_subblocks_per_block[iblk]; subblock_inf = subblock_data_ptr->subblock_inf[iblk]; num_const_gen = 0; num_ff = 0; error = 0; for (isub=0;isub<num_subblocks;isub++) { has_inputs = FALSE; for (ipin=0;ipin<subblock_lut_size;ipin++) { if (subblock_inf[isub].inputs[ipin] != OPEN) { has_inputs = TRUE; break; } } if (num_uses_of_sblk_opin[isub] == 0) { /* Output unused */ if (has_inputs || subblock_inf[isub].clock != OPEN) { printf ("Error: output of subblock #%d (%s) of block #%d (%s) is " "never used.\n", isub, subblock_inf[isub].name, iblk, block[iblk].name); error++; } } /* End if output unused */ /* Check that subblocks whose output is used have inputs. */ else { /* Subblock output is used. */ if (!has_inputs) { /* No inputs are used */ if (subblock_inf[isub].clock == OPEN) { printf ("Warning: block #%d (%s), subblock #%d (%s) is a " "constant generator.\n\t(Has no inputs.)\n", iblk, block[iblk].name, isub, subblock_inf[isub].name); num_const_gen++; } else { printf ("Error: block #%d (%s), subblock #%d (%s) is a CLOCKED " "\n\tconstant generator.\n\t(Has no inputs but is clocked.)\n", iblk, block[iblk].name, isub, subblock_inf[isub].name); num_const_gen++; error++; } } else { /* Both input and output are used */ if (subblock_inf[isub].clock != OPEN) num_ff++; } } } /* End for all subblocks */ subblock_data_ptr->num_const_gen += num_const_gen; subblock_data_ptr->num_ff += num_ff; return (error);}static int check_clb_to_subblock_connections (int iblk, t_subblock *subblock_inf, int num_subblocks, int *num_uses_of_clb_pin) {/* This routine checks that each non-OPEN clb input pin connects to some * * subblock inputs, and that each non-OPEN clb output pin is driven by * * exactly one subblock output. It returns the number of errors found. * * Note that num_uses_of_clb_pin is used to store the number of out-edges * * (fanout) for a CLB ipin, and the number of in-edges (fanin) for a CLB * * opin. */ int ipin, isub, clb_pin, error; error = 0;/* Count how many things connect to each clb output pin. */ for (isub=0;isub<num_subblocks;isub++) { clb_pin = subblock_inf[isub].output; if (clb_pin != OPEN) /* Guaranteed to connect to DRIVER pin only */ num_uses_of_clb_pin[clb_pin]++; } for (ipin=0;ipin<pins_per_clb;ipin++) { if (block[iblk].nets[ipin] != OPEN) { if (is_opin(ipin)) { /* CLB output */ if (num_uses_of_clb_pin[ipin] == 0) { /* No driver? */ printf ("Error: output pin %d on block #%d (%s) is not driven " "by any subblock.\n", ipin, iblk, block[iblk].name); error++; } else if (num_uses_of_clb_pin[ipin] > 1) { /* Multiple drivers? */ printf ("Error: output pin %d on block #%d (%s) is driven " "by %d subblocks.\n", ipin, iblk, block[iblk].name, num_uses_of_clb_pin[ipin]); error++; } } else { /* CLB ipin */ if (num_uses_of_clb_pin[ipin] <= 0) { /* Fans out? */ printf ("Error: pin %d on block #%d (%s) does not fanout to any " "subblocks.\n", ipin, iblk, block[iblk].name); error++; } } } /* End if not OPEN */ else if (is_opin(ipin)) { /* OPEN CLB output pin */ if (num_uses_of_clb_pin[ipin] > 1) { printf ("Error: pin %d on block #%d (%s) is driven by %d " "subblocks.\n", ipin, iblk, block[iblk].name, num_uses_of_clb_pin[ipin]); error++; } } } return (error);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -