<> <> <> <> <<-- 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>> 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; <> <<(this is, the dimension perpendicular to side) >> 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.