OpenFPGA/libs/libarchfpga/src/arch_util.cpp

1324 lines
57 KiB
C++

#include <cstring>
#include <sstream>
#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<t_logical_block_type>& 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<std::string> 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<t_physical_tile_type>& 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<t_logical_block_type>& 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<t_logical_block_type>& 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<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);
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<t_logical_block_type>& 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);
}