Skip to content

libs: arch: interchange: add logical block and physical tiles support #1926

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
211 changes: 207 additions & 4 deletions libs/libarchfpga/src/arch_util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -555,9 +555,9 @@ t_port* findPortByName(const char* name, t_pb_type* pb_type, int* high_index, in
return port;
}

t_physical_tile_type SetupEmptyPhysicalType() {
t_physical_tile_type get_empty_physical_type(std::string name) {
t_physical_tile_type type;
type.name = vtr::strdup("EMPTY");
type.name = vtr::strdup(name.c_str());
type.num_pins = 0;
type.width = 1;
type.height = 1;
Expand All @@ -573,9 +573,9 @@ t_physical_tile_type SetupEmptyPhysicalType() {
return type;
}

t_logical_block_type SetupEmptyLogicalType() {
t_logical_block_type get_empty_logical_type(std::string name) {
t_logical_block_type type;
type.name = vtr::strdup("EMPTY");
type.name = vtr::strdup(name.c_str());
type.pb_type = nullptr;

return type;
Expand Down Expand Up @@ -1392,5 +1392,208 @@ const t_pin_to_pin_annotation* find_combinational_annotation(const t_pb_type* pb
}
}
}

return nullptr;
}

void link_physical_logical_types(std::vector<t_physical_tile_type>& PhysicalTileTypes,
std::vector<t_logical_block_type>& LogicalBlockTypes) {
for (auto& physical_tile : PhysicalTileTypes) {
if (physical_tile.index == EMPTY_TYPE_INDEX) continue;

auto eq_sites_set = get_equivalent_sites_set(&physical_tile);
auto equivalent_sites = std::vector<t_logical_block_type_ptr>(eq_sites_set.begin(), eq_sites_set.end());

auto criteria = [&physical_tile](const t_logical_block_type* lhs, const t_logical_block_type* rhs) {
int num_pins = physical_tile.num_inst_pins;

int lhs_num_logical_pins = lhs->pb_type->num_pins;
int rhs_num_logical_pins = rhs->pb_type->num_pins;

int lhs_diff_num_pins = num_pins - lhs_num_logical_pins;
int rhs_diff_num_pins = num_pins - rhs_num_logical_pins;

return lhs_diff_num_pins < rhs_diff_num_pins;
};

std::sort(equivalent_sites.begin(), equivalent_sites.end(), criteria);

for (auto& logical_block : LogicalBlockTypes) {
for (auto site : equivalent_sites) {
if (0 == strcmp(logical_block.name, site->pb_type->name)) {
logical_block.equivalent_tiles.push_back(&physical_tile);
break;
}
}
}
}

for (auto& logical_block : LogicalBlockTypes) {
if (logical_block.index == EMPTY_TYPE_INDEX) continue;

auto& equivalent_tiles = logical_block.equivalent_tiles;

if ((int)equivalent_tiles.size() <= 0) {
archfpga_throw(__FILE__, __LINE__,
"Logical Block %s does not have any equivalent tiles.\n", logical_block.name);
}

std::unordered_map<int, bool> ignored_pins_check_map;
std::unordered_map<int, bool> global_pins_check_map;

auto criteria = [&logical_block](const t_physical_tile_type* lhs, const t_physical_tile_type* rhs) {
int num_logical_pins = logical_block.pb_type->num_pins;

int lhs_num_pins = lhs->num_inst_pins;
int rhs_num_pins = rhs->num_inst_pins;

int lhs_diff_num_pins = lhs_num_pins - num_logical_pins;
int rhs_diff_num_pins = rhs_num_pins - num_logical_pins;

return lhs_diff_num_pins < rhs_diff_num_pins;
};

std::sort(equivalent_tiles.begin(), equivalent_tiles.end(), criteria);

for (int pin = 0; pin < logical_block.pb_type->num_pins; pin++) {
for (auto& tile : equivalent_tiles) {
auto direct_maps = tile->tile_block_pin_directs_map.at(logical_block.index);

for (auto& sub_tile : tile->sub_tiles) {
auto equiv_sites = sub_tile.equivalent_sites;
if (std::find(equiv_sites.begin(), equiv_sites.end(), &logical_block) == equiv_sites.end()) {
continue;
}

auto direct_map = direct_maps.at(sub_tile.index);

auto result = direct_map.find(t_logical_pin(pin));
if (result == direct_map.end()) {
archfpga_throw(__FILE__, __LINE__,
"Logical pin %d not present in pin mapping between Tile %s and Block %s.\n",
pin, tile->name, logical_block.name);
}

int sub_tile_pin_index = result->second.pin;
int phy_index = sub_tile.sub_tile_to_tile_pin_indices[sub_tile_pin_index];

bool is_ignored = tile->is_ignored_pin[phy_index];
bool is_global = tile->is_pin_global[phy_index];

auto ignored_result = ignored_pins_check_map.insert(std::pair<int, bool>(pin, is_ignored));
if (!ignored_result.second && ignored_result.first->second != is_ignored) {
archfpga_throw(__FILE__, __LINE__,
"Physical Tile %s has a different value for the ignored pin (physical pin: %d, logical pin: %d) "
"different from the corresponding pins of the other equivalent site %s\n.",
tile->name, phy_index, pin, logical_block.name);
}

auto global_result = global_pins_check_map.insert(std::pair<int, bool>(pin, is_global));
if (!global_result.second && global_result.first->second != is_global) {
archfpga_throw(__FILE__, __LINE__,
"Physical Tile %s has a different value for the global pin (physical pin: %d, logical pin: %d) "
"different from the corresponding pins of the other equivalent sites\n.",
tile->name, phy_index, pin);
}
}
}
}
}
}

/* Sets up the pin classes for the type. */
void setup_pin_classes(t_physical_tile_type* type) {
int i, k;
int pin_count;
int num_class;

for (i = 0; i < type->num_pins; i++) {
type->pin_class.push_back(OPEN);
type->is_ignored_pin.push_back(true);
type->is_pin_global.push_back(true);
}

pin_count = 0;

t_class_range class_range;

/* Equivalent pins share the same class, non-equivalent pins belong to different pin classes */
for (auto& sub_tile : type->sub_tiles) {
int capacity = sub_tile.capacity.total();
class_range.low = type->class_inf.size();
class_range.high = class_range.low - 1;
for (i = 0; i < capacity; ++i) {
for (const auto& port : sub_tile.ports) {
if (port.equivalent != PortEquivalence::NONE) {
t_class class_inf;
num_class = (int)type->class_inf.size();
class_inf.num_pins = port.num_pins;
class_inf.equivalence = port.equivalent;

if (port.type == IN_PORT) {
class_inf.type = RECEIVER;
} else {
VTR_ASSERT(port.type == OUT_PORT);
class_inf.type = DRIVER;
}

for (k = 0; k < port.num_pins; ++k) {
class_inf.pinlist.push_back(pin_count);
type->pin_class[pin_count] = num_class;
// clock pins and other specified global ports are initially specified
// as ignored pins (i.e. connections are not created in the rr_graph and
// nets connected to the port are ignored as well).
type->is_ignored_pin[pin_count] = port.is_clock || port.is_non_clock_global;
// clock pins and other specified global ports are flaged as global
type->is_pin_global[pin_count] = port.is_clock || port.is_non_clock_global;

if (port.is_clock) {
type->clock_pin_indices.push_back(pin_count);
}

pin_count++;
}

type->class_inf.push_back(class_inf);
class_range.high++;
} else if (port.equivalent == PortEquivalence::NONE) {
for (k = 0; k < port.num_pins; ++k) {
t_class class_inf;
num_class = (int)type->class_inf.size();
class_inf.num_pins = 1;
class_inf.pinlist.push_back(pin_count);
class_inf.equivalence = port.equivalent;

if (port.type == IN_PORT) {
class_inf.type = RECEIVER;
} else {
VTR_ASSERT(port.type == OUT_PORT);
class_inf.type = DRIVER;
}

type->pin_class[pin_count] = num_class;
// clock pins and other specified global ports are initially specified
// as ignored pins (i.e. connections are not created in the rr_graph and
// nets connected to the port are ignored as well).
type->is_ignored_pin[pin_count] = port.is_clock || port.is_non_clock_global;
// clock pins and other specified global ports are flaged as global
type->is_pin_global[pin_count] = port.is_clock || port.is_non_clock_global;

if (port.is_clock) {
type->clock_pin_indices.push_back(pin_count);
}

pin_count++;

type->class_inf.push_back(class_inf);
class_range.high++;
}
}
}
}

type->sub_tiles[sub_tile.index].class_range = class_range;
}

VTR_ASSERT(pin_count == type->num_pins);
}
8 changes: 6 additions & 2 deletions libs/libarchfpga/src/arch_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ void free_type_descriptors(std::vector<t_physical_tile_type>& type_descriptors);

t_port* findPortByName(const char* name, t_pb_type* pb_type, int* high_index, int* low_index);

t_physical_tile_type SetupEmptyPhysicalType();
t_logical_block_type SetupEmptyLogicalType();
t_physical_tile_type get_empty_physical_type(std::string name);
t_logical_block_type get_empty_logical_type(std::string name);

std::unordered_set<t_logical_block_type_ptr> get_equivalent_sites_set(t_physical_tile_type_ptr type);

Expand Down Expand Up @@ -100,4 +100,8 @@ bool pb_type_contains_blif_model(const t_pb_type* pb_type, const std::string& bl
const t_pin_to_pin_annotation* find_sequential_annotation(const t_pb_type* pb_type, const t_model_ports* port, enum e_pin_to_pin_delay_annotations annot_type);
const t_pin_to_pin_annotation* find_combinational_annotation(const t_pb_type* pb_type, std::string in_port, std::string out_port);

void link_physical_logical_types(std::vector<t_physical_tile_type>& PhysicalTileTypes,
std::vector<t_logical_block_type>& LogicalBlockTypes);

void setup_pin_classes(t_physical_tile_type* type);
#endif
19 changes: 19 additions & 0 deletions libs/libarchfpga/src/physical_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -1738,6 +1738,20 @@ struct t_lut_cell {
std::vector<std::string> inputs;
};

struct t_lut_bel {
std::string name;

std::vector<std::string> input_pins;
std::string output_pin;
};

struct t_package_pin {
std::string name;

std::string site_name;
std::string bel_name;
};

/* Detailed routing architecture */
struct t_arch {
mutable vtr::string_internment strings;
Expand Down Expand Up @@ -1787,6 +1801,11 @@ struct t_arch {

// Luts
std::vector<t_lut_cell> lut_cells;
std::vector<t_lut_bel> lut_bels;

// Package pins
// TODO: add possibility to have multiple packages
std::vector<t_package_pin> pad_bels;

//The name of the switch used for the input connection block (i.e. to
//connect routing tracks to block pins).
Expand Down
Loading