DIRECTORY BasicTime USING [GMT, Now, Period], CD USING [CreateDrawRef, Design, DrawProc, DrawRef, Instance, InstanceList, Layer, Number, Object, Technology], CDBasics USING [Extend], CDCommandOps USING [DoWithResource], CDDirectory USING [Fetch], CDErrors USING [IncludeMessage, RemoveMessages], CDInstances USING [NewInst], CDIO USING [ReadDesign], CDOps USING [InstList, LayerRope, ObjectRope], CDProperties USING [GetDesignProp, GetObjectProp, PutDesignProp, RegisterProperty], CDSequencer USING [Command, ImplementCommand, UseAbortFlag], Core USING [Wire], CoreClasses USING [recordCellClass, RecordCellType], CoreGeometry USING [GetObject], CoreOps USING [CopyWire, GetCellTypeName, GetShortWireName, PrintCellType, SetShortWireName], CoreProperties USING [GetProp], CoreView USING [debugViewer, DestroyView, GeometryView, StartIncrementalView, Viewer], CStitching USING [DumpCache], Drc USING [CheckDesignRules, CoreCell, coreInconsistent, DRV, DRVkey, ErrorRect, Layout, Wire], DrcCMOSB USING [cMosBcomplete, cMosBsimple], DrcDebug USING [debug, dLog], IO USING [card, int, PutF, PutFR1, rope], PrincOpsUtils USING [], Process USING [priorityBackground, SetPriority], Rope USING [Cat, IsEmpty, ROPE], Sinix USING [Extract, Mode], SinixOps USING [GetExtractMode], TerminalIO USING [PutRope, PutRopes, PutF, PutF1], UserProfile USING [Boolean, CallWhenProfileChanges, ProfileChangedProc]; DrcCommandImpl: CEDAR PROGRAM IMPORTS BasicTime, CD, CDBasics, CDCommandOps, CDDirectory, CDErrors, CDInstances, CDIO, CDOps, CDProperties, CDSequencer, CoreClasses, CoreGeometry, CoreOps, CoreProperties, CoreView, CStitching, Drc, DrcCMOSB, DrcDebug, IO, Process, Rope, Sinix, SinixOps, TerminalIO, UserProfile ~ BEGIN OPEN DrcCMOSB; ROPE: TYPE ~ Rope.ROPE; timing: BOOL _ UserProfile.Boolean ["Genista.Timing", FALSE]; religion: BOOL _ UserProfile.Boolean ["Genista.EmulateSoS", FALSE]; failureReason: ROPE; failureTorch: REF ANY; regressionDesign: ROPE _ "[DATools]Genista>DragonRules.dale"; layoutViewer: CoreView.Viewer; Misc: TYPE ~ REF Stuff; Stuff: TYPE ~ RECORD [design: CD.Design, geom: Drc.Layout]; Execute: PROC [comm: CDSequencer.Command] ~ BEGIN ENABLE Drc.coreInconsistent => BEGIN failureReason _ reason; failureTorch _ torch; GOTO failure END; state: Misc ~ NEW [Stuff]; abort: REF BOOL _ NEW [BOOL _ FALSE]; ExtractAndCheck: PROC [comm: CDSequencer.Command] ~ BEGIN startTime1, startTime2, lapTime, stopTime: BasicTime.GMT; tech: Sinix.Mode _ SinixOps.GetExtractMode [state.design.technology]; violations: CARDINAL _ 0; IF (tech = NIL) THEN BEGIN TerminalIO.PutRope [Rope.Cat ["The technology ", comm.design.technology.name, " is not implemented in Sinix or Drc.\n"]]; RETURN END; state.geom _ tech.decoration; FOR all: CD.InstanceList _ CDOps.InstList [state.design], all.rest WHILE all # NIL DO IF all.first.selected THEN BEGIN TRUSTED {Process.SetPriority [Process.priorityBackground]}; startTime1 _ BasicTime.Now []; WITH Sinix.Extract [obj: all.first.ob, mode: tech].result SELECT FROM coreCell: Drc.CoreCell => BEGIN v: REF CARDINAL _ NIL; fakeActual: Drc.Wire ~ CoreOps.CopyWire [coreCell.public]; FOR i: NAT IN [0 .. fakeActual.size) DO givenName: ROPE ~ CoreOps.GetShortWireName [fakeActual[i]]; fakeActual[i] _ CoreOps.SetShortWireName [fakeActual[i], IF givenName.IsEmpty THEN IO.PutFR1 ["External", IO.int [i]] ELSE givenName] ENDLOOP; IF DrcDebug.debug THEN BEGIN IF (layoutViewer # NIL) THEN CoreView.DestroyView [layoutViewer]; IF (CoreView.debugViewer # NIL) THEN CoreView.DestroyView [CoreView.debugViewer]; layoutViewer _ CoreView.GeometryView [coreCell, tech.decoration, abort]; CoreView.debugViewer _ CoreView.StartIncrementalView [coreCell, tech.decoration, abort] END; CDProperties.PutDesignProp [state.design, $DrcCoreCircularity]; -- remove lapTime _ BasicTime.Now []; IF DrcDebug.debug THEN BEGIN CoreOps.PrintCellType [coreCell, DrcDebug.dLog]; DrcDebug.dLog.PutF ["\n"]; END; startTime2 _ BasicTime.Now []; violations _ Drc.CheckDesignRules [cell: coreCell, external: fakeActual, tech: IF religion THEN cMosBsimple ELSE cMosBcomplete, stopFlag: abort, layout: state.geom]; stopTime _ BasicTime.Now []; TerminalIO.PutF [format: "\nNumber of new design violations found: %l%g%l\n", v1: IO.rope ["b"], v2: IO.card [violations], v3: IO.rope ["B"]]; IF DrcDebug.debug THEN VerifyObjects [state.design, all.first.ob]; IF timing THEN BEGIN TerminalIO.PutF1 ["\nElapsed time for extraction: %g", IO.int [startTime1.Period [lapTime]]]; TerminalIO.PutF1 ["\nElapsed time for DRC: %g", IO.int [startTime2.Period [stopTime]]]; TerminalIO.PutF1 ["\nTotal elapsed time: %g\n", IO.int [startTime1.Period [stopTime]]] END; IF (violations > 0) THEN v _ NEW [CARDINAL _ violations]; CDProperties.PutDesignProp [state.design, $DrcNr, v]; CDProperties.PutDesignProp [state.design, $DrcCoreCircularity, coreCell]; -- a circularity, but I don not have a better idea at the moment CStitching.DumpCache []; EnumerateCore [coreCell, BackAnnotation, state, abort] END; w: Core.Wire => ERROR; ENDCASE => NULL -- e.g., cell contains text or schematics END -- if selected ENDLOOP END; -- ExtractAndCheck TerminalIO.PutRope ["DRC (Genista).\n"]; state.design _ comm.design; CDSequencer.UseAbortFlag [state.design, abort]; [] _ CDCommandOps.DoWithResource [ExtractAndCheck, comm, $Drc]; TerminalIO.PutRope ["Drc done.\n"]; EXITS failure => BEGIN TerminalIO.PutRopes [failureReason, ". Core structure inconsistent. DRC aborted.\n"] END END; -- Execute EachCell: TYPE ~ PROC [cell: Drc.CoreCell, data: REF ANY _ NIL]; EnumerateCore: PROC [cell: Drc.CoreCell, action: EachCell, data: REF ANY _ NIL, stopFlag: REF BOOL] ~ BEGIN SELECT cell.class FROM CoreClasses.recordCellClass => BEGIN cellData: CoreClasses.RecordCellType ~ NARROW [cell.data]; IF stopFlag^ THEN ERROR ABORTED; FOR sub: NAT IN [0 .. cellData.size) DO EnumerateCore [cellData.instances[sub].type, action, data, stopFlag] ENDLOOP; action [cell, data] END; ENDCASE => NULL END; -- EnumerateCore BackAnnotation: EachCell ~ BEGIN state: Misc ~ NARROW [data]; cdCell: CD.Object ~ CoreGeometry.GetObject [state.geom, cell]; drv: Drc.DRV ~ NARROW [CoreProperties.GetProp [cell.properties, Drc.DRVkey]]; CDErrors.RemoveMessages [design: state.design, ob: cdCell, owner: Drc.DRVkey]; IF (drv # NIL) THEN FOR v: LIST OF Drc.ErrorRect _ drv.places, v.rest WHILE v # NIL DO [] _ CDErrors.IncludeMessage [design: state.design, ob: cdCell, rect: CDBasics.Extend [v.first.r, 4], message: v.first.msg, owner: Drc.DRVkey] ENDLOOP; END; -- BackAnnotation ProblemMessage: EachCell ~ BEGIN state: Misc ~ NARROW [data]; cdCell: CD.Object ~ CoreGeometry.GetObject [state.geom, cell]; IF (CoreProperties.GetProp [cell.properties, Drc.DRVkey] # NIL) THEN BEGIN TerminalIO.PutRopes [CDOps.ObjectRope [cdCell], " is not verified correctly ("]; TerminalIO.PutRopes [NARROW [CDProperties.GetObjectProp [cdCell, $rule], ROPE], ")\n"] END END; -- ProblemMessage UncheckedMessage: EachCell ~ BEGIN state: Misc ~ NARROW [data]; cdCell: CD.Object ~ CoreGeometry.GetObject [state.geom, cell]; drv: Drc.DRV ~ NARROW [CoreProperties.GetProp [cell.properties, Drc.DRVkey]]; IF (drv = NIL) OR (drv.count # 1) THEN BEGIN description: ROPE ~ NARROW [CDProperties.GetObjectProp [cdCell, $rule]]; flat: BOOL ~ (CDProperties.GetObjectProp [cdCell, $flat] # NIL); IF flat THEN TerminalIO.PutF ["%g is verified flat (%g)\n", IO.rope [CDOps.ObjectRope [cdCell]], IO.rope [description]] ELSE TerminalIO.PutF ["%g is not verified correctly (%g)\n", IO.rope [CDOps.ObjectRope [cdCell]], IO.rope [description]] END END; -- UncheckedMessage List: PROC [comm: CDSequencer.Command] ~ BEGIN violations: REF CARDINAL ~ NARROW [CDProperties.GetDesignProp [comm.design, $DrcNr]]; IF (violations = NIL) THEN TerminalIO.PutRope ["No new violations found last time.\n"] ELSE TerminalIO.PutF1 ["Number of design rule violations found last time: %g\n", IO.card[violations^]]; END; -- List PrintDRV: EachCell ~ BEGIN drv: Drc.DRV ~ NARROW [CoreProperties.GetProp [cell.properties, Drc.DRVkey]]; IF (drv # NIL) THEN BEGIN cellName: ROPE ~ CoreOps.GetCellTypeName [cell]; l: CD.Number ~ NARROW [data, CD.Technology].lambda; TerminalIO.PutF ["\ncell %g, %g violations:\n", IO.rope [cellName], IO.int [drv.count]]; FOR e: LIST OF Drc.ErrorRect _ drv.places, e.rest WHILE e # NIL DO TerminalIO.PutF ["%g at [(%g, %g); (%g, %g)] \n", IO.rope [e.first.msg], IO.int [e.first.r.x1/l], IO.int [e.first.r.y1/l], IO.int [e.first.r.x2/l], IO.int [e.first.r.y2/l]] ENDLOOP END END; -- PrintDRV ListAll: PROC [comm: CDSequencer.Command] ~ BEGIN coreCell: Drc.CoreCell ~ NARROW [CDProperties.GetDesignProp [comm.design, $DrcCoreCircularity]]; abort: REF BOOL _ NEW [BOOL_FALSE]; ListDRV: PROC [comm: CDSequencer.Command] ~ BEGIN EnumerateCore [coreCell, PrintDRV, comm.design.technology, abort] END; -- ListDRV TerminalIO.PutRope ["Design rule violations stored in Core:\n"]; CDSequencer.UseAbortFlag [comm.design, abort]; IF (coreCell = NIL) THEN TerminalIO.PutRope ["None recorded.\n"] ELSE [] _ CDCommandOps.DoWithResource [ListDRV, comm, $Drc] END; -- ListAll RegressionTest: PROC ~ BEGIN state: Misc ~ NEW [Stuff]; dummy: REF BOOL ~ NEW [BOOL _ FALSE]; test: CD.Design ~ CDIO.ReadDesign [regressionDesign]; tech: Sinix.Mode; ok, ko: CD.Object; IF (test = NIL) THEN GOTO maintenanceProblem; tech _ SinixOps.GetExtractMode [test.technology]; state.geom _ tech.decoration; ok _ CDDirectory.Fetch [test, "ok"].object; IF (ok = NIL) THEN GOTO maintenanceProblem; TerminalIO.PutRope ["\n"]; WITH Sinix.Extract [obj: ok, mode: tech].result SELECT FROM coreCell: Drc.CoreCell => IF (Drc.CheckDesignRules [cell: coreCell, tech: IF religion THEN cMosBsimple ELSE cMosBcomplete, external: coreCell.public, stopFlag: dummy, layout: state.geom] > 0) THEN EnumerateCore [coreCell, ProblemMessage, state, dummy]; ENDCASE => ERROR; TerminalIO.PutRope ["\n"]; ko _ CDDirectory.Fetch [test, "ko"].object; IF (ko = NIL) THEN GOTO maintenanceProblem; WITH Sinix.Extract [obj: ko, mode: tech].result SELECT FROM coreCell: Drc.CoreCell => BEGIN [] _ Drc.CheckDesignRules [cell: coreCell, tech: IF religion THEN cMosBsimple ELSE cMosBcomplete, external: coreCell.public, stopFlag: dummy, layout: state.geom]; EnumerateCore [coreCell, UncheckedMessage, state, dummy] END; ENDCASE => ERROR; EXITS maintenanceProblem => BEGIN TerminalIO.PutRope ["Please inform DRC maintainers that the self verification is broken.\n"] END END; -- RegressionTest VerifyRect: CD.DrawProc ~ BEGIN specialLayers: CD.Layer = 5; -- combined, highLightShade, highLightError, pinRepresentation lambda: CD.Number ~ pr.design.technology.lambda; IF (inst.ob.class.objectType = $Rect) AND (inst.ob.layer >= specialLayers) AND (CDProperties.GetObjectProp [inst.ob, $DrcTrace] = NIL) THEN DrcDebug.dLog.PutF [format: "Failed to check rectangle at [%g, %g] %l %g%l\n", v1: IO.int [trans.off.x / lambda], v2: IO.int [trans.off.y / lambda], v3: IO.rope ["b"], v4: IO.rope [CDOps.LayerRope[inst.ob.layer]], v5: IO.rope ["B"]] END; -- VerifyRect VerifyObjects: PROC [design: CD.Design, obj: CD.Object] ~ BEGIN envelope: CD.Instance = CDInstances.NewInst [obj]; drawRef: CD.DrawRef _ CD.CreateDrawRef [[design: design]]; drawRef.drawChild _ VerifyRect; envelope.trans.off _ [0, 0]; obj.class.drawMe [envelope, envelope.trans, drawRef] END; -- VerifyObjects EmulateSoS: UserProfile.ProfileChangedProc ~ BEGIN religion _ UserProfile.Boolean ["Genista.EmulateSoS", FALSE] END; -- EmulateSoS Timing: UserProfile.ProfileChangedProc ~ BEGIN timing _ UserProfile.Boolean ["Genista.Timing", FALSE] END; -- Timing [] _ CDProperties.RegisterProperty [$DrcNr, $gbb]; [] _ CDProperties.RegisterProperty [$DrcCoreCircularity, $gbb]; CDSequencer.ImplementCommand [key: $DrcSel, proc: Execute, queue: doQueue]; CDSequencer.ImplementCommand [key: $DrcDir, proc: List, queue: doQueue]; CDSequencer.ImplementCommand [key: $DrcAll, proc: ListAll, queue: doQueue]; UserProfile.CallWhenProfileChanges [EmulateSoS]; UserProfile.CallWhenProfileChanges [Timing]; TerminalIO.PutRope ["DRC package Genista installed.\n"]; IF UserProfile.Boolean ["Genista.RegressionTest", TRUE] THEN RegressionTest END.  DrcCommandImpl.mesa Copyright Σ 1987 by Xerox Corporation. All rights reserved. Rewritten by gbb January 12, 1987 11:53:06 am PST gbb March 30, 1987 5:18:53 pm PST Interface to ChipNDale. Called by ChipNDale upon activation of the command. Protected procedure. Enumerates the cell and does action on each subcell. [cell: Drc.CoreCell, data: REF ANY _ NIL] Annotates the ChipNDale design with the design rule violations. [cell: Drc.CoreCell, data: REF ANY _ NIL] Asserts that correct cells are not flagged for violations [cell: Drc.CoreCell, data: REF ANY _ NIL] Asserts that correct cells are not flagged for violations Called by ChipNDale upon activation of the command. [cell: Drc.CoreCell, data: REF ANY _ NIL] Called by ChipNDale upon activation of the command. Protected procedure. Makes a DRC run over the test file to assess the correctnes of the implementation. The test file is not ready as yet. [inst: Instance, trans: Transformation, pr: REF DrawInformation] Traverses the cell and reports undiscovered rectangles. Κ z˜šœ™Jšœ<™Kšœ žœžœ8˜MMšœN˜Nšžœžœž˜š žœžœžœ$žœžœž˜BKšœŽ˜ŽJšžœ˜——Kšžœ‘˜—š œ ž˜ Kšœžœžœžœ™)K™9Kšœžœ˜Kšœžœ4˜>šžœ9žœžœž˜JKšœP˜PKšœžœ.žœ ˜VKšž˜—Kšžœ‘˜—š œ ž˜"Kšœžœžœžœ™)K™9Kšœžœ˜Kšœžœ4˜>Kšœ žœžœ8˜Mš žœžœžœžœž˜,Kšœ žœžœ.˜HKšœžœ1žœ˜@Kšžœžœ0žœ#žœ˜wKšžœ9žœ#žœ˜xKšž˜—Kšžœ‘˜—š œžœž˜.K™3Kšœ žœžœžœ4˜UKšžœžœžœ<˜VKšžœMžœ˜gKšžœ‘˜ —š œ ž˜Kšœžœžœžœ™)Kšœ žœžœ8˜Mšžœžœžœž˜Kšœ žœ"˜0Kšœžœ žœžœ˜3Kšœ0žœžœ˜Xš žœžœžœ$žœžœž˜BJš œ3žœžœžœžœžœ˜­Jšž˜—Jšž˜—Kšžœ‘ ˜—š œžœž˜1K™3KšœžœA˜`Lš œžœžœžœžœžœ˜#š œžœž˜1K™KšœA˜AKšžœ‘ ˜—Mšœ@˜@Kšœ.˜.Kšžœ žœžœ(˜@Kšžœ7˜;Kšžœ‘ ˜—š œžœž˜K™uKšœžœ ˜Kš œžœžœžœžœžœ˜%Kšœžœ žœ˜5Kšœ˜Kšœžœ˜Mšžœ žœžœžœ˜-Kšœ1˜1Kšœ˜Kšœ+˜+Kšžœžœžœžœ˜+Kšœ˜šžœ,žœž˜;šœ˜Kš žœ.žœ žœ žœUžœ8˜β—Kšžœžœ˜—Kšœ˜Kšœ+˜+Kšžœžœžœžœ˜+šžœ,žœž˜;šœž˜Kšœ1žœ žœ žœP˜’Kšœ8˜8Kšžœ˜—Kšžœžœ˜—šž˜šœž˜Kšœ\˜\Kšž˜——Kšžœ‘˜—š  œžœ ž˜Kšœ,žœ™@Kšœžœ ‘>˜[Kšœžœ&˜0š žœ$žœ"žœ4žœž˜‹Kš œSžœ!žœ!žœžœ,žœ ˜θ—Kšžœ‘ ˜—š   œžœ žœžœ ž˜?K™7Kšœ žœ&˜2Kšœ žœ žœ"˜:Kšœ˜Kšœ˜Jšœ4˜4Kšžœ‘ ˜—š  œ#ž˜2Lšœ6žœ˜