From e6aa59a12d48c0acf4b3e74db15ddfba3816090e Mon Sep 17 00:00:00 2001 From: "D. Mitch Bailey" Date: Fri, 8 Feb 2019 12:47:13 +0900 Subject: [PATCH] Changes for version 0.17.9 and 0.17.10 Added setup option to list models and power setting suggestions No unrelated short checks when short tolerance > 0 Use leak limit with limited to sim shorts (fixed comparison bug) --- configure.ac | 2 +- src/CCvcDb.cc | 10 +-- src/CCvcDb.hh | 1 + src/CCvcDb_init.cc | 149 ++++++++++++++++++++++++++++++++++++++++-- src/CCvcDb_main.cc | 12 +++- src/CCvcParameters.cc | 16 +++-- src/Cvc.hh | 3 +- src/cvc.cc | 1 + 8 files changed, 178 insertions(+), 16 deletions(-) diff --git a/configure.ac b/configure.ac index 76ee2ba..cc5ccf0 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ([2.69]) -AC_INIT(CVC, [0.17.8], [cvc@shuharisystem.com]) +AC_INIT(CVC, [0.17.10], [cvc@shuharisystem.com]) AC_CONFIG_SRCDIR(src) AC_CONFIG_HEADERS([config.h]) AC_USE_SYSTEM_EXTENSIONS diff --git a/src/CCvcDb.cc b/src/CCvcDb.cc index d2bb2b1..e0917ad 100755 --- a/src/CCvcDb.cc +++ b/src/CCvcDb.cc @@ -96,14 +96,16 @@ void CCvcDb::ReportShort(deviceId_t theDeviceId) { (IsPmos_(deviceType_v[theDeviceId]) && myConnections.simGateVoltage - myMaxVoltage == myConnections.device_p->model_p->Vth); myLeakCurrent = myConnections.EstimatedCurrent(myVthFlag); } - bool myUnrelatedFlag = ! myConnections.simSourcePower_p->IsRelatedPower(myConnections.simDrainPower_p, netVoltagePtr_v, simNet_v, simNet_v, true); + bool myUnrelatedFlag = cvcParameters.cvcShortErrorThreshold == 0 + && ! myConnections.simSourcePower_p->IsRelatedPower(myConnections.simDrainPower_p, netVoltagePtr_v, simNet_v, simNet_v, true); // no unrelated checks for real sim checks bool myCheckLeakLimit = cvcParameters.cvcShortErrorThreshold == 0 || myMaxVoltage - myMinVoltage > cvcParameters.cvcShortErrorThreshold; if ( ( myCheckLeakLimit && ExceedsLeakLimit_(myLeakCurrent) ) // flag leaks with large current || myUnrelatedFlag // flag leaks between unrelated power || ( myMaxVoltage != myMinVoltage && ! myVthFlag // ignore leaks between same voltages or at Vth && ( ( IsExternalPower_(myConnections.simSourcePower_p) && IsExternalPower_(myConnections.simDrainPower_p) - && myMaxVoltage - myMinVoltage > cvcParameters.cvcShortErrorThreshold ) // flag leaks between power nets + && myMaxVoltage - myMinVoltage > cvcParameters.cvcShortErrorThreshold + && ( cvcParameters.cvcShortErrorThreshold == 0 || ExceedsLeakLimit_(myLeakCurrent) )) // flag leaks between power nets || myConnections.simSourcePower_p->flagAllShorts || myConnections.simDrainPower_p->flagAllShorts ) ) ) { // flag nets for calculated logic levels // errorCount[LEAK]++; if ( cvcParameters.cvcCircuitErrorLimit == 0 || IncrementDeviceError(theDeviceId, LEAK) < cvcParameters.cvcCircuitErrorLimit ) { @@ -1086,7 +1088,7 @@ string CCvcDb::AdjustSimVoltage(CEventQueue& theEventQueue, deviceId_t theDevice myCalculation = " Limited sim to min" + myCalculation; debugFile << myCalculation << " " << NetName(myTargetNet) << endl; if ( thePropagationType != POWER_NETS_ONLY && myOriginalVoltage < myMinTargetVoltage - && theConnections.EstimatedCurrent(theVoltage, myMinTargetVoltage, mySourceResistance, myMinTargetResistance) < cvcParameters.cvcLeakLimit ) { + && theConnections.EstimatedCurrent(theVoltage, myMinTargetVoltage, mySourceResistance, myMinTargetResistance) > cvcParameters.cvcLeakLimit ) { ReportSimShort(theDeviceId, theVoltage, myMinTargetVoltage, myCalculation); } // voltage drops in first pass are skipped, only report original voltage limits @@ -1096,7 +1098,7 @@ string CCvcDb::AdjustSimVoltage(CEventQueue& theEventQueue, deviceId_t theDevice myCalculation = " Limited sim to max" + myCalculation; debugFile << myCalculation << " " << NetName(myTargetNet) << endl; if ( thePropagationType != POWER_NETS_ONLY && myOriginalVoltage > myMaxTargetVoltage - && theConnections.EstimatedCurrent(theVoltage, myMaxTargetVoltage, mySourceResistance, myMaxTargetResistance) < cvcParameters.cvcLeakLimit ) { + && theConnections.EstimatedCurrent(theVoltage, myMaxTargetVoltage, mySourceResistance, myMaxTargetResistance) > cvcParameters.cvcLeakLimit ) { ReportSimShort(theDeviceId, theVoltage, myMaxTargetVoltage, myCalculation); } // voltage drops in first pass are skipped, only report original voltage limits diff --git a/src/CCvcDb.hh b/src/CCvcDb.hh index 393575c..1b6ed67 100755 --- a/src/CCvcDb.hh +++ b/src/CCvcDb.hh @@ -229,6 +229,7 @@ public: voltage_t theMinVoltage, voltage_t theMaxVoltage, CDeviceIdVector & theFirstDrain_v, CDeviceIdVector & theNextDrain_v, CNetIdVector & theSourceNet_v); bool IsOppositeLogic(netId_t theFirstNet, netId_t theSecondNet); + void PrintNetSuggestions(); // error void PrintFuseError(netId_t theTargetNetId, CConnection & theConnections); diff --git a/src/CCvcDb_init.cc b/src/CCvcDb_init.cc index 90670a7..60cb4e6 100755 --- a/src/CCvcDb_init.cc +++ b/src/CCvcDb_init.cc @@ -88,6 +88,9 @@ CCvcDb::CCvcDb(int argc, const char * argv[]) : if ( ! IsAlphanumeric(reportPrefix) ) throw EFatalError("invalid prefix " + reportPrefix); } else if ( strcmp(argv[cvcArgIndex], "-v") == 0 || strcmp(argv[cvcArgIndex], "--version") == 0 ) { cout << "CVC: Circuit Validation Check Version " << CVC_VERSION << endl; + } else if ( strcmp(argv[cvcArgIndex], "-s") == 0 || strcmp(argv[cvcArgIndex], "--setup") == 0 ) { + cout << "CVC: Creating setup files " << endl; + gSetup_cvc = true; } else { cout << "WARNING: unrecognized option " << argv[cvcArgIndex] << endl; } @@ -545,8 +548,10 @@ returnCode_t CCvcDb::SetDeviceModels() { // parameterModelPtrMap[myDevice_p->parameters] = myDevice_p->model_p; // } if ( myDevice_p->model_p == NULL ) { - reportFile << "ERROR: No model match " << (*circuit_ppit)->name << "/" << myDevice_p->name; - reportFile << " " << myDevice_p->parameters << endl; + if ( ! gSetup_cvc ) { + reportFile << "ERROR: No model match " << (*circuit_ppit)->name << "/" << myDevice_p->name; + reportFile << " " << myDevice_p->parameters << endl; + } string myParameterString = trim_(string(myDevice_p->parameters)); myErrorModelSet.insert(myParameterString.substr(0, myParameterString.find(" ", 2))); myModelError = true; @@ -581,12 +586,14 @@ returnCode_t CCvcDb::SetDeviceModels() { isDeviceModelSet = true; if ( myModelError ) { if ( ! myErrorModelSet.empty() ) { - reportFile << "Missing models" << endl; + reportFile << "Missing models" << endl << endl; for ( auto model_pit = myErrorModelSet.begin(); model_pit != myErrorModelSet.end(); model_pit++) { - reportFile << *model_pit << endl; + reportFile << model_pit->substr(2) << " " << model_pit->substr(0,1) << endl; } } - reportFile << "ERROR: Model file problem" << endl; + if ( ! gSetup_cvc ) { + reportFile << endl << "ERROR: Model file problem" << endl; + } return(FAIL); } else { return (cvcParameters.cvcModelListMap.SetVoltageTolerances(reportFile, cvcParameters.cvcPowerMacroPtrMap)); @@ -1698,3 +1705,135 @@ bool CCvcDb::IsOppositeLogic(netId_t theFirstNet, netId_t theSecondNet) { return (inverterNet_v[theFirstNet] == theSecondNet || theFirstNet == inverterNet_v[theSecondNet]); } +void CCvcDb::PrintNetSuggestions() { + reportFile << "CVC: Possible power definitions" << endl; + unordered_map> myBulkCount; + CDeviceIdVector myNextBulk_v; + ResetVector(myNextBulk_v, deviceCount, UNKNOWN_DEVICE); + for (deviceId_t device_it = 0; device_it < deviceCount; device_it++) { + if ( bulkNet_v[device_it] == UNKNOWN_NET ) continue; + if ( IsMos_(deviceType_v[device_it]) && sourceNet_v[device_it] != drainNet_v[device_it] ) { // only count non-capacitor mosfet + if ( myBulkCount[bulkNet_v[device_it]].first++ > 0 ) { + myNextBulk_v[device_it] = myBulkCount[bulkNet_v[device_it]].second; + } + myBulkCount[bulkNet_v[device_it]].second = device_it; + } + } + map myDeviceCount; + for (CModelListMap::iterator keyModelListPair_pit = cvcParameters.cvcModelListMap.begin(); keyModelListPair_pit != cvcParameters.cvcModelListMap.end(); keyModelListPair_pit++) { + for (CModelList::iterator model_pit = keyModelListPair_pit->second.begin(); model_pit != keyModelListPair_pit->second.end(); model_pit++) { + myDeviceCount[model_pit->name] = 0; + } + } + reportFile << "CVC: Bulk > SD" << endl << endl; + for( auto net_it = 0; net_it < netCount; net_it++ ) { + if ( netVoltagePtr_v[net_it] ) continue; + if ( myBulkCount.count(net_it) && myBulkCount[net_it].first > connectionCount_v[net_it].SourceDrainCount() ) { + reportFile << NetName(net_it, PRINT_CIRCUIT_ON) << " SD/bulk " << connectionCount_v[net_it].SourceDrainCount() << "/" << myBulkCount[net_it].first; + for ( auto count_pit = myDeviceCount.begin(); count_pit != myDeviceCount.end(); count_pit++ ) { + count_pit->second = 0; + } + deviceId_t device_it = myBulkCount[net_it].second; + while ( device_it != UNKNOWN_DEVICE ) { + CInstance * myInstance_p = instancePtr_v[deviceParent_v[device_it]]; + deviceId_t myDeviceOffset = device_it - myInstance_p->firstDeviceId; + myDeviceCount[myInstance_p->master_p->devicePtr_v[myDeviceOffset]->model_p->name]++; + device_it = myNextBulk_v[device_it]; + } + for ( auto count_pit = myDeviceCount.begin(); count_pit != myDeviceCount.end(); count_pit++ ) { + if ( count_pit->second > 0 ) { + reportFile << " " << count_pit->first << "(" << count_pit->second << ")"; + } + } + reportFile << endl; + } +/* + if ( myBulkCount.count(net_it) && myBulkCount[net_it] > connectionCount_v[net_it].SourceDrainCount() ) { + reportFile << NetName(net_it, PRINT_CIRCUIT_ON) << " SD/bulk " << connectionCount_v[net_it].SourceDrainCount() << "/" << myBulkCount[net_it]; + for (CModelListMap::iterator keyModelListPair_pit = cvcParameters.cvcModelListMap.begin(); keyModelListPair_pit != cvcParameters.cvcModelListMap.end(); keyModelListPair_pit++) { + deviceId_t myDeviceCount = 0; + string myModelName; + for (CModelList::iterator model_pit = keyModelListPair_pit->second.begin(); model_pit != keyModelListPair_pit->second.end(); model_pit++) { + if ( IsMos_(model_pit->type) ) { + myModelName = model_pit->name; + CDevice * myDevice_p = model_pit->firstDevice_p; + while (myDevice_p) { + CCircuit * myParent_p = myDevice_p->parent_p; + deviceId_t myLocalDeviceId = myDevice_p->offset; + for (instanceId_t instance_it = 0; instance_it < myParent_p->instanceId_v.size(); instance_it++) { + CInstance * myInstance_p = instancePtr_v[myParent_p->instanceId_v[instance_it]]; + deviceId_t myDeviceId = myInstance_p->firstDeviceId + myLocalDeviceId; + if ( bulkNet_v[myDeviceId] == net_it ) { + myDeviceCount++; + } + } + myDevice_p = myDevice_p->nextDevice_p; + } + } + } + if ( myDeviceCount > 0 ) { + reportFile << " " << myModelName << "(" << myDeviceCount << ")"; + } + } + reportFile << endl; + } +*/ + } + reportFile << endl; + reportFile << "CVC: INPUT PORTS" << endl << endl; + for( auto net_it = 0; net_it < topCircuit_p->portCount; net_it++ ) { + if ( netVoltagePtr_v[net_it] ) continue; + unordered_set myCheckedNets; + unordered_set myUncheckedNets; + myUncheckedNets.insert(net_it); + bool myIsPossibleInput = true; + bool myHasGateConnection = false; + if ( firstGate_v[net_it] == UNKNOWN_DEVICE && firstSource_v[net_it] == UNKNOWN_DEVICE && firstDrain_v[net_it] == UNKNOWN_DEVICE ) { + reportFile << NetName(net_it, PRINT_CIRCUIT_ON) << " NO_CONNECTIONS" << endl; + } + while( ! myUncheckedNets.empty() && myUncheckedNets.size() < 10 && myIsPossibleInput ) { // 10 is arbitrary limit to prevent runaway + netId_t myCheckNet = *(myUncheckedNets.begin()); + myCheckedNets.insert(myCheckNet); + myUncheckedNets.erase(myUncheckedNets.begin()); + if ( firstGate_v[myCheckNet] != UNKNOWN_DEVICE ) { + myHasGateConnection = true; + } + //cout << "checked " << myCheckedNets.size() << " unchecked " << myUncheckedNets.size() << endl; + for ( deviceId_t device_it = firstSource_v[myCheckNet]; device_it != UNKNOWN_DEVICE && myIsPossibleInput; device_it = nextSource_v[device_it] ) { + netId_t mySearchNet = drainNet_v[device_it]; + if ( ( IsMos_(deviceType_v[device_it]) && mySearchNet != gateNet_v[device_it] ) + || ( ! IsMos_(device_it) && netVoltagePtr_v[mySearchNet] ) ) { + myIsPossibleInput = false; + } else if ( ! IsMos_(deviceType_v[device_it]) ) { + if ( myCheckedNets.count(mySearchNet) == 0 && myUncheckedNets.count(mySearchNet) == 0 ) { + if ( myUncheckedNets.size() < 10 ) { + myUncheckedNets.insert(mySearchNet); + } else { + myIsPossibleInput = false; + } + } + } + } + for ( deviceId_t device_it = firstDrain_v[myCheckNet]; device_it != UNKNOWN_DEVICE && myIsPossibleInput; device_it = nextDrain_v[device_it] ) { + netId_t mySearchNet = sourceNet_v[device_it]; + if ( ( IsMos_(deviceType_v[device_it]) && mySearchNet != gateNet_v[device_it] ) + || ( ! IsMos_(device_it) && netVoltagePtr_v[mySearchNet] ) ) { + myIsPossibleInput = false; + } else if ( ! IsMos_(deviceType_v[device_it]) ) { + if ( myCheckedNets.count(mySearchNet) == 0 && myUncheckedNets.count(mySearchNet) == 0 ) { + if ( myUncheckedNets.size() < 10 ) { + myUncheckedNets.insert(mySearchNet); + } else { + myIsPossibleInput = false; + } + } + } + } + } + if ( myIsPossibleInput && myHasGateConnection ) { + reportFile << NetName(net_it, PRINT_CIRCUIT_ON) << endl; + } + } + reportFile << endl; +} + diff --git a/src/CCvcDb_main.cc b/src/CCvcDb_main.cc index 4c0a280..afd01eb 100755 --- a/src/CCvcDb_main.cc +++ b/src/CCvcDb_main.cc @@ -127,7 +127,11 @@ void CCvcDb::VerifyCircuitForAllModes(int argc, const char * argv[]) { if ( gInteractive_cvc && --gContinueCount < 1 && InteractiveCvc(STAGE_START) == SKIP ) continue; if ( modelFileStatus != OK || powerFileStatus != OK || fuseFileStatus != OK ) { - reportFile << "ERROR: skipped due to problems in model/power/fuse files" << endl; + if ( gSetup_cvc ) { + reportFile << endl << "CVC: Setup check complete." << endl; + } else { + reportFile << "ERROR: skipped due to problems in model/power/fuse files" << endl; + } continue; } @@ -145,6 +149,9 @@ void CCvcDb::VerifyCircuitForAllModes(int argc, const char * argv[]) { cvcParameters.cvcPowerPtrList.SetPowerLimits(maxPower, minPower); LinkDevices(); OverrideFuses(); + if ( gSetup_cvc ) { + PrintNetSuggestions(); + } reportFile << PrintProgress(&lastSnapshot, "EQUIV ") << endl; reportFile << "Power nets " << CPower::powerCount << endl; // DumpStatistics(parameterModelPtrMap, "parameter->model map", logFile); @@ -154,6 +161,9 @@ void CCvcDb::VerifyCircuitForAllModes(int argc, const char * argv[]) { if ( gInteractive_cvc && --gContinueCount < 1 && InteractiveCvc(STAGE_LINK) == SKIP ) { continue; } + if ( gSetup_cvc ) { + continue; + } /// Stage 3) Calculate voltages across resistors /// - Calculated resistance diff --git a/src/CCvcParameters.cc b/src/CCvcParameters.cc index 397ba4f..8578e70 100755 --- a/src/CCvcParameters.cc +++ b/src/CCvcParameters.cc @@ -328,8 +328,12 @@ returnCode_t CCvcParameters::LoadModels() { cvcModelListMap.Clear(); cvcModelListMap.filename = cvcModelFilename; if ( myModelFile.fail() ) { - reportFile << "ERROR: Could not open " << cvcModelFilename << endl; - return (FAIL); + if ( gSetup_cvc ) { + return(OK); + } else { + reportFile << "ERROR: Could not open " << cvcModelFilename << endl; + return (FAIL); + } // throw EFatalError("Could not open " + cvcModelFilename); // exit(1); } @@ -385,8 +389,12 @@ returnCode_t CCvcParameters::LoadPower() { cvcPowerFamilyMap.clear(); cvcPowerMacroPtrMap.clear(); if ( myPowerFile.fail() ) { - reportFile << "ERROR: Could not open " << cvcPowerFilename << endl; - return (FAIL); + if ( gSetup_cvc ) { + return(OK); + } else { + reportFile << "ERROR: Could not open " << cvcPowerFilename << endl; + return (FAIL); + } // throw EFatalError("Could not open " + cvcPowerFilename); // exit(1); } diff --git a/src/Cvc.hh b/src/Cvc.hh index 777db08..618385c 100755 --- a/src/Cvc.hh +++ b/src/Cvc.hh @@ -24,9 +24,10 @@ #ifndef CVC_H_ #define CVC_H_ -#define CVC_VERSION "0.17.8" +#define CVC_VERSION "0.17.10" extern bool gDebug_cvc; +extern bool gSetup_cvc; extern bool gInterrupted; extern bool gInteractive_cvc; diff --git a/src/cvc.cc b/src/cvc.cc index 3a83a18..c020036 100755 --- a/src/cvc.cc +++ b/src/cvc.cc @@ -38,6 +38,7 @@ char vv_suffix[2], vv_trailer[2]; ///@} bool gDebug_cvc = false; +bool gSetup_cvc = false; bool gInterrupted = false; //!< for detecting interrupts HIST_ENTRY **gHistoryList; //!< readline history