1 /*
2  * CCvcDb_error.cc
3  *
4  * Copyright 2014-2020 D. Mitch Bailey  cvc at shuharisystem dot com
5  *
6  * This file is part of cvc.
7  *
8  * cvc is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * cvc is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with cvc.  If not, see <http://www.gnu.org/licenses/>.
20  *
21  * You can download cvc from https://github.com/d-m-bailey/cvc.git
22  */
23 
24 #include "CCvcDb.hh"
25 
26 #include "CCircuit.hh"
27 #include "CConnectionCount.hh"
28 #include "CModel.hh"
29 #include "CDevice.hh"
30 #include "CPower.hh"
31 #include "CInstance.hh"
32 #include "CEventQueue.hh"
33 #include "CVirtualNet.hh"
34 #include <stdio.h>
35 
PrintFuseError(netId_t theTargetNetId,CConnection & theConnections)36 void CCvcDb::PrintFuseError(netId_t theTargetNetId, CConnection & theConnections) {
37 	if ( IncrementDeviceError(theConnections.deviceId, FUSE_ERROR) < cvcParameters.cvcCircuitErrorLimit || cvcParameters.cvcCircuitErrorLimit == 0 ) {
38 		CFullConnection myFullConnections;
39 		CInstance * myInstance_p = instancePtr_v[deviceParent_v[theConnections.deviceId]];
40 		CCircuit * myParent_p = myInstance_p->master_p;
41 		CDevice * myDevice_p = myParent_p->devicePtr_v[theConnections.deviceId - myInstance_p->firstDeviceId];
42 		MapDeviceNets(myInstance_p, myDevice_p, myFullConnections);
43 		errorFile << "! Power/Ground path through fuse at " << NetName(theTargetNetId, PRINT_CIRCUIT_ON, PRINT_HIERARCHY_OFF);
44 		if ( deviceType_v[theConnections.deviceId] == FUSE_ON ) {
45 			errorFile << "; possible floating when cut" << endl;
46 		} else if ( deviceType_v[theConnections.deviceId] == FUSE_OFF ) {
47 			errorFile << "; possibly unusable" << endl;
48 		} else {
49 			errorFile << "; unknown fuse type" << endl;
50 		}
51 		PrintDeviceWithAllConnections(deviceParent_v[theConnections.deviceId], myFullConnections, errorFile);
52 		errorFile << endl;
53 	}
54 }
55 
PrintMinVoltageConflict(netId_t theTargetNetId,CConnection & theMinConnections,voltage_t theExpectedVoltage,float theLeakCurrent)56 void CCvcDb::PrintMinVoltageConflict(netId_t theTargetNetId, CConnection & theMinConnections, voltage_t theExpectedVoltage, float theLeakCurrent) {
57 	if ( IncrementDeviceError(theMinConnections.deviceId, MIN_VOLTAGE_CONFLICT) < cvcParameters.cvcCircuitErrorLimit || cvcParameters.cvcCircuitErrorLimit == 0 ) {
58 		CFullConnection myFullConnections;
59 		CInstance * myInstance_p = instancePtr_v[deviceParent_v[theMinConnections.deviceId]];
60 		CCircuit * myParent_p = myInstance_p->master_p;
61 		CDevice * myDevice_p = myParent_p->devicePtr_v[theMinConnections.deviceId - myInstance_p->firstDeviceId];
62 		MapDeviceNets(myInstance_p, myDevice_p, myFullConnections);
63 		errorFile << "! Min voltage already set for " << NetName(theTargetNetId, PRINT_CIRCUIT_ON, PRINT_HIERARCHY_OFF);
64 		errorFile << " at mos diode: expected/found " << theExpectedVoltage << "/" << theMinConnections.gateVoltage;
65 		errorFile << " estimated current " << AddSiSuffix(theLeakCurrent) << "A" << endl;
66 		PrintDeviceWithAllConnections(deviceParent_v[theMinConnections.deviceId], myFullConnections, errorFile);
67 		errorFile << endl;
68 	}
69 }
70 
PrintMaxVoltageConflict(netId_t theTargetNetId,CConnection & theMaxConnections,voltage_t theExpectedVoltage,float theLeakCurrent)71 void CCvcDb::PrintMaxVoltageConflict(netId_t theTargetNetId, CConnection & theMaxConnections, voltage_t theExpectedVoltage, float theLeakCurrent) {
72 	if ( IncrementDeviceError(theMaxConnections.deviceId, MAX_VOLTAGE_CONFLICT) < cvcParameters.cvcCircuitErrorLimit || cvcParameters.cvcCircuitErrorLimit == 0 ) {
73 		CFullConnection myFullConnections;
74 		CInstance * myInstance_p = instancePtr_v[deviceParent_v[theMaxConnections.deviceId]];
75 		CCircuit * myParent_p = myInstance_p->master_p;
76 		CDevice * myDevice_p = myParent_p->devicePtr_v[theMaxConnections.deviceId - myInstance_p->firstDeviceId];
77 		MapDeviceNets(myInstance_p, myDevice_p, myFullConnections);
78 		errorFile << "! Max voltage already set for " << NetName(theTargetNetId, PRINT_CIRCUIT_ON, PRINT_HIERARCHY_OFF);
79 		errorFile << " at mos diode: expected/found " << theExpectedVoltage << "/" << theMaxConnections.gateVoltage;
80 		errorFile << " estimated current " << AddSiSuffix(theLeakCurrent) << "A" << endl;
81 		PrintDeviceWithAllConnections(deviceParent_v[theMaxConnections.deviceId], myFullConnections, errorFile);
82 		errorFile << endl;
83 	}
84 }
85 
FindVbgError(ogzstream & theErrorFile,voltage_t theParameter,CFullConnection & theConnections,instanceId_t theInstanceId,string theDisplayParameter)86 void CCvcDb::FindVbgError(ogzstream & theErrorFile, voltage_t theParameter, CFullConnection & theConnections, instanceId_t theInstanceId, string theDisplayParameter) {
87 	theParameter += cvcParameters.cvcOvervoltageErrorThreshold;
88 	if ( ( theConnections.validMaxGate && theConnections.validMinBulk
89 				&& abs(theConnections.maxGateVoltage - theConnections.minBulkVoltage) > theParameter )
90 			|| ( theConnections.validMinGate && theConnections.validMaxBulk
91 				&& abs(theConnections.minGateVoltage - theConnections.maxBulkVoltage) > theParameter ) ) {
92 		PrintOverVoltageError(theErrorFile, theConnections, OVERVOLTAGE_VBG, "Overvoltage Error:Gate vs Bulk:" + theDisplayParameter, theInstanceId);
93 	} else if ( ! cvcParameters.cvcLeakOvervoltage ) {
94 		return ;
95 	} else if ( ( theConnections.validMaxGateLeak && theConnections.validMinBulkLeak
96 				&& abs(theConnections.maxGateLeakVoltage - theConnections.minBulkLeakVoltage) > theParameter )
97 			|| ( theConnections.validMinGateLeak && theConnections.validMaxBulkLeak
98 				&& abs(theConnections.minGateLeakVoltage - theConnections.maxBulkLeakVoltage) > theParameter )
99 			|| ( theConnections.validMaxGateLeak && ! theConnections.validMinBulkLeak
100 				&& abs(theConnections.maxGateLeakVoltage) > theParameter )
101 			|| ( theConnections.validMinGateLeak && ! theConnections.validMaxBulkLeak
102 				&& abs(theConnections.minGateLeakVoltage) > theParameter )
103 			|| ( ! theConnections.validMaxGateLeak && theConnections.validMinBulkLeak
104 				&& abs(theConnections.minBulkLeakVoltage) > theParameter )
105 			|| ( ! theConnections.validMinGate && theConnections.validMaxBulkLeak
106 				&& abs(theConnections.maxBulkLeakVoltage) > theParameter ) ) {
107 		PrintOverVoltageError(theErrorFile, theConnections, OVERVOLTAGE_VBG, "Overvoltage Error:Gate vs Bulk: (logic ok)" + theDisplayParameter, theInstanceId);
108 	}
109 }
110 
FindVbsError(ogzstream & theErrorFile,voltage_t theParameter,CFullConnection & theConnections,instanceId_t theInstanceId,string theDisplayParameter)111 void CCvcDb::FindVbsError(ogzstream & theErrorFile, voltage_t theParameter, CFullConnection & theConnections, instanceId_t theInstanceId, string theDisplayParameter) {
112 	theParameter += cvcParameters.cvcOvervoltageErrorThreshold;
113 	if ( ( theConnections.validMaxSource && theConnections.validMinBulk
114 				&& abs(theConnections.maxSourceVoltage - theConnections.minBulkVoltage) > theParameter )
115 			|| ( theConnections.validMinSource && theConnections.validMaxBulk
116 				&& abs(theConnections.minSourceVoltage - theConnections.maxBulkVoltage) > theParameter )
117 			|| ( theConnections.validMaxDrain && theConnections.validMinBulk
118 				&& abs(theConnections.maxDrainVoltage - theConnections.minBulkVoltage) > theParameter )
119 			|| ( theConnections.validMinDrain && theConnections.validMaxBulk
120 				&& abs(theConnections.minDrainVoltage - theConnections.maxBulkVoltage) > theParameter ) ) {
121 		PrintOverVoltageError(theErrorFile, theConnections, OVERVOLTAGE_VBS, "Overvoltage Error:Source/Drain vs Bulk:" + theDisplayParameter, theInstanceId);
122 	} else if ( ! cvcParameters.cvcLeakOvervoltage ) {
123 		return ;
124 	} else if ( ( theConnections.validMaxSourceLeak && theConnections.validMinBulkLeak
125 				&& abs(theConnections.maxSourceLeakVoltage - theConnections.minBulkLeakVoltage) > theParameter )
126 			|| ( theConnections.validMinSourceLeak && theConnections.validMaxBulkLeak
127 				&& abs(theConnections.minSourceLeakVoltage - theConnections.maxBulkLeakVoltage) > theParameter )
128 			|| ( theConnections.validMaxDrainLeak && theConnections.validMinBulkLeak
129 				&& abs(theConnections.maxDrainLeakVoltage - theConnections.minBulkLeakVoltage) > theParameter )
130 			|| ( theConnections.validMinDrainLeak && theConnections.validMaxBulkLeak
131 				&& abs(theConnections.minDrainLeakVoltage - theConnections.maxBulkLeakVoltage) > theParameter )
132 			|| ( theConnections.validMinBulkLeak && ! theConnections.validMaxSourceLeak && ! theConnections.validMaxDrainLeak
133 				&& abs(theConnections.minBulkLeakVoltage) > theParameter )
134 			|| ( theConnections.validMaxBulkLeak && ! theConnections.validMinSourceLeak && ! theConnections.validMinDrainLeak
135 				&& abs(theConnections.maxBulkLeakVoltage) > theParameter )
136 			|| ( theConnections.validMinSourceLeak && ! theConnections.validMaxBulkLeak
137 				&& abs(theConnections.minSourceLeakVoltage) > theParameter )
138 			|| ( theConnections.validMaxSourceLeak && ! theConnections.validMinBulkLeak
139 				&& abs(theConnections.maxSourceLeakVoltage) > theParameter )
140 			|| ( theConnections.validMinDrainLeak && ! theConnections.validMaxBulkLeak
141 				&& abs(theConnections.minDrainLeakVoltage) > theParameter )
142 			|| ( theConnections.validMaxDrainLeak && ! theConnections.validMinBulkLeak
143 				&& abs(theConnections.maxDrainLeakVoltage) > theParameter ) ) {
144 		PrintOverVoltageError(theErrorFile, theConnections, OVERVOLTAGE_VBS, "Overvoltage Error:Source/Drain vs Bulk: (logic ok)" + theDisplayParameter, theInstanceId);
145 	}
146 }
147 
FindVdsError(ogzstream & theErrorFile,voltage_t theParameter,CFullConnection & theConnections,instanceId_t theInstanceId,string theDisplayParameter)148 void CCvcDb::FindVdsError(ogzstream & theErrorFile, voltage_t theParameter, CFullConnection & theConnections, instanceId_t theInstanceId, string theDisplayParameter) {
149 	theParameter += cvcParameters.cvcOvervoltageErrorThreshold;
150 	if ( ( theConnections.validMinSource && theConnections.validMaxDrain
151 				&& abs(theConnections.minSourceVoltage - theConnections.maxDrainVoltage) > theParameter )
152 			|| ( theConnections.validMaxSource && theConnections.validMinDrain
153 				&& abs(theConnections.maxSourceVoltage - theConnections.minDrainVoltage) > theParameter ) ) {
154 		if ( theConnections.IsPumpCapacitor() &&
155 				abs(theConnections.minSourceVoltage - theConnections.minDrainVoltage) <= theParameter &&
156 				abs(theConnections.maxSourceVoltage - theConnections.maxDrainVoltage) <= theParameter ) {
157 			; // for pumping capacitors only check min-min/max-max differences
158 		} else {
159 			PrintOverVoltageError(theErrorFile, theConnections, OVERVOLTAGE_VDS, "Overvoltage Error:Source vs Drain:" + theDisplayParameter, theInstanceId);
160 		}
161 	} else if ( ! cvcParameters.cvcLeakOvervoltage ) {
162 		return ;
163 	} else if ( ( theConnections.validMinSourceLeak && theConnections.validMaxDrainLeak
164 				&& abs(theConnections.minSourceLeakVoltage - theConnections.maxDrainLeakVoltage) > theParameter )
165 			|| ( theConnections.validMaxSourceLeak && theConnections.validMinDrainLeak
166 				&& abs(theConnections.maxSourceLeakVoltage - theConnections.minDrainLeakVoltage) > theParameter )
167 			|| ( theConnections.validMinSourceLeak && ! theConnections.validMaxDrainLeak
168 				&& abs(theConnections.minSourceLeakVoltage) > theParameter )
169 			|| ( ! theConnections.validMinSourceLeak && theConnections.validMaxDrainLeak
170 				&& abs(theConnections.maxDrainLeakVoltage) > theParameter )
171 			|| ( theConnections.validMaxSourceLeak && ! theConnections.validMinDrainLeak
172 				&& abs(theConnections.maxSourceLeakVoltage) > theParameter )
173 			|| ( ! theConnections.validMaxSourceLeak && theConnections.validMinDrainLeak
174 				&& abs(theConnections.minDrainLeakVoltage) > theParameter )	) {
175 		PrintOverVoltageError(theErrorFile, theConnections, OVERVOLTAGE_VDS, "Overvoltage Error:Source vs Drain: (logic ok)" + theDisplayParameter, theInstanceId);
176 	}
177 }
178 
FindVgsError(ogzstream & theErrorFile,voltage_t theParameter,CFullConnection & theConnections,instanceId_t theInstanceId,string theDisplayParameter)179 void CCvcDb::FindVgsError(ogzstream & theErrorFile, voltage_t theParameter, CFullConnection & theConnections, instanceId_t theInstanceId, string theDisplayParameter) {
180 	theParameter += cvcParameters.cvcOvervoltageErrorThreshold;
181 	if ( ( theConnections.validMinGate && theConnections.validMaxSource
182 				&& abs(theConnections.minGateVoltage - theConnections.maxSourceVoltage) > theParameter )
183 			|| ( theConnections.validMaxGate && theConnections.validMinSource
184 				&& abs(theConnections.maxGateVoltage - theConnections.minSourceVoltage) > theParameter )
185 			|| ( theConnections.validMinGate && theConnections.validMaxDrain
186 				&& abs(theConnections.minGateVoltage - theConnections.maxDrainVoltage) > theParameter )
187 			|| ( theConnections.validMaxGate && theConnections.validMinDrain
188 				&& abs(theConnections.maxGateVoltage - theConnections.minDrainVoltage) > theParameter ) ) {
189 		PrintOverVoltageError(theErrorFile, theConnections, OVERVOLTAGE_VGS, "Overvoltage Error:Gate vs Source/Drain:" + theDisplayParameter, theInstanceId);
190 	} else if ( ! cvcParameters.cvcLeakOvervoltage ) {
191 		return ;
192 	} else if ( ( theConnections.validMinGateLeak && theConnections.validMaxSourceLeak
193 				&& abs(theConnections.minGateLeakVoltage - theConnections.maxSourceLeakVoltage) > theParameter )
194 			|| ( theConnections.validMaxGateLeak && theConnections.validMinSourceLeak
195 				&& abs(theConnections.maxGateLeakVoltage - theConnections.minSourceLeakVoltage) > theParameter )
196 			|| ( theConnections.validMinGateLeak && theConnections.validMaxDrainLeak
197 				&& abs(theConnections.minGateLeakVoltage - theConnections.maxDrainLeakVoltage) > theParameter )
198 			|| ( theConnections.validMaxGateLeak && theConnections.validMinDrainLeak
199 				&& abs(theConnections.maxGateLeakVoltage - theConnections.minDrainLeakVoltage) > theParameter )
200 			|| ( theConnections.validMinGateLeak && ! theConnections.validMaxSourceLeak && ! theConnections.validMaxDrainLeak
201 				&& abs(theConnections.minGateLeakVoltage) > theParameter )
202 			|| ( theConnections.validMaxGateLeak && ! theConnections.validMinSourceLeak && ! theConnections.validMinDrainLeak
203 				&& abs(theConnections.maxGateLeakVoltage) > theParameter )
204 			|| ( ! theConnections.validMinGateLeak && theConnections.validMaxSourceLeak
205 				&& abs(theConnections.maxSourceLeakVoltage) > theParameter )
206 			|| ( ! theConnections.validMinGateLeak && theConnections.validMaxDrainLeak
207 				&& abs(theConnections.maxDrainLeakVoltage) > theParameter )
208 			|| ( ! theConnections.validMaxGateLeak && theConnections.validMinSourceLeak
209 				&& abs(theConnections.minSourceLeakVoltage) > theParameter )
210 			|| ( ! theConnections.validMaxGateLeak && theConnections.validMinDrainLeak
211 				&& abs(theConnections.minDrainLeakVoltage) > theParameter )	) {
212 		PrintOverVoltageError(theErrorFile, theConnections, OVERVOLTAGE_VGS, "Overvoltage Error:Gate vs Source/Drain: (logic ok)" + theDisplayParameter, theInstanceId);
213 	}
214 }
215 
FindModelError(ogzstream & theErrorFile,CModelCheck & theCheck,CFullConnection & theConnections,instanceId_t theInstanceId)216 void CCvcDb::FindModelError(ogzstream & theErrorFile, CModelCheck & theCheck, CFullConnection & theConnections, instanceId_t theInstanceId) {
217 	bool myError = false;
218 	if ( theCheck.parameter == "Vb" ) {
219 		if ( ! (theConnections.validMinBulk && theConnections.validMaxBulk) ) {
220 			myError = true;
221 		} else {
222 			if ( ! IsEmpty(theCheck.minExclusiveText) ) {
223 				myError |= theConnections.minBulkVoltage <= theCheck.minExclusiveVoltage;
224 			} else if ( ! IsEmpty(theCheck.minInclusiveText) ) {
225 				myError |= theConnections.minBulkVoltage < theCheck.minInclusiveVoltage;
226 			}
227 			if ( ! IsEmpty(theCheck.maxExclusiveText) ) {
228 				myError |= theConnections.maxBulkVoltage >= theCheck.maxExclusiveVoltage;
229 			} else if ( ! IsEmpty(theCheck.maxInclusiveText) ) {
230 				myError |= theConnections.maxBulkVoltage > theCheck.maxInclusiveVoltage;
231 			}
232 		}
233 	}
234 	if ( myError ) {
235 		PrintModelError(theErrorFile, theConnections, theCheck, theInstanceId);
236 	}
237 }
238 
PrintOverVoltageError(ogzstream & theErrorFile,CFullConnection & theConnections,cvcError_t theErrorIndex,string theExplanation,instanceId_t theInstanceId)239 void CCvcDb::PrintOverVoltageError(ogzstream & theErrorFile, CFullConnection & theConnections, cvcError_t theErrorIndex, string theExplanation, instanceId_t theInstanceId) {
240 	if ( cvcParameters.cvcCircuitErrorLimit == 0 || IncrementDeviceError(theConnections.deviceId, theErrorIndex) < cvcParameters.cvcCircuitErrorLimit ) {
241 		theErrorFile << theExplanation << endl;
242 		bool myLeakCheckFlag = ( theExplanation.find("logic ok") < string::npos );
243 		PrintDeviceWithAllConnections(theInstanceId, theConnections, theErrorFile, myLeakCheckFlag);
244 		theErrorFile << endl;
245 	}
246 }
247 
PrintModelError(ogzstream & theErrorFile,CFullConnection & theConnections,CModelCheck & theCheck,instanceId_t theInstanceId)248 void CCvcDb::PrintModelError(ogzstream & theErrorFile, CFullConnection & theConnections, CModelCheck & theCheck, instanceId_t theInstanceId) {
249 	if ( cvcParameters.cvcCircuitErrorLimit == 0 || IncrementDeviceError(theConnections.deviceId, MODEL_CHECK) < cvcParameters.cvcCircuitErrorLimit ) {
250 		theErrorFile << "Model error: " << theCheck.check << endl;
251 		PrintDeviceWithAllConnections(theInstanceId, theConnections, theErrorFile, false);
252 		theErrorFile << endl;
253 	}
254 }
255 
FindAllOverVoltageErrors()256 void CCvcDb::FindAllOverVoltageErrors() {
257 	CFullConnection myConnections;
258 	reportFile << "! Checking overvoltage errors" << endl << endl;
259 	string myVbgErrorFileName(tmpnam(NULL));
260 	ogzstream myVbgErrorFile(myVbgErrorFileName);
261 	myVbgErrorFile << "! Checking Vbg overvoltage errors" << endl << endl;
262 	string myVbsErrorFileName(tmpnam(NULL));
263 	ogzstream myVbsErrorFile(myVbsErrorFileName);
264 	myVbsErrorFile << "! Checking Vbs overvoltage errors" << endl << endl;
265 	string myVdsErrorFileName(tmpnam(NULL));
266 	ogzstream myVdsErrorFile(myVdsErrorFileName);
267 	myVdsErrorFile << "! Checking Vds overvoltage errors" << endl << endl;
268 	string myVgsErrorFileName(tmpnam(NULL));
269 	ogzstream myVgsErrorFile(myVgsErrorFileName);
270 	myVgsErrorFile << "! Checking Vgs overvoltage errors" << endl << endl;
271 	string myModelErrorFileName(tmpnam(NULL));
272 	ogzstream myModelErrorFile(myModelErrorFileName);
273 	myModelErrorFile << "! Checking Model errors" << endl << endl;
274 
275 	for (CModelListMap::iterator keyModelListPair_pit = cvcParameters.cvcModelListMap.begin(); keyModelListPair_pit != cvcParameters.cvcModelListMap.end(); keyModelListPair_pit++) {
276 		for (CModelList::iterator model_pit = keyModelListPair_pit->second.begin(); model_pit != keyModelListPair_pit->second.end(); model_pit++) {
277 			if ( model_pit->maxVbg == UNKNOWN_VOLTAGE && model_pit->maxVbs == UNKNOWN_VOLTAGE
278 				&&  model_pit->maxVds == UNKNOWN_VOLTAGE && model_pit->maxVgs == UNKNOWN_VOLTAGE ) continue;
279 			CDevice * myDevice_p = model_pit->firstDevice_p;
280 			string myVbgDisplayParameter, myVbsDisplayParameter, myVdsDisplayParameter, myVgsDisplayParameter;
281 			if ( model_pit->maxVbg != UNKNOWN_VOLTAGE ) {
282 				myVbgDisplayParameter = " Vbg=" + PrintToleranceParameter(model_pit->maxVbgDefinition, model_pit->maxVbg, VOLTAGE_SCALE) + " " + model_pit->ConditionString();
283 			}
284 			if ( model_pit->maxVbs != UNKNOWN_VOLTAGE ) {
285 				myVbsDisplayParameter = " Vbs=" + PrintToleranceParameter(model_pit->maxVbsDefinition, model_pit->maxVbs, VOLTAGE_SCALE) + " " + model_pit->ConditionString();
286 			}
287 			if ( model_pit->maxVds != UNKNOWN_VOLTAGE ) {
288 				myVdsDisplayParameter = " Vds=" + PrintToleranceParameter(model_pit->maxVdsDefinition, model_pit->maxVds, VOLTAGE_SCALE) + " " + model_pit->ConditionString();
289 			}
290 			if ( model_pit->maxVgs != UNKNOWN_VOLTAGE ) {
291 				myVgsDisplayParameter = " Vgs=" + PrintToleranceParameter(model_pit->maxVgsDefinition, model_pit->maxVgs, VOLTAGE_SCALE) + " " + model_pit->ConditionString();
292 			}
293 			while (myDevice_p) {
294 				CCircuit * myParent_p = myDevice_p->parent_p;
295 				for (instanceId_t instance_it = 0; instance_it < myParent_p->instanceId_v.size(); instance_it++) {
296 					if  ( instancePtr_v[myParent_p->instanceId_v[instance_it]]->IsParallelInstance() ) continue;  // parallel/empty instances
297 					instanceId_t myInstanceId = myParent_p->instanceId_v[instance_it];
298 					CInstance * myInstance_p = instancePtr_v[myInstanceId];
299 					MapDeviceNets(myInstance_p, myDevice_p, myConnections);
300 					myConnections.SetMinMaxLeakVoltagesAndFlags(this);
301 					//string myErrorExplanation = "";
302 					if ( model_pit->maxVbg != UNKNOWN_VOLTAGE ) FindVbgError(myVbgErrorFile, model_pit->maxVbg, myConnections, myInstanceId, myVbgDisplayParameter);
303 					if ( model_pit->maxVbs != UNKNOWN_VOLTAGE ) FindVbsError(myVbsErrorFile, model_pit->maxVbs, myConnections, myInstanceId, myVbsDisplayParameter);
304 					if ( model_pit->maxVds != UNKNOWN_VOLTAGE ) FindVdsError(myVdsErrorFile, model_pit->maxVds, myConnections, myInstanceId, myVdsDisplayParameter);
305 					if ( model_pit->maxVgs != UNKNOWN_VOLTAGE ) FindVgsError(myVgsErrorFile, model_pit->maxVgs, myConnections, myInstanceId, myVgsDisplayParameter);
306 					for ( auto check_pit = model_pit->checkList.begin(); check_pit != model_pit->checkList.end(); check_pit++ ) {
307 						FindModelError(myModelErrorFile, *check_pit, myConnections, myInstanceId);
308 					}
309 				}
310 				myDevice_p = myDevice_p->nextDevice_p;
311 			}
312 		}
313 	}
314 	myVbgErrorFile.close();
315 	myVbsErrorFile.close();
316 	myVdsErrorFile.close();
317 	myVgsErrorFile.close();
318 	myModelErrorFile.close();
319 	AppendErrorFile(myVbgErrorFileName, "! Checking Vbg overvoltage errors", OVERVOLTAGE_VBG - OVERVOLTAGE_VBG);
320 	AppendErrorFile(myVbsErrorFileName, "! Checking Vbs overvoltage errors", OVERVOLTAGE_VBS - OVERVOLTAGE_VBG);
321 	AppendErrorFile(myVdsErrorFileName, "! Checking Vds overvoltage errors", OVERVOLTAGE_VDS - OVERVOLTAGE_VBG);
322 	AppendErrorFile(myVgsErrorFileName, "! Checking Vgs overvoltage errors", OVERVOLTAGE_VGS - OVERVOLTAGE_VBG);
323 	AppendErrorFile(myModelErrorFileName, "! Checking Model errors", MODEL_CHECK - OVERVOLTAGE_VBG);
324 }
325 
AppendErrorFile(string theTempFileName,string theHeading,int theErrorSubIndex)326 void CCvcDb::AppendErrorFile(string theTempFileName, string theHeading, int theErrorSubIndex) {
327 	igzstream myTempFile(theTempFileName);
328 	errorFile << myTempFile.rdbuf();
329 	cvcCircuitList.PrintAndResetCircuitErrors(this, cvcParameters.cvcCircuitErrorLimit, logFile, errorFile, theHeading, theErrorSubIndex);
330 	myTempFile.close();
331 	remove(theTempFileName.c_str());
332 }
333 
FindNmosGateVsSourceErrors()334 void CCvcDb::FindNmosGateVsSourceErrors() {
335 	CFullConnection myConnections;
336 	reportFile << "! Checking nmos gate vs source errors: " << endl << endl;
337 	errorFile << "! Checking nmos gate vs source errors: " << endl << endl;
338 	for ( deviceId_t device_it = 0; device_it < deviceCount; device_it++ ) {
339 		CInstance * myInstance_p = instancePtr_v[deviceParent_v[device_it]];
340 		CCircuit * myParent_p = myInstance_p->master_p;
341 		CDevice * myDevice_p = myParent_p->devicePtr_v[device_it - myInstance_p->firstDeviceId];
342 		if ( ! IsNmos_(myDevice_p->model_p->type) ) continue;
343 		MapDeviceNets(myInstance_p, myDevice_p, myConnections);
344 		bool myVthFlag = false;
345 		bool myUnrelatedFlag = false;
346 		if ( ! myConnections.minGatePower_p ) continue;
347 		if ( myConnections.minGatePower_p->type[ANALOG_BIT] && ! cvcParameters.cvcAnalogGates ) continue;  // ignore analog gate errors
348 		if ( myConnections.minGatePower_p->IsRelatedPower(myConnections.minSourcePower_p, netVoltagePtr_v, minNet_v, minNet_v, true, true)
349 				&& myConnections.minGatePower_p->IsRelatedPower(myConnections.minDrainPower_p, netVoltagePtr_v, minNet_v, minNet_v, true, true) ) {
350 			// if relatives (default), then checks are conditional
351 			voltage_t myGateSourceDifference = myConnections.minGateVoltage - min(myConnections.minSourceVoltage, myConnections.minSourceVoltage + myDevice_p->model_p->Vth);
352 			voltage_t myGateDrainDifference = myConnections.minGateVoltage - min(myConnections.minDrainVoltage, myConnections.minDrainVoltage + myDevice_p->model_p->Vth);
353 			voltage_t myMaxVoltageDifference = min(0, myDevice_p->model_p->Vth);
354 			if ( myConnections.CheckTerminalMinVoltages(GATE | SOURCE)
355 					&& myGateSourceDifference > myMaxVoltageDifference
356 					&& myConnections.gateId != myConnections.drainId ) {
357 				myMaxVoltageDifference = myGateSourceDifference;
358 			}
359 			if ( myConnections.CheckTerminalMinVoltages(GATE | DRAIN)
360 					&& myGateDrainDifference > myMaxVoltageDifference
361 					&& myConnections.gateId != myConnections.sourceId ) {
362 				myMaxVoltageDifference = myGateDrainDifference;
363 			}
364 			if ( myMaxVoltageDifference <= cvcParameters.cvcGateErrorThreshold
365 					|| ( cvcParameters.cvcMinVthGates && myMaxVoltageDifference < myDevice_p->model_p->Vth ) ) continue;  // no error
366 			// Skip gates that are always fully on
367 			if ( myConnections.CheckTerminalMaxVoltages(SOURCE) ) {
368 				if ( myConnections.CheckTerminalMaxVoltages(DRAIN) ) {
369 					if ( myConnections.minGateVoltage >= max(myConnections.maxSourceVoltage, myConnections.maxDrainVoltage) - cvcParameters.cvcGateErrorThreshold ) continue;
370 					if ( myConnections.sourceId == myConnections.drainId ) {  // capacitor check
371 						if ( IsPower_(netVoltagePtr_v[myConnections.gateId].full) && IsPower_(netVoltagePtr_v[myConnections.drainId].full) ) continue;  // ignore direct power capacitors
372 						if ( ! IsInputOrPower_(netVoltagePtr_v[myConnections.masterMinSourceNet.finalNetId].full)
373 								|| ! IsInputOrPower_(netVoltagePtr_v[myConnections.masterMinGateNet.finalNetId].full) ) continue;  // ignore capacitors connected to non-input/power nets
374 					}
375 				} else {
376 					if ( myConnections.minGateVoltage >= myConnections.maxSourceVoltage - cvcParameters.cvcGateErrorThreshold ) continue;
377 				}
378 			} else if ( myConnections.CheckTerminalMaxVoltages(DRAIN) ) {
379 				if ( myConnections.minGateVoltage >= myConnections.maxDrainVoltage - cvcParameters.cvcGateErrorThreshold ) continue;
380 			} else {
381 				continue;  // ignore devices with no max connections
382 			}
383 			myVthFlag = myConnections.minGatePower_p->type[MIN_CALCULATED_BIT]
384 				&& ( myConnections.minGateVoltage - myConnections.minSourceVoltage == myDevice_p->model_p->Vth
385 					|| myConnections.minGateVoltage - myConnections.minDrainVoltage == myDevice_p->model_p->Vth );
386 			if ( myVthFlag && ! cvcParameters.cvcVthGates ) continue;
387 		} else {
388 			myUnrelatedFlag = true;  // if not relatives, always an error
389 		}
390 		if ( IncrementDeviceError(myConnections.deviceId, NMOS_GATE_SOURCE) < cvcParameters.cvcCircuitErrorLimit || cvcParameters.cvcCircuitErrorLimit == 0 ) {
391 			if ( myUnrelatedFlag ) {
392 				errorFile << "Unrelated power error" << endl;
393 /*
394 			} else if ( myConnections.minGatePower_p->type[REFERENCE_BIT] ) {
395 				errorFile << "Gate reference signal" << endl;
396 */
397 			} else if ( myVthFlag ) {
398 				errorFile << "Gate-source = Vth" << endl;
399 			}
400 			PrintDeviceWithAllConnections(deviceParent_v[device_it], myConnections, errorFile);
401 			errorFile << endl;
402 		}
403 	}
404 	CheckInverterIO(NMOS);
405 	CheckOppositeLogic(NMOS);
406 	cvcCircuitList.PrintAndResetCircuitErrors(this, cvcParameters.cvcCircuitErrorLimit, logFile, errorFile, "! Checking nmos gate vs source errors: ");
407 }
408 
FindPmosGateVsSourceErrors()409 void CCvcDb::FindPmosGateVsSourceErrors() {
410 	CFullConnection myConnections;
411 	reportFile << "! Checking pmos gate vs source errors: " << endl << endl;
412 	errorFile << "! Checking pmos gate vs source errors: " << endl << endl;
413 	for ( deviceId_t device_it = 0; device_it < deviceCount; device_it++ ) {
414 		CInstance * myInstance_p = instancePtr_v[deviceParent_v[device_it]];
415 		CCircuit * myParent_p = myInstance_p->master_p;
416 		CDevice * myDevice_p = myParent_p->devicePtr_v[device_it - myInstance_p->firstDeviceId];
417 		if ( ! IsPmos_(myDevice_p->model_p->type) ) continue;
418 		MapDeviceNets(myInstance_p, myDevice_p, myConnections);
419 		bool myVthFlag = false;
420 		bool myUnrelatedFlag = false;
421 		if ( ! myConnections.maxGatePower_p ) continue;
422 		if ( myConnections.maxGatePower_p->type[ANALOG_BIT] && ! cvcParameters.cvcAnalogGates ) continue;  // ignore analog gate errors
423 		if ( myConnections.maxGatePower_p->IsRelatedPower(myConnections.maxSourcePower_p, netVoltagePtr_v, maxNet_v, maxNet_v, true, true)
424 				&& myConnections.maxGatePower_p->IsRelatedPower(myConnections.maxDrainPower_p, netVoltagePtr_v, maxNet_v, maxNet_v, true, true) ) {
425 			// if relatives (default), then checks are conditional
426 			voltage_t myGateSourceDifference = max(myConnections.maxSourceVoltage, myConnections.maxSourceVoltage + myDevice_p->model_p->Vth) - myConnections.maxGateVoltage;
427 			voltage_t myGateDrainDifference = max(myConnections.maxDrainVoltage, myConnections.maxDrainVoltage + myDevice_p->model_p->Vth) - myConnections.maxGateVoltage;
428 			voltage_t myMaxVoltageDifference = max(0, myDevice_p->model_p->Vth);
429 			if ( myConnections.CheckTerminalMaxVoltages(GATE | SOURCE) &&
430 					myGateSourceDifference > myMaxVoltageDifference  &&
431 					myConnections.gateId != myConnections.drainId ) {
432 				myMaxVoltageDifference = myGateSourceDifference;
433 			}
434 			if ( myConnections.CheckTerminalMaxVoltages(GATE | DRAIN) &&
435 					myGateDrainDifference > myMaxVoltageDifference  &&
436 					myConnections.gateId != myConnections.sourceId ) {
437 				myMaxVoltageDifference = myGateDrainDifference;
438 			}
439 			if ( myMaxVoltageDifference <= cvcParameters.cvcGateErrorThreshold
440 					|| ( cvcParameters.cvcMinVthGates && myMaxVoltageDifference < -myDevice_p->model_p->Vth ) ) continue;  // no error
441 			// Skip gates that are always fully on
442 			if ( myConnections.CheckTerminalMinVoltages(SOURCE) ) {
443 				if ( myConnections.CheckTerminalMinVoltages(DRAIN) ) {
444 					if ( myConnections.maxGateVoltage <= min(myConnections.minSourceVoltage, myConnections.minDrainVoltage) + cvcParameters.cvcGateErrorThreshold ) continue;
445 					if ( myConnections.sourceId == myConnections.drainId ) {  // capacitor check
446 						if ( IsPower_(netVoltagePtr_v[myConnections.gateId].full) && IsPower_(netVoltagePtr_v[myConnections.drainId].full) ) continue;  // ignore direct power capacitors
447 						if ( ! IsInputOrPower_(netVoltagePtr_v[myConnections.masterMinSourceNet.finalNetId].full)
448 								|| ! IsInputOrPower_(netVoltagePtr_v[myConnections.masterMinGateNet.finalNetId].full) ) continue;  // ignore capacitors connected to non-input/power nets
449 					}
450 				} else {
451 					if ( myConnections.maxGateVoltage <= myConnections.minSourceVoltage + cvcParameters.cvcGateErrorThreshold ) continue;
452 				}
453 			} else if ( myConnections.CheckTerminalMinVoltages(DRAIN) ) {
454 				if ( myConnections.maxGateVoltage <= myConnections.minDrainVoltage + cvcParameters.cvcGateErrorThreshold ) continue;
455 			} else {
456 				continue;  // ignore devices with no min connections
457 			}
458 			myVthFlag= myConnections.maxGatePower_p->type[MAX_CALCULATED_BIT]
459 				&& ( myConnections.maxGateVoltage - myConnections.maxSourceVoltage == myDevice_p->model_p->Vth
460 					|| myConnections.maxGateVoltage - myConnections.maxDrainVoltage == myDevice_p->model_p->Vth );
461 			if ( myVthFlag && ! cvcParameters.cvcVthGates ) continue;
462 		} else {
463 			myUnrelatedFlag = true; // if not relatives, always an error
464 		}
465 		if ( IncrementDeviceError(myConnections.deviceId, PMOS_GATE_SOURCE) < cvcParameters.cvcCircuitErrorLimit || cvcParameters.cvcCircuitErrorLimit == 0 ) {
466 			if ( myUnrelatedFlag ) {
467 				errorFile << "Unrelated power error" << endl;
468 /*
469 			} else if ( myConnections.maxGatePower_p->type[REFERENCE_BIT] ) {
470 				errorFile << "Gate reference signal" << endl;
471 */
472 			} else if ( myVthFlag ) {
473 				errorFile << "Gate-source = Vth" << endl;
474 			}
475 			PrintDeviceWithAllConnections(deviceParent_v[device_it], myConnections, errorFile);
476 			errorFile << endl;
477 		}
478 	}
479 	CheckInverterIO(PMOS);
480 	CheckOppositeLogic(PMOS);
481 	cvcCircuitList.PrintAndResetCircuitErrors(this, cvcParameters.cvcCircuitErrorLimit, logFile, errorFile, "! Checking pmos gate vs source errors: ");
482 }
483 
FindNmosSourceVsBulkErrors()484 void CCvcDb::FindNmosSourceVsBulkErrors() {
485 	CFullConnection myConnections;
486 	reportFile << "! Checking nmos source/drain vs bias errors: " << endl << endl;
487 	errorFile << "! Checking nmos source/drain vs bias errors: " << endl << endl;
488 	unordered_set<netId_t> myProblemNets;
489 	for ( deviceId_t device_it = 0; device_it < deviceCount; device_it++ ) {
490 		CInstance * myInstance_p = instancePtr_v[deviceParent_v[device_it]];
491 		CCircuit * myParent_p = myInstance_p->master_p;
492 		CDevice * myDevice_p = myParent_p->devicePtr_v[device_it - myInstance_p->firstDeviceId];
493 		if ( ! IsNmos_(myDevice_p->model_p->type) ) continue;
494 		MapDeviceNets(myInstance_p, myDevice_p, myConnections);
495 		if ( myConnections.sourceId == myConnections.drainId && myConnections.sourceId == myConnections.bulkId ) continue;  // ignore drain = source = bulk
496 		bool myErrorFlag = false;
497 		bool myUnrelatedFlag = false;
498 		bool mySourceError = false;
499 		bool myDrainError = false;
500 		if ( ! myConnections.minBulkPower_p
501 				|| (myConnections.minBulkPower_p->IsRelatedPower(myConnections.minSourcePower_p, netVoltagePtr_v, minNet_v, minNet_v, true, true)
502 					&& myConnections.minBulkPower_p->IsRelatedPower(myConnections.minDrainPower_p, netVoltagePtr_v, minNet_v, minNet_v, true, true)) ) {
503 			// if relatives (default), then checks are conditional
504 			if ( (myConnections.maxBulkVoltage == myConnections.minSourceVoltage || myConnections.minSourceVoltage == UNKNOWN_VOLTAGE)
505 					&& (myConnections.maxBulkVoltage == myConnections.minDrainVoltage || myConnections.minDrainVoltage == UNKNOWN_VOLTAGE) ) continue;
506 				// no error if max bulk = min source = min drain
507 			if ( myConnections.minBulkPower_p && myConnections.minBulkPower_p->type[HIZ_BIT] ) {
508 				if ( myConnections.sourceId == myConnections.bulkId && myConnections.drainId == myConnections.bulkId ) continue;
509 				if ( myConnections.minSourcePower_p && ! myConnections.minBulkPower_p->IsRelatedPower(myConnections.minSourcePower_p, netVoltagePtr_v, minNet_v, minNet_v, false) ) {
510 					myErrorFlag = true;
511 				} else if ( myConnections.simSourcePower_p && IsKnownVoltage_(myConnections.simSourcePower_p->simVoltage)
512 						&& ! myConnections.minBulkPower_p->IsRelatedPower(myConnections.simSourcePower_p, netVoltagePtr_v, minNet_v, simNet_v, false)
513 						&& myConnections.simSourceVoltage < myConnections.maxBulkVoltage ) {
514 					myErrorFlag = true;
515 				} else if ( myConnections.maxSourcePower_p && ! myConnections.minBulkPower_p->IsRelatedPower(myConnections.maxSourcePower_p, netVoltagePtr_v, minNet_v, maxNet_v, false) ) {
516 					myErrorFlag = true;
517 				} else if ( myConnections.minDrainPower_p && ! myConnections.minBulkPower_p->IsRelatedPower(myConnections.minDrainPower_p, netVoltagePtr_v, minNet_v, minNet_v, false) ) {
518 					myErrorFlag = true;
519 				} else if ( myConnections.simDrainPower_p && IsKnownVoltage_(myConnections.simDrainPower_p->simVoltage)
520 						&& ! myConnections.minBulkPower_p->IsRelatedPower(myConnections.simDrainPower_p, netVoltagePtr_v, minNet_v, simNet_v, false)
521 						&& myConnections.simDrainVoltage < myConnections.maxBulkVoltage ) {
522 					myErrorFlag = true;
523 				} else if ( myConnections.maxDrainPower_p && ! myConnections.minBulkPower_p->IsRelatedPower(myConnections.maxDrainPower_p, netVoltagePtr_v, minNet_v, maxNet_v, false) ) {
524 					myErrorFlag = true;
525 				}
526 			} else if ( myConnections.CheckTerminalMinVoltages(BULK) == false ) {
527 				if ( myConnections.minSourcePower_p || myConnections.simSourcePower_p || myConnections.maxSourcePower_p ||
528 						myConnections.minDrainPower_p || myConnections.simDrainPower_p || myConnections.maxDrainPower_p ) { // has some connection (all connections open -> no error)
529 					myErrorFlag = true;
530 				}
531 			} else if ( myConnections.CheckTerminalMinVoltages(BULK | SOURCE) &&
532 					( myConnections.minBulkVoltage - myConnections.minSourceVoltage > cvcParameters.cvcBiasErrorThreshold ||
533 						( myConnections.minSourceVoltage == myConnections.minBulkVoltage &&
534 							cvcParameters.cvcBiasErrorThreshold == 0 &&
535 							myConnections.masterMinSourceNet.finalResistance < myConnections.masterMinBulkNet.finalResistance) ) ) {
536 				mySourceError = true;
537 			} else if (	myConnections.CheckTerminalMinVoltages(BULK | DRAIN) &&
538 					( myConnections.minBulkVoltage - myConnections.minDrainVoltage > cvcParameters.cvcBiasErrorThreshold ||
539 						( myConnections.minDrainVoltage == myConnections.minBulkVoltage &&
540 							cvcParameters.cvcBiasErrorThreshold == 0 &&
541 							myConnections.masterMinDrainNet.finalResistance < myConnections.masterMinBulkNet.finalResistance) ) ) {
542 				myDrainError = true;
543 			} else if (	myConnections.CheckTerminalSimVoltages(BULK | SOURCE) &&
544 					( myConnections.simBulkVoltage - myConnections.simSourceVoltage > cvcParameters.cvcBiasErrorThreshold ||
545 						( myConnections.simSourceVoltage == myConnections.simBulkVoltage &&
546 							cvcParameters.cvcBiasErrorThreshold == 0 &&
547 							myConnections.masterSimSourceNet.finalResistance < myConnections.masterSimBulkNet.finalResistance) ) ) {
548 				myErrorFlag = true;
549 			} else if (	myConnections.CheckTerminalSimVoltages(BULK | DRAIN) &&
550 					( myConnections.simBulkVoltage - myConnections.simDrainVoltage > cvcParameters.cvcBiasErrorThreshold ||
551 						( myConnections.simDrainVoltage == myConnections.simBulkVoltage &&
552 							cvcParameters.cvcBiasErrorThreshold == 0 &&
553 							myConnections.masterSimDrainNet.finalResistance < myConnections.masterSimBulkNet.finalResistance) ) ) {
554 				myErrorFlag = true;
555 			} else if (	myConnections.CheckTerminalMaxVoltages(BULK | SOURCE) &&
556 					( ( myConnections.maxBulkVoltage - myConnections.maxSourceVoltage > cvcParameters.cvcBiasErrorThreshold &&
557 							myConnections.maxSourcePower_p->defaultMaxNet != myConnections.bulkId ) ||
558 						( myConnections.maxSourceVoltage == myConnections.maxBulkVoltage &&
559 							cvcParameters.cvcBiasErrorThreshold == 0 &&
560 							myConnections.maxSourceVoltage != myConnections.minBulkVoltage && // no leak path
561 	//						myConnections.masterMinBulkNet.finalNetId != myConnections.masterMaxBulkNet.finalNetId &&
562 							myConnections.masterMaxSourceNet.finalResistance > myConnections.masterMaxBulkNet.finalResistance &&
563 							! myConnections.minBulkPower_p->type[HIZ_BIT] &&
564 							! PathContains(maxNet_v, myConnections.sourceId, myConnections.bulkId)) ) ) { // resistance check backwards in NMOS max (ignore connections through self)
565 				myErrorFlag = true;
566 	// Added 20140523
567 			} else if (	myConnections.CheckTerminalMaxVoltages(BULK | DRAIN) &&
568 					( ( myConnections.maxBulkVoltage - myConnections.maxDrainVoltage > cvcParameters.cvcBiasErrorThreshold &&
569 							myConnections.maxDrainPower_p->defaultMaxNet != myConnections.bulkId ) ||
570 						( myConnections.maxDrainVoltage == myConnections.maxBulkVoltage &&
571 							cvcParameters.cvcBiasErrorThreshold == 0 &&
572 							myConnections.maxDrainVoltage != myConnections.minBulkVoltage && // no leak path
573 	//						myConnections.masterMinBulkNet.finalNetId != myConnections.masterMaxBulkNet.finalNetId &&
574 							myConnections.masterMaxDrainNet.finalResistance > myConnections.masterMaxBulkNet.finalResistance &&
575 							! myConnections.minBulkPower_p->type[HIZ_BIT] &&
576 							! PathContains(maxNet_v, myConnections.drainId, myConnections.bulkId)) ) ) { // resistance check backwards in NMOS max (ignore connections through self)
577 				myErrorFlag = true;
578 			}
579 		} else {
580 			myErrorFlag = true; // if not relatives, always an error
581 			myUnrelatedFlag = true;
582 		}
583 		if ( gSetup_cvc ) {
584 			if ( myDrainError ) {
585 				myProblemNets.insert(myConnections.drainId);
586 			} else if ( mySourceError ) {
587 				myProblemNets.insert(myConnections.sourceId);
588 			}
589 		} else if ( myErrorFlag || myDrainError || mySourceError ) {
590 			if ( IncrementDeviceError(myConnections.deviceId, NMOS_SOURCE_BULK) < cvcParameters.cvcCircuitErrorLimit || cvcParameters.cvcCircuitErrorLimit == 0 ) {
591 				if ( myUnrelatedFlag ) {
592 					errorFile << "Unrelated power error" << endl;
593 				}
594 				PrintDeviceWithAllConnections(deviceParent_v[device_it], myConnections, errorFile);
595 				errorFile << endl;
596 			}
597 		}
598 	}
599 	if ( gSetup_cvc ) {
600 		reportFile << endl << "CVC SETUP: nmos bias problems" << endl << endl;
601 		unordered_set<netId_t> myPrintedNets;
602 		unordered_set<netId_t> myParentNets;
603 		for ( auto net_pit = myProblemNets.begin(); net_pit != myProblemNets.end(); net_pit++ ) {
604 			netId_t myNextNet = *net_pit;
605 			while(myNextNet != minNet_v[myNextNet].nextNetId) {
606 				myNextNet = minNet_v[myNextNet].nextNetId;
607 				myParentNets.insert(myNextNet);
608 			}
609 		}
610 		for ( auto net_pit = myProblemNets.begin(); net_pit != myProblemNets.end(); net_pit++ ) {
611 			if ( myParentNets.count(*net_pit) ) continue;
612 			netId_t traceNet_it = *net_pit;
613 			reportFile << endl;
614 			PrintNetWithModelCounts(traceNet_it, SOURCE | DRAIN);
615 			while ( traceNet_it != minNet_v[traceNet_it].nextNetId ) {
616 				traceNet_it = minNet_v[traceNet_it].nextNetId;
617 				if ( traceNet_it == minNet_v[traceNet_it].nextNetId ) {
618 					reportFile << NetName(traceNet_it, PRINT_CIRCUIT_ON) << endl;
619 				} else {
620 					PrintNetWithModelCounts(traceNet_it, SOURCE | DRAIN);
621 					if ( myPrintedNets.count(traceNet_it) ) {
622 						reportFile << "**********" << endl;
623 						break;
624 					}
625 					myPrintedNets.insert(traceNet_it);
626 				}
627 			}
628 		}
629 	} else {
630 		cvcCircuitList.PrintAndResetCircuitErrors(this, cvcParameters.cvcCircuitErrorLimit, logFile, errorFile, "! Checking nmos source/drain vs bias errors: ");
631 	}
632 }
633 
FindPmosSourceVsBulkErrors()634 void CCvcDb::FindPmosSourceVsBulkErrors() {
635 	CFullConnection myConnections;
636 	reportFile << "! Checking pmos source/drain vs bias errors: " << endl << endl;
637 	errorFile << "! Checking pmos source/drain vs bias errors: " << endl << endl;
638 	unordered_set<netId_t> myProblemNets;
639 	for ( deviceId_t device_it = 0; device_it < deviceCount; device_it++ ) {
640 		CInstance * myInstance_p = instancePtr_v[deviceParent_v[device_it]];
641 		CCircuit * myParent_p = myInstance_p->master_p;
642 		CDevice * myDevice_p = myParent_p->devicePtr_v[device_it - myInstance_p->firstDeviceId];
643 		if ( ! IsPmos_(myDevice_p->model_p->type) ) continue;
644 		MapDeviceNets(myInstance_p, myDevice_p, myConnections);
645 		if ( myConnections.sourceId == myConnections.drainId && myConnections.sourceId == myConnections.bulkId ) continue;  // ignore drain = source = bulk
646 		bool myErrorFlag = false;
647 		bool myUnrelatedFlag = false;
648 		bool mySourceError = false;
649 		bool myDrainError = false;
650 		if ( ! myConnections.maxBulkPower_p
651 				|| (myConnections.maxBulkPower_p->IsRelatedPower(myConnections.maxSourcePower_p, netVoltagePtr_v, maxNet_v, maxNet_v, true, true)
652 					&& myConnections.maxBulkPower_p->IsRelatedPower(myConnections.maxDrainPower_p, netVoltagePtr_v, maxNet_v, maxNet_v, true, true)) ) {
653 			// if relatives (default), then checks are conditional
654 			if ( (myConnections.minBulkVoltage == myConnections.maxSourceVoltage || myConnections.maxSourceVoltage == UNKNOWN_VOLTAGE)
655 					&& (myConnections.minBulkVoltage == myConnections.maxDrainVoltage || myConnections.maxDrainVoltage == UNKNOWN_VOLTAGE) ) continue;
656 				 // no error if min bulk = max source = max drain
657 			if ( myConnections.maxBulkPower_p && myConnections.maxBulkPower_p->type[HIZ_BIT] ) {
658 				if ( myConnections.minSourcePower_p && ! myConnections.maxBulkPower_p->IsRelatedPower(myConnections.minSourcePower_p, netVoltagePtr_v, maxNet_v, minNet_v, false) ) {
659 					myErrorFlag = true;
660 				} else if ( myConnections.simSourcePower_p && IsKnownVoltage_(myConnections.simSourcePower_p->simVoltage)
661 						&& ! myConnections.maxBulkPower_p->IsRelatedPower(myConnections.simSourcePower_p, netVoltagePtr_v, maxNet_v, simNet_v, false)
662 						&& myConnections.simSourceVoltage > myConnections.minBulkVoltage ) {
663 					myErrorFlag = true;
664 				} else if ( myConnections.maxSourcePower_p && ! myConnections.maxBulkPower_p->IsRelatedPower(myConnections.maxSourcePower_p, netVoltagePtr_v, maxNet_v, maxNet_v, false) ) {
665 					myErrorFlag = true;
666 				} else if ( myConnections.minDrainPower_p && ! myConnections.maxBulkPower_p->IsRelatedPower(myConnections.minDrainPower_p, netVoltagePtr_v, maxNet_v, minNet_v, false) ) {
667 					myErrorFlag = true;
668 				} else if ( myConnections.simDrainPower_p && IsKnownVoltage_(myConnections.simDrainPower_p->simVoltage)
669 						&& ! myConnections.maxBulkPower_p->IsRelatedPower(myConnections.simDrainPower_p, netVoltagePtr_v, maxNet_v, simNet_v, false)
670 						&& myConnections.simDrainVoltage > myConnections.minBulkVoltage ) {
671 					myErrorFlag = true;
672 				} else if ( myConnections.maxDrainPower_p && ! myConnections.maxBulkPower_p->IsRelatedPower(myConnections.maxDrainPower_p, netVoltagePtr_v, maxNet_v, maxNet_v, false) ) {
673 					myErrorFlag = true;
674 				}
675 			} else if ( myConnections.CheckTerminalMaxVoltages(BULK) == false ) {
676 				if ( myConnections.minSourcePower_p || myConnections.simSourcePower_p || myConnections.maxSourcePower_p ||
677 						myConnections.minDrainPower_p || myConnections.simDrainPower_p || myConnections.maxDrainPower_p ) { // has some connection (all connections open -> no error)
678 					myErrorFlag = true;
679 				}
680 			} else if (	myConnections.CheckTerminalMinVoltages(BULK | SOURCE) &&
681 					( ( myConnections.minSourceVoltage - myConnections.minBulkVoltage > cvcParameters.cvcBiasErrorThreshold &&
682 							myConnections.minSourcePower_p->defaultMinNet != myConnections.bulkId ) ||
683 						( myConnections.minSourceVoltage == myConnections.minBulkVoltage &&
684 							cvcParameters.cvcBiasErrorThreshold == 0 &&
685 	//						myConnections.masterMinBulkNet.finalNetId != myConnections.masterMaxBulkNet.finalNetId &&
686 							myConnections.minSourceVoltage != myConnections.maxBulkVoltage && // no leak path
687 							myConnections.masterMinSourceNet.finalResistance > myConnections.masterMinBulkNet.finalResistance &&
688 							! myConnections.maxBulkPower_p->type[HIZ_BIT] &&
689 							! PathContains(minNet_v, myConnections.sourceId, myConnections.bulkId)) ) ) { // resistance check backwards in PMOS min (ignore connections through self)
690 				myErrorFlag = true;
691 			} else if (	myConnections.CheckTerminalMinVoltages(BULK | DRAIN) &&
692 					( ( myConnections.minDrainVoltage - myConnections.minBulkVoltage > cvcParameters.cvcBiasErrorThreshold &&
693 							myConnections.minDrainPower_p->defaultMinNet != myConnections.bulkId ) ||
694 						( myConnections.minDrainVoltage == myConnections.minBulkVoltage &&
695 							cvcParameters.cvcBiasErrorThreshold == 0 &&
696 	//						myConnections.masterMinBulkNet.finalNetId != myConnections.masterMaxBulkNet.finalNetId &&
697 							myConnections.minDrainVoltage != myConnections.maxBulkVoltage && // no leak path
698 							myConnections.masterMinDrainNet.finalResistance > myConnections.masterMinBulkNet.finalResistance &&
699 							! myConnections.maxBulkPower_p->type[HIZ_BIT] &&
700 							! PathContains(minNet_v, myConnections.drainId, myConnections.bulkId)) ) ) { // resistance check backwards in PMOS min (ignore connections through self)
701 				myErrorFlag = true;
702 			} else if (	myConnections.CheckTerminalSimVoltages(BULK | SOURCE) &&
703 					( myConnections.simSourceVoltage - myConnections.simBulkVoltage > cvcParameters.cvcBiasErrorThreshold ||
704 						( myConnections.simSourceVoltage == myConnections.simBulkVoltage &&
705 							cvcParameters.cvcBiasErrorThreshold == 0 &&
706 							myConnections.masterSimSourceNet.finalResistance < myConnections.masterSimBulkNet.finalResistance) ) ) {
707 				myErrorFlag = true;
708 			} else if (	myConnections.CheckTerminalSimVoltages(BULK | DRAIN) &&
709 					( myConnections.simDrainVoltage - myConnections.simBulkVoltage > cvcParameters.cvcBiasErrorThreshold ||
710 						( myConnections.simDrainVoltage == myConnections.simBulkVoltage &&
711 							cvcParameters.cvcBiasErrorThreshold == 0 &&
712 							myConnections.masterSimDrainNet.finalResistance < myConnections.masterSimBulkNet.finalResistance) ) ) {
713 				myErrorFlag = true;
714 			} else if (	myConnections.CheckTerminalMaxVoltages(BULK | SOURCE) &&
715 					( myConnections.maxSourceVoltage - myConnections.maxBulkVoltage > cvcParameters.cvcBiasErrorThreshold ||
716 						( myConnections.maxSourceVoltage == myConnections.maxBulkVoltage &&
717 							cvcParameters.cvcBiasErrorThreshold == 0 &&
718 							myConnections.masterMaxSourceNet.finalResistance < myConnections.masterMaxBulkNet.finalResistance) ) ) {
719 				mySourceError = true;
720 			} else if (	myConnections.CheckTerminalMaxVoltages(BULK | DRAIN) &&
721 					( myConnections.maxDrainVoltage - myConnections.maxBulkVoltage > cvcParameters.cvcBiasErrorThreshold ||
722 						( myConnections.maxDrainVoltage == myConnections.maxBulkVoltage &&
723 							cvcParameters.cvcBiasErrorThreshold == 0 &&
724 							myConnections.masterMaxDrainNet.finalResistance < myConnections.masterMaxBulkNet.finalResistance) ) ) {
725 				myDrainError = true;
726 			}
727 		} else {
728 			myUnrelatedFlag = true;
729 			myErrorFlag = true; // if not relatives, always an error
730 		}
731 		if ( gSetup_cvc ) {
732 			if ( myDrainError ) {
733 				myProblemNets.insert(myConnections.drainId);
734 			} else if ( mySourceError ) {
735 				myProblemNets.insert(myConnections.sourceId);
736 			}
737 		} else if ( myErrorFlag || myDrainError || mySourceError ) {
738 			if ( IncrementDeviceError(myConnections.deviceId, PMOS_SOURCE_BULK) < cvcParameters.cvcCircuitErrorLimit || cvcParameters.cvcCircuitErrorLimit == 0 ) {
739 				if ( myUnrelatedFlag ) {
740 					errorFile << "Unrelated power error" << endl;
741 				}
742 				PrintDeviceWithAllConnections(deviceParent_v[device_it], myConnections, errorFile);
743 				errorFile << endl;
744 			}
745 		}
746 	}
747 	if ( gSetup_cvc ) {
748 		reportFile << endl << "CVC SETUP: pmos bias problems" << endl << endl;
749 		unordered_set<netId_t> myPrintedNets;
750 		unordered_set<netId_t> myParentNets;
751 		for ( auto net_pit = myProblemNets.begin(); net_pit != myProblemNets.end(); net_pit++ ) {
752 			netId_t myNextNet = *net_pit;
753 			while(myNextNet != minNet_v[myNextNet].nextNetId) {
754 				myNextNet = minNet_v[myNextNet].nextNetId;
755 				myParentNets.insert(myNextNet);
756 			}
757 		}
758 		for ( auto net_pit = myProblemNets.begin(); net_pit != myProblemNets.end(); net_pit++ ) {
759 			if ( myParentNets.count(*net_pit) ) continue;
760 			netId_t traceNet_it = *net_pit;
761 			reportFile << endl;
762 			PrintNetWithModelCounts(traceNet_it, SOURCE | DRAIN);
763 			while ( traceNet_it != minNet_v[traceNet_it].nextNetId ) {
764 				traceNet_it = minNet_v[traceNet_it].nextNetId;
765 				if ( traceNet_it == minNet_v[traceNet_it].nextNetId ) {
766 					reportFile << NetName(traceNet_it, PRINT_CIRCUIT_ON) << endl;
767 				} else {
768 					PrintNetWithModelCounts(traceNet_it, SOURCE | DRAIN);
769 					if ( myPrintedNets.count(traceNet_it) ) {
770 						reportFile << "**********" << endl;
771 						break;
772 					}
773 					myPrintedNets.insert(traceNet_it);
774 				}
775 			}
776 		}
777 	} else {
778 		cvcCircuitList.PrintAndResetCircuitErrors(this, cvcParameters.cvcCircuitErrorLimit, logFile, errorFile, "! Checking pmos source/drain vs bias errors: ");
779 	}
780 }
781 
FindForwardBiasDiodes()782 void CCvcDb::FindForwardBiasDiodes() {
783 	CFullConnection myConnections;
784 	CFullConnection myDiodeConnections;
785 	reportFile << "! Checking forward bias diode errors: " << endl << endl;
786 	errorFile << "! Checking forward bias diode errors: " << endl << endl;
787 	for ( deviceId_t device_it = 0; device_it < deviceCount; device_it++ ) {
788 		CInstance * myInstance_p = instancePtr_v[deviceParent_v[device_it]];
789 		CCircuit * myParent_p = myInstance_p->master_p;
790 		CDevice * myDevice_p = myParent_p->devicePtr_v[device_it - myInstance_p->firstDeviceId];
791 //		if ( myDevice_p->model_p->type != DIODE ) continue;
792 		if ( IsNmos_(deviceType_v[device_it]) || IsPmos_(deviceType_v[device_it]) ) continue;
793 		if ( myDevice_p->model_p->diodeList.empty() ) continue;
794 		MapDeviceNets(myInstance_p, myDevice_p, myConnections);
795 		bool myErrorFlag = false;
796 		for ( auto diode_pit = myDevice_p->model_p->diodeList.begin(); diode_pit != myDevice_p->model_p->diodeList.end(); diode_pit++ ) {
797 			if ( myErrorFlag ) continue;  // only one error per device
798 			SetDiodeConnections((*diode_pit), myConnections, myDiodeConnections);  // switch connections for diodes
799 			if ( GetEquivalentNet(myDiodeConnections.originalSourceId) == GetEquivalentNet(myDiodeConnections.originalDrainId) ) continue;
800 			bool myUnrelatedFlag = false;
801 			if ( myDiodeConnections.CheckTerminalMinMaxVoltages(SOURCE | DRAIN) ) {
802 				voltage_t mySourceVoltage = UNKNOWN_VOLTAGE, myDrainVoltage = UNKNOWN_VOLTAGE;
803 				if ( myDiodeConnections.minSourcePower_p == myDiodeConnections.minDrainPower_p ) {
804 					if ( myDiodeConnections.maxSourceVoltage == myDiodeConnections.maxDrainVoltage
805 							&& myDiodeConnections.minSourceVoltage == myDiodeConnections.maxDrainVoltage ) continue;
806 					if ( myDiodeConnections.masterMinSourceNet.finalResistance < myDiodeConnections.masterMinDrainNet.finalResistance ) {
807 						mySourceVoltage = myDiodeConnections.minSourceVoltage;
808 					} else if ( myDiodeConnections.masterMinSourceNet.finalResistance > myDiodeConnections.masterMinDrainNet.finalResistance ) {
809 						myDrainVoltage = myDiodeConnections.minDrainVoltage;
810 					}
811 				}
812 				if ( myDiodeConnections.maxSourcePower_p == myDiodeConnections.maxDrainPower_p ) {
813 					if ( myDiodeConnections.masterMaxDrainNet.finalResistance < myDiodeConnections.masterMaxSourceNet.finalResistance ) {
814 						if (myDrainVoltage == UNKNOWN_VOLTAGE) {
815 							myDrainVoltage = myDiodeConnections.maxDrainVoltage; // min drain overrides
816 						} else if ( PathCrosses(maxNet_v, myDiodeConnections.sourceId, minNet_v, myDiodeConnections.drainId) ) {
817 							continue; // no error if anode to power crosses cathode to ground path
818 						} else {
819 							logFile << "INFO: unexpected diode " << DeviceName(device_it, PRINT_CIRCUIT_ON) << endl << endl;
820 							PrintVirtualNet<CVirtualNetVector>(maxNet_v, myDiodeConnections.sourceId, "Max anode path", logFile);
821 							PrintVirtualNet<CVirtualNetVector>(minNet_v, myDiodeConnections.sourceId, "Min anode path", logFile);
822 							PrintVirtualNet<CVirtualNetVector>(maxNet_v, myDiodeConnections.drainId, "Max cathode path", logFile);
823 							PrintVirtualNet<CVirtualNetVector>(minNet_v, myDiodeConnections.drainId, "Min cathode path", logFile);
824 						}
825 					} else {
826 						if ( PathCrosses(minNet_v, myDiodeConnections.drainId, maxNet_v, myDiodeConnections.sourceId) ) {
827 							continue; // no error if anode to power crosses cathode to ground path
828 						} else if ( mySourceVoltage != UNKNOWN_VOLTAGE ) {
829 							logFile << "INFO: unexpected diode " << DeviceName(device_it, PRINT_CIRCUIT_ON) << endl << endl;
830 							PrintVirtualNet<CVirtualNetVector>(maxNet_v, myDiodeConnections.sourceId, "Max anode path", logFile);
831 							PrintVirtualNet<CVirtualNetVector>(minNet_v, myDiodeConnections.sourceId, "Min anode path", logFile);
832 							PrintVirtualNet<CVirtualNetVector>(maxNet_v, myDiodeConnections.drainId, "Max cathode path", logFile);
833 							PrintVirtualNet<CVirtualNetVector>(minNet_v, myDiodeConnections.drainId, "Min cathode path", logFile);
834 						}
835 						mySourceVoltage = myDiodeConnections.maxSourceVoltage; // max source overrides
836 					}
837 				}
838 				if ( mySourceVoltage == UNKNOWN_VOLTAGE ) {
839 					mySourceVoltage = myDiodeConnections.maxSourceVoltage;
840 				}
841 				if ( myDrainVoltage == UNKNOWN_VOLTAGE ) {
842 					myDrainVoltage = myDiodeConnections.minDrainVoltage;
843 				}
844 				if ( mySourceVoltage - myDrainVoltage > cvcParameters.cvcForwardErrorThreshold ) {
845 					if ( myDiodeConnections.maxSourcePower_p->type[HIZ_BIT] || myDiodeConnections.minDrainPower_p->type[HIZ_BIT] ) {
846 						// the following are errors for cutoff power. unknown annode, unknown cathode, source > max drain, max source not related to min drain
847 						if ( mySourceVoltage == UNKNOWN_VOLTAGE || myDiodeConnections.maxDrainVoltage == UNKNOWN_VOLTAGE || mySourceVoltage > myDiodeConnections.maxDrainVoltage ) {
848 								myErrorFlag = true;
849 						} else if ( ! myDiodeConnections.maxSourcePower_p->IsRelatedPower(myDiodeConnections.minDrainPower_p, netVoltagePtr_v, maxNet_v, minNet_v, true)) {
850 								myErrorFlag = true;
851 						}
852 					} else {
853 						myErrorFlag = true;
854 					}
855 				} else if ( ! myDiodeConnections.minSourcePower_p->IsRelatedPower(myDiodeConnections.minDrainPower_p, netVoltagePtr_v, minNet_v, minNet_v, true, true)
856 						|| ! myDiodeConnections.maxSourcePower_p->IsRelatedPower(myDiodeConnections.maxDrainPower_p, netVoltagePtr_v, maxNet_v, maxNet_v, true, true) ) {
857 					myErrorFlag = true;
858 					myUnrelatedFlag = true;
859 				}
860 			} else if ( myDiodeConnections.CheckTerminalMinMaxVoltages(SOURCE) && ! myDiodeConnections.CheckTerminalMinMaxVoltages(DRAIN) ) {
861 				if ( myDiodeConnections.maxSourceVoltage > 0 && ! myDiodeConnections.maxSourcePower_p->type[HIZ_BIT] ) {
862 					myErrorFlag = true;
863 				}
864 			} else if ( ! myDiodeConnections.CheckTerminalMinMaxVoltages(SOURCE) && myDiodeConnections.CheckTerminalMinMaxVoltages(DRAIN) ) {
865 				if ( myDiodeConnections.minDrainVoltage <= 0 && ! myDiodeConnections.minDrainPower_p->type[HIZ_BIT] ) {
866 					myErrorFlag = true;
867 				}
868 			}
869 			if ( myErrorFlag ) {
870 				if ( IncrementDeviceError(myConnections.deviceId, FORWARD_DIODE) < cvcParameters.cvcCircuitErrorLimit || cvcParameters.cvcCircuitErrorLimit == 0 ) {
871 					if ( myUnrelatedFlag ) {
872 						errorFile << "Unrelated power error" << endl;
873 					}
874 					PrintDeviceWithAllConnections(deviceParent_v[device_it], myConnections, errorFile);
875 					errorFile << endl;
876 				}
877 			}
878 		}
879 	}
880 	cvcCircuitList.PrintAndResetCircuitErrors(this, cvcParameters.cvcCircuitErrorLimit, logFile, errorFile, "! Checking forward bias diode errors: ");
881 }
882 
FindNmosPossibleLeakErrors()883 void CCvcDb::FindNmosPossibleLeakErrors() {
884 	CFullConnection myConnections;
885 	reportFile << "! Checking nmos possible leak errors: " << endl << endl;
886 	errorFile << "! Checking nmos possible leak errors: " << endl << endl;
887 	for ( deviceId_t device_it = 0; device_it < deviceCount; device_it++ ) {
888 		CInstance * myInstance_p = instancePtr_v[deviceParent_v[device_it]];
889 		CCircuit * myParent_p = myInstance_p->master_p;
890 		CDevice * myDevice_p = myParent_p->devicePtr_v[device_it - myInstance_p->firstDeviceId];
891 		if ( ! IsNmos_(myDevice_p->model_p->type) ) continue;
892 		bool myErrorFlag = false;
893 		MapDeviceNets(myInstance_p, myDevice_p, myConnections);
894 		if ( IsKnownVoltage_(myConnections.simGateVoltage) ) continue;
895 		if ( myConnections.CheckTerminalMinVoltages(SOURCE | DRAIN) == true ) {
896 			voltage_t myMaxGateVoltage = MaxVoltage(myConnections.gateId);
897 			if ( myMaxGateVoltage == UNKNOWN_VOLTAGE ) {
898 				myMaxGateVoltage = MaxLeakVoltage(myConnections.gateId);
899 			}
900 			if ( myMaxGateVoltage != UNKNOWN_VOLTAGE
901 					&& myMaxGateVoltage <= myConnections.minSourceVoltage + myConnections.device_p->model_p->Vth
902 					&& myMaxGateVoltage <= myConnections.minDrainVoltage + myConnections.device_p->model_p->Vth ) {
903 				continue;  // always off
904 			}
905 		}
906 		if ( myConnections.CheckTerminalSimVoltages(SOURCE | DRAIN) == true ) {
907 			if ( myConnections.simSourceVoltage == myConnections.simDrainVoltage ) continue;
908 			if ( abs(myConnections.simSourceVoltage - myConnections.simDrainVoltage) <= cvcParameters.cvcLeakErrorThreshold ) continue;
909 			if ( myConnections.simSourcePower_p->type[HIZ_BIT] &&
910 					! myConnections.simSourcePower_p->IsRelatedPower(myConnections.simDrainPower_p, netVoltagePtr_v, simNet_v, simNet_v, false) ) {
911 				;  // possible leaks to cutoff power
912 			} else if ( myConnections.simDrainPower_p->type[HIZ_BIT] &&
913 					! myConnections.simDrainPower_p->IsRelatedPower(myConnections.simSourcePower_p, netVoltagePtr_v, simNet_v, simNet_v, false) ) {
914 				;  // possible leaks to cutoff power
915 			} else if ( myConnections.simSourcePower_p->IsInternalOverride() || myConnections.simDrainPower_p->IsInternalOverride() ) {
916 				continue;
917 			} else if ( myConnections.simSourcePower_p->type[SIM_CALCULATED_BIT] || myConnections.simDrainPower_p->type[SIM_CALCULATED_BIT] ) {
918 				if ( myConnections.EstimatedCurrent() <= cvcParameters.cvcLeakLimit ) continue;
919 			}
920 			myErrorFlag = true;
921 		} else if ( myConnections.EstimatedMinimumCurrent() > cvcParameters.cvcLeakLimit ) {
922 			myErrorFlag = true;
923 		}
924 		if ( myErrorFlag ) {
925 			if ( IncrementDeviceError(myConnections.deviceId, NMOS_POSSIBLE_LEAK) < cvcParameters.cvcCircuitErrorLimit || cvcParameters.cvcCircuitErrorLimit == 0 ) {
926 				PrintDeviceWithAllConnections(deviceParent_v[device_it], myConnections, errorFile);
927 				errorFile << endl;
928 			}
929 		}
930 	}
931 	cvcCircuitList.PrintAndResetCircuitErrors(this, cvcParameters.cvcCircuitErrorLimit, logFile, errorFile, "! Checking nmos possible leak errors: ");
932 }
933 
FindPmosPossibleLeakErrors()934 void CCvcDb::FindPmosPossibleLeakErrors() {
935 	CFullConnection myConnections;
936 	reportFile << "! Checking pmos possible leak errors: " << endl << endl;
937 	errorFile << "! Checking pmos possible leak errors: " << endl << endl;
938 	for ( deviceId_t device_it = 0; device_it < deviceCount; device_it++ ) {
939 		CInstance * myInstance_p = instancePtr_v[deviceParent_v[device_it]];
940 		CCircuit * myParent_p = myInstance_p->master_p;
941 		CDevice * myDevice_p = myParent_p->devicePtr_v[device_it - myInstance_p->firstDeviceId];
942 		if ( ! IsPmos_(myDevice_p->model_p->type) ) continue;
943 		bool myErrorFlag = false;
944 		MapDeviceNets(myInstance_p, myDevice_p, myConnections);
945 		if ( IsKnownVoltage_(myConnections.simGateVoltage) ) continue;
946 		if ( myConnections.CheckTerminalMaxVoltages(SOURCE | DRAIN) == true ) {
947 			voltage_t myMinGateVoltage = MinVoltage(myConnections.gateId);
948 			if ( myMinGateVoltage == UNKNOWN_VOLTAGE ) {
949 				myMinGateVoltage = MinLeakVoltage(myConnections.gateId);
950 			}
951 			if ( myMinGateVoltage != UNKNOWN_VOLTAGE
952 					&& myMinGateVoltage >= myConnections.maxSourceVoltage + myConnections.device_p->model_p->Vth
953 					&& myMinGateVoltage >= myConnections.maxDrainVoltage + myConnections.device_p->model_p->Vth ) {
954 				continue;  // always off
955 			}
956 		}
957 		if ( myConnections.CheckTerminalSimVoltages(SOURCE | DRAIN) == true ) {
958 			if ( myConnections.simSourceVoltage == myConnections.simDrainVoltage ) continue;
959 			if ( abs(myConnections.simSourceVoltage - myConnections.simDrainVoltage) <= cvcParameters.cvcLeakErrorThreshold ) continue;
960 			if ( myConnections.simSourcePower_p->type[HIZ_BIT] &&
961 					! myConnections.simSourcePower_p->IsRelatedPower(myConnections.simDrainPower_p, netVoltagePtr_v, simNet_v, simNet_v, false) ) {
962 				;  // possible leaks to cutoff power
963 			} else if ( myConnections.simDrainPower_p->type[HIZ_BIT] &&
964 					! myConnections.simDrainPower_p->IsRelatedPower(myConnections.simSourcePower_p, netVoltagePtr_v, simNet_v, simNet_v, false) ) {
965 				;  // possible leaks to cutoff power
966 			} else if ( myConnections.simSourcePower_p->IsInternalOverride() || myConnections.simDrainPower_p->IsInternalOverride() ) {
967 				continue;
968 			} else if ( myConnections.simSourcePower_p->type[SIM_CALCULATED_BIT] || myConnections.simDrainPower_p->type[SIM_CALCULATED_BIT] ) {
969 				if ( myConnections.EstimatedCurrent() <= cvcParameters.cvcLeakLimit ) continue;
970 			}
971 			myErrorFlag = true;
972 		} else if ( myConnections.EstimatedMinimumCurrent() > cvcParameters.cvcLeakLimit ) {
973 			myErrorFlag = true;
974 		}
975 		if ( myErrorFlag ) {
976 			if ( IncrementDeviceError(myConnections.deviceId, PMOS_POSSIBLE_LEAK) < cvcParameters.cvcCircuitErrorLimit || cvcParameters.cvcCircuitErrorLimit == 0 ) {
977 				PrintDeviceWithAllConnections(deviceParent_v[device_it], myConnections, errorFile);
978 				errorFile << endl;
979 			}
980 		}
981 	}
982 	cvcCircuitList.PrintAndResetCircuitErrors(this, cvcParameters.cvcCircuitErrorLimit, logFile, errorFile, "! Checking pmos possible leak errors: ");
983 }
984 
FindFloatingInputErrors()985 void CCvcDb::FindFloatingInputErrors() {
986 	CFullConnection myConnections;
987 	reportFile << "! Checking mos floating input errors:" << endl << endl;
988 	errorFile << "! Checking mos floating input errors:" << endl << endl;
989 	bool myFloatingFlag;
990 	for (netId_t net_it = 0; net_it < netCount; net_it++) {
991 		if ( connectionCount_v[net_it].gateCount > 0 ) { // skips subordinate nets. only equivalent master nets have counts
992 			if ( firstGate_v[net_it] == UNKNOWN_DEVICE ) continue;
993 			MapDeviceNets(firstGate_v[net_it], myConnections);
994 			if ( myConnections.simGateVoltage != UNKNOWN_VOLTAGE ) continue;  // skip known voltages
995 			myFloatingFlag = IsFloatingGate(myConnections);
996 			if ( myFloatingFlag || myConnections.IsPossibleHiZ(this) ) {
997 				for ( deviceId_t device_it = firstGate_v[net_it]; device_it != UNKNOWN_DEVICE; device_it = nextGate_v[device_it] ) {
998 					MapDeviceNets(device_it, myConnections);
999 					bool myHasLeakPath = HasLeakPath(myConnections);
1000 					if ( myFloatingFlag ) {
1001 						deviceStatus_v[device_it][SIM_INACTIVE] = true;  // ignore true floating input gates (not possible floating)
1002 					}
1003 					if ( cvcParameters.cvcIgnoreVthFloating && IsAlwaysOff(myConnections) ) continue;  // skips Hi-Z input that is never on
1004 					if ( ! myHasLeakPath && cvcParameters.cvcIgnoreNoLeakFloating
1005 							&& connectionCount_v[net_it].SourceDrainCount() == 0 ) continue;  // skip no leak floating
1006 					if ( myHasLeakPath || connectionCount_v[net_it].SourceDrainCount() == 0 ) {  // physically floating gates too
1007 						if ( IncrementDeviceError(myConnections.deviceId, HIZ_INPUT) < cvcParameters.cvcCircuitErrorLimit || cvcParameters.cvcCircuitErrorLimit == 0 ) {
1008 							if ( ! myHasLeakPath ) errorFile << "* No leak path" << endl;
1009 							if ( ! myFloatingFlag ) errorFile << "* Tri-state input" << endl;
1010 							PrintDeviceWithAllConnections(deviceParent_v[device_it], myConnections, errorFile);
1011 							errorFile << endl;
1012 						}
1013 					}
1014 				}
1015 			}
1016 		}
1017 	}
1018 	for (netId_t net_it = 0; net_it < netCount; net_it++) {  // second pass to catch floating nets caused by floating nets
1019 		if ( connectionCount_v[net_it].gateCount > 0 ) { // skips subordinate nets. only equivalent master nets have counts
1020 			if ( firstGate_v[net_it] == UNKNOWN_DEVICE ) continue;
1021 			if ( SimVoltage(net_it) != UNKNOWN_VOLTAGE || (netVoltagePtr_v[net_it].full && netVoltagePtr_v[net_it].full->type[INPUT_BIT]) ) continue;
1022 			if ( HasActiveConnections(net_it) ) continue;
1023 			MapDeviceNets(firstGate_v[net_it], myConnections);
1024 			if ( IsFloatingGate(myConnections) ) continue;  // Already processed previously
1025 			for ( deviceId_t device_it = firstGate_v[net_it]; device_it != UNKNOWN_DEVICE; device_it = nextGate_v[device_it] ) {
1026 				MapDeviceNets(device_it, myConnections);
1027 				bool myHasLeakPath = HasLeakPath(myConnections);
1028 				if ( myHasLeakPath ) {
1029 					if ( IncrementDeviceError(myConnections.deviceId, HIZ_INPUT) < cvcParameters.cvcCircuitErrorLimit || cvcParameters.cvcCircuitErrorLimit == 0 ) {
1030 						errorFile << "* Secondary HI-Z error" << endl;
1031 						PrintDeviceWithAllConnections(deviceParent_v[device_it], myConnections, errorFile);
1032 						errorFile << endl;
1033 					}
1034 				}
1035 			}
1036 		}
1037 	}
1038 	cvcCircuitList.PrintAndResetCircuitErrors(this, cvcParameters.cvcCircuitErrorLimit, logFile, errorFile, "! Checking mos floating input errors:");
1039 }
1040 
CheckExpectedValues()1041 void CCvcDb::CheckExpectedValues() {
1042 	CFullConnection myConnections;
1043 	netId_t myNetId, mySimNetId, myMinNetId, myMaxNetId;
1044 //	voltage_t mySimVoltage, myMinVoltage, myMaxVoltage;
1045 	CVirtualNet mySimNet, myMinNet, myMaxNet;
1046 	bool myExpectedValueFound;
1047 	reportFile << "! Checking expected values:" << endl << endl;
1048 	errorFile << "! Checking expected values:" << endl << endl;
1049 	// Expected voltage errors do not respect error limit
1050 	for (auto power_ppit = cvcParameters.cvcExpectedLevelPtrList.begin(); power_ppit != cvcParameters.cvcExpectedLevelPtrList.end(); power_ppit++) {
1051 		size_t myLastErrorCount = errorCount[EXPECTED_VOLTAGE];
1052 		myNetId = GetEquivalentNet((*power_ppit)->netId);
1053 		if ( ! IsEmpty((*power_ppit)->expectedSim()) ) {
1054 			mySimNet(simNet_v, myNetId);
1055 			mySimNetId = mySimNet.finalNetId;
1056 			myExpectedValueFound = false;
1057 			myMinNet(minNet_v, myNetId);
1058 			myMinNetId = myMinNet.finalNetId;
1059 			myMaxNet(maxNet_v, myNetId);
1060 			myMaxNetId = myMaxNet.finalNetId;
1061 			if ( (*power_ppit)->expectedSim() == "open" ) {
1062 				if ( ( mySimNetId == UNKNOWN_NET || ! netVoltagePtr_v[mySimNetId].full || netVoltagePtr_v[mySimNetId].full->simVoltage == UNKNOWN_VOLTAGE ) &&
1063 						( myMinNetId == UNKNOWN_NET || ! netVoltagePtr_v[myMinNetId].full || netVoltagePtr_v[myMinNetId].full->minVoltage == UNKNOWN_VOLTAGE || netVoltagePtr_v[myMinNetId].full->type[HIZ_BIT] ||
1064 							myMaxNetId == UNKNOWN_NET || ! netVoltagePtr_v[myMaxNetId].full || netVoltagePtr_v[myMaxNetId].full->maxVoltage == UNKNOWN_VOLTAGE || netVoltagePtr_v[myMaxNetId].full->type[HIZ_BIT]) ) { // open match
1065 					myExpectedValueFound = true;
1066 				}
1067 			} else if ( mySimNetId != UNKNOWN_NET && netVoltagePtr_v[mySimNetId].full && netVoltagePtr_v[mySimNetId].full->simVoltage != UNKNOWN_VOLTAGE ) {
1068 				if ( IsValidVoltage_((*power_ppit)->expectedSim())
1069 						&& abs(String_to_Voltage((*power_ppit)->expectedSim()) - netVoltagePtr_v[mySimNetId].full->simVoltage) <= cvcParameters.cvcExpectedErrorThreshold ) { // voltage match
1070 					myExpectedValueFound = true;
1071 				} else if ( (*power_ppit)->expectedSim() == NetName(mySimNetId) ) { // name match
1072 					myExpectedValueFound = true;
1073 				} else if ( (*power_ppit)->expectedSim() == string(netVoltagePtr_v[mySimNetId].full->powerAlias()) ) { // alias match
1074 					myExpectedValueFound = true;
1075 				}
1076 				if ( ! myExpectedValueFound ) {
1077 					debugFile << "EXPECT: " << NetName(myNetId) << " " << NetName(mySimNetId) << "@" << netVoltagePtr_v[mySimNetId].full->simVoltage << "~>" << netVoltagePtr_v[mySimNetId].full->powerAlias() << " = " << (*power_ppit)->expectedSim() << endl;
1078 				}
1079 			}
1080 			if ( ! myExpectedValueFound ) {
1081 				errorCount[EXPECTED_VOLTAGE]++;
1082 				errorFile << "Expected " << NetName(myNetId) << " = " << (*power_ppit)->expectedSim() << " but found ";
1083 				if ( mySimNetId != UNKNOWN_NET && netVoltagePtr_v[mySimNetId].full && netVoltagePtr_v[mySimNetId].full->simVoltage != UNKNOWN_VOLTAGE ) {
1084 					errorFile << NetName(mySimNetId) << "@" << PrintVoltage(netVoltagePtr_v[mySimNetId].full->simVoltage) << endl;
1085 				} else if ( (*power_ppit)->expectedSim() == "open" ) {
1086 					bool myPrintedReason = false;
1087 					if ( myMinNetId != UNKNOWN_NET && netVoltagePtr_v[myMinNetId].full && netVoltagePtr_v[myMinNetId].full->minVoltage != UNKNOWN_VOLTAGE ) {
1088 						errorFile << "(min)" << NetName(myMinNetId) << "@" << PrintVoltage(netVoltagePtr_v[myMinNetId].full->minVoltage) << " ";
1089 						myPrintedReason = true;
1090 					}
1091 					if ( myMaxNetId != UNKNOWN_NET && netVoltagePtr_v[myMaxNetId].full && netVoltagePtr_v[myMaxNetId].full->maxVoltage != UNKNOWN_VOLTAGE ) {
1092 						errorFile << "(max)" << NetName(myMaxNetId) << "@" << PrintVoltage(netVoltagePtr_v[myMaxNetId].full->maxVoltage);
1093 						myPrintedReason = true;
1094 					}
1095 					if ( myPrintedReason ) {
1096 						errorFile << endl;
1097 					} else {
1098 						errorFile << "unknown" << endl;
1099 					}
1100 				} else {
1101 					errorFile << "unknown" << endl;
1102 				}
1103 			}
1104 		}
1105 		if ( ! IsEmpty((*power_ppit)->expectedMin()) ) {
1106 			myMinNet(minNet_v, myNetId);
1107 			myMinNetId = myMinNet.finalNetId;
1108 			myExpectedValueFound = false;
1109 			if ( (*power_ppit)->expectedMin() == "open" ) {
1110 				// simVoltage in the following condition is correct. open voltages can have min/max voltages.
1111 				if ( myMinNetId == UNKNOWN_NET || ! netVoltagePtr_v[myMinNetId].full || netVoltagePtr_v[myMinNetId].full->simVoltage == UNKNOWN_VOLTAGE ) { // open match
1112 					myExpectedValueFound = true;
1113 				}
1114 			} else if ( myMinNetId != UNKNOWN_NET && netVoltagePtr_v[myMinNetId].full ) {
1115 				if ( String_to_Voltage((*power_ppit)->expectedMin()) <= netVoltagePtr_v[myMinNetId].full->minVoltage ) { // voltage match (anything higher than expected is ok)
1116 					myExpectedValueFound = true;
1117 				} else if ( (*power_ppit)->expectedMin() == NetName(myMinNetId) ) { // name match
1118 					myExpectedValueFound = true;
1119 				} else if ( (*power_ppit)->expectedMin() == string(netVoltagePtr_v[myMinNetId].full->powerAlias()) ) { // alias match
1120 					myExpectedValueFound = true;
1121 				}
1122 			}
1123 			if ( ! myExpectedValueFound ) {
1124 				errorCount[EXPECTED_VOLTAGE]++;
1125 				errorFile << "Expected minimum " << NetName(myNetId) << " = " << (*power_ppit)->expectedMin() << " but found ";
1126 				if ( myMinNetId != UNKNOWN_NET && netVoltagePtr_v[myMinNetId].full && netVoltagePtr_v[myMinNetId].full->minVoltage != UNKNOWN_VOLTAGE ) {
1127 					errorFile << NetName(myMinNetId) << "@" << PrintVoltage(netVoltagePtr_v[myMinNetId].full->minVoltage) << endl;
1128 				} else {
1129 					errorFile << "unknown" << endl;
1130 				}
1131 			}
1132 		}
1133 		if ( ! IsEmpty((*power_ppit)->expectedMax()) ) {
1134 			myMaxNet(maxNet_v, myNetId);
1135 			myMaxNetId = myMaxNet.finalNetId;
1136 			myExpectedValueFound = false;
1137 			if ( (*power_ppit)->expectedMax() == "open" ) {
1138 				// simVoltage in the following condition is correct. open voltages can have min/max voltages.
1139 				if ( myMaxNetId == UNKNOWN_NET || ! netVoltagePtr_v[myMaxNetId].full || netVoltagePtr_v[myMaxNetId].full->simVoltage == UNKNOWN_VOLTAGE ) { // open match
1140 					myExpectedValueFound = true;
1141 				}
1142 			} else if ( myMaxNetId != UNKNOWN_NET && netVoltagePtr_v[myMaxNetId].full ) {
1143 				if ( String_to_Voltage((*power_ppit)->expectedMax()) >= netVoltagePtr_v[myMaxNetId].full->maxVoltage ) { // voltage match (anything lower than expected is ok)
1144 					myExpectedValueFound = true;
1145 				} else if ( (*power_ppit)->expectedMax() == NetName(myMaxNetId) ) { // name match
1146 					myExpectedValueFound = true;
1147 				} else if ( (*power_ppit)->expectedMax() == string(netVoltagePtr_v[myMaxNetId].full->powerAlias()) ) { // alias match
1148 					myExpectedValueFound = true;
1149 				}
1150 			}
1151 			if ( ! myExpectedValueFound ) {
1152 				errorCount[EXPECTED_VOLTAGE]++;
1153 				errorFile << "Expected maximum " << NetName(myNetId) << " = " << (*power_ppit)->expectedMax() << " but found ";
1154 				if ( myMaxNetId != UNKNOWN_NET && netVoltagePtr_v[myMaxNetId].full && netVoltagePtr_v[myMaxNetId].full->maxVoltage != UNKNOWN_VOLTAGE ) {
1155 					errorFile << NetName(myMaxNetId) << "@" << PrintVoltage(netVoltagePtr_v[myMaxNetId].full->maxVoltage) << endl;
1156 				} else {
1157 					errorFile << "unknown" << endl;
1158 				}
1159 			}
1160 		}
1161 		if ( myLastErrorCount != errorCount[EXPECTED_VOLTAGE] ) errorFile << endl;
1162 	}
1163 	errorFile << "! Finished" << endl << endl;
1164 }
1165 
FindLDDErrors()1166 void CCvcDb::FindLDDErrors() {
1167 	CFullConnection myConnections;
1168 	for (CModelListMap::iterator keyModelListPair_pit = cvcParameters.cvcModelListMap.begin(); keyModelListPair_pit != cvcParameters.cvcModelListMap.end(); keyModelListPair_pit++) {
1169 		for (CModelList::iterator model_pit = keyModelListPair_pit->second.begin(); model_pit != keyModelListPair_pit->second.end(); model_pit++) {
1170 			if ( model_pit->type == LDDN || model_pit->type == LDDP ) {
1171 				reportFile << "! Checking LDD errors for model: " << model_pit->definition << endl << endl;
1172 				errorFile << "! Checking LDD errors for model: " << model_pit->definition << endl << endl;
1173 				CDevice * myDevice_p = model_pit->firstDevice_p;
1174 				while (myDevice_p) {
1175 					CCircuit * myParent_p = myDevice_p->parent_p;
1176 	//				deviceId_t myLocalDeviceId = myParent_p->localDeviceIdMap[myDevice_p->name];
1177 					for (instanceId_t instance_it = 0; instance_it < myParent_p->instanceId_v.size(); instance_it++) {
1178 						if  ( instancePtr_v[myParent_p->instanceId_v[instance_it]]->IsParallelInstance() ) continue;  // parallel/empty instances
1179 						CInstance * myInstance_p = instancePtr_v[myParent_p->instanceId_v[instance_it]];
1180 						MapDeviceNets(myInstance_p, myDevice_p, myConnections);
1181 						if ( model_pit->type == LDDN ) {
1182 							if ( ! myConnections.CheckTerminalMinMaxVoltages(SOURCE | DRAIN, true) ) continue;
1183 							if ( myConnections.maxSourceVoltage <= myConnections.minDrainVoltage ) continue;
1184 							if ( myConnections.minSourceVoltage > myConnections.minDrainVoltage ||
1185 									( myConnections.minSourceVoltage == myConnections.minDrainVoltage &&
1186 										myConnections.masterMinSourceNet.finalResistance > myConnections.masterMinDrainNet.finalResistance ) ||
1187 									myConnections.maxSourceVoltage > myConnections.maxDrainVoltage ||
1188 									( myConnections.maxSourceVoltage == myConnections.maxDrainVoltage &&
1189 										myConnections.masterMaxSourceNet.finalResistance < myConnections.masterMaxDrainNet.finalResistance &&
1190 										myConnections.minSourceVoltage != myConnections.maxDrainVoltage && // if min = max -> no leak regardless of resistance
1191 //										myConnections.masterMaxSourceNet.finalNetId != myConnections.masterMaxDrainNet.finalNetId &&
1192 										myConnections.masterMaxDrainNet.nextNetId != GetEquivalentNet(myConnections.sourceId)) ) { // NMOS max voltage resistance check is intentionally backwards
1193 								if ( !( IsKnownVoltage_(myConnections.simGateVoltage) &&
1194 										myConnections.simGateVoltage <= min(myConnections.minSourceVoltage, myConnections.minDrainVoltage) ) ) {
1195 									if ( IncrementDeviceError(myConnections.deviceId, LDD_SOURCE) < cvcParameters.cvcCircuitErrorLimit || cvcParameters.cvcCircuitErrorLimit == 0 ) {
1196 										PrintDeviceWithAllConnections(myParent_p->instanceId_v[instance_it], myConnections, errorFile);
1197 										errorFile << endl;
1198 									}
1199 								}
1200 							}
1201 						} else {
1202 							assert( model_pit->type == LDDP );
1203 							if ( ! myConnections.CheckTerminalMinMaxVoltages(SOURCE | DRAIN, true) ) continue;
1204 							if ( myConnections.minSourceVoltage >= myConnections.maxDrainVoltage ) continue;
1205 							if ( myConnections.maxSourceVoltage < myConnections.maxDrainVoltage ||
1206 									( myConnections.maxSourceVoltage == myConnections.maxDrainVoltage &&
1207 										myConnections.masterMaxSourceNet.finalResistance > myConnections.masterMaxDrainNet.finalResistance ) ||
1208 									myConnections.minSourceVoltage < myConnections.minDrainVoltage ||
1209 									( myConnections.minSourceVoltage == myConnections.minDrainVoltage &&
1210 										myConnections.masterMinSourceNet.finalResistance < myConnections.masterMinDrainNet.finalResistance &&
1211 										myConnections.maxSourceVoltage != myConnections.minDrainVoltage && // if max = min -> no leak regardless of resistance
1212 //										myConnections.masterMinSourceNet.finalNetId != myConnections.masterMinDrainNet.finalNetId &&
1213 										myConnections.masterMinDrainNet.nextNetId != GetEquivalentNet(myConnections.sourceId)) ) { // PMOS max voltage resistance check is intentionally backwards
1214 								if ( !( IsKnownVoltage_(myConnections.simGateVoltage) &&
1215 										myConnections.simGateVoltage >= max(myConnections.maxSourceVoltage, myConnections.maxDrainVoltage) ) ) {
1216 									if ( IncrementDeviceError(myConnections.deviceId, LDD_SOURCE) < cvcParameters.cvcCircuitErrorLimit || cvcParameters.cvcCircuitErrorLimit == 0 ) {
1217 										PrintDeviceWithAllConnections(myParent_p->instanceId_v[instance_it], myConnections, errorFile);
1218 										errorFile << endl;
1219 									}
1220 								}
1221 							}
1222 						}
1223 					}
1224 					myDevice_p = myDevice_p->nextDevice_p;
1225 				}
1226 			}
1227 		}
1228 	}
1229 	cvcCircuitList.PrintAndResetCircuitErrors(this, cvcParameters.cvcCircuitErrorLimit, logFile, errorFile, "! Checking LDD errors for model: ");
1230 }
1231 
CheckInverterIO(modelType_t theType)1232 void CCvcDb::CheckInverterIO(modelType_t theType) {
1233 	// Checks nets loaded from cvcNetCheckFile
1234 	for ( auto check_pit = inverterInputOutputCheckList.begin(); check_pit != inverterInputOutputCheckList.end(); check_pit++ ) {
1235 		debugFile << "DEBUG: inverter input output check " << *check_pit << endl;
1236 		set<netId_t> * myNetIdList = FindUniqueNetIds(*check_pit);
1237 		CVirtualNet myMinInput;
1238 		CVirtualNet myMaxInput;
1239 		CVirtualNet myMinOutput;
1240 		CVirtualNet myMaxOutput;
1241 		for ( auto net_pit = myNetIdList->begin(); net_pit != myNetIdList->end(); net_pit++ ) {
1242 			netId_t myInverterInput = FindInverterInput(*net_pit);
1243 			if ( myInverterInput == UNKNOWN_NET ) {
1244 				myInverterInput = inverterNet_v[*net_pit];
1245 				reportFile << "INFO: Couldn't calculate inverter input for " << NetName(*net_pit, true) << endl;
1246 			}
1247 			if (myInverterInput == UNKNOWN_NET) {
1248 				reportFile << "Warning: expected inverter input at " << NetName(*net_pit, true) << endl;
1249 				continue;
1250 
1251 			}
1252 			myMinInput(minNet_v, myInverterInput);
1253 			myMaxInput(maxNet_v, myInverterInput);
1254 			myMinOutput(minNet_v, *net_pit);
1255 			myMaxOutput(maxNet_v, *net_pit);
1256 			if ( myMinInput.finalNetId == myMaxInput.finalNetId
1257 					&& ( myMinInput.finalNetId == myMinOutput.finalNetId
1258 						|| myMaxInput.finalNetId == myMaxOutput.finalNetId ) ) continue;  // input is tied to matching power.
1259 
1260 			if ( ( myMinInput.finalNetId != myMinOutput.finalNetId && theType == NMOS )
1261 					|| ( myMaxInput.finalNetId != myMaxOutput.finalNetId && theType == PMOS ) ) {
1262 				deviceId_t myDevice = FindInverterDevice(myInverterInput, *net_pit, theType);
1263 				if ( myDevice == UNKNOWN_DEVICE ) {
1264 					reportFile << "Warning: could not find inverter device for " << NetName(*net_pit, true) << endl;
1265 					continue;
1266 
1267 				}
1268 				if ( IncrementDeviceError(myDevice, (theType == NMOS ? NMOS_GATE_SOURCE : PMOS_GATE_SOURCE)) < cvcParameters.cvcCircuitErrorLimit || cvcParameters.cvcCircuitErrorLimit == 0 ) {
1269 					CFullConnection myFullConnections;
1270 					MapDeviceNets(myDevice, myFullConnections);
1271 					errorFile << "* inverter input/output mismatch" << endl;
1272 					PrintDeviceWithAllConnections(deviceParent_v[myDevice], myFullConnections, errorFile);
1273 					errorFile << endl;
1274 				}
1275 			}
1276 		}
1277 	}
1278 }
1279 
CheckOppositeLogic(modelType_t theType)1280 void CCvcDb::CheckOppositeLogic(modelType_t theType) {
1281 	for ( auto check_pit = oppositeLogicList.begin(); check_pit != oppositeLogicList.end(); check_pit++ ) {
1282 		debugFile << "DEBUG: opposite logic check " << get<0>(*check_pit) << " & " << get<1>(*check_pit) << endl;
1283 		forward_list<netId_t> * myNetIdList = FindNetIds(get<0>(*check_pit));
1284 		forward_list<netId_t> * myOppositeNetIdList = FindNetIds(get<1>(*check_pit));
1285 		for ( auto net_pit = myNetIdList->begin(), opposite_pit = myOppositeNetIdList->begin(); net_pit != myNetIdList->end(); net_pit++, opposite_pit++ ) {
1286 			CPower * myFirstPower_p = netVoltagePtr_v[GetEquivalentNet(*net_pit)].full;
1287 			CPower * mySecondPower_p = netVoltagePtr_v[GetEquivalentNet(*opposite_pit)].full;
1288 			if ( myFirstPower_p && mySecondPower_p && IsPower_(myFirstPower_p) && IsPower_(mySecondPower_p)
1289 				&& myFirstPower_p->simVoltage != mySecondPower_p->simVoltage ) continue;  // ignore direct connections to different power
1290 
1291 			unordered_set<netId_t> myInvertedNets;
1292 			unordered_set<netId_t> mySameLogicNets;
1293 			netId_t net_it = GetEquivalentNet(*net_pit);
1294 			// make sets of same logic nets and opposite logic nets for first nets
1295 			bool myInverted = false;
1296 			logFile << "Checking " << NetName(net_it, true) << endl;
1297 			while ( net_it != UNKNOWN_NET && mySameLogicNets.count(net_it) == 0 ) {
1298 				if ( myInverted ) {
1299 					myInvertedNets.insert(net_it);
1300 					assert(myInvertedNets.count(inverterNet_v[net_it]) == 0);  // oscillators
1301 
1302 				} else {
1303 					mySameLogicNets.insert(net_it);
1304 					assert(mySameLogicNets.count(inverterNet_v[net_it]) == 0);  // oscillators
1305 
1306 				}
1307 				myInverted = ! myInverted;
1308 				net_it = inverterNet_v[net_it];
1309 			}
1310 			// check second net against first net to find opposite logic
1311 			myInverted = true;
1312 			net_it = GetEquivalentNet(*opposite_pit);
1313 			while ( net_it != UNKNOWN_NET
1314 					&& ( (myInverted && myInvertedNets.count(net_it) == 0)
1315 						|| (! myInverted && mySameLogicNets.count(net_it) == 0) ) ) {
1316 				net_it = inverterNet_v[net_it];
1317 				myInverted = ! myInverted;
1318 			}
1319 			if ( net_it != UNKNOWN_NET ) continue;  // nets are opposite
1320 
1321 			netId_t myErrorNet = (myFirstPower_p && IsPower_(myFirstPower_p)) ? GetEquivalentNet(*opposite_pit) : GetEquivalentNet(*net_pit);
1322 			int myErrorCount = 0;
1323 			for ( auto device_it = firstGate_v[myErrorNet]; device_it != UNKNOWN_DEVICE; device_it = nextGate_v[device_it]) {
1324 				if ( sourceNet_v[device_it] == drainNet_v[device_it] ) continue;  // ignore inactive devices
1325 
1326 				if ( theType == PMOS && ! IsPmos_(deviceType_v[device_it]) ) continue;  // ignore wrong types
1327 
1328 				if ( theType == NMOS && ! IsNmos_(deviceType_v[device_it]) ) continue;  // ignore wrong types
1329 
1330 				myErrorCount++;
1331 				if ( IncrementDeviceError(device_it, HIZ_INPUT) < cvcParameters.cvcCircuitErrorLimit || cvcParameters.cvcCircuitErrorLimit == 0 ) {
1332 					CFullConnection myFullConnections;
1333 					MapDeviceNets(device_it, myFullConnections);
1334 					errorFile << "* opposite logic required " << get<0>(*check_pit) << " & " << get<1>(*check_pit) << endl;
1335 					PrintDeviceWithAllConnections(deviceParent_v[device_it], myFullConnections, errorFile);
1336 					errorFile << endl;
1337 				}
1338 			}
1339 			if ( myErrorCount == 0 ) {
1340 				reportFile << "Warning: No errors printed for opposite logic check at " << get<0>(*check_pit) << " & " << get<1>(*check_pit);
1341 				reportFile << " for net " << NetName(*net_pit, true) << endl;
1342 			}
1343 		}
1344 	}
1345 }
1346