1
2 from empro.toolkit import _printexception, Bunch
3 from docx import Document
4 from docx.shared import Inches
5 from topology import Topology
6 from topology import TopologyElement
7 from topology import TopologyConnection
8
10 text = u'<table class="table table-condensed">'
11 text+= u'<thead><tr>' + u''.join([u'<th>%s</th>' % h for h in header]) + u'</tr></thead>'
12 text+= u'<tbody>'
13 for d in data:
14 text += u'<tr>' + u''.join([u'<th>%s</th>' % x for x in d]) + u'</tr>\n'
15 text+= u'</tbody></table>'
16 return text
17
18
20 - def __init__(self, result, tableInfo, maxCurrent, maxTemperature, showViolatingCurrent, showViolatingT, **kwargs):
21 """
22 kwargs
23 'figures' any of "ALL", "TOP_BOTTOM", [id1,id2]. The default is 'ALL'
24 """
25 import os
26 import empro
27 self._result = result
28 self._tableInfo = tableInfo
29 self._maxCurrent = maxCurrent
30 self._maxTemperature = maxTemperature
31 self._showViolatingCurrent = showViolatingCurrent
32 self._showViolatingT = showViolatingT
33 self._showDifference = isinstance(self._result, empro.toolkit.analysis.dc.results.DCResultsDiff)
34 self.templatesLocation = '.'
35 self.figuresLocation = '.'
36 self.name = ''
37 self._vars = {}
38 self._temperatureFormat = "%4.1f"
39 self._voltageFormat = "%6.5f"
40 self._currentDensityFormat = "%5.1f"
41 self._epsRFormat = "%3.1f"
42 self._lossTangentFormat = "%4.3f"
43 self._conductivityFormat = "%7.0f S/m"
44 self._layerStatistics = self._result.layerStatistics
45 zSortedLayerNames = [ (k,v['zMax'],v['zMin']) for (k,v) in self._layerStatistics.iteritems()]
46 self._zSortedLayerNames = sorted(zSortedLayerNames, key=lambda x:(-x[2],-x[1]))
47 parts = empro.activeProject.geometry().flatList(True)
48 conductorsName = []
49 self.topBottomTemperatureLayersIds = []
50 self.topBottomVoltageLayersIds = []
51 self.topBottomCurrentLayersIds = []
52 self.topBottomPowerdensityLayersIds = []
53 for part in parts:
54 if isinstance(part,empro.geometry.OaConductiveLayer):
55 conductorsName.append(part.name)
56 conductiveLayers = []
57 for item in self._zSortedLayerNames:
58 if item[0] in conductorsName:
59 conductiveLayers.append(item)
60 self._nameToLayerId = {}
61 for k,v in self._layerStatistics.iteritems():
62 self._nameToLayerId[k] = v['layerId']
63 toKeepLayers = [self._nameToLayerId[conductiveLayers[-1][0]],self._nameToLayerId[conductiveLayers[0][0]]]
64 index = 0
65 if not self._tableInfo == []:
66 temperatureToKeepLayers = []
67 voltageToKeepLayers = []
68 currentToKeepLayers = []
69 powerdensityToKeepLayers = []
70 for i in range(len(self._tableInfo)-2):
71 if self._tableInfo[i][1] == True:
72 temperatureToKeepLayers.append(self._nameToLayerId[self._zSortedLayerNames[index][0]])
73 if self._tableInfo[i][2] == True:
74 voltageToKeepLayers.append(self._nameToLayerId[self._zSortedLayerNames[index][0]])
75 if self._tableInfo[i][3] == True:
76 currentToKeepLayers.append(self._nameToLayerId[self._zSortedLayerNames[index][0]])
77 if self._tableInfo[i][4] == True:
78 powerdensityToKeepLayers.append(self._nameToLayerId[self._zSortedLayerNames[index][0]])
79 index = index + 1
80 if self._tableInfo[len(self._tableInfo)-2][1] == True:
81 self.topBottomTemperatureLayersIds.append(-2)
82 if self._tableInfo[len(self._tableInfo)-1][1] == True:
83 self.topBottomTemperatureLayersIds.append(-3)
84 if self._tableInfo[len(self._tableInfo)-2][2] == True:
85 self.topBottomVoltageLayersIds.append(-2)
86 if self._tableInfo[len(self._tableInfo)-1][2] == True:
87 self.topBottomVoltageLayersIds.append(-3)
88 if self._tableInfo[len(self._tableInfo)-2][3] == True:
89 self.topBottomCurrentLayersIds.append(-2)
90 if self._tableInfo[len(self._tableInfo)-1][3] == True:
91 self.topBottomCurrentLayersIds.append(-3)
92 if self._tableInfo[len(self._tableInfo)-2][4] == True:
93 self.topBottomPowerdensityLayersIds.append(-2)
94 if self._tableInfo[len(self._tableInfo)-1][4] == True:
95 self.topBottomPowerdensityLayersIds.append(-3)
96 self._temperatureIds = [-1]+[v['layerId'] for k,v in self._layerStatistics.iteritems() if v['layerId'] not in temperatureToKeepLayers]
97 self._voltageIds = [-1]+[v['layerId'] for k,v in self._layerStatistics.iteritems() if v['layerId'] not in voltageToKeepLayers]
98 self._currentIds = [-1]+[v['layerId'] for k,v in self._layerStatistics.iteritems() if v['layerId'] not in currentToKeepLayers]
99 self._powerdensityIds = [-1]+[v['layerId'] for k,v in self._layerStatistics.iteritems() if v['layerId'] not in powerdensityToKeepLayers]
100 self._bottomTopIds = [-1]+[v['layerId'] for k,v in self._layerStatistics.iteritems() if v['layerId'] not in toKeepLayers]
101 self._figuresOptions = kwargs.get('figures','ALL')
102 self._topBottomFigures = True
103 self.progressCallback = self._dummyCallback
104
107
109 import datetime
110 import empro
111 parts = empro.activeProject.geometry().flatList(True)
112 substrateInfo = {}
113 diels = {}
114 vias = {}
115 conductors = {}
116 for part in parts:
117 if isinstance(part,empro.geometry.OaLayout):
118 self._vars['designName'] = part._designRef.cell
119 if isinstance(part,empro.geometry.OaDielectricLayer):
120 epsR = '---'
121 lossTangent = '---'
122 m = empro.activeProject.materials()[part.material.name]
123 if hasattr(m.details.electricProperties.parameters,'relativePermittivity'):
124 epsR = m.details.electricProperties.parameters.relativePermittivity
125 if hasattr(m.details.electricProperties.parameters,'lossTangent'):
126 lossTangent = m.details.electricProperties.parameters.lossTangent
127 diels[part.name] = Bunch(name=part.name,materialName=part.material.name,thickness=part.thickness,layerNumber=part._layerNumber,Er=epsR,lossTangent=lossTangent)
128 if isinstance(part,empro.geometry.OaConductiveLayer):
129 conductivity = '---'
130 m = empro.activeProject.materials()[part.material.name]
131 if hasattr(m.details.electricProperties.parameters,'conductivity'):
132 conductivity = m.details.electricProperties.parameters.conductivity
133 conductors[part.name] = Bunch(name=part.name,materialName=part.material.name,thickness=part.thickness,layerNumber=part._layerNumber,conductivity=conductivity)
134 if isinstance(part,empro.geometry.OaViaLayer):
135 vias[part.name] = Bunch(name=part.name,materialName=part.material.name,layerNumber=part._layerNumber)
136
137 substrateInfo['conductors'] = conductors
138 substrateInfo['dielectrics'] = diels
139 substrateInfo['vias'] = vias
140 self._vars['substrate'] = substrateInfo
141 try:
142 self._vars['analysisName'] = self._result.resultName
143 except:
144 self._vars['analysisName'] = "%s vs %s" % (tuple(self._result.resultNames))
145 self._vars['reportGenerationTime'] = datetime.datetime.now().strftime('%Y-%m-%d %H:%M')
146
148 import os
149 self.name = os.path.split(targetFileName)[1]
150 self._fillVariables()
151 self._generateFigures()
152 text = u'<!DOCTYPE html><html lang="en">'
153 text += self._head()
154 text += u'<body>'
155 text += self._leadIn()
156 text += self._overview()
157 text += self._powerGraph()
158 text += self._designInfo()
159 text += self._sinks()
160 text += self._vrms()
161 text += self._vias()
162 text += self._thermalComponents()
163 text += self._layers()
164 text += u'</body>'
165 text += '</html>'
166 return text
167
193
196
198 import string
199 import os
200 fn = os.path.join(self.templatesLocation,'head.html')
201 template = string.Template(open(fn).read())
202 keyValues = self._variables()
203 return template.safe_substitute(keyValues)
204
206 import string
207 import os
208 fn = os.path.join(self.templatesLocation,'leadIn.html')
209 template = string.Template(open(fn).read())
210 keyValues = self._variables()
211 return template.safe_substitute(keyValues)
212
241
243 import string
244 import os
245 fn = os.path.join(self.templatesLocation,'powerGraph.html')
246 template = string.Template(open(fn).read())
247 keyValues = self._variables()
248 pwrTreeImgNm = os.path.join(self.figuresLocation,"figures_for_"+self.name,"powerGraph.png")
249 import empro
250 import empro.gui
251 import empro.toolkit.analysis.dc.output
252 scn = empro.gui.GraphicsScene()
253 empro.toolkit.analysis.dc.output._powerGraphSceneFromResults(scn,self._result)
254 scn._save(pwrTreeImgNm)
255
256
257 picLoc = os.path.join(r"./","figures_for_"+self.name,"powerGraph.png")
258 picLoc = picLoc.replace('\\','/')
259 powerGraphImg = '<img src="%(picLoc)s"></img>' % vars()
260 if not self._result.vrms or not self._result.sinks:
261 self._vars['powerGraph'] = ""
262 else:
263 self._vars['powerGraph'] = powerGraphImg
264 return template.safe_substitute(keyValues)
265
267 import string
268 import os
269 fn = os.path.join(self.templatesLocation,'vrms.html')
270 template = string.Template(open(fn).read())
271
272 vrms = []
273 for index, vrm in enumerate(self._result.vrms):
274 row = [vrm.name, vrm.sourceVoltage, vrm.outputVoltage ,vrm.outputCurrent, vrm.tolerance, vrm.margin]
275 if not self._showDifference:
276 row.append(vrm.result)
277 vrms.append(row)
278
279 deltaSymbol = ''
280 header = ["Name", deltaSymbol+"Source\nVoltage [V]", deltaSymbol+"Output\nVoltage [V]", deltaSymbol+"Output\nCurrent [A]", "Tolerance", deltaSymbol+"Margin [V]", "Pass/Fail"]
281 self._vars['vrmTable'] = _htmlTable(header,vrms)
282
283 keyValues = self._variables()
284 return template.safe_substitute(keyValues)
285
287 import empro
288 import math
289 self.vias = []
290 lengthUnit = empro.units.unitByAbbreviation("um")
291 areaUnit = empro.units.unitByAbbreviation("squm")
292 celsius = empro.units.unitByAbbreviation("degC")
293 if self._showDifference:
294 celsius = empro.units.unitByAbbreviation("K")
295 localParamList = empro.activeProject.parameters().clone()
296 localParamList.append("Radius",0.0)
297 localParamList.append("Plating",0.0)
298 localParamList.append("Area",0.0)
299 numberOfViolatingVias = 0
300 numberOfViolatingViasT = 0
301 for key, via in self._result.viaCurrents.iteritems():
302 viaCurrent = float(via[0])
303 viaTemperature = celsius.fromReferenceUnits(self._result.viaMaxTemperatures.get(key,298.15))
304 radius, plating = self._result.viaRadiusThickness.get(key,(-1,-1))
305 localParamList.setFormula("Radius",radius)
306 localParamList.setFormula("Plating",plating)
307 area = math.pi*radius*radius
308 if plating>0.0:
309 area -= math.pi*(radius-plating)*(radius-plating)
310 localParamList.setFormula("Area",area)
311 maxCurrent = empro.core.Expression(self._maxCurrent).evaluate(localParamList)
312 maxT = celsius.fromReferenceUnits(empro.core.Expression(self._maxTemperature).evaluate(localParamList))
313
314 currentIsPassed = False
315 if float(via[0]) < maxCurrent:
316 currentIsPassed = True
317 else:
318 numberOfViolatingVias += 1
319 tempIsPassed = viaTemperature < maxT
320 if not tempIsPassed:
321 numberOfViolatingViasT += 1
322
323 hideRow = (self._showViolatingCurrent and currentIsPassed) or (self._showViolatingT and tempIsPassed)
324 radiusStr = lengthUnit.fromReferenceUnits(radius)
325 platingStr = lengthUnit.fromReferenceUnits(plating)
326 areaStr = areaUnit.fromReferenceUnits(area)
327 passOrFail = ""
328 if (not currentIsPassed) and tempIsPassed:
329 passOrFail = "Current fail"
330 elif currentIsPassed and (not tempIsPassed):
331 passOrFail = "Temperature fail"
332 elif (not currentIsPassed) and (not tempIsPassed):
333 passOrFail = "Both Current and T fail"
334 else:
335 passOrFail = "Pass"
336 if not hideRow:
337 if (not currentIsPassed) or (not tempIsPassed):
338 row = [str(key), viaCurrent, viaTemperature, radiusStr, platingStr, areaStr, passOrFail]
339 self.vias.append(row)
340 self.maximumCurrent = "Maximum Current: " + self._maxCurrent + " (" + "%d"%numberOfViolatingVias + " Violations)"
341 self.maximumTemperature = "Maximum Temperature: " + self._maxTemperature + " (" + "%d"%numberOfViolatingViasT + " Violations)"
342 deltaSymbol = ''
343 self.viasHeader = ["Id", deltaSymbol+"Current [A]", deltaSymbol+"T [degC]", deltaSymbol+"Radius [um]", deltaSymbol+"Plating [um]", deltaSymbol+"Area [um**2]", "Pass/Fail"]
344 return
345
347 import string
348 import os
349 fn = os.path.join(self.templatesLocation,'vias.html')
350 template = string.Template(open(fn).read())
351 self._viasBulk()
352 self._vars['maxCurrent'] = self.maximumCurrent
353 self._vars['maxTemperature'] = self.maximumTemperature
354 self._vars['viasTable'] = _htmlTable(self.viasHeader, self.vias)
355 keyValues = self._variables()
356 return template.safe_substitute(keyValues)
357
359 import string
360 import os
361 fn = os.path.join(self.templatesLocation,'thermalComponents.html')
362 template = string.Template(open(fn).read())
363
364 import empro
365 celsius = empro.units.unitByAbbreviation("degC")
366 if self._showDifference:
367 celsius = empro.units.unitByAbbreviation("K")
368 degUnit = 'T ['+celsius.abbreviation()+']'
369 degSymbol = '['+celsius.abbreviation()+']'
370
371 comps = []
372 for index, source in enumerate(self._result.thermalComponents):
373 if hasattr(source,'heat'):
374 row = [source.name, source.heat, '---','---']
375 else:
376 row = [source.name, source.heatDie, source.heatBoard, source.heatCase]
377 if hasattr(source,"temperature"):
378 row += [self._temperatureFormat % celsius.fromReferenceUnits(source.temperature), "---","---","---", source.bareBoardThermalResistance]
379 else:
380 row += ["---", self._temperatureFormat % celsius.fromReferenceUnits(source.temperatureBoard), self._temperatureFormat % celsius.fromReferenceUnits(source.temperatureDie), self._temperatureFormat % celsius.fromReferenceUnits(source.temperatureCase), source.bareBoardThermalResistance]
381 comps.append(row)
382
383 deltaSymbol = ''
384
385 header = ["Name", deltaSymbol+"Source [W]", deltaSymbol+"Heat To\nBoard [W]", deltaSymbol+"Heat To\nCase [W]", deltaSymbol+degUnit,deltaSymbol+"Case Bottom\n"+degUnit, deltaSymbol+"Die "+degUnit, deltaSymbol+"Case Top "+degUnit, deltaSymbol+"Thermal Resistance\nBare Board [K/W]"]
386 self._vars['thermalComponentsTable'] = _htmlTable(header,comps)
387
388 keyValues = self._variables()
389 return template.safe_substitute(keyValues)
390
392 import string
393 import os
394 fn = os.path.join(self.templatesLocation,'sinks.html')
395 template = string.Template(open(fn).read())
396
397 sinks = []
398 for index, sink in enumerate(self._result.sinks):
399 row = [sink.name, sink.sourceCurrent, sink.vrmVoltage,sink.inputVoltage,sink.resistance, sink.tolerance, sink.margin]
400 if not self._showDifference:
401 row.append(sink.result)
402 sinks.append(row)
403
404 deltaSymbol = ''
405 header = ["Name", "Source\nCurrent [A]", "VRM\nVoltage [V]", deltaSymbol+"Input\n Voltage [V]", deltaSymbol+"Resistance\n [Ohm]", "Tolerance", deltaSymbol+"Margin [V]", "Pass/Fail"]
406 self._vars['sinksTable'] = _htmlTable(header,sinks)
407
408 keyValues = self._variables()
409 return template.safe_substitute(keyValues)
410
411
424
425 def _asLength(x):
426 return '%f %s' % (lengthUnit.fromReferenceUnits(float(x)), lengthUnit.abbreviation())
427
428 fn = os.path.join(self.templatesLocation,'designInfo.html')
429 template = string.Template(open(fn).read())
430
431 dielInfo = []
432 for k,v in self._vars['substrate']['dielectrics'].iteritems():
433 dielInfo.append([v.name, v.materialName, _asLength(abs(float(v.thickness))),_formatOr(self._epsRFormat, v.Er), _formatOr(self._lossTangentFormat,v.lossTangent)])
434
435 condInfo = []
436 for k,v in self._vars['substrate']['conductors'].iteritems():
437 condInfo.append([v.name, v.materialName, _asLength(abs(float(v.thickness))),_formatOr(self._conductivityFormat,v.conductivity)])
438
439 viaInfo = []
440 for k,v in self._vars['substrate']['vias'].iteritems():
441 viaInfo.append([v.name, v.materialName])
442
443 self._vars['dielectricsTable'] = _htmlTable(['Name','Material','Thickness','Er','LossTangent'],dielInfo)
444 self._vars['conductorsTable'] = _htmlTable(['Name','Material','Thickness','Conductivity'],condInfo)
445 self._vars['viasTable'] = _htmlTable(['Name','Material'],viaInfo)
446 keyValues = self._variables()
447
448 return template.safe_substitute(keyValues)
449
451 import string
452 import os
453 import empro
454
455 temperatureMetaData = [x for x in self._figuresMetaData if 'outputType' in x and x['outputType']=='temperature']
456 voltageMetaData = [x for x in self._figuresMetaData if 'outputType' in x and x['outputType']=='voltage']
457 powerLossDensityMetaData = [x for x in self._figuresMetaData if 'outputType' in x and x['outputType']=='powerLossDensity']
458 currentMetaData = [x for x in self._figuresMetaData if 'outputType' in x and x['outputType']=='current']
459
460 fn = os.path.join(self.templatesLocation,'layers.html')
461 template = string.Template(open(fn).read())
462
463 celsius = empro.units.unitByAbbreviation("degC")
464 if self._showDifference:
465 celsius = empro.units.unitByAbbreviation("K")
466 degUnit = 'T ['+celsius.abbreviation()+']'
467 degSymbol = '['+celsius.abbreviation()+']'
468
469 temperatureDataIds = set([int(x['layerId']) for x in temperatureMetaData])
470 voltageDataIds = set([int(x['layerId']) for x in voltageMetaData])
471 currentDataIds = set([int(x['layerId']) for x in currentMetaData])
472 powerLossDensityDataIds = set([int(x['layerId']) for x in powerLossDensityMetaData])
473
474 layerInfo = []
475 for layer in self._zSortedLayerNames:
476 layerName = layer[0]
477 layerStats = self._layerStatistics[layerName]
478 layerNr = layerStats['layerId']
479 layerLinks = ''
480 if temperatureMetaData and layerNr in temperatureDataIds:
481 layerLinks += r'<a class="btn btn-primary btn-sm" href="#temp_%(layerNr)d"><span class="glyphicon glyphicon-link"></span> T</a>' % vars()
482 if voltageMetaData and layerNr in voltageDataIds:
483 layerLinks +=r'<a class="btn btn-primary btn-sm" href="#voltage_%(layerNr)d"><span class="glyphicon glyphicon-link"></span> V</a>' % vars()
484 if currentMetaData and layerNr in currentDataIds:
485 layerLinks +=r'<a class="btn btn-primary btn-sm" href="#current_%(layerNr)d"><span class="glyphicon glyphicon-link"></span> A</a>' % vars()
486 if powerLossDensityMetaData and layerNr in powerLossDensityDataIds:
487 layerLinks +=r'<a class="btn btn-primary btn-sm" href="#powerLossDensity_%(layerNr)d"><span class="glyphicon glyphicon-link"></span> W/(m*m)</a>' % vars()
488 row = [layerName, layerLinks, self._temperatureFormat % celsius.fromReferenceUnits(layerStats["temperatureMin"]), self._temperatureFormat % celsius.fromReferenceUnits(layerStats["temperatureMax"]), self._currentDensityFormat % (layerStats["currentMin"]*1e-6),self._currentDensityFormat % (layerStats["currentMax"]*1e-6),self._voltageFormat % layerStats["voltageMin"],self._voltageFormat % layerStats["voltageMax"]]
489 layerInfo.append(row)
490
491 for layerId in [-2,-3]:
492 layerName = {-2 : "top", -3 : "bottom"}[layerId]
493
494 layerNr = layerId
495 layerLinks = ''
496 if temperatureMetaData and layerNr in temperatureDataIds:
497 layerLinks += r'<a class="btn btn-primary btn-sm" href="#temp_%(layerNr)d"><span class="glyphicon glyphicon-link"></span> T</a>' % vars()
498 if voltageMetaData and layerNr in voltageDataIds:
499 layerLinks +=r'<a class="btn btn-primary btn-sm" href="#voltage_%(layerNr)d"><span class="glyphicon glyphicon-link"></span> V</a>' % vars()
500 if currentMetaData and layerNr in currentDataIds:
501 layerLinks +=r'<a class="btn btn-primary btn-sm" href="#current_%(layerNr)d"><span class="glyphicon glyphicon-link"></span> A</a>' % vars()
502 if powerLossDensityMetaData and layerNr in powerLossDensityDataIds:
503 layerLinks +=r'<a class="btn btn-primary btn-sm" href="#powerLossDensity_%(layerNr)d"><span class="glyphicon glyphicon-link"></span> W/(m*m)</a>' % vars()
504
505
506 row = [layerName, layerLinks, '---', '---', '---','---','---','---']
507 layerInfo.append(row)
508
509
510
511 deltaSymbol = ''
512 header = ["Layer", "", deltaSymbol + "Min "+degUnit,deltaSymbol + deltaSymbol+"Max "+degUnit, deltaSymbol+"Min Current\nDensity [A/mm**2]", deltaSymbol+"Max Current\nDensity [A/mm**2]",deltaSymbol+"Min\nVoltage [V]", deltaSymbol+"Max\nVoltage [V]"]
513 self._vars['layersTable'] = _htmlTable(header,layerInfo)
514
515 tempHeader = ['Name','Scale','Plot']
516 voltageHeader = ['Name','Scale','Plot']
517 currentHeader = ['Name','Scale','Plot']
518 powerLossDensityHeader = ['Name','Scale','Plot']
519 tempInfo = []
520 voltageInfo = []
521 currentInfo = []
522 powerLossDensityInfo = []
523
524
525 for layer in self._zSortedLayerNames:
526 layerName = layer[0]
527 layerStats = self._layerStatistics[layerName]
528 metaData = [x for x in temperatureMetaData if 'layerId' in x and int(x['layerId'])==int(layerStats['layerId'])]
529 if not metaData:
530 continue
531 metaData = metaData[0]
532 picLoc = metaData['fileName']
533
534
535 picName = os.path.basename(picLoc)
536 picLoc = os.path.join(r"./","figures_for_"+self.name,picName)
537 picLoc = picLoc.replace('\\','/')
538 scaleStr = (self._temperatureFormat + " - " + self._temperatureFormat + " " + degSymbol) % (celsius.fromReferenceUnits(float(metaData["minValue"])),celsius.fromReferenceUnits(float(metaData["maxValue"])))
539 layerNr = layerStats['layerId']
540 layerAnchor = r'<span id="temp_%(layerNr)d">%(layerName)s</span>' % vars()
541 row = [layerAnchor, scaleStr, '<img src="%(picLoc)s"></img>' % vars()]
542 tempInfo.append(row)
543
544 for layerId in [-2,-3]:
545 layerName = {-2 : "top", -3 : "bottom"}[layerId]
546 metaData = [x for x in temperatureMetaData if 'layerId' in x and int(x['layerId'])==layerId]
547 if not metaData:
548 continue
549 metaData = metaData[0]
550 picLoc = metaData['fileName']
551
552
553 picName = os.path.basename(picLoc)
554 picLoc = os.path.join(r"./","figures_for_"+self.name,picName)
555 picLoc = picLoc.replace('\\','/')
556 scaleStr = "%6.5f - %6.5f [V]" % (float(metaData["minValue"]),float(metaData["maxValue"]))
557 layerAnchor = r'<span id="temp_%(layerId)d">%(layerName)s</span>' % vars()
558 row = [layerAnchor, scaleStr, '<img src="%(picLoc)s"></img>' % vars()]
559 tempInfo.append(row)
560
561 prettyName = { 'power' : "Power" , 'ground' : "Ground", 'signal' : "Signal" }
562
563 for layer in self._zSortedLayerNames:
564 layerName = layer[0]
565 layerStats = self._layerStatistics[layerName]
566 for netType in ["power","ground","signal"]:
567 metaData = [x for x in voltageMetaData if 'layerId' in x and int(x['layerId'])==int(layerStats['layerId']) and 'netType' in x and x['netType']==netType]
568 if not metaData:
569 continue
570 metaData = metaData[0]
571 picLoc = metaData['fileName']
572
573
574 picName = os.path.basename(picLoc)
575 picLoc = os.path.join(r"./","figures_for_"+self.name,picName)
576 picLoc = picLoc.replace('\\','/')
577 scaleStr = "%6.5f - %6.5f [V]" % (float(metaData["minValue"]),float(metaData["maxValue"]))
578 layerNr = layerStats['layerId']
579 prettyNetType = prettyName[netType]
580 layerAnchor = r'<span id="voltage_%(layerNr)d">%(layerName)s - %(prettyNetType)s</span>' % vars()
581 row = [layerAnchor, scaleStr, '<img src="%(picLoc)s"></img>' % vars()]
582 voltageInfo.append(row)
583
584 for layerId in [-2,-3]:
585 layerName = {-2 : "top", -3 : "bottom"}[layerId]
586 for netType in ["power","ground","signal"]:
587 metaData = [x for x in voltageMetaData if 'layerId' in x and int(x['layerId'])==layerId and 'netType' in x and x['netType']==netType]
588 if not metaData:
589 continue
590 metaData = metaData[0]
591 picLoc = metaData['fileName']
592
593
594 picName = os.path.basename(picLoc)
595 picLoc = os.path.join(r"./","figures_for_"+self.name,picName)
596 picLoc = picLoc.replace('\\','/')
597 scaleStr = "%6.5f - %6.5f [V]" % (float(metaData["minValue"]),float(metaData["maxValue"]))
598 prettyNetType = prettyName[netType]
599 layerAnchor = r'<span id="voltage_%(layerId)d">%(layerName)s - %(prettyNetType)s</span>' % vars()
600 row = [layerAnchor, scaleStr, '<img src="%(picLoc)s"></img>' % vars()]
601 voltageInfo.append(row)
602
603 for layer in self._zSortedLayerNames:
604 layerName = layer[0]
605 layerStats = self._layerStatistics[layerName]
606 for netType in ["power","ground","signal"]:
607 metaData = [x for x in currentMetaData if 'layerId' in x and int(x['layerId'])==int(layerStats['layerId']) and 'netType' in x and x['netType']==netType]
608 if not metaData:
609 continue
610 metaData = metaData[0]
611 picLoc = metaData['fileName']
612
613
614 picName = os.path.basename(picLoc)
615 picLoc = os.path.join(r"./","figures_for_"+self.name,picName)
616 picLoc = picLoc.replace('\\','/')
617 scaleStr = "%6.5f - %6.5f [A/mm**2]" % (1e-6*float(metaData["minValue"]),1e-6*float(metaData["maxValue"]))
618 layerNr = layerStats['layerId']
619 prettyNetType = prettyName[netType]
620 layerAnchor = r'<span id="current_%(layerNr)d">%(layerName)s - %(prettyNetType)s</span>' % vars()
621 row = [layerAnchor, scaleStr, '<img src="%(picLoc)s"></img>' % vars()]
622 currentInfo.append(row)
623
624 for layerId in [-2,-3]:
625 layerName = {-2 : "top", -3 : "bottom"}[layerId]
626 for netType in ["power","ground","signal"]:
627 metaData = [x for x in currentMetaData if 'layerId' in x and int(x['layerId'])==layerId and 'netType' in x and x['netType']==netType]
628 if not metaData:
629 continue
630 metaData = metaData[0]
631 picLoc = metaData['fileName']
632
633
634 picName = os.path.basename(picLoc)
635 picLoc = os.path.join(r"./","figures_for_"+self.name,picName)
636 picLoc = picLoc.replace('\\','/')
637 scaleStr = "%6.5f - %6.5f [A/mm**2]" % (1e-6*float(metaData["minValue"]),1e-6*float(metaData["maxValue"]))
638 prettyNetType = prettyName[netType]
639 layerAnchor = r'<span id="current_%(layerId)d">%(layerName)s - %(prettyNetType)s</span>' % vars()
640 row = [layerAnchor, scaleStr, '<img src="%(picLoc)s"></img>' % vars()]
641 currentInfo.append(row)
642
643 for layer in self._zSortedLayerNames:
644 layerName = layer[0]
645 layerStats = self._layerStatistics[layerName]
646 for netType in ["power","ground","signal"]:
647 metaData = [x for x in powerLossDensityMetaData if 'layerId' in x and int(x['layerId'])==int(layerStats['layerId']) and 'netType' in x and x['netType']==netType]
648 if not metaData:
649 continue
650 metaData = metaData[0]
651 picLoc = metaData['fileName']
652
653
654 picName = os.path.basename(picLoc)
655 picLoc = os.path.join(r"./","figures_for_"+self.name,picName)
656 picLoc = picLoc.replace('\\','/')
657 scaleStr = "%6.5f - %6.5f [W/mm**2]" % (1e-6*float(metaData["minValue"]),1e-6*float(metaData["maxValue"]))
658 layerNr = layerStats['layerId']
659 prettyNetType = prettyName[netType]
660 layerAnchor = r'<span id="powerLossDensity_%(layerNr)d">%(layerName)s - %(prettyNetType)s</span>' % vars()
661 row = [layerAnchor, scaleStr, '<img src="%(picLoc)s"></img>' % vars()]
662 powerLossDensityInfo.append(row)
663
664 for layerId in [-2,-3]:
665 layerName = {-2 : "top", -3 : "bottom"}[layerId]
666 for netType in ["power","ground","signal"]:
667 metaData = [x for x in powerLossDensityMetaData if 'layerId' in x and int(x['layerId'])==layerId and 'netType' in x and x['netType']==netType]
668 if not metaData:
669 continue
670 metaData = metaData[0]
671 picLoc = metaData['fileName']
672
673
674 picName = os.path.basename(picLoc)
675 picLoc = os.path.join(r"./","figures_for_"+self.name,picName)
676 picLoc = picLoc.replace('\\','/')
677 scaleStr = "%6.5f - %6.5f [W/mm**2]" % (1e-6*float(metaData["minValue"]),1e-6*float(metaData["maxValue"]))
678 prettyNetType = prettyName[netType]
679 layerAnchor = r'<span id="powerLossDensity_%(layerId)d">%(layerName)s - %(prettyNetType)s</span>' % vars()
680 row = [layerAnchor, scaleStr, '<img src="%(picLoc)s"></img>' % vars()]
681 powerLossDensityInfo.append(row)
682
683 if tempInfo:
684 layersTemperatureFiguresTable = _htmlTable(tempHeader,tempInfo)
685 else:
686 layersTemperatureFiguresTable = ""
687 if currentInfo:
688 layersCurrentFiguresTable = _htmlTable(currentHeader,currentInfo)
689 else:
690 layersCurrentFiguresTable = ""
691 if powerLossDensityInfo:
692 layersPowerLossDensityFiguresTable = _htmlTable(powerLossDensityHeader,powerLossDensityInfo)
693 else:
694 layersPowerLossDensityFiguresTable = ""
695 if voltageInfo:
696 layersVoltageFiguresTable = _htmlTable(voltageHeader,voltageInfo)
697 else:
698 layersVoltageFiguresTable = ""
699
700 self._vars['layersTemperatureFiguresTable'] = layersTemperatureFiguresTable
701 self._vars['layersVoltageFiguresTable'] = layersVoltageFiguresTable
702 self._vars['layersCurrentFiguresTable'] = layersCurrentFiguresTable
703 self._vars['layersPowerLossDensityFiguresTable'] = layersPowerLossDensityFiguresTable
704
705 keyValues = self._variables()
706 return template.safe_substitute(keyValues)
707
708
710 interConnects = {}
711 for comp in inResult.components:
712 pinNetNames = [str(x.netName) for x in comp.pins if x.netType=="Power" or x.netType=="Signal"]
713 interConnects[comp.name] = Bunch(netNames=pinNetNames,vrms=[],sinks=[],component=comp)
714
715 for k,v in interConnects.iteritems():
716 v.netNames = set(v.netNames)
717
718 for vrm in inResult.vrms:
719 pinNetNames = set([x.netName for x in vrm.pins if x.netType=="Power" or x.netType=="Signal"])
720 for k,inter in interConnects.iteritems():
721 intersection = pinNetNames.intersection(inter.netNames)
722 if intersection:
723 inter.vrms.append(vrm)
724
725 for sink in inResult.sinks:
726 pinNetNames = set([x.netName for x in sink.pins if x.netType=="Power" or x.netType=="Signal"])
727 for k,inter in interConnects.iteritems():
728 intersection = pinNetNames.intersection(inter.netNames)
729 if intersection:
730 inter.sinks.append(sink)
731
732 return interConnects
733
735 selVrmNetNames = set([x.netName for x in selVrm.pins if x.netType=="Power" or x.netType=="Signal"])
736
737 connectedSinks = []
738 for sink in sinks:
739 pinNetNames = set([x.netName for x in sink.pins if x.netType=="Power" or x.netType=="Signal"])
740 intersection = pinNetNames.intersection(selVrmNetNames)
741 if intersection:
742 connectedSinks.append(Bunch(sink=sink, interConnect=None))
743 else:
744 for name, inter in interconnects.iteritems():
745 interSinkNames = [x.name for x in inter.sinks]
746 interVrmNames = [x.name for x in inter.vrms]
747 if selVrm.name in interVrmNames and sink.name in interSinkNames:
748 connectedSinks.append(Bunch(sink=sink, interConnect=inter.component))
749 break
750
751 return connectedSinks
752
755 self.name = "sense_" + vrm.name
756 self.vrmName = vrm.name
757 self.senseNetName = vrm.senseNetName
758
759
793
795 switchNameToVrmName = {}
796 vrmList = setup.getVrmList()
797 for vrm in vrmList:
798 if vrm.sourceType != 'PackagedVrm':
799 for pin in vrm.upSwitch.plusPins():
800 switchNameToVrmName[pin.getInstanceName()] = vrm.name
801 break
802 for pin in vrm.lowSwitch.plusPins():
803 switchNameToVrmName[pin.getInstanceName()] = vrm.name
804 break
805 for pin in vrm.inductor.plusPins():
806 switchNameToVrmName[pin.getInstanceName()] = vrm.name
807 break
808 return switchNameToVrmName
809
810 '''
811 build the power tree topology
812 the topology will consist of VRMs, sinks and components
813 the returned value will be two dimensional array where each cell representing an element to be drawn
814 '''
816 import empro
817
818 layout = empro.activeProject.geometry()[0]
819 layoutObj = empro.activeProject.layout
820 tplg = Topology()
821
822
823 if hasattr(result,"sipiData"):
824 setup = result.sipiData
825 else:
826 setup = result.sipiDatas[0]
827 allowedNets = [x.name for x in setup.getNetList() if x.type in [1,2,4]]
828
829 vrms = {}
830 sinks = {}
831 components = dict((x.name,x) for x in result.components)
832 connectionInstances = []
833 switchToVrmDict = _switchToVrmDict(setup)
834
835 for vrm in setup.getVrmList():
836 instList = []
837 for pin in vrm.plusPins():
838 instList.append((pin.getInstanceName(),pin.getPinName()))
839 break
840 instList = set(instList)
841 vrms[vrm.name] = instList
842 if vrm.sourceType != 'PackagedVrm':
843 for pin in vrm.upSwitch.plusPins():
844 connectionInstances.append(pin.getInstanceName())
845 break
846 for pin in vrm.lowSwitch.plusPins():
847 connectionInstances.append(pin.getInstanceName())
848 break
849 for pin in vrm.inductor.plusPins():
850 connectionInstances.append(pin.getInstanceName())
851 break
852
853 for sink in setup.getSinkList():
854 instList = []
855 for pin in sink.plusPins():
856 instList.append((pin.getInstanceName(),pin.getPinName()))
857 break
858 instList = set(instList)
859 sinks[sink.name] = instList
860 sinkInstances = sum([list(x) for x in sinks.values()],[])
861 sinkInstanceNames = [name for (name,pin) in sinkInstances]
862
863 for compGroup in setup.getComponentModelGroupList():
864 for inst in compGroup.instances():
865 connectionInstances.append(inst.name)
866
867 for vrmIterator, (vrmName, vrmInstances) in enumerate(vrms.iteritems()):
868 addedSwitches = []
869 vrm = [x for x in result.vrms if x.name==vrmName][0]
870 vrmColor = (0.7,0.9,0.70,1)
871 if hasattr(vrm,'result') and 'pass' not in vrm.result:
872 vrmColor = (0.9,0.5,0.5,1)
873 if vrm.senseVoltage is not None:
874 tplg.addSenseLine(TopologyElement(vrmIterator, SenseLine(vrm), TopologyElement.SENSE,vrmColor))
875 if vrm.sourceType != 'PackagedVrm':
876 continue
877
878 vrmElement = tplg.addElement(TopologyElement(vrmIterator, vrm, TopologyElement.VRM, vrmColor))
879
880 vrmInstance, pinName = list(vrmInstances)[0]
881 limitInsts = True
882 connections = layout._connectionsFromInstance((vrmInstance, pinName),sinkInstances,[2,4],allowedNets, limitInsts, connectionInstances, 0, lambda x:None)
883
884 for connectionIndex, connection in enumerate(connections):
885 previousElement = vrmElement
886 for pieceIndex, piece in enumerate(connection):
887
888 if piece.instanceName:
889
890 if piece.instanceName in sinkInstanceNames:
891 sink = None
892 sinkPinNames = set()
893 instance = layoutObj.instanceByName(piece.instanceName)
894 for pinPos in piece.pinPositionsIn:
895 pin = instance.instPin(pinPos)
896 sinkPinNames.add(instance.name+'.'+pin.name)
897 for sinkIter in result.sinks:
898 for pin in sinkIter.pins:
899 if pin.name in sinkPinNames:
900 sink = sinkIter
901 break
902 if sink==None:
903 continue
904
905 color = (0.7,0.9,0.70,1)
906 if hasattr(sink,'result') and 'pass' not in sink.result:
907 color = (0.9,0.5,0.5,1)
908
909 sinkElement = tplg.addElement(TopologyElement(vrmIterator, sink, TopologyElement.SINK, color))
910 label = connectionLabel(connection[pieceIndex - 1], piece)
911 tplg.addConnection(previousElement, sinkElement, inLabel=label)
912 tplg.addRow()
913
914
915 elif piece.instanceName in components:
916 color = (0.75,0.75,0.75,1)
917 instance = layoutObj.instanceByName(piece.instanceName)
918 pinsIn = []
919 pinsOut = []
920 instPinNames = []
921 for pinPos in piece.pinPositionsIn:
922 pin = instance.instPin(pinPos)
923 pinsIn.append(pin)
924 instPinNames.append( piece.instanceName + "." + pin.name)
925 for pinPos in piece.pinPositionsOut:
926 pin = instance.instPin(pinPos)
927 pinsOut.append(pin)
928 instPinNames.append( piece.instanceName + "." + pin.name)
929
930 component = components.get(piece.instanceName,None)
931 if component==None:
932 element = tplg.addElement(TopologyElement(vrmIterator, instance, TopologyElement.UNKNOWN, color))
933 label = connectionLabel(connection[pieceIndex - 1], piece)
934 tplg.addConnection(previousElement, element, inLabel=label)
935 componentElement = element
936 previousElement = componentElement
937 continue
938
939 pinsIn = set([instance.name+"."+pin.name for pin in pinsIn])
940 pinsOut = set([instance.name+"."+pin.name for pin in pinsOut])
941 powerIn = [pin.voltage*pin.current for pin in component.pins if pin.name in pinsIn]
942 powerOut = [pin.voltage*pin.current for pin in component.pins if pin.name in pinsOut]
943 voltagesIn = [pin.voltage for pin in component.pins if pin.name in pinsIn]
944 voltagesOut = [pin.voltage for pin in component.pins if pin.name in pinsOut]
945 ampsIn = [pin.current for pin in component.pins if pin.name in pinsIn]
946 voltage = component.voltage
947 current = abs(sum(ampsIn))
948 if voltagesIn and voltagesOut:
949 voltage = (sum(voltagesIn)/len(voltagesIn)) - (sum(voltagesOut)/len(voltagesOut))
950 if powerIn and powerOut and current!=0.0:
951 voltage = (abs(sum(powerIn))-abs(sum(powerOut)))/current
952 element = tplg.addElement(TopologyElement(vrmIterator, component, TopologyElement.COMPONENT, color, metaData = {"voltage": voltage, "current": current}))
953 label = connectionLabel(connection[pieceIndex - 1], piece)
954 tplg.addConnection(previousElement, element, inLabel=label)
955 componentElement = element
956 previousElement = componentElement
957
958
959 elif piece.instanceName in switchToVrmDict:
960 switchVrmName = switchToVrmDict[piece.instanceName]
961 if switchVrmName in addedSwitches:
962 previousElement = switchElement
963 continue
964 addedSwitches.append(switchVrmName)
965 switchVrm = [x for x in result.vrms if x.name==switchVrmName][0]
966
967 color = (0.7,0.9,0.70,1)
968 if hasattr(switchVrm,'result') and 'pass' not in switchVrm.result:
969 color = (0.9,0.5,0.5,1)
970
971 switchElement = tplg.addElement(TopologyElement(vrmIterator, switchVrm, TopologyElement.SWITCHVRM, color))
972 label = connectionLabel(connection[pieceIndex - 1], piece)
973 tplg.addConnection(previousElement, switchElement, inLabel=label)
974 previousElement = switchElement
975
976
977 elif (piece.topLevelPinName) and (pieceIndex == len(connection)-1):
978 sink = None
979 for sinkIter in result.sinks:
980 for pin in sinkIter.pins:
981 if pin.name == piece.topLevelPinName:
982 sink = sinkIter
983 break
984 if sink==None:
985 continue
986
987 color = (0.7,0.9,0.70,1)
988 if hasattr(sink,'result') and 'pass' not in sink.result:
989 color = (0.9,0.5,0.5,1)
990
991 sinkElement = tplg.addElement(TopologyElement(vrmIterator, sink, TopologyElement.SINK, color))
992 label = connectionLabel(connection[pieceIndex - 1], piece)
993 tplg.addConnection(previousElement, sinkElement, inLabel=label)
994 tplg.addRow()
995
996 tplg.setPreviousIterator(vrmIterator)
997 tplg.resetColumn()
998
999 matrix = tplg.topology()
1000 if len(matrix) == 0:
1001 return tplg
1002 return tplg.build()
1003
1005 dx = 0
1006 dy = 0
1007 elementWidth = 150
1008 elementHeight = 75
1009 intDx = 60
1010 intDy = 10
1011 spacingWidth = elementWidth + intDx * 4.0
1012 spacingHeight = elementHeight * 1.25
1013 textColor = (0.05,0.05,0.05,1)
1014
1015 def _ellipsis(x,length=15):
1016 if len(x)>length-3:
1017 return x[:(length-3)]+'...'
1018 return x
1019
1020 def renderVrm(vrm,centerX,centerY,textColor):
1021 if vrm.senseVoltage is not None:
1022 scene.addRect(centerX-elementWidth*0.5,centerY-elementHeight*0.5,elementWidth,elementHeight)
1023 scene.addText(_ellipsis(vrm.name,24),centerX,centerY-18,8,True,textColor)
1024 scene.addText("Vnom = %4.3f V" % vrm.sourceVoltage,centerX,centerY-6,8,True,textColor)
1025 scene.addText("- %s" % (vrm.tolerance),centerX,centerY+6,8,True,textColor)
1026 scene.addText("%4.3f V" % (vrm.minVoltagePowerPins),centerX+elementWidth*0.5+intDx/2, -8+centerY,8,True,textColor)
1027 scene.addText("%4.3f A" % (-vrm.outputCurrent),centerX+elementWidth*0.5+intDx/2, 8+centerY,8,True,textColor)
1028 scene.addText("Vsense = %4.3f V" % (vrm.senseVoltage),centerX,centerY+18,8,True,textColor)
1029 scene.addText("%4.3f V" % (vrm.minSensePlusPinVoltage),25+centerX-elementWidth/4,centerY+elementHeight*0.5+intDy,8,True,textColor)
1030 scene.addText("%4.3f A" % (vrm.senseportCurrent),25+centerX-elementWidth/4,centerY+elementHeight*0.5+intDy+16,8,True,textColor)
1031 else:
1032 scene.addRect(centerX-elementWidth*0.5,centerY-elementHeight*0.5,elementWidth,elementHeight)
1033 scene.addText(_ellipsis(vrm.name,24),centerX,centerY-16,8,True,textColor)
1034 scene.addText("Vnom = %4.3f V" % vrm.sourceVoltage,centerX,centerY-0,8,True,textColor)
1035 scene.addText("- %s" % (vrm.tolerance),centerX,centerY+16,8,True,textColor)
1036 scene.addText("%4.3f V" % (vrm.minVoltagePowerPins),centerX+elementWidth*0.5+intDx/2, -8+centerY,8,True,textColor)
1037 scene.addText("%4.3f A" % (-vrm.outputCurrent),centerX+elementWidth*0.5+intDx/2, 8+centerY,8,True,textColor)
1038
1039 def renderSink(sink,centerX,centerY,textColor):
1040 scene.addRect(centerX-elementWidth*0.5,centerY-elementHeight*0.5,elementWidth,elementHeight)
1041
1042 deltaV = sink.vrmVoltage-sink.inputVoltage
1043 deltaVg = sink.maxVoltageGroundPins
1044 deltaVp = sink.vrmVoltage-sink.minVoltagePowerPins
1045
1046 scene.addText(_ellipsis(sink.name,24),centerX,centerY-24,8,True,textColor)
1047 scene.addText(u"\u00b1 %s" % (sink.tolerance),centerX,centerY-12,8,True,textColor)
1048 scene.addText(u"%4.3f V" % (sink.inputVoltage),centerX,centerY-0,8,True,textColor)
1049 scene.addText(u"\u0394V %3.1f mV" % (deltaV*1000.0),centerX,centerY+12,8,True,textColor)
1050 scene.addText(u"\u0394Vp %3.1f mV \u0394Vg %3.1f mV" % (deltaVp*1000.0,deltaVg*1000.0),centerX,centerY+24,8,True,textColor)
1051
1052 scene.addText(u"%4.3f V" % (sink.minVoltagePowerPins),centerX-elementWidth*0.5-intDx/2,centerY-8,8,True,textColor)
1053 scene.addText(u"%4.3f A" % (sink.sourceCurrent),centerX-elementWidth*0.5-intDx/2,centerY+8,8,True,textColor)
1054
1055 def renderComponent(comp,voltage, current, centerX,centerY,textColor):
1056 scene.addRect(centerX-elementWidth*0.5,centerY-elementHeight*0.5,elementWidth,elementHeight)
1057 scene.addText("%s" % _ellipsis(comp.name,24), centerX, centerY-18,8,True,textColor)
1058 scene.addText(u"%0.4f mV" % (1000.0*abs(voltage)), centerX, centerY,8,True,textColor)
1059 scene.addText("%4.3f A" % abs(current), centerX, centerY+18,8,True,textColor)
1060
1061 def renderUnknownComponent(comp,centerX,centerY,textColor):
1062 scene.addRect(centerX-elementWidth*0.5,centerY-elementHeight*0.5,elementWidth,elementHeight)
1063 scene.addText("%s" % _ellipsis(comp.name,24), centerX, centerY,8,True,textColor)
1064
1065 def renderSenseLine(senseLine, centerX, centerY, textColor):
1066 scene.penStyle = 2
1067 scene.addLine(dx - elementWidth / 4, dy - spacingHeight + elementHeight / 2, dx - elementWidth / 4, dy)
1068 scene.addLine(dx - elementWidth / 4, dy, dx + elementWidth * 0.25, dy)
1069 scene.addText(_ellipsis(senseLine.senseNetName, 24), dx, dy - 8, 8, True, textColor)
1070 scene.penStyle = 1
1071
1072 def renderSwitchVrm(vrm,centerX,centerY,textColor):
1073 scene.addRect(centerX-elementWidth*0.5,centerY-elementHeight*0.5,elementWidth,elementHeight)
1074 scene.addText(_ellipsis(vrm.name,24),centerX,centerY-24,8,True,textColor)
1075 scene.addText("Vnom = %4.3f V" % vrm.sourceVoltage,centerX,centerY-12,8,True,textColor)
1076 scene.addText("Vin = %4.3f V" % vrm.inputVoltage,centerX,centerY-0,8,True,textColor)
1077 scene.addText("- %s" % (vrm.tolerance),centerX,centerY+12,8,True,textColor)
1078 scene.addText("%4.3f V" % (vrm.switchOutputVoltage),centerX+elementWidth*0.5+intDx/2, -8+centerY,8,True,textColor)
1079 scene.addText("%4.3f A" % (-vrm.switchOutputCurrent),centerX+elementWidth*0.5+intDx/2, 8+centerY,8,True,textColor)
1080 scene.addText("%4.3f V" % (vrm.switchInputVoltage),centerX-elementWidth*0.5-intDx/2,centerY-8,8,True,textColor)
1081 scene.addText("%4.3f A" % (-vrm.switchInputCurrent),centerX-elementWidth*0.5-intDx/2,centerY+8,8,True,textColor)
1082 if vrm.senseVoltage is not None:
1083 scene.addText("Vsense = %4.3f V" % (vrm.senseVoltage),centerX,centerY+24,8,True,textColor)
1084 scene.addText("%4.3f V" % (vrm.minSensePlusPinVoltage),25+centerX-elementWidth/4,centerY+elementHeight*0.5+intDy,8,True,textColor)
1085 scene.addText("%4.3f A" % (vrm.senseportCurrent),25+centerX-elementWidth/4,centerY+elementHeight*0.5+intDy+16,8,True,textColor)
1086
1087
1088 for row in topology.topology():
1089 for element in row:
1090 if element is not None:
1091
1092 scene.brushColor = element.color
1093 if element.type == TopologyElement.VRM:
1094 renderVrm(element.obj, dx, dy, textColor)
1095 elif element.type == TopologyElement.SINK:
1096 renderSink(element.obj, dx, dy, textColor)
1097 elif element.type == TopologyElement.UNKNOWN:
1098 renderUnknownComponent(element.obj, dx, dy, textColor)
1099 elif element.type == TopologyElement.COMPONENT:
1100 renderComponent(element.obj, element.metaData["voltage"], element.metaData["current"], dx, dy, textColor)
1101 elif element.type == TopologyElement.SENSE:
1102 renderSenseLine(element.obj, dx, dy, textColor)
1103 elif element.type == TopologyElement.SWITCHVRM:
1104 renderSwitchVrm(element.obj, dx, dy, textColor)
1105
1106 inX = dx - elementWidth / 2
1107 inY = dy
1108
1109 '''
1110 if len(element.inputs()) > 1:
1111 inX = dx - spacingWidth / 4
1112 inY = dy
1113 scene.brushColor= (0, 0, 0, 1)
1114 scene.addCircle(inX, inY, 4)
1115 scene.addLine(inX, inY, dx - elementWidth / 2, dy)
1116 '''
1117
1118
1119
1120 if len(element.outputs()) > 1:
1121 scene.brushColor= (0, 0, 0, 1)
1122 scene.addCircle(dx + elementWidth / 2 + intDx, dy, 4)
1123 scene.addLine(dx + elementWidth / 2, dy, dx + elementWidth / 2 + intDx, dy)
1124
1125
1126 for connection in element.inputs():
1127 pos = topology.position(connection.to)
1128 outX = pos[1] * spacingWidth + elementWidth / 2
1129 outY = pos[0] * spacingHeight
1130 if len(connection.to.outputs()) > 1:
1131 outX = pos[1] * spacingWidth + elementWidth / 2 + intDx
1132 if outY != inY:
1133 scene.addLine(outX, outY, outX, inY)
1134 scene.addLine(outX, inY, inX, inY)
1135 else:
1136 scene.addLine(outX, outY, inX, inY)
1137 scene.addText("%s" % _ellipsis(connection.label), (outX + inX) / 2, inY - 8, 8, True, textColor)
1138
1139 dx += spacingWidth
1140 dx = 0
1141 dy += spacingHeight
1142
1151
1152
1154 def _ellipsis(x,length=15):
1155 if len(x)>length-3:
1156 return x[:(length-3)]+'...'
1157 return x
1158
1159 interConnects = _interconnectedComponents(result)
1160
1161 dy = 0
1162 dx = 0
1163 vrmWidth = 150
1164 vrmHeight = 75
1165 sinkWidth = 150
1166 sinkHeight = 75
1167 sinkSpacing = 75*1.25
1168 compWidth = 150
1169 compHeight = 75
1170 dxToSink = 500
1171 intDx = 60
1172 intDy = 10
1173 scene.brushColor= (0.95,0.95,0.95,1)
1174 textColor = (0.05,0.05,0.05,1)
1175 sinksShown = set()
1176
1177 import empro
1178 layout = empro.activeProject.geometry()[0]
1179 layoutObj = empro.activeProject.layout
1180 if hasattr(result,"sipiData"):
1181 setup = result.sipiData
1182 else:
1183 setup = result.sipiDatas[0]
1184 allowedNets = [x.name for x in setup.getNetList() if x.type in [1,2]]
1185
1186 vrms = {}
1187 for vrm in setup.getVrmList():
1188 instList = []
1189 for pin in vrm.plusPins():
1190 instList.append((pin.getInstanceName(),pin.getPinName()))
1191 break
1192 instList = set(instList)
1193 vrms[vrm.name] = instList
1194
1195 sinks = {}
1196 for sink in setup.getSinkList():
1197 instList = []
1198 for pin in sink.plusPins():
1199 instList.append((pin.getInstanceName(),pin.getPinName()))
1200 break
1201 instList = set(instList)
1202 sinks[sink.name] = instList
1203
1204 insts = []
1205 for compGroup in setup.getComponentModelGroupList():
1206 for inst in compGroup.instances():
1207 insts.append(inst.name)
1208
1209 components = dict((x.name,x) for x in result.components)
1210
1211 _showDifference = False
1212 if isinstance(result, empro.toolkit.analysis.dc.results.DCResultsDiff):
1213 _showDifference = True
1214
1215 def renderVrm(vrm,centerX,centerY,textColor):
1216 if not _showDifference and vrm.senseVoltage is not None:
1217 scene.addRect(centerX-vrmWidth*0.5,centerY-vrmHeight*0.5,vrmWidth,vrmHeight)
1218 scene.addText(_ellipsis(vrm.name,24),centerX,centerY-18,8,True,textColor)
1219 scene.addText("Vnom = %4.3f V" % vrm.sourceVoltage,centerX,centerY-6,8,True,textColor)
1220 scene.addText("- %s" % (vrm.tolerance),centerX,centerY+6,8,True,textColor)
1221 sinkIndex = 0
1222 scene.addText("%4.3f V" % (vrm.minVoltagePowerPins),centerX+vrmWidth*0.5+intDx/2, -8+centerY,8,True,textColor)
1223 scene.addText("%4.3f A" % (-vrm.outputCurrent),centerX+vrmWidth*0.5+intDx/2, 8+centerY,8,True,textColor)
1224 scene.addText("Vsense = %4.3f V" % (vrm.senseVoltage),centerX,centerY+18,8,True,textColor)
1225 scene.addText("%4.3f V" % (vrm.minSensePlusPinVoltage),25+centerX-vrmWidth/4,centerY+vrmHeight*0.5+intDy,8,True,textColor)
1226 scene.addText("%4.3f A" % (vrm.senseportCurrent),25+centerX-vrmWidth/4,centerY+vrmHeight*0.5+intDy+16,8,True,textColor)
1227 else:
1228 scene.addRect(centerX-vrmWidth*0.5,centerY-vrmHeight*0.5,vrmWidth,vrmHeight)
1229 scene.addText(_ellipsis(vrm.name,24),centerX,centerY-16,8,True,textColor)
1230 scene.addText("Vnom = %4.3f V" % vrm.sourceVoltage,centerX,centerY-0,8,True,textColor)
1231 scene.addText("- %s" % (vrm.tolerance),centerX,centerY+16,8,True,textColor)
1232 sinkIndex = 0
1233 scene.addText("%4.3f V" % (vrm.minVoltagePowerPins),centerX+vrmWidth*0.5+intDx/2, -8+centerY,8,True,textColor)
1234 scene.addText("%4.3f A" % (-vrm.outputCurrent),centerX+vrmWidth*0.5+intDx/2, 8+centerY,8,True,textColor)
1235
1236 def renderSink(sink,centerX,centerY,textColor):
1237 scene.addRect(centerX-sinkWidth*0.5,centerY-sinkHeight*0.5,sinkWidth,sinkHeight)
1238
1239 deltaV = sink.vrmVoltage-sink.inputVoltage
1240 deltaVg = sink.maxVoltageGroundPins
1241 deltaVp = sink.vrmVoltage-sink.minVoltagePowerPins
1242
1243 scene.addText(_ellipsis(sink.name,24),centerX,centerY-24,8,True,textColor)
1244 scene.addText(u"\u00b1 %s" % (sink.tolerance),centerX,centerY-12,8,True,textColor)
1245 scene.addText(u"%4.3f V" % (sink.inputVoltage),centerX,centerY-0,8,True,textColor)
1246 scene.addText(u"\u0394V %3.1f mV" % (deltaV*1000.0),centerX,centerY+12,8,True,textColor)
1247 scene.addText(u"\u0394Vp %3.1f mV \u0394Vg %3.1f mV" % (deltaVp*1000.0,deltaVg*1000.0),centerX,centerY+24,8,True,textColor)
1248
1249 scene.addText(u"%4.3f V" % (sink.minVoltagePowerPins),centerX-sinkWidth*0.5-intDx/2,centerY-8,8,True,textColor)
1250 scene.addText(u"%4.3f A" % (sink.sourceCurrent),centerX-sinkWidth*0.5-intDx/2,centerY+8,8,True,textColor)
1251
1252 def renderComponent(comp,voltage, current, centerX,centerY,textColor):
1253 scene.addRect(centerX-compWidth*0.5,centerY-compHeight*0.5,compWidth,compHeight)
1254 scene.addText("%s" % _ellipsis(comp.name,24), centerX, centerY-18,8,True,textColor)
1255 scene.addText(u"%0.4f mV" % (1000.0*abs(voltage)), centerX, centerY,8,True,textColor)
1256 scene.addText("%4.3f A" % abs(current), centerX, centerY+18,8,True,textColor)
1257
1258 def renderUnknownComponent(comp,centerX,centerY,textColor):
1259 scene.addRect(centerX-compWidth*0.5,centerY-compHeight*0.5,compWidth,compHeight)
1260 scene.addText("%s" % _ellipsis(comp.name,24), centerX, centerY,8,True,textColor)
1261
1262 for vrmName, vrmInstances in vrms.iteritems():
1263 vrmInstance, firstPinName = list(vrmInstances)[0]
1264 sinkInstances = sum([list(x) for x in sinks.values()],[])
1265 limitInsts = True
1266 connections = layout._connectionsFromInstance((vrmInstance, firstPinName),sinkInstances,[2],allowedNets, limitInsts, insts, 0, lambda x:None)
1267
1268 vrm = [x for x in result.vrms if x.name==vrmName][0]
1269
1270 vrmFailed = False
1271 if hasattr(vrm,'result'):
1272 vrmFailed = 'pass' not in vrm.result
1273
1274 if vrmFailed:
1275 scene.brushColor= (0.9,0.5,0.5,1)
1276 else:
1277 scene.brushColor= (0.7,0.9,0.70,1)
1278
1279 renderVrm(vrm,0,dy,textColor)
1280
1281 if False:
1282 print "*"*50
1283 print "Vrm", vrm.name
1284 for connection in connections:
1285 print " ","-"*50
1286 for piece in connection:
1287 print " ", piece.componentName, piece.instanceName
1288 instance = layoutObj.instanceByName(piece.instanceName)
1289 if piece.pinPositionsIn:
1290 for pinPos in piece.pinPositionsIn:
1291 pin = instance.instPin(pinPos)
1292 print " in", pin.name, pin.netName
1293 if piece.pinPositionsOut:
1294 for pinPos in piece.pinPositionsOut:
1295 pin = instance.instPin(pinPos)
1296 print " out", pin.name, pin.netName
1297 print "+"*20
1298
1299 sinkIndex = 0
1300
1301 if not _showDifference and vrm.senseVoltage is not None:
1302 scene.penStyle = 2
1303 scene.addLine(-vrmWidth/4,dy+vrmHeight*0.5,-vrmWidth/4,dy+sinkHeight*1.25)
1304 scene.addLine(-vrmWidth/4,dy+sinkHeight*1.25,vrmWidth*0.25,dy+sinkHeight*1.25)
1305 scene.addText(_ellipsis(vrm.senseNetName,24),0,-8+dy+sinkHeight*1.25,8,True,textColor)
1306 scene.penStyle = 1
1307
1308 for connectionIndex, connection in enumerate(connections):
1309 for pieceIndex, piece in enumerate(connection):
1310 if len(connection)==pieceIndex+1:
1311
1312 sink = None
1313 sinkPinNames = set()
1314 if piece.instanceName:
1315 instance = layoutObj.instanceByName(piece.instanceName)
1316 for pinPos in piece.pinPositionsIn:
1317 pin = instance.instPin(pinPos)
1318 sinkPinNames.add(instance.name+'.'+pin.name)
1319 elif piece.topLevelPinName:
1320 sinkPinNames.add(piece.topLevelPinName)
1321 for sinkIter in result.sinks:
1322 for pin in sinkIter.pins:
1323 if pin.name in sinkPinNames:
1324 sink = sinkIter
1325 break
1326 '''
1327 if sink==None and len(sinks)==1:
1328 sink = result.sinks[0]
1329 '''
1330 if sink==None:
1331 continue
1332
1333 sinksShown.add(sink.name)
1334 sinkNetNames = set([pin.netName for pin in sink.pins if pin.netType=="Power"])
1335 sinkFailed = False
1336 if hasattr(sink,'result'):
1337 sinkFailed = 'pass' not in sink.result
1338 textColor = (0.05,0.05,0.05,1)
1339 if sinkFailed:
1340 scene.brushColor= (0.9,0.5,0.5,1)
1341 else:
1342 scene.brushColor= (0.7,0.9,0.70,1)
1343
1344 renderSink(sink,pieceIndex*(compWidth+intDx*4.0),dy+sinkIndex*sinkSpacing,textColor)
1345 elif pieceIndex>0:
1346 scene.brushColor= (0.75,0.75,0.75,1)
1347 instance = layoutObj.instanceByName(piece.instanceName)
1348 pinsIn = []
1349 pinsOut = []
1350 instPinNames = []
1351 for pinPos in piece.pinPositionsIn:
1352 pin = instance.instPin(pinPos)
1353 pinsIn.append(pin)
1354 instPinNames.append( piece.instanceName + "." + pin.name)
1355 for pinPos in piece.pinPositionsOut:
1356 pin = instance.instPin(pinPos)
1357 pinsOut.append(pin)
1358 instPinNames.append( piece.instanceName + "." + pin.name)
1359
1360 component = components.get(piece.instanceName,None)
1361 if not component:
1362
1363 for sinkComp in result.sinks:
1364 for pin in sinkComp.pins:
1365 if pin.name in instPinNames:
1366 component = sinkComp
1367 break
1368 if not component:
1369
1370 for vrmComp in result.vrms:
1371 for pin in vrmComp.pins:
1372 if pin.name in instPinNames:
1373 component = vrmComp
1374 break
1375
1376 if component==None:
1377 renderUnknownComponent(instance,pieceIndex*(compWidth+intDx*4.0),dy+sinkIndex*sinkSpacing,textColor)
1378 continue
1379
1380 pinsIn = set([instance.name+"."+pin.name for pin in pinsIn])
1381 pinsOut = set([instance.name+"."+pin.name for pin in pinsOut])
1382 powerIn = [pin.voltage*pin.current for pin in component.pins if pin.name in pinsIn]
1383 powerOut = [pin.voltage*pin.current for pin in component.pins if pin.name in pinsOut]
1384 voltagesIn = [pin.voltage for pin in component.pins if pin.name in pinsIn]
1385 voltagesOut = [pin.voltage for pin in component.pins if pin.name in pinsOut]
1386 ampsIn = [pin.current for pin in component.pins if pin.name in pinsIn]
1387 ampsOut = [pin.current for pin in component.pins if pin.name in pinsOut]
1388 voltage = component.voltage
1389 current = abs(sum(ampsIn))
1390 if voltagesIn and voltagesOut:
1391 voltage = (sum(voltagesIn)/len(voltagesIn)) - (sum(voltagesOut)/len(voltagesOut))
1392 if powerIn and powerOut and current!=0.0:
1393 voltage = (abs(sum(powerIn))-abs(sum(powerOut)))/current
1394 renderComponent(component,voltage, current,pieceIndex*(compWidth+intDx*4.0),dy+sinkIndex*sinkSpacing,textColor)
1395
1396
1397
1398 for pieceIndex, piece in enumerate(connection[1:]):
1399 sx = pieceIndex*(compWidth+intDx*4.0) + compWidth*0.5
1400 ex = (pieceIndex+1)*(compWidth+intDx*4.0) - compWidth*0.5
1401 cy = dy+sinkIndex*sinkSpacing
1402
1403 if connectionIndex>0 and pieceIndex==0:
1404 sx = sx+intDx
1405 scene.brushColor= (0,0,0,1)
1406 scene.addCircle(sx,cy,4)
1407 scene.addLine(sx,cy,sx,cy-sinkSpacing)
1408 if connectionIndex==0 and len(connections)>1:
1409 scene.brushColor= (0,0,0,1)
1410 scene.addCircle(sx+intDx,cy,4)
1411
1412 scene.addLine(sx,cy,ex,cy)
1413
1414 fromPiece = connection[pieceIndex]
1415 toPiece = piece
1416 netNames1 = []
1417 netNames2 = []
1418 instance = layoutObj.instanceByName(fromPiece.instanceName)
1419 if fromPiece.pinPositionsOut:
1420 for pinPos in fromPiece.pinPositionsOut:
1421 pin = instance.instPin(pinPos)
1422 netNames1.append(pin.netName)
1423 instance = layoutObj.instanceByName(toPiece.instanceName)
1424 if toPiece.pinPositionsIn:
1425 for pinPos in toPiece.pinPositionsIn:
1426 pin = instance.instPin(pinPos)
1427 netNames2.append(pin.netName)
1428
1429 netNames1 = set(netNames1)
1430 netNames2 = set(netNames2)
1431 netNames = netNames1.intersection(netNames2)
1432 scene.addText("%s" % _ellipsis(",".join(netNames)), 0.5*(sx+ex),cy-8,8,True,textColor)
1433 dy += sinkHeight*1.25
1434 sinkIndex += 0
1435 if not _showDifference and vrm.senseVoltage is not None:
1436 dy += sinkHeight*1.25
1437
1439 - def __init__(self, result, tableInfo, maxCurrent, maxTemperature, showViolatingCurrent, showViolatingT, **kwargs):
1440 Html.__init__(self, result, tableInfo, maxCurrent, maxTemperature, showViolatingCurrent, showViolatingT, **kwargs)
1441 self.document = Document()
1442
1444 textTitle = self._variables()
1445 for key in textTitle.keys():
1446 if key == "analysisName":
1447 self.document.add_heading("Analysis " + textTitle.get(key) + " Report",0)
1448 return
1449
1451 import os
1452 self.name = os.path.split(targetFileName)[1]
1453 self._fillVariables()
1454 self._generateFigures()
1455 self._title()
1456 self._overview()
1457 self._powerGraph()
1458 self._designInfo()
1459 self._sinks()
1460 self._vrms()
1461 self._vias()
1462 self._thermalComponents()
1463 self._layers()
1464 from docx.shared import Pt
1465 style = self.document.styles['Normal']
1466 font = style.font
1467 font.size = Pt(8)
1468 self.document.save(targetFileName)
1469 return
1470
1498
1511
1512 def _asLength(x):
1513 return '%f %s' % (lengthUnit.fromReferenceUnits(float(x)), lengthUnit.abbreviation())
1514
1515 dielInfo = []
1516 for k,v in self._vars['substrate']['dielectrics'].iteritems():
1517 dielInfo.append([v.name, v.materialName, _asLength(abs(float(v.thickness))),_formatOr(self._epsRFormat, v.Er), _formatOr(self._lossTangentFormat,v.lossTangent)])
1518
1519 condInfo = []
1520 for k,v in self._vars['substrate']['conductors'].iteritems():
1521 condInfo.append([v.name, v.materialName, _asLength(abs(float(v.thickness))),_formatOr(self._conductivityFormat,v.conductivity)])
1522
1523 viaInfo = []
1524 for k,v in self._vars['substrate']['vias'].iteritems():
1525 viaInfo.append([v.name, v.materialName])
1526 self.document.add_heading("Design information", level=1)
1527
1528 self.document.add_heading("Substrate", level=2)
1529 self.document.add_heading("Dielectrics", level=3)
1530 dielectricsHeader = ['Name','Material','Thickness','Er','LossTangent']
1531 dielectricstable = self.document.add_table(rows= 1 , cols=len(dielectricsHeader))
1532 dielectricstable.style = "Table Grid"
1533 hdr_cells = dielectricstable.rows[0].cells
1534 for i in range(len(dielectricsHeader)):
1535 hdr_cells[i].text = dielectricsHeader[i]
1536 for item in dielInfo:
1537 row_cells = dielectricstable.add_row().cells
1538 for i in range(len(item)):
1539 row_cells[i].text = str(item[i])
1540
1541 self.document.add_heading("Conductors", level=3)
1542 conductorsHeader = ['Name','Material','Thickness','Conductivity']
1543 conductorstable = self.document.add_table(rows= 1 , cols=len(conductorsHeader))
1544 conductorstable.style = "Table Grid"
1545 hdr_cells = conductorstable.rows[0].cells
1546 for i in range(len(conductorsHeader)):
1547 hdr_cells[i].text = conductorsHeader[i]
1548 for item in condInfo:
1549 row_cells = conductorstable.add_row().cells
1550 for i in range(len(item)):
1551 row_cells[i].text = str(item[i])
1552
1553 self.document.add_heading("Vias", level=3)
1554 viasHeader = ['Name','Material']
1555 viastable = self.document.add_table(rows= 1 , cols=len(viasHeader))
1556 viastable.style = "Table Grid"
1557 hdr_cells = viastable.rows[0].cells
1558 for i in range(len(viasHeader)):
1559 hdr_cells[i].text = viasHeader[i]
1560 for item in viaInfo:
1561 row_cells = viastable.add_row().cells
1562 for i in range(len(item)):
1563 row_cells[i].text = str(item[i])
1564 return
1565
1567 import string
1568 import os
1569 vrms = []
1570 for index, vrm in enumerate(self._result.vrms):
1571 row = [vrm.name, vrm.sourceVoltage, vrm.outputVoltage ,vrm.outputCurrent, vrm.tolerance, vrm.margin]
1572 if not self._showDifference:
1573 row.append(vrm.result)
1574 vrms.append(row)
1575 self.document.add_heading("VRMs", level=1)
1576 deltaSymbol = ''
1577 header = ["Name", deltaSymbol+"Source\nVoltage [V]", deltaSymbol+"Output\nVoltage [V]", deltaSymbol+"Output\nCurrent [A]", "Tolerance", deltaSymbol+"Margin [V]", "Pass/Fail"]
1578 table = self.document.add_table(rows= 1 , cols=len(header))
1579 table.style = "Table Grid"
1580 hdr_cells = table.rows[0].cells
1581 for i in range(len(header)):
1582 hdr_cells[i].text = header[i]
1583 for item in vrms:
1584 row_cells = table.add_row().cells
1585 for i in range(len(item)):
1586 row_cells[i].text = str(item[i])
1587 return
1588
1590 import string
1591 import os
1592 self._viasBulk()
1593 self.document.add_heading("Vias", level=1)
1594 self.document.add_paragraph(self.maximumCurrent, style = 'List Bullet')
1595 self.document.add_paragraph(self.maximumTemperature, style = 'List Bullet')
1596 table = self.document.add_table(rows= 1 , cols=len(self.viasHeader))
1597 table.style = "Table Grid"
1598 hdr_cells = table.rows[0].cells
1599 for i in range(len(self.viasHeader)):
1600 hdr_cells[i].text = self.viasHeader[i]
1601 for item in self.vias:
1602 row_cells = table.add_row().cells
1603 for i in range(len(item)):
1604 row_cells[i].text = str(item[i])
1605 return
1606
1608 import string
1609 import os
1610 import empro
1611 celsius = empro.units.unitByAbbreviation("degC")
1612 if self._showDifference:
1613 celsius = empro.units.unitByAbbreviation("K")
1614 degUnit = 'T ['+celsius.abbreviation()+']'
1615 degSymbol = '['+celsius.abbreviation()+']'
1616
1617 comps = []
1618 for index, source in enumerate(self._result.thermalComponents):
1619 if hasattr(source,'heat'):
1620 row = [source.name, source.heat, '---','---']
1621 else:
1622 row = [source.name, source.heatDie, source.heatBoard, source.heatCase]
1623 if hasattr(source,"temperature"):
1624 row += [self._temperatureFormat % celsius.fromReferenceUnits(source.temperature), "---","---","---", source.bareBoardThermalResistance]
1625 else:
1626 row += ["---", self._temperatureFormat % celsius.fromReferenceUnits(source.temperatureBoard), self._temperatureFormat % celsius.fromReferenceUnits(source.temperatureDie), self._temperatureFormat % celsius.fromReferenceUnits(source.temperatureCase), source.bareBoardThermalResistance]
1627 comps.append(row)
1628 self.document.add_heading("Thermal Components", level=1)
1629 deltaSymbol = ''
1630 header = ["Name", deltaSymbol+"Source [W]", deltaSymbol+"Heat To\nBoard [W]", deltaSymbol+"Heat To\nCase [W]", deltaSymbol+degUnit,deltaSymbol+"Case Bottom\n"+degUnit, deltaSymbol+"Die "+degUnit, deltaSymbol+"Case Top "+degUnit, deltaSymbol+"Thermal Resistance\nBare Board [K/W]"]
1631 table = self.document.add_table(rows= 1 , cols=len(header))
1632 table.style = "Table Grid"
1633 hdr_cells = table.rows[0].cells
1634 for i in range(len(header)):
1635 hdr_cells[i].text = header[i]
1636 for item in comps:
1637 row_cells = table.add_row().cells
1638 for i in range(len(item)):
1639 row_cells[i].text = str(item[i])
1640 return
1641
1643 import string
1644 import os
1645 sinks = []
1646 for index, sink in enumerate(self._result.sinks):
1647 row = [sink.name, sink.sourceCurrent, sink.vrmVoltage,sink.inputVoltage,sink.resistance, sink.tolerance, sink.margin]
1648 if not self._showDifference:
1649 row.append(sink.result)
1650 sinks.append(row)
1651 self.document.add_heading("Sinks", level=1)
1652 deltaSymbol = ''
1653 header = ["Name", "Source\nCurrent [A]", "VRM\nVoltage [V]", deltaSymbol+"Input\n Voltage [V]", deltaSymbol+"Resistance\n [Ohm]", "Tolerance", deltaSymbol+"Margin [V]", "Pass/Fail"]
1654 table = self.document.add_table(rows= 1 , cols=len(header))
1655 table.style = "Table Grid"
1656 hdr_cells = table.rows[0].cells
1657 for i in range(len(header)):
1658 hdr_cells[i].text = header[i]
1659 for item in sinks:
1660 row_cells = table.add_row().cells
1661 for i in range(len(item)):
1662 row_cells[i].text = str(item[i])
1663 return
1664
1666 import string
1667 import os
1668 pwrTreeImgNm = os.path.join(self.figuresLocation,"figures_for_"+self.name,"powerGraph.png")
1669 import empro
1670 import empro.gui
1671 import empro.toolkit.analysis.dc.output
1672 scn = empro.gui.GraphicsScene()
1673 empro.toolkit.analysis.dc.output._powerGraphSceneFromResults(scn,self._result)
1674 scn._save(pwrTreeImgNm)
1675 picLoc = pwrTreeImgNm.replace('\\','/')
1676 powerGraphImg = '%(picLoc)s' % vars()
1677 self.document.add_heading("Power Graph", level=1)
1678 if not self._result.vrms or not self._result.sinks:
1679 pass
1680 else:
1681 self.document.add_picture(powerGraphImg, width=Inches(3.0))
1682 return
1683
1685 from docx.oxml import OxmlElement
1686 from docx.oxml.ns import qn
1687 from docx.text.run import Run
1688 tableName = self.document.add_table(rows= 1 , cols=len(header))
1689 tableName.style = "Table Grid"
1690 hdr_cells = tableName.rows[0].cells
1691 for i in range(len(header)):
1692 hdr_cells[i].text = header[i]
1693 for item in info:
1694 row_cells = tableName.add_row().cells
1695 for i in range(len(item)-1):
1696 if (i == 0):
1697 paragraph_bk = row_cells[0].paragraphs[0]
1698 elem = paragraph_bk._element
1699 r = OxmlElement('w:r')
1700 elem.append(r)
1701 Run(r, para).text = str(item[0])
1702 pCaption = OxmlElement('w:bookmarkStart')
1703 pCaption.set(qn('w:id'), str(i))
1704 pCaption.set(qn('w:name'), str(item[0]) + bookmarkName)
1705 elem.append(pCaption)
1706 pCaption = OxmlElement('w:bookmarkEnd')
1707 pCaption.set(qn('w:id'),str(i))
1708 elem.append(pCaption)
1709 elif (i == 1):
1710 row_cells[i].text = item[i]
1711 else:
1712 row_cells[i].text = str(item[i])
1713 paragraph = row_cells[len(item)-1].paragraphs[0]
1714 run = paragraph.add_run()
1715 run.add_picture(item[len(item)-1], width=Inches(1.25))
1716 return
1717
1719 import string
1720 import os
1721 import empro
1722 from docx.oxml import OxmlElement
1723 from docx.oxml.ns import qn
1724 from docx.text.run import Run
1725 temperatureMetaData = [x for x in self._figuresMetaData if 'outputType' in x and x['outputType']=='temperature']
1726 voltageMetaData = [x for x in self._figuresMetaData if 'outputType' in x and x['outputType']=='voltage']
1727 powerLossDensityMetaData = [x for x in self._figuresMetaData if 'outputType' in x and x['outputType']=='powerLossDensity']
1728 currentMetaData = [x for x in self._figuresMetaData if 'outputType' in x and x['outputType']=='current']
1729
1730 celsius = empro.units.unitByAbbreviation("degC")
1731 if self._showDifference:
1732 celsius = empro.units.unitByAbbreviation("K")
1733 degUnit = 'T ['+celsius.abbreviation()+']'
1734 degSymbol = '['+celsius.abbreviation()+']'
1735
1736 temperatureDataIds = set([int(x['layerId']) for x in temperatureMetaData])
1737 voltageDataIds = set([int(x['layerId']) for x in voltageMetaData])
1738 currentDataIds = set([int(x['layerId']) for x in currentMetaData])
1739 powerLossDensityDataIds = set([int(x['layerId']) for x in powerLossDensityMetaData])
1740
1741 layerInfo = []
1742 for layer in self._zSortedLayerNames:
1743 layerName = layer[0]
1744 layerStats = self._layerStatistics[layerName]
1745 layerNr = layerStats['layerId']
1746 layerLinksTemperature = ''
1747 layerLinksVoltage = ''
1748 layerLinksCurrent = ''
1749 layerLinksPower = ''
1750 if temperatureMetaData and layerNr in temperatureDataIds:
1751 layerLinksTemperature += "T"
1752 if voltageMetaData and layerNr in voltageDataIds:
1753 layerLinksVoltage += "V"
1754 if currentMetaData and layerNr in currentDataIds:
1755 layerLinksCurrent += "A"
1756 if powerLossDensityMetaData and layerNr in powerLossDensityDataIds:
1757 layerLinksPower += "P"
1758 row = [layerName, layerLinksTemperature, layerLinksVoltage, layerLinksCurrent, layerLinksPower, self._temperatureFormat % celsius.fromReferenceUnits(layerStats["temperatureMin"]), self._temperatureFormat % celsius.fromReferenceUnits(layerStats["temperatureMax"]), self._currentDensityFormat % (layerStats["currentMin"]*1e-6),self._currentDensityFormat % (layerStats["currentMax"]*1e-6),self._voltageFormat % layerStats["voltageMin"],self._voltageFormat % layerStats["voltageMax"]]
1759 layerInfo.append(row)
1760
1761 for layerId in [-2,-3]:
1762 layerName = {-2 : "top", -3 : "bottom"}[layerId]
1763
1764 layerNr = layerId
1765 layerLinksTemperature = ''
1766 layerLinksVoltage = ''
1767 layerLinksCurrent = ''
1768 layerLinksPower = ''
1769 if temperatureMetaData and layerNr in temperatureDataIds:
1770 layerLinksTemperature += "T"
1771 if voltageMetaData and layerNr in voltageDataIds:
1772 layerLinksVoltage += "V"
1773 if currentMetaData and layerNr in currentDataIds:
1774 layerLinksCurrent += "A"
1775 if powerLossDensityMetaData and layerNr in powerLossDensityDataIds:
1776 layerLinksPower += "P"
1777
1778
1779 row = [layerName, layerLinksTemperature, layerLinksVoltage, layerLinksCurrent, layerLinksPower, '---', '---', '---','---','---','---']
1780 layerInfo.append(row)
1781
1782 tempHeader = ['Name','Scale','Plot']
1783 voltageHeader = ['Name','Scale','Plot']
1784 currentHeader = ['Name','Scale','Plot']
1785 powerLossDensityHeader = ['Name','Scale','Plot']
1786 tempInfo = []
1787 voltageInfo = []
1788 currentInfo = []
1789 powerLossDensityInfo = []
1790
1791
1792 for layer in self._zSortedLayerNames:
1793 layerName = layer[0]
1794 layerStats = self._layerStatistics[layerName]
1795 metaData = [x for x in temperatureMetaData if 'layerId' in x and int(x['layerId'])==int(layerStats['layerId'])]
1796 if not metaData:
1797 continue
1798 metaData = metaData[0]
1799 picLoc = metaData['fileName']
1800 picLoc = picLoc.replace('\\','/')
1801
1802 scaleStr = (self._temperatureFormat + " - " + self._temperatureFormat + " " + degSymbol) % (celsius.fromReferenceUnits(float(metaData["minValue"])),celsius.fromReferenceUnits(float(metaData["maxValue"])))
1803 layerNr = layerStats['layerId']
1804 layerAnchor = r'%(layerName)s' % vars()
1805 row = [layerAnchor, scaleStr, '%(picLoc)s' % vars()]
1806 tempInfo.append(row)
1807
1808 for layerId in [-2,-3]:
1809 layerName = {-2 : "top", -3 : "bottom"}[layerId]
1810 metaData = [x for x in temperatureMetaData if 'layerId' in x and int(x['layerId'])==layerId]
1811 if not metaData:
1812 continue
1813 metaData = metaData[0]
1814 picLoc = metaData['fileName']
1815 picLoc = picLoc.replace('\\','/')
1816
1817 scaleStr = (self._temperatureFormat + " - " + self._temperatureFormat + " " + degSymbol) % (celsius.fromReferenceUnits(float(metaData["minValue"])),celsius.fromReferenceUnits(float(metaData["maxValue"])))
1818 layerAnchor = r'%(layerName)s' % vars()
1819 row = [layerAnchor, scaleStr, '%(picLoc)s' % vars()]
1820 tempInfo.append(row)
1821
1822 prettyName = { 'power' : "Power" , 'ground' : "Ground" , 'signal' : "Signal"}
1823
1824 for layer in self._zSortedLayerNames:
1825 layerName = layer[0]
1826 layerStats = self._layerStatistics[layerName]
1827 for netType in ["power","ground","signal"]:
1828 metaData = [x for x in voltageMetaData if 'layerId' in x and int(x['layerId'])==int(layerStats['layerId']) and 'netType' in x and x['netType']==netType]
1829 if not metaData:
1830 continue
1831 metaData = metaData[0]
1832 picLoc = metaData['fileName']
1833 picLoc = picLoc.replace('\\','/')
1834
1835 scaleStr = "%6.5f - %6.5f [V]" % (float(metaData["minValue"]),float(metaData["maxValue"]))
1836 layerNr = layerStats['layerId']
1837 prettyNetType = prettyName[netType]
1838 layerAnchor = r'%(layerName)s- %(prettyNetType)s' % vars()
1839 row = [layerAnchor, scaleStr, '%(picLoc)s' % vars()]
1840 voltageInfo.append(row)
1841
1842 for layerId in [-2,-3]:
1843 layerName = {-2 : "top", -3 : "bottom"}[layerId]
1844 for netType in ["power","ground","signal"]:
1845 metaData = [x for x in voltageMetaData if 'layerId' in x and int(x['layerId'])==layerId and 'netType' in x and x['netType']==netType]
1846 if not metaData:
1847 continue
1848 metaData = metaData[0]
1849 picLoc = metaData['fileName']
1850 picLoc = picLoc.replace('\\','/')
1851
1852 scaleStr = "%6.5f - %6.5f [V]" % (float(metaData["minValue"]),float(metaData["maxValue"]))
1853 prettyNetType = prettyName[netType]
1854 layerAnchor = r'%(layerName)s- %(prettyNetType)s' % vars()
1855 row = [layerAnchor, scaleStr, '%(picLoc)s' % vars()]
1856 voltageInfo.append(row)
1857
1858 for layer in self._zSortedLayerNames:
1859 layerName = layer[0]
1860 layerStats = self._layerStatistics[layerName]
1861 for netType in ["power","ground","signal"]:
1862 metaData = [x for x in currentMetaData if 'layerId' in x and int(x['layerId'])==int(layerStats['layerId']) and 'netType' in x and x['netType']==netType]
1863 if not metaData:
1864 continue
1865 metaData = metaData[0]
1866 picLoc = metaData['fileName']
1867 picLoc = picLoc.replace('\\','/')
1868
1869 scaleStr = "%6.5f - %6.5f [A/mm**2]" % (1e-6*float(metaData["minValue"]),1e-6*float(metaData["maxValue"]))
1870 layerNr = layerStats['layerId']
1871 prettyNetType = prettyName[netType]
1872 layerAnchor = r'%(layerName)s- %(prettyNetType)s' % vars()
1873 row = [layerAnchor, scaleStr, '%(picLoc)s' % vars()]
1874 currentInfo.append(row)
1875
1876 for layerId in [-2,-3]:
1877 layerName = {-2 : "top", -3 : "bottom"}[layerId]
1878 for netType in ["power","ground","signal"]:
1879 metaData = [x for x in currentMetaData if 'layerId' in x and int(x['layerId'])==layerId and 'netType' in x and x['netType']==netType]
1880 if not metaData:
1881 continue
1882 metaData = metaData[0]
1883 picLoc = metaData['fileName']
1884 picLoc = picLoc.replace('\\','/')
1885
1886 scaleStr = "%6.5f - %6.5f [A/mm**2]" % (1e-6*float(metaData["minValue"]),1e-6*float(metaData["maxValue"]))
1887 prettyNetType = prettyName[netType]
1888 layerAnchor = r'%(layerName)s- %(prettyNetType)s' % vars()
1889 row = [layerAnchor, scaleStr, '%(picLoc)s' % vars()]
1890 currentInfo.append(row)
1891
1892 for layer in self._zSortedLayerNames:
1893 layerName = layer[0]
1894 layerStats = self._layerStatistics[layerName]
1895 for netType in ["power","ground","signal"]:
1896 metaData = [x for x in powerLossDensityMetaData if 'layerId' in x and int(x['layerId'])==int(layerStats['layerId']) and 'netType' in x and x['netType']==netType]
1897 if not metaData:
1898 continue
1899 metaData = metaData[0]
1900 picLoc = metaData['fileName']
1901 picLoc = picLoc.replace('\\','/')
1902
1903 scaleStr = "%6.5f - %6.5f [W/mm**2]" % (1e-6*float(metaData["minValue"]),1e-6*float(metaData["maxValue"]))
1904 layerNr = layerStats['layerId']
1905 prettyNetType = prettyName[netType]
1906 layerAnchor = r'%(layerName)s- %(prettyNetType)s' % vars()
1907 row = [layerAnchor, scaleStr, '%(picLoc)s' % vars()]
1908 powerLossDensityInfo.append(row)
1909
1910 for layerId in [-2,-3]:
1911 layerName = {-2 : "top", -3 : "bottom"}[layerId]
1912 for netType in ["power","ground","signal"]:
1913 metaData = [x for x in powerLossDensityMetaData if 'layerId' in x and int(x['layerId'])==layerId and 'netType' in x and x['netType']==netType]
1914 if not metaData:
1915 continue
1916 metaData = metaData[0]
1917 picLoc = metaData['fileName']
1918 picLoc = picLoc.replace('\\','/')
1919
1920 scaleStr = "%6.5f - %6.5f [W/mm**2]" % (1e-6*float(metaData["minValue"]),1e-6*float(metaData["maxValue"]))
1921 prettyNetType = prettyName[netType]
1922 layerAnchor = r'%(layerName)s- %(prettyNetType)s' % vars()
1923 row = [layerAnchor, scaleStr, '%(picLoc)s' % vars()]
1924 powerLossDensityInfo.append(row)
1925 self.document.add_heading("Layers", level=1)
1926 deltaSymbol = ''
1927 header = ["Layer", "Plots", "", "", "", deltaSymbol + "Min "+degUnit,deltaSymbol + deltaSymbol+"Max "+degUnit, deltaSymbol+"Min Current\nDensity [A/mm**2]", deltaSymbol+"Max Current\nDensity [A/mm**2]",deltaSymbol+"Min\nVoltage [V]", deltaSymbol+"Max\nVoltage [V]"]
1928 table = self.document.add_table(rows= 1 , cols=len(header))
1929 table.style = "Table Grid"
1930 hdr_cells = table.rows[0].cells
1931 for i in range(len(header)):
1932 hdr_cells[i].text = header[i]
1933 for item in layerInfo:
1934 row_cells = table.add_row().cells
1935 for i in range(len(item)):
1936 if (i > 0 and i < 5):
1937 p = row_cells[i].paragraphs[0]
1938 elem = p._element
1939 hyperlink = OxmlElement('w:hyperlink')
1940 hyperlink.set(qn('w:anchor'), str(item[0].replace(' ','_'))+ "-_Power"+str(item[i]))
1941 hyperlink.set(qn('w:history'), "1")
1942 elem.append(hyperlink)
1943 r = OxmlElement('w:r')
1944 hyperlink.append(r)
1945 rPr = OxmlElement('w:rPr')
1946 rStyle = OxmlElement('w:rStyle')
1947 rStyle.set(qn('w:val'), "Hyperlink" )
1948 rPr.append(rStyle)
1949 u = OxmlElement('w:u')
1950 u.set(qn('w:val'), "single")
1951 rPr.append(u)
1952 color = OxmlElement('w:color')
1953
1954 color.set(qn('w:val'), "2F5496")
1955 rPr.append(color)
1956 r.append(rPr)
1957 r.text = str(item[i])
1958 else:
1959 row_cells[i].text = str(item[i])
1960 hdr_cells[1].merge(hdr_cells[2]).merge(hdr_cells[3]).merge(hdr_cells[4])
1961
1962 if not(tempInfo == []):
1963 self.document.add_heading("Temperature Plots Table", level=2)
1964 self.plotTableTemplate(tempHeader, tempInfo, "-_PowerT", p)
1965
1966 if not(voltageInfo == []):
1967 self.document.add_heading("Voltage Plots Table", level=2)
1968 self.plotTableTemplate(voltageHeader, voltageInfo, "V", p)
1969
1970 if not(currentInfo == []):
1971 self.document.add_heading("Current Density Plots Table", level=2)
1972 self.plotTableTemplate(currentHeader, currentInfo, "A", p)
1973
1974 if not(powerLossDensityInfo == []):
1975 self.document.add_heading("Power Loss Density Plots Table", level=2)
1976 self.plotTableTemplate(powerLossDensityHeader, powerLossDensityInfo, "P", p)
1977 return
1978
1979 if False:
1982
1983 import empro.toolkit.analysis.dc.results
1984 if not hasattr(empro.internal,'__tempResults'):
1985
1986
1987
1988 results = empro.toolkit.analysis.dc.results.DCResults(empro.activeProject.analyses[0])
1989 empro.internal.__tempResults = results
1990
1991 results = empro.toolkit.analysis.dc.results.DCResults(empro.activeProject.analyses[2])
1992 docxinstance = Docx(results)
1993 docxinstance.figuresLocation = r'C:\Temp\report\result'
1994 docxinstance.progressCallback = progress
1995 docxinstance.targetFileName = r"C:\Temp\test.docx"
1996 import time
1997 stime = time.time()
1998 docxinstance.generate(docxinstance.targetFileName)
1999 empro.internal._figuresMetaData = docxinstance._figuresMetaData
2000 print time.time()-stime, "s"
2001
2002 if False:
2005
2006 import empro.toolkit.analysis.dc.results
2007 if not hasattr(empro.internal,'__tempResults'):
2008
2009
2010
2011 results = empro.toolkit.analysis.dc.results.DCResults(empro.activeProject.analyses[-2])
2012 empro.internal.__tempResults = results
2013 results = empro.internal.__tempResults
2014 html = Html(results)
2015 html.templatesLocation = r"F:\builds\empro-opt-64\src\empro\src\toolkit\sipi\dc\data\templates"
2016 html.figuresLocation = r'C:\Temp\report\result'
2017 html.progressCallback = progress
2018 import time
2019 stime = time.time()
2020 text = html.generate()
2021 empro.internal._figuresMetaData = html._figuresMetaData
2022 print time.time()-stime, "s"
2023 import codecs
2024 with codecs.open(r'C:\Temp\report\result\result.html','w','utf-8') as f:
2025 f.write(text)
2026
2027
2028 if False:
2029 import empro.toolkit.analysis.dc.results
2030 results = empro.toolkit.analysis.dc.results.DCResults(empro.activeProject.analyses[-1])
2031 gr = empro.gui.GraphicsScene()
2032 _powerGraphSceneFromResults(gr,results)
2033 gr._save(r"c:\temp\powerGraph.png")
2034