VPR-6.0
|
00001 /* 00002 * @file 00003 * 00004 * Jason Luu 00005 * April 15, 2011 00006 * Loads statistical information (min/max delays, power) onto the pb_graph. 00007 */ 00008 00009 #include <stdlib.h> 00010 #include <stdio.h> 00011 #include <assert.h> 00012 #include <string.h> 00013 00014 #include "util.h" 00015 #include "arch_types.h" 00016 #include "vpr_types.h" 00017 #include "globals.h" 00018 #include "vpr_utils.h" 00019 #include "pb_type_graph.h" 00020 #include "token.h" 00021 #include "pb_type_graph_annotations.h" 00022 00023 00024 00025 static void load_critical_path_annotations(INOUTP t_pb_graph_node *pb_graph_node, 00026 INP int mode, 00027 INP enum e_pin_to_pin_annotation_format input_format, 00028 INP enum e_pin_to_pin_delay_annotations delay_type, 00029 INP char *annot_in_pins, 00030 INP char *annot_out_pins, 00031 INP char* value); 00032 00033 static t_tedge * find_edge(); 00034 00035 void load_pb_graph_pin_to_pin_annotations(INOUTP t_pb_graph_node *pb_graph_node) 00036 { 00037 int i, j, k, m; 00038 const t_pb_type *pb_type; 00039 t_pin_to_pin_annotation *annotations; 00040 00041 pb_type = pb_graph_node->pb_type; 00042 00043 /* Load primitive critical path delays */ 00044 if(pb_type->num_modes == 0) { 00045 annotations = pb_type->annotations; 00046 for(i = 0; i < pb_type->num_annotations; i++) { 00047 if(annotations[i].type == E_ANNOT_PIN_TO_PIN_DELAY) { 00048 for(j = 0; j < annotations[i].num_value_prop_pairs; j++) { 00049 if( annotations[i].prop[j] == E_ANNOT_PIN_TO_PIN_DELAY_MAX || 00050 annotations[i].prop[j] == E_ANNOT_PIN_TO_PIN_DELAY_CLOCK_TO_Q_MAX || 00051 annotations[i].prop[j] == E_ANNOT_PIN_TO_PIN_DELAY_TSETUP ) { 00052 load_critical_path_annotations(pb_graph_node, OPEN, annotations[i].format, annotations[i].prop[j], annotations[i].input_pins, annotations[i].output_pins, annotations[i].value[j]); 00053 } else { 00054 assert(annotations[i].prop[j] == E_ANNOT_PIN_TO_PIN_DELAY_MIN || 00055 annotations[i].prop[j] == E_ANNOT_PIN_TO_PIN_DELAY_CLOCK_TO_Q_MIN || 00056 annotations[i].prop[j] == E_ANNOT_PIN_TO_PIN_DELAY_THOLD ); 00057 } 00058 } 00059 } else { 00060 /* Todo: 00061 load_hold_time_constraints_annotations(pb_graph_node); 00062 load_power_annotations(pb_graph_node); 00063 */ 00064 } 00065 } 00066 } else { 00067 /* Load interconnect delays */ 00068 for(i = 0; i < pb_type->num_modes; i++) { 00069 for(j = 0; j < pb_type->modes[i].num_interconnect; j++) { 00070 annotations = pb_type->modes[i].interconnect[j].annotations; 00071 for(k = 0; k < pb_type->modes[i].interconnect[j].num_annotations; k++) { 00072 if(annotations[k].type == E_ANNOT_PIN_TO_PIN_DELAY) { 00073 for(m = 0; m < annotations[k].num_value_prop_pairs; m++) { 00074 if( annotations[k].prop[m] == E_ANNOT_PIN_TO_PIN_DELAY_MAX || 00075 annotations[k].prop[m] == E_ANNOT_PIN_TO_PIN_DELAY_CLOCK_TO_Q_MAX || 00076 annotations[k].prop[m] == E_ANNOT_PIN_TO_PIN_DELAY_TSETUP ) { 00077 load_critical_path_annotations(pb_graph_node, i, annotations[k].format, annotations[k].prop[m], 00078 annotations[k].input_pins, annotations[k].output_pins, annotations[k].value[m]); 00079 } else { 00080 assert(annotations[k].prop[m] == E_ANNOT_PIN_TO_PIN_DELAY_MIN || 00081 annotations[k].prop[m] == E_ANNOT_PIN_TO_PIN_DELAY_CLOCK_TO_Q_MIN || 00082 annotations[k].prop[m] == E_ANNOT_PIN_TO_PIN_DELAY_THOLD ); 00083 } 00084 } 00085 } else { 00086 /* Todo: 00087 load_hold_time_constraints_annotations(pb_graph_node); 00088 load_power_annotations(pb_graph_node); 00089 */ 00090 } 00091 } 00092 } 00093 } 00094 } 00095 00096 for(i = 0; i < pb_type->num_modes; i++) { 00097 for(j = 0; j < pb_type->modes[i].num_pb_type_children; j++) { 00098 for(k = 0; k < pb_type->modes[i].pb_type_children[j].num_pb; k++) { 00099 load_pb_graph_pin_to_pin_annotations(&pb_graph_node->child_pb_graph_nodes[i][j][k]); 00100 } 00101 } 00102 } 00103 } 00104 00105 00106 static void load_critical_path_annotations(INOUTP t_pb_graph_node *pb_graph_node, 00107 INP int mode, 00108 INP enum e_pin_to_pin_annotation_format input_format, 00109 INP enum e_pin_to_pin_delay_annotations delay_type, 00110 INP char *annot_in_pins, 00111 INP char *annot_out_pins, 00112 INP char* value) { 00113 00114 int i, j, k, m, n, p, iedge; 00115 t_pb_graph_pin ***in_port, ***out_port; 00116 int *num_in_ptrs, *num_out_ptrs, num_in_sets, num_out_sets; 00117 float **delay_matrix; 00118 t_pb_graph_node **children = NULL; 00119 00120 int count; 00121 int num_inputs, num_outputs; 00122 00123 in_port = out_port = NULL; 00124 num_out_sets = num_in_sets = 0; 00125 num_out_ptrs = num_in_ptrs = NULL; 00126 00127 00128 /* Primarily 3 kinds of delays that affect critical path: 00129 1. Intrablock interconnect delays 00130 2. Combinational primitives (pin-to-pin delays of primitive) 00131 3. Sequential primitives (setup and clock-to-q times) 00132 00133 Note: Proper I/O modelling requires knowledge of the extra-chip world (eg. the load that pin is driving, drive strength, etc) 00134 For now, I/O delays are modelled as a constant in the architecture file by setting the pad-I/O block interconnect delay to be a constant I/O delay 00135 00136 Algorithm: Intrablock and combinational primitive delays apply to edges 00137 Sequential delays apply to pins 00138 1. Determine if delay applies to pin or edge 00139 2. Format the delay information 00140 3. Load delay information 00141 */ 00142 00143 00144 /* Determine what pins to read based on delay type */ 00145 num_inputs = num_outputs = 0; 00146 if(mode == OPEN) { 00147 children = NULL; 00148 } else { 00149 children = pb_graph_node->child_pb_graph_nodes[mode]; 00150 } 00151 if(delay_type == E_ANNOT_PIN_TO_PIN_DELAY_TSETUP) { 00152 assert(pb_graph_node->pb_type->blif_model != NULL); 00153 in_port = alloc_and_load_port_pin_ptrs_from_string(pb_graph_node, 00154 children, 00155 annot_in_pins, 00156 &num_in_ptrs, 00157 &num_in_sets, 00158 FALSE, 00159 FALSE); 00160 } else if (delay_type == E_ANNOT_PIN_TO_PIN_DELAY_CLOCK_TO_Q_MAX) { 00161 assert(pb_graph_node->pb_type->blif_model != NULL); 00162 in_port = alloc_and_load_port_pin_ptrs_from_string(pb_graph_node, 00163 children, 00164 annot_in_pins, 00165 &num_in_ptrs, 00166 &num_in_sets, 00167 FALSE, 00168 FALSE); 00169 } else { 00170 assert(delay_type == E_ANNOT_PIN_TO_PIN_DELAY_MAX); 00171 in_port = alloc_and_load_port_pin_ptrs_from_string(pb_graph_node, 00172 children, 00173 annot_in_pins, 00174 &num_in_ptrs, 00175 &num_in_sets, 00176 FALSE, 00177 FALSE); 00178 out_port = alloc_and_load_port_pin_ptrs_from_string(pb_graph_node, 00179 children, 00180 annot_out_pins, 00181 &num_out_ptrs, 00182 &num_out_sets, 00183 FALSE, 00184 FALSE); 00185 } 00186 00187 num_inputs = 0; 00188 for(i = 0; i < num_in_sets; i++) { 00189 num_inputs += num_in_ptrs[i]; 00190 } 00191 00192 if(out_port != NULL) { 00193 num_outputs = 0; 00194 for(i = 0; i < num_out_sets; i++) { 00195 num_outputs += num_out_ptrs[i]; 00196 } 00197 } else { 00198 num_outputs = 1; 00199 } 00200 00201 delay_matrix = my_malloc(sizeof(float*) * num_inputs); 00202 for(i = 0; i < num_inputs; i++) { 00203 delay_matrix[i] = my_malloc(sizeof(float) * num_outputs); 00204 } 00205 00206 if(input_format == E_ANNOT_PIN_TO_PIN_MATRIX) { 00207 my_atof_2D(delay_matrix, num_inputs, num_outputs, value); 00208 } else { 00209 assert(input_format == E_ANNOT_PIN_TO_PIN_CONSTANT); 00210 for(i = 0; i < num_inputs; i++) { 00211 for(j = 0; j < num_outputs; j++) { 00212 delay_matrix[i][j] = atof(value); 00213 } 00214 } 00215 } 00216 00217 if(delay_type == E_ANNOT_PIN_TO_PIN_DELAY_TSETUP || delay_type == E_ANNOT_PIN_TO_PIN_DELAY_CLOCK_TO_Q_MAX) { 00218 k = 0; 00219 for(i = 0; i < num_in_sets; i++) { 00220 for(j = 0; j < num_in_ptrs[i]; j++) { 00221 in_port[i][j]->tsu_tco = delay_matrix[k][0]; 00222 k++; 00223 } 00224 } 00225 } else { 00226 if(pb_graph_node->pb_type->num_modes != 0) { 00227 /* Not a primitive, find pb_graph_edge */ 00228 k = 0; 00229 for(i = 0; i < num_in_sets; i++) { 00230 for(j = 0; j < num_in_ptrs[i]; j++) { 00231 p = 0; 00232 for(m = 0; m < num_out_sets; m++) { 00233 for(n = 0; n < num_out_ptrs[m]; n++) { 00234 for(iedge = 0; iedge < in_port[i][j]->num_output_edges; iedge++) { 00235 if(in_port[i][j]->output_edges[iedge]->output_pins[0] == out_port[m][n]) { 00236 assert(in_port[i][j]->output_edges[iedge]->delay_max == 0); 00237 break; 00238 } 00239 } 00240 /* jluu Todo: This is inefficient, I know the interconnect so I know what edges exist 00241 can use this info to only annotate existing edges */ 00242 if(iedge != in_port[i][j]->num_output_edges) { 00243 in_port[i][j]->output_edges[iedge]->delay_max = delay_matrix[k][p]; 00244 } 00245 p++; 00246 } 00247 } 00248 k++; 00249 } 00250 } 00251 } else { 00252 /* Primitive, allocate appropriate nodes */ 00253 k = 0; 00254 for(i = 0; i < num_in_sets; i++) { 00255 for(j = 0; j < num_in_ptrs[i]; j++) { 00256 delay_matrix[k][0]; 00257 count = p = 0; 00258 for(m = 0; m < num_out_sets; m++) { 00259 for(n = 0; n < num_out_ptrs[m]; n++) { 00260 /* OPEN indicates that connection does not exist */ 00261 if(delay_matrix[k][p] != OPEN) { 00262 count++; 00263 } 00264 p++; 00265 } 00266 } 00267 in_port[i][j]->num_pin_timing = count; 00268 in_port[i][j]->pin_timing_del_max = my_malloc(sizeof(float) * count); 00269 in_port[i][j]->pin_timing = my_malloc(sizeof(t_pb_graph_pin*) * count); 00270 p = 0; 00271 count = 0; 00272 for(m = 0; m < num_out_sets; m++) { 00273 for(n = 0; n < num_out_ptrs[m]; n++) { 00274 if(delay_matrix[k][p] != OPEN) { 00275 in_port[i][j]->pin_timing_del_max[count] = delay_matrix[k][p]; 00276 in_port[i][j]->pin_timing[count] = out_port[m][n]; 00277 count++; 00278 } 00279 p++; 00280 } 00281 } 00282 assert(in_port[i][j]->num_pin_timing == count); 00283 k++; 00284 } 00285 } 00286 } 00287 } 00288 if(in_port != NULL) { 00289 for(i = 0; i < num_in_sets; i++) { 00290 free(in_port[i]); 00291 } 00292 free(in_port); 00293 free(num_in_ptrs); 00294 } 00295 if(out_port != NULL) { 00296 for(i = 0; i < num_out_sets; i++) { 00297 free(out_port[i]); 00298 } 00299 free(out_port); 00300 free(num_out_ptrs); 00301 } 00302 for(i = 0; i < num_inputs; i++) { 00303 free(delay_matrix[i]); 00304 } 00305 free(delay_matrix); 00306 }