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