1 /*
2 * CCvcDb_interactive.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 <bitset>
25 #include <cstddef>
26 #include <cstdint>
27 #include <list>
28 #include <map>
29 #include <memory>
30 #include <set>
31 #include <string>
32 #include <vector>
33 #include <regex>
34
35
36 #include "CCircuit.hh"
37 #include "CConnection.hh"
38 #include "CCvcDb.hh"
39 #include "CCvcExceptions.hh"
40 #include "CCvcParameters.hh"
41 #include "CDevice.hh"
42 #include "CEventQueue.hh"
43 #include "CInstance.hh"
44 #include "CModel.hh"
45 #include "CPower.hh"
46 #include "Cvc.hh"
47 #include "CvcTypes.hh"
48 #include "CVirtualNet.hh"
49 #include "gzstream.h"
50
51 //#include "readline.h"
52 #include <readline/readline.h>
53 // extern char * readline(const char * thePrompt);
54 #include <readline/history.h>
55 // extern void add_history(char * line_read);
56
57 extern int gContinueCount;
58
59 /* A static variable for holding the line. */
60 static char *line_read = (char *)NULL;
61
62 /* Read a string, and return a pointer to it. Returns NULL on EOF. */
63 char *
rl_gets(string thePrompt)64 rl_gets (string thePrompt) {
65 /* If the buffer has already been allocated, return the memory to the free pool. */
66 if (line_read) {
67 free (line_read);
68 line_read = (char *)NULL;
69 }
70
71 /* Get a line from the user. */
72 line_read = readline (thePrompt.c_str());
73
74 /* If the line has any text in it, save it on the history. */
75 if (line_read && *line_read) add_history (line_read);
76
77 return (line_read);
78 }
79
FindInstances(string theSubcircuit,bool thePrintCircuitFlag)80 void CCvcDb::FindInstances(string theSubcircuit, bool thePrintCircuitFlag) {
81 size_t myInstanceCount = 0;
82 try {
83 CCircuit * myCircuit_p = cvcCircuitList.FindCircuit(theSubcircuit);
84 for ( auto instance_pit = myCircuit_p->instanceId_v.begin(); instance_pit != myCircuit_p->instanceId_v.end(); instance_pit++ ) {
85 int myMFactor = CalculateMFactor(*instance_pit);
86 reportFile << HierarchyName(*instance_pit, thePrintCircuitFlag);
87 if ( myMFactor > 1 ) {
88 reportFile << " {m=" << myMFactor << "}";
89 myInstanceCount += myMFactor;
90 } else if ( instancePtr_v[*instance_pit]->IsParallelInstance() ) {
91 reportFile << " {parallel}";
92 } else {
93 myInstanceCount++;
94 }
95 reportFile << endl;
96 }
97 reportFile << "found " << myInstanceCount << " instances" << endl;
98 }
99 catch (const out_of_range& oor_exception) {
100 reportFile << "Searching for subcircuits matching " << theSubcircuit << endl;
101 size_t myMatchCount = 0;
102 vector<string> mySearchList;
103 try {
104 regex mySearchPattern(FuzzyFilter(theSubcircuit));
105 mySearchList.reserve(cvcParameters.cvcSearchLimit);
106 for( auto circuit_ppit = cvcCircuitList.begin(); circuit_ppit != cvcCircuitList.end(); circuit_ppit++) {
107 if ( regex_match((*circuit_ppit)->name, mySearchPattern) ) {
108 if ( myMatchCount++ < cvcParameters.cvcSearchLimit ) {
109 mySearchList.push_back(string((*circuit_ppit)->name) + " #instances: " + to_string<uintmax_t>((*circuit_ppit)->instanceCount));
110 }
111 }
112 }
113 if ( myMatchCount == 0 ) {
114 reportFile << "Could not find any subcircuits matching " << theSubcircuit << endl;
115 } else {
116 sort(mySearchList.begin(), mySearchList.end());
117 for ( size_t myIndex = 0; myIndex < mySearchList.size(); myIndex++ ) {
118 reportFile << mySearchList[myIndex] << endl;
119 }
120 reportFile << "Displayed " << mySearchList.size() << "/" << myMatchCount << " matches" << endl;
121 }
122 }
123 catch (const regex_error& myError) {
124 reportFile << "regex_error: " << RegexErrorString(myError.code()) << endl;
125 }
126 }
127 }
128
FindNets(string theName,instanceId_t theInstanceId,bool thePrintCircuitFlag)129 void CCvcDb::FindNets(string theName, instanceId_t theInstanceId, bool thePrintCircuitFlag) {
130 size_t myNetCount = 0;
131 cout << "Searching..." << endl;
132 gInterrupted = false;
133 regex mySearchPattern(FuzzyFilter(theName));
134 ShowNets(myNetCount, mySearchPattern, theInstanceId, thePrintCircuitFlag);
135 if ( gInterrupted ) cout << "Search cancelled" << endl;
136 reportFile << "Displayed " << ((myNetCount < cvcParameters.cvcSearchLimit) ? myNetCount : cvcParameters.cvcSearchLimit);
137 reportFile << "/" << myNetCount << " matches." << endl;
138 }
139
ShowNets(size_t & theNetCount,regex & theSearchPattern,instanceId_t theInstanceId,bool thePrintCircuitFlag)140 void CCvcDb::ShowNets(size_t & theNetCount, regex & theSearchPattern, instanceId_t theInstanceId, bool thePrintCircuitFlag) {
141 // updates theNetCount
142 if ( instancePtr_v[theInstanceId] == NULL ) return;
143 if ( instancePtr_v[theInstanceId]->IsParallelInstance() ) return;
144 CInstance * myInstance_p = instancePtr_v[theInstanceId];
145 if ( myInstance_p->master_p->subcircuitPtr_v.size() == 0 && myInstance_p->master_p->devicePtr_v.size() == 0 ) return;
146 for( auto signalMap_pit = myInstance_p->master_p->localSignalIdMap.begin(); signalMap_pit != myInstance_p->master_p->localSignalIdMap.end(); signalMap_pit++ ) {
147 if ( gInterrupted ) return;
148 if ( regex_match(signalMap_pit->first, theSearchPattern) ) {
149 if ( theNetCount++ < cvcParameters.cvcSearchLimit ) {
150 string myLowerNet = HierarchyName(theInstanceId, thePrintCircuitFlag) + "/" + signalMap_pit->first;
151 netId_t myNetId = myInstance_p->localToGlobalNetId_v[signalMap_pit->second];
152 netId_t myEquivalentNetId = (isFixedEquivalentNet) ? GetEquivalentNet(myNetId) : myNetId;
153 string myTopNet = NetName(myEquivalentNetId, thePrintCircuitFlag);
154 reportFile << myLowerNet;
155 if ( myLowerNet != myTopNet ) {
156 reportFile << " -> " << myTopNet;
157 }
158 reportFile << endl;
159 }
160 }
161 }
162 for( size_t instance_it = 0; instance_it != myInstance_p->master_p->subcircuitPtr_v.size(); instance_it++ ) {
163 ShowNets(theNetCount, theSearchPattern, myInstance_p->firstSubcircuitId + instance_it, thePrintCircuitFlag);
164 }
165 }
166
FindSubcircuit(string theSubcircuit)167 CCircuit * CCvcDb::FindSubcircuit(string theSubcircuit) {
168 try {
169 return(cvcCircuitList.FindCircuit(theSubcircuit));
170 }
171 catch (const out_of_range& oor_exception) {
172 reportFile << "Could not find subcircuit " << theSubcircuit << endl;
173 return(NULL);
174 }
175 }
176
PrintSubcircuitCdl(string theSubcircuit)177 void CCvcDb::PrintSubcircuitCdl(string theSubcircuit) {
178
179 CCircuit * myCircuit = FindSubcircuit(theSubcircuit);
180 if ( myCircuit == NULL ) return;
181
182 string myFileName = theSubcircuit + ".cdl";
183 ofstream myCdlFile(myFileName);
184 if (myCdlFile.fail()) {
185 reportFile << "Could not open " << myFileName << endl;
186 return;
187 }
188 unordered_set<text_t> myPrintedList;
189 PrintHierarchicalCdl(myCircuit, myPrintedList, myCdlFile);
190 myCdlFile << endl;
191 reportFile << "Wrote subcircuit " << theSubcircuit << " to " << theSubcircuit << ".cdl" << endl;
192 myCdlFile.close();
193 }
194
FindHierarchy(instanceId_t theCurrentInstanceId,string theHierarchy,bool theAllowPartialMatch,bool thePrintUnmatchFlag)195 instanceId_t CCvcDb::FindHierarchy(instanceId_t theCurrentInstanceId, string theHierarchy, bool theAllowPartialMatch, bool thePrintUnmatchFlag) {
196 // HIERARCHY_DELIMITER is only used to delimit hierarchy
197 if ( theHierarchy.find_first_of(cvcParameters.cvcHierarchyDelimiters, 0) == 0 ) { // starts with delimiter
198 theCurrentInstanceId = 0;
199 theHierarchy = theHierarchy.substr(1);
200 }
201 size_t myStringBegin = 0;
202 size_t myStringEnd;
203 string myInstanceName;
204 string myUnmatchedHierarchy = "";
205 instanceId_t myLocalInstanceId;
206 while ( myStringBegin <= theHierarchy.length() ) {
207 try {
208 myStringEnd = theHierarchy.find_first_of(cvcParameters.cvcHierarchyDelimiters, myStringBegin);
209 myInstanceName = theHierarchy.substr(myStringBegin, myStringEnd - myStringBegin);
210 try {
211 myInstanceName = myInstanceName.erase(myInstanceName.find_first_of("("));
212 }
213 catch (...) {
214 }
215 if ( ! IsEmpty(myUnmatchedHierarchy) ) {
216 myInstanceName = myUnmatchedHierarchy + HIERARCHY_DELIMITER + myInstanceName;
217 }
218 if ( myInstanceName == ".." ) {
219 theCurrentInstanceId = instancePtr_v[theCurrentInstanceId]->parentId;
220 } else {
221 myLocalInstanceId = instancePtr_v[theCurrentInstanceId]->master_p->GetLocalSubcircuitId(cvcCircuitList.cdlText.GetTextAddress(myInstanceName));
222 theCurrentInstanceId = instancePtr_v[theCurrentInstanceId]->firstSubcircuitId + myLocalInstanceId;
223 }
224 myUnmatchedHierarchy = "";
225 }
226 catch (const out_of_range& oor_exception) {
227 myUnmatchedHierarchy = myInstanceName;
228 }
229 myStringBegin = theHierarchy.find_first_not_of(cvcParameters.cvcHierarchyDelimiters, myStringEnd);
230 }
231 if ( IsEmpty(myUnmatchedHierarchy) || theAllowPartialMatch ) {
232 ; // For next searches, the last hierarchy may be part of a flattened hierarchy
233 } else {
234 theCurrentInstanceId = UNKNOWN_INSTANCE;
235 if ( thePrintUnmatchFlag ) {
236 reportFile << "Could not find instance " << myInstanceName << endl;
237 }
238 }
239 return ( theCurrentInstanceId );
240 }
241
ShortString(netId_t theNetId,bool thePrintSubcircuitNameFlag)242 string CCvcDb::ShortString(netId_t theNetId, bool thePrintSubcircuitNameFlag) {
243 string myShortString = "";
244 if ( netVoltagePtr_v[theNetId].full ) {
245 string myStandardDefinition = netVoltagePtr_v[theNetId].full->StandardDefinition();
246 if ( IsCalculatedVoltage_(netVoltagePtr_v[theNetId].full) ) {
247 myShortString += " calculated as";
248 } else {
249 myShortString += " defined as ";
250 }
251 if ( string(netVoltagePtr_v[theNetId].full->definition) != myStandardDefinition ) {
252 myShortString = myShortString + netVoltagePtr_v[theNetId].full->definition + " => ";
253 }
254 myShortString += myStandardDefinition;
255 }
256 return myShortString;
257 }
258
LeakShortString(netId_t theNetId,bool thePrintSubcircuitNameFlag)259 string CCvcDb::LeakShortString(netId_t theNetId, bool thePrintSubcircuitNameFlag) {
260 string myShortString = "";
261 CPower * myLeakPower_p = leakVoltagePtr_v[theNetId].full;
262 if ( myLeakPower_p ) {
263 string myStandardDefinition = myLeakPower_p->StandardDefinition();
264 if ( IsCalculatedVoltage_(myLeakPower_p) ) {
265 myShortString += " calculated as";
266 } else {
267 myShortString += " defined as ";
268 }
269 if ( string(myLeakPower_p->definition) != myStandardDefinition ) {
270 myShortString = myShortString + myLeakPower_p->definition + " => ";
271 }
272 myShortString += myStandardDefinition;
273 }
274 return myShortString;
275 }
276
PrintParallelInstance(instanceId_t theInstanceId,bool thePrintSubcircuitNameFlag)277 void CCvcDb::PrintParallelInstance(instanceId_t theInstanceId, bool thePrintSubcircuitNameFlag) {
278 reportFile << "Parallel Instance: " << HierarchyName(theInstanceId, thePrintSubcircuitNameFlag) << endl;
279 if ( instancePtr_v[theInstanceId]->parallelInstanceId != 0 ) {
280 reportFile << "Merged with: " << HierarchyName(instancePtr_v[theInstanceId]->parallelInstanceId, thePrintSubcircuitNameFlag) << endl;
281 } else {
282 instanceId_t myInstanceId = theInstanceId;
283 while ( instancePtr_v[myInstanceId]->IsParallelInstance() && instancePtr_v[myInstanceId]->parallelInstanceId == 0 ) {
284 myInstanceId = instancePtr_v[myInstanceId]->parentId;
285 }
286 reportFile << "Merged at: " << HierarchyName(instancePtr_v[myInstanceId]->parallelInstanceId, thePrintSubcircuitNameFlag) << endl;
287 }
288 }
289
PrintNets(instanceId_t theCurrentInstanceId,string theFilter,bool thePrintSubcircuitNameFlag,bool theIsValidPowerFlag)290 void CCvcDb::PrintNets(instanceId_t theCurrentInstanceId, string theFilter, bool thePrintSubcircuitNameFlag, bool theIsValidPowerFlag) {
291 if ( instancePtr_v[theCurrentInstanceId]->IsParallelInstance() ) {
292 PrintParallelInstance(theCurrentInstanceId, thePrintSubcircuitNameFlag);
293 return;
294 }
295 CCircuit * myMasterCircuit_p = instancePtr_v[theCurrentInstanceId]->master_p;
296 CTextVector mySignal_v;
297 stringstream myNetString;
298 netId_t myGlobalNetId;
299 vector<string> mySearchList;
300 size_t myMatchCount = 0;
301 try {
302 regex mySearchPattern(FuzzyFilter(theFilter));
303 mySignal_v.reserve(myMasterCircuit_p->localSignalIdMap.size());
304 mySearchList.reserve(mySignal_v.capacity());
305 for ( auto pair_pit = myMasterCircuit_p->localSignalIdMap.begin(); pair_pit != myMasterCircuit_p->localSignalIdMap.end(); pair_pit++ ) {
306 mySignal_v[pair_pit->second] = pair_pit->first;
307 }
308 for ( netId_t net_it = 0; net_it < myMasterCircuit_p->localSignalIdMap.size(); net_it++ ) {
309 if ( net_it == myMasterCircuit_p->portCount && net_it != 0 ) {
310 reportFile << "Ports:" << endl;
311 sort(mySearchList.begin(), mySearchList.end());
312 for ( size_t myIndex = 0; myIndex < mySearchList.size(); myIndex++ ) {
313 reportFile << mySearchList[myIndex] << endl;
314 }
315 reportFile << "Displayed " << mySearchList.size() << "/" << myMatchCount << " matches" << endl;
316 myMatchCount = 0;
317 mySearchList.clear();
318 }
319 myGlobalNetId = instancePtr_v[theCurrentInstanceId]->localToGlobalNetId_v[net_it];
320 string myGlobalNet = "";
321 if ( thePrintSubcircuitNameFlag ) {
322 myGlobalNet = "(";
323 myGlobalNet += NetName(myGlobalNetId, false);
324 myGlobalNet += ")";
325 }
326 myNetString.str("");
327 myNetString << mySignal_v[net_it] << myGlobalNet << ((theIsValidPowerFlag) ? ShortString(myGlobalNetId, thePrintSubcircuitNameFlag) : "");
328 if ( IsEmpty(theFilter) || regex_match(mySignal_v[net_it], mySearchPattern) ) {
329 if ( myMatchCount++ < cvcParameters.cvcSearchLimit ) {
330 mySearchList.push_back(myNetString.str());
331 }
332 }
333 }
334 reportFile << "Internal nets:" << endl;
335 sort(mySearchList.begin(), mySearchList.end());
336 for ( size_t myIndex = 0; myIndex < mySearchList.size(); myIndex++ ) {
337 reportFile << mySearchList[myIndex] << endl;
338 }
339 reportFile << "Displayed " << mySearchList.size() << "/" << myMatchCount << " matches" << endl;
340 }
341 catch (const regex_error& myError) {
342 reportFile << "regex_error: " << RegexErrorString(myError.code()) << endl;
343 }
344
345 }
346
PrintDevices(instanceId_t theCurrentInstanceId,string theFilter,bool thePrintSubcircuitNameFlag,bool theIsValidModelFlag)347 void CCvcDb::PrintDevices(instanceId_t theCurrentInstanceId, string theFilter, bool thePrintSubcircuitNameFlag, bool theIsValidModelFlag) {
348 if ( instancePtr_v[theCurrentInstanceId]->IsParallelInstance() ) {
349 PrintParallelInstance(theCurrentInstanceId, thePrintSubcircuitNameFlag);
350 return;
351 }
352 string myParameters = "";
353 stringstream myDeviceString;
354 vector<string> mySearchList;
355 size_t myMatchCount = 0;
356 try {
357 regex mySearchPattern(FuzzyFilter(theFilter));
358 CCircuit * myMasterCircuit_p = instancePtr_v[theCurrentInstanceId]->master_p;
359 mySearchList.reserve(myMasterCircuit_p->devicePtr_v.size());
360 for ( auto device_ppit = myMasterCircuit_p->devicePtr_v.begin();
361 device_ppit != myMasterCircuit_p->devicePtr_v.end(); device_ppit++ ) {
362 if ( thePrintSubcircuitNameFlag ) {
363 myParameters = "(";
364 myParameters += (*device_ppit)->parameters;
365 myParameters += ")";
366 }
367 myDeviceString.str("");
368 myDeviceString << (*device_ppit)->name << myParameters << " " << ((theIsValidModelFlag) ? (*device_ppit)->model_p->definition : "" );
369 if ( IsEmpty(theFilter) || regex_match((*device_ppit)->name, mySearchPattern) ) {
370 if ( myMatchCount++ < cvcParameters.cvcSearchLimit ) {
371 mySearchList.push_back(myDeviceString.str());
372 }
373 }
374 }
375 sort(mySearchList.begin(), mySearchList.end());
376 for ( size_t myIndex = 0; myIndex < mySearchList.size(); myIndex++ ) {
377 reportFile << mySearchList[myIndex] << endl;
378 }
379 reportFile << "Displayed " << mySearchList.size() << "/" << myMatchCount << " matches" << endl;
380 }
381 catch (const regex_error& myError) {
382 reportFile << "regex_error: " << RegexErrorString(myError.code()) << endl;
383 }
384 }
385
PrintInstances(instanceId_t theCurrentInstanceId,string theFilter,bool thePrintSubcircuitNameFlag)386 void CCvcDb::PrintInstances(instanceId_t theCurrentInstanceId, string theFilter, bool thePrintSubcircuitNameFlag) {
387 if ( instancePtr_v[theCurrentInstanceId]->IsParallelInstance() ) {
388 PrintParallelInstance(theCurrentInstanceId, thePrintSubcircuitNameFlag);
389 return;
390 }
391 string myMasterName = "";
392 stringstream myInstanceString;
393 vector<string> mySearchList;
394 size_t myMatchCount = 0;
395 try {
396 regex mySearchPattern(FuzzyFilter(theFilter));
397 CCircuit * myMasterCircuit_p = instancePtr_v[theCurrentInstanceId]->master_p;
398 mySearchList.reserve(myMasterCircuit_p->subcircuitPtr_v.size());
399 for ( auto subcircuit_ppit = myMasterCircuit_p->subcircuitPtr_v.begin();
400 subcircuit_ppit != myMasterCircuit_p->subcircuitPtr_v.end(); subcircuit_ppit++ ) {
401 if ( thePrintSubcircuitNameFlag ) {
402 myMasterName = "(";
403 myMasterName += (*subcircuit_ppit)->masterName;
404 myMasterName += ")";
405 }
406 myInstanceString.str("");
407 myInstanceString << (*subcircuit_ppit)->name << myMasterName;
408 if ( IsEmpty(theFilter) || regex_match((*subcircuit_ppit)->name, mySearchPattern) ) {
409 if ( myMatchCount++ < cvcParameters.cvcSearchLimit ) {
410 mySearchList.push_back(myInstanceString.str());
411 }
412 }
413 }
414 sort(mySearchList.begin(), mySearchList.end());
415 for ( size_t myIndex = 0; myIndex < mySearchList.size(); myIndex++ ) {
416 reportFile << mySearchList[myIndex] << endl;
417 }
418 reportFile << "Displayed " << mySearchList.size() << "/" << myMatchCount << " matches" << endl;
419 }
420 catch (const regex_error& myError) {
421 reportFile << "regex_error: " << RegexErrorString(myError.code()) << endl;
422 }
423 }
424
425 /*
426 void CCvcDb::ReadShorts(string theShortFileName) {
427 // TODO: make sure short output applies to current data base
428 igzstream myShortFile(theShortFileName);
429 if ( myShortFile.fail() ) {
430 reportFile << "ERROR: Could not open " << theShortFileName << endl;
431 return;
432 }
433 string myInputLine;
434 char myValue[256];
435 netId_t myNetId, myShortId;
436 // voltage_t myVoltage;
437 // resistance_t myResistance;
438 int myInputCount;
439 try {
440 while ( getline(myShortFile, myInputLine) ) {
441 myValue[0] = '\0';
442 myInputCount = sscanf(myInputLine.c_str(), "%u->%u%s", &myNetId, &myShortId, myValue);
443 if ( myInputCount == 1 ) {
444 myInputCount = sscanf(myInputLine.c_str(), "%u%s", &myNetId, myValue);
445 myShortId = myNetId;
446 }
447 if ( myNetId >= netCount ) throw EShortFileError();
448 short_v[myNetId].first = myShortId;
449 short_v[myNetId].second = myValue;
450 }
451 isValidShortData = true;
452 }
453 catch (exception& e) {
454 reportFile << "Error reading short file" << endl;
455 isValidShortData = false;
456 ResetVector<CShortVector>(short_v, netCount);
457 }
458 }
459 */
460
FindNet(instanceId_t theCurrentInstanceId,string theNetName,bool theDisplayErrorFlag)461 netId_t CCvcDb::FindNet(instanceId_t theCurrentInstanceId, string theNetName, bool theDisplayErrorFlag) {
462 instanceId_t myCurrentInstanceId;
463 string myInitialHierarchy;
464 string mySearchHierarchy;
465 if (theNetName.length() > theNetName.find_last_of(cvcParameters.cvcHierarchyDelimiters) ) {
466 mySearchHierarchy = theNetName.substr(0, theNetName.find_last_of(cvcParameters.cvcHierarchyDelimiters));
467 } else {
468 mySearchHierarchy = "";
469 }
470 string myNetName;
471 try {
472 if ( theNetName.find_first_of(cvcParameters.cvcHierarchyDelimiters, 0) == 0 ) { // starts with delimiter
473 myInitialHierarchy = "";
474 myCurrentInstanceId = FindHierarchy(0, mySearchHierarchy, true, false);
475 } else {
476 myInitialHierarchy = HierarchyName(theCurrentInstanceId, false) + HIERARCHY_DELIMITER;
477 myCurrentInstanceId = FindHierarchy(theCurrentInstanceId, mySearchHierarchy, true, false);
478 }
479 if ( myCurrentInstanceId == UNKNOWN_INSTANCE ) throw out_of_range("not found");
480 if ( instancePtr_v[theCurrentInstanceId]->IsParallelInstance() ) {
481 PrintParallelInstance(theCurrentInstanceId, false);
482 return ( UNKNOWN_NET );
483 }
484 CCircuit * myCircuit_p = instancePtr_v[myCurrentInstanceId]->master_p;
485 string myParentName = HierarchyName(myCurrentInstanceId, false) + HIERARCHY_DELIMITER;
486 myNetName = theNetName.substr(myParentName.length() - myInitialHierarchy.length());
487 return instancePtr_v[myCurrentInstanceId]->localToGlobalNetId_v[myCircuit_p->localSignalIdMap.at(cvcCircuitList.cdlText.GetTextAddress(myNetName))];
488 }
489 catch (const out_of_range& oor_exception) {
490 if ( theDisplayErrorFlag ) {
491 reportFile << "Could not find net " << myInitialHierarchy << myNetName << endl;
492 }
493 }
494 return ( UNKNOWN_NET );
495 }
496
FindDevice(instanceId_t theCurrentInstanceId,string theDeviceName)497 deviceId_t CCvcDb::FindDevice(instanceId_t theCurrentInstanceId, string theDeviceName) {
498 instanceId_t myCurrentInstanceId;
499 string myInitialHierarchy;
500 string mySearchHierarchy;
501 if (theDeviceName.length() > theDeviceName.find_last_of(cvcParameters.cvcHierarchyDelimiters) ) {
502 mySearchHierarchy = theDeviceName.substr(0, theDeviceName.find_last_of(cvcParameters.cvcHierarchyDelimiters));
503 } else {
504 mySearchHierarchy = "";
505 }
506 string myDeviceName;
507 try {
508 if ( theDeviceName.find_first_of(cvcParameters.cvcHierarchyDelimiters, 0) == 0 ) { // starts with delimiter
509 myInitialHierarchy = "";
510 myCurrentInstanceId = FindHierarchy(0, mySearchHierarchy, true, false);
511 } else {
512 myInitialHierarchy = HierarchyName(theCurrentInstanceId, false) + HIERARCHY_DELIMITER;
513 myCurrentInstanceId = FindHierarchy(theCurrentInstanceId, mySearchHierarchy, true, false);
514 }
515 if ( myCurrentInstanceId == UNKNOWN_INSTANCE ) throw out_of_range("not found");
516 if ( instancePtr_v[theCurrentInstanceId]->IsParallelInstance() ) {
517 PrintParallelInstance(theCurrentInstanceId, false);
518 return ( UNKNOWN_DEVICE );
519 }
520 CCircuit * myCircuit_p = instancePtr_v[myCurrentInstanceId]->master_p;
521 string myParentName = HierarchyName(myCurrentInstanceId, false) + HIERARCHY_DELIMITER;
522 myDeviceName = theDeviceName.substr(myParentName.length() - myInitialHierarchy.length());
523 return instancePtr_v[myCurrentInstanceId]->firstDeviceId + myCircuit_p->GetLocalDeviceId(cvcCircuitList.cdlText.GetTextAddress(myDeviceName));
524 }
525 catch (const out_of_range& oor_exception) {
526 reportFile << "Could not find device " << HierarchyName(myCurrentInstanceId) << HIERARCHY_DELIMITER << myDeviceName << endl;
527 }
528 return ( UNKNOWN_DEVICE );
529 }
530
InteractiveCvc(int theCurrentStage)531 returnCode_t CCvcDb::InteractiveCvc(int theCurrentStage) {
532 string myInputLine;
533 char * myInput;
534 char myInputBuffer[1024];
535 istringstream myInputStream;
536 string myCommand;
537 string myOption;
538 string myHierarchy;
539 string myFilter;
540 string mySubcircuit;
541 string myFileName;
542 string myName;
543 string myNumberString;
544 string myCommandMode = "";
545 list<streambuf *> mySavedBufferStack;
546 ifstream *myBatchFile;
547 bool myIsBatchInput = false;
548 int mySearchLimit;
549 static instanceId_t myCurrentInstanceId = 0;
550 bool myPrintSubcircuitNameFlag = false;
551 size_t myNumber;
552 returnCode_t myReturnCode = UNKNOWN_RETURN_CODE;
553 stringstream myPrompt;
554
555 while ( myReturnCode == UNKNOWN_RETURN_CODE ) {
556 reportFile.flush();
557 myPrompt.clear();
558 myPrompt.str("");
559 if ( myCommandMode == "fs" ) {
560 myPrompt << "--> find subcircuit (^D to exit) ?> ";
561 } else if ( myCommandMode == "fn" ) {
562 myPrompt << "--> find net (^D to exit) ?> ";
563 } else if ( myCommandMode == "pd" ) {
564 myPrompt << "--> print device (^D to exit) ?> ";
565 } else if ( myCommandMode == "ph" ) {
566 myPrompt << "--> print hierarchy (^D to exit) ?> ";
567 } else if ( myCommandMode == "pi" ) {
568 myPrompt << "--> print instance (^D to exit) ?> ";
569 } else if ( myCommandMode == "pn" ) {
570 myPrompt << "--> print net (^D to exit) ?> ";
571 } else if ( myCommandMode == "gd" ) {
572 myPrompt << "--> get device (^D to exit) ?> ";
573 } else if ( myCommandMode == "gh" ) {
574 myPrompt << "--> get hierarchy (^D to exit) ?> ";
575 } else if ( myCommandMode == "gi" ) {
576 myPrompt << "--> get instance (^D to exit) ?> ";
577 } else if ( myCommandMode == "gn" ) {
578 myPrompt << "--> get net (^D to exit) ?> ";
579 } else if ( myCommandMode == "en" ) {
580 myPrompt << "--> expand net (^D to exit) ?> ";
581 } else if ( myCommandMode == "ed" ) {
582 myPrompt << "--> expand device (^D to exit) ?> ";
583 } else if ( myCommandMode == "ei" ) {
584 myPrompt << "--> expand instance (^D to exit) ?> ";
585 } else {
586 myPrompt << "** Stage " << theCurrentStage << "/" << STAGE_COMPLETE << ": Enter command ?> ";
587 }
588 if ( myIsBatchInput ) {
589 cin.getline(myInputBuffer, 1024);
590 if ( cin.eof() ) {
591 myInput = NULL;
592 } else {
593 myInput = myInputBuffer;
594 }
595 } else {
596 myInput = rl_gets(myPrompt.str());
597 }
598 if ( myInput == NULL ) { // eof
599 if ( myIsBatchInput ) {
600 reportFile << "finished source. Depth " << mySavedBufferStack.size() << endl;
601 cin.rdbuf(mySavedBufferStack.front());
602 mySavedBufferStack.pop_front();
603 myCommandMode = "";
604 if ( mySavedBufferStack.empty() ) {
605 myIsBatchInput = false;
606 }
607 } else if ( IsEmpty(myCommandMode) ){
608 gInteractive_cvc = false;
609 cin.clear();
610 myReturnCode = OK;
611 } else {
612 myCommandMode = "";
613 }
614 reportFile << endl;
615 continue;
616 }
617 reportFile << endl << "> " << myInput << endl;
618 try {
619 myInputLine = myInput;
620 myInputStream.str(myInputLine);
621 myInputStream.clear();
622 if ( IsEmpty(myCommandMode) ) {
623 if ( ! (myInputStream >> myCommand) ) continue;
624 } else {
625 myCommand = myCommandMode;
626 }
627 if ( myCommand == "findsubcircuit" || myCommand == "fs" ) {
628 if ( myInputStream >> mySubcircuit ) {
629 FindInstances(mySubcircuit, myPrintSubcircuitNameFlag);
630 } else {
631 myCommandMode = "fs";
632 }
633 } else if ( myCommand == "findnet" || myCommand == "fn" ) {
634 if ( myInputStream >> myName ) {
635 FindNets(myName, myCurrentInstanceId, myPrintSubcircuitNameFlag);
636 } else {
637 myCommandMode = "fn";
638 }
639 } else if ( myCommand == "goto" || myCommand == "g" || myCommand == "cd" ) {
640 myHierarchy = "/"; // default returns to top
641 myInputStream >> myHierarchy;
642 instanceId_t myNewInstanceId = FindHierarchy(myCurrentInstanceId, RemoveCellNames(myHierarchy));
643 if ( myNewInstanceId == UNKNOWN_INSTANCE ) {
644 cout << "Could not find instance " << myHierarchy << endl;
645 } else {
646 myCurrentInstanceId = myNewInstanceId;
647 }
648 } else if ( myCommand == "help" || myCommand == "h" ) {
649 cout << "Available commands are:" << endl;
650 cout << "<ctrl-d> switch to automatic (i.e. end interactive)" << endl;
651 cout << "searchlimit<sl> [limit]: set search limit" << endl;
652 cout << "hierarchydelimiter<hd> [character]: set interactive hierarchy delimiter" << endl;
653 cout << "goto<g|cd> <hierarchy>: goto hierarchy" << endl;
654 cout << "currenthierarchy<ch|pwd>: print current hierarchy" << endl;
655 cout << "printhierarchy<ph> hierarchynumber: print hierarchy name" << endl;
656 cout << "printdevice<pd> devicenumber: print device name" << endl;
657 cout << "printnet<pn> netnumber: print net name" << endl;
658 cout << "listnet|listdevice|listinstance<ln|ld|li> filter: list net|device|instances in current subcircuit filtered by filter" << endl;
659 cout << "getnet|getdevice|getinstance<gn|gd|gi> name: get net|device|instance number for name" << endl;
660 cout << "expandnet|expanddevice|expandinstance<en|ed|ei> name: expand net|device|instance to top level" << endl;
661 cout << "getsim name: expand nets and print sim value" << endl;
662 cout << "dumpfuse<df> filename: dump fuse to filename" << endl;
663 cout << "dumpanalognets<dan> filename: dump analog nets to filename" << endl;
664 cout << "dumpunknownlogicalnets<duln> filename: dump unknown logical nets to filename" << endl;
665 cout << "dumpunknownlogicalports<dulp> filter filename: dump unknown logical ports matching filter in current hierarchy to filename" << endl;
666 cout << "dumplevelshifter<dls> filename: dump level shifters to filename" << endl;
667 cout << "traceinverter<ti> name: trace signal as inverter output for name" << endl;
668 cout << "findsubcircuit<fs> subcircuit: list all instances of subcircuit or if regex, subcircuits that match" << endl;
669 cout << "findnet<fn> net: list all nets that match in lower subcircuits." << endl;
670 cout << "printcdl<pc> subcircuit: print subcircuit as subcircuit.cdl" << endl;
671 cout << "printenvironment<pe>: print simulation environment" << endl;
672 cout << "togglename<n>: toggle subcircuit names" << endl;
673 // cout << "shortfile<s> file: use file as shorts" << endl;
674 cout << "setpower<sp> file: use file as power" << endl;
675 cout << "setmodel<sm> file: use file as model" << endl;
676 cout << "setfuse<sf> file: use file as fuse overrides" << endl;
677 cout << "printpower<pp>: print power settings" << endl;
678 cout << "printmodel<pm>: print model statistics" << endl;
679 cout << "source file: read commands from file" << endl;
680 cout << "debug instance id: create debug.cvcrc.id file for debugging instance" << endl;
681 cout << "noerror: skip error processing (just propagation)" << endl;
682 cout << "skip: skip this cvcrc and use next one" << endl;
683 cout << "rerun: rerun this cvcrc" << endl;
684 cout << "continue<c>: continue" << endl;
685 cout << "help<h>: help" << endl;
686 cout << "quit<q>: quit" << endl;
687 } else if ( myCommand == "source" ) {
688 myFileName = "";
689 myInputStream >> myFileName;
690 myBatchFile = new ifstream(myFileName);
691 if ( myBatchFile && myBatchFile->good() ) {
692 myIsBatchInput = true;
693 mySavedBufferStack.push_front(cin.rdbuf());
694 cout << "sourcing from " << myFileName << ". Depth " << mySavedBufferStack.size() << endl;
695 cin.rdbuf(myBatchFile->rdbuf());
696 } else {
697 reportFile << "Could not open " << myFileName << endl;
698 }
699 } else if ( myCommand == "debug" ) {
700 if ( theCurrentStage < STAGE_FIRST_SIM ) {
701 reportFile << "ERROR: Can only debug after final sim." << endl;
702 continue;
703 }
704 string myInstanceName = "";
705 myInputStream >> myInstanceName;
706 instanceId_t myInstanceId = FindHierarchy(myCurrentInstanceId, RemoveCellNames(myInstanceName));
707 if ( myInstanceId == UNKNOWN_INSTANCE ) {
708 cout << "ERROR: Could not find " << myInstanceName << endl;
709 continue;
710 }
711 string myCell = "";
712 myInputStream >> myCell;
713 string myDebugCvcrcName = "debug.cvcrc." + myCell + "." + cvcParameters.cvcMode;
714 ofstream myDebugCvcrcFile(myDebugCvcrcName);
715 if ( myDebugCvcrcFile && myDebugCvcrcFile.good() ) {
716 CreateDebugCvcrcFile(myDebugCvcrcFile, myInstanceId, myCell, theCurrentStage);
717 cout << "Wrote debug cvcrc file " << myDebugCvcrcName << endl;
718 } else {
719 cout << "ERROR: Could not create cvcrc file " << myDebugCvcrcName << endl;
720 }
721 } else if ( myCommand == "noerror" ) {
722 cout << "WARNING: Ignoring errors." << endl;
723 errorFile << "WARNING: ERROR DETECTION HALTED" << endl;
724 detectErrorFlag = false;
725 } else if ( myCommand == "setmodel" || myCommand == "sm" ) {
726 if ( theCurrentStage != STAGE_START ) {
727 reportFile << "ERROR: Can only change model file at stage 1." << endl;
728 continue;
729 }
730 myFileName = "";
731 myInputStream >> myFileName;
732 cvcParameters.cvcModelFilename = myFileName;
733 if ( ( modelFileStatus = cvcParameters.LoadModels() ) == OK ) {
734 powerFileStatus = SetModePower();
735 modelFileStatus = SetDeviceModels();
736 }
737 if ( modelFileStatus == OK ) {
738 fuseFileStatus = CheckFuses();
739 } else if ( ! IsEmpty(cvcParameters.cvcFuseFilename) ){
740 reportFile << "WARNING: fuse file not checked due to invalid model file" << endl;
741 fuseFileStatus = SKIP;
742 }
743 } else if ( myCommand == "setpower" || myCommand == "sp" ) {
744 if ( theCurrentStage != 1 ) {
745 reportFile << "ERROR: Can only change power file at stage 1." << endl;
746 continue;
747 }
748 myFileName = "";
749 myInputStream >> myFileName;
750 cvcParameters.cvcPowerFilename = myFileName;
751 if ( ( powerFileStatus = cvcParameters.LoadPower() ) == OK ) {
752 powerFileStatus = SetModePower();
753 modelFileStatus = SetDeviceModels();
754 }
755 } else if ( myCommand == "setfuse" || myCommand == "sf" ) {
756 if ( theCurrentStage != 1 ) {
757 reportFile << "ERROR: Can only change fuse file at stage 1." << endl;
758 continue;
759 }
760 myFileName = "";
761 myInputStream >> myFileName;
762 cvcParameters.cvcFuseFilename = myFileName;
763 if ( modelFileStatus == OK ) {
764 fuseFileStatus = CheckFuses();
765 } else if ( ! IsEmpty(cvcParameters.cvcFuseFilename) ){
766 reportFile << "WARNING: fuse file not checked due to invalid model file" << endl;
767 fuseFileStatus = SKIP;
768 }
769 } else if ( myCommand == "searchlimit" || myCommand == "sl" ) {
770 if ( myInputStream >> mySearchLimit ) {
771 cvcParameters.cvcSearchLimit = mySearchLimit;
772 reportFile << "Search limit set to: " << cvcParameters.cvcSearchLimit << endl;
773 } else {
774 reportFile << "Current search limit: " << cvcParameters.cvcSearchLimit << endl;
775 }
776 } else if ( myCommand == "hierarchydelimiter" || myCommand == "hd" ) {
777 string myHierarchyDelimiters;
778 if ( myInputStream >> myHierarchyDelimiters ) {
779 cvcParameters.cvcHierarchyDelimiters = myHierarchyDelimiters;
780 reportFile << "Hierarchy delimiter(s) set to: '" << cvcParameters.cvcHierarchyDelimiters << "'" << endl;
781 } else {
782 reportFile << "Current hierarchy delimiter(s): '" << cvcParameters.cvcHierarchyDelimiters << "'" << endl;
783 }
784 } else if ( myCommand == "printmodel" || myCommand == "pm" ) {
785 cvcParameters.cvcModelListMap.Print(reportFile);
786 } else if ( myCommand == "printpower" || myCommand == "pp" ) {
787 PrintPowerList(reportFile);
788 } else if ( myCommand == "printcdl" || myCommand == "pc" ) {
789 mySubcircuit = "";
790 myInputStream >> mySubcircuit;
791 PrintSubcircuitCdl(mySubcircuit);
792 } else if ( myCommand == "printenvironment" || myCommand == "pe" ) {
793 cvcParameters.PrintEnvironment(reportFile);
794 } else if ( myCommand == "listnet" || myCommand == "ln" ) {
795 if ( myInputStream >> myFilter ) {
796 PrintNets(myCurrentInstanceId, myFilter, myPrintSubcircuitNameFlag, powerFileStatus == OK);
797 } else {
798 PrintNets(myCurrentInstanceId, "", myPrintSubcircuitNameFlag, powerFileStatus == OK);
799 }
800 } else if ( myCommand == "listdevice" || myCommand == "ld" ) {
801 if ( myInputStream >> myFilter ) {
802 PrintDevices(myCurrentInstanceId, myFilter, myPrintSubcircuitNameFlag, modelFileStatus == OK);
803 } else {
804 PrintDevices(myCurrentInstanceId, "", myPrintSubcircuitNameFlag, modelFileStatus == OK);
805 }
806 } else if ( myCommand == "listinstance" || myCommand == "li" ) {
807 if ( myInputStream >> myFilter ) {
808 PrintInstances(myCurrentInstanceId, myFilter, myPrintSubcircuitNameFlag);
809 } else {
810 PrintInstances(myCurrentInstanceId, "", myPrintSubcircuitNameFlag);
811 }
812 } else if ( myCommand == "expandnet" || myCommand == "en" ) {
813 if ( myInputStream >> myName ) {
814 set<netId_t> * myNetIdList = FindUniqueNetIds(myName); // expands buses and hierarchy
815 for (auto netId_pit = myNetIdList->begin(); netId_pit != myNetIdList->end(); netId_pit++) {
816 netId_t myEquivalentNetId = (isFixedEquivalentNet) ? GetEquivalentNet(*netId_pit) : *netId_pit;
817 string myTopNet = NetName(myEquivalentNetId, myPrintSubcircuitNameFlag);
818 reportFile << myTopNet << endl;
819 }
820 if ( myNetIdList->empty() ) {
821 reportFile << "* Could not expand net " << myName << endl;
822 }
823 } else {
824 myCommandMode = "en";
825 }
826 } else if ( myCommand == "getsim" ) {
827 if ( myInputStream >> myName ) {
828 set<netId_t> * myNetIdList = FindUniqueNetIds(myName); // expands buses and hierarchy
829 for (auto netId_pit = myNetIdList->begin(); netId_pit != myNetIdList->end(); netId_pit++) {
830 netId_t myEquivalentNetId = (isFixedEquivalentNet) ? GetEquivalentNet(*netId_pit) : *netId_pit;
831 string myTopNet = NetName(myEquivalentNetId, myPrintSubcircuitNameFlag);
832 netId_t myFinalNet = simNet_v[myEquivalentNetId].finalNetId;
833 reportFile << myTopNet << " ";
834 if ( netVoltagePtr_v[myFinalNet].full ) {
835 netVoltagePtr_v[myFinalNet].full->Print(reportFile);
836 } else {
837 reportFile << endl;
838 }
839 }
840 if ( myNetIdList->empty() ) {
841 reportFile << "* Could not expand net " << myName << endl;
842 }
843 }
844 } else if ( myCommand == "expanddevice" || myCommand == "ed" ) {
845 if ( myInputStream >> myName ) {
846 reportFile << "expanddevice not yet implemented" << endl;
847 } else {
848 myCommandMode = "ed";
849 }
850 } else if ( myCommand == "expandinstance" || myCommand == "ei" ) {
851 if ( myInputStream >> myName ) {
852 reportFile << "expandinstance not yet implemented" << endl;
853 } else {
854 myCommandMode = "ei";
855 }
856 } else if ( myCommand == "dumpfuse" || myCommand == "df" ) {
857 if ( myInputStream >> myFileName ) {
858 if ( modelFileStatus == OK ) {
859 DumpFuses(myFileName);
860 } else {
861 reportFile << "ERROR: Cannot dump fuses because model file is invalid" << endl;
862 }
863 } else {
864 reportFile << "ERROR: no fuse file name" << endl;
865 }
866 } else if ( myCommand == "dumpanalognets" || myCommand == "dan" ) {
867 if ( myInputStream >> myFileName ) {
868 if ( theCurrentStage > STAGE_START ) {
869 DumpAnalogNets(myFileName, myPrintSubcircuitNameFlag);
870 } else {
871 reportFile << "ERROR: Can only dump analog nets after second stage" << endl;
872 }
873 } else {
874 reportFile << "ERROR: no analog net file name" << endl;
875 }
876 } else if ( myCommand == "dumpunknownlogicalnets" || myCommand == "duln" ) {
877 if ( myInputStream >> myFileName ) {
878 if ( theCurrentStage >= STAGE_FIRST_MINMAX ) {
879 DumpUnknownLogicalNets(myFileName, myPrintSubcircuitNameFlag);
880 } else {
881 reportFile << "ERROR: Can only dump unknown logical nets after first min/max stage" << endl;
882 }
883 } else {
884 reportFile << "ERROR: no unknown logical net file name" << endl;
885 }
886 } else if ( myCommand == "dumpunknownlogicalports" || myCommand == "dulp" ) {
887 string myFilter;
888 if ( myInputStream >> myFilter && myInputStream >> myFileName ) {
889 if ( theCurrentStage >= STAGE_FIRST_SIM ) {
890 DumpUnknownLogicalPorts(myCurrentInstanceId, myFilter, myFileName, myPrintSubcircuitNameFlag);
891 } else {
892 reportFile << "ERROR: Can only dump unknown logical ports after first sim stage" << endl;
893 }
894 } else {
895 reportFile << "ERROR: no unknown logical port file name" << endl;
896 }
897 } else if ( myCommand == "dumplevelshifters" || myCommand == "dls" ) {
898 if ( myInputStream >> myFileName ) {
899 if ( theCurrentStage >= STAGE_FIRST_MINMAX ) {
900 DumpLevelShifters(myFileName, myPrintSubcircuitNameFlag);
901 } else {
902 reportFile << "ERROR: Can only dump level shifters after first min/max stage" << endl;
903 }
904 } else {
905 reportFile << "ERROR: no level shifter file name" << endl;
906 }
907 } else if ( myCommand == "togglename" || myCommand == "n" ) {
908 myPrintSubcircuitNameFlag = ! myPrintSubcircuitNameFlag;
909 reportFile << "Printing subcircuit name option is now " << ((myPrintSubcircuitNameFlag) ? "on" : "off") << endl;
910 } else if ( myCommand == "currenthierarchy" || myCommand == "ch" || myCommand == "pwd" ) {
911 reportFile << "Current hierarchy(" << myCurrentInstanceId << "): " << HierarchyName(myCurrentInstanceId, myPrintSubcircuitNameFlag) << endl;
912 } else if ( myCommand == "printhierarchy" || myCommand == "ph" ) {
913 myNumberString = "";
914 if ( myInputStream >> myNumberString ) {
915 myNumber = from_string<size_t>(myNumberString);
916 reportFile << "Current hierarchy(" << myNumber << "): " << HierarchyName(myNumber, myPrintSubcircuitNameFlag) << endl;
917 } else {
918 myCommandMode = "ph";
919 }
920 } else if ( myCommand == "printdevice" || myCommand == "pd" ) {
921 myNumberString = "";
922 if ( myInputStream >> myNumberString ) {
923 myNumber = from_string<size_t>(myNumberString);
924 if ( myNumber == 0 && myNumberString != "0" ) {
925 reportFile << "Invalid device number" << endl;
926 } else {
927 reportFile << "Device " << myNumber << ": " << DeviceName(myNumber, myPrintSubcircuitNameFlag) << endl;
928 }
929 } else {
930 myCommandMode = "pd";
931 }
932 } else if ( myCommand == "printnet" || myCommand == "pn" ) {
933 myNumberString = "";
934 if ( myInputStream >> myNumberString ) {
935 myNumber = from_string<size_t>(myNumberString);
936 if ( myNumber == 0 && myNumberString != "0" ) {
937 reportFile << "Invalid net number" << endl;
938 } else {
939 reportFile << "Net " << myNumber << ": " << NetName(myNumber, myPrintSubcircuitNameFlag) << endl;
940 }
941 } else {
942 myCommandMode = "pn";
943 }
944 } else if ( myCommand == "getinstance" || myCommand == "gi" ) {
945 if ( myInputStream >> myName ) {
946 reportFile << "getinstance not yet implemented" << endl;
947 } else {
948 myCommandMode = "gi";
949 }
950 } else if ( myCommand == "getdevice" || myCommand == "gd" ) {
951 myName = "";
952 if ( myInputStream >> myName ) {
953 netId_t myDeviceId = FindDevice(myCurrentInstanceId, RemoveCellNames(myName));
954 if ( myDeviceId != UNKNOWN_DEVICE ) {
955 CInstance * myParent_p = instancePtr_v[deviceParent_v[myDeviceId]];
956 CDevice * myDevice_p = myParent_p->master_p->devicePtr_v[myDeviceId - myParent_p->firstDeviceId];
957 reportFile << "Device " << DeviceName(myDeviceId, myPrintSubcircuitNameFlag) << ": " << myDeviceId;
958 reportFile << " " << myDevice_p->parameters << " R=" << parameterResistanceMap[myDevice_p->parameters] << endl;
959 reportFile << " Model " << myDevice_p->model_p->definition << endl;
960 }
961 } else {
962 myCommandMode = "gd";
963 }
964 } else if ( myCommand == "traceinverter" || myCommand == "ti" ) {
965 myName = "";
966 myInputStream >> myName;
967 netId_t myNetId = FindNet(myCurrentInstanceId, RemoveCellNames(myName));
968 if ( myNetId != UNKNOWN_NET ) {
969 netId_t myEquivalentNetId = (isFixedEquivalentNet) ? GetEquivalentNet(myNetId) : myNetId;
970 if ( theCurrentStage >= STAGE_FIRST_MINMAX ) {
971 reportFile << NetName(myNetId, myPrintSubcircuitNameFlag) << endl;
972 if ( myNetId != myEquivalentNetId ) {
973 reportFile << " = " << NetName(myEquivalentNetId, myPrintSubcircuitNameFlag) << endl;
974 }
975 if ( inverterNet_v[myEquivalentNetId] != UNKNOWN_NET ) {
976 string myInversion = ( theCurrentStage < STAGE_COMPLETE ) ? " - " :
977 (highLow_v[myEquivalentNetId]) ? " + " : " - ";
978 for( netId_t net_it = inverterNet_v[myEquivalentNetId]; net_it != UNKNOWN_NET; net_it = inverterNet_v[net_it] ) {
979 reportFile << myInversion << NetName(net_it, myPrintSubcircuitNameFlag) << endl;
980 myInversion = ( myInversion == " - " ? " + " : " - " );
981 }
982 } else {
983 reportFile << " not an inverter output." << endl;
984 }
985 } else {
986 reportFile << " Inverters have not been processed. Try later stage." << endl;
987 }
988 }
989 } else if ( myCommand == "getnet" || myCommand == "gn" ) {
990 myName = "";
991 if ( myInputStream >> myName ) {
992 netId_t myNetId = FindNet(myCurrentInstanceId, RemoveCellNames(myName));
993 if ( myNetId != UNKNOWN_NET ) {
994 reportFile << "Net " << NetName(myNetId, myPrintSubcircuitNameFlag) << ": " << myNetId << endl;
995 netId_t myEquivalentNetId = (isFixedEquivalentNet) ? GetEquivalentNet(myNetId) : myNetId;
996 if ( theCurrentStage >= STAGE_LINK ) {
997 reportFile << " connections: gate " << connectionCount_v[myEquivalentNetId].gateCount;
998 reportFile << " source " << connectionCount_v[myEquivalentNetId].sourceCount;
999 reportFile << " drain " << connectionCount_v[myEquivalentNetId].drainCount;
1000 reportFile << " bulk " << CountBulkConnections(myEquivalentNetId) << endl;
1001 }
1002 string mySimpleName = NetName(myEquivalentNetId, PRINT_CIRCUIT_OFF);
1003 CPower * myLeakPower_p = leakVoltagePtr_v[myEquivalentNetId].full;
1004 CPower * myPower_p = netVoltagePtr_v[myEquivalentNetId].full;
1005 if ( leakVoltageSet && myLeakPower_p && myLeakPower_p != myPower_p ) {
1006 reportFile << " leak definition " << myLeakPower_p->powerSignal()
1007 << LeakShortString(myEquivalentNetId, myPrintSubcircuitNameFlag) << endl;
1008 reportFile << " default min " << NetName(myLeakPower_p->defaultMinNet) << endl;
1009 reportFile << " default sim " << NetName(myLeakPower_p->defaultSimNet) << endl;
1010 reportFile << " default max " << NetName(myLeakPower_p->defaultMaxNet) << endl;
1011 }
1012 if ( powerFileStatus == OK && netVoltagePtr_v[myEquivalentNetId].full ) {
1013 if ( myPower_p->powerSignal() != mySimpleName ) {
1014 reportFile << " base definition " << myPower_p->powerSignal() << endl;
1015 reportFile << " default min " << NetName(myPower_p->defaultMinNet) << endl;
1016 reportFile << " default sim " << NetName(myPower_p->defaultSimNet) << endl;
1017 reportFile << " default max " << NetName(myPower_p->defaultMaxNet) << endl;
1018 }
1019 reportFile << ShortString(myEquivalentNetId, myPrintSubcircuitNameFlag) << endl;
1020 }
1021 reportFile << endl;
1022 if ( theCurrentStage >= STAGE_COMPLETE ) {
1023 if ( minNet_v[myEquivalentNetId].backupNetId != myNetId )
1024 PrintBackupNet(minNet_v, myNetId, "Initial min path", reportFile);
1025 if ( maxNet_v[myEquivalentNetId].backupNetId != myNetId )
1026 PrintBackupNet(maxNet_v, myNetId, "Initial max path", reportFile);
1027 }
1028 if ( theCurrentStage >= STAGE_SECOND_SIM ) {
1029 if ( simNet_v[myEquivalentNetId].backupNetId != myNetId )
1030 PrintBackupNet(simNet_v, myNetId, "Initial sim path", reportFile);
1031 /* 3pass
1032 if ( logicMinNet_v[myNetId].nextNetId != myNetId )
1033 PrintVirtualNet(logicMinNet_v, myNetId, "Logic min path", cout);
1034 if ( logicMaxNet_v[myNetId].nextNetId != myNetId )
1035 PrintVirtualNet(logicMaxNet_v, myNetId, "Logic max path", cout);
1036 if ( logicSimNet_v[myNetId].nextNetId != myNetId )
1037 PrintVirtualNet(logicSimNet_v, myNetId, "Logic sim path", cout);
1038 */
1039 }
1040 if ( theCurrentStage >= STAGE_RESISTANCE ) {
1041
1042 if ( minNet_v[myEquivalentNetId].nextNetId != myNetId )
1043 PrintVirtualNet<CVirtualNetVector>(minNet_v, myNetId, "Min path", reportFile);
1044 if ( maxNet_v[myEquivalentNetId].nextNetId != myNetId )
1045 PrintVirtualNet<CVirtualNetVector>(maxNet_v, myNetId, "Max path", reportFile);
1046 if ( simNet_v[myEquivalentNetId].nextNetId != myNetId )
1047 PrintVirtualNet<CVirtualNetVector>(simNet_v, myNetId, "Sim path", reportFile);
1048 }
1049 }
1050 } else {
1051 myCommandMode = "gn";
1052 }
1053 } else if ( myCommand == "skip" ) {
1054 myCurrentInstanceId = 0; // reset saved hierarchy
1055 myReturnCode = SKIP;
1056 } else if ( myCommand == "rerun" ) {
1057 myCurrentInstanceId = 0; // reset saved hierarchy
1058 cvcArgIndex--;
1059 logFile.close();
1060 errorFile.close();
1061 myReturnCode = SKIP;
1062 // } else if ( myCommand == "shortfile" || myCommand == "s" ) {
1063 // myFileName = "";
1064 // myInputStream >> myFileName;
1065 // ReadShorts(myFileName);
1066 } else if ( myCommand == "c" || myCommand == "continue" ) {
1067 if ( theCurrentStage == STAGE_COMPLETE && cvcArgIndex + 1 >= cvcArgCount ) { // attempt to continue past last cvcrc
1068 reportFile << "This is the last cvcrc file. Use 'rerun' or 'quit'." << endl;
1069 } else { // valid continue
1070 myReturnCode = OK;
1071 if ( myInputStream >> gContinueCount ) {
1072 ;
1073 } else {
1074 gContinueCount = 1;
1075 }
1076 cout << "continuing for " << gContinueCount << " step(s)" << endl;
1077 }
1078 } else if ( myCommand == "q" || myCommand == "quit" ) {
1079 RemoveLock();
1080 Cleanup();
1081 exit(0);
1082 } else {
1083 reportFile << "Unrecognized command '" << myCommand << "'" << endl;
1084 }
1085 }
1086 catch (invalid_argument& e) {
1087 reportFile << "invalid argument" << endl;
1088 }
1089 }
1090 return(myReturnCode);
1091 }
1092
DumpFuses(string theFileName)1093 void CCvcDb::DumpFuses(string theFileName) {
1094 ofstream myDumpFile(theFileName);
1095 if ( myDumpFile.fail() ) {
1096 reportFile << "ERROR: Could not open " << theFileName << endl;
1097 return;
1098 }
1099 reportFile << "Dumping fuses to " << theFileName << " ... "; cout.flush();
1100 size_t myFuseCount = 0;
1101 for (CModelListMap::iterator keyModelListPair_pit = cvcParameters.cvcModelListMap.begin(); keyModelListPair_pit != cvcParameters.cvcModelListMap.end(); keyModelListPair_pit++) {
1102 for (CModelList::iterator model_pit = keyModelListPair_pit->second.begin(); model_pit != keyModelListPair_pit->second.end(); model_pit++) {
1103 if ( model_pit->type == FUSE_ON || model_pit->type == FUSE_OFF ) {
1104 for (CDevice * device_pit = model_pit->firstDevice_p; device_pit != NULL; device_pit = device_pit->nextDevice_p) {
1105 CCircuit * myParent_p = device_pit->parent_p;
1106 for (instanceId_t instance_it = 0; instance_it < myParent_p->instanceId_v.size(); instance_it++) {
1107 myDumpFile << DeviceName(instancePtr_v[myParent_p->instanceId_v[instance_it]]->firstDeviceId + device_pit->offset) << " " << gModelTypeMap[model_pit->type] << endl;
1108 myFuseCount++;
1109 }
1110 }
1111 }
1112 }
1113 }
1114 reportFile << "total fuses written: " << myFuseCount << endl;
1115 myDumpFile.close();
1116 }
1117
DumpAnalogNets(string theFileName,bool thePrintCircuitFlag)1118 void CCvcDb::DumpAnalogNets(string theFileName, bool thePrintCircuitFlag) {
1119 ofstream myDumpFile(theFileName);
1120 if ( myDumpFile.fail() ) {
1121 reportFile << "ERROR: Could not open " << theFileName << endl;
1122 return;
1123 }
1124 reportFile << "Dumping analog nets to " << theFileName << " ... "; cout.flush();
1125 size_t myNetCount = 0;
1126 for ( netId_t net_it = 0; net_it < netCount; net_it++ ) {
1127 if ( net_it != GetEquivalentNet(net_it) ) continue; // skip shorted nets
1128 if ( netVoltagePtr_v[net_it].full && netVoltagePtr_v[net_it].full->type[POWER_BIT] ) continue; // skip power
1129 if ( IsAnalogNet(net_it) ) {
1130 myDumpFile << NetName(net_it, thePrintCircuitFlag) << endl;
1131 myNetCount++;
1132 }
1133 }
1134 reportFile << "total nets written: " << myNetCount << endl;
1135 myDumpFile.close();
1136 }
1137
DumpUnknownLogicalPorts(instanceId_t theCurrentInstanceId,string theFilter,string theFileName,bool thePrintCircuitFlag)1138 void CCvcDb::DumpUnknownLogicalPorts(instanceId_t theCurrentInstanceId, string theFilter, string theFileName, bool thePrintCircuitFlag) {
1139 // for each port matching theFilter in every instance at or below theCurrentInstanceId,
1140 // output the highest inverter input at the lowest level that matched the filter
1141 ofstream myDumpFile(theFileName);
1142 regex mySearchPattern(FuzzyFilter(theFilter));
1143 unordered_set<netId_t> myPrintedNets;
1144 CVirtualNet myMinNet;
1145 CVirtualNet myMaxNet;
1146 if ( myDumpFile.fail() ) {
1147 reportFile << "ERROR: Could not open " << theFileName << endl;
1148 return;
1149 }
1150 reportFile << "Dumping unknown logical ports filtered by " << theFilter << " to " << theFileName << " ... " << endl;
1151 vector<bool> myIsLogicalNet_v;
1152 myIsLogicalNet_v.resize(netCount, false);
1153 size_t myNetCount = 0;
1154 cout << "DEBUG: setting net types ..." << endl;
1155 for ( netId_t net_it = 0; net_it < netCount; net_it++ ) {
1156 if ( net_it != GetEquivalentNet(net_it) ) continue; // skip shorted nets
1157 CPower * myPower_p = netVoltagePtr_v[net_it].full;
1158 if ( myPower_p && ( myPower_p->simVoltage != UNKNOWN_VOLTAGE || myPower_p->type[POWER_BIT] ) ) continue; // skip defined sim voltages and power
1159 myIsLogicalNet_v[net_it] = ! IsAnalogNet(net_it);
1160 }
1161 cout << "DEBUG: searching instances..." << endl;
1162 for ( instanceId_t instance_it = 0; instance_it < instancePtr_v.size(); instance_it++ ) {
1163 if ( ! IsSubcircuitOf(instance_it, theCurrentInstanceId) ) continue; // only process subcircuits
1164 CInstance * myInstance_p = instancePtr_v[instance_it];
1165 if ( ! myInstance_p || ! myInstance_p->master_p ) {
1166 continue;
1167 }
1168 CCircuit * myCircuit_p = myInstance_p->master_p;
1169 for( auto signalMap_pit = myCircuit_p->localSignalIdMap.begin(); signalMap_pit != myCircuit_p->localSignalIdMap.end(); signalMap_pit++ ) {
1170 netId_t net_it = signalMap_pit->second;
1171 if ( net_it >= myCircuit_p->portCount && instance_it != theCurrentInstanceId ) continue; // skip internal signals in subcircuits
1172 list<tuple<instanceId_t, netId_t, netId_t>> myNetStack;
1173 netId_t myTopNetId = GetEquivalentNet(myInstance_p->localToGlobalNetId_v[net_it]);
1174 if ( myPrintedNets.count(myTopNetId) > 0 ) continue; // ignore already printed
1175 if ( ! myIsLogicalNet_v[myTopNetId] ) continue; // ignore analog nets and known logic
1176 if ( ! regex_match(signalMap_pit->first, mySearchPattern) ) continue; // ignore non-match
1177 if ( firstGate_v[myTopNetId] == UNKNOWN_NET ) continue; // ignore floating outputs (also ignores transfer gate connections)
1178 netId_t mySourceNet = myTopNetId;
1179 myNetStack.push_front(tuple<instanceId_t, netId_t, netId_t>(instance_it, net_it, mySourceNet));
1180 // must be done after second sim so power & override nets are propagated
1181 while ( inverterNet_v[mySourceNet] != UNKNOWN_NET ) {
1182 mySourceNet = inverterNet_v[mySourceNet];
1183 myNetStack.push_front(tuple<instanceId_t, netId_t, netId_t>(UNKNOWN_INSTANCE, UNKNOWN_NET, mySourceNet));
1184 }
1185 bool myNetFound = false;
1186 while ( myNetStack.size() > 0 && ! myNetFound ) {
1187 tuple<instanceId_t, netId_t, netId_t> mySearchTuple = myNetStack.front();
1188 myNetStack.pop_front();
1189 netId_t myNet = get<2>(mySearchTuple);
1190 if ( ! IsInstanceNet(myNet, theCurrentInstanceId) ) continue; // ignore nets not in current instance
1191 instanceId_t mySearchInstance = get<0>(mySearchTuple);
1192 deviceId_t mySourceDevice = ( firstSource_v[myNet] == UNKNOWN_DEVICE ) ? firstDrain_v[myNet] : firstSource_v[myNet];
1193 if ( mySourceDevice != UNKNOWN_DEVICE ) { // use device instance as search
1194 mySearchInstance = deviceParent_v[mySourceDevice];
1195 }
1196 if ( ! IsSubcircuitOf(mySearchInstance, theCurrentInstanceId) ) { // outside hierarchy
1197 mySearchInstance = UNKNOWN_INSTANCE;
1198 }
1199 if ( mySearchInstance == UNKNOWN_INSTANCE ) { // source outside hierarchy or input (no source)
1200 mySearchInstance == FindNetInstance(myNet, theCurrentInstanceId);
1201 }
1202 if ( IsInternalNet(myNet, mySearchInstance) ) continue; // ignore non ports
1203 netId_t port_it;
1204 CInstance * mySearchInstance_p;
1205 CCircuit * mySearchCircuit_p;
1206 text_t myLocalNetName = NULL;
1207 while ( mySearchInstance != theCurrentInstanceId && IsSubcircuitOf(mySearchInstance, theCurrentInstanceId) && ! myNetFound ) {
1208 // unfortunately requires 2 reverse searches. port given global net, and name given port
1209 mySearchInstance_p = instancePtr_v[mySearchInstance];
1210 if ( myNet < mySearchInstance_p->firstNetId ) { // only process ports
1211 myLocalNetName = GetLocalNetName(mySearchInstance, myNet);
1212 if ( myLocalNetName != NULL ) {
1213 //cout << "DEBUG: checking " << myLocalNetName << endl;
1214 myNetFound = regex_match(myLocalNetName, mySearchPattern);
1215 }
1216 }
1217 if ( ! myNetFound ) {
1218 mySearchInstance = instancePtr_v[mySearchInstance]->parentId;
1219 }
1220 }
1221 if ( ! myNetFound && mySearchInstance == theCurrentInstanceId ) { // include internal nets of top level
1222 mySearchInstance_p = instancePtr_v[theCurrentInstanceId];
1223 mySearchCircuit_p = mySearchInstance_p->master_p;
1224 netId_t mySearchLimit = mySearchInstance_p->localToGlobalNetId_v.size();
1225 myLocalNetName = GetLocalNetName(theCurrentInstanceId, myNet);
1226 if ( myLocalNetName != NULL ) {
1227 myNetFound = regex_match(myLocalNetName, mySearchPattern);
1228 }
1229 }
1230 if ( ! myNetFound ) continue; // couldn't find net
1231 if ( myPrintedNets.count(myNet) > 0 ) continue; // already printed
1232 myMinNet(minNet_v, myNet);
1233 myMaxNet(maxNet_v, myNet);
1234 if ( myMinNet.finalNetId == UNKNOWN_NET
1235 || myMaxNet.finalNetId == UNKNOWN_NET
1236 || myMinNet.finalNetId == myNet
1237 || myMaxNet.finalNetId == myNet
1238 || myMinNet.finalNetId == myMaxNet.finalNetId ) continue; // invalid min/max
1239 myDumpFile << HierarchyName(mySearchInstance, thePrintCircuitFlag) << "/" << myLocalNetName;
1240 myDumpFile << " min " << NetName(myMinNet.finalNetId, thePrintCircuitFlag);
1241 myDumpFile << " max " << NetName(myMaxNet.finalNetId, thePrintCircuitFlag) << endl;
1242 myPrintedNets.insert(myNet);
1243 }
1244 }
1245 }
1246 reportFile << "total nets written: " << myPrintedNets.size() << endl;
1247 myDumpFile.close();
1248 }
1249
DumpUnknownLogicalNets(string theFileName,bool thePrintCircuitFlag)1250 void CCvcDb::DumpUnknownLogicalNets(string theFileName, bool thePrintCircuitFlag) {
1251 ofstream myDumpFile(theFileName);
1252 CVirtualNet myMinNet;
1253 CVirtualNet myMaxNet;
1254 if ( myDumpFile.fail() ) {
1255 reportFile << "ERROR: Could not open " << theFileName << endl;
1256 return;
1257 }
1258 reportFile << "Dumping unknown logical nets to " << theFileName << " ... " << endl;
1259 vector<bool> myIsLogicalNet_v;
1260 myIsLogicalNet_v.resize(netCount, false);
1261 size_t myNetCount = 0;
1262 for ( netId_t net_it = 0; net_it < netCount; net_it++ ) {
1263 if ( net_it != GetEquivalentNet(net_it) ) continue; // skip shorted nets
1264 CPower * myPower_p = netVoltagePtr_v[net_it].full;
1265 if ( myPower_p && ( myPower_p->simVoltage != UNKNOWN_VOLTAGE || myPower_p->type[POWER_BIT] ) ) continue; // skip defined sim voltages and power
1266 myIsLogicalNet_v[net_it] = ! IsAnalogNet(net_it);
1267 }
1268 for ( netId_t net_it = 0; net_it < netCount; net_it++ ) {
1269 if ( ! myIsLogicalNet_v[net_it] ) continue; // skip shorted, defined, and analog nets
1270
1271 if ( simNet_v[net_it].finalNetId != net_it ) continue; // skip known values
1272
1273 if ( inverterNet_v[net_it] != UNKNOWN_NET
1274 && inverterNet_v[net_it] >= topCircuit_p->portCount
1275 && ! netStatus_v[inverterNet_v[net_it]][ANALOG] ) continue; // skip inverter output unless inverter input is chip input or analog signal
1276
1277 CDeviceCount myDeviceCount(net_it, this);
1278 if ( myDeviceCount.activePmosCount == 0 || myDeviceCount.activeNmosCount == 0 ) continue; // skip non logic output
1279 myMinNet(minNet_v, net_it);
1280 myMaxNet(maxNet_v, net_it);
1281 if ( myMinNet.finalNetId == UNKNOWN_NET
1282 || myMaxNet.finalNetId == UNKNOWN_NET
1283 || myMinNet.finalNetId == net_it
1284 || myMaxNet.finalNetId == net_it
1285 || myMinNet.finalNetId == myMaxNet.finalNetId ) continue; // invalid min/max
1286 myDumpFile << NetName(net_it, thePrintCircuitFlag);
1287 myDumpFile << " min " << NetName(myMinNet.finalNetId, thePrintCircuitFlag);
1288 myDumpFile << " max " << NetName(myMaxNet.finalNetId, thePrintCircuitFlag) << endl;
1289 myNetCount++;
1290 }
1291 reportFile << "total nets written: " << myNetCount << endl;
1292 myDumpFile.close();
1293 }
1294
DumpLevelShifters(string theFileName,bool thePrintCircuitFlag)1295 void CCvcDb::DumpLevelShifters(string theFileName, bool thePrintCircuitFlag) {
1296 /// Write a sampling (one per cell/power pair) of possible level shifters to theFileName
1297 ofstream myDumpFile(theFileName);
1298 CVirtualNet myMinNmosInputNet;
1299 CVirtualNet myMinPmosInputNet;
1300 CVirtualNet myMinOutputNet;
1301 CVirtualNet myMaxNmosInputNet;
1302 CVirtualNet myMaxPmosInputNet;
1303 CVirtualNet myMaxOutputNet;
1304 if ( myDumpFile.fail() ) {
1305 reportFile << "ERROR: Could not open " << theFileName << endl;
1306 return;
1307 }
1308 reportFile << "Dumping level shifters to " << theFileName << " ... "; cout.flush();
1309 vector<bool> myIsLogicalNet_v;
1310 myIsLogicalNet_v.resize(netCount, false);
1311 size_t myLevelShifterCount = 0;
1312 for ( netId_t net_it = 0; net_it < netCount; net_it++ ) {
1313 if ( net_it != GetEquivalentNet(net_it) ) continue; // skip shorted nets
1314 CPower * myPower_p = netVoltagePtr_v[net_it].full;
1315 if ( myPower_p && ( myPower_p->simVoltage != UNKNOWN_VOLTAGE || myPower_p->type[POWER_BIT] ) ) continue; // skip defined sim voltages and power
1316 myIsLogicalNet_v[net_it] = ! IsAnalogNet(net_it);
1317 }
1318 set<string> myLevelShifters;
1319 debugFile << "DEBUG level shifters" << endl;
1320 for ( netId_t net_it = 0; net_it < netCount; net_it++ ) {
1321 if ( ! myIsLogicalNet_v[net_it] ) continue; // skip shorted, defined, and analog nets
1322
1323 CDeviceCount myDeviceCount(net_it, this);
1324 if ( myDeviceCount.activePmosCount == 0 || myDeviceCount.activeNmosCount == 0 ) continue; // skip non logic output
1325
1326 myMinOutputNet(minNet_v, net_it);
1327 myMaxOutputNet(maxNet_v, net_it);
1328 CPower * myOutputGround_p = netVoltagePtr_v[myMinOutputNet.finalNetId].full;
1329 CPower * myOutputPower_p = netVoltagePtr_v[myMaxOutputNet.finalNetId].full;
1330 if ( myMinOutputNet.finalNetId == UNKNOWN_NET
1331 || myMaxOutputNet.finalNetId == UNKNOWN_NET
1332 || myMinOutputNet.finalNetId == net_it
1333 || myMaxOutputNet.finalNetId == net_it
1334 || myMinOutputNet.finalNetId == myMaxOutputNet.finalNetId
1335 || ! myOutputGround_p || ! IsPower_(myOutputGround_p)
1336 || ! myOutputPower_p || ! IsPower_(myOutputPower_p) ) continue; // invalid min/max
1337
1338 deviceId_t myNmos = GetAttachedDevice(net_it, NMOS, SD);
1339 deviceId_t myPmos = GetAttachedDevice(net_it, PMOS, SD);
1340 if ( myNmos == UNKNOWN_DEVICE || myPmos == UNKNOWN_DEVICE ) continue; // skip if missing NMOS or PMOS
1341
1342 if ( deviceParent_v[myNmos] != deviceParent_v[myPmos] ) continue; // skip if in different subcircuits
1343
1344 CInstance * myInstance_p = instancePtr_v[deviceParent_v[myNmos]];
1345 CCircuit * myMaster_p = myInstance_p->master_p;
1346 netId_t myNmosGate = GetEquivalentNet(gateNet_v[myNmos]);
1347 netId_t myPmosGate = GetEquivalentNet(gateNet_v[myPmos]);
1348 myMinNmosInputNet(minNet_v, myNmosGate);
1349 myMinPmosInputNet(minNet_v, myPmosGate);
1350 myMaxNmosInputNet(maxNet_v, myNmosGate);
1351 myMaxPmosInputNet(maxNet_v, myPmosGate);
1352 // CPower * myNmosPower_p = netVoltagePtr_v[myNmosGate].full;
1353 // CPower * myPmosPower_p = netVoltagePtr_v[myPmosGate].full;
1354 CPower * myNmosGround_p = netVoltagePtr_v[myMinNmosInputNet.finalNetId].full;
1355 CPower * myNmosPower_p = netVoltagePtr_v[myMaxNmosInputNet.finalNetId].full;
1356 CPower * myPmosGround_p = netVoltagePtr_v[myMinPmosInputNet.finalNetId].full;
1357 CPower * myPmosPower_p = netVoltagePtr_v[myMaxPmosInputNet.finalNetId].full;
1358 if ( ! myNmosGround_p || ! IsPower_(myNmosGround_p) || ! myNmosPower_p || ! IsPower_(myNmosPower_p)
1359 || ! myPmosGround_p || ! IsPower_(myPmosGround_p) || ! myPmosPower_p || ! IsPower_(myPmosPower_p) ) continue; // ignore inputs with non-power min/max
1360
1361 if ( ( myMinNmosInputNet.finalNetId == myMaxNmosInputNet.finalNetId // power
1362 || ( myNmosGround_p->powerAlias() == myOutputGround_p->powerAlias()
1363 && myNmosPower_p->powerAlias() == myOutputPower_p->powerAlias() ) )
1364 && ( myMinPmosInputNet.finalNetId == myMaxPmosInputNet.finalNetId // power
1365 || ( myPmosGround_p->powerAlias() == myOutputGround_p->powerAlias()
1366 && myPmosPower_p->powerAlias() == myOutputPower_p->powerAlias() )) ) continue; // input = output
1367
1368 if ( myMinNmosInputNet.finalNetId != myMinOutputNet.finalNetId
1369 && myMaxNmosInputNet.finalNetId != myMaxOutputNet.finalNetId
1370 && myMinPmosInputNet.finalNetId != myMinOutputNet.finalNetId
1371 && myMaxPmosInputNet.finalNetId != myMaxOutputNet.finalNetId ) continue; // one power must be equal
1372
1373 if ( inverterNet_v[myNmosGate] == UNKNOWN_NET && inverterNet_v[myPmosGate] == UNKNOWN_NET ) continue; // ignore signals not from inverters
1374
1375 netId_t myCheckNet;
1376 deviceId_t myCheckDevice;
1377 string myInputPower;
1378 string myOutputPower = NetName(myMinOutputNet.finalNetId, thePrintCircuitFlag) + "/" + NetName(myMaxOutputNet.finalNetId, thePrintCircuitFlag);
1379 if ( myMinNmosInputNet.finalNetId != myMaxNmosInputNet.finalNetId // ignore direct connections to power
1380 && ( myMinNmosInputNet.finalNetId != myMinOutputNet.finalNetId
1381 || myMaxNmosInputNet.finalNetId != myMaxOutputNet.finalNetId ) ) {
1382 myCheckDevice = myNmos;
1383 myCheckNet = myNmosGate;
1384 myInputPower = NetName(myMinNmosInputNet.finalNetId, thePrintCircuitFlag) + "/" + NetName(myMaxNmosInputNet.finalNetId, thePrintCircuitFlag);
1385 } else if ( myMinPmosInputNet.finalNetId != myMaxPmosInputNet.finalNetId // ignore direct connections to power
1386 && ( myMinPmosInputNet.finalNetId != myMinOutputNet.finalNetId
1387 || myMaxPmosInputNet.finalNetId != myMaxOutputNet.finalNetId ) ) {
1388 myCheckDevice = myPmos;
1389 myCheckNet = myPmosGate;
1390 myInputPower = NetName(myMinPmosInputNet.finalNetId, thePrintCircuitFlag) + "/" + NetName(myMaxPmosInputNet.finalNetId, thePrintCircuitFlag);
1391 } else if ( myMinNmosInputNet.finalNetId != myMaxNmosInputNet.finalNetId
1392 || myMinNmosInputNet.finalNetId != myMaxNmosInputNet.finalNetId ) { // tied to power
1393 continue;
1394
1395 } else {
1396 myDumpFile << "UNEXPECTED connection at " << DeviceName(myNmos, true);
1397 myDumpFile << " N " << myNmosGate << " " <<myMinNmosInputNet.finalNetId << "/" << myMaxNmosInputNet.finalNetId;
1398 myDumpFile << " P " << myPmosGate << " " <<myMinPmosInputNet.finalNetId << "/" << myMaxPmosInputNet.finalNetId;
1399 myDumpFile << " out " << myMinOutputNet.finalNetId << "/" << myMaxOutputNet.finalNetId << endl;
1400 continue;
1401
1402 }
1403 if (inverterNet_v[myCheckNet] == UNKNOWN_NET) {
1404 myDumpFile << "UNEXPECTED non-inverter at " << DeviceName(myCheckDevice, true) << endl;
1405 continue;
1406
1407 }
1408 deviceId_t myDeviceOffset = myCheckDevice - myInstance_p->firstDeviceId;
1409 string myCircuitName = myMaster_p->name;
1410 netId_t myNetOffset = myMaster_p->devicePtr_v[myDeviceOffset]->signalId_v[1];
1411 debugFile << "DEBUG " << myCircuitName << " " << myDeviceOffset << " " << myNetOffset;
1412 debugFile << " " << myInputPower << "->" << myOutputPower << endl;
1413 string myKeyString = myCircuitName + to_string(myNetOffset) + myInputPower + myOutputPower;
1414 if ( myLevelShifters.count(myKeyString) == 0 ) {
1415 bool myIsInternal = false;
1416 if ( deviceParent_v[myCheckDevice] == netParent_v[myCheckNet]
1417 && netParent_v[myCheckNet] == netParent_v[inverterNet_v[myCheckNet]] ) { // same subcircuit
1418 CVirtualNet myMinInverterInput;
1419 CVirtualNet myMaxInverterInput;
1420 myMinInverterInput(minNet_v, inverterNet_v[myCheckNet]);
1421 myMaxInverterInput(maxNet_v, inverterNet_v[myCheckNet]);
1422 string myInverterPower = NetName(myMinInverterInput.finalNetId, thePrintCircuitFlag) + "/" + NetName(myMaxInverterInput.finalNetId, thePrintCircuitFlag);
1423 myIsInternal = myInputPower == myInverterPower; // level shifter contained in subcircuit with same power
1424 }
1425 vector<text_t> mySignals_v;
1426 mySignals_v.reserve(myMaster_p->localSignalIdMap.size());
1427 for (auto signal_net_pair_pit = myMaster_p->localSignalIdMap.begin(); signal_net_pair_pit != myMaster_p->localSignalIdMap.end(); signal_net_pair_pit++) {
1428 mySignals_v[signal_net_pair_pit->second] = signal_net_pair_pit->first;
1429 }
1430 string myLocalNetName = "*(" + myCircuitName + ")/" + string(mySignals_v[myNetOffset]);
1431 myDumpFile << ( myIsInternal ? "#" : "" ); // level shifters that are internal to subcircuits do not need to be checked
1432 myDumpFile << HierarchyName(deviceParent_v[myNmos], true) << "/" << string(mySignals_v[myNetOffset]);
1433 myDumpFile << " " << (myCheckDevice == myNmos ? "N" : "P");
1434 myDumpFile << " " << myInputPower << "->" << myOutputPower << endl;
1435 myLevelShifters.insert(myKeyString);
1436 if ( ! myIsInternal ) {
1437 myLevelShifterCount++;
1438 }
1439 }
1440 }
1441 reportFile << "total level shifters written: " << myLevelShifterCount << endl;
1442 myDumpFile.close();
1443 }
1444
CheckFuses()1445 returnCode_t CCvcDb::CheckFuses() {
1446 if ( IsEmpty(cvcParameters.cvcFuseFilename) ) return (OK);
1447 ifstream myFuseFile(cvcParameters.cvcFuseFilename);
1448 if ( myFuseFile.fail() ) {
1449 reportFile << "ERROR: Could not open fuse file: " << cvcParameters.cvcFuseFilename << endl;
1450 return(FAIL);
1451 }
1452 string myFuseName, myFuseStatus;
1453 bool myFuseError = false;
1454 deviceId_t myDeviceId;
1455 string myInputLine;
1456 while ( getline(myFuseFile, myInputLine) ) {
1457 if ( myInputLine.length() == 0 ) continue;
1458 if ( myInputLine.substr(0, 1) == "#" ) continue;
1459 myInputLine = trim_(myInputLine);
1460 stringstream myFuseStringStream(myInputLine);
1461 myFuseStringStream >> myFuseName >> myFuseStatus;
1462 if ( myFuseStringStream.fail() ) {
1463 reportFile << "ERROR: invalid format '" << myInputLine << "' expected fuse_name fuse_on/fuse_off" << endl;
1464 myFuseError = true;
1465 continue;
1466 }
1467 myDeviceId = FindDevice(0, myFuseName);
1468 if ( myFuseStatus != "fuse_on" && myFuseStatus != "fuse_off" ) {
1469 reportFile << "ERROR: unknown fuse setting " << myFuseStatus << endl;
1470 myFuseError = true;
1471 }
1472 if ( myDeviceId == UNKNOWN_DEVICE ) {
1473 reportFile << "ERROR: unknown device " << myFuseName << endl;
1474 myFuseError = true;
1475 } else {
1476 CInstance * myInstance_p = instancePtr_v[deviceParent_v[myDeviceId]];
1477 CCircuit * myCircuit_p = myInstance_p->master_p;
1478 CModel * myModel_p = myCircuit_p->devicePtr_v[myDeviceId - myInstance_p->firstDeviceId]->model_p;
1479 if ( myModel_p->type != FUSE_ON && myModel_p->type != FUSE_OFF ) {
1480 reportFile << "ERROR: not a fuse " << myFuseName << endl;
1481 myFuseError = true;
1482 }
1483 }
1484 }
1485 myFuseFile.close();
1486 return ((myFuseError) ? FAIL : OK);
1487 }
1488
CreateDebugCvcrcFile(ofstream & theOutputFile,instanceId_t theInstanceId,string theCell,int theCurrentStage)1489 void CCvcDb::CreateDebugCvcrcFile(ofstream & theOutputFile, instanceId_t theInstanceId, string theCell, int theCurrentStage) {
1490 if ( instancePtr_v[theInstanceId]->IsParallelInstance() ) {
1491 reportFile << "Cannot create debug file for parallel instance" << endl;
1492 PrintParallelInstance(theInstanceId, false);
1493 return;
1494 }
1495 theOutputFile << "# Debug cvcrc for " << HierarchyName(theInstanceId) << endl;
1496 string mySubcircuitName = instancePtr_v[theInstanceId]->master_p->name;
1497 theOutputFile << "CVC_TOP = '" << mySubcircuitName << "'" << endl;
1498 PrintSubcircuitCdl(mySubcircuitName);
1499 theOutputFile << "CVC_NETLIST = '" << mySubcircuitName << ".cdl" << "'" << endl;
1500 theOutputFile << "CVC_MODE = '" << theCell << "." << cvcParameters.cvcMode << "'" << endl;
1501 theOutputFile << "CVC_MODEL_FILE = '" << cvcParameters.cvcModelFilename << "'" << endl;
1502 string myPowerFile = "power." + theCell + "." + cvcParameters.cvcMode;
1503 PrintInstancePowerFile(theInstanceId, myPowerFile, theCurrentStage);
1504 theOutputFile << "CVC_POWER_FILE = '" << myPowerFile << "'" << endl;
1505 theOutputFile << "CVC_FUSE_FILE = ''" << endl;
1506 theOutputFile << "CVC_REPORT_FILE = '" << "debug_" << theCell << "_" << cvcParameters.cvcMode << ".log" << "'" << endl;
1507 theOutputFile << "CVC_REPORT_TITLE = 'Debug " << theCell << " mode " << cvcParameters.cvcMode << "'" << endl;
1508 theOutputFile << "CVC_CIRCUIT_ERROR_LIMIT = '" << cvcParameters.cvcCircuitErrorLimit << "'" << endl;
1509 theOutputFile << "CVC_SEARCH_LIMIT = '" << cvcParameters.cvcSearchLimit << "'" << endl;
1510 theOutputFile << "CVC_LEAK_LIMIT = '" << cvcParameters.cvcLeakLimit << "'" << endl;
1511 theOutputFile << "CVC_SOI = '" << (( cvcParameters.cvcSOI ) ? "true" : "false") << "'" << endl;
1512 theOutputFile << "CVC_SCRC = '" << (( cvcParameters.cvcSCRC ) ? "true" : "false") << "'" << endl;
1513 theOutputFile << "CVC_VTH_GATES = '" << (( cvcParameters.cvcVthGates ) ? "true" : "false") << "'" << endl;
1514 theOutputFile << "CVC_MIN_VTH_GATES = '" << (( cvcParameters.cvcMinVthGates ) ? "true" : "false") << "'" << endl;
1515 theOutputFile << "CVC_IGNORE_VTH_FLOATING = '" << (( cvcParameters.cvcIgnoreVthFloating ) ? "true" : "false") << "'" << endl;
1516 theOutputFile << "CVC_IGNORE_NO_LEAK_FLOATING = '" << (( cvcParameters.cvcIgnoreNoLeakFloating ) ? "true" : "false") << "'" << endl;
1517 theOutputFile << "CVC_LEAK_OVERVOLTAGE = '" << (( cvcParameters.cvcLeakOvervoltage ) ? "true" : "false") << "'" << endl;
1518 theOutputFile << "CVC_LOGIC_DIODES = '" << (( cvcParameters.cvcLogicDiodes ) ? "true" : "false") << "'" << endl;
1519 theOutputFile << "CVC_ANALOG_GATES = '" << (( cvcParameters.cvcAnalogGates ) ? "true" : "false") << "'" << endl;
1520 theOutputFile << "CVC_MOS_DIODE_ERROR_THRESHOLD = '" << Voltage_to_float(cvcParameters.cvcMosDiodeErrorThreshold) << "'" << endl;
1521 theOutputFile << "CVC_SHORT_ERROR_THRESHOLD = '" << Voltage_to_float(cvcParameters.cvcShortErrorThreshold) << "'" << endl;
1522 theOutputFile << "CVC_BIAS_ERROR_THRESHOLD = '" << Voltage_to_float(cvcParameters.cvcBiasErrorThreshold) << "'" << endl;
1523 theOutputFile << "CVC_FORWARD_ERROR_THRESHOLD = '" << Voltage_to_float(cvcParameters.cvcForwardErrorThreshold) << "'" << endl;
1524 theOutputFile << "CVC_FLOATING_ERROR_THRESHOLD = '" << Voltage_to_float(cvcParameters.cvcFloatingErrorThreshold) << "'" << endl;
1525 theOutputFile << "CVC_GATE_ERROR_THRESHOLD = '" << Voltage_to_float(cvcParameters.cvcGateErrorThreshold) << "'" << endl;
1526 theOutputFile << "CVC_LEAK?_ERROR_THRESHOLD = '" << Voltage_to_float(cvcParameters.cvcLeakErrorThreshold) << "'" << endl;
1527 theOutputFile << "CVC_EXPECTED_ERROR_THRESHOLD = '" << Voltage_to_float(cvcParameters.cvcExpectedErrorThreshold) << "'" << endl;
1528 theOutputFile << "CVC_OVERVOLTAGE_ERROR_THRESHOLD = '" << Voltage_to_float(cvcParameters.cvcOvervoltageErrorThreshold) << "'" << endl;
1529 theOutputFile << "CVC_PARALLEL_CIRCUIT_PORT_LIMIT = '" << cvcParameters.cvcParallelCircuitPortLimit << "'" << endl;
1530 theOutputFile << "CVC_CELL_ERROR_LIMIT_FILE = '" << cvcParameters.cvcCellErrorLimitFile << "'" << endl;
1531 theOutputFile << "CVC_CELL_CHECKSUM_FILE = '" << cvcParameters.cvcCellChecksumFile << "'" << endl;
1532 theOutputFile << "CVC_LARGE_CIRCUIT_SIZE = '" << cvcParameters.cvcLargeCircuitSize << "'" << endl;
1533 }
1534
PrintInstancePowerFile(instanceId_t theInstanceId,string thePowerFileName,int theCurrentStage)1535 void CCvcDb::PrintInstancePowerFile(instanceId_t theInstanceId, string thePowerFileName, int theCurrentStage) {
1536 ofstream myPowerFile(thePowerFileName);
1537 if ( ! ( myPowerFile && myPowerFile.good() ) ) {
1538 cout << "ERROR: Could not open power file " << thePowerFileName << " for output." << endl;
1539 return;
1540 }
1541 myPowerFile << "#NO AUTO MACROS" << endl;
1542 // print macro definitions
1543 // really bad overkill
1544 vector<string> myMacro_v;
1545 myMacro_v.reserve(CPower::powerCount);
1546 myMacro_v.resize(CPower::powerCount, "");
1547 for ( auto pair_pit = cvcParameters.cvcPowerMacroPtrMap.begin(); pair_pit != cvcParameters.cvcPowerMacroPtrMap.end(); pair_pit++ ) {
1548 myMacro_v[pair_pit->second->powerId] = pair_pit->first;
1549 }
1550 for ( netId_t macro_it = 0; macro_it < CPower::powerCount; macro_it++ ) {
1551 if ( ! IsEmpty(myMacro_v[macro_it]) ) {
1552 myPowerFile << "#define " << myMacro_v[macro_it] << " " << cvcParameters.cvcPowerMacroPtrMap[myMacro_v[macro_it]]->definition << endl;
1553 }
1554 }
1555 CInstance * myInstance_p = instancePtr_v[theInstanceId];
1556 CCircuit * myCircuit_p = myInstance_p->master_p;
1557 const text_t myResistorText = CPower::powerDefinitionText.SetTextAddress(RESISTOR_TEXT);
1558 // print port power and input definitions
1559 vector<text_t> mySignals_v;
1560 mySignals_v.reserve(myCircuit_p->localSignalIdMap.size());
1561 for (auto signal_net_pair_pit = myCircuit_p->localSignalIdMap.begin(); signal_net_pair_pit != myCircuit_p->localSignalIdMap.end(); signal_net_pair_pit++) {
1562 if ( signal_net_pair_pit->first != myResistorText ) {
1563 mySignals_v[signal_net_pair_pit->second] = signal_net_pair_pit->first;
1564 }
1565 }
1566 for ( netId_t net_it = 0; net_it < myInstance_p->master_p->portCount; net_it++ ) {
1567 netId_t myGlobalNetId = GetEquivalentNet(myInstance_p->localToGlobalNetId_v[net_it]);
1568 CPower * myPower_p = netVoltagePtr_v[myGlobalNetId].full;
1569 if ( myPower_p && ! IsEmpty(myPower_p->powerSignal()) ) {
1570 string myDefinition = string(myPower_p->definition).substr(0, string(myPower_p->definition).find(" calculation=>"));
1571 myPowerFile << mySignals_v[net_it] << myDefinition << endl;
1572 } else {
1573 CDeviceCount myDeviceCounts(myGlobalNetId, this, theInstanceId);
1574 // myDeviceCounts.Print(this);
1575 string mySuffix = "";
1576 if ( myDeviceCounts.activeNmosCount + myDeviceCounts.activePmosCount + myDeviceCounts.resistorCount == 0 ) {
1577 mySuffix = " input";
1578 } else { // print ports that are not input for reference
1579 myPowerFile << "#";
1580 }
1581 myPowerFile << mySignals_v[net_it] << mySuffix;
1582 netId_t myMinNetId, myMaxNetId;
1583 CPower *myMinPower_p = NULL;
1584 CPower *myMaxPower_p = NULL;
1585 if ( theCurrentStage == STAGE_COMPLETE ) {
1586 myMinNetId = minNet_v[myGlobalNetId].backupNetId;
1587 if ( myMinNetId != UNKNOWN_NET ) {
1588 while ( myMinNetId != minNet_v[myMinNetId].backupNetId ) {
1589 myMinNetId = minNet_v[myMinNetId].backupNetId;
1590 }
1591 myMinPower_p = leakVoltagePtr_v[myMinNetId].full;
1592 }
1593 myMaxNetId = maxNet_v[myGlobalNetId].backupNetId;
1594 if ( myMaxNetId != UNKNOWN_NET ) {
1595 while ( myMaxNetId != maxNet_v[myMaxNetId].backupNetId ) {
1596 myMaxNetId = maxNet_v[myMaxNetId].backupNetId;
1597 }
1598 myMaxPower_p = leakVoltagePtr_v[myMaxNetId].full;
1599 }
1600 } else {
1601 myMinNetId = minNet_v[myGlobalNetId].finalNetId;
1602 if ( myMinNetId != UNKNOWN_NET ) {
1603 myMinPower_p = netVoltagePtr_v[myMinNetId].full;
1604 }
1605 myMaxNetId = maxNet_v[myGlobalNetId].finalNetId;
1606 if ( myMaxNetId != UNKNOWN_NET ) {
1607 myMaxPower_p = netVoltagePtr_v[myMaxNetId].full;
1608 }
1609 }
1610 netId_t mySimNetId = simNet_v[myGlobalNetId].finalNetId;
1611 if ( myMinPower_p && myMinPower_p->minVoltage != UNKNOWN_VOLTAGE ) {
1612 myPowerFile << " min@" << PrintParameter(myMinPower_p->minVoltage, VOLTAGE_SCALE);
1613 }
1614 if ( mySimNetId != UNKNOWN_NET && netVoltagePtr_v[mySimNetId].full ) {
1615 CPower * mySimPower_p = netVoltagePtr_v[mySimNetId].full;
1616 if ( mySimPower_p->simVoltage != UNKNOWN_VOLTAGE ) {
1617 myPowerFile << " sim@" << PrintParameter(mySimPower_p->simVoltage, VOLTAGE_SCALE);
1618 }
1619 if ( mySimPower_p->type[HIZ_BIT] ) {
1620 myPowerFile << " open";
1621 }
1622 }
1623 if ( myMaxPower_p && myMaxPower_p->maxVoltage != UNKNOWN_VOLTAGE ) {
1624 myPowerFile << " max@" << PrintParameter(myMaxPower_p->maxVoltage, VOLTAGE_SCALE);
1625 }
1626 myPowerFile << endl;
1627 }
1628 }
1629 // print internal definitions
1630 unordered_set<text_t> myInternalDefinitions; // only print internal definitions once
1631 netId_t myFirstNetId = myInstance_p->firstNetId;
1632 for ( netId_t net_it = myFirstNetId; net_it < netCount && IsSubcircuitOf(netParent_v[net_it], theInstanceId); net_it++ ) {
1633 CPower * myPower_p = netVoltagePtr_v[net_it].full;
1634 if ( myPower_p ) {
1635 text_t mySignal = myPower_p->powerSignal();
1636 if ( ! IsEmpty(mySignal) && mySignal != myResistorText && myPower_p->simCalculationType != ESTIMATED_CALCULATION
1637 && myInternalDefinitions.count(mySignal) == 0 ) { // do not print resistor calculations, latch/scrc estimates, or duplicates
1638 myPowerFile << mySignal << " " << myPower_p->definition << endl;
1639 myInternalDefinitions.insert(mySignal);
1640 }
1641 }
1642 }
1643 cout << "Wrote debug power file " << thePowerFileName << endl;
1644 myPowerFile.close();
1645 }
1646