DIRECTORY Atom, List, MPCDefs, PartitionDefs, ParserTypeDefs, NStripeDefs, PrincOps, Real, Rope, IntStorageDefs, IntTransDefs, IODefs, PolygonDefs, ParserErrorDefs, OutputDefs, OutputInternalDefs; Output: CEDAR PROGRAM IMPORTS List, PartitionDefs, NStripeDefs, Real, IntTransDefs, IODefs, PolygonDefs, ParserErrorDefs EXPORTS OutputDefs, OutputInternalDefs = BEGIN OPEN OutputDefs; Point: TYPE = ParserTypeDefs.Point; PointList: TYPE = ParserTypeDefs.PointList; Path: TYPE = ParserTypeDefs.Path; one: REAL _ 1.0; half: REAL _ 0.5; small: REAL _ 0.0001; --used relative to 1 mebes unit w: PUBLIC REF MPCDefs.WaferDescriptor; c: PUBLIC REF MPCDefs.ChipDescriptor; p: PUBLIC REF MPCDefs.ProjectDescriptor; InitOutput: PUBLIC PROC [chip: REF MPCDefs.ChipDescriptor] RETURNS [BOOL] = BEGIN PartitionDefs.InitPartitions["Pfile$"]; c _ chip; w _ c.inWafer; NStripeDefs.InitStripe[c.chipSizeX*w.outputUnitsPerMicron, c.chipSizeY*w.outputUnitsPerMicron]; FOR pl: Atom.PropList _ w.layerFileList, pl.rest WHILE pl#NIL DO WITH pl.first.val SELECT FROM lfi: MPCDefs.LayerFileItem => TRUSTED { lfi.pFileLayer _ List.Length[LOOPHOLE[pl]] }; ENDCASE => ERROR; ENDLOOP; RETURN[TRUE]; END; InitProject: PUBLIC PROC [project: REF MPCDefs.ProjectDescriptor] RETURNS [BOOL] = BEGIN p _ project; IF p.inChip # c THEN ERROR; TRUSTED { cifMap _ NEW[OutputInternalDefs.CIFMap[List.Length[LOOPHOLE[p.layerMap]]+1]] }; cifMap[0] _ NIL; FOR pl: Atom.PropList _ p.layerMap, pl.rest WHILE pl#NIL DO WITH pl.first.val SELECT FROM lg: MPCDefs.LayerGroup => BEGIN TRUSTED {lg.cifIndex _ List.Length[LOOPHOLE[pl]] }; cifMap[lg.cifIndex] _ lg; END; ENDCASE => ERROR; ENDLOOP; RETURN[TRUE]; END; RPoint: TYPE = RECORD [x, y: REAL]; cifMap: PUBLIC REF OutputInternalDefs.CIFMap _ NIL; ID: PROC [n: CARDINAL, index: INTEGER] RETURNS [fileLayer: CARDINAL, stretch: REAL -- diameter, CIF units --, nextindex: INTEGER] = BEGIN IF cifMap[n] = NIL THEN {ParserErrorDefs.Report["No Such Layer", Advisory]; RETURN[0, 0, -1]} ELSE BEGIN r: REF ANY; TRUSTED { r _ List.NthTail[LOOPHOLE[cifMap[n].maskLayers], index] }; IF r = NIL THEN RETURN[0, 0, -1] ELSE WITH r SELECT FROM pl: Atom.PropList => WITH pl.first.val SELECT FROM la: MPCDefs.LayerAssoc => RETURN[ fileLayer: la.toLayer.pFileLayer, stretch: 100*la.stretch, -- express stretch in CIF units nextindex: index+1]; ENDCASE => ERROR; ENDCASE => ERROR; END; END; -- of ID OutputWire: PUBLIC PROC [ visible: VisibleType, layerName: CARDINAL, width: LONG CARDINAL, a: Path] = BEGIN ENABLE NStripeDefs.OutOfBoundsNumber => BEGIN ParserErrorDefs.Report["Wire coordinate out of bounds", Fatal]; CONTINUE; END; layer: CARDINAL; stretch, length, Width, halfw, offset: REAL; A, b, c: PointList; ab, bc: Point; lengthab, lengthbc: REAL; aExt, bExt: REAL; inline: REAL; index: INTEGER _ 0; Stepbc: PROC = BEGIN --given old c, compute b, new c, bc, lengthbc b _ c; UNTIL c = a.last DO c _ c.rest; bc _ Point[c.first.x - b.first.x, c.first.y - b.first.y]; lengthbc _ Real.SqRt[Dot[bc, bc]]; IF lengthbc = 0 THEN b _ c ELSE EXIT; ENDLOOP; END; IF a.length = 0 OR layerName = 100 THEN RETURN; DO --once per definition of this layer [layer, stretch, index] _ ID[layerName, index]; IF index < 0 THEN RETURN; Width _ width + stretch; halfw _ Width*half; c _ a.first; Stepbc[]; IF b = a.last THEN BEGIN OutputFlash[visible, layerName, width, b.first]; RETURN; END; bExt _ halfw; UNTIL b = a.last DO A _ b; aExt _ bExt; ab _ bc; lengthab _ lengthbc; Stepbc[]; IF b = a.last THEN bExt _ halfw ELSE BEGIN IF (inline _ Dot[ab, bc]) < 0 THEN BEGIN bExt _ 0; OutputFlash[visible, layerName, width, b.first]; END ELSE bExt _ halfw*ABS[Dot[[ab.y, -ab.x], bc]]/(inline + lengthab*lengthbc); END; length _ lengthab + aExt + bExt; offset _ (lengthab - aExt + bExt)/2; SELECT TRUE FROM ab.y = 0 => ROutputBox[ layer, length, Width, [ IF ab.x >= 0 THEN A.first.x + offset ELSE A.first.x - offset, A.first.y]]; ab.x = 0 => ROutputBox[ layer, width, length, [ A.first.x, IF ab.y >= 0 THEN A.first.y + offset ELSE A.first.y - offset]]; ENDCASE => BEGIN IntTransDefs.Push[]; IntTransDefs.Translate[Real.Round[offset], 0]; --'A' to origin IntTransDefs.Rotate[ab.x, ab.y]; IntTransDefs.Translate[A.first.x, A.first.y]; --'A' to correct place ROutputBox[layer, length, Width, [0, 0]]; IntTransDefs.Pop[]; END; ENDLOOP; ENDLOOP; --multi-layers loop END; Dot: PROC [p, q: Point] RETURNS [dotProd: REAL] = BEGIN RETURN[Real.Float[p.x]*Real.Float[q.x] + Real.Float[p.y]*Real.Float[q.y]]; END; twoMR2: REAL = 2.0 - Real.SqRt[2]; R2M1: REAL = Real.SqRt[2] - 1.0; OutputFlash: PUBLIC PROC [ visible: VisibleType, layerName: CARDINAL, diameter: LONG CARDINAL, center: Point] = BEGIN ENABLE NStripeDefs.OutOfBoundsNumber => BEGIN ParserErrorDefs.Report["Flash coordinate out of bounds", Fatal]; CONTINUE; END; layer: CARDINAL; stretch, h1, h2, cX, cY, Diameter, radius: REAL; index: INTEGER _ 0; IF layerName = 100 THEN RETURN; DO --once per definition of this layer [layer, stretch, index] _ ID[layerName, index]; IF index < 0 THEN RETURN; Diameter _ (diameter + stretch)*w.outputUnitsPerMicron/100; radius _ Diameter/2; h1 _ twoMR2*radius; h2 _ R2M1*radius; [cX, cY] _ IntTransDefs.RTransformPoint[center.x, center.y]; NStripeDefs.WriteTrapezoid[layer, Diameter, h1, cX - radius, cY + h2, 1, -1]; NStripeDefs.WriteRectangle[layer, Diameter, h2 + h2, cX - radius, cY - h2]; NStripeDefs.WriteTrapezoid[layer, h2 + h2, h1, cX - h2, cY - radius, -1, 1]; ENDLOOP; END; OutputPolygon: PUBLIC PROC [ visible: VisibleType, layerName: CARDINAL, a: Path] = BEGIN ENABLE NStripeDefs.OutOfBoundsNumber => BEGIN ParserErrorDefs.Report["Polygon coordinate out of bounds", Fatal]; CONTINUE; END; xT, yT, stretch, R2M1s: REAL; p, prev: PointList; layer: CARDINAL; poly: PolygonDefs.PolygonDescriptor; index: INTEGER _ 0; Angle: TYPE = { lessthan45, between45and90, perp, between90and135, between135and180}; StretchedTrapezoid: PROC [llx, lrx, ly, ulx, urx, uy: REAL] = BEGIN h: REAL = uy - ly; IF h < small THEN RETURN; NStripeDefs.WriteTrapezoid[layer, lrx - llx, h, llx, ly, (ulx - llx)/h, (urx - lrx)/h]; END; UnStretchedTrapezoid: PROC [llx, lrx, ly, ulx, urx, uy: REAL] = BEGIN --Stretch each trapezoid and reconvert it polygon: PolygonDefs.PolygonDescriptor _ PolygonDefs.PolyCreate[]; p, p1, p2, q, q1, q2, r, r1, r2: RPoint; case: Angle; [case, p1, p, p2, q1, q, q2, r1, r, r2] _ ExtendCorners[ [urx, uy], [lrx, ly], stretch]; IF case = lessthan45 THEN PolygonDefs.PolyVertex[polygon, urx + p.x, uy + p.y] ELSE BEGIN PolygonDefs.PolyVertex[polygon, urx + p1.x, uy + p1.y]; PolygonDefs.PolyVertex[polygon, urx + p2.x, uy + p2.y] END; SELECT case FROM lessthan45 => BEGIN PolygonDefs.PolyVertex[polygon, lrx + q1.x, ly + q1.y]; PolygonDefs.PolyVertex[polygon, lrx + q2.x, ly + q2.y]; END; between45and90 => PolygonDefs.PolyVertex[polygon, lrx + q.x, ly + q.y]; between90and135 => PolygonDefs.PolyVertex[polygon, urx + q.x, uy + q.y]; between135and180 => BEGIN PolygonDefs.PolyVertex[polygon, urx + q1.x, uy + q1.y]; PolygonDefs.PolyVertex[polygon, urx + q2.x, uy + q2.y]; END; ENDCASE; IF case = between135and180 THEN PolygonDefs.PolyVertex[polygon, lrx + r.x, ly + r.y] ELSE BEGIN PolygonDefs.PolyVertex[polygon, lrx + r1.x, ly + r1.y]; PolygonDefs.PolyVertex[polygon, lrx + r2.x, ly + r2.y]; END; [case, p1, p, p2, q1, q, q2, r1, r, r2] _ ExtendCorners[ [-llx, -ly], [-ulx, -uy], stretch]; IF case = lessthan45 THEN PolygonDefs.PolyVertex[polygon, llx - p.x, ly - p.y] ELSE BEGIN PolygonDefs.PolyVertex[polygon, llx - p1.x, ly - p1.y]; PolygonDefs.PolyVertex[polygon, llx - p2.x, ly - p2.y] END; SELECT case FROM lessthan45 => BEGIN PolygonDefs.PolyVertex[polygon, ulx - q1.x, uy - q1.y]; PolygonDefs.PolyVertex[polygon, ulx - q2.x, uy - q2.y]; END; between45and90 => PolygonDefs.PolyVertex[polygon, ulx - q.x, uy - q.y]; between90and135 => PolygonDefs.PolyVertex[polygon, llx - q.x, ly - q.y]; between135and180 => BEGIN PolygonDefs.PolyVertex[polygon, llx - q1.x, ly - q1.y]; PolygonDefs.PolyVertex[polygon, llx - q2.x, ly - q2.y]; END; ENDCASE; IF case = between135and180 THEN PolygonDefs.PolyVertex[polygon, ulx - r.x, uy - r.y] ELSE BEGIN PolygonDefs.PolyVertex[polygon, ulx - r1.x, uy - r1.y]; PolygonDefs.PolyVertex[polygon, ulx - r2.x, uy - r2.y]; END; PolygonDefs.PolyGenerate[polygon, StretchedTrapezoid]; END; ExtendCorners: PUBLIC PROC [tr, br: RPoint, s: REAL] RETURNS [case: Angle, P1, P, P2, Q1, Q, Q2, R1, R, R2: RPoint] = BEGIN --return case and displacements of extended points for right edge bc: RPoint; upSideDown: BOOL = tr.x > br.x; s _ s/2; -- Halve stretch so get TOTAL compensation, PJM IF upSideDown THEN BEGIN t: REAL = tr.x; tr.x _ br.x; br.x _ t; END; bc _ [br.x - tr.x, br.y - tr.y]; IF bc.x = 0 THEN RETURN[ perp, [R2M1s, s], [s, s], [s, R2M1s], [s, 0], [s, 0], [s, 0], [ s, -R2M1s], [s, -s], [R2M1s, -s]] ELSE BEGIN p1, p, p2, q1, q, q2, r1, r, r2: RPoint; lengthbc: REAL = Real.SqRt[bc.x*bc.x + bc.y*bc.y]; unitbc: RPoint = [bc.x/lengthbc, bc.y/lengthbc]; bcrot: RPoint = [-unitbc.y, unitbc.x]; pdir: RPoint = [bcrot.x, bcrot.y + 1]; qdir: RPoint = [bcrot.x + 1, bcrot.y]; p _ [s*pdir.x/pdir.y, s]; p1 _ [R2M1*p.x, s]; p2 _ [s*bcrot.x - p1.x*unitbc.x, s*bcrot.y - p1.x*unitbc.y]; q _ [s, s*qdir.y/qdir.x]; q2 _ [s, R2M1*q.y]; q1 _ [s*bcrot.x + q2.y*unitbc.x, s*bcrot.y + q2.y*unitbc.y]; r _ [s, -s]; r1 _ [s, -R2M1s]; r2 _ [R2M1s, -s]; IF upSideDown THEN RETURN[ IF bc.x > -bc.y THEN between135and180 ELSE between90and135, [ r2.x, -r2.y], [r.x, -r.y], [r1.x, -r1.y], [q2.x, -q2.y], [ q.x, -q.y], [q1.x, -q1.y], [p2.x, -p2.y], [p.x, -p.y], [ p1.x, -p1.y]] ELSE RETURN[ IF bc.x > -bc.y THEN lessthan45 ELSE between45and90, p1, p, p2, q1, q, q2, r1, r, r2]; END; END; IF a.length = 0 OR layerName = 100 THEN RETURN; DO --once per definition of this layer [layer, stretch, index] _ ID[layerName, index]; IF index < 0 THEN RETURN; IF stretch < 0 THEN ParserErrorDefs.Report["Negative polygon stretch", Advisory]; stretch _ stretch*w.outputUnitsPerMicron/100; --stretch in CIF units R2M1s _ R2M1*stretch; poly _ PolygonDefs.PolyCreate[]; prev _ NIL; FOR p _ a.first, p.rest UNTIL prev = a.last DO [xT, yT] _ IntTransDefs.RTransformPoint[p.first.x, p.first.y]; PolygonDefs.PolyVertex[poly, xT, yT]; prev _ p; ENDLOOP; PolygonDefs.PolyGenerate[ poly, IF stretch = 0 THEN StretchedTrapezoid ELSE UnStretchedTrapezoid]; ENDLOOP; END; OutputBox: PUBLIC PROC [ visible: VisibleType, layerName: CARDINAL, length, width: LONG CARDINAL, center: Point, xRotation, yRotation: INT] = BEGIN ENABLE NStripeDefs.OutOfBoundsNumber => BEGIN ParserErrorDefs.Report["Box coordinate out of bounds", Fatal]; CONTINUE; END; layer: CARDINAL; Length, Width, stretch: REAL; centerX: REAL _ center.x; centerY: REAL _ center.y; index: INTEGER _ 0; IF layerName = 100 THEN RETURN; DO --once per definition of this layer [layer, stretch, index] _ ID[layerName, index]; IF index < 0 THEN RETURN; Length _ length + stretch; Width _ width + stretch; SELECT TRUE FROM yRotation = 0 => ROutputBox[layer, Length, Width, [centerX, centerY]]; xRotation = 0 => ROutputBox[layer, Width, Length, [centerX, centerY]]; ENDCASE => BEGIN --do rotation AND translation via transformations IntTransDefs.Push[]; IntTransDefs.Rotate[xRotation, yRotation]; IntTransDefs.Translate[center.x, center.y]; ROutputBox[layer, Length, Width, [0, 0]]; IntTransDefs.Pop[]; END; ENDLOOP; END; ROutputBox: PROC [layer: CARDINAL, length, width: REAL, center: RPoint] = BEGIN lenR: REAL _ length*half; widR: REAL _ width*half; lenT, widT: RPoint; --Transformed half Length and Width [lenT.x, lenT.y] _ IntTransDefs.RTransformVector[lenR, 0]; [widT.x, widT.y] _ IntTransDefs.RTransformVector[0, widR]; IF widT.x = 0 OR widT.y = 0 THEN BEGIN ax, ay, bx, by: REAL; [ax, ay] _ IntTransDefs.RTransformPoint[center.x - lenR, center.y - widR]; [bx, by] _ IntTransDefs.RTransformPoint[center.x + lenR, center.y + widR]; NStripeDefs.WriteRectangle[layer, ABS[bx - ax], ABS[by - ay], MIN[ax, bx], MIN[ay, by]]; END ELSE BEGIN top, nextA, nextB: RPoint; lenSl, widSl, widTx2, widTy2, cX, cY: REAL; widH: REAL; --horizontal Width IF lenT.y < 0 THEN lenT _ [-lenT.x, -lenT.y]; IF widT.y < 0 THEN widT _ [-widT.x, -widT.y]; IF lenT.y < widT.y THEN BEGIN T: RPoint _ lenT; lenT _ widT; widT _ T; END; lenSl _ lenT.x/lenT.y; widSl _ widT.x/widT.y; widH _ 2*(widT.x + widT.y/widSl); top _ [lenT.x + widT.x, lenT.y + widT.y]; nextA _ [lenT.x - widT.x, lenT.y - widT.y]; nextB _ [nextA.x + widH, nextA.y]; widTx2 _ widT.x + widT.x; widTy2 _ widT.y + widT.y; [cX, cY] _ IntTransDefs.RTransformPoint[center.x, center.y]; IF lenT.x > 0 THEN BEGIN --L in first quadrant, widT.x & widH negative NStripeDefs.WriteTrapezoid[ layer, -widH, widTy2, cX + nextB.x, cY + nextB.y, lenSl, widSl]; IF nextA.y # 0 THEN NStripeDefs.WriteTrapezoid[ layer, -widH, nextA.y + nextA.y, cX - nextA.x, cY - nextA.y, lenSl, lenSl]; NStripeDefs.WriteTrapezoid[layer, 0, widTy2, cX - top.x, cY - top.y, widSl, lenSl]; END ELSE BEGIN --L in second quadrant, widT.x & widH positive NStripeDefs.WriteTrapezoid[ layer, widH, widTy2, cX + nextA.x, cY + nextA.y, widSl, lenSl]; IF nextA.y # 0 THEN NStripeDefs.WriteTrapezoid[ layer, widH, nextA.y + nextA.y, cX - nextB.x, cY - nextB.y, lenSl, lenSl]; NStripeDefs.WriteTrapezoid[layer, 0, widTy2, cX - top.x, cY - top.y, lenSl, widSl]; END; END; END; OutputUserCommand: PUBLIC PROC [command: [0..9], userText: Rope.ROPE] = BEGIN END; OutputUserObject: PUBLIC PROC [visible: VisibleType, layerName: CARDINAL, data: REF ANY] = { NULL }; OutputBoundingBox: PUBLIC PROC [left, right, bottom, top: INT] = BEGIN IODefs.WriteLine["OutputBoundingBox Called"]; END; Relation: PUBLIC PROC [ left1, right1, bottom1, top1, left2, right2, bottom2, top2: INT] RETURNS [RelationType] = BEGIN RETURN[ dontcare ]; END; Visible: PUBLIC PROC [ kind: IntStorageDefs.Object, level: CARDINAL, parentVis: VisibleType, left, right, bottom, top: INT] RETURNS [VisibleType] = BEGIN RETURN[yes]; END; BBWire: PUBLIC PROC [ layerName: CARDINAL, width: LONG CARDINAL, a: Path] RETURNS [left, right, bottom, top: INT] = BEGIN halfw, xT, yT: REAL; p, prev: PointList; IF a.length = 0 THEN RETURN[0, 0, 0, 0]; minmaxStarted _ FALSE; halfw _ width/2; prev _ NIL; FOR p _ a.first, p.rest UNTIL prev = a.last DO [xT, yT] _ IntTransDefs.RTransformPoint[p.first.x, p.first.y]; UpdateMinMax[xT - halfw, xT + halfw, yT - halfw, yT + halfw]; prev _ p; ENDLOOP; RETURN[FloorI[XMin], CeilingI[XMax], FloorI[YMin], CeilingI[YMax]]; END; BBFlash: PUBLIC PROC [ layerName: CARDINAL, diameter: LONG CARDINAL, center: Point] RETURNS [left, right, bottom, top: INT] = BEGIN radius: REAL = diameter*half; xT, yT: REAL; [xT, yT] _ IntTransDefs.RTransformPoint[center.x, center.y]; RETURN[ FloorI[xT - radius], CeilingI[xT + radius], FloorI[yT - radius], CeilingI[ yT + radius]]; END; BBPolygon: PUBLIC PROC [layerName: CARDINAL, a: Path] RETURNS [left, right, bottom, top: INT] = BEGIN xT, yT: REAL; p, prev: PointList; IF a.length = 0 THEN RETURN[0, 0, 0, 0]; minmaxStarted _ FALSE; prev _ NIL; FOR p _ a.first, p.rest UNTIL prev = a.last DO [xT, yT] _ IntTransDefs.RTransformPoint[p.first.x, p.first.y]; UpdateMinMax[xT, xT, yT, yT]; prev _ p; ENDLOOP; RETURN[FloorI[XMin], CeilingI[XMax], FloorI[YMin], CeilingI[YMax]]; END; BBBox: PUBLIC PROC [ layerName: CARDINAL, length, width: LONG CARDINAL, center: Point, xRotation, yRotation: INT] RETURNS [left, right, bottom, top: INT] = BEGIN SELECT TRUE FROM yRotation = 0 => [left, right, bottom, top] _ RBBBox[length, width, [center.x, center.y]]; xRotation = 0 => [left, right, bottom, top] _ RBBBox[width, length, [center.x, center.y]]; ENDCASE => BEGIN --accomplish rotation AND translation via transformations IntTransDefs.Push[]; IntTransDefs.Rotate[xRotation, yRotation]; IntTransDefs.Translate[center.x, center.y]; [left, right, bottom, top] _ RBBBox[length, width, [0, 0]]; IntTransDefs.Pop[]; END; END; BBUserObject: PUBLIC PROC [ layerName: CARDINAL, data: REF ANY] RETURNS [left, right, bottom, top: INT] = BEGIN left _ right _ bottom _ top _ 0; END; RBBBox: PROC [length, width: REAL, center: RPoint] RETURNS [left, right, bottom, top: INT] = BEGIN lenR: REAL _ length*half; --depends on length and width being positive widR: REAL _ width*half; cx, cy: REAL; lenT, widT: RPoint; --Transformed half length and Width [cx, cy] _ IntTransDefs.RTransformPoint[center.x, center.y]; [widT.x, widT.y] _ IntTransDefs.RTransformVector[0, widR]; SELECT TRUE FROM widT.x = 0 => RETURN[ FloorI[cx - lenR], CeilingI[cx + lenR], FloorI[cy - widR], CeilingI[ cy + widR]]; widT.y = 0 => RETURN[ FloorI[cx - widR], CeilingI[cx + widR], FloorI[cy - lenR], CeilingI[ cy + lenR]]; ENDCASE => BEGIN w, h: REAL; [lenT.x, lenT.y] _ IntTransDefs.RTransformVector[lenR, 0]; IF lenT.y < 0 THEN lenT _ [-lenT.x, -lenT.y]; IF widT.y < 0 THEN widT _ [-widT.x, -widT.y]; w _ ABS[lenT.x - widT.x]; h _ ABS[lenT.y + widT.y]; RETURN[ FloorI[cx - w], CeilingI[cx + w], FloorI[cy - h], CeilingI[cy + h]]; END; END; minmaxStarted: BOOL; XMin, XMax, YMin, YMax: REAL; UpdateMinMax: PROC [xmin, xmax, ymin, ymax: REAL] = INLINE BEGIN IF minmaxStarted THEN BEGIN IF xmin < XMin THEN XMin _ xmin; IF xmax > XMax THEN XMax _ xmax; IF ymin < YMin THEN YMin _ ymin; IF ymax > YMax THEN YMax _ ymax; END ELSE BEGIN XMin _ xmin; XMax _ xmax; YMin _ ymin; YMax _ ymax; minmaxStarted _ TRUE; END; END; FloorI: PROC [r: REAL] RETURNS [i: INT] = INLINE BEGIN i _ Real.Fix[r]; IF r < 0 THEN i _ Real.Fix[r - i + 1] + i - 1; END; CeilingI: PROC [r: REAL] RETURNS [i: INT] = INLINE BEGIN i _ Real.Fix[r]; IF r > 0 THEN i _ Real.Fix[r - i - 1] + i + 1; END; END. TOutput.mesa Last edited: November 1, 1982 7:21 PM Modified by TRS for compat with new Parser/Interp December 9, 1980 2:47 PM Modified by AWP on May 14, 1982 for CMOS. WARNING: LAYERS MAPPED INTO '100' GO BYE-BYE!!! Edited by AWP, Nov 1, 82 to use latest MAGIC interpreter (parent vis parameter added at Visible:) Modified by PJM on 14-Nov-83 11:15:42 Fixed Polygon compensation to be Total not by edge Modified by PJM on April 6, 1984 fixed NSIL3 ability Last Edited by: McCreight, June 13, 1985 4:15:59 pm PDT .. to scale stretches returned by the ID routine to CIF units instead of microns Assign partition file layer indices Assign Cif layer indices and set up a map Looks up fileLayer and stretch (in CIF units) from string layer name Multiple entries are possible. On first entry, "index" should be set to 0. On subsequent entries "index" should be set to the last returned "nextindex". When nextindex is returned negative then no layer was found and no more entries should be made. If no distinct new c then b will be a.Last Filters out verticies giving rise to zero length segments Approximate circle with an octagon aligned with axes Generate new corners and build new polygon Right edge Left edge - turn through 180 degrees Convert it again Polygon code starts here Internal procedure for really dealing with boxes It assumes that stretches have been applied to the input data Rotations must have been dealt with either by interchanging coords or by setting up the appropriate transformation. Check for "Manhattan" rectangle (common case) Arrange rectangle axes to have positive y, with L higher We now have one of two similar configurations mirrored about y axis ParserErrorDefs.Report["User Extension ignored", Advisory]; in chip coordinates, not obvious how to call this yet establish ordering this version orders left within bottom SELECT bottom1 FROM rel, =bottom2 => same, ENDCASE => norel determine whether an item should be shown returns the bounding box of the primitive interpreted in the current context Internal procedure for really dealing with boxes Rotations must have been dealt with either by interchanging coords or by setting up the appropriate transformation. Check for "Manhattan" rectangles (common case) Arrange rectangle axes to have positive y We now have one of two similar configurations mirrored about y axis Private procedure Êi˜J˜Jšœ ™ Jšœ&™&JšœK™KJšœ)™)Jšœ/™/Jšœ8™8Jšœ(™(Jšœ&™&Jšœ3™3Jšœ5™5šœ7™7J™P—J˜šÏk ˜ Jšœº˜ºJ˜—šœœ˜š˜J˜=J˜—Jšœ!˜(J˜Jš˜šœ ˜J˜—Jšœœ˜#Jšœ œ˜+Jšœœ˜!J˜Jšœœ˜Jšœœ˜Jšœœ Ïc˜6J˜J˜Jšœ œ˜&Jšœ œ˜%Jšœ œ˜(J˜š Ïn œœœœœœ˜KJš˜J˜'J˜ J˜J˜_J˜Jšœ#™#šœ.œœ˜@šœœ˜šœ˜Jšœ œ˜7—Jšœœ˜—Jšœ˜J˜—Jšœœ˜ Jšœ˜J˜—š Ÿ œœœ œœœ˜RJš˜Jšœ ˜ Jšœœœ˜J˜Jšœ)™)Jšœ œ'œ˜YJšœ œ˜šœ)œœ˜;šœœ˜šœ˜Jš˜Jšœœ˜3Jšœ˜Jšœ˜—Jšœœ˜—Jšœ˜J˜—Jšœœ˜ Jšœ˜J˜—Jšœœœœ˜#J˜J˜Jšœœœœ˜3J˜šœœœ œ˜&Jš œ œ œžœ œ˜\JšœD™DJšœK™KJšœ@™@Jšœ ™ JšœB™BJšœ™Jš˜šœ œ˜Jšœ4œ ˜E—š˜Jš˜Jšœœœ˜ Jšœœ!˜DJšœœœœ ˜ š˜šœœ˜˜šœœ˜šœœ˜!Jšœ!˜!Jšœž˜8Jšœ˜—Jšœœ˜——Jšœœ˜——Jšœ˜—šœž˜ J˜—J˜—šŸ œœœ˜Jšœ!œ œœ˜@J˜ Jš˜š˜˜ JšœAœœ˜T——Jšœœ˜Jšœ'œ˜,Jšœ˜J˜Jšœœ˜Jšœ œ˜Jšœœ˜ Jšœœ˜šŸœœ˜Jšœž-˜4Jšœ*™*Jšœ9™9J˜šœ ˜J˜ J˜9J˜"Jšœœœœ˜%Jšœ˜—Jšœ˜J˜—Jšœœœœ˜/šœž#˜'Jšœœ˜/Jšœ œœ˜J˜J˜J˜J˜ J˜ šœ ˜Jšœ2œœ˜C—J˜ šœ ˜Jšœ˜J˜ J˜J˜J˜ Jšœ œ ˜š˜Jš˜šœ˜"Jšœ<˜D—š˜Jšœ œ6˜F—Jšœ˜—J˜ J˜$šœœ˜˜ ˜ J˜Jš œ œœœœ˜=Jšœ ˜ ——˜ ˜ J˜Jšœ ˜ Jš œ œœœœ˜?——šœ˜ Jš˜J˜Jšœ0ž˜?Jšœ ˜ Jšœœ œ ž˜EJ˜)Jšœ˜Jšœ˜——Jšœ˜—Jšœž˜—Jšœ˜J˜—šŸœœœ œ˜1JšœœEœ˜UJ˜—Jšœœ˜"Jšœœ˜ J˜šŸ œœœ˜Jšœ!œ œœ˜CJ˜Jšœ4™4Jš˜š˜˜ JšœBœœ˜U——Jšœœ˜Jšœ+œ˜0Jšœœ˜J˜Jšœœœ˜šœž#˜'Jšœœ˜/Jšœ œœ˜J˜;J˜J˜J˜Jšœ<˜˜QJšœ/ž˜EJ˜Jšœ ˜ Jšœœ˜ šœœ˜.Jšœ>˜>Jšœ%˜%J˜ Jšœ˜—šœ˜Jšœœ œœ˜H—Jšœ˜—Jšœ˜J˜—šŸ œœœ˜Jšœ!œœœ˜HJšœ%œ˜+Jš˜š˜˜ Jšœ@œœ˜S——Jšœœ˜Jšœœ˜Jšœ œ ˜Jšœ œ ˜Jšœœ˜J˜Jšœœœ˜šœž#˜'Jšœœ˜/Jšœ œœ˜J˜J˜šœœ˜J˜FJ˜Fšœ˜ Jšœž1˜8J˜Jšœ*˜*Jšœ+˜+J˜)Jšœ˜Jšœ˜——Jšœ˜—Jšœ˜J˜—šŸ œœ œœ˜IJš˜Jšœ0™0Jšœ=™=JšœE™EJšœ-™-J˜Jšœœ˜Jšœœ˜Jšœž#˜8J˜Jšœ:˜:Jšœ:˜:Jšœ-™-šœ œ ˜ Jš˜Jšœœ˜JšœJ˜JJšœJ˜JJš œ"œ œ œ œ ˜XJš˜—š˜Jš˜J˜Jšœ&œ˜+Jšœœž˜Jšœ8™8Jšœ œ˜-Jšœ œ˜-Jš œœœœ%œœ˜KJšœC™CJ˜J˜J˜!J˜)J˜+J˜"J˜J˜Jšœ<˜<šœ ˜Jšœž-˜4˜J˜@—šœ ˜˜J˜CJ˜——J˜SJš˜—š˜Jšœž.˜5˜J˜?—šœ ˜˜J˜BJ˜——J˜SJšœ˜—Jšœ˜—Jšœ˜J˜—šŸœœœ"œ˜GJš˜Jšœ;™;Jšœ˜——˜šŸœœœ#œ˜IJšœœœœ˜J˜—Jšœ5™5šŸœœœœ˜@Jšœ/œ˜8J˜—Jšœ™šŸœœœ˜Jšœ<œ˜@Jšœ˜Jš˜Jšœ&™&šœ˜˜Jšœ™Jšœ™Jšœ™Jšœ™J˜——Jšœ˜J˜—Jšœ)™)šŸœœœ˜Jšœ$œ˜EJšœœœ˜6Jšœœœ˜J˜—JšœL™LšŸœœœ˜Jšœ œ œœ ˜3Jšœœ˜)Jš˜Jšœœ˜Jšœ˜J˜Jšœœœ ˜(Jšœœ˜J˜Jšœœ˜ šœœ˜.Jšœ>˜>J˜=J˜ Jšœ˜—Jšœ=˜CJšœ˜J˜—šŸœœœ˜Jšœ œ œœ˜˜>J˜J˜ Jšœ˜—Jšœ=˜CJšœ˜J˜—šŸœœœ˜Jšœ œœœ˜2Jšœ%œ˜)Jšœœ˜)Jš˜šœœ˜˜J˜I—˜J˜I—šœ˜ Jšœž9˜@J˜Jšœ*˜*Jšœ+˜+J˜;Jšœ˜Jšœ˜——Jšœ˜J˜—šŸ œœœ˜Jšœ œœœ˜#Jšœœ˜)Jšœ"œ˜+J˜—šŸœœœ˜2Jšœœ˜)Jš˜Jšœ0™0JšœE™EJšœ-™-J˜Jšœœž,˜GJšœœ˜Jšœœ˜ Jšœž#˜8J˜Jšœ<˜