Sta latest 0618#372
Conversation
Signed-off-by: James Cherry <cherry@CerezoBook.local>
Signed-off-by: James Cherry <cherry@CerezoBook.local>
Signed-off-by: James Cherry <cherry@CerezoBook.local>
Signed-off-by: James Cherry <cherry@CerezoBook.local>
|
James Cherry seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account. You have signed the CLA already but the status is still pending? Let us recheck it. |
There was a problem hiding this comment.
Code Review
This pull request introduces support for bidirectional port paths and input delay reference pin edges by creating virtual edges in the timing graph. While these changes improve timing analysis accuracy, several critical issues were identified during the review. First, there are potential null pointer dereferences in Graph::makeInstDrvrWireEdges and Sdc::ensureInputDelayRefPinEdges if the lookup for pin vertices returns null. Second, the virtual edges created for input delay reference pins are never cleaned up when SDC constraints are cleared or re-read, which can lead to memory leaks and performance degradation. Implementing a helper method to delete these virtual edges during cleanup is highly recommended.
| if (network_->isTopInstance(inst) | ||
| && network_->direction(pin)->isBidirect()) { | ||
| Vertex *bidir_load, *bidir_drvr; | ||
| pinVertices(pin, bidir_load, bidir_drvr); | ||
| Edge *edge = makeEdge(bidir_load, bidir_drvr, TimingArcSet::wireTimingArcSet()); | ||
| edge->setIsBidirectPortPath(true); | ||
| } |
There was a problem hiding this comment.
Potential null pointer dereference. If bidir_load or bidir_drvr is null (for example, if the pin is a power or ground pin, or if the vertices were not created), calling makeEdge will dereference a null pointer when calling id(from) or id(to). A null check should be added before creating the edge.
if (network_->isTopInstance(inst)
&& network_->direction(pin)->isBidirect()) {
Vertex *bidir_load, *bidir_drvr;
pinVertices(pin, bidir_load, bidir_drvr);
if (bidir_load && bidir_drvr) {
Edge *edge = makeEdge(bidir_load, bidir_drvr, TimingArcSet::wireTimingArcSet());
edge->setIsBidirectPortPath(true);
}
}| Sdc::ensureInputDelayRefPinEdges() | ||
| { | ||
| if (have_input_delay_ref_pins_) { | ||
| for (InputDelay *input_delay : input_delays_) { | ||
| const Pin *ref_pin = input_delay->refPin(); | ||
| if (ref_pin | ||
| && !input_delay->refPinEdgesExist()) { | ||
| Vertex *ref_pin_vertex = graph_->pinLoadVertex(ref_pin); | ||
| for (const Pin *pin : input_delay->leafPins()) { | ||
| Vertex *input_vertex = graph_->pinDrvrVertex(pin); | ||
| graph_->makeEdge(ref_pin_vertex, input_vertex, | ||
| TimingArcSet::portRefPinTimingArcSet()); | ||
| } | ||
| input_delay->setRefPinEdgesExist(true); | ||
| } | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
Potential null pointer dereference. If ref_pin_vertex or input_vertex is null (for example, if the pin is a power or ground pin, or if the vertices were not created), calling makeEdge will dereference a null pointer. Null checks should be added before creating the edge.
void
Sdc::ensureInputDelayRefPinEdges()
{
if (have_input_delay_ref_pins_) {
for (InputDelay *input_delay : input_delays_) {
const Pin *ref_pin = input_delay->refPin();
if (ref_pin
&& !input_delay->refPinEdgesExist()) {
Vertex *ref_pin_vertex = graph_->pinLoadVertex(ref_pin);
if (ref_pin_vertex) {
for (const Pin *pin : input_delay->leafPins()) {
Vertex *input_vertex = graph_->pinDrvrVertex(pin);
if (input_vertex) {
graph_->makeEdge(ref_pin_vertex, input_vertex,
TimingArcSet::portRefPinTimingArcSet());
}
}
}
input_delay->setRefPinEdgesExist(true);
}
}
}
}| @@ -287,12 +285,10 @@ Sdc::deleteConstraints() | |||
| deleteContents(input_delays_); | |||
There was a problem hiding this comment.
When SDC constraints are cleared or re-read, the virtual edges created for input delay reference pins (TimingRole::portDelayRefPin()) are not removed from the graph. This causes virtual edges to accumulate in the graph across multiple SDC reads, leading to memory leaks and performance degradation. We should clean up these virtual edges when the input delays are deleted.
deleteInputDelayRefPinEdges();
deleteContents(input_delays_);| } | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
Implement the helper method to clean up virtual edges created for input delay reference pins.
}
void
Sdc::deleteInputDelayRefPinEdges()
{
if (have_input_delay_ref_pins_) {
for (InputDelay *input_delay : input_delays_) {
const Pin *ref_pin = input_delay->refPin();
if (ref_pin && input_delay->refPinEdgesExist()) {
Vertex *ref_pin_vertex = graph_->pinLoadVertex(ref_pin);
if (ref_pin_vertex) {
for (const Pin *pin : input_delay->leafPins()) {
Vertex *input_vertex = graph_->pinDrvrVertex(pin);
if (input_vertex) {
VertexOutEdgeIterator edge_iter(ref_pin_vertex, graph_);
while (edge_iter.hasNext()) {
Edge *edge = edge_iter.next();
if (edge->to(graph_) == input_vertex
&& edge->role() == TimingRole::portDelayRefPin()) {
graph_->deleteEdge(edge);
break;
}
}
}
}
}
}
}
}
}| InputDelay *except); | ||
| void deleteInputDelaysReferencing(const Clock *clk); | ||
| void deleteInputDelay(InputDelay *input_delay); | ||
|
|
Update from latest codes in Parallaxsw/OpenSTA