DIRECTORY Atom USING [GetPName], CD USING [InstanceList, Object, Rect], CDBasics USING [Extend], CDDirectory USING [EnumerateChildObjects, EnumerateObjectsProc, Name], CDErrors USING [IncludeMessage, RemoveMessages], CDEvents USING [EventProc, RegisterEventProc], CDOps USING [Info], CDProperties USING [GetPropFromObject, PutPropOnObject], CDSequencer USING [], IO USING [int, PutFR, rope], Rope USING [Cat, Concat, IsEmpty, ROPE], SX USING [Circuit, LogicalCell, TranslateGeometry], SXAccess USING [design, formatKey, invocation, stopFlag, sxTech], SXAccessInternal USING [], SXAtoms USING [spinifexCircuitDescription], SXLayers USING [AnalyzeGeometry], SXOutput USING [PrintCircuit], SXUserExtract USING [TranslateCell], TerminalIO USING [WriteLn, WriteRope]; SXAccessInternalImpl: CEDAR PROGRAM IMPORTS Atom, CDBasics, CDDirectory, CDErrors, CDEvents, CDOps, CDProperties, IO, Rope, SX, SXAccess, SXAtoms, SXLayers, SXOutput, SXUserExtract, TerminalIO EXPORTS SXAccessInternal = BEGIN SXData: TYPE = SX.LogicalCell; DoneList: TYPE = LIST OF REF SXData; errorSummary: LIST OF Rope.ROPE _ NIL; doneList: DoneList; InvertList: PROC [old: DoneList] RETURNS [new: DoneList _ NIL] = BEGIN FOR list: DoneList _ old, list.rest WHILE list#NIL DO new _ CONS [list.first, new] ENDLOOP END; -- InvertList PrintDoneList: PROC [d: DoneList] ~ BEGIN TerminalIO.WriteRope ["\nDone list: "]; FOR l: DoneList _ d, l.rest WHILE l # NIL DO TerminalIO.WriteRope [CDOps.Info[l.first.cellObj]]; TerminalIO.WriteRope [", "] ENDLOOP; TerminalIO.WriteRope ["\n"] END; -- PrintDoneList GetSXData: PUBLIC PROC[ob: CD.Object] RETURNS [REF SXData] = BEGIN IF ~ob.class.inDirectory THEN RETURN [NIL]; WITH CDProperties.GetPropFromObject [ob, $SX] SELECT FROM sxd: REF SXData => RETURN [sxd]; ENDCASE => { sxd: REF SXData _ NEW [SXData]; sxd.analysisState _ notYetDone; -- redundant sxd.cellObj _ ob; -- WOULD BE BETTER TO AVOID THIS CIRCULARITY ! CDProperties.PutPropOnObject [onto: ob, prop: $SX, val: sxd]; RETURN [sxd] } END; -- GetSXData ClearSXData: CDEvents.EventProc = BEGIN cell: CD.Object = NARROW [x, CD.Object]; CDProperties.PutPropOnObject [onto: cell, prop: $SX, val: NIL] END; -- ClearSXData Analyze: PUBLIC PROC [hierarchyRoots: CD.InstanceList] = BEGIN MarkAndCheckRoots: PROC [hierarchyRoots: CD.InstanceList] RETURNS [roots: CD.InstanceList_NIL] = BEGIN FOR al: CD.InstanceList _ hierarchyRoots, al.rest WHILE al#NIL DO IF al.first.ob.class.inDirectory THEN { sx: REF SXData = GetSXData [al.first.ob]; sx.rootOnInvocation _ SXAccess.invocation; roots _ CONS [al.first, roots]; } ELSE TerminalIO.WriteRope [IO.PutFR["*** %g cannot be root of analysis.\n", IO.rope[CDOps.Info[al.first.ob]]]]; ENDLOOP END; -- MarkAndCheckRoots AnalyzeEach: PROC [hierarchyRoots: CD.InstanceList ] = BEGIN FOR al: CD.InstanceList _ hierarchyRoots, al.rest WHILE al#NIL DO [] _ AnalyzeObAndChildren[al.first.ob] ENDLOOP END; -- AnalyzeEach WriteErrorSummary: PROC [] = BEGIN IF (errorSummary = NIL) THEN TerminalIO.WriteRope ["no errors\n"] ELSE { TerminalIO.WriteRope ["Summary of DRC errors:\n"]; FOR list: LIST OF Rope.ROPE _ errorSummary, list.rest WHILE list#NIL DO TerminalIO.WriteRope [" "]; TerminalIO.WriteRope [list.first]; TerminalIO.WriteLn [] ENDLOOP }; END; -- WriteErrorSummary errorSummary _ NIL; doneList _ NIL; hierarchyRoots _ MarkAndCheckRoots [hierarchyRoots]; AnalyzeEach [hierarchyRoots]; WriteErrorSummary []; IF (doneList # NIL) AND (SXAccess.formatKey # NIL) THEN SXOutput.PrintCircuit [InvertList[doneList], SXAccess.formatKey] END; -- Analyze AnalyzeObAndChildren: PROC [ob: CD.Object] RETURNS [propagate: BOOL _ FALSE] = BEGIN CheckAChild: CDDirectory.EnumerateObjectsProc = BEGIN childPropagates: BOOL _ AnalyzeObAndChildren[me]; propagate _ propagate OR childPropagates; END; -- CheckAChild sx: REF SXData = GetSXData [ob]; IF sx#NIL AND (sx.lastInvocation#SXAccess.invocation OR sx.analysisState=notYetDone) THEN { propagate _ (sx.analysisState = notYetDone); CDDirectory.EnumerateChildObjects [me: ob, p: CheckAChild, x: NIL]; IF propagate THEN BEGIN -- analyze object CDErrors.RemoveMessages [design: SXAccess.design, ob: ob, owner: $SXErrorMessage]; AnalyzePreparedOb [ob] END ELSE SkipAnalyzedOb [ob, sx]; sx.lastInvocation _ SXAccess.invocation } END; -- AnalyzeObAndChildren WriteErrors: PROC [sx: REF SXData] = BEGIN IF sx.errorCount#0 THEN { message: Rope.ROPE _ IO.PutFR[" %g errors", IO.int[sx.errorCount]]; IF ~Rope.IsEmpty[sx.errorContext] THEN message _ Rope.Cat [message, " displayed in ", sx.errorContext]; TerminalIO.WriteRope [Rope.Concat ["; ", message]]; errorSummary _ CONS [Rope.Concat[CDDirectory.Name[sx.cellObj], message], errorSummary] } END; -- WriteErrors WriteDevices: PROC [sx: REF SXData] = BEGIN TerminalIO.WriteRope [IO.PutFR [" %g/%g transistors.", IO.int [sx.circuit.linkageCount.inSelf+sx.circuit.linkageCount.inChildren], IO.int [sx.circuit.linkageCount.inSelf]]]; END; -- WriteDevices SkipAnalyzedOb: PROC [ob: CD.Object, sx: REF SXData] = BEGIN cell: REF SX.LogicalCell = GetSXData [ob]; doneList _ CONS [cell, doneList]; TerminalIO.WriteRope [IO.PutFR ["skipped: %g, already analyzed.", IO.rope[CDDirectory.Name[ob]]]]; WriteDevices[sx]; WriteErrors[sx]; TerminalIO.WriteLn[] END; -- SkipAnalyzedOb AnalyzePreparedOb: PUBLIC PROC [ob: CD.Object] = BEGIN cell: REF SX.LogicalCell = GetSXData [ob]; opaque: REF = CDProperties.GetPropFromObject [ob, SXAtoms.spinifexCircuitDescription]; cell.circuit _ NEW [SX.Circuit]; IF opaque # NIL THEN AnalyzeOpaqueOb [ob, opaque] ELSE { TerminalIO.WriteRope [Rope.Cat["analyzing: """, CDDirectory.Name[cell.cellObj], """ "]]; IF SXAccess.stopFlag^ THEN ERROR ABORTED; SX.TranslateGeometry [cell]; TerminalIO.WriteRope [". "]; IF SXAccess.stopFlag^ THEN ERROR ABORTED; SXLayers.AnalyzeGeometry [cell]; IF SXAccess.stopFlag^ THEN ERROR ABORTED; IF (SXAccess.sxTech.cellPostProcess # NIL) THEN SXAccess.sxTech.cellPostProcess [cell] }; doneList _ CONS [cell, doneList]; WriteDevices [cell]; WriteErrors [cell]; TerminalIO.WriteLn []; cell.analysisState _ useCircuit END; -- AnalyzePreparedOb AnalyzeOpaqueOb: PUBLIC PROC [ob: CD.Object, key: REF] = BEGIN cell: REF SX.LogicalCell = GetSXData [ob]; WITH key SELECT FROM cirDesc: Rope.ROPE => { TerminalIO.WriteRope [Rope.Cat["processing user circuit description: """, CDDirectory.Name[cell.cellObj], """"]]; SXUserExtract.TranslateCell [cell, cirDesc]; }; ENDCASE => { TerminalIO.WriteRope [Rope.Cat["$", Atom.GetPName[SXAtoms.spinifexCircuitDescription], "property of cell " , CDDirectory.Name[ob], " not a rope.\n"]]; ERROR ABORTED } END; -- AnalyzeOpaqueOb PutError: PUBLIC PROC [ob: CD.Object, r: CD.Rect, message: Rope.ROPE] = BEGIN sx: REF SXData = GetSXData [ob]; done: BOOL = CDErrors.IncludeMessage [design: SXAccess.design, ob: ob, rect: CDBasics.Extend [r, SXAccess.design.technology.lambda/2], message: message, owner: $SXErrorMessage].done; IF sx#NIL THEN { sx.errorCount _ sx.errorCount + 1; IF (sx.errorCount < 10) THEN TerminalIO.WriteRope ["|"]; }; IF ~done THEN TerminalIO.WriteRope [Rope.Cat ["** unable to place error message ", message, ".\n"]]; END; -- PutError CDEvents.RegisterEventProc [proc: ClearSXData, event: $AfterCellReplacement]; CDEvents.RegisterEventProc [proc: ClearSXData, event: $AfterChange]; END. œSXAccessInternalImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Written by Jacobi, April 2, 1985 5:11:35 pm PST Last Edited by: Jacobi, April 2, 1985 5:11:39 pm PST Last edited by: gbb March 5, 1986 3:01:08 pm PST For debugging. [event: REF, design: CD.Design, x: REF] RETURNS [dont: BOOL_FALSE] Deletes the Spinifex data from a cell when it has been edited. Main of Analyze PROC [me: CD.Object, x: REF] figures out if we need to reanalyze AnalyzeObAndChildren.ob because me changed Technology dependent manipulation and checking (e.g. CMOS n-well connects). Edited on June 18, 1985 6:04:15 pm PDT, by Beretta done list of logicall cells is inverted before output is produced, because Thyme requires circuits to be declared before they are referenced. changes to: InvertList: new, Analyze: SXOutput.PrintCircuit is called with inverted list. Edited on July 3, 1985 3:11:06 pm PDT, by Beretta Introduced a changedList into which ChipNDale keeps track of changed cells. When Spinifex is invocated it first removes the cadavers form the doneList. changes to: DoneList: new type, changedList: holds the pointers to the changed cells, CleanUpDoneList: removes the cadavers, ClearSXData: updates the changedList, Analyze: calls CleanUpDoneList, CleanUpDoneList gbb February 13, 1986 4:40:43 pm PST Definitive fix of all bugs pertaining to the doneList (I hope so at least)., cirDesc (local of AnalyzeOpaqueOb) ส ˜code™Kšœ ฯmœ1™Kšœžœ žœžœ ˜(Kšœ:žœ˜>Kšžœก˜—š  œžœžœžœž˜>š  œžœžœžœ žœžœž˜fš žœžœ(žœžœž˜Ašžœžœ˜'Kšœžœ"˜)Kšœ*˜*Kšœžœ˜Kšœ˜—Kšžœžœ.žœ!˜oKšž˜—Kšžœก˜—š  œžœžœž˜<š žœžœ(žœžœž˜AKšœ&˜&Kšž˜—Kšžœก˜—š œžœž˜"Kšžœžœžœ%˜Ašžœ˜Kšœ2˜2š žœžœžœžœžœžœž˜GKšœU˜UKšž˜—Kšœ˜—Kšžœก˜—M™Kšœžœžœ˜$Kšœ4˜4Mšœ˜Mšœ˜š žœ žœžœžœž˜7Kšœ@˜@—Kšžœก ˜—š  œžœžœ žœ žœžœž˜Tšข œ%ž˜5Kšžœžœ žœ™KšœDฯeœ™NKšœžœ˜1Kšœžœ˜)Kšžœก˜—Mšœžœ˜ š žœžœžœ(žœžœ˜[Kšœ,˜,Kšœ>žœ˜Cšžœ žœžœก˜)KšœR˜RKšœ˜Kšž˜—šžœ˜Kšœ˜—Kšœ'˜'K˜—Kšžœก˜—š  œžœžœ ž˜*šžœžœ˜Kšœžœžœžœ˜Cšžœ žœ˜'Kšœ@˜@—Kšœ3˜3KšœžœC˜VK˜—Kšžœก˜—š  œžœžœ ž˜+KšœžœžœIžœ(˜ฎKšžœก˜—š  œžœžœ žœ ž˜Kšœžœžœ˜*šžœžœž˜šœžœ˜Kšœq˜qKšœ,˜,K˜—šžœ˜ Kšœ–˜–Kšžœž˜ Kšœ˜——Kšžœก˜—š  œž œžœ žœžœž˜MKšœžœ˜ Kšœžœฌ˜ถšžœžœžœ˜Kšœ"˜"Kšžœžœ˜8K˜—•StartOfExpansion[]šžœž˜ KšœV˜V—Kšžœก ˜—LšœM˜MKšœD˜DLšžœ˜™2K™Kšœ ฯr œค œ5™Y—™1Kšœ ค œvคœ™—Kš œ ค œ ค œ)คœค œคœค ™า—™$Kšœ-คœค œ™o—K™K™—…—j+&