<> <> <> <> DIRECTORY Atom, CD, CDBasics, CDCSUtil, CDErrors, CDMenus, CDInstances, CDProperties, CDSequencer, CDSimpleRules, CDValue, CDViewer, CedarProcess, MBQueue, Process, Rope, TerminalIO, ViewerClasses, ViewerOps; CDSCheck: CEDAR PROGRAM IMPORTS Atom, CD, CDBasics, CDCSUtil, CDErrors, CDMenus, CDInstances, CDProperties, CDSimpleRules, CDValue, CDViewer, CedarProcess, MBQueue, Process, Rope, TerminalIO, ViewerOps = BEGIN Message: PROC [x: REF ANY] = BEGIN h: CDCSUtil.CDWorld ~ NARROW[x]; errors: CDCSUtil.Plane ~ NARROW[CDProperties.GetProp[h.propRef, $err]]; layerName: Rope.ROPE ~ NARROW[CDProperties.GetProp[h.propRef, $layer]]; key: ATOM ~ Atom.MakeAtom[Rope.Concat["||ck-", layerName]]; IF CDValue.Fetch[h.design, key]=h.design.actual.first.dummyCell.ob THEN CDErrors.RemoveMessages[h.design, NIL, key] ELSE CDErrors.RemoveAllMessages[h.design, key]; [] _ CDCSUtil.ExtractErrors[h, errors, Rope.Concat[layerName, " spacing"], key]; CDValue.Store[h.design, key, h.design.actual.first.dummyCell.ob]; END; CheckSpacing: PROC [d: CD.Design, r: CD.Rect, layer: CD.Layer] = BEGIN h: CDCSUtil.CDWorld _ NEW[CDCSUtil.CDWorldRec _ [design: d, scaleNum: 2, clip: r, propRef: CD.InitPropRef[]]]; original: CDCSUtil.Plane _ CDCSUtil.Make[h, LIST[NEW[CDCSUtil.LayerDescRec_[layer]]]]; distRule: CD.Number _ CDSimpleRules.MinDist[layer, layer]; amount: INT _ (h.scaleNum*distRule)/2-1; grown: CDCSUtil.Plane _ CDCSUtil.Grow[original, amount]; again: CDCSUtil.Plane _ CDCSUtil.Grow[grown, -amount]; errors: CDCSUtil.Plane _ CDCSUtil.AndNot[again, original]; CDProperties.PutProp[h.propRef, $err, errors]; CDProperties.PutProp[h.propRef, $layer, Atom.GetPName[CD.LayerKey[layer]]]; MBQueue.QueueClientAction[d.queue, Message, h]; END; CheckProcess: PROC [] = BEGIN d: CD.Design; md: CD.Number; CedarProcess.SetPriority[CedarProcess.Priority[background]]; DO -- forever v: ViewerClasses.Viewer _ CDViewer.LastViewer[]; IF v#NIL AND ViewerOps.FetchProp[v, $backCheck]=$y AND (d_CDViewer.DesignOf[v])#NIL THEN { r: CD.Rect _ CDViewer.VisibleRect[v]; --handle view rect only for speed up <<--restrict further to pushed in cell>> IF d.actual.rest#NIL THEN r _ CDBasics.Intersection[r, CDInstances.InstRectO[d.actual.first.mightReplace]]; <<--restrict further to handy scales>> IF r.y2-r.y1<150*d.technology.lambda THEN FOR ll: LIST OF CD.Layer _ d.technology.usedLayers, ll.rest WHILE ll#NIL DO IF (md_CDSimpleRules.MinDist[ll.first, ll.first])>0 THEN CheckSpacing[d, CDBasics.Extend[r, md+d.technology.lambda], ll.first]; Process.Pause[Process.MsecToTicks[1]]; ENDLOOP; }; d _ NIL; --gc Process.Pause[Process.MsecToTicks[500]]; ENDLOOP; END; CheckStartCommand: PROC [comm: CDSequencer.Command] = BEGIN v: ViewerClasses.Viewer _ CDViewer.GetViewer[comm]; TerminalIO.WriteRope[" start background checking for this viewer\n"]; IF v#NIL THEN ViewerOps.AddProp[v, $backCheck, $y]; END; CheckStopCommand: PROC [comm: CDSequencer.Command] = BEGIN v: ViewerClasses.Viewer _ CDViewer.GetViewer[comm]; TerminalIO.WriteRope[" stop background checking in this viewer\n"]; IF v#NIL THEN ViewerOps.AddProp[v, $backCheck, NIL]; END; CDMenus.ImplementEntryCommand[$ProgramMenu, "start background checking", CheckStartCommand]; CDMenus.ImplementEntryCommand[$ProgramMenu, "stop background checking", CheckStopCommand]; TRUSTED { Process.Detach[FORK CheckProcess[]] }; END.