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