<> <> <> <> <> <> DIRECTORY BasicTime USING [GMT, Now, Period], CD USING [CreateDrawRef, Design, DrawProc, DrawRef, Instance, InstanceList, Layer, Number, Object], CDCommandOps USING [CallWithResource], CDDirectory USING [Fetch, Name], CDEvents USING [EventProc, RegisterEventProc], CDInstances USING [NewInst], CDMenus USING [CreateEntry], CDMenuSpecials USING [SelectOneOf], CDOps USING [InstList, LayerName], CDProperties USING [GetDesignProp, GetObjectProp, PutDesignProp, RegisterProperty], CDSequencer USING [Command, CommandRec, ExecuteCommand, ImplementCommand], Core USING [CellType, Wire], CoreClasses USING [recordCellClass, RecordCellType], CoreOps USING [GetCellTypeName, PrintCellType], CoreProperties USING [GetProp], IO USING [int, noWhereStream, PutF, PutFR, PutFR1, rope, STREAM], PrincOpsUtils USING [], Process USING [priorityBackground, SetPriority], Rope USING [Cat, ROPE], Sinix USING [Extract, Mode], SinixCMos USING [extractAMode, extractBMode], SinixNMos USING [extractMode], SoS USING [CheckDesignRules, coreInconsistent, DRV, DRVkey, ErrorRect], SymTab USING [Create, Delete, EachPairAction, Fetch, GetSize, Insert, Pairs, Ref], TerminalIO USING [WriteRope, WriteLn], ViewerIO USING [CreateViewerStreams], ViewerTools USING [FindExistingViewer, Viewer]; SoSCommandImpl: CEDAR PROGRAM IMPORTS BasicTime, CD, CDCommandOps, CDDirectory, CDEvents, CDInstances, CDMenus, CDMenuSpecials, CDOps, CDProperties, CDSequencer, CoreClasses, CoreOps, CoreProperties, IO, Process, Rope, Sinix, SinixCMos, SinixNMos, TerminalIO, ViewerIO, ViewerTools, SoS, SymTab ~ BEGIN debug: BOOL _ FALSE; -- to start debugging enter: _ SoSCommandImpl.Debug[] timing: BOOL _ FALSE; -- turn off fast mouse failureReason: Rope.ROPE; failureTorch: REF ANY; dLog: IO.STREAM _ IO.noWhereStream; currentLambda: CD.Number; -- sorry for the hack instead of using the handle DRVSummary: TYPE = SymTab.Ref; Execute: PROC [comm: CDSequencer.Command] ~ BEGIN <> ENABLE SoS.coreInconsistent [failureReason, failureTorch] => GOTO failure; violations: DRVSummary = SymTab.Create []; abort: REF BOOL _ NEW [BOOL _ FALSE]; ExtractAndCheck: PROC [comm: CDSequencer.Command] ~ BEGIN <> startTime1, startTime2, lapTime, stopTime: BasicTime.GMT; tech: Sinix.Mode; cdObjHint: ATOM _ $PWCoreLayout; SELECT comm.design.technology.key FROM $cmos => tech _ SinixCMos.extractAMode; $cmosB => tech _ SinixCMos.extractBMode; $nmos => tech _ SinixNMos.extractMode; ENDCASE => BEGIN TerminalIO.WriteRope [Rope.Cat ["The technology ", comm.design.technology.name, " is not implemented in Sinix or SoS.\n"]]; RETURN END; FOR all: CD.InstanceList _ CDOps.InstList [comm.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: Core.CellType => BEGIN lapTime _ BasicTime.Now []; IF debug THEN CoreOps.PrintCellType [coreCell, dLog]; startTime2 _ BasicTime.Now []; [] _ SoS.CheckDesignRules [cell: coreCell, design: comm.design, abortFlag: abort, cdObjKey: cdObjHint, cdInstKey: tech.instanceProp, cdInstListKey: tech.wireGeometryProp]; stopTime _ BasicTime.Now []; IF debug THEN BEGIN currentLambda _ comm.design.technology.lambda; VerifyObjects [comm.design, all.first.ob] END; IF timing THEN BEGIN TerminalIO.WriteRope [Rope.Cat ["\nElapsed time for extraction: ", TimeToRope [startTime1, lapTime]]]; TerminalIO.WriteRope [Rope.Cat [". Elapsed time for DRC: ", TimeToRope [startTime2, stopTime]]]; TerminalIO.WriteRope [Rope.Cat ["\nTotal elapsed time: ", TimeToRope [startTime1, stopTime], "\n"]] END; UpdateDRVDirectory [coreCell, violations] END; w: Core.Wire => NULL; ENDCASE => NULL END -- if selected ENDLOOP END; -- ExtractAndCheck TerminalIO.WriteRope ["SoS.\n"]; CDProperties.PutDesignProp [comm.design, $SoSCmdDir]; [] _ CDCommandOps.CallWithResource [ExtractAndCheck, comm, $SoS, abort]; TerminalIO.WriteRope ["SoS done.\n"]; IF (violations.GetSize[] > 0) THEN BEGIN TerminalIO.WriteRope ["Summary of design rule violations:\n"]; CDProperties.PutDesignProp [comm.design, $SoSCmdDir, violations]; [] _ violations.Pairs [PrintDRVSummary] END; EXITS failure => BEGIN TerminalIO.WriteRope [failureReason]; TerminalIO.WriteRope [". Core structure inconsistent. SoS aborted.\n"] END END; -- Execute List: PROC [comm: CDSequencer.Command] ~ BEGIN <> violations: DRVSummary = NARROW [CDProperties.GetDesignProp [comm.design, $SoSCmdDir]]; abort: REF BOOL _ NEW [BOOL_FALSE]; ListDRV: PROC [comm: CDSequencer.Command] ~ BEGIN <> existsInCD: BOOL; drv: SoS.DRV; cell: Rope.ROPE _ CDMenuSpecials.SelectOneOf [violations, "Cells with errors"]; <> IF (cell = NIL) THEN RETURN; -- no selection drv _ NARROW [SymTab.Fetch[violations, cell].val, SoS.DRV]; FOR e: LIST OF SoS.ErrorRect _ drv.places, e.rest WHILE e # NIL DO TerminalIO.WriteRope [e.first.msg]; TerminalIO.WriteLn; IF abort^ THEN ERROR ABORTED ENDLOOP; existsInCD _ CDDirectory.Fetch [comm.design, cell].found; IF NOT existsInCD THEN TerminalIO.WriteRope ["No ChipNDale correspondent found for this cell.\n"] ELSE BEGIN nestedCmd: CDSequencer.Command _ NEW [CDSequencer.CommandRec _ [key: $PushNamed, design: comm.design, data: cell, ref: comm.ref]]; TerminalIO.WriteRope ["Trying to push into ChipNDale correspondent for this cell. Pop out of current cell if it fails.\n"]; CDSequencer.ExecuteCommand [comm: nestedCmd, queue: dontQueue]; <> <> <> <> <> END END; -- ListDRV TerminalIO.WriteRope ["List design rule violations.\n"]; IF (violations = NIL) THEN TerminalIO.WriteRope ["None available.\n"] ELSE [] _ CDCommandOps.CallWithResource [ListDRV, comm, $SoS, abort]; TerminalIO.WriteRope ["Design rule violations listed.\n"] END; -- List ListAll: PROC [comm: CDSequencer.Command] ~ BEGIN <> violations: DRVSummary = NARROW [CDProperties.GetDesignProp [comm.design, $SoSCmdDir]]; abort: REF BOOL _ NEW [BOOL_FALSE]; PrintDRV: SymTab.EachPairAction ~ BEGIN <<[key: Key, val: Val] RETURNS [quit: BOOL]>> drv: SoS.DRV = NARROW [val]; TerminalIO.WriteRope [IO.PutFR ["cell %g, %g violations:\n", IO.rope [key], IO.int [drv.count]]]; FOR e: LIST OF SoS.ErrorRect _ drv.places, e.rest WHILE e # NIL DO TerminalIO.WriteRope [e.first.msg]; TerminalIO.WriteLn; IF abort^ THEN ERROR ABORTED ENDLOOP; RETURN [abort^] END; -- PrintDRV ListDRV: PROC [comm: CDSequencer.Command] ~ BEGIN <> IF violations.Pairs [PrintDRV] THEN TerminalIO.WriteRope ["Aborted.\n"] END; -- ListDRV TerminalIO.WriteRope ["List all design rule violations.\n"]; IF (violations = NIL) THEN TerminalIO.WriteRope ["None available.\n"] ELSE [] _ CDCommandOps.CallWithResource [ListDRV, comm, $SoS, abort]; TerminalIO.WriteRope ["All design rule violations listed.\n"] END; -- ListAll UpdateDRVDirectory: PROC [cell: Core.CellType, dir: DRVSummary] ~ BEGIN <> name: Rope.ROPE = CoreOps.GetCellTypeName[cell]; IF SymTab.Fetch[dir, name].found THEN RETURN; -- prune SELECT cell.class FROM CoreClasses.recordCellClass => BEGIN data: CoreClasses.RecordCellType = NARROW [cell.data]; drv: SoS.DRV = NARROW [CoreProperties.GetProp [cell.properties, SoS.DRVkey]]; FOR sub: NAT IN [0 .. data.size) DO UpdateDRVDirectory [data.instances[sub].type, dir] ENDLOOP; IF (drv # NIL) THEN [] _ dir.Insert [name, drv] END; ENDCASE => NULL END; -- UpdateDRVDirectory PrintDRVSummary: SymTab.EachPairAction ~ BEGIN <<[key: Key, val: Val] RETURNS [quit: BOOL]>> drv: SoS.DRV = NARROW [val]; TerminalIO.WriteRope [IO.PutFR ["cell %g: %g\n", IO.rope [key], IO.int [drv.count]]]; RETURN [FALSE] END; -- PrintDRVSummary InvalidateDRV: CDEvents.EventProc ~ BEGIN <<[event: REF, design: CD.Design, x: REF] RETURNS [dont: BOOL _ FALSE]>> <> violations: DRVSummary = NARROW [CDProperties.GetDesignProp [design, $SoSCmdDir]]; cellName: Rope.ROPE = CDDirectory.Name [NARROW [x, CD.Object]]; IF (violations # NIL) AND (cellName # NIL) THEN [] _ violations.Delete [cellName] END; -- InvalidateDRV VerifyRect: CD.DrawProc ~ BEGIN <<[inst: Instance, pos: Position, orient: Orientation, pr: REF DrawInformation]>> specialLayers: CD.Layer = 5; -- combined, highLightShade, highLightError, pinRepresentation IF (inst.ob.class.objectType = $Rect) AND (inst.ob.layer >= specialLayers) AND (CDProperties.GetObjectProp [inst.ob, $SoSSeparationChecked] = NIL) THEN IO.PutF [stream: dLog, format: "Failed to check rectangle at [%g, %g] %l %g%l\n", v1: IO.int [pos.x / currentLambda], v2: IO.int [pos.y / currentLambda], v3: IO.rope ["b"], v4: IO.rope [CDOps.LayerName[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.location _ [0, 0]; obj.class.drawMe [envelope, envelope.location, 0, drawRef] END; -- VerifyObjects TimeToRope: PROC [from, to: BasicTime.GMT] RETURNS [time: Rope.ROPE] ~ BEGIN <> tmp: Rope.ROPE; sec: INT = BasicTime.Period [from, to]; min: INT = sec / 60; h: INT = min / 60; tmp _ IO.PutFR1 [value: IO.int [h]]; time _ SELECT h FROM = 0 => "00", < 10 => Rope.Cat ["0", tmp], ENDCASE => tmp; tmp _ IO.PutFR1 [value: IO.int [min MOD 60]]; time _ Rope.Cat [time, ":", SELECT min FROM = 0 => "00", < 10 => Rope.Cat ["0", tmp], ENDCASE => tmp]; tmp _ IO.PutFR1 [value: IO.int [sec MOD 60]]; time _ Rope.Cat [time, ":", SELECT sec FROM = 0 => "00", < 10 => Rope.Cat ["0", tmp], ENDCASE => tmp] END; -- TimeToRope Debug: PROC ~ BEGIN <> viewer: ViewerTools.Viewer; dummy: IO.STREAM; debug _ TRUE; -- Get all in one viewer _ ViewerTools.FindExistingViewer ["SoS debug"]; IF viewer # NIL THEN [in: dummy, out: dLog] _ ViewerIO.CreateViewerStreams ["SoS debug", viewer] ELSE BEGIN viewer _ ViewerTools.FindExistingViewer ["Terminal"]; [in: dummy, out: dLog] _ ViewerIO.CreateViewerStreams ["Terminal", viewer] END END; -- Debug [] _ CDProperties.RegisterProperty [$SoSCmdDir, $gbb]; CDSequencer.ImplementCommand [key: $SoSSel, proc: Execute, queue: doQueue]; CDMenus.CreateEntry [menu: $ProgramMenu, entry: "Extract & DRC (Sinix & SoS)", key: $SoSSel]; CDSequencer.ImplementCommand [key: $SoSDir, proc: List, queue: doQueue]; CDMenus.CreateEntry [menu: $ProgramMenu, entry: "List Violations (SoS)", key: $SoSDir]; CDSequencer.ImplementCommand [key: $SoSAll, proc: ListAll, queue: doQueue]; CDMenus.CreateEntry [menu: $ProgramMenu, entry: "List All Violations (SoS)", key: $SoSAll]; CDEvents.RegisterEventProc [proc: InvalidateDRV, event: $AfterCellReplacement]; CDEvents.RegisterEventProc [proc: InvalidateDRV, event: $AfterChange]; IF debug THEN Debug []; TerminalIO.WriteRope ["SoS package loaded.\n"] END. <> <> <> <> <> <> <> <> <> <> <> <<>>