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 <array>
20 #include <vector>
21 #include "DisallowCopyAssign.hh"
22 #include "Iterator.hh"
23 #include "Map.hh"
24 #include "StringUtil.hh"
25 
26 namespace sta {
27 
28 class Transition;
29 class RiseFall;
30 class RiseFallBoth;
31 
32 typedef Map<const char*, Transition*, CharPtrLess> TransitionMap;
33 
34 // Rise/fall transition.
35 class RiseFall
36 {
37 public:
38   // Singleton accessors.
rise()39   static RiseFall *rise() { return &rise_; }
fall()40   static RiseFall *fall() { return &fall_; }
riseIndex()41   static int riseIndex() { return rise_.sdf_triple_index_; }
fallIndex()42   static int fallIndex() { return fall_.sdf_triple_index_; }
asString() const43   const char *asString() const { return short_name_; }
name() const44   const char *name() const { return name_; }
shortName() const45   const char *shortName() const { return short_name_; }
46   void setShortName(const char *short_name);
index() const47   int index() const { return sdf_triple_index_; }
48   RiseFallBoth *asRiseFallBoth();
49   const RiseFallBoth *asRiseFallBoth() const;
50   Transition *asTransition() const;
51   // Find transition corresponding to tr_str.
52   static RiseFall *find(const char *tr_str);
53   // Find transition from index.
54   static RiseFall *find(int index);
55   RiseFall *opposite() const;
56 
57   // for range support.
58   // for (auto tr : RiseFall::range()) {}
range()59   static const std::array<RiseFall*, 2> &range() { return range_; }
60   // for (auto tr_index : RiseFall::rangeIndex()) {}
rangeIndex()61   static const std::array<int, 2> &rangeIndex() { return range_index_; }
62   static const int index_count = 2;
63   static const int index_max = (index_count - 1);
64   static const int index_bit_count = 1;
65 
66 protected:
67   RiseFall(const char *name,
68 		const char *short_name,
69 		int sdf_triple_index);
70   ~RiseFall();
71 
72   const char *name_;
73   const char *short_name_;
74   const int sdf_triple_index_;
75 
76   static RiseFall rise_;
77   static RiseFall fall_;
78   static const std::array<RiseFall*, 2> range_;
79   static const std::array<int, 2> range_index_;
80 
81 private:
82   DISALLOW_COPY_AND_ASSIGN(RiseFall);
83 };
84 
85 // Rise/fall/risefall transition.
86 class RiseFallBoth
87 {
88 public:
89   // Singleton accessors.
rise()90   static RiseFallBoth *rise() { return &rise_; }
fall()91   static RiseFallBoth *fall() { return &fall_; }
riseFall()92   static RiseFallBoth *riseFall() { return &rise_fall_; }
asString() const93   const char *asString() const { return short_name_; }
name() const94   const char *name() const { return name_; }
shortName() const95   const char *shortName() const { return short_name_; }
96   void setShortName(const char *short_name);
index() const97   int index() const { return sdf_triple_index_; }
98   bool matches(const RiseFall *rf) const;
99   bool matches(const Transition *tr) const;
asRiseFall() const100   RiseFall *asRiseFall() const { return as_rise_fall_; }
101   // Find transition corresponding to string.
102   static RiseFallBoth *find(const char *tr_str);
103   // for (auto tr : min_max->range()) {}
range() const104   const std::vector<RiseFall*> &range() const { return range_; }
105   // for (auto tr_index : min_max->rangeIndex()) {}
rangeIndex() const106   const std::vector<int> &rangeIndex() const { return range_index_; }
107 
108   static const int index_count = 3;
109   static const int index_max = (index_count - 1);
110   static const int index_bit_count = 2;
111 
112 protected:
113   RiseFallBoth(const char *name,
114 		    const char *short_name,
115 		    int sdf_triple_index,
116 		    RiseFall *as_rise_fall,
117 		    std::vector<RiseFall*> range,
118 		    std::vector<int> range_index);
119   ~RiseFallBoth();
120 
121   const char *name_;
122   const char *short_name_;
123   const int sdf_triple_index_;
124   RiseFall *as_rise_fall_;
125   const std::vector<RiseFall*> range_;
126   const std::vector<int> range_index_;
127 
128   static RiseFallBoth rise_;
129   static RiseFallBoth fall_;
130   static RiseFallBoth rise_fall_;
131 
132 private:
133   DISALLOW_COPY_AND_ASSIGN(RiseFallBoth);
134 };
135 
136 // General SDF transition.
137 class Transition
138 {
139 public:
140   // Singleton accessors.
rise()141   static Transition *rise() { return &rise_; }
fall()142   static Transition *fall() { return &fall_; }
tr0Z()143   static Transition *tr0Z() { return &tr_0Z_; }
trZ1()144   static Transition *trZ1() { return &tr_Z1_; }
tr1Z()145   static Transition *tr1Z() { return &tr_1Z_; }
trZ0()146   static Transition *trZ0() { return &tr_Z0_; }
tr0X()147   static Transition *tr0X() { return &tr_0X_; }
trX1()148   static Transition *trX1() { return &tr_X1_; }
tr1X()149   static Transition *tr1X() { return &tr_1X_; }
trX0()150   static Transition *trX0() { return &tr_X0_; }
trXZ()151   static Transition *trXZ() { return &tr_XZ_; }
trZX()152   static Transition *trZX() { return &tr_ZX_; }
153   void setName(const char *name);
154   // Matches rise and fall.
riseFall()155   static Transition *riseFall() { return &rise_fall_; }
asString() const156   const char *asString() const { return name_; }
157   // As initial/final value pair.
asInitFinalString() const158   const char *asInitFinalString() const { return init_final_; }
sdfTripleIndex() const159   int sdfTripleIndex() const { return sdf_triple_index_; }
index() const160   int index() const { return sdf_triple_index_; }
asRiseFall() const161   RiseFall *asRiseFall() const { return as_rise_fall_; }
162   const RiseFallBoth *asRiseFallBoth() const;
163   bool matches(const Transition *tr) const;
164   // Find transition corresponding to string.
165   static Transition *find(const char *tr_str);
maxIndex()166   static int maxIndex() { return max_index_; }
167 
168 private:
169   Transition(const char *name,
170 	     const char *init_final,
171 	     RiseFall *as_rise_fall,
172 	     int sdf_triple_index);
173   ~Transition();
174 
175   const char *name_;
176   const char *init_final_;
177   RiseFall *as_rise_fall_;
178   const int sdf_triple_index_;
179 
180   static Transition rise_;
181   static Transition fall_;
182   static Transition tr_0Z_;
183   static Transition tr_Z1_;
184   static Transition tr_1Z_;
185   static Transition tr_Z0_;
186   static Transition tr_0X_;
187   static Transition tr_X1_;
188   static Transition tr_1X_;
189   static Transition tr_X0_;
190   static Transition tr_XZ_;
191   static Transition tr_ZX_;
192   static Transition rise_fall_;
193   static const int index_count = 13;
194   static const int index_max = (index_count - 1);
195   static const int index_bit_count = 4;
196 
197   static TransitionMap transition_map_;
198   static int max_index_;
199 
200 private:
201   DISALLOW_COPY_AND_ASSIGN(Transition);
202 };
203 
204 // Obsolete. Use range iteration instead.
205 // for (RiseFall *rf : RiseFall::range()) {}
206 class RiseFallIterator : public Iterator<RiseFall*>
207 {
208 public:
RiseFallIterator()209   RiseFallIterator() : index_(0), index_max_(RiseFall::index_max) {}
210   explicit RiseFallIterator(const RiseFallBoth *rf);
211   void init();
212   virtual bool hasNext();
213   virtual RiseFall *next();
214 
215 private:
216   DISALLOW_COPY_AND_ASSIGN(RiseFallIterator);
217 
218   int index_;
219   int index_max_;
220 };
221 
222 } // namespace
223