Skip to content

Commit 7a1a6fa

Browse files
committed
libs: arch: interchange: fix luts that have additional pins
Signed-off-by: Alessandro Comodi <[email protected]>
1 parent 88336f3 commit 7a1a6fa

File tree

1 file changed

+68
-40
lines changed

1 file changed

+68
-40
lines changed

libs/libarchfpga/src/read_fpga_interchange_arch.cpp

Lines changed: 68 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ static const auto INPUT = LogicalNetlist::Netlist::Direction::INPUT;
4141
static const auto OUTPUT = LogicalNetlist::Netlist::Direction::OUTPUT;
4242
static const auto INOUT = LogicalNetlist::Netlist::Direction::INOUT;
4343

44+
static const auto LOGIC = Device::BELCategory::LOGIC;
45+
static const auto ROUTING = Device::BELCategory::ROUTING;
46+
static const auto SITE_PORT = Device::BELCategory::SITE_PORT;
47+
4448
// Enum for pack pattern expansion direction
4549
enum e_pp_dir {
4650
FORWARD = 0,
@@ -67,7 +71,7 @@ struct t_bel_cell_mapping {
6771
// Intermediate data type to store information on interconnects to be created
6872
struct t_ic_data {
6973
std::string input;
70-
std::vector<std::string> outputs;
74+
std::set<std::string> outputs;
7175

7276
bool requires_pack_pattern;
7377
};
@@ -334,10 +338,14 @@ struct ArchReader {
334338
}
335339

336340
/** @brief Get the BEL count of a site depending on its category (e.g. logic or routing BELs) */
337-
int get_bel_type_count(Device::SiteType::Reader& site, Device::BELCategory category) {
341+
int get_bel_type_count(Device::SiteType::Reader& site, Device::BELCategory category, bool skip_lut = false) {
338342
int count = 0;
339343
for (auto bel : site.getBels()) {
340-
bool is_logic = category == Device::BELCategory::LOGIC;
344+
auto bel_name = str(bel.getName());
345+
bool is_logic = category == LOGIC;
346+
347+
if (skip_lut && is_lut(bel_name, str(site.getName())))
348+
continue;
341349

342350
bool skip_bel = is_logic && take_bels_.count(bel.getName()) == 0;
343351

@@ -370,7 +378,7 @@ struct ArchReader {
370378

371379
/** @brief Get the BEL name, with an optional deduplication suffix in case its name collides with the site name */
372380
std::string get_bel_name(Device::SiteType::Reader& site, Device::BEL::Reader& bel) {
373-
if (bel.getCategory() == Device::BELCategory::SITE_PORT)
381+
if (bel.getCategory() == SITE_PORT)
374382
return str(site.getName());
375383

376384
auto site_name = str(site.getName());
@@ -511,8 +519,8 @@ struct ArchReader {
511519
auto in_bel_name = get_bel_name(site, in_bel);
512520
auto in_bel_pin_name = out_pin_name;
513521

514-
bool skip_in_bel = in_bel.getCategory() == Device::BELCategory::LOGIC && take_bels_.count(in_bel.getName()) == 0;
515-
bool skip_out_bel = out_bel.getCategory() == Device::BELCategory::LOGIC && take_bels_.count(out_bel.getName()) == 0;
522+
bool skip_in_bel = in_bel.getCategory() == LOGIC && take_bels_.count(in_bel.getName()) == 0;
523+
bool skip_out_bel = out_bel.getCategory() == LOGIC && take_bels_.count(out_bel.getName()) == 0;
516524
if (skip_in_bel || skip_out_bel)
517525
continue;
518526

@@ -521,25 +529,54 @@ struct ArchReader {
521529
// adjust pb_type name in the interconnect accordingly.
522530
auto get_lut_element_index = [&](const std::string& bel_name) {
523531
auto lut_element = get_lut_element_for_bel(site_type, bel_name);
524-
if (lut_element == nullptr) {
532+
if (lut_element == nullptr)
525533
return -1;
526-
}
527534

528535
const auto& lut_elements = arch_->lut_elements.at(site_type);
529536
auto it = std::find(lut_elements.begin(), lut_elements.end(), *lut_element);
530537
VTR_ASSERT(it != lut_elements.end());
538+
531539
return (int)std::distance(lut_elements.begin(), it);
532540
};
533541

534-
int index = -1;
542+
// TODO: This avoids having LUTs that can be used in other ways than LUTs, e.g. as DRAMs.
543+
// Once support is added for macro expansion, all the connections currently marked as
544+
// invalid will be re-enabled.
545+
auto is_lut_connection_valid = [&](const std::string& bel_name, const std::string& pin_name) {
546+
auto lut_element = get_lut_element_for_bel(site_type, bel_name);
547+
if (lut_element == nullptr)
548+
return false;
549+
550+
bool pin_found = false;
551+
for (auto lut_bel : lut_element->lut_bels) {
552+
for (auto lut_bel_pin : lut_bel.input_pins)
553+
pin_found |= lut_bel_pin == pin_name;
554+
555+
pin_found |= lut_bel.output_pin == pin_name;
556+
}
557+
558+
if (!pin_found)
559+
return false;
560+
561+
return true;
562+
};
535563

536-
index = get_lut_element_index(out_bel_name);
564+
int index = get_lut_element_index(out_bel_name);
565+
bool valid_lut = is_lut_connection_valid(out_bel_name, out_bel_pin_name);
537566
if (index >= 0) {
538567
out_bel_name = "LUT" + std::to_string(index);
568+
569+
if (!valid_lut)
570+
continue;
539571
}
572+
540573
index = get_lut_element_index(in_bel_name);
574+
valid_lut = is_lut_connection_valid(in_bel_name, in_bel_pin_name);
541575
if (index >= 0) {
542576
in_bel_name = "LUT" + std::to_string(index);
577+
578+
if (!valid_lut)
579+
continue;
543580
}
544581

545582
std::string ostr = out_bel_name + "." + out_bel_pin_name;
@@ -560,7 +597,7 @@ struct ArchReader {
560597
std::string extra_ostr = in_bel_name + "." + in_bel_pin_name + in_suffix_;
561598
std::string extra_ic_name = ic_name + "_extra";
562599

563-
std::vector<std::string> extra_ostrs{extra_ostr};
600+
std::set<std::string> extra_ostrs{extra_ostr};
564601
t_ic_data extra_ic_data = {
565602
extra_istr, // ic input
566603
extra_ostrs, // ic outputs
@@ -580,7 +617,7 @@ struct ArchReader {
580617
}
581618
}
582619

583-
std::vector<std::string> ostrs{ostr};
620+
std::set<std::string> ostrs{ostr};
584621
t_ic_data ic_data = {
585622
istr,
586623
ostrs,
@@ -600,7 +637,8 @@ struct ArchReader {
600637
VTR_ASSERT(old_data.input == data.input);
601638
VTR_ASSERT(data.outputs.size() == 1);
602639

603-
res.first->second.outputs.push_back(data.outputs[0]);
640+
for (auto out : data.outputs)
641+
res.first->second.outputs.insert(out);
604642
res.first->second.requires_pack_pattern |= data.requires_pack_pattern;
605643
}
606644
}
@@ -974,35 +1012,23 @@ struct ArchReader {
9741012

9751013
// Get LUT elements for this site
9761014
std::vector<t_lut_element> lut_elements;
977-
if (arch_->lut_elements.count(name)) {
1015+
if (arch_->lut_elements.count(name))
9781016
lut_elements = arch_->lut_elements.at(name);
979-
}
9801017

9811018
// Count non-LUT BELs plus LUT elements
982-
int block_count = 0;
983-
int count = 0;
984-
985-
for (auto bel : site.getBels()) {
986-
if (bel.getCategory() != Device::BELCategory::LOGIC) {
987-
continue;
988-
}
989-
if (is_lut(str(bel.getName()), name)) {
990-
continue;
991-
}
992-
block_count++;
993-
}
994-
block_count += lut_elements.size();
1019+
int block_count = get_bel_type_count(site, LOGIC, true) + get_bel_type_count(site, ROUTING, true) + lut_elements.size();
9951020

9961021
mode->num_pb_type_children = block_count;
9971022
mode->pb_type_children = new t_pb_type[mode->num_pb_type_children];
9981023

9991024
// Add regular BELs
1025+
int count = 0;
10001026
for (auto bel : bels) {
10011027
auto category = bel.getCategory();
1002-
if (bel.getCategory() == Device::BELCategory::SITE_PORT)
1028+
if (bel.getCategory() == SITE_PORT)
10031029
continue;
10041030

1005-
bool is_logic = category == Device::BELCategory::LOGIC;
1031+
bool is_logic = category == LOGIC;
10061032

10071033
if (take_bels_.count(bel.getName()) == 0 && is_logic)
10081034
continue;
@@ -1013,7 +1039,7 @@ struct ArchReader {
10131039
auto bel_name = str(bel.getName());
10141040
std::pair<std::string, std::string> key(name, bel_name);
10151041

1016-
auto mid_pb_type = new t_pb_type;
1042+
auto mid_pb_type = &mode->pb_type_children[count++];
10171043
std::string mid_pb_type_name = bel_name == name ? bel_name + bel_dedup_suffix_ : bel_name;
10181044

10191045
mid_pb_type->name = vtr::strdup(mid_pb_type_name.c_str());
@@ -1029,7 +1055,7 @@ struct ArchReader {
10291055
else if (is_logic)
10301056
process_generic_block(mid_pb_type, bel, site);
10311057
else {
1032-
VTR_ASSERT(category == Device::BELCategory::ROUTING);
1058+
VTR_ASSERT(category == ROUTING);
10331059
process_routing_block(mid_pb_type);
10341060
}
10351061
}
@@ -1362,6 +1388,7 @@ struct ArchReader {
13621388
for (auto map : maps) {
13631389
auto name = str(map.cell);
13641390
bool is_compatible = map.site == site.getName();
1391+
13651392
for (auto pin_map : map.pins) {
13661393
if (is_compatible == false)
13671394
break;
@@ -1378,9 +1405,8 @@ struct ArchReader {
13781405

13791406
auto model_port = get_model_port(arch_, name, cell_pin, false);
13801407

1381-
if (is_inout && model_port != nullptr) {
1408+
if (is_inout && model_port != nullptr)
13821409
bel_pin = model_port->dir == IN_PORT ? bel_pin + in_suffix_ : bel_pin + out_suffix_;
1383-
}
13841410

13851411
is_compatible &= block_port_exists(pb_type, bel_pin);
13861412
}
@@ -1394,6 +1420,8 @@ struct ArchReader {
13941420

13951421
int num_modes = maps.size();
13961422

1423+
VTR_ASSERT(num_modes > 0);
1424+
13971425
pb_type->num_modes = num_modes;
13981426
pb_type->modes = new t_mode[num_modes];
13991427

@@ -1403,7 +1431,7 @@ struct ArchReader {
14031431
continue;
14041432

14051433
int idx = count++;
1406-
auto mode = &pb_type->modes[idx];
1434+
t_mode* mode = &pb_type->modes[idx];
14071435
auto name = str(map.cell);
14081436
mode->name = vtr::strdup(name.c_str());
14091437
mode->parent_pb_type = pb_type;
@@ -1645,7 +1673,7 @@ struct ArchReader {
16451673
auto input = ic_data.input;
16461674
auto outputs = ic_data.outputs;
16471675

1648-
auto merge_string = [](std::string& ss, std::string& s) {
1676+
auto merge_string = [](std::string ss, std::string s) {
16491677
return ss.empty() ? s : ss + " " + s;
16501678
};
16511679

@@ -1740,6 +1768,7 @@ struct ArchReader {
17401768
// Assign mode and pb_type
17411769
t_mode* parent_mode = ic->parent_mode;
17421770
t_pb_type* pb_type = nullptr;
1771+
17431772
for (int ipb = 0; ipb < parent_mode->num_pb_type_children; ipb++)
17441773
if (std::string(parent_mode->pb_type_children[ipb].name) == bel)
17451774
pb_type = &parent_mode->pb_type_children[ipb];
@@ -1749,7 +1778,7 @@ struct ArchReader {
17491778
auto bel_reader = get_bel_reader(site, remove_bel_suffix(bel));
17501779

17511780
// Passing through routing mux. Check at the muxes input pins interconnects
1752-
if (bel_reader.getCategory() == Device::BELCategory::ROUTING) {
1781+
if (bel_reader.getCategory() == ROUTING) {
17531782
for (auto bel_pin : bel_reader.getPins()) {
17541783
auto pin_reader = site_pins[bel_pin];
17551784
auto pin_name = str(pin_reader.getName());
@@ -1766,9 +1795,8 @@ struct ArchReader {
17661795
std::string ic_to_find = bel + "." + pin_name;
17671796

17681797
bool found = false;
1769-
for (auto out : vtr::split(is_backward ? other_ic->output_string : other_ic->input_string, " ")) {
1798+
for (auto out : vtr::split(is_backward ? other_ic->output_string : other_ic->input_string, " "))
17701799
found |= out == ic_to_find;
1771-
}
17721800

17731801
if (found) {
17741802
// An output interconnect to propagate was found, continue searching
@@ -1780,7 +1808,7 @@ struct ArchReader {
17801808
}
17811809
}
17821810
} else {
1783-
VTR_ASSERT(bel_reader.getCategory() == Device::BELCategory::LOGIC);
1811+
VTR_ASSERT(bel_reader.getCategory() == LOGIC);
17841812

17851813
for (int imode = 0; imode < pb_type->num_modes; imode++) {
17861814
t_mode* mode = &pb_type->modes[imode];

0 commit comments

Comments
 (0)