在 IPKISS 中导出/导入 GDSⅡ 文件

在 IPKISS 中如何导出 GDSⅡ 版图?不是在 IPKISS 上设计的 GDSⅡ 版图文件要怎么复用?

本篇教程将会展示:

将一个光栅耦合器输出为 GDSⅡ 版图

1.  导入所需的 PDK 库以及 IPKISS 函数库等。此示例中,使用的是 Luceda academy 自带的示例 PDK:si_fab
from si_fab import all as pdk 
from ipkiss3 import all as i3
import numpy as np
import pylab as plt
注意
开始版图设计之前,需要先导入 PDK 库。
2. 调用已有器件库中的器件并输出为 GDSⅡ 文件
  (1)  从 Picazzo 通用器件库中调用一个光纤光栅耦合器:FiberCouplerCurvedGrating
from picazzo3.fibcoup.curved.cell import FiberCouplerCurvedGrating

【在 Luceda IPKISS 中有三种器件设计的方式】
  • 从不同流片厂的 pdk 中调用已有器件,具体可查看相应的all.py文件
  • 从 IPKISS 内置的通用器件库Picazzo中调用现有器件(本案例所采用的方式)
  • 通过参数化单元i3.PCell自定义器件(包括器件属性+布局视图+网表视图+行为模型视图)

(2)  创建并输出 GDSⅡ 文件
给调用的器件定义唯一名称unique_grating_name_used_in_GDSII,并对其实例化,通过write_gdsii函数将实例化的光纤光栅耦合器输出为 GDSⅡ 文件,文件名为my_grating.gds
my_grating = FiberCouplerCurvedGrating(
    name = "unique_grating_name_used_in_GDSⅡ" 
)
my_grating_layout = my_grating.Layout()  
my_grating_layout_ports = my_grating_layout.ports 
my_grating_layout.visualize()
my_grating_layout.write_gdsii("my_grating.gds")
(3) 定义光栅耦合器的仿真模型
i3.CompactModel生成光栅耦合器的紧凑型模型,需要定义以下属性及方法:
  • 定义该紧凑型模型所需要的所有参数parameters(包括:用来计算散射矩阵或频率响应、时间响应等参数),还可以提供参数的默认值。在光栅耦合器中需要定义 3dB 带宽、传输谱峰值、中心波长、反射率。
  • 定义期间的端口terms(注意区别于布局视图i3.Layoutview下需要构建器件交互端口时所用到的i3.OpticalPort)。在光栅耦合器中包含两个端口,一个是与光纤垂直耦合的端口vertical_in,一个是与波导连接的输入端口in
  • 定义计算散射矩阵的方法:calculate_smatrix。由于光栅耦合器是一个具有固定反射参数的简单高斯模型,因此有以下关系:
class GratingModel(i3.CompactModel):
    parameters = [
        "bandwidth_3dB",
        "peak_transmission",
        "center_wavelength",
        "reflection",
    ]
    terms = [
        i3.OpticalTerm(name="in"),
        i3.OpticalTerm(name="vertical_in"),
    ]
    def calculate_smatrix(parameters, env, S):
        sigma = parameters.bandwidth_3dB / 2.35482
        power_S = parameters.peak_transmission * np.exp(
            -((env.wavelength - parameters.center_wavelength) ** 2.0 / (2.0 * sigma ** 2.0))
        )
        S["vertical_in","in"] = S["in","vertical_in"] = np.sqrt(power_S)
        S["in","in"] = parameters.reflection

导入 GDSⅡ 版图

1.  使用i3.GDSCell导入 GDSⅡ 文件   
定义一个继承自i3.GDSCell的类ImportedGrating,其作用类似于用i3.PCell来定义器件。
class ImportedGrating(i3.GDSCell):
    def _default_filename(self):
        return "my_grating.gds" # gdsii 文件的路径,该文件包含要导入的单元

    def _default_cell_name(self):
        return "unique_grating_name_used_in_GDSII" # 要导入 gdsii 文件中的单元名称
2. 构建布局视图 
由于导入的 GDSCell 还没有端口信息,所以我们需要先在class ImportedGrating下构建布局视图,给器件添加端口。
class Layout(i3.GDSCell.Layout):
    # 导入的GDS已经包含视图属性及器件基本形状,因此省去了定义property及_generate_elements的步骤
    def _generate_ports(self, ports):
        ports += i3.OpticalPort(
            name = "in",
            position = (20.0, 0.0),
            angle = 0.0,
        )   # 需要手动设置端口,因为gdsii文件中还没有此信息
        ports += i3.VerticalOpticalPort(
            name = "vertical_in",
            position = (0.0, 0.0),
            inclination = 90.0, # 轨道倾角,垂直耦合
            angle = 0.0,
        )
        return ports
