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 "Error.hh"
21 #include "Set.hh"
22 #include "SdcCmdComment.hh"
23 #include "SdcClass.hh"
24 
25 namespace sta {
26 
27 class RiseFall;
28 class RiseFallBoth;
29 class MinMaxAll;
30 class Network;
31 class Pin;
32 class Clock;
33 
34 class ExceptionPt;
35 class ExceptionFrom;
36 class ExceptionThru;
37 class ExceptionTo;
38 class ExceptionState;
39 
40 typedef Vector<ExceptionPath*> ExceptionPathSeq;
41 
42 class ExceptionPath : public SdcCmdComment
43 {
44 public:
45   ExceptionPath(ExceptionFrom *from,
46 		ExceptionThruSeq *thrus,
47 		ExceptionTo *to,
48 		const MinMaxAll *min_max,
49 		bool own_pts,
50 		int priority,
51 		const char *comment);
52   virtual ~ExceptionPath();
isFalse() const53   virtual bool isFalse() const { return false; }
isLoop() const54   virtual bool isLoop() const { return false; }
isMultiCycle() const55   virtual bool isMultiCycle() const { return false; }
isPathDelay() const56   virtual bool isPathDelay() const { return false; }
isGroupPath() const57   virtual bool isGroupPath() const { return false; }
isFilter() const58   virtual bool isFilter() const { return false; }
59   virtual ExceptionPathType type() const = 0;
60   virtual const char *asString(const Network *network) const;
from() const61   ExceptionFrom *from() const { return from_; }
thrus() const62   ExceptionThruSeq *thrus() const { return thrus_; }
to() const63   ExceptionTo *to() const { return to_; }
64   ExceptionPt *firstPt();
65   bool intersectsPts(ExceptionPath *exception) const;
minMax() const66   const MinMaxAll *minMax() const { return min_max_; }
67   virtual bool matches(const MinMax *min_max,
68 		       bool exact) const;
69   bool matchesFirstPt(const RiseFall *to_rf,
70 		      const MinMax *min_max);
71   ExceptionState *firstState();
72   virtual bool resetMatch(ExceptionFrom *from,
73 			  ExceptionThruSeq *thrus,
74 			  ExceptionTo *to,
75 			  const MinMaxAll *min_max);
76   // The priority remains the same even though pin/clock/net/inst objects
77   // are added to the exceptions points during exception merging because
78   // only exceptions with the same priority are merged.
priority(const MinMax *) const79   virtual int priority(const MinMax *) const { return priority_; }
priority() const80   int priority() const { return priority_; }
81   void setPriority(int priority);
82   virtual int typePriority() const = 0;
83   // Exception type priorities are spaced to accomodate
84   // fromThruToPriority from 0 thru 127.
falsePathPriority()85   static int falsePathPriority() { return 4000; }
pathDelayPriority()86   static int pathDelayPriority() { return 3000; }
multiCyclePathPriority()87   static int multiCyclePathPriority() { return 2000; }
filterPathPriority()88   static int filterPathPriority() { return 1000; }
groupPathPriority()89   static int groupPathPriority() { return 0; }
90   // Compare the value (path delay or cycle count) to another exception
91   // of the same priority.  Because the exception "values" are floats,
92   // they cannot be coded into the priority.
93   virtual bool tighterThan(ExceptionPath *exception) const = 0;
94   static int fromThruToPriority(ExceptionFrom *from,
95   				ExceptionThruSeq *thrus,
96 				ExceptionTo *to);
97   size_t hash() const;
98   size_t hash(ExceptionPt *missing_pt) const;
99   // Mergeable properties (independent of exception points).
100   virtual bool mergeable(ExceptionPath *exception) const;
101   bool mergeablePts(ExceptionPath *exception) const;
102   bool mergeablePts(ExceptionPath *exception2,
103 		    ExceptionPt *missing_pt2,
104 		    ExceptionPt *&missing_pt) const;
105   // Overrides properties (independent of exception points).
106   virtual bool overrides(ExceptionPath *exception) const = 0;
107   virtual ExceptionPath *clone(ExceptionFrom *from,
108 			       ExceptionThruSeq *thrus,
109 			       ExceptionTo *to,
110 			       bool own_pts) = 0;
111   // Default handlers.
useEndClk() const112   virtual bool useEndClk() const { return false; }
pathMultiplier() const113   virtual int pathMultiplier() const { return 0; }
delay() const114   virtual float delay() const { return 0.0; }
name() const115   virtual const char *name() const { return nullptr; }
isDefault() const116   virtual bool isDefault() const { return false; }
ignoreClkLatency()117   virtual bool ignoreClkLatency() { return false; }
118 
119 protected:
120   virtual const char *typeString() const = 0;
121   const char *fromThruToString(const Network *network) const;
122   void makeStates();
123 
124   ExceptionFrom *from_;
125   ExceptionThruSeq *thrus_;
126   ExceptionTo *to_;
127   const MinMaxAll *min_max_;
128   bool own_pts_;
129   int priority_;
130   ExceptionState *states_;
131 
132 private:
133   DISALLOW_COPY_AND_ASSIGN(ExceptionPath);
134 };
135 
136 // set_false_path
137 class FalsePath : public ExceptionPath
138 {
139 public:
140   FalsePath(ExceptionFrom *from,
141 	    ExceptionThruSeq *thrus,
142 	    ExceptionTo *to,
143 	    const MinMaxAll *min_max,
144 	    bool own_pts,
145 	    const char *comment);
146   FalsePath(ExceptionFrom *from,
147 	    ExceptionThruSeq *thrus,
148 	    ExceptionTo *to,
149 	    const MinMaxAll *min_max,
150 	    bool own_pts,
151 	    int priority,
152 	    const char *comment);
153   virtual ExceptionPath *clone(ExceptionFrom *from,
154 			       ExceptionThruSeq *thrus,
155 			       ExceptionTo *to,
156 			       bool own_pts);
isFalse() const157   virtual bool isFalse() const { return true; }
type() const158   virtual ExceptionPathType type() const { return ExceptionPathType::false_path; }
159   virtual const char *typeString() const;
160   virtual bool mergeable(ExceptionPath *exception) const;
161   virtual bool overrides(ExceptionPath *exception) const;
162   virtual int typePriority() const;
163   virtual bool tighterThan(ExceptionPath *exception) const;
164 
165 private:
166   DISALLOW_COPY_AND_ASSIGN(FalsePath);
167 };
168 
169 // Loop paths are false paths used to disable paths around
170 // combinational loops when dynamic loop breaking is enabled.
171 class LoopPath : public FalsePath
172 {
173 public:
174   LoopPath(ExceptionThruSeq *thrus,
175 	   bool own_pts);
isLoop() const176   virtual bool isLoop() const { return true; }
type() const177   virtual ExceptionPathType type() const { return ExceptionPathType::loop; }
178   virtual const char *typeString() const;
179   virtual bool mergeable(ExceptionPath *exception) const;
180 
181 private:
182   DISALLOW_COPY_AND_ASSIGN(LoopPath);
183 };
184 
185 // set_max_delay/set_min_delay
186 class PathDelay : public ExceptionPath
187 {
188 public:
189   PathDelay(ExceptionFrom *from,
190 	    ExceptionThruSeq *thrus,
191 	    ExceptionTo *to,
192 	    const MinMax *min_max,
193 	    bool ignore_clk_latency,
194 	    float delay,
195 	    bool own_pts,
196 	    const char *comment);
197   virtual ExceptionPath *clone(ExceptionFrom *from,
198 			       ExceptionThruSeq *thrus,
199 			       ExceptionTo *to,
200 			       bool own_pts);
isPathDelay() const201   virtual bool isPathDelay() const { return true; }
type() const202   virtual ExceptionPathType type() const { return ExceptionPathType::path_delay; }
203   virtual const char *asString(const Network *network) const;
204   virtual const char *typeString() const;
205   virtual bool mergeable(ExceptionPath *exception) const;
206   virtual bool overrides(ExceptionPath *exception) const;
delay() const207   virtual float delay() const { return delay_; }
208   virtual int typePriority() const;
209   virtual bool tighterThan(ExceptionPath *exception) const;
ignoreClkLatency()210   virtual bool ignoreClkLatency() { return ignore_clk_latency_; }
211 
212 protected:
213   bool ignore_clk_latency_;
214   float delay_;
215 
216 private:
217   DISALLOW_COPY_AND_ASSIGN(PathDelay);
218 };
219 
220 // set_multicycle_path
221 class MultiCyclePath : public ExceptionPath
222 {
223 public:
224   MultiCyclePath(ExceptionFrom *from,
225 		 ExceptionThruSeq *thrus,
226 		 ExceptionTo *to,
227 		 const MinMaxAll *min_max,
228 		 bool use_end_clk,
229 		 int path_multiplier,
230 		 bool own_pts,
231 		 const char *comment);
232   virtual ExceptionPath *clone(ExceptionFrom *from,
233 			       ExceptionThruSeq *thrus,
234 			       ExceptionTo *to,
235 			       bool own_pts);
isMultiCycle() const236   virtual bool isMultiCycle() const { return true; }
type() const237   virtual ExceptionPathType type() const { return ExceptionPathType::multi_cycle; }
238   virtual bool matches(const MinMax *min_max,
239 		       bool exactly) const;
240   virtual const char *asString(const Network *network) const;
241   virtual const char *typeString() const;
242   virtual bool mergeable(ExceptionPath *exception) const;
243   virtual bool overrides(ExceptionPath *exception) const;
useEndClk() const244   virtual bool useEndClk() const { return use_end_clk_; }
245   virtual int pathMultiplier(const MinMax *min_max) const;
pathMultiplier() const246   virtual int pathMultiplier() const { return path_multiplier_; }
247   virtual int priority(const MinMax *min_max) const;
248   virtual int typePriority() const;
249   virtual bool tighterThan(ExceptionPath *exception) const;
250 
251   using ExceptionPath::priority;
252 
253 protected:
254   bool use_end_clk_;
255   int path_multiplier_;
256 
257 private:
258   DISALLOW_COPY_AND_ASSIGN(MultiCyclePath);
259 };
260 
261 // Filter used restrict path reporting -from/-thru nets/pins.
262 class FilterPath : public ExceptionPath
263 {
264 public:
265   FilterPath(ExceptionFrom *from,
266 	     ExceptionThruSeq *thrus,
267 	     ExceptionTo *to,
268 	     bool own_pts);
269   virtual ExceptionPath *clone(ExceptionFrom *from,
270 			       ExceptionThruSeq *thrus,
271 			       ExceptionTo *to,
272 			       bool own_pts);
isFilter() const273   virtual bool isFilter() const { return true; }
type() const274   virtual ExceptionPathType type() const { return ExceptionPathType::filter; }
275   virtual const char *typeString() const;
276   virtual bool mergeable(ExceptionPath *exception) const;
277   virtual bool overrides(ExceptionPath *exception) const;
278   virtual bool resetMatch(ExceptionFrom *from,
279 			  ExceptionThruSeq *thrus,
280 			  ExceptionTo *to,
281 			  const MinMaxAll *min_max);
282   virtual int typePriority() const;
283   virtual bool tighterThan(ExceptionPath *exception) const;
284 
285 private:
286   DISALLOW_COPY_AND_ASSIGN(FilterPath);
287 };
288 
289 class GroupPath : public ExceptionPath
290 {
291 public:
292   GroupPath(const char *name,
293 	    bool is_default,
294 	    ExceptionFrom *from,
295 	    ExceptionThruSeq *thrus,
296 	    ExceptionTo *to,
297 	    bool own_pts,
298 	    const char *comment);
299   virtual ~GroupPath();
300   virtual ExceptionPath *clone(ExceptionFrom *from,
301 			       ExceptionThruSeq *thrus,
302 			       ExceptionTo *to,
303 			       bool own_pts);
isGroupPath() const304   virtual bool isGroupPath() const { return true; }
type() const305   virtual ExceptionPathType type() const { return ExceptionPathType::group_path; }
306   virtual const char *typeString() const;
307   virtual bool mergeable(ExceptionPath *exception) const;
308   virtual bool overrides(ExceptionPath *exception) const;
309   virtual int typePriority() const;
310   virtual bool tighterThan(ExceptionPath *exception) const;
name() const311   virtual const char *name()  const { return name_; }
isDefault() const312   virtual bool isDefault() const { return is_default_; }
313 
314 protected:
315   const char *name_;
316   bool is_default_;
317 
318 private:
319   DISALLOW_COPY_AND_ASSIGN(GroupPath);
320 };
321 
322 // Base class for Exception from/thru/to.
323 class ExceptionPt
324 {
325 public:
326   ExceptionPt(const RiseFallBoth *rf,
327 	      bool own_pts);
~ExceptionPt()328   virtual ~ExceptionPt() {};
isFrom() const329   virtual bool isFrom() const { return false; }
isThru() const330   virtual bool isThru() const { return false; }
isTo() const331   virtual bool isTo() const { return false; }
transition() const332   const RiseFallBoth *transition() const { return rf_; }
333   virtual PinSet *pins() = 0;
334   virtual ClockSet *clks() = 0;
335   virtual InstanceSet *instances() = 0;
336   virtual NetSet *nets() = 0;
337   virtual EdgePinsSet *edges() = 0;
338   size_t hash() const;
339   virtual int nameCmp(ExceptionPt *pt, const Network *network) const = 0;
340   virtual void mergeInto(ExceptionPt *pt) = 0;
341   // All pins and instance/net pins.
342   virtual void allPins(const Network *network,
343 		       PinSet *pins) = 0;
344   virtual int typePriority() const = 0;
345   virtual const char *asString(const Network *network) const = 0;
346   virtual size_t objectCount() const = 0;
347   virtual void addPin(Pin *pin) = 0;
348   virtual void addClock(Clock *clk) = 0;
349   virtual void addInstance(Instance *inst) = 0;
350   virtual void addNet(Net *net) = 0;
351   virtual void addEdge(EdgePins *edge) = 0;
352   virtual void connectPinAfter(PinSet *,
353 			       Network *network) = 0;
354   virtual void disconnectPinBefore(Pin *pin,
355 				   Network *network) = 0;
356 
357 protected:
358   const RiseFallBoth *rf_;
359   // True when the pin/net/inst/edge sets are owned by the exception point.
360   bool own_pts_;
361   // Hash is cached because there may be many objects to speed up
362   // exception merging.
363   size_t hash_;
364 
365   // Maximum number of objects for asString() to show.
366   static const int as_string_max_objects_;
367   static const size_t hash_clk  =  3;
368   static const size_t hash_pin  =  5;
369   static const size_t hash_net  =  7;
370   static const size_t hash_inst = 11;
371 
372 private:
373   DISALLOW_COPY_AND_ASSIGN(ExceptionPt);
374 };
375 
376 class ExceptionFromTo : public ExceptionPt
377 {
378 public:
379   ExceptionFromTo(PinSet *pins, ClockSet *clks,
380 		  InstanceSet *insts,
381 		  const RiseFallBoth *rf,
382 		  bool own_pts);
383   ~ExceptionFromTo();
pins()384   virtual PinSet *pins() { return pins_; }
385   bool hasPins() const;
clks()386   ClockSet *clks() { return clks_; }
387   bool hasClocks() const;
instances()388   InstanceSet *instances() { return insts_; }
389   bool hasInstances() const;
nets()390   virtual NetSet *nets() { return nullptr; }
edges()391   virtual EdgePinsSet *edges() { return nullptr; }
392   bool hasObjects() const;
393   void deleteObjects(ExceptionFromTo *pt);
394   virtual void allPins(const Network *network,
395 		       PinSet *pins);
396   bool equal(ExceptionFromTo *from_to) const;
397   virtual int nameCmp(ExceptionPt *pt,
398 		      const Network *network) const;
399   virtual void mergeInto(ExceptionPt *pt);
400   virtual const char *asString(const Network *network) const;
401   virtual size_t objectCount() const;
402   void deleteClock(Clock *clk);
403   virtual void addPin(Pin *pin);
404   virtual void addClock(Clock *clk);
405   virtual void addInstance(Instance *inst);
addNet(Net *)406   virtual void addNet(Net *) {}
addEdge(EdgePins *)407   virtual void addEdge(EdgePins *) {}
connectPinAfter(PinSet *,Network *)408   virtual void connectPinAfter(PinSet *,
409 			       Network *) {}
disconnectPinBefore(Pin *,Network *)410   virtual void disconnectPinBefore(Pin *,
411 				   Network *) {}
412 
413 protected:
414   virtual void findHash();
415 
416   void deletePin(Pin *pin);
417   void deleteInstance(Instance *inst);
418   virtual const char *cmdKeyword() const = 0;
419 
420   PinSet *pins_;
421   ClockSet *clks_;
422   InstanceSet *insts_;
423 
424 private:
425   DISALLOW_COPY_AND_ASSIGN(ExceptionFromTo);
426 };
427 
428 class ExceptionFrom : public ExceptionFromTo
429 {
430 public:
431   ExceptionFrom(PinSet *pins,
432 		ClockSet *clks,
433 		InstanceSet *insts,
434 		const RiseFallBoth *rf,
435 		bool own_pts);
436   ExceptionFrom *clone();
isFrom() const437   virtual bool isFrom() const { return true; }
438   bool intersectsPts(ExceptionFrom *from) const;
typePriority() const439   virtual int typePriority() const { return 0; }
440 
441 protected:
442   virtual const char *cmdKeyword() const;
443   virtual void findHash();
444 
445 private:
446   DISALLOW_COPY_AND_ASSIGN(ExceptionFrom);
447 };
448 
449 class ExceptionTo : public ExceptionFromTo
450 {
451 public:
452   ExceptionTo(PinSet *pins,
453 	      ClockSet *clks,
454 	      InstanceSet *insts,
455 	      // -to|-rise_to|-fall_to
456 	      const RiseFallBoth *rf,
457 	      // -rise|-fall endpoint transition.
458 	      const RiseFallBoth *end_rf,
459 	      bool own_pts);
460   ExceptionTo *clone();
isTo() const461   virtual bool isTo() const { return true; }
462   const char *asString(const Network *network) const;
endTransition()463   const RiseFallBoth *endTransition() { return end_rf_; }
464   bool intersectsPts(ExceptionTo *to) const;
typePriority() const465   virtual int typePriority() const { return 1; }
466   bool matches(const Pin *pin,
467  	       const ClockEdge *clk_edge,
468  	       const RiseFall *end_rf,
469  	       const Network *network) const;
470   bool matches(const Pin *pin,
471 	       const RiseFall *end_rf) const;
472   bool matches(const Clock *clk) const;
473   bool matchesFilter(const Pin *pin,
474 		     const ClockEdge *clk_edge,
475 		     const RiseFall *end_rf,
476 		     const Network *network) const;
477   virtual int nameCmp(ExceptionPt *pt, const Network *network) const;
478 
479 protected:
480   bool matches(const Pin *pin,
481 	       const ClockEdge *clk_edge,
482 	       const RiseFall *end_rf,
483 	       bool inst_matches_reg_clk_pin,
484 	       const Network *network) const;
485   virtual const char *cmdKeyword() const;
486 
487   // -rise|-fall endpoint transition.
488   const RiseFallBoth *end_rf_;
489 
490 private:
491   DISALLOW_COPY_AND_ASSIGN(ExceptionTo);
492 };
493 
494 class ExceptionThru : public ExceptionPt
495 {
496 public:
497   ExceptionThru(PinSet *pins,
498 		NetSet *nets,
499 		InstanceSet *insts,
500 		const RiseFallBoth *rf,
501 		bool own_pts,
502 		const Network *network);
503   ~ExceptionThru();
504   ExceptionThru *clone(const Network *network);
505   virtual const char *asString(const Network *network) const;
isThru() const506   virtual bool isThru() const { return true; }
pins()507   PinSet *pins() { return pins_; }
edges()508   EdgePinsSet *edges() { return edges_; }
nets()509   NetSet *nets() { return nets_; }
instances()510   InstanceSet *instances() { return insts_; }
clks()511   virtual ClockSet *clks() { return nullptr; }
512   bool hasObjects() const;
513   void deleteObjects(ExceptionThru *pt);
514   virtual void allPins(const Network *network,
515 		       PinSet *pins);
516   bool matches(const Pin *from_pin,
517 	       const Pin *to_pin,
518 	       const RiseFall *to_rf,
519 	       const Network *network);
520   bool equal(ExceptionThru *thru) const;
521   virtual int nameCmp(ExceptionPt *pt,
522 		      const Network *network) const;
523   virtual void mergeInto(ExceptionPt *pt);
524   bool intersectsPts(ExceptionThru *thru) const;
typePriority() const525   virtual int typePriority() const { return 2; }
526   virtual size_t objectCount() const;
527   virtual void connectPinAfter(PinSet *drvrs,
528 			       Network *network);
529   virtual void disconnectPinBefore(Pin *pin,
530 				   Network *network);
531 
532 protected:
533   void findHash();
534   virtual void addPin(Pin *pin);
535   virtual void addEdge(EdgePins *edge);
536   virtual void addNet(Net *net);
537   virtual void addInstance(Instance *inst);
addClock(Clock *)538   virtual void addClock(Clock *) {}
539   void deletePin(Pin *pin);
540   void deleteEdge(EdgePins *edge);
541   void deleteNet(Net *net);
542   void deleteInstance(Instance *inst);
543   void makeAllEdges(const Network *network);
544   void makePinEdges(const Network *network);
545   void makeNetEdges(const Network *network);
546   void makeInstEdges(const Network *network);
547   void makeHpinEdges(const Pin *pin,
548 		     const Network *network);
549   void makePinEdges(Pin *pin,
550 		    const Network *network);
551   void makeNetEdges(Net *net,
552 		    const Network *network);
553   void makeInstEdges(Instance *inst,
554 		     Network *network);
555   void deletePinEdges(Pin *pin,
556 		      Network *network);
557   void deleteNetEdges(Net *net,
558 		      const Network *network);
559   void deleteInstEdges(Instance *inst,
560 		       Network *network);
561 
562   // Leaf/port pins.
563   PinSet *pins_;
564   // Graph edges that traverse thru hierarchical pins.
565   EdgePinsSet *edges_;
566   NetSet *nets_;
567   InstanceSet *insts_;
568 
569 private:
570   DISALLOW_COPY_AND_ASSIGN(ExceptionThru);
571 };
572 
573 ExceptionThruSeq *
574 exceptionThrusClone(ExceptionThruSeq *thrus,
575 		    const Network *network);
576 
577 // Iterate uniformly across exception from/thru/to's.
578 class ExceptionPtIterator
579 {
580 public:
581   explicit ExceptionPtIterator(const ExceptionPath *exception);
582   bool hasNext();
583   ExceptionPt *next();
584 
585 private:
586   DISALLOW_COPY_AND_ASSIGN(ExceptionPtIterator);
587 
588   const ExceptionPath *exception_;
589   bool from_done_;
590   ExceptionThruSeq::Iterator thru_iter_;
591   bool to_done_;
592 };
593 
594 // Visitor for exception point sets expanded into single object paths.
595 // For example:
596 //  -from {A B} -to {C D}
597 // expands into
598 //  -from A -to C
599 //  -from A -to D
600 //  -from B -to C
601 //  -from B -to D
602 class ExpandedExceptionVisitor
603 {
604 public:
605   ExpandedExceptionVisitor(ExceptionPath *exception,
606 			   const Network *network);
~ExpandedExceptionVisitor()607   virtual ~ExpandedExceptionVisitor() {}
608   void visitExpansions();
609   // From/thrus/to have a single exception point (pin/instance/net/clock).
610   virtual void visit(ExceptionFrom *from,
611 		     ExceptionThruSeq *thrus,
612 		     ExceptionTo *to) = 0;
613 
614 protected:
615   ExceptionPath *exception_;
616   const Network *network_;
617 
618 private:
619   DISALLOW_COPY_AND_ASSIGN(ExpandedExceptionVisitor);
620   void expandFrom();
621   void expandThrus(ExceptionFrom *expanded_from);
622   void expandThru(ExceptionFrom *expanded_from,
623 		  ExceptionThruSeq::Iterator &thru_iter,
624 		  ExceptionThruSeq *expanded_thrus);
625   void expandTo(ExceptionFrom *expanded_from,
626 		ExceptionThruSeq *expanded_thrus);
627 };
628 
629 // States used by tags to know what exception points have been seen
630 // so far in a path.
631 class ExceptionState
632 {
633 public:
634   ExceptionState(ExceptionPath *exception,
635 		 ExceptionThru *next_thru,
636 		 int index);
exception()637   ExceptionPath *exception() { return exception_; }
638   bool matchesNextThru(const Pin *from_pin,
639 		       const Pin *to_pin,
640 		       const RiseFall *to_rf,
641 		       const MinMax *min_max,
642 		       const Network *network) const;
643   bool isComplete() const;
nextThru() const644   ExceptionThru *nextThru() const { return next_thru_; }
nextState() const645   ExceptionState *nextState() const { return next_state_; }
646   void setNextState(ExceptionState *next_state);
647   size_t hash() const;
648 
649 private:
650   DISALLOW_COPY_AND_ASSIGN(ExceptionState);
651 
652   ExceptionPath *exception_;
653   ExceptionThru *next_thru_;
654   ExceptionState *next_state_;
655   int index_;
656 };
657 
658 // Exception thrown by check.
659 class EmptyExpceptionPt : public Exception
660 {
661 public:
662   virtual const char *what() const noexcept;
663 };
664 
665 // Throws EmptyExpceptionPt it finds an empty exception point.
666 void
667 checkFromThrusTo(ExceptionFrom *from,
668 		 ExceptionThruSeq *thrus,
669 		 ExceptionTo *to);
670 
671 void
672 sortExceptions(ExceptionPathSet *set,
673 	       ExceptionPathSeq &exceptions,
674 	       Network *network);
675 
676 bool
677 intersects(PinSet *set1,
678 	   PinSet *set2);
679 bool
680 intersects(ClockSet *set1,
681 	   ClockSet *set2);
682 
683 } // namespace
684