Skip to content

Commit 7ff9f73

Browse files
Tarachand Pagaraniacomodi
Tarachand Pagarani
authored andcommitted
add support for writing blackbox timing in sdf
1 parent 469ab56 commit 7ff9f73

File tree

1 file changed

+113
-77
lines changed

1 file changed

+113
-77
lines changed

vpr/src/base/netlist_writer.cpp

Lines changed: 113 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,7 @@ class BlackBoxInst : public Instance {
554554
std::map<std::string, std::vector<std::string>> output_port_conns, ///<Port connections: Dictionary of <port,nets>
555555
std::vector<Arc> timing_arcs, ///<Combinational timing arcs
556556
std::map<std::string, double> ports_tsu, ///<Port setup checks
557+
std::map<std::string, double> ports_thld, ///<Port hold checks
557558
std::map<std::string, double> ports_tcq) ///<Port clock-to-q delays
558559
: type_name_(type_name)
559560
, inst_name_(inst_name)
@@ -563,6 +564,7 @@ class BlackBoxInst : public Instance {
563564
, output_port_conns_(output_port_conns)
564565
, timing_arcs_(timing_arcs)
565566
, ports_tsu_(ports_tsu)
567+
, ports_thld_(ports_thld)
566568
, ports_tcq_(ports_tcq) {}
567569

568570
void print_blif(std::ostream& os, size_t& unconn_count, int depth = 0) override {
@@ -648,75 +650,80 @@ class BlackBoxInst : public Instance {
648650
}
649651

650652
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";
655-
656-
if (!timing_arcs_.empty() || !ports_tcq_.empty()) {
657-
os << indent(depth + 2) << "(ABSOLUTE\n";
658-
659-
//Combinational paths
660-
for (const auto& arc : timing_arcs_) {
661-
double delay_ps = get_delay_ps(arc.delay());
662-
663-
std::stringstream delay_triple;
664-
delay_triple << "(" << delay_ps << ":" << delay_ps << ":" << delay_ps << ")";
665653

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() << "]";
679-
}
680-
os << " ";
681-
os << delay_triple.str();
682-
os << ")\n";
683-
}
684-
685-
//Clock-to-Q delays
686-
for (auto kv : ports_tcq_) {
687-
double clock_to_q_ps = get_delay_ps(kv.second);
688-
689-
std::stringstream delay_triple;
690-
delay_triple << "(" << clock_to_q_ps << ":" << clock_to_q_ps << ":" << clock_to_q_ps << ")";
691-
692-
os << indent(depth + 3) << "(IOPATH (posedge clock) " << escape_sdf_identifier(kv.first) << " " << delay_triple.str() << " " << delay_triple.str() << ")\n";
693-
}
694-
os << indent(depth + 2) << ")\n"; //ABSOLUTE
695-
}
696-
os << indent(depth + 1) << ")\n"; //DELAY
697-
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);
703-
704-
std::stringstream delay_triple;
705-
delay_triple << "(" << setup_ps << ":" << setup_ps << ":" << setup_ps << ")";
706-
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);
711-
712-
std::stringstream delay_triple;
713-
delay_triple << "(" << hold_ps << ":" << hold_ps << ":" << hold_ps << ")";
714-
715-
os << indent(depth + 2) << "(HOLD " << escape_sdf_identifier(kv.first) << " (posedge clock) " << delay_triple.str() << ")\n";
716-
}
717-
os << indent(depth + 1) << ")\n"; //TIMINGCHECK
718-
}
719-
os << indent(depth) << ")\n"; //CELL
654+
655+
if (!timing_arcs_.empty() || !ports_tcq_.empty() || !ports_tsu_.empty() || !ports_thld_.empty()) {
656+
os << indent(depth) << "(CELL\n";
657+
os << indent(depth + 1) << "(CELLTYPE \"" << type_name_ << "\")\n";
658+
os << indent(depth + 1) << "(INSTANCE " << escape_sdf_identifier(inst_name_) << ")\n";
659+
os << indent(depth + 1) << "(DELAY\n";
660+
661+
662+
if (!timing_arcs_.empty() || !ports_tcq_.empty()) {
663+
os << indent(depth + 2) << "(ABSOLUTE\n";
664+
665+
//Combinational paths
666+
for (const auto& arc : timing_arcs_) {
667+
double delay_ps = get_delay_ps(arc.delay());
668+
669+
std::stringstream delay_triple;
670+
delay_triple << "(" << delay_ps << ":" << delay_ps << ":" << delay_ps << ")";
671+
672+
//Note that we explicitly do not escape the last array indexing so an SDF
673+
//reader will treat the ports as multi-bit
674+
//
675+
//We also only put the last index in if the port has multiple bits
676+
os << indent(depth + 3) << "(IOPATH ";
677+
os << escape_sdf_identifier(arc.source_name());
678+
if (find_port_size(arc.source_name()) > 1) {
679+
os << "[" << arc.source_ipin() << "]";
680+
}
681+
os << " ";
682+
os << escape_sdf_identifier(arc.sink_name());
683+
if (find_port_size(arc.sink_name()) > 1) {
684+
os << "[" << arc.sink_ipin() << "]";
685+
}
686+
os << " ";
687+
os << delay_triple.str();
688+
os << ")\n";
689+
}
690+
691+
//Clock-to-Q delays
692+
for (auto kv : ports_tcq_) {
693+
double clock_to_q_ps = get_delay_ps(kv.second);
694+
695+
std::stringstream delay_triple;
696+
delay_triple << "(" << clock_to_q_ps << ":" << clock_to_q_ps << ":" << clock_to_q_ps << ")";
697+
698+
os << indent(depth + 3) << "(IOPATH (posedge clock) " << escape_sdf_identifier(kv.first) << " " << delay_triple.str() << " " << delay_triple.str() << ")\n";
699+
}
700+
os << indent(depth + 2) << ")\n"; //ABSOLUTE
701+
}
702+
os << indent(depth + 1) << ")\n"; //DELAY
703+
704+
if (!ports_tsu_.empty() || !ports_thld_.empty()) {
705+
//Setup checks
706+
os << indent(depth + 1) << "(TIMINGCHECK\n";
707+
for (auto kv : ports_tsu_) {
708+
double setup_ps = get_delay_ps(kv.second);
709+
710+
std::stringstream delay_triple;
711+
delay_triple << "(" << setup_ps << ":" << setup_ps << ":" << setup_ps << ")";
712+
713+
os << indent(depth + 2) << "(SETUP " << escape_sdf_identifier(kv.first) << " (posedge clock) " << delay_triple.str() << ")\n";
714+
}
715+
for (auto kv : ports_thld_) {
716+
double hold_ps = get_delay_ps(kv.second);
717+
718+
std::stringstream delay_triple;
719+
delay_triple << "(" << hold_ps << ":" << hold_ps << ":" << hold_ps << ")";
720+
721+
os << indent(depth + 2) << "(HOLD " << escape_sdf_identifier(kv.first) << " (posedge clock) " << delay_triple.str() << ")\n";
722+
}
723+
os << indent(depth + 1) << ")\n"; //TIMINGCHECK
724+
}
725+
os << indent(depth) << ")\n"; //CELL
726+
}
720727
}
721728

