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