📄 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"/**************** Subroutines local to this module **************************/static int check_connections_to_global_clb_pins (int inet);static int check_clb_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_clb_pin, int *num_uses_of_sblk_opin); 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);static int check_internal_subblock_connections (t_subblock_data *subblock_data_ptr, int iblk, int *num_uses_of_sblk_opin); static int check_clb_to_subblock_connections (int iblk, t_subblock *subblock_inf, int num_subblocks, int *num_uses_of_clb_pin);/*********************** Subroutine definitions *****************************/void check_netlist (t_subblock_data *subblock_data_ptr, int *num_driver) {/* 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; int *num_uses_of_clb_pin, *num_uses_of_sblk_opin, *num_subblocks_per_block; 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; num_uses_of_clb_pin = (int *) my_malloc (pins_per_clb * sizeof (int)); num_uses_of_sblk_opin = (int *) my_malloc ( subblock_data_ptr->max_subblocks_per_block * sizeof (int));/* Check that nets fanout and have a driver. */ for (i=0;i<num_nets;i++) { if (num_driver[i] != 1) { printf ("Error: net %s has %d signals driving it.\n", net[i].name,num_driver[i]); error++; } if ((net[i].num_pins - num_driver[i]) < 1) { printf("Error: net %s has no fanout.\n",net[i].name); error++; } error += check_connections_to_global_clb_pins (i); }/* Check that each block makes sense. */ for (i=0;i<num_blocks;i++) { num_conn = get_num_conn (i); if (block[i].type == CLB) { error += check_clb_conn (i, num_conn); error += check_subblocks (i, subblock_data_ptr, num_uses_of_clb_pin, num_uses_of_sblk_opin); } else { /* IO block *//* This error check is a redundant double check. */ if (num_conn != 1) { printf("Error: io block #%d (%s) of type %d" "has %d pins.\n", i, block[i].name, block[i].type, num_conn); error++; } /* IO blocks must have no subblock information. */ if (num_subblocks_per_block[i] != 0) { printf("Error: IO block #%d (%s) contains %d subblocks.\n" "Expected 0.\n", i, block[i].name, num_subblocks_per_block[i]); error++; } } } check_for_multiple_sink_connections (); error += check_for_duplicate_block_names (); free (num_uses_of_clb_pin); free (num_uses_of_sblk_opin); if (error != 0) { printf("Found %d fatal Errors in the input netlist.\n",error); exit(1); }}static int check_connections_to_global_clb_pins (int inet) {/* Checks that a global net (inet) connects only to global CLB input pins * * and that non-global nets never connects to a global CLB pin. Either * * global or non-global nets are allowed to connect to pads. */ int ipin, num_pins, iblk, blk_pin, error; num_pins = net[inet].num_pins; error = 0;/* For now global signals can be driven by an I/O pad or any CLB output * * although a CLB output generates a warning. I could make a global CLB * * 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].blocks[ipin]; if (block[iblk].type == CLB) { /* I/O pads are exempt. */ blk_pin = net[inet].blk_pin[ipin]; if (is_global_clb_pin[blk_pin] != is_global[inet]) { /* Allow a CLB output pin to drive a global net (warning only). */ if (ipin == 0 && is_global[inet]) { printf ("Warning in check_connections_to_global_clb_pins:\n" "\tnet #%d (%s) is driven by CLB output pin (#%d)\n" "\ton block #%d (%s).\n", inet, net[inet].name, blk_pin, iblk, block[iblk].name); } else { /* Otherwise -> Error */ printf ("Error in check_connections_to_global_clb_pins:\n" "\tpin %d on net #%d (%s) connects to CLB input pin (#%d)\n" "\ton block #%d (%s).\n", ipin, inet, net[inet].name, blk_pin, iblk, block[iblk].name); error++; } if (is_global[inet]) printf ("\tNet is global, but CLB pin is not.\n\n"); else printf ("\tCLB pin is global, but net is not.\n\n"); } } } /* End for all pins */ return (error);}static int check_clb_conn (int iblk, int num_conn) { /* Checks that the connections into and out of the clb make sense. */ int iclass, ipin, error; error = 0; 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<pins_per_clb;ipin++) { if (block[iblk].nets[ipin] != OPEN) { iclass = clb_pin_class[ipin]; if (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 > pins_per_clb) { printf("Error: logic block #%d with output %s has %d pins.\n", iblk, block[iblk].name,num_conn); error++; } return (error);}static int check_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 int check_subblocks (int iblk, t_subblock_data *subblock_data_ptr, int *num_uses_of_clb_pin, int *num_uses_of_sblk_opin) { /* This routine checks the subblocks of iblk (which must be a CLB). It * * returns the number of errors found. */ int error, isub, ipin, clb_pin, i; int num_subblocks, max_subblocks_per_block, subblock_lut_size; t_subblock *subblock_inf; error = 0; subblock_inf = subblock_data_ptr->subblock_inf[iblk]; num_subblocks = subblock_data_ptr->num_subblocks_per_block[iblk]; max_subblocks_per_block = subblock_data_ptr->max_subblocks_per_block; subblock_lut_size = subblock_data_ptr->subblock_lut_size; 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 CLB pin and are in the * * correct range. */ for (isub=0;isub<num_subblocks;isub++) { for (ipin=0;ipin<subblock_lut_size;ipin++) { /* Input pins */ clb_pin = subblock_inf[isub].inputs[ipin]; error += check_subblock_pin (clb_pin, 0, pins_per_clb + num_subblocks - 1, RECEIVER, iblk, isub, subblock_inf); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -