1 // OpenSTA, Static Timing Analyzer
2 // Copyright (c) 2021, 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 #include "DisabledPorts.hh"
18 
19 #include <algorithm>
20 
21 #include "StringUtil.hh"
22 #include "TimingRole.hh"
23 #include "Liberty.hh"
24 #include "Network.hh"
25 
26 namespace sta {
27 
DisabledPorts()28 DisabledPorts::DisabledPorts() :
29   all_(false),
30   from_(nullptr),
31   to_(nullptr),
32   from_to_(nullptr)
33 {
34 }
35 
~DisabledPorts()36 DisabledPorts::~DisabledPorts()
37 {
38   delete from_;
39   delete to_;
40   if (from_to_) {
41     from_to_->deleteContents();
42     delete from_to_;
43   }
44 }
45 
46 void
setDisabledAll()47 DisabledPorts::setDisabledAll()
48 {
49   all_ = true;
50 }
51 
52 void
removeDisabledAll()53 DisabledPorts::removeDisabledAll()
54 {
55   all_ = false;
56 }
57 
58 void
setDisabledFrom(LibertyPort * port)59 DisabledPorts::setDisabledFrom(LibertyPort *port)
60 {
61   if (from_ == nullptr)
62     from_ = new LibertyPortSet;
63   from_->insert(port);
64 }
65 
66 void
removeDisabledFrom(LibertyPort * port)67 DisabledPorts::removeDisabledFrom(LibertyPort *port)
68 {
69   if (from_)
70     from_->erase(port);
71 }
72 
73 void
setDisabledTo(LibertyPort * port)74 DisabledPorts::setDisabledTo(LibertyPort *port)
75 {
76   if (to_ == nullptr)
77     to_ = new LibertyPortSet;
78   to_->insert(port);
79 }
80 
81 void
removeDisabledTo(LibertyPort * port)82 DisabledPorts::removeDisabledTo(LibertyPort *port)
83 {
84   if (to_)
85     to_->erase(port);
86 }
87 
88 void
setDisabledFromTo(LibertyPort * from,LibertyPort * to)89 DisabledPorts::setDisabledFromTo(LibertyPort *from, LibertyPort *to)
90 {
91   if (from_to_ == nullptr)
92     from_to_ = new LibertyPortPairSet;
93   LibertyPortPair pair(from, to);
94   if (!from_to_->hasKey(&pair)) {
95     LibertyPortPair *pair = new LibertyPortPair(from, to);
96     from_to_->insert(pair);
97   }
98 }
99 
100 void
removeDisabledFromTo(LibertyPort * from,LibertyPort * to)101 DisabledPorts::removeDisabledFromTo(LibertyPort *from, LibertyPort *to)
102 {
103   if (from_to_) {
104     LibertyPortPair probe(from, to);
105     LibertyPortPair *pair = from_to_->findKey(&probe);
106     if (pair) {
107       from_to_->erase(pair);
108       delete pair;
109     }
110   }
111 }
112 
113 bool
isDisabled(LibertyPort * from,LibertyPort * to,const TimingRole * role)114 DisabledPorts::isDisabled(LibertyPort *from, LibertyPort *to,
115 			  const TimingRole *role)
116 {
117   LibertyPortPair pair(from, to);
118   // set_disable_timing instance does not disable timing checks.
119   return (all_ && !role->isTimingCheck())
120     || (from_ && from_->hasKey(from))
121     || (to_ && to_->hasKey(to))
122     || (from_to_ && from_to_->hasKey(&pair));
123 }
124 
125 ////////////////////////////////////////////////////////////////
126 
DisabledCellPorts(LibertyCell * cell)127 DisabledCellPorts::DisabledCellPorts(LibertyCell *cell) :
128   DisabledPorts(),
129   cell_(cell),
130   arc_sets_(nullptr)
131 {
132 }
133 
134 
~DisabledCellPorts()135 DisabledCellPorts::~DisabledCellPorts()
136 {
137   delete arc_sets_;
138 }
139 
140 void
setDisabled(TimingArcSet * arc_set)141 DisabledCellPorts::setDisabled(TimingArcSet *arc_set)
142 {
143   if (arc_sets_ == nullptr)
144     arc_sets_ = new TimingArcSetSet;
145   arc_sets_->insert(arc_set);
146 }
147 
148 void
removeDisabled(TimingArcSet * arc_set)149 DisabledCellPorts::removeDisabled(TimingArcSet *arc_set)
150 {
151   if (arc_sets_)
152     arc_sets_->erase(arc_set);
153 }
154 
155 bool
isDisabled(TimingArcSet * arc_set) const156 DisabledCellPorts::isDisabled(TimingArcSet *arc_set) const
157 {
158   return arc_sets_
159     && arc_sets_->hasKey(arc_set);
160 }
161 
162 class DisabledCellPortsLess
163 {
164 public:
165   DisabledCellPortsLess();
166   bool operator()(const DisabledCellPorts *disable1,
167 		  const DisabledCellPorts *disable2);
168 };
169 
DisabledCellPortsLess()170 DisabledCellPortsLess::DisabledCellPortsLess()
171 {
172 }
173 
174 bool
operator ()(const DisabledCellPorts * disable1,const DisabledCellPorts * disable2)175 DisabledCellPortsLess::operator()(const DisabledCellPorts *disable1,
176 				  const DisabledCellPorts *disable2)
177 {
178   return stringLess(disable1->cell()->name(),
179 		    disable2->cell()->name());
180 }
181 
182 void
sortDisabledCellPortsMap(DisabledCellPortsMap * cell_map,DisabledCellPortsSeq & disables)183 sortDisabledCellPortsMap(DisabledCellPortsMap *cell_map,
184 			 DisabledCellPortsSeq &disables)
185 {
186   DisabledCellPortsMap::Iterator disabled_iter(cell_map);
187   while (disabled_iter.hasNext())
188     disables.push_back(disabled_iter.next());
189   sort(disables, DisabledCellPortsLess());
190 }
191 
192 ////////////////////////////////////////////////////////////////
193 
DisabledInstancePorts(Instance * inst)194 DisabledInstancePorts::DisabledInstancePorts(Instance *inst) :
195   DisabledPorts(),
196   inst_(inst)
197 {
198 }
199 
200 class DisabledInstPortsLess
201 {
202 public:
203   explicit DisabledInstPortsLess(Network *network);
204   bool operator()(const DisabledInstancePorts *disable1,
205 		  const DisabledInstancePorts *disable2);
206 
207 private:
208   Network *network_;
209 };
210 
DisabledInstPortsLess(Network * network)211 DisabledInstPortsLess::DisabledInstPortsLess(Network *network) :
212   network_(network)
213 {
214 }
215 
216 bool
operator ()(const DisabledInstancePorts * disable1,const DisabledInstancePorts * disable2)217 DisabledInstPortsLess::operator()(const DisabledInstancePorts *disable1,
218 				 const DisabledInstancePorts *disable2)
219 {
220   return stringLess(network_->pathName(disable1->instance()),
221 		    network_->pathName(disable2->instance()));
222 }
223 
224 void
sortDisabledInstancePortsMap(DisabledInstancePortsMap * inst_map,Network * network,DisabledInstancePortsSeq & disables)225 sortDisabledInstancePortsMap(DisabledInstancePortsMap *inst_map,
226 			     Network *network,
227 			     DisabledInstancePortsSeq &disables)
228 {
229   DisabledInstancePortsMap::Iterator disabled_iter(inst_map);
230   while (disabled_iter.hasNext())
231     disables.push_back(disabled_iter.next());
232   sort(disables, DisabledInstPortsLess(network));
233 }
234 
235 ////////////////////////////////////////////////////////////////
236 
237 class LibertyPortPairNameLess
238 {
239 public:
240   bool operator()(const LibertyPortPair *pair1,
241 		  const LibertyPortPair *pair2);
242 };
243 
244 bool
operator ()(const LibertyPortPair * pair1,const LibertyPortPair * pair2)245 LibertyPortPairNameLess::operator()(const LibertyPortPair *pair1,
246 				    const LibertyPortPair *pair2)
247 {
248   const char *from1 = pair1->first->name();
249   const char *from2 = pair2->first->name();
250   const char *to1 = pair1->second->name();
251   const char *to2 = pair2->second->name();
252   return stringLess(from1, from2)
253     || (stringEq(from1, from2) && stringLess(to1, to2));
254 }
255 
256 void
sortLibertyPortPairSet(LibertyPortPairSet * sets,LibertyPortPairSeq & pairs)257 sortLibertyPortPairSet(LibertyPortPairSet *sets,
258 		       LibertyPortPairSeq &pairs)
259 {
260   LibertyPortPairSet::Iterator pair_iter(sets);
261   while (pair_iter.hasNext())
262     pairs.push_back(pair_iter.next());
263   sort(pairs, LibertyPortPairNameLess());
264 }
265 
266 }
267