2021年6月22日 星期二

在Spyder開發演算法,再結合到AEDT當中

 AEDT編程環境不提供除錯的功能,如果算法牽涉到複雜的數學計算,可以先在Spyder當中完成,再將其整合到AEDT當中。以下是在一條線周圍等間距加上vias。因此我先定義線的點位置。在Spyder當中開發算法,並確認工作無誤才整合到AEDT 3D Layout當中。

# -*- coding: utf-8 -*-
"""
Created on Tue Jun 22 06:48:44 2021

@author: mlin
"""

from math import sin, cos, atan, pi, sqrt, degrees, acos
import matplotlib.pyplot as plt

plt.figure(figsize=(6, 6))

distance = 5
line = [(0, 0), (50, 0), (50, 50), (0, 50), (0, 10), (25, 25)]


def getAngle(v1, v2):
v1_mag = sqrt(v1[0] ** 2 + v1[1] ** 2)
v2_mag = sqrt(v2[0] ** 2 + v2[1] ** 2)
dotsum = v1[0] * v2[0] + v1[1] * v2[1]
if v1[0] * v2[1] - v1[1] * v2[0] > 0:
scale = 1
else:
scale = -1
dtheta = scale * acos(dotsum / (v1_mag * v2_mag))
print(v1, v2)
print(degrees(dtheta))

return dtheta


def getParalletLines(pts, distance):
leftline = []
rightline = []

x0, y0 = pts[0]
x1, y1 = pts[1]
vector = (x1 - x0, y1 - y0)
orientation1 = getAngle((1, 0), vector)

leftturn = orientation1 + pi / 2
righrturn = orientation1 - pi / 2
leftPt = (x0 + distance * cos(leftturn), y0 + distance * sin(leftturn))
leftline.append(leftPt)
rightPt = (x0 + distance * cos(righrturn), y0 + distance * sin(righrturn))
rightline.append(rightPt)

for n in range(1, len(pts) - 1):
print('hello')
x0, y0 = pts[n - 1]
x1, y1 = pts[n]
x2, y2 = pts[n + 1]

v1 = (x1 - x0, y1 - y0)
v2 = (x2 - x1, y2 - y1)
dtheta = getAngle(v1, v2)
orientation1 = getAngle((1, 0), v1)
print(degrees(dtheta))

leftturn = orientation1 + dtheta / 2 + pi / 2
righrturn = orientation1 + dtheta / 2 - pi / 2

distance2 = distance / sin((pi - dtheta) / 2)
leftPt = (x1 + distance2 * cos(leftturn), y1 + distance2 * sin(leftturn))
leftline.append(leftPt)
rightPt = (x1 + distance2 * cos(righrturn), y1 + distance2 * sin(righrturn))
rightline.append(rightPt)

x0, y0 = pts[-2]
x1, y1 = pts[-1]

vector = (x1 - x0, y1 - y0)
orientation1 = getAngle((1, 0), vector)
leftturn = orientation1 + pi / 2
righrturn = orientation1 - pi / 2
leftPt = (x1 + distance * cos(leftturn), y1 + distance * sin(leftturn))
leftline.append(leftPt)
rightPt = (x1 + distance * cos(righrturn), y1 + distance * sin(righrturn))
rightline.append(rightPt)
return leftline, rightline


def getLocations(line, gap):
location = [line[0]]
residual = 0

for n in range(len(line) - 1):
x0, y0 = line[n]
x1, y1 = line[n + 1]
length = sqrt((x1 - x0) ** 2 + (y1 - y0) ** 2)
dx, dy = (x1 - x0) / length, (y1 - y0) / length
x = x0 - dx * residual
y = y0 - dy * residual
length = length + residual
while length >= gap:
x += gap * dx
y += gap * dy
location.append((x, y))
length -= gap

residual = length

return location


plt.plot(*zip(*line), c='black', linewidth=3)
leftline, rightline = getParalletLines(line, 2)
plt.plot(*zip(*leftline), c='r')
plt.plot(*zip(*rightline), c='b')

locations = getLocations(rightline, 8)
plt.scatter(*zip(*locations), s=20)

locations = getLocations(leftline, 8)
plt.scatter(*zip(*locations), s=20)

plt.show()

(圖一) 平行線與Via圍牆


2021年6月16日 星期三

如何在不開啟AEDT執行電路模擬

之前介紹過在Command Window執行nexxim,速度快,缺點是sdf2csv只能轉出S parameter和時域資料。複雜一點的如Z parameter,眼圖統計等就沒辦法了。這邊的做法是將整個包含有netlist的AEDT檔案內容當成字串放在.py當中,修改字串當中的資料即可更改netlist設計或設定。將其輸出成.aedt檔再以ansysedt執行之後輸出所需資料即可。

