Package empro :: Package toolkit :: Module eemAdfiParse
[frames] | no frames]

Source Code for Module empro.toolkit.eemAdfiParse

   1  #!python 
   2  # Copyright Keysight Technologies 2009 - 2017   
   3  # Copyright (C)  Keysight EEsof EDA 
   4  # All rights reserved. 
   5  # 
   6  # Process an DFI file for import into ADS 
   7  # 
   8  # invoked through ads_invoke_process("eesofSubed", "", ".",TRUE,TRUE,"tt") 
   9   
  10  import string 
  11  import re 
  12  import os 
  13  import sys 
  14  import subprocess 
  15  import logging 
  16   
  17  if __name__=="__main__": 
  18      # From ADS this file is always executed as the main program 
  19      # The current working directory is then set such that there is write permission 
  20      logfile = './eemAdfiParse.log' 
  21  else:     
  22      # From EMPro this module is imported 
  23      # The current working directory is not set and it may have no write permission 
  24      import tempfile 
  25      file_h, logfile = tempfile.mkstemp("_eemAdfiParse.log") 
  26      os.close(file_h) 
  27   
  28  #enable new logging on recent versions 
  29  hversion=sys.hexversion 
  30  if hversion >= 0x20401F0: 
  31      #setup logging before loading other modules that use logging 
  32      logging.basicConfig(level=logging.DEBUG, 
  33                      format='%(asctime)s %(levelname)-8s %(message)s', 
  34                      datefmt='%a, %d %b %Y %H:%M:%S', 
  35                      filename=logfile, 
  36                      filemode='w') 
  37      console = logging.StreamHandler() 
  38      console.setLevel(logging.INFO) 
  39      formatter = logging.Formatter('ADFI parser: %(levelname)-8s %(message)s') 
  40      console.setFormatter(formatter) 
  41      logging.getLogger('').addHandler(console) 
  42      console.flush() 
  43   
  44      eemWriteError=logging.error 
  45      eemWriteWarn=logging.warn 
  46      eemWriteInfo=logging.info 
  47      eemWriteDebug=logging.debug 
  48  else: 
