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