run.bat

SET PATH=%PATH%;D:\Program Files\AnsysEM\AnsysEM21.1\Win64
ansysedt.exe -features=beta -ng -RunScriptAndExit .\run.py

run.py


text = r"""$begin 'AnsoftProject'
Created='Wed Jun 16 06:35:01 2021'
Product='ElectronicsDesktop'
FileOwnedByWorkbench=false
$begin 'Desktop'
Version(2021, 1)
InfrastructureVersion(1, 0)
$begin 'FactoryHeader'
$end 'FactoryHeader'
$end 'Desktop'
UsesAdvancedFeatures=false
NextUniqueID=0
MoveBackwards=false
$begin 'HFSSEnvironment'
Version(1, 0)
$end 'HFSSEnvironment'
$begin 'PlanarEMEnvironment'
Version(1, 0)
$end 'PlanarEMEnvironment'
$begin 'Q3DEnvironment'
Version(1, 0)
$end 'Q3DEnvironment'
$begin '2DExtractorEnvironment'
Version(1, 0)
$end '2DExtractorEnvironment'
$begin 'NexximEnvironment'
Version(1, 0)
$end 'NexximEnvironment'
$begin 'NexximNetlistEnvironment'
Version(1, 0)
$end 'NexximNetlistEnvironment'
$begin 'EmitEnvironment'
Version(1, 0)
$end 'EmitEnvironment'
$begin 'Maxwell3DEnvironment'
Version(1, 0)
$end 'Maxwell3DEnvironment'
$begin 'Maxwell2DEnvironment'
Version(1, 0)
$end 'Maxwell2DEnvironment'
$begin 'RMxprtEnvironment'
Version(1, 0)
$end 'RMxprtEnvironment'
$begin 'MaxCirEnvironment'
Version(1, 0)
$end 'MaxCirEnvironment'
$begin 'SimplorerEnvironment'
Version(1, 0)
$end 'SimplorerEnvironment'
$begin 'IcepakEnvironment'
Version(1, 0)
$end 'IcepakEnvironment'
$begin 'MechanicalEnvironment'
Version(1, 0)
$end 'MechanicalEnvironment'
$begin 'FilterDesignEnvironment'
$end 'FilterDesignEnvironment'
$begin 'SchematicEnvironment'
Version(1, 0)
$end 'SchematicEnvironment'
$begin 'geometry3deditor'
Version(1, 0)
$end 'geometry3deditor'
ReadVersion=8
$begin 'DesignMgrEnvironment'
CompInstCounter=1
GPortCounter=0
NetCounter=0
Alias('Ieee;Simplorer Elements\\Ieee', 'Std;Simplorer Elements\\Std', 'Basic_VHDLAMS;Simplorer Elements\\Basic Elements VHDLAMS\\Basic Elements VHDLAMS', 'Digital_Elements;Simplorer Elements\\Digital Elements\\Digital Elements', 'Transformations;Simplorer Elements\\Tools\\Transformations\\Transformations', 'HEV_VHDLAMS;Simplorer Elements\\HEV VHDLAMS\\HEV VHDLAMS', 'automotive_vda;Simplorer Elements\\VDALibs VHDLAMS\\automotive_vda', 'example_boardnet;Simplorer Elements\\VDALibs VHDLAMS\\example_boardnet', 'example_ecar;Simplorer Elements\\VDALibs VHDLAMS\\example_ecar', 'fundamentals_vda;Simplorer Elements\\VDALibs VHDLAMS\\fundamentals_vda', 'hybrid_emc_vda;Simplorer Elements\\VDALibs VHDLAMS\\hybrid_emc_vda', 'megma;Simplorer Elements\\VDALibs VHDLAMS\\megma', 'modelica_rotational;Simplorer Elements\\VDALibs VHDLAMS\\modelica_rotational', 'modelica_thermal;Simplorer Elements\\VDALibs VHDLAMS\\modelica_thermal', 'modelica_translational;Simplorer Elements\\VDALibs VHDLAMS\\modelica_translational', 'spice2vhd;Simplorer Elements\\VDALibs VHDLAMS\\spice2vhd', 'spice2vhd_devices;Simplorer Elements\\VDALibs VHDLAMS\\spice2vhd_devices', 'aircraft_electrical_vhdlams;Simplorer Elements\\Aircraft Electrical VHDLAMS\\Aircraft Electrical VHDLAMS', 'power_system_vhdlams;Simplorer Elements\\Power System VHDLAMS\\Power System VHDLAMS')
$end 'DesignMgrEnvironment'
$begin 'ProjectDatasets'
NextUniqueID=0
MoveBackwards=false
DatasetType='ProjectDatasetType'
$begin 'DatasetDefinitions'
$end 'DatasetDefinitions'
$end 'ProjectDatasets'
VariableOrders[0:]
$begin 'Definitions'
$begin 'Folders'
Definitions(1604, 10000, 1, 1, 0, false, false)
Materials(1604, 9500, 9, 2, 1, false, false)
'Surface Materials'(1604, 9501, 33503, 3, 1, false, false)
Scripts(1604, 9502, 33500, 4, 1, false, false)
Padstacks(1604, 9003, 12, 105, 1, false, false)
Symbols(1604, 9001, 10, 103, 1, false, false)
Footprints(1604, 9002, 11, 104, 1, false, false)
Bondwires(1604, 9006, 12, 108, 1, false, false)
Components(1604, 9000, 8, 102, 1, false, false)
Models(1604, 9004, 13, 106, 1, false, false)
Packages(1604, 9005, 33502, 107, 1, false, false)
$end 'Folders'
$begin 'Materials'
$end 'Materials'
$begin 'SurfaceMaterials'
$end 'SurfaceMaterials'
$begin 'Scripts'
$end 'Scripts'
$begin 'Symbols'
$begin 'CircuitNetlist1'
ModTime=1623796486
Library=''
ModSinceLib=false
LibLocation='Project'
HighestLevel=1
Normalize=true
InitialLevels(0, 1)
$begin 'Graphics'
Rect(0, 0, 0, 0, 0.00254, 0.00254, 0.00508, 0.00508, 0, 0, 0)
Rect(0, 1, 0, 0, 0.000423333333333333, 0.00254, 0.000423333333333333, 0.000423333333333334, 0, 0, 0)
$end 'Graphics'
$end 'CircuitNetlist1'
$end 'Symbols'
$begin 'DefInfo'
CircuitNetlist1(1002, 0, 17, 0, '', 1623796486, '', 'CircuitNetlist1', '', '', '', '', '', 'Design.bmp', '', 'Project', '', '', 1623796486, '', 0, 0)
$end 'DefInfo'
$begin 'Compdefs'
$begin 'CircuitNetlist1'
Library=''
CircuitEnv=0
Refbase='U'
NumParts=1
ModSinceLib=true
$begin 'Properties'
TextProp('Representation', 'SRD', '', 'CircuitNetlist1')
TextProp('Owner', 'SRD', '', 'Circuit Netlist')
$end 'Properties'
CompExtID=6
$end 'CircuitNetlist1'
$end 'Compdefs'
$end 'Definitions'
DesignIDServer=3
MoveBackwards=false
$begin 'NexximNetlist'
RepRewriteV2=true
Name='CircuitNetlist1'
DesignID=1
$begin 'DesignDatasets'
NextUniqueID=0
MoveBackwards=false
DatasetType='DesignDatasetType'
$begin 'DatasetDefinitions'
$end 'DatasetDefinitions'
$end 'DesignDatasets'
VariableOrders[0:]
Language='HSPICE'
$begin 'Netlist'
Text='* 0;Circuit1.sph\
**************************************************************************************************\
* Circuit Design netlist *\
* created by ANSYS Electronics Desktop *\
**************************************************************************************************\
\
.option PARHIER=\'local\'\
.option max_messages=1\
\
* begin toplevel circuit\
\
C1 Port1 Port2 1e-12\
RPort1 Port1 0 PORTNUM=1 RZ={0} IZ=0 \
.PORT Port1 0 1 RPort1 \
RPort2 Port2 0 PORTNUM=2 RZ={0} IZ=0 \
.PORT Port2 0 2 RPort2 \
\
* end toplevel circuit\
.LNA\
+ LIN 10 0 1000000000\
+ FLAG=\'LNA\'\
\
.end'
$end 'Netlist'
$begin 'OutputVariable'
NextUniqueID=0
MoveBackwards=false
$end 'OutputVariable'
$begin 'SolutionManager'
$begin 'SimDataExtractors'
$begin 'Version ID Map'
V=1
$end 'Version ID Map'
$end 'SimDataExtractors'
$begin 'Variations'
$end 'Variations'
$end 'SolutionManager'
IntegrationMethod='FFT'
InvisibleFlag=false
OwnerDesignInstance=0
OwnerSetup=''
OwnerSolutionID=0
DefaultSetupID=-1
$begin 'UserDefinedSolutionMgr'
NextUniqueID=1000000
MoveBackwards=false
$end 'UserDefinedSolutionMgr'
$begin 'DatasetSolutionMgr'
NextUniqueID=2000000
MoveBackwards=false
$end 'DatasetSolutionMgr'
Notes=$begin_cdata$ $end_cdata$
$begin 'AnimationSetups'
$end 'AnimationSetups'
CacheHeaderFile='HDR4E7B1498016237965015.tmp'
$end 'NexximNetlist'
$begin 'DataInstances'
DesignEditor='TopLevel'
Refdes('0', 'U1')
$begin 'CompInstances'
$begin 'Compinst'
ID='0'
Status='Status'
CompName='CircuitNetlist1'
GatesInUse()
$begin 'Properties'
TextProp('ID', 'SRID', '', '0')
$end 'Properties'
$end 'Compinst'
$end 'CompInstances'
$begin 'Instance'
DesignEditor='CircuitNetlist1'
ID='0'
$begin 'NexximNetlist'
DesignInstanceID=2
$begin 'WindowPosition'
$begin 'EditorWindow'
Netlist(Netlist(View(WindowPos(3, -1, -1, -9, -38, 32, 32, 1231, 390))))
$end 'EditorWindow'
$end 'WindowPosition'
$begin 'ReportSetup'
$begin 'ReportManager'
$begin 'Reports'
$end 'Reports'
NextUniqueID=0
MoveBackwards=false
$begin 'NextVersID'
NextUniqueID=0
MoveBackwards=false
$end 'NextVersID'
$end 'ReportManager'
$begin 'Reports'
$end 'Reports'
$begin 'ReportsWindowInfoList'
$end 'ReportsWindowInfoList'
$end 'ReportSetup'
$begin 'Properties'
$end 'Properties'
$begin 'UserDefinedDocument'
$begin 'Data'
$end 'Data'
$end 'UserDefinedDocument'
$end 'NexximNetlist'
$end 'Instance'
$begin 'SODInfo'
$end 'SODInfo'
$end 'DataInstances'
$begin 'WBSystemIDToDesignInstanceIDMap'
$end 'WBSystemIDToDesignInstanceIDMap'
$begin 'WBSysIDSysDetails'
$end 'WBSysIDSysDetails'
$begin 'WBConnIDConnDetails'
$end 'WBConnIDConnDetails'
$begin 'WBMaterialGuidDetails'
WBMaterialGuidMap()
$end 'WBMaterialGuidDetails'
$begin 'MinervaProjectSettingsBlk'
MinervaRemoteFilePath=''
FolderContainerString=''
$end 'MinervaProjectSettingsBlk'
$end 'AnsoftProject'
$begin 'AllReferencedFilesForProject'
$end 'AllReferencedFilesForProject'
$begin 'ProjectPreview'
IsEncrypted=false
Thumbnail64=''
$begin 'DesignInfo'
DesignName='CircuitNetlist1'
Notes=''
Factory='Circuit Netlist'
IsSolved=false
'Nominal Setups'[0:]
'Nominal Setup Types'[0:]
'Optimetrics Setups'[0:]
'Optimetrics Experiment Types'[0:]
Image64=''
$end 'DesignInfo'
$end 'ProjectPreview'
"""
with open('d:/demo/x5.aedt', 'w') as f:
f.write(text.format(50))

