#include #include #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(std::vector& type_descriptors); static void free_pb_graph(t_pb_graph_node* pb_graph_node); static void free_pb_type(t_pb_type* pb_type); InstPort::InstPort(std::string str) { std::vector inst_port = vtr::split(str, "."); if (inst_port.size() == 1) { instance_ = name_index(); port_ = parse_name_index(inst_port[0]); } else if (inst_port.size() == 2) { instance_ = parse_name_index(inst_port[0]); port_ = parse_name_index(inst_port[1]); } else { std::string msg = vtr::string_fmt("Failed to parse instance port specification '%s'", str.c_str()); throw ArchFpgaError(msg); } } InstPort::name_index InstPort::parse_name_index(std::string str) { auto open_bracket_pos = str.find("["); auto close_bracket_pos = str.find("]"); auto colon_pos = str.find(":"); //Parse checks if (open_bracket_pos == std::string::npos && close_bracket_pos != std::string::npos) { //Close brace only std::string msg = "near '" + str + "', missing '['"; throw ArchFpgaError(msg); } if (open_bracket_pos != std::string::npos && close_bracket_pos == std::string::npos) { //Open brace only std::string msg = "near '" + str + "', missing ']'"; throw ArchFpgaError(msg); } if (open_bracket_pos != std::string::npos && close_bracket_pos != std::string::npos) { //Have open and close braces, close must be after open if (open_bracket_pos > close_bracket_pos) { std::string msg = "near '" + str + "', '[' after ']'"; throw ArchFpgaError(msg); } } if (colon_pos != std::string::npos) { //Have a colon, it must be between open/close braces if (colon_pos > close_bracket_pos || colon_pos < open_bracket_pos) { std::string msg = "near '" + str + "', found ':' but not between '[' and ']'"; throw ArchFpgaError(msg); } } //Extract the name and index info std::string name = str.substr(0, open_bracket_pos); std::string first_idx_str; std::string second_idx_str; if (colon_pos == std::string::npos && open_bracket_pos == std::string::npos && close_bracket_pos == std::string::npos) { } else if (colon_pos == std::string::npos) { //No colon, implies a single element first_idx_str = str.substr(open_bracket_pos + 1, close_bracket_pos); second_idx_str = first_idx_str; } else { //Colon, implies a range first_idx_str = str.substr(open_bracket_pos + 1, colon_pos); second_idx_str = str.substr(colon_pos + 1, close_bracket_pos); } int first_idx = UNSPECIFIED; if (!first_idx_str.empty()) { std::stringstream ss(first_idx_str); size_t idx; ss >> idx; if (!ss.good()) { std::string msg = "near '" + str + "', expected positive integer"; throw ArchFpgaError(msg); } first_idx = idx; } int second_idx = UNSPECIFIED; if (!second_idx_str.empty()) { std::stringstream ss(second_idx_str); size_t idx; ss >> idx; if (!ss.good()) { std::string msg = "near '" + str + "', expected positive integer"; throw ArchFpgaError(msg); } second_idx = idx; } name_index value; value.name = name; value.low_idx = std::min(first_idx, second_idx); value.high_idx = std::max(first_idx, second_idx); return value; } int InstPort::num_instances() const { if (instance_high_index() == UNSPECIFIED || instance_low_index() == UNSPECIFIED) { throw ArchFpgaError("Unspecified instance indicies"); } return instance_high_index() - instance_low_index() + 1; } int InstPort::num_pins() const { if (port_high_index() == UNSPECIFIED || port_low_index() == UNSPECIFIED) { throw ArchFpgaError("Unspecified port indicies"); } return port_high_index() - port_low_index() + 1; } 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(std::vector& type_descriptors) { for (auto& type : type_descriptors) { vtr::free(type.name); if (type.index == EMPTY_TYPE_INDEX) { continue; } for (int width = 0; width < type.width; ++width) { for (int height = 0; height < type.height; ++height) { for (int side = 0; side < 4; ++side) { for (int pin = 0; pin < type.num_pin_loc_assignments[width][height][side]; ++pin) { if (type.pin_loc_assignments[width][height][side][pin]) vtr::free(type.pin_loc_assignments[width][height][side][pin]); } vtr::free(type.pinloc[width][height][side]); vtr::free(type.pin_loc_assignments[width][height][side]); } vtr::free(type.pinloc[width][height]); vtr::free(type.pin_loc_assignments[width][height]); vtr::free(type.num_pin_loc_assignments[width][height]); } vtr::free(type.pinloc[width]); vtr::free(type.pin_loc_assignments[width]); vtr::free(type.num_pin_loc_assignments[width]); } vtr::free(type.pinloc); vtr::free(type.pin_loc_assignments); vtr::free(type.num_pin_loc_assignments); for (int j = 0; j < type.num_class; ++j) { vtr::free(type.class_inf[j].pinlist); } vtr::free(type.class_inf); vtr::free(type.is_ignored_pin); vtr::free(type.is_pin_global); vtr::free(type.pin_class); for (auto port : type.ports) { vtr::free(port.name); } } type_descriptors.clear(); } void free_type_descriptors(std::vector& type_descriptors) { free_all_pb_graph_nodes(type_descriptors); for (auto& type : type_descriptors) { vtr::free(type.name); if (type.index == EMPTY_TYPE_INDEX) { continue; } free_pb_type(type.pb_type); delete type.pb_type; } type_descriptors.clear(); } static void free_all_pb_graph_nodes(std::vector& type_descriptors) { for (auto& type : type_descriptors) { if (type.pb_type) { if (type.pb_graph_head) { free_pb_graph(type.pb_graph_head); vtr::free(type.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]; } 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); if (pb_graph_node->interconnect_pins) { for (i = 0; i < pb_graph_node->pb_type->num_modes; i++) { if (pb_graph_node->interconnect_pins[i] == nullptr) continue; t_mode* mode = &pb_graph_node->pb_type->modes[i]; for (j = 0; j < mode->num_interconnect; ++j) { //The interconnect_pins data structures are only initialized for power analysis and //are bizarrely baroque... t_interconnect* interconn = pb_graph_node->interconnect_pins[i][j].interconnect; VTR_ASSERT(interconn == &mode->interconnect[j]); t_interconnect_power* interconn_power = interconn->interconnect_power; for (int iport = 0; iport < interconn_power->num_input_ports; ++iport) { vtr::free(pb_graph_node->interconnect_pins[i][j].input_pins[iport]); } for (int iport = 0; iport < interconn_power->num_output_ports; ++iport) { vtr::free(pb_graph_node->interconnect_pins[i][j].output_pins[iport]); } vtr::free(pb_graph_node->interconnect_pins[i][j].input_pins); vtr::free(pb_graph_node->interconnect_pins[i][j].output_pins); } vtr::free(pb_graph_node->interconnect_pins[i]); } } vtr::free(pb_graph_node->interconnect_pins); vtr::free(pb_graph_node->pb_node_power); 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) delete[] pb_type->modes[i].interconnect; if (pb_type->modes[i].mode_power) vtr::free(pb_type->modes[i].mode_power); } if (pb_type->modes) delete[] 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; } t_physical_tile_type SetupEmptyPhysicalType() { t_physical_tile_type type; 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.area = UNDEFINED; type.switchblock_locations = vtr::Matrix({{size_t(type.width), size_t(type.height)}}, e_sb_type::FULL); type.switchblock_switch_overrides = vtr::Matrix({{size_t(type.width), size_t(type.height)}}, DEFAULT_SWITCH); return type; } t_logical_block_type SetupEmptyLogicalType() { t_logical_block_type type; type.name = vtr::strdup("EMPTY"); type.pb_type = nullptr; return type; } 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->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 = new t_mode[lut_pb_type->num_modes]; /* 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 = new t_interconnect[1]; 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 = new t_interconnect[lut_pb_type->modes[1].num_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 = new t_mode[1]; 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 = new t_interconnect[mem_pb_type->modes[0].num_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 std::vector& Types) { for (auto& Type : Types) { if (Type.pb_type != nullptr) { SyncModelsPbTypes_rec(arch, Type.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); }