# -*- Mode:Python -*- # # This file is part of the Coriolis Software. # Copyright (c) Sorbonne Université 2015-2021, All Rights Reserved # # +-----------------------------------------------------------------+ # | C O R I O L I S | # | Alliance / Hurricane Interface | # | | # | Author : Jean-Paul CHAPUT | # | E-mail : Jean-Paul.Chaput@lip6.fr | # | =============================================================== | # | Python : "./crlcore/python/helpers/analogtechno.py" | # +-----------------------------------------------------------------+ import os import os.path import sys import Hurricane from Hurricane import DbU from Hurricane import DataBase from Hurricane import Layer from helpers.io import catch, ErrorMessage, WarningMessage tech = None technoFile = '' Length = 0x0001 Area = 0x0002 Asymmetric = 0x0004 Unit = 0x0008 def valueToDbU ( value, unit, lengthType ): length = DbU.fromPhysical( value, unit ) if lengthType & Length: return length area = DbU.fromPhysical( float(length), unit ) return area def isStepped ( entry ): if isinstance(entry,tuple): for item in entry: if not isinstance(item,tuple) or len(item) != 2: return False return True return False def isNonIsotropic ( entry ): if not isinstance(entry,tuple) or len(entry) != 2: return False if not isinstance(entry[0],int) and not isinstance(entry[0],float): return False if not isinstance(entry[1],int) and not isinstance(entry[1],float): return False return True def checkEntry ( entry, entryNo ): if not isinstance(entry,tuple): raise ErrorMessage( 1, [ 'Entry %d is malformed in .' % entryNo , 'Not a tuple (a, b, c, ...) or (a,).' , str(entry) ] ) if not len(entry) in (4, 5, 6): raise ErrorMessage( 1, [ 'Entry %d is malformed in .' % entryNo , 'Tuple must have *4*, *5* or *6* items only.' , str(entry) ] ) if not entry[-2] in (Length, Length|Asymmetric, Area, Unit): raise ErrorMessage( 1, [ 'Entry %d is malformed in .' % entryNo , 'Beforelast item is neither Length, Length|Asymmetric nor Area.' , str(entry) ] ) return def _loadAnalogTechno ( techno, ruleTable ): unit = None entryNo = 0 for entry in ruleTable: entryNo += 1 try: if entryNo > 1: checkEntry( entry, entryNo ) if entry[0] == 'Header': unit = entry[2] techno.setName( entry[1] ) continue # Zero-layer rule. if len(entry) == 4: if entry[2] & Unit: rule = techno.addUnitRule( entry[0], entry[3] ) rule.addValue( entry[1] ) else: rule = techno.addPhysicalRule( entry[0], entry[3] ) rule.addValue( valueToDbU(entry[1], unit, entry[2]), 0 ) # One-layer rule. if len(entry) == 5: rule = techno.addPhysicalRule( entry[0], entry[1], entry[4] ) if entry[3] & Unit: rule.addValue( entry[2] ) else: if isStepped(entry[2]): for step in entry[2]: rule.addValue( valueToDbU(step[0], unit, entry[3]) , valueToDbU(step[1], unit, entry[3]) ) elif isNonIsotropic(entry[2]): rule.addValue( valueToDbU(entry[2][0], unit, entry[3]) , valueToDbU(entry[2][1], unit, entry[3]) , 0 ) else: rule.addValue( valueToDbU(entry[2], unit, entry[3]), 0 ) # Two-layer rule. if len(entry) == 6: symmetric = True if entry[4] & Asymmetric: symmetric = False rule = techno.addPhysicalRule( entry[0], entry[1], entry[2], entry[5] ) rule.setSymmetric( symmetric ) if isNonIsotropic(entry[3]): rule.addValue( valueToDbU(entry[3][0], unit, entry[4]) , valueToDbU(entry[3][1], unit, entry[4]) , 0 ) else: rule.addValue( valueToDbU(entry[3], unit, entry[4]), 0 ) except Exception as e: e = ErrorMessage( 1, e ) e.addMessage( 'In {}: at index {}.'.format(technoFile,entryNo) ) print( str(e) ) return def loadAnalogTechno ( table, fromFile ): global technoFile global tech if not tech: tech = DataBase.getDB().getTechnology() technoFile = fromFile _loadAnalogTechno( tech, table ) return def addDevice ( **kw ): global tech if not tech: tech = DataBase.getDB().getTechnology() try: if 'name' in kw: devDesc = tech.addDeviceDescriptor( kw['name'] ) if 'spice' in kw: devDesc.setSpiceFilePath( kw['spice'] ) if 'connectors' in kw: for connector in kw['connectors']: devDesc.addConnector( connector ) else: print( WarningMessage( 'common.addDevice(): Missing connectors on device "{}".' \ .format(kw['name']))) if 'layouts' in kw: for layout in kw['layouts']: devDesc.addLayout( layout[0], layout[1] ) else: print( WarningMessage( 'common.addDevice(): Missing layouts on device "{}".' \ .format( kw['name'] ))) except Exception as e: catch( e ) return