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 _ FIRST[INT]; [] _ 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 left, right => result _ bpRow.sideOrg.q + inst.offset; bottom, 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 left, right => [bpRow.sideOrg.p + xyPos.x, bpRow.sideOrg.q + inst.offset + xyPos.y], bottom, 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 Σ 1986, 1987 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 ΚH˜codešœ™KšœB™BKšœ*Οk™-—K˜Kšœ™KšΟc=™=Kšž?™?Kšž>™>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šœ6˜6Kšœ6˜6Kšœ˜ —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šœT˜TKšœT˜TKšœœ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šœC˜CKšœ˜—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˜š œœœœœ˜