Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 86 additions & 10 deletions liberty/LibertyReader.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2031,6 +2031,20 @@ LibertyReader::endCell(LibertyGroup *group)
void
LibertyReader::finishPortGroups()
{
// Populate bit_overrides_ with the timing groups of each port.
bit_overrides_.clear();
for (PortGroup *port_group : cell_port_groups_) {
if (port_group->timingGroups().empty())
continue;
for (LibertyPort *port : *port_group->ports()) {
// Map port to timing groups in it.
std::vector<TimingGroup*> &timingGroups = bit_overrides_[port];
for (TimingGroup *timing : port_group->timingGroups())
timingGroups.push_back(timing);
}
}

// Make timing arcs for each port group.
for (PortGroup *port_group : cell_port_groups_) {
int line = port_group->line();
for (LibertyPort *port : *port_group->ports()) {
Expand All @@ -2039,8 +2053,10 @@ LibertyReader::finishPortGroups()
}
makeTimingArcs(port_group);
makeInternalPowers(port_group);
delete port_group;
}
// Defer deletion until after the loop so overrides can safely walk.
for (PortGroup *port_group : cell_port_groups_)
delete port_group;
cell_port_groups_.clear();
Comment on lines +2057 to 2060
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Dangling pointers remain in bit_overrides_ after deletion loop

After the port-group deletion loop completes, bit_overrides_ still holds TimingGroup* pointers that now point to freed memory. The next call to finishPortGroups() clears the map before any use, so this is currently safe, but any subclass or future code that calls hasBitPinTimingOverride() between the end of finishPortGroups() and the next cell's finishPortGroups() would trigger undefined behaviour. A simple bit_overrides_.clear() immediately after the deletion loop makes the lifetime unambiguous.

}

Expand Down Expand Up @@ -2520,6 +2536,59 @@ TimingGroup::makeTableModels(LibertyCell *cell,
}
}

bool
LibertyReader::relatedPinIncludesPort(TimingGroup *t,
LibertyPort *from_port,
int line)
{
if (t->relatedPortNames() == nullptr) // no related pin
return false;
// Check every related port name for a matching port.
for (const char *related_pin : *t->relatedPortNames()) {
PortNameBitIterator it(cell_, related_pin, this, line);
while (it.hasNext()) {
if (it.next() == from_port)
return true;
}
}
return false;
}

bool
LibertyReader::sameArcIdentity(TimingGroup *pin_t,
TimingGroup *bus_timing,
LibertyPort *from_port)
{
// Check that the timing types are the same.
if (pin_t->attrs()->timingType() == bus_timing->attrs()->timingType()) {
// Check that the conditions are equivalent.
if (FuncExpr::equiv(pin_t->attrs()->cond(), bus_timing->attrs()->cond())) {
// Check that the related pins are the same.
if (from_port == nullptr && pin_t->relatedPortNames() == nullptr) {
return true;
}
return relatedPinIncludesPort(pin_t, from_port, bus_timing->line());
}
}
return false;
}

bool
LibertyReader::hasBitPinTimingOverride(LibertyPort *to_port_bit,
LibertyPort *from_port,
TimingGroup *bus_timing)
{
// Look for destination port bit in overrides map.
auto it = bit_overrides_.find(to_port_bit);
if (it == bit_overrides_.end())
return false;
// Check every timing group for the port in the overrides map.
for (TimingGroup *pin_t : it->second)
if (sameArcIdentity(pin_t, bus_timing, from_port))
return true;
return false;
}

void
LibertyReader::makeTimingArcs(const char *from_port_name,
PortNameBitIterator &from_port_iter,
Expand Down Expand Up @@ -2555,9 +2624,12 @@ LibertyReader::makeTimingArcs(const char *from_port_name,
libWarn(1214, timing->line(), "timing group from output port.");
LibertyPortMemberIterator bit_iter(to_port);
while (bit_iter.hasNext()) {
LibertyPort *to_port_bit = bit_iter.next();
builder_.makeTimingArcs(cell_, from_port, to_port_bit, related_out_port,
timing->attrs(), timing->line());
LibertyPort *to_port_bit = bit_iter.next();
// Skip bits whose pin(<bit>) block declares a matching timing arc
if (!hasBitPinTimingOverride(to_port_bit, from_port, timing))
builder_.makeTimingArcs(cell_, from_port, to_port_bit,
related_out_port,
timing->attrs(), timing->line());
}
}
}
Expand Down Expand Up @@ -2588,9 +2660,11 @@ LibertyReader::makeTimingArcs(const char *from_port_name,
LibertyPort *to_port_bit = to_port_iter.next();
if (from_port_bit->direction()->isOutput())
libWarn(1215, timing->line(), "timing group from output port.");
builder_.makeTimingArcs(cell_, from_port_bit, to_port_bit,
related_out_port, timing->attrs(),
timing->line());
// Skip bits whose pin(<bit>) block declares a matching timing arc.
if (!hasBitPinTimingOverride(to_port_bit, from_port_bit, timing))
builder_.makeTimingArcs(cell_, from_port_bit, to_port_bit,
related_out_port, timing->attrs(),
timing->line());
}
}
else {
Expand All @@ -2601,9 +2675,11 @@ LibertyReader::makeTimingArcs(const char *from_port_name,
LibertyPortMemberIterator to_iter(to_port);
while (to_iter.hasNext()) {
LibertyPort *to_port_bit = to_iter.next();
builder_.makeTimingArcs(cell_, from_port_bit, to_port_bit,
related_out_port, timing->attrs(),
timing->line());
// Skip bits whose pin(<bit>) block declares a matching timing arc.
if (!hasBitPinTimingOverride(to_port_bit, from_port_bit, timing))
builder_.makeTimingArcs(cell_, from_port_bit, to_port_bit,
related_out_port, timing->attrs(),
timing->line());
}
}
}
Expand Down
12 changes: 12 additions & 0 deletions liberty/LibertyReaderPvt.hh
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,18 @@ public:
virtual void makeTimingArcs(LibertyPort *to_port,
LibertyPort *related_out_port,
TimingGroup *timing);

// Helper functions for makeTimingArcs()
std::unordered_map<LibertyPort*, std::vector<TimingGroup*>> bit_overrides_;
bool relatedPinIncludesPort(TimingGroup *t,
LibertyPort *from_port,
int line);
bool sameArcIdentity(TimingGroup *pin_t,
TimingGroup *bus_timing,
LibertyPort *from_port);
bool hasBitPinTimingOverride(LibertyPort *to_port_bit,
LibertyPort *from_port,
TimingGroup *bus_timing);
Comment thread
akashlevy marked this conversation as resolved.

virtual void visitClockGatingIntegratedCell(LibertyAttr *attr);
virtual void visitArea(LibertyAttr *attr);
Expand Down
Loading