oDesktop.OpenProject("D:/demo/x5.aedt")
oProject = oDesktop.SetActiveProject("x5")
oDesign = oProject.SetActiveDesign("CircuitNetlist1")
oDesign.AnalyzeAll()
oModule = oDesign.GetModule("ReportSetup")
oModule.CreateReport("Z Parameter Plot 1", "Standard", "Rectangular Plot", "LNA",
[
"NAME:Context",
"SimValueContext:=" , [3,0,2,0,False,False,-1,1,0,1,1,"",0,0]
],
[
"Freq:=" , ["All"]
],
[
"X Component:=" , "Freq",
"Y Component:=" , ["dB(Z(1,1))","dB(Z(2,1))","dB(Z(1,2))","dB(Z(2,2))"]
])
oModule.ExportToFile("Z Parameter Plot 1", "D:/demo/sss.csv", False)


2021年6月15日 星期二

DataGridView資料儲存與載入

 按鈕將資料保存到Json檔案當中,下次執行程式自動載入。

def Form1_Load(self, sender, e):
try:
with open('./data.json') as f:
data = json.load(f)
AddWarningMessage(str(data))
for i in data:
self.dataGridView1.Rows.Add(*i)
except:
return None


def button1_Click(self, sender, e):
data = []
try:
for i in range(len(self.dataGridView1.Rows)):
data.append([])
for j in range(len(self.dataGridView1.Rows[i].Cells)):
x = self.dataGridView1.Rows[i].Cells[j].Value
if j == 3:
data[i].append(True if x else False)
continue
if not string.IsNullOrEmpty(x):
data[i].append(x)
else:
data[i].append("")
except:
raise
with open('./data.json', 'w') as f:
json.dump(data, f)



