EDA Tool

#1.ReadDeviceList.py :


import xlrd    
def ReadDeviceList(ExcelPath,SheetName):
    #define output data
    DeviceDict={}
    #Tabel format:
    TableFormatHeader=['Device','Terminal','DeviceName','Instance Statement','Device Description (ADS explanation)','Equation']
    ColumnOfTable=len(TableFormatHeader)
    #read excel and parse
    with xlrd.open_workbook(ExcelPath) as Excel:
        #SheetName= Excel.sheet_names()[0]
        #get sheet contain Device List info
        Sheet=Excel.sheet_by_name(SheetName)
        #遍历每一行,count数行数
        Nrows=Sheet.nrows #获得sheet的总行数
        Section=0
        Count=0
        while Count<Nrows:
            RowList=Sheet.row_values(Count) #RowList是一个以每一行的各个列元素组合成的list
            Count+=1
        #read by lines, Section = 1 mean catch the table info of device list 
            if (RowList[1].find(TableFormatHeader[0]) != -1):  #RowList should be string or error occur
                Section=1 # the first section Mask Name table, extract Layers
                continue    #if catch header, jump out of this segment
            elif Section==1:  #
                try:
                    DeviceDict[RowList[TableFormatHeader.index('DeviceName')+1]]=RowList[TableFormatHeader.index('Instance Statement')+1]
                except IndexError:
                    pass
            elif Section==2:  #Section 2 is Design Rule Info
                pass                    
        if Count==0:
            pass
        #read failure
    #Excel.close() workbook do not have close() function
    return DeviceDict   #output format {DeviceName:'statement'}  statement format like {'qebe':'qbebxxx (E,B,C) we =2[1.6,5] le =20[10,50]  ne=1[2,8] nb=3[::] nc=2 selft =1 trise = 0 rthpkg =0 cthpag =0'}


import re
def DeleteNullInList(StringList):
    for item in StringList:
        if (item=='' or item==[]):
            StringList.remove(item)
def ParseStatement(Statement):
    #define output
    ParameterDict={}
    Pins=[]
    PinsDict={}
    #
    if isinstance(Statement,str):
        RegularStatement=re.sub('=',' = ',Statement)
        #check if string
        Words=re.split('\s',RegularStatement)
        DeleteNullInList(Words) # delete null cell
        #Words[0] is like 'qebexxx' represent the format
        #Words[1] is pins
        Pins=re.split('\s|(|)|,',Words[1])
        DeleteNullInList(Pins) 
        PinsDict['Pins']=Pins
        #Words[2+] is parameters
        WordLen=len(Words)
        i=Words.index('=') #initial i as the first index of '='
        while (i < WordLen):
            ParameterIndex=i-1
            ValueIndex=i+1
            OperatorIndex=i
            #check value exist & value
            try:
                if (Words[OperatorIndex] != '='):
                    break
                ValuePattern='\s|\[|\]|,|:'  #Notice [] represent the or relation of the sepeartors set
                ValueList=re.split(ValuePattern,Words[ValueIndex])
                DeleteNullInList(ValueList)
                ValueLen=len(ValueList)
                if ValueLen==3 or ValueLen==1:
                    ParameterValueList=[ValueLen]+ValueList
                    ParameterDict[Words[ParameterIndex]]=ParameterValueList
                    i=i+3
                else:
                    return 'FormatError','Statement format is unrecognizable' # waring that the format is unknown
                
            except IndexError:
                return 'IndexError','some words may missing or foramt is not unrecognizable' #error warning code & write log
            
        return ParameterDict,Pins
        #result is like {'we':[3,'2','1','10'],'le':}
        #multi expression []

    else:
        return 'TypeError','Arguement is not string'# error warning code


def ParseDeviceDict(DeviceDictRaw):
    DeviceDict={}
    for key in DeviceDictRaw:
        Paremeters,Pins=ParseStatement(DeviceDictRaw[key])
        TempDict={}
        TempDict.update(Parameters)
        TempDict.update(Pins)
        DeviceDict[key]=TempDict
    return DeviceDict        

