突破GDS文件元数据兼容性壁垒:从设计到制造的全流程解决方案

突破GDS文件元数据兼容性壁垒:从设计到制造的全流程解决方案

【免费下载链接】gdsfactory python library to design chips (Photonics, Analog, Quantum, MEMs, ...), objects for 3D printing or PCBs. 【免费下载链接】gdsfactory 项目地址: https://gitcode.com/gh_mirrors/gd/gdsfactory

引言:GDS元数据兼容性的隐形挑战

你是否曾在芯片设计流程中遭遇过这些困境?团队协作时,旧版本GDS文件导入后端口信息神秘消失;流片前检查发现关键参数在不同工具间传递时发生畸变;甚至同一份设计文件在不同PDK版本中表现出截然不同的行为。这些令人沮丧的现象背后,隐藏着GDS(GDSII Stream Format,GDSII流格式)文件元数据(Metadata)兼容性的深层挑战。

作为芯片设计的通用语言,GDS文件不仅承载着几何图形信息,还通过元数据记录了从设计参数到制造约束的关键信息。然而,元数据标准的模糊性、工具实现的差异性以及版本迭代带来的API变更,共同构成了阻碍设计流畅传递的"隐形壁垒"。本文将系统剖析GDS元数据兼容性问题的根源,提供从检测、规避到解决的全流程方法论,并通过gdsfactory项目的实战案例,展示如何构建鲁棒的元数据管理体系,确保你的设计从概念到硅片的无缝衔接。

读完本文,你将获得:

  • 对GDS元数据结构的深度理解,包括其在gdsfactory中的实现方式
  • 识别和诊断元数据兼容性问题的实用工具与技术
  • 跨版本、跨工具元数据兼容的10条黄金法则
  • 针对历史项目迁移和未来设计的元数据管理最佳实践
  • 完整的gdsfactory元数据兼容性保障代码框架

GDS元数据架构与兼容性痛点解析

GDS元数据的双重生命周期

GDS元数据在芯片设计中经历着从"创建-传递-解析"的完整生命周期,每个阶段都可能引入兼容性风险:

mermaid

在gdsfactory中,元数据通过Component.write_gds()方法写入,核心实现如下:

def write_gds(
    self,
    gdspath: PathType | None = None,
    gdsdir: PathType | None = None,
    save_options: kdb.SaveLayoutOptions | None = None,
    with_metadata: bool = True,  # 控制元数据写入
    exclude_layers: Sequence[LayerSpec] | None = None,
) -> pathlib.Path:
    # ... 省略其他代码 ...
    if not with_metadata:
        save_options.write_context_info = False  # 禁用元数据写入
    
    self.write(filename=gdspath, save_options=save_options)
    return pathlib.Path(gdspath)

with_metadata标志控制是否将组件的设置(settings)和端口(ports)信息写入GDS文件。当设置为True时,gdsfactory会将这些信息编码为GDSII格式的上下文信息(context info),以便后续工具读取和解析。

元数据兼容性问题的三大根源

1. 数据结构差异

不同工具对元数据的编码和解码方式存在显著差异,导致信息传递失真。gdsfactory采用JSON格式序列化元数据:

def clean_value_json(value: Any) -> Any:
    """将对象序列化为JSON兼容格式"""
    if isinstance(value, pydantic.BaseModel):
        return clean_dict(value.model_dump(exclude_none=True))
    elif isinstance(value, np.ndarray):
        return orjson.loads(orjson.dumps(value, option=orjson.OPT_SERIALIZE_NUMPY))
    # ... 处理其他类型 ...
    else:
        try:
            return orjson.loads(orjson.dumps(value, default=clean_value_json))
        except TypeError as e:
            print(f"Error serializing {value!r}")
            raise e

而某些传统EDA工具可能使用自定义二进制格式或简化的键值对结构,当导入gdsfactory生成的GDS文件时,可能无法正确解析复杂嵌套的元数据结构。

2. API版本变更

gdsfactory的版本迭代引入了元数据处理机制的变化,如v8版本中的重大变更:

