Skip to content

Commit 010774b

Browse files
[NetlistWriter] Fixed Tcq SDF Writing for BlackBoxs
The Netlist Writer is used to write the post-implementation netlist and SDF files for use in post-implementation timing analysis. While working with this tool on blocks with multi-port, registered output pins, I found that the SDF file generated was not correct. The issue was that the Netlist Writer always assumed that any registered output ports had only 1 bit, so the SDF file did not contain delays per output port causing it to be invalid. This was easy to fix by making clock to q paths timing arcs instead so that the pin IDs in each port can be passed to the SDF writer and the SDF writer can annotate the correct delays.
1 parent 724ced2 commit 010774b

File tree

1 file changed

+39
-19
lines changed

1 file changed

+39
-19
lines changed

vpr/src/base/netlist_writer.cpp

Lines changed: 39 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -645,7 +645,7 @@ class BlackBoxInst : public Instance {
645645
std::vector<Arc> timing_arcs, ///<Combinational timing arcs
646646
std::map<std::string, sequential_port_delay_pair> ports_tsu, ///<Port setup checks
647647
std::map<std::string, sequential_port_delay_pair> ports_thld, ///<Port hold checks
648-
std::map<std::string, sequential_port_delay_pair> ports_tcq, ///<Port clock-to-q delays
648+
std::vector<Arc> cq_timing_arcs, ///<Port clock-to-q timing arcs
649649
struct t_analysis_opts opts)
650650
: type_name_(type_name)
651651
, inst_name_(inst_name)
@@ -656,7 +656,7 @@ class BlackBoxInst : public Instance {
656656
, timing_arcs_(timing_arcs)
657657
, ports_tsu_(ports_tsu)
658658
, ports_thld_(ports_thld)
659-
, ports_tcq_(ports_tcq)
659+
, cq_timing_arcs_(cq_timing_arcs)
660660
, opts_(opts) {}
661661

662662
void print_blif(std::ostream& os, size_t& unconn_count, int depth = 0) override {
@@ -763,17 +763,17 @@ class BlackBoxInst : public Instance {
763763
}
764764

765765
void print_sdf(std::ostream& os, int depth = 0) override {
766-
if (!timing_arcs_.empty() || !ports_tcq_.empty() || !ports_tsu_.empty() || !ports_thld_.empty()) {
766+
if (!timing_arcs_.empty() || !cq_timing_arcs_.empty() || !ports_tsu_.empty() || !ports_thld_.empty()) {
767767
os << indent(depth) << "(CELL\n";
768768
os << indent(depth + 1) << "(CELLTYPE \"" << type_name_ << "\")\n";
769769
os << indent(depth + 1) << "(INSTANCE " << escape_sdf_identifier(inst_name_) << ")\n";
770770
os << indent(depth + 1) << "(DELAY\n";
771771

772-
if (!timing_arcs_.empty() || !ports_tcq_.empty()) {
772+
if (!timing_arcs_.empty() || !cq_timing_arcs_.empty()) {
773773
os << indent(depth + 2) << "(ABSOLUTE\n";
774774

775775
//Combinational paths
776-
for (const auto& arc : timing_arcs_) {
776+
for (const Arc& arc : timing_arcs_) {
777777
//Note that we explicitly do not escape the last array indexing so an SDF
778778
//reader will treat the ports as multi-bit
779779
//
@@ -794,9 +794,21 @@ class BlackBoxInst : public Instance {
794794
}
795795

796796
//Clock-to-Q delays
797-
for (auto kv : ports_tcq_) {
798-
DelayTriple delay_triple = kv.second.first;
799-
os << indent(depth + 3) << "(IOPATH (posedge " << escape_sdf_identifier(kv.second.second) << ") " << escape_sdf_identifier(kv.first) << " " << delay_triple.str() << " " << delay_triple.str() << ")\n";
797+
for (const Arc& cq_arc : cq_timing_arcs_) {
798+
os << indent(depth + 3) << "(IOPATH (posedge ";
799+
os << escape_sdf_identifier(cq_arc.source_name());
800+
if (find_port_size(cq_arc.source_name()) > 1) {
801+
os << "[" << cq_arc.source_ipin() << "]";
802+
}
803+
os << ") ";
804+
os << escape_sdf_identifier(cq_arc.sink_name());
805+
if (find_port_size(cq_arc.sink_name()) > 1) {
806+
os << "[" << cq_arc.sink_ipin() << "]";
807+
}
808+
os << " ";
809+
os << cq_arc.delay().str();
810+
os << ")\n";
811+
800812
}
801813
os << indent(depth + 2) << ")\n"; //ABSOLUTE
802814
}
@@ -845,7 +857,7 @@ class BlackBoxInst : public Instance {
845857
std::vector<Arc> timing_arcs_;
846858
std::map<std::string, sequential_port_delay_pair> ports_tsu_;
847859
std::map<std::string, sequential_port_delay_pair> ports_thld_;
848-
std::map<std::string, sequential_port_delay_pair> ports_tcq_;
860+
std::vector<Arc> cq_timing_arcs_;
849861
struct t_analysis_opts opts_;
850862
};
851863

@@ -1419,7 +1431,7 @@ class NetlistWriterVisitor : public NetlistVisitor {
14191431
std::vector<Arc> timing_arcs;
14201432
std::map<std::string, sequential_port_delay_pair> ports_tsu;
14211433
std::map<std::string, sequential_port_delay_pair> ports_thld;
1422-
std::map<std::string, sequential_port_delay_pair> ports_tcq;
1434+
std::vector<Arc> cq_timing_arcs;
14231435

14241436
params["ADDR_WIDTH"] = "0";
14251437
params["DATA_WIDTH"] = "0";
@@ -1513,7 +1525,11 @@ class NetlistWriterVisitor : public NetlistVisitor {
15131525
}
15141526
output_port_conns[port_name].push_back(net);
15151527
DelayTriple delay_triple = get_pin_tco_delay_triple(*pin);
1516-
ports_tcq[port_name] = std::make_pair(delay_triple, pin->associated_clock_pin->port->name);
1528+
cq_timing_arcs.emplace_back(pin->associated_clock_pin->port->name,
1529+
pin->associated_clock_pin->pin_number,
1530+
port_name,
1531+
ipin,
1532+
delay_triple);
15171533
}
15181534
}
15191535

@@ -1544,7 +1560,7 @@ class NetlistWriterVisitor : public NetlistVisitor {
15441560
}
15451561
}
15461562

1547-
return std::make_shared<BlackBoxInst>(type, inst_name, params, attrs, input_port_conns, output_port_conns, timing_arcs, ports_tsu, ports_thld, ports_tcq, opts_);
1563+
return std::make_shared<BlackBoxInst>(type, inst_name, params, attrs, input_port_conns, output_port_conns, timing_arcs, ports_tsu, ports_thld, cq_timing_arcs, opts_);
15481564
}
15491565

15501566
///@brief Returns an Instance object representing a Multiplier
@@ -1564,7 +1580,7 @@ class NetlistWriterVisitor : public NetlistVisitor {
15641580
std::vector<Arc> timing_arcs;
15651581
std::map<std::string, sequential_port_delay_pair> ports_tsu;
15661582
std::map<std::string, sequential_port_delay_pair> ports_thld;
1567-
std::map<std::string, sequential_port_delay_pair> ports_tcq;
1583+
std::vector<Arc> cq_timing_arcs;
15681584

15691585
params["WIDTH"] = "0";
15701586

@@ -1639,7 +1655,7 @@ class NetlistWriterVisitor : public NetlistVisitor {
16391655

16401656
VTR_ASSERT(pb_graph_node->num_clock_ports == 0); //No clocks
16411657

1642-
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, opts_);
1658+
return std::make_shared<BlackBoxInst>(type_name, inst_name, params, attrs, input_port_conns, output_port_conns, timing_arcs, ports_tsu, ports_thld, cq_timing_arcs, opts_);
16431659
}
16441660

16451661
///@brief Returns an Instance object representing an Adder
@@ -1659,7 +1675,7 @@ class NetlistWriterVisitor : public NetlistVisitor {
16591675
std::vector<Arc> timing_arcs;
16601676
std::map<std::string, sequential_port_delay_pair> ports_tsu;
16611677
std::map<std::string, sequential_port_delay_pair> ports_thld;
1662-
std::map<std::string, sequential_port_delay_pair> ports_tcq;
1678+
std::vector<Arc> cq_timing_arcs;
16631679

16641680
params["WIDTH"] = "0";
16651681

@@ -1738,7 +1754,7 @@ class NetlistWriterVisitor : public NetlistVisitor {
17381754
}
17391755
}
17401756

1741-
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, opts_);
1757+
return std::make_shared<BlackBoxInst>(type_name, inst_name, params, attrs, input_port_conns, output_port_conns, timing_arcs, ports_tsu, ports_thld, cq_timing_arcs, opts_);
17421758
}
17431759

17441760
std::shared_ptr<Instance> make_blackbox_instance(const t_pb* atom) {
@@ -1764,7 +1780,7 @@ class NetlistWriterVisitor : public NetlistVisitor {
17641780
// tcq : Clock-to-Q
17651781
std::map<std::string, sequential_port_delay_pair> ports_tsu;
17661782
std::map<std::string, sequential_port_delay_pair> ports_thld;
1767-
std::map<std::string, sequential_port_delay_pair> ports_tcq;
1783+
std::vector<Arc> cq_timing_arcs;
17681784

17691785
//Delay matrix[sink_tnode] -> tuple of source_port_name, pin index, delay
17701786
std::map<tatum::NodeId, std::vector<std::tuple<std::string, int, DelayTriple>>> tnode_delay_matrix;
@@ -1844,7 +1860,11 @@ class NetlistWriterVisitor : public NetlistVisitor {
18441860
output_port_conns[port->name].push_back(net);
18451861
if (pin->type == PB_PIN_SEQUENTIAL && !std::isnan(pin->tco_max)) {
18461862
DelayTriple delay_triple = get_pin_tco_delay_triple(*pin);
1847-
ports_tcq[port->name] = std::make_pair(delay_triple, pin->associated_clock_pin->port->name);
1863+
cq_timing_arcs.emplace_back(pin->associated_clock_pin->port->name,
1864+
pin->associated_clock_pin->pin_number,
1865+
port->name,
1866+
ipin,
1867+
delay_triple);
18481868
}
18491869
}
18501870
}
@@ -1884,7 +1904,7 @@ class NetlistWriterVisitor : public NetlistVisitor {
18841904
attrs[attr.first] = attr.second;
18851905
}
18861906

1887-
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, opts_);
1907+
return std::make_shared<BlackBoxInst>(type_name, inst_name, params, attrs, input_port_conns, output_port_conns, timing_arcs, ports_tsu, ports_thld, cq_timing_arcs, opts_);
18881908
}
18891909

18901910
///@brief Returns the top level pb_route associated with the given pb

0 commit comments

Comments
 (0)