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