Skip to content

Commit

Permalink
Changes for version 0.17.32
Browse files Browse the repository at this point in the history
CVC: Added interactive function to dump possible level shifters
CVC: Added capability to read file of net checks (currently only inverter input = output)
CVC: Combined MapDevice functions to avoid redundant code
  • Loading branch information
d-m-bailey committed Aug 13, 2020
1 parent 769c4db commit c65c5e0
Show file tree
Hide file tree
Showing 10 changed files with 386 additions and 13 deletions.
2 changes: 1 addition & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# Process this file with autoconf to produce a configure script.

AC_PREREQ([2.69])
AC_INIT(CVC, [0.17.31], [cvc@shuharisystem.com])
AC_INIT(CVC, [0.17.32], [cvc@shuharisystem.com])
AC_CONFIG_SRCDIR(src)
AC_CONFIG_HEADERS([config.h])
AC_USE_SYSTEM_EXTENSIONS
Expand Down
15 changes: 12 additions & 3 deletions src/CCvcDb.hh
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* CCvcDb.hh
*
* Copyright 2014-2018 D. Mitch Bailey cvc at shuharisystem dot com
* Copyright 2014-2020 D. Mitch Bailey cvc at shuharisystem dot com
*
* This file is part of cvc.
*
Expand Down Expand Up @@ -66,7 +66,7 @@ public:

CInstancePtrVector instancePtr_v;

// parent instance. offset from first in instance to find name, etc.
// parent instance. Use offset from first in instance to find name, etc.
// [*] = instance
CInstanceIdVector netParent_v;
// CInstanceIdVector subcircuitParent;
Expand Down Expand Up @@ -171,9 +171,11 @@ public:

unordered_map<string, deviceId_t> cellErrorCountMap;

forward_list<string> inverterInputOutputCheckList; // list of nets to check for matched input/output

ogzstream errorFile;
ofstream logFile;
teestream reportFile;
teestream reportFile; // simultaneous output to stdout and logFile
ogzstream debugFile;

string lockFile;
Expand Down Expand Up @@ -239,6 +241,7 @@ public:
void PrintNetSuggestions();
returnCode_t LoadCellErrorLimits();
void LoadCellChecksums();
void LoadNetChecks();

// error
void PrintFuseError(netId_t theTargetNetId, CConnection & theConnections);
Expand Down Expand Up @@ -266,6 +269,7 @@ public:
void FindFloatingInputErrors();
void CheckExpectedValues();
void FindLDDErrors();
void CheckNets(modelType_t theType);

//
// void ReportBadLddConnection(CEventQueue & theEventQueue, deviceId_t theDeviceId);
Expand Down Expand Up @@ -392,6 +396,10 @@ public:
bool IsOneConnectionNet(netId_t theNetId);
void SetDiodeConnections(pair<int, int> 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 FindInverterInput(netId_t theOutputNet);


// CCvcDb-print
void SetOutputFiles(string theReportFile);
Expand Down Expand Up @@ -471,6 +479,7 @@ public:
void DumpFuses(string theFileName);
void DumpAnalogNets(string theFileName, bool thePrintCircuitFlag);
void DumpUnknownLogicalNets(string theFileName, bool thePrintCircuitFlag);
void DumpLevelShifters(string theFileName, bool thePrintCircuitFlag);
returnCode_t CheckFuses();
void CreateDebugCvcrcFile(ofstream & theOutputFile, instanceId_t theInstanceId, string theMode, int theCurrentStage);
void PrintInstancePowerFile(instanceId_t theInstanceId, string thePowerFileName, int theCurrentStage);
Expand Down
51 changes: 49 additions & 2 deletions src/CCvcDb_error.cc
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* CCvcDb_error.cc
*
* Copyright 2014-2018 D. Mitch Bailey cvc at shuharisystem dot com
* Copyright 2014-2020 D. Mitch Bailey cvc at shuharisystem dot com
*
* This file is part of cvc.
*
Expand Down Expand Up @@ -591,6 +591,7 @@ void CCvcDb::FindNmosGateVsSourceErrors() {
errorFile << endl;
}
}
CheckNets(NMOS);
cvcCircuitList.PrintAndResetCircuitErrors(this, cvcParameters.cvcCircuitErrorLimit, logFile, errorFile, "! Checking nmos gate vs source errors: ");
}