#######################################################################

#2.ReadPDKCircuitAel.py

#get all file in PDK/circuit/ael document: path, filename
import os
def RecursionFileInDoc(PATH):  
    if(PATH[-1]!='/'):
        PWD=PATH+'/' 
    else:
        PWD=PATH # if not / add
    Files=[]
    
    CurrentDir=os.listdir(PATH)
    for i in range (len(CurrentDir)):
        if(os.path.isdir(PWD+CurrentDir[i])):
            Files=Files+(recursionFile(PWD+CurrentDir[i]))
        elif(os.path.isfile(PWD+CurrentDir[i])):
            Files.append(PWD+CurrentDir[i])
    return Files    
#if the filename is not end with FilterKeywords like 'ael', it will be delete
def FilenameFilter(FileList,FilterKeyword):
    for filename in FileList:
        tempname=re.split('.',filename)
        if tempname[-1]!=FilterKeyword :
            FileList.remove(filename)


#ParseAel file
def ParseCircuitAel(FilePath):
    DeviceParameterList=[]
    with open(FilePath) as CircuitAelFile:
        #FilePath is CircuitAelFile 
        #ParseWords=[]
        Count=0 
        TempStringList=[]
        # 0: not parsing >0 parsing; different segment different parsing
        for row in CircuitAelFile:
            #remove //commmet
            CommentIndex=row.find('//')
            CodeString=row[0:CommentIndex]
            #when row catch 'create_item' start Parsing
            if row.find('create_item')!=-1:
                TempStringList.append(CodeString)
                Count=1
            elif row.find('create_parm')!=-1:
                TempStringList.append(CodeString)
                Count=Count+1
            if Count>0:
                TempStringList[Count-1]+=CodeString
        #TempStringList is code segements split by 'create_item' or 'create_parm'
        for item in TempStringList:
            #item is segment of code
            CommentIndexStart=item.find('/*')
            CommentIndexEnd=item.find('*/')
            CodeString=item[0:CommentIndexStart]+item[CommentIndexEnd:-1]
            #search prm("StdForm", "20 um") and first "item"  prm(.*)
            StartIndex=CodeString.find('prm(')+4
            EndIndex=CodeString.find(')')
            DefaultString=CodeString[StartIndex:EndIndex]
            #search Parameter name lik "we"
            Words=re.split('"',CodeString)
            DeviceParameterList.append(Words[1])
        DeleteNullInList(DeviceParameterList)  #why there may be null exist in list
        return DeviceParameterList

def ParseCircuitAelofPath(DocPath):
    DeviceParameterListSet=[]
    FileList=RecursionFileInDoc(DocPath)
    FilterKeyword='ael'
    FilenameFilter(FileList,FilterKeyword)
    for file in FileList:
        DeviceParameterListSet.append(ParseCircuitAel(file))
    return DeviceParameterListSet


def DataStructureTransform(DeviceParaListSet):
    DeviceParaDictSet={}
    ListLen=len(DeviceParaListSet)
    i=0
    while(i<ListLen):
        try:
            item=DeviceParaListSet[i]
            DeviceName=item[0]
            ParaList=item[1:]
            DeviceParaDictSet.update({DeviceName:ParaList})
        except IndexError:
            pass
            return 'IndexError: out of range'
        i+=1
    return DeviceParaDictSet
#test code####################################################################
DocPath='D:/10000130/ADS_PDK/PDK/Sanan_BIHEMT/circuit/ael/'
ParseCircuitAelofPath(DocPath)

#3.CatInfo2Csv.py

