GenerateCompositeOb:
PROC [obj:
CD.ObPtr] =
--output composite objects
--the children must be already defined
BEGIN
pr: CD.DrawRef ← CD.CreateDrawRef[design];
dummyApPtr:
CD.ApplicationPtr =
NEW[
CD.Application];
--match the type of drawMe parameter
dummyApPtr^.ob ← obj;
pr.stopFlag ← stopFlag;
SymHeader[obj];
CIFDrawCellName[CDDirectory.Name[obj]];
--call the children
pr.drawChild ← CallChildren;
obj.p.drawMe[dummyApPtr, [0, 0], CD.original, pr];
--draw the rectangles
pr.drawChild ← DrawRectChilds;
pr.drawRect ← pr.saveRect ← CIFOrArea;
FOR directives:
LIST
OF
REF
ANY ← cifDirectives, directives.rest
WHILE directives#
NIL
DO
currentDirective ← NARROW[directives.first];
cifLayerAnnounced ← FALSE;
IF currentDirective.deltaRadius>=0
THEN
obj.p.drawMe[dummyApPtr, [0, 0], CD.original, pr];
ENDLOOP;
SymTrailer[];
END;
CIFDefineObject:
PROC [obj:
CD.ObPtr] =
--Print out CIF pertaining to object starting with the furthest object from the top; After leaving procedure, object will have been assigned a CIF ID # in its properties field
BEGIN
CheckChildren: CDDirectory.EnumerateObjectsProc = {
IF me.p.inDirectory
AND CDEnvironment.Propagates[me]
THEN {
hasChildWhichPropagates ← TRUE
}
ELSE CIFDefineObject[me]
};
hasChildWhichPropagates: BOOL ← FALSE;
IF debugging THEN TerminalIO.WriteRope["Entering CIFDefineObject\n"];
IF CDProperties.GetPropFromObject[obj, cellIDKey]#
NIL
THEN
RETURN;
--non-NIL value indicates that object has already been assigned an ID # and is therefore already defined
--We should also make a test here to decide whether any hierarchical geometry results from this object, and assign a special value to this object's attribute $CellIDNo if not.
IF obj.p.inDirectory
THEN {
IF CDEnvironment.Propagates[obj] THEN ERROR;
CDDirectory.EnumerateChildObjects[obj, CheckChildren, NIL];
};
IF hasChildWhichPropagates
THEN {
ob1: CD.ObPtr ← CDDirectory.ExpandHard[me: obj, from: design, to: NIL];
IF ob1#
NIL
AND ~CDEnvironment.Propagates[ob1]
AND ~CDEnvironment.SomeChildPropagates[ob1]
THEN {
CIFDefineObject[ob1];
CDProperties.PutPropOnObject[
onto: obj,
prop: cellIDKey,
val: CDProperties.GetPropFromObject[ob1, cellIDKey]
];
}
ELSE GenerateGeometricOb[obj: obj];
}
ELSE
WITH obj.specificRef
SELECT
FROM
refPtr: CDImports.ReferencePtr => {
IF refPtr.boundApp=NIL THEN ERROR;
CIFDefineObject[refPtr.boundApp.ob];
SymHeader[obj];
CIFDrawCellName[Rope.Cat[refPtr.designName, ".", refPtr.objectName]];
CIFSymbolCall[refPtr.boundApp.ob, CD.original, [0, 0]];
SymTrailer[];
};
cellptr:
CD.CellPtr => {
SymHeader[obj];
CIFDrawCellName[cellptr.name];
--For each member of the application list, determine whether obj is a cell. If so, determine transformations
FOR aplist:
CD.ApplicationList ← cellptr.contents, aplist.rest
WHILE aplist#
NIL
DO
IF ~SimpleRect[aplist.first.ob]
THEN {
cifPos: CIFPos ← CDPosToCIF[CDOrient.MapPoint[
pointInCell: [0, 0],
cellSize: aplist.first.ob.size,
cellInstOrient: aplist.first.orientation,
cellInstPos: aplist.first.location
]];
CIFSymbolCall[aplist.first.ob, aplist.first.orientation, cifPos];
};
ENDLOOP;
--for each layer, pick out the rectangles belonging to that layer
--and output them
FOR directives:
LIST
OF
REF
ANY ← cifDirectives, directives.rest
WHILE directives#
NIL
DO
currentDirective ← NARROW[directives.first];
cifLayerAnnounced ← FALSE;
IF currentDirective.deltaRadius>=0
THEN
FOR aplist:
CD.ApplicationList ← cellptr.contents, aplist.rest
WHILE aplist#
NIL
DO
IF SimpleRect[aplist.first.ob]
THEN {
aplist.first.ob.p.drawMe[aptr: aplist.first, pos: aplist.first.location, orient: aplist.first.orientation, pr: cifDrawRec];
};
ENDLOOP;
ENDLOOP;
--generate all signal names
FOR aplist:
CD.ApplicationList ← cellptr.contents, aplist.rest
WHILE aplist#
NIL
DO
value: REF = CDProperties.GetPropFromObject[aplist.first.ob, $signalName];
IF value#
NIL
THEN
IF SimpleRect[aplist.first.ob]
THEN
CIFLabelTerminalIO[aplist.first, NARROW[value], aplist.first.ob.layer];
ENDLOOP;
SymTrailer[];
}; -- of cell
ENDCASE =>
-- crazy or transistors or geometry or rects
IF obj.p.inDirectory THEN GenerateCompositeOb[obj]
ELSE
IF ~SimpleRect[obj]
THEN {
IF ISTYPE[obj.specificRef, CDPolygons.PolygonPtr] THEN GeneratePolygon[obj]
ELSE GenerateGeometricOb[obj];
};
IF debugging THEN TerminalIO.WriteRope["Leaving CIFDefineObject\n"];
END;
WriteCIF:
PROC[ comm: CDSequencer.Command] =
BEGIN
ENABLE BEGIN
ABORTED => {TerminalIO.WriteRope[" CIF generation aborted\n"]; GOTO Exit};
RopeNeeded => {
explanation: Rope.ROPE = IO.PutFR[format: "Please enter a string corresponding to the value %g: ", v1: IO.refAny[ref^]];
ref^ ← TerminalIO.RequestRope[explanation];
RESUME;
};
UNWIND => NULL;
END; --enable
--assign world variable from sequencer
mainOb: CD.ObPtr;
cifKey: Rope.ROPE;
design ← comm.design;
cifKey ← ToRope[CDProperties.GetPropFromTechnology[design.technology, $CDxCIFName]];
IF Rope.IsEmpty[cifKey]
THEN {
TerminalIO.WriteRope["The CIF layers for this technology are not yet defined\n"];
RETURN
};
TerminalIO.WriteRope["Use CIF layer definitions ["];
TerminalIO.WriteRope[cifKey];
TerminalIO.WriteRope["]\n"];
--initialize main object, layer names, resolution, cellCount, and draw records
mainOb ← CDExtras.CreateDummyObject[design];
cellCount ← 0;
stopFlag^ ← FALSE;
cifMeasureR ← CD.CreateDrawRef[design];
cifMeasureR.interestClip ← CDBasics.universe;
cifMeasureR.drawRect ← cifMeasureR.saveRect ← CIFMeasureArea;
cifMeasureR.stopFlag ← stopFlag;
clearIDsRec ← CD.CreateDrawRef[design];
clearIDsRec.interestClip ← CDBasics.universe;
clearIDsRec.drawChild ← ClearCellIDs;
clearIDsRec.stopFlag ← stopFlag;
cifDrawRec ← CD.CreateDrawRef[design];
cifDrawRec.interestClip ← CDBasics.universe;
cifDrawRec.drawRect ← cifDrawRec.saveRect ← CIFOrArea;
cifDrawRec.stopFlag ← stopFlag;
--Search world data structure: normalize coordinates,
--set mainRect to design size, mark used layers
CDOps.DrawDesign[design, cifMeasureR];
--get file name
TerminalIO.WriteRope["Input name of CIF file ("];
TerminalIO.WriteRope[CDIO.GetWorkingDirectory[design]];
TerminalIO.WriteRope[") "];
base ← TerminalIO.RequestRope[">> "];
IF Rope.IsEmpty[base] THEN base ← design.name;
IF Rope.IsEmpty[base] THEN base ← "foo";
name ← CDIO.MakeName[base: base, ext: ".cif", wDir: CDIO.GetWorkingDirectory[design]];
cifFile ←
FS.StreamOpen[name, create !
FS.Error =>
IF error.group#bug
THEN {
TerminalIO.WriteRope[error.explanation];
GOTO FileIOOpenFailed;
}
];
TerminalIO.WriteRope["How many CIF units per lambda?\n"];
cifPerLambda ← TerminalIO.RequestInt[" (1 CIF unit = 0.01 microns) \n", ">> "];
IF cifPerLambda<2
THEN {
TerminalIO.WriteRope["cif Per Lambda value not reasonable\n"];
RETURN
};
IF debugging
THEN {
TerminalIO.WriteRope["cif Per Lambda = "];
TerminalIO.WriteInt[cifPerLambda];
TerminalIO.WriteRope["\n"];
};
cifPerCD ← cifPerLambda/lambda;
--output header
cifFile.PutF["( %s );\n", IO.rope[design.name]];
cifFile.PutF["( generated %g by Xerox PARC ChipNDale and BrandyCIFter);\n", IO.time[]];
cifFile.PutF["( with lambda = %d CIF units );\n", IO.int[cifPerLambda]];
cifFile.PutF["( origin = [x: 0, y: 0], size = [x: %d, y: %d] CIF units );\n", IO.int[cifPerCD*(mainRect.x2-mainRect.x1)], IO.int[cifPerCD*(mainRect.y2-mainRect.y1)]];
cifFile.PutF["( CIF KEY: %s );\n", IO.rope[cifKey]];
cifFile.PutRope["(BRANDYCIFTER NOT YET TESTED);\n"];
--ask for comment lines
TerminalIO.WriteRope["Comment line: \n"];
comment ← TerminalIO.RequestRope["(parens must balance, CR for no comment)\n", ">> "];
WHILE
NOT Rope.IsEmpty[comment]
DO
cifFile.PutF["( %s )\n", IO.rope[comment]];
comment ← NIL;
TerminalIO.WriteRope["Another comment line:\n"];
comment←TerminalIO.RequestRope[
"(parens must balance, CR for no further comments)\n", ">> "];
ENDLOOP;
IO.PutChar[cifFile,
IO.
CR];
CollectDirectives[];
SetCIFScaling[];
ClearCellIDs[design.actual.first.dummyCell, [0,0], 0, NIL];
CIFDefineObject[mainOb];
--define hybrid top layer object
SymHeader[topLayerOb];
CIFSymbolCall[mainOb];
FOR directives:
LIST
OF
REF
ANY ← cifDirectives, directives.rest
WHILE directives#
NIL
DO
currentDirective ← NARROW[directives.first];
IF currentDirective.deltaRadius<0
THEN
BEGIN
cifLayerAnnounced ← FALSE;
MakeFlatCIF[rectProc: CIFRectOut];
END;
ENDLOOP;
SymTrailer[];
CIFSymbolCall[topLayerOb, CDOrient.original, [x: -cifPerCD*mainRect.x1, y: -cifPerCD*mainRect.y2]];
cifFile.PutRope[";\nEnd ... \n"];
cifFile.Close[];
TerminalIO.WriteLn[];
TerminalIO.WriteRope["CIF file on "];
TerminalIO.WriteRope[name];
TerminalIO.WriteLn[];
FreeStorage[]
EXITS
Exit => FreeStorage[];
FileIOOpenFailed => {
TerminalIO.WriteRope["Open Failed\n"];
FreeStorage[]
};
END; -- of WriteCIF