DIRECTORY CD, CDBasics, CoreClasses, Rope, SC, SCInstUtil, SCPrivate, SCRowUtil, SCUtil, RTBasic, RTSets; SCInstUtilImpl: CEDAR PROGRAM IMPORTS CDBasics, SC, SCInstUtil, SCRowUtil, SCUtil, Rope, RTBasic, RTSets EXPORTS SCInstUtil SHARES SC = BEGIN defltLgOrien: PUBLIC SCPrivate.Orientation _ 1; defltBpOrien: PUBLIC ARRAY SC.Side OF SCPrivate.Orientation _ [3, 1, 4, 2]; InstWidth: PUBLIC PROCEDURE[inst: SCPrivate.Instance] RETURNS[width: SC.Number] = BEGIN orien: SCPrivate.OrientationOrNone _ inst.curOrien; SELECT orien FROM 0, 1, 3, 5, 6 => width _ inst.object.size.p; 2, 4, 7, 8 => width _ inst.object.size.q; ENDCASE; END; InstHeight: PUBLIC PROCEDURE[inst: SCPrivate.Instance] RETURNS[height: SC.Number] = BEGIN orien: SCPrivate.OrientationOrNone _ inst.curOrien; SELECT orien FROM 0, 1, 3, 5, 6 => height _ inst.object.size.q; 2, 4, 7, 8 => height _ inst.object.size.p; ENDCASE; END; BpHeight: PUBLIC PROCEDURE[inst: SCPrivate.Instance] RETURNS[height: SC.Number] = { IF inst.whichClass # io THEN SC.Error[programmingError, Rope.Cat["Instance: ", inst.name, " should be an IO"]]; SELECT inst.curSide FROM top, bottom => height _ InstHeight[inst]; left, right => height _ InstWidth[inst]; ENDCASE => SC.Error[programmingError, NIL]}; BpWidth: PUBLIC PROCEDURE[inst: SCPrivate.Instance] RETURNS[width: SC.Number] = { IF inst.whichClass # io THEN SC.Error[programmingError, Rope.Cat["Instance: ", inst.name, " should be an IO"]]; SELECT inst.curSide FROM top, bottom => width _ InstWidth[inst]; left, right => width _ InstHeight[inst]; ENDCASE => SC.Error[programmingError, NIL]}; MinMaxBPOffset: PUBLIC PROCEDURE[handle: SC.Handle, side: SC.Side] RETURNS [minOffset, maxOffset: SC.Number] = { InstProc: SCRowUtil.EachInstProc = { minOffset _ MIN[minOffset, instance.offset]; maxOffset _ MAX[maxOffset, instance.offset]}; minOffset _ LAST[INT]; maxOffset _ -minOffset; [] _ SCRowUtil.EnumerateAllInstsOnSide[handle, side, InstProc]}; BpOffsets: PUBLIC PROCEDURE[handle: SC.Handle, side: SC.Side, pos1, pos2: SCPrivate.ZMaxPosSr] = { layoutData: SCPrivate.LayoutData _ NARROW[handle.layoutData]; bpRow: SCPrivate.BpRow _ layoutData.bpRows[side]; offset: SC.Number; posA: SCPrivate.ZMaxPosSr _ MIN[pos1, pos2]; posB: SCPrivate.ZMaxPosSr _ MAX[pos1, pos2]; IF posA <= 1 THEN {posA _ 1; offset _ 0} ELSE {inst: SCPrivate.Instance _ bpRow.bpsOnSide[posA-1]; IF side = bottom OR side = right THEN offset _ inst.offset + InstWidth[inst] + bpRow.bpSpacing ELSE offset _ inst.offset + bpRow.bpSpacing}; IF posB = 0 OR posB > bpRow.nBpsOnSide THEN posB _ bpRow.nBpsOnSide; FOR posIndex: SCPrivate.ZMaxPosSr IN [posA .. posB] DO inst: SCPrivate.Instance _ bpRow.bpsOnSide[posIndex]; width: SC.Number _ BpWidth[inst]; IF side = bottom OR side = right THEN inst.offset _ offset ELSE inst.offset _ offset + width; offset _ offset + width + bpRow.bpSpacing; ENDLOOP}; CheckBpOffsets: PUBLIC PROCEDURE[handle: SC.Handle, side: SC.Side] = { layoutData: SCPrivate.LayoutData _ NARROW[handle.layoutData]; bpRow: SCPrivate.BpRow _ layoutData.bpRows[side]; offset: SC.Number _ 0; FOR posIndex: SCPrivate.ZMaxPosSr IN [1 .. bpRow.nBpsOnSide] DO inst: SCPrivate.Instance _ bpRow.bpsOnSide[posIndex]; width: SC.Number _ BpWidth[inst]; IF side = bottom OR side = right THEN { IF inst.offset # offset THEN SC.Error[programmingError, "Not suppose to happen"]} ELSE { IF inst.offset # offset + width THEN SC.Error[programmingError, "Not suppose to happen"]}; offset _ offset + width + bpRow.bpSpacing; ENDLOOP}; BpPos: PUBLIC PROCEDURE[handle: SC.Handle, inst: SCPrivate.Instance] RETURNS[result: SC.Number] = { layoutData: SCPrivate.LayoutData _ NARROW[handle.layoutData]; bpRow: SCPrivate.BpRow _ layoutData.bpRows[inst.curSide]; IF inst.whichClass # io THEN SC.Error[programmingError, "objet must be of type io"]; SELECT inst.curSide FROM right => result _ bpRow.sideOrg.q + inst.offset; bottom => result _ bpRow.sideOrg.p + inst.offset; left => result _ bpRow.sideOrg.q - inst.offset; top => result _ bpRow.sideOrg.p - inst.offset; ENDCASE}; InstPosOf: PUBLIC PROCEDURE[handle: SC.Handle, inst: SCPrivate.Instance, pin: SCPrivate.ObjectPin] RETURNS[pos: RTBasic.PQPos] = { layoutData: SCPrivate.LayoutData _ NARROW[handle.layoutData]; xy: CD.Position _ SELECT pin.pinPos.side FROM bottom => [pin.pinPos.location, pin.pinPos.depth], right => [InstWidth[inst] - pin.pinPos.depth, pin.pinPos.location], top => [pin.pinPos.location, InstHeight[inst] - pin.pinPos.depth], left => [pin.pinPos.depth, pin.pinPos.location], ENDCASE => SC.Error[programmingError, "No suppose to happen"]; xyPos: CD.Position _ SELECT inst.curOrien FROM 1 => [xy.x, xy.y], -- original 2 => [xy.y, InstWidth[inst] - xy.x], -- rotate270 3 => [InstWidth[inst] - xy.x, InstHeight[inst] - xy.y], -- rotate180 4 => [InstHeight[inst] - xy.y, xy.x], -- rotate90 5 => [InstWidth[inst] - xy.x, xy.y], -- mirrorX 6 => [xy.x, InstHeight[inst] - xy.y], -- rotate180X 7 => [xy.y, xy.x], -- rotate270X 8 => [InstHeight[inst] - xy.y, InstWidth[inst] - xy.x], -- rotate90X ENDCASE => SC.Error[programmingError, "No suppose to happen"]; SELECT inst.whichClass FROM logic, ft => { lgRow: SCPrivate.LgRow _ layoutData.lgRows.rows[inst.curRow]; pos _ [lgRow.rowOrg.p + inst.offset + xyPos.x, lgRow.rowOrg.q + xyPos.y]}; io => { bpRow: SCPrivate.BpRow _ layoutData.bpRows[inst.curSide]; pos _ SELECT inst.curSide FROM right => [bpRow.sideOrg.p + xyPos.x, bpRow.sideOrg.q + inst.offset + xyPos.y], bottom => [bpRow.sideOrg.p + inst.offset + xyPos.x, bpRow.sideOrg.q + xyPos.y], left => [bpRow.sideOrg.p + xyPos.x, bpRow.sideOrg.q - inst.offset + xyPos.y], top => [bpRow.sideOrg.p - inst.offset + xyPos.x, bpRow.sideOrg.q + xyPos.y], ENDCASE => SC.Error[programmingError, "No suppose to happen"]}; ENDCASE}; PosOf: PUBLIC PROCEDURE[inst: SCPrivate.Instance, pin: SCPrivate.ObjectPin] RETURNS [pinDes: SCInstUtil.PinDescription] = { xy: CD.Position _ SELECT pin.pinPos.side FROM bottom => [pin.pinPos.location, pin.pinPos.depth], right => [InstWidth[inst] - pin.pinPos.depth, pin.pinPos.location], top => [pin.pinPos.location, InstHeight[inst] - pin.pinPos.depth], left => [pin.pinPos.depth, pin.pinPos.location], ENDCASE => SC.Error[programmingError, "No suppose to happen"]; xyOrien: CD.Position _ SELECT inst.curOrien FROM 1 => [xy.x, xy.y], -- original 2 => [xy.y, InstWidth[inst] - xy.x], -- rotate270 3 => [InstWidth[inst] - xy.x, InstHeight[inst] - xy.y], -- rotate180 4 => [InstHeight[inst] - xy.y, xy.x], -- rotate90 5 => [InstWidth[inst] - xy.x, xy.y], -- mirrorX 6 => [xy.x, InstHeight[inst] - xy.y], -- rotate180X 7 => [xy.y, xy.x], -- rotate270X 8 => [InstHeight[inst] - xy.y, InstWidth[inst] - xy.x], -- rotate90X ENDCASE => SC.Error[programmingError, "No suppose to happen"]; pinDes _ [xyOrien.x, xyOrien.y, SCUtil.SideTranslate[pin.pinPos.side, inst.curOrien]]}; RotateRect: PUBLIC PROCEDURE[inst: SCPrivate.Instance, defRect: SC.Rect] RETURNS [SC.Rect] = { newRect: SC.Rect; SELECT inst.curOrien FROM 1 => -- original {newRect.x1 _ defRect.x1; newRect.y1 _ defRect.y1; newRect.x2 _ defRect.x2; newRect.y2 _ defRect.y2}; 2 => -- rotate270 {newRect.x1 _ defRect.y1; newRect.y1 _ InstWidth[inst] - defRect.x1; newRect.x2 _ defRect.y2; newRect.y2 _ InstWidth[inst] - defRect.x2}; 3 => -- rotate180 {newRect.x1 _ InstWidth[inst] - defRect.x1; newRect.y1 _ InstHeight[inst] - defRect.y1; newRect.x2 _ InstWidth[inst] - defRect.x2; newRect.y2 _ InstHeight[inst] - defRect.y2}; 4 => -- rotate90 {newRect.x1 _ InstHeight[inst] - defRect.y1; newRect.y1 _ defRect.x1; newRect.x2 _ InstHeight[inst] - defRect.y2; newRect.y2 _ defRect.x2}; 5 => -- mirrorX {newRect.x1 _ InstWidth[inst] - defRect.x1; newRect.y1 _ defRect.y1; newRect.x2 _ InstWidth[inst] - defRect.x2; newRect.y2 _ defRect.y2}; 6 => -- rotate180X {newRect.x1 _ defRect.x1; newRect.y1 _ InstHeight[inst] - defRect.y1; newRect.x2 _ defRect.x2; newRect.y2 _ InstHeight[inst] - defRect.y2}; 7 => -- rotate270X {newRect.x1 _ defRect.y1; newRect.y1 _ defRect.x1; newRect.x2 _ defRect.y2; newRect.y2 _ defRect.x2}; 8 => -- rotate90X {newRect.x1 _ InstHeight[inst] - defRect.y1; newRect.y1 _ InstWidth[inst] - defRect.x1; newRect.x2 _ InstHeight[inst] - defRect.y2; newRect.y2 _ InstWidth[inst] - defRect.x2}; ENDCASE => SC.Error[programmingError, "No suppose to happen"]; RETURN[CDBasics.ReInterpreteRect[newRect]]}; LgOffsets: PUBLIC PROCEDURE[handle: SC.Handle, row: SCPrivate.ZMaxRowSr, pos1, pos2: SCPrivate.ZMaxPosSr] = { layoutData: SCPrivate.LayoutData _ NARROW[handle.layoutData]; lgRows: SCPrivate.LgRows _ layoutData.lgRows; lgRow: SCPrivate.LgRow _ lgRows.rows[row]; offset: SC.Number; posA: SCPrivate.ZMaxPosSr _ MIN[pos1, pos2]; posB: SCPrivate.ZMaxPosSr _ MAX[pos1, pos2]; IF posA <= 1 THEN {posA _ 1; offset _ 0} ELSE {inst: SCPrivate.Instance _ lgRow.lgsOnRow[posA-1]; offset _ inst.offset + InstWidth[inst]}; IF posB = 0 OR posB > lgRow.nLgsOnRow THEN posB _ lgRow.nLgsOnRow; FOR posIndex: SCPrivate.MaxPosSr IN [posA .. posB] DO inst: SCPrivate.Instance _ lgRow.lgsOnRow[posIndex]; SELECT inst.whichClass FROM ft, logic => {inst.offset _ offset; offset _ offset + InstWidth[inst]}; ENDCASE; ENDLOOP; IF posB = lgRow.nLgsOnRow THEN {lgRow.size.p _ offset; IF lgRow.size.p >= lgRows.maxRowWidth THEN {lgRows.maxRowWidth _ lgRow.size.p; lgRows.numMaxRows _ 1} ELSE [lgRows.maxRowWidth, lgRows.numMaxRows] _ SCRowUtil.FindMaxRow[handle]}}; AllOffsets: PUBLIC PROCEDURE [handle: SC.Handle] = { RowRroc: SCRowUtil.EachRowProc = { LgOffsets[handle, row, 0, SCPrivate.maxPos]}; SideProc: SCRowUtil.EachSideProc = { BpOffsets[handle, side, 0, SCPrivate.maxPos]}; [] _ SCRowUtil.EnumerateRows[handle, RowRroc]; [] _ SCRowUtil.EnumerateSides[handle, SideProc]}; AsgnChanPos: PUBLIC PROCEDURE[handle: SC.Handle] = BEGIN EachSide: SCRowUtil.EachSideProc = { IF bpRow.dimInvalid THEN SCRowUtil.ComputeSideHeight[handle, side]; sideDim[side] _ MAX[0, bpRow.size.p + (bpRow.nBpsOnSide -1) * bpRow.bpSpacing]}; EachRow: SCRowUtil.EachRowProc = { IF lgRow.dimInvalid THEN SCRowUtil.ComputeRowHeight[handle, lgRow.rowNum]}; layoutData: SCPrivate.LayoutData _ NARROW[handle.layoutData]; parms: SCPrivate.Parms _ NARROW[handle.parms]; lgRows: SCPrivate.LgRows _ layoutData.lgRows; bpRows: SCPrivate.BpRows _ layoutData.bpRows; sideChans: SCPrivate.SideChans _ layoutData.sideChans; rowChans: SCPrivate.RowChans _ layoutData.rowChans; nChans: SCPrivate.MaxChanSr _ rowChans.count; pitch: SC.Number _ RTBasic.IRSize[parms.ftObject.cdOb].x; sideDim: ARRAY SC.Side OF SC.Number; [] _ SCRowUtil.EnumerateSides[handle, EachSide]; [] _ SCRowUtil.EnumerateRows[handle, EachRow]; rowChans.chans[1].chanPos _ 0; sideChans[left].sideChanPos _ 0; lgRows.horzRowOrg _ 0; lgRows.rows[1].rowOrg.p _ lgRows.horzRowOrg + ((lgRows.maxRowWidth - lgRows.rows[1].size.p)/2)/pitch*pitch; lgRows.rows[1].rowOrg.q _ rowChans.chans[1].chanPos; FOR chan: SCPrivate.MaxChanSr IN [2 .. nChans] DO rowChans.chans[chan].chanPos _ lgRows.rows[chan-1].rowOrg.q + lgRows.rows[chan-1].size.q; IF chan <= lgRows.count THEN { lgRows.rows[chan].rowOrg.q _ rowChans.chans[chan].chanPos + rowChans.chans[chan].chanWidth; lgRows.rows[chan].rowOrg.p _ lgRows.horzRowOrg + ((lgRows.maxRowWidth - lgRows.rows[chan].size.p)/2)/pitch*pitch}; ENDLOOP; sideChans[right].sideChanPos _ lgRows.horzRowOrg + lgRows.maxRowWidth; layoutData.totHeight _ rowChans.chans[nChans].chanPos; -- + rowChans.chans[nChans].chanWidth; layoutData.totWidth _ sideChans[right].sideChanPos; bpRows[bottom].sideOrg.q _ 0; bpRows[bottom].sideOrg.p _ lgRows.horzRowOrg + (lgRows.maxRowWidth - sideDim[bottom]) / 2; bpRows[right].sideOrg.p _ layoutData.totWidth; bpRows[right].sideOrg.q _ (layoutData.totHeight - sideDim[right])/ 2; bpRows[top].sideOrg.p _ lgRows.horzRowOrg + (lgRows.maxRowWidth + sideDim[top])/ 2; bpRows[top].sideOrg.q _ layoutData.totHeight; bpRows[left].sideOrg.p _ 0; bpRows[left].sideOrg.q _ (layoutData.totHeight +sideDim[left])/ 2; END; ChansForInsts: PUBLIC PROCEDURE[handle: SC.Handle, insts: SCPrivate.InstanceList] RETURNS [touchesChan: SCPrivate.ChanSet _ RTSets.RTMdSetEmpty] = { layoutData: SCPrivate.LayoutData _ NARROW[handle.layoutData]; FOR instList: SCPrivate.InstanceList _ insts, instList.rest WHILE instList # NIL DO inst: SCPrivate.Instance _ instList.first; SELECT inst.whichClass FROM ft, logic => {IF inst.curRow > 0 THEN {touchesChan _ RTSets.RTMdSetUnion[touchesChan, RTSets.RTMdSetGenerateElement[(inst.curRow+1)-1]]; touchesChan _ RTSets.RTMdSetUnion[touchesChan , RTSets.RTMdSetGenerateElement[(inst.curRow)-1]]}}; io => {IF inst.curSide = bottom THEN touchesChan _ RTSets.RTMdSetUnion[touchesChan, RTSets.RTMdSetGenerateElement[(1)-1]]; IF inst.curSide = top THEN touchesChan _ RTSets.RTMdSetUnion[touchesChan, RTSets.RTMdSetGenerateElement[(layoutData.rowChans.count)-1]]}; ENDCASE; ENDLOOP}; CheckInst: PUBLIC PROCEDURE[handle: SC.Handle, inst: SCPrivate.Instance] = { layoutData: SCPrivate.LayoutData _ NARROW[handle.layoutData]; SELECT inst.whichClass FROM logic, ft => {row: SC.Number _ inst.curRow; pos: SC.Number _ inst.curPos; lgRow: SCPrivate.LgRow _ layoutData.lgRows.rows[row]; IF row <= 0 OR row > layoutData.rowChans.count THEN {IF ~(row = 0 AND pos = 0 AND inst.whichClass = ft) THEN SC.Error[programmingError, " "]} ELSE IF pos <= 0 OR pos > lgRow.nLgsOnRow THEN SC.Error[programmingError, " "] ELSE {trialInst: SCPrivate.Instance _ lgRow.lgsOnRow[pos]; IF inst # trialInst THEN SC.Error[programmingError, " "]}}; io => {side: SC.Side _ inst.curSide; pos: SC.Number _ inst.curPos; bpRow: SCPrivate.BpRow _ layoutData.bpRows[side]; IF side = none THEN SC.Error[programmingError, " "] ELSE IF pos <= 0 OR pos > bpRow.nBpsOnSide THEN SC.Error[programmingError, " "] ELSE {trialInst: SCPrivate.Instance _ bpRow.bpsOnSide[pos]; IF inst # trialInst THEN SC.Error[programmingError, " "]}}; ENDCASE}; CheckInsts: PUBLIC PROCEDURE[handle: SC.Handle] = { EachInst: SCInstUtil.EachInstanceProc = { CheckInst[handle, instance]}; [] _ SCInstUtil.EnumerateAllInstances[handle, EachInst]}; EnumerateAllInstances: PUBLIC PROC [handle: SC.Handle, eachInstance: SCInstUtil.EachInstanceProc] RETURNS [quit: BOOL] = { structureData: SCPrivate.StructureData _ NARROW[handle.structureData]; quit _ EnumerateInstances[handle, 1, structureData.instances.count, eachInstance]}; EnumerateInstances: PUBLIC PROC [handle: SC.Handle, startInst, stopInst: SCPrivate.MaxInstanceSr, eachInstance: SCInstUtil.EachInstanceProc] RETURNS [quit: BOOL _ FALSE] = { structureData: SCPrivate.StructureData _ NARROW[handle.structureData]; FOR inst: SCPrivate.MaxInstanceSr IN [startInst .. stopInst] WHILE ~quit DO quit _ eachInstance[structureData.instances.inst[inst]]; ENDLOOP}; EnumeratePinsOnInst: PUBLIC PROC [instance: SCPrivate.Instance, eachPin: SCInstUtil.EachPinProc] RETURNS [quit: BOOL _ FALSE] = { FOR pin: NAT IN [0 .. instance.pinNets.size) WHILE ~quit DO quit _ eachPin[instance, pin, instance.pinNets.n[pin]]; ENDLOOP}; DefineInstance: PUBLIC PROCEDURE [handle: SC.Handle, instanceName: Rope.ROPE, object: SCPrivate.Object, coreInstance: CoreClasses.CellInstance, equivName: Rope.ROPE _ NIL] RETURNS [instance: SCPrivate.Instance _ NIL] = { structureData: SCPrivate.StructureData _ NARROW[handle.structureData]; instances: SCPrivate.Instances _ structureData.instances; object.numTimesUsed _ object.numTimesUsed + 1; SELECT object.typeClass FROM logic => {instance _ NEW[logic SCPrivate.InstanceRec]; instance.whichClass _ logic; instances.numLogics _ instances.numLogics + 1}; ft => {instance _ NEW[ft SCPrivate.InstanceRec]; instance.whichClass _ ft; instances.numFts _ instances.numFts + 1}; io => {instance _ NEW[io SCPrivate.InstanceRec]; instance.equivPortClass _ equivName; instance.whichClass _ io; instances.numIOs _ instances.numIOs + 1}; ENDCASE => SC.Error[callingError, Rope.Cat["Feedthrus not allowed in input: ", instance.name, ", object: ", object.name, "\n"]]; instance.name _ instanceName; instance.object _ object; instance.pinNets _ NEW[SCPrivate.PinNetsRec[object.numPins]]; instances.count _ instances.count + 1; instance.num _ instances.count; instances.inst[instances.count] _ instance}; NumInstsOnList: PUBLIC PROCEDURE [instances: SCPrivate.InstanceList] RETURNS [count: SCPrivate.ZMaxInstanceSr _ 0] = { FOR instList: SCPrivate.InstanceList _ instances, instList.rest WHILE instList # NIL DO count _ count + 1; ENDLOOP}; CDOrien: PUBLIC PROCEDURE[instance: SCPrivate.Instance] RETURNS [orien: CD.Orientation] = { SELECT instance.curOrien FROM 0 => orien _ SC.Error[programmingError, "Not suppose to happen"]; 1 => orien _ original; 2 => orien _ rotate270; 3 => orien _ rotate180; 4 => orien _ rotate90; 5 => orien _ mirrorX; 6 => orien _ rotate180X; 7 => orien _ rotate270X; 8 => orien _ rotate90X; ENDCASE}; END. ΤSCInstUtilImpl.mesa Copyright c 1986 by Xerox Corporation. All rights reserved. Bryan Preas, January 19, 1987 12:18:55 pm PST compoments utility routines -- InstWidth - find width of component at current orientation -- InstHeight - find height of component at current orientation -- BpHeight - find height of bp when considering side it is on -- BpWidth - find width of bp when considering side it is on -- MinMaxBPOffset - find min and max offsets of bonding pads on side -- BpOffsets - find offsets of bonding pads on side -- BpPos - find position of inst on side -- PosOf- find the position (side, x, and y) of a component on a pin -- RotateRect- Rotate a rectangle of a cell -- LgOffsets- determine offsets of components in row -- AllOffsets - determine all component offsets -- AsgnChanPos - assign current positions to horizontal and vertical channels -- CheckInsts - check row and position of comps -- CheckInst - check row and position of a inst -- EnumeratePinsOnInst - enumerate the net pins on an instance find width of component at current orientation find current orientation now get width based on orientation find height of component at current orientation find current orientation now get height based on orientation find height of bp when considering its side (this is, the dimension perpendicular to side) find height of bp when considering side it is on this is along to side find offsets of bonding pads on side find offsets of bonding pads on side check offsets of bonding pads on side find position of inst on side assumes that channel and bp positions have been assigned. find position of pin on an inst assumes that channel and instance positions have been assigned. this code is copied from PosOf for efficiency first find the position at normal orientation now rotate the pin position to current orien find the position (side, x, and y) of a component on a pin first find the position at normal orientation now rotate the pin position to current orien find the position of a rotated rectangle wintin a component now rotate the pin position to current orien determine offsets of components in row compute offsets of all comps on row update max row widths determine all component offsets assign current positions to horizontal and vertical channels compute the minimum channel dimensions row 1 and channel 1 data now the interior channels now the right side get total height and width now update the side orgs update right side data update top side data update left side data find chans that these comps touch check row and position of a inst check row and position of a inst define a component (an instance of object) construct he instance record initialize the nets connected to these pins get the CD orientation Κe˜codešœ™Kšœ Οmœ1™™>KšŸ<™™>K˜šž ˜ Kšžœžœ<˜_K˜—šΟnœžœž˜Kšžœ žœ6˜JKšžœ ˜Kšžœžœ˜ K˜Kšž˜Kšœžœ˜/Kš œžœžœžœžœ&˜KK˜—˜Kšœ.™.š   œžœž œžœžœ ˜RK˜Kšž˜Kšœ™Kšœ3˜3K˜Kšœ"™"šžœž˜Kšœ,˜,Kšœ)˜)Kšžœ˜—Kšžœ˜K˜—Kšœ/™/š   œžœž œžœ žœ ˜TK˜Kšž˜Kšœ™šœ3˜3K˜—Kšœ$™$šžœž˜Kšœ-˜-Kšœ*˜*Kšžœ˜—Kšžœ˜K˜—Kšœ+™+Kšœ/™/š  œžœž œžœ žœ ˜SK˜šžœž˜KšžœP˜RK˜—šžœž˜Kšœ)˜)Kšœ(˜(Kšžœžœžœ˜,K˜——Kšœ0™0Kšœ™š  œžœž œžœžœ ˜QK˜šžœž˜KšžœP˜RK˜—šžœž˜Kšœ'˜'Kšœ(˜(Kšžœžœžœ˜,—K™—Kšœ%™%š œžœž œ žœžœžœžœ ˜pK˜š œ˜$Kšœ žœ˜,Kšœ žœ˜-K˜—Kšœ žœžœ˜Kšœ˜Kšœ@˜@K˜—Kšœ%™%š   œžœž œ žœžœ+˜bK˜Kšœ#žœ˜=Kšœ1˜1Kšœžœ˜Kšœžœ ˜,Kšœžœ ˜,Kšžœ žœ˜(šž˜Kšœ4˜4Kšžœžœžœ9˜^Kšžœ)˜-—Kšžœ žœžœ˜DK˜šžœžœžœ˜7Kšœ5˜5Kšœžœ˜!Kšžœžœžœ˜:Kšžœ˜"Kšœ*˜*Kšžœ˜ —K˜—Kšœ&™&š  œžœž œ žœžœ ˜FK˜Kšœ#žœ˜=Kšœ1˜1Kšœžœ ˜K˜šžœžœžœ˜@Kšœ5˜5Kšœžœ˜!šžœžœžœ˜'Kšžœžœžœ2˜Q—šžœ˜Kšžœžœžœ3˜Z—Kšœ*˜*Kšžœ˜ —K˜—Kšœ™Kšœ9™9š  œžœž œ žœ#žœ žœ ˜cK˜Kšœ#žœ˜=Kšœ9˜9šžœž˜Kšžœ5˜7—šžœž˜Kšœ0˜0Kšœ1˜1Kšœ/˜/Kšœ.˜.Kšžœ˜ —K˜—Kšœ™Kšœ?™?š   œžœž œ žœ=žœ˜‚K˜Kšœ#žœ˜=K™Kšœ-™-Kšœ.™.šœžœ žœž˜-Kšœ2˜2KšœC˜CKšœB˜BKšœ0˜0šžœžœ2˜?K˜——Kšœ-™-šœžœ žœž˜.KšœŸ ˜Kšœ&Ÿ ˜2Kšœ9Ÿ ˜EKšœ'Ÿ ˜2Kšœ&Ÿ ˜0Kšœ'Ÿ ˜4KšœŸ ˜!Kšœ9Ÿ ˜EKšžœžœ1˜>K˜—šžœž˜šœ˜Kšœ=˜=KšœJ˜J—šœ˜Kšœ9˜9šœžœž˜KšœN˜NKšœO˜OKšœM˜MKšœL˜LKšžœžœ2˜?——Kšžœ˜ —K˜—Kšœ;™;š œžœž œ4˜KKšžœ(˜/K˜Kšœ.™.šžœž˜-Kšœ2˜2KšœC˜CKšœB˜BKšœ0˜0šžœžœ2˜?K˜——Kšœ-™-šœžœž˜0KšœŸ ˜Kšœ%Ÿ ˜1Kšœ9Ÿ ˜EKšœ'Ÿ ˜2Kšœ&Ÿ ˜0Kšœ'Ÿ ˜4KšœŸ ˜!Kšœ9Ÿ ˜EKšžœžœ1˜>—K˜KšœW˜WK˜—Kšœ;™;š  œžœž œ$žœ˜HKšžœžœ ˜K˜Kšœ-™-Kšœ žœ˜šžœž˜šœŸ ˜Kšœ2˜2Kšœ2˜2—šœŸ ˜KšœD˜DKšœD˜D—šœŸ ˜KšœW˜WKšœW˜W—šœŸ ˜KšœE˜EKšœE˜E—šœŸ ˜KšœD˜DKšœD˜D—šœŸ ˜KšœE˜EKšœE˜E—šœŸ ˜Kšœ2˜2Kšœ2˜2—šœŸ ˜KšœW˜WKšœW˜W—Kšžœžœ1˜>—Kšžœ&˜,K˜—Kšœ'™'š  œžœž œ žœG˜mK˜Kšœ#™#Kšœ#žœ˜=Kšœ-˜-Kšœ*˜*Kšœžœ˜Kšœžœ ˜,Kšœžœ ˜,Kšžœ žœ˜(šž˜Kšœ3˜3Kšœ(˜(—Kšžœ žœžœ˜BK˜šžœžœžœ˜6Kšœ4˜4šžœž˜KšœG˜GKšžœ˜—Kšžœ˜K˜—Kšœ™šžœž˜Kšœ˜šžœ$ž˜*Kšœ:˜:—KšžœK˜O—K˜—Kšœ ™ š  œžœž œ žœ ˜4K˜š œ˜"Kšœ-˜-—š œ˜$Kšœ.˜.—Kšœ.˜.Kšœ1˜1K˜—Kšœ=™=š  œžœž œ žœ ˜3K˜Kšž˜Kšœ&™&š œ˜$Kšžœžœ+˜CKšœžœ=˜PK˜—š œ˜"Kšžœžœ3˜KK˜—Kšœ#žœ˜=Kšœžœ˜.Kšœ-˜-Kšœ-˜-Kšœ6˜6Kšœ3˜3Kšœ-˜-Kšœžœ0˜9Kš œ žœžœžœžœ˜$K˜Kšœ0˜0K˜Kšœ.˜.K˜Kšœ™Kšœ˜Kšœ ˜ K˜Kšœ˜Kšœk˜kKšœ4˜4Kšœ™šžœžœžœ˜2KšœY˜Yšžœžœ˜Kšœ[˜[Kšœr˜r—šžœ˜K˜—Kšœ™šœF˜FK˜—Kšœ™K˜Kšœ7Ÿ&˜]K˜Kšœ3˜3K˜Kšœ™Kšœ˜šœZ˜ZK˜—Kšœ™Kšœ.˜.šœE˜EK˜—Kšœ™KšœS˜Sšœ-˜-K˜—Kšœ™Kšœ˜KšœB˜BKšžœ˜—K˜—Kšœ"™"š  œžœž œ žœ'˜QKšžœ;˜BK˜Kšœ#žœ˜=šžœ9žœ žœžœ˜TKšœ*˜*šžœž˜šœžœž˜%šœb˜bKšœb˜b——šœžœž˜$KšœU˜Ušžœž˜Kšœn˜n——Kšžœ˜—Kšžœ˜ —K˜—Kšœ!™!š  œžœž œ žœ&˜LKšœ#žœ˜=šžœž˜šœ ˜ Kšœžœ˜Kšœžœ˜Kšœ5˜5šžœ žœ!ž˜3šœžœ žœ žœž˜8Kšžœ˜ ——šžœžœ žœž˜.Kšžœ˜—šž˜Kšœ5˜5šžœž˜Kšžœ ˜"———šœ˜Kšœžœ˜Kšœžœ˜Kšœ1˜1šžœ ž˜Kšžœ˜—šžœžœ žœž˜/Kšžœ˜—šž˜Kšœ6˜6šžœž˜Kšžœ ˜"———Kšžœ˜ —K˜—Kšœ!™!š  œžœž œ žœ ˜3K˜š œ!˜)Kšœ˜—Kšœ9˜9K˜—š  œžœžœ žœ4žœžœ˜zK˜Kšœ)žœ˜FKšœS˜SK˜—š œžœžœ žœbžœžœžœ˜­K˜Kšœ)žœ˜Fšžœžœžœž˜KKšœ8˜8Kšžœ˜ —K˜—š  œžœžœAžœžœžœ˜K˜š žœžœžœžœžœ˜