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

📄 read_netlist.c

📁 fpga设计评估软件
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <string.h>#include <stdio.h>#include "util.h"#include "vpr_types.h"#include "globals.h"#include "read_netlist.h"#include "hash.h"#include "check_netlist.h"#include <assert.h>/* This source file reads in a .net file.  A .net file is a netlist   * * format defined by me to allow arbitary logic blocks (clbs) to      * * make up a netlist.  There are three legal block types: .input,     * * .output, and .clb.  To define a block, you start a line with one   * * of these keywords; the function of each type of block is obvious.  * * After the block type keyword, you specify the name of this block.  * * The line below must start with the keyword pinlist:, and gives a   * * list of the nets connected to the pins of this block.  .input and  * * .output blocks are pads and have only one net connected to them.   * * The number of pins on a .clb block is specified in the arch-       * * itecture file, as are the equivalences between pins.  Each         * * clb must have the same number of pins (heterogeneous FPGAs are     * * currently not supported) so any pins which are not used on a clb   * * must be identified with the reserved word "open".  All keywords    * * must be lower case.                                                * *                                                                    * * The lines immediately below the pinlist line must specify the      * * contents of the clb.  Each .subblock line lists the name of the    * * subblock, followed by the clb pin number or subblock output to     * * which each subblock pin should connect.  Each subblock is assummed * * to consist of a LUT with subblock_lut_size inputs, a FF, and an    * * output.  The pin order is input1, input2, ... output, clock.  The  * * architecture file sets the number of subblocks per clb and the LUT * * size used.  Subblocks are used only for timing analysis.  An       * * example clb declaration is:                                        * *                                                                    * * .clb name_of_clb  # comment                                        * *  pinlist:  net_1 net_2 my_net net_of_mine open D open              * *  subblock: sub_1 0 1 2 3 open open open                            * *  subblock: sub_2 1 3 ble_0 open open 5 open                        * *                                                                    * * Notice that the output of the first subblock (ble_0) is used only  * * by the second subblock.  This is fine.                             * *                                                                    * * Ending a line with a backslash (\) means it is continued on the    * * line below.  A sharp sign (#) indicates the rest of a line is      * * a comment.                                                         * * The vpack program can be used to convert a flat blif netlist       * * into .net format.                                                  * *                                                                    * * V. Betz, Jan. 29, 1997.                                            *//* A note about the way the character buffer, buf, is passed around. * * strtok does not make a local copy of the character string         * * initially passed to it, so you must make sure it always exists.   * * Hence, I just use one buffer declared in read_net and pass it     * * downstream.  Starting a new line with an automatic variable       * * buffer in a downstream subroutine and then returning and trying   * * to keep tokenizing it would cause problems since the buffer now   * * lies on a stale part of the stack and can be overwritten.         *//*************************** Variables local to this module *****************//* Temporary storage used during parsing. */static int *num_driver, *temp_num_pins;static struct s_hash **hash_table;static int temp_block_storage;/* Used for memory chunking of everything except subblock data. */static int chunk_bytes_avail = 0;static char *chunk_next_avail_mem = NULL;/* Subblock data can be accessed anywhere within this module.  Pointers to * * the main subblock data structures are passed back to the rest of the    * * program through the subblock_data_ptr structure passed to read_net.     */static int max_subblocks_per_block;static int subblock_lut_size;static t_subblock **subblock_inf;static int *num_subblocks_per_block;/* The subblock data is put in its own "chunk" so it can be freed without  * * hosing the other netlist data.                                          */static int ch_subblock_bytes_avail;static char *ch_subblock_next_avail_mem;static struct s_linked_vptr *ch_subblock_head_ptr;/************************ Subroutines local to this module ******************/static int add_net (char *ptr, enum e_pin_type type, int bnum, int blk_pnum,        int doall); static char *get_tok(char *buf, int doall, FILE *fp_net);static void add_io (int doall, int type, FILE *fp_net, char *buf);static char *add_clb (int doall, FILE *fp_net, char *buf);static void add_global (int doall, FILE *fp_net, char *buf);static void init_parse(int doall);static void free_parse (void);static void parse_name_and_pinlist (int doall, FILE *fp_net, char *buf);static int get_pin_number (char *ptr); static void load_subblock_array (int doall, FILE *fp_net, char *temp_buf,      int num_subblocks, int bnum); static void set_subblock_count (int bnum, int num_subblocks); static char *parse_subblocks (int doall, FILE *fp_net, char *buf, int bnum); /********************** Subroutine definitions *******************************/void read_net (char *net_file, t_subblock_data *subblock_data_ptr) {/* Main routine that parses a netlist file in my (.net) format. */ char buf[BUFSIZE], *ptr; int doall; FILE *fp_net;/* Make two variables below accessible anywhere in the module because I'm * * too lazy to pass them all over the place.                              */ max_subblocks_per_block = subblock_data_ptr->max_subblocks_per_block; subblock_lut_size = subblock_data_ptr->subblock_lut_size; fp_net = my_fopen (net_file, "r", 0);/* First pass builds the symbol table and counts the number of pins  * * on each net.  Then I allocate exactly the right amount of storage * * for each net.  Finally, the second pass loads the block and net   * * arrays.                                                           */ for (doall=0;doall<=1;doall++) {  /* Pass number. */    init_parse(doall);    linenum = 0;   /* Reset line number. */    ptr = my_fgets (buf, BUFSIZE, fp_net);    while (ptr != NULL) {       ptr = get_tok (buf, doall, fp_net);    }    rewind (fp_net);  /* Start at beginning of file again */ }  fclose(fp_net);/* Return the three data structures below through subblock_data_ptr.        */ subblock_data_ptr->subblock_inf = subblock_inf; subblock_data_ptr->num_subblocks_per_block = num_subblocks_per_block; subblock_data_ptr->chunk_head_ptr = ch_subblock_head_ptr; check_netlist (subblock_data_ptr, num_driver); free_parse();}static void init_parse(int doall) {/* Allocates and initializes the data structures needed for the parse. */ int i, j, len, nindex, pin_count; int *tmp_ptr; struct s_hash_iterator hash_iterator; struct s_hash *h_ptr; if (!doall) {  /* Initialization before first (counting) pass */    num_nets = 0;      hash_table = alloc_hash_table ();#define INITIAL_BLOCK_STORAGE 2000    temp_block_storage = INITIAL_BLOCK_STORAGE;    num_subblocks_per_block = my_malloc (INITIAL_BLOCK_STORAGE *             sizeof(int));    ch_subblock_bytes_avail = 0;    ch_subblock_next_avail_mem = NULL;    ch_subblock_head_ptr = NULL; }/* Allocate memory for second (load) pass */  else {       net = (struct s_net *) my_malloc (num_nets*sizeof(struct s_net));    block = (struct s_block *) my_malloc (num_blocks*        sizeof(struct s_block));       is_global = (boolean *) my_calloc (num_nets, sizeof(boolean));    num_driver = (int *) my_malloc (num_nets * sizeof(int));    temp_num_pins = (int *) my_malloc (num_nets * sizeof(int));    for (i=0;i<num_nets;i++) {       num_driver[i] = 0;       net[i].num_pins = 0;    }/* Allocate block pin connection storage.  Some is wasted for io blocks. * * Method used below "chunks" the malloc of a bunch of small things to   * * reduce the memory housekeeping overhead of malloc.                    */    tmp_ptr = (int *) my_malloc (pins_per_clb * num_blocks * sizeof(int));    for (i=0;i<num_blocks;i++)        block[i].nets = tmp_ptr + i * pins_per_clb;/* I use my_chunk_malloc for some storage locations below.  my_chunk_malloc  * * avoids the 12 byte or so overhead incurred by malloc, but since I call it * * with a NULL head_ptr, it will not keep around enough information to ever  * * free these data arrays.  If you ever have compatibility problems on a     * * non-SPARC architecture, just change all the my_chunk_malloc calls to      * * my_malloc calls.                                                          */    hash_iterator = start_hash_table_iterator ();    h_ptr = get_next_hash (hash_table, &hash_iterator);        while (h_ptr != NULL) {       nindex = h_ptr->index;       pin_count = h_ptr->count;       net[nindex].blocks = (int *) my_chunk_malloc(pin_count *               sizeof(int), NULL, &chunk_bytes_avail, &chunk_next_avail_mem);       net[nindex].blk_pin = (int *) my_chunk_malloc (pin_count *                sizeof(int), NULL, &chunk_bytes_avail, &chunk_next_avail_mem);/* For avoiding assigning values beyond end of pins array. */       temp_num_pins[nindex] = pin_count;       len = strlen (h_ptr->name);       net[nindex].name = (char *) my_chunk_malloc ((len + 1) *            sizeof(char), NULL, &chunk_bytes_avail, &chunk_next_avail_mem);       strcpy (net[nindex].name, h_ptr->name);       h_ptr = get_next_hash (hash_table, &hash_iterator);    }/* Allocate storage for subblock info. (what's in each logic block) */   num_subblocks_per_block = (int *) my_realloc (num_subblocks_per_block,                  num_blocks * sizeof (int));   subblock_inf = (t_subblock **) my_malloc (num_blocks *                         sizeof(t_subblock *));   for (i=0;i<num_blocks;i++) {      if (num_subblocks_per_block[i] == 0)          subblock_inf[i] = NULL;      else {         subblock_inf[i] = (t_subblock *) my_chunk_malloc (              num_subblocks_per_block[i] * sizeof (t_subblock),               &ch_subblock_head_ptr, &ch_subblock_bytes_avail,               &ch_subblock_next_avail_mem);         for (j=0;j<num_subblocks_per_block[i];j++)             subblock_inf[i][j].inputs = (int *) my_chunk_malloc                 (subblock_lut_size * sizeof(int), &ch_subblock_head_ptr,                  &ch_subblock_bytes_avail, &ch_subblock_next_avail_mem);      }   } }/* Initializations for both passes. */ linenum = 0; num_p_inputs = 0; num_p_outputs = 0; num_clbs = 0; num_blocks = 0; num_globals = 0;}static char *get_tok (char *buf, int doall, FILE *fp_net) {/* Figures out which, if any token is at the start of this line and * * takes the appropriate action.  It always returns a pointer to    * * the next line (I need to do this so I can do some lookahead).    */ char *ptr;   ptr = my_strtok(buf,TOKENS,fp_net,buf); if (ptr == NULL) {                       /* Empty line.  Skip. */    ptr = my_fgets(buf, BUFSIZE, fp_net);    return (ptr); }  if (strcmp(ptr,".clb") == 0) {    ptr = add_clb (doall, fp_net, buf);    return (ptr); } if (strcmp(ptr,".input") == 0) {    add_io (doall, INPAD, fp_net, buf);    ptr = my_fgets(buf, BUFSIZE, fp_net);    return (ptr); } if (strcmp(ptr,".output") == 0) {    add_io (doall, OUTPAD, fp_net, buf);    ptr = my_fgets(buf, BUFSIZE, fp_net);    return (ptr); } if (strcmp(ptr,".global") == 0) {    add_global (doall, fp_net, buf);    ptr = my_fgets(buf, BUFSIZE, fp_net);    return (ptr); } printf ("Error in get_tok while parsing netlist file.\n"); printf ("Line %d starts with an invalid token (%s).\n", linenum, ptr); exit (1);}static int get_pin_number (char *ptr) {/* Returns the pin number to which a subblock pin connects.  This pin number * * can be OPEN, one of the clb pins (from 0 to clb_size-1) or a "hidden"     * * pin that refers to the output of one of the subblocks within the clb      * * (the output of subblock 0 is pin clb_size, the output of subblock         * * max_subblocks_per_block is clb_size + max_subblocks_per_block-1).         */ int val; if (strcmp("open",ptr) == 0)     return (OPEN); if (strncmp ("ble_", ptr, 4) == 0) {   /* "Hidden" pin (Subblock output) */    val = my_atoi (ptr + 4);    if (val < 0 || val >= max_subblocks_per_block) {       printf("Error in get_pin_number on line %d of netlist file.\n",             linenum);       printf("Pin ble_%d is out of legal range (ble_%d to ble_%d).\n"            "Aborting.\n\n", val, 0, max_subblocks_per_block - 1);       exit (1);    }    val += pins_per_clb;  /* pins_per_clb .. pins_per_clb + max_subblocks-1 */    return (val); } /* Clb input pin. */ val = my_atoi (ptr); if (val < 0 || val >= pins_per_clb) {    printf("Error in get_pin_number on line %d of netlist file.\n",          linenum);    printf("Pin %d is out of legal range (%d to %d).\nAborting.\n\n",         val, 0, pins_per_clb - 1);    exit (1); } return (val);}static void load_subblock_array (int doall, FILE *fp_net,           char *temp_buf, int num_subblocks, int bnum) {/* Parses one subblock line and, if doall is 1, loads the proper   * * arrays.  Each subblock line is of the format:                   * * subblock: <name> <ipin0> <ipin1> .. <ipin[subblock_lut_size-1]> * *          <opin> <clockpin>                                      */  int ipin, len, connect_to; char *ptr; ipin = 0; ptr = my_strtok(NULL,TOKENS,fp_net,temp_buf); if (ptr == NULL) {    printf("Error in load_subblock_array on line %d of netlist file.\n",             linenum);    printf("Subblock name is missing.\nAborting.\n\n");    exit (1); }    /* Load subblock name if this is the load pass. */ if (doall == 1) {    len = strlen (ptr);    subblock_inf[bnum][num_subblocks-1].name = my_chunk_malloc ((len+1) *             sizeof(char), &ch_subblock_head_ptr, &ch_subblock_bytes_avail,             &ch_subblock_next_avail_mem);    strcpy (subblock_inf[bnum][num_subblocks-1].name, ptr); }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -