1 /*
2  * CCvcDb-utility.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 <bitset>
25 #include <cstddef>
26 #include <cstdint>
27 #include <list>
28 #include <map>
29 #include <memory>
30 #include <set>
31 #include <string>
32 #include <vector>
33 #include <sys/stat.h>
34 #include <sys/mman.h>
35 
36 #include "CCircuit.hh"
37 #include "CConnection.hh"
38 #include "CCvcDb.hh"
39 #include "CCvcExceptions.hh"
40 #include "CCvcParameters.hh"
41 #include "CDevice.hh"
42 #include "CEventQueue.hh"
43 #include "CInstance.hh"
44 #include "CModel.hh"
45 #include "CPower.hh"
46 #include "Cvc.hh"
47 #include "CvcTypes.hh"
48 #include "CVirtualNet.hh"
49 
MinVoltage(netId_t theNetId,bool theSkipHiZFlag)50 voltage_t CCvcDb::MinVoltage(netId_t theNetId, bool theSkipHiZFlag) {
51 	if ( theNetId != UNKNOWN_NET ) {
52 		static CVirtualNet myVirtualNet;
53 		assert(theNetId == GetEquivalentNet(theNetId));
54 		myVirtualNet(minNet_v, theNetId);
55 		if ( myVirtualNet.finalNetId != UNKNOWN_NET ) {
56 			CPower * myFinalPower_p = netVoltagePtr_v[myVirtualNet.finalNetId].full;
57 			if ( myFinalPower_p ) {
58 				if ( theSkipHiZFlag && myFinalPower_p->type[HIZ_BIT] ) return UNKNOWN_VOLTAGE;
59 				return myFinalPower_p->minVoltage;
60 			}
61 		}
62 	}
63 	return UNKNOWN_VOLTAGE;
64 }
65 
MinSimVoltage(netId_t theNetId)66 voltage_t CCvcDb::MinSimVoltage(netId_t theNetId) {
67 	// limit min value to calculated sim value
68 	if ( theNetId != UNKNOWN_NET ) {
69 		static CVirtualNet myVirtualNet;
70 		assert(theNetId == GetEquivalentNet(theNetId));
71 		myVirtualNet(minNet_v, theNetId);
72 		if ( myVirtualNet.finalNetId != UNKNOWN_NET ) {
73 			voltage_t myMinVoltage = ( netVoltagePtr_v[myVirtualNet.finalNetId].full ) ? netVoltagePtr_v[myVirtualNet.finalNetId].full->minVoltage : UNKNOWN_VOLTAGE;
74 			netId_t myNetId = theNetId;
75 			while ( myNetId != minNet_v[myNetId].nextNetId ) {
76 				myNetId = minNet_v[myNetId].nextNetId;
77 				CPower * myPower_p = netVoltagePtr_v[myNetId].full;
78 				if ( myPower_p && myPower_p->type[SIM_CALCULATED_BIT] && myPower_p->simVoltage != UNKNOWN_VOLTAGE ) {
79 					return ((myMinVoltage == UNKNOWN_VOLTAGE) ? myPower_p->simVoltage : max(myPower_p->simVoltage, myMinVoltage));
80 				}
81 			}
82 			return myMinVoltage;
83 		}
84 	}
85 	return UNKNOWN_VOLTAGE;
86 }
87 
MinResistance(netId_t theNetId)88 resistance_t CCvcDb::MinResistance(netId_t theNetId) {
89 	// resistance to minimum master net
90 	if ( theNetId != UNKNOWN_NET ) {
91 		static CVirtualNet myVirtualNet;
92 		assert(theNetId == GetEquivalentNet(theNetId));
93 		myVirtualNet(minNet_v, theNetId);
94 		if ( myVirtualNet.finalNetId != UNKNOWN_NET ) {
95 			return myVirtualNet.finalResistance;
96 		}
97 	}
98 	return UNKNOWN_VOLTAGE;
99 }
100 
MinLeakVoltage(netId_t theNetId)101 voltage_t CCvcDb::MinLeakVoltage(netId_t theNetId) {
102 	if ( theNetId != UNKNOWN_NET && leakVoltageSet ) {
103 		netId_t myNetId = minNet_v[theNetId].backupNetId;
104 //		CVirtualNet myVirtualNet(minLeakNet_v, theNetId);
105 		assert(theNetId == GetEquivalentNet(theNetId));
106 		if ( myNetId != UNKNOWN_NET ) {
107 			while ( myNetId != minNet_v[myNetId].backupNetId ) {
108 				myNetId = minNet_v[myNetId].backupNetId;
109 			}
110 			if ( leakVoltagePtr_v[myNetId].full ) {
111 				return leakVoltagePtr_v[myNetId].full->minVoltage;
112 			}
113 		}
114 	}
115 	return UNKNOWN_VOLTAGE;
116 }
117 
SimVoltage(netId_t theNetId)118 voltage_t CCvcDb::SimVoltage(netId_t theNetId) {
119 	if ( theNetId != UNKNOWN_NET ) {
120 		static CVirtualNet myVirtualNet;
121 		assert(theNetId == GetEquivalentNet(theNetId));
122 		myVirtualNet(simNet_v, theNetId);
123 		if ( myVirtualNet.finalNetId != UNKNOWN_NET ) {
124 			CPower * myFinalPower_p = netVoltagePtr_v[myVirtualNet.finalNetId].full;
125 			if ( myFinalPower_p ) {
126 				return myFinalPower_p->simVoltage;
127 			}
128 		}
129 	}
130 	return UNKNOWN_VOLTAGE;
131 }
132 
IsAlwaysOnCandidate(deviceId_t theDeviceId,shortDirection_t theDirection)133 bool CCvcDb::IsAlwaysOnCandidate(deviceId_t theDeviceId, shortDirection_t theDirection) {
134 	if ( theDeviceId == UNKNOWN_DEVICE ) return false;
135 	static CVirtualNet myMinVirtualSourceNet;
136 	static CVirtualNet myMinVirtualDrainNet;
137 	static CVirtualNet myMaxVirtualSourceNet;
138 	static CVirtualNet myMaxVirtualDrainNet;
139 	netId_t mySourceNetId = GetEquivalentNet(sourceNet_v[theDeviceId]);
140 	netId_t myDrainNetId = GetEquivalentNet(drainNet_v[theDeviceId]);
141 	if ( theDirection == DRAIN_TO_MASTER_SOURCE && connectionCount_v[myDrainNetId].sourceDrainType != NMOS_PMOS ) return true;  // non-output devices are always true
142 	if ( theDirection == SOURCE_TO_MASTER_DRAIN && connectionCount_v[mySourceNetId].sourceDrainType != NMOS_PMOS ) return true;  // non-output devices are always true
143 	myMinVirtualSourceNet(minNet_v, mySourceNetId);
144 	myMinVirtualDrainNet(minNet_v, myDrainNetId);
145 	myMaxVirtualSourceNet(maxNet_v, mySourceNetId);
146 	myMaxVirtualDrainNet(maxNet_v, myDrainNetId);
147 	netId_t myMinSourceNetId = myMinVirtualSourceNet.finalNetId;
148 	netId_t myMinDrainNetId = myMinVirtualDrainNet.finalNetId;
149 	netId_t myMaxSourceNetId = myMaxVirtualSourceNet.finalNetId;
150 	netId_t myMaxDrainNetId = myMaxVirtualDrainNet.finalNetId;
151 	if ( myMinSourceNetId == UNKNOWN_NET || ! netVoltagePtr_v[myMinSourceNetId].full ) return false;
152 	if ( myMinDrainNetId == UNKNOWN_NET || ! netVoltagePtr_v[myMinDrainNetId].full ) return false;
153 	if ( myMaxSourceNetId == UNKNOWN_NET || ! netVoltagePtr_v[myMaxSourceNetId].full ) return false;
154 	if ( myMaxDrainNetId == UNKNOWN_NET || ! netVoltagePtr_v[myMaxDrainNetId].full ) return false;
155 	voltage_t myMinSourceVoltage = netVoltagePtr_v[myMinSourceNetId].full->minVoltage;
156 	voltage_t myMinDrainVoltage = netVoltagePtr_v[myMinDrainNetId].full->minVoltage;
157 	voltage_t myMaxSourceVoltage = netVoltagePtr_v[myMaxSourceNetId].full->maxVoltage;
158 	voltage_t myMaxDrainVoltage = netVoltagePtr_v[myMaxDrainNetId].full->maxVoltage;
159 	terminal_t myTargetTerminal;
160 	if ( myMinSourceVoltage < myMinDrainVoltage ) {
161 		myTargetTerminal = SOURCE;
162 	} else if ( myMinSourceVoltage > myMinDrainVoltage ) {
163 		myTargetTerminal = DRAIN;
164 	} else if ( myMinSourceVoltage == myMaxSourceVoltage && myMinDrainVoltage == myMaxDrainVoltage ) {  // all voltages the same: no leak tie hi/lo
165 		return true;
166 	} else if ( myMinVirtualSourceNet.finalResistance > myMinVirtualDrainNet.finalResistance ) {
167 		myTargetTerminal = SOURCE;
168 	} else {
169 		myTargetTerminal = DRAIN;
170 	}
171 	if ( myMaxSourceVoltage > myMaxDrainVoltage ) {
172 		if ( myTargetTerminal != SOURCE ) return false;
173 	} else if ( myMaxSourceVoltage < myMaxDrainVoltage ) {
174 		if ( myTargetTerminal != DRAIN ) return false;
175 	} else if ( myMaxVirtualSourceNet.finalResistance > myMaxVirtualDrainNet.finalResistance ) {
176 		if ( myTargetTerminal != SOURCE ) return false;
177 	} else {
178 		if ( myTargetTerminal != DRAIN ) return false;
179 	}
180 	// Returns true if min/max resistance with 128 times
181 	if ( myTargetTerminal == SOURCE && myMinVirtualSourceNet.finalResistance < MAX_RESISTANCE >> 7 && myMaxVirtualSourceNet.finalResistance < MAX_RESISTANCE >> 7 ) {
182 		if ( myMinVirtualSourceNet.finalResistance << 7 > myMaxVirtualSourceNet.finalResistance
183 				&& myMinVirtualSourceNet.finalResistance < myMaxVirtualSourceNet.finalResistance << 7 ) {
184 			return true;
185 		}
186 	} else if ( myMinVirtualDrainNet.finalResistance < MAX_RESISTANCE >> 7 && myMaxVirtualDrainNet.finalResistance < MAX_RESISTANCE >> 7 ) {
187 		if ( myMinVirtualDrainNet.finalResistance << 7 > myMaxVirtualDrainNet.finalResistance
188 				&& myMinVirtualDrainNet.finalResistance < myMaxVirtualDrainNet.finalResistance << 7 ) {
189 			return true;
190 		}
191 	}
192 	return false;
193 }
194 
SimResistance(netId_t theNetId)195 resistance_t CCvcDb::SimResistance(netId_t theNetId) {
196 //	resistance_t myResistance;
197 	if ( theNetId != UNKNOWN_NET ) {
198 		static CVirtualNet myVirtualNet;
199 		assert(theNetId == GetEquivalentNet(theNetId));
200 		myVirtualNet(simNet_v, theNetId);
201 		return myVirtualNet.finalResistance;
202 	}
203 	return MAX_RESISTANCE;
204 }
205 
MaxVoltage(netId_t theNetId,bool theSkipHiZFlag)206 voltage_t CCvcDb::MaxVoltage(netId_t theNetId, bool theSkipHiZFlag) {
207 	if ( theNetId != UNKNOWN_NET ) {
208 		static CVirtualNet myVirtualNet;
209 		assert(theNetId == GetEquivalentNet(theNetId));
210 		myVirtualNet(maxNet_v, theNetId);
211 		if ( myVirtualNet.finalNetId != UNKNOWN_NET ) {
212 			CPower * myFinalPower_p = netVoltagePtr_v[myVirtualNet.finalNetId].full;
213 			if ( myFinalPower_p ) {
214 				if ( theSkipHiZFlag && myFinalPower_p->type[HIZ_BIT] ) return UNKNOWN_VOLTAGE;
215 				return myFinalPower_p->maxVoltage;
216 			}
217 		}
218 	}
219 	return UNKNOWN_VOLTAGE;
220 }
221 
MaxSimVoltage(netId_t theNetId)222 voltage_t CCvcDb::MaxSimVoltage(netId_t theNetId) {
223 	// limit max value to calculated sim value
224 	if ( theNetId != UNKNOWN_NET ) {
225 		static CVirtualNet myVirtualNet;
226 		assert(theNetId == GetEquivalentNet(theNetId));
227 		myVirtualNet(maxNet_v, theNetId);
228 		if ( myVirtualNet.finalNetId != UNKNOWN_NET ) {
229 			voltage_t myMaxVoltage = ( netVoltagePtr_v[myVirtualNet.finalNetId].full ) ? netVoltagePtr_v[myVirtualNet.finalNetId].full->maxVoltage : UNKNOWN_VOLTAGE;
230 			netId_t myNetId = theNetId;
231 			while ( myNetId != maxNet_v[myNetId].nextNetId ) {
232 				myNetId = maxNet_v[myNetId].nextNetId;
233 				CPower * myPower_p = netVoltagePtr_v[myNetId].full;
234 				if ( myPower_p && myPower_p->type[SIM_CALCULATED_BIT] && myPower_p->simVoltage != UNKNOWN_VOLTAGE ) {
235 					return ((myMaxVoltage == UNKNOWN_VOLTAGE) ? myPower_p->simVoltage : min(myPower_p->simVoltage, myMaxVoltage));
236 				}
237 			}
238 			return myMaxVoltage;
239 		}
240 	}
241 	return UNKNOWN_VOLTAGE;
242 }
243 
MaxResistance(netId_t theNetId)244 resistance_t CCvcDb::MaxResistance(netId_t theNetId) {
245 	// resistance to maximum master net
246 	if ( theNetId != UNKNOWN_NET ) {
247 		static CVirtualNet myVirtualNet;
248 		assert(theNetId == GetEquivalentNet(theNetId));
249 		myVirtualNet(maxNet_v, theNetId);
250 		if ( myVirtualNet.finalNetId != UNKNOWN_NET ) {
251 			return myVirtualNet.finalResistance;
252 		}
253 	}
254 	return UNKNOWN_VOLTAGE;
255 }
256 
MaxLeakVoltage(netId_t theNetId)257 voltage_t CCvcDb::MaxLeakVoltage(netId_t theNetId) {
258 	if ( theNetId != UNKNOWN_NET && leakVoltageSet ) {
259 		assert(theNetId == GetEquivalentNet(theNetId));
260 		netId_t myNetId = maxNet_v[theNetId].backupNetId;
261 		if ( myNetId != UNKNOWN_NET ) {
262 			while ( myNetId != maxNet_v[myNetId].backupNetId ) {
263 				myNetId = maxNet_v[myNetId].backupNetId;
264 			}
265 			if ( leakVoltagePtr_v[myNetId].full ) {
266 				return leakVoltagePtr_v[myNetId].full->maxVoltage;
267 			}
268 		}
269 	}
270 	return UNKNOWN_VOLTAGE;
271 }
272 
273 // equivalency list is descending order loop; return node is greatest
GetGreatestEquivalentNet(netId_t theNetId)274 netId_t CCvcDb::GetGreatestEquivalentNet(netId_t theNetId) {
275 	if ( theNetId == UNKNOWN_NET ) return UNKNOWN_NET;
276 	while ( equivalentNet_v[theNetId] < theNetId ) {
277 		theNetId = equivalentNet_v[theNetId];
278 	}
279 	return equivalentNet_v[theNetId];
280 }
281 
282 // equivalency list is descending order loop; return node is least
GetLeastEquivalentNet(netId_t theNetId)283 netId_t CCvcDb::GetLeastEquivalentNet(netId_t theNetId) {
284 	if ( theNetId == UNKNOWN_NET ) return UNKNOWN_NET;
285 	while ( equivalentNet_v[theNetId] < theNetId ) {
286 		theNetId = equivalentNet_v[theNetId];
287 	}
288 	return theNetId;
289 }
290 
GetEquivalentNet(netId_t theNetId)291 netId_t CCvcDb::GetEquivalentNet(netId_t theNetId) {
292 	if ( theNetId == UNKNOWN_NET ) return UNKNOWN_NET;
293 	if ( isFixedEquivalentNet ) {
294 		theNetId = equivalentNet_v[theNetId];
295 	} else {
296 		theNetId = GetLeastEquivalentNet(theNetId);
297 	}
298 	CPower * myPower_p = netVoltagePtr_v[theNetId].full;
299 	if ( myPower_p && myPower_p->netId != UNKNOWN_NET ) {
300 		return(myPower_p->netId);
301 	}
302 	return theNetId;
303 }
304 
DeviceParameters(const deviceId_t theDeviceId)305 text_t CCvcDb::DeviceParameters(const deviceId_t theDeviceId) {
306 	instanceId_t myParentId = deviceParent_v[theDeviceId];
307 	deviceId_t myDeviceOffset = theDeviceId - instancePtr_v[myParentId]->firstDeviceId;
308 	return(instancePtr_v[myParentId]->master_p->devicePtr_v[myDeviceOffset]->parameters);
309 }
310 
311 
SetDeviceNets(CInstance * theInstance_p,CDevice * theDevice_p,netId_t & theSourceId,netId_t & theGateId,netId_t & theDrainId,netId_t & theBulkId)312 void CCvcDb::SetDeviceNets(CInstance * theInstance_p, CDevice * theDevice_p, netId_t& theSourceId, netId_t& theGateId, netId_t& theDrainId, netId_t& theBulkId) {
313 	// sets a element in each of the sourceNet_v, gateNet_v, drainNet_v, bulkNet_v arrays
314 	switch (theDevice_p->model_p->type) {
315 		case NMOS: case PMOS: case LDDN: case LDDP: {
316 			theDrainId = GetEquivalentNet(theInstance_p->localToGlobalNetId_v[theDevice_p->signalId_v[0]]);
317 			theGateId = GetEquivalentNet(theInstance_p->localToGlobalNetId_v[theDevice_p->signalId_v[1]]);
318 			theSourceId = GetEquivalentNet(theInstance_p->localToGlobalNetId_v[theDevice_p->signalId_v[2]]);
319 			if ( cvcParameters.cvcSOI ) {
320 				theBulkId = UNKNOWN_NET;
321 			} else {
322 				theBulkId = GetEquivalentNet(theInstance_p->localToGlobalNetId_v[theDevice_p->signalId_v[3]]);
323 			}
324 		break; }
325 		case DIODE: case SWITCH_OFF: case FUSE_OFF: case CAPACITOR:	case SWITCH_ON:	case FUSE_ON: case RESISTOR: {
326 			theSourceId = GetEquivalentNet(theInstance_p->localToGlobalNetId_v[theDevice_p->signalId_v[0]]);
327 			theGateId = UNKNOWN_NET;
328 			theDrainId = GetEquivalentNet(theInstance_p->localToGlobalNetId_v[theDevice_p->signalId_v[1]]);
329 			theBulkId = UNKNOWN_NET;
330 			if ( theDevice_p->signalId_v.size() == 3 ) {
331 				theBulkId = GetEquivalentNet(theInstance_p->localToGlobalNetId_v[theDevice_p->signalId_v[2]]);
332 			} else {
333 				theBulkId = UNKNOWN_NET;
334 			}
335 		break; }
336 /*
337 		case NRESISTOR: case PRESISTOR: {
338 			theSourceId = GetEquivalentNet(theInstance_p->localToGlobalNetId_v[theDevice_p->signalId_v[0]]);
339 			theGateId = UNKNOWN_NET;
340 			theDrainId = GetEquivalentNet(theInstance_p->localToGlobalNetId_v[theDevice_p->signalId_v[1]]);
341 			theBulkId = GetEquivalentNet(theInstance_p->localToGlobalNetId_v[theDevice_p->signalId_v[2]]);
342 		break; }
343 */
344 		case BIPOLAR: /* case NPN: case PNP: */ {
345 			theSourceId = GetEquivalentNet(theInstance_p->localToGlobalNetId_v[theDevice_p->signalId_v[0]]);
346 			theGateId = GetEquivalentNet(theInstance_p->localToGlobalNetId_v[theDevice_p->signalId_v[1]]);
347 			theDrainId = GetEquivalentNet(theInstance_p->localToGlobalNetId_v[theDevice_p->signalId_v[2]]);
348 			theBulkId = UNKNOWN_NET;
349 		break; }
350 		default: {
351 //			cout << "ERROR: Unknown model type in LinkDevices" << endl;
352 			theDevice_p->model_p->Print();
353 			throw EUnknownModel();
354 		}
355 	}
356 }
357 
SetDeviceNets(deviceId_t theDeviceId,CDevice * theDevice_p,netId_t & theSourceId,netId_t & theGateId,netId_t & theDrainId,netId_t & theBulkId)358 void CCvcDb::SetDeviceNets(deviceId_t theDeviceId, CDevice * theDevice_p, netId_t& theSourceId, netId_t& theGateId, netId_t& theDrainId, netId_t& theBulkId) {
359 	CInstance * myInstance_p = instancePtr_v[deviceParent_v[theDeviceId]];
360 	theDevice_p = myInstance_p->master_p->devicePtr_v[theDeviceId - myInstance_p->firstDeviceId];
361 	SetDeviceNets(myInstance_p, theDevice_p, theSourceId, theGateId, theDrainId, theBulkId);
362 }
363 
MapDeviceNets(deviceId_t theDeviceId,CEventQueue & theEventQueue,CConnection & theConnections)364 void CCvcDb::MapDeviceNets(deviceId_t theDeviceId, CEventQueue& theEventQueue, CConnection& theConnections) {
365 	/// Get connections for device at one sample point (min/sim/max)
366 	CDevice * myDevice_p;
367 	CInstance * myInstance_p = instancePtr_v[deviceParent_v[theDeviceId]];
368 	myDevice_p = myInstance_p->master_p->devicePtr_v[theDeviceId - myInstance_p->firstDeviceId];
369 	SetConnections_(theConnections, theDeviceId);
370 	theConnections.masterSourceNet(theEventQueue.virtualNet_v, theConnections.sourceId);
371 	theConnections.masterGateNet(theEventQueue.virtualNet_v, theConnections.gateId);
372 	theConnections.masterDrainNet(theEventQueue.virtualNet_v, theConnections.drainId);
373 	theConnections.masterBulkNet(theEventQueue.virtualNet_v, theConnections.bulkId);
374 	if ( theEventQueue.queueType == MAX_QUEUE ) {
375 		theConnections.sourceVoltage = netVoltagePtr_v.MaxVoltage(theConnections.masterSourceNet.finalNetId);
376 		theConnections.gateVoltage = netVoltagePtr_v.MaxVoltage(theConnections.masterGateNet.finalNetId);
377 		theConnections.drainVoltage = netVoltagePtr_v.MaxVoltage(theConnections.masterDrainNet.finalNetId);
378 		theConnections.bulkVoltage = netVoltagePtr_v.MaxVoltage(theConnections.masterBulkNet.finalNetId);
379 	} else if ( theEventQueue.queueType == MIN_QUEUE ) {
380 		theConnections.sourceVoltage = netVoltagePtr_v.MinVoltage(theConnections.masterSourceNet.finalNetId);
381 		theConnections.gateVoltage = netVoltagePtr_v.MinVoltage(theConnections.masterGateNet.finalNetId);
382 		theConnections.drainVoltage = netVoltagePtr_v.MinVoltage(theConnections.masterDrainNet.finalNetId);
383 		theConnections.bulkVoltage = netVoltagePtr_v.MinVoltage(theConnections.masterBulkNet.finalNetId);
384 	} else if ( theEventQueue.queueType == SIM_QUEUE ) {
385 		theConnections.sourceVoltage = netVoltagePtr_v.SimVoltage(theConnections.masterSourceNet.finalNetId);
386 		theConnections.gateVoltage = netVoltagePtr_v.SimVoltage(theConnections.masterGateNet.finalNetId);
387 		theConnections.drainVoltage = netVoltagePtr_v.SimVoltage(theConnections.masterDrainNet.finalNetId);
388 		theConnections.bulkVoltage = netVoltagePtr_v.SimVoltage(theConnections.masterBulkNet.finalNetId);
389 	}
390 	if ( theConnections.masterGateNet.finalNetId == UNKNOWN_NET ) {
391 		theConnections.gatePower_p = NULL;
392 	} else {
393 		theConnections.gatePower_p = netVoltagePtr_v[theConnections.masterGateNet.finalNetId].full;
394 	}
395 	theConnections.sourcePower_p = netVoltagePtr_v[theConnections.masterSourceNet.finalNetId].full;
396 	if ( IsSCRCPower(theConnections.sourcePower_p) ) {
397 		theConnections.sourceVoltage = theConnections.sourcePower_p->minVoltage;  // min = max
398 	}
399 	theConnections.drainPower_p = netVoltagePtr_v[theConnections.masterDrainNet.finalNetId].full;
400 	if ( IsSCRCPower(theConnections.drainPower_p) ) {
401 		theConnections.drainVoltage = theConnections.drainPower_p->minVoltage;  // min = max
402 	}
403 	theConnections.device_p = myDevice_p;
404 	theConnections.deviceId = theDeviceId;
405 	theConnections.resistance = parameterResistanceMap[theConnections.device_p->parameters];
406 }
407 
MapDeviceNets(deviceId_t theDeviceId,CFullConnection & theConnections)408 void CCvcDb::MapDeviceNets(deviceId_t theDeviceId, CFullConnection& theConnections) {
409 	/// Get connections for device at all sample points (min/sim/max) from deviceId
410 	CInstance * myInstance_p = instancePtr_v[deviceParent_v[theDeviceId]];
411 	CDevice * myDevice_p = myInstance_p->master_p->devicePtr_v[theDeviceId - myInstance_p->firstDeviceId];
412 	MapDeviceNets(myInstance_p, myDevice_p, theConnections);
413 }
414 
MapDeviceSourceDrainNets(deviceId_t theDeviceId,CFullConnection & theConnections)415 void CCvcDb::MapDeviceSourceDrainNets(deviceId_t theDeviceId, CFullConnection& theConnections) {
416 	CDevice * myDevice_p;
417 	CInstance * myInstance_p = instancePtr_v[deviceParent_v[theDeviceId]];
418 	myDevice_p = myInstance_p->master_p->devicePtr_v[theDeviceId - myInstance_p->firstDeviceId];
419 	SetConnections_(theConnections, theDeviceId);
420 	switch (myDevice_p->model_p->type) {
421 		case NMOS: case PMOS: case LDDN: case LDDP: {
422 			theConnections.originalDrainId = myInstance_p->localToGlobalNetId_v[myDevice_p->signalId_v[0]];
423 			theConnections.originalSourceId = myInstance_p->localToGlobalNetId_v[myDevice_p->signalId_v[2]];
424 			break; }
425 		case BIPOLAR: case DIODE: case SWITCH_OFF: case FUSE_OFF: case CAPACITOR:	case SWITCH_ON:	case FUSE_ON: case RESISTOR: {
426 			theConnections.originalSourceId = myInstance_p->localToGlobalNetId_v[myDevice_p->signalId_v[0]];
427 			theConnections.originalDrainId = myInstance_p->localToGlobalNetId_v[myDevice_p->signalId_v[1]];
428 			break; }
429 		default: {
430 			myDevice_p->model_p->Print();
431 			throw EUnknownModel();
432 		}
433 	}
434 	theConnections.masterMaxSourceNet(maxNet_v, theConnections.sourceId);
435 	theConnections.masterMaxDrainNet(maxNet_v, theConnections.drainId);
436 	theConnections.maxSourceVoltage = netVoltagePtr_v.MaxVoltage(theConnections.masterMaxSourceNet.finalNetId);
437 	theConnections.maxDrainVoltage = netVoltagePtr_v.MaxVoltage(theConnections.masterMaxDrainNet.finalNetId);
438 	theConnections.maxSourcePower_p = netVoltagePtr_v[theConnections.masterMaxSourceNet.finalNetId].full;
439 	theConnections.maxDrainPower_p = netVoltagePtr_v[theConnections.masterMaxDrainNet.finalNetId].full;
440 
441 	theConnections.masterMinSourceNet(minNet_v, theConnections.sourceId);
442 	theConnections.masterMinDrainNet(minNet_v, theConnections.drainId);
443 	theConnections.minSourceVoltage = netVoltagePtr_v.MinVoltage(theConnections.masterMinSourceNet.finalNetId);
444 	theConnections.minDrainVoltage = netVoltagePtr_v.MinVoltage(theConnections.masterMinDrainNet.finalNetId);
445 	theConnections.minSourcePower_p = netVoltagePtr_v[theConnections.masterMinSourceNet.finalNetId].full;
446 	theConnections.minDrainPower_p = netVoltagePtr_v[theConnections.masterMinDrainNet.finalNetId].full;
447 
448 	theConnections.masterSimSourceNet(simNet_v, theConnections.sourceId);
449 	theConnections.masterSimDrainNet(simNet_v, theConnections.drainId);
450 	theConnections.simSourceVoltage = netVoltagePtr_v.SimVoltage(theConnections.masterSimSourceNet.finalNetId);
451 	theConnections.simDrainVoltage = netVoltagePtr_v.SimVoltage(theConnections.masterSimDrainNet.finalNetId);
452 	theConnections.simSourcePower_p = netVoltagePtr_v[theConnections.masterSimSourceNet.finalNetId].full;
453 	theConnections.simDrainPower_p = netVoltagePtr_v[theConnections.masterSimDrainNet.finalNetId].full;
454 
455 	theConnections.device_p = myDevice_p;
456 	theConnections.deviceId = theDeviceId;
457 	theConnections.resistance = parameterResistanceMap[theConnections.device_p->parameters];
458 }
459 
MapDeviceNets(CInstance * theInstance_p,CDevice * theDevice_p,CFullConnection & theConnections)460 void CCvcDb::MapDeviceNets(CInstance * theInstance_p, CDevice * theDevice_p, CFullConnection& theConnections) {
461 	theConnections.device_p = theDevice_p;
462 	theConnections.deviceId = theInstance_p->firstDeviceId + theDevice_p->offset;
463 	SetConnections_(theConnections, theConnections.deviceId);
464 	switch (theDevice_p->model_p->type) {
465 		case NMOS: case PMOS: case LDDN: case LDDP: {
466 			theConnections.originalDrainId = theInstance_p->localToGlobalNetId_v[theDevice_p->signalId_v[0]];
467 			theConnections.originalGateId = theInstance_p->localToGlobalNetId_v[theDevice_p->signalId_v[1]];
468 			theConnections.originalSourceId = theInstance_p->localToGlobalNetId_v[theDevice_p->signalId_v[2]];
469 			if ( cvcParameters.cvcSOI ) {
470 				theConnections.originalBulkId = UNKNOWN_NET;
471 			} else {
472 				theConnections.originalBulkId = theInstance_p->localToGlobalNetId_v[theDevice_p->signalId_v[3]];
473 			}
474 			break; }
475 		case DIODE: case SWITCH_OFF: case FUSE_OFF: case CAPACITOR:	case SWITCH_ON:	case FUSE_ON: case RESISTOR: {
476 			theConnections.originalSourceId = theInstance_p->localToGlobalNetId_v[theDevice_p->signalId_v[0]];
477 			theConnections.originalGateId = UNKNOWN_NET;
478 			theConnections.originalDrainId = theInstance_p->localToGlobalNetId_v[theDevice_p->signalId_v[1]];
479 			if ( theDevice_p->signalId_v.size() == 3 ) {
480 				theConnections.originalBulkId = theInstance_p->localToGlobalNetId_v[theDevice_p->signalId_v[2]];;
481 			} else {
482 				theConnections.originalBulkId = UNKNOWN_NET;
483 			}
484 			break; }
485 		case BIPOLAR: {
486 			theConnections.originalSourceId = theInstance_p->localToGlobalNetId_v[theDevice_p->signalId_v[0]];
487 			theConnections.originalGateId = theInstance_p->localToGlobalNetId_v[theDevice_p->signalId_v[1]];
488 			theConnections.originalDrainId = theInstance_p->localToGlobalNetId_v[theDevice_p->signalId_v[2]];
489 			theConnections.originalBulkId = UNKNOWN_NET;
490 			break; }
491 		default: {
492 			theDevice_p->model_p->Print();
493 			throw EUnknownModel();
494 		}
495 	}
496 	theConnections.masterMaxSourceNet(maxNet_v, theConnections.sourceId);
497 	theConnections.masterMaxGateNet(maxNet_v, theConnections.gateId);
498 	theConnections.masterMaxDrainNet(maxNet_v, theConnections.drainId);
499 	theConnections.masterMaxBulkNet(maxNet_v, theConnections.bulkId);
500 	theConnections.maxSourceVoltage = netVoltagePtr_v.MaxVoltage(theConnections.masterMaxSourceNet.finalNetId);
501 	theConnections.maxGateVoltage = netVoltagePtr_v.MaxVoltage(theConnections.masterMaxGateNet.finalNetId);
502 	theConnections.maxDrainVoltage = netVoltagePtr_v.MaxVoltage(theConnections.masterMaxDrainNet.finalNetId);
503 	theConnections.maxBulkVoltage = netVoltagePtr_v.MaxVoltage(theConnections.masterMaxBulkNet.finalNetId);
504 	theConnections.maxSourcePower_p = netVoltagePtr_v[theConnections.masterMaxSourceNet.finalNetId].full;
505 	theConnections.maxDrainPower_p = netVoltagePtr_v[theConnections.masterMaxDrainNet.finalNetId].full;
506 	if ( theConnections.masterMaxGateNet.finalNetId == UNKNOWN_NET ) {
507 		theConnections.maxGatePower_p = NULL;
508 	} else {
509 		theConnections.maxGatePower_p = netVoltagePtr_v[theConnections.masterMaxGateNet.finalNetId].full;
510 	}
511 	if ( theConnections.masterMaxBulkNet.finalNetId == UNKNOWN_NET ) {
512 		theConnections.maxBulkPower_p = NULL;
513 	} else {
514 		theConnections.maxBulkPower_p = netVoltagePtr_v[theConnections.masterMaxBulkNet.finalNetId].full;
515 	}
516 
517 	theConnections.masterMinSourceNet(minNet_v, theConnections.sourceId);
518 	theConnections.masterMinGateNet(minNet_v, theConnections.gateId);
519 	theConnections.masterMinDrainNet(minNet_v, theConnections.drainId);
520 	theConnections.masterMinBulkNet(minNet_v, theConnections.bulkId);
521 	theConnections.minSourceVoltage = netVoltagePtr_v.MinVoltage(theConnections.masterMinSourceNet.finalNetId);
522 	theConnections.minGateVoltage = netVoltagePtr_v.MinVoltage(theConnections.masterMinGateNet.finalNetId);
523 	theConnections.minDrainVoltage = netVoltagePtr_v.MinVoltage(theConnections.masterMinDrainNet.finalNetId);
524 	theConnections.minBulkVoltage = netVoltagePtr_v.MinVoltage(theConnections.masterMinBulkNet.finalNetId);
525 	theConnections.minSourcePower_p = netVoltagePtr_v[theConnections.masterMinSourceNet.finalNetId].full;
526 	theConnections.minDrainPower_p = netVoltagePtr_v[theConnections.masterMinDrainNet.finalNetId].full;
527 	if ( theConnections.masterMinGateNet.finalNetId == UNKNOWN_NET ) {
528 		theConnections.minGatePower_p = NULL;
529 	} else {
530 		theConnections.minGatePower_p = netVoltagePtr_v[theConnections.masterMinGateNet.finalNetId].full;
531 	}
532 	if ( theConnections.masterMinBulkNet.finalNetId == UNKNOWN_NET ) {
533 		theConnections.minBulkPower_p = NULL;
534 	} else {
535 		theConnections.minBulkPower_p = netVoltagePtr_v[theConnections.masterMinBulkNet.finalNetId].full;
536 	}
537 
538 	theConnections.masterSimSourceNet(simNet_v, theConnections.sourceId);
539 	theConnections.masterSimGateNet(simNet_v, theConnections.gateId);
540 	theConnections.masterSimDrainNet(simNet_v, theConnections.drainId);
541 	theConnections.masterSimBulkNet(simNet_v, theConnections.bulkId);
542 	theConnections.simSourceVoltage = netVoltagePtr_v.SimVoltage(theConnections.masterSimSourceNet.finalNetId);
543 	theConnections.simGateVoltage = netVoltagePtr_v.SimVoltage(theConnections.masterSimGateNet.finalNetId);
544 	theConnections.simDrainVoltage = netVoltagePtr_v.SimVoltage(theConnections.masterSimDrainNet.finalNetId);
545 	theConnections.simBulkVoltage = netVoltagePtr_v.SimVoltage(theConnections.masterSimBulkNet.finalNetId);
546 	theConnections.simSourcePower_p = netVoltagePtr_v[theConnections.masterSimSourceNet.finalNetId].full;
547 	theConnections.simDrainPower_p = netVoltagePtr_v[theConnections.masterSimDrainNet.finalNetId].full;
548 	if ( theConnections.masterSimGateNet.finalNetId == UNKNOWN_NET ) {
549 		theConnections.simGatePower_p = NULL;
550 	} else {
551 		theConnections.simGatePower_p = netVoltagePtr_v[theConnections.masterSimGateNet.finalNetId].full;
552 	}
553 	if ( theConnections.masterSimBulkNet.finalNetId == UNKNOWN_NET ) {
554 		theConnections.simBulkPower_p = NULL;
555 	} else {
556 		theConnections.simBulkPower_p = netVoltagePtr_v[theConnections.masterSimBulkNet.finalNetId].full;
557 	}
558 	theConnections.resistance = parameterResistanceMap[theConnections.device_p->parameters];
559 }
560 
IgnoreDevice(deviceId_t theDeviceId)561 void CCvcDb::IgnoreDevice(deviceId_t theDeviceId) {
562 	static CStatus myIgnoredDevice = 0;
563 	if ( myIgnoredDevice == 0 ) {
564 		myIgnoredDevice[MAX_INACTIVE] = true;
565 		myIgnoredDevice[MAX_PENDING] = false;
566 		myIgnoredDevice[MIN_INACTIVE] = true;
567 		myIgnoredDevice[MIN_PENDING] = false;
568 		myIgnoredDevice[SIM_INACTIVE] = true;
569 		myIgnoredDevice[SIM_PENDING] = false;
570 	}
571 	deviceStatus_v[theDeviceId] = myIgnoredDevice;
572 }
573 
EqualMasterNets(CVirtualNetVector & theVirtualNet_v,netId_t theFirstNetId,netId_t theSecondNetId)574 bool CCvcDb::EqualMasterNets(CVirtualNetVector& theVirtualNet_v, netId_t theFirstNetId, netId_t theSecondNetId) {
575 	resistance_t myFirstResistance = 0, mySecondResistance = 0;
576 	if ( theFirstNetId == theSecondNetId ) return true;
577 	while ( theFirstNetId != theVirtualNet_v[theFirstNetId].nextNetId ) {
578 		AddResistance(myFirstResistance, theVirtualNet_v[theFirstNetId].resistance);
579 		CheckResistorOverflow_(myFirstResistance, theFirstNetId, logFile);
580 		theFirstNetId = theVirtualNet_v[theFirstNetId].nextNetId;
581 	}
582 	while ( theSecondNetId != theVirtualNet_v[theSecondNetId].nextNetId ) {
583 		AddResistance(mySecondResistance, theVirtualNet_v[theSecondNetId].resistance);
584 		CheckResistorOverflow_(mySecondResistance, theSecondNetId, logFile);
585 		theSecondNetId = theVirtualNet_v[theSecondNetId].nextNetId;
586 	}
587 	return ( (theFirstNetId == theSecondNetId) && (mySecondResistance == myFirstResistance) );
588 }
589 
GateEqualsDrain(CConnection & theConnections)590 bool CCvcDb::GateEqualsDrain(CConnection& theConnections) {
591 	if ( netVoltagePtr_v[theConnections.masterDrainNet.finalNetId].full == NULL ) return theConnections.gateId == theConnections.drainId;
592 	if ( netVoltagePtr_v[theConnections.masterSourceNet.nextNetId].full == NULL ) return theConnections.gateId == theConnections.sourceId;
593 	throw EDatabaseError("GateEqualsDrain: " + NetName(theConnections.gateId));
594 }
595 
PathContains(CVirtualNetVector & theSearchVector,netId_t theSearchNet,netId_t theTargetNet)596 bool CCvcDb::PathContains(CVirtualNetVector& theSearchVector, netId_t theSearchNet, netId_t theTargetNet) {
597 	netId_t myTargetNet = GetEquivalentNet(theTargetNet);
598 	if (theSearchNet == myTargetNet) return true;
599 	netId_t net_it = theSearchNet;
600 	do {
601 		net_it = theSearchVector[net_it].nextNetId;
602 		if ( net_it != myTargetNet ) return true;
603 	} while ( ! theSearchVector.IsTerminal(net_it) );
604 	return false;
605 }
606 
PathCrosses(CVirtualNetVector & theSearchVector,netId_t theSearchNet,CVirtualNetVector & theTargetVector,netId_t theTargetNet)607 bool CCvcDb::PathCrosses(CVirtualNetVector& theSearchVector, netId_t theSearchNet, CVirtualNetVector& theTargetVector, netId_t theTargetNet) {
608 	set<netId_t>	myTargetSet;
609 	myTargetSet.insert(theTargetNet);
610 	netId_t net_it = theTargetNet;
611 	do {
612 		net_it = theTargetVector[net_it].nextNetId;
613 		myTargetSet.insert(net_it);
614 	} while ( ! theTargetVector.IsTerminal(net_it) );
615 	if ( myTargetSet.find(theSearchNet) != myTargetSet.end() ) return true;
616 	net_it = theSearchNet;
617 	do {
618 		net_it = theSearchVector[net_it].nextNetId;
619 		if ( myTargetSet.find(net_it) != myTargetSet.end() ) return true;
620 	} while ( ! theSearchVector.IsTerminal(net_it) );
621 	return false;
622 }
623 
HasActiveConnection(netId_t theNetId)624 bool CCvcDb::HasActiveConnection(netId_t theNetId) {
625 	for ( deviceId_t device_it = firstSource_v[theNetId]; device_it != UNKNOWN_DEVICE; device_it = nextSource_v[device_it] ) {
626 		if ( deviceStatus_v[device_it][SIM_INACTIVE] == false ) return true;
627 	}
628 	for ( deviceId_t device_it = firstDrain_v[theNetId]; device_it != UNKNOWN_DEVICE; device_it = nextDrain_v[device_it] ) {
629 		if ( deviceStatus_v[device_it][SIM_INACTIVE] == false ) return true;
630 	}
631 	return false;
632 }
633 
DefaultMinVoltage(CPower * thePower_p)634 voltage_t CCvcDb::DefaultMinVoltage(CPower * thePower_p) {
635 	if ( thePower_p->defaultMinNet == UNKNOWN_NET ) {
636 		return(UNKNOWN_VOLTAGE);
637 	} else {
638 		netId_t myMinNet = minNet_v[thePower_p->defaultMinNet].finalNetId;
639 		CPower * myMinPower_p = netVoltagePtr_v[myMinNet].full;
640 		if ( myMinPower_p && myMinPower_p->minVoltage != UNKNOWN_VOLTAGE ) {
641 			return(myMinPower_p->minVoltage);
642 		} else {
643 			reportFile << "DEBUG: Unexpected min voltage at net " << NetName(myMinNet) << endl;
644 			return(UNKNOWN_VOLTAGE);
645 		}
646 	}
647 }
648 
DefaultMaxVoltage(CPower * thePower_p)649 voltage_t CCvcDb::DefaultMaxVoltage(CPower * thePower_p) {
650 	if ( thePower_p->defaultMaxNet == UNKNOWN_NET ) {
651 		return(UNKNOWN_VOLTAGE);
652 	} else {
653 		netId_t myMaxNet = maxNet_v[thePower_p->defaultMaxNet].finalNetId;
654 		CPower * myMaxPower_p = netVoltagePtr_v[myMaxNet].full;
655 		if ( myMaxPower_p && myMaxPower_p->maxVoltage != UNKNOWN_VOLTAGE ) {
656 			return(myMaxPower_p->maxVoltage);
657 		} else {
658 			reportFile << "DEBUG: Unexpected max voltage at net " << NetName(myMaxNet) << endl;
659 			return(UNKNOWN_VOLTAGE);
660 		}
661 	}
662 }
663 
HasLeakPath(CFullConnection & theConnections)664 bool CCvcDb::HasLeakPath(CFullConnection & theConnections) {
665 	if ( theConnections.minSourcePower_p ) {
666 		if ( ! theConnections.minSourcePower_p->active[MIN_ACTIVE] ) return false;
667 		if ( theConnections.maxDrainPower_p && theConnections.minSourcePower_p->type[HIZ_BIT] ) {
668 			if ( theConnections.drainId == maxNet_v[theConnections.drainId].nextNetId && theConnections.maxDrainVoltage == UNKNOWN_VOLTAGE ) return false;
669 //			if ( theConnections.maxDrainPower_p->type[HIZ_BIT] ) return false;
670 			return ! theConnections.minSourcePower_p->IsRelatedPower(theConnections.maxDrainPower_p, netVoltagePtr_v, minNet_v, maxNet_v, false);
671 		}
672 	}
673 	if ( theConnections.minDrainPower_p ) {
674 		if ( ! theConnections.minDrainPower_p->active[MIN_ACTIVE] ) return false;
675 		if ( theConnections.maxSourcePower_p && theConnections.minDrainPower_p->type[HIZ_BIT] ) {
676 			if ( theConnections.sourceId == maxNet_v[theConnections.sourceId].nextNetId && theConnections.maxSourceVoltage == UNKNOWN_VOLTAGE ) return false;
677 //			if ( theConnections.maxSourcePower_p->type[HIZ_BIT] ) return false;
678 			return ! theConnections.minDrainPower_p->IsRelatedPower(theConnections.maxSourcePower_p, netVoltagePtr_v, minNet_v, maxNet_v, false);
679 		}
680 	}
681 	if ( theConnections.maxSourcePower_p ) {
682 		if ( ! theConnections.maxSourcePower_p->active[MAX_ACTIVE] ) return false;
683 		if ( theConnections.minDrainPower_p && theConnections.maxSourcePower_p->type[HIZ_BIT] ) {
684 			if ( theConnections.drainId == minNet_v[theConnections.drainId].nextNetId && theConnections.minDrainVoltage == UNKNOWN_VOLTAGE ) return false;
685 //			if ( theConnections.minDrainPower_p->type[HIZ_BIT] ) return false;
686 			return ! theConnections.maxSourcePower_p->IsRelatedPower(theConnections.minDrainPower_p, netVoltagePtr_v, maxNet_v, minNet_v, false);
687 		}
688 	}
689 	if ( theConnections.maxDrainPower_p ) {
690 		if ( ! theConnections.maxDrainPower_p->active[MAX_ACTIVE] ) return false;
691 		if ( theConnections.minSourcePower_p && theConnections.maxDrainPower_p->type[HIZ_BIT] ) {
692 			if ( theConnections.sourceId == minNet_v[theConnections.sourceId].nextNetId && theConnections.minSourceVoltage == UNKNOWN_VOLTAGE ) return false;
693 //			if ( theConnections.minSourcePower_p->type[HIZ_BIT] ) return false;
694 			return ! theConnections.maxDrainPower_p->IsRelatedPower(theConnections.minSourcePower_p, netVoltagePtr_v, maxNet_v, minNet_v, false);
695 		}
696 	}
697 	if ( theConnections.simSourcePower_p && theConnections.simSourcePower_p->defaultSimNet == theConnections.drainId ) return false;  // ignore leaks to own calculated voltage
698 	if ( theConnections.simDrainPower_p && theConnections.simDrainPower_p->defaultSimNet == theConnections.sourceId ) return false;  // ignore leaks to own calculated voltage
699 	if ( theConnections.simSourceVoltage != UNKNOWN_VOLTAGE
700 			&& abs(theConnections.simSourceVoltage - theConnections.simDrainVoltage) < cvcParameters.cvcFloatingErrorThreshold ) return false;  // ignore leaks less than threshold
701 	netId_t myMinSourceNet = minNet_v[theConnections.sourceId].nextNetId;
702 	netId_t myMaxSourceNet = maxNet_v[theConnections.sourceId].nextNetId;
703 	netId_t myMinDrainNet = minNet_v[theConnections.drainId].nextNetId;
704 	netId_t myMaxDrainNet = maxNet_v[theConnections.drainId].nextNetId;
705 	CPower * myPower_p = netVoltagePtr_v[theConnections.sourceId].full;
706 	if ( myPower_p ) {
707 		if ( myPower_p->type[MIN_CALCULATED_BIT] && myPower_p->defaultMinNet != UNKNOWN_NET ) myMinSourceNet = myPower_p->defaultMinNet;
708 		if ( myPower_p->type[MAX_CALCULATED_BIT] && myPower_p->defaultMaxNet != UNKNOWN_NET ) myMaxSourceNet = myPower_p->defaultMaxNet;
709 	}
710 	myPower_p = netVoltagePtr_v[theConnections.drainId].full;
711 	if ( myPower_p ) {
712 		if ( myPower_p->type[MIN_CALCULATED_BIT] && myPower_p->defaultMinNet != UNKNOWN_NET ) myMinDrainNet = myPower_p->defaultMinNet;
713 		if ( myPower_p->type[MAX_CALCULATED_BIT] && myPower_p->defaultMaxNet != UNKNOWN_NET ) myMaxDrainNet = myPower_p->defaultMaxNet;
714 	}
715 	if ( (myMinSourceNet == theConnections.drainId || theConnections.minSourceVoltage == UNKNOWN_VOLTAGE)
716 			&& (myMaxSourceNet == theConnections.drainId || theConnections.maxSourceVoltage == UNKNOWN_VOLTAGE) ) return false;  // min/max path same or non-existant
717 //			&& connectionCount_v[theConnections.sourceId].gateCount == 0) return false;  // min/max path same with no gate connections
718 	if ( (myMinDrainNet == theConnections.sourceId || theConnections.minDrainVoltage == UNKNOWN_VOLTAGE)
719 			&& (myMaxDrainNet == theConnections.sourceId || theConnections.maxDrainVoltage == UNKNOWN_VOLTAGE) ) return false;  // min/max path same with no gate connections
720 //			&& connectionCount_v[theConnections.drainId].gateCount == 0) return false;  // min/max path same with no gate connections
721 	voltage_t myMinSourceVoltage = theConnections.minSourceVoltage;
722 	if ( theConnections.minSourcePower_p && theConnections.minSourcePower_p->type[MIN_CALCULATED_BIT] ) {
723 		myMinSourceVoltage = DefaultMinVoltage(theConnections.minSourcePower_p);
724 	}
725 	voltage_t myMaxSourceVoltage = theConnections.maxSourceVoltage;
726 	if ( theConnections.maxSourcePower_p && theConnections.maxSourcePower_p->type[MAX_CALCULATED_BIT] ) {
727 		myMaxSourceVoltage = DefaultMaxVoltage(theConnections.maxSourcePower_p);
728 	}
729 	voltage_t myMinDrainVoltage = theConnections.minDrainVoltage;
730 	if ( theConnections.minDrainPower_p && theConnections.minDrainPower_p->type[MIN_CALCULATED_BIT] ) {
731 		myMinDrainVoltage = DefaultMinVoltage(theConnections.minDrainPower_p);
732 	}
733 	voltage_t myMaxDrainVoltage = theConnections.maxDrainVoltage;
734 	if ( theConnections.maxDrainPower_p && theConnections.maxDrainPower_p->type[MAX_CALCULATED_BIT] ) {
735 		myMaxDrainVoltage = DefaultMaxVoltage(theConnections.maxDrainPower_p);
736 	}
737 	if ( myMinSourceVoltage != UNKNOWN_VOLTAGE && myMaxDrainVoltage != UNKNOWN_VOLTAGE && myMinSourceVoltage < myMaxDrainVoltage ) return true;
738 	if ( myMaxSourceVoltage != UNKNOWN_VOLTAGE && myMinDrainVoltage != UNKNOWN_VOLTAGE && myMaxSourceVoltage > myMinDrainVoltage ) return true;
739 	return false;
740 }
741 
IncrementDeviceError(deviceId_t theDeviceId,int theErrorIndex)742 size_t CCvcDb::IncrementDeviceError(deviceId_t theDeviceId, int theErrorIndex) {
743 	CInstance * myInstance_p = instancePtr_v[deviceParent_v[theDeviceId]];
744 	CCircuit * myParent_p = myInstance_p->master_p;
745 	int myErrorSubIndex = 0;
746 	if ( theErrorIndex >= OVERVOLTAGE_VBG && theErrorIndex <= MODEL_CHECK ) {
747 		myErrorSubIndex = theErrorIndex - OVERVOLTAGE_VBG;
748 	}
749 	int myMFactor = CalculateMFactor(deviceParent_v[theDeviceId]);
750 	size_t myReturnCount = myParent_p->devicePrintCount_v[theDeviceId - myInstance_p->firstDeviceId][myErrorSubIndex] + 1;
751 	string myKey = "";
752 	deviceId_t myLimit = UNKNOWN_DEVICE;
753 	if ( ! IsEmpty(cvcParameters.cvcCellErrorLimitFile) ) {
754 		instanceId_t myAncestor = deviceParent_v[theDeviceId];
755 		while ( myAncestor > 0 && instancePtr_v[myAncestor]->master_p->errorLimit == UNKNOWN_DEVICE ) {
756 			myAncestor = instancePtr_v[myAncestor]->parentId;
757 		}
758 		if (myAncestor > 0) {
759 			myLimit = instancePtr_v[myAncestor]->master_p->errorLimit;
760 			if ( myLimit > 0 ) {
761 				myKey = string(instancePtr_v[myAncestor]->master_p->name) + " " + string(myParent_p->name) + " "
762 						+ to_string<deviceId_t>(theDeviceId - myInstance_p->firstDeviceId) + " " + to_string<int>(myErrorSubIndex);
763 				cellErrorCountMap[myKey]++;
764 				if ( cellErrorCountMap[myKey] > myLimit ) {
765 					myReturnCount = UNKNOWN_DEVICE;
766 				} else {
767 					myReturnCount = cellErrorCountMap[myKey];  // if limit is set, always print up to error limit
768 				}
769 			} else {  // no map entries needed if limit is 0
770 				myReturnCount = UNKNOWN_DEVICE;
771 			}
772 		}
773 	}
774 	if ( myLimit > 0 ) {
775 		myParent_p->deviceErrorCount_v[theDeviceId - myInstance_p->firstDeviceId][myErrorSubIndex] += myMFactor;
776 		errorCount[theErrorIndex] += myMFactor;
777 	}
778 	if ( myReturnCount < UNKNOWN_DEVICE ) {
779 		myParent_p->devicePrintCount_v[theDeviceId - myInstance_p->firstDeviceId][myErrorSubIndex]++;
780 	}
781 	return(myReturnCount);
782 }
783 
SplitHierarchy(string theFullPath)784 list<string> * CCvcDb::SplitHierarchy(string theFullPath) {
785 	list<string> * myHierarchy = new list<string>;
786 	size_t myStringStart = 0;
787 	if ( theFullPath.substr(0, 1) == "/" ) {
788 		myHierarchy->push_back("");
789 		myStringStart = 1;
790 	}
791 	size_t myHierarchyOffset = theFullPath.find(cvcParameters.cvcHierarchyDelimiters, myStringStart);
792 	while ( myHierarchyOffset <= theFullPath.size() ) {
793 		myHierarchy->push_back(theFullPath.substr(myStringStart, myHierarchyOffset - myStringStart));
794 		myStringStart = myHierarchyOffset + 1;
795 		myHierarchyOffset = theFullPath.find(cvcParameters.cvcHierarchyDelimiters, myStringStart);
796 	}
797 	myHierarchy->push_back(theFullPath.substr(myStringStart));
798 	return myHierarchy;
799 }
800 
SaveMinMaxLeakVoltages()801 void CCvcDb::SaveMinMaxLeakVoltages() {
802 	leakVoltageSet = true;
803 	cout << "Saving min/max voltages..." << endl;
804 	minNet_v.BackupVirtualNets();
805 	maxNet_v.BackupVirtualNets();
806 	leakVoltagePtr_v = netVoltagePtr_v;
807 }
808 
SaveInitialVoltages()809 void CCvcDb::SaveInitialVoltages() {
810 	cout << "Saving simulation voltages..." << endl;
811 	simNet_v.BackupVirtualNets();
812 	initialVoltagePtr_v = netVoltagePtr_v;
813 }
814 
ExpandBusNet(string theBusName)815 list<string> * CCvcDb::ExpandBusNet(string theBusName) {
816 	list<string> * myNetList = new(list<string>);
817 	size_t myBusLength = theBusName.length();
818 	string myBusTerminator;
819 	size_t myBusBegin = theBusName.find_first_of("<");
820 	size_t myBusDelimiter = theBusName.find_first_of(":");
821 	myBusTerminator = ">";
822 	if ( myBusBegin > myBusLength ) { // '<' not found
823 		myBusBegin = theBusName.find_first_of("[");
824 		myBusTerminator = "]";
825 	}
826 	if ( myBusBegin > myBusLength ) { // '[' not found
827 		myBusBegin = theBusName.find_first_of("(");
828 		myBusTerminator = ")";
829 	}
830 	if ( myBusBegin > myBusLength ) { // '(' not found
831 		myBusBegin = theBusName.find_first_of("{");
832 		myBusTerminator = "}";
833 	}
834 	size_t myBusEnd = theBusName.find_first_of(myBusTerminator);
835 	if ( myBusBegin < myBusLength && myBusDelimiter < myBusLength && myBusEnd <= myBusLength ) {
836 		string myBaseSignal = theBusName.substr(0, myBusBegin + 1);
837 		int myFirstBusIndex = from_string<int>(theBusName.substr(myBusBegin + 1, myBusDelimiter - myBusBegin - 1));
838 		int myLastBusIndex = from_string<int>(theBusName.substr(myBusDelimiter + 1, myBusEnd - myBusDelimiter - 1));
839 		for ( int myBusIndex = min(myFirstBusIndex, myLastBusIndex); myBusIndex <= max(myFirstBusIndex, myLastBusIndex); myBusIndex++ ) {
840 			string myPowerDefinition = myBaseSignal + to_string<int>(myBusIndex) + theBusName.substr(myBusEnd);
841 			if ( myFirstBusIndex < myLastBusIndex ) {
842 				myNetList->push_back(myPowerDefinition); // ascending
843 			} else {
844 				myNetList->push_front(myPowerDefinition); // descending
845 			}
846 		}
847 	} else {
848 		myNetList->push_front(theBusName);
849 	}
850 
851 	return(myNetList);
852 }
853 
854 #define EVENT_CUTOFF (1<<24)
855 #define LARGE_EVENT_SCALE 8
856 
SimKey(eventKey_t theCurrentKey,resistance_t theIncrement)857 eventKey_t CCvcDb::SimKey(eventKey_t theCurrentKey, resistance_t theIncrement) {
858 	long myEventKey;
859 	if ( long(theCurrentKey) < EVENT_CUTOFF ) {
860 		myEventKey = theCurrentKey;
861 	} else {
862 		myEventKey = EVENT_CUTOFF + ((long(theCurrentKey) - EVENT_CUTOFF) << LARGE_EVENT_SCALE);
863 	}
864 	myEventKey += theIncrement;
865 	if ( myEventKey > EVENT_CUTOFF ) {
866 		myEventKey = EVENT_CUTOFF + ((myEventKey - EVENT_CUTOFF) >> LARGE_EVENT_SCALE);
867 	}
868 	assert(myEventKey < MAX_EVENT_TIME);
869 	return(myEventKey);
870 }
871 
IsDerivedFromFloating(CVirtualNetVector & theVirtualNet_v,netId_t theNetId)872 bool CCvcDb::IsDerivedFromFloating(CVirtualNetVector& theVirtualNet_v, netId_t theNetId) {
873 	static CVirtualNet	myVirtualNet;
874 	assert(theNetId == GetEquivalentNet(theNetId));
875 	myVirtualNet(theVirtualNet_v, theNetId);
876 	return( netVoltagePtr_v[myVirtualNet.finalNetId].full && netVoltagePtr_v[myVirtualNet.finalNetId].full->type[HIZ_BIT] );
877 }
878 
HasActiveConnections(netId_t theNetId)879 bool CCvcDb::HasActiveConnections(netId_t theNetId) {
880 	for ( deviceId_t device_it = firstSource_v[theNetId]; device_it != UNKNOWN_DEVICE; device_it = nextSource_v[device_it] ) {
881 		if ( ! deviceStatus_v[device_it][SIM_INACTIVE] ) return true;
882 	}
883 	for ( deviceId_t device_it = firstDrain_v[theNetId]; device_it != UNKNOWN_DEVICE; device_it = nextDrain_v[device_it] ) {
884 		if ( ! deviceStatus_v[device_it][SIM_INACTIVE] ) return true;
885 	}
886 	return false;
887 }
888 
InstanceDepth(instanceId_t theInstanceId)889 size_t CCvcDb::InstanceDepth(instanceId_t theInstanceId) {
890 	size_t myDepth = 0;
891 	while ( theInstanceId != 0 ) {
892 		assert(myDepth < subcircuitCount);
893 		assert(theInstanceId != UNKNOWN_INSTANCE);
894 		myDepth++;
895 		theInstanceId = instancePtr_v[theInstanceId]->parentId;
896 	}
897 	return(myDepth);
898 }
899 
IsSubcircuitOf(instanceId_t theInstanceId,instanceId_t theParentId)900 bool CCvcDb::IsSubcircuitOf(instanceId_t theInstanceId, instanceId_t theParentId) {
901 	if ( theParentId == 0 ) return true;  // everything is subcircuit of root
902 	if ( theInstanceId == theParentId ) return true;
903 	if ( instancePtr_v[theInstanceId]->parentId == theParentId ) return true;
904 	size_t myCount = 0;
905 	while ( instancePtr_v[theInstanceId]->parentId != 0 ) {
906 		assert(myCount++ < subcircuitCount);
907 		theInstanceId = instancePtr_v[theInstanceId]->parentId;
908 		if ( theInstanceId == theParentId ) return true;
909 	}
910 	return false;
911 }
912 
RemoveInvalidPower(netId_t theNetId,size_t & theRemovedCount)913 void CCvcDb::RemoveInvalidPower(netId_t theNetId, size_t & theRemovedCount) {
914 	if ( theNetId == UNKNOWN_NET || ! netVoltagePtr_v[theNetId].full ) return;
915 	if ( minNet_v[theNetId].finalNetId > theNetId ) {
916 		RemoveInvalidPower(minNet_v[theNetId].finalNetId, theRemovedCount);
917 	}
918 	if ( maxNet_v[theNetId].finalNetId > theNetId ) {
919 		RemoveInvalidPower(maxNet_v[theNetId].finalNetId, theRemovedCount);
920 	}
921 	voltage_t myMaxVoltage = MaxVoltage(theNetId, true);
922 	voltage_t myMinVoltage = MinVoltage(theNetId, true);
923 	if ( netStatus_v[theNetId][NEEDS_MIN_CHECK] && ! netStatus_v[theNetId][NEEDS_MAX_CHECK] && ! IsDerivedFromFloating(minNet_v, theNetId) ) {
924 		voltage_t myMinCheckVoltage = ( myMinVoltage == UNKNOWN_VOLTAGE ) ? MinLeakVoltage(theNetId) : myMinVoltage;
925 		// intentionally not parallel with following check. only need to check high value for unknown.
926 		if ( myMaxVoltage != UNKNOWN_VOLTAGE && myMinCheckVoltage < myMaxVoltage ) {
927 			netStatus_v[theNetId][NEEDS_MIN_CHECK] = false;
928 		}
929 	}
930 	if ( netStatus_v[theNetId][NEEDS_MAX_CHECK] && ! netStatus_v[theNetId][NEEDS_MIN_CHECK] && ! IsDerivedFromFloating(maxNet_v, theNetId) ) {
931 		voltage_t myMaxCheckVoltage = ( myMaxVoltage == UNKNOWN_VOLTAGE ) ? MaxLeakVoltage(theNetId) : myMaxVoltage;
932 		if ( myMaxCheckVoltage != UNKNOWN_VOLTAGE && myMaxCheckVoltage > myMinVoltage ) {
933 			netStatus_v[theNetId][NEEDS_MAX_CHECK] = false;
934 		}
935 	}
936 	if ( myMinVoltage != UNKNOWN_VOLTAGE && myMaxVoltage != UNKNOWN_VOLTAGE && myMinVoltage <= myMaxVoltage
937 			&& netStatus_v[theNetId][NEEDS_MIN_CHECK] && netStatus_v[theNetId][NEEDS_MAX_CHECK] ) {
938 		// both min and max are calculated values
939 		netStatus_v[theNetId][NEEDS_MIN_CHECK] = netStatus_v[theNetId][NEEDS_MAX_CHECK] = false;
940 	}
941 	if ( gDebug_cvc && netStatus_v[theNetId][NEEDS_MIN_CHECK] ) cout << "DEBUG: unverified min net " << theNetId << endl;
942 	if ( gDebug_cvc && netStatus_v[theNetId][NEEDS_MAX_CHECK] ) cout << "DEBUG: unverified max net " << theNetId << endl;
943 	if ( IsCalculatedVoltage_(netVoltagePtr_v[theNetId].full) == false ) { // handle partial power specification
944 		if ( netStatus_v[theNetId][NEEDS_MIN_CHECK] || netStatus_v[theNetId][NEEDS_MAX_CONNECTION] ) {
945 			// NEEDS_MIN_CHECK means that max prop through nmos occurred (Vth drop), but no lower voltage was found
946 			// NEEDS_MAX_CONNECTION means that max estimated voltage through nmos diode, does not have pull up connections
947 			if (gDebug_cvc) cout << "INFO: Remove max voltage at net " << theNetId << " Min: " << myMinVoltage << " Max: " << myMaxVoltage << endl;
948 			// maybe use default min here
949 			netVoltagePtr_v[theNetId].full->maxVoltage = netVoltagePtr_v[netVoltagePtr_v[theNetId].full->defaultMaxNet].full->maxVoltage;
950 			netStatus_v[theNetId][NEEDS_MIN_CHECK] = netStatus_v[theNetId][NEEDS_MAX_CONNECTION] = false;
951 		}
952 		if ( netStatus_v[theNetId][NEEDS_MAX_CHECK] || netStatus_v[theNetId][NEEDS_MIN_CONNECTION] ) {
953 			// NEEDS_MAX_CHECK means that min prop through pmos occurred (Vth step up), but no higher voltage was found
954 			// NEEDS_MIN_CONNECTION means that min estimated voltage through pmos diode, does not have pull down connections
955 			if (gDebug_cvc) cout << "INFO: Remove min voltage at net " << theNetId << " Min: " << myMinVoltage << " Max: " << myMaxVoltage << endl;
956 			// maybe use default max here
957 			netVoltagePtr_v[theNetId].full->minVoltage = netVoltagePtr_v[netVoltagePtr_v[theNetId].full->defaultMinNet].full->minVoltage;
958 			netStatus_v[theNetId][NEEDS_MAX_CHECK] = netStatus_v[theNetId][NEEDS_MIN_CONNECTION] = false;
959 		}
960 		return;
961 	}
962 	if ( myMinVoltage == UNKNOWN_VOLTAGE || myMaxVoltage == UNKNOWN_VOLTAGE || myMinVoltage > myMaxVoltage ||
963 			netStatus_v[theNetId][NEEDS_MIN_CHECK] || netStatus_v[theNetId][NEEDS_MAX_CHECK] ||
964 			netStatus_v[theNetId][NEEDS_MIN_CONNECTION] || netStatus_v[theNetId][NEEDS_MAX_CONNECTION] ) {
965 		// invalid calculation
966 		if (gDebug_cvc) cout << "INFO: Checking " << theNetId
967 				<< " MIN/MAX_CHECK " << (netStatus_v[theNetId][NEEDS_MIN_CHECK] ? "1" : "0") << "|" << (netStatus_v[theNetId][NEEDS_MAX_CHECK] ? "1" : "0")
968 				<< " MIN/MAX_CONNECTION " << (netStatus_v[theNetId][NEEDS_MIN_CONNECTION] ? "1" : "0") << "|" << (netStatus_v[theNetId][NEEDS_MAX_CONNECTION] ? "1" : "0") << endl;
969 			netStatus_v[theNetId][NEEDS_MIN_CHECK] = netStatus_v[theNetId][NEEDS_MAX_CHECK] = false;
970 			netStatus_v[theNetId][NEEDS_MIN_CONNECTION] = netStatus_v[theNetId][NEEDS_MAX_CONNECTION] = false;
971 			if ( leakVoltageSet && leakVoltagePtr_v[theNetId].full ) {
972 				voltage_t myMaxLeakVoltage = MaxLeakVoltage(theNetId);
973 				if ( myMaxLeakVoltage != UNKNOWN_VOLTAGE && myMinVoltage != UNKNOWN_VOLTAGE && myMaxVoltage != UNKNOWN_VOLTAGE
974 						&& myMinVoltage <= myMaxVoltage && myMaxVoltage <= myMaxLeakVoltage && myMinVoltage >= MinLeakVoltage(theNetId) ) {
975 					return;  // first pass leak voltages mean current calculated voltages ok.
976 			}
977 		}
978 		if (gDebug_cvc) cout << "INFO: Remove calculated voltage at net " << theNetId << " Min: " << myMinVoltage << " Max: " << myMaxVoltage << endl;
979 		if ( theNetId < instancePtr_v[0]->master_p->portCount ) {
980 			reportFile << "WARNING: Invalid Min/Max on top level port: " << NetName(theNetId) << " Min/Max: " << myMinVoltage << "/" << myMaxVoltage << endl;
981 		}
982 		CPower * myPower_p = netVoltagePtr_v[theNetId].full;
983 		if ( ! ( (myPower_p->type[MIN_CALCULATED_BIT] || myPower_p->minVoltage == UNKNOWN_VOLTAGE)
984 				&& (myPower_p->type[MAX_CALCULATED_BIT] || myPower_p->maxVoltage == UNKNOWN_VOLTAGE) ) ) {
985 			reportFile << "WARNING: ignoring setting for " << myPower_p->powerSignal() << " at ";
986 			myPower_p->Print(reportFile, "", NetName(theNetId));
987 		}
988 		netVoltagePtr_v[theNetId].full = NULL;
989 		theRemovedCount++;
990 		// replace deleted voltage with known voltage
991 		myMaxVoltage = MaxVoltage(theNetId);
992 		myMinVoltage = MinVoltage(theNetId);
993 		if ( myMinVoltage == UNKNOWN_VOLTAGE ) {
994 			if ( myPower_p->defaultMinNet != UNKNOWN_NET ) {
995 				// do not increment lastUpdate
996 				minNet_v.Set(theNetId, myPower_p->defaultMinNet, DEFAULT_UNKNOWN_RESISTANCE, minNet_v.lastUpdate);
997 				CheckResistorOverflow_(minNet_v[theNetId].finalResistance, theNetId, logFile);
998 			}
999 		}
1000 		if ( myMaxVoltage == UNKNOWN_VOLTAGE ) {
1001 			if ( myPower_p->defaultMaxNet != UNKNOWN_NET ) {
1002 				// do not increment lastUpdate
1003 				maxNet_v.Set(theNetId, myPower_p->defaultMaxNet, DEFAULT_UNKNOWN_RESISTANCE, maxNet_v.lastUpdate);
1004 				CheckResistorOverflow_(maxNet_v[theNetId].finalResistance, theNetId, logFile);
1005 			}
1006 		}
1007 		if ( ! leakVoltageSet || leakVoltagePtr_v[theNetId].full != myPower_p ) {  // delete unless leak voltage
1008 				delete myPower_p;
1009 		}
1010 	}
1011 }
1012 
GetCalculationType(CPower * thePower_p,eventQueue_t theQueueType)1013 calculationType_t CCvcDb::GetCalculationType(CPower * thePower_p, eventQueue_t theQueueType) {
1014 	switch ( theQueueType ) {
1015 	case MIN_QUEUE: { return thePower_p->minCalculationType; break; }
1016 	case SIM_QUEUE: { return thePower_p->simCalculationType; break; }
1017 	case MAX_QUEUE: { return thePower_p->maxCalculationType; break; }
1018 	default: return UNKNOWN_CALCULATION;
1019 	}
1020 }
1021 
GetSeriesConnectedDevice(deviceId_t theDeviceId,netId_t theNetId)1022 deviceId_t CCvcDb::GetSeriesConnectedDevice(deviceId_t theDeviceId, netId_t theNetId) {
1023 	modelType_t myDeviceType = deviceType_v[theDeviceId];
1024 	deviceId_t myReturnDevice = UNKNOWN_DEVICE;
1025 	for ( deviceId_t device_it = firstDrain_v[theNetId]; device_it != UNKNOWN_DEVICE; device_it = nextDrain_v[device_it] ) {
1026 		switch ( deviceType_v[device_it] ) {
1027 		case SWITCH_OFF: case FUSE_OFF: case CAPACITOR: case DIODE: case BIPOLAR: {
1028 			break;
1029 		}
1030 		default: {
1031 			if ( theDeviceId == device_it ) continue;
1032 			if ( deviceType_v[device_it] != myDeviceType ) return UNKNOWN_DEVICE;  // different type
1033 			if ( myReturnDevice != UNKNOWN_DEVICE ) return UNKNOWN_DEVICE;  // more than one
1034 			myReturnDevice = device_it;
1035 		}
1036 		}
1037 	}
1038 	for ( deviceId_t device_it = firstSource_v[theNetId]; device_it != UNKNOWN_DEVICE; device_it = nextSource_v[device_it] ) {
1039 		switch ( deviceType_v[device_it] ) {
1040 		case SWITCH_OFF: case FUSE_OFF: case CAPACITOR: case DIODE: case BIPOLAR: {
1041 			break;
1042 		}
1043 		default: {
1044 			if ( theDeviceId == device_it ) continue;
1045 			if ( deviceType_v[device_it] != myDeviceType ) return UNKNOWN_DEVICE;  // different type
1046 			if ( myReturnDevice != UNKNOWN_DEVICE ) return UNKNOWN_DEVICE;  // more than one
1047 			myReturnDevice = device_it;
1048 		}
1049 		}
1050 	}
1051 	return(myReturnDevice);
1052 }
1053 
Cleanup()1054 void CCvcDb::Cleanup() {
1055 	if ( logFile.is_open() ) logFile.close();
1056 	if ( errorFile.is_open() ) errorFile.close();
1057 	if ( debugFile.is_open() ) debugFile.close();
1058 	RemoveLock();
1059 	try {
1060 		cvcParameters.cvcPowerPtrList.Clear(leakVoltagePtr_v, netVoltagePtr_v, netCount);  // defined power deleted here
1061 		if ( gDebug_cvc ) cout << "Cleared power pointer list" << endl;
1062 		int myDeleteCount = 0;
1063 		for ( netId_t net_it = 0; net_it < netCount; net_it++ ) {
1064 			CPower * myPower_p = netVoltagePtr_v[net_it].full;
1065 			if ( leakVoltageSet ) {
1066 				CPower * myLeakPower_p = leakVoltagePtr_v[net_it].full;
1067 				if ( leakVoltagePtr_v.size() > net_it && myLeakPower_p && myPower_p != myLeakPower_p ) {  // unique leak power deleted here
1068 					if ( myLeakPower_p->extraData ) {
1069 						if ( gDebug_cvc ) cout << "DEBUG: extra data at net " << net_it << endl;
1070 					}
1071 					delete myLeakPower_p;
1072 					myDeleteCount++;
1073 				}
1074 			}
1075 			if ( netVoltagePtr_v.size() > net_it && myPower_p ) {  // calculated power deleted here
1076 				if ( myPower_p->extraData ) {
1077 					if ( gDebug_cvc ) cout << "DEBUG: extra data at net " << net_it << endl;
1078 				}
1079 				delete myPower_p;
1080 				myDeleteCount++;
1081 			}
1082 		}
1083 		if ( gDebug_cvc ) cout << "DEBUG: Deleted " << myDeleteCount << " power objects" << endl;
1084 		cvcParameters.cvcExpectedLevelPtrList.Clear();
1085 		cvcParameters.cvcPowerMacroPtrMap.Clear();
1086 		CPower::powerDefinitionText.Clear();
1087 		cvcParameters.cvcModelListMap.Clear();
1088 	}
1089 	catch (...) {  // ignore errors freeing malloc memory
1090 		cout << "INFO: problem with memory cleanup" << endl;
1091 	}
1092 }
1093 
CountBulkConnections(netId_t theNetId)1094 deviceId_t CCvcDb::CountBulkConnections(netId_t theNetId) {
1095 	deviceId_t myDeviceCount = 0;
1096 	for (deviceId_t device_it = 0; device_it < deviceCount; device_it++) {
1097 		if ( bulkNet_v[device_it] == theNetId ) {
1098 			myDeviceCount++;
1099 		}
1100 	}
1101 	return myDeviceCount;
1102 }
1103 
IsAnalogNet(netId_t theNetId)1104 bool CCvcDb::IsAnalogNet(netId_t theNetId) {
1105 	assert(GetEquivalentNet(theNetId) == theNetId);
1106 	return(netStatus_v[theNetId][ANALOG]);
1107 	CVirtualNet myMinNet;
1108 	CVirtualNet myMaxNet;
1109 	myMinNet(minNet_v, theNetId);
1110 	myMaxNet(maxNet_v, theNetId);
1111 	CPower * myMinNet_p = netVoltagePtr_v[myMinNet.finalNetId].full;
1112 	CPower * myMaxNet_p = netVoltagePtr_v[myMaxNet.finalNetId].full;
1113 	bool myIsAnalogNet = ( myMinNet_p && myMinNet_p->type[ANALOG_BIT] ) || ( myMaxNet_p && myMaxNet_p->type[ANALOG_BIT] );
1114 	deviceId_t device_it = firstSource_v[theNetId];
1115 	while ( ! myIsAnalogNet && device_it != UNKNOWN_DEVICE ) {
1116 		if ( GetEquivalentNet(drainNet_v[device_it]) != theNetId ) {
1117 			switch( deviceType_v[device_it] ) {
1118 			case NMOS: case LDDN: case PMOS: case LDDP: {
1119 				if ( GetEquivalentNet(gateNet_v[device_it]) == theNetId) myIsAnalogNet = true;
1120 				break;
1121 			}
1122 			case RESISTOR: { myIsAnalogNet = true; break; }
1123 			default: break;
1124 			}
1125 		}
1126 		device_it = nextSource_v[device_it];
1127 	}
1128 	device_it = firstDrain_v[theNetId];
1129 	while ( ! myIsAnalogNet && device_it != UNKNOWN_DEVICE ) {
1130 		if ( GetEquivalentNet(sourceNet_v[device_it]) != theNetId ) {
1131 			switch( deviceType_v[device_it] ) {
1132 			case NMOS: case LDDN: case PMOS: case LDDP: {
1133 				if ( GetEquivalentNet(gateNet_v[device_it]) == theNetId) myIsAnalogNet = true;
1134 				break;
1135 			}
1136 			case RESISTOR: { myIsAnalogNet = true; break; }
1137 			default: break;
1138 			}
1139 		}
1140 		device_it = nextDrain_v[device_it];
1141 	}
1142 	return (myIsAnalogNet);
1143 }
1144 
IsAlwaysOff(CFullConnection & theConnections)1145 bool CCvcDb::IsAlwaysOff(CFullConnection& theConnections) {
1146 	/// True if gate is always off
1147 	theConnections.SetMinMaxLeakVoltagesAndFlags(this);
1148 	switch (deviceType_v[theConnections.deviceId]) {
1149 	case NMOS:
1150 	case LDDN: {
1151 		if ( theConnections.maxGateLeakVoltage == UNKNOWN_VOLTAGE ) return false;
1152 		if ( theConnections.minSourceLeakVoltage == UNKNOWN_VOLTAGE ) return false;
1153 		if ( theConnections.minDrainLeakVoltage == UNKNOWN_VOLTAGE ) return false;
1154 		return ( theConnections.maxGateLeakVoltage < min(theConnections.minSourceLeakVoltage, theConnections.minDrainLeakVoltage) + theConnections.device_p->model_p->Vth );
1155 		break;
1156 	}
1157 	case PMOS:
1158 	case LDDP: {
1159 		if ( theConnections.minGateLeakVoltage == UNKNOWN_VOLTAGE ) return false;
1160 		if ( theConnections.maxSourceLeakVoltage == UNKNOWN_VOLTAGE ) return false;
1161 		if ( theConnections.maxDrainLeakVoltage == UNKNOWN_VOLTAGE ) return false;
1162 		return ( theConnections.minGateLeakVoltage > max(theConnections.maxSourceLeakVoltage, theConnections.maxDrainLeakVoltage) + theConnections.device_p->model_p->Vth );
1163 		break;
1164 	}
1165 	case RESISTOR:
1166 	case SWITCH_ON:
1167 	case FUSE_ON:
1168 	case FUSE_OFF: {
1169 		return false;
1170 		break;
1171 	}
1172 	case CAPACITOR:
1173 	case SWITCH_OFF: {
1174 		return true;
1175 		break;
1176 	}
1177 	case DIODE: {
1178 		if ( theConnections.minDrainLeakVoltage == UNKNOWN_VOLTAGE ) return false;
1179 		if ( theConnections.maxSourceLeakVoltage == UNKNOWN_VOLTAGE ) return false;
1180 		return theConnections.maxSourceLeakVoltage > theConnections.minDrainLeakVoltage;
1181 		break;
1182 	}
1183 	case BIPOLAR: {
1184 		return false;
1185 		break;
1186 	}
1187 	default:
1188 		return false;
1189 	}
1190 }
1191 
IsOneConnectionNet(netId_t theNetId)1192 bool CCvcDb::IsOneConnectionNet(netId_t theNetId) {
1193 	// WARNING: Doesn't count bulk connections.
1194 	netId_t myNetId = GetEquivalentNet(theNetId);
1195 	deviceId_t myDevice;
1196 	if ( firstGate_v[myNetId] != UNKNOWN_DEVICE ) {
1197 		myDevice = firstGate_v[myNetId];
1198 	} else if ( firstSource_v[myNetId] != UNKNOWN_DEVICE ) {
1199 		myDevice = firstSource_v[myNetId];
1200 	} else if ( firstDrain_v[myNetId] != UNKNOWN_DEVICE ) {
1201 		myDevice = firstDrain_v[myNetId];
1202 	} else {
1203 		return true;  // nets not connected to any devices are also 'one connection', i.e. no leak.
1204 	}
1205 	if ( firstGate_v[myNetId] != UNKNOWN_DEVICE ) {
1206 		if ( firstGate_v[myNetId] != myDevice || nextGate_v[myDevice] != UNKNOWN_DEVICE ) return false;
1207 	}
1208 	if ( firstSource_v[myNetId] != UNKNOWN_DEVICE ) {
1209 		if ( firstSource_v[myNetId] != myDevice || nextSource_v[myDevice] != UNKNOWN_DEVICE ) return false;
1210 	}
1211 	if ( firstDrain_v[myNetId] != UNKNOWN_DEVICE ) {
1212 		if ( firstDrain_v[myNetId] != myDevice || nextDrain_v[myDevice] != UNKNOWN_DEVICE ) return false;
1213 	}
1214 	return true;
1215 }
1216 
SetDiodeConnections(pair<int,int> theDiodePair,CFullConnection & theConnections,CFullConnection & theDiodeConnections)1217 void CCvcDb::SetDiodeConnections(pair<int, int> theDiodePair, CFullConnection & theConnections, CFullConnection & theDiodeConnections) {
1218 	theDiodeConnections = theConnections;
1219 	int myAnnode, myCathode;
1220 	if (theConnections.device_p->model_p->baseType == "M" ) {
1221 		switch(theDiodePair.first){
1222 			case 1: { myAnnode = DRAIN; break; }
1223 			case 2: { myAnnode = GATE; break; }
1224 			case 3: { myAnnode = SOURCE; break; }
1225 			case 4: { myAnnode = BULK; break; }
1226 			default: {
1227 				theConnections.device_p->model_p->Print();
1228 				throw EInvalidTerminal("base type " + theConnections.device_p->model_p->baseType + " does not have terminal " + to_string<int>(theDiodePair.first));
1229 			}
1230 		}
1231 		switch(theDiodePair.second){
1232 			case 1: { myCathode = DRAIN; break; }
1233 			case 2: { myCathode = GATE; break; }
1234 			case 3: { myCathode = SOURCE; break; }
1235 			case 4: { myCathode = BULK; break; }
1236 			default: {
1237 				theConnections.device_p->model_p->Print();
1238 				throw EInvalidTerminal("base type " + theConnections.device_p->model_p->baseType + " does not have terminal " + to_string<int>(theDiodePair.first));
1239 			}
1240 		}
1241 	} else if (theConnections.device_p->model_p->baseType == "D"
1242 			|| theConnections.device_p->model_p->baseType == "R"
1243 			|| theConnections.device_p->model_p->baseType == "C") {
1244 		switch(theDiodePair.first){
1245 			case 1: { myAnnode = SOURCE; break; }
1246 			case 2: { myAnnode = DRAIN; break; }
1247 			case 3: { myAnnode = BULK; break; }
1248 			default: {
1249 				theConnections.device_p->model_p->Print();
1250 				throw EInvalidTerminal("base type " + theConnections.device_p->model_p->baseType + " does not have terminal " + to_string<int>(theDiodePair.first));
1251 			}
1252 		}
1253 		switch(theDiodePair.second){
1254 			case 1: { myCathode = SOURCE; break; }
1255 			case 2: { myCathode = DRAIN; break; }
1256 			case 3: { myCathode = BULK; break; }
1257 			default: {
1258 				theConnections.device_p->model_p->Print();
1259 				throw EInvalidTerminal("base type " + theConnections.device_p->model_p->baseType + " does not have terminal " + to_string<int>(theDiodePair.first));
1260 			}
1261 		}
1262 	} else if (theConnections.device_p->model_p->baseType == "Q" ) {
1263 		switch(theDiodePair.first){
1264 			case 1: { myAnnode = SOURCE; break; }
1265 			case 2: { myAnnode = GATE; break; }
1266 			case 3: { myAnnode = DRAIN; break; }
1267 			default: {
1268 				theConnections.device_p->model_p->Print();
1269 				throw EInvalidTerminal("base type " + theConnections.device_p->model_p->baseType + " does not have terminal " + to_string<int>(theDiodePair.first));
1270 			}
1271 		}
1272 		switch(theDiodePair.second){
1273 			case 1: { myCathode = SOURCE; break; }
1274 			case 2: { myCathode = GATE; break; }
1275 			case 3: { myCathode = DRAIN; break; }
1276 			default: {
1277 				theConnections.device_p->model_p->Print();
1278 				throw EInvalidTerminal("base type " + theConnections.device_p->model_p->baseType + " does not have terminal " + to_string<int>(theDiodePair.first));
1279 			}
1280 		}
1281 	} else {
1282 		theConnections.device_p->model_p->Print();
1283 		throw EUnknownModel();
1284 	}
1285 	switch(myAnnode) {
1286 		case SOURCE: {
1287 			theDiodeConnections.sourceId = theConnections.sourceId;
1288 			theDiodeConnections.masterMaxSourceNet = theConnections.masterMaxSourceNet;
1289 			theDiodeConnections.masterMinSourceNet = theConnections.masterMinSourceNet;
1290 			theDiodeConnections.masterSimSourceNet = theConnections.masterSimSourceNet;
1291 			theDiodeConnections.maxSourceLeakVoltage = theConnections.maxSourceLeakVoltage;
1292 			theDiodeConnections.maxSourcePower_p = theConnections.maxSourcePower_p;
1293 			theDiodeConnections.maxSourceVoltage = theConnections.maxSourceVoltage;
1294 			theDiodeConnections.minSourceLeakVoltage = theConnections.minSourceLeakVoltage;
1295 			theDiodeConnections.minSourcePower_p = theConnections.minSourcePower_p;
1296 			theDiodeConnections.minSourceVoltage = theConnections.minSourceVoltage;
1297 			theDiodeConnections.originalSourceId = theConnections.originalSourceId;
1298 			theDiodeConnections.simSourcePower_p = theConnections.simSourcePower_p;
1299 			theDiodeConnections.simSourceVoltage = theConnections.simSourceVoltage;
1300 			theDiodeConnections.validMaxSource = theConnections.validMaxSource;
1301 			theDiodeConnections.validMaxSourceLeak = theConnections.validMaxSourceLeak;
1302 			theDiodeConnections.validMinSource = theConnections.validMinSource;
1303 			theDiodeConnections.validMinSourceLeak = theConnections.validMinSourceLeak;
1304 			theDiodeConnections.validSimSource = theConnections.validSimSource;
1305 			break;
1306 		}
1307 		case GATE: {
1308 			theDiodeConnections.sourceId = theConnections.gateId;
1309 			theDiodeConnections.masterMaxSourceNet = theConnections.masterMaxGateNet;
1310 			theDiodeConnections.masterMinSourceNet = theConnections.masterMinGateNet;
1311 			theDiodeConnections.masterSimSourceNet = theConnections.masterSimGateNet;
1312 			theDiodeConnections.maxSourceLeakVoltage = theConnections.maxGateLeakVoltage;
1313 			theDiodeConnections.maxSourcePower_p = theConnections.maxGatePower_p;
1314 			theDiodeConnections.maxSourceVoltage = theConnections.maxGateVoltage;
1315 			theDiodeConnections.minSourceLeakVoltage = theConnections.minGateLeakVoltage;
1316 			theDiodeConnections.minSourcePower_p = theConnections.minGatePower_p;
1317 			theDiodeConnections.minSourceVoltage = theConnections.minGateVoltage;
1318 			theDiodeConnections.originalSourceId = theConnections.originalGateId;
1319 			theDiodeConnections.simSourcePower_p = theConnections.simGatePower_p;
1320 			theDiodeConnections.simSourceVoltage = theConnections.simGateVoltage;
1321 			theDiodeConnections.validMaxSource = theConnections.validMaxGate;
1322 			theDiodeConnections.validMaxSourceLeak = theConnections.validMaxGateLeak;
1323 			theDiodeConnections.validMinSource = theConnections.validMinGate;
1324 			theDiodeConnections.validMinSourceLeak = theConnections.validMinGateLeak;
1325 			theDiodeConnections.validSimSource = theConnections.validSimGate;
1326 			break;
1327 		}
1328 		case DRAIN: {
1329 			theDiodeConnections.sourceId = theConnections.drainId;
1330 			theDiodeConnections.masterMaxSourceNet = theConnections.masterMaxDrainNet;
1331 			theDiodeConnections.masterMinSourceNet = theConnections.masterMinDrainNet;
1332 			theDiodeConnections.masterSimSourceNet = theConnections.masterSimDrainNet;
1333 			theDiodeConnections.maxSourceLeakVoltage = theConnections.maxDrainLeakVoltage;
1334 			theDiodeConnections.maxSourcePower_p = theConnections.maxDrainPower_p;
1335 			theDiodeConnections.maxSourceVoltage = theConnections.maxDrainVoltage;
1336 			theDiodeConnections.minSourceLeakVoltage = theConnections.minDrainLeakVoltage;
1337 			theDiodeConnections.minSourcePower_p = theConnections.minDrainPower_p;
1338 			theDiodeConnections.minSourceVoltage = theConnections.minDrainVoltage;
1339 			theDiodeConnections.originalSourceId = theConnections.originalDrainId;
1340 			theDiodeConnections.simSourcePower_p = theConnections.simDrainPower_p;
1341 			theDiodeConnections.simSourceVoltage = theConnections.simDrainVoltage;
1342 			theDiodeConnections.validMaxSource = theConnections.validMaxDrain;
1343 			theDiodeConnections.validMaxSourceLeak = theConnections.validMaxDrainLeak;
1344 			theDiodeConnections.validMinSource = theConnections.validMinDrain;
1345 			theDiodeConnections.validMinSourceLeak = theConnections.validMinDrainLeak;
1346 			theDiodeConnections.validSimSource = theConnections.validSimDrain;
1347 			break;
1348 		}
1349 		case BULK: {
1350 			theDiodeConnections.sourceId = theConnections.bulkId;
1351 			theDiodeConnections.masterMaxSourceNet = theConnections.masterMaxBulkNet;
1352 			theDiodeConnections.masterMinSourceNet = theConnections.masterMinBulkNet;
1353 			theDiodeConnections.masterSimSourceNet = theConnections.masterSimBulkNet;
1354 			theDiodeConnections.maxSourceLeakVoltage = theConnections.maxBulkLeakVoltage;
1355 			theDiodeConnections.maxSourcePower_p = theConnections.maxBulkPower_p;
1356 			theDiodeConnections.maxSourceVoltage = theConnections.maxBulkVoltage;
1357 			theDiodeConnections.minSourceLeakVoltage = theConnections.minBulkLeakVoltage;
1358 			theDiodeConnections.minSourcePower_p = theConnections.minBulkPower_p;
1359 			theDiodeConnections.minSourceVoltage = theConnections.minBulkVoltage;
1360 			theDiodeConnections.originalSourceId = theConnections.originalBulkId;
1361 			theDiodeConnections.simSourcePower_p = theConnections.simBulkPower_p;
1362 			theDiodeConnections.simSourceVoltage = theConnections.simBulkVoltage;
1363 			theDiodeConnections.validMaxSource = theConnections.validMaxBulk;
1364 			theDiodeConnections.validMaxSourceLeak = theConnections.validMaxBulkLeak;
1365 			theDiodeConnections.validMinSource = theConnections.validMinBulk;
1366 			theDiodeConnections.validMinSourceLeak = theConnections.validMinBulkLeak;
1367 			theDiodeConnections.validSimSource = theConnections.validSimBulk;
1368 			break;
1369 		}
1370 		default: {
1371 			theConnections.device_p->model_p->Print();
1372 			throw EInvalidTerminal(to_string<int>(myAnnode) + " is not a valid terminal");
1373 		}
1374 	}
1375 	switch(myCathode) {
1376 		case SOURCE: {
1377 			theDiodeConnections.drainId = theConnections.sourceId;
1378 			theDiodeConnections.masterMaxDrainNet = theConnections.masterMaxSourceNet;
1379 			theDiodeConnections.masterMinDrainNet = theConnections.masterMinSourceNet;
1380 			theDiodeConnections.masterSimDrainNet = theConnections.masterSimSourceNet;
1381 			theDiodeConnections.maxDrainLeakVoltage = theConnections.maxSourceLeakVoltage;
1382 			theDiodeConnections.maxDrainPower_p = theConnections.maxSourcePower_p;
1383 			theDiodeConnections.maxDrainVoltage = theConnections.maxSourceVoltage;
1384 			theDiodeConnections.minDrainLeakVoltage = theConnections.minSourceLeakVoltage;
1385 			theDiodeConnections.minDrainPower_p = theConnections.minSourcePower_p;
1386 			theDiodeConnections.minDrainVoltage = theConnections.minSourceVoltage;
1387 			theDiodeConnections.originalDrainId = theConnections.originalSourceId;
1388 			theDiodeConnections.simDrainPower_p = theConnections.simSourcePower_p;
1389 			theDiodeConnections.simDrainVoltage = theConnections.simSourceVoltage;
1390 			theDiodeConnections.validMaxDrain = theConnections.validMaxSource;
1391 			theDiodeConnections.validMaxDrainLeak = theConnections.validMaxSourceLeak;
1392 			theDiodeConnections.validMinDrain = theConnections.validMinSource;
1393 			theDiodeConnections.validMinDrainLeak = theConnections.validMinSourceLeak;
1394 			theDiodeConnections.validSimDrain = theConnections.validSimSource;
1395 			break;
1396 		}
1397 		case GATE: {
1398 			theDiodeConnections.drainId = theConnections.gateId;
1399 			theDiodeConnections.masterMaxDrainNet = theConnections.masterMaxGateNet;
1400 			theDiodeConnections.masterMinDrainNet = theConnections.masterMinGateNet;
1401 			theDiodeConnections.masterSimDrainNet = theConnections.masterSimGateNet;
1402 			theDiodeConnections.maxDrainLeakVoltage = theConnections.maxGateLeakVoltage;
1403 			theDiodeConnections.maxDrainPower_p = theConnections.maxGatePower_p;
1404 			theDiodeConnections.maxDrainVoltage = theConnections.maxGateVoltage;
1405 			theDiodeConnections.minDrainLeakVoltage = theConnections.minGateLeakVoltage;
1406 			theDiodeConnections.minDrainPower_p = theConnections.minGatePower_p;
1407 			theDiodeConnections.minDrainVoltage = theConnections.minGateVoltage;
1408 			theDiodeConnections.originalDrainId = theConnections.originalGateId;
1409 			theDiodeConnections.simDrainPower_p = theConnections.simGatePower_p;
1410 			theDiodeConnections.simDrainVoltage = theConnections.simGateVoltage;
1411 			theDiodeConnections.validMaxDrain = theConnections.validMaxGate;
1412 			theDiodeConnections.validMaxDrainLeak = theConnections.validMaxGateLeak;
1413 			theDiodeConnections.validMinDrain = theConnections.validMinGate;
1414 			theDiodeConnections.validMinDrainLeak = theConnections.validMinGateLeak;
1415 			theDiodeConnections.validSimDrain = theConnections.validSimGate;
1416 			break;
1417 		}
1418 		case DRAIN: {
1419 			theDiodeConnections.drainId = theConnections.drainId;
1420 			theDiodeConnections.masterMaxDrainNet = theConnections.masterMaxDrainNet;
1421 			theDiodeConnections.masterMinDrainNet = theConnections.masterMinDrainNet;
1422 			theDiodeConnections.masterSimDrainNet = theConnections.masterSimDrainNet;
1423 			theDiodeConnections.maxDrainLeakVoltage = theConnections.maxDrainLeakVoltage;
1424 			theDiodeConnections.maxDrainPower_p = theConnections.maxDrainPower_p;
1425 			theDiodeConnections.maxDrainVoltage = theConnections.maxDrainVoltage;
1426 			theDiodeConnections.minDrainLeakVoltage = theConnections.minDrainLeakVoltage;
1427 			theDiodeConnections.minDrainPower_p = theConnections.minDrainPower_p;
1428 			theDiodeConnections.minDrainVoltage = theConnections.minDrainVoltage;
1429 			theDiodeConnections.originalDrainId = theConnections.originalDrainId;
1430 			theDiodeConnections.simDrainPower_p = theConnections.simDrainPower_p;
1431 			theDiodeConnections.simDrainVoltage = theConnections.simDrainVoltage;
1432 			theDiodeConnections.validMaxDrain = theConnections.validMaxDrain;
1433 			theDiodeConnections.validMaxDrainLeak = theConnections.validMaxDrainLeak;
1434 			theDiodeConnections.validMinDrain = theConnections.validMinDrain;
1435 			theDiodeConnections.validMinDrainLeak = theConnections.validMinDrainLeak;
1436 			theDiodeConnections.validSimDrain = theConnections.validSimDrain;
1437 			break;
1438 		}
1439 		case BULK: {
1440 			theDiodeConnections.drainId = theConnections.bulkId;
1441 			theDiodeConnections.masterMaxDrainNet = theConnections.masterMaxBulkNet;
1442 			theDiodeConnections.masterMinDrainNet = theConnections.masterMinBulkNet;
1443 			theDiodeConnections.masterSimDrainNet = theConnections.masterSimBulkNet;
1444 			theDiodeConnections.maxDrainLeakVoltage = theConnections.maxBulkLeakVoltage;
1445 			theDiodeConnections.maxDrainPower_p = theConnections.maxBulkPower_p;
1446 			theDiodeConnections.maxDrainVoltage = theConnections.maxBulkVoltage;
1447 			theDiodeConnections.minDrainLeakVoltage = theConnections.minBulkLeakVoltage;
1448 			theDiodeConnections.minDrainPower_p = theConnections.minBulkPower_p;
1449 			theDiodeConnections.minDrainVoltage = theConnections.minBulkVoltage;
1450 			theDiodeConnections.originalDrainId = theConnections.originalBulkId;
1451 			theDiodeConnections.simDrainPower_p = theConnections.simBulkPower_p;
1452 			theDiodeConnections.simDrainVoltage = theConnections.simBulkVoltage;
1453 			theDiodeConnections.validMaxDrain = theConnections.validMaxBulk;
1454 			theDiodeConnections.validMaxDrainLeak = theConnections.validMaxBulkLeak;
1455 			theDiodeConnections.validMinDrain = theConnections.validMinBulk;
1456 			theDiodeConnections.validMinDrainLeak = theConnections.validMinBulkLeak;
1457 			theDiodeConnections.validSimDrain = theConnections.validSimBulk;
1458 			break;
1459 		}
1460 		default: {
1461 			theConnections.device_p->model_p->Print();
1462 			throw EInvalidTerminal(to_string<int>(myAnnode) + " is not a valid terminal");
1463 		}
1464 	}
1465 }
1466 
CalculateMFactor(instanceId_t theInstanceId)1467 int CCvcDb::CalculateMFactor(instanceId_t theInstanceId) {
1468 	if (  instancePtr_v[theInstanceId]->IsParallelInstance() ) return 0;  // parallel/empty instances
1469 	int myMFactor = 1;
1470 	instanceId_t myInstanceId = theInstanceId;
1471 	if ( instancePtr_v[myInstanceId]->parallelInstanceCount > 1 ) {
1472 		myMFactor = instancePtr_v[myInstanceId]->parallelInstanceCount;
1473 	}
1474 	return myMFactor;
1475 }
1476 
1477 
GetAttachedDevice(netId_t theNetId,modelType_t theType,terminal_t theTerminal)1478 deviceId_t CCvcDb::GetAttachedDevice(netId_t theNetId, modelType_t theType, terminal_t theTerminal) {
1479 	/// Return the first non-shorted device of type theType with terminal theTerminal connected to theNetId
1480 	assert(GetEquivalentNet(theNetId) == theNetId);
1481 
1482 	deviceId_t device_it;
1483 	if ( theTerminal & GATE ) {
1484 		device_it = firstGate_v[theNetId];
1485 		while ( device_it != UNKNOWN_DEVICE ) {
1486 			if ( sourceNet_v[device_it] != drainNet_v[device_it] ) {
1487 				if ( theType == NMOS && IsNmos_(deviceType_v[device_it]) ) return device_it;
1488 
1489 				if ( theType == PMOS && IsPmos_(deviceType_v[device_it]) ) return device_it;
1490 
1491 				if ( theType == deviceType_v[device_it] ) return device_it;
1492 
1493 			}
1494 			device_it = nextGate_v[device_it];
1495 		}
1496 	}
1497 	if ( theTerminal & SOURCE ) {
1498 		device_it = firstSource_v[theNetId];
1499 		while ( device_it != UNKNOWN_DEVICE ) {
1500 			if ( sourceNet_v[device_it] != drainNet_v[device_it] ) {
1501 				if ( theType == NMOS && IsNmos_(deviceType_v[device_it]) ) return device_it;
1502 
1503 				if ( theType == PMOS && IsPmos_(deviceType_v[device_it]) ) return device_it;
1504 
1505 				if ( theType == deviceType_v[device_it] ) return device_it;
1506 
1507 			}
1508 			device_it = nextSource_v[device_it];
1509 		}
1510 	}
1511 	if ( theTerminal & DRAIN ) {
1512 		device_it = firstDrain_v[theNetId];
1513 		while ( device_it != UNKNOWN_DEVICE ) {
1514 			if ( sourceNet_v[device_it] != drainNet_v[device_it] ) {
1515 				if ( theType == NMOS && IsNmos_(deviceType_v[device_it]) ) return device_it;
1516 
1517 				if ( theType == PMOS && IsPmos_(deviceType_v[device_it]) ) return device_it;
1518 
1519 				if ( theType == deviceType_v[device_it] ) return device_it;
1520 
1521 			}
1522 			device_it = nextDrain_v[device_it];
1523 		}
1524 	}
1525 	return (UNKNOWN_DEVICE);
1526 }
1527 
FindInverterDevice(netId_t theInputNet,netId_t theOutputNet,modelType_t theType)1528 deviceId_t CCvcDb::FindInverterDevice(netId_t theInputNet, netId_t theOutputNet, modelType_t theType) {
1529 	/// Return the first device of theType with input theInputNet and output theOutputNet
1530 	///
1531 	/// Note: Will not find any device if inverter contains both nmos/pmos clamps
1532 	unordered_set<deviceId_t> myDeviceList;
1533 	deviceId_t device_it = firstSource_v[theOutputNet];
1534 	while ( device_it != UNKNOWN_DEVICE ) {
1535 		if ( sourceNet_v[device_it] != drainNet_v[device_it] ) {
1536 			if ( theType == NMOS && IsNmos_(deviceType_v[device_it] ) ) {
1537 				myDeviceList.insert(device_it);
1538 			} if ( theType == PMOS && IsPmos_(deviceType_v[device_it] ) ) {
1539 				myDeviceList.insert(device_it);
1540 			}
1541 		}
1542 		device_it = nextSource_v[device_it];
1543 	}
1544 	device_it = firstDrain_v[theOutputNet];
1545 	while ( device_it != UNKNOWN_DEVICE ) {
1546 		if ( sourceNet_v[device_it] != drainNet_v[device_it] ) {
1547 			if ( theType == NMOS && IsNmos_(deviceType_v[device_it] ) ) {
1548 				myDeviceList.insert(device_it);
1549 			} if ( theType == PMOS && IsPmos_(deviceType_v[device_it] ) ) {
1550 				myDeviceList.insert(device_it);
1551 			}
1552 		}
1553 		device_it = nextDrain_v[device_it];
1554 	}
1555 	device_it = firstGate_v[theInputNet];
1556 	while ( device_it != UNKNOWN_DEVICE ) {
1557 		if ( myDeviceList.count(device_it) > 0 ) return device_it;
1558 
1559 		device_it = nextGate_v[device_it];
1560 	}
1561 	return(UNKNOWN_DEVICE);
1562 }
1563 
FindUniqueMosInputs(netId_t theOutputNet,netId_t theGroundNet,netId_t thePowerNet,CDeviceIdVector & theFirst_v,CDeviceIdVector & theNext_v,CNetIdVector & theSourceNet_v,CNetIdVector & theDrainNet_v,netId_t & theNmosInput,netId_t & thePmosInput)1564 returnCode_t CCvcDb::FindUniqueMosInputs(netId_t theOutputNet, netId_t theGroundNet, netId_t thePowerNet,
1565 		CDeviceIdVector &theFirst_v, CDeviceIdVector &theNext_v, CNetIdVector &theSourceNet_v, CNetIdVector &theDrainNet_v,
1566 		netId_t &theNmosInput, netId_t &thePmosInput) {
1567 	/// Return the mos gates for devices with source connected to theOutputNet
1568 	///
1569 	/// Modifies theNmosInput, thePmosInput
1570 	CPower * myGround_p = netVoltagePtr_v[theGroundNet].full;
1571 	CPower * myPower_p = netVoltagePtr_v[thePowerNet].full;
1572 	for ( deviceId_t device_it = theFirst_v[theOutputNet]; device_it != UNKNOWN_DEVICE; device_it = theNext_v[device_it] ) {
1573 		if ( theSourceNet_v[device_it] == theDrainNet_v[device_it] ) continue;  // ignore inactive devices
1574 
1575 		if ( IsNmos_(deviceType_v[device_it]) ) {
1576 			if ( theDrainNet_v[device_it] == theGroundNet ) {  // expected ground
1577 				if ( theNmosInput == UNKNOWN_NET ) {
1578 					theNmosInput = gateNet_v[device_it];
1579 				} else if ( theNmosInput != gateNet_v[device_it] ) return(FAIL);  // multiple NMOS inputs yield unknown result
1580 
1581 			} else if ( IsOnGate(device_it, myGround_p) ) {  // series gate on
1582 				deviceId_t myNextNmos = GetNextInSeries(device_it, theDrainNet_v[device_it]);
1583 				if ( myNextNmos == UNKNOWN_DEVICE ) return(FAIL);  // not series
1584 
1585 				if ( OppositeNet(myNextNmos, theDrainNet_v[device_it]) == theGroundNet ) {
1586 					if ( theNmosInput == UNKNOWN_NET ) {
1587 						theNmosInput = gateNet_v[myNextNmos];
1588 					} else if ( theNmosInput != gateNet_v[myNextNmos] ) return(FAIL);  // multiple NMOS inputs yield unknown result
1589 
1590 				} else return(FAIL);  // more than 2 in series
1591 
1592 			} else return(FAIL);  // no connection to ground detected
1593 
1594 		}
1595 		if ( IsPmos_(deviceType_v[device_it]) ) {
1596 			if ( theDrainNet_v[device_it] == thePowerNet ) {  // expected power
1597 				if ( thePmosInput == UNKNOWN_NET ) {
1598 					thePmosInput = gateNet_v[device_it];
1599 				} else if ( thePmosInput != gateNet_v[device_it] ) return(FAIL);  // multiple PMOS inputs yield unknown result
1600 
1601 			} else if ( IsOnGate(device_it, myPower_p) ) {  // series gate on
1602 				deviceId_t myNextPmos = GetNextInSeries(device_it, theDrainNet_v[device_it]);
1603 				if ( myNextPmos == UNKNOWN_DEVICE ) return(FAIL);  // not series
1604 
1605 				if ( OppositeNet(myNextPmos, theDrainNet_v[device_it]) == thePowerNet ) {
1606 					if ( thePmosInput == UNKNOWN_NET ) {
1607 						thePmosInput = gateNet_v[myNextPmos];
1608 					} else if ( thePmosInput != gateNet_v[myNextPmos] ) return(FAIL);  // multiple PMOS inputs yield unknown result
1609 
1610 				} else return(FAIL);  // more than 2 in series
1611 
1612 			} else return(FAIL);  // no connection to power detected
1613 
1614 		}
1615 	}
1616 	return(OK);
1617 }
1618 
FindInverterInput(netId_t theOutputNet)1619 netId_t CCvcDb::FindInverterInput(netId_t theOutputNet) {
1620 	/// Find the input of inverter with output theOutputNet
1621 	CVirtualNet myMinOutput;
1622 	CVirtualNet myMaxOutput;
1623 	myMinOutput(minNet_v, theOutputNet);
1624 	myMaxOutput(maxNet_v, theOutputNet);
1625 	netId_t myGroundNet = myMinOutput.finalNetId;
1626 	netId_t myPowerNet = myMaxOutput.finalNetId;
1627 	CPower * myGround_p = netVoltagePtr_v[myGroundNet].full;
1628 	CPower * myPower_p = netVoltagePtr_v[myPowerNet].full;
1629 	netId_t myNmosInput = UNKNOWN_NET;
1630 	netId_t myPmosInput = UNKNOWN_NET;
1631 	if ( ! IsPower_(myGround_p) || ! IsPower_(myPower_p) ) {
1632 		logFile << "DEBUG: missing power for inverter at " << NetName(theOutputNet, true) << endl;
1633 		return(UNKNOWN_NET);
1634 
1635 	}
1636 	returnCode_t mySourceCheck = FindUniqueMosInputs(theOutputNet, myGroundNet, myPowerNet, firstSource_v, nextSource_v, sourceNet_v, drainNet_v,
1637 			myNmosInput, myPmosInput);
1638 	returnCode_t myDrainCheck = FindUniqueMosInputs(theOutputNet, myGroundNet, myPowerNet, firstDrain_v, nextDrain_v, drainNet_v, sourceNet_v,
1639 			myNmosInput, myPmosInput);
1640 	return( ( mySourceCheck == OK && myDrainCheck == OK
1641 			&& myNmosInput != UNKNOWN_NET && myNmosInput == myPmosInput ) ? myNmosInput : UNKNOWN_NET);
1642 }
1643 
IsOnGate(deviceId_t theDevice,CPower * thePower_p)1644 bool CCvcDb::IsOnGate(deviceId_t theDevice, CPower * thePower_p) {
1645 	// Return true if gate is always on
1646 	CPower * myGatePower_p = netVoltagePtr_v[gateNet_v[theDevice]].full;
1647 	if ( ! IsPower_(myGatePower_p) ) return false;  // gate is not power
1648 
1649 	if ( IsNmos_(deviceType_v[theDevice]) ) return( myGatePower_p->minVoltage > thePower_p->minVoltage );
1650 
1651 	if ( IsPmos_(deviceType_v[theDevice]) ) return( myGatePower_p->maxVoltage < thePower_p->maxVoltage );
1652 
1653 	assert(false);  // error if called with device that is not NMOS or PMOS
1654 }
1655 
OppositeNet(deviceId_t theDevice,netId_t theNet)1656 netId_t CCvcDb::OppositeNet(deviceId_t theDevice, netId_t theNet) {
1657 	// return the opposite net of a device
1658 	assert((sourceNet_v[theDevice] == theNet) || (drainNet_v[theDevice] == theNet));
1659 
1660 	return((sourceNet_v[theDevice] == theNet) ? drainNet_v[theDevice] : sourceNet_v[theDevice]);
1661 }
1662 
GetNextInSeries(deviceId_t theDevice,netId_t theNet)1663 deviceId_t CCvcDb::GetNextInSeries(deviceId_t theDevice, netId_t theNet) {
1664 	// Return the next device in series
1665 	deviceId_t myNextDevice = UNKNOWN_DEVICE;
1666 	for ( deviceId_t device_it = firstSource_v[theNet]; device_it != UNKNOWN_DEVICE; device_it = nextSource_v[device_it] ) {
1667 		if ( sourceNet_v[device_it] != drainNet_v[device_it] ) continue;  // ignore inactive devices
1668 
1669 		if ( device_it == theDevice ) continue;  // looking for device connected to this one
1670 
1671 		if ( myNextDevice != UNKNOWN_DEVICE ) return(UNKNOWN_DEVICE);  // not in series, return error
1672 
1673 		myNextDevice = device_it;
1674 	}
1675 	for ( deviceId_t device_it = firstDrain_v[theNet]; device_it != UNKNOWN_DEVICE; device_it = nextDrain_v[device_it] ) {
1676 		if ( sourceNet_v[device_it] != drainNet_v[device_it] ) continue;  // ignore inactive devices
1677 
1678 		if ( device_it == theDevice ) continue;  // looking for device connected to this one
1679 
1680 		if ( myNextDevice != UNKNOWN_DEVICE ) return(UNKNOWN_DEVICE);  // not in series, return error
1681 
1682 		myNextDevice = device_it;
1683 	}
1684 	if ( myNextDevice != UNKNOWN_DEVICE ) {
1685 		if ( deviceType_v[theDevice] != deviceType_v[myNextDevice] ) {  // should be the same type
1686 			if ( IsNmos_(deviceType_v[theDevice]) && IsNmos_(deviceType_v[myNextDevice]) ) {  // type mismatch ok if both nmos
1687 				;
1688 			} else if ( IsPmos_(deviceType_v[theDevice]) && IsPmos_(deviceType_v[myNextDevice]) ) {  // type mismatch ok if both pmos
1689 				;
1690 			} else return(UNKNOWN_DEVICE);
1691 
1692 		}
1693 	}
1694 	return(myNextDevice);
1695 }
1696 
IsInstanceNet(netId_t theNetId,instanceId_t theInstance)1697 bool CCvcDb::IsInstanceNet(netId_t theNetId, instanceId_t theInstance) {
1698 	// return true if theNet is used in theInstance
1699 	if ( theInstance == UNKNOWN_INSTANCE || theNetId == UNKNOWN_NET ) return false;  // bad instance or net
1700 	instanceId_t myParent = netParent_v[theNetId];
1701 	if ( IsSubcircuitOf(myParent, theInstance) ) return true;
1702 	CInstance * myInstance_p = instancePtr_v[theInstance];
1703 	CCircuit * myCircuit_p = myInstance_p->master_p;
1704 	for ( netId_t port_it = 0; port_it < myCircuit_p->portCount; port_it++ ) {
1705 		if ( theNetId == GetEquivalentNet(myInstance_p->localToGlobalNetId_v[port_it]) ) return true;
1706 	}
1707 	return false;
1708 }
1709 
FindNetInstance(netId_t theNetId,instanceId_t theInstance)1710 instanceId_t CCvcDb::FindNetInstance(netId_t theNetId, instanceId_t theInstance) {
1711 	// return highest instance using net in theInstance
1712 	if ( theInstance == UNKNOWN_INSTANCE || theNetId == UNKNOWN_NET ) return UNKNOWN_INSTANCE;  // bad instance or net
1713 	instanceId_t myParent = netParent_v[theNetId];
1714 	if ( IsSubcircuitOf(myParent, theInstance) ) return myParent;
1715 	CInstance * myInstance_p = instancePtr_v[theInstance];
1716 	CCircuit * myCircuit_p = myInstance_p->master_p;
1717 	for ( netId_t port_it = 0; port_it < myCircuit_p->portCount; port_it++ ) {
1718 		if ( theNetId == GetEquivalentNet(myInstance_p->localToGlobalNetId_v[port_it]) ) return theInstance;
1719 	}
1720 	return UNKNOWN_INSTANCE;
1721 }
1722 
IsInternalNet(netId_t theNetId,instanceId_t theInstance)1723 bool CCvcDb::IsInternalNet(netId_t theNetId, instanceId_t theInstance) {
1724 	// true if net is internal to instance
1725 	if ( theInstance == UNKNOWN_INSTANCE || theNetId == UNKNOWN_NET ) return false;  // bad instance or net
1726 	instanceId_t myParent = netParent_v[theNetId];
1727 	if ( myParent == 0 && theInstance == 0 ) return false;  // top level nets are not internal
1728 	return( IsSubcircuitOf(myParent, theInstance) );
1729 }
1730 
GetLocalNetName(instanceId_t theInstance,netId_t theNet)1731 text_t CCvcDb::GetLocalNetName(instanceId_t theInstance, netId_t theNet) {
1732 	// requires 2 reverse searches
1733 	CInstance * myInstance_p = instancePtr_v[theInstance];
1734 	CCircuit * myMaster_p = myInstance_p->master_p;
1735 	netId_t net_it = 0;
1736 	while ( net_it < myInstance_p->localToGlobalNetId_v.size() && myInstance_p->localToGlobalNetId_v[net_it] != theNet ) {
1737 		net_it++;
1738 	}
1739 	if ( net_it >= myInstance_p->localToGlobalNetId_v.size() ) return(NULL);
1740 	for( auto signalMap_pit = myMaster_p->localSignalIdMap.begin(); signalMap_pit != myMaster_p->localSignalIdMap.end(); signalMap_pit++ ) {
1741 		if ( signalMap_pit->second == net_it ) return signalMap_pit->first;
1742 	}
1743 	return(NULL);
1744 }
1745