1 /*
2 * CCvcDb.cc
3 *
4 * Copyright 2014-2020 D. Mitch Bailey cvc at shuharisystem dot com
5 *
6 * This file is part of cvc.
7 *
8 * cvc is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * cvc is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with cvc. If not, see <http://www.gnu.org/licenses/>.
20 *
21 * You can download cvc from https://github.com/d-m-bailey/cvc.git
22 */
23
24 #include "CCvcDb.hh"
25
26 #include "CCircuit.hh"
27 #include "CModel.hh"
28 #include "CDevice.hh"
29 #include "CPower.hh"
30 #include "CInstance.hh"
31 #include "CEventQueue.hh"
32 #include "CVirtualNet.hh"
33 #include "CConnection.hh"
34
35 extern set<modelType_t> FUSE_MODELS;
36 char RESISTOR_TEXT[] = " resistor"; // leading space to differentiate from normal signals
37
38 /**
39 * \brief Report shorts during logic simulation propagation that involve limited voltages.
40 *
41 * A limited voltage is an unknown simulation voltage with a known min/max value that indicates a current leak (short).
42 * For example, a 1.2V power signal propagated to a net that has a max voltage of 1.0V would be flagged as a leak.
43 * Note: if the propagated voltage and limited voltage differ by exactly Vth, the short is ignored. This is the expected result of mos diodes.
44 */
ReportSimShort(deviceId_t theDeviceId,voltage_t theMainVoltage,voltage_t theShortVoltage,string theCalculation)45 void CCvcDb::ReportSimShort(deviceId_t theDeviceId, voltage_t theMainVoltage, voltage_t theShortVoltage, string theCalculation) {
46 static CFullConnection myConnections;
47 MapDeviceNets(theDeviceId, myConnections);
48 voltage_t myMaxVoltage = max(theMainVoltage, theShortVoltage);
49 voltage_t myMinVoltage = min(theMainVoltage, theShortVoltage);
50 if ( abs(theMainVoltage - theShortVoltage) != abs(myConnections.device_p->model_p->Vth) &&
51 abs(theMainVoltage - theShortVoltage) > cvcParameters.cvcShortErrorThreshold ) {
52 if ( IncrementDeviceError(theDeviceId, LEAK) < cvcParameters.cvcCircuitErrorLimit || cvcParameters.cvcCircuitErrorLimit == 0 ) {
53 errorFile << "! Short Detected: " << PrintVoltage(myMaxVoltage) << " to " << PrintVoltage(myMinVoltage) << theCalculation << endl;
54 PrintDeviceWithAllConnections(deviceParent_v[theDeviceId], myConnections, errorFile);
55 errorFile << endl;
56 }
57 }
58 }
59
60 /**
61 * \brief Report shorts during logic simulation propagation.
62 *
63 * Variables controlling short error detection:
64 * cvcShortErrorThreshold: only report errors between voltages exceeding threshold.
65 * cvcLeakLimit: minimum leak current for short detection.
66 * myVthFlag: true if gate-source voltage difference is exactly Vth.
67 * myLeakCurrent: rough estimate of leak current.
68 * myUnrelatedFlag: true if leaks between shorted nets are prohibited.
69 * Note: leaks between external power are always errors if threshold = 0.
70 */
ReportShort(deviceId_t theDeviceId)71 void CCvcDb::ReportShort(deviceId_t theDeviceId) {
72 static CFullConnection myConnections;
73 MapDeviceNets(theDeviceId, myConnections);
74 voltage_t myMaxVoltage = max(myConnections.simSourceVoltage, myConnections.simDrainVoltage);
75 voltage_t myMinVoltage = min(myConnections.simSourceVoltage, myConnections.simDrainVoltage);
76 float myLeakCurrent;
77 bool myVthFlag;
78 if ( myConnections.simSourcePower_p->type[HIZ_BIT]
79 && myConnections.simSourcePower_p->IsRelatedPower(myConnections.simDrainPower_p, netVoltagePtr_v, simNet_v, simNet_v, false) ) return;
80 // no shorts from Hi-Z to expected leak path
81 if ( myConnections.simDrainPower_p->type[HIZ_BIT]
82 && myConnections.simDrainPower_p->IsRelatedPower(myConnections.simSourcePower_p, netVoltagePtr_v, simNet_v, simNet_v, false) ) return;
83 // no shorts from Hi-Z to expected leak path
84 if ( myMaxVoltage == UNKNOWN_VOLTAGE || myMinVoltage == UNKNOWN_VOLTAGE ) {
85 myLeakCurrent = 0;
86 myVthFlag = false;
87 } else {
88 myVthFlag = (IsNmos_(deviceType_v[theDeviceId]) && myConnections.simGateVoltage - myMinVoltage == myConnections.device_p->model_p->Vth) ||
89 (IsPmos_(deviceType_v[theDeviceId]) && myConnections.simGateVoltage - myMaxVoltage == myConnections.device_p->model_p->Vth);
90 myLeakCurrent = myConnections.EstimatedCurrent(myVthFlag);
91 }
92 bool myUnrelatedFlag = cvcParameters.cvcShortErrorThreshold == 0
93 && ! myConnections.simSourcePower_p->IsRelatedPower(myConnections.simDrainPower_p, netVoltagePtr_v, simNet_v, simNet_v, true); // no unrelated checks for real sim checks
94 if ( ( myMaxVoltage - myMinVoltage > cvcParameters.cvcShortErrorThreshold && ExceedsLeakLimit_(myLeakCurrent) ) // flag leaks with large current
95 || myUnrelatedFlag // flag leaks between unrelated power
96 || ( myMaxVoltage != myMinVoltage && ! myVthFlag // ignore leaks between same voltages or at Vth
97 && ( ( IsExternalPower_(myConnections.simSourcePower_p)
98 && IsExternalPower_(myConnections.simDrainPower_p)
99 && cvcParameters.cvcShortErrorThreshold == 0 ) // flag all leaks between power nets if threshold = 0
100 || myConnections.simSourcePower_p->flagAllShorts || myConnections.simDrainPower_p->flagAllShorts ) ) ) { // flag nets for calculated logic levels
101 if ( IncrementDeviceError(theDeviceId, LEAK) < cvcParameters.cvcCircuitErrorLimit || cvcParameters.cvcCircuitErrorLimit == 0 ) {
102 errorFile << "! Short Detected: " << PrintVoltage(myMaxVoltage) << " to " << PrintVoltage(myMinVoltage);
103 if ( myVthFlag ) errorFile << " at Vth ";
104 errorFile << " Estimated current: " << AddSiSuffix(myLeakCurrent) << "A" << endl;
105 if ( myUnrelatedFlag ) {
106 errorFile << "Unrelated power error" << endl;
107 }
108 PrintDeviceWithAllConnections(deviceParent_v[theDeviceId], myConnections, errorFile);
109 errorFile << endl;
110 }
111 }
112 }
113
114 /**
115 * \brief Check virtual net connection to see if reroute is necessary.
116 *
117 * When the source and drain final virtual net connections both point to the same net,
118 * this routine determines whether or not to change the drain connection
119 * by comparing the source connection to the next drain connection.
120 * NOTE: this calculation is NOT propagated to subsequent devices in the voltage path.
121 * Require:
122 * source net is defined terminal net
123 * drain net is not terminal net
124 * drain final net is defined net
125 */
CheckConnectionReroute(CEventQueue & theEventQueue,CConnection & theConnections,shortDirection_t theDirection)126 bool CCvcDb::CheckConnectionReroute(CEventQueue & theEventQueue, CConnection& theConnections, shortDirection_t theDirection) {
127 // return true if connection should be rerouted
128 netId_t myNextDrainNet;
129 CPower * mySourcePower_p;
130 resistance_t myDrainResistance;
131 if ( theDirection == DRAIN_TO_MASTER_SOURCE ) {
132 myNextDrainNet = theEventQueue.virtualNet_v[theConnections.drainId].nextNetId;
133 mySourcePower_p = netVoltagePtr_v[theConnections.sourceId].full;
134 myDrainResistance = theConnections.masterDrainNet.finalResistance;
135 } else { // swap source and drain
136 assert(theDirection == SOURCE_TO_MASTER_DRAIN);
137 myNextDrainNet = theEventQueue.virtualNet_v[theConnections.sourceId].nextNetId;
138 mySourcePower_p = netVoltagePtr_v[theConnections.drainId].full;
139 myDrainResistance = theConnections.masterSourceNet.finalResistance;
140 }
141 CPower * myNextDrainPower_p = netVoltagePtr_v[myNextDrainNet].full;
142 if ( ! theEventQueue.virtualNet_v.IsTerminal(myNextDrainNet) ) return true; // reroute if source is terminal, next drain not terminal
143 // both terminal
144 if ( myNextDrainPower_p->type[POWER_BIT] ) {
145 if ( ! mySourcePower_p->type[POWER_BIT] ) return false; // do not reroute if next drain is power, source not power
146 // both power. reroute if less resistance.
147 return (theConnections.resistance < myDrainResistance);
148 }
149 // next drain not power
150 if ( mySourcePower_p->type[POWER_BIT] ) return true; // reroute if source is power, next drain not power
151 // both not power. reroute if drain is calculated, source not calculated.
152 return (myNextDrainPower_p->type[theEventQueue.virtualNet_v.calculatedBit] && ! mySourcePower_p->type[theEventQueue.virtualNet_v.calculatedBit]);
153 }
154
IsPriorityDevice(CEventQueue & theEventQueue,modelType_t theModel)155 bool CCvcDb::IsPriorityDevice(CEventQueue& theEventQueue, modelType_t theModel) {
156 if ( theEventQueue.queueType == MIN_QUEUE && ! IsNmos_(theModel) ) return false;
157 if ( theEventQueue.queueType == MAX_QUEUE && ! IsPmos_(theModel) ) return false;
158 return true;
159 }
160
AlreadyShorted(CEventQueue & theEventQueue,deviceId_t theDeviceId,CConnection & theConnections)161 void CCvcDb::AlreadyShorted(CEventQueue& theEventQueue, deviceId_t theDeviceId, CConnection& theConnections) {
162 // add logic for equivalent voltage shorts.
163 static CVirtualNet myLastVirtualNet;
164 if ( theConnections.masterSourceNet.finalNetId == theConnections.masterDrainNet.finalNetId ) {
165 // no shifting on second pass causes looping. Only reroute direct connections.
166 if ( IsPriorityDevice(theEventQueue, deviceType_v[theConnections.deviceId]) ) {
167 if ( leakVoltageSet ) { // second pass. Only reroute direct connections
168 if ( ! theEventQueue.virtualNet_v.IsTerminal(theConnections.drainId)
169 && theEventQueue.virtualNet_v.IsTerminal(theConnections.sourceId)
170 && CheckConnectionReroute(theEventQueue, theConnections, DRAIN_TO_MASTER_SOURCE) ) { // direct connections have precedence
171 // lastUpdate changed due to virtual net rerouting
172 theEventQueue.virtualNet_v.lastUpdate++;
173 ShortNets(theEventQueue, theDeviceId, theConnections, DRAIN_TO_MASTER_SOURCE);
174 } else if ( ! theEventQueue.virtualNet_v.IsTerminal(theConnections.sourceId)
175 && theEventQueue.virtualNet_v.IsTerminal(theConnections.drainId)
176 && CheckConnectionReroute(theEventQueue, theConnections, SOURCE_TO_MASTER_DRAIN) ) { // direct connections have precedence
177 // lastUpdate changed due to virtual net rerouting
178 theEventQueue.virtualNet_v.lastUpdate++;
179 ShortNets(theEventQueue, theDeviceId, theConnections, SOURCE_TO_MASTER_DRAIN);
180 }
181 } else if ( ! theEventQueue.virtualNet_v.IsTerminal(theConnections.drainId)
182 && ( theEventQueue.virtualNet_v.IsTerminal(theConnections.sourceId) // direct connections have precedence
183 || theConnections.masterSourceNet.finalResistance + theConnections.resistance < theConnections.masterDrainNet.finalResistance ) ) {
184 myLastVirtualNet = theEventQueue.virtualNet_v[theConnections.drainId];
185 // lastUpdate changed due to virtual net rerouting
186 theEventQueue.virtualNet_v.lastUpdate++;
187 ShortNets(theEventQueue, theDeviceId, theConnections, DRAIN_TO_MASTER_SOURCE);
188 ShiftVirtualNets(theEventQueue, theConnections.drainId, myLastVirtualNet,
189 theConnections.masterSourceNet.finalResistance + theConnections.resistance, theConnections.masterDrainNet.finalResistance);
190 } else if ( ! theEventQueue.virtualNet_v.IsTerminal(theConnections.sourceId)
191 && ( theEventQueue.virtualNet_v.IsTerminal(theConnections.drainId) // direct connections have precedence
192 || theConnections.masterDrainNet.finalResistance + theConnections.resistance < theConnections.masterSourceNet.finalResistance ) ) {
193 myLastVirtualNet = theEventQueue.virtualNet_v[theConnections.sourceId];
194 // lastUpdate changed due to virtual net rerouting
195 theEventQueue.virtualNet_v.lastUpdate++;
196 ShortNets(theEventQueue, theDeviceId, theConnections, SOURCE_TO_MASTER_DRAIN);
197 ShiftVirtualNets(theEventQueue, theConnections.sourceId, myLastVirtualNet,
198 theConnections.masterDrainNet.finalResistance + theConnections.resistance, theConnections.masterSourceNet.finalResistance);
199 }
200 }
201 } else {
202 if ( theEventQueue.queueType == SIM_QUEUE ) {
203 if ( deviceType_v[theDeviceId] != FUSE_OFF ) {
204 // TODO: should do relative check and/or alias check
205 if ( theConnections.sourcePower_p->type[HIZ_BIT] && theConnections.sourcePower_p->relativeFriendly
206 && theConnections.sourcePower_p->family() == theConnections.drainPower_p->powerSignal() ) return;
207 if ( theConnections.drainPower_p->type[HIZ_BIT] && theConnections.drainPower_p->relativeFriendly
208 && theConnections.drainPower_p->family() == theConnections.sourcePower_p->powerSignal() ) return;
209 ReportShort(theDeviceId);
210 }
211 } else {
212 if ( theEventQueue.queueType == MIN_QUEUE ) {
213 // TODO: IsUnknown check may not be needed. Checked in calling function
214 if ( netStatus_v[theConnections.sourceId][NEEDS_MIN_CONNECTION] && IsKnownVoltage_(theConnections.drainVoltage)
215 && IsVerifiedPower(theConnections.masterDrainNet.finalNetId) ) {
216 voltage_t myMaxVoltage = MaxVoltage(theConnections.sourceId);
217 assert(netVoltagePtr_v[theConnections.sourceId].full);
218 CPower * myPower_p = netVoltagePtr_v[theConnections.sourceId].full;
219 if ( theConnections.sourceVoltage > theConnections.drainVoltage && ! ( leakVoltageSet && theConnections.drainPower_p->type[HIZ_BIT] ) ) {
220 // ignore pull downs to HI-Z power in second pass
221 if ( ! myPower_p->extraData ) myPower_p->extraData = new CExtraPowerData;
222 myPower_p->extraData->pullDownVoltage = theConnections.drainVoltage;
223 netStatus_v[theConnections.sourceId][NEEDS_MIN_CONNECTION] = false;
224 if ( gDebug_cvc ) cout << "DEBUG: removed min connection check for net: " << theConnections.sourceId << " "
225 << theConnections.sourceVoltage << ">" << theConnections.drainVoltage << endl;
226 } else if ( theConnections.sourceVoltage == theConnections.drainVoltage
227 && theConnections.drainVoltage == myMaxVoltage && ! netStatus_v[theConnections.drainId][NEEDS_MIN_CONNECTION] ) {
228 // handles propagation through mos switch that might get deleted in second pass for HiZ power. (needs verification)
229 if ( ! myPower_p->extraData ) myPower_p->extraData = new CExtraPowerData;
230 myPower_p->extraData->pullDownVoltage = theConnections.drainVoltage;
231 netStatus_v[theConnections.sourceId][NEEDS_MIN_CONNECTION] = false;
232 if ( gDebug_cvc ) cout << "DEBUG: removed matching min connection check for net: " << theConnections.sourceId << " "
233 << theConnections.sourceVoltage << endl;
234 } else if ( ! leakVoltageSet
235 && ( ( IsNmos_(deviceType_v[theDeviceId]) && LastNmosConnection(MIN_PENDING, theConnections.sourceId) )
236 || theConnections.device_p->IsResistor() ) ) {
237 // remove calculated net and reroute to drain. only for initial power prop.
238 if ( ! myPower_p->extraData ) myPower_p->extraData = new CExtraPowerData;
239 myPower_p->extraData->pullDownVoltage = theConnections.drainVoltage;
240 theEventQueue.virtualNet_v.Set(theConnections.sourceId, theConnections.drainId, theConnections.resistance, ++theEventQueue.virtualNet_v.lastUpdate);
241 CheckResistorOverflow_(theEventQueue.virtualNet_v[theConnections.sourceId].finalResistance, theConnections.sourceId, logFile);
242 if ( theConnections.sourceVoltage > theConnections.drainVoltage ) {
243 netStatus_v[theConnections.sourceId][NEEDS_MIN_CONNECTION] = false;
244 if ( gDebug_cvc ) cout << "DEBUG: rerouted min connection check for net: " << theConnections.sourceId << endl;
245 }
246 }
247 }
248 if ( netStatus_v[theConnections.drainId][NEEDS_MIN_CONNECTION] && IsKnownVoltage_(theConnections.sourceVoltage)
249 && IsVerifiedPower(theConnections.masterSourceNet.finalNetId) ) {
250 voltage_t myMaxVoltage = MaxVoltage(theConnections.drainId);
251 assert(netVoltagePtr_v[theConnections.drainId].full);
252 CPower * myPower_p = netVoltagePtr_v[theConnections.drainId].full;
253 if ( theConnections.drainVoltage > theConnections.sourceVoltage && ! ( leakVoltageSet && theConnections.sourcePower_p->type[HIZ_BIT] ) ) {
254 // ignore pull downs to HI-Z power in second pass
255 if ( ! myPower_p->extraData ) myPower_p->extraData = new CExtraPowerData;
256 myPower_p->extraData->pullDownVoltage = theConnections.sourceVoltage;
257 netStatus_v[theConnections.drainId][NEEDS_MIN_CONNECTION] = false;
258 if ( gDebug_cvc ) cout << "DEBUG: removed min connection check for net: " << theConnections.drainId << " "
259 << theConnections.drainVoltage << ">" << theConnections.sourceVoltage << endl;
260 } else if ( theConnections.sourceVoltage == theConnections.drainVoltage
261 && theConnections.sourceVoltage == myMaxVoltage && ! netStatus_v[theConnections.sourceId][NEEDS_MIN_CONNECTION] ) {
262 // handles propagation through mos switch that might get deleted in second pass for HiZ power. (needs verification)
263 if ( ! myPower_p->extraData ) myPower_p->extraData = new CExtraPowerData;
264 myPower_p->extraData->pullDownVoltage = theConnections.sourceVoltage;
265 netStatus_v[theConnections.drainId][NEEDS_MIN_CONNECTION] = false;
266 if ( gDebug_cvc ) cout << "DEBUG: removed matching min connection check for net: " << theConnections.drainId << " "
267 << theConnections.drainVoltage << endl;
268 } else if ( ! leakVoltageSet
269 && ( ( IsNmos_(deviceType_v[theDeviceId]) && LastNmosConnection(MIN_PENDING, theConnections.drainId) )
270 || theConnections.device_p->IsResistor() ) ) {
271 // remove calculated net and reroute to drain. only for initial power prop.
272 if ( ! myPower_p->extraData ) myPower_p->extraData = new CExtraPowerData;
273 myPower_p->extraData->pullDownVoltage = theConnections.sourceVoltage;
274 theEventQueue.virtualNet_v.Set(theConnections.drainId, theConnections.sourceId, theConnections.resistance, ++theEventQueue.virtualNet_v.lastUpdate);
275 CheckResistorOverflow_(theEventQueue.virtualNet_v[theConnections.drainId].finalResistance, theConnections.drainId, logFile);
276 if ( theConnections.drainVoltage > theConnections.sourceVoltage ) {
277 netStatus_v[theConnections.drainId][NEEDS_MIN_CONNECTION] = false;
278 if ( gDebug_cvc ) cout << "DEBUG: rerouted min connection check for net: " << theConnections.drainId << endl;
279 }
280 }
281
282 }
283 }
284 if ( theEventQueue.queueType == MAX_QUEUE ) {
285 if ( netStatus_v[theConnections.sourceId][NEEDS_MAX_CONNECTION] && IsKnownVoltage_(theConnections.drainVoltage)
286 && IsVerifiedPower(theConnections.masterDrainNet.finalNetId) ) {
287 voltage_t myMinVoltage = MinVoltage(theConnections.sourceId);
288 assert(netVoltagePtr_v[theConnections.sourceId].full);
289 CPower * myPower_p = netVoltagePtr_v[theConnections.sourceId].full;
290 if ( theConnections.sourceVoltage < theConnections.drainVoltage && ! ( leakVoltageSet && theConnections.drainPower_p->type[HIZ_BIT] ) ) {
291 // ignore pull ups to HI-Z power in second pass
292 if ( ! myPower_p->extraData ) myPower_p->extraData = new CExtraPowerData;
293 myPower_p->extraData->pullUpVoltage = theConnections.drainVoltage;
294 netStatus_v[theConnections.sourceId][NEEDS_MAX_CONNECTION] = false;
295 if ( gDebug_cvc ) cout << "DEBUG: removed max connection check for net: " << theConnections.sourceId << " "
296 << theConnections.sourceVoltage << "<" << theConnections.drainVoltage << endl;
297 } else if ( theConnections.sourceVoltage == theConnections.drainVoltage
298 && theConnections.drainVoltage == myMinVoltage && ! netStatus_v[theConnections.drainId][NEEDS_MAX_CONNECTION] ) {
299 // handles propagation through mos switch that might get deleted in second pass for HiZ power. (needs verification)
300 if ( ! myPower_p->extraData ) myPower_p->extraData = new CExtraPowerData;
301 myPower_p->extraData->pullUpVoltage = theConnections.drainVoltage;
302 netStatus_v[theConnections.sourceId][NEEDS_MAX_CONNECTION] = false;
303 if ( gDebug_cvc ) cout << "DEBUG: removed matching max connection check for net: " << theConnections.sourceId << " "
304 << theConnections.sourceVoltage << endl;
305 } else if ( ! leakVoltageSet
306 && ( ( IsPmos_(deviceType_v[theDeviceId]) && LastPmosConnection(MAX_PENDING, theConnections.sourceId) )
307 || theConnections.device_p->IsResistor() ) ) {
308 // remove calculated net and reroute to drain. only for initial power prop.
309 if ( ! myPower_p->extraData ) myPower_p->extraData = new CExtraPowerData;
310 myPower_p->extraData->pullUpVoltage = theConnections.drainVoltage;
311 theEventQueue.virtualNet_v.Set(theConnections.sourceId, theConnections.drainId, theConnections.resistance, ++theEventQueue.virtualNet_v.lastUpdate);
312 CheckResistorOverflow_(theEventQueue.virtualNet_v[theConnections.sourceId].finalResistance, theConnections.sourceId, logFile);
313 if ( theConnections.sourceVoltage < theConnections.drainVoltage ) {
314 netStatus_v[theConnections.sourceId][NEEDS_MAX_CONNECTION] = false;
315 if ( gDebug_cvc ) cout << "DEBUG: rerouted max connection check for net: " << theConnections.sourceId << endl;
316 }
317 }
318 }
319 if ( netStatus_v[theConnections.drainId][NEEDS_MAX_CONNECTION] && IsKnownVoltage_(theConnections.sourceVoltage)
320 && IsVerifiedPower(theConnections.masterSourceNet.finalNetId) ) {
321 voltage_t myMinVoltage = MinVoltage(theConnections.drainId);
322 assert(netVoltagePtr_v[theConnections.drainId].full);
323 CPower * myPower_p = netVoltagePtr_v[theConnections.drainId].full;
324 if ( theConnections.drainVoltage < theConnections.sourceVoltage && ! ( leakVoltageSet && theConnections.sourcePower_p->type[HIZ_BIT] ) ) {
325 // ignore pull ups to HI-Z power in second pass
326 if ( ! myPower_p->extraData ) myPower_p->extraData = new CExtraPowerData;
327 myPower_p->extraData->pullUpVoltage = theConnections.sourceVoltage;
328 netStatus_v[theConnections.drainId][NEEDS_MAX_CONNECTION] = false;
329 if ( gDebug_cvc ) cout << "DEBUG: removed max connection check for net: " << theConnections.drainId << " "
330 << theConnections.drainVoltage << "<" << theConnections.sourceVoltage << endl;
331 } else if ( theConnections.sourceVoltage == theConnections.drainVoltage
332 && theConnections.drainVoltage == myMinVoltage && ! netStatus_v[theConnections.sourceId][NEEDS_MAX_CONNECTION] ) {
333 // handles propagation through mos switch that might get deleted in second pass for HiZ power. (needs verification)
334 if ( ! myPower_p->extraData ) myPower_p->extraData = new CExtraPowerData;
335 myPower_p->extraData->pullUpVoltage = theConnections.sourceVoltage;
336 netStatus_v[theConnections.drainId][NEEDS_MAX_CONNECTION] = false;
337 if ( gDebug_cvc ) cout << "DEBUG: removed matching max connection check for net: " << theConnections.drainId << " "
338 << theConnections.drainVoltage << endl;
339 } else if ( ! leakVoltageSet
340 && ( ( IsPmos_(deviceType_v[theDeviceId]) && LastPmosConnection(MAX_PENDING, theConnections.drainId) )
341 || theConnections.device_p->IsResistor() ) ) {
342 // remove calculated net and reroute to drain. only for initial power prop.
343 if ( ! myPower_p->extraData ) myPower_p->extraData = new CExtraPowerData;
344 myPower_p->extraData->pullUpVoltage = theConnections.sourceVoltage;
345 theEventQueue.virtualNet_v.Set(theConnections.drainId, theConnections.sourceId, theConnections.resistance, ++theEventQueue.virtualNet_v.lastUpdate);
346 CheckResistorOverflow_(theEventQueue.virtualNet_v[theConnections.drainId].finalResistance, theConnections.drainId, logFile);
347 if ( theConnections.drainVoltage < theConnections.sourceVoltage ) {
348 netStatus_v[theConnections.drainId][NEEDS_MAX_CONNECTION] = false;
349 if ( gDebug_cvc ) cout << "DEBUG: rerouted max connection check for net: " << theConnections.drainId << endl;
350 }
351 }
352 }
353 }
354 // TODO: family check not correct. need to check for relatives
355 if ( theConnections.sourcePower_p->family() != theConnections.drainPower_p->family() ) {
356 if (gDebug_cvc) cout << "adding leak" << endl;
357 theEventQueue.AddLeak(theDeviceId, theConnections);
358 }
359 }
360 }
361 deviceStatus_v[theDeviceId][theEventQueue.inactiveBit] = true;
362 }
363
VoltageConflict(CEventQueue & theEventQueue,deviceId_t theDeviceId,CConnection & theConnections)364 bool CCvcDb::VoltageConflict(CEventQueue& theEventQueue, deviceId_t theDeviceId, CConnection& theConnections) {
365 // first MIN/MAX pass propagate to unknown open nets. SIM and second MIN/MAX cause error.
366 if ( ! leakVoltageSet && ( theConnections.sourceVoltage == UNKNOWN_VOLTAGE || theConnections.drainVoltage == UNKNOWN_VOLTAGE ) ) return false;
367 if ( theConnections.IsUnknownSourceVoltage() || theConnections.IsUnknownDrainVoltage() ) return false;
368 // check voltage family conflicts later
369 if ( theEventQueue.queueType == SIM_QUEUE && IsMos_(deviceType_v[theDeviceId]) && theConnections.gateVoltage == UNKNOWN_VOLTAGE ) return false;
370
371 if (gDebug_cvc) cout << "already shorted VC " << gEventQueueTypeMap[theEventQueue.queueType] << " " << theDeviceId << endl;
372 // activate voltages
373 deviceStatus_v[theDeviceId][theEventQueue.pendingBit] = true;
374 if ( theEventQueue.queueType == MIN_QUEUE ) {
375 if ( theConnections.drainPower_p && theConnections.drainPower_p->minVoltage != UNKNOWN_VOLTAGE &&
376 ! theConnections.drainPower_p->active[MIN_ACTIVE] && ! theConnections.drainPower_p->active[MIN_IGNORE] ) {
377 if ( theConnections.sourceVoltage <= theConnections.drainVoltage ) {
378 theConnections.drainPower_p->active[MIN_ACTIVE] = true;
379 EnqueueAttachedDevices(theEventQueue, theConnections.drainId, theConnections.drainVoltage);
380 } else if ( IsGreaterVoltage_(MinLeakVoltage(theConnections.drainId), theConnections.drainVoltage) ) {
381 reportFile << "WARNING: min voltage " << theConnections.drainPower_p->minVoltage << " ignored for " << NetName(theConnections.drainId, PRINT_CIRCUIT_OFF) \
382 << " at " << DeviceName(theDeviceId, PRINT_CIRCUIT_ON) << endl;
383 }
384 } else if ( theConnections.sourcePower_p && theConnections.sourcePower_p->minVoltage != UNKNOWN_VOLTAGE &&
385 ! theConnections.sourcePower_p->active[MIN_ACTIVE] && ! theConnections.sourcePower_p->active[MIN_IGNORE] ) {
386 if ( theConnections.drainVoltage <= theConnections.sourceVoltage ) {
387 theConnections.sourcePower_p->active[MIN_ACTIVE] = true;
388 EnqueueAttachedDevices(theEventQueue, theConnections.sourceId, theConnections.sourceVoltage);
389 } else if ( IsGreaterVoltage_(MinLeakVoltage(theConnections.sourceId), theConnections.sourceVoltage) ) {
390 reportFile << "WARNING: min voltage " << theConnections.sourcePower_p->minVoltage << " ignored for " << NetName(theConnections.sourceId, PRINT_CIRCUIT_OFF) \
391 << " at " << DeviceName(theDeviceId, PRINT_CIRCUIT_ON) << endl;
392 }
393 }
394 // Unset min checks
395 CStatus & myDrainStatus = netStatus_v[theConnections.drainId];
396 CStatus & mySourceStatus = netStatus_v[theConnections.sourceId];
397 bool mySourceVerified = ! (mySourceStatus[NEEDS_MIN_CHECK] || mySourceStatus[NEEDS_MIN_CONNECTION]);
398 bool myDrainVerified = ! (myDrainStatus[NEEDS_MIN_CHECK] || myDrainStatus[NEEDS_MIN_CONNECTION]);
399 if ( ( myDrainStatus[NEEDS_MIN_CHECK] || myDrainStatus[NEEDS_MIN_CONNECTION] )
400 && theConnections.sourceVoltage != UNKNOWN_VOLTAGE && theConnections.drainVoltage != UNKNOWN_VOLTAGE
401 && mySourceVerified
402 && theConnections.drainVoltage > theConnections.sourceVoltage ) {
403 if ( gDebug_cvc ) cout << "DEBUG: Removed min check for net " << theConnections.drainId
404 << "(" << theConnections.drainVoltage << ") from " << theConnections.sourceId << "(" << theConnections.sourceVoltage << ")" << endl;
405 assert(netVoltagePtr_v[theConnections.drainId].full);
406 CPower * myPower_p = netVoltagePtr_v[theConnections.drainId].full;
407 if ( ! myPower_p->extraData ) myPower_p->extraData = new CExtraPowerData;
408 myPower_p->extraData->pullDownVoltage = theConnections.sourceVoltage;
409 myDrainStatus[NEEDS_MIN_CHECK] = myDrainStatus[NEEDS_MIN_CONNECTION] = false;
410 }
411 if ( ( mySourceStatus[NEEDS_MIN_CHECK] || mySourceStatus[NEEDS_MIN_CONNECTION] )
412 && theConnections.sourceVoltage != UNKNOWN_VOLTAGE && theConnections.drainVoltage != UNKNOWN_VOLTAGE
413 && myDrainVerified
414 && theConnections.sourceVoltage > theConnections.drainVoltage ) {
415 if ( gDebug_cvc ) cout << "DEBUG: Removed min check for net " << theConnections.sourceId
416 << "(" << theConnections.sourceVoltage << ") from " << theConnections.drainId << "(" << theConnections.drainVoltage << ")" << endl;
417 assert(netVoltagePtr_v[theConnections.sourceId].full);
418 CPower * myPower_p = netVoltagePtr_v[theConnections.sourceId].full;
419 if ( ! myPower_p->extraData ) myPower_p->extraData = new CExtraPowerData;
420 myPower_p->extraData->pullDownVoltage = theConnections.drainVoltage;
421 mySourceStatus[NEEDS_MIN_CHECK] = mySourceStatus[NEEDS_MIN_CONNECTION] = false;
422 }
423 // for mos connected as diode with source/drain known. Add max voltage propagation/check
424 if ( IsMos_(deviceType_v[theDeviceId]) ) {
425 voltage_t mySourceVoltage;
426 netId_t myTargetNetId = UNKNOWN_NET;
427 netId_t mySourceNetId;
428 calculationType_t myCalculationType;
429 if ( theConnections.sourceId == theConnections.gateId ) {
430 myTargetNetId = theConnections.sourceId;
431 mySourceNetId = theConnections.drainId;
432 mySourceVoltage = theConnections.drainVoltage;
433 myCalculationType = theConnections.drainPower_p->minCalculationType;
434 } else if ( theConnections.drainId == theConnections.gateId ) {
435 myTargetNetId = theConnections.drainId;
436 mySourceNetId = theConnections.sourceId;
437 mySourceVoltage = theConnections.sourceVoltage;
438 myCalculationType = theConnections.sourcePower_p->minCalculationType;
439 }
440 if ( myTargetNetId != UNKNOWN_NET ) {
441 voltage_t myExpectedVoltage = mySourceVoltage + theConnections.device_p->model_p->Vth;
442 CConnection myMaxConnections;
443 MapDeviceNets(theConnections.deviceId, maxEventQueue, myMaxConnections);
444 if ( myCalculationType != DOWN_CALCULATION ) { // do not cross propagate calculated voltages
445 if ( myMaxConnections.gateVoltage == UNKNOWN_VOLTAGE ) {
446 EnqueueAttachedDevices(maxEventQueue, myTargetNetId, myExpectedVoltage); // enqueue in opposite queue
447 } else if ( ! myMaxConnections.gatePower_p->type[HIZ_BIT]
448 && ((myMaxConnections.gateVoltage > myExpectedVoltage && IsNmos_(deviceType_v[theConnections.deviceId]))
449 || (myMaxConnections.gateVoltage < myExpectedVoltage && IsPmos_(deviceType_v[theConnections.deviceId])) ) ) {
450 float myLeakCurrent = myMaxConnections.EstimatedMosDiodeCurrent(mySourceVoltage, theConnections);
451 bool myCheckLeakCurrent = cvcParameters.cvcMosDiodeErrorThreshold == 0
452 || abs(myMaxConnections.gateVoltage - myExpectedVoltage) > cvcParameters.cvcMosDiodeErrorThreshold;
453 if ( myCheckLeakCurrent && ExceedsLeakLimit_(myLeakCurrent) && netVoltagePtr_v[mySourceNetId].full ) { // no errors if not direct propagation
454 PrintMaxVoltageConflict(myTargetNetId, myMaxConnections, myExpectedVoltage, myLeakCurrent);
455 }
456 }
457 }
458 }
459 }
460 } else if ( theEventQueue.queueType == MAX_QUEUE ) {
461 if ( theConnections.drainPower_p && theConnections.drainPower_p->maxVoltage != UNKNOWN_VOLTAGE &&
462 ! theConnections.drainPower_p->active[MAX_ACTIVE] && ! theConnections.drainPower_p->active[MAX_IGNORE] ) {
463 if ( theConnections.drainVoltage <= theConnections.sourceVoltage ) {
464 theConnections.drainPower_p->active[MAX_ACTIVE] = true;
465 EnqueueAttachedDevices(theEventQueue, theConnections.drainId, theConnections.drainVoltage);
466 } else if ( IsLesserVoltage_(MaxLeakVoltage(theConnections.drainId), theConnections.drainVoltage) ) {
467 reportFile << "WARNING: max voltage " << theConnections.drainPower_p->maxVoltage << " ignored for " << NetName(theConnections.drainId, PRINT_CIRCUIT_OFF, PRINT_HIERARCHY_OFF) \
468 << " at " << DeviceName(theDeviceId, PRINT_CIRCUIT_ON) << endl;
469 }
470 } else if ( theConnections.sourcePower_p && theConnections.sourcePower_p->maxVoltage != UNKNOWN_VOLTAGE &&
471 ! theConnections.sourcePower_p->active[MAX_ACTIVE] && ! theConnections.sourcePower_p->active[MAX_IGNORE] ) {
472 if ( theConnections.sourceVoltage <= theConnections.drainVoltage ) {
473 theConnections.sourcePower_p->active[MAX_ACTIVE] = true;
474 EnqueueAttachedDevices(theEventQueue, theConnections.sourceId, theConnections.sourceVoltage);
475 } else if ( IsLesserVoltage_(MaxLeakVoltage(theConnections.sourceId), theConnections.sourceVoltage) ) {
476 reportFile << "WARNING: max voltage " << theConnections.sourcePower_p->maxVoltage << " ignored for " << NetName(theConnections.sourceId, PRINT_CIRCUIT_OFF, PRINT_HIERARCHY_OFF) \
477 << " at " << DeviceName(theDeviceId, PRINT_CIRCUIT_ON) << endl;
478 }
479 }
480 // Unset max checks
481 CStatus & myDrainStatus = netStatus_v[theConnections.drainId];
482 CStatus & mySourceStatus = netStatus_v[theConnections.sourceId];
483 bool mySourceVerified = ! (mySourceStatus[NEEDS_MAX_CHECK] || mySourceStatus[NEEDS_MAX_CONNECTION]);
484 bool myDrainVerified = ! (myDrainStatus[NEEDS_MAX_CHECK] || myDrainStatus[NEEDS_MAX_CONNECTION]);
485 if ( ( myDrainStatus[NEEDS_MAX_CHECK] || myDrainStatus[NEEDS_MAX_CONNECTION] )
486 && theConnections.sourceVoltage != UNKNOWN_VOLTAGE && theConnections.drainVoltage != UNKNOWN_VOLTAGE
487 && mySourceVerified
488 && theConnections.drainVoltage < theConnections.sourceVoltage ) {
489 if ( gDebug_cvc ) cout << "DEBUG: Removed max check for net " << theConnections.drainId
490 << "(" << theConnections.drainVoltage << ") from " << theConnections.sourceId << "(" << theConnections.sourceVoltage << ")" << endl;
491 assert(netVoltagePtr_v[theConnections.drainId].full);
492 CPower * myPower_p = netVoltagePtr_v[theConnections.drainId].full;
493 if ( ! myPower_p->extraData ) myPower_p->extraData = new CExtraPowerData;
494 myPower_p->extraData->pullUpVoltage = theConnections.sourceVoltage;
495 myDrainStatus[NEEDS_MAX_CHECK] = myDrainStatus[NEEDS_MAX_CONNECTION] = false;
496 }
497 if ( ( mySourceStatus[NEEDS_MAX_CHECK] || mySourceStatus[NEEDS_MAX_CONNECTION] )
498 && theConnections.sourceVoltage != UNKNOWN_VOLTAGE && theConnections.drainVoltage != UNKNOWN_VOLTAGE
499 && myDrainVerified
500 && theConnections.sourceVoltage < theConnections.drainVoltage ) {
501 if ( gDebug_cvc ) cout << "DEBUG: Removed max check for net " << theConnections.sourceId
502 << "(" << theConnections.sourceVoltage << ") from " << theConnections.drainId << "(" << theConnections.drainVoltage << ")" << endl;
503 assert(netVoltagePtr_v[theConnections.sourceId].full);
504 CPower * myPower_p = netVoltagePtr_v[theConnections.sourceId].full;
505 if ( ! myPower_p->extraData ) myPower_p->extraData = new CExtraPowerData;
506 myPower_p->extraData->pullUpVoltage = theConnections.drainVoltage;
507 mySourceStatus[NEEDS_MAX_CHECK] = mySourceStatus[NEEDS_MAX_CONNECTION] = false;
508 }
509
510 // for mos connected as diode with source/drain known. Add min voltage propagation/check
511 if ( IsMos_(deviceType_v[theDeviceId]) ) {
512 voltage_t mySourceVoltage;
513 netId_t myTargetNetId = UNKNOWN_NET;
514 netId_t mySourceNetId;
515 calculationType_t myCalculationType;
516 if ( theConnections.sourceId == theConnections.gateId ) {
517 myTargetNetId = theConnections.sourceId;
518 mySourceNetId = theConnections.drainId;
519 mySourceVoltage = theConnections.drainVoltage;
520 myCalculationType = theConnections.drainPower_p->maxCalculationType;
521 } else if ( theConnections.drainId == theConnections.gateId ) {
522 myTargetNetId = theConnections.drainId;
523 mySourceNetId = theConnections.sourceId;
524 mySourceVoltage = theConnections.sourceVoltage;
525 myCalculationType = theConnections.sourcePower_p->maxCalculationType;
526 }
527 if ( myTargetNetId != UNKNOWN_NET ) {
528 voltage_t myExpectedVoltage = mySourceVoltage + theConnections.device_p->model_p->Vth;
529 CConnection myMinConnections;
530 MapDeviceNets(theConnections.deviceId, minEventQueue, myMinConnections);
531 if ( myCalculationType != UP_CALCULATION ) { // do not cross propagate calculated voltages
532 if ( myMinConnections.gateVoltage == UNKNOWN_VOLTAGE ) {
533 EnqueueAttachedDevices(minEventQueue, myTargetNetId, myExpectedVoltage); // enqueue in opposite queue
534 } else if ( ! myMinConnections.gatePower_p->type[HIZ_BIT]
535 && ((myMinConnections.gateVoltage > myExpectedVoltage && IsNmos_(deviceType_v[theConnections.deviceId]))
536 || (myMinConnections.gateVoltage < myExpectedVoltage && IsPmos_(deviceType_v[theConnections.deviceId])) ) ) {
537 float myLeakCurrent = myMinConnections.EstimatedMosDiodeCurrent(mySourceVoltage, theConnections);
538 bool myCheckLeakCurrent = cvcParameters.cvcMosDiodeErrorThreshold == 0
539 || abs(myMinConnections.gateVoltage - myExpectedVoltage) > cvcParameters.cvcMosDiodeErrorThreshold;
540 if ( myCheckLeakCurrent && ExceedsLeakLimit_(myLeakCurrent) && netVoltagePtr_v[mySourceNetId].full ) { // no errors if not direct propagation
541 PrintMinVoltageConflict(myTargetNetId, myMinConnections, myExpectedVoltage, myLeakCurrent);
542 }
543 }
544 }
545 }
546 }
547 }
548 deviceStatus_v[theDeviceId][theEventQueue.pendingBit] = false;
549 AlreadyShorted(theEventQueue, theDeviceId, theConnections);
550
551 return true;
552 }
553
TopologicallyOffMos(eventQueue_t theQueueType,modelType_t theModelType,CConnection & theConnections)554 bool CCvcDb::TopologicallyOffMos(eventQueue_t theQueueType, modelType_t theModelType, CConnection& theConnections) {
555 if ( (theQueueType == MAX_QUEUE && IsPmos_(theModelType)) || (theQueueType == MIN_QUEUE && IsNmos_(theModelType)) ) {
556 if ( theConnections.drainVoltage == UNKNOWN_VOLTAGE ) return theConnections.gateId == theConnections.sourceId;
557 if ( theConnections.sourceVoltage == UNKNOWN_VOLTAGE ) return theConnections.gateId == theConnections.drainId;
558 } else if ( (theQueueType == MAX_QUEUE && IsNmos_(theModelType)) || (theQueueType == MIN_QUEUE && IsPmos_(theModelType)) ) {
559 if ( theConnections.drainVoltage == UNKNOWN_VOLTAGE ) return theConnections.gateId == theConnections.drainId;
560 if ( theConnections.sourceVoltage == UNKNOWN_VOLTAGE ) return theConnections.gateId == theConnections.sourceId;
561 }
562 return false;
563 }
564
IsOffMos(eventQueue_t theQueueType,deviceId_t theDeviceId,CConnection & theConnections,voltage_t theVoltage)565 bool CCvcDb::IsOffMos(eventQueue_t theQueueType, deviceId_t theDeviceId, CConnection& theConnections, voltage_t theVoltage) {
566 if ( TopologicallyOffMos(theQueueType, deviceType_v[theDeviceId], theConnections) ) {
567 // TODO: possibly ignore for queue type
568 // IgnoreDevice(theDeviceId);
569 return true;
570 }
571 if ( theConnections.sourceVoltage == theVoltage || theConnections.drainVoltage == theVoltage ) {
572 // TODO: Possible ordering problem. change to min/max Leak?
573 if ( theQueueType == MAX_QUEUE && IsPmos_(deviceType_v[theDeviceId]) ) {
574 voltage_t myMinGate = MinVoltage(theConnections.gateId);
575 if ( myMinGate != UNKNOWN_VOLTAGE && myMinGate > theVoltage + theConnections.device_p->model_p->Vth ) return true;
576 }
577 if ( theQueueType == MIN_QUEUE && IsNmos_(deviceType_v[theDeviceId]) ) {
578 voltage_t myMaxGate = MaxVoltage(theConnections.gateId);
579 if ( myMaxGate != UNKNOWN_VOLTAGE && myMaxGate < theVoltage + theConnections.device_p->model_p->Vth ) return true;
580 }
581 }
582 if ( theQueueType == SIM_QUEUE ) {
583 if ( IsPmos_(deviceType_v[theDeviceId]) ) {
584 voltage_t myGateVoltage = ( theConnections.gateVoltage == UNKNOWN_VOLTAGE ) ? MinVoltage(theConnections.gateId) : theConnections.gateVoltage;
585 voltage_t mySourceVoltage = ( theConnections.sourceVoltage == UNKNOWN_VOLTAGE ) ? MaxLeakVoltage(theConnections.sourceId) : theConnections.sourceVoltage;
586 voltage_t myDrainVoltage = ( theConnections.drainVoltage == UNKNOWN_VOLTAGE ) ? MaxLeakVoltage(theConnections.drainId) : theConnections.drainVoltage;
587 if ( myGateVoltage == UNKNOWN_VOLTAGE || mySourceVoltage == UNKNOWN_VOLTAGE || myDrainVoltage == UNKNOWN_VOLTAGE ) return false;
588 bool mySourceOff = myGateVoltage > mySourceVoltage + theConnections.device_p->model_p->Vth;
589 bool myDrainOff = myGateVoltage > myDrainVoltage + theConnections.device_p->model_p->Vth;
590 if ( theConnections.sourceVoltage == UNKNOWN_VOLTAGE && myDrainOff && ! mySourceOff && maxNet_v[theConnections.sourceId].nextNetId == theConnections.drainId ) return true; // prevents vth drops back through mos.
591 if ( theConnections.drainVoltage == UNKNOWN_VOLTAGE && ! myDrainOff && mySourceOff && maxNet_v[theConnections.drainId].nextNetId == theConnections.sourceId ) return true; // prevents vth drops back through mos.
592 if ( mySourceOff && myDrainOff ) return true;
593 }
594 if ( IsNmos_(deviceType_v[theDeviceId]) ) {
595 voltage_t myGateVoltage = ( theConnections.gateVoltage == UNKNOWN_VOLTAGE ) ? MaxVoltage(theConnections.gateId) : theConnections.gateVoltage;
596 voltage_t mySourceVoltage = ( theConnections.sourceVoltage == UNKNOWN_VOLTAGE ) ? MinLeakVoltage(theConnections.sourceId) : theConnections.sourceVoltage;
597 voltage_t myDrainVoltage = ( theConnections.drainVoltage == UNKNOWN_VOLTAGE ) ? MinLeakVoltage(theConnections.drainId) : theConnections.drainVoltage;
598 if ( myGateVoltage == UNKNOWN_VOLTAGE || mySourceVoltage == UNKNOWN_VOLTAGE || myDrainVoltage == UNKNOWN_VOLTAGE ) return false;
599 bool mySourceOff = myGateVoltage < mySourceVoltage + theConnections.device_p->model_p->Vth;
600 bool myDrainOff = myGateVoltage < myDrainVoltage + theConnections.device_p->model_p->Vth;
601 if ( theConnections.sourceVoltage == UNKNOWN_VOLTAGE && myDrainOff && ! mySourceOff && minNet_v[theConnections.sourceId].nextNetId == theConnections.drainId ) return true; // prevents vth drops back through mos.
602 if ( theConnections.drainVoltage == UNKNOWN_VOLTAGE && ! myDrainOff && mySourceOff && minNet_v[theConnections.drainId].nextNetId == theConnections.sourceId ) return true; // prevents vth drops back through mos.
603 if ( mySourceOff && myDrainOff ) return true; }
604 }
605 return false;
606 }
607
LastNmosConnection(deviceStatus_t thePendingBit,netId_t theNetId)608 bool CCvcDb::LastNmosConnection(deviceStatus_t thePendingBit, netId_t theNetId) {
609 int myConnectionCount = 0;
610 for ( deviceId_t device_it = firstSource_v[theNetId]; device_it != UNKNOWN_DEVICE; device_it = nextSource_v[device_it] ) {
611 if ( IsNmos_(deviceType_v[device_it]) && deviceStatus_v[device_it][thePendingBit] ) {
612 if ( ++myConnectionCount > 1 ) return false;
613 }
614 }
615 for ( deviceId_t device_it = firstDrain_v[theNetId]; device_it != UNKNOWN_DEVICE; device_it = nextDrain_v[device_it] ) {
616 if ( IsNmos_(deviceType_v[device_it]) && deviceStatus_v[device_it][thePendingBit] ) {
617 if ( ++myConnectionCount > 1 ) return false;
618 }
619 }
620 return ( myConnectionCount < 2 );
621 }
622
LastPmosConnection(deviceStatus_t thePendingBit,netId_t theNetId)623 bool CCvcDb::LastPmosConnection(deviceStatus_t thePendingBit, netId_t theNetId) {
624 int myConnectionCount = 0;
625 for ( deviceId_t device_it = firstSource_v[theNetId]; device_it != UNKNOWN_DEVICE; device_it = nextSource_v[device_it] ) {
626 if ( IsPmos_(deviceType_v[device_it]) && deviceStatus_v[device_it][thePendingBit] ) {
627 if ( ++myConnectionCount > 1 ) return false;
628 }
629 }
630 for ( deviceId_t device_it = firstDrain_v[theNetId]; device_it != UNKNOWN_DEVICE; device_it = nextDrain_v[device_it] ) {
631 if ( IsPmos_(deviceType_v[device_it]) && deviceStatus_v[device_it][thePendingBit] ) {
632 if ( ++myConnectionCount > 1 ) return false;
633 }
634 }
635 return ( myConnectionCount < 2 );
636 }
637
IsIrrelevant(CEventQueue & theEventQueue,deviceId_t theDeviceId,CConnection & theConnections,voltage_t theVoltage,queueStatus_t theQueueStatus)638 bool CCvcDb::IsIrrelevant(CEventQueue& theEventQueue, deviceId_t theDeviceId, CConnection& theConnections, voltage_t theVoltage, queueStatus_t theQueueStatus) {
639 // Already shorted nets are irrelevant
640 if ( theConnections.masterSourceNet == theConnections.masterDrainNet) return true;
641 // mos is off
642 if ( theQueueStatus == ENQUEUE && theEventQueue.queueType != SIM_QUEUE ) return false; // MIN/MAX queues don't check for off mos because not in order
643 if ( IsOffMos(theEventQueue.queueType, theDeviceId, theConnections, theVoltage) ) {
644 if ( leakVoltageSet ) return true;
645 // first time, propagate thru off mos if only chance
646 netId_t myTargetNet;
647 if ( theConnections.sourceVoltage == UNKNOWN_VOLTAGE ) {
648 myTargetNet = theConnections.sourceId;
649 } else if ( theConnections.drainVoltage == UNKNOWN_VOLTAGE ) {
650 myTargetNet = theConnections.drainId;
651 } else {
652 // Voltage conflict with off mos
653 if ( theEventQueue.queueType == MIN_QUEUE ) {
654 if ( netStatus_v[theConnections.sourceId][NEEDS_MIN_CONNECTION] && theConnections.sourceVoltage > theConnections.drainVoltage ) {
655 netStatus_v[theConnections.sourceId][NEEDS_MIN_CONNECTION] = false;
656 } else if ( netStatus_v[theConnections.drainId][NEEDS_MIN_CONNECTION] && theConnections.drainVoltage > theConnections.sourceVoltage ) {
657 netStatus_v[theConnections.drainId][NEEDS_MIN_CONNECTION] = false;
658 }
659 } else if ( theEventQueue.queueType == MAX_QUEUE ) {
660 if ( netStatus_v[theConnections.sourceId][NEEDS_MAX_CONNECTION] && theConnections.sourceVoltage < theConnections.drainVoltage ) {
661 netStatus_v[theConnections.sourceId][NEEDS_MAX_CONNECTION] = false;
662 } else if ( netStatus_v[theConnections.drainId][NEEDS_MAX_CONNECTION] && theConnections.drainVoltage < theConnections.sourceVoltage ) {
663 netStatus_v[theConnections.drainId][NEEDS_MAX_CONNECTION] = false;
664 }
665 }
666 return true;
667 }
668 // first time enqueue all off mos, subsequently only process last connections
669 if ( theEventQueue.queueType == MIN_QUEUE && IsNmos_(deviceType_v[theDeviceId]) ) {
670 if ( theEventQueue.dequeueCount > 0 && ! LastNmosConnection(MIN_PENDING, myTargetNet) ) return true; // LDDN is NMOS in connection count
671 } else if ( theEventQueue.queueType == MAX_QUEUE && IsPmos_(deviceType_v[theDeviceId]) ) {
672 if ( theEventQueue.dequeueCount > 0 && ! LastPmosConnection(MAX_PENDING, myTargetNet) ) return true; // LDDP is PMOS in connection count
673 } else {
674 return true;
675 }
676 }
677 // devices connecting 2 powers to be handled later
678
679 // Skip short checks on enqueue (common for MIN/MAX/SIM).
680 if ( theQueueStatus == DEQUEUE ) {
681 if ( VoltageConflict(theEventQueue, theDeviceId, theConnections) ) {
682 return true;
683 }
684 }
685
686 // wrong bias: delays, does not prevent
687
688 // other conditions
689 return false;
690 }
691
AdjustMaxPmosKey(CConnection & theConnections,netId_t theDrainId,voltage_t theMaxSource,eventKey_t & theEventKey,queuePosition_t & theQueuePosition)692 string CCvcDb::AdjustMaxPmosKey(CConnection& theConnections, netId_t theDrainId, voltage_t theMaxSource, eventKey_t& theEventKey, queuePosition_t& theQueuePosition) {
693 string myAdjustment = "";
694 if ( theConnections.gateId == theDrainId ) {
695 if ( theConnections.device_p->model_p->Vth < 0 ) {
696 myAdjustment = " PMOS Vth drop " + PrintParameter(theEventKey, VOLTAGE_SCALE) + PrintParameter(theConnections.device_p->model_p->Vth, VOLTAGE_SCALE);
697 theEventKey = theEventKey + theConnections.device_p->model_p->Vth;
698 }
699 theQueuePosition = MOS_DIODE; // mos diode
700 } else {
701 if ( connectionCount_v[theDrainId].sourceDrainType[NMOS] ) {
702 theQueuePosition = DELAY_FRONT; // front of delay queue
703 }
704 if ( theConnections.bulkVoltage == UNKNOWN_VOLTAGE ) {
705 theQueuePosition = DELAY_BACK; // back of delay queue
706 } else if ( theMaxSource > theConnections.bulkVoltage ) {
707 theQueuePosition = DELAY_BACK; // back of delay queue
708 }
709 }
710 return(myAdjustment);
711 }
712
AdjustMaxNmosKey(CConnection & theConnections,voltage_t theSimGate,voltage_t theMaxSource,eventKey_t & theEventKey,queuePosition_t & theQueuePosition,bool theWarningFlag)713 string CCvcDb::AdjustMaxNmosKey(CConnection& theConnections, voltage_t theSimGate, voltage_t theMaxSource, eventKey_t& theEventKey, queuePosition_t& theQueuePosition,
714 bool theWarningFlag) {
715 theQueuePosition = DELAY_BACK; // default: back of delay queue
716 string myAdjustment = "";
717 // do not use sim on first pass
718 voltage_t myGateVoltage = ( ! isFixedSimNet || theSimGate == UNKNOWN_VOLTAGE ) ? MaxVoltage(theConnections.gateId) : theSimGate;
719 if ( myGateVoltage == UNKNOWN_VOLTAGE ) {
720 if ( connectionCount_v[theConnections.gateId].SourceDrainCount() == 0 ) {
721 if (theWarningFlag && ! (IsOneConnectionNet(theConnections.sourceId) || IsOneConnectionNet(theConnections.drainId)) ) {
722 CInstance * myInstance_p = instancePtr_v[deviceParent_v[theConnections.deviceId]];
723 string myUnknownKey = string(myInstance_p->master_p->name) + "/" + string(myInstance_p->master_p->devicePtr_v[theConnections.deviceId - myInstance_p->firstDeviceId]->name);
724 if ( unknownGateSet.count(myUnknownKey) == 0 ) {
725 reportFile << "WARNING: unknown max gate at net->device: " << NetName(theConnections.gateId) << " -> " <<
726 HierarchyName(deviceParent_v[theConnections.deviceId], PRINT_CIRCUIT_ON) << "/" << theConnections.device_p->name << endl;
727 unknownGateSet.insert(myUnknownKey);
728 }
729 }
730 if ( theConnections.device_p->model_p->Vth > 0 ) {
731 myAdjustment = " NMOS Vth drop " + PrintParameter(theEventKey, VOLTAGE_SCALE) + "-" + PrintParameter(theConnections.device_p->model_p->Vth, VOLTAGE_SCALE);
732 theEventKey = theEventKey - theConnections.device_p->model_p->Vth;
733 }
734 } else {
735 theQueuePosition = SKIP_QUEUE; // no enqueue with unknown gate in maxNmos
736 }
737 } else if ( myGateVoltage - theConnections.device_p->model_p->Vth <= theMaxSource ) {
738 myAdjustment = " NMOS gate limited " + PrintParameter(myGateVoltage, VOLTAGE_SCALE) + "-" + PrintParameter(theConnections.device_p->model_p->Vth, VOLTAGE_SCALE);
739 theEventKey = myGateVoltage - theConnections.device_p->model_p->Vth;
740 } else if ( theEventKey != theMaxSource ){
741 myAdjustment = " NMOS limited to source " + PrintParameter(theMaxSource, VOLTAGE_SCALE);
742 theEventKey = theMaxSource;
743 }
744 return(myAdjustment);
745 }
746
AdjustMinNmosKey(CConnection & theConnections,netId_t theDrainId,voltage_t theMinSource,eventKey_t & theEventKey,queuePosition_t & theQueuePosition)747 string CCvcDb::AdjustMinNmosKey(CConnection& theConnections, netId_t theDrainId, voltage_t theMinSource, eventKey_t& theEventKey, queuePosition_t& theQueuePosition) {
748 string myAdjustment = "";
749 if ( theConnections.gateId == theDrainId ) {
750 if ( theConnections.device_p->model_p->Vth > 0 ) {
751 myAdjustment = " NMOS Vth drop " + PrintParameter(theEventKey, VOLTAGE_SCALE) + "+" + PrintParameter(theConnections.device_p->model_p->Vth, VOLTAGE_SCALE);
752 theEventKey = theEventKey + theConnections.device_p->model_p->Vth;
753 }
754 theQueuePosition = MOS_DIODE; // mos diode
755 } else {
756 if ( connectionCount_v[theDrainId].sourceDrainType[PMOS] ) {
757 theQueuePosition = DELAY_FRONT; // front of delay queue
758 }
759 if ( theConnections.bulkVoltage == UNKNOWN_VOLTAGE ) {
760 theQueuePosition = DELAY_BACK; // back of delay queue
761 } else if ( theMinSource < theConnections.bulkVoltage ) {
762 theQueuePosition = DELAY_BACK; // back of delay queue
763 }
764 }
765 return(myAdjustment);
766 }
767
AdjustMinPmosKey(CConnection & theConnections,voltage_t theSimGate,voltage_t theMinSource,eventKey_t & theEventKey,queuePosition_t & theQueuePosition,bool theWarningFlag)768 string CCvcDb::AdjustMinPmosKey(CConnection& theConnections, voltage_t theSimGate, voltage_t theMinSource, eventKey_t& theEventKey, queuePosition_t& theQueuePosition,
769 bool theWarningFlag) {
770 theQueuePosition = DELAY_BACK; // default: back of delay queue
771 string myAdjustment = "";
772 // do not use sim on first pass
773 voltage_t myGateVoltage = ( ! isFixedSimNet || theSimGate == UNKNOWN_VOLTAGE ) ? MinVoltage(theConnections.gateId) : theSimGate;
774 if ( myGateVoltage == UNKNOWN_VOLTAGE ) {
775 if ( connectionCount_v[theConnections.gateId].SourceDrainCount() == 0 ) {
776 if (theWarningFlag && ! (IsOneConnectionNet(theConnections.sourceId) || IsOneConnectionNet(theConnections.drainId)) ) {
777 CInstance * myInstance_p = instancePtr_v[deviceParent_v[theConnections.deviceId]];
778 string myUnknownKey = string(myInstance_p->master_p->name) + "/" + string(myInstance_p->master_p->devicePtr_v[theConnections.deviceId - myInstance_p->firstDeviceId]->name);
779 if ( unknownGateSet.count(myUnknownKey) == 0 ) {
780 reportFile << "WARNING: unknown min gate at net->device: " << NetName(theConnections.gateId) << " -> " <<
781 HierarchyName(deviceParent_v[theConnections.deviceId], PRINT_CIRCUIT_ON) << "/" << theConnections.device_p->name << endl;
782 unknownGateSet.insert(myUnknownKey);
783 }
784 }
785 if ( theConnections.device_p->model_p->Vth < 0 ) {
786 myAdjustment = " PMOS Vth drop " + PrintParameter(theEventKey, VOLTAGE_SCALE) + "+" + PrintParameter(-theConnections.device_p->model_p->Vth, VOLTAGE_SCALE);
787 theEventKey = theEventKey - theConnections.device_p->model_p->Vth;
788 }
789 } else {
790 theQueuePosition = SKIP_QUEUE; // no enqueue with unknown gate in minPmos
791 }
792 } else if ( myGateVoltage - theConnections.device_p->model_p->Vth >= theMinSource ) {
793 myAdjustment = " PMOS gate limited " + PrintParameter(myGateVoltage, VOLTAGE_SCALE) + "+" + PrintParameter(-theConnections.device_p->model_p->Vth, VOLTAGE_SCALE);
794 theEventKey = myGateVoltage - theConnections.device_p->model_p->Vth;
795 } else if ( theEventKey != theMinSource ){
796 myAdjustment = " PMOS limited to source " + PrintParameter(theMinSource, VOLTAGE_SCALE);
797 theEventKey = theMinSource;
798 }
799 return(myAdjustment);
800 }
801
AdjustKey(CEventQueue & theEventQueue,deviceId_t theDeviceId,CConnection & theConnections,eventKey_t & theEventKey,queuePosition_t & theQueuePosition,shortDirection_t theDirection,bool theWarningFlag)802 string CCvcDb::AdjustKey(CEventQueue& theEventQueue, deviceId_t theDeviceId, CConnection& theConnections, eventKey_t& theEventKey, queuePosition_t& theQueuePosition, shortDirection_t theDirection, bool theWarningFlag) {
803 // MinMax queue Population+Propagation, Sim queue population only
804 assert( (theConnections.sourceVoltage == UNKNOWN_VOLTAGE && theConnections.drainVoltage != UNKNOWN_VOLTAGE) \
805 || (theConnections.sourceVoltage != UNKNOWN_VOLTAGE && theConnections.drainVoltage == UNKNOWN_VOLTAGE) \
806 || (theEventQueue.queueType == SIM_QUEUE && theConnections.gateVoltage == UNKNOWN_VOLTAGE) );
807 if ( deviceType_v[theDeviceId] == FUSE_ON || deviceType_v[theDeviceId] == FUSE_OFF ) { // process fuses last
808 theQueuePosition = DELAY_BACK;
809 }
810 if ( ! IsMos_(deviceType_v[theDeviceId]) ) return("");
811 netId_t myLinkNetId;
812 voltage_t myLinkVoltage;
813 bool myIsCalculatedPower; // all SIM_QUEUE calculated power goes to delay queue
814 bool myIsHiZPower;
815 string myAdjustedVoltage = "";
816 if ( theDirection == SOURCE_TO_MASTER_DRAIN ) { // propagate from drain
817 myLinkNetId = theConnections.sourceId;
818 myLinkVoltage = theConnections.drainVoltage;
819 myIsCalculatedPower = theConnections.drainPower_p->type[SIM_CALCULATED_BIT];
820 myIsHiZPower = theConnections.drainPower_p->type[HIZ_BIT];
821 theQueuePosition = DefaultQueuePosition_(theConnections.drainPower_p->type[POWER_BIT], theEventQueue);
822 } else {
823 myLinkNetId = theConnections.drainId;
824 myLinkVoltage = theConnections.sourceVoltage;
825 myIsCalculatedPower = theConnections.sourcePower_p->type[SIM_CALCULATED_BIT];
826 myIsHiZPower = theConnections.sourcePower_p->type[HIZ_BIT];
827 theQueuePosition = DefaultQueuePosition_(theConnections.sourcePower_p->type[POWER_BIT], theEventQueue);
828 }
829 if ( theEventQueue.queueType == MAX_QUEUE ) {
830 if ( IsPmos_(deviceType_v[theDeviceId]) ) {
831 if ( leakVoltageSet && myIsHiZPower ) { // no voltage change for HiZ nets in second min/max, high priority
832 theQueuePosition = QUEUE_HIZ;
833 } else {
834 myAdjustedVoltage = AdjustMaxPmosKey(theConnections, myLinkNetId, myLinkVoltage, theEventKey, theQueuePosition);
835 }
836 } else { // NMOS
837 if ( leakVoltageSet && myIsHiZPower ) { // no voltage change for HiZ nets in second min/max
838 theQueuePosition = DELAY_BACK;
839 } else {
840 myAdjustedVoltage = AdjustMaxNmosKey(theConnections, SimVoltage(theConnections.gateId), myLinkVoltage, theEventKey, theQueuePosition, theWarningFlag);
841 }
842 }
843 } else if ( theEventQueue.queueType == MIN_QUEUE ) {
844 if ( IsNmos_(deviceType_v[theDeviceId]) ) {
845 if ( leakVoltageSet && myIsHiZPower ) { // no voltage change for HiZ nets in second min/max, high priority
846 theQueuePosition = QUEUE_HIZ;
847 } else {
848 myAdjustedVoltage = AdjustMinNmosKey(theConnections, myLinkNetId, myLinkVoltage, theEventKey, theQueuePosition);
849 }
850 } else { // PMOS
851 if ( leakVoltageSet && myIsHiZPower ) { // no voltage change for HiZ nets in second min/max
852 theQueuePosition = DELAY_BACK;
853 } else {
854 myAdjustedVoltage = AdjustMinPmosKey(theConnections, SimVoltage(theConnections.gateId), myLinkVoltage, theEventKey, theQueuePosition, theWarningFlag);
855 }
856 }
857 } else if ( theEventQueue.queueType == SIM_QUEUE ) {
858 //theEventKey = SimKey(theEventQueue.QueueTime(), theConnections.resistance); // Sim Key is adjusted in calling routine
859 if ( theConnections.gateId == theConnections.sourceId || theConnections.gateId == theConnections.drainId ) {
860 theQueuePosition = DELAY_FRONT;
861 } else if ( theConnections.gateVoltage == UNKNOWN_VOLTAGE ) { // check always on
862 voltage_t myMinGateVoltage = MinVoltage(theConnections.gateId);
863 voltage_t myMaxGateVoltage = MaxVoltage(theConnections.gateId);
864 if ( IsNmos_(deviceType_v[theDeviceId]) && myMinGateVoltage != UNKNOWN_VOLTAGE
865 && myMinGateVoltage > myLinkVoltage + theConnections.device_p->model_p->Vth ) {
866 ; // always on. default delay
867 } else if ( IsPmos_(deviceType_v[theDeviceId]) && myMaxGateVoltage != UNKNOWN_VOLTAGE
868 && myMaxGateVoltage < myLinkVoltage + theConnections.device_p->model_p->Vth ) {
869 ; // always on. default delay
870 } else { // skip
871 theQueuePosition = SKIP_QUEUE;
872 }
873 } else if ( IsNmos_(deviceType_v[theDeviceId]) && theConnections.gateVoltage < myLinkVoltage + theConnections.device_p->model_p->Vth ) { // off devices delayed
874 theQueuePosition = DELAY_FRONT;
875 } else if ( IsPmos_(deviceType_v[theDeviceId]) && theConnections.gateVoltage > myLinkVoltage + theConnections.device_p->model_p->Vth ) { // off devices delayed
876 theQueuePosition = DELAY_FRONT;
877 } else if ( myIsCalculatedPower ) {
878 theQueuePosition = DELAY_FRONT;
879 }
880 }
881 return(myAdjustedVoltage);
882 }
883
AdjustSimVoltage(CEventQueue & theEventQueue,deviceId_t theDeviceId,CConnection & theConnections,voltage_t & theVoltage,shortDirection_t theDirection,propagation_t thePropagationType)884 string CCvcDb::AdjustSimVoltage(CEventQueue& theEventQueue, deviceId_t theDeviceId, CConnection& theConnections, voltage_t& theVoltage, shortDirection_t theDirection,
885 propagation_t thePropagationType) {
886 assert( (theConnections.sourceVoltage == UNKNOWN_VOLTAGE && theConnections.drainVoltage != UNKNOWN_VOLTAGE)
887 || (theConnections.sourceVoltage != UNKNOWN_VOLTAGE && theConnections.drainVoltage == UNKNOWN_VOLTAGE) );
888 CPower * myPower_p = ( theDirection == SOURCE_TO_MASTER_DRAIN ) ? theConnections.sourcePower_p : theConnections.drainPower_p;
889 netId_t myTargetNet = ( theDirection == SOURCE_TO_MASTER_DRAIN ) ? theConnections.sourceId : theConnections.drainId;
890 resistance_t mySourceResistance = ( theDirection == SOURCE_TO_MASTER_DRAIN ) ? theConnections.masterDrainNet.finalResistance : theConnections.masterSourceNet.finalResistance;
891
892 voltage_t myMinTargetVoltage = MinSimVoltage(myTargetNet);
893 voltage_t myMaxTargetVoltage = MaxSimVoltage(myTargetNet);
894 resistance_t myMinTargetResistance = MinResistance(myTargetNet);
895 resistance_t myMaxTargetResistance = MaxResistance(myTargetNet);
896 voltage_t myOriginalVoltage = theVoltage;
897 if ( myMinTargetVoltage != UNKNOWN_VOLTAGE && myMinTargetVoltage > myMaxTargetVoltage) {
898 voltage_t myTrueMinVoltage = myMaxTargetVoltage;
899 resistance_t myTrueMinResistance = myMaxTargetResistance;
900 myMaxTargetVoltage = myMinTargetVoltage;
901 myMaxTargetResistance = myMinTargetResistance;
902 myMinTargetVoltage = myTrueMinVoltage;
903 myMinTargetResistance = myTrueMinResistance;
904 }
905 string myCalculation = "";
906 if ( IsMos_(deviceType_v[theDeviceId]) ) {
907 if ( theConnections.gateId == myTargetNet ) { // mos as diodes
908 if ( myMinTargetVoltage == myMaxTargetVoltage && ( myPower_p && ! myPower_p->type[HIZ_BIT] ) ) { //may cause problem in nets not directly connected to power
909 // only propagate if min = max
910 myCalculation = " MOS sim drop " + PrintParameter(theVoltage, VOLTAGE_SCALE) + "V->" + PrintParameter(myMaxTargetVoltage, VOLTAGE_SCALE) + "V";
911 theVoltage = myMaxTargetVoltage;
912 } else {
913 theVoltage = UNKNOWN_VOLTAGE;
914 }
915 } else {
916 if ( theConnections.gateVoltage == UNKNOWN_VOLTAGE ) {
917 voltage_t myMinGateVoltage = MinVoltage(theConnections.gateId);
918 voltage_t myMaxGateVoltage = MaxVoltage(theConnections.gateId);
919 if ( IsNmos_(deviceType_v[theDeviceId]) && myMinGateVoltage != UNKNOWN_VOLTAGE
920 && myMinGateVoltage > theVoltage + theConnections.device_p->model_p->Vth ) {
921 theConnections.gateVoltage = myMinGateVoltage; // always on
922 } else if ( IsPmos_(deviceType_v[theDeviceId]) && myMaxGateVoltage != UNKNOWN_VOLTAGE
923 && myMaxGateVoltage < theVoltage + theConnections.device_p->model_p->Vth ) {
924 theConnections.gateVoltage = myMaxGateVoltage; // always on
925 }
926 }
927 assert(theConnections.gateVoltage != UNKNOWN_VOLTAGE);
928 if ( theConnections.gateVoltage == theVoltage + theConnections.device_p->model_p->Vth ) {
929 theVoltage = UNKNOWN_VOLTAGE; // skip simulation propagation
930 } else if ( IsNmos_(deviceType_v[theDeviceId]) && myMinTargetVoltage != UNKNOWN_VOLTAGE ) {
931 voltage_t myGateStepDown = theConnections.gateVoltage - theConnections.device_p->model_p->Vth;
932 if ( myPower_p && myPower_p->type[HIZ_BIT] ) {
933 ; // Don't adjust open voltages
934 } else if ( myGateStepDown < theVoltage ) {
935 myCalculation = " NMOS sim Vth drop " + PrintParameter(theConnections.gateVoltage, VOLTAGE_SCALE) + "-" + PrintParameter(theConnections.device_p->model_p->Vth, VOLTAGE_SCALE);
936 myCalculation += " limited by " + PrintParameter(myMinTargetVoltage, VOLTAGE_SCALE);
937 theVoltage = max(myGateStepDown, myMinTargetVoltage);
938 }
939 } else if ( IsPmos_(deviceType_v[theDeviceId]) && myMaxTargetVoltage != UNKNOWN_VOLTAGE) {
940 voltage_t myGateStepUp = theConnections.gateVoltage - theConnections.device_p->model_p->Vth;
941 if ( myPower_p && myPower_p->type[HIZ_BIT] ) {
942 ; // Don't adjust open voltages
943 } else if ( myGateStepUp > theVoltage ) {
944 myCalculation = " PMOS sim Vth drop " + PrintParameter(theConnections.gateVoltage, VOLTAGE_SCALE) + "+" + PrintParameter(-theConnections.device_p->model_p->Vth, VOLTAGE_SCALE);
945 myCalculation += " limited by " + PrintParameter(myMaxTargetVoltage, VOLTAGE_SCALE);
946 theVoltage = min(myGateStepUp, myMaxTargetVoltage);
947 }
948 }
949 }
950 }
951 if ( theVoltage == UNKNOWN_VOLTAGE ) return("");
952 if ( myMinTargetVoltage != UNKNOWN_VOLTAGE && theVoltage < myMinTargetVoltage ) {
953 myCalculation = " Limited sim to min" + myCalculation;
954 debugFile << myCalculation << " " << NetName(myTargetNet) << endl;
955 if ( thePropagationType != POWER_NETS_ONLY && myOriginalVoltage < myMinTargetVoltage
956 && theConnections.EstimatedCurrent(theVoltage, myMinTargetVoltage, mySourceResistance, myMinTargetResistance) > cvcParameters.cvcLeakLimit ) {
957 ReportSimShort(theDeviceId, theVoltage, myMinTargetVoltage, myCalculation);
958 }
959 // voltage drops in first pass are skipped, only report original voltage limits
960 theVoltage = myMinTargetVoltage;
961 }
962 if ( myMaxTargetVoltage != UNKNOWN_VOLTAGE && theVoltage > myMaxTargetVoltage ) {
963 myCalculation = " Limited sim to max" + myCalculation;
964 debugFile << myCalculation << " " << NetName(myTargetNet) << endl;
965 if ( thePropagationType != POWER_NETS_ONLY && myOriginalVoltage > myMaxTargetVoltage
966 && theConnections.EstimatedCurrent(theVoltage, myMaxTargetVoltage, mySourceResistance, myMaxTargetResistance) > cvcParameters.cvcLeakLimit ) {
967 ReportSimShort(theDeviceId, theVoltage, myMaxTargetVoltage, myCalculation);
968 }
969 // voltage drops in first pass are skipped, only report original voltage limits
970 theVoltage = myMaxTargetVoltage;
971 }
972 return(myCalculation);
973 }
974
EnqueueAttachedDevicesByTerminal(CEventQueue & theEventQueue,netId_t theNetId,CDeviceIdVector & theFirstDevice_v,CDeviceIdVector & theNextDevice_v,eventKey_t theEventKey)975 void CCvcDb::EnqueueAttachedDevicesByTerminal(CEventQueue& theEventQueue, netId_t theNetId, CDeviceIdVector& theFirstDevice_v, CDeviceIdVector& theNextDevice_v, eventKey_t theEventKey) {
976 // TODO: possibly remove inactive devices from connection lists
977 if ( theFirstDevice_v[theNetId] == UNKNOWN_DEVICE ) return;
978 static CConnection myConnections;
979 queuePosition_t myQueuePosition;
980 eventKey_t myEventKey;
981 string myAdjustedCalculation;
982 int myGateBiasCount = 0;
983 calculationType_t myCalculationType = UNKNOWN_CALCULATION;
984 for (deviceId_t device_it = theFirstDevice_v[theNetId]; device_it != UNKNOWN_DEVICE; device_it = theNextDevice_v[device_it]) {
985 if ( deviceStatus_v[device_it][theEventQueue.inactiveBit] || deviceStatus_v[device_it][theEventQueue.pendingBit] ) {
986 continue; // skip inactive and pending devices
987 } else {
988 MapDeviceNets(device_it, theEventQueue, myConnections);
989 if ( IsIrrelevant(theEventQueue, device_it, myConnections, theEventKey, ENQUEUE) ) {
990 deviceStatus_v[device_it][theEventQueue.inactiveBit] = true;
991 } else if ( myConnections.sourceVoltage == UNKNOWN_VOLTAGE && myConnections.drainVoltage == UNKNOWN_VOLTAGE ) { // ignore bias/gate only changes
992 myGateBiasCount++;
993 } else {
994 myEventKey = theEventKey;
995 if ( myConnections.sourceVoltage == UNKNOWN_VOLTAGE || myConnections.drainVoltage == UNKNOWN_VOLTAGE ) { // Adjust key for non-shorts
996 shortDirection_t myDirection;
997 if ( myConnections.sourceVoltage == UNKNOWN_VOLTAGE ) {
998 myDirection = SOURCE_TO_MASTER_DRAIN;
999 myQueuePosition = DefaultQueuePosition_(myConnections.drainPower_p->type[POWER_BIT], theEventQueue);
1000 myCalculationType = GetCalculationType(myConnections.drainPower_p, theEventQueue.queueType);
1001 } else {
1002 myDirection = DRAIN_TO_MASTER_SOURCE;
1003 myQueuePosition = DefaultQueuePosition_(myConnections.sourcePower_p->type[POWER_BIT], theEventQueue);
1004 myCalculationType = GetCalculationType(myConnections.sourcePower_p, theEventQueue.queueType);
1005 }
1006 myAdjustedCalculation = AdjustKey(theEventQueue, device_it, myConnections, myEventKey, myQueuePosition, myDirection, IGNORE_WARNINGS);
1007 // sets myQueuePosition, myEventKey
1008 } else {
1009 myQueuePosition = DefaultQueuePosition_(myConnections.sourcePower_p->type[POWER_BIT] || myConnections.drainPower_p->type[POWER_BIT], theEventQueue);
1010 }
1011 if ( myQueuePosition == SKIP_QUEUE ) continue; // SIM queues/maxNmos/minPmos with unknown mos gate return SKIP_QUEUE, skip for now
1012 if ( myEventKey < theEventKey && myCalculationType == UP_CALCULATION ) {
1013 debugFile << "DEBUG: Skipped down propagation at " << DeviceName(myConnections.deviceId);
1014 debugFile << " voltage " << PrintVoltage(myEventKey) << "(" << myAdjustedCalculation << ") from " << PrintVoltage(theEventKey) << endl;
1015 continue; // do not propagate opposite calculations
1016 }
1017 if ( myEventKey > theEventKey && myCalculationType == DOWN_CALCULATION ) {
1018 debugFile << "DEBUG: Skipped up propagation at " << DeviceName(myConnections.deviceId);
1019 debugFile << " voltage " << PrintVoltage(myEventKey) << "(" << myAdjustedCalculation << ") from " << PrintVoltage(theEventKey) << endl;
1020 continue; // do not propagate opposite calculations
1021 }
1022 if ( theEventQueue.queueType == SIM_QUEUE ) {
1023 myEventKey = SimKey(theEventQueue.QueueTime(), myConnections.resistance);
1024 }
1025 theEventQueue.AddEvent(myEventKey, device_it, myQueuePosition);
1026 deviceStatus_v[device_it][theEventQueue.pendingBit] = true;
1027 if ( myQueuePosition == MOS_DIODE && theEventQueue.queueType != SIM_QUEUE
1028 && ! (myConnections.gatePower_p && myConnections.gatePower_p->type[HIZ_BIT]) ) { // mos diode connections in min/max queues
1029 netId_t myDrainNetId, mySourceNetId;
1030 voltage_t myMinSourceVoltage, myMaxSourceVoltage;
1031 voltage_t myMinDrainVoltage, myMaxDrainVoltage;
1032 if ( myConnections.sourceVoltage == UNKNOWN_VOLTAGE ) {
1033 assert ( myConnections.drainVoltage != UNKNOWN_VOLTAGE );
1034 myDrainNetId = myConnections.sourceId;
1035 mySourceNetId = myConnections.drainId;
1036 } else if ( myConnections.drainVoltage == UNKNOWN_VOLTAGE ) {
1037 myDrainNetId = myConnections.drainId;
1038 mySourceNetId = myConnections.sourceId;
1039 } else {
1040 throw EDatabaseError("EnqueueAttachedDevicesByTerminal: " + DeviceName(device_it));
1041 }
1042 myMinSourceVoltage = MinVoltage(mySourceNetId);
1043 myMaxSourceVoltage = MaxVoltage(mySourceNetId);
1044 myMinDrainVoltage = MinVoltage(myDrainNetId);
1045 myMaxDrainVoltage = MaxVoltage(myDrainNetId);
1046 if ( theEventQueue.queueType == MAX_QUEUE && myMinSourceVoltage == theEventKey ) { // set MIN voltage too
1047 // theEventKey = before drop, myEventKey = after drop
1048 voltage_t myMinLeakVoltage = MinLeakVoltage(myDrainNetId);
1049 if ( myMinDrainVoltage == UNKNOWN_VOLTAGE ) {
1050 netVoltagePtr_v.CalculatePower(minEventQueue, myEventKey, myDrainNetId, mySourceNetId, this, myAdjustedCalculation);
1051 netVoltagePtr_v[myDrainNetId].full->type[ANALOG_BIT] = true;
1052 if ( gDebug_cvc ) cout << "DEBUG: Calculated power at net: " << myDrainNetId << " MIN " << myEventKey << endl;
1053 // do not increment lastUpdate
1054 minNet_v.Set(myDrainNetId, myDrainNetId, parameterResistanceMap[myConnections.device_p->parameters] * 100, minNet_v.lastUpdate);
1055 CheckResistorOverflow_(minNet_v[myDrainNetId].finalResistance, myDrainNetId, logFile);
1056 if ( leakVoltageSet && myMinLeakVoltage != UNKNOWN_VOLTAGE && myMinLeakVoltage <= myEventKey ) continue;
1057 assert(netVoltagePtr_v[myDrainNetId].full);
1058 if ( netVoltagePtr_v[myDrainNetId].full->pullDownVoltage() != UNKNOWN_VOLTAGE && netVoltagePtr_v[myDrainNetId].full->pullDownVoltage() <= myEventKey ) continue;
1059 // pull down not known
1060 netStatus_v[myDrainNetId][NEEDS_MIN_CONNECTION] = true;
1061 if ( gDebug_cvc ) cout << "DEBUG: min estimate net: " << myDrainNetId << endl;
1062 if ( netStatus_v[mySourceNetId][NEEDS_MIN_CONNECTION] == true ) {
1063 if ( gDebug_cvc ) cout << "DEBUG: min estimate dependency net: " << mySourceNetId << endl;
1064 minConnectionDependencyMap[mySourceNetId].push_front(myDrainNetId);
1065 }
1066 // calculated power only
1067 } else {
1068 if ( myMinDrainVoltage < myEventKey ) {
1069 reportFile << "WARNING: Min voltage already set for " << NetName(myDrainNetId, PRINT_CIRCUIT_ON, PRINT_HIERARCHY_OFF);
1070 reportFile << " at " << DeviceName(myConnections.deviceId, PRINT_CIRCUIT_ON) << " expected/found " << myEventKey << "/" << myMinDrainVoltage << endl;
1071 netStatus_v[myDrainNetId][NEEDS_MIN_CONNECTION] = false;
1072 netStatus_v[mySourceNetId][NEEDS_MIN_CONNECTION] = false; // reset parent also
1073 }
1074 }
1075 } else if ( theEventQueue.queueType == MIN_QUEUE && myMaxSourceVoltage == theEventKey ) { // set MAX voltage too
1076 voltage_t myMaxLeakVoltage = MaxLeakVoltage(myDrainNetId);
1077 if ( myMaxDrainVoltage == UNKNOWN_VOLTAGE ) {
1078 netVoltagePtr_v.CalculatePower(maxEventQueue, myEventKey, myDrainNetId, mySourceNetId, this, myAdjustedCalculation);
1079 netVoltagePtr_v[myDrainNetId].full->type[ANALOG_BIT] = true;
1080 if ( gDebug_cvc ) cout << "DEBUG: Calculated power at net: " << myDrainNetId << " MAX " << myEventKey << endl;
1081 // do not increment lastUpdate
1082 maxNet_v.Set(myDrainNetId, myDrainNetId, parameterResistanceMap[myConnections.device_p->parameters] * 100, maxNet_v.lastUpdate);
1083 CheckResistorOverflow_(maxNet_v[myDrainNetId].finalResistance, myDrainNetId, logFile);
1084 if ( leakVoltageSet && myMaxLeakVoltage != UNKNOWN_VOLTAGE && myMaxLeakVoltage >= myEventKey ) continue;
1085 assert(netVoltagePtr_v[myDrainNetId].full);
1086 if ( netVoltagePtr_v[myDrainNetId].full->pullUpVoltage() != UNKNOWN_VOLTAGE && netVoltagePtr_v[myDrainNetId].full->pullUpVoltage() >= myEventKey ) continue;
1087 // pull up not known
1088 netStatus_v[myDrainNetId][NEEDS_MAX_CONNECTION] = true;
1089 if ( gDebug_cvc ) cout << "DEBUG: max estimate net: " << myDrainNetId << endl;
1090 if ( netStatus_v[mySourceNetId][NEEDS_MAX_CONNECTION] == true ) {
1091 if ( gDebug_cvc ) cout << "DEBUG: max estimate dependency net: " << mySourceNetId << endl;
1092 maxConnectionDependencyMap[mySourceNetId].push_front(myDrainNetId);
1093 }
1094 // calculated power only
1095 } else {
1096 if ( myMaxDrainVoltage > myEventKey ) {
1097 reportFile << "WARNING: Max voltage already set for " << NetName(myDrainNetId, PRINT_CIRCUIT_ON, PRINT_HIERARCHY_OFF);
1098 reportFile << " at " << DeviceName(myConnections.deviceId, PRINT_CIRCUIT_ON) << " expected/found " << myEventKey << "/" << myMaxDrainVoltage << endl;
1099 netStatus_v[myDrainNetId][NEEDS_MAX_CONNECTION] = false;
1100 netStatus_v[mySourceNetId][NEEDS_MAX_CONNECTION] = false; // reset parent also
1101 }
1102 }
1103 }
1104 }
1105 }
1106 }
1107 }
1108 if ( myGateBiasCount > 10000 && theEventQueue.queueType != SIM_QUEUE ) {
1109 reportFile << "WARNING: large non-power gate/bias net " << NetName(theNetId) << " at " << DeviceName(theFirstDevice_v[theNetId]) << endl;
1110 }
1111 }
1112
EnqueueAttachedDevices(CEventQueue & theEventQueue,netId_t theNetId,eventKey_t theEventKey)1113 void CCvcDb::EnqueueAttachedDevices(CEventQueue& theEventQueue, netId_t theNetId, eventKey_t theEventKey) {
1114 EnqueueAttachedDevicesByTerminal(theEventQueue, theNetId, firstSource_v, nextSource_v, theEventKey);
1115 EnqueueAttachedDevicesByTerminal(theEventQueue, theNetId, firstDrain_v, nextDrain_v, theEventKey);
1116 // EnqueueAttachedDevicesByTerminal(theEventQueue, theNetId, firstBulk_v, nextBulk_v, theEventKey);
1117 EnqueueAttachedDevicesByTerminal(theEventQueue, theNetId, firstGate_v, nextGate_v, theEventKey);
1118 }
1119
EnqueueAttachedResistorsByTerminal(CEventQueue & theEventQueue,netId_t theNetId,CDeviceIdVector & theFirstDevice_v,CDeviceIdVector & theNextDevice_v,eventKey_t theEventKey,queuePosition_t theQueuePosition)1120 void CCvcDb::EnqueueAttachedResistorsByTerminal(CEventQueue& theEventQueue, netId_t theNetId, CDeviceIdVector& theFirstDevice_v, CDeviceIdVector& theNextDevice_v, eventKey_t theEventKey, queuePosition_t theQueuePosition) {
1121 // TODO: possibly remove inactive devices from connection lists
1122 for (deviceId_t device_it = theFirstDevice_v[theNetId]; device_it != UNKNOWN_DEVICE; device_it = theNextDevice_v[device_it]) {
1123 if ( deviceType_v[device_it] == RESISTOR ) {
1124 if ( deviceStatus_v[device_it][theEventQueue.inactiveBit] || deviceStatus_v[device_it][theEventQueue.pendingBit] ) {
1125 continue; // skip inactive and pending devices
1126 } else {
1127 theEventQueue.AddEvent(theEventKey, device_it, theQueuePosition);
1128 deviceStatus_v[device_it][theEventQueue.pendingBit] = true;
1129 }
1130 }
1131 }
1132 }
1133
EnqueueAttachedResistors(CEventQueue & theEventQueue,netId_t theNetId,eventKey_t theEventKey,queuePosition_t theQueuePosition)1134 void CCvcDb::EnqueueAttachedResistors(CEventQueue& theEventQueue, netId_t theNetId, eventKey_t theEventKey, queuePosition_t theQueuePosition) {
1135 EnqueueAttachedResistorsByTerminal(theEventQueue, theNetId, firstSource_v, nextSource_v, theEventKey, theQueuePosition);
1136 EnqueueAttachedResistorsByTerminal(theEventQueue, theNetId, firstDrain_v, nextDrain_v, theEventKey, theQueuePosition);
1137 }
1138
ShiftVirtualNets(CEventQueue & theEventQueue,netId_t theNewNetId,CVirtualNet & theLastVirtualNet,resistance_t theSourceResistance,resistance_t theDrainResistance)1139 void CCvcDb::ShiftVirtualNets(CEventQueue& theEventQueue, netId_t theNewNetId, CVirtualNet& theLastVirtualNet, resistance_t theSourceResistance, resistance_t theDrainResistance) {
1140 netId_t myNetId;
1141 resistance_t myNewResistance;
1142 int myShiftCount = 0;
1143 while ( long(theSourceResistance) + theLastVirtualNet.resistance < long(theDrainResistance) - theLastVirtualNet.resistance ) {
1144 if ( myShiftCount++ > 10000 ) {
1145 cout << "ERROR: exceeded shift limit for net# " << theNewNetId << endl;
1146 cout << " name: " << NetName(theNewNetId) << endl;
1147 cout << " next net is " << theEventQueue.virtualNet_v[theNewNetId].nextNetId << endl;
1148 assert(myShiftCount < 10000 );
1149 }
1150 if (gDebug_cvc) cout << gEventQueueTypeMap[theEventQueue.queueType] << " Shifted Net " << theNewNetId << endl;
1151 assert(long(theSourceResistance) + theLastVirtualNet.resistance < MAX_RESISTANCE);
1152 theSourceResistance += theLastVirtualNet.resistance;
1153 assert(theDrainResistance >= theLastVirtualNet.resistance);
1154 theDrainResistance -= theLastVirtualNet.resistance;
1155 myNetId = theLastVirtualNet.nextNetId;
1156 myNewResistance = theLastVirtualNet.resistance;
1157 theLastVirtualNet(theEventQueue.virtualNet_v, myNetId);
1158 if ( theEventQueue.virtualNet_v[myNetId].finalResistance != theDrainResistance ) {
1159 cout << "Shift: unexpected drain resistance at net " << myNetId
1160 << " found " << theEventQueue.virtualNet_v[myNetId].finalResistance << " expected " << theDrainResistance << endl;
1161 }
1162 theEventQueue.virtualNet_v.Set(myNetId, theNewNetId, myNewResistance, ++theEventQueue.virtualNet_v.lastUpdate);
1163 if ( theEventQueue.virtualNet_v[myNetId].finalResistance != theSourceResistance ) {
1164 cout << "Shift: unexpected source resistance at net " << myNetId
1165 << " found " << theEventQueue.virtualNet_v[myNetId].finalResistance << " expected " << theSourceResistance << endl;
1166 }
1167 CheckResistorOverflow_(theEventQueue.virtualNet_v[myNetId].finalResistance, myNetId, logFile);
1168 theNewNetId = myNetId;
1169 }
1170 }
1171
RecalculateFinalResistance(CEventQueue & theEventQueue,netId_t theNetId,bool theRecursingFlag)1172 void CCvcDb::RecalculateFinalResistance(CEventQueue& theEventQueue, netId_t theNetId, bool theRecursingFlag) {
1173 netId_t mySourceId, myDrainId;
1174 CConnection myConnections;
1175 CDevice myDevice;
1176 static unordered_set<netId_t> myProccessedNets;
1177 if ( ! theRecursingFlag ) {
1178 myProccessedNets.clear();
1179 }
1180 myProccessedNets.insert(theNetId);
1181 netId_t mySearchNetId = theNetId;
1182 while ( theEventQueue.virtualNet_v[mySearchNetId].nextNetId != mySearchNetId && theEventQueue.virtualNet_v[mySearchNetId].resistance == 0 ) {
1183 // find the master net for non-conducting resistors
1184 mySearchNetId = theEventQueue.virtualNet_v[mySearchNetId].nextNetId;
1185 }
1186 for (deviceId_t device_it = firstSource_v[mySearchNetId]; device_it != UNKNOWN_DEVICE; device_it = nextSource_v[device_it]) {
1187 if ( deviceStatus_v[device_it][theEventQueue.inactiveBit] ) { // only process shorted nets
1188 SetDeviceNets(device_it, &myDevice, myConnections.sourceId, myConnections.gateId, myConnections.drainId, myConnections.bulkId);
1189 if ( myConnections.sourceId != theNetId ) continue; // skip devices that aren't connected to the net we want
1190 myDrainId = myConnections.drainId;
1191 if ( theNetId == theEventQueue.virtualNet_v[myDrainId].nextNetId ) { // only process nets that need to be recalculated
1192 theEventQueue.virtualNet_v.Set(myDrainId, theNetId, theEventQueue.virtualNet_v[myDrainId].resistance, ++theEventQueue.virtualNet_v.lastUpdate);
1193 CheckResistorOverflow_(theEventQueue.virtualNet_v[myDrainId].finalResistance, myDrainId, logFile);
1194 }
1195 }
1196 }
1197 for (deviceId_t device_it = firstDrain_v[mySearchNetId]; device_it != UNKNOWN_DEVICE; device_it = nextDrain_v[device_it]) {
1198 if ( deviceStatus_v[device_it][theEventQueue.inactiveBit] ) { // only process shorted nets (process source but not drain)
1199 SetDeviceNets(device_it, &myDevice, myConnections.sourceId, myConnections.gateId, myConnections.drainId, myConnections.bulkId);
1200 if ( myConnections.drainId != theNetId ) continue; // skip devices that aren't connected to the net we want
1201 mySourceId = myConnections.sourceId;
1202 if ( theNetId == theEventQueue.virtualNet_v[mySourceId].nextNetId ) { // only process nets that need to be recalculated
1203 theEventQueue.virtualNet_v.Set(mySourceId, theNetId, theEventQueue.virtualNet_v[mySourceId].resistance, ++theEventQueue.virtualNet_v.lastUpdate);
1204 CheckResistorOverflow_(theEventQueue.virtualNet_v[mySourceId].finalResistance, mySourceId, logFile);
1205 }
1206 }
1207 }
1208 }
1209
ShortNets(CEventQueue & theEventQueue,deviceId_t theDeviceId,CConnection & theConnections,shortDirection_t theDirection)1210 void CCvcDb::ShortNets(CEventQueue& theEventQueue, deviceId_t theDeviceId, CConnection& theConnections, shortDirection_t theDirection) {
1211 if ( theDirection == DRAIN_TO_MASTER_SOURCE ) {
1212 // do not increment lastUpdate (increment in calling routine if necessary)
1213 theEventQueue.virtualNet_v.Set(theConnections.drainId, theConnections.sourceId, parameterResistanceMap[theConnections.device_p->parameters], theEventQueue.virtualNet_v.lastUpdate);
1214 CheckResistorOverflow_(theEventQueue.virtualNet_v[theConnections.drainId].finalResistance, theConnections.drainId, logFile);
1215 if ( deviceType_v[theDeviceId] == RESISTOR ) {
1216 PropagateConnectionType(theEventQueue.virtualNet_v, connectionCount_v[theConnections.drainId].sourceDrainType, theConnections.sourceId);
1217 }
1218 } else if ( theDirection == SOURCE_TO_MASTER_DRAIN ) {
1219 // do not increment lastUpdate (increment in calling routine if necessary)
1220 theEventQueue.virtualNet_v.Set(theConnections.sourceId, theConnections.drainId, parameterResistanceMap[theConnections.device_p->parameters], theEventQueue.virtualNet_v.lastUpdate);
1221 CheckResistorOverflow_(theEventQueue.virtualNet_v[theConnections.sourceId].finalResistance, theConnections.sourceId, logFile);
1222 if ( deviceType_v[theDeviceId] == RESISTOR ) {
1223 PropagateConnectionType(theEventQueue.virtualNet_v, connectionCount_v[theConnections.sourceId].sourceDrainType, theConnections.drainId);
1224 }
1225 } else {
1226 throw EDatabaseError("ShortNets: " + DeviceName(theDeviceId));
1227 }
1228 deviceStatus_v[theDeviceId][theEventQueue.inactiveBit] = true;
1229 }
1230
ShortNets(CEventQueue & theEventQueue,deviceId_t theDeviceId,CConnection & theConnections,shortDirection_t theDirection,voltage_t theShortVoltage,string theCalculation)1231 void CCvcDb::ShortNets(CEventQueue& theEventQueue, deviceId_t theDeviceId, CConnection& theConnections, shortDirection_t theDirection, voltage_t theShortVoltage, string theCalculation) {
1232 // for min/max queues.
1233 netId_t myMasterNet, mySlaveNet;
1234 voltage_t myMasterVoltage;
1235 voltage_t mySimVoltage;
1236 if ( theDirection == DRAIN_TO_MASTER_SOURCE ) {
1237 myMasterNet = theConnections.sourceId;
1238 mySlaveNet = theConnections.drainId;
1239 myMasterVoltage = theConnections.sourceVoltage;
1240 } else if ( theDirection == SOURCE_TO_MASTER_DRAIN ) {
1241 myMasterNet = theConnections.drainId;
1242 mySlaveNet = theConnections.sourceId;
1243 myMasterVoltage = theConnections.drainVoltage;
1244 } else {
1245 throw EDatabaseError("ShortNets " + DeviceName(theDeviceId));
1246 }
1247 if ( isFixedSimNet ) {
1248 mySimVoltage = SimVoltage(mySlaveNet);
1249 if ( theEventQueue.queueType == MIN_QUEUE ) {
1250 if ( mySimVoltage != UNKNOWN_VOLTAGE && theShortVoltage > mySimVoltage ) {
1251 if (gDebug_cvc) cout << "DEBUG: min > sim (" << theShortVoltage << ">" << mySimVoltage << ")" << endl;
1252 theShortVoltage = mySimVoltage;
1253 theCalculation = " Limited min to sim";
1254 }
1255 } else if ( theEventQueue.queueType == MAX_QUEUE ) {
1256 if ( mySimVoltage != UNKNOWN_VOLTAGE && theShortVoltage < mySimVoltage ) {
1257 if (gDebug_cvc) cout << "DEBUG: max < sim (" << theShortVoltage << "<" << mySimVoltage << ")" << endl;
1258 theShortVoltage = mySimVoltage;
1259 theCalculation = " Limited max to sim";
1260 }
1261 }
1262 }
1263 if ( theShortVoltage == myMasterVoltage ) {
1264 // do not increment lastUpdate (increment in calling routine if necessary)
1265 theEventQueue.virtualNet_v.Set(mySlaveNet, myMasterNet, parameterResistanceMap[theConnections.device_p->parameters], theEventQueue.virtualNet_v.lastUpdate);
1266 CheckResistorOverflow_(theEventQueue.virtualNet_v[mySlaveNet].finalResistance, mySlaveNet, logFile);
1267 } else {
1268 netVoltagePtr_v.CalculatePower(theEventQueue, theShortVoltage, mySlaveNet, myMasterNet, this, theCalculation);
1269 if ( gDebug_cvc ) cout << "DEBUG: Calculated power at net: " << mySlaveNet << " " << gEventQueueTypeMap[theEventQueue.queueType] << " " << theShortVoltage << endl;
1270 // do not increment lastUpdate (increment in calling routine if necessary)
1271 theEventQueue.virtualNet_v.Set(mySlaveNet, mySlaveNet, parameterResistanceMap[theConnections.device_p->parameters] + theEventQueue.virtualNet_v[myMasterNet].finalResistance, theEventQueue.virtualNet_v.lastUpdate);
1272 CheckResistorOverflow_(theEventQueue.virtualNet_v[mySlaveNet].finalResistance, mySlaveNet, logFile);
1273 }
1274 if ( deviceType_v[theDeviceId] == RESISTOR ) {
1275 PropagateConnectionType(theEventQueue.virtualNet_v, connectionCount_v[mySlaveNet].sourceDrainType, myMasterNet);
1276 } else if ( deviceType_v[theDeviceId] == FUSE_ON || deviceType_v[theDeviceId] == FUSE_OFF ) {
1277 netId_t myNextOtherNet;
1278 if ( theEventQueue.queueType == MIN_QUEUE ) {
1279 myNextOtherNet = maxNet_v[mySlaveNet].nextNetId;
1280 } else {
1281 assert( theEventQueue.queueType == MAX_QUEUE );
1282 myNextOtherNet = minNet_v[mySlaveNet].nextNetId;
1283 }
1284 if ( myNextOtherNet == myMasterNet ) {
1285 PrintFuseError(mySlaveNet, theConnections);
1286 }
1287 }
1288 deviceStatus_v[theDeviceId][theEventQueue.inactiveBit] = true;
1289 }
1290
ShortSimNets(CEventQueue & theEventQueue,deviceId_t theDeviceId,CConnection & theConnections,shortDirection_t theDirection,voltage_t theShortVoltage,string theCalculation)1291 void CCvcDb::ShortSimNets(CEventQueue& theEventQueue, deviceId_t theDeviceId, CConnection& theConnections, shortDirection_t theDirection, voltage_t theShortVoltage, string theCalculation) {
1292 netId_t myMasterNet, mySlaveNet;
1293 voltage_t myMasterVoltage;
1294 CPower * myMasterPower_p;
1295 if ( theDirection == DRAIN_TO_MASTER_SOURCE ) {
1296 myMasterPower_p = theConnections.sourcePower_p;
1297 myMasterNet = theConnections.sourceId;
1298 mySlaveNet = theConnections.drainId;
1299 myMasterVoltage = theConnections.sourceVoltage;
1300 } else if ( theDirection == SOURCE_TO_MASTER_DRAIN ) {
1301 myMasterPower_p = theConnections.drainPower_p;
1302 myMasterNet = theConnections.drainId;
1303 mySlaveNet = theConnections.sourceId;
1304 myMasterVoltage = theConnections.drainVoltage;
1305 } else {
1306 throw EDatabaseError("ShortSimNets " + DeviceName(theDeviceId));
1307 }
1308 voltage_t myMaxSlaveVoltage = MaxLeakVoltage(mySlaveNet);
1309 voltage_t myMinSlaveVoltage = MinLeakVoltage(mySlaveNet);
1310 // 2013.11.13 added min max limits for sim voltages
1311 string myCalculation = "";
1312 if ( myMaxSlaveVoltage != UNKNOWN_VOLTAGE && myMaxSlaveVoltage < theShortVoltage ) {
1313 theShortVoltage = myMaxSlaveVoltage;
1314 myCalculation = " Limited to max";
1315 }
1316 if ( myMinSlaveVoltage != UNKNOWN_VOLTAGE && myMinSlaveVoltage > theShortVoltage ) {
1317 theShortVoltage = myMinSlaveVoltage;
1318 myCalculation = " Limited to min";
1319 }
1320 if ( theShortVoltage == myMasterVoltage ) {
1321 if ( IsSCRCPower(myMasterPower_p) && connectionCount_v[mySlaveNet].sourceDrainType[NMOS] && connectionCount_v[mySlaveNet].sourceDrainType[PMOS] ) {
1322 if ( IncrementDeviceError(theDeviceId, LEAK) < cvcParameters.cvcCircuitErrorLimit || cvcParameters.cvcCircuitErrorLimit == 0 ) {
1323 errorFile << "! Short Detected: SCRC " << PrintVoltage(myMasterVoltage) << " to output" << endl;
1324 static CFullConnection myConnections;
1325 MapDeviceNets(theDeviceId, myConnections);
1326 PrintDeviceWithAllConnections(deviceParent_v[theDeviceId], myConnections, errorFile);
1327 errorFile << endl;
1328 }
1329 }
1330 // do not increment lastUpdate
1331 theEventQueue.virtualNet_v.Set(mySlaveNet, myMasterNet, parameterResistanceMap[theConnections.device_p->parameters], theEventQueue.virtualNet_v.lastUpdate);
1332 } else {
1333 netVoltagePtr_v.CalculatePower(theEventQueue, theShortVoltage, mySlaveNet, myMasterNet, this, theCalculation + myCalculation);
1334 if ( gDebug_cvc ) cout << "DEBUG: Calculated power at net: " << mySlaveNet << " " << gEventQueueTypeMap[theEventQueue.queueType] << " " << theShortVoltage << endl;
1335 if ( IsMos_(deviceType_v[theDeviceId]) && theConnections.gateId == mySlaveNet ) { // gate/drain connections increase effective resistance (trace is broken so add master final resistance)
1336 // do not increment lastUpdate
1337 theEventQueue.virtualNet_v.Set(mySlaveNet, mySlaveNet, parameterResistanceMap[theConnections.device_p->parameters] * 100 + theEventQueue.virtualNet_v[myMasterNet].finalResistance, theEventQueue.virtualNet_v.lastUpdate);
1338 } else {
1339 // do not increment lastUpdate
1340 theEventQueue.virtualNet_v.Set(mySlaveNet, mySlaveNet, parameterResistanceMap[theConnections.device_p->parameters] + theEventQueue.virtualNet_v[myMasterNet].finalResistance, theEventQueue.virtualNet_v.lastUpdate);
1341 }
1342 }
1343 CheckResistorOverflow_(theEventQueue.virtualNet_v[mySlaveNet].finalResistance, mySlaveNet, logFile);
1344 if ( deviceType_v[theDeviceId] == RESISTOR ) {
1345 PropagateConnectionType(theEventQueue.virtualNet_v, connectionCount_v[mySlaveNet].sourceDrainType, myMasterNet);
1346 }
1347 deviceStatus_v[theDeviceId][theEventQueue.inactiveBit] = true;
1348 }
1349
PropagateConnectionType(CVirtualNetVector & theVirtualNet_v,CStatus theSourceDrainType,netId_t theNetId)1350 void CCvcDb::PropagateConnectionType(CVirtualNetVector& theVirtualNet_v, CStatus theSourceDrainType, netId_t theNetId) {
1351 CStatus myNewStatus;
1352 // TODO: Propagate upstream??
1353 int myPropagationCount = 0;
1354 while ( theNetId != theVirtualNet_v[theNetId].nextNetId ) {
1355 assert(theNetId != UNKNOWN_NET );
1356 myNewStatus = connectionCount_v[theNetId].sourceDrainType | theSourceDrainType;
1357 if ( myNewStatus == connectionCount_v[theNetId].sourceDrainType ) break;
1358 connectionCount_v[theNetId].sourceDrainType = myNewStatus;
1359 theNetId = theVirtualNet_v[theNetId].nextNetId;
1360 if ( myPropagationCount++ > 10000 ) {
1361 reportFile << "ERROR: exceeded connection type propagation limit for net# " << theNetId << endl;
1362 reportFile << " name: " << NetName(theNetId) << endl;
1363 reportFile << " next net is " << theVirtualNet_v[theNetId].nextNetId << endl;
1364 assert(myPropagationCount < 10000 );
1365 }
1366 }
1367 }
1368
PropagateResistorVoltages(CEventQueue & theEventQueue)1369 void CCvcDb::PropagateResistorVoltages(CEventQueue& theEventQueue) {
1370 deviceId_t myDeviceId = theEventQueue.GetEvent();
1371 deviceStatus_v[myDeviceId][theEventQueue.pendingBit] = false;
1372 queuePosition_t myQueuePosition;
1373 if ( deviceStatus_v[myDeviceId][theEventQueue.inactiveBit] ) return;
1374 static CConnection myConnections;
1375 MapDeviceNets(myDeviceId, theEventQueue, myConnections);
1376 if ( myConnections.IsUnknownSourceVoltage() ) {
1377 assert (myConnections.drainVoltage != UNKNOWN_VOLTAGE);
1378 ShortNets(theEventQueue, myDeviceId, myConnections, SOURCE_TO_MASTER_DRAIN);
1379 myQueuePosition = ( myConnections.drainPower_p->type[POWER_BIT] ) ? MAIN_BACK : DELAY_FRONT;
1380 EnqueueAttachedResistors(theEventQueue, myConnections.sourceId, myConnections.drainVoltage, myQueuePosition);
1381 } else if ( myConnections.IsUnknownDrainVoltage() ) { // sourceVoltage != UNKNOWN_VOLTAGE
1382 ShortNets(theEventQueue, myDeviceId, myConnections, DRAIN_TO_MASTER_SOURCE);
1383 myQueuePosition = ( myConnections.sourcePower_p->type[POWER_BIT] ) ? MAIN_BACK : DELAY_FRONT;
1384 EnqueueAttachedResistors(theEventQueue, myConnections.drainId, myConnections.sourceVoltage, myQueuePosition);
1385 } else {
1386 if (gDebug_cvc) cout << "already shorted PRV " << gEventQueueTypeMap[theEventQueue.queueType] << " " << myDeviceId << endl;
1387 AlreadyShorted(theEventQueue, myDeviceId, myConnections);
1388 if ( theEventQueue.virtualNet_v[myConnections.drainId].nextNetId != myConnections.drainId ) { // not terminal
1389 PropagateConnectionType(theEventQueue.virtualNet_v, connectionCount_v[myConnections.drainId].sourceDrainType, myConnections.sourceId);
1390 }
1391 if ( theEventQueue.virtualNet_v[myConnections.sourceId].nextNetId != myConnections.sourceId ) { // not terminal
1392 PropagateConnectionType(theEventQueue.virtualNet_v, connectionCount_v[myConnections.sourceId].sourceDrainType, myConnections.drainId);
1393 }
1394 }
1395 }
1396
PropagateMinMaxVoltages(CEventQueue & theEventQueue)1397 void CCvcDb::PropagateMinMaxVoltages(CEventQueue& theEventQueue) {
1398 eventKey_t myQueueKey = theEventQueue.QueueTime();
1399 deviceId_t myDeviceId = theEventQueue.GetEvent();
1400 deviceStatus_v[myDeviceId][theEventQueue.pendingBit] = false;
1401 if ( deviceStatus_v[myDeviceId][theEventQueue.inactiveBit] ) return;
1402 eventKey_t myOriginalEventKey, myEventKey;
1403 queuePosition_t myQueuePosition;
1404 netId_t myDrainId, mySourceId;
1405 shortDirection_t myDirection;
1406 static CConnection myConnections;
1407 MapDeviceNets(myDeviceId, theEventQueue, myConnections);
1408 // BUG: 20140307 if both nets are known, need highest for max, lowest for min.
1409 if ( myConnections.sourceVoltage != UNKNOWN_VOLTAGE ) {
1410 if ( myConnections.drainVoltage != UNKNOWN_VOLTAGE ) {
1411 if ( theEventQueue.queueType == MIN_QUEUE ) {
1412 if ( myConnections.sourceVoltage <= myConnections.drainVoltage ) {
1413 myDirection = DRAIN_TO_MASTER_SOURCE;
1414 } else {
1415 myDirection = SOURCE_TO_MASTER_DRAIN;
1416 }
1417 } else { // MAX_QUEUE
1418 assert(theEventQueue.queueType == MAX_QUEUE);
1419 if ( myConnections.sourceVoltage >= myConnections.drainVoltage ) {
1420 myDirection = DRAIN_TO_MASTER_SOURCE;
1421 } else {
1422 myDirection = SOURCE_TO_MASTER_DRAIN;
1423 }
1424 }
1425 } else {
1426 myDirection = DRAIN_TO_MASTER_SOURCE;
1427 }
1428 } else if ( myConnections.drainVoltage != UNKNOWN_VOLTAGE ) {
1429 myDirection = SOURCE_TO_MASTER_DRAIN;
1430 } else return; // enqueued due to gate/bias changes. ignore for now.
1431 if ( myDirection == DRAIN_TO_MASTER_SOURCE ) {
1432 myOriginalEventKey = myConnections.sourceVoltage;
1433 myDrainId = myConnections.drainId;
1434 mySourceId = myConnections.sourceId;
1435 myQueuePosition = DefaultQueuePosition_(myConnections.sourcePower_p->type[POWER_BIT], theEventQueue);
1436 } else { // myDirection = SOURCE_TO_MASTER_DRAIN;
1437 myOriginalEventKey = myConnections.drainVoltage;
1438 myDrainId = myConnections.sourceId;
1439 mySourceId = myConnections.drainId;
1440 myQueuePosition = DefaultQueuePosition_(myConnections.drainPower_p->type[POWER_BIT], theEventQueue);
1441 }
1442 myEventKey = myOriginalEventKey;
1443 string myAdjustedCalculation = "";
1444 if ( IsIrrelevant(theEventQueue, myDeviceId, myConnections, myEventKey, DEQUEUE) ) { // both source/drain defined handled here
1445 deviceStatus_v[myDeviceId][theEventQueue.inactiveBit] = true;
1446 } else {
1447 if ( myDirection == DRAIN_TO_MASTER_SOURCE) assert (myConnections.drainVoltage == UNKNOWN_VOLTAGE);
1448
1449 myAdjustedCalculation = AdjustKey(theEventQueue, myDeviceId, myConnections, myEventKey, myQueuePosition, myDirection, PRINT_WARNINGS);
1450 if ( myQueuePosition == SKIP_QUEUE ) return;
1451 if (gDebug_cvc) cout << "DEBUG propagation:(" << gEventQueueTypeMap[theEventQueue.queueType] << ") device: " << myDeviceId << " QueueKey: " << myQueueKey << " EventKey: " << myEventKey << endl;
1452 if ( theEventQueue.Later(myEventKey, myQueueKey) ) {
1453 theEventQueue.AddEvent(myEventKey, myDeviceId, myQueuePosition);
1454 deviceStatus_v[myDeviceId][theEventQueue.pendingBit] = true;
1455 theEventQueue.requeueCount++;
1456 if (gDebug_cvc) cout << "requeueing" << endl;
1457 } else {
1458 ShortNets(theEventQueue, myDeviceId, myConnections, myDirection, myEventKey, myAdjustedCalculation);
1459 if ( theEventQueue.queueType == MIN_QUEUE && myOriginalEventKey < myEventKey && IsPmos_(deviceType_v[myConnections.deviceId]) ) {
1460 voltage_t myMaxVoltage = MaxVoltage(myDrainId);
1461 if ( IsDerivedFromFloating(maxNet_v, myDrainId) || myMaxVoltage == UNKNOWN_VOLTAGE || myMaxVoltage == myEventKey || netStatus_v[mySourceId][NEEDS_MAX_CHECK] ) {
1462 if (netVoltagePtr_v[myDrainId].full ) {
1463 if ( netVoltagePtr_v[myDrainId].full->pullUpVoltage() == UNKNOWN_VOLTAGE || netVoltagePtr_v[myDrainId].full->pullUpVoltage() < myEventKey ) {
1464 if (gDebug_cvc) cout << "DEBUG: Adding max check at net " << myDrainId << endl;
1465 netStatus_v[myDrainId][NEEDS_MAX_CHECK] = true;
1466 }
1467 } else cout << "DEBUG: missing voltage for max check " << NetName(myDrainId) << endl;
1468 }
1469 } else if ( theEventQueue.queueType == MAX_QUEUE && myOriginalEventKey > myEventKey && IsNmos_(deviceType_v[myConnections.deviceId]) ) {
1470 voltage_t myMinVoltage = MinVoltage(myDrainId);
1471 if ( IsDerivedFromFloating(minNet_v, myDrainId) || myMinVoltage == UNKNOWN_VOLTAGE || myMinVoltage == myEventKey || netStatus_v[mySourceId][NEEDS_MIN_CHECK] ) {
1472 if ( netVoltagePtr_v[myDrainId].full ) {
1473 if ( netVoltagePtr_v[myDrainId].full->pullDownVoltage() == UNKNOWN_VOLTAGE || netVoltagePtr_v[myDrainId].full->pullDownVoltage() > myEventKey ) {
1474 if (gDebug_cvc) cout << "DEBUG: Adding min check at net " << myDrainId << endl;
1475 netStatus_v[myDrainId][NEEDS_MIN_CHECK] = true;
1476 }
1477 } else cout << "DEBUG: missing voltage for min check " << NetName(myDrainId) << endl;
1478 }
1479 }
1480 EnqueueAttachedDevices(theEventQueue, myDrainId, myEventKey);
1481 if ( deviceType_v[myDeviceId] == RESISTOR && myOriginalEventKey == myEventKey ) {
1482 // resistors propagating unchanged voltages
1483 CDeviceCount myDeviceCount(myDrainId, this);
1484 if ( theEventQueue.queueType == MIN_QUEUE && myDeviceCount.resistorCount == 1 && myDeviceCount.activePmosCount == 0 ) {
1485 // one resistor connected to no pmos
1486 ShortNets(minEventQueue, myDeviceId, myConnections, myDirection, myEventKey, "power through resistor");
1487 EnqueueAttachedDevices(minEventQueue, myDrainId, myEventKey);
1488 } else if (theEventQueue.queueType == MAX_QUEUE && myDeviceCount.resistorCount == 1 && myDeviceCount.activeNmosCount == 0 ) {
1489 // one resistor connected to no nmos
1490 ShortNets(maxEventQueue, myDeviceId, myConnections, myDirection, myEventKey, "power through resistor");
1491 EnqueueAttachedDevices(maxEventQueue, myDrainId, myEventKey);
1492 }
1493 }
1494 }
1495 }
1496 }
1497
PropagateSimVoltages(CEventQueue & theEventQueue,propagation_t thePropagationType)1498 void CCvcDb::PropagateSimVoltages(CEventQueue& theEventQueue, propagation_t thePropagationType) {
1499 eventKey_t myQueueKey = theEventQueue.QueueTime();
1500 deviceId_t myDeviceId = theEventQueue.GetEvent();
1501 deviceStatus_v[myDeviceId][theEventQueue.pendingBit] = false;
1502 if ( deviceStatus_v[myDeviceId][theEventQueue.inactiveBit] ) return;
1503 voltage_t mySimVoltage;
1504 netId_t myNextNetId;
1505 shortDirection_t myDirection;
1506 static CConnection myConnections;
1507 MapDeviceNets(myDeviceId, theEventQueue, myConnections);
1508 // 20140522A: when both source and drain are known, choose high for pmos, low for nmos
1509 if ( myConnections.IsUnknownSourceVoltage() ) {
1510 if ( myConnections.IsUnknownDrainVoltage() ) return; // enqueued to do gate/bias changes. ignore for now.
1511 myDirection = SOURCE_TO_MASTER_DRAIN;
1512 if ( myConnections.drainPower_p && myConnections.drainPower_p->type[HIZ_BIT] && ! IsSCRCPower(myConnections.drainPower_p) ) return; // Don't propagate non-SCRC Hi-Z power
1513 } else if ( myConnections.IsUnknownDrainVoltage() ) {
1514 myDirection = DRAIN_TO_MASTER_SOURCE;
1515 if ( myConnections.sourcePower_p && myConnections.sourcePower_p->type[HIZ_BIT] && ! IsSCRCPower(myConnections.sourcePower_p) ) return; // Don't propagate non-SCRC Hi-Z power
1516 } else if ( myConnections.sourceVoltage == UNKNOWN_VOLTAGE && myConnections.drainVoltage == UNKNOWN_VOLTAGE ) { // drain/source Hi-Z, use default
1517 myDirection = DRAIN_TO_MASTER_SOURCE;
1518 } else if ( myConnections.sourceVoltage == UNKNOWN_VOLTAGE ) { // source Hi-Z
1519 myDirection = SOURCE_TO_MASTER_DRAIN;
1520 } else if ( myConnections.drainVoltage == UNKNOWN_VOLTAGE ) { // drain Hi-Z
1521 myDirection = DRAIN_TO_MASTER_SOURCE;
1522 } else if ( ( IsPmos_(deviceType_v[myDeviceId]) && myConnections.drainVoltage >= myConnections.sourceVoltage ) \
1523 || ( IsNmos_(deviceType_v[myDeviceId]) && myConnections.drainVoltage <= myConnections.sourceVoltage ) ) { // both source drain known
1524 myDirection = SOURCE_TO_MASTER_DRAIN;
1525 } else {
1526 myDirection = DRAIN_TO_MASTER_SOURCE;
1527 }
1528 if ( myDirection == SOURCE_TO_MASTER_DRAIN ) {
1529 mySimVoltage = myConnections.drainVoltage;
1530 myNextNetId = myConnections.sourceId;
1531 // TODO: Possibly not necessary. Only primed voltages are processed.
1532 if ( thePropagationType == POWER_NETS_ONLY && ! IsPriorityPower_(myConnections.drainPower_p) ) return;
1533 } else {
1534 mySimVoltage = myConnections.sourceVoltage;
1535 myNextNetId = myConnections.drainId;
1536 // TODO: Possibly not necessary. Only primed voltages are processed.
1537 if ( thePropagationType == POWER_NETS_ONLY && ! IsPriorityPower_(myConnections.sourcePower_p) ) return;
1538 }
1539 if ( IsMos_(deviceType_v[myDeviceId]) ) {
1540 if ( myConnections.gateVoltage == UNKNOWN_VOLTAGE ) {
1541 // check always on devices
1542 voltage_t myMaxGateVoltage = MaxVoltage(myConnections.masterGateNet.finalNetId);
1543 voltage_t myMinGateVoltage = MinVoltage(myConnections.masterGateNet.finalNetId);
1544 if ( IsPmos_(deviceType_v[myDeviceId]) && myMaxGateVoltage != UNKNOWN_VOLTAGE && mySimVoltage != UNKNOWN_VOLTAGE
1545 && myMaxGateVoltage < mySimVoltage + myConnections.device_p->model_p->Vth ) {
1546 if ( ! IsAlwaysOnCandidate(myDeviceId, myDirection) ) return;
1547 myConnections.gateVoltage = myMaxGateVoltage;
1548 } else if ( IsNmos_(deviceType_v[myDeviceId]) && myMinGateVoltage != UNKNOWN_VOLTAGE && mySimVoltage != UNKNOWN_VOLTAGE
1549 && myMinGateVoltage > mySimVoltage + myConnections.device_p->model_p->Vth ) {
1550 if ( ! IsAlwaysOnCandidate(myDeviceId, myDirection) ) return;
1551 myConnections.gateVoltage = myMinGateVoltage;
1552 } else if ( thePropagationType == POWER_NETS_ONLY || // no mos-diode propagation for fixed-only
1553 (myConnections.gateId != myConnections.sourceId && myConnections.gateId != myConnections.drainId)) return; // skip unknown non-diode mos gates
1554 } else {
1555 if ( thePropagationType == POWER_NETS_ONLY && ! IsPriorityPower_(myConnections.gatePower_p) ) return;
1556 }
1557 }
1558 if (deviceType_v[myDeviceId] == FUSE_ON && thePropagationType != ALL_NETS_AND_FUSE) return;
1559 if ( deviceType_v[myDeviceId] == FUSE_OFF /* && thePropagationType == ALL_NETS_AND_FUSE */ ) {
1560 deviceStatus_v[myDeviceId][theEventQueue.inactiveBit] = true;
1561 } else if ( IsIrrelevant(theEventQueue, myDeviceId, myConnections, mySimVoltage, DEQUEUE) ) {
1562 deviceStatus_v[myDeviceId][theEventQueue.inactiveBit] = true;
1563 } else {
1564 if (gDebug_cvc) cout << "DEBUG propagation:(" << gEventQueueTypeMap[theEventQueue.queueType] << ") device: " << myDeviceId << " QueueKey: " << myQueueKey << " EventKey: " << mySimVoltage << endl;
1565 string myCalculation;
1566 myCalculation = AdjustSimVoltage(theEventQueue, myDeviceId, myConnections, mySimVoltage, myDirection, thePropagationType);
1567 if ( thePropagationType == POWER_NETS_ONLY && ! IsEmpty(myCalculation) ) return; // skip adjusted sim voltages with fixed-only
1568 if ( mySimVoltage == UNKNOWN_VOLTAGE ) return; // gate input = Vth (non mos diode)
1569 ShortSimNets(theEventQueue, myDeviceId, myConnections, myDirection, mySimVoltage, myCalculation);
1570 EnqueueAttachedDevices(theEventQueue, myNextNetId, mySimVoltage);
1571 }
1572 }
1573
CalculateResistorVoltage(netId_t theNetId,voltage_t theMinVoltage,resistance_t theMinResistance,voltage_t theMaxVoltage,resistance_t theMaxResistance)1574 void CCvcDb::CalculateResistorVoltage(netId_t theNetId, voltage_t theMinVoltage, resistance_t theMinResistance,
1575 voltage_t theMaxVoltage, resistance_t theMaxResistance ) {
1576 if ( theMinVoltage == UNKNOWN_VOLTAGE || theMaxVoltage == UNKNOWN_VOLTAGE ) return; // myIgnoreResistorFlag = true; // can't propagate unknown voltage
1577 if ( theMinResistance == 0 || theMaxResistance == 0 ) return; //myIgnoreResistorFlag = true; // don't recalculate 0 resistance
1578 netId_t myMinNet = minNet_v[theNetId].finalNetId;
1579 netId_t myMaxNet = maxNet_v[theNetId].finalNetId;
1580 if ( ! netVoltagePtr_v[myMinNet].full || netVoltagePtr_v[myMinNet].full->type[HIZ_BIT] ) return; // don't calculate non-power or open
1581 if ( ! netVoltagePtr_v[myMaxNet].full || netVoltagePtr_v[myMaxNet].full->type[HIZ_BIT] ) return; // don't calculate non-power or open
1582 if ( // myIgnoreResistorFlag == false &&
1583 minNet_v[theNetId].nextNetId != maxNet_v[theNetId].nextNetId && // different paths to min/max
1584 ( minNet_v.IsTerminal(minNet_v[theNetId].nextNetId) || theNetId == maxNet_v[minNet_v[theNetId].nextNetId].nextNetId ) &&
1585 ( maxNet_v.IsTerminal(maxNet_v[theNetId].nextNetId) || theNetId == minNet_v[maxNet_v[theNetId].nextNetId].nextNetId ) ) {
1586 if ( ! netVoltagePtr_v[theNetId].full ) {
1587 cvcParameters.cvcPowerPtrList.push_back(new CPower(theNetId));
1588 netVoltagePtr_v[theNetId].full = cvcParameters.cvcPowerPtrList.back();
1589 netVoltagePtr_v[theNetId].full->extraData = new CExtraPowerData;
1590 netVoltagePtr_v[theNetId].full->extraData->powerSignal = CPower::powerDefinitionText.SetTextAddress(RESISTOR_TEXT);
1591 }
1592 CPower * myPower_p = netVoltagePtr_v[theNetId].full;
1593 voltage_t myNewVoltage = theMinVoltage + long( theMaxVoltage - theMinVoltage ) * theMinResistance / ( theMinResistance + theMaxResistance );
1594 calculatedResistanceInfo_v[theNetId] = NetName(theNetId, PRINT_CIRCUIT_ON) + " " + to_string<voltage_t>(myNewVoltage);
1595 calculatedResistanceInfo_v[theNetId] += " MinV:" + to_string<voltage_t>(theMinVoltage) + " MaxV:" + to_string<voltage_t>(theMaxVoltage);
1596 calculatedResistanceInfo_v[theNetId] += " MinR:" + to_string<resistance_t>(theMinResistance) + " MaxR:" + to_string<resistance_t>(theMaxResistance);
1597 calculatedResistanceInfo_v[theNetId] += (netVoltagePtr_v[theNetId].full->type[RESISTOR_BIT] ? " explicit" : " implicit");
1598 string myCalculation = " R: " + PrintParameter(theMaxVoltage, 1000) + "V -> " + AddSiSuffix((float) theMaxResistance) + " ohm -> ";
1599 myCalculation += PrintParameter(myNewVoltage, 1000) + "V -> ";
1600 myCalculation += AddSiSuffix((float) theMinResistance) + " ohm -> " + PrintParameter(theMinVoltage, 1000) + "V";
1601
1602 myPower_p->simVoltage = myNewVoltage;
1603 myPower_p->simCalculationType = RESISTOR_CALCULATION;
1604 myPower_p->maxVoltage = myNewVoltage;
1605 myPower_p->maxCalculationType = RESISTOR_CALCULATION;
1606 myPower_p->minVoltage = myNewVoltage;
1607 myPower_p->minCalculationType = RESISTOR_CALCULATION;
1608 myPower_p->defaultMinNet = minNet_v[theNetId].finalNetId;
1609 myPower_p->defaultMaxNet = maxNet_v[theNetId].finalNetId;
1610 myPower_p->netId = theNetId;
1611 myPower_p->type[MIN_CALCULATED_BIT] = true;
1612 // myPower_p->type[SIM_CALCULATED_BIT] = true;
1613 myPower_p->type[MAX_CALCULATED_BIT] = true;
1614 myPower_p->type[ANALOG_BIT] = true;
1615 string myDefinition = myPower_p->definition + (" calculation=> " + myCalculation);
1616 myPower_p->definition = CPower::powerDefinitionText.SetTextAddress((text_t)myDefinition.c_str());
1617 myPower_p->type[RESISTOR_BIT] = true;
1618 minNet_v.lastUpdate += 1;
1619 simNet_v.lastUpdate += 1;
1620 maxNet_v.lastUpdate += 1;
1621 }
1622 }
1623
PropagateResistorCalculations(netId_t theNetId,CDeviceIdVector & theFirstDevice_v,CDeviceIdVector & theNextDevice_v)1624 void CCvcDb::PropagateResistorCalculations(netId_t theNetId, CDeviceIdVector& theFirstDevice_v, CDeviceIdVector& theNextDevice_v) {
1625 CFullConnection myConnections;
1626 for ( deviceId_t device_it = theFirstDevice_v[theNetId]; device_it != UNKNOWN_DEVICE; device_it = theNextDevice_v[device_it] ) {
1627 if ( deviceType_v[device_it] == RESISTOR ) {
1628 MapDeviceNets(device_it, myConnections);
1629 if ( netVoltagePtr_v[myConnections.drainId].full == NULL ) {
1630 cvcParameters.cvcPowerPtrList.push_back(new CPower(myConnections.drainId));
1631 netVoltagePtr_v[myConnections.drainId].full = cvcParameters.cvcPowerPtrList.back();
1632 netVoltagePtr_v[myConnections.drainId].full->type[RESISTOR_BIT] = true;
1633 netVoltagePtr_v[myConnections.drainId].full->extraData = new CExtraPowerData;
1634 netVoltagePtr_v[myConnections.drainId].full->extraData->powerSignal = CPower::powerDefinitionText.SetTextAddress(RESISTOR_TEXT);
1635 }
1636 if ( netVoltagePtr_v[myConnections.sourceId].full == NULL ) {
1637 cvcParameters.cvcPowerPtrList.push_back(new CPower(myConnections.sourceId));
1638 netVoltagePtr_v[myConnections.sourceId].full = cvcParameters.cvcPowerPtrList.back();
1639 netVoltagePtr_v[myConnections.sourceId].full->type[RESISTOR_BIT] = true;
1640 netVoltagePtr_v[myConnections.sourceId].full->extraData = new CExtraPowerData;
1641 netVoltagePtr_v[myConnections.sourceId].full->extraData->powerSignal = CPower::powerDefinitionText.SetTextAddress(RESISTOR_TEXT);
1642 }
1643 }
1644 }
1645 }
1646
CalculateResistorVoltages()1647 void CCvcDb::CalculateResistorVoltages() {
1648 CFullConnection myConnections;
1649 calculatedResistanceInfo_v.clear();
1650 for (auto power_ppit = cvcParameters.cvcPowerPtrList.begin(); power_ppit != cvcParameters.cvcPowerPtrList.end(); power_ppit++) {
1651 // since new entries are appended to the power list, this routine is effectively recursive
1652 if ( (*power_ppit)->type[RESISTOR_BIT] ) { // && (*power_ppit)->simVoltage == UNKNOWN_VOLTAGE ) {
1653 netId_t myPowerNet = (*power_ppit)->netId;
1654 if ( myPowerNet != UNKNOWN_NET && netVoltagePtr_v[myPowerNet].full == *power_ppit ) { // process only used power nodes (ununsed power kept in powerPtrList)
1655 PropagateResistorCalculations(myPowerNet, firstSource_v, nextSource_v);
1656 PropagateResistorCalculations(myPowerNet, firstDrain_v, nextDrain_v);
1657 }
1658 }
1659 }
1660 for (deviceId_t device_it = 0; device_it < deviceCount; device_it++ ) {
1661 if ( deviceType_v[device_it] == RESISTOR && deviceStatus_v[device_it][SIM_INACTIVE] == false ) {
1662 MapDeviceNets(device_it, myConnections);
1663 if ( ( netVoltagePtr_v[myConnections.sourceId].full == NULL && connectionCount_v[myConnections.sourceId].sourceDrainType == RESISTOR_ONLY ) ||
1664 ( netVoltagePtr_v[myConnections.sourceId].full && netVoltagePtr_v[myConnections.sourceId].full->type[RESISTOR_BIT] && netVoltagePtr_v[myConnections.sourceId].full->simVoltage == UNKNOWN_VOLTAGE ) ) {
1665 if ( myConnections.minSourceVoltage != myConnections.maxSourceVoltage ) {
1666 CalculateResistorVoltage(myConnections.sourceId, myConnections.minSourceVoltage, myConnections.masterMinSourceNet.finalResistance,
1667 myConnections.maxSourceVoltage, myConnections.masterMaxSourceNet.finalResistance);
1668
1669 }
1670 }
1671 if ( ( netVoltagePtr_v[myConnections.drainId].full == NULL && connectionCount_v[myConnections.drainId].sourceDrainType == RESISTOR_ONLY ) ||
1672 ( netVoltagePtr_v[myConnections.drainId].full && netVoltagePtr_v[myConnections.drainId].full->type[RESISTOR_BIT] && netVoltagePtr_v[myConnections.drainId].full->simVoltage == UNKNOWN_VOLTAGE ) ) {
1673 if ( myConnections.minDrainVoltage != myConnections.maxDrainVoltage ) {
1674 CalculateResistorVoltage(myConnections.drainId, myConnections.minDrainVoltage, myConnections.masterMinDrainNet.finalResistance,
1675 myConnections.maxDrainVoltage, myConnections.masterMaxDrainNet.finalResistance);
1676 }
1677 }
1678 }
1679 }
1680 netId_t myLastPowerNet;
1681 vector<bool> myPrintedPower(netCount, false);
1682 for (auto power_ppit = cvcParameters.cvcPowerPtrList.begin(); power_ppit != cvcParameters.cvcPowerPtrList.end(); power_ppit++) {
1683 if ( myPrintedPower[(*power_ppit)->netId] ) continue; // already printed
1684 if ( (*power_ppit)->type[RESISTOR_BIT] ) {
1685 netId_t myPowerNet = (*power_ppit)->netId;
1686 if ( netVoltagePtr_v[myPowerNet].full->simVoltage == UNKNOWN_VOLTAGE ) {
1687 if ( ! IsEmpty(netVoltagePtr_v[myPowerNet].full->definition) ) {
1688 reportFile << "WARNING: Could not calculate explicit resistor voltage for " << NetName((*power_ppit)->netId, PRINT_CIRCUIT_ON) << endl;
1689 }
1690 } else if ( IsCalculatedVoltage_((*power_ppit)) ) {
1691 if ( netVoltagePtr_v[myPowerNet].full != *power_ppit ) continue; // skip unused power nodes
1692 netId_t myNextNet = minNet_v[myPowerNet].nextNetId;
1693 while ( netVoltagePtr_v[myNextNet].full && netVoltagePtr_v[myNextNet].full->simVoltage != UNKNOWN_VOLTAGE && ! minNet_v.IsTerminal(myNextNet) ) {
1694 myPowerNet = myNextNet;
1695 myNextNet = minNet_v[myNextNet].nextNetId;
1696 }
1697 do {
1698 debugFile << "INFO: Resistor voltage calculation " << calculatedResistanceInfo_v[myPowerNet] << endl;
1699 myPrintedPower[(*power_ppit)->netId] = true;
1700 myLastPowerNet = myPowerNet;
1701 myPowerNet = maxNet_v[myPowerNet].nextNetId;
1702 minNet_v[myLastPowerNet].nextNetId = maxNet_v[myLastPowerNet].nextNetId = myLastPowerNet;
1703 minNet_v[myLastPowerNet].finalNetId = maxNet_v[myLastPowerNet].finalNetId = myLastPowerNet;
1704 } while ( netVoltagePtr_v[myPowerNet].full && netVoltagePtr_v[myPowerNet].full->simVoltage != UNKNOWN_VOLTAGE && ! maxNet_v.IsTerminal(myPowerNet));
1705 debugFile << endl;
1706 }
1707 }
1708 }
1709 }
1710
SetResistorVoltagesByPower()1711 void CCvcDb::SetResistorVoltagesByPower() {
1712 reportFile << "CVC: Calculating resistor voltages..." << endl;
1713 queuePosition_t myQueuePosition;
1714 for (CPowerPtrList::iterator power_ppit = cvcParameters.cvcPowerPtrList.begin(); power_ppit != cvcParameters.cvcPowerPtrList.end(); power_ppit++) {
1715 // should only be defined voltages at this time.
1716 CPower * myPower_p = * power_ppit;
1717 netId_t myNetId = myPower_p->netId;
1718 if ( myPower_p->minVoltage != UNKNOWN_VOLTAGE ) {
1719 myQueuePosition = DefaultQueuePosition_(myPower_p->type[POWER_BIT], minEventQueue);
1720 EnqueueAttachedResistors(minEventQueue, myNetId, myPower_p->minVoltage, myQueuePosition);
1721 }
1722 if ( myPower_p->maxVoltage != UNKNOWN_VOLTAGE ) {
1723 myQueuePosition = DefaultQueuePosition_(myPower_p->type[POWER_BIT], maxEventQueue);
1724 EnqueueAttachedResistors(maxEventQueue, myNetId, myPower_p->maxVoltage, myQueuePosition);
1725 }
1726 }
1727 minEventQueue.queueStart = true;
1728 maxEventQueue.queueStart = true;
1729 while (minEventQueue.QueueSize() + maxEventQueue.QueueSize() > 0) {
1730 if (minEventQueue.QueueSize() > maxEventQueue.QueueSize()) {
1731 PropagateResistorVoltages(minEventQueue);
1732 } else {
1733 PropagateResistorVoltages(maxEventQueue);
1734 }
1735 }
1736 CalculateResistorVoltages();
1737 cvcCircuitList.PrintAndResetCircuitErrors(this, cvcParameters.cvcCircuitErrorLimit, logFile, errorFile, "! Resistor Errors");
1738 if ( gDebug_cvc ) {
1739 PrintVirtualNets(minNet_v, "(minimum r)");
1740 PrintVirtualNets(maxNet_v, "(maximum r)");
1741 PrintVirtualNets(simNet_v, "(simulation r)");
1742 }
1743 }
1744
CheckEstimateDependency(CDependencyMap & theDependencyMap,size_t theEstimateType,list<netId_t> & theDependencyList)1745 bool CCvcDb::CheckEstimateDependency(CDependencyMap& theDependencyMap, size_t theEstimateType, list<netId_t>& theDependencyList) {
1746 assert(! theDependencyList.empty());
1747 for (auto net_pit = theDependencyList.begin(); net_pit != theDependencyList.end(); net_pit++) {
1748 if ( netStatus_v[*net_pit][theEstimateType] == false ) return false;
1749 if ( theDependencyMap.count(*net_pit) == 0 ) continue;
1750 if ( CheckEstimateDependency(theDependencyMap, theEstimateType, theDependencyMap[*net_pit]) == false ) return false;
1751 }
1752 return(true);
1753 }
1754
CheckEstimateDependencies()1755 void CCvcDb::CheckEstimateDependencies() {
1756 for(auto netListPair_pit = minConnectionDependencyMap.begin(); netListPair_pit != minConnectionDependencyMap.end(); netListPair_pit++) {
1757 netId_t myNetId = netListPair_pit->first;
1758 if ( gDebug_cvc ) cout << "DEBUG: Min dependency queue " << myNetId << "(" << netListPair_pit->second.front() << "-" << netListPair_pit->second.size() << ")" << endl;
1759 if ( netStatus_v[myNetId][NEEDS_MIN_CONNECTION] == false ) continue;
1760 netStatus_v[myNetId][NEEDS_MIN_CONNECTION] = CheckEstimateDependency(minConnectionDependencyMap, NEEDS_MIN_CONNECTION, netListPair_pit->second);
1761 }
1762 for(auto netListPair_pit = maxConnectionDependencyMap.begin(); netListPair_pit != maxConnectionDependencyMap.end(); netListPair_pit++) {
1763 netId_t myNetId = netListPair_pit->first;
1764 if ( gDebug_cvc ) cout << "DEBUG: Max dependency queue " << myNetId << "(" << netListPair_pit->second.front() << "-" << netListPair_pit->second.size() << ")" << endl;
1765 if ( netStatus_v[myNetId][NEEDS_MAX_CONNECTION] == false ) continue;
1766 netStatus_v[myNetId][NEEDS_MAX_CONNECTION] = CheckEstimateDependency(maxConnectionDependencyMap, NEEDS_MAX_CONNECTION, netListPair_pit->second);
1767 }
1768 }
1769
SetTrivialMinMaxPower()1770 void CCvcDb::SetTrivialMinMaxPower() {
1771 reportFile << "Processing trivial nets";
1772 cout.flush();
1773 deviceId_t myNmos, myPmos;
1774 CConnection myConnections;
1775 netId_t myGroundNet, myPowerNet, myGateNet;
1776 voltage_t myMinPower, myMaxPower;
1777 resistance_t myNmosResistance, myPmosResistance;
1778 int myTrivialCount = 0;
1779 int myPrintCount = 1000000;
1780 set<string> myUndefinedPowerNets;
1781 for ( netId_t net_it = 0; net_it < netCount; net_it++ ) {
1782 if ( net_it != GetEquivalentNet(net_it) ) continue;
1783 if ( myPrintCount-- <= 0 ) {
1784 cout << "."; cout.flush();
1785 myPrintCount = 1000000;
1786 }
1787 if ( minNet_v[net_it].nextNetId != net_it || maxNet_v[net_it].nextNetId != net_it ) continue; // already assigned
1788 if ( netVoltagePtr_v[net_it].full
1789 && ! ( netVoltagePtr_v[net_it].full->minVoltage == UNKNOWN_VOLTAGE && netVoltagePtr_v[net_it].full->minVoltage == UNKNOWN_VOLTAGE ) ) continue; // skip defined min/max
1790 if ( connectionCount_v[net_it].sourceCount + connectionCount_v[net_it].drainCount == 2 ) { // only hits master equivalent nets
1791 if ( connectionCount_v[net_it].sourceDrainType[NMOS] && connectionCount_v[net_it].sourceDrainType[PMOS] ) {
1792 myNmos = UNKNOWN_DEVICE;
1793 myPmos = UNKNOWN_DEVICE;
1794 for ( deviceId_t device_it = firstDrain_v[net_it]; device_it != UNKNOWN_DEVICE; device_it = nextDrain_v[device_it] ) {
1795 //if ( sourceNet_v[device_it] == gateNet_v[device_it] ) continue; // skip mos diodes (need this for tied inverters)
1796 if ( sourceNet_v[device_it] == drainNet_v[device_it] ) continue; // skip mos capacitors
1797
1798 if ( IsNmos_(deviceType_v[device_it]) ) {
1799 if ( myNmos == UNKNOWN_DEVICE || sourceNet_v[device_it] != gateNet_v[device_it] ) { // only use tied input if nothing else is available
1800 myNmos = device_it;
1801 }
1802 }
1803 if ( IsPmos_(deviceType_v[device_it]) ) {
1804 if ( myPmos == UNKNOWN_DEVICE || sourceNet_v[device_it] != gateNet_v[device_it] ) { // only use tied input if nothing else is available
1805 myPmos = device_it;
1806 }
1807 }
1808 }
1809 for ( deviceId_t device_it = firstSource_v[net_it]; device_it != UNKNOWN_DEVICE; device_it = nextSource_v[device_it] ) {
1810 if ( sourceNet_v[device_it] == drainNet_v[device_it] ) continue; // skip mos capacitors
1811
1812 if ( IsNmos_(deviceType_v[device_it]) ) {
1813 if ( myNmos == UNKNOWN_DEVICE || drainNet_v[device_it] != gateNet_v[device_it] ) { // only use tied input if nothing else is available
1814 myNmos = device_it;
1815 }
1816 }
1817 if ( IsPmos_(deviceType_v[device_it]) ) {
1818 if ( myPmos == UNKNOWN_DEVICE || drainNet_v[device_it] != gateNet_v[device_it] ) { // only use tied input if nothing else is available
1819 myPmos = device_it;
1820 }
1821 }
1822 }
1823 if ( myNmos == UNKNOWN_DEVICE ) continue;
1824 if ( myPmos == UNKNOWN_DEVICE ) continue;
1825 if ( deviceStatus_v[myNmos][MIN_INACTIVE] ) continue;
1826 if ( deviceStatus_v[myPmos][MAX_INACTIVE] ) continue;
1827 MapDeviceNets(myNmos, minEventQueue, myConnections);
1828 myGateNet = myConnections.gateId;
1829 if ( myConnections.sourceId == net_it ) {
1830 myGroundNet = myConnections.drainId;
1831 } else if ( myConnections.drainId == net_it ) {
1832 myGroundNet = myConnections.sourceId;
1833 } else {
1834 continue; // net already assigned
1835 }
1836 if ( myConnections.gateId == net_it ) continue; // mos diodes are not trivial
1837 myNmosResistance = myConnections.resistance;
1838 MapDeviceNets(myPmos, maxEventQueue, myConnections);
1839 if ( myConnections.sourceId == net_it ) {
1840 myPowerNet = myConnections.drainId;
1841 } else if ( myConnections.drainId == net_it ) {
1842 myPowerNet = myConnections.sourceId;
1843 } else {
1844 continue; // net already assigned
1845 }
1846 if ( myConnections.gateId == net_it ) continue; // mos diodes are not trivial
1847 myPmosResistance = myConnections.resistance;
1848 if ( myGateNet != myConnections.gateId ) continue; // ignore non-inverters
1849 if ( netVoltagePtr_v[myGroundNet].full && netVoltagePtr_v[myPowerNet].full && netVoltagePtr_v[myGroundNet].full->type[POWER_BIT] && netVoltagePtr_v[myPowerNet].full->type[POWER_BIT] ) {
1850 if ( netVoltagePtr_v[myGroundNet].full->minVoltage != netVoltagePtr_v[myGroundNet].full->maxVoltage ) continue; // ignore variable power
1851 if ( netVoltagePtr_v[myPowerNet].full->minVoltage != netVoltagePtr_v[myPowerNet].full->maxVoltage ) continue; // ignore variable power
1852 myMinPower = netVoltagePtr_v[myGroundNet].full->minVoltage;
1853 myMaxPower = netVoltagePtr_v[myPowerNet].full->maxVoltage;
1854 if ( myMaxPower != UNKNOWN_VOLTAGE && myMinPower < myMaxPower ) { // implies myMinPower != UNKNOWN_VOLTAGE
1855 minNet_v.Set(net_it, myGroundNet, myNmosResistance, 0);
1856 CheckResistorOverflow_(minNet_v[net_it].resistance, net_it, logFile);
1857 maxNet_v.Set(net_it, myPowerNet, myPmosResistance, 0);
1858 CheckResistorOverflow_(maxNet_v[net_it].resistance, net_it, logFile);
1859 deviceStatus_v[myNmos][MIN_INACTIVE] = true;
1860 deviceStatus_v[myNmos][MAX_INACTIVE] = true;
1861 deviceStatus_v[myPmos][MIN_INACTIVE] = true;
1862 deviceStatus_v[myPmos][MAX_INACTIVE] = true;
1863 myTrivialCount++;
1864 if ( inverterNet_v[net_it] == UNKNOWN_NET ) {
1865 inverterNet_v[net_it] = myGateNet;
1866 } else if ( inverterNet_v[net_it] != myGateNet ) {
1867 reportFile << "WARNING: could not set " << myGateNet << " ->inv-> " << net_it;
1868 reportFile << " because " << inverterNet_v[net_it] << " ->inv-> " << net_it << " already set" << endl;
1869 }
1870 }
1871 } else if ( gSetup_cvc ) {
1872 CStatus myGateTypes;
1873 for ( deviceId_t device_it = firstGate_v[net_it]; device_it != UNKNOWN_DEVICE; device_it = nextGate_v[device_it] ) {
1874 if ( IsNmos_(deviceType_v[device_it]) ) {
1875 myGateTypes[NMOS] = true;
1876 } else if ( IsPmos_(deviceType_v[device_it]) ) {
1877 myGateTypes[PMOS] = true;
1878 }
1879 }
1880 if ( myGateTypes != NMOS_PMOS ) continue; // Only flag if has connections to nmos and pmos gates.
1881 if ( ! netVoltagePtr_v[myGroundNet].full && connectionCount_v[myGroundNet].SourceDrainCount() > 5 ) {
1882 myUndefinedPowerNets.insert(NetName(myGroundNet, PRINT_CIRCUIT_ON) + " " + to_string<deviceId_t>(connectionCount_v[myGroundNet].SourceDrainCount()) );
1883 }
1884 if ( ! netVoltagePtr_v[myPowerNet].full && connectionCount_v[myPowerNet].SourceDrainCount() > 5 ) {
1885 myUndefinedPowerNets.insert(NetName(myPowerNet, PRINT_CIRCUIT_ON) + " " + to_string<deviceId_t>(connectionCount_v[myPowerNet].SourceDrainCount()) );
1886 }
1887 }
1888 }
1889 }
1890 }
1891 reportFile << " found " << myTrivialCount << " trivial nets" << endl;
1892 if ( ! myUndefinedPowerNets.empty() ) {
1893 reportFile << endl << "CVC SETUP: Undefined inverter power" << endl << endl;
1894 for ( auto net_pit = myUndefinedPowerNets.begin(); net_pit != myUndefinedPowerNets.end(); net_pit++ ) {
1895 reportFile << *net_pit << endl;
1896 }
1897 reportFile << endl;
1898 }
1899 }
ResetMinMaxActiveStatus()1900 void CCvcDb::ResetMinMaxActiveStatus() {
1901 // possibly change to netVoltagePtr_v
1902 for (auto power_ppit = cvcParameters.cvcPowerPtrList.begin(); power_ppit != cvcParameters.cvcPowerPtrList.end(); power_ppit++) {
1903 (*power_ppit)->active[MIN_ACTIVE] = (*power_ppit)->active[MAX_ACTIVE] = false;
1904 if ( (*power_ppit)->type[INPUT_BIT] // always activate min/max for inputs
1905 || (*power_ppit)->type[POWER_BIT] // always activate min/max for power
1906 || ! ((*power_ppit)->simVoltage == UNKNOWN_VOLTAGE || (*power_ppit)->type[SIM_CALCULATED_BIT]) ) { // activate min/max if sim set but not calculated
1907 if ( (*power_ppit)->minVoltage != UNKNOWN_VOLTAGE && ! (*power_ppit)->active[MIN_IGNORE] ) {
1908 (*power_ppit)->active[MIN_ACTIVE] = true;
1909 }
1910 if ( (*power_ppit)->maxVoltage != UNKNOWN_VOLTAGE && ! (*power_ppit)->active[MAX_IGNORE] ) {
1911 (*power_ppit)->active[MAX_ACTIVE] = true;
1912 }
1913 }
1914 }
1915 }
1916
SetInitialMinMaxPower()1917 void CCvcDb::SetInitialMinMaxPower() {
1918 reportFile << "CVC: Calculating min/max voltages..." << endl;
1919 isFixedMinNet = isFixedMaxNet = false;
1920 minConnectionDependencyMap.clear();
1921 maxConnectionDependencyMap.clear();
1922 unknownGateSet.clear();
1923 ResetMinMaxActiveStatus();
1924 SetTrivialMinMaxPower();
1925 CVirtualNet myMinMasterNet, myMaxMasterNet;
1926 for ( netId_t net_it = 0; net_it < netCount; net_it++ ) {
1927 if ( net_it != GetEquivalentNet(net_it) ) continue; // skip subordinate nets
1928 myMinMasterNet(minNet_v, net_it);
1929 myMaxMasterNet(maxNet_v, net_it);
1930 CPower * myPower_p = netVoltagePtr_v[myMinMasterNet.finalNetId].full;
1931 if ( myPower_p && myPower_p->active[MIN_ACTIVE] ) {
1932 voltage_t myMinVoltage = ( isFixedSimNet && myPower_p->simVoltage != UNKNOWN_VOLTAGE ) ? myPower_p->simVoltage : myPower_p->minVoltage;
1933 if ( myMinVoltage != UNKNOWN_VOLTAGE ) {
1934 EnqueueAttachedDevicesByTerminal(minEventQueue, net_it, firstSource_v, nextSource_v, myMinVoltage);
1935 EnqueueAttachedDevicesByTerminal(minEventQueue, net_it, firstDrain_v, nextDrain_v, myMinVoltage);
1936 }
1937 }
1938 myPower_p = netVoltagePtr_v[myMaxMasterNet.finalNetId].full;
1939 if ( myPower_p && myPower_p->active[MAX_ACTIVE] ) {
1940 voltage_t myMaxVoltage = ( isFixedSimNet && myPower_p->simVoltage != UNKNOWN_VOLTAGE ) ? myPower_p->simVoltage : myPower_p->maxVoltage;
1941 if ( myMaxVoltage != UNKNOWN_VOLTAGE ) {
1942 EnqueueAttachedDevicesByTerminal(maxEventQueue, net_it, firstSource_v, nextSource_v, myMaxVoltage);
1943 EnqueueAttachedDevicesByTerminal(maxEventQueue, net_it, firstDrain_v, nextDrain_v, myMaxVoltage);
1944 }
1945 }
1946 }
1947 minEventQueue.queueStart = true;
1948 maxEventQueue.queueStart = true;
1949 long myLoopCount = minEventQueue.QueueSize() + maxEventQueue.QueueSize();
1950 long myDequeueCount = 0;
1951 bool myProcessingMinQueue = false;
1952 while ( myLoopCount > 0 ) {
1953 if (gDebug_cvc) cout << "Event Queue Size(min/max): " << minEventQueue.mainQueue.size() << "+" << minEventQueue.delayQueue.size();
1954 if (gDebug_cvc) cout << "/" << maxEventQueue.mainQueue.size() << "+" << maxEventQueue.delayQueue.size() << endl;
1955
1956 // main queues first, then by size
1957 if ( myDequeueCount == 0 ) {
1958 if ((minEventQueue.IsNextMainQueue() == maxEventQueue.IsNextMainQueue() && minEventQueue.QueueSize() > maxEventQueue.QueueSize())
1959 || (minEventQueue.IsNextMainQueue() && ! maxEventQueue.IsNextMainQueue()) ) {
1960 myProcessingMinQueue = true;
1961 myDequeueCount = ( minEventQueue.IsNextMainQueue() ) ?
1962 minEventQueue.mainQueue.begin()->second.eventListSize :
1963 minEventQueue.delayQueue.begin()->second.eventListSize;
1964 } else {
1965 myProcessingMinQueue = false;
1966 myDequeueCount = ( maxEventQueue.IsNextMainQueue() ) ?
1967 maxEventQueue.mainQueue.begin()->second.eventListSize :
1968 maxEventQueue.delayQueue.begin()->second.eventListSize;
1969 }
1970 }
1971 assert(myDequeueCount);
1972 if ( myProcessingMinQueue ) {
1973 PropagateMinMaxVoltages(minEventQueue);
1974 } else {
1975 PropagateMinMaxVoltages(maxEventQueue);
1976 }
1977 myDequeueCount --;
1978 myLoopCount --;
1979 if ( myLoopCount < 1 ) {
1980 myLoopCount = minEventQueue.QueueSize() + maxEventQueue.QueueSize();
1981 }
1982 }
1983 // Reset min/max voltage conflict errors
1984 cvcCircuitList.PrintAndResetCircuitErrors(this, cvcParameters.cvcCircuitErrorLimit, logFile, errorFile, "! Power/Ground path through fuse", FUSE_ERROR - FUSE_ERROR, FUSE_MODELS);
1985 cvcCircuitList.PrintAndResetCircuitErrors(this, cvcParameters.cvcCircuitErrorLimit, logFile, errorFile, "! ... voltage already set");
1986 CheckEstimateDependencies();
1987 reportFile << "CVC: Ignoring invalid calculations..." << endl;
1988 size_t myRemovedCount = 0;
1989 for ( netId_t net_it = 0; net_it < netCount; net_it++ ) {
1990 if ( netVoltagePtr_v[net_it].full == NULL ) continue; // skips subordinate nets
1991 RemoveInvalidPower(net_it, myRemovedCount);
1992 }
1993 reportFile << "CVC: Removed " << myRemovedCount << " calculations" << endl;
1994 int myProgressCount = 0;
1995 reportFile << "Copying master nets"; cout.flush();
1996 for ( netId_t net_it = 0; net_it < netCount; net_it++ ) {
1997 if ( ++myProgressCount == 1000000 ) {
1998 cout << "."; cout.flush();
1999 myProgressCount = 0;
2000 }
2001 minNet_v[net_it](minNet_v, net_it); // recalculate final values
2002 maxNet_v[net_it](maxNet_v, net_it); // recalculate final values
2003 }
2004 reportFile << endl;
2005 isFixedMinNet = isFixedMaxNet = true;
2006 if ( gSetup_cvc ) {
2007 set<string> myUndefinedPowerNets;
2008 for ( netId_t net_it = 0; net_it < netCount; net_it++ ) {
2009 if ( ! netVoltagePtr_v[net_it].full || netVoltagePtr_v[net_it].full->type[POWER_BIT] ) continue;
2010 if ( minNet_v[net_it].finalNetId != UNKNOWN_NET && maxNet_v[net_it].finalNetId != UNKNOWN_NET
2011 && netVoltagePtr_v[minNet_v[net_it].finalNetId].full && netVoltagePtr_v[maxNet_v[net_it].finalNetId].full
2012 && netVoltagePtr_v[minNet_v[net_it].finalNetId].full->minVoltage != UNKNOWN_VOLTAGE
2013 && netVoltagePtr_v[maxNet_v[net_it].finalNetId].full->maxVoltage != UNKNOWN_VOLTAGE
2014 && netVoltagePtr_v[minNet_v[net_it].finalNetId].full->minVoltage <= netVoltagePtr_v[maxNet_v[net_it].finalNetId].full->maxVoltage ) continue;
2015 if ( connectionCount_v[net_it].SourceDrainCount() > 9 ) {
2016 myUndefinedPowerNets.insert(NetName(net_it, PRINT_CIRCUIT_ON) + " " + to_string<size_t>(connectionCount_v[net_it].SourceDrainCount()));
2017 }
2018 }
2019 reportFile << endl << "CVC SETUP: possible power nodes..." << endl << endl;
2020 for ( auto item_pit = myUndefinedPowerNets.begin(); item_pit != myUndefinedPowerNets.end(); item_pit++ ) {
2021 reportFile << *item_pit << endl;
2022 }
2023 reportFile << endl;
2024 }
2025 reportFile << "CVC: Ignoring non-conducting devices..." << endl;
2026 // ignore devices with no leak paths
2027 // really slow. has to calculate #device*#terminal instead of #net
2028 size_t myIgnoreCount = 0;
2029 CFullConnection myConnections;
2030 for ( deviceId_t device_it = 0; device_it < deviceCount; device_it++ ) {
2031 if ( deviceStatus_v[device_it][SIM_INACTIVE] ) continue;
2032 MapDeviceSourceDrainNets(device_it, myConnections);
2033 bool myIsHiZDrain = ( myConnections.minDrainPower_p && myConnections.minDrainPower_p->type[HIZ_BIT] ) ||
2034 ( myConnections.maxDrainPower_p && myConnections.maxDrainPower_p->type[HIZ_BIT] );
2035 bool myIsHiZSource = ( myConnections.minSourcePower_p && myConnections.minSourcePower_p->type[HIZ_BIT] ) ||
2036 ( myConnections.maxSourcePower_p && myConnections.maxSourcePower_p->type[HIZ_BIT] );
2037 if ( (! myIsHiZSource && myConnections.minSourceVoltage == UNKNOWN_VOLTAGE && myConnections.maxSourceVoltage == UNKNOWN_VOLTAGE) ||
2038 (! myIsHiZDrain && myConnections.minDrainVoltage == UNKNOWN_VOLTAGE && myConnections.maxDrainVoltage == UNKNOWN_VOLTAGE) ) {
2039 if (gDebug_cvc) cout << "Ignoring device " << device_it << " Connected to unknown min/max voltage." << endl;
2040 IgnoreDevice(device_it);
2041 myIgnoreCount++;
2042 }
2043 }
2044 reportFile << "CVC: Ignored " << myIgnoreCount << " devices" << endl;
2045 }
2046
IgnoreUnusedDevices()2047 void CCvcDb::IgnoreUnusedDevices() {
2048 CFullConnection myConnections;
2049 for ( deviceId_t device_it = 0; device_it < deviceCount; device_it++ ) {
2050 if ( deviceStatus_v[device_it][SIM_INACTIVE] ) continue;
2051 MapDeviceNets(device_it, myConnections);
2052 if ( myConnections.minSourceVoltage == UNKNOWN_VOLTAGE || myConnections.minDrainVoltage == UNKNOWN_VOLTAGE ||
2053 myConnections.maxSourceVoltage == UNKNOWN_VOLTAGE || myConnections.maxDrainVoltage == UNKNOWN_VOLTAGE ) {
2054 if (gDebug_cvc) cout << "Ignoring device " << device_it << " Connected to unknown min/max voltage." << endl;
2055 IgnoreDevice(device_it);
2056 }
2057 }
2058 }
2059
ResetMinMaxPower()2060 void CCvcDb::ResetMinMaxPower() {
2061 minEventQueue.ResetQueue(deviceCount);
2062 maxEventQueue.ResetQueue(deviceCount);
2063 minNet_v.InitializeUpdateArray();
2064 maxNet_v.InitializeUpdateArray();
2065 for (deviceId_t device_it = 0; device_it < deviceCount; device_it++) {
2066 deviceStatus_v[device_it][MIN_INACTIVE] = deviceStatus_v[device_it][MAX_INACTIVE] = deviceStatus_v[device_it][SIM_INACTIVE];
2067 }
2068 CPower * myVoltage_p;
2069 for (netId_t net_it = 0; net_it < netCount; net_it++) {
2070 if ( isFixedSimNet ) { // after first sim pass
2071 if ( simNet_v[net_it].finalNetId == UNKNOWN_NET
2072 || ! netVoltagePtr_v[simNet_v[net_it].finalNetId].full
2073 || netVoltagePtr_v[simNet_v[net_it].finalNetId].full->simVoltage == UNKNOWN_VOLTAGE ) {
2074 minNet_v[net_it].Copy(simNet_v[net_it]);
2075 maxNet_v[net_it].Copy(simNet_v[net_it]);
2076 } else {
2077 if ( minNet_v[net_it].finalNetId == UNKNOWN_NET
2078 || ! netVoltagePtr_v[minNet_v[net_it].finalNetId].full
2079 || netVoltagePtr_v[minNet_v[net_it].finalNetId].full->minVoltage == UNKNOWN_VOLTAGE
2080 || ( netVoltagePtr_v[simNet_v[net_it].finalNetId].full->minVoltage != UNKNOWN_VOLTAGE
2081 && netVoltagePtr_v[minNet_v[net_it].finalNetId].full->minVoltage <= netVoltagePtr_v[simNet_v[net_it].finalNetId].full->minVoltage ) ) {
2082 minNet_v[net_it].Copy(simNet_v[net_it]);
2083 } else {
2084 minNet_v.Set(net_it, net_it, 0, 0);
2085 }
2086 if ( maxNet_v[net_it].finalNetId == UNKNOWN_NET
2087 || ! netVoltagePtr_v[maxNet_v[net_it].finalNetId].full
2088 || netVoltagePtr_v[maxNet_v[net_it].finalNetId].full->maxVoltage == UNKNOWN_VOLTAGE
2089 || ( netVoltagePtr_v[maxNet_v[net_it].finalNetId].full->maxVoltage != UNKNOWN_VOLTAGE
2090 && netVoltagePtr_v[maxNet_v[net_it].finalNetId].full->maxVoltage >= netVoltagePtr_v[simNet_v[net_it].finalNetId].full->maxVoltage ) ) {
2091 maxNet_v[net_it].Copy(simNet_v[net_it]);
2092 } else {
2093 maxNet_v.Set(net_it, net_it, 0, 0);
2094 }
2095 }
2096 if ( netVoltagePtr_v[net_it].full &&
2097 simNet_v[net_it].finalNetId != UNKNOWN_NET &&
2098 netVoltagePtr_v[simNet_v[net_it].finalNetId].full->simVoltage == UNKNOWN_VOLTAGE ) {
2099 // remove min/max calculations if not equal to sim
2100 if ( netVoltagePtr_v[net_it].full->type[MIN_CALCULATED_BIT] ) {
2101 if ( netVoltagePtr_v[net_it].full == leakVoltagePtr_v[net_it].full ) { // Save old copy before erasing.
2102 leakVoltagePtr_v[net_it].full = new CPower(netVoltagePtr_v[net_it].full);
2103 }
2104 netVoltagePtr_v[net_it].full->type[MIN_CALCULATED_BIT] = false;
2105 netVoltagePtr_v[net_it].full->defaultMinNet = UNKNOWN_NET;
2106 netVoltagePtr_v[net_it].full->minVoltage = UNKNOWN_VOLTAGE;
2107 }
2108 if ( netVoltagePtr_v[net_it].full->type[MAX_CALCULATED_BIT] ) {
2109 if ( netVoltagePtr_v[net_it].full == leakVoltagePtr_v[net_it].full ) { // Save old copy before erasing.
2110 leakVoltagePtr_v[net_it].full = new CPower(netVoltagePtr_v[net_it].full);
2111 }
2112 netVoltagePtr_v[net_it].full->type[MAX_CALCULATED_BIT] = false;
2113 netVoltagePtr_v[net_it].full->defaultMaxNet = UNKNOWN_NET;
2114 netVoltagePtr_v[net_it].full->maxVoltage = UNKNOWN_VOLTAGE;
2115 }
2116 if ( netVoltagePtr_v[net_it].full->type == NO_TYPE && IsEmpty(netVoltagePtr_v[net_it].full->powerSignal()) ) {
2117 if ( gDebug_cvc ) {
2118 cout << "DEBUG: Deleting net: " << net_it;
2119 netVoltagePtr_v[net_it].full->Print(cout);
2120 }
2121 delete netVoltagePtr_v[net_it].full;
2122 netVoltagePtr_v[net_it].full = NULL;
2123 }
2124 }
2125 } else { // first min max. reset from resistance propagation.
2126 if ( minNet_v[net_it].nextNetId == simNet_v[net_it].nextNetId ) {
2127 minNet_v[net_it].finalNetId = simNet_v[net_it].finalNetId;
2128 if ( minNet_v.IsTerminal(net_it) ) { // save resistances for calculated power
2129 minNet_v[net_it].resistance = minNet_v[net_it].finalResistance;
2130 }
2131 } else {
2132 minNet_v.Set(net_it, net_it, 0, 0);
2133 }
2134 if ( maxNet_v[net_it].nextNetId == simNet_v[net_it].nextNetId ) {
2135 maxNet_v[net_it].finalNetId = simNet_v[net_it].finalNetId;
2136 if ( maxNet_v.IsTerminal(net_it) ) { // save resistances for calculated power
2137 maxNet_v[net_it].resistance = maxNet_v[net_it].finalResistance;
2138 }
2139 } else {
2140 maxNet_v.Set(net_it, net_it, 0, 0);
2141 }
2142 }
2143 myVoltage_p = netVoltagePtr_v[net_it].full;
2144 if ( myVoltage_p == NULL ) continue; // skips subordinate nets
2145 if ( isFixedSimNet && myVoltage_p->simVoltage != UNKNOWN_VOLTAGE ) {
2146 // default min/max voltages are not calculated. meaning there is no path to source voltage.
2147 string myDefinition = myVoltage_p->definition;
2148 if ( myVoltage_p->minVoltage == UNKNOWN_VOLTAGE ) {
2149 if ( leakVoltagePtr_v[net_it].full && leakVoltagePtr_v[net_it].full->minVoltage != UNKNOWN_VOLTAGE
2150 && leakVoltagePtr_v[net_it].full->minVoltage > myVoltage_p->simVoltage ) {
2151 myVoltage_p->minVoltage = leakVoltagePtr_v[net_it].full->minVoltage;
2152 myVoltage_p->defaultMinNet = leakVoltagePtr_v[net_it].full->defaultMinNet;
2153 myDefinition += " min=leak";
2154 } else {
2155 myVoltage_p->minVoltage = myVoltage_p->simVoltage;
2156 myVoltage_p->defaultMinNet = UNKNOWN_NET;
2157 myDefinition += " min=sim";
2158 }
2159 myVoltage_p->active[MIN_ACTIVE] = true;
2160 myVoltage_p->type[MIN_CALCULATED_BIT] = true;
2161 }
2162 if ( myVoltage_p->maxVoltage == UNKNOWN_VOLTAGE ) {
2163 if ( leakVoltagePtr_v[net_it].full && leakVoltagePtr_v[net_it].full->maxVoltage != UNKNOWN_VOLTAGE
2164 && leakVoltagePtr_v[net_it].full->maxVoltage < myVoltage_p->simVoltage ) {
2165 myVoltage_p->maxVoltage = leakVoltagePtr_v[net_it].full->maxVoltage;
2166 myVoltage_p->defaultMaxNet = UNKNOWN_NET;
2167 myDefinition += " max=leak";
2168 } else {
2169 myVoltage_p->maxVoltage = myVoltage_p->simVoltage;
2170 myVoltage_p->defaultMaxNet = UNKNOWN_NET;
2171 myDefinition += " max=sim";
2172 }
2173 myVoltage_p->active[MAX_ACTIVE] = true;
2174 myVoltage_p->type[MAX_CALCULATED_BIT] = true;
2175 }
2176 if ( myVoltage_p->active[MIN_ACTIVE] && myVoltage_p->minVoltage > myVoltage_p->simVoltage ) {
2177 reportFile << "WARNING: MIN > SIM " << myVoltage_p->minVoltage << " > " << myVoltage_p->simVoltage << " for " << NetName(net_it, PRINT_CIRCUIT_ON) << endl;
2178 }
2179 if ( myVoltage_p->active[MAX_ACTIVE] && myVoltage_p->maxVoltage < myVoltage_p->simVoltage ) {
2180 reportFile << "WARNING: MAX < SIM " << myVoltage_p->maxVoltage << " < " << myVoltage_p->simVoltage << " for " << NetName(net_it, PRINT_CIRCUIT_ON) << endl;
2181 }
2182 myVoltage_p->definition = CPower::powerDefinitionText.SetTextAddress((text_t)myDefinition.c_str());
2183 } else if ( SimVoltage(net_it) == UNKNOWN_VOLTAGE && IsEmpty(myVoltage_p->powerSignal()) && IsCalculatedVoltage_(myVoltage_p) ) {
2184 if ( gDebug_cvc ) {
2185 cout << "DEBUG: Deleting net: " << net_it;
2186 myVoltage_p->Print(cout);
2187 }
2188 netVoltagePtr_v[net_it].full = NULL;
2189 }
2190
2191 }
2192 SetInitialMinMaxPower();
2193 minNet_v.ClearUpdateArray();
2194 maxNet_v.ClearUpdateArray();
2195 }
2196
SetAnalogNets()2197 void CCvcDb::SetAnalogNets() {
2198 for (netId_t net_it = 0; net_it < netCount; net_it++) {
2199 if ( net_it != GetEquivalentNet(net_it) ) continue; // skip subordinate nets
2200 if ( netVoltagePtr_v[net_it].full && netVoltagePtr_v[net_it].full->type[POWER_BIT] ) continue; // skip power
2201 bool myIsAnalogNet = false;
2202 deviceId_t device_it = firstSource_v[net_it];
2203 while ( ! myIsAnalogNet && device_it != UNKNOWN_DEVICE ) {
2204 if ( GetEquivalentNet(drainNet_v[device_it]) != net_it ) {
2205 switch( deviceType_v[device_it] ) {
2206 case NMOS: case LDDN: case PMOS: case LDDP: {
2207 if ( GetEquivalentNet(gateNet_v[device_it]) == net_it) myIsAnalogNet = true;
2208 break;
2209 }
2210 case RESISTOR: { myIsAnalogNet = true; break; }
2211 default: break;
2212 }
2213 }
2214 device_it = nextSource_v[device_it];
2215 }
2216 device_it = firstDrain_v[net_it];
2217 while ( ! myIsAnalogNet && device_it != UNKNOWN_DEVICE ) {
2218 if ( GetEquivalentNet(sourceNet_v[device_it]) != net_it ) {
2219 switch( deviceType_v[device_it] ) {
2220 case NMOS: case LDDN: case PMOS: case LDDP: {
2221 if ( GetEquivalentNet(gateNet_v[device_it]) == net_it) myIsAnalogNet = true;
2222 break;
2223 }
2224 case RESISTOR: { myIsAnalogNet = true; break; }
2225 default: break;
2226 }
2227 }
2228 device_it = nextDrain_v[device_it];
2229 }
2230 if ( myIsAnalogNet ) {
2231 PropagateAnalogNetType(net_it, 0);
2232 }
2233 }
2234 for (CPowerPtrList::iterator power_ppit = cvcParameters.cvcPowerPtrList.begin(); power_ppit != cvcParameters.cvcPowerPtrList.end(); power_ppit++) {
2235 if ( (*power_ppit)->type[ANALOG_BIT] ) {
2236 PropagateAnalogNetType(GetEquivalentNet((*power_ppit)->netId), 0);
2237 }
2238 }
2239 }
2240
PropagateAnalogNetType(netId_t theNetId,int theGateCount)2241 void CCvcDb::PropagateAnalogNetType(netId_t theNetId, int theGateCount) {
2242 // must propagate through gates for all base analog nets (source/drain may have already been propagated)
2243 bool myIsAlreadyAnalog = netStatus_v[theNetId][ANALOG];
2244 netStatus_v[theNetId][ANALOG] = true;
2245 if ( theGateCount < 1 ) {
2246 PropagateAnalogNetTypeByTerminal(theNetId, firstGate_v, nextGate_v, theGateCount + 1);
2247 }
2248 if ( ! myIsAlreadyAnalog ) {
2249 PropagateAnalogNetTypeByTerminal(theNetId, firstSource_v, nextSource_v, theGateCount);
2250 PropagateAnalogNetTypeByTerminal(theNetId, firstDrain_v, nextDrain_v, theGateCount);
2251 }
2252 }
2253
PropagateAnalogNetTypeByTerminal(netId_t theNetId,CDeviceIdVector & theFirstDevice_v,CDeviceIdVector & theNextDevice_v,int theGateCount)2254 void CCvcDb::PropagateAnalogNetTypeByTerminal(netId_t theNetId, CDeviceIdVector& theFirstDevice_v, CDeviceIdVector& theNextDevice_v, int theGateCount) {
2255 for (deviceId_t device_it = theFirstDevice_v[theNetId]; device_it != UNKNOWN_DEVICE; device_it = theNextDevice_v[device_it]) {
2256 netId_t mySourceId = GetEquivalentNet(sourceNet_v[device_it]);
2257 netId_t myDrainId = GetEquivalentNet(drainNet_v[device_it]);
2258 if ( mySourceId != myDrainId ) {
2259 if ( ! ( netVoltagePtr_v[mySourceId].full || netStatus_v[mySourceId][ANALOG] ) ) { // ignore power and already set
2260 PropagateAnalogNetType(mySourceId, theGateCount);
2261 }
2262 if ( ! ( netVoltagePtr_v[myDrainId].full || netStatus_v[myDrainId][ANALOG] ) ) { // ignore power and already set
2263 PropagateAnalogNetType(myDrainId, theGateCount);
2264 }
2265 }
2266 }
2267 }
2268
SetSimPower(propagation_t thePropagationType,CNetIdSet & theNewNetSet)2269 void CCvcDb::SetSimPower(propagation_t thePropagationType, CNetIdSet & theNewNetSet) {
2270 reportFile << "CVC: Propagating Simulation voltages " << thePropagationType << "..." << endl;
2271 simEventQueue.ResetQueue(deviceCount);
2272 simNet_v.InitializeUpdateArray();
2273 isFixedSimNet = false;
2274 CVirtualNet mySimMasterNet;
2275 for (netId_t net_it = 0; net_it < netCount; net_it++) {
2276 if ( net_it != GetEquivalentNet(net_it) ) continue; // skip subordinate nets
2277 // TODO: Change to GetMasterNet
2278 mySimMasterNet(simNet_v, net_it);
2279 if ( theNewNetSet.size() > 0 && theNewNetSet.count(net_it) == 0 ) continue; // not relavant to this pass
2280 if ( netVoltagePtr_v[mySimMasterNet.finalNetId].full == NULL ) continue;
2281 CPower * myPower_p = netVoltagePtr_v[mySimMasterNet.finalNetId].full;
2282 if ( myPower_p->simVoltage == UNKNOWN_VOLTAGE && ! IsSCRCPower(myPower_p) ) continue;
2283 if ( thePropagationType == POWER_NETS_ONLY && ! IsPriorityPower_(myPower_p) ) continue;
2284 EnqueueAttachedDevicesByTerminal(simEventQueue, net_it, firstSource_v, nextSource_v, myPower_p->simVoltage);
2285 EnqueueAttachedDevicesByTerminal(simEventQueue, net_it, firstDrain_v, nextDrain_v, myPower_p->simVoltage);
2286 EnqueueAttachedDevicesByTerminal(simEventQueue, net_it, firstGate_v, nextGate_v, myPower_p->simVoltage);
2287 }
2288 simEventQueue.queueStart = true;
2289 while (simEventQueue.QueueSize() > 0) {
2290 PropagateSimVoltages(simEventQueue, thePropagationType);
2291 }
2292 for ( netId_t net_it = 0; net_it < netCount; net_it++ ) {
2293 simNet_v[net_it](simNet_v, net_it); // recalculate final values
2294 }
2295 isFixedSimNet = true;
2296 simNet_v.ClearUpdateArray();
2297 }
2298
CheckConnections()2299 void CCvcDb::CheckConnections() {
2300 static CVirtualNet myVirtualNet;
2301 static CVirtualNet myMinNet;
2302 static CVirtualNet myMaxNet;
2303 unordered_map<netId_t, pair<deviceId_t, deviceId_t>> myBulkCount;
2304 for (deviceId_t device_it = 0; device_it < deviceCount; device_it++) {
2305 if ( bulkNet_v[device_it] == UNKNOWN_NET ) continue;
2306 if ( IsMos_(deviceType_v[device_it]) && sourceNet_v[device_it] != drainNet_v[device_it] ) { // only count non-capacitor mosfet
2307 netId_t myBulkNet = bulkNet_v[device_it];
2308 if ( myBulkCount[myBulkNet].first++ == 0 ) { // remember the first connected device
2309 myBulkCount[myBulkNet].second = device_it;
2310 }
2311 }
2312 }
2313 for (netId_t net_it = 0; net_it < netCount; net_it++) {
2314 if ( myBulkCount.count(net_it) > 0 && myBulkCount[net_it].first >= connectionCount_v[net_it].sourceCount + connectionCount_v[net_it].drainCount ) {
2315 // skips subordinate nets because only equivalent masters have counts.
2316 // may have problems with moscaps, because one device has both source and drain connection. <- moscaps not included in connectionCounts
2317 myVirtualNet(simNet_v, net_it);
2318 assert( myVirtualNet.finalNetId != UNKNOWN_NET );
2319 CPower * myPower_p = netVoltagePtr_v[myVirtualNet.finalNetId].full;
2320 if ( myVirtualNet.finalResistance > 1000000 && myVirtualNet.finalResistance != INFINITE_RESISTANCE ) {
2321 reportFile << "WARNING: high res bias (" << myBulkCount[net_it].first << ") " << NetName(net_it, PRINT_CIRCUIT_ON) << " r=" << myVirtualNet.finalResistance << endl;
2322 } else if ( ! myPower_p
2323 || ( myPower_p->simVoltage == UNKNOWN_VOLTAGE
2324 && ( myPower_p->minVoltage == UNKNOWN_VOLTAGE || myPower_p->maxVoltage == UNKNOWN_VOLTAGE ) ) ) { // no error for missing bias if min/max defined.
2325 myMinNet(minNet_v, net_it);
2326 myMaxNet(maxNet_v, net_it);
2327 if ( myMinNet.finalNetId != UNKNOWN_NET
2328 && netVoltagePtr_v[myMinNet.finalNetId].full
2329 && netVoltagePtr_v[myMinNet.finalNetId].full->minVoltage != UNKNOWN_VOLTAGE
2330 && myMinNet.finalNetId == myMaxNet.finalNetId ) continue; // bias with min/max to same voltage not error
2331 reportFile << "WARNING: missing bias (" << myBulkCount[net_it].first << ") " << NetName(net_it, PRINT_CIRCUIT_ON);
2332 reportFile << " at " << DeviceName(myBulkCount[net_it].second, PRINT_CIRCUIT_ON, PRINT_HIERARCHY_OFF) << endl;
2333 } else if ( IsCalculatedVoltage_(myPower_p) ) {
2334 reportFile << "WARNING: calculated bias (" << myBulkCount[net_it].first << ") " << NetName(net_it, PRINT_CIRCUIT_ON);
2335 reportFile << " at " << DeviceName(myBulkCount[net_it].second, PRINT_CIRCUIT_ON, PRINT_HIERARCHY_OFF)
2336 << (myPower_p->type[MIN_CALCULATED_BIT] ? " 1|" : " 0|")
2337 << (myPower_p->type[SIM_CALCULATED_BIT] ? "1|" : "0|")
2338 << (myPower_p->type[MAX_CALCULATED_BIT] ? "1" : "0") << endl;
2339 }
2340 }
2341 }
2342 }
2343
SetInverterHighLow(netId_t theNetId,netId_t theMaxNetId)2344 void CCvcDb::SetInverterHighLow(netId_t theNetId, netId_t theMaxNetId) {
2345 bool myDebug = false;
2346 if ( inverterNet_v[theNetId] == UNKNOWN_NET ) {
2347 return;
2348 } else if ( inverterNet_v[theNetId] == theMaxNetId ) { // prevent looping
2349 return;
2350 } else {
2351 netId_t myInputId = inverterNet_v[theNetId];
2352 SetInverterHighLow(myInputId, max(theMaxNetId, myInputId));
2353 highLow_v[theNetId] = ! highLow_v[myInputId];
2354 if ( myDebug ) cout << "Net " << theNetId << " input " << inverterNet_v[theNetId] << " " << highLow_v[theNetId] << " " << myInputId << endl;
2355 }
2356 }
2357
SetInverterInput(netId_t theNetId,netId_t theMaxNetId)2358 netId_t CCvcDb::SetInverterInput(netId_t theNetId, netId_t theMaxNetId) {
2359 bool myDebug = false;
2360 if ( inverterNet_v[theNetId] == UNKNOWN_NET ) {
2361 return(theNetId);
2362 } else if ( inverterNet_v[theNetId] == theMaxNetId ) { // prevent looping
2363 return(theMaxNetId);
2364 } else {
2365 netId_t myInputId = inverterNet_v[theNetId];
2366 inverterNet_v[theNetId] = SetInverterInput(myInputId, max(theMaxNetId, myInputId));
2367 if ( myDebug ) cout << "Net " << theNetId << " input " << inverterNet_v[theNetId] << " " << highLow_v[theNetId] << " " << myInputId << endl;
2368 return(inverterNet_v[theNetId]);
2369 }
2370 }
2371
SetInverters()2372 void CCvcDb::SetInverters() {
2373 bool myDebug = false;
2374 for( netId_t net_it = 0; net_it < netCount; net_it++ ) {
2375 if ( net_it != GetEquivalentNet(net_it) ) continue;
2376 myDebug = false;
2377 if ( myDebug ) cout << endl << "Starting " << net_it << endl;
2378 if ( inverterNet_v[net_it] != UNKNOWN_NET ) {
2379 netId_t myInputId = inverterNet_v[net_it];
2380 SetInverterHighLow(myInputId, max(net_it, myInputId));
2381 highLow_v[net_it] = ! highLow_v[myInputId];
2382 }
2383 }
2384 for( netId_t net_it = 0; net_it < netCount; net_it++ ) {
2385 if ( net_it != GetEquivalentNet(net_it) ) continue;
2386 myDebug = false;
2387 if ( myDebug ) cout << endl << "Starting " << net_it << endl;
2388 if ( inverterNet_v[net_it] != UNKNOWN_NET ) {
2389 netId_t myInputId = inverterNet_v[net_it];
2390 inverterNet_v[net_it] = SetInverterInput(myInputId, max(net_it, myInputId));
2391 }
2392 }
2393 }
2394