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