📄 read_arch.c
字号:
#include <string.h>#include <stdio.h>#include <math.h>#include "util.h"#include "vpr_types.h"#include "globals.h"#include "read_arch.h"/* This source file reads in the architectural description of an FPGA. * * A # symbol anywhere in the input file denotes a comment to the end * * of the line. Put a \ at the end of a line if you want to continue * * a command across multiple lines. Non-comment lines are in the * * format keyword value(s). The entire file should be lower case. * * The keywords and their arguments are: * * * * io_rat integer (sets the number of io pads which fit into the * * space one CLB would use). * * chan_width_io float (Width of the channels between the pads and * * core relative to the widest core channel.) * * chan_width_x [gaussian|uniform|pulse] peak <width> <xpeak> <dc>. * * (<> bracketed quantities needed only for pulse and gaussian. * * Width and xpeak values from 0 to 1. Sets the distribution of * * tracks for the x-directed channels.) * * Other possibility: delta peak xpeak dc. * * chan_width_y [gaussian|uniform|pulse] peak <width> <xpeak> <dc>. * * (Sets the distribution of tracks for the y-directed channels.) * * outpin class: integer [top|bottom|left|right] [top|bottom|left| * * right] ... * * (Sets the class to which each pin belongs and the side(s) of * * CLBs on which the physical output pin connection(s) is (are). * * All pins with the same class number are logically equivalent * * -- such as all the inputs of a LUT. Class numbers must start * * at zero and be consecutive.) * * inpin class: integer <global> [top|bottom|left|right] [top|bottom|left| * * right] ... * * (All parameters have the same meanings as their counterparts * * in the outpin statement, except the optional global keyword. If * * global is specified, this inpin can connect only to global nets. * * Global nets are not routed by the router, and are normally only * * things like clock nets. A global pin has no switches connecting it * * to the regular routing, so it takes up no area in the area model.) * * * * NOTE: The order in which your inpin and outpin statements appear * * must be the same as the order in which your netlist (.net) * * file lists the connections to the clbs. For example, if the * * first pin on each clb in the netlist file is the clock pin, * * your first pin statement in the architecture file must be * * an inpin statement defining the clock pin. * * * * subblocks_per_clb <int> (Number of LUT + ff logic blocks in each clb * * at most). * * subblock_lut_size <int> (Number of inputs to each LUT in the * * clbs. Each subblock has subblock_lut_size inputs, one output * * and a clock input.) * * * * The following parameters only need to be in the architecture * * file if detailed routing is going to be performed (i.e. route_type * * == DETAILED). * * * * Fc_type [absolute|fractional] (Are the 3 Fc values absolute * * numbers of tracks to connect to, or the fraction of the W * * tracks to which each pin can connect?) * * Fc_output float (Sets the value of Fc -- the number of tracks * * each pin can connect to in each channel bordering the pin -- * * for output pins. The Fc_output value used is always * * min(W,Fc_selected), so set Fc to be huge if you want Fc = W.) * * Fc_input float (Sets the value of Fc for input pins.) * * Fc_pad float (Sets the value of Fc for pads.) * * switch_block_type [subset|wilton|universal] (Chooses the type of * * switch block used. See vpr_types.h for details.) * * segment frequency: <float> length: <int | longline> wire_switch: <int> * * opin_switch: <int> Frac_cb: <float> Frac_sb: <float> Rmetal: <float> * * Cmetal: <float> * * Describes one type of segment. wire_switch is the type of * * switch used when going *to* a segment of this type from any CHANX or * * CHANY routing segment. opin_switch is the type of switch used * * by a clb or pad output driver (OPIN) to connect to segments of this * * type. Cmetal is the capacitance per logic block spanned (i.e. per * * channel segment) of a routing track of this segment type. * * Similarly, Rmetal is the resistance per logic block spanned. * * switch <int> buffered: {yes|no} R: <float> Cin: <float> * * Cout: <float> Tdel: <float>. Describes a type of switch. * * R_minW_nmos <float> Resistance, in Ohms, of a minimum width nmos * * transistor. Used only in the transistor-level area model. * * R_minW_pmos <float> Resistance, in Ohms, of a minimum width pmos * * transistor. Used only in the transistor-level area model. * * * * The following parameters allow timing analysis. * * C_ipin_cblock <float>: Input capacitance of the buffer isolating a * * routing track from the input pin Cboxes connected to it at each * * (i,j) location. * * T_ipin_cblock <float>: Delay to go through a connection block to a * * logic block (clb) input pin. * * T_sblk_opin_to_sblk_ipin <float>: Delay through the local interconnect * * (muxes, wires or whatever) in a clb containing multiple subblocks. * * That is, the delay from a subblock output to the input of another * * subblock in the same clb. * * T_clb_ipin_to_sblk_ipin <float>: Delay from a clb input pin to any * * subblock input pin (e.g. the mux delay in an Altera 8K clb). * * T_sblk_opin_to_clb_opin <float>: Delay from a subblock output to a clb * * output. Will be 0 in many architectures. * * T_ipad: Delay through an input pad. * * T_opad: Delay through an output pad (setup time if you assume the * * outputs are registered before being sent out). * * T_subblock T_comb: <float> T_seq_in: <float> T_seq_out: <float> * * The combinational delay through a subblock combinational mode), the * * delay from subblock input to data being latched (including setup * * time), and the delay from clock to data coming out of the subblock * * output (i.e. clk_to_Q plus any delays due to muxes, etc.). If a * * subblock is being used in combinational mode (clock input is open) * * then Tcomb is used to find the delay through it. If the subblock * * is being used in sequential mode (clock input not open) then * * T_seq_in gives the delay to the storage element and T_seq_out gives * * the delay from storage element to subblock output. You need one * * of these T_subblock lines for each of the subblocks_per_clb * * subblocks in your architecture. The first line gives the delays for * * subblock 0 (first one listed for each logic block in the netlist * * file) and so on. *//******************* Defines and types local to this module *****************/#define NUM_REQUIRED 8 /* Number of parameters that are always required. */#define NUM_DETAILED 9 /* Number needed only if detailed routing used. */#define NUM_TIMING 8 /* Number needed only if timing analysis used. */#define DETAILED_START NUM_REQUIRED#define TIMING_START (NUM_REQUIRED + NUM_DETAILED)/* Total number of different parameters in arch file. */#define NUMINP (NUM_REQUIRED + NUM_DETAILED + NUM_TIMING)/******************** Variables local to this module. **********************/static int isread[NUMINP];static const char *names[NUMINP] = {"io_rat", "chan_width_x", "chan_width_y", "chan_width_io", "outpin", "inpin", "subblocks_per_clb", "subblock_lut_size", "Fc_output", "Fc_input", "Fc_pad", "Fc_type", "switch_block_type", "segment", "switch", "R_minW_nmos", "R_minW_pmos", "C_ipin_cblock", "T_ipin_cblock", "T_sblk_opin_to_sblk_ipin", "T_clb_ipin_to_sblk_ipin", "T_sblk_opin_to_clb_opin", "T_ipad", "T_opad", "T_subblock"};/********************** Subroutines local to this module. ******************/static float get_float (char *ptr, int inp_num, float llim, float ulim, FILE *fp_arch, char *buf); static float get_one_float (char *ptr, int inp_num, float low_lim, float upp_lim, FILE *fp_arch, char *buf); static int get_int (char *ptr, int inp_num, FILE *fp_arch, char *buf, int min_val);static char *get_middle_token (FILE *fp, char *buf); static char *get_last_token (FILE *fp, char *buf); static void check_keyword (FILE *fp, char *buf, const char *keyword); 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); static void fill_arch (void);static void get_chan (char *ptr, t_chan *chan, int inp_num, FILE *fp_arch, char *buf); static void get_pin (char *ptr, int pinnum, enum e_pin_type type, FILE *fp_arch, char *buf);static enum e_Fc_type get_Fc_type (char *ptr, FILE *fp_arch, char *buf); static enum e_switch_block_type get_switch_block_type (FILE *fp_arch, char *buf); static void get_segment_inf (FILE *fp_arch, char *buf, t_segment_inf *seg_ptr, int num_switch, enum e_route_type route_type); static void get_switch_inf (FILE *fp_arch, char *buf, int num_switch, enum e_route_type route_type); static void get_T_subblock (FILE *fp_arch, char *buf, t_T_subblock *T_subblock); static int get_class (FILE *fp_arch, char *buf);static void load_global_segment_and_switch (struct s_det_routing_arch * det_routing_arch, t_segment_inf *segment_inf, t_timing_inf *timing_inf); static void load_extra_switch_types (struct s_det_routing_arch * det_routing_arch, t_timing_inf *timing_inf); static void countpass (FILE *fp_arch, enum e_route_type route_type, t_segment_inf **segment_inf_ptr, struct s_det_routing_arch *det_routing_arch_ptr, t_timing_inf *timing_inf); /****************** Subroutine definitions **********************************/void read_arch (char *arch_file, enum e_route_type route_type, struct s_det_routing_arch *det_routing_arch, t_segment_inf **segment_inf_ptr, t_timing_inf *timing_inf_ptr, t_subblock_data *subblock_data_ptr, t_chan_width_dist *chan_width_dist_ptr) {/* Reads in the architecture description file for the FPGA. */ int i, j, pinnum, next_segment; char *ptr, buf[BUFSIZE]; FILE *fp_arch; t_T_subblock *next_T_subblock_ptr; fp_arch = my_fopen (arch_file, "r", 0); countpass (fp_arch, route_type, segment_inf_ptr, det_routing_arch, timing_inf_ptr); rewind (fp_arch); linenum = 0; pinnum = 0; next_segment = 0; for (i=0;i<NUMINP;i++) isread[i] = 0; pinloc = (int **) alloc_matrix (0, 3, 0, pins_per_clb-1, sizeof (int)); for (i=0;i<=3;i++) for (j=0;j<pins_per_clb;j++) pinloc[i][j] = 0; /* Initialize these two things to zero, since they're used in graph building * * and they needn't be set by the user if timing_analysis isn't enabled. */ timing_inf_ptr->C_ipin_cblock = 0.; timing_inf_ptr->T_ipin_cblock = 0.;/* Start the main pass (pass 2). */ while ((ptr = my_fgets(buf, BUFSIZE, fp_arch)) != NULL) { ptr = my_strtok(ptr, TOKENS, fp_arch, buf); if (ptr == NULL) continue; /* Empty or comment line *//* This linear compare is getting pretty long. Could speed up with a hash * * table search -- do that if this starts getting slow. */ if (strcmp(ptr,names[0]) == 0) { /* io_rat */ io_rat = get_int (ptr, 0, fp_arch, buf, 1); continue; } if (strcmp(ptr,names[1]) == 0) { /*chan_width_x */ get_chan(ptr, &chan_width_dist_ptr->chan_x_dist, 1, fp_arch, buf); continue; } if (strcmp(ptr,names[2]) == 0) { /* chan_width_y */ get_chan(ptr, &chan_width_dist_ptr->chan_y_dist, 2, fp_arch, buf); continue; } if (strcmp(ptr,names[3]) == 0) { /* chan_width_io */ chan_width_dist_ptr->chan_width_io = get_one_float (ptr, 3, 0. ,5000., fp_arch, buf); continue; } if (strcmp(ptr,names[4]) == 0) { /* outpin */ get_pin (ptr, pinnum, DRIVER, fp_arch, buf); pinnum++; isread[4]++; continue; } if (strcmp(ptr,names[5]) == 0) { /* inpin */ get_pin (ptr, pinnum, RECEIVER, fp_arch, buf); pinnum++; isread[5]++; continue; } if (strcmp(ptr,names[6]) == 0) { /* subblocks_per_clb */ subblock_data_ptr->max_subblocks_per_block = get_int (ptr, 6, fp_arch, buf, 1); continue; } if (strcmp(ptr,names[7]) == 0) { /* subblock_lut_size */ subblock_data_ptr->subblock_lut_size = get_int (ptr, 7, fp_arch, buf, 1); continue; } if (strcmp(ptr,names[DETAILED_START]) == 0) { /* Fc_output */ det_routing_arch->Fc_output = get_one_float (ptr, DETAILED_START, 0., 1.e20, fp_arch, buf); continue; } if (strcmp(ptr,names[DETAILED_START + 1]) == 0) { /* Fc_input */ det_routing_arch->Fc_input = get_one_float (ptr, DETAILED_START + 1, 0., 1.e20, fp_arch, buf); continue; } if (strcmp(ptr,names[DETAILED_START + 2]) == 0) { /* Fc_pad */ det_routing_arch->Fc_pad = get_one_float (ptr, DETAILED_START + 2, 0., 1.e20, fp_arch, buf); continue; } if (strcmp(ptr,names[DETAILED_START + 3]) == 0) { /* Fc_type */ det_routing_arch->Fc_type = get_Fc_type (ptr, fp_arch, buf); isread[DETAILED_START + 3]++; continue; } if (strcmp(ptr,names[DETAILED_START + 4]) == 0) { /* switch_block_type */ det_routing_arch->switch_block_type = get_switch_block_type (fp_arch, buf); isread[DETAILED_START + 4]++; continue; } if (strcmp(ptr,names[DETAILED_START + 5]) == 0) { /* segment */ get_segment_inf (fp_arch, buf, *segment_inf_ptr + next_segment, det_routing_arch->num_switch, route_type); next_segment++; isread[DETAILED_START + 5]++; continue; } if (strcmp(ptr,names[DETAILED_START + 6]) == 0) { /* switch */ get_switch_inf (fp_arch, buf, det_routing_arch->num_switch, route_type); isread[DETAILED_START + 6]++; continue; } if (strcmp(ptr,names[DETAILED_START + 7]) == 0) { /* R_minW_nmos */ det_routing_arch->R_minW_nmos = get_one_float (ptr, DETAILED_START + 7, 0., 1.e20, fp_arch, buf); continue; } if (strcmp(ptr,names[DETAILED_START + 8]) == 0) { /* R_minW_pmos */ det_routing_arch->R_minW_pmos = get_one_float (ptr, DETAILED_START + 8, 0., 1.e20, fp_arch, buf); continue; } if (strcmp(ptr,names[TIMING_START]) == 0) { /* C_ipin_cblock */ timing_inf_ptr->C_ipin_cblock = get_one_float (ptr, TIMING_START, -1e-30, 1e20, fp_arch, buf); continue; } if (strcmp(ptr,names[TIMING_START + 1]) == 0) { /* T_ipin_cblock */ timing_inf_ptr->T_ipin_cblock = get_one_float (ptr, TIMING_START + 1, -1e-30, 1e20, fp_arch, buf); continue; } if (strcmp(ptr,names[TIMING_START + 2]) == 0) { /* T_sblk_opin_to_sblk_ipin */ timing_inf_ptr->T_sblk_opin_to_sblk_ipin = get_one_float (ptr, TIMING_START + 2, -1e-30, 1e20, fp_arch, buf); continue; } if (strcmp(ptr,names[TIMING_START + 3]) == 0) { /* T_clb_ipin_to_sblk_ipin */ timing_inf_ptr->T_clb_ipin_to_sblk_ipin = get_one_float (ptr, TIMING_START + 3, -1e-30, 1e20, fp_arch, buf); continue; } if (strcmp(ptr,names[TIMING_START + 4]) == 0) { /* T_sblk_opin_to_clb_opin */ timing_inf_ptr->T_sblk_opin_to_clb_opin = get_one_float (ptr, TIMING_START + 4, -1e-30, 1e20, fp_arch, buf); continue; } if (strcmp(ptr,names[TIMING_START + 5]) == 0) { /* T_ipad */ timing_inf_ptr->T_ipad = get_one_float (ptr, TIMING_START + 5, -1e-30, 1e20, fp_arch, buf); continue; } if (strcmp(ptr,names[TIMING_START + 6]) == 0) { /* T_opad */ timing_inf_ptr->T_opad = get_one_float (ptr, TIMING_START + 6, -1e-30, 1e20, fp_arch, buf); continue; } if (strcmp(ptr,names[TIMING_START + 7]) == 0) { /* T_subblock */ next_T_subblock_ptr = timing_inf_ptr->T_subblock + isread[TIMING_START + 7]; get_T_subblock (fp_arch, buf, next_T_subblock_ptr); isread[TIMING_START + 7]++; continue; } printf ("Error: unrecognized keyword (%s) on line %d.\n", ptr, linenum); exit (1); } if (route_type == GLOBAL) { load_global_segment_and_switch (det_routing_arch, *segment_inf_ptr, timing_inf_ptr); } else { load_extra_switch_types (det_routing_arch, timing_inf_ptr); } check_arch (arch_file, route_type, *det_routing_arch, *segment_inf_ptr, *timing_inf_ptr, subblock_data_ptr->max_subblocks_per_block, *chan_width_dist_ptr); fclose (fp_arch);}static void countpass (FILE *fp_arch, enum e_route_type route_type, t_segment_inf **segment_inf_ptr, struct s_det_routing_arch *det_routing_arch_ptr, t_timing_inf *timing_inf_ptr) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -