DIRECTORY Atom, CD, CDBasics, CDDirectory, CDErrors, CDEvents, CDOps, CDProperties, CDSequencer, IO, Rope, SX, SXAccess, SXAccessInternal, SXAtoms, SXLayers, SXOutput, SXUserExtract, TerminalIO; 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; changedList: LIST OF CD.ObPtr _ NIL; 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 CleanUpDoneList: PROCEDURE [dirty: DoneList] RETURNS [clean: DoneList _ NIL] = BEGIN FOR cells: DoneList _ doneList, cells.rest WHILE cells # NIL DO notObsolete: BOOL _ TRUE; FOR cadavers: LIST OF CD.ObPtr _ changedList, cadavers.rest WHILE cadavers # NIL DO IF cells.first.cellObj = cadavers.first THEN notObsolete _ FALSE ENDLOOP; IF notObsolete THEN clean _ CONS [cells.first, clean] ENDLOOP; clean _ InvertList [clean]; changedList _ NIL END; -- CleanUpDoneList GetSXData: PUBLIC PROC[ob: CD.ObPtr] RETURNS [REF SXData] = BEGIN IF ~ob.p.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.ObPtr = NARROW [x, CD.ObPtr]; changedList _ CONS [cell, changedList]; CDProperties.PutPropOnObject [onto: cell, prop: $SX, val: NIL]; END; -- ClearSXData Analyze: PUBLIC PROC [hierarchyRoots: CD.ApplicationList] = BEGIN MarkAndCheckRoots: PROC [hierarchyRoots: CD.ApplicationList] RETURNS [roots: CD.ApplicationList_NIL] = BEGIN FOR al: CD.ApplicationList _ hierarchyRoots, al.rest WHILE al#NIL DO IF al.first.ob.p.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.ApplicationList ] = BEGIN FOR al: CD.ApplicationList _ 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 _ CleanUpDoneList [doneList]; hierarchyRoots _ MarkAndCheckRoots[hierarchyRoots]; AnalyzeEach[hierarchyRoots]; WriteErrorSummary[]; SXOutput.PrintCircuit [InvertList[doneList], SXAccess.formatKey] END; -- Analyze AnalyzeObAndChildren: PROC [ob: CD.ObPtr] 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 -- analyze object BEGIN 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[";"]; TerminalIO.WriteRope[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.ObPtr, sx: REF SXData] = BEGIN TerminalIO.WriteRope[IO.PutFR["skipped: %g, already analyzed", IO.rope[CDDirectory.Name[ob]] ]]; WriteDevices[sx]; WriteErrors[sx]; TerminalIO.WriteLn[]; END; AnalyzePreparedOb: PUBLIC PROC [ob: CD.ObPtr] = 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.ObPtr, 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.ObPtr, r: CD.DesignRect, message: Rope.ROPE] = BEGIN sx: REF SXData = GetSXData[ob]; done: BOOL = CDErrors.IncludeMessage[ design: SXAccess.design, ob: ob, rect: CDBasics.Extend[r, CD.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["** unable to place error message "]; TerminalIO.WriteRope[message]; TerminalIO.WriteLn[]; }; END; -- PutError CDEvents.RegisterEventProc [proc: ClearSXData, event: $AfterCellReplacement]; CDEvents.RegisterEventProc [proc: ClearSXData, event: $AfterChange]; END. RSXAccessInternalImpl.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: Beretta, July 3, 1985 3:11:06 pm PDT When a cell is edited and replaced, it gets into the doneList. This procedure removes the old logical cell associated with this cell. --PROC [event: REF, design: CD.Design, x: REF] RETURNS [dont: BOOL_FALSE] Main of Analyze --PROC [me: CD.ObPtr, 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 ส ˜code™Kšœ ฯmœ1™Kšž˜šžœ!žœžœž˜5Kšœžœ˜Kšžœ˜—Kšžœฯc ˜—š œž œžœžœ˜NK™…Kšž˜šžœ(žœ žœž˜?Kšœ žœžœ˜š žœ žœžœžœ$žœ žœž˜SKšžœ&žœž˜@Kšžœ˜—Kšžœ žœ žœ˜5Kšžœ˜—Kšœ*ž˜-Kšžœก˜—K˜š   œžœžœžœžœžœ ˜;Kšž˜Kšžœžœžœžœ˜'šžœ*žœž˜9Kšœžœ žœ˜ šžœ˜ Kšœžœ žœ ˜Kšœ ก ˜,Kšœก-˜?Kšœ=˜=Kšžœ˜ Kšœ˜——Kšžœก ˜—šŸ œ˜"KšœJ™JKšž˜Kšœžœ žœžœ˜&Kšœžœ˜'Kšœ:žœ˜?Kšžœก˜—š œžœžœžœ˜;Kšž˜š œžœžœ˜=Kšžœ žœžœ˜)Kšž˜š žœžœ+žœžœž˜Dšžœžœ˜#Kšœžœ!˜(Kšœ*˜*Kšœžœ˜Kšœ˜—Kšžœžœ,žœ!˜mKšžœ˜—Kšžœก˜—š  œžœžœ˜9Kšž˜š žœžœ+žœžœž˜DKšœ&˜&Kšž˜—Kšžœก˜—š œžœ˜Kšž˜Kšžœžœžœ$˜<šžœ˜Kšœ1˜1š žœžœžœžœžœžœž˜GKšœ˜Kšœ!˜!Kšœ˜Kšž˜—Kšœ˜—Kšžœก˜—L™Kšœžœ˜Kšœ&˜&Kšœ3˜3Kšœ˜Kšœ˜Kšœ@˜@Kšžœก ˜—K˜š œžœžœ˜*Kšžœ žœžœ˜#Kšž˜šŸ œ%˜0Kšœ™KšœFฯeœ™PKšž˜Kšœžœ˜1Kšœžœ˜)Kšžœก˜—Lšœžœ˜š žœžœžœ(žœžœ˜[Kšœ(˜(Kšœ=žœ˜Bšžœ žœก˜#Kšž˜KšœR˜RKšœ˜Kšž˜—šžœ˜Kšœ˜—Kšœ(˜(K˜—Kšžœก˜—K˜š  œžœžœ ˜$Kšž˜šžœžœ˜Kšœžœžœžœ˜Cšžœ žœ˜'Kšœ?˜?—Kšœ˜Kšœ˜KšœžœB˜UK˜—Kšžœก˜—K˜š  œžœžœ ˜%Kšž˜šœžœ˜4KšžœH˜JKšžœ$˜&Kšœ˜—Kšžœก˜—K˜š œžœžœ žœ ˜5Kšž˜šœžœ'˜>Kšžœ˜Kšœ˜—Kšœ˜Kšœ˜Kšœ˜Kšžœ˜—code2š œžœžœžœ ˜/Kšž˜Kšœžœžœ˜)KšœžœJ˜UKšœžœžœ ˜Kšžœžœžœ˜.šžœ˜KšœV˜VKšžœžœžœžœ˜)Kšžœ˜Kšœ˜Kšžœžœžœžœ˜)Kšœ˜Kšžœžœžœžœ˜)K™MKšžœ!žœžœ'˜RK˜—Kšœ žœ˜ Kšœ˜Kšœ˜K˜Kšœ ˜ Kšžœก˜—K˜š  œžœžœžœ žœ˜7Kšž˜Kšœžœžœ˜)šžœžœž˜šœžœ˜Kšœp˜pKšœ+˜+K˜—šžœ˜ Kšœ”˜”Kšžœž˜ Kšœ˜——Kšžœก˜—K˜š  œž œžœ žœžœ˜LKšž˜Kšœžœ˜šœžœ˜%Kšœ˜Kšœ˜Kšœžœ ˜&Kšœ˜Kšœ˜—šžœžœžœ˜Kšœ"˜"Kšžœžœ˜3K˜—•StartOfExpansion[]šžœžœ˜Kšœ:˜:Kšœ˜Kšœ˜K˜—Kšžœก ˜—K˜KšœM˜MKšœD˜DKšžœ˜K™™2K™Kšœ ฯr œฃ œ5™Y—™1Kšœ ฃ œvฃœ™—Kš œ ฃ œ ฃ œ)ฃœฃ œฃœฃ ™า—K™K™—…—ฌ*