Expand Down Expand Up @@ -664,6 +665,7 @@ void CCvcDb::FindPmosGateVsSourceErrors() {
errorFile << endl;
}
}
CheckNets(PMOS);
cvcCircuitList.PrintAndResetCircuitErrors(this, cvcParameters.cvcCircuitErrorLimit, logFile, errorFile, "! Checking pmos gate vs source errors: ");
}

Expand Down Expand Up @@ -1446,4 +1448,49 @@ void CCvcDb::FindLDDErrors() {
}
*/


void CCvcDb::CheckNets(modelType_t theType) {
// Checks nets loaded from cvcNetCheckFile
for ( auto check_pit = inverterInputOutputCheckList.begin(); check_pit != inverterInputOutputCheckList.end(); check_pit++ ) {
debugFile << "DEBUG: inverter input output check " << *check_pit << endl;
set<netId_t> * myNetIdList = FindNetIds(*check_pit);
CVirtualNet myMinInput;
CVirtualNet myMaxInput;
CVirtualNet myMinOutput;
CVirtualNet myMaxOutput;
for ( auto net_pit = myNetIdList->begin(); net_pit != myNetIdList->end(); net_pit++ ) {
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;
}
if (myInverterInput == UNKNOWN_NET) {
reportFile << "Warning: expected inverter input at " << NetName(myInverterInput, true) << endl;
continue;
}
myMinInput(minNet_v, myInverterInput);
myMaxInput(maxNet_v, myInverterInput);
myMinOutput(minNet_v, *net_pit);
myMaxOutput(maxNet_v, *net_pit);
if ( myMinInput.finalNetId == myMaxInput.finalNetId
&& ( myMinInput.finalNetId == myMinOutput.finalNetId
|| myMaxInput.finalNetId == myMaxOutput.finalNetId ) ) continue; // input is tied to matching power.

if ( ( myMinInput.finalNetId != myMinOutput.finalNetId && theType == NMOS )
|| ( myMaxInput.finalNetId != myMaxOutput.finalNetId && theType == PMOS ) ) {
deviceId_t myDevice = FindInverterDevice(myInverterInput, *net_pit, theType);
if ( myDevice == UNKNOWN_DEVICE ) {
reportFile << "Warning: could not find inverter device for " << NetName(*net_pit, true) << endl;
continue;

}
if ( IncrementDeviceError(myDevice, (theType == NMOS ? NMOS_GATE_SOURCE : PMOS_GATE_SOURCE)) < cvcParameters.cvcCircuitErrorLimit || cvcParameters.cvcCircuitErrorLimit == 0 ) {
CFullConnection myFullConnections;
MapDeviceNets(myDevice, myFullConnections);
errorFile << "* inverter input/output mismatch" << endl;
PrintDeviceWithAllConnections(deviceParent_v[myDevice], myFullConnections, errorFile);
errorFile << endl;
}
}
}
}
}
41 changes: 40 additions & 1 deletion src/CCvcDb_init.cc
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* CCvcDb_init.cc
*
* Copyright 2014-2018 D. Mitch Bailey cvc at shuharisystem dot com
* Copyright 2014-2020 D. Mitch Bailey cvc at shuharisystem dot com
*
* This file is part of cvc.
*
Expand Down Expand Up @@ -1687,3 +1687,42 @@ void CCvcDb::LoadCellChecksums() {
myCellChecksumFile.close();
}

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
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) ) {
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);
set<netId_t> * myNetIdList = FindNetIds(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);
if ( myOperation == "inverter_input=output" ) {
inverterInputOutputCheckList.push_front(myNetName);
} else if ( myOperation == "opposite_logic" ) {
; // not yet supported
} else {
reportFile << "ERROR: unknown check " << myInput << endl;
}
}
myNetCheckFile.close();
}