722729
size_t find_port_size(std::string port_name) {
@@ -1278,6 +1285,7 @@ class NetlistWriterVisitor : public NetlistVisitor {
12781285
std::map<std::string, std::vector<std::string>> output_port_conns;
12791286
std::vector<Arc> timing_arcs;
12801287
std::map<std::string, double> ports_tsu;
1288+
std::map<std::string, double> ports_thld;
12811289
std::map<std::string, double> ports_tcq;
12821290

12831291
params["ADDR_WIDTH"] = "0";
@@ -1401,7 +1409,7 @@ class NetlistWriterVisitor : public NetlistVisitor {
14011409
}
14021410
}
14031411

1404-
return std::make_shared<BlackBoxInst>(type, inst_name, params, attrs, input_port_conns, output_port_conns, timing_arcs, ports_tsu, ports_tcq);
1412+
return std::make_shared<BlackBoxInst>(type, inst_name, params, attrs, input_port_conns, output_port_conns, timing_arcs, ports_tsu, ports_thld, ports_tcq);
14051413
}
14061414

14071415
///@brief Returns an Instance object representing a Multiplier
@@ -1420,6 +1428,7 @@ class NetlistWriterVisitor : public NetlistVisitor {
14201428
std::map<std::string, std::vector<std::string>> output_port_conns;
14211429
std::vector<Arc> timing_arcs;
14221430
std::map<std::string, double> ports_tsu;
1431+
std::map<std::string, double> ports_thld;
14231432
std::map<std::string, double> ports_tcq;
14241433

14251434
params["WIDTH"] = "0";
@@ -1496,7 +1505,7 @@ class NetlistWriterVisitor : public NetlistVisitor {
14961505

14971506
VTR_ASSERT(pb_graph_node->num_clock_ports == 0); //No clocks
14981507

1499-
return std::make_shared<BlackBoxInst>(type_name, inst_name, params, attrs, input_port_conns, output_port_conns, timing_arcs, ports_tsu, ports_tcq);
1508+
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);
15001509
}
15011510

15021511
///@brief Returns an Instance object representing an Adder
@@ -1515,6 +1524,7 @@ class NetlistWriterVisitor : public NetlistVisitor {
15151524
std::map<std::string, std::vector<std::string>> output_port_conns;
15161525
std::vector<Arc> timing_arcs;
15171526
std::map<std::string, double> ports_tsu;
1527+
std::map<std::string, double> ports_thld;
15181528
std::map<std::string, double> ports_tcq;
15191529

15201530
params["WIDTH"] = "0";
@@ -1595,14 +1605,15 @@ class NetlistWriterVisitor : public NetlistVisitor {
15951605
}
15961606
}
15971607

