1 /*
2  * CCvcDb_print.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 "CModel.hh"
28 #include "CDevice.hh"
29 #include "CPower.hh"
30 #include "CInstance.hh"
31 #include "CEventQueue.hh"
32 #include "CVirtualNet.hh"
33 
SetOutputFiles(string theReportFilename)34 void CCvcDb::SetOutputFiles(string theReportFilename) {
35 	ifstream myTestFile;
36 	string myBackupFilename, myBaseFilename;
37 	string myCompressedFilename, myBaseCompressedFilename;
38 	string mySystemCommand;
39 	myBaseFilename = theReportFilename.substr(0, theReportFilename.find(".log"));
40 	cvcParameters.cvcReportBaseFilename = myBaseFilename;
41 	if ( cvcParameters.cvcBackupResults ) {
42 		int myFileSuffix = 0;
43 		myBackupFilename = theReportFilename;
44 		myCompressedFilename = myBackupFilename + ".gz";
45 		while ( ( myTestFile.open(myBackupFilename), myTestFile.good() ) || ( myTestFile.open(myCompressedFilename), myTestFile.good() ) ) {
46 			myTestFile.close();
47 			myBackupFilename = theReportFilename + "." + to_string<int>(++myFileSuffix);
48 			myCompressedFilename = myBackupFilename + ".gz";
49 		}
50 		if ( myFileSuffix > 0 ) {
51 			cout << "INFO: Moving " << theReportFilename << " to " << myCompressedFilename << endl;
52 			assert(rename(theReportFilename.c_str(), myBackupFilename.c_str()) == 0);
53 			mySystemCommand = "gzip -f " + myBackupFilename;
54 			assert(system(mySystemCommand.c_str()) == 0);
55 
56 			myBaseFilename = cvcParameters.cvcReportBaseFilename + ".error";
57 			myBaseCompressedFilename = myBaseFilename + ".gz";
58 			myBackupFilename = myBaseFilename + "." + to_string<int>(myFileSuffix);
59 			myCompressedFilename = myBackupFilename + ".gz";
60 			if ( ( myTestFile.open(myBackupFilename), myTestFile.good() ) || ( myTestFile.open(myCompressedFilename), myTestFile.good() ) ) {
61 				myTestFile.close();
62 				cout << "INFO: Removing " << myBackupFilename << endl;
63 				assert((remove(myBackupFilename.c_str()) == 0) || (remove(myCompressedFilename.c_str()) == 0));
64 			}
65 			if ( myTestFile.open(myBaseFilename), myTestFile.good() ) {
66 				myTestFile.close();
67 				cout << "INFO: Moving " << myBaseFilename << " to " << myCompressedFilename << endl;
68 				assert(rename(myBaseFilename.c_str(), myBackupFilename.c_str()) == 0);
69 				mySystemCommand = "gzip -f " + myBackupFilename;
70 				assert(system(mySystemCommand.c_str()) == 0);
71 			} else if ( myTestFile.open(myBaseCompressedFilename), myTestFile.good() ) {
72 				myTestFile.close();
73 				cout << "INFO: Moving " << myBaseCompressedFilename << " to " << myCompressedFilename << endl;
74 				assert(rename(myBaseCompressedFilename.c_str(), myCompressedFilename.c_str()) == 0);
75 			}
76 
77 			myBaseFilename = cvcParameters.cvcReportBaseFilename + ".shorts";
78 			myBaseCompressedFilename = myBaseFilename + ".gz";
79 			myBackupFilename = myBaseFilename + "." + to_string<int>(myFileSuffix);
80 			myCompressedFilename = myBackupFilename + ".gz";
81 			if ( ( myTestFile.open(myBackupFilename), myTestFile.good() ) || ( myTestFile.open(myCompressedFilename), myTestFile.good() ) ) {
82 				myTestFile.close();
83 				cout << "INFO: Removing " << myBackupFilename << endl;
84 				assert((remove(myBackupFilename.c_str()) == 0) || (remove(myCompressedFilename.c_str()) == 0));
85 			}
86 			if ( myTestFile.open(myBaseFilename), myTestFile.good() ) {
87 				myTestFile.close();
88 				cout << "INFO: Moving " << myBaseFilename << " to " << myCompressedFilename << endl;
89 				assert(rename(myBaseFilename.c_str(), myBackupFilename.c_str()) == 0);
90 				mySystemCommand = "gzip -f " + myBackupFilename;
91 				assert(system(mySystemCommand.c_str()) == 0);
92 			} else if ( myTestFile.open(myBaseCompressedFilename), myTestFile.good() ) {
93 				myTestFile.close();
94 				cout << "INFO: Moving " << myBaseCompressedFilename << " to " << myCompressedFilename << endl;
95 				assert(rename(myBaseCompressedFilename.c_str(), myCompressedFilename.c_str()) == 0);
96 			}
97 		} else {
98 			myBaseFilename = cvcParameters.cvcReportBaseFilename + ".error";
99 			myBaseCompressedFilename = myBaseFilename + ".gz";
100 			if ( myTestFile.open(myBaseFilename), myTestFile.good() ) {
101 				myTestFile.close();
102 				cout << "INFO: Removing " << myBaseFilename << endl;
103 				remove(myBaseFilename.c_str());
104 			}
105 			if ( myTestFile.open(myBaseCompressedFilename), myTestFile.good() ) {
106 				myTestFile.close();
107 				cout << "INFO: Removing " << myBaseCompressedFilename << endl;
108 				remove(myBaseCompressedFilename.c_str());
109 			}
110 			myBaseFilename = cvcParameters.cvcReportBaseFilename + ".shorts";
111 			myBaseCompressedFilename = myBaseFilename + ".gz";
112 			if ( myTestFile.open(myBaseFilename), myTestFile.good() ) {
113 				myTestFile.close();
114 				cout << "INFO: Removing " << myBaseFilename << endl;
115 				remove(myBaseFilename.c_str());
116 			}
117 			if ( myTestFile.open(myBaseCompressedFilename), myTestFile.good() ) {
118 				myTestFile.close();
119 				cout << "INFO: Removing " << myBaseCompressedFilename << endl;
120 				remove(myBaseCompressedFilename.c_str());
121 			}
122 		}
123 	}
124 	logFile.open(theReportFilename);
125 	if ( ! logFile.good() ) {
126 		throw EFatalError("Could not open " + theReportFilename);
127 	}
128 	errorFile.open(cvcParameters.cvcReportBaseFilename + ".error.gz");
129 	if ( ! errorFile.good() ) {
130 		throw EFatalError("Could not open " + cvcParameters.cvcReportBaseFilename + ".error.gz");
131 	}
132 	debugFile.open(cvcParameters.cvcReportBaseFilename + ".debug.gz");
133 	if ( ! debugFile.good() ) {
134 		throw EFatalError("Could not open " + cvcParameters.cvcReportBaseFilename + ".debug.gz");
135 	}
136 
137 	reportFile << "CVC: Log output to " << theReportFilename << endl;
138 	reportFile << "CVC: Error output to " << cvcParameters.cvcReportBaseFilename << ".error.gz" << endl;
139 	reportFile << "CVC: Debug output to " << cvcParameters.cvcReportBaseFilename << ".debug.gz" << endl;
140 //	reportFile << "CVC: Short output to " << cvcParameters.cvcReportBaseFilename << ".shorts.gz" << endl;
141 }
142 
NetAlias(netId_t theNetId,bool thePrintCircuitFlag)143 string CCvcDb::NetAlias(netId_t theNetId, bool thePrintCircuitFlag) {
144 	string myAlias = "";
145 	CPower * myPower_p = netVoltagePtr_v[theNetId].full;
146 	if ( myPower_p && ! IsEmpty(myPower_p->powerAlias()) && myPower_p->powerAlias() != myPower_p->powerSignal() ) myAlias = "~>" + string(myPower_p->powerAlias());
147 	return (thePrintCircuitFlag) ? myAlias : "";
148 }
149 
NetName(CPower * thePowerPtr,bool thePrintCircuitFlag,bool thePrintHierarchyFlag)150 string CCvcDb::NetName(CPower * thePowerPtr, bool thePrintCircuitFlag, bool thePrintHierarchyFlag) {
151 	netId_t myNetId;
152 	if ( thePowerPtr->netId != UNKNOWN_NET ) {
153 		myNetId = thePowerPtr->netId;
154 	} else {
155 		return "unknown";
156 	}
157 	instanceId_t myParentId = netParent_v[myNetId];
158 	if ( myParentId == 0 && myNetId < instancePtr_v[myParentId]->master_p->portCount ) {
159 		return instancePtr_v[myParentId]->master_p->internalSignal_v[myNetId] + NetAlias(myNetId, thePrintCircuitFlag);
160 	} else {
161 		netId_t myNetOffset = myNetId - instancePtr_v[myParentId]->firstNetId;
162 		return(HierarchyName(myParentId, thePrintCircuitFlag, thePrintHierarchyFlag) + "/" + instancePtr_v[myParentId]->master_p->internalSignal_v[myNetOffset]) + NetAlias(myNetId, thePrintCircuitFlag);
163 	}
164 }
165 
NetName(const netId_t theNetId,bool thePrintCircuitFlag,bool thePrintHierarchyFlag)166 string CCvcDb::NetName(const netId_t theNetId, bool thePrintCircuitFlag, bool thePrintHierarchyFlag) {
167 	if ( theNetId == UNKNOWN_NET ) return "unknown";
168 	instanceId_t myParentId = netParent_v[theNetId];
169 	if ( myParentId == 0 && theNetId < instancePtr_v[myParentId]->master_p->portCount ) {
170 		return instancePtr_v[myParentId]->master_p->internalSignal_v[theNetId] + NetAlias(theNetId, thePrintCircuitFlag);
171 	} else {
172 		netId_t myNetOffset = theNetId - instancePtr_v[myParentId]->firstNetId;
173 		return(HierarchyName(myParentId, thePrintCircuitFlag, thePrintHierarchyFlag) + "/" + instancePtr_v[myParentId]->master_p->internalSignal_v[myNetOffset]) + NetAlias(theNetId, thePrintCircuitFlag);
174 	}
175 }
176 
HierarchyName(const instanceId_t theInstanceId,bool thePrintCircuitFlag,bool thePrintHierarchyFlag)177 string CCvcDb::HierarchyName(const instanceId_t theInstanceId, bool thePrintCircuitFlag, bool thePrintHierarchyFlag) {
178 	if ( theInstanceId == 0 ) {
179 		// top circuit
180 		return "";
181 	} else {
182 		instanceId_t myParentId = instancePtr_v[theInstanceId]->parentId;
183 		instanceId_t mySubcircuitOffset = theInstanceId - instancePtr_v[myParentId]->firstSubcircuitId;
184 		string myCircuitName = "";
185 		if ( thePrintCircuitFlag ) {
186 			myCircuitName = "(" + string(instancePtr_v[myParentId]->master_p->subcircuitPtr_v[mySubcircuitOffset]->masterName) + ")";
187 			if ( ! thePrintHierarchyFlag ) return ( myCircuitName );
188 		}
189 		return(HierarchyName(myParentId, thePrintCircuitFlag, thePrintHierarchyFlag) + "/" + instancePtr_v[myParentId]->master_p->subcircuitPtr_v[mySubcircuitOffset]->name + myCircuitName);
190 	}
191 }
192 
DeviceName(const deviceId_t theDeviceId,bool thePrintCircuitFlag,bool thePrintHierarchyFlag)193 string CCvcDb::DeviceName(const deviceId_t theDeviceId, bool thePrintCircuitFlag, bool thePrintHierarchyFlag) {
194 	instanceId_t myParentId = deviceParent_v[theDeviceId];
195 	deviceId_t myDeviceOffset = theDeviceId - instancePtr_v[myParentId]->firstDeviceId;
196 	return(HierarchyName(myParentId, thePrintCircuitFlag, thePrintHierarchyFlag) + "/" + instancePtr_v[myParentId]->master_p->devicePtr_v[myDeviceOffset]->name);
197 }
198 
DeviceName(string theName,const instanceId_t theParentId,bool thePrintCircuitFlag,bool thePrintHierarchyFlag)199 string CCvcDb::DeviceName(string theName, const instanceId_t theParentId, bool thePrintCircuitFlag, bool thePrintHierarchyFlag) {
200 	return(HierarchyName(theParentId, thePrintCircuitFlag, thePrintHierarchyFlag) + "/" + theName);
201 }
202 
PrintEquivalentNets(string theIndentation)203 void CCvcDb::PrintEquivalentNets(string theIndentation) {
204 	string myIndentation = theIndentation + " ";
205 	cout << theIndentation << "EquivalentNets> start" << endl;
206 	for (netId_t net_it = 0; net_it < netCount; net_it++) {
207 		if ( net_it != equivalentNet_v[net_it] ) cout << myIndentation << net_it << "(" << equivalentNet_v[net_it] << ")" << endl;
208 	}
209 	cout << theIndentation << "EquivalentNets> end" << endl;
210 }
211 
PrintInverterNets(string theIndentation)212 void CCvcDb::PrintInverterNets(string theIndentation) {
213 	string myIndentation = theIndentation + " ";
214 	cout << theIndentation << "InverterNets> start" << endl;
215 	for (netId_t net_it = 0; net_it < netCount; net_it++) {
216 		if ( inverterNet_v[net_it] != UNKNOWN_NET ) cout << myIndentation << "in " << inverterNet_v[net_it] << ((highLow_v[net_it]) ? " ->" : " =>") << " out " << net_it << endl;
217 	}
218 	cout << theIndentation << "InverterNets> end" << endl;
219 }
220 
PrintFlatCdl()221 void CCvcDb::PrintFlatCdl() {
222 	PrintNewCdlLine(string(".SUBCKT"));
223 	PrintCdlLine(topCircuit_p->name);
224 	for (netId_t net_it = 0; net_it < topCircuit_p->portCount; net_it++) {
225 		PrintCdlLine(topCircuit_p->internalSignal_v[net_it]);
226 	}
227 
228 	CCircuit * myMaster_p;
229 	for (instanceId_t instance_it = 0; instance_it < instancePtr_v.size(); instance_it++) {
230 		if ( instancePtr_v[instance_it]->IsParallelInstance() ) continue;
231 		myMaster_p = instancePtr_v[instance_it]->master_p;
232 		for (deviceId_t device_it = 0; device_it < myMaster_p->devicePtr_v.size(); device_it++) {
233 			PrintNewCdlLine(myMaster_p->devicePtr_v[device_it]->parameters[0] + DeviceName(instancePtr_v[instance_it]->firstDeviceId + device_it, PRINT_CIRCUIT_OFF));
234 			for (netId_t net_it = 0; net_it < myMaster_p->devicePtr_v[device_it]->signalId_v.size(); net_it++) {
235 				PrintCdlLine(NetName(instancePtr_v[instance_it]->localToGlobalNetId_v[myMaster_p->devicePtr_v[device_it]->signalId_v[net_it]]));
236 			}
237 			PrintCdlLine(myMaster_p->devicePtr_v[device_it]->parameters + 2);  // skip first 2 characters of parameter string
238 			if ( instancePtr_v[instance_it]->parallelInstanceCount > 1 ) {
239 				PrintCdlLine("M=" + to_string<instanceId_t> (instancePtr_v[instance_it]->parallelInstanceCount));
240 			}
241 			PrintCdlLine(string(""));
242 		}
243 	}
244 	PrintNewCdlLine(string(".ENDS"));
245 	PrintNewCdlLine(string(""));
246 }
247 
PrintHierarchicalCdl(CCircuit * theCircuit,unordered_set<text_t> & thePrintedList,ostream & theCdlFile)248 void CCvcDb::PrintHierarchicalCdl(CCircuit *theCircuit, unordered_set<text_t> & thePrintedList, ostream & theCdlFile) {
249 	for (instanceId_t instance_it = 0; instance_it < theCircuit->subcircuitPtr_v.size(); instance_it++) {
250 		CCircuit * myMaster_p = theCircuit->subcircuitPtr_v[instance_it]->master_p;
251 		if (thePrintedList.count(myMaster_p->name) == 0) {
252 			thePrintedList.insert(myMaster_p->name);
253 			PrintHierarchicalCdl(myMaster_p, thePrintedList, theCdlFile);
254 		}
255 	}
256 
257 	PrintNewCdlLine(string(".SUBCKT"), theCdlFile);
258 	PrintCdlLine(theCircuit->name, theCdlFile);
259 	vector<text_t> mySignals_v;
260 	mySignals_v.reserve(theCircuit->localSignalIdMap.size());
261 	for (auto signal_net_pair_pit = theCircuit->localSignalIdMap.begin(); signal_net_pair_pit != theCircuit->localSignalIdMap.end(); signal_net_pair_pit++) {
262 		mySignals_v[signal_net_pair_pit->second] = signal_net_pair_pit->first;
263 	}
264 	for (netId_t net_it = 0; net_it < theCircuit->portCount; net_it++) {
265 		PrintCdlLine(mySignals_v[net_it], theCdlFile);
266 	}
267 	for (deviceId_t device_it = 0; device_it < theCircuit->devicePtr_v.size(); device_it++) {
268 		PrintNewCdlLine(theCircuit->devicePtr_v[device_it]->name, theCdlFile);
269 		string myDeviceType = theCircuit->devicePtr_v[device_it]->model_p->baseType;
270 		if ( myDeviceType == "R" || myDeviceType == "C" ) {
271 			for (netId_t net_it = 0; net_it < 2; net_it++) {
272 				PrintCdlLine(mySignals_v[theCircuit->devicePtr_v[device_it]->signalId_v[net_it]], theCdlFile);
273 			}
274 		} else {
275 			for (netId_t net_it = 0; net_it < theCircuit->devicePtr_v[device_it]->signalId_v.size(); net_it++) {
276 				PrintCdlLine(mySignals_v[theCircuit->devicePtr_v[device_it]->signalId_v[net_it]], theCdlFile);
277 			}
278 		}
279 		PrintCdlLine(theCircuit->devicePtr_v[device_it]->parameters + 2, theCdlFile);  // The first 2 characters of the parameters are device type code. ignore them.
280 /*
281 		if ( theCircuit->devicePtr_v[device_it]->model_p->type == NRESISTOR || theCircuit->devicePtr_v[device_it]->model_p->type == PRESISTOR ) {
282 			PrintCdlLine(string("$SUB=") + mySignals_v[theCircuit->devicePtr_v[device_it]->signalId_v[2]], theCdlFile);
283 		}
284 */
285 		if ( (myDeviceType == "R" || myDeviceType == "C") && theCircuit->devicePtr_v[device_it]->signalId_v.size() == 3 ) {
286 			PrintCdlLine(string("$SUB=") + mySignals_v[theCircuit->devicePtr_v[device_it]->signalId_v[2]], theCdlFile);
287 		}
288 		PrintCdlLine(string(""), theCdlFile);
289 	}
290 	for (instanceId_t instance_it = 0; instance_it < theCircuit->subcircuitPtr_v.size(); instance_it++) {
291 		PrintNewCdlLine(theCircuit->subcircuitPtr_v[instance_it]->name, theCdlFile);
292 		for (netId_t net_it = 0; net_it < theCircuit->subcircuitPtr_v[instance_it]->signalId_v.size(); net_it++) {
293 			PrintCdlLine(mySignals_v[theCircuit->subcircuitPtr_v[instance_it]->signalId_v[net_it]], theCdlFile);
294 		}
295 		PrintCdlLine(theCircuit->subcircuitPtr_v[instance_it]->masterName, theCdlFile);
296 		PrintCdlLine(string(""), theCdlFile);
297 	}
298 	PrintNewCdlLine(string(".ENDS"), theCdlFile);
299 	PrintNewCdlLine(string(" "), theCdlFile);
300 }
301 
PrintCdlLine(const string theData,ostream & theOutput,const unsigned int theMaxLength)302 void CCvcDb::PrintCdlLine(const string theData, ostream & theOutput, const unsigned int theMaxLength) {
303 	if (lineLength + theData.length() > theMaxLength) {
304 		theOutput << endl << "+";
305 		lineLength = 1;
306 	}
307 	theOutput << " " << theData;
308 	lineLength += theData.length() + 1;
309 }
310 
PrintNewCdlLine(const string theData,ostream & theOutput)311 void CCvcDb::PrintNewCdlLine(const string theData, ostream & theOutput) {
312 	if ( lineLength > 0) {
313 		theOutput << endl;
314 	}
315 	theOutput << theData;
316 	lineLength = theData.length();
317 }
318 
PrintCdlLine(const char * theData,ostream & theOutput,const unsigned int theMaxLength)319 void CCvcDb::PrintCdlLine(const char * theData, ostream & theOutput, const unsigned int theMaxLength) {
320 	if (lineLength + strlen(theData) > theMaxLength) {
321 		theOutput << endl << "+";
322 		lineLength = 1;
323 	}
324 	theOutput << " " << theData;
325 	lineLength += strlen(theData);
326 }
327 
PrintNewCdlLine(const text_t theData,ostream & theOutput)328 void CCvcDb::PrintNewCdlLine(const text_t theData, ostream & theOutput) {
329 	if ( lineLength > 0) {
330 		theOutput << endl;
331 	}
332 	theOutput << theData;
333 	lineLength = strlen(theData);
334 }
335 
PrintNewCdlLine(const char theData,ostream & theOutput)336 void CCvcDb::PrintNewCdlLine(const char theData, ostream & theOutput) {
337 	if ( lineLength > 0) {
338 		theOutput << endl;
339 	}
340 	theOutput << theData;
341 	lineLength = 1;
342 }
343 
PrintSourceDrainConnections(CStatus & theConnectionStatus,string theIndentation)344 void CCvcDb::PrintSourceDrainConnections(CStatus& theConnectionStatus, string theIndentation) {
345 	cout << theIndentation << "SourceConnectionsTo:";
346 	if ( theConnectionStatus[NMOS] ) cout << " NMOS";
347 	if ( theConnectionStatus[PMOS] ) cout << " PMOS";
348 	if ( theConnectionStatus[RESISTOR] ) cout << " RESISTOR";
349 	if ( theConnectionStatus[FUSE_ON] ) cout << " FUSE_ON";
350 	if ( theConnectionStatus[FUSE_OFF] ) cout << " FUSE_OFF";
351 	cout << endl;
352 }
353 
PrintConnections(deviceId_t theDeviceCount,deviceId_t theDeviceId,CDeviceIdVector & theNextDevice_v,string theIndentation,string theHeading)354 void CCvcDb::PrintConnections(deviceId_t theDeviceCount, deviceId_t theDeviceId, CDeviceIdVector& theNextDevice_v, string theIndentation, string theHeading) {
355 	cout << theIndentation << theHeading << "(" << theDeviceCount << ")>";
356 	while (theDeviceId != UNKNOWN_DEVICE ) {
357 		cout << " " << theDeviceId;
358 		theDeviceId = theNextDevice_v[theDeviceId];
359 	}
360 	cout << endl;
361 }
362 
PrintBulkConnections(netId_t theNetId,string theIndentation,string theHeading)363 void CCvcDb::PrintBulkConnections(netId_t theNetId, string theIndentation, string theHeading) {
364 	// debug function. not optimized.
365 	deviceId_t myDeviceCount = 0;
366 	for ( deviceId_t device_it = 0; device_it < deviceCount; device_it++ ) {
367 		if ( bulkNet_v[device_it] == theNetId ) {
368 			myDeviceCount++;
369 		}
370 	}
371 	cout << theIndentation << theHeading << "(" << myDeviceCount << ")>";
372 	for ( deviceId_t device_it = 0; device_it < deviceCount; device_it++ ) {
373 		if ( bulkNet_v[device_it] == theNetId ) {
374 			cout << " " << device_it;
375 		}
376 	}
377 	cout << endl;
378 }
379 
StatusString(const CStatus & theStatus)380 string CCvcDb::StatusString(const CStatus& theStatus) {
381 	string myStatus = "";
382 	for (size_t bit_it = 0; bit_it < theStatus.size(); bit_it++) {
383 		myStatus += (theStatus[bit_it]) ? "1" : "0";
384 	}
385 	return myStatus;
386 }
387 
PrintPowerList(ostream & theOutputFile,string theHeading,string theIndentation)388 void CCvcDb::PrintPowerList(ostream & theOutputFile, string theHeading, string theIndentation) {
389 	theOutputFile << theIndentation << theHeading << "> filename " << cvcParameters.cvcPowerFilename << endl;
390 	string myRealPowerName;
391 	text_t myLastPowerSignal = NULL;
392 	for (CPowerPtrList::iterator power_ppit = cvcParameters.cvcPowerPtrList.begin(); power_ppit != cvcParameters.cvcPowerPtrList.end(); power_ppit++) {
393 		if ( IsEmpty((*power_ppit)->powerSignal()) ) continue; // skip resistor definitions
394 		myRealPowerName = NetName((*power_ppit)->netId);
395 		if ( myLastPowerSignal != (*power_ppit)->powerSignal() && myRealPowerName != string((*power_ppit)->powerSignal()) ) {
396 			string myAlias = "";
397 			if ( ! IsEmpty((*power_ppit)->powerAlias()) && string((*power_ppit)->powerSignal()) != (*power_ppit)->powerAlias() ) {
398 				myAlias = ALIAS_DELIMITER + string((*power_ppit)->powerAlias());
399 			}
400 			theOutputFile << (*power_ppit)->powerSignal() << myAlias << (*power_ppit)->definition << endl;
401 		}
402 		myLastPowerSignal = (*power_ppit)->powerSignal();
403 		(*power_ppit)->Print(theOutputFile, theIndentation + " ", myRealPowerName);
404 	}
405 	myLastPowerSignal = NULL;
406 	theOutputFile << theIndentation << "> expected values" << endl;
407 	for (auto power_ppit = cvcParameters.cvcExpectedLevelPtrList.begin(); power_ppit != cvcParameters.cvcExpectedLevelPtrList.end(); power_ppit++) {
408 		myRealPowerName = NetName((*power_ppit)->netId);
409 		if ( myLastPowerSignal != (*power_ppit)->powerSignal() && myRealPowerName != string((*power_ppit)->powerSignal()) ) {
410 			string myAlias = "";
411 			if ( ! IsEmpty((*power_ppit)->powerAlias()) && (*power_ppit)->powerSignal() != (*power_ppit)->powerAlias() ) {
412 				myAlias = ALIAS_DELIMITER + string((*power_ppit)->powerAlias());
413 			}
414 			theOutputFile << (*power_ppit)->powerSignal() << myAlias << (*power_ppit)->definition << endl;
415 		}
416 		myLastPowerSignal = (*power_ppit)->powerSignal();
417 		(*power_ppit)->Print(theOutputFile, theIndentation + " ", myRealPowerName);
418 	}
419 	theOutputFile << theIndentation << "> macros" << endl;
420 	for (auto powerMap_pit = cvcParameters.cvcPowerMacroPtrMap.begin(); powerMap_pit != cvcParameters.cvcPowerMacroPtrMap.end(); powerMap_pit++) {
421 		netId_t myNetId = FindNet(0, powerMap_pit->first, false);
422 //		if (myNetId == UNKNOWN_NET || ! netVoltagePtr_v[myNetId]) { // power definition does not exist, therefore this is macro
423 		if (myNetId == UNKNOWN_NET) { // power definition does not exist, therefore this is macro
424 			theOutputFile << theIndentation << " #define";
425 			powerMap_pit->second->Print(theOutputFile, theIndentation + " ", powerMap_pit->first);
426 		}
427 	}
428 	theOutputFile << theIndentation << theHeading << "> end" << endl << endl;
429 }
430 
Print(const string theIndentation,const string theHeading)431 void CCvcDb::Print(const string theIndentation, const string theHeading) {
432 	string myIndentation = theIndentation + " ";
433 
434 	cout << endl << theIndentation << theHeading << " start" << endl;
435 	cout << myIndentation << "Counts> Devices: " << deviceCount;
436 	cout << "  Subcircuits: " << subcircuitCount;
437 	cout << "  Nets: " << netCount << endl;
438 	cout << myIndentation << "InstanceList> start" << endl;
439 	for (instanceId_t instance_it = 0; instance_it < subcircuitCount; instance_it++) {
440 		instancePtr_v[instance_it]->Print(instance_it, myIndentation + " ");
441 	}
442 	cout << myIndentation << "InstanceList> end" << endl << endl;
443 	cout << myIndentation << "NetList> start" << endl;
444 	vector<deviceId_t> myBulkCount;
445 	ResetVector<vector<deviceId_t>>(myBulkCount, netCount, 0);
446 	for (deviceId_t device_it = 0; device_it < deviceCount; device_it++) {
447 		if ( bulkNet_v[device_it] == UNKNOWN_DEVICE ) continue;
448 		myBulkCount[bulkNet_v[device_it]]++;
449 	}
450 	for (netId_t net_it = 0; net_it < netCount; net_it++) {
451 		cout << myIndentation + " Net " << net_it << ":" << NetName(net_it) << endl;
452 		if ( netVoltagePtr_v[net_it].full ) {
453 			netVoltagePtr_v[net_it].full->Print(cout, myIndentation + "  ");
454 //			if ( IsCalculatedVoltage_(netVoltagePtr_v[net_it]) ) {
455 //				netVoltagePtr_v[net_it]->Print(cout, myIndentation + "  =>");
456 //			} else {
457 //				netVoltagePtr_v[net_it]->Print(cout, myIndentation + "  ");
458 //			}
459 		}
460 		if ( firstSource_v[net_it] != UNKNOWN_DEVICE ) PrintConnections(connectionCount_v[net_it].sourceCount, firstSource_v[net_it], nextSource_v, myIndentation + "  ", "SourceConnections");
461 		if ( firstDrain_v[net_it] != UNKNOWN_DEVICE ) PrintConnections(connectionCount_v[net_it].drainCount, firstDrain_v[net_it], nextDrain_v, myIndentation + "  ", "DrainConnections");
462 		if ( firstGate_v[net_it] != UNKNOWN_DEVICE ) PrintConnections(connectionCount_v[net_it].gateCount, firstGate_v[net_it], nextGate_v, myIndentation + "  ", "GateConnections");
463 		if ( myBulkCount[net_it] > 0 ) PrintBulkConnections(net_it, myIndentation + "  ", "BulkConnections");
464 //		if ( firstBulk_v[net_it] != UNKNOWN_DEVICE ) PrintConnections(connectionCount_v[net_it].bulkCount, firstBulk_v[net_it], nextBulk_v, myIndentation + "  ", "BulkConnections");
465 		if ( connectionCount_v[net_it].sourceCount + connectionCount_v[net_it].drainCount > 0 ) {
466 			PrintSourceDrainConnections(connectionCount_v[net_it].sourceDrainType, myIndentation + "  ");
467 		}
468 	}
469 	cout << myIndentation << "NetList> end" << endl << endl;
470 	cout << myIndentation << "DeviceList> start" << endl;
471 	for (deviceId_t device_it = 0; device_it < deviceCount; device_it++) {
472 		cout << myIndentation + " Device " << device_it << ":";
473 		cout << gModelTypeMap[deviceType_v[device_it]] << " ";
474 		cout << DeviceName(device_it, PRINT_CIRCUIT_ON) << "@" << parameterResistanceMap[DeviceParameters(device_it)];
475 		cout << " Status: " << StatusString(deviceStatus_v[device_it]) << endl;
476 	}
477 	cout << myIndentation << "DeviceList> end" << endl << endl;
478 	PrintPowerList(cout, "PowerList", myIndentation);
479 /*
480 	cout << myIndentation << "PowerList> start" << endl;
481 	string myRealPowerName;
482 	for (CPowerPtrList::iterator power_ppit = cvcParameters.cvcPowerPtrList.begin(); power_ppit != cvcParameters.cvcPowerPtrList.end(); power_ppit++) {
483 		myRealPowerName = NetName((*power_ppit)->baseNetId);
484 		(*power_ppit)->Print(myIndentation + " ", myRealPowerName);
485 	}
486 	cout << myIndentation << "PowerList> end" << endl << endl;
487 */
488 
489 	PrintEquivalentNets(myIndentation);
490 	PrintInverterNets(myIndentation);
491 
492 	cout << theIndentation << theHeading << " end" << endl << endl;
493 }
494 
PrintVirtualNets(CVirtualNetVector & theVirtualNet_v,string theTitle,string theIndentation)495 void CCvcDb::PrintVirtualNets(CVirtualNetVector& theVirtualNet_v, string theTitle, string theIndentation) {
496 	cout << theIndentation << "VirtualNetVector" << theTitle << "> start " << theVirtualNet_v.size() << endl;
497 	netId_t myEquivalentNet;
498 	for ( netId_t net_it = 0; net_it < theVirtualNet_v.size(); net_it++ ) {
499 		myEquivalentNet = equivalentNet_v[theVirtualNet_v[net_it].nextNetId];
500 		CPower * myPower_p = netVoltagePtr_v[myEquivalentNet].full;
501 		if ( myPower_p && myPower_p->netId != UNKNOWN_NET ) {
502 			myEquivalentNet = myPower_p->netId;
503 		}
504 		cout << theIndentation + "  ";
505 		if ( net_it == myEquivalentNet ) {
506 			if ( myPower_p ) {
507 				cout << net_it << "=>";
508 				if ( myPower_p->minVoltage != UNKNOWN_VOLTAGE ) {
509 					cout << myPower_p->minVoltage;
510 				}
511 				cout << "/";
512 				if ( myPower_p->simVoltage != UNKNOWN_VOLTAGE ) {
513 					cout << myPower_p->simVoltage;
514 				}
515 				cout << "/";
516 				if ( myPower_p->maxVoltage != UNKNOWN_VOLTAGE ) {
517 					cout << myPower_p->maxVoltage;
518 				}
519 				cout << endl;
520 			} else {
521 				cout << net_it << "??" << endl;
522 			}
523 		} else {
524 			cout << net_it << "->" << myEquivalentNet << "@" << theVirtualNet_v[net_it].resistance << endl;
525 		}
526 	}
527 	cout << theIndentation << "VirtualNetVector" << theTitle << "> end" << endl;
528 }
529 
PrintDeviceWithAllConnections(instanceId_t theParentId,CFullConnection & theConnections,ogzstream & theErrorFile,bool theIncludeLeakVoltage)530 void CCvcDb::PrintDeviceWithAllConnections(instanceId_t theParentId, CFullConnection& theConnections, ogzstream& theErrorFile, bool theIncludeLeakVoltage) {
531 	int myMFactor = CalculateMFactor(theParentId);
532 	theErrorFile << DeviceName(theConnections.device_p->name, theParentId, PRINT_CIRCUIT_ON) << " " << theConnections.device_p->parameters;
533 	if ( myMFactor > 1 ) theErrorFile << " {m=" << myMFactor << "}";
534 	theErrorFile << " (r=" << parameterResistanceMap[theConnections.device_p->parameters] << ")" << endl;
535 	switch ( theConnections.device_p->model_p->type ) {
536 		case NMOS: case PMOS: case LDDN: case LDDP: {
537 			PrintAllTerminalConnections(GATE, theConnections, theErrorFile, theIncludeLeakVoltage);
538 			PrintAllTerminalConnections(SOURCE, theConnections, theErrorFile, theIncludeLeakVoltage);
539 			PrintAllTerminalConnections(DRAIN, theConnections, theErrorFile, theIncludeLeakVoltage);
540 			if ( ! cvcParameters.cvcSOI ) PrintAllTerminalConnections(BULK, theConnections, theErrorFile, theIncludeLeakVoltage);
541 		break; }
542 		case RESISTOR: case CAPACITOR: case DIODE: case FUSE_OFF: case FUSE_ON: case SWITCH_ON: case SWITCH_OFF: {
543 			PrintAllTerminalConnections(SOURCE, theConnections, theErrorFile, theIncludeLeakVoltage);
544 			PrintAllTerminalConnections(DRAIN, theConnections, theErrorFile, theIncludeLeakVoltage);
545 			if ( theConnections.originalBulkId != UNKNOWN_NET) {
546 				PrintAllTerminalConnections(BULK, theConnections, theErrorFile, theIncludeLeakVoltage);
547 			}
548 		break; }
549 		case BIPOLAR: {
550 			PrintAllTerminalConnections(SOURCE, theConnections, theErrorFile, theIncludeLeakVoltage);
551 			PrintAllTerminalConnections(GATE, theConnections, theErrorFile, theIncludeLeakVoltage);
552 			PrintAllTerminalConnections(DRAIN, theConnections, theErrorFile, theIncludeLeakVoltage);
553 		break; }
554 		default: {
555 			throw EDatabaseError("Invalid device type: " + theConnections.device_p->model_p->type);
556 		}
557 	}
558 }
559 
PrintDeviceWithSimConnections(instanceId_t theParentId,CFullConnection & theConnections,ogzstream & theErrorFile)560 void CCvcDb::PrintDeviceWithSimConnections(instanceId_t theParentId, CFullConnection& theConnections, ogzstream& theErrorFile) {
561 	int myMFactor = CalculateMFactor(theParentId);
562 	theErrorFile << DeviceName(theConnections.device_p->name, theParentId, PRINT_CIRCUIT_ON) << " " << theConnections.device_p->parameters;
563 	if ( myMFactor > 1 ) theErrorFile << " {m=" << myMFactor << "}";
564 	theErrorFile << " (r=" << parameterResistanceMap[theConnections.device_p->parameters] << ")" << endl;
565 	switch ( theConnections.device_p->model_p->type ) {
566 		case NMOS: case PMOS: case LDDN: case LDDP: {
567 			PrintSimTerminalConnections(GATE, theConnections, theErrorFile);
568 			PrintSimTerminalConnections(SOURCE, theConnections, theErrorFile);
569 			PrintSimTerminalConnections(DRAIN, theConnections, theErrorFile);
570 			if ( ! cvcParameters.cvcSOI ) PrintSimTerminalConnections(BULK, theConnections, theErrorFile);
571 		break; }
572 		case RESISTOR: case CAPACITOR: case DIODE: case FUSE_OFF: case FUSE_ON: case SWITCH_ON: case SWITCH_OFF: {
573 			PrintSimTerminalConnections(SOURCE, theConnections, theErrorFile);
574 			PrintSimTerminalConnections(DRAIN, theConnections, theErrorFile);
575 			if ( theConnections.originalBulkId != UNKNOWN_NET) {
576 				PrintSimTerminalConnections(BULK, theConnections, theErrorFile);
577 			}
578 		break; }
579 		case BIPOLAR: {
580 			PrintSimTerminalConnections(SOURCE, theConnections, theErrorFile);
581 			PrintSimTerminalConnections(GATE, theConnections, theErrorFile);
582 			PrintSimTerminalConnections(DRAIN, theConnections, theErrorFile);
583 		break; }
584 		default: {
585 			throw EDatabaseError("Invalid device type: " + theConnections.device_p->model_p->type);
586 		}
587 	}
588 }
589 
PrintVoltage(voltage_t theVoltage)590 string CCvcDb::PrintVoltage(voltage_t theVoltage) {
591 	if ( theVoltage == UNKNOWN_VOLTAGE ) {
592 		return "???";
593 	} else {
594 		return to_string<voltage_t>(theVoltage);
595 	}
596 }
597 
PrintVoltage(voltage_t theVoltage,CPower * thePower_p)598 string CCvcDb::PrintVoltage(voltage_t theVoltage, CPower * thePower_p) {
599 	if ( theVoltage == UNKNOWN_VOLTAGE ) {
600 		if ( thePower_p && thePower_p->type[HIZ_BIT] ) {
601 			return "open";
602 		} else {
603 			return "???";
604 		}
605 	} else {
606 		return to_string<voltage_t>(theVoltage);
607 	}
608 }
609 
PrintAllTerminalConnections(terminal_t theTerminal,CFullConnection & theConnections,ogzstream & theErrorFile,bool theIncludeLeakVoltage)610 void CCvcDb::PrintAllTerminalConnections(terminal_t theTerminal, CFullConnection& theConnections, ogzstream& theErrorFile, bool theIncludeLeakVoltage) {
611 	netId_t myNetId, myMinNetId, mySimNetId, myMaxNetId;
612 	string myMinVoltageString, mySimVoltageString, myMaxVoltageString;
613 	string myMinLeakVoltageString = "", myMaxLeakVoltageString = "";
614 	string myMinPowerDelimiter, mySimPowerDelimiter, myMaxPowerDelimiter;
615 	resistance_t myMinResistance;
616 	resistance_t mySimResistance;
617 	resistance_t myMaxResistance;
618 	switch (theTerminal) {
619 		case GATE: {
620 			theErrorFile << (theConnections.device_p->model_p->type == BIPOLAR ? "B: " : "G: ");
621 			myNetId = theConnections.originalGateId;
622 			myMinNetId = theConnections.masterMinGateNet.finalNetId;
623 			myMinResistance = theConnections.masterMinGateNet.finalResistance;
624 			myMinVoltageString = PrintVoltage(theConnections.minGateVoltage, theConnections.minGatePower_p);
625 			myMinPowerDelimiter = PowerDelimiter_(theConnections.minGatePower_p, MIN_CALCULATED_BIT);
626 			if ( theIncludeLeakVoltage && theConnections.minGateVoltage != theConnections.minGateLeakVoltage ) {
627 				myMinLeakVoltageString = PrintVoltage(theConnections.minGateLeakVoltage, (CPower *) NULL);;
628 			}
629 			mySimNetId = theConnections.masterSimGateNet.finalNetId;
630 			mySimResistance = theConnections.masterSimGateNet.finalResistance;
631 			mySimVoltageString = PrintVoltage(theConnections.simGateVoltage, theConnections.simGatePower_p);
632 			mySimPowerDelimiter = PowerDelimiter_(theConnections.simGatePower_p, SIM_CALCULATED_BIT);
633 			myMaxNetId = theConnections.masterMaxGateNet.finalNetId;
634 			myMaxResistance = theConnections.masterMaxGateNet.finalResistance;
635 			myMaxVoltageString = PrintVoltage(theConnections.maxGateVoltage, theConnections.maxGatePower_p);
636 			myMaxPowerDelimiter = PowerDelimiter_(theConnections.maxGatePower_p, MAX_CALCULATED_BIT);
637 			if ( theIncludeLeakVoltage && theConnections.maxGateVoltage != theConnections.maxGateLeakVoltage ) {
638 				myMaxLeakVoltageString = PrintVoltage(theConnections.maxGateLeakVoltage, (CPower *) NULL);;
639 			}
640 		break; }
641 		case SOURCE: {
642 			theErrorFile << (theConnections.device_p->model_p->type == BIPOLAR ? "C: " : "S: ");
643 			myNetId = theConnections.originalSourceId;
644 			myMinNetId = theConnections.masterMinSourceNet.finalNetId;
645 			myMinResistance = theConnections.masterMinSourceNet.finalResistance;
646 			myMinVoltageString = PrintVoltage(theConnections.minSourceVoltage, theConnections.minSourcePower_p);
647 			myMinPowerDelimiter = PowerDelimiter_(theConnections.minSourcePower_p, MIN_CALCULATED_BIT);
648 			if ( theIncludeLeakVoltage && theConnections.minSourceVoltage != theConnections.minSourceLeakVoltage ) {
649 				myMinLeakVoltageString = PrintVoltage(theConnections.minSourceLeakVoltage, (CPower *) NULL);;
650 			}
651 			mySimNetId = theConnections.masterSimSourceNet.finalNetId;
652 			mySimResistance = theConnections.masterSimSourceNet.finalResistance;
653 			mySimVoltageString = PrintVoltage(theConnections.simSourceVoltage, theConnections.simSourcePower_p);
654 			mySimPowerDelimiter = PowerDelimiter_(theConnections.simSourcePower_p, SIM_CALCULATED_BIT);
655 			myMaxNetId = theConnections.masterMaxSourceNet.finalNetId;
656 			myMaxResistance = theConnections.masterMaxSourceNet.finalResistance;
657 			myMaxVoltageString = PrintVoltage(theConnections.maxSourceVoltage, theConnections.maxSourcePower_p);
658 			myMaxPowerDelimiter = PowerDelimiter_(theConnections.maxSourcePower_p, MAX_CALCULATED_BIT);
659 			if ( theIncludeLeakVoltage && theConnections.maxSourceVoltage != theConnections.maxSourceLeakVoltage ) {
660 				myMaxLeakVoltageString = PrintVoltage(theConnections.maxSourceLeakVoltage, (CPower *) NULL);;
661 			}
662 		break; }
663 		case DRAIN: {
664 			theErrorFile << (theConnections.device_p->model_p->type == BIPOLAR ? "E: " : "D: ");
665 			myNetId = theConnections.originalDrainId;
666 			myMinNetId = theConnections.masterMinDrainNet.finalNetId;
667 			myMinResistance = theConnections.masterMinDrainNet.finalResistance;
668 			myMinVoltageString = PrintVoltage(theConnections.minDrainVoltage, theConnections.minDrainPower_p);
669 			myMinPowerDelimiter = PowerDelimiter_(theConnections.minDrainPower_p, MIN_CALCULATED_BIT);
670 			if ( theIncludeLeakVoltage && theConnections.minDrainVoltage != theConnections.minDrainLeakVoltage ) {
671 				myMinLeakVoltageString = PrintVoltage(theConnections.minDrainLeakVoltage, (CPower *) NULL);;
672 			}
673 			mySimNetId = theConnections.masterSimDrainNet.finalNetId;
674 			mySimResistance = theConnections.masterSimDrainNet.finalResistance;
675 			mySimVoltageString = PrintVoltage(theConnections.simDrainVoltage, theConnections.simDrainPower_p);
676 			mySimPowerDelimiter = PowerDelimiter_(theConnections.simDrainPower_p, SIM_CALCULATED_BIT);
677 			myMaxNetId = theConnections.masterMaxDrainNet.finalNetId;
678 			myMaxResistance = theConnections.masterMaxDrainNet.finalResistance;
679 			myMaxVoltageString = PrintVoltage(theConnections.maxDrainVoltage, theConnections.maxDrainPower_p);
680 			myMaxPowerDelimiter = PowerDelimiter_(theConnections.maxDrainPower_p, MAX_CALCULATED_BIT);
681 			if ( theIncludeLeakVoltage && theConnections.maxDrainVoltage != theConnections.maxDrainLeakVoltage ) {
682 				myMaxLeakVoltageString = PrintVoltage(theConnections.maxDrainLeakVoltage, (CPower *) NULL);;
683 			}
684 		break; }
685 		case BULK: {
686 			theErrorFile << "B: ";
687 			myNetId = theConnections.originalBulkId;
688 			myMinNetId = theConnections.masterMinBulkNet.finalNetId;
689 			myMinResistance = theConnections.masterMinBulkNet.finalResistance;
690 			myMinVoltageString = PrintVoltage(theConnections.minBulkVoltage, theConnections.minBulkPower_p);
691 			myMinPowerDelimiter = PowerDelimiter_(theConnections.minBulkPower_p, MIN_CALCULATED_BIT);
692 			if ( theIncludeLeakVoltage && theConnections.minBulkVoltage != theConnections.minBulkLeakVoltage ) {
693 				myMinLeakVoltageString = PrintVoltage(theConnections.minBulkLeakVoltage, (CPower *) NULL);;
694 			}
695 			mySimNetId = theConnections.masterSimBulkNet.finalNetId;
696 			mySimResistance = theConnections.masterSimBulkNet.finalResistance;
697 			mySimVoltageString = PrintVoltage(theConnections.simBulkVoltage, theConnections.simBulkPower_p);
698 			mySimPowerDelimiter = PowerDelimiter_(theConnections.simBulkPower_p, SIM_CALCULATED_BIT);
699 			myMaxNetId = theConnections.masterMaxBulkNet.finalNetId;
700 			myMaxResistance = theConnections.masterMaxBulkNet.finalResistance;
701 			myMaxVoltageString = PrintVoltage(theConnections.maxBulkVoltage, theConnections.maxBulkPower_p);
702 			myMaxPowerDelimiter = PowerDelimiter_(theConnections.maxBulkPower_p, MAX_CALCULATED_BIT);
703 			if ( theIncludeLeakVoltage && theConnections.maxBulkVoltage != theConnections.maxBulkLeakVoltage ) {
704 				myMaxLeakVoltageString = PrintVoltage(theConnections.maxBulkLeakVoltage, (CPower *) NULL);;
705 			}
706 		break; }
707 		default: { throw EDatabaseError("Invalid terminal type: " + theTerminal); }
708 	}
709 	theErrorFile << NetName(myNetId) << endl;
710 	theErrorFile << " Min: " << NetName(myMinNetId) << NetVoltageSuffix(myMinPowerDelimiter, myMinVoltageString, myMinResistance, myMinLeakVoltageString) << endl;
711 	theErrorFile << " Sim: " << NetName(mySimNetId) << NetVoltageSuffix(mySimPowerDelimiter, mySimVoltageString, mySimResistance) << endl;
712 	theErrorFile << " Max: " << NetName(myMaxNetId) << NetVoltageSuffix(myMaxPowerDelimiter, myMaxVoltageString, myMaxResistance, myMaxLeakVoltageString) << endl;
713 }
714 
PrintSimTerminalConnections(terminal_t theTerminal,CFullConnection & theConnections,ogzstream & theErrorFile)715 void CCvcDb::PrintSimTerminalConnections(terminal_t theTerminal, CFullConnection& theConnections, ogzstream& theErrorFile) {
716 	netId_t myNetId, mySimNetId;
717 	string mySimVoltageString;
718 	string mySimPowerDelimiter;
719 	resistance_t mySimResistance;
720 	switch (theTerminal) {
721 		case GATE: {
722 			theErrorFile << (theConnections.device_p->model_p->type == BIPOLAR ? "B: " : "G: ");
723 			myNetId = theConnections.originalGateId;
724 			mySimNetId = theConnections.masterSimGateNet.finalNetId;
725 			mySimResistance = theConnections.masterSimGateNet.finalResistance;
726 			mySimVoltageString = PrintVoltage(theConnections.simGateVoltage, theConnections.simGatePower_p);
727 			mySimPowerDelimiter = PowerDelimiter_(theConnections.simGatePower_p, SIM_CALCULATED_BIT);
728 		break; }
729 		case SOURCE: {
730 			theErrorFile << (theConnections.device_p->model_p->type == BIPOLAR ? "C: " : "S: ");
731 			myNetId = theConnections.originalSourceId;
732 			mySimNetId = theConnections.masterSimSourceNet.finalNetId;
733 			mySimResistance = theConnections.masterSimSourceNet.finalResistance;
734 			mySimVoltageString = PrintVoltage(theConnections.simSourceVoltage, theConnections.simSourcePower_p);
735 			mySimPowerDelimiter = PowerDelimiter_(theConnections.simSourcePower_p, SIM_CALCULATED_BIT);
736 		break; }
737 		case DRAIN: {
738 			theErrorFile << (theConnections.device_p->model_p->type == BIPOLAR ? "E: " : "D: ");
739 			myNetId = theConnections.originalDrainId;
740 			mySimNetId = theConnections.masterSimDrainNet.finalNetId;
741 			mySimResistance = theConnections.masterSimDrainNet.finalResistance;
742 			mySimVoltageString = PrintVoltage(theConnections.simDrainVoltage, theConnections.simDrainPower_p);
743 			mySimPowerDelimiter = PowerDelimiter_(theConnections.simDrainPower_p, SIM_CALCULATED_BIT);
744 		break; }
745 		case BULK: {
746 			theErrorFile << "B: ";
747 			myNetId = theConnections.originalBulkId;
748 			mySimNetId = theConnections.masterSimBulkNet.finalNetId;
749 			mySimResistance = theConnections.masterSimBulkNet.finalResistance;
750 			mySimVoltageString = PrintVoltage(theConnections.simBulkVoltage, theConnections.simBulkPower_p);
751 			mySimPowerDelimiter = PowerDelimiter_(theConnections.simBulkPower_p, SIM_CALCULATED_BIT);
752 		break; }
753 		default: { throw EDatabaseError("Invalid terminal type: " + theTerminal); }
754 	}
755 	theErrorFile << NetName(myNetId) << endl;
756 	theErrorFile << " Sim: " << NetName(mySimNetId) << NetVoltageSuffix(mySimPowerDelimiter, mySimVoltageString, mySimResistance) << endl;
757 }
758 
PrintErrorTotals()759 void CCvcDb::PrintErrorTotals() {
760 	reportFile << "CVC: Error Counts" << endl;
761 	reportFile << "CVC: Fuse Problems:         " << errorCount[FUSE_ERROR] << endl;
762 	reportFile << "CVC: Min Voltage Conflicts: " << errorCount[MIN_VOLTAGE_CONFLICT] << endl;
763 	reportFile << "CVC: Max Voltage Conflicts: " << errorCount[MAX_VOLTAGE_CONFLICT] << endl;
764 	reportFile << "CVC: Leaks:                 " << errorCount[LEAK] << endl;
765 	if ( detectErrorFlag ) {
766 		reportFile << "CVC: LDD drain->source:     " << errorCount[LDD_SOURCE] << endl;
767 		reportFile << "CVC: HI-Z Inputs:           " << errorCount[HIZ_INPUT] << endl;
768 		reportFile << "CVC: Forward Bias Diodes:   " << errorCount[FORWARD_DIODE] << endl;
769 		if ( ! cvcParameters.cvcSOI ) reportFile << "CVC: NMOS Source vs Bulk:   " << errorCount[NMOS_SOURCE_BULK] << endl;
770 		reportFile << "CVC: NMOS Gate vs Source:   " << errorCount[NMOS_GATE_SOURCE] << endl;
771 		reportFile << "CVC: NMOS Possible Leaks:   " << errorCount[NMOS_POSSIBLE_LEAK] << endl;
772 		if ( ! cvcParameters.cvcSOI ) reportFile << "CVC: PMOS Source vs Bulk:   " << errorCount[PMOS_SOURCE_BULK] << endl;
773 		reportFile << "CVC: PMOS Gate vs Source:   " << errorCount[PMOS_GATE_SOURCE] << endl;
774 		reportFile << "CVC: PMOS Possible Leaks:   " << errorCount[PMOS_POSSIBLE_LEAK] << endl;
775 		reportFile << "CVC: Overvoltage-VBG:       " << errorCount[OVERVOLTAGE_VBG] << endl;
776 		reportFile << "CVC: Overvoltage-VBS:       " << errorCount[OVERVOLTAGE_VBS] << endl;
777 		reportFile << "CVC: Overvoltage-VDS:       " << errorCount[OVERVOLTAGE_VDS] << endl;
778 		reportFile << "CVC: Overvoltage-VGS:       " << errorCount[OVERVOLTAGE_VGS] << endl;
779 		reportFile << "CVC: Model errors:          " << errorCount[MODEL_CHECK] << endl;
780 		reportFile << "CVC: Unexpected voltage :   " << errorCount[EXPECTED_VOLTAGE] << endl;
781 	} else {
782 		reportFile << "WARNING: Error detection incomplete" << endl;
783 	}
784 	size_t myErrorTotal = 0;
785 	for ( auto myIndex = 0; myIndex < ERROR_TYPE_COUNT; myIndex++ ) {
786 		myErrorTotal += errorCount[myIndex];
787 	}
788 	reportFile << "CVC: Total:                 " << myErrorTotal << endl;
789 }
790 
791 /*
792 void CCvcDb::PrintShortedNets(string theShortFileName) {
793 	cout << "CVC: Printing shorted nets to " << theShortFileName << " ..." << endl;
794 	ogzstream	shortFile(theShortFileName);
795 //	instanceId_t myLastParent = 0;
796 //	CInstance * myParent_p;
797 	netId_t mySimNet;
798 	resistance_t myResistance;
799 //	bool myPrintResistance;
800 	string myNetPrefix;
801 	for (netId_t net_it = 0; net_it < netCount; net_it++) {
802 		//changed to include sim paths
803 		mySimNet = simNet_v[GetEquivalentNet(net_it)].nextNetId;
804 		myResistance = simNet_v[GetEquivalentNet(net_it)].resistance;
805 		if ( net_it == mySimNet && ! netVoltagePtr_v[net_it] ) continue;
806 		if ( net_it != mySimNet ) shortFile << net_it << "->";
807 		shortFile << mySimNet;
808 		short_v[net_it].first = mySimNet;
809 		if ( netVoltagePtr_v[mySimNet] && netVoltagePtr_v[mySimNet]->simVoltage != UNKNOWN_VOLTAGE ) {
810 			if ( netVoltagePtr_v[mySimNet]->type[SIM_CALCULATED_BIT] ) {
811 				short_v[net_it].second = "=";
812 				if ( net_it < instancePtr_v[0]->master_p->portCount ) {
813 					logFile << "WARNING: possible missing input at net " << NetName(net_it);
814 					logFile << NetVoltageSuffix(PowerDelimiter_(netVoltagePtr_v[mySimNet], SIM_CALCULATED_BIT),
815 							PrintVoltage(netVoltagePtr_v[mySimNet]->simVoltage, netVoltagePtr_v[mySimNet]),
816 							simNet_v[mySimNet].finalResistance) << endl;
817 				}
818 			} else {
819 				short_v[net_it].second = "@";
820 			}
821 			short_v[net_it].second += PrintParameter(netVoltagePtr_v[mySimNet]->simVoltage, VOLTAGE_SCALE);
822 			if ( net_it != mySimNet ) short_v[net_it].second += " r=" + to_string<resistance_t>(myResistance);
823 			shortFile << short_v[net_it].second;
824 		} else {
825 			short_v[net_it].second = "";
826 		}
827 		shortFile << endl;
828 */
829 /*
830 // short file format
831 0@1200		<- power definition
832 1@0
833 2			<- defined voltage, but no simulation value
834 3
835 4
836 6@-500
837 7@0
838 8@1200
839 9@3300
840 14->13		<- switch short
841 15->16
842 17->18
843 20->8@1200 r=875	<- propagated voltage and resistance
844 21=210				<- calculated voltage
845 */
846 /*
847 
848 	}
849 	shortFile.close();
850 	isValidShortData = true;
851 }
852 */
853 
NetVoltageSuffix(string theDelimiter,string theVoltage,resistance_t theResistance,string theLeakVoltage)854 string CCvcDb::NetVoltageSuffix(string theDelimiter, string theVoltage, resistance_t theResistance, string theLeakVoltage) {
855 	if ( theVoltage == "???" && IsEmpty(theLeakVoltage) ) return ("");
856 	if ( ! IsEmpty(theLeakVoltage) ) theLeakVoltage = "(" + theLeakVoltage + ")";
857 	return ( theDelimiter + theVoltage + theLeakVoltage + " r=" + to_string<resistance_t>(theResistance));
858 }
859 
PrintResistorOverflow(netId_t theNet,ofstream & theOutputFile)860 void CCvcDb::PrintResistorOverflow(netId_t theNet, ofstream& theOutputFile) {
861 	theOutputFile << "WARNING: resistance exceeded 1G ohm at " << NetName(theNet, PRINT_CIRCUIT_ON) << endl;
862 }
863 
PrintClassSizes()864 void CCvcDb::PrintClassSizes() {
865 	cout << "CBaseVirtualNet " << sizeof(class CBaseVirtualNet) << endl;
866 //	cout << "CBaseVirtualNetVector " << sizeof(class CBaseVirtualNetVector) << endl;
867 //	cout << "CCdlParserDriver " << sizeof(class CCdlParserDriver) << endl;
868 	cout << "CCdlText " << sizeof(class CCdlText) << endl;
869 	cout << "CCircuit " << sizeof(class CCircuit) << endl;
870 	cout << "CCircuitPtrList " << sizeof(class CCircuitPtrList) << endl;
871 	cout << "CCondition " << sizeof(class CCondition) << endl;
872 	cout << "CConditionPtrList " << sizeof(class CConditionPtrList) << endl;
873 	cout << "CConnection " << sizeof(class CConnection) << endl;
874 	cout << "CConnectionCount " << sizeof(class CConnectionCount) << endl;
875 	cout << "CConnectionCountVector " << sizeof(class CConnectionCountVector) << endl;
876 	cout << "CCvcDb " << sizeof(class CCvcDb) << endl;
877 	cout << "CCvcParameters " << sizeof(class CCvcParameters) << endl;
878 	cout << "CDependencyMap " << sizeof(class CDependencyMap) << endl;
879 	cout << "CDevice " << sizeof(class CDevice) << endl;
880 	cout << "CDeviceCount " << sizeof(class CDeviceCount) << endl;
881 	cout << "CDeviceIdVector " << sizeof(class CDeviceIdVector) << endl;
882 	cout << "CDevicePtrList " << sizeof(class CDevicePtrList) << endl;
883 	cout << "CDevicePtrVector " << sizeof(class CDevicePtrVector) << endl;
884 	cout << "CEventList " << sizeof(class CEventList) << endl;
885 	cout << "CEventQueue " << sizeof(class CEventQueue) << endl;
886 	cout << "CEventSubQueue " << sizeof(class CEventSubQueue) << endl;
887 	cout << "CFixedText " << sizeof(class CFixedText) << endl;
888 	cout << "CFullConnection " << sizeof(class CFullConnection) << endl;
889 	cout << "CHierList " << sizeof(class CHierList) << endl;
890 	cout << "CInstance " << sizeof(class CInstance) << endl;
891 	cout << "CInstanceIdVector " << sizeof(class CInstanceIdVector) << endl;
892 	cout << "CInstancePtrVector " << sizeof(class CInstancePtrVector) << endl;
893 	cout << "CLeakList " << sizeof(class CLeakList) << endl;
894 	cout << "CLeakMap " << sizeof(class CLeakMap) << endl;
895 	cout << "CModel " << sizeof(class CModel) << endl;
896 	cout << "CModeList " << sizeof(class CModeList) << endl;
897 	cout << "CModelList " << sizeof(class CModelList) << endl;
898 	cout << "CModelListMap " << sizeof(class CModelListMap) << endl;
899 	cout << "CNetIdVector " << sizeof(class CNetIdVector) << endl;
900 	cout << "CNetList " << sizeof(class CNetList) << endl;
901 	cout << "CNetMap " << sizeof(class CNetMap) << endl;
902 	cout << "CNormalValue " << sizeof(class CNormalValue) << endl;
903 	cout << "CParameterMap " << sizeof(class CParameterMap) << endl;
904 	cout << "CPower " << sizeof(class CPower) << endl;
905 	cout << "CPowerFamilyMap " << sizeof(class CPowerFamilyMap) << endl;
906 	cout << "CPowerPtrList " << sizeof(class CPowerPtrList) << endl;
907 	cout << "CPowerPtrMap " << sizeof(class CPowerPtrMap) << endl;
908 	cout << "CPowerPtrVector " << sizeof(class CPowerPtrVector) << endl;
909 	cout << "CSet " << sizeof(class CSet) << endl;
910 	cout << "CShortVector " << sizeof(class CShortVector) << endl;
911 	cout << "CStatusVector " << sizeof(class CStatusVector) << endl;
912 	cout << "CStringList " << sizeof(class CStringList) << endl;
913 	cout << "CStringTextMap " << sizeof(class CStringTextMap) << endl;
914 	cout << "CTextCircuitPtrMap " << sizeof(class CTextCircuitPtrMap) << endl;
915 	cout << "CTextDeviceIdMap " << sizeof(class CTextDeviceIdMap) << endl;
916 	cout << "CTextInstanceIdMap " << sizeof(class CTextInstanceIdMap) << endl;
917 	cout << "CTextList " << sizeof(class CTextList) << endl;
918 	cout << "CTextModelPtrMap " << sizeof(class CTextModelPtrMap) << endl;
919 	cout << "CTextNetIdMap " << sizeof(class CTextNetIdMap) << endl;
920 	cout << "CTextResistanceMap " << sizeof(class CTextResistanceMap) << endl;
921 	cout << "CTextVector " << sizeof(class CTextVector) << endl;
922 //	cout << "CVirtualLeakNet " << sizeof(class CVirtualLeakNet) << endl;
923 //	cout << "CVirtualLeakNetVector " << sizeof(class CVirtualLeakNetVector) << endl;
924 	cout << "CVirtualNet " << sizeof(class CVirtualNet) << endl;
925 	cout << "CVirtualNetMappedVector " << sizeof(class CVirtualNetMappedVector) << endl;
926 	cout << "CVirtualNetVector " << sizeof(class CVirtualNetVector) << endl;
927 }
928 
PrintNetWithModelCounts(netId_t theNetId,int theTerminals)929 void CCvcDb::PrintNetWithModelCounts(netId_t theNetId, int theTerminals) {
930 	map<string, deviceId_t> myDeviceCount;
931 	for (CModelListMap::iterator keyModelListPair_pit = cvcParameters.cvcModelListMap.begin(); keyModelListPair_pit != cvcParameters.cvcModelListMap.end(); keyModelListPair_pit++) {
932 		for (CModelList::iterator model_pit = keyModelListPair_pit->second.begin(); model_pit != keyModelListPair_pit->second.end(); model_pit++) {
933 			myDeviceCount[model_pit->name] = 0;
934 		}
935 	}
936 	if ( theTerminals & GATE ) {
937 		for ( deviceId_t device_it = firstGate_v[theNetId]; device_it != UNKNOWN_NET; device_it = nextGate_v[device_it]) {
938 			CInstance * myInstance_p = instancePtr_v[deviceParent_v[device_it]];
939 			deviceId_t myDeviceOffset = device_it - myInstance_p->firstDeviceId;
940 			myDeviceCount[myInstance_p->master_p->devicePtr_v[myDeviceOffset]->model_p->name]++;
941 		}
942 	}
943 	if ( theTerminals & SOURCE ) {
944 		for ( deviceId_t device_it = firstSource_v[theNetId]; device_it != UNKNOWN_NET; device_it = nextSource_v[device_it]) {
945 			CInstance * myInstance_p = instancePtr_v[deviceParent_v[device_it]];
946 			deviceId_t myDeviceOffset = device_it - myInstance_p->firstDeviceId;
947 			myDeviceCount[myInstance_p->master_p->devicePtr_v[myDeviceOffset]->model_p->name]++;
948 		}
949 	}
950 	if ( theTerminals & DRAIN ) {
951 		for ( deviceId_t device_it = firstDrain_v[theNetId]; device_it != UNKNOWN_NET; device_it = nextDrain_v[device_it]) {
952 			CInstance * myInstance_p = instancePtr_v[deviceParent_v[device_it]];
953 			deviceId_t myDeviceOffset = device_it - myInstance_p->firstDeviceId;
954 			myDeviceCount[myInstance_p->master_p->devicePtr_v[myDeviceOffset]->model_p->name]++;
955 		}
956 	}
957 	reportFile << NetName(theNetId, PRINT_CIRCUIT_ON);
958 	for ( auto count_pit = myDeviceCount.begin(); count_pit != myDeviceCount.end(); count_pit++ ) {
959 		if ( count_pit->second > 0 ) {
960 			reportFile << " " << count_pit->first << "(" << count_pit->second << ")";
961 		}
962 	}
963 	reportFile << endl;
964 }
965 
PrintBackupNet(CVirtualNetVector & theVirtualNet_v,netId_t theNetId,string theTitle,ostream & theOutputFile)966 void CCvcDb::PrintBackupNet(CVirtualNetVector& theVirtualNet_v, netId_t theNetId, string theTitle, ostream& theOutputFile) {
967 	theOutputFile << theTitle << endl;
968 	theOutputFile << NetName(theNetId) << endl;
969 	netId_t myNetId = GetEquivalentNet(theNetId);
970 	if ( myNetId != theNetId ) cout << "=>" << NetName(myNetId) << endl;
971 	while ( myNetId != theVirtualNet_v[myNetId].backupNetId ) {
972 		theOutputFile << "->" << NetName(theVirtualNet_v[myNetId].backupNetId) << endl;
973 		myNetId = theVirtualNet_v[myNetId].backupNetId;
974 	}
975 	if ( leakVoltagePtr_v[myNetId].full ) leakVoltagePtr_v[myNetId].full->Print(theOutputFile);
976 	theOutputFile << endl;
977 }
978 
PrintLargeCircuits()979 void CCvcDb::PrintLargeCircuits() {
980 	for ( auto circuit_ppit = cvcCircuitList.begin(); circuit_ppit != cvcCircuitList.end(); circuit_ppit++ ) {
981 		if ( (*circuit_ppit)->deviceCount > cvcParameters.cvcLargeCircuitSize ) {
982 			for ( auto instance_pit = (*circuit_ppit)->instanceId_v.begin(); instance_pit != (*circuit_ppit)->instanceId_v.end(); instance_pit++ ) {
983 				debugFile << "INFO: Large circuit " << HierarchyName(*instance_pit, true, true) << " device count " << (*circuit_ppit)->deviceCount << endl;
984 			}
985 		}
986 	}
987 }
988 
989 
990 
991