#final data structure {'device':[{parameter1:type,default,min,max....},{parameter2:type=1,default},{parameter3:value3}]}
#DeviceDict like {'qbeb':{'we':[3,'2','1','10'],'le':[1,'4'],'Pins':['a','b','c']},
#                  'device2':{'we':[3,'2','1','10'],'nf':[3,'2','1','10'],'Pins':['a','b','c']}}
#                }
#DeviceParameterListSet like {'qbeb':['we','le'], 'device2':['we','nf'], }
#Output DeviceInfoListSet like {'device':[['we',3,'2','1','10'],['le',1,'4']]}
def SortInOrder(DeviceDict,DeviceParameterListSet):
    DeviceInfoListSet={}
    #intermedia variable
    TempDict={}
    for device in DeviceDict:
        try:
            ParameterDict=DeviceDict[device]
            ParameterList=DeviceParameterListSet[device]
            DeviceInfoList=[]
            for Parameter in ParameterList:
                try:
                    ValueListOfPara=ParameterDict[Parameter]
                    DeviceInfoList=[Parameter]+ValueListOfPara
                except IndexError:
                    pass
            DeviceInfoListSet[device]=DeviceInfoList 
        except IndexError:
            return 'Error: device name not match'
    return DeviceInfoListSet

#define sampling method
def SimplingInScope(METHOD,Scope,Nmax):
    #define output var
    SimplingList=[]
    #case by method
    if METHOD==1:
        pass
    else:    #default case Max Min Medium
        if len(Scope)==2:
            Delta=(Scope[0]+Scope[1])/(Nmax+1)
            i=0
            while(i<Nmax+2):
                SimplingList.append(Scop[0]+i*Delta)
                i+=1
            return SimplingList 
#!!!!Notice Generate Value type is String???


def Randomize(DeviceInfoListSet,Nmax): #Generate not more than Nmax
    #first get the list contain which parameter is randomizeable, scan all parameters
    for Device in DeviceInfoListSet:
        ParaListOfDevice=DeviceInfoListSet[Device] #format=[ParameterName,VarOrVal,Default,Min,Max]
        RandomizeIndexList=[]
        if ParaListOfDevice[1]==3 : #means Var not Val
            #simple and append the value to le Parameter List ['we',3,'2','1','10']->['we',3,'2','1','10','5','3'...]
        elif ParaListOfDevice[1]==1: # should complement parameter len to 3 like ['le',1,'4']->['le',1,'4','4','4']
            ParaListOfDevice+=[ParaListOfDevice[-1]]*Nmax
            DeviceInfoListSet[Device]=ParaListOfDevice
    return DeviceInfoListSet


def WriteCsvByDeviceInstance(CsvPath,DeviceInfoListSet):
    for Device in DeviceInfoListSet:

#Final Type: {'DeviceName':[[ParameterList,value1,value2..],[ParameterList,value1,value2..]...,[Location,x,y,dx,dy]]}


#4.AelCodeGernator.py

