From c6551a0fa59f9b0bf828598b3154b06ba2dd5ee7 Mon Sep 17 00:00:00 2001 From: "D. Mitch Bailey" Date: Fri, 18 Dec 2020 12:47:13 +0900 Subject: [PATCH] Changes for version 1.1.0 Added model check. (currently only Vb checks. no check_cvc support. --- configure.ac | 2 +- src/CCircuit.hh | 4 +- src/CCvcDb.hh | 3 ++ src/CCvcDb_error.cc | 77 +++++++++++++++++++------- src/CCvcDb_init.cc | 122 ++++++++++++++++++++++++++++++------------ src/CCvcDb_main.cc | 3 +- src/CCvcDb_print.cc | 1 + src/CCvcDb_utility.cc | 2 +- src/CCvcParameters.cc | 18 ++++--- src/CCvcParameters.hh | 4 +- src/CModel.cc | 39 ++++++++++++++ src/CModel.hh | 26 +++++++++ src/Cvc.hh | 2 +- src/CvcTypes.hh | 2 +- 14 files changed, 239 insertions(+), 66 deletions(-) diff --git a/configure.ac b/configure.ac index 4e49e69..37572d1 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, [1.0.0], [cvc@shuharisystem.com]) +AC_INIT(CVC, [1.1.0], [cvc@shuharisystem.com]) AC_CONFIG_SRCDIR(src) AC_CONFIG_HEADERS([config.h]) AC_USE_SYSTEM_EXTENSIONS diff --git a/src/CCircuit.hh b/src/CCircuit.hh index 2ebbf31..595b858 100755 --- a/src/CCircuit.hh +++ b/src/CCircuit.hh @@ -49,8 +49,8 @@ public: CTextVector internalSignal_v; CDevicePtrVector devicePtr_v; CDevicePtrVector subcircuitPtr_v; - vector> deviceErrorCount_v; - vector> devicePrintCount_v; + vector> deviceErrorCount_v; + vector> devicePrintCount_v; CInstanceIdVector instanceId_v; CInstanceIdVector instanceHashId_v; diff --git a/src/CCvcDb.hh b/src/CCvcDb.hh index 4a77973..3dab955 100755 --- a/src/CCvcDb.hh +++ b/src/CCvcDb.hh @@ -221,6 +221,7 @@ public: returnCode_t LoadCellErrorLimits(); void LoadCellChecksums(); void LoadNetChecks(); + void LoadModelChecks(); // error void PrintFuseError(netId_t theTargetNetId, CConnection & theConnections); @@ -230,7 +231,9 @@ public: void FindVbsError(ogzstream & theErrorFile, voltage_t theParameter, CFullConnection & theConnections, instanceId_t theInstance_p, string theDisplayParameter); void FindVdsError(ogzstream & theErrorFile, voltage_t theParameter, CFullConnection & theConnections, instanceId_t theInstance_p, string theDisplayParameter); void FindVgsError(ogzstream & theErrorFile, voltage_t theParameter, CFullConnection & theConnections, instanceId_t theInstance_p, string theDisplayParameter); + void FindModelError(ogzstream & theErrorFile, CModelCheck &theCheck, CFullConnection & theConnections, instanceId_t theInstanceId); void PrintOverVoltageError(ogzstream & theErrorFile, CFullConnection & theConnections, cvcError_t theErrorIndex, string theExplanation, instanceId_t theInstance_p); + void PrintModelError(ogzstream & theErrorFile, CFullConnection & theConnections, CModelCheck & theCheck, instanceId_t theInstanceId); void FindAllOverVoltageErrors(); void AppendErrorFile(string theTempFileName, string theHeading, int theErrorSubIndex); void FindNmosGateVsSourceErrors(); diff --git a/src/CCvcDb_error.cc b/src/CCvcDb_error.cc index 7bec2df..f5fc69c 100755 --- a/src/CCvcDb_error.cc +++ b/src/CCvcDb_error.cc @@ -177,7 +177,7 @@ void CCvcDb::FindVdsError(ogzstream & theErrorFile, voltage_t theParameter, CFul } void CCvcDb::FindVgsError(ogzstream & theErrorFile, voltage_t theParameter, CFullConnection & theConnections, instanceId_t theInstanceId, string theDisplayParameter) { - theParameter += cvcParameters.cvcOvervoltageErrorThreshold; + theParameter += cvcParameters.cvcOvervoltageErrorThreshold; if ( ( theConnections.validMinGate && theConnections.validMaxSource && abs(theConnections.minGateVoltage - theConnections.maxSourceVoltage) > theParameter ) || ( theConnections.validMaxGate && theConnections.validMinSource @@ -186,9 +186,9 @@ void CCvcDb::FindVgsError(ogzstream & theErrorFile, voltage_t theParameter, CFul && abs(theConnections.minGateVoltage - theConnections.maxDrainVoltage) > theParameter ) || ( theConnections.validMaxGate && theConnections.validMinDrain && abs(theConnections.maxGateVoltage - theConnections.minDrainVoltage) > theParameter ) ) { - PrintOverVoltageError(theErrorFile, theConnections, OVERVOLTAGE_VGS, "Overvoltage Error:Gate vs Source/Drain:" + theDisplayParameter, theInstanceId); + PrintOverVoltageError(theErrorFile, theConnections, OVERVOLTAGE_VGS, "Overvoltage Error:Gate vs Source/Drain:" + theDisplayParameter, theInstanceId); } else if ( ! cvcParameters.cvcLeakOvervoltage ) { - return ; + return ; } else if ( ( theConnections.validMinGateLeak && theConnections.validMaxSourceLeak && abs(theConnections.minGateLeakVoltage - theConnections.maxSourceLeakVoltage) > theParameter ) || ( theConnections.validMaxGateLeak && theConnections.validMinSourceLeak @@ -209,19 +209,50 @@ void CCvcDb::FindVgsError(ogzstream & theErrorFile, voltage_t theParameter, CFul && abs(theConnections.minSourceLeakVoltage) > theParameter ) || ( ! theConnections.validMaxGateLeak && theConnections.validMinDrainLeak && abs(theConnections.minDrainLeakVoltage) > theParameter ) ) { - PrintOverVoltageError(theErrorFile, theConnections, OVERVOLTAGE_VGS, "Overvoltage Error:Gate vs Source/Drain: (logic ok)" + theDisplayParameter, theInstanceId); + PrintOverVoltageError(theErrorFile, theConnections, OVERVOLTAGE_VGS, "Overvoltage Error:Gate vs Source/Drain: (logic ok)" + theDisplayParameter, theInstanceId); + } +} + +void CCvcDb::FindModelError(ogzstream & theErrorFile, CModelCheck & theCheck, CFullConnection & theConnections, instanceId_t theInstanceId) { + bool myError = false; + if ( theCheck.parameter == "Vb" ) { + if ( ! (theConnections.validMinBulk && theConnections.validMaxBulk) ) { + myError = true; + } else { + if ( ! IsEmpty(theCheck.minExclusiveText) ) { + myError |= theConnections.minBulkVoltage <= theCheck.minExclusiveVoltage; + } else if ( ! IsEmpty(theCheck.minInclusiveText) ) { + myError |= theConnections.minBulkVoltage < theCheck.minInclusiveVoltage; + } + if ( ! IsEmpty(theCheck.maxExclusiveText) ) { + myError |= theConnections.maxBulkVoltage >= theCheck.maxExclusiveVoltage; + } else if ( ! IsEmpty(theCheck.maxInclusiveText) ) { + myError |= theConnections.maxBulkVoltage > theCheck.maxInclusiveVoltage; + } + } + } + if ( myError ) { + PrintModelError(theErrorFile, theConnections, theCheck, theInstanceId); + } +} + +void CCvcDb::PrintOverVoltageError(ogzstream & theErrorFile, CFullConnection & theConnections, cvcError_t theErrorIndex, string theExplanation, instanceId_t theInstanceId) { + if ( cvcParameters.cvcCircuitErrorLimit == 0 || IncrementDeviceError(theConnections.deviceId, theErrorIndex) < cvcParameters.cvcCircuitErrorLimit ) { + theErrorFile << theExplanation << endl; + bool myLeakCheckFlag = ( theExplanation.find("logic ok") < string::npos ); + PrintDeviceWithAllConnections(theInstanceId, theConnections, theErrorFile, myLeakCheckFlag); + theErrorFile << endl; + } +} + +void CCvcDb::PrintModelError(ogzstream & theErrorFile, CFullConnection & theConnections, CModelCheck & theCheck, instanceId_t theInstanceId) { + if ( cvcParameters.cvcCircuitErrorLimit == 0 || IncrementDeviceError(theConnections.deviceId, MODEL_CHECK) < cvcParameters.cvcCircuitErrorLimit ) { + theErrorFile << "Model error: " << theCheck.check << endl; + PrintDeviceWithAllConnections(theInstanceId, theConnections, theErrorFile, false); + theErrorFile << endl; } } -void CCvcDb::PrintOverVoltageError(ogzstream & theErrorFile, CFullConnection & theConnections, cvcError_t theErrorIndex, string theExplanation, instanceId_t theInstanceId) { - if ( cvcParameters.cvcCircuitErrorLimit == 0 || IncrementDeviceError(theConnections.deviceId, theErrorIndex) < cvcParameters.cvcCircuitErrorLimit ) { - theErrorFile << theExplanation << endl; - bool myLeakCheckFlag = ( theExplanation.find("logic ok") < string::npos ); - PrintDeviceWithAllConnections(theInstanceId, theConnections, theErrorFile, myLeakCheckFlag); - theErrorFile << endl; - } -} - void CCvcDb::FindAllOverVoltageErrors() { CFullConnection myConnections; reportFile << "! Checking overvoltage errors" << endl << endl; @@ -235,8 +266,11 @@ void CCvcDb::FindAllOverVoltageErrors() { ogzstream myVdsErrorFile(myVdsErrorFileName); myVdsErrorFile << "! Checking Vds overvoltage errors" << endl << endl; string myVgsErrorFileName(tmpnam(NULL)); - ogzstream myVgsErrorFile(myVgsErrorFileName); - myVgsErrorFile << "! Checking Vgs overvoltage errors" << endl << endl; + ogzstream myVgsErrorFile(myVgsErrorFileName); + myVgsErrorFile << "! Checking Vgs overvoltage errors" << endl << endl; + string myModelErrorFileName(tmpnam(NULL)); + ogzstream myModelErrorFile(myModelErrorFileName); + myModelErrorFile << "! Checking Model errors" << endl << endl; 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++) { @@ -255,7 +289,7 @@ void CCvcDb::FindAllOverVoltageErrors() { } if ( model_pit->maxVgs != UNKNOWN_VOLTAGE ) { myVgsDisplayParameter = " Vgs=" + PrintToleranceParameter(model_pit->maxVgsDefinition, model_pit->maxVgs, VOLTAGE_SCALE) + " " + model_pit->ConditionString(); - } + } while (myDevice_p) { CCircuit * myParent_p = myDevice_p->parent_p; for (instanceId_t instance_it = 0; instance_it < myParent_p->instanceId_v.size(); instance_it++) { @@ -268,7 +302,10 @@ void CCvcDb::FindAllOverVoltageErrors() { if ( model_pit->maxVbg != UNKNOWN_VOLTAGE ) FindVbgError(myVbgErrorFile, model_pit->maxVbg, myConnections, myInstanceId, myVbgDisplayParameter); if ( model_pit->maxVbs != UNKNOWN_VOLTAGE ) FindVbsError(myVbsErrorFile, model_pit->maxVbs, myConnections, myInstanceId, myVbsDisplayParameter); if ( model_pit->maxVds != UNKNOWN_VOLTAGE ) FindVdsError(myVdsErrorFile, model_pit->maxVds, myConnections, myInstanceId, myVdsDisplayParameter); - if ( model_pit->maxVgs != UNKNOWN_VOLTAGE ) FindVgsError(myVgsErrorFile, model_pit->maxVgs, myConnections, myInstanceId, myVgsDisplayParameter); + if ( model_pit->maxVgs != UNKNOWN_VOLTAGE ) FindVgsError(myVgsErrorFile, model_pit->maxVgs, myConnections, myInstanceId, myVgsDisplayParameter); + for ( auto check_pit = model_pit->checkList.begin(); check_pit != model_pit->checkList.end(); check_pit++ ) { + FindModelError(myModelErrorFile, *check_pit, myConnections, myInstanceId); + } } myDevice_p = myDevice_p->nextDevice_p; } @@ -277,11 +314,13 @@ void CCvcDb::FindAllOverVoltageErrors() { myVbgErrorFile.close(); myVbsErrorFile.close(); myVdsErrorFile.close(); - myVgsErrorFile.close(); + myVgsErrorFile.close(); + myModelErrorFile.close(); AppendErrorFile(myVbgErrorFileName, "! Checking Vbg overvoltage errors", OVERVOLTAGE_VBG - OVERVOLTAGE_VBG); AppendErrorFile(myVbsErrorFileName, "! Checking Vbs overvoltage errors", OVERVOLTAGE_VBS - OVERVOLTAGE_VBG); AppendErrorFile(myVdsErrorFileName, "! Checking Vds overvoltage errors", OVERVOLTAGE_VDS - OVERVOLTAGE_VBG); - AppendErrorFile(myVgsErrorFileName, "! Checking Vgs overvoltage errors", OVERVOLTAGE_VGS - OVERVOLTAGE_VBG); + AppendErrorFile(myVgsErrorFileName, "! Checking Vgs overvoltage errors", OVERVOLTAGE_VGS - OVERVOLTAGE_VBG); + AppendErrorFile(myModelErrorFileName, "! Checking Model errors", MODEL_CHECK - OVERVOLTAGE_VBG); } void CCvcDb::AppendErrorFile(string theTempFileName, string theHeading, int theErrorSubIndex) { diff --git a/src/CCvcDb_init.cc b/src/CCvcDb_init.cc index cbd2797..1d357f1 100755 --- a/src/CCvcDb_init.cc +++ b/src/CCvcDb_init.cc @@ -1740,45 +1740,101 @@ void CCvcDb::LoadNetChecks() { /// /// Currently supports: /// "inverter_input=output": check to verify inverter output ground/power are the same as input ground/power - /// "opposite_logic": verify that 2 nets are logically opposite - if ( IsEmpty(cvcParameters.cvcNetCheckFile) ) return; - igzstream myNetCheckFile; - myNetCheckFile.open(cvcParameters.cvcNetCheckFile); - if ( myNetCheckFile.fail() ) { - throw EFatalError("Could not open level shifter file: '" + cvcParameters.cvcNetCheckFile + "'"); + /// "opposite_logic": verify that 2 nets are logically opposite + if ( IsEmpty(cvcParameters.cvcNetCheckFile) ) return; + + igzstream myNetCheckFile; + myNetCheckFile.open(cvcParameters.cvcNetCheckFile); + if ( myNetCheckFile.fail() ) { + throw EFatalError("Could not open level shifter file: '" + cvcParameters.cvcNetCheckFile + "'"); exit(1); - - } - string myInput; - reportFile << "CVC: Reading net checks..." << endl; - while ( getline(myNetCheckFile, myInput) ) { + + } + string myInput; + reportFile << "CVC: Reading net checks..." << endl; + while ( getline(myNetCheckFile, myInput) ) { if ( myInput.substr(0, 1) == "#" ) continue; // ignore comments - - size_t myStringBegin = myInput.find_first_not_of(" \t"); - size_t myStringEnd = myInput.find_first_of(" \t", myStringBegin); - string myNetName = myInput.substr(myStringBegin, myStringEnd - myStringBegin); - set * myNetIdList = FindUniqueNetIds(myNetName); // expands buses and hierarchy - if ( myNetIdList->empty() ) { - reportFile << "ERROR: Could not expand net " << myNetName << endl; - } - myStringBegin = myInput.find_first_not_of(" \t", myStringEnd); - myStringEnd = myInput.find_first_of(" \t", myStringBegin); - string myOperation = myInput.substr(myStringBegin, myStringEnd - myStringBegin); - if ( myOperation == "inverter_input=output" ) { - inverterInputOutputCheckList.push_front(myNetName); + + size_t myStringBegin = myInput.find_first_not_of(" \t"); + size_t myStringEnd = myInput.find_first_of(" \t", myStringBegin); + string myNetName = myInput.substr(myStringBegin, myStringEnd - myStringBegin); + set * myNetIdList = FindUniqueNetIds(myNetName); // expands buses and hierarchy + if ( myNetIdList->empty() ) { + reportFile << "ERROR: Could not expand net " << myNetName << endl; + } + myStringBegin = myInput.find_first_not_of(" \t", myStringEnd); + myStringEnd = myInput.find_first_of(" \t", myStringBegin); + string myOperation = myInput.substr(myStringBegin, myStringEnd - myStringBegin); + if ( myOperation == "inverter_input=output" ) { + inverterInputOutputCheckList.push_front(myNetName); } else if ( myOperation == "opposite_logic" ) { myStringBegin = myInput.find_first_not_of(" \t", myStringEnd); myStringEnd = myInput.find_first_of(" \t", myStringBegin); - string myOpposite = myInput.substr(myStringBegin, myStringEnd - myStringBegin); + string myOpposite = myInput.substr(myStringBegin, myStringEnd - myStringBegin); size_t myDelimiter = myNetName.find_last_of(HIERARCHY_DELIMITER); if ( myDelimiter < myNetName.npos ) { myOpposite = myNetName.substr(0, myDelimiter) + HIERARCHY_DELIMITER + myOpposite; } - oppositeLogicList.push_front(make_pair(myNetName, myOpposite)); - } else { - reportFile << "ERROR: unknown check " << myInput << endl; - } - } - myNetCheckFile.close(); -} - + oppositeLogicList.push_front(make_pair(myNetName, myOpposite)); + } else { + reportFile << "ERROR: unknown check " << myInput << endl; + } + } + myNetCheckFile.close(); +} + +void CCvcDb::LoadModelChecks() { + /// Load model checks from file. + /// + /// Currently supports: + /// "Vb": check bulk voltage + if ( IsEmpty(cvcParameters.cvcModelCheckFile) ) return; + + igzstream myModelCheckFile; + myModelCheckFile.open(cvcParameters.cvcModelCheckFile); + if ( myModelCheckFile.fail() ) { + throw EFatalError("Could not open model check file: '" + cvcParameters.cvcModelCheckFile + "'"); + exit(1); + + } + string myInput; + reportFile << "CVC: Reading model checks..." << endl; + while ( getline(myModelCheckFile, myInput) ) { + if ( myInput.substr(0, 1) == "#" ) continue; // ignore comments + + size_t myStringBegin = myInput.find_first_not_of(" \t"); + size_t myStringEnd = myInput.find_first_of(" \t", myStringBegin); + string myModelName = myInput.substr(myStringBegin, myStringEnd - myStringBegin); + CModelList * myModelList_p = cvcParameters.cvcModelListMap.FindModelList(myModelName); + if ( ! myModelList_p ) { + reportFile << "WARNING: could not find model " << myModelName << " for model check '" << myInput << "'" << endl; + continue; + + } + myStringBegin = myInput.find_first_not_of(" \t", myStringEnd); + myStringEnd = myInput.find_first_of(" \t", myStringBegin); + string myCheck = myInput.substr(myStringBegin, myStringEnd - myStringBegin); + myStringEnd = myInput.find_first_of(" \t=<>", myStringBegin); + string myParameter = myInput.substr(myStringBegin, myStringEnd - myStringBegin); + myStringBegin = myInput.find_first_of("=<>", myStringEnd); + myStringEnd = myInput.find_first_not_of("=<>", myStringBegin); + string myOperation = myInput.substr(myStringBegin, myStringEnd - myStringBegin); + myStringBegin = myInput.find_first_not_of("=<>", myStringEnd); + myStringEnd = myInput.find_first_of(" \t", myStringBegin); + string myValue = myInput.substr(myStringBegin, myStringEnd - myStringBegin); + if ( myParameter == "Vb" ) { + if ( myOperation != "=" ) { + reportFile << "WARNING: unknown operation '" << myOperation << "' in model check '" << myInput << "'" << endl; + continue; + + } + for ( auto model_pit = myModelList_p->begin(); model_pit != myModelList_p->end(); model_pit++ ) { + model_pit->checkList.push_front(CModelCheck(myCheck, "Vb", myValue, "", myValue, "")); + } + } else { + reportFile << "WARNING: unknown parameter '" << myParameter << "' in model check '" << myInput << "'" << endl; + } + } + myModelCheckFile.close(); +} + diff --git a/src/CCvcDb_main.cc b/src/CCvcDb_main.cc index 0bdaebe..67b2633 100755 --- a/src/CCvcDb_main.cc +++ b/src/CCvcDb_main.cc @@ -106,7 +106,8 @@ void CCvcDb::VerifyCircuitForAllModes(int argc, const char * argv[]) { LoadCellChecksums(); CountObjectsAndLinkSubcircuits(); AssignGlobalIDs(); - LoadNetChecks(); + LoadNetChecks(); + LoadModelChecks(); PrintLargeCircuits(); reportFile << PrintProgress(&lastSnapshot, "DB") << endl; } diff --git a/src/CCvcDb_print.cc b/src/CCvcDb_print.cc index 70c1962..7cdceb1 100755 --- a/src/CCvcDb_print.cc +++ b/src/CCvcDb_print.cc @@ -776,6 +776,7 @@ void CCvcDb::PrintErrorTotals() { reportFile << "CVC: Overvoltage-VBS: " << errorCount[OVERVOLTAGE_VBS] << endl; reportFile << "CVC: Overvoltage-VDS: " << errorCount[OVERVOLTAGE_VDS] << endl; reportFile << "CVC: Overvoltage-VGS: " << errorCount[OVERVOLTAGE_VGS] << endl; + reportFile << "CVC: Model errors: " << errorCount[MODEL_CHECK] << endl; reportFile << "CVC: Unexpected voltage : " << errorCount[EXPECTED_VOLTAGE] << endl; } else { reportFile << "WARNING: Error detection incomplete" << endl; diff --git a/src/CCvcDb_utility.cc b/src/CCvcDb_utility.cc index a6973b2..7f50f3d 100755 --- a/src/CCvcDb_utility.cc +++ b/src/CCvcDb_utility.cc @@ -743,7 +743,7 @@ size_t CCvcDb::IncrementDeviceError(deviceId_t theDeviceId, int theErrorIndex) { CInstance * myInstance_p = instancePtr_v[deviceParent_v[theDeviceId]]; CCircuit * myParent_p = myInstance_p->master_p; int myErrorSubIndex = 0; - if ( theErrorIndex >= OVERVOLTAGE_VBG && theErrorIndex <= OVERVOLTAGE_VGS ) { + if ( theErrorIndex >= OVERVOLTAGE_VBG && theErrorIndex <= MODEL_CHECK ) { myErrorSubIndex = theErrorIndex - OVERVOLTAGE_VBG; } int myMFactor = CalculateMFactor(deviceParent_v[theDeviceId]); diff --git a/src/CCvcParameters.cc b/src/CCvcParameters.cc index 61f57f5..9b4578b 100755 --- a/src/CCvcParameters.cc +++ b/src/CCvcParameters.cc @@ -105,8 +105,10 @@ void CCvcParameters::ResetEnvironment() { //! Name of file containing list of checksums for each circuit cvcLargeCircuitSize = defaultLargeCircuitSize; //! Minimum device count to display large circuits - cvcNetCheckFile = defaultNetCheckFile; - //! Name of file containing list of net checks + cvcNetCheckFile = defaultNetCheckFile; + //! Name of file containing list of net checks + cvcModelCheckFile = defaultModelCheckFile; + //! Name of file containing list of model checks } void CCvcParameters::PrintEnvironment(ostream & theOutputFile) { @@ -145,7 +147,8 @@ void CCvcParameters::PrintEnvironment(ostream & theOutputFile) { theOutputFile << "CVC_CELL_ERROR_LIMIT_FILE = '" << cvcCellErrorLimitFile << "'" << endl; theOutputFile << "CVC_CELL_CHECKSUM_FILE = '" << cvcCellChecksumFile << "'" << endl; theOutputFile << "CVC_LARGE_CIRCUIT_SIZE = '" << cvcLargeCircuitSize << "'" << endl; - theOutputFile << "CVC_NET_CHECK_FILE = '" << cvcNetCheckFile << "'" << endl; + theOutputFile << "CVC_NET_CHECK_FILE = '" << cvcNetCheckFile << "'" << endl; + theOutputFile << "CVC_MODEL_CHECK_FILE = '" << cvcModelCheckFile << "'" << endl; theOutputFile << "End of parameters" << endl << endl; } @@ -191,7 +194,8 @@ void CCvcParameters::PrintDefaultEnvironment() { myDefaultCvcrc << "CVC_CELL_ERROR_LIMIT_FILE = '" << cvcCellErrorLimitFile << "'" << endl; myDefaultCvcrc << "CVC_CELL_CHECKSUM_FILE = '" << cvcCellChecksumFile << "'" << endl; myDefaultCvcrc << "CVC_LARGE_CIRCUIT_SIZE = '" << cvcLargeCircuitSize << "'" << endl; - myDefaultCvcrc << "CVC_NET_CHECK_FILE = '" << cvcNetCheckFile << "'" << endl; + myDefaultCvcrc << "CVC_NET_CHECK_FILE = '" << cvcNetCheckFile << "'" << endl; + myDefaultCvcrc << "CVC_MODEL_CHECK_FILE = '" << cvcModelCheckFile << "'" << endl; myDefaultCvcrc.close(); } @@ -303,8 +307,10 @@ void CCvcParameters::LoadEnvironment(const string theEnvironmentFilename, const cvcCellChecksumFile = myBuffer; } else if ( myVariable == "CVC_LARGE_CIRCUIT_SIZE" ) { cvcLargeCircuitSize = from_string(myBuffer); - } else if ( myVariable == "CVC_NET_CHECK_FILE" ) { - cvcNetCheckFile = myBuffer; + } else if ( myVariable == "CVC_NET_CHECK_FILE" ) { + cvcNetCheckFile = myBuffer; + } else if ( myVariable == "CVC_MODEL_CHECK_FILE" ) { + cvcModelCheckFile = myBuffer; } } if ( ! IsEmpty(theReportPrefix) ) { diff --git a/src/CCvcParameters.hh b/src/CCvcParameters.hh index 032b731..b29c365 100755 --- a/src/CCvcParameters.hh +++ b/src/CCvcParameters.hh @@ -57,6 +57,7 @@ public: const string defaultCellChecksumFile = ""; const size_t defaultLargeCircuitSize = 10e6; const string defaultNetCheckFile = ""; + const string defaultModelCheckFile = ""; string cvcReportTitle; @@ -106,7 +107,8 @@ public: string cvcCellErrorLimitFile = defaultCellErrorLimitFile; string cvcCellChecksumFile = defaultCellChecksumFile; size_t cvcLargeCircuitSize = defaultLargeCircuitSize; - string cvcNetCheckFile = defaultNetCheckFile; + string cvcNetCheckFile = defaultNetCheckFile; + string cvcModelCheckFile = defaultModelCheckFile; string cvcLastTopBlock; string cvcLastNetlistFilename; diff --git a/src/CModel.cc b/src/CModel.cc index 5081970..81d642a 100755 --- a/src/CModel.cc +++ b/src/CModel.cc @@ -30,6 +30,30 @@ #include "CPower.hh" #include +CModelCheck::CModelCheck(string theCheck, string theParameter, string theInclusiveMin, string theExclusiveMin, string theInclusiveMax, string theExclusiveMax ) { + check = theCheck; + parameter = theParameter; + isVoltage = (theParameter[0] == 'V'); + minInclusiveText = theInclusiveMin; + minExclusiveText = theExclusiveMin; + maxInclusiveText = theInclusiveMax; + maxExclusiveText = theExclusiveMax; + SetValue(minInclusiveText, minInclusiveVoltage, minInclusiveValue); + SetValue(maxInclusiveText, maxInclusiveVoltage, maxInclusiveValue); + SetValue(minExclusiveText, minExclusiveVoltage, minExclusiveValue); + SetValue(maxExclusiveText, maxExclusiveVoltage, maxExclusiveValue); +} + +void CModelCheck::SetValue(string theParameter, voltage_t &theVoltage, float &theValue) { + if ( ! IsEmpty(theParameter) ) { + if ( isVoltage && IsValidVoltage_(theParameter) ) { + theVoltage = round(from_string(theParameter) * VOLTAGE_SCALE + 0.1); + } else { + theValue = from_string(theParameter); + } + } +} + CModel::CModel(string theParameterString) { // parameter string example // NMOS nch Vth=0.500 Vgs=0.3 Vds=0.5 Vbs=0.4 condition=(L<0.4u w>=1.2u) @@ -295,6 +319,7 @@ void CModelListMap::AddModel(string theParameterString) { } CModel * CModelListMap::FindModel(text_t theCellName, text_t theParameterText, CTextResistanceMap& theParameterResistanceMap, ostream& theLogFile) { + // FindModel: Set the model type based on theParameterText. Also adds entry to theParameterResistanceMap. string myParameterString = trim_(string(theParameterText)); string myModelKey = myParameterString.substr(0, myParameterString.find(" ", 2)); try { @@ -307,6 +332,7 @@ CModel * CModelListMap::FindModel(text_t theCellName, text_t theParameterText, C for (CModelList::iterator model_pit = this->at(myModelKey).begin(); model_pit != myLastModel; model_pit++) { if ( model_pit->ParameterMatch(myParameterMap, theCellName) ) { switch (model_pit->type) { + // TODO: do not recalculate if already exists case NMOS: case PMOS: case LDDN: case LDDP: { theParameterResistanceMap[theParameterText] = myParameterMap.CalculateResistance(model_pit->resistanceDefinition); if ( theParameterResistanceMap[theParameterText] == MAX_RESISTANCE ) { @@ -332,6 +358,19 @@ CModel * CModelListMap::FindModel(text_t theCellName, text_t theParameterText, C } } +CModelList * CModelListMap::FindModelList(string theModelName) { + // FindModelList: Return a pointer to the first model list for theModelName + // + // Warning: is 2 different types of models have the same name, only returns the first. + for (auto mapPair_pit = begin(); mapPair_pit != end(); mapPair_pit++) { + if ( mapPair_pit->first.substr(2) == theModelName ) { + return &mapPair_pit->second; + + } + } + return NULL; +} + void CModelListMap::Print(ostream & theLogFile, string theIndentation) { string myIndentation = theIndentation + " "; theLogFile << endl << theIndentation << "ModelList> filename " << filename << endl; diff --git a/src/CModel.hh b/src/CModel.hh index 39f0f2b..4f30814 100755 --- a/src/CModel.hh +++ b/src/CModel.hh @@ -34,6 +34,29 @@ class CPowerPtrMap; #include "CParameterMap.hh" #include +class CModelCheck { +public: + string check = ""; + string parameter = ""; + bool isVoltage = false; + string minInclusiveText = ""; + string minExclusiveText = ""; + string maxInclusiveText = ""; + string maxExclusiveText = ""; + float minInclusiveValue = 0.; + float minExclusiveValue = 0.; + float maxInclusiveValue = 0.; + float maxExclusiveValue = 0.; + voltage_t minInclusiveVoltage = 0.; + voltage_t minExclusiveVoltage = 0.; + voltage_t maxInclusiveVoltage = 0.; + voltage_t maxExclusiveVoltage = 0.; + + CModelCheck(string theCheck, string theParameter, string theInclusiveMin, string theExclusiveMin, string theInclusiveMax, string theExclusiveMax ); + void SetValue(string theParameter, voltage_t &theVoltage, float &theValue); + +}; + class CModel { public: string name; @@ -70,6 +93,8 @@ public: string definition; + forward_list checkList; + CModel(string theParameterString); void Clear(); size_t ModelCount(); @@ -100,6 +125,7 @@ public: void Clear(); void AddModel(string theParameterString); CModel * FindModel(text_t theCellName, text_t theParameterText, CTextResistanceMap & theParameterResistanceMap, ostream& theLogFile); + CModelList * FindModelList(string theModelName); void Print(ostream & theLogFile, string theIndentation = ""); void DebugPrint(string theIndentation = ""); returnCode_t SetVoltageTolerances(teestream & theReportFile, CPowerPtrMap & thePowerMacroPtrMap); diff --git a/src/Cvc.hh b/src/Cvc.hh index 9f188b4..6247544 100755 --- a/src/Cvc.hh +++ b/src/Cvc.hh @@ -24,7 +24,7 @@ #ifndef CVC_H_ #define CVC_H_ -#define CVC_VERSION "1.0.0" +#define CVC_VERSION "1.1.0" extern bool gDebug_cvc; extern bool gSetup_cvc; diff --git a/src/CvcTypes.hh b/src/CvcTypes.hh index 9d1eb84..3bffd69 100755 --- a/src/CvcTypes.hh +++ b/src/CvcTypes.hh @@ -141,7 +141,7 @@ enum propagation_t { POWER_NETS_ONLY = 1, ALL_NETS_NO_FUSE, ALL_NETS_AND_FUSE }; enum cvcError_t { LEAK = 0, HIZ_INPUT, FORWARD_DIODE, NMOS_SOURCE_BULK, NMOS_GATE_SOURCE, NMOS_POSSIBLE_LEAK, PMOS_SOURCE_BULK, PMOS_GATE_SOURCE, PMOS_POSSIBLE_LEAK, OVERVOLTAGE_VBG, OVERVOLTAGE_VBS, OVERVOLTAGE_VDS, - OVERVOLTAGE_VGS, EXPECTED_VOLTAGE, LDD_SOURCE, MIN_VOLTAGE_CONFLICT, MAX_VOLTAGE_CONFLICT, FUSE_ERROR, ERROR_TYPE_COUNT }; + OVERVOLTAGE_VGS, MODEL_CHECK, EXPECTED_VOLTAGE, LDD_SOURCE, MIN_VOLTAGE_CONFLICT, MAX_VOLTAGE_CONFLICT, FUSE_ERROR, ERROR_TYPE_COUNT }; // Flag Constants #define PRINT_CIRCUIT_ON true