1 // OpenSTA, Static Timing Analyzer 2 // Copyright (c) 2020, Parallax Software, Inc. 3 // 4 // This program is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // This program is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with this program. If not, see <https://www.gnu.org/licenses/>. 16 17 #pragma once 18 19 #include "DisallowCopyAssign.hh" 20 #include "MinMax.hh" 21 #include "RiseFallMinMax.hh" 22 #include "SdcClass.hh" 23 #include "SdcCmdComment.hh" 24 #include "GraphClass.hh" 25 26 namespace sta { 27 28 typedef Map<Pin*, PinSet*> ClkHpinEdgeMap; 29 30 class Clock : public SdcCmdComment 31 { 32 public: 33 ~Clock(); name() const34 const char *name() const { return name_; } period() const35 float period() const { return period_; } 36 // Virtual clocks have no pins. 37 bool isVirtual() const; pins()38 PinSet &pins() { return pins_; } pins() const39 const PinSet &pins() const { return pins_; } 40 // The clock source pin's leaf pins. 41 // If the source pin is hierarchical, the leaf pins are: 42 // hierarchical input - load pins inside the hierarchical instance 43 // hierarchical output - load pins outside the hierarchical instance leafPins()44 PinSet &leafPins() { return leaf_pins_; } leafPins() const45 const PinSet &leafPins() const { return leaf_pins_; } 46 // Clock pin used by input/output delay for propagated generated 47 // clock insertion delay. 48 Pin *defaultPin() const; addToPins() const49 bool addToPins() const { return add_to_pins_; } 50 void setAddToPins(bool add_to_pins); waveform()51 FloatSeq *waveform() { return waveform_; } waveform() const52 const FloatSeq *waveform() const { return waveform_; } 53 ClockEdge *edge(const RiseFall *rf) const; index() const54 int index() const { return index_; } isPropagated() const55 bool isPropagated() const { return is_propagated_; } 56 void setIsPropagated(bool propagated); 57 // Ideal clock slew. 58 void slew(const RiseFall *rf, 59 const MinMax *min_max, 60 // Return values. 61 float &slew, 62 bool &exists) const; 63 // Return zero (default) if no slew exists. 64 float slew(const RiseFall *rf, 65 const MinMax *min_max) const; 66 void setSlew(const RiseFall *rf, 67 const MinMax *min_max, 68 float slew); 69 void setSlew(const RiseFallBoth *rf, 70 const MinMaxAll *min_max, 71 float slew); 72 void removeSlew(); slews()73 RiseFallMinMax *slews() { return &slews_; } 74 void setSlewLimit(const RiseFallBoth *rf, 75 const PathClkOrData clk_data, 76 const MinMax *min_max, 77 float slew); 78 void slewLimit(const RiseFall *rf, 79 const PathClkOrData clk_data, 80 const MinMax *min_max, 81 // Return values. 82 float &slew, 83 bool &exists) const; uncertainties() const84 ClockUncertainties *uncertainties() const { return uncertainties_; } 85 void uncertainty(const SetupHold *setup_hold, 86 // Return values. 87 float &uncertainty, 88 bool &exists) const; 89 void setUncertainty(const SetupHoldAll *setup_hold, 90 float uncertainty); 91 void setUncertainty(const SetupHold *setup_hold, 92 float uncertainty); 93 void removeUncertainty(const SetupHoldAll *setup_hold); 94 95 void setPeriod(float period); 96 void setWaveform(FloatSeq *waveform); 97 98 void addPin(Pin *pin); 99 void deletePin(Pin *pin); 100 void makeLeafPins(const Network *network); 101 102 bool isGenerated() const; 103 bool isGeneratedWithPropagatedMaster() const; 104 void generate(const Clock *src_clk); srcPin() const105 Pin *srcPin() const { return src_pin_; } masterClk() const106 Clock *masterClk() const { return master_clk_; } masterClkInfered() const107 bool masterClkInfered() const { return master_clk_infered_; } 108 void setInferedMasterClk(Clock *master_clk); pllOut() const109 Pin *pllOut() const { return pll_out_; } pllFdbk() const110 Pin *pllFdbk() const { return pll_fdbk_; } divideBy() const111 int divideBy() const { return divide_by_; } multiplyBy() const112 int multiplyBy() const { return multiply_by_; } dutyCycle() const113 float dutyCycle() const { return duty_cycle_; } invert() const114 bool invert() const { return invert_; } edges() const115 IntSeq *edges() const { return edges_; } edgeShifts() const116 FloatSeq *edgeShifts() const { return edge_shifts_; } 117 const RiseFall *masterClkEdgeTr(const RiseFall *rf) const; combinational() const118 bool combinational() const { return combinational_; } 119 bool isDivideByOneCombinational() const; 120 bool generatedUpToDate() const; 121 void srcPinVertices(VertexSet &src_vertices, 122 const Network *network, 123 Graph *graph); 124 // True if the generated clock waveform is up to date. waveformValid() const125 bool waveformValid() const { return waveform_valid_; } 126 void waveformInvalid(); 127 128 protected: 129 // Private to Constraints::makeClock. 130 Clock(const char *name, 131 int index); 132 void initClk(PinSet *pins, 133 bool add_to_pins, 134 float period, 135 FloatSeq *waveform, 136 const char *comment, 137 const Network *network); 138 void initGeneratedClk(PinSet *pins, 139 bool add_to_pins, 140 Pin *src_pin, 141 Clock *master_clk, 142 Pin *pll_out, 143 Pin *pll_fdbk, 144 int divide_by, 145 int multiply_by, 146 float duty_cycle, 147 bool invert, 148 bool combinational, 149 IntSeq *edges, 150 FloatSeq *edge_shifts, 151 bool is_propagated, 152 const char *comment, 153 const Network *network); 154 void setPins(PinSet *pins, 155 const Network *network); 156 void setMasterClk(Clock *master); 157 void makeClkEdges(); 158 void setClkEdgeTimes(); 159 void setClkEdgeTime(const RiseFall *rf); 160 void generateScaledClk(const Clock *src_clk, 161 float scale); 162 void generateEdgesClk(const Clock *src_clk); 163 164 const char *name_; 165 PinSet pins_; 166 bool add_to_pins_; 167 // Hierarchical pins in pins_ become driver pins through the pin. 168 PinSet leaf_pins_; 169 Pin *pll_out_; 170 Pin *pll_fdbk_; 171 float period_; 172 FloatSeq *waveform_; 173 bool waveform_valid_; 174 const int index_; 175 ClockEdge **clk_edges_; 176 bool is_propagated_; 177 RiseFallMinMax slews_; 178 RiseFallMinMax slew_limits_[path_clk_or_data_count]; 179 ClockUncertainties *uncertainties_; 180 bool is_generated_; 181 // Generated clock variables. 182 Pin *src_pin_; 183 Clock *master_clk_; 184 // True if the master clock is infered rather than specified by command. 185 bool master_clk_infered_; 186 int divide_by_; 187 int multiply_by_; 188 float duty_cycle_; 189 bool invert_; 190 bool combinational_; 191 IntSeq *edges_; 192 FloatSeq *edge_shifts_; 193 194 private: 195 DISALLOW_COPY_AND_ASSIGN(Clock); 196 197 friend class Sdc; 198 }; 199 200 // A single rise/fall edge of a clock 201 class ClockEdge 202 { 203 public: clock() const204 Clock *clock() const { return clock_; } 205 ~ClockEdge(); transition() const206 RiseFall *transition() const { return rf_; } time() const207 float time() const { return time_; } name() const208 const char *name() const { return name_; } index() const209 int index() const { return index_; } 210 ClockEdge *opposite() const; 211 // Pulse width if this is the leading edge of the pulse. 212 float pulseWidth() const; 213 214 friend class Clock; // builder 215 private: 216 DISALLOW_COPY_AND_ASSIGN(ClockEdge); 217 ClockEdge(Clock *clock, RiseFall *rf); 218 void setTime(float time); 219 220 Clock *clock_; 221 RiseFall *rf_; 222 const char *name_; 223 float time_; 224 int index_; 225 }; 226 227 int 228 clkCmp(const Clock *clk1, 229 const Clock *clk2); 230 int 231 clkEdgeCmp(ClockEdge *clk_edge1, 232 ClockEdge *clk_edge2); 233 bool 234 clkEdgeLess(ClockEdge *clk_edge1, 235 ClockEdge *clk_edge2); 236 237 class ClockNameLess 238 { 239 public: 240 bool operator()(const Clock *clk1, const Clock *clk2); 241 }; 242 243 //////////////////////////////////////////////////////////////// 244 245 class InterClockUncertainty 246 { 247 public: 248 InterClockUncertainty(const Clock *src, 249 const Clock *target); src() const250 const Clock *src() const { return src_; } target() const251 const Clock *target() const { return target_; } 252 void uncertainty(const RiseFall *src_rf, 253 const RiseFall *tgt_rf, 254 const SetupHold *setup_hold, 255 // Return values. 256 float &uncertainty, 257 bool &exists) const; 258 void setUncertainty(const RiseFallBoth *src_rf, 259 const RiseFallBoth *tgt_rf, 260 const SetupHoldAll *setup_hold, 261 float uncertainty); 262 void removeUncertainty(const RiseFallBoth *src_rf, 263 const RiseFallBoth *tgt_rf, 264 const SetupHoldAll *setup_hold); 265 const RiseFallMinMax *uncertainties(RiseFall *src_rf) const; 266 bool empty() const; 267 268 private: 269 DISALLOW_COPY_AND_ASSIGN(InterClockUncertainty); 270 271 const Clock *src_; 272 const Clock *target_; 273 RiseFallMinMax uncertainties_[RiseFall::index_count]; 274 }; 275 276 class InterClockUncertaintyLess 277 { 278 public: 279 bool operator()(const InterClockUncertainty *inter1, 280 const InterClockUncertainty *inter2) const; 281 }; 282 283 class ClkNameLess 284 { 285 public: operator ()(const Clock * clk1,const Clock * clk2) const286 bool operator()(const Clock *clk1, 287 const Clock *clk2) const 288 { 289 return stringLess(clk1->name(), clk2->name()); 290 } 291 }; 292 293 void 294 sortClockSet(ClockSet * set, 295 ClockSeq &clks); 296 297 } // namespace 298