49 - def eemWriteLog(iType,iMessage):
50 sys.stderr.write('%s: %s\n' % (iType,iMessage))
51 - def eemWriteError(iMessage):
52 eemWriteLog('Error',iMessage)
53 - def eemWriteWarn(iMessage):
54 eemWriteLog('Warning',iMessage)
55 - def eemWriteInfo(iMessage):
56 eemWriteLog('Info',iMessage)
57 - def eemWriteDebug(iMessage):
58 eemWriteLog('Debug',iMessage)
59 eemWriteWarn('Using stderr for log output') 60 61 if hversion < 0x20401F0: 62 eemWriteError('Python version not recent enough') 63 sys.exit(1) 64 65 66 ############################################################################## 67 # parsing using Python's xml.dom.minidom and xml.dom.pulldom modules 68 # 69 import xml.dom.pulldom 70 import xml.dom.minidom 71 import xml.sax 72 import xml.sax.handler 73
74 -def eemGetElNodeValByTag(iNode, iTag):
75 elements = iNode.getElementsByTagName(iTag) 76 value = None 77 if elements and len(elements)==1: 78 value = getInnerText(elements[0]) 79 return value
80
81 -def eemGetElNodeAttrByTagAttrValue(iNode, iTag, attrKeyName, attrKeyValue, attrValueName):
82 elements = iNode.getElementsByTagName(iTag) 83 for el in elements: 84 if el.hasAttribute(attrKeyName) and el.getAttribute(attrKeyName).upper() == attrKeyValue.upper(): 85 if el.hasAttribute(attrValueName): 86 return el.getAttribute(attrValueName) 87 return None
88
89 -def contentOfNode(node):
90 if node.nodeType == node.TEXT_NODE: 91 return node.data 92 elif node.nodeType==node.ELEMENT_NODE: 93 return getInnerText(node) # recursive !!! 94 elif node.nodeType==node.CDATA_SECTION_NODE: 95 return node.data 96 else: 97 # node.nodeType: PROCESSING_INSTRUCTION_NODE, COMMENT_NODE, DOCUMENT_NODE, NOTATION_NODE and so on 98 pass
99
100 -def getInnerText(oNode):
101 rc = "" 102 nodelist = oNode.childNodes 103 rc = ''.join([contentOfNode(node) for node in nodelist]) 104 return rc
105 106
107 -def eemFixName(iName, iMapChar='[^a-zA-Z0-9_@`#&$%^=+-]'):
108 return re.sub(iMapChar, '_', iName)
109 110
111 -class AdfiInfo:
112 - def __init__(self):
113 self.version=None 114 self.mainVersion=-1 115 self.minorVersion=None 116 self.revision=0 117 self.tool=None 118 self.target=None 119 self.drawing_units=None 120 self.drawing_resolution=None
121
122 - def setAdfiToAdsAttributes(self,event,nodeAdfiToAds):
123 if event==xml.dom.pulldom.START_ELEMENT and nodeAdfiToAds.localName=='AdfiToAds': 124 if nodeAdfiToAds.hasAttribute('adfiVersion'): 125 self.version=nodeAdfiToAds.getAttribute('adfiVersion') 126 vl=self.version.split('.') 127 self.mainVersion=int(vl[0]) 128 if len(vl)==3: 129 self.minorVersion=int(vl[1]) 130 self.minorVersion=int(vl[-1]) 131 if nodeAdfiToAds.hasAttribute('tool'): 132 self.tool=nodeAdfiToAds.getAttribute('tool') 133 if nodeAdfiToAds.hasAttribute('adfiTarget'): 134 self.target=nodeAdfiToAds.getAttribute('adfiTarget')
135
136 - def setUnits(self,iUnitsNode):
137 self.drawing_units=eemGetElNodeAttrByTagAttrValue(iUnitsNode, "Unit", 'key', 'drawing_units', 'value') 138 self.drawing_resolution=eemGetElNodeAttrByTagAttrValue(iUnitsNode, "Unit", 'key', 'drawing_resolution', 'value')
139
141 # TODO: add other units 142 factorMap = {'m':1,'mm':1e-3,'um':1e-6,'nm':1e-9,'pm':1e-12,'mil':2.54e-5,'inch':2.54e-2,'in':2.54e-2} 143 conversionFactor = 1 144 unit=self.drawing_units 145 if unit in factorMap.keys(): 146 conversionFactor = factorMap[unit] 147 else: 148 raise Exception('Unknown unit %s' % unit) 149 return conversionFactor
150
151 - def checkTargetPlatform(self,target='ads'):
152 if self.target == None: 153 return 154 if self.target!=target: 155 # if self.version = 4.1.4 then the adfiTarget is always ads -> ignore check 156 if self.version != None and self.version == "4.1.4": 157 return 158 raise Exception('Adfi target platform: %s not matching!' % self.target) 159 else: 160 pass
161 162
163 -class AdfiEgsWriter:
164 """This class is used to write out .egs file."""
165 - def __init__(self, fileName,useSolderBalls=False):
166 self.fileName = fileName 167 self.file = None 168 self.useSolderBalls=useSolderBalls 169 self.filterEgs={}
170
171 - def close(self):
172 if self.file==None: 173 return 174 self.file.close()
175
176 - def writeHeader(self, egsHeader=''):
177 try: 178 if self.file==None: 179 self.file = open(self.fileName,'w') 180 self.file.write(egsHeader) 181 self.file.write("\n\n") 182 except: 183 raise Exception("Failed to write egs header in %s!" % self.fileName)
184 185
186 - def writeBody(self, iEgsData='', iId='', iName='', top=None, maskNameNbMap={}):
187 if self.file==None: 188 raise Exception("Failed to write into egs file") 189 #assemble egs here 190 refDes = eemFixName(iId) 191 egsData = iEgsData 192 egsBody = '' 193 name = iName 194 if top: 195 refDes += "_adfi" 196 if iId in self.filterEgs.keys(): 197 # Filter out layer bumpLayerNb and pinLayerNb 198 #eemWriteDebug("Egs data to be filtered %s" % (egsData)) 199 (bumpLayer, pinLayer)=self.filterEgs[iId] 200 bumpLayerNb = maskNameNbMap[bumpLayer] 201 pinLayerNb = maskNameNbMap[pinLayer] 202 egsData = re.sub('ADD [A-Z]%s \:W.+;\n*'% bumpLayerNb,'', egsData) 203 egsData = re.sub('ADD [A-Z]%s \:W.+;\n*'% pinLayerNb,'', egsData) 204 #eemWriteDebug("Egs data after filtering %s" % (egsData)) 205 pass 206 egsBody += "EDIT " + refDes + ";\n" 207 egsBody += "$$ component " + name + " instance " + refDes + ";\n" 208 egsBody += egsData + "\nSAVE;\n\n" 209 self.file.write(egsBody)
210
211 - def updateFilterEgsMap(self,cmpParmsNode,iId=''):
212 parameters = getComponentParms(cmpParmsNode) 213 # eemWriteDebug("update egs map %s" % str(parameters)) 214 if self.useSolderBalls and parameters: 215 if parameters.has_key('ICPKG_TYPE') and parameters['ICPKG_TYPE'] == 'DIE_FLIPCHIP': 216 bumpLayer = parameters['ICPKG_BUMP_LAYER'] 217 pinLayer = parameters['ICPKG_PIN_LAYER'] 218 self.filterEgs[iId]=tuple([bumpLayer,pinLayer]) 219 eemWriteDebug("Found flipchip component with solder balls on layer %s to be excluded from egs." % bumpLayer) 220 elif parameters.has_key('PKG_TYPE') and parameters['PKG_TYPE'] == 'BGA': 221 filterEgs = True 222 bumpLayer = parameters['PKG_BALL_LAYER'] 223 pinLayer = parameters['PKG_PIN_LAYER_ATPKG'] 224 self.filterEgs[iId]=tuple([bumpLayer,pinLayer]) 225 eemWriteDebug("Found BGA component with solder balls on layer %s to be excluded from egs." % bumpLayer)
226 227
228 -def getMaskNames(iStacks):
229 # get top level substrate information 230 ltdFile = iStacks.getLtdFileName(None) 231 ltdFp = open( ltdFile, "r" ) 232 maskNameNbMap = {} 233 for line in ltdFp.readlines(): 234 words = line.split() 235 if len(words) < 3: 236 continue 237 if (words[0].upper() != 'MASK'): 238 continue 239 maskNb = words[1] 240 for w in words[2:]: 241 subwords=w.split('=') 242 if len(subwords) < 2: 243 continue 244 if (subwords[0].upper() != 'NAME'): 245 continue 246 maskName = subwords[1] 247 maskNameNbMap[maskName]=maskNb 248 ltdFp.close() 249 return maskNameNbMap
250 251
252 -class AdfiHdefWriter:
253 """This class is used to write out .hdef file."""
254 - def __init__(self, fprefix, iAdfiInfo, iAblPresent=False, iUseAblRoot=False):
255 fName = fprefix + '_adfi.ahdf' 256 eemWriteDebug("ADFI Hierarchical Definition Filename is: %s" % fName) 257 self.dirName=os.path.dirname(fName) 258 self.hasAbl=iAblPresent 259 self.useAblRoot=iUseAblRoot 260 self.file = open(fName, "w") 261 self.file.write("\"ADFISTARTINFO|VERSION|%s|TOOL|%s\",\n" %(iAdfiInfo.version, iAdfiInfo.tool))
262
263 - def close(self):
264 self.file.close()
265
266 - def writeLibrarySubstrate(self,iStacks=None):
267 if self.hasAbl: 268 return 269 refDesName=None 270 slmFile=None 271 ltdFile=None 272 if iStacks: 273 refDesName = iStacks.getTopDesignName() 274 slmFile = iStacks.getSlmFileName(refDesName) 275 ltdFile = iStacks.getLtdFileName(refDesName) 276 if slmFile!=None: 277 if ltdFile==None: 278 self.file.write("\"ADFILIBRARYSUBSTRATE|DESIGN|%s|%s\",\n" % (eemFixName(refDesName),slmFile)) 279 else: 280 self.file.write("\"ADFILIBRARYSUBSTRATE|DESIGN|%s|%s|%s\",\n" % (eemFixName(refDesName + "_adfi"),slmFile,ltdFile))
281
282 - def writeCmpInfo(self, adfiVersion, tool, refDes, name, cmpType, topLevel, mainLevel, viewName):
283 if viewName == None or viewName == '': 284 self.file.write("\"ADFICMPINFO|VERSION|%s|TOOL|%s|DESIGN|%s|CMPNAME|%s|TYPE|%s|TOP|%s|MAIN|%s\",\n" % 285 (adfiVersion, tool, eemFixName(refDes), eemFixName(name), cmpType, topLevel, mainLevel)) 286 else: 287 self.file.write("\"ADFICMPINFO|VERSION|%s|TOOL|%s|DESIGN|%s|CMPNAME|%s|TYPE|%s|TOP|%s|MAIN|%s|VIEW|%s\",\n" % 288 (adfiVersion, tool, eemFixName(refDes), eemFixName(name), cmpType, topLevel, mainLevel, eemFixName(viewName)))
289
290 - def writeFiguresInfo(self,iVersion, iTool, iRefDes):
291 self.file.write("\"ADFIFIGURESINFO|VERSION|%s|TOOL|%s|DESIGN|%s\",\n" % (iVersion, iTool, eemFixName(iRefDes)))
292
293 - def writeCircleFormat(self):
294 self.file.write("\"ADFIFIGURESCIRCLEFORMAT|LAYERNUMBER|LAYERNAME|RADIUS|XLOC|YLOC\"\n")
295 - def writeTraceFormat(self):
296 self.file.write("\"ADFIFIGURESTRACEFORMAT|LAYERNUMBER|LAYERNAME|WIDTH|RADIUS[|X|Y]+\"\n")
297 - def writePolygonFormat(self):
298 self.file.write("\"ADFIFIGURESPOLYGONFORMAT|LAYERNUMBER|LAYERNAME|NROFHOLES\n")
299 - def writeViaFormat(self):
300 self.file.write("\"ADFIFIGURESVIASFORMAT|VIANAME[|X|Y]+\"\n")
301
302 - def writeCircle(self, node):
303 layerName = eemGetElNodeValByTag(node, 'LayerName') 304 layerNumber= eemGetElNodeValByTag(node, 'LayerNumber') 305 r = eemAdfiGetRadius(node) 306 (x,y) = eemAdfiGetLocation(node,'XY') 307 self.file.write("\"ADFIFIGURESCIRCLEDEF|%s|%s|%s|%s|%s\"\n" % 308 (layerNumber,layerName,r,x,y))
309
310 - def writeTrace(self,tr):
311 layerName = eemGetElNodeValByTag(tr, 'LayerName') 312 layerNumber= eemGetElNodeValByTag(tr, 'LayerNumber') 313 r = eemAdfiGetRadius(tr) 314 w = eemAdfiGetWidth(tr) 315 self.file.write("\"ADFIFIGURESTRACEDEF|%s|%s|%s|%s" % 316 (layerNumber,layerName,w,r)) 317 xys = tr.getElementsByTagName('XY') 318 trs="" 319 for xy in xys: 320 x=xy.getAttribute('x') 321 y=xy.getAttribute('y') 322 trs+=("|%s|%s" % (x,y)) 323 self.file.write("%s\"\n" %trs)
324
325 - def writePolygon(self, p):
326 layerName = eemGetElNodeValByTag(p, 'LayerName') 327 layerNumber= eemGetElNodeValByTag(p, 'LayerNumber') 328 outline = p.getElementsByTagName('Outline') 329 verts = getInnerText(outline[0].getElementsByTagName('Vertices')[0]) 330 verts = verts.strip('\n') 331 bulges = getInnerText(outline[0].getElementsByTagName('Bulges')[0]) 332 bulges = bulges.strip('\n') 333 holes = p.getElementsByTagName('Hole') 334 nrOfHoles = len(holes) 335 eemWriteDebug("Polygon %s with holes %d: %s" % (str(p),nrOfHoles,str(holes))) 336 self.file.write("\"ADFIFIGURESPOLYGONDEF|%s|%s|%d\"\n" % (layerNumber,layerName,nrOfHoles)) 337 self.file.write("\"ADFIFIGURESPOLYGONOUTLV|%s\"\n" % verts) 338 self.file.write("\"ADFIFIGURESPOLYGONOUTLB|%s\"\n" % bulges) 339 for hole in holes: 340 vertsHole = getInnerText(hole.getElementsByTagName('Vertices')[0]) 341 vertsHole = vertsHole.strip('\n').replace(',',' ') 342 bulgesHole = getInnerText(hole.getElementsByTagName('Bulges')[0]) 343 bulgesHole = bulgesHole.strip('\n').replace(',',' ') 344 self.file.write("\"ADFIFIGURESPOLYGONHOLEV|%s\"\n" % vertsHole) 345 self.file.write("\"ADFIFIGURESPOLYGONHOLEB|%s\"\n" % bulgesHole) 346 self.file.write("\"ADFIFIGURESPOLYGONEND\"\n")
347
348 - def writeOAVias(self,v):
349 viaName = eemGetElNodeValByTag(v, 'ViaName') 350 xys = v.getElementsByTagName('XY') 351 vS="" 352 for xy in xys: 353 x=xy.getAttribute('x') 354 y=xy.getAttribute('y') 355 vS+=("|%s|%s" % (x,y)) 356 self.file.write("\"ADFIFIGURESVIASDEF|%s%s\"\n" % (viaName,vS))
357
358 - def writeAblShapes(self, shapesEvents, iRefDes):
359 shapesName = iRefDes + '_shapes.xml' 360 fName = os.path.join(self.dirName, shapesName) 361 curString = "<abl:Shapes " 362 if self.useAblRoot: 363 curString += "xmlns:abl=\"http://keysight.com/eesof/abl\">\n" 364 else: 365 curString += "xmlns:abl=\"http://agilent.com/abl\">\n" 366 nrOfNodes = 0 367 shapeFile = None 368 for (event,node) in shapesEvents: 369 if (event==xml.dom.pulldom.START_ELEMENT 370 and ( node.tagName in ('abl:Trace', 'abl:Path', "abl:oaEllipse", "abl:oaPolygon", "abl:oaLine") ) ): 371 shapesEvents.expandNode(node) 372 curString += node.toxml() + '\n' 373 nrOfNodes+=1 374 if ( nrOfNodes > 10 ): 375 if shapeFile==None: 376 shapeFile = open(fName, "w") 377 shapeFile.write( curString ) 378 curString = '' 379 elif (event==xml.dom.pulldom.END_ELEMENT 380 and node.tagName=='abl:Shapes'): 381 break 382 383 if ( nrOfNodes<=10): 384 self.file.write("\"ADFIABL_SHAPES_START\",\n") 385 self.file.write(curString) 386 self.file.write("</abl:Shapes>\n\"ADFIABL_SHAPES_END\",\n") 387 else: 388 if ( len(curString)>0 ): 389 shapeFile.write(curString) 390 shapeFile.write("</abl:Shapes>\n") 391 shapeFile.close() 392 self.file.write("\"ADFIABL_SHAPES_FILE|%s\",\n" % shapesName)
393 394
395 - def writeFiguresEnd(self, nrOfFigures):
396 self.file.write("\"ADFIFIGURESEND|%d\",\n" % nrOfFigures)
397
398 - def writeParmsToFile(self, iParms, iType, iRefDes, iTool, iVersion, iParmsFromFile):
399 if (iParms or iParmsFromFile): 400 self.file.write("\"ADFI%sPARMSINFO|VERSION|%s|TOOL|%s|DESIGN|%s\",\n" % 401 (iType, iVersion, iTool, eemFixName(iRefDes))) 402 self.file.write("\"ADFI%sPARMSFORMAT|Key|Value\",\n" % iType) 403 404 eemWriteDebug("parameters %s" % str(iParms)) 405 parms = iParms[0].getElementsByTagName('Parameter') 406 parmMap = {} 407 if iParmsFromFile != None: 408 parmMap = iParmsFromFile 409 410 #process the adfi exported parameters and csv list into one map 411 for parm in parms: 412 key = parm.getAttribute('key') 413 value = parm.getAttribute('value') 414 if key == 'VALUE': 415 value = eemAdfiWriteConvertToADSValues(iRefDes,value) 416 value = re.sub('[Ss]iemens','S',value) 417 value = re.sub('[oO][hH][mM]','Ohm',value) 418 if key not in parmMap.keys(): 419 parmMap[key] = value 420 421 #write all the parameters to the file 422 for key,value in parmMap.iteritems(): 423 self.file.write("\"ADFI%sPARM|%s|%s\",\n" % (iType, key, value)) 424 425 self.file.write("\"ADFI%sPARMSEND|%d\",\n" % (iType, len(parms)))
426
427 - def writePinInfo(self,iVersion, iTool, iRefDes):
428 self.file.write("\"ADFIPININFO|VERSION|%s|TOOL|%s|DESIGN|%s\",\n" % (iVersion, iTool, eemFixName(iRefDes))) 429 self.file.write("\"ADFIPINFORMAT|PINNAME|LAYERNUMBER|LAYERNAME|PORTNUMBER|PINNUMBER|"+ 430 "NETNAME|XLOC|YLOC|PINTYPE|REPORTZ|IMPORTZ|PORTOFFSET|PORTNAME|POSNEG\",\n") 431 self.file.write("\"ADFIPINFORMATAREA|PINNAME[|x|y]+\",\n")
432
433 - def writePinEnd(self,nrOfPins):
434 self.file.write("\"ADFIPINEND|%d\",\n" % nrOfPins)
435
436 - def writePinDef(self,pinName,layerNumber,layerName,portNumber,pinNumber,netName, 437 xLoc,yLoc,pinType,rePortZ,imPortZ,portOffset,portName,posNeg):
438 self.file.write("\"ADFIPINDEF|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s\",\n" % 439 (pinName,layerNumber,layerName,portNumber,pinNumber,netName, 440 xLoc,yLoc,pinType,rePortZ,imPortZ,portOffset,portName,posNeg))
441
442 - def writePinExtra(self,phi,diffPair,isMultiPortRef,usage):
443 if phi != 0.0 or diffPair != None or isMultiPortRef or usage != None: 444 self.file.write("\"ADFIPINEXTRA") 445 if phi != 0.0: 446 self.file.write("|ANGLE|%s" % phi) 447 if diffPair != None: 448 self.file.write("|DIFFPAIR|%s" % diffPair) 449 if isMultiPortRef == True: 450 self.file.write("|MULTIPORTREF|TRUE") 451 if usage != None: 452 self.file.write("|USAGE|%s" % usage) 453 self.file.write("\"\n")
454
455 - def writePinAreaCircle(self,pinName,x,y,r):
456 self.file.write("\"ADFIPINAREA|%s|%s|%s|%s|%s\",\n" % (pinName,'CR',x,y,r))
457
458 - def writePinAreaCircle(self,pinName,x,y,r):
459 self.file.write("\"ADFIPINAREA|%s|%s|%s|%s|%s\",\n" % (pinName,'CR',x,y,r))
460
461 - def writePinAreaPolygon(self,pinName,verts,bulges):
462 self.file.write("\"ADFIPINAREA|%s|%s|%s|%s\",\n" % (pinName,'PP',verts,bulges))
463
464 - def writePinAreaString(self,pinName,pinString):
465 self.file.write("\"ADFIPINAREA|%s|%s\",\n" % (pinName,pinString))
466
467 - def writeInstsInfo(self,iVersion, iTool, iRefDes):
468 self.file.write("\"ADFIINSTSINFO|VERSION|%s|TOOL|%s|DESIGN|%s\",\n" % (iVersion, iTool, eemFixName(iRefDes))) 469 self.file.write("\"ADFIINSTDATAFORMAT|REFDES|CMPNAME|XLOC|YLOC|ROTATION[|VIEW]\",\n")
470
471 - def writeInstData(self, refDes, cmpName, viewName,xLoc, yLoc, rot):
472 if viewName != None: 473 self.file.write("\"ADFIINSTDATA|%s|%s|%s|%s|%s|%s\",\n" % 474 (eemFixName(refDes), eemFixName(cmpName), xLoc, yLoc, rot, eemFixName(viewName))) 475 else: 476 self.file.write("\"ADFIINSTDATA|%s|%s|%s|%s|%s\",\n" % 477 (eemFixName(refDes), eemFixName(cmpName), xLoc, yLoc, rot))
478
479 - def writeInstsEnd(self, nrOfInstances):
480 self.file.write("\"ADFIINSTSEND|%d\",\n" % nrOfInstances)
481
482 - def writeRefLocation(self,refLocation):
483 self.file.write("\"ADFICMPREFLOCATION|X|%s|Y|%s\",\n" % refLocation)
484
485 - def writeCmpSubstrate(self,refDes,refDesName,iStacks):
486 if self.hasAbl: 487 return 488 slmFile = iStacks.getSlmFileName(refDesName) 489 ltdFile = iStacks.getLtdFileName(refDesName) 490 if slmFile!=None: 491 if ltdFile==None: 492 self.file.write("\"ADFICMPSUBSTRATE|%s\",\n" % slmFile) 493 else: 494 self.file.write("\"ADFICMPSUBSTRATE|%s|%s\",\n" % (slmFile,ltdFile))
495
496 - def writeCmpEnd(self,refDes):
497 self.file.write("\"ADFICMPEND|DESIGN|%s\",\n" % eemFixName(refDes))
498
499 - def writeEnd(self,nrOfComponent):
500 self.file.write("\"ADFIEND|%d\"\n\n" % nrOfComponent)
501 502
503 -def eemAdfiProcessHDefEgsFile(iAdfiDoc, iAdfiInfo, iHDefWriter, iEgsWriter, iBondWireWriter, 504 iStacks, iParmMap, iMaskNameNbMap={}):
505 """extract and write pin/port/comp info""" 506 507 eemWriteDebug("Writing hierarchical design data") 508 tool = iAdfiInfo.tool 509 adfiVersion = iAdfiInfo.version 510 511 parser=xml.sax.make_parser() 512 # skip external dtd definition 513 parser.setFeature(xml.sax.handler.feature_external_ges,0) 514 # limit parser memory to about 1GByte 515 events = xml.dom.pulldom.parse(iAdfiDoc,parser,1024*1024*16) 516 517 iHDefWriter.writeLibrarySubstrate(iStacks) 518 519 cmpName='' 520 refDes='' 521 refDesName='' 522 viewName='' 523 inComponent=None 524 topLevel='FALSE' 525 top=False 526 mainLevel='FALSE' 527 addedParameters = None 528 nrOfComponent=0 529 egsData='' 530 name='' 531 drawingConversionFactor=iAdfiInfo.getDrawingUnitConversionFactor() 532 for (event,node) in events: 533 if (event!=xml.dom.pulldom.START_ELEMENT 534 and event!=xml.dom.pulldom.END_ELEMENT): 535 continue 536 elif (event==xml.dom.pulldom.START_ELEMENT 537 and node.localName=="AdfiComponent"): 538 cmpName = (node.getAttribute('id')).strip() 539 inComponent=True 540 viewName='' 541 name='' 542 if node.getAttribute('top') == 'true': 543 topLevel = 'TRUE' 544 top=True 545 else: 546 topLevel = 'FALSE' 547 top=False 548 if node.hasAttribute('main') and node.getAttribute('main') == 'true': 549 mainLevel = 'TRUE' 550 else: 551 mainLevel = 'FALSE' 552 elif (inComponent 553 and event==xml.dom.pulldom.START_ELEMENT 554 and node.localName=="Name"): 555 events.expandNode(node) 556 name=(getInnerText(node)).strip() 557 if cmpName==None or cmpName=='': 558 cmpName=name 559 refDes = cmpName 560 refDesName = refDes 561 if top: 562 refDes = refDes + "_adfi" 563 elif (inComponent 564 and event==xml.dom.pulldom.START_ELEMENT 565 and node.localName=="View"): 566 events.expandNode(node) 567 viewNameString=(getInnerText(node)).strip() 568 if viewName==None or viewName=='': 569 viewName = viewNameString 570 refDes = cmpName 571 refDesName = refDes 572 if top: 573 refDes = refDes + "_adfi" 574 elif (inComponent 575 and event==xml.dom.pulldom.START_ELEMENT 576 and node.localName=="Units"): 577 events.expandNode(node) 578 drawingConversionFactor=getDrawingUnitConversionFactor(node) 579 if drawingConversionFactor==None: 580 drawingConversionFactor=iAdfiInfo.getDrawingUnitConversionFactor() 581 elif (inComponent 582 and event==xml.dom.pulldom.START_ELEMENT 583 and node.localName=="Type"): 584 events.expandNode(node) 585 cmpType=getInnerText(node) 586 iHDefWriter.writeCmpInfo(adfiVersion, tool, refDes, name, cmpType, topLevel, mainLevel, viewName) 587 elif (inComponent 588 and event==xml.dom.pulldom.START_ELEMENT 589 and node.localName=="Geometry2D" 590 and node.hasAttribute('geometry2DType') 591 and node.getAttribute('geometry2DType')=='egs' 592 and (not node.hasAttribute('geometry2DOp') or 593 node.getAttribute('geometry2DOp')!='process')): 594 events.expandNode(node) 595 egsData=getInnerText(node) 596 iEgsWriter.writeBody(egsData,cmpName,name,top,iMaskNameNbMap) 597 elif (inComponent 598 and event==xml.dom.pulldom.START_ELEMENT 599 and node.localName=="Geometry2D" 600 and node.hasAttribute('geometry2DType') 601 and node.getAttribute('geometry2DType')=='direct'): 602 eemAdfiWriteCmpFiguresToFile(events, iHDefWriter, refDes, tool, adfiVersion) 603 elif (inComponent 604 and event==xml.dom.pulldom.START_ELEMENT 605 and node.localName=="ComponentParms"): 606 events.expandNode(node) 607 eemAdfiWriteCmpParmsToFile(iHDefWriter, node, refDes, tool, adfiVersion, addedParameters) 608 elif (inComponent 609 and event==xml.dom.pulldom.START_ELEMENT 610 and node.localName=="Ports"): 611 events.expandNode(node) 612 eemAdfiWriteCmpPinsToFile(iHDefWriter, node, refDes, tool, adfiVersion) 613 elif (inComponent 614 and event==xml.dom.pulldom.START_ELEMENT 615 and node.localName=="Instances"): 616 events.expandNode(node) 617 eemAdfiWriteCmpInstToFile(iHDefWriter, node, refDes, tool, adfiVersion, iParmMap) 618 iBondWireWriter.writeCmptBondwires(node,refDes,drawingConversionFactor) 619 elif (inComponent 620 and event==xml.dom.pulldom.START_ELEMENT 621 and node.localName=="RefLocation"): 622 events.expandNode(node) 623 eemAdfiWriteCmpRefLocationToFile(iHDefWriter, node) 624 elif event==xml.dom.pulldom.END_ELEMENT and node.localName=="AdfiComponent": 625 iHDefWriter.writeCmpSubstrate(refDes,refDesName,iStacks) 626 iHDefWriter.writeCmpEnd(refDes) 627 nrOfComponent+=1 628 629 cmpName='' 630 refDes='' 631 refDesName='' 632 inComponent=None 633 topLevel='FALSE' 634 top=False 635 addedParameters = None 636 egsData='' 637 name='' 638 iHDefWriter.writeEnd(nrOfComponent) 639 eemWriteDebug("Writing hierarchical design data done")
640 641 #process the trace/circle like objects
642 -def eemAdfiWriteCmpFiguresToFile(events, iHDefWriter, iRefDes, iTool, iVersion):
643 eemWriteDebug("Processing the figures of %s" % iRefDes) 644 nrOfFigures = 0 645 nrOfCircles=0 646 nrOfTraces=0 647 nrOfPolygons=0 648 nrOfVias=0 649 for (event,node) in events: 650 if (event==xml.dom.pulldom.START_ELEMENT 651 and node.tagName=="abl:Shapes"): 652 iHDefWriter.writeAblShapes(events, iRefDes) 653 elif (event==xml.dom.pulldom.START_ELEMENT 654 and node.localName=="Figures"): 655 iHDefWriter.writeFiguresInfo(iVersion, iTool, iRefDes) 656 elif (event==xml.dom.pulldom.START_ELEMENT 657 and node.localName=='Circle'): 658 if nrOfCircles==0: 659 iHDefWriter.writeCircleFormat() 660 nrOfFigures+=1 661 nrOfCircles+=1 662 events.expandNode(node) 663 iHDefWriter.writeCircle(node) 664 elif (event==xml.dom.pulldom.START_ELEMENT 665 and node.localName=='Trace'): 666 if nrOfTraces==0: 667 iHDefWriter.writeTraceFormat() 668 nrOfFigures+=1 669 nrOfTraces+=1 670 events.expandNode(node) 671 iHDefWriter.writeTrace(node) 672 elif (event==xml.dom.pulldom.START_ELEMENT 673 and node.localName=='Polygon'): 674 if nrOfPolygons==0: 675 iHDefWriter.writePolygonFormat() 676 nrOfFigures+=1 677 nrOfPolygons+=1 678 events.expandNode(node) 679 iHDefWriter.writePolygon(node) 680 elif (event==xml.dom.pulldom.START_ELEMENT 681 and node.localName=='OAVias'): 682 if nrOfVias==0: 683 iHDefWriter.writeViaFormat() 684 nrOfFigures+=1 685 nrOfVias+=1 686 events.expandNode(node) 687 iHDefWriter.writeOAVias(node) 688 elif (event==xml.dom.pulldom.END_ELEMENT 689 and ( node.localName=='Figures' or node.localName=='Geometry2D') ): 690 if( nrOfFigures>0 ): 691 iHDefWriter.writeFiguresEnd(nrOfFigures) 692 break 693 eemWriteDebug("End processing the figures of %s" % iRefDes)
694 695
696 -def eemAdfiWriteCmpPinsToFile(iHDefWriter, iCmp, iRefDes, iTool, iVersion):
697 eemWriteDebug("Process the pins of %s" % iRefDes) 698 pins = iCmp.getElementsByTagName('PortDescription') 699 if pins: 700 iHDefWriter.writePinInfo(iVersion, iTool, iRefDes) 701 cmpPinSet = set() 702 for pin in pins: 703 eemAdfiWriteCmpPinToFile(iHDefWriter, pin, cmpPinSet) 704 eemAdfiWriteCmpPinAreaToFile(iHDefWriter, pin) 705 iHDefWriter.writePinEnd(len(pins)) 706 eemWriteDebug("Processing pins %s done" % iRefDes)
707
708 -def eemAdfiGetLocation (iNode, locElName='Location'):
709 if (iNode.localName==locElName): 710 xLoc = iNode.getAttribute('x') 711 yLoc = iNode.getAttribute('y') 712 else: 713 location = iNode.getElementsByTagName(locElName) 714 if location: 715 xLoc = location[0].getAttribute('x') 716 yLoc = location[0].getAttribute('y') 717 else: 718 xLoc = '0.0' 719 yLoc = '0.0' 720 return (xLoc,yLoc)
721
722 -def eemAdfiGetRotation (iNode):
723 phi = '0.0' 724 rot = iNode.getElementsByTagName('Rotation') 725 if rot: 726 phi = rot[0].getAttribute('phi') 727 return phi
728
729 -def eemAdfiGetRadius (iNode):
730 r = '0.0' 731 rad = iNode.getElementsByTagName('Radius') 732 if rad: 733 r = rad[0].getAttribute('r') 734 return r
735
736 -def eemAdfiGetWidth (iNode):
737 w = '0.0' 738 width = iNode.getElementsByTagName('Width') 739 if width: 740 w = width[0].getAttribute('w') 741 return w
742
743 -def eemAdfiWriteCmpRefLocationToFile(iHDefWriter,iNode):
744 refLocation = eemAdfiGetLocation(iNode,'RefLocation') 745 if refLocation!=('0.0','0.0'): 746 eemWriteDebug("Ref location found: %s,%s" % refLocation) 747 iHDefWriter.writeRefLocation(refLocation)
748
749 -def eemAdfiWriteCmpPinToFile(iHDefWriter, iPin, pinSet):
750 pinName = eemGetElNodeValByTag(iPin, 'PinName') 751 eemWriteDebug("Process pin %s" % pinName) 752 pinNumber = eemGetElNodeValByTag(iPin, 'PinNumber') 753 portNumber = eemGetElNodeValByTag(iPin, 'PortNumber') 754 if portNumber == None: 755 portNumber = pinNumber 756 layerName = eemGetElNodeValByTag(iPin, 'LayerName') 757 layerNumber= eemGetElNodeValByTag(iPin, 'LayerNumber') 758 netName = eemGetElNodeValByTag(iPin, 'NetName') 759 if netName == None: 760 netName = '__NONE__' 761 (xLoc,yLoc)= eemAdfiGetLocation(iPin) 762 phi = eemAdfiGetRotation(iPin) 763 pinType = eemGetElNodeValByTag(iPin, 'PinType') 764 if pinType == None: 765 pinType = '0' 766 rePortZ = eemGetElNodeValByTag(iPin, 'RePortZ') 767 if rePortZ == None: 768 rePortZ = '50.0' 769 imPortZ = eemGetElNodeValByTag(iPin, 'ImPortZ') 770 if imPortZ == None: 771 imPortZ = '0.0' 772 portOffset = eemGetElNodeValByTag(iPin, 'PortOffset') 773 if portOffset == None: 774 portOffset = '0.0' 775 portName = eemGetElNodeValByTag(iPin, 'PortName') 776 if portName == None: 777 portName = pinName 778 posNeg = eemGetElNodeValByTag(iPin, 'PosNeg') 779 if posNeg == None: 780 posNeg = '0' 781 diffPair = eemGetElNodeValByTag(iPin, 'DifferentialPair') 782 usage = eemGetElNodeValByTag(iPin, 'Usage') 783 784 iHDefWriter.writePinDef(pinName,layerNumber,layerName,portNumber,pinNumber,netName, 785 xLoc,yLoc,pinType,rePortZ,imPortZ,portOffset,portName,posNeg) 786 pinId = pinName 787 isMultiPortRef = False 788 if pinId in pinSet: 789 isMultiPortRef = True 790 else: 791 pinSet.add(pinId) 792 793 iHDefWriter.writePinExtra(phi,diffPair,isMultiPortRef,usage)
794 795
796 -def eemAdfiWriteCmpPinAreaToFile(iHDefWriter, iPin):
797 pinName = eemGetElNodeValByTag(iPin, 'PinName') 798 pinArea = iPin.getElementsByTagName('PinArea') 799 if pinArea: 800 # eemWriteDebug("Process pin polygon for %s" % pinName) 801 pinAreaType = pinArea[0].getAttribute('pinAreaType') 802 if pinAreaType=='direct': 803 circle = pinArea[0].getElementsByTagName('Circle') 804 if circle: 805 r = eemAdfiGetRadius(circle[0]) 806 (x,y) = eemAdfiGetLocation(circle[0],'XY') 807 iHDefWriter.writePinAreaCircle(pinName,x,y,r) 808 else: 809 polygon = pinArea[0].getElementsByTagName('Polygon') 810 if polygon: 811 #eemWriteDebug("Process pin polygon %s for %s" % (pinName, str(polygon[0]))) 812 outline = polygon[0].getElementsByTagName('Outline') 813 verts = getInnerText(outline[0].getElementsByTagName('Vertices')[0]) 814 verts = verts.strip('\n') 815 #eemWriteDebug("Process pin polygon %s for %s\n" % (pinName, verts)) 816 bulges = getInnerText(outline[0].getElementsByTagName('Bulges')[0]) 817 bulges = bulges.strip('\n') 818 #eemWriteDebug("Process pin polygon %s for %s\n" % (pinName, bulges)) 819 iHDefWriter.writePinAreaPolygon(pinName,verts,bulges) 820 else: 821 pinString = str(getInnerText(pinArea[0])) 822 #eemWriteDebug("Pin area string: %s" % pinString) 823 if len(pinString)>5: 824 # need to check for other shapes 825 pinString = re.sub('ADD ([CPLR])[0-9]+ \:W[0-9.]+ ',r'\1 ', pinString) 826 pinString = pinString.strip('\n \t;') 827 pinString = re.sub('[ ,]+','|', pinString) 828 iHDefWriter.writePinAreaString(pinName,pinString)
829
830 -def eemAdfiWriteCmpParmsToFile(iHDefWriter, iCmp, iRefDes, iTool, iVersion,iParmMap=None):
831 eemWriteDebug("Process Component parameters %s" % iRefDes) 832 addedParameters=None 833 if ((iParmMap != None) and (refDes in iParmMap.keys())): 834 addedParameters = iParmMap[refDes] 835 cmpParms=[] 836 if iCmp.localName=='ComponentParms': 837 cmpParms.append(iCmp) 838 else: 839 cmpParms = iCmp.getElementsByTagName('ComponentParms') 840 iHDefWriter.writeParmsToFile(cmpParms, 'CMP', iRefDes, iTool, iVersion, addedParameters) 841 eemWriteDebug("Process Component parameters %s done" % iRefDes)
842 843 844
845 -def eemAdfiWriteConvertToADSValues(iRefDes, iValue):
846 m = re.match('([-+]?[0-9]*[\.,]?[0-9]+)([eE][-+]?[0-9]+)?([ \t]+)?([a-zA-Z]+)?',iValue) 847 if m!=None: 848 value = m.group(1) 849 if m.group(2)!=None: 850 value = value + m.group(2) 851 if ((m.group(4)!=None) and 852 (m.group(4)!='')): 853 value = value + ' ' 854 if m.group(4) == 'MEG': 855 value = value + 'M' 856 elif len(m.group(4))==1: 857 if m.group(4) in ['A','F','K','N','P','U']: 858 value = value + m.group(4).lower() 859 else: 860 value = value + m.group(4) 861 elif len(m.group(4))==2: 862 if ((iRefDes[0] == 'L') 863 or (iRefDes[0] == 'C') 864 or (m.group(4)[1] in ['h','H','f','F'])): 865 if (m.group(4)[0] in ['A','F','K','M','N','P','U']): 866 value = value + m.group(4)[0].lower() + m.group(4)[1].upper() 867 else: 868 value = value + m.group(4)[0] + m.group(4)[1].upper() 869 else: 870 value = value + m.group(4) 871 else: 872 value = value + m.group(4) 873 else: 874 if (iRefDes[0] == 'L'): 875 value = value + ' nH' 876 if (iRefDes[0] == 'C'): 877 value = value + ' pF' 878 value = re.sub(',','.',value) 879 eemWriteDebug("Transformed ivalue: %s into value: %s" % (iValue,value)) 880 return value 881 return iValue
882 883 884
885 -def eemAdfiWriteCmpInstToFile(iHDefWriter, iCmp, iRefDes, iTool, iVersion, iParmMap):
886 eemWriteDebug("Process instances in component %s when present"% iRefDes) 887 instances = iCmp.getElementsByTagName('Instance') 888 if instances: 889 iHDefWriter.writeInstsInfo(iVersion, iTool, iRefDes) 890 for inst in instances: 891 refDes = inst.getAttribute('id') 892 cmpName = eemGetElNodeValByTag(inst, 'Component').strip() 893 viewName = eemGetElNodeValByTag(inst, 'View') 894 if viewName!=None: 895 viewName = viewName.strip() 896 eemWriteDebug("Process instance %s of component %s view %s" % (refDes, cmpName, viewName)) 897 else: 898 eemWriteDebug("Process instance %s of component %s" % (refDes,cmpName)) 899 (xLoc, yLoc) = eemAdfiGetLocation(inst) 900 rot = eemAdfiGetRotation(inst) 901 eemWriteDebug("Process instance location %s,%s rotation %s" % (xLoc,yLoc,rot)) 902 iHDefWriter.writeInstData(refDes, cmpName, viewName, xLoc, yLoc, rot) 903 #hierarchical instance param values from file 904 hInstName = iRefDes + '.' + refDes 905 addedParameters = None 906 if ((iParmMap != None) and (hInstName in iParmMap.keys())): 907 addedParameters = iParmMap[hInstName] 908 eemAdfiWriteInstParmsToFile(iHDefWriter, inst, refDes, iTool, iVersion, addedParameters) 909 eemWriteDebug("Processing instance %s of component %s done" % (refDes,cmpName)) 910 iHDefWriter.writeInstsEnd(len(instances))
911
912 -def eemAdfiWriteInstParmsToFile(iHDefWriter, iInst, instName, iTool, iVersion, iParmsFromFile):
913 eemWriteDebug("Process instance parameters %s" % instName) 914 instParms = iInst.getElementsByTagName('InstanceParms') 915 iHDefWriter.writeParmsToFile(instParms, 'INST', instName, iTool, iVersion, iParmsFromFile) 916 eemWriteDebug("Processing instance parameters %s done" % instName)
917 918
919 -def eemAdfiReadOptParmFile(adfiNamePrefix):
920 fname = adfiNamePrefix + "_adfi_parms.csv" 921 if not os.path.isfile(fname): 922 eemWriteDebug("No additional/updated parameters for components found") 923 return None 924 925 try: 926 import csv 927 eemWriteDebug("Read additional/updated parameters for components: %s" % fname) 928 fp = open(fname,"rb") 929 reader = csv.reader(fp) 930 fp.close() 931 parmMap = {} 932 for row in reader: 933 instMap = {} 934 iName = row[0] 935 if iName in parmMap.keys(): 936 instMap = parmMap[iName] 937 parmList = row[1:] 938 for i in range(0,len(parmList),2): 939 instMap[parmList[i]] = parmList[i+1] 940 parmMap[iName] = instMap 941 return parmMap 942 eemWriteDebug("Read additional and updated parameters done") 943 except: 944 eemWriteDebug("Can not read from ADS ADFI file: %s" % iAdfiFilename) 945 return None
946
947 -def getDrawingUnitConversionFactor(cInst):
948 unit = eemGetElNodeAttrByTagAttrValue(cInst, "Unit", 'key', 'drawing_units', 'value') 949 # TODO: add other units 950 factorMap = {'m':1,'mm':1e-3,'um':1e-6,'nm':1e-9,'pm':1e-12,'mil':2.54e-5,'inch':2.54e-2,'in':2.54e-2} 951 conversionFactor = 1 952 if unit in factorMap.keys(): 953 conversionFactor = factorMap[unit] 954 else: 955 raise Exception('Unknown unit %s' % unit) 956 return conversionFactor
957
958 -def getPinNodeListUnitInfo(iPortsDom,iAdfiInfo=None,needUnit=False):
959 pins=None 960 conversionFactor=None 961 try: 962 if(iPortsDom.nodeType==iPortsDom.DOCUMENT_NODE): 963 components = iPortsDom.getElementsByTagName('AdfiComponent') 964 for cInst in components: 965 if cInst.getAttribute('top') == 'true': 966 if iAdfiInfo==None and needUnit: 967 conversionFactor = getDrawingUnitConversionFactor(cInst) 968 pins = cInst.getElementsByTagName('PortDescription') 969 break 970 except: 971 pass # can be ports element 972 973 try: 974 if (pins==None 975 and iPortsDom.nodeType==iPortsDom.ELEMENT_NODE): 976 # we have a ports element 977 pins = iPortsDom.getElementsByTagName('PortDescription') 978 except: 979 pass 980 981 try: 982 if (pins==None 983 and len(iPortsDom) 984 and iPortsDom[0].nodeType==iPortsDom[0].ELEMENT_NODE): 985 # get a pinNodeList immediately 986 pins=iPortsDom 987 except: 988 raise Exception('Unknown port/pin object %s' % str(iPortsDom)) 989 990 if conversionFactor==None and needUnit: 991 conversionFactor = iAdfiInfo.getDrawingUnitConversionFactor() 992 993 return (pins,conversionFactor)
994
995 -class pinWriter():
996 """This class is used to write out the .pin file of the top level of an adfi file."""
997 - def __init__(self, filename):
998 self.file = open( filename, "w" ) 999 self.file.write(r'<?xml version="1.0" encoding="UTF-8"?>')
1000 1001 # TODO: write out other pin properties
1002 - def writePin(self,name,net,layer,purpose,x,y):
1003 self.file.write(""" 1004 <pin> 1005 <name>"""+name+"""</name> 1006 <net>"""+net+"""</net> 1007 <layout> 1008 <shape> 1009 <layer>"""+str(layer)+"""</layer> 1010 <purpose>"""+str(purpose)+"""</purpose> 1011 <point> 1012 <x>"""+str(x)+"""</x> 1013 <y>"""+str(y)+"""</y> 1014 </point> 1015 </shape> 1016 </layout> 1017 </pin>""")
1018
1019 - def writePinList(self,iPortsDom,iAdfiInfo=None):
1020 pins=None 1021 conversionFactor=None 1022 try: 1023 (pins, conversionFactor) = getPinNodeListUnitInfo(iPortsDom,iAdfiInfo,True) 1024 except: 1025 raise 1026 1027 self.file.write(""" 1028 <pin_list version="1.0"> 1029 <!-- note: all coordinates are in meter -->""") 1030 for iPin in pins: 1031 pinName = eemGetElNodeValByTag(iPin, 'PinName') 1032 eemWriteDebug("Process pin %s" % pinName) 1033 pinNumber = eemGetElNodeValByTag(iPin, 'PinNumber') 1034 layerName = eemGetElNodeValByTag(iPin, 'LayerName') 1035 layerNumber= eemGetElNodeValByTag(iPin, 'LayerNumber') 1036 netName = eemGetElNodeValByTag(iPin, 'NetName') 1037 if netName == None: 1038 netName = "" 1039 (xLoc,yLoc)= eemAdfiGetLocation(iPin) 1040 phi = eemAdfiGetRotation(iPin) 1041 # TODO: purpose = -1 ??? 1042 # Convert coordinates to meter 1043 self.writePin(pinName,netName,layerNumber,-1, 1044 conversionFactor*float(xLoc), 1045 conversionFactor*float(yLoc)) 1046 self.file.write('\n'+r'</pin_list>'+'\n')
1047
1048 - def close(self):
1049 self.file.close()
1050
1051 -def eemAdfiWritePinFile(fName, iDom, iAdfiInfo=None):
1052 """write out top level pins in .pin file""" 1053 writer = pinWriter(fName) 1054 writer.writePinList(iDom,iAdfiInfo) 1055 writer.close()
1056
1057 -class portWriter():
1058 - def __init__(self, filename):
1059 self.file = open( filename, "w" ) 1060 self.file.write(r'<?xml version="1.0" encoding="UTF-8"?>'+'\n')
1061
1063 self.file.write(""" <calibration_group_list> 1064 <calibration_group id="1"> 1065 <type>TML</type> 1066 <auto_split>true</auto_split> 1067 </calibration_group> 1068 </calibration_group_list> 1069 """)
1070
1071 - def writePort(self,id,name,plusPinList,minusPinList,impedanceR,impedanceI):
1072 self.file.write(" <port id=\""+str(id)+"\">\n") 1073 self.file.write(" <name>"""+name+"</name>\n") 1074 for plusPin in plusPinList: 1075 self.file.write(" <plus_pin>"+plusPin+"</plus_pin>\n") 1076 for minusPin in minusPinList: 1077 self.file.write(" <minus_pin>"+minusPin+"</minus_pin>\n") 1078 self.file.write(" <impedance>\n") 1079 self.file.write(" <real>"+str(impedanceR)+"</real>\n") 1080 self.file.write(" <imag>"+str(impedanceI)+"</imag>\n") 1081 self.file.write(" </impedance>\n") 1082 self.file.write(" <calibration_group_ref ref=\"1\" />\n") 1083 self.file.write(" </port>\n")
1084
1085 - def writePortSetup(self,iDom):
1086 self.file.write(r'<port_setup version="1.1">'+'\n') 1087 self.writeDefaultCalibrationGroupList() 1088 self.writePortList(iDom) 1089 self.file.write(r'</port_setup>'+'\n')
1090
1091 - def writePortList(self,iPortsDom):
1092 pins=None 1093 conversionFactor=None 1094 try: 1095 (pins, conversionFactor) = getPinNodeListUnitInfo(iPortsDom) 1096 except: 1097 raise 1098 1099 self.file.write(" <port_list>\n") 1100 portList = {} 1101 for iPin in pins: 1102 # TODO: clean-up unused elements 1103 pinName = eemGetElNodeValByTag(iPin, 'PinName') 1104 pinNumber = eemGetElNodeValByTag(iPin, 'PinNumber') 1105 portNumber = int(eemGetElNodeValByTag(iPin, 'PortNumber')) 1106 if portNumber == None: 1107 portNumber = pinNumber 1108 pinType = eemGetElNodeValByTag(iPin, 'PinType') 1109 if pinType == None: 1110 pinType = '+1' 1111 rePortZ = eemGetElNodeValByTag(iPin, 'RePortZ') 1112 if rePortZ == None: 1113 rePortZ = '50.0' 1114 imPortZ = eemGetElNodeValByTag(iPin, 'ImPortZ') 1115 if imPortZ == None: 1116 imPortZ = '0.0' 1117 portOffset = eemGetElNodeValByTag(iPin, 'PortOffset') 1118 if portOffset == None: 1119 portOffset = '0.0' 1120 portName = eemGetElNodeValByTag(iPin, 'PortName') 1121 eemWriteDebug("Process pin %s in port %s" % (pinName,portName)) 1122 if portName == None: 1123 portName = pinName 1124 posNeg = eemGetElNodeValByTag(iPin, 'PosNeg') 1125 if posNeg == None: 1126 posNeg = '0' 1127 diffPair = eemGetElNodeValByTag(iPin, 'DifferentialPair') 1128 # Check if port already exists and if not create it 1129 if portList.has_key(portNumber): 1130 thisPort = portList[portNumber] 1131 else: 1132 newPort = dict(name=portName,plusPinList=[],minusPinList=[],rePortZ=rePortZ,imPortZ=imPortZ) 1133 thisPort = newPort 1134 portList[portNumber]=thisPort 1135 # Add pin to plus or minus pin list 1136 if pinType == '+1': 1137 thisPort['plusPinList'].append(pinName) 1138 else: 1139 thisPort['minusPinList'].append(pinName) 1140 # Write out all ports 1141 keys = portList.keys() 1142 keys.sort() 1143 for id in keys: 1144 port = portList[id] 1145 self.writePort(id,port['name'],port['plusPinList'],port['minusPinList'],port['rePortZ'],port['imPortZ']) 1146 self.file.write(' </port_list>\n')
1147
1148 - def close(self):
1149 self.file.close()
1150
1151 -def eemAdfiWritePortFile(fName, iPorts):
1152 """write out top level ports in .prt file""" 1153 writer = portWriter(fName) 1154 writer.writePortSetup(iPorts) 1155 writer.close()
1156 1157
1158 -class bondWireWriter():
1159 - def __init__(self, filename,maskNameNbMap):
1160 self.maskNameNbMap = maskNameNbMap 1161 self.file = open( filename, "w" ) 1162 self.file.write( 1163 """# bondwire file format version 2.0 1164 1165 # uses mks units 1166 # 1167 # wire 1168 # name "<bondwire name>"; 1169 # netname "<bondwire net name>"; 1170 # resistivity <resistivity in Ohm*m> 1171 # radius <bondwire radius in m>; 1172 # points <nr of points n>, 1173 # <x1 y1 mask z1 [top|bottom]>, 1174 # <x2 y2 [(mask [z1|zn] [top|bottom] delta)|absolute] z2>, 1175 # ... 1176 # <xn yn mask zn [top|bottom]>; 1177 # end_wire 1178 # ... 1179 """)
1180
1181 - def close(self):
1182 self.file.close()
1183
1184 - def writeBondWire(self,iCmp,inst,iCmpId=None,iDrawConversionFactor=None):
1185 cmpId=iCmpId 1186 if cmpId==None: 1187 cmpId = iCmp.getAttribute('id') 1188 1189 if iDrawConversionFactor!=None: 1190 drawingConversionFactor = iDrawConversionFactor 1191 else: 1192 drawingConversionFactor = getDrawingUnitConversionFactor(iCmp) 1193 1194 bondId = inst.getAttribute('id') 1195 self.file.write('\nwire\n') 1196 # Name 1197 # TODO get entire hierarchy in name 1198 self.file.write(' name "%s_%s";\n' % (cmpId.replace('-','_'),bondId.replace('-','_'))) 1199 # Resistivity 1200 conductivityString = eemGetElNodeAttrByTagAttrValue(inst, "Parameter", 'key', 'Conductivity', 'value') 1201 condV,condUnit = conductivityString.split() 1202 # TODO: add other units 1203 # TODO: investigate case sensitivity 1204 factorMap = {'GS':1e9,'MS':1e6,'kS':1e3,'S':1,'mS':1e-3,'uS':1e-6,'nS':1e-9,'pS':1e-12} 1205 conversionFactor = 1 1206 if condUnit in factorMap.keys(): 1207 conversionFactor = factorMap[condUnit] 1208 else: 1209 raise Exception('Unknown unit %s' % condUnit) 1210 self.file.write(' resistivity %s;\n' % (1/(float(condV)*conversionFactor))) 1211 # Radius 1212 radius = eemGetElNodeAttrByTagAttrValue(inst, "Parameter", 'key', 'Radius', 'value') 1213 self.file.write(' radius %s;\n' % (float(radius)*drawingConversionFactor)) 1214 # Geometry 1215 startLocation = inst.getElementsByTagName('Location')[0] 1216 xStart = drawingConversionFactor*float(startLocation.getAttribute('x')) 1217 yStart = drawingConversionFactor*float(startLocation.getAttribute('y')) 1218 xEnd = drawingConversionFactor*float(eemGetElNodeAttrByTagAttrValue(inst, "Parameter", 'key', 'xEnd', 'value')) 1219 yEnd = drawingConversionFactor*float(eemGetElNodeAttrByTagAttrValue(inst, "Parameter", 'key', 'yEnd', 'value')) 1220 maskNameStart = eemGetElNodeAttrByTagAttrValue(inst, "Parameter", 'key', 'Layer1', 'value') 1221 maskNameEnd = eemGetElNodeAttrByTagAttrValue(inst, "Parameter", 'key', 'Layer2', 'value') 1222 if maskNameStart in self.maskNameNbMap.keys(): 1223 maskNbStart = self.maskNameNbMap[maskNameStart] 1224 else: 1225 eemWriteWarn("Mask number not found start mask for %s of bondwire %s.\nUsing \"0\" instead." % (str(maskNameStart),str(bondId))) 1226 maskNbStart = '0' 1227 if maskNameEnd in self.maskNameNbMap.keys(): 1228 maskNbEnd = self.maskNameNbMap[maskNameEnd] 1229 else: 1230 eemWriteWarn("Mask number not found end mask for %s of bondwire %s.\nUsing \"0\" instead." % (str(maskNameEnd),str(bondId))) 1231 maskNbEnd = '0' 1232 import math 1233 dX = xEnd - xStart 1234 dY = yEnd - yStart 1235 length = math.sqrt(dX * dX + dY * dY) 1236 wireAbove = (eemGetElNodeAttrByTagAttrValue(inst, "Parameter", 'key', 'RelToSubstrate', 'value') == 'ABOVE') 1237 if (wireAbove): 1238 onSide = 'top' 1239 else: 1240 onSide = 'bot' 1241 NumberOfLengthsSpecified = int(eemGetElNodeAttrByTagAttrValue(inst, "Parameter", 'key', 'NumberOfLengthsSpecified', 'value')) 1242 lList = [] 1243 zList = [] 1244 for ind in range(1,NumberOfLengthsSpecified+1): 1245 li = drawingConversionFactor*float(eemGetElNodeAttrByTagAttrValue(inst, "Parameter", 'key', 'l'+str(ind), 'value')) 1246 zi = drawingConversionFactor*float(eemGetElNodeAttrByTagAttrValue(inst, "Parameter", 'key', 'z'+str(ind), 'value')) 1247 lList.append(li) 1248 zList.append(zi) 1249 self.file.write(' points %s,\n' % (NumberOfLengthsSpecified + 2)) 1250 self.file.write(' %s %s mask %s %s,\n' % (xStart,yStart,maskNbStart,onSide)) 1251 xi = xStart 1252 yi = yStart 1253 for li,zi in zip(lList,zList): 1254 dXi = li/length * dX 1255 dYi = li/length * dY 1256 xi += dXi 1257 yi += dYi 1258 self.file.write(' %s %s mask %s %s delta %s,\n' % (xi,yi,maskNbStart,onSide,zi)) 1259 self.file.write(' %s %s mask %s %s;\n' % (xEnd,yEnd,maskNbEnd,onSide)) 1260 self.file.write('end_wire\n')
1261
1262 - def writeDummyBondWire(self,name,paramMap):
1263 self.file.write('\nwire\n') 1264 # Name 1265 self.file.write(' name "%s";\n' % name) 1266 # Resistivity 1267 self.file.write(' resistivity %s;\n' % paramMap['resistivity']) 1268 # Radius 1269 radius = float(paramMap['radius']) 1270 self.file.write(' radius %s;\n' % (radius/10)) 1271 # Geometry 1272 xStart = float(paramMap['x']) - radius/4 1273 yStart = float(paramMap['y']) - radius/4 1274 xEnd = xStart + radius/2 1275 yEnd = yStart + radius/2 1276 maskNameStart = paramMap['mask_top'] 1277 maskNameEnd = paramMap['mask_bottom'] 1278 maskNbStart = self.maskNameNbMap[maskNameStart] 1279 maskNbEnd = self.maskNameNbMap[maskNameEnd] 1280 self.file.write(' points %s,\n' % (3)) 1281 self.file.write(' %s %s mask %s %s,\n' % (xStart,yStart,maskNbStart,'bot')) 1282 self.file.write(' %s %s mask %s %s delta %s,\n' % (xStart,yStart,maskNbStart,'bot', radius)) 1283 self.file.write(' %s %s mask %s %s;\n' % (xEnd,yEnd,maskNbEnd,'top')) 1284 self.file.write('end_wire\n')
1285
1286 - def writeCmptBondwires(self, iInsts, iCmpId=None, iDrawConversionFactor=None):
1287 instances=[] 1288 if iInsts: 1289 instances=iInsts.getElementsByTagName('Instance') 1290 if instances: 1291 for inst in instances: 1292 cmpName = eemGetElNodeValByTag(inst, 'Component') 1293 if cmpName == 'SBOND': 1294 self.writeBondWire(None ,inst, iCmpId, iDrawConversionFactor)
1295
1296 - def writeSBDummyBondWires(self,iDom,useSolderBalls=False,sbMap=None):
1297 if not iDom: 1298 return 1299 if useSolderBalls: 1300 importer = solderBallImporter() 1301 sbMap = importer.getSolderBallMap(iDom,sbMap) 1302 for name,(id,comp,paramMap) in sbMap.iteritems(): 1303 eemWriteDebug("Dummy bondwire for solderball with name %s and paramMap %s" % (name,str(paramMap))) 1304 self.writeDummyBondWire(name,paramMap)
1305
1306 - def writeBondWires(self,iDom,useSolderBalls=False,sbMap=None):
1307 if not iDom: 1308 return 1309 components = iDom.getElementsByTagName('AdfiComponent') 1310 for iCmp in components: 1311 instances = iCmp.getElementsByTagName('Instance') 1312 if instances: 1313 for inst in instances: 1314 cmpName = eemGetElNodeValByTag(inst, 'Component') 1315 if cmpName == 'SBOND': 1316 self.writeBondWire(iCmp,inst) 1317 self.writeSBDummyBondWires(iDom,useSolderBalls,sbMap)
1318
1319 -def eemAdfiWriteBondwireFile(fName, iDom, maskNameNbMap,useSolderBalls=False,sbMap=None):
1320 writer = bondWireWriter(fName,maskNameNbMap) 1321 writer.writeBondWires(iDom,useSolderBalls,sbMap) 1322 writer.close()
1323
1324 -class UnitException(Exception):
1325 pass
1326
1327 -def getRLCUnitConversionFactor(unit):
1328 if len(unit) == 1: 1329 return 1 1330 # consider MF, MH and mO as milli, but MO as mega 1331 if unit == 'MO': 1332 return 1e6 1333 factorPrefix = unit.upper()[:-1] 1334 # case insensitive => confusion between Mega and milli 1335 # TODO debug possible problems with units 1336 factorMapWithCase = {'T':1e12,'G':1e9,'MEG':1e6,'k':1e3,'m':1e-3,'u':1e-6,'n':1e-9,'p':1e-12,'f':1e-15,'a':1e-18} 1337 # Extend with capitals 1338 factorMap = {} 1339 for k,v in factorMapWithCase.iteritems(): 1340 factorMap[k.upper()]=v 1341 conversionFactor = 1 1342 if factorPrefix in factorMap.keys(): 1343 conversionFactor = factorMap[factorPrefix] 1344 else: 1345 msg = 'Unknown unit %s.' % unit 1346 eemWriteDebug(msg) 1347 raise UnitException(msg) 1348 return conversionFactor
1349
1350 -def _layerNameToVariable(layerName,above,addQuotes=False):
1351 if above: 1352 varName = "mask_%s_Zmax" % layerName 1353 else: 1354 varName = "mask_%s_Zmin" % layerName 1355 if addQuotes: 1356 return '"%s"' % varName 1357 else: 1358 return varName
1359
1360 -def getResistivityFromConductivityString(conductivityString):
1361 #resistivity = getResistivityFromConductivityString(conductivityString) 1362 condV,condUnit = conductivityString.split() 1363 # TODO: add other units 1364 # TODO: investigate case sensitivity 1365 factorMap = {'GS':1e9,'MS':1e6,'kS':1e3,'S':1,'mS':1e-3,'uS':1e-6,'nS':1e-9,'pS':1e-12,'SIEMENS':1} 1366 conversionFactor = 1 1367 if condUnit in factorMap.keys(): 1368 conversionFactor = factorMap[condUnit] 1369 else: 1370 if condUnit[-2:].upper()=='/M': 1371 condUnit = condUnit[:-2] 1372 if condUnit in factorMap.keys(): 1373 conversionFactor = factorMap[condUnit] 1374 elif condUnit.upper() in factorMap.keys(): 1375 conversionFactor = factorMap[condUnit.upper()] 1376 else: 1377 raise Exception('Unknown unit %s' % condUnit) 1378 resistivity = 1/(float(condV)*conversionFactor) 1379 return resistivity
1380
1381 -class bondwireImporter():
1382 - def __init__(self):
1383 self.bwMaterials={} # Map from resistivity to material
1384 1385 # TODO: replace this function with the official function in EMPro
1386 - def _makeJedecDefinition(self,alpha="60 deg", beta="15 deg", h1="30 pct", radius="0.5 mil", numFaces=6, name=None):
1387 import empro 1388 h1IsProportional = "pct" in str(h1) # this is tricky. what if we have pct as parameter name for an absolute length? 1389 bonddef = empro.geometry.BondwireDefinition(name or "", radius, numFaces) 1390 v = empro.geometry.BondwireVertex(alpha, h1) 1391 v.tUnitClass = empro.units.ANGLE 1392 v.zUnitClass = h1IsProportional and empro.units.SCALAR or empro.units.LENGTH 1393 bonddef.append(v) 1394 v = empro.geometry.BondwireVertex("12.5 pct", "0") 1395 v.tReference = v.zReference = "Previous" 1396 v.tUnitClass = v.zUnitClass = empro.units.SCALAR 1397 bonddef.append(v) 1398 v = empro.geometry.BondwireVertex("50 pct", beta) 1399 v.tReference = v.zReference = "End" 1400 v.tUnitClass = empro.units.SCALAR 1401 v.zUnitClass = empro.units.ANGLE 1402 bonddef.append(v) 1403 return bonddef
1404
1405 - def createOrGetBondwireProfileDefinition(self,iCmp,inst):
1406 profileName = eemGetElNodeAttrByTagAttrValue(inst, "Parameter", 'key', "ProfileName", 'value') 1407 height = float(eemGetElNodeAttrByTagAttrValue(inst, "Parameter", 'key', "JedecHeight", 'value')) 1408 alpha = float(eemGetElNodeAttrByTagAttrValue(inst, "Parameter", 'key', "JedecAlpha" , 'value')) 1409 beta = float(eemGetElNodeAttrByTagAttrValue(inst, "Parameter", 'key', "JedecBeta" , 'value')) 1410 radius = float(eemGetElNodeAttrByTagAttrValue(inst, "Parameter", 'key', 'Radius', 'value')) 1411 # Radius 1412 drawingConversionFactor = getDrawingUnitConversionFactor(iCmp) 1413 radius = radius*drawingConversionFactor 1414 height = height*drawingConversionFactor 1415 # Check if a component definition can be reused 1416 import empro 1417 bwDefs = empro.activeProject.bondwireDefinitions() 1418 for i in range(len(bwDefs)): 1419 bwDef = bwDefs[i] 1420 if bwDef.name != profileName: 1421 continue 1422 eemWriteDebug(" This bondwire matches definition with name '%s'" % profileName) 1423 return bwDef 1424 # If not create a new one and add it to the current project 1425 eemWriteDebug(" Creating new bondwire definition '%s'" % profileName) 1426 created_bonddef = self._makeJedecDefinition(alpha = str(alpha)+" deg",beta = str(beta)+" deg", radius=radius,h1 = height,name=profileName) 1427 empro.activeProject.bondwireDefinitions().append(created_bonddef) 1428 # it's important NOT to use the bonddef you created, as a COPY is placed in bondwireDefinitions. 1429 # This is something to be fixed in EMPro 1430 bwDefs = empro.activeProject.bondwireDefinitions() 1431 bonddef_to_use = bwDefs[len(bwDefs)-1] 1432 return bonddef_to_use
1433
1434 - def createBondwire(self,iCmp,inst):
1435 cmpId = iCmp.getAttribute('id') 1436 bondId = inst.getAttribute('id') 1437 # Name 1438 name = "%s_%s" % (cmpId.replace('-','_'),bondId.replace('-','_')) 1439 # Resistivity 1440 conductivityString = eemGetElNodeAttrByTagAttrValue(inst, "Parameter", 'key', 'Conductivity', 'value') 1441 resistivity = getResistivityFromConductivityString(conductivityString) 1442 # Geometry 1443 drawingConversionFactor = getDrawingUnitConversionFactor(iCmp) 1444 startLocation = inst.getElementsByTagName('Location')[0] 1445 xStart = drawingConversionFactor*float(startLocation.getAttribute('x')) 1446 yStart = drawingConversionFactor*float(startLocation.getAttribute('y')) 1447 xEnd = drawingConversionFactor*float(eemGetElNodeAttrByTagAttrValue(inst, "Parameter", 'key', 'xEnd', 'value')) 1448 yEnd = drawingConversionFactor*float(eemGetElNodeAttrByTagAttrValue(inst, "Parameter", 'key', 'yEnd', 'value')) 1449 maskNameStart = eemGetElNodeAttrByTagAttrValue(inst, "Parameter", 'key', 'Layer1', 'value') 1450 maskNameEnd = eemGetElNodeAttrByTagAttrValue(inst, "Parameter", 'key', 'Layer2', 'value') 1451 wireAbove = (eemGetElNodeAttrByTagAttrValue(inst, "Parameter", 'key', 'RelToSubstrate', 'value') == 'ABOVE') 1452 ######## 1453 eemWriteDebug("Found bondwire with name %s" % (name)) 1454 bondwireDef = self.createOrGetBondwireProfileDefinition(iCmp,inst) 1455 zStart = _layerNameToVariable(maskNameStart,wireAbove,False) 1456 zEnd = _layerNameToVariable(maskNameEnd,wireAbove,False) 1457 import empro 1458 V=empro.geometry.Vector3d 1459 beginP = V(xStart,yStart,zStart) 1460 endP = V(xEnd,yEnd,zEnd) 1461 bw = empro.geometry.Bondwire(beginP,endP,None) 1462 bw.definition = bondwireDef 1463 model = empro.geometry.Model() 1464 model.name = name 1465 model.recipe.append(bw) 1466 if not wireAbove: 1467 # rotate bondwires over 180 degrees 1468 import math 1469 model.coordinateSystem.rotate(math.pi,0,0) 1470 # Add attributes to model 1471 parameters = getInstanceParms(inst,toUpper=False) 1472 if parameters: 1473 for key,value in parameters.iteritems(): 1474 try: 1475 model.addAttribute(key,str(value)) 1476 except TypeError: 1477 model.addAttribute(key,"dummy_value") 1478 ## Assign material to bondwire 1479 #if (self.bwMaterials.has_key(resistivity)): 1480 # material = self.bwMaterials[resistivity] 1481 #else: 1482 # import empro.toolkit.ads_import 1483 # session=empro.toolkit.ads_import.Import_session(units="um", wall_boundary="Radiation") 1484 # material=session.create_material(name="bondwire", color=(0,0,255,255), resistivity=resistivity) 1485 # empro.activeProject.materials().append(material) 1486 # self.bwMaterials[resistivity]=material 1487 #empro.toolkit.applyMaterial(model,material) 1488 return model
1489
1490 - def getBondwireMap(self,iDom,bwComps=None):
1491 components = iDom.getElementsByTagName('AdfiComponent') 1492 if bwComps == None: 1493 bwComps = {} 1494 import empro 1495 assembly=empro.geometry.Assembly() 1496 assembly.name = "Bondwires" 1497 for iCmp in components: 1498 instances = iCmp.getElementsByTagName('Instance') 1499 if instances: 1500 for inst in instances: 1501 cmpName = eemGetElNodeValByTag(inst, 'Component') 1502 if cmpName == 'SBOND': 1503 comp = self.createBondwire(iCmp,inst) 1504 if (comp): 1505 bwComps[comp.name]=comp 1506 return bwComps
1507
1508 - def importBondwires(self,iDom,topAssembly):
1509 bwComps = self.getBondwireMap(iDom) 1510 import empro 1511 assembly=empro.geometry.Assembly() 1512 assembly.name = "Bondwires" 1513 for name,comp in bwComps.iteritems(): 1514 assembly.append(comp) 1515 if len(assembly) > 0: 1516 if topAssembly == None: 1517 empro.activeProject.geometry().append(assembly) 1518 else: 1519 topAssembly.append(assembly)
1520
1521 -def getComponentParms(iCmp,toUpper=True):
1522 return getParms(iCmp,toUpper,"ComponentParms")
1523
1524 -def getParms(iCmp,toUpper=True,groupName="ComponentParms"):
1525 keyValuePairs = {} 1526 if (iCmp.localName == groupName): 1527 cmpParms=iCmp 1528 else: 1529 cmpParms = iCmp.getElementsByTagName(groupName) 1530 if cmpParms and len(cmpParms)==1: 1531 cmpParms = cmpParms[0] 1532 else: 1533 return None 1534 parameterNodes = cmpParms.getElementsByTagName('Parameter') 1535 for pNodes in parameterNodes: 1536 key = pNodes.getAttribute('key') 1537 value = pNodes.getAttribute('value') 1538 if toUpper: 1539 key = key.upper() 1540 value = value.upper() 1541 keyValuePairs[key] = value 1542 eemWriteDebug(" Parameter %s : %s" % (key,value)) 1543 return keyValuePairs
1544
1545 -def getInstanceParms(iCmp,toUpper=True):
1546 return getParms(iCmp,toUpper,"InstanceParms") 1547 InstanceParms 1548 InstanceParms
1549
1550 -class componentImporter():
1551 - def __init__(self):
1552 pass
1553
1554 - def valueToRLC(self,value,partName=""):
1555 R = 0 1556 L = 0 1557 C = 0 1558 if value.upper()[-3:]=='OHM': 1559 value = value[:-2] 1560 if value.upper()[-3:]=='MHO': 1561 value = value[:-3]+'S' 1562 try: 1563 #valueWithoutUnit = float(re.sub('[A-Z]+','',value.upper())) 1564 valueWithoutUnit = float(re.sub('[^0-9.]+','',value)) 1565 except ValueError: 1566 return (R,L,C) 1567 unit = re.sub('[0-9.]+','',value) 1568 mainUnit = unit.upper()[-1:] 1569 if mainUnit in ['O','H','F','S']: 1570 if mainUnit == 'O': 1571 R = valueWithoutUnit * getRLCUnitConversionFactor(unit) 1572 elif mainUnit == 'H': 1573 L = valueWithoutUnit * getRLCUnitConversionFactor(unit) 1574 elif mainUnit == 'F': 1575 C = valueWithoutUnit * getRLCUnitConversionFactor(unit) 1576 elif mainUnit == 'S': 1577 R = 1/(valueWithoutUnit * getRLCUnitConversionFactor(unit)) 1578 else: 1579 if partName in ['R','L','C']: 1580 if partName == 'R': 1581 unit += 'O' 1582 R = valueWithoutUnit * getRLCUnitConversionFactor(unit) 1583 elif partName == 'L': 1584 unit += 'H' 1585 L = valueWithoutUnit * getRLCUnitConversionFactor(unit) 1586 elif partName == 'C': 1587 unit += 'F' 1588 C = valueWithoutUnit * getRLCUnitConversionFactor(unit) 1589 else: 1590 eemWriteDebug('Found no unit in value %s. Taking Ohm as default' % value) 1591 unit += 'O' 1592 R = valueWithoutUnit * getRLCUnitConversionFactor(unit) 1593 return (R,L,C)
1594
1595 - def createOrGetComponentDefinition(self,value,partName=""):
1596 if not value: 1597 return None 1598 # Check if a component definition can be reused 1599 try: 1600 (R,L,C) = self.valueToRLC(value,partName) 1601 except UnitException: 1602 return None 1603 if (R,L,C) == (0,0,0): 1604 return None 1605 eemWriteDebug(" Component with (R,L,C) = (%s,%s,%s)" % (R,L,C)) 1606 import empro 1607 cdefs = empro.activeProject.circuitComponentDefinitions() 1608 for i in range(len(cdefs)): 1609 cmp = cdefs[i] 1610 if (cmp.impedance.resistance != R or cmp.impedance.inductance != L or cmp.impedance.capacitance != C) : 1611 continue 1612 if cmp.impedance.elementArrangement != "Series": 1613 continue 1614 eemWriteDebug(" This component matches definition with name '%s'" % cmp.name) 1615 return cmp 1616 # If not create a new one and add it to the current project 1617 name = "%s Passive Load"%value 1618 newCmp = empro.components.PassiveLoad(name) 1619 newCmp.impedance.resistance = R 1620 newCmp.impedance.inductance = L 1621 newCmp.impedance.capacitance = C 1622 newCmp.impedance.elementArrangement = "Series" 1623 newCmp.name = "%s Passive Load"%value 1624 empro.activeProject.circuitComponentDefinitions().append(newCmp) 1625 cdefs = empro.activeProject.circuitComponentDefinitions() 1626 newCmp = cdefs[len(cdefs)-1] 1627 return newCmp
1628 1629
1630 - def getPins(self,iCmp):
1631 # get number,x,y,layer 1632 ports = iCmp.getElementsByTagName('PortDescription') 1633 cmpName = (eemGetElNodeValByTag(iCmp, 'Name')).strip() 1634 if len(ports) > 2: 1635 eemWriteWarn(" Components with more than 2 pins not supported! Only using pin 1 and 2 of %s." % cmpName) 1636 if len(ports) == 1: 1637 eemWriteWarn(" Components with only 1 pin not supported!") 1638 tailDef = None 1639 headDef = None 1640 for p in ports: 1641 pinName = eemGetElNodeValByTag(p, 'PinName') 1642 pinNumber = int(eemGetElNodeValByTag(p, 'PinNumber')) 1643 pinLayerName = eemGetElNodeValByTag(p, 'LayerName') 1644 netName = eemGetElNodeValByTag(p, 'NetName') 1645 if netName == None: 1646 netName = '' 1647 (xLoc,yLoc)= eemAdfiGetLocation(p) 1648 eemWriteDebug(" Port %s (nb %s) on %s at (%s,%s) on net %s" % (pinName,pinNumber,pinLayerName,xLoc,yLoc,netName)) 1649 pin = {} 1650 pin['x' ] = float(xLoc) 1651 pin['y' ] = float(yLoc) 1652 pin['zLayer' ] = pinLayerName 1653 pin['name' ] = pinName 1654 pin['number' ] = pinNumber 1655 pin['netName'] = netName 1656 if pinNumber == 1: 1657 tailDef = pin 1658 elif pinNumber == 2: 1659 headDef = pin 1660 else: 1661 if tailDef == None: 1662 tailDef = pin 1663 elif headDef == None: 1664 headDef = pin 1665 if not headDef or not tailDef: 1666 includeInvalidComponents = False 1667 if includeInvalidComponents: 1668 if headDef or tailDef: 1669 headDef = tailDef or headDef 1670 tailDef = tailDef or headDef 1671 eemWriteWarn(" Colocating pins of %s since only one found in .adfi file!"%cmpName) 1672 return (tailDef,headDef)
1673
1674 - def createComponent(self,iCmp):
1675 cmpName = eemGetElNodeValByTag(iCmp, 'Name') 1676 if iCmp.hasAttribute('id'): 1677 id = iCmp.getAttribute('id') 1678 else: 1679 id = 'Unknown component' 1680 eemWriteDebug("Found component with name %s and id %s" % (cmpName,id)) 1681 parameters = getComponentParms(iCmp) 1682 above = True 1683 compDef = None 1684 if (parameters and parameters.has_key('VALUE')): 1685 CmpValue = parameters['VALUE'] 1686 try: 1687 compDef = self.createOrGetComponentDefinition(CmpValue,partName=parameters['PART_NAME']) 1688 except KeyError: 1689 compDef = self.createOrGetComponentDefinition(CmpValue) 1690 if (parameters and parameters.has_key('RELATIVE_TO_SUBSTRATE')): 1691 relToSub = parameters['RELATIVE_TO_SUBSTRATE'] 1692 if relToSub.upper() == 'BELOW': 1693 above = False 1694 conversionFactor = getDrawingUnitConversionFactor(iCmp) 1695 tailDef,headDef = self.getPins(iCmp) 1696 if not tailDef or not headDef: 1697 eemWriteWarn(" Component %s not imported due to incorrect or unsupported pin setup!"%cmpName) 1698 return None 1699 # Create new component 1700 import empro 1701 newCmp=empro.components.CircuitComponent() 1702 newCmp.name= "%s %s" % (cmpName,id) 1703 newCmp.definition=compDef 1704 newCmp.port = False 1705 newCmp.notes = "Component imported from .adfi file.\nParameter values: \n%s\nDrawing unit conversion factor %s" % (str(parameters),conversionFactor) 1706 V=empro.geometry.Vector3d 1707 if headDef: 1708 newCmp.head=V(conversionFactor*headDef['x'],conversionFactor*headDef['y'],_layerNameToVariable(headDef['zLayer'],above,False)) 1709 if tailDef: 1710 newCmp.tail=V(conversionFactor*tailDef['x'],conversionFactor*tailDef['y'],_layerNameToVariable(tailDef['zLayer'],above,False)) 1711 return newCmp
1712 1713
1714 - def importComponents(self,iDom):
1715 components = iDom.getElementsByTagName('AdfiComponent') 1716 comps = [] 1717 for iCmp in components: 1718 cmpType = eemGetElNodeValByTag(iCmp, 'Type').strip() 1719 if cmpType.upper() == 'COMPONENT': 1720 comp = self.createComponent(iCmp) 1721 if comp: 1722 comps.append(comp) 1723 import empro 1724 empro.activeProject.circuitComponents().appendList(comps)
1725 1726
1727 -class solderBallImporter():
1728 - def __init__(self):
1729 self.sbMaterials={} # Map from resistivity to material 1730 self.pkgLayer = "" 1731 self.compType = "flipchip"
1732
1733 - def findPorts(self,iCmp):
1734 conversionFactor = getDrawingUnitConversionFactor(iCmp) 1735 try: 1736 if self.compType == "flipchip": 1737 pinLayer = self.parameters['ICPKG_PIN_LAYER'] 1738 else: 1739 pinLayer = self.parameters['PKG_PIN_LAYER_ATPKG'] 1740 pins = iCmp.getElementsByTagName('PortDescription') 1741 sbLocs = [] 1742 for pin in pins: 1743 layerName = eemGetElNodeValByTag(pin, 'LayerName') 1744 if layerName != pinLayer: 1745 if self.pkgLayer != layerName: 1746 eemWriteDebug("Found package layer %s" % (layerName)) 1747 self.pkgLayer = layerName 1748 continue 1749 pinName = eemGetElNodeValByTag(pin, 'PinName') 1750 (x,y) = eemAdfiGetLocation(pin) 1751 x = float(x) * conversionFactor 1752 y = float(y) * conversionFactor 1753 eemWriteDebug("Found ball on location %s,%s" % (x,y)) 1754 sbLocs.append((x,y,pinName)) 1755 return sbLocs 1756 except: 1757 return []
1758
1759 - def getSolderBallMap(self,iDom,sbComps=None):
1760 if sbComps == None: 1761 sbComps = {} 1762 components = iDom.getElementsByTagName('AdfiComponent') 1763 import empro 1764 for iCmp in components: 1765 self.parameters = getComponentParms(iCmp) 1766 if (self.parameters): 1767 if self.parameters.has_key('ICPKG_TYPE') and self.parameters['ICPKG_TYPE'] == 'DIE_FLIPCHIP': 1768 self.compType = "flipchip" 1769 elif self.parameters.has_key('PKG_TYPE') and self.parameters['PKG_TYPE'] == 'BGA': 1770 self.compType = "bga" 1771 else: 1772 continue 1773 else: 1774 continue 1775 eemWriteDebug("Found component with solder balls.") 1776 id = iCmp.getAttribute('id') 1777 if self.compType == "flipchip": 1778 h = self.parameters["ICPKG_BUMP_HEIGHT"].lower() 1779 widthMax = self.parameters["ICPKG_BUMP_DIAMETER_MAX"].lower() 1780 widthFaceNear = self.parameters["ICPKG_BUMP_DIAMETER_ATDIE"].lower() 1781 widthFaceFar = self.parameters["ICPKG_BUMP_DIAMETER_ATPKG"].lower() 1782 bumpLayer = self.parameters['ICPKG_BUMP_LAYER'] 1783 pinLayer = self.parameters['ICPKG_PIN_LAYER'] 1784 relToSub = self.parameters['RELATIVE_TO_SUBSTRATE'] 1785 conductivityString = self.parameters["ICPKG_BUMP_CONDUCTIVITY"] 1786 else: 1787 h = self.parameters["PKG_BALL_HEIGHT"].lower() 1788 try: 1789 widthMax = self.parameters["PKG_BALL_DIAMETER"].lower() 1790 except: 1791 widthMax = self.parameters["PKG_BALL_DIAMETER_MAX"].lower() 1792 widthFaceNear = self.parameters["PKG_BALL_DIAMETER_ATPKG"].lower() 1793 widthFaceFar = self.parameters["PKG_BALL_DIAMETER_ATBRD"].lower() 1794 bumpLayer = self.parameters['PKG_BALL_LAYER'] 1795 pinLayer = self.parameters['PKG_PIN_LAYER_ATPKG'] 1796 #relToSub = self.parameters['RELATIVE_TO_SUBSTRATE'] 1797 relToSub = 'ABOVE' # TODO check if this is always true 1798 # Dummy value that should never be used since the material from the 'PKG_BALL_LAYER' will be taken 1799 conductivityString = "6.897e+006 Siemens/m" 1800 widthFace = "((%s)+(%s))/2.0" % (widthFaceNear,widthFaceFar) 1801 # e.g. "6.897e+006 Siemens/m" 1802 resistivity = getResistivityFromConductivityString(conductivityString) 1803 # radius in m for dummy bondwire 1804 import re 1805 value = widthFaceNear 1806 valueWithoutUnit = float(re.sub('[A-Z]+','',value.upper())) 1807 unit = re.sub('[0-9. ]+','',value) 1808 radius = valueWithoutUnit * getRLCUnitConversionFactor(unit) 1809 above = True 1810 if relToSub.upper() == 'BELOW': 1811 above = False 1812 divisions = 3 1813 import math 1814 arcRes = "45 deg" # 45/180.0*math.pi 1815 portList = self.findPorts(iCmp) 1816 V=empro.geometry.Vector3d 1817 z = _layerNameToVariable(bumpLayer,above,addQuotes=False) 1818 if above: 1819 z = "(%s) - (%s)" % (z,h) 1820 eemWriteDebug ("z dim = %s" %(z)) 1821 session=empro.toolkit.ads_import.Import_session(units="um", wall_boundary="Radiation") 1822 arcResParName = "solderBall_%s_arcRes"%id 1823 divisionsParName = "solderBall_%s_divisions"%id 1824 session.create_parameter(divisionsParName,str(divisions),"Nb of divisions of solderBalls of %s"%id,True) 1825 session.create_parameter(arcResParName,str(arcRes),"Arc resolution of solderBalls of %s"%id,True) 1826 sb = empro.geometry.SolderBall(h,widthFace,widthMax,divisionsParName,arcResParName) 1827 for (x,y,name) in portList: 1828 eemWriteDebug ("Creating ball with h=%s, wFace=%s, wMax=%s" %(h,widthFace,widthMax)) 1829 model = empro.geometry.Model() 1830 # Add attributes to model 1831 for key,value in self.parameters.iteritems(): 1832 try: 1833 model.addAttribute(key,str(value)) 1834 except TypeError: 1835 model.addAttribute(key,"dummy_value") 1836 model.name = id+"_"+name 1837 model.recipe.append(sb.clone()) 1838 anchorPoint = empro.geometry.CoordinateSystemPositionExpression(V(x,y,z)) 1839 eemWriteDebug ("anchorPoint z %s" %( anchorPoint.position)) 1840 model.coordinateSystem.anchorPoint = anchorPoint 1841 paramMap = {} 1842 paramMap['comp_id'] = id 1843 paramMap['radius'] = radius 1844 paramMap['resistivity'] = resistivity 1845 paramMap['x'] = x 1846 paramMap['y'] = y 1847 paramMap['above'] = above 1848 paramMap['mask_top'] = pinLayer 1849 paramMap['mask_bottom'] = self.pkgLayer 1850 paramMap['material_name'] = bumpLayer 1851 sbComps[model.name]=(id,model,paramMap) 1852 return sbComps
1853
1854 - def importSolderBalls(self,iDom,topAssembly):
1855 sbMap = self.getSolderBallMap(iDom) 1856 import empro 1857 assembly=empro.geometry.Assembly() 1858 assembly.name = "SolderBalls" 1859 assemblyMap = {} 1860 for name,(id,comp,paramMap) in sbMap.iteritems(): 1861 if assemblyMap.has_key(id): 1862 assemblyMap[id].append(comp) 1863 else: 1864 newAssembly = empro.geometry.Assembly() 1865 assemblyMap[id] = newAssembly 1866 newAssembly.append(comp) 1867 newAssembly.name = id + "_solderBalls" 1868 assembly.append(newAssembly) 1869 if len(assembly) > 0: 1870 if topAssembly == None: 1871 empro.activeProject.geometry().append(assembly) 1872 else: 1873 topAssembly.append(assembly) 1874 return
1875
1876 -def eemAdfiImportComponents(iAdfiFileName,useJedecBondwires=False,useSolderBalls=False,topAssembly=None):
1877 eemWriteDebug("Importing components") 1878 try: 1879 iDom = eemAdfiReadFile(iAdfiFileName) 1880 except: 1881 raise 1882 importer = componentImporter() 1883 importer.importComponents(iDom) 1884 if useJedecBondwires: 1885 importer = bondwireImporter() 1886 importer.importBondwires(iDom,topAssembly) 1887 if useSolderBalls: 1888 importer = solderBallImporter() 1889 importer.importSolderBalls(iDom,topAssembly)
1890 1891 1892 1893 ########################################################## 1894 # Export the ltd files and do the slm conversion 1895 # 1896 # 1897
1898 -class AdfiLtds:
1899 - def __init__(self,fPrefix=None):
1900 self.fPrefix = fPrefix 1901 self.ltdMap = {} 1902 self.ltdRevMap = {} 1903 self.ltds = {} 1904 self.instMergeMap = {'main':{'idx':-1}, 1905 'top':{'idx':-1}, 1906 'bottom':{'idx':-1}} 1907 self.top = None 1908 self.topInstancesMap = {} 1909 self.topSlmData = None 1910 self.topSlmDataFileName = None 1911 self.topLtdData = None 1912 self.topSlmFile = None 1913 self.topLtdFile = None 1914 self.topSubName = None 1915 self.topTypeLtdOrSlm = None
1916
1917 - def assembleLtdSlmMaps(self):
1918 eemWriteDebug("Process layer stack informations") 1919 1920 self.__minimizeLtds() 1921 try: 1922 self.__writeTopSlmFile() 1923 except: 1924 eemWriteError("Problem writing top slm technology file output: need to exit") 1925 raise 1926 try: 1927 self.__writeLtdFiles() 1928 except: 1929 eemWriteError("Problem with ltd technology file output: need to exit") 1930 raise 1931 try: 1932 if self.__mergeLtdFiles()!=0: 1933 raise ValueError 1934 except: 1935 eemWriteError("Problem with ltd technology file merge: need to exit") 1936 raise 1937 try: 1938 self.__convertLtdToSlm() 1939 except: 1940 eemWriteError("Problem with ltd to slm file conversion") 1941 raise 1942 eemWriteDebug("Process layer stack informations done")
1943 1944
1945 - def topName(self,topName=None):
1946 if topName!=None: 1947 self.top = topName 1948 return self.top
1949
1950 - def addLtdSlmMap(self,iDocNode,cmpName=None,top=None):
1951 eemWriteDebug("Add component with layer stack information") 1952 1953 subName = eemGetElNodeValByTag(iDocNode, 'SubstrateName') 1954 if subName == None: 1955 subName=cmpName 1956 1957 subData = iDocNode.getElementsByTagName('SubstrateData') 1958 if (subData): 1959 ltdOrSlm = getInnerText(subData[0]) 1960 typeLtdOrSlm = subData[0].getAttribute('substrateDataType') 1961 if typeLtdOrSlm=='ltd': 1962 ltd = ltdOrSlm 1963 v=None 1964 if ltd in self.ltdMap.keys(): 1965 v = self.ltdMap[ltd] 1966 else: 1967 v = len(self.ltdMap) 1968 self.ltds[v]=ltd 1969 self.ltdMap[ltd]=v 1970 self.ltdRevMap[subName]=v 1971 self.ltdRevMap[cmpName]=v 1972 if (top): 1973 eemWriteDebug("Top components %s with layer stack information identified %s" % (self.top,str(typeLtdOrSlm))) 1974 self.topTypeLtdOrSlm=typeLtdOrSlm 1975 self.topSubName=subName 1976 if typeLtdOrSlm=='ltd': 1977 self.topLtdData=ltdOrSlm 1978 elif typeLtdOrSlm=='slm': 1979 self.topSlmData=ltdOrSlm 1980 elif typeLtdOrSlm=='ltdFile': 1981 self.topLtdFile==ltdOrSlm 1982 elif typeLtdOrSlm=='slmFile': 1983 self.topSlmFile==ltdOrSlm 1984 eemWriteDebug("Component with layer stack information identified")
1985
1986 - def addSubstrateInstanceMap(self, iDocNode):
1987 eemWriteDebug("Add component instances with layer stack information") 1988 instances = iDocNode.getElementsByTagName('Instance') 1989 for inst in instances: 1990 instName = inst.getAttribute('id') 1991 side = 'main' 1992 layer = None 1993 instMap= {} 1994 direct = None 1995 instMap['cmpName']=(eemGetElNodeValByTag(inst, 'Component')).strip() 1996 subMerge = inst.getElementsByTagName('MergeAtInterface') 1997 if subMerge: 1998 direct = subMerge[0].getAttribute('mergeDirection') 1999 layer = (getInnerText(subMerge[0])).strip() 2000 if direct == 'up': 2001 side = 'top' 2002 elif direct == 'down': 2003 side = 'bottom' 2004 instMap['direct'] = direct 2005 instMap['side'] = side 2006 instMap['layer'] = layer 2007 self.topInstancesMap[instName] = instMap 2008 2009 eemWriteDebug("Component instances with layer stack information identified")
2010
2011 - def __minimizeLtds(self):
2012 eemWriteDebug("Find duplicate layer stacks") 2013 instances = self.topInstancesMap 2014 2015 if self.topLtdData!=None: 2016 cmap=self.instMergeMap['main'] 2017 cmap['idx'] = self.ltdRevMap[self.top] 2018 cmap['instNames'] = [self.top] 2019 cmap['layer'] = None 2020 self.instMergeMap['main']=cmap 2021 2022 for instName,instMap in instances.iteritems(): 2023 cmpName = instMap['cmpName'] 2024 if not(instName in self.ltdRevMap.keys() 2025 or cmpName in self.ltdRevMap.keys()): 2026 continue 2027 2028 2029 # instance with substrate associated with it 2030 side = instMap['side'] 2031 layer = instMap['layer'] 2032 cmap = self.instMergeMap[side] 2033 if cmap['idx']<0: 2034 cmap['idx'] = self.ltdRevMap[instName] 2035 aList = [] 2036 aList.append(instName) 2037 cmap['instNames'] = aList 2038 if layer: 2039 cmap['layer'] = layer 2040 else: 2041 if ((cmap['idx'] != self.ltdRevMap[instName]) 2042 or (cmap['idx'] != self.ltdRevMap[cmpName]) 2043 or (layer != None 2044 and 'layer' in cmap.keys() 2045 and cmap['layer'] != layer)): 2046 eemWriteWarn("Found different %s substrate definitions: keep first." % side) 2047 aList = cmap['instNames'] 2048 aList.append(instName) 2049 cmap['instNames'] = aList 2050 2051 self.instMergeMap[side] = cmap 2052 2053 2054 idxMap = {} 2055 instFound = [] 2056 for wLtd in self.instMergeMap.keys(): 2057 aList=[] 2058 cmap = self.instMergeMap[wLtd] 2059 idx = cmap['idx'] 2060 if idx >= 0: 2061 idxMap[idx] = wLtd 2062 aList = cmap['instNames'] 2063 instFound.extend(aList) 2064 2065 for iKey in self.ltdRevMap.keys(): 2066 if iKey in instFound: 2067 continue 2068 ltdIdx = self.ltdRevMap[iKey] 2069 a = [] 2070 if ltdIdx not in idxMap.keys(): 2071 cmap = {'idx':ltdIdx} 2072 a.append(iKey) 2073 cmap['instNames'] = a 2074 self.instMergeMap[iKey] = cmap 2075 idxMap[ltdIdx] = iKey 2076 else: 2077 cmap = self.instMergeMap[idxMap[ltdIdx]] 2078 a = cmap['instNames'] 2079 a.append(iKey) 2080 cmap['instNames']= a 2081 self.instMergeMap[idxMap[ltdIdx]] = cmap 2082 eemWriteDebug("Duplicates in layer stacks identified")
2083
2084 - def __writeLtdFiles(self):
2085 eemWriteDebug("Write the found layer stacks") 2086 fPrefix=self.fPrefix 2087 for ltdName,ltdMap in self.instMergeMap.iteritems(): 2088 if ltdMap['idx']<0: 2089 continue 2090 fName = fPrefix + "_" + str(ltdName) + ".ltd" 2091 ltdMap['ltdFile'] = fName 2092 fp = open(fName, 'w') 2093 fp.write(self.ltds[ltdMap['idx']]) 2094 fp.close() 2095 self.instMergeMap[ltdName]=ltdMap 2096 eemWriteDebug("Writing layer stacks done")
2097
2098 - def __writeTopSlmFile(self):
2099 fPrefix=self.fPrefix 2100 if self.topSlmData!=None: 2101 eemWriteDebug("Write top slm file") 2102 fName = fPrefix + "_" + self.topSubName + ".slm" 2103 self.topSlmDataFileName=fName 2104 fp = open(fName, 'w') 2105 fp.write(self.topSlmData) 2106 fp.close()
2107
2108 - def __mergeLtdFiles(self):
2109 topComponent=self.top 2110 fPrefix=self.fPrefix 2111 eemWriteDebug("Start merge with %s for %s" % (fPrefix,topComponent)) 2112 bottom = self.instMergeMap['bottom'] 2113 main = self.instMergeMap['main'] 2114 top = self.instMergeMap['top'] 2115 r = 0 2116 fIn1 = '' 2117 fIn2 = '' 2118 fOut = '' 2119 insts=[] 2120 insts.append(topComponent) 2121 verOk = eemIsValidSubedVersion() 2122 if (main['idx']<0 2123 or (bottom['idx']<0 and top['idx']<0) 2124 or not verOk): 2125 eemWriteDebug("No merge needed or can not merge: use main substrate") 2126 fOut = main['ltdFile'] 2127 elif bottom['idx']>0 and top['idx']<0: 2128 fIn1 = bottom['ltdFile'] 2129 fIn2 = main['ltdFile'] 2130 fOut = fPrefix + '_bottom_main.ltd' 2131 r=eemMergeLtdFile(fIn1, fIn2, fOut) 2132 elif bottom['idx']<0 and top['idx']>0: 2133 fIn1 = main['ltdFile'] 2134 fIn2 = top['ltdFile'] 2135 fOut = fPrefix + '_main_top.ltd' 2136 r=eemMergeLtdFile(fIn1, fIn2, fOut) 2137 else: 2138 fIn1 = bottom['ltdFile'] 2139 fIn2 = main['ltdFile'] 2140 fOut = fPrefix + '_bottom_main.ltd' 2141 r=eemMergeLtdFile(fIn1, fIn2, fOut) 2142 if r==0: 2143 fIn1 = fOut 2144 fIn2 = top['ltdFile'] 2145 fOut = fPrefix + '_bottom_main_top.ltd' 2146 r=eemMergeLtdFile(fIn1, fIn2, fOut) 2147 merge = {} 2148 merge['idx']=len(self.ltds) 2149 if r == 0: 2150 merge['ltdFile']=fOut 2151 else: 2152 merge['ltdFile']=main['ltdFile'] 2153 merge['instNames']=insts 2154 self.instMergeMap['merge'] = merge 2155 eemWriteDebug("Merge of layerstacks %s for %s done" % (fPrefix,topComponent)) 2156 return r
2157
2158 - def __convertLtdToSlm(self):
2159 eemWriteDebug("Convert ltd to slm and lay files") 2160 fOutNames = [] 2161 r=0 2162 for mapName,mergeMap in self.instMergeMap.iteritems(): 2163 if 'ltdFile' in mergeMap.keys(): 2164 fIn = mergeMap['ltdFile'] 2165 fInSplit = os.path.splitext(fIn) 2166 fOut = fInSplit[0] + '.slm' 2167 if fOut not in fOutNames: 2168 fOutNames.append(fOut) 2169 r=eemConverLtdToSlmFile(fIn, fOut) 2170 mergeMap['slmFile']=fOut 2171 self.instMergeMap[mapName]=mergeMap 2172 eemWriteDebug("Conversion ltd to slm and lay files done")
2173
2174 - def getTopDesignName(self):
2175 return self.top
2176
2177 - def getSlmFileName(self,iName=None):
2178 eemWriteDebug("Check for stack info of %s" % iName) 2179 name = self.top 2180 if iName: 2181 name = iName 2182 if (not((name == self.top) 2183 or (name in self.ltdRevMap.keys()))): 2184 return None 2185 2186 if self.topSlmDataFileName!=None : 2187 return self.topSlmDataFileName 2188 if self.topSlmFile!=None : 2189 return self.topSlmFile 2190 2191 slmName=None 2192 for mapName,mergeMap in self.instMergeMap.iteritems(): 2193 if (('slmFile' in mergeMap.keys()) 2194 and ('instNames' in mergeMap.keys()) 2195 and (name in mergeMap['instNames'])): 2196 slmName = mergeMap['slmFile'] 2197 break 2198 if ((name == None) or 2199 (slmName == None)): 2200 slmName = self.instMergeMap['main']['slmFile'] 2201 eemWriteDebug("No valid slm file found: return main substrate instead") 2202 return slmName
2203
2204 - def getLtdFileName(self,iName=None):
2205 eemWriteDebug("Check for stack info of %s ltd version" % iName) 2206 name = self.top 2207 if iName: 2208 name = iName 2209 if ((name != self.top) 2210 and (name not in self.ltdRevMap.keys())): 2211 return None 2212 2213 if self.topLtdFile!=None : 2214 return self.topLtdFile 2215 2216 for mapName,mergeMap in self.instMergeMap.iteritems(): 2217 if (('ltdFile' in mergeMap.keys()) 2218 and ('instNames' in mergeMap.keys()) 2219 and (name in mergeMap['instNames'])): 2220 ltdFile = mergeMap['ltdFile'] 2221 break 2222 if ((name == None) or 2223 (ltdFile == None)): 2224 ltdFile = self.instMergeMap['main']['ltdFile'] 2225 eemWriteDebug("No valid ltd file found: return main substrate instead") 2226 return ltdFile
2227
2228 -def subProcessStartupInfo():
2229 import subprocess 2230 try: 2231 startupinfo = subprocess.STARTUPINFO() 2232 startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW 2233 except AttributeError: 2234 startupinfo = None 2235 return startupinfo
2236
2237 -def subedRemoveFromEnviron_QtQpaPluginPlatform():
2238 envVars = os.environ.copy() 2239 qpaId = 'QT_QPA_PLATFORM_PLUGIN_PATH' 2240 if envVars.has_key(qpaId): 2241 del envVars[qpaId] 2242 return envVars
2243
2244 -def eemIsValidSubedVersion():
2245 import subprocess,re,os,string 2246 envVars = subedRemoveFromEnviron_QtQpaPluginPlatform() 2247 subedCmd = ['eesofsubed','--version'] 2248 #subedCmd = "eesofsubed --version" 2249 eemWriteDebug("Check subed version: %s" % subedCmd) 2250 myProcess = subprocess.Popen(args=subedCmd, 2251 executable=None, 2252 stdin=None, 2253 stdout=subprocess.PIPE, 2254 stderr=subprocess.PIPE, 2255 universal_newlines=True, 2256 startupinfo=subProcessStartupInfo(), 2257 shell=False, 2258 env=envVars) 2259 #wait for termination of child process 2260 if 'wait' in dir(os): 2261 cmdStatus=os.wait() 2262 2263 res=''.join(myProcess.stdout.readlines()) 2264 rMatch=re.search('Substrate Editor v(?P<version>[0-9]+\.[0-9]+)',res,re.M) 2265 val=0.0 2266 if rMatch!=None: 2267 val=float(rMatch.group(1)) 2268 valNeeded = 2.1 2269 if val < valNeeded: 2270 eemWriteInfo("No valid EESof Substrate Editor found: needs version %s or higher (should be available in ADS 2009 / EMPro 2011.07 or later)" % valNeeded) 2271 print sys.path 2272 print os.environ['PATH'] 2273 return False 2274 eemWriteDebug("Found valid EESof Substrate Editor") 2275 return True
2276 2277
2278 -def eemMergeLtdFile(fIn1,fIn2,fOut):
2279 envVars = subedRemoveFromEnviron_QtQpaPluginPlatform() 2280 subedCmd = 'eesofsubed -M --stack --pos2=top1 --out=' 2281 subedCmd = subedCmd + fOut 2282 subedCmd = ' '.join([subedCmd, fIn1, fIn2]) 2283 2284 eemWriteDebug("Ltd merge operation: %s" % subedCmd) 2285 2286 myProcess = subprocess.Popen(args=subedCmd, 2287 executable=None, 2288 stdin=None, 2289 stdout=subprocess.PIPE, 2290 stderr=subprocess.PIPE, 2291 universal_newlines=True, 2292 startupinfo=subProcessStartupInfo(), 2293 shell=True, 2294 env=envVars) 2295 #wait for termination of child process 2296 if 'wait' in dir(os): 2297 cmdStatus=os.wait() 2298 2299 res=''.join(myProcess.stdout.readlines()) 2300 if re.search('(Merged stack saved)',res,re.M) == None: 2301 errorString = "Problem merging ltd files: %s and %s into %s\n" % (fIn1, fIn2,fOut) 2302 errorString = errorString + "Process output:\n%s" % res 2303 eemWriteDebug(errorString) 2304 raise Exception(errorString) 2305 2306 eemWriteDebug("Success merging ltd files: %s and %s into %s" % (fIn1, fIn2,fOut)) 2307 return 0
2308 2309
2310 -def eemConverLtdToSlmFile(ifIn, ifOut):
2311 envVars = subedRemoveFromEnviron_QtQpaPluginPlatform() 2312 subedCmd = 'eesofsubed -C --ltd2slm' 2313 fIn = '\"' + ifIn + '\"' 2314 fOut = '\"' + ifOut + '\"' 2315 subedCmd = ' '.join([subedCmd, fIn, fOut]) 2316 2317 eemWriteDebug("Ltd to slm conversion: %s" % subedCmd) 2318 2319 myProcess = subprocess.Popen(args=subedCmd, 2320 executable=None, 2321 stdin=None, 2322 stdout=subprocess.PIPE, 2323 stderr=subprocess.PIPE, 2324 universal_newlines=True, 2325 startupinfo=subProcessStartupInfo(), 2326 shell=True, 2327 env=envVars) 2328 #wait for termination of child process 2329 if 'wait' in dir(os): 2330 cmdStatus=os.wait() 2331 2332 res=''.join(myProcess.stdout.readlines()) 2333 if re.search('(Export successful)',res,re.M) == None: 2334 errorString = "Converting ltd to slm file failed for: %s to %s\n" % (fIn, fOut) 2335 errorString = errorString + "Process output:\n%s" % res 2336 eemWriteDebug(errorString) 2337 raise Exception(errorString) 2338 2339 eemWriteDebug("Ltd to slm file conversion success: %s to %s\n" % (fIn, fOut))
2340 2341
2342 -class AdfiLayers:
2343 - def __init__(self, adfiPrefix):
2344 self.layName = adfiPrefix + '.lay' 2345 self.layDisplayPrefName = adfiPrefix + '.lyrprf' 2346 self.lineTypes = {'solid':0, 2347 'dotted':1, 2348 'double dotted':2, 2349 'short dash':3, 2350 'short dot dash':4, 2351 'long dash':5, 2352 'long dot dash':6} 2353 self.layerData=[] 2354 self.egsProcess=None
2355
2356 - def addSubstrateLayerData(self,iLayerDataNode=None):
2357 if (iLayerDataNode!=None 2358 and self.layerData==[]): 2359 substrateLayerDataNode=iLayerDataNode.getElementsByTagName('SubstrateLayerData') 2360 if substrateLayerDataNode: 2361 clNode=substrateLayerDataNode[0].cloneNode(True) 2362 self.layerData=clNode.getElementsByTagName('SubstrateLayer')
2363
2364 - def addEgsProcess(self,iEgsHeader=None):
2365 self.egsProcess=iEgsHeader
2366
2367 - def writeLayFile(self, mainVersion):
2368 eemWriteDebug("Extract the lay file from adfi elements") 2369 2370 if (self.egsProcess=="" 2371 and self.layerData==[]): 2372 raise Exception('Both SubstrateLayerData and egs process data are missing') 2373 2374 outFormat='%s\tnumber = %s stream = %s iges = %s color = %s fill = %s line = %s, %s %s %s, \"%s\", type = %s, dxf = \"%s\" trans = %s\n' 2375 2376 try: 2377 fName = self.layName 2378 layerData = self.layerData 2379 lineTypes = self.lineTypes 2380 eemWriteDebug("Layer filename is: %s" % fName) 2381 eemWriteDebug("version and layerdata is: %d, %s" % (mainVersion, layerData)) 2382 layFp = open(fName,"w") 2383 if not ((mainVersion < 4) or (layerData==[])): 2384 eemWriteDebug("Version 4 or higher and SubstrateLayer data for this to work.") 2385 first=True 2386 for i in layerData: 2387 layerName = i.getElementsByTagName('LayerName')[0].childNodes[0].nodeValue 2388 layerNum = i.getAttribute('id') 2389 if first: 2390 layFp.write( 'CurrentLayer number = ' + str(layerNum) + '\n' ) 2391 first=None 2392 2393 layerColor = i.getElementsByTagName('LayerColor') 2394 color='1' 2395 if layerColor!=[]: 2396 color=layerColor[0].getAttribute('id') 2397 2398 line='0' 2399 fill='1' 2400 pattern='18' 2401 trans='50' 2402 layerParms = i.getElementsByTagName('Parameter') 2403 for parm in layerParms: 2404 key = parm.getAttribute('key') 2405 value = parm.getAttribute('value') 2406 eemWriteDebug('%s %s'%( key, value)) 2407 if key == 'fill': 2408 val=1 2409 if value == 'outline': 2410 val=0 2411 elif value == 'both': 2412 val=2 2413 fill = str(val) 2414 elif key == 'line': 2415 line = str(lineTypes[value]) 2416 elif key == 'trans': 2417 trans = str(value) 2418 elif key == 'pattern': 2419 pattern = str(value) 2420 layFp.write( outFormat % (layerName, layerNum, layerNum, layerNum, color, 2421 pattern, line, fill, '0', '1', '', '1', layerName, trans) ) 2422 else: 2423 eemWriteDebug("do it from egs process data if necessary") 2424 layers=re.findall('EQU\s+(\w+).*?[:Cc](\d+)\s+:[P]\d+\s+(\d+);', process, re.M) 2425 first=True 2426 for layerName, color, layerNum in layers: 2427 if layerName!='default': 2428 if first: 2429 layFp.write( 'CurrentLayer number = ' + str(layerNum) + '\n' ) 2430 first=None 2431 line='0' 2432 fill='1' 2433 pattern='1' 2434 trans='50' 2435 layFp.write( outFormat % (layerName, layerNum, layerNum, layerNum, color, 2436 pattern, line, fill, '0', '1', '', '1', layerName, trans) ) 2437 2438 layFp.close() 2439 eemWriteDebug("Done: Extract the lay file from adfi elements") 2440 2441 except: 2442 eemWriteError("Can not write lay file info from ADS ADFI file.") 2443 raise
2444
2445 - def writeDisplayPreferenceFile(self, mainVersion):
2446 eemWriteDebug("Extract the layer preference setting and put them into the output") 2447 # process output 2448 try: 2449 lineTypes = self.lineTypes 2450 fName = self.layDisplayPrefName 2451 eemWriteDebug("Layer preference filename is: %s" % fName) 2452 lyrFp = open(fName,"w") 2453 if mainVersion<4: 2454 # need to have at least version 4 2455 lyrFp.close() 2456 raise Exception('Main version needs to be >= 4') 2457 2458 layerData = self.layerData 2459 # need at least version 4 and layerdata to work 2460 if layerData==[]: 2461 lyrFp.close() 2462 raise Exception('No layer data found') 2463 2464 for i in layerData: 2465 line = "" 2466 layerName = i.getElementsByTagName('LayerName')[0].childNodes[0].nodeValue 2467 eemWriteDebug("layer name %s" % layerName) 2468 2469 line = "layer|" + layerName 2470 layerColor = i.getElementsByTagName('LayerColor') 2471 eemWriteDebug("layer name %s" % str(layerColor)) 2472 if layerColor!=[]: 2473 r=layerColor[0].getAttribute('r') 2474 g=layerColor[0].getAttribute('g') 2475 b=layerColor[0].getAttribute('b') 2476 line = line + '|red|' + r + '|green|' + g + '|blue|' + b 2477 eemWriteDebug("layer %s color r=%s g=%s b=%s" % (layerName,r,g,b)) 2478 2479 layerParms = i.getElementsByTagName('Parameter') 2480 eemWriteDebug("layer parms %s" % str(layerParms)) 2481 fillVal=1 2482 lineVal=0 2483 otherLine='' 2484 for parm in layerParms: 2485 key = parm.getAttribute('key') 2486 value = parm.getAttribute('value') 2487 if key == 'fill': 2488 if value == 'outline': 2489 fillVal=0 2490 elif value == 'both': 2491 fillVal=2 2492 elif key == 'line': 2493 lineVal = value 2494 else: 2495 otherLine = otherLine + "|" + str(key) + "|" + str(value) 2496 2497 line = line + "|fill|" + str(fillVal) 2498 line = line + "|line|" + str(lineTypes[lineVal]) 2499 line = line + otherLine 2500 line = line + "\n" 2501 lyrFp.write(line) 2502 lyrFp.close() 2503 eemWriteDebug("Done: Extract the layer preference setting and put them into the output") 2504 2505 except Exception, err: 2506 errorString = "Cannot write display preference info from ADS ADFI file.\n%s" % str(err) 2507 eemWriteDebug(errorString) 2508 raise Exception(errorString)
2509
2510 -class AdfiAblLibInfo:
2511 - def __init__( self, targetDir, adfiPrefix, iLibName=''):
2512 self.present_ = False 2513 self.useAblRoot_ = False 2514 self.targetDir = targetDir 2515 self.fPrefix = adfiPrefix 2516 self.name = iLibName 2517 self.libName = '' 2518 self.refTechnologies = [] 2519 self.userUnits = None 2520 self.DBUperUU = None 2521 self.instTextHeight='0.' 2522 self.portSize='0.' 2523 self.processTypes = {'Not defined':'PROCESS_ROLE_NONE', 2524 'Conductor':'PROCESS_ROLE_CONDUCTOR', 2525 'Dielectric':'PROCESS_ROLE_DIELECTRIC'} 2526 2527 self.lineTypes = {'solid':0, 2528 'dotted':1, 2529 'double dotted':2, 2530 'short dash':3, 2531 'short dot dash':4, 2532 'long dash':5, 2533 'long dot dash':6, 2534 'Solid':0, 2535 'Dotted':1, 2536 'Double Dotted':2, 2537 'Short Dash':3, 2538 'Short Dot Dash':4, 2539 'Long Dash':5, 2540 'Long Dot Dash':6} 2541 self.patternTypes = {'solid':18,'Solid':18,'18':18 } 2542 self.fillTypes = {'Outlined':0,'outline':0, 2543 'Filled':1,'filled':1, 2544 'Both':2,'both':2} 2545 self.unitsMap = {'um':'micron', 2546 'micron':'micron', 2547 'mm':'millimeter', 2548 'millimeter':'millimeter', 2549 'cm':'centimeter', 2550 'centimeter':'centimeter', 2551 'meter':'meter', 2552 'mil':'mil', 2553 'inch':'inch'} 2554 self.maskNameNbMap = {} 2555 self.layers = [] 2556 self.layerIds = [] 2557 self.defaultSubstrate = None 2558 self.substrateList = [] 2559 self.ebondsList = []
2560
2561 - def present( self, status=None ):
2562 if status!=None: 2563 self.present_=status 2564 return self.present_
2565
2566 - def useAblRoot( self ):
2567 return self.useAblRoot_
2568
2569 - def getMaskMap( self ):
2570 return self.maskNameNbMap
2571
2572 - def buildAblData( self, ablNode ):
2573 eemWriteDebug("Process ABL library data") 2574 self.present_=True 2575 if ablNode.tagName == 'abl:ABLRoot': 2576 self.useAblRoot_=True 2577 libraryNode=ablNode.getElementsByTagName('abl:Library')[0] 2578 if libraryNode.hasAttribute('name') and (self.libName=='' or self.libName==None): 2579 self.libName = libraryNode.getAttribute('name') 2580 else: 2581 self.libName = self.name 2582 2583 techNode=ablNode.getElementsByTagName('abl:Technology')[0] 2584 self.getRefTechnologies( techNode ) 2585 self.getUnits( techNode ) 2586 self.getLayers( techNode ) 2587 self.getLayerIds( techNode ) 2588 self.getMaterials( techNode ) 2589 self.getSubstrates( techNode ) 2590 self.getPreferences( ablNode ) 2591 self.getEBondProfiles( ablNode ) 2592 if self.libName != self.name: 2593 libraryNode.setAttribute('name', self.name) 2594 2595 nestedSubstrateNodes=techNode.getElementsByTagName('abl:NestedSubstrate') 2596 for nestedSubstrate in nestedSubstrateNodes: 2597 nestedSubstrate.setAttribute('library', self.name) 2598 nestedSubstrate.setAttribute('layerMapLib', self.name) 2599 2600 if not ablNode.hasAttribute('xmlns:abl'): 2601 if self.useAblRoot_: 2602 ablNode.setAttribute("xmlns:abl", "http://keysight.com/eesof/abl") 2603 else: 2604 ablNode.setAttribute("xmlns:abl", "http://agilent.com/abl") 2605 self.writeAblLibXml(ablNode) 2606 self.writeAblLibInfo() 2607 eemWriteDebug("Done: processing ABL library data")
2608
2609 - def writeAblLibXml(self, ablNode ):
2610 fileName = self.fPrefix + '_abl.xml' 2611 fp = open(fileName, 'w') 2612 fp.write( '<?xml version="1.0" encoding="UTF-8"?>\n' ) 2613 xmlString = ablNode.toxml() 2614 fp.write(xmlString) 2615 fp.write('\n') 2616 fp.close()
2617 2618
2619 - def writeAblLibInfo(self ):
2620 fileName = self.fPrefix + '_abl.aldf' 2621 fp = open(fileName, 'w') 2622 fp.write( 'ABLLIBRARY|%s|UU|%s|DBUTOUU|%s\n' % 2623 ( self.name, self.unitsMap[self.userUnits], self.DBUperUU ) ) 2624 fp.write( 'ABLLAYOUTPREFERENCES|PORT_SIZE|%s|ANNOTATION_HEIGHT|%s\n' % 2625 ( self.portSize, self.instTextHeight ) ) 2626 for tech in self.refTechnologies: 2627 fp.write( 'ABLREFTECH|%s\n' % tech ) 2628 fp.write( 'ABLREFTECHEND\n' ) 2629 fp.write( 'ABLLAYERSSTART|layername|layernumber|process_role\n' ) 2630 for layer in self.layers: 2631 fp.write( 'ABLLAYERS|%s|%s|%s\n' % layer ) 2632 fp.write( 'ABLLAYERSEND\n' ) 2633 fp.write( 'ABLLAYERIDSTART|layer|purpose\n' ) 2634 for layerId in self.layerIds: 2635 data='ABLLAYERID' 2636 for (key,value) in layerId.iteritems(): 2637 data += '|' + str(key) + '|' + str(value) 2638 data += '\n' 2639 fp.write( data ) 2640 fp.write( 'ABLLAYERIDEND\n' ) 2641 fp.write( 'ABLMATERIALS|materials.matdb|%s\n' % os.path.join( self.targetDir, 'materials.matdb' )) 2642 for substrate in self.substrateList: 2643 substrateName = substrate + '.subst' 2644 fp.write( 'ABLSUBSTRATEFILE|%s|%s\n' % (substrateName, os.path.join( self.targetDir, substrateName ))) 2645 fp.write( 'ABLLIBRARYDEFAULTSUBSTRATE|%s\n' % self.defaultSubstrate ) 2646 fp.write( 'ABLEBONDSTART\n' ) 2647 for ebond in self.ebondsList: 2648 fp.write( '%s' % ebond ) 2649 fp.write( 'ABLEBONDEND\n' ) 2650 fp.write( 'ABLLIBRARYEND\n' ) 2651 fp.close()
2652
2653 - def getRefTechnologies( self, techNode ):
2654 refTechNodes =[] 2655 if techNode: 2656 refTechNodes = techNode.getElementsByTagName( 'abl:ReferencedTechnology' ) 2657 for node in refTechNodes: 2658 if node.hasAttribute( 'referencedLibraryName' ): 2659 self.refTechnologies.append(node.getAttribute( 'referencedLibraryName' ))
2660
2661 - def getUnits( self, techNode ):
2662 techUnitsNode = techNode.getElementsByTagName( 'abl:TechUnits' )[0] 2663 if techUnitsNode == None: 2664 return 2665 layoutUnitNode = techUnitsNode.getElementsByTagName( 'abl:LayoutUnits' )[0] 2666 if layoutUnitNode != None: 2667 self.userUnits=layoutUnitNode.getAttribute( 'oaUserUnits' ) 2668 self.DBUperUU=layoutUnitNode.getAttribute( 'DBUperUU' )
2669
2670 - def getLayers( self, techNode ):
2671 layersNode = techNode.getElementsByTagName( 'abl:Layers' )[0] 2672 if layersNode==None: 2673 return 2674 layerNodes = layersNode.getElementsByTagName('abl:Layer' ) 2675 for node in layerNodes: 2676 name = node.getAttribute('name') 2677 number = node.getAttribute('number') 2678 self.maskNameNbMap[name] = number 2679 processRole = self.processTypes[node.getAttribute('processRole')] 2680 layerEntry = tuple([name, number, processRole]) 2681 self.layers.append( layerEntry )
2682
2683 - def getLayerIds( self, techNode ):
2684 layerIdsNode = techNode.getElementsByTagName( 'abl:DisplayProperties' )[0] 2685 if layerIdsNode==None: 2686 return 2687 layerIdNodes = layerIdsNode.getElementsByTagName( 'abl:DisplayProperty' ) 2688 for node in layerIdNodes: 2689 layerId={} 2690 layerId['layer'] = node.getAttribute('layer') 2691 layerId['purpose'] = node.getAttribute('purpose') 2692 layerId['r'] = node.getAttribute('r') 2693 layerId['g'] = node.getAttribute('g') 2694 layerId['b'] = node.getAttribute('b') 2695 layerId['alpha'] = node.getAttribute('alpha') 2696 layerId['fill'] = self.fillTypes[node.getAttribute('displayMode')] 2697 layerId['line'] = self.lineTypes[node.getAttribute('lineType')] 2698 layerId['pattern'] = self.patternTypes[node.getAttribute('fillType')] 2699 layerId['visible'] = '1' 2700 layerId['protected'] = '0' 2701 self.layerIds.append(layerId)
2702
2703 - def getMaterials( self, techNode ):
2704 materialsNode = techNode.getElementsByTagName( 'abl:Materials' )[0] 2705 if materialsNode==None: 2706 return 2707 eemAdfiAblMaterialWriting( materialsNode, self.targetDir )
2708
2709 - def getSubstrates( self, techNode ):
2710 substratesNode = techNode.getElementsByTagName( 'abl:Substrates' )[0] 2711 if substratesNode==None: 2712 return 2713 defaultsNode = substratesNode.getElementsByTagName( 'abl:DefaultSubstrate' )[0] 2714 defaultLib = defaultsNode.getAttribute('library') 2715 defaultSubstrateName = defaultsNode.getAttribute('name') 2716 if defaultLib=='__CURRENT__': 2717 defaultLib = self.name 2718 defaultsNode.setAttribute('library', self.name) 2719 self.defaultSubstrate = defaultLib + '|' + defaultSubstrateName 2720 self.substrateList = writeSubstrates( substratesNode, self.name, self.targetDir )
2721
2722 - def getPreferences( self, ablNode ):
2723 libPrefNodes = ablNode.getElementsByTagName( 'abl:LibraryPreferences' ) 2724 if libPrefNodes==[]: 2725 return 2726 libPrefNodes = ablNode.getElementsByTagName( 'abl:LayoutPreferences' ) 2727 if libPrefNodes==[]: 2728 return 2729 prefNodes = libPrefNodes[0].getElementsByTagName( 'abl:FileContents' ) 2730 if prefNodes==[]: 2731 return 2732 preferences=getInnerText(prefNodes[0]).splitlines() 2733 for i in preferences: 2734 lst=i.split(' ') 2735 if len(lst)==2: 2736 name = lst[0] 2737 value = lst[1] 2738 if name == 'instTextHeight': 2739 self.instTextHeight = value 2740 elif name == 'portSize': 2741 self.portSize = value
2742
2743 - def getEBondProfiles( self, ablNode ):
2744 ebondNodes = ablNode.getElementsByTagName( 'abl:Instance' ) 2745 if ebondNodes==[]: 2746 return 2747 for ebondNode in ebondNodes: 2748 if ebondNode.getAttribute('cellName')!='EBOND_Shape': 2749 continue 2750 ebondEntry = 'ABLEBOND|' + ebondNode.getAttribute('instanceName') 2751 parmNodes = ebondNode.getElementsByTagName( 'abl:Parameter' ) 2752 for parmNode in parmNodes: 2753 name = parmNode.getAttribute('name') 2754 value = parmNode.getAttribute('value') 2755 if name.startswith(('rT','tT','vT','rZ','tZ','vZ')): 2756 ebondEntry+= '|' + str(name) + '|' + str(value) 2757 ebondEntry += '\n' 2758 self.ebondsList.append(ebondEntry)
2759 2760 2761
2762 -def eemAdfiAblMaterialWriting( iMaterialsNode, targetDir ):
2763 filename = os.path.join( targetDir, 'materials.matdb') 2764 file = open( filename, "w" ) 2765 file.write( '<!DOCTYPE Materials>\n' ) 2766 xmlString = iMaterialsNode.toxml() 2767 xmlString = xmlString.replace( 'abl:', '' ) 2768 file.write(xmlString) 2769 file.write('\n') 2770 file.close()
2771 2772
2773 -class eemAdfiAblSubstWriter:
2774 - def __init__( self, iLibName='', iStackName=None, iTargetDir=None ):
2775 self.name = iStackName 2776 self.libName = iLibName 2777 targetDir = iTargetDir 2778 if targetDir==None or targetDir=='': 2779 targetDir='.' 2780 filename = os.path.join( targetDir, iStackName + '.subst' ) 2781 self.file = open( filename, "w" ) 2782 self.file.write( '<!DOCTYPE Substrate>\n<SubstrateModel>\n' )
2783
2784 - def close( self ):
2785 self.file.write( '</SubstrateModel>\n' ) 2786 self.file.close()
2787
2788 - def writeStack( self, iStackNode ):
2789 xmlString = iStackNode.toxml() 2790 xmlString = xmlString.replace( 'abl:', '' ) 2791 xmlString = xmlString.replace( 'SubStack', 'stack' ) 2792 xmlString = xmlString.replace( 'SubMaterial', 'material' ) 2793 xmlString = xmlString.replace( 'SubInterface', 'interface' ) 2794 self.file.write( xmlString ) 2795 self.file.write( '\n' )
2796
2797 - def writeLayers( self, iLayersNode ):
2798 xmlString = iLayersNode.toxml() 2799 xmlString = xmlString.replace('abl:SubLayer', 'layer') 2800 self.file.write( xmlString ) 2801 self.file.write( '\n' )
2802
2803 - def writeVias( self, iViaNode ):
2804 xmlString = iViaNode.toxml() 2805 xmlString = xmlString.replace( 'abl:SubVia', 'via' ) 2806 self.file.write( xmlString ) 2807 self.file.write( '\n' )
2808
2809 - def writeNestedSubstrates(self, iNestedSubstrates):
2810 xmlString = iNestedSubstrates.toxml() 2811 xmlString = xmlString.replace('abl:NestedSubstrate', 'substrate') 2812 xmlString = xmlString.replace('__CURRENT__', self.libName) 2813 self.file.write( xmlString ) 2814 self.file.write( '\n' )
2815
2816 -def writeSubstrates(iSubstratesNode, iLibName, targetDir):
2817 stackList=[] 2818 elements = iSubstratesNode.getElementsByTagName('abl:Substrate') 2819 for el in elements: 2820 if el.hasAttribute('name'): 2821 stackName = el.getAttribute('name') 2822 currentStack = eemAdfiAblSubstWriter( iLibName, stackName, targetDir ) 2823 stackNode = el.getElementsByTagName( 'abl:SubStack' )[0] 2824 currentStack.writeStack( stackNode ) 2825 layersNode = el.getElementsByTagName( 'abl:SubLayers' )[0] 2826 currentStack.writeLayers( layersNode ) 2827 viasNode = el.getElementsByTagName( 'abl:SubVias' )[0] 2828 currentStack.writeVias( viasNode ) 2829 nestedSubstratesNode = el.getElementsByTagName( 'abl:NestedSubstrates' ) 2830 if nestedSubstratesNode: 2831 currentStack.writeNestedSubstrates( nestedSubstratesNode[0] ) 2832 currentStack.close() 2833 stackList.append(stackName) 2834 return stackList
2835 2836 2837 2838 2839 2840 ########################################################## 2841 # Load and parse adfi file using mindom parser 2842 #
2843 -def eemAdfiReadFile(iAdfiFilename):
2844 # load content 2845 try: 2846 eemWriteDebug("Filename is: %s" % iAdfiFilename) 2847 f = open(iAdfiFilename,"r") 2848 content = ''.join(f.readlines()) 2849 f.close() 2850 except: 2851 eemWriteError("Can not read from ADS ADFI file: %s" % iAdfiFilename) 2852 raise 2853 2854 # remove unnecessary white space 2855 content = re.sub('>\s+<','><',content) 2856 2857 # xml dom 2858 eemWriteDebug("Parse ADS ADFI file document") 2859 try: 2860 eemAdfiDom = xml.dom.minidom.parseString(content) 2861 except: 2862 eemWriteError("Problem with xml.dom.minidom parser: need to exit") 2863 raise 2864 return eemAdfiDom
2865 2866 2867
2868 -def eemAdfiProcessCollect(iAdfiDoc, iFprefix, iAdfiInfo, iAdfiTechData, iAdfiEgsWriter, iAdfiLayers, iAblLibInfo,targetPlatform='ads'):
2869 """ First pass through file using pulldom mechanism """ 2870 2871 parser=xml.sax.make_parser() 2872 # skip external dtd definition 2873 parser.setFeature(xml.sax.handler.feature_external_ges,0) 2874 # limit parser memory to about 1GByte 2875 events = xml.dom.pulldom.parse(iAdfiDoc,parser,1024*1024*16) 2876 2877 inComponent=None 2878 top=None 2879 cmpName=None 2880 name=None 2881 egsHeader='' 2882 for (event,node) in events: 2883 if (event==xml.dom.pulldom.START_ELEMENT 2884 and node.localName=='AdfiToAds'): 2885 iAdfiInfo.setAdfiToAdsAttributes(event,node) 2886 try: 2887 iAdfiInfo.checkTargetPlatform(targetPlatform) 2888 except Exception, err: 2889 eemWriteWarn(str(err)) 2890 if targetPlatform=='empro': 2891 eemWriteWarn("!!! This may result in loss of objects during the import.") 2892 eemWriteWarn("!!! Please regenerate your .adfi file with EMPro as target platform.") 2893 pass # currently not critical 2894 elif event==xml.dom.pulldom.START_ELEMENT and ( node.tagName=='abl:AgilentBoardLink' or node.tagName=='abl:ABLRoot' ): 2895 events.expandNode(node) 2896 iAblLibInfo.buildAblData(node) 2897 2898 elif event==xml.dom.pulldom.START_ELEMENT and node.localName=="AdfiComponent": 2899 cmpName = node.getAttribute('id') 2900 top = (node.getAttribute('top')=='true') 2901 if top: 2902 iAdfiTechData.topName(cmpName) 2903 inComponent = True 2904 elif event==xml.dom.pulldom.END_ELEMENT and node.localName=="AdfiComponent": 2905 cmpName = None 2906 top = None 2907 inComponent = None 2908 name= None 2909 2910 elif inComponent and event==xml.dom.pulldom.START_ELEMENT and node.localName=='Name': 2911 events.expandNode(node) 2912 name = eemFixName(getInnerText(node)) 2913 2914 elif (inComponent 2915 and event==xml.dom.pulldom.START_ELEMENT 2916 and node.localName=='ComponentParms'): 2917 events.expandNode(node) 2918 iAdfiEgsWriter.updateFilterEgsMap(node,cmpName) 2919 2920 elif (inComponent and top 2921 and event==xml.dom.pulldom.START_ELEMENT 2922 and node.localName=='Units'): 2923 events.expandNode(node) 2924 iAdfiInfo.setUnits(node) 2925 2926 elif (inComponent 2927 and event==xml.dom.pulldom.START_ELEMENT 2928 and node.localName=='Substrate'): 2929 events.expandNode(node) 2930 iAdfiTechData.addLtdSlmMap(node,cmpName,top) 2931 iAdfiLayers.addSubstrateLayerData(node) 2932 2933 elif inComponent and top and event==xml.dom.pulldom.START_ELEMENT and node.localName=='Instances': 2934 events.expandNode(node) 2935 iAdfiTechData.addSubstrateInstanceMap(node) 2936 2937 elif (inComponent and top 2938 and event==xml.dom.pulldom.START_ELEMENT 2939 and node.localName=='Geometry2D' 2940 and node.hasAttribute('geometry2DType') 2941 and node.getAttribute('geometry2DType')=='egs' 2942 and node.hasAttribute('geometry2DOp') 2943 and node.getAttribute('geometry2DOp')=='process'): 2944 events.expandNode(node) 2945 egsHeader+=getInnerText(node) 2946 iAdfiLayers.addEgsProcess(egsHeader) 2947 iAdfiEgsWriter.writeHeader(egsHeader) 2948 2949 elif (inComponent and top 2950 and event==xml.dom.pulldom.START_ELEMENT 2951 and node.localName=='Ports'): 2952 events.expandNode(node) 2953 try: 2954 fName = iFprefix + '_top.prt' 2955 eemWriteDebug("Port Filename is: %s" % fName) 2956 eemAdfiWritePortFile(fName, node) 2957 except Exception, err: 2958 eemWriteError("Problem processing definitions of ports on top level: need to exit") 2959 eemWriteError('ERROR: %s\n' % str(err)) 2960 raise 2961 # process pins and ports on top level and write out .pin and .prt file 2962 try: 2963 fName = iFprefix + '_top.pin' 2964 eemWriteDebug("Pin Filename is: %s" % fName) 2965 eemAdfiWritePinFile(fName, node, iAdfiInfo) 2966 except Exception, err: 2967 eemWriteError("Problem processing definitions of pins on top level: need to exit") 2968 eemWriteError('ERROR: %s\n' % str(err)) 2969 raise
2970 2971 2972 2973 ########################################################## 2974 # process adfi file 2975 #
2976 -def eemAdfiProcessFile(iAdfiFilename,targetDir=None,useJedecBondwires=False,useSolderBalls=False,bwMap=None,sbMap=None,targetPlatform='ads', oaLibName=None ):
2977 """Load and parse adfi file for use in ADS and EMPro""" 2978 2979 fprefix = os.path.splitext(iAdfiFilename)[0] 2980 if (targetDir != None): 2981 fprefix = os.path.join(targetDir,os.path.basename(fprefix)) 2982 adfiPrefix = fprefix + '_adfi' 2983 if oaLibName==None: 2984 oaLibName=os.path.basename(fprefix)+ '_lib' 2985 2986 eemAdfiInfo=AdfiInfo() 2987 eemAdfiTechData=AdfiLtds(fprefix) 2988 eemAdfiEgsWriter=AdfiEgsWriter( adfiPrefix + '_egs', 2989 useSolderBalls ) 2990 eemAdfiLayers=AdfiLayers(adfiPrefix) 2991 eemAblLibInfo=AdfiAblLibInfo(targetDir, adfiPrefix, oaLibName) 2992 2993 try: 2994 eemAdfiProcessCollect(iAdfiFilename, fprefix, eemAdfiInfo, eemAdfiTechData, eemAdfiEgsWriter, eemAdfiLayers, eemAblLibInfo, targetPlatform) 2995 except: 2996 eemWriteError("Problem with initial doc parsing: need to exit") 2997 raise 2998 2999 maskNameNbMap={} 3000 hasAbl=eemAblLibInfo.present() 3001 useAblRoot=eemAblLibInfo.useAblRoot() 3002 if hasAbl: 3003 maskNameNbMap = eemAblLibInfo.getMaskMap() 3004 else: 3005 # process LTD information 3006 try: 3007 eemAdfiTechData.assembleLtdSlmMaps() 3008 except: 3009 eemWriteError("Problem with stack processing: need to exit") 3010 raise 3011 maskNameNbMap = getMaskNames(eemAdfiTechData) 3012 eemWriteDebug("maskNameNbMap : %s" % (str(maskNameNbMap))) 3013 3014 3015 try: 3016 eemAdfiLayers.writeLayFile(eemAdfiInfo.mainVersion) 3017 except: 3018 pass # not critical 3019 try: 3020 eemAdfiLayers.writeDisplayPreferenceFile(eemAdfiInfo.mainVersion) 3021 except: 3022 pass # not critical 3023 3024 eemAdfiHdefWriter=None 3025 try: 3026 eemAdfiHdefWriter=AdfiHdefWriter(fprefix,eemAdfiInfo,hasAbl,useAblRoot) 3027 except: 3028 eemWriteError("Problem creating hierachical processing file: need to exit") 3029 raise 3030 3031 eemAdfiBondWireWriter=None 3032 try: 3033 fName = fprefix + '_adfi.dbw' 3034 eemWriteDebug("Bondwire Filename is: %s" % fName) 3035 eemAdfiBondWireWriter = bondWireWriter(fName,maskNameNbMap) 3036 except: 3037 eemWriteError("Problem creating bondwire file: need to exit") 3038 raise 3039 3040 try: 3041 eemAdditionalParms = eemAdfiReadOptParmFile(os.path.splitext(iAdfiFilename)[0]) 3042 except: 3043 eemAdditionalParms = None 3044 pass 3045 3046 # process pins, ports and instances in components 3047 try: 3048 eemWriteDebug("ADFI Process Hierarchical Definition") 3049 eemAdfiProcessHDefEgsFile(iAdfiFilename, eemAdfiInfo, 3050 eemAdfiHdefWriter, eemAdfiEgsWriter, 3051 eemAdfiBondWireWriter, eemAdfiTechData, 3052 eemAdditionalParms, maskNameNbMap) 3053 eemAdfiHdefWriter.close() 3054 eemAdfiEgsWriter.close() 3055 except Exception, err: 3056 eemWriteError("Problem Hierarchical Definition output processing: need to exit") 3057 eemWriteError('ERROR: %s\n' % str(err)) 3058 raise 3059 3060 # process bondwires 3061 if (useSolderBalls or 3062 (useJedecBondwires and bwMap != None)): 3063 3064 adfiDom=None 3065 3066 try: 3067 eemAdfiDom = eemAdfiReadFile(iAdfiFilename) 3068 except: 3069 raise 3070 3071 if useSolderBalls: 3072 try: 3073 eemAdfiBondWireWriter.writeSBDummyBondWires(eemAdfiDom,useSolderBalls,sbMap=sbMap) 3074 except Exception, err: 3075 eemWriteError("Problem processing definitions of bondwires: need to exit") 3076 eemWriteError('ERROR: %s\n' % str(err)) 3077 raise 3078 if useJedecBondwires and bwMap != None: 3079 importer = bondwireImporter() 3080 importer.getBondwireMap(eemAdfiDom,bwComps=bwMap) 3081 3082 eemAdfiBondWireWriter.close() 3083 eemWriteDebug("ADFI Hierarchical Definition File processed") 3084 3085 return 1
3086 3087 3088 3089 if __name__=="__main__": 3090 try: 3091 if len(sys.argv)==2: 3092 eemAdfiProcessFile( sys.argv[1] ) 3093 elif len(sys.argv)==3: 3094 eemAdfiProcessFile( sys.argv[1],sys.argv[2] ) 3095 elif len(sys.argv)==4: 3096 eemAdfiProcessFile( sys.argv[1], sys.argv[2], oaLibName=sys.argv[3] ) 3097 else: 3098 print "usage: python $IMPORT_ADFI_ADD_ON/scripts/eemAdfiParse.py <file> [<targetDir> [<oalibName>]]" 3099 sys.exit(2) 3100 sys.exit(0) 3101 except Exception, err: 3102 eemWriteError('%s\n' % str(err)) 3103 sys.exit(1) 3104