2021年6月10日 星期四

如何將.sdf.csv檔轉成sNp檔

如何利用Python呼叫nexxim.exe執行電路模擬當中,我們介紹了如何在command line環境執行nexxim.exe完成電路網表模擬。如果網表做的是S參數模擬,該如何將輸出的.sdf.csv檔轉成S參數檔案?以下代碼即可將.sdf.csv轉成.sNp檔:

with open ('netlist.cir.sdf.csv') as f:
header = next(f)
N = int(math.sqrt(((len(header.split(','))-2)/2)))
with open('result.s{}p'.format(N), 'w') as fsnp:
fsnp.writelines('# Hz S RI R 50.000000\n\n')
for line in f:
data = line.split(',')
fsnp.write(' '.join(data[1:]))

2021年6月9日 星期三

3D Layout 輸出到Q3D並加上Source/Sink

目前版本3D Layout輸出到Q3D是沒有Source/Sink設定的,這個腳本可以讓使用者定義Source/Sink並輸出到Q3D當中。到下面連結下載ExportLayoutQ3D.py

https://github.com/linmingchih/HowtoSim_Script/tree/master/2021

(圖一)使用者定義Source/Sink

更改線寬的腳本

可選擇特定層,輸入關鍵字,便可顯示符合條件的走線並更改線寬。可至下面連結下載Python原始碼changeLineWidth.py:

