set_clock_sense -> set_sense, LibertyPort::driveResistance

This commit is contained in:
James Cherry 2019-06-23 19:52:29 -07:00
parent b9a7b349eb
commit 12494398e9
9 changed files with 116 additions and 72 deletions

Binary file not shown.

View File

@ -43,13 +43,25 @@ hashPort(const LibertyPort *port);
static unsigned
hashString(const char *str);
class CellDriveResistanceLess
static float
cellDriveResistance(const LibertyCell *cell)
{
LibertyCellPortBitIterator port_iter(cell);
while (port_iter.hasNext()) {
auto port = port_iter.next();
if (port->direction()->isOutput())
return port->driveResistance();
}
return 0.0;
}
class CellDriveResistanceGreater
{
public:
bool operator()(const LibertyCell *cell1,
const LibertyCell *cell2) const
{
return cell1->driveResistance() > cell2->driveResistance();
return cellDriveResistance(cell1) > cellDriveResistance(cell2);
}
};
@ -62,7 +74,7 @@ EquivCells::EquivCells(LibertyLibrarySeq *equiv_libs,
// Sort the equiv sets by drive resistance.
for (auto cell : unique_equiv_cells_) {
auto equivs = equiv_cells_.findKey(cell);
sort(equivs, CellDriveResistanceLess());
sort(equivs, CellDriveResistanceGreater());
}
if (map_libs) {
for (auto lib : *map_libs)

View File

@ -1440,42 +1440,6 @@ LibertyCell::setCornerCell(LibertyCell *corner_cell,
////////////////////////////////////////////////////////////////
// Use the min/max "drive" for all the timing arcs in the cell.
float
LibertyCell::driveResistance(const TransRiseFall *tr,
const MinMax *min_max) const
{
float max_drive = min_max->initValue();
LibertyCellTimingArcSetIterator set_iter(this);
while (set_iter.hasNext()) {
TimingArcSet *set = set_iter.next();
if (!set->role()->isTimingCheck()) {
TimingArcSetArcIterator arc_iter(set);
while (arc_iter.hasNext()) {
TimingArc *arc = arc_iter.next();
if (tr == nullptr
|| arc->toTrans()->asRiseFall() == tr) {
GateTimingModel *model = dynamic_cast<GateTimingModel*>(arc->model());
if (model) {
float drive = model->driveResistance(this, nullptr);
if (min_max->compare(drive, max_drive))
max_drive = drive;
}
}
}
}
}
return max_drive;
}
float
LibertyCell::driveResistance() const
{
return driveResistance(nullptr, MinMax::max());
}
////////////////////////////////////////////////////////////////
float
LibertyCell::ocvArcDepth() const
{
@ -1953,6 +1917,47 @@ LibertyPort::capacitanceIsOneValue() const
return capacitance_.isOneValue();
}
////////////////////////////////////////////////////////////////
// Use the min/max "drive" for all the timing arcs in the cell.
float
LibertyPort::driveResistance(const TransRiseFall *tr,
const MinMax *min_max) const
{
float max_drive = min_max->initValue();
bool found_drive = false;
LibertyCellTimingArcSetIterator set_iter(liberty_cell_, nullptr, this);
while (set_iter.hasNext()) {
TimingArcSet *set = set_iter.next();
if (!set->role()->isTimingCheck()) {
TimingArcSetArcIterator arc_iter(set);
while (arc_iter.hasNext()) {
TimingArc *arc = arc_iter.next();
if (tr == nullptr
|| arc->toTrans()->asRiseFall() == tr) {
GateTimingModel *model = dynamic_cast<GateTimingModel*>(arc->model());
if (model) {
float drive = model->driveResistance(liberty_cell_, nullptr);
if (min_max->compare(drive, max_drive))
max_drive = drive;
found_drive = true;
}
}
}
}
}
if (found_drive)
return max_drive;
else
return 0.0;
}
float
LibertyPort::driveResistance() const
{
return driveResistance(nullptr, MinMax::max());
}
void
LibertyPort::setFunction(FuncExpr *func)
{

View File

@ -411,7 +411,7 @@ public:
bool isClockGateOther() const;
bool isClockGate() const;
void setClockGateType(ClockGateType type);
// Internal to LibertyCellTimingArcSetIterator.
// from or to may be nullptr to wildcard.
TimingArcSetSeq *timingArcSets(const LibertyPort *from,
const LibertyPort *to) const;
size_t timingArcSetCount() const;
@ -490,10 +490,6 @@ public:
virtual void finish(bool infer_latches,
Report *report,
Debug *debug);
float driveResistance(const TransRiseFall *tr,
const MinMax *min_max) const;
// Max of rise/fall.
float driveResistance() const;
bool isBuffer() const;
// Only valid when isBuffer() returns true.
void bufferPorts(// Return values.
@ -607,6 +603,7 @@ class LibertyCellTimingArcSetIterator : public TimingArcSetSeq::ConstIterator
{
public:
LibertyCellTimingArcSetIterator(const LibertyCell *cell);
// from or to may be nullptr to wildcard.
LibertyCellTimingArcSetIterator(const LibertyCell *cell,
const LibertyPort *from,
const LibertyPort *to);
@ -659,6 +656,10 @@ public:
void setCapacitance(const TransRiseFall *tr,
const MinMax *min_max,
float cap);
float driveResistance(const TransRiseFall *tr,
const MinMax *min_max) const;
// Max of rise/fall.
float driveResistance() const;
FuncExpr *function() const { return function_; }
void setFunction(FuncExpr *func);
FuncExpr *&functionRef() { return function_; }

View File

@ -918,7 +918,7 @@ WriteSdc::writeClockSense(PinClockPair &pin_clk,
flag = "-negative";
else if (sense == ClockSense::stop)
flag = "-stop_propagation";
fprintf(stream_, "set_clock_sense %s ", flag);
fprintf(stream_, "set_sense -type clock %s ", flag);
const Clock *clk = pin_clk.second;
if (clk) {
fprintf(stream_, "-clock ");

View File

@ -527,18 +527,6 @@ getProperty(const LibertyCell *cell,
return PropertyValue(cell->filename());
else if (stringEqual(property, "library"))
return PropertyValue(cell->libertyLibrary());
else if (stringEqual(property, "drive_resistance_rise_min"))
return PropertyValue(cell->driveResistance(TransRiseFall::rise(),
MinMax::min()));
else if (stringEqual(property, "drive_resistance_rise_max"))
return PropertyValue(cell->driveResistance(TransRiseFall::rise(),
MinMax::max()));
else if (stringEqual(property, "drive_resistance_fall_min"))
return PropertyValue(cell->driveResistance(TransRiseFall::fall(),
MinMax::min()));
else if (stringEqual(property, "drive_resistance_fall_max"))
return PropertyValue(cell->driveResistance(TransRiseFall::fall(),
MinMax::max()));
else if (stringEqual(property, "is_buffer"))
return PropertyValue(cell->isBuffer());
else if (stringEqual(property, "dont_use"))
@ -656,6 +644,18 @@ getProperty(const LibertyPort *port,
float cap = port->capacitance(TransRiseFall::rise(), MinMax::max());
return PropertyValue(sta->units()->capacitanceUnit()->asString(cap, 6));
}
else if (stringEqual(property, "drive_resistance_rise_min"))
return PropertyValue(port->driveResistance(TransRiseFall::rise(),
MinMax::min()));
else if (stringEqual(property, "drive_resistance_rise_max"))
return PropertyValue(port->driveResistance(TransRiseFall::rise(),
MinMax::max()));
else if (stringEqual(property, "drive_resistance_fall_min"))
return PropertyValue(port->driveResistance(TransRiseFall::fall(),
MinMax::min()));
else if (stringEqual(property, "drive_resistance_fall_max"))
return PropertyValue(port->driveResistance(TransRiseFall::fall(),
MinMax::max()));
else
throw PropertyUnknown("liberty port", property);
}

View File

@ -192,16 +192,6 @@ SearchThru::searchThru(Edge *edge)
&& loopEnabled(edge, sdc, graph, search);
}
class ClkArrivalSearchPred : public EvalPred
{
public:
ClkArrivalSearchPred(const StaState *sta);
virtual bool searchThru(Edge *edge);
private:
DISALLOW_COPY_AND_ASSIGN(ClkArrivalSearchPred);
};
ClkArrivalSearchPred::ClkArrivalSearchPred(const StaState *sta) :
EvalPred(sta)
{

View File

@ -346,6 +346,7 @@ public:
VisitPathEnds *visitPathEnds() { return visit_path_ends_; }
GatedClk *gatedClk() { return gated_clk_; }
Genclks *genclks() { return genclks_; }
void findClkVertexPins(PinSet &clk_pins);
protected:
void init(StaState *sta);
@ -376,7 +377,6 @@ protected:
const PathAnalysisPt *path_ap,
Arrival insertion,
TagGroupBldr *tag_bldr);
void findClkVertexPins(PinSet &clk_pins);
Tag *clkDataTag(const Pin *pin,
Clock *clk,
const TransRiseFall *tr,
@ -624,6 +624,16 @@ protected:
bool search_thru_latches_;
};
class ClkArrivalSearchPred : public EvalPred
{
public:
ClkArrivalSearchPred(const StaState *sta);
virtual bool searchThru(Edge *edge);
private:
DISALLOW_COPY_AND_ASSIGN(ClkArrivalSearchPred);
};
// Class for visiting fanin/fanout paths of a vertex.
// This used by forward/backward search to find arrival/required path times.
class PathVisitor : public VertexVisitor

View File

@ -1434,15 +1434,41 @@ proc set_clock_latency { args } {
################################################################
define_cmd_args "set_sense" \
{[-type clock|data] [-positive] [-negative] [-pulse pulse_type]\
[-stop_propagation] [-clocks clocks] pins}
proc set_sense { args } {
parse_key_args "set_clock_sense" args keys {-type} flags {} 0
set type "clock"
if { [info exists keys(-type)] } {
set type $keys(-type)
if { $type == "data" } {
sdc_warn "set_sense -type data not supported."
} elseif { $type == "clock" } {
set_clock_sense_cmd1 "set_sense" $args
} else {
sdc_error "set_sense -type clock|data"
}
}
}
# deprecated in SDC 2.1
define_cmd_args "set_clock_sense" \
{[-positive] [-negative] [-pulse pulse_type] [-stop_propagation] \
[-clock clocks] pins}
proc set_clock_sense { args } {
sdc_warn "set_clock_sense is deprecated as of SDC 2.1. Use set_sense -type clock."
set_clock_sense_cmd1 "set_clock_sense" $args
}
proc set_clock_sense_cmd1 { cmd cmd_args } {
# SDC uses -clock, OT, OC use -clocks
parse_key_args "set_clock_sense" args keys {-clock -clocks -pulse} \
flags {-positive -negative -stop_propagation}
check_argc_eq1 "set_clock_sense" $args
parse_key_args $cmd cmd_args keys {-clock -clocks -pulse} \
flags {-positive -negative -stop_propagation} 0
check_argc_eq1 "set_clock_sense" $cmd_args
set pulse [info exists keys(-pulse)]
if { $pulse } {
@ -1458,7 +1484,7 @@ proc set_clock_sense { args } {
sta_warn "-positive, -negative, -stop_propagation and -pulse are mutually exclusive."
}
set pins [get_port_pins_error "pins" [lindex $args 0]]
set pins [get_port_pins_error "pins" [lindex $cmd_args 0]]
set clks {}
if {[info exists keys(-clock)]} {
set clks [get_clocks_warn "clock" $keys(-clock)]