1 /*
2 * CCircuit.cc
3 *
4 * Copyright 2014-2018 D. Mitch Bailey cvc at shuharisystem dot com
5 *
6 * This file is part of cvc.
7 *
8 * cvc is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * cvc is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with cvc. If not, see <http://www.gnu.org/licenses/>.
20 *
21 * You can download cvc from https://github.com/d-m-bailey/cvc.git
22 */
23
24 #include "CCircuit.hh"
25
26 class CCvcDb;
27 #include "CDevice.hh"
28 #include "CFixedText.hh"
29 #include "CCvcDb.hh"
30
31 text_t CCircuit::lastDeviceMap = NULL;
32 CTextDeviceIdMap CCircuit::localDeviceIdMap;
33 text_t CCircuit::lastSubcircuitMap = NULL;
34 CTextDeviceIdMap CCircuit::localSubcircuitIdMap;
35
AddPortSignalIds(CTextList * thePortList_p)36 void CCircuit::AddPortSignalIds(CTextList * thePortList_p) {
37 for (CTextList::iterator text_pit = thePortList_p->begin(); text_pit != thePortList_p->end(); ++text_pit) {
38 localSignalIdMap[*text_pit] = portCount++;
39 }
40 }
41
SetSignalIds(CTextList * signalList_p,CNetIdVector & signalId_v)42 void CCircuit::SetSignalIds(CTextList * signalList_p, CNetIdVector& signalId_v ) {
43 netId_t mySignalId;
44
45 signalId_v.reserve(signalList_p->size());
46 for (CTextList::iterator text_pit = signalList_p->begin(); text_pit != signalList_p->end(); ++text_pit) {
47 try {
48 mySignalId = localSignalIdMap.at(*text_pit);
49 }
50 catch (const out_of_range& oor_exception) {
51 mySignalId = localSignalIdMap.size();
52 localSignalIdMap[*text_pit] = mySignalId;
53 internalSignalList.push_back(*text_pit);
54 }
55 signalId_v.push_back(mySignalId);
56 }
57 }
58
GetLocalDeviceId(text_t theName)59 deviceId_t CCircuit::GetLocalDeviceId(text_t theName) {
60 if ( CCircuit::lastDeviceMap != name ) {
61 CCircuit::localDeviceIdMap.clear();
62 for ( deviceId_t device_it = 0; device_it < devicePtr_v.size(); device_it++ ) {
63 CCircuit::localDeviceIdMap[devicePtr_v[device_it]->name] = device_it;
64 }
65 CCircuit::lastDeviceMap = name;
66 }
67 return (CCircuit::localDeviceIdMap.at(theName));
68 }
69
GetLocalSubcircuitId(text_t theName)70 deviceId_t CCircuit::GetLocalSubcircuitId(text_t theName) {
71 if ( CCircuit::lastSubcircuitMap != name ) {
72 CCircuit::localSubcircuitIdMap.clear();
73 for ( deviceId_t device_it = 0; device_it < subcircuitPtr_v.size(); device_it++ ) {
74 CCircuit::localSubcircuitIdMap[subcircuitPtr_v[device_it]->name] = device_it;
75 }
76 CCircuit::lastSubcircuitMap = name;
77 }
78 return (CCircuit::localSubcircuitIdMap.at(theName));
79 }
80
LoadDevices(CDevicePtrList * theDevicePtrList_p)81 void CCircuit::LoadDevices(CDevicePtrList * theDevicePtrList_p) {
82 CDevice * myDevice_p;
83 deviceId_t myDeviceIndex = 0;
84 deviceId_t myInstanceIndex = 0;
85 static int myDeviceCount = 0;
86 static int myCircuitCount = 0;
87 static int myInstanceCount = 0;
88 static int myPrintCount = 0;
89
90 devicePtr_v.reserve(theDevicePtrList_p->DeviceCount());
91 deviceErrorCount_v.resize(theDevicePtrList_p->DeviceCount());
92 devicePrintCount_v.resize(theDevicePtrList_p->DeviceCount());
93 subcircuitPtr_v.reserve(theDevicePtrList_p->SubcircuitCount());
94 myCircuitCount++;
95 if ( ++myPrintCount >= 100000 ) {
96 cout << "Read " << myCircuitCount << " circuits, " << myInstanceCount << " instances, " << myDeviceCount << " devices\r" << std::flush;
97 myPrintCount = 0;
98 }
99 CTextDeviceIdMap myDeviceIdMap; // temporary map to check for duplicate device/instance names
100 for (CDevicePtrList::iterator device_ppit = theDevicePtrList_p->begin(); device_ppit != theDevicePtrList_p->end(); device_ppit++) {
101 myDevice_p = *device_ppit;
102 SetSignalIds(myDevice_p->signalList_p, myDevice_p->signalId_v);
103 myDevice_p->parent_p = this;
104 if ( myDeviceIdMap.count(myDevice_p->name) ) {
105 cout << "ERROR: Duplicate instance " << myDevice_p->name << " in " << name << endl;
106 throw EDuplicateInstance();
107 }
108 if ( myDevice_p->IsSubcircuit() ) {
109 myDevice_p->offset = myInstanceIndex++;
110 myDeviceIdMap[myDevice_p->name] = subcircuitPtr_v.size();
111 subcircuitPtr_v.push_back(myDevice_p);
112 myInstanceCount++;
113 myPrintCount++;
114 } else {
115 myDevice_p->offset = myDeviceIndex++;
116 myDeviceIdMap[myDevice_p->name] = devicePtr_v.size();
117 devicePtr_v.push_back(myDevice_p);
118 myDeviceCount++;
119 myPrintCount++;
120 }
121 }
122 // list to vector conversion (top circuit must be redone to include top ports)
123 internalSignal_v.reserve(internalSignalList.size());
124 while( ! internalSignalList.empty() ) {
125 internalSignal_v.push_back(internalSignalList.front());
126 internalSignalList.pop_front();
127 }
128
129 }
130
CountObjectsAndLinkSubcircuits(unordered_map<text_t,CCircuit * > & theCircuitNameMap)131 void CCircuit::CountObjectsAndLinkSubcircuits(unordered_map<text_t, CCircuit *> & theCircuitNameMap) {
132 CCircuit * myChild_p;
133
134 deviceCount = devicePtr_v.size();
135 netCount = LocalNetCount();
136 subcircuitCount = subcircuitPtr_v.size();
137 for (CDevicePtrVector::iterator subcircuit_ppit = subcircuitPtr_v.begin(); subcircuit_ppit != subcircuitPtr_v.end(); subcircuit_ppit++) {
138 try {
139 (*subcircuit_ppit)->master_p = theCircuitNameMap.at((*subcircuit_ppit)->masterName);
140 myChild_p = (*subcircuit_ppit)->master_p;
141 if ( myChild_p->linked ) {
142 if ( myChild_p->subcircuitCount > 0 ) {
143 myChild_p->CountInstantiations();
144 }
145 } else {
146 myChild_p->CountObjectsAndLinkSubcircuits(theCircuitNameMap);
147 }
148 if ( (*subcircuit_ppit)->signalId_v.size() != myChild_p->portCount ) {
149 stringstream myErrorMessage;
150 myErrorMessage << "port mismatch in " << (*subcircuit_ppit)->name << " " << (*subcircuit_ppit)->signalId_v.size() << ":" << myChild_p->portCount << endl;
151 throw EFatalError(myErrorMessage.str());
152 }
153 myChild_p->instanceCount++;
154 deviceCount += myChild_p->deviceCount;
155 netCount += myChild_p->netCount;
156 subcircuitCount += myChild_p->subcircuitCount;
157 }
158 catch (const out_of_range& oor_exception) {
159 stringstream myErrorMessage;
160 myErrorMessage << "could not find subcircuit: " << (*subcircuit_ppit)->name << "(" << (*subcircuit_ppit)->masterName << ") in " << name << endl;
161 throw EFatalError(myErrorMessage.str());
162 }
163 }
164 linked = true;
165 }
166
CountInstantiations()167 void CCircuit::CountInstantiations() {
168 CCircuit * myChild_p;
169
170 for (CDevicePtrVector::iterator subcircuit_ppit = subcircuitPtr_v.begin(); subcircuit_ppit != subcircuitPtr_v.end(); subcircuit_ppit++) {
171 myChild_p = (*subcircuit_ppit)->master_p;
172 assert(myChild_p->linked);
173 if ( myChild_p->subcircuitCount > 0 ) {
174 myChild_p->CountInstantiations();
175 }
176 myChild_p->instanceCount++;
177 }
178 }
179
Print(const string theIndentation)180 void CCircuit::Print (const string theIndentation) {
181 CTextVector mySignalName_v;
182 netId_t mySignalId = 0;
183
184 cout << theIndentation << "Circuit Name: " << name << endl;
185 cout << theIndentation << "Linked: " << linked;
186 cout << " Counts Devices: " << deviceCount;
187 cout << " Nets: " << netCount;
188 cout << " Subcircuits: " << subcircuitCount;
189 cout << " Instances: " << instanceCount << endl;
190 string myIndentation = theIndentation + " ";
191 cout << myIndentation << "Signal List(" << portCount << "/" << localSignalIdMap.size() << "): ";
192 mySignalName_v.reserve(localSignalIdMap.size());
193 for (CTextNetIdMap::iterator textNetIdPair_pit = localSignalIdMap.begin(); textNetIdPair_pit != localSignalIdMap.end(); ++textNetIdPair_pit) {
194 mySignalName_v[textNetIdPair_pit->second] = textNetIdPair_pit->first;
195 }
196 while (mySignalId < localSignalIdMap.size()) {
197 cout << " " << mySignalName_v[mySignalId] << ":" << mySignalId;
198 mySignalId++;
199 }
200 cout << endl;
201 devicePtr_v.Print(mySignalName_v, myIndentation, "DeviceList>");
202 subcircuitPtr_v.Print(mySignalName_v, this, myIndentation, "SubcircuitList>");
203 if ( instanceCount > 0 && instanceId_v.size() == instanceCount ) {
204 cout << myIndentation << "InstanceList>";
205 for (instanceId_t instance_it = 0; instance_it < instanceCount; instance_it++) {
206 cout << " " << instanceId_v[instance_it];
207 }
208 cout << endl;
209 }
210 cout << endl;
211 }
212
Clear()213 void CCircuitPtrList::Clear() {
214 cdlText.Clear();
215 circuitNameMap.clear();
216 parameterText.Clear();
217 for ( auto circuit_ppit = begin(); circuit_ppit != end(); circuit_ppit++ ) {
218 delete (*circuit_ppit);
219 }
220 errorCount = 0;
221 }
222
Print(const string theIndentation,const string theHeading)223 void CCircuitPtrList::Print (const string theIndentation, const string theHeading) {
224 cout << theIndentation << theHeading << " start" << endl;
225 string myIndentation = theIndentation + " ";
226 cout << myIndentation << "Cdl text size: " << cdlText.Size() << endl;
227 for (CCircuitPtrList::iterator circuit_ppit = begin(); circuit_ppit != end(); ++circuit_ppit) {
228 (*circuit_ppit)->Print(myIndentation);
229 }
230 cout << theIndentation << theHeading << " end" << endl << endl;
231 }
232
FindCircuit(const string theSearchCircuitName)233 CCircuit * CCircuitPtrList::FindCircuit(const string theSearchCircuitName) {
234 // error handling in calling routine
235 return(circuitNameMap.at(cdlText.GetTextAddress(theSearchCircuitName)));
236 }
237
SetChecksum(const string theCircuitName,const string theChecksum)238 void CCircuitPtrList::SetChecksum(const string theCircuitName, const string theChecksum) {
239 CCircuit * myCircuitPtr = FindCircuit(theCircuitName);
240 myCircuitPtr->checksum = theChecksum;
241 }
242
PrintAndResetCircuitErrors(CCvcDb * theCvcDb_p,deviceId_t theErrorLimit,ofstream & theLogFile,ogzstream & theErrorFile,string theSummaryHeading,int theErrorSubIndex,set<modelType_t> & theModelList)243 void CCircuitPtrList::PrintAndResetCircuitErrors(CCvcDb * theCvcDb_p, deviceId_t theErrorLimit, ofstream & theLogFile, ogzstream & theErrorFile,
244 string theSummaryHeading, int theErrorSubIndex, set<modelType_t> & theModelList) {
245 list<string> myErrorSummaryList;
246 theErrorFile << theSummaryHeading << endl;
247 for (auto circuit_ppit = begin(); circuit_ppit != end(); circuit_ppit++) {
248 if ( (*circuit_ppit)->instanceCount == 0 ) continue; // ignore unused circuits
249 for (size_t device_it = 0; device_it < (*circuit_ppit)->devicePtr_v.size(); device_it++) {
250 if ( theModelList.empty() || theModelList.count((*circuit_ppit)->devicePtr_v[device_it]->model_p->type) > 0 ) {
251 if ( (*circuit_ppit)->devicePrintCount_v[device_it][theErrorSubIndex] > 0 ) {
252 stringstream myErrorSummary;
253 myErrorSummary.str("");
254 myErrorSummary << "INFO: SUBCKT (" << (*circuit_ppit)->name << ")/" << (*circuit_ppit)->devicePtr_v[device_it]->name;
255 myErrorSummary << "(" << (*circuit_ppit)->devicePtr_v[device_it]->model_p->name << ")";
256 myErrorSummary << " error count " << (*circuit_ppit)->deviceErrorCount_v[device_it][theErrorSubIndex] << "/" << (*circuit_ppit)->instanceId_v.size();
257 if ( theErrorLimit > 0 && (*circuit_ppit)->deviceErrorCount_v[device_it][theErrorSubIndex] > theErrorLimit ) {
258 myErrorSummary << " exceeded error limit " << theErrorLimit;
259 }
260 myErrorSummary << " checksum(" << (*circuit_ppit)->checksum << ")";
261 myErrorSummaryList.push_front(myErrorSummary.str());
262 }
263 (*circuit_ppit)->deviceErrorCount_v[device_it][theErrorSubIndex] = 0;
264 (*circuit_ppit)->devicePrintCount_v[device_it][theErrorSubIndex] = 0;
265 }
266 }
267 }
268 myErrorSummaryList.sort();
269 for ( auto error_pit = myErrorSummaryList.begin(); error_pit != myErrorSummaryList.end(); error_pit++ ) {
270 theErrorFile << (*error_pit) << endl;
271 }
272 theErrorFile << endl<< "! Finished" << endl << endl;
273 theCvcDb_p->cellErrorCountMap.clear();
274 }
275
AllocateInstances(CCvcDb * theCvcDb_p,instanceId_t theFirstInstanceId)276 void CCircuit::AllocateInstances(CCvcDb * theCvcDb_p, instanceId_t theFirstInstanceId) {
277 instanceId_v.reserve(instanceCount);
278 instanceHashId_v.resize(instanceCount, UNKNOWN_DEVICE);
279 }
280