概述
#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
最后
以上就是勤恳蜜蜂为你收集整理的EDA Tool的全部内容,希望文章能够帮你解决EDA Tool所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复