1 /*
2  * CDevice.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 "CDevice.hh"
25 
26 #include "CCvcDb.hh"
27 #include "CCircuit.hh"
28 
~CDevice()29 CDevice::~CDevice() {
30 	delete signalList_p;
31 }
32 
33 // Print primitive devices
Print(CTextVector & theSignalName_v,const string theIndentation)34 void CDevice::Print (CTextVector& theSignalName_v, const string theIndentation) {
35 	string myIndentation = theIndentation + " ";
36 	cout << theIndentation << "Device Name: " << name << endl;
37 	if ( model_p == NULL ) {
38 		cout << myIndentation << "Model: unknown" << endl;
39 	} else {
40 		model_p->Print(cout, PRINT_DEVICE_LIST_OFF, myIndentation);
41 	}
42 	cout << myIndentation << "Signal List(" << signalId_v.size() << "):";
43 	cout << ((sourceDrainSet) ? "+" : "-") << ((sourceDrainSwapOk) ? "+" : "-");
44 	for (netId_t net_it = 0; net_it < signalId_v.size(); ++net_it) {
45 		cout << " " << theSignalName_v[signalId_v[net_it]] << ":" << signalId_v[net_it];
46 	}
47 	cout << endl << myIndentation << "Parameter List: " << parameters << endl;
48 }
49 
50 // Print Subcircuit Devices
51 
Print(CTextVector & theSignalName_v,deviceId_t theId,const string theIndentation)52 void CDevice::Print (CTextVector & theSignalName_v, deviceId_t theId, const string theIndentation) {
53 	string myIndentation = theIndentation + " ";
54 	cout << theIndentation << "Instance Name: " << name << ":" << theId << endl;
55 	cout << myIndentation << "Master Name: " << masterName;
56 	if ( master_p == NULL ) {
57 		cout << " ?" << endl;
58 	} else {
59 		cout << " ok" << endl;
60 	}
61 	cout << myIndentation << "Signal List(" << signalId_v.size() << "):";
62 	for (netId_t net_it = 0; net_it < signalId_v.size(); ++net_it) {
63 		cout << " " << theSignalName_v[signalId_v[net_it]] << ":" << signalId_v[net_it];
64 	}
65 	cout << endl;
66 }
67 
Print(CTextVector & theSignalName_v,const string theIndentation,const string myHeading)68 void CDevicePtrList::Print (CTextVector& theSignalName_v, const string theIndentation, const string myHeading) {
69 	cout << theIndentation << myHeading << " start" << endl;
70 	string myIndentation = theIndentation + " ";
71 	for (CDevicePtrList::iterator device_ppit = begin(); device_ppit != end(); ++device_ppit) {
72 		(*device_ppit)->Print(theSignalName_v, myIndentation);
73 	}
74 	cout << theIndentation << myHeading << " end" << endl;
75 }
76 
~CDevicePtrVector()77 CDevicePtrVector::~CDevicePtrVector() {
78 	for ( auto device_ppit = begin(); device_ppit != end(); device_ppit++ ) {
79 		delete (*device_ppit);
80 	}
81 	resize(0);
82 }
83 
Print(CTextVector & theSignalName_v,const string theIndentation,const string myHeading)84 void CDevicePtrVector::Print(CTextVector& theSignalName_v, const string theIndentation, const string myHeading) {
85 	if (empty()) {
86 		cout << theIndentation << myHeading << " empty" << endl;
87 	} else {
88 		cout << theIndentation << myHeading << " start" << endl;
89 		string myIndentation = theIndentation + " ";
90 		for (CDevicePtrVector::iterator device_ppit = begin(); device_ppit != end(); ++device_ppit) {
91 			(*device_ppit)->Print(theSignalName_v, myIndentation);
92 		}
93 		cout << theIndentation << myHeading << " end" << endl;
94 	}
95 }
96 
Print(CTextVector & theSignalName_v,CCircuit * theParent_p,const string theIndentation,const string myHeading)97 void CDevicePtrVector::Print(CTextVector& theSignalName_v, CCircuit * theParent_p, const string theIndentation, const string myHeading) {
98 	if (empty()) {
99 		cout << theIndentation << myHeading << " empty" << endl;
100 	} else {
101 		cout << theIndentation << myHeading << " start" << endl;
102 		string myIndentation = theIndentation + " ";
103 		for (CDevicePtrVector::iterator device_ppit = begin(); device_ppit != end(); ++device_ppit) {
104 			(*device_ppit)->Print(theSignalName_v, (*device_ppit)->offset, myIndentation);
105 		}
106 		cout << theIndentation << myHeading << " end" << endl;
107 	}
108 }
109 
110 #define A_PRIME 0xcc9e2d51
111 
MakePortHash(CNetIdVector & theLocalToGlobalNetId_v)112 instanceId_t CDevice::MakePortHash(CNetIdVector & theLocalToGlobalNetId_v) {
113 	instanceId_t myHash = 0;
114 	for ( netId_t port_it = 0; port_it < master_p->portCount; port_it++ ) {
115 		myHash = myHash << 16 ^ theLocalToGlobalNetId_v[signalId_v[port_it]] ^ myHash;
116 		myHash *= A_PRIME;
117 	}
118 	return ( myHash % master_p->instanceCount );
119 }
120 
121 extern int gHashCollisionCount;
122 extern int gMaxHashLength;
123 
FindParallelInstance(CCvcDb * theCvcDb_p,instanceId_t theInstanceId,CNetIdVector & theLocalToGlobalNetId_v)124 instanceId_t CDevice::FindParallelInstance(CCvcDb * theCvcDb_p, instanceId_t theInstanceId, CNetIdVector & theLocalToGlobalNetId_v) {
125 	// Executed once and only once for each instance
126 	instanceId_t myKey = MakePortHash(theLocalToGlobalNetId_v);
127 	assert(myKey != UNKNOWN_DEVICE && myKey < master_p->instanceCount );
128 	if ( master_p->instanceHashId_v[myKey] == UNKNOWN_DEVICE ) {
129 		master_p->instanceHashId_v[myKey] = theInstanceId;
130 	} else {
131 		instanceId_t myCheckInstanceId = master_p->instanceHashId_v[myKey];
132 		CInstance * myInstance_p;
133 		int myHashLength = 0;
134 		do {
135 			myInstance_p = theCvcDb_p->instancePtr_v[myCheckInstanceId];
136 			if ( master_p != myInstance_p->master_p ) {
137 				cout << "DEBUG: master mismatch at instance " << theInstanceId << " and " << myCheckInstanceId << endl;
138 				cout << "  " << master_p->name << " != " << myInstance_p->master_p->name << endl;
139 			}
140 			for ( netId_t port_it = 0; port_it <= master_p->portCount; port_it++ ) {
141 				if ( port_it == master_p->portCount ) {  // all ports match
142 					return (myCheckInstanceId);
143 				} else {
144 					if (theLocalToGlobalNetId_v[signalId_v[port_it]] != myInstance_p->localToGlobalNetId_v[port_it]) break;
145 				}
146 			}
147 			myHashLength++;
148 			gHashCollisionCount++;
149 			myCheckInstanceId = myInstance_p->nextHashedInstanceId;
150 		} while ( myCheckInstanceId != UNKNOWN_DEVICE );
151 		if ( gMaxHashLength < myHashLength ) gMaxHashLength = myHashLength;
152 		myInstance_p->nextHashedInstanceId = theInstanceId;
153 	}
154 	return (theInstanceId);
155 }
156