set_min/max_delay -from reg/D startpoint warning resolves #265

Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
James Cherry 2025-07-03 17:08:44 -07:00
parent 1c09954518
commit 606c666180
9 changed files with 75 additions and 67 deletions

View File

@ -489,7 +489,6 @@ public:
// timing arcs.
bool hasInferedRegTimingArcs() const { return has_infered_reg_timing_arcs_; }
TestCell *testCell() const { return test_cell_; }
bool isLatchData(LibertyPort *port);
void latchEnable(const TimingArcSet *arc_set,
// Return values.
const LibertyPort *&enable_port,
@ -803,6 +802,10 @@ public:
// Has register/latch rise/fall edges from pin.
bool isRegClk() const { return is_reg_clk_; }
void setIsRegClk(bool is_clk);
bool isRegOutput() const { return is_reg_output_; }
void setIsRegOutput(bool is_reg_out);
bool isLatchData() const { return is_latch_data_; }
void setIsLatchData(bool is_latch_data);
// Is the clock for timing checks.
bool isCheckClk() const { return is_check_clk_; }
void setIsCheckClk(bool is_clk);
@ -899,6 +902,8 @@ protected:
bool min_period_exists_:1;
bool is_clk_:1;
bool is_reg_clk_:1;
bool is_reg_output_:1;
bool is_latch_data_: 1;
bool is_check_clk_:1;
bool is_clk_gate_clk_:1;
bool is_clk_gate_enable_:1;

View File

@ -771,6 +771,7 @@ public:
ClockSet *from_clks,
InstanceSet *from_insts,
const RiseFallBoth *from_rf);
bool isExceptionStartpoint(const Pin *pin) const;
// Make an exception -through specification.
ExceptionThru *makeExceptionThru(PinSet *pins,
NetSet *nets,
@ -972,10 +973,11 @@ public:
ExceptionStateSet *&states) const;
// Return hierarchical -thru exceptions that start between
// from_pin and to_pin.
ExceptionStateSet *exceptionThruStates(const Pin *from_pin,
void exceptionThruStates(const Pin *from_pin,
const Pin *to_pin,
const RiseFall *to_rf,
const MinMax *min_max) const;
const MinMax *min_max,
ExceptionStateSet *&states) const;
// Find the highest priority exception with first exception pt at
// pin/clk end.
void exceptionTo(ExceptionPathType type,

View File

@ -531,7 +531,6 @@ public:
void checkExceptionFromPins(ExceptionFrom *from,
const char *file,
int line) const;
bool exceptionFromInvalid(const Pin *pin) const;
void deleteExceptionFrom(ExceptionFrom *from);
// Make an exception -through specification.
ExceptionThru *makeExceptionThru(PinSet *pins,

View File

@ -1244,10 +1244,13 @@ LibertyCell::addTimingArcSet(TimingArcSet *arc_set)
timing_arc_sets_.push_back(arc_set);
LibertyPort *from = arc_set->from();
LibertyPort *to = arc_set->to();
const TimingRole *role = arc_set->role();
if (role == TimingRole::regClkToQ()
|| role == TimingRole::latchEnToQ())
|| role == TimingRole::latchEnToQ()) {
from->setIsRegClk(true);
to->setIsRegOutput(true);
}
if (role->isTimingCheck())
from->setIsCheckClk(true);
return set_index;
@ -1881,7 +1884,7 @@ LibertyCell::makeLatchEnable(LibertyPort *d,
latch_enables_.push_back(latch_enable);
latch_d_to_q_map_[d_to_q] = latch_enable;
latch_check_map_[setup_check] = latch_enable;
latch_data_ports_.insert(d);
d->setIsLatchData(true);
debugPrint(debug, "liberty_latch", 1,
"latch %s -> %s | %s %s -> %s | %s %s -> %s setup",
d->name(),
@ -1933,12 +1936,6 @@ LibertyCell::inferLatchRoles(Report *report,
}
}
bool
LibertyCell::isLatchData(LibertyPort *port)
{
return latch_data_ports_.hasKey(port);
}
void
LibertyCell::latchEnable(const TimingArcSet *d_to_q_set,
// Return values.
@ -2100,6 +2097,8 @@ LibertyPort::LibertyPort(LibertyCell *cell,
min_period_exists_(false),
is_clk_(false),
is_reg_clk_(false),
is_reg_output_(false),
is_latch_data_(false),
is_check_clk_(false),
is_clk_gate_clk_(false),
is_clk_gate_enable_(false),
@ -2547,6 +2546,18 @@ LibertyPort::setIsRegClk(bool is_clk)
is_reg_clk_ = is_clk;
}
void
LibertyPort::setIsRegOutput(bool is_reg_out)
{
is_reg_output_ = is_reg_out;
}
void
LibertyPort::setIsLatchData(bool is_latch_data)
{
is_latch_data_ = is_latch_data;
}
void
LibertyPort::setIsCheckClk(bool is_clk)
{

View File

@ -655,7 +655,7 @@ Network::isLatchData(const Pin *pin) const
{
LibertyPort *port = libertyPort(pin);
if (port)
return port->libertyCell()->isLatchData(port);
return port->isLatchData();
else
return false;
}

View File

@ -3914,8 +3914,7 @@ Sdc::recordPathDelayInternalFrom(ExceptionPath *exception)
if (from
&& from->hasPins()) {
for (const Pin *pin : *from->pins()) {
if (!(network_->isRegClkPin(pin)
|| network_->isTopLevelPort(pin))) {
if (!isExceptionStartpoint(pin)) {
path_delay_internal_from_.insert(pin);
if (exception->breakPath())
path_delay_internal_from_break_.insert(pin);
@ -3932,8 +3931,7 @@ Sdc::unrecordPathDelayInternalFrom(ExceptionPath *exception)
&& from->hasPins()
&& !path_delay_internal_from_.empty()) {
for (const Pin *pin : *from->pins()) {
if (!(network_->isRegClkPin(pin)
|| network_->isTopLevelPort(pin))
if (!isExceptionStartpoint(pin)
&& !pathDelayFrom(pin)) {
path_delay_internal_from_.erase(pin);
if (exception->breakPath())
@ -3943,6 +3941,21 @@ Sdc::unrecordPathDelayInternalFrom(ExceptionPath *exception)
}
}
bool
Sdc::isExceptionStartpoint(const Pin *pin) const
{
Net *net = network_->net(pin);
const LibertyPort *port = network_->libertyPort(pin);
return ((network_->isTopLevelPort(pin)
&& network_->direction(pin)->isAnyInput())
|| (port && port->isRegClk())
|| (port && port->isLatchData()))
// Pins connected to power/ground are invalid.
&& !(net
&& (network_->isPower(net)
|| network_->isGround(net)));
}
bool
Sdc::pathDelayFrom(const Pin *pin)
{
@ -5304,13 +5317,13 @@ Sdc::filterRegQStates(const Pin *to_pin,
}
}
ExceptionStateSet *
void
Sdc::exceptionThruStates(const Pin *from_pin,
const Pin *to_pin,
const RiseFall *to_rf,
const MinMax *min_max) const
const MinMax *min_max,
ExceptionStateSet *&states) const
{
ExceptionStateSet *states = nullptr;
exceptionThruStates(first_thru_pin_exceptions_.findKey(to_pin),
to_rf, min_max, states);
if (!first_thru_edge_exceptions_.empty()) {
@ -5325,7 +5338,6 @@ Sdc::exceptionThruStates(const Pin *from_pin,
exceptionThruStates(first_thru_inst_exceptions_.findKey(to_inst),
to_rf, min_max, states);
}
return states;
}
void

View File

@ -2355,6 +2355,7 @@ proc set_path_delay { cmd args min_max } {
set from [parse_from_arg keys arg_error]
set thrus [parse_thrus_arg args arg_error]
set to [parse_to_arg keys flags arg_error]
check_exception_pins $from $to
if { $arg_error } {
delete_from_thrus_to $from $thrus $to
} else {

View File

@ -980,12 +980,10 @@ Search::visitStartpoints(VertexVisitor *visitor)
visitor->visit(vertex);
const PinSet &startpoints = sdc_->pathDelayInternalFrom();
if (!startpoints.empty()) {
for (const Pin *pin : startpoints) {
Vertex *vertex = graph_->pinDrvrVertex(pin);
visitor->visit(vertex);
}
}
}
void
@ -2176,7 +2174,6 @@ PathVisitor::visitFromPath(const Pin *from_pin,
to_tag = search_->thruClkTag(from_path, from_vertex, from_tag, true,
edge, to_rf, arc_delay_min_max_eq,
min_max, path_ap);
if (to_tag)
to_arrival = from_arrival + arc_delay;
}
}
@ -2272,11 +2269,10 @@ PathVisitor::visitFromPath(const Pin *from_pin,
else {
if (!(sdc_->isPathDelayInternalFromBreak(to_pin)
|| sdc_->isPathDelayInternalToBreak(from_pin))) {
arc_delay = search_->deratedDelay(from_vertex, arc, edge, false, path_ap);
if (!delayInf(arc_delay)) {
to_arrival = from_arrival + arc_delay;
to_tag = search_->thruTag(from_tag, edge, to_rf, min_max, path_ap);
}
arc_delay = search_->deratedDelay(from_vertex, arc, edge, false, path_ap);
if (!delayInf(arc_delay))
to_arrival = from_arrival + arc_delay;
}
}
if (to_tag)
@ -2643,7 +2639,7 @@ Search::mutateTag(Tag *from_tag,
// Kill path delay tags past the -to pin.
if ((exception->isPathDelay()
&& sdc_->isCompleteTo(state, from_pin, from_rf, min_max))
&& sdc_->isCompleteTo(state, to_pin, to_rf, min_max))
// Kill loop tags at register clock pins.
|| (exception->isLoop()
&& to_is_reg_clk)) {
@ -2653,7 +2649,7 @@ Search::mutateTag(Tag *from_tag,
}
// Get the set of -thru exceptions starting at to_pin/edge.
new_states = sdc_->exceptionThruStates(from_pin, to_pin, to_rf, min_max);
sdc_->exceptionThruStates(from_pin, to_pin, to_rf, min_max, new_states);
if (new_states || state_change) {
// Second pass to apply state changes and add updated existing
// states to new states.
@ -2691,7 +2687,7 @@ Search::mutateTag(Tag *from_tag,
}
else
// Get the set of -thru exceptions starting at to_pin/edge.
new_states = sdc_->exceptionThruStates(from_pin, to_pin, to_rf, min_max);
sdc_->exceptionThruStates(from_pin, to_pin, to_rf, min_max, new_states);
if (new_states)
return findTag(to_rf, path_ap, to_clk_info, to_is_clk,

View File

@ -2027,7 +2027,7 @@ Sta::checkExceptionFromPins(ExceptionFrom *from,
PinSet::ConstIterator pin_iter(from->pins());
while (pin_iter.hasNext()) {
const Pin *pin = pin_iter.next();
if (exceptionFromInvalid(pin)) {
if (!sdc_->isExceptionStartpoint(pin)) {
if (line)
report_->fileWarn(1554, file, line, "'%s' is not a valid start point.",
cmd_network_->pathName(pin));
@ -2039,24 +2039,6 @@ Sta::checkExceptionFromPins(ExceptionFrom *from,
}
}
bool
Sta::exceptionFromInvalid(const Pin *pin) const
{
Net *net = network_->net(pin);
// Floating pins are invalid.
return (net == nullptr
&& !network_->isTopLevelPort(pin))
|| (net
// Pins connected to power/ground are invalid.
&& (network_->isPower(net)
|| network_->isGround(net)))
|| !((network_->isTopLevelPort(pin)
&& network_->direction(pin)->isAnyInput())
|| network_->isRegClkPin(pin)
|| network_->isLatchData(pin)
|| network_->direction(pin)->isInternal());
}
void
Sta::deleteExceptionFrom(ExceptionFrom *from)
{