@@ -41,6 +41,10 @@ static const auto INPUT = LogicalNetlist::Netlist::Direction::INPUT;
41
41
static const auto OUTPUT = LogicalNetlist::Netlist::Direction::OUTPUT;
42
42
static const auto INOUT = LogicalNetlist::Netlist::Direction::INOUT;
43
43
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
+
44
48
// Enum for pack pattern expansion direction
45
49
enum e_pp_dir {
46
50
FORWARD = 0 ,
@@ -67,7 +71,7 @@ struct t_bel_cell_mapping {
67
71
// Intermediate data type to store information on interconnects to be created
68
72
struct t_ic_data {
69
73
std::string input;
70
- std::vector <std::string> outputs;
74
+ std::set <std::string> outputs;
71
75
72
76
bool requires_pack_pattern;
73
77
};
@@ -334,10 +338,14 @@ struct ArchReader {
334
338
}
335
339
336
340
/* * @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 ) {
338
342
int count = 0 ;
339
343
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 ;
341
349
342
350
bool skip_bel = is_logic && take_bels_.count (bel.getName ()) == 0 ;
343
351
@@ -370,7 +378,7 @@ struct ArchReader {
370
378
371
379
/* * @brief Get the BEL name, with an optional deduplication suffix in case its name collides with the site name */
372
380
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)
374
382
return str (site.getName ());
375
383
376
384
auto site_name = str (site.getName ());
@@ -511,8 +519,8 @@ struct ArchReader {
511
519
auto in_bel_name = get_bel_name (site, in_bel);
512
520
auto in_bel_pin_name = out_pin_name;
513
521
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 ;
516
524
if (skip_in_bel || skip_out_bel)
517
525
continue ;
518
526
@@ -521,25 +529,54 @@ struct ArchReader {
521
529
// adjust pb_type name in the interconnect accordingly.
522
530
auto get_lut_element_index = [&](const std::string& bel_name) {
523
531
auto lut_element = get_lut_element_for_bel (site_type, bel_name);
524
- if (lut_element == nullptr ) {
532
+ if (lut_element == nullptr )
525
533
return -1 ;
526
- }
527
534
528
535
const auto & lut_elements = arch_->lut_elements .at (site_type);
529
536
auto it = std::find (lut_elements.begin (), lut_elements.end (), *lut_element);
530
537
VTR_ASSERT (it != lut_elements.end ());
538
+
531
539
return (int )std::distance (lut_elements.begin (), it);
532
540
};
533
541
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
+ };
535
563
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);
537
566
if (index >= 0 ) {
538
567
out_bel_name = " LUT" + std::to_string (index );
568
+
569
+ if (!valid_lut)
570
+ continue ;
539
571
}
572
+
540
573
index = get_lut_element_index (in_bel_name);
574
+ valid_lut = is_lut_connection_valid (in_bel_name, in_bel_pin_name);
541
575
if (index >= 0 ) {
542
576
in_bel_name = " LUT" + std::to_string (index );
577
+
578
+ if (!valid_lut)
579
+ continue ;
543
580
}
544
581
545
582
std::string ostr = out_bel_name + " ." + out_bel_pin_name;
@@ -560,7 +597,7 @@ struct ArchReader {
560
597
std::string extra_ostr = in_bel_name + " ." + in_bel_pin_name + in_suffix_;
561
598
std::string extra_ic_name = ic_name + " _extra" ;
562
599
563
- std::vector <std::string> extra_ostrs{extra_ostr};
600
+ std::set <std::string> extra_ostrs{extra_ostr};
564
601
t_ic_data extra_ic_data = {
565
602
extra_istr, // ic input
566
603
extra_ostrs, // ic outputs
@@ -580,7 +617,7 @@ struct ArchReader {
580
617
}
581
618
}
582
619
583
- std::vector <std::string> ostrs{ostr};
620
+ std::set <std::string> ostrs{ostr};
584
621
t_ic_data ic_data = {
585
622
istr,
586
623
ostrs,
@@ -600,7 +637,8 @@ struct ArchReader {
600
637
VTR_ASSERT (old_data.input == data.input );
601
638
VTR_ASSERT (data.outputs .size () == 1 );
602
639
603
- res.first ->second .outputs .push_back (data.outputs [0 ]);
640
+ for (auto out : data.outputs )
641
+ res.first ->second .outputs .insert (out);
604
642
res.first ->second .requires_pack_pattern |= data.requires_pack_pattern ;
605
643
}
606
644
}
@@ -974,35 +1012,23 @@ struct ArchReader {
974
1012
975
1013
// Get LUT elements for this site
976
1014
std::vector<t_lut_element> lut_elements;
977
- if (arch_->lut_elements .count (name)) {
1015
+ if (arch_->lut_elements .count (name))
978
1016
lut_elements = arch_->lut_elements .at (name);
979
- }
980
1017
981
1018
// 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 ();
995
1020
996
1021
mode->num_pb_type_children = block_count;
997
1022
mode->pb_type_children = new t_pb_type[mode->num_pb_type_children ];
998
1023
999
1024
// Add regular BELs
1025
+ int count = 0 ;
1000
1026
for (auto bel : bels) {
1001
1027
auto category = bel.getCategory ();
1002
- if (bel.getCategory () == Device::BELCategory:: SITE_PORT)
1028
+ if (bel.getCategory () == SITE_PORT)
1003
1029
continue ;
1004
1030
1005
- bool is_logic = category == Device::BELCategory:: LOGIC;
1031
+ bool is_logic = category == LOGIC;
1006
1032
1007
1033
if (take_bels_.count (bel.getName ()) == 0 && is_logic)
1008
1034
continue ;
@@ -1013,7 +1039,7 @@ struct ArchReader {
1013
1039
auto bel_name = str (bel.getName ());
1014
1040
std::pair<std::string, std::string> key (name, bel_name);
1015
1041
1016
- auto mid_pb_type = new t_pb_type ;
1042
+ auto mid_pb_type = &mode-> pb_type_children [count++] ;
1017
1043
std::string mid_pb_type_name = bel_name == name ? bel_name + bel_dedup_suffix_ : bel_name;
1018
1044
1019
1045
mid_pb_type->name = vtr::strdup (mid_pb_type_name.c_str ());
@@ -1029,7 +1055,7 @@ struct ArchReader {
1029
1055
else if (is_logic)
1030
1056
process_generic_block (mid_pb_type, bel, site);
1031
1057
else {
1032
- VTR_ASSERT (category == Device::BELCategory:: ROUTING);
1058
+ VTR_ASSERT (category == ROUTING);
1033
1059
process_routing_block (mid_pb_type);
1034
1060
}
1035
1061
}
@@ -1362,6 +1388,7 @@ struct ArchReader {
1362
1388
for (auto map : maps) {
1363
1389
auto name = str (map.cell );
1364
1390
bool is_compatible = map.site == site.getName ();
1391
+
1365
1392
for (auto pin_map : map.pins ) {
1366
1393
if (is_compatible == false )
1367
1394
break ;
@@ -1378,9 +1405,8 @@ struct ArchReader {
1378
1405
1379
1406
auto model_port = get_model_port (arch_, name, cell_pin, false );
1380
1407
1381
- if (is_inout && model_port != nullptr ) {
1408
+ if (is_inout && model_port != nullptr )
1382
1409
bel_pin = model_port->dir == IN_PORT ? bel_pin + in_suffix_ : bel_pin + out_suffix_;
1383
- }
1384
1410
1385
1411
is_compatible &= block_port_exists (pb_type, bel_pin);
1386
1412
}
@@ -1394,6 +1420,8 @@ struct ArchReader {
1394
1420
1395
1421
int num_modes = maps.size ();
1396
1422
1423
+ VTR_ASSERT (num_modes > 0 );
1424
+
1397
1425
pb_type->num_modes = num_modes;
1398
1426
pb_type->modes = new t_mode[num_modes];
1399
1427
@@ -1403,7 +1431,7 @@ struct ArchReader {
1403
1431
continue ;
1404
1432
1405
1433
int idx = count++;
1406
- auto mode = &pb_type->modes [idx];
1434
+ t_mode* mode = &pb_type->modes [idx];
1407
1435
auto name = str (map.cell );
1408
1436
mode->name = vtr::strdup (name.c_str ());
1409
1437
mode->parent_pb_type = pb_type;
@@ -1645,7 +1673,7 @@ struct ArchReader {
1645
1673
auto input = ic_data.input ;
1646
1674
auto outputs = ic_data.outputs ;
1647
1675
1648
- auto merge_string = [](std::string& ss, std::string& s) {
1676
+ auto merge_string = [](std::string ss, std::string s) {
1649
1677
return ss.empty () ? s : ss + " " + s;
1650
1678
};
1651
1679
@@ -1740,6 +1768,7 @@ struct ArchReader {
1740
1768
// Assign mode and pb_type
1741
1769
t_mode* parent_mode = ic->parent_mode ;
1742
1770
t_pb_type* pb_type = nullptr ;
1771
+
1743
1772
for (int ipb = 0 ; ipb < parent_mode->num_pb_type_children ; ipb++)
1744
1773
if (std::string (parent_mode->pb_type_children [ipb].name ) == bel)
1745
1774
pb_type = &parent_mode->pb_type_children [ipb];
@@ -1749,7 +1778,7 @@ struct ArchReader {
1749
1778
auto bel_reader = get_bel_reader (site, remove_bel_suffix (bel));
1750
1779
1751
1780
// 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) {
1753
1782
for (auto bel_pin : bel_reader.getPins ()) {
1754
1783
auto pin_reader = site_pins[bel_pin];
1755
1784
auto pin_name = str (pin_reader.getName ());
@@ -1766,9 +1795,8 @@ struct ArchReader {
1766
1795
std::string ic_to_find = bel + " ." + pin_name;
1767
1796
1768
1797
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 , " " ))
1770
1799
found |= out == ic_to_find;
1771
- }
1772
1800
1773
1801
if (found) {
1774
1802
// An output interconnect to propagate was found, continue searching
@@ -1780,7 +1808,7 @@ struct ArchReader {
1780
1808
}
1781
1809
}
1782
1810
} else {
1783
- VTR_ASSERT (bel_reader.getCategory () == Device::BELCategory:: LOGIC);
1811
+ VTR_ASSERT (bel_reader.getCategory () == LOGIC);
1784
1812
1785
1813
for (int imode = 0 ; imode < pb_type->num_modes ; imode++) {
1786
1814
t_mode* mode = &pb_type->modes [imode];
0 commit comments