📄 check_netlist.c
字号:
return (error); load_one_fb_fanout_count(subblock_inf, num_subblocks, num_uses_of_fb_pin, num_uses_of_sblk_opin, iblk); error += check_fb_to_subblock_connections(iblk, subblock_inf, num_subblocks, num_uses_of_fb_pin); error += check_internal_subblock_connections(subblock_data_ptr, iblk, num_uses_of_sblk_opin); return (error);}static intcheck_subblock_pin(int fb_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; t_type_ptr type; type = block[iblk].type; if(fb_pin != OPEN) { if(fb_pin < min_val || fb_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, fb_pin); return (1); } if(fb_pin < type->num_pins) { /* clb pin */ iclass = type->pin_class[fb_pin]; if(type->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, fb_pin); return (1); } } } return (0);}static voidcheck_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; t_type_ptr type; 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++) { type = block[iblk].type; for(iclass = 0; iclass < type->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(type->class_inf[iclass].type == DRIVER) continue; for(class_pin = 0; class_pin < type->class_inf[iclass].num_pins; class_pin++) { ipin = type->class_inf[iclass].pinlist[class_pin]; inet = block[iblk].nets[ipin]; if(inet != OPEN) num_pins_connected[inet]++; } for(class_pin = 0; class_pin < type->class_inf[iclass].num_pins; class_pin++) { ipin = type->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 intget_num_conn(int bnum){/* This routine returns the number of connections to a block. */ int i, num_conn; t_type_ptr type; type = block[bnum].type; num_conn = 0; for(i = 0; i < type->num_pins; i++) { if(block[bnum].nets[i] != OPEN) num_conn++; } return (num_conn);}static intcheck_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, opin, i; boolean has_inputs, has_outputs; int subblock_lut_size; int num_subblocks; t_subblock *subblock_inf; t_type_ptr type; type = block[iblk].type; subblock_lut_size = type->max_subblock_inputs; 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; } } has_outputs = FALSE; for(opin = 0; opin < type->max_subblock_outputs; opin++) { if(num_uses_of_sblk_opin[isub][opin] != 0) { has_outputs = TRUE; break; } } if(type == IO_TYPE) { /* Subblock inputs and outputs are faked for I/O's so this is an internal error */ assert((has_inputs && !has_outputs) || (!has_inputs && has_outputs)); } else if(!has_outputs) { /* 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) { for(i = 0; i < type->max_subblock_outputs; i++) { if(subblock_inf[isub]. outputs[i] != 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 intcheck_fb_to_subblock_connections(int iblk, t_subblock * subblock_inf, int num_subblocks, int *num_uses_of_fb_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_fb_pin is used to store the number of out-edges * * (fanout) for a FB ipin, and the number of in-edges (fanin) for a FB * * opin. */ int ipin, isub, fb_pin, error; int num_outputs; error = 0; num_outputs = block[iblk].type->max_subblock_outputs;/* Count how many things connect to each clb output pin. */ for(isub = 0; isub < num_subblocks; isub++) { for(ipin = 0; ipin < num_outputs; ++ipin) { fb_pin = subblock_inf[isub].outputs[ipin]; if(fb_pin != OPEN) /* Guaranteed to connect to DRIVER pin only */ num_uses_of_fb_pin[fb_pin]++; } } for(ipin = 0; ipin < block[iblk].type->num_pins; ipin++) { if(block[iblk].nets[ipin] != OPEN) { if(is_opin(ipin, block[iblk].type)) { /* FB output */ if(num_uses_of_fb_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_fb_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_fb_pin[ipin]); error++; } } else { /* FB ipin */ if(num_uses_of_fb_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, block[iblk].type)) { /* OPEN FB output pin */ if(num_uses_of_fb_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_fb_pin[ipin]); error++; } } } return (error);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -