1 /*
2  * CInstance.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 "CInstance.hh"
25 
26 #include "CCvcDb.hh"
27 #include "CCircuit.hh"
28 #include "obstack.h"
29 
30 #define NOT_PARALLEL false
31 
32 int gHashCollisionCount;
33 int gMaxHashLength;
34 
AssignTopGlobalIDs(CCvcDb * theCvcDb_p,CCircuit * theMaster_p)35 void CInstance::AssignTopGlobalIDs(CCvcDb * theCvcDb_p, CCircuit * theMaster_p) {
36 
37 	theMaster_p->instanceId_v.push_back(0);
38 	theCvcDb_p->subcircuitCount = 1;
39 	firstSubcircuitId = 1;
40 	parentId = 0;
41 	master_p = theMaster_p;
42 	netId_t myLastNet = theMaster_p->localSignalIdMap.size();
43 	localToGlobalNetId_v.reserve(myLastNet);
44 	localToGlobalNetId_v.resize(myLastNet);
45 	theMaster_p->internalSignal_v.clear();
46 	theMaster_p->internalSignal_v.reserve(theMaster_p->localSignalIdMap.size());
47 	theMaster_p->internalSignal_v.resize(theMaster_p->localSignalIdMap.size());
48 	for (CTextNetIdMap::iterator textNetIdPair_pit = theMaster_p->localSignalIdMap.begin(); textNetIdPair_pit != theMaster_p->localSignalIdMap.end(); textNetIdPair_pit++) {
49 		theMaster_p->internalSignal_v[textNetIdPair_pit->second] = textNetIdPair_pit->first;
50 	}
51 	for (netId_t globalNet_it = 0; globalNet_it < myLastNet; globalNet_it++) {
52 		localToGlobalNetId_v[globalNet_it] = globalNet_it;
53 	}
54 	theCvcDb_p->netCount = myLastNet;
55 	theCvcDb_p->subcircuitCount += theMaster_p->subcircuitPtr_v.size();
56 	theCvcDb_p->deviceCount = theMaster_p->devicePtr_v.size();
57 	theCvcDb_p->netParent_v.resize(theCvcDb_p->netCount, 0);
58 	theCvcDb_p->deviceParent_v.resize(theCvcDb_p->deviceCount, 0);
59 
60 	instanceId_t myLastSubcircuitId = theMaster_p->subcircuitPtr_v.size();
61 	instanceId_t myNewInstanceId;
62 	for (instanceId_t subcircuit_it = 0; subcircuit_it < myLastSubcircuitId; subcircuit_it++) {
63 		if (theMaster_p->subcircuitPtr_v[subcircuit_it]->master_p->deviceCount > 0) {
64 			myNewInstanceId = firstSubcircuitId + subcircuit_it;
65 			CDevice * mySubcircuit_p = theMaster_p->subcircuitPtr_v[subcircuit_it];
66 			if ( mySubcircuit_p->master_p->instanceId_v.size() == 0 ) mySubcircuit_p->master_p->AllocateInstances(theCvcDb_p, myNewInstanceId);
67 			theCvcDb_p->instancePtr_v[myNewInstanceId] = new CInstance;
68 			theCvcDb_p->instancePtr_v[myNewInstanceId]->AssignGlobalIDs(theCvcDb_p, myNewInstanceId, mySubcircuit_p, 0, this, NOT_PARALLEL);
69 		}
70 	}
71 	theCvcDb_p->netParent_v.shrink_to_fit();
72 	theCvcDb_p->deviceParent_v.shrink_to_fit();
73 	theCvcDb_p->debugFile << "DEBUG: netParent size " << theCvcDb_p->netParent_v.size() << "; deviceParent size " << theCvcDb_p->deviceParent_v.size() << endl;
74 	theCvcDb_p->debugFile << "DEBUG: parallel collisions " << gHashCollisionCount << " max length " << gMaxHashLength << endl;
75 }
76 
AssignGlobalIDs(CCvcDb * theCvcDb_p,const instanceId_t theInstanceId,CDevice * theSubcircuit_p,const instanceId_t theParentId,CInstance * theParent_p,bool isParallel)77 void CInstance::AssignGlobalIDs(CCvcDb * theCvcDb_p, const instanceId_t theInstanceId, CDevice * theSubcircuit_p, const instanceId_t theParentId,
78 		CInstance * theParent_p, bool isParallel) {
79 	master_p = theSubcircuit_p->master_p;
80 	instanceId_t myLastSubcircuitId = master_p->subcircuitPtr_v.size();
81 	firstSubcircuitId = theCvcDb_p->subcircuitCount;
82 	master_p->instanceId_v.push_back(theInstanceId);
83 
84 	parentId = theParentId;
85 	instanceId_t myParallelInstance;
86 	if ( isParallel ) {
87 		assert(theParent_p->IsParallelInstance());
88 		CInstance * myParentParallelInstance_p = theCvcDb_p->instancePtr_v[theParent_p->parallelInstanceId];
89 		int myInstanceOffset = theInstanceId - theParent_p->firstSubcircuitId;
90 		parallelInstanceId = myParentParallelInstance_p->firstSubcircuitId + myInstanceOffset;
91 		CInstance * myParallelInstance_p = theCvcDb_p->instancePtr_v[parallelInstanceId];
92 		if ( myParallelInstance_p->IsParallelInstance() ) {
93 			theCvcDb_p->instancePtr_v[myParallelInstance_p->parallelInstanceId]->parallelInstanceCount++;
94 		} else {
95 			myParallelInstance_p->parallelInstanceCount++;
96 		}
97 		theCvcDb_p->debugFile << "DEBUG: found parallel instance in parallel instance at " << theCvcDb_p->HierarchyName(theInstanceId) << endl;
98 	} else {
99 		if ( theSubcircuit_p->signalId_v.size() <= theCvcDb_p->cvcParameters.cvcParallelCircuitPortLimit ) {
100 			myParallelInstance = theSubcircuit_p->FindParallelInstance(theCvcDb_p, theInstanceId, theParent_p->localToGlobalNetId_v);
101 			if ( myParallelInstance == theInstanceId ) {
102 				theCvcDb_p->instancePtr_v[theInstanceId]->parallelInstanceCount = 1;
103 			} else {  // skip parallel circuits
104 				theCvcDb_p->instancePtr_v[myParallelInstance]->parallelInstanceCount++;
105 				theCvcDb_p->debugFile << "DEBUG: found parallel instance at " << theCvcDb_p->HierarchyName(theInstanceId) << endl;
106 				parallelInstanceId = myParallelInstance;
107 				isParallel = true;
108 			}
109 		}
110 	}
111 	if ( ! isParallel ) {  // don't expand devices/nets for parallel instances
112 		firstNetId = theCvcDb_p->netCount;
113 		firstDeviceId = theCvcDb_p->deviceCount;
114 
115 		netId_t myLastNet = master_p->localSignalIdMap.size();
116 		localToGlobalNetId_v.reserve(myLastNet);
117 		localToGlobalNetId_v.resize(myLastNet);
118 		for (netId_t net_it = 0; net_it < master_p->portCount; net_it++) {
119 			localToGlobalNetId_v[net_it] = theParent_p->localToGlobalNetId_v[theSubcircuit_p->signalId_v[net_it]];
120 		}
121 		for (netId_t net_it = master_p->portCount; net_it < myLastNet; net_it++) {
122 			localToGlobalNetId_v[net_it] = firstNetId + net_it - master_p->portCount;
123 		}
124 		theCvcDb_p->netCount += master_p->LocalNetCount();
125 		theCvcDb_p->deviceCount += master_p->devicePtr_v.size();
126 		theCvcDb_p->netParent_v.resize(theCvcDb_p->netCount, theInstanceId);
127 		theCvcDb_p->deviceParent_v.resize(theCvcDb_p->deviceCount, theInstanceId);
128 	}
129 
130 	theCvcDb_p->subcircuitCount += master_p->subcircuitPtr_v.size();
131 
132 	instanceId_t myNewInstanceId;
133 	for (instanceId_t subcircuit_it = 0; subcircuit_it < myLastSubcircuitId; subcircuit_it++) {
134 		myNewInstanceId = firstSubcircuitId + subcircuit_it;
135 		CDevice * mySubcircuit_p = master_p->subcircuitPtr_v[subcircuit_it];
136 		if (mySubcircuit_p->master_p->deviceCount > 0) {
137 			if ( mySubcircuit_p->master_p->instanceId_v.size() == 0 ) mySubcircuit_p->master_p->AllocateInstances(theCvcDb_p, myNewInstanceId);
138 			theCvcDb_p->instancePtr_v[myNewInstanceId] = new CInstance;
139 			theCvcDb_p->instancePtr_v[myNewInstanceId]->AssignGlobalIDs(theCvcDb_p, myNewInstanceId, mySubcircuit_p, theInstanceId, this, isParallel);
140 		}
141 	}
142 }
143 
Print(const instanceId_t theInstanceId,const string theIndentation)144 void CInstance::Print (const instanceId_t theInstanceId, const string theIndentation) {
145 	cout << theIndentation << "Instance> " << theInstanceId << endl;
146 	string myIndentation = theIndentation + " ";
147 	cout << myIndentation << "First: subcircuit: " << firstSubcircuitId;
148 	cout << "  net: " << firstNetId;
149 	cout << "  device: " << firstDeviceId << endl;
150 	cout << myIndentation << "parent: " << parentId << "  master: " << master_p->name << endl;
151 	cout << myIndentation << "signal map:";
152 	for (netId_t net_it = 0; net_it < localToGlobalNetId_v.size(); net_it++) {
153 		cout << " " << net_it << ":" << localToGlobalNetId_v[net_it];
154 	}
155 	cout << endl;
156 }
157 
Clear()158 void CInstancePtrVector::Clear() {
159 	for ( auto instance_ppit = begin(); instance_ppit != end(); instance_ppit++ ) {
160 		delete (*instance_ppit);
161 	}
162 	resize(0);
163 }
164 
~CInstancePtrVector()165 CInstancePtrVector::~CInstancePtrVector() {
166 	Clear();
167 }
168 
169