<> <> <> <> <> <> <> <> DIRECTORY Atom USING [GetPName], BasicTime USING [Now], CD, CDAtomicObjects, CDBasics, CDDirectory USING [Fetch], CDErrors USING [IncludeMessage, RemoveMessages], CDInstances, CDProperties, CDRects, CDSimpleRules USING [MaxWidth, MinDist, MinWidth, NotKnown], CDSymbolicObjects, Core USING [CellType, Properties, Wire], CoreClasses USING [recordCellClass, RecordCellType, transistorCellClass, unspecifiedCellClass], CoreGeometry, CoreOps USING [CreateWires, CopyWire, GetCellTypeName, GetShortWireName, SetShortWireName], CoreProperties, FS USING [StreamOpen], IO USING [card, char, Close, Error, ErrorCode, int, noWhereStream, Put1, PutF, PutF1, PutFR, PutFR1, PutRope, refAny, rope, STREAM, time], RefTab USING [Create, EachPairAction, Fetch, Insert, Pairs, Ref, SeqIndex], Rope USING [Cat, ROPE], SoS, SoSTNT USING [BlowTNT, InitTNT, InTNT, RememberTNT, SweepTNT, TNT], ViewerIO USING [CreateViewerStreams], ViewerTools USING [FindExistingViewer, Viewer]; SoSImpl: CEDAR PROGRAM IMPORTS Atom, BasicTime, CD, CDBasics, CDDirectory, CDErrors, CDInstances, CDProperties, CDRects, CDSimpleRules, CDSymbolicObjects, CoreClasses, CoreGeometry, CoreOps, CoreProperties, FS, IO, RefTab, Rope, SoSTNT, ViewerIO, ViewerTools EXPORTS SoS SHARES CDRects ~ BEGIN OPEN SoSTNT; debug: BOOL _ FALSE; -- to start debugging enter: _ SoSImpl.Debug[] occDebug: BOOL = FALSE; -- for occasional debugging useTNT: BOOL = TRUE; -- for timing analysis only persist: BOOL _ TRUE; -- depends on Sinix (try hard to flag CD design) fast: BOOL _ TRUE; -- if FALSE then SoS is purely "object oriented" break: SIGNAL = CODE; -- for debugging; related to property $SoSBreak panic: SIGNAL = CODE; -- cannot communicate violations coreMess: SIGNAL [reason: Rope.ROPE, torch: REF ANY] = CODE; -- clean up before issuing coreInconsistent coreInconsistent: PUBLIC ERROR [reason: Rope.ROPE, torch: REF ANY] = CODE; mLog: IO.STREAM; -- messages eLog: IO.STREAM; -- error log dLog: IO.STREAM _ IO.noWhereStream; -- debugging <> State: TYPE = SoS.State; -- REF StateRec; StateRec: TYPE = SoS.StateRec; Wire: TYPE = Core.Wire; DRV: TYPE = SoS.DRV; -- REF DesignRuleViolation DesignRuleViolation: TYPE = SoS.DesignRuleViolation; <> ErrorRect: TYPE = SoS.ErrorRect; <> <> checked: ATOM = CoreProperties.RegisterProperty [$SoSWasHere]; <> DRVkey: PUBLIC ATOM _ CoreProperties.RegisterProperty [$SoSError]; <> bbKey: ATOM _ CoreProperties.RegisterProperty [$SoSbb]; <> trace: ATOM = CoreProperties.RegisterProperty [$SoSSeparationChecked]; <> <> analysis: ATOM = CoreProperties.RegisterProperty [$SoSAnalysis]; cellHull: ATOM = CoreProperties.RegisterProperty [$SoSHull]; matToCell: ATOM = CoreProperties.RegisterProperty [$SoSmc]; cellToCell: ATOM = CoreProperties.RegisterProperty [$SoScc]; <> rectClass: ATOM = $Rect; pinClass: ATOM = $PinOb0; <> doNotAnalyse: ATOM = $DoNotDRC; previousTechnology: CD.Technology _ NIL; previousMaxSeparation: CD.Number _ 75 * 8; specialLayers: CD.Layer = MAX [CD.shadeLayer, CD.errorLayer, CD.backgroundLayer, CD.outlineLayer, CD.selectionLayer, CD.commentLayer] + 1; <> <> errorFeedbackCutOff: CARDINAL = 50; -- after this number of errors, a | is no longer displayed in the ChipNDale Terminal viewer (if it may be displayed at all). WireSet: TYPE = REF WireSetRec; -- the wires of a set of cells WireSetRec: TYPE = RECORD [elt: SEQUENCE size: NAT OF Wire]; PropSet: TYPE = REF PropSetRec; -- the properties of a set of cells PropSetRec: TYPE = RECORD [p: SEQUENCE size: NAT OF Core.Properties]; <> CheckDesignRules: PUBLIC PROC [cell: Core.CellType, design: CD.Design _ NIL, abortFlag: REF BOOL _ NIL, attributes: CoreGeometry.Decoration] RETURNS [quantity: CARDINAL _ 1] ~ BEGIN <> ENABLE BEGIN IO.Error => IF ec = StreamClosed THEN BEGIN s: IO.STREAM; m: BOOL = (stream = mLog); IF m THEN StartLog [] ELSE Debug []; s _ IF m THEN mLog ELSE dLog; CONTINUE END; panic => GOTO paranoia END; state: State _ NEW [StateRec]; messy, okToType: BOOL _ FALSE; abortionCause: Rope.ROPE; debugTorch: REF ANY; shadowCell: Core.CellType; -- to be implemented fakeActual: Wire; cellName: Rope.ROPE = CoreOps.GetCellTypeName [cell]; designName: Rope.ROPE = IF design#NIL THEN design.name ELSE "in the sky"; eLog _ FS.StreamOpen [fileName: "[]<>Temp>DRC>SoS.log", accessOptions: create, keep: 5, extendFileProc: NIL, remoteCheck: FALSE, wDir: NIL]; -- keep is 5 because of incremental use eLog.PutF1 ["Error log by SoS. Design: %g\n\n", IO.rope [designName]]; <> shadowCell _ CopyCell [cell]; -- to be implemented <> mLog.PutF [format: "\nChecking wire geometry in cell %l%g%l of design %g\n", v1: IO.rope ["b"], v2: IO.rope [cellName], v3: IO.rope ["B"], v4: IO.rope [designName]]; IF debug THEN IO.PutF [stream: dLog, format: "\n%g. design: %g, cell: %g\n", v1: IO.time [], v2: IO.rope [designName], v3: IF cellName = NIL THEN IO.refAny [shadowCell] ELSE IO.rope [cellName]]; state.design _ design; state.abort _ IF abortFlag # NIL THEN abortFlag ELSE NEW [BOOL _ FALSE]; IF useTNT THEN state.nt _ InitTNT []; IF (design = NIL) OR (design.technology = NIL) THEN BEGIN state.maxSeparation _ previousMaxSeparation _ 75 * 8; <> previousTechnology _ NIL END ELSE IF design.technology # previousTechnology THEN BEGIN previousMaxSeparation _ ComputeMaxSeparation [design.technology]; previousTechnology _ design.technology END; state.maxSeparation _ previousMaxSeparation; state.globalErrorCount _ 0; state.attributes _ attributes; <> fakeActual _ CoreOps.CopyWire [shadowCell.public]; CheckCoreCell [self: shadowCell, state: state, actual: fakeActual, loc: [0, 0], orient: original ! coreMess => {messy _ TRUE; abortionCause _ reason; debugTorch _ torch; CONTINUE}]; IF useTNT THEN BlowTNT [state.nt]; IF messy THEN BEGIN <> IF debug THEN break; cell.properties _ CoreProperties.PutProp [shadowCell.properties, checked, NIL]; <> eLog.PutRope ["\nDRC failed. Your Core data structure is busted! You lose, you lose."]; eLog.Close []; coreInconsistent [abortionCause, debugTorch] END; < 0 and we do not know whether what we found in it is meaningful.>> quantity _ state.globalErrorCount; <> mLog.PutF [format: "\nNumber of new design violations found: %l%g%l\n", v1: IO.rope ["b"], v2: IO.card [state.globalErrorCount], v3: IO.rope ["B"]]; <> eLog.PutRope ["\nDRC terminated normally."]; eLog.Close []; EXITS <> paranoia => -- cannot communicate with anybody {eLog.PutRope ["\nThis is paranoia."]; eLog.Close []} END; -- CheckDesignRules <> EnumerateGeometry: PROC [state: State, wire: Wire, eachRect: PROC [CD.Rect, CD.Layer]] = { FOR list: LIST OF CD.Instance _ CoreGeometry.GetGeometry[state.attributes, wire], list.rest WHILE list#NIL DO instance: CD.Instance = list.first; SELECT TRUE FROM instance.ob.class=CDRects.bareRectClass => IF instance.ob.layer>=specialLayers AND CD.LayerKey[instance.ob.layer]#NIL THEN eachRect[CDInstances.InstRectO[instance], instance.ob.layer]; -- Filter out the special layers. Also the extractor creates material at illegal levels. We try heuristically to filter it out here. CDSymbolicObjects.IsSymbolicOb[instance.ob] => {}; ENDCASE => FOR rList: CDAtomicObjects.DrawList _ CoreGeometry.FlattenAtomic[instance.ob], rList.rest WHILE rList#NIL DO eachRect[ CDBasics.MapRect[rList.first.r, instance.tran], rList.first.layer ]; ENDLOOP; ENDLOOP; }; GetObject: PROC [cell: Core.CellType, state: State] RETURNS [obj: CD.Object] ~ INLINE BEGIN obj _ NARROW [CoreProperties.GetProp [cell.properties, state.cdObjKey], CD.Object]; IF persist AND (obj=NIL) AND (state.design#NIL) THEN obj _ CDDirectory.Fetch [state.design, CoreOps.GetCellTypeName[cell]].object; RETURN [obj]; END; -- GetObject <> CopyCell: PROC [original: Core.CellType] RETURNS [copy: Core.CellType] ~ BEGIN <> copy _ original -- << Yuck. Terrible hack. >> To be implemented END; -- CopyCell CheckCell: TYPE = SoS.CheckCell; <> CheckCoreCell: CheckCell ~ BEGIN Send: PROC ~ INLINE BEGIN check: REF CheckCell _ NARROW [CoreProperties.GetProp [self.properties, analysis]]; IF check = NIL THEN check _ NARROW [CoreProperties.GetProp [self.class.properties, analysis]]; IF check = NIL THEN BEGIN obj: CD.Object = GetObject [self, state]; IF obj = NIL THEN RETURN; -- Cell contains no rectangles check _ NEW [CheckCell _ DoNotCheck]; MarkError [self, state, [obj.class.interestRect[obj], "Cell has no provisions to be checked"]] END; check^ [self, state, actual, loc, trans.orient] END; -- Send IF fast THEN SELECT self.class FROM CoreClasses.recordCellClass => CheckRecord [self, state, actual, loc, trans.orient]; CoreClasses.transistorCellClass => CheckTransistor [self, state, actual, loc, trans.orient]; CoreClasses.unspecifiedCellClass => NULL; ENDCASE => Send [] ELSE Send [] END; -- CheckCoreCell CheckRecord: CheckCell ~ BEGIN <<[self: Core.CellType, state: State, actual: Wire, loc: CD.Position, trans.orient: CD.Orientation]>> origin: CD.Position = [0, 0]; cellData: CoreClasses.RecordCellType; bindingTable: RefTab.Ref; boundInternal: Wire; propagatedActuals: WireSet; -- one wire per subcell savedProps: PropSet; -- holds properties during recursion ownName: Rope.ROPE = CoreOps.GetCellTypeName [self]; IF (CoreProperties.GetProp [self.properties, doNotAnalyse]#NIL) OR (CoreProperties.GetProp[self.properties, checked]#NIL) THEN RETURN; mLog.Put1 [IO.char ['.]]; IF debug THEN IO.PutF [stream: dLog, format: "\nChecking cell %l%g%l .\n", v1: IO.rope ["e"], v2: IF ownName = NIL THEN IO.refAny [self] ELSE IO.rope [ownName], v3: IO.rope ["E"]]; IF state.abort^ THEN ERROR ABORTED; ClearErrors [self, state]; cellData _ NARROW [self.data, CoreClasses.RecordCellType]; <> savedProps _ NEW [PropSetRec[actual.size]]; FOR p: NAT IN [0 .. actual.size) DO savedProps[p] _ actual[p].properties; -- modified by BS on October 26, 1986 8:55:22 pm PST ENDLOOP; bindingTable _ CreateBindingTable [actual: actual, public: self.public]; boundInternal _ BindInternal [bindingTable, cellData.internal, state]; IF occDebug THEN BEGIN dLog.PutF1 ["Binding and propagating: %g. Binding table:\n", IO.rope [ownName]]; PrintBinding [bindingTable]; dLog.PutF1 ["Bound internal of %g:\n", IO.rope [ownName]]; PrintWire [boundInternal] END; <> propagatedActuals _ NEW [WireSetRec[cellData.size]]; FOR sub: NAT IN [0 .. cellData.size) DO propagatedActuals[sub] _ PropagateBinding [state, bindingTable, cellData.instances[sub].actual] ENDLOOP; FlushBindingTable [bindingTable]; <> FOR sub: NAT IN [0 .. cellData.size) DO cdInst: CD.Instance = CoreGeometry.GetTransf[state.attributes, cellData.instances[sub]]; IF (cdInst = NIL) THEN coreMess ["Core record cell has no geometry (1)", cellData]; CheckCoreCell [self: cellData.instances[sub].type, state: state, actual: propagatedActuals[sub], loc: CDBasics.AddPoints [loc, cdInst.trans.off], orient: CDBasics.ComposeOrient [trans.orient, cdInst.trans.orient]] ENDLOOP; <> IF occDebug THEN BEGIN dLog.PutF1 ["Verifying: %g\nbound internal:\n", IO.rope [ownName]]; PrintWire [boundInternal] END; <> FOR i: NAT IN [0 .. cellData.internal.size) DO FOR j: NAT IN [i .. cellData.internal.size) DO <> MaterialSeparation [state: state, cell: self, w1: boundInternal[i], w2: boundInternal[j], loc1: origin, loc2: origin, orient1: original, orient2: original] ENDLOOP; WidthCheck [self, state, boundInternal[i]] ENDLOOP; <> FOR sub: NAT IN [0 .. cellData.size) DO cdInst: CD.Instance = CoreGeometry.GetTransf[state.attributes, cellData.instances[sub]]; IF (cdInst = NIL) THEN coreMess ["Core record cell has no geometry (2)", cellData]; FOR i: NAT IN [0 .. cellData.internal.size) DO MaterialToCellSeparation [state: state, self: cellData.instances[sub].type, actual: propagatedActuals[sub], wire: cellData.internal[i], father: self, -- for error marking materialLoc: loc, cellLoc: cdInst.trans.off, materialOrient: trans.orient, cellOrient: cdInst.orientation] ENDLOOP ENDLOOP; <> IF useTNT THEN SweepTNT [state.nt]; FOR sub1: NAT IN [0 .. cellData.size) DO cdInst1: CD.Instance = CoreGeometry.GetTransf[state.attributes, cellData.instances[sub1]]; IF (cdInst1 = NIL) THEN coreMess ["Core record cell has no geometry (3)", cellData]; FOR sub2: NAT IN (sub1 .. cellData.size) DO cdInst2: CD.Instance = CoreGeometry.GetTransf[state.attributes, cellData.instances[sub2]]; IF (cdInst2 = NIL) THEN coreMess ["Core record cell has no geometry (4)", cellData]; IF useTNT AND (InTNT [state.nt, cdInst1, cdInst2, propagatedActuals[sub1], propagatedActuals[sub2]]) THEN LOOP; CellToCellSeparation [state: state, self: cellData.instances[sub1].type, otherCell: cellData.instances[sub2].type, selfActual: propagatedActuals[sub1], otherActual: propagatedActuals[sub2], father: self, -- for error marking selfLoc: CDBasics.AddPoints [loc, cdInst1.trans.off], otherLoc: CDBasics.AddPoints [loc, cdInst2.trans.off], selfOrient: CDBasics.ComposeOrient [trans.orient, cdInst1.orientation], otherOrient: CDBasics.ComposeOrient [trans.orient, cdInst2.orientation]]; IF useTNT THEN RememberTNT [state.nt, cdInst1, cdInst2, propagatedActuals[sub1], propagatedActuals[sub2]] ENDLOOP ENDLOOP; <> FOR p: NAT IN [0 .. self.public.size) DO actual[p].properties _ savedProps[p]; -- BS on October 26, 1986 8:55:47 pm PST ENDLOOP; self.properties _ CoreProperties.PutProp [self.properties, checked, checked] END; -- CheckRecord CheckTransistor: CheckCell ~ BEGIN <<[self: Core.CellType, state: State, actual: Wire, loc: CD.Position, trans.orient: CD.Orientation]>> <> DoNotCheck [self, state, actual, loc, trans.orient] END; -- CheckTransistor DoNotCheck: CheckCell ~ BEGIN <<[self: Core.CellType, state: State, actual: Wire, loc: CD.Position, trans.orient: CD.Orientation]>> <<(self.class = CoreClasses.unspecifiedCellClass) OR (CoreProperties.GetProp [self.properties, doNotAnalyse]#NIL);>> self.properties _ CoreProperties.PutProp [self.properties, checked, checked] END; -- DoNotCheck RegisterAnalysisProcs: PROC ~ BEGIN <> CoreClasses.recordCellClass.properties _ CoreProperties.PutProp [ on: CoreClasses.recordCellClass.properties, prop: analysis, value: NEW [CheckCell _ CheckRecord]]; CoreClasses.transistorCellClass.properties _ CoreProperties.PutProp [CoreClasses.transistorCellClass.properties, analysis, NEW [CheckCell _ CheckTransistor]]; CoreClasses.unspecifiedCellClass.properties _ CoreProperties.PutProp [CoreClasses.unspecifiedCellClass.properties, analysis, NEW [CheckCell _ DoNotCheck]]; END; -- RegisterAnalysisProcs <> CellHullProc: TYPE = SoS.CellHullProc; <> AtomicWireHull: PROC [w: Wire, state: State] RETURNS [h: CD.Rect _ CDBasics.empty] ~ BEGIN <> stored: REF CD.Rect _ NARROW [CoreProperties.GetProp [w.properties, bbKey]]; EachRect: PROC [r: CD.Rect, l: CD.Layer] = { h.x1 _ MIN [h.x1, r.x1]; h.y1 _ MIN [h.y1, r.y1]; h.x2 _ MAX [h.x2, r.x2]; h.y2 _ MAX [h.y2, r.y2]; }; IF w.size > 0 THEN BEGIN <> <<[] _ Msg ["Your Core data structure is busted! You do not lose yet."];>> break -- you may proceede END; IF (stored # NIL) THEN RETURN [stored^]; EnumerateGeometry[state, w, EachRect]; stored _ NEW [CD.Rect _ h]; w.properties _ CoreProperties.PutProp [w.properties, bbKey, stored] END; -- AtomicWireHull CellHull: CellHullProc ~ BEGIN <> <> hull: REF CellHullProc _ NEW [CellHullProc]; SELECT self.class FROM CoreClasses.recordCellClass => hull^ _ RecordCellHull; CoreClasses.transistorCellClass => hull^ _ TransistorHull; CoreClasses.unspecifiedCellClass => hull^ _ UnspecifiedHull; ENDCASE => BEGIN hull _ NARROW [CoreProperties.GetProp [self.properties, cellHull]]; IF hull = NIL THEN hull _ NARROW [CoreProperties.GetProp [self.class.properties, cellHull]]; IF hull = NIL THEN hull^ _ UnspecifiedHull; END; RETURN [hull^ [self, state]] END; -- CellHull; RecordCellHull: CellHullProc ~ BEGIN <<[self: Core.CellType, state: State] RETURNS [h: CD.Rect _ CDBasics.empty]>> stored: REF CD.Rect _ NARROW [CoreProperties.GetProp [self.properties, bbKey]]; IF (stored = NIL) THEN BEGIN cellData: CoreClasses.RecordCellType = NARROW [self.data, CoreClasses.RecordCellType]; IF cellData.internal.size = 0 THEN break; -- you may proceede <> FOR i: NAT IN [0 .. cellData.internal.size) DO a: CD.Rect = AtomicWireHull [cellData.internal[i], state]; h.x1 _ MIN [h.x1, a.x1]; h.y1 _ MIN [h.y1, a.y1]; h.x2 _ MAX [h.x2, a.x2]; h.y2 _ MAX [h.y2, a.y2] ENDLOOP; FOR sub: NAT IN [0 .. cellData.size) DO <> r: CD.Rect = CellHull [cellData.instances[sub].type, state]; h.x1 _ MIN [h.x1, r.x1]; h.y1 _ MIN [h.y1, r.y1]; h.x2 _ MAX [h.x2, r.x2]; h.y2 _ MAX [h.y2, r.y2] ENDLOOP; stored _ NEW [CD.Rect _ h]; self.properties _ CoreProperties.PutProp [self.properties, bbKey, stored] END END; -- RecordCellHull TransistorHull: CellHullProc ~ BEGIN <<[self: Core.CellType, state: State] RETURNS [h: CD.Rect _ CDBasics.empty]>> stored: REF CD.Rect _ NARROW [CoreProperties.GetProp [self.properties, bbKey]]; IF (stored = NIL) THEN BEGIN wire: Wire = self.public; IF wire.size = 0 THEN break; -- you may proceede <> FOR i: NAT IN [0 .. wire.size) DO a: CD.Rect = AtomicWireHull [wire[i], state]; h.x1 _ MIN [h.x1, a.x1]; h.y1 _ MIN [h.y1, a.y1]; h.x2 _ MAX [h.x2, a.x2]; h.y2 _ MAX [h.y2, a.y2] ENDLOOP; stored _ NEW [CD.Rect _ h]; self.properties _ CoreProperties.PutProp [self.properties, bbKey, stored] END END; -- TransistorHull UnspecifiedHull: CellHullProc ~ BEGIN <<[self: Core.CellType, state: State] RETURNS [h: CD.Rect _ CDBasics.empty]>> stored: REF CD.Rect _ NARROW [CoreProperties.GetProp [self.properties, bbKey]]; IF (stored = NIL) THEN BEGIN stored _ NEW [CD.Rect _ h]; self.properties _ CoreProperties.PutProp [self.properties, bbKey, stored] END END; -- UnspecifiedHull RegisterPruningProcs: PROC ~ BEGIN <> CoreClasses.recordCellClass.properties _ CoreProperties.PutProp [ on: CoreClasses.recordCellClass.properties, prop: cellHull, value: NEW [CellHullProc _ RecordCellHull]]; CoreClasses.transistorCellClass.properties _ CoreProperties.PutProp [CoreClasses.transistorCellClass.properties, cellHull, NEW [CellHullProc _ TransistorHull]]; CoreClasses.unspecifiedCellClass.properties _ CoreProperties.PutProp [CoreClasses.unspecifiedCellClass.properties, cellHull, NEW [CellHullProc _ UnspecifiedHull]] END; -- RegisterPruningProcs <> CreateBindingTable: PROC [actual, public: Wire] RETURNS [bindingTable: RefTab.Ref] ~ BEGIN tableSize: RefTab.SeqIndex _ public.size; IF actual.size # public.size THEN BEGIN IF debug THEN BEGIN dLog.Put1 [IO.rope ["actual.size # public.size. Actual wire:\n"]]; PrintWire [actual]; dLog.Put1 [IO.rope ["Public wire:\n"]]; PrintWire [public]; ERROR END ELSE coreMess ["actual.size # public.size (5)", actual] END; IF (tableSize MOD 2) = 0 THEN tableSize _ tableSize.SUCC; bindingTable _ RefTab.Create [tableSize]; FOR i: NAT IN [0 .. public.size) DO [] _ RefTab.Insert [x: bindingTable, key: public[i], val: actual[i]] ENDLOOP END; -- CreateBindingTable FlushBindingTable: PROC [bindingTable: RefTab.Ref] ~ INLINE BEGIN bindingTable _ NIL END; -- FlushBindingTable PropagateBinding: PROC [state: State, bindingTable: RefTab.Ref, actual: Wire] RETURNS [boundActual: Wire] ~ BEGIN <> PropagateAtomic: PROC [state: State, bindingTable: RefTab.Ref, actual: Wire] RETURNS [boundActual: Wire] ~ INLINE BEGIN <> boundActual _ NARROW [RefTab.Fetch [bindingTable, actual].val]; <> IF boundActual = NIL THEN BEGIN name: Rope.ROPE = IF debug THEN IO.PutFR1 ["New signal # %g", IO.card [state.wireCreationCount]] ELSE "New signal by SoS"; boundActual _ CoreOps.CreateWires [size: 0, name: name]; state.wireCreationCount _ state.wireCreationCount.SUCC; [] _ RefTab.Insert [x: bindingTable, key: actual, val: boundActual] END ELSE boundActual _ CoreOps.SetShortWireName [boundActual, CoreOps.GetShortWireName[actual]] END; -- PropagateAtomic boundActual _ CoreOps.CreateWires [actual.size]; FOR i: NAT IN [0 .. actual.size) DO boundActual[i] _ PropagateAtomic [state, bindingTable, actual[i]] ENDLOOP END; -- PropagateBinding BindInternal: PROC [bindingTable: RefTab.Ref, internal: Wire, state: State] RETURNS [boundInternal: Wire] ~ BEGIN <> boundInternal _ CoreOps.CopyWire [internal]; FOR i: NAT IN [0 .. internal.size) DO b: Wire = NARROW [RefTab.Fetch [bindingTable, internal[i]].val]; <> IF b # NIL THEN BEGIN <> boundInternal[i] _ b; <> <> <> boundInternal[i].properties _ internal[i].properties; -- BS on October 26, 1986 8:56:07 pm PST END ENDLOOP END; -- BindInternal BindTransistor: PROC [public, actual: Wire, state: State] RETURNS [tw: Wire] ~ BEGIN <> tw _ CoreOps.CopyWire [public]; FOR i: NAT IN [0 .. public.size) DO tw[i] _ actual[i]; tw[i].properties _ public[i].properties; -- BS on October 26, 1986 8:56:37 pm PST ENDLOOP END; -- BindTransistor <> MaterialToCellProc: TYPE = SoS.MaterialToCellProc; <> CellToCellProc: TYPE = SoS.CellToCellProc; <> WidthCheck: PROC [c: Core.CellType, state: State, w: Wire] ~ BEGIN <> <> EachRect: PROC [r: CD.Rect, l: CD.Layer] = { min: CD.Number _ CDSimpleRules.MinWidth [l]; max: CD.Number _ CDSimpleRules.MaxWidth [l]; a: CD.Number _ MAX [(r.x2 - r.x1), (r.y2 - r.y1)]; b: CD.Number _ MIN [(r.x2 - r.x1), (r.y2 - r.y1)]; -- a and b are such that a > b IF (a < min) OR (b < min) OR (a > max) OR (b > max) THEN BEGIN <<<< Total Hack. Yuk. >>>> <> splitA: CD.Number = 3 * min; splitB: CD.Number = min; -- yuk, spit <> IF (CD.LayerKey[l] = $cut) AND (a = splitA) AND (b = splitB) THEN NULL -- mumble ELSE MarkError [c, state, [r, Rope.Cat ["Width violation on layer ", Atom.GetPName [CD.LayerKey [l]], " (wire ", CoreOps.GetShortWireName[w], ")"]]] END }; EnumerateGeometry[state, w, EachRect]; END; -- WidthCheck IsCut: PROC [layer: CD.Layer] RETURNS [BOOL] ~ INLINE BEGIN key: ATOM = CD.LayerKey[layer]; <> RETURN [key = $cut OR key = $cut2] END; <> MaterialSeparation: PROC [cell: Core.CellType, state: State, w1, w2: Wire, loc1, loc2: CD.Position, orient1, orient2: CD.Orientation] ~ BEGIN <> <> EachRect1: PROC [r1: CD.Rect, l1: CD.Layer] = { EachRect2: PROC [r2: CD.Rect, l2: CD.Layer] = { r, s: CD.Rect; sep: CD.Number; IF state.abort^ THEN ERROR ABORTED; <> IF w1 = w2 AND NOT (IsCut[l1] AND IsCut[l2]) THEN RETURN; sep _ CDSimpleRules.MinDist [l1, l2 ! CDSimpleRules.NotKnown => sep _ 0]; IF sep = 0 THEN RETURN; r2 _ CDBasics.MapRect [ r2, CDBasics.SizeOfRect[r2], -- This parameter looks wrong to me [BS] orient2, loc2]; IF w1 = w2 AND l1 = l2 AND r1 = r2 THEN RETURN; r _ CDBasics.Extend [r1, sep / 2]; s _ CDBasics.Extend [r2, sep / 2]; IF ((r.x1> MarkError [cell, state, [CDBasics.Intersection[r,s], Rope.Cat["Separation violation between ", rect1, " and ", rect2]]]; END; }; r1 _ CDBasics.MapRect [itemInCell: r1, cellSize: CDBasics.SizeOfRect[r1], -- This parameter looks wrong to me [BS] cellInstOrient: orient1, cellInstPos: loc1]; EnumerateGeometry[state, w2, EachRect2]; }; IF state.abort^ THEN ERROR ABORTED; <> IF CoreGeometry.GetGeometry[state.attributes, w1] = NIL THEN RETURN; -- Skip wires without geometry IF CoreGeometry.GetGeometry[state.attributes, w2] = NIL THEN RETURN; -- Skip wires without geometry IF NOT CDBasics.Intersect [CDBasics.Extend[AtomicWireHull[w1, state], state.maxSeparation], AtomicWireHull[w2, state]] THEN RETURN; -- or whose geometry is too far apart. EnumerateGeometry[state, w1, EachRect1]; END; -- MaterialSeparation MaterialToCellSeparation: MaterialToCellProc ~ BEGIN <<[self: Core.CellType, state: State, actual, wire: Wire, father: Core.CellType, materialLoc, cellLoc: CD.Position, materialOrient, cellOrient: CD.Orientation]>> <> Send: PROC ~ INLINE BEGIN check: REF MaterialToCellProc _ NARROW [CoreProperties.GetProp [self.properties, matToCell]]; IF check = NIL THEN check _ NARROW [CoreProperties.GetProp [self.class.properties, matToCell]]; IF check = NIL THEN BEGIN obj: CD.Object = GetObject [self, state]; IF obj = NIL THEN RETURN; -- Cell contains no rectangles check _ NEW [MaterialToCellProc _ MaterialToUnspecifiedSeparation]; MarkError [self, state, [obj.class.interestRect[obj], "Cell has no provisions to be checked"]] END; check^ [self, state, actual, wire, father, materialLoc, cellLoc, materialOrient, cellOrient] END; -- Send IF fast THEN SELECT self.class FROM CoreClasses.recordCellClass => MaterialToRecordCellSeparation [self, state, actual, wire, father, materialLoc, cellLoc, materialOrient, cellOrient]; CoreClasses.transistorCellClass => MaterialToTransistorSeparation [self, state, actual, wire, father, materialLoc, cellLoc, materialOrient, cellOrient]; CoreClasses.unspecifiedCellClass => MaterialToUnspecifiedSeparation [self, state, actual, wire, father, materialLoc, cellLoc, materialOrient, cellOrient]; ENDCASE => Send [] ELSE Send [] END; -- MaterialToCellSeparation MaterialToTransistorSeparation: MaterialToCellProc ~ BEGIN <<[self: Core.CellType, state: State, actual, wire: Wire, father: Core.CellType, materialLoc, cellLoc: CD.Position, materialOrient, cellOrient: CD.Orientation]>> wbb, tbb: CD.Rect; -- bounding boxes tw: Wire; Intersect: PROC RETURNS [BOOL] ~ INLINE BEGIN RETURN [CDBasics.Intersect [CDBasics.Extend[tbb,state.maxSeparation], wbb]] END; -- Intersect IF state.abort^ THEN ERROR ABORTED; IF (CoreProperties.GetProp [self.properties, doNotAnalyse] # NIL) THEN RETURN; <> wbb _ AtomicWireHull [wire, state]; wbb _ CDBasics.MapRect [itemInCell: wbb, cellSize: CDBasics.SizeOfRect [wbb], cellInstOrient: materialOrient, cellInstPos: materialLoc]; tbb _ TransistorHull [self, state]; tbb _ CDBasics.MapRect [itemInCell: tbb, cellSize: CDBasics.SizeOfRect [tbb], cellInstOrient: cellOrient, cellInstPos: cellLoc]; IF (NOT Intersect[]) THEN RETURN; tw _ BindTransistor [self.public, actual, state]; <> FOR i: NAT IN [0 .. tw.size) DO MaterialSeparation [state: state, cell: father, w1: tw[i], w2: wire, loc1: cellLoc, loc2: materialLoc, orient1: cellOrient, orient2: materialOrient] ENDLOOP END; -- MaterialToTransistorSeparation MaterialToUnspecifiedSeparation: MaterialToCellProc ~ BEGIN <<[self: Core.CellType, state: State, actual, wire: Wire, father: Core.CellType, materialLoc, cellLoc: CD.Position, materialOrient, cellOrient: CD.Orientation]>> NULL END; -- MaterialToUnspecifiedSeparation MaterialToRecordCellSeparation: MaterialToCellProc ~ BEGIN <<[self: Core.CellType, state: State, actual, wire: Wire, father: Core.CellType, materialLoc, cellLoc: CD.Position, materialOrient, cellOrient: CD.Orientation]>> wbb, cbb: CD.Rect; -- bounding boxes boundInternal: Wire; propagatedActuals: WireSet; -- one wire per subcell bindingTable: RefTab.Ref; cellData: CoreClasses.RecordCellType _ NARROW [self.data]; Intersect: PROC RETURNS [BOOL] ~ INLINE BEGIN RETURN [CDBasics.Intersect [CDBasics.Extend[cbb,state.maxSeparation], wbb]] END; -- Intersect IF state.abort^ THEN ERROR ABORTED; IF (CoreProperties.GetProp [self.properties, doNotAnalyse] # NIL) OR (cellData.internal.size = 0) THEN RETURN; <> wbb _ AtomicWireHull [wire, state]; wbb _ CDBasics.MapRect [itemInCell: wbb, cellSize: CDBasics.SizeOfRect [wbb], cellInstOrient: materialOrient, cellInstPos: materialLoc]; cbb _ RecordCellHull [self, state]; cbb _ CDBasics.MapRect [itemInCell: cbb, cellSize: CDBasics.SizeOfRect [cbb], cellInstOrient: cellOrient, cellInstPos: cellLoc]; IF (NOT Intersect[]) THEN RETURN; <> bindingTable _ CreateBindingTable [actual: actual, public: self.public]; boundInternal _ BindInternal [bindingTable, cellData.internal, state]; FOR i: NAT IN [0 .. boundInternal.size) DO MaterialSeparation [state: state, cell: father, w1: boundInternal[i], w2: wire, loc1: cellLoc, loc2: materialLoc, orient1: cellOrient, orient2: materialOrient] ENDLOOP; <> propagatedActuals _ NEW [WireSetRec[cellData.size]]; FOR sub: NAT IN [0 .. cellData.size) DO propagatedActuals[sub] _ PropagateBinding [state, bindingTable, cellData.instances[sub].actual] ENDLOOP; FlushBindingTable [bindingTable]; <> FOR sub: NAT IN [0 .. cellData.size) DO cdInst: CD.Instance = CoreGeometry.GetTransf[state.attributes, cellData.instances[sub]]; IF (cdInst = NIL) THEN coreMess ["Core record subcell has no geometry (6)", cellData]; MaterialToCellSeparation [self: cellData.instances[sub].type, state: state, actual: propagatedActuals[sub], wire: wire, father: self, materialLoc: materialLoc, cellLoc: CDBasics.AddPoints [cellLoc, cdInst.trans.off], materialOrient: materialOrient, cellOrient: CDBasics.ComposeOrient [cellOrient, cdInst.orientation]] ENDLOOP END; -- MaterialToRecordCellSeparation CellToCellSeparation: CellToCellProc ~ BEGIN <<[self: Core.CellType, state: State, otherCell: Core.CellType, selfActual, otherActual: Wire, father: Core.CellType, selfLoc, otherLoc: CD.Position, selfOrient, otherOrient: CD.Orientation]>> <> Send: PROC ~ INLINE BEGIN check: REF CellToCellProc _ NARROW [CoreProperties.GetProp [self.properties, cellToCell]]; IF check = NIL THEN check _ NARROW [CoreProperties.GetProp [self.class.properties, cellToCell]]; IF check = NIL THEN BEGIN obj: CD.Object = GetObject [self, state]; IF obj = NIL THEN RETURN; -- Cell contains no rectangles check _ NEW [CellToCellProc _ UnspecifiedToAnyClassSeparation]; MarkError [self, state, [obj.class.interestRect[obj], "Cell has no provisions to be checked"]] END; check^ [self, state, otherCell, selfActual, otherActual, father, selfLoc, otherLoc, selfOrient, otherOrient] END; -- Send SELECT otherCell.class FROM CoreClasses.unspecifiedCellClass => RETURN; CoreClasses.recordCellClass => NULL; -- default case CoreClasses.transistorCellClass => -- nasty case IF self.class = CoreClasses.transistorCellClass THEN BEGIN IF fast THEN TransistorToTransistorSeparation [self, state, otherCell, selfActual, otherActual, father, selfLoc, otherLoc, selfOrient, otherOrient] ELSE Send []; RETURN END ELSE BEGIN -- swap selfZ: Core.CellType = self; selfActualZ: Wire = selfActual; selfLocZ: CD.Position = selfLoc; selfOrientZ: CD.Orientation = selfOrient; self _ otherCell; otherCell _ selfZ; selfActual _ otherActual; otherActual _ selfActualZ; selfLoc _ otherLoc; otherLoc _ selfLocZ; selfOrient _ otherOrient; otherOrient _ selfOrientZ END; ENDCASE => ERROR; IF fast THEN SELECT self.class FROM CoreClasses.recordCellClass => RecordCellToRecordCellSeparation [self, state, otherCell, selfActual, otherActual, father, selfLoc, otherLoc, selfOrient, otherOrient]; CoreClasses.transistorCellClass => TransistorToRecordCellSeparation [self, state, otherCell, selfActual, otherActual, father, selfLoc, otherLoc, selfOrient, otherOrient]; CoreClasses.unspecifiedCellClass => UnspecifiedToAnyClassSeparation [self, state, otherCell, selfActual, otherActual, father, selfLoc, otherLoc, selfOrient, otherOrient]; ENDCASE => Send [] ELSE Send [] END; -- CellToCellSeparation TransistorToRecordCellSeparation: CellToCellProc ~ BEGIN <<[self: Core.CellType, state: State, otherCell: Core.CellType, selfActual, otherActual: Wire, father: Core.CellType, selfLoc, otherLoc: CD.Position, selfOrient, otherOrient: CD.Orientation]>> cbb1, cbb2: CD.Rect; -- bounding boxes othersCellData: CoreClasses.RecordCellType _ NARROW [otherCell.data]; othersBindingTable: RefTab.Ref; tw: Wire; othersBoundInternal: Wire; ownName: Rope.ROPE = CoreOps.GetCellTypeName [self]; otherName: Rope.ROPE = CoreOps.GetCellTypeName [otherCell]; Intersect: PROC RETURNS [BOOL] ~ INLINE BEGIN RETURN [CDBasics.Intersect [CDBasics.Extend[cbb1,state.maxSeparation], cbb2]] END; -- Intersect <> IF state.abort^ THEN ERROR ABORTED; IF (CoreProperties.GetProp [self.properties, doNotAnalyse]#NIL) OR (CoreProperties.GetProp [otherCell.properties, doNotAnalyse]#NIL) THEN RETURN; IF debug THEN BEGIN IO.PutF [stream: dLog, format: "Checking transistor %l%g%l vs. %g. ", v1: IO.rope ["e"], v2: IF ownName = NIL THEN IO.refAny [self] ELSE IO.rope [ownName], v3: IO.rope ["E"], v4: IF otherName = NIL THEN IO.refAny [otherCell] ELSE IO.rope [otherName]]; IO.PutF [stream: dLog, format: "Rel. trans.orient: %g, dist: (%g, %g).\n", v1: IO.int [CDBasics.DecomposeOrient [otherOrient, selfOrient]], v2: IO.int [(otherLoc.x - selfLoc.x) / previousTechnology.lambda], v3: IO.int [(otherLoc.y - selfLoc.y) / previousTechnology.lambda]] END; cbb1 _ RecordCellHull [self, state]; cbb1 _ CDBasics.MapRect [itemInCell: cbb1, cellSize: CDBasics.SizeOfRect [cbb1], cellInstOrient: selfOrient, cellInstPos: selfLoc]; cbb2 _ RecordCellHull [otherCell, state]; cbb2 _ CDBasics.MapRect [itemInCell: cbb2, cellSize: CDBasics.SizeOfRect [cbb2], cellInstOrient: otherOrient, cellInstPos: otherLoc]; IF (NOT Intersect[]) THEN RETURN; <> IF state.abort^ THEN ERROR ABORTED; othersBindingTable _ CreateBindingTable [actual: otherActual, public: otherCell.public]; othersBoundInternal _ BindInternal [othersBindingTable, othersCellData.internal, state]; tw _ BindTransistor [self.public, selfActual, state]; FlushBindingTable [othersBindingTable]; FOR i: NAT IN [0 .. tw.size) DO FOR j: NAT IN [0 .. othersCellData.internal.size) DO MaterialSeparation [state: state, cell: father, -- the cell getting the error flag -- w1: tw[i], w2: othersBoundInternal[j], loc1: selfLoc, loc2: otherLoc, orient1: selfOrient, orient2: otherOrient] ENDLOOP ENDLOOP END; -- TransistorToRecordCellSeparation TransistorToTransistorSeparation: CellToCellProc ~ BEGIN <<[self: Core.CellType, state: State, otherCell: Core.CellType, selfActual, otherActual: Wire, father: Core.CellType, selfLoc, otherLoc: CD.Position, selfOrient, otherOrient: CD.Orientation]>> cbb1, cbb2: CD.Rect; -- bounding boxes tw1, tw2: Wire; ownName: Rope.ROPE = CoreOps.GetCellTypeName [self]; otherName: Rope.ROPE = CoreOps.GetCellTypeName [otherCell]; Intersect: PROC RETURNS [BOOL] ~ INLINE BEGIN RETURN [CDBasics.Intersect [CDBasics.Extend[cbb1,state.maxSeparation], cbb2]] END; -- Intersect <> IF state.abort^ THEN ERROR ABORTED; IF (CoreProperties.GetProp [self.properties, doNotAnalyse]#NIL) OR (CoreProperties.GetProp [otherCell.properties, doNotAnalyse]#NIL) THEN RETURN; cbb1 _ RecordCellHull [self, state]; cbb1 _ CDBasics.MapRect [itemInCell: cbb1, cellSize: CDBasics.SizeOfRect [cbb1], cellInstOrient: selfOrient, cellInstPos: selfLoc]; cbb2 _ RecordCellHull [otherCell, state]; cbb2 _ CDBasics.MapRect [itemInCell: cbb2, cellSize: CDBasics.SizeOfRect [cbb2], cellInstOrient: otherOrient, cellInstPos: otherLoc]; IF (NOT Intersect[]) THEN RETURN; <> IF state.abort^ THEN ERROR ABORTED; tw1 _ BindTransistor [self.public, selfActual, state]; tw2 _ BindTransistor [otherCell.public, otherActual, state]; FOR i: NAT IN [0 .. tw1.size) DO FOR j: NAT IN [0 .. tw2.size) DO MaterialSeparation [state: state, cell: father, -- the cell getting the error flag -- w1: tw1[i], w2: tw2[j], loc1: selfLoc, loc2: otherLoc, orient1: selfOrient, orient2: otherOrient] ENDLOOP ENDLOOP END; -- TransistorToTransistorSeparation UnspecifiedToAnyClassSeparation: CellToCellProc ~ BEGIN <<[self: Core.CellType, state: State, otherCell: Core.CellType, selfActual, otherActual: Wire, father: Core.CellType, selfLoc, otherLoc: CD.Position, selfOrient, otherOrient: CD.Orientation]>> NULL END; -- UnspecifiedToAnyClassSeparation RecordCellToRecordCellSeparation: CellToCellProc ~ BEGIN <<[self: Core.CellType, state: State, otherCell: Core.CellType, selfActual, otherActual: Wire, father: Core.CellType, selfLoc, otherLoc: CD.Position, selfOrient, otherOrient: CD.Orientation]>> cbb1, cbb2: CD.Rect; -- bounding boxes ownCellData: CoreClasses.RecordCellType _ NARROW [self.data]; othersCellData: CoreClasses.RecordCellType _ NARROW [otherCell.data]; ownBindingTable, othersBindingTable: RefTab.Ref; ownBoundInternal, othersBoundInternal: Wire; ownName: Rope.ROPE = CoreOps.GetCellTypeName [self]; otherName: Rope.ROPE = CoreOps.GetCellTypeName [otherCell]; Intersect: PROC RETURNS [BOOL] ~ INLINE BEGIN RETURN [CDBasics.Intersect [CDBasics.Extend[cbb1,state.maxSeparation], cbb2]] END; -- Intersect <> IF state.abort^ THEN ERROR ABORTED; IF (CoreProperties.GetProp [self.properties, doNotAnalyse]#NIL) OR (CoreProperties.GetProp [otherCell.properties, doNotAnalyse]#NIL) THEN RETURN; IF debug THEN BEGIN IO.PutF [stream: dLog, format: "Checking cell %l%g%l vs. %g. ", v1: IO.rope ["e"], v2: IF ownName = NIL THEN IO.refAny [self] ELSE IO.rope [ownName], v3: IO.rope ["E"], v4: IF otherName = NIL THEN IO.refAny [otherCell] ELSE IO.rope [otherName]]; IO.PutF [stream: dLog, format: "Rel. trans.orient: %g, dist: (%g, %g).\n", v1: IO.int [CDBasics.DecomposeOrient [otherOrient, selfOrient]], v2: IO.int [(otherLoc.x - selfLoc.x) / previousTechnology.lambda], v3: IO.int [(otherLoc.y - selfLoc.y) / previousTechnology.lambda]] END; cbb1 _ RecordCellHull [self, state]; cbb1 _ CDBasics.MapRect [itemInCell: cbb1, cellSize: CDBasics.SizeOfRect [cbb1], cellInstOrient: selfOrient, cellInstPos: selfLoc]; cbb2 _ RecordCellHull [otherCell, state]; cbb2 _ CDBasics.MapRect [itemInCell: cbb2, cellSize: CDBasics.SizeOfRect [cbb2], cellInstOrient: otherOrient, cellInstPos: otherLoc]; IF (NOT Intersect[]) THEN RETURN; <> IF state.abort^ THEN ERROR ABORTED; ownBindingTable _ CreateBindingTable [actual: selfActual, public: self.public]; othersBindingTable _ CreateBindingTable [actual: otherActual, public: otherCell.public]; ownBoundInternal _ BindInternal [ownBindingTable, ownCellData.internal, state]; othersBoundInternal _ BindInternal [othersBindingTable, othersCellData.internal, state]; FlushBindingTable [ownBindingTable]; FlushBindingTable [othersBindingTable]; FOR i: NAT IN [0 .. ownCellData.internal.size) DO FOR j: NAT IN [0 .. othersCellData.internal.size) DO MaterialSeparation [state: state, cell: father, -- the cell getting the error flag -- w1: ownBoundInternal[i], w2: othersBoundInternal[j], loc1: selfLoc, loc2: otherLoc, orient1: selfOrient, orient2: otherOrient] ENDLOOP ENDLOOP END; -- RecordCellToRecordCellSeparation ComputeMaxSeparation: PROC [technology: CD.Technology] RETURNS [maxSeparation: CD.Number] ~ BEGIN <> maxSeparation _ 0; FOR s1: CD.Layer IN CD.Layer DO IF CD.LayerTechnology[s1] = technology THEN FOR s2: CD.Layer IN CD.Layer DO IF CD.LayerTechnology[s2] = technology THEN BEGIN sep: CD.Number = CDSimpleRules.MinDist [s1, s2 ! CDSimpleRules.NotKnown => LOOP]; -- try to filter out inappropriate layers maxSeparation _ MAX [maxSeparation, sep] END ENDLOOP ENDLOOP END; -- ComputeMaxSeparation RegisterSeparationProcs: PROC ~ BEGIN <> CoreClasses.recordCellClass.properties _ CoreProperties.PutProp [ on: CoreClasses.recordCellClass.properties, prop: matToCell, value: NEW [MaterialToCellProc _ MaterialToRecordCellSeparation]]; CoreClasses.transistorCellClass.properties _ CoreProperties.PutProp [CoreClasses.transistorCellClass.properties, matToCell, NEW [MaterialToCellProc _ MaterialToTransistorSeparation]]; CoreClasses.unspecifiedCellClass.properties _ CoreProperties.PutProp [CoreClasses.unspecifiedCellClass.properties, matToCell, NEW [MaterialToCellProc _ MaterialToUnspecifiedSeparation]]; CoreClasses.recordCellClass.properties _ CoreProperties.PutProp [ on: CoreClasses.recordCellClass.properties, prop: cellToCell, value: NEW [CellToCellProc _ RecordCellToRecordCellSeparation]]; CoreClasses.transistorCellClass.properties _ CoreProperties.PutProp [CoreClasses.transistorCellClass.properties, cellToCell, NEW [CellToCellProc _ TransistorToRecordCellSeparation]]; CoreClasses.unspecifiedCellClass.properties _ CoreProperties.PutProp [CoreClasses.unspecifiedCellClass.properties, cellToCell, NEW [CellToCellProc _ UnspecifiedToAnyClassSeparation]]; END; -- RegisterSeparationProcs <> ClearErrors: PROC [obj: Core.CellType, state: State] ~ BEGIN <> IF state.shy THEN RETURN; IF (state.design # NIL) THEN CDErrors.RemoveMessages [design: state.design, ob: GetObject [obj, state], owner: DRVkey]; obj.properties _ CoreProperties.PutProp [obj.properties, DRVkey, NIL] END; -- ClearErrors MarkError: PROC [obj: Core.CellType, state: State, e: ErrorRect] ~ BEGIN <> objName: Rope.ROPE = CoreOps.GetCellTypeName [obj]; cdObj: CD.Object _ GetObject [obj, state]; violations: DRV _ NARROW [CoreProperties.GetProp [obj.properties, DRVkey]]; longMsg: Rope.ROPE _ IO.PutFR ["%g: %g", IF objName=NIL THEN IO.refAny [obj] ELSE IO.rope [objName], IO.rope[e.msg]]; done: BOOL _ FALSE; -- initialization of done important eLog.PutF1 ["%g\n", IO.rope [longMsg]]; IF (violations = NIL) THEN BEGIN violations _ NEW [DesignRuleViolation]; violations.count _ 1; violations.places _ LIST [e] END ELSE BEGIN violations.count _ violations.count.SUCC; violations.places _ CONS [e, violations.places] END; state.globalErrorCount _ state.globalErrorCount.SUCC; IF state.abort^ THEN ERROR ABORTED; <> <> IF state.globalErrorCount < errorFeedbackCutOff THEN mLog.Put1 [IO.char ['|]]; obj.properties _ CoreProperties.PutProp [on: obj.properties, prop: DRVkey, value: violations]; IF (state.design # NIL) AND (cdObj # NIL) THEN done _ CDErrors.IncludeMessage [ design: state.design, ob: cdObj, rect: CDBasics.Extend [e.r, 4], message: e.msg, owner: DRVkey].done; IF NOT done THEN longMsg _ Rope.Cat [r1: longMsg, r2: " (not flagged in the layout)"]; IF debug THEN dLog.PutF1 ["%g\n", IO.rope [longMsg]] END; -- MarkError <> PrintError: CoreProperties.PropPrintProc ~ BEGIN IO.PutF1 [stream: to, format: "SoS error count = %g ", value: IO.int [NARROW[val,DRV].count]] END; -- PrintError PrintChecked: CoreProperties.PropPrintProc ~ BEGIN IO.Put1 [stream: to, value: IO.rope ["Design rules checked"]] END; -- PrintChecked RegisterProperties: PROC ~ BEGIN <> <> IF (NOT CDProperties.RegisterProperty [DRVkey, $gbb]) OR (NOT CDProperties.RegisterProperty [checked, $gbb]) OR (NOT CDProperties.RegisterProperty [bbKey, $gbb]) OR (NOT CDProperties.RegisterProperty [cellHull, $gbb]) OR (NOT CDProperties.RegisterProperty [trace, $gbb]) THEN IF NOT debug THEN mLog.Put1 [IO.rope["SoS probably is being reexecuted.\n"]]; <> <> CoreProperties.StoreProperties [prop: DRVkey, properties: CoreProperties.Props [[CoreProperties.propPrint, NEW [CoreProperties.PropPrintProc _ PrintError]]]]; CoreProperties.StoreProperties [prop: checked, properties: CoreProperties.Props [[CoreProperties.propPrint, NEW [CoreProperties.PropPrintProc _ PrintChecked]]]]; END; -- RegisterProperties for the interesting ones (modified by BS on October 26, 1986 8:58:33 pm PST) <> StartLog: PROC ~ BEGIN <> viewer: ViewerTools.Viewer; dummy: IO.STREAM; name: Rope.ROPE; viewer _ ViewerTools.FindExistingViewer ["Terminal"]; name _ IF viewer # NIL THEN "Terminal" ELSE "Son of Spinifex"; [in: dummy, out: mLog] _ ViewerIO.CreateViewerStreams [name, viewer] END; -- StartLog Debug: PROC ~ BEGIN <> viewer: ViewerTools.Viewer; dummy: IO.STREAM; debug _ TRUE; viewer _ ViewerTools.FindExistingViewer ["SoS debug"]; [in: dummy, out: dLog] _ ViewerIO.CreateViewerStreams ["SoS debug", viewer]; IF dLog = NIL THEN dLog _ mLog END; -- Debug PrintWire: PROC [w: Wire] ~ BEGIN <> dLog.PutF ["%g %g %g\n", IO.rope [CoreOps.GetShortWireName[w]], IO.card [LOOPHOLE[w]], IO.refAny [w]]; FOR i: NAT IN [0 .. w.size) DO dLog.PutF ["\t(%g) %g %g %g\n", IO.card [i], IO.rope [CoreOps.GetShortWireName[w[i]]], IO.card [LOOPHOLE[w[i]]], IO.refAny [w[i]]] ENDLOOP END; -- PrintWire PrintEntryShort: RefTab.EachPairAction ~ BEGIN <<[key: Key, val: Val] RETURNS [quit: BOOLEAN]>> dLog.PutF ["public: %g\t actual: %g\n", IO.card [LOOPHOLE[key]], IO.card [LOOPHOLE[val]]]; RETURN [FALSE] END; -- PrintEntryShort PrintEntryLong: RefTab.EachPairAction ~ BEGIN <<[key: Key, val: Val] RETURNS [quit: BOOLEAN]>> PrintWire [NARROW [key, Wire]]; PrintWire [NARROW [val, Wire]]; dLog.Put1 [IO.char['\n]]; RETURN [FALSE] END; -- PrintEntryLong PrintBinding: PROC [bindingTable: RefTab.Ref] ~ BEGIN <> [] _ RefTab.Pairs [bindingTable, PrintEntryShort] END; -- PrintBinding <> StartLog []; -- Should be first, so problems can be communicated IF debug THEN Debug[]; RegisterProperties []; -- CD & Core RegisterPruningProcs []; RegisterAnalysisProcs []; RegisterSeparationProcs [] -- Core END. <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <<>>