92
92
// File local type declarations
93
93
//
94
94
95
+ // This pair cointains the following values:
96
+ // - double: hold, setup or clock-to-q delays of the port
97
+ // - string: port name of the associated source clock pin of the sequential port
98
+ typedef std::pair<double , std::string> sequential_port_delay_pair;
99
+
95
100
/* enum class PortType {
96
101
* IN,
97
102
* OUT,
@@ -553,8 +558,9 @@ class BlackBoxInst : public Instance {
553
558
std::map<std::string, std::vector<std::string>> input_port_conns, // /<Port connections: Dictionary of <port,nets>
554
559
std::map<std::string, std::vector<std::string>> output_port_conns, // /<Port connections: Dictionary of <port,nets>
555
560
std::vector<Arc> timing_arcs, // /<Combinational timing arcs
556
- std::map<std::string, double > ports_tsu, // /<Port setup checks
557
- std::map<std::string, double > ports_tcq) // /<Port clock-to-q delays
561
+ std::map<std::string, sequential_port_delay_pair> ports_tsu, // /<Port setup checks
562
+ std::map<std::string, sequential_port_delay_pair> ports_thld, // /<Port hold checks
563
+ std::map<std::string, sequential_port_delay_pair> ports_tcq) // /<Port clock-to-q delays
558
564
: type_name_(type_name)
559
565
, inst_name_(inst_name)
560
566
, params_(params)
@@ -563,6 +569,7 @@ class BlackBoxInst : public Instance {
563
569
, output_port_conns_(output_port_conns)
564
570
, timing_arcs_(timing_arcs)
565
571
, ports_tsu_(ports_tsu)
572
+ , ports_thld_(ports_thld)
566
573
, ports_tcq_(ports_tcq) {}
567
574
568
575
void print_blif (std::ostream& os, size_t & unconn_count, int depth = 0 ) override {
@@ -648,75 +655,77 @@ class BlackBoxInst : public Instance {
648
655
}
649
656
650
657
void print_sdf (std::ostream& os, int depth = 0 ) override {
651
- os << indent (depth) << " (CELL\n " ;
652
- os << indent (depth + 1 ) << " (CELLTYPE \" " << type_name_ << " \" )\n " ;
653
- os << indent (depth + 1 ) << " (INSTANCE " << escape_sdf_identifier (inst_name_) << " )\n " ;
654
- os << indent (depth + 1 ) << " (DELAY\n " ;
658
+ if (!timing_arcs_.empty () || !ports_tcq_.empty () || !ports_tsu_.empty () || !ports_thld_.empty ()) {
659
+ os << indent (depth) << " (CELL\n " ;
660
+ os << indent (depth + 1 ) << " (CELLTYPE \" " << type_name_ << " \" )\n " ;
661
+ os << indent (depth + 1 ) << " (INSTANCE " << escape_sdf_identifier (inst_name_) << " )\n " ;
662
+ os << indent (depth + 1 ) << " (DELAY\n " ;
655
663
656
- if (!timing_arcs_.empty () || !ports_tcq_.empty ()) {
657
- os << indent (depth + 2 ) << " (ABSOLUTE\n " ;
664
+ if (!timing_arcs_.empty () || !ports_tcq_.empty ()) {
665
+ os << indent (depth + 2 ) << " (ABSOLUTE\n " ;
658
666
659
- // Combinational paths
660
- for (const auto & arc : timing_arcs_) {
661
- double delay_ps = get_delay_ps (arc.delay ());
667
+ // Combinational paths
668
+ for (const auto & arc : timing_arcs_) {
669
+ double delay_ps = get_delay_ps (arc.delay ());
662
670
663
- std::stringstream delay_triple;
664
- delay_triple << " (" << delay_ps << " :" << delay_ps << " :" << delay_ps << " )" ;
671
+ std::stringstream delay_triple;
672
+ delay_triple << " (" << delay_ps << " :" << delay_ps << " :" << delay_ps << " )" ;
665
673
666
- // Note that we explicitly do not escape the last array indexing so an SDF
667
- // reader will treat the ports as multi-bit
668
- //
669
- // We also only put the last index in if the port has multiple bits
670
- os << indent (depth + 3 ) << " (IOPATH " ;
671
- os << escape_sdf_identifier (arc.source_name ());
672
- if (find_port_size (arc.source_name ()) > 1 ) {
673
- os << " [" << arc.source_ipin () << " ]" ;
674
- }
675
- os << " " ;
676
- os << escape_sdf_identifier (arc.sink_name ());
677
- if (find_port_size (arc.sink_name ()) > 1 ) {
678
- os << " [" << arc.sink_ipin () << " ]" ;
674
+ // Note that we explicitly do not escape the last array indexing so an SDF
675
+ // reader will treat the ports as multi-bit
676
+ //
677
+ // We also only put the last index in if the port has multiple bits
678
+ os << indent (depth + 3 ) << " (IOPATH " ;
679
+ os << escape_sdf_identifier (arc.source_name ());
680
+ if (find_port_size (arc.source_name ()) > 1 ) {
681
+ os << " [" << arc.source_ipin () << " ]" ;
682
+ }
683
+ os << " " ;
684
+ os << escape_sdf_identifier (arc.sink_name ());
685
+ if (find_port_size (arc.sink_name ()) > 1 ) {
686
+ os << " [" << arc.sink_ipin () << " ]" ;
687
+ }
688
+ os << " " ;
689
+ os << delay_triple.str ();
690
+ os << " )\n " ;
679
691
}
680
- os << " " ;
681
- os << delay_triple.str ();
682
- os << " )\n " ;
683
- }
684
692
685
- // Clock-to-Q delays
686
- for (auto kv : ports_tcq_) {
687
- double clock_to_q_ps = get_delay_ps (kv.second );
693
+ // Clock-to-Q delays
694
+ for (auto kv : ports_tcq_) {
695
+ double clock_to_q_ps = get_delay_ps (kv.second . first );
688
696
689
- std::stringstream delay_triple;
690
- delay_triple << " (" << clock_to_q_ps << " :" << clock_to_q_ps << " :" << clock_to_q_ps << " )" ;
697
+ std::stringstream delay_triple;
698
+ delay_triple << " (" << clock_to_q_ps << " :" << clock_to_q_ps << " :" << clock_to_q_ps << " )" ;
691
699
692
- os << indent (depth + 3 ) << " (IOPATH (posedge clock) " << escape_sdf_identifier (kv.first ) << " " << delay_triple.str () << " " << delay_triple.str () << " )\n " ;
700
+ os << indent (depth + 3 ) << " (IOPATH (posedge " << escape_sdf_identifier (kv.second .second ) << " ) " << escape_sdf_identifier (kv.first ) << " " << delay_triple.str () << " " << delay_triple.str () << " )\n " ;
701
+ }
702
+ os << indent (depth + 2 ) << " )\n " ; // ABSOLUTE
693
703
}
694
- os << indent (depth + 2 ) << " )\n " ; // ABSOLUTE
695
- }
696
- os << indent (depth + 1 ) << " )\n " ; // DELAY
704
+ os << indent (depth + 1 ) << " )\n " ; // DELAY
697
705
698
- if (!ports_tsu_.empty () || !ports_thld_.empty ()) {
699
- // Setup checks
700
- os << indent (depth + 1 ) << " (TIMINGCHECK\n " ;
701
- for (auto kv : ports_tsu_) {
702
- double setup_ps = get_delay_ps (kv.second );
706
+ if (!ports_tsu_.empty () || !ports_thld_.empty ()) {
707
+ // Setup checks
708
+ os << indent (depth + 1 ) << " (TIMINGCHECK\n " ;
709
+ for (auto kv : ports_tsu_) {
710
+ double setup_ps = get_delay_ps (kv.second . first );
703
711
704
- std::stringstream delay_triple;
705
- delay_triple << " (" << setup_ps << " :" << setup_ps << " :" << setup_ps << " )" ;
712
+ std::stringstream delay_triple;
713
+ delay_triple << " (" << setup_ps << " :" << setup_ps << " :" << setup_ps << " )" ;
706
714
707
- os << indent (depth + 2 ) << " (SETUP " << escape_sdf_identifier (kv.first ) << " (posedge clock ) " << delay_triple.str () << " )\n " ;
708
- }
709
- for (auto kv : ports_thld_) {
710
- double hold_ps = get_delay_ps (kv.second );
715
+ os << indent (depth + 2 ) << " (SETUP " << escape_sdf_identifier (kv.first ) << " (posedge " << escape_sdf_identifier (kv. second . second ) << " ) " << delay_triple.str () << " )\n " ;
716
+ }
717
+ for (auto kv : ports_thld_) {
718
+ double hold_ps = get_delay_ps (kv.second . first );
711
719
712
- std::stringstream delay_triple;
713
- delay_triple << " (" << hold_ps << " :" << hold_ps << " :" << hold_ps << " )" ;
720
+ std::stringstream delay_triple;
721
+ delay_triple << " (" << hold_ps << " :" << hold_ps << " :" << hold_ps << " )" ;
714
722
715
- os << indent (depth + 2 ) << " (HOLD " << escape_sdf_identifier (kv.first ) << " (posedge clock) " << delay_triple.str () << " )\n " ;
723
+ os << indent (depth + 2 ) << " (HOLD " << escape_sdf_identifier (kv.first ) << " (posedge " << escape_sdf_identifier (kv.second .second ) << " ) " << delay_triple.str () << " )\n " ;
724
+ }
725
+ os << indent (depth + 1 ) << " )\n " ; // TIMINGCHECK
716
726
}
717
- os << indent (depth + 1 ) << " )\n " ; // TIMINGCHECK
727
+ os << indent (depth) << " )\n " ; // CELL
718
728
}
719
- os << indent (depth) << " )\n " ; // CELL
720
729
}
721
730
722
731
size_t find_port_size (std::string port_name) {
@@ -743,9 +752,9 @@ class BlackBoxInst : public Instance {
743
752
std::map<std::string, std::vector<std::string>> input_port_conns_;
744
753
std::map<std::string, std::vector<std::string>> output_port_conns_;
745
754
std::vector<Arc> timing_arcs_;
746
- std::map<std::string, double > ports_tsu_;
747
- std::map<std::string, double > ports_thld_;
748
- std::map<std::string, double > ports_tcq_;
755
+ std::map<std::string, sequential_port_delay_pair > ports_tsu_;
756
+ std::map<std::string, sequential_port_delay_pair > ports_thld_;
757
+ std::map<std::string, sequential_port_delay_pair > ports_tcq_;
749
758
};
750
759
751
760
/* *
@@ -894,6 +903,8 @@ class NetlistWriterVisitor : public NetlistVisitor {
894
903
}
895
904
}
896
905
906
+ verilog_os_ << indent (depth + 1 ) << " wire DummyOut;\n " ;
907
+
897
908
// connections between primary I/Os and their internal wires
898
909
verilog_os_ << " \n " ;
899
910
verilog_os_ << indent (depth + 1 ) << " //IO assignments\n " ;
@@ -1277,8 +1288,9 @@ class NetlistWriterVisitor : public NetlistVisitor {
1277
1288
std::map<std::string, std::vector<std::string>> input_port_conns;
1278
1289
std::map<std::string, std::vector<std::string>> output_port_conns;
1279
1290
std::vector<Arc> timing_arcs;
1280
- std::map<std::string, double > ports_tsu;
1281
- std::map<std::string, double > ports_tcq;
1291
+ std::map<std::string, sequential_port_delay_pair> ports_tsu;
1292
+ std::map<std::string, sequential_port_delay_pair> ports_thld;
1293
+ std::map<std::string, sequential_port_delay_pair> ports_tcq;
1282
1294
1283
1295
params[" ADDR_WIDTH" ] = " 0" ;
1284
1296
params[" DATA_WIDTH" ] = " 0" ;
@@ -1334,7 +1346,7 @@ class NetlistWriterVisitor : public NetlistVisitor {
1334
1346
}
1335
1347
1336
1348
input_port_conns[port_name].push_back (net);
1337
- ports_tsu[port_name] = pin->tsu ;
1349
+ ports_tsu[port_name] = std::make_pair ( pin->tsu , pin-> associated_clock_pin -> port -> name ) ;
1338
1350
}
1339
1351
}
1340
1352
@@ -1370,7 +1382,7 @@ class NetlistWriterVisitor : public NetlistVisitor {
1370
1382
" Unrecognized input port class '%s' for primitive '%s' (%s)\n " , port_class.c_str (), atom->name , pb_type->name );
1371
1383
}
1372
1384
output_port_conns[port_name].push_back (net);
1373
- ports_tcq[port_name] = pin->tco_max ;
1385
+ ports_tcq[port_name] = std::make_pair ( pin->tco_max , pin-> associated_clock_pin -> port -> name ) ;
1374
1386
}
1375
1387
}
1376
1388
@@ -1401,7 +1413,7 @@ class NetlistWriterVisitor : public NetlistVisitor {
1401
1413
}
1402
1414
}
1403
1415
1404
- return std::make_shared<BlackBoxInst>(type, inst_name, params, attrs, input_port_conns, output_port_conns, timing_arcs, ports_tsu, ports_tcq);
1416
+ return std::make_shared<BlackBoxInst>(type, inst_name, params, attrs, input_port_conns, output_port_conns, timing_arcs, ports_tsu, ports_thld, ports_tcq);
1405
1417
}
1406
1418
1407
1419
// /@brief Returns an Instance object representing a Multiplier
@@ -1419,8 +1431,9 @@ class NetlistWriterVisitor : public NetlistVisitor {
1419
1431
std::map<std::string, std::vector<std::string>> input_port_conns;
1420
1432
std::map<std::string, std::vector<std::string>> output_port_conns;
1421
1433
std::vector<Arc> timing_arcs;
1422
- std::map<std::string, double > ports_tsu;
1423
- std::map<std::string, double > ports_tcq;
1434
+ std::map<std::string, sequential_port_delay_pair> ports_tsu;
1435
+ std::map<std::string, sequential_port_delay_pair> ports_thld;
1436
+ std::map<std::string, sequential_port_delay_pair> ports_tcq;
1424
1437
1425
1438
params[" WIDTH" ] = " 0" ;
1426
1439
@@ -1496,7 +1509,7 @@ class NetlistWriterVisitor : public NetlistVisitor {
1496
1509
1497
1510
VTR_ASSERT (pb_graph_node->num_clock_ports == 0 ); // No clocks
1498
1511
1499
- return std::make_shared<BlackBoxInst>(type_name, inst_name, params, attrs, input_port_conns, output_port_conns, timing_arcs, ports_tsu, ports_tcq);
1512
+ return std::make_shared<BlackBoxInst>(type_name, inst_name, params, attrs, input_port_conns, output_port_conns, timing_arcs, ports_tsu, ports_thld, ports_tcq);
1500
1513
}
1501
1514
1502
1515
// /@brief Returns an Instance object representing an Adder
@@ -1514,8 +1527,9 @@ class NetlistWriterVisitor : public NetlistVisitor {
1514
1527
std::map<std::string, std::vector<std::string>> input_port_conns;
1515
1528
std::map<std::string, std::vector<std::string>> output_port_conns;
1516
1529
std::vector<Arc> timing_arcs;
1517
- std::map<std::string, double > ports_tsu;
1518
- std::map<std::string, double > ports_tcq;
1530
+ std::map<std::string, sequential_port_delay_pair> ports_tsu;
1531
+ std::map<std::string, sequential_port_delay_pair> ports_thld;
1532
+ std::map<std::string, sequential_port_delay_pair> ports_tcq;
1519
1533
1520
1534
params[" WIDTH" ] = " 0" ;
1521
1535
@@ -1595,23 +1609,33 @@ class NetlistWriterVisitor : public NetlistVisitor {
1595
1609
}
1596
1610
}
1597
1611
1598
- return std::make_shared<BlackBoxInst>(type_name, inst_name, params, attrs, input_port_conns, output_port_conns, timing_arcs, ports_tsu, ports_tcq);
1612
+ return std::make_shared<BlackBoxInst>(type_name, inst_name, params, attrs, input_port_conns, output_port_conns, timing_arcs, ports_tsu, ports_thld, ports_tcq);
1599
1613
}
1600
1614
1601
1615
std::shared_ptr<Instance> make_blackbox_instance (const t_pb* atom) {
1602
1616
const auto & top_pb_route = find_top_pb_route (atom);
1603
1617
const t_pb_graph_node* pb_graph_node = atom->pb_graph_node ;
1604
1618
const t_pb_type* pb_type = pb_graph_node->pb_type ;
1605
1619
1620
+ auto & timing_ctx = g_vpr_ctx.timing ();
1606
1621
std::string type_name = pb_type->model ->name ;
1607
1622
std::string inst_name = join_identifier (type_name, atom->name );
1608
1623
std::map<std::string, std::string> params;
1609
1624
std::map<std::string, std::string> attrs;
1610
1625
std::map<std::string, std::vector<std::string>> input_port_conns;
1611
1626
std::map<std::string, std::vector<std::string>> output_port_conns;
1612
1627
std::vector<Arc> timing_arcs;
1613
- std::map<std::string, double > ports_tsu;
1614
- std::map<std::string, double > ports_tcq;
1628
+
1629
+ // Maps to store a sink's port with the corresponding timing edge to that sink
1630
+ // - key : string corresponding to the port's name
1631
+ // - value : pair with the delay and the associated clock pin port name
1632
+ //
1633
+ // tsu : Setup
1634
+ // thld: Hold
1635
+ // tcq : Clock-to-Q
1636
+ std::map<std::string, sequential_port_delay_pair> ports_tsu;
1637
+ std::map<std::string, sequential_port_delay_pair> ports_thld;
1638
+ std::map<std::string, sequential_port_delay_pair> ports_tcq;
1615
1639
1616
1640
// Delay matrix[sink_tnode] -> tuple of source_port_name, pin index, delay
1617
1641
std::map<tatum::NodeId, std::vector<std::tuple<std::string, int , double >>> tnode_delay_matrix;
@@ -1627,6 +1651,7 @@ class NetlistWriterVisitor : public NetlistVisitor {
1627
1651
std::string net;
1628
1652
if (!top_pb_route.count (cluster_pin_idx)) {
1629
1653
// Disconnected
1654
+ net = " " ;
1630
1655
1631
1656
} else {
1632
1657
// Connected
@@ -1635,9 +1660,22 @@ class NetlistWriterVisitor : public NetlistVisitor {
1635
1660
1636
1661
auto src_tnode = find_tnode (atom, cluster_pin_idx);
1637
1662
net = make_inst_wire (atom_net_id, src_tnode, inst_name, PortType::INPUT, iport, ipin);
1663
+ // Delays
1664
+ //
1665
+ // We record the source's sink tnodes and their delays here
1666
+ for (tatum::EdgeId edge : timing_ctx.graph ->node_out_edges (src_tnode)) {
1667
+ double delay = delay_calc_->max_edge_delay (*timing_ctx.graph , edge);
1668
+
1669
+ auto sink_tnode = timing_ctx.graph ->edge_sink_node (edge);
1670
+ tnode_delay_matrix[sink_tnode].emplace_back (port->name , ipin, delay);
1671
+ }
1638
1672
}
1639
1673
1640
1674
input_port_conns[port->name ].push_back (net);
1675
+ if (pin->type == PB_PIN_SEQUENTIAL) {
1676
+ if (!std::isnan (pin->tsu )) ports_tsu[port->name ] = std::make_pair (pin->tsu , pin->associated_clock_pin ->port ->name );
1677
+ if (!std::isnan (pin->thld )) ports_thld[port->name ] = std::make_pair (pin->thld , pin->associated_clock_pin ->port ->name );
1678
+ }
1641
1679
}
1642
1680
}
1643
1681
@@ -1660,9 +1698,17 @@ class NetlistWriterVisitor : public NetlistVisitor {
1660
1698
1661
1699
auto inode = find_tnode (atom, cluster_pin_idx);
1662
1700
net = make_inst_wire (atom_net_id, inode, inst_name, PortType::OUTPUT, iport, ipin);
1701
+ // Record the timing arcs
1702
+ for (auto & data_tuple : tnode_delay_matrix[inode]) {
1703
+ auto src_name = std::get<0 >(data_tuple);
1704
+ auto src_ipin = std::get<1 >(data_tuple);
1705
+ auto delay = std::get<2 >(data_tuple);
1706
+ timing_arcs.emplace_back (src_name, src_ipin, port->name , ipin, delay);
1707
+ }
1663
1708
}
1664
1709
1665
1710
output_port_conns[port->name ].push_back (net);
1711
+ if (pin->type == PB_PIN_SEQUENTIAL && !std::isnan (pin->tco_max )) ports_tcq[port->name ] = std::make_pair (pin->tco_max , pin->associated_clock_pin ->port ->name );
1666
1712
}
1667
1713
}
1668
1714
@@ -1701,7 +1747,7 @@ class NetlistWriterVisitor : public NetlistVisitor {
1701
1747
attrs[attr.first ] = attr.second ;
1702
1748
}
1703
1749
1704
- return std::make_shared<BlackBoxInst>(type_name, inst_name, params, attrs, input_port_conns, output_port_conns, timing_arcs, ports_tsu, ports_tcq);
1750
+ return std::make_shared<BlackBoxInst>(type_name, inst_name, params, attrs, input_port_conns, output_port_conns, timing_arcs, ports_tsu, ports_thld, ports_tcq);
1705
1751
}
1706
1752
1707
1753
// /@brief Returns the top level pb_route associated with the given pb
@@ -2116,7 +2162,7 @@ void print_verilog_port(std::ostream& os, const std::string& port_name, const st
2116
2162
os << " 1'b0" ;
2117
2163
} else {
2118
2164
VTR_ASSERT (type == PortType::OUTPUT);
2119
- os << " " ;
2165
+ os << " DummyOut " ;
2120
2166
}
2121
2167
} else {
2122
2168
// Connected
@@ -2135,7 +2181,7 @@ void print_verilog_port(std::ostream& os, const std::string& port_name, const st
2135
2181
os << " 1'b0" ;
2136
2182
} else {
2137
2183
VTR_ASSERT (type == PortType::OUTPUT);
2138
- os << " " ;
2184
+ os << " DummyOut " ;
2139
2185
}
2140
2186
} else {
2141
2187
// Connected
0 commit comments