当我们从版图文件中读取数据并生成我们基于角勾链的数据模式后,下一步就是在我们的版图上进行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.*/

接下来的drcPrintErrordrcPrintError就不多说了,分别是对应的错误打印和窗口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(内部调用的DRCInteractionCheckDRCArrayCheck两个函数),然后通过调用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;
}

可以看到checkwhy的区别,check在检查前需要进行读取,并且检查调用的是DRCCheckThis函数,而why底层调用的是DRCInteractionCheckDRCArrayCheck两个函数。为什么会有这种区别呢?

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检查的实现(上)相关推荐

  1. mybatis源码阅读(四):mapper(dao)实例化

    转载自   mybatis源码阅读(四):mapper(dao)实例化 在开始分析之前,先来了解一下这个模块中的核心组件之间的关系,如图: 1.MapperRegistry&MapperPro ...

  2. 39 网络相关函数(七)——live555源码阅读(四)网络

    39 网络相关函数(七)--live555源码阅读(四)网络 39 网络相关函数(七)--live555源码阅读(四)网络 简介 14)readSocket从套接口读取数据 recv/recvfrom ...

  3. spark源码(四)executor在worker上的创建过程,executor本质是什么,是线程池吗?

    上篇文章我们讲解了master调度driver和executor(application)的过程,但是对于executor在worker上的创建过程没有讲,这里我们接着上篇文章继续讲. 首先我们从wo ...

  4. ThreadLocal源码阅读四:如何解决hash碰撞的?

    背景 推荐阅读ThreadLocal工作过程 推荐阅读ThreadLocal的魔数引发的疑问与思考 什么样的使用场景会出现hash碰撞? 如何解决hash碰撞的? 过程 可能产生hash碰撞的场景 分 ...

  5. Struts2源码阅读(四)_DispatcherConfigurationProvider续

    接下来第三步:init_LegacyStrutsProperties() 调用的是调用的是LegacyPropertiesConfigurationProvider 通过比较前面DefaultProp ...

  6. Junit源码阅读(四)之自定义扩展

    前言 上次的博客中我们着重介绍了Junit的Validator机制,这次我们将聚焦到自定义扩展Rule上来.在很多情形下我们需要在测试过程中加入一些自定义的动作,这些就需要对statement进行包装 ...

  7. redis源码阅读-持久化之RDB

    持久化介绍: redis的持久化有两种方式: rdb :可以在指定的时间间隔内生成数据集的时间点快照(point-in-time snapshot) aof : 记录redis执行的所有写操作命令 根 ...

  8. 源码阅读及理论详解《 Informer: Beyond Efficient Transformer for Long Sequence Time-Series Forecasting 》

    Informer论文:https://arxiv.org/pdf/2012.07436.pdf Informer源码:GitHub - zhouhaoyi/Informer2020: The GitH ...

  9. redis源码阅读-zset

    前段时间给小伙伴分享redis,顺带又把redis撸了一遍了,对其源码,又有了比较深入的了解.(ps: 分享的文章再丰富下再放出来). 数据结构 我们先看下redis 5.0的代码.本次讲解主要是zs ...

最新文章

  1. 史上最全的正则表达式
  2. hdu1715 大菲波数
  3. JS魔法堂:彻底理解0.1 + 0.2 === 0.30000000000000004的背后
  4. PAT甲级题目翻译+答案 AcWing(基础算法与数据结构)
  5. python基础(一)简单入门
  6. 北京市计算机专修学院,北京计算机专修学院:三大热门专业
  7. 华为ac控制器web配置手册_欧姆龙AC伺服系统1S系列产品型号说明及功能介绍
  8. LVS + Nginx +Tomcat 高可用架构
  9. 为suse 12.3桌面系统安装金山WPS OFFICE
  10. pdf转换器下载使用步骤
  11. CAN FD实战之示波器捕捉波形及对照CAN FD帧定义解析CAN FD帧
  12. plc编程和python的联系_Python与三菱PLC通信
  13. median函数的使用方法_如何在Google表格中使用MEDIAN函数
  14. vue 挑战最强大脑 记忆力5分 观察力5分 推理力4分
  15. delphi学习笔记(2)-object pascal语言的语句 选择自 xmz2629 的 Blog
  16. html如何设置下画虚线框,如何用css画虚线
  17. excel表格横向纵向变换_什么是报表工具?和 EXCEL 有什么区别?
  18. 实习日记(9)——C++编译出现error in locking authority file ~/.Xauthority
  19. SQL SERVER 查询、删除重复数据
  20. 计算机主机拆卸心得,1计算机硬件拆装实验报告(01)

热门文章

  1. fmt:formatNumber 用法
  2. transformer 模型(self-attention自注意力)
  3. ‘utf-8‘ codec can‘t decode byte 0xb9 in position 24: invalid start byte
  4. 星球大战尤达(Baby Yoda)
  5. 人工智能PK人类?这部电影超前地预见了人类社会的终极形态
  6. android芝麻认证sdk,芝麻认证接入文档.docx
  7. VS配置永久OpenGL环境------GLUT、GLFW
  8. 怎么利用知乎蹭实时热点?1篇文章教你
  9. 读书笔记:《代码大全第2版》 01.打好基础
  10. vscode 编辑md文件 好用的插件