/* * CCircuit.cc * * Copyright 2014-2018 D. Mitch Bailey cvc at shuharisystem dot com * * This file is part of cvc. * * cvc is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * cvc is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with cvc. If not, see . * * You can download cvc from https://github.com/d-m-bailey/cvc.git */ #include "CCircuit.hh" class CCvcDb; #include "CDevice.hh" #include "CFixedText.hh" #include "CCvcDb.hh" text_t CCircuit::lastDeviceMap = NULL; CTextDeviceIdMap CCircuit::localDeviceIdMap; text_t CCircuit::lastSubcircuitMap = NULL; CTextDeviceIdMap CCircuit::localSubcircuitIdMap; void CCircuit::AddPortSignalIds(CTextList * thePortList_p) { for (CTextList::iterator text_pit = thePortList_p->begin(); text_pit != thePortList_p->end(); ++text_pit) { localSignalIdMap[*text_pit] = portCount++; } } void CCircuit::SetSignalIds(CTextList * signalList_p, CNetIdVector& signalId_v ) { netId_t mySignalId; signalId_v.reserve(signalList_p->size()); for (CTextList::iterator text_pit = signalList_p->begin(); text_pit != signalList_p->end(); ++text_pit) { try { mySignalId = localSignalIdMap.at(*text_pit); } catch (const out_of_range& oor_exception) { mySignalId = localSignalIdMap.size(); localSignalIdMap[*text_pit] = mySignalId; internalSignalList.push_back(*text_pit); } signalId_v.push_back(mySignalId); } } deviceId_t CCircuit::GetLocalDeviceId(text_t theName) { if ( CCircuit::lastDeviceMap != name ) { CCircuit::localDeviceIdMap.clear(); for ( deviceId_t device_it = 0; device_it < devicePtr_v.size(); device_it++ ) { CCircuit::localDeviceIdMap[devicePtr_v[device_it]->name] = device_it; } CCircuit::lastDeviceMap = name; } return (CCircuit::localDeviceIdMap.at(theName)); } deviceId_t CCircuit::GetLocalSubcircuitId(text_t theName) { if ( CCircuit::lastSubcircuitMap != name ) { CCircuit::localSubcircuitIdMap.clear(); for ( deviceId_t device_it = 0; device_it < subcircuitPtr_v.size(); device_it++ ) { CCircuit::localSubcircuitIdMap[subcircuitPtr_v[device_it]->name] = device_it; } CCircuit::lastSubcircuitMap = name; } return (CCircuit::localSubcircuitIdMap.at(theName)); } void CCircuit::LoadDevices(CDevicePtrList * theDevicePtrList_p) { CDevice * myDevice_p; deviceId_t myDeviceIndex = 0; deviceId_t myInstanceIndex = 0; static int myDeviceCount = 0; static int myCircuitCount = 0; static int myInstanceCount = 0; static int myPrintCount = 0; devicePtr_v.reserve(theDevicePtrList_p->DeviceCount()); deviceErrorCount_v.resize(theDevicePtrList_p->DeviceCount()); devicePrintCount_v.resize(theDevicePtrList_p->DeviceCount()); subcircuitPtr_v.reserve(theDevicePtrList_p->SubcircuitCount()); myCircuitCount++; if ( ++myPrintCount >= 100000 ) { cout << "Read " << myCircuitCount << " circuits, " << myInstanceCount << " instances, " << myDeviceCount << " devices\r" << std::flush; myPrintCount = 0; } CTextDeviceIdMap myDeviceIdMap; // temporary map to check for duplicate device/instance names for (CDevicePtrList::iterator device_ppit = theDevicePtrList_p->begin(); device_ppit != theDevicePtrList_p->end(); device_ppit++) { myDevice_p = *device_ppit; SetSignalIds(myDevice_p->signalList_p, myDevice_p->signalId_v); myDevice_p->parent_p = this; if ( myDeviceIdMap.count(myDevice_p->name) ) { cout << "ERROR: Duplicate instance " << myDevice_p->name << " in " << name << endl; throw EDuplicateInstance(); } if ( myDevice_p->IsSubcircuit() ) { myDevice_p->offset = myInstanceIndex++; myDeviceIdMap[myDevice_p->name] = subcircuitPtr_v.size(); subcircuitPtr_v.push_back(myDevice_p); myInstanceCount++; myPrintCount++; } else { myDevice_p->offset = myDeviceIndex++; myDeviceIdMap[myDevice_p->name] = devicePtr_v.size(); devicePtr_v.push_back(myDevice_p); myDeviceCount++; myPrintCount++; } } // list to vector conversion (top circuit must be redone to include top ports) internalSignal_v.reserve(internalSignalList.size()); while( ! internalSignalList.empty() ) { internalSignal_v.push_back(internalSignalList.front()); internalSignalList.pop_front(); } } void CCircuit::CountObjectsAndLinkSubcircuits(unordered_map & theCircuitNameMap) { CCircuit * myChild_p; deviceCount = devicePtr_v.size(); netCount = LocalNetCount(); subcircuitCount = subcircuitPtr_v.size(); for (CDevicePtrVector::iterator subcircuit_ppit = subcircuitPtr_v.begin(); subcircuit_ppit != subcircuitPtr_v.end(); subcircuit_ppit++) { try { (*subcircuit_ppit)->master_p = theCircuitNameMap.at((*subcircuit_ppit)->masterName); myChild_p = (*subcircuit_ppit)->master_p; if ( myChild_p->linked ) { if ( myChild_p->subcircuitCount > 0 ) { myChild_p->CountInstantiations(); } } else { myChild_p->CountObjectsAndLinkSubcircuits(theCircuitNameMap); } if ( (*subcircuit_ppit)->signalId_v.size() != myChild_p->portCount ) { stringstream myErrorMessage; myErrorMessage << "port mismatch in " << (*subcircuit_ppit)->name << " " << (*subcircuit_ppit)->signalId_v.size() << ":" << myChild_p->portCount << endl; throw EFatalError(myErrorMessage.str()); } myChild_p->instanceCount++; deviceCount += myChild_p->deviceCount; netCount += myChild_p->netCount; subcircuitCount += myChild_p->subcircuitCount; } catch (const out_of_range& oor_exception) { stringstream myErrorMessage; myErrorMessage << "could not find subcircuit: " << (*subcircuit_ppit)->name << "(" << (*subcircuit_ppit)->masterName << ") in " << name << endl; throw EFatalError(myErrorMessage.str()); } } linked = true; } void CCircuit::CountInstantiations() { CCircuit * myChild_p; for (CDevicePtrVector::iterator subcircuit_ppit = subcircuitPtr_v.begin(); subcircuit_ppit != subcircuitPtr_v.end(); subcircuit_ppit++) { myChild_p = (*subcircuit_ppit)->master_p; assert(myChild_p->linked); if ( myChild_p->subcircuitCount > 0 ) { myChild_p->CountInstantiations(); } myChild_p->instanceCount++; } } void CCircuit::Print (const string theIndentation) { CTextVector mySignalName_v; netId_t mySignalId = 0; cout << theIndentation << "Circuit Name: " << name << endl; cout << theIndentation << "Linked: " << linked; cout << " Counts Devices: " << deviceCount; cout << " Nets: " << netCount; cout << " Subcircuits: " << subcircuitCount; cout << " Instances: " << instanceCount << endl; string myIndentation = theIndentation + " "; cout << myIndentation << "Signal List(" << portCount << "/" << localSignalIdMap.size() << "): "; mySignalName_v.reserve(localSignalIdMap.size()); for (CTextNetIdMap::iterator textNetIdPair_pit = localSignalIdMap.begin(); textNetIdPair_pit != localSignalIdMap.end(); ++textNetIdPair_pit) { mySignalName_v[textNetIdPair_pit->second] = textNetIdPair_pit->first; } while (mySignalId < localSignalIdMap.size()) { cout << " " << mySignalName_v[mySignalId] << ":" << mySignalId; mySignalId++; } cout << endl; devicePtr_v.Print(mySignalName_v, myIndentation, "DeviceList>"); subcircuitPtr_v.Print(mySignalName_v, this, myIndentation, "SubcircuitList>"); if ( instanceCount > 0 && instanceId_v.size() == instanceCount ) { cout << myIndentation << "InstanceList>"; for (instanceId_t instance_it = 0; instance_it < instanceCount; instance_it++) { cout << " " << instanceId_v[instance_it]; } cout << endl; } cout << endl; } void CCircuitPtrList::Clear() { cdlText.Clear(); circuitNameMap.clear(); parameterText.Clear(); for ( auto circuit_ppit = begin(); circuit_ppit != end(); circuit_ppit++ ) { delete (*circuit_ppit); } errorCount = 0; } void CCircuitPtrList::Print (const string theIndentation, const string theHeading) { cout << theIndentation << theHeading << " start" << endl; string myIndentation = theIndentation + " "; cout << myIndentation << "Cdl text size: " << cdlText.Size() << endl; for (CCircuitPtrList::iterator circuit_ppit = begin(); circuit_ppit != end(); ++circuit_ppit) { (*circuit_ppit)->Print(myIndentation); } cout << theIndentation << theHeading << " end" << endl << endl; } CCircuit * CCircuitPtrList::FindCircuit(const string theSearchCircuitName) { // error handling in calling routine return(circuitNameMap.at(cdlText.GetTextAddress(theSearchCircuitName))); } void CCircuitPtrList::SetChecksum(const string theCircuitName, const string theChecksum) { CCircuit * myCircuitPtr = FindCircuit(theCircuitName); myCircuitPtr->checksum = theChecksum; } void CCircuitPtrList::PrintAndResetCircuitErrors(CCvcDb * theCvcDb_p, deviceId_t theErrorLimit, ofstream & theLogFile, ogzstream & theErrorFile, string theSummaryHeading, int theErrorSubIndex, set & theModelList) { list myErrorSummaryList; theErrorFile << theSummaryHeading << endl; for (auto circuit_ppit = begin(); circuit_ppit != end(); circuit_ppit++) { if ( (*circuit_ppit)->instanceCount == 0 ) continue; // ignore unused circuits for (size_t device_it = 0; device_it < (*circuit_ppit)->devicePtr_v.size(); device_it++) { if ( theModelList.empty() || theModelList.count((*circuit_ppit)->devicePtr_v[device_it]->model_p->type) > 0 ) { if ( (*circuit_ppit)->devicePrintCount_v[device_it][theErrorSubIndex] > 0 ) { stringstream myErrorSummary; myErrorSummary.str(""); myErrorSummary << "INFO: SUBCKT (" << (*circuit_ppit)->name << ")/" << (*circuit_ppit)->devicePtr_v[device_it]->name; myErrorSummary << "(" << (*circuit_ppit)->devicePtr_v[device_it]->model_p->name << ")"; myErrorSummary << " error count " << (*circuit_ppit)->deviceErrorCount_v[device_it][theErrorSubIndex] << "/" << (*circuit_ppit)->instanceId_v.size(); if ( theErrorLimit > 0 && (*circuit_ppit)->deviceErrorCount_v[device_it][theErrorSubIndex] > theErrorLimit ) { myErrorSummary << " exceeded error limit " << theErrorLimit; } myErrorSummary << " checksum(" << (*circuit_ppit)->checksum << ")"; myErrorSummaryList.push_front(myErrorSummary.str()); } (*circuit_ppit)->deviceErrorCount_v[device_it][theErrorSubIndex] = 0; (*circuit_ppit)->devicePrintCount_v[device_it][theErrorSubIndex] = 0; } } } myErrorSummaryList.sort(); for ( auto error_pit = myErrorSummaryList.begin(); error_pit != myErrorSummaryList.end(); error_pit++ ) { theErrorFile << (*error_pit) << endl; } theErrorFile << endl<< "! Finished" << endl << endl; theCvcDb_p->cellErrorCountMap.clear(); } void CCircuit::AllocateInstances(CCvcDb * theCvcDb_p, instanceId_t theFirstInstanceId) { instanceId_v.reserve(instanceCount); instanceHashId_v.resize(instanceCount, UNKNOWN_DEVICE); }