SXAccessInternalImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Written by Jacobi, April 2, 1985 5:11:35 pm PST
Last Edited by: Jacobi, June 6, 1986 8:20:04 pm PDT
Last edited by: gbb March 26, 1986 2:58:44 pm PST
DIRECTORY
Atom USING [GetPName],
CD USING [InstanceList, Object, Rect],
CDBasics USING [Extend],
CDBottomUp,
CDDirectory USING [EnumerateChildObjects, EnumerateObjectsProc, Name],
CDErrors USING [IncludeMessage, RemoveMessages],
CDEvents USING [EventProc, RegisterEventProc],
CDOps USING [ObjectInfo],
CDProperties USING [GetObjectProp, PutObjectProp],
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, CDBottomUp, 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.ROPENIL;
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
For debugging.
TerminalIO.WriteRope ["\nDone list: "];
FOR l: DoneList ← d, l.rest WHILE l # NIL DO
TerminalIO.WriteRope [CDOps.ObjectInfo[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.GetObjectProp [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.PutObjectProp [onto: ob, prop: $SX, val: sxd];
RETURN [sxd]
}
END; -- GetSXData
ClearSXData: CDEvents.EventProc = BEGIN
[event: REF, design: CD.Design, x: REF] RETURNS [dont: BOOL�LSE]
Deletes the Spinifex data from a cell when it has been edited.
cell: CD.Object = NARROW [x, CD.Object];
CDProperties.PutObjectProp [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.ObjectInfo[al.first.ob]]]];
ENDLOOP
END; -- MarkAndCheckRoots
AnalyzeEach: PROC [hierarchyRoots: CD.InstanceList ] = BEGIN
h: CDBottomUp.Handle ← CDBottomUp.MakeHandle[spinifex, SXAccess.design];
FOR al: CD.InstanceList ← hierarchyRoots, al.rest WHILE al#NIL DO
[] ← CDBottomUp.DoRecurse[h, 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
Main of Analyze
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
DoProc: CDBottomUp.DoProc = {
sx: REF SX.LogicalCell = GetSXData[ob];
CDErrors.RemoveMessages[design: SXAccess.design, ob: ob, owner: $SXErrorMessage];
AnalyzePreparedOb[ob];
sx.lastInvocation ← SXAccess.invocation
};
ReUseProc: CDBottomUp.ReUseProc = {
cell: REF SX.LogicalCell = GetSXData[ob];
doneList ← CONS [cell, doneList];
TerminalIO.WriteRope [IO.PutFR ["skipped: %g, already analyzed.", IO.rope[CDDirectory.Name[ob]]]];
WriteDevices[cell]; WriteErrors[cell]; TerminalIO.WriteLn[];
cell.lastInvocation ← SXAccess.invocation;
};
WriteErrors: PROC [sx: REF SXData] = BEGIN
IF sx.errorCount#0 THEN {
message: Rope.ROPEIO.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
AnalyzeObAndChildren: PROC [ob: CD.Object] RETURNS [propagate: BOOLFALSE] = BEGIN
CheckAChild: CDDirectory.EnumerateObjectsProc = BEGIN
PROC [me: CD.Object, x: REF]
figures out if we need to reanalyze AnalyzeObAndChildren.ob because me changed
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
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.GetObjectProp [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;
Technology dependent manipulation and checking (e.g. CMOS n-well connects).
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
spinifex: CDBottomUp.Class = CDBottomUp.Register[DoProc, ReUseProc];
CDEvents.RegisterEventProc [proc: ClearSXData, event: $AfterCellReplacement];
CDEvents.RegisterEventProc [proc: ClearSXData, event: $AfterChange];
END.
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)