1 /*
2  * CCvcDb_main.cc
3  *
4  * Copyright 2014-2018 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 "Cvc.hh"
25 #include "CCdlParserDriver.hh"
26 #include "CCvcParameters.hh"
27 #include "CCircuit.hh"
28 #include "CCvcDb.hh"
29 
30 #include "CDevice.hh"
31 #include "resource.hh"
32 
33 /// \file
34 /// CVC main loop
35 
36 /// \name interactive globals
37 ///@{
38 bool gInteractive_cvc = false; //!< interactive mode
39 int gContinueCount = 0; //!< number of stages to run before stopping; always stop after final stage
40 ///@}
41 
42 rusage lastSnapshot; //!< resource usage tracking
43 
44 // debugging variables for virtual net updates
45 long gVirtualNetAccessCount = 0;
46 long gVirtualNetUpdateCount = 0;
47 
48 /**
49  * \brief Main Loop: Verify circuits using settings in each verification resource file.
50  *
51  * Verification resource files typically have a .cvcrc suffix.
52  */
VerifyCircuitForAllModes(int argc,const char * argv[])53 void CCvcDb::VerifyCircuitForAllModes(int argc, const char * argv[]) {
54 	CCdlParserDriver cvcParserDriver;
55 
56 	cvcParameters.PrintDefaultEnvironment();
57 	for ( ; cvcArgIndex < argc; cvcArgIndex++ ) { // loop through all cvcrc files on command line
58 /// Setup
59 		gContinueCount = 0;
60 		if ( ! cvcParameters.cvcPowerPtrList.empty() ) Cleanup();
61 		RemoveLock();
62 		detectErrorFlag = true;
63 		cout << "CVC: Circuit Validation Check  Version " << CVC_VERSION << endl;
64 		cvcParameters.ResetEnvironment();
65 		cvcParameters.LoadEnvironment(argv[cvcArgIndex], reportPrefix);
66 		if ( ! LockReport(gInteractive_cvc) ) continue;
67 		SetOutputFiles(cvcParameters.cvcReportFilename);
68 		logFile << "CVC: Circuit Validation Check  Version " << CVC_VERSION << endl;
69 		reportFile << "CVC: Start: " << CurrentTime() << endl;
70 		TakeSnapshot(&lastSnapshot);
71 		cvcParameters.PrintEnvironment(reportFile);
72 ///	Read model and power settings.
73 		modelFileStatus = cvcParameters.LoadModels();
74 		powerFileStatus = cvcParameters.LoadPower();
75 		if ( modelFileStatus != OK || powerFileStatus != OK ) { // Catch syntax problems before reading netlist
76 			if ( ! gInteractive_cvc ) {
77 				reportFile << "ERROR: skipped due to problems in model/power files" << endl;
78 				continue;
79 			}
80 		}
81 
82 /// Read netlist
83 		if ( cvcParameters.IsSameDatabase() ) {
84 			reportFile << "CVC: Reusing " << cvcParameters.cvcTopBlock << " of "
85 					<< cvcParameters.cvcNetlistFilename << endl;
86 			// TODO: Reset error limits for cells
87 /*
88 			if ( isDeviceModelSet ) {
89 				ResetMosFuse();
90 			}
91 */
92 		} else {
93 			reportFile << "CVC: Parsing netlist " << cvcParameters.cvcNetlistFilename << endl;
94 			cvcCircuitList.Clear();
95 			instancePtr_v.Clear();
96 			if (cvcParserDriver.parse (cvcParameters.cvcNetlistFilename, cvcCircuitList,
97 					cvcParameters.cvcSOI ) != 0 ) {
98 				throw EFatalError("Could not parse " + cvcParameters.cvcNetlistFilename);
99 			}
100 			if (cvcCircuitList.errorCount > 0 || cvcCircuitList.warningCount > 0) {
101 				reportFile << "WARNING: unsupported devices in netlist" << endl;
102 			}
103 			cvcParameters.SaveDatabaseParameters();
104 			reportFile << "Cdl fixed data size " << cvcCircuitList.cdlText.Size() << endl;
105 			reportFile << PrintProgress(&lastSnapshot, "CDL") << endl;
106 			LoadCellChecksums();
107 			CountObjectsAndLinkSubcircuits();
108 			AssignGlobalIDs();
109 			LoadNetChecks();
110 			LoadModelChecks();
111 			PrintLargeCircuits();
112 			reportFile << PrintProgress(&lastSnapshot, "DB") << endl;
113 		}
114 		returnCode_t myCellErrorLimitStatus = LoadCellErrorLimits();
115 		if ( myCellErrorLimitStatus != OK ) {
116 			throw EFatalError("Could not load " + cvcParameters.cvcCellErrorLimitFile);
117 		}
118 		reportFile << "CVC: " << topCircuit_p->subcircuitCount << "(" << subcircuitCount << ") instances, "
119 			<< topCircuit_p->netCount << "(" << netCount << ") nets, "
120 			<< topCircuit_p->deviceCount << "(" << deviceCount << ") devices." << endl;
121 
122 /// Stage 1) Set power and model
123 		if ( powerFileStatus == OK ) {
124 			cout << "Setting power for mode..." << endl;
125 			powerFileStatus = SetModePower();
126 		}
127 		if ( modelFileStatus == OK ) {
128 			cout << "Setting models..." << endl;
129 			modelFileStatus = SetDeviceModels();
130 		}
131 		if ( modelFileStatus == OK ) {
132 			fuseFileStatus = CheckFuses();
133 		} else {
134 			fuseFileStatus = FAIL;
135 		}
136 		if ( gInteractive_cvc && --gContinueCount < 1
137 				&& InteractiveCvc(STAGE_START) == SKIP ) continue;
138 		if ( modelFileStatus != OK || powerFileStatus != OK || fuseFileStatus != OK ) {
139 			if ( gSetup_cvc ) {
140 				reportFile << endl << "CVC: Setup check complete." << endl;
141 			} else {
142 				reportFile << "ERROR: skipped due to problems in model/power/fuse files" << endl;
143 			}
144 			continue;
145 		}
146 
147 /// Stage 2) Create database
148 		ResetMinSimMaxAndQueues();
149 		SetEquivalentNets();
150 		if ( SetInstancePower() != OK || SetExpectedPower() != OK ) {
151 			reportFile << "ERROR: skipped due to problems in power files" << endl;
152 			continue;
153 		}
154 		cvcParameters.cvcPowerPtrList.SetFamilies(cvcParameters.cvcPowerFamilyMap);
155 		cvcParameters.SetHiZPropagation();
156 		cvcParameters.cvcModelListMap.Print(logFile);
157 		PrintPowerList(logFile, "Power List");
158 		cvcParameters.cvcPowerPtrList.SetPowerLimits(maxPower, minPower);
159 		LinkDevices();
160 		OverrideFuses();
161 		mosDiodeSet.clear();
162 		if ( gSetup_cvc ) {
163 			PrintNetSuggestions();
164 		}
165 		reportFile << PrintProgress(&lastSnapshot, "EQUIV") << endl;
166 		reportFile << "Power nets " << CPower::powerCount << endl;
167 //		DumpStatistics(parameterModelPtrMap, "parameter->model map", logFile);
168 		DumpStatistics(parameterResistanceMap, "parameter->resistance map", logFile);
169 		DumpStatistics(cvcCircuitList.circuitNameMap, "text->circuit map", logFile);
170 		DumpStatistics(cvcCircuitList.cdlText.fixedTextToAddressMap, "string->text map", logFile);
171 		if ( gInteractive_cvc && --gContinueCount < 1 && InteractiveCvc(STAGE_LINK) == SKIP ) {
172 			continue;
173 		}
174 
175 /// Stage 3) Calculate voltages across resistors
176 /// - Calculated resistance
177 		ShortNonConductingResistors();
178 //		SetResistorVoltagesForMosSwitches();
179 		SetResistorVoltagesByPower();
180 		reportFile << PrintProgress(&lastSnapshot, "RES") << endl;
181 		reportFile << "Power nets " << CPower::powerCount << endl;
182 		if ( gInteractive_cvc && --gContinueCount < 1
183 				&& InteractiveCvc(STAGE_RESISTANCE) == SKIP ) continue;
184 
185 /// Stage 4) First min/max propagation\n
186 /// - unexpected min/max values\n
187 /// - forward bias diode errors\n
188 /// - NMOS source-bulk errors\n
189 /// - NMOS gate-source errors\n
190 /// - PMOS source-bulk errors\n
191 /// - PMOS gate-source errors\n
192 		ResetMinMaxPower();
193 		SetAnalogNets();
194 		reportFile << PrintProgress(&lastSnapshot, "MIN/MAX1") << endl;
195 		reportFile << "Power nets " << CPower::powerCount << endl;
196 		if ( detectErrorFlag ) {
197 			if ( ! cvcParameters.cvcLogicDiodes ) {
198 				FindForwardBiasDiodes();
199 			}
200 			if ( ! cvcParameters.cvcSOI ) {
201 				FindNmosSourceVsBulkErrors();
202 			}
203 			if ( ! gSetup_cvc ) {
204 				FindNmosGateVsSourceErrors();
205 			}
206 			if ( ! cvcParameters.cvcSOI ) {
207 				FindPmosSourceVsBulkErrors();
208 			}
209 			if ( ! gSetup_cvc ) {
210 				FindPmosGateVsSourceErrors();
211 			}
212 			reportFile << PrintProgress(&lastSnapshot, "ERROR") << endl;
213 		}
214 		if ( gInteractive_cvc && --gContinueCount < 1
215 				&& InteractiveCvc(STAGE_FIRST_MINMAX) == SKIP ) continue;
216 		if ( gSetup_cvc ) continue;
217 
218 /// Stage 5) First sim propagation\n
219 /// - missing bulk connection check
220 		SaveMinMaxLeakVoltages();
221 		SetSimPower(POWER_NETS_ONLY);
222 		cvcCircuitList.PrintAndResetCircuitErrors(this, cvcParameters.cvcCircuitErrorLimit, logFile, errorFile, "! Logic shorts 1");
223 		reportFile << PrintProgress(&lastSnapshot, "SIM1") << endl;
224 		reportFile << "Power nets " << CPower::powerCount << endl;
225 		if ( ! cvcParameters.cvcSOI ) {
226 			CheckConnections();
227 		}
228 		if ( gInteractive_cvc && --gContinueCount < 1
229 				&& InteractiveCvc(STAGE_FIRST_SIM) == SKIP ) continue;
230 		SaveInitialVoltages();
231 		if ( gDebug_cvc ) {
232 			PrintAllVirtualNets<CVirtualNetVector>(
233 					minNet_v, simNet_v, maxNet_v, "(1)");
234 		}
235 
236 /// Stage 6) Second sim propagation\n
237 /// - LDD connection errors
238 		if ( cvcParameters.cvcSCRC ) {
239 			SetSCRCPower();
240 		}
241 		SetSimPower(ALL_NETS_AND_FUSE);
242 		reportFile << PrintProgress(&lastSnapshot, "SIM2") << endl;
243 		reportFile << "Power nets " << CPower::powerCount << endl;
244 		CNetIdSet myNewNetSet;
245 		vector<bool> myIgnoreNet_v(simNet_v.size(), false);
246 		int myPassCount = 0;
247 		while ( SetLatchPower(++myPassCount, myIgnoreNet_v, myNewNetSet) ) {
248 			SetSimPower(ALL_NETS_AND_FUSE, myNewNetSet);
249 			reportFile << PrintProgress(&lastSnapshot, "LATCH " + to_string(myPassCount)) << endl;
250 		}
251 		cvcCircuitList.PrintAndResetCircuitErrors(this, cvcParameters.cvcCircuitErrorLimit, logFile, errorFile, "! Logic shorts 2");
252 		if ( detectErrorFlag ) {
253 			FindLDDErrors();
254 //			FindForwardBiasDiodes();
255 		}
256 		if ( gInteractive_cvc && --gContinueCount < 1
257 				&& InteractiveCvc(STAGE_SECOND_SIM) == SKIP ) continue;
258 
259 /// Stage 7) Second min/max propagation\n
260 /// - overvoltage errors\n
261 /// - NMOS possible leak errors\n
262 /// - PMOS possible leak errors\n
263 /// - floating gate errors\n
264 /// - expected value errors
265 		ResetMinMaxPower();
266 		SetInverters();
267 		reportFile << PrintProgress(&lastSnapshot, "MIN/MAX2") << endl;
268 		reportFile << "Power nets " << CPower::powerCount << endl;
269 		if ( detectErrorFlag ) {
270 			if ( cvcParameters.cvcLogicDiodes ) {
271 				FindForwardBiasDiodes();
272 			}
273 			FindAllOverVoltageErrors();
274 			FindNmosPossibleLeakErrors();
275 			FindPmosPossibleLeakErrors();
276 			FindFloatingInputErrors();
277 			CheckExpectedValues();
278 		}
279 		PrintErrorTotals();
280 //		PrintShortedNets(cvcParameters.cvcReportBaseFilename + ".shorts.gz");
281 		reportFile << PrintProgress(&lastSnapshot, "Total") << endl;
282 		if ( gDebug_cvc ) {
283 			PrintAllVirtualNets<CVirtualNetVector>(minNet_v, simNet_v, maxNet_v, "(3)");
284 			cvcCircuitList.Print("", "CVC Full Circuit List");
285 			cvcParameters.cvcModelListMap.DebugPrint();
286 			Print("", "CVC Database");
287 			PrintFlatCdl();
288 		}
289 		reportFile << "Virtual net update/access " << gVirtualNetUpdateCount << "/"
290 				<< gVirtualNetAccessCount << endl;
291 		reportFile << "CVC: Log output to " << cvcParameters.cvcReportFilename << endl;
292 		reportFile << "CVC: End: " << CurrentTime() << endl;
293 		errorFile.close();
294 		debugFile.close();
295 		if ( gInteractive_cvc ) InteractiveCvc(STAGE_COMPLETE);
296 
297 /// Clean-up
298 		logFile.close();
299 	}
300 	Cleanup();
301 }
302 
303 
304 
305