⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 check_netlist.c

📁 用于学术研究的FPGA布局布线软件VPR
💻 C
📖 第 1 页 / 共 2 页
字号:
#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 + -