#output format :CodeRowList [[Code Segment1],[CodeSegement2]....]
#input format: DeviceInfoListSet{'Device':[[Parameter1],[Parameter2],....[Loaction]]}
#LibInfo=[ProcessLibName,LibName,LibCellName]
#Test Input: 
#DeviceInfoListSet={'RES_TFR':[['"Resistance"','"Resistance"','"Resistance"'],['"3 um"','"10 um"','"5 um"'],['"3 um"','"10 um"','"5 um"'],['""','""','""''],['"50 Ohm"','"50 Ohm"','"50 Ohm"],['"0"','"0"','"0"'],['"rt"','"rt"','"rt"'],[200,200,200,200]]}
#LibInfo=['"Sanan_P25ED"','"P25_ED"','"LayoutQA"']
#LayoutArraySetting=[1,5] #array cells by 1x5
def AelCodeGenerator(DeviceInfoListSet,LibInfo,LayoutArraySetting):
    #outpu definition
    CodeRowList=[]
    #Infomation May from input
    ProcessLibName=LibInfo[0]
    LibName=LibInfo[1]
    ADSCellName=LibInfo[2]
    #定义:需要与lib内容对应: 
    CodeDefinitionSegment=[]
    CodeDefinitionSegment.append('//definition code segment start:')
    CodeDefinitionSegment.append('decl processLibName="%s";'%ProcessLibName)
    CodeDefinitionSegment.append('decl libName="%s";'%LibName)
    CodeDefinitionSegment.append('decl cellName="%s";'%ADSCellName)
    CodeDefinitionSegment.append('//definition code segment end')
    CodeRowList.append(CodeDefinitionSegment)
    #cycle body 
    for Device in DeviceInfoListSet:
        #extract every type of device info from input
        DeviceInfoList=DeviceInfoListSet[Device]
        ParameterNum=len(DeviceInfoList)-1
        ParameterInfoList=DeviceInfoList[0:-1]
        dx=DeviceInfoList[-1][0]
        dy=DeviceInfoList[-1][1]
        colNum=LayoutArraySetting[1]
        DeviceName=Device
        LibCellName=ADSCellName #PDK lib里面定义的Cell的名字
        MaxNum=len(ParameterInfoList[0])  #device generate number
        #generate code for every device
        CodeRowListOfSingleDevice=[]
        CodeRowListOfSingleDevice.append('//%s code segment start:'%DeviceName)
        CodeRowListOfSingleDevice.append('decl dx = %f;'%dx)
        CodeRowListOfSingleDevice.append('decl dy = %f;'%dy)
        CodeRowListOfSingleDevice.append('decl colNum = %0.f;'%colNum)
        CodeRowListOfSingleDevice.append('decl deviceName="%s";'%DeviceName)
        CodeRowListOfSingleDevice.append('decl deviceArtworkFileName="%s";'%LibCellName)  #like P25ED_Scalable...
        CodeRowListOfSingleDevice.append('decl context = db_oa_create_empty_design(%s, %s, %s, 2);'%(LibName,ADSCellName,DeviceName))
        CodeRowListOfSingleDevice.append('de_show_context_in_new_window(context);')
        CodeRowListOfSingleDevice.append('decl i = 0;')
        CodeRowListOfSingleDevice.append('decl MaxNum=%0.f;'%MaxNum)
        CodeRowListOfSingleDevice.append('while(i<MaxNum){')
        #for every Device generate layout
        i=0 #i means 1st/2nd/3rd/4th....ith instance of device
        while(i<MaxNum):
            #extract info 
            CodeRowListOfSingleDevice.append('    decl itemName=strcat(%s,":",%s,":","layout");'%(ProcessLibName,LibCellName))
            CodeRowListOfSingleDevice.append('    decl itemInfo0LP = de_init_item(itemName);')
            CodeRowListOfSingleDevice.append('    de_place_item(itemInfo0LP, dx*(i%colNum), dy*(i/colNum));')
            CodeRowListOfSingleDevice.append('    //修改参数:参数必须对应')
            CodeRowListOfSingleDevice.append('    de_set_item_parameters(itemInfo0LP, list(')
            j=0   #j is the parameter No
            while(j<ParameterNum):
                CodeRowListOfSingleDevice.append('        prm_ex("Sanan_P25ED","StdForm","%s"),'%DeviceInfoList[j][i])
                j+=1
            CodeRowListOfSingleDevice.append('    de_end_edit_item(itemInfo0LP);')
            CodeRowListOfSingleDevice.append('    i+=1;')
            CodeRowListOfSingleDevice.append('}')
            i+=1
        #End of a device instance drawing
        CodeRowListOfSingleDevice.append('decl designName=strcat(%s,":", %s,":", %s);'%(LibName,ADSCellName,DeviceName))
        CodeRowListOfSingleDevice.append('de_save_oa_design(designName);')
        CodeRowListOfSingleDevice.append('de_close_window();')
        CodeRowListOfSingleDevice.append('//%s code segment end'%DeviceName)
        CodeRowList.append(CodeRowListOfSingleDevice)
    return CodeRowList


def WriteList2File(CodeRowList,FilePath):
    with open(FilePath,'w') as f: 
        SegmentNum=len(CodeRowList)
        iSegment=0
        while(iSegment<SegmentNum):
            CodeSegment=CodeRowList[iSegment]
            RowNum=len(CodeSegment)
            iRow=0
            while(iRow<RowNum):
                #write
                f.write(CodeRowList[iSegment][iRow])
                f.write('\n')
                iRow+=1
            iSegment+=1

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值