SXAccessInternalImpl.mesa
Copyright © 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
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
For debugging.
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
Main of Analyze
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;
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.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.
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