Skip to content

Commit 44f9683

Browse files
authored
Merge pull request #1937 from antmicro/acom/fpga-interchange-improve-arch-reading
FPGA Interchange: improve arch reader
2 parents 36789e4 + 450540c commit 44f9683

13 files changed

+2328
-338
lines changed

libs/libarchfpga/src/arch_util.cpp

Lines changed: 207 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -555,9 +555,9 @@ t_port* findPortByName(const char* name, t_pb_type* pb_type, int* high_index, in
555555
return port;
556556
}
557557

558-
t_physical_tile_type SetupEmptyPhysicalType() {
558+
t_physical_tile_type get_empty_physical_type(const char* name) {
559559
t_physical_tile_type type;
560-
type.name = vtr::strdup("EMPTY");
560+
type.name = vtr::strdup(name);
561561
type.num_pins = 0;
562562
type.width = 1;
563563
type.height = 1;
@@ -573,9 +573,9 @@ t_physical_tile_type SetupEmptyPhysicalType() {
573573
return type;
574574
}
575575

576-
t_logical_block_type SetupEmptyLogicalType() {
576+
t_logical_block_type get_empty_logical_type(const char* name) {
577577
t_logical_block_type type;
578-
type.name = vtr::strdup("EMPTY");
578+
type.name = vtr::strdup(name);
579579
type.pb_type = nullptr;
580580

581581
return type;
@@ -1392,5 +1392,208 @@ const t_pin_to_pin_annotation* find_combinational_annotation(const t_pb_type* pb
13921392
}
13931393
}
13941394
}
1395+
13951396
return nullptr;
13961397
}
1398+
1399+
void link_physical_logical_types(std::vector<t_physical_tile_type>& PhysicalTileTypes,
1400+
std::vector<t_logical_block_type>& LogicalBlockTypes) {
1401+
for (auto& physical_tile : PhysicalTileTypes) {
1402+
if (physical_tile.index == EMPTY_TYPE_INDEX) continue;
1403+
1404+
auto eq_sites_set = get_equivalent_sites_set(&physical_tile);
1405+
auto equivalent_sites = std::vector<t_logical_block_type_ptr>(eq_sites_set.begin(), eq_sites_set.end());
1406+
1407+
auto criteria = [&physical_tile](const t_logical_block_type* lhs, const t_logical_block_type* rhs) {
1408+
int num_pins = physical_tile.num_inst_pins;
1409+
1410+
int lhs_num_logical_pins = lhs->pb_type->num_pins;
1411+
int rhs_num_logical_pins = rhs->pb_type->num_pins;
1412+
1413+
int lhs_diff_num_pins = num_pins - lhs_num_logical_pins;
1414+
int rhs_diff_num_pins = num_pins - rhs_num_logical_pins;
1415+
1416+
return lhs_diff_num_pins < rhs_diff_num_pins;
1417+
};
1418+
1419+
std::sort(equivalent_sites.begin(), equivalent_sites.end(), criteria);
1420+
1421+
for (auto& logical_block : LogicalBlockTypes) {
1422+
for (auto site : equivalent_sites) {
1423+
if (0 == strcmp(logical_block.name, site->pb_type->name)) {
1424+
logical_block.equivalent_tiles.push_back(&physical_tile);
1425+
break;
1426+
}
1427+
}
1428+
}
1429+
}
1430+
1431+
for (auto& logical_block : LogicalBlockTypes) {
1432+
if (logical_block.index == EMPTY_TYPE_INDEX) continue;
1433+
1434+
auto& equivalent_tiles = logical_block.equivalent_tiles;
1435+
1436+
if ((int)equivalent_tiles.size() <= 0) {
1437+
archfpga_throw(__FILE__, __LINE__,
1438+
"Logical Block %s does not have any equivalent tiles.\n", logical_block.name);
1439+
}
1440+
1441+
std::unordered_map<int, bool> ignored_pins_check_map;
1442+
std::unordered_map<int, bool> global_pins_check_map;
1443+
1444+
auto criteria = [&logical_block](const t_physical_tile_type* lhs, const t_physical_tile_type* rhs) {
1445+
int num_logical_pins = logical_block.pb_type->num_pins;
1446+
1447+
int lhs_num_pins = lhs->num_inst_pins;
1448+
int rhs_num_pins = rhs->num_inst_pins;
1449+
1450+
int lhs_diff_num_pins = lhs_num_pins - num_logical_pins;
1451+
int rhs_diff_num_pins = rhs_num_pins - num_logical_pins;
1452+
1453+
return lhs_diff_num_pins < rhs_diff_num_pins;
1454+
};
1455+
1456+
std::sort(equivalent_tiles.begin(), equivalent_tiles.end(), criteria);
1457+
1458+
for (int pin = 0; pin < logical_block.pb_type->num_pins; pin++) {
1459+
for (auto& tile : equivalent_tiles) {
1460+
auto direct_maps = tile->tile_block_pin_directs_map.at(logical_block.index);
1461+
1462+
for (auto& sub_tile : tile->sub_tiles) {
1463+
auto equiv_sites = sub_tile.equivalent_sites;
1464+
if (std::find(equiv_sites.begin(), equiv_sites.end(), &logical_block) == equiv_sites.end()) {
1465+
continue;
1466+
}
1467+
1468+
auto direct_map = direct_maps.at(sub_tile.index);
1469+
1470+
auto result = direct_map.find(t_logical_pin(pin));
1471+
if (result == direct_map.end()) {
1472+
archfpga_throw(__FILE__, __LINE__,
1473+
"Logical pin %d not present in pin mapping between Tile %s and Block %s.\n",
1474+
pin, tile->name, logical_block.name);
1475+
}
1476+
1477+
int sub_tile_pin_index = result->second.pin;
1478+
int phy_index = sub_tile.sub_tile_to_tile_pin_indices[sub_tile_pin_index];
1479+
1480+
bool is_ignored = tile->is_ignored_pin[phy_index];
1481+
bool is_global = tile->is_pin_global[phy_index];
1482+
1483+
auto ignored_result = ignored_pins_check_map.insert(std::pair<int, bool>(pin, is_ignored));
1484+
if (!ignored_result.second && ignored_result.first->second != is_ignored) {
1485+
archfpga_throw(__FILE__, __LINE__,
1486+
"Physical Tile %s has a different value for the ignored pin (physical pin: %d, logical pin: %d) "
1487+
"different from the corresponding pins of the other equivalent site %s\n.",
1488+
tile->name, phy_index, pin, logical_block.name);
1489+
}
1490+
1491+
auto global_result = global_pins_check_map.insert(std::pair<int, bool>(pin, is_global));
1492+
if (!global_result.second && global_result.first->second != is_global) {
1493+
archfpga_throw(__FILE__, __LINE__,
1494+
"Physical Tile %s has a different value for the global pin (physical pin: %d, logical pin: %d) "
1495+
"different from the corresponding pins of the other equivalent sites\n.",
1496+
tile->name, phy_index, pin);
1497+
}
1498+
}
1499+
}
1500+
}
1501+
}
1502+
}
1503+
1504+
/* Sets up the pin classes for the type. */
1505+
void setup_pin_classes(t_physical_tile_type* type) {
1506+
int i, k;
1507+
int pin_count;
1508+
int num_class;
1509+
1510+
for (i = 0; i < type->num_pins; i++) {
1511+
type->pin_class.push_back(OPEN);
1512+
type->is_ignored_pin.push_back(true);
1513+
type->is_pin_global.push_back(true);
1514+
}
1515+
1516+
pin_count = 0;
1517+
1518+
t_class_range class_range;
1519+
1520+
/* Equivalent pins share the same class, non-equivalent pins belong to different pin classes */
1521+
for (auto& sub_tile : type->sub_tiles) {
1522+
int capacity = sub_tile.capacity.total();
1523+
class_range.low = type->class_inf.size();
1524+
class_range.high = class_range.low - 1;
1525+
for (i = 0; i < capacity; ++i) {
1526+
for (const auto& port : sub_tile.ports) {
1527+
if (port.equivalent != PortEquivalence::NONE) {
1528+
t_class class_inf;
1529+
num_class = (int)type->class_inf.size();
1530+
class_inf.num_pins = port.num_pins;
1531+
class_inf.equivalence = port.equivalent;
1532+
1533+
if (port.type == IN_PORT) {
1534+
class_inf.type = RECEIVER;
1535+
} else {
1536+
VTR_ASSERT(port.type == OUT_PORT);
1537+
class_inf.type = DRIVER;
1538+
}
1539+
1540+
for (k = 0; k < port.num_pins; ++k) {
1541+
class_inf.pinlist.push_back(pin_count);
1542+
type->pin_class[pin_count] = num_class;
1543+
// clock pins and other specified global ports are initially specified
1544+
// as ignored pins (i.e. connections are not created in the rr_graph and
1545+
// nets connected to the port are ignored as well).
1546+
type->is_ignored_pin[pin_count] = port.is_clock || port.is_non_clock_global;
1547+
// clock pins and other specified global ports are flaged as global
1548+
type->is_pin_global[pin_count] = port.is_clock || port.is_non_clock_global;
1549+
1550+
if (port.is_clock) {
1551+
type->clock_pin_indices.push_back(pin_count);
1552+
}
1553+
1554+
pin_count++;
1555+
}
1556+
1557+
type->class_inf.push_back(class_inf);
1558+
class_range.high++;
1559+
} else if (port.equivalent == PortEquivalence::NONE) {
1560+
for (k = 0; k < port.num_pins; ++k) {
1561+
t_class class_inf;
1562+
num_class = (int)type->class_inf.size();
1563+
class_inf.num_pins = 1;
1564+
class_inf.pinlist.push_back(pin_count);
1565+
class_inf.equivalence = port.equivalent;
1566+
1567+
if (port.type == IN_PORT) {
1568+
class_inf.type = RECEIVER;
1569+
} else {
1570+
VTR_ASSERT(port.type == OUT_PORT);
1571+
class_inf.type = DRIVER;
1572+
}
1573+
1574+
type->pin_class[pin_count] = num_class;
1575+
// clock pins and other specified global ports are initially specified
1576+
// as ignored pins (i.e. connections are not created in the rr_graph and
1577+
// nets connected to the port are ignored as well).
1578+
type->is_ignored_pin[pin_count] = port.is_clock || port.is_non_clock_global;
1579+
// clock pins and other specified global ports are flaged as global
1580+
type->is_pin_global[pin_count] = port.is_clock || port.is_non_clock_global;
1581+
1582+
if (port.is_clock) {
1583+
type->clock_pin_indices.push_back(pin_count);
1584+
}
1585+
1586+
pin_count++;
1587+
1588+
type->class_inf.push_back(class_inf);
1589+
class_range.high++;
1590+
}
1591+
}
1592+
}
1593+
}
1594+
1595+
type->sub_tiles[sub_tile.index].class_range = class_range;
1596+
}
1597+
1598+
VTR_ASSERT(pin_count == type->num_pins);
1599+
}

libs/libarchfpga/src/arch_util.h

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ void set_arch_file_name(const char* arch);
1515
*/
1616
const char* get_arch_file_name();
1717

18+
constexpr const char* EMPTY_BLOCK_NAME = "EMPTY";
19+
1820
class InstPort {
1921
public:
2022
static constexpr int UNSPECIFIED = -1;
@@ -60,8 +62,15 @@ void free_type_descriptors(std::vector<t_physical_tile_type>& type_descriptors);
6062

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

63-
t_physical_tile_type SetupEmptyPhysicalType();
64-
t_logical_block_type SetupEmptyLogicalType();
65+
/** @brief Returns and empty physical tile type, assigned with the given name argument.
66+
* The default empty string is assigned if no name is provided
67+
*/
68+
t_physical_tile_type get_empty_physical_type(const char* name = EMPTY_BLOCK_NAME);
69+
70+
/** @brief Returns and empty logical block type, assigned with the given name argument.
71+
* The default empty string is assigned if no name is provided
72+
*/
73+
t_logical_block_type get_empty_logical_type(const char* name = EMPTY_BLOCK_NAME);
6574

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

@@ -100,4 +109,17 @@ bool pb_type_contains_blif_model(const t_pb_type* pb_type, const std::string& bl
100109
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);
101110
const t_pin_to_pin_annotation* find_combinational_annotation(const t_pb_type* pb_type, std::string in_port, std::string out_port);
102111

112+
/**
113+
* @brief Updates the physical and logical types based on the equivalence between one and the other.
114+
*
115+
* This function is required to check and synchronize all the information to be able to use the logical block
116+
* equivalence, and link all the logical block pins to the physical tile ones, given that multiple logical blocks (i.e. pb_types)
117+
* can be placed at the same physical location if this is allowed in the architecture description.
118+
*
119+
* See https://docs.verilogtorouting.org/en/latest/tutorials/arch/equivalent_sites/ for reference
120+
*/
121+
void link_physical_logical_types(std::vector<t_physical_tile_type>& PhysicalTileTypes,
122+
std::vector<t_logical_block_type>& LogicalBlockTypes);
123+
124+
void setup_pin_classes(t_physical_tile_type* type);
103125
#endif

libs/libarchfpga/src/physical_types.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
#include "physical_types.h"
22
#include "vtr_math.h"
33
#include "vtr_util.h"
4+
#include "vtr_log.h"
5+
6+
#include "arch_util.h"
47

58
static bool switch_type_is_buffered(SwitchType type);
69
static bool switch_type_is_configurable(SwitchType type);
@@ -129,6 +132,18 @@ int t_physical_tile_type::get_sub_tile_loc_from_pin(int pin_num) const {
129132
return OPEN;
130133
}
131134

135+
bool t_physical_tile_type::is_empty() const {
136+
return std::string(name) == std::string(EMPTY_BLOCK_NAME);
137+
}
138+
139+
/*
140+
* t_logical_block_type
141+
*/
142+
143+
bool t_logical_block_type::is_empty() const {
144+
return std::string(name) == std::string(EMPTY_BLOCK_NAME);
145+
}
146+
132147
/**
133148
* t_pb_graph_node
134149
*/

libs/libarchfpga/src/physical_types.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,9 @@ struct t_physical_tile_type {
653653

654654
// Does this t_physical_tile_type contain an outpad?
655655
bool is_output_type = false;
656+
657+
// Is this t_physical_tile_type an empty type?
658+
bool is_empty() const;
656659
};
657660

658661
/* Holds the capacity range of a certain sub_tile block within the parent physical tile type.
@@ -828,6 +831,9 @@ struct t_logical_block_type {
828831

829832
std::vector<t_physical_tile_type_ptr> equivalent_tiles; ///>List of physical tiles at which one could
830833
///>place this type of netlist block.
834+
835+
// Is this t_logical_block_type empty?
836+
bool is_empty() const;
831837
};
832838

833839
/*************************************************************************************************
@@ -1738,9 +1744,31 @@ struct t_lut_cell {
17381744
std::vector<std::string> inputs;
17391745
};
17401746

1747+
struct t_lut_bel {
1748+
std::string name;
1749+
1750+
std::vector<std::string> input_pins;
1751+
std::string output_pin;
1752+
1753+
bool operator==(const t_lut_bel& other) const {
1754+
return name == other.name && input_pins == other.input_pins && output_pin == other.output_pin;
1755+
}
1756+
};
1757+
1758+
struct t_lut_element {
1759+
std::string site_type;
1760+
int width;
1761+
std::vector<t_lut_bel> lut_bels;
1762+
1763+
bool operator==(const t_lut_element& other) const {
1764+
return site_type == other.site_type && width == other.width && lut_bels == other.lut_bels;
1765+
}
1766+
};
1767+
17411768
/* Detailed routing architecture */
17421769
struct t_arch {
17431770
mutable vtr::string_internment strings;
1771+
std::vector<vtr::interned_string> interned_strings;
17441772

17451773
char* architecture_id; //Secure hash digest of the architecture file to uniquely identify this architecture
17461774

@@ -1787,6 +1815,7 @@ struct t_arch {
17871815

17881816
// Luts
17891817
std::vector<t_lut_cell> lut_cells;
1818+
std::unordered_map<std::string, std::vector<t_lut_element>> lut_elements;
17901819

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

0 commit comments

Comments
 (0)