3. 构建行为模型视图
为了对导入的GDSCell 进行器件/线路仿真 ,我们还需要在class ImportedGrating 下构建行为模型视图,这里使用_generate_model方法调用前面定义的紧凑型模型来生成CircuitModel
class CircuitModel(i3.CircuitModelView):
    center_wavelength = i3.PositiveNumberProperty(default=1.55, doc = "center wavelength[um]")
    bandwidth_3dB = i3.PositiveNumberProperty(default=0.060, doc = "3dB bamdwidth[um]")
    peak_transmission = i3.NonNegativeNumberProperty(default=1.0, doc = "peak transmission (0 to 1)")
    reflection = i3.ComplexFractionProperty(default=0.0, doc = "Complex reflection back into the waveguide")

    def _generate_model(self):
        return GratingModel(
            center_wavelength = self.center_wavelength,
            bandwidth_3dB = self.bandwidth_3dB,
            peak_transmission = self.peak_transmission,
            reflection = self.reflection,
        )

实例化导入的 GDSCell

定义后的 GDSCell 和 PCell 一样,可以被调用、实例化,用于绘制更复杂的线路版图,还可以进行线路仿真。
1. 实例化、可视化版图
# 实例化导入的光栅耦合器的布局视图
grating_cell = ImportedGrating()
grating_lv = grating_cell.Layout()
grating_lv.visualize(annotate = True)
2. 线路仿真
# 实例化导入的光栅耦合器的线路模型视图并进行线路仿真
grating_cm = grating_cell.CircuitModel(bandwidth_3dB=0.1, peak_transmission=0.6)
wavelengths = np.linspace(1.5, 1.6, 51)
S = grating_cm.get_smatrix(wavelengths=wavelengths)
plt.plot(wavelengths, np.abs(S["vertical_in","in"]) ** 2, '-', linewidth=2.2)
plt.xlabel('Wavelength [um]', fontsize=16)
plt.ylabel('Transmission [dB]', fontsize=16)
plt.show()

完整代码

from si_fab import all as pdk 
from ipkiss3 import all as i3
import numpy as np
import pylab as plt
# 1.将已有的设计导出为GDSⅡ格式文件
from picazzo3.fibcoup.curved.cell import FiberCouplerCurvedGrating

my_grating = FiberCouplerCurvedGrating(
    name = "unique_grating_name_used_in_GDSII" 
)
my_grating_layout = my_grating.Layout() 
my_grating_layout_ports = my_grating_layout.ports 
my_grating_layout.visualize()
my_grating_layout.write_gdsii("my_grating.gds")

class GratingModel(i3.CompactModel):
    parameters = [
        "bandwidth_3dB",
        "peak_transmission",
        "center_wavelength",
        "reflection",
    ]
    terms = [
        i3.OpticalTerm(name="in"),
        i3.OpticalTerm(name="vertical_in"),
    ]
    def calculate_smatrix(parameters, env, S):
        sigma = parameters.bandwidth_3dB / 2.35482
        power_S = parameters.peak_transmission * np.exp(
            -((env.wavelength - parameters.center_wavelength) ** 2.0 / (2.0 * sigma ** 2.0))
        )
        S["vertical_in","in"] = S["in","vertical_in"] = np.sqrt(power_S)
        S["in","in"] = parameters.reflection
# 2.将生成的GDSⅡ文件导入IPKISS中
class ImportedGrating(i3.GDSCell):
    def _default_filename(self):
        return "my_grating.gds" 

    def _default_cell_name(self):
        return "unique_grating_name_used_in_GDSII"  

    class Layout(i3.GDSCell.Layout):
      
        def _generate_ports(self, ports):
            ports += i3.OpticalPort(
                name = "in",
                position = (20.0, 0.0),
                angle = 0.0,
            )  
            ports += i3.VerticalOpticalPort(
                name = "vertical_in",
                position = (0.0, 0.0),
                inclination = 90.0, 
                angle = 0.0,
            )
            return ports
    class CircuitModel(i3.CircuitModelView):
        center_wavelength = i3.PositiveNumberProperty(default=1.55, doc = "center wavelength[um]")
        bandwidth_3dB = i3.PositiveNumberProperty(default=0.060, doc = "3dB bamdwidth[um]")
        peak_transmission = i3.NonNegativeNumberProperty(default=1.0, doc = "peak transmission (0 to 1)")
        reflection = i3.ComplexFractionProperty(default=0.0, doc = "Complex reflection back into the waveguide")

        def _generate_model(self):
            return GratingModel(
                center_wavelength = self.center_wavelength,
                bandwidth_3dB = self.bandwidth_3dB,
                peak_transmission = self.peak_transmission,
                reflection = self.reflection,
            )
# 3. 使用“布局视图”、“行为模型视图”实例化导入的GDS Cell
grating_cell = ImportedGrating()
grating_lv = grating_cell.Layout()
grating_lv.visualize(annotate = True)

grating_cm = grating_cell.CircuitModel(bandwidth_3dB=0.1, peak_transmission=0.6)
wavelengths = np.linspace(1.5, 1.6, 51)
S = grating_cm.get_smatrix(wavelengths=wavelengths)
plt.plot(wavelengths, np.abs(S["vertical_in","in"]) ** 2, '-', linewidth=2.2)
plt.xlabel('Wavelength [um]', fontsize=16)
plt.ylabel('Transmission [dB]', fontsize=16)
plt.show()
参考文档:Luceda 官方技术文档:Creating a Cell from an Existing GDSII 
2023-06-26
0