https://github.com/linmingchih/HowtoSim_Script/tree/master/2021

(圖一)更改特定層nets的線寬


2021年6月5日 星期六

如何將圖片嵌到程式碼當中

當我們要在GUI上面放上一些圖片檔,要另外提供.png檔實在是一件麻煩的事。如果可以將圖片放在Python檔裡面就可以只要提供一個檔案即可,這可以透過Base64機制達成。首先將PNG檔轉成Base64字串,很多的網站都有提供這個功能。再將字串插入到Python程式當中。等到在AEDT執行時將字串還原成圖片即可。

import base64

base64_img = '''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
AAAAAAAAAAAAAAAAAAAAAAAH//2Q=='''

base64_img_bytes = base64_img.encode('utf-8')
with open('d:/demo/ANSYS_Logo.png', 'wb') as file_to_save:
decoded_image_data = base64.b64decode(base64_img_bytes)
file_to_save.write(decoded_image_data)

(圖一)字串還原的圖片


2021年6月4日 星期五

用logging取代AddWarningMessage()來Debug腳本

AddWarningMessage雖然可以直接輸出抓取的訊息,但是message視窗小字也小。如果資料量大要再做處理也不容易。用logging模組可以解決這個問題。印到log檔案的訊息可以在文字編輯器或Spyder當中打開檢視。一邊看代碼,一邊看輸出結果。複雜的資料只要做簡單的處理便可以在變數表單打開或是畫成圖表方便檢視,另外要比較代碼修改前後資料結構改變也很容易,因為logging模組預設輸出資料會附加到log檔當中,而非覆蓋。使用logging很簡單,只要一開始設定好logging如下:

import logging
FORMAT = '%(asctime)s %(levelname)s: %(message)s' logging.basicConfig(filename='simulation.log', encoding='utf-8', filemode='w', level=logging.DEBUG, format=FORMAT)

之後用logging.info()就可以將資料丟到log檔案中即可。

if __name__ == '__main__':
oDesktop.ClearMessages("", "", 2)
logging.info('-'*80+'\n')
logging.info(getLayerElevation())
logging.info(getComponentElevation())
logging.info(getComponentElevation())
logging.info(getPinInfo())
logging.info(getListViewInfo())
(圖一) 在Spyder當中一個頁面寫script,一個頁面檢查輸出結果

2021年6月2日 星期三

如何找到特殊符號用於表單設計

在GUI設計時,想要加入特殊字元,可以在工具列搜尋char,即可找到字元對應表,在上面編輯字串之後就可以複製到表單之中。

(圖一)字元對應表


(圖二)特殊字串