Package empro :: Package toolkit :: Package analysis :: Package dc :: Module results
[frames] | no frames]

Source Code for Module empro.toolkit.analysis.dc.results

   1  # Copyright 1983-2019 Keysight Technologies, Inc , Keysight Confidential 
   2  import io 
   3   
   4  from empro.toolkit import _printexception, Bunch 
5 6 -def _pinNameToNetNameDict():
7 import empro 8 nameToNet = {} 9 for part in empro.activeProject.geometry().flatList(True): 10 if isinstance(part, empro.geometry.OaLayout): 11 for index in range(part._instanceCount()): 12 inst = part._instance(index) 13 for pi in range(inst.instPinCount()): 14 pin = inst.instPin(pi) 15 name = inst.name + '.' + pin.name 16 nameToNet[name]= pin.netName 17 for index in range(part._pinCount()): 18 pin = part._pin(index) 19 nameToNet[pin.name]= pin.netName 20 return nameToNet
21
22 -class DCResults(object):
23 @_printexception
24 - def __init__(self,sipiData):
25 import os 26 import collections 27 import empro 28 self.sipiData = sipiData 29 self.resultName = sipiData.name 30 self.resultAnalysisType = sipiData.analysisType 31 simLocation = sipiData.simulationPath 32 if not simLocation: 33 raise Exception("Simulation Results Not Found") 34 simInpData = os.path.join(simLocation, "design.sti") 35 pinHashToName = {} 36 pinHashToName[0] = "---" 37 instancePinHashToName = {} 38 #netNameDict = empro.toolkit.sipi._createPinHashNetName() #[TODO] robin: why was this used? 39 netNameDict = {} 40 netNameDict[0] = "---" 41 pinNameToNetName = _pinNameToNetNameDict() 42 netList = empro.activeProject.geometry()[0]._netList() 43 powerNets = list(netList.getPowerNetNames()) 44 groundNets = list(netList.getGroundNetNames()) 45 signalNets = list(netList.getSignalNetNames()) 46 vrms = {} 47 sinks = {} 48 thermalComponents = {} 49 vrmsPlusNets = {} 50 sinksPlusNets = {} 51 components = {} 52 cmptNameToTolerance = {} 53 nbVrms = len(sipiData.getVrmList()) 54 diagonalLoadsOnly = os.environ.has_key("SIPI_DC_DIAGONAL_LOADS_ONLY") 55 if diagonalLoadsOnly: 56 print "Warning: only diagonal loads are considered and off-diagonal loads are neglected" 57 58 with open(simInpData,"r") as inp: 59 lines = inp.readlines() 60 for index, line in enumerate(lines): 61 line = line.strip() 62 if not line.startswith('#'): 63 continue 64 cols = line[1:].split(";") 65 key = cols[0].strip() 66 if key=="AvailablePin": 67 pinHashToName[int(cols[1])]=cols[2] 68 netNameDict[int(cols[1])] = pinNameToNetName[cols[2]] 69 if key=="AvailableInstancePin": 70 instancePinHashToName[int(cols[1])]=cols[2] 71 if key=="Vrm": 72 for vrm in sipiData.getVrmList(): 73 cmptNameToTolerance[vrm.name] = vrm.tolerance 74 nr = int(cols[1]) 75 name = cols[2] 76 voltage = float(cols[3]) 77 tolerance = float(cols[4]) 78 plusPins = [x.strip() for x in map(str,lines[index+1].split(";")[2:])] 79 minPins = [x.strip() for x in map(str,lines[index+2].split(";")[2:])] 80 plusNets = [] 81 if "NetPlus" in lines[index+3]: 82 plusNets = map(str,lines[index+3].split(";")[2:]) 83 vrmsPlusNets[nr] = plusNets 84 vrms[nr] = [name, voltage, "?", "?", tolerance, "?", "?", plusPins, minPins] 85 if key=="ComponentModel": 86 nr = int(cols[1]) 87 name = cols[2] 88 if "ComponentModelPlus1" in lines[index+1]: 89 # multi port component 90 counter = 0 91 plusPins = [] 92 minPins= [] 93 while "ComponentModelPlus" in lines[index+1+counter] or "ComponentModelMinus" in lines[index+1+counter]: 94 if "ComponentModelPlus" in lines[index+1+counter]: 95 plusPins += [x.strip() for x in map(str,lines[index+1+counter].split(";")[2:])] 96 else: 97 minPins += [x.strip() for x in map(str,lines[index+1+counter].split(";")[2:])] 98 counter += 1 99 else: 100 plusPins = [x.strip() for x in map(str,lines[index+1].split(";")[2:])] 101 minPins = [x.strip() for x in map(str,lines[index+2].split(";")[2:])] 102 components[nr] = Bunch(name=name,plusPinNames=plusPins,minusPinNames=minPins) 103 if key=="ThermalComponent": 104 nr = int(cols[1]) 105 name = cols[2] 106 heatSource = float(cols[3]) 107 pins = [x.strip() for x in map(str,lines[index+1].split(";")[2:])] 108 thermalComponent = Bunch(name=name, heatSource=heatSource, pins=pins) 109 thermalComponents[nr] = thermalComponent 110 if key=="Sink": 111 for sink in sipiData.getSinkList(): 112 cmptNameToTolerance[sink.name] = sink.tolerance 113 nr = int(cols[1]) 114 name = cols[2] 115 current = float(cols[3]) 116 tolerance = float(cols[4]) 117 plusPins = [x.strip() for x in map(str,lines[index+1].split(";")[2:])] 118 instanceCandidate = "" 119 for pinName in plusPins: 120 tokens = pinName.split(".") 121 if len(tokens)==2: 122 instanceCandidate=tokens[0] 123 minPins = [x.strip() for x in map(str,lines[index+2].split(";")[2:])] 124 plusNets = [] 125 if "NetPlus" in lines[index+3]: 126 plusNets = map(str,lines[index+3].split(";")[2:]) 127 sinksPlusNets[nr] = plusNets 128 sinks[nr] = [name, current, "?", "?", tolerance, "?", "?", plusPins, minPins, instanceCandidate] 129 if diagonalLoadsOnly: 130 loadsSeenFromSinks = [] 131 else: 132 matrixLoadsSeenFromSinks = [] 133 for index, line in enumerate(lines): 134 line = line.strip() 135 if line.startswith('#'): 136 continue 137 if line.startswith("Electric") or line.startswith("Lumped"): 138 words = line.replace(':','').split() 139 id = int(words[1]) 140 if not sinks.has_key(id): 141 found = False 142 lookAhead = 250 143 144 words = lines[index+1].strip().split() 145 nrOfPorts = 1 146 if words[0].startswith("nrOfPorts"): 147 nrOfPorts = int(words[1]) 148 lookAhead = 250 + nrOfPorts * 3 149 150 for incr in range(lookAhead): 151 if index+incr>=len(lines): 152 break 153 words = lines[index+incr].strip().split() 154 if nrOfPorts==1 and (words[0].startswith("portNr") or words[0].startswith("port")): 155 id = int(words[1]) 156 if nrOfPorts>1 and (words[0].startswith("portNr[1]") or words[0].startswith("port[1]")): 157 id = int(words[1]) 158 if words[0].startswith("load"): 159 if words[1].startswith("open"): 160 if diagonalLoadsOnly: 161 loadsSeenFromSinks.append([id-1,1e9]) 162 else: 163 matrixLoadsSeenFromSinks.append([id-1,id-1,1e9]) 164 elif words[1].startswith("short"): 165 if diagonalLoadsOnly: 166 loadsSeenFromSinks.append([id-1,0.0]) 167 else: 168 matrixLoadsSeenFromSinks.append([id-1,id-1,0.0]) 169 elif words[1] == "resistor": 170 if nrOfPorts==1: 171 if len(words)==4: 172 R = float(words[3]) 173 else: 174 words = words[2].split('=') 175 R = float(words[1]) 176 if diagonalLoadsOnly: 177 loadsSeenFromSinks.append([id-1,R]) 178 else: 179 matrixLoadsSeenFromSinks.append([id-1,id-1,R]) 180 else: 181 line = lines[index+incr].strip() 182 filteredLine = line[line.find("R=")+2:] 183 values = map(float,filteredLine.split()) 184 if diagonalLoadsOnly: 185 # read the diagonal elements 186 def diagonalElements(nbPorts): 187 elements = [0] 188 index = 0 189 for i in range(nbPorts-1): 190 index += nbPorts-i 191 elements.append(index) 192 return elements
193 diagonalValues = [] 194 for index in diagonalElements(nrOfPorts): 195 diagonalValues.append(values[index]) 196 for index, value in enumerate(diagonalValues): 197 loadsSeenFromSinks.append([id-1+index,value]) 198 else: 199 # read as matrix load 200 assert(len(values) == nrOfPorts*(nrOfPorts+1)/2) 201 cnt = 0 202 for r in range(id-1, id+nrOfPorts-1): 203 for c in range(r, id+nrOfPorts-1): 204 matrixLoadsSeenFromSinks.append([r,c,values[cnt]]) 205 cnt = cnt + 1 206 207 break 208 209 def buildMatrixLoad(matrixLoadsSeenFromSinks): 210 import empro.enparams 211 loadIds = set([]) 212 for load in matrixLoadsSeenFromSinks: 213 loadIds.add(load[0]) 214 loadIds.add(load[1]) 215 g2l = {} # global -> local 216 lid = 0 217 loadIdsVec = [] 218 for gid in loadIds: 219 loadIdsVec.append(gid) 220 g2l[gid] = lid 221 lid = lid + 1 222 matrixLoad = empro.enparams.SquareComplexMatrix(len(g2l)) 223 for load in matrixLoadsSeenFromSinks: 224 r = g2l[load[0]] 225 c = g2l[load[1]] 226 v = load[2] 227 matrixLoad.setValue(r, c, v) 228 if r != c: matrixLoad.setValue(c, r, v) 229 return loadIdsVec, matrixLoad
230 231 self.pins = [] 232 self.thermalPins = [] 233 lumpNrToVI = {} 234 lumpNrToTH = {} 235 electricNameTolumpNr = {} 236 simOutpData = os.path.join(simLocation, "design.out.sti") 237 import re 238 posintRe = r"\d+" 239 floatRe = r"[-+]?(\d+(\.\d*)?|\.\d+)([eE][-+]?\d+)?" 240 pinRe = r"((plus)|(min))pin[\[" + posintRe + r"\]]*:" 241 extractPinVI = re.compile(r"\s*" + pinRe + r"\s*(?P<pinId>"+ posintRe +r")\s+voltage:\s*(?P<V>" + floatRe + r")\s+current:\s*(?P<I>" + floatRe + r")") 242 extractPinTH = re.compile(r"\s*" + pinRe + r"\s*(?P<pinId>"+ posintRe +r")\s+temperature:\s*(?P<T>" + floatRe + r")\s+heat:\s*(?P<H>" + floatRe + r")") 243 lastThermalLumpNr = None 244 lastElectricLumpNr = None 245 246 if not os.path.exists(simOutpData): 247 raise RuntimeError("Cannot find output file. Simulations results are incomplete.\nSearched for file: %(simOutpData)s" % vars()) 248 249 with io.open(simOutpData) as inp: 250 lines = inp.readlines() 251 for index, line in enumerate(lines): 252 if line.startswith("StiFile"): 253 continue 254 matchVI = extractPinVI.match(line) 255 matchTH = extractPinTH.match(line) 256 if matchVI: 257 pinHash = int(matchVI.groupdict()["pinId"]) 258 voltage = float(matchVI.groupdict()["V"]) 259 current = float(matchVI.groupdict()["I"]) 260 if pinHash in netNameDict: 261 netName = netNameDict[pinHash] 262 if netName in powerNets: 263 netType = "Power" 264 elif netName in groundNets: 265 netType = "Ground" 266 elif netName in signalNets: 267 netType = "Signal" 268 else: 269 netType = "Undefined" 270 pinName = pinHashToName[pinHash] 271 else: 272 pinName = "" 273 netName = "" 274 netType = "Virtual" 275 pinInfo = [pinName,netName,netType, voltage, current] 276 self.pins.append(pinInfo) 277 lumpNrToVI.get(lastElectricLumpNr,[0.0,0.0,[]])[2].append( Bunch(name=pinName,netName=netName,netType=netType,voltage=voltage,current=current) ) 278 elif matchTH: 279 pinHash = int(matchTH.groupdict()["pinId"]) 280 temperature = float(matchTH.groupdict()["T"]) 281 heat = float(matchTH.groupdict()["H"]) 282 if pinHash in netNameDict: 283 netName = netNameDict[pinHash] 284 if netName in powerNets: 285 netType = "Power" 286 elif netName in groundNets: 287 netType = "Ground" 288 elif netName in signalNets: 289 netType = "Signal" 290 else: 291 netType = "Undefined" 292 pinName = pinHashToName[pinHash] 293 else: 294 pinName = "" 295 netName = "" 296 if pinHash==0: 297 netType = "Virtual" 298 else: 299 netType = "ThermalPad" 300 pinInfo = Bunch(name=pinName,netName=netName,netType=netType,temperature=temperature,heat=heat) 301 self.thermalPins.append(pinInfo) 302 lumpNrToTH.get(lastThermalLumpNr,Bunch(temperature=298.15, heat=0.0, pins=[])).pins.append( Bunch(name=pinName,netName=netName,netType=netType,temperature=temperature,heat=heat) ) 303 continue 304 elif line.startswith("Lumped") or line.startswith("Electric"): 305 if line.startswith("Lumped"): 306 lumpNr = int(line.replace("Lumped","").replace(":","")) 307 else: 308 lumpNr = int(line.replace("Electric","").replace(":","")) 309 lastElectricLumpNr = lumpNr 310 nextIndex = index + 1 311 if "name:" in lines[nextIndex]: 312 electricName = lines[nextIndex].replace("name","").replace(":","").lstrip(" ").rstrip("\n") 313 electricNameTolumpNr[electricName] = lumpNr 314 nextIndex += 1 315 parts = lines[nextIndex].split(":") 316 if "nrOfPorts" in parts[0]: 317 if int(parts[1]) > 1: 318 continue 319 else: 320 nextIndex = nextIndex + 1 321 parts = lines[nextIndex].split(":") 322 if not "voltage" in parts[0]: 323 raise Exception("parsing error at line %d: voltage expected" % nextIndex) 324 voltage = float(parts[1]) 325 nextIndex = nextIndex + 1 326 parts = lines[nextIndex].split(":") 327 if not "current" in parts[0]: 328 raise Exception("parsing error at line %d: current expected" % nextIndex) 329 current = float(parts[1]) 330 lumpNrToVI[lumpNr] = [voltage,current,[]] 331 elif line.startswith("Thermal"): 332 lumpNr = int(line.replace("Thermal","").replace(":","")) 333 lastThermalLumpNr = lumpNr 334 nextIndex = index + 1 335 if "name:" in lines[nextIndex]: 336 nextIndex += 1 337 parts = lines[nextIndex].split(":") 338 if "nrOfPorts" in parts[0]: 339 if int(parts[1]) > 1: 340 continue 341 else: 342 nextIndex = nextIndex + 1 343 parts = lines[nextIndex].split(":") 344 if not "temperature" in parts[0]: 345 raise Exception("parsing error at line %d: temperature expected" % nextIndex) 346 tempDescr = parts[1].strip().split(" ") 347 temperature = float(tempDescr[0]) 348 nextIndex = nextIndex + 1 349 parts = lines[nextIndex].split(":") 350 if not "heat" in parts[0]: 351 raise Exception("parsing error at line %d: heat expected" % nextIndex) 352 353 heatDescr = parts[1].strip().split(" ") 354 heatBoard, heatDie, heatCase = float(heatDescr[0]),float(heatDescr[1]),float(heatDescr[2]) 355 if len(tempDescr)==3: 356 temperatureBoard, temperatureDie, temperatureCase = float(tempDescr[0]),float(tempDescr[1]),float(tempDescr[2]) 357 temperatureResult = Bunch(temperatureBoard=temperatureBoard, temperatureDie=temperatureDie, temperatureCase=temperatureCase, heatBoard=heatBoard,heatDie=heatDie, heatCase=heatCase, pins=[]) 358 lumpNrToTH[lumpNr] = temperatureResult 359 else: 360 temperatureResult = Bunch(temperature=temperature, heatBoard=heatBoard,heatDie=heatDie, heatCase=heatCase, pins=[]) 361 lumpNrToTH[lumpNr] = temperatureResult 362 363 import empro.enparams 364 thermalZ = None 365 if os.path.exists(os.path.join(simLocation, "design.out.thermal.cti")): 366 thermalCtiEvaluator = empro.enparams.CitiEvaluator(os.path.join(simLocation, "design.out.thermal.cti"), False) 367 thermalZ = thermalCtiEvaluator.Zmatrix(0) 368 369 thermalPinMap = {} 370 for thermalPin in self.thermalPins: 371 thermalPinMap[thermalPin.name] = thermalPin 372 373 self.thermalComponents = [] 374 for sourceNr, sourceDescr in thermalComponents.iteritems(): 375 if sourceNr not in lumpNrToTH: 376 continue 377 source = sourceDescr 378 source.merge(lumpNrToTH[sourceNr]) 379 if thermalZ: 380 source.bareBoardThermalResistance = abs(thermalZ(sourceNr-1,sourceNr-1)) 381 else: 382 source.bareBoardThermalResistance = '---' 383 source.heatToBoard = 0.0 384 for pin in source.pins: 385 if pin.netType!="Virtual": 386 source.heatToBoard -= pin.heat 387 self.thermalComponents.append(source) 388 389 def _vrmSenseportVoltageDict(): 390 vrmSenseportVoltageDict = {} 391 vrmList = self.sipiData.getVrmList() 392 for vrm in vrmList: 393 if vrm.hasSenseLine: 394 senseName = "sense_"+vrm.name 395 try: 396 lumpNr = electricNameTolumpNr[senseName] 397 v,i,pins = lumpNrToVI[lumpNr] 398 except KeyError: 399 v = None 400 i = None 401 pins = [] 402 sensePort = vrm.sensePort 403 plusPinNames = [x.name for x in sensePort.plusPins()] 404 plusPinVoltages = [x.voltage for x in pins if x.name in plusPinNames] 405 if plusPinVoltages: 406 minPlusPinVoltage = min(plusPinVoltages) 407 else: 408 minPlusPinVoltage = 0.0 409 vrmSenseportVoltageDict[vrm.name]=[float(vrm.senseVoltage),v,i,minPlusPinVoltage] 410 return vrmSenseportVoltageDict 411 412 def _vrmSwitchPortDict(): 413 vrmSwitchPortDict = {} 414 vrmList = self.sipiData.getVrmList() 415 for vrm in vrmList: 416 if vrm.sourceType != 'PackagedVrm': 417 upSwitchName = "upSwitch_"+vrm.name 418 try: 419 lumpNr = electricNameTolumpNr[upSwitchName] 420 v_upSwitch,i_upSwitch,pins_upSwitch = lumpNrToVI[lumpNr] 421 except KeyError: 422 v_upSwitch = None 423 i_upSwitch = None 424 pins_upSwitch = [] 425 upSwitch = vrm.upSwitch 426 lowSwitchName = "lowSwitch_"+vrm.name 427 try: 428 lumpNr = electricNameTolumpNr[lowSwitchName] 429 v_lowSwitch,i_lowSwitch,pins_lowSwitch = lumpNrToVI[lumpNr] 430 except KeyError: 431 v_lowSwitch = None 432 i_lowSwitch = None 433 pins_lowSwitch = [] 434 lowSwitch = vrm.lowSwitch 435 inductorName = "inductor_" + vrm.name 436 try: 437 lumpNr = electricNameTolumpNr[inductorName] 438 v_inductor,i_inductor,pins_inductor = lumpNrToVI[lumpNr] 439 except KeyError: 440 v_inductor = None 441 i_inductor = None 442 pins_inductor = [] 443 inductor = vrm.inductor 444 445 upPlusPinNames = set(y.name for y in upSwitch.plusPins()) 446 upMinusPinNames = set(y.name for y in upSwitch.minusPins()) 447 try: 448 upSwitchPlusPinVoltage = min(x.voltage for x in pins_upSwitch if x.name in upPlusPinNames) 449 upSwitchMinusPinVoltage = max(x.voltage for x in pins_upSwitch if x.name in upMinusPinNames) 450 except ValueError: 451 upSwitchPlusPinVoltage = 0.0 452 upSwitchMinusPinVoltage = 0.0 453 upSwitchBunch = Bunch(plusVoltage=upSwitchPlusPinVoltage, minusVoltage=upSwitchMinusPinVoltage,current=i_upSwitch) 454 455 lowPlusPinNames = set(y.name for y in lowSwitch.plusPins()) 456 lowMinusPinNames = set(y.name for y in lowSwitch.minusPins()) 457 try: 458 lowSwitchPlusPinVoltage = min(x.voltage for x in pins_lowSwitch if x.name in lowPlusPinNames) 459 lowSwitchMinusPinVoltage = max(x.voltage for x in pins_lowSwitch if x.name in lowMinusPinNames) 460 except ValueError: 461 lowSwitchPlusPinVoltage = 0.0 462 lowSwitchMinusPinVoltage = 0.0 463 lowSwitchBunch = Bunch(plusVoltage=lowSwitchPlusPinVoltage, minusVoltage=lowSwitchMinusPinVoltage,current=i_lowSwitch) 464 465 inductorPlusPinNames = set(y.name for y in inductor.plusPins()) 466 inductorMinusPinNames = set(y.name for y in inductor.minusPins()) 467 try: 468 inductorPlusPinVoltage = min(x.voltage for x in pins_inductor if x.name in inductorPlusPinNames) 469 inductorMinusPinVoltage = max(x.voltage for x in pins_inductor if x.name in inductorMinusPinNames) 470 except ValueError: 471 inductorPlusPinVoltage = 0.0 472 inductorMinusPinVoltage = 0.0 473 inductorBunch = Bunch(plusVoltage=inductorPlusPinVoltage, minusVoltage=inductorMinusPinVoltage,current=i_inductor) 474 475 switchOutputVoltage = inductorPlusPinVoltage 476 switchOutputCurrent = i_inductor 477 switchInputVoltage = upSwitchMinusPinVoltage 478 switchInputCurrent = i_upSwitch 479 if vrm.sourceType != 'DiscreteBuck': 480 switchOutputVoltage = lowSwitchPlusPinVoltage 481 switchOutputCurrent = i_lowSwitch 482 if vrm.sourceType =='DiscreteBoost': 483 switchInputVoltage = inductorMinusPinVoltage 484 switchInputCurrent = i_inductor 485 vrmSwitchPortDict[vrm.name]=[float(vrm.inputVoltage),vrm.sourceType,upSwitchBunch,lowSwitchBunch,inductorBunch,switchOutputVoltage,switchOutputCurrent,switchInputVoltage,switchInputCurrent] 486 487 return vrmSwitchPortDict 488 489 vrmVoltage = 0.0 490 self.failedVrms = [] 491 vrm = None 492 vrmSenseportVoltageDict = _vrmSenseportVoltageDict() 493 vrmSwitchDict = _vrmSwitchPortDict() 494 for vrmNr, vrm in vrms.iteritems(): 495 v,i,pins = lumpNrToVI.get(vrmNr,[0.0,0.0,[]]) 496 for pin in pins: 497 temperature = thermalPinMap.get(pin.name,Bunch(temperature=298.15)).temperature 498 pin.temperature = temperature 499 vrm[2] = v 500 vrm[3] = i 501 vrmVoltage = vrm[1] 502 503 try: 504 senseVoltage, senseportVoltage, senseportCurrent, minSensePlusPinVoltage = vrmSenseportVoltageDict[vrm[0]] 505 except KeyError: 506 senseVoltage = None 507 senseportVoltage = None 508 senseportCurrent = None 509 minSensePlusPinVoltage = None 510 vrm.append(senseVoltage) 511 vrm.append(senseportVoltage) 512 vrm.append(senseportCurrent) 513 vrm.append(minSensePlusPinVoltage) 514 515 try: 516 inputVoltage, sourceType, upSwitchBunch,lowSwitchBunch,inductorBunch,switchOutputVoltage,switchOutputCurrent,switchInputVoltage,switchInputCurrent = vrmSwitchDict[vrm[0]] 517 except KeyError: 518 inputVoltage = None 519 sourceType = 'PackagedVrm' 520 upSwitchBunch = None 521 lowSwitchBunch = None 522 inductorBunch = None 523 switchOutputVoltage = None 524 switchOutputCurrent = None 525 switchInputVoltage = None 526 switchInputCurrent = None 527 vrm.append(inputVoltage) 528 vrm.append(sourceType) 529 vrm.append(upSwitchBunch) 530 vrm.append(lowSwitchBunch) 531 vrm.append(inductorBunch) 532 vrm.append(switchOutputVoltage) 533 vrm.append(switchOutputCurrent) 534 vrm.append(switchInputVoltage) 535 vrm.append(switchInputCurrent) 536 vrm.append(pins) 537 538 margin = self._calculateMargin(vrmVoltage, switchOutputVoltage if switchOutputVoltage else v, cmptNameToTolerance[vrm[0]]) 539 vrm[5] = margin 540 if margin<0.0: 541 vrm[6] = "fail" 542 else: 543 vrm[6] = "pass" 544 if vrm[6] == "fail": 545 self.failedVrms.append(vrm[0]) 546 547 548 def _vrmsConnectedToSinks(): 549 setup = self.sipiData 550 layout = empro.activeProject.geometry()[0] 551 layoutObj = empro.activeProject.layout 552 allowedNets = [x.name for x in setup.getNetList() if x.type in [1,2,4]] 553 foundConnections = {} 554 vrms = {} # map from vrm name to the list of instances attached to it 555 compInsts = [] 556 for vrm in setup.getVrmList(): 557 instList = [] 558 for pin in vrm.plusPins(): 559 instList.append((pin.getInstanceName(),pin.getPinName())) 560 break 561 instList = set(instList) 562 vrms[vrm.name] = instList 563 if vrm.sourceType == 'DiscreteBuck': 564 for pin in vrm.inductor.plusPins(): 565 compInsts.append(pin.getInstanceName()) 566 break 567 elif vrm.sourceType != 'PackagedVrm': 568 for pin in vrm.lowSwitch.plusPins(): 569 compInsts.append(pin.getInstanceName()) 570 break 571 sinks = {} 572 for sink in setup.getSinkList(): 573 instList = [] 574 for pin in sink.plusPins(): 575 instList.append((pin.getInstanceName(),pin.getPinName())) 576 break 577 instList = set(instList) 578 sinks[sink.name] = instList 579 580 for compGroup in setup.getComponentModelGroupList(): 581 for inst in compGroup.instances(): 582 compInsts.append(inst.name) 583 limitInstances = True 584 for sinkName, sinkInstances in sinks.iteritems(): 585 sinkInstance, firstPinName = list(sinkInstances)[0] 586 for vrmName, vrmInstances in vrms.iteritems(): 587 connections = layout._connectionsFromInstance((sinkInstance,firstPinName),list(vrmInstances),[1,2,4],allowedNets, limitInstances, compInsts, 0, lambda x:None) 588 if connections: 589 if sinkName in foundConnections: 590 vrmsFound = foundConnections[sinkName] 591 vrmsFound.append(vrmName) 592 foundConnections[sinkName] = vrmsFound 593 else: 594 foundConnections[sinkName] = [vrmName] 595 return foundConnections 596 vrmsConnectedToSink = _vrmsConnectedToSinks() 597 598 vrmMap = dict( (vrm[0], vrm) for index, vrm in vrms.iteritems()) 599 vrmVoltageOfSink = {} 600 for sinkNr, sink in sinks.iteritems(): 601 allVrmVoltages = [vrmMap.get(vrmName,[None,None,0.0])[1] for vrmName in vrmsConnectedToSink.get(sink[0],[])] 602 if allVrmVoltages: 603 vrmVoltageOfSink[sinkNr] = max(allVrmVoltages) 604 else: 605 vrmVoltageOfSink[sinkNr] = 0.0 606 if sinksPlusNets[sinkNr]: 607 # look for the VRM that shares the plus net 608 sinkPlusNets = sinksPlusNets[sinkNr] 609 for vrmNr, vrmNets in vrmsPlusNets.iteritems(): 610 for plusNet in sinkPlusNets: 611 if plusNet in vrmNets: 612 vrmVoltageOfSink[sinkNr] = vrms[vrmNr][1] 613 614 vrmOutputVoltageOfSink = {} 615 for sinkNr, sink in sinks.iteritems(): 616 allVrmVoltages = [vrmMap.get(vrmName,[None,None,0.0])[2] for vrmName in vrmsConnectedToSink.get(sink[0],[])] 617 if allVrmVoltages: 618 vrmOutputVoltageOfSink[sinkNr] = max(allVrmVoltages) 619 else: 620 vrmOutputVoltageOfSink[sinkNr] = 0.0 621 if sinksPlusNets[sinkNr]: 622 # look for the VRM that shares the plus net 623 sinkPlusNets = sinksPlusNets[sinkNr] 624 for vrmNr, vrmNets in vrmsPlusNets.iteritems(): 625 for plusNet in sinkPlusNets: 626 if plusNet in vrmNets: 627 vrmOutputVoltageOfSink[sinkNr] = vrms[vrmNr][2] 628 629 self.failedSinks = [] 630 for sinkNr, sink in sinks.iteritems(): 631 v,i,pins = lumpNrToVI.get(sinkNr,[0.0,0.0,[]]) 632 for pin in pins: 633 temperature = thermalPinMap.get(pin.name,Bunch(temperature=298.15)).temperature 634 pin.temperature = temperature 635 tolerance = float(sink[4]) 636 vrmVoltage = vrmVoltageOfSink[sinkNr] 637 # add units to the column values 638 sink[2] = vrmVoltage 639 sink[3] = v 640 sink[5] = None # place holder for margin 641 sink[6] = None # place holder for success/failure 642 sink.append(pins) 643 644 645 vrmsList =[] 646 sinksList=[] 647 pinsList=[] 648 649 for vrmNr, vrm in vrms.iteritems(): 650 vrm[4] = self._toleranceToString(cmptNameToTolerance[vrm[0]]) # Tolerance 651 vVrm = vrm[:-1] 652 vrmTemperature, tempB, tempD, tempC = [298.15,298.15,298.15,298.15] 653 if thermalZ: 654 vVrm.insert(4, abs(thermalZ(vrmNr,vrmNr))) # thermalResistanceBareBoard 655 else: 656 vVrm.insert(4, 0.0) 657 vVrm.insert(5, 0.0) # thermalResistance 658 vVrm.insert(6, vrmTemperature) 659 vVrm.insert(7, tempD) 660 vVrm.insert(8, tempB) 661 vVrm.insert(9, tempC) 662 vVrm.append(vrm[-1]) 663 #vVrm.append(vrm[-1]) # add the pins 664 #vrms = Vrms(*vVrm) 665 #vrmsList.append(vrms) 666 plusSenseNetName = self._vrmNameToPlusSenseNet(vVrm[0]) 667 vrmObj = Bunch(name=vVrm[0], 668 sourceVoltage=vVrm[1], 669 outputVoltage=vVrm[2], 670 outputCurrent=vVrm[3], 671 thermalResistanceBareBoard=vVrm[4], 672 thermalResistance=vVrm[5], 673 temperature=vVrm[6], 674 temperatureDie=vVrm[7], 675 temperatureBoard=vVrm[8], 676 temperatureCase=vVrm[9], 677 tolerance=vVrm[10], 678 margin=vVrm[11], 679 result=vVrm[12], 680 plusPins = vVrm[13], 681 minusPins = vVrm[14], 682 senseVoltage = vVrm[15], 683 senseportVoltage = vVrm[16], 684 senseportCurrent = vVrm[17], 685 minSensePlusPinVoltage = vVrm[18], 686 senseNetName = plusSenseNetName, 687 inputVoltage = vVrm[19], 688 sourceType = vVrm[20], 689 upSwitchBunch = vVrm[21], 690 lowSwitchBunch = vVrm[22], 691 inductorBunch = vVrm[23], 692 switchOutputVoltage = vVrm[24], 693 switchOutputCurrent = vVrm[25], 694 switchInputVoltage = vVrm[26], 695 switchInputCurrent = vVrm[27], 696 pins=vVrm[-1]) 697 vrmsList.append(vrmObj) 698 699 electricCtiFile = os.path.join(simLocation, "design.out.electric.cti") 700 electricCtiBckFile = os.path.join(simLocation, "design.out.cti") 701 702 ctiEvaluator = None 703 if os.path.exists(electricCtiFile): 704 ctiEvaluator = empro.enparams.CitiEvaluator(electricCtiFile, False) 705 elif os.path.exists(electricCtiBckFile): 706 ctiEvaluator = empro.enparams.CitiEvaluator(electricCtiBckFile, False) 707 electricCtiFile = electricCtiBckFile 708 709 if ctiEvaluator: 710 Z = ctiEvaluator.Zmatrix(0) 711 if diagonalLoadsOnly: 712 if Z.size() != len(sinks) + len(loadsSeenFromSinks): 713 raise Exception("invalid #ports in cti-file <%s>: expected %d, found %d" % (electricCtiFile, len(sinks) + len(loadsSeenFromSinks), Z.size())) 714 else: 715 loadIds, matrixLoad = buildMatrixLoad(matrixLoadsSeenFromSinks) 716 if Z.size() != len(sinks) + len(loadIds): 717 raise Exception("invalid #ports in cti-file <%s>: expected %d, found %d" % (electricCtiFile, len(sinks) + len(loadIds), Z.size())) 718 719 720 import os 721 useOldRsink = os.environ.has_key("SIPI_DC_USE_OLD_R_SINK") 722 if useOldRsink: 723 print "Using old formula for calculation of R seen from sinks" 724 725 self.failedSinks = [] 726 for sinkKey, sink in sinks.iteritems(): 727 if useOldRsink: 728 R = float((sink[2]-sink[3])/sink[1]) 729 else: 730 if diagonalLoadsOnly: 731 R = Z.param_loaded(sinkKey-1,sinkKey-1,loadsSeenFromSinks).real 732 else: 733 R = Z.param_schur(sinkKey-1, sinkKey-1, loadIds, matrixLoad).real 734 sink.insert(4,round(R,4)) 735 if thermalZ: 736 sink.insert(5, abs(thermalZ(sinkKey-1, sinkKey-1))) # thermalResistanceBareBoard 737 else: 738 sink.insert(5, 0.0) 739 sink.insert(6, 0.0) # thermalResistance 740 sink[7] = self._toleranceToString(cmptNameToTolerance[sink[0]]) # Tolerance 741 sSink = sink[:] 742 sinkTemperature, tempB, tempD, tempC = [298.15,298.15,298.15,298.15] 743 sSink.insert(7, sinkTemperature) 744 sSink.insert(8, tempD) 745 sSink.insert(9, tempB) 746 sSink.insert(10, tempC) 747 #sinks = Sinks(*sSink) 748 #sinksList.append(sinks) 749 sinkObj = Bunch(name=sSink[0], 750 sourceCurrent=sSink[1], 751 vrmVoltage=sSink[2], 752 inputVoltage=sSink[3], 753 resistance=sSink[4], 754 thermalResistanceBareBoard=sSink[5], 755 thermalResistance=sSink[6], 756 temperature=sSink[7], 757 temperatureDie=sSink[8], 758 temperatureBoard=sSink[9], 759 temperatureCase=sSink[10], 760 tolerance=sSink[11], 761 margin=sSink[12], 762 result=sSink[13], 763 plusPins=sSink[14], 764 minusPins=sSink[15], 765 instNameCandidate=sSink[16], 766 vrmOutputVoltage = vrmOutputVoltageOfSink[sinkKey], 767 pins=sSink[-1]) 768 769 770 plusPinNames = set(sinkObj.plusPins) 771 minusPinNames = set(sinkObj.minusPins) 772 minPinVoltages = [x.voltage for x in sinkObj.pins if x.name in minusPinNames] 773 plusPinVoltages = [x.voltage for x in sinkObj.pins if x.name in plusPinNames] 774 if minPinVoltages and plusPinVoltages: 775 sinkObj.inputVoltage = min(plusPinVoltages)-max(minPinVoltages) 776 777 sinkObj.margin = self._calculateMargin(sinkObj.vrmVoltage, sinkObj.inputVoltage, cmptNameToTolerance[sinkObj.name]) 778 sinkPass = self._calculateSinkPass(sinkObj.vrmVoltage, sinkObj.inputVoltage, cmptNameToTolerance[sinkObj.name]) 779 sinkObj.result = { False : 'fail', True : 'pass'}[sinkPass] 780 if not sinkPass: 781 self.failedSinks.append(sinkObj.name) 782 783 sinksList.append(sinkObj) 784 785 self.vrms = vrmsList 786 self.sinks = sinksList 787 self.pins = sorted(self.pins, key=lambda x:x[0]) 788 for pin in self.pins: 789 Pins= collections.namedtuple('Pin',['name', 'netName','netType','voltage', 'current','temperature']) 790 pPin = pin[:] 791 pPin.append( thermalPinMap.get(pPin[0], Bunch(temperature=298.15)).temperature ) 792 pins = Pins(*pPin) 793 pinsList.append(pins) 794 self.pins = pinsList 795 else: 796 self.vrms = [] 797 self.sinks = [] 798 self.pins = [] 799 800 pinMap = {} 801 for pin in self.pins: 802 pinMap[pin.name] = pin 803 804 self.components = [] 805 for componentNr, component in components.iteritems(): 806 comp = component 807 v,i,pins = lumpNrToVI.get(componentNr,[0.0,0.0,[]]) 808 comp.voltage = v 809 comp.current = i 810 comp.pins = [x for x in [pinMap.get(name,None) for name in comp.minusPinNames] if x!=None] 811 comp.pins += [x for x in [pinMap.get(name,None) for name in comp.plusPinNames] if x!=None] 812 self.components.append(comp) 813 814 for vrm in self.vrms: 815 plusPinNames = set(vrm.plusPins) 816 plusPinVoltages = [x.voltage for x in vrm.pins if x.name in plusPinNames] 817 if plusPinVoltages: 818 plusPinVoltage = min(plusPinVoltages) 819 else: 820 plusPinVoltage = 0.0 821 822 vrm.minVoltagePowerPins = plusPinVoltage 823 824 for sink in self.sinks: 825 plusPinNames = set(sink.plusPins) 826 minusPinNames = set(sink.minusPins) 827 828 #plusPinVoltage = min([x.voltage for x in sink.pins if x.name in plusPinNames]) 829 plusPinVoltages = [x.voltage for x in sink.pins if x.name in plusPinNames] 830 if plusPinVoltages: 831 plusPinVoltage = min(plusPinVoltages) 832 else: 833 plusPinVoltage = 0.0 834 minPinVoltages = [x.voltage for x in sink.pins if x.name in minusPinNames] 835 if minPinVoltages: 836 minPinVoltage = max(minPinVoltages) 837 else: 838 minPinVoltage = 0.0 839 840 sink.minVoltagePowerPins = plusPinVoltage 841 sink.maxVoltageGroundPins = minPinVoltage 842 843 self.layerStatistics = {} 844 self._extractLayerData(sipiData) 845 846 ##########################################################3 847 848 try: 849 self.viaCurrents = sipiData.vias() 850 except: 851 self.viaCurrents = {} 852 try: 853 self.viaMaxTemperatures = sipiData.viasMaxTemperature() 854 except: 855 self.viaMaxTemperatures = {} 856 try: 857 self.viaRadiusThickness = sipiData._viasRadiiThickness() 858 except: 859 self.viaRadiusThickness = {} 860 861 @_printexception
862 - def _extractLayerData(self,sipiData):
863 import os 864 import collections 865 import empro 866 simLocation = sipiData.simulationPath 867 if not simLocation: 868 raise Exception("Simulation Results Not Found") 869 layerStatistics = sipiData._perLayerStatistics() 870 import empro.toolkit.analysis as sipi 871 layerMapping = sipi._filterData(sipiData) 872 self.layerStatistics = {} 873 for index, name in layerMapping.iteritems(): 874 if index in layerStatistics: 875 self.layerStatistics[name] = layerStatistics[index] 876 newDict = {} 877 for k,v in self.layerStatistics[name].iteritems(): 878 newDict[k] = v 879 newDict['layerId'] = index 880 self.layerStatistics[name] = newDict
881
882 - def _calculateMargin(self, vrmVoltage, inputVoltage, tolerance):
883 toleranceVoltage = None 884 if tolerance.unitClass()=="ELECTRIC_POTENTIAL": 885 # tolerance specified in voltage 886 toleranceVoltage = float(tolerance) 887 elif tolerance.unitClass()=="SCALAR": 888 # tolerance specified in percentage 889 toleranceVoltage = float(tolerance)*vrmVoltage 890 deltaVoltage = vrmVoltage-inputVoltage 891 return abs(toleranceVoltage)-deltaVoltage
892
893 - def _calculateSinkPass(self, vrmVoltage, inputVoltage, tolerance):
894 toleranceVoltage = None 895 if tolerance.unitClass()=="ELECTRIC_POTENTIAL": 896 # tolerance specified in voltage 897 toleranceVoltage = float(tolerance) 898 elif tolerance.unitClass()=="SCALAR": 899 # tolerance specified in percentage 900 toleranceVoltage = float(tolerance)*vrmVoltage 901 deltaVoltage = inputVoltage-vrmVoltage 902 return abs(deltaVoltage) < abs(toleranceVoltage)
903
904 - def _valuewithUnit(self, value, unit):
905 result = None 906 if value.is_integer(): 907 result = "%d %s" % (value, unit) 908 else: 909 if value < 1e-6: 910 result = "%s %s" % (value, unit) 911 else: 912 result = "%.6f %s" % (value, unit) 913 return result
914
915 - def _toleranceToString(self, tolerance):
916 result = str(float(tolerance)) 917 if tolerance.unitClass()=="ELECTRIC_POTENTIAL": 918 result = tolerance.formula() 919 elif tolerance.unitClass()=="SCALAR": 920 toleranceVal = float(tolerance)*100 921 if toleranceVal.is_integer(): 922 result = "%d %%" % int(toleranceVal) 923 else: 924 result = "%f %%" % toleranceVal 925 return result
926
927 - def _vrmNameToPlusSenseNet(self,name):
928 plusSenseNetName = None 929 vrmList = self.sipiData.getVrmList() 930 for vrm in vrmList: 931 if vrm.name == name and vrm.hasSenseLine: 932 sensePort = vrm.sensePort 933 for plusPin in sensePort.plusPins(): 934 plusSenseNetName = plusPin.getNetName() 935 break 936 break 937 return plusSenseNetName
938
939 -class DCResultsDiff(object):
940 @_printexception
941 - def __init__(self, result1, result2):
942 def diff(a,b): 943 if a==b: 944 if a=="---": 945 return a 946 return 0.0 947 try: 948 return a-b 949 except: 950 return "???"
951 952 def diffPins(a,b): 953 difference = [] 954 pinsA = {} 955 pinsB = {} 956 for pin in a: 957 pinsA[pin.name] = pin 958 for pin in b: 959 pinsB[pin.name] = pin 960 for name, pinA in pinsA.iteritems(): 961 if name in pinsB: 962 pinB = pinsB[name] 963 pin = Bunch(name=name,netType=pinA.netType,netName=pinA.netName,voltage=pinA.voltage-pinB.voltage,current=pinA.current-pinB.current,temperature=pinA.temperature-pinB.temperature) 964 difference.append(pin) 965 return difference
966 967 self.resultNames = [result1.sipiData.name, result2.sipiData.name] 968 self.sipiDatas = [result1.sipiData, result2.sipiData] 969 self.resultAnalysisType = result1.sipiData.analysisType 970 971 sinks1 = sorted(result1.sinks,key=lambda x:x.name) 972 sinks2 = sorted(result2.sinks,key=lambda x:x.name) 973 self.sinks = [] 974 if [x.name for x in sinks1]==[x.name for x in sinks2]: 975 for sink1,sink2 in zip(sinks1,sinks2): 976 self.sinks.append(Bunch(name=sink1.name, 977 sourceCurrent=sink1.sourceCurrent-sink2.sourceCurrent, 978 vrmVoltage=sink1.vrmVoltage-sink2.vrmVoltage, 979 vrmOutputVoltage=sink1.vrmOutputVoltage-sink2.vrmOutputVoltage, 980 inputVoltage=sink1.inputVoltage-sink2.inputVoltage, 981 resistance=sink1.resistance-sink2.resistance, 982 tolerance=diff(sink1.tolerance,sink2.tolerance), 983 margin=sink1.margin-sink2.margin, 984 minVoltagePowerPins = sink1.minVoltagePowerPins-sink2.minVoltagePowerPins, 985 maxVoltageGroundPins = sink1.maxVoltageGroundPins-sink2.maxVoltageGroundPins, 986 pins=diffPins(sink1.pins,sink2.pins))) 987 988 vrms1 = sorted(result1.vrms,key=lambda x:x.name) 989 vrms2 = sorted(result2.vrms,key=lambda x:x.name) 990 self.vrms = [] 991 if [x.name for x in vrms1]==[x.name for x in vrms2]: 992 for vrm1,vrm2 in zip(vrms1,vrms2): 993 vrmObj = Bunch(name=vrm1.name, 994 sourceVoltage=vrm1.sourceVoltage-vrm2.sourceVoltage, 995 outputVoltage=vrm1.outputVoltage-vrm2.outputVoltage, 996 outputCurrent=vrm1.outputCurrent-vrm2.outputCurrent, 997 tolerance=diff(vrm1.tolerance,vrm2.tolerance), 998 margin=vrm1.margin-vrm2.margin, 999 minVoltagePowerPins = vrm1.minVoltagePowerPins-vrm2.minVoltagePowerPins, 1000 pins=diffPins(vrm1.pins,vrm2.pins)) 1001 if vrm1.senseVoltage and vrm2.senseVoltage: 1002 vrmObj.senseVoltage = vrm1.senseVoltage - vrm2.senseVoltage 1003 vrmObj.senseportVoltage = vrm1.senseportVoltage - vrm2.senseportVoltage 1004 vrmObj.senseportCurrent = vrm1.senseportCurrent - vrm2.senseportCurrent 1005 vrmObj.minSensePlusPinVoltage = vrm1.minSensePlusPinVoltage - vrm2.minSensePlusPinVoltage 1006 vrmObj.senseNetName = vrm1.senseNetName if vrm1.senseNetName==vrm2.senseNetName else "" 1007 else: 1008 vrmObj.senseVoltage = None 1009 vrmObj.senseportVoltage = None 1010 vrmObj.senseportCurrent = None 1011 vrmObj.minSensePlusPinVoltage = None 1012 vrmObj.senseNetName = None 1013 if vrm1.sourceType !='PackagedVrm' and (vrm1.sourceType==vrm2.sourceType): 1014 vrmObj.inputVoltage = vrm1.inputVoltage - vrm2.inputVoltage 1015 vrmObj.sourceType = vrm1.sourceType 1016 vrmObj.upSwitchBunch = Bunch(plusVoltage=vrm1.upSwitchBunch.plusVoltage-vrm2.upSwitchBunch.plusVoltage, minusVoltage=vrm1.upSwitchBunch.minusVoltage-vrm2.upSwitchBunch.minusVoltage,current=vrm1.upSwitchBunch.current-vrm2.upSwitchBunch.current) 1017 vrmObj.lowSwitchBunch = Bunch(plusVoltage=vrm1.lowSwitchBunch.plusVoltage-vrm2.lowSwitchBunch.plusVoltage, minusVoltage=vrm1.lowSwitchBunch.minusVoltage-vrm2.lowSwitchBunch.minusVoltage,current=vrm1.lowSwitchBunch.current-vrm2.lowSwitchBunch.current) 1018 vrmObj.inductorBunch = Bunch(plusVoltage=vrm1.inductorBunch.plusVoltage-vrm2.inductorBunch.plusVoltage, minusVoltage=vrm1.inductorBunch.minusVoltage-vrm2.inductorBunch.minusVoltage,current=vrm1.inductorBunch.current-vrm2.inductorBunch.current) 1019 vrmObj.switchOutputVoltage = vrm1.switchOutputVoltage - vrm2.switchOutputVoltage 1020 vrmObj.switchOutputCurrent = vrm1.switchOutputCurrent - vrm2.switchOutputCurrent 1021 vrmObj.switchInputVoltage = vrm1.switchInputVoltage - vrm2.switchInputVoltage 1022 vrmObj.switchInputCurrent = vrm1.switchInputCurrent - vrm2.switchInputCurrent 1023 else: 1024 vrmObj.inputVoltage = None 1025 vrmObj.sourceType = 'PackagedVrm' 1026 vrmObj.upSwitchBunch = None 1027 vrmObj.lowSwitchBunch = None 1028 vrmObj.inductorBunch = None 1029 vrmObj.switchOutputVoltage = None 1030 vrmObj.switchOutputCurrent = None 1031 vrmObj.switchInputVoltage = None 1032 vrmObj.switchInputCurrent = None 1033 self.vrms.append(vrmObj) 1034 1035 comps1 = sorted(result1.components,key=lambda x:x.name) 1036 comps2 = sorted(result2.components,key=lambda x:x.name) 1037 self.components = [] 1038 if [x.name for x in comps1]==[x.name for x in comps2]: 1039 for comp1,comp2 in zip(comps1,comps2): 1040 self.components.append(Bunch(name=comp1.name, 1041 voltage=comp1.voltage-comp2.voltage, 1042 current=comp1.current-comp2.current, 1043 pins=diffPins(comp1.pins,comp2.pins))) 1044 1045 pins1 = sorted(result1.pins,key=lambda x:x[0]) 1046 pins2 = sorted(result2.pins,key=lambda x:x[0]) 1047 self.pins = [] 1048 if [x[0] for x in pins1]==[x[0] for x in pins2]: 1049 for pin1,pin2 in zip(pins1,pins2): 1050 self.pins.append(Bunch(name=pin1[0],netType=pin1.netType,netName=pin1.netName,voltage=pin1[3]-pin2[3],current=pin1[4]-pin2[4],temperature=pin1[5]-pin2[5],)) 1051 1052 thermalComponents1 = sorted(result1.thermalComponents,key=lambda x:x.name) 1053 thermalComponents2 = sorted(result2.thermalComponents,key=lambda x:x.name) 1054 self.thermalComponents = [] 1055 if len(thermalComponents1)==len(thermalComponents2): 1056 for comp1,comp2 in zip(thermalComponents1,thermalComponents2): 1057 if hasattr(comp1, "temperatureBoard"): 1058 self.thermalComponents.append(Bunch(name=comp1.name, 1059 heatSource = comp1.heatSource-comp2.heatSource, 1060 heatToBoard = comp1.heatToBoard-comp2.heatToBoard, 1061 temperatureBoard=comp1.temperatureBoard-comp2.temperatureBoard, 1062 temperatureDie=comp1.temperatureDie-comp2.temperatureDie, 1063 temperatureCase=comp1.temperatureCase-comp2.temperatureCase, 1064 heatBoard=comp1.heatBoard-comp2.heatBoard, 1065 heatDie=comp1.heatDie-comp2.heatDie, 1066 heatCase=comp1.heatCase-comp2.heatCase, 1067 bareBoardThermalResistance=diff(comp1.bareBoardThermalResistance,comp2.bareBoardThermalResistance), 1068 )) 1069 else: 1070 self.thermalComponents.append(Bunch(name=comp1.name, 1071 heatSource = comp1.heatSource-comp2.heatSource, 1072 heatToBoard = comp1.heatToBoard-comp2.heatToBoard, 1073 temperature=comp1.temperature-comp2.temperature, 1074 heatBoard=comp1.heatBoard-comp2.heatBoard, 1075 heatDie=comp1.heatDie-comp2.heatDie, 1076 heatCase=comp1.heatCase-comp2.heatCase, 1077 bareBoardThermalResistance=diff(comp1.bareBoardThermalResistance,comp2.bareBoardThermalResistance), 1078 )) 1079 1080 1081 layers1 = result1.layerStatistics 1082 layers2 = result2.layerStatistics 1083 self.layerStatistics = {} 1084 for layerName,layer1 in layers1.iteritems(): 1085 if layerName not in layers2: 1086 continue 1087 layer2 = layers2[layerName] 1088 newDict = {} 1089 for k,v in layer1.iteritems(): 1090 if k not in ["zMax","zMin","layerId"]: 1091 newDict[k] = v-layer2[k] 1092 else: 1093 newDict[k] = v 1094 newDict['layerId'] = layer1['layerId'] 1095 self.layerStatistics[layerName] = newDict 1096 1097 viaCurrs1 = result1.viaCurrents 1098 viaCurrs2 = result2.viaCurrents 1099 self.viaCurrents = {} 1100 if len(list(viaCurrs1.keys()))==len(list(viaCurrs2.keys())): 1101 for id, via1 in viaCurrs1.iteritems(): 1102 via2 = viaCurrs2[id] 1103 viaDiff = (via1[0]-via2[0], via1[1]) 1104 self.viaCurrents[id] = viaDiff 1105 1106 viaMaxTemps1 = result1.viaMaxTemperatures 1107 viaMaxTemps2 = result2.viaMaxTemperatures 1108 self.viaMaxTemperatures = {} 1109 for id, via1 in viaMaxTemps1.iteritems(): 1110 via2 = viaMaxTemps2[id] 1111 self.viaMaxTemperatures[id] = via1-via2 1112 1113 viaRadiiThick1 = result1.viaRadiusThickness 1114 viaRadiiThick2 = result2.viaRadiusThickness 1115 self.viaRadiusThickness = {} 1116 for id, via1 in viaRadiiThick1.iteritems(): 1117 via2 = viaRadiiThick2[id] 1118 self.viaRadiusThickness[id] = (via1[0]-via2[0],via1[1]-via2[1]) 1119 1120 1121 1122 if False: 1123 try: 1124 del empro.internal.__tempResults 1125 pass 1126 except: 1127 pass 1128 if True or not hasattr(empro.internal,'__tempResults'): 1129 #results1 = DCResults(empro.activeProject.sipiSetupList()[-1]) 1130 #results2 = DCResults(empro.activeProject.sipiSetupList()[-1]) 1131 #results = DCResultsDiff(results1,results2) 1132 results = DCResults(empro.activeProject.analyses[-1]) 1133 empro.internal.__tempResults = results 1134 results = empro.internal.__tempResults 1135 """ 1136 for vrm in results.vrms: 1137 print vrm 1138 print 1139 """ 1140 for sink in results.sinks: 1141 print sink.name, sink.vrmVoltage, sink.margin 1142 print 1143 """ 1144 for comp in results.thermalComponents: 1145 print comp 1146 print 1147 for comp in results.components: 1148 print comp 1149 print 1150 """ 1151 """ 1152 for via in results.viaMaxTemperatures.iteritems(): 1153 print via 1154 """ 1155