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, April 2, 1985 5:11:39 pm PST
Last edited by: gbb July 15, 1985 11:58:23 am PDT
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.Object ← 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] =
When a cell is edited and replaced, it gets into the doneList. This procedure removes the old logical cell associated with this cell.
BEGIN
FOR cells: DoneList ← doneList, cells.rest
WHILE cells #
NIL
DO
notObsolete: BOOL ← TRUE;
FOR cadavers:
LIST
OF
CD.Object ← 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.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 =
--PROC [event: REF, design: CD.Design, x: REF] RETURNS [dont: BOOLLSE]
BEGIN
cell: CD.Object = NARROW [x, CD.Object];
changedList ← CONS [cell, changedList];
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
Main of Analyze
errorSummary ← NIL;
doneList ← CleanUpDoneList [doneList];
hierarchyRoots ← MarkAndCheckRoots[hierarchyRoots];
AnalyzeEach[hierarchyRoots];
WriteErrorSummary[];
SXOutput.PrintCircuit [InvertList[doneList], SXAccess.formatKey]
END; -- Analyze
AnalyzeObAndChildren:
PROC [ob:
CD.Object]
RETURNS [propagate: BOOL ← FALSE] =
BEGIN
CheckAChild: CDDirectory.EnumerateObjectsProc =
--PROC [me: CD.Object, x: REF]
--figures out if we need to reanalyze AnalyzeObAndChildren.ob because me changed
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.Object, 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.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;
--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, 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.
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