Magic源码阅读(四)——DRC检查的实现(上)
当我们从版图文件中读取数据并生成我们基于角勾链的数据模式后,下一步就是在我们的版图上进行DRC(设计规则检查),接下来让我们看一下magic是如何进行常用的DRC的。
DRC部分涉及的源码主要有以下几个源文件
drc.h #declaration of the main interface, defination of global variablesDRCarray.c #implementation of array related design rule checkDRCbasic.c #implementation of basic design rule check method#including interatcion, overlap, distance, etc...DRCcif.c #maybe related to the cif format layout fileDRCcontin.c #implementation of continuously design rule check methodDRCextend.c #implementation of extend design rule check method#including angle, length, width, rect size, etc...DRCmain.c #implementation of main interface and commandDRCprint.c #some additional function related printingDRCsubcell.c #implementation of subcell design rule check method#including interaction, overlap, flat, etc...DRCtech.c #Technology initialization for the DRC module
先从DRCmain.c
看起。
首先是一系列全局变量的定义,这些全局变量用来存储DRC发现的错误数据,magic将DRC检查DRCBasicCheck
与错误的打印drcPrintError
和绘制drcPrintError
解耦为不同的方法,用全局变量来传递数据。
DRCKeep *DRCStyleList = NULL;DRCStyle *DRCCurStyle = NULL;/* Used by both routines: */int DRCErrorCount; /* Incremented by each call to either routine.*//* Used by drcPaintError: */CellDef *DRCErrorDef; /* Place to paint error tiles. */
TileType DRCErrorType; /* Type of error tile to paint. *//* Used by drcPrintError: */int *DRCErrorList; /* List of DRC error type counts */
HashTable DRCErrorTable; /* Table of DRC errors and geometry *//* Global variables used by all DRC modules to record statistics.* For each statistic we keep two values, the count since stats* were last printed (in DRCstatXXX), and the total count (in* drcTotalXXX).*/int DRCstatSquares = 0; /* Number of DRCStepSize-by-DRCStepSize* squares processed by continuous checker.*/
int DRCstatTiles = 0; /* Number of tiles processed by basic* checker.*/
int DRCstatEdges = 0; /* Number of "atomic" edges processed* by basic checker.*/
int DRCstatRules = 0; /* Number of rules processed by basic checker* (rule = one constraint for one edge).*/
int DRCstatSlow = 0; /* Number of places where constraint doesn't* all fall in a single tile.*/
int DRCstatInteractions = 0; /* Number of times drcInt is called to check* an interaction area.*/
int DRCstatIntTiles = 0; /* Number of tiles processed as part of* subcell interaction checks.*/
int DRCstatCifTiles = 0; /* Number of tiles processed as part of* cif checks.*/
int DRCstatArrayTiles = 0; /* Number of tiles processed as part of* array interaction checks.*/
接下来的drcPrintError
和drcPrintError
就不多说了,分别是对应的错误打印和窗口UI的更新的实现,我们继续往下看:
/** 找出某个给定区域内的所有错误并打印所有不同类型的违背的规则*/void
DRCWhy(dolist, use, area) bool dolist; /** Generate Tcl list for value*/CellUse *use; /* Use in whose definition to start* the hierarchical check.*/Rect *area; /* Area, in def's coordinates, that* is to be checked.*/
{SearchContext scx;Rect box;int i;extern int drcWhyFunc(); /* Forward reference. *//* Create a hash table to eliminate duplicate messages. */DRCErrorList = (int *)mallocMagic((DRCCurStyle->DRCWhySize + 1) * sizeof(int));for (i = 0; i <= DRCCurStyle->DRCWhySize; i++)DRCErrorList[i] = 0;DRCErrorCount = 0;box = DRCdef->cd_bbox;/* Undo will only slow things down in here, so turn it off. */UndoDisable();scx.scx_use = use;scx.scx_x = use->cu_xlo;scx.scx_y = use->cu_ylo;scx.scx_area = *area;scx.scx_trans = GeoIdentityTransform;drcWhyFunc(&scx, (pointertype)dolist);UndoEnable();/* Delete the error list */freeMagic(DRCErrorList);/* Redisplay the DRC yank definition in case anyone is looking* at it.*/DBReComputeBbox(DRCdef);(void) GeoInclude(&DRCdef->cd_bbox, &box);/** 根据找到的错误发更新window*/DBWAreaChanged(DRCdef, &box, DBW_ALLWINDOWS, &DBAllButSpaceBits); if (DRCErrorCount == 0) TxPrintf("No errors found.\n");
}/** 由drcWhy调用,drcWhy将参数封装为searchcontent传递给drcWhyFunc*//* ARGSUSED */
int
drcWhyFunc(scx, cdarg)SearchContext *scx; /* Describes current state of search. */ClientData cdarg; /* Used to hold boolean value "dolist" */
{CellDef *def = scx->scx_use->cu_def;bool dolist = (bool)((pointertype)cdarg);/* Check paint and interactions in this subcell. *//* * 最终调用的两个函数是DRCInteractionCheck和DRCArrayCheck*/(void) DRCInteractionCheck(def, &scx->scx_area, &scx->scx_area,(dolist) ? drcListError : drcPrintError,(ClientData) scx);(void) DRCArrayCheck(def, &scx->scx_area,(dolist) ? drcListError : drcPrintError,(ClientData) scx);/* New behavior: Don't search children, instead propagate errors up. *//* (void) DBCellSrArea(scx, drcWhyFunc, (ClientData)cdarg); */return 0;
}
可见当我们使用drc why命令检查某个区域时,drc命令将传入的参数包装为searchContent
搜索上下文,传递给drcWhyFunc
,由其完成DRC(内部调用的DRCInteractionCheck
和DRCArrayCheck
两个函数),然后通过调用dbwind
下的相关函数进行错误的打印和窗口的更新。
而接下来的DRCcheck
则有所不同:
void
DRCCheck(use, area)CellUse *use; /* Top-level use of hierarchy. */Rect *area; /* This area is rechecked everywhere in the* hierarchy underneath use.*/
{SearchContext scx;extern int drcCheckFunc(); /* Forward reference. *//** DRC Check先进行了读取,将要检查的区域加载进内存*/DBCellReadArea(use, area);/** 同样封装了参数,传递并调用了函数DRCCheckFunc*/scx.scx_use = use;scx.scx_x = use->cu_xlo;scx.scx_y = use->cu_ylo;scx.scx_area = *area;scx.scx_trans = GeoIdentityTransform;(void) drcCheckFunc(&scx, (ClientData) NULL);
}/* ARGSUSED */
int
drcCheckFunc(scx, cdarg)SearchContext *scx;ClientData cdarg; /* Not used. */
{Rect cellArea;CellDef *def;/* * 将区域裁剪为单元格的大小,然后重新检查该区域。 通过直接绘制检查信息,然后调用DRCCheckThis,仅将单元格添加到要检查的单元格列表中,即可处理重新检查。 这避免了通常由DRCCheckThis进行的向上的分层搜索,但是我们不希望这样(速度很慢)。*/cellArea = scx->scx_area;def = scx->scx_use->cu_def;GeoClip(&cellArea, &def->cd_bbox);GEO_EXPAND(&cellArea, DRCTechHalo, &cellArea);DBPaintPlane(def->cd_planes[PL_DRC_CHECK], &cellArea,DBStdPaintTbl(TT_CHECKPAINT, PL_DRC_CHECK),(PaintUndoInfo *) NULL);DRCCheckThis(def, TT_CHECKPAINT, (Rect *) NULL);/* New behavior: Don't search children, instead propagate errors up. *//* (void) DBCellSrArea(scx, drcCheckFunc, (ClientData) NULL); *//* As a special performance hack, if the complete cell area is* handled here, don't bother to look at any more array elements.*/if (GEO_SURROUND(&cellArea, &def->cd_bbox))return 2;else return 0;
}
可以看到check
和why
的区别,check
在检查前需要进行读取,并且检查调用的是DRCCheckThis
函数,而why
底层调用的是DRCInteractionCheck
和DRCArrayCheck
两个函数。为什么会有这种区别呢?
DRCCheckThis
在源文件DRCcontin.c
中,我们带着疑问看一下DRCCheckThis
的实现:
void
DRCCheckThis (celldef, operation, area)CellDef * celldef; /* Allows check areas to propagate* up from EditCell.*/TileType operation; /* TT_CHECKPAINT or TT_CHECKSUBCELL */Rect * area; /* Area that changed. */
{CellUse * cu; /* Ptr to uses of the given CellDef */Rect transRect; /* Area in coords of parent CellDefs,* expanded if the use is in an array*/Rect dummyRect, dummyRect2;DRCPendingCookie * p, ** pback; /* Used to insert new element in list* of CellDefs waiting for DRC*//* Ignore read-only, internal, and vendor GDS cells. None of these *//* can contain DRC errors that could be fixed in magic. */if (celldef->cd_flags & (CDVENDORGDS | CDNOEDIT | CDINTERNAL)) return;/* Insert celldef into list of Defs waiting to be checked, unless *//* it is already there. */pback = &DRCPendingRoot;p = DRCPendingRoot;while (p != (DRCPendingCookie *) NULL){if (p->dpc_def == celldef){*pback = p->dpc_next;break;}pback = &(p->dpc_next);p = p->dpc_next;}if (p == (DRCPendingCookie *) NULL){p = (DRCPendingCookie *) mallocMagic(sizeof (DRCPendingCookie));p->dpc_def = celldef;}p->dpc_next = DRCPendingRoot;DRCPendingRoot = p;/* Mark the area in this celldef (but don't worry about this stuff* for undo purposes). Also, it's important to disable interrupts* in here, or the paint operation could get aborted underneath us.** Mark an area of a CellDef so that it will be checked by continuous* DRC. Add the CellDef to the list of Defs to be checked. If the* pointer to the area rectangle is NULL, just add the CellDef to the* list.*/if (area != (Rect *) NULL){GEO_EXPAND(area, DRCTechHalo, &dummyRect);SigDisableInterrupts();DBPaintPlane(celldef->cd_planes[PL_DRC_CHECK], &dummyRect,DBStdPaintTbl(TT_CHECKPAINT, PL_DRC_CHECK),(PaintUndoInfo *) NULL);SigEnableInterrupts();}else return;/* Call recursively for each use of this* CellDef in a parent.*/for (cu = celldef->cd_parents; cu != (CellUse *) NULL; cu = cu->cu_nextuse){if (cu->cu_parent == (CellDef *) NULL) /* use for a Window */continue;/* area in coordinates of the parent Def */GeoTransRect (&(cu->cu_transform), area, &transRect);if ((cu->cu_xlo != cu->cu_xhi) || (cu->cu_ylo != cu->cu_yhi)){/* transRect needs to include all images* of "area" in the array, in coordinates* of the parent Def*/DBComputeArrayArea(area, cu, cu->cu_xhi, cu->cu_yhi, &dummyRect);GeoTransRect(&cu->cu_transform, &dummyRect, &dummyRect2);(void) GeoInclude (&dummyRect2, &transRect);}DRCCheckThis (cu->cu_parent, TT_CHECKSUBCELL, &transRect);}
}
可以看到,DRCcheckthis
的实现是将当前的区域添加到待DRC的list中,由后台持续运行的DRC检查器来进行检查,同时,递归的调用以检查嵌套的cell。
个人的理解是DRCcheckthis
执行的是一种粗粒度的检查,由一个持续运行的规则检查器来完成,针对的是整个版图或者版图的某一层这种大规模的数据,因此在检查前需要进行数据的加载和预处理,得到的结果是大规模的区域及其中违反规则的部分。而DRCwhy
执行的是更为细粒度的检查,顾名思义会得到此处违反的具体规则是什么,检查的对象是初步检查过的图,数据已在内存中,无需加载。
Magic源码阅读(四)——DRC检查的实现(上)相关推荐
- mybatis源码阅读(四):mapper(dao)实例化
转载自 mybatis源码阅读(四):mapper(dao)实例化 在开始分析之前,先来了解一下这个模块中的核心组件之间的关系,如图: 1.MapperRegistry&MapperPro ...
- 39 网络相关函数(七)——live555源码阅读(四)网络
39 网络相关函数(七)--live555源码阅读(四)网络 39 网络相关函数(七)--live555源码阅读(四)网络 简介 14)readSocket从套接口读取数据 recv/recvfrom ...
- spark源码(四)executor在worker上的创建过程,executor本质是什么,是线程池吗?
上篇文章我们讲解了master调度driver和executor(application)的过程,但是对于executor在worker上的创建过程没有讲,这里我们接着上篇文章继续讲. 首先我们从wo ...
- ThreadLocal源码阅读四:如何解决hash碰撞的?
背景 推荐阅读ThreadLocal工作过程 推荐阅读ThreadLocal的魔数引发的疑问与思考 什么样的使用场景会出现hash碰撞? 如何解决hash碰撞的? 过程 可能产生hash碰撞的场景 分 ...
- Struts2源码阅读(四)_DispatcherConfigurationProvider续
接下来第三步:init_LegacyStrutsProperties() 调用的是调用的是LegacyPropertiesConfigurationProvider 通过比较前面DefaultProp ...
- Junit源码阅读(四)之自定义扩展
前言 上次的博客中我们着重介绍了Junit的Validator机制,这次我们将聚焦到自定义扩展Rule上来.在很多情形下我们需要在测试过程中加入一些自定义的动作,这些就需要对statement进行包装 ...
- redis源码阅读-持久化之RDB
持久化介绍: redis的持久化有两种方式: rdb :可以在指定的时间间隔内生成数据集的时间点快照(point-in-time snapshot) aof : 记录redis执行的所有写操作命令 根 ...
- 源码阅读及理论详解《 Informer: Beyond Efficient Transformer for Long Sequence Time-Series Forecasting 》
Informer论文:https://arxiv.org/pdf/2012.07436.pdf Informer源码:GitHub - zhouhaoyi/Informer2020: The GitH ...
- redis源码阅读-zset
前段时间给小伙伴分享redis,顺带又把redis撸了一遍了,对其源码,又有了比较深入的了解.(ps: 分享的文章再丰富下再放出来). 数据结构 我们先看下redis 5.0的代码.本次讲解主要是zs ...
最新文章
- 史上最全的正则表达式
- hdu1715 大菲波数
- JS魔法堂:彻底理解0.1 + 0.2 === 0.30000000000000004的背后
- PAT甲级题目翻译+答案 AcWing(基础算法与数据结构)
- python基础(一)简单入门
- 北京市计算机专修学院,北京计算机专修学院:三大热门专业
- 华为ac控制器web配置手册_欧姆龙AC伺服系统1S系列产品型号说明及功能介绍
- LVS + Nginx +Tomcat 高可用架构
- 为suse 12.3桌面系统安装金山WPS OFFICE
- pdf转换器下载使用步骤
- CAN FD实战之示波器捕捉波形及对照CAN FD帧定义解析CAN FD帧
- plc编程和python的联系_Python与三菱PLC通信
- median函数的使用方法_如何在Google表格中使用MEDIAN函数
- vue 挑战最强大脑 记忆力5分 观察力5分 推理力4分
- delphi学习笔记(2)-object pascal语言的语句 选择自 xmz2629 的 Blog
- html如何设置下画虚线框,如何用css画虚线
- excel表格横向纵向变换_什么是报表工具?和 EXCEL 有什么区别?
- 实习日记(9)——C++编译出现error in locking authority file ~/.Xauthority
- SQL SERVER 查询、删除重复数据
- 计算机主机拆卸心得,1计算机硬件拆装实验报告(01)
热门文章
- fmt:formatNumber 用法
- transformer 模型(self-attention自注意力)
- ‘utf-8‘ codec can‘t decode byte 0xb9 in position 24: invalid start byte
- 星球大战尤达(Baby Yoda)
- 人工智能PK人类?这部电影超前地预见了人类社会的终极形态
- android芝麻认证sdk,芝麻认证接入文档.docx
- VS配置永久OpenGL环境------GLUT、GLFW
- 怎么利用知乎蹭实时热点?1篇文章教你
- 读书笔记:《代码大全第2版》 01.打好基础
- vscode 编辑md文件 好用的插件