1 /*
2  * Copyright (c) D. Mitch Bailey 2014.
3  *
4  * Copyright 2014-2019 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 "CCvcParameters.hh"
25 
26 #include "wordexp.h"
27 #include "gzstream.h"
28 
CvcFileName()29 string CCvcParameters::CvcFileName() {
30 	return cvcNetlistFilename;
31 }
32 
IsSameDatabase()33 bool CCvcParameters::IsSameDatabase() {
34 	return(cvcLastTopBlock == cvcTopBlock && cvcLastNetlistFilename == cvcNetlistFilename && cvcLastSOI == cvcSOI);
35 }
36 
SaveDatabaseParameters()37 void CCvcParameters::SaveDatabaseParameters() {
38 		cvcLastTopBlock = cvcTopBlock;
39 		cvcLastNetlistFilename = cvcNetlistFilename;
40 		cvcLastSOI = cvcSOI;
41 }
42 
ResetEnvironment()43 void CCvcParameters::ResetEnvironment() {
44 	//! Sets CVC environment variables to defaults.
45 
46 //	cvcLastTopBlock = cvcTopBlock;
47 //	cvcLastNetlistFilename = cvcNetlistFilename;
48 //	cvcLastSOI = cvcSOI;
49 	/*!
50 	 * cvcLast* variables uniquely identify the last CDL file input.
51 	 * If these values are the same for the next run,
52 	 * the current database is used and the CDL file is NOT reread.
53 	 */
54 	cvcTopBlock = "";
55 	cvcNetlistFilename = "";
56 	cvcModelFilename = "";
57 	cvcPowerFilename = "";
58 	cvcFuseFilename = "";
59 	//! The cvcFuseFilename is an optional parameter used to override the type (fuse_on/fuse_off) of specific fuses.
60 	//! The fuse file can be created from the interactive menu command 'dumpfuse filename'.
61 	cvcReportFilename = "";
62 	cvcReportTitle = "";
63 	cvcCircuitErrorLimit = defaultErrorLimit;
64 	//! Default error limit for a given error at a given device in a given circuit is cvcCircuitErrorLimit (default 100).
65 	//! Once the error limit is exceeded, specific device information is NOT printed.
66 	cvcLeakLimit = defaultLeakLimit;
67 	//! Leak errors involving overridden or calculated voltages are flagged if the leak current is >= cvcLeakLimit (default 200uA).
68 	cvcSOI = defaultSOI;
69 	//! cvcSOI (Silicon-On-Insolator) is false for 4 terminal (D-G-S-B) mos.
70 	//! To ignore the bulk connection and corresponding errors, set cvcSOI = true;
71 	cvcSCRC = defaultSCRC;
72 	//! cvcSCRC (Sub-threshhold Current Reduction Circuit)
73 	//! When true, calculates expected SCRC levels after first propagation.
74 	cvcVthGates = defaultVthGates;
75 	//! When true, detects calculated gate-source errors at Vth. Default is to ignore calculated voltage errors at exactly Vth.
76 	cvcMinVthGates = defaultMinVthGates;
77 	//! When true, detect gate-source errors only if >= Vth. Default is to detect errors regardless of Vth.
78 	cvcIgnoreVthFloating = defaultIgnoreVthFloating;
79 	//! When true, ignore Hi-Z errors if max gate-source difference does not exceed Vth. Default is to detect errors regardless of Vth.
80 	cvcIgnoreNoLeakFloating = defaultIgnoreNoLeakFloating;
81 	//! When true, ignore Hi-Z errors if there is no leak. Default is to detect unconnected gates even if there is no leak path.
82 	cvcLeakOvervoltage = defaultLeakOvervoltage;
83 	//! When true, detects worst case overvoltage errors. Default is to flag all errors including those not possible with current mode logic.
84 	cvcLogicDiodes = defaultLogicDiodes;
85 	//! When true, uses logic values, if known, for diode checks. Default is to ignore logic values.
86 	cvcAnalogGates = defaultAnalogGates;
87 	//! When false, ignore errors from analog gates. Default is to use analog values.
88 	cvcBackupResults = defaultBackupResults;
89 	//! When true, backup log and error file. Default is to not create backups.
90 	cvcMosDiodeErrorThreshold = defaultErrorThreshold;
91 	cvcShortErrorThreshold = defaultErrorThreshold;
92 	cvcBiasErrorThreshold = defaultErrorThreshold;
93 	cvcForwardErrorThreshold = defaultErrorThreshold;
94 	cvcFloatingErrorThreshold = defaultErrorThreshold;
95 	cvcGateErrorThreshold = defaultErrorThreshold;
96 	cvcLeakErrorThreshold = defaultErrorThreshold;
97 	cvcExpectedErrorThreshold = defaultErrorThreshold;
98 	cvcOvervoltageErrorThreshold = defaultErrorThreshold;
99 	//! Ignore errors with voltage difference less than the threshold. Default is 0, flag errors regardless of voltage difference.
100 	cvcParallelCircuitPortLimit = defaultParallelCircuitPortLimit;
101 	//! Port count limit for parallel cell processing
102 	cvcCellErrorLimitFile = defaultCellErrorLimitFile;
103 	//! Name of file containing list of cells with error limits
104 	cvcCellChecksumFile = defaultCellChecksumFile;
105 	//! Name of file containing list of checksums for each circuit
106 	cvcLargeCircuitSize = defaultLargeCircuitSize;
107 	//! Minimum device count to display large circuits
108 	cvcNetCheckFile = defaultNetCheckFile;
109 	//! Name of file containing list of net checks
110 	cvcModelCheckFile = defaultModelCheckFile;
111 	//! Name of file containing list of model checks
112 }
113 
PrintEnvironment(ostream & theOutputFile)114 void CCvcParameters::PrintEnvironment(ostream & theOutputFile) {
115 	theOutputFile << "Using the following parameters for CVC (Circuit Validation Check) from " << cvcParamterFilename << endl;
116 	theOutputFile << "CVC_TOP = '" << cvcTopBlock << "'" << endl;
117 	theOutputFile << "CVC_NETLIST = '" << cvcNetlistFilename << "'" << endl;
118 	theOutputFile << "CVC_MODE = '" << cvcMode << "'" << endl;
119 	theOutputFile << "CVC_MODEL_FILE = '" << cvcModelFilename << "'" << endl;
120 	theOutputFile << "CVC_POWER_FILE = '" << cvcPowerFilename << "'" << endl;
121 	theOutputFile << "CVC_FUSE_FILE = '" << cvcFuseFilename << "'" << endl;
122 	theOutputFile << "CVC_REPORT_FILE = '" << cvcReportFilename << "'" << endl;
123 	theOutputFile << "CVC_REPORT_TITLE = '" << cvcReportTitle << "'" << endl;
124 	theOutputFile << "CVC_CIRCUIT_ERROR_LIMIT = '" << cvcCircuitErrorLimit << "'" << endl;
125 	theOutputFile << "CVC_SEARCH_LIMIT = '" << cvcSearchLimit << "'" << endl;
126 	theOutputFile << "CVC_LEAK_LIMIT = '" << cvcLeakLimit << "'" << endl;
127 	theOutputFile << "CVC_SOI = '" << (( cvcSOI ) ? "true" : "false") << "'" << endl;
128 	theOutputFile << "CVC_SCRC = '" << (( cvcSCRC ) ? "true" : "false") << "'" << endl;
129 	theOutputFile << "CVC_VTH_GATES = '" << (( cvcVthGates ) ? "true" : "false") << "'" << endl;
130 	theOutputFile << "CVC_MIN_VTH_GATES = '" << (( cvcMinVthGates ) ? "true" : "false") << "'" << endl;
131 	theOutputFile << "CVC_IGNORE_VTH_FLOATING = '" << (( cvcIgnoreVthFloating ) ? "true" : "false") << "'" << endl;
132 	theOutputFile << "CVC_IGNORE_NO_LEAK_FLOATING = '" << (( cvcIgnoreNoLeakFloating ) ? "true" : "false") << "'" << endl;
133 	theOutputFile << "CVC_LEAK_OVERVOLTAGE = '" << (( cvcLeakOvervoltage ) ? "true" : "false") << "'" << endl;
134 	theOutputFile << "CVC_LOGIC_DIODES = '" << (( cvcLogicDiodes ) ? "true" : "false") << "'" << endl;
135 	theOutputFile << "CVC_ANALOG_GATES = '" << (( cvcAnalogGates ) ? "true" : "false") << "'" << endl;
136 	theOutputFile << "CVC_BACKUP_RESULTS = '" << (( cvcBackupResults ) ? "true" : "false") << "'" << endl;
137 	theOutputFile << "CVC_MOS_DIODE_ERROR_THRESHOLD = '" << Voltage_to_float(cvcMosDiodeErrorThreshold) << "'" << endl;
138 	theOutputFile << "CVC_SHORT_ERROR_THRESHOLD = '" << Voltage_to_float(cvcShortErrorThreshold) << "'" << endl;
139 	theOutputFile << "CVC_BIAS_ERROR_THRESHOLD = '" << Voltage_to_float(cvcBiasErrorThreshold) << "'" << endl;
140 	theOutputFile << "CVC_FORWARD_ERROR_THRESHOLD = '" << Voltage_to_float(cvcForwardErrorThreshold) << "'" << endl;
141 	theOutputFile << "CVC_FLOATING_ERROR_THRESHOLD = '" << Voltage_to_float(cvcFloatingErrorThreshold) << "'" << endl;
142 	theOutputFile << "CVC_GATE_ERROR_THRESHOLD = '" << Voltage_to_float(cvcGateErrorThreshold) << "'" << endl;
143 	theOutputFile << "CVC_LEAK?_ERROR_THRESHOLD = '" << Voltage_to_float(cvcLeakErrorThreshold) << "'" << endl;
144 	theOutputFile << "CVC_EXPECTED_ERROR_THRESHOLD = '" << Voltage_to_float(cvcExpectedErrorThreshold) << "'" << endl;
145 	theOutputFile << "CVC_OVERVOLTAGE_ERROR_THRESHOLD = '" << Voltage_to_float(cvcOvervoltageErrorThreshold) << "'" << endl;
146 	theOutputFile << "CVC_PARALLEL_CIRCUIT_PORT_LIMIT = '" << cvcParallelCircuitPortLimit << "'" << endl;
147 	theOutputFile << "CVC_CELL_ERROR_LIMIT_FILE = '" << cvcCellErrorLimitFile << "'" << endl;
148 	theOutputFile << "CVC_CELL_CHECKSUM_FILE = '" << cvcCellChecksumFile << "'" << endl;
149 	theOutputFile << "CVC_LARGE_CIRCUIT_SIZE = '" << cvcLargeCircuitSize << "'" << endl;
150 	theOutputFile << "CVC_NET_CHECK_FILE = '" << cvcNetCheckFile << "'" << endl;
151 	theOutputFile << "CVC_MODEL_CHECK_FILE = '" << cvcModelCheckFile << "'" << endl;
152 	theOutputFile << "End of parameters" << endl << endl;
153 }
154 
PrintDefaultEnvironment()155 void CCvcParameters::PrintDefaultEnvironment() {
156 	string myDefaultCvcrcFilename = "default.cvcrc";
157 	ifstream myTemporaryCvcrc(myDefaultCvcrcFilename);
158 	if ( myTemporaryCvcrc.good() ) return; // file exists, do nothing
159 	ofstream myDefaultCvcrc(myDefaultCvcrcFilename);
160 	if ( myDefaultCvcrc.fail() ) return; // ignore errors
161 
162 	cout << "Default cvcrc in " << myDefaultCvcrcFilename << endl;
163 	myDefaultCvcrc << "CVC_TOP = '" << cvcTopBlock << "'" << endl;
164 	myDefaultCvcrc << "CVC_NETLIST = '" << cvcNetlistFilename << "'" << endl;
165 	myDefaultCvcrc << "CVC_MODE = '" << cvcMode << "'" << endl;
166 	myDefaultCvcrc << "CVC_MODEL_FILE = '" << cvcModelFilename << "'" << endl;
167 	myDefaultCvcrc << "CVC_POWER_FILE = '" << cvcPowerFilename << "'" << endl;
168 	myDefaultCvcrc << "CVC_FUSE_FILE = '" << cvcFuseFilename << "'" << endl;
169 	myDefaultCvcrc << "CVC_REPORT_FILE = '" << cvcReportFilename << "'" << endl;
170 	myDefaultCvcrc << "CVC_REPORT_TITLE = '" << cvcReportTitle << "'" << endl;
171 	myDefaultCvcrc << "CVC_CIRCUIT_ERROR_LIMIT = '" << cvcCircuitErrorLimit << "'" << endl;
172 	myDefaultCvcrc << "CVC_SEARCH_LIMIT = '" << cvcSearchLimit << "'" << endl;
173 	myDefaultCvcrc << "CVC_LEAK_LIMIT = '" << cvcLeakLimit << "'" << endl;
174 	myDefaultCvcrc << "CVC_SOI = '" << (( cvcSOI ) ? "true" : "false") << "'" << endl;
175 	myDefaultCvcrc << "CVC_SCRC = '" << (( cvcSCRC ) ? "true" : "false") << "'" << endl;
176 	myDefaultCvcrc << "CVC_VTH_GATES = '" << (( cvcVthGates ) ? "true" : "false") << "'" << endl;
177 	myDefaultCvcrc << "CVC_MIN_VTH_GATES = '" << (( cvcMinVthGates ) ? "true" : "false") << "'" << endl;
178 	myDefaultCvcrc << "CVC_IGNORE_VTH_FLOATING = '" << (( cvcIgnoreVthFloating ) ? "true" : "false") << "'" << endl;
179 	myDefaultCvcrc << "CVC_IGNORE_NO_LEAK_FLOATING = '" << (( cvcIgnoreNoLeakFloating ) ? "true" : "false") << "'" << endl;
180 	myDefaultCvcrc << "CVC_LEAK_OVERVOLTAGE = '" << (( cvcLeakOvervoltage ) ? "true" : "false") << "'" << endl;
181 	myDefaultCvcrc << "CVC_LOGIC_DIODES = '" << (( cvcLogicDiodes ) ? "true" : "false") << "'" << endl;
182 	myDefaultCvcrc << "CVC_ANALOG_GATES = '" << (( cvcAnalogGates ) ? "true" : "false") << "'" << endl;
183 	myDefaultCvcrc << "CVC_BACKUP_RESULTS = '" << (( cvcBackupResults ) ? "true" : "false") << "'" << endl;
184 	myDefaultCvcrc << "CVC_MOS_DIODE_ERROR_THRESHOLD = '" << Voltage_to_float(cvcMosDiodeErrorThreshold) << "'" << endl;
185 	myDefaultCvcrc << "CVC_SHORT_ERROR_THRESHOLD = '" << Voltage_to_float(cvcShortErrorThreshold) << "'" << endl;
186 	myDefaultCvcrc << "CVC_BIAS_ERROR_THRESHOLD = '" << Voltage_to_float(cvcBiasErrorThreshold) << "'" << endl;
187 	myDefaultCvcrc << "CVC_FORWARD_ERROR_THRESHOLD = '" << Voltage_to_float(cvcForwardErrorThreshold) << "'" << endl;
188 	myDefaultCvcrc << "CVC_FLOATING_ERROR_THRESHOLD = '" << Voltage_to_float(cvcFloatingErrorThreshold) << "'" << endl;
189 	myDefaultCvcrc << "CVC_GATE_ERROR_THRESHOLD = '" << Voltage_to_float(cvcGateErrorThreshold) << "'" << endl;
190 	myDefaultCvcrc << "CVC_LEAK?_ERROR_THRESHOLD = '" << Voltage_to_float(cvcLeakErrorThreshold) << "'" << endl;
191 	myDefaultCvcrc << "CVC_EXPECTED_ERROR_THRESHOLD = '" << Voltage_to_float(cvcExpectedErrorThreshold) << "'" << endl;
192 	myDefaultCvcrc << "CVC_OVERVOLTAGE_ERROR_THRESHOLD = '" << Voltage_to_float(cvcOvervoltageErrorThreshold) << "'" << endl;
193 	myDefaultCvcrc << "CVC_PARALLEL_CIRCUIT_PORT_LIMIT = '" << cvcParallelCircuitPortLimit << "'" << endl;
194 	myDefaultCvcrc << "CVC_CELL_ERROR_LIMIT_FILE = '" << cvcCellErrorLimitFile << "'" << endl;
195 	myDefaultCvcrc << "CVC_CELL_CHECKSUM_FILE = '" << cvcCellChecksumFile << "'" << endl;
196 	myDefaultCvcrc << "CVC_LARGE_CIRCUIT_SIZE = '" << cvcLargeCircuitSize << "'" << endl;
197 	myDefaultCvcrc << "CVC_NET_CHECK_FILE = '" << cvcNetCheckFile << "'" << endl;
198 	myDefaultCvcrc << "CVC_MODEL_CHECK_FILE = '" << cvcModelCheckFile << "'" << endl;
199 	myDefaultCvcrc.close();
200 }
201 
LoadEnvironment(const string theEnvironmentFilename,const string theReportPrefix)202 void CCvcParameters::LoadEnvironment(const string theEnvironmentFilename, const string theReportPrefix) {
203 	//! Set CVC environment variables from cvcrc file.
204 	/*!
205 	 * CVC environment files can access and define shell environment variables.
206 	 */
207 	ifstream myEnvironmentFile(theEnvironmentFilename);
208 	if ( myEnvironmentFile.fail() ) {
209 		throw EFatalError("Could not open " + theEnvironmentFilename);
210 	}
211 	cvcParamterFilename = theEnvironmentFilename;
212 	string myTuple, myVariable, myValue;
213 	char myBuffer[1024];
214 
215 	while ( getline(myEnvironmentFile, myTuple) ) {
216 		if ( myTuple[0] == '#' ) continue; // skip comments
217 		if ( myTuple.find_first_not_of(" \t\n") > myTuple.length() ) continue; // skip blank lines
218 		if ( myTuple.find("=") > myTuple.length() ) {
219 			cout << "Invalid environment setting: " << myTuple << endl;
220 			throw EBadEnvironment();
221 		}
222 		myVariable = trim_(myTuple.substr(0, myTuple.find("=")));
223 		myValue = trim_(myTuple.substr(myTuple.find("=") + 1));
224 		string myEchoCommand = "echo " + myValue;
225 		FILE * myEcho = popen(myEchoCommand.c_str(), "r");
226 		fgets(myBuffer, 1024, myEcho);
227 		myBuffer[strlen(myBuffer) - 1] = '\0';
228 		setenv(myVariable.c_str(), myBuffer, 1);
229 		pclose(myEcho);
230 		if ( myVariable == "CVC_TOP" ) {
231 			cvcTopBlock = myBuffer;
232 		} else if ( myVariable == "CVC_NETLIST" ) {
233 			cvcNetlistFilename = myBuffer;
234 		} else if ( myVariable == "CVC_MODE" ) {
235 			cvcMode = myBuffer;
236 		} else if ( myVariable == "CVC_MODEL_FILE" ) {
237 			cvcModelFilename = myBuffer;
238 		} else if ( myVariable == "CVC_POWER_FILE" ) {
239 			cvcPowerFilename = myBuffer;
240 		} else if ( myVariable == "CVC_FUSE_FILE" ) {
241 			cvcFuseFilename = myBuffer;
242 		} else if ( myVariable == "CVC_REPORT_FILE" ) {
243 			cvcReportFilename = myBuffer;
244 			if ( cvcReportFilename.find_first_of("\\/") < cvcReportFilename.length() ) {
245 				cvcReportDirectory = cvcReportFilename.substr(0, cvcReportFilename.find_last_of("\\/") + 1);
246 				cvcReportName = cvcReportFilename.substr(cvcReportFilename.find_last_of("\\/") + 1);
247 			} else {
248 				cvcReportDirectory = "";
249 				cvcReportName = cvcReportFilename;
250 			}
251 		} else if ( myVariable == "CVC_REPORT_TITLE" ) {
252 			cvcReportTitle = myBuffer;
253 		} else if ( myVariable == "CVC_CIRCUIT_ERROR_LIMIT" ) {
254 			cvcCircuitErrorLimit = from_string<deviceId_t>(myBuffer);
255 		} else if ( myVariable == "CVC_LEAK_LIMIT" ) {
256 			cvcLeakLimit = from_string<float>(myBuffer);
257 		} else if ( myVariable == "CVC_SEARCH_LIMIT" ) {
258 			cvcSearchLimit = from_string<int>(myBuffer);
259 		} else if ( myVariable == "CVC_SOI" ) {
260 			cvcSOI = strcasecmp(myBuffer, "true") == 0;
261 		} else if ( myVariable == "CVC_SCRC" ) {
262 			cvcSCRC = strcasecmp(myBuffer, "true") == 0;
263 		} else if ( myVariable == "CVC_VTH_GATES" ) {
264 			cvcVthGates = strcasecmp(myBuffer, "true") == 0;
265 		} else if ( myVariable == "CVC_MIN_VTH_GATES" ) {
266 			cvcMinVthGates = strcasecmp(myBuffer, "true") == 0;
267 		} else if ( myVariable == "CVC_IGNORE_VTH_FLOATING" ) {
268 			cvcIgnoreVthFloating = strcasecmp(myBuffer, "true") == 0;
269 		} else if ( myVariable == "CVC_IGNORE_NO_LEAK_FLOATING" ) {
270 			cvcIgnoreNoLeakFloating = strcasecmp(myBuffer, "true") == 0;
271 		} else if ( myVariable == "CVC_LEAK_OVERVOLTAGE" ) {
272 			cvcLeakOvervoltage = strcasecmp(myBuffer, "true") == 0;
273 		} else if ( myVariable == "CVC_LOGIC_DIODES" ) {
274 			cvcLogicDiodes = strcasecmp(myBuffer, "true") == 0;
275 		} else if ( myVariable == "CVC_ANALOG_GATES" ) {
276 			cvcAnalogGates = strcasecmp(myBuffer, "true") == 0;
277 		} else if ( myVariable == "CVC_BACKUP_RESULTS" ) {
278 			cvcBackupResults = strcasecmp(myBuffer, "true") == 0;
279 		} else if ( myVariable == "CVC_MOS_DIODE_ERROR_THRESHOLD" ) {
280 			cvcMosDiodeErrorThreshold = String_to_Voltage(string(myBuffer));
281 		} else if ( myVariable == "CVC_SHORT_ERROR_THRESHOLD" ) {
282 			cvcShortErrorThreshold = String_to_Voltage(string(myBuffer));
283 		} else if ( myVariable == "CVC_BIAS_ERROR_THRESHOLD" ) {
284 			cvcBiasErrorThreshold = String_to_Voltage(string(myBuffer));
285 		} else if ( myVariable == "CVC_FORWARD_ERROR_THRESHOLD" ) {
286 			cvcForwardErrorThreshold = String_to_Voltage(string(myBuffer));
287 		} else if ( myVariable == "CVC_FLOATING_ERROR_THRESHOLD" ) {
288 			cvcFloatingErrorThreshold = String_to_Voltage(string(myBuffer));
289 		} else if ( myVariable == "CVC_GATE_ERROR_THRESHOLD" ) {
290 			cvcGateErrorThreshold = String_to_Voltage(string(myBuffer));
291 		} else if ( myVariable == "CVC_LEAK?_ERROR_THRESHOLD" ) {
292 			cvcLeakErrorThreshold = String_to_Voltage(string(myBuffer));
293 		} else if ( myVariable == "CVC_EXPECTED_ERROR_THRESHOLD" ) {
294 			cvcExpectedErrorThreshold = String_to_Voltage(string(myBuffer));
295 		} else if ( myVariable == "CVC_OVERVOLTAGE_ERROR_THRESHOLD" ) {
296 			cvcOvervoltageErrorThreshold = String_to_Voltage(string(myBuffer));
297 		} else if ( myVariable == "CVC_PARALLEL_CIRCUIT_PORT_LIMIT" ) {
298 			cvcParallelCircuitPortLimit = from_string<int>(myBuffer);
299 			if ( cvcParallelCircuitPortLimit > MAX_PARALLEL_CIRCUIT_PORT_LIMIT ) {
300 				reportFile << "Warning: Parallel circuit port limit exceeds maximum " << cvcParallelCircuitPortLimit << " > " << MAX_PARALLEL_CIRCUIT_PORT_LIMIT << endl;
301 				reportFile << "Parallel circuit port limit set to " << MAX_PARALLEL_CIRCUIT_PORT_LIMIT << endl;
302 				cvcParallelCircuitPortLimit = MAX_PARALLEL_CIRCUIT_PORT_LIMIT;
303 			}
304 		} else if ( myVariable == "CVC_CELL_ERROR_LIMIT_FILE" ) {
305 			cvcCellErrorLimitFile = myBuffer;
306 		} else if ( myVariable == "CVC_CELL_CHECKSUM_FILE" ) {
307 			cvcCellChecksumFile = myBuffer;
308 		} else if ( myVariable == "CVC_LARGE_CIRCUIT_SIZE" ) {
309 			cvcLargeCircuitSize = from_string<size_t>(myBuffer);
310 		} else if ( myVariable == "CVC_NET_CHECK_FILE" ) {
311 			cvcNetCheckFile = myBuffer;
312 		} else if ( myVariable == "CVC_MODEL_CHECK_FILE" ) {
313 			cvcModelCheckFile = myBuffer;
314 		}
315 	}
316 	if ( ! IsEmpty(theReportPrefix) ) {
317 		cvcReportName = theReportPrefix + "-" + cvcReportName;
318 	}
319 	cvcReportFilename = cvcReportDirectory + cvcReportName;
320 	cvcLockFile = cvcReportDirectory + "." + cvcReportName;
321 	myEnvironmentFile.close();
322 }
323 
AddTestModels()324 void CCvcParameters::AddTestModels() {
325 	cvcModelListMap.AddModel("NMOS N Vth=0.3 Vgs=1.2 Vds=1.2");
326 	cvcModelListMap.AddModel("PMOS P Vth=-0.4 Vgs=1.2 Vds=1.2");
327 	cvcModelListMap.AddModel("NMOS MN Vth=0.35 Vgs=5.0 Vds=5.0");
328 	cvcModelListMap.AddModel("PMOS MP Vth=-0.45 Vgs=5.0 Vds=5.0");
329 	cvcModelListMap.AddModel("CAPACITOR CAP Vds=1.2");
330 	cvcModelListMap.AddModel("RESISTOR RES");
331 	cvcModelListMap.AddModel("RESISTOR RESSW model=switch_on");
332 	cvcModelListMap.AddModel("RESISTOR RESWON model=switch_on");
333 	cvcModelListMap.AddModel("RESISTOR RESWOFF model=switch_off");
334 	cvcModelListMap.AddModel("RESISTOR FUSEON model=fuse_on");
335 	cvcModelListMap.AddModel("RESISTOR FUSEOFF model=fuse_off");
336 	cvcModelListMap.AddModel("CAPACITOR CAPSW model=switch_off");
337 	cvcModelListMap.AddModel("DIODE DIO");
338 }
339 
LoadModels()340 returnCode_t CCvcParameters::LoadModels() {
341 	ifstream myModelFile(cvcModelFilename);
342 	cvcModelListMap.Clear();
343 	cvcModelListMap.filename = cvcModelFilename;
344 	if ( myModelFile.fail() ) {
345 		if ( gSetup_cvc ) {
346 			return(OK);
347 		} else {
348 			reportFile << "ERROR: Could not open " << cvcModelFilename << endl;
349 			return (FAIL);
350 		}
351 	}
352 	string myInput, myVariable, myValue;
353 
354 	reportFile << "CVC: Reading device model settings..." << endl;
355 	cvcModelListMap.hasError = false;
356 	while ( getline(myModelFile, myInput) ) {
357 		if ( myInput[0] == '#' ) continue; // skip comments
358 		if ( myInput.find_first_not_of(" \t\n") > myInput.length() ) continue; // skip blank lines
359 		cvcModelListMap.AddModel(myInput);
360 	}
361 	myModelFile.close();
362 	if ( cvcModelListMap.hasError ) {
363 		reportFile << "Invalid model file" << endl;
364 		return(SKIP);
365 	} else {
366 		return(OK);
367 	}
368 
369 }
370 
LoadPower()371 returnCode_t CCvcParameters::LoadPower() {
372 	igzstream myPowerFile;
373 	myPowerFile.open(cvcPowerFilename);
374 	cvcPowerPtrList.Clear();
375 	cvcExpectedLevelPtrList.Clear();
376 	cvcPowerFamilyMap.clear();
377 	cvcPowerMacroPtrMap.clear();
378 	if ( myPowerFile.fail() ) {
379 		if ( gSetup_cvc ) {
380 			return(OK);
381 		} else {
382 			reportFile << "ERROR: Could not open " << cvcPowerFilename << endl;
383 			return (FAIL);
384 		}
385 	}
386 	string myInput, myVariable, myValue;
387 
388 	reportFile << "CVC: Reading power settings..." << endl;
389 	bool myPowerErrorFlag = false;
390 	bool myAutoMacroFlag = true;
391 	while ( getline(myPowerFile, myInput) ) {
392 		try {
393 			bool myIsMacro = ( myInput.substr(0, myInput.find_first_of(" \t", 0)) == "#define" );
394 			bool myIsInstance = ( myInput.substr(0, myInput.find_first_of(" \t", 0)) == "#instance" );
395 			if ( myInput == "#NO AUTO MACROS" ) myAutoMacroFlag = false;
396 			if ( myInput[0] == '#' && ! (myIsMacro || myIsInstance) ) continue; // skip comments
397 			if ( myInput.find_first_not_of(" \t\n") > myInput.length() ) continue; // skip blank lines
398 			myInput = trim_(myInput);
399 			string myMacroName = "";
400 			string myMacroDefinition;
401 			if ( myIsMacro ) {
402 				myMacroDefinition = myInput.substr(myInput.find_first_not_of(" \t\n", 7));
403 				if ( myMacroDefinition.substr(0, myMacroDefinition.find_first_of(" \t", 0)) == "family" ) {
404 					cvcPowerFamilyMap.AddFamily(myMacroDefinition);
405 				} else {
406 					myMacroName = myMacroDefinition.substr(0, myMacroDefinition.find_first_of(" \t", 0));
407 				}
408 			} else if ( myIsInstance ) {
409 				cvcInstancePowerPtrList.push_back(new CInstancePower(myInput));
410 			} else {
411 				CPower * myPowerPtr = new CPower(myInput, cvcPowerMacroPtrMap, cvcModelListMap);
412 				if ( ! (IsEmpty(myPowerPtr->expectedMin()) && IsEmpty(myPowerPtr->expectedSim()) && IsEmpty(myPowerPtr->expectedMax())) ) {
413 					cvcExpectedLevelPtrList.push_back(new CPower(myPowerPtr));  // duplicate CPower (not a bit-wise copy)
414 				}
415 				if (myPowerPtr->type != NO_TYPE || myPowerPtr->minVoltage != UNKNOWN_VOLTAGE || myPowerPtr->simVoltage != UNKNOWN_VOLTAGE || myPowerPtr->maxVoltage != UNKNOWN_VOLTAGE) {
416 					cvcPowerPtrList.push_back(new CPower(myPowerPtr));  // duplicate CPower (not a bit-wise copy)
417 				}
418 				myMacroName = string(myPowerPtr->powerSignal());
419 				if ( myMacroName[0] == '/' ) { // macros for top level nets that are not ports
420 					myMacroName = myMacroName.substr(1);
421 				}
422 				myMacroDefinition = myInput;
423 				delete myPowerPtr;
424 			}
425 			if ( myMacroName.find_first_of("(<[}/*@+-") > myMacroName.length() && isalpha(myMacroName[0]) ) { // no special characters in macro names
426 				if ( cvcPowerMacroPtrMap.count(myMacroName) > 0 ) {
427 					if ( myAutoMacroFlag ) {
428 						throw EPowerError("duplicate macro name: " + myMacroName);
429 					} else {  // Ignore duplicate macro definitions when debugging subcircuits
430 						continue;
431 					}
432 				}
433 				cvcPowerMacroPtrMap[myMacroName] = new CPower(myMacroDefinition, cvcPowerMacroPtrMap, cvcModelListMap);
434 			}
435 		}
436 		catch (const EPowerError& myException) {
437 			reportFile << myException.what() << endl;
438 			myPowerErrorFlag = true;
439 		}
440 	}
441 	for ( auto instance_ppit = cvcInstancePowerPtrList.begin(); instance_ppit != cvcInstancePowerPtrList.end(); instance_ppit++ ) {
442 		ifstream myInstancePowerFile((*instance_ppit)->powerFile);
443 		if ( myInstancePowerFile.fail() ) {
444 			reportFile << "ERROR: Could not open " << (*instance_ppit)->powerFile << endl;
445 			return (FAIL);
446 		}
447 		while ( getline(myInstancePowerFile, myInput) ) {
448 			if ( myInput[0] == '#' ) continue; // skip comments, macros, and instances (no instance in instance)
449 			if ( myInput.find_first_not_of(" \t\n") > myInput.length() ) continue; // skip blank lines
450 			myInput = trim_(myInput);
451 			(*instance_ppit)->powerList.push_back(myInput);
452 		}
453 		myInstancePowerFile.close();
454 	}
455 	myPowerFile.close();
456 	if ( myPowerErrorFlag ) {
457 		reportFile << "Invalid power file: " << cvcPowerFilename << endl;
458 		return (SKIP);
459 	} else {
460 		return (OK);
461 	}
462 }
463 
SetHiZPropagation()464 void CCvcParameters::SetHiZPropagation() {
465 	for ( auto power_ppit = cvcPowerPtrList.begin(); power_ppit != cvcPowerPtrList.end(); power_ppit++ ) {
466 		if ( (*power_ppit)->type[HIZ_BIT] && ! IsEmpty((*power_ppit)->family()) ) {
467 			if ( (*power_ppit)->RelativeVoltage(cvcPowerMacroPtrMap, MIN_POWER, cvcModelListMap) == (*power_ppit)->minVoltage ) {
468 				(*power_ppit)->active[MIN_IGNORE] = true;
469 			}
470 			if ( (*power_ppit)->RelativeVoltage(cvcPowerMacroPtrMap, MAX_POWER, cvcModelListMap) == (*power_ppit)->maxVoltage ) {
471 				(*power_ppit)->active[MAX_IGNORE] = true;
472 			}
473 		}
474 	}
475 }
476 
PrintPowerList(ostream & theLogFile,string theIndentation)477 void CCvcParameters::PrintPowerList(ostream & theLogFile, string theIndentation) {
478 	string myIndentation = theIndentation + " ";
479 	theLogFile << endl << theIndentation << "PowerList> filename " << cvcPowerFilename << endl;
480 	for (CPowerPtrList::iterator power_ppit = cvcPowerPtrList.begin(); power_ppit != cvcPowerPtrList.end(); power_ppit++) {
481 		(*power_ppit)->Print(theLogFile, myIndentation);
482 	}
483 	theLogFile << theIndentation << "PowerList> end" << endl << endl;
484 }
485 
486