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

📄 read_arch.c

📁 fpga设计评估软件
💻 C
📖 第 1 页 / 共 4 页
字号:
static void check_arch (char *arch_file, enum e_route_type route_type,        struct s_det_routing_arch det_routing_arch, t_segment_inf *segment_inf,        t_timing_inf timing_inf, int max_subblocks_per_block,         t_chan_width_dist chan_width_dist) {/* This routine checks that the input architecture file makes sense and * * specifies all the needed parameters.  The parameters must also be    * * self-consistent and make sense.                                      */ int i, fatal, opin_switch; float total_segment_freq, chan_width_io; boolean must_be_set[NUMINP]; t_chan chan_x_dist, chan_y_dist; fatal = 0;/* NUMINP parameters can be set in the architecture file.  The first      * * NUM_REQUIRED are always mandatory.  The next NUM_DETAILED ones are     * * needed only if detailed routing is going to be performed.  The last    * * NUM_TIMING ones are needed only if timing analysis is going to be      * * performed.  Expect the corresponding isread for each parameter to be   * * 1, except isread[4] (outpin), isread[5] (inpin), isread[13] (segment)  * * and isread[14] (switch)  which should all be greater than 0.           */ for (i=0;i<NUM_REQUIRED;i++)     must_be_set[i] = TRUE; for (i=NUM_REQUIRED;i<NUMINP;i++)     must_be_set[i] = FALSE; if (route_type == DETAILED) {    for (i=NUM_REQUIRED;i<NUM_REQUIRED + NUM_DETAILED;i++)       must_be_set[i] = TRUE; } if (timing_inf.timing_analysis_enabled) {    for (i=NUM_REQUIRED + NUM_DETAILED;i<NUMINP;i++)       must_be_set[i] = TRUE; } for (i=0;i<NUMINP;i++) {    if (!must_be_set[i])       continue;    if (i == TIMING_START + 7) {   /* T_subblock lines */       if (isread[i] < 1 || isread[i] != max_subblocks_per_block) {          printf ("Error: Got %d T_subblock lines -- expected %d.\n",              isread[i], max_subblocks_per_block);          fatal = 1;       }    }    else if (i != 4 && i != 5 && i != DETAILED_START + 5 && i !=                       DETAILED_START + 6) {       if (isread[i] == 0) {          printf("Error:  %s not set in file %s.\n",names[i],             arch_file);          fatal=1;       }       if (isread[i] > 1) {          printf("Error:  %s set %d times in file %s.\n",names[i],              isread[i],arch_file);          fatal = 1;       }    }    else {    /* outpin, inpin, segment, or switch lines */       if (isread[i] < 1) {          printf("Error:  in file %s.  Clb has %d %s(s).\n",arch_file,                   isread[i], names[i]);          fatal = 1;       }    } }/* Segment info is used for both GLOBAL and DETAILED routing. */ total_segment_freq = 0.; for (i=0;i<det_routing_arch.num_segment;i++) {    total_segment_freq += segment_inf[i].frequency;    opin_switch = segment_inf[i].opin_switch;    if (switch_inf[opin_switch].buffered == FALSE) {       printf ("Error in check_arch:  opin_switch (#%d) of segment type #%d "               "is not buffered.\n", opin_switch, i);       exit (1);    } } if (fabs (total_segment_freq - 1.) > 0.001) {    printf ("Error in check_arch:  Segment frequencies must sum to 1.\n"            "\tSum is %g.\n", total_segment_freq);    fatal = 1; }/* Detailed routing is only supported on architectures with all channel  * * widths the same for now.  The router could handle non-uniform widths, * * but the routing resource graph generator doesn't build the rr_graph   * * for the nonuniform case as yet.                                       */ if (route_type == DETAILED) {    chan_width_io = chan_width_dist.chan_width_io;    chan_x_dist = chan_width_dist.chan_x_dist;    chan_y_dist = chan_width_dist.chan_y_dist;    if (chan_x_dist.type != UNIFORM || chan_y_dist.type != UNIFORM ||          chan_x_dist.peak != chan_y_dist.peak || chan_x_dist.peak !=          chan_width_io) {       printf("Error in check_arch:  detailed routing currently only\n"             "supported on FPGAs with all channels of equal width.\n");       fatal = 1;    }    if (det_routing_arch.Fc_type == ABSOLUTE) {       if (det_routing_arch.Fc_output < 1 || det_routing_arch.Fc_input < 1              || det_routing_arch.Fc_pad < 1) {          printf ("Error in check_arch:  Fc values must be >= 1 in absolute "                  "mode.\n");          fatal = 1;       }    }    else {   /* FRACTIONAL mode */       if (det_routing_arch.Fc_output > 1. || det_routing_arch.Fc_input > 1.              || det_routing_arch.Fc_pad > 1.) {          printf ("Error in check_arch:  Fc values must be <= 1. in "                 "fractional mode.\n");          fatal = 1;       }    }     for (i=0;i<det_routing_arch.num_switch;i++) {       if (switch_inf[i].buffered) {      /* Largest resistance tri-state buffer would have a minimum width     *       * transistor in the buffer pull-down and a min-width pass transistor *       * on the output.  Hence largest R = 2 * largest_transistor_R.        */          if (switch_inf[i].R > 2 * det_routing_arch.R_minW_nmos) {             printf ("Error in check_arch:  Switch %d R value (%g) is greater"                     " than 2 * R_minW_nmos (%g).\n", i, switch_inf[i].R,                     2 * det_routing_arch.R_minW_nmos);             exit (1);          }       }       else {    /* Pass transistor switch */          if (switch_inf[i].R > det_routing_arch.R_minW_nmos) {             printf ("Error in check_arch:  Switch %d R value (%g) is greater "                     "than R_minW_nmos (%g).\n", i, switch_inf[i].R,                     det_routing_arch.R_minW_nmos);             exit (1);          }       }    }     /* End for all switches. */ }     /* End if route_type == DETAILED */ if (fatal)     exit(1);}       void print_arch (char *arch_file, enum e_route_type route_type,       struct s_det_routing_arch det_routing_arch, t_segment_inf *segment_inf,       t_timing_inf timing_inf, t_subblock_data subblock_data,       t_chan_width_dist chan_width_dist) {/* Prints out the architectural parameters for verification in the  * * file "arch.echo."  The name of the architecture file is passed   * * in and is printed out as well.                                   */ int i, j; FILE *fp; t_T_subblock T_subblock; t_chan chan_x_dist, chan_y_dist; float chan_width_io; fp = my_fopen ("arch.echo", "w", 0); chan_width_io = chan_width_dist.chan_width_io; chan_x_dist = chan_width_dist.chan_x_dist; chan_y_dist = chan_width_dist.chan_y_dist; fprintf(fp,"Input netlist file: %s\n\n",arch_file); fprintf(fp,"io_rat: %d.\n",io_rat); fprintf(fp,"chan_width_io: %g  pins_per_clb (pins per clb): %d\n",      chan_width_dist.chan_width_io, pins_per_clb); fprintf(fp,"\n\nChannel Types:  UNIFORM = %d; GAUSSIAN = %d; PULSE = %d;"    " DELTA = %d\n\n", UNIFORM, GAUSSIAN, PULSE, DELTA); fprintf(fp,"\nchan_width_x:\n"); fprintf(fp,"type: %d  peak: %g  width: %g  xpeak: %g  dc: %g\n",   chan_x_dist.type, chan_x_dist.peak, chan_x_dist.width,      chan_x_dist.xpeak, chan_x_dist.dc); fprintf(fp,"\nchan_width_y:\n"); fprintf(fp,"type: %d  peak: %g  width: %g  xpeak: %g  dc: %g\n\n",   chan_y_dist.type, chan_y_dist.peak, chan_y_dist.width,      chan_y_dist.xpeak, chan_y_dist.dc); fprintf(fp,"Pin #\tclass\ttop\tbottom\tleft\tright\tglobal"); for (i=0;i<pins_per_clb;i++) {    fprintf(fp,"\n%d\t%d\t", i, clb_pin_class[i]);    for (j=0;j<=3;j++)        fprintf(fp,"%d\t",pinloc[j][i]);    fprintf (fp, "%d", is_global_clb_pin[i]); } fprintf(fp,"\n\nClass types:  DRIVER = %d; RECEIVER = %d\n\n", DRIVER,     RECEIVER); fprintf(fp,"Class\tType\tNumpins\tPins"); for (i=0;i<num_class;i++) {    fprintf(fp,"\n%d\t%d\t%d\t", i, class_inf[i].type, class_inf[i].num_pins);    for (j=0;j<class_inf[i].num_pins;j++)        fprintf(fp,"%d\t",class_inf[i].pinlist[j]); } fprintf(fp,"\n\n"); fprintf(fp,"subblocks_per_clb (maximum): %d\n",       subblock_data.max_subblocks_per_block); fprintf(fp,"subblock_lut_size: %d\n", subblock_data.subblock_lut_size); if (route_type == DETAILED) {    fprintf(fp,"\n");    if (det_routing_arch.Fc_type == ABSOLUTE)        fprintf(fp,"Fc value is absolute number of tracks.\n");    else        fprintf(fp,"Fc value is fraction of tracks in a channel.\n");       fprintf(fp,"Fc_output: %g.  Fc_input: %g.  Fc_pad: %g.\n",             det_routing_arch.Fc_output, det_routing_arch.Fc_input,             det_routing_arch.Fc_pad);    if (det_routing_arch.switch_block_type == SUBSET)        fprintf (fp, "switch_block_type: SUBSET.\n");    else if (det_routing_arch.switch_block_type == WILTON)       fprintf (fp, "switch_block_type: WILTON.\n");    else       fprintf (fp, "switch_block_type: UNIVERSAL.\n"); }/* Segmentation info. useful even if route_type == GLOBAL */ fprintf (fp, "\nnum_segment: %d,  num_switch: %d.\n",           det_routing_arch.num_segment, det_routing_arch.num_switch); if (route_type == DETAILED)     fprintf (fp, "(Two switch types were generated automatically.)\n"); fprintf (fp, "#%d:  delayless switch.  #%d:  wire_to_ipin_switch.\n",          det_routing_arch.delayless_switch,           det_routing_arch.wire_to_ipin_switch); fprintf (fp, "\nSeg. #\tfreq.\tlength\tlongln\topin_sw\twire_sw\tFrac_cb\t"              "Frac_sb\tCmetal\tRmetal\n"); for (i=0;i<det_routing_arch.num_segment;i++)     fprintf (fp, "%d\t%g\t%d\t%d\t%d\t%d\t%g\t%g\t%g\t%g\n", i,        segment_inf[i].frequency, segment_inf[i].length,        segment_inf[i].longline, segment_inf[i].opin_switch,        segment_inf[i].wire_switch, segment_inf[i].frac_cb,        segment_inf[i].frac_sb, segment_inf[i].Cmetal, segment_inf[i].Rmetal); fprintf (fp,"\nSwitch#\tbuff?\tR\tCin\tCout\tTdel\n"); for (i=0;i<det_routing_arch.num_switch;i++)     fprintf (fp, "%d\t%d\t%g\t%g\t%g\t%g\n", i, switch_inf[i].buffered,        switch_inf[i].R, switch_inf[i].Cin, switch_inf[i].Cout,         switch_inf[i].Tdel); fprintf (fp,"\n\nR_minW_nmos: %g  R_minW_pmos: %g\n",         det_routing_arch.R_minW_nmos, det_routing_arch.R_minW_pmos); if (timing_inf.timing_analysis_enabled) {    fprintf (fp, "\n\nTiming information:\n");    fprintf (fp,"---------------------------------------------------------\n");    fprintf (fp, "C_ipin_cblock: %g (F) \nT_ipin_cblock: %g (s)\n\n",                 timing_inf.C_ipin_cblock, timing_inf.T_ipin_cblock);    fprintf (fp, "T_sblk_opin_to_sblk_ipin: %g (s)\n",                        timing_inf.T_sblk_opin_to_sblk_ipin);    fprintf (fp, "T_clb_ipin_to_sblk_ipin: %g (s)\n",                        timing_inf.T_clb_ipin_to_sblk_ipin);    fprintf (fp, "T_sblk_opin_to_clb_opin: %g (s)\n",                        timing_inf.T_sblk_opin_to_clb_opin);    fprintf (fp,"T_ipad: %g (s)  \nT_opad: %g (s)\n",                 timing_inf.T_ipad, timing_inf.T_opad);    fprintf (fp,"\nSubblock #\tT_comb (s)\tT_seq_in (s)\tT_seq_out (s)\n");    for (i=0;i<subblock_data.max_subblocks_per_block;i++) {       T_subblock = timing_inf.T_subblock[i];       fprintf (fp, "%10d\t%10g\t%10g\t%10g (s)\n", i, T_subblock.T_comb,                 T_subblock.T_seq_in, T_subblock.T_seq_out);    } } fclose (fp);}void init_arch (float aspect_ratio, boolean user_sized) {/* Allocates various data structures that depend on the FPGA         * * architecture.  Aspect_ratio specifies how many columns there are  * * relative to the number of rows -- i.e. width/height.  Used-sized  * * is TRUE if the user specified nx and ny already; in that case     * * use the user's values and don't recompute them.                   */ int io_lim;/* User specified the dimensions on the command line.  Check if they * * will fit the circuit.                                             */ if (user_sized == TRUE) {    if (num_clbs > nx * ny || num_p_inputs + num_p_outputs >            2 * io_rat * (nx + ny)) {       printf ("Error:  User-specified size is too small for circuit.\n");        exit (1);    } }/* Size the FPGA automatically to be smallest that will fit circuit */ else {/* Area = nx * ny = ny * ny * aspect_ratio                  * * Perimeter = 2 * (nx + ny) = 2 * ny * (1. + aspect_ratio)  */    ny = (int) ceil (sqrt ((double) (num_clbs / aspect_ratio)));    io_lim = (int) ceil ((num_p_inputs + num_p_outputs) / (2 * io_rat *           (1. + aspect_ratio)));    ny = max (ny, io_lim);    nx = (int) ceil (ny * aspect_ratio); }/* If both nx and ny are 1, we only have one valid location for a clb. * * That's a major problem, as won't be able to move the clb and the    * * find_to routine that tries moves in the placer will go into an      * * infinite loop trying to move it.  Exit with an error message        * * instead.                                                            */ if (nx == 1  && ny == 1 && num_clbs != 0) {    printf ("Error:\n");    printf ("Sorry, can't place a circuit with only one valid location\n");    printf ("for a logic block (clb).\n");    printf ("Try me with a more realistic circuit!\n");    exit (1); }/* To remove this limitation, change ylow etc. in t_rr_node to        * * be ints instead.  Used shorts to save memory.                      */ if (nx > 32766 || ny > 32766) {    printf("Error:  nx and ny must be less than 32767, since the \n");    printf("router uses shorts (16-bit) to store coordinates.\n");    printf("nx: %d.  ny: %d.\n", nx, ny);    exit (1); } clb = (struct s_clb **) alloc_matrix (0, nx+1, 0, ny+1,               sizeof(struct s_clb)); chan_width_x = (int *) my_malloc ((ny+1) * sizeof(int)); chan_width_y = (int *) my_malloc ((nx+1) * sizeof(int));  fill_arch();}static void fill_arch (void) {/* Fill some of the FPGA architecture data structures.         */ int i, j, *index;/* allocate io_blocks arrays. Done this way to save storage */ i = 2*io_rat*(nx+ny);   index = (int *) my_malloc (i*sizeof(int)); for (i=1;i<=nx;i++) {    clb[i][0].u.io_blocks = index;    index+=io_rat;    clb[i][ny+1].u.io_blocks = index;    index+=io_rat; } for (i=1;i<=ny;i++) {    clb[0][i].u.io_blocks = index;    index+=io_rat;    clb[nx+1][i].u.io_blocks = index;    index+=io_rat; }  /* Initialize type, and occupancy. */ for (i=1;i<=nx;i++) {      clb[i][0].type = IO;    clb[i][ny+1].type = IO;  /* perimeter (IO) cells */ } for (i=1;i<=ny;i++) {    clb[0][i].type = IO;    clb[nx+1][i].type = IO; } for (i=1;i<=nx;i++) {   /* interior (LUT) cells */    for (j=1;j<=ny;j++) {       clb[i][j].type = CLB;    } }/* Nothing goes in the corners.      */ clb[0][0].type = clb[nx+1][0].type = ILLEGAL;   clb[0][ny+1].type = clb[nx+1][ny+1].type = ILLEGAL;}

⌨️ 快捷键说明

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