1598-
return std::make_shared<BlackBoxInst>(type_name, inst_name, params, attrs, input_port_conns, output_port_conns, timing_arcs, ports_tsu, ports_tcq);
1608+
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);
15991609
}
16001610

16011611
std::shared_ptr<Instance> make_blackbox_instance(const t_pb* atom) {
16021612
const auto& top_pb_route = find_top_pb_route(atom);
16031613
const t_pb_graph_node* pb_graph_node = atom->pb_graph_node;
16041614
const t_pb_type* pb_type = pb_graph_node->pb_type;
16051615

1616+
auto& timing_ctx = g_vpr_ctx.timing();
16061617
std::string type_name = pb_type->model->name;
16071618
std::string inst_name = join_identifier(type_name, atom->name);
16081619
std::map<std::string, std::string> params;
@@ -1611,6 +1622,7 @@ class NetlistWriterVisitor : public NetlistVisitor {
16111622
std::map<std::string, std::vector<std::string>> output_port_conns;
16121623
std::vector<Arc> timing_arcs;
16131624
std::map<std::string, double> ports_tsu;
1625+
std::map<std::string, double> ports_thld;
16141626
std::map<std::string, double> ports_tcq;
16151627

16161628
//Delay matrix[sink_tnode] -> tuple of source_port_name, pin index, delay
@@ -1627,6 +1639,7 @@ class NetlistWriterVisitor : public NetlistVisitor {
16271639
std::string net;
16281640
if (!top_pb_route.count(cluster_pin_idx)) {
16291641
//Disconnected
1642+
net = "";
16301643

16311644
} else {
16321645
//Connected
@@ -1635,13 +1648,27 @@ class NetlistWriterVisitor : public NetlistVisitor {
16351648

16361649
auto src_tnode = find_tnode(atom, cluster_pin_idx);
16371650
net = make_inst_wire(atom_net_id, src_tnode, inst_name, PortType::INPUT, iport, ipin);
1651+
//Delays
1652+
//
1653+
//We record the souce sink tnodes and thier delays here
1654+
for (tatum::EdgeId edge : timing_ctx.graph->node_out_edges(src_tnode)) {
1655+
double delay = delay_calc_->max_edge_delay(*timing_ctx.graph, edge);
1656+
1657+
auto sink_tnode = timing_ctx.graph->edge_sink_node(edge);
1658+
tnode_delay_matrix[sink_tnode].emplace_back(port->name, ipin, delay);
1659+
}
16381660
}
16391661

1640-
input_port_conns[port->name].push_back(net);
1641-
}
1642-
}
16431662

1644-
//Process the output ports
1663+
input_port_conns[port->name].push_back(net);
1664+
if (pin->type == PB_PIN_SEQUENTIAL) {
1665+
if (!std::isnan(pin->tsu)) ports_tsu[port->name] = pin->tsu;
1666+
if (!std::isnan(pin->thld)) ports_thld[port->name] = pin->thld;
1667+
}
1668+
}
1669+
}
1670+
1671+
//Process the output ports
16451672
for (int iport = 0; iport < pb_graph_node->num_output_ports; ++iport) {
16461673
for (int ipin = 0; ipin < pb_graph_node->num_output_pins[iport]; ++ipin) {
16471674
const t_pb_graph_pin* pin = &pb_graph_node->output_pins[iport][ipin];
@@ -1651,7 +1678,7 @@ class NetlistWriterVisitor : public NetlistVisitor {
16511678

16521679
std::string net;
16531680
if (!top_pb_route.count(cluster_pin_idx)) {
1654-
//Disconnected
1681+
//Disconnected
16551682
net = "";
16561683
} else {
16571684
//Connected
@@ -1660,9 +1687,18 @@ class NetlistWriterVisitor : public NetlistVisitor {
16601687

16611688
auto inode = find_tnode(atom, cluster_pin_idx);
16621689
net = make_inst_wire(atom_net_id, inode, inst_name, PortType::OUTPUT, iport, ipin);
1690+
//Record the timing arcs
1691+
for (auto& data_tuple : tnode_delay_matrix[inode]) {
1692+
auto src_name = std::get<0>(data_tuple);
1693+
auto src_ipin = std::get<1>(data_tuple);
1694+
auto delay = std::get<2>(data_tuple);
1695+
timing_arcs.emplace_back(src_name, src_ipin, port->name, ipin, delay);
1696+
}
16631697
}
16641698

1699+
16651700
output_port_conns[port->name].push_back(net);
1701+
if (pin->type == PB_PIN_SEQUENTIAL && !std::isnan(pin->tco_max)) ports_tcq[port->name] = pin->tco_max;
16661702
}
16671703
}
16681704

@@ -1701,7 +1737,7 @@ class NetlistWriterVisitor : public NetlistVisitor {
17011737
attrs[attr.first] = attr.second;
17021738
}
17031739

1704-
return std::make_shared<BlackBoxInst>(type_name, inst_name, params, attrs, input_port_conns, output_port_conns, timing_arcs, ports_tsu, ports_tcq);
1740+
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);
17051741
}
17061742

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

0 commit comments

Comments
 (0)