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

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

  1  # Copyright 1983-2019 Keysight Technologies, Inc , Keysight Confidential 
  2  import empro 
  3  from empro.toolkit import _printexception 
  4  from empro.toolkit import long_path_util 
5 6 @_printexception 7 -def _generateThermalResistanceStimulus(thermalResistance, instance, zLowerEffHeatTransfer=2.5, zUpperEffHeatTransfer=10.0):
8 stimulusLines = [] 9 if isinstance(thermalResistance, empro.components.ToAmbientSpecification): 10 tempThermalResistance = float(thermalResistance.resistance) 11 if tempThermalResistance>0.0: 12 stimulusLines.append(" load: resistor R=%(tempThermalResistance)f" % vars()) 13 else: 14 stimulusLines.append(" load: open" % vars()) 15 else: 16 Rjb = 0.0 17 if isinstance(thermalResistance, empro.components.Package3RSpecification): 18 Rjb = float(thermalResistance.dieToCaseBottomResistance) 19 20 Rjc = float(thermalResistance.dieToCaseTopResistance) 21 Rca = 200.0 22 if thermalResistance.useCaseToAmbientResistance: 23 Rca = float(thermalResistance.caseToAmbientResistance) 24 else: 25 bb = instance.boundingBox() 26 extent = bb.extent() 27 totalArea = max(extent.x*extent.y, 1e-6) # the minimal area assumed is 1mm*1mm 28 effHeatTransfer = zUpperEffHeatTransfer 29 effectiveHeatTransfer = totalArea * effHeatTransfer 30 if effectiveHeatTransfer>0.0: 31 Rca = 1.0 / effectiveHeatTransfer 32 tempThermalResistance = Rjb + Rjc + Rca 33 if tempThermalResistance>0.0: 34 stimulusLines.append(" load: resistor R=%(Rjb)f %(Rjc)f %(Rca)f" % vars()) 35 else: 36 stimulusLines.append(" load: open" % vars()) 37 return stimulusLines
38
39 40 @_printexception 41 -def _generateStimulusFileThermalOnly(fileName, sipiData):
42 # 43 import datetime 44 import os 45 import empro.toolkit.analysis as sipi 46 pinHash = sipi._createPinHash() 47 instanceHash = sipi._createInstanceHash() 48 pinNetNames = sipi._createPinHashNetName() 49 50 simData = sipiData.newSimulationData() 51 generateThermalPorts = simData.sParametersEnabled 52 53 backGroundTemperature = float(simData.ambientConditions.backgroundTemperature) 54 zLowerEffHeatTransfer = max(1e-4,simData.ambientConditions._zLowerEvaluatedEffectiveHeatTransfer()) 55 zUpperEffHeatTransfer = max(1e-4,simData.ambientConditions._zUpperEvaluatedEffectiveHeatTransfer()) 56 57 stimulusLines = [] 58 portNr = 0 59 thermalComponentGroupList = sipiData.getThermalComponentGroupList() 60 for group in thermalComponentGroupList: 61 for source in group: 62 portNr += 1 63 name = source.name 64 instance = source.instance() 65 instHash = instanceHash[instance.name] 66 thermalSource = float(source.heatSource) 67 pinNames = [instance.name + "." + pin.name for pin in instance.pins()] 68 stimulusLines.append("Thermal %(portNr)d:" % vars()) 69 stimulusLines.append(" name: %(name)s" % vars()) 70 if generateThermalPorts: 71 stimulusLines.append(" port: %(portNr)d" % vars()) 72 73 generateR = isinstance(group.thermalResistance, empro.components.Package3RSpecification) 74 if generateR: 75 pinR = float(group.thermalResistance.pinResistance) 76 for pinName in pinNames: 77 pinNr = str(pinHash[pinName]) 78 if generateR: 79 stimulusLines.append(" pluspin: %(pinNr)s R=%(pinR)f name=%(pinName)s" % vars()) 80 else: 81 stimulusLines.append(" pluspin: %(pinNr)s name=%(pinName)s" % vars()) 82 83 if isinstance(group.thermalResistance, empro.components.Package3RSpecification): 84 if group.thermalResistance.useCaseToBoardResistance: 85 padR = float(group.thermalResistance.caseToBoardResistance) 86 pinNr = str(instHash) 87 pinName = name + "..BOARD" 88 stimulusLines.append(" pluspin: %(pinNr)s R=%(padR)f name=%(pinName)s" % vars()) 89 90 stimulusLines.append(" minpin: 0") 91 92 thermalSource = float(source.heatSource) 93 if source.sourceType in ["Disabled", "ElectricDissipation", "ElectricDissipationAndHeatSource","HeatSource"]: 94 if source.sourceType in ["Disabled", "ElectricDissipation"]: 95 thermalSource = 0.0 96 stimulusLines.append(" source: heat Q=%(thermalSource)f" % vars()) 97 elif source.sourceType in ["TemperatureSource"]: 98 temperatureSource = float(source.temperatureSource)-backGroundTemperature 99 stimulusLines.append(" source: temperature T=%(temperatureSource)f" % vars()) 100 101 if not (source.sourceType in ["TemperatureSource"] and isinstance(group.thermalResistance, empro.components.ToAmbientSpecification)): 102 stimulus = _generateThermalResistanceStimulus(group.thermalResistance, instance, zLowerEffHeatTransfer, zUpperEffHeatTransfer) 103 stimulusLines += stimulus 104 105 106 stimulusDesc = "\n".join(stimulusLines) 107 with open(long_path_util.resolveLongPath(fileName),"w") as stimulusFile: 108 stimulusFile.write(_generateStimulusHeader(sipiData)) 109 stimulusFile.write(stimulusDesc)
110
111 @_printexception 112 -def _getDCResistance(componentGroup):
113 componentModel = componentGroup.models()[componentGroup.defaultModelIndex] 114 impedanceSpecification = None 115 if componentModel.modelType == 2: # Vendor parts database 116 impedanceSpecification = componentModel.getPassiveLoadFromVendorPartsDb().impedance 117 elif componentModel.modelType == 4: # Library Cell 118 viewName = componentModel.viewName 119 firstInstance = None 120 libCellName = None 121 if componentGroup.instances()[0]: 122 firstInstance = componentGroup.instances()[0].instance().name 123 libCellName = componentGroup.instances()[0]._libCellName 124 else: 125 raise RuntimeError("Model <%s> has no instances" % componentGroup.models()[ componentGroup.defaultModelIndex ].name) 126 layoutLibName = empro.activeProject.location.lib 127 layoutCellName = empro.activeProject.location.cell 128 layoutViewName = empro.activeProject.geometry()[0].name 129 if not layoutViewName or layoutViewName=='': 130 layoutViewName='layout' 131 parentLCVLayout = layoutLibName + ':' + layoutCellName + ':' + layoutViewName 132 pinPortMap = componentGroup.pinPortMap() 133 nrOfPorts = pinPortMap.nrPorts() 134 pinNamePortNumberPairs = pinPortMap.getPinNamePortNumberPairs(True, True); 135 impedanceSpecification = componentModel.getPassiveLoadFromLibCell(libCellName, viewName, firstInstance, 136 parentLCVLayout, nrOfPorts, 137 pinNamePortNumberPairs).impedance 138 else: 139 impedanceSpecification = componentModel.getPassiveLoad().impedance 140 if isinstance(impedanceSpecification, empro.components.RLCSpecification): 141 resistance = float(impedanceSpecification.resistance) 142 capacitance = float(impedanceSpecification.capacitance) 143 inductance = float(impedanceSpecification.inductance) 144 arrangement = impedanceSpecification.elementArrangement 145 if arrangement=="Series" and capacitance>0.0: 146 resistance = 1e8 147 elif arrangement=="Parallel": 148 if inductance>0.0: 149 resistance = 0.0 150 elif capacitance>0.0 and resistance==0.0: 151 resistance = 1e8 152 result = (1, [resistance]) 153 elif isinstance(impedanceSpecification, empro.components.SnPSpecification): 154 import empro.enparams as enparams 155 snpEvaluator = enparams.TouchstoneEvaluator(impedanceSpecification.fileName) 156 minFreq = snpEvaluator.storedFrequencies()[0] 157 if minFreq != 0.0: 158 message = "DC not available in <%s>, using %e Hz instead" % (impedanceSpecification.fileName, minFreq) 159 empro.gui.MessageBox.warning("Warning", message, 0, 0) 160 #raise RuntimeError("0 Hz not available in <%s>" % impedanceSpecification.fileName) 161 Z = snpEvaluator.Zmatrix(0) # evaluation at lowest frequency 162 resistance = [] 163 nrOfPorts = snpEvaluator.nbPorts() 164 for r in range(nrOfPorts): 165 for c in range(r, nrOfPorts): 166 resistance.append(Z.param(r,c).real) 167 result = (snpEvaluator.nbPorts(), resistance) 168 else: 169 raise RuntimeError("Unknown impedance specification type", ) 170 if componentGroup.arrayedComponent: 171 if result[0] != 1: 172 raise RuntimeError("Model <%s> for array component has invalid #ports=%s: should be 1"%(componentGroup.models()[ componentGroup.defaultModelIndex ].name, str(result[0]))) 173 assert(len(result[1]) == 1) 174 R = result[1][0] 175 nbPorts = componentGroup.pinPortMap().nrPorts() 176 resistance = [] 177 for r in range(nbPorts): 178 for c in range(r, nbPorts): 179 if r == c: 180 resistance.append(R) 181 else: 182 #for impedance matrix, cross terms are 0 for arrayed components 183 resistance.append(0) 184 result = (nbPorts, resistance) 185 return result
186
187 @_printexception 188 -def _generateStimulusFileElectroThermal(fileName, sipiData, idealGround):
189 # 190 import datetime 191 import os 192 import empro.toolkit.analysis as sipi 193 pinHash = sipi._createPinHash() 194 instanceHash = sipi._createInstanceHash() 195 pinNetNames = sipi._createPinHashNetName() 196 pinNetTypes = sipi._createPinHashNetTypeString() 197 198 simData = sipiData.newSimulationData() 199 generateThermalPorts = simData.sParametersEnabled 200 201 stimulusLines = [] 202 203 electricalNameToLump = {} 204 vrmList = sipiData.getVrmList() 205 sinkList = sipiData.getSinkList() 206 207 lumped = 0 208 portNr = 0 209 for vrm in vrmList: 210 port = vrm 211 if port.hasSenseLine: 212 senseLumped, sensePortNr, stimulusLines = _generateSensePortStimulusElectro(port, stimulusLines, lumped, portNr, pinHash, pinNetTypes, idealGround) 213 lumped += 1 214 portNr +=1 215 lumped += 1 216 portNr += 1 217 if port.sourceType != 'PackagedVrm': 218 #we always assume to have all 3 switch ports 219 switchLumped, switchStimulusLines, voltage = _generateAllSwitchPortStimulusElectro(port, lumped, portNr, pinHash, pinNetTypes, idealGround) 220 name = vrm.name 221 electricalNameToLump[vrm.name] = lumped 222 plusPinNames = [x.name for x in port.plusPins()] 223 minusPinNames = [x.name for x in port.minusPins()] 224 stimulusLines.append("Electric %(lumped)d:" % vars()) 225 stimulusLines.append(" name: %(name)s" % vars()) 226 stimulusLines.append(" port: %(portNr)d" % vars()) 227 228 for pinName in plusPinNames: 229 pinHashNr = pinHash[pinName] 230 pinNetType = pinNetTypes[pinHashNr] 231 if idealGround and pinNetType=="gnd": 232 stimulusLines.append(" pluspin: 0") 233 else: 234 stimulusLines.append(" pluspin: %(pinHashNr)d %(pinNetType)s R=0 name=%(pinName)s" % vars()) 235 236 for pinName in minusPinNames: 237 pinHashNr = pinHash[pinName] 238 pinNetType = pinNetTypes[pinHashNr] 239 if idealGround and pinNetType=="gnd": 240 stimulusLines.append(" minpin: 0") 241 else: 242 stimulusLines.append(" minpin: %(pinHashNr)d %(pinNetType)s R=0 name=%(pinName)s" % vars()) 243 244 if port.sourceType == 'PackagedVrm': 245 resValue = float(port.resistance) 246 if resValue>1e-12: 247 stimulusLines.append(" load: resistor R=%(resValue)f" % vars()) 248 else: 249 stimulusLines.append(" load: short" % vars()) 250 else: 251 stimulusLines.append(" load: short" % vars()) 252 253 if port.sourceType == 'PackagedVrm': 254 voltage = float(port.voltage) 255 stimulusLines.append(" source: voltage V=%f" % (voltage)) 256 if port.hasSenseLine: 257 senseVoltage = float(port.senseVoltage) 258 stimulusLines[-1]+= " sense %d %f" %(senseLumped,senseVoltage) 259 if port.sourceType != 'PackagedVrm': 260 inputVoltage = float(port.inputVoltage) 261 stimulusSourceType = port.sourceType.split("Discrete")[1] 262 stimulusLines[-1]+= " switch %s %d %d %d %f" %(stimulusSourceType,switchLumped[0],switchLumped[1],switchLumped[2],inputVoltage) 263 stimulusLines += switchStimulusLines 264 lumped += 3 265 portNr += 3 266 267 for sink in sinkList: 268 port = sink 269 lumped += 1 270 name = sink.name 271 electricalNameToLump[sink.name] = lumped 272 plusPinNames = [x.name for x in port.plusPins()] 273 minusPinNames = [x.name for x in port.minusPins()] 274 275 stimulusLines.append("Electric %(lumped)d:" % vars()) 276 portNr += 1 277 stimulusLines.append(" name: %(name)s" % vars()) 278 stimulusLines.append(" port: %(portNr)d" % vars()) 279 280 if sink.pinCurrentModel=="EqualVoltage": 281 for pinName in plusPinNames: 282 pinHashNr = pinHash[pinName] 283 pinNetType = pinNetTypes[pinHashNr] 284 if idealGround and pinNetType=="gnd": 285 stimulusLines.append(" pluspin: 0") 286 else: 287 stimulusLines.append(" pluspin: %(pinHashNr)d %(pinNetType)s R=0 name=%(pinName)s" % vars()) 288 289 for pinName in minusPinNames: 290 pinHashNr = pinHash[pinName] 291 pinNetType = pinNetTypes[pinHashNr] 292 if idealGround and pinNetType=="gnd": 293 stimulusLines.append(" minpin: 0") 294 else: 295 stimulusLines.append(" minpin: %(pinHashNr)d %(pinNetType)s R=0 name=%(pinName)s" % vars()) 296 resistance = float(sink.resistance) 297 stimulusLines.append(" load: resistor R=%(resistance)f" % vars()) 298 current = -float(sink.current) 299 stimulusLines.append(" source: current I=%(current)f" % vars()) 300 else: 301 current = -float(sink.current) 302 currentPerPin = current/max(1.0,len(plusPinNames)) 303 resistancePerPin = len(plusPinNames) * float(sink.resistance) 304 for pinName in plusPinNames: 305 pinHashNr = pinHash[pinName] 306 pinNetType = pinNetTypes[pinHashNr] 307 if idealGround and pinNetType=="gnd": 308 stimulusLines.append(" pluspin: 0") 309 else: 310 stimulusLines.append(" pluspin: %(pinHashNr)d %(pinNetType)s R=%(resistancePerPin)f I=%(currentPerPin)f " % vars()) 311 for pinName in minusPinNames: 312 pinHashNr = pinHash[pinName] 313 pinNetType = pinNetTypes[pinHashNr] 314 if idealGround and pinNetType=="gnd": 315 stimulusLines.append(" minpin: 0") 316 else: 317 stimulusLines.append(" minpin: %(pinHashNr)d %(pinNetType)s R=0 name=%(pinName)s" % vars()) 318 stimulusLines.append(" load: resistor R=0" % vars()) 319 320 for componentGroup in sipiData.getComponentModelGroupList(): 321 nbPorts = 0 322 nbPorts, resistance = _getDCResistance(componentGroup) 323 pinPortMap = componentGroup.pinPortMap() 324 if pinPortMap.nrPorts() != nbPorts: 325 raise RuntimeError("nbPorts of component (=%d) and nbPorts of impedance model (=%d) must be identical" % (pinPortMap.nrPorts(), nbPorts)) 326 327 if nbPorts == 1 and componentGroup.pinPortMap().nrPins()==2: 328 for componentInstance in componentGroup.instances(): 329 plusPinNames = [] 330 minusPinNames = [] 331 332 lumped += 1 333 name = componentInstance.name 334 electricalNameToLump[componentInstance.name] = lumped 335 336 stimulusLines.append("Electric %(lumped)d:" % vars()) 337 portNr += 1 338 stimulusLines.append(" name: %(name)s" % vars()) 339 stimulusLines.append(" port: %(portNr)d" % vars()) 340 341 # pins 342 component = componentInstance.instance() 343 pin1 = component.pins()[0] 344 pin2 = component.pins()[1] 345 pinName1 = component.name + "." + pin1.name 346 pinName2 = component.name + "." + pin2.name 347 plusPinNames = [pinName1] 348 minusPinNames = [pinName2] 349 for pinName in plusPinNames: 350 pinHashNr = pinHash[pinName] 351 pinNetType = pinNetTypes[pinHashNr] 352 if idealGround and pinNetType=="gnd": 353 stimulusLines.append(" pluspin: 0") 354 else: 355 stimulusLines.append(" pluspin: %(pinHashNr)d %(pinNetType)s R=0 name=%(pinName)s" % vars()) 356 357 for pinName in minusPinNames: 358 pinHashNr = pinHash[pinName] 359 pinNetType = pinNetTypes[pinHashNr] 360 if idealGround and pinNetType=="gnd": 361 stimulusLines.append(" minpin: 0") 362 else: 363 stimulusLines.append(" minpin: %(pinHashNr)d %(pinNetType)s R=0 name=%(pinName)s" % vars()) 364 365 stimulusLines.append(" load: resistor R=%f" % resistance[0]) 366 stimulusLines.append("\n") 367 # multi-port 368 else: 369 for componentInstance in componentGroup.instances(): 370 lumped += 1 371 electricalNameToLump[componentInstance.name] = lumped 372 name = componentInstance.name 373 374 stimulusLines.append("Electric %(lumped)d:" % vars()) 375 stimulusLines.append(" nrOfPorts: %(nbPorts)d" % vars()) 376 stimulusLines.append(" name: %(name)s" % vars()) 377 378 # pins 379 componentName = componentInstance.instance().name 380 for localPortId, pinNames in pinPortMap.getPinNamesForPortNumbers(True): 381 portNr += 1 382 stimulusLines.append( " port[%d]: %d" % (localPortId, portNr) ) 383 plusPins = pinNames[0] 384 minPins = pinNames[1] 385 for pin in plusPins: 386 pinName = componentName + "." + pin 387 pinHashNr = pinHash[pinName] 388 pinNetType = pinNetTypes[pinHashNr] 389 if idealGround and pinNetType=="gnd": 390 stimulusLines.append(" pluspin[%(localPortId)d]: 0" % vars()) 391 else: 392 stimulusLines.append(" pluspin[%(localPortId)d]: %(pinHashNr)d %(pinNetType)s R=0 name=%(pinName)s" % vars()) 393 394 for pin in minPins: 395 pinName = componentName + "." + pin 396 pinHashNr = pinHash[pinName] 397 pinNetType = pinNetTypes[pinHashNr] 398 if idealGround and pinNetType=="gnd": 399 stimulusLines.append(" minpin[%(localPortId)d]: 0" % vars()) 400 else: 401 stimulusLines.append(" minpin[%(localPortId)d]: %(pinHashNr)d %(pinNetType)s R=0 name=%(pinName)s" % vars()) 402 # load 403 stimulusLines.append(" load: resistor R= %s" % " ".join([str(x) for x in resistance]) ) 404 stimulusLines.append("\n") 405 406 407 backGroundTemperature = float(simData.ambientConditions.backgroundTemperature) 408 zLowerEffHeatTransfer = max(1e-4,simData.ambientConditions._zLowerEvaluatedEffectiveHeatTransfer()) 409 zUpperEffHeatTransfer = max(1e-4,simData.ambientConditions._zUpperEvaluatedEffectiveHeatTransfer()) 410 411 portNr = 0 412 thermalComponentGroupList = sipiData.getThermalComponentGroupList() 413 for group in thermalComponentGroupList: 414 for source in group: 415 portNr += 1 416 name = source.name 417 instance = source.instance() 418 instHash = instanceHash[instance.name] 419 420 pinNames = [instance.name + "." + pin.name for pin in instance.pins()] 421 stimulusLines.append("Thermal %(portNr)d:" % vars()) 422 stimulusLines.append(" name: %(name)s" % vars()) 423 if generateThermalPorts: 424 stimulusLines.append(" port: %(portNr)d" % vars()) 425 426 generateR = isinstance(group.thermalResistance, empro.components.Package3RSpecification) 427 if generateR: 428 pinR = float(group.thermalResistance.pinResistance) 429 for pinName in pinNames: 430 pinNr = str(pinHash[pinName]) 431 if generateR: 432 stimulusLines.append(" pluspin: %(pinNr)s R=%(pinR)f name=%(pinName)s" % vars()) 433 else: 434 stimulusLines.append(" pluspin: %(pinNr)s name=%(pinName)s" % vars()) 435 436 if isinstance(group.thermalResistance, empro.components.Package3RSpecification): 437 if group.thermalResistance.useCaseToBoardResistance: 438 pinNr = str(instHash) 439 pinName = name + "..BOARD" 440 padR = float(group.thermalResistance.caseToBoardResistance) 441 stimulusLines.append(" pluspin: %(pinNr)s R=%(padR)f name=%(pinName)s" % vars()) 442 443 stimulusLines.append(" minpin: 0") 444 thermalSource = float(source.heatSource) 445 if source.sourceType in ["Disabled", "ElectricDissipation", "ElectricDissipationAndHeatSource","HeatSource"]: 446 if source.sourceType in ["Disabled", "ElectricDissipation"]: 447 thermalSource = 0.0 448 stimulusLines.append(" source: heat Q=%(thermalSource)f" % vars()) 449 elif source.sourceType in ["TemperatureSource"]: 450 temperatureSource = float(source.temperatureSource)-backGroundTemperature 451 stimulusLines.append(" source: temperature T=%(temperatureSource)f" % vars()) 452 453 eff = [] 454 for k,v in source.dissipationFactors.iteritems(): 455 strippedName = k 456 if k.startswith("VRM:"): 457 strippedName = strippedName[4:] 458 elif k.startswith("Sink:"): 459 strippedName = strippedName[5:] 460 elif k.startswith("ComponentInstance:"): 461 strippedName = strippedName[18:] 462 eff.append( (electricalNameToLump[strippedName], float(v) ) ) 463 464 if source.sourceType in ["ElectricDissipation", "ElectricDissipationAndHeatSource"]: 465 for es in eff: 466 electricSourceNr = es[0] 467 dissipationFactor = es[1] 468 stimulusLines.append(" electric: %(electricSourceNr)d %(dissipationFactor)f" % vars()) 469 470 if not (source.sourceType in ["TemperatureSource"] and isinstance(group.thermalResistance, empro.components.ToAmbientSpecification)): 471 stimulus = _generateThermalResistanceStimulus(group.thermalResistance, instance, zLowerEffHeatTransfer, zUpperEffHeatTransfer) 472 stimulusLines += stimulus 473 474 stimulusDesc = "\n".join(stimulusLines) 475 with open(long_path_util.resolveLongPath(fileName),"w") as stimulusFile: 476 stimulusFile.write(_generateStimulusHeader(sipiData)) 477 stimulusFile.write(stimulusDesc)
478
479 @_printexception 480 -def _generateStimulusHeader(sipiData):
481 import datetime 482 import os 483 import empro.toolkit.analysis as sipi 484 stimulusLines = [] 485 header = "StiFile 1.0\n" 486 header+= "# Generated " + str(datetime.datetime.now()) + "\n\n" 487 488 pinHash = sipi._createPinHash() 489 instanceHash = sipi._createInstanceHash() 490 pinNetNames = sipi._createPinHashNetName() 491 usedPins = sipi._pinsUsed(sipiData) 492 lumped = 0 493 494 vrmList = sipiData.getVrmList() 495 for vrm in vrmList: 496 if vrm.hasSenseLine: 497 lumped += 1 498 lumped += 1 499 port = vrm 500 name = vrm.name 501 voltage = float(vrm.voltage) 502 tolerance = float(vrm.tolerance) 503 plusNames = ";".join([x.name for x in port.plusPins()]) 504 minusNames = ";".join([x.name for x in port.minusPins()]) 505 plusNetNames = ";".join(list(set([ pinNetNames[ pinHash[x.name] ] for x in port.plusPins()]))) 506 stimulusLines.append("# Vrm;%(lumped)d;%(name)s;%(voltage)f;%(tolerance)f" % vars()) 507 stimulusLines.append("# VrmPlus;%(lumped)s;%(plusNames)s" % vars()) 508 stimulusLines.append("# VrmMinus;%(lumped)s;%(minusNames)s" % vars()) 509 stimulusLines.append("# VrmNetPlus;%(lumped)s;%(plusNetNames)s" % vars()) 510 if vrm.sourceType != 'PackagedVrm': 511 lumped += 3 512 513 sinkList = sipiData.getSinkList() 514 for sink in sinkList: 515 lumped += 1 516 port = sink 517 name = sink.name 518 tolerance = float(sink.tolerance) 519 current = float(sink.current) 520 plusNames = ";".join([x.name for x in port.plusPins()]) 521 minusNames = ";".join([x.name for x in port.minusPins()]) 522 plusNetNames = ";".join(list(set([ pinNetNames[ pinHash[x.name] ] for x in port.plusPins()]))) 523 stimulusLines.append("# Sink;%(lumped)d;%(name)s;%(current)f;%(tolerance)f" % vars()) 524 stimulusLines.append("# SinkPlus;%(lumped)s;%(plusNames)s" % vars()) 525 stimulusLines.append("# SinkMinus;%(lumped)s;%(minusNames)s" % vars()) 526 stimulusLines.append("# SinkNetPlus;%(lumped)s;%(plusNetNames)s" % vars()) 527 528 thermalLumped = 0 529 thermalComponentGroupList = sipiData.getThermalComponentGroupList() 530 for group in thermalComponentGroupList: 531 for source in group: 532 thermalLumped += 1 533 instance = source.instance() 534 heatSource = float(source.heatSource) 535 name = instance.name 536 plusNames = ";".join([x.name for x in instance.pins()]) 537 stimulusLines.append("# ThermalComponent;%(thermalLumped)d;%(name)s;%(heatSource)f" % vars()) 538 stimulusLines.append("# ThermalComponentPlus;%(thermalLumped)s;%(plusNames)s" % vars()) 539 540 for componentGroup in sipiData.getComponentModelGroupList(): 541 pinPortMap = componentGroup.pinPortMap() 542 if pinPortMap.nrPorts() == 1 and pinPortMap.nrPins()==2: 543 for componentInstance in componentGroup.instances(): 544 lumped += 1 545 component = componentInstance.instance() 546 name = component.name 547 stimulusLines.append("# ComponentModel;%(lumped)d;%(name)s" % vars()) 548 pinName1 = component.name + "." + component.pins()[0].name 549 pinName2 = component.name + "." + component.pins()[1].name 550 stimulusLines.append("# ComponentModelPlus;%(lumped)d;%(pinName1)s" % vars()) 551 stimulusLines.append("# ComponentModelMinus;%(lumped)d;%(pinName2)s" % vars()) 552 else: 553 for componentInstance in componentGroup.instances(): 554 lumped += 1 555 name = componentInstance.instance().name 556 stimulusLines.append("# ComponentModel;%(lumped)d;%(name)s" % vars()) 557 for localPortId, pinNames in pinPortMap.getPinNamesForPortNumbers(True): 558 plusPinNames = pinNames[0] 559 minusPinNames = pinNames[1] 560 561 for pin in plusPinNames: 562 pinName = name + "." + pin 563 stimulusLines.append("# ComponentModelPlus%(localPortId)d;%(lumped)d;%(pinName)s" % vars()) 564 for pin in minusPinNames: 565 pinName = name + "." + pin 566 stimulusLines.append("# ComponentModelMinus%(localPortId)d;%(lumped)d;%(pinName)s" % vars()) 567 568 569 stimulusLines.append("# Available Pins") 570 for k,v in pinHash.iteritems(): 571 stimulusLines.append("# AvailablePin;%(v)d;%(k)s" % vars()) 572 573 stimulusLines.append("# Available Instance Pins") 574 for k,v in instanceHash.iteritems(): 575 stimulusLines.append("# AvailableInstancePin;%(v)d;%(k)s" % vars()) 576 577 stimulusLines.append("# Used Pins") 578 for name in usedPins: 579 hash = pinHash[name] 580 stimulusLines.append("# UsedPin;%(hash)d;%(name)s" % vars()) 581 582 return header+"\n".join(stimulusLines) + "\n"
583
584 -def _generateSensePortStimulusElectro(vrm, stimulusLines, lumped, portNr, pinHash, pinNetTypes, idealGround = False):
585 lumped += 1 586 portNr += 1 587 sensePort = vrm.sensePort 588 name = 'sense_' + vrm.name 589 plusPinNames = [x.name for x in sensePort.plusPins()] 590 minusPinNames = [x.name for x in sensePort.minusPins()] 591 stimulusLines.append("Electric %(lumped)d:" % vars()) 592 stimulusLines.append(" name: %(name)s" % vars()) 593 stimulusLines.append(" port: %(portNr)d" % vars()) 594 for pinName in plusPinNames: 595 pinHashNr = pinHash[pinName] 596 pinNetType = pinNetTypes[pinHashNr] 597 if idealGround and pinNetType=="gnd": 598 stimulusLines.append(" pluspin: 0") 599 else: 600 stimulusLines.append(" pluspin: %(pinHashNr)d %(pinNetType)s R=0 name=%(pinName)s" % vars()) 601 602 for pinName in minusPinNames: 603 pinHashNr = pinHash[pinName] 604 pinNetType = pinNetTypes[pinHashNr] 605 if idealGround and pinNetType=="gnd": 606 stimulusLines.append(" minpin: 0") 607 else: 608 stimulusLines.append(" minpin: %(pinHashNr)d %(pinNetType)s R=0 name=%(pinName)s" % vars()) 609 610 stimulusLines.append(" load: open") 611 612 return lumped, portNr, stimulusLines
613
614 -def _generateSingleSwitchPortStimulusElectro(port, stimulusLines, lumped, portNr, pinHash, pinNetTypes, name, isBoostPort, sourceVal, idealGround = False, resValue = None):
615 lumped += 1 616 portNr += 1 617 plusPinNames = [x.name for x in port.plusPins()] 618 minusPinNames = [x.name for x in port.minusPins()] 619 stimulusLines.append("Electric %(lumped)d:" % vars()) 620 stimulusLines.append(" name: %(name)s" % vars()) 621 stimulusLines.append(" port: %(portNr)d" % vars()) 622 for pinName in plusPinNames: 623 pinHashNr = pinHash[pinName] 624 pinNetType = pinNetTypes[pinHashNr] 625 if idealGround and pinNetType=="gnd": 626 stimulusLines.append(" pluspin: 0") 627 else: 628 stimulusLines.append(" pluspin: %(pinHashNr)d %(pinNetType)s R=0 name=%(pinName)s" % vars()) 629 630 for pinName in minusPinNames: 631 pinHashNr = pinHash[pinName] 632 pinNetType = pinNetTypes[pinHashNr] 633 if idealGround and pinNetType=="gnd": 634 stimulusLines.append(" minpin: 0") 635 else: 636 stimulusLines.append(" minpin: %(pinHashNr)d %(pinNetType)s R=0 name=%(pinName)s" % vars()) 637 638 if resValue and resValue>1e-12: #only supported for buck converter 639 stimulusLines.append(" load: resistor R=%(resValue)f" % vars()) 640 stimulusLines.append(" source: voltage V=%f" %(sourceVal)) 641 elif isBoostPort: 642 stimulusLines.append(" load: short") 643 stimulusLines.append(" source: voltage V=%f" %(sourceVal)) 644 else: 645 stimulusLines.append(" load: open") 646 stimulusLines.append(" source: current I=%f" %(sourceVal)) 647 return lumped, stimulusLines
648
649 650 -def _generateAllSwitchPortStimulusElectro(vrm, lumped, portNr, pinHash, pinNetTypes, idealGround = False):
651 stimulusLines= [] 652 inputVoltage = float(vrm.inputVoltage) 653 dcVoltage = float(vrm.voltage) 654 R = None 655 if vrm.sourceType == 'DiscreteBuck': 656 R = float(vrm.resistance) 657 voltage = dcVoltage 658 boostVoltage = 0 659 ports = [vrm.upSwitch, vrm.lowSwitch, vrm.inductor] 660 names = ['upSwitch_' + vrm.name, 'lowSwitch_' + vrm.name, 'inductor_' + vrm.name] 661 elif vrm.sourceType == 'DiscreteBoost': 662 voltage = inputVoltage 663 boostVoltage = dcVoltage - inputVoltage 664 ports = [vrm.inductor, vrm.upSwitch, vrm.lowSwitch] 665 names = [ 'inductor_' + vrm.name, 'upSwitch_' + vrm.name, 'lowSwitch_' + vrm.name] 666 else: 667 voltage = 0 668 boostVoltage = dcVoltage 669 ports = [vrm.upSwitch, vrm.inductor, vrm.lowSwitch] 670 names = ['upSwitch_' + vrm.name, 'inductor_' + vrm.name, 'lowSwitch_' + vrm.name] 671 672 highLumped, stimulusLines = _generateSingleSwitchPortStimulusElectro(ports[0], stimulusLines, lumped, portNr, pinHash, pinNetTypes, names[0], False, 0, idealGround) 673 lowLumped, stimulusLines = _generateSingleSwitchPortStimulusElectro(ports[1], stimulusLines, lumped+1, portNr+1, pinHash, pinNetTypes, names[1], False, 0, idealGround) 674 outLumped, stimulusLines = _generateSingleSwitchPortStimulusElectro(ports[2], stimulusLines, lumped+2, portNr+2, pinHash, pinNetTypes, names[2], True, boostVoltage, idealGround, resValue = R) 675 switchLumped = [highLumped,lowLumped,outLumped] 676 return switchLumped, stimulusLines, voltage
677
678 @_printexception 679 -def _generateStimulusFileElectro(fileName, sipiData, idealGround = False):
680 # 681 import empro.toolkit.analysis as sipi 682 pinHash = sipi._createPinHash() 683 instanceHash = sipi._createInstanceHash() 684 simData = sipiData.newSimulationData() 685 generateThermalStimulus = False 686 generateElectroStimulus = True 687 688 lumped = 0 689 stimulusLines = [] 690 portNr = 0 691 692 vrmList = sipiData.getVrmList() 693 sinkList = sipiData.getSinkList() 694 pinNetNames = sipi._createPinHashNetName() 695 pinNetTypes = sipi._createPinHashNetTypeString() 696 697 698 for vrm in vrmList: 699 port = vrm 700 if port.hasSenseLine: 701 senseLumped, sensePortNr, stimulusLines = _generateSensePortStimulusElectro(port, stimulusLines, lumped, portNr, pinHash, pinNetTypes, idealGround) 702 lumped += 1 703 portNr +=1 704 lumped += 1 705 portNr += 1 706 if port.sourceType != 'PackagedVrm': 707 #we always assume to have all 3 switch ports 708 switchLumped, switchStimulusLines, voltage = _generateAllSwitchPortStimulusElectro(port, lumped, portNr, pinHash, pinNetTypes, idealGround) 709 name = port.name 710 plusPinNames = [x.name for x in port.plusPins()] 711 minusPinNames = [x.name for x in port.minusPins()] 712 713 stimulusLines.append("Electric %(lumped)d:" % vars()) 714 stimulusLines.append(" name: %(name)s" % vars()) 715 stimulusLines.append(" port: %(portNr)d" % vars()) 716 for pinName in plusPinNames: 717 pinHashNr = pinHash[pinName] 718 pinNetType = pinNetTypes[pinHashNr] 719 if idealGround and pinNetType=="gnd": 720 stimulusLines.append(" pluspin: 0") 721 else: 722 stimulusLines.append(" pluspin: %(pinHashNr)d %(pinNetType)s R=0 name=%(pinName)s" % vars()) 723 724 for pinName in minusPinNames: 725 pinHashNr = pinHash[pinName] 726 pinNetType = pinNetTypes[pinHashNr] 727 if idealGround and pinNetType=="gnd": 728 stimulusLines.append(" minpin: 0") 729 else: 730 stimulusLines.append(" minpin: %(pinHashNr)d %(pinNetType)s R=0 name=%(pinName)s" % vars()) 731 732 if port.sourceType == 'PackagedVrm': 733 resValue = float(port.resistance) 734 if resValue>1e-12: 735 stimulusLines.append(" load: resistor R=%(resValue)f" % vars()) 736 else: 737 stimulusLines.append(" load: short" % vars()) 738 else: 739 stimulusLines.append(" load: short" % vars()) 740 741 742 if port.sourceType == 'PackagedVrm': 743 voltage = float(port.voltage) 744 stimulusLines.append(" source: voltage V=%f" % (voltage)) 745 if port.hasSenseLine: 746 senseVoltage = float(port.senseVoltage) 747 stimulusLines[-1]+= " sense %d %f" %(senseLumped,senseVoltage) 748 if port.sourceType != 'PackagedVrm': 749 inputVoltage = float(port.inputVoltage) 750 stimulusSourceType = port.sourceType.split("Discrete")[1] 751 stimulusLines[-1]+= " switch %s %d %d %d %f" %(stimulusSourceType,switchLumped[0],switchLumped[1],switchLumped[2],inputVoltage) 752 stimulusLines += switchStimulusLines 753 lumped += 3 754 portNr += 3 755 756 for sink in sinkList: 757 port = sink 758 lumped += 1 759 portNr += 1 760 name = sink.name 761 762 plusPinNames = [x.name for x in port.plusPins()] 763 minusPinNames = [x.name for x in port.minusPins()] 764 765 stimulusLines.append("Electric %(lumped)d:" % vars()) 766 stimulusLines.append(" name: %(name)s" % vars()) 767 stimulusLines.append(" port: %(portNr)d" % vars()) 768 769 if sink.pinCurrentModel=="EqualVoltage": 770 for pinName in plusPinNames: 771 pinHashNr = pinHash[pinName] 772 pinNetType = pinNetTypes[pinHashNr] 773 if idealGround and pinNetType=="gnd": 774 stimulusLines.append(" pluspin: 0") 775 else: 776 stimulusLines.append(" pluspin: %(pinHashNr)d %(pinNetType)s R=0 name=%(pinName)s" % vars()) 777 778 for pinName in minusPinNames: 779 pinHashNr = pinHash[pinName] 780 pinNetType = pinNetTypes[pinHashNr] 781 if idealGround and pinNetType=="gnd": 782 stimulusLines.append(" minpin: 0") 783 else: 784 stimulusLines.append(" minpin: %(pinHashNr)d %(pinNetType)s R=0 name=%(pinName)s" % vars()) 785 786 resistance = float(sink.resistance) 787 stimulusLines.append(" load: resistor R=%(resistance)f" % vars()) 788 current = -float(sink.current) 789 stimulusLines.append(" source: current I=%(current)f" % vars()) 790 791 else: 792 current = -float(sink.current) 793 currentPerPin = current/max(1.0,len(plusPinNames)) 794 resistancePerPin = len(plusPinNames) * float(sink.resistance) 795 for pinName in plusPinNames: 796 pinHashNr = pinHash[pinName] 797 pinNetType = pinNetTypes[pinHashNr] 798 if idealGround and pinNetType=="gnd": 799 stimulusLines.append(" pluspin: 0") 800 else: 801 stimulusLines.append(" pluspin: %(pinHashNr)d %(pinNetType)s R=%(resistancePerPin)f I=%(currentPerPin)f " % vars()) 802 803 for pinName in minusPinNames: 804 pinHashNr = pinHash[pinName] 805 pinNetType = pinNetTypes[pinHashNr] 806 if idealGround and pinNetType=="gnd": 807 stimulusLines.append(" minpin: 0") 808 else: 809 stimulusLines.append(" minpin: %(pinHashNr)d %(pinNetType)s R=0 name=%(pinName)s" % vars()) 810 811 stimulusLines.append(" load: resistor R=0" % vars()) 812 813 814 for componentGroup in sipiData.getComponentModelGroupList(): 815 nbPorts = 0 816 if generateElectroStimulus: 817 nbPorts, resistance = _getDCResistance(componentGroup) 818 pinPortMap = componentGroup.pinPortMap() 819 if pinPortMap.nrPorts() != nbPorts: 820 raise RuntimeError("nbPorts of component (=%d) and nbPorts of impedance model (=%d) must be identical" % (pinPortMap.nrPorts(), nbPorts)) 821 822 # 1-port 823 if nbPorts == 1 and componentGroup.pinPortMap().nrPins()==2: 824 for componentInstance in componentGroup.instances(): 825 plusPinNames = [] 826 minusPinNames = [] 827 lumped += 1 828 portNr += 1 829 name = componentInstance.name 830 stimulusLines.append("Electric %(lumped)d:" % vars()) 831 stimulusLines.append(" name: %(name)s" % vars()) 832 stimulusLines.append(" port: %(portNr)d" % vars()) 833 # pins 834 component = componentInstance.instance() 835 pin1 = component.pins()[0] 836 pin2 = component.pins()[1] 837 pinName1 = component.name + "." + pin1.name 838 pinName2 = component.name + "." + pin2.name 839 840 plusPinNames = [pinName1] 841 minusPinNames = [pinName2] 842 for pinName in plusPinNames: 843 pinHashNr = pinHash[pinName] 844 pinNetType = pinNetTypes[pinHashNr] 845 if idealGround and pinNetType=="gnd": 846 stimulusLines.append(" pluspin: 0") 847 else: 848 stimulusLines.append(" pluspin: %(pinHashNr)d %(pinNetType)s R=0 name=%(pinName)s" % vars()) 849 850 minPinIsAttachedToGndNet = True 851 groundNetNames = empro.activeProject.geometry()[0]._netList().getGroundNetNames() 852 minPinIsAttachedToGndNet = pinNetNames[ pinHash[pinName2] ] in groundNetNames 853 854 for pinName in minusPinNames: 855 pinHashNr = pinHash[pinName] 856 pinNetType = pinNetTypes[pinHashNr] 857 if idealGround and pinNetType=="gnd": 858 stimulusLines.append(" minpin: 0") 859 else: 860 stimulusLines.append(" minpin: %(pinHashNr)d %(pinNetType)s R=0 name=%(pinName)s" % vars()) 861 862 stimulusLines.append(" load: resistor R=%f" % resistance[0]) 863 864 # multi-port 865 else: 866 for componentInstance in componentGroup.instances(): 867 lumped += 1 868 name = componentInstance.name 869 870 stimulusLines.append("Electric %(lumped)d:" % vars()) 871 stimulusLines.append(" nrOfPorts: %(nbPorts)d" % vars()) 872 stimulusLines.append(" name: %(name)s" % vars()) 873 874 # pins 875 componentName = componentInstance.instance().name 876 for localPortId, pinNames in pinPortMap.getPinNamesForPortNumbers(True): 877 portNr += 1 878 stimulusLines.append( " port[%d]: %d" % (localPortId, portNr) ) 879 plusPins = pinNames[0] 880 minPins = pinNames[1] 881 for pin in plusPins: 882 pinName = componentName + "." + pin 883 pinHashNr = pinHash[pinName] 884 pinNetType = pinNetTypes[pinHashNr] 885 if idealGround and pinNetType=="gnd": 886 stimulusLines.append(" pluspin[%(localPortId)d]: 0" % vars()) 887 else: 888 stimulusLines.append(" pluspin[%(localPortId)d]: %(pinHashNr)d %(pinNetType)s R=0 name=%(pinName)s" % vars()) 889 890 for pin in minPins: 891 pinName = componentName + "." + pin 892 pinHashNr = pinHash[pinName] 893 pinNetType = pinNetTypes[pinHashNr] 894 if idealGround and pinNetType=="gnd": 895 stimulusLines.append(" minpin[%(localPortId)d]: 0" % vars()) 896 else: 897 stimulusLines.append(" minpin[%(localPortId)d]: %(pinHashNr)d %(pinNetType)s R=0 name=%(pinName)s" % vars()) 898 899 # load 900 stimulusLines.append(" load: resistor R= %s" % " ".join([str(x) for x in resistance]) ) 901 902 stimulusDesc = "\n".join(stimulusLines) 903 with open(long_path_util.resolveLongPath(fileName),"w") as stimulusFile: 904 stimulusFile.write(_generateStimulusHeader(sipiData)) 905 stimulusFile.write(stimulusDesc)
906
907 @_printexception 908 -def _generateStimulusFileCombined(fileName, sipiData, idealGround = False):
909 if sipiData.analysisType==empro.toolkit.analysis.THERMAL: 910 return _generateStimulusFileThermalOnly(fileName, sipiData) 911 elif sipiData.analysisType==empro.toolkit.analysis.ELECTRO_THERMAL: 912 return _generateStimulusFileElectroThermal(fileName, sipiData,idealGround) 913 elif sipiData.analysisType==empro.toolkit.analysis.PIDC: 914 return _generateStimulusFileElectro(fileName, sipiData,idealGround) 915 else: 916 raise RuntimeError("Unknown Simulator Type")
917