📄 check_netlist.c
字号:
#include <stdio.h>#include "util.h"#include "vpr_types.h"#include "globals.h"#include "hash.h"#include "vpr_utils.h"#include "check_netlist.h"#include "assert.h"/**************** Subroutines local to this module **************************/static int check_connections_to_global_fb_pins(int inet);static int check_fb_conn(int iblk, int num_conn);static void check_for_multiple_sink_connections(void);static int check_for_duplicate_block_names(void);static int get_num_conn(int bnum);static int check_subblocks(int iblk, t_subblock_data * subblock_data_ptr, int *num_uses_of_fb_pin, int **num_uses_of_sblk_opin);static int check_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);static int check_internal_subblock_connections(t_subblock_data * subblock_data_ptr, int iblk, int **num_uses_of_sblk_opin);static int check_fb_to_subblock_connections(int iblk, t_subblock * subblock_inf, int num_subblocks, int *num_uses_of_fb_pin);/*********************** Subroutine definitions *****************************/voidcheck_netlist(t_subblock_data * subblock_data_ptr){/* This routine checks that the netlist makes sense, and sets the num_ff * * and num_const_gen members of subblock_data. */ int i, error, num_conn, max_subblocks, max_pins, max_sub_opins; int *num_uses_of_fb_pin, **num_uses_of_sblk_opin, *num_subblocks_per_block; struct s_hash **net_hash_table, *h_ptr; net_hash_table = alloc_hash_table(); num_subblocks_per_block = subblock_data_ptr->num_subblocks_per_block; subblock_data_ptr->num_ff = 0; subblock_data_ptr->num_const_gen = 0; error = 0; max_pins = 0; max_sub_opins = 0; /* Determine max number of subblocks for all types */ max_subblocks = 0; for(i = 0; i < num_types; i++) { max_subblocks = max(max_subblocks, type_descriptors[i].max_subblocks); max_pins = max(max_pins, type_descriptors[i].num_pins); max_sub_opins = max(max_sub_opins, type_descriptors[i].max_subblock_outputs); } /* one mem alloc to save space */ num_uses_of_fb_pin = (int *)my_malloc(max_pins * sizeof(int)); num_uses_of_sblk_opin = (int **)alloc_matrix(0, max_subblocks - 1, 0, max_sub_opins - 1, sizeof(int));/* Check that nets fanout and have a driver. */ for(i = 0; i < num_nets; i++) { h_ptr = insert_in_hash_table(net_hash_table, net[i].name, i); if(h_ptr->count != 1) { printf("Error: net %s has multiple drivers.\n", net[i].name); error++; } if(net[i].num_sinks == 0) { printf("Error: net %s has no fanout.\n", net[i].name); error++; } error += check_connections_to_global_fb_pins(i); } free_hash_table(net_hash_table);/* Check that each block makes sense. */ for(i = 0; i < num_blocks; i++) { num_conn = get_num_conn(i); error += check_fb_conn(i, num_conn); error += check_subblocks(i, subblock_data_ptr, num_uses_of_fb_pin, num_uses_of_sblk_opin); } check_for_multiple_sink_connections(); error += check_for_duplicate_block_names(); free(num_uses_of_fb_pin); free_matrix(num_uses_of_sblk_opin, 0, max_subblocks - 1, 0, sizeof(int)); if(error != 0) { printf("Found %d fatal Errors in the input netlist.\n", error); exit(1); }}static intcheck_connections_to_global_fb_pins(int inet){/* Checks that a global net (inet) connects only to global FB input pins * * and that non-global nets never connects to a global FB pin. Either * * global or non-global nets are allowed to connect to pads. */ int ipin, num_pins, iblk, node_block_pin, error; num_pins = (net[inet].num_sinks + 1); error = 0;/* For now global signals can be driven by an I/O pad or any FB output * * although a FB output generates a warning. I could make a global FB * * output pin type to allow people to make architectures that didn't have * * this warning. */ for(ipin = 0; ipin < num_pins; ipin++) { iblk = net[inet].node_block[ipin]; node_block_pin = net[inet].node_block_pin[ipin]; if(block[iblk].type->is_global_pin[node_block_pin] != net[inet].is_global) { /* Allow a FB output pin to drive a global net (warning only). */ if(ipin == 0 && net[inet].is_global) { printf ("Warning in check_connections_to_global_fb_pins:\n" "\tnet #%d (%s) is driven by FB output pin (#%d)\n" "\ton block #%d (%s).\n", inet, net[inet].name, node_block_pin, iblk, block[iblk].name); } else { /* Otherwise -> Error */ printf ("Error in check_connections_to_global_fb_pins:\n" "\tpin %d on net #%d (%s) connects to FB input pin (#%d)\n" "\ton block #%d (%s).\n", ipin, inet, net[inet].name, node_block_pin, iblk, block[iblk].name); error++; } if(net[inet].is_global) printf("\tNet is global, but FB pin is not.\n\n"); else printf("\tCLB pin is global, but net is not.\n\n"); } } /* End for all pins */ return (error);}static intcheck_fb_conn(int iblk, int num_conn){/* Checks that the connections into and out of the fb make sense. */ int iclass, ipin, error; t_type_ptr type; error = 0; type = block[iblk].type; if(type == IO_TYPE) { if(num_conn != 1) { printf(ERRTAG "io blk #%d (%s) has %d pins.\n", iblk, block[iblk].name, num_conn); error++; } } else if(num_conn < 2) { printf("Warning: logic block #%d (%s) has only %d pin.\n", iblk, block[iblk].name, num_conn);/* Allow the case where we have only one OUTPUT pin connected to continue. * * This is used sometimes as a constant generator for a primary output, * * but I will still warn the user. If the only pin connected is an input, * * abort. */ if(num_conn == 1) { for(ipin = 0; ipin < type->num_pins; ipin++) { if(block[iblk].nets[ipin] != OPEN) { iclass = type->pin_class[ipin]; if(type->class_inf[iclass].type != DRIVER) { error++; } else { printf ("\tPin is an output -- may be a constant generator.\n" "\tNon-fatal, but check this.\n"); } break; } } } else { error++; } }/* This case should already have been flagged as an error -- this is * * just a redundant double check. */ if(num_conn > type->num_pins) { printf("Error: logic block #%d with output %s has %d pins.\n", iblk, block[iblk].name, num_conn); error++; } return (error);}static intcheck_for_duplicate_block_names(void){/* Checks that all blocks have duplicate names. Returns the number of * * duplicate names. */ int error, iblk; struct s_hash **block_hash_table, *h_ptr; struct s_hash_iterator hash_iterator; error = 0; block_hash_table = alloc_hash_table(); for(iblk = 0; iblk < num_blocks; iblk++) h_ptr = insert_in_hash_table(block_hash_table, block[iblk].name, iblk); hash_iterator = start_hash_table_iterator(); h_ptr = get_next_hash(block_hash_table, &hash_iterator); while(h_ptr != NULL) { if(h_ptr->count != 1) { printf ("Error: %d blocks are named %s. Block names must be unique." "\n", h_ptr->count, h_ptr->name); error++; } h_ptr = get_next_hash(block_hash_table, &hash_iterator); } free_hash_table(block_hash_table); return (error);}static intcheck_subblocks(int iblk, t_subblock_data * subblock_data_ptr, int *num_uses_of_fb_pin, int **num_uses_of_sblk_opin){/* This routine checks the subblocks of iblk (which must be a FB). It * * returns the number of errors found. */ int error, isub, ipin, fb_pin, num_pins_fb; int num_subblocks, max_subblocks_per_block, subblock_lut_size, num_outputs; t_subblock *subblock_inf; num_pins_fb = block[iblk].type->num_pins; error = 0; subblock_inf = subblock_data_ptr->subblock_inf[iblk]; num_subblocks = subblock_data_ptr->num_subblocks_per_block[iblk]; max_subblocks_per_block = block[iblk].type->max_subblocks; subblock_lut_size = block[iblk].type->max_subblock_inputs; num_outputs = block[iblk].type->max_subblock_outputs; if(num_subblocks < 1 || num_subblocks > max_subblocks_per_block) { printf("Error: block #%d (%s) contains %d subblocks.\n", iblk, block[iblk].name, num_subblocks); error++; }/* Check that all pins connect to the proper type of FB pin and are in the * * correct range. */ for(isub = 0; isub < num_subblocks; isub++) { for(ipin = 0; ipin < subblock_lut_size; ipin++) { /* Input pins */ fb_pin = subblock_inf[isub].inputs[ipin]; error += check_subblock_pin(fb_pin, 0, (num_pins_fb + (num_subblocks * num_outputs) - 1), RECEIVER, iblk, isub, subblock_inf); } for(ipin = 0; ipin < num_outputs; ++ipin) { /* Output pins. */ fb_pin = subblock_inf[isub].outputs[ipin]; error += check_subblock_pin(fb_pin, 0, (num_pins_fb - 1), DRIVER, iblk, isub, subblock_inf); } /* Subblock clock pin. */ fb_pin = subblock_inf[isub].clock; error += check_subblock_pin(fb_pin, 0, (num_pins_fb + (num_subblocks * num_outputs) - 1), RECEIVER, iblk, isub, subblock_inf); } /* End subblock for loop. *//* If pins out of range, return. Could get seg faults otherwise. */ if(error != 0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -