<> <> <> <> <> DIRECTORY CD USING [Layer, LayerKey, LayerTechnology, NewLayer, Number, Object, Position, Rect, Technology], CDAtomicObjects USING [AtomicObsSpecific, DrawList], CDColors USING [Brick, DefineColor, DefineIColor], CDProperties USING [RegisterProperty], ImagerColor USING [ColorFromRGB], Real USING [Float, InlineRound], Rope USING [ROPE], Saguaro; SaguaroImpl: CEDAR PROGRAM IMPORTS CD, CDColors, CDProperties, ImagerColor, Real EXPORTS Saguaro ~ BEGIN OPEN Real, Saguaro; <> gate: PUBLIC CD.Layer ~ CD.NewLayer [NIL, $gate]; invalidTransistor: PUBLIC SIGNAL [msg: Rope.ROPE] ~ CODE; <> <> <> <> <> <> <> <> ExtractTransistor: PUBLIC PROC [obj: CD.Object] RETURNS [et: ExtractedTransistor] ~ BEGIN class: ATOM ~ obj.class.objectType; poly, diff, well: CD.Layer; polList, difList, chList, difListSouth, wellList: LIST OF CD.Rect _ NIL; extL, extW: CD.Number; -- vert. diff, hor. poly tech: CD.Technology; IF (class = $Cell) THEN SIGNAL invalidTransistor ["Cannot extract hand-made transistors"]; IF (class = $NMosTransistor) OR (class = $NMosATransistor) OR (class = $NMosPullUp) THEN SIGNAL invalidTransistor ["N-Mos not supported"]; <> IF ISTYPE [obj.specific, CDAtomicObjects.AtomicObsSpecific] THEN FOR geom: CDAtomicObjects.DrawList _ NARROW [obj.specific, CDAtomicObjects.AtomicObsSpecific].rList, geom.rest WHILE geom # NIL DO SELECT CD.LayerKey [geom.first.layer] FROM $pol => {poly _ geom.first.layer; polList _ CONS [geom.first.r, polList]}; $ndif, $ndiff, $pdif, $pdiff => {diff _ geom.first.layer; difList _ CONS [geom.first.r, difList]}; $nwel, $nwell, $pwel, $pwell => {well _ geom.first.layer; wellList _ CONS [geom.first.r, wellList]}; ENDCASE => SIGNAL invalidTransistor ["Unknown transistor geometry"] ENDLOOP ELSE SIGNAL invalidTransistor ["Replace this old Chipmonk transistor"]; <> tech _ CD.LayerTechnology [obj.layer]; IF (tech = NIL) THEN tech _ CD.LayerTechnology [poly]; IF (tech = NIL) THEN tech _ CD.LayerTechnology [diff]; IF (tech = NIL) THEN ERROR; <> et _ NEW [ExXtr]; SELECT CD.LayerKey [obj.layer] FROM $ndif, $ndiff, $wndif => et.type _ nE; $pdif, $pdiff, $wpdif => et.type _ pE; ENDCASE => SIGNAL invalidTransistor ["Version mismatch"]; et.type _ IF (CD.LayerKey [obj.layer] = $ndif) THEN nE ELSE pE; SELECT class FROM $C2Trans, $C2WellTrans, $CTrans, $CWellTrans => BEGIN -- straight transistors difRect, polRect, chRect: CD.Rect; difExtRectNorth, difExtRectSouth, polExtEast, polExtWest: CD.Rect; IF (difList.rest # NIL) OR (polList.rest # NIL) THEN SIGNAL invalidTransistor ["Version mismatch"]; difRect _ difList.first; polRect _ polList.first; chRect _ [difRect.x1, polRect.y1, difRect.x2, polRect.y2]; difExtRectNorth _ difExtRectSouth _ difRect; difExtRectNorth.y1 _ polRect.y2; difExtRectSouth. y2 _ polRect.y1; polExtWest _ [polRect.x1, polRect.y1, difRect.x1, polRect.y2]; polExtEast _ [difRect.x2, polRect.y1, polRect.x2, polRect.y2]; extL _ polRect.y1 - difRect.y1; extW _ difRect.x1 - polRect.x1; et.length _ chRect.y2 - chRect.y1; et.width _ chRect.x2 - chRect.x1; et.gate.area _ (et.width + 2*extW) * et.length; et.gate.perimeter _ (et.width + 2*extW + et.length) * 2; et.ch1.area _ et.ch2.area _ extL * et.width; et.ch1.perimeter _ et.ch2.perimeter _ 2 * extL + et.width; et.gate.layout _ LIST [[polExtEast, poly], [polExtWest, poly], [chRect, gate]]; et.ch1.layout _ LIST [[difExtRectNorth, diff]]; et.ch2.layout _ LIST [[difExtRectSouth, diff]]; IF (((class = $C2WellTrans) OR (class = $CWellTrans)) AND (wellList = NIL)) THEN SIGNAL invalidTransistor ["Well transistor must have a well"] END; -- case $CTrans $C2LTrans, $C2LWellTrans, $CLTrans, $CLWellTrans => BEGIN -- angle transistors diffNE: CD.Position _ [FIRST[CD.Number], FIRST[CD.Number]]; diffSW, polSW, polSE: CD.Position _ [LAST[CD.Number], LAST[CD.Number]]; polHor, polVert, polExtWest, polExtNorth, chRectH, chRectV, rect: CD.Rect; d: CD.Number; IF ((polList.first.y2-polList.first.y1) < (polList.rest.first.y2-polList.rest.first.y1)) THEN {polHor _ polList.first; polVert _ polList.rest.first} ELSE {polHor _ polList.rest.first; polVert _ polList.first}; FOR dl: LIST OF CD.Rect _ difList, dl.rest WHILE dl # NIL DO IF (dl.first.x1 <= diffSW.x) AND (dl.first.y1 <= diffSW.y) THEN diffSW _ [dl.first.x1, dl.first.y1]; IF (dl.first.x2 >= diffNE.x) AND (dl.first.y2 >= diffNE.y) THEN diffNE _ [dl.first.x2, dl.first.y2]; ENDLOOP; polSW _ [polHor.x1, polHor.y1]; polSE _ [polVert.x2, polHor.y1]; extW _ diffSW.x - polSW.x; extL _ polSW.y - diffSW.y; et.length _ polHor.y2 - polHor.y1; et.width _ ((polSE.x - polHor.x1) - extW) + ((polVert.y2 - polSE.y) - extW) - InlineRound [0.45 * Float [et.length*et.length]]; et.gate.area _ ((et.width+et.length/2) + 2*extW) * et.length; et.gate.perimeter _ ((polHor.x2 - polHor.x1) + (polVert.y2 - polVert.y1)) * 2; -- ok! et.ch2.area _ ((diffNE.x - diffSW.x) + (diffNE.y - diffSW.y - extL)) * extL; et.ch2.perimeter _ 2 * extL + (diffNE.x - diffSW.x) + (diffNE.y - diffSW.y); et.ch1.perimeter _ diffNE.x + diffNE.y - diffSW.x - diffSW.y - 2 * (extL + et.length); et.ch1.area _ et.ch2.perimeter * extL; polExtWest _ [polSW.x, polSW.y, diffSW.x, polHor.y2]; polExtNorth _ [diffNE.x-extL-et.length, diffNE.y, diffNE.x-extL, polVert.y2]; chRectH _ polHor; chRectH.x1 _ chRectH.x1 + extW; chRectV _ polVert; chRectV.y1 _ polHor.y2; chRectV.y2 _ chRectV.y2 - extW; et.gate.layout _ LIST [[polExtWest, poly], [polExtNorth, poly], [chRectH, gate], [chRectV, gate]]; d _ extL + et.length; rect _ [x1: diffSW.x, y1: diffSW.y+d, x2: diffNE.x-d, y2: polSW.y+d]; IF (rect.x1 = diffNE.x-d-extL) THEN BEGIN rect.y2 _ diffNE.y; et.ch1.layout _ LIST [[rect, diff]] -- Nord END ELSE BEGIN et.ch1.layout _ LIST [[rect, diff]]; -- Nord IF (rect.y2 < diffNE.y) THEN BEGIN rect _ [x1: diffNE.x-d-extL, y1: polSW.y+d, x2: diffNE.x-d, y2: diffNE.y]; et.ch1.layout _ CONS [[rect, diff], et.ch1.layout] -- West END END; rect _ [x1: diffSW.x, y1: diffSW.y, x2: diffNE.x, y2: polSW.y]; et.ch2.layout _ LIST [[rect, diff]]; -- South rect _ [x1: diffNE.x-extL, y1: polSW.y, x2: diffNE.x, y2: diffNE.y]; et.ch2.layout _ CONS [[rect, diff], et.ch2.layout]; -- East <> IF (((class = $C2LWellTrans) OR (class = $CLWellTrans)) AND (wellList = NIL)) THEN SIGNAL invalidTransistor ["Well transistor must have a well"] END; -- case $C2LTrans, $C2LWellTrans ENDCASE => SIGNAL invalidTransistor ["Unknown or antiquated transistor class"]; et.ch1.perimeter _ et.ch1.perimeter / tech.lambda; et.ch1.area _ et.ch1.area / tech.lambda / tech.lambda; et.ch2.perimeter _ et.ch2.perimeter / tech.lambda; et.ch2.area _ et.ch2.area / tech.lambda / tech.lambda; et.gate.perimeter _ et.gate.perimeter / tech.lambda; et.gate.area _ et.gate.area / tech.lambda / tech.lambda; et.length _ et.length / tech.lambda; et.width _ et.width / tech.lambda; FOR w: LIST OF CD.Rect _ wellList, w.rest WHILE w # NIL DO et.bulk.layout _ CONS [[w.first, well], et.bulk.layout] ENDLOOP; END; -- ExtractTransistor <> <> CDColors.DefineColor [layer: gate, brick: NEW [CDColors.Brick _ [4369, 4369, 4369, 4369]], display: bit8]; CDColors.DefineColor [layer: gate, brick: NEW [CDColors.Brick _ [4352, 17, 4352, 17]], display: bit8, mode: pushedOut]; CDColors.DefineIColor [layer: gate, col: ImagerColor.ColorFromRGB [[1.0, 1.0, 0.0]], display: bit8]; [] _ CDProperties.RegisterProperty [$gate, $gbb] END.