| #include <cstring> |
| |
| #include "vtr_assert.h" |
| #include "vtr_memory.h" |
| #include "vtr_util.h" |
| |
| #include "arch_types.h" |
| #include "arch_util.h" |
| #include "arch_error.h" |
| |
| |
| |
| #include "read_xml_arch_file.h" |
| #include "read_xml_util.h" |
| |
| static void free_all_pb_graph_nodes(t_type_descriptor* type_descriptors, int num_type_descriptors); |
| static void free_pb_graph(t_pb_graph_node *pb_graph_node); |
| static void free_pb_type(t_pb_type *pb_type); |
| |
| void free_arch(t_arch* arch) { |
| if (arch == nullptr) { |
| return; |
| } |
| |
| for (int i = 0; i < arch->num_switches; ++i) { |
| if (arch->Switches->name != nullptr) { |
| vtr::free(arch->Switches[i].name); |
| } |
| } |
| delete[] arch->Switches; |
| arch->Switches = nullptr; |
| t_model *model = arch->models; |
| while (model) { |
| t_model_ports *input_port = model->inputs; |
| while (input_port) { |
| t_model_ports *prev_port = input_port; |
| input_port = input_port->next; |
| vtr::free(prev_port->name); |
| delete prev_port; |
| } |
| t_model_ports *output_port = model->outputs; |
| while (output_port) { |
| t_model_ports *prev_port = output_port; |
| output_port = output_port->next; |
| vtr::free(prev_port->name); |
| delete prev_port; |
| } |
| vtr::t_linked_vptr *vptr = model->pb_types; |
| while (vptr) { |
| vtr::t_linked_vptr *vptr_prev = vptr; |
| vptr = vptr->next; |
| vtr::free(vptr_prev); |
| } |
| t_model *prev_model = model; |
| |
| model = model->next; |
| if (prev_model->instances) |
| vtr::free(prev_model->instances); |
| vtr::free(prev_model->name); |
| delete prev_model; |
| } |
| |
| for (int i = 0; i < arch->num_directs; ++i) { |
| vtr::free(arch->Directs[i].name); |
| vtr::free(arch->Directs[i].from_pin); |
| vtr::free(arch->Directs[i].to_pin); |
| } |
| vtr::free(arch->Directs); |
| |
| vtr::free(arch->architecture_id); |
| |
| if (arch->model_library) { |
| for (int i = 0; i < 4; ++i) { |
| vtr::t_linked_vptr *vptr = arch->model_library[i].pb_types; |
| while (vptr) { |
| vtr::t_linked_vptr *vptr_prev = vptr; |
| vptr = vptr->next; |
| vtr::free(vptr_prev); |
| } |
| } |
| |
| vtr::free(arch->model_library[0].name); |
| vtr::free(arch->model_library[0].outputs->name); |
| delete[] arch->model_library[0].outputs; |
| vtr::free(arch->model_library[1].inputs->name); |
| delete[] arch->model_library[1].inputs; |
| vtr::free(arch->model_library[1].name); |
| vtr::free(arch->model_library[2].name); |
| vtr::free(arch->model_library[2].inputs[0].name); |
| vtr::free(arch->model_library[2].inputs[1].name); |
| delete[] arch->model_library[2].inputs; |
| vtr::free(arch->model_library[2].outputs->name); |
| delete[] arch->model_library[2].outputs; |
| vtr::free(arch->model_library[3].name); |
| vtr::free(arch->model_library[3].inputs->name); |
| delete[] arch->model_library[3].inputs; |
| vtr::free(arch->model_library[3].outputs->name); |
| delete[] arch->model_library[3].outputs; |
| delete[] arch->model_library; |
| } |
| |
| if (arch->clocks) { |
| vtr::free(arch->clocks->clock_inf); |
| } |
| } |
| |
| void free_type_descriptors(t_type_descriptor* type_descriptors, int num_type_descriptors) { |
| free_all_pb_graph_nodes(type_descriptors, num_type_descriptors); |
| |
| for (int i = 0; i < num_type_descriptors; ++i) { |
| |
| vtr::free(type_descriptors[i].name); |
| if (i == EMPTY_TYPE_INDEX) { |
| continue; |
| } |
| |
| for (int width = 0; width < type_descriptors[i].width; ++width) { |
| for (int height = 0; height < type_descriptors[i].height; ++height) { |
| for (int side = 0; side < 4; ++side) { |
| for (int pin = 0; pin < type_descriptors[i].num_pin_loc_assignments[width][height][side]; ++pin) { |
| if (type_descriptors[i].pin_loc_assignments[width][height][side][pin]) |
| vtr::free(type_descriptors[i].pin_loc_assignments[width][height][side][pin]); |
| } |
| vtr::free(type_descriptors[i].pinloc[width][height][side]); |
| vtr::free(type_descriptors[i].pin_loc_assignments[width][height][side]); |
| } |
| vtr::free(type_descriptors[i].pinloc[width][height]); |
| vtr::free(type_descriptors[i].pin_loc_assignments[width][height]); |
| vtr::free(type_descriptors[i].num_pin_loc_assignments[width][height]); |
| } |
| vtr::free(type_descriptors[i].pinloc[width]); |
| vtr::free(type_descriptors[i].pin_loc_assignments[width]); |
| vtr::free(type_descriptors[i].num_pin_loc_assignments[width]); |
| } |
| vtr::free(type_descriptors[i].pinloc); |
| vtr::free(type_descriptors[i].pin_loc_assignments); |
| vtr::free(type_descriptors[i].num_pin_loc_assignments); |
| |
| for (int j = 0; j < type_descriptors[i].num_class; ++j) { |
| vtr::free(type_descriptors[i].class_inf[j].pinlist); |
| } |
| vtr::free(type_descriptors[i].class_inf); |
| vtr::free(type_descriptors[i].is_ignored_pin); |
| vtr::free(type_descriptors[i].pin_class); |
| |
| free_pb_type(type_descriptors[i].pb_type); |
| delete type_descriptors[i].pb_type; |
| } |
| delete[] type_descriptors; |
| } |
| |
| static void free_all_pb_graph_nodes(t_type_descriptor* type_descriptors, int num_type_descriptors) { |
| for (int i = 0; i < num_type_descriptors; i++) { |
| if (type_descriptors[i].pb_type) { |
| if (type_descriptors[i].pb_graph_head) { |
| free_pb_graph(type_descriptors[i].pb_graph_head); |
| vtr::free(type_descriptors[i].pb_graph_head); |
| } |
| } |
| } |
| } |
| |
| static void free_pb_graph(t_pb_graph_node *pb_graph_node) { |
| |
| int i, j, k; |
| const t_pb_type *pb_type; |
| |
| pb_type = pb_graph_node->pb_type; |
| |
| /*free all lists of connectable input pin pointer of pb_graph_node and it's children*/ |
| /*free_list_of_connectable_input_pin_ptrs (pb_graph_node);*/ |
| |
| /* Free ports for pb graph node */ |
| for (i = 0; i < pb_graph_node->num_input_ports; i++) { |
| for (j = 0; j < pb_graph_node->num_input_pins[i]; j++) { |
| if (pb_graph_node->input_pins[i][j].pin_timing) |
| vtr::free(pb_graph_node->input_pins[i][j].pin_timing); |
| if (pb_graph_node->input_pins[i][j].pin_timing_del_max) |
| vtr::free(pb_graph_node->input_pins[i][j].pin_timing_del_max); |
| if (pb_graph_node->input_pins[i][j].pin_timing_del_min) |
| vtr::free(pb_graph_node->input_pins[i][j].pin_timing_del_min); |
| if (pb_graph_node->input_pins[i][j].input_edges) |
| vtr::free(pb_graph_node->input_pins[i][j].input_edges); |
| if (pb_graph_node->input_pins[i][j].output_edges) |
| vtr::free(pb_graph_node->input_pins[i][j].output_edges); |
| if (pb_graph_node->input_pins[i][j].parent_pin_class) |
| vtr::free(pb_graph_node->input_pins[i][j].parent_pin_class); |
| } |
| delete[] pb_graph_node->input_pins[i]; |
| } |
| for (i = 0; i < pb_graph_node->num_output_ports; i++) { |
| for (j = 0; j < pb_graph_node->num_output_pins[i]; j++) { |
| if (pb_graph_node->output_pins[i][j].pin_timing) |
| vtr::free(pb_graph_node->output_pins[i][j].pin_timing); |
| if (pb_graph_node->output_pins[i][j].pin_timing_del_max) |
| vtr::free(pb_graph_node->output_pins[i][j].pin_timing_del_max); |
| if (pb_graph_node->output_pins[i][j].pin_timing_del_min) |
| vtr::free(pb_graph_node->output_pins[i][j].pin_timing_del_min); |
| if (pb_graph_node->output_pins[i][j].input_edges) |
| vtr::free(pb_graph_node->output_pins[i][j].input_edges); |
| if (pb_graph_node->output_pins[i][j].output_edges) |
| vtr::free(pb_graph_node->output_pins[i][j].output_edges); |
| if (pb_graph_node->output_pins[i][j].parent_pin_class) |
| vtr::free(pb_graph_node->output_pins[i][j].parent_pin_class); |
| |
| if (pb_graph_node->output_pins[i][j].list_of_connectable_input_pin_ptrs) { |
| for (k = 0; k < pb_graph_node->pb_type->depth; k++) { |
| if (pb_graph_node->output_pins[i][j].list_of_connectable_input_pin_ptrs[k]) { |
| vtr::free( |
| pb_graph_node->output_pins[i][j].list_of_connectable_input_pin_ptrs[k]); |
| } |
| } |
| vtr::free( |
| pb_graph_node->output_pins[i][j].list_of_connectable_input_pin_ptrs); |
| } |
| |
| if (pb_graph_node->output_pins[i][j].num_connectable_primitive_input_pins) |
| vtr::free( |
| pb_graph_node->output_pins[i][j].num_connectable_primitive_input_pins); |
| } |
| delete[] pb_graph_node->output_pins[i]; |
| } |
| for (i = 0; i < pb_graph_node->num_clock_ports; i++) { |
| for (j = 0; j < pb_graph_node->num_clock_pins[i]; j++) { |
| if (pb_graph_node->clock_pins[i][j].pin_timing) |
| vtr::free(pb_graph_node->clock_pins[i][j].pin_timing); |
| if (pb_graph_node->clock_pins[i][j].pin_timing_del_max) |
| vtr::free(pb_graph_node->clock_pins[i][j].pin_timing_del_max); |
| if (pb_graph_node->clock_pins[i][j].pin_timing_del_min) |
| vtr::free(pb_graph_node->clock_pins[i][j].pin_timing_del_min); |
| if (pb_graph_node->clock_pins[i][j].input_edges) |
| vtr::free(pb_graph_node->clock_pins[i][j].input_edges); |
| if (pb_graph_node->clock_pins[i][j].output_edges) |
| vtr::free(pb_graph_node->clock_pins[i][j].output_edges); |
| if (pb_graph_node->clock_pins[i][j].parent_pin_class) |
| vtr::free(pb_graph_node->clock_pins[i][j].parent_pin_class); |
| } |
| delete[] pb_graph_node->clock_pins[i]; |
| } |
| |
| |
| for (i = 0; i < pb_graph_node->pb_type->num_modes; i++) { |
| vtr::free(pb_graph_node->interconnect_pins[i]); |
| } |
| vtr::free(pb_graph_node->interconnect_pins); |
| |
| vtr::free(pb_graph_node->input_pins); |
| vtr::free(pb_graph_node->output_pins); |
| vtr::free(pb_graph_node->clock_pins); |
| |
| vtr::free(pb_graph_node->num_input_pins); |
| vtr::free(pb_graph_node->num_output_pins); |
| vtr::free(pb_graph_node->num_clock_pins); |
| |
| vtr::free(pb_graph_node->input_pin_class_size); |
| vtr::free(pb_graph_node->output_pin_class_size); |
| |
| for (i = 0; i < pb_type->num_modes; i++) { |
| for (j = 0; j < pb_type->modes[i].num_pb_type_children; j++) { |
| for (k = 0; k < pb_type->modes[i].pb_type_children[j].num_pb; k++) { |
| free_pb_graph(&pb_graph_node->child_pb_graph_nodes[i][j][k]); |
| } |
| vtr::free(pb_graph_node->child_pb_graph_nodes[i][j]); |
| } |
| vtr::free(pb_graph_node->child_pb_graph_nodes[i]); |
| } |
| vtr::free(pb_graph_node->child_pb_graph_nodes); |
| } |
| |
| static void free_pb_type(t_pb_type *pb_type) { |
| vtr::free(pb_type->name); |
| if (pb_type->blif_model) |
| vtr::free(pb_type->blif_model); |
| |
| for (int i = 0; i < pb_type->num_modes; ++i) { |
| for (int j = 0; j < pb_type->modes[i].num_pb_type_children; ++j) { |
| free_pb_type(&pb_type->modes[i].pb_type_children[j]); |
| } |
| delete[] pb_type->modes[i].pb_type_children; |
| vtr::free(pb_type->modes[i].name); |
| for (int j = 0; j < pb_type->modes[i].num_interconnect; ++j) { |
| vtr::free(pb_type->modes[i].interconnect[j].input_string); |
| vtr::free(pb_type->modes[i].interconnect[j].output_string); |
| vtr::free(pb_type->modes[i].interconnect[j].name); |
| |
| for (int k = 0; k < pb_type->modes[i].interconnect[j].num_annotations; ++k) { |
| if (pb_type->modes[i].interconnect[j].annotations[k].clock) |
| vtr::free(pb_type->modes[i].interconnect[j].annotations[k].clock); |
| if (pb_type->modes[i].interconnect[j].annotations[k].input_pins) { |
| vtr::free(pb_type->modes[i].interconnect[j].annotations[k].input_pins); |
| } |
| if (pb_type->modes[i].interconnect[j].annotations[k].output_pins) { |
| vtr::free(pb_type->modes[i].interconnect[j].annotations[k].output_pins); |
| } |
| for (int m = 0; m < pb_type->modes[i].interconnect[j].annotations[k].num_value_prop_pairs; ++m) { |
| vtr::free(pb_type->modes[i].interconnect[j].annotations[k].value[m]); |
| } |
| vtr::free(pb_type->modes[i].interconnect[j].annotations[k].prop); |
| vtr::free(pb_type->modes[i].interconnect[j].annotations[k].value); |
| } |
| vtr::free(pb_type->modes[i].interconnect[j].annotations); |
| if (pb_type->modes[i].interconnect[j].interconnect_power) |
| vtr::free(pb_type->modes[i].interconnect[j].interconnect_power); |
| } |
| if (pb_type->modes[i].interconnect) |
| vtr::free(pb_type->modes[i].interconnect); |
| if (pb_type->modes[i].mode_power) |
| vtr::free(pb_type->modes[i].mode_power); |
| } |
| if (pb_type->modes) |
| vtr::free(pb_type->modes); |
| |
| for (int i = 0; i < pb_type->num_annotations; ++i) { |
| for (int j = 0; j < pb_type->annotations[i].num_value_prop_pairs; ++j) { |
| vtr::free(pb_type->annotations[i].value[j]); |
| } |
| vtr::free(pb_type->annotations[i].value); |
| vtr::free(pb_type->annotations[i].prop); |
| if (pb_type->annotations[i].input_pins) { |
| vtr::free(pb_type->annotations[i].input_pins); |
| } |
| if (pb_type->annotations[i].output_pins) { |
| vtr::free(pb_type->annotations[i].output_pins); |
| } |
| if (pb_type->annotations[i].clock) { |
| vtr::free(pb_type->annotations[i].clock); |
| } |
| } |
| if (pb_type->num_annotations > 0) { |
| vtr::free(pb_type->annotations); |
| } |
| |
| if (pb_type->pb_type_power) { |
| vtr::free(pb_type->pb_type_power); |
| } |
| |
| for (int i = 0; i < pb_type->num_ports; ++i) { |
| vtr::free(pb_type->ports[i].name); |
| if (pb_type->ports[i].port_class) { |
| vtr::free(pb_type->ports[i].port_class); |
| } |
| if (pb_type->ports[i].port_power) { |
| vtr::free(pb_type->ports[i].port_power); |
| } |
| } |
| vtr::free(pb_type->ports); |
| } |
| |
| t_port * findPortByName(const char * name, t_pb_type * pb_type, |
| int * high_index, int * low_index) { |
| t_port * port; |
| int i; |
| unsigned int high; |
| unsigned int low; |
| unsigned int bracket_pos; |
| unsigned int colon_pos; |
| |
| bracket_pos = strcspn(name, "["); |
| |
| /* Find port by name */ |
| port = nullptr; |
| for (i = 0; i < pb_type->num_ports; i++) { |
| char * compare_to = pb_type->ports[i].name; |
| |
| if (strlen(compare_to) == bracket_pos |
| && strncmp(name, compare_to, bracket_pos) == 0) { |
| port = &pb_type->ports[i]; |
| break; |
| } |
| } |
| if (i >= pb_type->num_ports) { |
| return nullptr; |
| } |
| |
| /* Get indices */ |
| if (strlen(name) > bracket_pos) { |
| high = atoi(&name[bracket_pos + 1]); |
| |
| colon_pos = strcspn(name, ":"); |
| |
| if (colon_pos < strlen(name)) { |
| low = atoi(&name[colon_pos + 1]); |
| } else { |
| low = high; |
| } |
| } else { |
| high = port->num_pins - 1; |
| low = 0; |
| } |
| |
| if (high_index && low_index) { |
| *high_index = high; |
| *low_index = low; |
| } |
| |
| return port; |
| } |
| |
| void SetupEmptyType(t_type_descriptor* cb_type_descriptors, |
| t_type_ptr EMPTY_TYPE) { |
| t_type_descriptor * type; |
| type = &cb_type_descriptors[EMPTY_TYPE->index]; |
| type->name = vtr::strdup("EMPTY"); |
| type->num_pins = 0; |
| type->width = 1; |
| type->height = 1; |
| type->capacity = 0; |
| type->num_drivers = 0; |
| type->num_receivers = 0; |
| type->pinloc = nullptr; |
| type->num_class = 0; |
| type->class_inf = nullptr; |
| type->pin_class = nullptr; |
| type->is_ignored_pin = nullptr; |
| type->pb_type = nullptr; |
| type->area = UNDEFINED; |
| type->switchblock_locations = vtr::Matrix<e_sb_type>({{size_t(type->width), size_t(type->height)}}, e_sb_type::FULL); |
| type->switchblock_switch_overrides = vtr::Matrix<int>({{size_t(type->width), size_t(type->height)}}, DEFAULT_SWITCH); |
| } |
| |
| void alloc_and_load_default_child_for_pb_type( t_pb_type *pb_type, |
| char *new_name, t_pb_type *copy) { |
| int i, j; |
| char *dot; |
| |
| VTR_ASSERT(pb_type->blif_model != nullptr); |
| |
| copy->name = vtr::strdup(new_name); |
| copy->blif_model = vtr::strdup(pb_type->blif_model); |
| copy->class_type = pb_type->class_type; |
| copy->depth = pb_type->depth; |
| copy->model = pb_type->model; |
| copy->modes = nullptr; |
| copy->num_modes = 0; |
| copy->num_clock_pins = pb_type->num_clock_pins; |
| copy->num_input_pins = pb_type->num_input_pins; |
| copy->num_output_pins = pb_type->num_output_pins; |
| copy->num_pb = 1; |
| |
| /* Power */ |
| copy->pb_type_power = (t_pb_type_power*) vtr::calloc(1, |
| sizeof(t_pb_type_power)); |
| copy->pb_type_power->estimation_method = power_method_inherited( |
| pb_type->pb_type_power->estimation_method); |
| |
| /* Ports */ |
| copy->num_ports = pb_type->num_ports; |
| copy->ports = (t_port*) vtr::calloc(pb_type->num_ports, sizeof(t_port)); |
| for (i = 0; i < pb_type->num_ports; i++) { |
| copy->ports[i].is_clock = pb_type->ports[i].is_clock; |
| copy->ports[i].model_port = pb_type->ports[i].model_port; |
| copy->ports[i].type = pb_type->ports[i].type; |
| copy->ports[i].num_pins = pb_type->ports[i].num_pins; |
| copy->ports[i].parent_pb_type = copy; |
| copy->ports[i].name = vtr::strdup(pb_type->ports[i].name); |
| copy->ports[i].port_class = vtr::strdup(pb_type->ports[i].port_class); |
| copy->ports[i].port_index_by_type = pb_type->ports[i].port_index_by_type; |
| |
| copy->ports[i].port_power = (t_port_power*) vtr::calloc(1, |
| sizeof(t_port_power)); |
| //Defaults |
| if (copy->pb_type_power->estimation_method == POWER_METHOD_AUTO_SIZES) { |
| copy->ports[i].port_power->wire_type = POWER_WIRE_TYPE_AUTO; |
| copy->ports[i].port_power->buffer_type = POWER_BUFFER_TYPE_AUTO; |
| } else if (copy->pb_type_power->estimation_method |
| == POWER_METHOD_SPECIFY_SIZES) { |
| copy->ports[i].port_power->wire_type = POWER_WIRE_TYPE_IGNORED; |
| copy->ports[i].port_power->buffer_type = POWER_BUFFER_TYPE_NONE; |
| } |
| } |
| |
| copy->max_internal_delay = pb_type->max_internal_delay; |
| copy->annotations = (t_pin_to_pin_annotation*) vtr::calloc( |
| pb_type->num_annotations, sizeof(t_pin_to_pin_annotation)); |
| copy->num_annotations = pb_type->num_annotations; |
| for (i = 0; i < copy->num_annotations; i++) { |
| copy->annotations[i].clock = vtr::strdup(pb_type->annotations[i].clock); |
| dot = strstr(pb_type->annotations[i].input_pins, "."); |
| copy->annotations[i].input_pins = (char*) vtr::malloc( |
| sizeof(char) * (strlen(new_name) + strlen(dot) + 1)); |
| copy->annotations[i].input_pins[0] = '\0'; |
| strcat(copy->annotations[i].input_pins, new_name); |
| strcat(copy->annotations[i].input_pins, dot); |
| if (pb_type->annotations[i].output_pins != nullptr) { |
| dot = strstr(pb_type->annotations[i].output_pins, "."); |
| copy->annotations[i].output_pins = (char*) vtr::malloc( |
| sizeof(char) * (strlen(new_name) + strlen(dot) + 1)); |
| copy->annotations[i].output_pins[0] = '\0'; |
| strcat(copy->annotations[i].output_pins, new_name); |
| strcat(copy->annotations[i].output_pins, dot); |
| } else { |
| copy->annotations[i].output_pins = nullptr; |
| } |
| copy->annotations[i].line_num = pb_type->annotations[i].line_num; |
| copy->annotations[i].format = pb_type->annotations[i].format; |
| copy->annotations[i].type = pb_type->annotations[i].type; |
| copy->annotations[i].num_value_prop_pairs = |
| pb_type->annotations[i].num_value_prop_pairs; |
| copy->annotations[i].prop = (int*) vtr::malloc( |
| sizeof(int) * pb_type->annotations[i].num_value_prop_pairs); |
| copy->annotations[i].value = (char**) vtr::malloc( |
| sizeof(char *) * pb_type->annotations[i].num_value_prop_pairs); |
| for (j = 0; j < pb_type->annotations[i].num_value_prop_pairs; j++) { |
| copy->annotations[i].prop[j] = pb_type->annotations[i].prop[j]; |
| copy->annotations[i].value[j] = vtr::strdup( |
| pb_type->annotations[i].value[j]); |
| } |
| } |
| |
| } |
| |
| /* populate special lut class */ |
| void ProcessLutClass(t_pb_type *lut_pb_type) { |
| char *default_name; |
| t_port *in_port; |
| t_port *out_port; |
| int i, j; |
| |
| if (strcmp(lut_pb_type->name, "lut") != 0) { |
| default_name = vtr::strdup("lut"); |
| } else { |
| default_name = vtr::strdup("lut_child"); |
| } |
| |
| lut_pb_type->num_modes = 2; |
| lut_pb_type->pb_type_power->leakage_default_mode = 1; |
| lut_pb_type->modes = (t_mode*) vtr::calloc(lut_pb_type->num_modes, |
| sizeof(t_mode)); |
| |
| /* First mode, route_through */ |
| lut_pb_type->modes[0].name = vtr::strdup("wire"); |
| lut_pb_type->modes[0].parent_pb_type = lut_pb_type; |
| lut_pb_type->modes[0].index = 0; |
| lut_pb_type->modes[0].num_pb_type_children = 0; |
| lut_pb_type->modes[0].mode_power = (t_mode_power*) vtr::calloc(1, |
| sizeof(t_mode_power)); |
| |
| /* Process interconnect */ |
| /* TODO: add timing annotations to route-through */ |
| VTR_ASSERT(lut_pb_type->num_ports == 2); |
| if (strcmp(lut_pb_type->ports[0].port_class, "lut_in") == 0) { |
| VTR_ASSERT(strcmp(lut_pb_type->ports[1].port_class, "lut_out") == 0); |
| in_port = &lut_pb_type->ports[0]; |
| out_port = &lut_pb_type->ports[1]; |
| } else { |
| VTR_ASSERT(strcmp(lut_pb_type->ports[0].port_class, "lut_out") == 0); |
| VTR_ASSERT(strcmp(lut_pb_type->ports[1].port_class, "lut_in") == 0); |
| out_port = &lut_pb_type->ports[0]; |
| in_port = &lut_pb_type->ports[1]; |
| } |
| lut_pb_type->modes[0].num_interconnect = 1; |
| lut_pb_type->modes[0].interconnect = (t_interconnect*) vtr::calloc(1, |
| sizeof(t_interconnect)); |
| lut_pb_type->modes[0].interconnect[0].name = (char*) vtr::calloc( |
| strlen(lut_pb_type->name) + 10, sizeof(char)); |
| sprintf(lut_pb_type->modes[0].interconnect[0].name, "complete:%s", |
| lut_pb_type->name); |
| lut_pb_type->modes[0].interconnect[0].type = COMPLETE_INTERC; |
| lut_pb_type->modes[0].interconnect[0].input_string = (char*) vtr::calloc( |
| strlen(lut_pb_type->name) + strlen(in_port->name) + 2, |
| sizeof(char)); |
| sprintf(lut_pb_type->modes[0].interconnect[0].input_string, "%s.%s", |
| lut_pb_type->name, in_port->name); |
| lut_pb_type->modes[0].interconnect[0].output_string = (char*) vtr::calloc( |
| strlen(lut_pb_type->name) + strlen(out_port->name) + 2, |
| sizeof(char)); |
| sprintf(lut_pb_type->modes[0].interconnect[0].output_string, "%s.%s", |
| lut_pb_type->name, out_port->name); |
| |
| lut_pb_type->modes[0].interconnect[0].parent_mode_index = 0; |
| lut_pb_type->modes[0].interconnect[0].parent_mode = &lut_pb_type->modes[0]; |
| lut_pb_type->modes[0].interconnect[0].interconnect_power = |
| (t_interconnect_power*) vtr::calloc(1, sizeof(t_interconnect_power)); |
| |
| lut_pb_type->modes[0].interconnect[0].annotations = |
| (t_pin_to_pin_annotation*) vtr::calloc(lut_pb_type->num_annotations, |
| sizeof(t_pin_to_pin_annotation)); |
| lut_pb_type->modes[0].interconnect[0].num_annotations = |
| lut_pb_type->num_annotations; |
| for (i = 0; i < lut_pb_type->modes[0].interconnect[0].num_annotations; |
| i++) { |
| lut_pb_type->modes[0].interconnect[0].annotations[i].clock = vtr::strdup( |
| lut_pb_type->annotations[i].clock); |
| lut_pb_type->modes[0].interconnect[0].annotations[i].input_pins = |
| vtr::strdup(lut_pb_type->annotations[i].input_pins); |
| lut_pb_type->modes[0].interconnect[0].annotations[i].output_pins = |
| vtr::strdup(lut_pb_type->annotations[i].output_pins); |
| lut_pb_type->modes[0].interconnect[0].annotations[i].line_num = |
| lut_pb_type->annotations[i].line_num; |
| lut_pb_type->modes[0].interconnect[0].annotations[i].format = |
| lut_pb_type->annotations[i].format; |
| lut_pb_type->modes[0].interconnect[0].annotations[i].type = |
| lut_pb_type->annotations[i].type; |
| lut_pb_type->modes[0].interconnect[0].annotations[i].num_value_prop_pairs = |
| lut_pb_type->annotations[i].num_value_prop_pairs; |
| lut_pb_type->modes[0].interconnect[0].annotations[i].prop = |
| (int*) vtr::malloc( |
| sizeof(int) |
| * lut_pb_type->annotations[i].num_value_prop_pairs); |
| lut_pb_type->modes[0].interconnect[0].annotations[i].value = |
| (char**) vtr::malloc( |
| sizeof(char *) |
| * lut_pb_type->annotations[i].num_value_prop_pairs); |
| for (j = 0; j < lut_pb_type->annotations[i].num_value_prop_pairs; j++) { |
| lut_pb_type->modes[0].interconnect[0].annotations[i].prop[j] = |
| lut_pb_type->annotations[i].prop[j]; |
| lut_pb_type->modes[0].interconnect[0].annotations[i].value[j] = |
| vtr::strdup(lut_pb_type->annotations[i].value[j]); |
| } |
| } |
| |
| /* Second mode, LUT */ |
| |
| lut_pb_type->modes[1].name = vtr::strdup(lut_pb_type->name); |
| lut_pb_type->modes[1].parent_pb_type = lut_pb_type; |
| lut_pb_type->modes[1].index = 1; |
| lut_pb_type->modes[1].num_pb_type_children = 1; |
| lut_pb_type->modes[1].mode_power = (t_mode_power*) vtr::calloc(1, |
| sizeof(t_mode_power)); |
| lut_pb_type->modes[1].pb_type_children = new t_pb_type[1]; |
| alloc_and_load_default_child_for_pb_type(lut_pb_type, default_name, |
| lut_pb_type->modes[1].pb_type_children); |
| /* moved annotations to child so delete old annotations */ |
| for (i = 0; i < lut_pb_type->num_annotations; i++) { |
| for (j = 0; j < lut_pb_type->annotations[i].num_value_prop_pairs; j++) { |
| free(lut_pb_type->annotations[i].value[j]); |
| } |
| free(lut_pb_type->annotations[i].value); |
| free(lut_pb_type->annotations[i].prop); |
| if (lut_pb_type->annotations[i].input_pins) { |
| free(lut_pb_type->annotations[i].input_pins); |
| } |
| if (lut_pb_type->annotations[i].output_pins) { |
| free(lut_pb_type->annotations[i].output_pins); |
| } |
| if (lut_pb_type->annotations[i].clock) { |
| free(lut_pb_type->annotations[i].clock); |
| } |
| } |
| lut_pb_type->num_annotations = 0; |
| free(lut_pb_type->annotations); |
| lut_pb_type->annotations = nullptr; |
| lut_pb_type->modes[1].pb_type_children[0].depth = lut_pb_type->depth + 1; |
| lut_pb_type->modes[1].pb_type_children[0].parent_mode = &lut_pb_type->modes[1]; |
| for (i = 0; i < lut_pb_type->modes[1].pb_type_children[0].num_ports; i++) { |
| if (lut_pb_type->modes[1].pb_type_children[0].ports[i].type == IN_PORT) { |
| lut_pb_type->modes[1].pb_type_children[0].ports[i].equivalent = PortEquivalence::FULL; |
| } |
| } |
| |
| /* Process interconnect */ |
| lut_pb_type->modes[1].num_interconnect = 2; |
| lut_pb_type->modes[1].interconnect = (t_interconnect*) vtr::calloc(2, |
| sizeof(t_interconnect)); |
| lut_pb_type->modes[1].interconnect[0].name = (char*) vtr::calloc( |
| strlen(lut_pb_type->name) + 10, sizeof(char)); |
| sprintf(lut_pb_type->modes[1].interconnect[0].name, "direct:%s", |
| lut_pb_type->name); |
| lut_pb_type->modes[1].interconnect[0].type = DIRECT_INTERC; |
| lut_pb_type->modes[1].interconnect[0].input_string = (char*) vtr::calloc( |
| strlen(lut_pb_type->name) + strlen(in_port->name) + 2, |
| sizeof(char)); |
| sprintf(lut_pb_type->modes[1].interconnect[0].input_string, "%s.%s", |
| lut_pb_type->name, in_port->name); |
| lut_pb_type->modes[1].interconnect[0].output_string = (char*) vtr::calloc( |
| strlen(default_name) + strlen(in_port->name) + 2, sizeof(char)); |
| sprintf(lut_pb_type->modes[1].interconnect[0].output_string, "%s.%s", |
| default_name, in_port->name); |
| lut_pb_type->modes[1].interconnect[0].infer_annotations = true; |
| |
| lut_pb_type->modes[1].interconnect[0].parent_mode_index = 1; |
| lut_pb_type->modes[1].interconnect[0].parent_mode = &lut_pb_type->modes[1]; |
| lut_pb_type->modes[1].interconnect[0].interconnect_power = |
| (t_interconnect_power*) vtr::calloc(1, sizeof(t_interconnect_power)); |
| |
| lut_pb_type->modes[1].interconnect[1].name = (char*) vtr::calloc( |
| strlen(lut_pb_type->name) + 11, sizeof(char)); |
| sprintf(lut_pb_type->modes[1].interconnect[1].name, "direct:%s", |
| lut_pb_type->name); |
| |
| lut_pb_type->modes[1].interconnect[1].type = DIRECT_INTERC; |
| lut_pb_type->modes[1].interconnect[1].input_string = (char*) vtr::calloc( |
| strlen(default_name) + strlen(out_port->name) + 4, sizeof(char)); |
| sprintf(lut_pb_type->modes[1].interconnect[1].input_string, "%s.%s", |
| default_name, out_port->name); |
| lut_pb_type->modes[1].interconnect[1].output_string = (char*) vtr::calloc( |
| strlen(lut_pb_type->name) + strlen(out_port->name) |
| + strlen(in_port->name) + 2, sizeof(char)); |
| sprintf(lut_pb_type->modes[1].interconnect[1].output_string, "%s.%s", |
| lut_pb_type->name, out_port->name); |
| lut_pb_type->modes[1].interconnect[1].infer_annotations = true; |
| |
| lut_pb_type->modes[1].interconnect[1].parent_mode_index = 1; |
| lut_pb_type->modes[1].interconnect[1].parent_mode = &lut_pb_type->modes[1]; |
| lut_pb_type->modes[1].interconnect[1].interconnect_power = |
| (t_interconnect_power*) vtr::calloc(1, sizeof(t_interconnect_power)); |
| |
| free(default_name); |
| |
| free(lut_pb_type->blif_model); |
| lut_pb_type->blif_model = nullptr; |
| lut_pb_type->model = nullptr; |
| } |
| |
| /* populate special memory class */ |
| void ProcessMemoryClass(t_pb_type *mem_pb_type) { |
| char *default_name; |
| char *input_name, *input_port_name, *output_name, *output_port_name; |
| int i, j, i_inter, num_pb; |
| |
| if (strcmp(mem_pb_type->name, "memory_slice") != 0) { |
| default_name = vtr::strdup("memory_slice"); |
| } else { |
| default_name = vtr::strdup("memory_slice_1bit"); |
| } |
| |
| mem_pb_type->modes = (t_mode*) vtr::calloc(1, sizeof(t_mode)); |
| mem_pb_type->modes[0].name = vtr::strdup(default_name); |
| mem_pb_type->modes[0].parent_pb_type = mem_pb_type; |
| mem_pb_type->modes[0].index = 0; |
| mem_pb_type->modes[0].mode_power = (t_mode_power*) vtr::calloc(1, |
| sizeof(t_mode_power)); |
| num_pb = OPEN; |
| for (i = 0; i < mem_pb_type->num_ports; i++) { |
| if (mem_pb_type->ports[i].port_class != nullptr |
| && strstr(mem_pb_type->ports[i].port_class, "data") |
| == mem_pb_type->ports[i].port_class) { |
| if (num_pb == OPEN) { |
| num_pb = mem_pb_type->ports[i].num_pins; |
| } else if (num_pb != mem_pb_type->ports[i].num_pins) { |
| archfpga_throw(get_arch_file_name(), 0, |
| "memory %s has inconsistent number of data bits %d and %d\n", |
| mem_pb_type->name, num_pb, |
| mem_pb_type->ports[i].num_pins); |
| } |
| } |
| } |
| |
| mem_pb_type->modes[0].num_pb_type_children = 1; |
| mem_pb_type->modes[0].pb_type_children = new t_pb_type[1]; |
| alloc_and_load_default_child_for_pb_type(mem_pb_type, default_name, |
| &mem_pb_type->modes[0].pb_type_children[0]); |
| mem_pb_type->modes[0].pb_type_children[0].depth = mem_pb_type->depth + 1; |
| mem_pb_type->modes[0].pb_type_children[0].parent_mode = |
| &mem_pb_type->modes[0]; |
| mem_pb_type->modes[0].pb_type_children[0].num_pb = num_pb; |
| |
| mem_pb_type->num_modes = 1; |
| |
| free(mem_pb_type->blif_model); |
| mem_pb_type->blif_model = nullptr; |
| mem_pb_type->model = nullptr; |
| |
| mem_pb_type->modes[0].num_interconnect = mem_pb_type->num_ports * num_pb; |
| mem_pb_type->modes[0].interconnect = (t_interconnect*) vtr::calloc( |
| mem_pb_type->modes[0].num_interconnect, sizeof(t_interconnect)); |
| |
| for (i = 0; i < mem_pb_type->modes[0].num_interconnect; i++) { |
| mem_pb_type->modes[0].interconnect[i].parent_mode_index = 0; |
| mem_pb_type->modes[0].interconnect[i].parent_mode = |
| &mem_pb_type->modes[0]; |
| } |
| |
| /* Process interconnect */ |
| i_inter = 0; |
| for (i = 0; i < mem_pb_type->num_ports; i++) { |
| mem_pb_type->modes[0].interconnect[i_inter].type = DIRECT_INTERC; |
| input_port_name = mem_pb_type->ports[i].name; |
| output_port_name = mem_pb_type->ports[i].name; |
| |
| if (mem_pb_type->ports[i].type == IN_PORT) { |
| input_name = mem_pb_type->name; |
| output_name = default_name; |
| } else { |
| input_name = default_name; |
| output_name = mem_pb_type->name; |
| } |
| |
| if (mem_pb_type->ports[i].port_class != nullptr |
| && strstr(mem_pb_type->ports[i].port_class, "data") |
| == mem_pb_type->ports[i].port_class) { |
| |
| mem_pb_type->modes[0].interconnect[i_inter].name = |
| (char*) vtr::calloc(i_inter / 10 + 8, sizeof(char)); |
| sprintf(mem_pb_type->modes[0].interconnect[i_inter].name, |
| "direct%d", i_inter); |
| mem_pb_type->modes[0].interconnect[i_inter].infer_annotations = true; |
| |
| if (mem_pb_type->ports[i].type == IN_PORT) { |
| /* force data pins to be one bit wide and update stats */ |
| mem_pb_type->modes[0].pb_type_children[0].ports[i].num_pins = 1; |
| mem_pb_type->modes[0].pb_type_children[0].num_input_pins -= |
| (mem_pb_type->ports[i].num_pins - 1); |
| |
| mem_pb_type->modes[0].interconnect[i_inter].input_string = |
| (char*) vtr::calloc( |
| strlen(input_name) + strlen(input_port_name) |
| + 2, sizeof(char)); |
| sprintf( |
| mem_pb_type->modes[0].interconnect[i_inter].input_string, |
| "%s.%s", input_name, input_port_name); |
| mem_pb_type->modes[0].interconnect[i_inter].output_string = |
| (char*) vtr::calloc( |
| strlen(output_name) + strlen(output_port_name) |
| + 2 * (6 + num_pb / 10), sizeof(char)); |
| sprintf( |
| mem_pb_type->modes[0].interconnect[i_inter].output_string, |
| "%s[%d:0].%s", output_name, num_pb - 1, |
| output_port_name); |
| } else { |
| /* force data pins to be one bit wide and update stats */ |
| mem_pb_type->modes[0].pb_type_children[0].ports[i].num_pins = 1; |
| mem_pb_type->modes[0].pb_type_children[0].num_output_pins -= |
| (mem_pb_type->ports[i].num_pins - 1); |
| |
| mem_pb_type->modes[0].interconnect[i_inter].input_string = |
| (char*) vtr::calloc( |
| strlen(input_name) + strlen(input_port_name) |
| + 2 * (6 + num_pb / 10), sizeof(char)); |
| sprintf( |
| mem_pb_type->modes[0].interconnect[i_inter].input_string, |
| "%s[%d:0].%s", input_name, num_pb - 1, input_port_name); |
| mem_pb_type->modes[0].interconnect[i_inter].output_string = |
| (char*) vtr::calloc( |
| strlen(output_name) + strlen(output_port_name) |
| + 2, sizeof(char)); |
| sprintf( |
| mem_pb_type->modes[0].interconnect[i_inter].output_string, |
| "%s.%s", output_name, output_port_name); |
| } |
| |
| /* Allocate interconnect power structures */ |
| mem_pb_type->modes[0].interconnect[i_inter].interconnect_power = |
| (t_interconnect_power*) vtr::calloc(1, |
| sizeof(t_interconnect_power)); |
| i_inter++; |
| } else { |
| for (j = 0; j < num_pb; j++) { |
| /* Anything that is not data must be an input */ |
| mem_pb_type->modes[0].interconnect[i_inter].name = |
| (char*) vtr::calloc(i_inter / 10 + j / 10 + 10, |
| sizeof(char)); |
| sprintf(mem_pb_type->modes[0].interconnect[i_inter].name, |
| "direct%d_%d", i_inter, j); |
| mem_pb_type->modes[0].interconnect[i_inter].infer_annotations = true; |
| |
| if (mem_pb_type->ports[i].type == IN_PORT) { |
| mem_pb_type->modes[0].interconnect[i_inter].type = |
| DIRECT_INTERC; |
| mem_pb_type->modes[0].interconnect[i_inter].input_string = |
| (char*) vtr::calloc( |
| strlen(input_name) + strlen(input_port_name) |
| + 2, sizeof(char)); |
| sprintf( |
| mem_pb_type->modes[0].interconnect[i_inter].input_string, |
| "%s.%s", input_name, input_port_name); |
| mem_pb_type->modes[0].interconnect[i_inter].output_string = |
| (char*) vtr::calloc( |
| strlen(output_name) |
| + strlen(output_port_name) |
| + 2 * (6 + num_pb / 10), |
| sizeof(char)); |
| sprintf( |
| mem_pb_type->modes[0].interconnect[i_inter].output_string, |
| "%s[%d:%d].%s", output_name, j, j, |
| output_port_name); |
| } else { |
| mem_pb_type->modes[0].interconnect[i_inter].type = |
| DIRECT_INTERC; |
| mem_pb_type->modes[0].interconnect[i_inter].input_string = |
| (char*) vtr::calloc( |
| strlen(input_name) + strlen(input_port_name) |
| + 2 * (6 + num_pb / 10), |
| sizeof(char)); |
| sprintf( |
| mem_pb_type->modes[0].interconnect[i_inter].input_string, |
| "%s[%d:%d].%s", input_name, j, j, input_port_name); |
| mem_pb_type->modes[0].interconnect[i_inter].output_string = |
| (char*) vtr::calloc( |
| strlen(output_name) |
| + strlen(output_port_name) + 2, |
| sizeof(char)); |
| sprintf( |
| mem_pb_type->modes[0].interconnect[i_inter].output_string, |
| "%s.%s", output_name, output_port_name); |
| |
| } |
| |
| /* Allocate interconnect power structures */ |
| mem_pb_type->modes[0].interconnect[i_inter].interconnect_power = |
| (t_interconnect_power*) vtr::calloc(1, |
| sizeof(t_interconnect_power)); |
| i_inter++; |
| } |
| } |
| } |
| |
| mem_pb_type->modes[0].num_interconnect = i_inter; |
| |
| free(default_name); |
| } |
| |
| e_power_estimation_method power_method_inherited( |
| e_power_estimation_method parent_power_method) { |
| switch (parent_power_method) { |
| case POWER_METHOD_IGNORE: |
| case POWER_METHOD_AUTO_SIZES: |
| case POWER_METHOD_SPECIFY_SIZES: |
| case POWER_METHOD_TOGGLE_PINS: |
| return parent_power_method; |
| case POWER_METHOD_C_INTERNAL: |
| case POWER_METHOD_ABSOLUTE: |
| return POWER_METHOD_IGNORE; |
| case POWER_METHOD_UNDEFINED: |
| return POWER_METHOD_UNDEFINED; |
| case POWER_METHOD_SUM_OF_CHILDREN: |
| /* Just revert to the default */ |
| return POWER_METHOD_AUTO_SIZES; |
| default: |
| VTR_ASSERT(0); |
| return POWER_METHOD_UNDEFINED; // Should never get here, but avoids a compiler warning. |
| } |
| } |
| |
| void CreateModelLibrary(t_arch *arch) { |
| t_model* model_library; |
| |
| model_library = new t_model[4]; |
| |
| //INPAD |
| model_library[0].name = vtr::strdup(MODEL_INPUT); |
| model_library[0].index = 0; |
| model_library[0].inputs = nullptr; |
| model_library[0].instances = nullptr; |
| model_library[0].next = &model_library[1]; |
| model_library[0].outputs = new t_model_ports[1]; |
| model_library[0].outputs->dir = OUT_PORT; |
| model_library[0].outputs->name = vtr::strdup("inpad"); |
| model_library[0].outputs->next = nullptr; |
| model_library[0].outputs->size = 1; |
| model_library[0].outputs->min_size = 1; |
| model_library[0].outputs->index = 0; |
| model_library[0].outputs->is_clock = false; |
| |
| //OUTPAD |
| model_library[1].name = vtr::strdup(MODEL_OUTPUT); |
| model_library[1].index = 1; |
| model_library[1].inputs = new t_model_ports[1]; |
| model_library[1].inputs->dir = IN_PORT; |
| model_library[1].inputs->name = vtr::strdup("outpad"); |
| model_library[1].inputs->next = nullptr; |
| model_library[1].inputs->size = 1; |
| model_library[1].inputs->min_size = 1; |
| model_library[1].inputs->index = 0; |
| model_library[1].inputs->is_clock = false; |
| model_library[1].instances = nullptr; |
| model_library[1].next = &model_library[2]; |
| model_library[1].outputs = nullptr; |
| |
| //LATCH |
| model_library[2].name = vtr::strdup(MODEL_LATCH); |
| model_library[2].index = 2; |
| model_library[2].inputs = new t_model_ports[2]; |
| |
| model_library[2].inputs[0].dir = IN_PORT; |
| model_library[2].inputs[0].name = vtr::strdup("D"); |
| model_library[2].inputs[0].next = &model_library[2].inputs[1]; |
| model_library[2].inputs[0].size = 1; |
| model_library[2].inputs[0].min_size = 1; |
| model_library[2].inputs[0].index = 0; |
| model_library[2].inputs[0].is_clock = false; |
| model_library[2].inputs[0].clock = "clk"; |
| |
| model_library[2].inputs[1].dir = IN_PORT; |
| model_library[2].inputs[1].name = vtr::strdup("clk"); |
| model_library[2].inputs[1].next = nullptr; |
| model_library[2].inputs[1].size = 1; |
| model_library[2].inputs[1].min_size = 1; |
| model_library[2].inputs[1].index = 0; |
| model_library[2].inputs[1].is_clock = true; |
| |
| model_library[2].instances = nullptr; |
| model_library[2].next = &model_library[3]; |
| |
| model_library[2].outputs = new t_model_ports[1]; |
| model_library[2].outputs[0].dir = OUT_PORT; |
| model_library[2].outputs[0].name = vtr::strdup("Q"); |
| model_library[2].outputs[0].next = nullptr; |
| model_library[2].outputs[0].size = 1; |
| model_library[2].outputs[0].min_size = 1; |
| model_library[2].outputs[0].index = 0; |
| model_library[2].outputs[0].is_clock = false; |
| model_library[2].outputs[0].clock = "clk"; |
| |
| //NAMES |
| model_library[3].name = vtr::strdup(MODEL_NAMES); |
| model_library[3].index = 3; |
| |
| model_library[3].inputs = new t_model_ports[1]; |
| model_library[3].inputs[0].dir = IN_PORT; |
| model_library[3].inputs[0].name = vtr::strdup("in"); |
| model_library[3].inputs[0].next = nullptr; |
| model_library[3].inputs[0].size = 1; |
| model_library[3].inputs[0].min_size = 1; |
| model_library[3].inputs[0].index = 0; |
| model_library[3].inputs[0].is_clock = false; |
| model_library[3].inputs[0].combinational_sink_ports = {"out"}; |
| |
| model_library[3].instances = nullptr; |
| model_library[3].next = nullptr; |
| |
| model_library[3].outputs = new t_model_ports[1]; |
| model_library[3].outputs[0].dir = OUT_PORT; |
| model_library[3].outputs[0].name = vtr::strdup("out"); |
| model_library[3].outputs[0].next = nullptr; |
| model_library[3].outputs[0].size = 1; |
| model_library[3].outputs[0].min_size = 1; |
| model_library[3].outputs[0].index = 0; |
| model_library[3].outputs[0].is_clock = false; |
| |
| arch->model_library = model_library; |
| } |
| |
| void SyncModelsPbTypes(t_arch *arch, |
| const t_type_descriptor * Types, const int NumTypes) { |
| int i; |
| for (i = 0; i < NumTypes; i++) { |
| if (Types[i].pb_type != nullptr) { |
| SyncModelsPbTypes_rec(arch, Types[i].pb_type); |
| } |
| } |
| } |
| |
| void SyncModelsPbTypes_rec(t_arch *arch, |
| t_pb_type * pb_type) { |
| int i, j, p; |
| t_model *model_match_prim, *cur_model; |
| t_model_ports *model_port; |
| vtr::t_linked_vptr *old; |
| char* blif_model_name = nullptr; |
| |
| bool found; |
| |
| if (pb_type->blif_model != nullptr) { |
| |
| /* get actual name of subckt */ |
| blif_model_name = pb_type->blif_model; |
| if (strstr(blif_model_name, ".subckt ") == blif_model_name) { |
| blif_model_name = strchr(blif_model_name, ' '); |
| ++blif_model_name; //Advance past space |
| } |
| if (!blif_model_name) { |
| archfpga_throw(get_arch_file_name(), 0, |
| "Unknown blif model %s in pb_type %s\n", |
| pb_type->blif_model, pb_type->name); |
| } |
| |
| /* There are two sets of models to consider, the standard library of models and the user defined models */ |
| if (is_library_model(blif_model_name)) { |
| cur_model = arch->model_library; |
| } else { |
| cur_model = arch->models; |
| } |
| |
| /* Determine the logical model to use */ |
| found = false; |
| model_match_prim = nullptr; |
| while (cur_model && !found) { |
| /* blif model always starts with .subckt so need to skip first 8 characters */ |
| if (strcmp(blif_model_name, cur_model->name) == 0) { |
| found = true; |
| model_match_prim = cur_model; |
| } |
| cur_model = cur_model->next; |
| } |
| if (found != true) { |
| archfpga_throw(get_arch_file_name(), 0, |
| "No matching model for pb_type %s\n", pb_type->blif_model); |
| } |
| |
| pb_type->model = model_match_prim; |
| old = model_match_prim->pb_types; |
| model_match_prim->pb_types = (vtr::t_linked_vptr*) vtr::malloc( |
| sizeof(vtr::t_linked_vptr)); |
| model_match_prim->pb_types->next = old; |
| model_match_prim->pb_types->data_vptr = pb_type; |
| |
| for (p = 0; p < pb_type->num_ports; p++) { |
| found = false; |
| /* TODO: Parse error checking - check if INPUT matches INPUT and OUTPUT matches OUTPUT (not yet done) */ |
| model_port = model_match_prim->inputs; |
| while (model_port && !found) { |
| if (strcmp(model_port->name, pb_type->ports[p].name) == 0) { |
| if (model_port->size < pb_type->ports[p].num_pins) { |
| model_port->size = pb_type->ports[p].num_pins; |
| } |
| if (model_port->min_size > pb_type->ports[p].num_pins |
| || model_port->min_size == -1) { |
| model_port->min_size = pb_type->ports[p].num_pins; |
| } |
| pb_type->ports[p].model_port = model_port; |
| if(pb_type->ports[p].type != model_port->dir) { |
| archfpga_throw(get_arch_file_name(), 0, |
| "Direction for port '%s' on model does not match port direction in pb_type '%s'\n", |
| pb_type->ports[p].name, pb_type->name); |
| } |
| if(pb_type->ports[p].is_clock != model_port->is_clock) { |
| archfpga_throw(get_arch_file_name(), 0, |
| "Port '%s' on model does not match is_clock in pb_type '%s'\n", |
| pb_type->ports[p].name, pb_type->name); |
| } |
| found = true; |
| } |
| model_port = model_port->next; |
| } |
| model_port = model_match_prim->outputs; |
| while (model_port && !found) { |
| if (strcmp(model_port->name, pb_type->ports[p].name) == 0) { |
| if (model_port->size < pb_type->ports[p].num_pins) { |
| model_port->size = pb_type->ports[p].num_pins; |
| } |
| if (model_port->min_size > pb_type->ports[p].num_pins |
| || model_port->min_size == -1) { |
| model_port->min_size = pb_type->ports[p].num_pins; |
| } |
| |
| pb_type->ports[p].model_port = model_port; |
| if(pb_type->ports[p].type != model_port->dir) { |
| archfpga_throw(get_arch_file_name(), 0, |
| "Direction for port '%s' on model does not match port direction in pb_type '%s'\n", |
| pb_type->ports[p].name, pb_type->name); |
| } |
| found = true; |
| } |
| model_port = model_port->next; |
| } |
| if (found != true) { |
| archfpga_throw(get_arch_file_name(), 0, |
| "No matching model port for port %s in pb_type %s\n", |
| pb_type->ports[p].name, pb_type->name); |
| } |
| } |
| } else { |
| for (i = 0; i < pb_type->num_modes; i++) { |
| for (j = 0; j < pb_type->modes[i].num_pb_type_children; j++) { |
| SyncModelsPbTypes_rec(arch, |
| &(pb_type->modes[i].pb_type_children[j])); |
| } |
| } |
| } |
| } |
| |
| void UpdateAndCheckModels(t_arch *arch) { |
| t_model * cur_model; |
| t_model_ports *port; |
| int i, j; |
| cur_model = arch->models; |
| while (cur_model) { |
| if (cur_model->pb_types == nullptr) { |
| archfpga_throw(get_arch_file_name(), 0, |
| "No pb_type found for model %s\n", cur_model->name); |
| } |
| port = cur_model->inputs; |
| i = 0; |
| j = 0; |
| while (port) { |
| if (port->is_clock) { |
| port->index = i; |
| i++; |
| } else { |
| port->index = j; |
| j++; |
| } |
| port = port->next; |
| } |
| port = cur_model->outputs; |
| i = 0; |
| while (port) { |
| port->index = i; |
| i++; |
| port = port->next; |
| } |
| cur_model = cur_model->next; |
| } |
| } |
| |
| /* Date:July 10th, 2013 |
| * Author: Daniel Chen |
| * Purpose: Attempts to match a clock_name specified in an |
| * timing annotation (Tsetup, Thold, Tc_to_q) with the |
| * clock_name specified in the primitive. Applies |
| * to flipflop/memory right now. |
| */ |
| void primitives_annotation_clock_match( |
| t_pin_to_pin_annotation *annotation, t_pb_type * parent_pb_type) { |
| |
| int i_port; |
| bool clock_valid = false; //Determine if annotation's clock is same as primtive's clock |
| |
| if (!parent_pb_type || !annotation) { |
| archfpga_throw(__FILE__, __LINE__, |
| "Annotation_clock check encouters invalid annotation or primitive.\n"); |
| } |
| |
| for (i_port = 0; i_port < parent_pb_type->num_ports; i_port++) { |
| if (parent_pb_type->ports[i_port].is_clock) { |
| if (strcmp(parent_pb_type->ports[i_port].name, annotation->clock) |
| == 0) { |
| clock_valid = true; |
| break; |
| } |
| } |
| } |
| |
| if (!clock_valid) { |
| archfpga_throw(get_arch_file_name(), annotation->line_num, |
| "Clock '%s' does not match any clock defined in pb_type '%s'.\n", |
| annotation->clock, parent_pb_type->name); |
| } |
| |
| } |
| |
| |
| const t_segment_inf* find_segment(const t_arch* arch, std::string name) { |
| |
| for (size_t i = 0; i < (arch->Segments).size(); ++i) { |
| const t_segment_inf* seg = &arch->Segments[i]; |
| if (seg->name == name) { |
| return seg; |
| } |
| } |
| |
| return nullptr; |
| } |
| |
| bool segment_exists(const t_arch* arch, std::string name) { |
| return find_segment(arch, name) != nullptr; |
| } |
| |
| bool is_library_model(const char* model_name) { |
| if (model_name == std::string(MODEL_NAMES) |
| || model_name == std::string(MODEL_LATCH) |
| || model_name == std::string(MODEL_INPUT) |
| || model_name == std::string(MODEL_OUTPUT)) { |
| return true; |
| } |
| return false; |
| } |
| |
| bool is_library_model(const t_model* model) { |
| return is_library_model(model->name); |
| } |
| |