OpenAccess作为集成电路设计领域的开放数据库标准,从根本上改变了传统EDA工具链的数据交互模式。在传统流程中,每个EDA工具通常使用私有数据格式,导致设计数据在不同工具间流转时需要频繁转换,不仅效率低下,还可能引入数据一致性风险。OpenAccess通过标准化数据模型和API接口,实现了三大核心突破:
首先,它建立了统一的对象导向数据模型。这个模型将芯片设计中的物理元素(如晶体管、互连线、接触孔等)抽象为可编程对象,每个对象都带有完整的属性和方法。例如,一个矩形金属层图形不再只是GDSII文件中的坐标集合,而是包含工艺层信息、电气特性、设计规则约束等丰富属性的智能对象。
其次,OpenAccess提供了跨平台的C++ API接口集。这些接口覆盖了从基础几何操作到复杂设计规则检查的全套功能,使得工具开发者可以专注于算法实现,而不必重复开发底层数据管理模块。我们在LSI开发的Viewer程序就充分利用了oaRegionQuery接口来实现高效的区域查询,相比传统基于GDSII的解决方案,查询速度提升了3-5倍。
第三,其扩展机制允许工具开发者添加自定义属性和行为。在实际项目中,我们通过扩展接口为设计对象添加了选择状态标记和显示属性,这些数据可以持久化保存在技术库中,不会干扰其他工具的正常运作。这种灵活性使得OpenAccess既能保持核心标准的稳定性,又能适应不同设计流程的特殊需求。
GDSII作为半导体行业的"通用语言",至今仍是工艺厂接受设计数据的主要格式。我们开发的GDS导入器采用分层转换策略:
结构层转换:将GDS的STRUCTURE转换为OpenAccess的CellView,保持严格的命名空间映射。特别处理了GDS的层级引用关系,确保转换后的设计保持相同的实例化结构。
元素层转换:
属性映射:通过OpenAccess的扩展机制保留GDS的PROPERTY属性,关键属性如net名、器件类型等会转换为标准OA属性。
测试数据显示OpenAccess数据库比原始GDS文件小60-70%,这主要得益于三个优化:
几何压缩:将相邻的矩形合并为多边形,减少重复顶点。对于规则阵列结构,采用参数化表示而非全展开。
层次共享:相同单元的多个实例共享存储空间,而GDSII需要重复记录相同几何数据。
智能编码:使用变长整数编码坐标数据,相比GDSII的固定8字节表示,节省30-50%空间。
关键提示:在转换大型设计时,建议启用渐进式加载模式,避免内存峰值。我们的测试表明,对于200MB以上的GDS文件,分块处理可降低30%的内存占用。
Viewer采用模型-视图-控制器(MVC)模式,其中:
这种解耦设计使得我们可以独立优化各个组件。例如在Sun Ultra-60工作站上,我们针对SPARC处理器优化了图形渲染管线,使刷新速率从5FPS提升到15FPS。
测试数据显示不同操作的时间分布:
优化措施包括:
传统API封装通常采用SWIG等通用工具,但面对OpenAccess这样包含2000+类的复杂API,我们开发了专用生成器:
这种方法的优势在于:
我们将OpenAccess的C++异常转换为Python异常,保持调用栈信息完整。关键转换包括:
测试数据揭示出有趣的平台差异:
| 操作类型 | WinPC(1.7G) | Sun(450M) | 性能比 |
|---|---|---|---|
| 数据库加载 | 6.74s | 18.28s | 2.7:1 |
| 区域查询(30μm) | 0.12s | 0.77s | 6.4:1 |
| 全选重绘 | 6.38s | 17.53s | 2.7:1 |
虽然Sun工作站CPU频率较低,但其大内存带宽(1.6GB/s vs PC800的1.06GB/s)在某些操作上表现更好。
中型设计(98MB GDS)的各项操作耗时分布:
首次视图:8.08s
二次视图:5.97s
OpenAccess采用混合内存模型:
我们发现在处理超大规模设计时,需要调整OA的内存配置参数:
cpp复制oaDesign::setDefaultPageSize(64); // 设置内存页大小为64MB
oaDesign::setDefaultCacheSize(1024); // 缓存1GB设计数据
虽然OpenAccess API声明为线程安全,但实际使用时需注意:
基于Python扩展,我们构建了多种高效工具:
python复制def check_hierarchy(cell):
for inst in cell.getInsts():
if not inst.getMaster().isValid():
print(f"Broken reference: {inst.getName()}")
check_hierarchy(inst.getMaster())
python复制def compare_layouts(cell1, cell2):
q1 = oaRegionQuery(cell1)
q2 = oaRegionQuery(cell2)
for layer in tech.getLayers():
for shape in q1.getShapes(layer):
if not q2.hasShape(shape):
report_difference(shape)
python复制def rename_nets(design, pattern):
for net in design.getNets():
if re.match(pattern, net.getName()):
net.setName(new_name)