1 /*
2 * CPower.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 "CPower.hh"
25
26 #include "CEventQueue.hh"
27 #include "CCvcDb.hh"
28
29 netId_t CPower::powerCount = 0;
30 CFixedText CPower::powerDefinitionText;
31
CExtraPowerData()32 CExtraPowerData::CExtraPowerData() {
33 powerSignal = CPower::powerDefinitionText.BlankTextAddress();
34 powerAlias = CPower::powerDefinitionText.BlankTextAddress();
35 }
36
CPower()37 CPower::CPower() {
38 powerId = powerCount++;
39 definition = CPower::powerDefinitionText.BlankTextAddress();
40 }
41
CPower(CPower * thePower_p)42 CPower::CPower(CPower * thePower_p) {
43 // Similar to byte-wise copy, but duplicates extraData;
44 *this = *thePower_p;
45 if ( extraData ) {
46 extraData = new CExtraPowerData(*(thePower_p->extraData));
47 }
48 }
49
CPower(CPower * thePower_p,netId_t theNetId)50 CPower::CPower(CPower * thePower_p, netId_t theNetId) {
51 // copies power for expanding power short cuts *(cell)/net
52 // use before family expansion
53 powerId = powerCount++;
54 minVoltage = thePower_p->minVoltage;
55 maxVoltage = thePower_p->maxVoltage;
56 simVoltage = thePower_p->simVoltage;
57 if ( thePower_p->extraData ) {
58 extraData = new CExtraPowerData;
59 extraData->powerSignal = thePower_p->powerSignal();
60 extraData->powerAlias = thePower_p->powerAlias();
61 extraData->expectedSim = thePower_p->expectedSim();
62 extraData->expectedMin = thePower_p->expectedMin();
63 extraData->expectedMax = thePower_p->expectedMax();
64 extraData->family = thePower_p->family();
65 extraData->implicitFamily = thePower_p->implicitFamily();
66 extraData->relativeSet = thePower_p->extraData->relativeSet;
67 }
68 relativeFriendly = thePower_p->relativeFriendly;
69 type = thePower_p->type;
70 definition = thePower_p->definition;
71 active = thePower_p->active;
72 netId = theNetId;
73 minCalculationType = thePower_p->minCalculationType;
74 simCalculationType = thePower_p->simCalculationType;
75 maxCalculationType = thePower_p->maxCalculationType;
76 }
77
CPower(string thePowerString,CPowerPtrMap & thePowerMacroPtrMap,CModelListMap & theModelListMap)78 CPower::CPower(string thePowerString, CPowerPtrMap & thePowerMacroPtrMap, CModelListMap & theModelListMap) {
79 // for power definitions
80 // Valid power definitions
81 // # ... <- comment
82 // VSS 0.0 <- power definition min=sim=max=0.0
83 // VDD 1.2 <- power definition min=sim=max=1.2
84 // VBB -0.5 <- power definition min=sim=max=-0.5
85 // A1 min@0.0 sim@0.6 max@1.2 <- input/output/internal signal min/sim/max.
86 // missing values are calculated.
87 // O1 min@0.0 expect@1.2 max@1.2 <- input/output/internal signal min/max.
88 // sim value is calculated and checked against expect.
89 // missing min/max values are calculated.
90 // VDDX min@0.0 max@1.2 open permit@VSS <- cutoff power definition (floating), unknown sim definition, path to VSS ok
91 // VSSX min@0.0 max@1.2 open permit@VDD <- cutoff power definition (floating), unknown sim definition, path to VDD ok
92 // VDDZ min@1.2 max@1.2 open <- SCRC power definition, no paths permitted
93 // VSSZ min@0.0 max@0.0 open <- SCRC power definition, no paths permitted
94 // active usage: only use min/max power marked as active
95 // sim values imply defined min/max active
96 // open, input also imply defined min/max active
97 // other min/max overrides must have path to lower/higher value to become active
98 // reset before min/max calculations for unknown sim values.
99 // powerAlias: all top level power nets have alias for power families VSS->VSS /VDDA->VDDA
100 // explicit overrides permitted /X7/VDD~>VDD7
101 // TODO: add power families
102 // VPP 2.6 permit@vdd <- power definition with explicit permitted connections
103 // VNWL -0.2 prohibit@VSS <- power definition with explicit prohibited connections
104 // family vdd VDD,VSS,... <- family definition
105 // sanity checks
106 // TODO: power definitions determine default families
107 thePowerString = trim_(thePowerString);
108 string myParameterName;
109 string myParameterValue;
110 size_t myAtIndex;
111 size_t myStringBegin = thePowerString.find_first_not_of(" \t");
112 size_t myStringEnd = thePowerString.find_first_of(" \t", myStringBegin);
113 type = 0;
114 powerId = powerCount++;
115 extraData = new CExtraPowerData;
116 size_t myAliasBegin = thePowerString.find(ALIAS_DELIMITER);
117 extraData->powerSignal = CPower::powerDefinitionText.SetTextAddress((text_t)(thePowerString.substr(myStringBegin, min(myStringEnd, myAliasBegin))).c_str());
118 string myDefinition = "";
119 string myImplicitFamily = "";
120 while (myStringEnd < thePowerString.length()) {
121 myStringBegin = thePowerString.find_first_not_of(" \t", myStringEnd);
122 myStringEnd = thePowerString.find_first_of(" \t", myStringBegin);
123 myAtIndex = thePowerString.find("@", myStringBegin);
124 if ( myAtIndex < myStringEnd ) {
125 myParameterName = thePowerString.substr(myStringBegin, myAtIndex - myStringBegin);
126 myParameterValue = thePowerString.substr(myAtIndex + 1, myStringEnd - (myAtIndex + 1));
127 if ( myParameterName == "min" ) {
128 minVoltage = thePowerMacroPtrMap.CalculateVoltage(myParameterValue, MIN_POWER, theModelListMap);
129 myImplicitFamily += thePowerMacroPtrMap.implicitFamily;
130 minCalculationType = NO_CALCULATION;
131 }
132 if ( myParameterName == "max" ) {
133 maxVoltage = thePowerMacroPtrMap.CalculateVoltage(myParameterValue, MAX_POWER, theModelListMap);
134 myImplicitFamily += thePowerMacroPtrMap.implicitFamily;
135 maxCalculationType = NO_CALCULATION;
136 }
137 if ( myParameterName == "sim" ) {
138 simVoltage = thePowerMacroPtrMap.CalculateVoltage(myParameterValue, SIM_POWER, theModelListMap);
139 myImplicitFamily += thePowerMacroPtrMap.implicitFamily;
140 simCalculationType = NO_CALCULATION;
141 }
142 if ( myParameterName == "expectMin" ) extraData->expectedMin = thePowerMacroPtrMap.CalculateExpectedValue(myParameterValue, MIN_POWER, theModelListMap);
143 if ( myParameterName == "expectMax" ) extraData->expectedMax = thePowerMacroPtrMap.CalculateExpectedValue(myParameterValue, MAX_POWER, theModelListMap);
144 if ( myParameterName == "expectSim" ) extraData->expectedSim = thePowerMacroPtrMap.CalculateExpectedValue(myParameterValue, SIM_POWER, theModelListMap);
145 if ( myParameterName == "permit" || myParameterName == "prohibit" ) {
146 if ( thePowerMacroPtrMap.count(myParameterValue) && ! IsEmpty(thePowerMacroPtrMap[myParameterValue]->powerAlias()) ) {
147 extraData->family = thePowerMacroPtrMap[myParameterValue]->powerAlias();
148 } else {
149 extraData->family = myParameterValue;
150 }
151 relativeFriendly = ( myParameterName == "permit" ) ? true : false;
152 }
153 myDefinition += " " + myParameterName + "@" + myParameterValue;
154 } else {
155 myParameterName = thePowerString.substr(myStringBegin, myStringEnd - myStringBegin);
156 myDefinition += " " + myParameterName;
157 if ( myParameterName == "input" ) {
158 type[INPUT_BIT] = true;
159 } else if ( myParameterName == "power" ) {
160 type[POWER_BIT] = true;
161 if ( IsEmpty(powerAlias()) ) {
162 SetPowerAlias(thePowerString, myAliasBegin);
163 }
164 } else if ( myParameterName == "analog" ) {
165 type[ANALOG_BIT] = true;
166 } else if ( myParameterName == "resistor" ) {
167 type[RESISTOR_BIT] = true;
168 /*
169 } else if ( myParameterName == "reference" ) {
170 type[REFERENCE_BIT] = true;
171 */
172 } else if ( myParameterName == "open" ) {
173 type[HIZ_BIT] = true;
174 simVoltage = UNKNOWN_VOLTAGE;
175 } else if ( IsValidVoltage_(myParameterName) ) { // voltage
176 simVoltage = String_to_Voltage(myParameterName);
177 maxVoltage = simVoltage;
178 minVoltage = simVoltage;
179 } else if ( thePowerMacroPtrMap.count(myParameterName) > 0 ) { // macro
180 minVoltage = thePowerMacroPtrMap[myParameterName]->minVoltage;
181 maxVoltage = thePowerMacroPtrMap[myParameterName]->maxVoltage;
182 simVoltage = thePowerMacroPtrMap[myParameterName]->simVoltage;
183 myImplicitFamily += "," + myParameterName;
184 if ( ! IsEmpty(thePowerMacroPtrMap[myParameterName]->family()) ) {
185 myImplicitFamily += "," + thePowerMacroPtrMap[myParameterName]->family();
186 }
187 if ( thePowerMacroPtrMap[myParameterName]->extraData ) {
188 if (! extraData) extraData = new CExtraPowerData;
189 extraData->expectedMin = thePowerMacroPtrMap[myParameterName]->expectedMin();
190 extraData->expectedMax = thePowerMacroPtrMap[myParameterName]->expectedMax();
191 extraData->expectedSim = thePowerMacroPtrMap[myParameterName]->expectedSim();
192 extraData->family = thePowerMacroPtrMap[myParameterName]->family();
193 }
194 relativeFriendly = thePowerMacroPtrMap[myParameterName]->relativeFriendly;
195 type[HIZ_BIT] = thePowerMacroPtrMap[myParameterName]->type[HIZ_BIT];
196 extraData->powerAlias = CPower::powerDefinitionText.SetTextAddress((text_t)myParameterName.c_str());
197 } else { // formula
198 simVoltage = thePowerMacroPtrMap.CalculateVoltage(myParameterName, SIM_POWER, theModelListMap);
199 maxVoltage = thePowerMacroPtrMap.CalculateVoltage(myParameterName, MAX_POWER, theModelListMap);
200 minVoltage = thePowerMacroPtrMap.CalculateVoltage(myParameterName, MIN_POWER, theModelListMap);
201 myImplicitFamily += thePowerMacroPtrMap.implicitFamily;
202 }
203 }
204 }
205 definition = CPower::powerDefinitionText.SetTextAddress((text_t)myDefinition.c_str());
206 if ( type[HIZ_BIT] ) {
207 if ( IsEmpty(extraData->family) ) extraData->family = "cvc-noleak";
208 }
209 if ( myImplicitFamily != "" ) {
210 extraData->implicitFamily = myImplicitFamily.substr(1); // ,net1,net2 -> net1,net2
211 }
212 }
213
CPower(netId_t theNetId)214 CPower::CPower(netId_t theNetId) {
215 // generic Power pointer for resistor propagation and calculated nets
216 powerId = powerCount++;
217 // powerSignal = "theNetName"; // TODO: Check literal
218 // simVoltage = theNewVoltage;
219 // maxVoltage = theNewVoltage;
220 // minVoltage = theNewVoltage;
221 netId = theNetId;
222 // type[RESISTOR_BIT] = true;
223 // type[MIN_CALCULATED_BIT] = true;
224 // type[SIM_CALCULATED_BIT] = true;
225 // type[MAX_CALCULATED_BIT] = true;
226 definition = CPower::powerDefinitionText.BlankTextAddress();
227 }
228
CPower(netId_t theNetId,voltage_t theSimVoltage,bool theCreateExtraData)229 CPower::CPower(netId_t theNetId, voltage_t theSimVoltage, bool theCreateExtraData) {
230 // for set sim level to thePowerNetId
231 powerId = powerCount++;
232 // powerSignal = "theNetName"; // TODO: Check literal
233 simVoltage = theSimVoltage;
234 // maxVoltage = theNewVoltage;
235 // minVoltage = theNewVoltage;
236 netId = theNetId;
237 // type[RESISTOR_BIT] = true;
238 // type[MIN_CALCULATED_BIT] = true;
239 // type[SIM_CALCULATED_BIT] = true;
240 // type[MAX_CALCULATED_BIT] = true;
241 flagAllShorts = true;
242 simCalculationType = ESTIMATED_CALCULATION;
243 definition = CPower::powerDefinitionText.BlankTextAddress();
244 if ( theCreateExtraData ) extraData = new CExtraPowerData;
245 }
246
CPower(netId_t theNetId,voltage_t theMinVoltage,voltage_t theSimVoltage,voltage_t theMaxVoltage,netId_t theDefaultMinNet,netId_t theDefaultSimNet,netId_t theDefaultMaxNet)247 CPower::CPower(netId_t theNetId, voltage_t theMinVoltage, voltage_t theSimVoltage, voltage_t theMaxVoltage, netId_t theDefaultMinNet, netId_t theDefaultSimNet, netId_t theDefaultMaxNet) {
248 powerId = powerCount++;
249 // powerSignal = "";
250 simVoltage = theSimVoltage;
251 maxVoltage = theMaxVoltage;
252 minVoltage = theMinVoltage;
253 defaultMinNet = theDefaultMinNet;
254 defaultSimNet = theDefaultSimNet;
255 defaultMaxNet = theDefaultMaxNet;
256 netId = theNetId;
257 definition = CPower::powerDefinitionText.BlankTextAddress();
258 // type set in calling routine
259 // type[MIN_CALCULATED_BIT] = true;
260 // type[SIM_CALCULATED_BIT] = true;
261 // type[MAX_CALCULATED_BIT] = true;
262 }
263
~CPower()264 CPower::~CPower() {
265 if ( extraData ) delete extraData;
266 }
267
SetPowerAlias(string thePowerString,size_t theAliasStart)268 void CPower::SetPowerAlias(string thePowerString, size_t theAliasStart) {
269 size_t myLastHierarchy = string(powerSignal()).find_last_of(HIERARCHY_DELIMITER);
270 string myPowerAlias = "";
271 if ( theAliasStart < thePowerString.length() ) {
272 size_t myAliasEnd = thePowerString.find_first_of(" \t", theAliasStart);
273 myPowerAlias = thePowerString.substr(theAliasStart + 2, myAliasEnd - theAliasStart - 2);
274 } else if ( myLastHierarchy < strlen(powerSignal()) ) {
275 if ( myLastHierarchy == 0 ) { // only set default powerAlias for top signals
276 myPowerAlias = string(powerSignal()).substr(myLastHierarchy + 1);
277 }
278 } else {
279 myPowerAlias = string(powerSignal());
280 }
281 size_t myBusStart = myPowerAlias.find_first_of("{[(<");
282 if ( myBusStart < myPowerAlias.length() ) {
283 myPowerAlias = myPowerAlias.substr(0, myBusStart);
284 }
285 extraData->powerAlias = CPower::powerDefinitionText.SetTextAddress((text_t)myPowerAlias.c_str());
286 }
287
IsSamePower(CPower * theMatchPower)288 bool CPower::IsSamePower(CPower * theMatchPower) {
289 return ( type == theMatchPower->type &&
290 minVoltage == theMatchPower->minVoltage &&
291 simVoltage == theMatchPower->simVoltage &&
292 maxVoltage == theMatchPower->maxVoltage &&
293 expectedMin() == theMatchPower->expectedMin() &&
294 expectedSim() == theMatchPower->expectedSim() &&
295 expectedMax() == theMatchPower->expectedMax() &&
296 family() == theMatchPower->family() &&
297 relativeFriendly == theMatchPower->relativeFriendly);
298 }
299
IsValidSubset(CPower * theMatchPower,voltage_t theThreshold)300 bool CPower::IsValidSubset(CPower * theMatchPower, voltage_t theThreshold) {
301 return ( (theMatchPower->type == NO_TYPE || (type[POWER_BIT] && theMatchPower->type[INPUT_BIT]) ) &&
302 (theMatchPower->minVoltage == UNKNOWN_VOLTAGE || abs(minVoltage - theMatchPower->minVoltage) <= theThreshold) &&
303 (theMatchPower->simVoltage == UNKNOWN_VOLTAGE || abs(simVoltage - theMatchPower->simVoltage) <= theThreshold) &&
304 (theMatchPower->maxVoltage == UNKNOWN_VOLTAGE || abs(maxVoltage - theMatchPower->maxVoltage) <= theThreshold) &&
305 theMatchPower->expectedMin() == "" &&
306 theMatchPower->expectedSim() == "" &&
307 theMatchPower->expectedMax() == "" &&
308 IsRelative(theMatchPower, true, false));
309 }
310
AddFamily(string thePowerString)311 void CPowerFamilyMap::AddFamily(string thePowerString) {
312 // Valid power family definitions
313 // family vdd VDD,VSS,... <- family definition
314 // sanity checks
315 string myFamilyName;
316 string myRelativeName;
317 size_t myStringBegin = thePowerString.find_first_not_of(" \t");
318 size_t myStringEnd = thePowerString.find_first_of(" \t", myStringBegin);
319 assert(thePowerString.substr(myStringBegin, myStringEnd - myStringBegin) == "family");
320 myStringBegin = thePowerString.find_first_not_of(" \t", myStringEnd);
321 myStringEnd = thePowerString.find_first_of(" \t", myStringBegin);
322 myFamilyName = thePowerString.substr(myStringBegin, myStringEnd - myStringBegin);
323 string myDefinition = thePowerString.substr(myStringEnd);
324 if ( this->count(myFamilyName) ) {
325 if ( definition != myDefinition ) {
326 cout << "DEBUG: duplicate family definition " << myFamilyName << " original " << definition << " new " << myDefinition << endl;
327 assert(definition == myDefinition);
328 }
329 return;
330 }
331 while (myStringEnd < thePowerString.length()) {
332 myStringBegin = thePowerString.find_first_not_of(", \t", myStringEnd);
333 myStringEnd = thePowerString.find_first_of(",", myStringBegin);
334 if ( myStringBegin < myStringEnd ) {
335 myRelativeName = thePowerString.substr(myStringBegin, myStringEnd - myStringBegin);
336 (*this)[myFamilyName].insert(CPower::powerDefinitionText.SetTextAddress((text_t)myRelativeName.c_str()));
337 }
338 }
339 }
340
GetBasePower(CPowerPtrVector & theNetVoltagePtr_v,CVirtualNetVector & theNet_v)341 CPower * CPower::GetBasePower(CPowerPtrVector & theNetVoltagePtr_v, CVirtualNetVector & theNet_v) {
342 CPower * myPower_p = this;
343 netId_t myNetId = netId;
344 netId_t myDefaultNet = UNKNOWN_NET;
345 while ( myPower_p && ( myPower_p->type[theNet_v.calculatedBit] || myNetId != theNet_v[myNetId].nextNetId ) ) {
346 switch ( theNet_v.calculatedBit ) {
347 case MIN_CALCULATED_BIT: { myDefaultNet = myPower_p->defaultMinNet; break; }
348 case SIM_CALCULATED_BIT: { myDefaultNet = myPower_p->defaultSimNet; break; }
349 case MAX_CALCULATED_BIT: { myDefaultNet = myPower_p->defaultMaxNet; break; }
350 default: break;
351 }
352 if ( myPower_p->type[theNet_v.calculatedBit] ) {
353 if ( myDefaultNet != UNKNOWN_NET ) {
354 myNetId = myDefaultNet;
355 } else if ( myNetId == theNet_v[myNetId].nextNetId ) { // no default net at master net
356 break;
357 }
358 }
359 while ( myNetId != theNet_v[myNetId].nextNetId ) {
360 myNetId = theNet_v[myNetId].nextNetId;
361 }
362 myPower_p = theNetVoltagePtr_v[myNetId].full;
363 }
364 return(myPower_p);
365 }
366
IsRelative(CPower * theTestPower_p,bool theDefault,bool theIsHiZRelative)367 bool CPower::IsRelative(CPower * theTestPower_p, bool theDefault, bool theIsHiZRelative) {
368 if ( ! theTestPower_p ) return theDefault;
369 if ( theIsHiZRelative && (type[HIZ_BIT] || theTestPower_p->type[HIZ_BIT]) ) return true; // HiZ is always family for certain checks
370
371 CSet emptySet;
372 CSet & myRelativeSet = (extraData) ? extraData->relativeSet : emptySet;
373 CSet & myTestRelativeSet = (theTestPower_p->extraData) ? theTestPower_p->extraData->relativeSet : emptySet;
374 if ( myRelativeSet.empty() && myTestRelativeSet.empty() ) return theDefault;
375 bool myFriend = false, myEnemy = false, myTestFriend = false, myTestEnemy = false;
376 bool myHasFriends = false, myHasEnemies = false, myTestHasFriends = false, myTestHasEnemies = false;
377 // relative sets are for explicit and implicit connections. explicit overrides implicit. only check if explicit definition exists. ie implicit, test->implicit -> no check
378
379 if ( ! IsEmpty(family()) ) {
380 bool myRelation = ( myRelativeSet.count(theTestPower_p->powerSignal())
381 || myRelativeSet.count(theTestPower_p->powerAlias())
382 || ( ! myTestRelativeSet.empty()
383 && myRelativeSet.Intersects(myTestRelativeSet) ) );
384 if ( relativeFriendly ) {
385 myHasFriends = true;
386 myFriend = myRelation;
387 } else {
388 myHasEnemies = true;
389 myEnemy = myRelation;
390 }
391 }
392 if ( ! IsEmpty(theTestPower_p->family()) ) {
393 bool myRelation = ( myTestRelativeSet.count(powerSignal())
394 || myTestRelativeSet.count(powerAlias())
395 || ( ! myRelativeSet.empty()
396 && myTestRelativeSet.Intersects(myRelativeSet) ) );
397 if ( theTestPower_p->relativeFriendly ) {
398 myTestHasFriends = true;
399 myTestFriend = myRelation;
400 } else {
401 myTestHasEnemies = true;
402 myTestEnemy = myRelation;
403 }
404 }
405 if ( myHasFriends && myTestHasFriends ) return ( myFriend || myTestFriend );
406 if ( myHasFriends && myTestHasEnemies ) {
407 if ( myTestEnemy ) return false;
408 if ( myFriend ) return true;
409 return theDefault;
410 }
411 if ( myHasEnemies && myTestHasFriends ) {
412 if ( myEnemy ) return false;
413 if ( myTestFriend ) return true;
414 return theDefault;
415 }
416 if ( myHasEnemies && myTestHasEnemies ) return ! ( myEnemy || myTestEnemy );
417 if ( myHasFriends ) return myFriend;
418 if ( myHasEnemies ) return ! myEnemy;
419 if ( myTestHasFriends ) return myTestFriend;
420 /*if ( myTestHasEnemies )*/ return ! myTestEnemy;
421 }
422
IsRelatedPower(CPower * theTestPower_p,CPowerPtrVector & theNetVoltagePtr_v,CVirtualNetVector & theNet_v,CVirtualNetVector & theTestNet_v,bool theDefault,bool theIsHiZRelative)423 bool CPower::IsRelatedPower(CPower * theTestPower_p, CPowerPtrVector & theNetVoltagePtr_v, CVirtualNetVector & theNet_v, CVirtualNetVector & theTestNet_v,
424 bool theDefault, bool theIsHiZRelative) {
425 if ( ! theTestPower_p ) return theDefault;
426 CPower * myPower_p = GetBasePower(theNetVoltagePtr_v, theNet_v);
427 CPower * myTestPower_p = theTestPower_p->GetBasePower(theNetVoltagePtr_v, theTestNet_v);
428 assert( myPower_p && myTestPower_p );
429 if ( myPower_p == myTestPower_p ) return true;
430 if ( ! IsEmpty(myPower_p->powerAlias())
431 && (myPower_p->powerAlias() == myTestPower_p->powerAlias() || myPower_p->powerAlias() == myTestPower_p->powerSignal()) ) return true;
432 if ( ! IsEmpty(myTestPower_p->powerAlias()) && myTestPower_p->powerAlias() == myPower_p->powerSignal()) return true;
433 return myPower_p->IsRelative(myTestPower_p, theDefault, theIsHiZRelative);
434 }
435
Print(ostream & theLogFile,string theIndentation,string theRealPowerName)436 void CPower::Print(ostream & theLogFile, string theIndentation, string theRealPowerName) {
437 if ( IsEmpty(theRealPowerName) || theRealPowerName == string(powerSignal()) ) {
438 string myAlias = ( IsEmpty(powerAlias()) || powerSignal() == powerAlias() ) ? "" : ALIAS_DELIMITER + string(powerAlias());
439 theLogFile << theIndentation << powerSignal() << myAlias;
440 } else { // expanded net names
441 theLogFile << theIndentation << "->" << theRealPowerName;
442 }
443 string myDefinition = StandardDefinition();
444 theLogFile << definition; // for defined voltages
445 if ( ! IsEmpty(myDefinition) && myDefinition != string(definition) ) {
446 theLogFile << (IsCalculatedVoltage_(this) ? " =>" : " ->") << myDefinition;
447 }
448 if ( extraData && ! extraData->relativeSet.empty() ) {
449 theLogFile << " family(";
450 for ( auto relative_it = extraData->relativeSet.begin(); relative_it != extraData->relativeSet.end(); relative_it++ ) {
451 theLogFile << *relative_it << ";";
452 }
453 theLogFile << ")";
454 }
455 theLogFile << endl;
456 }
457
StandardDefinition()458 string CPower::StandardDefinition() {
459 stringstream myDefinition;
460 if ( simVoltage != UNKNOWN_VOLTAGE && minVoltage == simVoltage && simVoltage == maxVoltage && type[POWER_BIT] ) {
461 myDefinition << " " << PrintParameter(minVoltage, VOLTAGE_SCALE);
462 } else {
463 if ( minVoltage != UNKNOWN_VOLTAGE ) myDefinition << " min" << (type[MIN_CALCULATED_BIT] ? "=" : "@") << PrintParameter(minVoltage, VOLTAGE_SCALE);
464 if ( simVoltage != UNKNOWN_VOLTAGE ) myDefinition << " sim" << (type[SIM_CALCULATED_BIT] ? "=" : "@") << PrintParameter(simVoltage, VOLTAGE_SCALE);
465 if ( maxVoltage != UNKNOWN_VOLTAGE ) myDefinition << " max" << (type[MAX_CALCULATED_BIT] ? "=" : "@") << PrintParameter(maxVoltage, VOLTAGE_SCALE);
466 }
467 if ( ! IsEmpty(expectedMin()) ) myDefinition << " expectMin@" << expectedMin();
468 if ( ! IsEmpty(expectedSim()) ) myDefinition << " expectSim@" << expectedSim();
469 if ( ! IsEmpty(expectedMax()) ) myDefinition << " expectMax@" << expectedMax();
470 if ( type[HIZ_BIT] ) myDefinition << " open";
471 if ( type[INPUT_BIT] ) myDefinition << " input";
472 if ( type[POWER_BIT] ) myDefinition << " power";
473 if ( type[RESISTOR_BIT] ) myDefinition << " resistor";
474 if ( ! IsEmpty(family()) ) myDefinition << (relativeFriendly ? " permit@" : " prohibit@") << family();
475 return(myDefinition.str());
476 }
477
MaxVoltage(netId_t theNetId)478 voltage_t CPowerPtrVector::MaxVoltage(netId_t theNetId) {
479 if ( theNetId == UNKNOWN_NET ) return UNKNOWN_VOLTAGE;
480 if ( (*this)[theNetId].full == NULL ) return UNKNOWN_VOLTAGE;
481 return (*this)[theNetId].full->maxVoltage;
482 }
483
MinVoltage(netId_t theNetId)484 voltage_t CPowerPtrVector::MinVoltage(netId_t theNetId) {
485 if ( theNetId == UNKNOWN_NET ) return UNKNOWN_VOLTAGE;
486 if ( (*this)[theNetId].full == NULL ) return UNKNOWN_VOLTAGE;
487 return (*this)[theNetId].full->minVoltage;
488 }
489
SimVoltage(netId_t theNetId)490 voltage_t CPowerPtrVector::SimVoltage(netId_t theNetId) {
491 if ( theNetId == UNKNOWN_NET ) return UNKNOWN_VOLTAGE;
492 if ( (*this)[theNetId].full == NULL ) return UNKNOWN_VOLTAGE;
493 return (*this)[theNetId].full->simVoltage;
494 }
495
Clear()496 void CPowerPtrList::Clear() {
497 while ( ! empty() ) {
498 delete front();
499 pop_front();
500 }
501 }
502
Clear(CPowerPtrVector & theLeakVoltage_v,CPowerPtrVector & theNetVoltage_v,netId_t theNetCount)503 void CPowerPtrList::Clear(CPowerPtrVector & theLeakVoltage_v, CPowerPtrVector & theNetVoltage_v, netId_t theNetCount) {
504 while ( ! empty() ) {
505 netId_t myNetId = front()->netId;
506 if ( myNetId != UNKNOWN_NET && theNetCount > 0 ) {
507 if ( theLeakVoltage_v.size() > myNetId && theLeakVoltage_v[myNetId].full && theLeakVoltage_v[myNetId].full == front() ) {
508 theLeakVoltage_v[myNetId].full = NULL;
509 }
510 if ( theNetVoltage_v.size() > myNetId && theNetVoltage_v[myNetId].full && theNetVoltage_v[myNetId].full == front() ) {
511 theNetVoltage_v[myNetId].full = NULL;
512 }
513 }
514 delete front();
515 pop_front();
516 }
517 CPower::powerDefinitionText.Clear();
518 }
519
Clear()520 void CPowerPtrMap::Clear() {
521 while ( ! empty() ) {
522 delete begin()->second;
523 erase(begin());
524 }
525 }
526
SetPowerLimits(voltage_t & theMaxPower,voltage_t & theMinPower)527 void CPowerPtrList::SetPowerLimits(voltage_t& theMaxPower, voltage_t& theMinPower) {
528 theMaxPower = MIN_VOLTAGE;
529 theMinPower = MAX_VOLTAGE;
530 for ( CPowerPtrList::iterator power_ppit = begin(); power_ppit != end(); power_ppit++ ) {
531 theMinPower = min(theMinPower, (*power_ppit)->minVoltage);
532 theMaxPower = max(theMaxPower, (*power_ppit)->maxVoltage);
533 }
534 }
535
536 /*
537 CPower * CPowerPtrList::FindCalculatedPower(CEventQueue& theEventQueue, CPower * theCurrentPower_p, voltage_t theShortVoltage, netId_t theNetId, netId_t theDefaultNetId, CCvcDb * theCvcDb_p) {
538 voltage_t myMinVoltage = UNKNOWN_VOLTAGE, mySimVoltage = UNKNOWN_VOLTAGE, myMaxVoltage = UNKNOWN_VOLTAGE;
539 netId_t myDefaultMinNet = UNKNOWN_NET, myDefaultSimNet = UNKNOWN_NET, myDefaultMaxNet = UNKNOWN_NET;
540 CPower * myPower_p;
541 CStatus myStatus = 0;
542 if ( theCurrentPower_p ) {
543 myMinVoltage = theCurrentPower_p->minVoltage;
544 myMaxVoltage = theCurrentPower_p->maxVoltage;
545 mySimVoltage = theCurrentPower_p->simVoltage;
546 myStatus = theCurrentPower_p->type;
547 }
548 if ( theEventQueue.queueType == MIN_QUEUE ) {
549 if ( myMinVoltage != UNKNOWN_VOLTAGE ) throw EDatabaseError("FindCalculatedPower: Min " + to_string<voltage_t>(myMinVoltage));
550 myMinVoltage = theShortVoltage;
551 myDefaultMinNet = theDefaultNetId;
552 myStatus[MIN_CALCULATED_BIT] = true;
553 }
554 if ( theEventQueue.queueType == MAX_QUEUE ) {
555 if ( myMaxVoltage != UNKNOWN_VOLTAGE ) throw EDatabaseError("FindCalculatedPower: Max " + to_string<voltage_t>(myMaxVoltage));
556 myMaxVoltage = theShortVoltage;
557 myDefaultMaxNet = theDefaultNetId;
558 myStatus[MAX_CALCULATED_BIT] = true;
559 }
560 if ( theEventQueue.queueType == SIM_QUEUE ) {
561 if ( mySimVoltage != UNKNOWN_VOLTAGE ) throw EDatabaseError("FindCalculatedPower: Sim " + to_string<voltage_t>(mySimVoltage));
562 mySimVoltage = theShortVoltage;
563 myDefaultSimNet = theDefaultNetId;
564 myStatus[SIM_CALCULATED_BIT] = true;
565 }
566 string myKeyString = int_to_hex<voltage_t>(myMinVoltage) + int_to_hex<voltage_t>(mySimVoltage) + int_to_hex<voltage_t>(myMaxVoltage);
567 try {
568 if (myMinVoltage != UNKNOWN_VOLTAGE && mySimVoltage != UNKNOWN_VOLTAGE && myMinVoltage > mySimVoltage) {
569 cout << "WARNING: MIN > SIM " << myMinVoltage << " > " << mySimVoltage << " for " << theCvcDb_p->NetName(theNetId, PRINT_CIRCUIT_ON) << endl;
570 }
571 if (myMaxVoltage != UNKNOWN_VOLTAGE && mySimVoltage != UNKNOWN_VOLTAGE && myMaxVoltage < mySimVoltage) {
572 cout << "WARNING: MAX < SIM " << myMaxVoltage << " < " << mySimVoltage << " for " << theCvcDb_p->NetName(theNetId, PRINT_CIRCUIT_ON) << endl;
573 }
574 myPower_p = calculatedPowerPtrMap.at(myKeyString);
575 }
576 catch (const out_of_range& oor_exception) {
577 if ( debug_cvc ) cout << "DEBUG: creating power: " << myKeyString << " " << myMinVoltage << "/" << mySimVoltage << "/" << myMaxVoltage << endl;
578 myPower_p = new CPower(myMinVoltage, mySimVoltage, myMaxVoltage, myDefaultMinNet, myDefaultSimNet, myDefaultMaxNet);
579 myPower_p->type = myStatus;
580 calculatedPowerPtrMap[myKeyString] = myPower_p;
581 }
582 return(myPower_p);
583 }
584
585 CPower * CPowerPtrList::FindCalculatedPower(voltage_t theMinVoltage, voltage_t theSimVoltage, voltage_t theMaxVoltage, netId_t theNetId, CCvcDb * theCvcDb_p) {
586 CPower * myPower_p;
587 string myKeyString = int_to_hex<voltage_t>(theMinVoltage) + int_to_hex<voltage_t>(theSimVoltage) + int_to_hex<voltage_t>(theMaxVoltage);
588 try {
589 if (theMinVoltage != UNKNOWN_VOLTAGE && theSimVoltage != UNKNOWN_VOLTAGE && theMinVoltage > theSimVoltage) {
590 cout << "WARNING: MIN > SIM " << theMinVoltage << " > " << theSimVoltage << " for " << theCvcDb_p->NetName(theNetId, PRINT_CIRCUIT_ON) << endl;
591 }
592 if (theMaxVoltage != UNKNOWN_VOLTAGE && theSimVoltage != UNKNOWN_VOLTAGE && theMaxVoltage < theSimVoltage) {
593 cout << "WARNING: MAX < SIM " << theMaxVoltage << " < " << theSimVoltage << " for " << theCvcDb_p->NetName(theNetId, PRINT_CIRCUIT_ON) << endl;
594 }
595 myPower_p = calculatedPowerPtrMap.at(myKeyString);
596 }
597 catch (const out_of_range& oor_exception) {
598 if ( debug_cvc ) cout << "DEBUG: creating power: " << myKeyString << endl;
599 myPower_p = new CPower(theMinVoltage, theSimVoltage, theMaxVoltage);
600 myPower_p->type[MIN_CALCULATED_BIT] = true;
601 myPower_p->type[SIM_CALCULATED_BIT] = true;
602 myPower_p->type[MAX_CALCULATED_BIT] = true;
603 calculatedPowerPtrMap[myKeyString] = myPower_p;
604 }
605 return(myPower_p);
606 }
607 */
608
609 /*
610 // Changed 2014/7/23 to always create new Power node
611 CPower * CPowerPtrList::FindCalculatedPower(CEventQueue& theEventQueue, CPower * theCurrentPower_p, voltage_t theShortVoltage, netId_t theNetId, netId_t theDefaultNetId, CCvcDb * theCvcDb_p) {
612 voltage_t myMinVoltage = UNKNOWN_VOLTAGE, mySimVoltage = UNKNOWN_VOLTAGE, myMaxVoltage = UNKNOWN_VOLTAGE;
613 netId_t myDefaultMinNet = UNKNOWN_NET, myDefaultSimNet = UNKNOWN_NET, myDefaultMaxNet = UNKNOWN_NET;
614 CPower * myPower_p;
615 CStatus myStatus = 0, myActiveStatus = 0;
616 if ( theCurrentPower_p ) {
617 myMinVoltage = theCurrentPower_p->minVoltage;
618 myMaxVoltage = theCurrentPower_p->maxVoltage;
619 mySimVoltage = theCurrentPower_p->simVoltage;
620 myDefaultMinNet = theCurrentPower_p->defaultMinNet;
621 myDefaultMaxNet = theCurrentPower_p->defaultMaxNet;
622 myDefaultSimNet = theCurrentPower_p->defaultSimNet;
623 myStatus = theCurrentPower_p->type;
624 myActiveStatus = theCurrentPower_p->active;
625 } else {
626 myStatus[CALCULATED_BIT] = true;
627 }
628 if ( theCvcDb_p->netVoltagePtr_v[theDefaultNetId] && theCvcDb_p->netVoltagePtr_v[theDefaultNetId]->type[HIZ_BIT] ) {
629 myStatus[HIZ_BIT] = true;
630 }
631 if ( theEventQueue.queueType == MIN_QUEUE ) {
632 if ( myMinVoltage != UNKNOWN_VOLTAGE ) throw EDatabaseError("FindCalculatedPower: Min " + to_string<voltage_t>(myMinVoltage));
633 myMinVoltage = theShortVoltage;
634 myDefaultMinNet = theDefaultNetId;
635 myStatus[MIN_CALCULATED_BIT] = true;
636 myActiveStatus[MIN_ACTIVE] = true;
637 }
638 if ( theEventQueue.queueType == MAX_QUEUE ) {
639 if ( myMaxVoltage != UNKNOWN_VOLTAGE ) throw EDatabaseError("FindCalculatedPower: Max " + to_string<voltage_t>(myMaxVoltage));
640 myMaxVoltage = theShortVoltage;
641 myDefaultMaxNet = theDefaultNetId;
642 myStatus[MAX_CALCULATED_BIT] = true;
643 myActiveStatus[MAX_ACTIVE] = true;
644 }
645 if ( theEventQueue.queueType == SIM_QUEUE ) {
646 if ( mySimVoltage != UNKNOWN_VOLTAGE ) throw EDatabaseError("FindCalculatedPower: Sim " + to_string<voltage_t>(mySimVoltage));
647 mySimVoltage = theShortVoltage;
648 myDefaultSimNet = theDefaultNetId;
649 myStatus[SIM_CALCULATED_BIT] = true;
650 }
651 // string myKeyString = int_to_hex<voltage_t>(myMinVoltage) + int_to_hex<voltage_t>(mySimVoltage) + int_to_hex<voltage_t>(myMaxVoltage);
652 // try {
653 if (myMinVoltage != UNKNOWN_VOLTAGE && mySimVoltage != UNKNOWN_VOLTAGE && myMinVoltage > mySimVoltage) {
654 cout << "WARNING: MIN > SIM " << myMinVoltage << " > " << mySimVoltage << " for " << theCvcDb_p->NetName(theNetId, PRINT_CIRCUIT_ON) << endl;
655 }
656 if (myMaxVoltage != UNKNOWN_VOLTAGE && mySimVoltage != UNKNOWN_VOLTAGE && myMaxVoltage < mySimVoltage) {
657 cout << "WARNING: MAX < SIM " << myMaxVoltage << " < " << mySimVoltage << " for " << theCvcDb_p->NetName(theNetId, PRINT_CIRCUIT_ON) << endl;
658 }
659 // myPower_p = calculatedPowerPtrMap.at(myKeyString);
660 // }
661 // catch (const out_of_range& oor_exception) {
662 // if ( debug_cvc ) cout << "DEBUG: creating power: " << myKeyString << " " << myMinVoltage << "/" << mySimVoltage << "/" << myMaxVoltage << endl;
663 myPower_p = new CPower(myMinVoltage, mySimVoltage, myMaxVoltage, myDefaultMinNet, myDefaultSimNet, myDefaultMaxNet);
664 myPower_p->type = myStatus;
665 myPower_p->active = myActiveStatus;
666 // calculatedPowerPtrMap[myKeyString] = myPower_p;
667 // }
668 return(myPower_p);
669 }
670 */
671
ResetPowerPointerVector(size_t theSize)672 void CPowerPtrVector::ResetPowerPointerVector(size_t theSize) {
673 this->clear();
674 this->reserve(theSize);
675 this->resize(theSize);
676 for ( size_t index_it = 0; index_it < theSize; index_it++ ) {
677 (*this)[index_it].full = NULL;
678 }
679 this->powerPtrType_v.clear();
680 this->powerPtrType_v.reserve(theSize);
681 this->powerPtrType_v.resize(theSize, UNKNOWN_POWER_PTR);
682 }
683
CalculatePower(CEventQueue & theEventQueue,voltage_t theShortVoltage,netId_t theNetId,netId_t theDefaultNetId,CCvcDb * theCvcDb_p,string theCalculation)684 void CPowerPtrVector::CalculatePower(CEventQueue& theEventQueue, voltage_t theShortVoltage, netId_t theNetId, netId_t theDefaultNetId, CCvcDb * theCvcDb_p, string theCalculation) {
685 if ( (*this)[theNetId].full == NULL ) {
686 (*this)[theNetId].full = new CPower(theNetId);
687 }
688 CPower * myPower_p = (*this)[theNetId].full;
689 CPower * myDefaultPower_p = (*this)[theDefaultNetId].full;
690 if ( myDefaultPower_p ) {
691 if ( myDefaultPower_p->type[HIZ_BIT] ) {
692 myPower_p->type[HIZ_BIT] = true;
693 }
694 if ( myDefaultPower_p->extraData ) {
695 if ( ! myPower_p->extraData ) myPower_p->extraData = new CExtraPowerData;
696 myPower_p->extraData->family = myDefaultPower_p->family();
697 myPower_p->extraData->implicitFamily = myDefaultPower_p->implicitFamily();
698 myPower_p->extraData->relativeSet = myDefaultPower_p->extraData->relativeSet;
699 }
700 myPower_p->relativeFriendly = myDefaultPower_p->relativeFriendly;
701 }
702 if ( theEventQueue.queueType == MIN_QUEUE ) {
703 if ( myPower_p->minVoltage != UNKNOWN_VOLTAGE ) {
704 cout << "DEBUG: CalculatePower: Min " << to_string<voltage_t>(myPower_p->minVoltage) << " at " << theCvcDb_p->NetName(theNetId) << endl;
705 //throw EDatabaseError("CalculatePower: Min " + to_string<voltage_t>(myPower_p->minVoltage) + " at " + theCvcDb_p->NetName(theNetId));
706 }
707 myPower_p->minVoltage = theShortVoltage;
708 myPower_p->defaultMinNet = theDefaultNetId;
709 myPower_p->type[MIN_CALCULATED_BIT] = true;
710 myPower_p->active[MIN_ACTIVE] = true;
711 if ( myDefaultPower_p && myDefaultPower_p->minVoltage != UNKNOWN_VOLTAGE ) {
712 if ( theShortVoltage < myDefaultPower_p->minVoltage ) {
713 myPower_p->minCalculationType = DOWN_CALCULATION;
714 } else if ( theShortVoltage > myDefaultPower_p->minVoltage ) {
715 myPower_p->minCalculationType = UP_CALCULATION;
716 }
717 }
718 }
719 if ( theEventQueue.queueType == MAX_QUEUE ) {
720 if ( myPower_p->maxVoltage != UNKNOWN_VOLTAGE ) {
721 cout << "DEBUG: CalculatePower: Max " << to_string<voltage_t>(myPower_p->maxVoltage) << " at " << theCvcDb_p->NetName(theNetId) << endl;
722 //throw EDatabaseError("CalculatePower: Max " + to_string<voltage_t>(myPower_p->maxVoltage) + " at " + theCvcDb_p->NetName(theNetId));
723 }
724 myPower_p->maxVoltage = theShortVoltage;
725 myPower_p->defaultMaxNet = theDefaultNetId;
726 myPower_p->type[MAX_CALCULATED_BIT] = true;
727 myPower_p->active[MAX_ACTIVE] = true;
728 if ( myDefaultPower_p && myDefaultPower_p->maxVoltage != UNKNOWN_VOLTAGE ) {
729 if ( theShortVoltage < myDefaultPower_p->maxVoltage ) {
730 myPower_p->maxCalculationType = DOWN_CALCULATION;
731 } else if ( theShortVoltage > myDefaultPower_p->maxVoltage ) {
732 myPower_p->maxCalculationType = UP_CALCULATION;
733 }
734 }
735 }
736 if ( theEventQueue.queueType == SIM_QUEUE ) {
737 if ( myPower_p->simVoltage != UNKNOWN_VOLTAGE ) {
738 throw EDatabaseError("CalculatePower: Sim " + to_string<voltage_t>(myPower_p->simVoltage) + " at " + theCvcDb_p->NetName(theNetId));
739 }
740 myPower_p->simVoltage = theShortVoltage;
741 myPower_p->defaultSimNet = theDefaultNetId;
742 myPower_p->type[SIM_CALCULATED_BIT] = true;
743 if ( myPower_p->powerAlias()[0] == '\0' ) {
744 CPower * myDefaultPower_p;
745 if ( myPower_p->minVoltage == myPower_p->simVoltage ) {
746 myDefaultPower_p = myPower_p->GetBasePower(theCvcDb_p->netVoltagePtr_v, theCvcDb_p->minNet_v);
747 } else if ( myPower_p->maxVoltage == myPower_p->simVoltage ) {
748 myDefaultPower_p = myPower_p->GetBasePower(theCvcDb_p->netVoltagePtr_v, theCvcDb_p->maxNet_v);
749 } else {
750 myDefaultPower_p = myPower_p->GetBasePower(theCvcDb_p->netVoltagePtr_v, theCvcDb_p->simNet_v);
751 }
752 if ( myDefaultPower_p && ! IsEmpty(myDefaultPower_p->powerAlias()) ) {
753 if (gDebug_cvc) cout << "Setting alias for " << theCvcDb_p->NetName(theNetId) << " = " << myDefaultPower_p->powerAlias() << endl;
754 if ( ! myPower_p->extraData ) myPower_p->extraData = new CExtraPowerData;
755 myPower_p->extraData->powerAlias = myDefaultPower_p->powerAlias();
756 }
757 }
758 if ( myDefaultPower_p && myDefaultPower_p->simVoltage != UNKNOWN_VOLTAGE ) {
759 if ( theShortVoltage < myDefaultPower_p->simVoltage ) {
760 myPower_p->simCalculationType = DOWN_CALCULATION;
761 } else if ( theShortVoltage > myDefaultPower_p->simVoltage ) {
762 myPower_p->simCalculationType = UP_CALCULATION;
763 }
764 }
765
766 }
767 if (myPower_p->minVoltage != UNKNOWN_VOLTAGE && myPower_p->simVoltage != UNKNOWN_VOLTAGE && myPower_p->minVoltage > myPower_p->simVoltage) {
768 cout << "WARNING: MIN > SIM " << myPower_p->minVoltage << " > " << myPower_p->simVoltage << " for " << theCvcDb_p->NetName(theNetId, PRINT_CIRCUIT_ON) << endl;
769 }
770 if (myPower_p->maxVoltage != UNKNOWN_VOLTAGE && myPower_p->simVoltage != UNKNOWN_VOLTAGE && myPower_p->maxVoltage < myPower_p->simVoltage) {
771 cout << "WARNING: MAX < SIM " << myPower_p->maxVoltage << " < " << myPower_p->simVoltage << " for " << theCvcDb_p->NetName(theNetId, PRINT_CIRCUIT_ON) << endl;
772 }
773 if ( myPower_p->definition[0] == '\0' ) {
774 myPower_p->definition = CPower::powerDefinitionText.SetTextAddress((text_t)theCalculation.c_str());
775 }
776 if (gDebug_cvc) cout << "INFO: Calculated voltage at net " << myPower_p->netId << " default Min/Sim/Max: " << myPower_p->defaultMinNet << "/"
777 << myPower_p->defaultSimNet << "/" << myPower_p->defaultMaxNet << endl;
778 }
779
780 /*
781 CPower * CPowerPtrList::FindCalculatedPower(voltage_t theMinVoltage, voltage_t theSimVoltage, voltage_t theMaxVoltage, netId_t theNetId, CCvcDb * theCvcDb_p) {
782 CPower * myPower_p;
783 // string myKeyString = int_to_hex<voltage_t>(theMinVoltage) + int_to_hex<voltage_t>(theSimVoltage) + int_to_hex<voltage_t>(theMaxVoltage);
784 // try {
785 if (theMinVoltage != UNKNOWN_VOLTAGE && theSimVoltage != UNKNOWN_VOLTAGE && theMinVoltage > theSimVoltage) {
786 cout << "WARNING: MIN > SIM " << theMinVoltage << " > " << theSimVoltage << " for " << theCvcDb_p->NetName(theNetId, PRINT_CIRCUIT_ON) << endl;
787 }
788 if (theMaxVoltage != UNKNOWN_VOLTAGE && theSimVoltage != UNKNOWN_VOLTAGE && theMaxVoltage < theSimVoltage) {
789 cout << "WARNING: MAX < SIM " << theMaxVoltage << " < " << theSimVoltage << " for " << theCvcDb_p->NetName(theNetId, PRINT_CIRCUIT_ON) << endl;
790 }
791 // myPower_p = calculatedPowerPtrMap.at(myKeyString);
792 // }
793 // catch (const out_of_range& oor_exception) {
794 // if ( debug_cvc ) cout << "DEBUG: creating power: " << myKeyString << endl;
795 myPower_p = new CPower(theMinVoltage, theSimVoltage, theMaxVoltage);
796 myPower_p->type[MIN_CALCULATED_BIT] = true;
797 myPower_p->type[SIM_CALCULATED_BIT] = true;
798 myPower_p->type[MAX_CALCULATED_BIT] = true;
799 // calculatedPowerPtrMap[myKeyString] = myPower_p;
800 // }
801 return(myPower_p);
802 }
803 */
804
SetFamilies(CPowerFamilyMap & thePowerFamilyMap)805 void CPowerPtrList::SetFamilies(CPowerFamilyMap & thePowerFamilyMap) {
806 string myFamilyName;
807 string myRelativeName;
808 string myFamilyList;
809 string myImplicitFamilyList;
810 size_t myStringBegin;
811 size_t myStringEnd;
812 for ( CPowerPtrList::iterator powerPtr_ppit = begin(); powerPtr_ppit != end(); powerPtr_ppit++ ) {
813 myFamilyList = (*powerPtr_ppit)->family();
814 myImplicitFamilyList = (*powerPtr_ppit)->implicitFamily();
815 if ( ! IsEmpty(myFamilyList) ) {
816 myStringBegin = myFamilyList.find_first_not_of(",", 0);
817 myStringEnd = myFamilyList.find_first_of(",", myStringBegin);
818 if ( ! (*powerPtr_ppit)->extraData ) (*powerPtr_ppit)->extraData = new CExtraPowerData;
819 while (myStringBegin < myFamilyList.length()) {
820 myRelativeName = myFamilyList.substr(myStringBegin, myStringEnd - myStringBegin);
821 if ( thePowerFamilyMap.count(myRelativeName) > 0 ) {
822 (*powerPtr_ppit)->extraData->relativeSet.insert(thePowerFamilyMap[myRelativeName].begin(), thePowerFamilyMap[myRelativeName].end());
823 } else {
824 (*powerPtr_ppit)->extraData->relativeSet.insert(CPower::powerDefinitionText.SetTextAddress((text_t)myRelativeName.c_str()));
825 }
826 myStringBegin = myFamilyList.find_first_not_of(",", myStringEnd);
827 myStringEnd = myFamilyList.find_first_of(",", myStringBegin);
828 }
829 // explicit family list overrides implicit list
830 } else if ( ! IsEmpty(myImplicitFamilyList) ) {
831 myStringBegin = myImplicitFamilyList.find_first_not_of(",", 0);
832 myStringEnd = myImplicitFamilyList.find_first_of(",", myStringBegin);
833 if ( ! (*powerPtr_ppit)->extraData ) (*powerPtr_ppit)->extraData = new CExtraPowerData;
834 while (myStringBegin < myImplicitFamilyList.length()) {
835 myRelativeName = myImplicitFamilyList.substr(myStringBegin, myStringEnd - myStringBegin);
836 if ( thePowerFamilyMap.count(myRelativeName) > 0 ) {
837 (*powerPtr_ppit)->extraData->relativeSet.insert(thePowerFamilyMap[myRelativeName].begin(), thePowerFamilyMap[myRelativeName].end());
838 } else {
839 (*powerPtr_ppit)->extraData->relativeSet.insert(CPower::powerDefinitionText.SetTextAddress((text_t)myRelativeName.c_str()));
840 }
841 myStringBegin = myImplicitFamilyList.find_first_not_of(",", myStringEnd);
842 myStringEnd = myImplicitFamilyList.find_first_of(",", myStringBegin);
843 }
844 }
845 }
846 }
847
PowerDefinition()848 string CPower::PowerDefinition() {
849 string myPowerDefinition = "";
850 if ( minVoltage != UNKNOWN_VOLTAGE ) myPowerDefinition += " min" + ( ((type[MIN_CALCULATED_BIT]) ? "=" : "@") + to_string<voltage_t>(minVoltage));
851 if ( simVoltage != UNKNOWN_VOLTAGE ) myPowerDefinition += " sim" + ( ((type[SIM_CALCULATED_BIT]) ? "=" : "@") + to_string<voltage_t>(simVoltage));
852 if ( maxVoltage != UNKNOWN_VOLTAGE ) myPowerDefinition += " max" + ( ((type[MAX_CALCULATED_BIT]) ? "=" : "@") + to_string<voltage_t>(maxVoltage));
853 if ( ! IsEmpty(expectedMin()) ) myPowerDefinition += " min?" + expectedMin();
854 if ( ! IsEmpty(expectedSim()) ) myPowerDefinition += " sim?" + expectedSim();
855 if ( ! IsEmpty(expectedMax()) ) myPowerDefinition += " max?" + expectedMax();
856 if ( type[HIZ_BIT] ) myPowerDefinition += " open";
857 if ( type[INPUT_BIT] ) myPowerDefinition += " input";
858 if ( type[RESISTOR_BIT] ) myPowerDefinition += " resistor";
859 // if ( definition != "" ) myPowerDefinition += " '" + definition + "'";
860 if ( ! IsEmpty(family()) ) myPowerDefinition += " '" + family() + ((relativeFriendly) ? " allowed'" : " prohibited'");
861 return myPowerDefinition;
862 }
863
CalculateExpectedValue(string theEquation,netStatus_t theType,CModelListMap & theModelListMap)864 string CPowerPtrMap::CalculateExpectedValue(string theEquation, netStatus_t theType, CModelListMap & theModelListMap) {
865 if ( theEquation == "open" ) return theEquation;
866 if ( this->count(theEquation) > 0 ) return theEquation;
867 if ( IsValidVoltage_(theEquation) ) return theEquation;
868 voltage_t myVoltage = CalculateVoltage(theEquation, theType, theModelListMap);
869 return(to_string<float>(float(myVoltage) / VOLTAGE_SCALE));
870 }
871
872 #define UNKNOWN_TOKEN (float(MAX_VOLTAGE) * 2)
CalculateVoltage(string theEquation,netStatus_t theType,CModelListMap & theModelListMap,bool thePermitUndefinedFlag,bool theResetImplicitFlag)873 voltage_t CPowerPtrMap::CalculateVoltage(string theEquation, netStatus_t theType, CModelListMap & theModelListMap, bool thePermitUndefinedFlag, bool theResetImplicitFlag) {
874 if ( theResetImplicitFlag) implicitFamily = "";
875 list<string> * myTokenList_p;
876 // exceptions cause memory leaks
877 if ( IsValidVoltage_(theEquation) ) {
878 myTokenList_p = new(list<string>);
879 myTokenList_p->push_back(theEquation);
880 } else {
881 myTokenList_p = postfix(theEquation);
882 }
883 list<float> myVoltageStack;
884 float myVoltage;
885 string myOperators = "+-/*<>";
886 for ( auto token_pit = myTokenList_p->begin(); token_pit != myTokenList_p->end(); token_pit++ ) {
887 if ( myOperators.find(*token_pit) < myOperators.length() ) {
888 if ( myVoltageStack.size() < 2 ) throw EPowerError("invalid equation: " + theEquation);
889 myVoltage = myVoltageStack.back();
890 myVoltageStack.pop_back();
891 if ( myVoltage == UNKNOWN_TOKEN ) {
892 if ( ( *token_pit == "<" ) || ( *token_pit == ">" ) ) { // min/max keep value on stack
893 ;
894 } else { // arithmetic with invalid values gives invalid value
895 myVoltageStack.back() = UNKNOWN_TOKEN;
896 }
897 } else if ( myVoltageStack.back() == UNKNOWN_TOKEN ) {
898 if ( ( *token_pit == "<" ) || ( *token_pit == ">" ) ) { // min/max replace with last voltage
899 myVoltageStack.back() = myVoltage;
900 }
901 } else if ( *token_pit == "+" ) {
902 myVoltageStack.back() += myVoltage;
903 } else if ( *token_pit == "-" ) {
904 myVoltageStack.back() -= myVoltage;
905 } else if ( *token_pit == "*" ) {
906 myVoltageStack.back() *= myVoltage;
907 } else if ( *token_pit == "/" ) {
908 myVoltageStack.back() /= myVoltage;
909 } else if ( *token_pit == "<" ) {
910 myVoltageStack.back() = min(myVoltageStack.back(), myVoltage);
911 } else if ( *token_pit == ">" ) {
912 myVoltageStack.back() = max(myVoltageStack.back(), myVoltage);
913 } else throw EPowerError("invalid operator: " + *token_pit);
914 } else if ( isalpha((*token_pit)[0]) ) { // power name
915 if ( this->count(*token_pit) > 0 ) { // power definition exists
916 if ( theType == MIN_POWER ) {
917 if ( (*this)[*token_pit]->minVoltage == UNKNOWN_VOLTAGE ) {
918 myVoltageStack.push_back(UNKNOWN_TOKEN);
919 } else {
920 myVoltageStack.push_back(float((*this)[*token_pit]->minVoltage) / VOLTAGE_SCALE);
921 }
922 }
923 if ( theType == SIM_POWER ) {
924 if ( (*this)[*token_pit]->simVoltage == UNKNOWN_VOLTAGE ) {
925 myVoltageStack.push_back(UNKNOWN_TOKEN);
926 } else {
927 myVoltageStack.push_back(float((*this)[*token_pit]->simVoltage) / VOLTAGE_SCALE);
928 }
929 }
930 if ( theType == MAX_POWER ) {
931 if ( (*this)[*token_pit]->maxVoltage == UNKNOWN_VOLTAGE ) {
932 myVoltageStack.push_back(UNKNOWN_TOKEN);
933 } else {
934 myVoltageStack.push_back(float((*this)[*token_pit]->maxVoltage) / VOLTAGE_SCALE);
935 }
936 }
937 implicitFamily += "," + *token_pit;
938 } else if ( (*token_pit).substr(0,4) == "Vth[" && (*token_pit).back() == ']' ){
939 string myModelName = "M " + (*token_pit).substr(4, (*token_pit).length() - 5);
940 if ( theModelListMap.count(myModelName) > 0 ) {
941 if ( theModelListMap[myModelName].Vth == UNKNOWN_VOLTAGE ) {
942 theModelListMap[myModelName].Vth = CalculateVoltage(theModelListMap[myModelName].vthDefinition, SIM_POWER, theModelListMap, false, false);
943 // recursive call fails if contains undefined macros. does not reset implicit power list
944 }
945 myVoltageStack.push_back(float(theModelListMap[myModelName].Vth) / VOLTAGE_SCALE);
946 } else {
947 throw EModelError("power definition error: " + theEquation + " unknown Vth for " + myModelName.substr(2));
948 }
949 } else if ( thePermitUndefinedFlag ){
950 myVoltageStack.push_back(UNKNOWN_TOKEN);
951 } else {
952 throw EPowerError("undefined macro: " + *token_pit);
953 }
954 } else if ( IsValidVoltage_(*token_pit) ) {
955 myVoltageStack.push_back(from_string<float>(*token_pit));
956 } else {
957 throw EPowerError("invalid power calculation token: " + *token_pit);
958 }
959 }
960 delete myTokenList_p;
961 if ( myVoltageStack.size() != 1 ) throw EPowerError("invalid equation: " + theEquation);
962 if ( myVoltageStack.front() > float(MAX_VOLTAGE) ) {
963 cout << "Warning: equation contains undefined tokens: " << theEquation << endl;
964 return(UNKNOWN_VOLTAGE);
965 }
966 return ( round(myVoltageStack.front() * VOLTAGE_SCALE + 0.1) );
967 }
968
RelativeVoltage(CPowerPtrMap & thePowerMacroPtrMap,netStatus_t theType,CModelListMap & theModelListMap)969 voltage_t CPower::RelativeVoltage(CPowerPtrMap & thePowerMacroPtrMap, netStatus_t theType, CModelListMap & theModelListMap) {
970 if ( ! extraData || IsEmpty(extraData->family) ) return UNKNOWN_VOLTAGE;
971 try {
972 return thePowerMacroPtrMap.CalculateVoltage(string(*(extraData->relativeSet.begin())), theType, theModelListMap);
973 }
974 catch (...) {
975 return UNKNOWN_VOLTAGE;
976 }
977 }
978
CInstancePower(string theDefinition)979 CInstancePower::CInstancePower(string theDefinition) {
980 theDefinition = trim_(theDefinition);
981 //size_t myAtIndex;
982 size_t myStringEnd = theDefinition.find_first_of(" \t"); // skip #instance
983 size_t myStringBegin = theDefinition.find_first_not_of(" \t", myStringEnd);
984 myStringEnd = theDefinition.find_first_of(" \t", myStringBegin);
985 instanceName = theDefinition.substr(myStringBegin, myStringEnd - myStringBegin);
986 myStringBegin = theDefinition.find_first_not_of(" \t", myStringEnd);
987 myStringEnd = theDefinition.find_first_of(" \t", myStringBegin);
988 powerFile = theDefinition.substr(myStringBegin, myStringEnd - myStringBegin);
989 }
990