From e73b0aadf663ad12e30091c22985200d4dbce869 Mon Sep 17 00:00:00 2001 From: "D. Mitch Bailey" Date: Fri, 18 Sep 2020 10:49:52 +0900 Subject: [PATCH] Changes for 0.17.34a CVC: Recognize inverters with inputs tied to power CVC: Added opposite_logic net check --- src/CCvcDb.cc | 32 +++++++-- src/CCvcDb.hh | 11 +++- src/CCvcDb_error.cc | 72 +++++++++++--------- src/CCvcDb_init.cc | 11 ++-- src/CCvcDb_utility.cc | 150 ++++++++++++++++++++++++++++++++++++------ src/Cvc.hh | 2 +- 6 files changed, 211 insertions(+), 67 deletions(-) diff --git a/src/CCvcDb.cc b/src/CCvcDb.cc index d8663fa..c284504 100755 --- a/src/CCvcDb.cc +++ b/src/CCvcDb.cc @@ -2158,14 +2158,34 @@ void CCvcDb::SetTrivialMinMaxPower() { myNmos = UNKNOWN_DEVICE; myPmos = UNKNOWN_DEVICE; for ( deviceId_t device_it = firstDrain_v[net_it]; device_it != UNKNOWN_DEVICE; device_it = nextDrain_v[device_it] ) { - if ( sourceNet_v[device_it] == gateNet_v[device_it] ) continue; // skip mos diodes - if ( IsNmos_(deviceType_v[device_it]) ) myNmos = device_it; - if ( IsPmos_(deviceType_v[device_it]) ) myPmos = device_it; + //if ( sourceNet_v[device_it] == gateNet_v[device_it] ) continue; // skip mos diodes (need this for tied inverters) + if ( sourceNet_v[device_it] == drainNet_v[device_it] ) continue; // skip mos capacitors + + if ( IsNmos_(deviceType_v[device_it]) ) { + if ( myNmos == UNKNOWN_DEVICE || sourceNet_v[device_it] != gateNet_v[device_it] ) { // only use tied input if nothing else is available + myNmos = device_it; + } + } + if ( IsPmos_(deviceType_v[device_it]) ) { + if ( myPmos == UNKNOWN_DEVICE || sourceNet_v[device_it] != gateNet_v[device_it] ) { // only use tied input if nothing else is available + myPmos = device_it; + } + } } for ( deviceId_t device_it = firstSource_v[net_it]; device_it != UNKNOWN_DEVICE; device_it = nextSource_v[device_it] ) { - if ( drainNet_v[device_it] == gateNet_v[device_it] ) continue; // skip mos diodes - if ( IsNmos_(deviceType_v[device_it]) ) myNmos = device_it; - if ( IsPmos_(deviceType_v[device_it]) ) myPmos = device_it; + //if ( drainNet_v[device_it] == gateNet_v[device_it] ) continue; // skip mos diodes (need this for tied inverters) + if ( sourceNet_v[device_it] == drainNet_v[device_it] ) continue; // skip mos capacitors + + if ( IsNmos_(deviceType_v[device_it]) ) { + if ( myNmos == UNKNOWN_DEVICE || drainNet_v[device_it] != gateNet_v[device_it] ) { // only use tied input if nothing else is available + myNmos = device_it; + } + } + if ( IsPmos_(deviceType_v[device_it]) ) { + if ( myPmos == UNKNOWN_DEVICE || drainNet_v[device_it] != gateNet_v[device_it] ) { // only use tied input if nothing else is available + myPmos = device_it; + } + } } if ( myNmos == UNKNOWN_DEVICE ) continue; if ( myPmos == UNKNOWN_DEVICE ) continue; diff --git a/src/CCvcDb.hh b/src/CCvcDb.hh index b893a3e..540e6a0 100755 --- a/src/CCvcDb.hh +++ b/src/CCvcDb.hh @@ -272,7 +272,7 @@ public: void CheckExpectedValues(); void FindLDDErrors(); void CheckInverterIO(modelType_t theType); - void CheckOppositeLogic(); + void CheckOppositeLogic(modelType_t theType); // // void ReportBadLddConnection(CEventQueue & theEventQueue, deviceId_t theDeviceId); @@ -400,9 +400,14 @@ public: void SetDiodeConnections(pair diode_pit, CFullConnection & myConnections, CFullConnection & myDiodeConnections); int CalculateMFactor(instanceId_t theInstanceId); deviceId_t GetAttachedDevice(netId_t theNetId, modelType_t theType, terminal_t theTerminal); - deviceId_t FindInverterDevice(netId_t theInputNet, netId_t theOutputNet, modelType_t theType); + deviceId_t FindInverterDevice(netId_t theInputNet, netId_t theOutputNet, modelType_t theType); + returnCode_t FindUniqueMosInputs(netId_t theOutputNet, netId_t theGroundNet, netId_t thePowerNet, + CDeviceIdVector &theFirst_v, CDeviceIdVector &theNext_v, CNetIdVector &theSourceNet_v, CNetIdVector &theDrainNet_v, + netId_t &theNmosInput, netId_t &thePmosInput); deviceId_t FindInverterInput(netId_t theOutputNet); - + bool IsOnGate(deviceId_t theDevice, CPower * thePower_p); + netId_t OppositeNet(deviceId_t theDevice, netId_t theNet); + deviceId_t GetNextInSeries(deviceId_t theDevice, netId_t theNet); // CCvcDb-print void SetOutputFiles(string theReportFile); diff --git a/src/CCvcDb_error.cc b/src/CCvcDb_error.cc index 399f9b1..d90d0b9 100755 --- a/src/CCvcDb_error.cc +++ b/src/CCvcDb_error.cc @@ -592,6 +592,7 @@ void CCvcDb::FindNmosGateVsSourceErrors() { } } CheckInverterIO(NMOS); + CheckOppositeLogic(NMOS); cvcCircuitList.PrintAndResetCircuitErrors(this, cvcParameters.cvcCircuitErrorLimit, logFile, errorFile, "! Checking nmos gate vs source errors: "); } @@ -666,6 +667,7 @@ void CCvcDb::FindPmosGateVsSourceErrors() { } } CheckInverterIO(PMOS); + CheckOppositeLogic(PMOS); cvcCircuitList.PrintAndResetCircuitErrors(this, cvcParameters.cvcCircuitErrorLimit, logFile, errorFile, "! Checking pmos gate vs source errors: "); } @@ -1233,7 +1235,6 @@ void CCvcDb::FindFloatingInputErrors() { } } } - CheckOppositeLogic(); cvcCircuitList.PrintAndResetCircuitErrors(this, cvcParameters.cvcCircuitErrorLimit, logFile, errorFile, "! Checking mos floating input errors:"); // errorFile << "! Finished" << endl << endl; } @@ -1462,11 +1463,12 @@ void CCvcDb::CheckInverterIO(modelType_t theType) { netId_t myInverterInput = FindInverterInput(*net_pit); if ( myInverterInput == UNKNOWN_NET ) { myInverterInput = inverterNet_v[*net_pit]; - reportFile << "INFO: Couldn't calculate inverter input for " << NetName(myInverterInput, true) << endl; + reportFile << "INFO: Couldn't calculate inverter input for " << NetName(*net_pit, true) << endl; } if (myInverterInput == UNKNOWN_NET) { - reportFile << "Warning: expected inverter input at " << NetName(myInverterInput, true) << endl; - continue; + reportFile << "Warning: expected inverter input at " << NetName(*net_pit, true) << endl; + continue; + } myMinInput(minNet_v, myInverterInput); myMaxInput(maxNet_v, myInverterInput); @@ -1496,51 +1498,56 @@ void CCvcDb::CheckInverterIO(modelType_t theType) { } } -void CCvcDb::CheckOppositeLogic() { +void CCvcDb::CheckOppositeLogic(modelType_t theType) { for ( auto check_pit = oppositeLogicList.begin(); check_pit != oppositeLogicList.end(); check_pit++ ) { debugFile << "DEBUG: opposite logic check " << get<0>(*check_pit) << " & " << get<1>(*check_pit) << endl; forward_list * myNetIdList = FindNetIds(get<0>(*check_pit)); forward_list * myOppositeNetIdList = FindNetIds(get<1>(*check_pit)); for ( auto net_pit = myNetIdList->begin(), opposite_pit = myOppositeNetIdList->begin(); net_pit != myNetIdList->end(); net_pit++, opposite_pit++ ) { - CPower * myFirstPower_p = netVoltagePtr_v[*net_pit].full; - CPower * mySecondPower_p = netVoltagePtr_v[*opposite_pit].full; + CPower * myFirstPower_p = netVoltagePtr_v[GetEquivalentNet(*net_pit)].full; + CPower * mySecondPower_p = netVoltagePtr_v[GetEquivalentNet(*opposite_pit)].full; if ( myFirstPower_p && mySecondPower_p && IsPower_(myFirstPower_p) && IsPower_(mySecondPower_p) - && myFirstPower_p->simVoltage != mySecondPower_p->simVoltage ) continue; // ignore direct connections to different power + && myFirstPower_p->simVoltage != mySecondPower_p->simVoltage ) continue; // ignore direct connections to different power unordered_set myInvertedNets; unordered_set mySameLogicNets; - netId_t inverter_it = *net_pit; + netId_t net_it = GetEquivalentNet(*net_pit); // make sets of same logic nets and opposite logic nets for first nets - mySameLogicNets.insert(inverter_it); - while ( inverterNet_v[inverter_it] != UNKNOWN_NET && myInvertedNets.count(inverterNet_v[inverter_it]) == 0 ) { - assert(mySameLogicNets.count(inverterNet_v[inverter_it]) == 0); // oscillators - - myInvertedNets.insert(inverterNet_v[inverter_it]); - inverter_it = inverterNet_v[inverter_it]; - if ( inverterNet_v[inverter_it] != UNKNOWN_NET ) { - mySameLogicNets.insert(inverter_it); - inverter_it = inverterNet_v[inverter_it]; - } + bool myInverted = false; + logFile << "Checking " << NetName(net_it, true) << endl; + while ( net_it != UNKNOWN_NET && mySameLogicNets.count(net_it) == 0 ) { + if ( myInverted ) { + myInvertedNets.insert(net_it); + assert(myInvertedNets.count(inverterNet_v[net_it]) == 0); // oscillators + + } else { + mySameLogicNets.insert(net_it); + assert(mySameLogicNets.count(inverterNet_v[net_it]) == 0); // oscillators + + } + myInverted = ! myInverted; + net_it = inverterNet_v[net_it]; } // check second net against first net to find opposite logic - inverter_it = *opposite_pit; - while ( inverterNet_v[inverter_it] != UNKNOWN_NET && myInvertedNets.count(inverter_it) == 0 ) { - if ( mySameLogicNets.count(inverterNet_v[inverter_it]) > 0 ) { // second net is later in inverter chain - myInvertedNets.insert(inverter_it); - } else { - inverter_it = inverterNet_v[inverter_it]; - if ( inverterNet_v[inverter_it] != UNKNOWN_NET ) { - inverter_it = inverterNet_v[inverter_it]; - } - } + myInverted = true; + net_it = GetEquivalentNet(*opposite_pit); + while ( net_it != UNKNOWN_NET + && ( (myInverted && myInvertedNets.count(net_it) == 0) + || (! myInverted && mySameLogicNets.count(net_it) == 0) ) ) { + net_it = inverterNet_v[net_it]; + myInverted = ! myInverted; } - if ( myInvertedNets.count(inverter_it) > 0 ) continue; // nets are opposite + if ( net_it != UNKNOWN_NET ) continue; // nets are opposite - netId_t myErrorNet = (myFirstPower_p && IsPower_(myFirstPower_p)) ? *opposite_pit : *net_pit; + netId_t myErrorNet = (myFirstPower_p && IsPower_(myFirstPower_p)) ? GetEquivalentNet(*opposite_pit) : GetEquivalentNet(*net_pit); int myErrorCount = 0; for ( auto device_it = firstGate_v[myErrorNet]; device_it != UNKNOWN_DEVICE; device_it = nextGate_v[device_it]) { if ( sourceNet_v[device_it] == drainNet_v[device_it] ) continue; // ignore inactive devices + if ( theType == PMOS && ! IsPmos_(deviceType_v[device_it]) ) continue; // ignore wrong types + + if ( theType == NMOS && ! IsNmos_(deviceType_v[device_it]) ) continue; // ignore wrong types + myErrorCount++; if ( IncrementDeviceError(device_it, HIZ_INPUT) < cvcParameters.cvcCircuitErrorLimit || cvcParameters.cvcCircuitErrorLimit == 0 ) { CFullConnection myFullConnections; @@ -1551,7 +1558,8 @@ void CCvcDb::CheckOppositeLogic() { } } if ( myErrorCount == 0 ) { - reportFile << "Warning: No errors printed for opposite logic check at " << get<0>(*check_pit) << " & " << get<1>(*check_pit) << endl; + reportFile << "Warning: No errors printed for opposite logic check at " << get<0>(*check_pit) << " & " << get<1>(*check_pit); + reportFile << " for net " << NetName(*net_pit, true) << endl; } } } diff --git a/src/CCvcDb_init.cc b/src/CCvcDb_init.cc index cd6c4e5..dabdc6c 100755 --- a/src/CCvcDb_init.cc +++ b/src/CCvcDb_init.cc @@ -1765,8 +1765,9 @@ void CCvcDb::LoadCellChecksums() { void CCvcDb::LoadNetChecks() { /// Load net checks from file. /// - /// Currently supports "inverter_input=output": check to verify inverter output ground/power is same as input ground/power - /// Future support for "opposite_logic": verify that 2 nets are logically opposite + /// 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); @@ -1782,20 +1783,20 @@ void CCvcDb::LoadNetChecks() { size_t myStringBegin = myInput.find_first_not_of(" \t"); size_t myStringEnd = myInput.find_first_of(" \t", myStringBegin); - string myNetName = myInput.substr(myStringBegin, myStringEnd); + 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); + 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); + 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; diff --git a/src/CCvcDb_utility.cc b/src/CCvcDb_utility.cc index 566ee5f..d1c18c4 100755 --- a/src/CCvcDb_utility.cc +++ b/src/CCvcDb_utility.cc @@ -1846,7 +1846,9 @@ deviceId_t CCvcDb::GetAttachedDevice(netId_t theNetId, modelType_t theType, term } deviceId_t CCvcDb::FindInverterDevice(netId_t theInputNet, netId_t theOutputNet, modelType_t theType) { - /// Return the first device of theType with input theInputNet and output theOutputNet + /// Return the first device of theType with input theInputNet and output theOutputNet + /// + /// Note: Will not find any device if inverter contains both nmos/pmos clamps unordered_set myDeviceList; deviceId_t device_it = firstSource_v[theOutputNet]; while ( device_it != UNKNOWN_DEVICE ) { @@ -1877,29 +1879,137 @@ deviceId_t CCvcDb::FindInverterDevice(netId_t theInputNet, netId_t theOutputNet, device_it = nextGate_v[device_it]; } return(UNKNOWN_DEVICE); +} + +returnCode_t CCvcDb::FindUniqueMosInputs(netId_t theOutputNet, netId_t theGroundNet, netId_t thePowerNet, + CDeviceIdVector &theFirst_v, CDeviceIdVector &theNext_v, CNetIdVector &theSourceNet_v, CNetIdVector &theDrainNet_v, + netId_t &theNmosInput, netId_t &thePmosInput) { + /// Return the mos gates for devices with source connected to theOutputNet + /// + /// Modifies theNmosInput, thePmosInput + CPower * myGround_p = netVoltagePtr_v[theGroundNet].full; + CPower * myPower_p = netVoltagePtr_v[thePowerNet].full; + for ( deviceId_t device_it = theFirst_v[theOutputNet]; device_it != UNKNOWN_DEVICE; device_it = theNext_v[device_it] ) { + if ( theSourceNet_v[device_it] == theDrainNet_v[device_it] ) continue; // ignore inactive devices + + if ( IsNmos_(deviceType_v[device_it]) ) { + if ( theDrainNet_v[device_it] == theGroundNet ) { // expected ground + if ( theNmosInput == UNKNOWN_NET ) { + theNmosInput = gateNet_v[device_it]; + } else if ( theNmosInput != gateNet_v[device_it] ) return(FAIL); // multiple NMOS inputs yield unknown result + + } else if ( IsOnGate(device_it, myGround_p) ) { // series gate on + deviceId_t myNextNmos = GetNextInSeries(device_it, theDrainNet_v[device_it]); + if ( myNextNmos == UNKNOWN_DEVICE ) return(FAIL); // not series + + if ( OppositeNet(myNextNmos, theDrainNet_v[device_it]) == theGroundNet ) { + if ( theNmosInput == UNKNOWN_NET ) { + theNmosInput = gateNet_v[myNextNmos]; + } else if ( theNmosInput != gateNet_v[myNextNmos] ) return(FAIL); // multiple NMOS inputs yield unknown result + + } else return(FAIL); // more than 2 in series + + } else return(FAIL); // no connection to ground detected + + } + if ( IsPmos_(deviceType_v[device_it]) ) { + if ( theDrainNet_v[device_it] == thePowerNet ) { // expected power + if ( thePmosInput == UNKNOWN_NET ) { + thePmosInput = gateNet_v[device_it]; + } else if ( thePmosInput != gateNet_v[device_it] ) return(FAIL); // multiple PMOS inputs yield unknown result + + } else if ( IsOnGate(device_it, myPower_p) ) { // series gate on + deviceId_t myNextPmos = GetNextInSeries(device_it, theDrainNet_v[device_it]); + if ( myNextPmos == UNKNOWN_DEVICE ) return(FAIL); // not series + + if ( OppositeNet(myNextPmos, theDrainNet_v[device_it]) == thePowerNet ) { + if ( thePmosInput == UNKNOWN_NET ) { + thePmosInput = gateNet_v[myNextPmos]; + } else if ( thePmosInput != gateNet_v[myNextPmos] ) return(FAIL); // multiple PMOS inputs yield unknown result + + } else return(FAIL); // more than 2 in series + + } else return(FAIL); // no connection to power detected + + } + } + return(OK); } netId_t CCvcDb::FindInverterInput(netId_t theOutputNet) { /// Find the input of inverter with output theOutputNet - unordered_set myInputList; - deviceId_t device_it = firstSource_v[theOutputNet]; - while ( device_it != UNKNOWN_DEVICE ) { - if ( sourceNet_v[device_it] != drainNet_v[device_it] ) { - myInputList.insert(gateNet_v[device_it]); - } - device_it = nextSource_v[device_it]; - } - device_it = firstDrain_v[theOutputNet]; - while ( device_it != UNKNOWN_DEVICE ) { - if ( sourceNet_v[device_it] != drainNet_v[device_it] ) { - myInputList.insert(gateNet_v[device_it]); - } - device_it = nextDrain_v[device_it]; - } - if ( myInputList.size() == 1 ) { - return(*(myInputList.begin())); - } else { + CVirtualNet myMinOutput; + CVirtualNet myMaxOutput; + myMinOutput(minNet_v, theOutputNet); + myMaxOutput(maxNet_v, theOutputNet); + netId_t myGroundNet = myMinOutput.finalNetId; + netId_t myPowerNet = myMaxOutput.finalNetId; + CPower * myGround_p = netVoltagePtr_v[myGroundNet].full; + CPower * myPower_p = netVoltagePtr_v[myPowerNet].full; + netId_t myNmosInput = UNKNOWN_NET; + netId_t myPmosInput = UNKNOWN_NET; + if ( ! IsPower_(myGround_p) || ! IsPower_(myPower_p) ) { + logFile << "DEBUG: missing power for inverter at " << NetName(theOutputNet, true) << endl; return(UNKNOWN_NET); - } + + } + returnCode_t mySourceCheck = FindUniqueMosInputs(theOutputNet, myGroundNet, myPowerNet, firstSource_v, nextSource_v, sourceNet_v, drainNet_v, + myNmosInput, myPmosInput); + returnCode_t myDrainCheck = FindUniqueMosInputs(theOutputNet, myGroundNet, myPowerNet, firstDrain_v, nextDrain_v, drainNet_v, sourceNet_v, + myNmosInput, myPmosInput); + return( ( mySourceCheck == OK && myDrainCheck == OK + && myNmosInput != UNKNOWN_NET && myNmosInput == myPmosInput ) ? myNmosInput : UNKNOWN_NET); +} + +bool CCvcDb::IsOnGate(deviceId_t theDevice, CPower * thePower_p) { + // Return true if gate is always on + CPower * myGatePower_p = netVoltagePtr_v[gateNet_v[theDevice]].full; + if ( ! IsPower_(myGatePower_p) ) return false; // gate is not power + + if ( IsNmos_(deviceType_v[theDevice]) ) return( myGatePower_p->minVoltage > thePower_p->minVoltage ); + + if ( IsPmos_(deviceType_v[theDevice]) ) return( myGatePower_p->maxVoltage < thePower_p->maxVoltage ); + + assert(false); // error if called with device that is not NMOS or PMOS +} + +netId_t CCvcDb::OppositeNet(deviceId_t theDevice, netId_t theNet) { + // return the opposite net of a device + assert((sourceNet_v[theDevice] == theNet) || (drainNet_v[theDevice] == theNet)); + + return((sourceNet_v[theDevice] == theNet) ? drainNet_v[theDevice] : sourceNet_v[theDevice]); } +deviceId_t CCvcDb::GetNextInSeries(deviceId_t theDevice, netId_t theNet) { + // Return the next device in series + deviceId_t myNextDevice = UNKNOWN_DEVICE; + for ( deviceId_t device_it = firstSource_v[theNet]; device_it != UNKNOWN_DEVICE; device_it = nextSource_v[device_it] ) { + if ( sourceNet_v[device_it] != drainNet_v[device_it] ) continue; // ignore inactive devices + + if ( device_it == theDevice ) continue; // looking for device connected to this one + + if ( myNextDevice != UNKNOWN_DEVICE ) return(UNKNOWN_DEVICE); // not in series, return error + + myNextDevice = device_it; + } + for ( deviceId_t device_it = firstDrain_v[theNet]; device_it != UNKNOWN_DEVICE; device_it = nextDrain_v[device_it] ) { + if ( sourceNet_v[device_it] != drainNet_v[device_it] ) continue; // ignore inactive devices + + if ( device_it == theDevice ) continue; // looking for device connected to this one + + if ( myNextDevice != UNKNOWN_DEVICE ) return(UNKNOWN_DEVICE); // not in series, return error + + myNextDevice = device_it; + } + if ( myNextDevice != UNKNOWN_DEVICE ) { + if ( deviceType_v[theDevice] != deviceType_v[myNextDevice] ) { // should be the same type + if ( IsNmos_(deviceType_v[theDevice]) && IsNmos_(deviceType_v[myNextDevice]) ) { // type mismatch ok if both nmos + ; + } else if ( IsPmos_(deviceType_v[theDevice]) && IsPmos_(deviceType_v[myNextDevice]) ) { // type mismatch ok if both pmos + ; + } else return(UNKNOWN_DEVICE); + + } + } + return(myNextDevice); +} diff --git a/src/Cvc.hh b/src/Cvc.hh index 7ec3aa6..4e9d4da 100755 --- a/src/Cvc.hh +++ b/src/Cvc.hh @@ -24,7 +24,7 @@ #ifndef CVC_H_ #define CVC_H_ -#define CVC_VERSION "0.17.33" +#define CVC_VERSION "0.17.34" extern bool gDebug_cvc; extern bool gSetup_cvc;