DIRECTORY Atom USING [GetPName], CD USING [Describe, InstanceList, Object, Rect], CDBasics USING [Extend], CDBottomUp USING [Class, DoProc, DoRecurse, Handle, MakeHandle, Register, ReUseProc], CDErrors USING [IncludeMessage, RemoveMessages], CDProperties, CDSequencer USING [], FS USING [StreamOpen], IO USING [Close, int, PutF, PutF1, PutFR, PutRope, rope, STREAM], 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; SXAccessInternalImpl: CEDAR PROGRAM IMPORTS Atom, CD, CDBasics, CDBottomUp, CDErrors, CDProperties, FS, IO, Rope, SX, SXAccess, SXAtoms, SXLayers, SXOutput, SXUserExtract, TerminalIO EXPORTS SXAccessInternal = BEGIN debug: BOOL _ FALSE; LogicalCell: TYPE = SX.LogicalCell; DoneList: TYPE = LIST OF REF LogicalCell; errorSummary: LIST OF Rope.ROPE _ NIL; eLog: IO.STREAM; -- error log 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 ~ BEGIN TerminalIO.PutRope ["\nDone list: "]; FOR l: DoneList _ doneList, l.rest WHILE l # NIL DO TerminalIO.PutRopes[CD.Describe[l.first.cellObj], ", "] ENDLOOP; TerminalIO.PutRope ["\n"] END; -- PrintDoneList GetLogicalCell: PUBLIC PROC [ob: CD.Object] RETURNS [REF LogicalCell] = BEGIN IF ~ob.class.composed THEN RETURN [NIL]; WITH CDProperties.GetObjectProp [ob, $SX] SELECT FROM sxd: REF LogicalCell => RETURN [sxd]; ENDCASE => { sxd: REF LogicalCell _ NEW [LogicalCell]; sxd.analysisState _ notYetDone; -- redundant sxd.cellObj _ ob; -- WOULD BE BETTER TO AVOID THIS CIRCULARITY ! CDProperties.PutObjectProp [onto: ob, prop: $SX, val: sxd]; RETURN [sxd] } END; -- GetLogicalCell 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.composed THEN { lc: REF LogicalCell = GetLogicalCell [al.first.ob]; lc.rootOnInvocation _ SXAccess.invocation; roots _ CONS [al.first, roots]; } ELSE TerminalIO.PutF["*** %g cannot be root of analysis.\n", IO.rope[CD.Describe[al.first.ob]]]; ENDLOOP END; -- MarkAndCheckRoots AnalyzeEach: PROC [recurseHandle: CDBottomUp.Handle, hierarchyRoots: CD.InstanceList ] = { FOR al: CD.InstanceList _ hierarchyRoots, al.rest WHILE al#NIL DO [] _ CDBottomUp.DoRecurse[recurseHandle, al.first.ob] ENDLOOP }; WriteErrorSummary: PROC [] = BEGIN IF errorSummary = NIL THEN TerminalIO.PutRope ["no errors\n"] ELSE { TerminalIO.PutRope ["Summary of DRC errors:\n"]; FOR list: LIST OF Rope.ROPE _ errorSummary, list.rest WHILE list#NIL DO TerminalIO.PutRopes[" ", list.first, "\n"] ENDLOOP }; END; -- WriteErrorSummary recurseHandle: CDBottomUp.Handle _ CDBottomUp.MakeHandle[spinifex, SXAccess.design]; errorSummary _ NIL; doneList _ NIL; eLog _ FS.StreamOpen [fileName: "[]<>Temp>DRC>Spinifex.log", accessOptions: create, keep: 5, extendFileProc: NIL, remoteCheck: FALSE, wDir: NIL]; -- keep is 5 because of incremental use eLog.PutF1 ["Error log by Spinifex. Design: %g\n\n", IO.rope [SXAccess.design.name]]; IF debug THEN TerminalIO.PutRope ["doneList _ NIL\n"]; hierarchyRoots _ MarkAndCheckRoots [hierarchyRoots]; AnalyzeEach [recurseHandle, hierarchyRoots]; IF debug THEN PrintDoneList []; WriteErrorSummary []; eLog.PutRope ["\nDRC terminated normally."]; eLog.Close []; IF (doneList # NIL) AND (SXAccess.formatKey # NIL) THEN SXOutput.PrintCircuit [InvertList[doneList], SXAccess.formatKey] END; -- Analyze DoProc: CDBottomUp.DoProc = BEGIN lc: REF LogicalCell = GetLogicalCell [ob]; CDErrors.RemoveMessages [design: SXAccess.design, ob: ob, owner: $SXErrorMessage]; AnalyzePreparedOb [ob]; END; -- DoProc ReUseProc: CDBottomUp.ReUseProc = BEGIN cell: REF LogicalCell = GetLogicalCell [ob]; doneList _ CONS [cell, doneList]; TerminalIO.PutF["skipped: %g, already analyzed.", IO.rope[CD.Describe[ob, NIL, SXAccess.design]]]; WriteDevices [cell]; WriteErrors [cell]; TerminalIO.PutRope ["\n"]; END; -- ReUseProc WriteErrors: PROC [lc: REF LogicalCell] = BEGIN IF lc.errorCount#0 THEN { message: Rope.ROPE _ IO.PutFR[" %g errors", IO.int[lc.errorCount]]; IF ~Rope.IsEmpty[lc.errorContext] THEN message _ Rope.Cat [message, " displayed in ", lc.errorContext]; TerminalIO.PutRopes["; ", message]; errorSummary _ CONS [Rope.Concat[CD.Describe[lc.cellObj, NIL, SXAccess.design], message], errorSummary] } END; -- WriteErrors WriteDevices: PROC [lc: REF LogicalCell] = BEGIN TerminalIO.PutF[" %g/%g transistors.", IO.int [lc.circuit.linkageCount.inSelf+lc.circuit.linkageCount.inChildren], IO.int [lc.circuit.linkageCount.inSelf]]; END; -- WriteDevices SkipAnalyzedOb: PROC [ob: CD.Object, lc: REF LogicalCell] = BEGIN cell: REF LogicalCell = GetLogicalCell [ob]; doneList _ CONS [cell, doneList]; TerminalIO.PutF["skipped: %g, already analyzed.", IO.rope[CD.Describe[ob, NIL, SXAccess.design]]]; WriteDevices[lc]; WriteErrors[lc]; TerminalIO.PutRope["\n"] END; -- SkipAnalyzedOb AnalyzePreparedOb: PUBLIC PROC [ob: CD.Object] = BEGIN cell: REF LogicalCell = GetLogicalCell [ob]; opaque: REF = CDProperties.GetObjectProp [ob, SXAtoms.spinifexCircuitDescription]; cell.circuit _ NEW [SX.Circuit]; IF opaque # NIL THEN AnalyzeOpaqueOb [ob, opaque] ELSE { TerminalIO.PutRopes["analyzing: """, CD.Describe[cell.cellObj, NIL, SXAccess.design], """ "]; IF SXAccess.stopFlag^ THEN ERROR ABORTED; SX.TranslateGeometry [cell]; TerminalIO.PutRope [". "]; 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.PutRope["\n"]; cell.analysisState _ useCircuit END; -- AnalyzePreparedOb AnalyzeOpaqueOb: PUBLIC PROC [ob: CD.Object, key: REF] = BEGIN cell: REF LogicalCell = GetLogicalCell [ob]; WITH key SELECT FROM cirDesc: Rope.ROPE => { TerminalIO.PutRope [Rope.Cat["processing user circuit description: """, CD.Describe[cell.cellObj, NIL, SXAccess.design], """"]]; SXUserExtract.TranslateCell [cell, cirDesc]; }; ENDCASE => { TerminalIO.PutRope [Rope.Cat["$", Atom.GetPName[SXAtoms.spinifexCircuitDescription], "property of cell " , CD.Describe[ob, NIL, SXAccess.design], " not a rope.\n"]]; ERROR ABORTED } END; -- AnalyzeOpaqueOb PutError: PUBLIC PROC [ob: CD.Object, r: CD.Rect, message: Rope.ROPE] = BEGIN lc: REF LogicalCell = GetLogicalCell [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 lc#NIL THEN { lc.errorCount _ lc.errorCount + 1; IF (lc.errorCount < 10) THEN TerminalIO.PutRope ["|"]; }; eLog.PutF ["%g: %g\n", IO.rope [CD.Describe [ob]], IO.rope [message]]; IF ~done THEN TerminalIO.PutRopes["** failed placing error message ", message, ".\n"]; END; -- PutError spinifex: CDBottomUp.Class = CDBottomUp.Register [DoProc, ReUseProc]; [] _ CDProperties.RegisterProperty [$SX, $SX]; CDProperties.InstallProcs [$SX, [makeCopy: CDProperties.CopyVal, exclusive: TRUE, autoRem: TRUE]] 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: Christian Jacobi, June 6, 1986 8:20:04 pm PDT Last edited by: Christian Jacobi, February 24, 1987 1:30:33 pm PST Last edited by: gbb September 2, 1986 1:42:55 pm PDT For debugging. Main of Analyze 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, DistroyLogicalCell: 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) gbb September 2, 1986 1:42:32 pm PDT Added an error log. changes to: DIRECTORY, SXAccessInternalImpl, errorSummary, Analyze, MarkAndCheckRoots (local of Analyze), PutError Êé˜code™Kšœ Ïmœ1™š ¡œžœžœžœ žœžœž˜fš žœžœ(žœžœž˜Ašžœžœ˜$Kšœžœ,˜3Kšœ*˜*Kšœžœ˜Kšœ˜—Kšžœ8žœ!˜`Kšž˜—Kšžœ ˜—š¡ œžœ4žœ˜[š žœžœ(žœžœž˜AKšœ5˜5Kšž˜—Kšœ˜—š¡œžœž˜"Kšžœžœžœ#˜=šžœ˜Kšœ0˜0š žœžœžœžœžœžœž˜GKšœžœ˜+Kšž˜—Kšœ˜—Kšžœ ˜—M™KšœT˜TKšœžœžœ˜$Kš œžœdžœžœžœ '˜¹Kšœ6žœ˜VKšžœžœ!žœ˜6Kšœ4˜4Mšœ,˜,Mšžœžœ˜Mšœ˜Kšœ;˜;š žœ žœžœžœž˜7Kšœ@˜@—Kšžœ  ˜—š¡œž˜!Kšœžœ#˜*KšœR˜RKšœ˜Kšžœ  ˜—š¡ œž˜'Kšœžœ#˜,Kšœ žœ˜!Kšœ2žœžœžœ˜bKšœE˜EKšžœ  ˜—š¡ œžœžœž˜/šžœžœ˜Kšœžœžœžœ˜Cšžœ žœ˜'Kšœ@˜@—Kšœ#˜#KšœžœT˜gK˜—Kšžœ ˜—š¡ œžœžœž˜0Kšœ'žœIžœ'˜Kšžœ ˜—š ¡œžœžœ žœž˜AKšœžœ#˜,Kšœ žœ˜!Kšœ1žœ.˜bKšœ=˜=Kšžœ ˜—š ¡œžœžœžœ ž˜6Kšœžœ#˜,KšœžœG˜RKšœžœžœ ˜ Kšžœ žœžœ˜1šžœ˜Kšœ^˜^Kšžœžœžœžœ˜)Kšžœ˜Kšœ˜Kšžœžœžœžœ˜)Kšœ ˜ Kšžœžœžœžœ˜)K™KKšžœ$žœžœ'˜VK˜—Kšœ žœ˜!KšœD˜DKšœ˜Kšžœ ˜—š ¡œžœžœžœžœž˜>Kšœžœ#˜,šžœžœž˜šœžœ˜Kšœ€˜€Kšœ,˜,K˜—šžœ˜ Kšœ¥˜¥Kšžœž˜ Kšœ˜——Kšžœ ˜—š ¡œž œžœ žœžœž˜MKšœžœ#˜*Kšœžœ¬˜¶šžœžœžœ˜Kšœ"˜"Kšžœžœ˜6K˜—Mšœžœžœ˜F•StartOfExpansion[]šžœž˜ KšœH˜H—Kšžœ  ˜—LšœE˜EKšœ.˜.KšœLžœ žœ˜aKšžœ˜™2K™Kšœ Ïr œ¢ œ5™Y—™1Kšœ ¢ œv¢œ™—Kš œ ¢ œ ¢ œ)¢œ¢œ¢œ¢ ™Ù—™$Kšœ-¢œ¢ œ™o—K™™$K™Kšœ ¢Iœ¢ ™r—K™—…—f+ÿ