157 changes: 155 additions & 2 deletions src/CCvcDb_interactive.cc
Original file line number Diff line number Diff line change
Expand Up @@ -690,6 +690,7 @@ returnCode_t CCvcDb::InteractiveCvc(int theCurrentStage) {
cout << "dumpfuse<df> filename: dump fuse to filename" << endl;
cout << "dumpanalognets<dan> filename: dump analog nets to filename" << endl;
cout << "dumpunknownlogicalnets<duln> filename: dump unknown logical nets to filename" << endl;
cout << "dumplevelshifter<dls> filename: dump level shifters to filename" << endl;
cout << "traceinverter<ti> name: trace signal as inverter output for name" << endl;
cout << "findsubcircuit<fs> subcircuit: list all instances of subcircuit or if regex, subcircuits that match" << endl;
cout << "findnet<fn> net: list all nets that match in lower subcircuits." << endl;
Expand Down Expand Up @@ -911,6 +912,16 @@ returnCode_t CCvcDb::InteractiveCvc(int theCurrentStage) {
} else {
reportFile << "ERROR: no unknown logical net file name" << endl;
}
} else if ( myCommand == "dumplevelshifters" || myCommand == "dls" ) {
if ( myInputStream >> myFileName ) {
if ( theCurrentStage >= STAGE_FIRST_MINMAX ) {
DumpLevelShifters(myFileName, myPrintSubcircuitNameFlag);
} else {
reportFile << "ERROR: Can only dump level shifters after first min/max stage" << endl;
}
} else {
reportFile << "ERROR: no level shifter file name" << endl;
}
} else if ( myCommand == "togglename" || myCommand == "n" ) {
myPrintSubcircuitNameFlag = ! myPrintSubcircuitNameFlag;
reportFile << "Printing subcircuit name option is now " << ((myPrintSubcircuitNameFlag) ? "on" : "off") << endl;
Expand Down Expand Up @@ -1194,12 +1205,15 @@ void CCvcDb::DumpUnknownLogicalNets(string theFileName, bool thePrintCircuitFlag
for ( netId_t net_it = 0; net_it < netCount; net_it++ ) {
// cout << "DEBUG: net " << net_it << endl;
if ( ! myIsLogicalNet_v[net_it] ) continue; // skip shorted, defined, and analog nets

// cout << "logic - clear" << endl;
if ( simNet_v[net_it].finalNetId != net_it ) continue; // skip known values

// cout << "unknown - clear" << endl;
if ( inverterNet_v[net_it] != UNKNOWN_NET
&& inverterNet_v[net_it] >= topCircuit_p->portCount
&& ! netStatus_v[inverterNet_v[net_it]][ANALOG] ) continue; // skip inverter output unless inverter input is chip input or analog signal
&& inverterNet_v[net_it] >= topCircuit_p->portCount
&& ! netStatus_v[inverterNet_v[net_it]][ANALOG] ) continue; // skip inverter output unless inverter input is chip input or analog signal

// cout << "inverter - clear" << endl;
CDeviceCount myDeviceCount(net_it, this);
// cout << "pmos " << myDeviceCount.pmosCount << ": nmos " << myDeviceCount.nmosCount << endl;
Expand All @@ -1221,6 +1235,145 @@ void CCvcDb::DumpUnknownLogicalNets(string theFileName, bool thePrintCircuitFlag
myDumpFile.close();
}

void CCvcDb::DumpLevelShifters(string theFileName, bool thePrintCircuitFlag) {
/// Write a sampling (one per cell/power pair) of possible level shifters to theFileName
ofstream myDumpFile(theFileName);
CVirtualNet myMinNmosInputNet;
CVirtualNet myMinPmosInputNet;
CVirtualNet myMinOutputNet;
CVirtualNet myMaxNmosInputNet;
CVirtualNet myMaxPmosInputNet;
CVirtualNet myMaxOutputNet;
if ( myDumpFile.fail() ) {
reportFile << "ERROR: Could not open " << theFileName << endl;
return;
}
reportFile << "Dumping level shifters to " << theFileName << " ... "; cout.flush();
vector<bool> myIsLogicalNet_v;
myIsLogicalNet_v.resize(netCount, false);
size_t myLevelShifterCount = 0;
for ( netId_t net_it = 0; net_it < netCount; net_it++ ) {
if ( net_it != GetEquivalentNet(net_it) ) continue; // skip shorted nets
CPower * myPower_p = netVoltagePtr_v[net_it].full;
if ( myPower_p && ( myPower_p->simVoltage != UNKNOWN_VOLTAGE || myPower_p->type[POWER_BIT] ) ) continue; // skip defined sim voltages and power
myIsLogicalNet_v[net_it] = ! IsAnalogNet(net_it);
}
set<string> myLevelShifters;
debugFile << "DEBUG level shifters" << endl;
for ( netId_t net_it = 0; net_it < netCount; net_it++ ) {
if ( ! myIsLogicalNet_v[net_it] ) continue; // skip shorted, defined, and analog nets

CDeviceCount myDeviceCount(net_it, this);
if ( myDeviceCount.activePmosCount == 0 || myDeviceCount.activeNmosCount == 0 ) continue; // skip non logic output

myMinOutputNet(minNet_v, net_it);
myMaxOutputNet(maxNet_v, net_it);
if ( myMinOutputNet.finalNetId == UNKNOWN_NET
|| myMaxOutputNet.finalNetId == UNKNOWN_NET
|| myMinOutputNet.finalNetId == net_it
|| myMaxOutputNet.finalNetId == net_it
|| myMinOutputNet.finalNetId == myMaxOutputNet.finalNetId ) continue; // invalid min/max

deviceId_t myNmos = GetAttachedDevice(net_it, NMOS, SD);
deviceId_t myPmos = GetAttachedDevice(net_it, PMOS, SD);
if ( myNmos == UNKNOWN_DEVICE || myPmos == UNKNOWN_DEVICE ) continue; // skip if missing NMOS or PMOS

if ( deviceParent_v[myNmos] != deviceParent_v[myPmos] ) continue; // skip if in different subcircuits

CInstance * myInstance_p = instancePtr_v[deviceParent_v[myNmos]];
CCircuit * myMaster_p = myInstance_p->master_p;
netId_t myNmosGate = GetEquivalentNet(gateNet_v[myNmos]);
netId_t myPmosGate = GetEquivalentNet(gateNet_v[myPmos]);
myMinNmosInputNet(minNet_v, myNmosGate);
myMinPmosInputNet(minNet_v, myPmosGate);
myMaxNmosInputNet(maxNet_v, myNmosGate);
myMaxPmosInputNet(maxNet_v, myPmosGate);
CPower * myNmosPower_p = netVoltagePtr_v[myNmosGate].full;
CPower * myPmosPower_p = netVoltagePtr_v[myPmosGate].full;
if ( ( myMinNmosInputNet.finalNetId == myMaxNmosInputNet.finalNetId // power
|| ( myMinNmosInputNet.finalNetId == myMinOutputNet.finalNetId
&& myMaxNmosInputNet.finalNetId == myMaxOutputNet.finalNetId ) )
&& ( myMinPmosInputNet.finalNetId == myMaxPmosInputNet.finalNetId // power
|| ( myMinPmosInputNet.finalNetId == myMinOutputNet.finalNetId
&& myMaxPmosInputNet.finalNetId == myMaxOutputNet.finalNetId )) ) continue; // input = output

if ( myMinNmosInputNet.finalNetId != myMinOutputNet.finalNetId
&& myMaxNmosInputNet.finalNetId != myMaxOutputNet.finalNetId
&& myMinPmosInputNet.finalNetId != myMinOutputNet.finalNetId
&& myMaxPmosInputNet.finalNetId != myMaxOutputNet.finalNetId ) continue; // one power must be equal

if ( inverterNet_v[myNmosGate] == UNKNOWN_NET && inverterNet_v[myPmosGate] == UNKNOWN_NET ) continue; // ignore signals not from inverters

netId_t myCheckNet;
deviceId_t myCheckDevice;
string myInputPower;
string myOutputPower = NetName(myMinOutputNet.finalNetId, thePrintCircuitFlag) + "/" + NetName(myMaxOutputNet.finalNetId, thePrintCircuitFlag);
if ( myMinNmosInputNet.finalNetId != myMaxNmosInputNet.finalNetId // ignore direct connections to power
&& ( myMinNmosInputNet.finalNetId != myMinOutputNet.finalNetId
|| myMaxNmosInputNet.finalNetId != myMaxOutputNet.finalNetId ) ) {
myCheckDevice = myNmos;
myCheckNet = myNmosGate;
myInputPower = NetName(myMinNmosInputNet.finalNetId, thePrintCircuitFlag) + "/" + NetName(myMaxNmosInputNet.finalNetId, thePrintCircuitFlag);
} else if ( myMinPmosInputNet.finalNetId != myMaxPmosInputNet.finalNetId // ignore direct connections to power
&& ( myMinPmosInputNet.finalNetId != myMinOutputNet.finalNetId
|| myMaxPmosInputNet.finalNetId != myMaxOutputNet.finalNetId ) ) {
myCheckDevice = myPmos;
myCheckNet = myPmosGate;
myInputPower = NetName(myMinPmosInputNet.finalNetId, thePrintCircuitFlag) + "/" + NetName(myMaxPmosInputNet.finalNetId, thePrintCircuitFlag);
} else if ( myMinNmosInputNet.finalNetId != myMaxNmosInputNet.finalNetId
|| myMinNmosInputNet.finalNetId != myMaxNmosInputNet.finalNetId ) { // tied to power
continue;

} else {
myDumpFile << "UNEXPECTED connection at " << DeviceName(myNmos, true);
myDumpFile << " N " << myNmosGate << " " <<myMinNmosInputNet.finalNetId << "/" << myMaxNmosInputNet.finalNetId;
myDumpFile << " P " << myPmosGate << " " <<myMinPmosInputNet.finalNetId << "/" << myMaxPmosInputNet.finalNetId;
myDumpFile << " out " << myMinOutputNet.finalNetId << "/" << myMaxOutputNet.finalNetId << endl;
continue;

}
if (inverterNet_v[myCheckNet] == UNKNOWN_NET) {
myDumpFile << "UNEXPECTED non-inverter at " << DeviceName(myCheckDevice, true) << endl;
continue;

}
deviceId_t myDeviceOffset = myCheckDevice - myInstance_p->firstDeviceId;
string myCircuitName = myMaster_p->name;
netId_t myNetOffset = myMaster_p->devicePtr_v[myDeviceOffset]->signalId_v[1];
debugFile << "DEBUG " << myCircuitName << " " << myDeviceOffset << " " << myNetOffset;
debugFile << " " << myInputPower << "->" << myOutputPower << endl;
string myKeyString = myCircuitName + to_string(myNetOffset) + myInputPower + myOutputPower;
if ( myLevelShifters.count(myKeyString) == 0 ) {
bool myIsInternal = false;
if ( deviceParent_v[myCheckDevice] == netParent_v[myCheckNet]
&& netParent_v[myCheckNet] == netParent_v[inverterNet_v[myCheckNet]] ) { // same subcircuit
CVirtualNet myMinInverterInput;
CVirtualNet myMaxInverterInput;
myMinInverterInput(minNet_v, inverterNet_v[myCheckNet]);
myMaxInverterInput(maxNet_v, inverterNet_v[myCheckNet]);
string myInverterPower = NetName(myMinInverterInput.finalNetId, thePrintCircuitFlag) + "/" + NetName(myMaxInverterInput.finalNetId, thePrintCircuitFlag);
myIsInternal = myInputPower == myInverterPower; // level shifter contained in subcircuit with same power
}
vector<text_t> mySignals_v;
mySignals_v.reserve(myMaster_p->localSignalIdMap.size());
for (auto signal_net_pair_pit = myMaster_p->localSignalIdMap.begin(); signal_net_pair_pit != myMaster_p->localSignalIdMap.end(); signal_net_pair_pit++) {
mySignals_v[signal_net_pair_pit->second] = signal_net_pair_pit->first;
}
string myLocalNetName = "*(" + myCircuitName + ")/" + string(mySignals_v[myNetOffset]);
myDumpFile << ( myIsInternal ? "#" : "" ); // level shifters that are internal to subcircuits do not need to be checked
myDumpFile << HierarchyName(deviceParent_v[myNmos], true) << "/" << string(mySignals_v[myNetOffset]);
myDumpFile << " " << (myCheckDevice == myNmos ? "N" : "P");
myDumpFile << " " << myInputPower << "->" << myOutputPower << endl;
myLevelShifters.insert(myKeyString);
if ( ! myIsInternal ) {
myLevelShifterCount++;
}
}
}
reportFile << "total level shifters written: " << myLevelShifterCount << endl;
myDumpFile.close();
}

returnCode_t CCvcDb::CheckFuses() {
if ( IsEmpty(cvcParameters.cvcFuseFilename) ) return (OK);
ifstream myFuseFile(cvcParameters.cvcFuseFilename);
Expand Down
1 change: 1 addition & 0 deletions src/CCvcDb_main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ void CCvcDb::VerifyCircuitForAllModes(int argc, const char * argv[]) {
LoadCellChecksums();
CountObjectsAndLinkSubcircuits();
AssignGlobalIDs();
LoadNetChecks();
PrintLargeCircuits();
reportFile << PrintProgress(&lastSnapshot, "DB ") << endl;
}
Expand Down
Loading

0 comments on commit c65c5e0

Please sign in to comment.