MPCControl:
CEDAR
PROGRAM
IMPORTS
FS, IntDefs, IO, IODefs, IntTransDefs, LayerFileDefs, OutputDefs, ParserDefs, ParserErrorDefs, ParserInputDefs, Rope
EXPORTS MPCDefs =
BEGIN
space: Rope.ROPE = " ";
InitMPC:
PUBLIC
PROCEDURE [mpc:
REF MPCDefs.MPCDescriptor]
RETURNS [ok: BOOLEAN] =
Set overall parameters
date must have exactly 6 characters (mmddyy)
BEGIN
IODefs.PrintTime[" InitMPC"];
IODefs.WriteString[" "];
IODefs.WriteString[mpc.title];
IODefs.WriteString[space];
IODefs.WriteString[mpc.date];
IODefs.WriteString[space];
IODefs.WriteLine[mpc.account];
ok ← mpc.title.Length <= 7 AND mpc.date.Length = 6 AND mpc.account.Length <= 20;
END;
InitWafer:
PUBLIC
PROCEDURE [wafer:
REF MPCDefs.WaferDescriptor]
RETURNS [ok: BOOLEAN] =
Set wafer parameters
BEGIN
IODefs.PrintTime[" InitWafer"];
IODefs.WriteString[" "];
IODefs.WriteString[wafer.waferName];
IODefs.WriteString[space];
IODefs.WriteReal[wafer.waferSizeX];
IODefs.WriteString[space];
IODefs.WriteReal[wafer.waferSizeY];
IODefs.WriteString[space];
IODefs.WriteReal[wafer.outputUnitsPerMicron];
IODefs.WriteLine[""];
ok ← (
SELECT wafer.outputUnitsPerMicron
FROM 1, 2, 4 =>
TRUE,
ENDCASE =>
FALSE)
AND wafer.inMPC.title.Length+wafer.waferName.Length <= 7;
END;
InitChip:
PUBLIC
PROCEDURE [chip:
REF MPCDefs.ChipDescriptor]
RETURNS [ok: BOOLEAN] =
Set chip parameters
chipName must have no more than 7 characters
chipSizeX, chipSizeY are in microns
positionOnWafer is not yet implemented
BEGIN
IODefs.PrintTime[" InitChip"];
IODefs.WriteString[" "];
IODefs.WriteString[chip.chipName];
IODefs.WriteString[space];
IODefs.WriteReal[chip.chipSizeX];
IODefs.WriteString[space];
IODefs.WriteReal[chip.chipSizeY];
IODefs.WriteLine[""];
ok ← chip.inWafer.inMPC.title.Length + chip.inWafer.waferName.Length + chip.chipName.Length = 7
AND
OutputDefs.InitOutput[chip];
END;
ConvertProject:
PUBLIC
PROCEDURE [project:
REF MPCDefs.ProjectDescriptor]
RETURNS [
ok: BOOLEAN,
errorSummary: ARRAY ParserErrorDefs.ErrorType OF CARDINAL] =
Set Project parameters and convert the project
rotateX, rotateY are as in CIF
translateX, translateY are in microns
layerArray provides correspondence between CIF layer names and
the internal fileLayer (normally to be numbered sequentially from
zero - used in WriteLayerFile) and with the stretches to be
used (in microns)
The errorSummary returned is a copy of the one from ParserErrorDefs
BEGIN
bias: LONG INTEGER; --Rounding fudge in CIF units to jog coords away from half units
aborted: BOOLEAN ← FALSE;
bias ← 8/project.inChip.inWafer.outputUnitsPerMicron;
IODefs.PrintTime[" ConvertProject"];
IODefs.WriteLine[IO.PutFR[" %g", IO.rope[UniqueID[project.cifFileName]]]];
IODefs.WriteLine[IO.PutFR[" %g %g %g %g", IO.real[project.rotateX], IO.real[project.rotateY], IO.real[project.translateX], IO.real[project.translateY]]];
ok ← TRUE;
errorSummary ← ALL[0];
[] ← OutputDefs.InitProject[project];
IF ~ParserDefs.InitParser[] OR ~ParserInputDefs.InFromFile[project.cifFileName] THEN RETURN[FALSE, errorSummary];
IF ~IntDefs.InitInterpreter[] THEN RETURN[FALSE, errorSummary];
Main loop to convert CIF file
BEGIN
ENABLE
ParserErrorDefs.ParserAbort =>
BEGIN aborted ← TRUE; IODefs.WriteLine["---Parser aborted---"]; CONTINUE; END;
nStatements: INT ← 0;
DO
SELECT ParserDefs.ParseStatement[]
FROM
End => BEGIN nStatements ← nStatements + 1; EXIT; END;
SemanticError, SyntaxError =>
IF ParserInputDefs.EndOfFile[] THEN aborted ← TRUE;
ENDCASE;
nStatements ← nStatements + 1;
IF nStatements
MOD 100 = 0
THEN
IODefs.PostIt[IO.PutFR["CIF File: %g, Statement: %g...", IO.rope[project.cifFileName], IO.int[nStatements]]];
IF ParserInputDefs.EndOfFile[]
THEN
BEGIN
IODefs.WriteLine[
"Unexpected end of input file, Probably missing End command"];
aborted ← TRUE;
END;
ENDLOOP;
END; --End of Enable clause
errorSummary ← ParserErrorDefs.ErrorSummary[];
[] ← ParserDefs.FinishParser[];
IntTransDefs.Push[];
IntTransDefs.Rotate[project.rotateX, project.rotateY]; --Orient project
IntTransDefs.Translate[(project.translateX*100) + bias, (project.translateY*100) + bias]; --Position project(converting to CIF units)
IntTransDefs.Scale[project.inChip.inWafer.outputUnitsPerMicron, 100]; --CIF units to Output(Mebes) units
IntTransDefs.Push[]; --Just in case next transformation user doesn't
ok ← ~aborted
AND
(errorSummary[Fatal] + errorSummary[FatalSyntax] + errorSummary[
FatalSemantic] + errorSummary[FatalInternal]) = 0;
IF ok THEN IntDefs.Instantiate[];
IntTransDefs.Pop[]; --to match safety Push
IntTransDefs.Pop[]; --project transformation
[] ← IntDefs.FinishInterpreter[];
END;
WriteLayerFile:
PUBLIC
PROCEDURE [layerFile: MPCDefs.LayerFileItem, chip:
REF MPCDefs.ChipDescriptor]
RETURNS [ok: BOOLEAN] =
Write Mebes layer file for internal fileLayer, using the Mebes
identification strings mebesLayerNumber and mebesLayerName
(e.g. "04" and "PO", respectively, for polysilicon)
BEGIN
totalChipName: Rope.
ROPE ←
IO.PutFR["%g%g%g",
IO.rope[chip.inWafer.inMPC.title], IO.rope[chip.inWafer.waferName],
IO.rope[chip.chipName]];
layerFileName: Rope.
ROPE ←
IO.PutFR["%g-%g-%g.mebes",
IO.rope[totalChipName], IO.rope[layerFile.layerNumber],
IO.rope[layerFile.layerName]];
layerNameString: Rope.
ROPE ←
IO.PutFR["%g%g.%g",
IO.rope[totalChipName], IO.rope[layerFile.layerNumber],
IO.rope[layerFile.layerName]];
IODefs.WriteLine[IO.PutFR[" WriteLayerFile %g %g %g ...", IO.rope[layerFile.layerNumber], IO.rope[layerFile.layerName], IO.time[]]];
LayerFileDefs.MakeLayerFile[
layerFileName, layerFile.pFileLayer, layerNameString, chip.inWafer.inMPC.date, " " -- mask shop info --,
chip.chipSizeX*chip.inWafer.outputUnitsPerMicron,
chip.chipSizeY*chip.inWafer.outputUnitsPerMicron,
chip.inWafer.outputUnitsPerMicron];
IODefs.WriteLine[IO.PutFR[" %g {%g} ... written", IO.rope[UniqueID[layerFileName]], IO.rope[layerNameString]]];
ok ← TRUE;
END;
FinishChip:
PUBLIC
PROCEDURE
RETURNS [ok:
BOOLEAN] =
BEGIN
IODefs.WriteString[" FinishChip -- "];
ok ← OutputDefs.FinishOutput[];
IODefs.PrintTime[" "];
END;
FinishWafer:
PUBLIC
PROCEDURE
RETURNS [ok:
BOOLEAN] =
Release all structures associated with the current wafer
BEGIN IODefs.PrintTime[" FinishWafer"]; RETURN[TRUE]; END;
FinishMPC:
PUBLIC
PROCEDURE
RETURNS [ok:
BOOLEAN] =
Release all structures associated with the whole run
BEGIN IODefs.PrintTime[" FinishMPC"]; RETURN[TRUE]; END;
UniqueID:
PROC [ fileName: Rope.
ROPE ]
RETURNS [ id: Rope.
ROPE ] =
BEGIN
fullFileName: Rope.ROPE ← fileName;
attachedTo: Rope.ROPE ← NIL;
bytes: INT ← 0;
gmt: BasicTime.GMT ← BasicTime.nullGMT;
[fullFName: fullFileName, attachedTo: attachedTo, bytes: bytes, created: gmt] ← FS.FileInfo[name: fileName, remoteCheck: TRUE ! FS.Error => CONTINUE];
id ←
IO.PutFR["%g%g (%g bytes) Of %g",
IO.rope[fullFileName],
IO.rope[(IF attachedTo.Length=0 THEN NIL ELSE IO.PutFR["(%g)", IO.rope[attachedTo]])],
IO.int[bytes],
(IF gmt=BasicTime.nullGMT THEN IO.rope["??"] ELSE IO.time[gmt])];
END;
END.