- add `Component.write_gds(with_metadata=True)` flag and deprecate `Component.write_gds_with_metadata()` [PR#1668]
- default read_metadata=False in import_gds
- add `read_metadata` flag to `gf.read.import_gds`

这些变更意味着使用旧版API写入的元数据可能无法被新版工具正确读取,反之亦然。例如,在v8之前,元数据写入通过独立方法write_gds_with_metadata()实现,而在v8及之后,这一功能被整合到write_gds()方法中,通过with_metadata参数控制。

3. 元数据范围不明确

gdsfactory支持多层级元数据结构,包括组件自身的设置、子组件的引用信息以及制造相关的附加数据:

def add_label_ehva(
    component: gf.Component,
    die: str = "demo",
    metadata_ignore: list[str] | None = None,
    metadata_include_parent: list[str] | None = None,
    metadata_include_child: list[str] | None = None,
) -> gf.Component:
    # ... 省略其他代码 ...
    metadata = component.settings
    info += [
        f"CIRCUITINFO NAME: {k}, VALUE: {v}"
        for k, v in metadata
        if k not in metadata_ignore and isinstance(v, int | float | str)
    ]
    
    # 包含父组件元数据
    metadata = component.settings
    info += [
        f"CIRCUITINFO NAME: {clean_name(k)}, VALUE: {metadata.get(k)}"
        for k in metadata_include_parent
        if metadata.get(k)
    ]
    
    # 包含子组件元数据
    metadata = component.settings
    info += [
        f"CIRCUITINFO NAME: {k}, VALUE: {metadata.get(k)}"
        for k in metadata_include_child
        if metadata.get(k)
    ]
    # ... 省略其他代码 ...

这种灵活性虽然强大,但也带来了兼容性挑战——不同工具对元数据层级的理解可能存在差异,导致部分信息被忽略或误读。

元数据兼容性问题的诊断与定位

兼容性问题的四大症状与诊断流程

GDS元数据兼容性问题通常表现为以下四种症状,每种症状对应特定的诊断方法:

症状可能原因诊断工具解决难度
端口信息丢失元数据未写入或解析错误get_ports_list()★☆☆☆☆
仿真参数不匹配数据类型转换错误to_dict() + 类型检查★★☆☆☆
子组件信息缺失递归元数据未启用get_netlist(recursive=True)★★★☆☆
完全无法解析版本不兼容或格式错误gf.diff() + 元数据对比★★★★☆
1. 端口信息丢失诊断

当导入GDS文件后发现端口信息丢失,可通过以下步骤诊断:

import gdsfactory as gf

# 读取GDS文件
c = gf.read.import_gds("problematic.gds", read_metadata=True)

# 检查端口是否存在
print("端口数量:", len(c.ports))
if not c.ports:
    # 尝试强制读取元数据
    c = gf.read.import_gds("problematic.gds", read_metadata=True, lazy=False)
    print("强制读取后端口数量:", len(c.ports))
    
    # 检查文件是否包含元数据块
    with open("problematic.gds", "rb") as f:
        content = f.read().hex()
        if "47445346" not in content:  # GDSII文件头标记
            print("不是有效的GDSII文件")
        elif "6D657461" not in content:  # "meta"字符串的十六进制
            print("文件中未找到元数据块")
2. 元数据版本兼容性检查

gdsfactory提供了版本迁移指南,可通过检查CHANGELOG识别潜在的兼容性问题:

def check_metadata_compatibility(gdspath, target_version="9.0.0"):
    """检查GDS文件元数据与目标版本的兼容性"""
    import re
    from gdsfactory.config import __version__
    
    # 读取文件创建时的版本信息
    c = gf.read.import_gds(gdspath, read_metadata=True)
    created_version = c.metadata.get("gdsfactory_version", "unknown")
    
    # 检查主要版本差异
    if created_version.split(".")[0] != target_version.split(".")[0]:
        print(f"主要版本不兼容: 创建于v{created_version}, 目标v{target_version}")
        
        # 查找迁移指南
        with open("CHANGELOG.md") as f:
            changelog = f.read()
            migration_section = re.search(
                rf"v{created_version}.*?v{target_version}(.*?)##", 
                changelog, 
                re.DOTALL
            )
            if migration_section:
                print("需要的迁移步骤:")
                print(migration_section.group(1))

元数据兼容性测试框架

为确保元数据在不同场景下的兼容性,建议构建如下测试框架:

import pytest
import gdsfactory as gf
from pathlib import Path

@pytest.mark.parametrize("version", ["8.0.0", "8.5.0", "9.0.0"])
def test_metadata_compatibility(version, tmpdir):
    """测试不同版本间的元数据兼容性"""
    # 1. 使用指定版本创建并写入带元数据的GDS
    c = gf.components.straight(length=10, width=0.5)
    gdspath = Path(tmpdir) / "test.gds"
    c.write_gds(gdspath, with_metadata=True)
    
    # 2. 模拟不同版本的读取过程
    if version < "9.0.0":
        # 旧版本使用独立的元数据读取方法
        c_read = gf.read.import_gds(gdspath, read_metadata=True)
    else:
        # 新版本默认禁用元数据读取,需显式启用
        c_read = gf.read.import_gds(gdspath, read_metadata=True)
    
    # 3. 验证关键元数据是否保留
    assert c_read.settings["length"] == 10, f"版本{version}长度参数不匹配"
    assert c_read.settings["width"] == 0.5, f"版本{version}宽度参数不匹配"
    assert len(c_read.ports) == 2, f"版本{version}端口信息丢失"

兼容性保障策略与最佳实践

元数据兼容性设计的10条黄金法则

基于gdsfactory的实践经验,我们总结出确保GDS元数据兼容性的10条黄金法则:

  1. 版本显式化:始终在元数据中包含创建版本信息

    def write_gds_with_version(self, gdspath, **kwargs):
        self.metadata["gdsfactory_version"] = gf.__version__
        return self.write_gds(gdspath, **kwargs)
    
  2. 类型严格化:使用标准化数据类型,避免复杂对象

    # 推荐
    self.metadata["width"] = float(width)  # 明确类型
    
    # 避免
    self.metadata["cross_section"] = cross_section  # 复杂对象
    
  3. 结构扁平化:深度不超过3层,便于所有工具解析

    # 推荐
    self.metadata["sim_settings_wavelength"] = 1.55
    self.metadata["sim_settings_temperature"] = 300
    
    # 避免
    self.metadata["sim_settings"] = {"wavelength": 1.55, "temperature": 300}
    
  4. 键名标准化:使用全小写+下划线命名法,避免特殊字符

    # 推荐
    self.metadata["bend_radius"] = 10.0
    
    # 避免
    self.metadata["Bend Radius!"] = 10.0
    
  5. 默认值显式化:始终包含关键参数的默认值

    def add_metadata(self, **kwargs):
        defaults = {"length": 10.0, "width": 0.5, "layer": (1, 0)}
        defaults.update(kwargs)
        self.metadata.update(defaults)
    
  6. 兼容性标记:为非标准元数据添加工具特定标记

    # 标准元数据
    self.metadata["pitch"] = 25.0
    
    # 工具特定元数据,添加前缀
    self.metadata["klayout_grid_size"] = 0.001
    self.metadata["lumerical_mesh_accuracy"] = 2
    
  7. 冗余备份:关键元数据同时以标签形式写入GDS

    def write_critical_metadata(self):
        # 写入元数据字典
        self.metadata["fiber_spacing"] = 127.0
    
        # 同时写入GDS标签作为备份
        self.add_label(
            text=f"FIBER_SPACING:127.0",
            position=(0, 0),
            layer=(200, 0)  # 专用元数据层
        )
    
  8. 最小化原则:只包含必要信息,避免元数据膨胀

    # 推荐:只包含制造和仿真必需的参数
    essential_metadata = {k: v for k, v in all_metadata.items() 
                         if k in ["length", "width", "layer", "pitch"]}
    self.metadata = essential_metadata
    
  9. 文档关联:元数据键与文档保持一致,便于追溯

    # 元数据键与文档章节对应
    self.metadata["taper_length"] = 10.0  # 对应文档 §3.2.1 锥形长度
    self.metadata["grating_period"] = 0.7  # 对应文档 §4.1 光栅周期
    
  10. 向后兼容:预留扩展字段,避免未来变更

    # 当前版本使用的字段
    self.metadata["version"] = 1
    self.metadata["params_v1"] = {"length": 10.0, "width": 0.5}
    
    # 预留未来扩展字段
    self.metadata["params_v2"] = {}
    self.metadata["extension_fields"] = {}
    

跨版本迁移策略

当需要将旧版本设计迁移至新版本gdsfactory时,可采用以下策略:

1. 元数据升级工具
def upgrade_metadata(old_gds_path, new_gds_path):
    """将旧版本元数据升级至新版本格式"""
    # 1. 读取旧版本GDS,禁用元数据自动解析
    c = gf.read.import_gds(old_gds_path, read_metadata=False)
    
    # 2. 手动解析旧格式元数据(假设存储在特定层的标签中)
    labels = c.get_labels(layer=(200, 0))  # 旧版元数据层
    old_metadata = {}
    for label in labels:
        key, value = label.text.split(":")
        old_metadata[key.lower()] = float(value)
    
    # 3. 转换为新版本元数据格式
    new_metadata = {
        "gdsfactory_version": gf.__version__,
        "original_version": "7.0.0",
        "parameters": old_metadata,
        "migration_date": str(datetime.now())
    }
    
    # 4. 写入新版本GDS
    c.metadata = new_metadata
    c.write_gds(new_gds_path, with_metadata=True)
    return c
2. 兼容性垫片(Shim)实现

对于无法立即升级的大型项目,可实现兼容性垫片:

def import_legacy_gds(gdspath):
    """导入旧版本GDS并提供兼容性接口"""
    c = gf.read.import_gds(gdspath, read_metadata=True)
    
    # 为旧版元数据键提供别名
    if "w" in c.metadata and "width" not in c.metadata:
        c.metadata["width"] = c.metadata["w"]
    
    # 模拟旧版API方法
    def get_ports_by_type_old(port_type):
        return c.get_ports_list(port_type=port_type)
    
    c.get_ports_by_type = get_ports_by_type_old
    return c

gdsfactory元数据兼容性实战案例

案例1:跨版本元数据迁移

某光子芯片项目需要从gdsfactory v7迁移至v9,面临元数据格式变更问题。通过以下步骤实现平滑迁移:

  1. 评估影响范围

    # 分析项目中使用元数据的组件类型
    import glob
    
    gds_files = glob.glob("library/**/*.gds", recursive=True)
    affected_components = set()
    
    for gds in gds_files:
        c = gf.read.import_gds(gds, read_metadata=False)
        labels = c.get_labels(layer=(200, 0))  # 旧版元数据层
        if labels:
            affected_components.add(c.name)
    
    print(f"发现{len(affected_components)}个使用旧版元数据的组件")
    
  2. 批量迁移脚本

    def batch_migrate_metadata(input_dir, output_dir):
        """批量迁移目录中所有GDS文件的元数据"""
        output_dir = Path(output_dir)
        output_dir.mkdir(exist_ok=True)
    
        for gds_path in Path(input_dir).glob("*.gds"):
            c = gf.read.import_gds(gds_path, read_metadata=False)
    
            # 读取旧版标签元数据
            labels = c.get_labels(layer=(200, 0))
            metadata = {}
            for label in labels:
                if ":" in label.text:
                    key, value = label.text.split(":", 1)
                    metadata[key.lower()] = value
    
            # 添加版本信息
            metadata["gdsfactory_version"] = gf.__version__
            metadata["migration_source"] = "v7"
    
            # 更新组件元数据
            c.metadata = metadata
    
            # 写入新版本GDS
            output_path = output_dir / gds_path.name
            c.write_gds(output_path, with_metadata=True)
            print(f"迁移完成: {gds_path.name}")
    
  3. 验证与回滚机制

    def verify_migration(original_dir, migrated_dir):
        """验证迁移后元数据的完整性"""
        report = {"passed": [], "failed": [], "warnings": []}
    
        for gds_path in Path(original_dir).glob("*.gds"):
            original = gf.read.import_gds(gds_path, read_metadata=False)
            migrated = gf.read.import_gds(migrated_dir / gds_path.name)
    
            # 比较关键参数
            original_params = {l.text for l in original.get_labels(layer=(200, 0))}
            migrated_params = set()
            for k, v in migrated.metadata.get("parameters", {}).items():
                migrated_params.add(f"{k.upper()}:{v}")
    
            if original_params.issubset(migrated_params):
                report["passed"].append(gds_path.name)
            else:
                missing = original_params - migrated_params
                report["failed"].append(f"{gds_path.name}: 缺失参数 {missing}")
    
        return report
    

案例2:多工具元数据协作流程

某团队需要在gdsfactory、KLayout和Lumerical之间共享元数据,实现如下协作流程:

mermaid

关键实现代码如下:

1. gdsfactory元数据增强
def prepare_for_multitool(c):
    """为多工具协作准备元数据"""
    # 1. 添加基本设计元数据
    c.metadata["designer"] = "Jane Doe"
    c.metadata["project"] = "silicon_photonic_filter"
    c.metadata["revision"] = "A.2"
    
    # 2. 添加KLayout特定元数据
    c.metadata["klayout"] = {
        "drc_script": "filter_drc.lydrc",
        "layer_map": "generic_tech.lyp",
        "grid_size": 0.001
    }
    
    # 3. 添加Lumerical特定元数据
    c.metadata["lumerical"] = {
        "simulation_type": "FDTD",
        "mesh_accuracy": 2,
        "wavelength_range": [1.5, 1.6],
        "monitor_points": [(0, 0), (10, 0)]
    }
    
    # 4. 添加协作流程元数据
    c.metadata["workflow"] = {
        "next_step": "klayout_drc",
        "approver": "john.smith@company.com",
        "due_date": "2023-12-15"
    }
    
    # 5. 写入GDS
    c.write_gds("filter_vA2.gds", with_metadata=True)
    return c
2. KLayout元数据处理脚本
# KLayout脚本:提取并更新元数据
import pya

def process_metadata():
    layout = pya.Layout()
    layout.read("filter_vA2.gds")
    top_cell = layout.top_cell()
    
    # 提取gdsfactory元数据
    metadata = {}
    for shape in top_cell.shapes(layout.layer(200, 0)):  # 元数据层
        if shape.is_text():
            text = shape.text.string
            if ":" in text:
                key, value = text.split(":", 1)
                metadata[key] = value
    
    # 执行DRC检查
    drc_results = run_drc(metadata["klayout_drc_script"])
    
    # 更新元数据
    metadata["drc"] = {
        "passed": drc_results["errors"] == 0,
        "errors": drc_results["errors"],
        "warnings": drc_results["warnings"],
        "checked_by": "klayout_script",
        "timestamp": str(pya.Date().to_string())
    }
    
    # 写回元数据标签
    meta_layer = layout.layer(200, 0)
    top_cell.shapes(meta_layer).clear()  # 清除旧标签
    for key, value in metadata.items():
        if isinstance(value, dict):
            for subkey, subval in value.items():
                text = pya.Text(f"{key}_{subkey}:{subval}", pya.DPoint(0, 0))
                top_cell.shapes(meta_layer).insert(text)
        else:
            text = pya.Text(f"{key}:{value}", pya.DPoint(0, 0))
            top_cell.shapes(meta_layer).insert(text)
    
    layout.write("filter_vA2_drc.gds")
3. Lumerical元数据集成
# Python脚本:从gdsfactory元数据生成Lumerical配置
import lumerical.load as lum

def run_simulation_from_metadata(gds_path):
    c = gf.read.import_gds(gds_path)
    sim_params = c.metadata.get("lumerical", {})
    
    # 创建仿真项目
    fdtd = lum.FDTD()
    
    # 设置仿真参数
    fdtd["mesh_accuracy"] = sim_params.get("mesh_accuracy", 2)
    fdtd["wavelength_start"] = sim_params["wavelength_range"][0]
    fdtd["wavelength_stop"] = sim_params["wavelength_range"][1]
    
    # 添加几何结构
    fdtd.add_gds(gds_path, cellname=c.name)
    
    # 添加监视器(基于元数据中定义的点)
    for i, (x, y) in enumerate(sim_params["monitor_points"]):
        monitor = lum.Monitor(f"monitor_{i}")
        monitor["position"] = (x, y, 0)
        fdtd.add(monitor)
    
    # 运行仿真
    results = fdtd.run()
    
    # 将结果写回元数据
    c.metadata["simulation_results"] = {
        "transmission": results.get("transmission", []),
        "wavelengths": results.get("wavelengths", []),
        "sim_time": results.get("sim_time", 0),
        "convergence": results.get("convergence", True)
    }
    
    c.write_gds(gds_path, with_metadata=True)
    return results

未来展望:标准化GDS元数据

随着芯片设计复杂度的增加,GDS元数据的标准化变得日益重要。未来发展方向包括:

  1. 基于JSON Schema的元数据验证
# 元数据模式定义示例
metadata_schema = {
    "$schema": "http://json-schema.org/draft-07/schema#",
    "type": "object",
    "properties": {
        "gdsfactory_version": {"type": "string", "pattern": "^\\d+\\.\\d+\\.\\d+$"},
        "parameters": {
            "type": "object",
            "properties": {
                "length": {"type": "number", "minimum": 0},
                "width": {"type": "number", "minimum": 0.1, "maximum": 10},
                "layer": {"type": "array", "items": {"type": "integer"}, "minItems": 2, "maxItems": 2}
            },
            "required": ["length", "width"]
        },
        "ports": {
            "type": "array",
            "items": {
                "type": "object",
                "properties": {
                    "name": {"type": "string"},
                    "position": {"type": "array", "items": {"type": "number"}, "minItems": 2},
                    "orientation": {"type": "number", "minimum": 0, "maximum": 360},
                    "width": {"type": "number", "minimum": 0.1}
                },
                "required": ["name", "position"]
            }
        }
    },
    "required": ["gdsfactory_version", "parameters"]
}

# 验证实现
from jsonschema import validate
def validate_metadata(metadata, schema=metadata_schema):
    validate(instance=metadata, schema=schema)
  1. 元数据版本协商机制
def negotiate_metadata_version(tools):
    """多工具元数据版本协商"""
    supported_versions = {tool: get_supported_versions(tool) for tool in tools}
    
    # 找到所有工具都支持的最新版本
    common_versions = set.intersection(*supported_versions.values())
    if common_versions:
        return max(common_versions, key=lambda v: tuple(map(int, v.split("."))))
    else:
        # 选择最大兼容子集
        return find_best_compromise(supported_versions)
  1. 语义化元数据扩展
# 语义化元数据示例
metadata = {
    "@context": "https://gdsfactory.github.io/metadata-context/v1",
    "@type": "PhotonicComponent",
    "identifier": "straight_waveguide_123",
    "name": "Standard Straight Waveguide",
    "description": "Single-mode waveguide with 0.5μm width",
    "designTool": {
        "@type": "SoftwareApplication",
        "name": "gdsfactory",
        "version": "9.0.0"
    },
    "parameters": {
        "@type": "PropertyValue",
        "name": "width",
        "value": 0.5,
        "unitCode": "UM"  # 使用UN/CEFACT单位代码
    },
    "simulationResults": {
        "@type": "Dataset",
        "name": "Transmission Spectrum",
        "url": "results/transmission_123.json",
        "measurementTechnique": "FDTD Simulation"
    }
}

结论与行动指南

GDS元数据兼容性问题虽然隐蔽,却可能对芯片设计流程造成严重阻碍。通过本文介绍的方法论和实践案例,你现在拥有了识别、诊断和解决这些问题的全套工具。记住,良好的元数据管理不仅是技术需求,更是团队协作和设计可追溯性的基础。

立即行动项

  1. 审计现有设计库中的元数据使用情况,识别潜在风险
  2. 实施元数据兼容性测试,将其纳入CI/CD流程
  3. 为团队制定元数据编写规范,统一命名和类型标准
  4. 建立版本迁移计划,逐步升级至最新元数据格式
  5. 参与gdsfactory社区讨论,贡献元数据标准的改进建议

通过这些步骤,你将能够构建一个鲁棒、可扩展的元数据管理体系,并充分利用gdsfactory的强大功能,确保你的芯片设计从概念到制造的无缝传递。


附录:元数据兼容性检查清单

检查项是/否/部分备注
元数据包含版本信息建议格式: gdsfactory_version:9.0.0
所有数值参数有明确单位width:0.5应注明单位为μm
端口信息完整包括位置、方向、宽度和类型
元数据深度≤3层避免过深嵌套
使用标准数据类型优先使用int, float, str, list
关键元数据有标签备份重要参数同时写入GDS标签
通过跨版本导入测试至少测试当前版本和前两个版本
元数据大小<1MB避免过度膨胀影响性能
包含创建者和时间戳便于追溯和协作
已验证多工具兼容性至少验证主要使用的EDA工具

【免费下载链接】gdsfactory python library to design chips (Photonics, Analog, Quantum, MEMs, ...), objects for 3D printing or PCBs. 【免费下载链接】gdsfactory 项目地址: https://gitcode.com/gh_mirrors/gd/gdsfactory

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值